From ea41783edc9fcf659412cffd3aa0317aa6fde05a Mon Sep 17 00:00:00 2001 From: Nailin Guan <150537269+Thmoas-Guan@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:50:35 +0000 Subject: [PATCH 001/681] chore(FieldTheory/Galois): small cleanup (#20217) Small refinements about Fieldtheory.Galois Mainly about few refine in proof style and some more suggested lemma. --- Mathlib/FieldTheory/Galois/Basic.lean | 7 ++--- Mathlib/FieldTheory/Galois/Infinite.lean | 39 +++++++++++------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Mathlib/FieldTheory/Galois/Basic.lean b/Mathlib/FieldTheory/Galois/Basic.lean index 5b30988548f8e..1213496da816d 100644 --- a/Mathlib/FieldTheory/Galois/Basic.lean +++ b/Mathlib/FieldTheory/Galois/Basic.lean @@ -286,11 +286,8 @@ def galoisCoinsertionIntermediateFieldSubgroup [FiniteDimensional F E] [IsGalois GaloisCoinsertion (OrderDual.toDual ∘ (IntermediateField.fixingSubgroup : IntermediateField F E → Subgroup (E ≃ₐ[F] E))) ((IntermediateField.fixedField : Subgroup (E ≃ₐ[F] E) → IntermediateField F E) ∘ - OrderDual.toDual) where - choice H _ := IntermediateField.fixedField H - gc K H := (IntermediateField.le_iff_le H K).symm - u_l_le K := le_of_eq (fixedField_fixingSubgroup K) - choice_eq _ _ := rfl + OrderDual.toDual) := + OrderIso.toGaloisCoinsertion intermediateFieldEquivSubgroup end IsGalois diff --git a/Mathlib/FieldTheory/Galois/Infinite.lean b/Mathlib/FieldTheory/Galois/Infinite.lean index c97aeaad84aa5..d93b6f9fec8dc 100644 --- a/Mathlib/FieldTheory/Galois/Infinite.lean +++ b/Mathlib/FieldTheory/Galois/Infinite.lean @@ -180,19 +180,15 @@ lemma fixingSubgroup_fixedField (H : ClosedSubgroup (K ≃ₐ[k] K)) [IsGalois k /-- The Galois correspondence from intermediate fields to closed subgroups. -/ def IntermediateFieldEquivClosedSubgroup [IsGalois k K] : IntermediateField k K ≃o (ClosedSubgroup (K ≃ₐ[k] K))ᵒᵈ where - toFun := fun L => - { L.fixingSubgroup with - isClosed' := fixingSubgroup_isClosed L } - invFun := fun H => IntermediateField.fixedField H.1 - left_inv := fun L => fixedField_fixingSubgroup L - right_inv := by - intro H + toFun L := ⟨L.fixingSubgroup, fixingSubgroup_isClosed L⟩ + invFun H := IntermediateField.fixedField H.1 + left_inv L := fixedField_fixingSubgroup L + right_inv H := by simp_rw [fixingSubgroup_fixedField H] rfl - map_rel_iff' := by - intro L₁ L₂ - show L₁.fixingSubgroup ≥ L₂.fixingSubgroup ↔ L₁ ≤ L₂ - rw [← fixedField_fixingSubgroup L₂, IntermediateField.le_iff_le, fixedField_fixingSubgroup L₂] + map_rel_iff' {K L} := by + rw [← fixedField_fixingSubgroup L, IntermediateField.le_iff_le, fixedField_fixingSubgroup L] + rfl /-- The Galois correspondence as a `GaloisInsertion` -/ def GaloisInsertionIntermediateFieldClosedSubgroup [IsGalois k K] : @@ -205,16 +201,14 @@ def GaloisInsertionIntermediateFieldClosedSubgroup [IsGalois k K] : /-- The Galois correspondence as a `GaloisCoinsertion` -/ def GaloisCoinsertionIntermediateFieldSubgroup [IsGalois k K] : GaloisCoinsertion (OrderDual.toDual ∘ fun (E : IntermediateField k K) ↦ E.fixingSubgroup) - ((fun (H : Subgroup (K ≃ₐ[k] K)) ↦ IntermediateField.fixedField H) ∘ - OrderDual.toDual) where + ((fun (H : Subgroup (K ≃ₐ[k] K)) ↦ IntermediateField.fixedField H) ∘ OrderDual.toDual) where choice H _ := IntermediateField.fixedField H gc E H := (IntermediateField.le_iff_le H E).symm u_l_le K := le_of_eq (fixedField_fixingSubgroup K) choice_eq _ _ := rfl theorem isOpen_iff_finite (L : IntermediateField k K) [IsGalois k K] : - IsOpen (IntermediateFieldEquivClosedSubgroup L).carrier ↔ - (FiniteDimensional k L) := by + IsOpen L.fixingSubgroup.carrier ↔ FiniteDimensional k L := by refine ⟨fun h ↦ ?_, fun h ↦ IntermediateField.fixingSubgroup_isOpen L⟩ have : (IntermediateFieldEquivClosedSubgroup.toFun L).carrier ∈ nhds 1 := IsOpen.mem_nhds h (congrFun rfl) @@ -234,14 +228,12 @@ theorem isOpen_iff_finite (L : IntermediateField k K) [IsGalois k K] : exact FiniteDimensional.left k L L'.1 theorem normal_iff_isGalois (L : IntermediateField k K) [IsGalois k K] : - Subgroup.Normal (IntermediateFieldEquivClosedSubgroup L).1 ↔ - IsGalois k L := by + L.fixingSubgroup.Normal ↔ IsGalois k L := by refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · let f : L → IntermediateField k K := fun x => IntermediateField.lift <| - IntermediateField.fixedField <| Subgroup.map (restrictNormalHom - (adjoin k {x.1})) L.fixingSubgroup - have h' (x : K) : (Subgroup.map (restrictNormalHom - (adjoin k {x})) L.fixingSubgroup).Normal := + IntermediateField.fixedField <| Subgroup.map (restrictNormalHom (adjoin k {x.1})) + L.fixingSubgroup + have h' (x : K) : (Subgroup.map (restrictNormalHom (adjoin k {x})) L.fixingSubgroup).Normal := Subgroup.Normal.map h (restrictNormalHom (adjoin k {x})) (restrictNormalHom_surjective K) have n' (l : L) : IsGalois k (IntermediateField.fixedField <| Subgroup.map (restrictNormalHom (adjoin k {l.1})) L.fixingSubgroup) := by @@ -267,4 +259,9 @@ theorem normal_iff_isGalois (L : IntermediateField k K) [IsGalois k K] : · simpa only [IntermediateFieldEquivClosedSubgroup, RelIso.coe_fn_mk, Equiv.coe_fn_mk, ← L.restrictNormalHom_ker] using MonoidHom.normal_ker (restrictNormalHom L) +theorem isOpen_and_normal_iff_finite_and_isGalois (L : IntermediateField k K) [IsGalois k K] : + IsOpen L.fixingSubgroup.carrier ∧ L.fixingSubgroup.Normal ↔ + FiniteDimensional k L ∧ IsGalois k L := by + rw [isOpen_iff_finite, normal_iff_isGalois] + end InfiniteGalois From 886b34020dd14621e8265d3aa4102c9b1fc6a514 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Mon, 6 Jan 2025 10:15:37 +0000 Subject: [PATCH 002/681] chore: remove >9 month old deprecations (#20505) --- Mathlib/Algebra/Algebra/Operations.lean | 13 ----- Mathlib/Algebra/Associated/Basic.lean | 2 - Mathlib/Algebra/CharP/Reduced.lean | 3 -- Mathlib/Algebra/GCDMonoid/Basic.lean | 3 -- Mathlib/Algebra/Group/Basic.lean | 18 ------- Mathlib/Algebra/Group/Defs.lean | 2 - Mathlib/Algebra/Group/UniqueProds/Basic.lean | 17 ------- Mathlib/Algebra/Group/Units/Basic.lean | 2 - .../Algebra/GroupWithZero/Units/Basic.lean | 10 ---- .../Algebra/Module/Submodule/Pointwise.lean | 5 -- .../Order/BigOperators/Ring/Finset.lean | 2 - Mathlib/Algebra/Order/Field/Basic.lean | 9 ---- Mathlib/Algebra/Order/Field/Power.lean | 2 - Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean | 3 -- Mathlib/Algebra/Polynomial/Div.lean | 1 - Mathlib/Algebra/Squarefree/Basic.lean | 3 -- Mathlib/AlgebraicGeometry/OpenImmersion.lean | 3 -- .../ProjectiveSpectrum/Scheme.lean | 1 - Mathlib/Analysis/CStarAlgebra/Matrix.lean | 22 -------- .../Analysis/CStarAlgebra/Unitization.lean | 4 -- .../Calculus/ContDiff/FTaylorSeries.lean | 4 -- .../InverseFunctionTheorem/Deriv.lean | 2 - .../InverseFunctionTheorem/FDeriv.lean | 2 - Mathlib/Analysis/Calculus/MeanValue.lean | 9 ---- .../Analysis/Complex/Polynomial/Basic.lean | 3 -- .../Analysis/Fourier/FourierTransform.lean | 8 --- .../InnerProductSpace/LaxMilgram.lean | 1 - .../Analysis/InnerProductSpace/TwoDim.lean | 4 -- Mathlib/Analysis/LocallyConvex/Basic.lean | 11 ---- Mathlib/Analysis/Matrix.lean | 33 ------------ Mathlib/Analysis/Normed/Lp/LpEquiv.lean | 4 -- .../Normed/Module/FiniteDimension.lean | 17 ------- .../NormedSpace/Multilinear/Basic.lean | 50 ------------------- .../NormedSpace/OperatorNorm/Basic.lean | 25 ---------- .../NormedSpace/OperatorNorm/Bilinear.lean | 5 -- .../OperatorNorm/Completeness.lean | 1 - .../NormedSpace/OperatorNorm/Mul.lean | 17 ------- .../NormedSpace/OperatorNorm/NNNorm.lean | 24 --------- .../NormedSpace/OperatorNorm/NormedSpace.lean | 4 -- .../NormedSpace/OperatorNorm/Prod.lean | 2 - Mathlib/Analysis/NormedSpace/RCLike.lean | 4 -- .../Gaussian/FourierTransform.lean | 9 ---- Mathlib/CategoryTheory/Filtered/Basic.lean | 3 -- Mathlib/CategoryTheory/IsConnected.lean | 4 -- .../Limits/FullSubcategory.lean | 6 --- Mathlib/CategoryTheory/Limits/Opposites.lean | 4 -- .../Combinatorics/SimpleGraph/Coloring.lean | 4 -- Mathlib/Data/Complex/Abs.lean | 3 -- Mathlib/Data/Countable/Small.lean | 6 --- Mathlib/Data/Fin/Basic.lean | 6 --- Mathlib/Data/Finset/Card.lean | 5 -- Mathlib/Data/Finset/Empty.lean | 1 - Mathlib/Data/Finset/Lattice/Basic.lean | 4 -- Mathlib/Data/Int/Defs.lean | 3 -- Mathlib/Data/List/Basic.lean | 6 --- Mathlib/Data/List/Defs.lean | 2 - Mathlib/Data/List/Infix.lean | 1 - Mathlib/Data/List/Pairwise.lean | 9 ---- Mathlib/Data/List/Sublists.lean | 5 -- Mathlib/Data/NNReal/Defs.lean | 1 - Mathlib/Data/Nat/Cast/Order/Basic.lean | 3 -- Mathlib/Data/Nat/Digits.lean | 3 -- Mathlib/Data/Rat/Cast/Defs.lean | 2 - Mathlib/Data/Rat/Defs.lean | 16 ------ Mathlib/Data/Real/Sqrt.lean | 5 -- Mathlib/Data/Set/Basic.lean | 7 --- Mathlib/Data/Set/Image.lean | 21 -------- Mathlib/Data/ZMod/Quotient.lean | 3 -- Mathlib/Deprecated/Cardinal/PartENat.lean | 4 -- Mathlib/Deprecated/Submonoid.lean | 1 - Mathlib/FieldTheory/PrimitiveElement.lean | 6 --- .../Euclidean/Angle/Unoriented/Affine.lean | 3 -- .../Manifold/SmoothManifoldWithCorners.lean | 1 - Mathlib/GroupTheory/OrderOfElement.lean | 8 --- .../GroupTheory/SpecificGroups/Cyclic.lean | 16 ------ Mathlib/LinearAlgebra/FiniteDimensional.lean | 4 -- .../LinearAlgebra/FiniteDimensional/Defs.lean | 9 ---- Mathlib/Logic/Basic.lean | 11 ---- .../Constructions/BorelSpace/Real.lean | 15 ------ Mathlib/MeasureTheory/Function/L1Space.lean | 4 -- .../MeasureTheory/Function/SimpleFunc.lean | 1 - .../Function/StronglyMeasurable/Basic.lean | 9 ---- .../MeasureTheory/Integral/PeakFunction.lean | 12 ----- Mathlib/MeasureTheory/Integral/SetToL1.lean | 3 -- .../MeasureTheory/Measure/Haar/Unique.lean | 15 ------ Mathlib/NumberTheory/LSeries/Dirichlet.lean | 3 -- .../Transcendental/Liouville/Residual.lean | 1 - Mathlib/RingTheory/Flat/Basic.lean | 6 --- .../RingTheory/Ideal/Quotient/Operations.lean | 5 -- .../RingTheory/MvPolynomial/Homogeneous.lean | 3 -- Mathlib/RingTheory/PowerBasis.lean | 1 - Mathlib/RingTheory/PrincipalIdealDomain.lean | 6 --- Mathlib/RingTheory/SimpleModule.lean | 6 --- .../UniqueFactorizationDomain/Defs.lean | 5 -- .../UniqueFactorizationDomain/FactorSet.lean | 1 - .../Multiplicity.lean | 5 -- Mathlib/SetTheory/Cardinal/Arithmetic.lean | 6 --- Mathlib/SetTheory/Cardinal/ToNat.lean | 19 ------- .../Topology/Algebra/InfiniteSum/NatInt.lean | 10 ---- Mathlib/Topology/Algebra/UniformRing.lean | 10 ---- Mathlib/Topology/Bases.lean | 6 --- Mathlib/Topology/CompactOpen.lean | 15 ------ Mathlib/Topology/Compactness/Compact.lean | 16 ------ Mathlib/Topology/Constructions.lean | 2 - .../Topology/ContinuousMap/Bounded/Basic.lean | 2 - .../Topology/ContinuousMap/ZeroAtInfty.lean | 1 - Mathlib/Topology/GDelta/Basic.lean | 9 ---- Mathlib/Topology/GDelta/UniformSpace.lean | 1 - Mathlib/Topology/Instances/Discrete.lean | 5 -- Mathlib/Topology/Instances/Int.lean | 1 - Mathlib/Topology/Instances/Irrational.lean | 1 - Mathlib/Topology/Instances/Real.lean | 3 -- Mathlib/Topology/Maps/Basic.lean | 1 - Mathlib/Topology/MetricSpace/Completion.lean | 4 -- Mathlib/Topology/MetricSpace/Polish.lean | 3 -- Mathlib/Topology/MetricSpace/Sequences.lean | 6 --- Mathlib/Topology/Order.lean | 11 ---- Mathlib/Topology/Order/Basic.lean | 10 ---- Mathlib/Topology/Order/OrderClosed.lean | 8 --- Mathlib/Topology/Semicontinuous.lean | 6 --- Mathlib/Topology/Separation/GDelta.lean | 2 - Mathlib/Topology/Separation/Hausdorff.lean | 3 -- Mathlib/Topology/Separation/Regular.lean | 9 ---- Mathlib/Topology/UniformSpace/Basic.lean | 14 ------ Mathlib/Topology/UnitInterval.lean | 2 - 125 files changed, 847 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index 01b7c2e0ecb3f..7a693780a741f 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -144,10 +144,6 @@ theorem smul_mono_left (h : I ≤ J) : I • N ≤ J • N := instance : CovariantClass (Submodule R A) (Submodule R M) HSMul.hSMul LE.le := ⟨fun _ _ => smul_mono le_rfl⟩ -@[deprecated smul_mono_right (since := "2024-03-31")] -protected theorem smul_mono_right (h : N ≤ P) : I • N ≤ I • P := - _root_.smul_mono_right I h - variable (I J N P) @[simp] @@ -180,10 +176,6 @@ protected theorem smul_assoc {B} [Semiring B] [Module R B] [Module A B] [Module (fun j hj n hn ↦ (smul_assoc r j n).symm ▸ smul_mem_smul (smul_mem_smul hr hj) hn) fun m₁ m₂ ↦ (smul_add r m₁ m₂) ▸ add_mem) -@[deprecated smul_inf_le (since := "2024-03-31")] -protected theorem smul_inf_le (M₁ M₂ : Submodule R M) : - I • (M₁ ⊓ M₂) ≤ I • M₁ ⊓ I • M₂ := smul_inf_le _ _ _ - theorem smul_iSup {ι : Sort*} {I : Submodule R A} {t : ι → Submodule R M} : I • (⨆ i, t i)= ⨆ i, I • t i := toAddSubmonoid_injective <| by @@ -196,11 +188,6 @@ theorem iSup_smul {ι : Sort*} {t : ι → Submodule R A} {N : Submodule R M} : (by simp_rw [zero_smul]; apply zero_mem) fun x y ↦ by simp_rw [add_smul]; apply add_mem) (iSup_le fun i ↦ Submodule.smul_mono_left <| le_iSup _ i) -@[deprecated smul_iInf_le (since := "2024-03-31")] -protected theorem smul_iInf_le {ι : Sort*} {I : Submodule R A} {t : ι → Submodule R M} : - I • iInf t ≤ ⨅ i, I • t i := - smul_iInf_le - protected theorem one_smul : (1 : Submodule R A) • N = N := by refine le_antisymm (smul_le.mpr fun r hr m hm ↦ ?_) fun m hm ↦ ?_ · obtain ⟨r, rfl⟩ := hr diff --git a/Mathlib/Algebra/Associated/Basic.lean b/Mathlib/Algebra/Associated/Basic.lean index 4484964fb4604..12ae9d5fdd160 100644 --- a/Mathlib/Algebra/Associated/Basic.lean +++ b/Mathlib/Algebra/Associated/Basic.lean @@ -581,7 +581,6 @@ theorem mk_le_mk_of_dvd {a b : M} : a ∣ b → Associates.mk a ≤ Associates.m theorem mk_le_mk_iff_dvd {a b : M} : Associates.mk a ≤ Associates.mk b ↔ a ∣ b := mk_dvd_mk -@[deprecated (since := "2024-03-16")] alias mk_le_mk_iff_dvd_iff := mk_le_mk_iff_dvd @[simp] theorem isPrimal_mk {a : M} : IsPrimal (Associates.mk a) ↔ IsPrimal a := by @@ -591,7 +590,6 @@ theorem isPrimal_mk {a : M} : IsPrimal (Associates.mk a) ↔ IsPrimal a := by exact ⟨a₁, a₂ * u, h₁, Units.mul_right_dvd.mpr h₂, mul_assoc _ _ _⟩ · exact ⟨a₁, a₂, h₁, h₂, congr_arg _ eq⟩ -@[deprecated (since := "2024-03-16")] alias isPrimal_iff := isPrimal_mk @[simp] theorem decompositionMonoid_iff : DecompositionMonoid (Associates M) ↔ DecompositionMonoid M := by diff --git a/Mathlib/Algebra/CharP/Reduced.lean b/Mathlib/Algebra/CharP/Reduced.lean index deea5f7b1eb53..90e5aa6b3aa17 100644 --- a/Mathlib/Algebra/CharP/Reduced.lean +++ b/Mathlib/Algebra/CharP/Reduced.lean @@ -44,6 +44,3 @@ theorem ExpChar.pow_prime_pow_mul_eq_one_iff (p k m : ℕ) [ExpChar R p] (x : R) rw [pow_mul'] convert ← (iterateFrobenius_inj R p k).eq_iff apply map_one - -@[deprecated (since := "2024-02-02")] -alias CharP.pow_prime_pow_mul_eq_one_iff := ExpChar.pow_prime_pow_mul_eq_one_iff diff --git a/Mathlib/Algebra/GCDMonoid/Basic.lean b/Mathlib/Algebra/GCDMonoid/Basic.lean index 16298274aed73..57c84854496c4 100644 --- a/Mathlib/Algebra/GCDMonoid/Basic.lean +++ b/Mathlib/Algebra/GCDMonoid/Basic.lean @@ -805,9 +805,6 @@ theorem lcm_eq_of_associated_right [NormalizedGCDMonoid α] {m n : α} (h : Asso end LCM -@[deprecated (since := "2024-02-12")] alias GCDMonoid.prime_of_irreducible := Irreducible.prime -@[deprecated (since := "2024-02-12")] alias GCDMonoid.irreducible_iff_prime := irreducible_iff_prime - end GCDMonoid section UniqueUnit diff --git a/Mathlib/Algebra/Group/Basic.lean b/Mathlib/Algebra/Group/Basic.lean index 1df564f491efd..bf22f85392085 100644 --- a/Mathlib/Algebra/Group/Basic.lean +++ b/Mathlib/Algebra/Group/Basic.lean @@ -797,14 +797,6 @@ theorem leftInverse_inv_mul_mul_right (c : G) : @[to_additive (attr := simp) natAbs_nsmul_eq_zero] lemma pow_natAbs_eq_one : a ^ n.natAbs = 1 ↔ a ^ n = 1 := by cases n <;> simp -set_option linter.existingAttributeWarning false in -@[to_additive, deprecated pow_natAbs_eq_one (since := "2024-02-14")] -lemma exists_pow_eq_one_of_zpow_eq_one (hn : n ≠ 0) (h : a ^ n = 1) : - ∃ n : ℕ, 0 < n ∧ a ^ n = 1 := ⟨_, Int.natAbs_pos.2 hn, pow_natAbs_eq_one.2 h⟩ - -attribute [deprecated natAbs_nsmul_eq_zero (since := "2024-02-14")] -exists_nsmul_eq_zero_of_zsmul_eq_zero - @[to_additive sub_nsmul] lemma pow_sub (a : G) {m n : ℕ} (h : n ≤ m) : a ^ (m - n) = a ^ m * (a ^ n)⁻¹ := eq_mul_inv_of_mul_eq <| by rw [← pow_add, Nat.sub_add_cancel h] @@ -1041,15 +1033,5 @@ theorem multiplicative_of_isTotal (p : α → Prop) (hswap : ∀ {a b}, p a → end multiplicative -@[deprecated (since := "2024-03-20")] alias div_mul_cancel' := div_mul_cancel -@[deprecated (since := "2024-03-20")] alias mul_div_cancel'' := mul_div_cancel_right -- The name `add_sub_cancel` was reused -- @[deprecated (since := "2024-03-20")] alias add_sub_cancel := add_sub_cancel_right -@[deprecated (since := "2024-03-20")] alias div_mul_cancel''' := div_mul_cancel_right -@[deprecated (since := "2024-03-20")] alias sub_add_cancel'' := sub_add_cancel_right -@[deprecated (since := "2024-03-20")] alias mul_div_cancel''' := mul_div_cancel_left -@[deprecated (since := "2024-03-20")] alias add_sub_cancel' := add_sub_cancel_left -@[deprecated (since := "2024-03-20")] alias mul_div_cancel'_right := mul_div_cancel -@[deprecated (since := "2024-03-20")] alias add_sub_cancel'_right := add_sub_cancel -@[deprecated (since := "2024-03-20")] alias div_mul_cancel'' := div_mul_cancel_left -@[deprecated (since := "2024-03-20")] alias sub_add_cancel' := sub_add_cancel_left diff --git a/Mathlib/Algebra/Group/Defs.lean b/Mathlib/Algebra/Group/Defs.lean index 324b405f14be4..9808a37d910f3 100644 --- a/Mathlib/Algebra/Group/Defs.lean +++ b/Mathlib/Algebra/Group/Defs.lean @@ -886,8 +886,6 @@ theorem zpow_natCast (a : G) : ∀ n : ℕ, a ^ (n : ℤ) = a ^ n _ = a ^ n * a := congrArg (· * a) (zpow_natCast a n) _ = a ^ (n + 1) := (pow_succ _ _).symm -@[deprecated (since := "2024-03-20")] alias zpow_coe_nat := zpow_natCast -@[deprecated (since := "2024-03-20")] alias coe_nat_zsmul := natCast_zsmul @[to_additive ofNat_zsmul] lemma zpow_ofNat (a : G) (n : ℕ) : a ^ (ofNat(n) : ℤ) = a ^ OfNat.ofNat n := diff --git a/Mathlib/Algebra/Group/UniqueProds/Basic.lean b/Mathlib/Algebra/Group/UniqueProds/Basic.lean index 41d9de70596fd..2e38b8dc940aa 100644 --- a/Mathlib/Algebra/Group/UniqueProds/Basic.lean +++ b/Mathlib/Algebra/Group/UniqueProds/Basic.lean @@ -625,23 +625,6 @@ instance (priority := 100) of_covariant_left [IsLeftCancelMul G] end TwoUniqueProds -@[deprecated (since := "2024-02-04")] -alias UniqueProds.mulHom_image_of_injective := UniqueProds.of_injective_mulHom -@[deprecated (since := "2024-02-04")] -alias UniqueSums.addHom_image_of_injective := UniqueSums.of_injective_addHom -@[deprecated (since := "2024-02-04")] -alias UniqueProds.mulHom_image_iff := MulEquiv.uniqueProds_iff -@[deprecated (since := "2024-02-04")] -alias UniqueSums.addHom_image_iff := AddEquiv.uniqueSums_iff -@[deprecated (since := "2024-02-04")] -alias TwoUniqueProds.mulHom_image_of_injective := TwoUniqueProds.of_injective_mulHom -@[deprecated (since := "2024-02-04")] -alias TwoUniqueSums.addHom_image_of_injective := TwoUniqueSums.of_injective_addHom -@[deprecated (since := "2024-02-04")] -alias TwoUniqueProds.mulHom_image_iff := MulEquiv.twoUniqueProds_iff -@[deprecated (since := "2024-02-04")] -alias TwoUniqueSums.addHom_image_iff := AddEquiv.twoUniqueSums_iff - instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, TwoUniqueSums (G i)] : TwoUniqueSums (Π₀ i, G i) := TwoUniqueSums.of_injective_addHom diff --git a/Mathlib/Algebra/Group/Units/Basic.lean b/Mathlib/Algebra/Group/Units/Basic.lean index 3630673d90f59..3cb0df004f9d7 100644 --- a/Mathlib/Algebra/Group/Units/Basic.lean +++ b/Mathlib/Algebra/Group/Units/Basic.lean @@ -474,5 +474,3 @@ attribute [deprecated sub_add_cancel_left (since := "2024-03-20")] IsAddUnit.sub -- @[deprecated (since := "2024-03-20")] alias IsUnit.mul_div_cancel := IsUnit.mul_div_cancel_right -- @[deprecated (since := "2024-03-20")] -- alias IsAddUnit.add_sub_cancel := IsAddUnit.add_sub_cancel_right -@[deprecated (since := "2024-03-20")] alias IsUnit.mul_div_cancel' := IsUnit.mul_div_cancel -@[deprecated (since := "2024-03-20")] alias IsAddUnit.add_sub_cancel' := IsAddUnit.add_sub_cancel diff --git a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean index 7702e037e5cb7..5b98cfd3fad68 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean @@ -315,10 +315,6 @@ lemma div_eq_one_iff_eq (hb : b ≠ 0) : a / b = 1 ↔ a = b := hb.isUnit.div_eq lemma div_mul_cancel_right₀ (hb : b ≠ 0) (a : G₀) : b / (a * b) = a⁻¹ := hb.isUnit.div_mul_cancel_right _ -set_option linter.deprecated false in -@[deprecated div_mul_cancel_right₀ (since := "2024-03-20")] -lemma div_mul_left (hb : b ≠ 0) : b / (a * b) = 1 / a := hb.isUnit.div_mul_left - lemma mul_div_mul_right (a b : G₀) (hc : c ≠ 0) : a * c / (b * c) = a / b := hc.isUnit.mul_div_mul_right _ _ @@ -415,10 +411,6 @@ instance (priority := 100) CommGroupWithZero.toDivisionCommMonoid : lemma div_mul_cancel_left₀ (ha : a ≠ 0) (b : G₀) : a / (a * b) = b⁻¹ := ha.isUnit.div_mul_cancel_left _ -@[deprecated div_mul_cancel_left₀ (since := "2024-03-22")] -lemma div_mul_right (b : G₀) (ha : a ≠ 0) : a / (a * b) = 1 / b := by - simp [div_mul_cancel_left₀ ha] - lemma mul_div_cancel_left_of_imp (h : a = 0 → b = 0) : a * b / a = b := by rw [mul_comm, mul_div_cancel_of_imp h] @@ -485,5 +477,3 @@ noncomputable def commGroupWithZeroOfIsUnitOrEqZero [hM : CommMonoidWithZero M] { groupWithZeroOfIsUnitOrEqZero h, hM with } end NoncomputableDefs - -@[deprecated (since := "2024-03-20")] alias mul_div_cancel' := mul_div_cancel₀ diff --git a/Mathlib/Algebra/Module/Submodule/Pointwise.lean b/Mathlib/Algebra/Module/Submodule/Pointwise.lean index b3c2fa905b8d3..811814d19e270 100644 --- a/Mathlib/Algebra/Module/Submodule/Pointwise.lean +++ b/Mathlib/Algebra/Module/Submodule/Pointwise.lean @@ -347,11 +347,6 @@ instance : CovariantClass (Set S) (Submodule R M) HSMul.hSMul LE.le := ⟨fun _ _ _ le => set_smul_le _ _ _ fun _ _ hr hm => mem_set_smul_of_mem_mem (mem1 := hr) (mem2 := le hm)⟩ -@[deprecated smul_mono_right (since := "2024-03-31")] -theorem set_smul_mono_right {p q : Submodule R M} (le : p ≤ q) : - s • p ≤ s • q := - smul_mono_right s le - lemma set_smul_mono_left {s t : Set S} (le : s ≤ t) : s • N ≤ t • N := set_smul_le _ _ _ fun _ _ hr hm => mem_set_smul_of_mem_mem (mem1 := le hr) diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean index 607f6e70c1a6c..96a7184d1eef9 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean @@ -217,8 +217,6 @@ lemma IsAbsoluteValue.abv_sum [Semiring R] [OrderedSemiring S] (abv : R → S) [ (f : ι → R) (s : Finset ι) : abv (∑ i ∈ s, f i) ≤ ∑ i ∈ s, abv (f i) := (IsAbsoluteValue.toAbsoluteValue abv).sum_le _ _ -@[deprecated (since := "2024-02-14")] alias abv_sum_le_sum_abv := IsAbsoluteValue.abv_sum - nonrec lemma AbsoluteValue.map_prod [CommSemiring R] [Nontrivial R] [LinearOrderedCommRing S] (abv : AbsoluteValue R S) (f : ι → R) (s : Finset ι) : abv (∏ i ∈ s, f i) = ∏ i ∈ s, abv (f i) := diff --git a/Mathlib/Algebra/Order/Field/Basic.lean b/Mathlib/Algebra/Order/Field/Basic.lean index e65d0da3e42fb..d2b9446b43e01 100644 --- a/Mathlib/Algebra/Order/Field/Basic.lean +++ b/Mathlib/Algebra/Order/Field/Basic.lean @@ -166,15 +166,6 @@ theorem one_le_inv_iff : 1 ≤ a⁻¹ ↔ 0 < a ∧ a ≤ 1 := one_le_inv_iff₀ ### Relating two divisions. -/ -@[deprecated (since := "2024-02-16")] alias div_le_div_of_le_of_nonneg := div_le_div_of_nonneg_right -@[deprecated (since := "2024-02-16")] alias div_lt_div_of_lt := div_lt_div_of_pos_right -@[deprecated (since := "2024-02-16")] alias div_le_div_of_le_left := div_le_div_of_nonneg_left -@[deprecated (since := "2024-02-16")] alias div_lt_div_of_lt_left := div_lt_div_of_pos_left - -@[deprecated div_le_div_of_nonneg_right (since := "2024-02-16")] -lemma div_le_div_of_le (hc : 0 ≤ c) (hab : a ≤ b) : a / c ≤ b / c := - div_le_div_of_nonneg_right hab hc - @[deprecated div_le_div_iff_of_pos_right (since := "2024-11-12")] theorem div_le_div_right (hc : 0 < c) : a / c ≤ b / c ↔ a ≤ b := div_le_div_iff_of_pos_right hc diff --git a/Mathlib/Algebra/Order/Field/Power.lean b/Mathlib/Algebra/Order/Field/Power.lean index 0da30f4498bde..ac82917ae0852 100644 --- a/Mathlib/Algebra/Order/Field/Power.lean +++ b/Mathlib/Algebra/Order/Field/Power.lean @@ -55,8 +55,6 @@ theorem zpow_strictAnti (h₀ : 0 < a) (h₁ : a < 1) : StrictAnti (a ^ · : ℤ theorem zpow_lt_iff_lt (hx : 1 < a) : a ^ m < a ^ n ↔ m < n := zpow_lt_zpow_iff_right₀ hx -@[deprecated (since := "2024-02-10")] alias ⟨_, zpow_lt_of_lt⟩ := zpow_lt_iff_lt - @[deprecated zpow_le_zpow_iff_right₀ (since := "2024-10-08")] theorem zpow_le_iff_le (hx : 1 < a) : a ^ m ≤ a ^ n ↔ m ≤ n := zpow_le_zpow_iff_right₀ hx diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean index 21b69f6811d62..bd7669e3210be 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean @@ -197,9 +197,6 @@ instance : AddLeftMono ℚ where @[simp] lemma num_pos {a : ℚ} : 0 < a.num ↔ 0 < a := lt_iff_lt_of_le_iff_le num_nonpos @[simp] lemma num_neg {a : ℚ} : a.num < 0 ↔ a < 0 := lt_iff_lt_of_le_iff_le num_nonneg -@[deprecated (since := "2024-02-16")] alias num_nonneg_iff_zero_le := num_nonneg -@[deprecated (since := "2024-02-16")] alias num_pos_iff_pos := num_pos - theorem div_lt_div_iff_mul_lt_mul {a b c d : ℤ} (b_pos : 0 < b) (d_pos : 0 < d) : (a : ℚ) / b < c / d ↔ a * d < c * b := by simp only [lt_iff_le_not_le] diff --git a/Mathlib/Algebra/Polynomial/Div.lean b/Mathlib/Algebra/Polynomial/Div.lean index 3bcbfbaac6a50..48d16d1d4a6f2 100644 --- a/Mathlib/Algebra/Polynomial/Div.lean +++ b/Mathlib/Algebra/Polynomial/Div.lean @@ -396,7 +396,6 @@ theorem modByMonic_eq_zero_iff_dvd (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p := degree_eq_natDegree (mt leadingCoeff_eq_zero.2 hrpq0)] at this exact not_lt_of_ge (Nat.le_add_right _ _) (WithBot.coe_lt_coe.1 this)⟩ -@[deprecated (since := "2024-03-23")] alias dvd_iff_modByMonic_eq_zero := modByMonic_eq_zero_iff_dvd /-- See `Polynomial.mul_left_modByMonic` for the other multiplication order. That version, unlike this one, requires commutativity. -/ diff --git a/Mathlib/Algebra/Squarefree/Basic.lean b/Mathlib/Algebra/Squarefree/Basic.lean index bdc6c55ec4a16..6096792244d94 100644 --- a/Mathlib/Algebra/Squarefree/Basic.lean +++ b/Mathlib/Algebra/Squarefree/Basic.lean @@ -160,9 +160,6 @@ theorem Squarefree.isRadical {x : R} (hx : Squarefree x) : IsRadical x := theorem Squarefree.dvd_pow_iff_dvd {x y : R} {n : ℕ} (hsq : Squarefree x) (h0 : n ≠ 0) : x ∣ y ^ n ↔ x ∣ y := ⟨hsq.isRadical n y, (·.pow h0)⟩ -@[deprecated (since := "2024-02-12")] -alias UniqueFactorizationMonoid.dvd_pow_iff_dvd_of_squarefree := Squarefree.dvd_pow_iff_dvd - end variable [CancelCommMonoidWithZero R] {x y p d : R} diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index 0c8626614a15c..b4eac11407814 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -65,9 +65,6 @@ theorem IsOpenImmersion.isOpen_range {X Y : Scheme.{u}} (f : X ⟶ Y) [H : IsOpe IsOpen (Set.range f.base) := H.base_open.isOpen_range -@[deprecated (since := "2024-03-17")] -alias IsOpenImmersion.open_range := IsOpenImmersion.isOpen_range - namespace Scheme.Hom variable {X Y : Scheme.{u}} (f : Scheme.Hom X Y) [H : IsOpenImmersion f] diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean index ba5a97a21ee36..91892e6714502 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean @@ -491,7 +491,6 @@ lemma toSpec_fromSpec {f : A} {m : ℕ} (f_deg : f ∈ 𝒜 m) (hm : 0 < m) (x : rw [← FromSpec.num_mem_carrier_iff f_deg hm x] exact ToSpec.mk_mem_carrier _ z -@[deprecated (since := "2024-03-02")] alias toSpecFromSpec := toSpec_fromSpec end toSpecFromSpec diff --git a/Mathlib/Analysis/CStarAlgebra/Matrix.lean b/Mathlib/Analysis/CStarAlgebra/Matrix.lean index 5db2ac0e4cf48..16c1080e57b78 100644 --- a/Mathlib/Analysis/CStarAlgebra/Matrix.lean +++ b/Mathlib/Analysis/CStarAlgebra/Matrix.lean @@ -171,53 +171,35 @@ scoped[Matrix.L2OpNorm] attribute [instance] Matrix.instL2OpNormedAddCommGroup lemma l2_opNorm_def (A : Matrix m n 𝕜) : ‖A‖ = ‖(toEuclideanLin (𝕜 := 𝕜) (m := m) (n := n)).trans toContinuousLinearMap A‖ := rfl -@[deprecated (since := "2024-02-02")] alias l2_op_norm_def := l2_opNorm_def - lemma l2_opNNNorm_def (A : Matrix m n 𝕜) : ‖A‖₊ = ‖(toEuclideanLin (𝕜 := 𝕜) (m := m) (n := n)).trans toContinuousLinearMap A‖₊ := rfl -@[deprecated (since := "2024-02-02")] alias l2_op_nnnorm_def := l2_opNNNorm_def - lemma l2_opNorm_conjTranspose [DecidableEq m] (A : Matrix m n 𝕜) : ‖Aᴴ‖ = ‖A‖ := by rw [l2_opNorm_def, toEuclideanLin_eq_toLin_orthonormal, LinearEquiv.trans_apply, toLin_conjTranspose, adjoint_toContinuousLinearMap] exact ContinuousLinearMap.adjoint.norm_map _ -@[deprecated (since := "2024-02-02")] alias l2_op_norm_conjTranspose := l2_opNorm_conjTranspose - lemma l2_opNNNorm_conjTranspose [DecidableEq m] (A : Matrix m n 𝕜) : ‖Aᴴ‖₊ = ‖A‖₊ := Subtype.ext <| l2_opNorm_conjTranspose _ -@[deprecated (since := "2024-02-02")] alias l2_op_nnnorm_conjTranspose := l2_opNNNorm_conjTranspose - lemma l2_opNorm_conjTranspose_mul_self (A : Matrix m n 𝕜) : ‖Aᴴ * A‖ = ‖A‖ * ‖A‖ := by classical rw [l2_opNorm_def, toEuclideanLin_eq_toLin_orthonormal, LinearEquiv.trans_apply, Matrix.toLin_mul (v₂ := (EuclideanSpace.basisFun m 𝕜).toBasis), toLin_conjTranspose] exact ContinuousLinearMap.norm_adjoint_comp_self _ -@[deprecated (since := "2024-02-02")] -alias l2_op_norm_conjTranspose_mul_self := l2_opNorm_conjTranspose_mul_self - lemma l2_opNNNorm_conjTranspose_mul_self (A : Matrix m n 𝕜) : ‖Aᴴ * A‖₊ = ‖A‖₊ * ‖A‖₊ := Subtype.ext <| l2_opNorm_conjTranspose_mul_self _ -@[deprecated (since := "2024-02-02")] -alias l2_op_nnnorm_conjTranspose_mul_self := l2_opNNNorm_conjTranspose_mul_self - -- note: with only a type ascription in the left-hand side, Lean picks the wrong norm. lemma l2_opNorm_mulVec (A : Matrix m n 𝕜) (x : EuclideanSpace 𝕜 n) : ‖(EuclideanSpace.equiv m 𝕜).symm <| A *ᵥ x‖ ≤ ‖A‖ * ‖x‖ := toEuclideanLin (n := n) (m := m) (𝕜 := 𝕜) |>.trans toContinuousLinearMap A |>.le_opNorm x -@[deprecated (since := "2024-02-02")] alias l2_op_norm_mulVec := l2_opNorm_mulVec - lemma l2_opNNNorm_mulVec (A : Matrix m n 𝕜) (x : EuclideanSpace 𝕜 n) : ‖(EuclideanSpace.equiv m 𝕜).symm <| A *ᵥ x‖₊ ≤ ‖A‖₊ * ‖x‖₊ := A.l2_opNorm_mulVec x -@[deprecated (since := "2024-02-02")] alias l2_op_nnnorm_mulVec := l2_opNNNorm_mulVec - lemma l2_opNorm_mul (A : Matrix m n 𝕜) (B : Matrix n l 𝕜) : ‖A * B‖ ≤ ‖A‖ * ‖B‖ := by simp only [l2_opNorm_def] @@ -227,13 +209,9 @@ lemma l2_opNorm_mul (A : Matrix m n 𝕜) (B : Matrix n l 𝕜) : ext1 x exact congr($(Matrix.toLin'_mul A B) x) -@[deprecated (since := "2024-02-02")] alias l2_op_norm_mul := l2_opNorm_mul - lemma l2_opNNNorm_mul (A : Matrix m n 𝕜) (B : Matrix n l 𝕜) : ‖A * B‖₊ ≤ ‖A‖₊ * ‖B‖₊ := l2_opNorm_mul A B -@[deprecated (since := "2024-02-02")] alias l2_op_nnnorm_mul := l2_opNNNorm_mul - /-- The normed algebra structure on `Matrix n n 𝕜` arising from the operator norm given by the identification with (continuous) linear endmorphisms of `EuclideanSpace 𝕜 n`. -/ def instL2OpNormedSpace : NormedSpace 𝕜 (Matrix m n 𝕜) where diff --git a/Mathlib/Analysis/CStarAlgebra/Unitization.lean b/Mathlib/Analysis/CStarAlgebra/Unitization.lean index 8771d6ba22cae..caa411ee70756 100644 --- a/Mathlib/Analysis/CStarAlgebra/Unitization.lean +++ b/Mathlib/Analysis/CStarAlgebra/Unitization.lean @@ -38,13 +38,9 @@ lemma opNorm_mul_flip_apply (a : E) : ‖(mul 𝕜 E).flip a‖ = ‖a‖ := by _ ≤ ‖(mul 𝕜 E).flip a‖ * ‖b‖ := by simpa only [flip_apply, mul_apply', norm_star] using le_opNorm ((mul 𝕜 E).flip a) (star b) -@[deprecated (since := "2024-02-02")] alias op_norm_mul_flip_apply := opNorm_mul_flip_apply - lemma opNNNorm_mul_flip_apply (a : E) : ‖(mul 𝕜 E).flip a‖₊ = ‖a‖₊ := Subtype.ext (opNorm_mul_flip_apply 𝕜 a) -@[deprecated (since := "2024-02-02")] alias op_nnnorm_mul_flip_apply := opNNNorm_mul_flip_apply - variable (E) lemma isometry_mul_flip : Isometry (mul 𝕜 E).flip := diff --git a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean index 400df9cb52915..168c48c5ac9ff 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean @@ -630,10 +630,6 @@ theorem HasFTaylorSeriesUpToOn.eq_iteratedFDerivWithin_of_uniqueDiffOn rw [iteratedFDerivWithin_succ_eq_comp_left, Function.comp_apply, this.fderivWithin (hs x hx)] exact (ContinuousMultilinearMap.uncurry_curryLeft _).symm -@[deprecated (since := "2024-03-28")] -alias HasFTaylorSeriesUpToOn.eq_ftaylor_series_of_uniqueDiffOn := - HasFTaylorSeriesUpToOn.eq_iteratedFDerivWithin_of_uniqueDiffOn - /-- The iterated derivative commutes with shifting the function by a constant on the left. -/ lemma iteratedFDerivWithin_comp_add_left' (n : ℕ) (a : E) : iteratedFDerivWithin 𝕜 n (fun z ↦ f (a + z)) s = diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/Deriv.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/Deriv.lean index 48cbff9518b9a..be38e1e55e5cc 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/Deriv.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/Deriv.lean @@ -49,5 +49,3 @@ variable {f} theorem isOpenMap_of_hasStrictDerivAt {f' : 𝕜 → 𝕜} (hf : ∀ x, HasStrictDerivAt f (f' x) x) (h0 : ∀ x, f' x ≠ 0) : IsOpenMap f := isOpenMap_iff_nhds_le.2 fun x => ((hf x).map_nhds_eq (h0 x)).ge -@[deprecated (since := "2024-03-23")] -alias open_map_of_strict_deriv := isOpenMap_of_hasStrictDerivAt diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean index 06f438efc45a0..7f5ef4e24ef29 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean @@ -194,5 +194,3 @@ end HasStrictFDerivAt theorem isOpenMap_of_hasStrictFDerivAt_equiv [CompleteSpace E] {f : E → F} {f' : E → E ≃L[𝕜] F} (hf : ∀ x, HasStrictFDerivAt f (f' x : E →L[𝕜] F) x) : IsOpenMap f := isOpenMap_iff_nhds_le.2 fun x => (hf x).map_nhds_eq_of_equiv.ge -@[deprecated (since := "2024-03-23")] -alias open_map_of_strict_fderiv_equiv := isOpenMap_of_hasStrictFDerivAt_equiv diff --git a/Mathlib/Analysis/Calculus/MeanValue.lean b/Mathlib/Analysis/Calculus/MeanValue.lean index 8194a4e3aa8f5..ee6d474ded239 100644 --- a/Mathlib/Analysis/Calculus/MeanValue.lean +++ b/Mathlib/Analysis/Calculus/MeanValue.lean @@ -1008,9 +1008,6 @@ lemma strictMonoOn_of_hasDerivWithinAt_pos {D : Set ℝ} (hD : Convex ℝ D) {f strictMonoOn_of_deriv_pos hD hf fun x hx ↦ by rw [deriv_eqOn isOpen_interior hf' hx]; exact hf'₀ _ hx -@[deprecated (since := "2024-03-02")] -alias StrictMonoOn_of_hasDerivWithinAt_pos := strictMonoOn_of_hasDerivWithinAt_pos - /-- Let `f : ℝ → ℝ` be a differentiable function. If `f'` is strictly positive, then `f` is a strictly monotone function. -/ lemma strictMono_of_hasDerivAt_pos {f f' : ℝ → ℝ} (hf : ∀ x, HasDerivAt f (f' x) x) @@ -1080,18 +1077,12 @@ lemma strictAntiOn_of_hasDerivWithinAt_neg {D : Set ℝ} (hD : Convex ℝ D) {f strictAntiOn_of_deriv_neg hD hf fun x hx ↦ by rw [deriv_eqOn isOpen_interior hf' hx]; exact hf'₀ _ hx -@[deprecated (since := "2024-03-02")] -alias StrictAntiOn_of_hasDerivWithinAt_pos := strictAntiOn_of_hasDerivWithinAt_neg - /-- Let `f : ℝ → ℝ` be a differentiable function. If `f'` is strictly positive, then `f` is a strictly monotone function. -/ lemma strictAnti_of_hasDerivAt_neg {f f' : ℝ → ℝ} (hf : ∀ x, HasDerivAt f (f' x) x) (hf' : ∀ x, f' x < 0) : StrictAnti f := strictAnti_of_deriv_neg fun x ↦ by rw [(hf _).deriv]; exact hf' _ -@[deprecated (since := "2024-03-02")] -alias strictAnti_of_hasDerivAt_pos := strictAnti_of_hasDerivAt_neg - /-- Let `f` be a function continuous on a convex (or, equivalently, connected) subset `D` of the real line. If `f` is differentiable on the interior of `D` and `f'` is nonpositive, then `f` is an antitone function on `D`. -/ diff --git a/Mathlib/Analysis/Complex/Polynomial/Basic.lean b/Mathlib/Analysis/Complex/Polynomial/Basic.lean index 82e38a8adc578..706b89c25be7f 100644 --- a/Mathlib/Analysis/Complex/Polynomial/Basic.lean +++ b/Mathlib/Analysis/Complex/Polynomial/Basic.lean @@ -216,6 +216,3 @@ lemma Irreducible.degree_le_two {p : ℝ[X]} (hp : Irreducible p) : degree p ≤ /-- An irreducible real polynomial has natural degree at most two. -/ lemma Irreducible.natDegree_le_two {p : ℝ[X]} (hp : Irreducible p) : natDegree p ≤ 2 := natDegree_le_iff_degree_le.2 hp.degree_le_two - -@[deprecated (since := "2024-02-18")] -alias Irreducible.nat_degree_le_two := Irreducible.natDegree_le_two diff --git a/Mathlib/Analysis/Fourier/FourierTransform.lean b/Mathlib/Analysis/Fourier/FourierTransform.lean index a5d1ddb0067c9..c75680f9ddcd1 100644 --- a/Mathlib/Analysis/Fourier/FourierTransform.lean +++ b/Mathlib/Analysis/Fourier/FourierTransform.lean @@ -136,9 +136,6 @@ theorem fourierIntegral_convergent_iff (he : Continuous e) e.map_zero_eq_one, one_smul] at this -- the `(e _)` speeds up elaboration considerably exact this -@[deprecated (since := "2024-03-29")] -alias fourier_integral_convergent_iff := VectorFourier.fourierIntegral_convergent_iff - theorem fourierIntegral_add (he : Continuous e) (hL : Continuous fun p : V × W ↦ L p.1 p.2) {f g : V → E} (hf : Integrable f μ) (hg : Integrable g μ) : fourierIntegral e μ L (f + g) = fourierIntegral e μ L f + fourierIntegral e μ L g := by @@ -431,16 +428,11 @@ theorem fourierIntegral_real_eq (f : ℝ → E) (w : ℝ) : fourierIntegral f w = ∫ v : ℝ, 𝐞 (-(v * w)) • f v := rfl -@[deprecated (since := "2024-02-21")] alias fourierIntegral_def := fourierIntegral_real_eq - theorem fourierIntegral_real_eq_integral_exp_smul (f : ℝ → E) (w : ℝ) : 𝓕 f w = ∫ v : ℝ, Complex.exp (↑(-2 * π * v * w) * Complex.I) • f v := by simp_rw [fourierIntegral_real_eq, Circle.smul_def, Real.fourierChar_apply, mul_neg, neg_mul, mul_assoc] -@[deprecated (since := "2024-02-21")] -alias fourierIntegral_eq_integral_exp_smul := fourierIntegral_real_eq_integral_exp_smul - theorem fourierIntegral_continuousLinearMap_apply {F : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] {f : V → (F →L[ℝ] E)} {a : F} {v : V} (hf : Integrable f) : diff --git a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean index 9aa623e738fae..4e702fd38f691 100644 --- a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean +++ b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean @@ -76,7 +76,6 @@ theorem isClosed_range (coercive : IsCoercive B) : IsClosed (range B♯ : Set V) rcases coercive.antilipschitz with ⟨_, _, antilipschitz⟩ exact antilipschitz.isClosed_range B♯.uniformContinuous -@[deprecated (since := "2024-03-19")] alias closed_range := isClosed_range theorem range_eq_top (coercive : IsCoercive B) : range B♯ = ⊤ := by haveI := coercive.isClosed_range.completeSpace_coe diff --git a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean index a9afb01f2a21b..ce34bcdfe2375 100644 --- a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean +++ b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean @@ -79,10 +79,6 @@ lemma FiniteDimensional.of_fact_finrank_eq_two {K V : Type*} [DivisionRing K] attribute [local instance] FiniteDimensional.of_fact_finrank_eq_two -@[deprecated (since := "2024-02-02")] -alias FiniteDimensional.finiteDimensional_of_fact_finrank_eq_two := - FiniteDimensional.of_fact_finrank_eq_two - variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] [Fact (finrank ℝ E = 2)] (o : Orientation ℝ E (Fin 2)) diff --git a/Mathlib/Analysis/LocallyConvex/Basic.lean b/Mathlib/Analysis/LocallyConvex/Basic.lean index ffe0e4d997485..f6d8feaab62d1 100644 --- a/Mathlib/Analysis/LocallyConvex/Basic.lean +++ b/Mathlib/Analysis/LocallyConvex/Basic.lean @@ -215,8 +215,6 @@ theorem Balanced.absorbs_self (hA : Balanced 𝕜 A) : Absorbs 𝕜 A A := theorem Balanced.smul_mem_iff (hs : Balanced 𝕜 s) (h : ‖a‖ = ‖b‖) : a • x ∈ s ↔ b • x ∈ s := ⟨(hs.smul_mem_mono · h.ge), (hs.smul_mem_mono · h.le)⟩ -@[deprecated (since := "2024-02-02")] alias Balanced.mem_smul_iff := Balanced.smul_mem_iff - variable [TopologicalSpace E] [ContinuousSMul 𝕜 E] /-- Every neighbourhood of the origin is absorbent. -/ @@ -235,10 +233,6 @@ theorem Balanced.zero_insert_interior (hA : Balanced 𝕜 A) : apply insert_subset_insert exact ((isOpenMap_smul₀ h).mapsTo_interior <| hA.smul_mem ha).image_subset -@[deprecated Balanced.zero_insert_interior (since := "2024-02-03")] -theorem balanced_zero_union_interior (hA : Balanced 𝕜 A) : Balanced 𝕜 ((0 : Set E) ∪ interior A) := - hA.zero_insert_interior - /-- The interior of a balanced set is balanced if it contains the origin. -/ protected theorem Balanced.interior (hA : Balanced 𝕜 A) (h : (0 : E) ∈ interior A) : Balanced 𝕜 (interior A) := by @@ -255,9 +249,6 @@ section NontriviallyNormedField variable [NontriviallyNormedField 𝕜] [AddCommGroup E] [Module 𝕜 E] {s : Set E} -@[deprecated Absorbent.zero_mem (since := "2024-02-02")] -theorem Absorbent.zero_mem' (hs : Absorbent 𝕜 s) : (0 : E) ∈ s := hs.zero_mem - variable [Module ℝ E] [SMulCommClass ℝ 𝕜 E] protected theorem Balanced.convexHull (hs : Balanced 𝕜 s) : Balanced 𝕜 (convexHull ℝ s) := by @@ -269,8 +260,6 @@ protected theorem Balanced.convexHull (hs : Balanced 𝕜 s) : Balanced 𝕜 (co simp only [smul_add, ← smul_comm] exact convex_convexHull ℝ s (hx a ha) (hy a ha) hu hv huv -@[deprecated (since := "2024-02-02")] alias balanced_convexHull_of_balanced := Balanced.convexHull - end NontriviallyNormedField section Real diff --git a/Mathlib/Analysis/Matrix.lean b/Mathlib/Analysis/Matrix.lean index 7a1f22fb8be30..d82d5f067fe3c 100644 --- a/Mathlib/Analysis/Matrix.lean +++ b/Mathlib/Analysis/Matrix.lean @@ -248,39 +248,27 @@ theorem linfty_opNorm_def (A : Matrix m n α) : change ‖fun i => (WithLp.equiv 1 _).symm (A i)‖ = _ simp [Pi.norm_def, PiLp.nnnorm_eq_of_L1] -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_def := linfty_opNorm_def - theorem linfty_opNNNorm_def (A : Matrix m n α) : ‖A‖₊ = (Finset.univ : Finset m).sup fun i : m => ∑ j : n, ‖A i j‖₊ := Subtype.ext <| linfty_opNorm_def A -@[deprecated (since := "2024-02-02")] alias linfty_op_nnnorm_def := linfty_opNNNorm_def - @[simp] theorem linfty_opNNNorm_col (v : m → α) : ‖col ι v‖₊ = ‖v‖₊ := by rw [linfty_opNNNorm_def, Pi.nnnorm_def] simp -@[deprecated (since := "2024-02-02")] alias linfty_op_nnnorm_col := linfty_opNNNorm_col - @[simp] theorem linfty_opNorm_col (v : m → α) : ‖col ι v‖ = ‖v‖ := congr_arg ((↑) : ℝ≥0 → ℝ) <| linfty_opNNNorm_col v -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_col := linfty_opNorm_col - @[simp] theorem linfty_opNNNorm_row (v : n → α) : ‖row ι v‖₊ = ∑ i, ‖v i‖₊ := by simp [linfty_opNNNorm_def] -@[deprecated (since := "2024-02-02")] alias linfty_op_nnnorm_row := linfty_opNNNorm_row - @[simp] theorem linfty_opNorm_row (v : n → α) : ‖row ι v‖ = ∑ i, ‖v i‖ := (congr_arg ((↑) : ℝ≥0 → ℝ) <| linfty_opNNNorm_row v).trans <| by simp [NNReal.coe_sum] -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_row := linfty_opNorm_row - @[simp] theorem linfty_opNNNorm_diagonal [DecidableEq m] (v : m → α) : ‖diagonal v‖₊ = ‖v‖₊ := by rw [linfty_opNNNorm_def, Pi.nnnorm_def] @@ -289,14 +277,10 @@ theorem linfty_opNNNorm_diagonal [DecidableEq m] (v : m → α) : ‖diagonal v · rw [diagonal_apply_ne' _ hij, nnnorm_zero] · rw [diagonal_apply_eq] -@[deprecated (since := "2024-02-02")] alias linfty_op_nnnorm_diagonal := linfty_opNNNorm_diagonal - @[simp] theorem linfty_opNorm_diagonal [DecidableEq m] (v : m → α) : ‖diagonal v‖ = ‖v‖ := congr_arg ((↑) : ℝ≥0 → ℝ) <| linfty_opNNNorm_diagonal v -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_diagonal := linfty_opNorm_diagonal - end SeminormedAddCommGroup section NonUnitalSeminormedRing @@ -320,24 +304,16 @@ theorem linfty_opNNNorm_mul (A : Matrix l m α) (B : Matrix m n α) : ‖A * B simp_rw [← Finset.sum_mul, ← NNReal.finset_sup_mul] rfl -@[deprecated (since := "2024-02-02")] alias linfty_op_nnnorm_mul := linfty_opNNNorm_mul - theorem linfty_opNorm_mul (A : Matrix l m α) (B : Matrix m n α) : ‖A * B‖ ≤ ‖A‖ * ‖B‖ := linfty_opNNNorm_mul _ _ -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_mul := linfty_opNorm_mul - theorem linfty_opNNNorm_mulVec (A : Matrix l m α) (v : m → α) : ‖A *ᵥ v‖₊ ≤ ‖A‖₊ * ‖v‖₊ := by rw [← linfty_opNNNorm_col (ι := Fin 1) (A *ᵥ v), ← linfty_opNNNorm_col v (ι := Fin 1)] exact linfty_opNNNorm_mul A (col (Fin 1) v) -@[deprecated (since := "2024-02-02")] alias linfty_op_nnnorm_mulVec := linfty_opNNNorm_mulVec - theorem linfty_opNorm_mulVec (A : Matrix l m α) (v : m → α) : ‖A *ᵥ v‖ ≤ ‖A‖ * ‖v‖ := linfty_opNNNorm_mulVec _ _ -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_mulVec := linfty_opNorm_mulVec - end NonUnitalSeminormedRing /-- Seminormed non-unital ring instance (using sup norm of L1 norm) for matrices over a semi normed @@ -435,15 +411,10 @@ lemma linfty_opNNNorm_eq_opNNNorm (A : Matrix m n α) : nnnorm_one, mul_one] at hN exact hN -@[deprecated (since := "2024-02-02")] -alias linfty_op_nnnorm_eq_op_nnnorm := linfty_opNNNorm_eq_opNNNorm - lemma linfty_opNorm_eq_opNorm (A : Matrix m n α) : ‖A‖ = ‖ContinuousLinearMap.mk (Matrix.mulVecLin A)‖ := congr_arg NNReal.toReal (linfty_opNNNorm_eq_opNNNorm A) -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_eq_op_norm := linfty_opNorm_eq_opNorm - variable [DecidableEq n] @[simp] lemma linfty_opNNNorm_toMatrix (f : (n → α) →L[α] (m → α)) : @@ -451,14 +422,10 @@ variable [DecidableEq n] rw [linfty_opNNNorm_eq_opNNNorm] simp only [← toLin'_apply', toLin'_toMatrix'] -@[deprecated (since := "2024-02-02")] alias linfty_op_nnnorm_toMatrix := linfty_opNNNorm_toMatrix - @[simp] lemma linfty_opNorm_toMatrix (f : (n → α) →L[α] (m → α)) : ‖LinearMap.toMatrix' (↑f : (n → α) →ₗ[α] (m → α))‖ = ‖f‖ := congr_arg NNReal.toReal (linfty_opNNNorm_toMatrix f) -@[deprecated (since := "2024-02-02")] alias linfty_op_norm_toMatrix := linfty_opNorm_toMatrix - end end LinftyOp diff --git a/Mathlib/Analysis/Normed/Lp/LpEquiv.lean b/Mathlib/Analysis/Normed/Lp/LpEquiv.lean index d77bc7fea6e3e..bd8818ac7ee46 100644 --- a/Mathlib/Analysis/Normed/Lp/LpEquiv.lean +++ b/Mathlib/Analysis/Normed/Lp/LpEquiv.lean @@ -133,7 +133,6 @@ noncomputable def AddEquiv.lpBCF : lp (fun _ : α ↦ E) ∞ ≃+ (α →ᵇ E) right_inv _f := rfl map_add' _f _g := rfl -@[deprecated (since := "2024-03-16")] alias AddEquiv.lpBcf := AddEquiv.lpBCF theorem coe_addEquiv_lpBCF (f : lp (fun _ : α ↦ E) ∞) : (AddEquiv.lpBCF f : α → E) = f := rfl @@ -149,7 +148,6 @@ noncomputable def lpBCFₗᵢ : lp (fun _ : α ↦ E) ∞ ≃ₗᵢ[𝕜] α → map_smul' := fun _ _ ↦ rfl norm_map' := fun f ↦ by simp only [norm_eq_iSup_norm, lp.norm_eq_ciSup]; rfl } -@[deprecated (since := "2024-03-16")] alias lpBcfₗᵢ := lpBCFₗᵢ variable {𝕜 E} @@ -168,7 +166,6 @@ noncomputable def RingEquiv.lpBCF : lp (fun _ : α ↦ R) ∞ ≃+* (α →ᵇ R { @AddEquiv.lpBCF _ R _ _ _ with map_mul' := fun _f _g => rfl } -@[deprecated (since := "2024-03-16")] alias RingEquiv.lpBcf := RingEquiv.lpBCF variable {R} @@ -187,7 +184,6 @@ variable (α) noncomputable def AlgEquiv.lpBCF : lp (fun _ : α ↦ A) ∞ ≃ₐ[𝕜] α →ᵇ A := { RingEquiv.lpBCF A with commutes' := fun _k ↦ rfl } -@[deprecated (since := "2024-03-16")] alias AlgEquiv.lpBcf := AlgEquiv.lpBCF variable {α A 𝕜} diff --git a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean index 789c690f2042f..3620ce5749a6c 100644 --- a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean +++ b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean @@ -287,15 +287,11 @@ theorem Basis.opNNNorm_le {ι : Type*} [Fintype ι] (v : Basis ι 𝕜 E) {u : E _ ≤ Fintype.card ι • (‖φ‖₊ * ‖e‖₊) := nsmul_le_nsmul_right (φ.le_opNNNorm e) _ _ = Fintype.card ι • ‖φ‖₊ * M * ‖e‖₊ := by simp only [smul_mul_assoc, mul_right_comm] -@[deprecated (since := "2024-02-02")] alias Basis.op_nnnorm_le := Basis.opNNNorm_le - theorem Basis.opNorm_le {ι : Type*} [Fintype ι] (v : Basis ι 𝕜 E) {u : E →L[𝕜] F} {M : ℝ} (hM : 0 ≤ M) (hu : ∀ i, ‖u (v i)‖ ≤ M) : ‖u‖ ≤ Fintype.card ι • ‖v.equivFunL.toContinuousLinearMap‖ * M := by simpa using NNReal.coe_le_coe.mpr (v.opNNNorm_le ⟨M, hM⟩ hu) -@[deprecated (since := "2024-02-02")] alias Basis.op_norm_le := Basis.opNorm_le - /-- A weaker version of `Basis.opNNNorm_le` that abstracts away the value of `C`. -/ theorem Basis.exists_opNNNorm_le {ι : Type*} [Finite ι] (v : Basis ι 𝕜 E) : ∃ C > (0 : ℝ≥0), ∀ {u : E →L[𝕜] F} (M : ℝ≥0), (∀ i, ‖u (v i)‖₊ ≤ M) → ‖u‖₊ ≤ C * M := by @@ -305,8 +301,6 @@ theorem Basis.exists_opNNNorm_le {ι : Type*} [Finite ι] (v : Basis ι 𝕜 E) zero_lt_one.trans_le (le_max_right _ _), fun {u} M hu => (v.opNNNorm_le M hu).trans <| mul_le_mul_of_nonneg_right (le_max_left _ _) (zero_le M)⟩ -@[deprecated (since := "2024-02-02")] alias Basis.exists_op_nnnorm_le := Basis.exists_opNNNorm_le - /-- A weaker version of `Basis.opNorm_le` that abstracts away the value of `C`. -/ theorem Basis.exists_opNorm_le {ι : Type*} [Finite ι] (v : Basis ι 𝕜 E) : ∃ C > (0 : ℝ), ∀ {u : E →L[𝕜] F} {M : ℝ}, 0 ≤ M → (∀ i, ‖u (v i)‖ ≤ M) → ‖u‖ ≤ C * M := by @@ -316,8 +310,6 @@ theorem Basis.exists_opNorm_le {ι : Type*} [Finite ι] (v : Basis ι 𝕜 E) : intro u M hM H simpa using h ⟨M, hM⟩ H -@[deprecated (since := "2024-02-02")] alias Basis.exists_op_norm_le := Basis.exists_opNorm_le - instance [FiniteDimensional 𝕜 E] [SecondCountableTopology F] : SecondCountableTopology (E →L[𝕜] F) := by set d := Module.finrank 𝕜 E @@ -455,27 +447,18 @@ theorem FiniteDimensional.of_isCompact_closedBall₀ {r : ℝ} (rpos : 0 < r) exact φmono (Nat.lt_succ_self N) _ < ‖c‖ := hN (N + 1) (Nat.le_succ N) -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_isCompact_closedBall₀ := FiniteDimensional.of_isCompact_closedBall₀ - /-- **Riesz's theorem**: if a closed ball of positive radius is compact in a vector space, then the space is finite-dimensional. -/ theorem FiniteDimensional.of_isCompact_closedBall {r : ℝ} (rpos : 0 < r) {c : E} (h : IsCompact (Metric.closedBall c r)) : FiniteDimensional 𝕜 E := .of_isCompact_closedBall₀ 𝕜 rpos <| by simpa using h.vadd (-c) -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_isCompact_closedBall := FiniteDimensional.of_isCompact_closedBall - /-- **Riesz's theorem**: a locally compact normed vector space is finite-dimensional. -/ theorem FiniteDimensional.of_locallyCompactSpace [LocallyCompactSpace E] : FiniteDimensional 𝕜 E := let ⟨_r, rpos, hr⟩ := exists_isCompact_closedBall (0 : E) .of_isCompact_closedBall₀ 𝕜 rpos hr -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_locallyCompactSpace := FiniteDimensional.of_locallyCompactSpace - /-- If a function has compact support, then either the function is trivial or the space is finite-dimensional. -/ theorem HasCompactSupport.eq_zero_or_finiteDimensional {X : Type*} [TopologicalSpace X] [Zero X] diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index 4a71d1dff9424..e45477c7b3695 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -374,29 +374,20 @@ theorem isLeast_opNorm (f : ContinuousMultilinearMap 𝕜 E G) : exact isClosed_Ici.inter (isClosed_iInter fun m ↦ isClosed_le continuous_const (continuous_id.mul continuous_const)) -@[deprecated (since := "2024-02-02")] alias isLeast_op_norm := isLeast_opNorm - theorem opNorm_nonneg (f : ContinuousMultilinearMap 𝕜 E G) : 0 ≤ ‖f‖ := Real.sInf_nonneg fun _ ⟨hx, _⟩ => hx -@[deprecated (since := "2024-02-02")] alias op_norm_nonneg := opNorm_nonneg - /-- The fundamental property of the operator norm of a continuous multilinear map: `‖f m‖` is bounded by `‖f‖` times the product of the `‖m i‖`. -/ theorem le_opNorm (f : ContinuousMultilinearMap 𝕜 E G) (m : ∀ i, E i) : ‖f m‖ ≤ ‖f‖ * ∏ i, ‖m i‖ := f.isLeast_opNorm.1.2 m -@[deprecated (since := "2024-02-02")] alias le_op_norm := le_opNorm - theorem le_mul_prod_of_opNorm_le_of_le {f : ContinuousMultilinearMap 𝕜 E G} {m : ∀ i, E i} {C : ℝ} {b : ι → ℝ} (hC : ‖f‖ ≤ C) (hm : ∀ i, ‖m i‖ ≤ b i) : ‖f m‖ ≤ C * ∏ i, b i := (f.le_opNorm m).trans <| by gcongr; exacts [f.opNorm_nonneg.trans hC, hm _] -@[deprecated (since := "2024-02-02")] -alias le_mul_prod_of_le_op_norm_of_le := le_mul_prod_of_opNorm_le_of_le - @[deprecated (since := "2024-11-27")] alias le_mul_prod_of_le_opNorm_of_le := le_mul_prod_of_opNorm_le_of_le @@ -404,67 +395,46 @@ theorem le_opNorm_mul_prod_of_le (f : ContinuousMultilinearMap 𝕜 E G) {m : ∀ i, E i} {b : ι → ℝ} (hm : ∀ i, ‖m i‖ ≤ b i) : ‖f m‖ ≤ ‖f‖ * ∏ i, b i := le_mul_prod_of_opNorm_le_of_le le_rfl hm -@[deprecated (since := "2024-02-02")] alias le_op_norm_mul_prod_of_le := le_opNorm_mul_prod_of_le - theorem le_opNorm_mul_pow_card_of_le (f : ContinuousMultilinearMap 𝕜 E G) {m b} (hm : ‖m‖ ≤ b) : ‖f m‖ ≤ ‖f‖ * b ^ Fintype.card ι := by simpa only [prod_const] using f.le_opNorm_mul_prod_of_le fun i => (norm_le_pi_norm m i).trans hm -@[deprecated (since := "2024-02-02")] -alias le_op_norm_mul_pow_card_of_le := le_opNorm_mul_pow_card_of_le - theorem le_opNorm_mul_pow_of_le {n : ℕ} {Ei : Fin n → Type*} [∀ i, SeminormedAddCommGroup (Ei i)] [∀ i, NormedSpace 𝕜 (Ei i)] (f : ContinuousMultilinearMap 𝕜 Ei G) {m : ∀ i, Ei i} {b : ℝ} (hm : ‖m‖ ≤ b) : ‖f m‖ ≤ ‖f‖ * b ^ n := by simpa only [Fintype.card_fin] using f.le_opNorm_mul_pow_card_of_le hm -@[deprecated (since := "2024-02-02")] alias le_op_norm_mul_pow_of_le := le_opNorm_mul_pow_of_le - theorem le_of_opNorm_le {f : ContinuousMultilinearMap 𝕜 E G} {C : ℝ} (h : ‖f‖ ≤ C) (m : ∀ i, E i) : ‖f m‖ ≤ C * ∏ i, ‖m i‖ := le_mul_prod_of_opNorm_le_of_le h fun _ ↦ le_rfl -@[deprecated (since := "2024-02-02")] alias le_of_op_norm_le := le_of_opNorm_le - theorem ratio_le_opNorm (f : ContinuousMultilinearMap 𝕜 E G) (m : ∀ i, E i) : (‖f m‖ / ∏ i, ‖m i‖) ≤ ‖f‖ := div_le_of_le_mul₀ (by positivity) (opNorm_nonneg _) (f.le_opNorm m) -@[deprecated (since := "2024-02-02")] alias ratio_le_op_norm := ratio_le_opNorm - /-- The image of the unit ball under a continuous multilinear map is bounded. -/ theorem unit_le_opNorm (f : ContinuousMultilinearMap 𝕜 E G) {m : ∀ i, E i} (h : ‖m‖ ≤ 1) : ‖f m‖ ≤ ‖f‖ := (le_opNorm_mul_pow_card_of_le f h).trans <| by simp -@[deprecated (since := "2024-02-02")] alias unit_le_op_norm := unit_le_opNorm - /-- If one controls the norm of every `f x`, then one controls the norm of `f`. -/ theorem opNorm_le_bound {f : ContinuousMultilinearMap 𝕜 E G} {M : ℝ} (hMp : 0 ≤ M) (hM : ∀ m, ‖f m‖ ≤ M * ∏ i, ‖m i‖) : ‖f‖ ≤ M := csInf_le bounds_bddBelow ⟨hMp, hM⟩ -@[deprecated (since := "2024-02-02")] alias op_norm_le_bound := opNorm_le_bound - theorem opNorm_le_iff {f : ContinuousMultilinearMap 𝕜 E G} {C : ℝ} (hC : 0 ≤ C) : ‖f‖ ≤ C ↔ ∀ m, ‖f m‖ ≤ C * ∏ i, ‖m i‖ := ⟨fun h _ ↦ le_of_opNorm_le h _, opNorm_le_bound hC⟩ -@[deprecated (since := "2024-02-02")] alias op_norm_le_iff := opNorm_le_iff - /-- The operator norm satisfies the triangle inequality. -/ theorem opNorm_add_le (f g : ContinuousMultilinearMap 𝕜 E G) : ‖f + g‖ ≤ ‖f‖ + ‖g‖ := opNorm_le_bound (add_nonneg (opNorm_nonneg f) (opNorm_nonneg g)) fun x => by rw [add_mul] exact norm_add_le_of_le (le_opNorm _ _) (le_opNorm _ _) -@[deprecated (since := "2024-02-02")] alias op_norm_add_le := opNorm_add_le - theorem opNorm_zero : ‖(0 : ContinuousMultilinearMap 𝕜 E G)‖ = 0 := (opNorm_nonneg _).antisymm' <| opNorm_le_bound le_rfl fun m => by simp -@[deprecated (since := "2024-02-02")] alias op_norm_zero := opNorm_zero - section variable {𝕜' : Type*} [NormedField 𝕜'] [NormedSpace 𝕜' G] [SMulCommClass 𝕜 𝕜' G] @@ -474,8 +444,6 @@ theorem opNorm_smul_le (c : 𝕜') (f : ContinuousMultilinearMap 𝕜 E G) : ‖ rw [smul_apply, norm_smul, mul_assoc] exact mul_le_mul_of_nonneg_left (le_opNorm _ _) (norm_nonneg _) -@[deprecated (since := "2024-02-02")] alias op_norm_smul_le := opNorm_smul_le - variable (𝕜 E G) in /-- Operator seminorm on the space of continuous multilinear maps, as `Seminorm`. @@ -544,8 +512,6 @@ instance normedSpace' : NormedSpace 𝕜' (ContinuousMultilinearMap 𝕜 (fun _ @[deprecated norm_neg (since := "2024-11-24")] theorem opNorm_neg (f : ContinuousMultilinearMap 𝕜 E G) : ‖-f‖ = ‖f‖ := norm_neg f -@[deprecated (since := "2024-02-02")] alias op_norm_neg := norm_neg - /-- The fundamental property of the operator norm of a continuous multilinear map: `‖f m‖` is bounded by `‖f‖` times the product of the `‖m i‖`, `nnnorm` version. -/ theorem le_opNNNorm (f : ContinuousMultilinearMap 𝕜 E G) (m : ∀ i, E i) : @@ -554,39 +520,27 @@ theorem le_opNNNorm (f : ContinuousMultilinearMap 𝕜 E G) (m : ∀ i, E i) : push_cast exact f.le_opNorm m -@[deprecated (since := "2024-02-02")] alias le_op_nnnorm := le_opNNNorm - theorem le_of_opNNNorm_le (f : ContinuousMultilinearMap 𝕜 E G) {C : ℝ≥0} (h : ‖f‖₊ ≤ C) (m : ∀ i, E i) : ‖f m‖₊ ≤ C * ∏ i, ‖m i‖₊ := (f.le_opNNNorm m).trans <| mul_le_mul' h le_rfl -@[deprecated (since := "2024-02-02")] alias le_of_op_nnnorm_le := le_of_opNNNorm_le - theorem opNNNorm_le_iff {f : ContinuousMultilinearMap 𝕜 E G} {C : ℝ≥0} : ‖f‖₊ ≤ C ↔ ∀ m, ‖f m‖₊ ≤ C * ∏ i, ‖m i‖₊ := by simp only [← NNReal.coe_le_coe]; simp [opNorm_le_iff C.coe_nonneg, NNReal.coe_prod] -@[deprecated (since := "2024-02-02")] alias op_nnnorm_le_iff := opNNNorm_le_iff - theorem isLeast_opNNNorm (f : ContinuousMultilinearMap 𝕜 E G) : IsLeast {C : ℝ≥0 | ∀ m, ‖f m‖₊ ≤ C * ∏ i, ‖m i‖₊} ‖f‖₊ := by simpa only [← opNNNorm_le_iff] using isLeast_Ici -@[deprecated (since := "2024-02-02")] alias isLeast_op_nnnorm := isLeast_opNNNorm - theorem opNNNorm_prod (f : ContinuousMultilinearMap 𝕜 E G) (g : ContinuousMultilinearMap 𝕜 E G') : ‖f.prod g‖₊ = max ‖f‖₊ ‖g‖₊ := eq_of_forall_ge_iff fun _ ↦ by simp only [opNNNorm_le_iff, prod_apply, Prod.nnnorm_def', max_le_iff, forall_and] -@[deprecated (since := "2024-02-02")] alias op_nnnorm_prod := opNNNorm_prod - theorem opNorm_prod (f : ContinuousMultilinearMap 𝕜 E G) (g : ContinuousMultilinearMap 𝕜 E G') : ‖f.prod g‖ = max ‖f‖ ‖g‖ := congr_arg NNReal.toReal (opNNNorm_prod f g) -@[deprecated (since := "2024-02-02")] alias op_norm_prod := opNorm_prod - theorem opNNNorm_pi [∀ i', SeminormedAddCommGroup (E' i')] [∀ i', NormedSpace 𝕜 (E' i')] (f : ∀ i', ContinuousMultilinearMap 𝕜 E (E' i')) : ‖pi f‖₊ = ‖f‖₊ := @@ -598,8 +552,6 @@ theorem opNorm_pi {ι' : Type v'} [Fintype ι'] {E' : ι' → Type wE'} ‖pi f‖ = ‖f‖ := congr_arg NNReal.toReal (opNNNorm_pi f) -@[deprecated (since := "2024-02-02")] alias op_norm_pi := opNorm_pi - section @[simp] @@ -1332,8 +1284,6 @@ variable {𝕜 : Type u} {ι : Type v} {E : ι → Type wE} {G : Type wG} {G' : theorem opNorm_zero_iff {f : ContinuousMultilinearMap 𝕜 E G} : ‖f‖ = 0 ↔ f = 0 := by simp [← (opNorm_nonneg f).le_iff_eq, opNorm_le_iff le_rfl, ContinuousMultilinearMap.ext_iff] -@[deprecated (since := "2024-02-02")] alias op_norm_zero_iff := opNorm_zero_iff - /-- Continuous multilinear maps themselves form a normed group with respect to the operator norm. -/ instance normedAddCommGroup : NormedAddCommGroup (ContinuousMultilinearMap 𝕜 E G) := diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean index 34ac1d9ef91a5..bef49e1cf0329 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean @@ -136,14 +136,12 @@ theorem isLeast_opNorm [RingHomIsometric σ₁₂] (f : E →SL[σ₁₂] F) : simp only [setOf_and, setOf_forall] refine isClosed_Ici.inter <| isClosed_iInter fun _ ↦ isClosed_le ?_ ?_ <;> continuity -@[deprecated (since := "2024-02-02")] alias isLeast_op_norm := isLeast_opNorm /-- If one controls the norm of every `A x`, then one controls the norm of `A`. -/ theorem opNorm_le_bound (f : E →SL[σ₁₂] F) {M : ℝ} (hMp : 0 ≤ M) (hM : ∀ x, ‖f x‖ ≤ M * ‖x‖) : ‖f‖ ≤ M := csInf_le bounds_bddBelow ⟨hMp, hM⟩ -@[deprecated (since := "2024-02-02")] alias op_norm_le_bound := opNorm_le_bound /-- If one controls the norm of every `A x`, `‖x‖ ≠ 0`, then one controls the norm of `A`. -/ theorem opNorm_le_bound' (f : E →SL[σ₁₂] F) {M : ℝ} (hMp : 0 ≤ M) @@ -152,13 +150,11 @@ theorem opNorm_le_bound' (f : E →SL[σ₁₂] F) {M : ℝ} (hMp : 0 ≤ M) (ne_or_eq ‖x‖ 0).elim (hM x) fun h => by simp only [h, mul_zero, norm_image_of_norm_zero f f.2 h, le_refl] -@[deprecated (since := "2024-02-02")] alias op_norm_le_bound' := opNorm_le_bound' theorem opNorm_le_of_lipschitz {f : E →SL[σ₁₂] F} {K : ℝ≥0} (hf : LipschitzWith K f) : ‖f‖ ≤ K := f.opNorm_le_bound K.2 fun x => by simpa only [dist_zero_right, f.map_zero] using hf.dist_le_mul x 0 -@[deprecated (since := "2024-02-02")] alias op_norm_le_of_lipschitz := opNorm_le_of_lipschitz theorem opNorm_eq_of_bounds {φ : E →SL[σ₁₂] F} {M : ℝ} (M_nonneg : 0 ≤ M) (h_above : ∀ x, ‖φ x‖ ≤ M * ‖x‖) (h_below : ∀ N ≥ 0, (∀ x, ‖φ x‖ ≤ N * ‖x‖) → M ≤ N) : @@ -167,22 +163,18 @@ theorem opNorm_eq_of_bounds {φ : E →SL[σ₁₂] F} {M : ℝ} (M_nonneg : 0 ((le_csInf_iff ContinuousLinearMap.bounds_bddBelow ⟨M, M_nonneg, h_above⟩).mpr fun N ⟨N_nonneg, hN⟩ => h_below N N_nonneg hN) -@[deprecated (since := "2024-02-02")] alias op_norm_eq_of_bounds := opNorm_eq_of_bounds theorem opNorm_neg (f : E →SL[σ₁₂] F) : ‖-f‖ = ‖f‖ := by simp only [norm_def, neg_apply, norm_neg] -@[deprecated (since := "2024-02-02")] alias op_norm_neg := opNorm_neg theorem opNorm_nonneg (f : E →SL[σ₁₂] F) : 0 ≤ ‖f‖ := Real.sInf_nonneg fun _ ↦ And.left -@[deprecated (since := "2024-02-02")] alias op_norm_nonneg := opNorm_nonneg /-- The norm of the `0` operator is `0`. -/ theorem opNorm_zero : ‖(0 : E →SL[σ₁₂] F)‖ = 0 := le_antisymm (opNorm_le_bound _ le_rfl fun _ ↦ by simp) (opNorm_nonneg _) -@[deprecated (since := "2024-02-02")] alias op_norm_zero := opNorm_zero /-- The norm of the identity is at most `1`. It is in fact `1`, except when the space is trivial where it is `0`. It means that one can not do better than an inequality in general. -/ @@ -197,51 +189,42 @@ variable [RingHomIsometric σ₁₂] [RingHomIsometric σ₂₃] (f g : E →SL[ /-- The fundamental property of the operator norm: `‖f x‖ ≤ ‖f‖ * ‖x‖`. -/ theorem le_opNorm : ‖f x‖ ≤ ‖f‖ * ‖x‖ := (isLeast_opNorm f).1.2 x -@[deprecated (since := "2024-02-02")] alias le_op_norm := le_opNorm theorem dist_le_opNorm (x y : E) : dist (f x) (f y) ≤ ‖f‖ * dist x y := by simp_rw [dist_eq_norm, ← map_sub, f.le_opNorm] -@[deprecated (since := "2024-02-02")] alias dist_le_op_norm := dist_le_opNorm theorem le_of_opNorm_le_of_le {x} {a b : ℝ} (hf : ‖f‖ ≤ a) (hx : ‖x‖ ≤ b) : ‖f x‖ ≤ a * b := (f.le_opNorm x).trans <| by gcongr; exact (opNorm_nonneg f).trans hf -@[deprecated (since := "2024-02-02")] alias le_of_op_norm_le_of_le := le_of_opNorm_le_of_le theorem le_opNorm_of_le {c : ℝ} {x} (h : ‖x‖ ≤ c) : ‖f x‖ ≤ ‖f‖ * c := f.le_of_opNorm_le_of_le le_rfl h -@[deprecated (since := "2024-02-02")] alias le_op_norm_of_le := le_opNorm_of_le theorem le_of_opNorm_le {c : ℝ} (h : ‖f‖ ≤ c) (x : E) : ‖f x‖ ≤ c * ‖x‖ := f.le_of_opNorm_le_of_le h le_rfl -@[deprecated (since := "2024-02-02")] alias le_of_op_norm_le := le_of_opNorm_le theorem opNorm_le_iff {f : E →SL[σ₁₂] F} {M : ℝ} (hMp : 0 ≤ M) : ‖f‖ ≤ M ↔ ∀ x, ‖f x‖ ≤ M * ‖x‖ := ⟨f.le_of_opNorm_le, opNorm_le_bound f hMp⟩ -@[deprecated (since := "2024-02-02")] alias op_norm_le_iff := opNorm_le_iff theorem ratio_le_opNorm : ‖f x‖ / ‖x‖ ≤ ‖f‖ := div_le_of_le_mul₀ (norm_nonneg _) f.opNorm_nonneg (le_opNorm _ _) -@[deprecated (since := "2024-02-02")] alias ratio_le_op_norm := ratio_le_opNorm /-- The image of the unit ball under a continuous linear map is bounded. -/ theorem unit_le_opNorm : ‖x‖ ≤ 1 → ‖f x‖ ≤ ‖f‖ := mul_one ‖f‖ ▸ f.le_opNorm_of_le -@[deprecated (since := "2024-02-02")] alias unit_le_op_norm := unit_le_opNorm theorem opNorm_le_of_shell {f : E →SL[σ₁₂] F} {ε C : ℝ} (ε_pos : 0 < ε) (hC : 0 ≤ C) {c : 𝕜} (hc : 1 < ‖c‖) (hf : ∀ x, ε / ‖c‖ ≤ ‖x‖ → ‖x‖ < ε → ‖f x‖ ≤ C * ‖x‖) : ‖f‖ ≤ C := f.opNorm_le_bound' hC fun _ hx => SemilinearMapClass.bound_of_shell_semi_normed f ε_pos hc hf hx -@[deprecated (since := "2024-02-02")] alias op_norm_le_of_shell := opNorm_le_of_shell theorem opNorm_le_of_ball {f : E →SL[σ₁₂] F} {ε : ℝ} {C : ℝ} (ε_pos : 0 < ε) (hC : 0 ≤ C) (hf : ∀ x ∈ ball (0 : E) ε, ‖f x‖ ≤ C * ‖x‖) : ‖f‖ ≤ C := by @@ -249,14 +232,12 @@ theorem opNorm_le_of_ball {f : E →SL[σ₁₂] F} {ε : ℝ} {C : ℝ} (ε_pos refine opNorm_le_of_shell ε_pos hC hc fun x _ hx => hf x ?_ rwa [ball_zero_eq] -@[deprecated (since := "2024-02-02")] alias op_norm_le_of_ball := opNorm_le_of_ball theorem opNorm_le_of_nhds_zero {f : E →SL[σ₁₂] F} {C : ℝ} (hC : 0 ≤ C) (hf : ∀ᶠ x in 𝓝 (0 : E), ‖f x‖ ≤ C * ‖x‖) : ‖f‖ ≤ C := let ⟨_, ε0, hε⟩ := Metric.eventually_nhds_iff_ball.1 hf opNorm_le_of_ball ε0 hC hε -@[deprecated (since := "2024-02-02")] alias op_norm_le_of_nhds_zero := opNorm_le_of_nhds_zero theorem opNorm_le_of_shell' {f : E →SL[σ₁₂] F} {ε C : ℝ} (ε_pos : 0 < ε) (hC : 0 ≤ C) {c : 𝕜} (hc : ‖c‖ < 1) (hf : ∀ x, ε * ‖c‖ ≤ ‖x‖ → ‖x‖ < ε → ‖f x‖ ≤ C * ‖x‖) : ‖f‖ ≤ C := by @@ -268,7 +249,6 @@ theorem opNorm_le_of_shell' {f : E →SL[σ₁₂] F} {ε C : ℝ} (ε_pos : 0 < refine opNorm_le_of_shell ε_pos hC hc ?_ rwa [norm_inv, div_eq_mul_inv, inv_inv] -@[deprecated (since := "2024-02-02")] alias op_norm_le_of_shell' := opNorm_le_of_shell' /-- For a continuous real linear map `f`, if one controls the norm of every `f x`, `‖x‖ = 1`, then one controls the norm of `f`. -/ @@ -280,14 +260,12 @@ theorem opNorm_le_of_unit_norm [NormedSpace ℝ E] [NormedSpace ℝ F] {f : E rwa [map_smul, norm_smul, norm_inv, norm_norm, ← div_eq_inv_mul, div_le_iff₀] at H₂ exact (norm_nonneg x).lt_of_ne' hx -@[deprecated (since := "2024-02-02")] alias op_norm_le_of_unit_norm := opNorm_le_of_unit_norm /-- The operator norm satisfies the triangle inequality. -/ theorem opNorm_add_le : ‖f + g‖ ≤ ‖f‖ + ‖g‖ := (f + g).opNorm_le_bound (add_nonneg f.opNorm_nonneg g.opNorm_nonneg) fun x => (norm_add_le_of_le (f.le_opNorm x) (g.le_opNorm x)).trans_eq (add_mul _ _ _).symm -@[deprecated (since := "2024-02-02")] alias op_norm_add_le := opNorm_add_le /-- If there is an element with norm different from `0`, then the norm of the identity equals `1`. (Since we are working with seminorms supposing that the space is non-trivial is not enough.) -/ @@ -303,7 +281,6 @@ theorem opNorm_smul_le {𝕜' : Type*} [NormedField 𝕜'] [NormedSpace 𝕜' F] rw [smul_apply, norm_smul, mul_assoc] exact mul_le_mul_of_nonneg_left (le_opNorm _ _) (norm_nonneg _) -@[deprecated (since := "2024-02-02")] alias op_norm_smul_le := opNorm_smul_le /-- Operator seminorm on the space of continuous (semi)linear maps, as `Seminorm`. @@ -352,7 +329,6 @@ theorem opNorm_comp_le (f : E →SL[σ₁₂] F) : ‖h.comp f‖ ≤ ‖h‖ * rw [mul_assoc] exact h.le_opNorm_of_le (f.le_opNorm x)⟩ -@[deprecated (since := "2024-02-02")] alias op_norm_comp_le := opNorm_comp_le /-- Continuous linear maps form a seminormed ring with respect to the operator norm. -/ instance toSemiNormedRing : SeminormedRing (E →L[𝕜] E) := @@ -378,7 +354,6 @@ theorem opNorm_subsingleton [Subsingleton E] : ‖f‖ = 0 := by intro x simp [Subsingleton.elim x 0] -@[deprecated (since := "2024-02-02")] alias op_norm_subsingleton := opNorm_subsingleton end OpNorm diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean index 9cb3ac62feea8..8193941231cfa 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean @@ -55,7 +55,6 @@ theorem opNorm_ext [RingHomIsometric σ₁₃] (f : E →SL[σ₁₂] F) (g : E rw [← h z] exact h₂ z -@[deprecated (since := "2024-02-02")] alias op_norm_ext := opNorm_ext variable [RingHomIsometric σ₂₃] @@ -63,20 +62,17 @@ theorem opNorm_le_bound₂ (f : E →SL[σ₁₃] F →SL[σ₂₃] G) {C : ℝ} (hC : ∀ x y, ‖f x y‖ ≤ C * ‖x‖ * ‖y‖) : ‖f‖ ≤ C := f.opNorm_le_bound h0 fun x => (f x).opNorm_le_bound (mul_nonneg h0 (norm_nonneg _)) <| hC x -@[deprecated (since := "2024-02-02")] alias op_norm_le_bound₂ := opNorm_le_bound₂ theorem le_opNorm₂ [RingHomIsometric σ₁₃] (f : E →SL[σ₁₃] F →SL[σ₂₃] G) (x : E) (y : F) : ‖f x y‖ ≤ ‖f‖ * ‖x‖ * ‖y‖ := (f x).le_of_opNorm_le (f.le_opNorm x) y -@[deprecated (since := "2024-02-02")] alias le_op_norm₂ := le_opNorm₂ theorem le_of_opNorm₂_le_of_le [RingHomIsometric σ₁₃] (f : E →SL[σ₁₃] F →SL[σ₂₃] G) {x : E} {y : F} {a b c : ℝ} (hf : ‖f‖ ≤ a) (hx : ‖x‖ ≤ b) (hy : ‖y‖ ≤ c) : ‖f x y‖ ≤ a * b * c := (f x).le_of_opNorm_le_of_le (f.le_of_opNorm_le_of_le hf hx) hy -@[deprecated (since := "2024-02-02")] alias le_of_op_norm₂_le_of_le := le_of_opNorm₂_le_of_le end OpNorm @@ -172,7 +168,6 @@ theorem flip_flip (f : E →SL[σ₁₃] F →SL[σ₂₃] G) : f.flip.flip = f theorem opNorm_flip (f : E →SL[σ₁₃] F →SL[σ₂₃] G) : ‖f.flip‖ = ‖f‖ := le_antisymm (by simpa only [flip_flip] using le_norm_flip f.flip) (le_norm_flip f) -@[deprecated (since := "2024-02-02")] alias op_norm_flip := opNorm_flip @[simp] theorem flip_add (f g : E →SL[σ₁₃] F →SL[σ₂₃] G) : (f + g).flip = f.flip + g.flip := diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean index 4043b6833c43d..39bbe337bb7d7 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean @@ -247,7 +247,6 @@ theorem opNorm_extend_le : _ ≤ ‖f‖ * (N * ‖e x‖) := mul_le_mul_of_nonneg_left (h_e x) (norm_nonneg _) _ ≤ N * ‖f‖ * ‖e x‖ := by rw [mul_comm ↑N ‖f‖, mul_assoc] -@[deprecated (since := "2024-02-02")] alias op_norm_extend_le := opNorm_extend_le end diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean index c45a659de2c23..147350c036a57 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean @@ -45,12 +45,10 @@ theorem mul_apply' (x y : 𝕜') : mul 𝕜 𝕜' x y = x * y := theorem opNorm_mul_apply_le (x : 𝕜') : ‖mul 𝕜 𝕜' x‖ ≤ ‖x‖ := opNorm_le_bound _ (norm_nonneg x) (norm_mul_le x) -@[deprecated (since := "2024-02-02")] alias op_norm_mul_apply_le := opNorm_mul_apply_le theorem opNorm_mul_le : ‖mul 𝕜 𝕜'‖ ≤ 1 := LinearMap.mkContinuous₂_norm_le _ zero_le_one _ -@[deprecated (since := "2024-02-02")] alias op_norm_mul_le := opNorm_mul_le /-- Multiplication on the left in a non-unital normed algebra `𝕜'` as a non-unital algebra homomorphism into the algebra of *continuous* linear maps. This is the left regular representation @@ -87,22 +85,14 @@ theorem opNorm_mulLeftRight_apply_apply_le (x y : 𝕜') : ‖mulLeftRight 𝕜 (opNorm_le_bound _ (norm_nonneg _) fun _ => (norm_mul_le _ _).trans_eq (mul_comm _ _)) (norm_nonneg _) (norm_nonneg _) -@[deprecated (since := "2024-02-02")] -alias op_norm_mulLeftRight_apply_apply_le := - opNorm_mulLeftRight_apply_apply_le - theorem opNorm_mulLeftRight_apply_le (x : 𝕜') : ‖mulLeftRight 𝕜 𝕜' x‖ ≤ ‖x‖ := opNorm_le_bound _ (norm_nonneg x) (opNorm_mulLeftRight_apply_apply_le 𝕜 𝕜' x) -@[deprecated (since := "2024-02-02")] -alias op_norm_mulLeftRight_apply_le := opNorm_mulLeftRight_apply_le - set_option maxSynthPendingDepth 2 in theorem opNorm_mulLeftRight_le : ‖mulLeftRight 𝕜 𝕜'‖ ≤ 1 := opNorm_le_bound _ zero_le_one fun x => (one_mul ‖x‖).symm ▸ opNorm_mulLeftRight_apply_le 𝕜 𝕜' x -@[deprecated (since := "2024-02-02")] alias op_norm_mulLeftRight_le := opNorm_mulLeftRight_le /-- This is a mixin class for non-unital normed algebras which states that the left-regular representation of the algebra on itself is isometric. Every unital normed algebra with `‖1‖ = 1` is @@ -133,13 +123,11 @@ lemma isometry_mul : Isometry (mul 𝕜 𝕜') := lemma opNorm_mul_apply (x : 𝕜') : ‖mul 𝕜 𝕜' x‖ = ‖x‖ := (AddMonoidHomClass.isometry_iff_norm (mul 𝕜 𝕜')).mp (isometry_mul 𝕜 𝕜') x -@[deprecated (since := "2024-02-02")] alias op_norm_mul_apply := opNorm_mul_apply @[simp] lemma opNNNorm_mul_apply (x : 𝕜') : ‖mul 𝕜 𝕜' x‖₊ = ‖x‖₊ := Subtype.ext <| opNorm_mul_apply 𝕜 𝕜' x -@[deprecated (since := "2024-02-02")] alias op_nnnorm_mul_apply := opNNNorm_mul_apply /-- Multiplication in a normed algebra as a linear isometry to the space of continuous linear maps. -/ @@ -210,7 +198,6 @@ variable {𝕜} theorem opNorm_lsmul_apply_le (x : 𝕜') : ‖(lsmul 𝕜 𝕜' x : E →L[𝕜] E)‖ ≤ ‖x‖ := ContinuousLinearMap.opNorm_le_bound _ (norm_nonneg x) fun y => norm_smul_le x y -@[deprecated (since := "2024-02-02")] alias op_norm_lsmul_apply_le := opNorm_lsmul_apply_le /-- The norm of `lsmul` is at most 1 in any semi-normed group. -/ theorem opNorm_lsmul_le : ‖(lsmul 𝕜 𝕜' : 𝕜' →L[𝕜] E →L[𝕜] E)‖ ≤ 1 := by @@ -218,7 +205,6 @@ theorem opNorm_lsmul_le : ‖(lsmul 𝕜 𝕜' : 𝕜' →L[𝕜] E →L[𝕜] E simp_rw [one_mul] exact opNorm_lsmul_apply_le _ -@[deprecated (since := "2024-02-02")] alias op_norm_lsmul_le := opNorm_lsmul_le end SMulLinear @@ -242,13 +228,11 @@ variable [SMulCommClass 𝕜 𝕜' 𝕜'] [RegularNormedAlgebra 𝕜 𝕜'] [Non theorem opNorm_mul : ‖mul 𝕜 𝕜'‖ = 1 := (mulₗᵢ 𝕜 𝕜').norm_toContinuousLinearMap -@[deprecated (since := "2024-02-02")] alias op_norm_mul := opNorm_mul @[simp] theorem opNNNorm_mul : ‖mul 𝕜 𝕜'‖₊ = 1 := Subtype.ext <| opNorm_mul 𝕜 𝕜' -@[deprecated (since := "2024-02-02")] alias op_nnnorm_mul := opNNNorm_mul end @@ -267,7 +251,6 @@ theorem opNorm_lsmul [NormedField 𝕜'] [NormedAlgebra 𝕜 𝕜'] [NormedSpace refine le_of_mul_le_mul_right ?_ (norm_pos_iff.mpr hy) simp_rw [one_mul, this] -@[deprecated (since := "2024-02-02")] alias op_norm_lsmul := opNorm_lsmul end ContinuousLinearMap diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean index 51f3b1705bfc9..018b01d78582b 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean @@ -56,14 +56,12 @@ theorem nnnorm_def (f : E →SL[σ₁₂] F) : ‖f‖₊ = sInf { c | ∀ x, theorem opNNNorm_le_bound (f : E →SL[σ₁₂] F) (M : ℝ≥0) (hM : ∀ x, ‖f x‖₊ ≤ M * ‖x‖₊) : ‖f‖₊ ≤ M := opNorm_le_bound f (zero_le M) hM -@[deprecated (since := "2024-02-02")] alias op_nnnorm_le_bound := opNNNorm_le_bound /-- If one controls the norm of every `A x`, `‖x‖₊ ≠ 0`, then one controls the norm of `A`. -/ theorem opNNNorm_le_bound' (f : E →SL[σ₁₂] F) (M : ℝ≥0) (hM : ∀ x, ‖x‖₊ ≠ 0 → ‖f x‖₊ ≤ M * ‖x‖₊) : ‖f‖₊ ≤ M := opNorm_le_bound' f (zero_le M) fun x hx => hM x <| by rwa [← NNReal.coe_ne_zero] -@[deprecated (since := "2024-02-02")] alias op_nnnorm_le_bound' := opNNNorm_le_bound' /-- For a continuous real linear map `f`, if one controls the norm of every `f x`, `‖x‖₊ = 1`, then one controls the norm of `f`. -/ @@ -71,45 +69,35 @@ theorem opNNNorm_le_of_unit_nnnorm [NormedSpace ℝ E] [NormedSpace ℝ F] {f : (hf : ∀ x, ‖x‖₊ = 1 → ‖f x‖₊ ≤ C) : ‖f‖₊ ≤ C := opNorm_le_of_unit_norm C.coe_nonneg fun x hx => hf x <| by rwa [← NNReal.coe_eq_one] -@[deprecated (since := "2024-02-02")] -alias op_nnnorm_le_of_unit_nnnorm := opNNNorm_le_of_unit_nnnorm - theorem opNNNorm_le_of_lipschitz {f : E →SL[σ₁₂] F} {K : ℝ≥0} (hf : LipschitzWith K f) : ‖f‖₊ ≤ K := opNorm_le_of_lipschitz hf -@[deprecated (since := "2024-02-02")] alias op_nnnorm_le_of_lipschitz := opNNNorm_le_of_lipschitz theorem opNNNorm_eq_of_bounds {φ : E →SL[σ₁₂] F} (M : ℝ≥0) (h_above : ∀ x, ‖φ x‖₊ ≤ M * ‖x‖₊) (h_below : ∀ N, (∀ x, ‖φ x‖₊ ≤ N * ‖x‖₊) → M ≤ N) : ‖φ‖₊ = M := Subtype.ext <| opNorm_eq_of_bounds (zero_le M) h_above <| Subtype.forall'.mpr h_below -@[deprecated (since := "2024-02-02")] alias op_nnnorm_eq_of_bounds := opNNNorm_eq_of_bounds theorem opNNNorm_le_iff {f : E →SL[σ₁₂] F} {C : ℝ≥0} : ‖f‖₊ ≤ C ↔ ∀ x, ‖f x‖₊ ≤ C * ‖x‖₊ := opNorm_le_iff C.2 -@[deprecated (since := "2024-02-02")] alias op_nnnorm_le_iff := opNNNorm_le_iff theorem isLeast_opNNNorm : IsLeast {C : ℝ≥0 | ∀ x, ‖f x‖₊ ≤ C * ‖x‖₊} ‖f‖₊ := by simpa only [← opNNNorm_le_iff] using isLeast_Ici -@[deprecated (since := "2024-02-02")] alias isLeast_op_nnnorm := isLeast_opNNNorm theorem opNNNorm_comp_le [RingHomIsometric σ₁₃] (f : E →SL[σ₁₂] F) : ‖h.comp f‖₊ ≤ ‖h‖₊ * ‖f‖₊ := opNorm_comp_le h f -@[deprecated (since := "2024-02-02")] alias op_nnnorm_comp_le := opNNNorm_comp_le theorem le_opNNNorm : ‖f x‖₊ ≤ ‖f‖₊ * ‖x‖₊ := f.le_opNorm x -@[deprecated (since := "2024-02-02")] alias le_op_nnnorm := le_opNNNorm theorem nndist_le_opNNNorm (x y : E) : nndist (f x) (f y) ≤ ‖f‖₊ * nndist x y := dist_le_opNorm f x y -@[deprecated (since := "2024-02-02")] alias nndist_le_op_nnnorm := nndist_le_opNNNorm /-- continuous linear maps are Lipschitz continuous. -/ theorem lipschitz : LipschitzWith ‖f‖₊ f := @@ -131,17 +119,11 @@ theorem exists_mul_lt_apply_of_lt_opNNNorm (f : E →SL[σ₁₂] F) {r : ℝ≥ not_mem_of_lt_csInf (nnnorm_def f ▸ hr : r < sInf { c : ℝ≥0 | ∀ x, ‖f x‖₊ ≤ c * ‖x‖₊ }) (OrderBot.bddBelow _) -@[deprecated (since := "2024-02-02")] -alias exists_mul_lt_apply_of_lt_op_nnnorm := exists_mul_lt_apply_of_lt_opNNNorm - theorem exists_mul_lt_of_lt_opNorm (f : E →SL[σ₁₂] F) {r : ℝ} (hr₀ : 0 ≤ r) (hr : r < ‖f‖) : ∃ x, r * ‖x‖ < ‖f x‖ := by lift r to ℝ≥0 using hr₀ exact f.exists_mul_lt_apply_of_lt_opNNNorm hr -@[deprecated (since := "2024-02-02")] -alias exists_mul_lt_of_lt_op_norm := exists_mul_lt_of_lt_opNorm - theorem exists_lt_apply_of_lt_opNNNorm {𝕜 𝕜₂ E F : Type*} [NormedAddCommGroup E] [SeminormedAddCommGroup F] [DenselyNormedField 𝕜] [NontriviallyNormedField 𝕜₂] {σ₁₂ : 𝕜 →+* 𝕜₂} [NormedSpace 𝕜 E] [NormedSpace 𝕜₂ F] [RingHomIsometric σ₁₂] (f : E →SL[σ₁₂] F) {r : ℝ≥0} @@ -158,9 +140,6 @@ theorem exists_lt_apply_of_lt_opNNNorm {𝕜 𝕜₂ E F : Type*} [NormedAddComm have : ‖σ₁₂ k‖₊ = ‖k‖₊ := Subtype.ext RingHomIsometric.is_iso rwa [map_smulₛₗ f, nnnorm_smul, ← div_lt_iff₀ hfy.bot_lt, div_eq_mul_inv, this] -@[deprecated (since := "2024-02-02")] -alias exists_lt_apply_of_lt_op_nnnorm := exists_lt_apply_of_lt_opNNNorm - theorem exists_lt_apply_of_lt_opNorm {𝕜 𝕜₂ E F : Type*} [NormedAddCommGroup E] [SeminormedAddCommGroup F] [DenselyNormedField 𝕜] [NontriviallyNormedField 𝕜₂] {σ₁₂ : 𝕜 →+* 𝕜₂} [NormedSpace 𝕜 E] [NormedSpace 𝕜₂ F] [RingHomIsometric σ₁₂] (f : E →SL[σ₁₂] F) {r : ℝ} @@ -170,9 +149,6 @@ theorem exists_lt_apply_of_lt_opNorm {𝕜 𝕜₂ E F : Type*} [NormedAddCommGr · lift r to ℝ≥0 using not_lt.1 hr₀ exact f.exists_lt_apply_of_lt_opNNNorm hr -@[deprecated (since := "2024-02-02")] -alias exists_lt_apply_of_lt_op_norm := exists_lt_apply_of_lt_opNorm - theorem sSup_unit_ball_eq_nnnorm {𝕜 𝕜₂ E F : Type*} [NormedAddCommGroup E] [SeminormedAddCommGroup F] [DenselyNormedField 𝕜] [NontriviallyNormedField 𝕜₂] {σ₁₂ : 𝕜 →+* 𝕜₂} [NormedSpace 𝕜 E] [NormedSpace 𝕜₂ F] [RingHomIsometric σ₁₂] (f : E →SL[σ₁₂] F) : diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean index b08ba685f3320..f9b408f94f338 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean @@ -102,7 +102,6 @@ theorem opNorm_zero_iff [RingHomIsometric σ₁₂] : ‖f‖ = 0 ↔ f = 0 := rintro rfl exact opNorm_zero) -@[deprecated (since := "2024-02-02")] alias op_norm_zero_iff := opNorm_zero_iff /-- If a normed space is non-trivial, then the norm of the identity equals `1`. -/ @[simp] @@ -208,9 +207,6 @@ theorem opNorm_comp_linearIsometryEquiv (f : F →SL[σ₂₃] G) (g : F' ≃ₛ haveI := g.symm.surjective.nontrivial simp [g.symm.toLinearIsometry.norm_toContinuousLinearMap] -@[deprecated (since := "2024-02-02")] -alias op_norm_comp_linearIsometryEquiv := opNorm_comp_linearIsometryEquiv - @[simp] theorem norm_smulRightL (c : E →L[𝕜] 𝕜) [Nontrivial Fₗ] : ‖smulRightL 𝕜 E Fₗ c‖ = ‖c‖ := ContinuousLinearMap.homothety_norm _ c.norm_smulRight_apply diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean index 51e531175bf03..8d1a93937e77e 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean @@ -52,13 +52,11 @@ theorem opNorm_prod (f : E →L[𝕜] F) (g : E →L[𝕜] G) : ‖f.prod g‖ = (opNorm_le_bound _ (norm_nonneg _) fun x => (le_max_right _ _).trans ((f.prod g).le_opNorm x)) -@[deprecated (since := "2024-02-02")] alias op_norm_prod := opNorm_prod @[simp] theorem opNNNorm_prod (f : E →L[𝕜] F) (g : E →L[𝕜] G) : ‖f.prod g‖₊ = ‖(f, g)‖₊ := Subtype.ext <| opNorm_prod f g -@[deprecated (since := "2024-02-02")] alias op_nnnorm_prod := opNNNorm_prod /-- `ContinuousLinearMap.prod` as a `LinearIsometryEquiv`. -/ def prodₗᵢ (R : Type*) [Semiring R] [Module R F] [Module R G] [ContinuousConstSMul R F] diff --git a/Mathlib/Analysis/NormedSpace/RCLike.lean b/Mathlib/Analysis/NormedSpace/RCLike.lean index f578908f625cc..a918890d4c64b 100644 --- a/Mathlib/Analysis/NormedSpace/RCLike.lean +++ b/Mathlib/Analysis/NormedSpace/RCLike.lean @@ -85,10 +85,6 @@ theorem ContinuousLinearMap.opNorm_bound_of_ball_bound {r : ℝ} (r_pos : 0 < r) apply LinearMap.bound_of_ball_bound' r_pos exact fun z hz => h z hz -@[deprecated (since := "2024-02-02")] -alias ContinuousLinearMap.op_norm_bound_of_ball_bound := - ContinuousLinearMap.opNorm_bound_of_ball_bound - variable (𝕜) include 𝕜 in theorem NormedSpace.sphere_nonempty_rclike [Nontrivial E] {r : ℝ} (hr : 0 ≤ r) : diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean index 89db8290e3687..ee0f874953f99 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean @@ -210,9 +210,6 @@ theorem _root_.fourierIntegral_gaussian (hb : 0 < b.re) (t : ℂ) : rw [integral_cexp_quadratic (show (-b).re < 0 by rwa [neg_re, neg_lt_zero]), neg_neg, zero_sub, mul_neg, div_neg, neg_neg, mul_pow, I_sq, neg_one_mul, mul_comm] -@[deprecated (since := "2024-02-21")] -alias _root_.fourier_transform_gaussian := fourierIntegral_gaussian - theorem _root_.fourierIntegral_gaussian_pi' (hb : 0 < b.re) (c : ℂ) : (𝓕 fun x : ℝ => cexp (-π * b * x ^ 2 + 2 * π * c * x)) = fun t : ℝ => 1 / b ^ (1 / 2 : ℂ) * cexp (-π / b * (t + I * c) ^ 2) := by @@ -233,17 +230,11 @@ theorem _root_.fourierIntegral_gaussian_pi' (hb : 0 < b.re) (c : ℂ) : simp only [I_sq] ring -@[deprecated (since := "2024-02-21")] -alias _root_.fourier_transform_gaussian_pi' := _root_.fourierIntegral_gaussian_pi' - theorem _root_.fourierIntegral_gaussian_pi (hb : 0 < b.re) : (𝓕 fun (x : ℝ) ↦ cexp (-π * b * x ^ 2)) = fun t : ℝ ↦ 1 / b ^ (1 / 2 : ℂ) * cexp (-π / b * t ^ 2) := by simpa only [mul_zero, zero_mul, add_zero] using fourierIntegral_gaussian_pi' hb 0 -@[deprecated (since := "2024-02-21")] -alias root_.fourier_transform_gaussian_pi := _root_.fourierIntegral_gaussian_pi - section InnerProductSpace variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℝ V] [FiniteDimensional ℝ V] diff --git a/Mathlib/CategoryTheory/Filtered/Basic.lean b/Mathlib/CategoryTheory/Filtered/Basic.lean index 584411d3326a4..e356e98a41ca6 100644 --- a/Mathlib/CategoryTheory/Filtered/Basic.lean +++ b/Mathlib/CategoryTheory/Filtered/Basic.lean @@ -829,9 +829,6 @@ theorem of_isInitial {X : C} (h : IsInitial X) : IsCofiltered C := instance (priority := 100) of_hasInitial [HasInitial C] : IsCofiltered C := of_isInitial _ initialIsInitial -@[deprecated (since := "2024-03-11")] -alias _root_.CategoryTheory.cofiltered_of_hasFiniteLimits := of_hasFiniteLimits - /-- For every universe `w`, `C` is filtered if and only if every finite diagram in `C` with shape in `w` admits a cocone. -/ theorem iff_cone_nonempty : IsCofiltered C ↔ diff --git a/Mathlib/CategoryTheory/IsConnected.lean b/Mathlib/CategoryTheory/IsConnected.lean index 9f27285ea78dc..ebe6c3c30a930 100644 --- a/Mathlib/CategoryTheory/IsConnected.lean +++ b/Mathlib/CategoryTheory/IsConnected.lean @@ -373,7 +373,6 @@ theorem isPreconnected_zigzag [IsPreconnected J] (j₁ j₂ : J) : Zigzag j₁ j equiv_relation _ zigzag_equivalence (fun f => Relation.ReflTransGen.single (Or.inl (Nonempty.intro f))) _ _ -@[deprecated (since := "2024-02-19")] alias isConnected_zigzag := isPreconnected_zigzag theorem zigzag_isPreconnected (h : ∀ j₁ j₂ : J, Zigzag j₁ j₂) : IsPreconnected J := by apply IsPreconnected.of_constant_of_preserves_morphisms @@ -454,7 +453,4 @@ theorem nonempty_hom_of_preconnected_groupoid {G} [Groupoid G] [IsPreconnected G attribute [instance] nonempty_hom_of_preconnected_groupoid -@[deprecated (since := "2024-02-19")] -alias nonempty_hom_of_connected_groupoid := nonempty_hom_of_preconnected_groupoid - end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/FullSubcategory.lean b/Mathlib/CategoryTheory/Limits/FullSubcategory.lean index 18abbde52961c..11c03c8e182d8 100644 --- a/Mathlib/CategoryTheory/Limits/FullSubcategory.lean +++ b/Mathlib/CategoryTheory/Limits/FullSubcategory.lean @@ -113,8 +113,6 @@ theorem hasLimit_of_closedUnderLimits (h : ClosedUnderLimitsOfShape J P) have : CreatesLimit F (fullSubcategoryInclusion P) := createsLimitFullSubcategoryInclusionOfClosed h F hasLimit_of_created F (fullSubcategoryInclusion P) -@[deprecated (since := "2024-03-23")] -alias hasLimit_of_closed_under_limits := hasLimit_of_closedUnderLimits theorem hasLimitsOfShape_of_closedUnderLimits (h : ClosedUnderLimitsOfShape J P) [HasLimitsOfShape J C] : HasLimitsOfShape J (FullSubcategory P) := @@ -136,14 +134,10 @@ theorem hasColimit_of_closedUnderColimits (h : ClosedUnderColimitsOfShape J P) have : CreatesColimit F (fullSubcategoryInclusion P) := createsColimitFullSubcategoryInclusionOfClosed h F hasColimit_of_created F (fullSubcategoryInclusion P) -@[deprecated (since := "2024-03-23")] -alias hasColimit_of_closed_under_colimits := hasColimit_of_closedUnderColimits theorem hasColimitsOfShape_of_closedUnderColimits (h : ClosedUnderColimitsOfShape J P) [HasColimitsOfShape J C] : HasColimitsOfShape J (FullSubcategory P) := { has_colimit := fun F => hasColimit_of_closedUnderColimits h F } -@[deprecated (since := "2024-03-23")] -alias hasColimitsOfShape_of_closed_under_colimits := hasColimitsOfShape_of_closedUnderColimits end diff --git a/Mathlib/CategoryTheory/Limits/Opposites.lean b/Mathlib/CategoryTheory/Limits/Opposites.lean index 76a2af3431f75..7c040f35246ea 100644 --- a/Mathlib/CategoryTheory/Limits/Opposites.lean +++ b/Mathlib/CategoryTheory/Limits/Opposites.lean @@ -32,10 +32,6 @@ namespace CategoryTheory.Limits variable {C : Type u₁} [Category.{v₁} C] variable {J : Type u₂} [Category.{v₂} J] -@[deprecated (since := "2024-03-26")] alias isLimitCoconeOp := IsColimit.op -@[deprecated (since := "2024-03-26")] alias isColimitConeOp := IsLimit.op -@[deprecated (since := "2024-03-26")] alias isLimitCoconeUnop := IsColimit.unop -@[deprecated (since := "2024-03-26")] alias isColimitConeUnop := IsLimit.unop /-- Turn a colimit for `F : J ⥤ Cᵒᵖ` into a limit for `F.leftOp : Jᵒᵖ ⥤ C`. -/ @[simps] diff --git a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean index 9d98315f91068..7f5fe6d81b937 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean @@ -265,10 +265,6 @@ theorem chromaticNumber_le_iff_colorable {n : ℕ} : G.chromaticNumber ≤ n ↔ rw [Set.mem_setOf_eq] at this exact this.mono h -@[deprecated Colorable.chromaticNumber_le (since := "2024-03-21")] -theorem chromaticNumber_le_card [Fintype α] (C : G.Coloring α) : - G.chromaticNumber ≤ Fintype.card α := C.colorable.chromaticNumber_le - theorem colorable_chromaticNumber {m : ℕ} (hc : G.Colorable m) : G.Colorable (ENat.toNat G.chromaticNumber) := by classical diff --git a/Mathlib/Data/Complex/Abs.lean b/Mathlib/Data/Complex/Abs.lean index 4735e0966f985..7531c38a54ff3 100644 --- a/Mathlib/Data/Complex/Abs.lean +++ b/Mathlib/Data/Complex/Abs.lean @@ -198,9 +198,6 @@ theorem abs_im_div_abs_le_one (z : ℂ) : |z.im / Complex.abs z| ≤ 1 := @[simp, norm_cast] lemma abs_intCast (n : ℤ) : abs n = |↑n| := by rw [← ofReal_intCast, abs_ofReal] -@[deprecated "No deprecation message was provided." (since := "2024-02-14")] -lemma int_cast_abs (n : ℤ) : |↑n| = Complex.abs n := (abs_intCast _).symm - theorem normSq_eq_abs (x : ℂ) : normSq x = (Complex.abs x) ^ 2 := by simp [abs, sq, abs_def, Real.mul_self_sqrt (normSq_nonneg _)] diff --git a/Mathlib/Data/Countable/Small.lean b/Mathlib/Data/Countable/Small.lean index 72387f0c4a096..b48f61815b730 100644 --- a/Mathlib/Data/Countable/Small.lean +++ b/Mathlib/Data/Countable/Small.lean @@ -18,9 +18,3 @@ universe w v instance (priority := 100) Countable.toSmall (α : Type v) [Countable α] : Small.{w} α := let ⟨_, hf⟩ := exists_injective_nat α small_of_injective hf - -@[deprecated (since := "2024-03-20"), nolint defLemma] -alias small_of_countable := Countable.toSmall - -@[deprecated (since := "2024-03-20"), nolint defLemma] -alias small_of_fintype := Countable.toSmall diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 6056e283f70cc..148cf433376f6 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -79,8 +79,6 @@ def finZeroElim {α : Fin 0 → Sort*} (x : Fin 0) : α x := namespace Fin -@[deprecated (since := "2024-02-15")] alias eq_of_veq := eq_of_val_eq -@[deprecated (since := "2024-02-15")] alias veq_of_eq := val_eq_of_eq @[deprecated (since := "2024-08-13")] alias ne_of_vne := ne_of_val_ne @[deprecated (since := "2024-08-13")] alias vne_of_ne := val_ne_of_ne @@ -151,10 +149,6 @@ section coe theorem val_eq_val (a b : Fin n) : (a : ℕ) = b ↔ a = b := Fin.ext_iff.symm -@[deprecated Fin.ext_iff (since := "2024-02-20")] -theorem eq_iff_veq (a b : Fin n) : a = b ↔ a.1 = b.1 := - Fin.ext_iff - theorem ne_iff_vne (a b : Fin n) : a ≠ b ↔ a.1 ≠ b.1 := Fin.ext_iff.not diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index 648f621a5abac..3d203a0107b42 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -500,8 +500,6 @@ lemma card_union_eq_card_add_card : #(s ∪ t) = #s + #t ↔ Disjoint s t := by @[simp] alias ⟨_, card_union_of_disjoint⟩ := card_union_eq_card_add_card -@[deprecated (since := "2024-02-09")] alias card_union_eq := card_union_of_disjoint -@[deprecated (since := "2024-02-09")] alias card_disjoint_union := card_union_of_disjoint lemma cast_card_inter [AddGroupWithOne R] : (#(s ∩ t) : R) = #s + #t - #(s ∪ t) := by @@ -676,9 +674,6 @@ theorem one_lt_card_iff_nontrivial : 1 < #s ↔ s.Nontrivial := by rw [← not_iff_not, not_lt, Finset.Nontrivial, ← Set.nontrivial_coe_sort, not_nontrivial_iff_subsingleton, card_le_one_iff_subsingleton_coe, coe_sort_coe] -@[deprecated (since := "2024-02-05")] -alias one_lt_card_iff_nontrivial_coe := one_lt_card_iff_nontrivial - theorem exists_ne_of_one_lt_card (hs : 1 < #s) (a : α) : ∃ b, b ∈ s ∧ b ≠ a := by obtain ⟨x, hx, y, hy, hxy⟩ := Finset.one_lt_card.mp hs by_cases ha : y = a diff --git a/Mathlib/Data/Finset/Empty.lean b/Mathlib/Data/Finset/Empty.lean index 5916c7d3dc88a..60a6034dfb73c 100644 --- a/Mathlib/Data/Finset/Empty.lean +++ b/Mathlib/Data/Finset/Empty.lean @@ -67,7 +67,6 @@ alias ⟨_, Nonempty.coe_sort⟩ := nonempty_coe_sort theorem Nonempty.exists_mem {s : Finset α} (h : s.Nonempty) : ∃ x : α, x ∈ s := h -@[deprecated (since := "2024-03-23")] alias Nonempty.bex := Nonempty.exists_mem theorem Nonempty.mono {s t : Finset α} (hst : s ⊆ t) (hs : s.Nonempty) : t.Nonempty := Set.Nonempty.mono hst hs diff --git a/Mathlib/Data/Finset/Lattice/Basic.lean b/Mathlib/Data/Finset/Lattice/Basic.lean index 14fc97ad84371..79aeaeff8285a 100644 --- a/Mathlib/Data/Finset/Lattice/Basic.lean +++ b/Mathlib/Data/Finset/Lattice/Basic.lean @@ -295,10 +295,6 @@ theorem union_inter_distrib_left (s t u : Finset α) : s ∪ t ∩ u = (s ∪ t) theorem inter_union_distrib_right (s t u : Finset α) : s ∩ t ∪ u = (s ∪ u) ∩ (t ∪ u) := sup_inf_right _ _ _ -@[deprecated (since := "2024-03-22")] alias inter_distrib_left := inter_union_distrib_left -@[deprecated (since := "2024-03-22")] alias inter_distrib_right := union_inter_distrib_right -@[deprecated (since := "2024-03-22")] alias union_distrib_left := union_inter_distrib_left -@[deprecated (since := "2024-03-22")] alias union_distrib_right := inter_union_distrib_right theorem union_union_distrib_left (s t u : Finset α) : s ∪ (t ∪ u) = s ∪ t ∪ (s ∪ u) := sup_sup_distrib_left _ _ _ diff --git a/Mathlib/Data/Int/Defs.lean b/Mathlib/Data/Int/Defs.lean index 3addc51ed7381..732c14aa0df2c 100644 --- a/Mathlib/Data/Int/Defs.lean +++ b/Mathlib/Data/Int/Defs.lean @@ -91,9 +91,6 @@ protected theorem ofNat_add_one_out (n : ℕ) : ↑n + (1 : ℤ) = ↑(succ n) : @[simp] lemma ofNat_eq_natCast (n : ℕ) : Int.ofNat n = n := rfl -@[deprecated ofNat_eq_natCast (since := "2024-03-24")] -protected lemma natCast_eq_ofNat (n : ℕ) : ↑n = Int.ofNat n := rfl - @[norm_cast] lemma natCast_inj {m n : ℕ} : (m : ℤ) = (n : ℤ) ↔ m = n := ofNat_inj @[simp, norm_cast] lemma natAbs_cast (n : ℕ) : natAbs ↑n = n := rfl diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 4c99fc84425e5..311d98d7e2fcd 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -73,7 +73,6 @@ theorem _root_.Decidable.List.eq_or_ne_mem_of_mem [DecidableEq α] lemma mem_pair {a b c : α} : a ∈ [b, c] ↔ a = b ∨ a = c := by rw [mem_cons, mem_singleton] -@[deprecated (since := "2024-03-23")] alias mem_split := append_of_mem -- The simpNF linter says that the LHS can be simplified via `List.mem_map`. -- However this is a higher priority lemma. @@ -872,11 +871,6 @@ theorem flatMap_pure_eq_map (f : α → β) (l : List α) : l.flatMap (pure ∘ @[deprecated (since := "2024-10-16")] alias bind_pure_eq_map := flatMap_pure_eq_map -set_option linter.deprecated false in -@[deprecated flatMap_pure_eq_map (since := "2024-03-24")] -theorem bind_ret_eq_map (f : α → β) (l : List α) : l.bind (List.ret ∘ f) = map f l := - bind_pure_eq_map f l - theorem flatMap_congr {l : List α} {f g : α → List β} (h : ∀ x ∈ l, f x = g x) : List.flatMap l f = List.flatMap l g := (congr_arg List.flatten <| map_congr_left h : _) diff --git a/Mathlib/Data/List/Defs.lean b/Mathlib/Data/List/Defs.lean index b340e9b270a42..9718d8cc7eb2c 100644 --- a/Mathlib/Data/List/Defs.lean +++ b/Mathlib/Data/List/Defs.lean @@ -504,8 +504,6 @@ alias ⟨eq_or_mem_of_mem_cons, _⟩ := mem_cons theorem not_exists_mem_nil (p : α → Prop) : ¬∃ x ∈ @nil α, p x := fun ⟨_, hx, _⟩ => List.not_mem_nil _ hx -@[deprecated (since := "2024-03-23")] alias not_bex_nil := not_exists_mem_nil -@[deprecated (since := "2024-03-23")] alias bex_cons := exists_mem_cons @[deprecated (since := "2024-08-10")] alias length_le_of_sublist := Sublist.length_le diff --git a/Mathlib/Data/List/Infix.lean b/Mathlib/Data/List/Infix.lean index ddab47721a8c6..942f206a4afa8 100644 --- a/Mathlib/Data/List/Infix.lean +++ b/Mathlib/Data/List/Infix.lean @@ -106,7 +106,6 @@ instance decidableInfix [DecidableEq α] : ∀ l₁ l₂ : List α, Decidable (l theorem cons_prefix_iff : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by simp -@[deprecated (since := "2024-03-26")] alias IsPrefix.filter_map := IsPrefix.filterMap protected theorem IsPrefix.reduceOption {l₁ l₂ : List (Option α)} (h : l₁ <+: l₂) : l₁.reduceOption <+: l₂.reduceOption := diff --git a/Mathlib/Data/List/Pairwise.lean b/Mathlib/Data/List/Pairwise.lean index be4f87bb84be6..be0725e086b7b 100644 --- a/Mathlib/Data/List/Pairwise.lean +++ b/Mathlib/Data/List/Pairwise.lean @@ -49,15 +49,6 @@ theorem Pairwise.forall (hR : Symmetric R) (hl : l.Pairwise R) : theorem Pairwise.set_pairwise (hl : Pairwise R l) (hr : Symmetric R) : { x | x ∈ l }.Pairwise R := hl.forall hr --- Porting note: Duplicate of `pairwise_map` but with `f` explicit. -@[deprecated "No deprecation message was provided." (since := "2024-02-25")] -theorem pairwise_map' (f : β → α) : - ∀ {l : List β}, Pairwise R (map f l) ↔ Pairwise (R on f) l - | [] => by simp only [map, Pairwise.nil] - | b :: l => by - simp only [map, pairwise_cons, mem_map, forall_exists_index, and_imp, - forall_apply_eq_imp_iff₂, pairwise_map] - theorem pairwise_of_reflexive_of_forall_ne {l : List α} {r : α → α → Prop} (hr : Reflexive r) (h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by rw [pairwise_iff_forall_sublist] diff --git a/Mathlib/Data/List/Sublists.lean b/Mathlib/Data/List/Sublists.lean index aca81a62467f5..cf9436cf68118 100644 --- a/Mathlib/Data/List/Sublists.lean +++ b/Mathlib/Data/List/Sublists.lean @@ -184,11 +184,6 @@ theorem map_pure_sublist_sublists (l : List α) : map pure l <+ sublists l := by singleton_sublist.2 <| mem_map.2 ⟨[], mem_sublists.2 (nil_sublist _), by rfl⟩).trans ((append_sublist_append_right _).2 ih) -set_option linter.deprecated false in -@[deprecated map_pure_sublist_sublists (since := "2024-03-24")] -theorem map_ret_sublist_sublists (l : List α) : map List.ret l <+ sublists l := - map_pure_sublist_sublists l - /-! ### sublistsLen -/ /-- Auxiliary function to construct the list of all sublists of a given length. Given an diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index c773102bcabad..fb7ef70dca4ff 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -143,7 +143,6 @@ protected theorem coe_injective : Injective ((↑) : ℝ≥0 → ℝ) := Subtype @[simp, norm_cast] lemma coe_inj {r₁ r₂ : ℝ≥0} : (r₁ : ℝ) = r₂ ↔ r₁ = r₂ := NNReal.coe_injective.eq_iff -@[deprecated (since := "2024-02-03")] protected alias coe_eq := coe_inj @[simp, norm_cast] lemma coe_zero : ((0 : ℝ≥0) : ℝ) = 0 := rfl diff --git a/Mathlib/Data/Nat/Cast/Order/Basic.lean b/Mathlib/Data/Nat/Cast/Order/Basic.lean index eec03f2914acb..7d749878466c4 100644 --- a/Mathlib/Data/Nat/Cast/Order/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Order/Basic.lean @@ -33,9 +33,6 @@ theorem mono_cast : Monotone (Nat.cast : ℕ → α) := monotone_nat_of_le_succ fun n ↦ by rw [Nat.cast_succ]; exact le_add_of_nonneg_right zero_le_one -@[deprecated mono_cast (since := "2024-02-10")] -theorem cast_le_cast {a b : ℕ} (h : a ≤ b) : (a : α) ≤ b := mono_cast h - @[gcongr] theorem _root_.GCongr.natCast_le_natCast {a b : ℕ} (h : a ≤ b) : (a : α) ≤ b := mono_cast h diff --git a/Mathlib/Data/Nat/Digits.lean b/Mathlib/Data/Nat/Digits.lean index 5adc574882628..bde0bf0b51b40 100644 --- a/Mathlib/Data/Nat/Digits.lean +++ b/Mathlib/Data/Nat/Digits.lean @@ -740,7 +740,6 @@ lemma toDigitsCore_lens_eq_aux (b f : Nat) : specialize ih (n / b) (Nat.digitChar (n % b) :: l1) (Nat.digitChar (n % b) :: l2) simp only [List.length, congrArg (fun l ↦ l + 1) hlen] at ih exact ih trivial -@[deprecated (since := "2024-02-19")] alias to_digits_core_lens_eq_aux:= toDigitsCore_lens_eq_aux lemma toDigitsCore_lens_eq (b f : Nat) : ∀ (n : Nat) (c : Char) (tl : List Char), (Nat.toDigitsCore b f n (c :: tl)).length = (Nat.toDigitsCore b f n tl).length + 1 := by @@ -757,7 +756,6 @@ lemma toDigitsCore_lens_eq (b f : Nat) : ∀ (n : Nat) (c : Char) (tl : List Cha have lens_eq : (x :: (c :: tl)).length = (c :: x :: tl).length := by simp apply toDigitsCore_lens_eq_aux exact lens_eq -@[deprecated (since := "2024-02-19")] alias to_digits_core_lens_eq:= toDigitsCore_lens_eq lemma nat_repr_len_aux (n b e : Nat) (h_b_pos : 0 < b) : n < b ^ e.succ → n / b < b ^ e := by simp only [Nat.pow_succ] @@ -788,7 +786,6 @@ lemma toDigitsCore_length (b : Nat) (h : 2 <= b) (f n e : Nat) have _ : b ^ 1 = b := by simp only [Nat.pow_succ, pow_zero, Nat.one_mul] have _ : n < b := ‹b ^ 1 = b› ▸ hlt simp [(@Nat.div_eq_of_lt n b ‹n < b› : n / b = 0)] -@[deprecated (since := "2024-02-19")] alias to_digits_core_length := toDigitsCore_length /-- The core implementation of `Nat.repr` returns a String with length less than or equal to the number of digits in the decimal number (represented by `e`). For example, the decimal string diff --git a/Mathlib/Data/Rat/Cast/Defs.lean b/Mathlib/Data/Rat/Cast/Defs.lean index a5fc916543c00..5636ef6193774 100644 --- a/Mathlib/Data/Rat/Cast/Defs.lean +++ b/Mathlib/Data/Rat/Cast/Defs.lean @@ -114,8 +114,6 @@ theorem cast_intCast (n : ℤ) : ((n : ℚ) : α) = n := theorem cast_natCast (n : ℕ) : ((n : ℚ) : α) = n := by rw [← Int.cast_natCast, cast_intCast, Int.cast_natCast] -@[deprecated (since := "2024-03-21")] alias cast_coe_int := cast_intCast -@[deprecated (since := "2024-03-21")] alias cast_coe_nat := cast_natCast @[simp, norm_cast] lemma cast_ofNat (n : ℕ) [n.AtLeastTwo] : ((ofNat(n) : ℚ) : α) = (ofNat(n) : α) := by diff --git a/Mathlib/Data/Rat/Defs.lean b/Mathlib/Data/Rat/Defs.lean index cb77cd4efc0c3..f848e1c3e14a3 100644 --- a/Mathlib/Data/Rat/Defs.lean +++ b/Mathlib/Data/Rat/Defs.lean @@ -167,24 +167,14 @@ theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → attribute [simp] divInt_add_divInt -@[deprecated divInt_add_divInt (since := "2024-03-18")] -theorem add_def'' {a b c d : ℤ} (b0 : b ≠ 0) (d0 : d ≠ 0) : - a /. b + c /. d = (a * d + c * b) /. (b * d) := divInt_add_divInt _ _ b0 d0 - attribute [simp] neg_divInt lemma neg_def (q : ℚ) : -q = -q.num /. q.den := by rw [← neg_divInt, num_divInt_den] @[simp] lemma divInt_neg (n d : ℤ) : n /. -d = -n /. d := divInt_neg' .. -@[deprecated (since := "2024-03-18")] alias divInt_neg_den := divInt_neg - attribute [simp] divInt_sub_divInt -@[deprecated divInt_sub_divInt (since := "2024-03-18")] -lemma sub_def'' {a b c d : ℤ} (b0 : b ≠ 0) (d0 : d ≠ 0) : - a /. b - c /. d = (a * d - c * b) /. (b * d) := divInt_sub_divInt _ _ b0 d0 - @[simp] lemma divInt_mul_divInt' (n₁ d₁ n₂ d₂ : ℤ) : (n₁ /. d₁) * (n₂ /. d₂) = (n₁ * n₂) /. (d₁ * d₂) := by obtain rfl | h₁ := eq_or_ne d₁ 0 @@ -270,17 +260,11 @@ protected theorem add_assoc : a + b + c = a + (b + c) := protected lemma neg_add_cancel : -a + a = 0 := by simp [add_def, normalize_eq_mkRat, Int.neg_mul, Int.add_comm, ← Int.sub_eq_add_neg] -@[deprecated zero_divInt (since := "2024-03-18")] -lemma divInt_zero_one : 0 /. 1 = 0 := zero_divInt _ - @[simp] lemma divInt_one (n : ℤ) : n /. 1 = n := by simp [divInt, mkRat, normalize] @[simp] lemma mkRat_one (n : ℤ) : mkRat n 1 = n := by simp [mkRat_eq_divInt] lemma divInt_one_one : 1 /. 1 = 1 := by rw [divInt_one, intCast_one] -@[deprecated divInt_one (since := "2024-03-18")] -lemma divInt_neg_one_one : -1 /. 1 = -1 := by rw [divInt_one, intCast_neg, intCast_one] - protected theorem mul_assoc : a * b * c = a * (b * c) := numDenCasesOn' a fun n₁ d₁ h₁ => numDenCasesOn' b fun n₂ d₂ h₂ => diff --git a/Mathlib/Data/Real/Sqrt.lean b/Mathlib/Data/Real/Sqrt.lean index 5b1193b70b404..14d02f76715e2 100644 --- a/Mathlib/Data/Real/Sqrt.lean +++ b/Mathlib/Data/Real/Sqrt.lean @@ -62,11 +62,6 @@ lemma sqrt_le_iff_le_sq : sqrt x ≤ y ↔ x ≤ y ^ 2 := sqrt.to_galoisConnecti lemma le_sqrt_iff_sq_le : x ≤ sqrt y ↔ x ^ 2 ≤ y := (sqrt.symm.to_galoisConnection _ _).symm -@[deprecated (since := "2024-02-14")] alias sqrt_le_sqrt_iff := sqrt_le_sqrt -@[deprecated (since := "2024-02-14")] alias sqrt_lt_sqrt_iff := sqrt_lt_sqrt -@[deprecated (since := "2024-02-14")] alias sqrt_le_iff := sqrt_le_iff_le_sq -@[deprecated (since := "2024-02-14")] alias le_sqrt_iff := le_sqrt_iff_sq_le -@[deprecated (since := "2024-02-14")] alias sqrt_eq_iff_sq_eq := sqrt_eq_iff_eq_sq @[simp] lemma sqrt_eq_zero : sqrt x = 0 ↔ x = 0 := by simp [sqrt_eq_iff_eq_sq] diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 64f61f2b25e36..0a7d5df2df1b0 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -514,7 +514,6 @@ theorem subset_eq_empty {s t : Set α} (h : t ⊆ s) (e : s = ∅) : t = ∅ := theorem forall_mem_empty {p : α → Prop} : (∀ x ∈ (∅ : Set α), p x) ↔ True := iff_true_intro fun _ => False.elim -@[deprecated (since := "2024-03-23")] alias ball_empty_iff := forall_mem_empty instance (α : Type u) : IsEmpty.{u + 1} (↥(∅ : Set α)) := ⟨fun x => x.2⟩ @@ -843,10 +842,6 @@ theorem union_inter_distrib_left (s t u : Set α) : s ∪ t ∩ u = (s ∪ t) theorem inter_union_distrib_right (s t u : Set α) : s ∩ t ∪ u = (s ∪ u) ∩ (t ∪ u) := sup_inf_right _ _ _ -@[deprecated (since := "2024-03-22")] alias inter_distrib_left := inter_union_distrib_left -@[deprecated (since := "2024-03-22")] alias inter_distrib_right := union_inter_distrib_right -@[deprecated (since := "2024-03-22")] alias union_distrib_left := union_inter_distrib_left -@[deprecated (since := "2024-03-22")] alias union_distrib_right := inter_union_distrib_right theorem union_union_distrib_left (s t u : Set α) : s ∪ (t ∪ u) = s ∪ t ∪ (s ∪ u) := sup_sup_distrib_left _ _ _ @@ -979,12 +974,10 @@ theorem forall_insert_of_forall {P : α → Prop} {a : α} {s : Set α} (H : ∀ theorem exists_mem_insert {P : α → Prop} {a : α} {s : Set α} : (∃ x ∈ insert a s, P x) ↔ (P a ∨ ∃ x ∈ s, P x) := by simp [mem_insert_iff, or_and_right, exists_and_left, exists_or] -@[deprecated (since := "2024-03-23")] alias bex_insert_iff := exists_mem_insert theorem forall_mem_insert {P : α → Prop} {a : α} {s : Set α} : (∀ x ∈ insert a s, P x) ↔ P a ∧ ∀ x ∈ s, P x := forall₂_or_left.trans <| and_congr_left' forall_eq -@[deprecated (since := "2024-03-23")] alias ball_insert_iff := forall_mem_insert /-- Inserting an element to a set is equivalent to the option type. -/ def subtypeInsertEquivOption diff --git a/Mathlib/Data/Set/Image.lean b/Mathlib/Data/Set/Image.lean index a98696d44ae14..a36c4d6171444 100644 --- a/Mathlib/Data/Set/Image.lean +++ b/Mathlib/Data/Set/Image.lean @@ -186,11 +186,6 @@ variable {f : α → β} {s t : Set α} -- Porting note: `Set.image` is already defined in `Data.Set.Defs` -@[deprecated mem_image (since := "2024-03-23")] -theorem mem_image_iff_bex {f : α → β} {s : Set α} {y : β} : - y ∈ f '' s ↔ ∃ (x : _) (_ : x ∈ s), f x = y := - bex_def.symm - theorem image_eta (f : α → β) : f '' s = (fun x => f x) '' s := rfl @@ -208,18 +203,6 @@ theorem forall_mem_image {f : α → β} {s : Set α} {p : β → Prop} : theorem exists_mem_image {f : α → β} {s : Set α} {p : β → Prop} : (∃ y ∈ f '' s, p y) ↔ ∃ x ∈ s, p (f x) := by simp -@[deprecated (since := "2024-02-21")] alias ball_image_iff := forall_mem_image -@[deprecated (since := "2024-02-21")] alias bex_image_iff := exists_mem_image -@[deprecated (since := "2024-02-21")] alias ⟨_, ball_image_of_ball⟩ := forall_mem_image - -@[deprecated forall_mem_image (since := "2024-02-21")] -theorem mem_image_elim {f : α → β} {s : Set α} {C : β → Prop} (h : ∀ x : α, x ∈ s → C (f x)) : - ∀ {y : β}, y ∈ f '' s → C y := forall_mem_image.2 h _ - -@[deprecated forall_mem_image (since := "2024-02-21")] -theorem mem_image_elim_on {f : α → β} {s : Set α} {C : β → Prop} {y : β} (h_y : y ∈ f '' s) - (h : ∀ x : α, x ∈ s → C (f x)) : C y := forall_mem_image.2 h _ h_y - -- Porting note: used to be `safe` @[congr] theorem image_congr {f g : α → β} {s : Set α} (h : ∀ a ∈ s, f a = g a) : f '' s = g '' s := by @@ -574,7 +557,6 @@ variable {f : ι → α} {s t : Set α} theorem forall_mem_range {p : α → Prop} : (∀ a ∈ range f, p a) ↔ ∀ i, p (f i) := by simp -@[deprecated (since := "2024-02-21")] alias forall_range_iff := forall_mem_range theorem forall_subtype_range_iff {p : range f → Prop} : (∀ a : range f, p a) ↔ ∀ i, p ⟨f i, mem_range_self _⟩ := @@ -584,9 +566,6 @@ theorem forall_subtype_range_iff {p : range f → Prop} : theorem exists_range_iff {p : α → Prop} : (∃ a ∈ range f, p a) ↔ ∃ i, p (f i) := by simp -@[deprecated (since := "2024-03-10")] -alias exists_range_iff' := exists_range_iff - theorem exists_subtype_range_iff {p : range f → Prop} : (∃ a : range f, p a) ↔ ∃ i, p ⟨f i, mem_range_self _⟩ := ⟨fun ⟨⟨a, i, hi⟩, ha⟩ => by diff --git a/Mathlib/Data/ZMod/Quotient.lean b/Mathlib/Data/ZMod/Quotient.lean index bcbc87a1d2aa0..1f9876b6be3b6 100644 --- a/Mathlib/Data/ZMod/Quotient.lean +++ b/Mathlib/Data/ZMod/Quotient.lean @@ -142,9 +142,6 @@ theorem orbitZPowersEquiv_symm_apply (k : ZMod (minimalPeriod (a • ·) b)) : (⟨a, mem_zpowers a⟩ : zpowers a) ^ (cast k : ℤ) • ⟨b, mem_orbit_self b⟩ := rfl -@[deprecated (since := "2024-02-21")] -alias _root_.AddAction.orbit_zmultiples_equiv_symm_apply := orbitZMultiplesEquiv_symm_apply - theorem orbitZPowersEquiv_symm_apply' (k : ℤ) : (orbitZPowersEquiv a b).symm k = (⟨a, mem_zpowers a⟩ : zpowers a) ^ k • ⟨b, mem_orbit_self b⟩ := by diff --git a/Mathlib/Deprecated/Cardinal/PartENat.lean b/Mathlib/Deprecated/Cardinal/PartENat.lean index e2c263a8cfb2e..47e21caf7cb31 100644 --- a/Mathlib/Deprecated/Cardinal/PartENat.lean +++ b/Mathlib/Deprecated/Cardinal/PartENat.lean @@ -48,9 +48,6 @@ theorem toPartENat_eq_top {c : Cardinal} : theorem toPartENat_apply_of_aleph0_le {c : Cardinal} (h : ℵ₀ ≤ c) : toPartENat c = ⊤ := congr_arg PartENat.ofENat (toENat_eq_top.2 h) -@[deprecated (since := "2024-02-15")] -alias toPartENat_cast := toPartENat_natCast - @[simp] theorem mk_toPartENat_of_infinite [h : Infinite α] : toPartENat #α = ⊤ := toPartENat_apply_of_aleph0_le (infinite_iff.1 h) @@ -62,7 +59,6 @@ theorem aleph0_toPartENat : toPartENat ℵ₀ = ⊤ := theorem toPartENat_surjective : Surjective toPartENat := fun x => PartENat.casesOn x ⟨ℵ₀, toPartENat_apply_of_aleph0_le le_rfl⟩ fun n => ⟨n, toPartENat_natCast n⟩ -@[deprecated (since := "2024-02-15")] alias toPartENat_eq_top_iff_le_aleph0 := toPartENat_eq_top theorem toPartENat_strictMonoOn : StrictMonoOn toPartENat (Set.Iic ℵ₀) := PartENat.withTopOrderIso.symm.strictMono.comp_strictMonoOn toENat_strictMonoOn diff --git a/Mathlib/Deprecated/Submonoid.lean b/Mathlib/Deprecated/Submonoid.lean index 2e9618d300fb9..104e7376fd117 100644 --- a/Mathlib/Deprecated/Submonoid.lean +++ b/Mathlib/Deprecated/Submonoid.lean @@ -184,7 +184,6 @@ theorem IsSubmonoid.pow_mem {a : M} (hs : IsSubmonoid s) (h : a ∈ s) : ∀ {n the `AddSubmonoid`."] theorem IsSubmonoid.powers_subset {a : M} (hs : IsSubmonoid s) (h : a ∈ s) : powers a ⊆ s := fun _ ⟨_, hx⟩ => hx ▸ hs.pow_mem h -@[deprecated (since := "2024-02-21")] alias IsSubmonoid.power_subset := IsSubmonoid.powers_subset end powers diff --git a/Mathlib/FieldTheory/PrimitiveElement.lean b/Mathlib/FieldTheory/PrimitiveElement.lean index 6b12f4601768f..b8174c3c41d64 100644 --- a/Mathlib/FieldTheory/PrimitiveElement.lean +++ b/Mathlib/FieldTheory/PrimitiveElement.lean @@ -286,9 +286,6 @@ theorem FiniteDimensional.of_finite_intermediateField rw [htop] at hfin exact topEquiv.toLinearEquiv.finiteDimensional -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_finite_intermediateField := FiniteDimensional.of_finite_intermediateField - theorem exists_primitive_element_of_finite_intermediateField [Finite (IntermediateField F E)] (K : IntermediateField F E) : ∃ α : E, F⟮α⟯ = K := by haveI := FiniteDimensional.of_finite_intermediateField F E @@ -307,9 +304,6 @@ theorem FiniteDimensional.of_exists_primitive_element [Algebra.IsAlgebraic F E] rw [hprim] at hfin exact topEquiv.toLinearEquiv.finiteDimensional -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_exists_primitive_element := FiniteDimensional.of_exists_primitive_element - -- A finite simple extension has only finitely many intermediate fields theorem finite_intermediateField_of_exists_primitive_element [Algebra.IsAlgebraic F E] (h : ∃ α : E, F⟮α⟯ = ⊤) : Finite (IntermediateField F E) := by diff --git a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean index 782d2803dcdb5..1531fd8dcb8b4 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean @@ -136,9 +136,6 @@ nonrec theorem angle_le_pi (p1 p2 p3 : P) : ∠ p1 p2 p3 ≤ π := /-- The angle ∠ABA at a point is `0`, unless `A = B`. -/ theorem angle_self_of_ne (h : p ≠ p₀) : ∠ p p₀ p = 0 := angle_self <| vsub_ne_zero.2 h -@[deprecated (since := "2024-02-14")] alias angle_eq_left := angle_self_left -@[deprecated (since := "2024-02-14")] alias angle_eq_right := angle_self_right -@[deprecated (since := "2024-02-14")] alias angle_eq_of_ne := angle_self_of_ne /-- If the angle ∠ABC at a point is π, the angle ∠BAC is 0. -/ theorem angle_eq_zero_of_angle_eq_pi_left {p1 p2 p3 : P} (h : ∠ p1 p2 p3 = π) : ∠ p2 p1 p3 = 0 := by diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean index d3b381f0c0511..4bf23adb82cdd 100644 --- a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean +++ b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean @@ -303,7 +303,6 @@ alias closedEmbedding := isClosedEmbedding theorem isClosed_range : IsClosed (range I) := I.isClosedEmbedding.isClosed_range -@[deprecated (since := "2024-03-17")] alias closed_range := isClosed_range theorem range_eq_closure_interior : range I = closure (interior (range I)) := Subset.antisymm I.range_subset_closure_interior I.isClosed_range.closure_interior_subset diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index a5f1e2aead8f6..514fd7841f060 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -263,9 +263,6 @@ protected lemma IsOfFinOrder.mem_powers_iff_mem_range_orderOf [DecidableEq G] protected lemma IsOfFinOrder.powers_eq_image_range_orderOf [DecidableEq G] (hx : IsOfFinOrder x) : (Submonoid.powers x : Set G) = (Finset.range (orderOf x)).image (x ^ ·) := Set.ext fun _ ↦ hx.mem_powers_iff_mem_range_orderOf -@[deprecated (since := "2024-02-21")] -alias IsOfFinAddOrder.powers_eq_image_range_orderOf := - IsOfFinAddOrder.multiples_eq_image_range_addOrderOf @[to_additive] theorem pow_eq_one_iff_modEq : x ^ n = 1 ↔ n ≡ 0 [MOD orderOf x] := by @@ -1089,19 +1086,14 @@ variable [Monoid α] [Monoid β] {x : α × β} {a : α} {b : β} @[to_additive] protected theorem Prod.orderOf (x : α × β) : orderOf x = (orderOf x.1).lcm (orderOf x.2) := minimalPeriod_prod_map _ _ _ -@[deprecated (since := "2024-02-21")] alias Prod.add_orderOf := Prod.addOrderOf @[to_additive] theorem orderOf_fst_dvd_orderOf : orderOf x.1 ∣ orderOf x := minimalPeriod_fst_dvd -@[deprecated (since := "2024-02-21")] -alias add_orderOf_fst_dvd_add_orderOf := addOrderOf_fst_dvd_addOrderOf @[to_additive] theorem orderOf_snd_dvd_orderOf : orderOf x.2 ∣ orderOf x := minimalPeriod_snd_dvd -@[deprecated (since := "2024-02-21")] alias -add_orderOf_snd_dvd_add_orderOf := addOrderOf_snd_dvd_addOrderOf @[to_additive] theorem IsOfFinOrder.fst {x : α × β} (hx : IsOfFinOrder x) : IsOfFinOrder x.1 := diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index 5ea4adad723cf..b469bc7d71d9f 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -105,8 +105,6 @@ theorem MonoidHom.map_cyclic [h : IsCyclic G] (σ : G →* G) : refine ⟨m, fun g => ?_⟩ obtain ⟨n, rfl⟩ := hG g rw [MonoidHom.map_zpow, ← hm, ← zpow_mul, ← zpow_mul'] -@[deprecated (since := "2024-02-21")] alias -MonoidAddHom.map_add_cyclic := AddMonoidHom.map_addCyclic @[to_additive] lemma isCyclic_iff_exists_orderOf_eq_natCard [Finite α] : @@ -132,9 +130,6 @@ theorem isCyclic_of_orderOf_eq_card [Finite α] (x : α) (hx : orderOf x = Nat.c IsCyclic α := isCyclic_iff_exists_orderOf_eq_natCard.mpr ⟨x, hx⟩ -@[deprecated (since := "2024-02-21")] -alias isAddCyclic_of_orderOf_eq_card := isAddCyclic_of_addOrderOf_eq_card - @[to_additive] theorem Subgroup.eq_bot_or_eq_top_of_prime_card (H : Subgroup G) [hp : Fact (Nat.card G).Prime] : H = ⊥ ∨ H = ⊤ := by @@ -324,8 +319,6 @@ theorem IsCyclic.card_pow_eq_one_le [DecidableEq α] [Fintype α] [IsCyclic α] rw [Nat.mul_div_cancel_left _ (gcd_pos_of_pos_left _ hn0), gcd_mul_left_left, hm, Nat.mul_div_cancel _ hm0] exact le_of_dvd hn0 (Nat.gcd_dvd_left _ _) -@[deprecated (since := "2024-02-21")] -alias IsAddCyclic.card_pow_eq_one_le := IsAddCyclic.card_nsmul_eq_zero_le end Classical @@ -478,9 +471,6 @@ theorem isCyclic_of_card_pow_eq_one_le : IsCyclic α := let ⟨x, hx⟩ := this isCyclic_of_orderOf_eq_card x (Finset.mem_filter.1 hx).2 -@[deprecated (since := "2024-02-21")] -alias isAddCyclic_of_card_pow_eq_one_le := isAddCyclic_of_card_nsmul_eq_zero_le - end Totient @[to_additive] @@ -488,9 +478,6 @@ lemma IsCyclic.card_orderOf_eq_totient [IsCyclic α] [Fintype α] {d : ℕ} (hd #{a : α | orderOf a = d} = totient d := by classical apply card_orderOf_eq_totient_aux₂ (fun n => IsCyclic.card_pow_eq_one_le) hd -@[deprecated (since := "2024-02-21")] -alias IsAddCyclic.card_orderOf_eq_totient := IsAddCyclic.card_addOrderOf_eq_totient - /-- A finite group of prime order is simple. -/ @[to_additive "A finite group of prime order is simple."] theorem isSimpleGroup_of_prime_card {p : ℕ} [hp : Fact p.Prime] @@ -532,9 +519,6 @@ theorem commutative_of_cyclic_center_quotient [IsCyclic G'] (f : G →* G') (hf _ = y ^ m * y ^ n * y ^ (-m) * (y ^ (-n) * b * a) := by rw [mem_center_iff.1 hb] _ = b * a := by group -@[deprecated (since := "2024-02-21")] -alias commutative_of_add_cyclic_center_quotient := commutative_of_addCyclic_center_quotient - /-- A group is commutative if the quotient by the center is cyclic. -/ @[to_additive "A group is commutative if the quotient by the center is cyclic."] diff --git a/Mathlib/LinearAlgebra/FiniteDimensional.lean b/Mathlib/LinearAlgebra/FiniteDimensional.lean index 3795257b53d17..1a9987e8e47be 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional.lean @@ -227,10 +227,6 @@ theorem LinearIndependent.span_eq_top_of_card_eq_finrank {ι : Type*} [Nonempty have : FiniteDimensional K V := .of_finrank_pos <| card_eq ▸ Fintype.card_pos lin_ind.span_eq_top_of_card_eq_finrank' card_eq -@[deprecated (since := "2024-02-14")] -alias span_eq_top_of_linearIndependent_of_card_eq_finrank := - LinearIndependent.span_eq_top_of_card_eq_finrank - /-- A linear independent family of `finrank K V` vectors forms a basis. -/ @[simps! repr_apply] noncomputable def basisOfLinearIndependentOfCardEqFinrank {ι : Type*} [Nonempty ι] [Fintype ι] diff --git a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean index 16ac3a373d3e2..66b253e50a6c7 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean @@ -322,21 +322,12 @@ theorem FiniteDimensional.of_rank_eq_nat {n : ℕ} (h : Module.rank K V = n) : FiniteDimensional K V := Module.finite_of_rank_eq_nat h -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_rank_eq_nat := FiniteDimensional.of_rank_eq_nat - theorem FiniteDimensional.of_rank_eq_zero (h : Module.rank K V = 0) : FiniteDimensional K V := Module.finite_of_rank_eq_zero h -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_rank_eq_zero := FiniteDimensional.of_rank_eq_zero - theorem FiniteDimensional.of_rank_eq_one (h : Module.rank K V = 1) : FiniteDimensional K V := Module.finite_of_rank_eq_one h -@[deprecated (since := "2024-02-02")] -alias finiteDimensional_of_rank_eq_one := FiniteDimensional.of_rank_eq_one - variable (K V) instance finiteDimensional_bot : FiniteDimensional K (⊥ : Submodule K V) := diff --git a/Mathlib/Logic/Basic.lean b/Mathlib/Logic/Basic.lean index 409b30a71b81e..56e15a7a87dc5 100644 --- a/Mathlib/Logic/Basic.lean +++ b/Mathlib/Logic/Basic.lean @@ -375,8 +375,6 @@ theorem forall_mem_comm {α β} [Membership α β] {s : β} {p : α → α → P (∀ a (_ : a ∈ s) b (_ : b ∈ s), p a b) ↔ ∀ a b, a ∈ s → b ∈ s → p a b := forall_cond_comm -@[deprecated (since := "2024-03-23")] alias ball_cond_comm := forall_cond_comm -@[deprecated (since := "2024-03-23")] alias ball_mem_comm := forall_mem_comm lemma ne_of_eq_of_ne {α : Sort*} {a b c : α} (h₁ : a = b) (h₂ : b ≠ c) : a ≠ c := h₁.symm ▸ h₂ lemma ne_of_ne_of_eq {α : Sort*} {a b c : α} (h₁ : a ≠ b) (h₂ : b = c) : a ≠ c := h₂ ▸ h₁ @@ -783,21 +781,12 @@ theorem BAll.imp_left (H : ∀ x, p x → q x) (h₁ : ∀ x, q x → r x) (x) ( theorem BEx.imp_left (H : ∀ x, p x → q x) : (∃ (x : _) (_ : p x), r x) → ∃ (x : _) (_ : q x), r x | ⟨x, hp, hr⟩ => ⟨x, H _ hp, hr⟩ -@[deprecated id (since := "2024-03-23")] -theorem ball_of_forall (h : ∀ x, p x) (x) : p x := h x - -@[deprecated forall_imp (since := "2024-03-23")] -theorem forall_of_ball (H : ∀ x, p x) (h : ∀ x, p x → q x) (x) : q x := h x <| H x - theorem exists_mem_of_exists (H : ∀ x, p x) : (∃ x, q x) → ∃ (x : _) (_ : p x), q x | ⟨x, hq⟩ => ⟨x, H x, hq⟩ theorem exists_of_exists_mem : (∃ (x : _) (_ : p x), q x) → ∃ x, q x | ⟨x, _, hq⟩ => ⟨x, hq⟩ -@[deprecated (since := "2024-03-23")] alias bex_of_exists := exists_mem_of_exists -@[deprecated (since := "2024-03-23")] alias exists_of_bex := exists_of_exists_mem -@[deprecated (since := "2024-03-23")] alias bex_imp := exists₂_imp theorem not_exists_mem : (¬∃ x h, P x h) ↔ ∀ x h, ¬P x h := exists₂_imp diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean index adcc5cb835bb0..7af987e92ef57 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean @@ -195,9 +195,6 @@ theorem aemeasurable_coe_nnreal_real_iff {f : α → ℝ≥0} {μ : Measure α} AEMeasurable (fun x => f x : α → ℝ) μ ↔ AEMeasurable f μ := ⟨fun h ↦ by simpa only [Real.toNNReal_coe] using h.real_toNNReal, AEMeasurable.coe_nnreal_real⟩ -@[deprecated (since := "2024-03-02")] -alias aEMeasurable_coe_nnreal_real_iff := aemeasurable_coe_nnreal_real_iff - /-- The set of finite `ℝ≥0∞` numbers is `MeasurableEquiv` to `ℝ≥0`. -/ def MeasurableEquiv.ennrealEquivNNReal : { r : ℝ≥0∞ | r ≠ ∞ } ≃ᵐ ℝ≥0 := ENNReal.neTopHomeomorphNNReal.toMeasurableEquiv @@ -283,17 +280,11 @@ theorem measurable_of_tendsto' {ι : Type*} {f : ι → α → ℝ≥0∞} {g : show Measurable fun y => liminf (fun n => (f (x n) y : ℝ≥0∞)) atTop exact .liminf fun n => hf (x n) -@[deprecated (since := "2024-03-09")] alias -_root_.measurable_of_tendsto_ennreal' := ENNReal.measurable_of_tendsto' - /-- A sequential limit of measurable `ℝ≥0∞` valued functions is measurable. -/ theorem measurable_of_tendsto {f : ℕ → α → ℝ≥0∞} {g : α → ℝ≥0∞} (hf : ∀ i, Measurable (f i)) (lim : Tendsto f atTop (𝓝 g)) : Measurable g := measurable_of_tendsto' atTop hf lim -@[deprecated (since := "2024-03-09")] alias -_root_.measurable_of_tendsto_ennreal := ENNReal.measurable_of_tendsto - /-- A limit (over a general filter) of a.e.-measurable `ℝ≥0∞` valued functions is a.e.-measurable. -/ lemma aemeasurable_of_tendsto' {ι : Type*} {f : ι → α → ℝ≥0∞} {g : α → ℝ≥0∞} @@ -453,17 +444,11 @@ theorem measurable_of_tendsto' {ι} {f : ι → α → ℝ≥0} {g : α → ℝ rw [tendsto_pi_nhds] at lim ⊢ exact fun x => (ENNReal.continuous_coe.tendsto (g x)).comp (lim x) -@[deprecated (since := "2024-03-09")] alias -_root_.measurable_of_tendsto_nnreal' := NNReal.measurable_of_tendsto' - /-- A sequential limit of measurable `ℝ≥0` valued functions is measurable. -/ theorem measurable_of_tendsto {f : ℕ → α → ℝ≥0} {g : α → ℝ≥0} (hf : ∀ i, Measurable (f i)) (lim : Tendsto f atTop (𝓝 g)) : Measurable g := measurable_of_tendsto' atTop hf lim -@[deprecated (since := "2024-03-09")] alias -_root_.measurable_of_tendsto_nnreal := NNReal.measurable_of_tendsto - end NNReal namespace EReal diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 30d728e7e06fc..0005ef1d22c72 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -173,9 +173,6 @@ theorem HasFiniteIntegral.of_finite [Finite α] [IsFiniteMeasure μ] {f : α → let ⟨_⟩ := nonempty_fintype α hasFiniteIntegral_of_bounded <| ae_of_all μ <| norm_le_pi_norm f -@[deprecated (since := "2024-02-05")] -alias hasFiniteIntegral_of_fintype := HasFiniteIntegral.of_finite - theorem HasFiniteIntegral.mono_measure {f : α → β} (h : HasFiniteIntegral f ν) (hμ : μ ≤ ν) : HasFiniteIntegral f μ := lt_of_le_of_lt (lintegral_mono' hμ le_rfl) h @@ -474,7 +471,6 @@ lemma Integrable.of_finite [Finite α] [MeasurableSingletonClass α] [IsFiniteMe @[deprecated Integrable.of_finite (since := "2024-10-05"), nolint deprecatedNoSince] lemma Integrable.of_isEmpty [IsEmpty α] {f : α → β} : Integrable f μ := .of_finite -@[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) (hp_ne_top : p ≠ ∞) : Integrable (fun x : α => ‖f x‖ ^ p.toReal) μ := by diff --git a/Mathlib/MeasureTheory/Function/SimpleFunc.lean b/Mathlib/MeasureTheory/Function/SimpleFunc.lean index 05df7e2bf5776..3d030c368a939 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFunc.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFunc.lean @@ -77,7 +77,6 @@ def ofFinite [Finite α] [MeasurableSingletonClass α] (f : α → β) : α → measurableSet_fiber' x := (toFinite (f ⁻¹' {x})).measurableSet finite_range' := Set.finite_range f -@[deprecated (since := "2024-02-05")] alias ofFintype := ofFinite /-- Simple function defined on the empty type. -/ def ofIsEmpty [IsEmpty α] : α →ₛ β := ofFinite isEmptyElim diff --git a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean index 757c23abb972f..3fcd3f10b57d4 100644 --- a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean +++ b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean @@ -130,14 +130,6 @@ theorem StronglyMeasurable.of_finite [Finite α] {_ : MeasurableSpace α} {f : α → β} : StronglyMeasurable f := ⟨fun _ => SimpleFunc.ofFinite f, fun _ => tendsto_const_nhds⟩ -@[deprecated (since := "2024-02-05")] -alias stronglyMeasurable_of_fintype := StronglyMeasurable.of_finite - -@[deprecated StronglyMeasurable.of_finite (since := "2024-02-06")] -theorem stronglyMeasurable_of_isEmpty [IsEmpty α] {_ : MeasurableSpace α} [TopologicalSpace β] - (f : α → β) : StronglyMeasurable f := - .of_finite - theorem stronglyMeasurable_const {α β} {_ : MeasurableSpace α} [TopologicalSpace β] {b : β} : StronglyMeasurable fun _ : α => b := ⟨fun _ => SimpleFunc.const α b, fun _ => tendsto_const_nhds⟩ @@ -1162,7 +1154,6 @@ theorem mono_measure {ν : Measure α} (hf : AEStronglyMeasurable f μ) (h : ν protected lemma mono_ac (h : ν ≪ μ) (hμ : AEStronglyMeasurable f μ) : AEStronglyMeasurable f ν := let ⟨g, hg, hg'⟩ := hμ; ⟨g, hg, h.ae_eq hg'⟩ -@[deprecated (since := "2024-02-15")] protected alias mono' := AEStronglyMeasurable.mono_ac theorem mono_set {s t} (h : s ⊆ t) (ht : AEStronglyMeasurable f (μ.restrict t)) : AEStronglyMeasurable f (μ.restrict s) := diff --git a/Mathlib/MeasureTheory/Integral/PeakFunction.lean b/Mathlib/MeasureTheory/Integral/PeakFunction.lean index 20b7988c88759..ea9c6d69cf046 100644 --- a/Mathlib/MeasureTheory/Integral/PeakFunction.lean +++ b/Mathlib/MeasureTheory/Integral/PeakFunction.lean @@ -83,10 +83,6 @@ theorem integrableOn_peak_smul_of_integrableOn_of_tendsto convert A.union B simp only [diff_union_inter] -@[deprecated (since := "2024-02-20")] -alias integrableOn_peak_smul_of_integrableOn_of_continuousWithinAt := - integrableOn_peak_smul_of_integrableOn_of_tendsto - /-- If a sequence of peak functions `φᵢ` converges uniformly to zero away from a point `x₀` and its integral on some finite-measure neighborhood of `x₀` converges to `1`, and `g` is integrable and has a limit `a` at `x₀`, then `∫ φᵢ • g` converges to `a`. @@ -176,10 +172,6 @@ theorem tendsto_setIntegral_peak_smul_of_integrableOn_of_tendsto_aux _ ≤ ‖∫ x in s \ u, φ i x • g x ∂μ‖ + ‖∫ x in s ∩ u, φ i x • g x ∂μ‖ := norm_add_le _ _ _ ≤ (δ * ∫ x in s, ‖g x‖ ∂μ) + 2 * δ := add_le_add C B -@[deprecated (since := "2024-02-20")] -alias tendsto_setIntegral_peak_smul_of_integrableOn_of_continuousWithinAt_aux := - tendsto_setIntegral_peak_smul_of_integrableOn_of_tendsto_aux - variable [CompleteSpace E] /-- If a sequence of peak functions `φᵢ` converges uniformly to zero away from a point `x₀` and its @@ -220,10 +212,6 @@ theorem tendsto_setIntegral_peak_smul_of_integrableOn_of_tendsto rw [restrict_restrict ht, inter_eq_left.mpr hts] exact .of_integral_ne_zero (fun h ↦ by simp [h] at h'i) -@[deprecated (since := "2024-02-20")] -alias tendsto_setIntegral_peak_smul_of_integrableOn_of_continuousWithinAt := - tendsto_setIntegral_peak_smul_of_integrableOn_of_tendsto - /-- If a sequence of peak functions `φᵢ` converges uniformly to zero away from a point `x₀` and its integral on some finite-measure neighborhood of `x₀` converges to `1`, and `g` is integrable and has a limit `a` at `x₀`, then `∫ φᵢ • g` converges to `a`. -/ diff --git a/Mathlib/MeasureTheory/Integral/SetToL1.lean b/Mathlib/MeasureTheory/Integral/SetToL1.lean index 7c6e7f8e1b323..9c3a4587da7c6 100644 --- a/Mathlib/MeasureTheory/Integral/SetToL1.lean +++ b/Mathlib/MeasureTheory/Integral/SetToL1.lean @@ -527,9 +527,6 @@ theorem norm_setToSimpleFunc_le_sum_opNorm {m : MeasurableSpace α} (T : Set α _ ≤ ∑ x ∈ f.range, ‖T (f ⁻¹' {x})‖ * ‖x‖ := by refine Finset.sum_le_sum fun b _ => ?_; simp_rw [ContinuousLinearMap.le_opNorm] -@[deprecated (since := "2024-02-02")] -alias norm_setToSimpleFunc_le_sum_op_norm := norm_setToSimpleFunc_le_sum_opNorm - theorem norm_setToSimpleFunc_le_sum_mul_norm (T : Set α → F →L[ℝ] F') {C : ℝ} (hT_norm : ∀ s, MeasurableSet s → ‖T s‖ ≤ C * (μ s).toReal) (f : α →ₛ F) : ‖f.setToSimpleFunc T‖ ≤ C * ∑ x ∈ f.range, (μ (f ⁻¹' {x})).toReal * ‖x‖ := diff --git a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean index e9d2e87202f9e..a4ed925b7ac08 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean @@ -390,12 +390,6 @@ lemma haarScalarFactor_pos_of_isHaarMeasure (μ' μ : Measure G) [IsHaarMeasure [IsHaarMeasure μ'] : 0 < haarScalarFactor μ' μ := pos_iff_ne_zero.2 (fun H ↦ by simpa [H] using haarScalarFactor_eq_mul μ' μ μ') -@[deprecated (since := "2024-02-12")] -alias haarScalarFactor_pos_of_isOpenPosMeasure := haarScalarFactor_pos_of_isHaarMeasure - -@[deprecated (since := "2024-02-12")] -alias addHaarScalarFactor_pos_of_isOpenPosMeasure := addHaarScalarFactor_pos_of_isAddHaarMeasure - /-! ### Uniqueness of measure of sets with compact closure @@ -681,13 +675,6 @@ lemma isHaarMeasure_eq_of_isProbabilityMeasure [LocallyCompactSpace G] (μ' μ : ext s _hs simp [A s, ← Z] -@[deprecated (since := "2024-02-12")] -alias haarScalarFactor_eq_one_of_isProbabilityMeasure := isHaarMeasure_eq_of_isProbabilityMeasure - -@[deprecated (since := "2024-02-12")] -alias addHaarScalarFactor_eq_one_of_isProbabilityMeasure := - isAddHaarMeasure_eq_of_isProbabilityMeasure - /-! ### Uniqueness of measure of open sets @@ -896,8 +883,6 @@ lemma isMulLeftInvariant_eq_smul [LocallyCompactSpace G] [SecondCountableTopolog -- one could use as well `isMulLeftInvariant_eq_smul_of_innerRegular`, as in a -- second countable topological space all Haar measures are regular and inner regular -@[deprecated (since := "2024-02-12")] alias isHaarMeasure_eq_smul := isMulLeftInvariant_eq_smul -@[deprecated (since := "2024-02-12")] alias isAddHaarMeasure_eq_smul := isAddLeftInvariant_eq_smul /-- An invariant σ-finite measure is absolutely continuous with respect to a Haar measure in a second countable group. -/ diff --git a/Mathlib/NumberTheory/LSeries/Dirichlet.lean b/Mathlib/NumberTheory/LSeries/Dirichlet.lean index 32e114a35c3d6..96724285e05ad 100644 --- a/Mathlib/NumberTheory/LSeries/Dirichlet.lean +++ b/Mathlib/NumberTheory/LSeries/Dirichlet.lean @@ -264,9 +264,6 @@ lemma LSeries_zeta_eq : L ↗ζ = L 1 := by theorem LSeriesSummable_zeta_iff {s : ℂ} : LSeriesSummable (ζ ·) s ↔ 1 < s.re := (LSeriesSummable_congr s const_one_eq_zeta).symm.trans <| LSeriesSummable_one_iff -@[deprecated (since := "2024-03-29")] -alias zeta_LSeriesSummable_iff_one_lt_re := LSeriesSummable_zeta_iff - /-- The abscissa of (absolute) convergence of the arithmetic function `ζ` is `1`. -/ lemma abscissaOfAbsConv_zeta : abscissaOfAbsConv ↗ζ = 1 := by rw [abscissaOfAbsConv_congr (g := 1) fun hn ↦ by simp [hn], abscissaOfAbsConv_one] diff --git a/Mathlib/NumberTheory/Transcendental/Liouville/Residual.lean b/Mathlib/NumberTheory/Transcendental/Liouville/Residual.lean index 9e0eff961d50c..fc253159650ba 100644 --- a/Mathlib/NumberTheory/Transcendental/Liouville/Residual.lean +++ b/Mathlib/NumberTheory/Transcendental/Liouville/Residual.lean @@ -34,7 +34,6 @@ theorem IsGδ.setOf_liouville : IsGδ { x | Liouville x } := by refine isOpen_iUnion fun a => isOpen_iUnion fun b => isOpen_iUnion fun _hb => ?_ exact isOpen_ball.inter isClosed_singleton.isOpen_compl -@[deprecated (since := "2024-02-15")] alias isGδ_setOf_liouville := IsGδ.setOf_liouville theorem setOf_liouville_eq_irrational_inter_iInter_iUnion : { x | Liouville x } = diff --git a/Mathlib/RingTheory/Flat/Basic.lean b/Mathlib/RingTheory/Flat/Basic.lean index 66b8a73a95d3f..0923edaa450fb 100644 --- a/Mathlib/RingTheory/Flat/Basic.lean +++ b/Mathlib/RingTheory/Flat/Basic.lean @@ -107,9 +107,6 @@ theorem iff_rTensor_injective' : rewrite [← rTensor_comp_apply] at hx₀ rw [(injective_iff_map_eq_zero _).mp (h hfg) y hx₀, LinearMap.map_zero] -@[deprecated (since := "2024-03-29")] -alias lTensor_inj_iff_rTensor_inj := LinearMap.lTensor_inj_iff_rTensor_inj - /-- The `lTensor`-variant of `iff_rTensor_injective`. . -/ theorem iff_lTensor_injective : Module.Flat R M ↔ ∀ ⦃I : Ideal R⦄ (_ : I.FG), Function.Injective (lTensor M I.subtype) := by @@ -259,9 +256,6 @@ theorem rTensor_preserves_injective_linearMap {N' : Type*} [AddCommGroup N'] [Mo Function.Injective (L.rTensor M) := rTensor_injective_iff_lcomp_surjective.2 ((iff_characterModule_baer.1 h).extension_property _ hL) -@[deprecated (since := "2024-03-29")] -alias preserves_injective_linearMap := rTensor_preserves_injective_linearMap - instance {S} [CommRing S] [Algebra R S] [Module S M] [IsScalarTower R S M] [Flat S M] [Flat R N] : Flat S (M ⊗[R] N) := (iff_rTensor_injective' _ _).mpr fun I ↦ by diff --git a/Mathlib/RingTheory/Ideal/Quotient/Operations.lean b/Mathlib/RingTheory/Ideal/Quotient/Operations.lean index 488ffed5743b2..f18039405d13b 100644 --- a/Mathlib/RingTheory/Ideal/Quotient/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Quotient/Operations.lean @@ -445,11 +445,6 @@ def quotientKerAlgEquivOfRightInverse {f : A →ₐ[R₁] B} {g : B → A} { RingHom.quotientKerEquivOfRightInverse hf, kerLiftAlg f with } -@[deprecated (since := "2024-02-27")] -alias quotientKerAlgEquivOfRightInverse.apply := quotientKerAlgEquivOfRightInverse_apply -@[deprecated (since := "2024-02-27")] -alias QuotientKerAlgEquivOfRightInverseSymm.apply := quotientKerAlgEquivOfRightInverse_symm_apply - /-- The **first isomorphism theorem** for algebras. -/ @[simps!] noncomputable def quotientKerAlgEquivOfSurjective {f : A →ₐ[R₁] B} (hf : Function.Surjective f) : diff --git a/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean b/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean index 0ad41dd02719a..f0bcd26091b84 100644 --- a/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean @@ -183,9 +183,6 @@ lemma _root_.MvPolynomial.isHomogeneous_C_mul_X (r : R) (i : σ) : (C r * X i).IsHomogeneous 1 := (isHomogeneous_X _ _).C_mul _ -@[deprecated (since := "2024-03-21")] -alias _root_.MvPolynomial.C_mul_X := _root_.MvPolynomial.isHomogeneous_C_mul_X - lemma pow (hφ : φ.IsHomogeneous m) (n : ℕ) : (φ ^ n).IsHomogeneous (m * n) := by rw [show φ ^ n = ∏ _i ∈ Finset.range n, φ by simp] rw [show m * n = ∑ _i ∈ Finset.range n, m by simp [mul_comm]] diff --git a/Mathlib/RingTheory/PowerBasis.lean b/Mathlib/RingTheory/PowerBasis.lean index 1e67541ed7447..fc58485528703 100644 --- a/Mathlib/RingTheory/PowerBasis.lean +++ b/Mathlib/RingTheory/PowerBasis.lean @@ -75,7 +75,6 @@ theorem coe_basis (pb : PowerBasis R S) : ⇑pb.basis = fun i : Fin pb.dim => pb /-- Cannot be an instance because `PowerBasis` cannot be a class. -/ theorem finite (pb : PowerBasis R S) : Module.Finite R S := .of_basis pb.basis -@[deprecated (since := "2024-03-05")] alias finiteDimensional := PowerBasis.finite theorem finrank [StrongRankCondition R] (pb : PowerBasis R S) : Module.finrank R S = pb.dim := by diff --git a/Mathlib/RingTheory/PrincipalIdealDomain.lean b/Mathlib/RingTheory/PrincipalIdealDomain.lean index 5343a17c2253a..77a6f3b5770e5 100644 --- a/Mathlib/RingTheory/PrincipalIdealDomain.lean +++ b/Mathlib/RingTheory/PrincipalIdealDomain.lean @@ -303,12 +303,6 @@ theorem isMaximal_of_irreducible [CommRing R] [IsPrincipalIdealRing R] {p : R} refine (of_irreducible_mul hp).resolve_right (mt (fun hb => ?_) (not_le_of_lt hI)) erw [Ideal.span_singleton_le_span_singleton, IsUnit.mul_right_dvd hb]⟩⟩ -@[deprecated (since := "2024-02-12")] -protected alias irreducible_iff_prime := irreducible_iff_prime - -@[deprecated (since := "2024-02-12")] -protected alias associates_irreducible_iff_prime := associates_irreducible_iff_prime - variable [CommRing R] [IsDomain R] [IsPrincipalIdealRing R] section diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index dbae9bcb743ed..ccf7c4055b535 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -176,9 +176,6 @@ theorem IsSemisimpleModule.of_sSup_simples_eq_top (h : sSup { m : Submodule R M | IsSimpleModule R m } = ⊤) : IsSemisimpleModule R M := complementedLattice_of_sSup_atoms_eq_top (by simp_rw [← h, isSimpleModule_iff_isAtom]) -@[deprecated (since := "2024-03-05")] -alias is_semisimple_of_sSup_simples_eq_top := IsSemisimpleModule.of_sSup_simples_eq_top - namespace IsSemisimpleModule variable [IsSemisimpleModule R M] @@ -261,9 +258,6 @@ theorem sSup_simples_eq_top_iff_isSemisimpleModule : sSup { m : Submodule R M | IsSimpleModule R m } = ⊤ ↔ IsSemisimpleModule R M := ⟨.of_sSup_simples_eq_top, fun _ ↦ IsSemisimpleModule.sSup_simples_eq_top _ _⟩ -@[deprecated (since := "2024-03-05")] -alias is_semisimple_iff_top_eq_sSup_simples := sSup_simples_eq_top_iff_isSemisimpleModule - /-- A module generated by semisimple submodules is itself semisimple. -/ lemma isSemisimpleModule_of_isSemisimpleModule_submodule {s : Set ι} {p : ι → Submodule R M} (hp : ∀ i ∈ s, IsSemisimpleModule R (p i)) (hp' : ⨆ i ∈ s, p i = ⊤) : diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean index 9456594b84a19..5a7f8e147aaf6 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean @@ -135,11 +135,6 @@ instance (priority := 100) ufm_of_decomposition_of_wfDvdMonoid UniqueFactorizationMonoid α := { ‹WfDvdMonoid α› with irreducible_iff_prime := irreducible_iff_prime } -@[deprecated ufm_of_decomposition_of_wfDvdMonoid (since := "2024-02-12")] -theorem ufm_of_gcd_of_wfDvdMonoid [CancelCommMonoidWithZero α] [WfDvdMonoid α] - [DecompositionMonoid α] : UniqueFactorizationMonoid α := - ufm_of_decomposition_of_wfDvdMonoid - end Prio namespace UniqueFactorizationMonoid diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain/FactorSet.lean b/Mathlib/RingTheory/UniqueFactorizationDomain/FactorSet.lean index 2dd1d63b54515..d2a4e0e814f99 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain/FactorSet.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain/FactorSet.lean @@ -219,7 +219,6 @@ noncomputable def factors (a : Associates α) : FactorSet α := by theorem factors_zero : (0 : Associates α).factors = ⊤ := dif_pos rfl -@[deprecated (since := "2024-03-16")] alias factors_0 := factors_zero @[simp] theorem factors_mk (a : α) (h : a ≠ 0) : (Associates.mk a).factors = factors' a := by diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain/Multiplicity.lean b/Mathlib/RingTheory/UniqueFactorizationDomain/Multiplicity.lean index 9768ee91a10df..fb49eb4d8fc1f 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain/Multiplicity.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain/Multiplicity.lean @@ -128,9 +128,4 @@ theorem count_normalizedFactors_eq' [DecidableEq R] {p x : R} (hp : p = 0 ∨ Ir end multiplicity -/-- Deprecated. Use `WfDvdMonoid.max_power_factor` instead. -/ -@[deprecated WfDvdMonoid.max_power_factor (since := "2024-03-01")] -theorem max_power_factor {a₀ x : R} (h : a₀ ≠ 0) (hx : Irreducible x) : - ∃ n : ℕ, ∃ a : R, ¬x ∣ a ∧ a₀ = x ^ n * a := WfDvdMonoid.max_power_factor h hx - end UniqueFactorizationMonoid diff --git a/Mathlib/SetTheory/Cardinal/Arithmetic.lean b/Mathlib/SetTheory/Cardinal/Arithmetic.lean index 5a7416afca6f0..59acdc7b0b398 100644 --- a/Mathlib/SetTheory/Cardinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Cardinal/Arithmetic.lean @@ -463,16 +463,10 @@ theorem add_le_add_iff_of_lt_aleph0 {α β γ : Cardinal} (γ₀ : γ < ℵ₀) theorem add_nat_le_add_nat_iff {α β : Cardinal} (n : ℕ) : α + n ≤ β + n ↔ α ≤ β := add_le_add_iff_of_lt_aleph0 (nat_lt_aleph0 n) -@[deprecated (since := "2024-02-12")] -alias add_nat_le_add_nat_iff_of_lt_aleph_0 := add_nat_le_add_nat_iff - @[simp] theorem add_one_le_add_one_iff {α β : Cardinal} : α + 1 ≤ β + 1 ↔ α ≤ β := add_le_add_iff_of_lt_aleph0 one_lt_aleph0 -@[deprecated (since := "2024-02-12")] -alias add_one_le_add_one_iff_of_lt_aleph_0 := add_one_le_add_one_iff - end aleph /-! ### Properties about `power` -/ diff --git a/Mathlib/SetTheory/Cardinal/ToNat.lean b/Mathlib/SetTheory/Cardinal/ToNat.lean index 0763034be27cb..80d792d3f53b3 100644 --- a/Mathlib/SetTheory/Cardinal/ToNat.lean +++ b/Mathlib/SetTheory/Cardinal/ToNat.lean @@ -82,20 +82,9 @@ theorem toNat_lt_iff_lt_of_lt_aleph0 (hc : c < ℵ₀) (hd : d < ℵ₀) : theorem toNat_le_toNat (hcd : c ≤ d) (hd : d < ℵ₀) : toNat c ≤ toNat d := toNat_monotoneOn (hcd.trans_lt hd) hd hcd -@[deprecated toNat_le_toNat (since := "2024-02-15")] -theorem toNat_le_of_le_of_lt_aleph0 (hd : d < ℵ₀) (hcd : c ≤ d) : - toNat c ≤ toNat d := - toNat_le_toNat hcd hd - theorem toNat_lt_toNat (hcd : c < d) (hd : d < ℵ₀) : toNat c < toNat d := toNat_strictMonoOn (hcd.trans hd) hd hcd -@[deprecated toNat_lt_toNat (since := "2024-02-15")] -theorem toNat_lt_of_lt_of_lt_aleph0 (hd : d < ℵ₀) (hcd : c < d) : toNat c < toNat d := - toNat_lt_toNat hcd hd - -@[deprecated (since := "2024-02-15")] alias toNat_cast := toNat_natCast - -- See note [no_index around OfNat.ofNat] @[simp] theorem toNat_ofNat (n : ℕ) [n.AtLeastTwo] : @@ -148,11 +137,6 @@ theorem toNat_congr {β : Type v} (e : α ≃ β) : toNat #α = toNat #β := by theorem toNat_mul (x y : Cardinal) : toNat (x * y) = toNat x * toNat y := map_mul toNat x y -@[deprecated map_prod (since := "2024-02-15")] -theorem toNat_finset_prod (s : Finset α) (f : α → Cardinal) : - toNat (∏ i ∈ s, f i) = ∏ i ∈ s, toNat (f i) := - map_prod toNat _ _ - @[simp] theorem toNat_add (hc : c < ℵ₀) (hd : d < ℵ₀) : toNat (c + d) = toNat c + toNat d := by lift c to ℕ using hc @@ -164,7 +148,4 @@ theorem toNat_lift_add_lift {a : Cardinal.{u}} {b : Cardinal.{v}} (ha : a < ℵ toNat (lift.{v} a + lift.{u} b) = toNat a + toNat b := by simp [*] -@[deprecated (since := "2024-02-15")] -alias toNat_add_of_lt_aleph0 := toNat_lift_add_lift - end Cardinal diff --git a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean index 688be889d23d8..d1448d49fe4b3 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean @@ -354,7 +354,6 @@ lemma HasProd.of_nat_of_neg_add_one {f : ℤ → M} exact (Nat.cast_injective.hasProd_range_iff.mpr hf₁).mul_isCompl this (hi₂.hasProd_range_iff.mpr hf₂) -@[deprecated (since := "2024-03-04")] alias HasSum.nonneg_add_neg := HasSum.of_nat_of_neg_add_one @[to_additive Summable.of_nat_of_neg_add_one] lemma Multipliable.of_nat_of_neg_add_one {f : ℤ → M} @@ -437,9 +436,6 @@ theorem HasProd.nat_mul_neg {f : ℤ → M} (hf : HasProd f m) : simp only [u1, u2, Nat.cast_inj, imp_self, implies_true, forall_const, prod_image, neg_inj] _ = ∏ b ∈ v', (f b * f (-b)) := prod_mul_distrib.symm⟩ -@[deprecated HasSum.nat_add_neg (since := "2024-03-04")] -alias HasSum.sum_nat_of_sum_int := HasSum.nat_add_neg - @[to_additive] theorem Multipliable.nat_mul_neg {f : ℤ → M} (hf : Multipliable f) : Multipliable fun n : ℕ ↦ f n * f (-n) := @@ -456,9 +452,6 @@ theorem HasProd.of_add_one_of_neg_add_one {f : ℤ → M} HasProd f (m * f 0 * m') := HasProd.of_nat_of_neg_add_one (mul_comm _ m ▸ HasProd.zero_mul hf₁) hf₂ -@[deprecated HasSum.of_add_one_of_neg_add_one (since := "2024-03-04")] -alias HasSum.pos_add_zero_add_neg := HasSum.of_add_one_of_neg_add_one - @[to_additive Summable.of_add_one_of_neg_add_one] lemma Multipliable.of_add_one_of_neg_add_one {f : ℤ → M} (hf₁ : Multipliable fun n : ℕ ↦ f (n + 1)) (hf₂ : Multipliable fun n : ℕ ↦ f (-(n + 1))) : @@ -490,9 +483,6 @@ lemma Multipliable.of_nat_of_neg {f : ℤ → G} (hf₁ : Multipliable fun n : (hf₂ : Multipliable fun n : ℕ ↦ f (-n)) : Multipliable f := (hf₁.hasProd.of_nat_of_neg hf₂.hasProd).multipliable -@[deprecated Summable.of_nat_of_neg (since := "2024-03-04")] -alias summable_int_of_summable_nat := Summable.of_nat_of_neg - @[to_additive] lemma tprod_of_nat_of_neg [T2Space G] {f : ℤ → G} (hf₁ : Multipliable fun n : ℕ ↦ f n) (hf₂ : Multipliable fun n : ℕ ↦ f (-n)) : diff --git a/Mathlib/Topology/Algebra/UniformRing.lean b/Mathlib/Topology/Algebra/UniformRing.lean index a52f63d8fafe8..5453277e0629f 100644 --- a/Mathlib/Topology/Algebra/UniformRing.lean +++ b/Mathlib/Topology/Algebra/UniformRing.lean @@ -233,16 +233,6 @@ theorem inseparableSetoid_ring (α) [CommRing α] [TopologicalSpace α] [Topolog Setoid.ext fun x y => addGroup_inseparable_iff.trans <| .trans (by rfl) (Submodule.quotientRel_def _).symm -@[deprecated (since := "2024-03-09")] -alias ring_sep_rel := inseparableSetoid_ring - --- Equality of types is evil -@[deprecated UniformSpace.inseparableSetoid_ring (since := "2024-02-16")] -theorem ring_sep_quot (α : Type u) [r : CommRing α] [TopologicalSpace α] [TopologicalRing α] : - SeparationQuotient α = (α ⧸ (⊥ : Ideal α).closure) := by - rw [SeparationQuotient, @inseparableSetoid_ring α r] - rfl - /-- Given a topological ring `α` equipped with a uniform structure that makes subtraction uniformly continuous, get an homeomorphism between the separated quotient of `α` and the quotient ring corresponding to the closure of zero. -/ diff --git a/Mathlib/Topology/Bases.lean b/Mathlib/Topology/Bases.lean index 691e389d9e045..db461531876af 100644 --- a/Mathlib/Topology/Bases.lean +++ b/Mathlib/Topology/Bases.lean @@ -526,15 +526,9 @@ theorem isSeparable_range [TopologicalSpace β] [SeparableSpace α] {f : α → theorem IsSeparable.of_subtype (s : Set α) [SeparableSpace s] : IsSeparable s := by simpa using isSeparable_range (continuous_subtype_val (p := (· ∈ s))) -@[deprecated (since := "2024-02-05")] -alias isSeparable_of_separableSpace_subtype := IsSeparable.of_subtype - theorem IsSeparable.of_separableSpace [h : SeparableSpace α] (s : Set α) : IsSeparable s := IsSeparable.mono (isSeparable_univ_iff.2 h) (subset_univ _) -@[deprecated (since := "2024-02-05")] -alias isSeparable_of_separableSpace := IsSeparable.of_separableSpace - end TopologicalSpace open TopologicalSpace diff --git a/Mathlib/Topology/CompactOpen.lean b/Mathlib/Topology/CompactOpen.lean index 49f2b425934f9..3f9c290325a74 100644 --- a/Mathlib/Topology/CompactOpen.lean +++ b/Mathlib/Topology/CompactOpen.lean @@ -279,17 +279,11 @@ theorem compactOpen_eq_iInf_induced : convert isOpen_induced (isOpen_setOf_mapsTo (isCompact_iff_isCompact_univ.1 hK) hU) simp [mapsTo_univ_iff, Subtype.forall, MapsTo] -@[deprecated (since := "2024-03-05")] -alias compactOpen_eq_sInf_induced := compactOpen_eq_iInf_induced - theorem nhds_compactOpen_eq_iInf_nhds_induced (f : C(X, Y)) : 𝓝 f = ⨅ (s) (_ : IsCompact s), (𝓝 (f.restrict s)).comap (ContinuousMap.restrict s) := by rw [compactOpen_eq_iInf_induced] simp only [nhds_iInf, nhds_induced] -@[deprecated (since := "2024-03-05")] -alias nhds_compactOpen_eq_sInf_nhds_induced := nhds_compactOpen_eq_iInf_nhds_induced - theorem tendsto_compactOpen_restrict {ι : Type*} {l : Filter ι} {F : ι → C(X, Y)} {f : C(X, Y)} (hFf : Filter.Tendsto F l (𝓝 f)) (s : Set X) : Tendsto (fun i => (F i).restrict s) l (𝓝 (f.restrict s)) := @@ -371,15 +365,6 @@ def curry (f : C(X × Y, Z)) : C(X, C(Y, Z)) where theorem curry_apply (f : C(X × Y, Z)) (a : X) (b : Y) : f.curry a b = f (a, b) := rfl -/-- Auxiliary definition, see `ContinuousMap.curry` and `Homeomorph.curry`. -/ -@[deprecated ContinuousMap.curry (since := "2024-03-05")] -def curry' (f : C(X × Y, Z)) (a : X) : C(Y, Z) := curry f a - -set_option linter.deprecated false in -/-- If a map `α × β → γ` is continuous, then its curried form `α → C(β, γ)` is continuous. -/ -@[deprecated ContinuousMap.curry (since := "2024-03-05")] -theorem continuous_curry' (f : C(X × Y, Z)) : Continuous (curry' f) := (curry f).continuous - /-- To show continuity of a map `α → C(β, γ)`, it suffices to show that its uncurried form `α × β → γ` is continuous. -/ theorem continuous_of_continuous_uncurry (f : X → C(Y, Z)) diff --git a/Mathlib/Topology/Compactness/Compact.lean b/Mathlib/Topology/Compactness/Compact.lean index 15e1b303bf533..3482d2379b813 100644 --- a/Mathlib/Topology/Compactness/Compact.lean +++ b/Mathlib/Topology/Compactness/Compact.lean @@ -283,10 +283,6 @@ theorem IsCompact.nonempty_iInter_of_directed_nonempty_isCompact_isClosed rcases htd i₀ i with ⟨j, hji₀, hji⟩ exact (htn j).mono (subset_inter hji₀ hji) -@[deprecated (since := "2024-02-28")] -alias IsCompact.nonempty_iInter_of_directed_nonempty_compact_closed := - IsCompact.nonempty_iInter_of_directed_nonempty_isCompact_isClosed - /-- Cantor's intersection theorem for `sInter`: the intersection of a directed family of nonempty compact closed sets is nonempty. -/ theorem IsCompact.nonempty_sInter_of_directed_nonempty_isCompact_isClosed @@ -307,10 +303,6 @@ theorem IsCompact.nonempty_iInter_of_sequence_nonempty_isCompact_isClosed (t : have htc : ∀ i, IsCompact (t i) := fun i => ht0.of_isClosed_subset (htcl i) (this i) IsCompact.nonempty_iInter_of_directed_nonempty_isCompact_isClosed t htd htn htc htcl -@[deprecated (since := "2024-02-28")] -alias IsCompact.nonempty_iInter_of_sequence_nonempty_compact_closed := - IsCompact.nonempty_iInter_of_sequence_nonempty_isCompact_isClosed - /-- For every open cover of a compact set, there exists a finite subcover. -/ theorem IsCompact.elim_finite_subcover_image {b : Set ι} {c : ι → Set X} (hs : IsCompact s) (hc₁ : ∀ i ∈ b, IsOpen (c i)) (hc₂ : s ⊆ ⋃ i ∈ b, c i) : @@ -640,14 +632,6 @@ theorem mem_coclosedCompact_iff : closure_minimal (compl_subset_comm.2 hst) htcl · exact ⟨closure sᶜ, ⟨isClosed_closure, h⟩, compl_subset_comm.2 subset_closure⟩ -@[deprecated mem_coclosedCompact_iff (since := "2024-02-16")] -theorem mem_coclosedCompact : s ∈ coclosedCompact X ↔ ∃ t, IsClosed t ∧ IsCompact t ∧ tᶜ ⊆ s := by - simp only [hasBasis_coclosedCompact.mem_iff, and_assoc] - -@[deprecated mem_coclosedCompact_iff (since := "2024-02-16")] -theorem mem_coclosed_compact' : s ∈ coclosedCompact X ↔ ∃ t, IsClosed t ∧ IsCompact t ∧ sᶜ ⊆ t := by - simp only [hasBasis_coclosedCompact.mem_iff, compl_subset_comm, and_assoc] - /-- Complement of a set belongs to `coclosedCompact` if and only if its closure is compact. -/ theorem compl_mem_coclosedCompact : sᶜ ∈ coclosedCompact X ↔ IsCompact (closure s) := by rw [mem_coclosedCompact_iff, compl_compl] diff --git a/Mathlib/Topology/Constructions.lean b/Mathlib/Topology/Constructions.lean index ee4d5a39eb471..5e5987a52ca6d 100644 --- a/Mathlib/Topology/Constructions.lean +++ b/Mathlib/Topology/Constructions.lean @@ -467,8 +467,6 @@ theorem Continuous.uncurry_right {f : X → Y → Z} (y : Y) (h : Continuous (un Continuous fun a => f a y := h.comp (Continuous.Prod.mk_left _) -@[deprecated (since := "2024-03-09")] alias continuous_uncurry_left := Continuous.uncurry_left -@[deprecated (since := "2024-03-09")] alias continuous_uncurry_right := Continuous.uncurry_right theorem continuous_curry {g : X × Y → Z} (x : X) (h : Continuous g) : Continuous (curry g x) := Continuous.uncurry_left x h diff --git a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean index c634039f9359d..0d56fcaf0d007 100644 --- a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean +++ b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean @@ -1414,8 +1414,6 @@ instance instLattice : Lattice (α →ᵇ β) := DFunLike.coe_injective.lattice @[simp, norm_cast] lemma coe_posPart (f : α →ᵇ β) : ⇑f⁺ = (⇑f)⁺ := rfl @[simp, norm_cast] lemma coe_negPart (f : α →ᵇ β) : ⇑f⁻ = (⇑f)⁻ := rfl -@[deprecated (since := "2024-02-21")] alias coeFn_sup := coe_sup -@[deprecated (since := "2024-02-21")] alias coeFn_abs := coe_abs instance instNormedLatticeAddCommGroup : NormedLatticeAddCommGroup (α →ᵇ β) := { instSeminormedAddCommGroup with diff --git a/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean b/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean index eecb451c02ae7..6726cd76211d7 100644 --- a/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean +++ b/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean @@ -430,7 +430,6 @@ theorem isClosed_range_toBCF : IsClosed (range (toBCF : C₀(α, β) → α → _ < ε := by simpa [add_halves ε] using add_lt_add_right (mem_ball.1 hg) (ε / 2) exact ⟨⟨f.toContinuousMap, this⟩, rfl⟩ -@[deprecated (since := "2024-03-17")] alias closed_range_toBCF := isClosed_range_toBCF /-- Continuous functions vanishing at infinity taking values in a complete space form a complete space. -/ diff --git a/Mathlib/Topology/GDelta/Basic.lean b/Mathlib/Topology/GDelta/Basic.lean index 60e2975ce2246..250e1184d4569 100644 --- a/Mathlib/Topology/GDelta/Basic.lean +++ b/Mathlib/Topology/GDelta/Basic.lean @@ -66,25 +66,21 @@ theorem IsOpen.isGδ {s : Set X} (h : IsOpen s) : IsGδ s := protected theorem IsGδ.empty : IsGδ (∅ : Set X) := isOpen_empty.isGδ -@[deprecated (since := "2024-02-15")] alias isGδ_empty := IsGδ.empty @[simp] protected theorem IsGδ.univ : IsGδ (univ : Set X) := isOpen_univ.isGδ -@[deprecated (since := "2024-02-15")] alias isGδ_univ := IsGδ.univ theorem IsGδ.biInter_of_isOpen {I : Set ι} (hI : I.Countable) {f : ι → Set X} (hf : ∀ i ∈ I, IsOpen (f i)) : IsGδ (⋂ i ∈ I, f i) := ⟨f '' I, by rwa [forall_mem_image], hI.image _, by rw [sInter_image]⟩ -@[deprecated (since := "2024-02-15")] alias isGδ_biInter_of_isOpen := IsGδ.biInter_of_isOpen theorem IsGδ.iInter_of_isOpen [Countable ι'] {f : ι' → Set X} (hf : ∀ i, IsOpen (f i)) : IsGδ (⋂ i, f i) := ⟨range f, by rwa [forall_mem_range], countable_range _, by rw [sInter_range]⟩ -@[deprecated (since := "2024-02-15")] alias isGδ_iInter_of_isOpen := IsGδ.iInter_of_isOpen lemma isGδ_iff_eq_iInter_nat {s : Set X} : IsGδ s ↔ ∃ (f : ℕ → Set X), (∀ n, IsOpen (f n)) ∧ s = ⋂ n, f n := by @@ -115,13 +111,11 @@ theorem IsGδ.biInter {s : Set ι} (hs : s.Countable) {t : ∀ i ∈ s, Set X} haveI := hs.to_subtype exact .iInter fun x => ht x x.2 -@[deprecated (since := "2024-02-15")] alias isGδ_biInter := IsGδ.biInter /-- A countable intersection of Gδ sets is a Gδ set. -/ theorem IsGδ.sInter {S : Set (Set X)} (h : ∀ s ∈ S, IsGδ s) (hS : S.Countable) : IsGδ (⋂₀ S) := by simpa only [sInter_eq_biInter] using IsGδ.biInter hS h -@[deprecated (since := "2024-02-15")] alias isGδ_sInter := IsGδ.sInter theorem IsGδ.inter {s t : Set X} (hs : IsGδ s) (ht : IsGδ t) : IsGδ (s ∩ t) := by rw [inter_eq_iInter] @@ -150,9 +144,6 @@ theorem IsGδ.biUnion {s : Set ι} (hs : s.Finite) {f : ι → Set X} (h : ∀ i rw [← sUnion_image] exact .sUnion (hs.image _) (forall_mem_image.2 h) -@[deprecated (since := "2024-02-15")] -alias isGδ_biUnion := IsGδ.biUnion - /-- The union of finitely many Gδ sets is a Gδ set, bounded indexed union version. -/ theorem IsGδ.iUnion [Finite ι'] {f : ι' → Set X} (h : ∀ i, IsGδ (f i)) : IsGδ (⋃ i, f i) := .sUnion (finite_range _) <| forall_mem_range.2 h diff --git a/Mathlib/Topology/GDelta/UniformSpace.lean b/Mathlib/Topology/GDelta/UniformSpace.lean index 3aab2f9dd00c0..735d3d2bd0269 100644 --- a/Mathlib/Topology/GDelta/UniformSpace.lean +++ b/Mathlib/Topology/GDelta/UniformSpace.lean @@ -50,6 +50,5 @@ theorem IsGδ.setOf_continuousAt [UniformSpace Y] [IsCountablyGenerated (𝓤 Y) rintro ⟨s, ⟨hsx, hso⟩, hsU⟩ filter_upwards [IsOpen.mem_nhds hso hsx] with _ hy using ⟨s, ⟨hy, hso⟩, hsU⟩ -@[deprecated (since := "2024-02-15")] alias isGδ_setOf_continuousAt := IsGδ.setOf_continuousAt end ContinuousAt diff --git a/Mathlib/Topology/Instances/Discrete.lean b/Mathlib/Topology/Instances/Discrete.lean index b9af3e7060b0e..d798a8a6591b8 100644 --- a/Mathlib/Topology/Instances/Discrete.lean +++ b/Mathlib/Topology/Instances/Discrete.lean @@ -36,11 +36,6 @@ instance (priority := 100) DiscreteTopology.secondCountableTopology_of_countable secondCountableTopology_of_countable_cover (singletons_open_iff_discrete.mpr hd) (iUnion_of_singleton α) -@[deprecated DiscreteTopology.secondCountableTopology_of_countable (since := "2024-03-11")] -theorem DiscreteTopology.secondCountableTopology_of_encodable {α : Type*} - [TopologicalSpace α] [DiscreteTopology α] [Countable α] : SecondCountableTopology α := - DiscreteTopology.secondCountableTopology_of_countable - theorem LinearOrder.bot_topologicalSpace_eq_generateFrom {α} [LinearOrder α] [PredOrder α] [SuccOrder α] : (⊥ : TopologicalSpace α) = generateFrom { s | ∃ a, s = Ioi a ∨ s = Iio a } := by let _ := Preorder.topology α diff --git a/Mathlib/Topology/Instances/Int.lean b/Mathlib/Topology/Instances/Int.lean index 009674177e1f0..ba41c15cda783 100644 --- a/Mathlib/Topology/Instances/Int.lean +++ b/Mathlib/Topology/Instances/Int.lean @@ -73,7 +73,6 @@ theorem cobounded_eq : Bornology.cobounded ℤ = atBot ⊔ atTop := by simp_rw [← comap_dist_right_atTop (0 : ℤ), dist_eq', sub_zero, ← comap_abs_atTop, ← @Int.comap_cast_atTop ℝ, comap_comap]; rfl -@[deprecated (since := "2024-02-07")] alias cocompact_eq := cocompact_eq_atBot_atTop @[simp] theorem cofinite_eq : (cofinite : Filter ℤ) = atBot ⊔ atTop := by diff --git a/Mathlib/Topology/Instances/Irrational.lean b/Mathlib/Topology/Instances/Irrational.lean index f395be578fdff..8b82916e9b93b 100644 --- a/Mathlib/Topology/Instances/Irrational.lean +++ b/Mathlib/Topology/Instances/Irrational.lean @@ -36,7 +36,6 @@ open Filter Topology protected theorem IsGδ.setOf_irrational : IsGδ { x | Irrational x } := (countable_range _).isGδ_compl -@[deprecated (since := "2024-02-15")] alias isGδ_irrational := IsGδ.setOf_irrational theorem dense_irrational : Dense { x : ℝ | Irrational x } := by refine Real.isTopologicalBasis_Ioo_rat.dense_iff.2 ?_ diff --git a/Mathlib/Topology/Instances/Real.lean b/Mathlib/Topology/Instances/Real.lean index 522b40e629e4b..41f5e2e54a206 100644 --- a/Mathlib/Topology/Instances/Real.lean +++ b/Mathlib/Topology/Instances/Real.lean @@ -74,10 +74,7 @@ theorem Real.isTopologicalBasis_Ioo_rat : theorem Real.cobounded_eq : cobounded ℝ = atBot ⊔ atTop := by simp only [← comap_dist_right_atTop (0 : ℝ), Real.dist_eq, sub_zero, comap_abs_atTop] -@[deprecated (since := "2024-02-07")] alias Real.cocompact_eq := cocompact_eq_atBot_atTop -@[deprecated (since := "2024-02-07")] alias Real.atBot_le_cocompact := atBot_le_cocompact -@[deprecated (since := "2024-02-07")] alias Real.atTop_le_cocompact := atTop_le_cocompact /- TODO(Mario): Prove that these are uniform isomorphisms instead of uniform embeddings lemma uniform_embedding_add_rat {r : ℚ} : uniform_embedding (fun p : ℚ => p + r) := diff --git a/Mathlib/Topology/Maps/Basic.lean b/Mathlib/Topology/Maps/Basic.lean index 077466f86f877..ecd68d48bac01 100644 --- a/Mathlib/Topology/Maps/Basic.lean +++ b/Mathlib/Topology/Maps/Basic.lean @@ -487,7 +487,6 @@ theorem of_nonempty (h : ∀ s, IsClosed s → s.Nonempty → IsClosed (f '' s)) theorem isClosed_range (hf : IsClosedMap f) : IsClosed (range f) := @image_univ _ _ f ▸ hf _ isClosed_univ -@[deprecated (since := "2024-03-17")] alias closed_range := isClosed_range theorem isQuotientMap (hcl : IsClosedMap f) (hcont : Continuous f) (hsurj : Surjective f) : IsQuotientMap f := diff --git a/Mathlib/Topology/MetricSpace/Completion.lean b/Mathlib/Topology/MetricSpace/Completion.lean index cbca7d20888b3..69037d369df59 100644 --- a/Mathlib/Topology/MetricSpace/Completion.lean +++ b/Mathlib/Topology/MetricSpace/Completion.lean @@ -158,10 +158,6 @@ instance instMetricSpace : MetricSpace (Completion α) := toUniformSpace := inferInstance uniformity_dist := Completion.uniformity_dist } _ -@[deprecated eq_of_dist_eq_zero (since := "2024-03-10")] -protected theorem eq_of_dist_eq_zero (x y : Completion α) (h : dist x y = 0) : x = y := - eq_of_dist_eq_zero h - /-- The embedding of a metric space in its completion is an isometry. -/ theorem coe_isometry : Isometry ((↑) : α → Completion α) := Isometry.of_dist_eq Completion.dist_eq diff --git a/Mathlib/Topology/MetricSpace/Polish.lean b/Mathlib/Topology/MetricSpace/Polish.lean index 70ae87a47d620..543d4da8c0d76 100644 --- a/Mathlib/Topology/MetricSpace/Polish.lean +++ b/Mathlib/Topology/MetricSpace/Polish.lean @@ -102,9 +102,6 @@ instance (priority := 100) instMetrizableSpace (α : Type*) [TopologicalSpace α letI := upgradePolishSpace α infer_instance -@[deprecated "No deprecation message was provided." (since := "2024-02-23")] -theorem t2Space (α : Type*) [TopologicalSpace α] [PolishSpace α] : T2Space α := inferInstance - /-- A countable product of Polish spaces is Polish. -/ instance pi_countable {ι : Type*} [Countable ι] {E : ι → Type*} [∀ i, TopologicalSpace (E i)] [∀ i, PolishSpace (E i)] : PolishSpace (∀ i, E i) := by diff --git a/Mathlib/Topology/MetricSpace/Sequences.lean b/Mathlib/Topology/MetricSpace/Sequences.lean index ed02f21cdebd7..5548bfac6db34 100644 --- a/Mathlib/Topology/MetricSpace/Sequences.lean +++ b/Mathlib/Topology/MetricSpace/Sequences.lean @@ -17,12 +17,6 @@ open scoped Topology variable {X : Type*} [PseudoMetricSpace X] -@[deprecated lebesgue_number_lemma_of_metric (since := "2024-02-24")] -nonrec theorem SeqCompact.lebesgue_number_lemma_of_metric {ι : Sort*} {c : ι → Set X} {s : Set X} - (hs : IsSeqCompact s) (hc₁ : ∀ i, IsOpen (c i)) (hc₂ : s ⊆ ⋃ i, c i) : - ∃ δ > 0, ∀ a ∈ s, ∃ i, ball a δ ⊆ c i := - lebesgue_number_lemma_of_metric hs.isCompact hc₁ hc₂ - variable [ProperSpace X] {s : Set X} /-- A version of **Bolzano-Weierstrass**: in a proper metric space (eg. $ℝ^n$), diff --git a/Mathlib/Topology/Order.lean b/Mathlib/Topology/Order.lean index 0be6eb00b68ce..2bd638f106979 100644 --- a/Mathlib/Topology/Order.lean +++ b/Mathlib/Topology/Order.lean @@ -286,9 +286,6 @@ theorem le_of_nhds_le_nhds (h : ∀ x, @nhds α t₁ x ≤ @nhds α t₂ x) : t rw [@isOpen_iff_mem_nhds _ _ t₁, @isOpen_iff_mem_nhds α _ t₂] exact fun hs a ha => h _ (hs _ ha) -@[deprecated (since := "2024-03-01")] -alias eq_of_nhds_eq_nhds := TopologicalSpace.ext_nhds - theorem eq_bot_of_singletons_open {t : TopologicalSpace α} (h : ∀ x, IsOpen[t] {x}) : t = ⊥ := bot_unique fun s _ => biUnion_of_singleton s ▸ isOpen_biUnion fun x _ => h x @@ -572,19 +569,11 @@ theorem nhds_nhdsAdjoint_same (a : α) (f : Filter α) : exact IsOpen.mem_nhds (fun _ ↦ htf) hat · exact sup_le (pure_le_nhds _) ((gc_nhds a).le_u_l f) -@[deprecated (since := "2024-02-10")] -alias nhdsAdjoint_nhds := nhds_nhdsAdjoint_same - theorem nhds_nhdsAdjoint_of_ne {a b : α} (f : Filter α) (h : b ≠ a) : @nhds α (nhdsAdjoint a f) b = pure b := let _ := nhdsAdjoint a f (isOpen_singleton_iff_nhds_eq_pure _).1 <| isOpen_singleton_nhdsAdjoint f h -@[deprecated nhds_nhdsAdjoint_of_ne (since := "2024-02-10")] -theorem nhdsAdjoint_nhds_of_ne (a : α) (f : Filter α) {b : α} (h : b ≠ a) : - @nhds α (nhdsAdjoint a f) b = pure b := - nhds_nhdsAdjoint_of_ne f h - theorem nhds_nhdsAdjoint [DecidableEq α] (a : α) (f : Filter α) : @nhds α (nhdsAdjoint a f) = update pure a (pure a ⊔ f) := eq_update_iff.2 ⟨nhds_nhdsAdjoint_same .., fun _ ↦ nhds_nhdsAdjoint_of_ne _⟩ diff --git a/Mathlib/Topology/Order/Basic.lean b/Mathlib/Topology/Order/Basic.lean index a0884956957dd..80dc91a3e3e3e 100644 --- a/Mathlib/Topology/Order/Basic.lean +++ b/Mathlib/Topology/Order/Basic.lean @@ -489,16 +489,6 @@ theorem Dense.topology_eq_generateFrom [OrderTopology α] [DenselyOrdered α] {s let _ := generateFrom (Ioi '' s ∪ Iio '' s) exact isOpen_iUnion fun x ↦ isOpen_iUnion fun h ↦ .basic _ <| .inr <| mem_image_of_mem _ h.1 -@[deprecated OrderBot.atBot_eq (since := "2024-02-14")] -theorem atBot_le_nhds_bot [OrderBot α] : (atBot : Filter α) ≤ 𝓝 ⊥ := by - rw [OrderBot.atBot_eq] - apply pure_le_nhds - -set_option linter.deprecated false in -@[deprecated OrderTop.atTop_eq (since := "2024-02-14")] -theorem atTop_le_nhds_top [OrderTop α] : (atTop : Filter α) ≤ 𝓝 ⊤ := - @atBot_le_nhds_bot αᵒᵈ _ _ _ - variable (α) /-- Let `α` be a densely ordered linear order with order topology. If `α` is a separable space, then diff --git a/Mathlib/Topology/Order/OrderClosed.lean b/Mathlib/Topology/Order/OrderClosed.lean index 94bdce684cd4a..846125f18cf39 100644 --- a/Mathlib/Topology/Order/OrderClosed.lean +++ b/Mathlib/Topology/Order/OrderClosed.lean @@ -108,10 +108,6 @@ variable [TopologicalSpace α] [Preorder α] [ClosedIicTopology α] {f : β → theorem isClosed_Iic : IsClosed (Iic a) := ClosedIicTopology.isClosed_Iic a -@[deprecated isClosed_Iic (since := "2024-02-15")] -lemma ClosedIicTopology.isClosed_le' (a : α) : IsClosed {x | x ≤ a} := isClosed_Iic a -export ClosedIicTopology (isClosed_le') - instance : ClosedIciTopology αᵒᵈ where isClosed_Ici _ := isClosed_Iic (α := α) @@ -415,10 +411,6 @@ variable [TopologicalSpace α] [Preorder α] [ClosedIciTopology α] {f : β → theorem isClosed_Ici {a : α} : IsClosed (Ici a) := ClosedIciTopology.isClosed_Ici a -@[deprecated isClosed_Ici (since := "2024-02-15")] -lemma ClosedIciTopology.isClosed_ge' (a : α) : IsClosed {x | a ≤ x} := isClosed_Ici a -export ClosedIciTopology (isClosed_ge') - instance : ClosedIicTopology αᵒᵈ where isClosed_Iic _ := isClosed_Ici (α := α) diff --git a/Mathlib/Topology/Semicontinuous.lean b/Mathlib/Topology/Semicontinuous.lean index ae630cd687ba7..b569bcd00df4f 100644 --- a/Mathlib/Topology/Semicontinuous.lean +++ b/Mathlib/Topology/Semicontinuous.lean @@ -326,14 +326,8 @@ theorem lowerSemicontinuous_iff_isClosed_epigraph {f : α → γ} : · rw [lowerSemicontinuous_iff_isClosed_preimage] exact fun hf y ↦ hf.preimage (Continuous.Prod.mk_left y) -@[deprecated (since := "2024-03-02")] -alias lowerSemicontinuous_iff_IsClosed_epigraph := lowerSemicontinuous_iff_isClosed_epigraph - alias ⟨LowerSemicontinuous.isClosed_epigraph, _⟩ := lowerSemicontinuous_iff_isClosed_epigraph -@[deprecated (since := "2024-03-02")] -alias LowerSemicontinuous.IsClosed_epigraph := LowerSemicontinuous.isClosed_epigraph - end /-! ### Composition -/ diff --git a/Mathlib/Topology/Separation/GDelta.lean b/Mathlib/Topology/Separation/GDelta.lean index abc821f17ade6..57bc39f4a2d32 100644 --- a/Mathlib/Topology/Separation/GDelta.lean +++ b/Mathlib/Topology/Separation/GDelta.lean @@ -35,7 +35,6 @@ section Separation theorem IsGδ.compl_singleton (x : X) [T1Space X] : IsGδ ({x}ᶜ : Set X) := isOpen_compl_singleton.isGδ -@[deprecated (since := "2024-02-15")] alias isGδ_compl_singleton := IsGδ.compl_singleton theorem Set.Countable.isGδ_compl {s : Set X} [T1Space X] (hs : s.Countable) : IsGδ sᶜ := by rw [← biUnion_of_singleton s, compl_iUnion₂] @@ -56,7 +55,6 @@ protected theorem IsGδ.singleton [FirstCountableTopology X] [T1Space X] (x : X) rw [← biInter_basis_nhds h_basis.toHasBasis] exact .biInter (to_countable _) fun n _ => (hU n).2.isGδ -@[deprecated (since := "2024-02-15")] alias isGδ_singleton := IsGδ.singleton theorem Set.Finite.isGδ [FirstCountableTopology X] {s : Set X} [T1Space X] (hs : s.Finite) : IsGδ s := diff --git a/Mathlib/Topology/Separation/Hausdorff.lean b/Mathlib/Topology/Separation/Hausdorff.lean index 17cc8d6659b95..957b2b4b1cfd1 100644 --- a/Mathlib/Topology/Separation/Hausdorff.lean +++ b/Mathlib/Topology/Separation/Hausdorff.lean @@ -528,9 +528,6 @@ theorem Function.LeftInverse.isClosed_range [T2Space X] {f : X → Y} {g : Y → h.rightInvOn_range.eqOn.closure (hg.comp hf) continuous_id isClosed_of_closure_subset fun x hx => ⟨f x, this hx⟩ -@[deprecated (since := "2024-03-17")] -alias Function.LeftInverse.closed_range := Function.LeftInverse.isClosed_range - theorem Function.LeftInverse.isClosedEmbedding [T2Space X] {f : X → Y} {g : Y → X} (h : Function.LeftInverse f g) (hf : Continuous f) (hg : Continuous g) : IsClosedEmbedding g := ⟨.of_leftInverse h hf hg, h.isClosed_range hf hg⟩ diff --git a/Mathlib/Topology/Separation/Regular.lean b/Mathlib/Topology/Separation/Regular.lean index f886e9d275213..3be8602edb54b 100644 --- a/Mathlib/Topology/Separation/Regular.lean +++ b/Mathlib/Topology/Separation/Regular.lean @@ -113,24 +113,15 @@ theorem RegularSpace.of_lift'_closure_le (h : ∀ x : X, (𝓝 x).lift' closure theorem RegularSpace.of_lift'_closure (h : ∀ x : X, (𝓝 x).lift' closure = 𝓝 x) : RegularSpace X := Iff.mpr ((regularSpace_TFAE X).out 0 5) h -@[deprecated (since := "2024-02-28")] -alias RegularSpace.ofLift'_closure := RegularSpace.of_lift'_closure - theorem RegularSpace.of_hasBasis {ι : X → Sort*} {p : ∀ a, ι a → Prop} {s : ∀ a, ι a → Set X} (h₁ : ∀ a, (𝓝 a).HasBasis (p a) (s a)) (h₂ : ∀ a i, p a i → IsClosed (s a i)) : RegularSpace X := .of_lift'_closure fun a => (h₁ a).lift'_closure_eq_self (h₂ a) -@[deprecated (since := "2024-02-28")] -alias RegularSpace.ofBasis := RegularSpace.of_hasBasis - theorem RegularSpace.of_exists_mem_nhds_isClosed_subset (h : ∀ (x : X), ∀ s ∈ 𝓝 x, ∃ t ∈ 𝓝 x, IsClosed t ∧ t ⊆ s) : RegularSpace X := Iff.mpr ((regularSpace_TFAE X).out 0 3) h -@[deprecated (since := "2024-02-28")] -alias RegularSpace.ofExistsMemNhdsIsClosedSubset := RegularSpace.of_exists_mem_nhds_isClosed_subset - /-- A weakly locally compact R₁ space is regular. -/ instance (priority := 100) [WeaklyLocallyCompactSpace X] [R1Space X] : RegularSpace X := .of_hasBasis isCompact_isClosed_basis_nhds fun _ _ ⟨_, _, h⟩ ↦ h diff --git a/Mathlib/Topology/UniformSpace/Basic.lean b/Mathlib/Topology/UniformSpace/Basic.lean index 0057d6c5ff78f..f5abe4496c48a 100644 --- a/Mathlib/Topology/UniformSpace/Basic.lean +++ b/Mathlib/Topology/UniformSpace/Basic.lean @@ -352,20 +352,6 @@ theorem UniformSpace.toCore_toTopologicalSpace (u : UniformSpace α) : TopologicalSpace.ext_nhds fun a ↦ by rw [u.nhds_eq_comap_uniformity, u.toCore.nhds_toTopologicalSpace] -/-- Build a `UniformSpace` from a `UniformSpace.Core` and a compatible topology. -Use `UniformSpace.mk` instead to avoid proving -the unnecessary assumption `UniformSpace.Core.refl`. - -The main constructor used to use a different compatibility assumption. -This definition was created as a step towards porting to a new definition. -Now the main definition is ported, -so this constructor will be removed in a few months. -/ -@[deprecated UniformSpace.mk (since := "2024-03-20")] -def UniformSpace.ofNhdsEqComap (u : UniformSpace.Core α) (_t : TopologicalSpace α) - (h : ∀ x, 𝓝 x = u.uniformity.comap (Prod.mk x)) : UniformSpace α where - __ := u - nhds_eq_comap_uniformity := h - @[ext (iff := false)] protected theorem UniformSpace.ext {u₁ u₂ : UniformSpace α} (h : 𝓤[u₁] = 𝓤[u₂]) : u₁ = u₂ := by have : u₁.toTopologicalSpace = u₂.toTopologicalSpace := TopologicalSpace.ext_nhds fun x ↦ by diff --git a/Mathlib/Topology/UnitInterval.lean b/Mathlib/Topology/UnitInterval.lean index cec95ceaeefe6..5cecb700fae18 100644 --- a/Mathlib/Topology/UnitInterval.lean +++ b/Mathlib/Topology/UnitInterval.lean @@ -122,8 +122,6 @@ def symmHomeomorph : I ≃ₜ I where theorem strictAnti_symm : StrictAnti σ := fun _ _ h ↦ sub_lt_sub_left (α := ℝ) h _ -@[deprecated (since := "2024-02-27")] alias involutive_symm := symm_involutive -@[deprecated (since := "2024-02-27")] alias bijective_symm := symm_bijective @[simp] theorem symm_inj {i j : I} : σ i = σ j ↔ i = j := symm_bijective.injective.eq_iff From 3279a44d606aac10f2909dd10d0ece578c78bf2f Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Mon, 6 Jan 2025 11:06:13 +0000 Subject: [PATCH 003/681] feat(CategoryTheory): products in the category of Ind-objects (#20507) Follow-up to #18988. --- .../Limits/Indization/Category.lean | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Limits/Indization/Category.lean b/Mathlib/CategoryTheory/Limits/Indization/Category.lean index c927eac12564d..4de4c45fb1b0f 100644 --- a/Mathlib/CategoryTheory/Limits/Indization/Category.lean +++ b/Mathlib/CategoryTheory/Limits/Indization/Category.lean @@ -8,6 +8,7 @@ import Mathlib.CategoryTheory.Limits.Constructions.Filtered import Mathlib.CategoryTheory.Limits.FullSubcategory import Mathlib.CategoryTheory.Limits.Indization.LocallySmall import Mathlib.CategoryTheory.Limits.Indization.FilteredColimits +import Mathlib.CategoryTheory.Limits.Indization.Products /-! # The category of Ind-objects @@ -24,7 +25,10 @@ Adopting the theorem numbering of [Kashiwara2006], we show that * `C ⥤ Ind C` preserves finite colimits (6.1.6), * if `C` has coproducts indexed by a finite type `α`, then `Ind C` has coproducts indexed by `α` (6.1.18(ii)), -* if `C` has finite coproducts, then `Ind C` has small coproducts (6.1.18(ii)). +* if `C` has finite coproducts, then `Ind C` has small coproducts (6.1.18(ii)), +* if `C` has products indexed by `α`, then `Ind C` has products indexed by `α`, and the functor + `Ind C ⥤ Cᵒᵖ ⥤ Type v` creates such products (6.1.17) +* the functor `C ⥤ Ind C` preserves small limits. More limit-colimit properties will follow. @@ -107,6 +111,23 @@ instance : HasFilteredColimits (Ind C) where HasColimitsOfShape _ _ _ := hasColimitsOfShape_of_hasColimitsOfShape_createsColimitsOfShape (Ind.inclusion C) +noncomputable instance {J : Type v} [HasLimitsOfShape (Discrete J) C] : + CreatesLimitsOfShape (Discrete J) (Ind.inclusion C) := + letI _ : CreatesLimitsOfShape (Discrete J) (fullSubcategoryInclusion (IsIndObject (C := C))) := + createsLimitsOfShapeFullSubcategoryInclusion (closedUnderLimitsOfShape_of_limit + (isIndObject_limit_of_discrete_of_hasLimitsOfShape _)) + inferInstanceAs <| + CreatesLimitsOfShape (Discrete J) ((Ind.equivalence C).functor ⋙ fullSubcategoryInclusion _) + +instance {J : Type v} [HasLimitsOfShape (Discrete J) C] : + HasLimitsOfShape (Discrete J) (Ind C) := + hasLimitsOfShape_of_hasLimitsOfShape_createsLimitsOfShape (Ind.inclusion C) + +instance : PreservesLimits (Ind.yoneda (C := C)) := + letI _ : PreservesLimitsOfSize.{v, v} (Ind.yoneda ⋙ Ind.inclusion C) := + preservesLimits_of_natIso Ind.yonedaCompInclusion.symm + preservesLimits_of_reflects_of_preserves Ind.yoneda (Ind.inclusion C) + theorem Ind.isIndObject_inclusion_obj (X : Ind C) : IsIndObject ((Ind.inclusion C).obj X) := X.2 From 14950c530f22c7bac6bee3168005c16dce3485f2 Mon Sep 17 00:00:00 2001 From: smorel394 Date: Mon, 6 Jan 2025 11:06:14 +0000 Subject: [PATCH 004/681] refactor(CategoryTheory/Limits/Preserves/Ulift): simplify the proof that the universe lifting functor for types preserves all colimits (#20508) The current proof that the universe lifting functor for types preserves all colimits is redundant with the work done in `CategoryTheory.Limits.Types`, in particular with `isColimit_iff_bijective_desc`, as the result actually follows almost immediately from this last statement. This PR simplifies the proof using `isColimit_iff_bijective_desc`. Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- .../Limits/Preserves/Ulift.lean | 99 +++---------------- Mathlib/CategoryTheory/Limits/Types.lean | 52 +++++++++- 2 files changed, 62 insertions(+), 89 deletions(-) diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean b/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean index d2998c6990db4..2b845755423e4 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Dagur Asgeirsson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Dagur Asgeirsson, Junyan Xu +Authors: Dagur Asgeirsson, Junyan Xu, Sophie Morel -/ import Mathlib.CategoryTheory.Limits.Creates import Mathlib.CategoryTheory.Limits.Types @@ -10,11 +10,12 @@ import Mathlib.Data.Set.Subsingleton /-! # `ULift` creates small (co)limits -This file shows that `uliftFunctor.{v, u}` creates (and hence preserves) limits and colimits indexed -by `J` with `[Category.{w, u} J]`. -It also shows that `uliftFunctor.{v, u}` *preserves* "all" limits, -potentially too big to exist in `Type u`). +This file shows that `uliftFunctor.{v, u}` preserves all limits and colimits, including those +potentially too big to exist in `Type u`. + +As this functor is fully faithful, we also deduce that it creates `u`-small limits and +colimits. -/ @@ -37,8 +38,7 @@ def sectionsEquiv {J : Type*} [Category J] (K : J ⥤ Type u) : /-- The functor `uliftFunctor : Type u ⥤ Type (max u v)` preserves limits of arbitrary size. -/ -noncomputable -instance : PreservesLimitsOfSize.{w', w} uliftFunctor.{v, u} where +noncomputable instance : PreservesLimitsOfSize.{w', w} uliftFunctor.{v, u} where preservesLimitsOfShape {J} := { preservesLimit := fun {K} => { preserves := fun {c} hc => by @@ -57,93 +57,16 @@ noncomputable instance : CreatesLimitsOfSize.{w, u} uliftFunctor.{v, u} where variable {J : Type*} [Category J] {K : J ⥤ Type u} {c : Cocone K} (hc : IsColimit c) variable {lc : Cocone (K ⋙ uliftFunctor.{v, u})} -/-- Given a subset of the cocone point of a cocone over the lifted functor, - produce a cocone over the original functor. -/ -def coconeOfSet (ls : Set lc.pt) : Cocone K where - pt := ULift Prop - ι := - { app := fun j x ↦ ⟨lc.ι.app j ⟨x⟩ ∈ ls⟩ - naturality := fun i j f ↦ by dsimp only; rw [← lc.w f]; rfl } - -/-- Given a subset of the cocone point of a cocone over the lifted functor, - produce a subset of the cocone point of a colimit cocone over the original functor. -/ -def descSet (ls : Set lc.pt) : Set c.pt := {x | (hc.desc (coconeOfSet ls) x).down} - -/-- Characterization the map `descSet hc`: the image of an element in a vertex of the original - diagram in the cocone point lies in `descSet hc ls` if and only if the image of the corresponding - element in the lifted diagram lie in `ls`. -/ -lemma descSet_spec (s : Set c.pt) (ls : Set lc.pt) : - descSet hc ls = s ↔ ∀ j x, lc.ι.app j ⟨x⟩ ∈ ls ↔ c.ι.app j x ∈ s := by - refine ⟨?_, fun he ↦ funext fun x ↦ ?_⟩ - · rintro rfl j x - exact (congr_arg ULift.down (congr_fun (hc.fac (coconeOfSet ls) j) x).symm).to_iff - · refine (congr_arg ULift.down (congr_fun (hc.uniq (coconeOfSet ls) (⟨· ∈ s⟩) fun j ↦ ?_) x)).symm - ext y; exact congr_arg ULift.up (propext (he j y).symm) - -lemma mem_descSet_singleton {x : lc.pt} {j : J} {y : K.obj j} : - c.ι.app j y ∈ descSet hc {x} ↔ lc.ι.app j ⟨y⟩ = x := - ((descSet_spec hc _ {x}).mp rfl j y).symm - -variable (lc) - -lemma descSet_univ : descSet hc (@Set.univ lc.pt) = Set.univ := by simp [descSet_spec] - -lemma iUnion_descSet_singleton : ⋃ x : lc.pt, descSet hc {x} = Set.univ := by - rw [← descSet_univ hc lc, eq_comm, descSet_spec] - intro j x - erw [true_iff, Set.mem_iUnion] - use lc.ι.app j ⟨x⟩ - rw [mem_descSet_singleton] - -lemma descSet_empty : descSet hc (∅ : Set lc.pt) = ∅ := by simp [descSet_spec] - -lemma descSet_inter_of_ne (x y : lc.pt) (hn : x ≠ y) : descSet hc {x} ∩ descSet hc {y} = ∅ := by - rw [eq_comm, ← descSet_empty hc lc, descSet_spec] - intro j z - erw [false_iff] - rintro ⟨hx, hy⟩ - rw [mem_descSet_singleton] at hx hy - exact hn (hx ▸ hy) - -lemma existsUnique_mem_descSet (x : c.pt) : ∃! y : lc.pt, x ∈ descSet hc {y} := - existsUnique_of_exists_of_unique - (Set.mem_iUnion.mp <| Set.eq_univ_iff_forall.mp (iUnion_descSet_singleton hc lc) x) - fun y₁ y₂ h₁ h₂ ↦ by_contra fun hn ↦ - Set.eq_empty_iff_forall_not_mem.1 (descSet_inter_of_ne hc lc y₁ y₂ hn) x ⟨h₁, h₂⟩ - -@[deprecated (since := "2024-12-17")] alias exists_unique_mem_descSet := existsUnique_mem_descSet - -/-- Given a colimit cocone in `Type u` and an arbitrary cocone over the diagram lifted to - `Type (max u v)`, produce a function from the cocone point of the colimit cocone to the - cocone point of the other cocone, that witnesses the colimit cocone also being a colimit - in the higher universe. -/ -noncomputable def descFun (x : c.pt) : lc.pt := (existsUnique_mem_descSet hc lc x).exists.choose - -lemma descFun_apply_spec {x : c.pt} {y : lc.pt} : descFun hc lc x = y ↔ x ∈ descSet hc {y} := - have hu := existsUnique_mem_descSet hc lc x - have hm := hu.exists.choose_spec - ⟨fun he ↦ he ▸ hm, hu.unique hm⟩ - -lemma descFun_spec (f : c.pt → lc.pt) : - f = descFun hc lc ↔ ∀ j, f ∘ c.ι.app j = lc.ι.app j ∘ ULift.up := by - refine ⟨?_, fun he ↦ funext fun x ↦ ((descFun_apply_spec hc lc).mpr ?_).symm⟩ - · rintro rfl j; ext - apply (descFun_apply_spec hc lc).mpr - rw [mem_descSet_singleton]; rfl - · rw [← (jointly_surjective_of_isColimit hc x).choose_spec.choose_spec, mem_descSet_singleton] - exact (congr_fun (he _) _).symm - /-- The functor `uliftFunctor : Type u ⥤ Type (max u v)` preserves colimits of arbitrary size. -/ noncomputable instance : PreservesColimitsOfSize.{w', w} uliftFunctor.{v, u} where preservesColimitsOfShape {J _} := { preservesColimit := fun {F} ↦ - { preserves := fun {c} hc ↦ ⟨{ - desc := fun lc x ↦ descFun hc lc x.down - fac := fun lc j ↦ by ext ⟨⟩; apply congr_fun ((descFun_spec hc lc _).mp rfl j) - uniq := fun lc f hf ↦ by ext ⟨⟩; apply congr_fun ((descFun_spec hc lc (f ∘ ULift.up)).mpr - fun j ↦ funext fun y ↦ congr_fun (hf j) ⟨y⟩) }⟩ } } + { preserves := fun {c} hc ↦ by + rw [isColimit_iff_bijective_desc, ← Function.Bijective.of_comp_iff _ + (quotQuotUliftEquiv F).bijective, Quot.desc_quotQuotUliftEquiv] + exact ULift.up_bijective.comp ((isColimit_iff_bijective_desc c).mp (Nonempty.intro hc)) } } /-- The functor `uliftFunctor : Type u ⥤ Type (max u v)` creates `u`-small colimits. diff --git a/Mathlib/CategoryTheory/Limits/Types.lean b/Mathlib/CategoryTheory/Limits/Types.lean index 0eff7c3add87e..fd38583178553 100644 --- a/Mathlib/CategoryTheory/Limits/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Types.lean @@ -23,7 +23,7 @@ and the type `lim Hom(F·, X)`. open CategoryTheory CategoryTheory.Limits -universe v u w +universe u' v u w namespace CategoryTheory.Limits @@ -357,6 +357,56 @@ lemma Quot.ι_desc (j : J) (x : F.obj j) : Quot.desc c (Quot.ι F j x) = c.ι.ap lemma Quot.map_ι {j j' : J} {f : j ⟶ j'} (x : F.obj j) : Quot.ι F j' (F.map f x) = Quot.ι F j x := (Quot.sound ⟨f, rfl⟩).symm +/-- +The obvious map from `Quot F` to `Quot (F ⋙ uliftFunctor.{u'})`. +-/ +def quotToQuotUlift (F : J ⥤ Type u) : Quot F → Quot (F ⋙ uliftFunctor.{u'}) := by + refine Quot.lift (fun ⟨j, x⟩ ↦ Quot.ι _ j (ULift.up x)) ?_ + intro ⟨j, x⟩ ⟨j', y⟩ ⟨(f : j ⟶ j'), (eq : y = F.map f x)⟩ + dsimp + have eq : ULift.up y = (F ⋙ uliftFunctor.{u'}).map f (ULift.up x) := by + rw [eq] + dsimp + rw [eq, Quot.map_ι] + +@[simp] +lemma quotToQuotUlift_ι (F : J ⥤ Type u) (j : J) (x : F.obj j) : + quotToQuotUlift F (Quot.ι F j x) = Quot.ι _ j (ULift.up x) := by + dsimp [quotToQuotUlift, Quot.ι] + +/-- +The obvious map from `Quot (F ⋙ uliftFunctor.{u'})` to `Quot F`. +-/ +def quotUliftToQuot (F : J ⥤ Type u) : Quot (F ⋙ uliftFunctor.{u'}) → Quot F := + Quot.lift (fun ⟨j, x⟩ ↦ Quot.ι _ j x.down) + (fun ⟨_, x⟩ ⟨_, y⟩ ⟨f, (eq : y = ULift.up (F.map f x.down))⟩ ↦ by simp [eq, Quot.map_ι]) + +@[simp] +lemma quotUliftToQuot_ι (F : J ⥤ Type u) (j : J) (x : (F ⋙ uliftFunctor.{u'}).obj j) : + quotUliftToQuot F (Quot.ι _ j x) = Quot.ι F j x.down := by + dsimp [quotUliftToQuot, Quot.ι] + +/-- +The equivalence between `Quot F` and `Quot (F ⋙ uliftFunctor.{u'})`. +-/ +@[simp] +def quotQuotUliftEquiv (F : J ⥤ Type u) : Quot F ≃ Quot (F ⋙ uliftFunctor.{u'}) where + toFun := quotToQuotUlift F + invFun := quotUliftToQuot F + left_inv x := by + obtain ⟨j, y, rfl⟩ := Quot.jointly_surjective x + rw [quotToQuotUlift_ι, quotUliftToQuot_ι] + right_inv x := by + obtain ⟨j, y, rfl⟩ := Quot.jointly_surjective x + rw [quotUliftToQuot_ι, quotToQuotUlift_ι] + rfl + +lemma Quot.desc_quotQuotUliftEquiv {F : J ⥤ Type u} (c : Cocone F) : + Quot.desc (uliftFunctor.{u'}.mapCocone c) ∘ quotQuotUliftEquiv F = ULift.up ∘ Quot.desc c := by + ext x + obtain ⟨_, _, rfl⟩ := Quot.jointly_surjective x + dsimp + /-- (implementation detail) A function `Quot F → α` induces a cocone on `F` as long as the universes work out. -/ @[simps] From e58d5d7294c575f1d97908377baa540bcf193787 Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Mon, 6 Jan 2025 11:22:24 +0000 Subject: [PATCH 005/681] chore(RingTheory/Finiteness): rename Module.Finite.out (#20506) Right now it's impossible to do ``` -- finite projective modules class IsFiniteProjective extends Module.Projective R M, Module.Finite R M : Prop where -- oops ``` because of a nameclash (both axioms are called `out`). --- Mathlib/Algebra/Module/FinitePresentation.lean | 8 ++++---- Mathlib/Algebra/Module/Torsion.lean | 2 +- Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean | 2 +- Mathlib/RingTheory/Artinian/Module.lean | 2 +- Mathlib/RingTheory/Finiteness/Basic.lean | 4 ++-- Mathlib/RingTheory/Finiteness/Defs.lean | 6 +++--- Mathlib/RingTheory/Finiteness/Nilpotent.lean | 2 +- Mathlib/RingTheory/Finiteness/TensorProduct.lean | 4 ++-- Mathlib/RingTheory/Flat/EquationalCriterion.lean | 2 +- Mathlib/RingTheory/LocalProperties/Projective.lean | 2 +- Mathlib/RingTheory/LocalRing/Module.lean | 4 ++-- Mathlib/RingTheory/Nakayama.lean | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Mathlib/Algebra/Module/FinitePresentation.lean b/Mathlib/Algebra/Module/FinitePresentation.lean index 468b2cc116e18..f956657b81585 100644 --- a/Mathlib/Algebra/Module/FinitePresentation.lean +++ b/Mathlib/Algebra/Module/FinitePresentation.lean @@ -187,7 +187,7 @@ lemma Module.FinitePresentation.fg_ker [Module.Finite R M] exact ⟨_, hy, by simp⟩ apply Submodule.fg_of_fg_map_of_fg_inf_ker f.range.mkQ · rw [this] - exact Module.Finite.out + exact Module.Finite.fg_top · rw [Submodule.ker_mkQ, inf_comm, ← Submodule.map_comap_eq, ← LinearMap.ker_comp, hf] exact hs'.map f @@ -201,8 +201,8 @@ lemma Module.finitePresentation_of_ker [Module.FinitePresentation R N] Module.FinitePresentation R M := by obtain ⟨s, hs⟩ : (⊤ : Submodule R M).FG := by apply Submodule.fg_of_fg_map_of_fg_inf_ker l - · rw [Submodule.map_top, LinearMap.range_eq_top.mpr hl]; exact Module.Finite.out - · rw [top_inf_eq, ← Submodule.fg_top]; exact Module.Finite.out + · rw [Submodule.map_top, LinearMap.range_eq_top.mpr hl]; exact Module.Finite.fg_top + · rw [top_inf_eq, ← Submodule.fg_top]; exact Module.Finite.fg_top refine ⟨s, hs, ?_⟩ let π := Finsupp.linearCombination R ((↑) : s → M) have H : Function.Surjective π := @@ -250,7 +250,7 @@ instance {A} [CommRing A] [Algebra R A] [Module.FinitePresentation R M] : apply Submodule.FG.map have : Module.Finite R (LinearMap.ker f) := ⟨(Submodule.fg_top _).mpr (Module.FinitePresentation.fg_ker f hf)⟩ - exact Module.Finite.out (R := A) (M := A ⊗[R] LinearMap.ker f) + exact Module.Finite.fg_top (R := A) (M := A ⊗[R] LinearMap.ker f) open TensorProduct in lemma FinitePresentation.of_isBaseChange diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index 08b33bcef771a..c7ce5c683b548 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -691,7 +691,7 @@ variable {R M} theorem _root_.Submodule.annihilator_top_inter_nonZeroDivisors [Module.Finite R M] (hM : Module.IsTorsion R M) : ((⊤ : Submodule R M).annihilator : Set R) ∩ R⁰ ≠ ∅ := by - obtain ⟨S, hS⟩ := ‹Module.Finite R M›.out + obtain ⟨S, hS⟩ := ‹Module.Finite R M›.fg_top refine Set.Nonempty.ne_empty ⟨_, ?_, (∏ x ∈ S, (@hM x).choose : R⁰).prop⟩ rw [Submonoid.coe_finset_prod, SetLike.mem_coe, ← hS, mem_annihilator_span] intro n diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean index a6138962526ff..db92f36bbab1d 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean @@ -210,7 +210,7 @@ theorem LinearMap.exists_monic_and_coeff_mem_pow_and_aeval_eq_zero_of_range_le_s cases subsingleton_or_nontrivial R · exact ⟨0, Polynomial.monic_of_subsingleton _, by simp⟩ obtain ⟨s : Finset M, hs : Submodule.span R (s : Set M) = ⊤⟩ := - Module.Finite.out (R := R) (M := M) + Module.Finite.fg_top (R := R) (M := M) -- Porting note: `H` was `rfl` obtain ⟨A, H, h⟩ := Matrix.isRepresentation.toEnd_exists_mem_ideal R ((↑) : s → M) diff --git a/Mathlib/RingTheory/Artinian/Module.lean b/Mathlib/RingTheory/Artinian/Module.lean index 53f91c83eee98..61c8771b69611 100644 --- a/Mathlib/RingTheory/Artinian/Module.lean +++ b/Mathlib/RingTheory/Artinian/Module.lean @@ -390,7 +390,7 @@ theorem isArtinian_of_fg_of_artinian {R M} [Ring R] [AddCommGroup M] [Module R M instance isArtinian_of_fg_of_artinian' {R M} [Ring R] [AddCommGroup M] [Module R M] [IsArtinianRing R] [Module.Finite R M] : IsArtinian R M := - have : IsArtinian R (⊤ : Submodule R M) := isArtinian_of_fg_of_artinian _ Module.Finite.out + have : IsArtinian R (⊤ : Submodule R M) := isArtinian_of_fg_of_artinian _ Module.Finite.fg_top isArtinian_of_linearEquiv (LinearEquiv.ofTop (⊤ : Submodule R M) rfl) theorem IsArtinianRing.of_finite (R S) [CommRing R] [Ring S] [Algebra R S] diff --git a/Mathlib/RingTheory/Finiteness/Basic.lean b/Mathlib/RingTheory/Finiteness/Basic.lean index 73248997ca909..bb1058f07fbc1 100644 --- a/Mathlib/RingTheory/Finiteness/Basic.lean +++ b/Mathlib/RingTheory/Finiteness/Basic.lean @@ -251,13 +251,13 @@ theorem equiv_iff (e : M ≃ₗ[R] N) : Module.Finite R M ↔ Module.Finite R N instance ulift [Module.Finite R M] : Module.Finite R (ULift M) := equiv ULift.moduleEquiv.symm -theorem iff_fg {N : Submodule R M} : Module.Finite R N ↔ N.FG := Module.finite_def.trans (fg_top _) +theorem iff_fg {N : Submodule R M} : Module.Finite R N ↔ N.FG := Module.finite_def.trans N.fg_top variable (R M) instance bot : Module.Finite R (⊥ : Submodule R M) := iff_fg.mpr fg_bot -instance top [Module.Finite R M] : Module.Finite R (⊤ : Submodule R M) := iff_fg.mpr out +instance top [Module.Finite R M] : Module.Finite R (⊤ : Submodule R M) := iff_fg.mpr fg_top variable {M} diff --git a/Mathlib/RingTheory/Finiteness/Defs.lean b/Mathlib/RingTheory/Finiteness/Defs.lean index fd8c45bb0be8d..9c52d2ce2bd80 100644 --- a/Mathlib/RingTheory/Finiteness/Defs.lean +++ b/Mathlib/RingTheory/Finiteness/Defs.lean @@ -103,9 +103,9 @@ variable (R A B M N : Type*) /-- A module over a semiring is `Module.Finite` if it is finitely generated as a module. -/ protected class Module.Finite [Semiring R] [AddCommMonoid M] [Module R M] : Prop where - out : (⊤ : Submodule R M).FG + fg_top : (⊤ : Submodule R M).FG -attribute [inherit_doc Module.Finite] Module.Finite.out +attribute [inherit_doc Module.Finite] Module.Finite.fg_top namespace Module @@ -131,7 +131,7 @@ variable {R M N} /-- See also `Module.Finite.exists_fin'`. -/ lemma exists_fin [Module.Finite R M] : ∃ (n : ℕ) (s : Fin n → M), Submodule.span R (range s) = ⊤ := - Submodule.fg_iff_exists_fin_generating_family.mp out + Submodule.fg_iff_exists_fin_generating_family.mp fg_top end Finite diff --git a/Mathlib/RingTheory/Finiteness/Nilpotent.lean b/Mathlib/RingTheory/Finiteness/Nilpotent.lean index 17b91ef86e77f..b2e0915fb0405 100644 --- a/Mathlib/RingTheory/Finiteness/Nilpotent.lean +++ b/Mathlib/RingTheory/Finiteness/Nilpotent.lean @@ -20,7 +20,7 @@ namespace Finite theorem Module.End.isNilpotent_iff_of_finite [Module.Finite R M] {f : End R M} : IsNilpotent f ↔ ∀ m : M, ∃ n : ℕ, (f ^ n) m = 0 := by refine ⟨fun ⟨n, hn⟩ m ↦ ⟨n, by simp [hn]⟩, fun h ↦ ?_⟩ - rcases Module.Finite.out (R := R) (M := M) with ⟨S, hS⟩ + rcases Module.Finite.fg_top (R := R) (M := M) with ⟨S, hS⟩ choose g hg using h use Finset.sup S g ext m diff --git a/Mathlib/RingTheory/Finiteness/TensorProduct.lean b/Mathlib/RingTheory/Finiteness/TensorProduct.lean index e1a686b2c3209..abfabac2a55e3 100644 --- a/Mathlib/RingTheory/Finiteness/TensorProduct.lean +++ b/Mathlib/RingTheory/Finiteness/TensorProduct.lean @@ -85,7 +85,7 @@ noncomputable local instance instance Module.Finite.base_change [CommSemiring R] [Semiring A] [Algebra R A] [AddCommMonoid M] [Module R M] [h : Module.Finite R M] : Module.Finite A (TensorProduct R A M) := by classical - obtain ⟨s, hs⟩ := h.out + obtain ⟨s, hs⟩ := h.fg_top refine ⟨⟨s.image (TensorProduct.mk R A M 1), eq_top_iff.mpr ?_⟩⟩ rintro x - induction x with @@ -103,7 +103,7 @@ instance Module.Finite.base_change [CommSemiring R] [Semiring A] [Algebra R A] [ instance Module.Finite.tensorProduct [CommSemiring R] [AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] [hM : Module.Finite R M] [hN : Module.Finite R N] : Module.Finite R (TensorProduct R M N) where - out := (TensorProduct.map₂_mk_top_top_eq_top R M N).subst (hM.out.map₂ _ hN.out) + fg_top := (TensorProduct.map₂_mk_top_top_eq_top R M N).subst (hM.fg_top.map₂ _ hN.fg_top) end ModuleAndAlgebra diff --git a/Mathlib/RingTheory/Flat/EquationalCriterion.lean b/Mathlib/RingTheory/Flat/EquationalCriterion.lean index 763d9dc2c83db..df38f6aa41c23 100644 --- a/Mathlib/RingTheory/Flat/EquationalCriterion.lean +++ b/Mathlib/RingTheory/Flat/EquationalCriterion.lean @@ -273,7 +273,7 @@ theorem exists_factorization_of_comp_eq_zero_of_free [Flat R M] {K N : Type u} [ use κ₂, hκ₂, a₂ ∘ₗ a₁, y₂ simp_rw [comp_assoc] exact ⟨trivial, sup_le (ha₁.trans (ker_le_ker_comp _ _)) ha₂⟩ - convert this ⊤ Finite.out + convert this ⊤ Finite.fg_top simp only [top_le_iff, ker_eq_top] /-- Every homomorphism from a finitely presented module to a flat module factors through a finite diff --git a/Mathlib/RingTheory/LocalProperties/Projective.lean b/Mathlib/RingTheory/LocalProperties/Projective.lean index bf3d45d29deed..dc9a8726d2715 100644 --- a/Mathlib/RingTheory/LocalProperties/Projective.lean +++ b/Mathlib/RingTheory/LocalProperties/Projective.lean @@ -121,7 +121,7 @@ theorem Module.projective_of_localization_maximal (H : ∀ (I : Ideal R) (_ : I. Module.Projective (Localization.AtPrime I) (LocalizedModule I.primeCompl M)) [Module.FinitePresentation R M] : Module.Projective R M := by have : Module.Finite R M := by infer_instance - have : (⊤ : Submodule R M).FG := this.out + have : (⊤ : Submodule R M).FG := this.fg_top have : ∃ (s : Finset M), _ := this obtain ⟨s, hs⟩ := this let N := s →₀ R diff --git a/Mathlib/RingTheory/LocalRing/Module.lean b/Mathlib/RingTheory/LocalRing/Module.lean index 8aec28a9bca3d..fdc9bee0bd9c1 100644 --- a/Mathlib/RingTheory/LocalRing/Module.lean +++ b/Mathlib/RingTheory/LocalRing/Module.lean @@ -61,7 +61,7 @@ theorem map_mkQ_eq {N₁ N₂ : Submodule R M} (h : N₁ ≤ N₂) (h' : N₂.FG theorem map_mkQ_eq_top {N : Submodule R M} [Module.Finite R M] : N.map (Submodule.mkQ (𝔪 • ⊤)) = ⊤ ↔ N = ⊤ := by - rw [← map_mkQ_eq (N₁ := N) le_top Module.Finite.out, Submodule.map_top, Submodule.range_mkQ] + rw [← map_mkQ_eq (N₁ := N) le_top Module.Finite.fg_top, Submodule.map_top, Submodule.range_mkQ] theorem map_tensorProduct_mk_eq_top {N : Submodule R M} [Module.Finite R M] : N.map (TensorProduct.mk R k M 1) = ⊤ ↔ N = ⊤ := by @@ -267,7 +267,7 @@ theorem free_of_lTensor_residueField_injective (hg : Surjective g) (h : Exact f (hf : Function.Injective (f.lTensor k)) : Module.Free R P := by have := Module.finitePresentation_of_free_of_surjective g hg - (by rw [h.linearMap_ker_eq, LinearMap.range_eq_map]; exact (Module.Finite.out).map f) + (by rw [h.linearMap_ker_eq, LinearMap.range_eq_map]; exact (Module.Finite.fg_top).map f) apply free_of_maximalIdeal_rTensor_injective rw [← LinearMap.lTensor_inj_iff_rTensor_inj] apply lTensor_injective_of_exact_of_exact_of_rTensor_injective diff --git a/Mathlib/RingTheory/Nakayama.lean b/Mathlib/RingTheory/Nakayama.lean index 0227b2a554422..ad4d01141b8f1 100644 --- a/Mathlib/RingTheory/Nakayama.lean +++ b/Mathlib/RingTheory/Nakayama.lean @@ -84,7 +84,7 @@ lemma eq_bot_of_set_smul_eq_of_subset_jacobson_annihilator {s : Set R} lemma top_ne_ideal_smul_of_le_jacobson_annihilator [Nontrivial M] [Module.Finite R M] {I} (h : I ≤ (Module.annihilator R M).jacobson) : (⊤ : Submodule R M) ≠ I • ⊤ := fun H => top_ne_bot <| - eq_bot_of_eq_ideal_smul_of_le_jacobson_annihilator Module.Finite.out H <| + eq_bot_of_eq_ideal_smul_of_le_jacobson_annihilator Module.Finite.fg_top H <| (congrArg (I ≤ Ideal.jacobson ·) annihilator_top).mpr h open Pointwise in From ae4ed0224c0525a639077956f6520becf0114f7e Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 6 Jan 2025 11:55:12 +0000 Subject: [PATCH 006/681] feat(Topology/Algebra/InfiniteSum/NatInt): Add pnat lems (#16544) Add some basic results about tsums indexed by pnat. Co-authored-by: Chris Birkbeck --- Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean index d1448d49fe4b3..662314f0bb691 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean @@ -514,3 +514,16 @@ lemma multipliable_int_iff_multipliable_nat_and_neg {f : ℤ → G} : end UniformGroup end Int + +section pnat + +@[to_additive] +theorem pnat_multipliable_iff_multipliable_succ {α : Type*} [TopologicalSpace α] [CommMonoid α] + {f : ℕ → α} : Multipliable (fun x : ℕ+ => f x) ↔ Multipliable fun x : ℕ => f (x + 1) := + Equiv.pnatEquivNat.symm.multipliable_iff.symm + +@[to_additive] +theorem tprod_pnat_eq_tprod_succ {α : Type*} [TopologicalSpace α] [CommMonoid α] (f : ℕ → α) : + ∏' n : ℕ+, f n = ∏' n, f (n + 1) := (Equiv.pnatEquivNat.symm.tprod_eq _).symm + +end pnat From 5b6f2c614086f75cce987fd1f75deefbae4b43bf Mon Sep 17 00:00:00 2001 From: smorel394 Date: Mon, 6 Jan 2025 12:15:39 +0000 Subject: [PATCH 007/681] refactor(Algebra/Category/Grp/Colimits): change the construction of colimits in `AddCommGrp` (#20474) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old version of this file has a remark saying "TODO: In fact, in `AddCommGrp` there is a much nicer model of colimits as quotients of finitely supported functions, and we really should implement this as well (or instead)." This PR does precisely this (choosing the "instead" option). In fact, given a functor `F : J ⥤ AddCommGrp.{w}`, it constructs a candidate for the colimit of `F` as a quotient of `DFinsupp (fun j ↦ F.obj j)`, without any smallness assumptions on `J`. It then proves that this quotient is a colimit of `F` if it is `w`-small, then deduces that `AddCommGrp.{w}` has all small colimits. Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Algebra/Category/Grp/Colimits.lean | 352 ++++++++---------- Mathlib/Algebra/Homology/LocalCohomology.lean | 4 +- Mathlib/Data/DFinsupp/Small.lean | 28 ++ 4 files changed, 176 insertions(+), 209 deletions(-) create mode 100644 Mathlib/Data/DFinsupp/Small.lean diff --git a/Mathlib.lean b/Mathlib.lean index f692eadfdec90..99606d29a64b3 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2456,6 +2456,7 @@ import Mathlib.Data.DFinsupp.NeLocus import Mathlib.Data.DFinsupp.Notation import Mathlib.Data.DFinsupp.Order import Mathlib.Data.DFinsupp.Sigma +import Mathlib.Data.DFinsupp.Small import Mathlib.Data.DFinsupp.Submonoid import Mathlib.Data.DFinsupp.WellFounded import Mathlib.Data.DList.Instances diff --git a/Mathlib/Algebra/Category/Grp/Colimits.lean b/Mathlib/Algebra/Category/Grp/Colimits.lean index 1164b843e4f0b..a7d7824126397 100644 --- a/Mathlib/Algebra/Category/Grp/Colimits.lean +++ b/Mathlib/Algebra/Category/Grp/Colimits.lean @@ -1,37 +1,29 @@ /- Copyright (c) 2019 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kim Morrison +Authors: Kim Morrison, Sophie Morel -/ import Mathlib.Algebra.Category.Grp.Preadditive -import Mathlib.CategoryTheory.Limits.Shapes.Kernels -import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits +import Mathlib.Algebra.Equiv.TransferInstance import Mathlib.CategoryTheory.ConcreteCategory.Elementwise +import Mathlib.Data.DFinsupp.BigOperators +import Mathlib.Data.DFinsupp.Small import Mathlib.GroupTheory.QuotientGroup.Defs - /-! # The category of additive commutative groups has all colimits. -This file uses a "pre-automated" approach, just as for `Algebra.Category.MonCat.Colimits`. -It is a very uniform approach, that conceivably could be synthesised directly -by a tactic that analyses the shape of `AddCommGroup` and `MonoidHom`. +This file constructs colimits in the categpry of additive commutative groups, as +quotients of finitely supported functions. -TODO: -In fact, in `AddCommGrp` there is a much nicer model of colimits as quotients -of finitely supported functions, and we really should implement this as well (or instead). -/ - universe w u v open CategoryTheory Limits --- [ROBOT VOICE]: --- You should pretend for now that this file was automatically generated. --- It follows the same template as colimits in Mon. namespace AddCommGrp -variable {J : Type u} [Category.{v} J] (F : J ⥤ AddCommGrp.{max u v w}) +variable {J : Type u} [Category.{v} J] (F : J ⥤ AddCommGrp.{w}) namespace Colimits @@ -42,220 +34,168 @@ then taking the quotient by the abelian group laws within each abelian group, and the identifications given by the morphisms in the diagram. -/ -/-- An inductive type representing all group expressions (without relations) -on a collection of types indexed by the objects of `J`. --/ -inductive Prequotient - -- There's always `of` - | of : ∀ (j : J) (_ : F.obj j), Prequotient - -- Then one generator for each operation - | zero : Prequotient - | neg : Prequotient → Prequotient - | add : Prequotient → Prequotient → Prequotient - -instance : Inhabited (Prequotient.{w} F) := - ⟨Prequotient.zero⟩ - -open Prequotient - -/-- The relation on `Prequotient` saying when two expressions are equal -because of the abelian group laws, or -because one element is mapped to another by a morphism in the diagram. +/-- +The relations between elements of the direct sum of the `F.obj j` given by the +morphisms in the diagram `J`. -/ -inductive Relation : Prequotient.{w} F → Prequotient.{w} F → Prop - -- Make it an equivalence relation: - | refl : ∀ x, Relation x x - | symm : ∀ (x y) (_ : Relation x y), Relation y x - | trans : ∀ (x y z) (_ : Relation x y) (_ : Relation y z), Relation x z - -- There's always a `map` relation - | map : ∀ (j j' : J) (f : j ⟶ j') (x : F.obj j), Relation (Prequotient.of j' (F.map f x)) - (Prequotient.of j x) - -- Then one relation per operation, describing the interaction with `of` - | zero : ∀ j, Relation (Prequotient.of j 0) zero - | neg : ∀ (j) (x : F.obj j), Relation (Prequotient.of j (-x)) (neg (Prequotient.of j x)) - | add : ∀ (j) (x y : F.obj j), Relation (Prequotient.of j (x + y)) (add (Prequotient.of j x) - (Prequotient.of j y)) - -- Then one relation per argument of each operation - | neg_1 : ∀ (x x') (_ : Relation x x'), Relation (neg x) (neg x') - | add_1 : ∀ (x x' y) (_ : Relation x x'), Relation (add x y) (add x' y) - | add_2 : ∀ (x y y') (_ : Relation y y'), Relation (add x y) (add x y') - -- And one relation per axiom - | zero_add : ∀ x, Relation (add zero x) x - | add_zero : ∀ x, Relation (add x zero) x - | neg_add_cancel : ∀ x, Relation (add (neg x) x) zero - | add_comm : ∀ x y, Relation (add x y) (add y x) - | add_assoc : ∀ x y z, Relation (add (add x y) z) (add x (add y z)) +abbrev Relations [DecidableEq J] : AddSubgroup (DFinsupp (fun j ↦ F.obj j)) := + AddSubgroup.closure {x | ∃ (j j' : J) (u : j ⟶ j') (a : F.obj j), + x = DFinsupp.single j' (F.map u a) - DFinsupp.single j a} /-- -The setoid corresponding to group expressions modulo abelian group relations and identifications. +The candidate for the colimit of `F`, defined as the quotient of the direct sum +of the commutative groups `F.obj j` by the relations given by the morphisms in +the diagram. -/ -def colimitSetoid : Setoid (Prequotient.{w} F) where - r := Relation F - iseqv := ⟨Relation.refl, fun r => Relation.symm _ _ r, fun r => Relation.trans _ _ _ r⟩ +def Quot [DecidableEq J] : Type (max u w) := + DFinsupp (fun j ↦ F.obj j) ⧸ Relations F -attribute [instance] colimitSetoid +instance [DecidableEq J] : AddCommGroup (Quot F) := + QuotientAddGroup.Quotient.addCommGroup (Relations F) -/-- The underlying type of the colimit of a diagram in `AddCommGrp`. +/-- Inclusion of `F.obj j` into the candidate colimit. -/ -def ColimitType : Type max u v w := - Quotient (colimitSetoid.{w} F) - -instance : Zero (ColimitType.{w} F) where - zero := Quotient.mk _ zero - -instance : Neg (ColimitType.{w} F) where - neg := Quotient.map neg Relation.neg_1 - -instance : Add (ColimitType.{w} F) where - add := Quotient.map₂ add <| fun _x x' rx y _y' ry => - Setoid.trans (Relation.add_1 _ _ y rx) (Relation.add_2 x' _ _ ry) - -instance : AddCommGroup (ColimitType.{w} F) where - zero_add := Quotient.ind <| fun _ => Quotient.sound <| Relation.zero_add _ - add_zero := Quotient.ind <| fun _ => Quotient.sound <| Relation.add_zero _ - neg_add_cancel := Quotient.ind <| fun _ => Quotient.sound <| Relation.neg_add_cancel _ - add_comm := Quotient.ind₂ <| fun _ _ => Quotient.sound <| Relation.add_comm _ _ - add_assoc := Quotient.ind <| fun _ => Quotient.ind₂ <| fun _ _ => - Quotient.sound <| Relation.add_assoc _ _ _ - nsmul := nsmulRec - zsmul := zsmulRec - -instance ColimitTypeInhabited : Inhabited (ColimitType.{w} F) := ⟨0⟩ - -@[simp] -theorem quot_zero : Quot.mk Setoid.r zero = (0 : ColimitType.{w} F) := - rfl +def Quot.ι [DecidableEq J] (j : J) : F.obj j →+ Quot F := + (QuotientAddGroup.mk' _).comp (DFinsupp.singleAddHom (fun j ↦ F.obj j) j) + +lemma Quot.addMonoidHom_ext [DecidableEq J] {α : Type*} [AddMonoid α] {f g : Quot F →+ α} + (h : ∀ (j : J) (x : F.obj j), f (Quot.ι F j x) = g (Quot.ι F j x)) : f = g := + QuotientAddGroup.addMonoidHom_ext _ (DFinsupp.addHom_ext h) + +variable (c : Cocone F) + +/-- (implementation detail) Part of the universal property of the colimit cocone, but without + assuming that `Quot F` lives in the correct universe. -/ +def Quot.desc [DecidableEq J] : Quot.{w} F →+ c.pt := by + refine QuotientAddGroup.lift _ (DFinsupp.sumAddHom c.ι.app) ?_ + dsimp + rw [AddSubgroup.closure_le] + intro _ ⟨_, _, _, _, eq⟩ + rw [eq] + simp only [SetLike.mem_coe, AddMonoidHom.mem_ker, map_sub, DFinsupp.sumAddHom_single] + change (F.map _ ≫ c.ι.app _) _ - _ = 0 + rw [c.ι.naturality] + simp only [Functor.const_obj_obj, Functor.const_obj_map, Category.comp_id, sub_self] @[simp] -theorem quot_neg (x) : - -- Porting note: force Lean to treat `ColimitType F` no as `Quot _` - (by exact Quot.mk Setoid.r (neg x) : ColimitType.{w} F) = - -(by exact Quot.mk Setoid.r x) := - rfl +lemma Quot.ι_desc [DecidableEq J] (j : J) (x : F.obj j) : + Quot.desc F c (Quot.ι F j x) = c.ι.app j x := by + dsimp [desc, ι] + erw [QuotientAddGroup.lift_mk'] + simp @[simp] -theorem quot_add (x y) : - (by exact Quot.mk Setoid.r (add x y) : ColimitType.{w} F) = - -- Porting note: force Lean to treat `ColimitType F` no as `Quot _` - (by exact Quot.mk Setoid.r x) + (by exact Quot.mk Setoid.r y) := - rfl - -/-- The bundled abelian group giving the colimit of a diagram. -/ -def colimit : AddCommGrp := - AddCommGrp.of (ColimitType.{w} F) - -/-- The function from a given abelian group in the diagram to the colimit abelian group. -/ -def coconeFun (j : J) (x : F.obj j) : ColimitType.{w} F := - Quot.mk _ (Prequotient.of j x) - -/-- The group homomorphism from a given abelian group in the diagram to the colimit abelian -group. -/ -def coconeMorphism (j : J) : F.obj j ⟶ colimit.{w} F where - toFun := coconeFun F j - map_zero' := by apply Quot.sound; apply Relation.zero - map_add' := by intros; apply Quot.sound; apply Relation.add +lemma Quot.map_ι [DecidableEq J] {j j' : J} {f : j ⟶ j'} (x : F.obj j) : + Quot.ι F j' (F.map f x) = Quot.ι F j x := by + dsimp [ι] + refine eq_of_sub_eq_zero ?_ + erw [← (QuotientAddGroup.mk' (Relations F)).map_sub, ← AddMonoidHom.mem_ker] + rw [QuotientAddGroup.ker_mk'] + simp only [DFinsupp.singleAddHom_apply] + exact AddSubgroup.subset_closure ⟨j, j', f, x, rfl⟩ + +/-- (implementation detail) A morphism of commutative additive groups `Quot F →+ A` +induces a cocone on `F` as long as the universes work out. +-/ +@[simps] +def toCocone [DecidableEq J] {A : Type w} [AddCommGroup A] (f : Quot F →+ A) : Cocone F where + pt := AddCommGrp.of A + ι := { app := fun j => f.comp (Quot.ι F j) } + +lemma Quot.desc_toCocone_desc [DecidableEq J] {A : Type w} [AddCommGroup A] (f : Quot F →+ A) + (hc : IsColimit c) : (hc.desc (toCocone F f)).comp (Quot.desc F c) = f := by + refine Quot.addMonoidHom_ext F (fun j x ↦ ?_) + rw [AddMonoidHom.comp_apply, ι_desc] + change (c.ι.app j ≫ hc.desc (toCocone F f)) _ = _ + rw [hc.fac] + simp + +lemma Quot.desc_toCocone_desc_app [DecidableEq J] {A : Type w} [AddCommGroup A] (f : Quot F →+ A) + (hc : IsColimit c) (x : Quot F) : hc.desc (toCocone F f) (Quot.desc F c x) = f x := by + conv_rhs => rw [← Quot.desc_toCocone_desc F c f hc] + dsimp -@[simp] -theorem cocone_naturality {j j' : J} (f : j ⟶ j') : - F.map f ≫ coconeMorphism.{w} F j' = coconeMorphism F j := by - ext - apply Quot.sound - apply Relation.map +/-- +If `c` is a cocone of `F` such that `Quot.desc F c` is bijective, then `c` is a colimit +cocone of `F`. +-/ +noncomputable def isColimit_of_bijective_desc [DecidableEq J] + (h : Function.Bijective (Quot.desc F c)) : IsColimit c where + desc s := AddCommGrp.ofHom ((Quot.desc F s).comp (AddEquiv.ofBijective + (Quot.desc F c) h).symm.toAddMonoidHom) + fac s j := by + ext x + dsimp + conv_lhs => erw [← Quot.ι_desc F c j x] + rw [← AddEquiv.ofBijective_apply _ h, AddEquiv.symm_apply_apply] + simp only [Quot.ι_desc, Functor.const_obj_obj] + uniq s m hm := by + ext x + obtain ⟨x, rfl⟩ := h.2 x + dsimp + rw [← AddEquiv.ofBijective_apply _ h, AddEquiv.symm_apply_apply] + suffices eq : m.comp (AddEquiv.ofBijective (Quot.desc F c) h) = Quot.desc F s by + rw [← eq]; rfl + exact Quot.addMonoidHom_ext F (by simp [← hm]) + +/-- (internal implementation) The colimit cocone of a functor `F`, implemented as a quotient of +`DFinsupp (fun j ↦ F.obj j)`, under the assumption that said quotient is small. +-/ +@[simps] +noncomputable def colimitCocone [DecidableEq J] [Small.{w} (Quot.{w} F)] : Cocone F where + pt := AddCommGrp.of (Shrink (Quot F)) + ι := + { app j := + AddCommGrp.ofHom (Shrink.addEquiv.symm.toAddMonoidHom.comp (Quot.ι F j)) + naturality _ _ _ := by + ext + dsimp + simp only [Category.comp_id, ofHom_apply, AddMonoidHom.coe_comp, AddMonoidHom.coe_coe, + Function.comp_apply] + change Shrink.addEquiv.symm _ = _ + rw [Quot.map_ι] } @[simp] -theorem cocone_naturality_components (j j' : J) (f : j ⟶ j') (x : F.obj j) : - (coconeMorphism.{w} F j') (F.map f x) = (coconeMorphism F j) x := by - rw [← cocone_naturality F f] - rfl - -/-- The cocone over the proposed colimit abelian group. -/ -def colimitCocone : Cocone F where - pt := colimit.{w} F - ι := { app := coconeMorphism F } - -/-- The function from the free abelian group on the diagram to the cone point of any other -cocone. -/ -@[simp] -def descFunLift (s : Cocone F) : Prequotient.{w} F → s.pt - | Prequotient.of j x => (s.ι.app j) x - | zero => 0 - | neg x => -descFunLift s x - | add x y => descFunLift s x + descFunLift s y - -/-- The function from the colimit abelian group to the cone point of any other cocone. -/ -def descFun (s : Cocone F) : ColimitType.{w} F → s.pt := by - fapply Quot.lift - · exact descFunLift F s - · intro x y r - induction r with - | refl => rfl - | symm _ _ _ r_ih => exact r_ih.symm - | trans _ _ _ _ _ r_ih_h r_ih_k => exact Eq.trans r_ih_h r_ih_k - | map j j' f x => simpa only [descFunLift, Functor.const_obj_obj] using - DFunLike.congr_fun (s.ι.naturality f) x - | zero => simp - | neg => simp - | add => simp - | neg_1 _ _ _ r_ih => dsimp; rw [r_ih] - | add_1 _ _ _ _ r_ih => dsimp; rw [r_ih] - | add_2 _ _ _ _ r_ih => dsimp; rw [r_ih] - | zero_add => dsimp; rw [zero_add] - | add_zero => dsimp; rw [add_zero] - | neg_add_cancel => dsimp; rw [neg_add_cancel] - | add_comm => dsimp; rw [add_comm] - | add_assoc => dsimp; rw [add_assoc] - -/-- The group homomorphism from the colimit abelian group to the cone point of any other cocone. -/ -def descMorphism (s : Cocone F) : colimit.{w} F ⟶ s.pt where - toFun := descFun F s - map_zero' := rfl - map_add' x y := Quot.induction_on₂ x y fun _ _ ↦ rfl - -/-- Evidence that the proposed colimit is the colimit. -/ -def colimitCoconeIsColimit : IsColimit (colimitCocone.{w} F) where - desc s := descMorphism F s - uniq s m w := DFunLike.ext _ _ fun x => Quot.inductionOn x fun x => by - change (m : ColimitType F →+ s.pt) _ = (descMorphism F s : ColimitType F →+ s.pt) _ - induction x using Prequotient.recOn with - | of j x => exact DFunLike.congr_fun (w j) x - | zero => - dsimp only [quot_zero] - rw [map_zero, map_zero] - | neg x ih => - dsimp only [quot_neg] - rw [map_neg, map_neg, ih] - | add x y ihx ihy => - simp only [quot_add] - rw [m.map_add, (descMorphism F s).map_add, ihx, ihy] +theorem Quot.desc_colimitCocone [DecidableEq J] (F : J ⥤ AddCommGrp.{w}) [Small.{w} (Quot F)] : + Quot.desc F (colimitCocone F) = (Shrink.addEquiv (α := Quot F)).symm.toAddMonoidHom := by + refine Quot.addMonoidHom_ext F (fun j x ↦ ?_) + simp only [colimitCocone_pt, coe_of, AddEquiv.toAddMonoidHom_eq_coe, AddMonoidHom.coe_coe] + erw [Quot.ι_desc] + simp + +/-- (internal implementation) The fact that the candidate colimit cocone constructed in +`colimitCocone` is the colimit. +-/ +noncomputable def colimitCoconeIsColimit [DecidableEq J] [Small.{w} (Quot F)] : + IsColimit (colimitCocone F) := by + refine isColimit_of_bijective_desc F _ ?_ + rw [Quot.desc_colimitCocone] + exact Shrink.addEquiv.symm.bijective end Colimits -lemma hasColimit : HasColimit F := ⟨_, Colimits.colimitCoconeIsColimit.{w} F⟩ - -variable (J) - -lemma hasColimitsOfShape : HasColimitsOfShape J AddCommGrp.{max u v w} where - has_colimit F := hasColimit.{w} F +open Colimits -lemma hasColimitsOfSize : HasColimitsOfSize.{v, u} AddCommGrp.{max u v w} := - ⟨fun _ => hasColimitsOfShape.{w} _⟩ +lemma hasColimit_of_small_quot [DecidableEq J] (h : Small.{w} (Quot F)) : HasColimit F := + ⟨_, colimitCoconeIsColimit F⟩ -instance hasColimits : HasColimits AddCommGrp.{w} := hasColimitsOfSize.{w} +instance [DecidableEq J] [Small.{w} J] : Small.{w} (Quot F) := + small_of_surjective (QuotientAddGroup.mk'_surjective _) -instance : HasColimitsOfSize.{v, v} (AddCommGrpMax.{u, v}) := hasColimitsOfSize.{u} -instance : HasColimitsOfSize.{u, u} (AddCommGrpMax.{u, v}) := hasColimitsOfSize.{v} -instance : HasColimitsOfSize.{u, v} (AddCommGrpMax.{u, v}) := hasColimitsOfSize.{u} -instance : HasColimitsOfSize.{v, u} (AddCommGrpMax.{u, v}) := hasColimitsOfSize.{u} -instance : HasColimitsOfSize.{0, 0} (AddCommGrp.{u}) := hasColimitsOfSize.{u, 0, 0} +instance hasColimit [Small.{w} J] (F : J ⥤ AddCommGrp.{w}) : HasColimit F := by + classical + exact hasColimit_of_small_quot F inferInstance -example : HasColimits AddCommGrpMax.{v, u} := - inferInstance -example : HasColimits AddCommGrpMax.{u, v} := - inferInstance +/-- +If `J` is `w`-small, then any functor `J ⥤ AddCommGrp.{w}` has a colimit. +-/ +instance hasColimitsOfShape [Small.{w} J] : HasColimitsOfShape J (AddCommGrp.{w}) where -example : HasColimits AddCommGrp.{u} := - inferInstance +/-- The category of additive commutative groups has all small colimits. +-/ +instance (priority := 1300) hasColimitsOfSize [UnivLE.{u, w}] : + HasColimitsOfSize.{v, u} (AddCommGrp.{w}) where end AddCommGrp diff --git a/Mathlib/Algebra/Homology/LocalCohomology.lean b/Mathlib/Algebra/Homology/LocalCohomology.lean index ebc2b550a5d65..7b53d4b469f1a 100644 --- a/Mathlib/Algebra/Homology/LocalCohomology.lean +++ b/Mathlib/Algebra/Homology/LocalCohomology.lean @@ -87,9 +87,7 @@ section variable {R : Type max u v} [CommRing R] {D : Type v} [SmallCategory D] lemma hasColimitDiagram (I : D ⥤ Ideal R) (i : ℕ) : - HasColimit (diagram I i) := by - have : HasColimitsOfShape Dᵒᵖ (AddCommGrpMax.{u, v}) := inferInstance - infer_instance + HasColimit (diagram I i) := inferInstance /- In this definition we do not assume any special property of the diagram `I`, but the relevant case diff --git a/Mathlib/Data/DFinsupp/Small.lean b/Mathlib/Data/DFinsupp/Small.lean new file mode 100644 index 0000000000000..04278d86c6531 --- /dev/null +++ b/Mathlib/Data/DFinsupp/Small.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2025 Sophie. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sophie Morel +-/ +import Mathlib.Data.DFinsupp.Defs +import Mathlib.Logic.Small.Basic + +/-! +# Smallness of the `DFinsupp` type + +Let `π : ι → Type v`. If `ι` and all the `π i` are `w`-small, this provides a `Small.{w}` +instance on `DFinsupp π`. + +-/ + +universe u v w + +variable {ι : Type u} {π : ι → Type v} [∀ i, Zero (π i)] + +section Small + +instance DFinsupp.small [Small.{w} ι] [∀ (i : ι), Small.{w} (π i)] : + Small.{w} (DFinsupp π) := small_of_injective (f := fun x j ↦ x j) (fun f f' eq ↦ by + ext j + exact congr_fun eq j) + +end Small From baef601f4b4baa6f9682b5f61bda2cdf52d12cd2 Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Mon, 6 Jan 2025 12:25:54 +0000 Subject: [PATCH 008/681] chore(Topology/UniformSpace/Completion): make coe' argument implicit (#20514) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right now coercions to completions of uniform spaces print weirdly: ```lean import Mathlib.Topology.UniformSpace.Completion variable (α : Type) [UniformSpace α] (x : α) open UniformSpace #check (x : Completion α) -- ↑α x : Completion α ``` This is because the coercion from `α` to `Completion α` is `UniformSpace.Completion.coe'` which (accidentally?) has `α` explicit. We make it implicit, so now we get the expected ```lean #check (x : Completion α) -- ↑x : Completion α ``` Zulip discussion: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/notation.20for.20coercion.20to.20completion/near/439560582 --- Mathlib/Topology/UniformSpace/Completion.lean | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mathlib/Topology/UniformSpace/Completion.lean b/Mathlib/Topology/UniformSpace/Completion.lean index 7e1f98e7b1de7..d7cc641b4699f 100644 --- a/Mathlib/Topology/UniformSpace/Completion.lean +++ b/Mathlib/Topology/UniformSpace/Completion.lean @@ -310,12 +310,13 @@ instance completeSpace : CompleteSpace (Completion α) := instance t0Space : T0Space (Completion α) := SeparationQuotient.instT0Space +variable {α} in /-- The map from a uniform space to its completion. -/ @[coe] def coe' : α → Completion α := SeparationQuotient.mk ∘ pureCauchy /-- Automatic coercion from `α` to its completion. Not always injective. -/ instance : Coe α (Completion α) := - ⟨coe' α⟩ + ⟨coe'⟩ -- note [use has_coe_t] protected theorem coe_eq : ((↑) : α → Completion α) = SeparationQuotient.mk ∘ pureCauchy := rfl From 88c4a940ec2fc143fcabf33ab1a7f0e56a45d5c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 6 Jan 2025 12:46:46 +0000 Subject: [PATCH 009/681] chore(Data/Multiset/Basic): move the `sub`, `union`, `inter` sections lower (#19863) * Move the sections about `sub`, `union` and `inter` under the sections about `count` and `filter` * `Multiset.countP_sub` now has a different argument order to match `List.countP_diff` * Golf `List.count_sub` * Name the instances and declare them using `where` notation * Define `Multiset.card` using `Quotient.lift`, not `Quotient.liftOn` --- Mathlib/Data/Multiset/Basic.lean | 629 +++++++++++++++---------------- 1 file changed, 294 insertions(+), 335 deletions(-) diff --git a/Mathlib/Data/Multiset/Basic.lean b/Mathlib/Data/Multiset/Basic.lean index f7425d084e924..9fec51e78b073 100644 --- a/Mathlib/Data/Multiset/Basic.lean +++ b/Mathlib/Data/Multiset/Basic.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Algebra.Order.Sub.Unbundled.Basic +import Mathlib.Data.List.Count import Mathlib.Data.List.Perm.Basic import Mathlib.Data.List.Perm.Lattice import Mathlib.Data.List.Perm.Subperm @@ -586,6 +587,7 @@ end /-! ### Additive monoid -/ +section add /-- The sum of two multisets is the lift of the list append operation. This adds the multiplicities of each element, @@ -651,6 +653,8 @@ theorem add_cons (a : α) (s t : Multiset α) : s + a ::ₘ t = a ::ₘ (s + t) theorem mem_add {a : α} {s t : Multiset α} : a ∈ s + t ↔ a ∈ s ∨ a ∈ t := Quotient.inductionOn₂ s t fun _l₁ _l₂ => mem_append +end add + theorem mem_of_mem_nsmul {a : α} {s : Multiset α} {n : ℕ} (h : a ∈ n • s) : a ∈ s := by induction' n with n ih · rw [zero_nsmul] at h @@ -679,7 +683,7 @@ theorem nsmul_cons {s : Multiset α} (n : ℕ) (a : α) : /-- The cardinality of a multiset is the sum of the multiplicities of all its elements, or simply the length of the underlying list. -/ -def card (s : Multiset α) : ℕ := Quot.liftOn s length fun _l₁ _l₂ => Perm.length_eq +def card : Multiset α → ℕ := Quot.lift length fun _l₁ _l₂ => Perm.length_eq @[simp] theorem coe_card (l : List α) : card (l : Multiset α) = length l := @@ -1463,260 +1467,6 @@ instance decidableDexistsMultiset {p : ∀ a ∈ m, Prop} [_hp : ∀ (a) (h : a end DecidablePiExists -/-! ### Subtraction -/ - - -section - -variable [DecidableEq α] {s t u : Multiset α} {a : α} - -/-- `s - t` is the multiset such that `count a (s - t) = count a s - count a t` for all `a` - (note that it is truncated subtraction, so it is `0` if `count a t ≥ count a s`). -/ -protected def sub (s t : Multiset α) : Multiset α := - (Quotient.liftOn₂ s t fun l₁ l₂ => (l₁.diff l₂ : Multiset α)) fun _v₁ _v₂ _w₁ _w₂ p₁ p₂ => - Quot.sound <| p₁.diff p₂ - -instance : Sub (Multiset α) := - ⟨Multiset.sub⟩ - -@[simp] -theorem coe_sub (s t : List α) : (s - t : Multiset α) = (s.diff t : List α) := - rfl - -/-- This is a special case of `tsub_zero`, which should be used instead of this. - This is needed to prove `OrderedSub (Multiset α)`. -/ -protected theorem sub_zero (s : Multiset α) : s - 0 = s := - Quot.inductionOn s fun _l => rfl - -@[simp] -theorem sub_cons (a : α) (s t : Multiset α) : s - a ::ₘ t = s.erase a - t := - Quotient.inductionOn₂ s t fun _l₁ _l₂ => congr_arg _ <| diff_cons _ _ _ - -protected theorem zero_sub (t : Multiset α) : 0 - t = 0 := - Multiset.induction_on t rfl fun a s ih => by simp [ih] - -/-- This is a special case of `tsub_le_iff_right`, which should be used instead of this. - This is needed to prove `OrderedSub (Multiset α)`. -/ -protected theorem sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t := by - revert s - exact @(Multiset.induction_on t (by simp [Multiset.sub_zero]) fun a t IH s => by - simp [IH, erase_le_iff_le_cons]) - -protected theorem sub_le_self (s t : Multiset α) : s - t ≤ s := by - rw [Multiset.sub_le_iff_le_add] - exact le_add_right _ _ - -instance : OrderedSub (Multiset α) := - ⟨fun _n _m _k => Multiset.sub_le_iff_le_add⟩ - -instance : ExistsAddOfLE (Multiset α) where - exists_add_of_le h := leInductionOn h fun s => - let ⟨l, p⟩ := s.exists_perm_append - ⟨l, Quot.sound p⟩ - -theorem cons_sub_of_le (a : α) {s t : Multiset α} (h : t ≤ s) : a ::ₘ s - t = a ::ₘ (s - t) := by - rw [← singleton_add, ← singleton_add, add_tsub_assoc_of_le h] - -theorem sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase s t := - Quotient.inductionOn₂ s t fun l₁ l₂ => by - show ofList (l₁.diff l₂) = foldl erase l₁ l₂ - rw [diff_eq_foldl l₁ l₂] - symm - exact foldl_hom _ _ _ _ _ fun x y => rfl - -@[simp] -theorem card_sub {s t : Multiset α} (h : t ≤ s) : card (s - t) = card s - card t := - Nat.eq_sub_of_add_eq <| by rw [← card_add, tsub_add_cancel_of_le h] - -/-! ### Union -/ - - -/-- `s ∪ t` is the lattice join operation with respect to the - multiset `≤`. The multiplicity of `a` in `s ∪ t` is the maximum - of the multiplicities in `s` and `t`. -/ -def union (s t : Multiset α) : Multiset α := - s - t + t - -instance : Union (Multiset α) := - ⟨union⟩ - -theorem union_def (s t : Multiset α) : s ∪ t = s - t + t := - rfl - -theorem le_union_left {s t : Multiset α} : s ≤ s ∪ t := - le_tsub_add - -theorem le_union_right {s t : Multiset α} : t ≤ s ∪ t := - le_add_left _ _ - -theorem eq_union_left : t ≤ s → s ∪ t = s := - tsub_add_cancel_of_le - -@[gcongr] -theorem union_le_union_right (h : s ≤ t) (u) : s ∪ u ≤ t ∪ u := - add_le_add_right (tsub_le_tsub_right h _) u - -theorem union_le (h₁ : s ≤ u) (h₂ : t ≤ u) : s ∪ t ≤ u := by - rw [← eq_union_left h₂]; exact union_le_union_right h₁ t - - -@[simp] -theorem mem_union : a ∈ s ∪ t ↔ a ∈ s ∨ a ∈ t := - ⟨fun h => (mem_add.1 h).imp_left (mem_of_le <| Multiset.sub_le_self _ _), - (Or.elim · (mem_of_le le_union_left) (mem_of_le le_union_right))⟩ - -@[simp] -theorem map_union [DecidableEq β] {f : α → β} (finj : Function.Injective f) {s t : Multiset α} : - map f (s ∪ t) = map f s ∪ map f t := - Quotient.inductionOn₂ s t fun l₁ l₂ => - congr_arg ofList (by rw [List.map_append f, List.map_diff finj]) - -@[simp] theorem zero_union : 0 ∪ s = s := by - simp [union_def, Multiset.zero_sub] - -@[simp] theorem union_zero : s ∪ 0 = s := by - simp [union_def] - -/-! ### Intersection -/ - -/-- `s ∩ t` is the lattice meet operation with respect to the - multiset `≤`. The multiplicity of `a` in `s ∩ t` is the minimum - of the multiplicities in `s` and `t`. -/ -def inter (s t : Multiset α) : Multiset α := - Quotient.liftOn₂ s t (fun l₁ l₂ => (l₁.bagInter l₂ : Multiset α)) fun _v₁ _v₂ _w₁ _w₂ p₁ p₂ => - Quot.sound <| p₁.bagInter p₂ - -instance : Inter (Multiset α) := - ⟨inter⟩ - -@[simp] -theorem inter_zero (s : Multiset α) : s ∩ 0 = 0 := - Quot.inductionOn s fun l => congr_arg ofList l.bagInter_nil - -@[simp] -theorem zero_inter (s : Multiset α) : 0 ∩ s = 0 := - Quot.inductionOn s fun l => congr_arg ofList l.nil_bagInter - -@[simp] -theorem cons_inter_of_pos {a} (s : Multiset α) {t} : a ∈ t → (a ::ₘ s) ∩ t = a ::ₘ s ∩ t.erase a := - Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_pos _ h - -@[simp] -theorem cons_inter_of_neg {a} (s : Multiset α) {t} : a ∉ t → (a ::ₘ s) ∩ t = s ∩ t := - Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_neg _ h - -theorem inter_le_left {s t : Multiset α} : s ∩ t ≤ s := - Quotient.inductionOn₂ s t fun _l₁ _l₂ => (bagInter_sublist_left _ _).subperm - -theorem inter_le_right {s t : Multiset α} : s ∩ t ≤ t := by - induction' s using Multiset.induction_on with a s IH generalizing t - · exact (zero_inter t).symm ▸ zero_le _ - by_cases h : a ∈ t - · simpa [h] using cons_le_cons a (IH (t := t.erase a)) - · simp [h, IH] - -theorem le_inter (h₁ : s ≤ t) (h₂ : s ≤ u) : s ≤ t ∩ u := by - revert s u; refine @(Multiset.induction_on t ?_ fun a t IH => ?_) <;> intros s u h₁ h₂ - · simpa only [zero_inter] using h₁ - by_cases h : a ∈ u - · rw [cons_inter_of_pos _ h, ← erase_le_iff_le_cons] - exact IH (erase_le_iff_le_cons.2 h₁) (erase_le_erase _ h₂) - · rw [cons_inter_of_neg _ h] - exact IH ((le_cons_of_not_mem <| mt (mem_of_le h₂) h).1 h₁) h₂ - -@[simp] -theorem mem_inter : a ∈ s ∩ t ↔ a ∈ s ∧ a ∈ t := - ⟨fun h => ⟨mem_of_le inter_le_left h, mem_of_le inter_le_right h⟩, fun ⟨h₁, h₂⟩ => by - rw [← cons_erase h₁, cons_inter_of_pos _ h₂]; apply mem_cons_self⟩ - -instance : Lattice (Multiset α) where - sup := (· ∪ ·) - sup_le _ _ _ := union_le - le_sup_left _ _ := le_union_left - le_sup_right _ _ := le_union_right - inf := (· ∩ ·) - le_inf _ _ _ := le_inter - inf_le_left _ _ := inter_le_left - inf_le_right _ _ := inter_le_right - -@[simp] -theorem sup_eq_union (s t : Multiset α) : s ⊔ t = s ∪ t := - rfl - -@[simp] -theorem inf_eq_inter (s t : Multiset α) : s ⊓ t = s ∩ t := - rfl - -@[simp] -theorem le_inter_iff : s ≤ t ∩ u ↔ s ≤ t ∧ s ≤ u := - le_inf_iff - -@[simp] -theorem union_le_iff : s ∪ t ≤ u ↔ s ≤ u ∧ t ≤ u := - sup_le_iff - -theorem union_comm (s t : Multiset α) : s ∪ t = t ∪ s := sup_comm _ _ - -theorem inter_comm (s t : Multiset α) : s ∩ t = t ∩ s := inf_comm _ _ - -theorem eq_union_right (h : s ≤ t) : s ∪ t = t := by rw [union_comm, eq_union_left h] - -@[gcongr] -theorem union_le_union_left (h : s ≤ t) (u) : u ∪ s ≤ u ∪ t := - sup_le_sup_left h _ - -theorem union_le_add (s t : Multiset α) : s ∪ t ≤ s + t := - union_le (le_add_right _ _) (le_add_left _ _) - -theorem union_add_distrib (s t u : Multiset α) : s ∪ t + u = s + u ∪ (t + u) := by - simpa [(· ∪ ·), union, eq_comm, add_assoc] using - show s + u - (t + u) = s - t by rw [add_comm t, tsub_add_eq_tsub_tsub, add_tsub_cancel_right] - -theorem add_union_distrib (s t u : Multiset α) : s + (t ∪ u) = s + t ∪ (s + u) := by - rw [add_comm, union_add_distrib, add_comm s, add_comm s] - -theorem cons_union_distrib (a : α) (s t : Multiset α) : a ::ₘ (s ∪ t) = a ::ₘ s ∪ a ::ₘ t := by - simpa using add_union_distrib (a ::ₘ 0) s t - -theorem inter_add_distrib (s t u : Multiset α) : s ∩ t + u = (s + u) ∩ (t + u) := by - by_contra! h - obtain ⟨a, ha⟩ := lt_iff_cons_le.1 <| h.lt_of_le <| le_inter - (add_le_add_right inter_le_left _) (add_le_add_right inter_le_right _) - rw [← cons_add] at ha - exact (lt_cons_self (s ∩ t) a).not_le <| le_inter - (le_of_add_le_add_right (ha.trans inter_le_left)) - (le_of_add_le_add_right (ha.trans inter_le_right)) - -theorem add_inter_distrib (s t u : Multiset α) : s + t ∩ u = (s + t) ∩ (s + u) := by - rw [add_comm, inter_add_distrib, add_comm s, add_comm s] - -theorem cons_inter_distrib (a : α) (s t : Multiset α) : a ::ₘ s ∩ t = (a ::ₘ s) ∩ (a ::ₘ t) := by - simp - -lemma union_add_inter (s t : Multiset α) : s ∪ t + s ∩ t = s + t := by - apply _root_.le_antisymm - · rw [union_add_distrib] - refine union_le (add_le_add_left inter_le_right _) ?_ - rw [add_comm] - exact add_le_add_right inter_le_left _ - · rw [add_comm, add_inter_distrib] - refine le_inter (add_le_add_right le_union_right _) ?_ - rw [add_comm] - exact add_le_add_right le_union_left _ - -theorem sub_add_inter (s t : Multiset α) : s - t + s ∩ t = s := by - rw [inter_comm] - revert s; refine Multiset.induction_on t (by simp) fun a t IH s => ?_ - by_cases h : a ∈ s - · rw [cons_inter_of_pos _ h, sub_cons, add_cons, IH, cons_erase h] - · rw [cons_inter_of_neg _ h, sub_cons, erase_of_not_mem h, IH] - -theorem sub_inter (s t : Multiset α) : s - s ∩ t = s - t := - add_right_cancel (b := s ∩ t) <| by - rw [sub_add_inter s t, tsub_add_cancel_of_le inter_le_left] - -end - /-! ### `Multiset.filter` -/ @@ -1822,35 +1572,6 @@ theorem filter_nsmul (s : Multiset α) (n : ℕ) : filter p (n • s) = n • fi variable (p) -@[simp] -theorem filter_sub [DecidableEq α] (s t : Multiset α) : - filter p (s - t) = filter p s - filter p t := by - revert s; refine Multiset.induction_on t (by simp) fun a t IH s => ?_ - rw [sub_cons, IH] - by_cases h : p a - · rw [filter_cons_of_pos _ h, sub_cons] - congr - by_cases m : a ∈ s - · rw [← cons_inj_right a, ← filter_cons_of_pos _ h, cons_erase (mem_filter_of_mem m h), - cons_erase m] - · rw [erase_of_not_mem m, erase_of_not_mem (mt mem_of_mem_filter m)] - · rw [filter_cons_of_neg _ h] - by_cases m : a ∈ s - · rw [(by rw [filter_cons_of_neg _ h] : filter p (erase s a) = filter p (a ::ₘ erase s a)), - cons_erase m] - · rw [erase_of_not_mem m] - -@[simp] -theorem filter_union [DecidableEq α] (s t : Multiset α) : - filter p (s ∪ t) = filter p s ∪ filter p t := by simp [(· ∪ ·), union] - -@[simp] -theorem filter_inter [DecidableEq α] (s t : Multiset α) : - filter p (s ∩ t) = filter p s ∩ filter p t := - le_antisymm (le_inter (filter_le_filter _ inter_le_left) (filter_le_filter _ inter_le_right)) <| - le_filter.2 ⟨inf_le_inf (filter_le _ _) (filter_le _ _), fun _a h => - of_mem_filter (mem_of_le inter_le_left h)⟩ - @[simp] theorem filter_filter (q) [DecidablePred q] (s : Multiset α) : filter p (filter q s) = filter (fun a => p a ∧ q a) s := @@ -2026,11 +1747,6 @@ def countPAddMonoidHom : Multiset α →+ ℕ where theorem coe_countPAddMonoidHom : (countPAddMonoidHom p : Multiset α → ℕ) = countP p := rfl -@[simp] -theorem countP_sub [DecidableEq α] {s t : Multiset α} (h : t ≤ s) : - countP p (s - t) = countP p s - countP p t := by - simp [countP_eq_card_filter, h, filter_le_filter] - @[gcongr] theorem countP_le_of_le {s t} (h : s ≤ t) : countP p s ≤ countP p t := by simpa [countP_eq_card_filter] using card_le_card (filter_le_filter p h) @@ -2209,23 +1925,6 @@ theorem count_erase_of_ne {a b : α} (ab : a ≠ b) (s : Multiset α) : Quotient.inductionOn s fun l => by convert List.count_erase_of_ne ab l <;> rw [← coe_count] <;> simp -@[simp] -theorem count_sub (a : α) (s t : Multiset α) : count a (s - t) = count a s - count a t := by - revert s; refine Multiset.induction_on t (by simp) fun b t IH s => ?_ - rw [sub_cons, IH] - rcases Decidable.eq_or_ne a b with rfl | ab - · rw [count_erase_self, count_cons_self, Nat.sub_sub, add_comm] - · rw [count_erase_of_ne ab, count_cons_of_ne ab] - -@[simp] -theorem count_union (a : α) (s t : Multiset α) : count a (s ∪ t) = max (count a s) (count a t) := by - simp [(· ∪ ·), union, Nat.sub_add_eq_max] - -@[simp] -theorem count_inter (a : α) (s t : Multiset α) : count a (s ∩ t) = min (count a s) (count a t) := by - apply @Nat.add_left_cancel (count a (s - t)) - rw [← count_add, sub_add_inter, count_sub, Nat.sub_add_min_cancel] - theorem le_count_iff_replicate_le {a : α} {s : Multiset α} {n : ℕ} : n ≤ count a s ↔ replicate n a ≤ s := Quot.inductionOn s fun _l => by @@ -2263,20 +1962,8 @@ theorem ext' {s t : Multiset α} : (∀ a, count a s = count a t) → s = t := lemma count_injective : Injective fun (s : Multiset α) a ↦ s.count a := fun _s _t hst ↦ ext' <| congr_fun hst -@[simp] -theorem coe_inter (s t : List α) : (s ∩ t : Multiset α) = (s.bagInter t : List α) := by ext; simp - theorem le_iff_count {s t : Multiset α} : s ≤ t ↔ ∀ a, count a s ≤ count a t := - ⟨fun h a => count_le_of_le a h, fun al => by - rw [← (ext.2 fun a => by simp [max_eq_right (al a)] : s ∪ t = t)]; apply le_union_left⟩ - -instance : DistribLattice (Multiset α) := - { le_sup_inf := fun s t u => - le_of_eq <| - Eq.symm <| - ext.2 fun a => by - simp only [max_min_distrib_left, Multiset.count_inter, Multiset.sup_eq_union, - Multiset.count_union, Multiset.inf_eq_inter] } + Quotient.inductionOn₂ s t fun _ _ ↦ by simp [subperm_iff_count] theorem count_map {α β : Type*} (f : α → β) (s : Multiset α) [DecidableEq β] (b : β) : count b (map f s) = card (s.filter fun a => b = f a) := by @@ -2303,11 +1990,6 @@ theorem count_map_eq_count' [DecidableEq β] (f : α → β) (s : Multiset α) ( rw [hf hkx] at hks contradiction -@[simp] -theorem sub_filter_eq_filter_not (p) [DecidablePred p] (s : Multiset α) : - s - s.filter p = s.filter (fun a ↦ ¬ p a) := by - ext a; by_cases h : p a <;> simp [h] - theorem filter_eq' (s : Multiset α) (b : α) : s.filter (· = b) = replicate (count b s) b := Quotient.inductionOn s fun l => by simp only [quot_mk_to_coe, filter_coe, mem_coe, coe_count] @@ -2316,6 +1998,292 @@ theorem filter_eq' (s : Multiset α) (b : α) : s.filter (· = b) = replicate (c theorem filter_eq (s : Multiset α) (b : α) : s.filter (Eq b) = replicate (count b s) b := by simp_rw [← filter_eq', eq_comm] +lemma erase_attach_map_val (s : Multiset α) (x : {x // x ∈ s}) : + (s.attach.erase x).map (↑) = s.erase x := by + rw [Multiset.map_erase _ val_injective, attach_map_val] + +lemma erase_attach_map (s : Multiset α) (f : α → β) (x : {x // x ∈ s}) : + (s.attach.erase x).map (fun j : {x // x ∈ s} ↦ f j) = (s.erase x).map f := by + simp only [← Function.comp_apply (f := f)] + rw [← map_map, erase_attach_map_val] + +end + +/-! ### Subtraction -/ + +section sub +variable [DecidableEq α] {s t u : Multiset α} {a : α} + +/-- `s - t` is the multiset such that `count a (s - t) = count a s - count a t` for all `a`. +(note that it is truncated subtraction, so `count a (s - t) = 0` if `count a s ≤ count a t`). -/ +protected def sub (s t : Multiset α) : Multiset α := + (Quotient.liftOn₂ s t fun l₁ l₂ => (l₁.diff l₂ : Multiset α)) fun _v₁ _v₂ _w₁ _w₂ p₁ p₂ => + Quot.sound <| p₁.diff p₂ + +instance : Sub (Multiset α) := ⟨.sub⟩ + +@[simp] +lemma coe_sub (s t : List α) : (s - t : Multiset α) = s.diff t := + rfl + +/-- This is a special case of `tsub_zero`, which should be used instead of this. +This is needed to prove `OrderedSub (Multiset α)`. -/ +@[simp, nolint simpNF] -- We want to use this lemma earlier than the lemma simp can prove it with +protected lemma sub_zero (s : Multiset α) : s - 0 = s := + Quot.inductionOn s fun _l => rfl + +@[simp] +lemma sub_cons (a : α) (s t : Multiset α) : s - a ::ₘ t = s.erase a - t := + Quotient.inductionOn₂ s t fun _l₁ _l₂ => congr_arg _ <| diff_cons _ _ _ + +protected lemma zero_sub (t : Multiset α) : 0 - t = 0 := + Multiset.induction_on t rfl fun a s ih => by simp [ih] + +@[simp] +lemma countP_sub {s t : Multiset α} : + t ≤ s → ∀ (p : α → Prop) [DecidablePred p], countP p (s - t) = countP p s - countP p t := + Quotient.inductionOn₂ s t fun _l₁ _l₂ hl _ _ ↦ List.countP_diff hl _ + +@[simp] +lemma count_sub (a : α) (s t : Multiset α) : count a (s - t) = count a s - count a t := + Quotient.inductionOn₂ s t <| by simp [List.count_diff] + +/-- This is a special case of `tsub_le_iff_right`, which should be used instead of this. +This is needed to prove `OrderedSub (Multiset α)`. -/ +protected lemma sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t := by + revert s + exact @(Multiset.induction_on t (by simp [Multiset.sub_zero]) fun a t IH s => by + simp [IH, erase_le_iff_le_cons]) + +protected lemma sub_le_self (s t : Multiset α) : s - t ≤ s := by + rw [Multiset.sub_le_iff_le_add] + exact le_add_right _ _ + +instance : OrderedSub (Multiset α) := + ⟨fun _n _m _k => Multiset.sub_le_iff_le_add⟩ + +instance : ExistsAddOfLE (Multiset α) where + exists_add_of_le h := leInductionOn h fun s => + let ⟨l, p⟩ := s.exists_perm_append + ⟨l, Quot.sound p⟩ + +@[simp] +lemma filter_sub (p : α → Prop) [DecidablePred p] (s t : Multiset α) : + filter p (s - t) = filter p s - filter p t := by + revert s; refine Multiset.induction_on t (by simp) fun a t IH s => ?_ + rw [sub_cons, IH] + by_cases h : p a + · rw [filter_cons_of_pos _ h, sub_cons] + congr + by_cases m : a ∈ s + · rw [← cons_inj_right a, ← filter_cons_of_pos _ h, cons_erase (mem_filter_of_mem m h), + cons_erase m] + · rw [erase_of_not_mem m, erase_of_not_mem (mt mem_of_mem_filter m)] + · rw [filter_cons_of_neg _ h] + by_cases m : a ∈ s + · rw [(by rw [filter_cons_of_neg _ h] : filter p (erase s a) = filter p (a ::ₘ erase s a)), + cons_erase m] + · rw [erase_of_not_mem m] + +@[simp] +lemma sub_filter_eq_filter_not (p : α → Prop) [DecidablePred p] (s : Multiset α) : + s - s.filter p = s.filter fun a ↦ ¬ p a := by ext a; by_cases h : p a <;> simp [h] + +lemma cons_sub_of_le (a : α) {s t : Multiset α} (h : t ≤ s) : a ::ₘ s - t = a ::ₘ (s - t) := by + rw [← singleton_add, ← singleton_add, add_tsub_assoc_of_le h] + +lemma sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase s t := + Quotient.inductionOn₂ s t fun l₁ l₂ => by + show ofList (l₁.diff l₂) = foldl erase l₁ l₂ + rw [diff_eq_foldl l₁ l₂] + symm + exact foldl_hom _ _ _ _ _ fun x y => rfl + +@[simp] +lemma card_sub {s t : Multiset α} (h : t ≤ s) : card (s - t) = card s - card t := + Nat.eq_sub_of_add_eq <| by rw [← card_add, tsub_add_cancel_of_le h] + +/-! ### Union -/ + +/-- `s ∪ t` is the multiset such that the multiplicity of each `a` in it is the maximum of the +multiplicity of `a` in `s` and `t`. This is the supremum of multisets. -/ +def union (s t : Multiset α) : Multiset α := s - t + t + +instance : Union (Multiset α) := ⟨union⟩ + +lemma union_def (s t : Multiset α) : s ∪ t = s - t + t := rfl + +lemma le_union_left : s ≤ s ∪ t := le_tsub_add +lemma le_union_right : t ≤ s ∪ t := le_add_left _ _ +lemma eq_union_left : t ≤ s → s ∪ t = s := tsub_add_cancel_of_le + +@[gcongr] +lemma union_le_union_right (h : s ≤ t) (u) : s ∪ u ≤ t ∪ u := + add_le_add_right (tsub_le_tsub_right h _) _ + +lemma union_le (h₁ : s ≤ u) (h₂ : t ≤ u) : s ∪ t ≤ u := by + rw [← eq_union_left h₂]; exact union_le_union_right h₁ t + +@[simp] +lemma mem_union : a ∈ s ∪ t ↔ a ∈ s ∨ a ∈ t := + ⟨fun h => (mem_add.1 h).imp_left (mem_of_le <| Multiset.sub_le_self _ _), + (Or.elim · (mem_of_le le_union_left) (mem_of_le le_union_right))⟩ + +@[simp] +lemma map_union [DecidableEq β] {f : α → β} (finj : Function.Injective f) {s t : Multiset α} : + map f (s ∪ t) = map f s ∪ map f t := + Quotient.inductionOn₂ s t fun l₁ l₂ => + congr_arg ofList (by rw [List.map_append f, List.map_diff finj]) + +@[simp] lemma zero_union : 0 ∪ s = s := by simp [union_def, Multiset.zero_sub] +@[simp] lemma union_zero : s ∪ 0 = s := by simp [union_def] + +@[simp] +lemma count_union (a : α) (s t : Multiset α) : count a (s ∪ t) = max (count a s) (count a t) := by + simp [(· ∪ ·), union, Nat.sub_add_eq_max] + +@[simp] lemma filter_union (p : α → Prop) [DecidablePred p] (s t : Multiset α) : + filter p (s ∪ t) = filter p s ∪ filter p t := by simp [(· ∪ ·), union] + +/-! ### Intersection -/ + +/-- `s ∩ t` is the multiset such that the multiplicity of each `a` in it is the minimum of the +multiplicity of `a` in `s` and `t`. This is the infimum of multisets. -/ +def inter (s t : Multiset α) : Multiset α := + Quotient.liftOn₂ s t (fun l₁ l₂ => (l₁.bagInter l₂ : Multiset α)) fun _v₁ _v₂ _w₁ _w₂ p₁ p₂ => + Quot.sound <| p₁.bagInter p₂ + +instance : Inter (Multiset α) := ⟨inter⟩ + +@[simp] lemma inter_zero (s : Multiset α) : s ∩ 0 = 0 := + Quot.inductionOn s fun l => congr_arg ofList l.bagInter_nil + +@[simp] lemma zero_inter (s : Multiset α) : 0 ∩ s = 0 := + Quot.inductionOn s fun l => congr_arg ofList l.nil_bagInter + +@[simp] +lemma cons_inter_of_pos (s : Multiset α) : a ∈ t → (a ::ₘ s) ∩ t = a ::ₘ s ∩ t.erase a := + Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_pos _ h + +@[simp] +lemma cons_inter_of_neg (s : Multiset α) : a ∉ t → (a ::ₘ s) ∩ t = s ∩ t := + Quotient.inductionOn₂ s t fun _l₁ _l₂ h => congr_arg ofList <| cons_bagInter_of_neg _ h + +lemma inter_le_left : s ∩ t ≤ s := + Quotient.inductionOn₂ s t fun _l₁ _l₂ => (bagInter_sublist_left _ _).subperm + +lemma inter_le_right : s ∩ t ≤ t := by + induction' s using Multiset.induction_on with a s IH generalizing t + · exact (zero_inter t).symm ▸ zero_le _ + by_cases h : a ∈ t + · simpa [h] using cons_le_cons a (IH (t := t.erase a)) + · simp [h, IH] + +lemma le_inter (h₁ : s ≤ t) (h₂ : s ≤ u) : s ≤ t ∩ u := by + revert s u; refine @(Multiset.induction_on t ?_ fun a t IH => ?_) <;> intros s u h₁ h₂ + · simpa only [zero_inter] using h₁ + by_cases h : a ∈ u + · rw [cons_inter_of_pos _ h, ← erase_le_iff_le_cons] + exact IH (erase_le_iff_le_cons.2 h₁) (erase_le_erase _ h₂) + · rw [cons_inter_of_neg _ h] + exact IH ((le_cons_of_not_mem <| mt (mem_of_le h₂) h).1 h₁) h₂ + +@[simp] +lemma mem_inter : a ∈ s ∩ t ↔ a ∈ s ∧ a ∈ t := + ⟨fun h => ⟨mem_of_le inter_le_left h, mem_of_le inter_le_right h⟩, fun ⟨h₁, h₂⟩ => by + rw [← cons_erase h₁, cons_inter_of_pos _ h₂]; apply mem_cons_self⟩ + +instance instLattice : Lattice (Multiset α) where + sup := (· ∪ ·) + sup_le _ _ _ := union_le + le_sup_left _ _ := le_union_left + le_sup_right _ _ := le_union_right + inf := (· ∩ ·) + le_inf _ _ _ := le_inter + inf_le_left _ _ := inter_le_left + inf_le_right _ _ := inter_le_right + +@[simp] lemma sup_eq_union (s t : Multiset α) : s ⊔ t = s ∪ t := rfl +@[simp] lemma inf_eq_inter (s t : Multiset α) : s ⊓ t = s ∩ t := rfl + +@[simp] lemma le_inter_iff : s ≤ t ∩ u ↔ s ≤ t ∧ s ≤ u := le_inf_iff +@[simp] lemma union_le_iff : s ∪ t ≤ u ↔ s ≤ u ∧ t ≤ u := sup_le_iff + +lemma union_comm (s t : Multiset α) : s ∪ t = t ∪ s := sup_comm .. +lemma inter_comm (s t : Multiset α) : s ∩ t = t ∩ s := inf_comm .. + +lemma eq_union_right (h : s ≤ t) : s ∪ t = t := by rw [union_comm, eq_union_left h] + +@[gcongr] lemma union_le_union_left (h : s ≤ t) (u) : u ∪ s ≤ u ∪ t := sup_le_sup_left h _ + +lemma union_le_add (s t : Multiset α) : s ∪ t ≤ s + t := union_le (le_add_right ..) (le_add_left ..) + +lemma union_add_distrib (s t u : Multiset α) : s ∪ t + u = s + u ∪ (t + u) := by + simpa [(· ∪ ·), union, eq_comm, add_assoc, add_left_inj] using + show s + u - (t + u) = s - t by + rw [add_comm t, tsub_add_eq_tsub_tsub, add_tsub_cancel_right] + +lemma add_union_distrib (s t u : Multiset α) : s + (t ∪ u) = s + t ∪ (s + u) := by + rw [add_comm, union_add_distrib, add_comm s, add_comm s] + +lemma cons_union_distrib (a : α) (s t : Multiset α) : a ::ₘ (s ∪ t) = a ::ₘ s ∪ a ::ₘ t := by + simpa using add_union_distrib (a ::ₘ 0) s t + +lemma inter_add_distrib (s t u : Multiset α) : s ∩ t + u = (s + u) ∩ (t + u) := by + by_contra! h + obtain ⟨a, ha⟩ := lt_iff_cons_le.1 <| h.lt_of_le <| le_inter + (add_le_add_right inter_le_left _) (add_le_add_right inter_le_right _) + rw [← cons_add] at ha + exact (lt_cons_self (s ∩ t) a).not_le <| le_inter + (le_of_add_le_add_right (ha.trans inter_le_left)) + (le_of_add_le_add_right (ha.trans inter_le_right)) + +lemma add_inter_distrib (s t u : Multiset α) : s + t ∩ u = (s + t) ∩ (s + u) := by + rw [add_comm, inter_add_distrib, add_comm s, add_comm s] + +lemma cons_inter_distrib (a : α) (s t : Multiset α) : a ::ₘ s ∩ t = (a ::ₘ s) ∩ (a ::ₘ t) := by + simp + +lemma union_add_inter (s t : Multiset α) : s ∪ t + s ∩ t = s + t := by + apply _root_.le_antisymm + · rw [union_add_distrib] + refine union_le (add_le_add_left inter_le_right _) ?_ + rw [add_comm] + exact add_le_add_right inter_le_left _ + · rw [add_comm, add_inter_distrib] + refine le_inter (add_le_add_right le_union_right _) ?_ + rw [add_comm] + exact add_le_add_right le_union_left _ + +lemma sub_add_inter (s t : Multiset α) : s - t + s ∩ t = s := by + rw [inter_comm] + revert s; refine Multiset.induction_on t (by simp) fun a t IH s => ?_ + by_cases h : a ∈ s + · rw [cons_inter_of_pos _ h, sub_cons, add_cons, IH, cons_erase h] + · rw [cons_inter_of_neg _ h, sub_cons, erase_of_not_mem h, IH] + +lemma sub_inter (s t : Multiset α) : s - s ∩ t = s - t := + (eq_tsub_of_add_eq <| sub_add_inter ..).symm + +@[simp] +lemma count_inter (a : α) (s t : Multiset α) : count a (s ∩ t) = min (count a s) (count a t) := by + apply @Nat.add_left_cancel (count a (s - t)) + rw [← count_add, sub_add_inter, count_sub, Nat.sub_add_min_cancel] + +@[simp] +lemma coe_inter (s t : List α) : (s ∩ t : Multiset α) = (s.bagInter t : List α) := by ext; simp + +instance instDistribLattice : DistribLattice (Multiset α) where + le_sup_inf s t u := ge_of_eq <| ext.2 fun a ↦ by + simp only [max_min_distrib_left, Multiset.count_inter, Multiset.sup_eq_union, + Multiset.count_union, Multiset.inf_eq_inter] + +@[simp] lemma filter_inter (p : α → Prop) [DecidablePred p] (s t : Multiset α) : + filter p (s ∩ t) = filter p s ∩ filter p t := + le_antisymm (le_inter (filter_le_filter _ inter_le_left) (filter_le_filter _ inter_le_right)) <| + le_filter.2 ⟨inf_le_inf (filter_le _ _) (filter_le _ _), fun _a h => + of_mem_filter (mem_of_le inter_le_left h)⟩ + @[simp] theorem replicate_inter (n : ℕ) (x : α) (s : Multiset α) : replicate n x ∩ s = replicate (min n (s.count x)) x := by @@ -2330,16 +2298,7 @@ theorem inter_replicate (s : Multiset α) (n : ℕ) (x : α) : s ∩ replicate n x = replicate (min (s.count x) n) x := by rw [inter_comm, replicate_inter, min_comm] -theorem erase_attach_map_val (s : Multiset α) (x : {x // x ∈ s}) : - (s.attach.erase x).map (↑) = s.erase x := by - rw [Multiset.map_erase _ val_injective, attach_map_val] - -theorem erase_attach_map (s : Multiset α) (f : α → β) (x : {x // x ∈ s}) : - (s.attach.erase x).map (fun j : {x // x ∈ s} ↦ f j) = (s.erase x).map f := by - simp only [← Function.comp_apply (f := f)] - rw [← map_map, erase_attach_map_val] - -end +end sub @[ext] theorem addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by @@ -2800,4 +2759,4 @@ theorem coe_subsingletonEquiv [Subsingleton α] : end Multiset -set_option linter.style.longFile 2900 +set_option linter.style.longFile 2800 From 5e298f933b82bbc911d081bf7b21b1e5d7a24ae9 Mon Sep 17 00:00:00 2001 From: smorel394 Date: Mon, 6 Jan 2025 13:13:30 +0000 Subject: [PATCH 010/681] feat(CategoryTheory/Shift/Adjunction): properties of `Adjunction.CommShift` (#20337) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide instances that say that `Adjunction.CommShift` holds for the identity adjunction and is stable by composition, as well as similar instances for `Equivalence.CommShift`. - [ ] depends on: #20364 - [ ] depends on: #20490 Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- Mathlib/CategoryTheory/Shift/Adjunction.lean | 102 +++++++++++++++++-- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/Mathlib/CategoryTheory/Shift/Adjunction.lean b/Mathlib/CategoryTheory/Shift/Adjunction.lean index f893e59286f66..8f6a5a6ddc1f9 100644 --- a/Mathlib/CategoryTheory/Shift/Adjunction.lean +++ b/Mathlib/CategoryTheory/Shift/Adjunction.lean @@ -200,9 +200,31 @@ class CommShift : Prop where commShift_unit : NatTrans.CommShift adj.unit A := by infer_instance commShift_counit : NatTrans.CommShift adj.counit A := by infer_instance +open CommShift in +attribute [instance] commShift_unit commShift_counit + +@[reassoc (attr := simp)] +lemma unit_app_commShiftIso_hom_app [adj.CommShift A] (a : A) (X : C) : + adj.unit.app (X⟦a⟧) ≫ ((F ⋙ G).commShiftIso a).hom.app X = (adj.unit.app X)⟦a⟧' := by + simpa using (NatTrans.shift_app_comm adj.unit a X).symm + +@[reassoc (attr := simp)] +lemma unit_app_shift_commShiftIso_inv_app [adj.CommShift A] (a : A) (X : C) : + (adj.unit.app X)⟦a⟧' ≫ ((F ⋙ G).commShiftIso a).inv.app X = adj.unit.app (X⟦a⟧) := by + simp [← cancel_mono (((F ⋙ G).commShiftIso _).hom.app _)] + +@[reassoc (attr := simp)] +lemma commShiftIso_hom_app_counit_app_shift [adj.CommShift A] (a : A) (Y : D) : + ((G ⋙ F).commShiftIso a).hom.app Y ≫ (adj.counit.app Y)⟦a⟧' = adj.counit.app (Y⟦a⟧) := by + simpa using (NatTrans.shift_app_comm adj.counit a Y) + +@[reassoc (attr := simp)] +lemma commShiftIso_inv_app_counit_app [adj.CommShift A] (a : A) (Y : D) : + ((G ⋙ F).commShiftIso a).inv.app Y ≫ adj.counit.app (Y⟦a⟧) = (adj.counit.app Y)⟦a⟧' := by + simp [← cancel_epi (((G ⋙ F).commShiftIso _).hom.app _)] + namespace CommShift -attribute [instance] commShift_unit commShift_counit /-- Constructor for `Adjunction.CommShift`. -/ lemma mk' (h : NatTrans.CommShift adj.unit A) : @@ -217,6 +239,30 @@ lemma mk' (h : NatTrans.CommShift adj.unit A) : Functor.commShiftIso_id_hom_app, whiskerRight_app, id_comp, Functor.commShiftIso_comp_hom_app] using congr_app (h.shift_comm a) X⟩ +variable [adj.CommShift A] + +/-- The identity adjunction is compatible with the trivial `CommShift` structure on the +identity functor. +-/ +instance instId : (Adjunction.id (C := C)).CommShift A where + commShift_counit := + inferInstanceAs (NatTrans.CommShift (𝟭 C).leftUnitor.hom A) + commShift_unit := + inferInstanceAs (NatTrans.CommShift (𝟭 C).leftUnitor.inv A) + +variable {E : Type*} [Category E] {F' : D ⥤ E} {G' : E ⥤ D} (adj' : F' ⊣ G') + [HasShift E A] [F'.CommShift A] [G'.CommShift A] [adj.CommShift A] [adj'.CommShift A] + +/-- Compatibility of `Adjunction.Commshift` with the composition of adjunctions. +-/ +instance instComp : (adj.comp adj').CommShift A where + commShift_counit := by + rw [comp_counit] + infer_instance + commShift_unit := by + rw [comp_unit] + infer_instance + end CommShift variable {A} @@ -288,8 +334,8 @@ lemma iso_inv_app (Y : D) : (F.obj (G.obj Y)))) ≫ G.map ((shiftFunctor D a).map (adj.counit.app Y)) := by obtain rfl : b = -a := by rw [← add_left_inj a, h, neg_add_cancel] - simp only [Functor.comp_obj, iso, iso', shiftEquiv', Equiv.toFun_as_coe, - conjugateIsoEquiv_apply_inv, conjugateEquiv_apply_app, comp_unit_app, Functor.id_obj, + simp only [iso, iso', shiftEquiv', Equiv.toFun_as_coe, conjugateIsoEquiv_apply_inv, + conjugateEquiv_apply_app, Functor.comp_obj, comp_unit_app, Functor.id_obj, Equivalence.toAdjunction_unit, Equivalence.Equivalence_mk'_unit, Iso.symm_hom, Functor.comp_map, comp_counit_app, Equivalence.toAdjunction_counit, Equivalence.Equivalence_mk'_counit, Functor.map_shiftFunctorCompIsoId_hom_app, assoc, Functor.map_comp] @@ -470,9 +516,28 @@ lemma mk' (h : NatTrans.CommShift E.unitIso.hom A) : commShift_counit := (Adjunction.CommShift.mk' E.toAdjunction A h).commShift_counit /-- -If `E : C ≌ D` is an equivalence and we have compatible `CommShift` structures on `E.functor` -and `E.inverse`, then we also have compatible `CommShift` structures on `E.symm.functor` -and `E.symm.inverse`. +The forward functor of the identity equivalence is compatible with shifts. +-/ +instance : (Equivalence.refl (C := C)).functor.CommShift A := by + dsimp + infer_instance + +/-- +The inverse functor of the identity equivalence is compatible with shifts. +-/ +instance : (Equivalence.refl (C := C)).inverse.CommShift A := by + dsimp + infer_instance + +/-- +The identity equivalence is compatible with shifts. +-/ +instance : (Equivalence.refl (C := C)).CommShift A := by + dsimp [Equivalence.CommShift, refl_toAdjunction] + infer_instance + +/-- +If an equivalence `E : C ≌ D` is compatible with shifts, so is `E.symm`. -/ instance [E.CommShift A] : E.symm.CommShift A := mk' E.symm A (inferInstanceAs (NatTrans.CommShift E.counitIso.inv A)) @@ -483,6 +548,31 @@ lemma mk'' (h : NatTrans.CommShift E.counitIso.hom A) : have := mk' E.symm A (inferInstanceAs (NatTrans.CommShift E.counitIso.inv A)) inferInstanceAs (E.symm.symm.CommShift A) +variable {F : Type*} [Category F] [HasShift F A] {E' : D ≌ F} [E.CommShift A] + [E'.functor.CommShift A] [E'.inverse.CommShift A] [E'.CommShift A] + +/-- +If `E : C ≌ D` and `E' : D ≌ F` are equivalence whose forward functors are compatible with shifts, +so is `(E.trans E').functor`. +-/ +instance : (E.trans E').functor.CommShift A := by + dsimp + infer_instance + +/-- +If `E : C ≌ D` and `E' : D ≌ F` are equivalence whose inverse functors are compatible with shifts, +so is `(E.trans E').inverse`. +-/ +instance : (E.trans E').inverse.CommShift A := by + dsimp + infer_instance + +/-- +If equivalences `E : C ≌ D` and `E' : D ≌ F` are compatible with shifts, so is `E.trans E'`. +-/ +instance : (E.trans E').CommShift A := + inferInstanceAs ((E.toAdjunction.comp E'.toAdjunction).CommShift A) + end CommShift end From fceef13c1e9adc7b86abf7215e508050a45bc2ad Mon Sep 17 00:00:00 2001 From: blizzard_inc Date: Mon, 6 Jan 2025 13:23:12 +0000 Subject: [PATCH 011/681] fix: Allow multiple builds on staging branch (#20515) as mentioned on [zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/ci.20on.20master.20is.20failing/near/492095011), staging CI fails, which we don't want. This pr allows multiple build runs on the `staging` branch at a time, which should hopefully fix the issue --- .github/build.in.yml | 3 ++- .github/workflows/bors.yml | 3 ++- .github/workflows/build.yml | 3 ++- .github/workflows/build_fork.yml | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/build.in.yml b/.github/build.in.yml index b7acc84572050..69c40f7765dae 100644 --- a/.github/build.in.yml +++ b/.github/build.in.yml @@ -15,7 +15,8 @@ env: concurrency: # label each workflow run; only the latest with each label will run # workflows on master get more expressive labels - group: ${{ github.workflow }}-${{ github.ref }}.${{(github.ref == 'refs/heads/master' && github.run_id) || ''}} + group: ${{ github.workflow }}-${{ github.ref }}. + ${{ ( contains(fromJSON( '["refs/heads/master", "refs/heads/staging"]'), github.ref ) && github.run_id) || ''}} # cancel any running workflow with the same label cancel-in-progress: true diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index 37c0ac50d19a0..3149eccc52722 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -25,7 +25,8 @@ env: concurrency: # label each workflow run; only the latest with each label will run # workflows on master get more expressive labels - group: ${{ github.workflow }}-${{ github.ref }}.${{(github.ref == 'refs/heads/master' && github.run_id) || ''}} + group: ${{ github.workflow }}-${{ github.ref }}. + ${{ ( contains(fromJSON( '["refs/heads/master", "refs/heads/staging"]'), github.ref ) && github.run_id) || ''}} # cancel any running workflow with the same label cancel-in-progress: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62525af3c3089..5a3bc5d84c1b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,7 +32,8 @@ env: concurrency: # label each workflow run; only the latest with each label will run # workflows on master get more expressive labels - group: ${{ github.workflow }}-${{ github.ref }}.${{(github.ref == 'refs/heads/master' && github.run_id) || ''}} + group: ${{ github.workflow }}-${{ github.ref }}. + ${{ ( contains(fromJSON( '["refs/heads/master", "refs/heads/staging"]'), github.ref ) && github.run_id) || ''}} # cancel any running workflow with the same label cancel-in-progress: true diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index 14ae2662c9d09..d7ceebe6b73e3 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -29,7 +29,8 @@ env: concurrency: # label each workflow run; only the latest with each label will run # workflows on master get more expressive labels - group: ${{ github.workflow }}-${{ github.ref }}.${{(github.ref == 'refs/heads/master' && github.run_id) || ''}} + group: ${{ github.workflow }}-${{ github.ref }}. + ${{ ( contains(fromJSON( '["refs/heads/master", "refs/heads/staging"]'), github.ref ) && github.run_id) || ''}} # cancel any running workflow with the same label cancel-in-progress: true From d5cc7c85a7795dcbd6fca653498bd3e643edba0a Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Mon, 6 Jan 2025 14:27:26 +0000 Subject: [PATCH 012/681] feat(RingTheory): classification of etale algebras over fields (#20324) Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/RingTheory/Etale/Field.lean | 70 +++++++++++++++++++++++++-- Mathlib/RingTheory/Etale/Pi.lean | 36 ++++++++++++++ Mathlib/RingTheory/Smooth/Pi.lean | 3 ++ Mathlib/RingTheory/Unramified/Pi.lean | 3 ++ 5 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 Mathlib/RingTheory/Etale/Pi.lean diff --git a/Mathlib.lean b/Mathlib.lean index 99606d29a64b3..2a2fd484ec0df 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4388,6 +4388,7 @@ import Mathlib.RingTheory.EisensteinCriterion import Mathlib.RingTheory.EssentialFiniteness import Mathlib.RingTheory.Etale.Basic import Mathlib.RingTheory.Etale.Field +import Mathlib.RingTheory.Etale.Pi import Mathlib.RingTheory.EuclideanDomain import Mathlib.RingTheory.Extension import Mathlib.RingTheory.Filtration diff --git a/Mathlib/RingTheory/Etale/Field.lean b/Mathlib/RingTheory/Etale/Field.lean index 3e6b3bd1c7814..be84c58cf9418 100644 --- a/Mathlib/RingTheory/Etale/Field.lean +++ b/Mathlib/RingTheory/Etale/Field.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.RingTheory.Etale.Basic +import Mathlib.RingTheory.Etale.Pi import Mathlib.RingTheory.Unramified.Field /-! @@ -14,9 +14,14 @@ import Mathlib.RingTheory.Unramified.Field Let `K` be a field, `A` be a `K`-algebra and `L` be a field extension of `K`. - `Algebra.FormallyEtale.of_isSeparable`: - If `L` is separable over `K`, then `L` is formally etale over `K`. + If `L` is separable over `K`, then `L` is formally étale over `K`. - `Algebra.FormallyEtale.iff_isSeparable`: - If `L` is (essentially) of finite type over `K`, then `L/K` is etale iff `L/K` is separable. + If `L` is (essentially) of finite type over `K`, then `L/K` is étale iff `L/K` is separable. +- `Algebra.FormallyEtale.iff_exists_algEquiv_prod`: + If `A` is (essentially) of finite type over `K`, + then `A/K` is étale iff `A` is a finite product of separable field extensions. +- `Algebra.Etale.iff_exists_algEquiv_prod`: + `A/K` is étale iff `A` is a finite product of finite separable field extensions. ## References @@ -27,7 +32,7 @@ Let `K` be a field, `A` be a `K`-algebra and `L` be a field extension of `K`. universe u -variable (K L : Type u) [Field K] [Field L] [Algebra K L] +variable (K L A : Type u) [Field K] [Field L] [CommRing A] [Algebra K L] [Algebra K A] open Algebra Polynomial @@ -148,4 +153,61 @@ theorem iff_isSeparable [EssFiniteType K L] : FormallyEtale K L ↔ Algebra.IsSeparable K L := ⟨fun _ ↦ FormallyUnramified.isSeparable K L, fun _ ↦ of_isSeparable K L⟩ +attribute [local instance] + IsArtinianRing.subtype_isMaximal_finite IsArtinianRing.fieldOfSubtypeIsMaximal in +/-- +If `A` is an essentially of finite type algebra over a field `K`, then `A` is formally étale +over `K` if and only if `A` is a finite product of separable field extensions. +-/ +theorem iff_exists_algEquiv_prod [EssFiniteType K A] : + FormallyEtale K A ↔ + ∃ (I : Type u) (_ : Finite I) (Ai : I → Type u) (_ : ∀ i, Field (Ai i)) + (_ : ∀ i, Algebra K (Ai i)) (_ : A ≃ₐ[K] Π i, Ai i), + ∀ i, Algebra.IsSeparable K (Ai i) := by + classical + constructor + · intro H + have := FormallyUnramified.finite_of_free K A + have := FormallyUnramified.isReduced_of_field K A + have : IsArtinianRing A := isArtinian_of_tower K inferInstance + letI : Fintype {I : Ideal A | I.IsMaximal} := (nonempty_fintype _).some + let v (i : {I : Ideal A | I.IsMaximal}) : A := (IsArtinianRing.equivPi A).symm (Pi.single i 1) + let e : A ≃ₐ[K] _ := { __ := IsArtinianRing.equivPi A, commutes' := fun r ↦ rfl } + have := (FormallyEtale.iff_of_equiv e).mp inferInstance + rw [FormallyEtale.pi_iff] at this + exact ⟨_, inferInstance, _, _, _, e, fun I ↦ (iff_isSeparable _ _).mp inferInstance⟩ + · intro ⟨I, _, Ai, _, _, e, _⟩ + rw [FormallyEtale.iff_of_equiv e, FormallyEtale.pi_iff] + have (i) : EssFiniteType K (Ai i) := by + letI := ((Pi.evalRingHom Ai i).comp e.toRingHom).toAlgebra + have : IsScalarTower K A (Ai i) := + .of_algebraMap_eq fun r ↦ by simp [RingHom.algebraMap_toAlgebra] + have : Algebra.FiniteType A (Ai i) := .of_surjective inferInstance (Algebra.ofId _ _) + (RingHomSurjective.is_surjective (σ := Pi.evalRingHom Ai i).comp e.surjective) + exact EssFiniteType.comp K A (Ai i) + exact fun I ↦ (iff_isSeparable _ _).mpr inferInstance + end Algebra.FormallyEtale + +attribute [local instance] + IsArtinianRing.subtype_isMaximal_finite IsArtinianRing.fieldOfSubtypeIsMaximal in +/-- +`A` is étale over a field `K` if and only if +`A` is a finite product of finite separable field extensions. +-/ +theorem Algebra.Etale.iff_exists_algEquiv_prod : + Etale K A ↔ + ∃ (I : Type u) (_ : Finite I) (Ai : I → Type u) (_ : ∀ i, Field (Ai i)) + (_ : ∀ i, Algebra K (Ai i)) (_ : A ≃ₐ[K] Π i, Ai i), + ∀ i, Module.Finite K (Ai i) ∧ Algebra.IsSeparable K (Ai i) := by + constructor + · intro H + obtain ⟨I, _, Ai, _, _, e, _⟩ := (FormallyEtale.iff_exists_algEquiv_prod K A).mp inferInstance + have := FormallyUnramified.finite_of_free K A + exact ⟨_, ‹_›, _, _, _, e, fun i ↦ ⟨.of_surjective ((LinearMap.proj i).comp e.toLinearMap) + ((Function.surjective_eval i).comp e.surjective), inferInstance⟩⟩ + · intro ⟨I, _, Ai, _, _, e, H⟩ + choose h₁ h₂ using H + have := Module.Finite.of_surjective e.symm.toLinearMap e.symm.surjective + refine ⟨?_, FinitePresentation.of_finiteType.mp inferInstance⟩ + exact (FormallyEtale.iff_exists_algEquiv_prod K A).mpr ⟨_, inferInstance, _, _, _, e, h₂⟩ diff --git a/Mathlib/RingTheory/Etale/Pi.lean b/Mathlib/RingTheory/Etale/Pi.lean new file mode 100644 index 0000000000000..0e50eccd56627 --- /dev/null +++ b/Mathlib/RingTheory/Etale/Pi.lean @@ -0,0 +1,36 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.RingTheory.Smooth.Pi +import Mathlib.RingTheory.Unramified.Pi +import Mathlib.RingTheory.Etale.Basic + +/-! + +# Formal-étaleness of finite products of rings + +## Main result + +- `Algebra.FormallyEtale.pi_iff`: If `I` is finite, `Π i : I, A i` is `R`-formally-étale + if and only if each `A i` is `R`-formally-étale. + +-/ + +universe u v + +namespace Algebra.FormallyEtale + +variable {R : Type (max u v)} {I : Type u} (A : I → Type (max u v)) +variable [CommRing R] [∀ i, CommRing (A i)] [∀ i, Algebra R (A i)] + +theorem pi_iff [Finite I] : + FormallyEtale R (Π i, A i) ↔ ∀ i, FormallyEtale R (A i) := by + simp_rw [FormallyEtale.iff_unramified_and_smooth, forall_and] + rw [FormallyUnramified.pi_iff A, FormallySmooth.pi_iff A] + +instance [Finite I] [∀ i, FormallyEtale R (A i)] : FormallyEtale R (Π i, A i) := + .of_unramified_and_smooth + +end Algebra.FormallyEtale diff --git a/Mathlib/RingTheory/Smooth/Pi.lean b/Mathlib/RingTheory/Smooth/Pi.lean index cfb4cf1dd16df..aab45da1545e8 100644 --- a/Mathlib/RingTheory/Smooth/Pi.lean +++ b/Mathlib/RingTheory/Smooth/Pi.lean @@ -118,4 +118,7 @@ theorem pi_iff [Finite I] : rwa [mul_sub, ← map_mul, mul_comm, mul_assoc, (he.idem i).eq, he', ← map_mul, ← Pi.single_mul, one_mul, sub_eq_zero] at this +instance [Finite I] [∀ i, FormallySmooth R (A i)] : FormallySmooth R (Π i, A i) := + (pi_iff _).mpr ‹_› + end Algebra.FormallySmooth diff --git a/Mathlib/RingTheory/Unramified/Pi.lean b/Mathlib/RingTheory/Unramified/Pi.lean index 755c16a601f58..ddebc82f3785d 100644 --- a/Mathlib/RingTheory/Unramified/Pi.lean +++ b/Mathlib/RingTheory/Unramified/Pi.lean @@ -95,4 +95,7 @@ theorem pi_iff : Ideal.Quotient.mkₐ_eq_mk] exact Ideal.mem_map_of_mem (Ideal.Quotient.mk J') (hf (Pi.single x r)) +instance [∀ i, FormallyUnramified R (f i)] : FormallyUnramified R (Π i, f i) := + (pi_iff _).mpr ‹_› + end Algebra.FormallyUnramified From f0c7c5c091e494feb1f8abf7a8d0e71815f4b06a Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Mon, 6 Jan 2025 14:36:15 +0000 Subject: [PATCH 013/681] feat(ContinuousMultilinearMap): add lemmas about `.prod` (#20462) --- .../NormedSpace/Multilinear/Basic.lean | 7 +- .../Algebra/Module/Multilinear/Basic.lean | 67 +++++++++++++++++-- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index e45477c7b3695..c6c4a0ad92ef2 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -610,14 +610,9 @@ variable (𝕜 E E' G G') def prodL : ContinuousMultilinearMap 𝕜 E G × ContinuousMultilinearMap 𝕜 E G' ≃ₗᵢ[𝕜] ContinuousMultilinearMap 𝕜 E (G × G') where - toFun f := f.1.prod f.2 - invFun f := - ((ContinuousLinearMap.fst 𝕜 G G').compContinuousMultilinearMap f, - (ContinuousLinearMap.snd 𝕜 G G').compContinuousMultilinearMap f) + __ := prodEquiv map_add' _ _ := rfl map_smul' _ _ := rfl - left_inv f := by ext <;> rfl - right_inv f := by ext <;> rfl norm_map' f := opNorm_prod f.1 f.2 /-- `ContinuousMultilinearMap.pi` as a `LinearIsometryEquiv`. -/ diff --git a/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean b/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean index 65348675488a9..442b6637f5b9f 100644 --- a/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Multilinear/Basic.lean @@ -299,6 +299,55 @@ theorem _root_.ContinuousLinearMap.compContinuousMultilinearMap_coe (g : M₂ ext m rfl +/-- `ContinuousMultilinearMap.prod` as an `Equiv`. -/ +@[simps apply symm_apply_fst symm_apply_snd, simps (config := .lemmasOnly) symm_apply] +def prodEquiv : + (ContinuousMultilinearMap R M₁ M₂ × ContinuousMultilinearMap R M₁ M₃) ≃ + ContinuousMultilinearMap R M₁ (M₂ × M₃) where + toFun f := f.1.prod f.2 + invFun f := ((ContinuousLinearMap.fst _ _ _).compContinuousMultilinearMap f, + (ContinuousLinearMap.snd _ _ _).compContinuousMultilinearMap f) + left_inv _ := rfl + right_inv _ := rfl + +theorem prod_ext_iff {f g : ContinuousMultilinearMap R M₁ (M₂ × M₃)} : + f = g ↔ (ContinuousLinearMap.fst _ _ _).compContinuousMultilinearMap f = + (ContinuousLinearMap.fst _ _ _).compContinuousMultilinearMap g ∧ + (ContinuousLinearMap.snd _ _ _).compContinuousMultilinearMap f = + (ContinuousLinearMap.snd _ _ _).compContinuousMultilinearMap g := by + rw [← Prod.mk.inj_iff, ← prodEquiv_symm_apply, ← prodEquiv_symm_apply, Equiv.apply_eq_iff_eq] + +@[ext] +theorem prod_ext {f g : ContinuousMultilinearMap R M₁ (M₂ × M₃)} + (h₁ : (ContinuousLinearMap.fst _ _ _).compContinuousMultilinearMap f = + (ContinuousLinearMap.fst _ _ _).compContinuousMultilinearMap g) + (h₂ : (ContinuousLinearMap.snd _ _ _).compContinuousMultilinearMap f = + (ContinuousLinearMap.snd _ _ _).compContinuousMultilinearMap g) : f = g := + prod_ext_iff.mpr ⟨h₁, h₂⟩ + +theorem eq_prod_iff {f : ContinuousMultilinearMap R M₁ (M₂ × M₃)} + {g : ContinuousMultilinearMap R M₁ M₂} {h : ContinuousMultilinearMap R M₁ M₃} : + f = g.prod h ↔ (ContinuousLinearMap.fst _ _ _).compContinuousMultilinearMap f = g ∧ + (ContinuousLinearMap.snd _ _ _).compContinuousMultilinearMap f = h := + prod_ext_iff + +theorem add_prod_add [ContinuousAdd M₂] [ContinuousAdd M₃] + (f₁ f₂ : ContinuousMultilinearMap R M₁ M₂) (g₁ g₂ : ContinuousMultilinearMap R M₁ M₃) : + (f₁ + f₂).prod (g₁ + g₂) = f₁.prod g₁ + f₂.prod g₂ := + rfl + +theorem smul_prod_smul {S : Type*} [Monoid S] [DistribMulAction S M₂] [DistribMulAction S M₃] + [ContinuousConstSMul S M₂] [SMulCommClass R S M₂] + [ContinuousConstSMul S M₃] [SMulCommClass R S M₃] + (c : S) (f : ContinuousMultilinearMap R M₁ M₂) (g : ContinuousMultilinearMap R M₁ M₃) : + (c • f).prod (c • g) = c • f.prod g := + rfl + +@[simp] +theorem zero_prod_zero : + (0 : ContinuousMultilinearMap R M₁ M₂).prod (0 : ContinuousMultilinearMap R M₁ M₃) = 0 := + rfl + /-- `ContinuousMultilinearMap.pi` as an `Equiv`. -/ @[simps] def piEquiv {ι' : Type*} {M' : ι' → Type*} [∀ i, AddCommMonoid (M' i)] @@ -306,12 +355,8 @@ def piEquiv {ι' : Type*} {M' : ι' → Type*} [∀ i, AddCommMonoid (M' i)] (∀ i, ContinuousMultilinearMap R M₁ (M' i)) ≃ ContinuousMultilinearMap R M₁ (∀ i, M' i) where toFun := ContinuousMultilinearMap.pi invFun f i := (ContinuousLinearMap.proj i : _ →L[R] M' i).compContinuousMultilinearMap f - left_inv f := by - ext - rfl - right_inv f := by - ext - rfl + left_inv _ := rfl + right_inv _ := rfl /-- An equivalence of the index set defines an equivalence between the spaces of continuous multilinear maps. This is the forward map of this equivalence. -/ @@ -453,6 +498,16 @@ instance : AddCommGroup (ContinuousMultilinearMap R M₁ M₂) := toMultilinearMap_injective.addCommGroup _ rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl +theorem neg_prod_neg [AddCommGroup M₃] [Module R M₃] [TopologicalSpace M₃] [TopologicalAddGroup M₃] + (f : ContinuousMultilinearMap R M₁ M₂) (g : ContinuousMultilinearMap R M₁ M₃) : + (-f).prod (-g) = - f.prod g := + rfl + +theorem sub_prod_sub [AddCommGroup M₃] [Module R M₃] [TopologicalSpace M₃] [TopologicalAddGroup M₃] + (f₁ f₂ : ContinuousMultilinearMap R M₁ M₂) (g₁ g₂ : ContinuousMultilinearMap R M₁ M₃) : + (f₁ - f₂).prod (g₁ - g₂) = f₁.prod g₁ - f₂.prod g₂ := + rfl + end TopologicalAddGroup end Ring From 15b2729d1e0f9d80a5d712fc3734db52d8c60069 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Mon, 6 Jan 2025 14:48:38 +0000 Subject: [PATCH 014/681] feat(Combinatorics/SimpleGraph/Walk): add `penultimate` and `snd` (#16769) Here are some reasons for it: - We want to add `penultimate`, as `p.getVert (p.length - 1)` duplicates `p`, and `snd` should exist for symmetry. - In some cases it makes sense to consider the vertices of a walk without the first/last one, and then this is the walk version of `List.head`/`List.last`, not `l[1]`/`l[l.size-2]` - In walks the first/last node and adjacency are a lot more important than they usually are in lists, so it makes more sense to have a special term for the node adjacent to the first/last node. - Walks always have a sensible default, so there's no need for the "take a proof/default value/panic/return an option" duplication which lists have and so this doesn't require much API. Co-authored-by: Daniel Weber <55664973+Command-Master@users.noreply.github.com> --- .../Combinatorics/SimpleGraph/Acyclic.lean | 2 +- .../Connectivity/WalkCounting.lean | 2 +- Mathlib/Combinatorics/SimpleGraph/Path.lean | 9 ++- Mathlib/Combinatorics/SimpleGraph/Walk.lean | 80 ++++++++++++++----- 4 files changed, 68 insertions(+), 25 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean b/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean index 9782814a525cc..126e91256aa32 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean @@ -175,7 +175,7 @@ lemma IsTree.card_edgeFinset [Fintype V] [Fintype G.edgeSet] (hG : G.IsTree) : length_tail_add_one (not_nil_of_ne (by simpa using ha))] at h3 omega · simp only [ne_eq, eq_mp_eq_cast, id_eq, isPath_copy] - exact (hf _).tail (not_nil_of_ne (by simpa using ha)) + exact (hf _).tail case surj => simp only [mem_edgeFinset, Finset.mem_compl, Finset.mem_singleton, Sym2.forall, mem_edgeSet] intros x y h diff --git a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean index 01d7e6a4232f3..10adfe87aff11 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean @@ -63,7 +63,7 @@ Note that `u` and `v` may be the same. -/ @[simps] def walkLengthTwoEquivCommonNeighbors (u v : V) : {p : G.Walk u v // p.length = 2} ≃ G.commonNeighbors u v where - toFun p := ⟨p.val.getVert 1, match p with + toFun p := ⟨p.val.snd, match p with | ⟨.cons _ (.cons _ .nil), _⟩ => ⟨‹G.Adj u _›, ‹G.Adj _ v›.symm⟩⟩ invFun w := ⟨w.prop.1.toWalk.concat w.prop.2.symm, rfl⟩ left_inv | ⟨.cons _ (.cons _ .nil), hp⟩ => by rfl diff --git a/Mathlib/Combinatorics/SimpleGraph/Path.lean b/Mathlib/Combinatorics/SimpleGraph/Path.lean index 34fc605b7283d..e95e8857cb5e8 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Path.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Path.lean @@ -258,10 +258,11 @@ lemma isCycle_reverse {p : G.Walk u u} : p.reverse.IsCycle ↔ p.IsCycle where mp h := by simpa using h.reverse mpr := .reverse -lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) (hp' : ¬ p.Nil) : p.tail.IsPath := by - rw [Walk.isPath_def] at hp ⊢ - rw [← cons_support_tail _ hp', List.nodup_cons] at hp - exact hp.2 +lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) : p.tail.IsPath := by + cases p with + | nil => simp + | cons hadj p => + simp_all [Walk.isPath_def] /-! ### About paths -/ diff --git a/Mathlib/Combinatorics/SimpleGraph/Walk.lean b/Mathlib/Combinatorics/SimpleGraph/Walk.lean index ae8224b0ec59d..af48c233e9bcd 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Walk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Walk.lean @@ -155,6 +155,9 @@ def getVert {u v : V} : G.Walk u v → ℕ → V @[simp] theorem getVert_zero {u v} (w : G.Walk u v) : w.getVert 0 = u := by cases w <;> rfl +@[simp] +theorem getVert_nil (u : V) {i : ℕ} : (@nil _ G u).getVert i = u := rfl + theorem getVert_of_length_le {u v} (w : G.Walk u v) {i : ℕ} (hi : w.length ≤ i) : w.getVert i = v := by induction w generalizing i with @@ -177,11 +180,6 @@ theorem adj_getVert_succ {u v} (w : G.Walk u v) {i : ℕ} (hi : i < w.length) : · simp [getVert, hxy] · exact ih (Nat.succ_lt_succ_iff.1 hi) -lemma getVert_cons_one {u v w} (q : G.Walk v w) (hadj : G.Adj u v) : - (q.cons hadj).getVert 1 = v := by - have : (q.cons hadj).getVert 1 = q.getVert 0 := rfl - simpa [getVert_zero] using this - @[simp] lemma getVert_cons_succ {u v w n} (p : G.Walk v w) (h : G.Adj u v) : (p.cons h).getVert (n + 1) = p.getVert n := rfl @@ -829,10 +827,6 @@ lemma notNilRec_cons {motive : {u w : V} → (p : G.Walk u w) → ¬ p.Nil → S motive (q.cons h) Walk.not_nil_cons) (h' : G.Adj u v) (q' : G.Walk v w) : @Walk.notNilRec _ _ _ _ _ cons _ _ = cons h' q' := by rfl -@[simp] lemma adj_getVert_one {p : G.Walk v w} (hp : ¬ p.Nil) : - G.Adj v (p.getVert 1) := by - simpa using adj_getVert_succ p (by simpa [not_nil_iff_lt_length] using hp : 0 < p.length) - /-- The walk obtained by removing the first `n` darts of a walk. -/ def drop {u v : V} (p : G.Walk u v) (n : ℕ) : G.Walk (p.getVert n) v := match p, n with @@ -840,11 +834,49 @@ def drop {u v : V} (p : G.Walk u v) (n : ℕ) : G.Walk (p.getVert n) v := | p, 0 => p.copy (getVert_zero p).symm rfl | .cons h q, (n + 1) => (q.drop n).copy (getVert_cons_succ _ h).symm rfl -/-- The walk obtained by removing the first dart of a non-nil walk. -/ -def tail (p : G.Walk u v) : G.Walk (p.getVert 1) v := p.drop 1 +/-- The second vertex of a walk, or the only vertex in a nil walk. -/ +abbrev snd (p : G.Walk u v) : V := p.getVert 1 + +@[simp] lemma adj_snd {p : G.Walk v w} (hp : ¬ p.Nil) : + G.Adj v p.snd := by + simpa using adj_getVert_succ p (by simpa [not_nil_iff_lt_length] using hp : 0 < p.length) + +lemma snd_cons {u v w} (q : G.Walk v w) (hadj : G.Adj u v) : + (q.cons hadj).snd = v := by simp + +/-- The penultimate vertex of a walk, or the only vertex in a nil walk. -/ +abbrev penultimate (p : G.Walk u v) : V := p.getVert (p.length - 1) + +@[simp] +lemma penultimate_cons_nil (h : G.Adj u v) : (cons h nil).penultimate = u := rfl + +@[simp] +lemma penultimate_cons_cons {w'} (h : G.Adj u v) (h₂ : G.Adj v w) (p : G.Walk w w') : + (cons h (cons h₂ p)).penultimate = (cons h₂ p).penultimate := rfl + +lemma penultimate_cons_of_not_nil (h : G.Adj u v) (p : G.Walk v w) (hp : ¬ p.Nil) : + (cons h p).penultimate = p.penultimate := + p.notNilRec (by simp) hp h + +@[simp] +lemma penultimate_concat {t u v} (p : G.Walk u v) (h : G.Adj v t) : + (p.concat h).penultimate = v := by simp [penultimate, concat_eq_append, getVert_append] + +@[simp] +lemma adj_penultimate {p : G.Walk v w} (hp : ¬ p.Nil) : + G.Adj p.penultimate w := by + conv => rhs; rw [← getVert_length p] + rw [nil_iff_length_eq] at hp + convert adj_getVert_succ _ _ <;> omega + +/-- The walk obtained by removing the first dart of a walk. A nil walk stays nil. -/ +def tail (p : G.Walk u v) : G.Walk (p.snd) v := p.drop 1 + +@[simp] +lemma tail_nil : (@nil _ G v).tail = .nil := rfl @[simp] -lemma tail_cons_nil (h : G.Adj u v) : (Walk.cons h .nil).tail = .nil := by rfl +lemma tail_cons_nil (h : G.Adj u v) : (Walk.cons h .nil).tail = .nil := rfl lemma tail_cons_eq (h : G.Adj u v) (p : G.Walk v w) : (p.cons h).tail = p.copy (getVert_zero p).symm rfl := by @@ -856,16 +888,26 @@ lemma tail_cons_eq (h : G.Adj u v) (p : G.Walk v w) : @[simps] def firstDart (p : G.Walk v w) (hp : ¬ p.Nil) : G.Dart where fst := v - snd := p.getVert 1 - adj := p.adj_getVert_one hp + snd := p.snd + adj := p.adj_snd hp + +/-- The last dart of a walk. -/ +@[simps] +def lastDart (p : G.Walk v w) (hp : ¬ p.Nil) : G.Dart where + fst := p.penultimate + snd := w + adj := p.adj_penultimate hp lemma edge_firstDart (p : G.Walk v w) (hp : ¬ p.Nil) : - (p.firstDart hp).edge = s(v, p.getVert 1) := rfl + (p.firstDart hp).edge = s(v, p.snd) := rfl + +lemma edge_lastDart (p : G.Walk v w) (hp : ¬ p.Nil) : + (p.lastDart hp).edge = s(p.penultimate, w) := rfl variable {x y : V} -- TODO: rename to u, v, w instead? lemma cons_tail_eq (p : G.Walk x y) (hp : ¬ p.Nil) : - cons (p.adj_getVert_one hp) p.tail = p := by + cons (p.adj_snd hp) p.tail = p := by cases p with | nil => simp only [nil_nil, not_true_eq_false] at hp | cons h q => @@ -1085,7 +1127,7 @@ theorem exists_boundary_dart {u v : V} (p : G.Walk u v) (S : Set V) (uS : u ∈ | .cons hadj q, 0 => simp only [copy_rfl_rfl, getVert_zero] | .cons hadj q, (n + 1) => simp only [copy_cons, getVert_cons_succ]; rfl -@[simp] lemma getVert_tail {u v n} (p : G.Walk u v) (hnp: ¬ p.Nil) : +@[simp] lemma getVert_tail {u v n} (p : G.Walk u v) : p.tail.getVert n = p.getVert (n + 1) := by match p with | .nil => rfl @@ -1121,8 +1163,8 @@ theorem mem_support_iff_exists_getVert {u v w : V} {p : G.Walk v w} : rw [mem_support_iff_exists_getVert] use n - 1 simp only [Nat.sub_le_iff_le_add] - rw [getVert_tail _ hnp, length_tail_add_one hnp] - have : (n - 1 + 1) = n:= by omega + rw [getVert_tail, length_tail_add_one hnp] + have : (n - 1 + 1) = n := by omega rwa [this] termination_by p.length decreasing_by From 9ab795afa4a2d4098113c0e893a6a95969ea4cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 6 Jan 2025 15:20:42 +0000 Subject: [PATCH 015/681] feat(1000): fill in more entries (#20470) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/) --------- Co-authored-by: Rémy Degenne --- .../InnerProductSpace/Projection.lean | 6 +- Mathlib/Combinatorics/SetFamily/LYM.lean | 2 +- .../MeasureTheory/Covering/Besicovitch.lean | 27 ++-- Mathlib/MeasureTheory/Covering/Vitali.lean | 14 +- docs/1000.yaml | 142 +++++++++++++++++- 5 files changed, 167 insertions(+), 24 deletions(-) diff --git a/Mathlib/Analysis/InnerProductSpace/Projection.lean b/Mathlib/Analysis/InnerProductSpace/Projection.lean index 902821ff1cdfd..ca88319d17068 100644 --- a/Mathlib/Analysis/InnerProductSpace/Projection.lean +++ b/Mathlib/Analysis/InnerProductSpace/Projection.lean @@ -63,10 +63,10 @@ local notation "absR" => abs -- FIXME this monolithic proof causes a deterministic timeout with `-T50000` -- It should be broken in a sequence of more manageable pieces, -- perhaps with individual statements for the three steps below. -/-- Existence of minimizers +/-- **Existence of minimizers**, aka the **Hilbert projection theorem**. + Let `u` be a point in a real inner product space, and let `K` be a nonempty complete convex subset. -Then there exists a (unique) `v` in `K` that minimizes the distance `‖u - v‖` to `u`. - -/ +Then there exists a (unique) `v` in `K` that minimizes the distance `‖u - v‖` to `u`. -/ theorem exists_norm_eq_iInf_of_complete_convex {K : Set F} (ne : K.Nonempty) (h₁ : IsComplete K) (h₂ : Convex ℝ K) : ∀ u : F, ∃ v ∈ K, ‖u - v‖ = ⨅ w : K, ‖u - w‖ := fun u => by let δ := ⨅ w : K, ‖u - w‖ diff --git a/Mathlib/Combinatorics/SetFamily/LYM.lean b/Mathlib/Combinatorics/SetFamily/LYM.lean index 67a603abd4165..24ec53fa6da54 100644 --- a/Mathlib/Combinatorics/SetFamily/LYM.lean +++ b/Mathlib/Combinatorics/SetFamily/LYM.lean @@ -211,7 +211,7 @@ end LYM /-- **Sperner's theorem**. The size of an antichain in `Finset α` is bounded by the size of the maximal layer in `Finset α`. This precisely means that `Finset α` is a Sperner order. -/ -theorem IsAntichain.sperner [Fintype α] {𝒜 : Finset (Finset α)} +theorem _root_.IsAntichain.sperner [Fintype α] {𝒜 : Finset (Finset α)} (h𝒜 : IsAntichain (· ⊆ ·) (𝒜 : Set (Finset α))) : #𝒜 ≤ (Fintype.card α).choose (Fintype.card α / 2) := by classical diff --git a/Mathlib/MeasureTheory/Covering/Besicovitch.lean b/Mathlib/MeasureTheory/Covering/Besicovitch.lean index a21afb385c697..9f8b24ead46f2 100644 --- a/Mathlib/MeasureTheory/Covering/Besicovitch.lean +++ b/Mathlib/MeasureTheory/Covering/Besicovitch.lean @@ -791,14 +791,17 @@ theorem exists_disjoint_closedBall_covering_ae_of_finiteMeasure_aux (μ : Measur rw [← Nat.succ_eq_add_one, u_succ] exact (hF (u n) (Pu n)).1 -/-- The measurable Besicovitch covering theorem. Assume that, for any `x` in a set `s`, -one is given a set of admissible closed balls centered at `x`, with arbitrarily small radii. -Then there exists a disjoint covering of almost all `s` by admissible closed balls centered at some -points of `s`. -This version requires that the underlying measure is sigma-finite, and that the space has the +/-- The measurable **Besicovitch covering theorem**. + +Assume that, for any `x` in a set `s`, one is given a set of admissible closed balls centered at +`x`, with arbitrarily small radii. Then there exists a disjoint covering of almost all `s` by +admissible closed balls centered at some points of `s`. + +This version requires the underlying measure to be sigma-finite, and the space to have the Besicovitch covering property (which is satisfied for instance by normed real vector spaces). It expresses the conclusion in a slightly awkward form (with a subset of `α × ℝ`) coming from the proof technique. + For a version giving the conclusion in a nicer form, see `exists_disjoint_closedBall_covering_ae`. -/ theorem exists_disjoint_closedBall_covering_ae_aux (μ : Measure α) [SFinite μ] (f : α → Set ℝ) @@ -813,12 +816,14 @@ theorem exists_disjoint_closedBall_covering_ae_aux (μ : Measure α) [SFinite μ ⟨t, t_count, ts, tr, tν, tdisj⟩ exact ⟨t, t_count, ts, tr, hμν tν, tdisj⟩ -/-- The measurable Besicovitch covering theorem. Assume that, for any `x` in a set `s`, -one is given a set of admissible closed balls centered at `x`, with arbitrarily small radii. -Then there exists a disjoint covering of almost all `s` by admissible closed balls centered at some -points of `s`. We can even require that the radius at `x` is bounded by a given function `R x`. -(Take `R = 1` if you don't need this additional feature). -This version requires that the underlying measure is sigma-finite, and that the space has the +/-- The measurable **Besicovitch covering theorem**. + +Assume that, for any `x` in a set `s`, one is given a set of admissible closed balls centered at +`x`, with arbitrarily small radii. Then there exists a disjoint covering of almost all `s` by +admissible closed balls centered at some points of `s`. We can even require that the radius at `x` +is bounded by a given function `R x`. (Take `R = 1` if you don't need this additional feature). + +This version requires the underlying measure to be sigma-finite, and the space to have the Besicovitch covering property (which is satisfied for instance by normed real vector spaces). -/ theorem exists_disjoint_closedBall_covering_ae (μ : Measure α) [SFinite μ] (f : α → Set ℝ) diff --git a/Mathlib/MeasureTheory/Covering/Vitali.lean b/Mathlib/MeasureTheory/Covering/Vitali.lean index 416a61a4c48c3..5b2934b6db6d8 100644 --- a/Mathlib/MeasureTheory/Covering/Vitali.lean +++ b/Mathlib/MeasureTheory/Covering/Vitali.lean @@ -198,12 +198,14 @@ theorem exists_disjoint_subfamily_covering_enlargement_closedBall alias exists_disjoint_subfamily_covering_enlargment_closedBall := exists_disjoint_subfamily_covering_enlargement_closedBall -/-- The measurable Vitali covering theorem. Assume one is given a family `t` of closed sets with -nonempty interior, such that each `a ∈ t` is included in a ball `B (x, r)` and covers a definite -proportion of the ball `B (x, 3 r)` for a given measure `μ` (think of the situation where `μ` is -a doubling measure and `t` is a family of balls). Consider a (possibly non-measurable) set `s` -at which the family is fine, i.e., every point of `s` belongs to arbitrarily small elements of `t`. -Then one can extract from `t` a disjoint subfamily that covers almost all `s`. +/-- The measurable **Vitali covering theorem**. + +Assume one is given a family `t` of closed sets with nonempty interior, such that each `a ∈ t` is +included in a ball `B (x, r)` and covers a definite proportion of the ball `B (x, 3 r)` for a given +measure `μ` (think of the situation where `μ` is a doubling measure and `t` is a family of balls). +Consider a (possibly non-measurable) set `s` at which the family is fine, i.e., every point of `s` +belongs to arbitrarily small elements of `t`. Then one can extract from `t` a disjoint subfamily +that covers almost all `s`. For more flexibility, we give a statement with a parameterized family of sets. -/ diff --git a/docs/1000.yaml b/docs/1000.yaml index 50d0e3fb4af8f..b7f982e4112d6 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -39,6 +39,9 @@ Q32182: Q33481: title: Arrow's impossibility theorem + author: Benjamin Davidson, Andrew Souther + date: 2021 + url: https://github.com/asouther4/lean-social-choice/blob/master/src/arrows_theorem.lean Q98831: title: Multiplication theorem @@ -54,9 +57,13 @@ Q132427: Q132469: title: Fermat's Last Theorem + # See https://imperialcollegelondon.github.io/FLT/ Q137164: title: Besicovitch covering theorem + decl: Besicovitch.exists_disjoint_closedBall_covering_ae + author: Sébastien Gouëzel + date: 2021 Q154210: title: CPCTC @@ -72,6 +79,9 @@ Q174955: Q179208: title: Cayley's theorem + decl: Equiv.Perm.subgroupOfMulAction + author: Eric Wieser + date: 2021 Q179467: title: Fourier theorem @@ -88,12 +98,17 @@ Q180345: Q182505: title: Bayes' theorem decl: ProbabilityTheory.cond_eq_inv_mul_cond_mul + author: Rishikesh Vaishnav + date: 2022 Q184410: title: Four color theorem Q188295: title: Fermat's little theorem + decl: ZMod.pow_card_sub_one_eq_one + author: Aaron Anderson + date: 2020 Q188745: title: Classification of Platonic solids @@ -104,6 +119,7 @@ Q189136: # XXX: other branch found exists_ratio_deriv_eq_ratio_slope, # is about Cauchy's vs Lagrange's Mean Value Theorem, TODO decide! author: Yury G. Kudryashov + date: 2019 Q190026: title: Ford's theorem @@ -119,16 +135,25 @@ Q190556: title: De Moivre's theorem decl: Complex.cos_add_sin_mul_I_pow author: Abhimanyu Pallavi Sudhir + date: 2019 Q191693: title: Lebesgue's decomposition theorem + decl: MeasureTheory.Measure.haveLebesgueDecomposition_of_sigmaFinite + author: Kexing Ying + date: 2021 Q192760: title: Fundamental theorem of algebra + decl: Complex.isAlgClosed + author: Chris Hughes + date: 2019 Q193286: title: Rolle's theorem decl: exists_deriv_eq_zero + author: Yury G. Kudryashov + date: 2019 Q193878: title: Chinese remainder theorem @@ -159,6 +184,7 @@ Q203565: title: Solutions of a general cubic equation decl: Theorems100.cubic_eq_zero_iff author: Jeoff Lee + date: 2022 Q204884: title: Löb's theorem @@ -529,6 +555,9 @@ Q608294: Q609612: title: Knaster–Tarski theorem + decl: fixedPoints.completeLattice + author: Kenny Lau + date: 2018 Q612021: title: Gibbard–Satterthwaite theorem @@ -563,6 +592,7 @@ Q642620: title: Krein–Milman theorem decl: closure_convexHull_extremePoints author: Yaël Dillies + date: 2022 Q643513: title: Riesz–Fischer theorem @@ -655,15 +685,22 @@ Q716171: title: Erdős–Ginzburg–Ziv theorem decl: ZMod.erdos_ginzburg_ziv author: Yaël Dillies + date: 2023 Q718875: title: Erdős–Ko–Rado theorem + decl: Finset.erdos_ko_rado + author: Bhavik Mehta, Yaël Dillies + date: 2020 Q719966: title: Toda's theorem Q720469: title: Chevalley–Warning theorem + decl: char_dvd_card_solutions_of_sum_lt + author: Johan Commelin + date: 2019 Q721695: title: Szemerédi–Trotter theorem @@ -702,6 +739,9 @@ Q744440: Q748233: title: Sylvester–Gallai theorem + author: Bhavik Mehta + url: https://github.com/YaelDillies/LeanCamCombi/blob/6a6a670f324b2af82ae17f21f9d51ac0bc859f6f/LeanCamCombi/SylvesterChvatal.lean#L610 + date: 2022 Q751120: title: Thue–Siegel–Roth theorem @@ -709,6 +749,8 @@ Q751120: Q752375: title: Extreme value theorem decl: IsCompact.exists_isMinOn + author: Sébastien Gouëzel + date: 2018 Q755986: title: Atiyah–Bott fixed-point theorem @@ -720,6 +762,7 @@ Q756946: title: Lagrange's four-square theorem decl: Nat.sum_four_squares author: Chris Hughes + date: 2019 Q764287: title: Van der Waerden's theorem @@ -777,6 +820,9 @@ Q830513: Q834025: title: Cauchy integral theorem + decl: Complex.circleIntegral_div_sub_of_differentiable_on_off_countable + author: Yury Kudryashov + date: 2021 Q834211: title: Wallace–Bolyai–Gerwien theorem @@ -793,6 +839,9 @@ Q841893: Q842953: title: Lebesgue's density theorem + decl: Besicovitch.ae_tendsto_measure_inter_div + author: Oliver Nash + date: 2022 Q844612: title: Brun's theorem @@ -967,8 +1016,10 @@ Q944297: # Banach open mapping theorem/Banach-Schauder theorem in functional analysis is in mathlib (ContinuousLinearMap.isOpenMap) Q948664: - title: Kneser's theorem - # TODO: is this in mathlib already? + title: Kneser's addition theorem + author: Mantas Bakšys, Yaël Dillies + url: https://github.com/YaelDillies/LeanCamCombi/blob/master/LeanCamCombi/Kneser/Kneser.lean + date: 2022 Q951327: title: Pasch's theorem @@ -1166,6 +1217,7 @@ Q1097021: title: Minkowski's theorem decl: MeasureTheory.exists_ne_zero_mem_lattice_of_measure_mul_two_pow_lt_measure author: Alex J. Best and Yaël Dillies + date: 2021 Q1103054: title: Lions–Lax–Milgram theorem @@ -1364,6 +1416,9 @@ Q1242398: Q1243340: title: Birkhoff–Von Neumann theorem + decl: doublyStochastic_eq_convexHull_permMatrix + author: Bhavik Mehta + date: 2024 Q1249069: title: Richardson's theorem @@ -1471,6 +1526,8 @@ Q1425529: Q1426292: title: Banach–Steinhaus theorem decl: banach_steinhaus + author: Jireh Loreaux + date: 2021 Q1434158: title: Fluctuation dissipation theorem @@ -1551,6 +1608,8 @@ Q1568612: Q1568811: title: Hahn decomposition theorem decl: MeasureTheory.SignedMeasure.exists_isCompl_positive_negative + author: Kexing Ying + date: 2021 Q1572474: title: Lindemann–Weierstrass theorem @@ -1582,6 +1641,9 @@ Q1632301: Q1632433: title: Helly's theorem + author: Vasily Nesterov + decl: Convex.helly_theorem + date: 2023 Q1637085: title: Poynting's theorem @@ -1597,6 +1659,9 @@ Q1683356: Q1687147: title: Sprague–Grundy theorem + decl: SetTheory.PGame.equiv_nim_grundyValue + author: Fox Thomson + date: 2020 Q1694565: title: Vinogradov's theorem @@ -1733,6 +1798,9 @@ Q2022775: Q2027347: title: Optional stopping theorem + decl: MeasureTheory.submartingale_iff_expected_stoppedValue_mono + author: Kexing Ying, Rémy Degenne + date: 2022 Q2028341: title: Ado's theorem @@ -1825,10 +1893,15 @@ Q2226774: Q2226786: title: Sperner's theorem + decl: IsAntichain.sperner + author: Bhavik Mehta, Alena Gusakov, Yaël Dillies + date: 2022 Q2226800: title: Schur–Zassenhaus theorem decl: Subgroup.exists_left_complement'_of_coprime + author: Thomas Browning + date: 2021 Q2226803: title: Tennenbaum's theorem @@ -1837,7 +1910,10 @@ Q2226807: title: Vantieghems theorem Q2226855: - title: Sarkovskii's theorem + title: Sharkovskii's theorem + # TODO: Find the code + author: Bhavik Mehta + date: 2022 Q2226868: title: Geometric mean theorem @@ -1864,6 +1940,9 @@ Q2270905: Q2275191: title: Lebesgue differentiation theorem + decl: VitaliFamily.ae_tendsto_lintegral_div + author: Sébastien Gouëzel + date: 2021 Q2277040: title: Shannon's expansion theorem @@ -1882,6 +1961,7 @@ Q2310718: Q2338929: title: Exchange theorem + # aka Steinitz exchange lemma. This must definitely be in mathlib somewhere Q2345282: title: Shannon's theorem @@ -1933,6 +2013,7 @@ Q2478371: Q2482753: title: Mann's theorem + # Done in LeanCamCombi Q2495664: title: Universal coefficient theorem @@ -1951,6 +2032,7 @@ Q2524990: Q2525646: title: Jordan–Hölder theorem + decl: CompositionSeries.jordan_holder Q2533936: title: Descartes's theorem on total angular defect @@ -2011,6 +2093,9 @@ Q2916568: Q2919401: title: Ostrowski's theorem + decl: Rat.AbsoluteValue.equiv_real_or_padic + author: David Kurniadi Angdinata, Fabrizio Barroero, Laura Capuano, Nirvana Coppola, María Inés de Frutos-Fernández, Sam van Gool, Silvain Rideau-Kikuchi, Amos Turchet, Francesco Veneziano + date: 2024 Q2981012: title: Monge's theorem @@ -2056,6 +2141,9 @@ Q3229335: Q3229352: title: Vitali covering theorem + decl: Vitali.exists_disjoint_covering_ae + author: Sébastien Gouëzel + date: 2021 Q3345678: title: Moore–Aronszajn theorem @@ -2092,6 +2180,9 @@ Q3526993: Q3526996: title: Kolmogorov extension theorem + author: Rémy Degenne, Peter Pfaffelhuber + date: 2023 + url: https://github.com/RemyDegenne/kolmogorov_extension4 Q3526998: title: Excision theorem @@ -2161,6 +2252,9 @@ Q3527100: Q3527102: title: Kruskal–Katona theorem + decl: Finset.kruskal_katona + author: Bhavik Mehta, Yaël Dillies + date: 2020 Q3527110: title: Lax–Wendroff theorem @@ -2212,6 +2306,9 @@ Q3527214: Q3527215: title: Hilbert projection theorem + decl: exists_norm_eq_iInf_of_complete_convex + author: Zhouhang Zhou + date: 2019 Q3527217: title: M. Riesz extension theorem @@ -2242,9 +2339,15 @@ Q3527247: Q3527250: title: Hadamard three-lines theorem + decl: Complex.HadamardThreeLines.norm_le_interpStrip_of_mem_verticalClosedStrip + author: Xavier Généreux + date: 2023 Q3527263: title: Kleene fixed-point theorem + decl: fixedPoints.lfp_eq_sSup_iterate + author: Ira Fesefeldt + date: 2024 Q3527279: title: Wiener's tauberian theorem @@ -2299,6 +2402,9 @@ Q3984052: Q3984053: title: Fourier inversion theorem + decl: Continuous.fourier_inversion + author: Sébastien Gouëzel + date: 2024 Q3984056: title: No-communication theorem @@ -2329,6 +2435,9 @@ Q4272645: Q4378868: title: Phragmén–Lindelöf theorem + decl: PhragmenLindelof.horizontal_strip + author: Yury G. Kudryashov + date: 2022 Q4378889: title: Carathéodory's theorem @@ -2416,6 +2525,9 @@ Q4677985: Q4695203: title: Four functions theorem + decl: four_functions_theorem + author: Yaël Dillies + date: 2023 Q4700718: title: Akhiezer's theorem @@ -2485,6 +2597,9 @@ Q4827308: Q4830725: title: Ax–Grothendieck theorem + decl: ax_grothendieck_zeroLocus + author: Chris Hughes + date: 2023 Q4832965: title: Aztec diamond theorem @@ -2698,6 +2813,9 @@ Q5166389: Q5171652: title: Corners theorem + decl: corners_theorem_nat + author: Yaël Dillies, Bhavik Mehta + date: 2022 Q5172143: title: Corona theorem @@ -3366,6 +3484,9 @@ Q7433034: Q7433182: title: Schwartz–Zippel theorem + decl: MvPolynomial.schwartz_zippel_sup_sum + author: Bolton Bailey, Yaël Dillies + date: 2023 Q7433295: title: Osterwalder–Schrader theorem @@ -3524,6 +3645,9 @@ Q7857350: Q7888360: title: Structure theorem for finitely generated modules over a principal ideal domain + decl: Module.equiv_free_prod_directSum + author: Pierre-Alexandre Bazin + date: 2022 Q7894110: title: Universal approximation theorem @@ -3587,6 +3711,9 @@ Q8066795: Q8074796: title: Zsigmondy's theorem + # TODO: Find the code + author: Mantas Bakšys + date: 2022 Q8081891: title: Śleszyński–Pringsheim theorem @@ -3605,6 +3732,9 @@ Q10942247: Q11352023: title: Vitali convergence theorem + decl: MeasureTheory.tendstoInMeasure_iff_tendsto_Lp + author: Igor Khavkine + date: 2024 Q11573495: title: Plancherel theorem for spherical functions @@ -3641,6 +3771,9 @@ Q15895894: Q16251580: title: Matiyasevich's theorem + decl: Pell.matiyasevic + author: Mario Carneiro + date: 2017 Q16680059: title: Strong perfect graph theorem @@ -3659,6 +3792,9 @@ Q17003552: Q17005116: title: Birkhoff's representation theorem + decl: LatticeHom.birkhoffSet + author: Yaël Dillies + date: 2022 Q17008559: title: Davenport–Schmidt theorem From 5716319cc527c44c374b07889bbd7c5c12965bdd Mon Sep 17 00:00:00 2001 From: Floris van Doorn Date: Mon, 6 Jan 2025 15:23:00 +0000 Subject: [PATCH 016/681] fix: linkfix in 100.yaml (#20517) --- docs/100.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/100.yaml b/docs/100.yaml index 991d6a09ae840..e7f8eb83b68c0 100644 --- a/docs/100.yaml +++ b/docs/100.yaml @@ -20,9 +20,8 @@ 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 + First incompleteness theorem: https://github.com/FormalizedFormalLogic/Incompleteness/blob/master/Incompleteness/Arith/First.lean + Second incompleteness theorem: https://github.com/FormalizedFormalLogic/Incompleteness/blob/master/Incompleteness/Arith/Second.lean website: https://formalizedformallogic.github.io/Book/ 7: title : Law of Quadratic Reciprocity From 648ca59824034ebd79298ec7250f99c7eb71f3b0 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Mon, 6 Jan 2025 15:56:35 +0000 Subject: [PATCH 017/681] feat: A disjoint union is finite iff all sets are finite, and all but finitely many are empty (#20457) From the Carleson project --- Mathlib/Data/Set/Finite/Lattice.lean | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Mathlib/Data/Set/Finite/Lattice.lean b/Mathlib/Data/Set/Finite/Lattice.lean index 85c9d8dbf4beb..0f87a472988fd 100644 --- a/Mathlib/Data/Set/Finite/Lattice.lean +++ b/Mathlib/Data/Set/Finite/Lattice.lean @@ -152,6 +152,35 @@ theorem Finite.iUnion {ι : Type*} {s : ι → Set α} {t : Set ι} (ht : t.Fini · rw [he i hi, mem_empty_iff_false] at hx contradiction +/-- An indexed union of pairwise disjoint sets is finite iff all sets are finite, and all but +finitely many are empty. -/ +lemma finite_iUnion_iff {ι : Type*} {s : ι → Set α} (hs : Pairwise fun i j ↦ Disjoint (s i) (s j)) : + (⋃ i, s i).Finite ↔ (∀ i, (s i).Finite) ∧ {i | (s i).Nonempty}.Finite where + mp h := by + refine ⟨fun i ↦ h.subset <| subset_iUnion _ _, ?_⟩ + let u (i : {i | (s i).Nonempty}) : ⋃ i, s i := ⟨i.2.choose, mem_iUnion.2 ⟨i.1, i.2.choose_spec⟩⟩ + have u_inj : Function.Injective u := by + rintro ⟨i, hi⟩ ⟨j, hj⟩ hij + ext + refine hs.eq <| not_disjoint_iff.2 ⟨u ⟨i, hi⟩, hi.choose_spec, ?_⟩ + rw [hij] + exact hj.choose_spec + have : Finite (⋃ i, s i) := h + exact .of_injective u u_inj + mpr h := h.2.iUnion (fun _ _ ↦ h.1 _) (by simp [not_nonempty_iff_eq_empty]) + +@[simp] lemma finite_iUnion_of_subsingleton {ι : Sort*} [Subsingleton ι] {s : ι → Set α} : + (⋃ i, s i).Finite ↔ ∀ i, (s i).Finite := by + rw [← iUnion_plift_down, finite_iUnion_iff _root_.Subsingleton.pairwise] + simp [PLift.forall, Finite.of_subsingleton] + +/-- An indexed union of pairwise disjoint sets is finite iff all sets are finite, and all but +finitely many are empty. -/ +lemma PairwiseDisjoint.finite_biUnion_iff {f : β → Set α} {s : Set β} (hs : s.PairwiseDisjoint f) : + (⋃ i ∈ s, f i).Finite ↔ (∀ i ∈ s, (f i).Finite) ∧ {i ∈ s | (f i).Nonempty}.Finite := by + rw [finite_iUnion_iff (by aesop (add unfold safe [Pairwise, PairwiseDisjoint, Set.Pairwise]))] + simp + section preimage variable {f : α → β} {s : Set β} From ee71c31a5c26f79ff825829748dec28897a08375 Mon Sep 17 00:00:00 2001 From: Seewoo Lee <49933279+seewoo5@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:31:30 +0000 Subject: [PATCH 018/681] feat: Polynomial FLT (#18882) Prove the polynomial FLT, using Mason-Stothers theorem #15706. More generally, prove non-solvability of Fermat-Catalan equation: $ux^p + vx^q + wz^r = 0$ where $u, v, w \in k^\times$ are units and $p, q, r \ge 3$ with $pq + qr + rp \le pqr$. Also derive the `IsCoprime b c` and `IsCoprime c a` assumptions from the `IsCoprime a b` and `a + b + c = 0` ones in `Polynomial.abc`. Co-authored-by: Jineon Baek Co-authored-by: Jineon Baek <34874130+jcpaik@users.noreply.github.com> Co-authored-by: Seewoo Lee --- Mathlib.lean | 1 + Mathlib/NumberTheory/FLT/MasonStothers.lean | 19 +- Mathlib/NumberTheory/FLT/Polynomial.lean | 275 ++++++++++++++++++++ 3 files changed, 290 insertions(+), 5 deletions(-) create mode 100644 Mathlib/NumberTheory/FLT/Polynomial.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2a2fd484ec0df..2bdbb9627ace3 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3894,6 +3894,7 @@ import Mathlib.NumberTheory.EulerProduct.ExpLog import Mathlib.NumberTheory.FLT.Basic import Mathlib.NumberTheory.FLT.Four import Mathlib.NumberTheory.FLT.MasonStothers +import Mathlib.NumberTheory.FLT.Polynomial import Mathlib.NumberTheory.FLT.Three import Mathlib.NumberTheory.FactorisationProperties import Mathlib.NumberTheory.Fermat diff --git a/Mathlib/NumberTheory/FLT/MasonStothers.lean b/Mathlib/NumberTheory/FLT/MasonStothers.lean index eee4ff81ac138..bd5d8a2c3a537 100644 --- a/Mathlib/NumberTheory/FLT/MasonStothers.lean +++ b/Mathlib/NumberTheory/FLT/MasonStothers.lean @@ -16,9 +16,6 @@ Proof is based on this online note by Franz Lemmermeyer http://www.fen.bilkent.e which is essentially based on Noah Snyder's paper "An Alternative Proof of Mason's Theorem", but slightly different. -## TODO - -Prove polynomial FLT using Mason-Stothers theorem. -/ open Polynomial UniqueFactorizationMonoid UniqueFactorizationDomain EuclideanDomain @@ -51,13 +48,25 @@ private theorem abc_subcall {a b c w : k[X]} {hw : w ≠ 0} (wab : w = wronskian exact Nat.add_lt_add_right abc_dr_ndeg_lt _ /-- **Polynomial ABC theorem.** -/ -theorem Polynomial.abc {a b c : k[X]} (ha : a ≠ 0) (hb : b ≠ 0) (hc : c ≠ 0) (hab : IsCoprime a b) - (hbc : IsCoprime b c) (hca : IsCoprime c a) (hsum : a + b + c = 0) : +protected theorem Polynomial.abc + {a b c : k[X]} (ha : a ≠ 0) (hb : b ≠ 0) (hc : c ≠ 0) + (hab : IsCoprime a b) (hsum : a + b + c = 0) : ( natDegree a + 1 ≤ (radical (a * b * c)).natDegree ∧ natDegree b + 1 ≤ (radical (a * b * c)).natDegree ∧ natDegree c + 1 ≤ (radical (a * b * c)).natDegree ) ∨ derivative a = 0 ∧ derivative b = 0 ∧ derivative c = 0 := by set w := wronskian a b with wab + have hbc : IsCoprime b c := by + rw [add_eq_zero_iff_neg_eq] at hsum + rw [← hsum, IsCoprime.neg_right_iff] + convert IsCoprime.add_mul_left_right hab.symm 1 + rw [mul_one] + have hsum' : b + c + a = 0 := by rwa [add_rotate] at hsum + have hca : IsCoprime c a := by + rw [add_eq_zero_iff_neg_eq] at hsum' + rw [← hsum', IsCoprime.neg_right_iff] + convert IsCoprime.add_mul_left_right hbc.symm 1 + rw [mul_one] have wbc : w = wronskian b c := wronskian_eq_of_sum_zero hsum have wca : w = wronskian c a := by rw [add_rotate] at hsum diff --git a/Mathlib/NumberTheory/FLT/Polynomial.lean b/Mathlib/NumberTheory/FLT/Polynomial.lean new file mode 100644 index 0000000000000..e6beb32165d5a --- /dev/null +++ b/Mathlib/NumberTheory/FLT/Polynomial.lean @@ -0,0 +1,275 @@ +/- +Copyright (c) 2024 Jineon Baek and Seewoo Lee. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jineon Baek, Seewoo Lee +-/ +import Mathlib.Algebra.Polynomial.Expand +import Mathlib.Algebra.GroupWithZero.Defs +import Mathlib.NumberTheory.FLT.Basic +import Mathlib.NumberTheory.FLT.MasonStothers +import Mathlib.RingTheory.Polynomial.Content + +/-! +# Fermat's Last Theorem for polynomials over a field + +This file states and proves the Fermat's Last Theorem for polynomials over a field. +For `n ≥ 3` not divisible by the characteristic of the coefficient field `k` and (pairwise) nonzero +coprime polynomials `a, b, c` (over a field) with `a ^ n + b ^ n = c ^ n`, +all polynomials must be constants. + +More generally, we can prove non-solvability of the Fermat-Catalan equation: there are no +non-constant polynomial solutions to the equation `u * a ^ p + v * b ^ q + w * c ^ r = 0`, where +`p, q, r ≥ 3` with `p * q + q * r + r * p ≤ p * q * r` , `p, q, r` not divisible by `char k`, +and `u, v, w` are nonzero elements in `k`. +FLT is the special case where `p = q = r = n`, `u = v = 1`, and `w = -1`. + +The proof uses the Mason-Stothers theorem (Polynomial ABC theorem) and infinite descent +(in the characteristic p case). +-/ + +open Polynomial UniqueFactorizationMonoid UniqueFactorizationDomain + +variable {k R : Type*} [Field k] [CommRing R] [IsDomain R] [NormalizationMonoid R] + [UniqueFactorizationMonoid R] + +private lemma Ne.isUnit_C {u : k} (hu : u ≠ 0) : IsUnit (C u) := + Polynomial.isUnit_C.mpr hu.isUnit + +-- auxiliary lemma that 'rotates' coprimality +private lemma rot_coprime + {p q r : ℕ} {a b c : k[X]} {u v w : k} + {hp : 0 < p} {hq : 0 < q} {hr : 0 < r} + {hu : u ≠ 0} {hv : v ≠ 0} {hw : w ≠ 0} + (heq : C u * a ^ p + C v * b ^ q + C w * c ^ r = 0) (hab : IsCoprime a b) : IsCoprime b c := by + have hCu : IsUnit (C u) := Ne.isUnit_C hu + have hCv : IsUnit (C v) := Ne.isUnit_C hv + have hCw : IsUnit (C w) := Ne.isUnit_C hw + rw [← IsCoprime.pow_iff hp hq, ← isCoprime_mul_units_left hCu hCv] at hab + rw [add_eq_zero_iff_neg_eq] at heq + rw [← IsCoprime.pow_iff hq hr, ← isCoprime_mul_units_left hCv hCw, + ← heq, IsCoprime.neg_right_iff] + convert IsCoprime.add_mul_left_right hab.symm 1 using 2 + rw [mul_one] + +private lemma ineq_pqr_contradiction {p q r a b c : ℕ} + (hp : 0 < p) (hq : 0 < q) (hr : 0 < r) + (hineq : q * r + r * p + p * q ≤ p * q * r) + (hpa : p * a < a + b + c) + (hqb : q * b < a + b + c) + (hrc : r * c < a + b + c) : False := by + suffices h : p * q * r * (a + b + c) + 1 ≤ p * q * r * (a + b + c) by simp at h + calc + _ = (p * a) * (q * r) + (q * b) * (r * p) + (r * c) * (p * q) + 1 := by ring + _ ≤ (a + b + c) * (q * r) + (a + b + c) * (r * p) + (a + b + c) * (p * q) := by + rw [Nat.succ_le] + gcongr + _ = (q * r + r * p + p * q) * (a + b + c) := by ring + _ ≤ _ := by gcongr + +private theorem Polynomial.flt_catalan_deriv [DecidableEq k] + {p q r : ℕ} (hp : 0 < p) (hq : 0 < q) (hr : 0 < r) + (hineq : q * r + r * p + p * q ≤ p * q * r) + (chp : (p : k) ≠ 0) (chq : (q : k) ≠ 0) (chr : (r : k) ≠ 0) + {a b c : k[X]} (ha : a ≠ 0) (hb : b ≠ 0) (hc : c ≠ 0) + (hab : IsCoprime a b) {u v w : k} (hu : u ≠ 0) (hv : v ≠ 0) (hw : w ≠ 0) + (heq : C u * a ^ p + C v * b ^ q + C w * c ^ r = 0) : + derivative a = 0 ∧ derivative b = 0 ∧ derivative c = 0 := by + have hbc : IsCoprime b c := by apply rot_coprime heq <;> assumption + have hca : IsCoprime c a := by + rw [add_rotate] at heq; apply rot_coprime heq <;> assumption + have hCu := C_ne_zero.mpr hu + have hCv := C_ne_zero.mpr hv + have hCw := C_ne_zero.mpr hw + have hap := pow_ne_zero p ha + have hbq := pow_ne_zero q hb + have hcr := pow_ne_zero r hc + have habp : IsCoprime (C u * a ^ p) (C v * b ^ q) := by + rw [isCoprime_mul_units_left hu.isUnit_C hv.isUnit_C]; exact hab.pow + have hbcp : IsCoprime (C v * b ^ q) (C w * c ^ r) := by + rw [isCoprime_mul_units_left hv.isUnit_C hw.isUnit_C]; exact hbc.pow + have hcap : IsCoprime (C w * c ^ r) (C u * a ^ p) := by + rw [isCoprime_mul_units_left hw.isUnit_C hu.isUnit_C]; exact hca.pow + have habcp := hcap.symm.mul_left hbcp + + -- Use Mason-Stothers theorem + rcases Polynomial.abc + (mul_ne_zero hCu hap) (mul_ne_zero hCv hbq) (mul_ne_zero hCw hcr) + habp heq with nd_lt | dr0 + · simp_rw [radical_mul habcp, radical_mul habp, + radical_mul_of_isUnit_left hu.isUnit_C, + radical_mul_of_isUnit_left hv.isUnit_C, + radical_mul_of_isUnit_left hw.isUnit_C, + radical_pow a hp, radical_pow b hq, radical_pow c hr, + natDegree_mul hCu hap, + natDegree_mul hCv hbq, + natDegree_mul hCw hcr, + natDegree_C, natDegree_pow, zero_add, + ← radical_mul hab, + ← radical_mul (hca.symm.mul_left hbc)] at nd_lt + + obtain ⟨hpa', hqb', hrc'⟩ := nd_lt + have hpa := hpa'.trans natDegree_radical_le + have hqb := hqb'.trans natDegree_radical_le + have hrc := hrc'.trans natDegree_radical_le + rw [natDegree_mul (mul_ne_zero ha hb) hc, + natDegree_mul ha hb, Nat.add_one_le_iff] at hpa hqb hrc + exfalso + exact (ineq_pqr_contradiction hp hq hr hineq hpa hqb hrc) + · rw [derivative_C_mul, derivative_C_mul, derivative_C_mul, + mul_eq_zero_iff_left (C_ne_zero.mpr hu), + mul_eq_zero_iff_left (C_ne_zero.mpr hv), + mul_eq_zero_iff_left (C_ne_zero.mpr hw), + derivative_pow_eq_zero chp, + derivative_pow_eq_zero chq, + derivative_pow_eq_zero chr] at dr0 + exact dr0 + +-- helper lemma that gives a baggage of small facts on `contract (ringChar k) a` +private lemma find_contract {a : k[X]} + (ha : a ≠ 0) (hda : derivative a = 0) (chn0 : ringChar k ≠ 0) : + ∃ ca, ca ≠ 0 ∧ + a = expand k (ringChar k) ca ∧ + a.natDegree = ca.natDegree * ringChar k := by + have heq := (expand_contract (ringChar k) hda chn0).symm + refine ⟨contract (ringChar k) a, ?_, heq, ?_⟩ + · intro h + rw [h, map_zero] at heq + exact ha heq + · rw [← natDegree_expand, ← heq] + +variable [DecidableEq k] + +private theorem Polynomial.flt_catalan_aux + {p q r : ℕ} {a b c : k[X]} {u v w : k} + (heq : C u * a ^ p + C v * b ^ q + C w * c ^ r = 0) + (hp : 0 < p) (hq : 0 < q) (hr : 0 < r) + (hineq : q * r + r * p + p * q ≤ p * q * r) + (chp : (p : k) ≠ 0) (chq : (q : k) ≠ 0) (chr : (r : k) ≠ 0) + (ha : a ≠ 0) (hb : b ≠ 0) (hc : c ≠ 0) (hab : IsCoprime a b) + (hu : u ≠ 0) (hv : v ≠ 0) (hw : w ≠ 0) : + a.natDegree = 0 := by + cases' eq_or_ne (ringChar k) 0 with ch0 chn0 + -- characteristic zero + · obtain ⟨da, -, -⟩ := flt_catalan_deriv + hp hq hr hineq chp chq chr ha hb hc hab hu hv hw heq + have czk : CharZero k := by + apply charZero_of_inj_zero + intro n + rw [ringChar.spec, ch0] + exact zero_dvd_iff.mp + rw [eq_C_of_derivative_eq_zero da] + exact natDegree_C _ + -- characteristic p > 0 + · generalize eq_d : a.natDegree = d + -- set up infinite descent + -- strong induct on `d := a.natDegree` + induction d + using Nat.case_strong_induction_on + generalizing a b c ha hb hc hab heq with + | hz => rfl + | hi d ih_d => -- have derivatives of `a, b, c` zero + obtain ⟨ad, bd, cd⟩ := flt_catalan_deriv + hp hq hr hineq chp chq chr ha hb hc hab hu hv hw heq + -- find contracts `ca, cb, cc` so that `a(k) = ca(k^ch)` + obtain ⟨ca, ca_nz, eq_a, eq_deg_a⟩ := find_contract ha ad chn0 + obtain ⟨cb, cb_nz, eq_b, eq_deg_b⟩ := find_contract hb bd chn0 + obtain ⟨cc, cc_nz, eq_c, eq_deg_c⟩ := find_contract hc cd chn0 + set ch := ringChar k + suffices hca : ca.natDegree = 0 by + rw [← eq_d, eq_deg_a, hca, zero_mul] + by_contra hnca; apply hnca + apply ih_d _ _ _ ca_nz cb_nz cc_nz <;> clear ih_d <;> try rfl + · apply (isCoprime_expand chn0).mp + rwa [← eq_a, ← eq_b] + · have _ : ch ≠ 1 := CharP.ringChar_ne_one + have hch2 : 2 ≤ ch := by omega + rw [← add_le_add_iff_right 1, ← eq_d, eq_deg_a] + refine le_trans ?_ (Nat.mul_le_mul_left _ hch2) + omega + · rw [eq_a, eq_b, eq_c, ← expand_C ch u, ← expand_C ch v, ← expand_C ch w] at heq + simp_rw [← map_pow, ← map_mul, ← map_add] at heq + rwa [Polynomial.expand_eq_zero (zero_lt_iff.mpr chn0)] at heq + +/-- Nonsolvability of the Fermat-Catalan equation. -/ +theorem Polynomial.flt_catalan + {p q r : ℕ} (hp : 0 < p) (hq : 0 < q) (hr : 0 < r) + (hineq : q * r + r * p + p * q ≤ p * q * r) + (chp : (p : k) ≠ 0) (chq : (q : k) ≠ 0) (chr : (r : k) ≠ 0) + {a b c : k[X]} (ha : a ≠ 0) (hb : b ≠ 0) (hc : c ≠ 0) (hab : IsCoprime a b) + {u v w : k} (hu : u ≠ 0) (hv : v ≠ 0) (hw : w ≠ 0) + (heq : C u * a ^ p + C v * b ^ q + C w * c ^ r = 0) : + a.natDegree = 0 ∧ b.natDegree = 0 ∧ c.natDegree = 0 := by + -- WLOG argument: essentially three times flt_catalan_aux + have hbc : IsCoprime b c := by + apply rot_coprime heq hab <;> assumption + have heq' : C v * b ^ q + C w * c ^ r + C u * a ^ p = 0 := by + rwa [add_rotate] at heq + have hca : IsCoprime c a := by + apply rot_coprime heq' hbc <;> assumption + refine ⟨?_, ?_, ?_⟩ + · apply flt_catalan_aux heq <;> assumption + · rw [add_rotate] at heq hineq + rw [mul_rotate] at hineq + apply flt_catalan_aux heq <;> assumption + · rw [← add_rotate] at heq hineq + rw [← mul_rotate] at hineq + apply flt_catalan_aux heq <;> assumption + +theorem Polynomial.flt + {n : ℕ} (hn : 3 ≤ n) (chn : (n : k) ≠ 0) + {a b c : k[X]} (ha : a ≠ 0) (hb : b ≠ 0) (hc : c ≠ 0) + (hab : IsCoprime a b) (heq : a ^ n + b ^ n = c ^ n) : + a.natDegree = 0 ∧ b.natDegree = 0 ∧ c.natDegree = 0 := by + have hn' : 0 < n := by linarith + rw [← sub_eq_zero, ← one_mul (a ^ n), ← one_mul (b ^ n), ← one_mul (c ^ n), sub_eq_add_neg, + ← neg_mul] at heq + have hone : (1 : k[X]) = C 1 := by rfl + have hneg_one : (-1 : k[X]) = C (-1) := by simp only [map_neg, map_one] + simp_rw [hneg_one, hone] at heq + apply flt_catalan hn' hn' hn' _ + chn chn chn ha hb hc hab one_ne_zero one_ne_zero (neg_ne_zero.mpr one_ne_zero) heq + have eq_lhs : n * n + n * n + n * n = 3 * n * n := by ring + rw [eq_lhs, mul_assoc, mul_assoc] + exact Nat.mul_le_mul_right (n * n) hn + +theorem fermatLastTheoremWith'_polynomial {n : ℕ} (hn : 3 ≤ n) (chn : (n : k) ≠ 0) : + FermatLastTheoremWith' k[X] n := by + rw [FermatLastTheoremWith'] + intros a b c ha hb hc heq + obtain ⟨a', eq_a⟩ := gcd_dvd_left a b + obtain ⟨b', eq_b⟩ := gcd_dvd_right a b + set d := gcd a b + have hd : d ≠ 0 := gcd_ne_zero_of_left ha + rw [eq_a, eq_b, mul_pow, mul_pow, ← mul_add] at heq + have hdc : d ∣ c := by + have hn : 0 < n := by omega + have hdncn : d ^ n ∣ c ^ n := ⟨_, heq.symm⟩ + + rw [dvd_iff_normalizedFactors_le_normalizedFactors hd hc] + rw [dvd_iff_normalizedFactors_le_normalizedFactors + (pow_ne_zero n hd) (pow_ne_zero n hc), + normalizedFactors_pow, normalizedFactors_pow] at hdncn + simp_rw [Multiset.le_iff_count, Multiset.count_nsmul, + mul_le_mul_left hn] at hdncn ⊢ + exact hdncn + obtain ⟨c', eq_c⟩ := hdc + rw [eq_a, mul_ne_zero_iff] at ha + rw [eq_b, mul_ne_zero_iff] at hb + rw [eq_c, mul_ne_zero_iff] at hc + rw [mul_comm] at eq_a eq_b eq_c + refine ⟨d, a', b', c', ⟨eq_a, eq_b, eq_c⟩, ?_⟩ + rw [eq_c, mul_pow, mul_comm, mul_left_inj' (pow_ne_zero n hd)] at heq + suffices goal : a'.natDegree = 0 ∧ b'.natDegree = 0 ∧ c'.natDegree = 0 by + simp [natDegree_eq_zero] at goal + obtain ⟨⟨ca', ha'⟩, ⟨cb', hb'⟩, ⟨cc', hc'⟩⟩ := goal + rw [← ha', ← hb', ← hc'] + rw [← ha', C_ne_zero] at ha + rw [← hb', C_ne_zero] at hb + rw [← hc', C_ne_zero] at hc + exact ⟨ha.right.isUnit_C, hb.right.isUnit_C, hc.right.isUnit_C⟩ + apply flt hn chn ha.right hb.right hc.right _ heq + convert isCoprime_div_gcd_div_gcd _ + · exact EuclideanDomain.eq_div_of_mul_eq_left ha.left eq_a.symm + · exact EuclideanDomain.eq_div_of_mul_eq_left ha.left eq_b.symm + · rw [eq_b] + exact mul_ne_zero hb.right hb.left From 69241484e921357756c37b487c438dc7ba2250e1 Mon Sep 17 00:00:00 2001 From: Artie Khovanov Date: Mon, 6 Jan 2025 17:01:52 +0000 Subject: [PATCH 019/681] chore(Algebra): make more names consistent (#20449) * Follows on from #20272 * Rename some substructure constructions to align with `oneLE` / `nonneg` * Clarify some documentation Moves: * squareIn -> square * evenIn -> even * sumSqIn -> sumSq --- Mathlib/Algebra/Group/Subgroup/Even.lean | 48 ++++++++++++------------ Mathlib/Algebra/Ring/SumsOfSquares.lean | 22 ++++++----- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/Mathlib/Algebra/Group/Subgroup/Even.lean b/Mathlib/Algebra/Group/Subgroup/Even.lean index b4735654ebe05..488a9b76c3b59 100644 --- a/Mathlib/Algebra/Group/Subgroup/Even.lean +++ b/Mathlib/Algebra/Group/Subgroup/Even.lean @@ -13,73 +13,73 @@ This file defines the subgroup of squares / even elements in an abelian group. -/ namespace Subsemigroup -variable {S : Type*} [CommSemigroup S] {a : S} +variable {S : Type*} [CommSemigroup S] variable (S) in /-- -In a commutative semigroup `S`, `Subsemigroup.squareIn S` is the subsemigroup of squares in `S`. +In a commutative semigroup `S`, `Subsemigroup.square S` is the subsemigroup of squares in `S`. -/ @[to_additive -"In a commutative additive semigroup `S`, the type `AddSubsemigroup.evenIn S` -is the subsemigroup of even elements of `S`."] -def squareIn : Subsemigroup S where +"In a commutative additive semigroup `S`, `AddSubsemigroup.even S` +is the subsemigroup of even elements in `S`."] +def square : Subsemigroup S where carrier := {s : S | IsSquare s} mul_mem' := IsSquare.mul @[to_additive (attr := simp)] -theorem mem_squareIn : a ∈ squareIn S ↔ IsSquare a := Iff.rfl +theorem mem_square {a : S} : a ∈ square S ↔ IsSquare a := Iff.rfl @[to_additive (attr := simp, norm_cast)] -theorem coe_squareIn : squareIn S = {s : S | IsSquare s} := rfl +theorem coe_square : square S = {s : S | IsSquare s} := rfl end Subsemigroup namespace Submonoid -variable {M : Type*} [CommMonoid M] {a : M} +variable {M : Type*} [CommMonoid M] variable (M) in /-- -In a commutative monoid `M`, `Submonoid.squareIn M` is the submonoid of squares in `M`. +In a commutative monoid `M`, `Submonoid.square M` is the submonoid of squares in `M`. -/ @[to_additive -"In a commutative additive monoid `M`, the type `AddSubmonoid.evenIn M` -is the submonoid of even elements of `M`."] -def squareIn : Submonoid M where - __ := Subsemigroup.squareIn M +"In a commutative additive monoid `M`, `AddSubmonoid.even M` +is the submonoid of even elements in `M`."] +def square : Submonoid M where + __ := Subsemigroup.square M one_mem' := IsSquare.one @[to_additive (attr := simp)] -theorem squareIn_toSubsemigroup : (squareIn M).toSubsemigroup = .squareIn M := rfl +theorem square_toSubsemigroup : (square M).toSubsemigroup = .square M := rfl @[to_additive (attr := simp)] -theorem mem_squareIn : a ∈ squareIn M ↔ IsSquare a := Iff.rfl +theorem mem_square {a : M} : a ∈ square M ↔ IsSquare a := Iff.rfl @[to_additive (attr := simp, norm_cast)] -theorem coe_squareIn : squareIn M = {s : M | IsSquare s} := rfl +theorem coe_square : square M = {s : M | IsSquare s} := rfl end Submonoid namespace Subgroup -variable {G : Type*} [CommGroup G] {a : G} +variable {G : Type*} [CommGroup G] variable (G) in /-- -In an abelian group `G`, `Subgroup.squareIn G` is the subgroup of squares in `G`. +In an abelian group `G`, `Subgroup.square G` is the subgroup of squares in `G`. -/ @[to_additive -"In an abelian additive group `G`, the type `AddSubgroup.evenIn G` is +"In an abelian additive group `G`, `AddSubgroup.even G` is the subgroup of even elements in `G`."] -def squareIn : Subgroup G where - __ := Submonoid.squareIn G +def square : Subgroup G where + __ := Submonoid.square G inv_mem' := IsSquare.inv @[to_additive (attr := simp)] -theorem squareIn_toSubmonoid : (squareIn G).toSubmonoid = .squareIn G := rfl +theorem square_toSubmonoid : (square G).toSubmonoid = .square G := rfl @[to_additive (attr := simp)] -theorem mem_squareIn : a ∈ squareIn G ↔ IsSquare a := Iff.rfl +theorem mem_square {a : G} : a ∈ square G ↔ IsSquare a := Iff.rfl @[to_additive (attr := simp, norm_cast)] -theorem coe_squareIn : squareIn G = {s : G | IsSquare s} := rfl +theorem coe_square : square G = {s : G | IsSquare s} := rfl end Subgroup diff --git a/Mathlib/Algebra/Ring/SumsOfSquares.lean b/Mathlib/Algebra/Ring/SumsOfSquares.lean index 83f2856af82f4..64898b4df47db 100644 --- a/Mathlib/Algebra/Ring/SumsOfSquares.lean +++ b/Mathlib/Algebra/Ring/SumsOfSquares.lean @@ -21,15 +21,15 @@ sum of squares in `R`. ## Auxiliary declarations -- The type `sumSqIn R` : in an additive monoid with multiplication `R`, we introduce the type -`sumSqIn R` as the submonoid of `R` whose carrier is the subset `{S : R | IsSumSq S}`. +- The term `sumSq R` : in an additive monoid with multiplication `R`, we introduce +`sumSq R` as the submonoid of `R` whose carrier is the subset `{S : R | IsSumSq S}`. ## Theorems - `IsSumSq.add`: if `S1` and `S2` are sums of squares in `R`, then so is `S1 + S2`. - `IsSumSq.nonneg`: in a linearly ordered semiring `R` with an `[ExistsAddOfLE R]` instance, sums of squares are non-negative. -- `mem_sumSqIn_of_isSquare`: a square is a sum of squares. +- `mem_sumSq_of_isSquare`: a square is a sum of squares. - `AddSubmonoid.closure_isSquare`: the submonoid of `R` generated by the squares in `R` is the set of sums of squares in `R`. @@ -73,34 +73,36 @@ theorem IsSumSq.sum_mul_self {ι : Type*} [AddCommMonoid R] (s : Finset ι) (f : variable (R) in /-- -In an additive monoid with multiplication `R`, the type `sumSqIn R` is the submonoid of sums of +In an additive monoid with multiplication `R`, `AddSubmonoid.sumSq R` is the submonoid of sums of squares in `R`. -/ -def sumSqIn [AddMonoid R] : AddSubmonoid R where +def sumSq [AddMonoid R] : AddSubmonoid R where carrier := {S : R | IsSumSq S} zero_mem' := IsSumSq.zero add_mem' := IsSumSq.add -@[deprecated (since := "2024-08-09")] alias SumSqIn := sumSqIn +@[deprecated (since := "2024-08-09")] alias SumSqIn := sumSq +@[deprecated (since := "2025-01-03")] alias sumSqIn := sumSq /-- In an additive monoid with multiplication, every square is a sum of squares. By definition, a square in `R` is a term `x : R` such that `x = y * y` for some `y : R` and in Mathlib this is known as `IsSquare R` (see Mathlib.Algebra.Group.Even). -/ -theorem mem_sumSqIn_of_isSquare [AddMonoid R] {x : R} (px : IsSquare x) : x ∈ sumSqIn R := by +theorem mem_sumSq_of_isSquare [AddMonoid R] {x : R} (px : IsSquare x) : x ∈ sumSq R := by rcases px with ⟨y, py⟩ rw [py, ← AddMonoid.add_zero (y * y)] exact IsSumSq.sq_add _ _ IsSumSq.zero -@[deprecated (since := "2024-08-09")] alias SquaresInSumSq := mem_sumSqIn_of_isSquare +@[deprecated (since := "2024-08-09")] alias SquaresInSumSq := mem_sumSq_of_isSquare +@[deprecated (since := "2025-01-03")] alias mem_sumSqIn_of_isSquare := mem_sumSq_of_isSquare /-- In an additive monoid with multiplication `R`, the submonoid generated by the squares is the set of sums of squares. -/ -theorem AddSubmonoid.closure_isSquare [AddMonoid R] : closure {x : R | IsSquare x} = sumSqIn R := by - refine le_antisymm (closure_le.2 (fun x hx ↦ mem_sumSqIn_of_isSquare hx)) (fun x hx ↦ ?_) +theorem AddSubmonoid.closure_isSquare [AddMonoid R] : closure {x : R | IsSquare x} = sumSq R := by + refine le_antisymm (closure_le.2 (fun x hx ↦ mem_sumSq_of_isSquare hx)) (fun x hx ↦ ?_) induction hx with | zero => exact zero_mem _ | sq_add a S _ ih => exact AddSubmonoid.add_mem _ (subset_closure ⟨a, rfl⟩) ih From 89f60e1045dca9bba5a7d8706ec160706782d7ef Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Mon, 6 Jan 2025 19:13:06 +0000 Subject: [PATCH 020/681] feat(RingTheory/Ideal): 37 cast to an ideal is just the whole ring. (#20244) https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/IdemSemiring.20.2B.20OfNat --- Mathlib/Algebra/Order/Kleene.lean | 8 ++++++++ Mathlib/RingTheory/Ideal/Operations.lean | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/Mathlib/Algebra/Order/Kleene.lean b/Mathlib/Algebra/Order/Kleene.lean index 208f87b231cde..96c7b6b8be108 100644 --- a/Mathlib/Algebra/Order/Kleene.lean +++ b/Mathlib/Algebra/Order/Kleene.lean @@ -133,6 +133,14 @@ scoped[Computability] attribute [simp] add_eq_sup theorem add_idem (a : α) : a + a = a := by simp +lemma natCast_eq_one {n : ℕ} (nezero : n ≠ 0) : (n : α) = 1 := by + induction n, Nat.one_le_iff_ne_zero.mpr nezero using Nat.le_induction with + | base => exact Nat.cast_one + | succ x _ hx => rw [Nat.cast_add, hx, Nat.cast_one, add_idem 1] + +lemma ofNat_eq_one {n : ℕ} [n.AtLeastTwo] : (ofNat(n) : α) = 1 := + natCast_eq_one <| Nat.not_eq_zero_of_lt Nat.AtLeastTwo.prop + theorem nsmul_eq_self : ∀ {n : ℕ} (_ : n ≠ 0) (a : α), n • a = a | 0, h => (h rfl).elim | 1, _ => one_nsmul diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index a04061874ab5e..911b9158f26d5 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -851,6 +851,14 @@ variable (R) in theorem top_pow (n : ℕ) : (⊤ ^ n : Ideal R) = ⊤ := Nat.recOn n one_eq_top fun n ih => by rw [pow_succ, ih, top_mul] +theorem natCast_eq_top {n : ℕ} (hn : n ≠ 0) : (n : Ideal R) = ⊤ := + natCast_eq_one hn |>.trans one_eq_top + +/-- `3 : Ideal R` is *not* the ideal generated by 3 (which would be spelt + `Ideal.span {3}`), it is simply `1 + 1 + 1 = ⊤`. -/ +theorem ofNat_eq_top {n : ℕ} [n.AtLeastTwo] : (ofNat(n) : Ideal R) = ⊤ := + ofNat_eq_one.trans one_eq_top + variable (I) lemma radical_pow : ∀ {n}, n ≠ 0 → radical (I ^ n) = radical I From aa37b8130b84fe5850f4e0917307d50e6b40c5b4 Mon Sep 17 00:00:00 2001 From: damiano Date: Mon, 6 Jan 2025 20:17:04 +0000 Subject: [PATCH 021/681] fix: silence the `#`-command linter on noisy commands (#20525) Reported on [Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/.23.20linter), the fix comes from [this update](https://leanprover.zulipchat.com/#narrow/channel/428973-nightly-testing/topic/Mathlib.20status.20updates/near/486115503). --- Mathlib/Tactic/Linter/HashCommandLinter.lean | 2 +- MathlibTest/HashCommandLinter.lean | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Mathlib/Tactic/Linter/HashCommandLinter.lean b/Mathlib/Tactic/Linter/HashCommandLinter.lean index 1f01c9b69a412..e4bcb714f146f 100644 --- a/Mathlib/Tactic/Linter/HashCommandLinter.lean +++ b/Mathlib/Tactic/Linter/HashCommandLinter.lean @@ -67,7 +67,7 @@ logs a warning only for the `#`-commands that do not already emit a message. -/ def hashCommandLinter : Linter where run := withSetOptionIn' fun stx => do let mod := (← getMainModule).components if Linter.getLinterValue linter.hashCommand (← getOptions) && - ((← get).messages.toList.isEmpty || warningAsError.get (← getOptions)) && + ((← get).messages.reportedPlusUnreported.isEmpty || warningAsError.get (← getOptions)) && -- we check that the module is either not in `test` or, is `test.HashCommandLinter` (mod.getD 0 default != `test || (mod == [`test, `HashCommandLinter])) then diff --git a/MathlibTest/HashCommandLinter.lean b/MathlibTest/HashCommandLinter.lean index cf5304e11e734..4193342406c14 100644 --- a/MathlibTest/HashCommandLinter.lean +++ b/MathlibTest/HashCommandLinter.lean @@ -2,12 +2,6 @@ import Lean.Elab.GuardMsgs import Mathlib.Tactic.AdaptationNote import Mathlib.Tactic.Linter.HashCommandLinter - --- #adaptation_note --- The hashCommand linter started failing after https://github.com/leanprover/lean4/pull/6299 --- Disabling aync elaboration fixes it, but of course we're not going to do that globally. -set_option Elab.async false - set_option linter.hashCommand true section ignored_commands From dfd963ffd03a17d8984119dc7e9b20d90b8f58ef Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Mon, 6 Jan 2025 22:05:00 +0000 Subject: [PATCH 022/681] chore: cleanup many `erw` (#20484) I used @dwrensha's `tryAtEachStep` tool to identify many places where `simp` can finish a proof earlier, and curated a few. I especially focused on places where we can remove an `erw`. --- .../Category/Grp/FilteredColimits.lean | 8 +++---- Mathlib/Algebra/Group/Subgroup/Basic.lean | 4 +--- .../HomotopyCategory/Pretriangulated.lean | 3 +-- Mathlib/Algebra/Homology/Opposite.lean | 8 ++----- Mathlib/Algebra/Homology/QuasiIso.lean | 4 +--- .../Algebra/Homology/TotalComplexShift.lean | 14 ++----------- Mathlib/Algebra/Lie/Nilpotent.lean | 2 +- .../Algebra/Module/LocalizedModule/Basic.lean | 4 ++-- .../EllipticCurve/Affine.lean | 16 ++++---------- .../AlgebraicGeometry/Morphisms/Affine.lean | 3 +-- Mathlib/AlgebraicTopology/CechNerve.lean | 14 +++---------- .../AlgebraicTopology/DoldKan/Homotopies.lean | 4 +--- .../AlgebraicTopology/DoldKan/Normalized.lean | 21 ++----------------- .../DoldKan/SplitSimplicialObject.lean | 2 +- Mathlib/Analysis/Analytic/ChangeOrigin.lean | 4 +--- Mathlib/CategoryTheory/Adjunction/Mates.lean | 3 +-- .../Comma/StructuredArrow/Basic.lean | 20 +++++------------- Mathlib/CategoryTheory/ComposableArrows.lean | 15 +++---------- Mathlib/CategoryTheory/Equivalence.lean | 2 +- Mathlib/CategoryTheory/Grothendieck.lean | 10 ++++----- .../Idempotents/FunctorCategories.lean | 5 +---- Mathlib/CategoryTheory/Limits/HasLimits.lean | 4 ++-- Mathlib/CategoryTheory/Limits/IsLimit.lean | 8 ++----- .../Limits/Shapes/Biproducts.lean | 2 +- Mathlib/CategoryTheory/Limits/VanKampen.lean | 7 ++----- .../Monoidal/Braided/Basic.lean | 9 +++----- Mathlib/CategoryTheory/Sites/Sheaf.lean | 1 - .../CategoryTheory/Triangulated/Rotate.lean | 10 +++------ Mathlib/Computability/RegularExpressions.lean | 2 +- Mathlib/Data/Int/Cast/Basic.lean | 2 +- Mathlib/Data/Int/Defs.lean | 2 +- Mathlib/Data/List/Basic.lean | 2 +- Mathlib/Data/Sum/Interval.lean | 8 +++---- Mathlib/Data/ZMod/Basic.lean | 2 +- .../Geometry/RingedSpace/OpenImmersion.lean | 4 ++-- .../RingedSpace/PresheafedSpace/Gluing.lean | 8 +++---- .../PresheafedSpace/HasColimits.lean | 3 +-- .../CliffordAlgebra/EvenEquiv.lean | 6 +----- .../Matrix/Determinant/Basic.lean | 5 +---- Mathlib/LinearAlgebra/Multilinear/Basic.lean | 6 ++---- Mathlib/LinearAlgebra/Span/Basic.lean | 4 +--- .../TensorProduct/Graded/Internal.lean | 2 +- .../MeasurableSpace/Embedding.lean | 6 ++---- Mathlib/ModelTheory/Algebra/Ring/Basic.lean | 8 +++---- Mathlib/NumberTheory/Zsqrtd/Basic.lean | 4 +--- Mathlib/RingTheory/Derivation/Basic.lean | 2 +- Mathlib/RingTheory/HahnSeries/Addition.lean | 3 +-- Mathlib/RingTheory/Ideal/Basis.lean | 3 +-- .../RingTheory/Kaehler/CotangentComplex.lean | 5 +---- .../RingTheory/Localization/Away/Basic.lean | 1 - .../ContinuousMap/StoneWeierstrass.lean | 7 ++----- 51 files changed, 89 insertions(+), 213 deletions(-) diff --git a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean index a31573223addd..b68cb33f290ff 100644 --- a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean @@ -95,11 +95,9 @@ noncomputable instance colimitGroup : Group (G.{v, u} F) := inv_mul_cancel := fun x => by refine Quot.inductionOn x ?_; clear x; intro x obtain ⟨j, x⟩ := x - erw [colimit_inv_mk_eq, - colimit_mul_mk_eq (F ⋙ forget₂ Grp MonCat.{max v u}) ⟨j, _⟩ ⟨j, _⟩ j (𝟙 j) (𝟙 j), - colimit_one_eq (F ⋙ forget₂ Grp MonCat.{max v u}) j] - dsimp - erw [CategoryTheory.Functor.map_id, inv_mul_cancel] } + erw [colimit_inv_mk_eq] + erw [colimit_mul_mk_eq (F ⋙ forget₂ Grp MonCat.{max v u}) ⟨j, _⟩ ⟨j, _⟩ j (𝟙 j) (𝟙 j)] + simp [colimit_one_eq (F ⋙ forget₂ Grp MonCat.{max v u}) j] } /-- The bundled group giving the filtered colimit of a diagram. -/ @[to_additive "The bundled additive group giving the filtered colimit of a diagram."] diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index e3e7ad321eee8..954661ef44610 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -642,9 +642,7 @@ theorem map_equiv_normalizer_eq (H : Subgroup G) (f : G ≃* N) : simp only [mem_normalizer_iff, mem_map_equiv] rw [f.toEquiv.forall_congr] intro - erw [f.toEquiv.symm_apply_apply] - simp only [map_mul, map_inv] - erw [f.toEquiv.symm_apply_apply] + simp /-- The image of the normalizer is equal to the normalizer of the image of a bijective function. -/ diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean index be5caab4950ee..c0a18009abb14 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean @@ -136,8 +136,7 @@ noncomputable def trianglehMapOfHomotopy : comm₃ := by dsimp rw [← Functor.map_comp_assoc, triangleMapOfHomotopy_comm₃, Functor.map_comp, assoc, assoc] - erw [← NatTrans.naturality] - rfl + simp end mapOfHomotopy diff --git a/Mathlib/Algebra/Homology/Opposite.lean b/Mathlib/Algebra/Homology/Opposite.lean index e234cce59912e..5bbd8fee09f16 100644 --- a/Mathlib/Algebra/Homology/Opposite.lean +++ b/Mathlib/Algebra/Homology/Opposite.lean @@ -131,9 +131,7 @@ def opUnitIso : 𝟭 (HomologicalComplex V c)ᵒᵖ ≅ opFunctor V c ⋙ opInve intro X Y f refine Quiver.Hom.unop_inj ?_ ext x - simp only [Quiver.Hom.unop_op, Functor.id_map, Iso.op_hom, Functor.comp_map, unop_comp, - comp_f, Hom.isoOfComponents_hom_f] - erw [Category.id_comp, Category.comp_id (f.unop.f x)]) + simp) /-- Auxiliary definition for `opEquivalence`. -/ def opCounitIso : opInverse V c ⋙ opFunctor V c ≅ 𝟭 (HomologicalComplex Vᵒᵖ c.symm) := @@ -182,9 +180,7 @@ def unopUnitIso : 𝟭 (HomologicalComplex Vᵒᵖ c)ᵒᵖ ≅ unopFunctor V c intro X Y f refine Quiver.Hom.unop_inj ?_ ext x - simp only [Quiver.Hom.unop_op, Functor.id_map, Iso.op_hom, Functor.comp_map, unop_comp, - comp_f, Hom.isoOfComponents_hom_f] - erw [Category.id_comp, Category.comp_id (f.unop.f x)]) + simp) /-- Auxiliary definition for `unopEquivalence`. -/ def unopCounitIso : unopInverse V c ⋙ unopFunctor V c ≅ 𝟭 (HomologicalComplex V c.symm) := diff --git a/Mathlib/Algebra/Homology/QuasiIso.lean b/Mathlib/Algebra/Homology/QuasiIso.lean index 47a65f02f7de3..19e311240e6ed 100644 --- a/Mathlib/Algebra/Homology/QuasiIso.lean +++ b/Mathlib/Algebra/Homology/QuasiIso.lean @@ -208,10 +208,8 @@ lemma quasiIso_iff_of_arrow_mk_iso (φ : K ⟶ L) (φ' : K' ⟶ L') (e : Arrow.m [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] [∀ i, K'.HasHomology i] [∀ i, L'.HasHomology i] : QuasiIso φ ↔ QuasiIso φ' := by - rw [← quasiIso_iff_comp_left (show K' ⟶ K from e.inv.left) φ, + simp [← quasiIso_iff_comp_left (show K' ⟶ K from e.inv.left) φ, ← quasiIso_iff_comp_right φ' (show L' ⟶ L from e.inv.right)] - erw [Arrow.w e.inv] - rfl lemma quasiIso_of_arrow_mk_iso (φ : K ⟶ L) (φ' : K' ⟶ L') (e : Arrow.mk φ ≅ Arrow.mk φ') [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] diff --git a/Mathlib/Algebra/Homology/TotalComplexShift.lean b/Mathlib/Algebra/Homology/TotalComplexShift.lean index 5c418bdf20985..c1ab4298eb34f 100644 --- a/Mathlib/Algebra/Homology/TotalComplexShift.lean +++ b/Mathlib/Algebra/Homology/TotalComplexShift.lean @@ -102,18 +102,8 @@ instance : ((shiftFunctor₂ C y).obj K).HasTotal (up ℤ) := fun n => invFun := fun ⟨⟨a, b⟩, h⟩ => ⟨(a, b - y), by simp only [Set.mem_preimage, instTotalComplexShape_π, Set.mem_singleton_iff] at h ⊢ omega⟩ - left_inv := by - rintro ⟨⟨a, b⟩, h⟩ - ext - · rfl - · dsimp - omega - right_inv := by - intro ⟨⟨a, b⟩, h⟩ - ext - · rfl - · dsimp - omega } + left_inv _ := by simp + right_inv _ := by simp } (fun _ => Iso.refl _) instance : ((shiftFunctor₂ C y ⋙ shiftFunctor₁ C x).obj K).HasTotal (up ℤ) := by diff --git a/Mathlib/Algebra/Lie/Nilpotent.lean b/Mathlib/Algebra/Lie/Nilpotent.lean index 7abb7b337eb4f..c87b73a148611 100644 --- a/Mathlib/Algebra/Lie/Nilpotent.lean +++ b/Mathlib/Algebra/Lie/Nilpotent.lean @@ -148,7 +148,7 @@ theorem eventually_iInf_lowerCentralSeries_eq [IsArtinian R M] : theorem trivial_iff_lower_central_eq_bot : IsTrivial L M ↔ lowerCentralSeries R L M 1 = ⊥ := by constructor <;> intro h - · erw [eq_bot_iff, LieSubmodule.lieSpan_le]; rintro m ⟨x, n, hn⟩; rw [← hn, h.trivial]; simp + · simp · rw [LieSubmodule.eq_bot_iff] at h; apply IsTrivial.mk; intro x m; apply h apply LieSubmodule.subset_lieSpan -- Porting note: was `use x, m; rfl` diff --git a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean index 9603b7c878309..7e3e8206620a1 100644 --- a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean +++ b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean @@ -677,8 +677,8 @@ there is a linear map `lift g ∘ mkLinearMap = g`. -/ theorem lift_comp (g : M →ₗ[R] M'') (h : ∀ x : S, IsUnit ((algebraMap R (Module.End R M'')) x)) : (lift S g h).comp (mkLinearMap S M) = g := by - ext x; dsimp; rw [LocalizedModule.lift_mk] - erw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, one_smul] + ext x + simp [LocalizedModule.lift_mk] /-- If `g` is a linear map `M → M''` such that all scalar multiplication by `s : S` is invertible and diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean index 189a1bc957349..97e4ff84b8c19 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean @@ -835,9 +835,7 @@ lemma baseChange_negPolynomial : rw [← map_negPolynomial, map_baseChange] lemma baseChange_negY (x y : A) : - (W.baseChange B).toAffine.negY (f x) (f y) = f ((W.baseChange A).toAffine.negY x y) := by - erw [← map_negY, map_baseChange] - rfl + (W.baseChange B).toAffine.negY (f x) (f y) = f ((W.baseChange A).toAffine.negY x y) := by simp lemma baseChange_addPolynomial (x y L : A) : (W.baseChange B).toAffine.addPolynomial (f x) (f y) (f L) = @@ -847,21 +845,15 @@ lemma baseChange_addPolynomial (x y L : A) : lemma baseChange_addX (x₁ x₂ L : A) : (W.baseChange B).toAffine.addX (f x₁) (f x₂) (f L) = - f ((W.baseChange A).toAffine.addX x₁ x₂ L) := by - erw [← map_addX, map_baseChange] - rfl + f ((W.baseChange A).toAffine.addX x₁ x₂ L) := by simp lemma baseChange_negAddY (x₁ x₂ y₁ L : A) : (W.baseChange B).toAffine.negAddY (f x₁) (f x₂) (f y₁) (f L) = - f ((W.baseChange A).toAffine.negAddY x₁ x₂ y₁ L) := by - erw [← map_negAddY, map_baseChange] - rfl + f ((W.baseChange A).toAffine.negAddY x₁ x₂ y₁ L) := by simp lemma baseChange_addY (x₁ x₂ y₁ L : A) : (W.baseChange B).toAffine.addY (f x₁) (f x₂) (f y₁) (f L) = - f ((W.baseChange A).toAffine.addY x₁ x₂ y₁ L) := by - erw [← map_addY, map_baseChange] - rfl + f ((W.baseChange A).toAffine.addY x₁ x₂ y₁ L) := by simp variable {F : Type u} [Field F] [Algebra R F] [Algebra S F] [IsScalarTower R S F] {K : Type v} [Field K] [Algebra R K] [Algebra S K] [IsScalarTower R S K] (f : F →ₐ[S] K) diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean index 32767133cd5ef..ff4190d85fb10 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean @@ -84,8 +84,7 @@ instance {X : Scheme} (r : Γ(X, ⊤)) : rw [X.basicOpen_res] ext1 refine Set.image_preimage_eq_inter_range.trans ?_ - erw [Subtype.range_coe] - rfl + simp lemma isAffineOpen_of_isAffineOpen_basicOpen_aux (s : Set Γ(X, ⊤)) (hs : Ideal.span s = ⊤) (hs₂ : ∀ i ∈ s, IsAffineOpen (X.basicOpen i)) : diff --git a/Mathlib/AlgebraicTopology/CechNerve.lean b/Mathlib/AlgebraicTopology/CechNerve.lean index 1a6755cccda6b..ac073516e5bf9 100644 --- a/Mathlib/AlgebraicTopology/CechNerve.lean +++ b/Mathlib/AlgebraicTopology/CechNerve.lean @@ -117,10 +117,7 @@ def equivalenceLeftToRight (X : SimplicialObject.Augmented C) (F : Arrow C) left := { app := fun x => Limits.WidePullback.lift (X.hom.app _ ≫ G.right) - (fun i => X.left.map (SimplexCategory.const _ x.unop i).op ≫ G.left) fun i => by - dsimp - erw [Category.assoc, Arrow.w, Augmented.toArrow_obj_hom, NatTrans.naturality_assoc, - Functor.const_obj_map, Category.id_comp] + (fun i => X.left.map (SimplexCategory.const _ x.unop i).op ≫ G.left) fun i => by simp naturality := by intro x y f dsimp @@ -280,9 +277,7 @@ def equivalenceRightToLeft (F : Arrow C) (X : CosimplicialObject.Augmented C) rw [Category.assoc, ← X.right.map_comp] rfl · dsimp - simp only [Functor.const_obj_map, ← NatTrans.naturality, WidePushout.head_desc_assoc, - WidePushout.head_desc, Category.assoc] - erw [Category.id_comp] } + simp [← NatTrans.naturality] } /-- A helper function used in defining the Čech conerve adjunction. -/ @[simps] @@ -408,10 +403,7 @@ def iso (X : C) : (Arrow.mk (terminal.from X)).cechNerve ≅ cechNerveTerminalFr NatIso.ofComponents (fun _ => wideCospan.limitIsoPi _ _) (fun {m n} f => by dsimp only [cechNerveTerminalFrom, Arrow.cechNerve] ext ⟨j⟩ - simp only [Category.assoc, limit.lift_π, Fan.mk_π_app] - erw [wideCospan.limitIsoPi_hom_comp_pi, - wideCospan.limitIsoPi_hom_comp_pi, limit.lift_π] - rfl) + simp) end CechNerveTerminalFrom diff --git a/Mathlib/AlgebraicTopology/DoldKan/Homotopies.lean b/Mathlib/AlgebraicTopology/DoldKan/Homotopies.lean index 1c3db5df719f3..6ecd1804b9639 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Homotopies.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Homotopies.lean @@ -145,9 +145,7 @@ theorem hσ'_naturality (q : ℕ) (n m : ℕ) (hnm : c.Rel m n) {X Y : Simplicia unfold hσ split_ifs · rw [zero_comp, comp_zero] - · simp only [zsmul_comp, comp_zsmul] - erw [f.naturality] - rfl + · simp /-- For each q, `Hσ q` is a natural transformation. -/ def natTransHσ (q : ℕ) : alternatingFaceMapComplex C ⟶ alternatingFaceMapComplex C where diff --git a/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean b/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean index cff0ffb6de103..d96dcebf3d5bd 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean @@ -111,26 +111,9 @@ using `PInfty` identifies to the composition of the normalized Moore complex fun and the inclusion in the Karoubi envelope. -/ def N₁_iso_normalizedMooreComplex_comp_toKaroubi : N₁ ≅ normalizedMooreComplex A ⋙ toKaroubi _ where hom := - { app := fun X => - { f := PInftyToNormalizedMooreComplex X - comm := by erw [comp_id, PInfty_comp_PInftyToNormalizedMooreComplex] } - naturality := fun X Y f => by - simp only [Functor.comp_map, normalizedMooreComplex_map, - PInftyToNormalizedMooreComplex_naturality, Karoubi.hom_ext_iff, Karoubi.comp_f, N₁_map_f, - PInfty_comp_PInftyToNormalizedMooreComplex_assoc, toKaroubi_map_f, assoc] } + { app := fun X => { f := PInftyToNormalizedMooreComplex X } } inv := - { app := fun X => - { f := inclusionOfMooreComplexMap X - comm := by erw [inclusionOfMooreComplexMap_comp_PInfty, id_comp] } - naturality := fun X Y f => by - ext - simp only [Functor.comp_obj, normalizedMooreComplex_obj, toKaroubi_obj_X, - NormalizedMooreComplex.obj_X, N₁_obj_X, AlternatingFaceMapComplex.obj_X, Functor.comp_map, - normalizedMooreComplex_map, Karoubi.comp_f, toKaroubi_map_f, HomologicalComplex.comp_f, - NormalizedMooreComplex.map_f, inclusionOfMooreComplexMap_f, NormalizedMooreComplex.objX, - factorThru_arrow, N₁_map_f, inclusionOfMooreComplexMap_comp_PInfty_assoc, - AlternatingFaceMapComplex.map_f] - } + { app := fun X => { f := inclusionOfMooreComplexMap X } } hom_inv_id := by ext X : 3 simp only [PInftyToNormalizedMooreComplex_comp_inclusionOfMooreComplexMap, diff --git a/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean b/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean index 1a0800fec44ea..bfe4476eb64b1 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean @@ -154,7 +154,7 @@ noncomputable def nondegComplex : ChainComplex C ℕ where simp only [d, assoc] have eq : K[X].d i j ≫ 𝟙 (X.obj (op [j])) ≫ K[X].d j k ≫ s.πSummand (IndexSet.id (op [k])) = 0 := by - erw [id_comp, HomologicalComplex.d_comp_d_assoc, zero_comp] + simp rw [s.decomposition_id] at eq classical rw [Fintype.sum_eq_add_sum_compl (IndexSet.id (op [j])), add_comp, comp_add, assoc, diff --git a/Mathlib/Analysis/Analytic/ChangeOrigin.lean b/Mathlib/Analysis/Analytic/ChangeOrigin.lean index 176f6f15e6afc..0e2e48a529be8 100644 --- a/Mathlib/Analysis/Analytic/ChangeOrigin.lean +++ b/Mathlib/Analysis/Analytic/ChangeOrigin.lean @@ -140,9 +140,7 @@ def changeOriginIndexEquiv : (⟨k', l', ⟨s.map (finCongr hkl).toEmbedding, hs'⟩⟩ : Σk l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) = ⟨k, l, ⟨s, hs⟩⟩ by apply this <;> simp only [hs, add_tsub_cancel_right] - rintro _ _ rfl rfl hkl hs' - simp only [Equiv.refl_toEmbedding, finCongr_refl, Finset.map_refl, eq_self_iff_true, - OrderIso.refl_toEquiv, and_self_iff, heq_iff_eq] + simp right_inv := by rintro ⟨n, s⟩ simp [tsub_add_cancel_of_le (card_finset_fin_le s), finCongr_eq_equivCast] diff --git a/Mathlib/CategoryTheory/Adjunction/Mates.lean b/Mathlib/CategoryTheory/Adjunction/Mates.lean index cd608363c1820..322bbb825e516 100644 --- a/Mathlib/CategoryTheory/Adjunction/Mates.lean +++ b/Mathlib/CategoryTheory/Adjunction/Mates.lean @@ -101,8 +101,7 @@ def mateEquiv : (G ⋙ L₂ ⟶ L₁ ⋙ H) ≃ (R₁ ⋙ G ⟶ H ⋙ R₂) wher /-- A component of a transposed version of the mates correspondence. -/ theorem mateEquiv_counit (α : G ⋙ L₂ ⟶ L₁ ⋙ H) (d : D) : L₂.map ((mateEquiv adj₁ adj₂ α).app _) ≫ adj₂.counit.app _ = - α.app _ ≫ H.map (adj₁.counit.app d) := by - erw [Functor.map_comp]; simp + α.app _ ≫ H.map (adj₁.counit.app d) := by simp /-- A component of a transposed version of the inverse mates correspondence. -/ theorem mateEquiv_counit_symm (α : R₁ ⋙ G ⟶ H ⋙ R₂) (d : D) : diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean index 42ce3a6553dbd..63d88f4bb3234 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean @@ -783,12 +783,7 @@ category of structured arrows `d ⟶ F.obj c` to the category of costructured ar def toCostructuredArrow (F : C ⥤ D) (d : D) : (StructuredArrow d F)ᵒᵖ ⥤ CostructuredArrow F.op (op d) where obj X := @CostructuredArrow.mk _ _ _ _ _ (op X.unop.right) F.op X.unop.hom.op - map f := - CostructuredArrow.homMk f.unop.right.op - (by - dsimp - rw [← op_comp, ← f.unop.w, Functor.const_obj_map] - erw [Category.id_comp]) + map f := CostructuredArrow.homMk f.unop.right.op (by simp [← op_comp]) /-- For a functor `F : C ⥤ D` and an object `d : D`, we obtain a contravariant functor from the category of structured arrows `op d ⟶ F.op.obj c` to the category of costructured arrows @@ -803,8 +798,8 @@ def toCostructuredArrow' (F : C ⥤ D) (d : D) : (by dsimp rw [← Quiver.Hom.unop_op (F.map (Quiver.Hom.unop f.unop.right)), ← unop_comp, ← F.op_map, ← - f.unop.w, Functor.const_obj_map] - erw [Category.id_comp]) + f.unop.w] + simp) end StructuredArrow @@ -818,12 +813,7 @@ category of costructured arrows `F.obj c ⟶ d` to the category of structured ar def toStructuredArrow (F : C ⥤ D) (d : D) : (CostructuredArrow F d)ᵒᵖ ⥤ StructuredArrow (op d) F.op where obj X := @StructuredArrow.mk _ _ _ _ _ (op X.unop.left) F.op X.unop.hom.op - map f := - StructuredArrow.homMk f.unop.left.op - (by - dsimp - rw [← op_comp, f.unop.w, Functor.const_obj_map] - erw [Category.comp_id]) + map f := StructuredArrow.homMk f.unop.left.op (by simp [← op_comp]) /-- For a functor `F : C ⥤ D` and an object `d : D`, we obtain a contravariant functor from the category of costructured arrows `F.op.obj c ⟶ op d` to the category of structured arrows @@ -839,7 +829,7 @@ def toStructuredArrow' (F : C ⥤ D) (d : D) : dsimp rw [← Quiver.Hom.unop_op (F.map f.unop.left.unop), ← unop_comp, ← F.op_map, f.unop.w, Functor.const_obj_map] - erw [Category.comp_id]) + simp) end CostructuredArrow diff --git a/Mathlib/CategoryTheory/ComposableArrows.lean b/Mathlib/CategoryTheory/ComposableArrows.lean index 45cd88fc81f69..9d9c9bb7cdc6d 100644 --- a/Mathlib/CategoryTheory/ComposableArrows.lean +++ b/Mathlib/CategoryTheory/ComposableArrows.lean @@ -335,10 +335,7 @@ lemma map_one_succ (j : ℕ) (hj : j + 1 < n + 1 + 1) : map F f 1 ⟨j + 1, hj⟩ (by simp [Fin.le_def]) = F.map' 0 j := rfl lemma map_id (i : Fin (n + 1 + 1)) : map F f i i (by simp) = 𝟙 _ := by - obtain ⟨i, hi⟩ := i - cases i - · rfl - · apply F.map_id + obtain ⟨_|_, hi⟩ := i <;> simp lemma map_comp {i j k : Fin (n + 1 + 1)} (hij : i ≤ j) (hjk : j ≤ k) : map F f i k (hij.trans hjk) = map F f i j hij ≫ map F f j k hjk := by @@ -542,14 +539,8 @@ lemma ext_succ {F G : ComposableArrows C (n + 1)} (h₀ : F.obj' 0 = G.obj' 0) exact Functor.ext_of_iso (isoMkSucc (eqToIso h₀) (eqToIso h) (by rw [w] dsimp [app'] - rw [eqToHom_app, assoc, assoc, eqToHom_trans, eqToHom_refl, comp_id])) this (by - rintro ⟨i, hi⟩ - dsimp - cases' i with i - · erw [homMkSucc_app_zero] - · rw [homMkSucc_app_succ] - dsimp [app'] - rw [eqToHom_app]) + rw [eqToHom_app, assoc, assoc, eqToHom_trans, eqToHom_refl, comp_id])) this + (by rintro ⟨_|_, hi⟩ <;> simp) lemma precomp_surjective (F : ComposableArrows C (n + 1)) : ∃ (F₀ : ComposableArrows C n) (X₀ : C) (f₀ : X₀ ⟶ F₀.left), F = F₀.precomp f₀ := diff --git a/Mathlib/CategoryTheory/Equivalence.lean b/Mathlib/CategoryTheory/Equivalence.lean index a7842ed6f55b9..85a5fc5503a8c 100644 --- a/Mathlib/CategoryTheory/Equivalence.lean +++ b/Mathlib/CategoryTheory/Equivalence.lean @@ -182,7 +182,7 @@ theorem unit_inverse_comp (e : C ≌ D) (Y : D) : slice_lhs 2 3 => erw [← map_comp e.inverse, ← e.counitIso.inv.naturality, (e.counitIso.app _).hom_inv_id, map_id] - erw [id_comp, (e.unitIso.app _).hom_inv_id]; rfl + simp @[reassoc (attr := simp)] theorem inverse_counitInv_comp (e : C ≌ D) (Y : D) : diff --git a/Mathlib/CategoryTheory/Grothendieck.lean b/Mathlib/CategoryTheory/Grothendieck.lean index 2d28b0e705e8b..c987c94e3af65 100644 --- a/Mathlib/CategoryTheory/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Grothendieck.lean @@ -87,7 +87,7 @@ theorem ext {X Y : Grothendieck F} (f g : Hom X Y) (w_base : f.base = g.base) -/ def id (X : Grothendieck F) : Hom X X where base := 𝟙 X.base - fiber := eqToHom (by erw [CategoryTheory.Functor.map_id, Functor.id_obj X.fiber]) + fiber := eqToHom (by simp) instance (X : Grothendieck F) : Inhabited (Hom X X) := ⟨id X⟩ @@ -97,7 +97,7 @@ instance (X : Grothendieck F) : Inhabited (Hom X X) := def comp {X Y Z : Grothendieck F} (f : Hom X Y) (g : Hom Y Z) : Hom X Z where base := f.base ≫ g.base fiber := - eqToHom (by erw [Functor.map_comp, Functor.comp_obj]) ≫ (F.map g.base).map f.fiber ≫ g.fiber + eqToHom (by simp) ≫ (F.map g.base).map f.fiber ≫ g.fiber attribute [local simp] eqToHom_map @@ -126,7 +126,7 @@ theorem id_base (X : Grothendieck F) : @[simp] theorem id_fiber (X : Grothendieck F) : - Hom.fiber (𝟙 X) = eqToHom (by erw [CategoryTheory.Functor.map_id, Functor.id_obj X.fiber]) := + Hom.fiber (𝟙 X) = eqToHom (by simp) := rfl @[simp] @@ -137,11 +137,9 @@ theorem comp_base {X Y Z : Grothendieck F} (f : X ⟶ Y) (g : Y ⟶ Z) : @[simp] theorem comp_fiber {X Y Z : Grothendieck F} (f : X ⟶ Y) (g : Y ⟶ Z) : Hom.fiber (f ≫ g) = - eqToHom (by erw [Functor.map_comp, Functor.comp_obj]) ≫ - (F.map g.base).map f.fiber ≫ g.fiber := + eqToHom (by simp) ≫ (F.map g.base).map f.fiber ≫ g.fiber := rfl - theorem congr {X Y : Grothendieck F} {f g : X ⟶ Y} (h : f = g) : f.fiber = eqToHom (by subst h; rfl) ≫ g.fiber := by subst h diff --git a/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean b/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean index 29b94beac78e3..34c4f44f5ce72 100644 --- a/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean +++ b/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean @@ -137,14 +137,11 @@ theorem toKaroubi_comp_karoubiFunctorCategoryEmbedding : apply Functor.ext · intro X Y f ext j - dsimp [toKaroubi] - simp only [eqToHom_app, eqToHom_refl] - erw [comp_id, id_comp] + simp · intro X apply Functor.ext · intro j j' φ ext - dsimp simp · intro j rfl diff --git a/Mathlib/CategoryTheory/Limits/HasLimits.lean b/Mathlib/CategoryTheory/Limits/HasLimits.lean index c3297674c5db3..e9ece3954362f 100644 --- a/Mathlib/CategoryTheory/Limits/HasLimits.lean +++ b/Mathlib/CategoryTheory/Limits/HasLimits.lean @@ -458,10 +458,10 @@ def lim : (J ⥤ C) ⥤ C where map α := limMap α map_id F := by apply Limits.limit.hom_ext; intro j - erw [limMap_π, Category.id_comp, Category.comp_id] + simp map_comp α β := by apply Limits.limit.hom_ext; intro j - erw [assoc, IsLimit.fac, IsLimit.fac, ← assoc, IsLimit.fac, assoc]; rfl + simp [assoc] end diff --git a/Mathlib/CategoryTheory/Limits/IsLimit.lean b/Mathlib/CategoryTheory/Limits/IsLimit.lean index 6c1343fba3041..be68bfd74c3fc 100644 --- a/Mathlib/CategoryTheory/Limits/IsLimit.lean +++ b/Mathlib/CategoryTheory/Limits/IsLimit.lean @@ -643,14 +643,10 @@ theorem hom_desc (h : IsColimit t) {W : C} (m : t.pt ⟶ W) : m = h.desc { pt := W - ι := - { app := fun b => t.ι.app b ≫ m - naturality := by intros; erw [← assoc, t.ι.naturality, comp_id, comp_id] } } := + ι := { app := fun b => t.ι.app b ≫ m } } := h.uniq { pt := W - ι := - { app := fun b => t.ι.app b ≫ m - naturality := _ } } + ι := { app := fun b => t.ι.app b ≫ m } } m fun _ => rfl /-- Two morphisms out of a colimit are equal if their compositions with diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean index 28ea0694e2027..29d7bf37aa103 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean @@ -579,7 +579,7 @@ theorem biproduct.map_eq_map' {f g : J → C} [HasBiproduct f] [HasBiproduct g] dsimp rw [biproduct.ι_π_assoc, biproduct.ι_π] split_ifs with h - · subst h; rw [eqToHom_refl, Category.id_comp]; erw [Category.comp_id] + · subst h; simp · simp @[reassoc (attr := simp)] diff --git a/Mathlib/CategoryTheory/Limits/VanKampen.lean b/Mathlib/CategoryTheory/Limits/VanKampen.lean index 705c13f505a00..dc4efd7144691 100644 --- a/Mathlib/CategoryTheory/Limits/VanKampen.lean +++ b/Mathlib/CategoryTheory/Limits/VanKampen.lean @@ -108,7 +108,7 @@ noncomputable def IsUniversalColimit.isColimit {F : J ⥤ C} {c : Cocone F} refine ((h c (𝟙 F) (𝟙 c.pt : _) (by rw [Functor.map_id, Category.comp_id, Category.id_comp]) (NatTrans.equifibered_of_isIso _)) fun j => ?_).some haveI : IsIso (𝟙 c.pt) := inferInstance - exact IsPullback.of_vert_isIso ⟨by erw [NatTrans.id_app, Category.comp_id, Category.id_comp]⟩ + exact IsPullback.of_vert_isIso ⟨by simp⟩ /-- A van Kampen colimit is a colimit. -/ noncomputable def IsVanKampenColimit.isColimit {F : J ⥤ C} {c : Cocone F} @@ -345,10 +345,7 @@ theorem IsUniversalColimit.map_reflective let cf : (Cocones.precompose β.hom).obj c' ⟶ Gl.mapCocone c'' := by refine { hom := pullback.lift ?_ f ?_ ≫ (PreservesPullback.iso _ _ _).inv, w := ?_ } · exact inv <| adj.counit.app c'.pt - · rw [IsIso.inv_comp_eq, ← adj.counit_naturality_assoc f, ← cancel_mono (adj.counit.app <| - Gl.obj c.pt), Category.assoc, Category.assoc, adj.left_triangle_components] - erw [Category.comp_id] - rfl + · simp [← cancel_mono (adj.counit.app <| Gl.obj c.pt)] · intro j rw [← Category.assoc, Iso.comp_inv_eq] ext diff --git a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean index 2b1164339e414..4f1f7e9e08cb8 100644 --- a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean @@ -268,11 +268,9 @@ theorem braiding_leftUnitor_aux₂ (X : C) : ((β_ X (𝟙_ C)).hom ▷ 𝟙_ C) ≫ (α_ _ _ _).hom ≫ (α_ _ _ _).inv ≫ ((λ_ X).hom ▷ 𝟙_ C) := by monoidal _ = ((β_ X (𝟙_ C)).hom ▷ 𝟙_ C) ≫ (α_ _ _ _).hom ≫ (_ ◁ (β_ X _).hom) ≫ - (_ ◁ (β_ X _).inv) ≫ (α_ _ _ _).inv ≫ ((λ_ X).hom ▷ 𝟙_ C) := by - simp + (_ ◁ (β_ X _).inv) ≫ (α_ _ _ _).inv ≫ ((λ_ X).hom ▷ 𝟙_ C) := by simp _ = (α_ _ _ _).hom ≫ (β_ _ _).hom ≫ (α_ _ _ _).hom ≫ (_ ◁ (β_ X _).inv) ≫ (α_ _ _ _).inv ≫ - ((λ_ X).hom ▷ 𝟙_ C) := by - (slice_lhs 1 3 => rw [← hexagon_forward]); simp only [assoc] + ((λ_ X).hom ▷ 𝟙_ C) := by simp _ = (α_ _ _ _).hom ≫ (β_ _ _).hom ≫ ((λ_ _).hom ▷ X) ≫ (β_ X _).inv := by rw [braiding_leftUnitor_aux₁] _ = (α_ _ _ _).hom ≫ (_ ◁ (λ_ _).hom) ≫ (β_ _ _).hom ≫ (β_ X _).inv := by @@ -302,8 +300,7 @@ theorem braiding_rightUnitor_aux₂ (X : C) : _ = (α_ _ _ _).inv ≫ (β_ _ _).hom ≫ (α_ _ _ _).inv ≫ ((β_ _ X).inv ▷ _) ≫ (α_ _ _ _).hom ≫ (𝟙_ C ◁ (ρ_ X).hom) := by (slice_lhs 1 3 => rw [← hexagon_reverse]); simp only [assoc] - _ = (α_ _ _ _).inv ≫ (β_ _ _).hom ≫ (X ◁ (ρ_ _).hom) ≫ (β_ _ X).inv := by - rw [braiding_rightUnitor_aux₁] + _ = (α_ _ _ _).inv ≫ (β_ _ _).hom ≫ (X ◁ (ρ_ _).hom) ≫ (β_ _ X).inv := by simp _ = (α_ _ _ _).inv ≫ ((ρ_ _).hom ▷ _) ≫ (β_ _ X).hom ≫ (β_ _ _).inv := by (slice_lhs 2 3 => rw [← braiding_naturality_left]); simp only [assoc] _ = (α_ _ _ _).inv ≫ ((ρ_ _).hom ▷ _) := by rw [Iso.hom_inv_id, comp_id] diff --git a/Mathlib/CategoryTheory/Sites/Sheaf.lean b/Mathlib/CategoryTheory/Sites/Sheaf.lean index a94ed5480644d..04835ed2104f8 100644 --- a/Mathlib/CategoryTheory/Sites/Sheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Sheaf.lean @@ -582,7 +582,6 @@ theorem isSheaf_iff_multiequalizer [∀ (X : C) (S : J.Cover X), HasMultiequaliz · apply (@asIso _ _ _ _ _ h).symm · intro a symm - erw [IsIso.inv_comp_eq] simp end MultiequalizerConditions diff --git a/Mathlib/CategoryTheory/Triangulated/Rotate.lean b/Mathlib/CategoryTheory/Triangulated/Rotate.lean index 4ef56167fa648..92a42f9b69e8f 100644 --- a/Mathlib/CategoryTheory/Triangulated/Rotate.lean +++ b/Mathlib/CategoryTheory/Triangulated/Rotate.lean @@ -101,13 +101,9 @@ def invRotate : Triangle C ⥤ Triangle C where hom₃ := f.hom₂ comm₁ := by dsimp - simp only [neg_comp, assoc, comp_neg, neg_inj, ← Functor.map_comp_assoc, ← f.comm₃] - rw [Functor.map_comp, assoc] - erw [← NatTrans.naturality] - rfl - comm₃ := by - erw [← reassoc_of% f.comm₂, Category.assoc, ← NatTrans.naturality] - rfl } + simp only [comp_neg, ← Functor.map_comp_assoc, ← f.comm₃] + rw [Functor.map_comp] + simp } variable {C} variable [∀ n : ℤ, Functor.Additive (shiftFunctor C n)] diff --git a/Mathlib/Computability/RegularExpressions.lean b/Mathlib/Computability/RegularExpressions.lean index b816d00833eee..c8dc9b8d41c7c 100644 --- a/Mathlib/Computability/RegularExpressions.lean +++ b/Mathlib/Computability/RegularExpressions.lean @@ -403,7 +403,7 @@ theorem matches'_map (f : α → β) : exact image_singleton -- Porting note: the following close with last `rw` but not with `simp`? | R + S => by simp only [matches'_map, map, matches'_add]; rw [map_add] - | comp R S => by simp only [matches'_map, map, matches'_mul]; erw [map_mul] + | comp R S => by simp [matches'_map] | star R => by simp_rw [map, matches', matches'_map] rw [Language.kstar_eq_iSup_pow, Language.kstar_eq_iSup_pow] diff --git a/Mathlib/Data/Int/Cast/Basic.lean b/Mathlib/Data/Int/Cast/Basic.lean index ade0aeafd71c2..27cca413964e4 100644 --- a/Mathlib/Data/Int/Cast/Basic.lean +++ b/Mathlib/Data/Int/Cast/Basic.lean @@ -72,7 +72,7 @@ theorem cast_one : ((1 : ℤ) : R) = 1 := by @[simp, norm_cast] theorem cast_neg : ∀ n, ((-n : ℤ) : R) = -n - | (0 : ℕ) => by erw [cast_zero, neg_zero] + | (0 : ℕ) => by simp | (n + 1 : ℕ) => by erw [cast_natCast, cast_negSucc] | -[n+1] => by erw [cast_natCast, cast_negSucc, neg_neg] -- type had `HasLiftT` diff --git a/Mathlib/Data/Int/Defs.lean b/Mathlib/Data/Int/Defs.lean index 732c14aa0df2c..2b92ec1456668 100644 --- a/Mathlib/Data/Int/Defs.lean +++ b/Mathlib/Data/Int/Defs.lean @@ -219,7 +219,7 @@ than `b`, and the `pred` of a number less than `b`. -/ where /-- The positive case of `Int.inductionOn'`. -/ pos : ∀ n : ℕ, C (b + n) - | 0 => cast (by erw [Int.add_zero]) H0 + | 0 => cast (by simp) H0 | n+1 => cast (by rw [Int.add_assoc]; rfl) <| Hs _ (Int.le_add_of_nonneg_right (ofNat_nonneg _)) (pos n) diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 311d98d7e2fcd..5f0e3516fab8b 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -328,7 +328,7 @@ theorem getLast_replicate_succ (m : ℕ) (a : α) : lemma getLast_filter' {p : α → Bool} : ∀ (l : List α) (hlp : l.filter p ≠ []), p (l.getLast (hlp <| ·.symm ▸ rfl)) = true → (l.filter p).getLast hlp = l.getLast (hlp <| ·.symm ▸ rfl) - | [a], h, h' => by rw [List.getLast_singleton'] at h'; simp [List.filter_cons, h'] + | [a], h, h' => by simp | a :: b :: as, h, h' => by rw [List.getLast_cons_cons] at h' ⊢ simp only [List.filter_cons (x := a)] at h ⊢ diff --git a/Mathlib/Data/Sum/Interval.lean b/Mathlib/Data/Sum/Interval.lean index f376aa6460b2f..9d51847e6bfbb 100644 --- a/Mathlib/Data/Sum/Interval.lean +++ b/Mathlib/Data/Sum/Interval.lean @@ -217,10 +217,10 @@ instance instLocallyFiniteOrder : LocallyFiniteOrder (α ⊕ β) where finsetIco := sumLift₂ Ico Ico finsetIoc := sumLift₂ Ioc Ioc finsetIoo := sumLift₂ Ioo Ioo - finset_mem_Icc := by rintro (a | a) (b | b) (x | x) <;> simp - finset_mem_Ico := by rintro (a | a) (b | b) (x | x) <;> simp - finset_mem_Ioc := by rintro (a | a) (b | b) (x | x) <;> simp - finset_mem_Ioo := by rintro (a | a) (b | b) (x | x) <;> simp + finset_mem_Icc := by simp + finset_mem_Ico := by simp + finset_mem_Ioc := by simp + finset_mem_Ioo := by simp variable (a₁ a₂ : α) (b₁ b₂ : β) diff --git a/Mathlib/Data/ZMod/Basic.lean b/Mathlib/Data/ZMod/Basic.lean index 33ba9dfef1f77..e6ccd28f30073 100644 --- a/Mathlib/Data/ZMod/Basic.lean +++ b/Mathlib/Data/ZMod/Basic.lean @@ -1046,7 +1046,7 @@ theorem neg_eq_self_iff {n : ℕ} (a : ZMod n) : -a = a ↔ a = 0 ∨ 2 * a.val refine (a.val_lt.not_le <| Nat.le_of_mul_le_mul_left ?_ zero_lt_two).elim rw [he, mul_comm] apply Nat.mul_le_mul_left - erw [Nat.succ_le_succ_iff, Nat.succ_le_succ_iff]; simp + simp · rintro (rfl | h) · rw [val_zero, mul_zero] apply dvd_zero diff --git a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean index 9456c6bb4f9f8..844ba7dddb0bc 100644 --- a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean +++ b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean @@ -130,7 +130,7 @@ theorem isoRestrict_hom_ofRestrict : (isoRestrict f).hom ≫ Y.ofRestrict _ = f erw [Category.comp_id, comp_c_app, f.c.naturality_assoc, ← X.presheaf.map_comp] trans f.c.app x ≫ X.presheaf.map (𝟙 _) · congr 1 - · erw [X.presheaf.map_id, Category.comp_id] + · simp @[reassoc (attr := simp)] theorem isoRestrict_inv_ofRestrict : (isoRestrict f).inv ≫ f = Y.ofRestrict _ := by @@ -417,7 +417,7 @@ theorem pullbackConeOfLeftLift_snd : erw [← s.pt.presheaf.map_comp, ← s.pt.presheaf.map_comp] trans s.snd.c.app x ≫ s.pt.presheaf.map (𝟙 _) · congr 1 - · rw [s.pt.presheaf.map_id]; erw [Category.comp_id] + · simp instance pullbackConeSndIsOpenImmersion : IsOpenImmersion (pullbackConeOfLeft f g).snd := by erw [CategoryTheory.Limits.PullbackCone.mk_snd] diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index 77f139367118c..b689c08051fcb 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -354,10 +354,10 @@ def ιInvApp {i : D.J} (U : Opens (D.U i).carrier) : induction Y using Opposite.rec' with | h Y => ?_ let f : Y ⟶ X := f'.unop; have : f' = f.op := rfl; clear_value f; subst this rcases f with (_ | ⟨j, k⟩ | ⟨j, k⟩) - · erw [Category.id_comp, CategoryTheory.Functor.map_id] - rw [Category.comp_id] - · erw [Category.id_comp]; congr 1 - erw [Category.id_comp] + · simp + · simp only [Functor.const_obj_obj, Functor.const_obj_map, Category.id_comp] + congr 1 + simp only [Functor.const_obj_obj, Functor.const_obj_map, Category.id_comp] -- It remains to show that the blue is equal to red + green in the original diagram. -- The proof strategy is illustrated in ![this diagram](https://i.imgur.com/mBzV1Rx.png) -- where we prove red = pink = light-blue = green = blue. diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean index 4d7c3d0c180bc..1f4e389113201 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean @@ -333,8 +333,7 @@ theorem colimitPresheafObjIsoComponentwiseLimit_inv_ι_app (F : J ⥤ Presheafed suffices f_eq : f = 𝟙 _ by rw [f_eq, comp_id] erw [← (F.obj j).presheaf.map_id] change (F.obj j).presheaf.map _ ≫ _ = _ - erw [← (F.obj j).presheaf.map_comp, ← (F.obj j).presheaf.map_comp] - congr 1 + simp @[simp] theorem colimitPresheafObjIsoComponentwiseLimit_hom_π (F : J ⥤ PresheafedSpace.{_, _, v} C) diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean index 27682d972414a..5932cf65e0bb7 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean @@ -244,11 +244,7 @@ theorem evenToNeg_ι (Q' : QuadraticForm R M) (h : Q' = -Q) (m₁ m₂ : M) : theorem evenToNeg_comp_evenToNeg (Q' : QuadraticForm R M) (h : Q' = -Q) (h' : Q = -Q') : (evenToNeg Q' Q h').comp (evenToNeg Q Q' h) = AlgHom.id R _ := by ext m₁ m₂ : 4 - dsimp only [EvenHom.compr₂_bilin, LinearMap.compr₂_apply, AlgHom.toLinearMap_apply, - AlgHom.comp_apply, AlgHom.id_apply] - rw [evenToNeg_ι] - -- Needed to use `RingHom.map_neg` to avoid a timeout and now `erw` https://github.com/leanprover-community/mathlib4/pull/8386 - erw [RingHom.map_neg, evenToNeg_ι, neg_neg] + simp [evenToNeg_ι] /-- The even subalgebras of the algebras with quadratic form `Q` and `-Q` are isomorphic. diff --git a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean index 57b1ced0fed82..d3f50bfe9f809 100644 --- a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean +++ b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean @@ -644,10 +644,7 @@ theorem det_fromBlocks_zero₂₁ (A : Matrix m m R) (B : Matrix m n R) (D : Mat · simp_rw [sum_mul_sum, ← sum_product', univ_product_univ] refine sum_nbij (fun σ ↦ σ.fst.sumCongr σ.snd) ?_ ?_ ?_ ?_ · intro σ₁₂ _ - simp only - erw [Set.mem_toFinset, MonoidHom.mem_range] - use σ₁₂ - simp only [sumCongrHom_apply] + simp · intro σ₁ _ σ₂ _ dsimp only intro h diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index f4fa630b71b58..578e4ff4923d4 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -1555,13 +1555,11 @@ def MultilinearMap.curryRight (f : MultilinearMap R M M₂) : map_update_add' := @fun dec m i x y => by rw [Subsingleton.elim dec (by clear dec; infer_instance)]; clear dec ext z - change f (snoc (update m i (x + y)) z) = f (snoc (update m i x) z) + f (snoc (update m i y) z) - rw [snoc_update, snoc_update, snoc_update, f.map_update_add] + simp map_update_smul' := @fun dec m i c x => by rw [Subsingleton.elim dec (by clear dec; infer_instance)]; clear dec ext z - change f (snoc (update m i (c • x)) z) = c • f (snoc (update m i x) z) - rw [snoc_update, snoc_update, f.map_update_smul] + simp @[simp] theorem MultilinearMap.curryRight_apply (f : MultilinearMap R M M₂) diff --git a/Mathlib/LinearAlgebra/Span/Basic.lean b/Mathlib/LinearAlgebra/Span/Basic.lean index 7ef6263250020..707818b275884 100644 --- a/Mathlib/LinearAlgebra/Span/Basic.lean +++ b/Mathlib/LinearAlgebra/Span/Basic.lean @@ -137,9 +137,7 @@ theorem span_smul_eq_of_isUnit (s : Set M) (r : R) (hr : IsUnit r) : span R (r apply le_antisymm · apply span_smul_le · convert span_smul_le (r • s) ((hr.unit⁻¹ : _) : R) - rw [smul_smul] - erw [hr.unit.inv_val] - rw [one_smul] + simp [smul_smul] /-- We can regard `coe_iSup_of_chain` as the statement that `(↑) : (Submodule R M) → Set M` is Scott continuous for the ω-complete partial order induced by the complete lattice structures. -/ diff --git a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean index c06613d1d7037..5c48e5305772b 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean @@ -252,7 +252,7 @@ instance instAlgebra : Algebra R (𝒜 ᵍ⊗[R] ℬ) where simp_rw [DirectSum.decompose_algebraMap, DirectSum.decompose_one, algebraMap_gradedMul] -- Qualified `map_smul` to avoid a TC timeout https://github.com/leanprover-community/mathlib4/pull/8386 erw [LinearMap.map_smul] - erw [LinearEquiv.symm_apply_apply] + simp lemma algebraMap_def (r : R) : algebraMap R (𝒜 ᵍ⊗[R] ℬ) r = algebraMap R A r ᵍ⊗ₜ[R] 1 := rfl diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean index d597d44b6f446..b7600589ddd7c 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean @@ -428,8 +428,7 @@ def Set.rangeInl : (range Sum.inl : Set (α ⊕ β)) ≃ᵐ α where toEquiv := Equiv.Set.rangeInl α β measurable_toFun s (hs : MeasurableSet s) := by refine ⟨_, hs.inl_image, Set.ext ?_⟩ - rintro ⟨ab, a, rfl⟩ - simp [Set.range_inl] + simp measurable_invFun := Measurable.subtype_mk measurable_inl /-- `β` is equivalent to its image in `α ⊕ β` as measurable spaces. -/ @@ -437,8 +436,7 @@ def Set.rangeInr : (range Sum.inr : Set (α ⊕ β)) ≃ᵐ β where toEquiv := Equiv.Set.rangeInr α β measurable_toFun s (hs : MeasurableSet s) := by refine ⟨_, hs.inr_image, Set.ext ?_⟩ - rintro ⟨ab, b, rfl⟩ - simp [Set.range_inr] + simp measurable_invFun := Measurable.subtype_mk measurable_inr /-- Products distribute over sums (on the right) as measurable spaces. -/ diff --git a/Mathlib/ModelTheory/Algebra/Ring/Basic.lean b/Mathlib/ModelTheory/Algebra/Ring/Basic.lean index c2c75e666e4b2..3def47d594af0 100644 --- a/Mathlib/ModelTheory/Algebra/Ring/Basic.lean +++ b/Mathlib/ModelTheory/Algebra/Ring/Basic.lean @@ -237,7 +237,7 @@ def languageEquivEquivRingEquiv {R S : Type*} [NonAssocRing R] [NonAssocRing S] [CompatibleRing R] [CompatibleRing S] : (Language.ring.Equiv R S) ≃ (R ≃+* S) := - { toFun := fun f => + { toFun f := { f with map_add' := by intro x y @@ -245,13 +245,13 @@ def languageEquivEquivRingEquiv {R S : Type*} map_mul' := by intro x y simpa using f.map_fun mulFunc ![x, y] } - invFun := fun f => + invFun f := { f with map_fun' := fun {n} f => by cases f <;> simp map_rel' := fun {n} f => by cases f }, - left_inv := fun f => by ext; rfl - right_inv := fun f => by ext; rfl } + left_inv f := rfl + right_inv f := rfl } variable (R : Type*) [Language.ring.Structure R] diff --git a/Mathlib/NumberTheory/Zsqrtd/Basic.lean b/Mathlib/NumberTheory/Zsqrtd/Basic.lean index 9d477daf4ffca..87f617b5528d4 100644 --- a/Mathlib/NumberTheory/Zsqrtd/Basic.lean +++ b/Mathlib/NumberTheory/Zsqrtd/Basic.lean @@ -927,9 +927,7 @@ def lift {d : ℤ} : { r : R // r * r = ↑d } ≃ (ℤ√d →+* R) where simp only [mul_re, Int.cast_add, Int.cast_mul, mul_im, this, r.prop] ring } invFun f := ⟨f sqrtd, by rw [← f.map_mul, dmuld, map_intCast]⟩ - left_inv r := by - ext - simp + left_inv r := by simp right_inv f := by ext simp diff --git a/Mathlib/RingTheory/Derivation/Basic.lean b/Mathlib/RingTheory/Derivation/Basic.lean index 5b01844f39b40..f530128d4efbe 100644 --- a/Mathlib/RingTheory/Derivation/Basic.lean +++ b/Mathlib/RingTheory/Derivation/Basic.lean @@ -137,7 +137,7 @@ theorem leibniz_pow (n : ℕ) : D (a ^ n) = n • a ^ (n - 1) • D a := by induction' n with n ihn · rw [pow_zero, map_one_eq_zero, zero_smul] · rcases (zero_le n).eq_or_lt with (rfl | hpos) - · erw [pow_one, one_smul, pow_zero, one_smul] + · simp · have : a * a ^ (n - 1) = a ^ n := by rw [← pow_succ', Nat.sub_add_cancel hpos] simp only [pow_succ', leibniz, ihn, smul_comm a n (_ : M), smul_smul a, add_smul, this, Nat.succ_eq_add_one, Nat.add_succ_sub_one, add_zero, one_nsmul] diff --git a/Mathlib/RingTheory/HahnSeries/Addition.lean b/Mathlib/RingTheory/HahnSeries/Addition.lean index 817b97d65f6d7..01acbffb87646 100644 --- a/Mathlib/RingTheory/HahnSeries/Addition.lean +++ b/Mathlib/RingTheory/HahnSeries/Addition.lean @@ -83,10 +83,9 @@ and the additive opposite of Hahn series over `Γ` with coefficients `R`. def addOppositeEquiv : HahnSeries Γ (Rᵃᵒᵖ) ≃+ (HahnSeries Γ R)ᵃᵒᵖ where toFun x := .op ⟨fun a ↦ (x.coeff a).unop, by convert x.isPWO_support; ext; simp⟩ invFun x := ⟨fun a ↦ .op (x.unop.coeff a), by convert x.unop.isPWO_support; ext; simp⟩ - left_inv x := by ext; simp + left_inv x := by simp right_inv x := by apply AddOpposite.unop_injective - ext simp map_add' x y := by apply AddOpposite.unop_injective diff --git a/Mathlib/RingTheory/Ideal/Basis.lean b/Mathlib/RingTheory/Ideal/Basis.lean index ac26138204089..0639ab56e0dd4 100644 --- a/Mathlib/RingTheory/Ideal/Basis.lean +++ b/Mathlib/RingTheory/Ideal/Basis.lean @@ -39,8 +39,7 @@ theorem basisSpanSingleton_apply (b : Basis ι R S) {x : S} (hx : x ≠ 0) (i : theorem constr_basisSpanSingleton {N : Type*} [Semiring N] [Module N S] [SMulCommClass R N S] (b : Basis ι R S) {x : S} (hx : x ≠ 0) : (b.constr N).toFun (((↑) : _ → S) ∘ (basisSpanSingleton b hx)) = Algebra.lmul R S x := - b.ext fun i => by - erw [Basis.constr_basis, Function.comp_apply, basisSpanSingleton_apply, LinearMap.mul_apply'] + b.ext fun i => by simp end Ideal diff --git a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean index 79c48f487358b..db25c94c9b3af 100644 --- a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean +++ b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean @@ -206,10 +206,7 @@ def Hom.sub (f g : Hom P P') : P.CotangentSpace →ₗ[S] P'.Cotangent := by map_one_eq_zero' := ?_ leibniz' := ?_ } · ext - simp only [LinearMap.coe_comp, LinearMap.coe_restrictScalars, Function.comp_apply, - Cotangent.val_mk, Cotangent.val_zero, Ideal.toCotangent_eq_zero] - erw [LinearMap.codRestrict_apply] - simp only [LinearMap.sub_apply, AlgHom.toLinearMap_apply, map_one, sub_self, Submodule.zero_mem] + simp [Ideal.toCotangent_eq_zero] · intro x y ext simp only [LinearMap.coe_comp, LinearMap.coe_restrictScalars, Function.comp_apply, diff --git a/Mathlib/RingTheory/Localization/Away/Basic.lean b/Mathlib/RingTheory/Localization/Away/Basic.lean index 97d2e44e131c1..d6ca20ff422c7 100644 --- a/Mathlib/RingTheory/Localization/Away/Basic.lean +++ b/Mathlib/RingTheory/Localization/Away/Basic.lean @@ -195,7 +195,6 @@ noncomputable def mapₐ (f : A →ₐ[R] B) (a : A) [Away a Aₚ] [Away (f a) B ⟨map Aₚ Bₚ f.toRingHom a, fun r ↦ by dsimp only [AlgHom.toRingHom_eq_coe, map, RingHom.coe_coe, OneHom.toFun_eq_coe] rw [IsScalarTower.algebraMap_apply R A Aₚ, IsScalarTower.algebraMap_eq R B Bₚ] - erw [IsLocalization.map_eq] simp⟩ @[simp] diff --git a/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean b/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean index e62e6489c8c9e..9e88d03fbe726 100644 --- a/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean +++ b/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean @@ -67,11 +67,8 @@ theorem polynomial_comp_attachBound (A : Subalgebra ℝ C(X, ℝ)) (f : A) (g : (g.toContinuousMapOn (Set.Icc (-‖f‖) ‖f‖)).comp (f : C(X, ℝ)).attachBound = Polynomial.aeval f g := by ext - simp only [ContinuousMap.coe_comp, Function.comp_apply, ContinuousMap.attachBound_apply_coe, - Polynomial.toContinuousMapOn_apply, Polynomial.aeval_subalgebra_coe, - Polynomial.aeval_continuousMap_apply, Polynomial.toContinuousMap_apply] - -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [ContinuousMap.attachBound_apply_coe] + simp only [Polynomial.aeval_subalgebra_coe, Polynomial.aeval_continuousMap_apply] + simp /-- Given a continuous function `f` in a subalgebra of `C(X, ℝ)`, postcomposing by a polynomial gives another function in `A`. From ac937eec045611309313571a5cc8e2b011ae8e22 Mon Sep 17 00:00:00 2001 From: Vasily Nesterov Date: Mon, 6 Jan 2025 22:50:53 +0000 Subject: [PATCH 023/681] =?UTF-8?q?feat(Analysis):=20asymptotics=20of=20in?= =?UTF-8?q?version=20at=20`atBot`=20and=20`=F0=9D=93=9D[<]=200`=20(#19817)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prove some lemmas about the inversion function's asymptotics at `atBot` and `𝓝[<] 0` filters, analogous to the existing API for `atTop` and `𝓝[>] 0` --- .../Order/Group/Pointwise/Interval.lean | 17 ++++++--- Mathlib/Topology/Algebra/Order/Field.lean | 35 +++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean b/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean index fb5b4cae02b8a..8a43aa8f926fc 100644 --- a/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean +++ b/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean @@ -778,15 +778,22 @@ theorem image_mul_left_Ioc {a : α} (h : 0 < a) (b c : α) : /-- The (pre)image under `inv` of `Ioo 0 a` is `Ioi a⁻¹`. -/ theorem inv_Ioo_0_left {a : α} (ha : 0 < a) : (Ioo 0 a)⁻¹ = Ioi a⁻¹ := by ext x - exact - ⟨fun h => inv_inv x ▸ (inv_lt_inv₀ ha h.1).2 h.2, fun h => - ⟨inv_pos.2 <| (inv_pos.2 ha).trans h, - inv_inv a ▸ (inv_lt_inv₀ ((inv_pos.2 ha).trans h) - (inv_pos.2 ha)).2 h⟩⟩ + exact ⟨fun h ↦ inv_lt_of_inv_lt₀ (inv_pos.1 h.1) h.2, + fun h ↦ ⟨inv_pos.2 <| (inv_pos.2 ha).trans h, inv_lt_of_inv_lt₀ ha h⟩⟩ + +/-- The (pre)image under `inv` of `Ioo a 0` is `Iio a⁻¹`. -/ +theorem inv_Ioo_0_right {a : α} (ha : a < 0) : (Ioo a 0)⁻¹ = Iio a⁻¹ := by + ext x + refine ⟨fun h ↦ (lt_inv_of_neg (inv_neg''.1 h.2) ha).2 h.1, fun h ↦ ?_⟩ + have h' := (h.trans (inv_neg''.2 ha)) + exact ⟨(lt_inv_of_neg ha h').2 h, inv_neg''.2 h'⟩ theorem inv_Ioi₀ {a : α} (ha : 0 < a) : (Ioi a)⁻¹ = Ioo 0 a⁻¹ := by rw [inv_eq_iff_eq_inv, inv_Ioo_0_left (inv_pos.2 ha), inv_inv] +theorem inv_Iio₀ {a : α} (ha : a < 0) : (Iio a)⁻¹ = Ioo a⁻¹ 0 := by + rw [inv_eq_iff_eq_inv, inv_Ioo_0_right (inv_neg''.2 ha), inv_inv] + theorem image_const_mul_Ioi_zero {k : Type*} [LinearOrderedField k] {x : k} (hx : 0 < x) : (fun y => x * y) '' Ioi (0 : k) = Ioi 0 := by erw [(Units.mk0 x hx.ne').mulLeft.image_eq_preimage, diff --git a/Mathlib/Topology/Algebra/Order/Field.lean b/Mathlib/Topology/Algebra/Order/Field.lean index 8bb48fa820d3e..4faff225f1e90 100644 --- a/Mathlib/Topology/Algebra/Order/Field.lean +++ b/Mathlib/Topology/Algebra/Order/Field.lean @@ -116,11 +116,20 @@ lemma inv_atTop₀ : (atTop : Filter 𝕜)⁻¹ = 𝓝[>] 0 := (((atTop_basis_Ioi' (0 : 𝕜)).map _).comp_surjective inv_surjective).eq_of_same_basis <| (nhdsGT_basis _).congr (by simp) fun a ha ↦ by simp [inv_Ioi₀ (inv_pos.2 ha)] +@[simp] +lemma inv_atBot₀ : (atBot : Filter 𝕜)⁻¹ = 𝓝[<] 0 := + (((atBot_basis_Iio' (0 : 𝕜)).map _).comp_surjective inv_surjective).eq_of_same_basis <| + (nhdsLT_basis _).congr (by simp) fun a ha ↦ by simp [inv_Iio₀ (inv_neg''.2 ha)] + @[simp] lemma inv_nhdsGT_zero : (𝓝[>] (0 : 𝕜))⁻¹ = atTop := by rw [← inv_atTop₀, inv_inv] @[deprecated (since := "2024-12-22")] alias inv_nhdsWithin_Ioi_zero := inv_nhdsGT_zero +@[simp] +lemma inv_nhdsLT_zero : (𝓝[<] (0 : 𝕜))⁻¹ = atBot := by + rw [← inv_atBot₀, inv_inv] + /-- The function `x ↦ x⁻¹` tends to `+∞` on the right of `0`. -/ theorem tendsto_inv_nhdsGT_zero : Tendsto (fun x : 𝕜 => x⁻¹) (𝓝[>] (0 : 𝕜)) atTop := inv_nhdsGT_zero.le @@ -138,24 +147,50 @@ alias tendsto_inv_atTop_zero' := tendsto_inv_atTop_nhdsGT_zero theorem tendsto_inv_atTop_zero : Tendsto (fun r : 𝕜 => r⁻¹) atTop (𝓝 0) := tendsto_inv_atTop_nhdsGT_zero.mono_right inf_le_left +/-- The function `x ↦ x⁻¹` tends to `-∞` on the left of `0`. -/ +theorem tendsto_inv_zero_atBot : Tendsto (fun x : 𝕜 => x⁻¹) (𝓝[<] (0 : 𝕜)) atBot := + inv_nhdsLT_zero.le + +/-- The function `r ↦ r⁻¹` tends to `0` on the left as `r → -∞`. -/ +theorem tendsto_inv_atBot_zero' : Tendsto (fun r : 𝕜 => r⁻¹) atBot (𝓝[<] (0 : 𝕜)) := + inv_atBot₀.le + +theorem tendsto_inv_atBot_zero : Tendsto (fun r : 𝕜 => r⁻¹) atBot (𝓝 0) := + tendsto_inv_atBot_zero'.mono_right inf_le_left + theorem Filter.Tendsto.div_atTop {a : 𝕜} (h : Tendsto f l (𝓝 a)) (hg : Tendsto g l atTop) : Tendsto (fun x => f x / g x) l (𝓝 0) := by simp only [div_eq_mul_inv] exact mul_zero a ▸ h.mul (tendsto_inv_atTop_zero.comp hg) +theorem Filter.Tendsto.div_atBot {a : 𝕜} (h : Tendsto f l (𝓝 a)) (hg : Tendsto g l atBot) : + Tendsto (fun x => f x / g x) l (𝓝 0) := by + simp only [div_eq_mul_inv] + exact mul_zero a ▸ h.mul (tendsto_inv_atBot_zero.comp hg) + lemma Filter.Tendsto.const_div_atTop (hg : Tendsto g l atTop) (r : 𝕜) : Tendsto (fun n ↦ r / g n) l (𝓝 0) := tendsto_const_nhds.div_atTop hg +lemma Filter.Tendsto.const_div_atBot (hg : Tendsto g l atBot) (r : 𝕜) : + Tendsto (fun n ↦ r / g n) l (𝓝 0) := + tendsto_const_nhds.div_atBot hg + theorem Filter.Tendsto.inv_tendsto_atTop (h : Tendsto f l atTop) : Tendsto f⁻¹ l (𝓝 0) := tendsto_inv_atTop_zero.comp h +theorem Filter.Tendsto.inv_tendsto_atBot (h : Tendsto f l atBot) : Tendsto f⁻¹ l (𝓝 0) := + tendsto_inv_atBot_zero.comp h + theorem Filter.Tendsto.inv_tendsto_nhdsGT_zero (h : Tendsto f l (𝓝[>] 0)) : Tendsto f⁻¹ l atTop := tendsto_inv_nhdsGT_zero.comp h @[deprecated (since := "2024-12-22")] alias Filter.Tendsto.inv_tendsto_zero := Filter.Tendsto.inv_tendsto_nhdsGT_zero +theorem Filter.Tendsto.inv_tendsto_nhdsLT_zero (h : Tendsto f l (𝓝[<] 0)) : Tendsto f⁻¹ l atBot := + tendsto_inv_zero_atBot.comp h + /-- If `g` tends to zero and there exists a constant `C : 𝕜` such that eventually `|f x| ≤ C`, then the product `f * g` tends to zero. -/ theorem bdd_le_mul_tendsto_zero' {f g : α → 𝕜} (C : 𝕜) (hf : ∀ᶠ x in l, |f x| ≤ C) From 2f1f7b9c5ff87506a38b2ead588636117fe9a13c Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Mon, 6 Jan 2025 22:50:54 +0000 Subject: [PATCH 024/681] feat: add @[simp] lemma Prod.norm_mk (#20411) --- Mathlib/Analysis/Normed/Group/Constructions.lean | 14 ++++++++++++-- Mathlib/Analysis/Normed/Lp/ProdLp.lean | 2 +- .../Analysis/NormedSpace/Multilinear/Basic.lean | 2 +- .../NumberField/CanonicalEmbedding/Basic.lean | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Mathlib/Analysis/Normed/Group/Constructions.lean b/Mathlib/Analysis/Normed/Group/Constructions.lean index 95eb19382e965..5a2a7e261e62b 100644 --- a/Mathlib/Analysis/Normed/Group/Constructions.lean +++ b/Mathlib/Analysis/Normed/Group/Constructions.lean @@ -229,6 +229,8 @@ instance Prod.toNorm : Norm (E × F) where norm x := ‖x.1‖ ⊔ ‖x.2‖ lemma Prod.norm_def (x : E × F) : ‖x‖ = max ‖x.1‖ ‖x.2‖ := rfl +@[simp] lemma Prod.norm_mk (x : E) (y : F) : ‖(x, y)‖ = max ‖x‖ ‖y‖ := rfl + lemma norm_fst_le (x : E × F) : ‖x.1‖ ≤ ‖x‖ := le_max_left _ _ lemma norm_snd_le (x : E × F) : ‖x.2‖ ≤ ‖x‖ := le_max_right _ _ @@ -246,8 +248,16 @@ instance Prod.seminormedGroup : SeminormedGroup (E × F) where dist_eq x y := by simp only [Prod.norm_def, Prod.dist_eq, dist_eq_norm_div, Prod.fst_div, Prod.snd_div] -@[to_additive Prod.nnnorm_def'] -lemma Prod.nnorm_def (x : E × F) : ‖x‖₊ = max ‖x.1‖₊ ‖x.2‖₊ := rfl +/-- Multiplicative version of `Prod.nnnorm_def`. +Earlier, this names was used for the additive version. -/ +@[to_additive Prod.nnnorm_def] +lemma Prod.nnnorm_def' (x : E × F) : ‖x‖₊ = max ‖x.1‖₊ ‖x.2‖₊ := rfl + +@[deprecated (since := "2025-01-02")] alias Prod.nnorm_def := Prod.nnnorm_def' + +/-- Multiplicative version of `Prod.nnnorm_mk`. -/ +@[to_additive (attr := simp) Prod.nnnorm_mk] +lemma Prod.nnnorm_mk' (x : E) (y : F) : ‖(x, y)‖₊ = max ‖x‖₊ ‖y‖₊ := rfl end SeminormedGroup diff --git a/Mathlib/Analysis/Normed/Lp/ProdLp.lean b/Mathlib/Analysis/Normed/Lp/ProdLp.lean index d94faf96a1d7e..be6e704e2ad40 100644 --- a/Mathlib/Analysis/Normed/Lp/ProdLp.lean +++ b/Mathlib/Analysis/Normed/Lp/ProdLp.lean @@ -616,7 +616,7 @@ theorem prod_nnnorm_eq_sup (f : WithLp ∞ (α × β)) : ‖f‖₊ = ‖f.fst norm_cast @[simp] theorem prod_nnnorm_equiv (f : WithLp ∞ (α × β)) : ‖WithLp.equiv ⊤ _ f‖₊ = ‖f‖₊ := by - rw [prod_nnnorm_eq_sup, Prod.nnnorm_def', equiv_fst, equiv_snd] + rw [prod_nnnorm_eq_sup, Prod.nnnorm_def, equiv_fst, equiv_snd] @[simp] theorem prod_nnnorm_equiv_symm (f : α × β) : ‖(WithLp.equiv ⊤ _).symm f‖₊ = ‖f‖₊ := (prod_nnnorm_equiv _).symm diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index c6c4a0ad92ef2..d7bef54d16d58 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -535,7 +535,7 @@ theorem isLeast_opNNNorm (f : ContinuousMultilinearMap 𝕜 E G) : theorem opNNNorm_prod (f : ContinuousMultilinearMap 𝕜 E G) (g : ContinuousMultilinearMap 𝕜 E G') : ‖f.prod g‖₊ = max ‖f‖₊ ‖g‖₊ := eq_of_forall_ge_iff fun _ ↦ by - simp only [opNNNorm_le_iff, prod_apply, Prod.nnnorm_def', max_le_iff, forall_and] + simp only [opNNNorm_le_iff, prod_apply, Prod.nnnorm_def, max_le_iff, forall_and] theorem opNorm_prod (f : ContinuousMultilinearMap 𝕜 E G) (g : ContinuousMultilinearMap 𝕜 E G') : ‖f.prod g‖ = max ‖f‖ ‖g‖ := diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean index 3b10a1368dea7..4101379ae8266 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean @@ -388,7 +388,7 @@ theorem nnnorm_eq_sup_normAtPlace (x : mixedSpace K) : (univ.image (fun w : {w : InfinitePlace K // IsComplex w} ↦ w.1)) := by ext; simp [isReal_or_isComplex] rw [this, sup_union, univ.sup_image, univ.sup_image, - Prod.nnnorm_def', Pi.nnnorm_def, Pi.nnnorm_def] + Prod.nnnorm_def, Pi.nnnorm_def, Pi.nnnorm_def] congr · ext w simp [normAtPlace_apply_isReal w.prop] From d4a7b67c52e526f04082b832d2f3d298b17bd29e Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Mon, 6 Jan 2025 23:14:21 +0000 Subject: [PATCH 025/681] chore: to_additive various results on groups, group actions (#20498) --- Mathlib/GroupTheory/GroupAction/Basic.lean | 9 +++ Mathlib/GroupTheory/GroupAction/Blocks.lean | 79 +++++++++++++++++-- .../GroupTheory/GroupAction/Pointwise.lean | 14 +++- .../GroupTheory/GroupAction/SubMulAction.lean | 56 +++++++++++-- Mathlib/GroupTheory/Index.lean | 4 +- 5 files changed, 145 insertions(+), 17 deletions(-) diff --git a/Mathlib/GroupTheory/GroupAction/Basic.lean b/Mathlib/GroupTheory/GroupAction/Basic.lean index 552dee07b3bcd..520ead2860814 100644 --- a/Mathlib/GroupTheory/GroupAction/Basic.lean +++ b/Mathlib/GroupTheory/GroupAction/Basic.lean @@ -17,6 +17,13 @@ This file primarily concerns itself with orbits, stabilizers, and other objects actions. Despite this file being called `basic`, low-level helper lemmas for algebraic manipulation of `•` belong elsewhere. +## Main definitions + +* `MulAction.orbit` +* `MulAction.fixedPoints` +* `MulAction.fixedBy` +* `MulAction.stabilizer` + -/ @@ -266,6 +273,8 @@ namespace MulAction variable {G : Type*} [Group G] {α : Type*} [MulAction G α] /-- To prove inclusion of a *subgroup* in a stabilizer, it is enough to prove inclusions.-/ +@[to_additive + "To prove inclusion of a *subgroup* in a stabilizer, it is enough to prove inclusions."] theorem le_stabilizer_iff_smul_le (s : Set α) (H : Subgroup G) : H ≤ stabilizer G s ↔ ∀ g ∈ H, g • s ⊆ s := by constructor diff --git a/Mathlib/GroupTheory/GroupAction/Blocks.lean b/Mathlib/GroupTheory/GroupAction/Blocks.lean index bb890e738c69d..59f18a034ab8f 100644 --- a/Mathlib/GroupTheory/GroupAction/Blocks.lean +++ b/Mathlib/GroupTheory/GroupAction/Blocks.lean @@ -16,6 +16,8 @@ Given `SMul G X`, an action of a type `G` on a type `X`, we define - the predicate `IsBlock G B` states that `B : Set X` is a block, which means that the sets `g • B`, for `g ∈ G`, are equal or disjoint. + Under `Group G` and `MulAction G X`, this is equivalent to the classical + definition `MulAction.IsBlock.def_one` - a bunch of lemmas that give examples of “trivial” blocks : ⊥, ⊤, singletons, and non trivial blocks: orbit of the group, orbit of a normal subgroup… @@ -25,14 +27,14 @@ The non-existence of nontrivial blocks is the definition of primitive actions. ## Results for actions on finite sets - `IsBlock.ncard_block_mul_ncard_orbit_eq` : The cardinality of a block -multiplied by the number of its translates is the cardinal of the ambient type + multiplied by the number of its translates is the cardinal of the ambient type - `IsBlock.eq_univ_of_card_lt` : a too large block is equal to `Set.univ` - `IsBlock.subsingleton_of_card_lt` : a too small block is a subsingleton - `IsBlock.of_subset` : the intersections of the translates of a finite subset -that contain a given point is a block + that contain a given point is a block ## References @@ -63,7 +65,7 @@ theorem orbit.pairwiseDisjoint : exact (orbit.eq_or_disjoint x y).resolve_right h /-- Orbits of an element form a partition -/ -@[to_additive] +@[to_additive "Orbits of an element of a partition"] theorem IsPartition.of_orbits : Setoid.IsPartition (Set.range fun a : X => orbit G a) := by apply orbit.pairwiseDisjoint.isPartition_of_exists_of_ne_empty @@ -143,8 +145,11 @@ lemma IsBlock.disjoint_smul_set_smul (hB : IsBlock G B) (hgs : ¬ g • B ⊆ s lemma IsBlock.disjoint_smul_smul_set (hB : IsBlock G B) (hgs : ¬ g • B ⊆ s • B) : Disjoint (s • B) (g • B) := (hB.disjoint_smul_set_smul hgs).symm +@[to_additive] alias ⟨IsBlock.smul_eq_smul_of_nonempty, _⟩ := isBlock_iff_smul_eq_smul_of_nonempty +@[to_additive] alias ⟨IsBlock.pairwiseDisjoint_range_smul, _⟩ := isBlock_iff_pairwiseDisjoint_range_smul +@[to_additive] alias ⟨IsBlock.smul_eq_smul_or_disjoint, _⟩ := isBlock_iff_smul_eq_smul_or_disjoint /-- A fixed block is a block. -/ @@ -277,6 +282,7 @@ protected lemma IsBlock.orbit (a : X) : IsBlock G (orbit G a) := (IsFixedBlock.o lemma isBlock_top : IsBlock (⊤ : Subgroup G) B ↔ IsBlock G B := Subgroup.topEquiv.toEquiv.forall_congr fun _ ↦ Subgroup.topEquiv.toEquiv.forall_congr_left +@[to_additive] lemma IsBlock.preimage {H Y : Type*} [Group H] [MulAction H Y] {φ : H → G} (j : Y →ₑ[φ] X) (hB : IsBlock G B) : IsBlock H (j ⁻¹' B) := by @@ -284,6 +290,7 @@ lemma IsBlock.preimage {H Y : Type*} [Group H] [MulAction H Y] rw [← Group.preimage_smul_setₛₗ, ← Group.preimage_smul_setₛₗ] at hg ⊢ exact (hB <| ne_of_apply_ne _ hg).preimage _ +@[to_additive] theorem IsBlock.image {H Y : Type*} [Group H] [MulAction H Y] {φ : G →* H} (j : X →ₑ[φ] Y) (hφ : Function.Surjective φ) (hj : Function.Injective j) @@ -292,18 +299,40 @@ theorem IsBlock.image {H Y : Type*} [Group H] [MulAction H Y] simp only [IsBlock, hφ.forall, ← image_smul_setₛₗ] exact fun g₁ g₂ hg ↦ disjoint_image_of_injective hj <| hB <| ne_of_apply_ne _ hg +@[to_additive] theorem IsBlock.subtype_val_preimage {C : SubMulAction G X} (hB : IsBlock G B) : IsBlock G (Subtype.val ⁻¹' B : Set C) := hB.preimage C.inclusion +@[to_additive] theorem isBlock_subtypeVal {C : SubMulAction G X} {B : Set C} : IsBlock G (Subtype.val '' B : Set X) ↔ IsBlock G B := by refine forall₂_congr fun g₁ g₂ ↦ ?_ rw [← SubMulAction.inclusion.coe_eq, ← image_smul_set, ← image_smul_set, ne_eq, Set.image_eq_image C.inclusion_injective, disjoint_image_iff C.inclusion_injective] +theorem _root_.AddAction.IsBlock.of_addsubgroup_of_conjugate + {G : Type*} [AddGroup G] {X : Type*} [AddAction G X] {B : Set X} + {H : AddSubgroup G} (hB : AddAction.IsBlock H B) (g : G) : + AddAction.IsBlock (H.map (AddAut.conj g).toAddMonoidHom) (g +ᵥ B) := by + rw [AddAction.isBlock_iff_vadd_eq_or_disjoint] + intro h' + obtain ⟨h, hH, hh⟩ := AddSubgroup.mem_map.mp (SetLike.coe_mem h') + simp only [AddEquiv.coe_toAddMonoidHom, AddAut.conj_apply] at hh + suffices h' +ᵥ (g +ᵥ B) = g +ᵥ (h +ᵥ B) by + simp only [this] + apply (hB.vadd_eq_or_disjoint ⟨h, hH⟩).imp + · intro hB'; congr + · exact Set.disjoint_image_of_injective (AddAction.injective g) + suffices (h' : G) +ᵥ (g +ᵥ B) = g +ᵥ (h +ᵥ B) by + exact this + rw [← hh, vadd_vadd, vadd_vadd] + erw [AddAut.conj_apply] + simp + +@[to_additive existing AddAction.IsBlock.of_addsubgroup_of_conjugate] theorem IsBlock.of_subgroup_of_conjugate {H : Subgroup G} (hB : IsBlock H B) (g : G) : - IsBlock (Subgroup.map (MulEquiv.toMonoidHom (MulAut.conj g)) H) (g • B) := by + IsBlock (H.map (MulAut.conj g).toMonoidHom) (g • B) := by rw [isBlock_iff_smul_eq_or_disjoint] intro h' obtain ⟨h, hH, hh⟩ := Subgroup.mem_map.mp (SetLike.coe_mem h') @@ -318,6 +347,18 @@ theorem IsBlock.of_subgroup_of_conjugate {H : Subgroup G} (hB : IsBlock H B) (g rw [← hh, smul_smul (g * h * g⁻¹) g B, smul_smul g h B, inv_mul_cancel_right] /-- A translate of a block is a block -/ +theorem _root_.AddAction.IsBlock.translate + {G : Type*} [AddGroup G] {X : Type*} [AddAction G X] (B : Set X) + (g : G) (hB : AddAction.IsBlock G B) : + AddAction.IsBlock G (g +ᵥ B) := by + rw [← AddAction.isBlock_top] at hB ⊢ + rw [← AddSubgroup.map_comap_eq_self_of_surjective (G := G) ?_ ⊤] + · apply AddAction.IsBlock.of_addsubgroup_of_conjugate + rwa [AddSubgroup.comap_top] + · exact (AddAut.conj g).surjective + +/-- A translate of a block is a block -/ +@[to_additive existing] theorem IsBlock.translate (g : G) (hB : IsBlock G B) : IsBlock G (g • B) := by rw [← isBlock_top] at hB ⊢ @@ -329,9 +370,12 @@ theorem IsBlock.translate (g : G) (hB : IsBlock G B) : variable (G) in /-- For `SMul G X`, a block system of `X` is a partition of `X` into blocks for the action of `G` -/ +@[to_additive "For `VAdd G X`, a block system of `X` is a partition of `X` into blocks + for the additive action of `G`"] def IsBlockSystem (ℬ : Set (Set X)) := Setoid.IsPartition ℬ ∧ ∀ ⦃B⦄, B ∈ ℬ → IsBlock G B -/-- Translates of a block form a block system. -/ +/-- Translates of a block form a block system -/ +@[to_additive "Translates of a block form a block system"] theorem IsBlock.isBlockSystem [hGX : MulAction.IsPretransitive G X] (hB : IsBlock G B) (hBe : B.Nonempty) : IsBlockSystem G (Set.range fun g : G => g • B) := by @@ -352,6 +396,7 @@ theorem IsBlock.isBlockSystem [hGX : MulAction.IsPretransitive G X] section Normal +@[to_additive] lemma smul_orbit_eq_orbit_smul (N : Subgroup G) [nN : N.Normal] (a : X) (g : G) : g • orbit N a = orbit N (g • a) := by simp only [orbit, Set.image_smul, Set.smul_set_range] @@ -368,6 +413,7 @@ lemma smul_orbit_eq_orbit_smul (N : Subgroup G) [nN : N.Normal] (a : X) (g : G) simp only [← mul_assoc, ← smul_smul, smul_inv_smul, inv_inv] /-- An orbit of a normal subgroup is a block -/ +@[to_additive "An orbit of a normal subgroup is a block"] theorem IsBlock.orbit_of_normal {N : Subgroup G} [N.Normal] (a : X) : IsBlock G (orbit N a) := by rw [isBlock_iff_smul_eq_or_disjoint] @@ -376,6 +422,7 @@ theorem IsBlock.orbit_of_normal {N : Subgroup G} [N.Normal] (a : X) : apply orbit.eq_or_disjoint /-- The orbits of a normal subgroup form a block system -/ +@[to_additive "The orbits of a normal subgroup form a block system"] theorem IsBlockSystem.of_normal {N : Subgroup G} [N.Normal] : IsBlockSystem G (Set.range fun a : X => orbit N a) := by constructor @@ -436,6 +483,7 @@ section Stabilizer (Wielandt, th. 7.5) -/ /-- The orbit of `a` under a subgroup containing the stabilizer of `a` is a block -/ +@[to_additive "The orbit of `a` under a subgroup containing the stabilizer of `a` is a block"] theorem IsBlock.of_orbit {H : Subgroup G} {a : X} (hH : stabilizer G a ≤ H) : IsBlock G (MulAction.orbit H a) := by rw [isBlock_iff_smul_eq_of_nonempty] @@ -447,11 +495,14 @@ theorem IsBlock.of_orbit {H : Subgroup G} {a : X} (hH : stabilizer G a ≤ H) : simpa only [mem_stabilizer_iff, InvMemClass.coe_inv, mul_smul, inv_smul_eq_iff] /-- If `B` is a block containing `a`, then the stabilizer of `B` contains the stabilizer of `a` -/ +@[to_additive + "If `B` is a block containing `a`, then the stabilizer of `B` contains the stabilizer of `a`"] theorem IsBlock.stabilizer_le (hB : IsBlock G B) {a : X} (ha : a ∈ B) : stabilizer G a ≤ stabilizer G B := fun g hg ↦ hB.smul_eq_of_nonempty ⟨a, by rwa [← hg, smul_mem_smul_set_iff], ha⟩ /-- A block containing `a` is the orbit of `a` under its stabilizer -/ +@[to_additive "A block containing `a` is the orbit of `a` under its stabilizer"] theorem IsBlock.orbit_stabilizer_eq [IsPretransitive G X] (hB : IsBlock G B) {a : X} (ha : a ∈ B) : MulAction.orbit (stabilizer G B) a = B := by ext x @@ -466,6 +517,9 @@ theorem IsBlock.orbit_stabilizer_eq [IsPretransitive G X] (hB : IsBlock G B) {a /-- A subgroup containing the stabilizer of `a` is the stabilizer of the orbit of `a` under that subgroup -/ +@[to_additive + "A subgroup containing the stabilizer of `a` + is the stabilizer of the orbit of `a` under that subgroup"] theorem stabilizer_orbit_eq {a : X} {H : Subgroup G} (hH : stabilizer G a ≤ H) : stabilizer G (orbit H a) = H := by ext g @@ -482,6 +536,9 @@ variable (G) /-- Order equivalence between blocks in `X` containing a point `a` and subgroups of `G` containing the stabilizer of `a` (Wielandt, th. 7.5)-/ +@[to_additive + "Order equivalence between blocks in `X` containing a point `a` + and subgroups of `G` containing the stabilizer of `a` (Wielandt, th. 7.5)"] def block_stabilizerOrderIso [htGX : IsPretransitive G X] (a : X) : { B : Set X // a ∈ B ∧ IsBlock G B } ≃o Set.Ici (stabilizer G a) where toFun := fun ⟨B, ha, hB⟩ => ⟨stabilizer G B, hB.stabilizer_le ha⟩ @@ -512,6 +569,7 @@ namespace IsBlock variable [IsPretransitive G X] {B : Set X} +@[to_additive] theorem ncard_block_eq_relindex (hB : IsBlock G B) {x : X} (hx : x ∈ B) : B.ncard = (stabilizer G x).relindex (stabilizer G B) := by have key : (stabilizer G x).subgroupOf (stabilizer G B) = stabilizer (stabilizer G B) x := by @@ -520,6 +578,9 @@ theorem ncard_block_eq_relindex (hB : IsBlock G B) {x : X} (hx : x ∈ B) : /-- The cardinality of the ambient space is the product of the cardinality of a block by the cardinality of the set of translates of that block -/ +@[to_additive + "The cardinality of the ambient space is the product of the cardinality of a block + by the cardinality of the set of translates of that block"] theorem ncard_block_mul_ncard_orbit_eq (hB : IsBlock G B) (hB_ne : B.Nonempty) : Set.ncard B * Set.ncard (orbit G B) = Nat.card X := by obtain ⟨x, hx⟩ := hB_ne @@ -527,11 +588,13 @@ theorem ncard_block_mul_ncard_orbit_eq (hB : IsBlock G B) (hB_ne : B.Nonempty) : Subgroup.relindex_mul_index (hB.stabilizer_le hx), index_stabilizer_of_transitive] /-- The cardinality of a block divides the cardinality of the ambient type -/ +@[to_additive "The cardinality of a block divides the cardinality of the ambient type"] theorem ncard_dvd_card (hB : IsBlock G B) (hB_ne : B.Nonempty) : Set.ncard B ∣ Nat.card X := Dvd.intro _ (hB.ncard_block_mul_ncard_orbit_eq hB_ne) /-- A too large block is equal to `univ` -/ +@[to_additive "A too large block is equal to `univ`"] theorem eq_univ_of_card_lt [hX : Finite X] (hB : IsBlock G B) (hB' : Nat.card X < Set.ncard B * 2) : B = Set.univ := by rcases Set.eq_empty_or_nonempty B with rfl | hB_ne @@ -547,6 +610,7 @@ theorem eq_univ_of_card_lt [hX : Finite X] (hB : IsBlock G B) (hB' : Nat.card X @[deprecated (since := "2024-10-29")] alias eq_univ_card_lt := eq_univ_of_card_lt /-- If a block has too many translates, then it is a (sub)singleton -/ +@[to_additive "If a block has too many translates, then it is a (sub)singleton"] theorem subsingleton_of_card_lt [Finite X] (hB : IsBlock G B) (hB' : Nat.card X < 2 * Set.ncard (orbit G B)) : B.Subsingleton := by @@ -568,7 +632,10 @@ theorem subsingleton_of_card_lt [Finite X] (hB : IsBlock G B) are just `k + ℕ`, for `k ≤ 0`, and the corresponding intersection is `ℕ`, which is not a block. (Remark by Thomas Browning) -/ /-- The intersection of the translates of a *finite* subset which contain a given point -is a block (Wielandt, th. 7.3 )-/ +is a block (Wielandt, th. 7.3)-/ +@[to_additive + "The intersection of the translates of a *finite* subset which contain a given point + is a block (Wielandt, th. 7.3)"] theorem of_subset (a : X) (hfB : B.Finite) : IsBlock G (⋂ (k : G) (_ : a ∈ k • B), k • B) := by let B' := ⋂ (k : G) (_ : a ∈ k • B), k • B diff --git a/Mathlib/GroupTheory/GroupAction/Pointwise.lean b/Mathlib/GroupTheory/GroupAction/Pointwise.lean index 3b3918cc93570..291344f1d949b 100644 --- a/Mathlib/GroupTheory/GroupAction/Pointwise.lean +++ b/Mathlib/GroupTheory/GroupAction/Pointwise.lean @@ -29,6 +29,7 @@ import Mathlib.GroupTheory.GroupAction.Hom open Set Pointwise +@[to_additive] theorem MulAction.smul_bijective_of_is_unit {M : Type*} [Monoid M] {α : Type*} [MulAction M α] {m : M} (hm : IsUnit m) : Function.Bijective (fun (a : α) ↦ m • a) := by @@ -54,11 +55,13 @@ variable [FunLike F M N] [MulActionSemiHomClass F σ M N] -- "Left-hand side does not simplify, when using the simp lemma on itself." -- For now we will have to manually add `image_smul_setₛₗ _` to the `simp` argument list. -- TODO: when https://github.com/leanprover/lean4/issues/3107 is fixed, mark this as `@[simp]`. +@[to_additive] theorem image_smul_setₛₗ : h '' (c • s) = σ c • h '' s := by simp only [← image_smul, image_image, map_smulₛₗ h] /-- Translation of preimage is contained in preimage of translation -/ +@[to_additive] theorem smul_preimage_set_leₛₗ : c • h ⁻¹' t ⊆ h ⁻¹' (σ c • t) := by rintro x ⟨y, hy, rfl⟩ @@ -67,6 +70,7 @@ theorem smul_preimage_set_leₛₗ : variable {c} /-- General version of `preimage_smul_setₛₗ` -/ +@[to_additive] theorem preimage_smul_setₛₗ' (hc : Function.Surjective (fun (m : M) ↦ c • m)) (hc' : Function.Injective (fun (n : N) ↦ σ c • n)) : @@ -82,6 +86,7 @@ theorem preimage_smul_setₛₗ' · exact smul_preimage_set_leₛₗ M N σ h c t /-- `preimage_smul_setₛₗ` when both scalars act by unit -/ +@[to_additive] theorem preimage_smul_setₛₗ_of_units (hc : IsUnit c) (hc' : IsUnit (σ c)) : h ⁻¹' (σ c • t) = c • h ⁻¹' t := by apply preimage_smul_setₛₗ' @@ -90,6 +95,7 @@ theorem preimage_smul_setₛₗ_of_units (hc : IsUnit c) (hc' : IsUnit (σ c)) : /-- `preimage_smul_setₛₗ` in the context of a `MonoidHom` -/ +@[to_additive] theorem MonoidHom.preimage_smul_setₛₗ (σ : R →* S) {F : Type*} [FunLike F M N] [MulActionSemiHomClass F ⇑σ M N] (h : F) {c : R} (hc : IsUnit c) (t : Set N) : @@ -97,6 +103,7 @@ theorem MonoidHom.preimage_smul_setₛₗ (σ : R →* S) preimage_smul_setₛₗ_of_units M N σ h t hc (IsUnit.map σ hc) /-- `preimage_smul_setₛₗ` in the context of a `MonoidHomClass` -/ +@[to_additive] theorem preimage_smul_setₛₗ {G : Type*} [FunLike G R S] [MonoidHomClass G R S] (σ : G) {F : Type*} [FunLike F M N] [MulActionSemiHomClass F σ M N] (h : F) @@ -105,6 +112,7 @@ theorem preimage_smul_setₛₗ MonoidHom.preimage_smul_setₛₗ M N (σ : R →* S) h hc t /-- `preimage_smul_setₛₗ` in the context of a groups -/ +@[to_additive] theorem Group.preimage_smul_setₛₗ {R S : Type*} [Group R] [Group S] (σ : R → S) [MulAction R M] [MulAction S N] @@ -121,21 +129,25 @@ variable (R) variable [FunLike F M₁ M₂] [MulActionHomClass F R M₁ M₂] (c : R) (s : Set M₁) (t : Set M₂) -@[simp] -- This can be safely removed as a `@[simp]` lemma if `image_smul_setₛₗ` is readded. +-- This can be safely removed as a `@[simp]` lemma if `image_smul_setₛₗ` is readded. +@[to_additive (attr := simp)] theorem image_smul_set : h '' (c • s) = c • h '' s := image_smul_setₛₗ _ _ _ h c s +@[to_additive] theorem smul_preimage_set_le : c • h ⁻¹' t ⊆ h ⁻¹' (c • t) := smul_preimage_set_leₛₗ _ _ _ h c t variable {c} +@[to_additive] theorem preimage_smul_set (hc : IsUnit c) : h ⁻¹' (c • t) = c • h ⁻¹' t := preimage_smul_setₛₗ_of_units _ _ _ h t hc hc +@[to_additive] theorem Group.preimage_smul_set {R : Type*} [Group R] (M₁ M₂ : Type*) [MulAction R M₁] [MulAction R M₂] diff --git a/Mathlib/GroupTheory/GroupAction/SubMulAction.lean b/Mathlib/GroupTheory/GroupAction/SubMulAction.lean index babd428140d21..d8e3ff10ecc68 100644 --- a/Mathlib/GroupTheory/GroupAction/SubMulAction.lean +++ b/Mathlib/GroupTheory/GroupAction/SubMulAction.lean @@ -161,41 +161,57 @@ structure SubMulAction (R : Type u) (M : Type v) [SMul R M] : Type v where /-- The carrier set is closed under scalar multiplication. -/ smul_mem' : ∀ (c : R) {x : M}, x ∈ carrier → c • x ∈ carrier +/-- A SubAddAction is a set which is closed under scalar multiplication. -/ +structure SubAddAction (R : Type u) (M : Type v) [VAdd R M] : Type v where + /-- The underlying set of a `SubAddAction`. -/ + carrier : Set M + /-- The carrier set is closed under scalar multiplication. -/ + vadd_mem' : ∀ (c : R) {x : M}, x ∈ carrier → c +ᵥ x ∈ carrier + +attribute [to_additive] SubMulAction + namespace SubMulAction variable [SMul R M] +@[to_additive] instance : SetLike (SubMulAction R M) M := ⟨SubMulAction.carrier, fun p q h => by cases p; cases q; congr⟩ +@[to_additive] instance : SMulMemClass (SubMulAction R M) R M where smul_mem := smul_mem' _ -@[simp] +@[to_additive (attr := simp)] theorem mem_carrier {p : SubMulAction R M} {x : M} : x ∈ p.carrier ↔ x ∈ (p : Set M) := Iff.rfl -@[ext] +@[to_additive (attr := ext)] theorem ext {p q : SubMulAction R M} (h : ∀ x, x ∈ p ↔ x ∈ q) : p = q := SetLike.ext h /-- Copy of a sub_mul_action with a new `carrier` equal to the old one. Useful to fix definitional equalities. -/ +@[to_additive "Copy of a sub_mul_action with a new `carrier` equal to the old one. + Useful to fix definitional equalities."] protected def copy (p : SubMulAction R M) (s : Set M) (hs : s = ↑p) : SubMulAction R M where carrier := s smul_mem' := hs.symm ▸ p.smul_mem' -@[simp] +@[to_additive (attr := simp)] theorem coe_copy (p : SubMulAction R M) (s : Set M) (hs : s = ↑p) : (p.copy s hs : Set M) = s := rfl +@[to_additive] theorem copy_eq (p : SubMulAction R M) (s : Set M) (hs : s = ↑p) : p.copy s hs = p := SetLike.coe_injective hs +@[to_additive] instance : Bot (SubMulAction R M) where bot := { carrier := ∅ smul_mem' := fun _c h => Set.not_mem_empty h } +@[to_additive] instance : Inhabited (SubMulAction R M) := ⟨⊥⟩ @@ -209,14 +225,16 @@ variable [SMul R M] variable (p : SubMulAction R M) variable {r : R} {x : M} +@[to_additive] theorem smul_mem (r : R) (h : x ∈ p) : r • x ∈ p := p.smul_mem' r h +@[to_additive] instance : SMul R p where smul c x := ⟨c • x.1, smul_mem _ c x.2⟩ variable {p} -@[simp, norm_cast] +@[to_additive (attr := norm_cast, simp)] theorem val_smul (r : R) (x : p) : (↑(r • x) : M) = r • (x : M) := rfl @@ -225,14 +243,16 @@ theorem val_smul (r : R) (x : p) : (↑(r • x) : M) = r • (x : M) := variable (p) /-- Embedding of a submodule `p` to the ambient space `M`. -/ +@[to_additive "Embedding of a submodule `p` to the ambient space `M`."] protected def subtype : p →[R] M where toFun := Subtype.val map_smul' := by simp [val_smul] -@[simp] +@[to_additive (attr := simp)] theorem subtype_apply (x : p) : p.subtype x = x := rfl +@[to_additive] theorem subtype_eq_val : (SubMulAction.subtype p : p → M) = Subtype.val := rfl @@ -245,14 +265,16 @@ variable [hA : SMulMemClass A R M] (S' : A) -- Prefer subclasses of `MulAction` over `SMulMemClass`. /-- A `SubMulAction` of a `MulAction` is a `MulAction`. -/ +@[to_additive "A `SubAddAction` of an `AddAction` is an `AddAction`."] instance (priority := 75) toMulAction : MulAction R S' := Subtype.coe_injective.mulAction Subtype.val (SetLike.val_smul S') /-- The natural `MulActionHom` over `R` from a `SubMulAction` of `M` to `M`. -/ +@[to_additive "The natural `AddActionHom` over `R` from a `SubAddAction` of `M` to `M`."] protected def subtype : S' →[R] M where toFun := Subtype.val; map_smul' _ _ := rfl -@[simp] +@[to_additive (attr := simp)] protected theorem coeSubtype : (SMulMemClass.subtype S' : S' → M) = Subtype.val := rfl @@ -267,28 +289,33 @@ section variable [SMul S R] [SMul S M] [IsScalarTower S R M] variable (p : SubMulAction R M) +@[to_additive] theorem smul_of_tower_mem (s : S) {x : M} (h : x ∈ p) : s • x ∈ p := by rw [← one_smul R x, ← smul_assoc] exact p.smul_mem _ h +@[to_additive] instance smul' : SMul S p where smul c x := ⟨c • x.1, smul_of_tower_mem _ c x.2⟩ +@[to_additive] instance isScalarTower : IsScalarTower S R p where smul_assoc s r x := Subtype.ext <| smul_assoc s r (x : M) +@[to_additive] instance isScalarTower' {S' : Type*} [SMul S' R] [SMul S' S] [SMul S' M] [IsScalarTower S' R M] [IsScalarTower S' S M] : IsScalarTower S' S p where smul_assoc s r x := Subtype.ext <| smul_assoc s r (x : M) -@[simp, norm_cast] +@[to_additive (attr := norm_cast, simp)] theorem val_smul_of_tower (s : S) (x : p) : ((s • x : p) : M) = s • (x : M) := rfl -@[simp] +@[to_additive (attr := simp)] theorem smul_mem_iff' {G} [Group G] [SMul G R] [MulAction G M] [IsScalarTower G R M] (g : G) {x : M} : g • x ∈ p ↔ x ∈ p := ⟨fun h => inv_smul_smul g x ▸ p.smul_of_tower_mem g⁻¹ h, p.smul_of_tower_mem g⟩ +@[to_additive] instance isCentralScalar [SMul Sᵐᵒᵖ R] [SMul Sᵐᵒᵖ M] [IsScalarTower Sᵐᵒᵖ R M] [IsCentralScalar S M] : IsCentralScalar S p where @@ -302,17 +329,20 @@ variable [Monoid S] [SMul S R] [MulAction S M] [IsScalarTower S R M] variable (p : SubMulAction R M) /-- If the scalar product forms a `MulAction`, then the subset inherits this action -/ +@[to_additive] instance mulAction' : MulAction S p where smul := (· • ·) one_smul x := Subtype.ext <| one_smul _ (x : M) mul_smul c₁ c₂ x := Subtype.ext <| mul_smul c₁ c₂ (x : M) +@[to_additive] instance mulAction : MulAction R p := p.mulAction' end /-- Orbits in a `SubMulAction` coincide with orbits in the ambient space. -/ +@[to_additive] theorem val_image_orbit {p : SubMulAction R M} (m : p) : Subtype.val '' MulAction.orbit R m = MulAction.orbit R (m : M) := (Set.range_comp _ _).symm @@ -322,15 +352,18 @@ lemma orbit_of_sub_mul {p : SubMulAction R M} (m : p) : (mul_action.orbit R m : set M) = MulAction.orbit R (m : M) := rfl -/ +@[to_additive] theorem val_preimage_orbit {p : SubMulAction R M} (m : p) : Subtype.val ⁻¹' MulAction.orbit R (m : M) = MulAction.orbit R m := by rw [← val_image_orbit, Subtype.val_injective.preimage_image] +@[to_additive] lemma mem_orbit_subMul_iff {p : SubMulAction R M} {x m : p} : x ∈ MulAction.orbit R m ↔ (x : M) ∈ MulAction.orbit R (m : M) := by rw [← val_preimage_orbit, Set.mem_preimage] /-- Stabilizers in monoid SubMulAction coincide with stabilizers in the ambient space -/ +@[to_additive] theorem stabilizer_of_subMul.submonoid {p : SubMulAction R M} (m : p) : MulAction.stabilizerSubmonoid R m = MulAction.stabilizerSubmonoid R (m : M) := by ext @@ -342,6 +375,7 @@ section MulActionGroup variable [Group R] [MulAction R M] +@[to_additive] lemma orbitRel_of_subMul (p : SubMulAction R M) : MulAction.orbitRel R p = (MulAction.orbitRel R M).comap Subtype.val := by refine Setoid.ext_iff.2 (fun x y ↦ ?_) @@ -349,6 +383,7 @@ lemma orbitRel_of_subMul (p : SubMulAction R M) : exact mem_orbit_subMul_iff /-- Stabilizers in group SubMulAction coincide with stabilizers in the ambient space -/ +@[to_additive] theorem stabilizer_of_subMul {p : SubMulAction R M} (m : p) : MulAction.stabilizer R m = MulAction.stabilizer R (m : M) := by rw [← Subgroup.toSubmonoid_inj] @@ -419,23 +454,28 @@ variable {M α : Type*} [Monoid M] [MulAction M α] /-- The inclusion of a SubMulAction into the ambient set, as an equivariant map -/ +@[to_additive "The inclusion of a SubAddAction into the ambient set, as an equivariant map."] def inclusion (s : SubMulAction M α) : s →[M] α where -- The inclusion map of the inclusion of a SubMulAction toFun := Subtype.val -- The commutation property map_smul' _ _ := rfl +@[to_additive] theorem inclusion.toFun_eq_coe (s : SubMulAction M α) : s.inclusion.toFun = Subtype.val := rfl +@[to_additive] theorem inclusion.coe_eq (s : SubMulAction M α) : ⇑s.inclusion = Subtype.val := rfl +@[to_additive] lemma image_inclusion (s : SubMulAction M α) : Set.range s.inclusion = s.carrier := by rw [inclusion.coe_eq] exact Subtype.range_coe +@[to_additive] lemma inclusion_injective (s : SubMulAction M α) : Function.Injective s.inclusion := Subtype.val_injective diff --git a/Mathlib/GroupTheory/Index.lean b/Mathlib/GroupTheory/Index.lean index 6ad32109acca6..f8e36f80728c3 100644 --- a/Mathlib/GroupTheory/Index.lean +++ b/Mathlib/GroupTheory/Index.lean @@ -617,12 +617,12 @@ namespace MulAction variable (G : Type*) {X : Type*} [Group G] [MulAction G X] (x : X) -theorem index_stabilizer : +@[to_additive] theorem index_stabilizer : (stabilizer G x).index = (orbit G x).ncard := (Nat.card_congr (MulAction.orbitEquivQuotientStabilizer G x)).symm.trans (Set.Nat.card_coe_set_eq (orbit G x)) -theorem index_stabilizer_of_transitive [IsPretransitive G X] : +@[to_additive] theorem index_stabilizer_of_transitive [IsPretransitive G X] : (stabilizer G x).index = Nat.card X := by rw [index_stabilizer, orbit_eq_univ, Set.ncard_univ] From 213762fb4c13fdf97f7c18e0f194b8086e94deb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 6 Jan 2025 23:47:14 +0000 Subject: [PATCH 026/681] chore: don't import algebra in `Data.Multiset.Basic` (#19775) --- Mathlib.lean | 1 + .../Algebra/BigOperators/Group/Multiset.lean | 3 +- .../BigOperators/GroupWithZero/Action.lean | 4 +- Mathlib/Algebra/Order/Group/Multiset.lean | 178 ++++++++++++ Mathlib/Data/Multiset/Basic.lean | 266 +++++++----------- Mathlib/Data/Multiset/OrderedMonoid.lean | 2 +- Mathlib/Data/Multiset/Range.lean | 2 +- Mathlib/Data/Sym/Basic.lean | 2 +- 8 files changed, 282 insertions(+), 176 deletions(-) create mode 100644 Mathlib/Algebra/Order/Group/Multiset.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2bdbb9627ace3..a43bb2278aa5e 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -689,6 +689,7 @@ import Mathlib.Algebra.Order.Group.Instances import Mathlib.Algebra.Order.Group.Int import Mathlib.Algebra.Order.Group.Lattice import Mathlib.Algebra.Order.Group.MinMax +import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Algebra.Order.Group.Nat import Mathlib.Algebra.Order.Group.Opposite import Mathlib.Algebra.Order.Group.OrderIso diff --git a/Mathlib/Algebra/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/BigOperators/Group/Multiset.lean index a93afea870a07..9f83c37dae0a1 100644 --- a/Mathlib/Algebra/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Multiset.lean @@ -5,7 +5,8 @@ Authors: Mario Carneiro -/ import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.Group.Prod -import Mathlib.Data.Multiset.Basic +import Mathlib.Algebra.Order.Group.Multiset +import Mathlib.Algebra.Order.Sub.Unbundled.Basic /-! # Sums and products over multisets diff --git a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean index 6f377d4ff77be..af5e65fe47cb5 100644 --- a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean +++ b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean @@ -3,11 +3,11 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ +import Mathlib.Algebra.BigOperators.Finprod import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.GroupWithZero.Action.Defs +import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Data.Finset.Basic -import Mathlib.Data.Multiset.Basic -import Mathlib.Algebra.BigOperators.Finprod /-! # Lemmas about group actions on big operators diff --git a/Mathlib/Algebra/Order/Group/Multiset.lean b/Mathlib/Algebra/Order/Group/Multiset.lean new file mode 100644 index 0000000000000..7fb63d8cd37e0 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Multiset.lean @@ -0,0 +1,178 @@ +/- +Copyright (c) 2015 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro +-/ +import Mathlib.Algebra.Group.Hom.Defs +import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Order.Monoid.Unbundled.ExistsOfLE +import Mathlib.Algebra.Order.Sub.Defs +import Mathlib.Data.Multiset.Basic + +/-! +# Multisets form an ordered monoid + +This file contains the ordered monoid instance on multisets, and lemmas related to it. + +See note [foundational algebra order theory]. +-/ + +open List Nat + +variable {α β : Type*} + +namespace Multiset + +/-! ### Additive monoid -/ + +instance instAddLeftMono : AddLeftMono (Multiset α) where elim _s _t _u := Multiset.add_le_add_left + +instance instAddLeftReflectLE : AddLeftReflectLE (Multiset α) where + elim _s _t _u := Multiset.le_of_add_le_add_left + +instance instAddCancelCommMonoid : AddCancelCommMonoid (Multiset α) where + add_comm := Multiset.add_comm + add_assoc := Multiset.add_assoc + zero_add := Multiset.zero_add + add_zero := Multiset.add_zero + add_left_cancel _ _ _ := Multiset.add_right_inj.1 + nsmul := nsmulRec + +lemma mem_of_mem_nsmul {a : α} {s : Multiset α} {n : ℕ} (h : a ∈ n • s) : a ∈ s := by + induction' n with n ih + · rw [zero_nsmul] at h + exact absurd h (not_mem_zero _) + · rw [succ_nsmul, mem_add] at h + exact h.elim ih id + +@[simp] +lemma mem_nsmul {a : α} {s : Multiset α} {n : ℕ} : a ∈ n • s ↔ n ≠ 0 ∧ a ∈ s := by + refine ⟨fun ha ↦ ⟨?_, mem_of_mem_nsmul ha⟩, fun h ↦ ?_⟩ + · rintro rfl + simp [zero_nsmul] at ha + obtain ⟨n, rfl⟩ := exists_eq_succ_of_ne_zero h.1 + rw [succ_nsmul, mem_add] + exact Or.inr h.2 + +lemma mem_nsmul_of_ne_zero {a : α} {s : Multiset α} {n : ℕ} (h0 : n ≠ 0) : a ∈ n • s ↔ a ∈ s := by + simp [*] + +lemma nsmul_cons {s : Multiset α} (n : ℕ) (a : α) : + n • (a ::ₘ s) = n • ({a} : Multiset α) + n • s := by + rw [← singleton_add, nsmul_add] + +/-! ### Cardinality -/ + +/-- `Multiset.card` bundled as a group hom. -/ +@[simps] +def cardHom : Multiset α →+ ℕ where + toFun := card + map_zero' := card_zero + map_add' := card_add + +@[simp] +lemma card_nsmul (s : Multiset α) (n : ℕ) : card (n • s) = n * card s := cardHom.map_nsmul .. + +/-! ### `Multiset.replicate` -/ + +/-- `Multiset.replicate` as an `AddMonoidHom`. -/ +@[simps] +def replicateAddMonoidHom (a : α) : ℕ →+ Multiset α where + toFun n := replicate n a + map_zero' := replicate_zero a + map_add' _ _ := replicate_add _ _ a + +lemma nsmul_replicate {a : α} (n m : ℕ) : n • replicate m a = replicate (n * m) a := + ((replicateAddMonoidHom a).map_nsmul _ _).symm + +lemma nsmul_singleton (a : α) (n) : n • ({a} : Multiset α) = replicate n a := by + rw [← replicate_one, nsmul_replicate, mul_one] + +/-! ### `Multiset.map` -/ + +/-- `Multiset.map` as an `AddMonoidHom`. -/ +@[simps] +def mapAddMonoidHom (f : α → β) : Multiset α →+ Multiset β where + toFun := map f + map_zero' := map_zero _ + map_add' := map_add _ + +@[simp] +lemma coe_mapAddMonoidHom (f : α → β) : (mapAddMonoidHom f : Multiset α → Multiset β) = map f := rfl + +lemma map_nsmul (f : α → β) (n : ℕ) (s) : map f (n • s) = n • map f s := + (mapAddMonoidHom f).map_nsmul _ _ + +/-! ### Subtraction -/ + +section +variable [DecidableEq α] + +instance : OrderedSub (Multiset α) where tsub_le_iff_right _n _m _k := Multiset.sub_le_iff_le_add + +instance : ExistsAddOfLE (Multiset α) where + exists_add_of_le h := leInductionOn h fun s ↦ + let ⟨l, p⟩ := s.exists_perm_append; ⟨l, Quot.sound p⟩ + +end + +/-! ### `Multiset.filter` -/ + +section +variable (p : α → Prop) [DecidablePred p] + +lemma filter_nsmul (s : Multiset α) (n : ℕ) : filter p (n • s) = n • filter p s := by + refine s.induction_on ?_ ?_ + · simp only [filter_zero, nsmul_zero] + · intro a ha ih + rw [nsmul_cons, filter_add, ih, filter_cons, nsmul_add] + congr + split_ifs with hp <;> + · simp only [filter_eq_self, nsmul_zero, filter_eq_nil] + intro b hb + rwa [mem_singleton.mp (mem_of_mem_nsmul hb)] + +/-! ### countP -/ + +@[simp] +lemma countP_nsmul (s) (n : ℕ) : countP p (n • s) = n * countP p s := by + induction n <;> simp [*, succ_nsmul, succ_mul, zero_nsmul] + +/-- `countP p`, the number of elements of a multiset satisfying `p`, promoted to an +`AddMonoidHom`. -/ +def countPAddMonoidHom : Multiset α →+ ℕ where + toFun := countP p + map_zero' := countP_zero _ + map_add' := countP_add _ + +@[simp] lemma coe_countPAddMonoidHom : (countPAddMonoidHom p : Multiset α → ℕ) = countP p := rfl + +end + +/-! ### Multiplicity of an element -/ + +section +variable [DecidableEq α] {s : Multiset α} + +/-- `count a`, the multiplicity of `a` in a multiset, promoted to an `AddMonoidHom`. -/ +def countAddMonoidHom (a : α) : Multiset α →+ ℕ := + countPAddMonoidHom (a = ·) + +@[simp] +lemma coe_countAddMonoidHom (a : α) : (countAddMonoidHom a : Multiset α → ℕ) = count a := rfl + +@[simp] +lemma count_nsmul (a : α) (n s) : count a (n • s) = n * count a s := by + induction n <;> simp [*, succ_nsmul, succ_mul, zero_nsmul] + +end + +-- TODO: This should be `addMonoidHom_ext` +@[ext] +lemma addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by + ext s + induction' s using Multiset.induction_on with a s ih + · simp only [_root_.map_zero] + · simp only [← singleton_add, _root_.map_add, ih, h] + +end Multiset diff --git a/Mathlib/Data/Multiset/Basic.lean b/Mathlib/Data/Multiset/Basic.lean index 9fec51e78b073..bb263451f18a0 100644 --- a/Mathlib/Data/Multiset/Basic.lean +++ b/Mathlib/Data/Multiset/Basic.lean @@ -3,15 +3,13 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Group.Hom.Defs -import Mathlib.Algebra.Group.Nat.Basic -import Mathlib.Algebra.Order.Sub.Unbundled.Basic import Mathlib.Data.List.Count import Mathlib.Data.List.Perm.Basic import Mathlib.Data.List.Perm.Lattice import Mathlib.Data.List.Perm.Subperm import Mathlib.Data.Set.List import Mathlib.Order.Hom.Basic +import Mathlib.Order.MinMax /-! # Multisets @@ -34,8 +32,8 @@ lists by permutation. This gives them computational content. occurrences of `a` in `s` and `t`. -/ --- No bundled ordered algebra should be required -assert_not_exists OrderedCommMonoid +-- No algebra should be required +assert_not_exists Monoid universe v @@ -588,6 +586,7 @@ end /-! ### Additive monoid -/ section add +variable {s t u : Multiset α} /-- The sum of two multisets is the lift of the list append operation. This adds the multiplicities of each element, @@ -607,28 +606,33 @@ theorem coe_add (s t : List α) : (s + t : Multiset α) = (s ++ t : List α) := theorem singleton_add (a : α) (s : Multiset α) : {a} + s = a ::ₘ s := rfl -private theorem add_le_add_iff_left' {s t u : Multiset α} : s + t ≤ s + u ↔ t ≤ u := +protected lemma add_le_add_iff_left : s + t ≤ s + u ↔ t ≤ u := Quotient.inductionOn₃ s t u fun _ _ _ => subperm_append_left _ -instance : AddLeftMono (Multiset α) := - ⟨fun _s _t _u => add_le_add_iff_left'.2⟩ +protected lemma add_le_add_iff_right : s + u ≤ t + u ↔ s ≤ t := + Quotient.inductionOn₃ s t u fun _ _ _ => subperm_append_right _ -instance : AddLeftReflectLE (Multiset α) := - ⟨fun _s _t _u => add_le_add_iff_left'.1⟩ +protected alias ⟨le_of_add_le_add_left, add_le_add_left⟩ := Multiset.add_le_add_iff_left +protected alias ⟨le_of_add_le_add_right, add_le_add_right⟩ := Multiset.add_le_add_iff_right -instance instAddCommMonoid : AddCancelCommMonoid (Multiset α) where - add_comm := fun s t => Quotient.inductionOn₂ s t fun _ _ => Quot.sound perm_append_comm - add_assoc := fun s₁ s₂ s₃ => - Quotient.inductionOn₃ s₁ s₂ s₃ fun l₁ l₂ l₃ => congr_arg _ <| append_assoc l₁ l₂ l₃ - zero_add := fun s => Quot.inductionOn s fun _ => rfl - add_zero := fun s => Quotient.inductionOn s fun l => congr_arg _ <| append_nil l - add_left_cancel := fun _ _ _ h => - le_antisymm (Multiset.add_le_add_iff_left'.mp h.le) (Multiset.add_le_add_iff_left'.mp h.ge) - nsmul := nsmulRec +protected lemma add_comm (s t : Multiset α) : s + t = t + s := + Quotient.inductionOn₂ s t fun _ _ ↦ Quot.sound perm_append_comm -theorem le_add_right (s t : Multiset α) : s ≤ s + t := by simpa using add_le_add_left (zero_le t) s +protected lemma add_assoc (s t u : Multiset α) : s + t + u = s + (t + u) := + Quotient.inductionOn₃ s t u fun _ _ _ ↦ congr_arg _ <| append_assoc .. -theorem le_add_left (s t : Multiset α) : s ≤ t + s := by simpa using add_le_add_right (zero_le t) s +@[simp, nolint simpNF] -- We want to use this lemma earlier than `zero_add` +protected lemma zero_add (s : Multiset α) : 0 + s = s := Quotient.inductionOn s fun _ ↦ rfl + +@[simp, nolint simpNF] -- We want to use this lemma earlier than `add_zero` +protected lemma add_zero (s : Multiset α) : s + 0 = s := + Quotient.inductionOn s fun l ↦ congr_arg _ <| append_nil l + +lemma le_add_right (s t : Multiset α) : s ≤ s + t := by + simpa using Multiset.add_le_add_left (zero_le t) + +lemma le_add_left (s t : Multiset α) : s ≤ t + s := by + simpa using Multiset.add_le_add_right (zero_le t) lemma subset_add_left {s t : Multiset α} : s ⊆ s + t := subset_of_le <| le_add_right s t @@ -643,11 +647,11 @@ theorem le_iff_exists_add {s t : Multiset α} : s ≤ t ↔ ∃ u, t = s + u := @[simp] theorem cons_add (a : α) (s t : Multiset α) : a ::ₘ s + t = a ::ₘ (s + t) := by - rw [← singleton_add, ← singleton_add, add_assoc] + rw [← singleton_add, ← singleton_add, Multiset.add_assoc] @[simp] theorem add_cons (a : α) (s t : Multiset α) : s + a ::ₘ t = a ::ₘ (s + t) := by - rw [add_comm, cons_add, add_comm] + rw [Multiset.add_comm, cons_add, Multiset.add_comm] @[simp] theorem mem_add {a : α} {s t : Multiset α} : a ∈ s + t ↔ a ∈ s ∨ a ∈ t := @@ -655,29 +659,6 @@ theorem mem_add {a : α} {s t : Multiset α} : a ∈ s + t ↔ a ∈ s ∨ a ∈ end add -theorem mem_of_mem_nsmul {a : α} {s : Multiset α} {n : ℕ} (h : a ∈ n • s) : a ∈ s := by - induction' n with n ih - · rw [zero_nsmul] at h - exact absurd h (not_mem_zero _) - · rw [succ_nsmul, mem_add] at h - exact h.elim ih id - -@[simp] -theorem mem_nsmul {a : α} {s : Multiset α} {n : ℕ} : a ∈ n • s ↔ n ≠ 0 ∧ a ∈ s := by - refine ⟨fun ha ↦ ⟨?_, mem_of_mem_nsmul ha⟩, fun h => ?_⟩ - · rintro rfl - simp [zero_nsmul] at ha - obtain ⟨n, rfl⟩ := exists_eq_succ_of_ne_zero h.1 - rw [succ_nsmul, mem_add] - exact Or.inr h.2 - -lemma mem_nsmul_of_ne_zero {a : α} {s : Multiset α} {n : ℕ} (h0 : n ≠ 0) : a ∈ n • s ↔ a ∈ s := by - simp [*] - -theorem nsmul_cons {s : Multiset α} (n : ℕ) (a : α) : - n • (a ::ₘ s) = n • ({a} : Multiset α) + n • s := by - rw [← singleton_add, nsmul_add] - /-! ### Cardinality -/ @@ -697,18 +678,9 @@ theorem length_toList (s : Multiset α) : s.toList.length = card s := by theorem card_zero : @card α 0 = 0 := rfl -@[simp] lemma card_add (s t : Multiset α) : card (s + t) = card s + card t := - Quotient.inductionOn₂ s t length_append - -/-- `Multiset.card` bundled as a monoid hom. -/ -@[simps] -def cardHom : Multiset α →+ ℕ where - toFun := card - map_zero' := card_zero - map_add' := card_add - @[simp] -lemma card_nsmul (s : Multiset α) (n : ℕ) : card (n • s) = n * card s := cardHom.map_nsmul .. +theorem card_add (s t : Multiset α) : card (s + t) = card s + card t := + Quotient.inductionOn₂ s t length_append @[simp] theorem card_cons (a : α) (s : Multiset α) : card (a ::ₘ s) = card s + 1 := @@ -716,7 +688,7 @@ theorem card_cons (a : α) (s : Multiset α) : card (a ::ₘ s) = card s + 1 := @[simp] theorem card_singleton (a : α) : card ({a} : Multiset α) = 1 := by - simp only [← cons_zero, card_zero, eq_self_iff_true, zero_add, card_cons] + simp only [← cons_zero, card_zero, eq_self_iff_true, Multiset.zero_add, card_cons] theorem card_pair (a b : α) : card {a, b} = 2 := by rw [insert_eq_cons, card_cons, card_singleton] @@ -840,13 +812,6 @@ theorem coe_replicate (n : ℕ) (a : α) : (List.replicate n a : Multiset α) = theorem replicate_add (m n : ℕ) (a : α) : replicate (m + n) a = replicate m a + replicate n a := congr_arg _ <| List.replicate_add .. -/-- `Multiset.replicate` as an `AddMonoidHom`. -/ -@[simps] -def replicateAddMonoidHom (a : α) : ℕ →+ Multiset α where - toFun := fun n => replicate n a - map_zero' := replicate_zero a - map_add' := fun _ _ => replicate_add _ _ a - theorem replicate_one (a : α) : replicate 1 a = {a} := rfl @[simp] theorem card_replicate (n) (a : α) : card (replicate n a) = n := @@ -885,12 +850,6 @@ theorem replicate_subset_singleton (n : ℕ) (a : α) : replicate n a ⊆ {a} := theorem replicate_le_coe {a : α} {n} {l : List α} : replicate n a ≤ l ↔ List.replicate n a <+ l := ⟨fun ⟨_l', p, s⟩ => perm_replicate.1 p ▸ s, Sublist.subperm⟩ -theorem nsmul_replicate {a : α} (n m : ℕ) : n • replicate m a = replicate (n * m) a := - ((replicateAddMonoidHom a).map_nsmul _ _).symm - -theorem nsmul_singleton (a : α) (n) : n • ({a} : Multiset α) = replicate n a := by - rw [← replicate_one, nsmul_replicate, mul_one] - theorem replicate_le_replicate (a : α) {k n : ℕ} : replicate k a ≤ replicate n a ↔ k ≤ n := _root_.trans (by rw [← replicate_le_coe, coe_replicate]) (List.replicate_sublist_replicate a) @@ -965,7 +924,8 @@ theorem le_cons_erase (s : Multiset α) (a : α) : s ≤ a ::ₘ s.erase a := else by rw [erase_of_not_mem h]; apply le_cons_self theorem add_singleton_eq_iff {s t : Multiset α} {a : α} : s + {a} = t ↔ a ∈ t ∧ s = t.erase a := by - rw [add_comm, singleton_add]; constructor + rw [Multiset.add_comm, singleton_add] + constructor · rintro rfl exact ⟨s.mem_cons_self a, (s.erase_cons_head a).symm⟩ · rintro ⟨h, rfl⟩ @@ -974,15 +934,15 @@ theorem add_singleton_eq_iff {s t : Multiset α} {a : α} : s + {a} = t ↔ a theorem erase_add_left_pos {a : α} {s : Multiset α} (t) : a ∈ s → (s + t).erase a = s.erase a + t := Quotient.inductionOn₂ s t fun _l₁ l₂ h => congr_arg _ <| erase_append_left l₂ h -theorem erase_add_right_pos {a : α} (s) {t : Multiset α} (h : a ∈ t) : - (s + t).erase a = s + t.erase a := by rw [add_comm, erase_add_left_pos s h, add_comm] +theorem erase_add_right_pos {a : α} (s) (h : a ∈ t) : (s + t).erase a = s + t.erase a := by + rw [Multiset.add_comm, erase_add_left_pos s h, Multiset.add_comm] theorem erase_add_right_neg {a : α} {s : Multiset α} (t) : a ∉ s → (s + t).erase a = s + t.erase a := Quotient.inductionOn₂ s t fun _l₁ l₂ h => congr_arg _ <| erase_append_right l₂ h -theorem erase_add_left_neg {a : α} (s) {t : Multiset α} (h : a ∉ t) : - (s + t).erase a = s.erase a + t := by rw [add_comm, erase_add_right_neg s h, add_comm] +theorem erase_add_left_neg {a : α} (s) (h : a ∉ t) : (s + t).erase a = s.erase a + t := by + rw [Multiset.add_comm, erase_add_right_neg s h, Multiset.add_comm] theorem erase_le (a : α) (s : Multiset α) : s.erase a ≤ s := Quot.inductionOn s fun l => (erase_sublist a l).subperm @@ -1101,20 +1061,6 @@ instance canLift (c) (p) [CanLift α β c p] : lift l to List β using hl exact ⟨l, map_coe _ _⟩ -/-- `Multiset.map` as an `AddMonoidHom`. -/ -def mapAddMonoidHom (f : α → β) : Multiset α →+ Multiset β where - toFun := map f - map_zero' := map_zero _ - map_add' := map_add _ - -@[simp] -theorem coe_mapAddMonoidHom (f : α → β) : - (mapAddMonoidHom f : Multiset α → Multiset β) = map f := - rfl - -theorem map_nsmul (f : α → β) (n : ℕ) (s) : map f (n • s) = n • map f s := - (mapAddMonoidHom f).map_nsmul _ _ - @[simp] theorem mem_map {f : α → β} {b : β} {s : Multiset α} : b ∈ map f s ↔ ∃ a, a ∈ s ∧ f a = b := Quot.inductionOn s fun _l => List.mem_map @@ -1553,22 +1499,11 @@ theorem filter_cons {a : α} (s : Multiset α) : filter p (a ::ₘ s) = (if p a then {a} else 0) + filter p s := by split_ifs with h · rw [filter_cons_of_pos _ h, singleton_add] - · rw [filter_cons_of_neg _ h, zero_add] + · rw [filter_cons_of_neg _ h, Multiset.zero_add] theorem filter_singleton {a : α} (p : α → Prop) [DecidablePred p] : filter p {a} = if p a then {a} else ∅ := by - simp only [singleton, filter_cons, filter_zero, add_zero, empty_eq_zero] - -theorem filter_nsmul (s : Multiset α) (n : ℕ) : filter p (n • s) = n • filter p s := by - refine s.induction_on ?_ ?_ - · simp only [filter_zero, nsmul_zero] - · intro a ha ih - rw [nsmul_cons, filter_add, ih, filter_cons, nsmul_add] - congr - split_ifs with hp <;> - · simp only [filter_eq_self, nsmul_zero, filter_eq_nil] - intro b hb - rwa [mem_singleton.mp (mem_of_mem_nsmul hb)] + simp only [singleton, filter_cons, filter_zero, Multiset.add_zero, empty_eq_zero] variable (p) @@ -1586,7 +1521,7 @@ theorem filter_add_filter (q) [DecidablePred q] (s : Multiset α) : theorem filter_add_not (s : Multiset α) : filter p s + filter (fun a => ¬p a) s = s := by rw [filter_add_filter, filter_eq_self.2, filter_eq_nil.2] - · simp only [add_zero] + · simp only [Multiset.add_zero] · simp [Decidable.em, -Bool.not_eq_true, -not_and, not_and_or, or_comm] · simp only [Bool.not_eq_true, decide_eq_true_eq, Bool.eq_false_or_eq_true, decide_true, implies_true, Decidable.em] @@ -1729,24 +1664,9 @@ theorem countP_le_card (s) : countP p s ≤ card s := theorem countP_add (s t) : countP p (s + t) = countP p s + countP p t := by simp [countP_eq_card_filter] -@[simp] -theorem countP_nsmul (s) (n : ℕ) : countP p (n • s) = n * countP p s := by - induction n <;> simp [*, succ_nsmul, succ_mul, zero_nsmul] - theorem card_eq_countP_add_countP (s) : card s = countP p s + countP (fun x => ¬p x) s := Quot.inductionOn s fun l => by simp [l.length_eq_countP_add_countP p] -/-- `countP p`, the number of elements of a multiset satisfying `p`, promoted to an -`AddMonoidHom`. -/ -def countPAddMonoidHom : Multiset α →+ ℕ where - toFun := countP p - map_zero' := countP_zero _ - map_add' := countP_add _ - -@[simp] -theorem coe_countPAddMonoidHom : (countPAddMonoidHom p : Multiset α → ℕ) = countP p := - rfl - @[gcongr] theorem countP_le_of_le {s t} (h : s ≤ t) : countP p s ≤ countP p t := by simpa [countP_eq_card_filter] using card_le_card (filter_le_filter p h) @@ -1774,7 +1694,7 @@ theorem countP_map (f : α → β) (s : Multiset α) (p : β → Prop) [Decidabl refine Multiset.induction_on s ?_ fun a t IH => ?_ · rw [map_zero, countP_zero, filter_zero, card_zero] · rw [map_cons, countP_cons, IH, filter_cons, card_add, apply_ite card, card_zero, card_singleton, - add_comm] + Nat.add_comm] -- Porting note: `Lean.Internal.coeM` forces us to type-ascript `{a // a ∈ s}` lemma countP_attach (s : Multiset α) : s.attach.countP (fun a : {a // a ∈ s} ↦ p a) = s.countP p := @@ -1825,7 +1745,7 @@ end section -variable [DecidableEq α] {s : Multiset α} +variable [DecidableEq α] {s t u : Multiset α} /-- `count a s` is the multiplicity of `a` in `s`. -/ def count (a : α) : Multiset α → ℕ := @@ -1866,24 +1786,12 @@ theorem count_singleton_self (a : α) : count a ({a} : Multiset α) = 1 := count_eq_one_of_mem (nodup_singleton a) <| mem_singleton_self a theorem count_singleton (a b : α) : count a ({b} : Multiset α) = if a = b then 1 else 0 := by - simp only [count_cons, ← cons_zero, count_zero, zero_add] + simp only [count_cons, ← cons_zero, count_zero, Nat.zero_add] @[simp] theorem count_add (a : α) : ∀ s t, count a (s + t) = count a s + count a t := countP_add _ -/-- `count a`, the multiplicity of `a` in a multiset, promoted to an `AddMonoidHom`. -/ -def countAddMonoidHom (a : α) : Multiset α →+ ℕ := - countPAddMonoidHom (a = ·) - -@[simp] -theorem coe_countAddMonoidHom {a : α} : (countAddMonoidHom a : Multiset α → ℕ) = count a := - rfl - -@[simp] -theorem count_nsmul (a : α) (n s) : count a (n • s) = n * count a s := by - induction n <;> simp [*, succ_nsmul, succ_mul, zero_nsmul] - @[simp] lemma count_attach (a : {x // x ∈ s}) : s.attach.count a = s.count ↑a := Eq.trans (countP_congr rfl fun _ _ => by simp [Subtype.ext_iff]) <| countP_attach _ _ @@ -2007,6 +1915,12 @@ lemma erase_attach_map (s : Multiset α) (f : α → β) (x : {x // x ∈ s}) : simp only [← Function.comp_apply (f := f)] rw [← map_map, erase_attach_map_val] +omit [DecidableEq α] in +protected lemma add_left_inj : s + u = t + u ↔ s = t := by classical simp [Multiset.ext] + +omit [DecidableEq α] in +protected lemma add_right_inj : s + t = s + u ↔ t = u := by classical simp [Multiset.ext] + end /-! ### Subtraction -/ @@ -2055,17 +1969,35 @@ protected lemma sub_le_iff_le_add : s - t ≤ u ↔ s ≤ u + t := by exact @(Multiset.induction_on t (by simp [Multiset.sub_zero]) fun a t IH s => by simp [IH, erase_le_iff_le_cons]) -protected lemma sub_le_self (s t : Multiset α) : s - t ≤ s := by +/-- This is a special case of `tsub_le_iff_left`, which should be used instead of this. -/ +protected lemma sub_le_iff_le_add' : s - t ≤ u ↔ s ≤ t + u := by + rw [Multiset.sub_le_iff_le_add, Multiset.add_comm] + +protected theorem sub_le_self (s t : Multiset α) : s - t ≤ s := by rw [Multiset.sub_le_iff_le_add] exact le_add_right _ _ -instance : OrderedSub (Multiset α) := - ⟨fun _n _m _k => Multiset.sub_le_iff_le_add⟩ +protected lemma add_sub_assoc (hut : u ≤ t) : s + t - u = s + (t - u) := by + ext a; simp [Nat.add_sub_assoc <| count_le_of_le _ hut] -instance : ExistsAddOfLE (Multiset α) where - exists_add_of_le h := leInductionOn h fun s => - let ⟨l, p⟩ := s.exists_perm_append - ⟨l, Quot.sound p⟩ +protected lemma add_sub_cancel (hts : t ≤ s) : s - t + t = s := by + ext a; simp [Nat.sub_add_cancel <| count_le_of_le _ hts] + +protected lemma sub_add_cancel (hts : t ≤ s) : s - t + t = s := by + ext a; simp [Nat.sub_add_cancel <| count_le_of_le _ hts] + +protected lemma sub_add_eq_sub_sub : s - (t + u) = s - t - u := by ext; simp [Nat.sub_add_eq] + +protected lemma le_sub_add : s ≤ s - t + t := Multiset.sub_le_iff_le_add.1 le_rfl +protected lemma le_add_sub : s ≤ t + (s - t) := Multiset.sub_le_iff_le_add'.1 le_rfl + +protected lemma sub_le_sub_right (hst : s ≤ t) : s - u ≤ t - u := + Multiset.sub_le_iff_le_add'.mpr <| hst.trans Multiset.le_add_sub + +protected lemma add_sub_cancel_right : s + t - t = s := by ext a; simp + +protected lemma eq_sub_of_add_eq (hstu : s + t = u) : s = u - t := by + rw [← hstu, Multiset.add_sub_cancel_right] @[simp] lemma filter_sub (p : α → Prop) [DecidablePred p] (s t : Multiset α) : @@ -2090,7 +2022,7 @@ lemma sub_filter_eq_filter_not (p : α → Prop) [DecidablePred p] (s : Multiset s - s.filter p = s.filter fun a ↦ ¬ p a := by ext a; by_cases h : p a <;> simp [h] lemma cons_sub_of_le (a : α) {s t : Multiset α} (h : t ≤ s) : a ::ₘ s - t = a ::ₘ (s - t) := by - rw [← singleton_add, ← singleton_add, add_tsub_assoc_of_le h] + rw [← singleton_add, ← singleton_add, Multiset.add_sub_assoc h] lemma sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase s t := Quotient.inductionOn₂ s t fun l₁ l₂ => by @@ -2101,7 +2033,7 @@ lemma sub_eq_fold_erase (s t : Multiset α) : s - t = foldl erase s t := @[simp] lemma card_sub {s t : Multiset α} (h : t ≤ s) : card (s - t) = card s - card t := - Nat.eq_sub_of_add_eq <| by rw [← card_add, tsub_add_cancel_of_le h] + Nat.eq_sub_of_add_eq <| by rw [← card_add, Multiset.sub_add_cancel h] /-! ### Union -/ @@ -2109,17 +2041,18 @@ lemma card_sub {s t : Multiset α} (h : t ≤ s) : card (s - t) = card s - card multiplicity of `a` in `s` and `t`. This is the supremum of multisets. -/ def union (s t : Multiset α) : Multiset α := s - t + t -instance : Union (Multiset α) := ⟨union⟩ +instance : Union (Multiset α) := + ⟨union⟩ lemma union_def (s t : Multiset α) : s ∪ t = s - t + t := rfl -lemma le_union_left : s ≤ s ∪ t := le_tsub_add +lemma le_union_left : s ≤ s ∪ t := Multiset.le_sub_add lemma le_union_right : t ≤ s ∪ t := le_add_left _ _ -lemma eq_union_left : t ≤ s → s ∪ t = s := tsub_add_cancel_of_le +lemma eq_union_left : t ≤ s → s ∪ t = s := Multiset.sub_add_cancel @[gcongr] lemma union_le_union_right (h : s ≤ t) (u) : s ∪ u ≤ t ∪ u := - add_le_add_right (tsub_le_tsub_right h _) _ + Multiset.add_le_add_right <| Multiset.sub_le_sub_right h lemma union_le (h₁ : s ≤ u) (h₂ : t ≤ u) : s ∪ t ≤ u := by rw [← eq_union_left h₂]; exact union_le_union_right h₁ t @@ -2219,12 +2152,12 @@ lemma eq_union_right (h : s ≤ t) : s ∪ t = t := by rw [union_comm, eq_union_ lemma union_le_add (s t : Multiset α) : s ∪ t ≤ s + t := union_le (le_add_right ..) (le_add_left ..) lemma union_add_distrib (s t u : Multiset α) : s ∪ t + u = s + u ∪ (t + u) := by - simpa [(· ∪ ·), union, eq_comm, add_assoc, add_left_inj] using + simpa [(· ∪ ·), union, eq_comm, Multiset.add_assoc, Multiset.add_left_inj] using show s + u - (t + u) = s - t by - rw [add_comm t, tsub_add_eq_tsub_tsub, add_tsub_cancel_right] + rw [t.add_comm, Multiset.sub_add_eq_sub_sub, Multiset.add_sub_cancel_right] lemma add_union_distrib (s t u : Multiset α) : s + (t ∪ u) = s + t ∪ (s + u) := by - rw [add_comm, union_add_distrib, add_comm s, add_comm s] + rw [Multiset.add_comm, union_add_distrib, s.add_comm, s.add_comm] lemma cons_union_distrib (a : α) (s t : Multiset α) : a ::ₘ (s ∪ t) = a ::ₘ s ∪ a ::ₘ t := by simpa using add_union_distrib (a ::ₘ 0) s t @@ -2232,14 +2165,14 @@ lemma cons_union_distrib (a : α) (s t : Multiset α) : a ::ₘ (s ∪ t) = a :: lemma inter_add_distrib (s t u : Multiset α) : s ∩ t + u = (s + u) ∩ (t + u) := by by_contra! h obtain ⟨a, ha⟩ := lt_iff_cons_le.1 <| h.lt_of_le <| le_inter - (add_le_add_right inter_le_left _) (add_le_add_right inter_le_right _) + (Multiset.add_le_add_right inter_le_left) (Multiset.add_le_add_right inter_le_right) rw [← cons_add] at ha exact (lt_cons_self (s ∩ t) a).not_le <| le_inter - (le_of_add_le_add_right (ha.trans inter_le_left)) - (le_of_add_le_add_right (ha.trans inter_le_right)) + (Multiset.le_of_add_le_add_right (ha.trans inter_le_left)) + (Multiset.le_of_add_le_add_right (ha.trans inter_le_right)) lemma add_inter_distrib (s t u : Multiset α) : s + t ∩ u = (s + t) ∩ (s + u) := by - rw [add_comm, inter_add_distrib, add_comm s, add_comm s] + rw [Multiset.add_comm, inter_add_distrib, s.add_comm, s.add_comm] lemma cons_inter_distrib (a : α) (s t : Multiset α) : a ::ₘ s ∩ t = (a ::ₘ s) ∩ (a ::ₘ t) := by simp @@ -2247,13 +2180,13 @@ lemma cons_inter_distrib (a : α) (s t : Multiset α) : a ::ₘ s ∩ t = (a :: lemma union_add_inter (s t : Multiset α) : s ∪ t + s ∩ t = s + t := by apply _root_.le_antisymm · rw [union_add_distrib] - refine union_le (add_le_add_left inter_le_right _) ?_ - rw [add_comm] - exact add_le_add_right inter_le_left _ - · rw [add_comm, add_inter_distrib] - refine le_inter (add_le_add_right le_union_right _) ?_ - rw [add_comm] - exact add_le_add_right le_union_left _ + refine union_le (Multiset.add_le_add_left inter_le_right) ?_ + rw [Multiset.add_comm] + exact Multiset.add_le_add_right inter_le_left + · rw [Multiset.add_comm, add_inter_distrib] + refine le_inter (Multiset.add_le_add_right le_union_right) ?_ + rw [Multiset.add_comm] + exact Multiset.add_le_add_right le_union_left lemma sub_add_inter (s t : Multiset α) : s - t + s ∩ t = s := by rw [inter_comm] @@ -2263,7 +2196,7 @@ lemma sub_add_inter (s t : Multiset α) : s - t + s ∩ t = s := by · rw [cons_inter_of_neg _ h, sub_cons, erase_of_not_mem h, IH] lemma sub_inter (s t : Multiset α) : s - s ∩ t = s - t := - (eq_tsub_of_add_eq <| sub_add_inter ..).symm + (Multiset.eq_sub_of_add_eq <| sub_add_inter ..).symm @[simp] lemma count_inter (a : α) (s t : Multiset α) : count a (s ∩ t) = min (count a s) (count a t) := by @@ -2300,13 +2233,6 @@ theorem inter_replicate (s : Multiset α) (n : ℕ) (x : α) : end sub -@[ext] -theorem addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by - ext s - induction' s using Multiset.induction_on with a s ih - · simp only [_root_.map_zero] - · simp only [← singleton_add, _root_.map_add, ih, h] - section Embedding @[simp] @@ -2661,7 +2587,7 @@ lemma add_eq_union_left_of_le [DecidableEq α] {s t u : Multiset α} (h : t ≤ rw [← add_eq_union_iff_disjoint] refine ⟨fun h0 ↦ ?_, ?_⟩ · rw [and_iff_right_of_imp] - · exact (le_of_add_le_add_left <| h0.trans_le <| union_le_add u t).antisymm h + · exact (Multiset.le_of_add_le_add_left <| h0.trans_le <| union_le_add u t).antisymm h · rintro rfl exact h0 · rintro ⟨h0, rfl⟩ diff --git a/Mathlib/Data/Multiset/OrderedMonoid.lean b/Mathlib/Data/Multiset/OrderedMonoid.lean index bf40bc0b213eb..a674512d9f22c 100644 --- a/Mathlib/Data/Multiset/OrderedMonoid.lean +++ b/Mathlib/Data/Multiset/OrderedMonoid.lean @@ -3,7 +3,7 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Multiset.Basic +import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Algebra.Order.Monoid.Canonical.Defs /-! diff --git a/Mathlib/Data/Multiset/Range.lean b/Mathlib/Data/Multiset/Range.lean index 7f1b911b0f826..82be6f025e6de 100644 --- a/Mathlib/Data/Multiset/Range.lean +++ b/Mathlib/Data/Multiset/Range.lean @@ -3,7 +3,7 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.Multiset.Basic +import Mathlib.Algebra.Order.Group.Multiset /-! # `Multiset.range n` gives `{0, 1, ..., n-1}` as a multiset. -/ diff --git a/Mathlib/Data/Sym/Basic.lean b/Mathlib/Data/Sym/Basic.lean index 2733966c42fc7..24af84e1ec2d4 100644 --- a/Mathlib/Data/Sym/Basic.lean +++ b/Mathlib/Data/Sym/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Mathlib.Data.Multiset.Basic +import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Data.Vector.Basic import Mathlib.Data.Setoid.Basic import Mathlib.Tactic.ApplyFun From 9e41cddbdfeff3a991bda66a964e0e3c6702c4ab Mon Sep 17 00:00:00 2001 From: Vasily Nesterov Date: Tue, 7 Jan 2025 00:39:34 +0000 Subject: [PATCH 027/681] feat(Analysis/Analytic): lemmas about `smul` for power series (#19816) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Prove `radius_le_smul` and `radius_smul_eq` stating that `c • p` converges on the same ball as `p`. * Prove `HasFPowerSeriesOnBall.const_smul` (and variations) stating that scalar multiplication preserves series' convergence on the same ball. * Add `smul_apply` simp-lemma for `FormalMultilinearSeries`. Co-authored-by: Vasily Nesterov <118051017+vasnesterov@users.noreply.github.com> --- Mathlib/Analysis/Analytic/Basic.lean | 15 ++++++++ Mathlib/Analysis/Analytic/Constructions.lean | 34 ++++++++++++++++++- .../Calculus/FormalMultilinearSeries.lean | 4 +++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index af1cd9c970c9d..b89802058d494 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -327,6 +327,21 @@ theorem min_radius_le_radius_add (p q : FormalMultilinearSeries 𝕜 E F) : theorem radius_neg (p : FormalMultilinearSeries 𝕜 E F) : (-p).radius = p.radius := by simp only [radius, neg_apply, norm_neg] +theorem radius_le_smul {p : FormalMultilinearSeries 𝕜 E F} {c : 𝕜} : p.radius ≤ (c • p).radius := by + simp only [radius, smul_apply] + refine iSup_mono fun r ↦ iSup_mono' fun C ↦ ⟨‖c‖ * C, iSup_mono' fun h ↦ ?_⟩ + simp only [le_refl, exists_prop, and_true] + intro n + rw [norm_smul c (p n), mul_assoc] + gcongr + exact h n + +theorem radius_smul_eq (p : FormalMultilinearSeries 𝕜 E F) {c : 𝕜} + (hc : c ≠ 0) : (c • p).radius = p.radius := by + apply eq_of_le_of_le _ radius_le_smul + conv => rhs; rw [show p = c⁻¹ • (c • p) by simp [smul_smul, inv_mul_cancel₀ hc]] + apply radius_le_smul + @[simp] theorem radius_shift (p : FormalMultilinearSeries 𝕜 E F) : p.shift.radius = p.radius := by simp only [radius, shift, Nat.succ_eq_add_one, ContinuousMultilinearMap.curryRight_norm] diff --git a/Mathlib/Analysis/Analytic/Constructions.lean b/Mathlib/Analysis/Analytic/Constructions.lean index a1a029bcd24a3..f56a2644814f0 100644 --- a/Mathlib/Analysis/Analytic/Constructions.lean +++ b/Mathlib/Analysis/Analytic/Constructions.lean @@ -62,12 +62,13 @@ theorem analyticOn_const {v : F} {s : Set E} : AnalyticOn 𝕜 (fun _ => v) s := alias analyticWithinOn_const := analyticOn_const /-! -### Addition, negation, subtraction +### Addition, negation, subtraction, scalar multiplication -/ section variable {f g : E → F} {pf pg : FormalMultilinearSeries 𝕜 E F} {s : Set E} {x : E} {r : ℝ≥0∞} + {c : 𝕜} theorem HasFPowerSeriesWithinOnBall.add (hf : HasFPowerSeriesWithinOnBall f pf s x r) (hg : HasFPowerSeriesWithinOnBall g pg s x r) : @@ -163,6 +164,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 HasFPowerSeriesWithinOnBall.const_smul (hf : HasFPowerSeriesWithinOnBall f pf s x r) : + HasFPowerSeriesWithinOnBall (c • f) (c • pf) s x r where + r_le := le_trans hf.r_le pf.radius_le_smul + r_pos := hf.r_pos + hasSum := fun hy h'y => (hf.hasSum hy h'y).const_smul _ + +theorem HasFPowerSeriesOnBall.const_smul (hf : HasFPowerSeriesOnBall f pf x r) : + HasFPowerSeriesOnBall (c • f) (c • pf) x r where + r_le := le_trans hf.r_le pf.radius_le_smul + r_pos := hf.r_pos + hasSum := fun hy => (hf.hasSum hy).const_smul _ + +theorem HasFPowerSeriesWithinAt.const_smul (hf : HasFPowerSeriesWithinAt f pf s x) : + HasFPowerSeriesWithinAt (c • f) (c • pf) s x := + let ⟨_, hrf⟩ := hf + hrf.const_smul.hasFPowerSeriesWithinAt + +theorem HasFPowerSeriesAt.const_smul (hf : HasFPowerSeriesAt f pf x) : + HasFPowerSeriesAt (c • f) (c • pf) x := + let ⟨_, hrf⟩ := hf + hrf.const_smul.hasFPowerSeriesAt + +theorem AnalyticWithinAt.const_smul (hf : AnalyticWithinAt 𝕜 f s x) : + AnalyticWithinAt 𝕜 (c • f) s x := + let ⟨_, hpf⟩ := hf + hpf.const_smul.analyticWithinAt + +theorem AnalyticAt.const_smul (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (c • f) x := + let ⟨_, hpf⟩ := hf + hpf.const_smul.analyticAt + 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) diff --git a/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean b/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean index 4b12e24cee9e5..4254d8378f1d6 100644 --- a/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean +++ b/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean @@ -81,6 +81,10 @@ theorem add_apply (p q : FormalMultilinearSeries 𝕜 E F) (n : ℕ) : (p + q) n @[simp] theorem sub_apply (p q : FormalMultilinearSeries 𝕜 E F) (n : ℕ) : (p - q) n = p n - q n := rfl +@[simp] +theorem smul_apply [Semiring 𝕜'] [Module 𝕜' F] [ContinuousConstSMul 𝕜' F] [SMulCommClass 𝕜 𝕜' F] + (f : FormalMultilinearSeries 𝕜 E F) (n : ℕ) (a : 𝕜') : (a • f) n = a • f n := rfl + @[ext] protected theorem ext {p q : FormalMultilinearSeries 𝕜 E F} (h : ∀ n, p n = q n) : p = q := funext h From 9df640dcb9e12d80ec175cdb724150d809643e30 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 7 Jan 2025 01:14:44 +0000 Subject: [PATCH 028/681] fix: do not keep only the first line of hints (#19756) This is still not really the right approach, but it's clearly less wrong. --- Mathlib/Tactic/Hint.lean | 2 +- MathlibTest/hint.lean | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Mathlib/Tactic/Hint.lean b/Mathlib/Tactic/Hint.lean index 8df08cd79a07e..a8a705aa76f8a 100644 --- a/Mathlib/Tactic/Hint.lean +++ b/Mathlib/Tactic/Hint.lean @@ -72,7 +72,7 @@ def suggestion (tac : TSyntax `tactic) (msgs : MessageLog := {}) : TacticM Sugge let msg? ← msgs.toList.findM? fun m => do pure <| m.severity == MessageSeverity.information && (← m.data.toString).startsWith "Try this: " let suggestion ← match msg? with - | some m => pure <| SuggestionText.string (((← m.data.toString).drop 10).takeWhile (· != '\n')) + | some m => pure <| SuggestionText.string ((← m.data.toString).drop 10) | none => pure <| SuggestionText.tsyntax tac return { suggestion, postInfo?, style? } diff --git a/MathlibTest/hint.lean b/MathlibTest/hint.lean index e793160ca9e7e..f2757fd22d69d 100644 --- a/MathlibTest/hint.lean +++ b/MathlibTest/hint.lean @@ -51,3 +51,26 @@ info: Try these: -/ #guard_msgs in example {P : Nat → Prop} (h : { x // P x }) : ∃ x, P x ∧ 0 ≤ x := by hint + +section multiline_hint + +local macro "this_is_a_multiline_exact" ppLine t:term : tactic => `(tactic| exact $t) + +local elab tk:"long_trivial" : tactic => do + let triv := Lean.mkIdent ``trivial + let actual ← `(tactic| this_is_a_multiline_exact $triv) + Lean.Meta.Tactic.TryThis.addSuggestion tk { suggestion := .tsyntax actual} + Lean.Elab.Tactic.evalTactic actual + +register_hint long_trivial + +/-- +info: Try these: +• this_is_a_multiline_exact + trivial +-/ +#guard_msgs in +example : True := by + hint + +end multiline_hint From ff9182249cd9f2cac619a512ec9aede9ba89505e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= Date: Tue, 7 Jan 2025 02:24:23 +0000 Subject: [PATCH 029/681] =?UTF-8?q?perf:=20improves=20the=20performance=20?= =?UTF-8?q?of=20the=20`Repr=20(Equiv.Perm=20=CE=B1)`=20instance=20(1/4)=20?= =?UTF-8?q?(#20519)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR reduces computation time from $O(n^2)$ (more precisery, $O(\sum_{k --- Mathlib/GroupTheory/Perm/Cycle/Basic.lean | 11 ++++++----- Mathlib/GroupTheory/Perm/Cycle/Concrete.lean | 8 ++++---- Mathlib/GroupTheory/Perm/Cycle/Factors.lean | 8 -------- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean index 84311136f832a..7a9275a5282d0 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean @@ -5,7 +5,7 @@ Authors: Chris Hughes, Yaël Dillies -/ import Mathlib.Algebra.Module.BigOperators -import Mathlib.Data.Fintype.Perm +import Mathlib.Data.List.Iterate import Mathlib.GroupTheory.Perm.Finite import Mathlib.GroupTheory.Perm.List @@ -205,12 +205,13 @@ instance (priority := 100) [DecidableEq α] : DecidableRel (SameCycle (1 : Perm decidable_of_iff (x = y) sameCycle_one.symm instance [Fintype α] [DecidableEq α] (f : Perm α) : DecidableRel (SameCycle f) := fun x y => - decidable_of_iff (∃ n ∈ List.range (Fintype.card (Perm α)), (f ^ n) x = y) - ⟨fun ⟨n, _, hn⟩ => ⟨n, hn⟩, fun ⟨i, hi⟩ => ⟨(i % orderOf f).natAbs, - List.mem_range.2 (Int.ofNat_lt.1 <| by + decidable_of_iff (y ∈ List.iterate f x (Fintype.card (Perm α))) <| by + simp only [List.mem_iterate, iterate_eq_pow, eq_comm (a := y)] + exact ⟨fun ⟨n, _, hn⟩ => ⟨n, hn⟩, fun ⟨i, hi⟩ => ⟨(i % orderOf f).natAbs, + Int.ofNat_lt.1 <| by rw [Int.natAbs_of_nonneg (Int.emod_nonneg _ <| Int.natCast_ne_zero.2 (orderOf_pos _).ne')] refine (Int.emod_lt _ <| Int.natCast_ne_zero_iff_pos.2 <| orderOf_pos _).trans_le ?_ - simp [orderOf_le_card_univ]), + simp [orderOf_le_card_univ], by rw [← zpow_natCast, Int.natAbs_of_nonneg (Int.emod_nonneg _ <| Int.natCast_ne_zero_iff_pos.2 <| orderOf_pos _), zpow_mod_orderOf, hi]⟩⟩ diff --git a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean index 50e4396f56fa1..4f238742343a8 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean @@ -193,7 +193,7 @@ variable [Fintype α] [DecidableEq α] (p : Equiv.Perm α) (x : α) until looping. That means when `f x = x`, `toList f x = []`. -/ def toList : List α := - (List.range (cycleOf p x).support.card).map fun k => (p ^ k) x + List.iterate p x (cycleOf p x).support.card @[simp] theorem toList_one : toList (1 : Perm α) x = [] := by simp [toList, cycleOf_one] @@ -223,7 +223,7 @@ theorem toList_get_zero (h : x ∈ p.support) : variable {p} {x} theorem mem_toList_iff {y : α} : y ∈ toList p x ↔ SameCycle p x y ∧ x ∈ p.support := by - simp only [toList, mem_range, mem_map] + simp only [toList, mem_iterate, iterate_eq_pow, eq_comm (a := y)] constructor · rintro ⟨n, hx, rfl⟩ refine ⟨⟨n, rfl⟩, ?_⟩ @@ -314,8 +314,8 @@ theorem toList_formPerm_nontrivial (l : List α) (hl : 2 ≤ l.length) (hn : Nod simp [Nat.succ_le_succ_iff] at hl rw [toList, hc.cycleOf_eq (mem_support.mp _), hs, card_toFinset, dedup_eq_self.mpr hn] · refine ext_getElem (by simp) fun k hk hk' => ?_ - simp only [get_eq_getElem, formPerm_pow_apply_getElem _ hn, zero_add, getElem_map, - getElem_range, Nat.mod_eq_of_lt hk'] + simp only [get_eq_getElem, getElem_iterate, iterate_eq_pow, formPerm_pow_apply_getElem _ hn, + zero_add, Nat.mod_eq_of_lt hk'] · simp [hs] theorem toList_formPerm_isRotated_self (l : List α) (hl : 2 ≤ l.length) (hn : Nodup l) (x : α) diff --git a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean index 990c4810661c5..a3fe94c15f780 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean @@ -4,14 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Yaël Dillies -/ -import Mathlib.Algebra.Module.BigOperators -import Mathlib.Data.Finset.NoncommProd -import Mathlib.Data.Fintype.Perm -import Mathlib.Data.Int.ModEq -import Mathlib.GroupTheory.Perm.List -import Mathlib.GroupTheory.Perm.Sign -import Mathlib.Logic.Equiv.Fintype - import Mathlib.GroupTheory.Perm.Cycle.Basic /-! From b84129c76939e72b449ca2f2cf173e0dcc4ce53a Mon Sep 17 00:00:00 2001 From: Mitchell Lee Date: Tue, 7 Jan 2025 02:59:53 +0000 Subject: [PATCH 030/681] doc: change "module homomorphism" to "linear map" (#20481) We change all occurrences of "module homomorphism" in docstrings to "linear map". See here: https://github.com/leanprover-community/mathlib4/pull/20452#issuecomment-2571343604 Co-authored-by: Mitchell Lee <130885647+trivial1711@users.noreply.github.com> --- Mathlib/Algebra/DirectSum/Algebra.lean | 2 +- Mathlib/LinearAlgebra/Prod.lean | 14 +++---- .../RingTheory/Flat/EquationalCriterion.lean | 40 +++++++++---------- Mathlib/RingTheory/Flat/FaithfullyFlat.lean | 2 +- Mathlib/Topology/Germ.lean | 2 +- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Mathlib/Algebra/DirectSum/Algebra.lean b/Mathlib/Algebra/DirectSum/Algebra.lean index 80c5c808cd07e..5db0ecc0efa46 100644 --- a/Mathlib/Algebra/DirectSum/Algebra.lean +++ b/Mathlib/Algebra/DirectSum/Algebra.lean @@ -129,7 +129,7 @@ theorem algHom_ext' ⦃f g : (⨁ i, A i) →ₐ[R] B⦄ theorem algHom_ext ⦃f g : (⨁ i, A i) →ₐ[R] B⦄ (h : ∀ i x, f (of A i x) = g (of A i x)) : f = g := algHom_ext' R A fun i => LinearMap.ext <| h i -/-- The piecewise multiplication from the `Mul` instance, as a bundled linear homomorphism. +/-- The piecewise multiplication from the `Mul` instance, as a bundled linear map. This is the graded version of `LinearMap.mul`, and the linear version of `DirectSum.gMulHom` -/ @[simps] diff --git a/Mathlib/LinearAlgebra/Prod.lean b/Mathlib/LinearAlgebra/Prod.lean index 328fdca858bd5..ed5cd352af5bd 100644 --- a/Mathlib/LinearAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/Prod.lean @@ -993,7 +993,7 @@ variable {R S G H I : Type*} [AddCommMonoid H] [Module S H] [AddCommMonoid I] [Module S I] -/-- **Vertical line test** for module homomorphisms. +/-- **Vertical line test** for linear maps. Let `f : G → H × I` be a linear (or semilinear) map to a product. Assume that `f` is surjective on the first factor and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` at @@ -1019,10 +1019,10 @@ lemma LinearMap.exists_range_eq_graph {f : G →ₛₗ[σ] H × I} (hf₁ : Surj simpa only [mem_range, Eq.comm, ZeroHom.toFun_eq_coe, AddMonoidHom.toZeroHom_coe, mem_graph_iff, coe_mk, AddHom.coe_mk, AddMonoidHom.coe_coe, Set.mem_range] using hf' x -/-- **Vertical line test** for module homomorphisms. +/-- **Vertical line test** for linear maps. Let `G ≤ H × I` be a submodule of a product of modules. Assume that `G` maps bijectively to the -first factor. Then `G` is the graph of some module homomorphism `f : H →ₗ[R] I`. -/ +first factor. Then `G` is the graph of some linear map `f : H →ₗ[R] I`. -/ lemma Submodule.exists_eq_graph {G : Submodule S (H × I)} (hf₁ : Bijective (Prod.fst ∘ G.subtype)) : ∃ f : H →ₗ[S] I, G = LinearMap.graph f := by simpa only [range_subtype] using LinearMap.exists_range_eq_graph hf₁.surjective @@ -1030,10 +1030,10 @@ lemma Submodule.exists_eq_graph {G : Submodule S (H × I)} (hf₁ : Bijective (P /-- **Line test** for module isomorphisms. -Let `f : G → H × I` be a homomorphism to a product of modules. Assume that `f` is surjective onto -both factors and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` and every -"horizontal line" `{(h, i) | h : H}` at most once. Then the image of `f` is the graph of some -module isomorphism `f' : H ≃ I`. -/ +Let `f : G → H × I` be a linear (or semilinear) map to a product of modules. Assume that `f` is +surjective onto both factors and that the image of `f` intersects every "vertical line" +`{(h, i) | i : I}` and every "horizontal line" `{(h, i) | h : H}` at most once. Then the image of +`f` is the graph of some module isomorphism `f' : H ≃ I`. -/ lemma LinearMap.exists_linearEquiv_eq_graph {f : G →ₛₗ[σ] H × I} (hf₁ : Surjective (Prod.fst ∘ f)) (hf₂ : Surjective (Prod.snd ∘ f)) (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 ↔ (f g₁).2 = (f g₂).2) : ∃ e : H ≃ₗ[S] I, range f = e.toLinearMap.graph := by diff --git a/Mathlib/RingTheory/Flat/EquationalCriterion.lean b/Mathlib/RingTheory/Flat/EquationalCriterion.lean index df38f6aa41c23..ccb3ba16c850c 100644 --- a/Mathlib/RingTheory/Flat/EquationalCriterion.lean +++ b/Mathlib/RingTheory/Flat/EquationalCriterion.lean @@ -25,9 +25,9 @@ The equational criterion for flatness can be stated in the following form (`Module.Flat.iff_forall_exists_factorization`). Let $M$ be an $R$-module. Then the following two conditions are equivalent: * $M$ is flat. -* For all finite index types $\iota$, all elements $f \in R^{\iota}$, and all homomorphisms +* For all finite index types $\iota$, all elements $f \in R^{\iota}$, and all linear maps $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there exist a finite index type $\kappa$ and module -homomorphisms $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such +linear maps $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. Of course, the module $R^\iota$ in this statement can be replaced by an arbitrary free module @@ -36,12 +36,12 @@ Of course, the module $R^\iota$ in this statement can be replaced by an arbitrar We also have the following strengthening of the equational criterion for flatness (`Module.Flat.exists_factorization_of_comp_eq_zero_of_free`): Let $M$ be a flat module. Let $K$ and $N$ be finite $R$-modules with $N$ free, and let $f \colon K \to N$ and -$x \colon N \to M$ be homomorphisms such that $x \circ f = 0$. Then there exist a finite index type -$\kappa$ and module homomorphisms $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such +$x \colon N \to M$ be linear maps such that $x \circ f = 0$. Then there exist a finite index type +$\kappa$ and $R$-linear maps $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a \circ f = 0$. We recover the usual equational criterion for flatness if $K = R$ and $N = R^\iota$. This is used in the proof of Lazard's theorem. -We conclude that every homomorphism from a finitely presented module to a flat module factors +We conclude that every linear map from a finitely presented module to a flat module factors through a finite free module (`Module.Flat.exists_factorization_of_isFinitelyPresented`). ## References @@ -103,12 +103,12 @@ Let $M$ be a module over a commutative ring $R$. The following are equivalent: * For all ideals $I \subseteq R$, the map $I \otimes M \to M$ is injective. * Every $\sum_i f_i \otimes x_i$ that vanishes in $R \otimes M$ vanishes trivially. * Every relation $\sum_i f_i x_i = 0$ in $M$ is trivial. -* For all finite index types $\iota$, all elements $f \in R^{\iota}$, and all homomorphisms +* For all finite index types $\iota$, all elements $f \in R^{\iota}$, and all linear maps $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there exist a finite index type $\kappa$ and module -homomorphisms $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such +linear maps $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -* For all finite free modules $N$, all elements $f \in N$, and all homomorphisms $x \colon N \to M$ -such that $x(f) = 0$, there exist a finite index type $\kappa$ and module homomorphisms +* For all finite free modules $N$, all elements $f \in N$, and all linear maps $x \colon N \to M$ +such that $x(f) = 0$, there exist a finite index type $\kappa$ and $R$-linear maps $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ theorem tfae_equational_criterion : List.TFAE [ @@ -203,8 +203,8 @@ theorem of_forall_isTrivialRelation (hfx : ∀ {ι : Type u} [Fintype ι] {f : [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), alternate form. A module $M$ is flat if and only if for all finite free modules $R^\iota$, -all $f \in R^{\iota}$, and all homomorphisms $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there -exist a finite free module $R^\kappa$ and homomorphisms $a \colon R^{\iota} \to R^{\kappa}$ and +all $f \in R^{\iota}$, and all linear maps $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there +exist a finite free module $R^\kappa$ and linear maps $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ theorem iff_forall_exists_factorization : Flat R M ↔ ∀ {ι : Type u} [Fintype ι] {f : ι →₀ R} {x : (ι →₀ R) →ₗ[R] M}, x f = 0 → @@ -215,8 +215,8 @@ theorem iff_forall_exists_factorization : Flat R M ↔ [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), forward direction, alternate form. Let $M$ be a flat module. Let $R^\iota$ be a finite free module, let $f \in R^{\iota}$ be an -element, and let $x \colon R^{\iota} \to M$ be a homomorphism such that $x(f) = 0$. Then there -exist a finite free module $R^\kappa$ and homomorphisms $a \colon R^{\iota} \to R^{\kappa}$ and +element, and let $x \colon R^{\iota} \to M$ be a linear map such that $x(f) = 0$. Then there +exist a finite free module $R^\kappa$ and linear maps $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ theorem exists_factorization_of_apply_eq_zero [Flat R M] {ι : Type u} [_root_.Finite ι] {f : ι →₀ R} {x : (ι →₀ R) →ₗ[R] M} (h : x f = 0) : @@ -228,8 +228,8 @@ theorem exists_factorization_of_apply_eq_zero [Flat R M] {ι : Type u} [_root_.F [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), backward direction, alternate form. Let $M$ be a module over a commutative ring $R$. Suppose that for all finite free modules $R^\iota$, -all $f \in R^{\iota}$, and all homomorphisms $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there -exist a finite free module $R^\kappa$ and homomorphisms $a \colon R^{\iota} \to R^{\kappa}$ and +all $f \in R^{\iota}$, and all linear maps $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there +exist a finite free module $R^\kappa$ and linear maps $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. Then $M$ is flat. -/ theorem of_forall_exists_factorization (h : ∀ {ι : Type u} [Fintype ι] {f : ι →₀ R} {x : (ι →₀ R) →ₗ[R] M}, x f = 0 → @@ -240,8 +240,8 @@ theorem of_forall_exists_factorization (h : ∀ {ι : Type u} [Fintype ι] {f : forward direction, second alternate form. Let $M$ be a flat module over a commutative ring $R$. Let $N$ be a finite free module over $R$, -let $f \in N$, and let $x \colon N \to M$ be a homomorphism such that $x(f) = 0$. Then there exist a -finite index type $\kappa$ and module homomorphisms $a \colon N \to R^{\kappa}$ and +let $f \in N$, and let $x \colon N \to M$ be a linear map such that $x(f) = 0$. Then there exist a +finite index type $\kappa$ and $R$-linear maps $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ theorem exists_factorization_of_apply_eq_zero_of_free [Flat R M] {N : Type u} [AddCommGroup N] [Module R N] [Free R N] [Module.Finite R N] {f : N} {x : N →ₗ[R] M} (h : x f = 0) : @@ -250,8 +250,8 @@ theorem exists_factorization_of_apply_eq_zero_of_free [Flat R M] {N : Type u} [A exact ((tfae_equational_criterion R M).out 0 5 rfl rfl).mp ‹Flat R M› h /-- Let $M$ be a flat module. Let $K$ and $N$ be finite $R$-modules with $N$ -free, and let $f \colon K \to N$ and $x \colon N \to M$ be homomorphisms such that -$x \circ f = 0$. Then there exist a finite index type $\kappa$ and module homomorphisms +free, and let $f \colon K \to N$ and $x \colon N \to M$ be linear maps such that +$x \circ f = 0$. Then there exist a finite index type $\kappa$ and $R$-linear maps $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a \circ f = 0$. -/ theorem exists_factorization_of_comp_eq_zero_of_free [Flat R M] {K N : Type u} [AddCommGroup K] @@ -276,7 +276,7 @@ theorem exists_factorization_of_comp_eq_zero_of_free [Flat R M] {K N : Type u} [ convert this ⊤ Finite.fg_top simp only [top_le_iff, ker_eq_top] -/-- Every homomorphism from a finitely presented module to a flat module factors through a finite +/-- Every linear map from a finitely presented module to a flat module factors through a finite free module. -/ theorem exists_factorization_of_isFinitelyPresented [Flat R M] {P : Type u} [AddCommGroup P] [Module R P] [FinitePresentation R P] (h₁ : P →ₗ[R] M) : diff --git a/Mathlib/RingTheory/Flat/FaithfullyFlat.lean b/Mathlib/RingTheory/Flat/FaithfullyFlat.lean index 39e1cd3c439b7..600a25333f1bd 100644 --- a/Mathlib/RingTheory/Flat/FaithfullyFlat.lean +++ b/Mathlib/RingTheory/Flat/FaithfullyFlat.lean @@ -55,7 +55,7 @@ variable (R : Type u) (M : Type v) [CommRing R] [AddCommGroup M] [Module R M] /-- A module `M` over a commutative ring `R` is *faithfully flat* if it is flat and, -for all `R`-module homomorphism `f : N → N'` such that `id ⊗ f = 0`, we have `f = 0`. +for all `R`-linear maps `f : N → N'` such that `id ⊗ f = 0`, we have `f = 0`. -/ @[mk_iff] class FaithfullyFlat extends Module.Flat R M : Prop where submodule_ne_top : ∀ ⦃m : Ideal R⦄ (_ : Ideal.IsMaximal m), m • (⊤ : Submodule R M) ≠ ⊤ diff --git a/Mathlib/Topology/Germ.lean b/Mathlib/Topology/Germ.lean index 35d47bcfa9b8a..acee607839565 100644 --- a/Mathlib/Topology/Germ.lean +++ b/Mathlib/Topology/Germ.lean @@ -17,7 +17,7 @@ with respect to the neighbourhood filter `𝓝 x`. * `Filter.Germ.value φ f`: value associated to the germ `φ` at a point `x`, w.r.t. the neighbourhood filter at `x`. This is the common value of all representatives of `φ` at `x`. * `Filter.Germ.valueOrderRingHom` and friends: the map `Germ (𝓝 x) E → E` is a -monoid homomorphism, 𝕜-module homomorphism, ring homomorphism, monotone ring homomorphism +monoid homomorphism, 𝕜-linear map, ring homomorphism, monotone ring homomorphism * `RestrictGermPredicate`: given a predicate on germs `P : Π x : X, germ (𝓝 x) Y → Prop` and `A : set X`, build a new predicate on germs `restrictGermPredicate P A` such that From d7f04b9d6c33326655ef71064b3ba40199bbcd31 Mon Sep 17 00:00:00 2001 From: Johannes Choo Date: Tue, 7 Jan 2025 04:29:22 +0000 Subject: [PATCH 031/681] feat(GroupTheory/QuotientGroup): group correspondence theorem (#20007) add the group correspondence theorem (a.k.a. lattice theorem, fourth isomorphism theorem). --- Mathlib/GroupTheory/QuotientGroup/Basic.lean | 32 ++++++++++++++++++++ Mathlib/GroupTheory/QuotientGroup/Defs.lean | 7 +++++ 2 files changed, 39 insertions(+) diff --git a/Mathlib/GroupTheory/QuotientGroup/Basic.lean b/Mathlib/GroupTheory/QuotientGroup/Basic.lean index 58622e2d53e83..ac753e21b448b 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Basic.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Basic.lean @@ -27,6 +27,9 @@ proves Noether's first and second isomorphism theorems. `N` of a group `G`. * `QuotientGroup.quotientQuotientEquivQuotient`: Noether's third isomorphism theorem, the canonical isomorphism between `(G / N) / (M / N)` and `G / M`, where `N ≤ M`. +* `QuotientGroup.comapMk'OrderIso`: The correspondence theorem, a lattice + isomorphism between the lattice of subgroups of `G ⧸ N` and the sublattice + of subgroups of `G` containing `N`. ## Tags @@ -321,6 +324,35 @@ def quotientQuotientEquivQuotient : (G ⧸ N) ⧸ M.map (QuotientGroup.mk' N) end ThirdIsoThm +section CorrespTheorem + +-- All these theorems are primed because `QuotientGroup.mk'` is. +set_option linter.docPrime false + +@[to_additive] +theorem le_comap_mk' (N : Subgroup G) [N.Normal] (H : Subgroup (G ⧸ N)) : + N ≤ Subgroup.comap (QuotientGroup.mk' N) H := by + simpa using Subgroup.comap_mono (f := mk' N) bot_le + +@[to_additive (attr := simp)] +theorem comap_map_mk' (N H : Subgroup G) [N.Normal] : + Subgroup.comap (mk' N) (Subgroup.map (mk' N) H) = N ⊔ H := by + simp [Subgroup.comap_map_eq, sup_comm] + +/-- The **correspondence theorem**, or lattice theorem, + or fourth isomorphism theorem for multiplicative groups-/ +@[to_additive "The **correspondence theorem**, or lattice theorem, + or fourth isomorphism theorem for additive groups"] +def comapMk'OrderIso (N : Subgroup G) [hn : N.Normal] : + Subgroup (G ⧸ N) ≃o { H : Subgroup G // N ≤ H } where + toFun H' := ⟨Subgroup.comap (mk' N) H', le_comap_mk' N _⟩ + invFun H := Subgroup.map (mk' N) H + left_inv H' := Subgroup.map_comap_eq_self <| by simp + right_inv := fun ⟨H, hH⟩ => Subtype.ext_val <| by simpa + map_rel_iff' := Subgroup.comap_le_comap_of_surjective <| mk'_surjective _ + +end CorrespTheorem + section trivial @[to_additive] diff --git a/Mathlib/GroupTheory/QuotientGroup/Defs.lean b/Mathlib/GroupTheory/QuotientGroup/Defs.lean index d33a94cc017c6..37c1c47dc4036 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Defs.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Defs.lean @@ -91,6 +91,13 @@ theorem eq_one_iff {N : Subgroup G} [N.Normal] (x : G) : (x : G ⧸ N) = 1 ↔ x refine QuotientGroup.eq.trans ?_ rw [mul_one, Subgroup.inv_mem_iff] +/- Note: `range_mk'` is a lemma about the primed constructor `QuotientGroup.mk'`, not a + modified version of some `range_mk`. -/ +set_option linter.docPrime false in +@[to_additive (attr := simp)] +theorem range_mk' : (QuotientGroup.mk' N).range = ⊤ := + MonoidHom.range_eq_top.mpr (mk'_surjective N) + @[to_additive] theorem ker_le_range_iff {I : Type w} [Group I] (f : G →* H) [f.range.Normal] (g : H →* I) : g.ker ≤ f.range ↔ (mk' f.range).comp g.ker.subtype = 1 := From 57f8888c4bdb82be079aaad594de5087e8a58b2c Mon Sep 17 00:00:00 2001 From: smorel394 Date: Tue, 7 Jan 2025 04:59:08 +0000 Subject: [PATCH 032/681] chore(Algebra/Category/MonCat/ForgetCorepresentable, Algebra/Group/Equiv/Basic): move definitions and add symmetric version (#20416) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the two definitions `MonoidHom.precompEquiv` (the equivalence `(β →* γ) ≃ (α →* γ)` obtained by precomposition with a multiplicative equivalence `e : α ≃* β`) and `AddMonoidHom.precompEquiv` (its additive version) from `Algebra.Category.MonCat.ForgetCorepresentable` to `Algebra.Group.Equiv.Basic`, so they can be used without importing files about `MonCat`. Also merge them into one definition using `@[to_additive]` and add the symmetric definition `(Add)MonoidHom.postcompEquiv`. --- .../Category/Grp/ForgetCorepresentable.lean | 3 -- Mathlib/Algebra/Category/Grp/Limits.lean | 2 ++ .../MonCat/ForgetCorepresentable.lean | 20 ------------- Mathlib/Algebra/Group/Equiv/Basic.lean | 28 +++++++++++++++++++ 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean b/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean index bf80cb3f9cbf7..5583ecdd7e331 100644 --- a/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean +++ b/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean @@ -4,9 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.Algebra.Category.Grp.Basic -import Mathlib.Algebra.Group.ULift -import Mathlib.CategoryTheory.Yoneda -import Mathlib.Algebra.Category.MonCat.ForgetCorepresentable /-! # The forget functor is corepresentable diff --git a/Mathlib/Algebra/Category/Grp/Limits.lean b/Mathlib/Algebra/Category/Grp/Limits.lean index f5aac619ae4f9..af71b540c80c5 100644 --- a/Mathlib/Algebra/Category/Grp/Limits.lean +++ b/Mathlib/Algebra/Category/Grp/Limits.lean @@ -3,6 +3,8 @@ Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ + +import Mathlib.Algebra.Category.MonCat.ForgetCorepresentable import Mathlib.Algebra.Category.Grp.ForgetCorepresentable import Mathlib.Algebra.Category.Grp.Preadditive import Mathlib.Algebra.Category.MonCat.Limits diff --git a/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean b/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean index 796d9ab458bb6..ce3e674738fab 100644 --- a/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean +++ b/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean @@ -21,16 +21,6 @@ open CategoryTheory Opposite namespace MonoidHom -/-- The equivalence `(β →* γ) ≃ (α →* γ)` obtained by precomposition with -a multiplicative equivalence `e : α ≃* β`. -/ -@[simps] -def precompEquiv {α β : Type*} [Monoid α] [Monoid β] (e : α ≃* β) (γ : Type*) [Monoid γ] : - (β →* γ) ≃ (α →* γ) where - toFun f := f.comp e - invFun g := g.comp e.symm - left_inv _ := by ext; simp - right_inv _ := by ext; simp - /-- The equivalence `(Multiplicative ℕ →* α) ≃ α` for any monoid `α`. -/ @[simps] def fromMultiplicativeNatEquiv (α : Type u) [Monoid α] : (Multiplicative ℕ →* α) ≃ α where @@ -49,16 +39,6 @@ end MonoidHom namespace AddMonoidHom -/-- The equivalence `(β →+ γ) ≃ (α →+ γ)` obtained by precomposition with -an additive equivalence `e : α ≃+ β`. -/ -@[simps] -def precompEquiv {α β : Type*} [AddMonoid α] [AddMonoid β] (e : α ≃+ β) (γ : Type*) [AddMonoid γ] : - (β →+ γ) ≃ (α →+ γ) where - toFun f := f.comp e - invFun g := g.comp e.symm - left_inv _ := by ext; simp - right_inv _ := by ext; simp - /-- The equivalence `(ℤ →+ α) ≃ α` for any additive group `α`. -/ @[simps] def fromNatEquiv (α : Type u) [AddMonoid α] : (ℕ →+ α) ≃ α where diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index 4d516e138b15b..30605dc8e53f9 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -634,6 +634,34 @@ protected theorem map_div [Group G] [DivisionMonoid H] (h : G ≃* H) (x y : G) end MulEquiv +namespace MonoidHom + +/-- The equivalence `(β →* γ) ≃ (α →* γ)` obtained by precomposition with +a multiplicative equivalence `e : α ≃* β`. -/ +@[to_additive (attr := simps) +"The equivalence `(β →+ γ) ≃ (α →+ γ)` obtained by precomposition with +an additive equivalence `e : α ≃+ β`."] +def precompEquiv {α β : Type*} [Monoid α] [Monoid β] (e : α ≃* β) (γ : Type*) [Monoid γ] : + (β →* γ) ≃ (α →* γ) where + toFun f := f.comp e + invFun g := g.comp e.symm + left_inv _ := by ext; simp + right_inv _ := by ext; simp + +/-- The equivalence `(γ →* α) ≃ (γ →* β)` obtained by postcomposition with +a multiplicative equivalence `e : α ≃* β`. -/ +@[to_additive (attr := simps) +"The equivalence `(γ →+ α) ≃ (γ →+ β)` obtained by postcomposition with +an additive equivalence `e : α ≃+ β`."] +def postcompEquiv {α β : Type*} [Monoid α] [Monoid β] (e : α ≃* β) (γ : Type*) [Monoid γ] : + (γ →* α) ≃ (γ →* β) where + toFun f := e.toMonoidHom.comp f + invFun g := e.symm.toMonoidHom.comp g + left_inv _ := by ext; simp + right_inv _ := by ext; simp + +end MonoidHom + -- Porting note: we want to add -- `@[simps (config := .asFn)]` -- here, but it generates simp lemmas which aren't in simp normal form From 1327df05c5e25bbb30d17f8d27b5989b0bef6911 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 7 Jan 2025 07:29:52 +0000 Subject: [PATCH 033/681] chore: smile more often (#20436) This replaces `: _)` with the shorter and otherwise *almost* identical `:)`. The former is a Lean 3 ism; or at least, the latter is new syntax in Lean 4. More precisely (thanks @kmill): - `(e : _)` elaborates `e` without an expected type, and then it inserts a coercion if the type of `e` does not match the expected type. - `(e :)` elaborates `e` without an expected type *to completion*, and then it inserts a coercion if the type of `e` does not match the expected type. A few places break when switched to `:)`; in many of these cases, the `: _)`/`:)` can just be dropped entirely. The remainder are left as is. --- Archive/Sensitivity.lean | 4 ++-- Counterexamples/Girard.lean | 2 +- Mathlib/Algebra/Algebra/NonUnitalHom.lean | 2 +- .../Algebra/Algebra/NonUnitalSubalgebra.lean | 2 +- Mathlib/Algebra/Algebra/RestrictScalars.lean | 2 +- Mathlib/Algebra/Algebra/Subalgebra/Basic.lean | 6 +++--- Mathlib/Algebra/Algebra/Subalgebra/Tower.lean | 2 +- Mathlib/Algebra/Algebra/Tower.lean | 4 ++-- .../Category/ModuleCat/Presheaf/Monoidal.lean | 2 +- .../Algebra/Category/Ring/Constructions.lean | 8 ++++---- Mathlib/Algebra/Category/Ring/Instances.lean | 2 +- .../Algebra/GCDMonoid/IntegrallyClosed.lean | 2 +- Mathlib/Algebra/GradedMonoid.lean | 4 ++-- Mathlib/Algebra/Group/Action/Units.lean | 10 +++++----- Mathlib/Algebra/Group/Opposite.lean | 2 +- Mathlib/Algebra/Group/Pi/Lemmas.lean | 2 +- Mathlib/Algebra/Group/Prod.lean | 2 +- .../Algebra/Group/Submonoid/Operations.lean | 6 +++--- Mathlib/Algebra/Lie/BaseChange.lean | 2 +- Mathlib/Algebra/Module/Equiv/Basic.lean | 2 +- Mathlib/Algebra/Module/LinearMap/Defs.lean | 4 ++-- .../Algebra/Module/LocalizedModule/Basic.lean | 2 +- Mathlib/Algebra/Module/Pi.lean | 2 +- Mathlib/Algebra/Module/Submodule/Basic.lean | 2 +- Mathlib/Algebra/Module/Submodule/Defs.lean | 2 +- .../Module/Submodule/RestrictScalars.lean | 2 +- Mathlib/Algebra/Module/Torsion.lean | 2 +- Mathlib/Algebra/MonoidAlgebra/Basic.lean | 2 +- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 4 ++-- Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean | 2 +- Mathlib/Algebra/MvPolynomial/Equiv.lean | 2 +- .../Algebra/Order/Interval/Set/Instances.lean | 4 ++-- Mathlib/Algebra/Ring/Subring/Defs.lean | 6 +++--- Mathlib/Algebra/Ring/Subsemiring/Defs.lean | 4 ++-- Mathlib/Algebra/RingQuot.lean | 2 +- Mathlib/Algebra/Star/NonUnitalSubalgebra.lean | 2 +- Mathlib/Algebra/Star/StarAlgHom.lean | 2 +- Mathlib/Algebra/Star/Subalgebra.lean | 2 +- Mathlib/AlgebraicGeometry/Cover/Open.lean | 2 +- Mathlib/AlgebraicGeometry/Limits.lean | 6 +++--- Mathlib/AlgebraicGeometry/Modules/Tilde.lean | 6 +++--- .../Morphisms/Preimmersion.lean | 2 +- .../Morphisms/SurjectiveOnStalks.lean | 2 +- .../Morphisms/UniversallyClosed.lean | 2 +- Mathlib/AlgebraicGeometry/OpenImmersion.lean | 6 +++--- .../AlgebraicGeometry/PrimeSpectrum/Basic.lean | 2 +- .../ProjectiveSpectrum/StructureSheaf.lean | 2 +- Mathlib/AlgebraicGeometry/Restrict.lean | 2 +- Mathlib/AlgebraicGeometry/Scheme.lean | 6 +++--- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 18 +++++++++--------- Mathlib/AlgebraicTopology/CechNerve.lean | 2 +- Mathlib/Analysis/Analytic/Composition.lean | 2 +- .../BoxIntegral/Partition/SubboxInduction.lean | 4 ++-- Mathlib/Analysis/CStarAlgebra/Multiplier.lean | 2 +- Mathlib/Analysis/Calculus/ContDiff/Defs.lean | 2 +- Mathlib/Analysis/Calculus/Deriv/Basic.lean | 2 +- Mathlib/Analysis/Calculus/FDeriv/Basic.lean | 2 +- Mathlib/Analysis/Calculus/Gradient/Basic.lean | 2 +- Mathlib/Analysis/Convolution.lean | 6 +++--- .../Fourier/FourierTransformDeriv.lean | 2 +- .../Analysis/InnerProductSpace/Completion.lean | 2 +- .../Analysis/InnerProductSpace/Projection.lean | 2 +- Mathlib/Analysis/Matrix.lean | 6 +++--- Mathlib/Analysis/Normed/Algebra/Basic.lean | 2 +- Mathlib/Analysis/Normed/Field/Basic.lean | 2 +- Mathlib/Analysis/Normed/Field/InfiniteSum.lean | 2 +- Mathlib/Analysis/Normed/Group/AddTorsor.lean | 2 +- .../Normed/Group/SemiNormedGrp/Kernels.lean | 2 +- Mathlib/Analysis/Normed/Module/Basic.lean | 2 +- .../NormedSpace/Multilinear/Basic.lean | 2 +- .../NormedSpace/OperatorNorm/Prod.lean | 2 +- Mathlib/CategoryTheory/Enriched/Basic.lean | 2 +- Mathlib/CategoryTheory/Extensive.lean | 12 ++++++------ Mathlib/CategoryTheory/Functor/Flat.lean | 4 ++-- .../CategoryTheory/Functor/FullyFaithful.lean | 2 +- Mathlib/CategoryTheory/IsConnected.lean | 2 +- .../CategoryTheory/Limits/ColimitLimit.lean | 2 +- Mathlib/CategoryTheory/Limits/Comma.lean | 8 ++++---- Mathlib/CategoryTheory/Limits/Cones.lean | 12 ++++++------ .../Limits/Constructions/BinaryProducts.lean | 6 +++--- Mathlib/CategoryTheory/Limits/Creates.lean | 8 ++++---- Mathlib/CategoryTheory/Limits/Final.lean | 4 ++-- Mathlib/CategoryTheory/Limits/IsLimit.lean | 8 ++++---- .../CategoryTheory/Limits/Preserves/Basic.lean | 8 ++++---- .../Limits/Preserves/Shapes/Pullbacks.lean | 2 +- .../Limits/Shapes/Multiequalizer.lean | 10 +++++----- .../Limits/Shapes/Pullback/Mono.lean | 4 ++-- .../Limits/Shapes/Pullback/PullbackCone.lean | 2 +- .../CategoryTheory/Limits/Shapes/Types.lean | 4 ++-- Mathlib/CategoryTheory/Limits/VanKampen.lean | 4 ++-- Mathlib/CategoryTheory/Monad/Adjunction.lean | 4 ++-- Mathlib/CategoryTheory/Monad/Kleisli.lean | 2 +- Mathlib/CategoryTheory/Monad/Limits.lean | 4 ++-- Mathlib/CategoryTheory/Preadditive/Mat.lean | 2 +- Mathlib/CategoryTheory/Sigma/Basic.lean | 4 ++-- .../Sites/DenseSubsite/Basic.lean | 4 ++-- .../Sites/EqualizerSheafCondition.lean | 2 +- .../CategoryTheory/Sites/Sheafification.lean | 2 +- Mathlib/CategoryTheory/Sites/Subsheaf.lean | 8 ++++---- Mathlib/Computability/RegularExpressions.lean | 2 +- Mathlib/Data/Complex/Module.lean | 4 ++-- Mathlib/Data/ENNReal/Operations.lean | 6 +++--- Mathlib/Data/Int/Cast/Lemmas.lean | 6 +++--- Mathlib/Data/List/Basic.lean | 2 +- Mathlib/Data/Matrix/Defs.lean | 2 +- Mathlib/Data/Matrix/Notation.lean | 2 +- Mathlib/Data/NNReal/Defs.lean | 8 ++++---- Mathlib/Data/PFunctor/Multivariate/Basic.lean | 2 +- Mathlib/Data/PFunctor/Multivariate/M.lean | 2 +- Mathlib/Data/Prod/Basic.lean | 4 ++-- Mathlib/Data/Sum/Basic.lean | 4 ++-- Mathlib/Data/TypeVec.lean | 2 +- Mathlib/Data/W/Basic.lean | 2 +- Mathlib/Dynamics/FixedPoints/Basic.lean | 2 +- Mathlib/FieldTheory/Adjoin.lean | 6 +++--- Mathlib/FieldTheory/IsAlgClosed/Basic.lean | 2 +- Mathlib/FieldTheory/Normal.lean | 2 +- .../Geometry/Manifold/ContMDiffMFDeriv.lean | 2 +- .../Manifold/LocalInvariantProperties.lean | 4 ++-- Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean | 4 ++-- Mathlib/Geometry/Manifold/MFDeriv/Basic.lean | 8 ++++---- Mathlib/Geometry/Manifold/MFDeriv/Defs.lean | 2 +- .../LocallyRingedSpace/HasColimits.lean | 14 +++++++------- Mathlib/Geometry/RingedSpace/Stalks.lean | 2 +- Mathlib/GroupTheory/GroupAction/Defs.lean | 2 +- Mathlib/GroupTheory/Perm/Finite.lean | 4 ++-- Mathlib/GroupTheory/QuotientGroup/Defs.lean | 2 +- .../SpecificGroups/Alternating.lean | 2 +- Mathlib/GroupTheory/Submonoid/Inverses.lean | 2 +- Mathlib/LinearAlgebra/Alternating/Basic.lean | 4 ++-- .../LinearAlgebra/BilinearForm/Properties.lean | 6 +++--- Mathlib/LinearAlgebra/BilinearMap.lean | 2 +- .../CliffordAlgebra/BaseChange.lean | 4 ++-- .../CliffordAlgebra/EvenEquiv.lean | 2 +- .../LinearAlgebra/Dimension/Constructions.lean | 2 +- Mathlib/LinearAlgebra/LinearIndependent.lean | 2 +- .../Matrix/Charpoly/FiniteField.lean | 2 +- .../Matrix/Charpoly/LinearMap.lean | 2 +- Mathlib/LinearAlgebra/Matrix/LDL.lean | 10 +++++----- Mathlib/LinearAlgebra/Matrix/Symmetric.lean | 4 ++-- .../LinearAlgebra/QuadraticForm/Isometry.lean | 2 +- Mathlib/LinearAlgebra/Quotient/Defs.lean | 2 +- Mathlib/LinearAlgebra/Ray.lean | 2 +- Mathlib/LinearAlgebra/Span/Basic.lean | 2 +- Mathlib/LinearAlgebra/TensorProduct/Basic.lean | 2 +- Mathlib/LinearAlgebra/TensorProduct/Tower.lean | 2 +- Mathlib/Logic/Function/Basic.lean | 4 ++-- .../Constructions/Polish/Basic.lean | 6 +++--- .../Function/LpSeminorm/CompareExp.lean | 4 ++-- .../Function/SimpleFuncDenseLp.lean | 2 +- Mathlib/MeasureTheory/Group/AddCircle.lean | 2 +- Mathlib/MeasureTheory/Group/Arithmetic.lean | 2 +- Mathlib/MeasureTheory/Integral/Prod.lean | 2 +- Mathlib/MeasureTheory/Measure/Prod.lean | 2 +- Mathlib/ModelTheory/LanguageMap.lean | 2 +- Mathlib/NumberTheory/Cyclotomic/Basic.lean | 2 +- Mathlib/Order/CompleteLattice.lean | 4 ++-- Mathlib/Order/Filter/Ultrafilter.lean | 2 +- Mathlib/Order/Height.lean | 4 ++-- Mathlib/Order/Hom/Order.lean | 8 ++++---- Mathlib/Order/Interval/Finset/Defs.lean | 6 +++--- Mathlib/Order/SupIndep.lean | 2 +- .../Probability/Kernel/Composition/Basic.lean | 2 +- .../Kernel/Composition/IntegralCompProd.lean | 2 +- .../DedekindDomain/AdicValuation.lean | 2 +- .../RingTheory/DedekindDomain/Different.lean | 4 ++-- .../RingTheory/Derivation/ToSquareZero.lean | 2 +- Mathlib/RingTheory/Ideal/AssociatedPrime.lean | 2 +- Mathlib/RingTheory/Ideal/Quotient/Defs.lean | 2 +- .../RingTheory/Ideal/Quotient/Operations.lean | 2 +- Mathlib/RingTheory/IsTensorProduct.lean | 6 +++--- Mathlib/RingTheory/Kaehler/Basic.lean | 6 +++--- .../RingTheory/Kaehler/CotangentComplex.lean | 2 +- Mathlib/RingTheory/Kaehler/JacobiZariski.lean | 2 +- Mathlib/RingTheory/MvPowerSeries/Basic.lean | 2 +- Mathlib/RingTheory/MvPowerSeries/Inverse.lean | 2 +- Mathlib/RingTheory/Nilpotent/Lemmas.lean | 2 +- Mathlib/RingTheory/NonUnitalSubring/Defs.lean | 6 +++--- .../RingTheory/NonUnitalSubsemiring/Defs.lean | 4 ++-- Mathlib/RingTheory/Perfection.lean | 2 +- Mathlib/RingTheory/Smooth/Basic.lean | 4 ++-- Mathlib/RingTheory/WittVector/Basic.lean | 2 +- Mathlib/SetTheory/Cardinal/Cofinality.lean | 2 +- .../Tactic/Linarith/Oracle/FourierMotzkin.lean | 2 +- Mathlib/Topology/Algebra/ConstMulAction.lean | 4 ++-- Mathlib/Topology/Algebra/Group/Basic.lean | 2 +- .../Algebra/InfiniteSum/Constructions.lean | 4 ++-- Mathlib/Topology/Algebra/Monoid.lean | 4 ++-- Mathlib/Topology/Algebra/UniformField.lean | 2 +- .../Topology/Algebra/UniformGroup/Basic.lean | 2 +- .../Topology/Algebra/UniformGroup/Defs.lean | 2 +- Mathlib/Topology/Basic.lean | 2 +- .../Topology/Category/TopCat/Limits/Basic.lean | 4 ++-- .../Category/TopCat/Limits/Products.lean | 10 +++++----- .../Category/TopCat/Limits/Pullbacks.lean | 4 ++-- Mathlib/Topology/Category/TopCat/Opens.lean | 2 +- Mathlib/Topology/ContinuousMap/Algebra.lean | 2 +- .../Topology/ContinuousMap/Bounded/Basic.lean | 2 +- .../Topology/ContinuousMap/ZeroAtInfty.lean | 4 ++-- Mathlib/Topology/Gluing.lean | 2 +- Mathlib/Topology/Instances/ENNReal.lean | 2 +- Mathlib/Topology/Instances/Matrix.lean | 6 +++--- Mathlib/Topology/List.lean | 2 +- Mathlib/Topology/LocalAtTarget.lean | 2 +- Mathlib/Topology/MetricSpace/Completion.lean | 2 +- Mathlib/Topology/MetricSpace/PiNat.lean | 2 +- .../MetricSpace/Pseudo/Constructions.lean | 4 ++-- Mathlib/Topology/Order/DenselyOrdered.lean | 4 ++-- Mathlib/Topology/Order/Lattice.lean | 4 ++-- Mathlib/Topology/PartialHomeomorph.lean | 2 +- .../SheafCondition/PairwiseIntersections.lean | 4 ++-- Mathlib/Topology/Sheaves/Stalks.lean | 6 +++--- .../UniformSpace/AbstractCompletion.lean | 2 +- Mathlib/Topology/VectorBundle/Basic.lean | 2 +- .../Topology/VectorBundle/Constructions.lean | 2 +- MathlibTest/TypeCheck.lean | 2 +- 216 files changed, 368 insertions(+), 368 deletions(-) diff --git a/Archive/Sensitivity.lean b/Archive/Sensitivity.lean index ab52f935c6633..7f94a65f75cbd 100644 --- a/Archive/Sensitivity.lean +++ b/Archive/Sensitivity.lean @@ -368,7 +368,7 @@ open Classical in subspace of `V (m+1)` spanned by the corresponding basis vectors non-trivially intersects the range of `g m`. -/ theorem exists_eigenvalue (H : Set (Q m.succ)) (hH : Card H ≥ 2 ^ m + 1) : - ∃ y ∈ Span (e '' H) ⊓ range (g m), y ≠ (0 : _) := by + ∃ y ∈ Span (e '' H) ⊓ range (g m), y ≠ 0 := by let W := Span (e '' H) let img := range (g m) suffices 0 < dim (W ⊓ img) by @@ -408,7 +408,7 @@ theorem huang_degree_theorem (H : Set (Q m.succ)) (hH : Card H ≥ 2 ^ m + 1) : rw [Finsupp.mem_support_iff] at p_in rw [Set.mem_toFinset] exact (dualBases_e_ε _).mem_of_mem_span y_mem_H p p_in - obtain ⟨q, H_max⟩ : ∃ q : Q m.succ, ∀ q' : Q m.succ, |(ε q' : _) y| ≤ |ε q y| := + obtain ⟨q, H_max⟩ : ∃ q : Q m.succ, ∀ q' : Q m.succ, |(ε q' :) y| ≤ |ε q y| := Finite.exists_max _ have H_q_pos : 0 < |ε q y| := by contrapose! y_ne diff --git a/Counterexamples/Girard.lean b/Counterexamples/Girard.lean index 2045588c13e53..16ea6890ecf9a 100644 --- a/Counterexamples/Girard.lean +++ b/Counterexamples/Girard.lean @@ -41,7 +41,7 @@ theorem girard.{u} (pi : (Type u → Type u) → Type u) let τ (T : Set (Set U)) : U := lam (G T) let σ (S : U) : Set (Set U) := app S U τ have στ : ∀ {s S}, s ∈ σ (τ S) ↔ {x | τ (σ x) ∈ s} ∈ S := fun {s S} => - iff_of_eq (congr_arg (fun f : F U => s ∈ f τ) (beta (G S) U) : _) + iff_of_eq (congr_arg (fun f : F U => s ∈ f τ) (beta (G S) U) :) let ω : Set (Set U) := {p | ∀ x, p ∈ σ x → x ∈ p} let δ (S : Set (Set U)) := ∀ p, p ∈ S → τ S ∈ p have : δ ω := fun _p d => d (τ ω) <| στ.2 fun x h => d (τ (σ x)) (στ.2 h) diff --git a/Mathlib/Algebra/Algebra/NonUnitalHom.lean b/Mathlib/Algebra/Algebra/NonUnitalHom.lean index 3ab73048ff9a8..88d007dcb7961 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalHom.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalHom.lean @@ -474,7 +474,7 @@ lemma coe_restrictScalars' (f : A →ₙₐ[S] B) : (f.restrictScalars R : A → theorem restrictScalars_injective : Function.Injective (restrictScalars R : (A →ₙₐ[S] B) → A →ₙₐ[R] B) := - fun _ _ h ↦ ext (congr_fun h : _) + fun _ _ h ↦ ext (congr_fun h :) end NonUnitalAlgHom diff --git a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean index bea24677990a7..f4ac70dcbba21 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean @@ -467,7 +467,7 @@ theorem coe_codRestrict (f : F) (S : NonUnitalSubalgebra R B) (hf : ∀ x, f x theorem injective_codRestrict (f : F) (S : NonUnitalSubalgebra R B) (hf : ∀ x : A, f x ∈ S) : Function.Injective (NonUnitalAlgHom.codRestrict f S hf) ↔ Function.Injective f := - ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy : _)⟩ + ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy :)⟩ /-- Restrict the codomain of an `NonUnitalAlgHom` `f` to `f.range`. diff --git a/Mathlib/Algebra/Algebra/RestrictScalars.lean b/Mathlib/Algebra/Algebra/RestrictScalars.lean index ba1e455fa5482..20a38263fd74c 100644 --- a/Mathlib/Algebra/Algebra/RestrictScalars.lean +++ b/Mathlib/Algebra/Algebra/RestrictScalars.lean @@ -124,7 +124,7 @@ instance RestrictScalars.opModule [Module Sᵐᵒᵖ M] : Module Rᵐᵒᵖ (Res instance RestrictScalars.isCentralScalar [Module S M] [Module Sᵐᵒᵖ M] [IsCentralScalar S M] : IsCentralScalar R (RestrictScalars R S M) where - op_smul_eq_smul r _x := (op_smul_eq_smul (algebraMap R S r) (_ : M) : _) + op_smul_eq_smul r _x := (op_smul_eq_smul (algebraMap R S r) (_ : M) :) /-- The `R`-algebra homomorphism from the original coefficient algebra `S` to endomorphisms of `RestrictScalars R S M`. diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index 20f8a381665c2..edf843664e624 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -520,7 +520,7 @@ theorem coe_codRestrict (f : A →ₐ[R] B) (S : Subalgebra R B) (hf : ∀ x, f theorem injective_codRestrict (f : A →ₐ[R] B) (S : Subalgebra R B) (hf : ∀ x, f x ∈ S) : Function.Injective (f.codRestrict S hf) ↔ Function.Injective f := - ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy : _)⟩ + ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy :)⟩ /-- Restrict the codomain of an `AlgHom` `f` to `f.range`. @@ -819,7 +819,7 @@ noncomputable def botEquivOfInjective (h : Function.Injective (algebraMap R A)) (⊥ : Subalgebra R A) ≃ₐ[R] R := AlgEquiv.symm <| AlgEquiv.ofBijective (Algebra.ofId R _) - ⟨fun _x _y hxy => h (congr_arg Subtype.val hxy : _), fun ⟨_y, x, hx⟩ => ⟨x, Subtype.eq hx⟩⟩ + ⟨fun _x _y hxy => h (congr_arg Subtype.val hxy :), fun ⟨_y, x, hx⟩ => ⟨x, Subtype.eq hx⟩⟩ /-- The bottom subalgebra is isomorphic to the field. -/ @[simps! symm_apply] @@ -995,7 +995,7 @@ instance isScalarTower_left [SMul α β] [SMul A α] [SMul A β] [IsScalarTower instance isScalarTower_mid {R S T : Type*} [CommSemiring R] [Semiring S] [AddCommMonoid T] [Algebra R S] [Module R T] [Module S T] [IsScalarTower R S T] (S' : Subalgebra R S) : IsScalarTower R S' T := - ⟨fun _x y _z => (smul_assoc _ (y : S) _ : _)⟩ + ⟨fun _x y _z => smul_assoc _ (y : S) _⟩ instance [SMul A α] [FaithfulSMul A α] (S : Subalgebra R A) : FaithfulSMul S α := inferInstanceAs (FaithfulSMul S.toSubsemiring α) diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean b/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean index c34c387d80077..ebe721d031b4f 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Tower.lean @@ -58,7 +58,7 @@ variable [Algebra R A] [IsScalarTower R S A] instance subalgebra' (S₀ : Subalgebra R S) : IsScalarTower R S₀ A := @IsScalarTower.of_algebraMap_eq R S₀ A _ _ _ _ _ _ fun _ ↦ - (IsScalarTower.algebraMap_apply R S A _ : _) + (IsScalarTower.algebraMap_apply R S A _ :) end Semiring diff --git a/Mathlib/Algebra/Algebra/Tower.lean b/Mathlib/Algebra/Algebra/Tower.lean index ba6b199b4aad6..16188b3a49e9b 100644 --- a/Mathlib/Algebra/Algebra/Tower.lean +++ b/Mathlib/Algebra/Algebra/Tower.lean @@ -200,7 +200,7 @@ theorem coe_restrictScalars' (f : A →ₐ[S] B) : (restrictScalars R f : A → theorem restrictScalars_injective : Function.Injective (restrictScalars R : (A →ₐ[S] B) → A →ₐ[R] B) := fun _ _ h => - AlgHom.ext (AlgHom.congr_fun h : _) + AlgHom.ext (AlgHom.congr_fun h :) end AlgHom @@ -223,7 +223,7 @@ theorem coe_restrictScalars' (f : A ≃ₐ[S] B) : (restrictScalars R f : A → theorem restrictScalars_injective : Function.Injective (restrictScalars R : (A ≃ₐ[S] B) → A ≃ₐ[R] B) := fun _ _ h => - AlgEquiv.ext (AlgEquiv.congr_fun h : _) + AlgEquiv.ext (AlgEquiv.congr_fun h :) end AlgEquiv diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean index 9547c9239b0fc..cd94fb824ae02 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean @@ -63,7 +63,7 @@ variable {M₁ M₂ M₃ M₄} @[simp] lemma tensorObj_map_tmul {X Y : Cᵒᵖ} (f : X ⟶ Y) (m₁ : M₁.obj X) (m₂ : M₂.obj X) : - DFunLike.coe (α := (M₁.obj X ⊗ M₂.obj X : _)) + DFunLike.coe (α := (M₁.obj X ⊗ M₂.obj X :)) (β := fun _ ↦ (ModuleCat.restrictScalars (R.map f).hom).obj (M₁.obj Y ⊗ M₂.obj Y)) ((tensorObj M₁ M₂).map f).hom (m₁ ⊗ₜ[R.obj X] m₂) = M₁.map f m₁ ⊗ₜ[R.obj Y] M₂.map f m₂ := rfl diff --git a/Mathlib/Algebra/Category/Ring/Constructions.lean b/Mathlib/Algebra/Category/Ring/Constructions.lean index 8bf3814986f64..19a99274584c3 100644 --- a/Mathlib/Algebra/Category/Ring/Constructions.lean +++ b/Mathlib/Algebra/Category/Ring/Constructions.lean @@ -283,7 +283,7 @@ def equalizerFork : Fork f g := def equalizerForkIsLimit : IsLimit (equalizerFork f g) := by fapply Fork.IsLimit.mk' intro s - use ofHom <| s.ι.hom.codRestrict _ fun x => (ConcreteCategory.congr_hom s.condition x : _) + use ofHom <| s.ι.hom.codRestrict _ fun x => (ConcreteCategory.congr_hom s.condition x :) constructor · ext rfl @@ -327,7 +327,7 @@ instance equalizer_ι_is_local_ring_hom' (F : WalkingParallelPairᵒᵖ ⥤ Comm have : _ = limit.π F (walkingParallelPairOpEquiv.functor.obj _) := (limit.isoLimitCone_inv_π ⟨_, IsLimit.whiskerEquivalence (limit.isLimit F) walkingParallelPairOpEquiv⟩ - WalkingParallelPair.zero : _) + WalkingParallelPair.zero :) erw [← this] -- note: this was not needed before https://github.com/leanprover-community/mathlib4/pull/19757 haveI : IsLocalHom (limit.π (walkingParallelPairOpEquiv.functor ⋙ F) zero).hom := by @@ -370,8 +370,8 @@ def pullbackConeIsLimit {A B C : CommRingCat.{u}} (f : A ⟶ C) (g : B ⟶ C) : · intro s m e₁ e₂ refine hom_ext <| RingHom.ext fun (x : s.pt) => Subtype.ext ?_ change (m x).1 = (_, _) - have eq1 := (congr_arg (fun f : s.pt →+* A => f x) (congrArg Hom.hom e₁) : _) - have eq2 := (congr_arg (fun f : s.pt →+* B => f x) (congrArg Hom.hom e₂) : _) + have eq1 := (congr_arg (fun f : s.pt →+* A => f x) (congrArg Hom.hom e₁) :) + have eq2 := (congr_arg (fun f : s.pt →+* B => f x) (congrArg Hom.hom e₂) :) rw [← eq1, ← eq2] rfl diff --git a/Mathlib/Algebra/Category/Ring/Instances.lean b/Mathlib/Algebra/Category/Ring/Instances.lean index 4fcf3b005de52..cc50fa4a7692e 100644 --- a/Mathlib/Algebra/Category/Ring/Instances.lean +++ b/Mathlib/Algebra/Category/Ring/Instances.lean @@ -34,7 +34,7 @@ instance Localization.epi {R : Type*} [CommRing R] (M : Submonoid R) : IsLocalization.epi M _ instance Localization.epi' {R : CommRingCat} (M : Submonoid R) : - @Epi CommRingCat _ R _ (CommRingCat.ofHom <| algebraMap R <| Localization M : _) := by + @Epi CommRingCat _ R _ (CommRingCat.ofHom <| algebraMap R <| Localization M :) := by rcases R with ⟨α, str⟩ exact IsLocalization.epi M _ diff --git a/Mathlib/Algebra/GCDMonoid/IntegrallyClosed.lean b/Mathlib/Algebra/GCDMonoid/IntegrallyClosed.lean index c528c210ffca8..6a53eb7e53fbd 100644 --- a/Mathlib/Algebra/GCDMonoid/IntegrallyClosed.lean +++ b/Mathlib/Algebra/GCDMonoid/IntegrallyClosed.lean @@ -40,6 +40,6 @@ instance (priority := 100) GCDMonoid.toIsIntegrallyClosed exact (dvd_gcd this <| dvd_refl y).trans (gcd_pow_left_dvd_pow_gcd.trans <| pow_dvd_pow_of_dvd (isUnit_iff_dvd_one.1 hg) _) - use x * (this.unit⁻¹ : _) + use x * (this.unit⁻¹ :) erw [map_mul, ← Units.coe_map_inv, eq_comm, Units.eq_mul_inv_iff_mul_eq] exact he diff --git a/Mathlib/Algebra/GradedMonoid.lean b/Mathlib/Algebra/GradedMonoid.lean index a4aa2463b4229..85e9bb219662e 100644 --- a/Mathlib/Algebra/GradedMonoid.lean +++ b/Mathlib/Algebra/GradedMonoid.lean @@ -403,11 +403,11 @@ theorem List.dProd_nil (fι : α → ι) (fA : ∀ a, A (fι a)) : (List.nil : List α).dProd fι fA = GradedMonoid.GOne.one := rfl --- the `( : _)` in this lemma statement results in the type on the RHS not being unfolded, which +-- the `( :)` in this lemma statement results in the type on the RHS not being unfolded, which -- is nicer in the goal view. @[simp] theorem List.dProd_cons (fι : α → ι) (fA : ∀ a, A (fι a)) (a : α) (l : List α) : - (a :: l).dProd fι fA = (GradedMonoid.GMul.mul (fA a) (l.dProd fι fA) : _) := + (a :: l).dProd fι fA = (GradedMonoid.GMul.mul (fA a) (l.dProd fι fA) :) := rfl theorem GradedMonoid.mk_list_dProd (l : List α) (fι : α → ι) (fA : ∀ a, A (fι a)) : diff --git a/Mathlib/Algebra/Group/Action/Units.lean b/Mathlib/Algebra/Group/Action/Units.lean index f2a6ef61171a5..5c32fade58481 100644 --- a/Mathlib/Algebra/Group/Action/Units.lean +++ b/Mathlib/Algebra/Group/Action/Units.lean @@ -46,20 +46,20 @@ instance [Monoid M] [SMul M α] [FaithfulSMul M α] : FaithfulSMul Mˣ α where @[to_additive] instance instMulAction [Monoid M] [MulAction M α] : MulAction Mˣ α where - one_smul := (one_smul M : _) + one_smul := one_smul M mul_smul m n := mul_smul (m : M) n @[to_additive] instance smulCommClass_left [Monoid M] [SMul M α] [SMul N α] [SMulCommClass M N α] : - SMulCommClass Mˣ N α where smul_comm m n := (smul_comm (m : M) n : _) + SMulCommClass Mˣ N α where smul_comm m n := smul_comm (m : M) n @[to_additive] instance smulCommClass_right [Monoid N] [SMul M α] [SMul N α] [SMulCommClass M N α] : - SMulCommClass M Nˣ α where smul_comm m n := (smul_comm m (n : N) : _) + SMulCommClass M Nˣ α where smul_comm m n := smul_comm m (n : N) @[to_additive] instance [Monoid M] [SMul M N] [SMul M α] [SMul N α] [IsScalarTower M N α] : - IsScalarTower Mˣ N α where smul_assoc m n := (smul_assoc (m : M) n : _) + IsScalarTower Mˣ N α where smul_assoc m n := smul_assoc (m : M) n /-! ### Action of a group `G` on units of `M` -/ @@ -102,7 +102,7 @@ instance isScalarTower' [SMul G H] [Group G] [Group H] [Monoid M] [MulAction G M @[to_additive "Transfer `VAddAssocClass G M α` to `VAddAssocClass G (AddUnits M) α`."] instance isScalarTower'_left [Group G] [Monoid M] [MulAction G M] [SMul M α] [SMul G α] [SMulCommClass G M M] [IsScalarTower G M M] [IsScalarTower G M α] : - IsScalarTower G Mˣ α where smul_assoc g m := (smul_assoc g (m : M) : _) + IsScalarTower G Mˣ α where smul_assoc g m := smul_assoc g (m : M) -- Just to prove this transfers a particularly useful instance. example [Monoid M] [Monoid N] [MulAction M N] [SMulCommClass M N N] [IsScalarTower M N N] : diff --git a/Mathlib/Algebra/Group/Opposite.lean b/Mathlib/Algebra/Group/Opposite.lean index 527a665d95d21..5d91ad7cacb87 100644 --- a/Mathlib/Algebra/Group/Opposite.lean +++ b/Mathlib/Algebra/Group/Opposite.lean @@ -556,6 +556,6 @@ theorem AddMonoidHom.mul_op_ext {α β} [AddZeroClass α] [AddZeroClass β] (f g f.comp (opAddEquiv : α ≃+ αᵐᵒᵖ).toAddMonoidHom = g.comp (opAddEquiv : α ≃+ αᵐᵒᵖ).toAddMonoidHom) : f = g := - AddMonoidHom.ext <| MulOpposite.rec' fun x => (DFunLike.congr_fun h : _) x + AddMonoidHom.ext <| MulOpposite.rec' fun x => (DFunLike.congr_fun h :) x end Ext diff --git a/Mathlib/Algebra/Group/Pi/Lemmas.lean b/Mathlib/Algebra/Group/Pi/Lemmas.lean index 1d2924faf728b..e9dd7d38a4ff0 100644 --- a/Mathlib/Algebra/Group/Pi/Lemmas.lean +++ b/Mathlib/Algebra/Group/Pi/Lemmas.lean @@ -69,7 +69,7 @@ def Pi.mulHom {γ : Type w} [∀ i, Mul (f i)] [Mul γ] (g : ∀ i, γ →ₙ* f theorem Pi.mulHom_injective {γ : Type w} [Nonempty I] [∀ i, Mul (f i)] [Mul γ] (g : ∀ i, γ →ₙ* f i) (hg : ∀ i, Function.Injective (g i)) : Function.Injective (Pi.mulHom g) := fun _ _ h => let ⟨i⟩ := ‹Nonempty I› - hg i ((funext_iff.mp h : _) i) + hg i ((funext_iff.mp h :) i) /-- A family of monoid homomorphisms `f a : γ →* β a` defines a monoid homomorphism `Pi.monoidHom f : γ →* Π a, β a` given by `Pi.monoidHom f x b = f b x`. -/ diff --git a/Mathlib/Algebra/Group/Prod.lean b/Mathlib/Algebra/Group/Prod.lean index 739752b4ea517..de72f571ab908 100644 --- a/Mathlib/Algebra/Group/Prod.lean +++ b/Mathlib/Algebra/Group/Prod.lean @@ -697,7 +697,7 @@ def embedProduct (α : Type*) [Monoid α] : αˣ →* α × αᵐᵒᵖ where @[to_additive] theorem embedProduct_injective (α : Type*) [Monoid α] : Function.Injective (embedProduct α) := - fun _ _ h => Units.ext <| (congr_arg Prod.fst h : _) + fun _ _ h => Units.ext <| (congr_arg Prod.fst h :) end Units diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index a643434cac8a2..8852316886684 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -1000,18 +1000,18 @@ instance smul [SMul M' α] (S : Submonoid M') : SMul S α := @[to_additive] instance smulCommClass_left [SMul M' β] [SMul α β] [SMulCommClass M' α β] (S : Submonoid M') : SMulCommClass S α β := - ⟨fun a _ _ => (smul_comm (a : M') _ _ : _)⟩ + ⟨fun a _ _ => smul_comm (a : M') _ _⟩ @[to_additive] instance smulCommClass_right [SMul α β] [SMul M' β] [SMulCommClass α M' β] (S : Submonoid M') : SMulCommClass α S β := - ⟨fun a s => (smul_comm a (s : M') : _)⟩ + ⟨fun a s => smul_comm a (s : M')⟩ /-- Note that this provides `IsScalarTower S M' M'` which is needed by `SMulMulAssoc`. -/ instance isScalarTower [SMul α β] [SMul M' α] [SMul M' β] [IsScalarTower M' α β] (S : Submonoid M') : IsScalarTower S α β := - ⟨fun a => (smul_assoc (a : M') : _)⟩ + ⟨fun a => smul_assoc (a : M')⟩ section SMul variable [SMul M' α] {S : Submonoid M'} diff --git a/Mathlib/Algebra/Lie/BaseChange.lean b/Mathlib/Algebra/Lie/BaseChange.lean index d6be0876fe3d9..86e3b96fc02af 100644 --- a/Mathlib/Algebra/Lie/BaseChange.lean +++ b/Mathlib/Algebra/Lie/BaseChange.lean @@ -135,7 +135,7 @@ variable [CommRing A] [LieAlgebra A L] instance lieAlgebra [CommRing R] [Algebra R A] : LieAlgebra R (RestrictScalars R A L) where lie_smul t x y := (lie_smul (algebraMap R A t) (RestrictScalars.addEquiv R A L x) - (RestrictScalars.addEquiv R A L y) : _) + (RestrictScalars.addEquiv R A L y) :) end RestrictScalars diff --git a/Mathlib/Algebra/Module/Equiv/Basic.lean b/Mathlib/Algebra/Module/Equiv/Basic.lean index a22205a1e0f06..b0228d7304c79 100644 --- a/Mathlib/Algebra/Module/Equiv/Basic.lean +++ b/Mathlib/Algebra/Module/Equiv/Basic.lean @@ -49,7 +49,7 @@ def restrictScalars (f : M ≃ₗ[S] M₂) : M ≃ₗ[R] M₂ := theorem restrictScalars_injective : Function.Injective (restrictScalars R : (M ≃ₗ[S] M₂) → M ≃ₗ[R] M₂) := fun _ _ h ↦ - ext (LinearEquiv.congr_fun h : _) + ext (LinearEquiv.congr_fun h :) @[simp] theorem restrictScalars_inj (f g : M ≃ₗ[S] M₂) : diff --git a/Mathlib/Algebra/Module/LinearMap/Defs.lean b/Mathlib/Algebra/Module/LinearMap/Defs.lean index d4c25f58c52fb..7041673c0691f 100644 --- a/Mathlib/Algebra/Module/LinearMap/Defs.lean +++ b/Mathlib/Algebra/Module/LinearMap/Defs.lean @@ -427,7 +427,7 @@ theorem restrictScalars_apply (fₗ : M →ₗ[S] M₂) (x) : restrictScalars R theorem restrictScalars_injective : Function.Injective (restrictScalars R : (M →ₗ[S] M₂) → M →ₗ[R] M₂) := fun _ _ h ↦ - ext (LinearMap.congr_fun h : _) + ext (LinearMap.congr_fun h :) @[simp] theorem restrictScalars_inj (fₗ gₗ : M →ₗ[S] M₂) : @@ -570,7 +570,7 @@ instance CompatibleSMul.intModule {S : Type*} [Semiring S] [Module S M] [Module instance CompatibleSMul.units {R S : Type*} [Monoid R] [MulAction R M] [MulAction R M₂] [Semiring S] [Module S M] [Module S M₂] [CompatibleSMul M M₂ R S] : CompatibleSMul M M₂ Rˣ S := - ⟨fun fₗ c x ↦ (CompatibleSMul.map_smul fₗ (c : R) x : _)⟩ + ⟨fun fₗ c x ↦ (CompatibleSMul.map_smul fₗ (c : R) x :)⟩ end AddCommGroup diff --git a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean index 7e3e8206620a1..b44b61b98fe6a 100644 --- a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean +++ b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean @@ -1233,7 +1233,7 @@ theorem mkOfAlgebra {R S S' : Type*} [CommRing R] [CommRing S] [CommRing S'] [Al simp_rw [Submonoid.smul_def, Algebra.smul_def] at e exact (h₁ x x.2).mul_left_cancel e · intro a - refine ⟨((h₁ x x.2).unit⁻¹ : _) * a, ?_⟩ + refine ⟨((h₁ x x.2).unit⁻¹ :) * a, ?_⟩ rw [Module.algebraMap_end_apply, Algebra.smul_def, ← mul_assoc, IsUnit.mul_val_inv, one_mul] · exact h₂ · intros x y diff --git a/Mathlib/Algebra/Module/Pi.lean b/Mathlib/Algebra/Module/Pi.lean index 23c86123bb947..944e5906eb762 100644 --- a/Mathlib/Algebra/Module/Pi.lean +++ b/Mathlib/Algebra/Module/Pi.lean @@ -26,7 +26,7 @@ namespace Pi theorem _root_.IsSMulRegular.pi {α : Type*} [∀ i, SMul α <| f i] {k : α} (hk : ∀ i, IsSMulRegular (f i) k) : IsSMulRegular (∀ i, f i) k := fun _ _ h => - funext fun i => hk i (congr_fun h i : _) + funext fun i => hk i (congr_fun h i :) instance smulWithZero (α) [Zero α] [∀ i, Zero (f i)] [∀ i, SMulWithZero α (f i)] : SMulWithZero α (∀ i, f i) := diff --git a/Mathlib/Algebra/Module/Submodule/Basic.lean b/Mathlib/Algebra/Module/Submodule/Basic.lean index e6ab0afbfd51c..1e3b2839af13e 100644 --- a/Mathlib/Algebra/Module/Submodule/Basic.lean +++ b/Mathlib/Algebra/Module/Submodule/Basic.lean @@ -99,7 +99,7 @@ instance [VAdd M α] : VAdd p α := p.toAddSubmonoid.vadd instance vaddCommClass [VAdd M β] [VAdd α β] [VAddCommClass M α β] : VAddCommClass p α β := - ⟨fun a => (vadd_comm (a : M) : _)⟩ + ⟨fun a => vadd_comm (a : M)⟩ instance [VAdd M α] [FaithfulVAdd M α] : FaithfulVAdd p α := ⟨fun h => Subtype.ext <| eq_of_vadd_eq_vadd h⟩ diff --git a/Mathlib/Algebra/Module/Submodule/Defs.lean b/Mathlib/Algebra/Module/Submodule/Defs.lean index 572cdc0af7b5b..985489a5a1fbe 100644 --- a/Mathlib/Algebra/Module/Submodule/Defs.lean +++ b/Mathlib/Algebra/Module/Submodule/Defs.lean @@ -288,7 +288,7 @@ theorem mem_toAddSubgroup : x ∈ p.toAddSubgroup ↔ x ∈ p := Iff.rfl theorem toAddSubgroup_injective : Injective (toAddSubgroup : Submodule R M → AddSubgroup M) - | _, _, h => SetLike.ext (SetLike.ext_iff.1 h : _) + | _, _, h => SetLike.ext (SetLike.ext_iff.1 h :) @[simp] theorem toAddSubgroup_inj : p.toAddSubgroup = p'.toAddSubgroup ↔ p = p' := diff --git a/Mathlib/Algebra/Module/Submodule/RestrictScalars.lean b/Mathlib/Algebra/Module/Submodule/RestrictScalars.lean index 54f609912e963..6cda15b8f5f30 100644 --- a/Mathlib/Algebra/Module/Submodule/RestrictScalars.lean +++ b/Mathlib/Algebra/Module/Submodule/RestrictScalars.lean @@ -55,7 +55,7 @@ variable (R M) theorem restrictScalars_injective : Function.Injective (restrictScalars S : Submodule R M → Submodule S M) := fun _ _ h => - ext <| Set.ext_iff.1 (SetLike.ext'_iff.1 h : _) + ext <| Set.ext_iff.1 (SetLike.ext'_iff.1 h :) @[simp] theorem restrictScalars_inj {V₁ V₂ : Submodule R M} : diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index c7ce5c683b548..6142c7d5ef137 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -501,7 +501,7 @@ instance IsTorsionBySet.isScalarTower (hM : IsTorsionBySet R M I) @IsScalarTower S (R ⧸ I) M _ (IsTorsionBySet.module hM).toSMul _ := -- Porting note: still needed to be fed the Module R / I M instance @IsScalarTower.mk S (R ⧸ I) M _ (IsTorsionBySet.module hM).toSMul _ - (fun b d x => Quotient.inductionOn' d fun c => (smul_assoc b c x : _)) + (fun b d x => Quotient.inductionOn' d fun c => (smul_assoc b c x :)) /-- An `(R ⧸ Ideal.span {r})`-module is an `R`-module for which `IsTorsionBy R M r`. -/ abbrev IsTorsionBy.module (hM : IsTorsionBy R M r) : Module (R ⧸ Ideal.span {r}) M := diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index 1e0a8e01e33eb..a0db55e090c4b 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -369,7 +369,7 @@ def liftMagma [Module k A] [IsScalarTower k A A] [SMulCommClass k A A] : (Multiplicative G →ₙ* A) ≃ (k[G] →ₙₐ[k] A) := { (MonoidAlgebra.liftMagma k : (Multiplicative G →ₙ* A) ≃ (_ →ₙₐ[k] A)) with toFun := fun f => - { (MonoidAlgebra.liftMagma k f : _) with + { (MonoidAlgebra.liftMagma k f :) with toFun := fun a => sum a fun m t => t • f (Multiplicative.ofAdd m) } invFun := fun F => F.toMulHom.comp (ofMagma k G) } diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index da1c6d0c0a369..379ff57f2cd6b 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -993,7 +993,7 @@ theorem liftNC_mul {g_hom : Type*} (f : k →+* R) (g : g_hom) (a b : k[G]) (h_comm : ∀ {x y}, y ∈ a.support → Commute (f (b x)) (g <| Multiplicative.ofAdd y)) : liftNC (f : k →+ R) g (a * b) = liftNC (f : k →+ R) g a * liftNC (f : k →+ R) g b := - (MonoidAlgebra.liftNC_mul f g _ _ @h_comm : _) + MonoidAlgebra.liftNC_mul f g _ _ @h_comm end Mul @@ -1013,7 +1013,7 @@ theorem one_def : (1 : k[G]) = single 0 1 := theorem liftNC_one {g_hom : Type*} [FunLike g_hom (Multiplicative G) R] [OneHomClass g_hom (Multiplicative G) R] (f : k →+* R) (g : g_hom) : liftNC (f : k →+ R) g 1 = 1 := - (MonoidAlgebra.liftNC_one f g : _) + MonoidAlgebra.liftNC_one f g end One diff --git a/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean b/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean index 2d06dc8ac12c6..81771c479c9ed 100644 --- a/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean +++ b/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean @@ -96,7 +96,7 @@ theorem AddMonoidAlgebra.toDirectSum_toAddMonoidAlgebra (f : AddMonoidAlgebra M @[simp] theorem DirectSum.toAddMonoidAlgebra_toDirectSum (f : ⨁ _ : ι, M) : f.toAddMonoidAlgebra.toDirectSum = f := - (DFinsupp.toFinsupp_toDFinsupp (show Π₀ _ : ι, M from f) : _) + (DFinsupp.toFinsupp_toDFinsupp (show Π₀ _ : ι, M from f) :) end diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index 5080eada19bc1..444676431d13e 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -250,7 +250,7 @@ def sumAlgEquiv : MvPolynomial (S₁ ⊕ S₂) R ≃ₐ[R] MvPolynomial S₁ (Mv { sumRingEquiv R S₁ S₂ with commutes' := by intro r - have A : algebraMap R (MvPolynomial S₁ (MvPolynomial S₂ R)) r = (C (C r) : _) := rfl + have A : algebraMap R (MvPolynomial S₁ (MvPolynomial S₂ R)) r = (C (C r) :) := rfl have B : algebraMap R (MvPolynomial (S₁ ⊕ S₂) R) r = C r := rfl simp only [sumRingEquiv, mvPolynomialEquivMvPolynomial, Equiv.toFun_as_coe, Equiv.coe_fn_mk, B, sumToIter_C, A] } diff --git a/Mathlib/Algebra/Order/Interval/Set/Instances.lean b/Mathlib/Algebra/Order/Interval/Set/Instances.lean index 4624971afef4b..06d73380d901f 100644 --- a/Mathlib/Algebra/Order/Interval/Set/Instances.lean +++ b/Mathlib/Algebra/Order/Interval/Set/Instances.lean @@ -267,9 +267,9 @@ instance cancelMonoid {α : Type*} [StrictOrderedRing α] [IsDomain α] : CancelMonoid (Ioc (0 : α) 1) := { Set.Ioc.monoid with mul_left_cancel := fun a _ _ h => - Subtype.ext <| mul_left_cancel₀ a.prop.1.ne' <| (congr_arg Subtype.val h : _) + Subtype.ext <| mul_left_cancel₀ a.prop.1.ne' <| (congr_arg Subtype.val h :) mul_right_cancel := fun _ b _ h => - Subtype.ext <| mul_right_cancel₀ b.prop.1.ne' <| (congr_arg Subtype.val h : _) } + Subtype.ext <| mul_right_cancel₀ b.prop.1.ne' <| (congr_arg Subtype.val h :) } instance cancelCommMonoid {α : Type*} [StrictOrderedCommRing α] [IsDomain α] : CancelCommMonoid (Ioc (0 : α) 1) := diff --git a/Mathlib/Algebra/Ring/Subring/Defs.lean b/Mathlib/Algebra/Ring/Subring/Defs.lean index 3b201ab0ecd61..321e09cc9aa05 100644 --- a/Mathlib/Algebra/Ring/Subring/Defs.lean +++ b/Mathlib/Algebra/Ring/Subring/Defs.lean @@ -199,13 +199,13 @@ theorem copy_eq (S : Subring R) (s : Set R) (hs : s = ↑S) : S.copy s hs = S := SetLike.coe_injective hs theorem toSubsemiring_injective : Function.Injective (toSubsemiring : Subring R → Subsemiring R) - | _, _, h => ext (SetLike.ext_iff.mp h : _) + | _, _, h => ext (SetLike.ext_iff.mp h :) theorem toAddSubgroup_injective : Function.Injective (toAddSubgroup : Subring R → AddSubgroup R) - | _, _, h => ext (SetLike.ext_iff.mp h : _) + | _, _, h => ext (SetLike.ext_iff.mp h :) theorem toSubmonoid_injective : Function.Injective (fun s : Subring R => s.toSubmonoid) - | _, _, h => ext (SetLike.ext_iff.mp h : _) + | _, _, h => ext (SetLike.ext_iff.mp h :) /-- Construct a `Subring R` from a set `s`, a submonoid `sm`, and an additive subgroup `sa` such that `x ∈ s ↔ x ∈ sm ↔ x ∈ sa`. -/ diff --git a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean index 3fe12b9558589..c6270059e4f28 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean @@ -161,11 +161,11 @@ theorem copy_eq (S : Subsemiring R) (s : Set R) (hs : s = ↑S) : S.copy s hs = SetLike.coe_injective hs theorem toSubmonoid_injective : Function.Injective (toSubmonoid : Subsemiring R → Submonoid R) - | _, _, h => ext (SetLike.ext_iff.mp h : _) + | _, _, h => ext (SetLike.ext_iff.mp h :) theorem toAddSubmonoid_injective : Function.Injective (toAddSubmonoid : Subsemiring R → AddSubmonoid R) - | _, _, h => ext (SetLike.ext_iff.mp h : _) + | _, _, h => ext (SetLike.ext_iff.mp h :) /-- Construct a `Subsemiring R` from a set `s`, a submonoid `sm`, and an additive submonoid `sa` such that `x ∈ s ↔ x ∈ sm ↔ x ∈ sa`. -/ diff --git a/Mathlib/Algebra/RingQuot.lean b/Mathlib/Algebra/RingQuot.lean index fb0556615bab7..468b97fb7ad6c 100644 --- a/Mathlib/Algebra/RingQuot.lean +++ b/Mathlib/Algebra/RingQuot.lean @@ -412,7 +412,7 @@ theorem ringQuot_ext [Semiring T] {r : R → R → Prop} (f g : RingQuot r →+* (w : f.comp (mkRingHom r) = g.comp (mkRingHom r)) : f = g := by ext x rcases mkRingHom_surjective r x with ⟨x, rfl⟩ - exact (RingHom.congr_fun w x : _) + exact (RingHom.congr_fun w x :) variable [Semiring T] diff --git a/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean b/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean index cca41ea3fd0c1..7fe2b7b29227b 100644 --- a/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean +++ b/Mathlib/Algebra/Star/NonUnitalSubalgebra.lean @@ -445,7 +445,7 @@ theorem coe_codRestrict (f : F) (S : NonUnitalStarSubalgebra R B) (hf : ∀ x, f theorem injective_codRestrict (f : F) (S : NonUnitalStarSubalgebra R B) (hf : ∀ x : A, f x ∈ S) : Function.Injective (NonUnitalStarAlgHom.codRestrict f S hf) ↔ Function.Injective f := - ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy : _)⟩ + ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy :)⟩ /-- Restrict the codomain of a non-unital star algebra homomorphism `f` to `f.range`. diff --git a/Mathlib/Algebra/Star/StarAlgHom.lean b/Mathlib/Algebra/Star/StarAlgHom.lean index 3a2986c6d730c..c1f51d104dfa9 100644 --- a/Mathlib/Algebra/Star/StarAlgHom.lean +++ b/Mathlib/Algebra/Star/StarAlgHom.lean @@ -279,7 +279,7 @@ lemma coe_restrictScalars' (f : A →⋆ₙₐ[S] B) : (f.restrictScalars R : A theorem restrictScalars_injective : Function.Injective (restrictScalars R : (A →⋆ₙₐ[S] B) → A →⋆ₙₐ[R] B) := - fun _ _ h ↦ ext (DFunLike.congr_fun h : _) + fun _ _ h ↦ ext (DFunLike.congr_fun h :) end RestrictScalars diff --git a/Mathlib/Algebra/Star/Subalgebra.lean b/Mathlib/Algebra/Star/Subalgebra.lean index 7df842838e470..8761b250d94cb 100644 --- a/Mathlib/Algebra/Star/Subalgebra.lean +++ b/Mathlib/Algebra/Star/Subalgebra.lean @@ -758,7 +758,7 @@ theorem subtype_comp_codRestrict (f : A →⋆ₐ[R] B) (S : StarSubalgebra R B) theorem injective_codRestrict (f : A →⋆ₐ[R] B) (S : StarSubalgebra R B) (hf : ∀ x : A, f x ∈ S) : Function.Injective (StarAlgHom.codRestrict f S hf) ↔ Function.Injective f := - ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy : _)⟩ + ⟨fun H _x _y hxy => H <| Subtype.eq hxy, fun H _x _y hxy => H (congr_arg Subtype.val hxy :)⟩ /-- Restriction of the codomain of a `StarAlgHom` to its range. -/ def rangeRestrict (f : A →⋆ₐ[R] B) : A →⋆ₐ[R] f.range := diff --git a/Mathlib/AlgebraicGeometry/Cover/Open.lean b/Mathlib/AlgebraicGeometry/Cover/Open.lean index 7c743cdacbf51..49feb36d291ee 100644 --- a/Mathlib/AlgebraicGeometry/Cover/Open.lean +++ b/Mathlib/AlgebraicGeometry/Cover/Open.lean @@ -278,7 +278,7 @@ theorem affineBasisCover_map_range (X : Scheme.{u}) (x : X) erw [coe_comp, Set.range_comp] -- Porting note: `congr` fails to see the goal is comparing image of the same function refine congr_arg (_ '' ·) ?_ - exact (PrimeSpectrum.localization_away_comap_range (Localization.Away r) r : _) + exact (PrimeSpectrum.localization_away_comap_range (Localization.Away r) r :) theorem affineBasisCover_is_basis (X : Scheme.{u}) : TopologicalSpace.IsTopologicalBasis diff --git a/Mathlib/AlgebraicGeometry/Limits.lean b/Mathlib/AlgebraicGeometry/Limits.lean index b4f7a0106ddca..6ca38222835bb 100644 --- a/Mathlib/AlgebraicGeometry/Limits.lean +++ b/Mathlib/AlgebraicGeometry/Limits.lean @@ -115,7 +115,7 @@ instance : HasInitial Scheme.{u} := hasInitial_of_unique ∅ instance initial_isEmpty : IsEmpty (⊥_ Scheme) := - ⟨fun x => ((initial.to Scheme.empty : _).base x).elim⟩ + ⟨fun x => ((initial.to Scheme.empty :).base x).elim⟩ theorem isAffineOpen_bot (X : Scheme) : IsAffineOpen (⊥ : X.Opens) := @isAffine_of_isEmpty _ (inferInstanceAs (IsEmpty (∅ : Set X))) @@ -276,7 +276,7 @@ lemma disjoint_opensRange_sigmaι (i j : ι) (h : i ≠ j) : obtain ⟨rfl⟩ := (sigmaι_eq_iff _ _ _ _ _).mp hy cases h rfl -lemma exists_sigmaι_eq (x : (∐ f : _)) : ∃ i y, (Sigma.ι f i).base y = x := by +lemma exists_sigmaι_eq (x : (∐ f :)) : ∃ i y, (Sigma.ι f i).base y = x := by obtain ⟨i, y, e⟩ := (disjointGlueData f).ι_jointly_surjective ((sigmaIsoGlued f).hom.base x) refine ⟨i, y, (sigmaIsoGlued f).hom.isOpenEmbedding.injective ?_⟩ rwa [← Scheme.comp_base_apply, ι_sigmaIsoGlued_hom] @@ -296,7 +296,7 @@ def sigmaOpenCover : (∐ f).OpenCover where /-- The underlying topological space of the coproduct is homeomorphic to the disjoint union. -/ noncomputable -def sigmaMk : (Σ i, f i) ≃ₜ (∐ f : _) := +def sigmaMk : (Σ i, f i) ≃ₜ (∐ f :) := TopCat.homeoOfIso ((colimit.isoColimitCocone ⟨_, TopCat.sigmaCofanIsColimit _⟩).symm ≪≫ (PreservesCoproduct.iso Scheme.forgetToTop f).symm) diff --git a/Mathlib/AlgebraicGeometry/Modules/Tilde.lean b/Mathlib/AlgebraicGeometry/Modules/Tilde.lean index affc194a86b50..aa13874400ecd 100644 --- a/Mathlib/AlgebraicGeometry/Modules/Tilde.lean +++ b/Mathlib/AlgebraicGeometry/Modules/Tilde.lean @@ -182,7 +182,7 @@ namespace Tilde @[simp] theorem res_apply (U V : Opens (PrimeSpectrum.Top R)) (i : V ⟶ U) (s : (tildeInModuleCat M).obj (op U)) (x : V) : - ((tildeInModuleCat M).map i.op s).1 x = (s.1 (i x) : _) := + ((tildeInModuleCat M).map i.op s).1 x = (s.1 (i x) :) := rfl lemma smul_section_apply (r : R) (U : Opens (PrimeSpectrum.Top R)) @@ -273,7 +273,7 @@ def openToLocalization (U : Opens (PrimeSpectrum R)) (x : PrimeSpectrum R) (hx : ModuleCat.ofHom (X := (tildeInModuleCat M).obj (op U)) (Y := ModuleCat.of R (LocalizedModule x.asIdeal.primeCompl M)) - { toFun := fun s => (s.1 ⟨x, hx⟩ : _) + { toFun := fun s => (s.1 ⟨x, hx⟩ :) map_add' := fun _ _ => rfl map_smul' := fun _ _ => rfl } @@ -299,7 +299,7 @@ theorem germ_comp_stalkToFiberLinearMap (U : Opens (PrimeSpectrum.Top R)) (x) (h theorem stalkToFiberLinearMap_germ (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpectrum.Top R) (hx : x ∈ U) (s : (tildeInModuleCat M).1.obj (op U)) : (stalkToFiberLinearMap M x).hom - (TopCat.Presheaf.germ (tildeInModuleCat M) U x hx s) = (s.1 ⟨x, hx⟩ : _) := + (TopCat.Presheaf.germ (tildeInModuleCat M) U x hx s) = (s.1 ⟨x, hx⟩ :) := DFunLike.ext_iff.1 (ModuleCat.hom_ext_iff.mp (germ_comp_stalkToFiberLinearMap M U x hx)) s @[reassoc (attr := simp), elementwise (attr := simp)] diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean index c1e4acd9220c2..b930b47ba6a4c 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean @@ -116,7 +116,7 @@ instance : IsStableUnderBaseChange @IsPreimmersion := by refine .mk' fun X Y Z f g _ _ ↦ ?_ have := pullback_fst (P := @SurjectiveOnStalks) f g inferInstance constructor - let L (x : (pullback f g : _)) : { x : X × Y | f.base x.1 = g.base x.2 } := + let L (x : (pullback f g :)) : { x : X × Y | f.base x.1 = g.base x.2 } := ⟨⟨(pullback.fst f g).base x, (pullback.snd f g).base x⟩, by simp only [Set.mem_setOf, ← Scheme.comp_base_apply, pullback.condition]⟩ have : IsEmbedding L := IsEmbedding.of_comp (by fun_prop) continuous_subtype_val diff --git a/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean index b71393e088b97..79e2e54a20a2b 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean @@ -129,7 +129,7 @@ lemma isEmbedding_pullback {X Y S : Scheme.{u}} (f : X ⟶ S) (g : Y ⟶ S) [Sur (continuous_fst.1 _ ((𝒱 ijk.1).map ijk.2.1 ≫ (𝒰.pullbackCover f).map ijk.1).opensRange.2).inter (continuous_snd.1 _ ((𝒲 ijk.1).map ijk.2.2 ≫ (𝒰.pullbackCover g).map ijk.1).opensRange.2)⟩ - have : Set.range L ⊆ (iSup U : _) := by + have : Set.range L ⊆ (iSup U :) := by simp only [Scheme.Cover.pullbackCover_J, Scheme.Cover.pullbackCover_obj, Set.range_subset_iff] intro z simp only [SetLike.mem_coe, TopologicalSpace.Opens.mem_iSup, Sigma.exists, Prod.exists] diff --git a/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean b/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean index 32c4886d35bf2..d04850a4a2454 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/UniversallyClosed.lean @@ -109,7 +109,7 @@ lemma compactSpace_of_universallyClosed let Ti (i : 𝒰.J) : T.Opens := basicOpen (MvPolynomial.X i) let fT : pullback f q ⟶ T := pullback.snd f q let p : pullback f q ⟶ X := pullback.fst f q - let Z : Set (pullback f q : _) := (⨆ i, fT ⁻¹ᵁ (Ti i) ⊓ p ⁻¹ᵁ (U i) : (pullback f q).Opens)ᶜ + let Z : Set (pullback f q :) := (⨆ i, fT ⁻¹ᵁ (Ti i) ⊓ p ⁻¹ᵁ (U i) : (pullback f q).Opens)ᶜ have hZ : IsClosed Z := by simp only [Z, isClosed_compl_iff, Opens.coe_iSup, Opens.coe_inf, Opens.map_coe] exact isOpen_iUnion fun i ↦ (fT.continuous.1 _ (Ti i).2).inter (p.continuous.1 _ (U i).2) diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index b4eac11407814..754e130626539 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -46,7 +46,7 @@ protected def scheme (X : LocallyRingedSpace.{u}) (h : ∀ x : X, ∃ (R : CommRingCat) (f : Spec.toLocallyRingedSpace.obj (op R) ⟶ X), - (x ∈ Set.range f.base : _) ∧ LocallyRingedSpace.IsOpenImmersion f) : + (x ∈ Set.range f.base :) ∧ LocallyRingedSpace.IsOpenImmersion f) : Scheme where toLocallyRingedSpace := X local_affine := by @@ -222,7 +222,7 @@ namespace Scheme instance basic_open_isOpenImmersion {R : CommRingCat.{u}} (f : R) : IsOpenImmersion (Spec.map (CommRingCat.ofHom (algebraMap R (Localization.Away f)))) := by apply SheafedSpace.IsOpenImmersion.of_stalk_iso (H := ?_) - · exact (PrimeSpectrum.localization_away_isOpenEmbedding (Localization.Away f) f : _) + · exact (PrimeSpectrum.localization_away_isOpenEmbedding (Localization.Away f) f :) · intro x exact Spec_map_localization_isIso R (Submonoid.powers f) x @@ -413,7 +413,7 @@ theorem _root_.AlgebraicGeometry.isIso_iff_stalk_iso {X Y : Scheme.{u}} (f : X · intro H; exact ⟨inferInstance, (TopCat.homeoOfIso (asIso f.base)).isOpenEmbedding⟩ /-- An open immersion induces an isomorphism from the domain onto the image -/ -def isoRestrict : X ≅ (Z.restrict H.base_open : _) := +def isoRestrict : X ≅ (Z.restrict H.base_open :) := Scheme.fullyFaithfulForgetToLocallyRingedSpace.preimageIso (LocallyRingedSpace.IsOpenImmersion.isoRestrict f.toLRSHom) diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index 2eabfbfe9f773..5111ffb0d516b 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -649,7 +649,7 @@ def localizationMapOfSpecializes {x y : PrimeSpectrum R} (h : x ⤳ y) : rw [← PrimeSpectrum.le_iff_specializes, ← asIdeal_le_asIdeal, ← SetLike.coe_subset_coe, ← Set.compl_subset_compl] at h exact (IsLocalization.map_units (Localization.AtPrime x.asIdeal) - ⟨a, show a ∈ x.asIdeal.primeCompl from h ha⟩ : _)) + ⟨a, show a ∈ x.asIdeal.primeCompl from h ha⟩ :)) section stableUnderSpecialization diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean index 7532e95080f90..44912ce1425be 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean @@ -243,7 +243,7 @@ evaluates the section on the point corresponding to a given homogeneous prime id def openToLocalization (U : Opens (ProjectiveSpectrum.top 𝒜)) (x : ProjectiveSpectrum.top 𝒜) (hx : x ∈ U) : (Proj.structureSheaf 𝒜).1.obj (op U) ⟶ CommRingCat.of (at x) := CommRingCat.ofHom - { toFun s := (s.1 ⟨x, hx⟩ : _) + { toFun s := (s.1 ⟨x, hx⟩ :) map_one' := rfl map_mul' _ _ := rfl map_zero' := rfl diff --git a/Mathlib/AlgebraicGeometry/Restrict.lean b/Mathlib/AlgebraicGeometry/Restrict.lean index afcdc6496a7fb..766c1a26259da 100644 --- a/Mathlib/AlgebraicGeometry/Restrict.lean +++ b/Mathlib/AlgebraicGeometry/Restrict.lean @@ -301,7 +301,7 @@ isomorphic to the structure sheaf. -/ @[simps!] def Scheme.restrictFunctorΓ : X.restrictFunctor.op ⋙ (Over.forget X).op ⋙ Scheme.Γ ≅ X.presheaf := NatIso.ofComponents - (fun U => X.presheaf.mapIso ((eqToIso (unop U).isOpenEmbedding_obj_top).symm.op : _)) + (fun U => X.presheaf.mapIso ((eqToIso (unop U).isOpenEmbedding_obj_top).symm.op :)) (by intro U V i dsimp diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index 5fffbe52e634b..6acbeea9a53e1 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -248,16 +248,16 @@ unif_hint forgetToTop_obj_eq_coe (X : Scheme) where ⊢ forgetToTop.obj X ≟ (X : TopCat) @[simp] -theorem id.base (X : Scheme) : (𝟙 X : _).base = 𝟙 _ := +theorem id.base (X : Scheme) : (𝟙 X :).base = 𝟙 _ := rfl @[simp] theorem id_app {X : Scheme} (U : X.Opens) : - (𝟙 X : _).app U = 𝟙 _ := rfl + (𝟙 X :).app U = 𝟙 _ := rfl @[simp] theorem id_appTop {X : Scheme} : - (𝟙 X : _).appTop = 𝟙 _ := + (𝟙 X :).appTop = 𝟙 _ := rfl @[reassoc] diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index 8d35ebe6a7520..e6e5296cb7084 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -263,7 +263,7 @@ namespace StructureSheaf @[simp] theorem res_apply (U V : Opens (PrimeSpectrum.Top R)) (i : V ⟶ U) (s : (structureSheaf R).1.obj (op U)) (x : V) : - ((structureSheaf R).1.map i.op s).1 x = (s.1 (i x) : _) := + ((structureSheaf R).1.map i.op s).1 x = (s.1 (i x) :) := rfl /- @@ -460,7 +460,7 @@ the section on the point corresponding to a given prime ideal. -/ def openToLocalization (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpectrum.Top R) (hx : x ∈ U) : (structureSheaf R).1.obj (op U) ⟶ CommRingCat.of (Localization.AtPrime x.asIdeal) := CommRingCat.ofHom - { toFun s := (s.1 ⟨x, hx⟩ : _) + { toFun s := (s.1 ⟨x, hx⟩ :) map_one' := rfl map_mul' _ _ := rfl map_zero' := rfl @@ -471,12 +471,12 @@ theorem coe_openToLocalization (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpect (hx : x ∈ U) : (openToLocalization R U x hx : (structureSheaf R).1.obj (op U) → Localization.AtPrime x.asIdeal) = - fun s => (s.1 ⟨x, hx⟩ : _) := + fun s => s.1 ⟨x, hx⟩ := rfl theorem openToLocalization_apply (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpectrum.Top R) (hx : x ∈ U) (s : (structureSheaf R).1.obj (op U)) : - openToLocalization R U x hx s = (s.1 ⟨x, hx⟩ : _) := + openToLocalization R U x hx s = s.1 ⟨x, hx⟩ := rfl /-- The ring homomorphism from the stalk of the structure sheaf of `R` at a point corresponding to @@ -650,7 +650,7 @@ theorem locally_const_basicOpen (U : Opens (PrimeSpectrum.Top R)) have basic_opens_eq := PrimeSpectrum.basicOpen_pow h (n + 1) (by omega) have i_basic_open := eqToHom basic_opens_eq ≫ homOfLE hDhV -- We claim that `(f * c) / h ^ (n+1)` is our desired representation - use f * c, h ^ (n + 1), i_basic_open ≫ iVU, (basic_opens_eq.symm.le : _) hxDh + use f * c, h ^ (n + 1), i_basic_open ≫ iVU, (basic_opens_eq.symm.le :) hxDh rw [op_comp, Functor.map_comp] --, comp_apply, ← s_eq, res_const] -- Porting note: `comp_apply` can't be rewritten, so use a change change const R _ _ _ _ = (structureSheaf R).1.map i_basic_open.op @@ -661,7 +661,7 @@ theorem locally_const_basicOpen (U : Opens (PrimeSpectrum.Top R)) swap · intro y hy rw [basic_opens_eq] at hy - exact (Set.Subset.trans hDhV hVDg : _) hy + exact (Set.Subset.trans hDhV hVDg :) hy -- All that is left is a simple calculation apply const_ext rw [mul_assoc f c g, hc] @@ -842,7 +842,7 @@ theorem toBasicOpen_surjective (f : R) : Function.Surjective (toBasicOpen R f) : · intro y hy change y ∈ PrimeSpectrum.basicOpen (f ^ (n + 1)) rw [PrimeSpectrum.basicOpen_pow f (n + 1) (by omega)] - exact (leOfHom (iDh i) : _) hy + exact (leOfHom (iDh i) :) hy -- The rest of the proof is just computation apply const_ext rw [← hb, Finset.sum_mul, Finset.mul_sum] @@ -989,7 +989,7 @@ def comapFun (f : R →+* S) (U : Opens (PrimeSpectrum.Top R)) (V : Opens (Prime (hUV : V.1 ⊆ PrimeSpectrum.comap f ⁻¹' U.1) (s : ∀ x : U, Localizations R x) (y : V) : Localizations S y := Localization.localRingHom (PrimeSpectrum.comap f y.1).asIdeal _ f rfl - (s ⟨PrimeSpectrum.comap f y.1, hUV y.2⟩ : _) + (s ⟨PrimeSpectrum.comap f y.1, hUV y.2⟩ :) theorem comapFunIsLocallyFraction (f : R →+* S) (U : Opens (PrimeSpectrum.Top R)) (V : Opens (PrimeSpectrum.Top S)) (hUV : V.1 ⊆ PrimeSpectrum.comap f ⁻¹' U.1) @@ -1052,7 +1052,7 @@ theorem comap_apply (f : R →+* S) (U : Opens (PrimeSpectrum.Top R)) (s : (structureSheaf R).1.obj (op U)) (p : V) : (comap f U V hUV s).1 p = Localization.localRingHom (PrimeSpectrum.comap f p.1).asIdeal _ f rfl - (s.1 ⟨PrimeSpectrum.comap f p.1, hUV p.2⟩ : _) := + (s.1 ⟨PrimeSpectrum.comap f p.1, hUV p.2⟩ :) := rfl theorem comap_const (f : R →+* S) (U : Opens (PrimeSpectrum.Top R)) diff --git a/Mathlib/AlgebraicTopology/CechNerve.lean b/Mathlib/AlgebraicTopology/CechNerve.lean index ac073516e5bf9..01886468c2e25 100644 --- a/Mathlib/AlgebraicTopology/CechNerve.lean +++ b/Mathlib/AlgebraicTopology/CechNerve.lean @@ -245,7 +245,7 @@ def augmentedCechConerve : Arrow C ⥤ CosimplicialObject.Augmented C where def equivalenceLeftToRight (F : Arrow C) (X : CosimplicialObject.Augmented C) (G : F.augmentedCechConerve ⟶ X) : F ⟶ Augmented.toArrow.obj X where left := G.left - right := (WidePushout.ι _ 0 ≫ G.right.app (SimplexCategory.mk 0) : _) + right := (WidePushout.ι _ 0 ≫ G.right.app (SimplexCategory.mk 0) :) w := by dsimp rw [@WidePushout.arrow_ι_assoc _ _ _ _ _ (fun (_ : Fin 1) => F.hom) diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index 8badf38fc79a0..f7188918787a3 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -534,7 +534,7 @@ giving the main statement in `comp_partialSum`. -/ power series. See also `comp_partialSum`. -/ def compPartialSumSource (m M N : ℕ) : Finset (Σ n, Fin n → ℕ) := - Finset.sigma (Finset.Ico m M) (fun n : ℕ => Fintype.piFinset fun _i : Fin n => Finset.Ico 1 N : _) + Finset.sigma (Finset.Ico m M) (fun n : ℕ => Fintype.piFinset fun _i : Fin n => Finset.Ico 1 N :) @[simp] theorem mem_compPartialSumSource_iff (m M N : ℕ) (i : Σ n, Fin n → ℕ) : diff --git a/Mathlib/Analysis/BoxIntegral/Partition/SubboxInduction.lean b/Mathlib/Analysis/BoxIntegral/Partition/SubboxInduction.lean index 58f1cc837f67c..ac9965aaeb450 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/SubboxInduction.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/SubboxInduction.lean @@ -99,7 +99,7 @@ well-defined. -/ theorem exists_taggedPartition_isHenstock_isSubordinate_homothetic (I : Box ι) (r : (ι → ℝ) → Ioi (0 : ℝ)) : ∃ π : TaggedPrepartition I, π.IsPartition ∧ π.IsHenstock ∧ π.IsSubordinate r ∧ - (∀ J ∈ π, ∃ m : ℕ, ∀ i, (J : _).upper i - J.lower i = (I.upper i - I.lower i) / 2 ^ m) ∧ + (∀ J ∈ π, ∃ m : ℕ, ∀ i, (J :).upper i - J.lower i = (I.upper i - I.lower i) / 2 ^ m) ∧ π.distortion = I.distortion := by refine subbox_induction_on I (fun J _ hJ => ?_) fun z _ => ?_ · choose! πi hP hHen hr Hn _ using hJ @@ -107,7 +107,7 @@ theorem exists_taggedPartition_isHenstock_isSubordinate_homothetic (I : Box ι) have hP : ((splitCenter J).biUnionTagged πi).IsPartition := (isPartition_splitCenter _).biUnionTagged hP have hsub : ∀ J' ∈ (splitCenter J).biUnionTagged πi, ∃ n : ℕ, ∀ i, - (J' : _).upper i - J'.lower i = (J.upper i - J.lower i) / 2 ^ n := by + (J' :).upper i - J'.lower i = (J.upper i - J.lower i) / 2 ^ n := by intro J' hJ' rcases (splitCenter J).mem_biUnionTagged.1 hJ' with ⟨J₁, h₁, h₂⟩ refine ⟨n J₁ J' + 1, fun i => ?_⟩ diff --git a/Mathlib/Analysis/CStarAlgebra/Multiplier.lean b/Mathlib/Analysis/CStarAlgebra/Multiplier.lean index 900b2eb10e19f..97b6d4406dc4b 100644 --- a/Mathlib/Analysis/CStarAlgebra/Multiplier.lean +++ b/Mathlib/Analysis/CStarAlgebra/Multiplier.lean @@ -530,7 +530,7 @@ theorem nnnorm_def' (a : 𝓜(𝕜, A)) : ‖a‖₊ = ‖toProdMulOppositeHom a instance instNormedSpace : NormedSpace 𝕜 𝓜(𝕜, A) := { DoubleCentralizer.instModule with - norm_smul_le := fun k a => (norm_smul_le k a.toProdMulOpposite : _) } + norm_smul_le := fun k a => (norm_smul_le k a.toProdMulOpposite :) } instance instNormedAlgebra : NormedAlgebra 𝕜 𝓜(𝕜, A) := { DoubleCentralizer.instAlgebra, DoubleCentralizer.instNormedSpace with } diff --git a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean index eabcdff56fab9..8b8a3b55c82e5 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean @@ -242,7 +242,7 @@ alias Filter.EventuallyEq.contDiffWithinAt_iff := Filter.EventuallyEq.congr_cont theorem ContDiffWithinAt.congr_of_eventuallyEq_insert (h : ContDiffWithinAt 𝕜 n f s x) (h₁ : f₁ =ᶠ[𝓝[insert x s] x] f) : ContDiffWithinAt 𝕜 n f₁ s x := h.congr_of_eventuallyEq (nhdsWithin_mono x (subset_insert x s) h₁) - (mem_of_mem_nhdsWithin (mem_insert x s) h₁ : _) + (mem_of_mem_nhdsWithin (mem_insert x s) h₁ :) theorem Filter.EventuallyEq.congr_contDiffWithinAt_of_insert (h₁ : f₁ =ᶠ[𝓝[insert x s] x] f) : ContDiffWithinAt 𝕜 n f₁ s x ↔ ContDiffWithinAt 𝕜 n f s x := diff --git a/Mathlib/Analysis/Calculus/Deriv/Basic.lean b/Mathlib/Analysis/Calculus/Deriv/Basic.lean index d0e6db0c4bcf9..64f66f524e715 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Basic.lean @@ -562,7 +562,7 @@ theorem HasDerivWithinAt.congr_deriv (h : HasDerivWithinAt f f' s x) (h' : f' = theorem HasDerivAt.congr_of_eventuallyEq (h : HasDerivAt f f' x) (h₁ : f₁ =ᶠ[𝓝 x] f) : HasDerivAt f₁ f' x := - HasDerivAtFilter.congr_of_eventuallyEq h h₁ (mem_of_mem_nhds h₁ : _) + HasDerivAtFilter.congr_of_eventuallyEq h h₁ (mem_of_mem_nhds h₁ :) theorem Filter.EventuallyEq.hasDerivAt_iff (h : f₀ =ᶠ[𝓝 x] f₁) : HasDerivAt f₀ f' x ↔ HasDerivAt f₁ f' x := diff --git a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean index c22d0f09c8255..e49d2ade9920f 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean @@ -854,7 +854,7 @@ theorem HasFDerivWithinAt.congr_of_eventuallyEq (h : HasFDerivWithinAt f f' s x) theorem HasFDerivAt.congr_of_eventuallyEq (h : HasFDerivAt f f' x) (h₁ : f₁ =ᶠ[𝓝 x] f) : HasFDerivAt f₁ f' x := - HasFDerivAtFilter.congr_of_eventuallyEq h h₁ (mem_of_mem_nhds h₁ : _) + HasFDerivAtFilter.congr_of_eventuallyEq h h₁ (mem_of_mem_nhds h₁ :) theorem DifferentiableWithinAt.congr_mono (h : DifferentiableWithinAt 𝕜 f s x) (ht : EqOn f₁ f t) (hx : f₁ x = f x) (h₁ : t ⊆ s) : DifferentiableWithinAt 𝕜 f₁ t x := diff --git a/Mathlib/Analysis/Calculus/Gradient/Basic.lean b/Mathlib/Analysis/Calculus/Gradient/Basic.lean index 5ebf3d941d6a8..5c6489419a6d0 100644 --- a/Mathlib/Analysis/Calculus/Gradient/Basic.lean +++ b/Mathlib/Analysis/Calculus/Gradient/Basic.lean @@ -284,7 +284,7 @@ theorem HasGradientWithinAt.congr_of_eventuallyEq_of_mem (h : HasGradientWithinA theorem HasGradientAt.congr_of_eventuallyEq (h : HasGradientAt f f' x) (h₁ : f₁ =ᶠ[𝓝 x] f) : HasGradientAt f₁ f' x := - HasGradientAtFilter.congr_of_eventuallyEq h h₁ (mem_of_mem_nhds h₁ : _) + HasGradientAtFilter.congr_of_eventuallyEq h h₁ (mem_of_mem_nhds h₁ :) theorem Filter.EventuallyEq.gradient_eq (hL : f₁ =ᶠ[𝓝 x] f) : ∇ f₁ x = ∇ f x := by unfold gradient diff --git a/Mathlib/Analysis/Convolution.lean b/Mathlib/Analysis/Convolution.lean index 9363b3cee07de..9834adcc2007f 100644 --- a/Mathlib/Analysis/Convolution.lean +++ b/Mathlib/Analysis/Convolution.lean @@ -931,7 +931,7 @@ variable [NormedAddCommGroup G] [BorelSpace G] theorem convolution_precompR_apply {g : G → E'' →L[𝕜] E'} (hf : LocallyIntegrable f μ) (hcg : HasCompactSupport g) (hg : Continuous g) (x₀ : G) (x : E'') : (f ⋆[L.precompR E'', μ] g) x₀ x = (f ⋆[L, μ] fun a => g a x) x₀ := by - have := hcg.convolutionExists_right (L.precompR E'' : _) hf hg x₀ + have := hcg.convolutionExists_right (L.precompR E'' :) hf hg x₀ simp_rw [convolution_def, ContinuousLinearMap.integral_apply this] rfl @@ -1096,7 +1096,7 @@ theorem hasFDerivAt_convolution_right_with_param {g : P → G → E'} {s : Set P have I3 : AEStronglyMeasurable (fun a : G => (L (f a)).comp (g' (q₀.fst, q₀.snd - a))) μ := by have T : HasCompactSupport fun y => g' (q₀.1, y) := HasCompactSupport.intro hk fun x hx => g'_zero q₀.1 x hq₀ hx - apply (HasCompactSupport.convolutionExists_right (L.precompR (P × G) : _) T hf _ q₀.2).1 + apply (HasCompactSupport.convolutionExists_right (L.precompR (P × G) :) T hf _ q₀.2).1 have : ContinuousOn g' (s ×ˢ univ) := hg.continuousOn_fderiv_of_isOpen (hs.prod isOpen_univ) le_rfl apply this.comp_continuous (continuous_const.prod_mk continuous_id') @@ -1206,7 +1206,7 @@ theorem contDiffOn_convolution_right_with_param_aux {G : Type uP} {E' : Type uP} filter_upwards [prod_mem_prod M1 M2] rintro ⟨p, y⟩ ⟨hp, hy⟩ exact hgs p y hp hy - apply ih (L.precompR (P × G) : _) B + apply ih (L.precompR (P × G) :) B convert hg.2.2 | htop ih => rw [contDiffOn_infty] at hg ⊢ diff --git a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean index 8543135aeea96..bd20aaa76f0cf 100644 --- a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean +++ b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean @@ -200,7 +200,7 @@ lemma _root_.MeasureTheory.AEStronglyMeasurable.fourierSMulRight have aux1 : AEStronglyMeasurable (fun v ↦ (L v, f v)) μ := L.continuous.aestronglyMeasurable.prod_mk hf -- Elaboration without the expected type is faster here: - exact (aux0.comp_aestronglyMeasurable aux1 : _) + exact (aux0.comp_aestronglyMeasurable aux1 :) variable {f} diff --git a/Mathlib/Analysis/InnerProductSpace/Completion.lean b/Mathlib/Analysis/InnerProductSpace/Completion.lean index 330ff19ec4db2..3642a0acb90ca 100644 --- a/Mathlib/Analysis/InnerProductSpace/Completion.lean +++ b/Mathlib/Analysis/InnerProductSpace/Completion.lean @@ -86,7 +86,7 @@ protected theorem continuous_inner : protected theorem Continuous.inner {α : Type*} [TopologicalSpace α] {f g : α → Completion E} (hf : Continuous f) (hg : Continuous g) : Continuous (fun x : α => inner (f x) (g x) : α → 𝕜) := - UniformSpace.Completion.continuous_inner.comp (hf.prod_mk hg : _) + UniformSpace.Completion.continuous_inner.comp (hf.prod_mk hg :) instance innerProductSpace : InnerProductSpace 𝕜 (Completion E) where norm_sq_eq_inner x := diff --git a/Mathlib/Analysis/InnerProductSpace/Projection.lean b/Mathlib/Analysis/InnerProductSpace/Projection.lean index ca88319d17068..2491cf9d734db 100644 --- a/Mathlib/Analysis/InnerProductSpace/Projection.lean +++ b/Mathlib/Analysis/InnerProductSpace/Projection.lean @@ -1288,7 +1288,7 @@ abbrev OrthogonalFamily.decomposition [DecidableEq ι] [Fintype ι] {V : ι → -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 erw [DFinsupp.sumAddHom_apply]; rw [DFinsupp.sum_eq_sum_fintype] · simp_rw [Equiv.apply_symm_apply, AddSubmonoidClass.coe_subtype] - exact hV.sum_projection_of_mem_iSup _ ((h.ge : _) Submodule.mem_top) + exact hV.sum_projection_of_mem_iSup _ ((h.ge :) Submodule.mem_top) · intro i exact map_zero _ right_inv x := by diff --git a/Mathlib/Analysis/Matrix.lean b/Mathlib/Analysis/Matrix.lean index d82d5f067fe3c..0101a1bd7d633 100644 --- a/Mathlib/Analysis/Matrix.lean +++ b/Mathlib/Analysis/Matrix.lean @@ -108,7 +108,7 @@ theorem nnnorm_map_eq (A : Matrix m n α) (f : α → β) (hf : ∀ a, ‖f a‖ @[simp] theorem norm_map_eq (A : Matrix m n α) (f : α → β) (hf : ∀ a, ‖f a‖ = ‖a‖) : ‖A.map f‖ = ‖A‖ := - (congr_arg ((↑) : ℝ≥0 → ℝ) <| nnnorm_map_eq A f fun a => Subtype.ext <| hf a : _) + (congr_arg ((↑) : ℝ≥0 → ℝ) <| nnnorm_map_eq A f fun a => Subtype.ext <| hf a :) @[simp] theorem nnnorm_transpose (A : Matrix m n α) : ‖Aᵀ‖₊ = ‖A‖₊ := @@ -493,7 +493,7 @@ theorem frobenius_nnnorm_map_eq (A : Matrix m n α) (f : α → β) (hf : ∀ a, @[simp] theorem frobenius_norm_map_eq (A : Matrix m n α) (f : α → β) (hf : ∀ a, ‖f a‖ = ‖a‖) : ‖A.map f‖ = ‖A‖ := - (congr_arg ((↑) : ℝ≥0 → ℝ) <| frobenius_nnnorm_map_eq A f fun a => Subtype.ext <| hf a : _) + (congr_arg ((↑) : ℝ≥0 → ℝ) <| frobenius_nnnorm_map_eq A f fun a => Subtype.ext <| hf a :) @[simp] theorem frobenius_nnnorm_transpose (A : Matrix m n α) : ‖Aᵀ‖₊ = ‖A‖₊ := by @@ -553,7 +553,7 @@ theorem frobenius_nnnorm_diagonal [DecidableEq n] (v : n → α) : @[simp] theorem frobenius_norm_diagonal [DecidableEq n] (v : n → α) : ‖diagonal v‖ = ‖(WithLp.equiv 2 _).symm v‖ := - (congr_arg ((↑) : ℝ≥0 → ℝ) <| frobenius_nnnorm_diagonal v : _).trans rfl + (congr_arg ((↑) : ℝ≥0 → ℝ) <| frobenius_nnnorm_diagonal v :).trans rfl end SeminormedAddCommGroup diff --git a/Mathlib/Analysis/Normed/Algebra/Basic.lean b/Mathlib/Analysis/Normed/Algebra/Basic.lean index d44b75699bb05..6da32173a5821 100644 --- a/Mathlib/Analysis/Normed/Algebra/Basic.lean +++ b/Mathlib/Analysis/Normed/Algebra/Basic.lean @@ -44,7 +44,7 @@ instance [ProperSpace 𝕜] : CompactSpace (characterSpace 𝕜 A) := by have h : characterSpace 𝕜 A ⊆ toNormedDual ⁻¹' Metric.closedBall 0 ‖(1 : A)‖ := by intro φ hφ rw [Set.mem_preimage, mem_closedBall_zero_iff] - exact (norm_le_norm_one ⟨φ, ⟨hφ.1, hφ.2⟩⟩ : _) + exact (norm_le_norm_one ⟨φ, ⟨hφ.1, hφ.2⟩⟩ :) exact (isCompact_closedBall 𝕜 0 _).of_isClosed_subset CharacterSpace.isClosed h end CharacterSpace diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index 723a44e211ecc..9d8514ced1889 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -292,7 +292,7 @@ instance (priority := 75) NonUnitalSubalgebraClass.nonUnitalNormedRing {S 𝕜 E instance ULift.nonUnitalSeminormedRing : NonUnitalSeminormedRing (ULift α) := { ULift.seminormedAddCommGroup, ULift.nonUnitalRing with - norm_mul := fun x y => (norm_mul_le x.down y.down : _) } + norm_mul := fun x y => (norm_mul_le x.down y.down :) } /-- Non-unital seminormed ring structure on the product of two non-unital seminormed rings, using the sup norm. -/ diff --git a/Mathlib/Analysis/Normed/Field/InfiniteSum.lean b/Mathlib/Analysis/Normed/Field/InfiniteSum.lean index 195aa8c9adc27..faf7d5a691a90 100644 --- a/Mathlib/Analysis/Normed/Field/InfiniteSum.lean +++ b/Mathlib/Analysis/Normed/Field/InfiniteSum.lean @@ -36,7 +36,7 @@ theorem Summable.mul_norm {f : ι → R} {g : ι' → R} (hf : Summable fun x => (hg : Summable fun x => ‖g x‖) : Summable fun x : ι × ι' => ‖f x.1 * g x.2‖ := .of_nonneg_of_le (fun _ ↦ norm_nonneg _) (fun x => norm_mul_le (f x.1) (g x.2)) - (hf.mul_of_nonneg hg (fun x => norm_nonneg <| f x) fun x => norm_nonneg <| g x : _) + (hf.mul_of_nonneg hg (fun x => norm_nonneg <| f x) fun x => norm_nonneg <| g x :) theorem summable_mul_of_summable_norm [CompleteSpace R] {f : ι → R} {g : ι' → R} (hf : Summable fun x => ‖f x‖) (hg : Summable fun x => ‖g x‖) : diff --git a/Mathlib/Analysis/Normed/Group/AddTorsor.lean b/Mathlib/Analysis/Normed/Group/AddTorsor.lean index e3a3f8109709e..d9089e512a53f 100644 --- a/Mathlib/Analysis/Normed/Group/AddTorsor.lean +++ b/Mathlib/Analysis/Normed/Group/AddTorsor.lean @@ -235,7 +235,7 @@ variable [TopologicalSpace α] theorem Continuous.vsub {f g : α → P} (hf : Continuous f) (hg : Continuous g) : Continuous (f -ᵥ g) := - continuous_vsub.comp (hf.prod_mk hg : _) + continuous_vsub.comp (hf.prod_mk hg :) nonrec theorem ContinuousAt.vsub {f g : α → P} {x : α} (hf : ContinuousAt f x) (hg : ContinuousAt g x) : diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean index 302ed81b07f5c..ba8df90a57055 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean @@ -80,7 +80,7 @@ instance : HasCokernels SemiNormedGrp₁.{u} where erw [zero_apply]) fun _ _ w => Subtype.eq - (NormedAddGroupHom.lift_unique f.1.range _ _ _ (congr_arg Subtype.val w : _)) } + (NormedAddGroupHom.lift_unique f.1.range _ _ _ (congr_arg Subtype.val w :)) } -- Sanity check example : HasCokernels SemiNormedGrp₁ := by infer_instance diff --git a/Mathlib/Analysis/Normed/Module/Basic.lean b/Mathlib/Analysis/Normed/Module/Basic.lean index 615129ab6a77a..3ca89f37a1d43 100644 --- a/Mathlib/Analysis/Normed/Module/Basic.lean +++ b/Mathlib/Analysis/Normed/Module/Basic.lean @@ -102,7 +102,7 @@ open NormedField instance ULift.normedSpace : NormedSpace 𝕜 (ULift E) := { __ := ULift.seminormedAddCommGroup (E := E), __ := ULift.module' - norm_smul_le := fun s x => (norm_smul_le s x.down : _) } + norm_smul_le := fun s x => (norm_smul_le s x.down :) } /-- The product of two normed spaces is a normed space, with the sup norm. -/ instance Prod.normedSpace : NormedSpace 𝕜 (E × F) := diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index d7bef54d16d58..c04f7b9a2dcf5 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -692,7 +692,7 @@ namespace ContinuousMultilinearMap these variables, and fixing the other ones equal to a given value `z`. It is denoted by `f.restr s hk z`, where `hk` is a proof that the cardinality of `s` is `k`. The implicit identification between `Fin k` and `s` that we use is the canonical (increasing) bijection. -/ -def restr {k n : ℕ} (f : (G[×n]→L[𝕜] G' : _)) (s : Finset (Fin n)) (hk : #s = k) (z : G) : +def restr {k n : ℕ} (f : (G[×n]→L[𝕜] G' :)) (s : Finset (Fin n)) (hk : #s = k) (z : G) : G[×k]→L[𝕜] G' := (f.toMultilinearMap.restr s hk z).mkContinuous (‖f‖ * ‖z‖ ^ (n - k)) fun _ => MultilinearMap.restr_norm_le _ _ _ _ f.le_opNorm _ diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean index 8d1a93937e77e..f50d7b58dac0e 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Prod.lean @@ -120,7 +120,7 @@ theorem _root_.Continuous.prod_map_equivL {f : X → M₁ ≃L[𝕜] M₂} {g : theorem _root_.ContinuousOn.prod_mapL {f : X → M₁ →L[𝕜] M₂} {g : X → M₃ →L[𝕜] M₄} {s : Set X} (hf : ContinuousOn f s) (hg : ContinuousOn g s) : ContinuousOn (fun x => (f x).prodMap (g x)) s := - ((prodMapL 𝕜 M₁ M₂ M₃ M₄).continuous.comp_continuousOn (hf.prod hg) : _) + ((prodMapL 𝕜 M₁ M₂ M₃ M₄).continuous.comp_continuousOn (hf.prod hg) :) theorem _root_.ContinuousOn.prod_map_equivL {f : X → M₁ ≃L[𝕜] M₂} {g : X → M₃ ≃L[𝕜] M₄} {s : Set X} (hf : ContinuousOn (fun x => (f x : M₁ →L[𝕜] M₂)) s) diff --git a/Mathlib/CategoryTheory/Enriched/Basic.lean b/Mathlib/CategoryTheory/Enriched/Basic.lean index bd179b0fdb051..0654c73c33d3c 100644 --- a/Mathlib/CategoryTheory/Enriched/Basic.lean +++ b/Mathlib/CategoryTheory/Enriched/Basic.lean @@ -143,7 +143,7 @@ def categoryOfEnrichedCategoryType (C : Type u₁) [𝒞 : EnrichedCategory (Typ comp f g := eComp (Type v) _ _ _ ⟨f, g⟩ id_comp f := congr_fun (e_id_comp (Type v) _ _) f comp_id f := congr_fun (e_comp_id (Type v) _ _) f - assoc f g h := (congr_fun (e_assoc (Type v) _ _ _ _) ⟨f, g, h⟩ : _) + assoc f g h := (congr_fun (e_assoc (Type v) _ _ _ _) ⟨f, g, h⟩ :) /-- Construct a `Type v`-enriched category from an honest category. -/ diff --git a/Mathlib/CategoryTheory/Extensive.lean b/Mathlib/CategoryTheory/Extensive.lean index 18e02517b1d56..f7766dcde513a 100644 --- a/Mathlib/CategoryTheory/Extensive.lean +++ b/Mathlib/CategoryTheory/Extensive.lean @@ -174,10 +174,10 @@ theorem FinitaryExtensive.mono_inl_of_isColimit [FinitaryExtensive C] {c : Binar FinitaryExtensive.mono_inr_of_isColimit (BinaryCofan.isColimitFlip hc) instance [FinitaryExtensive C] (X Y : C) : Mono (coprod.inl : X ⟶ X ⨿ Y) := - (FinitaryExtensive.mono_inl_of_isColimit (coprodIsCoprod X Y) : _) + (FinitaryExtensive.mono_inl_of_isColimit (coprodIsCoprod X Y) :) instance [FinitaryExtensive C] (X Y : C) : Mono (coprod.inr : Y ⟶ X ⨿ Y) := - (FinitaryExtensive.mono_inr_of_isColimit (coprodIsCoprod X Y) : _) + (FinitaryExtensive.mono_inr_of_isColimit (coprodIsCoprod X Y) :) theorem FinitaryExtensive.isPullback_initial_to_binaryCofan [FinitaryExtensive C] {c : BinaryCofan X Y} (hc : IsColimit c) : @@ -222,7 +222,7 @@ instance types.finitaryExtensive : FinitaryExtensive (Type u) := by · simp only [Types.binaryCoproductCocone_pt, Functor.const_obj_obj, Sum.inl.injEq, existsUnique_eq'] · apply_fun f at h - cases ((congr_fun s.condition x).symm.trans h).trans (congr_fun hαY val : _).symm + cases ((congr_fun s.condition x).symm.trans h).trans (congr_fun hαY val :).symm delta ExistsUnique at this choose l hl hl' using this exact ⟨l, (funext hl).symm, Types.isTerminalPunit.hom_ext _ _, @@ -233,7 +233,7 @@ instance types.finitaryExtensive : FinitaryExtensive (Type u) := by intro x cases' h : s.fst x with val val · apply_fun f at h - cases ((congr_fun s.condition x).symm.trans h).trans (congr_fun hαX val : _).symm + cases ((congr_fun s.condition x).symm.trans h).trans (congr_fun hαX val :).symm · simp only [Types.binaryCoproductCocone_pt, Functor.const_obj_obj, Sum.inr.injEq, existsUnique_eq'] delta ExistsUnique at this @@ -314,7 +314,7 @@ instance finitaryExtensive_TopCat : FinitaryExtensive TopCat.{u} := by · exact ⟨val, rfl, fun y h => Sum.inl_injective h.symm⟩ · apply_fun f at h cases ((ConcreteCategory.congr_hom s.condition x).symm.trans h).trans - (ConcreteCategory.congr_hom hαY val : _).symm + (ConcreteCategory.congr_hom hαY val :).symm delta ExistsUnique at this choose l hl hl' using this refine ⟨⟨l, ?_⟩, ContinuousMap.ext fun a => (hl a).symm, TopCat.isTerminalPUnit.hom_ext _ _, @@ -330,7 +330,7 @@ instance finitaryExtensive_TopCat : FinitaryExtensive TopCat.{u} := by cases' h : s.fst x with val val · apply_fun f at h cases ((ConcreteCategory.congr_hom s.condition x).symm.trans h).trans - (ConcreteCategory.congr_hom hαX val : _).symm + (ConcreteCategory.congr_hom hαX val :).symm · exact ⟨val, rfl, fun y h => Sum.inr_injective h.symm⟩ delta ExistsUnique at this choose l hl hl' using this diff --git a/Mathlib/CategoryTheory/Functor/Flat.lean b/Mathlib/CategoryTheory/Functor/Flat.lean index 0cb417530c71d..981c2d3094209 100644 --- a/Mathlib/CategoryTheory/Functor/Flat.lean +++ b/Mathlib/CategoryTheory/Functor/Flat.lean @@ -195,9 +195,9 @@ theorem uniq {K : J ⥤ C} {c : Cone K} (hc : IsLimit c) (s : Cone (K ⋙ F)) let α₂ : (F.mapCone c).toStructuredArrow ⋙ map f₂ ⟶ s.toStructuredArrow := { app := fun X => eqToHom (by simp [← h₂]) } let c₁ : Cone (s.toStructuredArrow ⋙ pre s.pt K F) := - (Cones.postcompose (whiskerRight α₁ (pre s.pt K F) : _)).obj (c.toStructuredArrowCone F f₁) + (Cones.postcompose (whiskerRight α₁ (pre s.pt K F) :)).obj (c.toStructuredArrowCone F f₁) let c₂ : Cone (s.toStructuredArrow ⋙ pre s.pt K F) := - (Cones.postcompose (whiskerRight α₂ (pre s.pt K F) : _)).obj (c.toStructuredArrowCone F f₂) + (Cones.postcompose (whiskerRight α₂ (pre s.pt K F) :)).obj (c.toStructuredArrowCone F f₂) -- The two cones can then be combined and we may obtain a cone over the two cones since -- `StructuredArrow s.pt F` is cofiltered. let c₀ := IsCofiltered.cone (biconeMk _ c₁ c₂) diff --git a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean index 82f3de969be51..c550e1890088a 100644 --- a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean +++ b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean @@ -64,7 +64,7 @@ lemma map_injective_iff (F : C ⥤ D) [Faithful F] {X Y : C} (f g : X ⟶ Y) : theorem mapIso_injective (F : C ⥤ D) [Faithful F] : Function.Injective <| (F.mapIso : (X ≅ Y) → (F.obj X ≅ F.obj Y)) := fun _ _ h => - Iso.ext (map_injective F (congr_arg Iso.hom h : _)) + Iso.ext (map_injective F (congr_arg Iso.hom h :)) theorem map_surjective (F : C ⥤ D) [Full F] : Function.Surjective (F.map : (X ⟶ Y) → (F.obj X ⟶ F.obj Y)) := diff --git a/Mathlib/CategoryTheory/IsConnected.lean b/Mathlib/CategoryTheory/IsConnected.lean index ebe6c3c30a930..62109a61f38ae 100644 --- a/Mathlib/CategoryTheory/IsConnected.lean +++ b/Mathlib/CategoryTheory/IsConnected.lean @@ -213,7 +213,7 @@ theorem isPreconnected_induction [IsPreconnected J] (Z : J → Sort*) {j₀ : J} (x : Z j₀) (j : J) : Nonempty (Z j) := (induct_on_objects { j | Nonempty (Z j) } ⟨x⟩ (fun f => ⟨by rintro ⟨y⟩; exact ⟨h₁ f y⟩, by rintro ⟨y⟩; exact ⟨h₂ f y⟩⟩) - j : _) + j :) /-- If `J` and `K` are equivalent, then if `J` is preconnected then `K` is as well. -/ theorem isPreconnected_of_equivalent {K : Type u₂} [Category.{v₂} K] [IsPreconnected J] diff --git a/Mathlib/CategoryTheory/Limits/ColimitLimit.lean b/Mathlib/CategoryTheory/Limits/ColimitLimit.lean index 23386c1aed4c1..3622820f62ff3 100644 --- a/Mathlib/CategoryTheory/Limits/ColimitLimit.lean +++ b/Mathlib/CategoryTheory/Limits/ColimitLimit.lean @@ -104,7 +104,7 @@ noncomputable def colimitLimitToLimitColimitCone (G : J ⥤ K ⥤ C) [HasLimit G colim.mapCone (limit.cone G) ⟶ limit.cone (G ⋙ colim) where hom := colim.map (limitIsoSwapCompLim G).hom ≫ - colimitLimitToLimitColimit (uncurry.obj G : _) ≫ + colimitLimitToLimitColimit (uncurry.obj G :) ≫ lim.map (whiskerRight (currying.unitIso.app G).inv colim) w j := by dsimp diff --git a/Mathlib/CategoryTheory/Limits/Comma.lean b/Mathlib/CategoryTheory/Limits/Comma.lean index 93476394301e1..bef775a823d34 100644 --- a/Mathlib/CategoryTheory/Limits/Comma.lean +++ b/Mathlib/CategoryTheory/Limits/Comma.lean @@ -41,7 +41,7 @@ variable (F : J ⥤ Comma L R) in the comma category. -/ @[simps!] def limitAuxiliaryCone (c₁ : Cone (F ⋙ fst L R)) : Cone ((F ⋙ snd L R) ⋙ R) := - (Cones.postcompose (whiskerLeft F (Comma.natTrans L R) : _)).obj (L.mapCone c₁) + (Cones.postcompose (whiskerLeft F (Comma.natTrans L R) :)).obj (L.mapCone c₁) /-- If `R` preserves the appropriate limit, then given a cone for `F ⋙ fst L R : J ⥤ L` and a limit cone for `F ⋙ snd L R : J ⥤ R` we can build a cone for `F` which will turn out to be a limit @@ -87,7 +87,7 @@ noncomputable def coneOfPreservesIsLimit [PreservesLimit (F ⋙ snd L R) R] {c in the comma category. -/ @[simps!] def colimitAuxiliaryCocone (c₂ : Cocone (F ⋙ snd L R)) : Cocone ((F ⋙ fst L R) ⋙ L) := - (Cocones.precompose (whiskerLeft F (Comma.natTrans L R) : _)).obj (R.mapCocone c₂) + (Cocones.precompose (whiskerLeft F (Comma.natTrans L R) :)).obj (R.mapCocone c₂) /-- If `L` preserves the appropriate colimit, then given a colimit cocone for `F ⋙ fst L R : J ⥤ L` and @@ -210,7 +210,7 @@ noncomputable instance createsLimitsOfShape [PreservesLimitsOfShape J G] : CreatesLimitsOfShape J (proj X G) where noncomputable instance createsLimitsOfSize [PreservesLimitsOfSize.{w, w'} G] : - CreatesLimitsOfSize.{w, w'} (proj X G : _) where + CreatesLimitsOfSize.{w, w'} (proj X G :) where instance mono_right_of_mono [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G] {Y Z : StructuredArrow X G} (f : Y ⟶ Z) [Mono f] : Mono f.right := @@ -255,7 +255,7 @@ noncomputable instance createsColimitsOfShape [PreservesColimitsOfShape J G] : CreatesColimitsOfShape J (proj G X) where noncomputable instance createsColimitsOfSize [PreservesColimitsOfSize.{w, w'} G] : - CreatesColimitsOfSize.{w, w'} (proj G X : _) where + CreatesColimitsOfSize.{w, w'} (proj G X :) where instance epi_left_of_epi [HasPushouts A] [PreservesColimitsOfShape WalkingSpan G] {Y Z : CostructuredArrow G X} (f : Y ⟶ Z) [Epi f] : Epi f.left := diff --git a/Mathlib/CategoryTheory/Limits/Cones.lean b/Mathlib/CategoryTheory/Limits/Cones.lean index 68bb5355b5bfe..05e9c7a87a567 100644 --- a/Mathlib/CategoryTheory/Limits/Cones.lean +++ b/Mathlib/CategoryTheory/Limits/Cones.lean @@ -719,7 +719,7 @@ isomorphic to the cone `H'.mapCone`. -/ @[simps!] def postcomposeWhiskerLeftMapCone {H H' : C ⥤ D} (α : H ≅ H') (c : Cone F) : - (Cones.postcompose (whiskerLeft F α.hom : _)).obj (mapCone H c) ≅ mapCone H' c := + (Cones.postcompose (whiskerLeft F α.hom :)).obj (mapCone H c) ≅ mapCone H' c := (functorialityCompPostcompose α).app c /-- @@ -730,7 +730,7 @@ a cone over `G ⋙ H`, and they are both isomorphic. @[simps!] def mapConePostcompose {α : F ⟶ G} {c} : mapCone H ((Cones.postcompose α).obj c) ≅ - (Cones.postcompose (whiskerRight α H : _)).obj (mapCone H c) := + (Cones.postcompose (whiskerRight α H :)).obj (mapCone H c) := Cones.ext (Iso.refl _) /-- `mapCone` commutes with `postcomposeEquivalence` @@ -738,7 +738,7 @@ def mapConePostcompose {α : F ⟶ G} {c} : @[simps!] def mapConePostcomposeEquivalenceFunctor {α : F ≅ G} {c} : mapCone H ((Cones.postcomposeEquivalence α).functor.obj c) ≅ - (Cones.postcomposeEquivalence (isoWhiskerRight α H : _)).functor.obj (mapCone H c) := + (Cones.postcomposeEquivalence (isoWhiskerRight α H :)).functor.obj (mapCone H c) := Cones.ext (Iso.refl _) /-- `functoriality F _ ⋙ precompose (whiskerLeft F _)` simplifies to `functoriality F _`. -/ @@ -755,7 +755,7 @@ isomorphic to the cocone `H'.mapCocone`. -/ @[simps!] def precomposeWhiskerLeftMapCocone {H H' : C ⥤ D} (α : H ≅ H') (c : Cocone F) : - (Cocones.precompose (whiskerLeft F α.inv : _)).obj (mapCocone H c) ≅ mapCocone H' c := + (Cocones.precompose (whiskerLeft F α.inv :)).obj (mapCocone H c) ≅ mapCocone H' c := (functorialityCompPrecompose α).app c /-- `map_cocone` commutes with `precompose`. In particular, for `F : J ⥤ C`, given a cocone @@ -765,7 +765,7 @@ ways of producing a cocone over `G ⋙ H`, and they are both isomorphic. @[simps!] def mapCoconePrecompose {α : F ⟶ G} {c} : mapCocone H ((Cocones.precompose α).obj c) ≅ - (Cocones.precompose (whiskerRight α H : _)).obj (mapCocone H c) := + (Cocones.precompose (whiskerRight α H :)).obj (mapCocone H c) := Cocones.ext (Iso.refl _) /-- `mapCocone` commutes with `precomposeEquivalence` @@ -773,7 +773,7 @@ def mapCoconePrecompose {α : F ⟶ G} {c} : @[simps!] def mapCoconePrecomposeEquivalenceFunctor {α : F ≅ G} {c} : mapCocone H ((Cocones.precomposeEquivalence α).functor.obj c) ≅ - (Cocones.precomposeEquivalence (isoWhiskerRight α H : _)).functor.obj (mapCocone H c) := + (Cocones.precomposeEquivalence (isoWhiskerRight α H :)).functor.obj (mapCocone H c) := Cocones.ext (Iso.refl _) /-- `mapCone` commutes with `whisker` diff --git a/Mathlib/CategoryTheory/Limits/Constructions/BinaryProducts.lean b/Mathlib/CategoryTheory/Limits/Constructions/BinaryProducts.lean index 4ad7a58d9ac61..f0c238e0c8044 100644 --- a/Mathlib/CategoryTheory/Limits/Constructions/BinaryProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Constructions/BinaryProducts.lean @@ -28,7 +28,7 @@ variable {C : Type u} [Category.{v} C] {D : Type u'} [Category.{v'} D] (F : C def isBinaryProductOfIsTerminalIsPullback (F : Discrete WalkingPair ⥤ C) (c : Cone F) {X : C} (hX : IsTerminal X) (f : F.obj ⟨WalkingPair.left⟩ ⟶ X) (g : F.obj ⟨WalkingPair.right⟩ ⟶ X) (hc : IsLimit - (PullbackCone.mk (c.π.app ⟨WalkingPair.left⟩) (c.π.app ⟨WalkingPair.right⟩ : _) <| + (PullbackCone.mk (c.π.app ⟨WalkingPair.left⟩) (c.π.app ⟨WalkingPair.right⟩ :) <| hX.hom_ext (_ ≫ f) (_ ≫ g))) : IsLimit c where lift s := hc.lift @@ -38,7 +38,7 @@ def isBinaryProductOfIsTerminalIsPullback (F : Discrete WalkingPair ⥤ C) (c : WalkingPair.casesOn j (hc.fac _ WalkingCospan.left) (hc.fac _ WalkingCospan.right) uniq s m J := by let c' := - PullbackCone.mk (m ≫ c.π.app ⟨WalkingPair.left⟩) (m ≫ c.π.app ⟨WalkingPair.right⟩ : _) + PullbackCone.mk (m ≫ c.π.app ⟨WalkingPair.left⟩) (m ≫ c.π.app ⟨WalkingPair.right⟩ :) (hX.hom_ext (_ ≫ f) (_ ≫ g)) dsimp; rw [← J, ← J] apply hc.hom_ext @@ -134,7 +134,7 @@ def isBinaryCoproductOfIsInitialIsPushout (F : Discrete WalkingPair ⥤ C) (c : (hX : IsInitial X) (f : X ⟶ F.obj ⟨WalkingPair.left⟩) (g : X ⟶ F.obj ⟨WalkingPair.right⟩) (hc : IsColimit - (PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩) (c.ι.app ⟨WalkingPair.right⟩ : _) <| + (PushoutCocone.mk (c.ι.app ⟨WalkingPair.left⟩) (c.ι.app ⟨WalkingPair.right⟩ :) <| hX.hom_ext (f ≫ _) (g ≫ _))) : IsColimit c where desc s := diff --git a/Mathlib/CategoryTheory/Limits/Creates.lean b/Mathlib/CategoryTheory/Limits/Creates.lean index 9769ea2520000..5f74ad2e03a1c 100644 --- a/Mathlib/CategoryTheory/Limits/Creates.lean +++ b/Mathlib/CategoryTheory/Limits/Creates.lean @@ -500,7 +500,7 @@ def createsLimitOfIsoDiagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K₁ ≅ K CreatesLimit K₂ F := { reflectsLimit_of_iso_diagram F h with lifts := fun c t => - let t' := (IsLimit.postcomposeInvEquiv (isoWhiskerRight h F : _) c).symm t + let t' := (IsLimit.postcomposeInvEquiv (isoWhiskerRight h F :) c).symm t { liftedCone := (Cones.postcompose h.hom).obj (liftLimit t') validLift := Functor.mapConePostcompose F ≪≫ @@ -513,7 +513,7 @@ def createsLimitOfIsoDiagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K₁ ≅ K /-- If `F` creates the limit of `K` and `F ≅ G`, then `G` creates the limit of `K`. -/ def createsLimitOfNatIso {F G : C ⥤ D} (h : F ≅ G) [CreatesLimit K F] : CreatesLimit K G where lifts c t := - { liftedCone := liftLimit ((IsLimit.postcomposeInvEquiv (isoWhiskerLeft K h : _) c).symm t) + { liftedCone := liftLimit ((IsLimit.postcomposeInvEquiv (isoWhiskerLeft K h :) c).symm t) validLift := by refine (IsLimit.mapConeEquiv h ?_).uniqueUpToIso t apply IsLimit.ofIsoLimit _ (liftedLimitMapsToOriginal _).symm @@ -534,7 +534,7 @@ def createsColimitOfIsoDiagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K₁ ≅ CreatesColimit K₂ F := { reflectsColimit_of_iso_diagram F h with lifts := fun c t => - let t' := (IsColimit.precomposeHomEquiv (isoWhiskerRight h F : _) c).symm t + let t' := (IsColimit.precomposeHomEquiv (isoWhiskerRight h F :) c).symm t { liftedCocone := (Cocones.precompose h.inv).obj (liftColimit t') validLift := Functor.mapCoconePrecompose F ≪≫ @@ -548,7 +548,7 @@ def createsColimitOfIsoDiagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K₁ ≅ /-- If `F` creates the colimit of `K` and `F ≅ G`, then `G` creates the colimit of `K`. -/ def createsColimitOfNatIso {F G : C ⥤ D} (h : F ≅ G) [CreatesColimit K F] : CreatesColimit K G where lifts c t := - { liftedCocone := liftColimit ((IsColimit.precomposeHomEquiv (isoWhiskerLeft K h : _) c).symm t) + { liftedCocone := liftColimit ((IsColimit.precomposeHomEquiv (isoWhiskerLeft K h :) c).symm t) validLift := by refine (IsColimit.mapCoconeEquiv h ?_).uniqueUpToIso t apply IsColimit.ofIsoColimit _ (liftedColimitMapsToOriginal _).symm diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index f704225f03972..5124dc554a97f 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -257,7 +257,7 @@ theorem colimit_cocone_comp_aux (s : Cocone (F ⋙ G)) (j : C) : G.map (homToLift F (F.obj j)) ≫ s.ι.app (lift F (F.obj j)) = s.ι.app j := by -- This point is that this would be true if we took `lift (F.obj j)` to just be `j` -- and `homToLift (F.obj j)` to be `𝟙 (F.obj j)`. - apply induction F fun X k => G.map k ≫ s.ι.app X = (s.ι.app j : _) + apply induction F fun X k => G.map k ≫ s.ι.app X = (s.ι.app j :) · intro j₁ j₂ k₁ k₂ f w h rw [← w] rw [← s.w f] at h @@ -607,7 +607,7 @@ theorem limit_cone_comp_aux (s : Cone (F ⋙ G)) (j : C) : s.π.app (lift F (F.obj j)) ≫ G.map (homToLift F (F.obj j)) = s.π.app j := by -- This point is that this would be true if we took `lift (F.obj j)` to just be `j` -- and `homToLift (F.obj j)` to be `𝟙 (F.obj j)`. - apply induction F fun X k => s.π.app X ≫ G.map k = (s.π.app j : _) + apply induction F fun X k => s.π.app X ≫ G.map k = (s.π.app j :) · intro j₁ j₂ k₁ k₂ f w h rw [← s.w f] rw [← w] at h diff --git a/Mathlib/CategoryTheory/Limits/IsLimit.lean b/Mathlib/CategoryTheory/Limits/IsLimit.lean index be68bfd74c3fc..a15e2af7ecdaa 100644 --- a/Mathlib/CategoryTheory/Limits/IsLimit.lean +++ b/Mathlib/CategoryTheory/Limits/IsLimit.lean @@ -404,7 +404,7 @@ def ofFaithful {t : Cone F} {D : Type u₄} [Category.{v₄} D] (G : C ⥤ D) [G -/ def mapConeEquiv {D : Type u₄} [Category.{v₄} D] {K : J ⥤ C} {F G : C ⥤ D} (h : F ≅ G) {c : Cone K} (t : IsLimit (mapCone F c)) : IsLimit (mapCone G c) := by - apply postcomposeInvEquiv (isoWhiskerLeft K h : _) (mapCone G c) _ + apply postcomposeInvEquiv (isoWhiskerLeft K h :) (mapCone G c) _ apply t.ofIsoLimit (postcomposeWhiskerLeftMapCone h.symm c).symm /-- A cone is a limit cone exactly if @@ -442,7 +442,7 @@ theorem coneOfHom_homOfCone (s : Cone F) : coneOfHom h (homOfCone h s) = s := by @[simp] theorem homOfCone_coneOfHom {Y : C} (f : Y ⟶ X) : homOfCone h (coneOfHom h f) = f := - congrArg ULift.down (congrFun (congrFun (congrArg NatTrans.app h.hom_inv_id) (op Y)) ⟨f⟩ : _) + congrArg ULift.down (congrFun (congrFun (congrArg NatTrans.app h.hom_inv_id) (op Y)) ⟨f⟩ :) /-- If `F.cones` is represented by `X`, the cone corresponding to the identity morphism on `X` will be a limit cone. -/ @@ -872,7 +872,7 @@ def ofFaithful {t : Cocone F} {D : Type u₄} [Category.{v₄} D] (G : C ⥤ D) def mapCoconeEquiv {D : Type u₄} [Category.{v₄} D] {K : J ⥤ C} {F G : C ⥤ D} (h : F ≅ G) {c : Cocone K} (t : IsColimit (mapCocone F c)) : IsColimit (mapCocone G c) := by apply IsColimit.ofIsoColimit _ (precomposeWhiskerLeftMapCocone h c) - apply (precomposeInvEquiv (isoWhiskerLeft K h : _) _).symm t + apply (precomposeInvEquiv (isoWhiskerLeft K h :) _).symm t /-- A cocone is a colimit cocone exactly if there is a unique cocone morphism from any other cocone. @@ -908,7 +908,7 @@ theorem coconeOfHom_homOfCocone (s : Cocone F) : coconeOfHom h (homOfCocone h s) @[simp] theorem homOfCocone_cooneOfHom {Y : C} (f : X ⟶ Y) : homOfCocone h (coconeOfHom h f) = f := - congrArg ULift.down (congrFun (congrFun (congrArg NatTrans.app h.hom_inv_id) Y) ⟨f⟩ : _) + congrArg ULift.down (congrFun (congrFun (congrArg NatTrans.app h.hom_inv_id) Y) ⟨f⟩ :) /-- If `F.cocones` is corepresented by `X`, the cocone corresponding to the identity morphism on `X` will be a colimit cocone. -/ diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean b/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean index c77df5a351b5d..895a0d9129194 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Basic.lean @@ -248,7 +248,7 @@ preservesLimit_of_preserves_limit_cone h hF lemma preservesLimit_of_iso_diagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K₁ ≅ K₂) [PreservesLimit K₁ F] : PreservesLimit K₂ F where preserves {c} t := ⟨by - apply IsLimit.postcomposeInvEquiv (isoWhiskerRight h F : _) _ _ + apply IsLimit.postcomposeInvEquiv (isoWhiskerRight h F :) _ _ have := (IsLimit.postcomposeInvEquiv h c).symm t apply IsLimit.ofIsoLimit (isLimitOfPreserves F this) exact Cones.ext (Iso.refl _)⟩ @@ -354,7 +354,7 @@ lemma preservesColimit_of_iso_diagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K [PreservesColimit K₁ F] : PreservesColimit K₂ F where preserves {c} t := ⟨by - apply IsColimit.precomposeHomEquiv (isoWhiskerRight h F : _) _ _ + apply IsColimit.precomposeHomEquiv (isoWhiskerRight h F :) _ _ have := (IsColimit.precomposeHomEquiv h c).symm t apply IsColimit.ofIsoColimit (isColimitOfPreserves F this) exact Cocones.ext (Iso.refl _)⟩ @@ -693,7 +693,7 @@ lemma reflectsLimit_of_iso_diagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K₁ ReflectsLimit K₂ F where reflects {c} t := ⟨by apply IsLimit.postcomposeInvEquiv h c (isLimitOfReflects F _) - apply ((IsLimit.postcomposeInvEquiv (isoWhiskerRight h F : _) _).symm t).ofIsoLimit _ + apply ((IsLimit.postcomposeInvEquiv (isoWhiskerRight h F :) _).symm t).ofIsoLimit _ exact Cones.ext (Iso.refl _)⟩ @[deprecated "use reflectsLimit_of_iso_diagram" (since := "2024-11-19")] @@ -868,7 +868,7 @@ lemma reflectsColimit_of_iso_diagram {K₁ K₂ : J ⥤ C} (F : C ⥤ D) (h : K ReflectsColimit K₂ F where reflects {c} t := ⟨by apply IsColimit.precomposeHomEquiv h c (isColimitOfReflects F _) - apply ((IsColimit.precomposeHomEquiv (isoWhiskerRight h F : _) _).symm t).ofIsoColimit _ + apply ((IsColimit.precomposeHomEquiv (isoWhiskerRight h F :) _).symm t).ofIsoColimit _ exact Cocones.ext (Iso.refl _)⟩ @[deprecated "use reflectsColimit_of_iso_diagram" (since := "2024-11-19")] diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Pullbacks.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Pullbacks.lean index 0eb7d4f49fdba..48b8cbe29f408 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Pullbacks.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Pullbacks.lean @@ -114,7 +114,7 @@ lemma preservesPullback_symmetry : PreservesLimit (cospan g f) G where infer_instance · exact (c.π.naturality WalkingCospan.Hom.inr).symm.trans - (c.π.naturality WalkingCospan.Hom.inl : _)⟩ + (c.π.naturality WalkingCospan.Hom.inl :)⟩ theorem hasPullback_of_preservesPullback [HasPullback f g] : HasPullback (G.map f) (G.map g) := ⟨⟨⟨_, isLimitPullbackConeMapOfIsLimit G _ (pullbackIsPullback _ _)⟩⟩⟩ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean b/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean index 83399224cf13d..b61c4579338d9 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean @@ -586,8 +586,8 @@ noncomputable def ofSigmaCofork (c : Cofork I.fstSigmaMap I.sndSigmaMap) : Multi ι := { app := fun x => match x with - | WalkingMultispan.left a => (Sigma.ι I.left a : _) ≫ I.fstSigmaMap ≫ c.π - | WalkingMultispan.right b => (Sigma.ι I.right b : _) ≫ c.π + | WalkingMultispan.left a => (Sigma.ι I.left a :) ≫ I.fstSigmaMap ≫ c.π + | WalkingMultispan.right b => (Sigma.ι I.right b :) ≫ c.π naturality := by rintro (_ | _) (_ | _) (_ | _ | _) · simp @@ -600,17 +600,17 @@ noncomputable def ofSigmaCofork (c : Cofork I.fstSigmaMap I.sndSigmaMap) : Multi @[simp] theorem ofSigmaCofork_ι_app_left (c : Cofork I.fstSigmaMap I.sndSigmaMap) (a) : (ofSigmaCofork I c).ι.app (WalkingMultispan.left a) = - (Sigma.ι I.left a : _) ≫ I.fstSigmaMap ≫ c.π := + (Sigma.ι I.left a :) ≫ I.fstSigmaMap ≫ c.π := rfl -- @[simp] -- Porting note: LHS simplifies to obtain the normal form below theorem ofSigmaCofork_ι_app_right (c : Cofork I.fstSigmaMap I.sndSigmaMap) (b) : - (ofSigmaCofork I c).ι.app (WalkingMultispan.right b) = (Sigma.ι I.right b : _) ≫ c.π := + (ofSigmaCofork I c).ι.app (WalkingMultispan.right b) = (Sigma.ι I.right b :) ≫ c.π := rfl @[simp] theorem ofSigmaCofork_ι_app_right' (c : Cofork I.fstSigmaMap I.sndSigmaMap) (b) : - π (ofSigmaCofork I c) b = (Sigma.ι I.right b : _) ≫ c.π := + π (ofSigmaCofork I c) b = (Sigma.ι I.right b :) ≫ c.π := rfl end Multicofork diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean index 5b6bfbf8ab8b4..315be3a49b8d5 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean @@ -112,7 +112,7 @@ def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : Pu ⟨l, h₁, h₂⟩ refine ⟨l, h₁, h₂, ?_⟩ intro m hm₁ hm₂ - exact (PullbackCone.IsLimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) : _) + exact (PullbackCone.IsLimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) :) end PullbackCone @@ -299,7 +299,7 @@ def isColimitOfEpiComp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h] (s : Pu ⟨l, h₁, h₂⟩ refine ⟨l, h₁, h₂, ?_⟩ intro m hm₁ hm₂ - exact (PushoutCocone.IsColimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) : _) + exact (PushoutCocone.IsColimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) :) end PushoutCocone diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean index 0c26846165918..04011c1c45cb3 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean @@ -286,7 +286,7 @@ composing with `diagramIsoCospan`. -/ def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) : (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅ PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right) - ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) := + ((t.π.naturality inl).symm.trans (t.π.naturality inr :)) := Cones.ext (Iso.refl _) <| by rintro (_ | (_ | _)) <;> · dsimp diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean index df7ea12153d1c..a7e173c76621e 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean @@ -346,7 +346,7 @@ def productLimitCone {J : Type v} (F : J → TypeMax.{v, u}) : π := Discrete.natTrans (fun ⟨j⟩ f => f j) } isLimit := { lift := fun s x j => s.π.app ⟨j⟩ x - uniq := fun _ _ w => funext fun x => funext fun j => (congr_fun (w ⟨j⟩) x : _) } + uniq := fun _ _ w => funext fun x => funext fun j => (congr_fun (w ⟨j⟩) x :) } /-- The categorical product in `TypeMax.{v, u}` is the type theoretic product `Π j, F j`. -/ noncomputable def productIso {J : Type v} (F : J → TypeMax.{v, u}) : ∏ᶜ F ≅ ∀ j, F j := @@ -385,7 +385,7 @@ noncomputable def productLimitCone : have : Small.{u} (∀ j, F j) := inferInstance { lift := fun s x => (equivShrink _) (fun j => s.π.app ⟨j⟩ x) uniq := fun s m w => funext fun x => Shrink.ext <| funext fun j => by - simpa using (congr_fun (w ⟨j⟩) x : _) } + simpa using (congr_fun (w ⟨j⟩) x :) } /-- The categorical product in `Type u` indexed in `Type v` is the type theoretic product `Π j, F j`, after shrinking back to `Type u`. -/ diff --git a/Mathlib/CategoryTheory/Limits/VanKampen.lean b/Mathlib/CategoryTheory/Limits/VanKampen.lean index dc4efd7144691..f66b56e21c46b 100644 --- a/Mathlib/CategoryTheory/Limits/VanKampen.lean +++ b/Mathlib/CategoryTheory/Limits/VanKampen.lean @@ -105,7 +105,7 @@ theorem IsVanKampenColimit.isUniversal {F : J ⥤ C} {c : Cocone F} (H : IsVanKa /-- A universal colimit is a colimit. -/ noncomputable def IsUniversalColimit.isColimit {F : J ⥤ C} {c : Cocone F} (h : IsUniversalColimit c) : IsColimit c := by - refine ((h c (𝟙 F) (𝟙 c.pt : _) (by rw [Functor.map_id, Category.comp_id, Category.id_comp]) + refine ((h c (𝟙 F) (𝟙 c.pt :) (by rw [Functor.map_id, Category.comp_id, Category.id_comp]) (NatTrans.equifibered_of_isIso _)) fun j => ?_).some haveI : IsIso (𝟙 c.pt) := inferInstance exact IsPullback.of_vert_isIso ⟨by simp⟩ @@ -423,7 +423,7 @@ theorem IsVanKampenColimit.map_reflective [HasColimitsOfShape J C] Gl.map (colimit.desc _ ⟨_, whiskerRight α' Gr ≫ c.2⟩) := by symm convert @IsColimit.coconePointUniqueUpToIso_hom_desc _ _ _ _ ((F' ⋙ Gr) ⋙ Gl) - (Gl.mapCocone ⟨_, (whiskerRight α' Gr ≫ c.2 : _)⟩) _ _ hl hr using 2 + (Gl.mapCocone ⟨_, (whiskerRight α' Gr ≫ c.2 :)⟩) _ _ hl hr using 2 · apply hr.hom_ext intro j rw [hr.fac, Functor.mapCocone_ι_app, ← Gl.map_comp, colimit.cocone_ι, colimit.ι_desc] diff --git a/Mathlib/CategoryTheory/Monad/Adjunction.lean b/Mathlib/CategoryTheory/Monad/Adjunction.lean index 7c5e8d990bb5a..447df18a698b9 100644 --- a/Mathlib/CategoryTheory/Monad/Adjunction.lean +++ b/Mathlib/CategoryTheory/Monad/Adjunction.lean @@ -172,7 +172,7 @@ theorem Monad.left_comparison (h : L ⊣ R) : L ⋙ Monad.comparison h = h.toMon rfl instance [R.Faithful] (h : L ⊣ R) : (Monad.comparison h).Faithful where - map_injective {_ _} _ _ w := R.map_injective (congr_arg Monad.Algebra.Hom.f w : _) + map_injective {_ _} _ _ w := R.map_injective (congr_arg Monad.Algebra.Hom.f w :) instance (T : Monad C) : (Monad.comparison T.adj).Full where map_surjective {_ _} f := ⟨⟨f.f, by simpa using f.h⟩, rfl⟩ @@ -218,7 +218,7 @@ theorem Comonad.left_comparison (h : L ⊣ R) : R ⋙ Comonad.comparison h = h.t instance Comonad.comparison_faithful_of_faithful [L.Faithful] (h : L ⊣ R) : (Comonad.comparison h).Faithful where - map_injective {_ _} _ _ w := L.map_injective (congr_arg Comonad.Coalgebra.Hom.f w : _) + map_injective {_ _} _ _ w := L.map_injective (congr_arg Comonad.Coalgebra.Hom.f w :) instance (G : Comonad C) : (Comonad.comparison G.adj).Full where map_surjective f := ⟨⟨f.f, by simpa using f.h⟩, rfl⟩ diff --git a/Mathlib/CategoryTheory/Monad/Kleisli.lean b/Mathlib/CategoryTheory/Monad/Kleisli.lean index e432473e5223b..9a251c5cb8b91 100644 --- a/Mathlib/CategoryTheory/Monad/Kleisli.lean +++ b/Mathlib/CategoryTheory/Monad/Kleisli.lean @@ -132,7 +132,7 @@ namespace Adjunction @[simps] def toCokleisli : C ⥤ Cokleisli U where obj X := (X : Cokleisli U) - map {X} {_} f := (U.ε.app X ≫ f : _) + map {X} {_} f := (U.ε.app X ≫ f :) map_comp {X} {Y} {_} f g := by -- Porting note: working around lack of unfold_projs change U.ε.app X ≫ f ≫ g = U.δ.app X ≫ U.map (U.ε.app X ≫ f) ≫ U.ε.app Y ≫ g diff --git a/Mathlib/CategoryTheory/Monad/Limits.lean b/Mathlib/CategoryTheory/Monad/Limits.lean index 8e99e8eace74d..6316344046718 100644 --- a/Mathlib/CategoryTheory/Monad/Limits.lean +++ b/Mathlib/CategoryTheory/Monad/Limits.lean @@ -347,7 +347,7 @@ theorem hasColimitsOfShape_of_reflective (R : D ⥤ C) [Reflective R] [HasColimi let t : IsColimit c := isColimitOfPreserves (monadicLeftAdjoint R) (colimit.isColimit _) apply HasColimit.mk ⟨_, (IsColimit.precomposeInvEquiv _ _).symm t⟩ apply - (isoWhiskerLeft F (asIso (monadicAdjunction R).counit) : _) ≪≫ F.rightUnitor + (isoWhiskerLeft F (asIso (monadicAdjunction R).counit) :) ≪≫ F.rightUnitor /-- If `C` has colimits then any reflective subcategory has colimits. -/ theorem hasColimits_of_reflective (R : D ⥤ C) [Reflective R] [HasColimitsOfSize.{v, u} C] : @@ -671,7 +671,7 @@ theorem hasLimitsOfShape_of_coreflective (R : D ⥤ C) [Coreflective R] [HasLimi let t : IsLimit c := isLimitOfPreserves (comonadicRightAdjoint R) (limit.isLimit _) apply HasLimit.mk ⟨_, (IsLimit.postcomposeHomEquiv _ _).symm t⟩ apply - (F.rightUnitor ≪≫ (isoWhiskerLeft F ((asIso (comonadicAdjunction R).unit) : _) )).symm + (F.rightUnitor ≪≫ (isoWhiskerLeft F ((asIso (comonadicAdjunction R).unit) :) )).symm /-- If `C` has limits then any coreflective subcategory has limits. -/ theorem hasLimits_of_coreflective (R : D ⥤ C) [Coreflective R] [HasLimitsOfSize.{v, u} C] : diff --git a/Mathlib/CategoryTheory/Preadditive/Mat.lean b/Mathlib/CategoryTheory/Preadditive/Mat.lean index af0bc591a2f18..4a2228de6b269 100644 --- a/Mathlib/CategoryTheory/Preadditive/Mat.lean +++ b/Mathlib/CategoryTheory/Preadditive/Mat.lean @@ -380,7 +380,7 @@ theorem additiveObjIsoBiproduct_naturality (F : Mat_ C ⥤ D) [Functor.Additive theorem additiveObjIsoBiproduct_naturality' (F : Mat_ C ⥤ D) [Functor.Additive F] {M N : Mat_ C} (f : M ⟶ N) : (additiveObjIsoBiproduct F M).inv ≫ F.map f = - biproduct.matrix (fun i j => F.map ((embedding C).map (f i j)) : _) ≫ + biproduct.matrix (fun i j => F.map ((embedding C).map (f i j)) :) ≫ (additiveObjIsoBiproduct F N).inv := by rw [Iso.inv_comp_eq, ← Category.assoc, Iso.eq_comp_inv, additiveObjIsoBiproduct_naturality] diff --git a/Mathlib/CategoryTheory/Sigma/Basic.lean b/Mathlib/CategoryTheory/Sigma/Basic.lean index d7550a04b3288..c4076b46e5492 100644 --- a/Mathlib/CategoryTheory/Sigma/Basic.lean +++ b/Mathlib/CategoryTheory/Sigma/Basic.lean @@ -210,9 +210,9 @@ variable {I} {K : Type w₃} -- so that the suitable category instances could be found /-- The functor `Sigma.map` applied to a composition is a composition of functors. -/ @[simps!] -def mapComp (f : K → J) (g : J → I) : map (fun x ↦ C (g x)) f ⋙ (map C g : _) ≅ map C (g ∘ f) := +def mapComp (f : K → J) (g : J → I) : map (fun x ↦ C (g x)) f ⋙ (map C g :) ≅ map C (g ∘ f) := (descUniq _ _) fun k => - (isoWhiskerRight (inclCompMap (fun i => C (g i)) f k) (map C g : _) : _) ≪≫ inclCompMap _ _ _ + (isoWhiskerRight (inclCompMap (fun i => C (g i)) f k) (map C g :) :) ≪≫ inclCompMap _ _ _ end diff --git a/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean b/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean index a7b6c780ed15f..e857f880260dd 100644 --- a/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean +++ b/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean @@ -172,11 +172,11 @@ theorem naturality [G.IsLocallyFull K] {X Y : C} (i : G.obj X ⟶ G.obj Y) : that is defined on a cover generated by the images of `G`. -/ noncomputable def pushforwardFamily {X} (x : ℱ.obj (op X)) : FamilyOfElements ℱ'.val (coverByImage G X) := fun _ _ hf => - ℱ'.val.map hf.some.lift.op <| α.app (op _) (ℱ.map hf.some.map.op x : _) + ℱ'.val.map hf.some.lift.op <| α.app (op _) (ℱ.map hf.some.map.op x) @[simp] theorem pushforwardFamily_def {X} (x : ℱ.obj (op X)) : pushforwardFamily α x = fun _ _ hf => - ℱ'.val.map hf.some.lift.op <| α.app (op _) (ℱ.map hf.some.map.op x : _) := rfl + ℱ'.val.map hf.some.lift.op <| α.app (op _) (ℱ.map hf.some.map.op x) := rfl @[simp] theorem pushforwardFamily_apply [G.IsLocallyFull K] diff --git a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean index 2679d293f850b..29b141d4386aa 100644 --- a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean +++ b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean @@ -95,7 +95,7 @@ namespace Sieve to check a family is compatible. -/ def SecondObj : Type max v u := - ∏ᶜ fun f : Σ(Y Z : _) (_ : Z ⟶ Y), { f' : Y ⟶ X // S f' } => P.obj (op f.2.1) + ∏ᶜ fun f : Σ (Y Z : _) (_ : Z ⟶ Y), { f' : Y ⟶ X // S f' } => P.obj (op f.2.1) variable {P S} diff --git a/Mathlib/CategoryTheory/Sites/Sheafification.lean b/Mathlib/CategoryTheory/Sites/Sheafification.lean index d8da476e5182c..be00c6666605c 100644 --- a/Mathlib/CategoryTheory/Sites/Sheafification.lean +++ b/Mathlib/CategoryTheory/Sites/Sheafification.lean @@ -136,7 +136,7 @@ variable {D} theorem isIso_toSheafify {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : IsIso (toSheafify J P) := by refine ⟨(sheafificationAdjunction J D |>.counit.app ⟨P, hP⟩).val, ?_, ?_⟩ - · change _ = (𝟙 (sheafToPresheaf J D ⋙ 𝟭 (Cᵒᵖ ⥤ D)) : _).app ⟨P, hP⟩ + · change _ = (𝟙 (sheafToPresheaf J D ⋙ 𝟭 (Cᵒᵖ ⥤ D)) :).app ⟨P, hP⟩ rw [← sheafificationAdjunction J D |>.right_triangle] rfl · change (sheafToPresheaf _ _).map _ ≫ _ = _ diff --git a/Mathlib/CategoryTheory/Sites/Subsheaf.lean b/Mathlib/CategoryTheory/Sites/Subsheaf.lean index 421d09f0798b1..b7b6807e53ccc 100644 --- a/Mathlib/CategoryTheory/Sites/Subsheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Subsheaf.lean @@ -98,7 +98,7 @@ instance {G G' : Subpresheaf F} (h : G ≤ G') : Mono (Subpresheaf.homOfLe h) := NatTrans.ext <| funext fun U => funext fun x => - Subtype.ext <| (congr_arg Subtype.val <| (congr_fun (congr_app e U) x : _) : _)⟩ + Subtype.ext <| (congr_arg Subtype.val <| (congr_fun (congr_app e U) x :) :)⟩ @[reassoc (attr := simp)] theorem Subpresheaf.homOfLe_ι {G G' : Subpresheaf F} (h : G ≤ G') : @@ -194,7 +194,7 @@ theorem Subpresheaf.eq_sheafify (h : Presieve.IsSheaf J F) (hG : Presieve.IsShea exact ((hG _ hs).amalgamate _ (G.family_of_elements_compatible s)).2 apply (h _ hs).isSeparatedFor.ext intro V i hi - exact (congr_arg Subtype.val ((hG _ hs).valid_glue (G.family_of_elements_compatible s) _ hi) : _) + exact (congr_arg Subtype.val ((hG _ hs).valid_glue (G.family_of_elements_compatible s) _ hi) :) theorem Subpresheaf.sheafify_isSheaf (hF : Presieve.IsSheaf J F) : Presieve.IsSheaf J (G.sheafify J).toPresheaf := by @@ -293,7 +293,7 @@ theorem Subpresheaf.to_sheafify_lift_unique (h : Presieve.IsSheaf J F') rintro V i hi dsimp at hi rw [← FunctorToTypes.naturality, ← FunctorToTypes.naturality] - exact (congr_fun (congr_app e <| op V) ⟨_, hi⟩ : _) + exact (congr_fun (congr_app e <| op V) ⟨_, hi⟩ :) theorem Subpresheaf.sheafify_le (h : G ≤ G') (hF : Presieve.IsSheaf J F) (hG' : Presieve.IsSheaf J G'.toPresheaf) : G.sheafify J ≤ G' := by @@ -358,7 +358,7 @@ instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ (Type (max v w))} (f : F ⟶ · intro x y e have := (NatTrans.mono_iff_mono_app f).mp hf X rw [mono_iff_injective] at this - exact this (congr_arg Subtype.val e : _) + exact this (congr_arg Subtype.val e :) · rintro ⟨_, ⟨x, rfl⟩⟩ exact ⟨x, rfl⟩ apply NatIso.isIso_of_isIso_app diff --git a/Mathlib/Computability/RegularExpressions.lean b/Mathlib/Computability/RegularExpressions.lean index c8dc9b8d41c7c..8082aa2d00f52 100644 --- a/Mathlib/Computability/RegularExpressions.lean +++ b/Mathlib/Computability/RegularExpressions.lean @@ -365,7 +365,7 @@ def map (f : α → β) : RegularExpression α → RegularExpression β protected theorem map_pow (f : α → β) (P : RegularExpression α) : ∀ n : ℕ, map f (P ^ n) = map f P ^ n | 0 => by unfold map; rfl - | n + 1 => (congr_arg (· * map f P) (RegularExpression.map_pow f P n) : _) + | n + 1 => (congr_arg (· * map f P) (RegularExpression.map_pow f P n) :) #adaptation_note /-- around nightly-2024-02-25, we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ diff --git a/Mathlib/Data/Complex/Module.lean b/Mathlib/Data/Complex/Module.lean index a322de00c4a36..6f3a26e7e4225 100644 --- a/Mathlib/Data/Complex/Module.lean +++ b/Mathlib/Data/Complex/Module.lean @@ -189,13 +189,13 @@ theorem Complex.coe_smul {E : Type*} [AddCommGroup E] [Module ℂ E] (x : ℝ) ( another scalar action of `M` on `E` whenever the action of `ℂ` commutes with the action of `M`. -/ instance (priority := 900) SMulCommClass.complexToReal {M E : Type*} [AddCommGroup E] [Module ℂ E] [SMul M E] [SMulCommClass ℂ M E] : SMulCommClass ℝ M E where - smul_comm r _ _ := (smul_comm (r : ℂ) _ _ : _) + smul_comm r _ _ := smul_comm (r : ℂ) _ _ /-- The scalar action of `ℝ` on a `ℂ`-module `E` induced by `Module.complexToReal` associates with another scalar action of `M` on `E` whenever the action of `ℂ` associates with the action of `M`. -/ instance IsScalarTower.complexToReal {M E : Type*} [AddCommGroup M] [Module ℂ M] [AddCommGroup E] [Module ℂ E] [SMul M E] [IsScalarTower ℂ M E] : IsScalarTower ℝ M E where - smul_assoc r _ _ := (smul_assoc (r : ℂ) _ _ : _) + smul_assoc r _ _ := smul_assoc (r : ℂ) _ _ -- check that the following instance is implied by the one above. example (E : Type*) [AddCommGroup E] [Module ℂ E] : IsScalarTower ℝ ℂ E := inferInstance diff --git a/Mathlib/Data/ENNReal/Operations.lean b/Mathlib/Data/ENNReal/Operations.lean index 6cea7623d8216..e97cc16c959c7 100644 --- a/Mathlib/Data/ENNReal/Operations.lean +++ b/Mathlib/Data/ENNReal/Operations.lean @@ -512,13 +512,13 @@ theorem smul_def {M : Type*} [MulAction ℝ≥0∞ M] (c : ℝ≥0) (x : M) : c rfl instance {M N : Type*} [MulAction ℝ≥0∞ M] [MulAction ℝ≥0∞ N] [SMul M N] [IsScalarTower ℝ≥0∞ M N] : - IsScalarTower ℝ≥0 M N where smul_assoc r := (smul_assoc (r : ℝ≥0∞) : _) + IsScalarTower ℝ≥0 M N where smul_assoc r := smul_assoc (r : ℝ≥0∞) instance smulCommClass_left {M N : Type*} [MulAction ℝ≥0∞ N] [SMul M N] [SMulCommClass ℝ≥0∞ M N] : - SMulCommClass ℝ≥0 M N where smul_comm r := (smul_comm (r : ℝ≥0∞) : _) + SMulCommClass ℝ≥0 M N where smul_comm r := smul_comm (r : ℝ≥0∞) instance smulCommClass_right {M N : Type*} [MulAction ℝ≥0∞ N] [SMul M N] [SMulCommClass M ℝ≥0∞ N] : - SMulCommClass M ℝ≥0 N where smul_comm m r := (smul_comm m (r : ℝ≥0∞) : _) + SMulCommClass M ℝ≥0 N where smul_comm m r := smul_comm m (r : ℝ≥0∞) /-- A `DistribMulAction` over `ℝ≥0∞` restricts to a `DistribMulAction` over `ℝ≥0`. -/ noncomputable instance {M : Type*} [AddMonoid M] [DistribMulAction ℝ≥0∞ M] : diff --git a/Mathlib/Data/Int/Cast/Lemmas.lean b/Mathlib/Data/Int/Cast/Lemmas.lean index f414c75984e4a..a9229d8aa827b 100644 --- a/Mathlib/Data/Int/Cast/Lemmas.lean +++ b/Mathlib/Data/Int/Cast/Lemmas.lean @@ -244,10 +244,10 @@ theorem ext_mint {f g : Multiplicative ℤ →* M} (h1 : f (ofAdd 1) = g (ofAdd theorem ext_int {f g : ℤ →* M} (h_neg_one : f (-1) = g (-1)) (h_nat : f.comp Int.ofNatHom.toMonoidHom = g.comp Int.ofNatHom.toMonoidHom) : f = g := by ext (x | x) - · exact (DFunLike.congr_fun h_nat x : _) + · exact (DFunLike.congr_fun h_nat x :) · rw [Int.negSucc_eq, ← neg_one_mul, f.map_mul, g.map_mul] congr 1 - exact mod_cast (DFunLike.congr_fun h_nat (x + 1) : _) + exact mod_cast (DFunLike.congr_fun h_nat (x + 1) :) end MonoidHom @@ -261,7 +261,7 @@ theorem ext_int {f g : ℤ →*₀ M} (h_neg_one : f (-1) = g (-1)) (h_nat : f.comp Int.ofNatHom.toMonoidWithZeroHom = g.comp Int.ofNatHom.toMonoidWithZeroHom) : f = g := toMonoidHom_injective <| MonoidHom.ext_int h_neg_one <| - MonoidHom.ext (DFunLike.congr_fun h_nat : _) + MonoidHom.ext (DFunLike.congr_fun h_nat :) end MonoidWithZeroHom diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 5f0e3516fab8b..6b908db84ff95 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -873,7 +873,7 @@ theorem flatMap_pure_eq_map (f : α → β) (l : List α) : l.flatMap (pure ∘ theorem flatMap_congr {l : List α} {f g : α → List β} (h : ∀ x ∈ l, f x = g x) : List.flatMap l f = List.flatMap l g := - (congr_arg List.flatten <| map_congr_left h : _) + (congr_arg List.flatten <| map_congr_left h :) @[deprecated (since := "2024-10-16")] alias bind_congr := flatMap_congr diff --git a/Mathlib/Data/Matrix/Defs.lean b/Mathlib/Data/Matrix/Defs.lean index d85e8a18a4b44..cfe899da9503e 100644 --- a/Mathlib/Data/Matrix/Defs.lean +++ b/Mathlib/Data/Matrix/Defs.lean @@ -465,7 +465,7 @@ theorem reindex_symm (eₘ : m ≃ l) (eₙ : n ≃ o) : theorem reindex_trans {l₂ o₂ : Type*} (eₘ : m ≃ l) (eₙ : n ≃ o) (eₘ₂ : l ≃ l₂) (eₙ₂ : o ≃ o₂) : (reindex eₘ eₙ).trans (reindex eₘ₂ eₙ₂) = (reindex (eₘ.trans eₘ₂) (eₙ.trans eₙ₂) : Matrix m n α ≃ _) := - Equiv.ext fun A => (A.submatrix_submatrix eₘ.symm eₙ.symm eₘ₂.symm eₙ₂.symm : _) + Equiv.ext fun A => (A.submatrix_submatrix eₘ.symm eₙ.symm eₘ₂.symm eₙ₂.symm :) theorem transpose_reindex (eₘ : m ≃ l) (eₙ : n ≃ o) (M : Matrix m n α) : (reindex eₘ eₙ M)ᵀ = reindex eₙ eₘ Mᵀ := diff --git a/Mathlib/Data/Matrix/Notation.lean b/Mathlib/Data/Matrix/Notation.lean index 66a14eeaec9ed..cafbf27798007 100644 --- a/Mathlib/Data/Matrix/Notation.lean +++ b/Mathlib/Data/Matrix/Notation.lean @@ -377,7 +377,7 @@ theorem submatrix_cons_row (A : Matrix m' n' α) (i : m') (row : Fin m → m') ( @[simp] theorem submatrix_updateRow_succAbove (A : Matrix (Fin m.succ) n' α) (v : n' → α) (f : o' → n') (i : Fin m.succ) : (A.updateRow i v).submatrix i.succAbove f = A.submatrix i.succAbove f := - ext fun r s => (congr_fun (updateRow_ne (Fin.succAbove_ne i r) : _ = A _) (f s) : _) + ext fun r s => (congr_fun (updateRow_ne (Fin.succAbove_ne i r) : _ = A _) (f s) :) /-- Updating a column then removing it is the same as removing it. -/ @[simp] diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index fb7ef70dca4ff..1fad797f40bcd 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -207,13 +207,13 @@ theorem smul_def {M : Type*} [MulAction ℝ M] (c : ℝ≥0) (x : M) : c • x = rfl instance {M N : Type*} [MulAction ℝ M] [MulAction ℝ N] [SMul M N] [IsScalarTower ℝ M N] : - IsScalarTower ℝ≥0 M N where smul_assoc r := (smul_assoc (r : ℝ) : _) + IsScalarTower ℝ≥0 M N where smul_assoc r := smul_assoc (r : ℝ) instance smulCommClass_left {M N : Type*} [MulAction ℝ N] [SMul M N] [SMulCommClass ℝ M N] : - SMulCommClass ℝ≥0 M N where smul_comm r := (smul_comm (r : ℝ) : _) + SMulCommClass ℝ≥0 M N where smul_comm r := smul_comm (r : ℝ) instance smulCommClass_right {M N : Type*} [MulAction ℝ N] [SMul M N] [SMulCommClass M ℝ N] : - SMulCommClass M ℝ≥0 N where smul_comm m r := (smul_comm m (r : ℝ) : _) + SMulCommClass M ℝ≥0 N where smul_comm m r := smul_comm m (r : ℝ) /-- A `DistribMulAction` over `ℝ` restricts to a `DistribMulAction` over `ℝ≥0`. -/ instance {M : Type*} [AddMonoid M] [DistribMulAction ℝ M] : DistribMulAction ℝ≥0 M := @@ -479,7 +479,7 @@ theorem zero_le_coe {q : ℝ≥0} : 0 ≤ (q : ℝ) := instance instOrderedSMul {M : Type*} [OrderedAddCommMonoid M] [Module ℝ M] [OrderedSMul ℝ M] : OrderedSMul ℝ≥0 M where - smul_lt_smul_of_pos hab hc := (smul_lt_smul_of_pos_left hab (NNReal.coe_pos.2 hc) : _) + smul_lt_smul_of_pos hab hc := (smul_lt_smul_of_pos_left hab (NNReal.coe_pos.2 hc) :) lt_of_smul_lt_smul_of_pos {_ _ c} hab _ := lt_of_smul_lt_smul_of_nonneg_left (by exact hab) (NNReal.coe_nonneg c) diff --git a/Mathlib/Data/PFunctor/Multivariate/Basic.lean b/Mathlib/Data/PFunctor/Multivariate/Basic.lean index 319632029d761..30e5c5bdb6316 100644 --- a/Mathlib/Data/PFunctor/Multivariate/Basic.lean +++ b/Mathlib/Data/PFunctor/Multivariate/Basic.lean @@ -109,7 +109,7 @@ end Const /-- Functor composition on polynomial functors -/ def comp (P : MvPFunctor.{u} n) (Q : Fin2 n → MvPFunctor.{u} m) : MvPFunctor m where A := Σ a₂ : P.1, ∀ i, P.2 a₂ i → (Q i).1 - B a i := Σ(j : _) (b : P.2 a.1 j), (Q j).2 (a.snd j b) i + B a i := Σ (j : _) (b : P.2 a.1 j), (Q j).2 (a.snd j b) i variable {P} {Q : Fin2 n → MvPFunctor.{u} m} {α β : TypeVec.{u} m} diff --git a/Mathlib/Data/PFunctor/Multivariate/M.lean b/Mathlib/Data/PFunctor/Multivariate/M.lean index 3760a1050ad44..758d698261463 100644 --- a/Mathlib/Data/PFunctor/Multivariate/M.lean +++ b/Mathlib/Data/PFunctor/Multivariate/M.lean @@ -238,7 +238,7 @@ theorem M.bisim {α : TypeVec n} (R : P.M α → P.M α → Prop) rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩ cases h'.symm.trans e₁' cases h'.symm.trans e₂' - · exact (congr_fun (congr_fun e₃ i) c : _) + · exact (congr_fun (congr_fun e₃ i) c :) · exact IH _ _ (h'' _) theorem M.bisim₀ {α : TypeVec n} (R : P.M α → P.M α → Prop) (h₀ : Equivalence R) diff --git a/Mathlib/Data/Prod/Basic.lean b/Mathlib/Data/Prod/Basic.lean index 37cb24c949727..d68eab7f60f81 100644 --- a/Mathlib/Data/Prod/Basic.lean +++ b/Mathlib/Data/Prod/Basic.lean @@ -251,10 +251,10 @@ theorem map_injective [Nonempty α] [Nonempty β] {f : α → γ} {g : β → δ ⟨fun a₁ a₂ ha => by inhabit β injection - @h (a₁, default) (a₂, default) (congr_arg (fun c : γ => Prod.mk c (g default)) ha : _), + @h (a₁, default) (a₂, default) (congr_arg (fun c : γ => Prod.mk c (g default)) ha :), fun b₁ b₂ hb => by inhabit α - injection @h (default, b₁) (default, b₂) (congr_arg (Prod.mk (f default)) hb : _)⟩, + injection @h (default, b₁) (default, b₂) (congr_arg (Prod.mk (f default)) hb :)⟩, fun h => h.1.prodMap h.2⟩ @[simp] diff --git a/Mathlib/Data/Sum/Basic.lean b/Mathlib/Data/Sum/Basic.lean index 9631344ff2cbf..5dd68ca13d171 100644 --- a/Mathlib/Data/Sum/Basic.lean +++ b/Mathlib/Data/Sum/Basic.lean @@ -198,8 +198,8 @@ open Function theorem map_injective {f : α → γ} {g : β → δ} : Injective (Sum.map f g) ↔ Injective f ∧ Injective g := ⟨fun h => - ⟨fun a₁ a₂ ha => inl_injective <| @h (inl a₁) (inl a₂) (congr_arg inl ha : _), fun b₁ b₂ hb => - inr_injective <| @h (inr b₁) (inr b₂) (congr_arg inr hb : _)⟩, + ⟨fun a₁ a₂ ha => inl_injective <| @h (inl a₁) (inl a₂) (congr_arg inl ha :), fun b₁ b₂ hb => + inr_injective <| @h (inr b₁) (inr b₂) (congr_arg inr hb :)⟩, fun h => h.1.sum_map h.2⟩ @[simp] diff --git a/Mathlib/Data/TypeVec.lean b/Mathlib/Data/TypeVec.lean index 88be36a0d3c00..7c4cbef504339 100644 --- a/Mathlib/Data/TypeVec.lean +++ b/Mathlib/Data/TypeVec.lean @@ -376,7 +376,7 @@ theorem const_nil {β} (x : β) (α : TypeVec 0) : TypeVec.const x α = nilFun : @[typevec] theorem repeat_eq_append1 {β} {n} (α : TypeVec n) : - repeatEq (α ::: β) = splitFun (α := (α ⊗ α) ::: _ ) + repeatEq (α ::: β) = splitFun (α := (α ⊗ α) ::: _) (α' := («repeat» n Prop) ::: _) (repeatEq α) (uncurry Eq) := by induction n <;> rfl diff --git a/Mathlib/Data/W/Basic.lean b/Mathlib/Data/W/Basic.lean index 7c1f339cc49d0..83c3b89cad539 100644 --- a/Mathlib/Data/W/Basic.lean +++ b/Mathlib/Data/W/Basic.lean @@ -82,7 +82,7 @@ theorem elim_injective (γ : Type*) (fγ : (Σa : α, β a → γ) → γ) | ⟨a₁, f₁⟩, ⟨a₂, f₂⟩, h => by obtain ⟨rfl, h⟩ := Sigma.mk.inj_iff.mp (fγ_injective h) congr with x - exact elim_injective γ fγ fγ_injective (congr_fun (eq_of_heq h) x : _) + exact elim_injective γ fγ fγ_injective (congr_fun (eq_of_heq h) x :) instance [hα : IsEmpty α] : IsEmpty (WType β) := ⟨fun w => WType.recOn w (IsEmpty.elim hα)⟩ diff --git a/Mathlib/Dynamics/FixedPoints/Basic.lean b/Mathlib/Dynamics/FixedPoints/Basic.lean index 78081cb348764..ed9a9b65367ad 100644 --- a/Mathlib/Dynamics/FixedPoints/Basic.lean +++ b/Mathlib/Dynamics/FixedPoints/Basic.lean @@ -35,7 +35,7 @@ open Function (Commute) /-- Every point is a fixed point of `id`. -/ theorem isFixedPt_id (x : α) : IsFixedPt id x := - (rfl : _) + (rfl :) namespace IsFixedPt diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index 80352130ce0b4..e0d6ba6cd6a31 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -928,7 +928,7 @@ theorem exists_finset_of_mem_supr' {ι : Type*} {f : ι → IntermediateField F theorem exists_finset_of_mem_supr'' {ι : Type*} {f : ι → IntermediateField F E} (h : ∀ i, Algebra.IsAlgebraic F (f i)) {x : E} (hx : x ∈ ⨆ i, f i) : - ∃ s : Finset (Σ i, f i), x ∈ ⨆ i ∈ s, adjoin F ((minpoly F (i.2 : _)).rootSet E) := by + ∃ s : Finset (Σ i, f i), x ∈ ⨆ i ∈ s, adjoin F ((minpoly F (i.2 :)).rootSet E) := by -- Porting note: writing `fun i x1 hx1 => ...` does not work. refine exists_finset_of_mem_iSup (SetLike.le_def.mp (iSup_le (fun i => ?_)) hx) intro x1 hx1 @@ -1099,7 +1099,7 @@ noncomputable def adjoinRootEquivAdjoin (h : IsIntegral F α) : AlgEquiv.ofBijective (AdjoinRoot.liftHom (minpoly F α) (AdjoinSimple.gen F α) (aeval_gen_minpoly F α)) (by - set f := AdjoinRoot.lift _ _ (aeval_gen_minpoly F α : _) + set f := AdjoinRoot.lift _ _ (aeval_gen_minpoly F α :) haveI := Fact.mk (minpoly.irreducible h) constructor · exact RingHom.injective f @@ -1163,7 +1163,7 @@ theorem isAlgebraic_adjoin_simple {x : L} (hx : IsIntegral K x) : Algebra.IsAlge @[stacks 09GN] theorem adjoin.finrank {x : L} (hx : IsIntegral K x) : Module.finrank K K⟮x⟯ = (minpoly K x).natDegree := by - rw [PowerBasis.finrank (adjoin.powerBasis hx : _)] + rw [PowerBasis.finrank (adjoin.powerBasis hx :)] rfl /-- If `K / E / F` is a field extension tower, `S ⊂ K` is such that `F(S) = K`, diff --git a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean index a8d5a85385e1b..156df9e238ca5 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean @@ -382,7 +382,7 @@ noncomputable def equivOfAlgebraic' [Nontrivial S] [NoZeroSMulDivisors R S] letI : NoZeroSMulDivisors R L := NoZeroSMulDivisors.of_algebraMap_injective <| by rw [IsScalarTower.algebraMap_eq R S L] exact (Function.Injective.comp (NoZeroSMulDivisors.algebraMap_injective S L) - (NoZeroSMulDivisors.algebraMap_injective R S) : _) + (NoZeroSMulDivisors.algebraMap_injective R S) :) letI : IsAlgClosure R L := { isAlgClosed := IsAlgClosure.isAlgClosed S isAlgebraic := ‹_› } diff --git a/Mathlib/FieldTheory/Normal.lean b/Mathlib/FieldTheory/Normal.lean index 12486d2a18034..c209741701297 100644 --- a/Mathlib/FieldTheory/Normal.lean +++ b/Mathlib/FieldTheory/Normal.lean @@ -142,7 +142,7 @@ instance normal_iSup {ι : Type*} (t : ι → IntermediateField F K) [h : ∀ i, Normal F (⨆ i, t i : IntermediateField F K) := by refine { toIsAlgebraic := isAlgebraic_iSup fun i => (h i).1, splits' := fun x => ?_ } obtain ⟨s, hx⟩ := exists_finset_of_mem_supr'' (fun i => (h i).1) x.2 - let E : IntermediateField F K := ⨆ i ∈ s, adjoin F ((minpoly F (i.2 : _)).rootSet K) + let E : IntermediateField F K := ⨆ i ∈ s, adjoin F ((minpoly F (i.2 :)).rootSet K) have hF : Normal F E := by haveI : IsSplittingField F E (∏ i ∈ s, minpoly F i.snd) := by refine isSplittingField_iSup ?_ fun i _ => adjoin_rootSet_isSplittingField ?_ diff --git a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean index 38b8fd8f39f73..e8a0505d2e9d8 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean @@ -118,7 +118,7 @@ protected theorem ContMDiffWithinAt.mfderivWithin {x₀ : N} {f : N → M → M' · apply inter_subset_left.trans rw [preimage_subset_iff] intro a ha - refine ⟨PartialEquiv.map_source _ (inter_subset_right ha : _), ?_⟩ + refine ⟨PartialEquiv.map_source _ (inter_subset_right ha :), ?_⟩ rw [mem_preimage, PartialEquiv.left_inv (extChartAt I (g x₀))] · exact hu (inter_subset_left ha) · exact (inter_subset_right ha :) diff --git a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean index 2e0b7b1b65cce..704caf6b4ef1e 100644 --- a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean +++ b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean @@ -97,7 +97,7 @@ theorem congr_nhdsWithin' {s : Set H} {x : H} {f g : H → H'} (h1 : f =ᶠ[𝓝 (hG.congr_iff_nhdsWithin h1 h2).mpr hP theorem congr_iff {s : Set H} {x : H} {f g : H → H'} (h : f =ᶠ[𝓝 x] g) : P f s x ↔ P g s x := - hG.congr_iff_nhdsWithin (mem_nhdsWithin_of_mem_nhds h) (mem_of_mem_nhds h : _) + hG.congr_iff_nhdsWithin (mem_nhdsWithin_of_mem_nhds h) (mem_of_mem_nhds h :) theorem congr {s : Set H} {x : H} {f g : H → H'} (h : f =ᶠ[𝓝 x] g) (hP : P f s x) : P g s x := (hG.congr_iff h).mp hP @@ -379,7 +379,7 @@ theorem liftPropWithinAt_congr_of_eventuallyEq (h : LiftPropWithinAt P g s x) (h theorem liftPropWithinAt_congr_of_eventuallyEq_of_mem (h : LiftPropWithinAt P g s x) (h₁ : g' =ᶠ[𝓝[s] x] g) (h₂ : x ∈ s) : LiftPropWithinAt P g' s x := - liftPropWithinAt_congr_of_eventuallyEq hG h h₁ (mem_of_mem_nhdsWithin h₂ h₁ : _) + liftPropWithinAt_congr_of_eventuallyEq hG h h₁ (mem_of_mem_nhdsWithin h₂ h₁ :) theorem liftPropWithinAt_congr_iff_of_eventuallyEq (h₁ : g' =ᶠ[𝓝[s] x] g) (hx : g' x = g x) : LiftPropWithinAt P g' s x ↔ LiftPropWithinAt P g s x := diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean index 9386f8ad261ec..92e871ba9dfed 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean @@ -227,11 +227,11 @@ section extChartAt variable [SmoothManifoldWithCorners I M] {s : Set M} {x y : M} {z : E} theorem hasMFDerivAt_extChartAt (h : y ∈ (chartAt H x).source) : - HasMFDerivAt I 𝓘(𝕜, E) (extChartAt I x) y (mfderiv I I (chartAt H x) y : _) := + HasMFDerivAt I 𝓘(𝕜, E) (extChartAt I x) y (mfderiv I I (chartAt H x) y :) := I.hasMFDerivAt.comp y ((mdifferentiable_chart x).mdifferentiableAt h).hasMFDerivAt theorem hasMFDerivWithinAt_extChartAt (h : y ∈ (chartAt H x).source) : - HasMFDerivWithinAt I 𝓘(𝕜, E) (extChartAt I x) s y (mfderiv I I (chartAt H x) y : _) := + HasMFDerivWithinAt I 𝓘(𝕜, E) (extChartAt I x) s y (mfderiv I I (chartAt H x) y :) := (hasMFDerivAt_extChartAt h).hasMFDerivWithinAt theorem mdifferentiableAt_extChartAt (h : y ∈ (chartAt H x).source) : diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean index bd60a56508a1f..7e2cc0458ea20 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean @@ -675,7 +675,7 @@ theorem mdifferentiableWithinAt_congr_nhds {t : Set M} (hst : 𝓝[s] x = 𝓝[t protected theorem MDifferentiableWithinAt.mfderivWithin (h : MDifferentiableWithinAt I I' f s x) : mfderivWithin I I' f s x = - fderivWithin 𝕜 (writtenInExtChartAt I I' x f : _) ((extChartAt I x).symm ⁻¹' s ∩ range I) + fderivWithin 𝕜 (writtenInExtChartAt I I' x f :) ((extChartAt I x).symm ⁻¹' s ∩ range I) ((extChartAt I x) x) := by simp only [mfderivWithin, h, if_pos] @@ -687,7 +687,7 @@ theorem MDifferentiableAt.hasMFDerivAt (h : MDifferentiableAt I I' f x) : protected theorem MDifferentiableAt.mfderiv (h : MDifferentiableAt I I' f x) : mfderiv I I' f x = - fderivWithin 𝕜 (writtenInExtChartAt I I' x f : _) (range I) ((extChartAt I x) x) := by + fderivWithin 𝕜 (writtenInExtChartAt I I' x f :) (range I) ((extChartAt I x) x) := by simp only [mfderiv, h, if_pos] protected theorem HasMFDerivAt.mfderiv (h : HasMFDerivAt I I' f x f') : mfderiv I I' f x = f' := @@ -932,7 +932,7 @@ theorem HasMFDerivWithinAt.congr_mono (h : HasMFDerivWithinAt I I' f s x f') theorem HasMFDerivAt.congr_of_eventuallyEq (h : HasMFDerivAt I I' f x f') (h₁ : f₁ =ᶠ[𝓝 x] f) : HasMFDerivAt I I' f₁ x f' := by rw [← hasMFDerivWithinAt_univ] at h ⊢ - apply h.congr_of_eventuallyEq _ (mem_of_mem_nhds h₁ : _) + apply h.congr_of_eventuallyEq _ (mem_of_mem_nhds h₁ :) rwa [nhdsWithin_univ] theorem MDifferentiableWithinAt.congr_of_eventuallyEq (h : MDifferentiableWithinAt I I' f s x) @@ -1013,7 +1013,7 @@ theorem tangentMapWithin_congr (h : ∀ x ∈ s, f x = f₁ x) (p : TangentBundl theorem Filter.EventuallyEq.mfderiv_eq (hL : f₁ =ᶠ[𝓝 x] f) : mfderiv I I' f₁ x = mfderiv I I' f x := by - have A : f₁ x = f x := (mem_of_mem_nhds hL : _) + have A : f₁ x = f x := (mem_of_mem_nhds hL :) rw [← mfderivWithin_univ, ← mfderivWithin_univ] rw [← nhdsWithin_univ] at hL exact hL.mfderivWithin_eq (uniqueMDiffWithinAt_univ I) A diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean index b7c3206ec3989..1629d372ecce9 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean @@ -340,7 +340,7 @@ variable (I I') in `f x`. -/ def mfderiv (f : M → M') (x : M) : TangentSpace I x →L[𝕜] TangentSpace I' (f x) := if MDifferentiableAt I I' f x then - (fderivWithin 𝕜 (writtenInExtChartAt I I' x f : E → E') (range I) ((extChartAt I x) x) : _) + (fderivWithin 𝕜 (writtenInExtChartAt I I' x f : E → E') (range I) ((extChartAt I x) x) :) else 0 variable (I I') in diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean index 45478ac73f241..a3b61da96f50c 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean @@ -74,7 +74,7 @@ noncomputable def coproduct : LocallyRingedSpace where (F.obj i).isLocalRing _ exact (asIso ((colimit.ι (C := SheafedSpace.{u+1, u, u} CommRingCatMax.{u, u}) - (F ⋙ forgetToSheafedSpace) i : _).stalkMap y)).symm.commRingCatIsoToRingEquiv.isLocalRing + (F ⋙ forgetToSheafedSpace) i :).stalkMap y)).symm.commRingCatIsoToRingEquiv.isLocalRing /-- The explicit coproduct cofan for `F : discrete ι ⥤ LocallyRingedSpace`. -/ noncomputable def coproductCofan : Cocone F where @@ -100,7 +100,7 @@ noncomputable def coproductCofanIsColimit : IsColimit (coproductCofan F) where erw [← this, PresheafedSpace.stalkMap.congr_hom _ _ (colimit.ι_desc (C := SheafedSpace.{u+1, u, u} CommRingCatMax.{u, u}) - (forgetToSheafedSpace.mapCocone s) i : _)] + (forgetToSheafedSpace.mapCocone s) i :)] haveI : IsLocalHom (((forgetToSheafedSpace.mapCocone s).ι.app i).stalkMap y).hom := @@ -134,7 +134,7 @@ namespace HasCoequalizer @[instance] theorem coequalizer_π_app_isLocalHom (U : TopologicalSpace.Opens (coequalizer f.toShHom g.toShHom).carrier) : - IsLocalHom ((coequalizer.π f.toShHom g.toShHom : _).c.app (op U)).hom := by + IsLocalHom ((coequalizer.π f.toShHom g.toShHom :).c.app (op U)).hom := by have := ι_comp_coequalizerComparison f.toShHom g.toShHom SheafedSpace.forgetToPresheafedSpace rw [← PreservesCoequalizer.iso_hom] at this erw [SheafedSpace.congr_app this.symm (op U)] @@ -223,7 +223,7 @@ theorem imageBasicOpen_image_open : @[instance] theorem coequalizer_π_stalk_isLocalHom (x : Y) : - IsLocalHom ((coequalizer.π f.toShHom g.toShHom : _).stalkMap x).hom := by + IsLocalHom ((coequalizer.π f.toShHom g.toShHom :).stalkMap x).hom := by constructor rintro a ha rcases TopCat.Presheaf.germ_exist (C := CommRingCat) _ _ a with ⟨U, hU, s, rfl⟩ @@ -240,13 +240,13 @@ theorem coequalizer_π_stalk_isLocalHom (x : Y) : SetLike.ext' hV.symm have V_open : IsOpen ((coequalizer.π f.toShHom g.toShHom).base '' V.1) := imageBasicOpen_image_open f g U s - have VleU : (⟨(coequalizer.π f.toShHom g.toShHom).base '' V.1, V_open⟩ : _) ≤ U := + have VleU : ⟨(coequalizer.π f.toShHom g.toShHom).base '' V.1, V_open⟩ ≤ U := Set.image_subset_iff.mpr (Y.toRingedSpace.basicOpen_le _) have hxV : x ∈ V := ⟨hU, ha⟩ rw [← CommRingCat.germ_res_apply (coequalizer f.toShHom g.toShHom).presheaf (homOfLE VleU) _ (@Set.mem_image_of_mem _ _ (coequalizer.π f.toShHom g.toShHom).base x V.1 hxV) s] apply RingHom.isUnit_map - rw [← isUnit_map_iff ((coequalizer.π f.toShHom g.toShHom : _).c.app _).hom, + rw [← isUnit_map_iff ((coequalizer.π f.toShHom g.toShHom :).c.app _).hom, ← CommRingCat.comp_apply, NatTrans.naturality, CommRingCat.comp_apply, ← isUnit_map_iff (Y.presheaf.map (eqToHom hV').op).hom] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11224): change `rw` to `erw` @@ -266,7 +266,7 @@ noncomputable def coequalizer : LocallyRingedSpace where isLocalRing x := by obtain ⟨y, rfl⟩ := (TopCat.epi_iff_surjective (coequalizer.π f.toShHom g.toShHom).base).mp inferInstance x - exact ((coequalizer.π f.toShHom g.toShHom : _).stalkMap y).hom.domain_isLocalRing + exact ((coequalizer.π f.toShHom g.toShHom :).stalkMap y).hom.domain_isLocalRing /-- The explicit coequalizer cofork of locally ringed spaces. -/ noncomputable def coequalizerCofork : Cofork f g := diff --git a/Mathlib/Geometry/RingedSpace/Stalks.lean b/Mathlib/Geometry/RingedSpace/Stalks.lean index 3f2955405ac1d..96927f0280b51 100644 --- a/Mathlib/Geometry/RingedSpace/Stalks.lean +++ b/Mathlib/Geometry/RingedSpace/Stalks.lean @@ -169,7 +169,7 @@ instance isIso {X Y : PresheafedSpace.{_, _, v} C} (α : X ⟶ Y) [IsIso α] (x -- `X.stalk x ⟶ X.stalk ((α ≫ β).base x)`. refine ⟨eqToHom (show X.presheaf.stalk x = X.presheaf.stalk ((α ≫ β).base x) by rw [h_eq]) ≫ - (β.stalkMap (α.base x) : _), + (β.stalkMap (α.base x) :), ?_, ?_⟩ · rw [← Category.assoc, congr_point α x ((α ≫ β).base x) h_eq.symm, Category.assoc] erw [← stalkMap.comp β α (α.base x)] diff --git a/Mathlib/GroupTheory/GroupAction/Defs.lean b/Mathlib/GroupTheory/GroupAction/Defs.lean index fa15f5e7d6253..d2cba75e644f6 100644 --- a/Mathlib/GroupTheory/GroupAction/Defs.lean +++ b/Mathlib/GroupTheory/GroupAction/Defs.lean @@ -113,7 +113,7 @@ variable (M) @[to_additive] theorem fixed_eq_iInter_fixedBy : fixedPoints M α = ⋂ m : M, fixedBy α m := Set.ext fun _ => - ⟨fun hx => Set.mem_iInter.2 fun m => hx m, fun hx m => (Set.mem_iInter.1 hx m : _)⟩ + ⟨fun hx => Set.mem_iInter.2 fun m => hx m, fun hx m => (Set.mem_iInter.1 hx m :)⟩ variable {M α} diff --git a/Mathlib/GroupTheory/Perm/Finite.lean b/Mathlib/GroupTheory/Perm/Finite.lean index feec477ac45f6..87b337db2fa4f 100644 --- a/Mathlib/GroupTheory/Perm/Finite.lean +++ b/Mathlib/GroupTheory/Perm/Finite.lean @@ -63,7 +63,7 @@ theorem perm_inv_on_of_perm_on_finset {s : Finset α} {f : Perm α} (h : ∀ x simp only [inv_apply_self] theorem perm_inv_mapsTo_of_mapsTo (f : Perm α) {s : Set α} [Finite s] (h : Set.MapsTo f s s) : - Set.MapsTo (f⁻¹ : _) s s := by + Set.MapsTo (f⁻¹ :) s s := by cases nonempty_fintype s exact fun x hx => Set.mem_toFinset.mp <| @@ -73,7 +73,7 @@ theorem perm_inv_mapsTo_of_mapsTo (f : Perm α) {s : Set α} [Finite s] (h : Set @[simp] theorem perm_inv_mapsTo_iff_mapsTo {f : Perm α} {s : Set α} [Finite s] : - Set.MapsTo (f⁻¹ : _) s s ↔ Set.MapsTo f s s := + Set.MapsTo (f⁻¹ :) s s ↔ Set.MapsTo f s s := ⟨perm_inv_mapsTo_of_mapsTo f⁻¹, perm_inv_mapsTo_of_mapsTo f⟩ theorem perm_inv_on_of_perm_on_finite {f : Perm α} {p : α → Prop} [Finite { x // p x }] diff --git a/Mathlib/GroupTheory/QuotientGroup/Defs.lean b/Mathlib/GroupTheory/QuotientGroup/Defs.lean index 37c1c47dc4036..a4bed8c014303 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Defs.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Defs.lean @@ -84,7 +84,7 @@ See note [partially-applied ext lemmas]. -/ See note [partially-applied ext lemmas]. "] theorem monoidHom_ext ⦃f g : G ⧸ N →* M⦄ (h : f.comp (mk' N) = g.comp (mk' N)) : f = g := - MonoidHom.ext fun x => QuotientGroup.induction_on x <| (DFunLike.congr_fun h : _) + MonoidHom.ext fun x => QuotientGroup.induction_on x <| (DFunLike.congr_fun h :) @[to_additive (attr := simp)] theorem eq_one_iff {N : Subgroup G} [N.Normal] (x : G) : (x : G ⧸ N) = 1 ↔ x ∈ N := by diff --git a/Mathlib/GroupTheory/SpecificGroups/Alternating.lean b/Mathlib/GroupTheory/SpecificGroups/Alternating.lean index df3d8243d1cdb..f24b630fe1377 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Alternating.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Alternating.lean @@ -231,7 +231,7 @@ theorem normalClosure_finRotate_five : normalClosure ({⟨finRotate 5, SetLike.mem_coe.1 (subset_normalClosure (Set.mem_singleton _)) exact (mul_mem (Subgroup.normalClosure_normal.conj_mem _ h -- Porting note: added `: _` - ⟨Fin.cycleRange 2, Fin.isThreeCycle_cycleRange_two.mem_alternatingGroup⟩) (inv_mem h) : _)) + ⟨Fin.cycleRange 2, Fin.isThreeCycle_cycleRange_two.mem_alternatingGroup⟩) (inv_mem h) :)) /-- The normal closure of $(04)(13)$ within $A_5$ is the whole group. This will be used to show that the normal closure of any permutation of cycle type $(2,2)$ is the whole group. diff --git a/Mathlib/GroupTheory/Submonoid/Inverses.lean b/Mathlib/GroupTheory/Submonoid/Inverses.lean index 997f9b0ea0a44..8af3344ef8ae6 100644 --- a/Mathlib/GroupTheory/Submonoid/Inverses.lean +++ b/Mathlib/GroupTheory/Submonoid/Inverses.lean @@ -70,7 +70,7 @@ theorem leftInv_leftInv_le : S.leftInv.leftInv ≤ S := by rw [← mul_one x, ← h₁, ← mul_assoc, h₂, one_mul] @[to_additive] -theorem unit_mem_leftInv (x : Mˣ) (hx : (x : M) ∈ S) : ((x⁻¹ : _) : M) ∈ S.leftInv := +theorem unit_mem_leftInv (x : Mˣ) (hx : (x : M) ∈ S) : ((x⁻¹ :) : M) ∈ S.leftInv := ⟨⟨x, hx⟩, x.inv_val⟩ @[to_additive] diff --git a/Mathlib/LinearAlgebra/Alternating/Basic.lean b/Mathlib/LinearAlgebra/Alternating/Basic.lean index cde969096e601..f45db0f96d8da 100644 --- a/Mathlib/LinearAlgebra/Alternating/Basic.lean +++ b/Mathlib/LinearAlgebra/Alternating/Basic.lean @@ -820,11 +820,11 @@ def alternatization : MultilinearMap R (fun _ : ι => M) N' →+ M [⋀^ι]→ zero_apply, smul_zero, Finset.sum_const_zero, AlternatingMap.zero_apply] theorem alternatization_def (m : MultilinearMap R (fun _ : ι => M) N') : - ⇑(alternatization m) = (∑ σ : Perm ι, Equiv.Perm.sign σ • m.domDomCongr σ : _) := + ⇑(alternatization m) = (∑ σ : Perm ι, Equiv.Perm.sign σ • m.domDomCongr σ :) := rfl theorem alternatization_coe (m : MultilinearMap R (fun _ : ι => M) N') : - ↑(alternatization m) = (∑ σ : Perm ι, Equiv.Perm.sign σ • m.domDomCongr σ : _) := + ↑(alternatization m) = (∑ σ : Perm ι, Equiv.Perm.sign σ • m.domDomCongr σ :) := coe_injective rfl theorem alternatization_apply (m : MultilinearMap R (fun _ : ι => M) N') (v : ι → M) : diff --git a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean index 47aa85348d3ba..1c1eeeec108bc 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean @@ -90,10 +90,10 @@ protected theorem eq (H : B.IsSymm) (x y : M) : B x y = B y x := theorem isRefl (H : B.IsSymm) : B.IsRefl := fun x y H1 => H x y ▸ H1 protected theorem add {B₁ B₂ : BilinForm R M} (hB₁ : B₁.IsSymm) (hB₂ : B₂.IsSymm) : - (B₁ + B₂).IsSymm := fun x y => (congr_arg₂ (· + ·) (hB₁ x y) (hB₂ x y) : _) + (B₁ + B₂).IsSymm := fun x y => (congr_arg₂ (· + ·) (hB₁ x y) (hB₂ x y) :) protected theorem sub {B₁ B₂ : BilinForm R₁ M₁} (hB₁ : B₁.IsSymm) (hB₂ : B₂.IsSymm) : - (B₁ - B₂).IsSymm := fun x y => (congr_arg₂ Sub.sub (hB₁ x y) (hB₂ x y) : _) + (B₁ - B₂).IsSymm := fun x y => (congr_arg₂ Sub.sub (hB₁ x y) (hB₂ x y) :) protected theorem neg {B : BilinForm R₁ M₁} (hB : B.IsSymm) : (-B).IsSymm := fun x y => congr_arg Neg.neg (hB x y) @@ -133,7 +133,7 @@ theorem eq_of_add_add_eq_zero [IsCancelAdd R] {a b c : M} (H : B.IsAlt) (hAdd : B a b = B b c := LinearMap.IsAlt.eq_of_add_add_eq_zero H hAdd protected theorem add {B₁ B₂ : BilinForm R M} (hB₁ : B₁.IsAlt) (hB₂ : B₂.IsAlt) : (B₁ + B₂).IsAlt := - fun x => (congr_arg₂ (· + ·) (hB₁ x) (hB₂ x) : _).trans <| add_zero _ + fun x => (congr_arg₂ (· + ·) (hB₁ x) (hB₂ x) :).trans <| add_zero _ protected theorem sub {B₁ B₂ : BilinForm R₁ M₁} (hB₁ : B₁.IsAlt) (hB₂ : B₂.IsAlt) : (B₁ - B₂).IsAlt := fun x => (congr_arg₂ Sub.sub (hB₁ x) (hB₂ x)).trans <| sub_zero _ diff --git a/Mathlib/LinearAlgebra/BilinearMap.lean b/Mathlib/LinearAlgebra/BilinearMap.lean index 176ef9be83217..e1b2be24a3275 100644 --- a/Mathlib/LinearAlgebra/BilinearMap.lean +++ b/Mathlib/LinearAlgebra/BilinearMap.lean @@ -196,7 +196,7 @@ def restrictScalars₁₂ (B : M →ₗ[R] N →ₗ[S] Pₗ) : M →ₗ[R'] N theorem restrictScalars₁₂_injective : Function.Injective (LinearMap.restrictScalars₁₂ R' S' : (M →ₗ[R] N →ₗ[S] Pₗ) → (M →ₗ[R'] N →ₗ[S'] Pₗ)) := - fun _ _ h ↦ ext₂ (congr_fun₂ h : _) + fun _ _ h ↦ ext₂ (congr_fun₂ h :) @[simp] theorem restrictScalars₁₂_inj {B B' : M →ₗ[R] N →ₗ[S] Pₗ} : diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean index 5651b6f8c5e13..8bf95f6eab875 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/BaseChange.lean @@ -161,7 +161,7 @@ theorem toBaseChange_comp_ofBaseChange (Q : QuadraticForm R V) : @[simp] theorem toBaseChange_ofBaseChange (Q : QuadraticForm R V) (x : A ⊗[R] CliffordAlgebra Q) : toBaseChange A Q (ofBaseChange A Q x) = x := - AlgHom.congr_fun (toBaseChange_comp_ofBaseChange A Q : _) x + AlgHom.congr_fun (toBaseChange_comp_ofBaseChange A Q :) x theorem ofBaseChange_comp_toBaseChange (Q : QuadraticForm R V) : (ofBaseChange A Q).comp (toBaseChange A Q) = AlgHom.id _ _ := by @@ -173,7 +173,7 @@ theorem ofBaseChange_comp_toBaseChange (Q : QuadraticForm R V) : @[simp] theorem ofBaseChange_toBaseChange (Q : QuadraticForm R V) (x : CliffordAlgebra (Q.baseChange A)) : ofBaseChange A Q (toBaseChange A Q x) = x := - AlgHom.congr_fun (ofBaseChange_comp_toBaseChange A Q : _) x + AlgHom.congr_fun (ofBaseChange_comp_toBaseChange A Q :) x /-- Base-changing the vector space of a clifford algebra is isomorphic as an A-algebra to base-changing the clifford algebra itself; <|Cℓ(A ⊗_R V, Q_A) ≅ A ⊗_R Cℓ(V, Q)<|. diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean index 5932cf65e0bb7..9699eda64fcc2 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean @@ -228,7 +228,7 @@ def evenToNeg (Q' : QuadraticForm R M) (h : Q' = -Q) : -- Porting note: added `letI`s letI : AddCommGroup (even Q') := AddSubgroupClass.toAddCommGroup _ letI : HasDistribNeg (even Q') := NonUnitalNonAssocRing.toHasDistribNeg - { bilin := -(even.ι Q' : _).bilin + { bilin := -(even.ι Q' :).bilin contract := fun m => by simp_rw [LinearMap.neg_apply, EvenHom.contract, h, QuadraticMap.neg_apply, map_neg, neg_neg] contract_mid := fun m₁ m₂ m₃ => by diff --git a/Mathlib/LinearAlgebra/Dimension/Constructions.lean b/Mathlib/LinearAlgebra/Dimension/Constructions.lean index 4caa6a8af25d2..81fbadfe29fce 100644 --- a/Mathlib/LinearAlgebra/Dimension/Constructions.lean +++ b/Mathlib/LinearAlgebra/Dimension/Constructions.lean @@ -57,7 +57,7 @@ theorem LinearIndependent.sum_elim_of_quotient theorem LinearIndependent.union_of_quotient {M' : Submodule R M} {s : Set M} (hs : s ⊆ M') (hs' : LinearIndependent (ι := s) R Subtype.val) {t : Set M} (ht : LinearIndependent (ι := t) R (Submodule.Quotient.mk (p := M') ∘ Subtype.val)) : - LinearIndependent (ι := (s ∪ t : _)) R Subtype.val := by + LinearIndependent (ι := (s ∪ t :)) R Subtype.val := by refine (LinearIndependent.sum_elim_of_quotient (f := Set.embeddingOfSubset s M' hs) (of_comp M'.subtype (by simpa using hs')) Subtype.val ht).to_subtype_range' ?_ simp only [embeddingOfSubset_apply_coe, Sum.elim_range, Subtype.range_val] diff --git a/Mathlib/LinearAlgebra/LinearIndependent.lean b/Mathlib/LinearAlgebra/LinearIndependent.lean index 561a2be1ce8fa..90ce06f81b213 100644 --- a/Mathlib/LinearAlgebra/LinearIndependent.lean +++ b/Mathlib/LinearAlgebra/LinearIndependent.lean @@ -1271,7 +1271,7 @@ lemma linearIndependent_algHom_toLinearMap apply LinearIndependent.of_comp (LinearMap.ltoFun K M L) exact (linearIndependent_monoidHom M L).comp (RingHom.toMonoidHom ∘ AlgHom.toRingHom) - (fun _ _ e ↦ AlgHom.ext (DFunLike.congr_fun e : _)) + (fun _ _ e ↦ AlgHom.ext (DFunLike.congr_fun e :)) lemma linearIndependent_algHom_toLinearMap' (K M L) [CommRing K] [Semiring M] [Algebra K M] [CommRing L] [IsDomain L] [Algebra K L] [NoZeroSMulDivisors K L] : diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean index 3eea92af5a206..703ede3a3d235 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/FiniteField.lean @@ -36,7 +36,7 @@ theorem FiniteField.Matrix.charpoly_pow_card {K : Type*} [Field K] [Fintype K] ( apply congr_arg det refine matPolyEquiv.injective ?_ rw [map_pow, matPolyEquiv_charmatrix, hk, sub_pow_char_pow_of_commute, ← C_pow] - · exact (id (matPolyEquiv_eq_X_pow_sub_C (p ^ k) M) : _) + · exact (id (matPolyEquiv_eq_X_pow_sub_C (p ^ k) M) :) · exact (C M).commute_X · exact congr_arg _ (Subsingleton.elim _ _) diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean index db92f36bbab1d..8befb3f75b370 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean @@ -64,7 +64,7 @@ theorem PiToModule.fromEnd_injective (hb : Submodule.span R (Set.range b) = ⊤) obtain ⟨m, rfl⟩ : m ∈ LinearMap.range (Fintype.linearCombination R R b) := by rw [(Fintype.range_linearCombination R b).trans hb] exact Submodule.mem_top - exact (LinearMap.congr_fun e m : _) + exact (LinearMap.congr_fun e m :) section diff --git a/Mathlib/LinearAlgebra/Matrix/LDL.lean b/Mathlib/LinearAlgebra/Matrix/LDL.lean index aeee211e5e6ec..7aaa5baf5130d 100644 --- a/Mathlib/LinearAlgebra/Matrix/LDL.lean +++ b/Mathlib/LinearAlgebra/Matrix/LDL.lean @@ -47,13 +47,13 @@ variable {S : Matrix n n 𝕜} [Fintype n] (hS : S.PosDef) applying Gram-Schmidt-Orthogonalization w.r.t. the inner product induced by `Sᵀ` on the standard basis vectors `Pi.basisFun`. -/ noncomputable def LDL.lowerInv : Matrix n n 𝕜 := - @gramSchmidt 𝕜 (n → 𝕜) _ (_ : _) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ + @gramSchmidt 𝕜 (n → 𝕜) _ (_ :) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ (Pi.basisFun 𝕜 n) theorem LDL.lowerInv_eq_gramSchmidtBasis : LDL.lowerInv hS = ((Pi.basisFun 𝕜 n).toMatrix - (@gramSchmidtBasis 𝕜 (n → 𝕜) _ (_ : _) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ + (@gramSchmidtBasis 𝕜 (n → 𝕜) _ (_ :) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ (Pi.basisFun 𝕜 n)))ᵀ := by letI := NormedAddCommGroup.ofMatrix hS.transpose letI := InnerProductSpace.ofMatrix hS.transpose @@ -65,13 +65,13 @@ noncomputable instance LDL.invertibleLowerInv : Invertible (LDL.lowerInv hS) := rw [LDL.lowerInv_eq_gramSchmidtBasis] haveI := Basis.invertibleToMatrix (Pi.basisFun 𝕜 n) - (@gramSchmidtBasis 𝕜 (n → 𝕜) _ (_ : _) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ + (@gramSchmidtBasis 𝕜 (n → 𝕜) _ (_ :) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ (Pi.basisFun 𝕜 n)) infer_instance theorem LDL.lowerInv_orthogonal {i j : n} (h₀ : i ≠ j) : ⟪LDL.lowerInv hS i, Sᵀ *ᵥ LDL.lowerInv hS j⟫ₑ = 0 := - @gramSchmidt_orthogonal 𝕜 _ _ (_ : _) (InnerProductSpace.ofMatrix hS.transpose) _ _ _ _ _ _ _ h₀ + @gramSchmidt_orthogonal 𝕜 _ _ (_ :) (InnerProductSpace.ofMatrix hS.transpose) _ _ _ _ _ _ _ h₀ /-- The entries of the diagonal matrix `D` of the LDL decomposition. -/ noncomputable def LDL.diagEntries : n → 𝕜 := fun i => @@ -83,7 +83,7 @@ noncomputable def LDL.diag : Matrix n n 𝕜 := theorem LDL.lowerInv_triangular {i j : n} (hij : i < j) : LDL.lowerInv hS i j = 0 := by rw [← - @gramSchmidt_triangular 𝕜 (n → 𝕜) _ (_ : _) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ + @gramSchmidt_triangular 𝕜 (n → 𝕜) _ (_ :) (InnerProductSpace.ofMatrix hS.transpose) n _ _ _ i j hij (Pi.basisFun 𝕜 n), Pi.basisFun_repr, LDL.lowerInv] diff --git a/Mathlib/LinearAlgebra/Matrix/Symmetric.lean b/Mathlib/LinearAlgebra/Matrix/Symmetric.lean index 498e22fb3bacc..2b2be9d38540a 100644 --- a/Mathlib/LinearAlgebra/Matrix/Symmetric.lean +++ b/Mathlib/LinearAlgebra/Matrix/Symmetric.lean @@ -126,8 +126,8 @@ theorem IsSymm.fromBlocks {A : Matrix m m α} {B : Matrix m n α} {C : Matrix n theorem isSymm_fromBlocks_iff {A : Matrix m m α} {B : Matrix m n α} {C : Matrix n m α} {D : Matrix n n α} : (A.fromBlocks B C D).IsSymm ↔ A.IsSymm ∧ Bᵀ = C ∧ Cᵀ = B ∧ D.IsSymm := ⟨fun h => - ⟨(congr_arg toBlocks₁₁ h : _), (congr_arg toBlocks₂₁ h : _), (congr_arg toBlocks₁₂ h : _), - (congr_arg toBlocks₂₂ h : _)⟩, + ⟨(congr_arg toBlocks₁₁ h :), (congr_arg toBlocks₂₁ h :), (congr_arg toBlocks₁₂ h :), + (congr_arg toBlocks₂₂ h :)⟩, fun ⟨hA, hBC, _, hD⟩ => IsSymm.fromBlocks hA hBC hD⟩ end Matrix diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean b/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean index 4208354f24bc0..e09af538b55e1 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Isometry.lean @@ -51,7 +51,7 @@ instance instLinearMapClass : LinearMapClass (Q₁ →qᵢ Q₂) R M₁ M₂ whe theorem toLinearMap_injective : Function.Injective (Isometry.toLinearMap : (Q₁ →qᵢ Q₂) → M₁ →ₗ[R] M₂) := fun _f _g h => - DFunLike.coe_injective (congr_arg DFunLike.coe h : _) + DFunLike.coe_injective (congr_arg DFunLike.coe h :) @[ext] theorem ext ⦃f g : Q₁ →qᵢ Q₂⦄ (h : ∀ x, f x = g x) : f = g := diff --git a/Mathlib/LinearAlgebra/Quotient/Defs.lean b/Mathlib/LinearAlgebra/Quotient/Defs.lean index 46e2cbca915b8..810d76fdc6985 100644 --- a/Mathlib/LinearAlgebra/Quotient/Defs.lean +++ b/Mathlib/LinearAlgebra/Quotient/Defs.lean @@ -241,7 +241,7 @@ variable {R₂ M₂ : Type*} [Ring R₂] [AddCommGroup M₂] [Module R₂ M₂] See note [partially-applied ext lemmas]. -/ @[ext 1100] -- Porting note: increase priority so this applies before `LinearMap.ext` theorem linearMap_qext ⦃f g : M ⧸ p →ₛₗ[τ₁₂] M₂⦄ (h : f.comp p.mkQ = g.comp p.mkQ) : f = g := - LinearMap.ext fun x => Submodule.Quotient.induction_on _ x <| (LinearMap.congr_fun h : _) + LinearMap.ext fun x => Submodule.Quotient.induction_on _ x <| (LinearMap.congr_fun h :) /-- Quotienting by equal submodules gives linearly equivalent quotients. -/ def quotEquivOfEq (h : p = p') : (M ⧸ p) ≃ₗ[R] M ⧸ p' := diff --git a/Mathlib/LinearAlgebra/Ray.lean b/Mathlib/LinearAlgebra/Ray.lean index d569b5c080c98..c460672f898e7 100644 --- a/Mathlib/LinearAlgebra/Ray.lean +++ b/Mathlib/LinearAlgebra/Ray.lean @@ -327,7 +327,7 @@ theorem someVector_ne_zero (x : Module.Ray R M) : x.someVector ≠ 0 := /-- The ray of `someVector`. -/ @[simp] theorem someVector_ray (x : Module.Ray R M) : rayOfNeZero R _ x.someVector_ne_zero = x := - (congr_arg _ (Subtype.coe_eta _ _) : _).trans x.out_eq + (congr_arg _ (Subtype.coe_eta _ _) :).trans x.out_eq end Module.Ray diff --git a/Mathlib/LinearAlgebra/Span/Basic.lean b/Mathlib/LinearAlgebra/Span/Basic.lean index 707818b275884..9da8fb60044f6 100644 --- a/Mathlib/LinearAlgebra/Span/Basic.lean +++ b/Mathlib/LinearAlgebra/Span/Basic.lean @@ -136,7 +136,7 @@ end theorem span_smul_eq_of_isUnit (s : Set M) (r : R) (hr : IsUnit r) : span R (r • s) = span R s := by apply le_antisymm · apply span_smul_le - · convert span_smul_le (r • s) ((hr.unit⁻¹ : _) : R) + · convert span_smul_le (r • s) ((hr.unit⁻¹ :) : R) simp [smul_smul] /-- We can regard `coe_iSup_of_chain` as the statement that `(↑) : (Submodule R M) → Set M` is diff --git a/Mathlib/LinearAlgebra/TensorProduct/Basic.lean b/Mathlib/LinearAlgebra/TensorProduct/Basic.lean index 75d5ed0bc25c0..64f12cf756387 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Basic.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Basic.lean @@ -1529,7 +1529,7 @@ instance CompatibleSMul.int : CompatibleSMul R ℤ M N := instance CompatibleSMul.unit {S} [Monoid S] [DistribMulAction S M] [DistribMulAction S N] [CompatibleSMul R S M N] : CompatibleSMul R Sˣ M N := - ⟨fun s m n => (CompatibleSMul.smul_tmul (s : S) m n : _)⟩ + ⟨fun s m n => CompatibleSMul.smul_tmul (s : S) m n⟩ end TensorProduct diff --git a/Mathlib/LinearAlgebra/TensorProduct/Tower.lean b/Mathlib/LinearAlgebra/TensorProduct/Tower.lean index b55604d42a282..33f45ceefbacc 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Tower.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Tower.lean @@ -94,7 +94,7 @@ See note [partially-applied ext lemmas]. -/ nonrec theorem curry_injective : Function.Injective (curry : (M ⊗ N →ₗ[A] P) → M →ₗ[A] N →ₗ[R] P) := fun _ _ h => LinearMap.restrictScalars_injective R <| - curry_injective <| (congr_arg (LinearMap.restrictScalars R) h : _) + curry_injective <| (congr_arg (LinearMap.restrictScalars R) h :) theorem ext {g h : M ⊗[R] N →ₗ[A] P} (H : ∀ x y, g (x ⊗ₜ y) = h (x ⊗ₜ y)) : g = h := curry_injective <| LinearMap.ext₂ H diff --git a/Mathlib/Logic/Function/Basic.lean b/Mathlib/Logic/Function/Basic.lean index a59d0b66dcbae..1eee4fc7e8759 100644 --- a/Mathlib/Logic/Function/Basic.lean +++ b/Mathlib/Logic/Function/Basic.lean @@ -844,13 +844,13 @@ protected theorem uncurry {α β γ : Type*} {f : α → β → γ} (hf : Inject /-- As a map from the left argument to a unary function, `f` is injective. -/ theorem left' (hf : Injective2 f) [Nonempty β] : Function.Injective f := fun _ _ h ↦ let ⟨b⟩ := ‹Nonempty β› - hf.left b <| (congr_fun h b : _) + hf.left b <| (congr_fun h b :) /-- As a map from the right argument to a unary function, `f` is injective. -/ theorem right' (hf : Injective2 f) [Nonempty α] : Function.Injective fun b a ↦ f a b := fun _ _ h ↦ let ⟨a⟩ := ‹Nonempty α› - hf.right a <| (congr_fun h a : _) + hf.right a <| (congr_fun h a :) theorem eq_iff (hf : Injective2 f) {a₁ a₂ b₁ b₂} : f a₁ b₁ = f a₂ b₂ ↔ a₁ = a₂ ∧ b₁ = b₂ := ⟨fun h ↦ hf h, fun ⟨h1, h2⟩ ↦ congr_arg₂ f h1 h2⟩ diff --git a/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean b/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean index ff610fee246c5..b016d6eba33b4 100644 --- a/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean @@ -251,7 +251,7 @@ theorem AnalyticSet.iInter [hι : Nonempty ι] [Countable ι] [T2Space α] {s : apply Subset.antisymm · rintro y ⟨x, rfl⟩ refine mem_iInter.2 fun n => ?_ - have : f n ((x : γ) n) = F x := (mem_iInter.1 x.2 n : _) + have : f n ((x : γ) n) = F x := (mem_iInter.1 x.2 n :) rw [← this, ← f_range n] exact mem_range_self _ · intro y hy @@ -740,10 +740,10 @@ theorem measurableSet_range_of_continuous_injective {β : Type*} [TopologicalSpa by_contra! h have A : x ∈ q ⟨(s m, s n), h⟩ \ q ⟨(s n, s m), h.symm⟩ := haveI := mem_iInter.1 (hxs m).2 (s n) - (mem_iInter.1 this h : _) + (mem_iInter.1 this h :) have B : x ∈ q ⟨(s n, s m), h.symm⟩ \ q ⟨(s m, s n), h⟩ := haveI := mem_iInter.1 (hxs n).2 (s m) - (mem_iInter.1 this h.symm : _) + (mem_iInter.1 this h.symm :) exact A.2 B.1 -- the points `y n` are nearby, and therefore they form a Cauchy sequence. have cauchy_y : CauchySeq y := by diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean index 1df002f2d7299..6c1499cfe95ca 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean @@ -306,7 +306,7 @@ variable {𝕜 α E F : Type*} {m : MeasurableSpace α} {μ : Measure α} [Norme theorem eLpNorm_smul_le_eLpNorm_top_mul_eLpNorm (p : ℝ≥0∞) (hf : AEStronglyMeasurable f μ) (φ : α → 𝕜) : eLpNorm (φ • f) p μ ≤ eLpNorm φ ∞ μ * eLpNorm f p μ := (eLpNorm_le_eLpNorm_top_mul_eLpNorm p φ hf (· • ·) - (Eventually.of_forall fun _ => nnnorm_smul_le _ _) : _) + (Eventually.of_forall fun _ => nnnorm_smul_le _ _) :) @[deprecated (since := "2024-07-27")] alias snorm_smul_le_snorm_top_mul_snorm := eLpNorm_smul_le_eLpNorm_top_mul_eLpNorm @@ -314,7 +314,7 @@ alias snorm_smul_le_snorm_top_mul_snorm := eLpNorm_smul_le_eLpNorm_top_mul_eLpNo theorem eLpNorm_smul_le_eLpNorm_mul_eLpNorm_top (p : ℝ≥0∞) (f : α → E) {φ : α → 𝕜} (hφ : AEStronglyMeasurable φ μ) : eLpNorm (φ • f) p μ ≤ eLpNorm φ p μ * eLpNorm f ∞ μ := (eLpNorm_le_eLpNorm_mul_eLpNorm_top p hφ f (· • ·) - (Eventually.of_forall fun _ => nnnorm_smul_le _ _) : _) + (Eventually.of_forall fun _ => nnnorm_smul_le _ _) :) @[deprecated (since := "2024-07-27")] alias snorm_smul_le_snorm_mul_snorm_top := eLpNorm_smul_le_eLpNorm_mul_eLpNorm_top diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index b8cf7ba03d100..d64f4c733873a 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -469,7 +469,7 @@ attribute [local instance] simpleFunc.module /-- If `E` is a normed space, `Lp.simpleFunc E p μ` is a normed space. Not declared as an instance as it is (as of writing) used only in the construction of the Bochner integral. -/ protected theorem boundedSMul [Fact (1 ≤ p)] : BoundedSMul 𝕜 (Lp.simpleFunc E p μ) := - BoundedSMul.of_norm_smul_le fun r f => (norm_smul_le r (f : Lp E p μ) : _) + BoundedSMul.of_norm_smul_le fun r f => (norm_smul_le r (f : Lp E p μ) :) attribute [local instance] simpleFunc.boundedSMul diff --git a/Mathlib/MeasureTheory/Group/AddCircle.lean b/Mathlib/MeasureTheory/Group/AddCircle.lean index 2e2847f50467b..3f20417353a69 100644 --- a/Mathlib/MeasureTheory/Group/AddCircle.lean +++ b/Mathlib/MeasureTheory/Group/AddCircle.lean @@ -95,7 +95,7 @@ theorem volume_of_add_preimage_eq (s I : Set <| AddCircle T) (u x : AddCircle T) let G := AddSubgroup.zmultiples u haveI : Fintype G := @Fintype.ofFinite _ hu.finite_zmultiples.to_subtype have hsG : ∀ g : G, (g +ᵥ s : Set <| AddCircle T) =ᵐ[volume] s := by - rintro ⟨y, hy⟩; exact (vadd_ae_eq_self_of_mem_zmultiples hs hy : _) + rintro ⟨y, hy⟩; exact (vadd_ae_eq_self_of_mem_zmultiples hs hy :) rw [(isAddFundamentalDomain_of_ae_ball I u x hu hI).measure_eq_card_smul_of_vadd_ae_eq_self s hsG, ← Nat.card_zmultiples u] diff --git a/Mathlib/MeasureTheory/Group/Arithmetic.lean b/Mathlib/MeasureTheory/Group/Arithmetic.lean index eaba1a41a370d..0d9b2426dd69b 100644 --- a/Mathlib/MeasureTheory/Group/Arithmetic.lean +++ b/Mathlib/MeasureTheory/Group/Arithmetic.lean @@ -662,7 +662,7 @@ instance Units.instMeasurableSpace : MeasurableSpace Mˣ := MeasurableSpace.coma @[to_additive] instance Units.measurableSMul : MeasurableSMul Mˣ β where - measurable_const_smul c := (measurable_const_smul (c : M) : _) + measurable_const_smul c := measurable_const_smul (c : M) measurable_smul_const x := (measurable_smul_const x : Measurable fun c : M => c • x).comp MeasurableSpace.le_map_comap diff --git a/Mathlib/MeasureTheory/Integral/Prod.lean b/Mathlib/MeasureTheory/Integral/Prod.lean index 7b77ffcd619e8..886d5b00bc910 100644 --- a/Mathlib/MeasureTheory/Integral/Prod.lean +++ b/Mathlib/MeasureTheory/Integral/Prod.lean @@ -301,7 +301,7 @@ theorem Integrable.integral_prod_left ⦃f : α × β → E⦄ (hf : Integrable (norm_integral_le_integral_norm _).trans_eq <| (norm_of_nonneg <| integral_nonneg_of_ae <| - Eventually.of_forall fun y => (norm_nonneg (f (x, y)) : _)).symm + Eventually.of_forall fun y => (norm_nonneg (f (x, y)) :)).symm theorem Integrable.integral_prod_right [SFinite μ] ⦃f : α × β → E⦄ (hf : Integrable f (μ.prod ν)) : Integrable (fun y => ∫ x, f (x, y) ∂μ) ν := diff --git a/Mathlib/MeasureTheory/Measure/Prod.lean b/Mathlib/MeasureTheory/Measure/Prod.lean index ce852342469e9..951fd5c3bf2c4 100644 --- a/Mathlib/MeasureTheory/Measure/Prod.lean +++ b/Mathlib/MeasureTheory/Measure/Prod.lean @@ -308,7 +308,7 @@ theorem measure_ae_null_of_prod_null {s : Set (α × β)} (h : μ.prod ν s = 0) rw [measure_prod_null mt] at ht rw [eventuallyLE_antisymm_iff] exact - ⟨EventuallyLE.trans_eq (Eventually.of_forall fun x => (measure_mono (preimage_mono hst) : _)) + ⟨EventuallyLE.trans_eq (Eventually.of_forall fun x => measure_mono (preimage_mono hst)) ht, Eventually.of_forall fun x => zero_le _⟩ diff --git a/Mathlib/ModelTheory/LanguageMap.lean b/Mathlib/ModelTheory/LanguageMap.lean index 2daf318f51f3e..6f637d83be0fc 100644 --- a/Mathlib/ModelTheory/LanguageMap.lean +++ b/Mathlib/ModelTheory/LanguageMap.lean @@ -363,7 +363,7 @@ theorem constantsOnMap_isExpansionOn {f : α → β} {fα : α → M} {fβ : β letI := constantsOn.structure fα letI := constantsOn.structure fβ exact - ⟨fun {n} => Nat.casesOn n (fun F _x => (congr_fun h F : _)) fun n F => isEmptyElim F, fun R => + ⟨fun {n} => Nat.casesOn n (fun F _x => (congr_fun h F :)) fun n F => isEmptyElim F, fun R => isEmptyElim R⟩ end ConstantsOn diff --git a/Mathlib/NumberTheory/Cyclotomic/Basic.lean b/Mathlib/NumberTheory/Cyclotomic/Basic.lean index ec3877fb1cd1d..c9e7e4599210e 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Basic.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Basic.lean @@ -548,7 +548,7 @@ instance CyclotomicField.noZeroSMulDivisors [IsFractionRing A K] : rw [IsScalarTower.algebraMap_eq A K (CyclotomicField n K)] exact (Function.Injective.comp (NoZeroSMulDivisors.algebraMap_injective K (CyclotomicField n K)) - (IsFractionRing.injective A K) : _) + (IsFractionRing.injective A K) :) /-- If `A` is a domain with fraction field `K` and `n : ℕ+`, we define `CyclotomicRing n A K` as the `A`-subalgebra of `CyclotomicField n K` generated by the roots of `X ^ n - 1`. If `n` diff --git a/Mathlib/Order/CompleteLattice.lean b/Mathlib/Order/CompleteLattice.lean index c225c90223d8d..d1c676bce4fdf 100644 --- a/Mathlib/Order/CompleteLattice.lean +++ b/Mathlib/Order/CompleteLattice.lean @@ -1726,11 +1726,11 @@ theorem iInf_sup_iInf_le (f g : ι → α) : (⨅ i, f i) ⊔ ⨅ i, g i ≤ ⨅ theorem disjoint_sSup_left {a : Set α} {b : α} (d : Disjoint (sSup a) b) {i} (hi : i ∈ a) : Disjoint i b := - disjoint_iff_inf_le.mpr (iSup₂_le_iff.1 (iSup_inf_le_sSup_inf.trans d.le_bot) i hi : _) + disjoint_iff_inf_le.mpr (iSup₂_le_iff.1 (iSup_inf_le_sSup_inf.trans d.le_bot) i hi :) theorem disjoint_sSup_right {a : Set α} {b : α} (d : Disjoint b (sSup a)) {i} (hi : i ∈ a) : Disjoint b i := - disjoint_iff_inf_le.mpr (iSup₂_le_iff.mp (iSup_inf_le_inf_sSup.trans d.le_bot) i hi : _) + disjoint_iff_inf_le.mpr (iSup₂_le_iff.mp (iSup_inf_le_inf_sSup.trans d.le_bot) i hi :) end CompleteLattice diff --git a/Mathlib/Order/Filter/Ultrafilter.lean b/Mathlib/Order/Filter/Ultrafilter.lean index d171f958a9ca2..f64833156e58c 100644 --- a/Mathlib/Order/Filter/Ultrafilter.lean +++ b/Mathlib/Order/Filter/Ultrafilter.lean @@ -261,7 +261,7 @@ theorem comap_pure {m : α → β} (a : α) (inj : Injective m) (large) : rw [coe_pure, ← principal_singleton, ← image_singleton, preimage_image_eq _ inj] theorem pure_injective : Injective (pure : α → Ultrafilter α) := fun _ _ h => - Filter.pure_injective (congr_arg Ultrafilter.toFilter h : _) + Filter.pure_injective (congr_arg Ultrafilter.toFilter h :) instance [Inhabited α] : Inhabited (Ultrafilter α) := ⟨pure default⟩ diff --git a/Mathlib/Order/Height.lean b/Mathlib/Order/Height.lean index 22b9697c5dd05..be2eaa7acd45b 100644 --- a/Mathlib/Order/Height.lean +++ b/Mathlib/Order/Height.lean @@ -291,10 +291,10 @@ theorem chainHeight_union_le : (s ∪ t).chainHeight ≤ s.chainHeight + t.chain let l₂ := l.filter (· ∈ t) have hl₁ : ↑l₁.length ≤ s.chainHeight := by apply Set.length_le_chainHeight_of_mem_subchain - exact ⟨hl.1.sublist (filter_sublist _), fun i h ↦ by simpa using (of_mem_filter h : _)⟩ + exact ⟨hl.1.sublist (filter_sublist _), fun i h ↦ by simpa using (of_mem_filter h :)⟩ have hl₂ : ↑l₂.length ≤ t.chainHeight := by apply Set.length_le_chainHeight_of_mem_subchain - exact ⟨hl.1.sublist (filter_sublist _), fun i h ↦ by simpa using (of_mem_filter h : _)⟩ + exact ⟨hl.1.sublist (filter_sublist _), fun i h ↦ by simpa using (of_mem_filter h :)⟩ refine le_trans ?_ (add_le_add hl₁ hl₂) simp_rw [l₁, l₂, ← Nat.cast_add, ← Multiset.coe_card, ← Multiset.card_add, ← Multiset.filter_coe] diff --git a/Mathlib/Order/Hom/Order.lean b/Mathlib/Order/Hom/Order.lean index 1fdadf691bf97..730ef64eb8a36 100644 --- a/Mathlib/Order/Hom/Order.lean +++ b/Mathlib/Order/Hom/Order.lean @@ -78,11 +78,11 @@ instance orderTop [Preorder β] [OrderTop β] : OrderTop (α →o β) where le_top _ _ := le_top instance [CompleteLattice β] : InfSet (α →o β) where - sInf s := ⟨fun x => ⨅ f ∈ s, (f : _) x, fun _ _ h => iInf₂_mono fun f _ => f.mono h⟩ + sInf s := ⟨fun x => ⨅ f ∈ s, (f :) x, fun _ _ h => iInf₂_mono fun f _ => f.mono h⟩ @[simp] theorem sInf_apply [CompleteLattice β] (s : Set (α →o β)) (x : α) : - sInf s x = ⨅ f ∈ s, (f : _) x := + sInf s x = ⨅ f ∈ s, (f :) x := rfl theorem iInf_apply {ι : Sort*} [CompleteLattice β] (f : ι → α →o β) (x : α) : @@ -95,11 +95,11 @@ theorem coe_iInf {ι : Sort*} [CompleteLattice β] (f : ι → α →o β) : funext x; simp [iInf_apply] instance [CompleteLattice β] : SupSet (α →o β) where - sSup s := ⟨fun x => ⨆ f ∈ s, (f : _) x, fun _ _ h => iSup₂_mono fun f _ => f.mono h⟩ + sSup s := ⟨fun x => ⨆ f ∈ s, (f :) x, fun _ _ h => iSup₂_mono fun f _ => f.mono h⟩ @[simp] theorem sSup_apply [CompleteLattice β] (s : Set (α →o β)) (x : α) : - sSup s x = ⨆ f ∈ s, (f : _) x := + sSup s x = ⨆ f ∈ s, (f :) x := rfl theorem iSup_apply {ι : Sort*} [CompleteLattice β] (f : ι → α →o β) (x : α) : diff --git a/Mathlib/Order/Interval/Finset/Defs.lean b/Mathlib/Order/Interval/Finset/Defs.lean index 5ca55dc50e9eb..43f60e43687da 100644 --- a/Mathlib/Order/Interval/Finset/Defs.lean +++ b/Mathlib/Order/Interval/Finset/Defs.lean @@ -670,7 +670,7 @@ variable [LocallyFiniteOrder α] (a b : α) `Finset αᵒᵈ`!) instead of `(Icc b a).map toDual.toEmbedding` as this means the following is defeq: ``` -lemma this : (Icc (toDual (toDual a)) (toDual (toDual b)) : _) = (Icc a b : _) := rfl +lemma this : (Icc (toDual (toDual a)) (toDual (toDual b)) :) = (Icc a b :) := rfl ``` -/ instance OrderDual.instLocallyFiniteOrder : LocallyFiniteOrder αᵒᵈ where @@ -728,7 +728,7 @@ variable [LocallyFiniteOrderTop α] /-- Note we define `Iic (toDual a)` as `Ici a` (which has type `Finset α` not `Finset αᵒᵈ`!) instead of `(Ici a).map toDual.toEmbedding` as this means the following is defeq: ``` -lemma this : (Iic (toDual (toDual a)) : _) = (Iic a : _) := rfl +lemma this : (Iic (toDual (toDual a)) :) = (Iic a :) := rfl ``` -/ instance OrderDual.instLocallyFiniteOrderBot : LocallyFiniteOrderBot αᵒᵈ where @@ -761,7 +761,7 @@ variable [LocallyFiniteOrderBot α] /-- Note we define `Ici (toDual a)` as `Iic a` (which has type `Finset α` not `Finset αᵒᵈ`!) instead of `(Iic a).map toDual.toEmbedding` as this means the following is defeq: ``` -lemma this : (Ici (toDual (toDual a)) : _) = (Ici a : _) := rfl +lemma this : (Ici (toDual (toDual a)) :) = (Ici a :) := rfl ``` -/ instance OrderDual.instLocallyFiniteOrderTop : LocallyFiniteOrderTop αᵒᵈ where diff --git a/Mathlib/Order/SupIndep.lean b/Mathlib/Order/SupIndep.lean index 27770ea7eaa4a..b962948122dc0 100644 --- a/Mathlib/Order/SupIndep.lean +++ b/Mathlib/Order/SupIndep.lean @@ -503,7 +503,7 @@ alias CompleteLattice.independent_map_orderIso_iff := iSupIndep_map_orderIso_iff subset of the rest. -/ theorem iSupIndep.disjoint_biSup {ι : Type*} {α : Type*} [CompleteLattice α] {t : ι → α} (ht : iSupIndep t) {x : ι} {y : Set ι} (hx : x ∉ y) : Disjoint (t x) (⨆ i ∈ y, t i) := - Disjoint.mono_right (biSup_mono fun _ hi => (ne_of_mem_of_not_mem hi hx : _)) (ht x) + Disjoint.mono_right (biSup_mono fun _ hi => (ne_of_mem_of_not_mem hi hx :)) (ht x) @[deprecated (since := "2024-11-24")] alias CompleteLattice.Independent.disjoint_biSup := iSupIndep.disjoint_biSup diff --git a/Mathlib/Probability/Kernel/Composition/Basic.lean b/Mathlib/Probability/Kernel/Composition/Basic.lean index 30d4f488d8861..5f580f7b80e64 100644 --- a/Mathlib/Probability/Kernel/Composition/Basic.lean +++ b/Mathlib/Probability/Kernel/Composition/Basic.lean @@ -308,7 +308,7 @@ theorem ae_null_of_compProd_null (h : (κ ⊗ₖ η) a s = 0) : rw [Filter.eventuallyLE_antisymm_iff] exact ⟨Filter.EventuallyLE.trans_eq - (Filter.Eventually.of_forall fun x => (measure_mono (Set.preimage_mono hst) : _)) ht, + (Filter.Eventually.of_forall fun x => measure_mono (Set.preimage_mono hst)) ht, Filter.Eventually.of_forall fun x => zero_le _⟩ theorem ae_ae_of_ae_compProd {p : β × γ → Prop} (h : ∀ᵐ bc ∂(κ ⊗ₖ η) a, p bc) : diff --git a/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean b/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean index 0f7fef4ed3332..a9ab89e8cf8f4 100644 --- a/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean +++ b/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean @@ -134,7 +134,7 @@ theorem _root_.MeasureTheory.Integrable.integral_compProd [NormedSpace ℝ E] (norm_integral_le_integral_norm _).trans_eq <| (norm_of_nonneg <| integral_nonneg_of_ae <| - Eventually.of_forall fun y => (norm_nonneg (f (x, y)) : _)).symm + Eventually.of_forall fun y => (norm_nonneg (f (x, y)) :)).symm /-! ### Bochner integral -/ diff --git a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean index 058f95c8bd4ad..77f7b9998fedb 100644 --- a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean +++ b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean @@ -364,7 +364,7 @@ variable {K} def adicValued : Valued K ℤₘ₀ := Valued.mk' v.valuation -theorem adicValued_apply {x : K} : (v.adicValued.v : _) x = v.valuation x := +theorem adicValued_apply {x : K} : v.adicValued.v x = v.valuation x := rfl variable (K) diff --git a/Mathlib/RingTheory/DedekindDomain/Different.lean b/Mathlib/RingTheory/DedekindDomain/Different.lean index 7b195346a4cf3..5ab55f608ea3d 100644 --- a/Mathlib/RingTheory/DedekindDomain/Different.lean +++ b/Mathlib/RingTheory/DedekindDomain/Different.lean @@ -462,7 +462,7 @@ open Submodule lemma differentialIdeal_le_fractionalIdeal_iff {I : FractionalIdeal B⁰ L} (hI : I ≠ 0) [NoZeroSMulDivisors A B] : - differentIdeal A B ≤ I ↔ (((I⁻¹ : _) : Submodule B L).restrictScalars A).map + differentIdeal A B ≤ I ↔ (((I⁻¹ :) : Submodule B L).restrictScalars A).map ((Algebra.trace K L).restrictScalars A) ≤ 1 := by rw [coeIdeal_differentIdeal A K L B, FractionalIdeal.inv_le_comm (by simp) hI, ← FractionalIdeal.coe_le_coe, FractionalIdeal.coe_dual_one] @@ -594,7 +594,7 @@ lemma pow_sub_one_dvd_differentIdeal_aux [IsFractionRing B L] [IsDedekindDomain rw [pow_add, hb, mul_assoc, mul_right_inj' (pow_ne_zero _ hPbot), pow_one, mul_comm] at ha exact ⟨_, ha.symm⟩ suffices ∀ x ∈ a, intTrace A B x ∈ p by - have hP : ((P ^ (e - 1) : _)⁻¹ : FractionalIdeal B⁰ L) = a / p.map (algebraMap A B) := by + have hP : ((P ^ (e - 1) :)⁻¹ : FractionalIdeal B⁰ L) = a / p.map (algebraMap A B) := by apply inv_involutive.injective simp only [inv_inv, ha, FractionalIdeal.coeIdeal_mul, inv_div, ne_eq, FractionalIdeal.coeIdeal_eq_zero, mul_div_assoc] diff --git a/Mathlib/RingTheory/Derivation/ToSquareZero.lean b/Mathlib/RingTheory/Derivation/ToSquareZero.lean index e99816f3014ce..dfaa5966fbf27 100644 --- a/Mathlib/RingTheory/Derivation/ToSquareZero.lean +++ b/Mathlib/RingTheory/Derivation/ToSquareZero.lean @@ -117,7 +117,7 @@ lifts `A →ₐ[R] B` of the canonical map `A →ₐ[R] B ⧸ I`. -/ def derivationToSquareZeroEquivLift [IsScalarTower R A B] : Derivation R A I ≃ { f : A →ₐ[R] B // (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I) } := by refine ⟨fun d => ⟨liftOfDerivationToSquareZero I hI d, ?_⟩, fun f => - (derivationToSquareZeroOfLift I hI f.1 f.2 : _), ?_, ?_⟩ + (derivationToSquareZeroOfLift I hI f.1 f.2 :), ?_, ?_⟩ · ext x; exact liftOfDerivationToSquareZero_mk_apply I hI d x · intro d; ext x; exact add_sub_cancel_right (d x : B) (algebraMap A B x) · rintro ⟨f, hf⟩; ext x; exact sub_add_cancel (f x) (algebraMap A B x) diff --git a/Mathlib/RingTheory/Ideal/AssociatedPrime.lean b/Mathlib/RingTheory/Ideal/AssociatedPrime.lean index e902fa6239cfa..0a316e3c547c5 100644 --- a/Mathlib/RingTheory/Ideal/AssociatedPrime.lean +++ b/Mathlib/RingTheory/Ideal/AssociatedPrime.lean @@ -161,7 +161,7 @@ theorem associatedPrimes.eq_singleton_of_isPrimary [IsNoetherianRing R] (hI : I. refine ⟨IsAssociatedPrime.eq_radical hI, ?_⟩ rintro rfl haveI : Nontrivial (R ⧸ I) := by - refine ⟨(Ideal.Quotient.mk I : _) 1, (Ideal.Quotient.mk I : _) 0, ?_⟩ + refine ⟨(Ideal.Quotient.mk I :) 1, (Ideal.Quotient.mk I :) 0, ?_⟩ rw [Ne, Ideal.Quotient.eq, sub_zero, ← Ideal.eq_top_iff_one] exact hI.1 obtain ⟨a, ha⟩ := associatedPrimes.nonempty R (R ⧸ I) diff --git a/Mathlib/RingTheory/Ideal/Quotient/Defs.lean b/Mathlib/RingTheory/Ideal/Quotient/Defs.lean index 5bd2896800b7f..a060399646f49 100644 --- a/Mathlib/RingTheory/Ideal/Quotient/Defs.lean +++ b/Mathlib/RingTheory/Ideal/Quotient/Defs.lean @@ -89,7 +89,7 @@ See note [partially-applied ext lemmas]. -/ @[ext 1100] theorem ringHom_ext [NonAssocSemiring S] ⦃f g : R ⧸ I →+* S⦄ (h : f.comp (mk I) = g.comp (mk I)) : f = g := - RingHom.ext fun x => Quotient.inductionOn' x <| (RingHom.congr_fun h : _) + RingHom.ext fun x => Quotient.inductionOn' x <| (RingHom.congr_fun h :) instance inhabited : Inhabited (R ⧸ I) := ⟨mk I 37⟩ diff --git a/Mathlib/RingTheory/Ideal/Quotient/Operations.lean b/Mathlib/RingTheory/Ideal/Quotient/Operations.lean index f18039405d13b..81c079b7988ec 100644 --- a/Mathlib/RingTheory/Ideal/Quotient/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Quotient/Operations.lean @@ -409,7 +409,7 @@ theorem Quotient.liftₐ_apply (I : Ideal A) (f : A →ₐ[R₁] B) (hI : ∀ a theorem Quotient.liftₐ_comp (I : Ideal A) (f : A →ₐ[R₁] B) (hI : ∀ a : A, a ∈ I → f a = 0) : (Ideal.Quotient.liftₐ I f hI).comp (Ideal.Quotient.mkₐ R₁ I) = f := - AlgHom.ext fun _ => (Ideal.Quotient.lift_mk I (f : A →+* B) hI : _) + AlgHom.ext fun _ => (Ideal.Quotient.lift_mk I (f : A →+* B) hI :) theorem KerLift.map_smul (f : A →ₐ[R₁] B) (r : R₁) (x : A ⧸ (RingHom.ker f)) : f.kerLift (r • x) = r • f.kerLift x := by diff --git a/Mathlib/RingTheory/IsTensorProduct.lean b/Mathlib/RingTheory/IsTensorProduct.lean index dccdc2035a370..addd18bf5d59f 100644 --- a/Mathlib/RingTheory/IsTensorProduct.lean +++ b/Mathlib/RingTheory/IsTensorProduct.lean @@ -504,7 +504,7 @@ theorem Algebra.pushoutDesc_left [Algebra.IsPushout R S R' S'] {A : Type*} [Semi theorem Algebra.lift_algHom_comp_left [Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) : (Algebra.pushoutDesc S' f g H).comp (toAlgHom R S S') = f := - AlgHom.ext fun x => (Algebra.pushoutDesc_left S' f g H x : _) + AlgHom.ext fun x => (Algebra.pushoutDesc_left S' f g H x :) @[simp] theorem Algebra.pushoutDesc_right [Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] @@ -519,7 +519,7 @@ theorem Algebra.pushoutDesc_right [Algebra.IsPushout R S R' S'] {A : Type*} [Sem theorem Algebra.lift_algHom_comp_right [Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) : (Algebra.pushoutDesc S' f g H).comp (toAlgHom R R' S') = g := - AlgHom.ext fun x => (Algebra.pushoutDesc_right S' f g H x : _) + AlgHom.ext fun x => (Algebra.pushoutDesc_right S' f g H x :) @[ext (iff := false)] theorem Algebra.IsPushout.algHom_ext [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] @@ -532,7 +532,7 @@ theorem Algebra.IsPushout.algHom_ext [H : Algebra.IsPushout R S R' S'] {A : Type · intro s s' e rw [Algebra.smul_def, map_mul, map_mul, e] congr 1 - exact (AlgHom.congr_fun h₂ s : _) + exact (AlgHom.congr_fun h₂ s :) · intro s₁ s₂ e₁ e₂ rw [map_add, map_add, e₁, e₂] diff --git a/Mathlib/RingTheory/Kaehler/Basic.lean b/Mathlib/RingTheory/Kaehler/Basic.lean index d668bcecc861a..ca03981436858 100644 --- a/Mathlib/RingTheory/Kaehler/Basic.lean +++ b/Mathlib/RingTheory/Kaehler/Basic.lean @@ -207,8 +207,8 @@ def KaehlerDifferential.D : Derivation R S (Ω[S⁄R]) := -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 erw [← LinearMap.map_smul_of_tower (M₂ := Ω[S⁄R]), ← LinearMap.map_smul_of_tower (M₂ := Ω[S⁄R]), ← map_add, Ideal.toCotangent_eq, pow_two] - convert Submodule.mul_mem_mul (KaehlerDifferential.one_smul_sub_smul_one_mem_ideal R a : _) - (KaehlerDifferential.one_smul_sub_smul_one_mem_ideal R b : _) using 1 + convert Submodule.mul_mem_mul (KaehlerDifferential.one_smul_sub_smul_one_mem_ideal R a :) + (KaehlerDifferential.one_smul_sub_smul_one_mem_ideal R b :) using 1 simp only [AddSubgroupClass.coe_sub, Submodule.coe_add, Submodule.coe_mk, TensorProduct.tmul_mul_tmul, mul_sub, sub_mul, mul_comm b, Submodule.coe_smul_of_tower, smul_sub, TensorProduct.smul_tmul', smul_eq_mul, mul_one] @@ -599,7 +599,7 @@ noncomputable def KaehlerDifferential.quotKerTotalEquiv : obtain ⟨x, rfl⟩ := Submodule.mkQ_surjective _ x exact LinearMap.congr_fun - (KaehlerDifferential.derivationQuotKerTotal_lift_comp_linearCombination R S : _) x + (KaehlerDifferential.derivationQuotKerTotal_lift_comp_linearCombination R S :) x right_inv := by intro x obtain ⟨x, rfl⟩ := KaehlerDifferential.linearCombination_surjective R S x diff --git a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean index db25c94c9b3af..819a67cdc7c96 100644 --- a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean +++ b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean @@ -374,7 +374,7 @@ lemma cotangentSpaceBasis_repr_one_tmul (x i) : simp lemma cotangentSpaceBasis_apply (i) : - P.cotangentSpaceBasis i = ((1 : S) ⊗ₜ[P.Ring] D R P.Ring (.X i) : _) := by + P.cotangentSpaceBasis i = ((1 : S) ⊗ₜ[P.Ring] D R P.Ring (.X i) :) := by simp [cotangentSpaceBasis, toExtension] universe w' u' v' diff --git a/Mathlib/RingTheory/Kaehler/JacobiZariski.lean b/Mathlib/RingTheory/Kaehler/JacobiZariski.lean index d4c5b8c6ef68f..6ccbe6af032c5 100644 --- a/Mathlib/RingTheory/Kaehler/JacobiZariski.lean +++ b/Mathlib/RingTheory/Kaehler/JacobiZariski.lean @@ -280,7 +280,7 @@ lemma δAux_C (r) : lemma δAux_toAlgHom {Q : Generators.{u₁} S T} {Q' : Generators.{u₃} S T} (f : Hom Q Q') (x) : δAux R Q' (f.toAlgHom x) = δAux R Q x + Finsupp.linearCombination _ (δAux R Q' ∘ f.val) - (Q.cotangentSpaceBasis.repr ((1 : T) ⊗ₜ[Q.Ring] D S Q.Ring x : _)) := by + (Q.cotangentSpaceBasis.repr ((1 : T) ⊗ₜ[Q.Ring] D S Q.Ring x :)) := by letI : AddCommGroup (T ⊗[S] Ω[S⁄R]) := inferInstance have : IsScalarTower Q.Ring Q.Ring T := IsScalarTower.left _ induction' x using MvPolynomial.induction_on with s x₁ x₂ hx₁ hx₂ p n IH diff --git a/Mathlib/RingTheory/MvPowerSeries/Basic.lean b/Mathlib/RingTheory/MvPowerSeries/Basic.lean index 136414a51996a..1a27f73a40bef 100644 --- a/Mathlib/RingTheory/MvPowerSeries/Basic.lean +++ b/Mathlib/RingTheory/MvPowerSeries/Basic.lean @@ -347,7 +347,7 @@ def C : R →+* MvPowerSeries σ R := { monomial R (0 : σ →₀ ℕ) with map_one' := rfl map_mul' := fun a b => (monomial_mul_monomial 0 0 a b).symm - map_zero' := (monomial R (0 : _)).map_zero } + map_zero' := (monomial R 0).map_zero } variable {σ} {R} diff --git a/Mathlib/RingTheory/MvPowerSeries/Inverse.lean b/Mathlib/RingTheory/MvPowerSeries/Inverse.lean index be1a66314f9d2..87dca83d6c5c6 100644 --- a/Mathlib/RingTheory/MvPowerSeries/Inverse.lean +++ b/Mathlib/RingTheory/MvPowerSeries/Inverse.lean @@ -120,7 +120,7 @@ theorem mul_invOfUnit (φ : MvPowerSeries σ R) (u : Rˣ) (h : constantCoeff σ cases' hij with h₁ h₂ subst n rw [if_pos] - suffices (0 : _) + j < i + j by simpa + suffices 0 + j < i + j by simpa apply add_lt_add_right constructor · intro s diff --git a/Mathlib/RingTheory/Nilpotent/Lemmas.lean b/Mathlib/RingTheory/Nilpotent/Lemmas.lean index cfafb9cea8b59..b039f2c0a844d 100644 --- a/Mathlib/RingTheory/Nilpotent/Lemmas.lean +++ b/Mathlib/RingTheory/Nilpotent/Lemmas.lean @@ -103,7 +103,7 @@ lemma isNilpotent_restrict_of_le {f : End R M} {p q : Submodule R M} simp_rw [LinearMap.zero_apply, ZeroMemClass.coe_zero, ZeroMemClass.coe_eq_zero] at hn ⊢ rw [LinearMap.pow_restrict, LinearMap.restrict_apply] at hn ⊢ ext - exact (congr_arg Subtype.val hn : _) + exact (congr_arg Subtype.val hn :) lemma isNilpotent.restrict {f : M →ₗ[R] M} {p : Submodule R M} (hf : MapsTo f p p) (hnil : IsNilpotent f) : diff --git a/Mathlib/RingTheory/NonUnitalSubring/Defs.lean b/Mathlib/RingTheory/NonUnitalSubring/Defs.lean index 557e930d7ef99..b0d51fc219306 100644 --- a/Mathlib/RingTheory/NonUnitalSubring/Defs.lean +++ b/Mathlib/RingTheory/NonUnitalSubring/Defs.lean @@ -159,7 +159,7 @@ theorem copy_eq (S : NonUnitalSubring R) (s : Set R) (hs : s = ↑S) : S.copy s theorem toNonUnitalSubsemiring_injective : Function.Injective (toNonUnitalSubsemiring : NonUnitalSubring R → NonUnitalSubsemiring R) - | _r, _s, h => ext (SetLike.ext_iff.mp h : _) + | _r, _s, h => ext (SetLike.ext_iff.mp h :) @[mono] theorem toNonUnitalSubsemiring_strictMono : @@ -173,7 +173,7 @@ theorem toNonUnitalSubsemiring_mono : theorem toAddSubgroup_injective : Function.Injective (toAddSubgroup : NonUnitalSubring R → AddSubgroup R) - | _r, _s, h => ext (SetLike.ext_iff.mp h : _) + | _r, _s, h => ext (SetLike.ext_iff.mp h :) @[mono] theorem toAddSubgroup_strictMono : @@ -185,7 +185,7 @@ theorem toAddSubgroup_mono : Monotone (toAddSubgroup : NonUnitalSubring R → Ad theorem toSubsemigroup_injective : Function.Injective (toSubsemigroup : NonUnitalSubring R → Subsemigroup R) - | _r, _s, h => ext (SetLike.ext_iff.mp h : _) + | _r, _s, h => ext (SetLike.ext_iff.mp h :) @[mono] theorem toSubsemigroup_strictMono : diff --git a/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean b/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean index 0dd80dd6b65cc..366fb8a79c8b3 100644 --- a/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean +++ b/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean @@ -119,11 +119,11 @@ theorem copy_eq (S : NonUnitalSubsemiring R) (s : Set R) (hs : s = ↑S) : S.cop theorem toSubsemigroup_injective : Function.Injective (toSubsemigroup : NonUnitalSubsemiring R → Subsemigroup R) - | _, _, h => ext (SetLike.ext_iff.mp h : _) + | _, _, h => ext (SetLike.ext_iff.mp h :) theorem toAddSubmonoid_injective : Function.Injective (toAddSubmonoid : NonUnitalSubsemiring R → AddSubmonoid R) - | _, _, h => ext (SetLike.ext_iff.mp h : _) + | _, _, h => ext (SetLike.ext_iff.mp h :) /-- Construct a `NonUnitalSubsemiring R` from a set `s`, a subsemigroup `sg`, and an additive submonoid `sa` such that `x ∈ s ↔ x ∈ sg ↔ x ∈ sa`. -/ diff --git a/Mathlib/RingTheory/Perfection.lean b/Mathlib/RingTheory/Perfection.lean index 7d7e45a3a1929..6dc12681fc5bd 100644 --- a/Mathlib/RingTheory/Perfection.lean +++ b/Mathlib/RingTheory/Perfection.lean @@ -247,7 +247,7 @@ variable {p R P} /-- A perfection map induces an isomorphism to the perfection. -/ noncomputable def equiv {π : P →+* R} (m : PerfectionMap p π) : P ≃+* Ring.Perfection R p := RingEquiv.ofBijective (Perfection.lift p P R π) - ⟨fun _ _ hxy => m.injective fun n => (congr_arg (Perfection.coeff R p n) hxy : _), fun f => + ⟨fun _ _ hxy => m.injective fun n => (congr_arg (Perfection.coeff R p n) hxy :), fun f => let ⟨x, hx⟩ := m.surjective f.1 f.2 ⟨x, Perfection.ext <| hx⟩⟩ diff --git a/Mathlib/RingTheory/Smooth/Basic.lean b/Mathlib/RingTheory/Smooth/Basic.lean index 4a40e5881dd41..0d42a4a3c9af6 100644 --- a/Mathlib/RingTheory/Smooth/Basic.lean +++ b/Mathlib/RingTheory/Smooth/Basic.lean @@ -98,7 +98,7 @@ theorem comp_lift [FormallySmooth R A] (I : Ideal B) (hI : IsNilpotent I) @[simp] theorem mk_lift [FormallySmooth R A] (I : Ideal B) (hI : IsNilpotent I) (g : A →ₐ[R] B ⧸ I) (x : A) : Ideal.Quotient.mk I (FormallySmooth.lift I hI g x) = g x := - AlgHom.congr_fun (FormallySmooth.comp_lift I hI g : _) x + AlgHom.congr_fun (FormallySmooth.comp_lift I hI g :) x variable {C : Type u} [CommRing C] [Algebra R C] @@ -202,7 +202,7 @@ theorem of_split [FormallySmooth R P] (g : A →ₐ[R] P ⧸ (RingHom.ker f.toRi refine Ideal.Quotient.liftₐ _ (FormallySmooth.lift I ⟨2, hI⟩ (i.comp f)) ?_ have : RingHom.ker f ≤ I.comap (FormallySmooth.lift I ⟨2, hI⟩ (i.comp f)) := by rintro x (hx : f x = 0) - have : _ = i (f x) := (FormallySmooth.mk_lift I ⟨2, hI⟩ (i.comp f) x : _) + have : _ = i (f x) := (FormallySmooth.mk_lift I ⟨2, hI⟩ (i.comp f) x :) rwa [hx, map_zero, ← Ideal.Quotient.mk_eq_mk, Submodule.Quotient.mk_eq_zero] at this intro x hx have := (Ideal.pow_right_mono this 2).trans (Ideal.le_comap_pow _ 2) hx diff --git a/Mathlib/RingTheory/WittVector/Basic.lean b/Mathlib/RingTheory/WittVector/Basic.lean index e2c5bfed3057c..9258b5955fdb9 100644 --- a/Mathlib/RingTheory/WittVector/Basic.lean +++ b/Mathlib/RingTheory/WittVector/Basic.lean @@ -70,7 +70,7 @@ namespace mapFun theorem injective (f : α → β) (hf : Injective f) : Injective (mapFun f : 𝕎 α → 𝕎 β) := by intros _ _ h ext p - exact hf (congr_arg (fun x => coeff x p) h : _) + exact hf (congr_arg (fun x => coeff x p) h :) theorem surjective (f : α → β) (hf : Surjective f) : Surjective (mapFun f : 𝕎 α → 𝕎 β) := fun x => ⟨mk _ fun n => Classical.choose <| hf <| x.coeff n, diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index 5668b0eb5d566..c165757a42992 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.lean @@ -994,7 +994,7 @@ theorem le_range_of_union_finset_eq_top {α β : Type*} [Infinite β] (f : α exact infinite_univ by_contra h simp only [not_le] at h - let u : ∀ b, ∃ a, b ∈ f a := fun b => by simpa using (w.ge : _) (Set.mem_univ b) + let u : ∀ b, ∃ a, b ∈ f a := fun b => by simpa using (w.ge :) (Set.mem_univ b) let u' : β → range f := fun b => ⟨f (u b).choose, by simp⟩ have v' : ∀ a, u' ⁻¹' {⟨f a, by simp⟩} ≤ f a := by rintro a p m diff --git a/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean b/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean index d1b3479c6c896..160faf10c2854 100644 --- a/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean +++ b/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean @@ -334,7 +334,7 @@ def CertificateOracle.fourierMotzkin : CertificateOracle where produceCertificate hyps maxVar := do let linarithData := mkLinarithData hyps maxVar let result ← - (ExceptT.run (StateT.run (do validate; elimAllVarsM : LinarithM Unit) linarithData) : _) + (ExceptT.run (StateT.run (do validate; elimAllVarsM : LinarithM Unit) linarithData) :) match result with | (Except.ok _) => failure | (Except.error contr) => return contr.src.flatten diff --git a/Mathlib/Topology/Algebra/ConstMulAction.lean b/Mathlib/Topology/Algebra/ConstMulAction.lean index cd4bdb42717b6..29af329afbd4b 100644 --- a/Mathlib/Topology/Algebra/ConstMulAction.lean +++ b/Mathlib/Topology/Algebra/ConstMulAction.lean @@ -162,7 +162,7 @@ variable [Monoid M] [MulAction M α] [ContinuousConstSMul M α] @[to_additive] instance Units.continuousConstSMul : ContinuousConstSMul Mˣ α where - continuous_const_smul m := (continuous_const_smul (m : M) : _) + continuous_const_smul m := continuous_const_smul (m : M) @[to_additive] theorem smul_closure_subset (c : M) (s : Set α) : c • closure s ⊆ closure (c • s) := @@ -474,7 +474,7 @@ instance (priority := 100) t2Space_of_properlyDiscontinuousSMul_of_t2Space [T2Sp have f_op : IsOpenMap f := isOpenMap_quotient_mk'_mul rintro ⟨x₀⟩ ⟨y₀⟩ (hxy : f x₀ ≠ f y₀) show ∃ U ∈ 𝓝 (f x₀), ∃ V ∈ 𝓝 (f y₀), _ - have hγx₀y₀ : ∀ γ : Γ, γ • x₀ ≠ y₀ := not_exists.mp (mt Quotient.sound hxy.symm : _) + have hγx₀y₀ : ∀ γ : Γ, γ • x₀ ≠ y₀ := not_exists.mp (mt Quotient.sound hxy.symm :) obtain ⟨K₀, hK₀, K₀_in⟩ := exists_compact_mem_nhds x₀ obtain ⟨L₀, hL₀, L₀_in⟩ := exists_compact_mem_nhds y₀ let bad_Γ_set := { γ : Γ | (γ • ·) '' K₀ ∩ L₀ ≠ ∅ } diff --git a/Mathlib/Topology/Algebra/Group/Basic.lean b/Mathlib/Topology/Algebra/Group/Basic.lean index 003e76adb5395..28b8320d761a6 100644 --- a/Mathlib/Topology/Algebra/Group/Basic.lean +++ b/Mathlib/Topology/Algebra/Group/Basic.lean @@ -1008,7 +1008,7 @@ variable [TopologicalSpace α] {f g : α → G} {s : Set α} {x : α} @[to_additive (attr := continuity, fun_prop) sub] theorem Continuous.div' (hf : Continuous f) (hg : Continuous g) : Continuous fun x => f x / g x := - continuous_div'.comp (hf.prod_mk hg : _) + continuous_div'.comp (hf.prod_mk hg :) @[to_additive (attr := continuity) continuous_sub_left] lemma continuous_div_left' (a : G) : Continuous (a / ·) := continuous_const.div' continuous_id diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean b/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean index 4386fe90f6bd1..81e5cd9c09b6a 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean @@ -256,14 +256,14 @@ open MulOpposite variable [AddCommMonoid α] [TopologicalSpace α] {f : β → α} {a : α} theorem HasSum.op (hf : HasSum f a) : HasSum (fun a ↦ op (f a)) (op a) := - (hf.map (@opAddEquiv α _) continuous_op : _) + (hf.map (@opAddEquiv α _) continuous_op :) theorem Summable.op (hf : Summable f) : Summable (op ∘ f) := hf.hasSum.op.summable theorem HasSum.unop {f : β → αᵐᵒᵖ} {a : αᵐᵒᵖ} (hf : HasSum f a) : HasSum (fun a ↦ unop (f a)) (unop a) := - (hf.map (@opAddEquiv α _).symm continuous_unop : _) + (hf.map (@opAddEquiv α _).symm continuous_unop :) theorem Summable.unop {f : β → αᵐᵒᵖ} (hf : Summable f) : Summable (unop ∘ f) := hf.hasSum.unop.summable diff --git a/Mathlib/Topology/Algebra/Monoid.lean b/Mathlib/Topology/Algebra/Monoid.lean index ccd647dbad6f8..f136b5fd39568 100644 --- a/Mathlib/Topology/Algebra/Monoid.lean +++ b/Mathlib/Topology/Algebra/Monoid.lean @@ -89,7 +89,7 @@ theorem ContinuousMul.induced {α : Type*} {β : Type*} {F : Type*} [FunLike F @[to_additive (attr := continuity, fun_prop)] theorem Continuous.mul {f g : X → M} (hf : Continuous f) (hg : Continuous g) : Continuous fun x => f x * g x := - continuous_mul.comp (hf.prod_mk hg : _) + continuous_mul.comp (hf.prod_mk hg :) @[to_additive (attr := continuity)] theorem continuous_mul_left (a : M) : Continuous fun b : M => a * b := @@ -102,7 +102,7 @@ theorem continuous_mul_right (a : M) : Continuous fun b : M => b * a := @[to_additive (attr := fun_prop)] theorem ContinuousOn.mul {f g : X → M} {s : Set X} (hf : ContinuousOn f s) (hg : ContinuousOn g s) : ContinuousOn (fun x => f x * g x) s := - (continuous_mul.comp_continuousOn (hf.prod hg) : _) + (continuous_mul.comp_continuousOn (hf.prod hg) :) @[to_additive] theorem tendsto_mul {a b : M} : Tendsto (fun p : M × M => p.fst * p.snd) (𝓝 (a, b)) (𝓝 (a * b)) := diff --git a/Mathlib/Topology/Algebra/UniformField.lean b/Mathlib/Topology/Algebra/UniformField.lean index 8c8c66bc9a593..a3f84dc3d6317 100644 --- a/Mathlib/Topology/Algebra/UniformField.lean +++ b/Mathlib/Topology/Algebra/UniformField.lean @@ -124,7 +124,7 @@ theorem mul_hatInv_cancel {x : hat K} (x_ne : x ≠ 0) : x * hatInv x = 1 := by letI : TopologicalSpace (hat K × hat K) := instTopologicalSpaceProd have : ContinuousAt (fun y : hat K => ((y, hatInv y) : hat K × hat K)) x := continuous_id.continuousAt.prod (continuous_hatInv x_ne) - exact (_root_.continuous_mul.continuousAt.comp this : _) + exact (_root_.continuous_mul.continuousAt.comp this :) have clo : x ∈ closure (c '' {0}ᶜ) := by have := isDenseInducing_coe.dense x rw [← image_univ, show (univ : Set K) = {0} ∪ {0}ᶜ from (union_compl_self _).symm, diff --git a/Mathlib/Topology/Algebra/UniformGroup/Basic.lean b/Mathlib/Topology/Algebra/UniformGroup/Basic.lean index 4baeea0bda780..f02e105e37e93 100644 --- a/Mathlib/Topology/Algebra/UniformGroup/Basic.lean +++ b/Mathlib/Topology/Algebra/UniformGroup/Basic.lean @@ -279,7 +279,7 @@ private theorem extend_Z_bilin_aux (x₀ : α) (y₁ : δ) : ∃ U₂ ∈ comap have := Tendsto.prod_mk (tendsto_sub_comap_self de x₀) (tendsto_const_nhds : Tendsto (fun _ : β × β => y₁) (comap ee <| 𝓝 (x₀, x₀)) (𝓝 y₁)) rw [nhds_prod_eq, prod_comap_comap_eq, ← nhds_prod_eq] - exact (this : _) + exact (this :) have lim2 : Tendsto (fun p : β × δ => φ p.1 p.2) (𝓝 (0, y₁)) (𝓝 0) := by simpa using hφ.tendsto (0, y₁) have lim := lim2.comp lim1 diff --git a/Mathlib/Topology/Algebra/UniformGroup/Defs.lean b/Mathlib/Topology/Algebra/UniformGroup/Defs.lean index 5b6a3aeeb9ff2..2733cc8e8d6b6 100644 --- a/Mathlib/Topology/Algebra/UniformGroup/Defs.lean +++ b/Mathlib/Topology/Algebra/UniformGroup/Defs.lean @@ -479,7 +479,7 @@ private theorem extend_Z_bilin_aux (x₀ : α) (y₁ : δ) : ∃ U₂ ∈ comap have := Tendsto.prod_mk (tendsto_sub_comap_self de x₀) (tendsto_const_nhds : Tendsto (fun _ : β × β => y₁) (comap ee <| 𝓝 (x₀, x₀)) (𝓝 y₁)) rw [nhds_prod_eq, prod_comap_comap_eq, ← nhds_prod_eq] - exact (this : _) + exact (this :) have lim2 : Tendsto (fun p : β × δ => φ p.1 p.2) (𝓝 (0, y₁)) (𝓝 0) := by simpa using hφ.tendsto (0, y₁) have lim := lim2.comp lim1 diff --git a/Mathlib/Topology/Basic.lean b/Mathlib/Topology/Basic.lean index e6f284b71d21c..04de611bd1b5b 100644 --- a/Mathlib/Topology/Basic.lean +++ b/Mathlib/Topology/Basic.lean @@ -1665,7 +1665,7 @@ However, lemmas with this conclusion are not nice to use in practice because continuous_add.comp (continuous_id.prod_mk continuous_id) ``` The second is a valid proof, which is accepted if you write it as - `continuous_add.comp (continuous_id.prod_mk continuous_id : _)` + `continuous_add.comp (continuous_id.prod_mk continuous_id :)` 2. If the operation has more than 2 arguments, they are impractical to use, because in your application the arguments in the domain might be in a different order or associated differently. diff --git a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean index 98981cae50ee9..99c6519501cba 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean @@ -100,7 +100,7 @@ def limitConeInfiIsLimit (F : J ⥤ TopCat.{max v u}) : IsLimit (limitConeInfi.{ continuous_iff_coinduced_le.mpr (le_iInf fun j => coinduced_le_iff_le_induced.mp <| - (continuous_iff_coinduced_le.mp (s.π.app j).continuous : _)) + (continuous_iff_coinduced_le.mp (s.π.app j).continuous :)) · rfl instance topCat_hasLimitsOfSize : HasLimitsOfSize.{w, v} TopCat.{max v u} where @@ -159,7 +159,7 @@ def colimitCoconeIsColimit (F : J ⥤ TopCat.{max v u}) : IsColimit (colimitCoco continuous_iff_le_induced.mpr (iSup_le fun j => coinduced_le_iff_le_induced.mp <| - (continuous_iff_coinduced_le.mp (s.ι.app j).continuous : _)) + (continuous_iff_coinduced_le.mp (s.ι.app j).continuous :)) · rfl instance topCat_hasColimitsOfSize : HasColimitsOfSize.{w,v} TopCat.{max v u} where diff --git a/Mathlib/Topology/Category/TopCat/Limits/Products.lean b/Mathlib/Topology/Category/TopCat/Limits/Products.lean index 6512a54157e40..6a1dbd61c0562 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Products.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Products.lean @@ -58,12 +58,12 @@ theorem piIsoPi_inv_π {ι : Type v} (α : ι → TopCat.{max v u}) (i : ι) : (piIsoPi α).inv ≫ Pi.π α i = piπ α i := by simp [piIsoPi] theorem piIsoPi_inv_π_apply {ι : Type v} (α : ι → TopCat.{max v u}) (i : ι) (x : ∀ i, α i) : - (Pi.π α i : _) ((piIsoPi α).inv x) = x i := + (Pi.π α i :) ((piIsoPi α).inv x) = x i := ConcreteCategory.congr_hom (piIsoPi_inv_π α i) x -- Porting note: needing the type ascription on `∏ᶜ α : TopCat.{max v u}` is unfortunate. theorem piIsoPi_hom_apply {ι : Type v} (α : ι → TopCat.{max v u}) (i : ι) - (x : (∏ᶜ α : TopCat.{max v u})) : (piIsoPi α).hom x i = (Pi.π α i : _) x := by + (x : (∏ᶜ α : TopCat.{max v u})) : (piIsoPi α).hom x i = (Pi.π α i :) x := by have := piIsoPi_inv_π α i rw [Iso.inv_comp_eq] at this exact ConcreteCategory.congr_hom this x @@ -106,11 +106,11 @@ theorem sigmaIsoSigma_hom_ι {ι : Type v} (α : ι → TopCat.{max v u}) (i : Sigma.ι α i ≫ (sigmaIsoSigma α).hom = sigmaι α i := by simp [sigmaIsoSigma] theorem sigmaIsoSigma_hom_ι_apply {ι : Type v} (α : ι → TopCat.{max v u}) (i : ι) (x : α i) : - (sigmaIsoSigma α).hom ((Sigma.ι α i : _) x) = Sigma.mk i x := + (sigmaIsoSigma α).hom ((Sigma.ι α i :) x) = Sigma.mk i x := ConcreteCategory.congr_hom (sigmaIsoSigma_hom_ι α i) x theorem sigmaIsoSigma_inv_apply {ι : Type v} (α : ι → TopCat.{max v u}) (i : ι) (x : α i) : - (sigmaIsoSigma α).inv ⟨i, x⟩ = (Sigma.ι α i : _) x := by + (sigmaIsoSigma α).inv ⟨i, x⟩ = (Sigma.ι α i :) x := by rw [← sigmaIsoSigma_hom_ι_apply, ← comp_app, ← comp_app, Iso.hom_inv_id, Category.comp_id] @@ -277,7 +277,7 @@ def binaryCofanIsColimit (X Y : TopCat.{u}) : IsColimit (TopCat.binaryCofan X Y) rfl · intro s m h₁ h₂ ext (x | x) - exacts [(ConcreteCategory.congr_hom h₁ x : _), (ConcreteCategory.congr_hom h₂ x : _)] + exacts [(ConcreteCategory.congr_hom h₁ x :), (ConcreteCategory.congr_hom h₂ x :)] theorem binaryCofan_isColimit_iff {X Y : TopCat} (c : BinaryCofan X Y) : Nonempty (IsColimit c) ↔ diff --git a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean index f7dfb76f0da23..1bc507cd752fd 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean @@ -452,14 +452,14 @@ theorem colimit_topology (F : J ⥤ TopCat.{max v u}) : (colimit F).str = ⨆ j, (F.obj j).str.coinduced (colimit.ι F j) := coinduced_of_isColimit _ (colimit.isColimit F) -theorem colimit_isOpen_iff (F : J ⥤ TopCat.{max v u}) (U : Set ((colimit F : _) : Type max v u)) : +theorem colimit_isOpen_iff (F : J ⥤ TopCat.{max v u}) (U : Set ((colimit F :) : Type max v u)) : IsOpen U ↔ ∀ j, IsOpen (colimit.ι F j ⁻¹' U) := by dsimp [topologicalSpace_coe] conv_lhs => rw [colimit_topology F] exact isOpen_iSup_iff theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u}) - (U : Set ((colimit F : _) : Type u)) : + (U : Set ((colimit F :) : Type u)) : IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by rw [colimit_isOpen_iff] constructor diff --git a/Mathlib/Topology/Category/TopCat/Opens.lean b/Mathlib/Topology/Category/TopCat/Opens.lean index 3a0f0d9137b1e..4e4930958fd0e 100644 --- a/Mathlib/Topology/Category/TopCat/Opens.lean +++ b/Mathlib/Topology/Category/TopCat/Opens.lean @@ -91,7 +91,7 @@ theorem infLELeft_apply_mk (U V : Opens X) (x) (m) : @[simp] theorem leSupr_apply_mk {ι : Type*} (U : ι → Opens X) (i : ι) (x) (m) : - (leSupr U i) ⟨x, m⟩ = ⟨x, (le_iSup U i : _) m⟩ := + (leSupr U i) ⟨x, m⟩ = ⟨x, (le_iSup U i :) m⟩ := rfl /-- The functor from open sets in `X` to `TopCat`, diff --git a/Mathlib/Topology/ContinuousMap/Algebra.lean b/Mathlib/Topology/ContinuousMap/Algebra.lean index 7b2984309d3c0..5d745326a17a6 100644 --- a/Mathlib/Topology/ContinuousMap/Algebra.lean +++ b/Mathlib/Topology/ContinuousMap/Algebra.lean @@ -50,7 +50,7 @@ variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] @[to_additive] instance instMul [Mul β] [ContinuousMul β] : Mul C(α, β) := - ⟨fun f g => ⟨f * g, continuous_mul.comp (f.continuous.prod_mk g.continuous : _)⟩⟩ + ⟨fun f g => ⟨f * g, continuous_mul.comp (f.continuous.prod_mk g.continuous :)⟩⟩ @[to_additive (attr := norm_cast, simp)] theorem coe_mul [Mul β] [ContinuousMul β] (f g : C(α, β)) : ⇑(f * g) = f * g := diff --git a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean index 0d56fcaf0d007..6a26326badb7b 100644 --- a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean +++ b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean @@ -519,7 +519,7 @@ theorem arzela_ascoli₁ [CompactSpace β] (A : Set (α →ᵇ β)) (closed : Is · exact (hU x').2.2 _ hx' _ (hU x').1 hf · exact (hU x').2.2 _ hx' _ (hU x').1 hg · have F_f_g : F (f x') = F (g x') := - (congr_arg (fun f : tα → tβ => (f ⟨x', x'tα⟩ : β)) f_eq_g : _) + (congr_arg (fun f : tα → tβ => (f ⟨x', x'tα⟩ : β)) f_eq_g :) calc dist (f x') (g x') ≤ dist (f x') (F (f x')) + dist (g x') (F (f x')) := dist_triangle_right _ _ _ diff --git a/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean b/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean index 6726cd76211d7..8756075a38d8e 100644 --- a/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean +++ b/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean @@ -466,7 +466,7 @@ variable [SeminormedAddCommGroup β] {𝕜 : Type*} [NormedField 𝕜] [NormedSp theorem norm_toBCF_eq_norm {f : C₀(α, β)} : ‖f.toBCF‖ = ‖f‖ := rfl -instance : NormedSpace 𝕜 C₀(α, β) where norm_smul_le k f := (norm_smul_le k f.toBCF : _) +instance : NormedSpace 𝕜 C₀(α, β) where norm_smul_le k f := (norm_smul_le k f.toBCF :) end NormedSpace @@ -534,7 +534,7 @@ section NormedStar variable [NormedAddCommGroup β] [StarAddMonoid β] [NormedStarGroup β] instance instNormedStarGroup : NormedStarGroup C₀(α, β) where - norm_star f := (norm_star f.toBCF : _) + norm_star f := (norm_star f.toBCF :) end NormedStar diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index 9af7fc85de01f..2b05f77e1de94 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -195,7 +195,7 @@ theorem ι_eq_iff_rel (i j : D.J) (x : D.U i) (y : D.U j) : show _ = Sigma.mk j y from ConcreteCategory.congr_hom (sigmaIsoSigma.{_, u} D.U).inv_hom_id _] change InvImage D.Rel (sigmaIsoSigma.{_, u} D.U).hom _ _ rw [← (InvImage.equivalence _ _ D.rel_equiv).eqvGen_iff] - refine Relation.EqvGen.mono ?_ (D.eqvGen_of_π_eq h : _) + refine Relation.EqvGen.mono ?_ (D.eqvGen_of_π_eq h :) rintro _ _ ⟨x⟩ obtain ⟨⟨⟨i, j⟩, y⟩, rfl⟩ := (ConcreteCategory.bijective_of_isIso (sigmaIsoSigma.{u, u} _).inv).2 x diff --git a/Mathlib/Topology/Instances/ENNReal.lean b/Mathlib/Topology/Instances/ENNReal.lean index fe2ae506c5631..d25ba301a1d4d 100644 --- a/Mathlib/Topology/Instances/ENNReal.lean +++ b/Mathlib/Topology/Instances/ENNReal.lean @@ -1176,7 +1176,7 @@ theorem continuous_edist : Continuous fun p : α × α => edist p.1 p.2 := by @[continuity, fun_prop] theorem Continuous.edist [TopologicalSpace β] {f g : β → α} (hf : Continuous f) (hg : Continuous g) : Continuous fun b => edist (f b) (g b) := - continuous_edist.comp (hf.prod_mk hg : _) + continuous_edist.comp (hf.prod_mk hg :) theorem Filter.Tendsto.edist {f g : β → α} {x : Filter β} {a b : α} (hf : Tendsto f x (𝓝 a)) (hg : Tendsto g x (𝓝 b)) : Tendsto (fun x => edist (f x) (g x)) x (𝓝 (edist a b)) := diff --git a/Mathlib/Topology/Instances/Matrix.lean b/Mathlib/Topology/Instances/Matrix.lean index 6dbd675168fb4..13decc88c4c0a 100644 --- a/Mathlib/Topology/Instances/Matrix.lean +++ b/Mathlib/Topology/Instances/Matrix.lean @@ -263,7 +263,7 @@ variable [AddCommMonoid R] [TopologicalSpace R] theorem HasSum.matrix_transpose {f : X → Matrix m n R} {a : Matrix m n R} (hf : HasSum f a) : HasSum (fun x => (f x)ᵀ) aᵀ := - (hf.map (Matrix.transposeAddEquiv m n R) continuous_id.matrix_transpose : _) + (hf.map (Matrix.transposeAddEquiv m n R) continuous_id.matrix_transpose :) theorem Summable.matrix_transpose {f : X → Matrix m n R} (hf : Summable f) : Summable fun x => (f x)ᵀ := @@ -283,7 +283,7 @@ theorem Matrix.transpose_tsum [T2Space R] {f : X → Matrix m n R} : (∑' x, f theorem HasSum.matrix_conjTranspose [StarAddMonoid R] [ContinuousStar R] {f : X → Matrix m n R} {a : Matrix m n R} (hf : HasSum f a) : HasSum (fun x => (f x)ᴴ) aᴴ := - (hf.map (Matrix.conjTransposeAddEquiv m n R) continuous_id.matrix_conjTranspose : _) + (hf.map (Matrix.conjTransposeAddEquiv m n R) continuous_id.matrix_conjTranspose :) theorem Summable.matrix_conjTranspose [StarAddMonoid R] [ContinuousStar R] {f : X → Matrix m n R} (hf : Summable f) : Summable fun x => (f x)ᴴ := @@ -359,7 +359,7 @@ theorem Matrix.blockDiagonal_tsum [DecidableEq p] [T2Space R] {f : X → p → M theorem HasSum.matrix_blockDiag {f : X → Matrix (m × p) (n × p) R} {a : Matrix (m × p) (n × p) R} (hf : HasSum f a) : HasSum (fun x => blockDiag (f x)) (blockDiag a) := - (hf.map (blockDiagAddMonoidHom m n p R) <| Continuous.matrix_blockDiag continuous_id : _) + (hf.map (blockDiagAddMonoidHom m n p R) <| Continuous.matrix_blockDiag continuous_id :) theorem Summable.matrix_blockDiag {f : X → Matrix (m × p) (n × p) R} (hf : Summable f) : Summable fun x => blockDiag (f x) := diff --git a/Mathlib/Topology/List.lean b/Mathlib/Topology/List.lean index c6bac03cf1d2e..be04e98105dbd 100644 --- a/Mathlib/Topology/List.lean +++ b/Mathlib/Topology/List.lean @@ -212,7 +212,7 @@ theorem continuous_insertIdx' {n : ℕ} {i : Fin (n + 1)} : theorem continuous_insertIdx {n : ℕ} {i : Fin (n + 1)} {f : β → α} {g : β → List.Vector α n} (hf : Continuous f) (hg : Continuous g) : Continuous fun b => Vector.insertIdx (f b) i (g b) := - continuous_insertIdx'.comp (hf.prod_mk hg : _) + continuous_insertIdx'.comp (hf.prod_mk hg) @[deprecated (since := "2024-10-21")] alias continuous_insertNth := continuous_insertIdx diff --git a/Mathlib/Topology/LocalAtTarget.lean b/Mathlib/Topology/LocalAtTarget.lean index af16705f2ce51..f1029b3df76df 100644 --- a/Mathlib/Topology/LocalAtTarget.lean +++ b/Mathlib/Topology/LocalAtTarget.lean @@ -195,7 +195,7 @@ To check that `f` is an embedding it suffices to check that `U i → Y` is an em theorem isEmbedding_of_iSup_eq_top_of_preimage_subset_range {X Y} [TopologicalSpace X] [TopologicalSpace Y] (f : X → Y) (h : Continuous f) {ι : Type*} - (U : ι → Opens Y) (hU : Set.range f ⊆ (iSup U : _)) + (U : ι → Opens Y) (hU : Set.range f ⊆ (iSup U :)) (V : ι → Type*) [∀ i, TopologicalSpace (V i)] (iV : ∀ i, V i → X) (hiV : ∀ i, Continuous (iV i)) (hV : ∀ i, f ⁻¹' U i ⊆ Set.range (iV i)) (hV' : ∀ i, IsEmbedding (f ∘ iV i)) : IsEmbedding f := by diff --git a/Mathlib/Topology/MetricSpace/Completion.lean b/Mathlib/Topology/MetricSpace/Completion.lean index 69037d369df59..e80a1ca356e08 100644 --- a/Mathlib/Topology/MetricSpace/Completion.lean +++ b/Mathlib/Topology/MetricSpace/Completion.lean @@ -45,7 +45,7 @@ protected theorem uniformContinuous_dist : /-- The new distance is continuous. -/ protected theorem continuous_dist [TopologicalSpace β] {f g : β → Completion α} (hf : Continuous f) (hg : Continuous g) : Continuous fun x ↦ dist (f x) (g x) := - Completion.uniformContinuous_dist.continuous.comp (hf.prod_mk hg : _) + Completion.uniformContinuous_dist.continuous.comp (hf.prod_mk hg :) /-- The new distance is an extension of the original distance. -/ @[simp] diff --git a/Mathlib/Topology/MetricSpace/PiNat.lean b/Mathlib/Topology/MetricSpace/PiNat.lean index b31d3608b2fed..db64438ea4873 100644 --- a/Mathlib/Topology/MetricSpace/PiNat.lean +++ b/Mathlib/Topology/MetricSpace/PiNat.lean @@ -681,7 +681,7 @@ theorem exists_nat_nat_continuous_surjective_of_completeSpace (α : Type*) [Metr let s : Set (ℕ → ℕ) := { x | (⋂ n : ℕ, closedBall (u (x n)) ((1 / 2) ^ n)).Nonempty } let g : s → α := fun x => x.2.some have A : ∀ (x : s) (n : ℕ), dist (g x) (u ((x : ℕ → ℕ) n)) ≤ (1 / 2) ^ n := fun x n => - (mem_iInter.1 x.2.some_mem n : _) + (mem_iInter.1 x.2.some_mem n :) have g_cont : Continuous g := by refine continuous_iff_continuousAt.2 fun y => ?_ refine continuousAt_of_locally_lipschitz zero_lt_one 4 fun x hxy => ?_ diff --git a/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean b/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean index aba39bbafa59c..844690eff5d58 100644 --- a/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean +++ b/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean @@ -207,7 +207,7 @@ lemma continuous_dist : Continuous fun p : α × α ↦ dist p.1 p.2 := uniformC @[continuity, fun_prop] protected lemma Continuous.dist [TopologicalSpace β] {f g : β → α} (hf : Continuous f) (hg : Continuous g) : Continuous fun b => dist (f b) (g b) := - continuous_dist.comp (hf.prod_mk hg : _) + continuous_dist.comp (hf.prod_mk hg :) protected lemma Filter.Tendsto.dist {f g : β → α} {x : Filter β} {a b : α} (hf : Tendsto f x (𝓝 a)) (hg : Tendsto g x (𝓝 b)) : @@ -233,7 +233,7 @@ lemma continuous_nndist : Continuous fun p : α × α => nndist p.1 p.2 := @[fun_prop] protected lemma Continuous.nndist [TopologicalSpace β] {f g : β → α} (hf : Continuous f) (hg : Continuous g) : Continuous fun b => nndist (f b) (g b) := - continuous_nndist.comp (hf.prod_mk hg : _) + continuous_nndist.comp (hf.prod_mk hg :) protected lemma Filter.Tendsto.nndist {f g : β → α} {x : Filter β} {a b : α} (hf : Tendsto f x (𝓝 a)) (hg : Tendsto g x (𝓝 b)) : diff --git a/Mathlib/Topology/Order/DenselyOrdered.lean b/Mathlib/Topology/Order/DenselyOrdered.lean index 0c981229bfc16..957c94d57c1e0 100644 --- a/Mathlib/Topology/Order/DenselyOrdered.lean +++ b/Mathlib/Topology/Order/DenselyOrdered.lean @@ -259,9 +259,9 @@ theorem map_coe_atTop_of_Ioo_subset (hb : s ⊆ Iio b) (hs : ∀ a' < b, ∃ a < theorem map_coe_atBot_of_Ioo_subset (ha : s ⊆ Ioi a) (hs : ∀ b' > a, ∃ b > a, Ioo a b ⊆ s) : map ((↑) : s → α) atBot = 𝓝[>] a := by - -- the elaborator gets stuck without `(... : _)` + -- the elaborator gets stuck without `(... :)` refine (map_coe_atTop_of_Ioo_subset (show ofDual ⁻¹' s ⊆ Iio (toDual a) from ha) - fun b' hb' => ?_ : _) + fun b' hb' => ?_ :) simpa only [OrderDual.exists, dual_Ioo] using hs b' hb' /-- The `atTop` filter for an open interval `Ioo a b` comes from the left-neighbourhoods filter at diff --git a/Mathlib/Topology/Order/Lattice.lean b/Mathlib/Topology/Order/Lattice.lean index 1ef8035f3ab65..60a021ba8a061 100644 --- a/Mathlib/Topology/Order/Lattice.lean +++ b/Mathlib/Topology/Order/Lattice.lean @@ -77,7 +77,7 @@ theorem continuous_inf [Min L] [ContinuousInf L] : Continuous fun p : L × L => @[continuity, fun_prop] theorem Continuous.inf [Min L] [ContinuousInf L] {f g : X → L} (hf : Continuous f) (hg : Continuous g) : Continuous fun x => f x ⊓ g x := - continuous_inf.comp (hf.prod_mk hg : _) + continuous_inf.comp (hf.prod_mk hg :) @[continuity] theorem continuous_sup [Max L] [ContinuousSup L] : Continuous fun p : L × L => p.1 ⊔ p.2 := @@ -86,7 +86,7 @@ theorem continuous_sup [Max L] [ContinuousSup L] : Continuous fun p : L × L => @[continuity, fun_prop] theorem Continuous.sup [Max L] [ContinuousSup L] {f g : X → L} (hf : Continuous f) (hg : Continuous g) : Continuous fun x => f x ⊔ g x := - continuous_sup.comp (hf.prod_mk hg : _) + continuous_sup.comp (hf.prod_mk hg :) namespace Filter.Tendsto diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index 0363f5b15a445..20435dc149290 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -1018,7 +1018,7 @@ theorem continuousWithinAt_iff_continuousWithinAt_comp_left {f : Z → X} {s : S neighborhood of the initial point is sent to the source of the partial homeomorphism -/ theorem continuousAt_iff_continuousAt_comp_left {f : Z → X} {x : Z} (h : f ⁻¹' e.source ∈ 𝓝 x) : ContinuousAt f x ↔ ContinuousAt (e ∘ f) x := by - have hx : f x ∈ e.source := (mem_of_mem_nhds h : _) + have hx : f x ∈ e.source := (mem_of_mem_nhds h :) have h' : f ⁻¹' e.source ∈ 𝓝[univ] x := by rwa [nhdsWithin_univ] rw [← continuousWithinAt_univ, ← continuousWithinAt_univ, e.continuousWithinAt_iff_continuousWithinAt_comp_left hx h'] diff --git a/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean b/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean index 4ae09d65bbf39..807fbd616d09b 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/PairwiseIntersections.lean @@ -217,7 +217,7 @@ after appropriate whiskering and postcomposition. -/ def pairwiseCoconeIso : (Pairwise.cocone U).op ≅ - (Cones.postcomposeEquivalence (NatIso.op (pairwiseDiagramIso U : _) : _)).functor.obj + (Cones.postcomposeEquivalence (NatIso.op (pairwiseDiagramIso U :) :)).functor.obj ((opensLeCoverCocone U).op.whisker (pairwiseToOpensLeCover U).op) := Cones.ext (Iso.refl _) (by aesop_cat) @@ -254,7 +254,7 @@ theorem isSheafOpensLeCover_iff_isSheafPairwiseIntersections : ((opensLeCoverCocone U).op.whisker (pairwiseToOpensLeCover U).op))) := (IsLimit.equivIsoLimit (Functor.mapConePostcomposeEquivalenceFunctor _).symm) _ ≃ IsLimit (F.mapCone (Pairwise.cocone U).op) := - IsLimit.equivIsoLimit ((Cones.functoriality _ _).mapIso (pairwiseCoconeIso U : _).symm) + IsLimit.equivIsoLimit ((Cones.functoriality _ _).mapIso (pairwiseCoconeIso U :).symm) /-- The sheaf condition in terms of an equalizer diagram is equivalent to the reformulation in terms of a limit diagram over `U i` and `U i ⊓ U j`. diff --git a/Mathlib/Topology/Sheaves/Stalks.lean b/Mathlib/Topology/Sheaves/Stalks.lean index 28c58d23c6a6d..3b24d1d5a253d 100644 --- a/Mathlib/Topology/Sheaves/Stalks.lean +++ b/Mathlib/Topology/Sheaves/Stalks.lean @@ -335,12 +335,12 @@ noncomputable def stalkSpecializes (F : X.Presheaf C) {x y : X} (h : x ⤳ y) : refine colimit.desc _ ⟨_, fun U => ?_, ?_⟩ · exact colimit.ι ((OpenNhds.inclusion x).op ⋙ F) - (op ⟨(unop U).1, (specializes_iff_forall_open.mp h _ (unop U).1.2 (unop U).2 : _)⟩) + (op ⟨(unop U).1, (specializes_iff_forall_open.mp h _ (unop U).1.2 (unop U).2 :)⟩) · intro U V i dsimp rw [Category.comp_id] - let U' : OpenNhds x := ⟨_, (specializes_iff_forall_open.mp h _ (unop U).1.2 (unop U).2 : _)⟩ - let V' : OpenNhds x := ⟨_, (specializes_iff_forall_open.mp h _ (unop V).1.2 (unop V).2 : _)⟩ + let U' : OpenNhds x := ⟨_, (specializes_iff_forall_open.mp h _ (unop U).1.2 (unop U).2 :)⟩ + let V' : OpenNhds x := ⟨_, (specializes_iff_forall_open.mp h _ (unop V).1.2 (unop V).2 :)⟩ exact colimit.w ((OpenNhds.inclusion x).op ⋙ F) (show V' ⟶ U' from i.unop).op @[reassoc (attr := simp), elementwise nosimp] diff --git a/Mathlib/Topology/UniformSpace/AbstractCompletion.lean b/Mathlib/Topology/UniformSpace/AbstractCompletion.lean index d5458eff1e284..67a5460ca8634 100644 --- a/Mathlib/Topology/UniformSpace/AbstractCompletion.lean +++ b/Mathlib/Topology/UniformSpace/AbstractCompletion.lean @@ -374,7 +374,7 @@ theorem uniformContinuous_map₂ (f : α → β → γ) : UniformContinuous₂ ( theorem continuous_map₂ {δ} [TopologicalSpace δ] {f : α → β → γ} {a : δ → hatα} {b : δ → hatβ} (ha : Continuous a) (hb : Continuous b) : Continuous fun d : δ => pkg.map₂ pkg' pkg'' f (a d) (b d) := - ((pkg.uniformContinuous_map₂ pkg' pkg'' f).continuous.comp (Continuous.prod_mk ha hb) : _) + ((pkg.uniformContinuous_map₂ pkg' pkg'' f).continuous.comp (Continuous.prod_mk ha hb) :) theorem map₂_coe_coe (a : α) (b : β) (f : α → β → γ) (hf : UniformContinuous₂ f) : pkg.map₂ pkg' pkg'' f (ι a) (ι' b) = ι'' (f a b) := diff --git a/Mathlib/Topology/VectorBundle/Basic.lean b/Mathlib/Topology/VectorBundle/Basic.lean index 63d31dc19d070..9ba91b204f66f 100644 --- a/Mathlib/Topology/VectorBundle/Basic.lean +++ b/Mathlib/Topology/VectorBundle/Basic.lean @@ -247,7 +247,7 @@ open Classical in def coordChangeL (e e' : Trivialization F (π F E)) [e.IsLinear R] [e'.IsLinear R] (b : B) : F ≃L[R] F := { toLinearEquiv := if hb : b ∈ e.baseSet ∩ e'.baseSet - then (e.linearEquivAt R b (hb.1 : _)).symm.trans (e'.linearEquivAt R b hb.2) + then (e.linearEquivAt R b (hb.1 :)).symm.trans (e'.linearEquivAt R b hb.2) else LinearEquiv.refl R F continuous_toFun := by by_cases hb : b ∈ e.baseSet ∩ e'.baseSet diff --git a/Mathlib/Topology/VectorBundle/Constructions.lean b/Mathlib/Topology/VectorBundle/Constructions.lean index 731ddade673df..0d6e705e2f422 100644 --- a/Mathlib/Topology/VectorBundle/Constructions.lean +++ b/Mathlib/Topology/VectorBundle/Constructions.lean @@ -145,7 +145,7 @@ theorem Trivialization.continuousLinearEquivAt_prod {e₁ : Trivialization F₁ ext v : 2 obtain ⟨v₁, v₂⟩ := v rw [(e₁.prod e₂).continuousLinearEquivAt_apply 𝕜, Trivialization.prod] - exact (congr_arg Prod.snd (prod_apply 𝕜 hx.1 hx.2 v₁ v₂) : _) + exact (congr_arg Prod.snd (prod_apply 𝕜 hx.1 hx.2 v₁ v₂) :) end diff --git a/MathlibTest/TypeCheck.lean b/MathlibTest/TypeCheck.lean index 9d38a614053df..1345ea5d983f1 100644 --- a/MathlibTest/TypeCheck.lean +++ b/MathlibTest/TypeCheck.lean @@ -29,7 +29,7 @@ example : True := by type_check Bool.true -- Bool type_check nat_lit 1 -- Nat type_check (1 : Nat) -- Nat - type_check (True : _) -- Prop + type_check (True :) -- Prop type_check ∀ x y : Nat, x = y -- Prop type_check fun x : Nat => 2 * x + 1 -- Nat -> Nat type_check [1] From eb9d83a331cc90b48e14c224c07cdb5dc871f00a Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 7 Jan 2025 08:13:01 +0000 Subject: [PATCH 034/681] chore(Measure/Pi): move parts to `MeasurableSpace/` (#20215) --- Mathlib.lean | 1 + Mathlib/MeasureTheory/Constructions/Pi.lean | 86 +------------- Mathlib/MeasureTheory/MeasurableSpace/Pi.lean | 107 ++++++++++++++++++ Mathlib/Probability/Independence/Basic.lean | 1 + Mathlib/Probability/Independence/Kernel.lean | 2 +- 5 files changed, 112 insertions(+), 85 deletions(-) create mode 100644 Mathlib/MeasureTheory/MeasurableSpace/Pi.lean diff --git a/Mathlib.lean b/Mathlib.lean index a43bb2278aa5e..280f1d1e523eb 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3763,6 +3763,7 @@ import Mathlib.MeasureTheory.MeasurableSpace.EventuallyMeasurable import Mathlib.MeasureTheory.MeasurableSpace.Instances import Mathlib.MeasureTheory.MeasurableSpace.Invariants import Mathlib.MeasureTheory.MeasurableSpace.NCard +import Mathlib.MeasureTheory.MeasurableSpace.Pi import Mathlib.MeasureTheory.MeasurableSpace.PreorderRestrict import Mathlib.MeasureTheory.MeasurableSpace.Prod import Mathlib.MeasureTheory.Measure.AEDisjoint diff --git a/Mathlib/MeasureTheory/Constructions/Pi.lean b/Mathlib/MeasureTheory/Constructions/Pi.lean index 963c8dcd5082f..102c61a082662 100644 --- a/Mathlib/MeasureTheory/Constructions/Pi.lean +++ b/Mathlib/MeasureTheory/Constructions/Pi.lean @@ -4,11 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ import Mathlib.MeasureTheory.Group.Measure +import Mathlib.MeasureTheory.MeasurableSpace.Pi import Mathlib.MeasureTheory.Measure.Prod import Mathlib.Topology.Constructions /-! -# Product measures +# Indexed product measures In this file we define and prove properties about finite products of measures (and at some point, countable products of measures). @@ -49,7 +50,6 @@ finitary product measure -/ - noncomputable section open Function Set MeasureTheory.OuterMeasure Filter MeasurableSpace Encodable @@ -60,88 +60,6 @@ universe u v variable {ι ι' : Type*} {α : ι → Type*} -/-! We start with some measurability properties -/ - -lemma MeasurableSpace.pi_eq_generateFrom_projections {mα : ∀ i, MeasurableSpace (α i)} : - pi = generateFrom {B | ∃ (i : ι) (A : Set (α i)), MeasurableSet A ∧ eval i ⁻¹' A = B} := by - simp only [pi, ← generateFrom_iUnion_measurableSet, iUnion_setOf, measurableSet_comap] - -/-- Boxes formed by π-systems form a π-system. -/ -theorem IsPiSystem.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsPiSystem (C i)) : - IsPiSystem (pi univ '' pi univ C) := by - rintro _ ⟨s₁, hs₁, rfl⟩ _ ⟨s₂, hs₂, rfl⟩ hst - rw [← pi_inter_distrib] at hst ⊢; rw [univ_pi_nonempty_iff] at hst - exact mem_image_of_mem _ fun i _ => hC i _ (hs₁ i (mem_univ i)) _ (hs₂ i (mem_univ i)) (hst i) - -/-- Boxes form a π-system. -/ -theorem isPiSystem_pi [∀ i, MeasurableSpace (α i)] : - IsPiSystem (pi univ '' pi univ fun i => { s : Set (α i) | MeasurableSet s }) := - IsPiSystem.pi fun _ => isPiSystem_measurableSet - -section Finite - -variable [Finite ι] - -/-- Boxes of countably spanning sets are countably spanning. -/ -theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) : - IsCountablySpanning (pi univ '' pi univ C) := by - choose s h1s h2s using hC - cases nonempty_encodable (ι → ℕ) - let e : ℕ → ι → ℕ := fun n => (@decode (ι → ℕ) _ n).iget - refine ⟨fun n => Set.pi univ fun i => s i (e n i), fun n => - mem_image_of_mem _ fun i _ => h1s i _, ?_⟩ - simp_rw - [e, (surjective_decode_iget (ι → ℕ)).iUnion_comp fun x => Set.pi univ fun i => s i (x i), - iUnion_univ_pi s, h2s, pi_univ] - -/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets - are countably spanning. -/ -theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) : - (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) = - generateFrom (pi univ '' pi univ C) := by - cases nonempty_encodable ι - apply le_antisymm - · refine iSup_le ?_; intro i; rw [comap_generateFrom] - apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩ - choose t h1t h2t using hC - simp_rw [eval_preimage, ← h2t] - rw [← @iUnion_const _ ℕ _ s] - have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) = - Set.pi univ fun k => ⋃ j : ℕ, - @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by - ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i' - by_cases h : i' = i - · subst h; simp - · rw [← Ne] at h; simp [h] - rw [this, ← iUnion_univ_pi] - apply MeasurableSet.iUnion - intro n; apply measurableSet_generateFrom - apply mem_image_of_mem; intro j _; dsimp only - by_cases h : j = i - · subst h; rwa [update_self] - · rw [update_of_ne h]; apply h1t - · apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩ - rw [univ_pi_eq_iInter]; apply MeasurableSet.iInter; intro i - apply @measurable_pi_apply _ _ (fun i => generateFrom (C i)) - exact measurableSet_generateFrom (hs i (mem_univ i)) - -/-- If `C` and `D` generate the σ-algebras on `α` resp. `β`, then rectangles formed by `C` and `D` - generate the σ-algebra on `α × β`. -/ -theorem generateFrom_eq_pi [h : ∀ i, MeasurableSpace (α i)] {C : ∀ i, Set (Set (α i))} - (hC : ∀ i, generateFrom (C i) = h i) (h2C : ∀ i, IsCountablySpanning (C i)) : - generateFrom (pi univ '' pi univ C) = MeasurableSpace.pi := by - simp only [← funext hC, generateFrom_pi_eq h2C] - -/-- The product σ-algebra is generated from boxes, i.e. `s ×ˢ t` for sets `s : set α` and - `t : set β`. -/ -theorem generateFrom_pi [∀ i, MeasurableSpace (α i)] : - generateFrom (pi univ '' pi univ fun i => { s : Set (α i) | MeasurableSet s }) = - MeasurableSpace.pi := - generateFrom_eq_pi (fun _ => generateFrom_measurableSet) fun _ => - isCountablySpanning_measurableSet - -end Finite - namespace MeasureTheory variable [Fintype ι] {m : ∀ i, OuterMeasure (α i)} diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Pi.lean b/Mathlib/MeasureTheory/MeasurableSpace/Pi.lean new file mode 100644 index 0000000000000..82e1418f467fc --- /dev/null +++ b/Mathlib/MeasureTheory/MeasurableSpace/Pi.lean @@ -0,0 +1,107 @@ +/- +Copyright (c) 2020 Floris van Doorn. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Floris van Doorn +-/ +import Mathlib.MeasureTheory.MeasurableSpace.Basic +import Mathlib.MeasureTheory.PiSystem + +/-! +# Bases of the indexed product σ-algebra + +In this file we prove several versions of the following lemma: + +given a finite indexed collection of measurable spaces `α i`, +if the σ-algebra on each `α i` is generated by `C i`, +then the sets `{x | ∀ i, x i ∈ s i}`, where `s i ∈ C i`, +generate the σ-algebra on the indexed product of `α i`s. +-/ + +noncomputable section + +open Function Set Filter MeasurableSpace Encodable +open scoped Classical + +variable {ι : Type*} {α : ι → Type*} + +/-! We start with some measurability properties -/ + +lemma MeasurableSpace.pi_eq_generateFrom_projections {mα : ∀ i, MeasurableSpace (α i)} : + pi = generateFrom {B | ∃ (i : ι) (A : Set (α i)), MeasurableSet A ∧ eval i ⁻¹' A = B} := by + simp only [pi, ← generateFrom_iUnion_measurableSet, iUnion_setOf, measurableSet_comap] + +/-- Boxes formed by π-systems form a π-system. -/ +theorem IsPiSystem.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsPiSystem (C i)) : + IsPiSystem (pi univ '' pi univ C) := by + rintro _ ⟨s₁, hs₁, rfl⟩ _ ⟨s₂, hs₂, rfl⟩ hst + rw [← pi_inter_distrib] at hst ⊢; rw [univ_pi_nonempty_iff] at hst + exact mem_image_of_mem _ fun i _ => hC i _ (hs₁ i (mem_univ i)) _ (hs₂ i (mem_univ i)) (hst i) + +/-- Boxes form a π-system. -/ +theorem isPiSystem_pi [∀ i, MeasurableSpace (α i)] : + IsPiSystem (pi univ '' pi univ fun i => { s : Set (α i) | MeasurableSet s }) := + IsPiSystem.pi fun _ => isPiSystem_measurableSet + +section Finite + +variable [Finite ι] + +/-- Boxes of countably spanning sets are countably spanning. -/ +theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) : + IsCountablySpanning (pi univ '' pi univ C) := by + choose s h1s h2s using hC + cases nonempty_encodable (ι → ℕ) + let e : ℕ → ι → ℕ := fun n => (@decode (ι → ℕ) _ n).iget + refine ⟨fun n => Set.pi univ fun i => s i (e n i), fun n => + mem_image_of_mem _ fun i _ => h1s i _, ?_⟩ + simp_rw + [e, (surjective_decode_iget (ι → ℕ)).iUnion_comp fun x => Set.pi univ fun i => s i (x i), + iUnion_univ_pi s, h2s, pi_univ] + +/-- The product of generated σ-algebras is the one generated by boxes, if both generating sets + are countably spanning. -/ +theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) : + (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) = + generateFrom (pi univ '' pi univ C) := by + cases nonempty_encodable ι + apply le_antisymm + · refine iSup_le ?_; intro i; rw [comap_generateFrom] + apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩ + choose t h1t h2t using hC + simp_rw [eval_preimage, ← h2t] + rw [← @iUnion_const _ ℕ _ s] + have : Set.pi univ (update (fun i' : ι => iUnion (t i')) i (⋃ _ : ℕ, s)) = + Set.pi univ fun k => ⋃ j : ℕ, + @update ι (fun i' => Set (α i')) _ (fun i' => t i' j) i s k := by + ext; simp_rw [mem_univ_pi]; apply forall_congr'; intro i' + by_cases h : i' = i + · subst h; simp + · rw [← Ne] at h; simp [h] + rw [this, ← iUnion_univ_pi] + apply MeasurableSet.iUnion + intro n; apply measurableSet_generateFrom + apply mem_image_of_mem; intro j _; dsimp only + by_cases h : j = i + · subst h; rwa [update_self] + · rw [update_of_ne h]; apply h1t + · apply generateFrom_le; rintro _ ⟨s, hs, rfl⟩ + rw [univ_pi_eq_iInter]; apply MeasurableSet.iInter; intro i + apply @measurable_pi_apply _ _ (fun i => generateFrom (C i)) + exact measurableSet_generateFrom (hs i (mem_univ i)) + +/-- If `C` and `D` generate the σ-algebras on `α` resp. `β`, then rectangles formed by `C` and `D` + generate the σ-algebra on `α × β`. -/ +theorem generateFrom_eq_pi [h : ∀ i, MeasurableSpace (α i)] {C : ∀ i, Set (Set (α i))} + (hC : ∀ i, generateFrom (C i) = h i) (h2C : ∀ i, IsCountablySpanning (C i)) : + generateFrom (pi univ '' pi univ C) = MeasurableSpace.pi := by + simp only [← funext hC, generateFrom_pi_eq h2C] + +/-- The product σ-algebra is generated from boxes, i.e. `s ×ˢ t` for sets `s : set α` and + `t : set β`. -/ +theorem generateFrom_pi [∀ i, MeasurableSpace (α i)] : + generateFrom (pi univ '' pi univ fun i => { s : Set (α i) | MeasurableSet s }) = + MeasurableSpace.pi := + generateFrom_eq_pi (fun _ => generateFrom_measurableSet) fun _ => + isCountablySpanning_measurableSet + +end Finite diff --git a/Mathlib/Probability/Independence/Basic.lean b/Mathlib/Probability/Independence/Basic.lean index a7ef0fcd188d8..3bdcf8aaffe0c 100644 --- a/Mathlib/Probability/Independence/Basic.lean +++ b/Mathlib/Probability/Independence/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ import Mathlib.Probability.Independence.Kernel +import Mathlib.MeasureTheory.Measure.Prod /-! # Independence of sets of sets and measure spaces (σ-algebras) diff --git a/Mathlib/Probability/Independence/Kernel.lean b/Mathlib/Probability/Independence/Kernel.lean index c83e793c26c67..1b8fc5fb8bb20 100644 --- a/Mathlib/Probability/Independence/Kernel.lean +++ b/Mathlib/Probability/Independence/Kernel.lean @@ -3,10 +3,10 @@ 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.MeasureTheory.Constructions.Pi import Mathlib.Probability.ConditionalProbability import Mathlib.Probability.Kernel.Basic import Mathlib.Tactic.Peel +import Mathlib.MeasureTheory.MeasurableSpace.Pi /-! # Independence with respect to a kernel and a measure From cc3161575e8082c990d735af2763dd6c13708233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 7 Jan 2025 08:46:41 +0000 Subject: [PATCH 035/681] feat: initial segment commutes with `Iio` (#20503) --- Mathlib/Order/InitialSeg.lean | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Mathlib/Order/InitialSeg.lean b/Mathlib/Order/InitialSeg.lean index 9d83ed92d1c08..d00f90a854fe1 100644 --- a/Mathlib/Order/InitialSeg.lean +++ b/Mathlib/Order/InitialSeg.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro, Floris van Doorn, Violeta Hernández Palacios import Mathlib.Data.Sum.Order import Mathlib.Logic.Equiv.Set import Mathlib.Order.RelIso.Set +import Mathlib.Order.UpperLower.Basic import Mathlib.Order.WellFounded /-! @@ -670,6 +671,9 @@ alias ⟨_, map_isMin⟩ := isMin_apply_iff theorem map_bot [PartialOrder α] [OrderBot α] [OrderBot β] (f : α ≤i β) : f ⊥ = ⊥ := (map_isMin f isMin_bot).eq_bot +theorem image_Iio [PartialOrder α] (f : α ≤i β) (a : α) : f '' Set.Iio a = Set.Iio (f a) := + f.toOrderEmbedding.image_Iio f.isLowerSet_range a + theorem le_apply_iff [LinearOrder α] (f : α ≤i β) : b ≤ f a ↔ ∃ c ≤ a, f c = b := by constructor · intro h @@ -726,6 +730,9 @@ alias ⟨_, map_isMin⟩ := isMin_apply_iff theorem map_bot [PartialOrder α] [OrderBot α] [OrderBot β] (f : α Date: Tue, 7 Jan 2025 09:21:25 +0000 Subject: [PATCH 036/681] chore: don't import algebra in `Data.Finset.Basic` (#19779) --- Mathlib/Algebra/Order/Group/Finset.lean | 33 +++++++++++++++++++ Mathlib/Algebra/Order/Group/Multiset.lean | 9 ++++- Mathlib/Algebra/Polynomial/FieldDivision.lean | 1 + Mathlib/Data/Finset/Basic.lean | 25 +------------- Mathlib/Data/Finset/Card.lean | 4 --- Mathlib/Data/Finset/Defs.lean | 4 +-- Mathlib/Data/Finset/Disjoint.lean | 8 ++--- Mathlib/Data/Finset/Lattice/Lemmas.lean | 2 +- Mathlib/Data/Finsupp/Multiset.lean | 1 + Mathlib/Data/Multiset/Dedup.lean | 14 ++------ Mathlib/Data/Multiset/NatAntidiagonal.lean | 6 ++-- Mathlib/Data/Multiset/Nodup.lean | 5 +-- Mathlib/Data/Multiset/Range.lean | 5 +-- Mathlib/Data/Multiset/Sum.lean | 9 ++--- Mathlib/RingTheory/Radical.lean | 1 + 15 files changed, 69 insertions(+), 58 deletions(-) diff --git a/Mathlib/Algebra/Order/Group/Finset.lean b/Mathlib/Algebra/Order/Group/Finset.lean index e08078aa0b808..e3f518734c79d 100644 --- a/Mathlib/Algebra/Order/Group/Finset.lean +++ b/Mathlib/Algebra/Order/Group/Finset.lean @@ -14,8 +14,41 @@ import Mathlib.Data.Finset.Lattice.Fold # `Finset.sup` in a group -/ +open scoped Finset + assert_not_exists MonoidWithZero +namespace Multiset +variable {α : Type*} [DecidableEq α] + +@[simp] lemma toFinset_nsmul (s : Multiset α) : ∀ n ≠ 0, (n • s).toFinset = s.toFinset + | 0, h => by contradiction + | n + 1, _ => by + by_cases h : n = 0 + · rw [h, zero_add, one_nsmul] + · rw [add_nsmul, toFinset_add, one_nsmul, toFinset_nsmul s n h, Finset.union_idempotent] + +lemma toFinset_eq_singleton_iff (s : Multiset α) (a : α) : + s.toFinset = {a} ↔ card s ≠ 0 ∧ s = card s • {a} := by + refine ⟨fun H ↦ ⟨fun h ↦ ?_, ext' fun x ↦ ?_⟩, fun H ↦ ?_⟩ + · rw [card_eq_zero.1 h, toFinset_zero] at H + exact Finset.singleton_ne_empty _ H.symm + · rw [count_nsmul, count_singleton] + by_cases hx : x = a + · simp_rw [hx, ite_true, mul_one, count_eq_card] + intro y hy + rw [← mem_toFinset, H, Finset.mem_singleton] at hy + exact hy.symm + have hx' : x ∉ s := fun h' ↦ hx <| by rwa [← mem_toFinset, H, Finset.mem_singleton] at h' + simp_rw [count_eq_zero_of_not_mem hx', hx, ite_false, Nat.mul_zero] + simpa only [toFinset_nsmul _ _ H.1, toFinset_singleton] using congr($(H.2).toFinset) + +lemma toFinset_card_eq_one_iff (s : Multiset α) : + #s.toFinset = 1 ↔ Multiset.card s ≠ 0 ∧ ∃ a : α, s = Multiset.card s • {a} := by + simp_rw [Finset.card_eq_one, Multiset.toFinset_eq_singleton_iff, exists_and_left] + +end Multiset + namespace Finset variable {ι κ M G : Type*} diff --git a/Mathlib/Algebra/Order/Group/Multiset.lean b/Mathlib/Algebra/Order/Group/Multiset.lean index 7fb63d8cd37e0..970a962cfde9c 100644 --- a/Mathlib/Algebra/Order/Group/Multiset.lean +++ b/Mathlib/Algebra/Order/Group/Multiset.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Algebra.Order.Monoid.Unbundled.ExistsOfLE import Mathlib.Algebra.Order.Sub.Defs -import Mathlib.Data.Multiset.Basic +import Mathlib.Data.Multiset.Dedup /-! # Multisets form an ordered monoid @@ -149,6 +149,13 @@ def countPAddMonoidHom : Multiset α →+ ℕ where end +@[simp] lemma dedup_nsmul [DecidableEq α] {s : Multiset α} {n : ℕ} (hn : n ≠ 0) : + (n • s).dedup = s.dedup := by ext a; by_cases h : a ∈ s <;> simp [h, hn] + +lemma Nodup.le_nsmul_iff_le {s t : Multiset α} {n : ℕ} (h : s.Nodup) (hn : n ≠ 0) : + s ≤ n • t ↔ s ≤ t := by + classical simp [← h.le_dedup_iff_le, Iff.comm, ← h.le_dedup_iff_le, hn] + /-! ### Multiplicity of an element -/ section diff --git a/Mathlib/Algebra/Polynomial/FieldDivision.lean b/Mathlib/Algebra/Polynomial/FieldDivision.lean index 36d71e8b2b9ee..07d250cccea6d 100644 --- a/Mathlib/Algebra/Polynomial/FieldDivision.lean +++ b/Mathlib/Algebra/Polynomial/FieldDivision.lean @@ -3,6 +3,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, Kim Morrison, Jens Wagemaker -/ +import Mathlib.Algebra.Order.Group.Finset import Mathlib.Algebra.Polynomial.Derivative import Mathlib.Algebra.Polynomial.Eval.SMul import Mathlib.Algebra.Polynomial.Roots diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index b6901aef2d20c..30dcc372ee2cd 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -48,7 +48,7 @@ assert_not_exists Multiset.powerset assert_not_exists CompleteLattice -assert_not_exists OrderedCommMonoid +assert_not_exists Monoid open Multiset Subtype Function @@ -532,29 +532,6 @@ variable [DecidableEq α] {s t : Multiset α} theorem toFinset_add (s t : Multiset α) : toFinset (s + t) = toFinset s ∪ toFinset t := Finset.ext <| by simp -@[simp] -theorem toFinset_nsmul (s : Multiset α) : ∀ n ≠ 0, (n • s).toFinset = s.toFinset - | 0, h => by contradiction - | n + 1, _ => by - by_cases h : n = 0 - · rw [h, zero_add, one_nsmul] - · rw [add_nsmul, toFinset_add, one_nsmul, toFinset_nsmul s n h, Finset.union_idempotent] - -theorem toFinset_eq_singleton_iff (s : Multiset α) (a : α) : - s.toFinset = {a} ↔ card s ≠ 0 ∧ s = card s • {a} := by - refine ⟨fun H ↦ ⟨fun h ↦ ?_, ext' fun x ↦ ?_⟩, fun H ↦ ?_⟩ - · rw [card_eq_zero.1 h, toFinset_zero] at H - exact Finset.singleton_ne_empty _ H.symm - · rw [count_nsmul, count_singleton] - by_cases hx : x = a - · simp_rw [hx, ite_true, mul_one, count_eq_card] - intro y hy - rw [← mem_toFinset, H, Finset.mem_singleton] at hy - exact hy.symm - have hx' : x ∉ s := fun h' ↦ hx <| by rwa [← mem_toFinset, H, Finset.mem_singleton] at h' - simp_rw [count_eq_zero_of_not_mem hx', hx, ite_false, Nat.mul_zero] - simpa only [toFinset_nsmul _ _ H.1, toFinset_singleton] using congr($(H.2).toFinset) - @[simp] theorem toFinset_inter (s t : Multiset α) : toFinset (s ∩ t) = toFinset s ∩ toFinset t := Finset.ext <| by simp diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index 3d203a0107b42..8c8e3dba2f006 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -610,10 +610,6 @@ theorem card_eq_one : #s = 1 ↔ ∃ a, s = {a} := by cases s simp only [Multiset.card_eq_one, Finset.card, ← val_inj, singleton_val] -theorem _root_.Multiset.toFinset_card_eq_one_iff [DecidableEq α] (s : Multiset α) : - #s.toFinset = 1 ↔ Multiset.card s ≠ 0 ∧ ∃ a : α, s = Multiset.card s • {a} := by - simp_rw [card_eq_one, Multiset.toFinset_eq_singleton_iff, exists_and_left] - theorem exists_eq_insert_iff [DecidableEq α] {s t : Finset α} : (∃ a ∉ s, insert a s = t) ↔ s ⊆ t ∧ #s + 1 = #t := by constructor diff --git a/Mathlib/Data/Finset/Defs.lean b/Mathlib/Data/Finset/Defs.lean index ff2e09b64a5eb..e63e94579aaed 100644 --- a/Mathlib/Data/Finset/Defs.lean +++ b/Mathlib/Data/Finset/Defs.lean @@ -63,7 +63,7 @@ assert_not_exists DirectedSystem assert_not_exists CompleteLattice -assert_not_exists OrderedCommMonoid +assert_not_exists Monoid open Multiset Subtype Function @@ -353,7 +353,7 @@ theorem sizeOf_lt_sizeOf_of_mem [SizeOf α] {x : α} {s : Finset α} (hx : x ∈ SizeOf.sizeOf x < SizeOf.sizeOf s := by cases s dsimp [SizeOf.sizeOf, SizeOf.sizeOf, Multiset.sizeOf] - rw [add_comm] + rw [Nat.add_comm] refine lt_trans ?_ (Nat.lt_succ_self _) exact Multiset.sizeOf_lt_sizeOf_of_mem hx diff --git a/Mathlib/Data/Finset/Disjoint.lean b/Mathlib/Data/Finset/Disjoint.lean index fdb75054aba95..4ef7defc5e0a6 100644 --- a/Mathlib/Data/Finset/Disjoint.lean +++ b/Mathlib/Data/Finset/Disjoint.lean @@ -27,7 +27,7 @@ assert_not_exists Multiset.powerset assert_not_exists CompleteLattice -assert_not_exists OrderedCommMonoid +assert_not_exists Monoid open Multiset Subtype Function @@ -134,17 +134,17 @@ theorem coe_disjUnion {s t : Finset α} (h : Disjoint s t) : theorem disjUnion_comm (s t : Finset α) (h : Disjoint s t) : disjUnion s t h = disjUnion t s h.symm := - eq_of_veq <| add_comm _ _ + eq_of_veq <| Multiset.add_comm _ _ @[simp] theorem empty_disjUnion (t : Finset α) (h : Disjoint ∅ t := disjoint_bot_left) : disjUnion ∅ t h = t := - eq_of_veq <| zero_add _ + eq_of_veq <| Multiset.zero_add _ @[simp] theorem disjUnion_empty (s : Finset α) (h : Disjoint s ∅ := disjoint_bot_right) : disjUnion s ∅ h = s := - eq_of_veq <| add_zero _ + eq_of_veq <| Multiset.add_zero _ theorem singleton_disjUnion (a : α) (t : Finset α) (h : Disjoint {a} t) : disjUnion {a} t h = cons a t (disjoint_singleton_left.mp h) := diff --git a/Mathlib/Data/Finset/Lattice/Lemmas.lean b/Mathlib/Data/Finset/Lattice/Lemmas.lean index c5783884b4b5a..32963dd45c201 100644 --- a/Mathlib/Data/Finset/Lattice/Lemmas.lean +++ b/Mathlib/Data/Finset/Lattice/Lemmas.lean @@ -25,7 +25,7 @@ assert_not_exists Multiset.powerset assert_not_exists CompleteLattice -assert_not_exists OrderedCommMonoid +assert_not_exists Monoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finsupp/Multiset.lean b/Mathlib/Data/Finsupp/Multiset.lean index df6435246cdea..0ff33f764dd1d 100644 --- a/Mathlib/Data/Finsupp/Multiset.lean +++ b/Mathlib/Data/Finsupp/Multiset.lean @@ -3,6 +3,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 -/ +import Mathlib.Algebra.Order.Group.Finset import Mathlib.Data.Finsupp.Basic import Mathlib.Data.Finsupp.Order diff --git a/Mathlib/Data/Multiset/Dedup.lean b/Mathlib/Data/Multiset/Dedup.lean index 7e580eb8e459b..07c9eabf1192c 100644 --- a/Mathlib/Data/Multiset/Dedup.lean +++ b/Mathlib/Data/Multiset/Dedup.lean @@ -10,6 +10,7 @@ import Mathlib.Data.Multiset.Nodup # Erasing duplicates in a multiset. -/ +assert_not_exists Monoid namespace Multiset @@ -104,11 +105,6 @@ theorem dedup_map_dedup_eq [DecidableEq β] (f : α → β) (s : Multiset α) : dedup (map f (dedup s)) = dedup (map f s) := by simp [dedup_ext] -@[simp] -theorem dedup_nsmul {s : Multiset α} {n : ℕ} (h0 : n ≠ 0) : (n • s).dedup = s.dedup := by - ext a - by_cases h : a ∈ s <;> simp [h, h0] - theorem Nodup.le_dedup_iff_le {s t : Multiset α} (hno : s.Nodup) : s ≤ t.dedup ↔ s ≤ t := by simp [le_dedup, hno] @@ -119,7 +115,7 @@ theorem Subset.dedup_add_right {s t : Multiset α} (h : s ⊆ t) : theorem Subset.dedup_add_left {s t : Multiset α} (h : t ⊆ s) : dedup (s + t) = dedup s := by - rw [add_comm, Subset.dedup_add_right h] + rw [s.add_comm, Subset.dedup_add_right h] theorem Disjoint.dedup_add {s t : Multiset α} (h : Disjoint s t) : dedup (s + t) = dedup s + dedup t := by @@ -132,9 +128,3 @@ theorem _root_.List.Subset.dedup_append_left {s t : List α} (h : t ⊆ s) : rw [← coe_eq_coe, ← coe_dedup, ← coe_add, Subset.dedup_add_left h, coe_dedup] end Multiset - -theorem Multiset.Nodup.le_nsmul_iff_le {α : Type*} {s t : Multiset α} {n : ℕ} (h : s.Nodup) - (hn : n ≠ 0) : s ≤ n • t ↔ s ≤ t := by - classical - rw [← h.le_dedup_iff_le, Iff.comm, ← h.le_dedup_iff_le] - simp [hn] diff --git a/Mathlib/Data/Multiset/NatAntidiagonal.lean b/Mathlib/Data/Multiset/NatAntidiagonal.lean index b9d75740e9a1f..55e2353bf8752 100644 --- a/Mathlib/Data/Multiset/NatAntidiagonal.lean +++ b/Mathlib/Data/Multiset/NatAntidiagonal.lean @@ -19,6 +19,8 @@ This refines file `Data.List.NatAntidiagonal` and is further refined by file `Data.Finset.NatAntidiagonal`. -/ +assert_not_exists Monoid + namespace Multiset namespace Nat @@ -55,8 +57,8 @@ theorem antidiagonal_succ {n : ℕ} : theorem antidiagonal_succ' {n : ℕ} : antidiagonal (n + 1) = (n + 1, 0) ::ₘ (antidiagonal n).map (Prod.map id Nat.succ) := by - rw [antidiagonal, List.Nat.antidiagonal_succ', ← coe_add, add_comm, antidiagonal, map_coe, - coe_add, List.singleton_append, cons_coe] + rw [antidiagonal, List.Nat.antidiagonal_succ', ← coe_add, Multiset.add_comm, antidiagonal, + map_coe, coe_add, List.singleton_append, cons_coe] theorem antidiagonal_succ_succ' {n : ℕ} : antidiagonal (n + 2) = diff --git a/Mathlib/Data/Multiset/Nodup.lean b/Mathlib/Data/Multiset/Nodup.lean index 87bbfbd63a93a..66e5cd4680dd3 100644 --- a/Mathlib/Data/Multiset/Nodup.lean +++ b/Mathlib/Data/Multiset/Nodup.lean @@ -10,6 +10,7 @@ import Mathlib.Data.List.Pairwise # The `Nodup` predicate for multisets without duplicate elements. -/ +assert_not_exists Monoid namespace Multiset @@ -62,7 +63,7 @@ theorem nodup_iff_ne_cons_cons {s : Multiset α} : s.Nodup ↔ ∀ a t, s ≠ a nodup_iff_le.trans ⟨fun h a _ s_eq => h a (s_eq.symm ▸ cons_le_cons a (cons_le_cons a (zero_le _))), fun h a le => let ⟨t, s_eq⟩ := le_iff_exists_add.mp le - h a t (by rwa [cons_add, cons_add, zero_add] at s_eq)⟩ + h a t (by rwa [cons_add, cons_add, Multiset.zero_add] at s_eq)⟩ theorem nodup_iff_count_le_one [DecidableEq α] {s : Multiset α} : Nodup s ↔ ∀ a, count a s ≤ 1 := Quot.induction_on s fun _l => by @@ -193,7 +194,7 @@ theorem mem_sub_of_nodup [DecidableEq α] {a : α} {s t : Multiset α} (d : Nodu refine count_eq_zero.1 ?_ h rw [count_sub a s t, Nat.sub_eq_zero_iff_le] exact le_trans (nodup_iff_count_le_one.1 d _) (count_pos.2 h')⟩, - fun ⟨h₁, h₂⟩ => Or.resolve_right (mem_add.1 <| mem_of_le le_tsub_add h₁) h₂⟩ + fun ⟨h₁, h₂⟩ => Or.resolve_right (mem_add.1 <| mem_of_le Multiset.le_sub_add h₁) h₂⟩ theorem map_eq_map_of_bij_of_nodup (f : α → γ) (g : β → γ) {s : Multiset α} {t : Multiset β} (hs : s.Nodup) (ht : t.Nodup) (i : ∀ a ∈ s, β) (hi : ∀ a ha, i a ha ∈ t) diff --git a/Mathlib/Data/Multiset/Range.lean b/Mathlib/Data/Multiset/Range.lean index 82be6f025e6de..61399e9389712 100644 --- a/Mathlib/Data/Multiset/Range.lean +++ b/Mathlib/Data/Multiset/Range.lean @@ -3,10 +3,11 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Order.Group.Multiset +import Mathlib.Data.Multiset.Basic /-! # `Multiset.range n` gives `{0, 1, ..., n-1}` as a multiset. -/ +assert_not_exists Monoid open List Nat @@ -27,7 +28,7 @@ theorem range_zero : range 0 = 0 := @[simp] theorem range_succ (n : ℕ) : range (succ n) = n ::ₘ range n := by - rw [range, List.range_succ, ← coe_add, add_comm]; rfl + rw [range, List.range_succ, ← coe_add, Multiset.add_comm]; rfl @[simp] theorem card_range (n : ℕ) : card (range n) = n := diff --git a/Mathlib/Data/Multiset/Sum.lean b/Mathlib/Data/Multiset/Sum.lean index 0dd8540893604..66512fa587909 100644 --- a/Mathlib/Data/Multiset/Sum.lean +++ b/Mathlib/Data/Multiset/Sum.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Data.Multiset.Nodup /-! @@ -29,11 +30,11 @@ def disjSum : Multiset (α ⊕ β) := @[simp] theorem zero_disjSum : (0 : Multiset α).disjSum t = t.map inr := - zero_add _ + Multiset.zero_add _ @[simp] theorem disjSum_zero : s.disjSum (0 : Multiset β) = s.map inl := - add_zero _ + Multiset.add_zero _ @[simp] theorem card_disjSum : Multiset.card (s.disjSum t) = Multiset.card s + Multiset.card t := by @@ -64,11 +65,11 @@ theorem disjSum_mono (hs : s₁ ≤ s₂) (ht : t₁ ≤ t₂) : s₁.disjSum t add_le_add (map_le_map hs) (map_le_map ht) theorem disjSum_mono_left (t : Multiset β) : Monotone fun s : Multiset α => s.disjSum t := - fun _ _ hs => add_le_add_right (map_le_map hs) _ + fun _ _ hs => Multiset.add_le_add_right (map_le_map hs) theorem disjSum_mono_right (s : Multiset α) : Monotone (s.disjSum : Multiset β → Multiset (α ⊕ β)) := fun _ _ ht => - add_le_add_left (map_le_map ht) _ + Multiset.add_le_add_left (map_le_map ht) theorem disjSum_lt_disjSum_of_lt_of_le (hs : s₁ < s₂) (ht : t₁ ≤ t₂) : s₁.disjSum t₁ < s₂.disjSum t₂ := diff --git a/Mathlib/RingTheory/Radical.lean b/Mathlib/RingTheory/Radical.lean index 8b60b67c3beb9..a213f7b39bfec 100644 --- a/Mathlib/RingTheory/Radical.lean +++ b/Mathlib/RingTheory/Radical.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jineon Baek, Seewoo Lee -/ import Mathlib.Algebra.EuclideanDomain.Basic +import Mathlib.Algebra.Order.Group.Finset import Mathlib.RingTheory.Coprime.Basic import Mathlib.RingTheory.UniqueFactorizationDomain.NormalizedFactors From 9ffea5b81fd24f8491e7304d32e192dc06a19088 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Tue, 7 Jan 2025 09:21:26 +0000 Subject: [PATCH 037/681] chore(Order/SuccPred/LinearLocallyFinite): change data-creating instances to defs (#20235) Co-authored-by: Yury G. Kudryashov Co-authored-by: David Loeffler --- .../Order/SuccPred/LinearLocallyFinite.lean | 27 ++++++++++++++----- Mathlib/Topology/Instances/Discrete.lean | 7 +++++ Mathlib/Topology/Instances/Int.lean | 1 - 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean index c2dd78d6d45f1..38669807baa70 100644 --- a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean +++ b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean @@ -30,7 +30,7 @@ Furthermore, we show that there is an `OrderIso` between such an order and a sub ## Main results -Instances about linear locally finite orders: +Results about linear locally finite orders: * `LinearLocallyFiniteOrder.SuccOrder`: a linear locally finite order has a successor function. * `LinearLocallyFiniteOrder.PredOrder`: a linear locally finite order has a predecessor function. @@ -140,16 +140,25 @@ theorem le_of_lt_succFn (j i : ι) (hij : j < succFn i) : j ≤ i := by rw [mem_lowerBounds] at hk_lb exact not_lt.mp fun hi_lt_j ↦ not_le.mpr hk (hk_lb j hi_lt_j) -noncomputable instance (priority := 100) [LocallyFiniteOrder ι] : SuccOrder ι where +variable (ι) in +/-- A locally finite order is a `SuccOrder`. +This is not an instance, because its `succ` field conflicts with computable `SuccOrder` structures +on `ℕ` and `ℤ`. -/ +noncomputable def succOrder [LocallyFiniteOrder ι] : SuccOrder ι where succ := succFn le_succ := le_succFn max_of_succ_le h := isMax_of_succFn_le _ h succ_le_of_lt h := succFn_le_of_lt _ _ h -noncomputable instance (priority := 100) [LocallyFiniteOrder ι] : PredOrder ι := +variable (ι) in +/-- A locally finite order is a `PredOrder`. +This is not an instance, because its `succ` field conflicts with computable `PredOrder` structures +on `ℕ` and `ℤ`. -/ +noncomputable def predOrder [LocallyFiniteOrder ι] : PredOrder ι := + letI := succOrder (ι := ιᵒᵈ) inferInstanceAs (PredOrder ιᵒᵈᵒᵈ) -instance (priority := 100) [LocallyFiniteOrder ι] : IsSuccArchimedean ι where +instance (priority := 100) [LocallyFiniteOrder ι] [SuccOrder ι] : IsSuccArchimedean ι where exists_succ_iterate_of_le := by intro i j hij rw [le_iff_lt_or_eq] at hij @@ -178,8 +187,8 @@ instance (priority := 100) [LocallyFiniteOrder ι] : IsSuccArchimedean ι where have h_max : IsMax (succ^[n] i) := isMax_iterate_succ_of_eq_of_ne h_eq hnm.ne exact not_le.mpr (h_lt n) (h_max (h_lt n).le) -instance (priority := 100) [LocallyFiniteOrder ι] : IsPredArchimedean ι := - inferInstance +instance (priority := 100) [LocallyFiniteOrder ι] [PredOrder ι] : IsPredArchimedean ι := + inferInstanceAs (IsPredArchimedean ιᵒᵈᵒᵈ) end LinearLocallyFiniteOrder @@ -428,3 +437,9 @@ def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] : rw [← @toZ_le_iff ι _ _ _ _ ⊥, Int.toNat_of_nonneg (toZ_nonneg bot_le)] end OrderIso + +instance (priority := 100) Countable.of_linearOrder_locallyFiniteOrder [LocallyFiniteOrder ι] : + Countable ι := + have := LinearLocallyFiniteOrder.succOrder ι + have := LinearLocallyFiniteOrder.predOrder ι + countable_of_linear_succ_pred_arch diff --git a/Mathlib/Topology/Instances/Discrete.lean b/Mathlib/Topology/Instances/Discrete.lean index d798a8a6591b8..4acd770481069 100644 --- a/Mathlib/Topology/Instances/Discrete.lean +++ b/Mathlib/Topology/Instances/Discrete.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ import Mathlib.Topology.Order.Basic +import Mathlib.Order.SuccPred.LinearLocallyFinite /-! # Instances related to the discrete topology @@ -58,3 +59,9 @@ alias discreteTopology_iff_orderTopology_of_pred_succ' := instance OrderTopology.of_discreteTopology [LinearOrder α] [PredOrder α] [SuccOrder α] [DiscreteTopology α] : OrderTopology α := discreteTopology_iff_orderTopology_of_pred_succ.mp ‹_› + +instance OrderTopology.of_linearLocallyFinite + [LinearOrder α] [LocallyFiniteOrder α] [DiscreteTopology α] : OrderTopology α := + haveI := LinearLocallyFiniteOrder.succOrder α + haveI := LinearLocallyFiniteOrder.predOrder α + inferInstance diff --git a/Mathlib/Topology/Instances/Int.lean b/Mathlib/Topology/Instances/Int.lean index ba41c15cda783..16ad9a3d16676 100644 --- a/Mathlib/Topology/Instances/Int.lean +++ b/Mathlib/Topology/Instances/Int.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Data.Int.Interval -import Mathlib.Data.Int.SuccPred import Mathlib.Data.Int.ConditionallyCompleteOrder import Mathlib.Topology.Instances.Discrete import Mathlib.Topology.MetricSpace.Bounded From 9f47fc531129f08955f2250ac59c65ff8830507b Mon Sep 17 00:00:00 2001 From: smorel394 Date: Tue, 7 Jan 2025 09:21:28 +0000 Subject: [PATCH 038/681] feat(CategoryTheory/Triangulated/Adjunction): the right adjoint of a triangulated functor is triangulated (#20255) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a functor `F : C ⥤ D` between pretriangulated categories is triangulated, and if we have an adjunction `F ⊣ G`, then `G` is also a triangulated functor. We deduce that, if `E : C ≌ D` is an equivalence of pretriangulated categories, then `E.functor` is triangulated if and only if `E.inverse` is triangulated. TODO: The case of left adjoints. - [x] depends on: #20083 [the adjoint of an additive functor is additive] - [ ] depends on: #20337 Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- Mathlib.lean | 1 + .../Triangulated/Adjunction.lean | 204 ++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 Mathlib/CategoryTheory/Triangulated/Adjunction.lean diff --git a/Mathlib.lean b/Mathlib.lean index 280f1d1e523eb..29d5ad6bf01f8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2213,6 +2213,7 @@ import Mathlib.CategoryTheory.Subterminal import Mathlib.CategoryTheory.Sums.Associator import Mathlib.CategoryTheory.Sums.Basic import Mathlib.CategoryTheory.Thin +import Mathlib.CategoryTheory.Triangulated.Adjunction import Mathlib.CategoryTheory.Triangulated.Basic import Mathlib.CategoryTheory.Triangulated.Functor import Mathlib.CategoryTheory.Triangulated.HomologicalFunctor diff --git a/Mathlib/CategoryTheory/Triangulated/Adjunction.lean b/Mathlib/CategoryTheory/Triangulated/Adjunction.lean new file mode 100644 index 0000000000000..2308c4936e127 --- /dev/null +++ b/Mathlib/CategoryTheory/Triangulated/Adjunction.lean @@ -0,0 +1,204 @@ +/- +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.CategoryTheory.Triangulated.Functor +import Mathlib.CategoryTheory.Shift.Adjunction +import Mathlib.CategoryTheory.Adjunction.Additive + +/-! +# The adjoint functor is triangulated + +If a functor `F : C ⥤ D` between pretriangulated categories is triangulated, and if we +have an adjunction `F ⊣ G`, then `G` is also a triangulated functor. + +We deduce that, if `E : C ≌ D` is an equivalence of pretriangulated categories, then +`E.functor` is triangulated if and only if `E.inverse` is triangulated. + +TODO: The case of left adjoints. +-/ + +namespace CategoryTheory + +open Category Limits Preadditive Pretriangulated Adjunction + +variable {C D : Type*} [Category C] [Category D] [HasZeroObject C] [HasZeroObject D] + [Preadditive C] [Preadditive D] [HasShift C ℤ] [HasShift D ℤ] + [∀ (n : ℤ), (shiftFunctor C n).Additive] [∀ (n : ℤ), (shiftFunctor D n).Additive] + [Pretriangulated C] [Pretriangulated D] + +namespace Adjunction + +variable {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G) [F.CommShift ℤ] [G.CommShift ℤ] + [adj.CommShift ℤ] + +include adj in +/-- +The right adjoint of a triangulated functor is triangulated. +-/ +lemma isTriangulated_rightAdjoint [F.IsTriangulated] : G.IsTriangulated where + map_distinguished T hT := by + have : G.Additive := adj.right_adjoint_additive + obtain ⟨Z, f, g, mem⟩ := distinguished_cocone_triangle (G.map T.mor₁) + obtain ⟨h, ⟨h₁, h₂⟩⟩ := complete_distinguished_triangle_morphism _ _ + (F.map_distinguished _ mem) hT (adj.counit.app T.obj₁) (adj.counit.app T.obj₂) (by simp) + dsimp at h h₁ h₂ ⊢ + have h₁' : f ≫ adj.unit.app Z ≫ G.map h = G.map T.mor₂ := by + simpa [homEquiv_apply] using DFunLike.congr_arg (adj.homEquiv _ _) h₁ + have h₂' : g ≫ (G.commShiftIso (1 : ℤ)).inv.app T.obj₁ = + adj.homEquiv _ _ h ≫ G.map T.mor₃ := by + apply (adj.homEquiv _ _).symm.injective + simp only [Functor.comp_obj, homEquiv_counit, Functor.id_obj, Functor.map_comp, assoc, + homEquiv_unit, counit_naturality, counit_naturality_assoc, left_triangle_components_assoc, + ← h₂, adj.shift_counit_app, Iso.hom_inv_id_app_assoc] + rw [assoc] at h₂ + have : Mono (adj.homEquiv _ _ h) := by + rw [mono_iff_cancel_zero] + intro _ φ hφ + obtain ⟨ψ, rfl⟩ := Triangle.coyoneda_exact₃ _ mem φ (by + dsimp + simp only [homEquiv_unit, Functor.comp_obj] at hφ + rw [← cancel_mono ((G.commShiftIso (1 : ℤ)).inv.app T.obj₁), assoc, h₂', zero_comp, + homEquiv_unit, assoc, reassoc_of% hφ, zero_comp]) + dsimp at ψ hφ ⊢ + obtain ⟨α, hα⟩ := T.coyoneda_exact₂ hT ((adj.homEquiv _ _).symm ψ) + ((adj.homEquiv _ _).injective (by simpa [homEquiv_counit, homEquiv_unit, ← h₁'] using hφ)) + have eq := DFunLike.congr_arg (adj.homEquiv _ _ ) hα + simp only [homEquiv_counit, Functor.id_obj, homEquiv_unit, comp_id, + Functor.map_comp, unit_naturality_assoc, right_triangle_components] at eq + have eq' := comp_distTriang_mor_zero₁₂ _ mem + dsimp at eq eq' + rw [eq, assoc, assoc, eq', comp_zero, comp_zero] + have := isIso_of_yoneda_map_bijective (adj.homEquiv _ _ h) (fun Y => by + constructor + · intro φ₁ φ₂ hφ + rw [← cancel_mono (adj.homEquiv _ _ h)] + exact hφ + · intro φ + obtain ⟨ψ, hψ⟩ := Triangle.coyoneda_exact₁ _ mem (φ ≫ G.map T.mor₃ ≫ + (G.commShiftIso (1 : ℤ)).hom.app T.obj₁) (by + dsimp + rw [assoc, assoc, ← G.commShiftIso_hom_naturality, ← G.map_comp_assoc, + comp_distTriang_mor_zero₃₁ _ hT, G.map_zero, zero_comp, comp_zero]) + dsimp at ψ hψ + obtain ⟨α, hα⟩ : ∃ α, α = φ - ψ ≫ adj.homEquiv _ _ h := ⟨_, rfl⟩ + have hα₀ : α ≫ G.map T.mor₃ = 0 := by + rw [hα, sub_comp, ← cancel_mono ((Functor.commShiftIso G (1 : ℤ)).hom.app T.obj₁), + assoc, sub_comp, assoc, assoc, hψ, zero_comp, sub_eq_zero, + ← cancel_mono ((Functor.commShiftIso G (1 : ℤ)).inv.app T.obj₁), assoc, + assoc, assoc, assoc, h₂', Iso.hom_inv_id_app, comp_id] + suffices ∃ (β : Y ⟶ Z), β ≫ adj.homEquiv _ _ h = α by + obtain ⟨β, hβ⟩ := this + refine ⟨ψ + β, ?_⟩ + dsimp + rw [add_comp, hβ, hα, add_sub_cancel] + obtain ⟨β, hβ⟩ := T.coyoneda_exact₃ hT ((adj.homEquiv _ _).symm α) + ((adj.homEquiv _ _).injective (by simpa [homEquiv_unit, homEquiv_counit] using hα₀)) + refine ⟨adj.homEquiv _ _ β ≫ f, ?_⟩ + simpa [homEquiv_unit, h₁'] using congr_arg (adj.homEquiv _ _).toFun hβ.symm) + refine isomorphic_distinguished _ mem _ (Iso.symm ?_) + refine Triangle.isoMk _ _ (Iso.refl _) (Iso.refl _) (asIso (adj.homEquiv Z T.obj₃ h)) ?_ ?_ ?_ + · dsimp + simp + · apply (adj.homEquiv _ _).symm.injective + dsimp + simp only [homEquiv_unit, homEquiv_counit, Functor.map_comp, assoc, + counit_naturality, left_triangle_components_assoc, h₁, id_comp] + · dsimp + rw [Functor.map_id, comp_id, homEquiv_unit, assoc, ← G.map_comp_assoc, ← h₂, + Functor.map_comp, Functor.map_comp, assoc, unit_naturality_assoc, assoc, + Functor.commShiftIso_hom_naturality, ← adj.shift_unit_app_assoc, + ← Functor.map_comp, right_triangle_components, Functor.map_id, comp_id] + +/-- +We say that an adjunction `F ⊣ G` is triangulated if it is compatible with the `CommShift` +structures on `F` and `G` (in the sense of `Adjunction.CommShift`) and if both `F` and `G` +are triangulated functors. +-/ +class IsTriangulated : Prop where + commShift : adj.CommShift ℤ := by infer_instance + leftAdjoint_isTriangulated : F.IsTriangulated := by infer_instance + rightAdjoint_isTriangulated : G.IsTriangulated := by infer_instance + +namespace IsTriangulated + +attribute [instance] commShift leftAdjoint_isTriangulated rightAdjoint_isTriangulated + +/-- Constructor for `Adjunction.IsTriangulated`. +-/ +lemma mk' [F.IsTriangulated] : adj.IsTriangulated where + rightAdjoint_isTriangulated := adj.isTriangulated_rightAdjoint + +/-- The identity adjunction is triangulated. +-/ +instance id : (Adjunction.id (C := C)).IsTriangulated where + +variable {E : Type*} [Category E] {F' : D ⥤ E} {G' : E ⥤ D} (adj' : F' ⊣ G') [HasZeroObject E] + [Preadditive E] [HasShift E ℤ] [∀ (n : ℤ), (shiftFunctor E n).Additive] [Pretriangulated E] + [F'.CommShift ℤ] [G'.CommShift ℤ] [adj'.CommShift ℤ] + +/-- A composition of triangulated adjunctions is triangulated. +-/ +instance comp [adj.IsTriangulated] [adj'.IsTriangulated] : (adj.comp adj').IsTriangulated where + +end IsTriangulated + +end Adjunction + +namespace Equivalence + +variable (E : C ≌ D) [E.functor.CommShift ℤ] [E.inverse.CommShift ℤ] [E.CommShift ℤ] + +/-- +We say that an equivalence of categories `E` is triangulated if both `E.functor` and +`E.inverse` are triangulated functors. +-/ +abbrev IsTriangulated : Prop := E.toAdjunction.IsTriangulated + +namespace IsTriangulated + +instance [E.IsTriangulated] : E.functor.IsTriangulated := inferInstance +instance [E.IsTriangulated] : E.inverse.IsTriangulated := inferInstance + +instance [h : E.functor.IsTriangulated] : E.symm.inverse.IsTriangulated := h +instance [h : E.inverse.IsTriangulated] : E.symm.functor.IsTriangulated := h + + +/-- Constructor for `Equivalence.IsTriangulated`. -/ +lemma mk' (h : E.functor.IsTriangulated) : E.IsTriangulated where + rightAdjoint_isTriangulated := E.toAdjunction.isTriangulated_rightAdjoint + +/-- Constructor for `Equivalence.IsTriangulated`. -/ +lemma mk'' (h : E.inverse.IsTriangulated) : E.IsTriangulated where + leftAdjoint_isTriangulated := (mk' E.symm h).rightAdjoint_isTriangulated + +/-- +The identity equivalence is triangulated. +-/ +instance refl : (Equivalence.refl (C := C)).IsTriangulated := by + dsimp [Equivalence.IsTriangulated] + rw [refl_toAdjunction] + infer_instance + +/-- If the equivalence `E` is triangulated, so is the equivalence `E.symm`. +-/ +instance symm [E.IsTriangulated] : E.symm.IsTriangulated where + +variable {D' : Type*} [Category D'] [HasZeroObject D'] [Preadditive D'] [HasShift D' ℤ] + [∀ (n : ℤ), (shiftFunctor D' n).Additive] [Pretriangulated D'] {E' : D ≌ D'} + [E'.functor.CommShift ℤ] [E'.inverse.CommShift ℤ] [E'.CommShift ℤ] + +/-- +If equivalences `E : C ≌ D` and `E' : D ≌ F` are triangulated, so is `E.trans E'`. +-/ +instance trans [E.IsTriangulated] [E'.IsTriangulated] : (E.trans E').IsTriangulated := by + dsimp [Equivalence.IsTriangulated] + rw [trans_toAdjunction] + infer_instance + +end IsTriangulated + +end Equivalence + +end CategoryTheory From 1a9143ba4b6d0ecaf315b8adcc2b2443b0c5aa44 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Tue, 7 Jan 2025 09:21:29 +0000 Subject: [PATCH 039/681] chore(*): replace `no_index (ofNat n)` with `ofNat(n)` everywhere (#20521) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR was made by searching for `no_index.*ofNat` and replacing all of the relevant occurrences with `ofNat(n)`. This is a rather naïve approach, but at least puts everything back in the same notation for easier applying and reviewing of later fixes. --- Mathlib/Algebra/AddConstMap/Basic.lean | 4 +-- Mathlib/Algebra/CharZero/Defs.lean | 10 +++--- Mathlib/Algebra/DirectSum/Internal.lean | 2 +- Mathlib/Algebra/Module/LinearMap/End.lean | 2 +- Mathlib/Algebra/Order/SuccPred/WithBot.lean | 2 +- Mathlib/Algebra/Polynomial/Derivative.lean | 2 +- Mathlib/Algebra/Polynomial/Eval/Defs.lean | 14 +++----- Mathlib/Algebra/Ring/Subsemiring/Defs.lean | 2 +- Mathlib/Algebra/Star/Basic.lean | 2 +- Mathlib/Analysis/Complex/Basic.lean | 6 ++-- Mathlib/Analysis/Normed/Group/Basic.lean | 4 +-- .../SpecialFunctions/Complex/Arg.lean | 2 +- .../SpecialFunctions/Complex/Log.lean | 2 +- .../SpecialFunctions/Gamma/Basic.lean | 4 +-- .../Analysis/SpecialFunctions/Pow/NNReal.lean | 4 +-- Mathlib/Data/ENNReal/Real.lean | 10 +++--- Mathlib/Data/ENat/Basic.lean | 19 ++++------ Mathlib/Data/Matrix/ConjTranspose.lean | 12 +++---- Mathlib/Data/Matrix/Diagonal.lean | 15 +++----- Mathlib/Data/Matrix/Kronecker.lean | 4 +-- Mathlib/Data/Matrix/Mul.lean | 6 ++-- Mathlib/Data/Matrix/Notation.lean | 6 ++-- Mathlib/Data/NNRat/Defs.lean | 6 ++-- Mathlib/Data/NNReal/Defs.lean | 13 ++++--- Mathlib/Data/Nat/Cast/Basic.lean | 4 +-- Mathlib/Data/Nat/Cast/Order/Basic.lean | 35 ++++++------------- Mathlib/Data/Nat/Cast/Synonym.lean | 4 +-- Mathlib/Data/Nat/PartENat.lean | 22 +++++------- Mathlib/Data/Nat/Prime/Int.lean | 3 +- Mathlib/Data/PNat/Basic.lean | 10 +++--- Mathlib/Data/Rat/Cast/Order.lean | 8 ++--- Mathlib/Data/Rat/Lemmas.lean | 7 ++-- Mathlib/Data/Rat/Sqrt.lean | 3 +- Mathlib/Data/Real/Hyperreal.lean | 3 +- Mathlib/Data/ZMod/IntUnitsPower.lean | 3 +- Mathlib/LinearAlgebra/Matrix/PosDef.lean | 6 ++-- Mathlib/NumberTheory/LucasLehmer.lean | 6 ++-- Mathlib/NumberTheory/Padics/PadicNumbers.lean | 3 +- Mathlib/NumberTheory/Zsqrtd/Basic.lean | 4 +-- Mathlib/Order/Filter/Germ/Basic.lean | 6 ++-- Mathlib/SetTheory/Cardinal/Aleph.lean | 3 +- Mathlib/SetTheory/Cardinal/Basic.lean | 35 +++++++------------ Mathlib/SetTheory/Cardinal/Continuum.lean | 12 +++---- Mathlib/SetTheory/Cardinal/ENat.lean | 18 +++++----- Mathlib/SetTheory/Cardinal/ToNat.lean | 3 +- Mathlib/SetTheory/Game/Birthday.lean | 3 +- Mathlib/SetTheory/Game/Short.lean | 2 +- Mathlib/SetTheory/Ordinal/Arithmetic.lean | 6 ++-- Mathlib/SetTheory/Ordinal/Basic.lean | 21 ++++------- Mathlib/Tactic/NoncommRing.lean | 4 +-- Mathlib/Tactic/Ring/PNat.lean | 1 + .../Topology/Algebra/Module/LinearMap.lean | 2 +- .../Algebra/SeparationQuotient/Basic.lean | 2 +- scripts/technical-debt-metrics.sh | 1 - 54 files changed, 156 insertions(+), 237 deletions(-) diff --git a/Mathlib/Algebra/AddConstMap/Basic.lean b/Mathlib/Algebra/AddConstMap/Basic.lean index 25685a81e92e9..f71b10f9c82ba 100644 --- a/Mathlib/Algebra/AddConstMap/Basic.lean +++ b/Mathlib/Algebra/AddConstMap/Basic.lean @@ -87,7 +87,7 @@ theorem map_add_one [AddMonoidWithOne G] [Add H] [AddConstMapClass F G H 1 b] @[scoped simp] theorem map_add_ofNat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : - f (x + no_index (OfNat.ofNat n)) = f x + (OfNat.ofNat n : ℕ) • b := + f (x + ofNat(n)) = f x + (OfNat.ofNat n : ℕ) • b := map_add_nat' f x n theorem map_add_nat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] @@ -181,7 +181,7 @@ theorem map_sub_nat' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 @[scoped simp] theorem map_sub_ofNat' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 b] (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : - f (x - no_index (OfNat.ofNat n)) = f x - OfNat.ofNat n • b := + f (x - ofNat(n)) = f x - OfNat.ofNat n • b := map_sub_nat' f x n @[scoped simp] diff --git a/Mathlib/Algebra/CharZero/Defs.lean b/Mathlib/Algebra/CharZero/Defs.lean index c82356e6fa6e7..f536a1bb1d7a4 100644 --- a/Mathlib/Algebra/CharZero/Defs.lean +++ b/Mathlib/Algebra/CharZero/Defs.lean @@ -89,20 +89,20 @@ namespace OfNat variable [AddMonoidWithOne R] [CharZero R] -@[simp] lemma ofNat_ne_zero (n : ℕ) [n.AtLeastTwo] : (no_index (ofNat n) : R) ≠ 0 := +@[simp] lemma ofNat_ne_zero (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : R) ≠ 0 := Nat.cast_ne_zero.2 (NeZero.ne n) -@[simp] lemma zero_ne_ofNat (n : ℕ) [n.AtLeastTwo] : 0 ≠ (no_index (ofNat n) : R) := +@[simp] lemma zero_ne_ofNat (n : ℕ) [n.AtLeastTwo] : 0 ≠ (ofNat(n) : R) := (ofNat_ne_zero n).symm -@[simp] lemma ofNat_ne_one (n : ℕ) [n.AtLeastTwo] : (no_index (ofNat n) : R) ≠ 1 := +@[simp] lemma ofNat_ne_one (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : R) ≠ 1 := Nat.cast_ne_one.2 (Nat.AtLeastTwo.ne_one) -@[simp] lemma one_ne_ofNat (n : ℕ) [n.AtLeastTwo] : (1 : R) ≠ no_index (ofNat n) := +@[simp] lemma one_ne_ofNat (n : ℕ) [n.AtLeastTwo] : (1 : R) ≠ ofNat(n) := (ofNat_ne_one n).symm @[simp] lemma ofNat_eq_ofNat {m n : ℕ} [m.AtLeastTwo] [n.AtLeastTwo] : - (no_index (ofNat m) : R) = no_index (ofNat n) ↔ (ofNat m : ℕ) = ofNat n := + (ofNat(m) : R) = ofNat(n) ↔ (ofNat m : ℕ) = ofNat n := Nat.cast_inj end OfNat diff --git a/Mathlib/Algebra/DirectSum/Internal.lean b/Mathlib/Algebra/DirectSum/Internal.lean index a75722faa88dc..fb7946b75ad16 100644 --- a/Mathlib/Algebra/DirectSum/Internal.lean +++ b/Mathlib/Algebra/DirectSum/Internal.lean @@ -337,7 +337,7 @@ instance instSemiring : Semiring (A 0) := (subsemiring A).toSemiring @[simp, norm_cast] theorem coe_natCast (n : ℕ) : (n : A 0) = (n : R) := rfl @[simp, norm_cast] theorem coe_ofNat (n : ℕ) [n.AtLeastTwo] : - (no_index (OfNat.ofNat n) : A 0) = (OfNat.ofNat n : R) := rfl + (ofNat(n) : A 0) = (OfNat.ofNat n : R) := rfl end Semiring diff --git a/Mathlib/Algebra/Module/LinearMap/End.lean b/Mathlib/Algebra/Module/LinearMap/End.lean index 5f1a7fe6fd3d0..d7cac2488f1b0 100644 --- a/Mathlib/Algebra/Module/LinearMap/End.lean +++ b/Mathlib/Algebra/Module/LinearMap/End.lean @@ -89,7 +89,7 @@ theorem _root_.Module.End.natCast_apply (n : ℕ) (m : M) : (↑n : Module.End R @[simp] theorem _root_.Module.End.ofNat_apply (n : ℕ) [n.AtLeastTwo] (m : M) : - (no_index (OfNat.ofNat n) : Module.End R M) m = OfNat.ofNat n • m := rfl + (ofNat(n) : Module.End R M) m = OfNat.ofNat n • m := rfl instance _root_.Module.End.ring : Ring (Module.End R N₁) := { Module.End.semiring, LinearMap.addCommGroup with diff --git a/Mathlib/Algebra/Order/SuccPred/WithBot.lean b/Mathlib/Algebra/Order/SuccPred/WithBot.lean index df9812d972bf8..08d2abbd2dca9 100644 --- a/Mathlib/Algebra/Order/SuccPred/WithBot.lean +++ b/Mathlib/Algebra/Order/SuccPred/WithBot.lean @@ -24,6 +24,6 @@ lemma succ_one : succ (1 : WithBot α) = 2 := by simpa [one_add_one_eq_two] usin @[simp] lemma succ_ofNat (n : ℕ) [n.AtLeastTwo] : - succ (no_index (OfNat.ofNat n) : WithBot α) = OfNat.ofNat n + 1 := succ_natCast n + succ (ofNat(n) : WithBot α) = OfNat.ofNat n + 1 := succ_natCast n end WithBot diff --git a/Mathlib/Algebra/Polynomial/Derivative.lean b/Mathlib/Algebra/Polynomial/Derivative.lean index c23fdfc0c1e98..e0154c45d7370 100644 --- a/Mathlib/Algebra/Polynomial/Derivative.lean +++ b/Mathlib/Algebra/Polynomial/Derivative.lean @@ -195,7 +195,7 @@ alias derivative_nat_cast := derivative_natCast @[simp] theorem derivative_ofNat (n : ℕ) [n.AtLeastTwo] : - derivative (no_index (OfNat.ofNat n) : R[X]) = 0 := + derivative (ofNat(n) : R[X]) = 0 := derivative_natCast theorem iterate_derivative_eq_zero {p : R[X]} {x : ℕ} (hx : p.natDegree < x) : diff --git a/Mathlib/Algebra/Polynomial/Eval/Defs.lean b/Mathlib/Algebra/Polynomial/Eval/Defs.lean index af51045eb7816..5b47a0237e819 100644 --- a/Mathlib/Algebra/Polynomial/Eval/Defs.lean +++ b/Mathlib/Algebra/Polynomial/Eval/Defs.lean @@ -102,10 +102,9 @@ theorem eval₂_natCast (n : ℕ) : (n : R[X]).eval₂ f x = n := by @[deprecated (since := "2024-04-17")] alias eval₂_nat_cast := eval₂_natCast --- See note [no_index around OfNat.ofNat] @[simp] lemma eval₂_ofNat {S : Type*} [Semiring S] (n : ℕ) [n.AtLeastTwo] (f : R →+* S) (a : S) : - (no_index (OfNat.ofNat n : R[X])).eval₂ f a = OfNat.ofNat n := by + (ofNat(n) : R[X]).eval₂ f a = OfNat.ofNat n := by simp [OfNat.ofNat] variable [Semiring T] @@ -263,10 +262,9 @@ theorem eval₂_at_natCast {S : Type*} [Semiring S] (f : R →+* S) (n : ℕ) : @[deprecated (since := "2024-04-17")] alias eval₂_at_nat_cast := eval₂_at_natCast --- See note [no_index around OfNat.ofNat] @[simp] theorem eval₂_at_ofNat {S : Type*} [Semiring S] (f : R →+* S) (n : ℕ) [n.AtLeastTwo] : - p.eval₂ f (no_index (OfNat.ofNat n)) = f (p.eval (OfNat.ofNat n)) := by + p.eval₂ f ofNat(n) = f (p.eval (OfNat.ofNat n)) := by simp [OfNat.ofNat] @[simp] @@ -279,10 +277,9 @@ theorem eval_natCast {n : ℕ} : (n : R[X]).eval x = n := by simp only [← C_eq @[deprecated (since := "2024-04-17")] alias eval_nat_cast := eval_natCast --- See note [no_index around OfNat.ofNat] @[simp] lemma eval_ofNat (n : ℕ) [n.AtLeastTwo] (a : R) : - (no_index (OfNat.ofNat n : R[X])).eval a = OfNat.ofNat n := by + (ofNat(n) : R[X]).eval a = OfNat.ofNat n := by simp only [OfNat.ofNat, eval_natCast] @[simp] @@ -398,7 +395,7 @@ theorem natCast_comp {n : ℕ} : (n : R[X]).comp p = n := by rw [← C_eq_natCas alias nat_cast_comp := natCast_comp @[simp] -theorem ofNat_comp (n : ℕ) [n.AtLeastTwo] : (no_index (OfNat.ofNat n) : R[X]).comp p = n := +theorem ofNat_comp (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : R[X]).comp p = n := natCast_comp @[simp] @@ -550,10 +547,9 @@ protected theorem map_natCast (n : ℕ) : (n : R[X]).map f = n := @[deprecated (since := "2024-04-17")] alias map_nat_cast := map_natCast --- See note [no_index around OfNat.ofNat] @[simp] protected theorem map_ofNat (n : ℕ) [n.AtLeastTwo] : - (no_index (OfNat.ofNat n) : R[X]).map f = OfNat.ofNat n := + (ofNat(n) : R[X]).map f = OfNat.ofNat n := show (n : R[X]).map f = n by rw [Polynomial.map_natCast] --TODO rename to `map_dvd_map` diff --git a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean index c6270059e4f28..ada342ff44bd3 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean @@ -32,7 +32,7 @@ theorem natCast_mem [AddSubmonoidWithOneClass S R] (n : ℕ) : (n : R) ∈ s := @[aesop safe apply (rule_sets := [SetLike])] lemma ofNat_mem [AddSubmonoidWithOneClass S R] (s : S) (n : ℕ) [n.AtLeastTwo] : - no_index (OfNat.ofNat n) ∈ s := by + ofNat(n) ∈ s := by rw [← Nat.cast_ofNat]; exact natCast_mem s n instance (priority := 74) AddSubmonoidWithOneClass.toAddMonoidWithOne diff --git a/Mathlib/Algebra/Star/Basic.lean b/Mathlib/Algebra/Star/Basic.lean index 04f2f59e38df2..929ae83b99d4a 100644 --- a/Mathlib/Algebra/Star/Basic.lean +++ b/Mathlib/Algebra/Star/Basic.lean @@ -289,7 +289,7 @@ theorem star_natCast [NonAssocSemiring R] [StarRing R] (n : ℕ) : star (n : R) @[simp] theorem star_ofNat [NonAssocSemiring R] [StarRing R] (n : ℕ) [n.AtLeastTwo] : - star (no_index (OfNat.ofNat n) : R) = OfNat.ofNat n := + star (ofNat(n) : R) = OfNat.ofNat n := star_natCast _ section diff --git a/Mathlib/Analysis/Complex/Basic.lean b/Mathlib/Analysis/Complex/Basic.lean index 05dc52915295f..73c4f7ae5cdfa 100644 --- a/Mathlib/Analysis/Complex/Basic.lean +++ b/Mathlib/Analysis/Complex/Basic.lean @@ -154,10 +154,10 @@ theorem comap_abs_nhds_zero : comap abs (𝓝 0) = 𝓝 0 := @[simp 1100, norm_cast] lemma nnnorm_ratCast (q : ℚ) : ‖(q : ℂ)‖₊ = ‖(q : ℝ)‖₊ := nnnorm_real q @[simp 1100] lemma norm_ofNat (n : ℕ) [n.AtLeastTwo] : - ‖(no_index (OfNat.ofNat n) : ℂ)‖ = OfNat.ofNat n := norm_natCast n + ‖(ofNat(n) : ℂ)‖ = OfNat.ofNat n := norm_natCast n @[simp 1100] lemma nnnorm_ofNat (n : ℕ) [n.AtLeastTwo] : - ‖(no_index (OfNat.ofNat n) : ℂ)‖₊ = OfNat.ofNat n := nnnorm_natCast n + ‖(ofNat(n) : ℂ)‖₊ = OfNat.ofNat n := nnnorm_natCast n @[deprecated (since := "2024-08-25")] alias norm_nat := norm_natCast @[deprecated (since := "2024-08-25")] alias norm_int := norm_intCast @@ -693,7 +693,7 @@ lemma natCast_mem_slitPlane {n : ℕ} : ↑n ∈ slitPlane ↔ n ≠ 0 := by alias nat_cast_mem_slitPlane := natCast_mem_slitPlane @[simp] -lemma ofNat_mem_slitPlane (n : ℕ) [n.AtLeastTwo] : no_index (OfNat.ofNat n) ∈ slitPlane := +lemma ofNat_mem_slitPlane (n : ℕ) [n.AtLeastTwo] : ofNat(n) ∈ slitPlane := natCast_mem_slitPlane.2 (NeZero.ne n) lemma mem_slitPlane_iff_not_le_zero {z : ℂ} : z ∈ slitPlane ↔ ¬z ≤ 0 := diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index fc2858dbb2006..493bd417df034 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -1240,10 +1240,10 @@ theorem le_norm_self (r : ℝ) : r ≤ ‖r‖ := @[deprecated (since := "2024-04-05")] alias nnnorm_coe_nat := nnnorm_natCast @[simp 1100] lemma norm_ofNat (n : ℕ) [n.AtLeastTwo] : - ‖(no_index (OfNat.ofNat n) : ℝ)‖ = OfNat.ofNat n := norm_natCast n + ‖(ofNat(n) : ℝ)‖ = OfNat.ofNat n := norm_natCast n @[simp 1100] lemma nnnorm_ofNat (n : ℕ) [n.AtLeastTwo] : - ‖(no_index (OfNat.ofNat n) : ℝ)‖₊ = OfNat.ofNat n := nnnorm_natCast n + ‖(ofNat(n) : ℝ)‖₊ = OfNat.ofNat n := nnnorm_natCast n lemma norm_two : ‖(2 : ℝ)‖ = 2 := abs_of_pos zero_lt_two lemma nnnorm_two : ‖(2 : ℝ)‖₊ = 2 := NNReal.eq <| by simp diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean index 0086e643a19b8..1b221e58e8826 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean @@ -201,7 +201,7 @@ lemma natCast_arg {n : ℕ} : arg n = 0 := ofReal_natCast n ▸ arg_ofReal_of_nonneg n.cast_nonneg @[simp] -lemma ofNat_arg {n : ℕ} [n.AtLeastTwo] : arg (no_index (OfNat.ofNat n)) = 0 := +lemma ofNat_arg {n : ℕ} [n.AtLeastTwo] : arg ofNat(n) = 0 := natCast_arg theorem arg_eq_zero_iff {z : ℂ} : arg z = 0 ↔ 0 ≤ z.re ∧ z.im = 0 := by diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean index 6beddd4acf3e0..60934d34bd710 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean @@ -65,7 +65,7 @@ lemma natCast_log {n : ℕ} : Real.log n = log n := ofReal_natCast n ▸ ofReal_ @[simp] lemma ofNat_log {n : ℕ} [n.AtLeastTwo] : - Real.log (no_index (OfNat.ofNat n)) = log (OfNat.ofNat n) := + Real.log ofNat(n) = log (OfNat.ofNat n) := natCast_log theorem log_ofReal_re (x : ℝ) : (log (x : ℂ)).re = Real.log x := by simp [log_re] diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean index d8f00d79a6694..5d627dc71ac06 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean @@ -330,7 +330,7 @@ theorem Gamma_nat_eq_factorial (n : ℕ) : Gamma (n + 1) = n ! := by @[simp] theorem Gamma_ofNat_eq_factorial (n : ℕ) [(n + 1).AtLeastTwo] : - Gamma (no_index (OfNat.ofNat (n + 1) : ℂ)) = n ! := + Gamma (ofNat(n + 1) : ℂ) = n ! := mod_cast Gamma_nat_eq_factorial (n : ℕ) /-- At `0` the Gamma function is undefined; by convention we assign it the value `0`. -/ @@ -434,7 +434,7 @@ theorem Gamma_nat_eq_factorial (n : ℕ) : Gamma (n + 1) = n ! := by @[simp] theorem Gamma_ofNat_eq_factorial (n : ℕ) [(n + 1).AtLeastTwo] : - Gamma (no_index (OfNat.ofNat (n + 1) : ℝ)) = n ! := + Gamma (ofNat(n + 1) : ℝ) = n ! := mod_cast Gamma_nat_eq_factorial (n : ℕ) /-- At `0` the Gamma function is undefined; by convention we assign it the value `0`. -/ diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean index 43bf1bcc6be45..cbe2f010c0703 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean @@ -176,7 +176,7 @@ alias rpow_nat_cast := rpow_natCast @[simp] lemma rpow_ofNat (x : ℝ≥0) (n : ℕ) [n.AtLeastTwo] : - x ^ (no_index (OfNat.ofNat n) : ℝ) = x ^ (OfNat.ofNat n : ℕ) := + x ^ (ofNat(n) : ℝ) = x ^ (OfNat.ofNat n : ℕ) := rpow_natCast x n theorem rpow_two (x : ℝ≥0) : x ^ (2 : ℝ) = x ^ 2 := rpow_ofNat x 2 @@ -635,7 +635,7 @@ alias rpow_nat_cast := rpow_natCast @[simp] lemma rpow_ofNat (x : ℝ≥0∞) (n : ℕ) [n.AtLeastTwo] : - x ^ (no_index (OfNat.ofNat n) : ℝ) = x ^ (OfNat.ofNat n) := + x ^ (ofNat(n) : ℝ) = x ^ (OfNat.ofNat n) := rpow_natCast x n @[simp, norm_cast] diff --git a/Mathlib/Data/ENNReal/Real.lean b/Mathlib/Data/ENNReal/Real.lean index 879ef89de544e..bf44809f4e036 100644 --- a/Mathlib/Data/ENNReal/Real.lean +++ b/Mathlib/Data/ENNReal/Real.lean @@ -216,7 +216,7 @@ lemma ofReal_lt_one {p : ℝ} : ENNReal.ofReal p < 1 ↔ p < 1 := by @[simp] lemma ofReal_lt_ofNat {p : ℝ} {n : ℕ} [n.AtLeastTwo] : - ENNReal.ofReal p < no_index (OfNat.ofNat n) ↔ p < OfNat.ofNat n := + ENNReal.ofReal p < ofNat(n) ↔ p < OfNat.ofNat n := ofReal_lt_natCast (NeZero.ne n) @[simp] @@ -232,7 +232,7 @@ lemma one_le_ofReal {p : ℝ} : 1 ≤ ENNReal.ofReal p ↔ 1 ≤ p := by @[simp] lemma ofNat_le_ofReal {n : ℕ} [n.AtLeastTwo] {p : ℝ} : - no_index (OfNat.ofNat n) ≤ ENNReal.ofReal p ↔ OfNat.ofNat n ≤ p := + ofNat(n) ≤ ENNReal.ofReal p ↔ OfNat.ofNat n ≤ p := natCast_le_ofReal (NeZero.ne n) @[simp, norm_cast] @@ -248,7 +248,7 @@ lemma ofReal_le_one {r : ℝ} : ENNReal.ofReal r ≤ 1 ↔ r ≤ 1 := @[simp] lemma ofReal_le_ofNat {r : ℝ} {n : ℕ} [n.AtLeastTwo] : - ENNReal.ofReal r ≤ no_index (OfNat.ofNat n) ↔ r ≤ OfNat.ofNat n := + ENNReal.ofReal r ≤ ofNat(n) ↔ r ≤ OfNat.ofNat n := ofReal_le_natCast @[simp] @@ -263,7 +263,7 @@ lemma one_lt_ofReal {r : ℝ} : 1 < ENNReal.ofReal r ↔ 1 < r := coe_lt_coe.tra @[simp] lemma ofNat_lt_ofReal {n : ℕ} [n.AtLeastTwo] {r : ℝ} : - no_index (OfNat.ofNat n) < ENNReal.ofReal r ↔ OfNat.ofNat n < r := + ofNat(n) < ENNReal.ofReal r ↔ OfNat.ofNat n < r := natCast_lt_ofReal @[simp] @@ -279,7 +279,7 @@ lemma ofReal_eq_one {r : ℝ} : ENNReal.ofReal r = 1 ↔ r = 1 := @[simp] lemma ofReal_eq_ofNat {r : ℝ} {n : ℕ} [n.AtLeastTwo] : - ENNReal.ofReal r = no_index (OfNat.ofNat n) ↔ r = OfNat.ofNat n := + ENNReal.ofReal r = ofNat(n) ↔ r = OfNat.ofNat n := ofReal_eq_natCast (NeZero.ne n) theorem ofReal_sub (p : ℝ) {q : ℝ} (hq : 0 ≤ q) : diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index 7f2011f33653d..99492bb51fbaf 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -104,7 +104,7 @@ def lift (x : ℕ∞) (h : x < ⊤) : ℕ := WithTop.untop x (WithTop.lt_top_iff @[simp] theorem lift_zero : lift 0 (WithTop.coe_lt_top 0) = 0 := rfl @[simp] theorem lift_one : lift 1 (WithTop.coe_lt_top 1) = 1 := rfl @[simp] theorem lift_ofNat (n : ℕ) [n.AtLeastTwo] : - lift (no_index (OfNat.ofNat n)) (WithTop.coe_lt_top n) = OfNat.ofNat n := rfl + lift ofNat(n) (WithTop.coe_lt_top n) = OfNat.ofNat n := rfl @[simp] theorem add_lt_top {a b : ℕ∞} : a + b < ⊤ ↔ a < ⊤ ∧ b < ⊤ := WithTop.add_lt_top @@ -145,9 +145,8 @@ theorem toNat_zero : toNat 0 = 0 := theorem toNat_one : toNat 1 = 1 := rfl --- See note [no_index around OfNat.ofNat] @[simp] -theorem toNat_ofNat (n : ℕ) [n.AtLeastTwo] : toNat (no_index (OfNat.ofNat n)) = n := +theorem toNat_ofNat (n : ℕ) [n.AtLeastTwo] : toNat ofNat(n) = n := rfl @[simp] @@ -164,19 +163,17 @@ theorem recTopCoe_zero {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) theorem recTopCoe_one {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) : @recTopCoe C d f 1 = f 1 := rfl --- See note [no_index around OfNat.ofNat] @[simp] theorem recTopCoe_ofNat {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) (x : ℕ) [x.AtLeastTwo] : - @recTopCoe C d f (no_index (OfNat.ofNat x)) = f (OfNat.ofNat x) := + @recTopCoe C d f ofNat(x) = f (OfNat.ofNat x) := rfl @[simp] theorem top_ne_coe (a : ℕ) : ⊤ ≠ (a : ℕ∞) := nofun --- See note [no_index around OfNat.ofNat] @[simp] -theorem top_ne_ofNat (a : ℕ) [a.AtLeastTwo] : ⊤ ≠ (no_index (OfNat.ofNat a : ℕ∞)) := +theorem top_ne_ofNat (a : ℕ) [a.AtLeastTwo] : ⊤ ≠ (ofNat(a) : ℕ∞) := nofun @[simp] lemma top_ne_zero : (⊤ : ℕ∞) ≠ 0 := nofun @@ -186,9 +183,8 @@ theorem top_ne_ofNat (a : ℕ) [a.AtLeastTwo] : ⊤ ≠ (no_index (OfNat.ofNat a theorem coe_ne_top (a : ℕ) : (a : ℕ∞) ≠ ⊤ := nofun --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_ne_top (a : ℕ) [a.AtLeastTwo] : (no_index (OfNat.ofNat a : ℕ∞)) ≠ ⊤ := +theorem ofNat_ne_top (a : ℕ) [a.AtLeastTwo] : (ofNat(a) : ℕ∞) ≠ ⊤ := nofun @[simp] lemma zero_ne_top : 0 ≠ (⊤ : ℕ∞) := nofun @@ -202,9 +198,8 @@ theorem top_sub_coe (a : ℕ) : (⊤ : ℕ∞) - a = ⊤ := theorem top_sub_one : (⊤ : ℕ∞) - 1 = ⊤ := top_sub_coe 1 --- See note [no_index around OfNat.ofNat] @[simp] -theorem top_sub_ofNat (a : ℕ) [a.AtLeastTwo] : (⊤ : ℕ∞) - (no_index (OfNat.ofNat a)) = ⊤ := +theorem top_sub_ofNat (a : ℕ) [a.AtLeastTwo] : (⊤ : ℕ∞) - ofNat(a) = ⊤ := top_sub_coe a @[simp] @@ -382,7 +377,7 @@ theorem map_zero (f : ℕ → α) : map f 0 = f 0 := rfl theorem map_one (f : ℕ → α) : map f 1 = f 1 := rfl @[simp] -theorem map_ofNat (f : ℕ → α) (n : ℕ) [n.AtLeastTwo] : map f (no_index (OfNat.ofNat n)) = f n := rfl +theorem map_ofNat (f : ℕ → α) (n : ℕ) [n.AtLeastTwo] : map f ofNat(n) = f n := rfl @[simp] lemma map_eq_top_iff {f : ℕ → α} : map f n = ⊤ ↔ n = ⊤ := WithTop.map_eq_top_iff diff --git a/Mathlib/Data/Matrix/ConjTranspose.lean b/Mathlib/Data/Matrix/ConjTranspose.lean index 5f5843664ca6b..4b856340799ca 100644 --- a/Mathlib/Data/Matrix/ConjTranspose.lean +++ b/Mathlib/Data/Matrix/ConjTranspose.lean @@ -163,17 +163,15 @@ theorem conjTranspose_eq_natCast [DecidableEq n] [Semiring α] [StarRing α] (Function.Involutive.eq_iff conjTranspose_conjTranspose).trans <| by rw [conjTranspose_natCast] --- See note [no_index around OfNat.ofNat] @[simp] theorem conjTranspose_ofNat [DecidableEq n] [Semiring α] [StarRing α] (d : ℕ) [d.AtLeastTwo] : - (no_index (OfNat.ofNat d) : Matrix n n α)ᴴ = OfNat.ofNat d := + (ofNat(d) : Matrix n n α)ᴴ = OfNat.ofNat d := conjTranspose_natCast _ --- See note [no_index around OfNat.ofNat] @[simp] theorem conjTranspose_eq_ofNat [DecidableEq n] [Semiring α] [StarRing α] {M : Matrix n n α} {d : ℕ} [d.AtLeastTwo] : - Mᴴ = no_index (OfNat.ofNat d) ↔ M = OfNat.ofNat d := + Mᴴ = ofNat(d) ↔ M = OfNat.ofNat d := conjTranspose_eq_natCast @[simp] @@ -239,11 +237,10 @@ theorem conjTranspose_natCast_smul [Semiring R] [AddCommMonoid α] [StarAddMonoi (c : ℕ) (M : Matrix m n α) : ((c : R) • M)ᴴ = (c : R) • Mᴴ := Matrix.ext <| by simp --- See note [no_index around OfNat.ofNat] @[simp] theorem conjTranspose_ofNat_smul [Semiring R] [AddCommMonoid α] [StarAddMonoid α] [Module R α] (c : ℕ) [c.AtLeastTwo] (M : Matrix m n α) : - ((no_index (OfNat.ofNat c : R)) • M)ᴴ = (OfNat.ofNat c : R) • Mᴴ := + ((ofNat(c) : R) • M)ᴴ = (OfNat.ofNat c : R) • Mᴴ := conjTranspose_natCast_smul c M @[simp] @@ -256,11 +253,10 @@ theorem conjTranspose_inv_natCast_smul [DivisionSemiring R] [AddCommMonoid α] [ [Module R α] (c : ℕ) (M : Matrix m n α) : ((c : R)⁻¹ • M)ᴴ = (c : R)⁻¹ • Mᴴ := Matrix.ext <| by simp --- See note [no_index around OfNat.ofNat] @[simp] theorem conjTranspose_inv_ofNat_smul [DivisionSemiring R] [AddCommMonoid α] [StarAddMonoid α] [Module R α] (c : ℕ) [c.AtLeastTwo] (M : Matrix m n α) : - ((no_index (OfNat.ofNat c : R))⁻¹ • M)ᴴ = (OfNat.ofNat c : R)⁻¹ • Mᴴ := + ((ofNat(c) : R)⁻¹ • M)ᴴ = (OfNat.ofNat c : R)⁻¹ • Mᴴ := conjTranspose_inv_natCast_smul c M @[simp] diff --git a/Mathlib/Data/Matrix/Diagonal.lean b/Mathlib/Data/Matrix/Diagonal.lean index a1ae509a8b378..89efdc3f4b838 100644 --- a/Mathlib/Data/Matrix/Diagonal.lean +++ b/Mathlib/Data/Matrix/Diagonal.lean @@ -117,13 +117,11 @@ theorem diagonal_natCast [Zero α] [NatCast α] (m : ℕ) : diagonal (fun _ : n @[norm_cast] theorem diagonal_natCast' [Zero α] [NatCast α] (m : ℕ) : diagonal ((m : n → α)) = m := rfl --- See note [no_index around OfNat.ofNat] theorem diagonal_ofNat [Zero α] [NatCast α] (m : ℕ) [m.AtLeastTwo] : - diagonal (fun _ : n => no_index (OfNat.ofNat m : α)) = OfNat.ofNat m := rfl + diagonal (fun _ : n => (ofNat(m) : α)) = OfNat.ofNat m := rfl --- See note [no_index around OfNat.ofNat] theorem diagonal_ofNat' [Zero α] [NatCast α] (m : ℕ) [m.AtLeastTwo] : - diagonal (no_index (OfNat.ofNat m : n → α)) = OfNat.ofNat m := rfl + diagonal (ofNat(m) : n → α) = OfNat.ofNat m := rfl instance [Zero α] [IntCast α] : IntCast (Matrix n n α) where intCast m := diagonal fun _ => m @@ -146,10 +144,9 @@ protected theorem map_natCast [AddMonoidWithOne α] [AddMonoidWithOne β] (d : Matrix n n α).map f = diagonal (fun _ => f d) := diagonal_map h --- See note [no_index around OfNat.ofNat] protected theorem map_ofNat [AddMonoidWithOne α] [AddMonoidWithOne β] {f : α → β} (h : f 0 = 0) (d : ℕ) [d.AtLeastTwo] : - (no_index (OfNat.ofNat d) : Matrix n n α).map f = diagonal (fun _ => f (OfNat.ofNat d)) := + (ofNat(d) : Matrix n n α).map f = diagonal (fun _ => f (OfNat.ofNat d)) := diagonal_map h protected theorem map_intCast [AddGroupWithOne α] [AddGroupWithOne β] @@ -310,17 +307,15 @@ theorem transpose_eq_natCast [DecidableEq n] [AddMonoidWithOne α] {M : Matrix n Mᵀ = d ↔ M = d := transpose_eq_diagonal --- See note [no_index around OfNat.ofNat] @[simp] theorem transpose_ofNat [DecidableEq n] [AddMonoidWithOne α] (d : ℕ) [d.AtLeastTwo] : - (no_index (OfNat.ofNat d) : Matrix n n α)ᵀ = OfNat.ofNat d := + (ofNat(d) : Matrix n n α)ᵀ = OfNat.ofNat d := transpose_natCast _ --- See note [no_index around OfNat.ofNat] @[simp] theorem transpose_eq_ofNat [DecidableEq n] [AddMonoidWithOne α] {M : Matrix n n α} {d : ℕ} [d.AtLeastTwo] : - Mᵀ = no_index (OfNat.ofNat d) ↔ M = OfNat.ofNat d := + Mᵀ = ofNat(d) ↔ M = OfNat.ofNat d := transpose_eq_diagonal @[simp] diff --git a/Mathlib/Data/Matrix/Kronecker.lean b/Mathlib/Data/Matrix/Kronecker.lean index 1d108492e89cf..0d5b9fc77bc99 100644 --- a/Mathlib/Data/Matrix/Kronecker.lean +++ b/Mathlib/Data/Matrix/Kronecker.lean @@ -313,12 +313,12 @@ theorem natCast_kronecker [NonAssocSemiring α] [DecidableEq l] (a : ℕ) (B : M simp [(Nat.cast_commute a _).eq] theorem kronecker_ofNat [Semiring α] [DecidableEq n] (A : Matrix l m α) (b : ℕ) [b.AtLeastTwo] : - A ⊗ₖ (no_index (OfNat.ofNat b) : Matrix n n α) = + A ⊗ₖ (ofNat(b) : Matrix n n α) = blockDiagonal fun _ => A <• (OfNat.ofNat b : α) := kronecker_diagonal _ _ theorem ofNat_kronecker [Semiring α] [DecidableEq l] (a : ℕ) [a.AtLeastTwo] (B : Matrix m n α) : - (no_index (OfNat.ofNat a) : Matrix l l α) ⊗ₖ B = + (ofNat(a) : Matrix l l α) ⊗ₖ B = Matrix.reindex (.prodComm _ _) (.prodComm _ _) (blockDiagonal fun _ => (OfNat.ofNat a : α) • B) := diagonal_kronecker _ _ diff --git a/Mathlib/Data/Matrix/Mul.lean b/Mathlib/Data/Matrix/Mul.lean index 96502a2383140..3d4f563be4268 100644 --- a/Mathlib/Data/Matrix/Mul.lean +++ b/Mathlib/Data/Matrix/Mul.lean @@ -814,16 +814,14 @@ theorem vecMul_natCast (x : ℕ) (v : m → α) : v ᵥ* x = MulOpposite.op (x : vecMul_diagonal_const _ _ --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_mulVec (x : ℕ) [x.AtLeastTwo] (v : m → α) : - OfNat.ofNat (no_index x) *ᵥ v = (OfNat.ofNat x : α) • v := + ofNat(x) *ᵥ v = (OfNat.ofNat x : α) • v := natCast_mulVec _ _ --- See note [no_index around OfNat.ofNat] @[simp] theorem vecMul_ofNat (x : ℕ) [x.AtLeastTwo] (v : m → α) : - v ᵥ* OfNat.ofNat (no_index x) = MulOpposite.op (OfNat.ofNat x : α) • v := + v ᵥ* ofNat(x) = MulOpposite.op (OfNat.ofNat x : α) • v := vecMul_natCast _ _ end NonAssocSemiring diff --git a/Mathlib/Data/Matrix/Notation.lean b/Mathlib/Data/Matrix/Notation.lean index cafbf27798007..e29b479e13304 100644 --- a/Mathlib/Data/Matrix/Notation.lean +++ b/Mathlib/Data/Matrix/Notation.lean @@ -418,15 +418,13 @@ theorem natCast_fin_three (n : ℕ) : ext i j fin_cases i <;> fin_cases j <;> rfl --- See note [no_index around OfNat.ofNat] theorem ofNat_fin_two (n : ℕ) [n.AtLeastTwo] : - (no_index (OfNat.ofNat n) : Matrix (Fin 2) (Fin 2) α) = + (ofNat(n) : Matrix (Fin 2) (Fin 2) α) = !![OfNat.ofNat n, 0; 0, OfNat.ofNat n] := natCast_fin_two _ --- See note [no_index around OfNat.ofNat] theorem ofNat_fin_three (n : ℕ) [n.AtLeastTwo] : - (no_index (OfNat.ofNat n) : Matrix (Fin 3) (Fin 3) α) = + (ofNat(n) : Matrix (Fin 3) (Fin 3) α) = !![OfNat.ofNat n, 0, 0; 0, OfNat.ofNat n, 0; 0, 0, OfNat.ofNat n] := natCast_fin_three _ diff --git a/Mathlib/Data/NNRat/Defs.lean b/Mathlib/Data/NNRat/Defs.lean index 1b559909a9913..05d7636202277 100644 --- a/Mathlib/Data/NNRat/Defs.lean +++ b/Mathlib/Data/NNRat/Defs.lean @@ -188,7 +188,6 @@ def coeHom : ℚ≥0 →+* ℚ where @[simp, norm_cast] lemma coe_natCast (n : ℕ) : (↑(↑n : ℚ≥0) : ℚ) = n := rfl --- See note [no_index around OfNat.ofNat] @[simp] theorem mk_natCast (n : ℕ) : @Eq ℚ≥0 (⟨(n : ℚ), Nat.cast_nonneg' n⟩ : ℚ≥0) n := rfl @@ -336,10 +335,9 @@ lemma coprime_num_den (q : ℚ≥0) : q.num.Coprime q.den := by simpa [num, den] @[simp, norm_cast] lemma num_natCast (n : ℕ) : num n = n := rfl @[simp, norm_cast] lemma den_natCast (n : ℕ) : den n = 1 := rfl --- See note [no_index around OfNat.ofNat] -@[simp] lemma num_ofNat (n : ℕ) [n.AtLeastTwo] : num (no_index (OfNat.ofNat n)) = OfNat.ofNat n := +@[simp] lemma num_ofNat (n : ℕ) [n.AtLeastTwo] : num ofNat(n) = OfNat.ofNat n := rfl -@[simp] lemma den_ofNat (n : ℕ) [n.AtLeastTwo] : den (no_index (OfNat.ofNat n)) = 1 := rfl +@[simp] lemma den_ofNat (n : ℕ) [n.AtLeastTwo] : den ofNat(n) = 1 := rfl theorem ext_num_den (hn : p.num = q.num) (hd : p.den = q.den) : p = q := by refine ext <| Rat.ext ?_ hd diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index 1fad797f40bcd..dbf988eb67926 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -314,10 +314,9 @@ theorem mk_natCast (n : ℕ) : @Eq ℝ≥0 (⟨(n : ℝ), n.cast_nonneg⟩ : ℝ theorem toNNReal_coe_nat (n : ℕ) : Real.toNNReal n = n := NNReal.eq <| by simp [Real.coe_toNNReal] --- See note [no_index around OfNat.ofNat] @[simp] theorem _root_.Real.toNNReal_ofNat (n : ℕ) [n.AtLeastTwo] : - Real.toNNReal (no_index (OfNat.ofNat n)) = OfNat.ofNat n := + Real.toNNReal ofNat(n) = OfNat.ofNat n := toNNReal_coe_nat n /-- `Real.toNNReal` and `NNReal.toReal : ℝ≥0 → ℝ` form a Galois insertion. -/ @@ -528,7 +527,7 @@ alias toNNReal_eq_nat_cast := toNNReal_eq_natCast @[simp] lemma toNNReal_eq_ofNat {r : ℝ} {n : ℕ} [n.AtLeastTwo] : - r.toNNReal = no_index (OfNat.ofNat n) ↔ r = OfNat.ofNat n := + r.toNNReal = ofNat(n) ↔ r = OfNat.ofNat n := toNNReal_eq_natCast (NeZero.ne n) @[simp] @@ -559,12 +558,12 @@ alias nat_cast_lt_toNNReal := natCast_lt_toNNReal @[simp] lemma toNNReal_le_ofNat {r : ℝ} {n : ℕ} [n.AtLeastTwo] : - r.toNNReal ≤ no_index (OfNat.ofNat n) ↔ r ≤ n := + r.toNNReal ≤ ofNat(n) ↔ r ≤ n := toNNReal_le_natCast @[simp] lemma ofNat_lt_toNNReal {r : ℝ} {n : ℕ} [n.AtLeastTwo] : - no_index (OfNat.ofNat n) < r.toNNReal ↔ n < r := + ofNat(n) < r.toNNReal ↔ n < r := natCast_lt_toNNReal @[simp] @@ -625,12 +624,12 @@ alias toNNReal_lt_nat_cast := toNNReal_lt_natCast @[simp] lemma toNNReal_lt_ofNat {r : ℝ} {n : ℕ} [n.AtLeastTwo] : - r.toNNReal < no_index (OfNat.ofNat n) ↔ r < OfNat.ofNat n := + r.toNNReal < ofNat(n) ↔ r < OfNat.ofNat n := toNNReal_lt_natCast (NeZero.ne n) @[simp] lemma ofNat_le_toNNReal {n : ℕ} {r : ℝ} [n.AtLeastTwo] : - no_index (OfNat.ofNat n) ≤ r.toNNReal ↔ OfNat.ofNat n ≤ r := + ofNat(n) ≤ r.toNNReal ↔ OfNat.ofNat n ≤ r := natCast_le_toNNReal (NeZero.ne n) @[simp] diff --git a/Mathlib/Data/Nat/Cast/Basic.lean b/Mathlib/Data/Nat/Cast/Basic.lean index 77459f473b112..4d4457e98263a 100644 --- a/Mathlib/Data/Nat/Cast/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Basic.lean @@ -158,12 +158,12 @@ theorem map_natCast [FunLike F R S] [RingHomClass F R S] (f : F) : ∀ n : ℕ, map_natCast' f <| map_one f /-- This lemma is not marked `@[simp]` lemma because its `#discr_tree_key` (for the LHS) would just -be `DFunLike.coe _ _`, due to the `no_index` that https://github.com/leanprover/lean4/issues/2867 +be `DFunLike.coe _ _`, due to the `ofNat` that https://github.com/leanprover/lean4/issues/2867 forces us to include, and therefore it would negatively impact performance. If that issue is resolved, this can be marked `@[simp]`. -/ theorem map_ofNat [FunLike F R S] [RingHomClass F R S] (f : F) (n : ℕ) [Nat.AtLeastTwo n] : - (f (no_index (OfNat.ofNat n)) : S) = OfNat.ofNat n := + (f ofNat(n) : S) = OfNat.ofNat n := map_natCast f n theorem ext_nat [FunLike F ℕ R] [RingHomClass F ℕ R] (f g : F) : f = g := diff --git a/Mathlib/Data/Nat/Cast/Order/Basic.lean b/Mathlib/Data/Nat/Cast/Order/Basic.lean index 7d749878466c4..6c96978eb5a1b 100644 --- a/Mathlib/Data/Nat/Cast/Order/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Order/Basic.lean @@ -42,9 +42,8 @@ theorem cast_nonneg' (n : ℕ) : 0 ≤ (n : α) := @Nat.cast_zero α _ ▸ mono_cast (Nat.zero_le n) /-- See also `Nat.ofNat_nonneg`, specialised for an `OrderedSemiring`. -/ --- See note [no_index around OfNat.ofNat] @[simp low] -theorem ofNat_nonneg' (n : ℕ) [n.AtLeastTwo] : 0 ≤ (no_index (OfNat.ofNat n : α)) := cast_nonneg' n +theorem ofNat_nonneg' (n : ℕ) [n.AtLeastTwo] : 0 ≤ (ofNat(n) : α) := cast_nonneg' n section Nontrivial @@ -100,48 +99,40 @@ theorem cast_le_one : (n : α) ≤ 1 ↔ n ≤ 1 := by rw [← cast_one, cast_le section variable [m.AtLeastTwo] --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_le_cast : (no_index (OfNat.ofNat m : α)) ≤ n ↔ (OfNat.ofNat m : ℕ) ≤ n := +theorem ofNat_le_cast : (ofNat(m) : α) ≤ n ↔ (OfNat.ofNat m : ℕ) ≤ n := cast_le --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_lt_cast : (no_index (OfNat.ofNat m : α)) < n ↔ (OfNat.ofNat m : ℕ) < n := +theorem ofNat_lt_cast : (ofNat(m) : α) < n ↔ (OfNat.ofNat m : ℕ) < n := cast_lt end variable [n.AtLeastTwo] --- See note [no_index around OfNat.ofNat] @[simp] -theorem cast_le_ofNat : (m : α) ≤ (no_index (OfNat.ofNat n)) ↔ m ≤ OfNat.ofNat n := +theorem cast_le_ofNat : (m : α) ≤ (ofNat(n) : α) ↔ m ≤ OfNat.ofNat n := cast_le --- See note [no_index around OfNat.ofNat] @[simp] -theorem cast_lt_ofNat : (m : α) < (no_index (OfNat.ofNat n)) ↔ m < OfNat.ofNat n := +theorem cast_lt_ofNat : (m : α) < (ofNat(n) : α) ↔ m < OfNat.ofNat n := cast_lt --- See note [no_index around OfNat.ofNat] @[simp] -theorem one_lt_ofNat : 1 < (no_index (OfNat.ofNat n : α)) := +theorem one_lt_ofNat : 1 < (ofNat(n) : α) := one_lt_cast.mpr AtLeastTwo.one_lt --- See note [no_index around OfNat.ofNat] @[simp] -theorem one_le_ofNat : 1 ≤ (no_index (OfNat.ofNat n : α)) := +theorem one_le_ofNat : 1 ≤ (ofNat(n) : α) := one_le_cast.mpr NeZero.one_le --- See note [no_index around OfNat.ofNat] @[simp] -theorem not_ofNat_le_one : ¬(no_index (OfNat.ofNat n : α)) ≤ 1 := +theorem not_ofNat_le_one : ¬(ofNat(n) : α) ≤ 1 := (cast_le_one.not.trans not_le).mpr AtLeastTwo.one_lt --- See note [no_index around OfNat.ofNat] @[simp] -theorem not_ofNat_lt_one : ¬(no_index (OfNat.ofNat n : α)) < 1 := +theorem not_ofNat_lt_one : ¬(ofNat(n) : α) < 1 := mt le_of_lt not_ofNat_le_one variable [m.AtLeastTwo] @@ -150,18 +141,14 @@ variable [m.AtLeastTwo] -- and `Nat.cast_ofNat`, but their LHSs match literally every inequality, so they're too expensive. -- If https://github.com/leanprover/lean4/issues/2867 is fixed in a performant way, these can be made `@[simp]`. --- See note [no_index around OfNat.ofNat] -- @[simp] theorem ofNat_le : - (no_index (OfNat.ofNat m : α)) ≤ (no_index (OfNat.ofNat n)) ↔ - (OfNat.ofNat m : ℕ) ≤ OfNat.ofNat n := + (ofNat(m) : α) ≤ (ofNat(n) : α) ↔ (OfNat.ofNat m : ℕ) ≤ OfNat.ofNat n := cast_le --- See note [no_index around OfNat.ofNat] -- @[simp] theorem ofNat_lt : - (no_index (OfNat.ofNat m : α)) < (no_index (OfNat.ofNat n)) ↔ - (OfNat.ofNat m : ℕ) < OfNat.ofNat n := + (ofNat(m) : α) < (ofNat(n) : α) ↔ (OfNat.ofNat m : ℕ) < OfNat.ofNat n := cast_lt end OrderedSemiring diff --git a/Mathlib/Data/Nat/Cast/Synonym.lean b/Mathlib/Data/Nat/Cast/Synonym.lean index 11b1f4d3b233a..c18a4c25a81dc 100644 --- a/Mathlib/Data/Nat/Cast/Synonym.lean +++ b/Mathlib/Data/Nat/Cast/Synonym.lean @@ -74,7 +74,7 @@ theorem toLex_natCast [NatCast α] (n : ℕ) : toLex (n : α) = n := @[simp] theorem toLex_ofNat [NatCast α] (n : ℕ) [n.AtLeastTwo] : - (toLex (no_index (OfNat.ofNat n : α))) = OfNat.ofNat n := + toLex (ofNat(n) : α) = OfNat.ofNat n := rfl @[simp] @@ -83,5 +83,5 @@ theorem ofLex_natCast [NatCast α] (n : ℕ) : (ofLex n : α) = n := @[simp] theorem ofLex_ofNat [NatCast α] (n : ℕ) [n.AtLeastTwo] : - (ofLex (no_index (OfNat.ofNat n : Lex α))) = OfNat.ofNat n := + ofLex (ofNat(n) : Lex α) = OfNat.ofNat n := rfl diff --git a/Mathlib/Data/Nat/PartENat.lean b/Mathlib/Data/Nat/PartENat.lean index 1000c54d34db3..22dbf8f8562ca 100644 --- a/Mathlib/Data/Nat/PartENat.lean +++ b/Mathlib/Data/Nat/PartENat.lean @@ -114,9 +114,8 @@ theorem natCast_inj {x y : ℕ} : (x : PartENat) = y ↔ x = y := theorem dom_natCast (x : ℕ) : (x : PartENat).Dom := trivial --- See note [no_index around OfNat.ofNat] @[simp] -theorem dom_ofNat (x : ℕ) [x.AtLeastTwo] : (no_index (OfNat.ofNat x : PartENat)).Dom := +theorem dom_ofNat (x : ℕ) [x.AtLeastTwo] : (ofNat(x) : PartENat).Dom := trivial @[simp] @@ -189,10 +188,9 @@ theorem get_zero (h : (0 : PartENat).Dom) : (0 : PartENat).get h = 0 := theorem get_one (h : (1 : PartENat).Dom) : (1 : PartENat).get h = 1 := rfl --- See note [no_index around OfNat.ofNat] @[simp] -theorem get_ofNat' (x : ℕ) [x.AtLeastTwo] (h : (no_index (OfNat.ofNat x : PartENat)).Dom) : - Part.get (no_index (OfNat.ofNat x : PartENat)) h = (no_index (OfNat.ofNat x)) := +theorem get_ofNat' (x : ℕ) [x.AtLeastTwo] (h : (ofNat(x) : PartENat).Dom) : + Part.get (ofNat(x) : PartENat) h = ofNat(x) := get_natCast' x h nonrec theorem get_eq_iff_eq_some {a : PartENat} {ha : a.Dom} {b : ℕ} : a.get ha = b ↔ a = some b := @@ -327,9 +325,8 @@ theorem zero_lt_top : (0 : PartENat) < ⊤ := theorem one_lt_top : (1 : PartENat) < ⊤ := natCast_lt_top 1 --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_lt_top (x : ℕ) [x.AtLeastTwo] : (no_index (OfNat.ofNat x : PartENat)) < ⊤ := +theorem ofNat_lt_top (x : ℕ) [x.AtLeastTwo] : (ofNat(x) : PartENat) < ⊤ := natCast_lt_top x @[simp] @@ -344,9 +341,8 @@ theorem zero_ne_top : (0 : PartENat) ≠ ⊤ := theorem one_ne_top : (1 : PartENat) ≠ ⊤ := natCast_ne_top 1 --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_ne_top (x : ℕ) [x.AtLeastTwo] : (no_index (OfNat.ofNat x : PartENat)) ≠ ⊤ := +theorem ofNat_ne_top (x : ℕ) [x.AtLeastTwo] : (ofNat(x) : PartENat) ≠ ⊤ := natCast_ne_top x theorem not_isMax_natCast (x : ℕ) : ¬IsMax (x : PartENat) := @@ -556,7 +552,7 @@ theorem toWithTop_natCast' (n : ℕ) {_ : Decidable (n : PartENat).Dom} : @[simp] theorem toWithTop_ofNat (n : ℕ) [n.AtLeastTwo] {_ : Decidable (OfNat.ofNat n : PartENat).Dom} : - toWithTop (no_index (OfNat.ofNat n : PartENat)) = OfNat.ofNat n := toWithTop_natCast' n + toWithTop (ofNat(n) : PartENat) = OfNat.ofNat n := toWithTop_natCast' n -- Porting note: statement changed. Mathlib 3 statement was -- ``` @@ -621,7 +617,7 @@ theorem ofENat_zero : ofENat 0 = 0 := rfl theorem ofENat_one : ofENat 1 = 1 := rfl @[simp, norm_cast] -theorem ofENat_ofNat (n : Nat) [n.AtLeastTwo] : ofENat (no_index (OfNat.ofNat n)) = OfNat.ofNat n := +theorem ofENat_ofNat (n : Nat) [n.AtLeastTwo] : ofENat ofNat(n) = OfNat.ofNat n := rfl @[simp, norm_cast] @@ -679,7 +675,7 @@ theorem withTopEquiv_one : withTopEquiv 1 = 1 := by simp theorem withTopEquiv_ofNat (n : Nat) [n.AtLeastTwo] : - withTopEquiv (no_index (OfNat.ofNat n)) = OfNat.ofNat n := by + withTopEquiv ofNat(n) = OfNat.ofNat n := by simp theorem withTopEquiv_le {x y : PartENat} : withTopEquiv x ≤ withTopEquiv y ↔ x ≤ y := by @@ -701,7 +697,7 @@ theorem withTopEquiv_symm_one : withTopEquiv.symm 1 = 1 := by simp theorem withTopEquiv_symm_ofNat (n : Nat) [n.AtLeastTwo] : - withTopEquiv.symm (no_index (OfNat.ofNat n)) = OfNat.ofNat n := by + withTopEquiv.symm ofNat(n) = OfNat.ofNat n := by simp theorem withTopEquiv_symm_le {x y : ℕ∞} : withTopEquiv.symm x ≤ withTopEquiv.symm y ↔ x ≤ y := by diff --git a/Mathlib/Data/Nat/Prime/Int.lean b/Mathlib/Data/Nat/Prime/Int.lean index d357a3d303050..474b170148988 100644 --- a/Mathlib/Data/Nat/Prime/Int.lean +++ b/Mathlib/Data/Nat/Prime/Int.lean @@ -38,10 +38,9 @@ end Nat namespace Int --- See note [no_index around OfNat.ofNat] @[simp] theorem prime_ofNat_iff {n : ℕ} : - Prime (no_index (OfNat.ofNat n : ℤ)) ↔ Nat.Prime (OfNat.ofNat n) := + Prime (ofNat(n) : ℤ) ↔ Nat.Prime (OfNat.ofNat n) := Nat.prime_iff_prime_int.symm theorem prime_two : Prime (2 : ℤ) := diff --git a/Mathlib/Data/PNat/Basic.lean b/Mathlib/Data/PNat/Basic.lean index 087e1dc61c787..5b28b50869c1a 100644 --- a/Mathlib/Data/PNat/Basic.lean +++ b/Mathlib/Data/PNat/Basic.lean @@ -56,12 +56,12 @@ theorem natPred_inj {m n : ℕ+} : m.natPred = n.natPred ↔ m = n := @[simp, norm_cast] lemma val_ofNat (n : ℕ) [NeZero n] : - ((no_index (OfNat.ofNat n) : ℕ+) : ℕ) = OfNat.ofNat n := + ((ofNat(n) : ℕ+) : ℕ) = OfNat.ofNat n := rfl @[simp] lemma mk_ofNat (n : ℕ) (h : 0 < n) : - @Eq ℕ+ (⟨no_index (OfNat.ofNat n), h⟩ : ℕ+) (haveI : NeZero n := ⟨h.ne'⟩; OfNat.ofNat n) := + @Eq ℕ+ (⟨ofNat(n), h⟩ : ℕ+) (haveI : NeZero n := ⟨h.ne'⟩; OfNat.ofNat n) := rfl end PNat @@ -182,17 +182,17 @@ theorem recOn_succ (n : ℕ+) {p : ℕ+ → Sort*} (p1 hp) : @[simp] theorem ofNat_le_ofNat {m n : ℕ} [NeZero m] [NeZero n] : - (no_index (OfNat.ofNat m) : ℕ+) ≤ no_index (OfNat.ofNat n) ↔ OfNat.ofNat m ≤ OfNat.ofNat n := + (ofNat(m) : ℕ+) ≤ ofNat(n) ↔ OfNat.ofNat m ≤ OfNat.ofNat n := .rfl @[simp] theorem ofNat_lt_ofNat {m n : ℕ} [NeZero m] [NeZero n] : - (no_index (OfNat.ofNat m) : ℕ+) < no_index (OfNat.ofNat n) ↔ OfNat.ofNat m < OfNat.ofNat n := + (ofNat(m) : ℕ+) < ofNat(n) ↔ OfNat.ofNat m < OfNat.ofNat n := .rfl @[simp] theorem ofNat_inj {m n : ℕ} [NeZero m] [NeZero n] : - (no_index (OfNat.ofNat m) : ℕ+) = no_index (OfNat.ofNat n) ↔ OfNat.ofNat m = OfNat.ofNat n := + (ofNat(m) : ℕ+) = ofNat(n) ↔ OfNat.ofNat m = OfNat.ofNat n := Subtype.mk_eq_mk @[simp, norm_cast] diff --git a/Mathlib/Data/Rat/Cast/Order.lean b/Mathlib/Data/Rat/Cast/Order.lean index 618e76fd32375..e5287b4093aaf 100644 --- a/Mathlib/Data/Rat/Cast/Order.lean +++ b/Mathlib/Data/Rat/Cast/Order.lean @@ -174,16 +174,16 @@ def castOrderEmbedding : ℚ≥0 ↪o K := section ofNat variable {n : ℕ} [n.AtLeastTwo] -@[simp] lemma cast_le_ofNat : (p : K) ≤ no_index (OfNat.ofNat n) ↔ p ≤ OfNat.ofNat n := by +@[simp] lemma cast_le_ofNat : (p : K) ≤ ofNat(n) ↔ p ≤ OfNat.ofNat n := by simp [← cast_le (K := K)] -@[simp] lemma ofNat_le_cast : no_index (OfNat.ofNat n) ≤ (p : K) ↔ OfNat.ofNat n ≤ p := by +@[simp] lemma ofNat_le_cast : ofNat(n) ≤ (p : K) ↔ OfNat.ofNat n ≤ p := by simp [← cast_le (K := K)] -@[simp] lemma cast_lt_ofNat : (p : K) < no_index (OfNat.ofNat n) ↔ p < OfNat.ofNat n := by +@[simp] lemma cast_lt_ofNat : (p : K) < ofNat(n) ↔ p < OfNat.ofNat n := by simp [← cast_lt (K := K)] -@[simp] lemma ofNat_lt_cast : no_index (OfNat.ofNat n) < (p : K) ↔ OfNat.ofNat n < p := by +@[simp] lemma ofNat_lt_cast : ofNat(n) < (p : K) ↔ OfNat.ofNat n < p := by simp [← cast_lt (K := K)] end ofNat diff --git a/Mathlib/Data/Rat/Lemmas.lean b/Mathlib/Data/Rat/Lemmas.lean index 739a18a81c1b1..e0ac6e8bf3883 100644 --- a/Mathlib/Data/Rat/Lemmas.lean +++ b/Mathlib/Data/Rat/Lemmas.lean @@ -125,10 +125,9 @@ theorem isSquare_natCast_iff {n : ℕ} : IsSquare (n : ℚ) ↔ IsSquare n := by theorem isSquare_intCast_iff {z : ℤ} : IsSquare (z : ℚ) ↔ IsSquare z := by simp_rw [isSquare_iff, intCast_num, intCast_den, IsSquare.one, and_true] --- See note [no_index around OfNat.ofNat] @[simp] theorem isSquare_ofNat_iff {n : ℕ} : - IsSquare (no_index (OfNat.ofNat n) : ℚ) ↔ IsSquare (OfNat.ofNat n : ℕ) := + IsSquare (ofNat(n) : ℚ) ↔ IsSquare (OfNat.ofNat n : ℕ) := isSquare_natCast_iff section Casts @@ -265,7 +264,7 @@ theorem inv_natCast_num (a : ℕ) : (a : ℚ)⁻¹.num = Int.sign a := inv_intCast_num a @[simp] -theorem inv_ofNat_num (a : ℕ) [a.AtLeastTwo] : (no_index (OfNat.ofNat a : ℚ))⁻¹.num = 1 := +theorem inv_ofNat_num (a : ℕ) [a.AtLeastTwo] : (ofNat(a) : ℚ)⁻¹.num = 1 := inv_natCast_num_of_pos (Nat.pos_of_neZero a) @[simp] @@ -301,7 +300,7 @@ theorem inv_natCast_den (a : ℕ) : (a : ℚ)⁻¹.den = if a = 0 then 1 else a @[simp] theorem inv_ofNat_den (a : ℕ) [a.AtLeastTwo] : - (no_index (OfNat.ofNat a : ℚ))⁻¹.den = OfNat.ofNat a := + (ofNat(a) : ℚ)⁻¹.den = OfNat.ofNat a := inv_natCast_den_of_pos (Nat.pos_of_neZero a) protected theorem «forall» {p : ℚ → Prop} : (∀ r, p r) ↔ ∀ a b : ℤ, p (a / b) := diff --git a/Mathlib/Data/Rat/Sqrt.lean b/Mathlib/Data/Rat/Sqrt.lean index 7c9fe65973ca4..5f6d920bde3b8 100644 --- a/Mathlib/Data/Rat/Sqrt.lean +++ b/Mathlib/Data/Rat/Sqrt.lean @@ -45,9 +45,8 @@ theorem sqrt_intCast (z : ℤ) : Rat.sqrt (z : ℚ) = Int.sqrt z := by theorem sqrt_natCast (n : ℕ) : Rat.sqrt (n : ℚ) = Nat.sqrt n := by rw [← Int.cast_natCast, sqrt_intCast, Int.sqrt_natCast, Int.cast_natCast] --- See note [no_index around OfNat.ofNat] @[simp] -theorem sqrt_ofNat (n : ℕ) : Rat.sqrt (no_index (OfNat.ofNat n) : ℚ) = Nat.sqrt (OfNat.ofNat n) := +theorem sqrt_ofNat (n : ℕ) : Rat.sqrt (ofNat(n) : ℚ) = Nat.sqrt (OfNat.ofNat n) := sqrt_natCast _ end Rat diff --git a/Mathlib/Data/Real/Hyperreal.lean b/Mathlib/Data/Real/Hyperreal.lean index fd849459ea9f9..4e7a601f04cdc 100644 --- a/Mathlib/Data/Real/Hyperreal.lean +++ b/Mathlib/Data/Real/Hyperreal.lean @@ -72,10 +72,9 @@ theorem coe_neg (x : ℝ) : ↑(-x) = (-x : ℝ*) := theorem coe_add (x y : ℝ) : ↑(x + y) = (x + y : ℝ*) := rfl --- See note [no_index around OfNat.ofNat] @[simp, norm_cast] theorem coe_ofNat (n : ℕ) [n.AtLeastTwo] : - ((no_index (OfNat.ofNat n : ℝ)) : ℝ*) = OfNat.ofNat n := + ((ofNat(n) : ℝ) : ℝ*) = OfNat.ofNat n := rfl @[simp, norm_cast] diff --git a/Mathlib/Data/ZMod/IntUnitsPower.lean b/Mathlib/Data/ZMod/IntUnitsPower.lean index 61cc3341fdfc7..80e8edf23f8c4 100644 --- a/Mathlib/Data/ZMod/IntUnitsPower.lean +++ b/Mathlib/Data/ZMod/IntUnitsPower.lean @@ -71,9 +71,8 @@ example : Int.instUnitsPow = DivInvMonoid.toZPow := rfl change ((n : R) • Additive.ofMul u).toMul = _ rw [Nat.cast_smul_eq_nsmul, toMul_nsmul, toMul_ofMul] --- See note [no_index around OfNat.ofNat] lemma uzpow_coe_nat (s : ℤˣ) (n : ℕ) [n.AtLeastTwo] : - s ^ (no_index (OfNat.ofNat n : R)) = s ^ (no_index (OfNat.ofNat n : ℕ)) := + s ^ (ofNat(n) : R) = s ^ (ofNat(n) : ℕ) := uzpow_natCast _ _ @[simp] lemma one_uzpow (x : R) : (1 : ℤˣ) ^ x = 1 := diff --git a/Mathlib/LinearAlgebra/Matrix/PosDef.lean b/Mathlib/LinearAlgebra/Matrix/PosDef.lean index fb373744d8173..5e46c1956c392 100644 --- a/Mathlib/LinearAlgebra/Matrix/PosDef.lean +++ b/Mathlib/LinearAlgebra/Matrix/PosDef.lean @@ -108,9 +108,8 @@ protected theorem natCast [StarOrderedRing R] [DecidableEq n] (d : ℕ) : rw [Nat.cast_smul_eq_nsmul] exact nsmul_nonneg (dotProduct_star_self_nonneg _) _⟩ --- See note [no_index around OfNat.ofNat] protected theorem ofNat [StarOrderedRing R] [DecidableEq n] (d : ℕ) [d.AtLeastTwo] : - PosSemidef (no_index (OfNat.ofNat d) : Matrix n n R) := + PosSemidef (ofNat(d) : Matrix n n R) := .natCast d protected theorem intCast [StarOrderedRing R] [DecidableEq n] (d : ℤ) (hd : 0 ≤ d) : @@ -386,10 +385,9 @@ theorem _root_.Matrix.posDef_natCast_iff [StarOrderedRing R] [DecidableEq n] [No PosDef (d : Matrix n n R) ↔ 0 < d := posDef_diagonal_iff.trans <| by simp --- See note [no_index around OfNat.ofNat] protected theorem ofNat [StarOrderedRing R] [DecidableEq n] [NoZeroDivisors R] (d : ℕ) [d.AtLeastTwo] : - PosDef (no_index (OfNat.ofNat d) : Matrix n n R) := + PosDef (ofNat(d) : Matrix n n R) := .natCast d (NeZero.ne _) protected theorem intCast [StarOrderedRing R] [DecidableEq n] [NoZeroDivisors R] diff --git a/Mathlib/NumberTheory/LucasLehmer.lean b/Mathlib/NumberTheory/LucasLehmer.lean index 7990d0b3b0785..01356b10609e7 100644 --- a/Mathlib/NumberTheory/LucasLehmer.lean +++ b/Mathlib/NumberTheory/LucasLehmer.lean @@ -270,14 +270,12 @@ instance : NatCast (X q) where @[simp] theorem snd_natCast (n : ℕ) : (n : X q).snd = (0 : ZMod q) := rfl --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_fst (n : ℕ) [n.AtLeastTwo] : - (no_index (OfNat.ofNat n) : X q).fst = OfNat.ofNat n := + (ofNat(n) : X q).fst = OfNat.ofNat n := rfl --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_snd (n : ℕ) [n.AtLeastTwo] : - (no_index (OfNat.ofNat n) : X q).snd = 0 := + (ofNat(n) : X q).snd = 0 := rfl instance : AddGroupWithOne (X q) := diff --git a/Mathlib/NumberTheory/Padics/PadicNumbers.lean b/Mathlib/NumberTheory/Padics/PadicNumbers.lean index a2b72fdf7bbad..c03112d1c05ed 100644 --- a/Mathlib/NumberTheory/Padics/PadicNumbers.lean +++ b/Mathlib/NumberTheory/Padics/PadicNumbers.lean @@ -977,10 +977,9 @@ lemma valuation_intCast (n : ℤ) : valuation (n : ℚ_[p]) = padicValInt p n := lemma valuation_natCast (n : ℕ) : valuation (n : ℚ_[p]) = padicValNat p n := by rw [← Rat.cast_natCast, valuation_ratCast, padicValRat.of_nat] --- See note [no_index around OfNat.ofNat] @[simp] lemma valuation_ofNat (n : ℕ) [n.AtLeastTwo] : - valuation (no_index (OfNat.ofNat n : ℚ_[p])) = padicValNat p n := + valuation (ofNat(n) : ℚ_[p]) = padicValNat p n := valuation_natCast n @[simp] diff --git a/Mathlib/NumberTheory/Zsqrtd/Basic.lean b/Mathlib/NumberTheory/Zsqrtd/Basic.lean index 87f617b5528d4..5165598a7e5fe 100644 --- a/Mathlib/NumberTheory/Zsqrtd/Basic.lean +++ b/Mathlib/NumberTheory/Zsqrtd/Basic.lean @@ -230,7 +230,7 @@ theorem natCast_re (n : ℕ) : (n : ℤ√d).re = n := rfl @[simp] -theorem ofNat_re (n : ℕ) [n.AtLeastTwo] : (no_index (OfNat.ofNat n) : ℤ√d).re = n := +theorem ofNat_re (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : ℤ√d).re = n := rfl @[simp] @@ -238,7 +238,7 @@ theorem natCast_im (n : ℕ) : (n : ℤ√d).im = 0 := rfl @[simp] -theorem ofNat_im (n : ℕ) [n.AtLeastTwo] : (no_index (OfNat.ofNat n) : ℤ√d).im = 0 := +theorem ofNat_im (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : ℤ√d).im = 0 := rfl theorem natCast_val (n : ℕ) : (n : ℤ√d) = ⟨n, 0⟩ := diff --git a/Mathlib/Order/Filter/Germ/Basic.lean b/Mathlib/Order/Filter/Germ/Basic.lean index fe099e6b204fa..f02186b5a0c53 100644 --- a/Mathlib/Order/Filter/Germ/Basic.lean +++ b/Mathlib/Order/Filter/Germ/Basic.lean @@ -427,16 +427,14 @@ theorem natCast_def [NatCast M] (n : ℕ) : ((fun _ ↦ n : α → M) : Germ l M @[simp, norm_cast] theorem const_nat [NatCast M] (n : ℕ) : ((n : M) : Germ l M) = n := rfl --- See note [no_index around OfNat.ofNat] @[simp, norm_cast] theorem coe_ofNat [NatCast M] (n : ℕ) [n.AtLeastTwo] : - ((no_index (OfNat.ofNat n : α → M)) : Germ l M) = OfNat.ofNat n := + ((ofNat(n) : α → M) : Germ l M) = OfNat.ofNat n := rfl --- See note [no_index around OfNat.ofNat] @[simp, norm_cast] theorem const_ofNat [NatCast M] (n : ℕ) [n.AtLeastTwo] : - ((no_index (OfNat.ofNat n : M)) : Germ l M) = OfNat.ofNat n := + ((ofNat(n) : M) : Germ l M) = OfNat.ofNat n := rfl instance instIntCast [IntCast M] : IntCast (Germ l M) where intCast n := (n : α → M) diff --git a/Mathlib/SetTheory/Cardinal/Aleph.lean b/Mathlib/SetTheory/Cardinal/Aleph.lean index 896cc181244ef..9e69e6a4684de 100644 --- a/Mathlib/SetTheory/Cardinal/Aleph.lean +++ b/Mathlib/SetTheory/Cardinal/Aleph.lean @@ -139,9 +139,8 @@ theorem preOmega_natCast (n : ℕ) : preOmega n = n := by rw [Nat.cast_lt] exact lt_succ n --- See note [no_index around OfNat.ofNat] @[simp] -theorem preOmega_ofNat (n : ℕ) [n.AtLeastTwo] : preOmega (no_index (OfNat.ofNat n)) = n := +theorem preOmega_ofNat (n : ℕ) [n.AtLeastTwo] : preOmega ofNat(n) = n := preOmega_natCast n theorem preOmega_le_of_forall_lt {o a : Ordinal} (ha : IsInitial a) (H : ∀ b < o, preOmega b < a) : diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index e2bee0bf6130e..ca3df047a7bdc 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -1290,10 +1290,9 @@ theorem mk_fin (n : ℕ) : #(Fin n) = n := by simp @[simp] theorem lift_natCast (n : ℕ) : lift.{u} (n : Cardinal.{v}) = n := by induction n <;> simp [*] --- See note [no_index around OfNat.ofNat] @[simp] theorem lift_ofNat (n : ℕ) [n.AtLeastTwo] : - lift.{u} (no_index (OfNat.ofNat n : Cardinal.{v})) = OfNat.ofNat n := + lift.{u} (ofNat(n) : Cardinal.{v}) = OfNat.ofNat n := lift_natCast n @[simp] @@ -1302,7 +1301,7 @@ theorem lift_eq_nat_iff {a : Cardinal.{u}} {n : ℕ} : lift.{v} a = n ↔ a = n @[simp] theorem lift_eq_ofNat_iff {a : Cardinal.{u}} {n : ℕ} [n.AtLeastTwo] : - lift.{v} a = (no_index (OfNat.ofNat n)) ↔ a = OfNat.ofNat n := + lift.{v} a = ofNat(n) ↔ a = OfNat.ofNat n := lift_eq_nat_iff @[simp] @@ -1320,10 +1319,9 @@ theorem one_eq_lift_iff {a : Cardinal.{u}} : (1 : Cardinal) = lift.{v} a ↔ 1 = a := by simpa using nat_eq_lift_iff (n := 1) --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_eq_lift_iff {a : Cardinal.{u}} {n : ℕ} [n.AtLeastTwo] : - (no_index (OfNat.ofNat n : Cardinal)) = lift.{v} a ↔ (OfNat.ofNat n : Cardinal) = a := + (ofNat(n) : Cardinal) = lift.{v} a ↔ (OfNat.ofNat n : Cardinal) = a := nat_eq_lift_iff @[simp] @@ -1335,10 +1333,9 @@ theorem lift_le_one_iff {a : Cardinal.{u}} : lift.{v} a ≤ 1 ↔ a ≤ 1 := by simpa using lift_le_nat_iff (n := 1) --- See note [no_index around OfNat.ofNat] @[simp] theorem lift_le_ofNat_iff {a : Cardinal.{u}} {n : ℕ} [n.AtLeastTwo] : - lift.{v} a ≤ (no_index (OfNat.ofNat n)) ↔ a ≤ OfNat.ofNat n := + lift.{v} a ≤ ofNat(n) ↔ a ≤ OfNat.ofNat n := lift_le_nat_iff @[simp] @@ -1350,27 +1347,24 @@ theorem one_le_lift_iff {a : Cardinal.{u}} : (1 : Cardinal) ≤ lift.{v} a ↔ 1 ≤ a := by simpa using nat_le_lift_iff (n := 1) --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_le_lift_iff {a : Cardinal.{u}} {n : ℕ} [n.AtLeastTwo] : - (no_index (OfNat.ofNat n : Cardinal)) ≤ lift.{v} a ↔ (OfNat.ofNat n : Cardinal) ≤ a := + (ofNat(n) : Cardinal) ≤ lift.{v} a ↔ (OfNat.ofNat n : Cardinal) ≤ a := nat_le_lift_iff @[simp] theorem lift_lt_nat_iff {a : Cardinal.{u}} {n : ℕ} : lift.{v} a < n ↔ a < n := by rw [← lift_natCast.{v,u}, lift_lt] --- See note [no_index around OfNat.ofNat] @[simp] theorem lift_lt_ofNat_iff {a : Cardinal.{u}} {n : ℕ} [n.AtLeastTwo] : - lift.{v} a < (no_index (OfNat.ofNat n)) ↔ a < OfNat.ofNat n := + lift.{v} a < ofNat(n) ↔ a < OfNat.ofNat n := lift_lt_nat_iff @[simp] theorem nat_lt_lift_iff {n : ℕ} {a : Cardinal.{u}} : n < lift.{v} a ↔ n < a := by rw [← lift_natCast.{v,u}, lift_lt] --- See note [no_index around OfNat.ofNat] @[simp] theorem zero_lt_lift_iff {a : Cardinal.{u}} : (0 : Cardinal) < lift.{v} a ↔ 0 < a := by @@ -1381,10 +1375,9 @@ theorem one_lt_lift_iff {a : Cardinal.{u}} : (1 : Cardinal) < lift.{v} a ↔ 1 < a := by simpa using nat_lt_lift_iff (n := 1) --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_lt_lift_iff {a : Cardinal.{u}} {n : ℕ} [n.AtLeastTwo] : - (no_index (OfNat.ofNat n : Cardinal)) < lift.{v} a ↔ (OfNat.ofNat n : Cardinal) < a := + (ofNat(n) : Cardinal) < lift.{v} a ↔ (OfNat.ofNat n : Cardinal) < a := nat_lt_lift_iff theorem lift_mk_fin (n : ℕ) : lift #(Fin n) = n := rfl @@ -1718,14 +1711,12 @@ theorem nat_mul_aleph0 {n : ℕ} (hn : n ≠ 0) : ↑n * ℵ₀ = ℵ₀ := @[simp] theorem aleph0_mul_nat {n : ℕ} (hn : n ≠ 0) : ℵ₀ * n = ℵ₀ := by rw [mul_comm, nat_mul_aleph0 hn] --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_mul_aleph0 {n : ℕ} [Nat.AtLeastTwo n] : no_index (OfNat.ofNat n) * ℵ₀ = ℵ₀ := +theorem ofNat_mul_aleph0 {n : ℕ} [Nat.AtLeastTwo n] : ofNat(n) * ℵ₀ = ℵ₀ := nat_mul_aleph0 (NeZero.ne n) --- See note [no_index around OfNat.ofNat] @[simp] -theorem aleph0_mul_ofNat {n : ℕ} [Nat.AtLeastTwo n] : ℵ₀ * no_index (OfNat.ofNat n) = ℵ₀ := +theorem aleph0_mul_ofNat {n : ℕ} [Nat.AtLeastTwo n] : ℵ₀ * ofNat(n) = ℵ₀ := aleph0_mul_nat (NeZero.ne n) @[simp] @@ -1740,14 +1731,12 @@ theorem aleph0_add_nat (n : ℕ) : ℵ₀ + n = ℵ₀ := @[simp] theorem nat_add_aleph0 (n : ℕ) : ↑n + ℵ₀ = ℵ₀ := by rw [add_comm, aleph0_add_nat] --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_add_aleph0 {n : ℕ} [Nat.AtLeastTwo n] : no_index (OfNat.ofNat n) + ℵ₀ = ℵ₀ := +theorem ofNat_add_aleph0 {n : ℕ} [Nat.AtLeastTwo n] : ofNat(n) + ℵ₀ = ℵ₀ := nat_add_aleph0 n --- See note [no_index around OfNat.ofNat] @[simp] -theorem aleph0_add_ofNat {n : ℕ} [Nat.AtLeastTwo n] : ℵ₀ + no_index (OfNat.ofNat n) = ℵ₀ := +theorem aleph0_add_ofNat {n : ℕ} [Nat.AtLeastTwo n] : ℵ₀ + ofNat(n) = ℵ₀ := aleph0_add_nat n theorem exists_nat_eq_of_le_nat {c : Cardinal} {n : ℕ} (h : c ≤ n) : ∃ m, m ≤ n ∧ c = m := by @@ -2204,4 +2193,4 @@ end Cardinal -- end Tactic -set_option linter.style.longFile 2400 +set_option linter.style.longFile 2300 diff --git a/Mathlib/SetTheory/Cardinal/Continuum.lean b/Mathlib/SetTheory/Cardinal/Continuum.lean index c04a55eca2aa0..3f36674f9acb7 100644 --- a/Mathlib/SetTheory/Cardinal/Continuum.lean +++ b/Mathlib/SetTheory/Cardinal/Continuum.lean @@ -115,14 +115,12 @@ theorem nat_add_continuum (n : ℕ) : ↑n + 𝔠 = 𝔠 := theorem continuum_add_nat (n : ℕ) : 𝔠 + n = 𝔠 := (add_comm _ _).trans (nat_add_continuum n) --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_add_continuum {n : ℕ} [Nat.AtLeastTwo n] : no_index (OfNat.ofNat n) + 𝔠 = 𝔠 := +theorem ofNat_add_continuum {n : ℕ} [Nat.AtLeastTwo n] : ofNat(n) + 𝔠 = 𝔠 := nat_add_continuum n --- See note [no_index around OfNat.ofNat] @[simp] -theorem continuum_add_ofNat {n : ℕ} [Nat.AtLeastTwo n] : 𝔠 + no_index (OfNat.ofNat n) = 𝔠 := +theorem continuum_add_ofNat {n : ℕ} [Nat.AtLeastTwo n] : 𝔠 + ofNat(n) = 𝔠 := continuum_add_nat n /-! @@ -150,14 +148,12 @@ theorem nat_mul_continuum {n : ℕ} (hn : n ≠ 0) : ↑n * 𝔠 = 𝔠 := theorem continuum_mul_nat {n : ℕ} (hn : n ≠ 0) : 𝔠 * n = 𝔠 := (mul_comm _ _).trans (nat_mul_continuum hn) --- See note [no_index around OfNat.ofNat] @[simp] -theorem ofNat_mul_continuum {n : ℕ} [Nat.AtLeastTwo n] : no_index (OfNat.ofNat n) * 𝔠 = 𝔠 := +theorem ofNat_mul_continuum {n : ℕ} [Nat.AtLeastTwo n] : ofNat(n) * 𝔠 = 𝔠 := nat_mul_continuum (OfNat.ofNat_ne_zero n) --- See note [no_index around OfNat.ofNat] @[simp] -theorem continuum_mul_ofNat {n : ℕ} [Nat.AtLeastTwo n] : 𝔠 * no_index (OfNat.ofNat n) = 𝔠 := +theorem continuum_mul_ofNat {n : ℕ} [Nat.AtLeastTwo n] : 𝔠 * ofNat(n) = 𝔠 := continuum_mul_nat (OfNat.ofNat_ne_zero n) /-! diff --git a/Mathlib/SetTheory/Cardinal/ENat.lean b/Mathlib/SetTheory/Cardinal/ENat.lean index b444b8fb5cd1f..5ad5cee75b2b2 100644 --- a/Mathlib/SetTheory/Cardinal/ENat.lean +++ b/Mathlib/SetTheory/Cardinal/ENat.lean @@ -48,7 +48,7 @@ instance : Coe ENat Cardinal := ⟨Cardinal.ofENat⟩ @[simp, norm_cast] lemma ofENat_one : ofENat 1 = 1 := rfl @[simp, norm_cast] lemma ofENat_ofNat (n : ℕ) [n.AtLeastTwo] : - ((no_index (OfNat.ofNat n : ℕ∞)) : Cardinal) = OfNat.ofNat n := + ((ofNat(n) : ℕ∞) : Cardinal) = OfNat.ofNat n := rfl lemma ofENat_strictMono : StrictMono ofENat := @@ -67,14 +67,14 @@ lemma ofENat_lt_aleph0 {m : ℕ∞} : (m : Cardinal) < ℵ₀ ↔ m < ⊤ := @[simp] lemma ofENat_lt_nat {m : ℕ∞} {n : ℕ} : ofENat m < n ↔ m < n := by norm_cast @[simp] lemma ofENat_lt_ofNat {m : ℕ∞} {n : ℕ} [n.AtLeastTwo] : - ofENat m < no_index (OfNat.ofNat n) ↔ m < OfNat.ofNat n := ofENat_lt_nat + ofENat m < ofNat(n) ↔ m < OfNat.ofNat n := ofENat_lt_nat @[simp] lemma nat_lt_ofENat {m : ℕ} {n : ℕ∞} : (m : Cardinal) < n ↔ m < n := by norm_cast @[simp] lemma ofENat_pos {m : ℕ∞} : 0 < (m : Cardinal) ↔ 0 < m := by norm_cast @[simp] lemma one_lt_ofENat {m : ℕ∞} : 1 < (m : Cardinal) ↔ 1 < m := by norm_cast @[simp, norm_cast] lemma ofNat_lt_ofENat {m : ℕ} [m.AtLeastTwo] {n : ℕ∞} : - no_index (OfNat.ofNat m : Cardinal) < n ↔ OfNat.ofNat m < n := nat_lt_ofENat + (ofNat(m) : Cardinal) < n ↔ OfNat.ofNat m < n := nat_lt_ofENat lemma ofENat_mono : Monotone ofENat := ofENat_strictMono.monotone @@ -88,14 +88,14 @@ lemma ofENat_le_ofENat {m n : ℕ∞} : (m : Cardinal) ≤ n ↔ m ≤ n := ofEN @[simp] lemma ofENat_le_one {m : ℕ∞} : ofENat m ≤ 1 ↔ m ≤ 1 := by norm_cast @[simp] lemma ofENat_le_ofNat {m : ℕ∞} {n : ℕ} [n.AtLeastTwo] : - ofENat m ≤ no_index (OfNat.ofNat n) ↔ m ≤ OfNat.ofNat n := ofENat_le_nat + ofENat m ≤ ofNat(n) ↔ m ≤ OfNat.ofNat n := ofENat_le_nat @[simp] lemma nat_le_ofENat {m : ℕ} {n : ℕ∞} : (m : Cardinal) ≤ n ↔ m ≤ n := by norm_cast @[simp] lemma one_le_ofENat {n : ℕ∞} : 1 ≤ (n : Cardinal) ↔ 1 ≤ n := by norm_cast @[simp] lemma ofNat_le_ofENat {m : ℕ} [m.AtLeastTwo] {n : ℕ∞} : - no_index (OfNat.ofNat m : Cardinal) ≤ n ↔ OfNat.ofNat m ≤ n := nat_le_ofENat + (ofNat(m) : Cardinal) ≤ n ↔ OfNat.ofNat m ≤ n := nat_le_ofENat lemma ofENat_injective : Injective ofENat := ofENat_strictMono.injective @@ -112,10 +112,10 @@ lemma ofENat_inj {m n : ℕ∞} : (m : Cardinal) = n ↔ m = n := ofENat_injecti @[simp] lemma one_eq_ofENat {m : ℕ∞} : 1 = (m : Cardinal) ↔ m = 1 := by norm_cast; apply eq_comm @[simp] lemma ofENat_eq_ofNat {m : ℕ∞} {n : ℕ} [n.AtLeastTwo] : - (m : Cardinal) = no_index (OfNat.ofNat n) ↔ m = OfNat.ofNat n := ofENat_eq_nat + (m : Cardinal) = ofNat(n) ↔ m = OfNat.ofNat n := ofENat_eq_nat @[simp] lemma ofNat_eq_ofENat {m : ℕ} {n : ℕ∞} [m.AtLeastTwo] : - no_index (OfNat.ofNat m) = (n : Cardinal) ↔ OfNat.ofNat m = n := nat_eq_ofENat + ofNat(m) = (n : Cardinal) ↔ OfNat.ofNat m = n := nat_eq_ofENat @[simp, norm_cast] lemma lift_ofENat : ∀ m : ℕ∞, lift.{u, v} m = m | (m : ℕ) => lift_natCast m @@ -247,10 +247,10 @@ lemma toENat_nat (n : ℕ) : toENat n = n := map_natCast _ n @[simp] lemma toENat_eq_one {a : Cardinal} : toENat a = 1 ↔ a = 1 := toENat_eq_nat @[simp] lemma toENat_le_ofNat {a : Cardinal} {n : ℕ} [n.AtLeastTwo] : - toENat a ≤ no_index (OfNat.ofNat n) ↔ a ≤ OfNat.ofNat n := toENat_le_nat + toENat a ≤ ofNat(n) ↔ a ≤ OfNat.ofNat n := toENat_le_nat @[simp] lemma toENat_eq_ofNat {a : Cardinal} {n : ℕ} [n.AtLeastTwo] : - toENat a = no_index (OfNat.ofNat n) ↔ a = OfNat.ofNat n := toENat_eq_nat + toENat a = ofNat(n) ↔ a = OfNat.ofNat n := toENat_eq_nat @[simp] lemma toENat_eq_top {a : Cardinal} : toENat a = ⊤ ↔ ℵ₀ ≤ a := enat_gc.u_eq_top diff --git a/Mathlib/SetTheory/Cardinal/ToNat.lean b/Mathlib/SetTheory/Cardinal/ToNat.lean index 80d792d3f53b3..296a181875639 100644 --- a/Mathlib/SetTheory/Cardinal/ToNat.lean +++ b/Mathlib/SetTheory/Cardinal/ToNat.lean @@ -85,10 +85,9 @@ theorem toNat_le_toNat (hcd : c ≤ d) (hd : d < ℵ₀) : toNat c ≤ toNat d : theorem toNat_lt_toNat (hcd : c < d) (hd : d < ℵ₀) : toNat c < toNat d := toNat_strictMonoOn (hcd.trans hd) hd hcd --- See note [no_index around OfNat.ofNat] @[simp] theorem toNat_ofNat (n : ℕ) [n.AtLeastTwo] : - Cardinal.toNat (no_index (OfNat.ofNat n)) = OfNat.ofNat n := + Cardinal.toNat ofNat(n) = OfNat.ofNat n := toNat_natCast n /-- `toNat` has a right-inverse: coercion. -/ diff --git a/Mathlib/SetTheory/Game/Birthday.lean b/Mathlib/SetTheory/Game/Birthday.lean index c0da2ca0c18a8..09a00361b6f86 100644 --- a/Mathlib/SetTheory/Game/Birthday.lean +++ b/Mathlib/SetTheory/Game/Birthday.lean @@ -215,10 +215,9 @@ theorem birthday_natCast (n : ℕ) : birthday n = n := by rw [← toGame_natCast] exact birthday_ordinalToGame _ --- See note [no_index around OfNat.ofNat] @[simp] theorem birthday_ofNat (n : ℕ) [n.AtLeastTwo] : - birthday (no_index (OfNat.ofNat n)) = OfNat.ofNat n := + birthday ofNat(n) = OfNat.ofNat n := birthday_natCast n @[simp] diff --git a/Mathlib/SetTheory/Game/Short.lean b/Mathlib/SetTheory/Game/Short.lean index 0fd2f40701cd5..8ff13c9c88a07 100644 --- a/Mathlib/SetTheory/Game/Short.lean +++ b/Mathlib/SetTheory/Game/Short.lean @@ -209,7 +209,7 @@ instance shortNat : ∀ n : ℕ, Short n | 0 => PGame.short0 | n + 1 => @PGame.shortAdd _ _ (shortNat n) PGame.short1 -instance shortOfNat (n : ℕ) [Nat.AtLeastTwo n] : Short (no_index (OfNat.ofNat n)) := shortNat n +instance shortOfNat (n : ℕ) [Nat.AtLeastTwo n] : Short ofNat(n) := shortNat n instance shortBit0 (x : PGame.{u}) [Short x] : Short (x + x) := by infer_instance diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index c914bbd405ef9..058fe74f9c6cc 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -2243,10 +2243,9 @@ theorem one_add_natCast (m : ℕ) : 1 + (m : Ordinal) = succ m := by @[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias one_add_nat_cast := one_add_natCast --- See note [no_index around OfNat.ofNat] @[simp] theorem one_add_ofNat (m : ℕ) [m.AtLeastTwo] : - 1 + (no_index (OfNat.ofNat m : Ordinal)) = Order.succ (OfNat.ofNat m : Ordinal) := + 1 + (ofNat(m) : Ordinal) = Order.succ (OfNat.ofNat m : Ordinal) := one_add_natCast m @[simp, norm_cast] @@ -2334,10 +2333,9 @@ theorem lift_natCast : ∀ n : ℕ, lift.{u, v} n = n @[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias lift_nat_cast := lift_natCast --- See note [no_index around OfNat.ofNat] @[simp] theorem lift_ofNat (n : ℕ) [n.AtLeastTwo] : - lift.{u, v} (no_index (OfNat.ofNat n)) = OfNat.ofNat n := + lift.{u, v} ofNat(n) = OfNat.ofNat n := lift_natCast n /-! ### Properties of ω -/ diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 33a1d3e36a834..7f225262b4727 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -867,10 +867,9 @@ theorem type_sum_lex {α β : Type u} (r : α → α → Prop) (s : β → β theorem card_nat (n : ℕ) : card.{u} n = n := by induction n <;> [simp; simp only [card_add, card_one, Nat.cast_succ, *]] --- See note [no_index around OfNat.ofNat] @[simp] theorem card_ofNat (n : ℕ) [n.AtLeastTwo] : - card.{u} (no_index (OfNat.ofNat n)) = OfNat.ofNat n := + card.{u} ofNat(n) = OfNat.ofNat n := card_nat n instance instAddLeftMono : AddLeftMono Ordinal.{u} where @@ -1211,9 +1210,8 @@ theorem ord_nat (n : ℕ) : ord n = n := @[simp] theorem ord_one : ord 1 = 1 := by simpa using ord_nat 1 --- See note [no_index around OfNat.ofNat] @[simp] -theorem ord_ofNat (n : ℕ) [n.AtLeastTwo] : ord (no_index (OfNat.ofNat n)) = OfNat.ofNat n := +theorem ord_ofNat (n : ℕ) [n.AtLeastTwo] : ord ofNat(n) = OfNat.ofNat n := ord_nat n @[simp] @@ -1378,10 +1376,9 @@ theorem nat_le_card {o} {n : ℕ} : (n : Cardinal) ≤ card o ↔ (n : Ordinal) theorem one_le_card {o} : 1 ≤ card o ↔ 1 ≤ o := by simpa using nat_le_card (n := 1) --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_le_card {o} {n : ℕ} [n.AtLeastTwo] : - (no_index (OfNat.ofNat n : Cardinal)) ≤ card o ↔ (OfNat.ofNat n : Ordinal) ≤ o := + (ofNat(n) : Cardinal) ≤ card o ↔ (OfNat.ofNat n : Ordinal) ≤ o := nat_le_card @[simp] @@ -1405,20 +1402,18 @@ theorem zero_lt_card {o} : 0 < card o ↔ 0 < o := by theorem one_lt_card {o} : 1 < card o ↔ 1 < o := by simpa using nat_lt_card (n := 1) --- See note [no_index around OfNat.ofNat] @[simp] theorem ofNat_lt_card {o} {n : ℕ} [n.AtLeastTwo] : - (no_index (OfNat.ofNat n : Cardinal)) < card o ↔ (OfNat.ofNat n : Ordinal) < o := + (ofNat(n) : Cardinal) < card o ↔ (OfNat.ofNat n : Ordinal) < o := nat_lt_card @[simp] theorem card_lt_nat {o} {n : ℕ} : card o < n ↔ o < n := lt_iff_lt_of_le_iff_le nat_le_card --- See note [no_index around OfNat.ofNat] @[simp] theorem card_lt_ofNat {o} {n : ℕ} [n.AtLeastTwo] : - card o < (no_index (OfNat.ofNat n)) ↔ o < OfNat.ofNat n := + card o < ofNat(n) ↔ o < OfNat.ofNat n := card_lt_nat @[simp] @@ -1429,10 +1424,9 @@ theorem card_le_nat {o} {n : ℕ} : card o ≤ n ↔ o ≤ n := theorem card_le_one {o} : card o ≤ 1 ↔ o ≤ 1 := by simpa using card_le_nat (n := 1) --- See note [no_index around OfNat.ofNat] @[simp] theorem card_le_ofNat {o} {n : ℕ} [n.AtLeastTwo] : - card o ≤ (no_index (OfNat.ofNat n)) ↔ o ≤ OfNat.ofNat n := + card o ≤ ofNat(n) ↔ o ≤ OfNat.ofNat n := card_le_nat @[simp] @@ -1457,10 +1451,9 @@ theorem lift_down' {a : Cardinal.{u}} {b : Ordinal.{max u v}} (h : card.{max u v} b ≤ Cardinal.lift.{v, u} a) : ∃ a', lift.{v, u} a' = b := mem_range_lift_of_card_le h --- See note [no_index around OfNat.ofNat] @[simp] theorem card_eq_ofNat {o} {n : ℕ} [n.AtLeastTwo] : - card o = (no_index (OfNat.ofNat n)) ↔ o = OfNat.ofNat n := + card o = ofNat(n) ↔ o = OfNat.ofNat n := card_eq_nat @[simp] diff --git a/Mathlib/Tactic/NoncommRing.lean b/Mathlib/Tactic/NoncommRing.lean index 7cced4a61594d..ad1410a6f8acb 100644 --- a/Mathlib/Tactic/NoncommRing.lean +++ b/Mathlib/Tactic/NoncommRing.lean @@ -23,9 +23,9 @@ namespace Mathlib.Tactic.NoncommRing section nat_lit_mul variable {R : Type*} [NonAssocSemiring R] (r : R) (n : ℕ) -lemma nat_lit_mul_eq_nsmul [n.AtLeastTwo] : no_index (OfNat.ofNat n) * r = OfNat.ofNat n • r := by +lemma nat_lit_mul_eq_nsmul [n.AtLeastTwo] : ofNat(n) * r = OfNat.ofNat n • r := by simp only [nsmul_eq_mul, Nat.cast_ofNat] -lemma mul_nat_lit_eq_nsmul [n.AtLeastTwo] : r * no_index (OfNat.ofNat n) = OfNat.ofNat n • r := by +lemma mul_nat_lit_eq_nsmul [n.AtLeastTwo] : r * ofNat(n) = OfNat.ofNat n • r := by simp only [nsmul_eq_mul', Nat.cast_ofNat] end nat_lit_mul diff --git a/Mathlib/Tactic/Ring/PNat.lean b/Mathlib/Tactic/Ring/PNat.lean index d5e2883e3d672..c37b0078f5085 100644 --- a/Mathlib/Tactic/Ring/PNat.lean +++ b/Mathlib/Tactic/Ring/PNat.lean @@ -25,6 +25,7 @@ instance {n} : CSLiftVal (no_index (OfNat.ofNat (n+1)) : ℕ+) (n + 1) := ⟨rfl instance {n h} : CSLiftVal (Nat.toPNat n h) n := ⟨rfl⟩ + instance {n} : CSLiftVal (Nat.succPNat n) (n + 1) := ⟨rfl⟩ instance {n} : CSLiftVal (Nat.toPNat' n) (n.pred + 1) := ⟨rfl⟩ diff --git a/Mathlib/Topology/Algebra/Module/LinearMap.lean b/Mathlib/Topology/Algebra/Module/LinearMap.lean index 48a01db20692e..c11c4e9d10354 100644 --- a/Mathlib/Topology/Algebra/Module/LinearMap.lean +++ b/Mathlib/Topology/Algebra/Module/LinearMap.lean @@ -505,7 +505,7 @@ theorem natCast_apply [ContinuousAdd M₁] (n : ℕ) (m : M₁) : (↑n : M₁ @[simp] theorem ofNat_apply [ContinuousAdd M₁] (n : ℕ) [n.AtLeastTwo] (m : M₁) : - ((no_index (OfNat.ofNat n) : M₁ →L[R₁] M₁)) m = OfNat.ofNat n • m := + (ofNat(n) : M₁ →L[R₁] M₁) m = OfNat.ofNat n • m := rfl section ApplyAction diff --git a/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean b/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean index 14e8443fb52c5..536e68588f287 100644 --- a/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean +++ b/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean @@ -268,7 +268,7 @@ theorem mk_natCast [NatCast R] (n : ℕ) : mk (n : R) = n := rfl @[simp] theorem mk_ofNat [NatCast R] (n : ℕ) [n.AtLeastTwo] : - mk (no_index (OfNat.ofNat n) : R) = OfNat.ofNat n := + mk (ofNat(n) : R) = OfNat.ofNat n := rfl instance instIntCast [IntCast R] : IntCast (SeparationQuotient R) where diff --git a/scripts/technical-debt-metrics.sh b/scripts/technical-debt-metrics.sh index 7c982cadbcb20..b3f3df14ec9aa 100755 --- a/scripts/technical-debt-metrics.sh +++ b/scripts/technical-debt-metrics.sh @@ -80,7 +80,6 @@ titlesPathsAndRegexes=( "adaptation notes" "*" "adaptation_note" "disabled simpNF lints" "*" "nolint simpNF" "erw" "*" "erw \[" - "ofNat" "*" "See note \[no_index around OfNat.ofNat\]" "maxHeartBeats modifications" ":^MathlibTest" "^ *set_option .*maxHeartbeats" ) From 3f719dcdfa9d6f09d02d04c14417d89bff149f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 7 Jan 2025 10:10:14 +0000 Subject: [PATCH 040/681] =?UTF-8?q?feat(Order/SuccPred/CompleteLinearOrder?= =?UTF-8?q?):=20`=E2=A8=86=20a=20<=20x,=20succ=20a=20=3D=20x`=20(#19970)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/Order/SuccPred/CompleteLinearOrder.lean | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Mathlib/Order/SuccPred/CompleteLinearOrder.lean b/Mathlib/Order/SuccPred/CompleteLinearOrder.lean index 748703d2d7787..66897b1f54ac7 100644 --- a/Mathlib/Order/SuccPred/CompleteLinearOrder.lean +++ b/Mathlib/Order/SuccPred/CompleteLinearOrder.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ +import Mathlib.Order.ConditionallyCompleteLattice.Indexed import Mathlib.Order.SuccPred.Limit /-! @@ -164,6 +165,15 @@ theorem sSup_Iio_eq_self_iff_isSuccPrelimit : sSup (Iio x) = x ↔ IsSuccPrelimi theorem iSup_Iio_eq_self_iff_isSuccPrelimit : ⨆ a : Iio x, a.1 = x ↔ IsSuccPrelimit x := by rw [← sSup_eq_iSup', sSup_Iio_eq_self_iff_isSuccPrelimit] +theorem iSup_succ [SuccOrder α] (x : α) : ⨆ a : Iio x, succ a.1 = x := by + have H : BddAbove (range fun a : Iio x ↦ succ a.1) := + ⟨succ x, by simp +contextual [upperBounds, succ_le_succ, le_of_lt]⟩ + apply le_antisymm _ (le_of_forall_lt fun y hy ↦ ?_) + · rw [ciSup_le_iff' H] + exact fun a ↦ succ_le_of_lt a.2 + · rw [lt_ciSup_iff' H] + exact ⟨⟨y, hy⟩, lt_succ_of_not_isMax hy.not_isMax⟩ + end ConditionallyCompleteLinearOrderBot section CompleteLinearOrder From 6116172428677f7c5f1dbbc2dfbeea4d0f4cde3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 7 Jan 2025 10:10:15 +0000 Subject: [PATCH 041/681] chore(BooleanSubalgebra): use `IsSublattice` in `closure_sdiff_sup_induction` (#20439) and make the `x` argument explicit. This is nicer to use with `induction`. From GrowthInGroups (LeanCamCombi) --- Mathlib/Order/BooleanSubalgebra.lean | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Mathlib/Order/BooleanSubalgebra.lean b/Mathlib/Order/BooleanSubalgebra.lean index 4419c6cc58077..f26406cb0a2f0 100644 --- a/Mathlib/Order/BooleanSubalgebra.lean +++ b/Mathlib/Order/BooleanSubalgebra.lean @@ -363,8 +363,8 @@ lemma closure_bot_sup_induction {p : ∀ g ∈ closure s, Prop} (mem : ∀ x hx, section sdiff_sup -variable (sup : SupClosed s) (inf : InfClosed s) (bot_mem : ⊥ ∈ s) (top_mem : ⊤ ∈ s) -include sup inf bot_mem top_mem +variable (isSublattice : IsSublattice s) (bot_mem : ⊥ ∈ s) (top_mem : ⊤ ∈ s) +include isSublattice bot_mem top_mem theorem mem_closure_iff_sup_sdiff {a : α} : a ∈ closure s ↔ ∃ t : Finset (s × s), a = t.sup fun x ↦ x.1.1 \ x.2.1 := by @@ -381,21 +381,21 @@ theorem mem_closure_iff_sup_sdiff {a : α} : simp_rw [Finset.sup_insert, compl_sup, eq] refine tc.induction ⟨∅, by simp⟩ fun ⟨z, w⟩ tc _ ⟨t, eq⟩ ↦ ?_ simp_rw [Finset.sup_insert, inf_sup_left, eq] - refine ⟨{(z, ⟨_, sup x.2 w.2⟩), (⟨_, inf y.2 z.2⟩, w)} ∪ t, ?_⟩ + use {(z, ⟨_, isSublattice.supClosed x.2 w.2⟩), (⟨_, isSublattice.infClosed y.2 z.2⟩, w)} ∪ t simp_rw [Finset.sup_union, Finset.sup_insert, Finset.sup_singleton, sdiff_eq, compl_sup, inf_left_comm z.1, compl_inf, compl_compl, inf_sup_right, inf_assoc] @[elab_as_elim] theorem closure_sdiff_sup_induction {p : ∀ g ∈ closure s, Prop} (sdiff : ∀ x hx y hy, p (x \ y) (sdiff_mem (subset_closure hx) (subset_closure hy))) - (sup' : ∀ x hx y hy, p x hx → p y hy → p (x ⊔ y) (sup_mem hx hy)) - {x} (hx : x ∈ closure s) : p x hx := by - obtain ⟨t, rfl⟩ := (mem_closure_iff_sup_sdiff sup inf bot_mem top_mem).mp hx + (sup : ∀ x hx y hy, p x hx → p y hy → p (x ⊔ y) (sup_mem hx hy)) + (x) (hx : x ∈ closure s) : p x hx := by + obtain ⟨t, rfl⟩ := (mem_closure_iff_sup_sdiff isSublattice bot_mem top_mem).mp hx revert hx classical refine t.induction (by simpa using sdiff _ bot_mem _ bot_mem) fun x t _ ih hxt ↦ ?_ simp only [Finset.sup_insert] at hxt ⊢ - exact sup' _ _ _ _ (sdiff _ x.1.2 _ x.2.2) - (ih <| (mem_closure_iff_sup_sdiff sup inf bot_mem top_mem).mpr ⟨_, rfl⟩) + exact sup _ _ _ ((mem_closure_iff_sup_sdiff isSublattice bot_mem top_mem).mpr ⟨_, rfl⟩) + (sdiff _ x.1.2 _ x.2.2) (ih _) end sdiff_sup From 16ed2398d056856086ed12ecef0600f1178f89e0 Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Tue, 7 Jan 2025 11:30:05 +0000 Subject: [PATCH 042/681] feat(RingTheory): being unramified is a local property (#20323) Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib.lean | 3 + Mathlib/RingTheory/Etale/Kaehler.lean | 53 ++++++++++ Mathlib/RingTheory/RingHom/Unramified.lean | 111 +++++++++++++++++++++ Mathlib/RingTheory/Smooth/Kaehler.lean | 3 + Mathlib/RingTheory/Unramified/Basic.lean | 3 +- Mathlib/RingTheory/Unramified/Locus.lean | 62 ++++++++++++ 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 Mathlib/RingTheory/Etale/Kaehler.lean create mode 100644 Mathlib/RingTheory/RingHom/Unramified.lean create mode 100644 Mathlib/RingTheory/Unramified/Locus.lean diff --git a/Mathlib.lean b/Mathlib.lean index 29d5ad6bf01f8..2f8cc2a277bfb 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4392,6 +4392,7 @@ import Mathlib.RingTheory.EisensteinCriterion import Mathlib.RingTheory.EssentialFiniteness import Mathlib.RingTheory.Etale.Basic import Mathlib.RingTheory.Etale.Field +import Mathlib.RingTheory.Etale.Kaehler import Mathlib.RingTheory.Etale.Pi import Mathlib.RingTheory.EuclideanDomain import Mathlib.RingTheory.Extension @@ -4647,6 +4648,7 @@ import Mathlib.RingTheory.RingHom.Integral import Mathlib.RingTheory.RingHom.Locally import Mathlib.RingTheory.RingHom.StandardSmooth import Mathlib.RingTheory.RingHom.Surjective +import Mathlib.RingTheory.RingHom.Unramified import Mathlib.RingTheory.RingHomProperties import Mathlib.RingTheory.RingInvo import Mathlib.RingTheory.RootsOfUnity.AlgebraicallyClosed @@ -4696,6 +4698,7 @@ import Mathlib.RingTheory.UniqueFactorizationDomain.NormalizedFactors import Mathlib.RingTheory.Unramified.Basic import Mathlib.RingTheory.Unramified.Field import Mathlib.RingTheory.Unramified.Finite +import Mathlib.RingTheory.Unramified.Locus import Mathlib.RingTheory.Unramified.Pi import Mathlib.RingTheory.Valuation.AlgebraInstances import Mathlib.RingTheory.Valuation.Basic diff --git a/Mathlib/RingTheory/Etale/Kaehler.lean b/Mathlib/RingTheory/Etale/Kaehler.lean new file mode 100644 index 0000000000000..509af402e838f --- /dev/null +++ b/Mathlib/RingTheory/Etale/Kaehler.lean @@ -0,0 +1,53 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.RingTheory.Etale.Basic +import Mathlib.RingTheory.Kaehler.JacobiZariski +import Mathlib.RingTheory.Localization.BaseChange +import Mathlib.RingTheory.Smooth.Kaehler + +/-! +# The differential module and etale algebras + +## Main results +`KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale`: +The canonical isomorphism `T ⊗[S] Ω[S⁄R] ≃ₗ[T] Ω[T⁄R]` for `T` a formally etale `S`-algebra. +-/ + +universe u + +variable (R S T : Type u) [CommRing R] [CommRing S] [CommRing T] +variable [Algebra R S] [Algebra R T] [Algebra S T] [IsScalarTower R S T] + +open TensorProduct + +/-- +The canonical isomorphism `T ⊗[S] Ω[S⁄R] ≃ₗ[T] Ω[T⁄R]` for `T` a formally etale `S`-algebra. +Also see `S ⊗[R] Ω[A⁄R] ≃ₗ[S] Ω[S ⊗[R] A⁄S]` at `KaehlerDifferential.tensorKaehlerEquiv`. +-/ +@[simps! apply] noncomputable +def KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale [Algebra.FormallyEtale S T] : + T ⊗[S] Ω[S⁄R] ≃ₗ[T] Ω[T⁄R] := by + refine LinearEquiv.ofBijective (mapBaseChange R S T) + ⟨?_, fun x ↦ (KaehlerDifferential.exact_mapBaseChange_map R S T x).mp (Subsingleton.elim _ _)⟩ + rw [injective_iff_map_eq_zero] + intros x hx + obtain ⟨x, rfl⟩ := (Algebra.H1Cotangent.exact_δ_mapBaseChange R S T x).mp hx + rw [Subsingleton.elim x 0, map_zero] + +lemma KaehlerDifferential.isBaseChange_of_formallyEtale [Algebra.FormallyEtale S T] : + IsBaseChange T (map R R S T) := by + show Function.Bijective _ + convert (tensorKaehlerEquivOfFormallyEtale R S T).bijective using 1 + show _ = ((tensorKaehlerEquivOfFormallyEtale + R S T).toLinearMap.restrictScalars S : T ⊗[S] Ω[S⁄R] → _) + congr! + ext + simp + +instance KaehlerDifferential.isLocalizedModule_map (M : Submonoid S) [IsLocalization M T] : + IsLocalizedModule M (map R R S T) := + have := Algebra.FormallyEtale.of_isLocalization (Rₘ := T) M + (isLocalizedModule_iff_isBaseChange M T _).mpr (isBaseChange_of_formallyEtale R S T) diff --git a/Mathlib/RingTheory/RingHom/Unramified.lean b/Mathlib/RingTheory/RingHom/Unramified.lean new file mode 100644 index 0000000000000..1016996901edb --- /dev/null +++ b/Mathlib/RingTheory/RingHom/Unramified.lean @@ -0,0 +1,111 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.RingTheory.Unramified.Locus +import Mathlib.RingTheory.LocalProperties.Basic + +/-! + +# The meta properties of unramified ring homomorphisms. + +-/ + +namespace RingHom + +variable {R : Type*} {S : Type*} [CommRing R] [CommRing S] + +/-- +A ring homomorphism `R →+* A` is formally unramified if `Ω[A⁄R]` is trivial. +See `Algebra.FormallyUnramified`. +-/ +@[algebraize Algebra.FormallyUnramified] +def FormallyUnramified (f : R →+* S) : Prop := + letI := f.toAlgebra + Algebra.FormallyUnramified R S + +lemma formallyUnramified_algebraMap [Algebra R S] : + (algebraMap R S).FormallyUnramified ↔ Algebra.FormallyUnramified R S := by + delta FormallyUnramified + congr! + exact Algebra.algebra_ext _ _ fun _ ↦ rfl + +namespace FormallyUnramified + +lemma stableUnderComposition : + StableUnderComposition FormallyUnramified := by + intros R S T _ _ _ f g _ _ + algebraize [f, g, g.comp f] + exact .comp R S T + +lemma respectsIso : + RespectsIso FormallyUnramified := by + refine stableUnderComposition.respectsIso ?_ + intros R S _ _ e + letI := e.toRingHom.toAlgebra + exact Algebra.FormallyUnramified.of_surjective (Algebra.ofId R S) e.surjective + +lemma isStableUnderBaseChange : + IsStableUnderBaseChange FormallyUnramified := by + refine .mk _ respectsIso ?_ + intros R S T _ _ _ _ _ h + show (algebraMap _ _).FormallyUnramified + rw [formallyUnramified_algebraMap] at h ⊢ + infer_instance + +lemma holdsForLocalizationAway : + HoldsForLocalizationAway FormallyUnramified := by + intros R S _ _ _ r _ + rw [formallyUnramified_algebraMap] + exact .of_isLocalization (.powers r) + +lemma ofLocalizationPrime : + OfLocalizationPrime FormallyUnramified := by + intros R S _ _ f H + algebraize [f] + rw [FormallyUnramified, ← Algebra.unramifiedLocus_eq_univ_iff, Set.eq_univ_iff_forall] + intro x + let Rₓ := Localization.AtPrime (x.asIdeal.comap f) + let Sₓ := Localization.AtPrime x.asIdeal + have := Algebra.FormallyUnramified.of_isLocalization (Rₘ := Rₓ) (x.asIdeal.comap f).primeCompl + letI : Algebra Rₓ Sₓ := (Localization.localRingHom _ _ _ rfl).toAlgebra + have : IsScalarTower R Rₓ Sₓ := .of_algebraMap_eq + fun x ↦ (Localization.localRingHom_to_map _ _ _ rfl x).symm + have : Algebra.FormallyUnramified Rₓ Sₓ := H _ _ + exact Algebra.FormallyUnramified.comp R Rₓ Sₓ + +lemma ofLocalizationSpanTarget : + OfLocalizationSpanTarget FormallyUnramified := by + intros R S _ _ f s hs H + algebraize [f] + rw [FormallyUnramified, ← Algebra.unramifiedLocus_eq_univ_iff, Set.eq_univ_iff_forall] + intro x + obtain ⟨r, hr, hrx⟩ : ∃ r ∈ s, x ∈ PrimeSpectrum.basicOpen r := by + simpa using (PrimeSpectrum.iSup_basicOpen_eq_top_iff'.mpr hs).ge + (TopologicalSpace.Opens.mem_top x) + refine Algebra.basicOpen_subset_unramifiedLocus_iff.mpr ?_ hrx + convert H ⟨r, hr⟩ + dsimp + rw [← algebraMap_toAlgebra f, ← IsScalarTower.algebraMap_eq, + formallyUnramified_algebraMap] + +lemma propertyIsLocal : + PropertyIsLocal FormallyUnramified := by + constructor + · intro R S _ _ f r R' S' _ _ _ _ _ _ H + algebraize [f, (algebraMap S S').comp f, IsLocalization.Away.map R' S' f r] + have := Algebra.FormallyUnramified.of_isLocalization (Rₘ := S') (.powers (f r)) + have := Algebra.FormallyUnramified.comp R S S' + have H : Submonoid.powers r ≤ (Submonoid.powers (f r)).comap f := by + rintro x ⟨n, rfl⟩; exact ⟨n, by simp⟩ + have : IsScalarTower R R' S' := .of_algebraMap_eq' (IsLocalization.map_comp H).symm + exact Algebra.FormallyUnramified.of_comp R R' S' + · exact ofLocalizationSpanTarget + · exact ofLocalizationSpanTarget.ofLocalizationSpan + (stableUnderComposition.stableUnderCompositionWithLocalizationAway + holdsForLocalizationAway).1 + · exact (stableUnderComposition.stableUnderCompositionWithLocalizationAway + holdsForLocalizationAway).2 + +end RingHom.FormallyUnramified diff --git a/Mathlib/RingTheory/Smooth/Kaehler.lean b/Mathlib/RingTheory/Smooth/Kaehler.lean index 780d71c547b67..089823b7d0f64 100644 --- a/Mathlib/RingTheory/Smooth/Kaehler.lean +++ b/Mathlib/RingTheory/Smooth/Kaehler.lean @@ -447,3 +447,6 @@ theorem Algebra.FormallySmooth.iff_subsingleton_and_projective : show Function.Injective (Generators.self R S).toExtension.cotangentComplex ↔ _ rw [← LinearMap.ker_eq_bot, ← Submodule.subsingleton_iff_eq_bot] rfl + +instance [Algebra.FormallySmooth R S] : Subsingleton (Algebra.H1Cotangent R S) := + (Algebra.FormallySmooth.iff_subsingleton_and_projective.mp ‹_›).1 diff --git a/Mathlib/RingTheory/Unramified/Basic.lean b/Mathlib/RingTheory/Unramified/Basic.lean index 81416a42263dc..9e91002b6692d 100644 --- a/Mathlib/RingTheory/Unramified/Basic.lean +++ b/Mathlib/RingTheory/Unramified/Basic.lean @@ -39,8 +39,7 @@ namespace Algebra section -variable (R : Type v) [CommRing R] -variable (A : Type u) [CommRing A] [Algebra R A] +variable (R : Type v) (A : Type u) [CommRing R] [CommRing A] [Algebra R A] /-- An `R`-algebra `A` is formally unramified if `Ω[A⁄R]` is trivial. diff --git a/Mathlib/RingTheory/Unramified/Locus.lean b/Mathlib/RingTheory/Unramified/Locus.lean new file mode 100644 index 0000000000000..ec9cd9995a51e --- /dev/null +++ b/Mathlib/RingTheory/Unramified/Locus.lean @@ -0,0 +1,62 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic +import Mathlib.RingTheory.Etale.Kaehler +import Mathlib.RingTheory.Support + +/-! +# Unramified locus of an algebra + +## Main results +- `Algebra.unramifiedLocus` : The set of primes that is unramified over the base. +- `Algebra.basicOpen_subset_unramifiedLocus_iff` : + `D(f)` is contained in the unramified locus if and only if `A_f` is unramified over `R`. +- `Algebra.unramifiedLocus_eq_univ_iff` : + The unramified locus is the whole spectrum if and only if `A` is unramified over `R`. +- `Algebra.isOpen_unramifiedLocus` : + If `A` is (essentially) of finite type over `R`, then the unramified locus is open. +-/ + +universe u + +variable (R A : Type u) [CommRing R] [CommRing A] [Algebra R A] + +namespace Algebra + +/-- `Algebra.unramifiedLocus R A` is the set of primes `p` of `A` +such that `Aₚ` is formally unramified over `R`. -/ +def unramifiedLocus : Set (PrimeSpectrum A) := + { p | Algebra.FormallyUnramified R (Localization.AtPrime p.asIdeal) } + +variable {R A} + +lemma unramifiedLocus_eq_compl_support : + unramifiedLocus R A = (Module.support A (Ω[A⁄R]))ᶜ := by + ext p + simp only [Set.mem_compl_iff, Module.not_mem_support_iff] + have := IsLocalizedModule.iso p.asIdeal.primeCompl + (KaehlerDifferential.map R R A (Localization.AtPrime p.asIdeal)) + exact (Algebra.formallyUnramified_iff _ _).trans this.subsingleton_congr.symm + +lemma basicOpen_subset_unramifiedLocus_iff {f : A} : + ↑(PrimeSpectrum.basicOpen f) ⊆ unramifiedLocus R A ↔ + Algebra.FormallyUnramified R (Localization.Away f) := by + rw [unramifiedLocus_eq_compl_support, Set.subset_compl_comm, + PrimeSpectrum.basicOpen_eq_zeroLocus_compl, compl_compl, + ← LocalizedModule.subsingleton_iff_support_subset, Algebra.formallyUnramified_iff] + exact (IsLocalizedModule.iso (.powers f) + (KaehlerDifferential.map R R A (Localization.Away f))).subsingleton_congr + +lemma unramifiedLocus_eq_univ_iff : + unramifiedLocus R A = Set.univ ↔ Algebra.FormallyUnramified R A := by + rw [unramifiedLocus_eq_compl_support, compl_eq_comm, Set.compl_univ, eq_comm, + Module.support_eq_empty_iff, Algebra.formallyUnramified_iff] + +lemma isOpen_unramifiedLocus [EssFiniteType R A] : IsOpen (unramifiedLocus R A) := by + rw [unramifiedLocus_eq_compl_support, Module.support_eq_zeroLocus] + exact (PrimeSpectrum.isClosed_zeroLocus _).isOpen_compl + +end Algebra From 01b6f1b31424bf27b073d672d772579eaf33d508 Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Tue, 7 Jan 2025 11:43:01 +0000 Subject: [PATCH 043/681] chore(Ideal/Basic): dependent generalization of `Ideal.pi` (#20535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also golf some proofs. TODO: similar to `Ideal.idealProdEquiv`, we may construct OrderEmbedding from `Πᵢ Ideal Rᵢ` to `Ideal (Πᵢ Rᵢ)`, which is an OrderIso if the indexing type is finite. This can then be used to show e.g. that a finite product of Noetherian rings is Noetherian without using an inductive argument. --- .../LinearAlgebra/InvariantBasisNumber.lean | 32 +++--------- Mathlib/RingTheory/Ideal/Basic.lean | 26 ++++------ Mathlib/RingTheory/Ideal/Quotient/Basic.lean | 51 +++++-------------- 3 files changed, 33 insertions(+), 76 deletions(-) diff --git a/Mathlib/LinearAlgebra/InvariantBasisNumber.lean b/Mathlib/LinearAlgebra/InvariantBasisNumber.lean index 2a0d1fc752546..2051aaf53b365 100644 --- a/Mathlib/LinearAlgebra/InvariantBasisNumber.lean +++ b/Mathlib/LinearAlgebra/InvariantBasisNumber.lean @@ -280,8 +280,8 @@ variable {R : Type u} [CommRing R] (I : Ideal R) {ι : Type v} [Fintype ι] {ι' /-- An `R`-linear map `R^n → R^m` induces a function `R^n/I^n → R^m/I^m`. -/ private def induced_map (I : Ideal R) (e : (ι → R) →ₗ[R] ι' → R) : - (ι → R) ⧸ I.pi ι → (ι' → R) ⧸ I.pi ι' := fun x => - Quotient.liftOn' x (fun y => Ideal.Quotient.mk (I.pi ι') (e y)) + (ι → R) ⧸ Ideal.pi (fun _ ↦ I) → (ι' → R) ⧸ Ideal.pi fun _ ↦ I := fun x => + Quotient.liftOn' x (fun y => Ideal.Quotient.mk _ (e y)) (by refine fun a b hab => Ideal.Quotient.eq.2 fun h => ?_ rw [Submodule.quotientRel_def] at hab @@ -291,30 +291,14 @@ private def induced_map (I : Ideal R) (e : (ι → R) →ₗ[R] ι' → R) : /-- An isomorphism of `R`-modules `R^n ≃ R^m` induces an isomorphism of `R/I`-modules `R^n/I^n ≃ R^m/I^m`. -/ private def induced_equiv [Fintype ι'] (I : Ideal R) (e : (ι → R) ≃ₗ[R] ι' → R) : - ((ι → R) ⧸ I.pi ι) ≃ₗ[R ⧸ I] (ι' → R) ⧸ I.pi ι' where + ((ι → R) ⧸ Ideal.pi fun _ ↦ I) ≃ₗ[R ⧸ I] (ι' → R) ⧸ Ideal.pi fun _ ↦ I where -- Porting note: Lean couldn't correctly infer `(I.pi ι)` and `(I.pi ι')` on their own toFun := induced_map I e invFun := induced_map I e.symm - map_add' := by - rintro ⟨a⟩ ⟨b⟩ - convert_to Ideal.Quotient.mk (I.pi ι') _ = Ideal.Quotient.mk (I.pi ι') _ - congr - simp only [map_add] - map_smul' := by - rintro ⟨a⟩ ⟨b⟩ - convert_to Ideal.Quotient.mk (I.pi ι') _ = Ideal.Quotient.mk (I.pi ι') _ - congr - simp only [LinearEquiv.coe_coe, LinearEquiv.map_smulₛₗ, RingHom.id_apply] - left_inv := by - rintro ⟨a⟩ - convert_to Ideal.Quotient.mk (I.pi ι) _ = Ideal.Quotient.mk (I.pi ι) _ - congr - simp only [LinearEquiv.coe_coe, LinearEquiv.symm_apply_apply] - right_inv := by - rintro ⟨a⟩ - convert_to Ideal.Quotient.mk (I.pi ι') _ = Ideal.Quotient.mk (I.pi ι') _ - congr - simp only [LinearEquiv.coe_coe, LinearEquiv.apply_symm_apply] + map_add' := by rintro ⟨a⟩ ⟨b⟩; exact congr_arg _ (map_add ..) + map_smul' := by rintro ⟨a⟩ ⟨b⟩; exact congr_arg _ (map_smul ..) + left_inv := by rintro ⟨a⟩; exact congr_arg _ (e.left_inv ..) + right_inv := by rintro ⟨a⟩; exact congr_arg _ (e.right_inv ..) end @@ -332,6 +316,6 @@ instance (priority := 100) invariantBasisNumber_of_nontrivial_of_commRing {R : T ⟨fun e => let ⟨I, _hI⟩ := Ideal.exists_maximal R eq_of_fin_equiv (R ⧸ I) - ((Ideal.piQuotEquiv _ _).symm ≪≫ₗ (induced_equiv _ e ≪≫ₗ Ideal.piQuotEquiv _ _))⟩ + ((Ideal.piQuotEquiv _ _).symm ≪≫ₗ induced_equiv _ e ≪≫ₗ Ideal.piQuotEquiv _ _)⟩ end diff --git a/Mathlib/RingTheory/Ideal/Basic.lean b/Mathlib/RingTheory/Ideal/Basic.lean index 9bcac7b686908..b2409062e4537 100644 --- a/Mathlib/RingTheory/Ideal/Basic.lean +++ b/Mathlib/RingTheory/Ideal/Basic.lean @@ -28,9 +28,7 @@ Support right ideals, and two-sided ideals over non-commutative rings. -/ -universe u v w - -variable {α : Type u} {β : Type v} {F : Type w} +variable {ι α β F : Type*} open Set Function @@ -40,20 +38,18 @@ section Semiring namespace Ideal -variable [Semiring α] (I : Ideal α) {a b : α} +variable {α : ι → Type*} [Π i, Semiring (α i)] (I : Π i, Ideal (α i)) section Pi -variable (ι : Type v) - -/-- `I^n` as an ideal of `R^n`. -/ -def pi : Ideal (ι → α) where - carrier := { x | ∀ i, x i ∈ I } - zero_mem' _i := I.zero_mem - add_mem' ha hb i := I.add_mem (ha i) (hb i) - smul_mem' a _b hb i := I.mul_mem_left (a i) (hb i) +/-- `Πᵢ Iᵢ` as an ideal of `Πᵢ Rᵢ`. -/ +def pi : Ideal (Π i, α i) where + carrier := { x | ∀ i, x i ∈ I i } + zero_mem' i := (I i).zero_mem + add_mem' ha hb i := (I i).add_mem (ha i) (hb i) + smul_mem' a _b hb i := (I i).mul_mem_left (a i) (hb i) -theorem mem_pi (x : ι → α) : x ∈ I.pi ι ↔ ∀ i, x i ∈ I := +theorem mem_pi (x : Π i, α i) : x ∈ pi I ↔ ∀ i, x i ∈ I i := Iff.rfl end Pi @@ -166,7 +162,7 @@ end CommSemiring section DivisionSemiring -variable {K : Type u} [DivisionSemiring K] (I : Ideal K) +variable {K : Type*} [DivisionSemiring K] (I : Ideal K) namespace Ideal @@ -254,7 +250,7 @@ end Ring namespace Ideal -variable {R : Type u} [CommSemiring R] [Nontrivial R] +variable {R : Type*} [CommSemiring R] [Nontrivial R] theorem bot_lt_of_maximal (M : Ideal R) [hm : M.IsMaximal] (non_field : ¬IsField R) : ⊥ < M := by rcases Ring.not_isField_iff_exists_ideal_bot_lt_and_lt_top.1 non_field with ⟨I, Ibot, Itop⟩ diff --git a/Mathlib/RingTheory/Ideal/Quotient/Basic.lean b/Mathlib/RingTheory/Ideal/Quotient/Basic.lean index 244da7d3aada9..dc04cdcc3ae36 100644 --- a/Mathlib/RingTheory/Ideal/Quotient/Basic.lean +++ b/Mathlib/RingTheory/Ideal/Quotient/Basic.lean @@ -151,55 +151,32 @@ section Pi variable (ι : Type v) /-- `R^n/I^n` is a `R/I`-module. -/ -instance modulePi : Module (R ⧸ I) ((ι → R) ⧸ I.pi ι) where +instance modulePi : Module (R ⧸ I) ((ι → R) ⧸ pi fun _ ↦ I) where smul c m := - Quotient.liftOn₂' c m (fun r m => Submodule.Quotient.mk <| r • m) <| by + Quotient.liftOn₂' c m (fun r m ↦ Submodule.Quotient.mk <| r • m) <| by intro c₁ m₁ c₂ m₂ hc hm apply Ideal.Quotient.eq.2 rw [Submodule.quotientRel_def] at hc hm intro i exact I.mul_sub_mul_mem hc (hm i) - one_smul := by - rintro ⟨a⟩ - convert_to Ideal.Quotient.mk (I.pi ι) _ = Ideal.Quotient.mk (I.pi ι) _ - congr with i; exact one_mul (a i) - mul_smul := by - rintro ⟨a⟩ ⟨b⟩ ⟨c⟩ - convert_to Ideal.Quotient.mk (I.pi ι) _ = Ideal.Quotient.mk (I.pi ι) _ - congr 1; funext i; exact mul_assoc a b (c i) - smul_add := by - rintro ⟨a⟩ ⟨b⟩ ⟨c⟩ - convert_to Ideal.Quotient.mk (I.pi ι) _ = Ideal.Quotient.mk (I.pi ι) _ - congr with i; exact mul_add a (b i) (c i) - smul_zero := by - rintro ⟨a⟩ - convert_to Ideal.Quotient.mk (I.pi ι) _ = Ideal.Quotient.mk (I.pi ι) _ - congr with _; exact mul_zero a - add_smul := by - rintro ⟨a⟩ ⟨b⟩ ⟨c⟩ - convert_to Ideal.Quotient.mk (I.pi ι) _ = Ideal.Quotient.mk (I.pi ι) _ - congr with i; exact add_mul a b (c i) - zero_smul := by - rintro ⟨a⟩ - convert_to Ideal.Quotient.mk (I.pi ι) _ = Ideal.Quotient.mk (I.pi ι) _ - congr with i; exact zero_mul (a i) + one_smul := by rintro ⟨a⟩; exact congr_arg _ (one_smul _ _) + mul_smul := by rintro ⟨a⟩ ⟨b⟩ ⟨c⟩; exact congr_arg _ (mul_smul _ _ _) + smul_add := by rintro ⟨a⟩ ⟨b⟩ ⟨c⟩; exact congr_arg _ (smul_add _ _ _) + smul_zero := by rintro ⟨a⟩; exact congr_arg _ (smul_zero _) + add_smul := by rintro ⟨a⟩ ⟨b⟩ ⟨c⟩; exact congr_arg _ (add_smul _ _ _) + zero_smul := by rintro ⟨a⟩; exact congr_arg _ (zero_smul _ _) /-- `R^n/I^n` is isomorphic to `(R/I)^n` as an `R/I`-module. -/ -noncomputable def piQuotEquiv : ((ι → R) ⧸ I.pi ι) ≃ₗ[R ⧸ I] ι → (R ⧸ I) where - toFun := fun x ↦ - Quotient.liftOn' x (fun f i => Ideal.Quotient.mk I (f i)) fun _ _ hab => - funext fun i => (Submodule.Quotient.eq' _).2 (QuotientAddGroup.leftRel_apply.mp hab i) +noncomputable def piQuotEquiv : ((ι → R) ⧸ pi fun _ ↦ I) ≃ₗ[R ⧸ I] ι → (R ⧸ I) where + toFun x := Quotient.liftOn' x (fun f i ↦ Ideal.Quotient.mk I (f i)) fun _ _ hab ↦ + funext fun i ↦ (Submodule.Quotient.eq' _).2 (QuotientAddGroup.leftRel_apply.mp hab i) map_add' := by rintro ⟨_⟩ ⟨_⟩; rfl map_smul' := by rintro ⟨_⟩ ⟨_⟩; rfl - invFun := fun x ↦ Ideal.Quotient.mk (I.pi ι) fun i ↦ Quotient.out (x i) + invFun x := Ideal.Quotient.mk _ (Quotient.out <| x ·) left_inv := by rintro ⟨x⟩ - exact Ideal.Quotient.eq.2 fun i => Ideal.Quotient.eq.1 (Quotient.out_eq' _) - right_inv := by - intro x - ext i - obtain ⟨_, _⟩ := @Quot.exists_rep _ _ (x i) - convert Quotient.out_eq' (x i) + exact Ideal.Quotient.eq.2 fun i ↦ Ideal.Quotient.eq.1 (Quotient.out_eq' _) + right_inv x := funext fun i ↦ Quotient.out_eq' (x i) /-- If `f : R^n → R^m` is an `R`-linear map and `I ⊆ R` is an ideal, then the image of `I^n` is contained in `I^m`. -/ From dd5ea9368cd7f0c205558d02f59fdf9c89018fdf Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 7 Jan 2025 14:23:23 +0000 Subject: [PATCH 044/681] fix(HashCommandLinter): remove unnecessary, broken workaround for tests (#20529) The old workaround for `test` is wrong on two accounts. 1. The test directory is now called `MathlibTest`, not `test`. 2. With the weak-option settings that mathlib uses, the test files are all already opt-in for the linters anyways. --- Mathlib/Tactic/Linter/HashCommandLinter.lean | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Mathlib/Tactic/Linter/HashCommandLinter.lean b/Mathlib/Tactic/Linter/HashCommandLinter.lean index e4bcb714f146f..41832c0f4570b 100644 --- a/Mathlib/Tactic/Linter/HashCommandLinter.lean +++ b/Mathlib/Tactic/Linter/HashCommandLinter.lean @@ -65,12 +65,9 @@ This means that CI will eventually fail on `#`-commands, but does not stop it fr However, in order to avoid local clutter, when `warningAsError` is `false`, the linter logs a warning only for the `#`-commands that do not already emit a message. -/ def hashCommandLinter : Linter where run := withSetOptionIn' fun stx => do - let mod := (← getMainModule).components if Linter.getLinterValue linter.hashCommand (← getOptions) && - ((← get).messages.reportedPlusUnreported.isEmpty || warningAsError.get (← getOptions)) && - -- we check that the module is either not in `test` or, is `test.HashCommandLinter` - (mod.getD 0 default != `test || (mod == [`test, `HashCommandLinter])) - then + ((← get).messages.reportedPlusUnreported.isEmpty || warningAsError.get (← getOptions)) + then if let some sa := stx.getHead? then let a := sa.getAtomVal if (a.get ⟨0⟩ == '#' && ! allowed_commands.contains a) then From 497cc54bdfb89abfd41eb161756d0dc530425ead Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Tue, 7 Jan 2025 15:07:38 +0000 Subject: [PATCH 045/681] perf: remove `@[simp]` on `Fintype.card_of{IsEmpty,Subsingleton}` (#20524) These lemmas only apply to `Fintype.ofIsEmpty` and `Fintype.ofSubsingleton`, but they're discrimination tree keys match any `Fintype.card` application. This forces Lean to attempt to unify the variables too often, especially because unification problems which introduce metavariables don't benefit from the same caching mechanisms. See [Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Adding.20.2F.20modifying.20Aesop.20lemmas/near/491949014) --- Mathlib/Data/Fintype/Card.lean | 2 -- 1 file changed, 2 deletions(-) diff --git a/Mathlib/Data/Fintype/Card.lean b/Mathlib/Data/Fintype/Card.lean index 08568f59f0f7d..eaa7a6616ea92 100644 --- a/Mathlib/Data/Fintype/Card.lean +++ b/Mathlib/Data/Fintype/Card.lean @@ -194,7 +194,6 @@ theorem card_eq {α β} [_F : Fintype α] [_G : Fintype β] : card α = card β /-- Note: this lemma is specifically about `Fintype.ofSubsingleton`. For a statement about arbitrary `Fintype` instances, use either `Fintype.card_le_one_iff_subsingleton` or `Fintype.card_unique`. -/ -@[simp] theorem card_ofSubsingleton (a : α) [Subsingleton α] : @Fintype.card _ (ofSubsingleton a) = 1 := rfl @@ -204,7 +203,6 @@ theorem card_unique [Unique α] [h : Fintype α] : Fintype.card α = 1 := /-- Note: this lemma is specifically about `Fintype.ofIsEmpty`. For a statement about arbitrary `Fintype` instances, use `Fintype.card_eq_zero`. -/ -@[simp] theorem card_ofIsEmpty [IsEmpty α] : @Fintype.card α Fintype.ofIsEmpty = 0 := rfl From 9e3f841ce2b5742da14a9cce51b947c77ca55d8e Mon Sep 17 00:00:00 2001 From: Robin Carlier <57142648+robin-carlier@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:55:44 +0000 Subject: [PATCH 046/681] chore(CategoryTheory/Limits/Fubini): relax universes constraints and weaken hypotheses (#20553) Weaken universes constraints in this file, and weaken the hypotheses on `C` for the Fubini theorems. --- Mathlib/CategoryTheory/Limits/Fubini.lean | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Mathlib/CategoryTheory/Limits/Fubini.lean b/Mathlib/CategoryTheory/Limits/Fubini.lean index 898d073faa5a4..9a6aedbc78108 100644 --- a/Mathlib/CategoryTheory/Limits/Fubini.lean +++ b/Mathlib/CategoryTheory/Limits/Fubini.lean @@ -35,14 +35,12 @@ All statements have their counterpart for colimits. -/ -universe v u - open CategoryTheory namespace CategoryTheory.Limits -variable {J K : Type v} [SmallCategory J] [SmallCategory K] -variable {C : Type u} [Category.{v} C] +variable {J K : Type*} [Category J] [Category K] +variable {C : Type*} [Category C] variable (F : J ⥤ K ⥤ C) -- We could try introducing a "dependent functor type" to handle this? @@ -486,9 +484,9 @@ end section -variable [HasLimits C] +variable [HasLimitsOfShape K C] [HasLimitsOfShape J C] [HasLimitsOfShape (K × J) C] [HasLimit G] + [HasLimit (curry.obj G ⋙ lim)] --- Certainly one could weaken the hypotheses here. open CategoryTheory.prod /-- A variant of the Fubini theorem for a functor `G : J × K ⥤ C`, @@ -525,7 +523,8 @@ end section -variable [HasColimits C] +variable [HasColimitsOfShape K C] [HasColimitsOfShape J C] [HasColimitsOfShape (K × J) C] + [HasColimit G] [HasColimit (curry.obj G ⋙ colim)] open CategoryTheory.prod From 01e663839357f0acbf26e478a6e76f6f29e98ce4 Mon Sep 17 00:00:00 2001 From: Lorenzo Luccioli Date: Tue, 7 Jan 2025 16:45:12 +0000 Subject: [PATCH 047/681] feat(Probability/Kernel): `Kernel.sectL` and `sectR` (#15466) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define a `Kernel α γ` and a `Kernel β γ` from a `Kernel (α × β) γ` by taking the comap of `fun a ↦ (a, b)` and `fun b ↦ (a, b)` respectively. - Add definitions of `Kernel.sectL` and `Kernel.sectR`. - Add some API lemmas: `sectL_apply`, `sectL_zero`, `comap_sectL`, `sectL_prodMkLeft`, `sectL_prodMkRight` and the equivalent lemmas for `sectR`. - Add instances for `IsMarkovKernel`, `IsFiniteKernel`, `IsSFiniteKernel` and `NeZero`. - Add `sectL_swapRight` and `sectR_swapRight`. - Add `compProd_apply_eq_compProd_sectR`. Co-authored-by: Yury G. Kudryashov Co-authored-by: Remy Degenne --- .../Probability/Kernel/Composition/Basic.lean | 99 +++++++++++++++++++ .../Kernel/Composition/MeasureCompProd.lean | 8 ++ 2 files changed, 107 insertions(+) diff --git a/Mathlib/Probability/Kernel/Composition/Basic.lean b/Mathlib/Probability/Kernel/Composition/Basic.lean index 5f580f7b80e64..f91eadde47725 100644 --- a/Mathlib/Probability/Kernel/Composition/Basic.lean +++ b/Mathlib/Probability/Kernel/Composition/Basic.lean @@ -1063,6 +1063,104 @@ lemma snd_swapRight (κ : Kernel α (β × γ)) : snd (swapRight κ) = fst κ := end FstSnd +section sectLsectR + +variable {γ δ : Type*} {mγ : MeasurableSpace γ} {mδ : MeasurableSpace δ} + +/-- Define a `Kernel α γ` from a `Kernel (α × β) γ` by taking the comap of `fun a ↦ (a, b)` for +a given `b : β`. -/ +noncomputable def sectL (κ : Kernel (α × β) γ) (b : β) : Kernel α γ := + comap κ (fun a ↦ (a, b)) (measurable_id.prod_mk measurable_const) + +@[simp] theorem sectL_apply (κ : Kernel (α × β) γ) (b : β) (a : α) : sectL κ b a = κ (a, b) := rfl + +@[simp] lemma sectL_zero (b : β) : sectL (0 : Kernel (α × β) γ) b = 0 := by simp [sectL] + +instance (κ : Kernel (α × β) γ) (b : β) [IsMarkovKernel κ] : IsMarkovKernel (sectL κ b) := by + rw [sectL]; infer_instance + +instance (κ : Kernel (α × β) γ) (b : β) [IsZeroOrMarkovKernel κ] : + IsZeroOrMarkovKernel (sectL κ b) := by + rw [sectL]; infer_instance + +instance (κ : Kernel (α × β) γ) (b : β) [IsFiniteKernel κ] : IsFiniteKernel (sectL κ b) := by + rw [sectL]; infer_instance + +instance (κ : Kernel (α × β) γ) (b : β) [IsSFiniteKernel κ] : IsSFiniteKernel (sectL κ b) := by + rw [sectL]; infer_instance + +instance (κ : Kernel (α × β) γ) (a : α) (b : β) [NeZero (κ (a, b))] : NeZero ((sectL κ b) a) := by + rw [sectL_apply]; infer_instance + +instance (priority := 100) {κ : Kernel (α × β) γ} [∀ b, IsMarkovKernel (sectL κ b)] : + IsMarkovKernel κ := by + refine ⟨fun _ ↦ ⟨?_⟩⟩ + rw [← sectL_apply, measure_univ] + +--I'm not sure this lemma is actually useful +lemma comap_sectL (κ : Kernel (α × β) γ) (b : β) {f : δ → α} (hf : Measurable f) : + comap (sectL κ b) f hf = comap κ (fun d ↦ (f d, b)) (hf.prod_mk measurable_const) := by + ext d s + rw [comap_apply, sectL_apply, comap_apply] + +@[simp] +lemma sectL_prodMkLeft (α : Type*) [MeasurableSpace α] (κ : Kernel β γ) (a : α) {b : β} : + sectL (prodMkLeft α κ) b a = κ b := rfl + +@[simp] +lemma sectL_prodMkRight (β : Type*) [MeasurableSpace β] (κ : Kernel α γ) (b : β) : + sectL (prodMkRight β κ) b = κ := rfl + +/-- Define a `Kernel β γ` from a `Kernel (α × β) γ` by taking the comap of `fun b ↦ (a, b)` for +a given `a : α`. -/ +noncomputable def sectR (κ : Kernel (α × β) γ) (a : α) : Kernel β γ := + comap κ (fun b ↦ (a, b)) (measurable_const.prod_mk measurable_id) + +@[simp] theorem sectR_apply (κ : Kernel (α × β) γ) (b : β) (a : α) : sectR κ a b = κ (a, b) := rfl + +@[simp] lemma sectR_zero (a : α) : sectR (0 : Kernel (α × β) γ) a = 0 := by simp [sectR] + +instance (κ : Kernel (α × β) γ) (a : α) [IsMarkovKernel κ] : IsMarkovKernel (sectR κ a) := by + rw [sectR]; infer_instance + +instance (κ : Kernel (α × β) γ) (a : α) [IsZeroOrMarkovKernel κ] : + IsZeroOrMarkovKernel (sectR κ a) := by + rw [sectR]; infer_instance + +instance (κ : Kernel (α × β) γ) (a : α) [IsFiniteKernel κ] : IsFiniteKernel (sectR κ a) := by + rw [sectR]; infer_instance + +instance (κ : Kernel (α × β) γ) (a : α) [IsSFiniteKernel κ] : IsSFiniteKernel (sectR κ a) := by + rw [sectR]; infer_instance + +instance (κ : Kernel (α × β) γ) (a : α) (b : β) [NeZero (κ (a, b))] : NeZero ((sectR κ a) b) := by + rw [sectR_apply]; infer_instance + +instance (priority := 100) {κ : Kernel (α × β) γ} [∀ b, IsMarkovKernel (sectR κ b)] : + IsMarkovKernel κ := by + refine ⟨fun _ ↦ ⟨?_⟩⟩ + rw [← sectR_apply, measure_univ] + +--I'm not sure this lemma is actually useful +lemma comap_sectR (κ : Kernel (α × β) γ) (a : α) {f : δ → β} (hf : Measurable f) : + comap (sectR κ a) f hf = comap κ (fun d ↦ (a, f d)) (measurable_const.prod_mk hf) := by + ext d s + rw [comap_apply, sectR_apply, comap_apply] + +@[simp] +lemma sectR_prodMkLeft (α : Type*) [MeasurableSpace α] (κ : Kernel β γ) (a : α) : + sectR (prodMkLeft α κ) a = κ := rfl + +@[simp] +lemma sectR_prodMkRight (β : Type*) [MeasurableSpace β] (κ : Kernel α γ) (b : β) {a : α} : + sectR (prodMkRight β κ) a b = κ a := rfl + +@[simp] lemma sectL_swapRight (κ : Kernel (α × β) γ) : sectL (swapLeft κ) = sectR κ := rfl + +@[simp] lemma sectR_swapRight (κ : Kernel (α × β) γ) : sectR (swapLeft κ) = sectL κ := rfl + +end sectLsectR + section Comp /-! ### Composition of two kernels -/ @@ -1204,6 +1302,7 @@ variable {γ δ : Type*} {mγ : MeasurableSpace γ} {mδ : MeasurableSpace δ} noncomputable def prod (κ : Kernel α β) (η : Kernel α γ) : Kernel α (β × γ) := κ ⊗ₖ swapLeft (prodMkLeft β η) +@[inherit_doc] scoped[ProbabilityTheory] infixl:100 " ×ₖ " => ProbabilityTheory.Kernel.prod theorem prod_apply' (κ : Kernel α β) [IsSFiniteKernel κ] (η : Kernel α γ) [IsSFiniteKernel η] diff --git a/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean b/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean index b57ca2ef11459..64933b8111dc2 100644 --- a/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean +++ b/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean @@ -73,6 +73,14 @@ lemma compProd_apply_prod [SFinite μ] [IsSFiniteKernel κ] rw [indicator_apply] split_ifs with ha <;> simp [ha] +lemma _root_.ProbabilityTheory.Kernel.compProd_apply_eq_compProd_sectR {γ : Type*} + {mγ : MeasurableSpace γ} (κ : Kernel α β) (η : Kernel (α × β) γ) + [IsSFiniteKernel κ] [IsSFiniteKernel η] (a : α) : + (κ ⊗ₖ η) a = (κ a) ⊗ₘ (Kernel.sectR η a) := by + ext s hs + simp_rw [Kernel.compProd_apply hs, compProd_apply hs, Kernel.sectR_apply] + rfl + lemma compProd_congr [IsSFiniteKernel κ] [IsSFiniteKernel η] (h : κ =ᵐ[μ] η) : μ ⊗ₘ κ = μ ⊗ₘ η := by by_cases hμ : SFinite μ From db72affa74bdee1086ce3f989c545eeb4280c420 Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Tue, 7 Jan 2025 17:10:34 +0000 Subject: [PATCH 048/681] chore: to_additive various results on groups, group actions (#20547) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two adjustments to #20498 that had been requested by Yaël but hadn't been implemented on time before merge. --- Mathlib/GroupTheory/GroupAction/Blocks.lean | 6 +++--- Mathlib/GroupTheory/GroupAction/SubMulAction.lean | 15 +++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Mathlib/GroupTheory/GroupAction/Blocks.lean b/Mathlib/GroupTheory/GroupAction/Blocks.lean index 59f18a034ab8f..5655e4bb9cc96 100644 --- a/Mathlib/GroupTheory/GroupAction/Blocks.lean +++ b/Mathlib/GroupTheory/GroupAction/Blocks.lean @@ -311,7 +311,7 @@ theorem isBlock_subtypeVal {C : SubMulAction G X} {B : Set C} : rw [← SubMulAction.inclusion.coe_eq, ← image_smul_set, ← image_smul_set, ne_eq, Set.image_eq_image C.inclusion_injective, disjoint_image_iff C.inclusion_injective] -theorem _root_.AddAction.IsBlock.of_addsubgroup_of_conjugate +theorem _root_.AddAction.IsBlock.of_addSubgroup_of_conjugate {G : Type*} [AddGroup G] {X : Type*} [AddAction G X] {B : Set X} {H : AddSubgroup G} (hB : AddAction.IsBlock H B) (g : G) : AddAction.IsBlock (H.map (AddAut.conj g).toAddMonoidHom) (g +ᵥ B) := by @@ -330,7 +330,7 @@ theorem _root_.AddAction.IsBlock.of_addsubgroup_of_conjugate erw [AddAut.conj_apply] simp -@[to_additive existing AddAction.IsBlock.of_addsubgroup_of_conjugate] +@[to_additive existing] theorem IsBlock.of_subgroup_of_conjugate {H : Subgroup G} (hB : IsBlock H B) (g : G) : IsBlock (H.map (MulAut.conj g).toMonoidHom) (g • B) := by rw [isBlock_iff_smul_eq_or_disjoint] @@ -353,7 +353,7 @@ theorem _root_.AddAction.IsBlock.translate AddAction.IsBlock G (g +ᵥ B) := by rw [← AddAction.isBlock_top] at hB ⊢ rw [← AddSubgroup.map_comap_eq_self_of_surjective (G := G) ?_ ⊤] - · apply AddAction.IsBlock.of_addsubgroup_of_conjugate + · apply AddAction.IsBlock.of_addSubgroup_of_conjugate rwa [AddSubgroup.comap_top] · exact (AddAut.conj g).surjective diff --git a/Mathlib/GroupTheory/GroupAction/SubMulAction.lean b/Mathlib/GroupTheory/GroupAction/SubMulAction.lean index d8e3ff10ecc68..9478f74a0c0be 100644 --- a/Mathlib/GroupTheory/GroupAction/SubMulAction.lean +++ b/Mathlib/GroupTheory/GroupAction/SubMulAction.lean @@ -154,13 +154,6 @@ end OfTower end SetLike -/-- A SubMulAction is a set which is closed under scalar multiplication. -/ -structure SubMulAction (R : Type u) (M : Type v) [SMul R M] : Type v where - /-- The underlying set of a `SubMulAction`. -/ - carrier : Set M - /-- The carrier set is closed under scalar multiplication. -/ - smul_mem' : ∀ (c : R) {x : M}, x ∈ carrier → c • x ∈ carrier - /-- A SubAddAction is a set which is closed under scalar multiplication. -/ structure SubAddAction (R : Type u) (M : Type v) [VAdd R M] : Type v where /-- The underlying set of a `SubAddAction`. -/ @@ -168,7 +161,13 @@ structure SubAddAction (R : Type u) (M : Type v) [VAdd R M] : Type v where /-- The carrier set is closed under scalar multiplication. -/ vadd_mem' : ∀ (c : R) {x : M}, x ∈ carrier → c +ᵥ x ∈ carrier -attribute [to_additive] SubMulAction +/-- A SubMulAction is a set which is closed under scalar multiplication. -/ +@[to_additive] +structure SubMulAction (R : Type u) (M : Type v) [SMul R M] : Type v where + /-- The underlying set of a `SubMulAction`. -/ + carrier : Set M + /-- The carrier set is closed under scalar multiplication. -/ + smul_mem' : ∀ (c : R) {x : M}, x ∈ carrier → c • x ∈ carrier namespace SubMulAction From 3e203da713dc741e113056355b2aa2abebcb3be0 Mon Sep 17 00:00:00 2001 From: JakobStiefel Date: Tue, 7 Jan 2025 17:42:08 +0000 Subject: [PATCH 049/681] feat: results on inner regularity of finite measures (#19780) in a `PseudoEMetricSpace` and `CompleteSpace` with `SecondCountableTopology`, any finite measure is inner regular with respect to compact sets. In other words, finite measures are tight. Important result in probability Co-authored-by: JakobStiefel <73285902+JakobStiefel@users.noreply.github.com> --- Mathlib.lean | 1 + .../MeasureTheory/Measure/MeasureSpace.lean | 18 ++ .../Measure/RegularityCompacts.lean | 248 ++++++++++++++++++ Mathlib/Topology/Instances/ENNReal.lean | 29 ++ Mathlib/Topology/UniformSpace/Cauchy.lean | 28 ++ 5 files changed, 324 insertions(+) create mode 100644 Mathlib/MeasureTheory/Measure/RegularityCompacts.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2f8cc2a277bfb..c0d76b970d1db 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3807,6 +3807,7 @@ import Mathlib.MeasureTheory.Measure.Portmanteau import Mathlib.MeasureTheory.Measure.ProbabilityMeasure import Mathlib.MeasureTheory.Measure.Prod import Mathlib.MeasureTheory.Measure.Regular +import Mathlib.MeasureTheory.Measure.RegularityCompacts import Mathlib.MeasureTheory.Measure.Restrict import Mathlib.MeasureTheory.Measure.SeparableMeasure import Mathlib.MeasureTheory.Measure.Stieltjes diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index a389edbf53a51..0303a1275e8c4 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -626,6 +626,24 @@ theorem tendsto_measure_iInter_le {α ι : Type*} {_ : MeasurableSpace α} {μ : exact tendsto_atTop_iInf fun i j hij ↦ measure_mono <| biInter_subset_biInter_left fun k hki ↦ le_trans hki hij +/-- Some version of continuity of a measure in the emptyset using the intersection along a set of +sets. -/ +theorem exists_measure_iInter_lt {α ι : Type*} {_ : MeasurableSpace α} {μ : Measure α} + [SemilatticeSup ι] [Countable ι] {f : ι → Set α} + (hm : ∀ i, NullMeasurableSet (f i) μ) {ε : ℝ≥0∞} (hε : 0 < ε) (hfin : ∃ i, μ (f i) ≠ ∞) + (hfem : ⋂ n, f n = ∅) : ∃ m, μ (⋂ n ≤ m, f n) < ε := by + let F m := μ (⋂ n ≤ m, f n) + have hFAnti : Antitone F := + fun i j hij => measure_mono (biInter_subset_biInter_left fun k hki => le_trans hki hij) + suffices Filter.Tendsto F Filter.atTop (𝓝 0) by + rw [@ENNReal.tendsto_atTop_zero_iff_lt_of_antitone + _ (nonempty_of_exists hfin) _ _ hFAnti] at this + exact this ε hε + have hzero : μ (⋂ n, f n) = 0 := by + simp only [hfem, measure_empty] + rw [← hzero] + exact tendsto_measure_iInter_le hm hfin + /-- The measure of the intersection of a decreasing sequence of measurable sets indexed by a linear order with first countable topology is the limit of the measures. -/ theorem tendsto_measure_biInter_gt {ι : Type*} [LinearOrder ι] [TopologicalSpace ι] diff --git a/Mathlib/MeasureTheory/Measure/RegularityCompacts.lean b/Mathlib/MeasureTheory/Measure/RegularityCompacts.lean new file mode 100644 index 0000000000000..1d8e91a4aa967 --- /dev/null +++ b/Mathlib/MeasureTheory/Measure/RegularityCompacts.lean @@ -0,0 +1,248 @@ +/- +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, Peter Pfaffelhuber +-/ +import Mathlib.Analysis.SpecificLimits.Basic +import Mathlib.MeasureTheory.Measure.Regular +import Mathlib.Topology.MetricSpace.Polish +import Mathlib.Topology.UniformSpace.Cauchy + +/-! +# Inner regularity of finite measures + +The main result of this file is `theorem InnerRegularCompactLTTop`: +A finite measure `μ` on a `PseudoEMetricSpace E` and `CompleteSpace E` with +`SecondCountableTopology E` is inner regular with respect to compact sets. In other +words, a finite measure on such a space is a tight measure. + +Finite measures on Polish spaces are an important special case, which makes the result +`theorem PolishSpace.innerRegular_isCompact_measurableSet` an important result in probability. +-/ + +open Set MeasureTheory + +open scoped ENNReal + +namespace MeasureTheory + +variable {α : Type*} [MeasurableSpace α] {μ : Measure α} + +theorem innerRegularWRT_isCompact_closure_iff [TopologicalSpace α] [R1Space α] : + μ.InnerRegularWRT (IsCompact ∘ closure) IsClosed ↔ μ.InnerRegularWRT IsCompact IsClosed := by + constructor <;> intro h A hA r hr + · rcases h hA r hr with ⟨K, ⟨hK1, hK2, hK3⟩⟩ + exact ⟨closure K, closure_minimal hK1 hA, hK2, hK3.trans_le (measure_mono subset_closure)⟩ + · rcases h hA r hr with ⟨K, ⟨hK1, hK2, hK3⟩⟩ + refine ⟨closure K, closure_minimal hK1 hA, ?_, ?_⟩ + · simpa only [closure_closure, Function.comp_apply] using hK2.closure + · exact hK3.trans_le (measure_mono subset_closure) + +lemma innerRegularWRT_isCompact_isClosed_iff_innerRegularWRT_isCompact_closure + [TopologicalSpace α] [R1Space α] : + μ.InnerRegularWRT (fun s ↦ IsCompact s ∧ IsClosed s) IsClosed + ↔ μ.InnerRegularWRT (IsCompact ∘ closure) IsClosed := by + constructor <;> intro h A hA r hr + · obtain ⟨K, hK1, ⟨hK2, _⟩, hK4⟩ := h hA r hr + refine ⟨K, hK1, ?_, hK4⟩ + simp only [closure_closure, Function.comp_apply] + exact hK2.closure + · obtain ⟨K, hK1, hK2, hK3⟩ := h hA r hr + refine ⟨closure K, closure_minimal hK1 hA, ?_, ?_⟩ + · simpa only [isClosed_closure, and_true] + · exact hK3.trans_le (measure_mono subset_closure) + +lemma innerRegularWRT_isCompact_isClosed_iff [TopologicalSpace α] [R1Space α] : + μ.InnerRegularWRT (fun s ↦ IsCompact s ∧ IsClosed s) IsClosed + ↔ μ.InnerRegularWRT IsCompact IsClosed := + innerRegularWRT_isCompact_isClosed_iff_innerRegularWRT_isCompact_closure.trans + innerRegularWRT_isCompact_closure_iff + +/-- +If predicate `p` is preserved under intersections with sets satisfying predicate `q`, and sets +satisfying `p` cover the space arbitrarily well, then `μ` is inner regular with respect to +predicates `p` and `q`. +-/ +theorem innerRegularWRT_of_exists_compl_lt {p q : Set α → Prop} (hpq : ∀ A B, p A → q B → p (A ∩ B)) + (hμ : ∀ ε, 0 < ε → ∃ K, p K ∧ μ Kᶜ < ε) : + μ.InnerRegularWRT p q := by + intro A hA r hr + obtain ⟨K, hK, hK_subset, h_lt⟩ : ∃ K, p K ∧ K ⊆ A ∧ μ (A \ K) < μ A - r := by + obtain ⟨K', hpK', hK'_lt⟩ := hμ (μ A - r) (tsub_pos_of_lt hr) + refine ⟨K' ∩ A, hpq K' A hpK' hA, inter_subset_right, ?_⟩ + · refine (measure_mono fun x ↦ ?_).trans_lt hK'_lt + simp only [diff_inter_self_eq_diff, mem_diff, mem_compl_iff, and_imp, imp_self, imp_true_iff] + refine ⟨K, hK_subset, hK, ?_⟩ + have h_lt' : μ A - μ K < μ A - r := le_measure_diff.trans_lt h_lt + exact lt_of_tsub_lt_tsub_left h_lt' + +theorem innerRegularWRT_isCompact_closure_of_univ [TopologicalSpace α] + (hμ : ∀ ε, 0 < ε → ∃ K, IsCompact (closure K) ∧ μ (Kᶜ) < ε) : + μ.InnerRegularWRT (IsCompact ∘ closure) IsClosed := by + refine innerRegularWRT_of_exists_compl_lt (fun s t hs ht ↦ ?_) hμ + have : IsCompact (closure s ∩ t) := hs.inter_right ht + refine this.of_isClosed_subset isClosed_closure ?_ + refine (closure_inter_subset_inter_closure _ _).trans_eq ?_ + rw [IsClosed.closure_eq ht] + +theorem exists_isCompact_closure_measure_compl_lt [UniformSpace α] [CompleteSpace α] + [SecondCountableTopology α] [(uniformity α).IsCountablyGenerated] + [OpensMeasurableSpace α] (P : Measure α) [IsFiniteMeasure P] (ε : ℝ≥0∞) (hε : 0 < ε) : + ∃ K, IsCompact (closure K) ∧ P Kᶜ < ε := by + /- + If α is empty, the result is trivial. + + Otherwise, fix a dense sequence `seq` and an antitone basis `t` of entourages. We find a sequence + of natural numbers `u n`, such that `interUnionBalls seq u t`, which is the intersection over + `n` of the `t n`-neighborhood of `seq 1, ..., seq (u n)`, covers the space arbitrarily well. + -/ + cases isEmpty_or_nonempty α + case inl => + refine ⟨∅, by simp, ?_⟩ + rw [← Set.univ_eq_empty_iff.mpr] + · simpa only [compl_univ, measure_empty, ENNReal.coe_pos] using hε + · assumption + case inr => + let seq := TopologicalSpace.denseSeq α + have hseq_dense : DenseRange seq := TopologicalSpace.denseRange_denseSeq α + obtain ⟨t : ℕ → Set (α × α), + hto : ∀ i, t i ∈ (uniformity α).sets ∧ IsOpen (t i) ∧ SymmetricRel (t i), + h_basis : (uniformity α).HasAntitoneBasis t⟩ := + (@uniformity_hasBasis_open_symmetric α _).exists_antitone_subbasis + let f : ℕ → ℕ → Set α := fun n m ↦ UniformSpace.ball (seq m) (t n) + have h_univ n : (⋃ m, f n m) = univ := hseq_dense.iUnion_uniformity_ball (hto n).1 + have h3 n (ε : ℝ≥0∞) (hε : 0 < ε) : ∃ m, P (⋂ m' ≤ m, (f n m')ᶜ) < ε := by + refine exists_measure_iInter_lt (fun m ↦ ?_) hε ⟨0, measure_ne_top P _⟩ ?_ + · exact (measurable_prod_mk_left (IsOpen.measurableSet (hto n).2.1)).compl.nullMeasurableSet + · rw [← compl_iUnion, h_univ, compl_univ] + choose! s' s'bound using h3 + rcases ENNReal.exists_pos_sum_of_countable' (ne_of_gt hε) ℕ with ⟨δ, hδ1, hδ2⟩ + classical + let u : ℕ → ℕ := fun n ↦ s' n (δ n) + refine ⟨interUnionBalls seq u t, isCompact_closure_interUnionBalls h_basis.toHasBasis seq u, ?_⟩ + rw [interUnionBalls, Set.compl_iInter] + refine ((measure_iUnion_le _).trans ?_).trans_lt hδ2 + refine ENNReal.tsum_le_tsum (fun n ↦ ?_) + have h'' n : Prod.swap ⁻¹' t n = t n := SymmetricRel.eq (hto n).2.2 + simp only [h'', compl_iUnion, ge_iff_le] + exact (s'bound n (δ n) (hδ1 n)).le + +theorem innerRegularWRT_isCompact_closure [UniformSpace α] [CompleteSpace α] + [SecondCountableTopology α] [(uniformity α).IsCountablyGenerated] + [OpensMeasurableSpace α] (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegularWRT (IsCompact ∘ closure) IsClosed := + innerRegularWRT_isCompact_closure_of_univ + (exists_isCompact_closure_measure_compl_lt P) + +theorem innerRegularWRT_isCompact_isClosed [UniformSpace α] [CompleteSpace α] + [SecondCountableTopology α] [(uniformity α).IsCountablyGenerated] + [OpensMeasurableSpace α] (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegularWRT (fun s ↦ IsCompact s ∧ IsClosed s) IsClosed := by + rw [innerRegularWRT_isCompact_isClosed_iff_innerRegularWRT_isCompact_closure] + exact innerRegularWRT_isCompact_closure P + +theorem innerRegularWRT_isCompact [UniformSpace α] [CompleteSpace α] + [SecondCountableTopology α] [(uniformity α).IsCountablyGenerated] + [OpensMeasurableSpace α] (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegularWRT IsCompact IsClosed := by + rw [← innerRegularWRT_isCompact_closure_iff] + exact innerRegularWRT_isCompact_closure P + +theorem innerRegularWRT_isCompact_isClosed_isOpen [PseudoEMetricSpace α] + [CompleteSpace α] [SecondCountableTopology α] [OpensMeasurableSpace α] + (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegularWRT (fun s ↦ IsCompact s ∧ IsClosed s) IsOpen := + (innerRegularWRT_isCompact_isClosed P).trans + (Measure.InnerRegularWRT.of_pseudoMetrizableSpace P) + +theorem innerRegularWRT_isCompact_isOpen [PseudoEMetricSpace α] + [CompleteSpace α] [SecondCountableTopology α] [OpensMeasurableSpace α] + (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegularWRT IsCompact IsOpen := + (innerRegularWRT_isCompact P).trans + (Measure.InnerRegularWRT.of_pseudoMetrizableSpace P) + +/-- +A finite measure `μ` on a `PseudoEMetricSpace E` and `CompleteSpace E` with +`SecondCountableTopology E` is inner regular. In other words, a finite measure +on such a space is a tight measure. +-/ +instance InnerRegular_of_pseudoEMetricSpace_completeSpace_secondCountable [PseudoEMetricSpace α] + [CompleteSpace α] [SecondCountableTopology α] [BorelSpace α] + (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegular := by + refine @Measure.InnerRegularCompactLTTop.instInnerRegularOfSigmaFinite _ _ _ _ + ⟨Measure.InnerRegularWRT.measurableSet_of_isOpen ?_ ?_⟩ _ + · exact innerRegularWRT_isCompact_isOpen P + · exact fun s t hs_compact ht_open ↦ hs_compact.inter_right ht_open.isClosed_compl + +/-- +A special case of `innerRegular_of_pseudoEMetricSpace_completeSpace_secondCountable` for Polish +spaces: A finite measure on a Polish space is a tight measure. +-/ +instance InnerRegular_of_polishSpace [TopologicalSpace α] + [PolishSpace α] [BorelSpace α] (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegular := by + letI := upgradePolishSpace α + exact InnerRegular_of_pseudoEMetricSpace_completeSpace_secondCountable P + +/-- +A measure `μ` on a `PseudoEMetricSpace E` and `CompleteSpace E` with `SecondCountableTopology E` +is inner regular for finite measure sets with respect to compact sets. +-/ +instance InnerRegularCompactLTTop_of_pseudoEMetricSpace_completeSpace_secondCountable + [PseudoEMetricSpace α] [CompleteSpace α] [SecondCountableTopology α] [BorelSpace α] + (μ : Measure α) : + μ.InnerRegularCompactLTTop := by + constructor; intro A ⟨hA1, hA2⟩ r hr + have IRC : Measure.InnerRegularCompactLTTop (μ.restrict A) := by + exact @Measure.InnerRegular.instInnerRegularCompactLTTop _ _ _ _ + (@InnerRegular_of_pseudoEMetricSpace_completeSpace_secondCountable _ _ _ _ _ _ + (μ.restrict A) (@Restrict.isFiniteMeasure _ _ _ μ (fact_iff.mpr hA2.lt_top))) + have hA2' : (μ.restrict A) A ≠ ⊤ := by + rwa [Measure.restrict_apply_self] + have hr' : r < μ.restrict A A := by + rwa [Measure.restrict_apply_self] + obtain ⟨K, ⟨hK1, hK2, hK3⟩⟩ := @MeasurableSet.exists_lt_isCompact_of_ne_top + _ _ (μ.restrict A) _ IRC _ hA1 hA2' r hr' + use K, hK1, hK2 + rwa [Measure.restrict_eq_self μ hK1] at hK3 + +/-- +A special case of `innerRegularCompactLTTop_of_pseudoEMetricSpace_completeSpace_secondCountable` +for Polish spaces: A measure `μ` on a Polish space inner regular for finite measure sets with +respect to compact sets. +-/ +instance InnerRegularCompactLTTop_of_polishSpace + [TopologicalSpace α] [PolishSpace α] [BorelSpace α] (μ : Measure α) : + μ.InnerRegularCompactLTTop := by + letI := upgradePolishSpace α + exact InnerRegularCompactLTTop_of_pseudoEMetricSpace_completeSpace_secondCountable μ + +theorem innerRegular_isCompact_isClosed_measurableSet_of_finite [PseudoEMetricSpace α] + [CompleteSpace α] [SecondCountableTopology α] [BorelSpace α] + (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegularWRT (fun s ↦ IsCompact s ∧ IsClosed s) MeasurableSet := by + suffices P.InnerRegularWRT (fun s ↦ IsCompact s ∧ IsClosed s) + fun s ↦ MeasurableSet s ∧ P s ≠ ∞ by + convert this + simp only [eq_iff_iff, iff_self_and] + exact fun _ ↦ measure_ne_top P _ + refine Measure.InnerRegularWRT.measurableSet_of_isOpen ?_ ?_ + · exact innerRegularWRT_isCompact_isClosed_isOpen P + · rintro s t ⟨hs_compact, hs_closed⟩ ht_open + rw [diff_eq] + exact ⟨hs_compact.inter_right ht_open.isClosed_compl, + hs_closed.inter (isClosed_compl_iff.mpr ht_open)⟩ + +/-- +On a Polish space, any finite measure is regular with respect to compact and closed sets. In +particular, a finite measure on a Polish space is a tight measure. +-/ +theorem PolishSpace.innerRegular_isCompact_isClosed_measurableSet [TopologicalSpace α] + [PolishSpace α] [BorelSpace α] (P : Measure α) [IsFiniteMeasure P] : + P.InnerRegularWRT (fun s ↦ IsCompact s ∧ IsClosed s) MeasurableSet := by + letI := upgradePolishSpace α + exact innerRegular_isCompact_isClosed_measurableSet_of_finite P + +end MeasureTheory diff --git a/Mathlib/Topology/Instances/ENNReal.lean b/Mathlib/Topology/Instances/ENNReal.lean index d25ba301a1d4d..93f04f375c31f 100644 --- a/Mathlib/Topology/Instances/ENNReal.lean +++ b/Mathlib/Topology/Instances/ENNReal.lean @@ -288,6 +288,35 @@ protected theorem tendsto_atTop_zero [Nonempty β] [SemilatticeSup β] {f : β Tendsto f atTop (𝓝 0) ↔ ∀ ε > 0, ∃ N, ∀ n ≥ N, f n ≤ ε := .trans (atTop_basis.tendsto_iff nhds_zero_basis_Iic) (by simp only [true_and]; rfl) +theorem tendsto_atTop_zero_iff_le_of_antitone {β : Type*} [Nonempty β] [SemilatticeSup β] + {f : β → ℝ≥0∞} (hf : Antitone f) : + Filter.Tendsto f Filter.atTop (𝓝 0) ↔ ∀ ε, 0 < ε → ∃ n : β, f n ≤ ε := by + rw [ENNReal.tendsto_atTop_zero] + refine ⟨fun h ↦ fun ε hε ↦ ?_, fun h ↦ fun ε hε ↦ ?_⟩ + · obtain ⟨n, hn⟩ := h ε hε + exact ⟨n, hn n le_rfl⟩ + · obtain ⟨n, hn⟩ := h ε hε + exact ⟨n, fun m hm ↦ (hf hm).trans hn⟩ + +theorem tendsto_atTop_zero_iff_lt_of_antitone {β : Type*} [Nonempty β] [SemilatticeSup β] + {f : β → ℝ≥0∞} (hf : Antitone f) : + Filter.Tendsto f Filter.atTop (𝓝 0) ↔ ∀ ε, 0 < ε → ∃ n : β, f n < ε := by + rw [ENNReal.tendsto_atTop_zero_iff_le_of_antitone hf] + constructor <;> intro h ε hε + · obtain ⟨n, hn⟩ := h (min 1 (ε / 2)) + (lt_min_iff.mpr ⟨zero_lt_one, (ENNReal.div_pos_iff.mpr ⟨ne_of_gt hε, ENNReal.two_ne_top⟩)⟩) + · refine ⟨n, hn.trans_lt ?_⟩ + by_cases hε_top : ε = ∞ + · rw [hε_top] + exact (min_le_left _ _).trans_lt ENNReal.one_lt_top + refine (min_le_right _ _).trans_lt ?_ + rw [ENNReal.div_lt_iff (Or.inr hε.ne') (Or.inr hε_top)] + conv_lhs => rw [← mul_one ε] + rw [ENNReal.mul_lt_mul_left hε.ne' hε_top] + norm_num + · obtain ⟨n, hn⟩ := h ε hε + exact ⟨n, hn.le⟩ + theorem tendsto_sub : ∀ {a b : ℝ≥0∞}, (a ≠ ∞ ∨ b ≠ ∞) → Tendsto (fun p : ℝ≥0∞ × ℝ≥0∞ => p.1 - p.2) (𝓝 (a, b)) (𝓝 (a - b)) | ∞, ∞, h => by simp only [ne_eq, not_true_eq_false, or_self] at h diff --git a/Mathlib/Topology/UniformSpace/Cauchy.lean b/Mathlib/Topology/UniformSpace/Cauchy.lean index 203ebe020f1ac..18f55b5f95253 100644 --- a/Mathlib/Topology/UniformSpace/Cauchy.lean +++ b/Mathlib/Topology/UniformSpace/Cauchy.lean @@ -645,6 +645,34 @@ theorem CauchySeq.totallyBounded_range {s : ℕ → α} (hs : CauchySeq s) : rcases le_total m n with hm | hm exacts [⟨m, hm, refl_mem_uniformity ha⟩, ⟨n, le_refl n, hn m hm n le_rfl⟩] +/-- Given a family of points `xs n`, a family of entourages `V n` of the diagonal and a family of +natural numbers `u n`, the intersection over `n` of the `V n`-neighborhood of `xs 1, ..., xs (u n)`. +Designed to be relatively compact when `V n` tends to the diagonal. -/ +def interUnionBalls (xs : ℕ → α) (u : ℕ → ℕ) (V : ℕ → Set (α × α)) : Set α := + ⋂ n, ⋃ m ≤ u n, UniformSpace.ball (xs m) (Prod.swap ⁻¹' V n) + +lemma totallyBounded_interUnionBalls {p : ℕ → Prop} {U : ℕ → Set (α × α)} + (H : (uniformity α).HasBasis p U) (xs : ℕ → α) (u : ℕ → ℕ) : + TotallyBounded (interUnionBalls xs u U) := by + rw [Filter.HasBasis.totallyBounded_iff H] + intro i _ + have h_subset : interUnionBalls xs u U + ⊆ ⋃ m ≤ u i, UniformSpace.ball (xs m) (Prod.swap ⁻¹' U i) := + fun x hx ↦ Set.mem_iInter.1 hx i + classical + refine ⟨Finset.image xs (Finset.range (u i + 1)), Finset.finite_toSet _, fun x hx ↦ ?_⟩ + simp only [Finset.coe_image, Finset.coe_range, mem_image, mem_Iio, iUnion_exists, biUnion_and', + iUnion_iUnion_eq_right, Nat.lt_succ_iff] + exact h_subset hx + +/-- The construction `interUnionBalls` is used to have a relatively compact set. -/ +theorem isCompact_closure_interUnionBalls {p : ℕ → Prop} {U : ℕ → Set (α × α)} + (H : (uniformity α).HasBasis p U) [CompleteSpace α] (xs : ℕ → α) (u : ℕ → ℕ) : + IsCompact (closure (interUnionBalls xs u U)) := by + rw [isCompact_iff_totallyBounded_isComplete] + refine ⟨TotallyBounded.closure ?_, isClosed_closure.isComplete⟩ + exact totallyBounded_interUnionBalls H xs u + /-! ### Sequentially complete space From aca5199ef8c76883b69b1d80abe14886b0e5d4cf Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 7 Jan 2025 17:42:10 +0000 Subject: [PATCH 050/681] feat(FTaylorSeries): add lemmas about `dist` between 0th and 1st derivs (#20089) These lemmas are useful to specialize conditions like $$C^{k+\alpha}$$ to low order derivatives. --- .../Calculus/ContDiff/FTaylorSeries.lean | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean index 168c48c5ac9ff..7cc8a905e12ec 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean @@ -412,9 +412,14 @@ theorem iteratedFDerivWithin_zero_eq_comp : iteratedFDerivWithin 𝕜 0 f s = (continuousMultilinearCurryFin0 𝕜 E F).symm ∘ f := rfl +@[simp] +theorem dist_iteratedFDerivWithin_zero (f : E → F) (s : Set E) (x : E) + (g : E → F) (t : Set E) (y : E) : + dist (iteratedFDerivWithin 𝕜 0 f s x) (iteratedFDerivWithin 𝕜 0 g t y) = dist (f x) (g y) := by + simp only [iteratedFDerivWithin_zero_eq_comp, comp_apply, LinearIsometryEquiv.dist_map] + @[simp] theorem norm_iteratedFDerivWithin_zero : ‖iteratedFDerivWithin 𝕜 0 f s x‖ = ‖f x‖ := by - -- Porting note: added `comp_apply`. rw [iteratedFDerivWithin_zero_eq_comp, comp_apply, LinearIsometryEquiv.norm_map] theorem iteratedFDerivWithin_succ_apply_left {n : ℕ} (m : Fin (n + 1) → E) : @@ -442,6 +447,23 @@ theorem norm_fderivWithin_iteratedFDerivWithin {n : ℕ} : -- Porting note: added `comp_apply`. rw [iteratedFDerivWithin_succ_eq_comp_left, comp_apply, LinearIsometryEquiv.norm_map] +@[simp] +theorem dist_iteratedFDerivWithin_one (f g : E → F) {y} + (hsx : UniqueDiffWithinAt 𝕜 s x) (hyt : UniqueDiffWithinAt 𝕜 t y) : + dist (iteratedFDerivWithin 𝕜 1 f s x) (iteratedFDerivWithin 𝕜 1 g t y) + = dist (fderivWithin 𝕜 f s x) (fderivWithin 𝕜 g t y) := by + simp only [iteratedFDerivWithin_succ_eq_comp_left, comp_apply, + LinearIsometryEquiv.dist_map, iteratedFDerivWithin_zero_eq_comp, + LinearIsometryEquiv.comp_fderivWithin, hsx, hyt] + apply (continuousMultilinearCurryFin0 𝕜 E F).symm.toLinearIsometry.postcomp.dist_map + +@[simp] +theorem norm_iteratedFDerivWithin_one (f : E → F) (h : UniqueDiffWithinAt 𝕜 s x) : + ‖iteratedFDerivWithin 𝕜 1 f s x‖ = ‖fderivWithin 𝕜 f s x‖ := by + simp only [← norm_fderivWithin_iteratedFDerivWithin, + iteratedFDerivWithin_zero_eq_comp, LinearIsometryEquiv.comp_fderivWithin _ h] + apply (continuousMultilinearCurryFin0 𝕜 E F).symm.toLinearIsometry.norm_toContinuousLinearMap_comp + theorem iteratedFDerivWithin_succ_apply_right {n : ℕ} (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) (m : Fin (n + 1) → E) : (iteratedFDerivWithin 𝕜 (n + 1) f s x : (Fin (n + 1) → E) → F) m = From f79db55507961d378eafbe7900aac132ff34766f Mon Sep 17 00:00:00 2001 From: Artie Khovanov Date: Tue, 7 Jan 2025 17:42:11 +0000 Subject: [PATCH 051/681] chore(Algebra/Ring): Clean up in SumsOfSquares and Semireal/Defs (#20528) * Make documentation clearer and more concise * Make notation consistent * Make proofs cleaner This PR splits off yet more chore material from #16094 Moves: * `sumSq` -> `AddSubmonoid.sumSq` --- Mathlib/Algebra/Ring/Semireal/Defs.lean | 13 ++- Mathlib/Algebra/Ring/SumsOfSquares.lean | 137 ++++++++++++------------ 2 files changed, 73 insertions(+), 77 deletions(-) diff --git a/Mathlib/Algebra/Ring/Semireal/Defs.lean b/Mathlib/Algebra/Ring/Semireal/Defs.lean index 7b16914e15ab1..cb5317abf618d 100644 --- a/Mathlib/Algebra/Ring/Semireal/Defs.lean +++ b/Mathlib/Algebra/Ring/Semireal/Defs.lean @@ -8,12 +8,11 @@ import Mathlib.Algebra.Ring.SumsOfSquares /-! # Semireal rings -A semireal ring is a non-trivial commutative ring (with unit) in which `-1` is *not* a sum of -squares. Note that `-1` does not make sense in a semiring. +A semireal ring is a non-trivial commutative ring (with unit) in which `-1` is *not* a +sum of squares. -For instance, linearly ordered fields are semireal, because sums of squares are positive and `-1` is -not. More generally, linearly ordered semirings in which `a ≤ b → ∃ c, a + c = b` holds, are -semireal. +For instance, linearly ordered rings are semireal, because sums of squares are positive and `-1` is +not. ## Main declaration @@ -29,8 +28,8 @@ variable (R : Type*) /-- A semireal ring is a non-trivial commutative ring (with unit) in which `-1` is *not* a sum of -squares. Note that `-1` does not make sense in a semiring. Below we define the class `IsSemireal R` -for all additive monoid `R` equipped with a multiplication, a multiplicative unit and a negation. +squares. We define the class `IsSemireal R` +for all additive monoids `R` equipped with a multiplication, a multiplicative unit and a negation. -/ @[mk_iff] class IsSemireal [AddMonoid R] [Mul R] [One R] [Neg R] : Prop where diff --git a/Mathlib/Algebra/Ring/SumsOfSquares.lean b/Mathlib/Algebra/Ring/SumsOfSquares.lean index 64898b4df47db..cd768870f9db6 100644 --- a/Mathlib/Algebra/Ring/SumsOfSquares.lean +++ b/Mathlib/Algebra/Ring/SumsOfSquares.lean @@ -10,114 +10,111 @@ import Mathlib.Algebra.Order.Ring.Defs /-! # Sums of squares -We introduce sums of squares in a type `R` endowed with an `[Add R]`, `[Zero R]` and `[Mul R]` -instances. Sums of squares in `R` are defined by an inductive predicate `IsSumSq : R → Prop`: -`0 : R` is a sum of squares and if `S` is a sum of squares, then for all `a : R`, `a * a + S` is a -sum of squares in `R`. +We introduce a predicate for sums of squares in a ring. -## Main declaration +## Main declarations -- The predicate `IsSumSq : R → Prop`, defining the property of being a sum of squares in `R`. - -## Auxiliary declarations - -- The term `sumSq R` : in an additive monoid with multiplication `R`, we introduce -`sumSq R` as the submonoid of `R` whose carrier is the subset `{S : R | IsSumSq S}`. - -## Theorems - -- `IsSumSq.add`: if `S1` and `S2` are sums of squares in `R`, then so is `S1 + S2`. -- `IsSumSq.nonneg`: in a linearly ordered semiring `R` with an `[ExistsAddOfLE R]` instance, sums of -squares are non-negative. -- `mem_sumSq_of_isSquare`: a square is a sum of squares. -- `AddSubmonoid.closure_isSquare`: the submonoid of `R` generated by the squares in `R` is the set -of sums of squares in `R`. +- `IsSumSq : R → Prop`: for a type `R` with addition, multiplication and a zero, + an inductive predicate defining the property of being a sum of squares in `R`. + `0 : R` is a sum of squares and if `S` is a sum of squares, then, for all `a : R`, + `a * a + s` is a sum of squares. +- `AddMonoid.sumSq R`: the submonoid of sums of squares in an additive monoid `R` + with multiplication. -/ -variable {R : Type*} [Mul R] +variable {R : Type*} /-- -In a type `R` with an addition, a zero element and a multiplication, the property of being a sum of -squares is defined by an inductive predicate: `0 : R` is a sum of squares and if `S` is a sum of -squares, then for all `a : R`, `a * a + S` is a sum of squares in `R`. +The property of being a sum of squares is defined inductively by: +`0 : R` is a sum of squares and if `s : R` is a sum of squares, +then for all `a : R`, `a * a + s` is a sum of squares in `R`. -/ @[mk_iff] -inductive IsSumSq [Add R] [Zero R] : R → Prop - | zero : IsSumSq 0 - | sq_add (a S : R) (pS : IsSumSq S) : IsSumSq (a * a + S) +inductive IsSumSq [Mul R] [Add R] [Zero R] : R → Prop + | zero : IsSumSq 0 + | sq_add (a : R) {s : R} (hs : IsSumSq s) : IsSumSq (a * a + s) @[deprecated (since := "2024-08-09")] alias isSumSq := IsSumSq /-- -If `S1` and `S2` are sums of squares in a semiring `R`, then `S1 + S2` is a sum of squares in `R`. +In an additive monoid with multiplication, +if `s₁` and `s₂` are sums of squares, then `s₁ + s₂` is a sum of squares. -/ -theorem IsSumSq.add [AddMonoid R] {S1 S2 : R} (p1 : IsSumSq S1) - (p2 : IsSumSq S2) : IsSumSq (S1 + S2) := by - induction p1 with - | zero => rw [zero_add]; exact p2 - | sq_add a S pS ih => rw [add_assoc]; exact IsSumSq.sq_add a (S + S2) ih +theorem IsSumSq.add [AddMonoid R] [Mul R] {s₁ s₂ : R} + (h₁ : IsSumSq s₁) (h₂ : IsSumSq s₂) : IsSumSq (s₁ + s₂) := by + induction h₁ <;> simp_all [add_assoc, sq_add] @[deprecated (since := "2024-08-09")] alias isSumSq.add := IsSumSq.add -/-- A finite sum of squares is a sum of squares. -/ -theorem IsSumSq.sum_mul_self {ι : Type*} [AddCommMonoid R] (s : Finset ι) (f : ι → R) : - IsSumSq (∑ i ∈ s, f i * f i) := by - induction s using Finset.cons_induction with - | empty => - simpa only [Finset.sum_empty] using IsSumSq.zero - | cons i s his h => - exact (Finset.sum_cons (β := R) his) ▸ IsSumSq.sq_add (f i) (∑ i ∈ s, f i * f i) h +namespace AddSubmonoid +variable {T : Type*} [AddMonoid T] [Mul T] {s : T} -@[deprecated (since := "2024-12-27")] alias isSumSq_sum_mul_self := IsSumSq.sum_mul_self - -variable (R) in +variable (T) in /-- In an additive monoid with multiplication `R`, `AddSubmonoid.sumSq R` is the submonoid of sums of squares in `R`. -/ -def sumSq [AddMonoid R] : AddSubmonoid R where - carrier := {S : R | IsSumSq S} - zero_mem' := IsSumSq.zero - add_mem' := IsSumSq.add +@[simps] +def sumSq [AddMonoid T] : AddSubmonoid T where + carrier := {s : T | IsSumSq s} + zero_mem' := .zero + add_mem' := .add + +attribute [norm_cast] coe_sumSq -@[deprecated (since := "2024-08-09")] alias SumSqIn := sumSq -@[deprecated (since := "2025-01-03")] alias sumSqIn := sumSq +@[simp] theorem mem_sumSq : s ∈ sumSq T ↔ IsSumSq s := Iff.rfl + +end AddSubmonoid + +@[deprecated (since := "2024-08-09")] alias SumSqIn := AddSubmonoid.sumSq +@[deprecated (since := "2025-01-03")] alias sumSqIn := AddSubmonoid.sumSq +@[deprecated (since := "2025-01-06")] alias sumSq := AddSubmonoid.sumSq /-- -In an additive monoid with multiplication, every square is a sum of squares. By definition, a square -in `R` is a term `x : R` such that `x = y * y` for some `y : R` and in Mathlib this is known as -`IsSquare R` (see Mathlib.Algebra.Group.Even). +In an additive monoid with multiplication, squares are sums of squares +(see Mathlib.Algebra.Group.Even). -/ -theorem mem_sumSq_of_isSquare [AddMonoid R] {x : R} (px : IsSquare x) : x ∈ sumSq R := by - rcases px with ⟨y, py⟩ - rw [py, ← AddMonoid.add_zero (y * y)] - exact IsSumSq.sq_add _ _ IsSumSq.zero +theorem mem_sumSq_of_isSquare [AddMonoid R] [Mul R] {x : R} (hx : IsSquare x) : + x ∈ AddSubmonoid.sumSq R := by + rcases hx with ⟨y, hy⟩ + rw [hy, ← AddMonoid.add_zero (y * y)] + exact IsSumSq.sq_add _ IsSumSq.zero @[deprecated (since := "2024-08-09")] alias SquaresInSumSq := mem_sumSq_of_isSquare @[deprecated (since := "2025-01-03")] alias mem_sumSqIn_of_isSquare := mem_sumSq_of_isSquare /-- In an additive monoid with multiplication `R`, the submonoid generated by the squares is the set of -sums of squares. +sums of squares in `R`. -/ -theorem AddSubmonoid.closure_isSquare [AddMonoid R] : closure {x : R | IsSquare x} = sumSq R := by +theorem AddSubmonoid.closure_isSquare [AddMonoid R] [Mul R] : + closure {x : R | IsSquare x} = sumSq R := by refine le_antisymm (closure_le.2 (fun x hx ↦ mem_sumSq_of_isSquare hx)) (fun x hx ↦ ?_) - induction hx with - | zero => exact zero_mem _ - | sq_add a S _ ih => exact AddSubmonoid.add_mem _ (subset_closure ⟨a, rfl⟩) ih + induction hx <;> aesop @[deprecated (since := "2024-08-09")] alias SquaresAddClosure := AddSubmonoid.closure_isSquare /-- -Let `R` be a linearly ordered semiring in which the property `a ≤ b → ∃ c, a + c = b` holds -(e.g. `R = ℕ`). If `S : R` is a sum of squares in `R`, then `0 ≤ S`. This is used in -`Mathlib.Algebra.Ring.Semireal.Defs` to show that linearly ordered fields are semireal. +In an additive commutative monoid with multiplication, +`∑ i ∈ I, a i * a i` is a sum of squares. +-/ +theorem IsSumSq.sum_mul_self [AddCommMonoid R] [Mul R] {ι : Type*} (I : Finset ι) (a : ι → R) : + IsSumSq (∑ i ∈ I, a i * a i) := by + induction I using Finset.cons_induction with + | empty => simpa using IsSumSq.zero + | cons i _ hi h => exact (Finset.sum_cons (β := R) hi) ▸ IsSumSq.sq_add (a i) h + +@[deprecated (since := "2024-12-27")] alias isSumSq_sum_mul_self := IsSumSq.sum_mul_self + +/-- +In a linearly ordered semiring with the property `a ≤ b → ∃ c, a + c = b` (e.g. `ℕ`), +sums of squares are non-negative. -/ -theorem IsSumSq.nonneg {R : Type*} [LinearOrderedSemiring R] [ExistsAddOfLE R] {S : R} - (pS : IsSumSq S) : 0 ≤ S := by - induction pS with - | zero => simp only [le_refl] - | sq_add x S _ ih => apply add_nonneg ?_ ih; simp only [← pow_two x, sq_nonneg] +theorem IsSumSq.nonneg {R : Type*} [LinearOrderedSemiring R] [ExistsAddOfLE R] {s : R} + (hs : IsSumSq s) : 0 ≤ s := by + induction hs with + | zero => simp only [le_refl] + | sq_add x _ ih => apply add_nonneg ?_ ih; simp only [← pow_two x, sq_nonneg] @[deprecated (since := "2024-08-09")] alias isSumSq.nonneg := IsSumSq.nonneg From 6bfeca124e6fdc47ea317b16669f174e2f2a0390 Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 7 Jan 2025 17:42:13 +0000 Subject: [PATCH 052/681] fix(scripts/technical-debt-metric): avoid division by 0 (#20537) The division by 0 affected #20521: all `ofNat` debts were removed in that PR, so one denominator became 0 giving a [CI error](https://github.com/leanprover-community/mathlib4/actions/runs/12636151506/job/35207580913). This PR fixes the issue. --- scripts/technical-debt-metrics.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/technical-debt-metrics.sh b/scripts/technical-debt-metrics.sh index b3f3df14ec9aa..efe28e4c7e85d 100755 --- a/scripts/technical-debt-metrics.sh +++ b/scripts/technical-debt-metrics.sh @@ -159,12 +159,14 @@ then then printf '
No changes to technical debt.\n' else - printf '%s\n' "${rep}" | + printf '%s\n' "${rep}" | # outputs lines containing `|Current number|Change|Type|`, so + # `$2` refers to `Current number` and `$3` to `Change`. awk -F '|' -v rep="${rep}" ' - BEGIN{total=0; weight=0} + BEGIN{total=0; weight=0; absWeight=0} + {absWeight+=$3+0} (($3+0 == $3) && (!($2+0 == 0))) {total+=1 / $2; weight+=$3 / $2} END{ - average=weight/total + if (total == 0) {average=absWeight} else {average=weight/total} if(average < 0) {change= "Decrease"; average=-average; weight=-weight} else {change= "Increase"} printf("
%s in tech debt: (relative, absolute) = (%4.2f, %4.2f)\n\n%s\n", change, average, weight, rep) }' fi From 576077ae409bbe2ebecd198a418cfab6f0518b82 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 7 Jan 2025 19:44:43 +0000 Subject: [PATCH 053/681] feat(ContDiff): weaken some assumptions (#20368) Assume `ContDiffWithinAt`/`ContDiffAt` instead of `ContDiffOn`/`ContDiff`. --- .../BumpFunction/FiniteDimension.lean | 4 +-- Mathlib/Analysis/Calculus/ContDiff/Basic.lean | 35 ++++++++++--------- .../Analysis/Calculus/ContDiff/Bounds.lean | 6 ++-- .../Calculus/IteratedDeriv/Lemmas.lean | 4 +-- .../Analysis/Distribution/SchwartzSpace.lean | 17 +++++---- .../Fourier/FourierTransformDeriv.lean | 4 +-- 6 files changed, 38 insertions(+), 32 deletions(-) diff --git a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean index 70091c5af4b09..3642e77febe4b 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean @@ -150,10 +150,10 @@ theorem IsOpen.exists_smooth_support_eq {s : Set E} (hs : IsOpen s) : calc ‖iteratedFDeriv ℝ i ((M⁻¹ * δ n) • g n) x‖ = ‖(M⁻¹ * δ n) • iteratedFDeriv ℝ i (g n) x‖ := by rw [iteratedFDeriv_const_smul_apply] - exact (g_smooth n).of_le (mod_cast le_top) + exact (g_smooth n).contDiffAt.of_le (mod_cast le_top) _ = M⁻¹ * δ n * ‖iteratedFDeriv ℝ i (g n) x‖ := by rw [norm_smul _ (iteratedFDeriv ℝ i (g n) x), Real.norm_of_nonneg]; positivity - _ ≤ M⁻¹ * δ n * M := (mul_le_mul_of_nonneg_left ((hR i x).trans (IR i hi)) (by positivity)) + _ ≤ M⁻¹ * δ n * M := by gcongr; exact (hR i x).trans (IR i hi) _ = δ n := by field_simp choose r rpos hr using this have S : ∀ x, Summable fun n => (r n • g n) x := fun x ↦ by diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index 87efceee82a5c..67c4727db222d 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -210,19 +210,22 @@ theorem ContDiff.continuousLinearMap_comp {f : E → F} (g : F →L[𝕜] G) (hf /-- The iterated derivative within a set of the composition with a linear map on the left is obtained by applying the linear map to the iterated derivative. -/ theorem ContinuousLinearMap.iteratedFDerivWithin_comp_left {f : E → F} (g : F →L[𝕜] G) - (hf : ContDiffOn 𝕜 n f s) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) {i : ℕ} (hi : i ≤ n) : + (hf : ContDiffWithinAt 𝕜 n f s x) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) {i : ℕ} (hi : i ≤ n) : iteratedFDerivWithin 𝕜 i (g ∘ f) s x = - g.compContinuousMultilinearMap (iteratedFDerivWithin 𝕜 i f s x) := - ((((hf.of_le hi).ftaylorSeriesWithin hs).continuousLinearMap_comp - g).eq_iteratedFDerivWithin_of_uniqueDiffOn le_rfl hs hx).symm + g.compContinuousMultilinearMap (iteratedFDerivWithin 𝕜 i f s x) := by + rcases hf.contDiffOn' hi (by simp) with ⟨U, hU, hxU, hfU⟩ + rw [← iteratedFDerivWithin_inter_open hU hxU, ← iteratedFDerivWithin_inter_open (f := f) hU hxU] + rw [insert_eq_of_mem hx] at hfU + exact .symm <| (hfU.ftaylorSeriesWithin (hs.inter hU)).continuousLinearMap_comp g + |>.eq_iteratedFDerivWithin_of_uniqueDiffOn le_rfl (hs.inter hU) ⟨hx, hxU⟩ /-- The iterated derivative of the composition with a linear map on the left is obtained by applying the linear map to the iterated derivative. -/ theorem ContinuousLinearMap.iteratedFDeriv_comp_left {f : E → F} (g : F →L[𝕜] G) - (hf : ContDiff 𝕜 n f) (x : E) {i : ℕ} (hi : i ≤ n) : + (hf : ContDiffAt 𝕜 n f x) {i : ℕ} (hi : i ≤ n) : iteratedFDeriv 𝕜 i (g ∘ f) x = g.compContinuousMultilinearMap (iteratedFDeriv 𝕜 i f x) := by simp only [← iteratedFDerivWithin_univ] - exact g.iteratedFDerivWithin_comp_left hf.contDiffOn uniqueDiffOn_univ (mem_univ x) hi + exact g.iteratedFDerivWithin_comp_left hf.contDiffWithinAt uniqueDiffOn_univ (mem_univ x) hi /-- The iterated derivative within a set of the composition with a linear equiv on the left is obtained by applying the linear equiv to the iterated derivative. This is true without @@ -251,7 +254,7 @@ theorem ContinuousLinearEquiv.iteratedFDerivWithin_comp_left (g : F ≃L[𝕜] G /-- Composition with a linear isometry on the left preserves the norm of the iterated derivative within a set. -/ theorem LinearIsometry.norm_iteratedFDerivWithin_comp_left {f : E → F} (g : F →ₗᵢ[𝕜] G) - (hf : ContDiffOn 𝕜 n f s) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) {i : ℕ} (hi : i ≤ n) : + (hf : ContDiffWithinAt 𝕜 n f s x) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) {i : ℕ} (hi : i ≤ n) : ‖iteratedFDerivWithin 𝕜 i (g ∘ f) s x‖ = ‖iteratedFDerivWithin 𝕜 i f s x‖ := by have : iteratedFDerivWithin 𝕜 i (g ∘ f) s x = @@ -263,10 +266,10 @@ theorem LinearIsometry.norm_iteratedFDerivWithin_comp_left {f : E → F} (g : F /-- Composition with a linear isometry on the left preserves the norm of the iterated derivative. -/ theorem LinearIsometry.norm_iteratedFDeriv_comp_left {f : E → F} (g : F →ₗᵢ[𝕜] G) - (hf : ContDiff 𝕜 n f) (x : E) {i : ℕ} (hi : i ≤ n) : + (hf : ContDiffAt 𝕜 n f x) {i : ℕ} (hi : i ≤ n) : ‖iteratedFDeriv 𝕜 i (g ∘ f) x‖ = ‖iteratedFDeriv 𝕜 i f x‖ := by simp only [← iteratedFDerivWithin_univ] - exact g.norm_iteratedFDerivWithin_comp_left hf.contDiffOn uniqueDiffOn_univ (mem_univ x) hi + exact g.norm_iteratedFDerivWithin_comp_left hf.contDiffWithinAt uniqueDiffOn_univ (mem_univ x) hi /-- Composition with a linear isometry equiv on the left preserves the norm of the iterated derivative within a set. -/ @@ -1612,16 +1615,16 @@ theorem ContDiffOn.const_smul {s : Set E} {f : E → F} (c : R) (hf : ContDiffOn variable {i : ℕ} {a : R} -theorem iteratedFDerivWithin_const_smul_apply (hf : ContDiffOn 𝕜 i f s) (hu : UniqueDiffOn 𝕜 s) - (hx : x ∈ s) : iteratedFDerivWithin 𝕜 i (a • f) s x = a • iteratedFDerivWithin 𝕜 i f s x := +theorem iteratedFDerivWithin_const_smul_apply (hf : ContDiffWithinAt 𝕜 i f s x) + (hu : UniqueDiffOn 𝕜 s) (hx : x ∈ s) : + iteratedFDerivWithin 𝕜 i (a • f) s x = a • iteratedFDerivWithin 𝕜 i f s x := (a • (1 : F →L[𝕜] F)).iteratedFDerivWithin_comp_left hf hu hx le_rfl -theorem iteratedFDeriv_const_smul_apply {x : E} (hf : ContDiff 𝕜 i f) : - iteratedFDeriv 𝕜 i (a • f) x = a • iteratedFDeriv 𝕜 i f x := by - simp_rw [← contDiffOn_univ, ← iteratedFDerivWithin_univ] at * - exact iteratedFDerivWithin_const_smul_apply hf uniqueDiffOn_univ (Set.mem_univ _) +theorem iteratedFDeriv_const_smul_apply (hf : ContDiffAt 𝕜 i f x) : + iteratedFDeriv 𝕜 i (a • f) x = a • iteratedFDeriv 𝕜 i f x := + (a • (1 : F →L[𝕜] F)).iteratedFDeriv_comp_left hf le_rfl -theorem iteratedFDeriv_const_smul_apply' {x : E} (hf : ContDiff 𝕜 i f) : +theorem iteratedFDeriv_const_smul_apply' (hf : ContDiffAt 𝕜 i f x) : iteratedFDeriv 𝕜 i (fun x ↦ a • f x) x = a • iteratedFDeriv 𝕜 i f x := iteratedFDeriv_const_smul_apply hf diff --git a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean index c869df9c43a51..e5879e948ab45 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean @@ -546,7 +546,7 @@ theorem norm_iteratedFDeriv_clm_apply {f : E → F →L[𝕜] G} {g : E → F} { (Set.mem_univ x) hn theorem norm_iteratedFDerivWithin_clm_apply_const {f : E → F →L[𝕜] G} {c : F} {s : Set E} {x : E} - {N : WithTop ℕ∞} {n : ℕ} (hf : ContDiffOn 𝕜 N f s) (hs : UniqueDiffOn 𝕜 s) + {N : WithTop ℕ∞} {n : ℕ} (hf : ContDiffWithinAt 𝕜 N f s x) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) (hn : n ≤ N) : ‖iteratedFDerivWithin 𝕜 n (fun y : E => (f y) c) s x‖ ≤ ‖c‖ * ‖iteratedFDerivWithin 𝕜 n f s x‖ := by @@ -559,10 +559,10 @@ theorem norm_iteratedFDerivWithin_clm_apply_const {f : E → F →L[𝕜] G} {c exact f.le_opNorm c theorem norm_iteratedFDeriv_clm_apply_const {f : E → F →L[𝕜] G} {c : F} {x : E} - {N : WithTop ℕ∞} {n : ℕ} (hf : ContDiff 𝕜 N f) (hn : n ≤ N) : + {N : WithTop ℕ∞} {n : ℕ} (hf : ContDiffAt 𝕜 N f x) (hn : n ≤ N) : ‖iteratedFDeriv 𝕜 n (fun y : E => (f y) c) x‖ ≤ ‖c‖ * ‖iteratedFDeriv 𝕜 n f x‖ := by simp only [← iteratedFDerivWithin_univ] - exact norm_iteratedFDerivWithin_clm_apply_const hf.contDiffOn uniqueDiffOn_univ + exact norm_iteratedFDerivWithin_clm_apply_const hf.contDiffWithinAt uniqueDiffOn_univ (Set.mem_univ x) hn end Apply diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean index c10db8c308277..01f21bd7293eb 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean @@ -65,13 +65,13 @@ theorem iteratedDerivWithin_const_sub (hn : 0 < n) (c : F) : @[deprecated (since := "2024-12-10")] alias iteratedDerivWithin_const_neg := iteratedDerivWithin_const_sub -theorem iteratedDerivWithin_const_smul (c : R) (hf : ContDiffOn 𝕜 n f s) : +theorem iteratedDerivWithin_const_smul (c : R) (hf : ContDiffWithinAt 𝕜 n f s x) : iteratedDerivWithin n (c • f) s x = c • iteratedDerivWithin n f s x := by simp_rw [iteratedDerivWithin] rw [iteratedFDerivWithin_const_smul_apply hf h hx] simp only [ContinuousMultilinearMap.smul_apply] -theorem iteratedDerivWithin_const_mul (c : 𝕜) {f : 𝕜 → 𝕜} (hf : ContDiffOn 𝕜 n f s) : +theorem iteratedDerivWithin_const_mul (c : 𝕜) {f : 𝕜 → 𝕜} (hf : ContDiffWithinAt 𝕜 n f s x) : iteratedDerivWithin n (fun z => c * f z) s x = c * iteratedDerivWithin n f s x := by simpa using iteratedDerivWithin_const_smul (F := 𝕜) hx h c hf diff --git a/Mathlib/Analysis/Distribution/SchwartzSpace.lean b/Mathlib/Analysis/Distribution/SchwartzSpace.lean index c5823ee573914..d259fdd46449b 100644 --- a/Mathlib/Analysis/Distribution/SchwartzSpace.lean +++ b/Mathlib/Analysis/Distribution/SchwartzSpace.lean @@ -185,7 +185,7 @@ variable [NormedField 𝕜] [NormedSpace 𝕜 F] [SMulCommClass ℝ 𝕜 F] theorem decay_smul_aux (k n : ℕ) (f : 𝓢(E, F)) (c : 𝕜) (x : E) : ‖x‖ ^ k * ‖iteratedFDeriv ℝ n (c • (f : E → F)) x‖ = ‖c‖ * ‖x‖ ^ k * ‖iteratedFDeriv ℝ n f x‖ := by - rw [mul_comm ‖c‖, mul_assoc, iteratedFDeriv_const_smul_apply (f.smooth _), + rw [mul_comm ‖c‖, mul_assoc, iteratedFDeriv_const_smul_apply (f.smooth _).contDiffAt, norm_smul c (iteratedFDeriv ℝ n (⇑f) x)] end Aux @@ -744,12 +744,15 @@ protected def evalCLM (m : E) : 𝓢(E, E →L[ℝ] F) →L[𝕜] 𝓢(E, F) := rintro ⟨k, n⟩ use {(k, n)}, ‖m‖, norm_nonneg _ intro f x - refine le_trans - (mul_le_mul_of_nonneg_left (norm_iteratedFDeriv_clm_apply_const f.2 (mod_cast le_top)) - (by positivity)) ?_ - move_mul [‖m‖] - gcongr ?_ * ‖m‖ - simp only [Finset.sup_singleton, schwartzSeminormFamily_apply, le_seminorm] + simp only [Finset.sup_singleton, schwartzSeminormFamily_apply] + calc + ‖x‖ ^ k * ‖iteratedFDeriv ℝ n (f · m) x‖ ≤ ‖x‖ ^ k * (‖m‖ * ‖iteratedFDeriv ℝ n f x‖) := by + gcongr + exact norm_iteratedFDeriv_clm_apply_const (f.smooth _).contDiffAt le_rfl + _ ≤ ‖m‖ * SchwartzMap.seminorm 𝕜 k n f := by + move_mul [‖m‖] + gcongr + apply le_seminorm end EvalCLM diff --git a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean index bd20aaa76f0cf..fe95597e697b1 100644 --- a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean +++ b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean @@ -386,8 +386,8 @@ lemma norm_iteratedFDeriv_fourierPowSMulRight -- second step: factor out the `(2 * π) ^ n` factor, and cancel it on both sides. have A : ContDiff ℝ K (fun y ↦ T (fun _ ↦ L y)) := (ContinuousMultilinearMap.contDiff _).comp (contDiff_pi.2 fun _ ↦ L.contDiff) - rw [iteratedFDeriv_const_smul_apply' (hf := (smulRightL ℝ (fun _ ↦ W) - E).isBoundedBilinearMap.contDiff.comp₂ (A.of_le hk) (hf.of_le hk)), + rw [iteratedFDeriv_const_smul_apply' (hf := ((smulRightL ℝ (fun _ ↦ W) + E).isBoundedBilinearMap.contDiff.comp₂ (A.of_le hk) (hf.of_le hk)).contDiffAt), norm_smul (β := V [×k]→L[ℝ] (W [×n]→L[ℝ] E))] simp only [norm_pow, norm_neg, norm_mul, RCLike.norm_ofNat, Complex.norm_eq_abs, abs_ofReal, _root_.abs_of_nonneg pi_nonneg, abs_I, mul_one, mul_assoc] From b7ad83b4b5c92960f75d7a65314511c5ff9dcb01 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 7 Jan 2025 19:57:25 +0000 Subject: [PATCH 054/681] feat(LowerUpperTopology): add lemmas (#20465) Add lemmas supporting a future refactor of `LowerSemicontinuous`. --- .../Topology/Order/LowerUpperTopology.lean | 57 +++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/Mathlib/Topology/Order/LowerUpperTopology.lean b/Mathlib/Topology/Order/LowerUpperTopology.lean index 34ccdbc54eeb5..2f58eb8afa600 100644 --- a/Mathlib/Topology/Order/LowerUpperTopology.lean +++ b/Mathlib/Topology/Order/LowerUpperTopology.lean @@ -102,16 +102,32 @@ protected def rec {β : WithLower α → Sort*} (h : ∀ a, β (toLower a)) : instance [Nonempty α] : Nonempty (WithLower α) := ‹Nonempty α› instance [Inhabited α] : Inhabited (WithLower α) := ‹Inhabited α› +section Preorder + variable [Preorder α] {s : Set α} instance : Preorder (WithLower α) := ‹Preorder α› -instance : TopologicalSpace (WithLower α) := lower α +instance : TopologicalSpace (WithLower α) := lower (WithLower α) + +@[simp] lemma toLower_le_toLower {x y : α} : toLower x ≤ toLower y ↔ x ≤ y := .rfl +@[simp] lemma toLower_lt_toLower {x y : α} : toLower x < toLower y ↔ x < y := .rfl +@[simp] lemma ofLower_le_ofLower {x y : WithLower α} : ofLower x ≤ ofLower y ↔ x ≤ y := .rfl +@[simp] lemma ofLower_lt_ofLower {x y : WithLower α} : ofLower x < ofLower y ↔ x < y := .rfl -lemma isOpen_preimage_ofLower : IsOpen (ofLower ⁻¹' s) ↔ (lower α).IsOpen s := Iff.rfl +lemma isOpen_preimage_ofLower : IsOpen (ofLower ⁻¹' s) ↔ IsOpen[lower α] s := Iff.rfl -lemma isOpen_def (T : Set (WithLower α)) : IsOpen T ↔ (lower α).IsOpen (WithLower.toLower ⁻¹' T) := +lemma isOpen_def (T : Set (WithLower α)) : IsOpen T ↔ IsOpen[lower α] (WithLower.toLower ⁻¹' T) := Iff.rfl +theorem continuous_toLower [TopologicalSpace α] [ClosedIciTopology α] : + Continuous (toLower : α → WithLower α) := + continuous_generateFrom_iff.mpr <| by rintro _ ⟨a, rfl⟩; exact isClosed_Ici.isOpen_compl + +end Preorder + +instance [PartialOrder α] : PartialOrder (WithLower α) := ‹PartialOrder α› +instance [LinearOrder α] : LinearOrder (WithLower α) := ‹LinearOrder α› + end WithLower /-- Type synonym for a preorder equipped with the upper topology. -/ @@ -141,15 +157,31 @@ protected def rec {β : WithUpper α → Sort*} (h : ∀ a, β (toUpper a)) : instance [Nonempty α] : Nonempty (WithUpper α) := ‹Nonempty α› instance [Inhabited α] : Inhabited (WithUpper α) := ‹Inhabited α› +section Preorder + variable [Preorder α] {s : Set α} instance : Preorder (WithUpper α) := ‹Preorder α› -instance : TopologicalSpace (WithUpper α) := upper α +instance : TopologicalSpace (WithUpper α) := upper (WithUpper α) + +@[simp] lemma toUpper_le_toUpper {x y : α} : toUpper x ≤ toUpper y ↔ x ≤ y := .rfl +@[simp] lemma toUpper_lt_toUpper {x y : α} : toUpper x < toUpper y ↔ x < y := .rfl +@[simp] lemma ofUpper_le_ofUpper {x y : WithUpper α} : ofUpper x ≤ ofUpper y ↔ x ≤ y := .rfl +@[simp] lemma ofUpper_lt_ofUpper {x y : WithUpper α} : ofUpper x < ofUpper y ↔ x < y := .rfl lemma isOpen_preimage_ofUpper : IsOpen (ofUpper ⁻¹' s) ↔ (upper α).IsOpen s := Iff.rfl lemma isOpen_def {s : Set (WithUpper α)} : IsOpen s ↔ (upper α).IsOpen (toUpper ⁻¹' s) := Iff.rfl +theorem continuous_toUpper [TopologicalSpace α] [ClosedIicTopology α] : + Continuous (toUpper : α → WithUpper α) := + continuous_generateFrom_iff.mpr <| by rintro _ ⟨a, rfl⟩; exact isClosed_Iic.isOpen_compl + +end Preorder + +instance [PartialOrder α] : PartialOrder (WithUpper α) := ‹PartialOrder α› +instance [LinearOrder α] : LinearOrder (WithUpper α) := ‹LinearOrder α› + end WithUpper /-- @@ -236,6 +268,11 @@ theorem isLowerSet_of_isOpen (h : IsOpen s) : IsLowerSet s := by theorem isUpperSet_of_isClosed (h : IsClosed s) : IsUpperSet s := isLowerSet_compl.1 <| isLowerSet_of_isOpen h.isOpen_compl +theorem tendsto_nhds_iff_not_le {β : Type*} {f : β → α} {l : Filter β} {x : α} : + Filter.Tendsto f l (𝓝 x) ↔ ∀ y, ¬y ≤ x → ∀ᶠ z in l, ¬y ≤ f z := by + simp [topology_eq_lowerTopology, tendsto_nhds_generateFrom_iff, Filter.Eventually, Ici, + compl_setOf] + /-- The closure of a singleton `{a}` in the lower topology is the left-closed right-infinite interval [a, ∞). @@ -292,6 +329,10 @@ lemma isTopologicalBasis_insert_univ_subbasis : use b ⊓ c rw [compl_Ici, compl_Ici, compl_Ici, Iio_inter_Iio]) +theorem tendsto_nhds_iff_lt {β : Type*} {f : β → α} {l : Filter β} {x : α} : + Filter.Tendsto f l (𝓝 x) ↔ ∀ y, x < y → ∀ᶠ z in l, f z < y := by + simp only [tendsto_nhds_iff_not_le, not_le] + end LinearOrder section CompleteLinearOrder @@ -382,6 +423,10 @@ theorem isUpperSet_of_isOpen (h : IsOpen s) : IsUpperSet s := theorem isLowerSet_of_isClosed (h : IsClosed s) : IsLowerSet s := isUpperSet_compl.1 <| isUpperSet_of_isOpen h.isOpen_compl +theorem tendsto_nhds_iff_not_le {β : Type*} {f : β → α} {l : Filter β} {x : α} : + Filter.Tendsto f l (𝓝 x) ↔ ∀ y, ¬x ≤ y → ∀ᶠ z in l, ¬f z ≤ y := + IsLower.tendsto_nhds_iff_not_le (α := αᵒᵈ) + /-- The closure of a singleton `{a}` in the upper topology is the left-infinite right-closed interval (-∞,a]. @@ -421,6 +466,10 @@ lemma isTopologicalBasis_insert_univ_subbasis : IsTopologicalBasis (insert univ {s : Set α | ∃ a, (Iic a)ᶜ = s}) := IsLower.isTopologicalBasis_insert_univ_subbasis (α := αᵒᵈ) +theorem tendsto_nhds_iff_lt {β : Type*} {f : β → α} {l : Filter β} {x : α} : + Filter.Tendsto f l (𝓝 x) ↔ ∀ y < x, ∀ᶠ z in l, y < f z := + IsLower.tendsto_nhds_iff_lt (α := αᵒᵈ) + end LinearOrder section CompleteLinearOrder From f100ec8bae32947af361f8bf641ea4e8195642c6 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 7 Jan 2025 19:57:26 +0000 Subject: [PATCH 055/681] feat(ContDiff): add `iteratedFDeriv_comp` (#20472) --- Mathlib/Analysis/Calculus/ContDiff/Basic.lean | 39 +++++++++++++++++++ Mathlib/Analysis/Calculus/ContDiff/Defs.lean | 12 ++++++ 2 files changed, 51 insertions(+) diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index 67c4727db222d..75de38f4c2f73 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -703,6 +703,45 @@ theorem ContDiff.comp_contDiffAt {g : F → G} {f : E → F} (x : E) (hg : ContD (hf : ContDiffAt 𝕜 n f x) : ContDiffAt 𝕜 n (g ∘ f) x := hg.comp_contDiffWithinAt hf +theorem iteratedFDerivWithin_comp_of_eventually_mem {t : Set F} + (hg : ContDiffWithinAt 𝕜 n g t (f x)) (hf : ContDiffWithinAt 𝕜 n f s x) + (ht : UniqueDiffOn 𝕜 t) (hs : UniqueDiffOn 𝕜 s) (hxs : x ∈ s) (hst : ∀ᶠ y in 𝓝[s] x, f y ∈ t) + {i : ℕ} (hi : i ≤ n) : + iteratedFDerivWithin 𝕜 i (g ∘ f) s x = + (ftaylorSeriesWithin 𝕜 g t (f x)).taylorComp (ftaylorSeriesWithin 𝕜 f s x) i := by + obtain ⟨u, hxu, huo, hfu, hgu⟩ : ∃ u, x ∈ u ∧ IsOpen u ∧ + HasFTaylorSeriesUpToOn i f (ftaylorSeriesWithin 𝕜 f s) (s ∩ u) ∧ + HasFTaylorSeriesUpToOn i g (ftaylorSeriesWithin 𝕜 g t) (f '' (s ∩ u)) := by + have hxt : f x ∈ t := hst.self_of_nhdsWithin hxs + have hf_tendsto : Tendsto f (𝓝[s] x) (𝓝[t] (f x)) := + tendsto_nhdsWithin_iff.mpr ⟨hf.continuousWithinAt, hst⟩ + have H₁ : ∀ᶠ u in (𝓝[s] x).smallSets, + HasFTaylorSeriesUpToOn i f (ftaylorSeriesWithin 𝕜 f s) u := + hf.eventually_hasFTaylorSeriesUpToOn hs hxs hi + have H₂ : ∀ᶠ u in (𝓝[s] x).smallSets, + HasFTaylorSeriesUpToOn i g (ftaylorSeriesWithin 𝕜 g t) (f '' u) := + hf_tendsto.image_smallSets.eventually (hg.eventually_hasFTaylorSeriesUpToOn ht hxt hi) + rcases (nhdsWithin_basis_open _ _).smallSets.eventually_iff.mp (H₁.and H₂) + with ⟨u, ⟨hxu, huo⟩, hu⟩ + exact ⟨u, hxu, huo, hu (by simp [inter_comm])⟩ + exact .symm <| (hgu.comp hfu (mapsTo_image _ _)).eq_iteratedFDerivWithin_of_uniqueDiffOn le_rfl + (hs.inter huo) ⟨hxs, hxu⟩ |>.trans <| iteratedFDerivWithin_inter_open huo hxu + +theorem iteratedFDerivWithin_comp {t : Set F} (hg : ContDiffWithinAt 𝕜 n g t (f x)) + (hf : ContDiffWithinAt 𝕜 n f s x) (ht : UniqueDiffOn 𝕜 t) (hs : UniqueDiffOn 𝕜 s) + (hx : x ∈ s) (hst : MapsTo f s t) {i : ℕ} (hi : i ≤ n) : + iteratedFDerivWithin 𝕜 i (g ∘ f) s x = + (ftaylorSeriesWithin 𝕜 g t (f x)).taylorComp (ftaylorSeriesWithin 𝕜 f s x) i := + iteratedFDerivWithin_comp_of_eventually_mem hg hf ht hs hx (eventually_mem_nhdsWithin.mono hst) hi + +theorem iteratedFDeriv_comp (hg : ContDiffAt 𝕜 n g (f x)) (hf : ContDiffAt 𝕜 n f x) + {i : ℕ} (hi : i ≤ n) : + iteratedFDeriv 𝕜 i (g ∘ f) x = + (ftaylorSeries 𝕜 g (f x)).taylorComp (ftaylorSeries 𝕜 f x) i := by + simp only [← iteratedFDerivWithin_univ, ← ftaylorSeriesWithin_univ] + exact iteratedFDerivWithin_comp hg.contDiffWithinAt hf.contDiffWithinAt + uniqueDiffOn_univ uniqueDiffOn_univ (mem_univ _) (mapsTo_univ _ _) hi + /-! ### Smoothness of projections -/ diff --git a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean index 8b8a3b55c82e5..1224f6b8ffeae 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean @@ -693,6 +693,18 @@ theorem iteratedFDerivWithin_subset {n : ℕ} (st : s ⊆ t) (hs : UniqueDiffOn iteratedFDerivWithin 𝕜 n f s x = iteratedFDerivWithin 𝕜 n f t x := (((h.ftaylorSeriesWithin ht).mono st).eq_iteratedFDerivWithin_of_uniqueDiffOn le_rfl hs hx).symm +theorem ContDiffWithinAt.eventually_hasFTaylorSeriesUpToOn {f : E → F} {s : Set E} {a : E} + (h : ContDiffWithinAt 𝕜 n f s a) (hs : UniqueDiffOn 𝕜 s) (ha : a ∈ s) {m : ℕ} (hm : m ≤ n) : + ∀ᶠ t in (𝓝[s] a).smallSets, HasFTaylorSeriesUpToOn m f (ftaylorSeriesWithin 𝕜 f s) t := by + rcases h.contDiffOn' hm (by simp) with ⟨U, hUo, haU, hfU⟩ + have : ∀ᶠ t in (𝓝[s] a).smallSets, t ⊆ s ∩ U := by + rw [eventually_smallSets_subset] + exact inter_mem_nhdsWithin _ <| hUo.mem_nhds haU + refine this.mono fun t ht ↦ .mono ?_ ht + rw [insert_eq_of_mem ha] at hfU + refine (hfU.ftaylorSeriesWithin (hs.inter hUo)).congr_series fun k hk x hx ↦ ?_ + exact iteratedFDerivWithin_inter_open hUo hx.2 + /-- On a set with unique differentiability, an analytic function is automatically `C^ω`, as its successive derivatives are also analytic. This does not require completeness of the space. See also `AnalyticOn.contDiffOn_of_completeSpace`.-/ From cac643fbed8871b8f5077c7d068c3fd69ad5d511 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 7 Jan 2025 20:10:54 +0000 Subject: [PATCH 056/681] feat(FDeriv/Equiv): generalize `HasFDerivAt.of_local_left_inverse` (#20516) ... to `HasFDerivWithinAt.of_local_left_inverse`. --- Mathlib/Analysis/Calculus/FDeriv/Equiv.lean | 39 ++++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean index b859dc97ba096..6445fa96ecce5 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean @@ -322,6 +322,30 @@ theorem comp_fderiv' {f : G → E} : end LinearIsometryEquiv +/-- If `f (g y) = y` for `y` in a neighborhood of `a` within `t`, +`g` maps a neighborhood of `a` within `t` to a neighborhood of `g a` within `s`, +and `f` has an invertible derivative `f'` at `g a` within `s`, +then `g` has the derivative `f'⁻¹` at `a` within `t`. + +This is one of the easy parts of the inverse function theorem: it assumes that we already have an +inverse function. -/ +theorem HasFDerivWithinAt.of_local_left_inverse {g : F → E} {f' : E ≃L[𝕜] F} {a : F} {t : Set F} + (hg : Tendsto g (𝓝[t] a) (𝓝[s] (g a))) (hf : HasFDerivWithinAt f (f' : E →L[𝕜] F) s (g a)) + (ha : a ∈ t) (hfg : ∀ᶠ y in 𝓝[t] a, f (g y) = y) : + HasFDerivWithinAt g (f'.symm : F →L[𝕜] E) t a := by + have : (fun x : F => g x - g a - f'.symm (x - a)) =O[𝓝[t] a] + fun x : F => f' (g x - g a) - (x - a) := + ((f'.symm : F →L[𝕜] E).isBigO_comp _ _).congr (fun x ↦ by simp) fun _ ↦ rfl + refine .of_isLittleO <| this.trans_isLittleO ?_ + clear this + refine ((hf.isLittleO.comp_tendsto hg).symm.congr' (hfg.mono ?_) .rfl).trans_isBigO ?_ + · intro p hp + simp [hp, hfg.self_of_nhdsWithin ha] + · refine ((hf.isBigO_sub_rev f'.antilipschitz).comp_tendsto hg).congr' + (Eventually.of_forall fun _ => rfl) (hfg.mono ?_) + rintro p hp + simp only [(· ∘ ·), hp, hfg.self_of_nhdsWithin ha] + /-- If `f (g y) = y` for `y` in some neighborhood of `a`, `g` is continuous at `a`, and `f` has an invertible derivative `f'` at `g a` in the strict sense, then `g` has the derivative `f'⁻¹` at `a` in the strict sense. @@ -357,19 +381,8 @@ an inverse function. -/ theorem HasFDerivAt.of_local_left_inverse {f : E → F} {f' : E ≃L[𝕜] F} {g : F → E} {a : F} (hg : ContinuousAt g a) (hf : HasFDerivAt f (f' : E →L[𝕜] F) (g a)) (hfg : ∀ᶠ y in 𝓝 a, f (g y) = y) : HasFDerivAt g (f'.symm : F →L[𝕜] E) a := by - have : (fun x : F => g x - g a - f'.symm (x - a)) =O[𝓝 a] - fun x : F => f' (g x - g a) - (x - a) := by - refine ((f'.symm : F →L[𝕜] E).isBigO_comp _ _).congr (fun x => ?_) fun _ => rfl - simp - refine HasFDerivAtFilter.of_isLittleO <| this.trans_isLittleO ?_ - clear this - refine ((hf.isLittleO.comp_tendsto hg).symm.congr' (hfg.mono ?_) .rfl).trans_isBigO ?_ - · intro p hp - simp [hp, hfg.self_of_nhds] - · refine ((hf.isBigO_sub_rev f'.antilipschitz).comp_tendsto hg).congr' - (Eventually.of_forall fun _ => rfl) (hfg.mono ?_) - rintro p hp - simp only [(· ∘ ·), hp, hfg.self_of_nhds] + simp only [← hasFDerivWithinAt_univ, ← nhdsWithin_univ] at hf hfg ⊢ + exact hf.of_local_left_inverse (.inf hg (by simp)) (mem_univ _) hfg /-- If `f` is a partial homeomorphism defined on a neighbourhood of `f.symm a`, and `f` has an invertible derivative `f'` in the sense of strict differentiability at `f.symm a`, then `f.symm` has From ddb5f7106f88ba3315647eb0b6299ccd2c836c71 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 7 Jan 2025 20:10:55 +0000 Subject: [PATCH 057/681] chore(Multilinear/Basic): generalize the `SMul` instance (#20536) --- Mathlib/LinearAlgebra/Multilinear/Basic.lean | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index 578e4ff4923d4..227f360fbe06f 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -195,20 +195,18 @@ theorem zero_apply (m : ∀ i, M₁ i) : (0 : MultilinearMap R M₁ M₂) m = 0 section SMul -variable {R' A : Type*} [Monoid R'] [Semiring A] [∀ i, Module A (M₁ i)] [DistribMulAction R' M₂] - [Module A M₂] [SMulCommClass A R' M₂] +variable [DistribSMul S M₂] [SMulCommClass R S M₂] -instance : SMul R' (MultilinearMap A M₁ M₂) := +instance : SMul S (MultilinearMap R M₁ M₂) := ⟨fun c f => ⟨fun m => c • f m, fun m i x y => by simp [smul_add], fun l i x d => by simp [← smul_comm x c (_ : M₂)]⟩⟩ @[simp] -theorem smul_apply (f : MultilinearMap A M₁ M₂) (c : R') (m : ∀ i, M₁ i) : (c • f) m = c • f m := +theorem smul_apply (f : MultilinearMap R M₁ M₂) (c : S) (m : ∀ i, M₁ i) : (c • f) m = c • f m := rfl -theorem coe_smul (c : R') (f : MultilinearMap A M₁ M₂) : ⇑(c • f) = c • (⇑ f) := - rfl +theorem coe_smul (c : S) (f : MultilinearMap R M₁ M₂) : ⇑(c • f) = c • (⇑ f) := rfl end SMul From 22296704febe701a1b70fb6b31f5a2fd2b65add6 Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Tue, 7 Jan 2025 20:32:56 +0000 Subject: [PATCH 058/681] feat(NumberTheory/AbelSummation): add more results (#19942) - Add versions for when the endpoints are `Nat` (for convenience). - Add limit versions for when the endpoint tends to infinity. - Add summability criteria using Abel summation --- Mathlib.lean | 1 + .../Normed/Module/FiniteDimension.lean | 5 + Mathlib/NumberTheory/AbelSummation.lean | 276 +++++++++++++++--- Mathlib/Topology/Order/IsLocallyClosed.lean | 49 ++++ 4 files changed, 289 insertions(+), 42 deletions(-) create mode 100644 Mathlib/Topology/Order/IsLocallyClosed.lean diff --git a/Mathlib.lean b/Mathlib.lean index c0d76b970d1db..276dd9ea42536 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5406,6 +5406,7 @@ import Mathlib.Topology.Order.Hom.Basic import Mathlib.Topology.Order.Hom.Esakia import Mathlib.Topology.Order.IntermediateValue import Mathlib.Topology.Order.IsLUB +import Mathlib.Topology.Order.IsLocallyClosed import Mathlib.Topology.Order.Lattice import Mathlib.Topology.Order.LawsonTopology import Mathlib.Topology.Order.LeftRight diff --git a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean index 3620ce5749a6c..90fc73c10bcf6 100644 --- a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean +++ b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean @@ -638,6 +638,11 @@ theorem summable_norm_iff {α E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ alias ⟨_, Summable.norm⟩ := summable_norm_iff +theorem summable_of_sum_range_norm_le {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + [FiniteDimensional ℝ E] {c : ℝ} {f : ℕ → E} (h : ∀ n, ∑ i ∈ Finset.range n, ‖f i‖ ≤ c) : + Summable f := + summable_norm_iff.mp <| summable_of_sum_range_le (fun _ ↦ norm_nonneg _) h + theorem summable_of_isBigO' {ι E F : Type*} [NormedAddCommGroup E] [CompleteSpace E] [NormedAddCommGroup F] [NormedSpace ℝ F] [FiniteDimensional ℝ F] {f : ι → E} {g : ι → F} (hg : Summable g) (h : f =O[cofinite] g) : Summable f := diff --git a/Mathlib/NumberTheory/AbelSummation.lean b/Mathlib/NumberTheory/AbelSummation.lean index 843b01ff64820..202136f5c40ad 100644 --- a/Mathlib/NumberTheory/AbelSummation.lean +++ b/Mathlib/NumberTheory/AbelSummation.lean @@ -3,7 +3,10 @@ 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.MeasureTheory.Integral.FundThmCalculus +import Mathlib.MeasureTheory.Function.Floor +import Mathlib.MeasureTheory.Integral.Asymptotics +import Mathlib.MeasureTheory.Integral.IntegralEqImproper +import Mathlib.Topology.Order.IsLocallyClosed /-! # Abel's summation formula @@ -13,14 +16,25 @@ We prove several versions of Abel's summation formula. ## Results * `sum_mul_eq_sub_sub_integral_mul`: general statement of the formula for a sum between two -(nonnegative) reals `a` and `b`. + (nonnegative) reals `a` and `b`. * `sum_mul_eq_sub_integral_mul`: a specialized version of `sum_mul_eq_sub_sub_integral_mul` for the case `a = 0`. - * `sum_mul_eq_sub_integral_mul`: a specialized version of `sum_mul_eq_sub_integral_mul` for +* `sum_mul_eq_sub_integral_mul₀`: a specialized version of `sum_mul_eq_sub_integral_mul` for when the first coefficient of the sequence is `0`. This is useful for `ArithmeticFunction`. +Primed versions of the three results above are also stated for when the endpoints are `Nat`. + +* `tendsto_sum_mul_atTop_nhds_one_sub_integral`: limit version of `sum_mul_eq_sub_integral_mul` + when `a` tends to `∞`. + +* `tendsto_sum_mul_atTop_nhds_one_sub_integral₀`: limit version of `sum_mul_eq_sub_integral_mul₀` + when `a` tends to `∞`. + +* `summable_mul_of_bigO_atTop`: let `c : ℕ → 𝕜` and `f : ℝ → 𝕜` with `𝕜 = ℝ` or `ℂ`, prove the + summability of `n ↦ (c n) * (f n)` using Abel's formula under some `bigO` assumptions at infinity. + ## References * @@ -29,12 +43,14 @@ We prove several versions of Abel's summation formula. noncomputable section -open Finset intervalIntegral MeasureTheory IntervalIntegrable +open Finset MeasureTheory variable {𝕜 : Type*} [RCLike 𝕜] (c : ℕ → 𝕜) {f : ℝ → 𝕜} {a b : ℝ} namespace abelSummationProof +open intervalIntegral IntervalIntegrable + private theorem sumlocc (n : ℕ) : ∀ᵐ t, t ∈ Set.Icc (n : ℝ) (n + 1) → ∑ k ∈ Icc 0 ⌊t⌋₊, c k = ∑ k ∈ Icc 0 n, c k := by filter_upwards [Ico_ae_eq_Icc] with t h ht @@ -67,31 +83,40 @@ private theorem ineqofmemIco' {k : ℕ} (hk : k ∈ Ico (⌊a⌋₊ + 1) ⌊b⌋ a ≤ k ∧ k + 1 ≤ b := ineqofmemIco (by rwa [← Finset.coe_Ico]) -private theorem integrablemulsum (ha : 0 ≤ a) (hb : ⌊a⌋₊ < ⌊b⌋₊) - (hf_int : IntegrableOn (deriv f) (Set.Icc a b)) : - IntegrableOn (fun t ↦ deriv f t * (∑ k ∈ Icc 0 ⌊t⌋₊, c k)) (Set.Icc a b) := by - have h_locint {t₁ t₂ : ℝ} {n : ℕ} (h : t₁ ≤ t₂) (h₁ : n ≤ t₁) (h₂ : t₂ ≤ n + 1) - (h₃ : a ≤ t₁) (h₄ : t₂ ≤ b) : - IntervalIntegrable (fun t ↦ deriv f t * (∑ k ∈ Icc 0 ⌊t⌋₊, c k)) volume t₁ t₂ := by - rw [intervalIntegrable_iff_integrableOn_Icc_of_le h] - exact (IntegrableOn.mono_set (hf_int.mul_const _) (Set.Icc_subset_Icc h₃ h₄)).congr - <| ae_restrict_of_ae_restrict_of_subset (Set.Icc_subset_Icc h₁ h₂) - <| (ae_restrict_iff' measurableSet_Icc).mpr - (by filter_upwards [sumlocc c n] with t h ht using by rw [h ht]) - have aux1 : 0 ≤ b := (Nat.pos_of_floor_pos <| (Nat.zero_le _).trans_lt hb).le - have aux2 : ⌊a⌋₊ + 1 ≤ b := by rwa [← Nat.cast_add_one, ← Nat.le_floor_iff aux1] - have aux3 : a ≤ ⌊a⌋₊ + 1 := (Nat.lt_floor_add_one _).le - have aux4 : a ≤ ⌊b⌋₊ := le_of_lt (by rwa [← Nat.floor_lt ha]) - -- now break up into 3 subintervals - rw [← intervalIntegrable_iff_integrableOn_Icc_of_le (aux3.trans aux2)] - have I1 : IntervalIntegrable _ volume a ↑(⌊a⌋₊ + 1) := - h_locint (mod_cast aux3) (Nat.floor_le ha) (mod_cast le_rfl) le_rfl (mod_cast aux2) - have I2 : IntervalIntegrable _ volume ↑(⌊a⌋₊ + 1) ⌊b⌋₊ := - trans_iterate_Ico hb fun k hk ↦ h_locint (mod_cast k.le_succ) - le_rfl (mod_cast le_rfl) (ineqofmemIco hk).1 (mod_cast (ineqofmemIco hk).2) - have I3 : IntervalIntegrable _ volume ⌊b⌋₊ b := - h_locint (Nat.floor_le aux1) le_rfl (Nat.lt_floor_add_one _).le aux4 le_rfl - exact (I1.trans I2).trans I3 +private theorem integrablemulsum (ha : 0 ≤ a) {g : ℝ → 𝕜} (hg_int : IntegrableOn g (Set.Icc a b)) : + IntegrableOn (fun t ↦ g t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) (Set.Icc a b) := by + obtain hab | hab := le_or_gt a b + · obtain hb | hb := eq_or_lt_of_le (Nat.floor_le_floor hab) + · have : ∀ᵐ t, t ∈ Set.Icc a b → ∑ k ∈ Icc 0 ⌊a⌋₊, c k = ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by + filter_upwards [sumlocc c ⌊a⌋₊] with t ht₁ ht₂ + rw [ht₁ ⟨(Nat.floor_le ha).trans ht₂.1, hb ▸ ht₂.2.trans (Nat.lt_floor_add_one b).le⟩] + rw [← ae_restrict_iff' measurableSet_Icc] at this + exact IntegrableOn.congr_fun_ae + (hg_int.mul_const _) ((Filter.EventuallyEq.refl _ g).mul this) + · have h_locint {t₁ t₂ : ℝ} {n : ℕ} (h : t₁ ≤ t₂) (h₁ : n ≤ t₁) (h₂ : t₂ ≤ n + 1) + (h₃ : a ≤ t₁) (h₄ : t₂ ≤ b) : + IntervalIntegrable (fun t ↦ g t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) volume t₁ t₂ := by + rw [intervalIntegrable_iff_integrableOn_Icc_of_le h] + exact (IntegrableOn.mono_set (hg_int.mul_const _) (Set.Icc_subset_Icc h₃ h₄)).congr + <| ae_restrict_of_ae_restrict_of_subset (Set.Icc_subset_Icc h₁ h₂) + <| (ae_restrict_iff' measurableSet_Icc).mpr + (by filter_upwards [sumlocc c n] with t h ht using by rw [h ht]) + have aux1 : 0 ≤ b := (Nat.pos_of_floor_pos <| (Nat.zero_le _).trans_lt hb).le + have aux2 : ⌊a⌋₊ + 1 ≤ b := by rwa [← Nat.cast_add_one, ← Nat.le_floor_iff aux1] + have aux3 : a ≤ ⌊a⌋₊ + 1 := (Nat.lt_floor_add_one _).le + have aux4 : a ≤ ⌊b⌋₊ := le_of_lt (by rwa [← Nat.floor_lt ha]) + -- now break up into 3 subintervals + rw [← intervalIntegrable_iff_integrableOn_Icc_of_le (aux3.trans aux2)] + have I1 : IntervalIntegrable _ volume a ↑(⌊a⌋₊ + 1) := + h_locint (mod_cast aux3) (Nat.floor_le ha) (mod_cast le_rfl) le_rfl (mod_cast aux2) + have I2 : IntervalIntegrable _ volume ↑(⌊a⌋₊ + 1) ⌊b⌋₊ := + trans_iterate_Ico hb fun k hk ↦ h_locint (mod_cast k.le_succ) + le_rfl (mod_cast le_rfl) (ineqofmemIco hk).1 (mod_cast (ineqofmemIco hk).2) + have I3 : IntervalIntegrable _ volume ⌊b⌋₊ b := + h_locint (Nat.floor_le aux1) le_rfl (Nat.lt_floor_add_one _).le aux4 le_rfl + exact (I1.trans I2).trans I3 + · rw [Set.Icc_eq_empty_of_lt hab] + exact integrableOn_empty /-- Abel's summation formula. -/ theorem _root_.sum_mul_eq_sub_sub_integral_mul (ha : 0 ≤ a) (hab : a ≤ b) @@ -99,7 +124,7 @@ theorem _root_.sum_mul_eq_sub_sub_integral_mul (ha : 0 ≤ a) (hab : a ≤ b) (hf_int : IntegrableOn (deriv f) (Set.Icc a b)) : ∑ k ∈ Ioc ⌊a⌋₊ ⌊b⌋₊, f k * c k = f b * (∑ k ∈ Icc 0 ⌊b⌋₊, c k) - f a * (∑ k ∈ Icc 0 ⌊a⌋₊, c k) - - ∫ t in Set.Ioc a b, deriv f t * (∑ k ∈ Icc 0 ⌊t⌋₊, c k) := by + ∫ t in Set.Ioc a b, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by rw [← integral_of_le hab] have aux1 : ⌊a⌋₊ ≤ a := Nat.floor_le ha have aux2 : b ≤ ⌊b⌋₊ + 1 := (Nat.lt_floor_add_one _).le @@ -129,45 +154,212 @@ theorem _root_.sum_mul_eq_sub_sub_integral_mul (ha : 0 ≤ a) (hab : a ≤ b) -- (Note we have 5 goals, but the 1st and 3rd are identical. TODO: find a non-hacky way of dealing -- with both at once.) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux6] - exact (integrablemulsum c ha hb hf_int).mono_set (Set.Icc_subset_Icc_right aux5) + exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux5) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux5] - exact (integrablemulsum c ha hb hf_int).mono_set (Set.Icc_subset_Icc_left aux6) + exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_left aux6) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux6] - exact (integrablemulsum c ha hb hf_int).mono_set (Set.Icc_subset_Icc_right aux5) + exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux5) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux3] - exact (integrablemulsum c ha hb hf_int).mono_set (Set.Icc_subset_Icc_right aux4) + exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux4) · exact fun k hk ↦ (intervalIntegrable_iff_integrableOn_Icc_of_le (mod_cast k.le_succ)).mpr - <| (integrablemulsum c ha hb hf_int).mono_set + <| (integrablemulsum c ha hf_int).mono_set <| (Set.Icc_subset_Icc_iff (mod_cast k.le_succ)).mpr <| mod_cast (ineqofmemIco hk) +/-- A version of `sum_mul_eq_sub_sub_integral_mul` where the endpoints are `Nat`. -/ +theorem _root_.sum_mul_eq_sub_sub_integral_mul' {n m : ℕ} (h : n ≤ m) + (hf_diff : ∀ t ∈ Set.Icc (n : ℝ) m, DifferentiableAt ℝ f t) + (hf_int : IntegrableOn (deriv f) (Set.Icc (n : ℝ) m)) : + ∑ k ∈ Ioc n m, f k * c k = + f m * (∑ k ∈ Icc 0 m, c k) - f n * (∑ k ∈ Icc 0 n, c k) - + ∫ t in Set.Ioc (n : ℝ) m, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by + convert sum_mul_eq_sub_sub_integral_mul c n.cast_nonneg (Nat.cast_le.mpr h) hf_diff hf_int + all_goals rw [Nat.floor_natCast] + end abelSummationProof +section specialversions + /-- Specialized version of `sum_mul_eq_sub_sub_integral_mul` for the case `a = 0`.-/ theorem sum_mul_eq_sub_integral_mul {b : ℝ} (hb : 0 ≤ b) (hf_diff : ∀ t ∈ Set.Icc 0 b, DifferentiableAt ℝ f t) (hf_int : IntegrableOn (deriv f) (Set.Icc 0 b)) : ∑ k ∈ Icc 0 ⌊b⌋₊, f k * c k = - f b * (∑ k ∈ Icc 0 ⌊b⌋₊, c k) - ∫ t in Set.Ioc 0 b, deriv f t * (∑ k ∈ Icc 0 ⌊t⌋₊, c k) := by - nth_rewrite 1 [Finset.Icc_eq_cons_Ioc (Nat.zero_le _)] + f b * (∑ k ∈ Icc 0 ⌊b⌋₊, c k) - ∫ t in Set.Ioc 0 b, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by + nth_rewrite 1 [Icc_eq_cons_Ioc (Nat.zero_le _)] rw [sum_cons, ← Nat.floor_zero (α := ℝ), sum_mul_eq_sub_sub_integral_mul c le_rfl hb hf_diff hf_int, Nat.floor_zero, Nat.cast_zero, Icc_self, sum_singleton] ring +/-- A version of `sum_mul_eq_sub_integral_mul` where the endpoint is a `Nat`. -/ +theorem sum_mul_eq_sub_integral_mul' (m : ℕ) + (hf_diff : ∀ t ∈ Set.Icc (0 : ℝ) m, DifferentiableAt ℝ f t) + (hf_int : IntegrableOn (deriv f) (Set.Icc (0 : ℝ) m)) : + ∑ k ∈ Icc 0 m, f k * c k = + f m * (∑ k ∈ Icc 0 m, c k) - + ∫ t in Set.Ioc (0 : ℝ) m, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by + convert sum_mul_eq_sub_integral_mul c m.cast_nonneg hf_diff hf_int + all_goals rw [Nat.floor_natCast] + /-- Specialized version of `sum_mul_eq_sub_integral_mul` when the first coefficient of the sequence `c` is equal to `0`. -/ -theorem sum_mul_eq_sub_integral_mul' (hc : c 0 = 0) (b : ℝ) +theorem sum_mul_eq_sub_integral_mul₀ (hc : c 0 = 0) (b : ℝ) (hf_diff : ∀ t ∈ Set.Icc 1 b, DifferentiableAt ℝ f t) (hf_int : IntegrableOn (deriv f) (Set.Icc 1 b)) : ∑ k ∈ Icc 0 ⌊b⌋₊, f k * c k = - f b * (∑ k ∈ Icc 0 ⌊b⌋₊, c k) - ∫ t in Set.Ioc 1 b, deriv f t * (∑ k ∈ Icc 0 ⌊t⌋₊, c k) := by + f b * (∑ k ∈ Icc 0 ⌊b⌋₊, c k) - ∫ t in Set.Ioc 1 b, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by obtain hb | hb := le_or_gt 1 b · have : 1 ≤ ⌊b⌋₊ := (Nat.one_le_floor_iff _).mpr hb - nth_rewrite 1 [Finset.Icc_eq_cons_Ioc (by omega), sum_cons, ← Nat.Icc_succ_left, - Finset.Icc_eq_cons_Ioc (by omega), sum_cons] + nth_rewrite 1 [Icc_eq_cons_Ioc (by omega), sum_cons, ← Nat.Icc_succ_left, + Icc_eq_cons_Ioc (by omega), sum_cons] rw [Nat.succ_eq_add_one, zero_add, ← Nat.floor_one (α := ℝ), sum_mul_eq_sub_sub_integral_mul c zero_le_one hb hf_diff hf_int, Nat.floor_one, Nat.cast_one, - Finset.Icc_eq_cons_Ioc zero_le_one, sum_cons, show 1 = 0 + 1 by rfl, Nat.Ioc_succ_singleton, + Icc_eq_cons_Ioc zero_le_one, sum_cons, show 1 = 0 + 1 by rfl, Nat.Ioc_succ_singleton, zero_add, sum_singleton, hc, mul_zero, zero_add] ring · simp_rw [Nat.floor_eq_zero.mpr hb, Icc_self, sum_singleton, Nat.cast_zero, hc, mul_zero, Set.Ioc_eq_empty_of_le hb.le, Measure.restrict_empty, integral_zero_measure, sub_self] + +/-- A version of `sum_mul_eq_sub_integral_mul₀` where the endpoint is a `Nat`. -/ +theorem sum_mul_eq_sub_integral_mul₀' (hc : c 0 = 0) (m : ℕ) + (hf_diff : ∀ t ∈ Set.Icc (1 : ℝ) m, DifferentiableAt ℝ f t) + (hf_int : IntegrableOn (deriv f) (Set.Icc (1 : ℝ) m)) : + ∑ k ∈ Icc 0 m, f k * c k = + f m * (∑ k ∈ Icc 0 m, c k) - + ∫ t in Set.Ioc (1 : ℝ) m, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by + convert sum_mul_eq_sub_integral_mul₀ c hc m hf_diff hf_int + all_goals rw [Nat.floor_natCast] + +end specialversions + +section limit + +open Filter Topology abelSummationProof intervalIntegral + +private theorem locallyintegrablemulsum (ha : 0 ≤ a) {g : ℝ → 𝕜} (hg : IntegrableOn g (Set.Ici a)) : + LocallyIntegrableOn (fun t ↦ g t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) (Set.Ici a) := by + refine (locallyIntegrableOn_iff isLocallyClosed_Ici).mpr fun K hK₁ hK₂ ↦ ?_ + by_cases hK₃ : K.Nonempty + · have h_inf : a ≤ sInf K := (hK₁ (hK₂.sInf_mem hK₃)) + refine IntegrableOn.mono_set ?_ (Bornology.IsBounded.subset_Icc_sInf_sSup hK₂.isBounded) + refine integrablemulsum _ (ha.trans h_inf) (hg.mono_set ?_) + exact (Set.Icc_subset_Ici_iff (Real.sInf_le_sSup _ hK₂.bddBelow hK₂.bddAbove)).mpr h_inf + · rw [Set.not_nonempty_iff_eq_empty.mp hK₃] + exact integrableOn_empty + +theorem tendsto_sum_mul_atTop_nhds_one_sub_integral + (hf_diff : ∀ t ∈ Set.Ici 0, DifferentiableAt ℝ f t) + (hf_int : IntegrableOn (deriv f) (Set.Ici 0)) {l : 𝕜} + (h_lim : Tendsto (fun n : ℕ ↦ f n * ∑ k ∈ Icc 0 n, c k) atTop (𝓝 l)) + {g : ℝ → 𝕜} (hg_dom : (fun t ↦ deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) =O[atTop] g) + (hg_int : IntegrableAtFilter g atTop) : + Tendsto (fun n : ℕ ↦ ∑ k ∈ Icc 0 n, f k * c k) atTop + (𝓝 (l - ∫ t in Set.Ioi 0, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k)) := by + have h_lim' : Tendsto (fun n : ℕ ↦ ∫ t in Set.Ioc (0 : ℝ) n, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) + atTop (𝓝 (∫ t in Set.Ioi 0, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k)) := by + refine Tendsto.congr (fun _ ↦ by rw [← integral_of_le (Nat.cast_nonneg _)]) ?_ + refine intervalIntegral_tendsto_integral_Ioi _ ?_ tendsto_natCast_atTop_atTop + exact integrableOn_Ici_iff_integrableOn_Ioi.mp + <| (locallyintegrablemulsum c le_rfl hf_int).integrableOn_of_isBigO_atTop hg_dom hg_int + refine (h_lim.sub h_lim').congr (fun _ ↦ ?_) + rw [sum_mul_eq_sub_integral_mul' _ _ (fun t ht ↦ hf_diff _ ht.1) + (hf_int.mono_set Set.Icc_subset_Ici_self)] + +theorem tendsto_sum_mul_atTop_nhds_one_sub_integral₀ (hc : c 0 = 0) + (hf_diff : ∀ t ∈ Set.Ici 1, DifferentiableAt ℝ f t) + (hf_int : IntegrableOn (deriv f) (Set.Ici 1)) {l : 𝕜} + (h_lim: Tendsto (fun n : ℕ ↦ f n * ∑ k ∈ Icc 0 n, c k) atTop (𝓝 l)) + {g : ℝ → ℝ} (hg_dom : (fun t ↦ deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) =O[atTop] g) + (hg_int : IntegrableAtFilter g atTop) : + Tendsto (fun n : ℕ ↦ ∑ k ∈ Icc 0 n, f k * c k) atTop + (𝓝 (l - ∫ t in Set.Ioi 1, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k)) := by + have h : (fun n : ℕ ↦ ∫ (x : ℝ) in (1 : ℝ)..n, deriv f x * ∑ k ∈ Icc 0 ⌊x⌋₊, c k) =ᶠ[atTop] + (fun n : ℕ ↦ ∫ (t : ℝ) in Set.Ioc 1 ↑n, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) := by + filter_upwards [eventually_ge_atTop 1] with _ h + rw [← integral_of_le (Nat.one_le_cast.mpr h)] + have h_lim' : Tendsto (fun n : ℕ ↦ ∫ t in Set.Ioc (1 : ℝ) n, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) + atTop (𝓝 (∫ t in Set.Ioi 1, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k)) := by + refine Tendsto.congr' h (intervalIntegral_tendsto_integral_Ioi _ ?_ tendsto_natCast_atTop_atTop) + exact integrableOn_Ici_iff_integrableOn_Ioi.mp + <| (locallyintegrablemulsum c zero_le_one hf_int).integrableOn_of_isBigO_atTop hg_dom hg_int + refine (h_lim.sub h_lim').congr (fun _ ↦ ?_) + rw [sum_mul_eq_sub_integral_mul₀' _ hc _ (fun t ht ↦ hf_diff _ ht.1) + (hf_int.mono_set Set.Icc_subset_Ici_self)] + +end limit + +section summable + +open Filter abelSummationProof + +private theorem summable_mul_of_bigO_atTop_aux (m : ℕ) + (h_bdd : (fun n : ℕ ↦ ‖f n‖ * ∑ k ∈ Icc 0 n, ‖c k‖) =O[atTop] fun _ ↦ (1 : ℝ)) + (hf_int : IntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici (m : ℝ))) + (hf : ∀ n : ℕ, ∑ k ∈ Icc 0 n, ‖f k‖ * ‖c k‖ = + ‖f n‖ * ∑ k ∈ Icc 0 n, ‖c k‖ - + ∫ (t : ℝ) in Set.Ioc ↑m ↑n, deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖) + {g : ℝ → ℝ} + (hg₁ : (fun t ↦ deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖) =O[atTop] g) + (hg₂ : IntegrableAtFilter g atTop) : + Summable (fun n : ℕ ↦ f n * c n) := by + obtain ⟨C₁, hC₁⟩ := Asymptotics.isBigO_one_nat_atTop_iff.mp h_bdd + let C₂ := ∫ t in Set.Ioi (m : ℝ), ‖deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖‖ + refine summable_of_sum_range_norm_le (c := max (C₁ + C₂) 1) fun n ↦ ?_ + cases n with + | zero => simp only [range_zero, norm_mul, sum_empty, le_sup_iff, zero_le_one, or_true] + | succ n => + have h_mes : Measurable fun t ↦ deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖ := + (measurable_deriv _).mul <| Measurable.comp' (g := fun n : ℕ ↦ ∑ k ∈ Icc 0 n, ‖c k‖) + (fun _ _ ↦ trivial) Nat.measurable_floor + rw [Nat.range_eq_Icc_zero_sub_one _ n.add_one_ne_zero, add_tsub_cancel_right] + calc + _ = ∑ k ∈ Icc 0 n, ‖f k‖ * ‖c k‖ := by simp_rw [norm_mul] + _ = ‖f n‖ * ∑ k ∈ Icc 0 n, ‖c k‖ - + ∫ t in Set.Ioc ↑m ↑n, deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖ := ?_ + _ ≤ C₁ - ∫ t in Set.Ioc ↑m ↑n, deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖ := ?_ + _ ≤ C₁ + ∫ t in Set.Ioc ↑m ↑n, ‖deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖‖ := ?_ + _ ≤ C₁ + C₂ := ?_ + _ ≤ max (C₁ + C₂) 1 := le_max_left _ _ + · exact hf _ + · refine tsub_le_tsub_right (le_of_eq_of_le (Real.norm_of_nonneg ?_).symm (hC₁ n)) _ + exact mul_nonneg (norm_nonneg _) (sum_nonneg fun _ _ ↦ norm_nonneg _) + · exact add_le_add_left + (le_trans (neg_le_abs _) (Real.norm_eq_abs _ ▸ norm_integral_le_integral_norm _)) _ + · refine add_le_add_left (setIntegral_mono_set ?_ ?_ Set.Ioc_subset_Ioi_self.eventuallyLE) C₁ + · refine integrableOn_Ici_iff_integrableOn_Ioi.mp <| + (integrable_norm_iff h_mes.aestronglyMeasurable).mpr <| + (locallyintegrablemulsum _ m.cast_nonneg hf_int).integrableOn_of_isBigO_atTop hg₁ hg₂ + · filter_upwards with t using norm_nonneg _ + +theorem summable_mul_of_bigO_atTop + (hf_diff : ∀ t ∈ Set.Ici 0, DifferentiableAt ℝ (fun x ↦ ‖f x‖) t) + (hf_int : IntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici 0)) + (h_bdd : (fun n : ℕ ↦ ‖f n‖ * ∑ k ∈ Icc 0 n, ‖c k‖) =O[atTop] fun _ ↦ (1 : ℝ)) + {g : ℝ → ℝ} (hg₁ : (fun t ↦ deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖) =O[atTop] g) + (hg₂ : IntegrableAtFilter g atTop) : + Summable (fun n : ℕ ↦ f n * c n) := by + refine summable_mul_of_bigO_atTop_aux c 0 h_bdd (by rwa [Nat.cast_zero]) (fun n ↦ ?_) hg₁ hg₂ + exact_mod_cast sum_mul_eq_sub_integral_mul' _ _ (fun _ ht ↦ hf_diff _ ht.1) + (hf_int.mono_set Set.Icc_subset_Ici_self) + +/-- A version of `summable_mul_of_bigO_atTop` that can be useful to avoid difficulties near zero. -/ +theorem summable_mul_of_bigO_atTop' + (hf_diff : ∀ t ∈ Set.Ici 1, DifferentiableAt ℝ (fun x ↦ ‖f x‖) t) + (hf_int : IntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici 1)) + (h_bdd : (fun n : ℕ ↦ ‖f n‖ * ∑ k ∈ Icc 1 n, ‖c k‖) =O[atTop] fun _ ↦ (1 : ℝ)) + {g : ℝ → ℝ} (hg₁ : (fun t ↦ deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 1 ⌊t⌋₊, ‖c k‖) =O[atTop] g) + (hg₂ : IntegrableAtFilter g atTop) : + Summable (fun n : ℕ ↦ f n * c n) := by + have h : ∀ n, ∑ k ∈ Icc 1 n, ‖c k‖ = ∑ k ∈ Icc 0 n, ‖(fun n ↦ if n = 0 then 0 else c n) k‖ := by + intro n + rw [Icc_eq_cons_Ioc n.zero_le, sum_cons, ← Nat.Icc_succ_left, Nat.succ_eq_add_one, zero_add] + simp_rw [if_pos, norm_zero, zero_add] + exact Finset.sum_congr rfl fun _ h ↦ by rw [if_neg (zero_lt_one.trans_le (mem_Icc.mp h).1).ne'] + simp_rw [h] at h_bdd hg₁ + refine Summable.congr_atTop (summable_mul_of_bigO_atTop_aux (fun n ↦ if n = 0 then 0 else c n) 1 + h_bdd (by rwa [Nat.cast_one]) (fun n ↦ ?_) hg₁ hg₂) ?_ + · exact_mod_cast sum_mul_eq_sub_integral_mul₀' _ (by simp only [reduceIte, norm_zero]) n + (fun _ ht ↦ hf_diff _ ht.1) (hf_int.mono_set Set.Icc_subset_Ici_self) + · filter_upwards [eventually_ne_atTop 0] with k hk + simp_rw [if_neg hk] + +end summable diff --git a/Mathlib/Topology/Order/IsLocallyClosed.lean b/Mathlib/Topology/Order/IsLocallyClosed.lean new file mode 100644 index 0000000000000..675c11d32edb6 --- /dev/null +++ b/Mathlib/Topology/Order/IsLocallyClosed.lean @@ -0,0 +1,49 @@ +/- +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.Topology.Order.OrderClosed +import Mathlib.Topology.LocallyClosed + +/-! +# Intervals are locally closed + +We prove that the intervals on a topological ordered space are locally closed. +-/ + +variable {X : Type*} [TopologicalSpace X] {a b : X} + +theorem isLocallyClosed_Icc [Preorder X] [OrderClosedTopology X] : + IsLocallyClosed (Set.Icc a b) := + isClosed_Icc.isLocallyClosed + +theorem isLocallyClosed_Ioo [LinearOrder X] [OrderClosedTopology X] : + IsLocallyClosed (Set.Ioo a b) := + isOpen_Ioo.isLocallyClosed + +theorem isLocallyClosed_Ici [Preorder X] [ClosedIciTopology X] : + IsLocallyClosed (Set.Ici a) := + isClosed_Ici.isLocallyClosed + +theorem isLocallyClosed_Iic [Preorder X] [ClosedIicTopology X] : + IsLocallyClosed (Set.Iic a) := + isClosed_Iic.isLocallyClosed + +theorem isLocallyClosed_Ioi [LinearOrder X] [ClosedIicTopology X] : + IsLocallyClosed (Set.Ioi a) := + isOpen_Ioi.isLocallyClosed + +theorem isLocallyClosed_Iio [LinearOrder X] [ClosedIciTopology X] : + IsLocallyClosed (Set.Iio a) := + isOpen_Iio.isLocallyClosed + +theorem isLocallyClosed_Ioc [LinearOrder X] [ClosedIicTopology X] : + IsLocallyClosed (Set.Ioc a b) := by + rw [← Set.Iic_inter_Ioi] + exact isLocallyClosed_Iic.inter isLocallyClosed_Ioi + +theorem isLocallyClosed_Ico [LinearOrder X] [ClosedIciTopology X] : + IsLocallyClosed (Set.Ico a b) := by + rw [← Set.Iio_inter_Ici] + exact isLocallyClosed_Iio.inter isLocallyClosed_Ici From 571927bcac6117d37b60714bd2d9ae3774ce0051 Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Tue, 7 Jan 2025 20:32:58 +0000 Subject: [PATCH 059/681] doc(RingTheory/Flat): add reference to Lambek's paper (#20266) --- Mathlib/RingTheory/Flat/Basic.lean | 3 ++- docs/references.bib | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Mathlib/RingTheory/Flat/Basic.lean b/Mathlib/RingTheory/Flat/Basic.lean index 0923edaa450fb..aa58cec320090 100644 --- a/Mathlib/RingTheory/Flat/Basic.lean +++ b/Mathlib/RingTheory/Flat/Basic.lean @@ -243,7 +243,8 @@ theorem iff_characterModule_baer : Flat R M ↔ Module.Baer R (CharacterModule M simp_rw [iff_rTensor_injective', Baer, rTensor_injective_iff_lcomp_surjective, Surjective, DFunLike.ext_iff, Subtype.forall]; rfl -/-- `CharacterModule M` is an injective module iff `M` is flat. -/ +/-- `CharacterModule M` is an injective module iff `M` is flat. +See [Lambek_1964] for a self-contained proof. -/ theorem iff_characterModule_injective [Small.{v} R] : Flat R M ↔ Module.Injective R (CharacterModule M) := iff_characterModule_baer.trans Module.Baer.iff_injective diff --git a/docs/references.bib b/docs/references.bib index 20343a1c0a28c..726943e64c4fe 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -2521,6 +2521,18 @@ @Book{ lam_1999 year = {1999} } +@Article{ Lambek_1964, + title = {A Module is Flat if and Only if its Character Module is + Injective}, + volume = {7}, + doi = {10.4153/CMB-1964-021-9}, + number = {2}, + journal = {Canadian Mathematical Bulletin}, + author = {Lambek, J.}, + year = {1964}, + pages = {237–243} +} + @Article{ lazarus1973, author = {Michel Lazarus}, title = {Les familles libres maximales d'un module ont-elles le From 1c56cac69d44a726563472f25cc31da6de6620c0 Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Tue, 7 Jan 2025 20:32:59 +0000 Subject: [PATCH 060/681] feat(RingTheory): Jacobian criterion for smoothness of local algebras (#20326) Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/RingTheory/Smooth/Kaehler.lean | 22 +++++++++++++++ Mathlib/RingTheory/Smooth/Local.lean | 37 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 Mathlib/RingTheory/Smooth/Local.lean diff --git a/Mathlib.lean b/Mathlib.lean index 276dd9ea42536..e726bbdbb8fa4 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4666,6 +4666,7 @@ import Mathlib.RingTheory.SimpleRing.Field import Mathlib.RingTheory.SimpleRing.Matrix import Mathlib.RingTheory.Smooth.Basic import Mathlib.RingTheory.Smooth.Kaehler +import Mathlib.RingTheory.Smooth.Local import Mathlib.RingTheory.Smooth.Pi import Mathlib.RingTheory.Smooth.StandardSmooth import Mathlib.RingTheory.Support diff --git a/Mathlib/RingTheory/Smooth/Kaehler.lean b/Mathlib/RingTheory/Smooth/Kaehler.lean index 089823b7d0f64..47603d7179636 100644 --- a/Mathlib/RingTheory/Smooth/Kaehler.lean +++ b/Mathlib/RingTheory/Smooth/Kaehler.lean @@ -380,6 +380,8 @@ include hf in Given a formally smooth `R`-algebra `P` and a surjective algebra homomorphism `f : P →ₐ[R] S` with kernel `I` (typically a presentation `R[X] → S`), `S` is formally smooth iff the `P`-linear map `I/I² → S ⊗[P] Ω[P⁄R]` is split injective. +Also see `Algebra.Extension.formallySmooth_iff_split_injection` +for the version in terms of `Extension`. -/ @[stacks 031I] theorem Algebra.FormallySmooth.iff_split_injection : @@ -388,6 +390,26 @@ theorem Algebra.FormallySmooth.iff_split_injection : simp only [nonempty_subtype] at this rw [this, ← Algebra.FormallySmooth.iff_split_surjection _ hf] +/-- +Given a formally smooth `R`-algebra `P` and a surjective algebra homomorphism `f : P →ₐ[R] S` +with kernel `I` (typically a presentation `R[X] → S`), +`S` is formally smooth iff the `P`-linear map `I/I² → S ⊗[P] Ω[P⁄R]` is split injective. +-/ +@[stacks 031I] +theorem Algebra.Extension.formallySmooth_iff_split_injection + (P : Algebra.Extension.{u} R S) [FormallySmooth R P.Ring] : + Algebra.FormallySmooth R S ↔ ∃ l, l ∘ₗ P.cotangentComplex = LinearMap.id := by + refine (Algebra.FormallySmooth.iff_split_injection P.algebraMap_surjective).trans ?_ + let e : P.ker.Cotangent ≃ₗ[P.Ring] P.Cotangent := + { __ := AddEquiv.refl _, map_smul' r m := by ext1; simp; rfl } + constructor + · intro ⟨l, hl⟩ + exact ⟨(e.comp l).extendScalarsOfSurjective P.algebraMap_surjective, + LinearMap.ext (DFunLike.congr_fun hl : _)⟩ + · intro ⟨l, hl⟩ + exact ⟨e.symm.toLinearMap ∘ₗ l.restrictScalars P.Ring, + LinearMap.ext (DFunLike.congr_fun hl : _)⟩ + include hf in /-- Given a formally smooth `R`-algebra `P` and a surjective algebra homomorphism `f : P →ₐ[R] S` diff --git a/Mathlib/RingTheory/Smooth/Local.lean b/Mathlib/RingTheory/Smooth/Local.lean new file mode 100644 index 0000000000000..589536e0c64de --- /dev/null +++ b/Mathlib/RingTheory/Smooth/Local.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.RingTheory.LocalRing.Module +import Mathlib.RingTheory.Smooth.Kaehler +import Mathlib.RingTheory.TensorProduct.Free + +/-! +# Formally smooth local algebras +-/ + +open TensorProduct IsLocalRing KaehlerDifferential + +/-- +The **Jacobian criterion** for smoothness of local algebras. +Suppose `S` is a local `R`-algebra, and `0 → I → P → S → 0` is a presentation such that +`P` is formally-smooth over `R`, `Ω[P⁄R]` is finite free over `P`, +(typically satisfied when `P` is the localization of a polynomial ring of finite type) +and `I` is finitely generated. +Then `S` is formally smooth iff `k ⊗ₛ I/I² → k ⊗ₚ Ω[P/R]` is injective, +where `k` is the residue field of `S`. +-/ +theorem Algebra.FormallySmooth.iff_injective_lTensor_residueField {R S} [CommRing R] + [CommRing S] [IsLocalRing S] [Algebra R S] (P : Algebra.Extension R S) + [FormallySmooth R P.Ring] + [Module.Free P.Ring (Ω[P.Ring⁄R])] [Module.Finite P.Ring (Ω[P.Ring⁄R])] + (h' : P.ker.FG) : + Algebra.FormallySmooth R S ↔ + Function.Injective (P.cotangentComplex.lTensor (ResidueField S)) := by + have : Module.Finite P.Ring P.Cotangent := + have : Module.Finite P.Ring P.ker := ⟨(Submodule.fg_top _).mpr h'⟩ + .of_surjective _ Extension.Cotangent.mk_surjective + have : Module.Finite S P.Cotangent := Module.Finite.of_restrictScalars_finite P.Ring _ _ + rw [← IsLocalRing.split_injective_iff_lTensor_residueField_injective, + P.formallySmooth_iff_split_injection] From 1e7c41df0e1bb72d55341ac53ca3d247e2a0b3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Tue, 7 Jan 2025 20:33:00 +0000 Subject: [PATCH 061/681] chore: extract 3 new files out of MeasureSpace (#20509) The MeasureSpace file contains many definitions about measures and is 2000 lines long. This PR splits 3 files by taking material from the bottom of MeasureSpace: - Map: map of a measure by a function - AbsolutelyContinuous: absolute continuity of measures - QuasiMeasurePreserving: quasi measure preserving functions Co-authored-by: Remy Degenne --- Mathlib.lean | 3 + .../MeasureTheory/Covering/VitaliFamily.lean | 2 +- Mathlib/MeasureTheory/Group/Defs.lean | 2 +- .../Measure/AbsolutelyContinuous.lean | 193 ++++++ Mathlib/MeasureTheory/Measure/Comap.lean | 2 +- Mathlib/MeasureTheory/Measure/Map.lean | 322 +++++++++ .../MeasureTheory/Measure/MeasureSpace.lean | 610 ------------------ .../Measure/QuasiMeasurePreserving.lean | 229 +++++++ Mathlib/MeasureTheory/Measure/Restrict.lean | 1 + 9 files changed, 751 insertions(+), 613 deletions(-) create mode 100644 Mathlib/MeasureTheory/Measure/AbsolutelyContinuous.lean create mode 100644 Mathlib/MeasureTheory/Measure/Map.lean create mode 100644 Mathlib/MeasureTheory/Measure/QuasiMeasurePreserving.lean diff --git a/Mathlib.lean b/Mathlib.lean index e726bbdbb8fa4..a35603b24ceef 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3769,6 +3769,7 @@ import Mathlib.MeasureTheory.MeasurableSpace.PreorderRestrict import Mathlib.MeasureTheory.MeasurableSpace.Prod import Mathlib.MeasureTheory.Measure.AEDisjoint import Mathlib.MeasureTheory.Measure.AEMeasurable +import Mathlib.MeasureTheory.Measure.AbsolutelyContinuous import Mathlib.MeasureTheory.Measure.AddContent import Mathlib.MeasureTheory.Measure.Comap import Mathlib.MeasureTheory.Measure.Complex @@ -3798,6 +3799,7 @@ import Mathlib.MeasureTheory.Measure.Lebesgue.Integral import Mathlib.MeasureTheory.Measure.Lebesgue.VolumeOfBalls import Mathlib.MeasureTheory.Measure.LevyProkhorovMetric import Mathlib.MeasureTheory.Measure.LogLikelihoodRatio +import Mathlib.MeasureTheory.Measure.Map import Mathlib.MeasureTheory.Measure.MeasureSpace import Mathlib.MeasureTheory.Measure.MeasureSpaceDef import Mathlib.MeasureTheory.Measure.MutuallySingular @@ -3806,6 +3808,7 @@ import Mathlib.MeasureTheory.Measure.OpenPos import Mathlib.MeasureTheory.Measure.Portmanteau import Mathlib.MeasureTheory.Measure.ProbabilityMeasure import Mathlib.MeasureTheory.Measure.Prod +import Mathlib.MeasureTheory.Measure.QuasiMeasurePreserving import Mathlib.MeasureTheory.Measure.Regular import Mathlib.MeasureTheory.Measure.RegularityCompacts import Mathlib.MeasureTheory.Measure.Restrict diff --git a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean index 0cfed115a59d7..e83670491cdf0 100644 --- a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean +++ b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 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.Measure.MeasureSpace +import Mathlib.MeasureTheory.Measure.AbsolutelyContinuous /-! # Vitali families diff --git a/Mathlib/MeasureTheory/Group/Defs.lean b/Mathlib/MeasureTheory/Group/Defs.lean index c68e87b9ad78f..d57a070570695 100644 --- a/Mathlib/MeasureTheory/Group/Defs.lean +++ b/Mathlib/MeasureTheory/Group/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Yury Kudryashov -/ -import Mathlib.MeasureTheory.Measure.MeasureSpace +import Mathlib.MeasureTheory.Measure.Map /-! # Definitions about invariant measures diff --git a/Mathlib/MeasureTheory/Measure/AbsolutelyContinuous.lean b/Mathlib/MeasureTheory/Measure/AbsolutelyContinuous.lean new file mode 100644 index 0000000000000..e201a358f0c78 --- /dev/null +++ b/Mathlib/MeasureTheory/Measure/AbsolutelyContinuous.lean @@ -0,0 +1,193 @@ +/- +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, Mario Carneiro +-/ +import Mathlib.MeasureTheory.Measure.Map + +/-! +# Absolute Continuity of Measures + +We say that `μ` is absolutely continuous with respect to `ν`, or that `μ` is dominated by `ν`, +if `ν(A) = 0` implies that `μ(A) = 0`. We denote that by `μ ≪ ν`. + +It is equivalent to an inequality of the almost everywhere filters of the measures: +`μ ≪ ν ↔ ae μ ≤ ae ν`. + +## Main definitions + +* `MeasureTheory.Measure.AbsolutelyContinuous μ ν`: `μ` is absolutely continuous with respect to `ν` + +## Main statements + +* `ae_le_iff_absolutelyContinuous`: `ae μ ≤ ae ν ↔ μ ≪ ν` + +## Notation + +* `μ ≪ ν`: `MeasureTheory.Measure.AbsolutelyContinuous μ ν`. That is: `μ` is absolutely continuous + with respect to `ν` + +-/ + +variable {α β δ ι R : Type*} + +namespace MeasureTheory + +open Set ENNReal NNReal + +variable {mα : MeasurableSpace α} {mβ : MeasurableSpace β} + {μ μ₁ μ₂ μ₃ ν ν' : Measure α} {s t : Set α} + +namespace Measure + +/-- We say that `μ` is absolutely continuous with respect to `ν`, or that `μ` is dominated by `ν`, + if `ν(A) = 0` implies that `μ(A) = 0`. -/ +def AbsolutelyContinuous {_m0 : MeasurableSpace α} (μ ν : Measure α) : Prop := + ∀ ⦃s : Set α⦄, ν s = 0 → μ s = 0 + +@[inherit_doc MeasureTheory.Measure.AbsolutelyContinuous] +scoped[MeasureTheory] infixl:50 " ≪ " => MeasureTheory.Measure.AbsolutelyContinuous + +theorem absolutelyContinuous_of_le (h : μ ≤ ν) : μ ≪ ν := fun s hs => + nonpos_iff_eq_zero.1 <| hs ▸ le_iff'.1 h s + +alias _root_.LE.le.absolutelyContinuous := absolutelyContinuous_of_le + +theorem absolutelyContinuous_of_eq (h : μ = ν) : μ ≪ ν := + h.le.absolutelyContinuous + +alias _root_.Eq.absolutelyContinuous := absolutelyContinuous_of_eq + +namespace AbsolutelyContinuous + +theorem mk (h : ∀ ⦃s : Set α⦄, MeasurableSet s → ν s = 0 → μ s = 0) : μ ≪ ν := by + intro s hs + rcases exists_measurable_superset_of_null hs with ⟨t, h1t, h2t, h3t⟩ + exact measure_mono_null h1t (h h2t h3t) + +@[refl] +protected theorem refl {_m0 : MeasurableSpace α} (μ : Measure α) : μ ≪ μ := + rfl.absolutelyContinuous + +protected theorem rfl : μ ≪ μ := fun _s hs => hs + +instance instIsRefl {_ : MeasurableSpace α} : IsRefl (Measure α) (· ≪ ·) := + ⟨fun _ => AbsolutelyContinuous.rfl⟩ + +@[simp] +protected lemma zero (μ : Measure α) : 0 ≪ μ := fun _ _ ↦ by simp + +@[trans] +protected theorem trans (h1 : μ₁ ≪ μ₂) (h2 : μ₂ ≪ μ₃) : μ₁ ≪ μ₃ := fun _s hs => h1 <| h2 hs + +@[mono] +protected theorem map (h : μ ≪ ν) {f : α → β} (hf : Measurable f) : μ.map f ≪ ν.map f := + AbsolutelyContinuous.mk fun s hs => by simpa [hf, hs] using @h _ + +protected theorem smul_left [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (h : μ ≪ ν) (c : R) : + c • μ ≪ ν := fun s hνs => by + simp only [h hνs, smul_apply, smul_zero, ← smul_one_smul ℝ≥0∞ c (0 : ℝ≥0∞)] + +/-- If `μ ≪ ν`, then `c • μ ≪ c • ν`. + +Earlier, this name was used for what's now called `AbsolutelyContinuous.smul_left`. -/ +protected theorem smul [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (h : μ ≪ ν) (c : R) : + c • μ ≪ c • ν := by + intro s hνs + rw [smul_apply, ← smul_one_smul ℝ≥0∞, smul_eq_mul, mul_eq_zero] at hνs ⊢ + exact hνs.imp_right fun hs ↦ h hs + +@[deprecated (since := "2024-11-14")] protected alias smul_both := AbsolutelyContinuous.smul + +protected lemma add (h1 : μ₁ ≪ ν) (h2 : μ₂ ≪ ν') : μ₁ + μ₂ ≪ ν + ν' := by + intro s hs + simp only [coe_add, Pi.add_apply, add_eq_zero] at hs ⊢ + exact ⟨h1 hs.1, h2 hs.2⟩ + +lemma add_left_iff {μ₁ μ₂ ν : Measure α} : + μ₁ + μ₂ ≪ ν ↔ μ₁ ≪ ν ∧ μ₂ ≪ ν := by + refine ⟨fun h ↦ ?_, fun h ↦ (h.1.add h.2).trans ?_⟩ + · have : ∀ s, ν s = 0 → μ₁ s = 0 ∧ μ₂ s = 0 := by intro s hs0; simpa using h hs0 + exact ⟨fun s hs0 ↦ (this s hs0).1, fun s hs0 ↦ (this s hs0).2⟩ + · rw [← two_smul ℝ≥0] + exact AbsolutelyContinuous.rfl.smul_left 2 + +lemma add_left {μ₁ μ₂ ν : Measure α} (h₁ : μ₁ ≪ ν) (h₂ : μ₂ ≪ ν) : μ₁ + μ₂ ≪ ν := + Measure.AbsolutelyContinuous.add_left_iff.mpr ⟨h₁, h₂⟩ + +lemma add_right (h1 : μ ≪ ν) (ν' : Measure α) : μ ≪ ν + ν' := by + intro s hs + simp only [coe_add, Pi.add_apply, add_eq_zero] at hs ⊢ + exact h1 hs.1 + +end AbsolutelyContinuous + +@[simp] +lemma absolutelyContinuous_zero_iff : μ ≪ 0 ↔ μ = 0 := + ⟨fun h ↦ measure_univ_eq_zero.mp (h rfl), fun h ↦ h.symm ▸ AbsolutelyContinuous.zero _⟩ + +alias absolutelyContinuous_refl := AbsolutelyContinuous.refl +alias absolutelyContinuous_rfl := AbsolutelyContinuous.rfl + +lemma absolutelyContinuous_sum_left {μs : ι → Measure α} (hμs : ∀ i, μs i ≪ ν) : + Measure.sum μs ≪ ν := + AbsolutelyContinuous.mk fun s hs hs0 ↦ by simp [sum_apply _ hs, fun i ↦ hμs i hs0] + +lemma absolutelyContinuous_sum_right {μs : ι → Measure α} (i : ι) (hνμ : ν ≪ μs i) : + ν ≪ Measure.sum μs := by + refine AbsolutelyContinuous.mk fun s hs hs0 ↦ ?_ + simp only [sum_apply _ hs, ENNReal.tsum_eq_zero] at hs0 + exact hνμ (hs0 i) + +lemma smul_absolutelyContinuous {c : ℝ≥0∞} : c • μ ≪ μ := .smul_left .rfl _ + +theorem absolutelyContinuous_of_le_smul {μ' : Measure α} {c : ℝ≥0∞} (hμ'_le : μ' ≤ c • μ) : + μ' ≪ μ := + (Measure.absolutelyContinuous_of_le hμ'_le).trans smul_absolutelyContinuous + +lemma absolutelyContinuous_smul {c : ℝ≥0∞} (hc : c ≠ 0) : μ ≪ c • μ := by + simp [AbsolutelyContinuous, hc] + +theorem ae_le_iff_absolutelyContinuous : ae μ ≤ ae ν ↔ μ ≪ ν := + ⟨fun h s => by + rw [measure_zero_iff_ae_nmem, measure_zero_iff_ae_nmem] + exact fun hs => h hs, fun h _ hs => h hs⟩ + +alias ⟨_root_.LE.le.absolutelyContinuous_of_ae, AbsolutelyContinuous.ae_le⟩ := + ae_le_iff_absolutelyContinuous + +alias ae_mono' := AbsolutelyContinuous.ae_le + +theorem AbsolutelyContinuous.ae_eq (h : μ ≪ ν) {f g : α → δ} (h' : f =ᵐ[ν] g) : f =ᵐ[μ] g := + h.ae_le h' + +end Measure + +protected theorem AEDisjoint.of_absolutelyContinuous + (h : AEDisjoint μ s t) {ν : Measure α} (h' : ν ≪ μ) : + AEDisjoint ν s t := h' h + +protected theorem AEDisjoint.of_le + (h : AEDisjoint μ s t) {ν : Measure α} (h' : ν ≤ μ) : + AEDisjoint ν s t := + h.of_absolutelyContinuous (Measure.absolutelyContinuous_of_le h') + +@[mono] +theorem ae_mono (h : μ ≤ ν) : ae μ ≤ ae ν := + h.absolutelyContinuous.ae_le + +end MeasureTheory + +namespace MeasurableEmbedding + +open MeasureTheory Measure + +variable {m0 : MeasurableSpace α} {m1 : MeasurableSpace β} {f : α → β} {μ ν : Measure α} + +lemma absolutelyContinuous_map (hf : MeasurableEmbedding f) (hμν : μ ≪ ν) : + μ.map f ≪ ν.map f := by + intro t ht + rw [hf.map_apply] at ht ⊢ + exact hμν ht + +end MeasurableEmbedding diff --git a/Mathlib/MeasureTheory/Measure/Comap.lean b/Mathlib/MeasureTheory/Measure/Comap.lean index 4b7a871e2f74c..457a53c721731 100644 --- a/Mathlib/MeasureTheory/Measure/Comap.lean +++ b/Mathlib/MeasureTheory/Measure/Comap.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Rémy Degenne -/ -import Mathlib.MeasureTheory.Measure.MeasureSpace +import Mathlib.MeasureTheory.Measure.Map /-! # Pullback of a measure diff --git a/Mathlib/MeasureTheory/Measure/Map.lean b/Mathlib/MeasureTheory/Measure/Map.lean new file mode 100644 index 0000000000000..468fd36fa10a3 --- /dev/null +++ b/Mathlib/MeasureTheory/Measure/Map.lean @@ -0,0 +1,322 @@ +/- +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, Mario Carneiro +-/ +import Mathlib.MeasureTheory.MeasurableSpace.Embedding +import Mathlib.MeasureTheory.Measure.MeasureSpace + +/-! +# Pushforward of a measure + +In this file we define the pushforward `MeasureTheory.Measure.map f μ` +of a measure `μ` along an almost everywhere measurable map `f`. +If `f` is not a.e. measurable, then we define `map f μ` to be zero. + +## Main definitions + +* `MeasureTheory.Measure.map f μ`: map of the measure `μ` along the map `f`. + +## Main statements + +* `map_apply`: for `s` a measurable set, `μ.map f s = μ (f ⁻¹' s)` +* `map_map`: `(μ.map f).map g = μ.map (g ∘ f)` + +-/ + +variable {α β γ : Type*} + +open Set Function ENNReal NNReal +open Filter hiding map + +namespace MeasureTheory + +variable {mα : MeasurableSpace α} {mβ : MeasurableSpace β} {mγ : MeasurableSpace γ} + {μ ν : Measure α} {s : Set α} + +namespace Measure + +/-- Lift a linear map between `OuterMeasure` spaces such that for each measure `μ` every measurable +set is caratheodory-measurable w.r.t. `f μ` to a linear map between `Measure` spaces. -/ +noncomputable +def liftLinear [MeasurableSpace β] (f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β) + (hf : ∀ μ : Measure α, ‹_› ≤ (f μ.toOuterMeasure).caratheodory) : + Measure α →ₗ[ℝ≥0∞] Measure β where + toFun μ := (f μ.toOuterMeasure).toMeasure (hf μ) + map_add' μ₁ μ₂ := ext fun s hs => by + simp only [map_add, coe_add, Pi.add_apply, toMeasure_apply, add_toOuterMeasure, + OuterMeasure.coe_add, hs] + map_smul' c μ := ext fun s hs => by + simp only [LinearMap.map_smulₛₗ, coe_smul, Pi.smul_apply, + toMeasure_apply, smul_toOuterMeasure (R := ℝ≥0∞), OuterMeasure.coe_smul (R := ℝ≥0∞), + smul_apply, hs] + +lemma liftLinear_apply₀ {f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β} (hf) {s : Set β} + (hs : NullMeasurableSet s (liftLinear f hf μ)) : liftLinear f hf μ s = f μ.toOuterMeasure s := + toMeasure_apply₀ _ (hf μ) hs + +@[simp] +theorem liftLinear_apply {f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β} (hf) {s : Set β} + (hs : MeasurableSet s) : liftLinear f hf μ s = f μ.toOuterMeasure s := + toMeasure_apply _ (hf μ) hs + +theorem le_liftLinear_apply {f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β} (hf) (s : Set β) : + f μ.toOuterMeasure s ≤ liftLinear f hf μ s := + le_toMeasure_apply _ (hf μ) s + +open Classical in +/-- The pushforward of a measure as a linear map. It is defined to be `0` if `f` is not +a measurable function. -/ +noncomputable +def mapₗ [MeasurableSpace α] [MeasurableSpace β] (f : α → β) : Measure α →ₗ[ℝ≥0∞] Measure β := + if hf : Measurable f then + liftLinear (OuterMeasure.map f) fun μ _s hs t => + le_toOuterMeasure_caratheodory μ _ (hf hs) (f ⁻¹' t) + else 0 + +theorem mapₗ_congr {f g : α → β} (hf : Measurable f) (hg : Measurable g) (h : f =ᵐ[μ] g) : + mapₗ f μ = mapₗ g μ := by + ext1 s hs + simpa only [mapₗ, hf, hg, hs, dif_pos, liftLinear_apply, OuterMeasure.map_apply] + using measure_congr (h.preimage s) + +open Classical in +/-- The pushforward of a measure. It is defined to be `0` if `f` is not an almost everywhere +measurable function. -/ +noncomputable +irreducible_def map [MeasurableSpace α] [MeasurableSpace β] (f : α → β) (μ : Measure α) : + Measure β := + if hf : AEMeasurable f μ then mapₗ (hf.mk f) μ else 0 + +theorem mapₗ_mk_apply_of_aemeasurable {f : α → β} (hf : AEMeasurable f μ) : + mapₗ (hf.mk f) μ = map f μ := by simp [map, hf] + +theorem mapₗ_apply_of_measurable {f : α → β} (hf : Measurable f) (μ : Measure α) : + mapₗ f μ = map f μ := by + simp only [← mapₗ_mk_apply_of_aemeasurable hf.aemeasurable] + exact mapₗ_congr hf hf.aemeasurable.measurable_mk hf.aemeasurable.ae_eq_mk + +@[simp] +theorem map_add (μ ν : Measure α) {f : α → β} (hf : Measurable f) : + (μ + ν).map f = μ.map f + ν.map f := by simp [← mapₗ_apply_of_measurable hf] + +@[simp] +theorem map_zero (f : α → β) : (0 : Measure α).map f = 0 := by + by_cases hf : AEMeasurable f (0 : Measure α) <;> simp [map, hf] + +@[simp] +theorem map_of_not_aemeasurable {f : α → β} {μ : Measure α} (hf : ¬AEMeasurable f μ) : + μ.map f = 0 := by simp [map, hf] + +theorem _root_.AEMeasurable.of_map_ne_zero {f : α → β} {μ : Measure α} (hf : μ.map f ≠ 0) : + AEMeasurable f μ := not_imp_comm.1 map_of_not_aemeasurable hf + +theorem map_congr {f g : α → β} (h : f =ᵐ[μ] g) : Measure.map f μ = Measure.map g μ := by + by_cases hf : AEMeasurable f μ + · have hg : AEMeasurable g μ := hf.congr h + simp only [← mapₗ_mk_apply_of_aemeasurable hf, ← mapₗ_mk_apply_of_aemeasurable hg] + exact + mapₗ_congr hf.measurable_mk hg.measurable_mk (hf.ae_eq_mk.symm.trans (h.trans hg.ae_eq_mk)) + · have hg : ¬AEMeasurable g μ := by simpa [← aemeasurable_congr h] using hf + simp [map_of_not_aemeasurable, hf, hg] + +@[simp] +protected theorem map_smul {R : Type*} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] + (c : R) (μ : Measure α) (f : α → β) : (c • μ).map f = c • μ.map f := by + suffices ∀ c : ℝ≥0∞, (c • μ).map f = c • μ.map f by simpa using this (c • 1) + clear c; intro c + rcases eq_or_ne c 0 with (rfl | hc); · simp + by_cases hf : AEMeasurable f μ + · have hfc : AEMeasurable f (c • μ) := + ⟨hf.mk f, hf.measurable_mk, (ae_smul_measure_iff hc).2 hf.ae_eq_mk⟩ + simp only [← mapₗ_mk_apply_of_aemeasurable hf, ← mapₗ_mk_apply_of_aemeasurable hfc, + LinearMap.map_smulₛₗ, RingHom.id_apply] + congr 1 + apply mapₗ_congr hfc.measurable_mk hf.measurable_mk + exact EventuallyEq.trans ((ae_smul_measure_iff hc).1 hfc.ae_eq_mk.symm) hf.ae_eq_mk + · have hfc : ¬AEMeasurable f (c • μ) := by + intro hfc + exact hf ⟨hfc.mk f, hfc.measurable_mk, (ae_smul_measure_iff hc).1 hfc.ae_eq_mk⟩ + simp [map_of_not_aemeasurable hf, map_of_not_aemeasurable hfc] + + +@[deprecated Measure.map_smul (since := "2024-11-13")] +protected theorem map_smul_nnreal (c : ℝ≥0) (μ : Measure α) (f : α → β) : + (c • μ).map f = c • μ.map f := + μ.map_smul c f + +variable {f : α → β} + +lemma map_apply₀ {f : α → β} (hf : AEMeasurable f μ) {s : Set β} + (hs : NullMeasurableSet s (map f μ)) : μ.map f s = μ (f ⁻¹' s) := by + rw [map, dif_pos hf, mapₗ, dif_pos hf.measurable_mk] at hs ⊢ + rw [liftLinear_apply₀ _ hs, measure_congr (hf.ae_eq_mk.preimage s)] + rfl + +/-- We can evaluate the pushforward on measurable sets. For non-measurable sets, see + `MeasureTheory.Measure.le_map_apply` and `MeasurableEquiv.map_apply`. -/ +@[simp] +theorem map_apply_of_aemeasurable (hf : AEMeasurable f μ) {s : Set β} (hs : MeasurableSet s) : + μ.map f s = μ (f ⁻¹' s) := map_apply₀ hf hs.nullMeasurableSet + +@[simp] +theorem map_apply (hf : Measurable f) {s : Set β} (hs : MeasurableSet s) : + μ.map f s = μ (f ⁻¹' s) := + map_apply_of_aemeasurable hf.aemeasurable hs + +theorem map_toOuterMeasure (hf : AEMeasurable f μ) : + (μ.map f).toOuterMeasure = (OuterMeasure.map f μ.toOuterMeasure).trim := by + rw [← trimmed, OuterMeasure.trim_eq_trim_iff] + intro s hs + simp [hf, hs] + +@[simp] lemma map_eq_zero_iff (hf : AEMeasurable f μ) : μ.map f = 0 ↔ μ = 0 := by + simp_rw [← measure_univ_eq_zero, map_apply_of_aemeasurable hf .univ, preimage_univ] + +@[simp] lemma mapₗ_eq_zero_iff (hf : Measurable f) : Measure.mapₗ f μ = 0 ↔ μ = 0 := by + rw [mapₗ_apply_of_measurable hf, map_eq_zero_iff hf.aemeasurable] + +/-- If `map f μ = μ`, then the measure of the preimage of any null measurable set `s` +is equal to the measure of `s`. +Note that this lemma does not assume (a.e.) measurability of `f`. -/ +lemma measure_preimage_of_map_eq_self {f : α → α} (hf : map f μ = μ) + {s : Set α} (hs : NullMeasurableSet s μ) : μ (f ⁻¹' s) = μ s := by + if hfm : AEMeasurable f μ then + rw [← map_apply₀ hfm, hf] + rwa [hf] + else + rw [map_of_not_aemeasurable hfm] at hf + simp [← hf] + +lemma map_ne_zero_iff (hf : AEMeasurable f μ) : μ.map f ≠ 0 ↔ μ ≠ 0 := (map_eq_zero_iff hf).not +lemma mapₗ_ne_zero_iff (hf : Measurable f) : Measure.mapₗ f μ ≠ 0 ↔ μ ≠ 0 := + (mapₗ_eq_zero_iff hf).not + +@[simp] +theorem map_id : map id μ = μ := + ext fun _ => map_apply measurable_id + +@[simp] +theorem map_id' : map (fun x => x) μ = μ := + map_id + +/-- Mapping a measure twice is the same as mapping the measure with the composition. This version is +for measurable functions. See `map_map_of_aemeasurable` when they are just ae measurable. -/ +theorem map_map {g : β → γ} {f : α → β} (hg : Measurable g) (hf : Measurable f) : + (μ.map f).map g = μ.map (g ∘ f) := + ext fun s hs => by simp [hf, hg, hs, hg hs, hg.comp hf, ← preimage_comp] + +@[mono] +theorem map_mono {f : α → β} (h : μ ≤ ν) (hf : Measurable f) : μ.map f ≤ ν.map f := + le_iff.2 fun s hs ↦ by simp [hf.aemeasurable, hs, h _] + +/-- Even if `s` is not measurable, we can bound `map f μ s` from below. + See also `MeasurableEquiv.map_apply`. -/ +theorem le_map_apply {f : α → β} (hf : AEMeasurable f μ) (s : Set β) : μ (f ⁻¹' s) ≤ μ.map f s := + calc + μ (f ⁻¹' s) ≤ μ (f ⁻¹' toMeasurable (μ.map f) s) := by gcongr; apply subset_toMeasurable + _ = μ.map f (toMeasurable (μ.map f) s) := + (map_apply_of_aemeasurable hf <| measurableSet_toMeasurable _ _).symm + _ = μ.map f s := measure_toMeasurable _ + +theorem le_map_apply_image {f : α → β} (hf : AEMeasurable f μ) (s : Set α) : + μ s ≤ μ.map f (f '' s) := + (measure_mono (subset_preimage_image f s)).trans (le_map_apply hf _) + +/-- Even if `s` is not measurable, `map f μ s = 0` implies that `μ (f ⁻¹' s) = 0`. -/ +theorem preimage_null_of_map_null {f : α → β} (hf : AEMeasurable f μ) {s : Set β} + (hs : μ.map f s = 0) : μ (f ⁻¹' s) = 0 := + nonpos_iff_eq_zero.mp <| (le_map_apply hf s).trans_eq hs + +theorem tendsto_ae_map {f : α → β} (hf : AEMeasurable f μ) : Tendsto f (ae μ) (ae (μ.map f)) := + fun _ hs => preimage_null_of_map_null hf hs + +end Measure + +open Measure + +theorem mem_ae_map_iff {f : α → β} (hf : AEMeasurable f μ) {s : Set β} (hs : MeasurableSet s) : + s ∈ ae (μ.map f) ↔ f ⁻¹' s ∈ ae μ := by + simp only [mem_ae_iff, map_apply_of_aemeasurable hf hs.compl, preimage_compl] + +theorem mem_ae_of_mem_ae_map {f : α → β} (hf : AEMeasurable f μ) {s : Set β} + (hs : s ∈ ae (μ.map f)) : f ⁻¹' s ∈ ae μ := + (tendsto_ae_map hf).eventually hs + +theorem ae_map_iff {f : α → β} (hf : AEMeasurable f μ) {p : β → Prop} + (hp : MeasurableSet { x | p x }) : (∀ᵐ y ∂μ.map f, p y) ↔ ∀ᵐ x ∂μ, p (f x) := + mem_ae_map_iff hf hp + +theorem ae_of_ae_map {f : α → β} (hf : AEMeasurable f μ) {p : β → Prop} (h : ∀ᵐ y ∂μ.map f, p y) : + ∀ᵐ x ∂μ, p (f x) := + mem_ae_of_mem_ae_map hf h + +theorem ae_map_mem_range {m0 : MeasurableSpace α} (f : α → β) (hf : MeasurableSet (range f)) + (μ : Measure α) : ∀ᵐ x ∂μ.map f, x ∈ range f := by + by_cases h : AEMeasurable f μ + · change range f ∈ ae (μ.map f) + rw [mem_ae_map_iff h hf] + filter_upwards using mem_range_self + · simp [map_of_not_aemeasurable h] + +end MeasureTheory + +namespace MeasurableEmbedding + +open MeasureTheory Measure + +variable {m0 : MeasurableSpace α} {m1 : MeasurableSpace β} {f : α → β} {μ ν : Measure α} + +nonrec theorem map_apply (hf : MeasurableEmbedding f) (μ : Measure α) (s : Set β) : + μ.map f s = μ (f ⁻¹' s) := by + refine le_antisymm ?_ (le_map_apply hf.measurable.aemeasurable s) + set t := f '' toMeasurable μ (f ⁻¹' s) ∪ (range f)ᶜ + have htm : MeasurableSet t := + (hf.measurableSet_image.2 <| measurableSet_toMeasurable _ _).union + hf.measurableSet_range.compl + have hst : s ⊆ t := by + rw [subset_union_compl_iff_inter_subset, ← image_preimage_eq_inter_range] + exact image_subset _ (subset_toMeasurable _ _) + have hft : f ⁻¹' t = toMeasurable μ (f ⁻¹' s) := by + rw [preimage_union, preimage_compl, preimage_range, compl_univ, union_empty, + hf.injective.preimage_image] + calc + μ.map f s ≤ μ.map f t := by gcongr + _ = μ (f ⁻¹' s) := by rw [map_apply hf.measurable htm, hft, measure_toMeasurable] + +end MeasurableEmbedding + +namespace MeasurableEquiv + +/-! Interactions of measurable equivalences and measures -/ + +open Equiv MeasureTheory MeasureTheory.Measure + +variable {_ : MeasurableSpace α} [MeasurableSpace β] {μ : Measure α} {ν : Measure β} + +/-- If we map a measure along a measurable equivalence, we can compute the measure on all sets + (not just the measurable ones). -/ +protected theorem map_apply (f : α ≃ᵐ β) (s : Set β) : μ.map f s = μ (f ⁻¹' s) := + f.measurableEmbedding.map_apply _ _ + +@[simp] +theorem map_symm_map (e : α ≃ᵐ β) : (μ.map e).map e.symm = μ := by + simp [map_map e.symm.measurable e.measurable] + +@[simp] +theorem map_map_symm (e : α ≃ᵐ β) : (ν.map e.symm).map e = ν := by + simp [map_map e.measurable e.symm.measurable] + +theorem map_measurableEquiv_injective (e : α ≃ᵐ β) : Injective (Measure.map e) := by + intro μ₁ μ₂ hμ + apply_fun Measure.map e.symm at hμ + simpa [map_symm_map e] using hμ + +theorem map_apply_eq_iff_map_symm_apply_eq (e : α ≃ᵐ β) : μ.map e = ν ↔ ν.map e.symm = μ := by + rw [← (map_measurableEquiv_injective e).eq_iff, map_map_symm, eq_comm] + +theorem map_ae (f : α ≃ᵐ β) (μ : Measure α) : Filter.map f (ae μ) = ae (map f μ) := by + ext s + simp_rw [mem_map, mem_ae_iff, ← preimage_compl, f.map_apply] + +end MeasurableEquiv diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index 0303a1275e8c4..54c1d8c77d045 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -4,8 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ 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 @@ -1140,201 +1138,6 @@ lemma nonempty_of_neZero (μ : Measure α) [NeZero μ] : Nonempty α := (isEmpty_or_nonempty α).resolve_left fun h ↦ by simpa [eq_empty_of_isEmpty] using NeZero.ne (μ univ) -/-! ### Pushforward and pullback -/ - - -/-- Lift a linear map between `OuterMeasure` spaces such that for each measure `μ` every measurable -set is caratheodory-measurable w.r.t. `f μ` to a linear map between `Measure` spaces. -/ -def liftLinear [MeasurableSpace β] (f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β) - (hf : ∀ μ : Measure α, ‹_› ≤ (f μ.toOuterMeasure).caratheodory) : - Measure α →ₗ[ℝ≥0∞] Measure β where - toFun μ := (f μ.toOuterMeasure).toMeasure (hf μ) - map_add' μ₁ μ₂ := ext fun s hs => by - simp only [map_add, coe_add, Pi.add_apply, toMeasure_apply, add_toOuterMeasure, - OuterMeasure.coe_add, hs] - map_smul' c μ := ext fun s hs => by - simp only [LinearMap.map_smulₛₗ, coe_smul, Pi.smul_apply, - toMeasure_apply, smul_toOuterMeasure (R := ℝ≥0∞), OuterMeasure.coe_smul (R := ℝ≥0∞), - smul_apply, hs] - -lemma liftLinear_apply₀ {f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β} (hf) {s : Set β} - (hs : NullMeasurableSet s (liftLinear f hf μ)) : liftLinear f hf μ s = f μ.toOuterMeasure s := - toMeasure_apply₀ _ (hf μ) hs - -@[simp] -theorem liftLinear_apply {f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β} (hf) {s : Set β} - (hs : MeasurableSet s) : liftLinear f hf μ s = f μ.toOuterMeasure s := - toMeasure_apply _ (hf μ) hs - -theorem le_liftLinear_apply {f : OuterMeasure α →ₗ[ℝ≥0∞] OuterMeasure β} (hf) (s : Set β) : - f μ.toOuterMeasure s ≤ liftLinear f hf μ s := - le_toMeasure_apply _ (hf μ) s - -open Classical in -/-- The pushforward of a measure as a linear map. It is defined to be `0` if `f` is not -a measurable function. -/ -def mapₗ [MeasurableSpace α] [MeasurableSpace β] (f : α → β) : Measure α →ₗ[ℝ≥0∞] Measure β := - if hf : Measurable f then - liftLinear (OuterMeasure.map f) fun μ _s hs t => - le_toOuterMeasure_caratheodory μ _ (hf hs) (f ⁻¹' t) - else 0 - -theorem mapₗ_congr {f g : α → β} (hf : Measurable f) (hg : Measurable g) (h : f =ᵐ[μ] g) : - mapₗ f μ = mapₗ g μ := by - ext1 s hs - simpa only [mapₗ, hf, hg, hs, dif_pos, liftLinear_apply, OuterMeasure.map_apply] - using measure_congr (h.preimage s) - -open Classical in -/-- The pushforward of a measure. It is defined to be `0` if `f` is not an almost everywhere -measurable function. -/ -irreducible_def map [MeasurableSpace α] [MeasurableSpace β] (f : α → β) (μ : Measure α) : - Measure β := - if hf : AEMeasurable f μ then mapₗ (hf.mk f) μ else 0 - -theorem mapₗ_mk_apply_of_aemeasurable {f : α → β} (hf : AEMeasurable f μ) : - mapₗ (hf.mk f) μ = map f μ := by simp [map, hf] - -theorem mapₗ_apply_of_measurable {f : α → β} (hf : Measurable f) (μ : Measure α) : - mapₗ f μ = map f μ := by - simp only [← mapₗ_mk_apply_of_aemeasurable hf.aemeasurable] - exact mapₗ_congr hf hf.aemeasurable.measurable_mk hf.aemeasurable.ae_eq_mk - -@[simp] -theorem map_add (μ ν : Measure α) {f : α → β} (hf : Measurable f) : - (μ + ν).map f = μ.map f + ν.map f := by simp [← mapₗ_apply_of_measurable hf] - -@[simp] -theorem map_zero (f : α → β) : (0 : Measure α).map f = 0 := by - by_cases hf : AEMeasurable f (0 : Measure α) <;> simp [map, hf] - -@[simp] -theorem map_of_not_aemeasurable {f : α → β} {μ : Measure α} (hf : ¬AEMeasurable f μ) : - μ.map f = 0 := by simp [map, hf] - -theorem _root_.AEMeasurable.of_map_ne_zero {f : α → β} {μ : Measure α} (hf : μ.map f ≠ 0) : - AEMeasurable f μ := not_imp_comm.1 map_of_not_aemeasurable hf - -theorem map_congr {f g : α → β} (h : f =ᵐ[μ] g) : Measure.map f μ = Measure.map g μ := by - by_cases hf : AEMeasurable f μ - · have hg : AEMeasurable g μ := hf.congr h - simp only [← mapₗ_mk_apply_of_aemeasurable hf, ← mapₗ_mk_apply_of_aemeasurable hg] - exact - mapₗ_congr hf.measurable_mk hg.measurable_mk (hf.ae_eq_mk.symm.trans (h.trans hg.ae_eq_mk)) - · have hg : ¬AEMeasurable g μ := by simpa [← aemeasurable_congr h] using hf - simp [map_of_not_aemeasurable, hf, hg] - -@[simp] -protected theorem map_smul {R : Type*} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] - (c : R) (μ : Measure α) (f : α → β) : (c • μ).map f = c • μ.map f := by - suffices ∀ c : ℝ≥0∞, (c • μ).map f = c • μ.map f by simpa using this (c • 1) - clear c; intro c - rcases eq_or_ne c 0 with (rfl | hc); · simp - by_cases hf : AEMeasurable f μ - · have hfc : AEMeasurable f (c • μ) := - ⟨hf.mk f, hf.measurable_mk, (ae_smul_measure_iff hc).2 hf.ae_eq_mk⟩ - simp only [← mapₗ_mk_apply_of_aemeasurable hf, ← mapₗ_mk_apply_of_aemeasurable hfc, - LinearMap.map_smulₛₗ, RingHom.id_apply] - congr 1 - apply mapₗ_congr hfc.measurable_mk hf.measurable_mk - exact EventuallyEq.trans ((ae_smul_measure_iff hc).1 hfc.ae_eq_mk.symm) hf.ae_eq_mk - · have hfc : ¬AEMeasurable f (c • μ) := by - intro hfc - exact hf ⟨hfc.mk f, hfc.measurable_mk, (ae_smul_measure_iff hc).1 hfc.ae_eq_mk⟩ - simp [map_of_not_aemeasurable hf, map_of_not_aemeasurable hfc] - - -@[deprecated Measure.map_smul (since := "2024-11-13")] -protected theorem map_smul_nnreal (c : ℝ≥0) (μ : Measure α) (f : α → β) : - (c • μ).map f = c • μ.map f := - μ.map_smul c f - -variable {f : α → β} - -lemma map_apply₀ {f : α → β} (hf : AEMeasurable f μ) {s : Set β} - (hs : NullMeasurableSet s (map f μ)) : μ.map f s = μ (f ⁻¹' s) := by - rw [map, dif_pos hf, mapₗ, dif_pos hf.measurable_mk] at hs ⊢ - rw [liftLinear_apply₀ _ hs, measure_congr (hf.ae_eq_mk.preimage s)] - rfl - -/-- We can evaluate the pushforward on measurable sets. For non-measurable sets, see - `MeasureTheory.Measure.le_map_apply` and `MeasurableEquiv.map_apply`. -/ -@[simp] -theorem map_apply_of_aemeasurable (hf : AEMeasurable f μ) {s : Set β} (hs : MeasurableSet s) : - μ.map f s = μ (f ⁻¹' s) := map_apply₀ hf hs.nullMeasurableSet - -@[simp] -theorem map_apply (hf : Measurable f) {s : Set β} (hs : MeasurableSet s) : - μ.map f s = μ (f ⁻¹' s) := - map_apply_of_aemeasurable hf.aemeasurable hs - -theorem map_toOuterMeasure (hf : AEMeasurable f μ) : - (μ.map f).toOuterMeasure = (OuterMeasure.map f μ.toOuterMeasure).trim := by - rw [← trimmed, OuterMeasure.trim_eq_trim_iff] - intro s hs - simp [hf, hs] - -@[simp] lemma map_eq_zero_iff (hf : AEMeasurable f μ) : μ.map f = 0 ↔ μ = 0 := by - simp_rw [← measure_univ_eq_zero, map_apply_of_aemeasurable hf .univ, preimage_univ] - -@[simp] lemma mapₗ_eq_zero_iff (hf : Measurable f) : Measure.mapₗ f μ = 0 ↔ μ = 0 := by - rw [mapₗ_apply_of_measurable hf, map_eq_zero_iff hf.aemeasurable] - -/-- If `map f μ = μ`, then the measure of the preimage of any null measurable set `s` -is equal to the measure of `s`. -Note that this lemma does not assume (a.e.) measurability of `f`. -/ -lemma measure_preimage_of_map_eq_self {f : α → α} (hf : map f μ = μ) - {s : Set α} (hs : NullMeasurableSet s μ) : μ (f ⁻¹' s) = μ s := by - if hfm : AEMeasurable f μ then - rw [← map_apply₀ hfm, hf] - rwa [hf] - else - rw [map_of_not_aemeasurable hfm] at hf - simp [← hf] - -lemma map_ne_zero_iff (hf : AEMeasurable f μ) : μ.map f ≠ 0 ↔ μ ≠ 0 := (map_eq_zero_iff hf).not -lemma mapₗ_ne_zero_iff (hf : Measurable f) : Measure.mapₗ f μ ≠ 0 ↔ μ ≠ 0 := - (mapₗ_eq_zero_iff hf).not - -@[simp] -theorem map_id : map id μ = μ := - ext fun _ => map_apply measurable_id - -@[simp] -theorem map_id' : map (fun x => x) μ = μ := - map_id - -/-- Mapping a measure twice is the same as mapping the measure with the composition. This version is -for measurable functions. See `map_map_of_aemeasurable` when they are just ae measurable. -/ -theorem map_map {g : β → γ} {f : α → β} (hg : Measurable g) (hf : Measurable f) : - (μ.map f).map g = μ.map (g ∘ f) := - ext fun s hs => by simp [hf, hg, hs, hg hs, hg.comp hf, ← preimage_comp] - -@[mono] -theorem map_mono {f : α → β} (h : μ ≤ ν) (hf : Measurable f) : μ.map f ≤ ν.map f := - le_iff.2 fun s hs ↦ by simp [hf.aemeasurable, hs, h _] - -/-- Even if `s` is not measurable, we can bound `map f μ s` from below. - See also `MeasurableEquiv.map_apply`. -/ -theorem le_map_apply {f : α → β} (hf : AEMeasurable f μ) (s : Set β) : μ (f ⁻¹' s) ≤ μ.map f s := - calc - μ (f ⁻¹' s) ≤ μ (f ⁻¹' toMeasurable (μ.map f) s) := by gcongr; apply subset_toMeasurable - _ = μ.map f (toMeasurable (μ.map f) s) := - (map_apply_of_aemeasurable hf <| measurableSet_toMeasurable _ _).symm - _ = μ.map f s := measure_toMeasurable _ - -theorem le_map_apply_image {f : α → β} (hf : AEMeasurable f μ) (s : Set α) : - μ s ≤ μ.map f (f '' s) := - (measure_mono (subset_preimage_image f s)).trans (le_map_apply hf _) - -/-- Even if `s` is not measurable, `map f μ s = 0` implies that `μ (f ⁻¹' s) = 0`. -/ -theorem preimage_null_of_map_null {f : α → β} (hf : AEMeasurable f μ) {s : Set β} - (hs : μ.map f s = 0) : μ (f ⁻¹' s) = 0 := - nonpos_iff_eq_zero.mp <| (le_map_apply hf s).trans_eq hs - -theorem tendsto_ae_map {f : α → β} (hf : AEMeasurable f μ) : Tendsto f (ae μ) (ae (μ.map f)) := - fun _ hs => preimage_null_of_map_null hf hs - section Sum variable {f : ι → Measure α} @@ -1466,307 +1269,6 @@ theorem sum_add_sum {ι : Type*} (μ ν : ι → Measure α) : sum μ + sum ν = simp [*, Function.apply_extend (fun μ : Measure α ↦ μ s)] end Sum -/-! ### Absolute continuity -/ - -/-- We say that `μ` is absolutely continuous with respect to `ν`, or that `μ` is dominated by `ν`, - if `ν(A) = 0` implies that `μ(A) = 0`. -/ -def AbsolutelyContinuous {_m0 : MeasurableSpace α} (μ ν : Measure α) : Prop := - ∀ ⦃s : Set α⦄, ν s = 0 → μ s = 0 - -@[inherit_doc MeasureTheory.Measure.AbsolutelyContinuous] -scoped[MeasureTheory] infixl:50 " ≪ " => MeasureTheory.Measure.AbsolutelyContinuous - -theorem absolutelyContinuous_of_le (h : μ ≤ ν) : μ ≪ ν := fun s hs => - nonpos_iff_eq_zero.1 <| hs ▸ le_iff'.1 h s - -alias _root_.LE.le.absolutelyContinuous := absolutelyContinuous_of_le - -theorem absolutelyContinuous_of_eq (h : μ = ν) : μ ≪ ν := - h.le.absolutelyContinuous - -alias _root_.Eq.absolutelyContinuous := absolutelyContinuous_of_eq - -namespace AbsolutelyContinuous - -theorem mk (h : ∀ ⦃s : Set α⦄, MeasurableSet s → ν s = 0 → μ s = 0) : μ ≪ ν := by - intro s hs - rcases exists_measurable_superset_of_null hs with ⟨t, h1t, h2t, h3t⟩ - exact measure_mono_null h1t (h h2t h3t) - -@[refl] -protected theorem refl {_m0 : MeasurableSpace α} (μ : Measure α) : μ ≪ μ := - rfl.absolutelyContinuous - -protected theorem rfl : μ ≪ μ := fun _s hs => hs - -instance instIsRefl {_ : MeasurableSpace α} : IsRefl (Measure α) (· ≪ ·) := - ⟨fun _ => AbsolutelyContinuous.rfl⟩ - -@[simp] -protected lemma zero (μ : Measure α) : 0 ≪ μ := fun _ _ ↦ by simp - -@[trans] -protected theorem trans (h1 : μ₁ ≪ μ₂) (h2 : μ₂ ≪ μ₃) : μ₁ ≪ μ₃ := fun _s hs => h1 <| h2 hs - -@[mono] -protected theorem map (h : μ ≪ ν) {f : α → β} (hf : Measurable f) : μ.map f ≪ ν.map f := - AbsolutelyContinuous.mk fun s hs => by simpa [hf, hs] using @h _ - -protected theorem smul_left [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (h : μ ≪ ν) (c : R) : - c • μ ≪ ν := fun s hνs => by - simp only [h hνs, smul_apply, smul_zero, ← smul_one_smul ℝ≥0∞ c (0 : ℝ≥0∞)] - -/-- If `μ ≪ ν`, then `c • μ ≪ c • ν`. - -Earlier, this name was used for what's now called `AbsolutelyContinuous.smul_left`. -/ -protected theorem smul [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (h : μ ≪ ν) (c : R) : - c • μ ≪ c • ν := by - intro s hνs - rw [smul_apply, ← smul_one_smul ℝ≥0∞, smul_eq_mul, mul_eq_zero] at hνs ⊢ - exact hνs.imp_right fun hs ↦ h hs - -@[deprecated (since := "2024-11-14")] protected alias smul_both := AbsolutelyContinuous.smul - -protected lemma add (h1 : μ₁ ≪ ν) (h2 : μ₂ ≪ ν') : μ₁ + μ₂ ≪ ν + ν' := by - intro s hs - simp only [coe_add, Pi.add_apply, add_eq_zero] at hs ⊢ - exact ⟨h1 hs.1, h2 hs.2⟩ - -lemma add_left_iff {μ₁ μ₂ ν : Measure α} : - μ₁ + μ₂ ≪ ν ↔ μ₁ ≪ ν ∧ μ₂ ≪ ν := by - refine ⟨fun h ↦ ?_, fun h ↦ (h.1.add h.2).trans ?_⟩ - · have : ∀ s, ν s = 0 → μ₁ s = 0 ∧ μ₂ s = 0 := by intro s hs0; simpa using h hs0 - exact ⟨fun s hs0 ↦ (this s hs0).1, fun s hs0 ↦ (this s hs0).2⟩ - · rw [← two_smul ℝ≥0] - exact AbsolutelyContinuous.rfl.smul_left 2 - -lemma add_left {μ₁ μ₂ ν : Measure α} (h₁ : μ₁ ≪ ν) (h₂ : μ₂ ≪ ν) : μ₁ + μ₂ ≪ ν := - Measure.AbsolutelyContinuous.add_left_iff.mpr ⟨h₁, h₂⟩ - -lemma add_right (h1 : μ ≪ ν) (ν' : Measure α) : μ ≪ ν + ν' := by - intro s hs - simp only [coe_add, Pi.add_apply, add_eq_zero] at hs ⊢ - exact h1 hs.1 - -end AbsolutelyContinuous - -@[simp] -lemma absolutelyContinuous_zero_iff : μ ≪ 0 ↔ μ = 0 := - ⟨fun h ↦ measure_univ_eq_zero.mp (h rfl), fun h ↦ h.symm ▸ AbsolutelyContinuous.zero _⟩ - -alias absolutelyContinuous_refl := AbsolutelyContinuous.refl -alias absolutelyContinuous_rfl := AbsolutelyContinuous.rfl - -lemma absolutelyContinuous_sum_left {μs : ι → Measure α} (hμs : ∀ i, μs i ≪ ν) : - Measure.sum μs ≪ ν := - AbsolutelyContinuous.mk fun s hs hs0 ↦ by simp [sum_apply _ hs, fun i ↦ hμs i hs0] - -lemma absolutelyContinuous_sum_right {μs : ι → Measure α} (i : ι) (hνμ : ν ≪ μs i) : - ν ≪ Measure.sum μs := by - refine AbsolutelyContinuous.mk fun s hs hs0 ↦ ?_ - simp only [sum_apply _ hs, ENNReal.tsum_eq_zero] at hs0 - exact hνμ (hs0 i) - -lemma smul_absolutelyContinuous {c : ℝ≥0∞} : c • μ ≪ μ := .smul_left .rfl _ - -theorem absolutelyContinuous_of_le_smul {μ' : Measure α} {c : ℝ≥0∞} (hμ'_le : μ' ≤ c • μ) : - μ' ≪ μ := - (Measure.absolutelyContinuous_of_le hμ'_le).trans smul_absolutelyContinuous - -lemma absolutelyContinuous_smul {c : ℝ≥0∞} (hc : c ≠ 0) : μ ≪ c • μ := by - simp [AbsolutelyContinuous, hc] - -theorem ae_le_iff_absolutelyContinuous : ae μ ≤ ae ν ↔ μ ≪ ν := - ⟨fun h s => by - rw [measure_zero_iff_ae_nmem, measure_zero_iff_ae_nmem] - exact fun hs => h hs, fun h _ hs => h hs⟩ - -alias ⟨_root_.LE.le.absolutelyContinuous_of_ae, AbsolutelyContinuous.ae_le⟩ := - ae_le_iff_absolutelyContinuous - -alias ae_mono' := AbsolutelyContinuous.ae_le - -theorem AbsolutelyContinuous.ae_eq (h : μ ≪ ν) {f g : α → δ} (h' : f =ᵐ[ν] g) : f =ᵐ[μ] g := - h.ae_le h' - -protected theorem _root_.MeasureTheory.AEDisjoint.of_absolutelyContinuous - (h : AEDisjoint μ s t) {ν : Measure α} (h' : ν ≪ μ) : - AEDisjoint ν s t := h' h - -protected theorem _root_.MeasureTheory.AEDisjoint.of_le - (h : AEDisjoint μ s t) {ν : Measure α} (h' : ν ≤ μ) : - AEDisjoint ν s t := - h.of_absolutelyContinuous (Measure.absolutelyContinuous_of_le h') - -/-! ### Quasi measure preserving maps (a.k.a. non-singular maps) -/ - - -/-- A map `f : α → β` is said to be *quasi measure preserving* (a.k.a. non-singular) w.r.t. measures -`μa` and `μb` if it is measurable and `μb s = 0` implies `μa (f ⁻¹' s) = 0`. -/ -structure QuasiMeasurePreserving {m0 : MeasurableSpace α} (f : α → β) - (μa : Measure α := by volume_tac) - (μb : Measure β := by volume_tac) : Prop where - protected measurable : Measurable f - protected absolutelyContinuous : μa.map f ≪ μb - -namespace QuasiMeasurePreserving - -protected theorem id {_m0 : MeasurableSpace α} (μ : Measure α) : QuasiMeasurePreserving id μ μ := - ⟨measurable_id, map_id.absolutelyContinuous⟩ - -variable {μa μa' : Measure α} {μb μb' : Measure β} {μc : Measure γ} {f : α → β} - -protected theorem _root_.Measurable.quasiMeasurePreserving - {_m0 : MeasurableSpace α} (hf : Measurable f) (μ : Measure α) : - QuasiMeasurePreserving f μ (μ.map f) := - ⟨hf, AbsolutelyContinuous.rfl⟩ - -theorem mono_left (h : QuasiMeasurePreserving f μa μb) (ha : μa' ≪ μa) : - QuasiMeasurePreserving f μa' μb := - ⟨h.1, (ha.map h.1).trans h.2⟩ - -theorem mono_right (h : QuasiMeasurePreserving f μa μb) (ha : μb ≪ μb') : - QuasiMeasurePreserving f μa μb' := - ⟨h.1, h.2.trans ha⟩ - -@[mono] -theorem mono (ha : μa' ≪ μa) (hb : μb ≪ μb') (h : QuasiMeasurePreserving f μa μb) : - QuasiMeasurePreserving f μa' μb' := - (h.mono_left ha).mono_right hb - -protected theorem comp {g : β → γ} {f : α → β} (hg : QuasiMeasurePreserving g μb μc) - (hf : QuasiMeasurePreserving f μa μb) : QuasiMeasurePreserving (g ∘ f) μa μc := - ⟨hg.measurable.comp hf.measurable, by - rw [← map_map hg.1 hf.1] - exact (hf.2.map hg.1).trans hg.2⟩ - -protected theorem iterate {f : α → α} (hf : QuasiMeasurePreserving f μa μa) : - ∀ n, QuasiMeasurePreserving f^[n] μa μa - | 0 => QuasiMeasurePreserving.id μa - | n + 1 => (hf.iterate n).comp hf - -protected theorem aemeasurable (hf : QuasiMeasurePreserving f μa μb) : AEMeasurable f μa := - hf.1.aemeasurable - -theorem smul_measure {R : Type*} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] - (hf : QuasiMeasurePreserving f μa μb) (c : R) : QuasiMeasurePreserving f (c • μa) (c • μb) := - ⟨hf.1, by rw [Measure.map_smul]; exact hf.2.smul c⟩ - -theorem ae_map_le (h : QuasiMeasurePreserving f μa μb) : ae (μa.map f) ≤ ae μb := - h.2.ae_le - -theorem tendsto_ae (h : QuasiMeasurePreserving f μa μb) : Tendsto f (ae μa) (ae μb) := - (tendsto_ae_map h.aemeasurable).mono_right h.ae_map_le - -theorem ae (h : QuasiMeasurePreserving f μa μb) {p : β → Prop} (hg : ∀ᵐ x ∂μb, p x) : - ∀ᵐ x ∂μa, p (f x) := - h.tendsto_ae hg - -theorem ae_eq (h : QuasiMeasurePreserving f μa μb) {g₁ g₂ : β → δ} (hg : g₁ =ᵐ[μb] g₂) : - g₁ ∘ f =ᵐ[μa] g₂ ∘ f := - h.ae hg - -theorem preimage_null (h : QuasiMeasurePreserving f μa μb) {s : Set β} (hs : μb s = 0) : - μa (f ⁻¹' s) = 0 := - preimage_null_of_map_null h.aemeasurable (h.2 hs) - -theorem preimage_mono_ae {s t : Set β} (hf : QuasiMeasurePreserving f μa μb) (h : s ≤ᵐ[μb] t) : - f ⁻¹' s ≤ᵐ[μa] f ⁻¹' t := - eventually_map.mp <| - Eventually.filter_mono (tendsto_ae_map hf.aemeasurable) (Eventually.filter_mono hf.ae_map_le h) - -theorem preimage_ae_eq {s t : Set β} (hf : QuasiMeasurePreserving f μa μb) (h : s =ᵐ[μb] t) : - f ⁻¹' s =ᵐ[μa] f ⁻¹' t := - EventuallyLE.antisymm (hf.preimage_mono_ae h.le) (hf.preimage_mono_ae h.symm.le) - -/-- The preimage of a null measurable set under a (quasi) measure preserving map is a null -measurable set. -/ -theorem _root_.MeasureTheory.NullMeasurableSet.preimage {s : Set β} (hs : NullMeasurableSet s μb) - (hf : QuasiMeasurePreserving f μa μb) : NullMeasurableSet (f ⁻¹' s) μa := - let ⟨t, htm, hst⟩ := hs - ⟨f ⁻¹' t, hf.measurable htm, hf.preimage_ae_eq hst⟩ - -theorem preimage_iterate_ae_eq {s : Set α} {f : α → α} (hf : QuasiMeasurePreserving f μ μ) (k : ℕ) - (hs : f ⁻¹' s =ᵐ[μ] s) : f^[k] ⁻¹' s =ᵐ[μ] s := by - induction' k with k ih; · rfl - rw [iterate_succ, preimage_comp] - exact EventuallyEq.trans (hf.preimage_ae_eq ih) hs - -theorem image_zpow_ae_eq {s : Set α} {e : α ≃ α} (he : QuasiMeasurePreserving e μ μ) - (he' : QuasiMeasurePreserving e.symm μ μ) (k : ℤ) (hs : e '' s =ᵐ[μ] s) : - (⇑(e ^ k)) '' s =ᵐ[μ] s := by - rw [Equiv.image_eq_preimage] - obtain ⟨k, rfl | rfl⟩ := k.eq_nat_or_neg - · replace hs : (⇑e⁻¹) ⁻¹' s =ᵐ[μ] s := by rwa [Equiv.image_eq_preimage] at hs - replace he' : (⇑e⁻¹)^[k] ⁻¹' s =ᵐ[μ] s := he'.preimage_iterate_ae_eq k hs - rwa [Equiv.Perm.iterate_eq_pow e⁻¹ k, inv_pow e k] at he' - · rw [zpow_neg, zpow_natCast] - replace hs : e ⁻¹' s =ᵐ[μ] s := by - convert he.preimage_ae_eq hs.symm - rw [Equiv.preimage_image] - replace he : (⇑e)^[k] ⁻¹' s =ᵐ[μ] s := he.preimage_iterate_ae_eq k hs - rwa [Equiv.Perm.iterate_eq_pow e k] at he - --- Need to specify `α := Set α` below because of diamond; see https://github.com/leanprover-community/mathlib4/issues/10941 -theorem limsup_preimage_iterate_ae_eq {f : α → α} (hf : QuasiMeasurePreserving f μ μ) - (hs : f ⁻¹' s =ᵐ[μ] s) : limsup (α := Set α) (fun n => (preimage f)^[n] s) atTop =ᵐ[μ] s := - limsup_ae_eq_of_forall_ae_eq (fun n => (preimage f)^[n] s) fun n ↦ by - simpa only [Set.preimage_iterate_eq] using hf.preimage_iterate_ae_eq n hs - --- Need to specify `α := Set α` below because of diamond; see https://github.com/leanprover-community/mathlib4/issues/10941 -theorem liminf_preimage_iterate_ae_eq {f : α → α} (hf : QuasiMeasurePreserving f μ μ) - (hs : f ⁻¹' s =ᵐ[μ] s) : liminf (α := Set α) (fun n => (preimage f)^[n] s) atTop =ᵐ[μ] s := - liminf_ae_eq_of_forall_ae_eq (fun n => (preimage f)^[n] s) fun n ↦ by - simpa only [Set.preimage_iterate_eq] using hf.preimage_iterate_ae_eq n hs - -/-- For a quasi measure preserving self-map `f`, if a null measurable set `s` is a.e. invariant, -then it is a.e. equal to a measurable invariant set. --/ -theorem exists_preimage_eq_of_preimage_ae {f : α → α} (h : QuasiMeasurePreserving f μ μ) - (hs : NullMeasurableSet s μ) (hs' : f ⁻¹' s =ᵐ[μ] s) : - ∃ t : Set α, MeasurableSet t ∧ t =ᵐ[μ] s ∧ f ⁻¹' t = t := by - obtain ⟨t, htm, ht⟩ := hs - refine ⟨limsup (f^[·] ⁻¹' t) atTop, ?_, ?_, ?_⟩ - · exact .measurableSet_limsup fun n ↦ h.measurable.iterate n htm - · have : f ⁻¹' t =ᵐ[μ] t := (h.preimage_ae_eq ht.symm).trans (hs'.trans ht) - exact limsup_ae_eq_of_forall_ae_eq _ fun n ↦ .trans (h.preimage_iterate_ae_eq _ this) ht.symm - · simp only [Set.preimage_iterate_eq] - exact CompleteLatticeHom.apply_limsup_iterate (CompleteLatticeHom.setPreimage f) t - -open Pointwise - -@[to_additive] -theorem smul_ae_eq_of_ae_eq {G α : Type*} [Group G] [MulAction G α] {_ : MeasurableSpace α} - {s t : Set α} {μ : Measure α} (g : G) - (h_qmp : QuasiMeasurePreserving (g⁻¹ • · : α → α) μ μ) - (h_ae_eq : s =ᵐ[μ] t) : (g • s : Set α) =ᵐ[μ] (g • t : Set α) := by - simpa only [← preimage_smul_inv] using h_qmp.ae_eq h_ae_eq - -end QuasiMeasurePreserving - -section Pointwise - -open Pointwise - -@[to_additive] -theorem pairwise_aedisjoint_of_aedisjoint_forall_ne_one {G α : Type*} [Group G] [MulAction G α] - {_ : MeasurableSpace α} {μ : Measure α} {s : Set α} - (h_ae_disjoint : ∀ g ≠ (1 : G), AEDisjoint μ (g • s) s) - (h_qmp : ∀ g : G, QuasiMeasurePreserving (g • ·) μ μ) : - Pairwise (AEDisjoint μ on fun g : G => g • s) := by - intro g₁ g₂ hg - let g := g₂⁻¹ * g₁ - replace hg : g ≠ 1 := by - rw [Ne, inv_mul_eq_one] - exact hg.symm - have : (g₂⁻¹ • ·) ⁻¹' (g • s ∩ s) = g₁ • s ∩ g₂ • s := by - rw [preimage_eq_iff_eq_image (MulAction.bijective g₂⁻¹), image_smul, smul_set_inter, smul_smul, - smul_smul, inv_mul_cancel, one_smul] - change μ (g₁ • s ∩ g₂ • s) = 0 - exact this ▸ (h_qmp g₂⁻¹).preimage_null (h_ae_disjoint g hg) - -end Pointwise - /-! ### The `cofinite` filter -/ /-- The filter of sets `s` such that `sᶜ` has finite measure. -/ @@ -1803,17 +1305,6 @@ lemma _root_.AEMeasurable.nullMeasurableSet_preimage {f : α → β} {s : Set β (hf : AEMeasurable f μ) (hs : MeasurableSet s) : NullMeasurableSet (f ⁻¹' s) μ := hf.nullMeasurable hs -theorem NullMeasurableSet.mono_ac (h : NullMeasurableSet s μ) (hle : ν ≪ μ) : - NullMeasurableSet s ν := - h.preimage <| (QuasiMeasurePreserving.id μ).mono_left hle - -theorem NullMeasurableSet.mono (h : NullMeasurableSet s μ) (hle : ν ≤ μ) : NullMeasurableSet s ν := - h.mono_ac hle.absolutelyContinuous - -theorem AEDisjoint.preimage {ν : Measure β} {f : α → β} {s t : Set β} (ht : AEDisjoint ν s t) - (hf : QuasiMeasurePreserving f μ ν) : AEDisjoint μ (f ⁻¹' s) (f ⁻¹' t) := - hf.preimage_null ht - @[simp] theorem ae_eq_bot : ae μ = ⊥ ↔ μ = 0 := by rw [← empty_mem_iff_bot, mem_ae_iff, compl_empty, measure_univ_eq_zero] @@ -1828,35 +1319,6 @@ instance Measure.ae.neBot [NeZero μ] : (ae μ).NeBot := ae_neBot.2 <| NeZero.ne theorem ae_zero {_m0 : MeasurableSpace α} : ae (0 : Measure α) = ⊥ := ae_eq_bot.2 rfl -@[mono] -theorem ae_mono (h : μ ≤ ν) : ae μ ≤ ae ν := - h.absolutelyContinuous.ae_le - -theorem mem_ae_map_iff {f : α → β} (hf : AEMeasurable f μ) {s : Set β} (hs : MeasurableSet s) : - s ∈ ae (μ.map f) ↔ f ⁻¹' s ∈ ae μ := by - simp only [mem_ae_iff, map_apply_of_aemeasurable hf hs.compl, preimage_compl] - -theorem mem_ae_of_mem_ae_map {f : α → β} (hf : AEMeasurable f μ) {s : Set β} - (hs : s ∈ ae (μ.map f)) : f ⁻¹' s ∈ ae μ := - (tendsto_ae_map hf).eventually hs - -theorem ae_map_iff {f : α → β} (hf : AEMeasurable f μ) {p : β → Prop} - (hp : MeasurableSet { x | p x }) : (∀ᵐ y ∂μ.map f, p y) ↔ ∀ᵐ x ∂μ, p (f x) := - mem_ae_map_iff hf hp - -theorem ae_of_ae_map {f : α → β} (hf : AEMeasurable f μ) {p : β → Prop} (h : ∀ᵐ y ∂μ.map f, p y) : - ∀ᵐ x ∂μ, p (f x) := - mem_ae_of_mem_ae_map hf h - -theorem ae_map_mem_range {m0 : MeasurableSpace α} (f : α → β) (hf : MeasurableSet (range f)) - (μ : Measure α) : ∀ᵐ x ∂μ.map f, x ∈ range f := by - by_cases h : AEMeasurable f μ - · change range f ∈ ae (μ.map f) - rw [mem_ae_map_iff h hf] - filter_upwards using mem_range_self - · simp [map_of_not_aemeasurable h] - - section Intervals theorem biSup_measure_Iic [Preorder α] {s : Set α} (hsc : s.Countable) @@ -1921,76 +1383,4 @@ end end MeasureTheory -namespace MeasurableEmbedding - -open MeasureTheory Measure - -variable {m0 : MeasurableSpace α} {m1 : MeasurableSpace β} {f : α → β} {μ ν : Measure α} - -nonrec theorem map_apply (hf : MeasurableEmbedding f) (μ : Measure α) (s : Set β) : - μ.map f s = μ (f ⁻¹' s) := by - refine le_antisymm ?_ (le_map_apply hf.measurable.aemeasurable s) - set t := f '' toMeasurable μ (f ⁻¹' s) ∪ (range f)ᶜ - have htm : MeasurableSet t := - (hf.measurableSet_image.2 <| measurableSet_toMeasurable _ _).union - hf.measurableSet_range.compl - have hst : s ⊆ t := by - rw [subset_union_compl_iff_inter_subset, ← image_preimage_eq_inter_range] - exact image_subset _ (subset_toMeasurable _ _) - have hft : f ⁻¹' t = toMeasurable μ (f ⁻¹' s) := by - rw [preimage_union, preimage_compl, preimage_range, compl_univ, union_empty, - hf.injective.preimage_image] - calc - μ.map f s ≤ μ.map f t := by gcongr - _ = μ (f ⁻¹' s) := by rw [map_apply hf.measurable htm, hft, measure_toMeasurable] - -lemma absolutelyContinuous_map (hf : MeasurableEmbedding f) (hμν : μ ≪ ν) : - μ.map f ≪ ν.map f := by - intro t ht - rw [hf.map_apply] at ht ⊢ - exact hμν ht - -end MeasurableEmbedding - -namespace MeasurableEquiv - -/-! Interactions of measurable equivalences and measures -/ - -open Equiv MeasureTheory.Measure - -variable {_ : MeasurableSpace α} [MeasurableSpace β] {μ : Measure α} {ν : Measure β} - -/-- If we map a measure along a measurable equivalence, we can compute the measure on all sets - (not just the measurable ones). -/ -protected theorem map_apply (f : α ≃ᵐ β) (s : Set β) : μ.map f s = μ (f ⁻¹' s) := - f.measurableEmbedding.map_apply _ _ - -@[simp] -theorem map_symm_map (e : α ≃ᵐ β) : (μ.map e).map e.symm = μ := by - simp [map_map e.symm.measurable e.measurable] - -@[simp] -theorem map_map_symm (e : α ≃ᵐ β) : (ν.map e.symm).map e = ν := by - simp [map_map e.measurable e.symm.measurable] - -theorem map_measurableEquiv_injective (e : α ≃ᵐ β) : Injective (Measure.map e) := by - intro μ₁ μ₂ hμ - apply_fun Measure.map e.symm at hμ - simpa [map_symm_map e] using hμ - -theorem map_apply_eq_iff_map_symm_apply_eq (e : α ≃ᵐ β) : μ.map e = ν ↔ ν.map e.symm = μ := by - rw [← (map_measurableEquiv_injective e).eq_iff, map_map_symm, eq_comm] - -theorem map_ae (f : α ≃ᵐ β) (μ : Measure α) : Filter.map f (ae μ) = ae (map f μ) := by - ext s - simp_rw [mem_map, mem_ae_iff, ← preimage_compl, f.map_apply] - -theorem quasiMeasurePreserving_symm (μ : Measure α) (e : α ≃ᵐ β) : - QuasiMeasurePreserving e.symm (map e μ) μ := - ⟨e.symm.measurable, by rw [Measure.map_map, e.symm_comp_self, Measure.map_id] <;> measurability⟩ - -end MeasurableEquiv - end - -set_option linter.style.longFile 2100 diff --git a/Mathlib/MeasureTheory/Measure/QuasiMeasurePreserving.lean b/Mathlib/MeasureTheory/Measure/QuasiMeasurePreserving.lean new file mode 100644 index 0000000000000..0630e9e86c598 --- /dev/null +++ b/Mathlib/MeasureTheory/Measure/QuasiMeasurePreserving.lean @@ -0,0 +1,229 @@ +/- +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, Mario Carneiro +-/ +import Mathlib.MeasureTheory.Measure.AbsolutelyContinuous +import Mathlib.MeasureTheory.OuterMeasure.BorelCantelli + +/-! +# Quasi Measure Preserving Functions + +A map `f : α → β` is said to be *quasi measure preserving* (a.k.a. non-singular) w.r.t. measures +`μa` and `μb` if it is measurable and `μb s = 0` implies `μa (f ⁻¹' s) = 0`. +That last condition can also be written `μa.map f ≪ μb` (the map of `μa` by `f` is +absolutely continuous with respect to `μb`). + +## Main definitions + +* `MeasureTheory.Measure.QuasiMeasurePreserving f μa μb`: `f` is quasi measure preserving with + respect to `μa` and `μb`. + +-/ + +variable {α β γ δ : Type*} + +namespace MeasureTheory + +open Set Function ENNReal +open Filter hiding map + +variable {mα : MeasurableSpace α} {mβ : MeasurableSpace β} {mγ : MeasurableSpace γ} + {μ ν : Measure α} {s : Set α} + +namespace Measure + +/-- A map `f : α → β` is said to be *quasi measure preserving* (a.k.a. non-singular) w.r.t. measures +`μa` and `μb` if it is measurable and `μb s = 0` implies `μa (f ⁻¹' s) = 0`. -/ +structure QuasiMeasurePreserving {m0 : MeasurableSpace α} (f : α → β) + (μa : Measure α := by volume_tac) + (μb : Measure β := by volume_tac) : Prop where + protected measurable : Measurable f + protected absolutelyContinuous : μa.map f ≪ μb + +namespace QuasiMeasurePreserving + +protected theorem id {_m0 : MeasurableSpace α} (μ : Measure α) : QuasiMeasurePreserving id μ μ := + ⟨measurable_id, map_id.absolutelyContinuous⟩ + +variable {μa μa' : Measure α} {μb μb' : Measure β} {μc : Measure γ} {f : α → β} + +protected theorem _root_.Measurable.quasiMeasurePreserving + {_m0 : MeasurableSpace α} (hf : Measurable f) (μ : Measure α) : + QuasiMeasurePreserving f μ (μ.map f) := + ⟨hf, AbsolutelyContinuous.rfl⟩ + +theorem mono_left (h : QuasiMeasurePreserving f μa μb) (ha : μa' ≪ μa) : + QuasiMeasurePreserving f μa' μb := + ⟨h.1, (ha.map h.1).trans h.2⟩ + +theorem mono_right (h : QuasiMeasurePreserving f μa μb) (ha : μb ≪ μb') : + QuasiMeasurePreserving f μa μb' := + ⟨h.1, h.2.trans ha⟩ + +@[mono] +theorem mono (ha : μa' ≪ μa) (hb : μb ≪ μb') (h : QuasiMeasurePreserving f μa μb) : + QuasiMeasurePreserving f μa' μb' := + (h.mono_left ha).mono_right hb + +protected theorem comp {g : β → γ} {f : α → β} (hg : QuasiMeasurePreserving g μb μc) + (hf : QuasiMeasurePreserving f μa μb) : QuasiMeasurePreserving (g ∘ f) μa μc := + ⟨hg.measurable.comp hf.measurable, by + rw [← map_map hg.1 hf.1] + exact (hf.2.map hg.1).trans hg.2⟩ + +protected theorem iterate {f : α → α} (hf : QuasiMeasurePreserving f μa μa) : + ∀ n, QuasiMeasurePreserving f^[n] μa μa + | 0 => QuasiMeasurePreserving.id μa + | n + 1 => (hf.iterate n).comp hf + +protected theorem aemeasurable (hf : QuasiMeasurePreserving f μa μb) : AEMeasurable f μa := + hf.1.aemeasurable + +theorem smul_measure {R : Type*} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] + (hf : QuasiMeasurePreserving f μa μb) (c : R) : QuasiMeasurePreserving f (c • μa) (c • μb) := + ⟨hf.1, by rw [Measure.map_smul]; exact hf.2.smul c⟩ + +theorem ae_map_le (h : QuasiMeasurePreserving f μa μb) : ae (μa.map f) ≤ ae μb := + h.2.ae_le + +theorem tendsto_ae (h : QuasiMeasurePreserving f μa μb) : Tendsto f (ae μa) (ae μb) := + (tendsto_ae_map h.aemeasurable).mono_right h.ae_map_le + +theorem ae (h : QuasiMeasurePreserving f μa μb) {p : β → Prop} (hg : ∀ᵐ x ∂μb, p x) : + ∀ᵐ x ∂μa, p (f x) := + h.tendsto_ae hg + +theorem ae_eq (h : QuasiMeasurePreserving f μa μb) {g₁ g₂ : β → δ} (hg : g₁ =ᵐ[μb] g₂) : + g₁ ∘ f =ᵐ[μa] g₂ ∘ f := + h.ae hg + +theorem preimage_null (h : QuasiMeasurePreserving f μa μb) {s : Set β} (hs : μb s = 0) : + μa (f ⁻¹' s) = 0 := + preimage_null_of_map_null h.aemeasurable (h.2 hs) + +theorem preimage_mono_ae {s t : Set β} (hf : QuasiMeasurePreserving f μa μb) (h : s ≤ᵐ[μb] t) : + f ⁻¹' s ≤ᵐ[μa] f ⁻¹' t := + eventually_map.mp <| + Eventually.filter_mono (tendsto_ae_map hf.aemeasurable) (Eventually.filter_mono hf.ae_map_le h) + +theorem preimage_ae_eq {s t : Set β} (hf : QuasiMeasurePreserving f μa μb) (h : s =ᵐ[μb] t) : + f ⁻¹' s =ᵐ[μa] f ⁻¹' t := + EventuallyLE.antisymm (hf.preimage_mono_ae h.le) (hf.preimage_mono_ae h.symm.le) + +/-- The preimage of a null measurable set under a (quasi) measure preserving map is a null +measurable set. -/ +theorem _root_.MeasureTheory.NullMeasurableSet.preimage {s : Set β} (hs : NullMeasurableSet s μb) + (hf : QuasiMeasurePreserving f μa μb) : NullMeasurableSet (f ⁻¹' s) μa := + let ⟨t, htm, hst⟩ := hs + ⟨f ⁻¹' t, hf.measurable htm, hf.preimage_ae_eq hst⟩ + +theorem preimage_iterate_ae_eq {s : Set α} {f : α → α} (hf : QuasiMeasurePreserving f μ μ) (k : ℕ) + (hs : f ⁻¹' s =ᵐ[μ] s) : f^[k] ⁻¹' s =ᵐ[μ] s := by + induction' k with k ih; · rfl + rw [iterate_succ, preimage_comp] + exact EventuallyEq.trans (hf.preimage_ae_eq ih) hs + +theorem image_zpow_ae_eq {s : Set α} {e : α ≃ α} (he : QuasiMeasurePreserving e μ μ) + (he' : QuasiMeasurePreserving e.symm μ μ) (k : ℤ) (hs : e '' s =ᵐ[μ] s) : + (⇑(e ^ k)) '' s =ᵐ[μ] s := by + rw [Equiv.image_eq_preimage] + obtain ⟨k, rfl | rfl⟩ := k.eq_nat_or_neg + · replace hs : (⇑e⁻¹) ⁻¹' s =ᵐ[μ] s := by rwa [Equiv.image_eq_preimage] at hs + replace he' : (⇑e⁻¹)^[k] ⁻¹' s =ᵐ[μ] s := he'.preimage_iterate_ae_eq k hs + rwa [Equiv.Perm.iterate_eq_pow e⁻¹ k, inv_pow e k] at he' + · rw [zpow_neg, zpow_natCast] + replace hs : e ⁻¹' s =ᵐ[μ] s := by + convert he.preimage_ae_eq hs.symm + rw [Equiv.preimage_image] + replace he : (⇑e)^[k] ⁻¹' s =ᵐ[μ] s := he.preimage_iterate_ae_eq k hs + rwa [Equiv.Perm.iterate_eq_pow e k] at he + +-- Need to specify `α := Set α` below because of diamond; see https://github.com/leanprover-community/mathlib4/issues/10941 +theorem limsup_preimage_iterate_ae_eq {f : α → α} (hf : QuasiMeasurePreserving f μ μ) + (hs : f ⁻¹' s =ᵐ[μ] s) : limsup (α := Set α) (fun n => (preimage f)^[n] s) atTop =ᵐ[μ] s := + limsup_ae_eq_of_forall_ae_eq (fun n => (preimage f)^[n] s) fun n ↦ by + simpa only [Set.preimage_iterate_eq] using hf.preimage_iterate_ae_eq n hs + +-- Need to specify `α := Set α` below because of diamond; see https://github.com/leanprover-community/mathlib4/issues/10941 +theorem liminf_preimage_iterate_ae_eq {f : α → α} (hf : QuasiMeasurePreserving f μ μ) + (hs : f ⁻¹' s =ᵐ[μ] s) : liminf (α := Set α) (fun n => (preimage f)^[n] s) atTop =ᵐ[μ] s := + liminf_ae_eq_of_forall_ae_eq (fun n => (preimage f)^[n] s) fun n ↦ by + simpa only [Set.preimage_iterate_eq] using hf.preimage_iterate_ae_eq n hs + +/-- For a quasi measure preserving self-map `f`, if a null measurable set `s` is a.e. invariant, +then it is a.e. equal to a measurable invariant set. +-/ +theorem exists_preimage_eq_of_preimage_ae {f : α → α} (h : QuasiMeasurePreserving f μ μ) + (hs : NullMeasurableSet s μ) (hs' : f ⁻¹' s =ᵐ[μ] s) : + ∃ t : Set α, MeasurableSet t ∧ t =ᵐ[μ] s ∧ f ⁻¹' t = t := by + obtain ⟨t, htm, ht⟩ := hs + refine ⟨limsup (f^[·] ⁻¹' t) atTop, ?_, ?_, ?_⟩ + · exact .measurableSet_limsup fun n ↦ h.measurable.iterate n htm + · have : f ⁻¹' t =ᵐ[μ] t := (h.preimage_ae_eq ht.symm).trans (hs'.trans ht) + exact limsup_ae_eq_of_forall_ae_eq _ fun n ↦ .trans (h.preimage_iterate_ae_eq _ this) ht.symm + · simp only [Set.preimage_iterate_eq] + exact CompleteLatticeHom.apply_limsup_iterate (CompleteLatticeHom.setPreimage f) t + +open Pointwise + +@[to_additive] +theorem smul_ae_eq_of_ae_eq {G α : Type*} [Group G] [MulAction G α] {_ : MeasurableSpace α} + {s t : Set α} {μ : Measure α} (g : G) + (h_qmp : QuasiMeasurePreserving (g⁻¹ • · : α → α) μ μ) + (h_ae_eq : s =ᵐ[μ] t) : (g • s : Set α) =ᵐ[μ] (g • t : Set α) := by + simpa only [← preimage_smul_inv] using h_qmp.ae_eq h_ae_eq + +end QuasiMeasurePreserving + +section Pointwise + +open Pointwise + +@[to_additive] +theorem pairwise_aedisjoint_of_aedisjoint_forall_ne_one {G α : Type*} [Group G] [MulAction G α] + {_ : MeasurableSpace α} {μ : Measure α} {s : Set α} + (h_ae_disjoint : ∀ g ≠ (1 : G), AEDisjoint μ (g • s) s) + (h_qmp : ∀ g : G, QuasiMeasurePreserving (g • ·) μ μ) : + Pairwise (AEDisjoint μ on fun g : G => g • s) := by + intro g₁ g₂ hg + let g := g₂⁻¹ * g₁ + replace hg : g ≠ 1 := by + rw [Ne, inv_mul_eq_one] + exact hg.symm + have : (g₂⁻¹ • ·) ⁻¹' (g • s ∩ s) = g₁ • s ∩ g₂ • s := by + rw [preimage_eq_iff_eq_image (MulAction.bijective g₂⁻¹), image_smul, smul_set_inter, smul_smul, + smul_smul, inv_mul_cancel, one_smul] + change μ (g₁ • s ∩ g₂ • s) = 0 + exact this ▸ (h_qmp g₂⁻¹).preimage_null (h_ae_disjoint g hg) + +end Pointwise + +end Measure + +open Measure + +theorem NullMeasurableSet.mono_ac (h : NullMeasurableSet s μ) (hle : ν ≪ μ) : + NullMeasurableSet s ν := + h.preimage <| (QuasiMeasurePreserving.id μ).mono_left hle + +theorem NullMeasurableSet.mono (h : NullMeasurableSet s μ) (hle : ν ≤ μ) : NullMeasurableSet s ν := + h.mono_ac hle.absolutelyContinuous + +theorem AEDisjoint.preimage {ν : Measure β} {f : α → β} {s t : Set β} (ht : AEDisjoint ν s t) + (hf : QuasiMeasurePreserving f μ ν) : AEDisjoint μ (f ⁻¹' s) (f ⁻¹' t) := + hf.preimage_null ht + +end MeasureTheory + +open MeasureTheory + +namespace MeasurableEquiv + +variable {_ : MeasurableSpace α} [MeasurableSpace β] {μ : Measure α} {ν : Measure β} + +theorem quasiMeasurePreserving_symm (μ : Measure α) (e : α ≃ᵐ β) : + Measure.QuasiMeasurePreserving e.symm (μ.map e) μ := + ⟨e.symm.measurable, by rw [Measure.map_map, e.symm_comp_self, Measure.map_id] <;> measurability⟩ + +end MeasurableEquiv diff --git a/Mathlib/MeasureTheory/Measure/Restrict.lean b/Mathlib/MeasureTheory/Measure/Restrict.lean index 71525b1a85059..cfbce99dab3ec 100644 --- a/Mathlib/MeasureTheory/Measure/Restrict.lean +++ b/Mathlib/MeasureTheory/Measure/Restrict.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.MeasureTheory.Measure.Comap +import Mathlib.MeasureTheory.Measure.QuasiMeasurePreserving /-! # Restricting a measure to a subset or a subtype From 231146f0404e6d6e8f63ebbef0402cd3a76fd4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 7 Jan 2025 20:33:01 +0000 Subject: [PATCH 062/681] chore(AlgebraicTopology): move SplitSimplicialObject.lean (#20511) This PR moves `SplitSimplicialObject` to `SimplicialObject.Split`. --- Mathlib.lean | 2 +- Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean | 2 +- Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean | 2 +- .../{SplitSimplicialObject.lean => SimplicialObject/Split.lean} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename Mathlib/AlgebraicTopology/{SplitSimplicialObject.lean => SimplicialObject/Split.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index a35603b24ceef..439e51e558829 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1082,6 +1082,7 @@ import Mathlib.AlgebraicTopology.SimplicialCategory.SimplicialObject import Mathlib.AlgebraicTopology.SimplicialNerve import Mathlib.AlgebraicTopology.SimplicialObject.Basic import Mathlib.AlgebraicTopology.SimplicialObject.Coskeletal +import Mathlib.AlgebraicTopology.SimplicialObject.Split import Mathlib.AlgebraicTopology.SimplicialSet.Basic import Mathlib.AlgebraicTopology.SimplicialSet.Coskeletal import Mathlib.AlgebraicTopology.SimplicialSet.HomotopyCat @@ -1091,7 +1092,6 @@ import Mathlib.AlgebraicTopology.SimplicialSet.Nerve import Mathlib.AlgebraicTopology.SimplicialSet.Path import Mathlib.AlgebraicTopology.SimplicialSet.StrictSegal import Mathlib.AlgebraicTopology.SingularSet -import Mathlib.AlgebraicTopology.SplitSimplicialObject import Mathlib.AlgebraicTopology.TopologicalSimplex import Mathlib.Analysis.Analytic.Basic import Mathlib.Analysis.Analytic.CPolynomial diff --git a/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean b/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean index 67d99a2628ff5..95e605ee3c7a9 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.AlgebraicTopology.SplitSimplicialObject +import Mathlib.AlgebraicTopology.SimplicialObject.Split import Mathlib.AlgebraicTopology.DoldKan.PInfty /-! diff --git a/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean b/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean index bfe4476eb64b1..c04554d7644e9 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.AlgebraicTopology.SplitSimplicialObject +import Mathlib.AlgebraicTopology.SimplicialObject.Split import Mathlib.AlgebraicTopology.DoldKan.Degeneracies import Mathlib.AlgebraicTopology.DoldKan.FunctorN diff --git a/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean b/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean similarity index 100% rename from Mathlib/AlgebraicTopology/SplitSimplicialObject.lean rename to Mathlib/AlgebraicTopology/SimplicialObject/Split.lean From 06c19488f753bbd4716ed8f1bb6d487163a49450 Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Tue, 7 Jan 2025 20:33:03 +0000 Subject: [PATCH 063/681] chore: protect `Filter.nhds_{iInf,inf}` (#20530) Per [Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/naming.3A.20nhds_iInf.20and.20Filter.2Enhds_iInf/near/482900553) --- Mathlib/Topology/Filter.lean | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mathlib/Topology/Filter.lean b/Mathlib/Topology/Filter.lean index 675480013b398..6cdd957ccc15e 100644 --- a/Mathlib/Topology/Filter.lean +++ b/Mathlib/Topology/Filter.lean @@ -119,16 +119,16 @@ theorem nhds_pure (x : α) : 𝓝 (pure x : Filter α) = 𝓟 {⊥, pure x} := b rw [← principal_singleton, nhds_principal, principal_singleton, Iic_pure] @[simp] -theorem nhds_iInf (f : ι → Filter α) : 𝓝 (⨅ i, f i) = ⨅ i, 𝓝 (f i) := by +protected theorem nhds_iInf (f : ι → Filter α) : 𝓝 (⨅ i, f i) = ⨅ i, 𝓝 (f i) := by simp only [nhds_eq] apply lift'_iInf_of_map_univ <;> simp @[simp] -theorem nhds_inf (l₁ l₂ : Filter α) : 𝓝 (l₁ ⊓ l₂) = 𝓝 l₁ ⊓ 𝓝 l₂ := by - simpa only [iInf_bool_eq] using nhds_iInf fun b => cond b l₁ l₂ +protected theorem nhds_inf (l₁ l₂ : Filter α) : 𝓝 (l₁ ⊓ l₂) = 𝓝 l₁ ⊓ 𝓝 l₂ := by + simpa only [iInf_bool_eq] using Filter.nhds_iInf fun b => cond b l₁ l₂ theorem monotone_nhds : Monotone (𝓝 : Filter α → Filter (Filter α)) := - Monotone.of_map_inf nhds_inf + Monotone.of_map_inf Filter.nhds_inf theorem sInter_nhds (l : Filter α) : ⋂₀ { s | s ∈ 𝓝 l } = Iic l := by simp_rw [nhds_eq, Function.comp_def, sInter_lift'_sets monotone_principal.Iic, Iic, @@ -164,7 +164,7 @@ instance : T0Space (Filter α) := (specializes_iff_le.1 h.symm.specializes)⟩ theorem nhds_atTop [Preorder α] : 𝓝 atTop = ⨅ x : α, 𝓟 (Iic (𝓟 (Ici x))) := by - simp only [atTop, nhds_iInf, nhds_principal] + simp only [atTop, Filter.nhds_iInf, nhds_principal] protected theorem tendsto_nhds_atTop_iff [Preorder β] {l : Filter α} {f : α → Filter β} : Tendsto f l (𝓝 atTop) ↔ ∀ y, ∀ᶠ a in l, Ici y ∈ f a := by From ed32f2fcb0ac168cbf9055fea0c35f83e8f7e0af Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Tue, 7 Jan 2025 20:33:04 +0000 Subject: [PATCH 064/681] chore(Noetherian/Artinian): generalize to Semiring (#20534) --- Mathlib/Algebra/Ring/Equiv.lean | 8 + Mathlib/LinearAlgebra/LinearIndependent.lean | 22 +- Mathlib/LinearAlgebra/Pi.lean | 6 +- Mathlib/RingTheory/Artinian/Module.lean | 322 +++++++++++-------- Mathlib/RingTheory/Artinian/Ring.lean | 2 +- Mathlib/RingTheory/Ideal/Maps.lean | 63 ++-- Mathlib/RingTheory/Ideal/Prod.lean | 17 +- Mathlib/RingTheory/Noetherian/Basic.lean | 95 +++--- Mathlib/RingTheory/Noetherian/Nilpotent.lean | 2 +- Mathlib/RingTheory/SimpleModule.lean | 12 +- 10 files changed, 303 insertions(+), 246 deletions(-) diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index f180f913b77df..f65b840107c50 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -530,6 +530,14 @@ theorem coe_prodCongr {R R' S S' : Type*} [NonUnitalNonAssocSemiring R] ⇑(RingEquiv.prodCongr f g) = Prod.map f g := rfl +/-- This is `Equiv.piOptionEquivProd` as a `RingEquiv`. -/ +@[simps!] +def piOptionEquivProd {ι : Type*} {R : Option ι → Type*} [Π i, NonUnitalNonAssocSemiring (R i)] : + (Π i, R i) ≃+* R none × (Π i, R (some i)) where + toEquiv := Equiv.piOptionEquivProd + map_add' _ _ := rfl + map_mul' _ _ := rfl + end NonUnitalSemiring section Semiring diff --git a/Mathlib/LinearAlgebra/LinearIndependent.lean b/Mathlib/LinearAlgebra/LinearIndependent.lean index 90ce06f81b213..81a9e0d48fe9e 100644 --- a/Mathlib/LinearAlgebra/LinearIndependent.lean +++ b/Mathlib/LinearAlgebra/LinearIndependent.lean @@ -801,6 +801,17 @@ theorem eq_of_linearIndependent_of_span_subtype [Nontrivial R] {s t : Set M} convert y.mem rw [← Subtype.mk.inj hy] +theorem le_of_span_le_span [Nontrivial R] {s t u : Set M} (hl : LinearIndependent R ((↑) : u → M)) + (hsu : s ⊆ u) (htu : t ⊆ u) (hst : span R s ≤ span R t) : s ⊆ t := by + have := + eq_of_linearIndependent_of_span_subtype (hl.mono (Set.union_subset hsu htu)) + Set.subset_union_right (Set.union_subset (Set.Subset.trans subset_span hst) subset_span) + rw [← this]; apply Set.subset_union_left + +theorem span_le_span_iff [Nontrivial R] {s t u : Set M} (hl : LinearIndependent R ((↑) : u → M)) + (hsu : s ⊆ u) (htu : t ⊆ u) : span R s ≤ span R t ↔ s ⊆ t := + ⟨le_of_span_le_span hl hsu htu, span_mono⟩ + end Semiring section Module @@ -1280,17 +1291,6 @@ lemma linearIndependent_algHom_toLinearMap' (K M L) [CommRing K] simp_rw [Algebra.smul_def, mul_one] exact NoZeroSMulDivisors.algebraMap_injective K L -theorem le_of_span_le_span [Nontrivial R] {s t u : Set M} (hl : LinearIndependent R ((↑) : u → M)) - (hsu : s ⊆ u) (htu : t ⊆ u) (hst : span R s ≤ span R t) : s ⊆ t := by - have := - eq_of_linearIndependent_of_span_subtype (hl.mono (Set.union_subset hsu htu)) - Set.subset_union_right (Set.union_subset (Set.Subset.trans subset_span hst) subset_span) - rw [← this]; apply Set.subset_union_left - -theorem span_le_span_iff [Nontrivial R] {s t u : Set M} (hl : LinearIndependent R ((↑) : u → M)) - (hsu : s ⊆ u) (htu : t ⊆ u) : span R s ≤ span R t ↔ s ⊆ t := - ⟨le_of_span_le_span hl hsu htu, span_mono⟩ - end Module section Nontrivial diff --git a/Mathlib/LinearAlgebra/Pi.lean b/Mathlib/LinearAlgebra/Pi.lean index 4c1ff2962f310..62bc97d66935b 100644 --- a/Mathlib/LinearAlgebra/Pi.lean +++ b/Mathlib/LinearAlgebra/Pi.lean @@ -217,8 +217,8 @@ theorem lsum_apply (S) [AddCommMonoid M] [Module R M] [Fintype ι] [Semiring S] lsum R φ S f = ∑ i : ι, (f i).comp (proj i) := rfl @[simp high] -theorem lsum_single {ι R : Type*} [Fintype ι] [DecidableEq ι] [CommRing R] {M : ι → Type*} - [(i : ι) → AddCommGroup (M i)] [(i : ι) → Module R (M i)] : +theorem lsum_single {ι R : Type*} [Fintype ι] [DecidableEq ι] [CommSemiring R] {M : ι → Type*} + [(i : ι) → AddCommMonoid (M i)] [(i : ι) → Module R (M i)] : LinearMap.lsum R M R (LinearMap.single R M) = LinearMap.id := LinearMap.ext fun x => by simp [Finset.univ_sum_single] @@ -458,7 +458,7 @@ def piCurry {ι : Type*} {κ : ι → Type*} (α : ∀ i, κ i → Type*) rfl /-- This is `Equiv.piOptionEquivProd` as a `LinearEquiv` -/ -def piOptionEquivProd {ι : Type*} {M : Option ι → Type*} [(i : Option ι) → AddCommGroup (M i)] +def piOptionEquivProd {ι : Type*} {M : Option ι → Type*} [(i : Option ι) → AddCommMonoid (M i)] [(i : Option ι) → Module R (M i)] : ((i : Option ι) → M i) ≃ₗ[R] M none × ((i : ι) → M (some i)) := { Equiv.piOptionEquivProd with diff --git a/Mathlib/RingTheory/Artinian/Module.lean b/Mathlib/RingTheory/Artinian/Module.lean index 61c8771b69611..fb67850d6a654 100644 --- a/Mathlib/RingTheory/Artinian/Module.lean +++ b/Mathlib/RingTheory/Artinian/Module.lean @@ -5,6 +5,7 @@ Authors: Chris Hughes -/ import Mathlib.Data.SetLike.Fintype import Mathlib.Order.Filter.EventuallyConst +import Mathlib.RingTheory.Ideal.Prod import Mathlib.RingTheory.Ideal.Quotient.Operations import Mathlib.RingTheory.Nilpotent.Lemmas import Mathlib.RingTheory.Noetherian.Defs @@ -59,10 +60,10 @@ theorem isArtinian_iff (R M) [Semiring R] [AddCommMonoid M] [Module R M] : IsArt WellFounded (· < · : Submodule R M → Submodule R M → Prop) := isWellFounded_iff _ _ -section +section Semiring variable {R M P N : Type*} -variable [Ring R] [AddCommGroup M] [AddCommGroup P] [AddCommGroup N] +variable [Semiring R] [AddCommMonoid M] [AddCommMonoid P] [AddCommMonoid N] variable [Module R M] [Module R P] [Module R N] theorem isArtinian_of_injective (f : M →ₗ[R] P) (h : Function.Injective f) [IsArtinian R P] : @@ -86,10 +87,6 @@ theorem isArtinian_of_surjective (f : M →ₗ[R] P) (hf : Function.Surjective f show A.comap f < B.comap f from Submodule.comap_strictMono_of_surjective hf hAB) (InvImage.wf (Submodule.comap f) IsWellFounded.wf)⟩ -instance isArtinian_of_quotient_of_artinian - (N : Submodule R M) [IsArtinian R M] : IsArtinian R (M ⧸ N) := - isArtinian_of_surjective M (Submodule.mkQ N) (Submodule.Quotient.mk_surjective N) - variable {M} instance isArtinian_range (f : M →ₗ[R] P) [IsArtinian R M] : IsArtinian R (LinearMap.range f) := @@ -101,74 +98,17 @@ theorem isArtinian_of_linearEquiv (f : M ≃ₗ[R] P) [IsArtinian R M] : IsArtin theorem LinearEquiv.isArtinian_iff (f : M ≃ₗ[R] P) : IsArtinian R M ↔ IsArtinian R P := ⟨fun _ ↦ isArtinian_of_linearEquiv f, fun _ ↦ isArtinian_of_linearEquiv f.symm⟩ -theorem isArtinian_of_range_eq_ker [IsArtinian R M] [IsArtinian R P] (f : M →ₗ[R] N) (g : N →ₗ[R] P) - (h : LinearMap.range f = LinearMap.ker g) : IsArtinian R N := - wellFounded_lt_exact_sequence (LinearMap.range f) (Submodule.map (f.ker.liftQ f le_rfl)) - (Submodule.comap (f.ker.liftQ f le_rfl)) - (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) - (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) - (Submodule.giMapComap g.surjective_rangeRestrict) - (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) - (by simp [Submodule.comap_map_eq, h]) - -theorem isArtinian_iff_submodule_quotient (S : Submodule R P) : - IsArtinian R P ↔ IsArtinian R S ∧ IsArtinian R (P ⧸ S) := by - refine ⟨fun h ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ - apply isArtinian_of_range_eq_ker S.subtype S.mkQ - rw [Submodule.ker_mkQ, Submodule.range_subtype] - -instance isArtinian_prod [IsArtinian R M] [IsArtinian R P] : IsArtinian R (M × P) := - isArtinian_of_range_eq_ker (LinearMap.inl R M P) (LinearMap.snd R M P) (LinearMap.range_inl R M P) - instance (priority := 100) isArtinian_of_finite [Finite M] : IsArtinian R M := ⟨Finite.wellFounded_of_trans_of_irrefl _⟩ -- Porting note: elab_as_elim can only be global and cannot be changed on an imported decl -- attribute [local elab_as_elim] Finite.induction_empty_option -instance isArtinian_sup (M₁ M₂ : Submodule R P) [IsArtinian R M₁] [IsArtinian R M₂] : - IsArtinian R ↥(M₁ ⊔ M₂) := by - have := isArtinian_range (M₁.subtype.coprod M₂.subtype) - rwa [LinearMap.range_coprod, Submodule.range_subtype, Submodule.range_subtype] at this - -variable {ι : Type*} [Finite ι] - -instance isArtinian_pi : - ∀ {M : ι → Type*} [∀ i, AddCommGroup (M i)] - [∀ i, Module R (M i)] [∀ i, IsArtinian R (M i)], IsArtinian R (∀ i, M i) := by - apply Finite.induction_empty_option _ _ _ ι - · exact fun e h ↦ isArtinian_of_linearEquiv (LinearEquiv.piCongrLeft R _ e) - · infer_instance - · exact fun ih ↦ isArtinian_of_linearEquiv (LinearEquiv.piOptionEquivProd R).symm - -/-- A version of `isArtinian_pi` for non-dependent functions. We need this instance because -sometimes Lean fails to apply the dependent version in non-dependent settings (e.g., it fails to -prove that `ι → ℝ` is finite dimensional over `ℝ`). -/ -instance isArtinian_pi' [IsArtinian R M] : IsArtinian R (ι → M) := - isArtinian_pi - ---Porting note (https://github.com/leanprover-community/mathlib4/issues/10754): new instance -instance isArtinian_finsupp [IsArtinian R M] : IsArtinian R (ι →₀ M) := - isArtinian_of_linearEquiv (Finsupp.linearEquivFunOnFinite _ _ _).symm - -instance isArtinian_iSup : - ∀ {M : ι → Submodule R P} [∀ i, IsArtinian R (M i)], IsArtinian R ↥(⨆ i, M i) := by - apply Finite.induction_empty_option _ _ _ ι - · intro _ _ e h _ _; rw [← e.iSup_comp]; apply h - · intros; rw [iSup_of_empty]; infer_instance - · intro _ _ ih _ _; rw [iSup_option]; infer_instance - -end - -open Submodule Function - -section Ring - -variable {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] +open Submodule theorem IsArtinian.finite_of_linearIndependent [Nontrivial R] [h : IsArtinian R M] {s : Set M} (hs : LinearIndependent R ((↑) : s → M)) : s.Finite := by - refine by_contradiction fun hf => (RelEmbedding.wellFounded_iff_no_descending_seq.1 h.wf).elim' ?_ + refine by_contradiction fun hf ↦ (RelEmbedding.wellFounded_iff_no_descending_seq.1 h.wf).elim' ?_ have f : ℕ ↪ s := Set.Infinite.natEmbedding s hf have : ∀ n, (↑) ∘ f '' { m | n ≤ m } ⊆ s := by rintro n x ⟨y, _, rfl⟩ @@ -179,10 +119,10 @@ theorem IsArtinian.finite_of_linearIndependent [Nontrivial R] [h : IsArtinian R rw [span_le_span_iff hs (this b) (this a), Set.image_subset_image_iff (Subtype.coe_injective.comp f.injective), Set.subset_def] simp only [Set.mem_setOf_eq] - exact ⟨fun hab x => le_trans hab, fun h => h _ le_rfl⟩ - exact ⟨⟨fun n => span R (Subtype.val ∘ f '' { m | n ≤ m }), fun x y => by + exact ⟨fun hab x ↦ hab.trans, (· _ le_rfl)⟩ + exact ⟨⟨fun n ↦ span R (Subtype.val ∘ f '' { m | n ≤ m }), fun x y ↦ by rw [le_antisymm_iff, ← this y x, ← this x y] - exact fun ⟨h₁, h₂⟩ => le_antisymm_iff.2 ⟨h₂, h₁⟩⟩, by + exact fun ⟨h₁, h₂⟩ ↦ le_antisymm_iff.2 ⟨h₂, h₁⟩⟩, by intro a b conv_rhs => rw [GT.gt, lt_iff_le_not_le, this, this, ← lt_iff_le_not_le] rfl⟩ @@ -219,12 +159,125 @@ theorem induction {P : Submodule R M → Prop} (hgt : ∀ I, (∀ J < I, P J) P I := WellFoundedLT.induction I hgt +open Function + +/-- Any injective endomorphism of an Artinian module is surjective. -/ +theorem surjective_of_injective_endomorphism (f : M →ₗ[R] M) (s : Injective f) : Surjective f := by + have h := ‹IsArtinian R M›; contrapose! h + rw [IsArtinian, WellFoundedLT, isWellFounded_iff] + refine (RelEmbedding.natGT (LinearMap.range <| f ^ ·) ?_).not_wellFounded_of_decreasing_seq + intro n + simp_rw [pow_succ, LinearMap.mul_eq_comp, LinearMap.range_comp, ← Submodule.map_top (f ^ n)] + refine Submodule.map_strictMono_of_injective (LinearMap.iterate_injective s n) (Ne.lt_top ?_) + rwa [Ne, LinearMap.range_eq_top] + +/-- Any injective endomorphism of an Artinian module is bijective. -/ +theorem bijective_of_injective_endomorphism (f : M →ₗ[R] M) (s : Injective f) : Bijective f := + ⟨s, surjective_of_injective_endomorphism f s⟩ + +/-- A sequence `f` of submodules of an artinian module, +with the supremum `f (n+1)` and the infimum of `f 0`, ..., `f n` being ⊤, +is eventually ⊤. -/ +theorem disjoint_partial_infs_eventually_top (f : ℕ → Submodule R M) + (h : ∀ n, Disjoint (partialSups (OrderDual.toDual ∘ f) n) (OrderDual.toDual (f (n + 1)))) : + ∃ n : ℕ, ∀ m, n ≤ m → f m = ⊤ := by + -- A little off-by-one cleanup first: + rsuffices ⟨n, w⟩ : ∃ n : ℕ, ∀ m, n ≤ m → OrderDual.toDual f (m + 1) = ⊤ + · use n + 1 + rintro (_ | m) p + · cases p + · apply w + exact Nat.succ_le_succ_iff.mp p + obtain ⟨n, w⟩ := monotone_stabilizes (partialSups (OrderDual.toDual ∘ f)) + refine ⟨n, fun m p => ?_⟩ + exact (h m).eq_bot_of_ge (sup_eq_left.1 <| (w (m + 1) <| le_add_right p).symm.trans <| w m p) + end IsArtinian namespace LinearMap variable [IsArtinian R M] +lemma eventually_iInf_range_pow_eq (f : Module.End R M) : + ∀ᶠ n in atTop, ⨅ m, LinearMap.range (f ^ m) = LinearMap.range (f ^ n) := by + obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.range (f ^ n) = LinearMap.range (f ^ m)⟩ := + IsArtinian.monotone_stabilizes f.iterateRange + refine eventually_atTop.mpr ⟨n, fun l hl ↦ le_antisymm (iInf_le _ _) (le_iInf fun m ↦ ?_)⟩ + rcases le_or_lt l m with h | h + · rw [← hn _ (hl.trans h), hn _ hl] + · exact f.iterateRange.monotone h.le + +end LinearMap + +end Semiring + +section Ring + +variable {R M P N : Type*} +variable [Ring R] [AddCommGroup M] [AddCommGroup P] [AddCommGroup N] +variable [Module R M] [Module R P] [Module R N] + +instance isArtinian_of_quotient_of_artinian + (N : Submodule R M) [IsArtinian R M] : IsArtinian R (M ⧸ N) := + isArtinian_of_surjective M (Submodule.mkQ N) (Submodule.Quotient.mk_surjective N) + +theorem isArtinian_of_range_eq_ker [IsArtinian R M] [IsArtinian R P] (f : M →ₗ[R] N) (g : N →ₗ[R] P) + (h : LinearMap.range f = LinearMap.ker g) : IsArtinian R N := + wellFounded_lt_exact_sequence (LinearMap.range f) (Submodule.map (f.ker.liftQ f le_rfl)) + (Submodule.comap (f.ker.liftQ f le_rfl)) + (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) + (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) + (Submodule.giMapComap g.surjective_rangeRestrict) + (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) + (by simp [Submodule.comap_map_eq, h]) + +theorem isArtinian_iff_submodule_quotient (S : Submodule R P) : + IsArtinian R P ↔ IsArtinian R S ∧ IsArtinian R (P ⧸ S) := by + refine ⟨fun h ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ + apply isArtinian_of_range_eq_ker S.subtype S.mkQ + rw [Submodule.ker_mkQ, Submodule.range_subtype] + +instance isArtinian_prod [IsArtinian R M] [IsArtinian R P] : IsArtinian R (M × P) := + isArtinian_of_range_eq_ker (LinearMap.inl R M P) (LinearMap.snd R M P) (LinearMap.range_inl R M P) + +instance isArtinian_sup (M₁ M₂ : Submodule R P) [IsArtinian R M₁] [IsArtinian R M₂] : + IsArtinian R ↥(M₁ ⊔ M₂) := by + have := isArtinian_range (M₁.subtype.coprod M₂.subtype) + rwa [LinearMap.range_coprod, Submodule.range_subtype, Submodule.range_subtype] at this + +variable {ι : Type*} [Finite ι] + +instance isArtinian_pi : + ∀ {M : ι → Type*} [Π i, AddCommGroup (M i)] + [Π i, Module R (M i)] [∀ i, IsArtinian R (M i)], IsArtinian R (Π i, M i) := by + apply Finite.induction_empty_option _ _ _ ι + · exact fun e h ↦ isArtinian_of_linearEquiv (LinearEquiv.piCongrLeft R _ e) + · infer_instance + · exact fun ih ↦ isArtinian_of_linearEquiv (LinearEquiv.piOptionEquivProd R).symm + +/-- A version of `isArtinian_pi` for non-dependent functions. We need this instance because +sometimes Lean fails to apply the dependent version in non-dependent settings (e.g., it fails to +prove that `ι → ℝ` is finite dimensional over `ℝ`). -/ +instance isArtinian_pi' [IsArtinian R M] : IsArtinian R (ι → M) := + isArtinian_pi + +--Porting note (https://github.com/leanprover-community/mathlib4/issues/10754): new instance +instance isArtinian_finsupp [IsArtinian R M] : IsArtinian R (ι →₀ M) := + isArtinian_of_linearEquiv (Finsupp.linearEquivFunOnFinite _ _ _).symm + +instance isArtinian_iSup : + ∀ {M : ι → Submodule R P} [∀ i, IsArtinian R (M i)], IsArtinian R ↥(⨆ i, M i) := by + apply Finite.induction_empty_option _ _ _ ι + · intro _ _ e h _ _; rw [← e.iSup_comp]; apply h + · intros; rw [iSup_of_empty]; infer_instance + · intro _ _ ih _ _; rw [iSup_option]; infer_instance + +open Submodule Function + +namespace LinearMap + +variable [IsArtinian R M] + /-- For any endomorphism of an Artinian module, any sufficiently high iterate has codisjoint kernel and range. -/ theorem eventually_codisjoint_ker_pow_range_pow (f : M →ₗ[R] M) : @@ -241,15 +294,6 @@ theorem eventually_codisjoint_ker_pow_range_pow (f : M →ₗ[R] M) : ← f.pow_apply m, ← mem_range (f := _), ← hn _ (n.le_add_left m), hn _ hm] exact LinearMap.mem_range_self (f ^ m) x -lemma eventually_iInf_range_pow_eq (f : Module.End R M) : - ∀ᶠ n in atTop, ⨅ m, LinearMap.range (f ^ m) = LinearMap.range (f ^ n) := by - obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.range (f ^ n) = LinearMap.range (f ^ m)⟩ := - IsArtinian.monotone_stabilizes f.iterateRange - refine eventually_atTop.mpr ⟨n, fun l hl ↦ le_antisymm (iInf_le _ _) (le_iInf fun m ↦ ?_)⟩ - rcases le_or_lt l m with h | h - · rw [← hn _ (hl.trans h), hn _ hl] - · exact f.iterateRange.monotone h.le - /-- This is the Fitting decomposition of the module `M` with respect to the endomorphism `f`. See also `LinearMap.isCompl_iSup_ker_pow_iInf_range_pow` for an alternative spelling. -/ @@ -271,46 +315,11 @@ theorem isCompl_iSup_ker_pow_iInf_range_pow [IsNoetherian R M] (f : M →ₗ[R] end LinearMap -namespace IsArtinian - -variable [IsArtinian R M] - -/-- Any injective endomorphism of an Artinian module is surjective. -/ -theorem surjective_of_injective_endomorphism (f : M →ₗ[R] M) (s : Injective f) : Surjective f := by - obtain ⟨n, hn⟩ := eventually_atTop.mp f.eventually_codisjoint_ker_pow_range_pow - specialize hn (n + 1) (n.le_add_right 1) - rw [codisjoint_iff, LinearMap.ker_eq_bot.mpr (LinearMap.iterate_injective s _), bot_sup_eq, - LinearMap.range_eq_top] at hn - exact LinearMap.surjective_of_iterate_surjective n.succ_ne_zero hn - -/-- Any injective endomorphism of an Artinian module is bijective. -/ -theorem bijective_of_injective_endomorphism (f : M →ₗ[R] M) (s : Injective f) : Bijective f := - ⟨s, surjective_of_injective_endomorphism f s⟩ - -/-- A sequence `f` of submodules of an artinian module, -with the supremum `f (n+1)` and the infimum of `f 0`, ..., `f n` being ⊤, -is eventually ⊤. -/ -theorem disjoint_partial_infs_eventually_top (f : ℕ → Submodule R M) - (h : ∀ n, Disjoint (partialSups (OrderDual.toDual ∘ f) n) (OrderDual.toDual (f (n + 1)))) : - ∃ n : ℕ, ∀ m, n ≤ m → f m = ⊤ := by - -- A little off-by-one cleanup first: - rsuffices ⟨n, w⟩ : ∃ n : ℕ, ∀ m, n ≤ m → OrderDual.toDual f (m + 1) = ⊤ - · use n + 1 - rintro (_ | m) p - · cases p - · apply w - exact Nat.succ_le_succ_iff.mp p - obtain ⟨n, w⟩ := monotone_stabilizes (partialSups (OrderDual.toDual ∘ f)) - refine ⟨n, fun m p => ?_⟩ - exact (h m).eq_bot_of_ge (sup_eq_left.1 <| (w (m + 1) <| le_add_right p).symm.trans <| w m p) - -end IsArtinian - end Ring -section CommRing +section CommSemiring -variable {R : Type*} (M : Type*) [CommRing R] [AddCommGroup M] [Module R M] [IsArtinian R M] +variable {R : Type*} (M : Type*) [CommSemiring R] [AddCommMonoid M] [Module R M] [IsArtinian R M] namespace IsArtinian @@ -334,13 +343,13 @@ theorem exists_pow_succ_smul_dvd (r : R) (x : M) : end IsArtinian -end CommRing +end CommSemiring -theorem isArtinian_of_submodule_of_artinian (R M) [Ring R] [AddCommGroup M] [Module R M] +theorem isArtinian_of_submodule_of_artinian (R M) [Semiring R] [AddCommMonoid M] [Module R M] (N : Submodule R M) (_ : IsArtinian R M) : IsArtinian R N := inferInstance /-- If `M / S / R` is a scalar tower, and `M / R` is Artinian, then `M / S` is also Artinian. -/ -theorem isArtinian_of_tower (R) {S M} [CommRing R] [Ring S] [AddCommGroup M] [Algebra R S] +theorem isArtinian_of_tower (R) {S M} [Semiring R] [Semiring S] [AddCommMonoid M] [SMul R S] [Module S M] [Module R M] [IsScalarTower R S M] (h : IsArtinian R M) : IsArtinian S M := ⟨(Submodule.restrictScalarsEmbedding R S M).wellFounded h.wf⟩ @@ -356,21 +365,26 @@ convenience in the commutative case. For a right Artinian ring, use `IsArtinian For equivalent definitions, see `Mathlib.RingTheory.Artinian.Ring`. -/ @[stacks 00J5] -abbrev IsArtinianRing (R) [Ring R] := +abbrev IsArtinianRing (R) [Semiring R] := IsArtinian R R -theorem isArtinianRing_iff {R} [Ring R] : IsArtinianRing R ↔ IsArtinian R R := Iff.rfl +theorem isArtinianRing_iff {R} [Semiring R] : IsArtinianRing R ↔ IsArtinian R R := Iff.rfl -instance DivisionRing.instIsArtinianRing {K : Type*} [DivisionRing K] : IsArtinianRing K := +instance DivisionSemiring.instIsArtinianRing {K : Type*} [DivisionSemiring K] : IsArtinianRing K := ⟨Finite.wellFounded_of_trans_of_irrefl _⟩ -theorem Ring.isArtinian_of_zero_eq_one {R} [Ring R] (h01 : (0 : R) = 1) : IsArtinianRing R := +instance DivisionRing.instIsArtinianRing {K : Type*} [DivisionRing K] : IsArtinianRing K := + inferInstance + +theorem Ring.isArtinian_of_zero_eq_one {R} [Semiring R] (h01 : (0 : R) = 1) : IsArtinianRing R := have := subsingleton_of_zero_eq_one h01 inferInstance instance (R) [CommRing R] [IsArtinianRing R] (I : Ideal R) : IsArtinianRing (R ⧸ I) := isArtinian_of_tower R inferInstance +open Submodule Function + theorem isArtinian_of_fg_of_artinian {R M} [Ring R] [AddCommGroup M] [Module R M] (N : Submodule R M) [IsArtinianRing R] (hN : N.FG) : IsArtinian R N := by let ⟨s, hs⟩ := hN @@ -403,18 +417,57 @@ theorem isArtinian_span_of_finite (R) {M} [Ring R] [AddCommGroup M] [Module R M] {A : Set M} (hA : A.Finite) : IsArtinian R (Submodule.span R A) := isArtinian_of_fg_of_artinian _ (Submodule.fg_def.mpr ⟨A, hA, rfl⟩) -theorem Function.Surjective.isArtinianRing {R} [Ring R] {S} [Ring S] {F} +theorem Function.Surjective.isArtinianRing {R} [Semiring R] {S} [Semiring S] {F} [FunLike F R S] [RingHomClass F R S] {f : F} (hf : Function.Surjective f) [H : IsArtinianRing R] : IsArtinianRing S := by rw [isArtinianRing_iff] at H ⊢ exact ⟨(Ideal.orderEmbeddingOfSurjective f hf).wellFounded H.wf⟩ +instance isArtinianRing_rangeS {R} [Semiring R] {S} [Semiring S] (f : R →+* S) [IsArtinianRing R] : + IsArtinianRing f.rangeS := + f.rangeSRestrict_surjective.isArtinianRing + instance isArtinianRing_range {R} [Ring R] {S} [Ring S] (f : R →+* S) [IsArtinianRing R] : IsArtinianRing f.range := - f.rangeRestrict_surjective.isArtinianRing + isArtinianRing_rangeS f + +theorem RingEquiv.isArtinianRing {R S} [Semiring R] [Semiring S] (f : R ≃+* S) + [IsArtinianRing R] : IsArtinianRing S := + f.surjective.isArtinianRing + +instance {R S} [Semiring R] [Semiring S] [IsArtinianRing R] [IsArtinianRing S] : + IsArtinianRing (R × S) := + Ideal.idealProdEquiv.toOrderEmbedding.wellFoundedLT + +instance {ι} [Finite ι] : ∀ {R : ι → Type*} [Π i, Semiring (R i)] [∀ i, IsArtinianRing (R i)], + IsArtinianRing (Π i, R i) := by + apply Finite.induction_empty_option _ _ _ ι + · exact fun e h ↦ RingEquiv.isArtinianRing (.piCongrLeft _ e) + · infer_instance + · exact fun ih ↦ RingEquiv.isArtinianRing (.symm .piOptionEquivProd) namespace IsArtinianRing +section CommSemiring + +variable (R : Type*) [CommSemiring R] [IsArtinianRing R] + +@[stacks 00J7] +lemma maximal_ideals_finite : {I : Ideal R | I.IsMaximal}.Finite := by + set Spec := {I : Ideal R | I.IsMaximal} + obtain ⟨_, ⟨s, rfl⟩, H⟩ := IsArtinian.set_has_minimal + (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩ + refine Set.finite_def.2 ⟨s, fun p ↦ ?_⟩ + classical + obtain ⟨q, hq1, hq2⟩ := p.2.isPrime.inf_le'.mp <| inf_eq_right.mp <| + inf_le_right.eq_of_not_lt (H (p ⊓ s.inf Subtype.val) ⟨insert p s, by simp⟩) + rwa [← Subtype.ext <| q.2.eq_of_le p.2.ne_top hq2] + +lemma subtype_isMaximal_finite : Finite {I : Ideal R | I.IsMaximal} := + (maximal_ideals_finite R).to_subtype + +end CommSemiring + variable {R : Type*} [CommRing R] [IsArtinianRing R] variable (R) in @@ -428,31 +481,20 @@ lemma isField_of_isDomain [IsDomain R] : IsField R := by rw [mul_eq_zero, sub_eq_zero] at hy exact ⟨_, hy.resolve_left <| pow_ne_zero _ hx⟩ +/- Does not hold in a commutative semiring: +consider {0, 0.5, 1} with ⊔ as + and ⊓ as *, then both {0} and {0, 0.5} are prime ideals. -/ instance isMaximal_of_isPrime (p : Ideal R) [p.IsPrime] : p.IsMaximal := Ideal.Quotient.maximal_of_isField _ (isField_of_isDomain _) lemma isPrime_iff_isMaximal (p : Ideal R) : p.IsPrime ↔ p.IsMaximal := ⟨fun _ ↦ isMaximal_of_isPrime p, fun h ↦ h.isPrime⟩ -variable (R) in -lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by - set Spec := {I : Ideal R | I.IsPrime} - obtain ⟨_, ⟨s, rfl⟩, H⟩ := IsArtinian.set_has_minimal - (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩ - refine Set.finite_def.2 ⟨s, fun p ↦ ?_⟩ - classical - obtain ⟨q, hq1, hq2⟩ := p.2.inf_le'.mp <| inf_eq_right.mp <| - inf_le_right.eq_of_not_lt (H (p ⊓ s.inf Subtype.val) ⟨insert p s, by simp⟩) - rwa [← Subtype.ext <| (@isMaximal_of_isPrime _ _ _ _ q.2).eq_of_le p.2.1 hq2] - variable (R) -@[stacks 00J7] -lemma maximal_ideals_finite : {I : Ideal R | I.IsMaximal}.Finite := by - simp_rw [← isPrime_iff_isMaximal] - apply primeSpectrum_finite R -@[local instance] lemma subtype_isMaximal_finite : Finite {I : Ideal R | I.IsMaximal} := - (maximal_ideals_finite R).to_subtype +lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by + simpa only [isPrime_iff_isMaximal] using maximal_ideals_finite R + +attribute [local instance] subtype_isMaximal_finite /-- A temporary field instance on the quotients by maximal ideals. -/ @[local instance] noncomputable def fieldOfSubtypeIsMaximal diff --git a/Mathlib/RingTheory/Artinian/Ring.lean b/Mathlib/RingTheory/Artinian/Ring.lean index 3c0e9a2fde380..a508c61431e11 100644 --- a/Mathlib/RingTheory/Artinian/Ring.lean +++ b/Mathlib/RingTheory/Artinian/Ring.lean @@ -85,7 +85,7 @@ theorem isNilpotent_jacobson_bot : IsNilpotent (Ideal.jacobson (⊥ : Ideal R)) section Localization -variable (S : Submonoid R) (L : Type*) [CommRing L] [Algebra R L] [IsLocalization S L] +variable (S : Submonoid R) (L : Type*) [CommSemiring L] [Algebra R L] [IsLocalization S L] include S /-- Localizing an artinian ring can only reduce the amount of elements. -/ diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index a0cca39024554..16fd9d345f686 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -334,6 +334,22 @@ theorem IsMaximal.comap_piEvalRingHom {ι : Type*} {R : ι → Type*} [∀ i, Se · simpa [eq_comm] using eq · simp [update_of_ne ne] +theorem comap_le_comap_iff_of_surjective (hf : Function.Surjective f) (I J : Ideal S) : + comap f I ≤ comap f J ↔ I ≤ J := + ⟨fun h => (map_comap_of_surjective f hf I).symm.le.trans (map_le_of_le_comap h), fun h => + le_comap_of_map_le ((map_comap_of_surjective f hf I).le.trans h)⟩ + +/-- The map on ideals induced by a surjective map preserves inclusion. -/ +def orderEmbeddingOfSurjective (hf : Function.Surjective f) : Ideal S ↪o Ideal R where + toFun := comap f + inj' _ _ eq := SetLike.ext' (Set.preimage_injective.mpr hf <| SetLike.ext'_iff.mp eq) + map_rel_iff' := comap_le_comap_iff_of_surjective _ hf .. + +theorem map_eq_top_or_isMaximal_of_surjective (hf : Function.Surjective f) {I : Ideal R} + (H : IsMaximal I) : map f I = ⊤ ∨ IsMaximal (map f I) := + or_iff_not_imp_left.2 fun ne_top ↦ ⟨⟨ne_top, fun _J hJ ↦ comap_injective_of_surjective f hf <| + H.1.2 _ (le_comap_map.trans_lt <| (orderEmbeddingOfSurjective f hf).strictMono hJ)⟩⟩ + end Surjective section Injective @@ -438,6 +454,11 @@ instance map_isMaximal_of_equiv {E : Type*} [EquivLike E R S] [RingEquivClass E {p : Ideal R} [hp : p.IsMaximal] : (map e p).IsMaximal := hp.map_bijective e (EquivLike.bijective e) +/-- The pullback of a maximal ideal under a ring isomorphism is a maximal ideal. -/ +instance comap_isMaximal_of_equiv {E : Type*} [EquivLike E R S] [RingEquivClass E R S] (e : E) + {p : Ideal S} [hp : p.IsMaximal] : (comap e p).IsMaximal := + hp.comap_bijective e (EquivLike.bijective e) + theorem isMaximal_iff_of_bijective : (⊥ : Ideal R).IsMaximal ↔ (⊥ : Ideal S).IsMaximal := ⟨fun h ↦ map_bot (f := f) ▸ h.map_bijective f hf, fun h ↦ have e := RingEquiv.ofBijective f hf map_bot (f := e.symm) ▸ h.map_bijective _ e.symm.bijective⟩ @@ -481,19 +502,7 @@ def relIsoOfSurjective (hf : Function.Surjective f) : ⟨fun H => map_comap_of_surjective f hf I1 ▸ map_comap_of_surjective f hf I2 ▸ map_mono H, comap_mono⟩ -/-- The map on ideals induced by a surjective map preserves inclusion. -/ -def orderEmbeddingOfSurjective (hf : Function.Surjective f) : Ideal S ↪o Ideal R := - (relIsoOfSurjective f hf).toRelEmbedding.trans (Subtype.relEmbedding (fun x y => x ≤ y) _) - -theorem map_eq_top_or_isMaximal_of_surjective (hf : Function.Surjective f) {I : Ideal R} - (H : IsMaximal I) : map f I = ⊤ ∨ IsMaximal (map f I) := by - refine or_iff_not_imp_left.2 fun ne_top => ⟨⟨fun h => ne_top h, fun J hJ => ?_⟩⟩ - · refine - (relIsoOfSurjective f hf).injective - (Subtype.ext_iff.2 (Eq.trans (H.1.2 (comap f J) (lt_of_le_of_ne ?_ ?_)) comap_top.symm)) - · exact map_le_iff_le_comap.1 (le_of_lt hJ) - · exact fun h => hJ.right (le_map_of_comap_le_of_surjective f hf (le_of_eq h.symm)) - +-- Does not hold if `R` is a semiring: consider `ℕ → ZMod 2`. theorem comap_isMaximal_of_surjective (hf : Function.Surjective f) {K : Ideal S} [H : IsMaximal K] : IsMaximal (comap f K) := by refine ⟨⟨comap_ne_top _ H.1.1, fun J hJ => ?_⟩⟩ @@ -509,16 +518,6 @@ theorem comap_isMaximal_of_surjective (hf : Function.Surjective f) {K : Ideal S} rw [comap_map_of_surjective _ hf, sup_eq_left] exact le_trans (comap_mono bot_le) (le_of_lt hJ) -/-- The pullback of a maximal ideal under a ring isomorphism is a maximal ideal. -/ -instance comap_isMaximal_of_equiv {E : Type*} [EquivLike E R S] [RingEquivClass E R S] (e : E) - {p : Ideal S} [p.IsMaximal] : (comap e p).IsMaximal := - comap_isMaximal_of_surjective e (EquivLike.surjective e) - -theorem comap_le_comap_iff_of_surjective (hf : Function.Surjective f) (I J : Ideal S) : - comap f I ≤ comap f J ↔ I ≤ J := - ⟨fun h => (map_comap_of_surjective f hf I).symm.le.trans (map_le_of_le_comap h), fun h => - le_comap_of_map_le ((map_comap_of_surjective f hf I).le.trans h)⟩ - end Surjective @@ -669,7 +668,7 @@ theorem ker_rangeRestrict (f : R →+* S) : ker f.rangeRestrict = ker f := end RingRing /-- The kernel of a homomorphism to a domain is a prime ideal. -/ -theorem ker_isPrime {F : Type*} [Ring R] [Ring S] [IsDomain S] +theorem ker_isPrime {F : Type*} [Semiring R] [Semiring S] [IsDomain S] [FunLike F R S] [RingHomClass F R S] (f : F) : (ker f).IsPrime := ⟨by @@ -679,7 +678,7 @@ theorem ker_isPrime {F : Type*} [Ring R] [Ring S] [IsDomain S] simpa only [mem_ker, map_mul] using @eq_zero_or_eq_zero_of_mul_eq_zero S _ _ _ _ _⟩ /-- The kernel of a homomorphism to a field is a maximal ideal. -/ -theorem ker_isMaximal_of_surjective {R K F : Type*} [Ring R] [Field K] +theorem ker_isMaximal_of_surjective {R K F : Type*} [Ring R] [DivisionRing K] [FunLike F R K] [RingHomClass F R K] (f : F) (hf : Function.Surjective f) : (ker f).IsMaximal := by refine @@ -836,6 +835,10 @@ instance map_isPrime_of_equiv {F' : Type*} [EquivLike F' R S] [RingEquivClass F' rw [h, map_comap_of_equiv (f : R ≃+* S)] exact Ideal.IsPrime.comap (RingEquiv.symm (f : R ≃+* S)) +theorem map_eq_bot_iff_of_injective {I : Ideal R} {f : F} (hf : Function.Injective f) : + I.map f = ⊥ ↔ I = ⊥ := by + simp [map, span_eq_bot, ← map_zero f, -map_zero, hf.eq_iff, I.eq_bot_iff] + end Semiring section Ring @@ -882,10 +885,6 @@ theorem map_isPrime_of_surjective {f : F} (hf : Function.Surjective f) {I : Idea exact (H.mem_or_mem this).imp (fun h => ha ▸ mem_map_of_mem f h) fun h => hb ▸ mem_map_of_mem f h -theorem map_eq_bot_iff_of_injective {I : Ideal R} {f : F} (hf : Function.Injective f) : - I.map f = ⊥ ↔ I = ⊥ := by - rw [map_eq_bot_iff_le_ker, (RingHom.injective_iff_ker_eq_bot f).mp hf, le_bot_iff] - end Ring section CommRing @@ -1036,9 +1035,9 @@ theorem of_ker_algebraMap_eq_bot (R A : Type*) [CommRing R] [Semiring A] [Algebr [NoZeroDivisors A] (h : RingHom.ker (algebraMap R A) = ⊥) : NoZeroSMulDivisors R A := of_algebraMap_injective ((RingHom.injective_iff_ker_eq_bot _).mpr h) -theorem ker_algebraMap_eq_bot (R A : Type*) [CommRing R] [Ring A] [Nontrivial A] [Algebra R A] - [NoZeroSMulDivisors R A] : RingHom.ker (algebraMap R A) = ⊥ := - (RingHom.injective_iff_ker_eq_bot _).mp (algebraMap_injective R A) +theorem ker_algebraMap_eq_bot (R A : Type*) [CommSemiring R] [Semiring A] [Nontrivial A] + [Algebra R A] [NoZeroSMulDivisors R A] : RingHom.ker (algebraMap R A) = ⊥ := by + ext; simp [Algebra.algebraMap_eq_smul_one'] theorem iff_ker_algebraMap_eq_bot {R A : Type*} [CommRing R] [Ring A] [IsDomain A] [Algebra R A] : NoZeroSMulDivisors R A ↔ RingHom.ker (algebraMap R A) = ⊥ := diff --git a/Mathlib/RingTheory/Ideal/Prod.lean b/Mathlib/RingTheory/Ideal/Prod.lean index 0e2afa702d110..44e48d9060023 100644 --- a/Mathlib/RingTheory/Ideal/Prod.lean +++ b/Mathlib/RingTheory/Ideal/Prod.lean @@ -22,15 +22,7 @@ variable {R : Type u} {S : Type v} [Semiring R] [Semiring S] (I : Ideal R) (J : namespace Ideal /-- `I × J` as an ideal of `R × S`. -/ -def prod : Ideal (R × S) where - carrier := { x | x.fst ∈ I ∧ x.snd ∈ J } - zero_mem' := by simp - add_mem' := by - rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨ha₁, ha₂⟩ ⟨hb₁, hb₂⟩ - exact ⟨I.add_mem ha₁ hb₁, J.add_mem ha₂ hb₂⟩ - smul_mem' := by - rintro ⟨a₁, a₂⟩ ⟨b₁, b₂⟩ ⟨hb₁, hb₂⟩ - exact ⟨I.mul_mem_left _ hb₁, J.mul_mem_left _ hb₂⟩ +def prod : Ideal (R × S) := I.comap (RingHom.fst R S) ⊓ J.comap (RingHom.snd R S) @[simp] theorem mem_prod {r : R} {s : S} : (⟨r, s⟩ : R × S) ∈ prod I J ↔ r ∈ I ∧ s ∈ J := @@ -78,11 +70,16 @@ theorem map_prodComm_prod : /-- Ideals of `R × S` are in one-to-one correspondence with pairs of ideals of `R` and ideals of `S`. -/ -def idealProdEquiv : Ideal (R × S) ≃ Ideal R × Ideal S where +def idealProdEquiv : Ideal (R × S) ≃o Ideal R × Ideal S where toFun I := ⟨map (RingHom.fst R S) I, map (RingHom.snd R S) I⟩ invFun I := prod I.1 I.2 left_inv I := (ideal_prod_eq I).symm right_inv := fun ⟨I, J⟩ => by simp + map_rel_iff' {I J} := by + simp only [Equiv.coe_fn_mk, ge_iff_le, Prod.mk_le_mk] + refine ⟨fun h ↦ ?_, fun h ↦ ⟨map_mono h, map_mono h⟩⟩ + rw [ideal_prod_eq I, ideal_prod_eq J] + exact inf_le_inf (comap_mono h.1) (comap_mono h.2) @[simp] theorem idealProdEquiv_symm_apply (I : Ideal R) (J : Ideal S) : diff --git a/Mathlib/RingTheory/Noetherian/Basic.lean b/Mathlib/RingTheory/Noetherian/Basic.lean index 38156a143989d..6ddbaf53f56f5 100644 --- a/Mathlib/RingTheory/Noetherian/Basic.lean +++ b/Mathlib/RingTheory/Noetherian/Basic.lean @@ -7,7 +7,7 @@ import Mathlib.LinearAlgebra.Quotient.Basic import Mathlib.RingTheory.Noetherian.Defs import Mathlib.RingTheory.Finiteness.Cardinality import Mathlib.RingTheory.Finiteness.Finsupp -import Mathlib.RingTheory.Ideal.Maps +import Mathlib.RingTheory.Ideal.Prod /-! # Noetherian rings and modules @@ -56,7 +56,7 @@ open Set Pointwise section -variable {R : Type*} {M : Type*} {P : Type*} +variable {R M P : Type*} variable [Semiring R] [AddCommMonoid M] [AddCommMonoid P] variable [Module R M] [Module R P] @@ -133,9 +133,9 @@ end Module section -variable {R : Type*} {M : Type*} {P : Type*} -variable [Ring R] [AddCommGroup M] [AddCommGroup P] -variable [Module R M] [Module R P] +variable {R M N P : Type*} +variable [Ring R] [AddCommGroup M] [AddCommGroup N] [AddCommGroup P] +variable [Module R M] [Module R N] [Module R P] open IsNoetherian @@ -148,6 +148,7 @@ theorem fg_of_ker_bot [IsNoetherian R P] {N : Submodule R M} (f : M →ₗ[R] P) haveI := isNoetherian_of_ker_bot f hf IsNoetherian.noetherian N +-- False over a semiring: ℕ is a Noetherian ℕ-module but ℕ × ℕ is not. instance isNoetherian_prod [IsNoetherian R M] [IsNoetherian R P] : IsNoetherian R (M × P) := ⟨fun s => Submodule.fg_of_fg_map_of_fg_inf_ker (LinearMap.snd R M P) (noetherian _) <| @@ -164,7 +165,7 @@ variable {ι : Type*} [Finite ι] instance isNoetherian_pi : ∀ {M : ι → Type*} [∀ i, AddCommGroup (M i)] - [∀ i, Module R (M i)] [∀ i, IsNoetherian R (M i)], IsNoetherian R (∀ i, M i) := by + [∀ i, Module R (M i)] [∀ i, IsNoetherian R (M i)], IsNoetherian R (Π i, M i) := by apply Finite.induction_empty_option _ _ _ ι · exact fun e h ↦ isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R _ e) · infer_instance @@ -183,6 +184,28 @@ instance isNoetherian_iSup : · intros; rw [iSup_of_empty]; infer_instance · intro _ _ ih _ _; rw [iSup_option]; infer_instance +/-- If the first and final modules in an exact sequence are Noetherian, + then the middle module is also Noetherian. -/ +theorem isNoetherian_of_range_eq_ker [IsNoetherian R M] [IsNoetherian R P] + (f : M →ₗ[R] N) (g : N →ₗ[R] P) (h : LinearMap.range f = LinearMap.ker g) : + IsNoetherian R N := + isNoetherian_mk <| + wellFounded_gt_exact_sequence + (LinearMap.range f) + (Submodule.map (f.ker.liftQ f le_rfl)) + (Submodule.comap (f.ker.liftQ f le_rfl)) + (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) + (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) + (Submodule.giMapComap g.surjective_rangeRestrict) + (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) + (by simp [Submodule.comap_map_eq, h]) + +theorem isNoetherian_iff_submodule_quotient (S : Submodule R P) : + IsNoetherian R P ↔ IsNoetherian R S ∧ IsNoetherian R (P ⧸ S) := by + refine ⟨fun _ ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ + apply isNoetherian_of_range_eq_ker S.subtype S.mkQ + rw [Submodule.ker_mkQ, Submodule.range_subtype] + end section CommRing @@ -204,10 +227,7 @@ open IsNoetherian Submodule Function section -universe w - -variable {R M P : Type*} {N : Type w} [Semiring R] [AddCommMonoid M] [Module R M] [AddCommMonoid N] - [Module R N] [AddCommMonoid P] [Module R P] +variable {R M : Type*} [Semiring R] [AddCommMonoid M] [Module R M] /-- If `∀ I > J, P I` implies `P J`, then `P` holds for all submodules. -/ theorem IsNoetherian.induction [IsNoetherian R M] {P : Submodule R M → Prop} @@ -218,10 +238,7 @@ end section -universe w - -variable {R M P : Type*} {N : Type w} [Ring R] [AddCommGroup M] [Module R M] [AddCommGroup N] - [Module R N] [AddCommGroup P] [Module R P] [IsNoetherian R M] +variable {R M N P : Type*} [Semiring R] [AddCommMonoid M] [Module R M] [IsNoetherian R M] lemma Submodule.finite_ne_bot_of_iSupIndep {ι : Type*} {N : ι → Submodule R M} (h : iSupIndep N) : @@ -246,28 +263,6 @@ theorem LinearIndependent.set_finite_of_isNoetherian [Nontrivial R] {s : Set M} (hi : LinearIndependent R ((↑) : s → M)) : s.Finite := @Set.toFinite _ _ hi.finite_of_isNoetherian -/-- If the first and final modules in an exact sequence are Noetherian, - then the middle module is also Noetherian. -/ -theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] - (f : M →ₗ[R] N) (g : N →ₗ[R] P) (h : LinearMap.range f = LinearMap.ker g) : - IsNoetherian R N := - isNoetherian_mk <| - wellFounded_gt_exact_sequence - (LinearMap.range f) - (Submodule.map (f.ker.liftQ f le_rfl)) - (Submodule.comap (f.ker.liftQ f le_rfl)) - (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) - (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) - (Submodule.giMapComap g.surjective_rangeRestrict) - (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) - (by simp [Submodule.comap_map_eq, h]) - -theorem isNoetherian_iff_submodule_quotient (S : Submodule R P) : - IsNoetherian R P ↔ IsNoetherian R S ∧ IsNoetherian R (P ⧸ S) := by - refine ⟨fun _ ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ - apply isNoetherian_of_range_eq_ker S.subtype S.mkQ - rw [Submodule.ker_mkQ, Submodule.range_subtype] - /-- A sequence `f` of submodules of a noetherian module, with `f (n+1)` disjoint from the supremum of `f 0`, ..., `f n`, is eventually zero. -/ @@ -353,14 +348,30 @@ theorem isNoetherian_span_of_finite (R) {M} [Ring R] [AddCommGroup M] [Module R [IsNoetherianRing R] {A : Set M} (hA : A.Finite) : IsNoetherian R (Submodule.span R A) := isNoetherian_of_fg_of_noetherian _ (Submodule.fg_def.mpr ⟨A, hA, rfl⟩) -theorem isNoetherianRing_of_surjective (R) [Ring R] (S) [Ring S] (f : R →+* S) +theorem isNoetherianRing_of_surjective (R) [Semiring R] (S) [Semiring S] (f : R →+* S) (hf : Function.Surjective f) [H : IsNoetherianRing R] : IsNoetherianRing S := isNoetherian_mk ⟨OrderEmbedding.wellFounded (Ideal.orderEmbeddingOfSurjective f hf).dual H.wf⟩ -instance isNoetherianRing_range {R} [Ring R] {S} [Ring S] (f : R →+* S) [IsNoetherianRing R] : - IsNoetherianRing f.range := - isNoetherianRing_of_surjective R f.range f.rangeRestrict f.rangeRestrict_surjective +instance isNoetherianRing_rangeS {R} [Semiring R] {S} [Semiring S] (f : R →+* S) + [IsNoetherianRing R] : IsNoetherianRing f.rangeS := + isNoetherianRing_of_surjective R f.rangeS f.rangeSRestrict f.rangeSRestrict_surjective + +instance isNoetherianRing_range {R} [Ring R] {S} [Ring S] (f : R →+* S) + [IsNoetherianRing R] : IsNoetherianRing f.range := + isNoetherianRing_rangeS f -theorem isNoetherianRing_of_ringEquiv (R) [Ring R] {S} [Ring S] (f : R ≃+* S) [IsNoetherianRing R] : - IsNoetherianRing S := +theorem isNoetherianRing_of_ringEquiv (R) [Semiring R] {S} [Semiring S] (f : R ≃+* S) + [IsNoetherianRing R] : IsNoetherianRing S := isNoetherianRing_of_surjective R S f.toRingHom f.toEquiv.surjective + +instance {R S} [Semiring R] [Semiring S] [IsNoetherianRing R] [IsNoetherianRing S] : + IsNoetherianRing (R × S) := by + rw [IsNoetherianRing, isNoetherian_iff'] at * + exact Ideal.idealProdEquiv.toOrderEmbedding.wellFoundedGT + +instance {ι} [Finite ι] : ∀ {R : ι → Type*} [Π i, Semiring (R i)] [∀ i, IsNoetherianRing (R i)], + IsNoetherianRing (Π i, R i) := by + apply Finite.induction_empty_option _ _ _ ι + · exact fun e h ↦ isNoetherianRing_of_ringEquiv _ (.piCongrLeft _ e) + · infer_instance + · exact fun ih ↦ isNoetherianRing_of_ringEquiv _ (.symm .piOptionEquivProd) diff --git a/Mathlib/RingTheory/Noetherian/Nilpotent.lean b/Mathlib/RingTheory/Noetherian/Nilpotent.lean index da206c8a9170d..251104d3dbd8b 100644 --- a/Mathlib/RingTheory/Noetherian/Nilpotent.lean +++ b/Mathlib/RingTheory/Noetherian/Nilpotent.lean @@ -18,7 +18,7 @@ import Mathlib.RingTheory.Noetherian.Defs open IsNoetherian -theorem IsNoetherianRing.isNilpotent_nilradical (R : Type*) [CommRing R] [IsNoetherianRing R] : +theorem IsNoetherianRing.isNilpotent_nilradical (R : Type*) [CommSemiring R] [IsNoetherianRing R] : IsNilpotent (nilradical R) := by obtain ⟨n, hn⟩ := Ideal.exists_radical_pow_le_of_fg (⊥ : Ideal R) (IsNoetherian.noetherian _) exact ⟨n, eq_bot_iff.mpr hn⟩ diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index ccf7c4055b535..1561b18e289da 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -303,12 +303,12 @@ instance IsSemisimpleRing.isCoatomic_submodule [IsSemisimpleRing R] : IsCoatomic open LinearMap in /-- A finite product of semisimple rings is semisimple. -/ -instance {ι} [Finite ι] (R : ι → Type*) [∀ i, Ring (R i)] [∀ i, IsSemisimpleRing (R i)] : - IsSemisimpleRing (∀ i, R i) := by - letI (i) : Module (∀ i, R i) (R i) := Module.compHom _ (Pi.evalRingHom R i) +instance {ι} [Finite ι] (R : ι → Type*) [Π i, Ring (R i)] [∀ i, IsSemisimpleRing (R i)] : + IsSemisimpleRing (Π i, R i) := by + letI (i) : Module (Π i, R i) (R i) := Module.compHom _ (Pi.evalRingHom R i) let e (i) : R i →ₛₗ[Pi.evalRingHom R i] R i := { AddMonoidHom.id (R i) with map_smul' := fun _ _ ↦ rfl } - have (i) : IsSemisimpleModule (∀ i, R i) (R i) := + have (i) : IsSemisimpleModule (Π i, R i) (R i) := ((e i).isSemisimpleModule_iff_of_bijective Function.bijective_id).mpr inferInstance classical exact isSemisimpleModule_of_isSemisimpleModule_submodule' (p := (range <| single _ _ ·)) @@ -359,8 +359,8 @@ universe u in /-- The existence part of the Artin–Wedderburn theorem. -/ proof_wanted isSemisimpleRing_iff_pi_matrix_divisionRing {R : Type u} [Ring R] : IsSemisimpleRing R ↔ - ∃ (n : ℕ) (S : Fin n → Type u) (d : Fin n → ℕ) (_ : ∀ i, DivisionRing (S i)), - Nonempty (R ≃+* ∀ i, Matrix (Fin (d i)) (Fin (d i)) (S i)) + ∃ (n : ℕ) (S : Fin n → Type u) (d : Fin n → ℕ) (_ : Π i, DivisionRing (S i)), + Nonempty (R ≃+* Π i, Matrix (Fin (d i)) (Fin (d i)) (S i)) variable {ι R} From b99ac0e050e868921ae5b026cadf95d1197dc2ca Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Tue, 7 Jan 2025 20:33:06 +0000 Subject: [PATCH 065/681] feat(NumberTheory/NumberField/Embeddings): definition of totally real field (#20542) --- .../NumberTheory/NumberField/Embeddings.lean | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Mathlib/NumberTheory/NumberField/Embeddings.lean b/Mathlib/NumberTheory/NumberField/Embeddings.lean index 1d5de4b41ece5..c057b1aa09be8 100644 --- a/Mathlib/NumberTheory/NumberField/Embeddings.lean +++ b/Mathlib/NumberTheory/NumberField/Embeddings.lean @@ -1096,4 +1096,28 @@ lemma infinitePlace_apply (v : InfinitePlace ℚ) (x : ℚ) : v x = |x| := by instance : Subsingleton (InfinitePlace ℚ) where allEq a b := by ext; simp +lemma isReal_infinitePlace : InfinitePlace.IsReal (infinitePlace) := + ⟨Rat.castHom ℂ, by ext; simp, rfl⟩ + end Rat + +/- + +## Totally real number fields + +-/ + +namespace NumberField + +/-- A number field `K` is totally real if all of its infinite places +are real. In other words, the image of every ring homomorphism `K → ℂ` +is a subset of `ℝ`. -/ +class IsTotallyReal (K : Type*) [Field K] [NumberField K] where + isReal : ∀ v : InfinitePlace K, v.IsReal + +instance : IsTotallyReal ℚ where + isReal v := by + rw [Subsingleton.elim v Rat.infinitePlace] + exact Rat.isReal_infinitePlace + +end NumberField From 97a203a2955ca17d5a7579fe729124dff70fe5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 7 Jan 2025 20:33:07 +0000 Subject: [PATCH 066/681] chore: move results about `DivisionMonoid` + `HasDistribNeg` (#20551) This way, we don't have to import fields to use those lemmas --- Mathlib/Algebra/Field/Basic.lean | 41 ------------------------------- Mathlib/Algebra/Module/Basic.lean | 3 ++- Mathlib/Algebra/Ring/Basic.lean | 40 ++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/Mathlib/Algebra/Field/Basic.lean b/Mathlib/Algebra/Field/Basic.lean index b022d2062981b..e98a7a85d09fc 100644 --- a/Mathlib/Algebra/Field/Basic.lean +++ b/Mathlib/Algebra/Field/Basic.lean @@ -73,47 +73,6 @@ protected theorem Commute.inv_add_inv (hab : Commute a b) (ha : a ≠ 0) (hb : b end DivisionSemiring -section DivisionMonoid - -variable [DivisionMonoid K] [HasDistribNeg K] {a b : K} - -theorem one_div_neg_one_eq_neg_one : (1 : K) / -1 = -1 := - have : -1 * -1 = (1 : K) := by rw [neg_mul_neg, one_mul] - Eq.symm (eq_one_div_of_mul_eq_one_right this) - -theorem one_div_neg_eq_neg_one_div (a : K) : 1 / -a = -(1 / a) := - calc - 1 / -a = 1 / (-1 * a) := by rw [neg_eq_neg_one_mul] - _ = 1 / a * (1 / -1) := by rw [one_div_mul_one_div_rev] - _ = 1 / a * -1 := by rw [one_div_neg_one_eq_neg_one] - _ = -(1 / a) := by rw [mul_neg, mul_one] - -theorem div_neg_eq_neg_div (a b : K) : b / -a = -(b / a) := - calc - b / -a = b * (1 / -a) := by rw [← inv_eq_one_div, division_def] - _ = b * -(1 / a) := by rw [one_div_neg_eq_neg_one_div] - _ = -(b * (1 / a)) := by rw [neg_mul_eq_mul_neg] - _ = -(b / a) := by rw [mul_one_div] - -theorem neg_div (a b : K) : -b / a = -(b / a) := by - rw [neg_eq_neg_one_mul, mul_div_assoc, ← neg_eq_neg_one_mul] - -@[field_simps] -theorem neg_div' (a b : K) : -(b / a) = -b / a := by simp [neg_div] - -@[simp] -theorem neg_div_neg_eq (a b : K) : -a / -b = a / b := by rw [div_neg_eq_neg_div, neg_div, neg_neg] - -theorem neg_inv : -a⁻¹ = (-a)⁻¹ := by rw [inv_eq_one_div, inv_eq_one_div, div_neg_eq_neg_div] - -theorem div_neg (a : K) : a / -b = -(a / b) := by rw [← div_neg_eq_neg_div] - -theorem inv_neg : (-a)⁻¹ = -a⁻¹ := by rw [neg_inv] - -theorem inv_neg_one : (-1 : K)⁻¹ = -1 := by rw [← neg_inv, inv_one] - -end DivisionMonoid - section DivisionRing variable [DivisionRing K] {a b c d : K} diff --git a/Mathlib/Algebra/Module/Basic.lean b/Mathlib/Algebra/Module/Basic.lean index b653c02aa9f6c..7ba518660f634 100644 --- a/Mathlib/Algebra/Module/Basic.lean +++ b/Mathlib/Algebra/Module/Basic.lean @@ -3,12 +3,13 @@ Copyright (c) 2015 Nathaniel Thomas. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro -/ -import Mathlib.Algebra.Field.Basic +import Mathlib.Algebra.Field.Defs import Mathlib.Algebra.Group.Action.Pi import Mathlib.Algebra.Group.Indicator import Mathlib.Algebra.GroupWithZero.Action.Units import Mathlib.Algebra.Module.NatInt import Mathlib.Algebra.NoZeroSMulDivisors.Defs +import Mathlib.Algebra.Ring.Invertible /-! # Further basic results about modules. diff --git a/Mathlib/Algebra/Ring/Basic.lean b/Mathlib/Algebra/Ring/Basic.lean index 1682f8c413b9e..61ec82eae38d6 100644 --- a/Mathlib/Algebra/Ring/Basic.lean +++ b/Mathlib/Algebra/Ring/Basic.lean @@ -183,3 +183,43 @@ lemma noZeroDivisors_iff_isDomain_or_subsingleton [Ring α] : rw [← isCancelMulZero_iff_noZeroDivisors, isCancelMulZero_iff_isDomain_or_subsingleton] end NoZeroDivisors + +section DivisionMonoid +variable [DivisionMonoid R] [HasDistribNeg R] {a b : R} + +lemma one_div_neg_one_eq_neg_one : (1 : R) / -1 = -1 := + have : -1 * -1 = (1 : R) := by rw [neg_mul_neg, one_mul] + Eq.symm (eq_one_div_of_mul_eq_one_right this) + +lemma one_div_neg_eq_neg_one_div (a : R) : 1 / -a = -(1 / a) := + calc + 1 / -a = 1 / (-1 * a) := by rw [neg_eq_neg_one_mul] + _ = 1 / a * (1 / -1) := by rw [one_div_mul_one_div_rev] + _ = 1 / a * -1 := by rw [one_div_neg_one_eq_neg_one] + _ = -(1 / a) := by rw [mul_neg, mul_one] + +lemma div_neg_eq_neg_div (a b : R) : b / -a = -(b / a) := + calc + b / -a = b * (1 / -a) := by rw [← inv_eq_one_div, division_def] + _ = b * -(1 / a) := by rw [one_div_neg_eq_neg_one_div] + _ = -(b * (1 / a)) := by rw [neg_mul_eq_mul_neg] + _ = -(b / a) := by rw [mul_one_div] + +lemma neg_div (a b : R) : -b / a = -(b / a) := by + rw [neg_eq_neg_one_mul, mul_div_assoc, ← neg_eq_neg_one_mul] + +@[field_simps] +lemma neg_div' (a b : R) : -(b / a) = -b / a := by simp [neg_div] + +@[simp] +lemma neg_div_neg_eq (a b : R) : -a / -b = a / b := by rw [div_neg_eq_neg_div, neg_div, neg_neg] + +lemma neg_inv : -a⁻¹ = (-a)⁻¹ := by rw [inv_eq_one_div, inv_eq_one_div, div_neg_eq_neg_div] + +lemma div_neg (a : R) : a / -b = -(a / b) := by rw [← div_neg_eq_neg_div] + +lemma inv_neg : (-a)⁻¹ = -a⁻¹ := by rw [neg_inv] + +lemma inv_neg_one : (-1 : R)⁻¹ = -1 := by rw [← neg_inv, inv_one] + +end DivisionMonoid From 0e673d61c819d5d7d4d25aac34f746a2e3928db4 Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 7 Jan 2025 21:11:20 +0000 Subject: [PATCH 067/681] fix(scripts/bench_summary): input jobID as a Nat, rather than a String (#20539) Hopefully, this fixes the bench_summary bot. You can see the error that the bot reports [here](https://github.com/leanprover-community/mathlib4/actions/runs/12648073160/job/35241690249), specifically it says ```lean :248:81: error: failed to synthesize OfNat String 12648073160 numerals are polymorphic in Lean, but the numeral `12648073160` cannot be used in a context where the expected type is String due to the absence of the instance above Additional diagnostic information may be available using the `set_option diagnostics true` command. ``` The issue is that the (lean) script takes the jobID as a `String`, since it wants to print the jobID url. However, due to quotation handling, the script receives a numeric literal, since the double quotes get lost in translation. If instead we ask Lean to do the conversion of a natural number to a string internally, everything should work. --- scripts/bench_summary.lean | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/bench_summary.lean b/scripts/bench_summary.lean index 9491ddef2ee99..12d9ec7fe769b 100644 --- a/scripts/bench_summary.lean +++ b/scripts/bench_summary.lean @@ -147,7 +147,9 @@ open Lean Elab Command in as a comment to a pull request. It takes as input * the number `PR` and the name `repo` as a `String` containing the relevant pull-request (it reads and posts comments there) -* the optional `jobID` string for reporting the action that produced the output +* the optional `jobID` numeral for reporting the action that produced the output + (`jobID` is a natural number, even though it gets converted to a `String` -- this is mostly + due to the fact that it is easier to get CI to pass a number, than a string with quotations) * the `String` `tempFile` of a temporary file where the command stores transient information. The code itself interfaces with the shell to retrieve and process json data and eventually @@ -163,7 +165,7 @@ Here is a summary of the steps: * process the final string to produce a summary (using `benchOutput`), * finally post the resulting output to the PR (using `gh pr comment ...`). -/ -def addBenchSummaryComment (PR : Nat) (repo : String) (jobID : String := "") +def addBenchSummaryComment (PR : Nat) (repo : String) (jobID : Nat := 0) (author : String := "leanprover-bot") (tempFile : String := "benchOutput.json") : CommandElabM Unit := do let job_msg := s!"\n[CI run](https://github.com/{repo}/actions/runs/{jobID})" From 0fdf47b574ac0725176467516746fe05337275b0 Mon Sep 17 00:00:00 2001 From: Michael Stoll Date: Tue, 7 Jan 2025 21:11:21 +0000 Subject: [PATCH 068/681] chore: deprecate MulRingNorm._ in favour of AbsoluteValue._ (#20557) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After refactoring the only customer of a number of declarations on `MulRingNorm`s to `AbsoluteValue` instead, this now deprecates these declarations (some of which do not adhere to the naming conventions anyway). It also adds text to the module docstring of `Mathlib.Analysis.Normed.Ring.Seminorm` and of `MulRingNorm` recommending to use `AbsoluteValue` instead. (Hence the `documentation` label. There is no label for deprecating/renaming things...) We add the equivalence `MulRingNorm R ≃ AbsoluteValue R ℝ` and `NormedField.toAbsoluteValue` to match `NormedField.toMulRingNorm`. Finally, it renames `AbsoluteValue.Equiv` to `AbsoluteValue.IsEquiv` (it is `Prop`-valued) etc. (Without deprecating the old names: they have been around for less than a week and are not used anywher by name; instead, Setoid notation is used downstream.) See [here](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/MulRingNorm.20vs.2E.20AbsoluteValue/near/491324423) on Zulip. --- .../Order/AbsoluteValue/Equivalence.lean | 32 +++++----- Mathlib/Analysis/Normed/Ring/Seminorm.lean | 58 ++++++++++++++++++- 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/Mathlib/Algebra/Order/AbsoluteValue/Equivalence.lean b/Mathlib/Algebra/Order/AbsoluteValue/Equivalence.lean index bd4fa328898cc..f63cfd022b9c4 100644 --- a/Mathlib/Algebra/Order/AbsoluteValue/Equivalence.lean +++ b/Mathlib/Algebra/Order/AbsoluteValue/Equivalence.lean @@ -18,45 +18,45 @@ variable {R : Type*} [Semiring R] /-- Two absolute values `f, g` on `R` with values in `ℝ` are *equivalent* if there exists a positive real constant `c` such that for all `x : R`, `(f x)^c = g x`. -/ -def Equiv (f g : AbsoluteValue R ℝ) : Prop := +def IsEquiv (f g : AbsoluteValue R ℝ) : Prop := ∃ c : ℝ, 0 < c ∧ (f · ^ c) = g /-- Equivalence of absolute values is reflexive. -/ -lemma equiv_refl (f : AbsoluteValue R ℝ) : Equiv f f := +lemma isEquiv_refl (f : AbsoluteValue R ℝ) : IsEquiv f f := ⟨1, Real.zero_lt_one, funext fun x ↦ Real.rpow_one (f x)⟩ /-- Equivalence of absolute values is symmetric. -/ -lemma equiv_symm {f g : AbsoluteValue R ℝ} (hfg : Equiv f g) : Equiv g f := by +lemma isEquiv_symm {f g : AbsoluteValue R ℝ} (hfg : IsEquiv f g) : IsEquiv g f := by rcases hfg with ⟨c, hcpos, h⟩ refine ⟨1 / c, one_div_pos.mpr hcpos, ?_⟩ simp [← h, Real.rpow_rpow_inv (apply_nonneg f _) (ne_of_lt hcpos).symm] /-- Equivalence of absolute values is transitive. -/ -lemma equiv_trans {f g k : AbsoluteValue R ℝ} (hfg : Equiv f g) (hgk : Equiv g k) : - Equiv f k := by +lemma isEquiv_trans {f g k : AbsoluteValue R ℝ} (hfg : IsEquiv f g) (hgk : IsEquiv g k) : + IsEquiv f k := by rcases hfg with ⟨c, hcPos, hfg⟩ rcases hgk with ⟨d, hdPos, hgk⟩ refine ⟨c * d, mul_pos hcPos hdPos, ?_⟩ simp [← hgk, ← hfg, Real.rpow_mul (apply_nonneg f _)] +instance : Setoid (AbsoluteValue R ℝ) where + r := IsEquiv + iseqv := { + refl := isEquiv_refl + symm := isEquiv_symm + trans := isEquiv_trans + } + /-- An absolute value is equivalent to the trivial iff it is trivial itself. -/ @[simp] -lemma eq_trivial_of_equiv_trivial [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R] +lemma eq_trivial_of_isEquiv_trivial [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R] (f : AbsoluteValue R ℝ) : - f.Equiv .trivial ↔ f = .trivial := by - refine ⟨fun ⟨c, hc₀, hc⟩ ↦ ext fun x ↦ ?_, fun H ↦ H ▸ equiv_refl f⟩ + f ≈ .trivial ↔ f = .trivial := by + refine ⟨fun ⟨c, hc₀, hc⟩ ↦ ext fun x ↦ ?_, fun H ↦ H ▸ isEquiv_refl f⟩ apply_fun (· x) at hc rcases eq_or_ne x 0 with rfl | hx · simp · simp only [ne_eq, hx, not_false_eq_true, trivial_apply] at hc ⊢ exact (Real.rpow_left_inj (f.nonneg x) zero_le_one hc₀.ne').mp <| (Real.one_rpow c).symm ▸ hc -instance : Setoid (AbsoluteValue R ℝ) where - r := Equiv - iseqv := { - refl := equiv_refl - symm := equiv_symm - trans := equiv_trans - } - end AbsoluteValue diff --git a/Mathlib/Analysis/Normed/Ring/Seminorm.lean b/Mathlib/Analysis/Normed/Ring/Seminorm.lean index 46f441641f167..7856ea39c83fa 100644 --- a/Mathlib/Analysis/Normed/Ring/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Ring/Seminorm.lean @@ -23,6 +23,8 @@ For a ring `R`: * `MulRingSeminorm`: A multiplicative seminorm on a ring `R` is a ring seminorm that preserves multiplication. * `MulRingNorm`: A multiplicative norm on a ring `R` is a ring norm that preserves multiplication. + `MulRingNorm R` is essentially the same as `AbsoluteValue R ℝ`, and it is recommended to + use the latter instead to avoid duplicating results. ## Notes @@ -60,7 +62,10 @@ structure MulRingSeminorm (R : Type*) [NonAssocRing R] extends AddGroupSeminorm MonoidWithZeroHom R ℝ /-- A multiplicative norm on a ring `R` is a multiplicative ring seminorm such that `f x = 0` -implies `x = 0`. -/ +implies `x = 0`. + +It is recommended to use `AbsoluteValue R ℝ` instead (which works for `Semiring R` +and is equivalent to `MulRingNorm R` for a nontrivial `Ring R`). -/ structure MulRingNorm (R : Type*) [NonAssocRing R] extends MulRingSeminorm R, AddGroupNorm R attribute [nolint docBlame] @@ -351,20 +356,56 @@ theorem apply_one (x : R) : (1 : MulRingNorm R) x = if x = 0 then 0 else 1 := instance : Inhabited (MulRingNorm R) := ⟨1⟩ +section MulRingNorm_equiv_AbsoluteValue + +variable {R : Type*} [Ring R] [Nontrivial R] + +/-- The equivalence of `MulRingNorm R` and `AbsoluteValue R ℝ` when `R` is a nontrivial ring. -/ +def mulRingNormEquivAbsoluteValue : MulRingNorm R ≃ AbsoluteValue R ℝ where + toFun N := { + toFun := N.toFun + map_mul' := N.map_mul' + nonneg' := apply_nonneg N + eq_zero' x := ⟨N.eq_zero_of_map_eq_zero' x, fun h ↦ h ▸ N.map_zero'⟩ + add_le' := N.add_le' + } + invFun v := { + toFun := v.toFun + map_zero' := (v.eq_zero' 0).mpr rfl + add_le' := v.add_le' + neg' := v.map_neg + map_one' := v.map_one + map_mul' := v.map_mul' + eq_zero_of_map_eq_zero' x := (v.eq_zero' x).mp + } + left_inv N := by ext1 x; simp only [MulRingSeminorm.toFun_eq_coe] -- `simp` does not work + right_inv v := by ext1 x; simp + +lemma mulRingNormEquivAbsoluteValue_apply (N : MulRingNorm R) (x : R) : + mulRingNormEquivAbsoluteValue N x = N x := rfl + +lemma mulRingNormEquivAbsoluteValue_symm_apply (v : AbsoluteValue R ℝ) (x : R) : + mulRingNormEquivAbsoluteValue.symm v x = v x := rfl + +end MulRingNorm_equiv_AbsoluteValue variable {R : Type*} [Ring R] /-- Two multiplicative ring norms `f, g` on `R` are equivalent if there exists a positive constant `c` such that for all `x ∈ R`, `(f x)^c = g x`. -/ - +@[deprecated "Use AbsoluteValue.IsEquiv instead" (since := "2025-01-07")] def equiv (f : MulRingNorm R) (g : MulRingNorm R) := ∃ c : ℝ, 0 < c ∧ (fun x => (f x) ^ c) = g +set_option linter.deprecated false in /-- Equivalence of multiplicative ring norms is reflexive. -/ +@[deprecated "Use AbsoluteValue.isEquiv_refl instead" (since := "2025-01-07")] lemma equiv_refl (f : MulRingNorm R) : equiv f f := by exact ⟨1, Real.zero_lt_one, by simp only [Real.rpow_one]⟩ +set_option linter.deprecated false in /-- Equivalence of multiplicative ring norms is symmetric. -/ +@[deprecated "Use AbsoluteValue.isEquiv_symm instead" (since := "2025-01-07")] lemma equiv_symm {f g : MulRingNorm R} (hfg : equiv f g) : equiv g f := by rcases hfg with ⟨c, hcpos, h⟩ use 1/c @@ -373,7 +414,9 @@ lemma equiv_symm {f g : MulRingNorm R} (hfg : equiv f g) : equiv g f := by ext x simpa [← congr_fun h x] using Real.rpow_rpow_inv (apply_nonneg f x) (ne_of_lt hcpos).symm +set_option linter.deprecated false in /-- Equivalence of multiplicative ring norms is transitive. -/ +@[deprecated "Use AbsoluteValue.isEquiv_trans instead" (since := "2025-01-07")] lemma equiv_trans {f g k : MulRingNorm R} (hfg : equiv f g) (hgk : equiv g k) : equiv f k := by rcases hfg with ⟨c, hcPos, hfg⟩ @@ -408,6 +451,7 @@ def normRingNorm (R : Type*) [NonUnitalNormedRing R] : RingNorm R := /-- A multiplicative ring norm satisfies `f n ≤ n` for every `n : ℕ`. -/ +@[deprecated "Use AbsoluteValue.apply_nat_le_self instead" (since := "2025-01-07")] lemma MulRingNorm_nat_le_nat {R : Type*} [Ring R] (n : ℕ) (f : MulRingNorm R) : f n ≤ n := by induction n with | zero => simp only [Nat.cast_zero, map_zero, le_refl] @@ -421,6 +465,7 @@ lemma MulRingNorm_nat_le_nat {R : Type*} [Ring R] (n : ℕ) (f : MulRingNorm R) open Int /-- A multiplicative norm composed with the absolute value on integers equals the norm itself. -/ +@[deprecated "Use AbsoluteValue.apply_natAbs_eq instead" (since := "2025-01-07")] lemma MulRingNorm.apply_natAbs_eq {R : Type*} [Ring R] (x : ℤ) (f : MulRingNorm R) : f (natAbs x) = f x := by obtain ⟨n, rfl | rfl⟩ := eq_nat_or_neg x <;> @@ -459,7 +504,16 @@ def NormedField.toMulRingNorm (R : Type*) [NormedField R] : MulRingNorm R where neg' := norm_neg eq_zero_of_map_eq_zero' x hx := by rw [← norm_eq_zero]; exact hx +/-- The norm on a `NormedField`, as an `AbsoluteValue`. -/ +def NormedField.toAbsoluteValue (R : Type*) [NormedField R] : AbsoluteValue R ℝ where + toFun := norm + map_mul' := norm_mul + nonneg' := norm_nonneg + eq_zero' _ := norm_eq_zero + add_le' := norm_add_le + /-- Triangle inequality for `MulRingNorm` applied to a list. -/ +@[deprecated "Use AbsoluteValue.listSum_le instead" (since := "2025-01-07")] lemma mulRingNorm_sum_le_sum_mulRingNorm {R : Type*} [NonAssocRing R] (l : List R) (f : MulRingNorm R) : f l.sum ≤ (l.map f).sum := by induction l with From 2e638548e934d91a77f7f1f7a49f86208d69af2d Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 7 Jan 2025 22:11:02 +0000 Subject: [PATCH 069/681] chore: disable docPrime linter (#20559) [Zulip thread](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/docPrime.20hell) (one of many). --- lakefile.lean | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lakefile.lean b/lakefile.lean index a9a535eb971a2..8547cccd1b924 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -24,7 +24,8 @@ require "leanprover-community" / "plausible" @ git "v4.16.0-rc1" * as `moreServerArgs`, to set their default value in mathlib (as well as `Archive`, `Counterexamples` and `test`). -/ abbrev mathlibOnlyLinters : Array LeanOption := #[ - ⟨`linter.docPrime, true⟩, + -- The `docPrime` linter is disabled: https://github.com/leanprover-community/mathlib4/issues/20560 + ⟨`linter.docPrime, false⟩, ⟨`linter.hashCommand, true⟩, ⟨`linter.oldObtain, true,⟩, ⟨`linter.refine, true⟩, From 12a21978832c63bb303ec97cbc0fecb4096fe847 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 8 Jan 2025 02:05:24 +0000 Subject: [PATCH 070/681] chore: scope 'on' notation to Function (#20562) Per [discussion](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/global.20notation.20linter/near/492266984) on zulip. --- Mathlib/Algebra/Module/Torsion.lean | 3 +++ Mathlib/Algebra/Order/Interval/Set/Group.lean | 1 + Mathlib/Algebra/Polynomial/Degree/Lemmas.lean | 2 ++ Mathlib/Algebra/Polynomial/RingDivision.lean | 1 + Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean | 2 ++ Mathlib/Analysis/InnerProductSpace/Orthogonal.lean | 1 + Mathlib/Analysis/Normed/Algebra/Exponential.lean | 1 + Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean | 1 + Mathlib/Data/Finset/NoncommProd.lean | 1 + Mathlib/Data/Finset/Pairwise.lean | 2 ++ Mathlib/Data/Finsupp/BigOperators.lean | 2 ++ Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean | 1 + Mathlib/Data/Matroid/Sum.lean | 2 ++ Mathlib/Data/Multiset/Bind.lean | 1 + Mathlib/Data/Nat/ChineseRemainder.lean | 1 + Mathlib/Data/Nat/Choose/Multinomial.lean | 2 ++ Mathlib/Data/Setoid/Basic.lean | 2 ++ Mathlib/Data/Setoid/Partition.lean | 2 ++ Mathlib/Data/ZMod/Quotient.lean | 1 + Mathlib/FieldTheory/Separable.lean | 1 + Mathlib/GroupTheory/CoprodI.lean | 4 ++++ Mathlib/LinearAlgebra/FreeProduct/Basic.lean | 4 ++++ Mathlib/LinearAlgebra/SesquilinearForm.lean | 1 + Mathlib/Logic/Embedding/Set.lean | 2 ++ Mathlib/Logic/Encodable/Lattice.lean | 1 + Mathlib/Logic/Equiv/Pairwise.lean | 2 ++ Mathlib/Logic/Function/Defs.lean | 2 +- Mathlib/Logic/Godel/GodelBetaFunction.lean | 1 + Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean | 1 + Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean | 1 + Mathlib/MeasureTheory/Covering/VitaliFamily.lean | 1 + Mathlib/MeasureTheory/Decomposition/SignedHahn.lean | 1 + Mathlib/MeasureTheory/Function/Jacobian.lean | 2 ++ Mathlib/MeasureTheory/Integral/Lebesgue.lean | 2 ++ Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean | 1 + Mathlib/MeasureTheory/Measure/NullMeasurable.lean | 2 ++ Mathlib/MeasureTheory/Measure/Regular.lean | 1 + Mathlib/MeasureTheory/OuterMeasure/Defs.lean | 2 ++ Mathlib/MeasureTheory/PiSystem.lean | 2 ++ Mathlib/MeasureTheory/VectorMeasure/Basic.lean | 1 + Mathlib/NumberTheory/ArithmeticFunction.lean | 1 + Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean | 1 + .../NumberTheory/NumberField/CanonicalEmbedding/Basic.lean | 1 + Mathlib/Order/Disjointed.lean | 2 ++ Mathlib/Order/Filter/Bases.lean | 1 + Mathlib/Order/PartialSups.lean | 1 + Mathlib/Order/SuccPred/IntervalSucc.lean | 4 ++++ Mathlib/Order/SupIndep.lean | 1 + Mathlib/Order/WellFounded.lean | 1 + Mathlib/Order/WellFoundedSet.lean | 2 ++ Mathlib/Probability/Kernel/Composition/Basic.lean | 1 + Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean | 1 + Mathlib/Probability/Kernel/Disintegration/Density.lean | 1 + Mathlib/Probability/StrongLaw.lean | 2 ++ Mathlib/RingTheory/Coprime/Lemmas.lean | 2 ++ Mathlib/RingTheory/Ideal/Operations.lean | 1 + Mathlib/RingTheory/Lasker.lean | 2 ++ Mathlib/Topology/MetricSpace/Thickening.lean | 2 ++ 58 files changed, 90 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index 6142c7d5ef137..7443d4cffa6a7 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -408,6 +408,8 @@ theorem supIndep_torsionBySet_ideal (hp : (S : Set ι).Pairwise fun i j => p i variable {q : ι → R} +open scoped Function -- required for scoped `on` notation + theorem iSup_torsionBy_eq_torsionBy_prod (hq : (S : Set ι).Pairwise <| (IsCoprime on q)) : ⨆ i ∈ S, torsionBy R M (q i) = torsionBy R M (∏ i ∈ S, q i) := by rw [← torsionBySet_span_singleton_eq, Ideal.submodule_span_eq, ← @@ -454,6 +456,7 @@ theorem torsionBySet_isInternal {p : ι → Ideal R} apply (iSup_torsionBySet_ideal_eq_torsionBySet_iInf hp).trans <| (Module.isTorsionBySet_iff_torsionBySet_eq_top _).mp hM) +open scoped Function in -- required for scoped `on` notation /-- If the `q i` are pairwise coprime, a `∏ i, q i`-torsion module is the internal direct sum of its `q i`-torsion submodules. -/ theorem torsionBy_isInternal {q : ι → R} (hq : (S : Set ι).Pairwise <| (IsCoprime on q)) diff --git a/Mathlib/Algebra/Order/Interval/Set/Group.lean b/Mathlib/Algebra/Order/Interval/Set/Group.lean index 671a053591075..185f1f2c53353 100644 --- a/Mathlib/Algebra/Order/Interval/Set/Group.lean +++ b/Mathlib/Algebra/Order/Interval/Set/Group.lean @@ -146,6 +146,7 @@ end LinearOrderedAddCommGroup /-! ### Lemmas about disjointness of translates of intervals -/ +open scoped Function -- required for scoped `on` notation section PairwiseDisjoint section OrderedCommGroup diff --git a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean index c6557963d2e95..e007ecda8074d 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean @@ -180,6 +180,8 @@ theorem coeff_add_eq_right_of_lt (pn : p.natDegree < n) : (p + q).coeff n = q.co rw [add_comm] exact coeff_add_eq_left_of_lt pn +open scoped Function -- required for scoped `on` notation + theorem degree_sum_eq_of_disjoint (f : S → R[X]) (s : Finset S) (h : Set.Pairwise { i | i ∈ s ∧ f i ≠ 0 } (Ne on degree ∘ f)) : degree (s.sum f) = s.sup fun i => degree (f i) := by diff --git a/Mathlib/Algebra/Polynomial/RingDivision.lean b/Mathlib/Algebra/Polynomial/RingDivision.lean index cf24ecbffc9f9..eb2061427a125 100644 --- a/Mathlib/Algebra/Polynomial/RingDivision.lean +++ b/Mathlib/Algebra/Polynomial/RingDivision.lean @@ -219,6 +219,7 @@ theorem isCoprime_X_sub_C_of_isUnit_sub {R} [CommRing R] {a b : R} (h : IsUnit ( congr exact h.val_inv_mul⟩ +open scoped Function in -- required for scoped `on` notation theorem pairwise_coprime_X_sub_C {K} [Field K] {I : Type v} {s : I → K} (H : Function.Injective s) : Pairwise (IsCoprime on fun i : I => X - C (s i)) := fun _ _ hij => isCoprime_X_sub_C_of_isUnit_sub (sub_ne_zero_of_ne <| H.ne hij).isUnit diff --git a/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean b/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean index 9816edf6682a7..a340ee71187ce 100644 --- a/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean +++ b/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean @@ -111,6 +111,8 @@ theorem directSum_isInternal_of_commute (hA : A.IsSymmetric) (hB : B.IsSymmetric rw [Submodule.orthogonal_eq_bot_iff, iSup_prod, iSup_comm] exact iSup_iSup_eigenspace_inf_eigenspace_eq_top_of_commute hA hB hAB +open scoped Function -- required for scoped `on` notation + /-- A commuting family of symmetric linear maps on a finite dimensional inner product space is simultaneously diagonalizable. -/ theorem iSup_iInf_eq_top_of_commute {ι : Type*} {T : ι → E →ₗ[𝕜] E} diff --git a/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean b/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean index 70a253a0c3e16..876666070250b 100644 --- a/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean +++ b/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean @@ -350,6 +350,7 @@ theorem IsOrtho.comap_iff (f : E ≃ₗᵢ[𝕜] F) {U V : Submodule 𝕜 F} : U end Submodule +open scoped Function in -- required for scoped `on` notation theorem orthogonalFamily_iff_pairwise {ι} {V : ι → Submodule 𝕜 E} : (OrthogonalFamily 𝕜 (fun i => V i) fun i => (V i).subtypeₗᵢ) ↔ Pairwise ((· ⟂ ·) on V) := forall₃_congr fun _i _j _hij => diff --git a/Mathlib/Analysis/Normed/Algebra/Exponential.lean b/Mathlib/Analysis/Normed/Algebra/Exponential.lean index 2c3861688440d..9166797fa69d8 100644 --- a/Mathlib/Analysis/Normed/Algebra/Exponential.lean +++ b/Mathlib/Analysis/Normed/Algebra/Exponential.lean @@ -474,6 +474,7 @@ theorem exp_mem_unitary_of_mem_skewAdjoint [StarRing 𝔸] [ContinuousStar 𝔸] end +open scoped Function in -- required for scoped `on` notation /-- In a Banach-algebra `𝔸` over `𝕂 = ℝ` or `𝕂 = ℂ`, if a family of elements `f i` mutually commute then `NormedSpace.exp 𝕂 (∑ i, f i) = ∏ i, NormedSpace.exp 𝕂 (f i)`. -/ theorem exp_sum_of_commute {ι} (s : Finset ι) (f : ι → 𝔸) diff --git a/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean b/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean index fe33c719a4832..3bbd2707d64b9 100644 --- a/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean +++ b/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean @@ -124,6 +124,7 @@ nonrec theorem exp_add_of_commute (A B : Matrix m m 𝔸) (h : Commute A B) : letI : NormedAlgebra 𝕂 (Matrix m m 𝔸) := Matrix.linftyOpNormedAlgebra exact exp_add_of_commute h +open scoped Function in -- required for scoped `on` notation nonrec theorem exp_sum_of_commute {ι} (s : Finset ι) (f : ι → Matrix m m 𝔸) (h : (s : Set ι).Pairwise (Commute on f)) : exp 𝕂 (∑ i ∈ s, f i) = diff --git a/Mathlib/Data/Finset/NoncommProd.lean b/Mathlib/Data/Finset/NoncommProd.lean index 712c62a411ec7..ccb90bcd3b3d0 100644 --- a/Mathlib/Data/Finset/NoncommProd.lean +++ b/Mathlib/Data/Finset/NoncommProd.lean @@ -228,6 +228,7 @@ namespace Finset variable [Monoid β] [Monoid γ] +open scoped Function -- required for scoped `on` notation /-- Proof used in definition of `Finset.noncommProd` -/ @[to_additive] diff --git a/Mathlib/Data/Finset/Pairwise.lean b/Mathlib/Data/Finset/Pairwise.lean index 0d7b6a6199507..3e9480a8c16bf 100644 --- a/Mathlib/Data/Finset/Pairwise.lean +++ b/Mathlib/Data/Finset/Pairwise.lean @@ -80,6 +80,8 @@ theorem pairwise_iff_coe_toFinset_pairwise (hn : l.Nodup) (hs : Symmetric r) : letI : IsSymm α r := ⟨hs⟩ rw [coe_toFinset, hn.pairwise_coe] +open scoped Function -- required for scoped `on` notation + theorem pairwise_disjoint_of_coe_toFinset_pairwiseDisjoint {α ι} [SemilatticeInf α] [OrderBot α] [DecidableEq ι] {l : List ι} {f : ι → α} (hl : (l.toFinset : Set ι).PairwiseDisjoint f) (hn : l.Nodup) : l.Pairwise (_root_.Disjoint on f) := diff --git a/Mathlib/Data/Finsupp/BigOperators.lean b/Mathlib/Data/Finsupp/BigOperators.lean index 170585fa66d4b..ed77d4374edaa 100644 --- a/Mathlib/Data/Finsupp/BigOperators.lean +++ b/Mathlib/Data/Finsupp/BigOperators.lean @@ -70,6 +70,8 @@ theorem Finset.mem_sup_support_iff [Zero M] {s : Finset (ι →₀ M)} {x : ι} x ∈ s.sup Finsupp.support ↔ ∃ f ∈ s, x ∈ f.support := Multiset.mem_sup_map_support_iff +open scoped Function -- required for scoped `on` notation + theorem List.support_sum_eq [AddMonoid M] (l : List (ι →₀ M)) (hl : l.Pairwise (_root_.Disjoint on Finsupp.support)) : l.sum.support = l.foldr (Finsupp.support · ⊔ ·) ∅ := by diff --git a/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean b/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean index 45e95c792981c..fc03f56398bf2 100644 --- a/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean +++ b/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean @@ -72,6 +72,7 @@ theorem ofDegLex_add [AddCommMonoid α] (a b : DegLex α) : namespace Finsupp +open scoped Function in -- required for scoped `on` notation /-- `Finsupp.DegLex r s` is the homogeneous lexicographic order on `α →₀ M`, where `α` is ordered by `r` and `M` is ordered by `s`. The type synonym `DegLex (α →₀ M)` has an order given by `Finsupp.DegLex (· < ·) (· < ·)`. -/ diff --git a/Mathlib/Data/Matroid/Sum.lean b/Mathlib/Data/Matroid/Sum.lean index f3e98ee11cd2c..99c771b42c302 100644 --- a/Mathlib/Data/Matroid/Sum.lean +++ b/Mathlib/Data/Matroid/Sum.lean @@ -185,6 +185,8 @@ end sum' section disjointSigma +open scoped Function -- required for scoped `on` notation + variable {α ι : Type*} {M : ι → Matroid α} /-- The sum of an indexed collection of matroids on `α` with pairwise disjoint ground sets, diff --git a/Mathlib/Data/Multiset/Bind.lean b/Mathlib/Data/Multiset/Bind.lean index b34913bef0ace..766b7f70ea703 100644 --- a/Mathlib/Data/Multiset/Bind.lean +++ b/Mathlib/Data/Multiset/Bind.lean @@ -201,6 +201,7 @@ theorem attach_bind_coe (s : Multiset α) (f : α → Multiset β) : variable {f s t} +open scoped Function in -- required for scoped `on` notation @[simp] lemma nodup_bind : Nodup (bind s f) ↔ (∀ a ∈ s, Nodup (f a)) ∧ s.Pairwise (Disjoint on f) := by have : ∀ a, ∃ l : List β, f a = l := fun a => Quot.induction_on (f a) fun l => ⟨l, rfl⟩ diff --git a/Mathlib/Data/Nat/ChineseRemainder.lean b/Mathlib/Data/Nat/ChineseRemainder.lean index 17beeef782677..e7147fe88bf42 100644 --- a/Mathlib/Data/Nat/ChineseRemainder.lean +++ b/Mathlib/Data/Nat/ChineseRemainder.lean @@ -22,6 +22,7 @@ Gödel's Beta function, which is used in proving Gödel's incompleteness theorem Chinese Remainder Theorem, Gödel, beta function -/ +open scoped Function -- required for scoped `on` notation namespace Nat variable {ι : Type*} diff --git a/Mathlib/Data/Nat/Choose/Multinomial.lean b/Mathlib/Data/Nat/Choose/Multinomial.lean index 318cee9f748cd..ea155b24f4e44 100644 --- a/Mathlib/Data/Nat/Choose/Multinomial.lean +++ b/Mathlib/Data/Nat/Choose/Multinomial.lean @@ -207,6 +207,8 @@ variable {α R : Type*} [DecidableEq α] section Semiring variable [Semiring R] +open scoped Function -- required for scoped `on` notation + -- TODO: Can we prove one of the following two from the other one? /-- The **multinomial theorem**. -/ lemma sum_pow_eq_sum_piAntidiag_of_commute (s : Finset α) (f : α → R) diff --git a/Mathlib/Data/Setoid/Basic.lean b/Mathlib/Data/Setoid/Basic.lean index 3599ac45fefc2..48dc6951f8870 100644 --- a/Mathlib/Data/Setoid/Basic.lean +++ b/Mathlib/Data/Setoid/Basic.lean @@ -89,6 +89,8 @@ theorem trans' (r : Setoid α) : ∀ {x y z}, r x y → r y z → r x z := r.ise theorem comm' (s : Setoid α) {x y} : s x y ↔ s y x := ⟨s.symm', s.symm'⟩ +open scoped Function -- required for scoped `on` notation + /-- The kernel of a function is an equivalence relation. -/ def ker (f : α → β) : Setoid α := ⟨(· = ·) on f, eq_equivalence.comap f⟩ diff --git a/Mathlib/Data/Setoid/Partition.lean b/Mathlib/Data/Setoid/Partition.lean index 7781e1a597991..c0909554e4007 100644 --- a/Mathlib/Data/Setoid/Partition.lean +++ b/Mathlib/Data/Setoid/Partition.lean @@ -310,6 +310,8 @@ structure IndexedPartition {ι α : Type*} (s : ι → Set α) where /-- membership invariance for `index`-/ mem_index : ∀ x, x ∈ s (index x) +open scoped Function -- required for scoped `on` notation + /-- The non-constructive constructor for `IndexedPartition`. -/ noncomputable def IndexedPartition.mk' {ι α : Type*} (s : ι → Set α) (dis : Pairwise (Disjoint on s)) (nonempty : ∀ i, (s i).Nonempty) diff --git a/Mathlib/Data/ZMod/Quotient.lean b/Mathlib/Data/ZMod/Quotient.lean index 1f9876b6be3b6..8f05b3b2992d5 100644 --- a/Mathlib/Data/ZMod/Quotient.lean +++ b/Mathlib/Data/ZMod/Quotient.lean @@ -63,6 +63,7 @@ end Int noncomputable section ChineseRemainder open Ideal +open scoped Function in -- required for scoped `on` notation /-- The **Chinese remainder theorem**, elementary version for `ZMod`. See also `Mathlib.Data.ZMod.Basic` for versions involving only two numbers. -/ def ZMod.prodEquivPi {ι : Type*} [Fintype ι] (a : ι → ℕ) diff --git a/Mathlib/FieldTheory/Separable.lean b/Mathlib/FieldTheory/Separable.lean index 159ba206bec4e..a06c06de06f6f 100644 --- a/Mathlib/FieldTheory/Separable.lean +++ b/Mathlib/FieldTheory/Separable.lean @@ -213,6 +213,7 @@ theorem separable_prod' {ι : Sort _} {f : ι → R[X]} {s : Finset ι} : h2.1.mul (ih h1.2.2 h2.2) (IsCoprime.prod_right fun i his => h1.1.2 i his <| Ne.symm <| ne_of_mem_of_not_mem his has) +open scoped Function in -- required for scoped `on` notation theorem separable_prod {ι : Sort _} [Fintype ι] {f : ι → R[X]} (h1 : Pairwise (IsCoprime on f)) (h2 : ∀ x, (f x).Separable) : (∏ x, f x).Separable := separable_prod' (fun _x _hx _y _hy hxy => h1 hxy) fun x _hx => h2 x diff --git a/Mathlib/GroupTheory/CoprodI.lean b/Mathlib/GroupTheory/CoprodI.lean index e5bc86accb345..dbb69a5fef864 100644 --- a/Mathlib/GroupTheory/CoprodI.lean +++ b/Mathlib/GroupTheory/CoprodI.lean @@ -812,6 +812,8 @@ open Pointwise open Cardinal +open scoped Function -- required for scoped `on` notation + variable {G : Type*} [Group G] variable {H : ι → Type*} [∀ i, Group (H i)] variable (f : ∀ i, H i →* G) @@ -966,6 +968,8 @@ section PingPongLemma open Pointwise Cardinal +open scoped Function -- required for scoped `on` notation + variable [Nontrivial ι] variable {G : Type u_1} [Group G] (a : ι → G) diff --git a/Mathlib/LinearAlgebra/FreeProduct/Basic.lean b/Mathlib/LinearAlgebra/FreeProduct/Basic.lean index 15dd2e3d55456..74441ef678e10 100644 --- a/Mathlib/LinearAlgebra/FreeProduct/Basic.lean +++ b/Mathlib/LinearAlgebra/FreeProduct/Basic.lean @@ -64,6 +64,8 @@ end DirectSum namespace RingQuot universe uS uA uB +open scoped Function -- required for scoped `on` notation + /--If two `R`-algebras are `R`-equivalent and their quotients by a relation `rel` are defined, then their quotients are also `R`-equivalent. @@ -135,6 +137,8 @@ inductive rel : FreeTensorAlgebra R A → FreeTensorAlgebra R A → Prop (tprod R (⨁ i, A i) 2 (fun | 0 => lof R I A i a₁ | 1 => lof R I A i a₂)) (ι R <| lof R I A i (a₁ * a₂)) +open scoped Function -- required for scoped `on` notation + /--The generating equivalence relation for elements of the power algebra that are identified in the free product. -/ @[reducible, simp] def rel' := rel R A on ofDirectSum diff --git a/Mathlib/LinearAlgebra/SesquilinearForm.lean b/Mathlib/LinearAlgebra/SesquilinearForm.lean index e4eb407fc013c..504d2acfe7e8e 100644 --- a/Mathlib/LinearAlgebra/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/SesquilinearForm.lean @@ -65,6 +65,7 @@ theorem isOrtho_zero_right (B : M₁ →ₛₗ[I₁] M₂ →ₛₗ[I₂] M) (x) theorem isOrtho_flip {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] M} {x y} : B.IsOrtho x y ↔ B.flip.IsOrtho y x := by simp_rw [isOrtho_def, flip_apply] +open scoped Function in -- required for scoped `on` notation /-- A set of vectors `v` is orthogonal with respect to some bilinear map `B` if and only if for all `i ≠ j`, `B (v i) (v j) = 0`. For orthogonality between two elements, use `BilinForm.isOrtho` -/ diff --git a/Mathlib/Logic/Embedding/Set.lean b/Mathlib/Logic/Embedding/Set.lean index 0c0ce8045a169..1c85ef2c28d32 100644 --- a/Mathlib/Logic/Embedding/Set.lean +++ b/Mathlib/Logic/Embedding/Set.lean @@ -160,6 +160,8 @@ variable {α ι : Type*} {s t r : Set α} range (Function.Embedding.sumSet h) = s ∪ t := by simp [Set.ext_iff] +open scoped Function -- required for scoped `on` notation + /-- For an indexed family `s : ι → Set α` of disjoint sets, the natural injection from the sigma-type `(i : ι) × ↑(s i)` to `α`. -/ @[simps] def Function.Embedding.sigmaSet {s : ι → Set α} (h : Pairwise (Disjoint on s)) : diff --git a/Mathlib/Logic/Encodable/Lattice.lean b/Mathlib/Logic/Encodable/Lattice.lean index 039681749b576..5ca2ec3f7aecc 100644 --- a/Mathlib/Logic/Encodable/Lattice.lean +++ b/Mathlib/Logic/Encodable/Lattice.lean @@ -44,6 +44,7 @@ theorem iUnion_decode₂_cases {f : β → Set α} {C : Set α → Prop} (H0 : C convert H1 b simp [Set.ext_iff] +open scoped Function in -- required for scoped `on` notation theorem iUnion_decode₂_disjoint_on {f : β → Set α} (hd : Pairwise (Disjoint on f)) : Pairwise (Disjoint on fun i => ⋃ b ∈ decode₂ β i, f b) := by rintro i j ij diff --git a/Mathlib/Logic/Equiv/Pairwise.lean b/Mathlib/Logic/Equiv/Pairwise.lean index a21f1515ce92a..ebf8a8f6c4853 100644 --- a/Mathlib/Logic/Equiv/Pairwise.lean +++ b/Mathlib/Logic/Equiv/Pairwise.lean @@ -10,6 +10,8 @@ import Mathlib.Logic.Pairwise # Interaction of equivalences with `Pairwise` -/ +open scoped Function -- required for scoped `on` notation + lemma EmbeddingLike.pairwise_comp {X : Type*} {Y : Type*} {F} [FunLike F Y X] [EmbeddingLike F Y X] (f : F) {p : X → X → Prop} (h : Pairwise p) : Pairwise (p on f) := h.comp_of_injective <| EmbeddingLike.injective f diff --git a/Mathlib/Logic/Function/Defs.lean b/Mathlib/Logic/Function/Defs.lean index 21054aab26345..0caf5f335d524 100644 --- a/Mathlib/Logic/Function/Defs.lean +++ b/Mathlib/Logic/Function/Defs.lean @@ -44,7 +44,7 @@ from `β` to `α`. -/ abbrev onFun (f : β → β → φ) (g : α → β) : α → α → φ := fun x y => f (g x) (g y) @[inherit_doc onFun] -infixl:2 " on " => onFun +scoped infixl:2 " on " => onFun abbrev swap {φ : α → β → Sort u₃} (f : ∀ x y, φ x y) : ∀ y x, φ x y := fun y x => f x y diff --git a/Mathlib/Logic/Godel/GodelBetaFunction.lean b/Mathlib/Logic/Godel/GodelBetaFunction.lean index 22435ce394cd4..092137dd0dea8 100644 --- a/Mathlib/Logic/Godel/GodelBetaFunction.lean +++ b/Mathlib/Logic/Godel/GodelBetaFunction.lean @@ -68,6 +68,7 @@ lemma coprimes_lt (a : Fin m → ℕ) (i) : a i < coprimes a i := by (le_add_right _ _)) simpa only [coprimes] using lt_of_lt_of_le h₁ h₂ +open scoped Function in -- required for scoped `on` notation private lemma pairwise_coprime_coprimes (a : Fin m → ℕ) : Pairwise (Coprime on coprimes a) := by intro i j hij wlog ltij : i < j diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean index 3648b47ac5b12..8767171c0332e 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean @@ -222,6 +222,7 @@ theorem IsOpen.measurableSet (h : IsOpen s) : MeasurableSet s := theorem IsOpen.nullMeasurableSet {μ} (h : IsOpen s) : NullMeasurableSet s μ := h.measurableSet.nullMeasurableSet +open scoped Function in -- required for scoped `on` notation @[elab_as_elim] theorem MeasurableSet.induction_on_open {C : ∀ s : Set γ, MeasurableSet s → Prop} (isOpen : ∀ U (hU : IsOpen U), C U hU.measurableSet) diff --git a/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean b/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean index e0b6251d52956..33e6f5d60ba87 100644 --- a/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean +++ b/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean @@ -99,6 +99,7 @@ section variable [NormedSpace ℝ E] [FiniteDimensional ℝ E] +open scoped Function in -- required for scoped `on` notation /-- Any `1`-separated set in the ball of radius `2` has cardinality at most `5 ^ dim`. This is useful to show that the supremum in the definition of `Besicovitch.multiplicity E` is well behaved. -/ diff --git a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean index e83670491cdf0..7671daaa30640 100644 --- a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean +++ b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean @@ -131,6 +131,7 @@ theorem index_subset : ∀ p : X × Set X, p ∈ h.index → p.1 ∈ s := theorem covering_disjoint : h.index.PairwiseDisjoint h.covering := h.exists_disjoint_covering_ae.choose_spec.2.1 +open scoped Function in -- required for scoped `on` notation theorem covering_disjoint_subtype : Pairwise (Disjoint on fun x : h.index => h.covering x) := (pairwise_subtype_iff_pairwise_set _ _).2 h.covering_disjoint diff --git a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean index f6fe47d6c9795..0a690c953d507 100644 --- a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean +++ b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean @@ -211,6 +211,7 @@ private theorem restrictNonposSeq_disjoint' {n m : ℕ} (h : n < m) : (someExistsOneDivLT_subset hx₂).2 (Set.mem_iUnion.2 ⟨n, Set.mem_iUnion.2 ⟨Nat.lt_succ_iff.mp h, hx₁⟩⟩) +open scoped Function in -- required for scoped `on` notation private theorem restrictNonposSeq_disjoint : Pairwise (Disjoint on restrictNonposSeq s i) := by intro n m h rw [Function.onFun, Set.disjoint_iff_inter_eq_empty] diff --git a/Mathlib/MeasureTheory/Function/Jacobian.lean b/Mathlib/MeasureTheory/Function/Jacobian.lean index f4914c6260a11..bfb9326f21a71 100644 --- a/Mathlib/MeasureTheory/Function/Jacobian.lean +++ b/Mathlib/MeasureTheory/Function/Jacobian.lean @@ -242,6 +242,8 @@ theorem exists_closed_cover_approximatesLinearOn_of_hasFDerivWithinAt [SecondCou variable [MeasurableSpace E] [BorelSpace E] (μ : Measure E) [IsAddHaarMeasure μ] +open scoped Function -- required for scoped `on` notation + /-- Assume that a function `f` has a derivative at every point of a set `s`. Then one may partition `s` into countably many disjoint relatively measurable sets (i.e., intersections of `s` with measurable sets `t n`) on which `f` is well approximated by linear maps `A n`. -/ diff --git a/Mathlib/MeasureTheory/Integral/Lebesgue.lean b/Mathlib/MeasureTheory/Integral/Lebesgue.lean index 71735659713fe..b0cbd7bec0648 100644 --- a/Mathlib/MeasureTheory/Integral/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Integral/Lebesgue.lean @@ -1304,6 +1304,8 @@ theorem lintegral_tsum [Countable β] {f : β → α → ℝ≥0∞} (hf : ∀ i open Measure +open scoped Function -- required for scoped `on` notation + theorem lintegral_iUnion₀ [Countable β] {s : β → Set α} (hm : ∀ i, NullMeasurableSet (s i) μ) (hd : Pairwise (AEDisjoint μ on s)) (f : α → ℝ≥0∞) : ∫⁻ a in ⋃ i, s i, f a ∂μ = ∑' i, ∫⁻ a in s i, f a ∂μ := by diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean index 2a68df2ddc985..aa7a1f5093442 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean @@ -128,6 +128,7 @@ namespace Measure ### Strict subspaces have zero measure -/ +open scoped Function -- required for scoped `on` notation /-- If a set is disjoint of its translates by infinitely many bounded vectors, then it has measure zero. This auxiliary lemma proves this assuming additionally that the set is bounded. -/ diff --git a/Mathlib/MeasureTheory/Measure/NullMeasurable.lean b/Mathlib/MeasureTheory/Measure/NullMeasurable.lean index b2e786979552e..0e4f0916c5455 100644 --- a/Mathlib/MeasureTheory/Measure/NullMeasurable.lean +++ b/Mathlib/MeasureTheory/Measure/NullMeasurable.lean @@ -207,6 +207,8 @@ end NullMeasurableSet open NullMeasurableSet +open scoped Function -- required for scoped `on` notation + /-- If `sᵢ` is a countable family of (null) measurable pairwise `μ`-a.e. disjoint sets, then there exists a subordinate family `tᵢ ⊆ sᵢ` of measurable pairwise disjoint sets such that `tᵢ =ᵐ[μ] sᵢ`. -/ diff --git a/Mathlib/MeasureTheory/Measure/Regular.lean b/Mathlib/MeasureTheory/Measure/Regular.lean index 91b924e0a4f30..815cd81e7c71e 100644 --- a/Mathlib/MeasureTheory/Measure/Regular.lean +++ b/Mathlib/MeasureTheory/Measure/Regular.lean @@ -386,6 +386,7 @@ instance smul_nnreal (μ : Measure α) [OuterRegular μ] (c : ℝ≥0) : OuterRegular (c • μ) := OuterRegular.smul μ coe_ne_top +open scoped Function in -- required for scoped `on` notation /-- If the restrictions of a measure to countably many open sets covering the space are outer regular, then the measure itself is outer regular. -/ lemma of_restrict [OpensMeasurableSpace α] {μ : Measure α} {s : ℕ → Set α} diff --git a/Mathlib/MeasureTheory/OuterMeasure/Defs.lean b/Mathlib/MeasureTheory/OuterMeasure/Defs.lean index a776ff90e2c9c..47b1684512889 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Defs.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Defs.lean @@ -38,6 +38,8 @@ variable {α : Type*} namespace MeasureTheory +open scoped Function -- required for scoped `on` notation + /-- An outer measure is a countably subadditive monotone function that sends `∅` to `0`. -/ structure OuterMeasure (α : Type*) where /-- Outer measure function. Use automatic coercion instead. -/ diff --git a/Mathlib/MeasureTheory/PiSystem.lean b/Mathlib/MeasureTheory/PiSystem.lean index 89a46dada7446..978141449968b 100644 --- a/Mathlib/MeasureTheory/PiSystem.lean +++ b/Mathlib/MeasureTheory/PiSystem.lean @@ -482,6 +482,8 @@ end UnionInter namespace MeasurableSpace +open scoped Function -- required for scoped `on` notation + variable {α : Type*} /-! ## Dynkin systems and Π-λ theorem -/ diff --git a/Mathlib/MeasureTheory/VectorMeasure/Basic.lean b/Mathlib/MeasureTheory/VectorMeasure/Basic.lean index c316fb186a98b..a2f2b3c39872a 100644 --- a/Mathlib/MeasureTheory/VectorMeasure/Basic.lean +++ b/Mathlib/MeasureTheory/VectorMeasure/Basic.lean @@ -46,6 +46,7 @@ noncomputable section open NNReal ENNReal MeasureTheory +open scoped Function -- required for scoped `on` notation namespace MeasureTheory variable {α β : Type*} {m : MeasurableSpace α} diff --git a/Mathlib/NumberTheory/ArithmeticFunction.lean b/Mathlib/NumberTheory/ArithmeticFunction.lean index 900057426c931..e8781f75262c5 100644 --- a/Mathlib/NumberTheory/ArithmeticFunction.lean +++ b/Mathlib/NumberTheory/ArithmeticFunction.lean @@ -568,6 +568,7 @@ theorem map_mul_of_coprime {f : ArithmeticFunction R} (hf : f.IsMultiplicative) end MonoidWithZero +open scoped Function in -- required for scoped `on` notation theorem map_prod {ι : Type*} [CommMonoidWithZero R] (g : ι → ℕ) {f : ArithmeticFunction R} (hf : f.IsMultiplicative) (s : Finset ι) (hs : (s : Set ι).Pairwise (Coprime on g)) : f (∏ i ∈ s, g i) = ∏ i ∈ s, f (g i) := by diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean index 890e52757badd..75d79867aa03b 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean @@ -38,6 +38,7 @@ section gammaSet_def /-- The set of pairs of coprime integers congruent to `a` mod `N`. -/ def gammaSet := {v : Fin 2 → ℤ | (↑) ∘ v = a ∧ IsCoprime (v 0) (v 1)} +open scoped Function in -- required for scoped `on` notation lemma pairwise_disjoint_gammaSet : Pairwise (Disjoint on gammaSet N) := by refine fun u v huv ↦ ?_ contrapose! huv diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean index 4101379ae8266..46dd10425cc97 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean @@ -979,6 +979,7 @@ theorem neg_of_mem_negA_plusPart (hx : x ∈ negAt s '' (plusPart A)) {w : {w // rw [negAt_apply_of_isReal_and_not_mem _ hw] exact hy.2 w +open scoped Function in -- required for scoped `on` notation /-- The images of `plusPart` by `negAt` are pairwise disjoint. -/ theorem disjoint_negAt_plusPart : Pairwise (Disjoint on (fun s ↦ negAt s '' (plusPart A))) := by intro s t hst diff --git a/Mathlib/Order/Disjointed.lean b/Mathlib/Order/Disjointed.lean index 766108a6dec8c..1366a858c3dcd 100644 --- a/Mathlib/Order/Disjointed.lean +++ b/Mathlib/Order/Disjointed.lean @@ -37,6 +37,8 @@ Related to the TODO in the module docstring of `Mathlib.Order.PartialSups`. variable {α : Type*} +open scoped Function -- required for scoped `on` notation + section GeneralizedBooleanAlgebra variable [GeneralizedBooleanAlgebra α] diff --git a/Mathlib/Order/Filter/Bases.lean b/Mathlib/Order/Filter/Bases.lean index 42dfb3d129084..9aeebbf245242 100644 --- a/Mathlib/Order/Filter/Bases.lean +++ b/Mathlib/Order/Filter/Bases.lean @@ -578,6 +578,7 @@ theorem _root_.Disjoint.exists_mem_filter_basis (h : Disjoint l l') (hl : l.HasB (hl' : l'.HasBasis p' s') : ∃ i, p i ∧ ∃ i', p' i' ∧ Disjoint (s i) (s' i') := (hl.disjoint_iff hl').1 h +open scoped Function in -- required for scoped `on` notation theorem _root_.Pairwise.exists_mem_filter_basis_of_disjoint {I} [Finite I] {l : I → Filter α} {ι : I → Sort*} {p : ∀ i, ι i → Prop} {s : ∀ i, ι i → Set α} (hd : Pairwise (Disjoint on l)) (h : ∀ i, (l i).HasBasis (p i) (s i)) : diff --git a/Mathlib/Order/PartialSups.lean b/Mathlib/Order/PartialSups.lean index e4d11dbda28a8..ee9a7e45473a8 100644 --- a/Mathlib/Order/PartialSups.lean +++ b/Mathlib/Order/PartialSups.lean @@ -133,6 +133,7 @@ lemma disjoint_partialSups_right [DistribLattice α] [OrderBot α] {f : ℕ → Disjoint x (partialSups f n) ↔ ∀ k ≤ n, Disjoint x (f k) := partialSups_iff_forall (Disjoint x) disjoint_sup_right +open scoped Function in -- required for scoped `on` notation /- Note this lemma requires a distributive lattice, so is not useful (or true) in situations such as submodules. -/ theorem partialSups_disjoint_of_disjoint [DistribLattice α] [OrderBot α] (f : ℕ → α) diff --git a/Mathlib/Order/SuccPred/IntervalSucc.lean b/Mathlib/Order/SuccPred/IntervalSucc.lean index 4e11847ea9a33..20b62818ae8fd 100644 --- a/Mathlib/Order/SuccPred/IntervalSucc.lean +++ b/Mathlib/Order/SuccPred/IntervalSucc.lean @@ -45,6 +45,8 @@ theorem biUnion_Ico_Ioc_map_succ [SuccOrder α] [IsSuccArchimedean α] [LinearOr · rw [hk.succ_eq, Ioc_self, empty_union] · rw [Ico_succ_right_eq_insert_of_not_isMax hmk hk, biUnion_insert] +open scoped Function -- required for scoped `on` notation + /-- If `α` is a linear succ order, `β` is a preorder, and `f : α → β` is a monotone function, then the intervals `Set.Ioc (f n) (f (Order.succ n))` are pairwise disjoint. -/ theorem pairwise_disjoint_on_Ioc_succ [SuccOrder α] [Preorder β] {f : α → β} (hf : Monotone f) : @@ -89,6 +91,8 @@ end Monotone namespace Antitone +open scoped Function -- required for scoped `on` notation + /-- If `α` is a linear succ order, `β` is a preorder, and `f : α → β` is an antitone function, then the intervals `Set.Ioc (f (Order.succ n)) (f n)` are pairwise disjoint. -/ theorem pairwise_disjoint_on_Ioc_succ [SuccOrder α] [Preorder β] {f : α → β} (hf : Antitone f) : diff --git a/Mathlib/Order/SupIndep.lean b/Mathlib/Order/SupIndep.lean index b962948122dc0..68a3a6a1f2487 100644 --- a/Mathlib/Order/SupIndep.lean +++ b/Mathlib/Order/SupIndep.lean @@ -565,6 +565,7 @@ alias setIndependent_iff_pairwiseDisjoint := sSupIndep_iff_pairwiseDisjoint alias ⟨_, _root_.Set.PairwiseDisjoint.sSupIndep⟩ := sSupIndep_iff_pairwiseDisjoint +open scoped Function in -- required for scoped `on` notation theorem iSupIndep_iff_pairwiseDisjoint {f : ι → α} : iSupIndep f ↔ Pairwise (Disjoint on f) := ⟨iSupIndep.pairwiseDisjoint, fun hs _ => disjoint_iSup_iff.2 fun _ => disjoint_iSup_iff.2 fun hij => hs hij.symm⟩ diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index 17b5c843b5ec7..5aa9a2eaa166b 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -37,6 +37,7 @@ instance : IsIrrefl α WellFoundedRelation.rel := IsAsymm.isIrrefl theorem mono (hr : WellFounded r) (h : ∀ a b, r' a b → r a b) : WellFounded r' := Subrelation.wf (h _ _) hr +open scoped Function in -- required for scoped `on` notation theorem onFun {α β : Sort*} {r : β → β → Prop} {f : α → β} : WellFounded r → WellFounded (r on f) := InvImage.wf _ diff --git a/Mathlib/Order/WellFoundedSet.lean b/Mathlib/Order/WellFoundedSet.lean index c2b623cec5ed6..b021f89341c75 100644 --- a/Mathlib/Order/WellFoundedSet.lean +++ b/Mathlib/Order/WellFoundedSet.lean @@ -46,6 +46,8 @@ Prove that `s` is partial well ordered iff it has no infinite descending chain o assert_not_exists OrderedSemiring +open scoped Function -- required for scoped `on` notation + variable {ι α β γ : Type*} {π : ι → Type*} namespace Set diff --git a/Mathlib/Probability/Kernel/Composition/Basic.lean b/Mathlib/Probability/Kernel/Composition/Basic.lean index f91eadde47725..c5cdd7bb8284a 100644 --- a/Mathlib/Probability/Kernel/Composition/Basic.lean +++ b/Mathlib/Probability/Kernel/Composition/Basic.lean @@ -77,6 +77,7 @@ We define a kernel composition-product `compProd : Kernel α β → Kernel (α × β) γ → Kernel α (β × γ)`. -/ +open scoped Function -- required for scoped `on` notation variable {γ : Type*} {mγ : MeasurableSpace γ} {s : Set (β × γ)} diff --git a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean index 3dceea49cb6c1..18477b6312708 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean @@ -576,6 +576,7 @@ lemma setLIntegral_toKernel_prod [IsFiniteKernel κ] (hf : IsCondKernelCDF f κ @[deprecated (since := "2024-06-29")] alias set_lintegral_toKernel_prod := setLIntegral_toKernel_prod +open scoped Function in -- required for scoped `on` notation lemma lintegral_toKernel_mem [IsFiniteKernel κ] (hf : IsCondKernelCDF f κ ν) (a : α) {s : Set (β × ℝ)} (hs : MeasurableSet s) : ∫⁻ b, hf.toKernel f (a, b) {y | (b, y) ∈ s} ∂(ν a) = κ a s := by diff --git a/Mathlib/Probability/Kernel/Disintegration/Density.lean b/Mathlib/Probability/Kernel/Disintegration/Density.lean index 30f8ae52d6d41..9dd84c89fa298 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Density.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Density.lean @@ -241,6 +241,7 @@ lemma setIntegral_densityProcess_of_mem (hκν : fst κ ≤ ν) [hν : IsFiniteK @[deprecated (since := "2024-04-17")] alias set_integral_densityProcess_of_mem := setIntegral_densityProcess_of_mem +open scoped Function in -- required for scoped `on` notation lemma setIntegral_densityProcess (hκν : fst κ ≤ ν) [IsFiniteKernel ν] (n : ℕ) (a : α) {s : Set β} (hs : MeasurableSet s) {A : Set γ} (hA : MeasurableSet[countableFiltration γ n] A) : diff --git a/Mathlib/Probability/StrongLaw.lean b/Mathlib/Probability/StrongLaw.lean index af74169d09b3b..0fadd8a41b7a2 100644 --- a/Mathlib/Probability/StrongLaw.lean +++ b/Mathlib/Probability/StrongLaw.lean @@ -62,6 +62,8 @@ open Set (indicator) open scoped Topology MeasureTheory ProbabilityTheory ENNReal NNReal +open scoped Function -- required for scoped `on` notation + namespace ProbabilityTheory /-! ### Prerequisites on truncations -/ diff --git a/Mathlib/RingTheory/Coprime/Lemmas.lean b/Mathlib/RingTheory/Coprime/Lemmas.lean index 0034b62252647..4ccc44de66126 100644 --- a/Mathlib/RingTheory/Coprime/Lemmas.lean +++ b/Mathlib/RingTheory/Coprime/Lemmas.lean @@ -22,6 +22,8 @@ lemmas about `Pow` since these are easiest to prove via `Finset.prod`. universe u v +open scoped Function -- required for scoped `on` notation + section IsCoprime variable {R : Type u} {I : Type v} [CommSemiring R] {x y z : R} {s : I → R} {t : Finset I} diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index 911b9158f26d5..3b8ded22c58e1 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -484,6 +484,7 @@ theorem multiset_prod_span_singleton (m : Multiset R) : Multiset.induction_on m (by simp) fun a m ih => by simp only [Multiset.map_cons, Multiset.prod_cons, ih, ← Ideal.span_singleton_mul_span_singleton] +open scoped Function in -- required for scoped `on` notation theorem finset_inf_span_singleton {ι : Type*} (s : Finset ι) (I : ι → R) (hI : Set.Pairwise (↑s) (IsCoprime on I)) : (s.inf fun i => Ideal.span ({I i} : Set R)) = Ideal.span {∏ i ∈ s, I i} := by diff --git a/Mathlib/RingTheory/Lasker.lean b/Mathlib/RingTheory/Lasker.lean index fc3785bfee908..77388bde77b56 100644 --- a/Mathlib/RingTheory/Lasker.lean +++ b/Mathlib/RingTheory/Lasker.lean @@ -55,6 +55,8 @@ lemma decomposition_erase_inf [DecidableEq (Ideal R)] {I : Ideal R} rw [← Finset.insert_erase hJ] at hs simp [← hs, hJ'] +open scoped Function -- required for scoped `on` notation + lemma isPrimary_decomposition_pairwise_ne_radical {I : Ideal R} {s : Finset (Ideal R)} (hs : s.inf id = I) (hs' : ∀ ⦃J⦄, J ∈ s → J.IsPrimary) : ∃ t : Finset (Ideal R), t.inf id = I ∧ (∀ ⦃J⦄, J ∈ t → J.IsPrimary) ∧ diff --git a/Mathlib/Topology/MetricSpace/Thickening.lean b/Mathlib/Topology/MetricSpace/Thickening.lean index 8ef9ed0bb9255..67b4aa3b257bc 100644 --- a/Mathlib/Topology/MetricSpace/Thickening.lean +++ b/Mathlib/Topology/MetricSpace/Thickening.lean @@ -99,6 +99,7 @@ theorem frontier_thickening_subset (E : Set α) {δ : ℝ} : frontier (thickening δ E) ⊆ { x : α | infEdist x E = ENNReal.ofReal δ } := frontier_lt_subset_eq continuous_infEdist continuous_const +open scoped Function in -- required for scoped `on` notation theorem frontier_thickening_disjoint (A : Set α) : Pairwise (Disjoint on fun r : ℝ => frontier (thickening r A)) := by refine (pairwise_disjoint_on _).2 fun r₁ r₂ hr => ?_ @@ -622,6 +623,7 @@ theorem cthickening_cthickening_subset (hε : 0 ≤ ε) (hδ : 0 ≤ δ) (s : Se simp_rw [mem_cthickening_iff, ENNReal.ofReal_add hε hδ] exact fun hx => infEdist_le_infEdist_cthickening_add.trans (add_le_add_right hx _) +open scoped Function in -- required for scoped `on` notation theorem frontier_cthickening_disjoint (A : Set α) : Pairwise (Disjoint on fun r : ℝ≥0 => frontier (cthickening r A)) := fun r₁ r₂ hr => ((disjoint_singleton.2 <| by simpa).preimage _).mono (frontier_cthickening_subset _) From 1b8352c6fa61f319be6448e02fd4e7255067cb57 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 8 Jan 2025 04:31:39 +0000 Subject: [PATCH 071/681] feat(Combinatorics/SimpleGraph): add lemmas about `spanningCoe` (#19377) Add some small lemma's supporting `Subgraph.spanningCoe` `SimpleGraph.adj_iff_of_sym2_eq` is currently unused, but added for symmetry with the `Subgraph` API. In preparation for Tutte's theorem. Co-authored-by: Pim Otte --- Mathlib/Combinatorics/SimpleGraph/Basic.lean | 6 ++++++ Mathlib/Combinatorics/SimpleGraph/Operations.lean | 10 ++++++++++ Mathlib/Combinatorics/SimpleGraph/Subgraph.lean | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/Mathlib/Combinatorics/SimpleGraph/Basic.lean b/Mathlib/Combinatorics/SimpleGraph/Basic.lean index fbf6473d0fddf..0c0f567f36892 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Basic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Basic.lean @@ -197,6 +197,12 @@ theorem adj_injective : Injective (Adj : SimpleGraph V → V → V → Prop) := theorem adj_inj {G H : SimpleGraph V} : G.Adj = H.Adj ↔ G = H := adj_injective.eq_iff +theorem adj_congr_of_sym2 {u v w x : V} (h : s(u, v) = s(w, x)) : G.Adj u v ↔ G.Adj w x := by + simp only [Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk] at h + cases' h with hl hr + · rw [hl.1, hl.2] + · rw [hr.1, hr.2, adj_comm] + section Order /-- The relation that one `SimpleGraph` is a subgraph of another. diff --git a/Mathlib/Combinatorics/SimpleGraph/Operations.lean b/Mathlib/Combinatorics/SimpleGraph/Operations.lean index fea650ca66f09..4af95c2d77aa8 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Operations.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Operations.lean @@ -5,6 +5,7 @@ Authors: Jeremy Tan -/ import Mathlib.Combinatorics.SimpleGraph.Finite import Mathlib.Combinatorics.SimpleGraph.Maps +import Mathlib.Combinatorics.SimpleGraph.Subgraph /-! # Local graph operations @@ -168,6 +169,15 @@ lemma sup_edge_of_adj (h : G.Adj s t) : G ⊔ edge s t = G := by rwa [sup_eq_left, ← edgeSet_subset_edgeSet, edge_edgeSet_of_ne h.ne, Set.singleton_subset_iff, mem_edgeSet] +theorem Subgraph.spanningCoe_sup_edge_le {H : Subgraph (G ⊔ edge s t)} (h : ¬ H.Adj s t) : + H.spanningCoe ≤ G := by + intro v w hvw + have := hvw.adj_sub + simp only [Subgraph.spanningCoe_adj, SimpleGraph.sup_adj, SimpleGraph.edge_adj] at * + by_cases hs : s(v, w) = s(s, t) + · exact (h ((Subgraph.adj_congr_of_sym2 hs).mp hvw)).elim + · aesop + variable [Fintype V] [DecidableRel G.Adj] variable [DecidableEq V] in diff --git a/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean b/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean index 3ee260f7663ee..87264b888eb6b 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean @@ -118,6 +118,13 @@ protected theorem Adj.snd_mem {H : G.Subgraph} {u v : V} (h : H.Adj u v) : v ∈ protected theorem Adj.ne {H : G.Subgraph} {u v : V} (h : H.Adj u v) : u ≠ v := h.adj_sub.ne +theorem adj_congr_of_sym2 {H : G.Subgraph} {u v w x : V} (h2 : s(u, v) = s(w, x)) : + H.Adj u v ↔ H.Adj w x := by + simp only [Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk] at h2 + cases' h2 with hl hr + · rw [hl.1, hl.2] + · rw [hr.1, hr.2, Subgraph.adj_comm] + /-- Coercion from `G' : Subgraph G` to a `SimpleGraph G'.verts`. -/ @[simps] protected def coe (G' : Subgraph G) : SimpleGraph G'.verts where @@ -164,6 +171,9 @@ lemma spanningCoe_le (G' : G.Subgraph) : G'.spanningCoe ≤ G := fun _ _ ↦ G'. theorem spanningCoe_inj : G₁.spanningCoe = G₂.spanningCoe ↔ G₁.Adj = G₂.Adj := by simp [Subgraph.spanningCoe] +lemma mem_of_adj_spanningCoe {v w : V} {s : Set V} (G : SimpleGraph s) + (hadj : G.spanningCoe.Adj v w) : v ∈ s := by aesop + /-- `spanningCoe` is equivalent to `coe` for a subgraph that `IsSpanning`. -/ @[simps] def spanningCoeEquivCoeOfSpanning (G' : Subgraph G) (h : G'.IsSpanning) : From d9a8247d4ad6f06800779c62c2e0807ba7f62920 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 8 Jan 2025 04:40:49 +0000 Subject: [PATCH 072/681] feat(Combinatorics/SimpleGraph/Path): add `IsPath.getVert_injOn` (#19373) Add lemma on injectivity of getVert for the indices that are in range. In preparation for Tutte's theorem. Co-authored-by: Pim Otte --- Mathlib/Combinatorics/SimpleGraph/Path.lean | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Mathlib/Combinatorics/SimpleGraph/Path.lean b/Mathlib/Combinatorics/SimpleGraph/Path.lean index e95e8857cb5e8..25c395c316dff 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Path.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Path.lean @@ -275,6 +275,26 @@ theorem IsPath.length_lt [Fintype V] {u v : V} {p : G.Walk u v} (hp : p.IsPath) rw [Nat.lt_iff_add_one_le, ← length_support] exact hp.support_nodup.length_le_card +lemma IsPath.getVert_injOn {p : G.Walk u v} (hp : p.IsPath) : + Set.InjOn p.getVert {i | i ≤ p.length} := by + intro n hn m hm hnm + induction p generalizing n m with + | nil => aesop + | @cons v w u h p ihp => + simp only [length_cons, Set.mem_setOf_eq] at hn hm hnm + by_cases hn0 : n = 0 <;> by_cases hm0 : m = 0 + · aesop + · simp only [hn0, getVert_zero, Walk.getVert_cons p h hm0] at hnm + have hvp : v ∉ p.support := by aesop + exact (hvp (Walk.mem_support_iff_exists_getVert.mpr ⟨(m - 1), ⟨hnm.symm, by omega⟩⟩)).elim + · simp only [hm0, Walk.getVert_cons p h hn0] at hnm + have hvp : v ∉ p.support := by aesop + exact (hvp (Walk.mem_support_iff_exists_getVert.mpr ⟨(n - 1), ⟨hnm, by omega⟩⟩)).elim + · simp only [Walk.getVert_cons _ _ hn0, Walk.getVert_cons _ _ hm0] at hnm + have := ihp hp.of_cons (by omega : (n - 1) ≤ p.length) + (by omega : (m - 1) ≤ p.length) hnm + omega + /-! ### Walk decompositions -/ section WalkDecomp From 4c753371a86392b66628ebe5dcc2aaad7d3a1631 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Wed, 8 Jan 2025 05:27:12 +0000 Subject: [PATCH 073/681] chore(Algebra/Lie): make IsNilpotent and IsSolvable independent of scalars (#20556) --- Mathlib/Algebra/Lie/Basic.lean | 6 +- Mathlib/Algebra/Lie/CartanSubalgebra.lean | 10 +- Mathlib/Algebra/Lie/Engel.lean | 28 +-- Mathlib/Algebra/Lie/EngelSubalgebra.lean | 4 +- Mathlib/Algebra/Lie/IdealOperations.lean | 11 +- Mathlib/Algebra/Lie/LieTheorem.lean | 4 +- Mathlib/Algebra/Lie/Nilpotent.lean | 251 ++++++++++++++-------- Mathlib/Algebra/Lie/Semisimple/Basic.lean | 10 +- Mathlib/Algebra/Lie/Solvable.lean | 120 ++++++++--- Mathlib/Algebra/Lie/TraceForm.lean | 12 +- Mathlib/Algebra/Lie/Weights/Basic.lean | 23 +- Mathlib/Algebra/Lie/Weights/Cartan.lean | 6 +- Mathlib/Algebra/Lie/Weights/Chain.lean | 8 +- Mathlib/Algebra/Lie/Weights/Linear.lean | 18 +- 14 files changed, 311 insertions(+), 200 deletions(-) diff --git a/Mathlib/Algebra/Lie/Basic.lean b/Mathlib/Algebra/Lie/Basic.lean index 8c75a9021fe88..7a022b824e648 100644 --- a/Mathlib/Algebra/Lie/Basic.lean +++ b/Mathlib/Algebra/Lie/Basic.lean @@ -200,13 +200,11 @@ theorem lie_nsmul (n : ℕ) : ⁅x, n • m⁆ = n • ⁅x, m⁆ := { toFun := fun m : M => ⁅x, m⁆, map_zero' := lie_zero x, map_add' := fun _ _ => lie_add _ _ _} _ _ -@[simp] theorem zsmul_lie (a : ℤ) : ⁅a • x, m⁆ = a • ⁅x, m⁆ := AddMonoidHom.map_zsmul { toFun := fun x : L => ⁅x, m⁆, map_zero' := zero_lie m, map_add' := fun _ _ => add_lie _ _ _ } _ _ -@[simp] theorem lie_zsmul (a : ℤ) : ⁅x, a • m⁆ = a • ⁅x, m⁆ := AddMonoidHom.map_zsmul { toFun := fun m : M => ⁅x, m⁆, map_zero' := lie_zero x, map_add' := fun _ _ => lie_add _ _ _ } @@ -221,6 +219,10 @@ theorem lie_jacobi : ⁅x, ⁅y, z⁆⁆ + ⁅y, ⁅z, x⁆⁆ + ⁅z, ⁅x, y instance LieRing.instLieAlgebra : LieAlgebra ℤ L where lie_smul n x y := lie_zsmul x y n +instance : LieModule ℤ L M where + smul_lie n x m := zsmul_lie x m n + lie_smul n x m := lie_zsmul x m n + instance LinearMap.instLieRingModule : LieRingModule L (M →ₗ[R] N) where bracket x f := { toFun := fun m => ⁅x, f m⁆ - f ⁅x, m⁆ diff --git a/Mathlib/Algebra/Lie/CartanSubalgebra.lean b/Mathlib/Algebra/Lie/CartanSubalgebra.lean index cfe41bd7c8bfd..1887a29efd5ca 100644 --- a/Mathlib/Algebra/Lie/CartanSubalgebra.lean +++ b/Mathlib/Algebra/Lie/CartanSubalgebra.lean @@ -44,10 +44,10 @@ namespace LieSubalgebra A _splitting_ Cartan subalgebra can be defined by mixing in `LieModule.IsTriangularizable R H L`. -/ class IsCartanSubalgebra : Prop where - nilpotent : LieAlgebra.IsNilpotent R H + nilpotent : LieRing.IsNilpotent H self_normalizing : H.normalizer = H -instance [H.IsCartanSubalgebra] : LieAlgebra.IsNilpotent R H := +instance [H.IsCartanSubalgebra] : LieRing.IsNilpotent H := IsCartanSubalgebra.nilpotent @[simp] @@ -66,7 +66,7 @@ theorem ucs_eq_self_of_isCartanSubalgebra (H : LieSubalgebra R L) [H.IsCartanSub theorem isCartanSubalgebra_iff_isUcsLimit : H.IsCartanSubalgebra ↔ H.toLieSubmodule.IsUcsLimit := by constructor · intro h - have h₁ : LieAlgebra.IsNilpotent R H := by infer_instance + have h₁ : LieRing.IsNilpotent H := by infer_instance obtain ⟨k, hk⟩ := H.toLieSubmodule.isNilpotent_iff_exists_self_le_ucs.mp h₁ replace hk : H.toLieSubmodule = LieSubmodule.ucs k ⊥ := le_antisymm hk @@ -77,7 +77,7 @@ theorem isCartanSubalgebra_iff_isUcsLimit : H.IsCartanSubalgebra ↔ H.toLieSubm · rintro ⟨k, hk⟩ exact { nilpotent := by - dsimp only [LieAlgebra.IsNilpotent] + dsimp only [LieRing.IsNilpotent] erw [H.toLieSubmodule.isNilpotent_iff_exists_lcs_eq_bot] use k rw [_root_.eq_bot_iff, LieSubmodule.lcs_le_iff, hk k (le_refl k)] @@ -113,7 +113,7 @@ theorem LieIdeal.normalizer_eq_top {R : Type u} {L : Type v} [CommRing R] [LieRi open LieIdeal /-- A nilpotent Lie algebra is its own Cartan subalgebra. -/ -instance LieAlgebra.top_isCartanSubalgebra_of_nilpotent [LieAlgebra.IsNilpotent R L] : +instance LieAlgebra.top_isCartanSubalgebra_of_nilpotent [LieRing.IsNilpotent L] : LieSubalgebra.IsCartanSubalgebra (⊤ : LieSubalgebra R L) where nilpotent := inferInstance self_normalizing := by rw [← top_toLieSubalgebra, normalizer_eq_top, top_toLieSubalgebra] diff --git a/Mathlib/Algebra/Lie/Engel.lean b/Mathlib/Algebra/Lie/Engel.lean index 4380e2dd3aef3..1ce0e3176e8a1 100644 --- a/Mathlib/Algebra/Lie/Engel.lean +++ b/Mathlib/Algebra/Lie/Engel.lean @@ -124,12 +124,13 @@ theorem lcs_le_lcs_of_is_nilpotent_span_sup_eq_top {n i j : ℕ} exact antitone_lowerCentralSeries R L M le_self_add theorem isNilpotentOfIsNilpotentSpanSupEqTop (hnp : IsNilpotent <| toEnd R L M x) - (hIM : IsNilpotent R I M) : IsNilpotent R L M := by + (hIM : IsNilpotent I M) : IsNilpotent L M := by obtain ⟨n, hn⟩ := hnp - obtain ⟨k, hk⟩ := hIM + obtain ⟨k, hk⟩ := IsNilpotent.nilpotent R I M have hk' : I.lcs M k = ⊥ := by simp only [← toSubmodule_inj, I.coe_lcs_eq, hk, bot_toSubmodule] suffices ∀ l, lowerCentralSeries R L M (l * n) ≤ I.lcs M l by + rw [isNilpotent_iff R] use k * n simpa [hk'] using this k intro l @@ -154,15 +155,14 @@ Engel's theorem `LieAlgebra.isEngelian_of_isNoetherian` states that any Noetheri Engelian. -/ def LieAlgebra.IsEngelian : Prop := ∀ (M : Type u₄) [AddCommGroup M] [Module R M] [LieRingModule L M] [LieModule R L M], - (∀ x : L, _root_.IsNilpotent (toEnd R L M x)) → LieModule.IsNilpotent R L M + (∀ x : L, _root_.IsNilpotent (toEnd R L M x)) → LieModule.IsNilpotent L M variable {R L} theorem LieAlgebra.isEngelian_of_subsingleton [Subsingleton L] : LieAlgebra.IsEngelian R L := by intro M _i1 _i2 _i3 _i4 _h use 1 - suffices (⊤ : LieIdeal R L) = ⊥ by simp [this] - subsingleton [(LieSubmodule.subsingleton_iff R L L).mpr inferInstance] + simp theorem Function.Surjective.isEngelian {f : L →ₗ⁅R⁆ L₂} (hf : Function.Surjective f) (h : LieAlgebra.IsEngelian.{u₁, u₂, u₄} R L) : LieAlgebra.IsEngelian.{u₁, u₃, u₄} R L₂ := by @@ -171,7 +171,7 @@ theorem Function.Surjective.isEngelian {f : L →ₗ⁅R⁆ L₂} (hf : Function letI : LieModule R L M := compLieHom M f have hnp : ∀ x, IsNilpotent (toEnd R L M x) := fun x => h' (f x) have surj_id : Function.Surjective (LinearMap.id : M →ₗ[R] M) := Function.surjective_id - haveI : LieModule.IsNilpotent R L M := h M hnp + haveI : LieModule.IsNilpotent L M := h M hnp apply hf.lieModuleIsNilpotent surj_id -- Porting note (https://github.com/leanprover-community/mathlib4/issues/10745): was `simp` intros; simp only [LinearMap.id_coe, id_eq]; rfl @@ -218,16 +218,16 @@ Note that this implies all traditional forms of Engel's theorem via `LieAlgebra.isNilpotent_iff_forall`. -/ theorem LieAlgebra.isEngelian_of_isNoetherian [IsNoetherian R L] : LieAlgebra.IsEngelian R L := by intro M _i1 _i2 _i3 _i4 h - rw [← isNilpotent_range_toEnd_iff] + rw [← isNilpotent_range_toEnd_iff R] let L' := (toEnd R L M).range replace h : ∀ y : L', _root_.IsNilpotent (y : Module.End R M) := by rintro ⟨-, ⟨y, rfl⟩⟩ simp [h] - change LieModule.IsNilpotent R L' M + change LieModule.IsNilpotent L' M let s := {K : LieSubalgebra R L' | LieAlgebra.IsEngelian R K} have hs : s.Nonempty := ⟨⊥, LieAlgebra.isEngelian_of_subsingleton⟩ suffices ⊤ ∈ s by - rw [← isNilpotent_of_top_iff] + rw [← isNilpotent_of_top_iff (R := R)] apply this M simp [LieSubalgebra.toEnd_eq, h] have : ∀ K ∈ s, K ≠ ⊤ → ∃ K' ∈ s, K < K' := by @@ -242,7 +242,7 @@ theorem LieAlgebra.isEngelian_of_isNoetherian [IsNoetherian R L] : LieAlgebra.Is LieSubmodule.top_toSubmodule, ← LieSubalgebra.top_toSubmodule, K.toSubmodule_inj] exact Submodule.Quotient.nontrivial_of_lt_top _ hK₂.lt_top - have : LieModule.IsNilpotent R K (L' ⧸ K.toLieSubmodule) := by + have : LieModule.IsNilpotent K (L' ⧸ K.toLieSubmodule) := by -- Porting note: was refine' hK₁ _ fun x => _ apply hK₁ intro x @@ -274,18 +274,18 @@ theorem LieAlgebra.isEngelian_of_isNoetherian [IsNoetherian R L] : LieAlgebra.Is See also `LieModule.isNilpotent_iff_forall'` which assumes that `M` is Noetherian instead of `L`. -/ theorem LieModule.isNilpotent_iff_forall [IsNoetherian R L] : - LieModule.IsNilpotent R L M ↔ ∀ x, _root_.IsNilpotent <| toEnd R L M x := + LieModule.IsNilpotent L M ↔ ∀ x, _root_.IsNilpotent <| toEnd R L M x := ⟨fun _ ↦ isNilpotent_toEnd_of_isNilpotent R L M, fun h => LieAlgebra.isEngelian_of_isNoetherian M h⟩ /-- Engel's theorem. -/ theorem LieModule.isNilpotent_iff_forall' [IsNoetherian R M] : - LieModule.IsNilpotent R L M ↔ ∀ x, _root_.IsNilpotent <| toEnd R L M x := by - rw [← isNilpotent_range_toEnd_iff, LieModule.isNilpotent_iff_forall]; simp + LieModule.IsNilpotent L M ↔ ∀ x, _root_.IsNilpotent <| toEnd R L M x := by + rw [← isNilpotent_range_toEnd_iff (R := R), LieModule.isNilpotent_iff_forall (R := R)]; simp /-- Engel's theorem. -/ theorem LieAlgebra.isNilpotent_iff_forall [IsNoetherian R L] : - LieAlgebra.IsNilpotent R L ↔ ∀ x, _root_.IsNilpotent <| LieAlgebra.ad R L x := + LieRing.IsNilpotent L ↔ ∀ x, _root_.IsNilpotent <| LieAlgebra.ad R L x := LieModule.isNilpotent_iff_forall end LieAlgebra diff --git a/Mathlib/Algebra/Lie/EngelSubalgebra.lean b/Mathlib/Algebra/Lie/EngelSubalgebra.lean index e011fcd6e98b4..65e5d19fc51f3 100644 --- a/Mathlib/Algebra/Lie/EngelSubalgebra.lean +++ b/Mathlib/Algebra/Lie/EngelSubalgebra.lean @@ -143,8 +143,8 @@ lemma normalizer_eq_self_of_engel_le [IsArtinian R L] if it is contained in the Engel subalgebra of all its elements. -/ lemma isNilpotent_of_forall_le_engel [IsNoetherian R L] (H : LieSubalgebra R L) (h : ∀ x ∈ H, H ≤ engel R x) : - LieAlgebra.IsNilpotent R H := by - rw [LieAlgebra.isNilpotent_iff_forall] + LieRing.IsNilpotent H := by + rw [LieAlgebra.isNilpotent_iff_forall (R := R)] intro x let K : ℕ →o Submodule R H := ⟨fun n ↦ LinearMap.ker ((ad R H x) ^ n), fun m n hmn ↦ ?mono⟩ diff --git a/Mathlib/Algebra/Lie/IdealOperations.lean b/Mathlib/Algebra/Lie/IdealOperations.lean index aae8ed34539a5..73180718964b1 100644 --- a/Mathlib/Algebra/Lie/IdealOperations.lean +++ b/Mathlib/Algebra/Lie/IdealOperations.lean @@ -69,19 +69,18 @@ variable [LieAlgebra R L] [LieModule R L M₂] (I J : LieIdeal R L) /-- Given a Lie module `M` over a Lie algebra `L`, the set of Lie ideals of `L` acts on the set of submodules of `M`. -/ instance hasBracket : Bracket (LieIdeal R L) (LieSubmodule R L M) := - ⟨fun I N => lieSpan R L { m | ∃ (x : I) (n : N), ⁅(x : L), (n : M)⁆ = m }⟩ + ⟨fun I N => lieSpan R L { ⁅(x : L), (n : M)⁆ | (x : I) (n : N) }⟩ theorem lieIdeal_oper_eq_span : - ⁅I, N⁆ = lieSpan R L { m | ∃ (x : I) (n : N), ⁅(x : L), (n : M)⁆ = m } := + ⁅I, N⁆ = lieSpan R L { ⁅(x : L), (n : M)⁆ | (x : I) (n : N) } := rfl /-- See also `LieSubmodule.lieIdeal_oper_eq_linear_span'` and `LieSubmodule.lieIdeal_oper_eq_tensor_map_range`. -/ theorem lieIdeal_oper_eq_linear_span [LieModule R L M] : - (↑⁅I, N⁆ : Submodule R M) = - Submodule.span R { m | ∃ (x : I) (n : N), ⁅(x : L), (n : M)⁆ = m } := by + (↑⁅I, N⁆ : Submodule R M) = Submodule.span R { ⁅(x : L), (n : M)⁆ | (x : I) (n : N) } := by apply le_antisymm - · let s := { m : M | ∃ (x : ↥I) (n : ↥N), ⁅(x : L), (n : M)⁆ = m } + · let s := { ⁅(x : L), (n : M)⁆ | (x : I) (n : N) } have aux : ∀ (y : L), ∀ m' ∈ Submodule.span R s, ⁅y, m'⁆ ∈ Submodule.span R s := by intro y m' hm' refine Submodule.span_induction (R := R) (M := M) (s := s) @@ -99,7 +98,7 @@ theorem lieIdeal_oper_eq_linear_span [LieModule R L M] : · rw [lieIdeal_oper_eq_span]; apply submodule_span_le_lieSpan theorem lieIdeal_oper_eq_linear_span' [LieModule R L M] : - (↑⁅I, N⁆ : Submodule R M) = Submodule.span R { m | ∃ x ∈ I, ∃ n ∈ N, ⁅x, n⁆ = m } := by + (↑⁅I, N⁆ : Submodule R M) = Submodule.span R { ⁅x, n⁆ | (x ∈ I) (n ∈ N) } := by rw [lieIdeal_oper_eq_linear_span] congr ext m diff --git a/Mathlib/Algebra/Lie/LieTheorem.lean b/Mathlib/Algebra/Lie/LieTheorem.lean index a9e21ea679bd7..b9df89d846f10 100644 --- a/Mathlib/Algebra/Lie/LieTheorem.lean +++ b/Mathlib/Algebra/Lie/LieTheorem.lean @@ -204,7 +204,7 @@ open LieAlgebra -- except that it additionally assumes a finiteness hypothesis. private lemma exists_forall_lie_eq_smul_of_isSolvable_of_finite (L : Type*) [LieRing L] [LieAlgebra k L] [LieRingModule L V] [LieModule k L V] - [IsSolvable k L] [LieModule.IsTriangularizable k L V] [Module.Finite k L] : + [IsSolvable L] [LieModule.IsTriangularizable k L V] [Module.Finite k L] : ∃ χ : Module.Dual k L, Nontrivial (weightSpace V χ) := by obtain H|⟨A, hA, hAL⟩ := eq_top_or_exists_le_coatom (derivedSeries k L 1).toSubmodule · obtain _|_ := subsingleton_or_nontrivial L @@ -231,7 +231,7 @@ have a common eigenvector for the action of all elements of the Lie algebra. See `LieModule.exists_nontrivial_weightSpace_of_isNilpotent` for the variant that assumes that `L` is nilpotent and drops the condition that `k` is of characteristic zero. -/ theorem exists_nontrivial_weightSpace_of_isSolvable - [IsSolvable k L] [LieModule.IsTriangularizable k L V] : + [IsSolvable L] [LieModule.IsTriangularizable k L V] : ∃ χ : Module.Dual k L, Nontrivial (weightSpace V χ) := by let imL := (toEnd k L V).range let toEndo : L →ₗ[k] imL := LinearMap.codRestrict imL.toSubmodule (toEnd k L V) diff --git a/Mathlib/Algebra/Lie/Nilpotent.lean b/Mathlib/Algebra/Lie/Nilpotent.lean index c87b73a148611..4e19fe0b77a4d 100644 --- a/Mathlib/Algebra/Lie/Nilpotent.lean +++ b/Mathlib/Algebra/Lie/Nilpotent.lean @@ -88,6 +88,39 @@ theorem lowerCentralSeries_succ : lowerCentralSeries R L M (k + 1) = ⁅(⊤ : LieIdeal R L), lowerCentralSeries R L M k⁆ := (⊤ : LieSubmodule R L M).lcs_succ k +private theorem coe_lowerCentralSeries_eq_int_aux (R₁ R₂ L M : Type*) + [CommRing R₁] [CommRing R₂] [AddCommGroup M] + [LieRing L] [LieAlgebra R₁ L] [LieAlgebra R₂ L] [Module R₁ M] [Module R₂ M] [LieRingModule L M] + [LieModule R₁ L M] (k : ℕ) : + let I := lowerCentralSeries R₂ L M k; let S : Set M := {⁅a, b⁆ | (a : L) (b ∈ I)} + (Submodule.span R₁ S : Set M) ≤ (Submodule.span R₂ S : Set M) := by + intro I S x hx + simp only [SetLike.mem_coe] at hx ⊢ + induction hx using Submodule.closure_induction with + | zero => exact Submodule.zero_mem _ + | add y z hy₁ hz₁ hy₂ hz₂ => exact Submodule.add_mem _ hy₂ hz₂ + | smul_mem c y hy => + obtain ⟨a, b, hb, rfl⟩ := hy + rw [← smul_lie] + exact Submodule.subset_span ⟨c • a, b, hb, rfl⟩ + +theorem coe_lowerCentralSeries_eq_int [LieModule R L M] (k : ℕ) : + (lowerCentralSeries R L M k : Set M) = (lowerCentralSeries ℤ L M k : Set M) := by + show ((lowerCentralSeries R L M k).toSubmodule : Set M) = + ((lowerCentralSeries ℤ L M k).toSubmodule : Set M) + induction k with + | zero => rfl + | succ k ih => + rw [lowerCentralSeries_succ, lowerCentralSeries_succ] + rw [LieSubmodule.lieIdeal_oper_eq_linear_span', LieSubmodule.lieIdeal_oper_eq_linear_span'] + rw [Set.ext_iff] at ih + simp only [SetLike.mem_coe, LieSubmodule.mem_toSubmodule] at ih + simp only [LieSubmodule.mem_top, ih, true_and] + apply le_antisymm + · exact coe_lowerCentralSeries_eq_int_aux _ _ L M k + · simp only [← ih] + exact coe_lowerCentralSeries_eq_int_aux _ _ L M k + end LieModule namespace LieSubmodule @@ -217,56 +250,73 @@ theorem derivedSeries_le_lowerCentralSeries (k : ℕ) : /-- A Lie module is nilpotent if its lower central series reaches 0 (in a finite number of steps). -/ +@[mk_iff isNilpotent_iff_int] class IsNilpotent : Prop where - nilpotent : ∃ k, lowerCentralSeries R L M k = ⊥ + mk_int :: + nilpotent_int : ∃ k, lowerCentralSeries ℤ L M k = ⊥ + +section + +variable [LieModule R L M] + +/-- See also `LieModule.isNilpotent_iff_exists_ucs_eq_top`. -/ +lemma isNilpotent_iff : + IsNilpotent L M ↔ ∃ k, lowerCentralSeries R L M k = ⊥ := by + simp [isNilpotent_iff_int, SetLike.ext'_iff, coe_lowerCentralSeries_eq_int R L M] -theorem exists_lowerCentralSeries_eq_bot_of_isNilpotent [IsNilpotent R L M] : +lemma IsNilpotent.nilpotent [IsNilpotent L M] : ∃ k, lowerCentralSeries R L M k = ⊥ := + (isNilpotent_iff R L M).mp ‹_› + +variable {R L} in +lemma IsNilpotent.mk {k : ℕ} (h : lowerCentralSeries R L M k = ⊥) : IsNilpotent L M := + (isNilpotent_iff R L M).mpr ⟨k, h⟩ + +@[deprecated IsNilpotent.nilpotent (since := "2025-01-07")] +theorem exists_lowerCentralSeries_eq_bot_of_isNilpotent [IsNilpotent L M] : ∃ k, lowerCentralSeries R L M k = ⊥ := - IsNilpotent.nilpotent + IsNilpotent.nilpotent R L M -@[simp] lemma iInf_lowerCentralSeries_eq_bot_of_isNilpotent [IsNilpotent R L M] : +@[simp] lemma iInf_lowerCentralSeries_eq_bot_of_isNilpotent [IsNilpotent L M] : ⨅ k, lowerCentralSeries R L M k = ⊥ := by - obtain ⟨k, hk⟩ := exists_lowerCentralSeries_eq_bot_of_isNilpotent R L M + obtain ⟨k, hk⟩ := IsNilpotent.nilpotent R L M rw [eq_bot_iff, ← hk] exact iInf_le _ _ -/-- See also `LieModule.isNilpotent_iff_exists_ucs_eq_top`. -/ -theorem isNilpotent_iff : IsNilpotent R L M ↔ ∃ k, lowerCentralSeries R L M k = ⊥ := - ⟨fun h => h.nilpotent, fun h => ⟨h⟩⟩ +end section variable {R L M} variable [LieModule R L M] theorem _root_.LieSubmodule.isNilpotent_iff_exists_lcs_eq_bot (N : LieSubmodule R L M) : - LieModule.IsNilpotent R L N ↔ ∃ k, N.lcs k = ⊥ := by - rw [isNilpotent_iff] + LieModule.IsNilpotent L N ↔ ∃ k, N.lcs k = ⊥ := by + rw [isNilpotent_iff R L N] refine exists_congr fun k => ?_ rw [N.lowerCentralSeries_eq_lcs_comap k, LieSubmodule.comap_incl_eq_bot, inf_eq_right.mpr (N.lcs_le_self k)] variable (R L M) -instance (priority := 100) trivialIsNilpotent [IsTrivial L M] : IsNilpotent R L M := +instance (priority := 100) trivialIsNilpotent [IsTrivial L M] : IsNilpotent L M := ⟨by use 1; change ⁅⊤, ⊤⁆ = ⊥; simp⟩ -theorem exists_forall_pow_toEnd_eq_zero [hM : IsNilpotent R L M] : +theorem exists_forall_pow_toEnd_eq_zero [IsNilpotent L M] : ∃ k : ℕ, ∀ x : L, toEnd R L M x ^ k = 0 := by - obtain ⟨k, hM⟩ := hM + obtain ⟨k, hM⟩ := IsNilpotent.nilpotent R L M use k intro x; ext m rw [LinearMap.pow_apply, LinearMap.zero_apply, ← @LieSubmodule.mem_bot R L M, ← hM] exact iterate_toEnd_mem_lowerCentralSeries R L M x m k -theorem isNilpotent_toEnd_of_isNilpotent [IsNilpotent R L M] (x : L) : +theorem isNilpotent_toEnd_of_isNilpotent [IsNilpotent L M] (x : L) : _root_.IsNilpotent (toEnd R L M x) := by change ∃ k, toEnd R L M x ^ k = 0 have := exists_forall_pow_toEnd_eq_zero R L M tauto -theorem isNilpotent_toEnd_of_isNilpotent₂ [IsNilpotent R L M] (x y : L) : +theorem isNilpotent_toEnd_of_isNilpotent₂ [IsNilpotent L M] (x y : L) : _root_.IsNilpotent (toEnd R L M x ∘ₗ toEnd R L M y) := by - obtain ⟨k, hM⟩ := exists_lowerCentralSeries_eq_bot_of_isNilpotent R L M + obtain ⟨k, hM⟩ := IsNilpotent.nilpotent R L M replace hM : lowerCentralSeries R L M (2 * k) = ⊥ := by rw [eq_bot_iff, ← hM]; exact antitone_lowerCentralSeries R L M (by omega) use k @@ -274,7 +324,7 @@ theorem isNilpotent_toEnd_of_isNilpotent₂ [IsNilpotent R L M] (x y : L) : rw [LinearMap.pow_apply, LinearMap.zero_apply, ← LieSubmodule.mem_bot (R := R) (L := L), ← hM] exact iterate_toEnd_mem_lowerCentralSeries₂ R L M x y m k -@[simp] lemma maxGenEigenSpace_toEnd_eq_top [IsNilpotent R L M] (x : L) : +@[simp] lemma maxGenEigenSpace_toEnd_eq_top [IsNilpotent L M] (x : L) : ((toEnd R L M x).maxGenEigenspace 0) = ⊤ := by ext m simp only [Module.End.mem_maxGenEigenspace, zero_smul, sub_zero, Submodule.mem_top, @@ -289,7 +339,8 @@ This is essentially the Lie module equivalent of the fact that a central extension of nilpotent Lie algebras is nilpotent. See `LieAlgebra.nilpotent_of_nilpotent_quotient` below for the corresponding result for Lie algebras. -/ theorem nilpotentOfNilpotentQuotient {N : LieSubmodule R L M} (h₁ : N ≤ maxTrivSubmodule R L M) - (h₂ : IsNilpotent R L (M ⧸ N)) : IsNilpotent R L M := by + (h₂ : IsNilpotent L (M ⧸ N)) : IsNilpotent L M := by + rw [isNilpotent_iff R L] at h₂ ⊢ obtain ⟨k, hk⟩ := h₂ use k + 1 simp only [lowerCentralSeries_succ] @@ -300,13 +351,13 @@ theorem nilpotentOfNilpotentQuotient {N : LieSubmodule R L M} (h₁ : N ≤ maxT exact map_lowerCentralSeries_le k (LieSubmodule.Quotient.mk' N) theorem isNilpotent_quotient_iff : - IsNilpotent R L (M ⧸ N) ↔ ∃ k, lowerCentralSeries R L M k ≤ N := by - rw [LieModule.isNilpotent_iff] + IsNilpotent L (M ⧸ N) ↔ ∃ k, lowerCentralSeries R L M k ≤ N := by + rw [isNilpotent_iff R L] refine exists_congr fun k ↦ ?_ rw [← LieSubmodule.Quotient.map_mk'_eq_bot_le, map_lowerCentralSeries_eq k (LieSubmodule.Quotient.surjective_mk' N)] -theorem iInf_lcs_le_of_isNilpotent_quot (h : IsNilpotent R L (M ⧸ N)) : +theorem iInf_lcs_le_of_isNilpotent_quot (h : IsNilpotent L (M ⧸ N)) : ⨅ k, lowerCentralSeries R L M k ≤ N := by obtain ⟨k, hk⟩ := (isNilpotent_quotient_iff R L M N).mp h exact iInf_le_of_le k hk @@ -318,81 +369,90 @@ the natural number `k` (the number of inclusions). For a non-nilpotent module, we use the junk value 0. -/ noncomputable def nilpotencyLength : ℕ := - sInf {k | lowerCentralSeries R L M k = ⊥} + sInf {k | lowerCentralSeries ℤ L M k = ⊥} @[simp] -theorem nilpotencyLength_eq_zero_iff [IsNilpotent R L M] : - nilpotencyLength R L M = 0 ↔ Subsingleton M := by - let s := {k | lowerCentralSeries R L M k = ⊥} +theorem nilpotencyLength_eq_zero_iff [IsNilpotent L M] : + nilpotencyLength L M = 0 ↔ Subsingleton M := by + let s := {k | lowerCentralSeries ℤ L M k = ⊥} have hs : s.Nonempty := by - obtain ⟨k, hk⟩ := (by infer_instance : IsNilpotent R L M) + obtain ⟨k, hk⟩ := IsNilpotent.nilpotent ℤ L M exact ⟨k, hk⟩ change sInf s = 0 ↔ _ - rw [← LieSubmodule.subsingleton_iff R L M, ← subsingleton_iff_bot_eq_top, ← - lowerCentralSeries_zero, @eq_comm (LieSubmodule R L M)] + rw [← LieSubmodule.subsingleton_iff ℤ L M, ← subsingleton_iff_bot_eq_top, ← + lowerCentralSeries_zero, @eq_comm (LieSubmodule ℤ L M)] refine ⟨fun h => h ▸ Nat.sInf_mem hs, fun h => ?_⟩ rw [Nat.sInf_eq_zero] exact Or.inl h +section + +variable [LieModule R L M] + theorem nilpotencyLength_eq_succ_iff (k : ℕ) : - nilpotencyLength R L M = k + 1 ↔ + nilpotencyLength L M = k + 1 ↔ lowerCentralSeries R L M (k + 1) = ⊥ ∧ lowerCentralSeries R L M k ≠ ⊥ := by - let s := {k | lowerCentralSeries R L M k = ⊥} + have aux (k : ℕ) : lowerCentralSeries R L M k = ⊥ ↔ lowerCentralSeries ℤ L M k = ⊥ := by + simp [SetLike.ext'_iff, coe_lowerCentralSeries_eq_int R L M] + let s := {k | lowerCentralSeries ℤ L M k = ⊥} + rw [aux, ne_eq, aux] change sInf s = k + 1 ↔ k + 1 ∈ s ∧ k ∉ s have hs : ∀ k₁ k₂, k₁ ≤ k₂ → k₁ ∈ s → k₂ ∈ s := by - rintro k₁ k₂ h₁₂ (h₁ : lowerCentralSeries R L M k₁ = ⊥) - exact eq_bot_iff.mpr (h₁ ▸ antitone_lowerCentralSeries R L M h₁₂) + rintro k₁ k₂ h₁₂ (h₁ : lowerCentralSeries ℤ L M k₁ = ⊥) + exact eq_bot_iff.mpr (h₁ ▸ antitone_lowerCentralSeries ℤ L M h₁₂) exact Nat.sInf_upward_closed_eq_succ_iff hs k @[simp] theorem nilpotencyLength_eq_one_iff [Nontrivial M] : - nilpotencyLength R L M = 1 ↔ IsTrivial L M := by - rw [nilpotencyLength_eq_succ_iff, ← trivial_iff_lower_central_eq_bot] + nilpotencyLength L M = 1 ↔ IsTrivial L M := by + rw [nilpotencyLength_eq_succ_iff ℤ, ← trivial_iff_lower_central_eq_bot] simp -theorem isTrivial_of_nilpotencyLength_le_one [IsNilpotent R L M] (h : nilpotencyLength R L M ≤ 1) : +theorem isTrivial_of_nilpotencyLength_le_one [IsNilpotent L M] (h : nilpotencyLength L M ≤ 1) : IsTrivial L M := by nontriviality M cases' Nat.le_one_iff_eq_zero_or_eq_one.mp h with h h · rw [nilpotencyLength_eq_zero_iff] at h; infer_instance · rwa [nilpotencyLength_eq_one_iff] at h +end + /-- Given a non-trivial nilpotent Lie module `M` with lower central series `M = C₀ ≥ C₁ ≥ ⋯ ≥ Cₖ = ⊥`, this is the `k-1`th term in the lower central series (the last non-trivial term). For a trivial or non-nilpotent module, this is the bottom submodule, `⊥`. -/ noncomputable def lowerCentralSeriesLast : LieSubmodule R L M := - match nilpotencyLength R L M with + match nilpotencyLength L M with | 0 => ⊥ | k + 1 => lowerCentralSeries R L M k theorem lowerCentralSeriesLast_le_max_triv [LieModule R L M] : lowerCentralSeriesLast R L M ≤ maxTrivSubmodule R L M := by rw [lowerCentralSeriesLast] - cases' h : nilpotencyLength R L M with k + cases' h : nilpotencyLength L M with k · exact bot_le · rw [le_max_triv_iff_bracket_eq_bot] - rw [nilpotencyLength_eq_succ_iff, lowerCentralSeries_succ] at h + rw [nilpotencyLength_eq_succ_iff R, lowerCentralSeries_succ] at h exact h.1 -theorem nontrivial_lowerCentralSeriesLast [Nontrivial M] [IsNilpotent R L M] : +theorem nontrivial_lowerCentralSeriesLast [LieModule R L M] [Nontrivial M] [IsNilpotent L M] : Nontrivial (lowerCentralSeriesLast R L M) := by rw [LieSubmodule.nontrivial_iff_ne_bot, lowerCentralSeriesLast] - cases h : nilpotencyLength R L M + cases h : nilpotencyLength L M · rw [nilpotencyLength_eq_zero_iff, ← not_nontrivial_iff_subsingleton] at h contradiction - · rw [nilpotencyLength_eq_succ_iff] at h + · rw [nilpotencyLength_eq_succ_iff R] at h exact h.2 -theorem lowerCentralSeriesLast_le_of_not_isTrivial [IsNilpotent R L M] (h : ¬ IsTrivial L M) : +theorem lowerCentralSeriesLast_le_of_not_isTrivial [IsNilpotent L M] (h : ¬ IsTrivial L M) : lowerCentralSeriesLast R L M ≤ lowerCentralSeries R L M 1 := by rw [lowerCentralSeriesLast] - replace h : 1 < nilpotencyLength R L M := by + replace h : 1 < nilpotencyLength L M := by by_contra contra - have := isTrivial_of_nilpotencyLength_le_one R L M (not_lt.mp contra) + have := isTrivial_of_nilpotencyLength_le_one L M (not_lt.mp contra) contradiction - cases' hk : nilpotencyLength R L M with k <;> rw [hk] at h + cases' hk : nilpotencyLength L M with k <;> rw [hk] at h · contradiction · exact antitone_lowerCentralSeries _ _ _ (Nat.lt_succ.mp h) @@ -403,7 +463,7 @@ of `M` contains a non-zero element on which `L` acts trivially unless the entire Taking `M = L`, this provides a useful characterisation of Abelian-ness for nilpotent Lie algebras. -/ -lemma disjoint_lowerCentralSeries_maxTrivSubmodule_iff [IsNilpotent R L M] : +lemma disjoint_lowerCentralSeries_maxTrivSubmodule_iff [IsNilpotent L M] : Disjoint (lowerCentralSeries R L M 1) (maxTrivSubmodule R L M) ↔ IsTrivial L M := by refine ⟨fun h ↦ ?_, fun h ↦ by simp⟩ nontriviality M @@ -416,7 +476,7 @@ lemma disjoint_lowerCentralSeries_maxTrivSubmodule_iff [IsNilpotent R L M] : rw [h.eq_bot, le_bot_iff] at this exact this ▸ not_nontrivial _ -theorem nontrivial_max_triv_of_isNilpotent [Nontrivial M] [IsNilpotent R L M] : +theorem nontrivial_max_triv_of_isNilpotent [Nontrivial M] [IsNilpotent L M] : Nontrivial (maxTrivSubmodule R L M) := Set.nontrivial_mono (lowerCentralSeriesLast_le_max_triv R L M) (nontrivial_lowerCentralSeriesLast R L M) @@ -441,7 +501,8 @@ theorem coe_lcs_range_toEnd_eq (k : ℕ) : @[simp] theorem isNilpotent_range_toEnd_iff : - IsNilpotent R (toEnd R L M).range M ↔ IsNilpotent R L M := by + IsNilpotent (toEnd R L M).range M ↔ IsNilpotent L M := by + simp only [isNilpotent_iff R _ M] constructor <;> rintro ⟨k, hk⟩ <;> use k <;> rw [← LieSubmodule.toSubmodule_inj] at hk ⊢ <;> simpa using hk @@ -513,9 +574,10 @@ theorem gc_lcs_ucs (k : ℕ) : theorem ucs_eq_top_iff (k : ℕ) : N.ucs k = ⊤ ↔ LieModule.lowerCentralSeries R L M k ≤ N := by rw [eq_top_iff, ← lcs_le_iff]; rfl +variable (R) in theorem _root_.LieModule.isNilpotent_iff_exists_ucs_eq_top : - LieModule.IsNilpotent R L M ↔ ∃ k, (⊥ : LieSubmodule R L M).ucs k = ⊤ := by - rw [LieModule.isNilpotent_iff]; exact exists_congr fun k => by simp [ucs_eq_top_iff] + LieModule.IsNilpotent L M ↔ ∃ k, (⊥ : LieSubmodule R L M).ucs k = ⊤ := by + rw [LieModule.isNilpotent_iff R]; exact exists_congr fun k => by simp [ucs_eq_top_iff] theorem ucs_comap_incl (k : ℕ) : ((⊥ : LieSubmodule R L M).ucs k).comap N.incl = (⊥ : LieSubmodule R L N).ucs k := by @@ -524,8 +586,8 @@ theorem ucs_comap_incl (k : ℕ) : | succ k ih => simp [← ih] theorem isNilpotent_iff_exists_self_le_ucs : - LieModule.IsNilpotent R L N ↔ ∃ k, N ≤ (⊥ : LieSubmodule R L M).ucs k := by - simp_rw [LieModule.isNilpotent_iff_exists_ucs_eq_top, ← ucs_comap_incl, comap_incl_eq_top] + LieModule.IsNilpotent L N ↔ ∃ k, N ≤ (⊥ : LieSubmodule R L M).ucs k := by + simp_rw [LieModule.isNilpotent_iff_exists_ucs_eq_top R, ← ucs_comap_incl, comap_incl_eq_top] theorem ucs_bot_one : (⊥ : LieSubmodule R L M).ucs 1 = LieModule.maxTrivSubmodule R L M := by simp [LieSubmodule.normalizer_bot_eq_maxTrivSubmodule] @@ -568,14 +630,15 @@ theorem Function.Surjective.lieModule_lcs_map_eq (k : ℕ) : exact ⟨⁅y, n⁆, ⟨y, n, hn, rfl⟩, (hfg y n).symm⟩ include hf hg hfg in -theorem Function.Surjective.lieModuleIsNilpotent [IsNilpotent R L M] : IsNilpotent R L₂ M₂ := by - obtain ⟨k, hk⟩ := id (by infer_instance : IsNilpotent R L M) +theorem Function.Surjective.lieModuleIsNilpotent [IsNilpotent L M] : IsNilpotent L₂ M₂ := by + obtain ⟨k, hk⟩ := IsNilpotent.nilpotent R L M + rw [isNilpotent_iff R] use k rw [← LieSubmodule.toSubmodule_inj] at hk ⊢ simp [← hf.lieModule_lcs_map_eq hg hfg k, hk] theorem Equiv.lieModule_isNilpotent_iff (f : L ≃ₗ⁅R⁆ L₂) (g : M ≃ₗ[R] M₂) - (hfg : ∀ x m, ⁅f x, g m⁆ = g ⁅x, m⁆) : IsNilpotent R L M ↔ IsNilpotent R L₂ M₂ := by + (hfg : ∀ x m, ⁅f x, g m⁆ = g ⁅x, m⁆) : IsNilpotent L M ↔ IsNilpotent L₂ M₂ := by constructor <;> intro h · have hg : Surjective (g : M →ₗ[R] M₂) := g.surjective exact f.surjective.lieModuleIsNilpotent hg hfg @@ -586,38 +649,37 @@ theorem Equiv.lieModule_isNilpotent_iff (f : L ≃ₗ⁅R⁆ L₂) (g : M ≃ₗ @[simp] theorem LieModule.isNilpotent_of_top_iff : - IsNilpotent R (⊤ : LieSubalgebra R L) M ↔ IsNilpotent R L M := + IsNilpotent (⊤ : LieSubalgebra R L) M ↔ IsNilpotent L M := Equiv.lieModule_isNilpotent_iff LieSubalgebra.topEquiv (1 : M ≃ₗ[R] M) fun _ _ => rfl @[simp] lemma LieModule.isNilpotent_of_top_iff' : - IsNilpotent R L {x // x ∈ (⊤ : LieSubmodule R L M)} ↔ IsNilpotent R L M := + IsNilpotent L {x // x ∈ (⊤ : LieSubmodule R L M)} ↔ IsNilpotent L M := Equiv.lieModule_isNilpotent_iff 1 (LinearEquiv.ofTop ⊤ rfl) fun _ _ ↦ rfl end Morphisms end NilpotentModules -instance (priority := 100) LieAlgebra.isSolvable_of_isNilpotent (R : Type u) (L : Type v) - [CommRing R] [LieRing L] [LieAlgebra R L] [hL : LieModule.IsNilpotent R L L] : - LieAlgebra.IsSolvable R L := by - obtain ⟨k, h⟩ : ∃ k, LieModule.lowerCentralSeries R L L k = ⊥ := hL.nilpotent +instance (priority := 100) LieAlgebra.isSolvable_of_isNilpotent (L : Type v) + [LieRing L] [hL : LieModule.IsNilpotent L L] : + LieAlgebra.IsSolvable L := by + obtain ⟨k, h⟩ : ∃ k, LieModule.lowerCentralSeries ℤ L L k = ⊥ := hL.nilpotent_int use k; rw [← le_bot_iff] at h ⊢ - exact le_trans (LieModule.derivedSeries_le_lowerCentralSeries R L k) h + exact le_trans (LieModule.derivedSeries_le_lowerCentralSeries ℤ L k) h section NilpotentAlgebras variable (R : Type u) (L : Type v) (L' : Type w) variable [CommRing R] [LieRing L] [LieAlgebra R L] [LieRing L'] [LieAlgebra R L'] -/-- We say a Lie algebra is nilpotent when it is nilpotent as a Lie module over itself via the +/-- We say a Lie ring is nilpotent when it is nilpotent as a Lie module over itself via the adjoint representation. -/ -abbrev LieAlgebra.IsNilpotent (R : Type u) (L : Type v) [CommRing R] [LieRing L] [LieAlgebra R L] : - Prop := - LieModule.IsNilpotent R L L +abbrev LieRing.IsNilpotent (L : Type v) [LieRing L] : Prop := + LieModule.IsNilpotent L L -open LieAlgebra +open LieRing -theorem LieAlgebra.nilpotent_ad_of_nilpotent_algebra [IsNilpotent R L] : +theorem LieAlgebra.nilpotent_ad_of_nilpotent_algebra [IsNilpotent L] : ∃ k : ℕ, ∀ x : L, ad R L x ^ k = 0 := LieModule.exists_forall_pow_toEnd_eq_zero R L L @@ -667,14 +729,14 @@ theorem LieModule.coe_lowerCentralSeries_ideal_le {I : LieIdeal R L} (k : ℕ) : /-- A central extension of nilpotent Lie algebras is nilpotent. -/ theorem LieAlgebra.nilpotent_of_nilpotent_quotient {I : LieIdeal R L} (h₁ : I ≤ center R L) - (h₂ : IsNilpotent R (L ⧸ I)) : IsNilpotent R L := by - suffices LieModule.IsNilpotent R L (L ⧸ I) by + (h₂ : IsNilpotent (L ⧸ I)) : IsNilpotent L := by + suffices LieModule.IsNilpotent L (L ⧸ I) by exact LieModule.nilpotentOfNilpotentQuotient R L L h₁ this - obtain ⟨k, hk⟩ := h₂ - use k + simp only [LieRing.IsNilpotent, LieModule.isNilpotent_iff R] at h₂ ⊢ + peel h₂ with k hk simp [← LieSubmodule.toSubmodule_inj, coe_lowerCentralSeries_ideal_quot_eq, hk] -theorem LieAlgebra.non_trivial_center_of_isNilpotent [Nontrivial L] [IsNilpotent R L] : +theorem LieAlgebra.non_trivial_center_of_isNilpotent [Nontrivial L] [IsNilpotent L] : Nontrivial <| center R L := LieModule.nontrivial_max_triv_of_isNilpotent R L L @@ -695,29 +757,27 @@ theorem LieIdeal.lowerCentralSeries_map_eq (k : ℕ) {f : L →ₗ⁅R⁆ L'} (h | zero => simp only [LieModule.lowerCentralSeries_zero]; exact h' | succ k ih => simp only [LieModule.lowerCentralSeries_succ, LieIdeal.map_bracket_eq f h, ih, h'] -theorem Function.Injective.lieAlgebra_isNilpotent [h₁ : IsNilpotent R L'] {f : L →ₗ⁅R⁆ L'} - (h₂ : Function.Injective f) : IsNilpotent R L := - { nilpotent := by - obtain ⟨k, hk⟩ := id h₁ - use k - apply LieIdeal.bot_of_map_eq_bot h₂; rw [eq_bot_iff, ← hk] - apply LieIdeal.map_lowerCentralSeries_le } - -theorem Function.Surjective.lieAlgebra_isNilpotent [h₁ : IsNilpotent R L] {f : L →ₗ⁅R⁆ L'} - (h₂ : Function.Surjective f) : IsNilpotent R L' := - { nilpotent := by - obtain ⟨k, hk⟩ := id h₁ - use k - rw [← LieIdeal.lowerCentralSeries_map_eq k h₂, hk] - simp only [LieIdeal.map_eq_bot_iff, bot_le] } +theorem Function.Injective.lieAlgebra_isNilpotent [h₁ : IsNilpotent L'] {f : L →ₗ⁅R⁆ L'} + (h₂ : Function.Injective f) : IsNilpotent L := by + rw [LieRing.IsNilpotent, LieModule.isNilpotent_iff R] at h₁ ⊢ + peel h₁ with k hk + apply LieIdeal.bot_of_map_eq_bot h₂; rw [eq_bot_iff, ← hk] + apply LieIdeal.map_lowerCentralSeries_le + +theorem Function.Surjective.lieAlgebra_isNilpotent [h₁ : IsNilpotent L] {f : L →ₗ⁅R⁆ L'} + (h₂ : Function.Surjective f) : IsNilpotent L' := by + rw [LieRing.IsNilpotent, LieModule.isNilpotent_iff R] at h₁ ⊢ + peel h₁ with k hk + rw [← LieIdeal.lowerCentralSeries_map_eq k h₂, hk] + simp only [LieIdeal.map_eq_bot_iff, bot_le] theorem LieEquiv.nilpotent_iff_equiv_nilpotent (e : L ≃ₗ⁅R⁆ L') : - IsNilpotent R L ↔ IsNilpotent R L' := by + IsNilpotent L ↔ IsNilpotent L' := by constructor <;> intro h · exact e.symm.injective.lieAlgebra_isNilpotent · exact e.injective.lieAlgebra_isNilpotent -theorem LieHom.isNilpotent_range [IsNilpotent R L] (f : L →ₗ⁅R⁆ L') : IsNilpotent R f.range := +theorem LieHom.isNilpotent_range [IsNilpotent L] (f : L →ₗ⁅R⁆ L') : IsNilpotent f.range := f.surjective_rangeRestrict.lieAlgebra_isNilpotent /-- Note that this result is not quite a special case of @@ -725,7 +785,7 @@ theorem LieHom.isNilpotent_range [IsNilpotent R L] (f : L →ₗ⁅R⁆ L') : Is `(ad R L).range`-module `L`, whereas this result concerns nilpotency of the `(ad R L).range`-module `(ad R L).range`. -/ @[simp] -theorem LieAlgebra.isNilpotent_range_ad_iff : IsNilpotent R (ad R L).range ↔ IsNilpotent R L := by +theorem LieAlgebra.isNilpotent_range_ad_iff : IsNilpotent (ad R L).range ↔ IsNilpotent L := by refine ⟨fun h => ?_, ?_⟩ · have : (ad R L).ker = center R L := by simp exact @@ -734,7 +794,7 @@ theorem LieAlgebra.isNilpotent_range_ad_iff : IsNilpotent R (ad R L).range ↔ I · intro h exact (ad R L).isNilpotent_range -instance [h : LieAlgebra.IsNilpotent R L] : LieAlgebra.IsNilpotent R (⊤ : LieSubalgebra R L) := +instance [h : LieRing.IsNilpotent L] : LieRing.IsNilpotent (⊤ : LieSubalgebra R L) := LieSubalgebra.topEquiv.nilpotent_iff_equiv_nilpotent.mpr h end NilpotentAlgebras @@ -829,9 +889,10 @@ lemma LieSubmodule.lowerCentralSeries_tensor_eq_baseChange (k : ℕ) : | zero => simp | succ k ih => simp only [lowerCentralSeries_succ, ih, ← baseChange_top, lie_baseChange] -instance LieModule.instIsNilpotentTensor [IsNilpotent R L M] : - IsNilpotent A (A ⊗[R] L) (A ⊗[R] M) := by - obtain ⟨k, hk⟩ := inferInstanceAs (IsNilpotent R L M) +instance LieModule.instIsNilpotentTensor [IsNilpotent L M] : + IsNilpotent (A ⊗[R] L) (A ⊗[R] M) := by + obtain ⟨k, hk⟩ := IsNilpotent.nilpotent R L M + rw [isNilpotent_iff A] exact ⟨k, by simp [hk]⟩ end ExtendScalars diff --git a/Mathlib/Algebra/Lie/Semisimple/Basic.lean b/Mathlib/Algebra/Lie/Semisimple/Basic.lean index 16117bb7c15bf..0697232c790f3 100644 --- a/Mathlib/Algebra/Lie/Semisimple/Basic.lean +++ b/Mathlib/Algebra/Lie/Semisimple/Basic.lean @@ -48,7 +48,7 @@ variable (R L : Type*) [CommRing R] [LieRing L] [LieAlgebra R L] variable {R L} in theorem HasTrivialRadical.eq_bot_of_isSolvable [HasTrivialRadical R L] - (I : LieIdeal R L) [hI : IsSolvable R I] : I = ⊥ := + (I : LieIdeal R L) [hI : IsSolvable I] : I = ⊥ := sSup_eq_bot.mp radical_eq_bot _ hI @[simp] @@ -56,19 +56,19 @@ theorem HasTrivialRadical.center_eq_bot [HasTrivialRadical R L] : center R L = HasTrivialRadical.eq_bot_of_isSolvable _ variable {R L} in -theorem hasTrivialRadical_of_no_solvable_ideals (h : ∀ I : LieIdeal R L, IsSolvable R I → I = ⊥) : +theorem hasTrivialRadical_of_no_solvable_ideals (h : ∀ I : LieIdeal R L, IsSolvable I → I = ⊥) : HasTrivialRadical R L := ⟨sSup_eq_bot.mpr h⟩ theorem hasTrivialRadical_iff_no_solvable_ideals : - HasTrivialRadical R L ↔ ∀ I : LieIdeal R L, IsSolvable R I → I = ⊥ := + HasTrivialRadical R L ↔ ∀ I : LieIdeal R L, IsSolvable I → I = ⊥ := ⟨@HasTrivialRadical.eq_bot_of_isSolvable _ _ _ _ _, hasTrivialRadical_of_no_solvable_ideals⟩ theorem hasTrivialRadical_iff_no_abelian_ideals : HasTrivialRadical R L ↔ ∀ I : LieIdeal R L, IsLieAbelian I → I = ⊥ := by rw [hasTrivialRadical_iff_no_solvable_ideals] constructor <;> intro h₁ I h₂ - · exact h₁ _ <| LieAlgebra.ofAbelianIsSolvable R I + · exact h₁ _ <| LieAlgebra.ofAbelianIsSolvable I · rw [← abelian_of_solvable_ideal_eq_bot_iff] exact h₁ _ <| abelian_derivedAbelianOfIdeal I @@ -318,7 +318,7 @@ to be reductive. Note that there is absolutely [no agreement](https://mathoverflow.net/questions/284713/) on what the label 'reductive' should mean when the coefficients are not a field of characteristic zero. -/ theorem abelian_radical_iff_solvable_is_abelian [IsNoetherian R L] : - IsLieAbelian (radical R L) ↔ ∀ I : LieIdeal R L, IsSolvable R I → IsLieAbelian I := by + IsLieAbelian (radical R L) ↔ ∀ I : LieIdeal R L, IsSolvable I → IsLieAbelian I := by constructor · rintro h₁ I h₂ rw [LieIdeal.solvable_iff_le_radical] at h₂ diff --git a/Mathlib/Algebra/Lie/Solvable.lean b/Mathlib/Algebra/Lie/Solvable.lean index a17e1accef60b..7e9c2d579d51f 100644 --- a/Mathlib/Algebra/Lie/Solvable.lean +++ b/Mathlib/Algebra/Lie/Solvable.lean @@ -190,23 +190,71 @@ theorem derivedSeries_eq_top (n : ℕ) (h : derivedSeries R L 1 = ⊤) : · rfl · rwa [derivedSeries_succ_eq_top_iff] +private theorem coe_derivedSeries_eq_int_aux (R₁ R₂ L : Type*) [CommRing R₁] [CommRing R₂] + [LieRing L] [LieAlgebra R₁ L] [LieAlgebra R₂ L] (k : ℕ) + (ih : ∀ (x : L), x ∈ derivedSeriesOfIdeal R₁ L k ⊤ ↔ x ∈ derivedSeriesOfIdeal R₂ L k ⊤) : + let I := derivedSeriesOfIdeal R₂ L k ⊤; let S : Set L := {⁅a, b⁆ | (a ∈ I) (b ∈ I)} + (Submodule.span R₁ S : Set L) ≤ (Submodule.span R₂ S : Set L) := by + intro I S x hx + simp only [SetLike.mem_coe] at hx ⊢ + induction hx using Submodule.closure_induction with + | zero => exact Submodule.zero_mem _ + | add y z hy₁ hz₁ hy₂ hz₂ => exact Submodule.add_mem _ hy₂ hz₂ + | smul_mem c y hy => + obtain ⟨a, ha, b, hb, rfl⟩ := hy + rw [← smul_lie] + refine Submodule.subset_span ⟨c • a, ?_, b, hb, rfl⟩ + rw [← ih] at ha ⊢ + exact Submodule.smul_mem _ _ ha + +theorem coe_derivedSeries_eq_int (k : ℕ) : + (derivedSeries R L k : Set L) = (derivedSeries ℤ L k : Set L) := by + show ((derivedSeries R L k).toSubmodule : Set L) = ((derivedSeries ℤ L k).toSubmodule : Set L) + rw [derivedSeries_def, derivedSeries_def] + induction k with + | zero => rfl + | succ k ih => + rw [derivedSeriesOfIdeal_succ, derivedSeriesOfIdeal_succ] + rw [LieSubmodule.lieIdeal_oper_eq_linear_span', LieSubmodule.lieIdeal_oper_eq_linear_span'] + rw [Set.ext_iff] at ih + simp only [SetLike.mem_coe, LieSubmodule.mem_toSubmodule] at ih + simp only [Subtype.exists, exists_prop, ih] + apply le_antisymm + · exact coe_derivedSeries_eq_int_aux _ _ L k ih + · simp only [← ih] + apply coe_derivedSeries_eq_int_aux _ _ L k + simp [ih] + end LieIdeal namespace LieAlgebra /-- A Lie algebra is solvable if its derived series reaches 0 (in a finite number of steps). -/ +@[mk_iff isSolvable_iff_int] class IsSolvable : Prop where - solvable : ∃ k, derivedSeries R L k = ⊥ + mk_int :: + solvable_int : ∃ k, derivedSeries ℤ L k = ⊥ -instance isSolvableBot : IsSolvable R (⊥ : LieIdeal R L) := +instance isSolvableBot : IsSolvable (⊥ : LieIdeal R L) := ⟨⟨0, Subsingleton.elim _ ⊥⟩⟩ -instance isSolvableAdd {I J : LieIdeal R L} [hI : IsSolvable R I] [hJ : IsSolvable R J] : - IsSolvable R (I + J) := by - obtain ⟨k, hk⟩ := id hI; obtain ⟨l, hl⟩ := id hJ - exact ⟨⟨k + l, LieIdeal.derivedSeries_add_eq_bot hk hl⟩⟩ +lemma isSolvable_iff : IsSolvable L ↔ ∃ k, derivedSeries R L k = ⊥ := by + simp [isSolvable_iff_int, SetLike.ext'_iff, LieIdeal.coe_derivedSeries_eq_int] + +lemma IsSolvable.solvable [IsSolvable L] : ∃ k, derivedSeries R L k = ⊥ := + (isSolvable_iff R L).mp ‹_› + +variable {R L} in +lemma IsSolvable.mk {k : ℕ} (h : derivedSeries R L k = ⊥) : IsSolvable L := + (isSolvable_iff R L).mpr ⟨k, h⟩ + +instance isSolvableAdd {I J : LieIdeal R L} [IsSolvable I] [IsSolvable J] : + IsSolvable (I + J) := by + obtain ⟨k, hk⟩ := IsSolvable.solvable R I + obtain ⟨l, hl⟩ := IsSolvable.solvable R J + exact IsSolvable.mk (LieIdeal.derivedSeries_add_eq_bot hk hl) -theorem derivedSeries_lt_top_of_solvable [IsSolvable R L] [Nontrivial L] : +theorem derivedSeries_lt_top_of_solvable [IsSolvable L] [Nontrivial L] : derivedSeries R L 1 < ⊤ := by obtain ⟨n, hn⟩ := IsSolvable.solvable (R := R) (L := L) rw [lt_top_iff_ne_top] @@ -222,76 +270,78 @@ namespace Function open LieAlgebra -theorem Injective.lieAlgebra_isSolvable [h₁ : IsSolvable R L] (h₂ : Injective f) : - IsSolvable R L' := by - obtain ⟨k, hk⟩ := id h₁ - use k - apply LieIdeal.bot_of_map_eq_bot h₂; rw [eq_bot_iff, ← hk] +theorem Injective.lieAlgebra_isSolvable [hL : IsSolvable L] (h : Injective f) : + IsSolvable L' := by + rw [isSolvable_iff R] at hL ⊢ + apply hL.imp + intro k hk + apply LieIdeal.bot_of_map_eq_bot h; rw [eq_bot_iff, ← hk] apply LieIdeal.derivedSeries_map_le -instance (A : LieIdeal R L) [IsSolvable R L] : IsSolvable R A := +instance (A : LieIdeal R L) [IsSolvable L] : IsSolvable A := A.incl_injective.lieAlgebra_isSolvable -theorem Surjective.lieAlgebra_isSolvable [h₁ : IsSolvable R L'] (h₂ : Surjective f) : - IsSolvable R L := by - obtain ⟨k, hk⟩ := id h₁ - use k - rw [← LieIdeal.derivedSeries_map_eq k h₂, hk] +theorem Surjective.lieAlgebra_isSolvable [hL' : IsSolvable L'] (h : Surjective f) : + IsSolvable L := by + rw [isSolvable_iff R] at hL' ⊢ + apply hL'.imp + intro k hk + rw [← LieIdeal.derivedSeries_map_eq k h, hk] simp only [LieIdeal.map_eq_bot_iff, bot_le] end Function -instance LieHom.isSolvable_range (f : L' →ₗ⁅R⁆ L) [LieAlgebra.IsSolvable R L'] : - LieAlgebra.IsSolvable R f.range := +instance LieHom.isSolvable_range (f : L' →ₗ⁅R⁆ L) [LieAlgebra.IsSolvable L'] : + LieAlgebra.IsSolvable f.range := f.surjective_rangeRestrict.lieAlgebra_isSolvable namespace LieAlgebra -theorem solvable_iff_equiv_solvable (e : L' ≃ₗ⁅R⁆ L) : IsSolvable R L' ↔ IsSolvable R L := by +theorem solvable_iff_equiv_solvable (e : L' ≃ₗ⁅R⁆ L) : IsSolvable L' ↔ IsSolvable L := by constructor <;> intro h · exact e.symm.injective.lieAlgebra_isSolvable · exact e.injective.lieAlgebra_isSolvable -theorem le_solvable_ideal_solvable {I J : LieIdeal R L} (h₁ : I ≤ J) (_ : IsSolvable R J) : - IsSolvable R I := +theorem le_solvable_ideal_solvable {I J : LieIdeal R L} (h₁ : I ≤ J) (_ : IsSolvable J) : + IsSolvable I := (LieIdeal.inclusion_injective h₁).lieAlgebra_isSolvable variable (R L) -instance (priority := 100) ofAbelianIsSolvable [IsLieAbelian L] : IsSolvable R L := by +instance (priority := 100) ofAbelianIsSolvable [IsLieAbelian L] : IsSolvable L := by use 1 rw [← abelian_iff_derived_one_eq_bot, lie_abelian_iff_equiv_lie_abelian LieIdeal.topEquiv] infer_instance /-- The (solvable) radical of Lie algebra is the `sSup` of all solvable ideals. -/ def radical := - sSup { I : LieIdeal R L | IsSolvable R I } + sSup { I : LieIdeal R L | IsSolvable I } /-- The radical of a Noetherian Lie algebra is solvable. -/ -instance radicalIsSolvable [IsNoetherian R L] : IsSolvable R (radical R L) := by +instance radicalIsSolvable [IsNoetherian R L] : IsSolvable (radical R L) := by have hwf := LieSubmodule.wellFoundedGT_of_noetherian R L L rw [← CompleteLattice.isSupClosedCompact_iff_wellFoundedGT] at hwf - refine hwf { I : LieIdeal R L | IsSolvable R I } ⟨⊥, ?_⟩ fun I hI J hJ => ?_ + refine hwf { I : LieIdeal R L | IsSolvable I } ⟨⊥, ?_⟩ fun I hI J hJ => ?_ · exact LieAlgebra.isSolvableBot R L · rw [Set.mem_setOf_eq] at hI hJ ⊢ apply LieAlgebra.isSolvableAdd R L /-- The `→` direction of this lemma is actually true without the `IsNoetherian` assumption. -/ theorem LieIdeal.solvable_iff_le_radical [IsNoetherian R L] (I : LieIdeal R L) : - IsSolvable R I ↔ I ≤ radical R L := + IsSolvable I ↔ I ≤ radical R L := ⟨fun h => le_sSup h, fun h => le_solvable_ideal_solvable h inferInstance⟩ theorem center_le_radical : center R L ≤ radical R L := - have h : IsSolvable R (center R L) := inferInstance + have h : IsSolvable (center R L) := inferInstance le_sSup h -instance [IsSolvable R L] : IsSolvable R (⊤ : LieSubalgebra R L) := by +instance [IsSolvable L] : IsSolvable (⊤ : LieSubalgebra R L) := by rwa [solvable_iff_equiv_solvable LieSubalgebra.topEquiv] -@[simp] lemma radical_eq_top_of_isSolvable [IsSolvable R L] : +@[simp] lemma radical_eq_top_of_isSolvable [IsSolvable L] : radical R L = ⊤ := by rw [eq_top_iff] - have h : IsSolvable R (⊤ : LieSubalgebra R L) := inferInstance + have h : IsSolvable (⊤ : LieSubalgebra R L) := inferInstance exact le_sSup h /-- Given a solvable Lie ideal `I` with derived series `I = D₀ ≥ D₁ ≥ ⋯ ≥ Dₖ = ⊥`, this is the @@ -348,17 +398,17 @@ theorem abelian_derivedAbelianOfIdeal (I : LieIdeal R L) : · dsimp; infer_instance · rw [derivedSeries_of_derivedLength_succ] at h; exact h.1 -theorem derivedLength_zero (I : LieIdeal R L) [hI : IsSolvable R I] : +theorem derivedLength_zero (I : LieIdeal R L) [IsSolvable I] : derivedLengthOfIdeal R L I = 0 ↔ I = ⊥ := by let s := { k | derivedSeriesOfIdeal R L k I = ⊥ } change sInf s = 0 ↔ _ have hne : s ≠ ∅ := by - obtain ⟨k, hk⟩ := id hI + obtain ⟨k, hk⟩ := IsSolvable.solvable R I refine Set.Nonempty.ne_empty ⟨k, ?_⟩ rw [derivedSeries_def, LieIdeal.derivedSeries_eq_bot_iff] at hk; exact hk simp [s, hne] -theorem abelian_of_solvable_ideal_eq_bot_iff (I : LieIdeal R L) [h : IsSolvable R I] : +theorem abelian_of_solvable_ideal_eq_bot_iff (I : LieIdeal R L) [h : IsSolvable I] : derivedAbelianOfIdeal I = ⊥ ↔ I = ⊥ := by dsimp only [derivedAbelianOfIdeal] split -- Porting note: Original tactic was `cases' h : derivedAbelianOfIdeal R L I with k` diff --git a/Mathlib/Algebra/Lie/TraceForm.lean b/Mathlib/Algebra/Lie/TraceForm.lean index e5914475629d3..80c810d875cb6 100644 --- a/Mathlib/Algebra/Lie/TraceForm.lean +++ b/Mathlib/Algebra/Lie/TraceForm.lean @@ -94,7 +94,7 @@ lemma traceForm_lieInvariant : (traceForm R L M).lieInvariant L := by rw [LieHom.lie_apply, LinearMap.sub_apply, Module.Dual.lie_apply, LinearMap.zero_apply, LinearMap.zero_apply, traceForm_apply_lie_apply', sub_self] -@[simp] lemma traceForm_eq_zero_of_isNilpotent [IsReduced R] [IsNilpotent R L M] : +@[simp] lemma traceForm_eq_zero_of_isNilpotent [IsReduced R] [IsNilpotent L M] : traceForm R L M = 0 := by ext x y simp only [traceForm_apply_apply, LinearMap.zero_apply, ← isNilpotent_iff_eq_zero] @@ -104,7 +104,7 @@ lemma traceForm_lieInvariant : (traceForm R L M).lieInvariant L := by @[simp] lemma traceForm_genWeightSpace_eq [Module.Free R M] [IsDomain R] [IsPrincipalIdealRing R] - [LieAlgebra.IsNilpotent R L] [IsNoetherian R M] [LinearWeights R L M] (χ : L → R) (x y : L) : + [LieRing.IsNilpotent L] [IsNoetherian R M] [LinearWeights R L M] (χ : L → R) (x y : L) : traceForm R L (genWeightSpace M χ) x y = finrank R (genWeightSpace M χ) • (χ x * χ y) := by set d := finrank R (genWeightSpace M χ) have h₁ : χ y • d • χ x - χ y • χ x • (d : R) = 0 := by simp [mul_comm (χ x)] @@ -160,7 +160,7 @@ lemma traceForm_apply_eq_zero_of_mem_lcs_of_mem_center {x y : L} /-- Given a bilinear form `B` on a representation `M` of a nilpotent Lie algebra `L`, if `B` is invariant (in the sense that the action of `L` is skew-adjoint wrt `B`) then components of the Fitting decomposition of `M` are orthogonal wrt `B`. -/ -lemma eq_zero_of_mem_genWeightSpace_mem_posFitting [LieAlgebra.IsNilpotent R L] +lemma eq_zero_of_mem_genWeightSpace_mem_posFitting [LieRing.IsNilpotent L] {B : LinearMap.BilinForm R M} (hB : ∀ (x : L) (m n : M), B ⁅x, m⁆ n = - B m ⁅x, n⁆) {m₀ m₁ : M} (hm₀ : m₀ ∈ genWeightSpace M (0 : L → R)) (hm₁ : m₁ ∈ posFittingComp R L M) : B m₀ m₁ = 0 := by @@ -211,7 +211,7 @@ lemma traceForm_lieSubalgebra_mk_right (L' : LieSubalgebra R L) {x : L'} {y : L} open TensorProduct -variable [LieAlgebra.IsNilpotent R L] [IsDomain R] [IsPrincipalIdealRing R] +variable [LieRing.IsNilpotent L] [IsDomain R] [IsPrincipalIdealRing R] lemma traceForm_eq_sum_genWeightSpaceOf [NoZeroSMulDivisors R M] [IsNoetherian R M] [IsTriangularizable R L M] (z : L) : @@ -344,7 +344,7 @@ lemma killingForm_apply_apply (x y : L) : killingForm R L x y = trace R L (ad R LieModule.traceForm_apply_apply R L L x y lemma killingForm_eq_zero_of_mem_zeroRoot_mem_posFitting - (H : LieSubalgebra R L) [LieAlgebra.IsNilpotent R H] + (H : LieSubalgebra R L) [LieRing.IsNilpotent H] {x₀ x₁ : L} (hx₀ : x₀ ∈ LieAlgebra.zeroRootSubalgebra R L H) (hx₁ : x₁ ∈ LieModule.posFittingComp R H L) : @@ -399,7 +399,7 @@ open Submodule (span subset_span) namespace LieModule variable [Field K] [LieAlgebra K L] [Module K M] [LieModule K L M] [FiniteDimensional K M] -variable [LieAlgebra.IsNilpotent K L] [LinearWeights K L M] [IsTriangularizable K L M] +variable [LieRing.IsNilpotent L] [LinearWeights K L M] [IsTriangularizable K L M] lemma traceForm_eq_sum_finrank_nsmul_mul (x y : L) : traceForm K L M x y = ∑ χ : Weight K L M, finrank K (genWeightSpace M χ) • (χ x * χ y) := by diff --git a/Mathlib/Algebra/Lie/Weights/Basic.lean b/Mathlib/Algebra/Lie/Weights/Basic.lean index 9cb657c719f2d..aaee9a5ecd8b8 100644 --- a/Mathlib/Algebra/Lie/Weights/Basic.lean +++ b/Mathlib/Algebra/Lie/Weights/Basic.lean @@ -156,7 +156,7 @@ variable (M) `genWeightSpaceOf M χ x` is the maximal generalized `χ`-eigenspace of the action of `x` on `M`. It is a Lie submodule because `L` is nilpotent. -/ -def genWeightSpaceOf [LieAlgebra.IsNilpotent R L] (χ : R) (x : L) : LieSubmodule R L M := +def genWeightSpaceOf [LieRing.IsNilpotent L] (χ : R) (x : L) : LieSubmodule R L M := { 𝕎(M, χ, x) with lie_mem := by intro y m hm @@ -168,7 +168,7 @@ def genWeightSpaceOf [LieAlgebra.IsNilpotent R L] (χ : R) (x : L) : LieSubmodul end notation_genWeightSpaceOf variable (M) -variable [LieAlgebra.IsNilpotent R L] +variable [LieRing.IsNilpotent L] theorem mem_genWeightSpaceOf (χ : R) (x : L) (m : M) : m ∈ genWeightSpaceOf M χ x ↔ ∃ k : ℕ, ((toEnd R L M x - χ • ↑1) ^ k) m = 0 := by @@ -298,7 +298,7 @@ end Weight /-- See also the more useful form `LieModule.zero_genWeightSpace_eq_top_of_nilpotent`. -/ @[simp] -theorem zero_genWeightSpace_eq_top_of_nilpotent' [IsNilpotent R L M] : +theorem zero_genWeightSpace_eq_top_of_nilpotent' [IsNilpotent L M] : genWeightSpace M (0 : L → R) = ⊤ := by ext simp [genWeightSpace, genWeightSpaceOf] @@ -311,7 +311,7 @@ theorem coe_genWeightSpace_of_top (χ : L → R) : simp @[simp] -theorem zero_genWeightSpace_eq_top_of_nilpotent [IsNilpotent R L M] : +theorem zero_genWeightSpace_eq_top_of_nilpotent [IsNilpotent L M] : genWeightSpace M (0 : (⊤ : LieSubalgebra R L) → R) = ⊤ := by ext m simp only [mem_genWeightSpace, Pi.zero_apply, zero_smul, sub_zero, Subtype.forall, @@ -356,7 +356,7 @@ theorem isNilpotent_toEnd_genWeightSpace_zero [IsNoetherian R M] (x : L) : /-- By Engel's theorem, the zero weight space of a Noetherian Lie module is nilpotent. -/ instance [IsNoetherian R M] : - IsNilpotent R L (genWeightSpace M (0 : L → R)) := + IsNilpotent L (genWeightSpace M (0 : L → R)) := isNilpotent_iff_forall'.mpr <| isNilpotent_toEnd_genWeightSpace_zero M variable (R L) @@ -437,7 +437,7 @@ lemma mem_posFittingCompOf (x : L) (m : M) : exact LieSubmodule.lie_mem_lie (LieSubmodule.mem_top x) ih @[simp] lemma posFittingCompOf_eq_bot_of_isNilpotent - [IsNilpotent R L M] (x : L) : + [IsNilpotent L M] (x : L) : posFittingCompOf R M x = ⊥ := by simp_rw [eq_bot_iff, ← iInf_lowerCentralSeries_eq_bot_of_isNilpotent, le_iInf_iff, posFittingCompOf_le_lowerCentralSeries, forall_const] @@ -470,7 +470,7 @@ lemma posFittingComp_le_iInf_lowerCentralSeries : ⨅ k, lowerCentralSeries R L M k = posFittingComp R L M := by refine le_antisymm ?_ (posFittingComp_le_iInf_lowerCentralSeries R L M) apply iInf_lcs_le_of_isNilpotent_quot - rw [LieModule.isNilpotent_iff_forall'] + rw [LieModule.isNilpotent_iff_forall' (R := R)] intro x obtain ⟨k, hk⟩ := Filter.eventually_atTop.mp (toEnd R L M x).eventually_iInf_range_pow_eq use k @@ -488,7 +488,7 @@ lemma posFittingComp_le_iInf_lowerCentralSeries : simpa using this @[simp] lemma posFittingComp_eq_bot_of_isNilpotent - [IsNilpotent R L M] : + [IsNilpotent L M] : posFittingComp R L M = ⊥ := by simp [posFittingComp] @@ -603,9 +603,9 @@ private lemma isCompl_genWeightSpace_zero_posFittingComp_aux set M₁ := posFittingComp R L M rcases forall_or_exists_not (fun (x : L) ↦ genWeightSpaceOf M (0 : R) x = ⊤) with h | ⟨x, hx : genWeightSpaceOf M (0 : R) x ≠ ⊤⟩ - · suffices IsNilpotent R L M by simp [M₀, M₁, isCompl_top_bot] + · suffices IsNilpotent L M by simp [M₀, M₁, isCompl_top_bot] replace h : M₀ = ⊤ := by simpa [M₀, genWeightSpace] - rw [← LieModule.isNilpotent_of_top_iff', ← h] + rw [← LieModule.isNilpotent_of_top_iff' (R := R), ← h] infer_instance · set M₀ₓ := genWeightSpaceOf M (0 : R) x set M₁ₓ := posFittingCompOf R M x @@ -750,8 +750,7 @@ section field open Module variable (K) -variable [Field K] [LieAlgebra K L] [Module K M] [LieModule K L M] [LieAlgebra.IsNilpotent K L] - [FiniteDimensional K M] +variable [Field K] [LieAlgebra K L] [Module K M] [LieModule K L M] [FiniteDimensional K M] instance instIsTriangularizableOfIsAlgClosed [IsAlgClosed K] : IsTriangularizable K L M := ⟨fun _ ↦ Module.End.iSup_maxGenEigenspace_eq_top _⟩ diff --git a/Mathlib/Algebra/Lie/Weights/Cartan.lean b/Mathlib/Algebra/Lie/Weights/Cartan.lean index 17a743e544aa1..d979a55e0b938 100644 --- a/Mathlib/Algebra/Lie/Weights/Cartan.lean +++ b/Mathlib/Algebra/Lie/Weights/Cartan.lean @@ -31,7 +31,7 @@ suppress_compilation open Set variable {R L : Type*} [CommRing R] [LieRing L] [LieAlgebra R L] - (H : LieSubalgebra R L) [LieAlgebra.IsNilpotent R H] + (H : LieSubalgebra R L) [LieRing.IsNilpotent H] {M : Type*} [AddCommGroup M] [Module R M] [LieRingModule L M] [LieModule R L M] namespace LieAlgebra @@ -44,7 +44,7 @@ space of `L` regarded as a module of `H` via the adjoint action. -/ abbrev rootSpace (χ : H → R) : LieSubmodule R H L := genWeightSpace L χ -theorem zero_rootSpace_eq_top_of_nilpotent [IsNilpotent R L] : +theorem zero_rootSpace_eq_top_of_nilpotent [LieRing.IsNilpotent L] : rootSpace (⊤ : LieSubalgebra R L) 0 = ⊤ := zero_genWeightSpace_eq_top_of_nilpotent L @@ -170,7 +170,7 @@ theorem toLieSubmodule_le_rootSpace_zero : H.toLieSubmodule ≤ rootSpace H 0 := simp only [LieSubalgebra.mem_toLieSubmodule] at hx simp only [mem_genWeightSpace, Pi.zero_apply, sub_zero, zero_smul] intro y - obtain ⟨k, hk⟩ := (inferInstance : IsNilpotent R H) + obtain ⟨k, hk⟩ := IsNilpotent.nilpotent R H H use k let f : Module.End R H := toEnd R H H y let g : Module.End R L := toEnd R H L y diff --git a/Mathlib/Algebra/Lie/Weights/Chain.lean b/Mathlib/Algebra/Lie/Weights/Chain.lean index b2ba09bb4e2bd..14ab6cec6e4a9 100644 --- a/Mathlib/Algebra/Lie/Weights/Chain.lean +++ b/Mathlib/Algebra/Lie/Weights/Chain.lean @@ -50,7 +50,7 @@ namespace LieModule section IsNilpotent -variable [LieAlgebra.IsNilpotent R L] (χ₁ χ₂ : L → R) (p q : ℤ) +variable [LieRing.IsNilpotent L] (χ₁ χ₂ : L → R) (p q : ℤ) section @@ -121,7 +121,7 @@ open LieAlgebra variable {H : LieSubalgebra R L} (α χ : H → R) (p q : ℤ) -lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_right [LieAlgebra.IsNilpotent R H] +lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_right [LieRing.IsNilpotent H] (hq : genWeightSpace M (q • α + χ) = ⊥) {x : L} (hx : x ∈ rootSpace H α) {y : M} (hy : y ∈ genWeightSpaceChain M α χ p q) : @@ -144,7 +144,7 @@ lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_right [LieAlgebra.IsN | h0 => simp | hadd _ _ _ _ hz₁ hz₂ => rw [lie_add]; exact add_mem hz₁ hz₂ -lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_left [LieAlgebra.IsNilpotent R H] +lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_left [LieRing.IsNilpotent H] (hp : genWeightSpace M (p • α + χ) = ⊥) {x : L} (hx : x ∈ rootSpace H (-α)) {y : M} (hy : y ∈ genWeightSpaceChain M α χ p q) : @@ -234,7 +234,7 @@ end LieSubalgebra section variable {M} -variable [LieAlgebra.IsNilpotent R L] +variable [LieRing.IsNilpotent L] variable [NoZeroSMulDivisors ℤ R] [NoZeroSMulDivisors R M] [IsNoetherian R M] variable (α : L → R) (β : Weight R L M) diff --git a/Mathlib/Algebra/Lie/Weights/Linear.lean b/Mathlib/Algebra/Lie/Weights/Linear.lean index bd48f9a203f78..f52cb53419a1b 100644 --- a/Mathlib/Algebra/Lie/Weights/Linear.lean +++ b/Mathlib/Algebra/Lie/Weights/Linear.lean @@ -48,14 +48,14 @@ namespace LieModule /-- A typeclass encoding the fact that a given Lie module has linear weights, vanishing on the derived ideal. -/ -class LinearWeights [LieAlgebra.IsNilpotent R L] : Prop where +class LinearWeights [LieRing.IsNilpotent L] : Prop where map_add : ∀ χ : L → R, genWeightSpace M χ ≠ ⊥ → ∀ x y, χ (x + y) = χ x + χ y map_smul : ∀ χ : L → R, genWeightSpace M χ ≠ ⊥ → ∀ (t : R) x, χ (t • x) = t • χ x map_lie : ∀ χ : L → R, genWeightSpace M χ ≠ ⊥ → ∀ x y : L, χ ⁅x, y⁆ = 0 namespace Weight -variable [LieAlgebra.IsNilpotent R L] [LinearWeights R L M] (χ : Weight R L M) +variable [LieRing.IsNilpotent L] [LinearWeights R L M] (χ : Weight R L M) /-- A weight of a Lie module, bundled as a linear map. -/ @[simps] @@ -115,7 +115,7 @@ section FiniteDimensional open Module variable [IsDomain R] [IsPrincipalIdealRing R] [Module.Free R M] [Module.Finite R M] - [LieAlgebra.IsNilpotent R L] + [LieRing.IsNilpotent L] lemma trace_comp_toEnd_genWeightSpace_eq (χ : L → R) : LinearMap.trace R _ ∘ₗ (toEnd R L (genWeightSpace M χ)).toLinearMap = @@ -154,7 +154,7 @@ instance instLinearWeightsOfCharZero [CharZero R] : end FiniteDimensional -variable [LieAlgebra.IsNilpotent R L] (χ : L → R) +variable [LieRing.IsNilpotent L] (χ : L → R) /-- A type synonym for the `χ`-weight space but with the action of `x : L` on `m : genWeightSpace M χ`, shifted to act as `⁅x, m⁆ - χ x • m`. -/ @@ -222,15 +222,15 @@ lemma toEnd_eq (x : L) : /-- By Engel's theorem, if `M` is Noetherian, the shifted action `⁅x, m⁆ - χ x • m` makes the `χ`-weight space into a nilpotent Lie module. -/ -instance [IsNoetherian R M] : IsNilpotent R L (shiftedGenWeightSpace R L M χ) := +instance [IsNoetherian R M] : IsNilpotent L (shiftedGenWeightSpace R L M χ) := LieModule.isNilpotent_iff_forall'.mpr fun x ↦ isNilpotent_toEnd_sub_algebraMap M χ x end shiftedGenWeightSpace open shiftedGenWeightSpace in -/-- Given a Lie module `M` of a Lie algebra `L` with coefficients in `R`, if a function `χ : L → R` -has a simultaneous generalized eigenvector for the action of `L` then it has a simultaneous true -eigenvector, provided `M` is Noetherian and has linear weights. -/ +/-- Given a Lie module `M` of a nilpotent Lie algebra `L` with coefficients in `R`, +if a function `χ : L → R` has a simultaneous generalized eigenvector for the action of `L` +then it has a simultaneous true eigenvector, provided `M` is Noetherian and has linear weights. -/ lemma exists_forall_lie_eq_smul [LinearWeights R L M] [IsNoetherian R M] (χ : Weight R L M) : ∃ m : M, m ≠ 0 ∧ ∀ x : L, ⁅x, m⁆ = χ x • m := by replace hχ : Nontrivial (shiftedGenWeightSpace R L M χ) := @@ -247,7 +247,7 @@ lemma exists_forall_lie_eq_smul [LinearWeights R L M] [IsNoetherian R M] (χ : W /-- See `LieModule.exists_nontrivial_weightSpace_of_isSolvable` for the variant that only assumes that `L` is solvable but additionally requires `k` to be of characteristic zero. -/ lemma exists_nontrivial_weightSpace_of_isNilpotent [Field k] [LieAlgebra k L] [Module k M] - [Module.Finite k M] [LieModule k L M] [LieAlgebra.IsNilpotent k L] [LinearWeights k L M] + [Module.Finite k M] [LieModule k L M] [LinearWeights k L M] [IsTriangularizable k L M] [Nontrivial M] : ∃ χ : Module.Dual k L, Nontrivial (weightSpace M χ) := by obtain ⟨χ⟩ : Nonempty (Weight k L M) := by From 7a48271ef6d19875f9e51e1a281eb3c254e60c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Wed, 8 Jan 2025 08:24:56 +0000 Subject: [PATCH 074/681] feat: misc. lemmas about moments, tilted measures (#20150) Co-authored-by: RemyDegenne --- .../Function/SpecialFunctions/Basic.lean | 14 +++++++---- Mathlib/MeasureTheory/Measure/Tilted.lean | 18 ++++++++------- .../MeasureTheory/Order/Group/Lattice.lean | 7 +++++- Mathlib/Probability/Moments.lean | 23 +++++++++++++++++-- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean b/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean index e072184cd1af6..2074623647f98 100644 --- a/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean +++ b/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean @@ -28,6 +28,8 @@ open NNReal ENNReal MeasureTheory namespace Real +variable {α : Type*} {_ : MeasurableSpace α} {f : α → ℝ} {μ : MeasureTheory.Measure α} + @[measurability] theorem measurable_exp : Measurable exp := continuous_exp.measurable @@ -37,20 +39,24 @@ theorem measurable_log : Measurable log := measurable_of_measurable_on_compl_singleton 0 <| Continuous.measurable <| continuousOn_iff_continuous_restrict.1 continuousOn_log -lemma measurable_of_measurable_exp {α : Type*} {_ : MeasurableSpace α} {f : α → ℝ} - (hf : Measurable (fun x ↦ exp (f x))) : +lemma measurable_of_measurable_exp (hf : Measurable (fun x ↦ exp (f x))) : Measurable f := by have : f = fun x ↦ log (exp (f x)) := by ext; rw [log_exp] rw [this] exact measurable_log.comp hf -lemma aemeasurable_of_aemeasurable_exp {α : Type*} {_ : MeasurableSpace α} {f : α → ℝ} - {μ : MeasureTheory.Measure α} (hf : AEMeasurable (fun x ↦ exp (f x)) μ) : +lemma aemeasurable_of_aemeasurable_exp (hf : AEMeasurable (fun x ↦ exp (f x)) μ) : AEMeasurable f μ := by have : f = fun x ↦ log (exp (f x)) := by ext; rw [log_exp] rw [this] exact measurable_log.comp_aemeasurable hf +lemma aemeasurable_of_aemeasurable_exp_mul {t : ℝ} + (ht : t ≠ 0) (hf : AEMeasurable (fun x ↦ exp (t * f x)) μ) : + AEMeasurable f μ := by + simpa only [mul_div_cancel_left₀ _ ht] + using (aemeasurable_of_aemeasurable_exp hf).div (aemeasurable_const (b := t)) + @[measurability] theorem measurable_sin : Measurable sin := continuous_sin.measurable diff --git a/Mathlib/MeasureTheory/Measure/Tilted.lean b/Mathlib/MeasureTheory/Measure/Tilted.lean index 78793a1d88732..a599a9994646b 100644 --- a/Mathlib/MeasureTheory/Measure/Tilted.lean +++ b/Mathlib/MeasureTheory/Measure/Tilted.lean @@ -119,14 +119,6 @@ lemma tilted_apply_eq_ofReal_integral [SFinite μ] (f : α → ℝ) (s : Set α) · exact ae_of_all _ (fun _ ↦ by positivity) · simp [tilted_of_not_integrable hf, integral_undef hf] -instance isFiniteMeasure_tilted : IsFiniteMeasure (μ.tilted f) := by - by_cases hf : Integrable (fun x ↦ exp (f x)) μ - · refine isFiniteMeasure_withDensity_ofReal ?_ - suffices Integrable (fun x ↦ exp (f x) / ∫ x, exp (f x) ∂μ) μ by exact this.2 - exact hf.div_const _ - · simp only [hf, not_false_eq_true, tilted_of_not_integrable] - infer_instance - lemma isProbabilityMeasure_tilted [NeZero μ] (hf : Integrable (fun x ↦ exp (f x)) μ) : IsProbabilityMeasure (μ.tilted f) := by constructor @@ -139,6 +131,16 @@ lemma isProbabilityMeasure_tilted [NeZero μ] (hf : Integrable (fun x ↦ exp (f exact integral_exp_pos hf · simp +instance isZeroOrProbabilityMeasure_tilted : IsZeroOrProbabilityMeasure (μ.tilted f) := by + rcases eq_zero_or_neZero μ with hμ | hμ + · simp only [hμ, tilted_zero_measure] + infer_instance + by_cases hf : Integrable (fun x ↦ exp (f x)) μ + · have := isProbabilityMeasure_tilted hf + infer_instance + · simp only [hf, not_false_eq_true, tilted_of_not_integrable] + infer_instance + section lintegral lemma setLIntegral_tilted' (f : α → ℝ) (g : α → ℝ≥0∞) {s : Set α} (hs : MeasurableSet s) : diff --git a/Mathlib/MeasureTheory/Order/Group/Lattice.lean b/Mathlib/MeasureTheory/Order/Group/Lattice.lean index da3f3746b9d09..6b39cae592902 100644 --- a/Mathlib/MeasureTheory/Order/Group/Lattice.lean +++ b/Mathlib/MeasureTheory/Order/Group/Lattice.lean @@ -44,6 +44,11 @@ variable [MeasurableSup₂ α] theorem measurable_mabs : Measurable (mabs : α → α) := measurable_id'.sup measurable_inv -@[to_additive (attr := measurability)] +@[to_additive (attr := measurability, fun_prop)] protected theorem Measurable.mabs (hf : Measurable f) : Measurable fun x ↦ mabs (f x) := measurable_mabs.comp hf + +@[to_additive (attr := measurability, fun_prop)] +protected theorem AEMeasurable.mabs {μ : MeasureTheory.Measure β} (hf : AEMeasurable f μ) : + AEMeasurable (fun x ↦ mabs (f x)) μ := + measurable_mabs.comp_aemeasurable hf diff --git a/Mathlib/Probability/Moments.lean b/Mathlib/Probability/Moments.lean index b6c17d414699d..7e8db5fd848ce 100644 --- a/Mathlib/Probability/Moments.lean +++ b/Mathlib/Probability/Moments.lean @@ -59,11 +59,18 @@ theorem moment_zero (hp : p ≠ 0) : moment 0 p μ = 0 := by simp only [moment, hp, zero_pow, Ne, not_false_iff, Pi.zero_apply, integral_const, smul_eq_mul, mul_zero, integral_zero] +@[simp] +lemma moment_zero_measure : moment X p (0 : Measure Ω) = 0 := by simp [moment] + @[simp] theorem centralMoment_zero (hp : p ≠ 0) : centralMoment 0 p μ = 0 := by simp only [centralMoment, hp, Pi.zero_apply, integral_const, smul_eq_mul, mul_zero, zero_sub, Pi.pow_apply, Pi.neg_apply, neg_zero, zero_pow, Ne, not_false_iff] +@[simp] +lemma centralMoment_zero_measure : centralMoment X p (0 : Measure Ω) = 0 := by + simp [centralMoment] + theorem centralMoment_one' [IsFiniteMeasure μ] (h_int : Integrable X μ) : centralMoment X 1 μ = (1 - (μ Set.univ).toReal) * μ[X] := by simp only [centralMoment, Pi.sub_apply, pow_one] @@ -118,7 +125,6 @@ theorem cgf_zero_measure : cgf X (0 : Measure Ω) t = 0 := by theorem mgf_const' (c : ℝ) : mgf (fun _ => c) μ t = (μ Set.univ).toReal * exp (t * c) := by simp only [mgf, integral_const, smul_eq_mul] --- @[simp] -- Porting note: `simp only` already proves this theorem mgf_const (c : ℝ) [IsProbabilityMeasure μ] : mgf (fun _ => c) μ t = exp (t * c) := by simp only [mgf_const', measure_univ, ENNReal.one_toReal, one_mul] @@ -139,7 +145,6 @@ theorem cgf_const [IsProbabilityMeasure μ] (c : ℝ) : cgf (fun _ => c) μ t = theorem mgf_zero' : mgf X μ 0 = (μ Set.univ).toReal := by simp only [mgf, zero_mul, exp_zero, integral_const, smul_eq_mul, mul_one] --- @[simp] -- Porting note: `simp only` already proves this theorem mgf_zero [IsProbabilityMeasure μ] : mgf X μ 0 = 1 := by simp only [mgf_zero', measure_univ, ENNReal.one_toReal] @@ -180,6 +185,12 @@ theorem mgf_pos [IsProbabilityMeasure μ] (h_int_X : Integrable (fun ω => exp ( 0 < mgf X μ t := mgf_pos' (IsProbabilityMeasure.ne_zero μ) h_int_X +lemma exp_cgf_of_neZero [hμ : NeZero μ] (hX : Integrable (fun ω ↦ exp (t * X ω)) μ) : + exp (cgf X μ t) = mgf X μ t := by rw [cgf, exp_log (mgf_pos' hμ.out hX)] + +lemma exp_cgf [IsProbabilityMeasure μ] (hX : Integrable (fun ω ↦ exp (t * X ω)) μ) : + exp (cgf X μ t) = mgf X μ t := by rw [cgf, exp_log (mgf_pos hX)] + lemma mgf_id_map (hX : AEMeasurable X μ) : mgf id (μ.map X) = mgf X μ := by ext t rw [mgf, integral_map hX] @@ -202,6 +213,8 @@ theorem mgf_const_add (α : ℝ) : mgf (fun ω => α + X ω) μ t = exp (t * α) theorem mgf_add_const (α : ℝ) : mgf (fun ω => X ω + α) μ t = mgf X μ t * exp (t * α) := by simp only [add_comm, mgf_const_add, mul_comm] +section IndepFun + /-- This is a trivial application of `IndepFun.comp` but it will come up frequently. -/ theorem IndepFun.exp_mul {X Y : Ω → ℝ} (h_indep : IndepFun X Y μ) (s t : ℝ) : IndepFun (fun ω => exp (s * X ω)) (fun ω => exp (t * Y ω)) μ := by @@ -302,6 +315,8 @@ theorem iIndepFun.cgf_sum {X : ι → Ω → ℝ} · rw [h_indep.mgf_sum h_meas] · exact (mgf_pos (h_int j hj)).ne' +end IndepFun + theorem mgf_congr_of_identDistrib (X : Ω → ℝ) {Ω' : Type*} {m' : MeasurableSpace Ω'} {μ' : Measure Ω'} (X' : Ω' → ℝ) (hident : IdentDistrib X X' μ μ') (t : ℝ) : @@ -318,6 +333,8 @@ theorem mgf_sum_of_identDistrib exact Finset.prod_eq_pow_card fun i hi => mgf_congr_of_identDistrib (X i) (X j) (hident i hi j hj) t +section Chernoff + /-- **Chernoff bound** on the upper tail of a real random variable. -/ theorem measure_ge_le_exp_mul_mgf [IsFiniteMeasure μ] (ε : ℝ) (ht : 0 ≤ t) (h_int : Integrable (fun ω => exp (t * X ω)) μ) : @@ -367,6 +384,8 @@ theorem measure_le_le_exp_cgf [IsFiniteMeasure μ] (ε : ℝ) (ht : t ≤ 0) rw [exp_add] exact mul_le_mul le_rfl (le_exp_log _) mgf_nonneg (exp_pos _).le +end Chernoff + lemma mgf_dirac {x : ℝ} (hX : μ.map X = .dirac x) (t : ℝ) : mgf X μ t = exp (x * t) := by have : IsProbabilityMeasure (μ.map X) := by rw [hX]; infer_instance rw [← mgf_id_map (.of_map_ne_zero <| IsProbabilityMeasure.ne_zero _), mgf, hX, integral_dirac, From 7cfa4bd7c9455166495fb83973d59cae190b9f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 8 Jan 2025 11:28:27 +0000 Subject: [PATCH 075/681] feat: the Boolean subalgebra generated by the lattice generated by a set (#20440) ... is just the Boolean subalgebra generated by that set. --- Mathlib/Order/BooleanSubalgebra.lean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mathlib/Order/BooleanSubalgebra.lean b/Mathlib/Order/BooleanSubalgebra.lean index f26406cb0a2f0..bf798efa14b9a 100644 --- a/Mathlib/Order/BooleanSubalgebra.lean +++ b/Mathlib/Order/BooleanSubalgebra.lean @@ -344,6 +344,12 @@ lemma subset_closure : s ⊆ closure s := fun _ hx ↦ mem_closure.2 fun _ hK lemma closure_mono (hst : s ⊆ t) : closure s ≤ closure t := sInf_le_sInf fun _L ↦ hst.trans +lemma latticeClosure_subset_closure : latticeClosure s ⊆ closure s := + latticeClosure_min subset_closure (closure s).isSublattice + +@[simp] lemma closure_latticeClosure (s : Set α) : closure (latticeClosure s) = closure s := + le_antisymm (closure_le.2 latticeClosure_subset_closure) (closure_mono subset_latticeClosure) + /-- An induction principle for closure membership. If `p` holds for `⊥` and all elements of `s`, and is preserved under suprema and complement, then `p` holds for all elements of the closure of `s`. -/ @[elab_as_elim] From a5183c326646823ecb22396451678a2acb764ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 8 Jan 2025 12:15:23 +0000 Subject: [PATCH 076/681] =?UTF-8?q?feat:=20`|=E2=88=AB=20a,=20f=20a=20?= =?UTF-8?q?=E2=88=82=CE=BC|=20=E2=89=A4=20=E2=88=AB=20a,=20|f=20a|=20?= =?UTF-8?q?=E2=88=82=CE=BC`=20(#20540)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From LeanAPAP --- Mathlib/MeasureTheory/Integral/Bochner.lean | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index dd20d7982e08b..2720940a760a3 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -1367,6 +1367,9 @@ theorem norm_integral_le_integral_norm (f : α → G) : ‖∫ a, f a ∂μ‖ · rw [integral_non_aestronglyMeasurable h, norm_zero] exact integral_nonneg_of_ae le_ae +lemma abs_integral_le_integral_abs {f : α → ℝ} : |∫ a, f a ∂μ| ≤ ∫ a, |f a| ∂μ := + norm_integral_le_integral_norm f + theorem norm_integral_le_of_norm_le {f : α → G} {g : α → ℝ} (hg : Integrable g μ) (h : ∀ᵐ x ∂μ, ‖f x‖ ≤ g x) : ‖∫ x, f x ∂μ‖ ≤ ∫ x, g x ∂μ := calc From af8eed890c34bb9b7ca0aa05f10dfb15f7f42e53 Mon Sep 17 00:00:00 2001 From: Dagur Asgeirsson Date: Wed, 8 Jan 2025 12:15:24 +0000 Subject: [PATCH 077/681] chore(CategoryTheory): remove data produced by tactic block (#20565) --- .../CategoryTheory/EffectiveEpi/Coproduct.lean | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean b/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean index 80a53351c358d..87c5560d945e1 100644 --- a/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean +++ b/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean @@ -36,20 +36,12 @@ def effectiveEpiStructIsColimitDescOfEffectiveEpiFamily {B : C} {α : Type*} (X uniq e _ m hm := EffectiveEpiFamily.uniq X π (fun a ↦ c.ι.app ⟨a⟩ ≫ e) (fun _ _ _ _ hg ↦ (by simp [← hm, reassoc_of% hg])) m (fun _ ↦ (by simp [← hm])) -/-- -Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an -`EffectiveEpi`. --/ -noncomputable -def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C) - (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] : - EffectiveEpiStruct (Sigma.desc π) := by - simpa [coproductIsCoproduct] using - effectiveEpiStructIsColimitDescOfEffectiveEpiFamily X _ (coproductIsCoproduct _) π - instance {B : C} {α : Type*} (X : α → C) (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] - [EffectiveEpiFamily X π] : EffectiveEpi (Sigma.desc π) := - ⟨⟨effectiveEpiStructDescOfEffectiveEpiFamily X π⟩⟩ + [EffectiveEpiFamily X π] : EffectiveEpi (Sigma.desc π) := by + let e := effectiveEpiStructIsColimitDescOfEffectiveEpiFamily X _ (coproductIsCoproduct _) π + simp only [Cofan.mk_pt, coproductIsCoproduct, colimit.cocone_x, IsColimit.ofIsoColimit_desc, + Cocones.ext_inv_hom, Iso.refl_inv, colimit.isColimit_desc, Category.id_comp] at e + exact ⟨⟨e⟩⟩ example {B : C} {α : Type*} (X : α → C) (π : (a : α) → (X a ⟶ B)) [EffectiveEpiFamily X π] [HasCoproduct X] : Epi (Sigma.desc π) := inferInstance From f890906945232a38372574e90cb98e3a9ad2dd50 Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Wed, 8 Jan 2025 12:28:18 +0000 Subject: [PATCH 078/681] =?UTF-8?q?feat(GroupTheory/Subgroup/Centralizer):?= =?UTF-8?q?=20`f(C(S))=20=E2=89=A4=20C(f(S))`=20(#20356)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR proves that the image of a centralizer is contained in the centralizer of the image. --- Mathlib/GroupTheory/Subgroup/Centralizer.lean | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Mathlib/GroupTheory/Subgroup/Centralizer.lean b/Mathlib/GroupTheory/Subgroup/Centralizer.lean index 70ce36b8a26b4..56e9672b715a0 100644 --- a/Mathlib/GroupTheory/Subgroup/Centralizer.lean +++ b/Mathlib/GroupTheory/Subgroup/Centralizer.lean @@ -11,7 +11,7 @@ import Mathlib.GroupTheory.Submonoid.Centralizer # Centralizers of subgroups -/ -variable {G : Type*} [Group G] +variable {G G' : Type*} [Group G] [Group G'] namespace Subgroup @@ -60,6 +60,12 @@ theorem centralizer_le {s t : Set G} (h : s ⊆ t) : centralizer t ≤ centraliz theorem centralizer_eq_top_iff_subset {s : Set G} : centralizer s = ⊤ ↔ s ⊆ center G := SetLike.ext'_iff.trans Set.centralizer_eq_top_iff_subset +@[to_additive] +theorem map_centralizer_le_centralizer_image (s : Set G) (f : G →* G') : + (Subgroup.centralizer s).map f ≤ Subgroup.centralizer (f '' s) := by + rintro - ⟨g, hg, rfl⟩ - ⟨h, hh, rfl⟩ + rw [← map_mul, ← map_mul, hg h hh] + @[to_additive] instance Centralizer.characteristic [hH : H.Characteristic] : (centralizer (H : Set G)).Characteristic := by From 5cd69fff626264e5bbb442ef9fb587b52a2beed0 Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Wed, 8 Jan 2025 12:28:19 +0000 Subject: [PATCH 079/681] feat(RingTheory/PowerSeries): basic API about truncation (#20426) --- Mathlib/RingTheory/MvPowerSeries/Trunc.lean | 12 ++++++++++- Mathlib/RingTheory/PowerSeries/Basic.lean | 2 ++ Mathlib/RingTheory/PowerSeries/Trunc.lean | 22 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Mathlib/RingTheory/MvPowerSeries/Trunc.lean b/Mathlib/RingTheory/MvPowerSeries/Trunc.lean index 4c1ecd9d3176f..17bb1c78178bd 100644 --- a/Mathlib/RingTheory/MvPowerSeries/Trunc.lean +++ b/Mathlib/RingTheory/MvPowerSeries/Trunc.lean @@ -29,7 +29,7 @@ namespace MvPowerSeries open Finsupp -variable {σ R : Type*} +variable {σ R S : Type*} section Trunc @@ -94,6 +94,16 @@ theorem trunc_c (n : σ →₀ ℕ) (hnn : n ≠ 0) (a : R) : trunc R n (C σ R split_ifs with H <;> first |rfl|try simp_all only [ne_eq, not_true_eq_false] exfalso; apply H; subst m; exact Ne.bot_lt hnn +@[simp] +theorem trunc_C_mul (n : σ →₀ ℕ) (a : R) (p : MvPowerSeries σ R) : + trunc R n (C σ R a * p) = MvPolynomial.C a * trunc R n p := by + ext m; simp [coeff_trunc] + +@[simp] +theorem trunc_map [CommSemiring S] (n : σ →₀ ℕ) (f : R →+* S) (p : MvPowerSeries σ R) : + trunc S n (map σ f p) = MvPolynomial.map f (trunc R n p) := by + ext m; simp [coeff_trunc, MvPolynomial.coeff_map, apply_ite f] + end Trunc end MvPowerSeries diff --git a/Mathlib/RingTheory/PowerSeries/Basic.lean b/Mathlib/RingTheory/PowerSeries/Basic.lean index 6baea6db2fd4a..798c473721bd8 100644 --- a/Mathlib/RingTheory/PowerSeries/Basic.lean +++ b/Mathlib/RingTheory/PowerSeries/Basic.lean @@ -199,6 +199,8 @@ def constantCoeff : R⟦X⟧ →+* R := def C : R →+* R⟦X⟧ := MvPowerSeries.C Unit R +@[simp] lemma algebraMap_eq {R : Type*} [CommSemiring R] : algebraMap R R⟦X⟧ = C R := rfl + variable {R} /-- The variable of the formal power series ring. -/ diff --git a/Mathlib/RingTheory/PowerSeries/Trunc.lean b/Mathlib/RingTheory/PowerSeries/Trunc.lean index 3362013251ac5..764b258ec87db 100644 --- a/Mathlib/RingTheory/PowerSeries/Trunc.lean +++ b/Mathlib/RingTheory/PowerSeries/Trunc.lean @@ -129,6 +129,20 @@ lemma trunc_X_of {n : ℕ} (hn : 2 ≤ n) : trunc n X = (Polynomial.X : R[X]) := | zero => contradiction | succ n => exact trunc_X n +@[simp] +lemma trunc_one_left (p : R⟦X⟧) : trunc (R := R) 1 p = .C (coeff R 0 p) := by + ext i; simp +contextual [coeff_trunc, Polynomial.coeff_C] + +lemma trunc_one_X : trunc (R := R) 1 X = 0 := by simp + +@[simp] +lemma trunc_C_mul (n : ℕ) (r : R) (f : R⟦X⟧) : trunc n (C R r * f) = .C r * trunc n f := by + ext i; simp [coeff_trunc] + +@[simp] +lemma trunc_mul_C (n : ℕ) (f : R⟦X⟧) (r : R) : trunc n (f * C R r) = trunc n f * .C r := by + ext i; simp [coeff_trunc] + end Trunc section Trunc @@ -211,6 +225,14 @@ theorem coeff_mul_eq_coeff_trunc_mul_trunc {d n} (f g) (h : d < n) : end Trunc +section Map +variable {S : Type*} [Semiring R] [Semiring S] (f : R →+* S) + +lemma trunc_map (p : R⟦X⟧) (n : ℕ) : (p.map f).trunc n = (p.trunc n).map f := by + ext m; simp [coeff_trunc, apply_ite f] + +end Map + end PowerSeries end From 0276568c8b8ab2ced9f581e085dba20202ac5fa0 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 8 Jan 2025 13:17:01 +0000 Subject: [PATCH 080/681] chore(Data/Nat/Bitwise) deprecate upstreamed lemma 'bitwise_lt' (#20284) Replaces `bitwise_lt` with a deprecated alias to [`bitwise_lt_two_pow`](https://github.com/leanprover/lean4/blob/fe45ddd6105078a0a3bd855e5d94673e794f6b88/src/Init/Data/Nat/Bitwise/Lemmas.lean#L428-L453), which was added to core in https://github.com/leanprover/lean4/commit/ca941249b98a2da3959e0b2b7d9311c647795778. Found by [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). --- Mathlib/Data/Nat/Bitwise.lean | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/Mathlib/Data/Nat/Bitwise.lean b/Mathlib/Data/Nat/Bitwise.lean index c321ba243c9b5..a6025b1de46a2 100644 --- a/Mathlib/Data/Nat/Bitwise.lean +++ b/Mathlib/Data/Nat/Bitwise.lean @@ -368,29 +368,15 @@ theorem even_xor {m n : ℕ} : Even (m ^^^ n) ↔ (Even m ↔ Even n) := by @[simp] theorem bit_lt_two_pow_succ_iff {b x n} : bit b x < 2 ^ (n + 1) ↔ x < 2 ^ n := by cases b <;> simp <;> omega -/-- If `x` and `y` fit within `n` bits, then the result of any bitwise operation on `x` and `y` also -fits within `n` bits -/ -theorem bitwise_lt {f x y n} (hx : x < 2 ^ n) (hy : y < 2 ^ n) : - bitwise f x y < 2 ^ n := by - induction x using Nat.binaryRec' generalizing n y with - | z => - simp only [bitwise_zero_left] - split <;> assumption - | @f bx nx hnx ih => - cases y using Nat.binaryRec' with - | z => - simp only [bitwise_zero_right] - split <;> assumption - | f «by» ny hny => - rw [bitwise_bit' _ _ _ _ hnx hny] - cases n <;> simp_all +@[deprecated bitwise_lt_two_pow (since := "2024-12-28")] +alias bitwise_lt := bitwise_lt_two_pow lemma shiftLeft_lt {x n m : ℕ} (h : x < 2 ^ n) : x <<< m < 2 ^ (n + m) := by simp only [Nat.pow_add, shiftLeft_eq, Nat.mul_lt_mul_right (Nat.two_pow_pos _), h] /-- Note that the LHS is the expression used within `Std.BitVec.append`, hence the name. -/ lemma append_lt {x y n m} (hx : x < 2 ^ n) (hy : y < 2 ^ m) : y <<< n ||| x < 2 ^ (n + m) := by - apply bitwise_lt + apply bitwise_lt_two_pow · rw [add_comm]; apply shiftLeft_lt hy · apply lt_of_lt_of_le hx <| Nat.pow_le_pow_right (le_succ _) (le_add_right _ _) From 340e6d1bc501422c4f0b8c08ec00f7939d7f2be5 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 8 Jan 2025 13:17:03 +0000 Subject: [PATCH 081/681] chore: fixes to compile under `debug.proofAsSorry` (#20561) We are quite far from actually making that possible, but as I was looking into it again I'll at least preserve these minor fixes. --- Mathlib/CategoryTheory/Category/ReflQuiv.lean | 9 ++++----- Mathlib/CategoryTheory/Elements.lean | 9 ++++----- Mathlib/CategoryTheory/FiberedCategory/Fiber.lean | 4 ++-- Mathlib/CategoryTheory/Functor/FunctorHom.lean | 2 +- Mathlib/Order/Defs/Unbundled.lean | 2 +- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Mathlib/CategoryTheory/Category/ReflQuiv.lean b/Mathlib/CategoryTheory/Category/ReflQuiv.lean index 8ec09b21eeb6e..0307f1d32f223 100644 --- a/Mathlib/CategoryTheory/Category/ReflQuiv.lean +++ b/Mathlib/CategoryTheory/Category/ReflQuiv.lean @@ -204,15 +204,14 @@ theorem adj.unit.component_eq (V : ReflQuiv.{max u v, u}) : /-- The counit components are defined using the universal property of the quotient from the corresponding counit component for the adjunction between categories and quivers.-/ @[simps!] -def adj.counit.app (C : Cat) : Cat.freeRefl.obj (forget.obj C) ⥤ C := by - fapply Quotient.lift - · exact Quiv.adj.counit.app C - · intro x y f g rel +def adj.counit.app (C : Cat) : Cat.freeRefl.obj (forget.obj C) ⥤ C := + Quotient.lift Cat.FreeReflRel (Quiv.adj.counit.app C) (by + intro x y f g rel cases rel unfold Quiv.adj simp only [Adjunction.mkOfHomEquiv_counit_app, Equiv.coe_fn_symm_mk, Quiv.lift_map, Prefunctor.mapPath_toPath, composePath_toPath] - rfl + rfl) /-- The counit of `ReflQuiv.adj` is closely related to the counit of `Quiv.adj`.-/ @[simp] diff --git a/Mathlib/CategoryTheory/Elements.lean b/Mathlib/CategoryTheory/Elements.lean index 01aa8d0ac97b7..d910c5b913178 100644 --- a/Mathlib/CategoryTheory/Elements.lean +++ b/Mathlib/CategoryTheory/Elements.lean @@ -201,12 +201,11 @@ given by `CategoryTheory.yonedaEquiv`. @[simps] def toCostructuredArrow (F : Cᵒᵖ ⥤ Type v) : F.Elementsᵒᵖ ⥤ CostructuredArrow yoneda F where obj X := CostructuredArrow.mk (yonedaEquiv.symm (unop X).2) - map f := by - fapply CostructuredArrow.homMk - · exact f.unop.val.unop - · ext Z y + map f := + CostructuredArrow.homMk f.unop.val.unop (by + ext Z y dsimp [yonedaEquiv] - simp only [FunctorToTypes.map_comp_apply, ← f.unop.2] + simp only [FunctorToTypes.map_comp_apply, ← f.unop.2]) /-- The reverse direction of the equivalence `F.Elementsᵒᵖ ≅ (yoneda, F)`, given by `CategoryTheory.yonedaEquiv`. diff --git a/Mathlib/CategoryTheory/FiberedCategory/Fiber.lean b/Mathlib/CategoryTheory/FiberedCategory/Fiber.lean index 94cfb1727d195..d5e2c539e3f7e 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/Fiber.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/Fiber.lean @@ -102,10 +102,10 @@ variable {p : 𝒳 ⥤ 𝒮} {S : 𝒮} {C : Type u₃} [Category.{v₃} C] {F : /-- Given a functor `F : C ⥤ 𝒳` such that `F ⋙ p` is constant at some `S : 𝒮`, then we get an induced functor `C ⥤ Fiber p S` that `F` factors through. -/ -@[simps] def inducedFunctor : C ⥤ Fiber p S where obj x := ⟨F.obj x, by simp only [← comp_obj, hF, const_obj_obj]⟩ - map φ := ⟨F.map φ, of_commsq _ _ _ _ _ <| by simpa using (eqToIso hF).hom.naturality φ⟩ + map φ := ⟨F.map φ, of_commsq _ _ _ (congr_obj hF _) (congr_obj hF _) <| + by simpa using (eqToIso hF).hom.naturality φ⟩ @[simp] lemma inducedFunctor_map {X Y : C} (f : X ⟶ Y) : diff --git a/Mathlib/CategoryTheory/Functor/FunctorHom.lean b/Mathlib/CategoryTheory/Functor/FunctorHom.lean index be91d1395df1e..c070e0ed4f0d8 100644 --- a/Mathlib/CategoryTheory/Functor/FunctorHom.lean +++ b/Mathlib/CategoryTheory/Functor/FunctorHom.lean @@ -145,7 +145,7 @@ def natTransEquiv : (𝟙_ (C ⥤ Type max v' v u) ⟶ F.functorHom G) ≃ (F have := HomObj.congr_app (congr_fun (f.naturality φ) PUnit.unit) Y (𝟙 Y) dsimp [functorHom, homObjFunctor] at this aesop ⟩ - invFun f := ⟨fun _ _ ↦ HomObj.ofNatTrans f, _⟩ + invFun f := { app _ _ := HomObj.ofNatTrans f } left_inv f := by ext X a Y φ have := HomObj.congr_app (congr_fun (f.naturality φ) PUnit.unit) Y (𝟙 Y) diff --git a/Mathlib/Order/Defs/Unbundled.lean b/Mathlib/Order/Defs/Unbundled.lean index c666d5f19cd3b..4b1a07444ecad 100644 --- a/Mathlib/Order/Defs/Unbundled.lean +++ b/Mathlib/Order/Defs/Unbundled.lean @@ -148,7 +148,7 @@ instance IsSymm.decide [DecidableRel r] [IsSymm α r] : instance IsAntisymm.decide [DecidableRel r] [IsAntisymm α r] : IsAntisymm α (fun a b => decide (r a b) = true) where - antisymm := fun a b h₁ h₂ => antisymm _ _ (by simpa using h₁) (by simpa using h₂) + antisymm a b h₁ h₂ := antisymm (r := r) _ _ (by simpa using h₁) (by simpa using h₂) instance IsAsymm.decide [DecidableRel r] [IsAsymm α r] : IsAsymm α (fun a b => decide (r a b) = true) where From 0fe74732b679f28f3cf40e9886154358182c25b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 8 Jan 2025 13:31:05 +0000 Subject: [PATCH 082/681] chore(Algebra/CharP/Basic): don't import `IsSimpleRing` (#20550) --- Mathlib/Algebra/Algebra/ZMod.lean | 1 + Mathlib/Algebra/CharP/Algebra.lean | 12 ++++++++---- Mathlib/Algebra/CharP/Basic.lean | 8 +++----- Mathlib/Algebra/Homology/Bifunctor.lean | 1 + Mathlib/Algebra/Homology/BifunctorAssociator.lean | 2 ++ Mathlib/Algebra/Homology/BifunctorHomotopy.lean | 2 ++ Mathlib/Algebra/Homology/BifunctorShift.lean | 2 ++ Mathlib/Algebra/Homology/ComplexShapeSigns.lean | 2 ++ Mathlib/Algebra/Homology/DerivedCategory/Basic.lean | 2 ++ .../Homology/DerivedCategory/ExactFunctor.lean | 2 ++ .../Algebra/Homology/DerivedCategory/Ext/Basic.lean | 2 ++ .../Homology/DerivedCategory/Ext/ExactSequences.lean | 2 ++ .../Homology/DerivedCategory/Ext/ExtClass.lean | 2 ++ .../Homology/DerivedCategory/HomologySequence.lean | 2 ++ .../Algebra/Homology/DerivedCategory/ShortExact.lean | 2 ++ .../Homology/DerivedCategory/SingleTriangle.lean | 2 ++ .../Homology/HomotopyCategory/DegreewiseSplit.lean | 5 ++++- .../Homology/HomotopyCategory/HomComplex.lean | 2 ++ .../Homology/HomotopyCategory/HomComplexShift.lean | 2 ++ .../HomotopyCategory/HomologicalFunctor.lean | 2 ++ .../Homology/HomotopyCategory/MappingCone.lean | 2 ++ .../Homology/HomotopyCategory/Pretriangulated.lean | 2 ++ Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean | 2 ++ .../Homology/HomotopyCategory/ShiftSequence.lean | 2 ++ .../Homology/HomotopyCategory/ShortExact.lean | 2 ++ .../Homology/HomotopyCategory/SingleFunctors.lean | 2 ++ .../Homology/HomotopyCategory/Triangulated.lean | 2 ++ Mathlib/Algebra/Homology/Monoidal.lean | 2 ++ Mathlib/Algebra/Homology/TotalComplex.lean | 2 ++ Mathlib/Algebra/Homology/TotalComplexShift.lean | 2 ++ Mathlib/Algebra/Homology/TotalComplexSymmetry.lean | 3 +++ Mathlib/Algebra/Module/ZMod.lean | 2 ++ Mathlib/Algebra/Order/ToIntervalMod.lean | 1 + Mathlib/Algebra/Periodic.lean | 1 + Mathlib/Algebra/Ring/NegOnePow.lean | 2 ++ .../CategoryTheory/Localization/Triangulated.lean | 2 ++ .../CategoryTheory/Sites/SheafCohomology/Basic.lean | 2 ++ Mathlib/CategoryTheory/Triangulated/Adjunction.lean | 2 ++ Mathlib/CategoryTheory/Triangulated/Functor.lean | 2 ++ .../Triangulated/Opposite/Functor.lean | 2 ++ .../Triangulated/Opposite/Pretriangulated.lean | 2 ++ .../CategoryTheory/Triangulated/Pretriangulated.lean | 1 + Mathlib/CategoryTheory/Triangulated/Subcategory.lean | 2 ++ .../Triangulated/TStructure/Basic.lean | 2 ++ .../CategoryTheory/Triangulated/TriangleShift.lean | 2 ++ .../CategoryTheory/Triangulated/Triangulated.lean | 1 + Mathlib/CategoryTheory/Triangulated/Yoneda.lean | 2 ++ Mathlib/Combinatorics/Additive/AP/Three/Defs.lean | 3 +++ Mathlib/Combinatorics/Additive/Corner/Defs.lean | 3 +++ Mathlib/Combinatorics/Additive/FreimanHom.lean | 3 +++ Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean | 1 + Mathlib/Combinatorics/SimpleGraph/Matching.lean | 2 ++ .../Combinatorics/SimpleGraph/UniversalVerts.lean | 2 ++ Mathlib/Data/Nat/Periodic.lean | 1 + Mathlib/Data/ZMod/Aut.lean | 2 ++ Mathlib/Data/ZMod/Basic.lean | 1 + Mathlib/Data/ZMod/Coprime.lean | 1 + Mathlib/Data/ZMod/Factorial.lean | 2 ++ Mathlib/Data/ZMod/IntUnitsPower.lean | 3 +++ Mathlib/Data/ZMod/Units.lean | 1 + Mathlib/FieldTheory/Perfect.lean | 3 ++- Mathlib/GroupTheory/CommutingProbability.lean | 3 +++ Mathlib/GroupTheory/Coxeter/Inversion.lean | 2 ++ Mathlib/GroupTheory/Coxeter/Length.lean | 2 ++ Mathlib/GroupTheory/SpecificGroups/Dihedral.lean | 1 + Mathlib/LinearAlgebra/Matrix/Determinant/Misc.lean | 2 ++ Mathlib/NumberTheory/FLT/Four.lean | 1 + Mathlib/NumberTheory/LucasLehmer.lean | 1 + Mathlib/NumberTheory/PythagoreanTriples.lean | 1 + Mathlib/RingTheory/Polynomial/Dickson.lean | 5 ++--- 70 files changed, 140 insertions(+), 14 deletions(-) diff --git a/Mathlib/Algebra/Algebra/ZMod.lean b/Mathlib/Algebra/Algebra/ZMod.lean index 0d26ab239fe68..1318279bee0d5 100644 --- a/Mathlib/Algebra/Algebra/ZMod.lean +++ b/Mathlib/Algebra/Algebra/ZMod.lean @@ -10,6 +10,7 @@ import Mathlib.Data.ZMod.Basic # The `ZMod n`-algebra structure on rings whose characteristic divides `n` -/ +assert_not_exists TwoSidedIdeal namespace ZMod diff --git a/Mathlib/Algebra/CharP/Algebra.lean b/Mathlib/Algebra/CharP/Algebra.lean index 4b23ad5f49507..3f501e0643d13 100644 --- a/Mathlib/Algebra/CharP/Algebra.lean +++ b/Mathlib/Algebra/CharP/Algebra.lean @@ -3,9 +3,10 @@ Copyright (c) 2021 Jon Eugster. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jon Eugster, Eric Wieser -/ -import Mathlib.Algebra.CharP.Basic +import Mathlib.Algebra.CharP.Defs import Mathlib.Algebra.FreeAlgebra import Mathlib.RingTheory.Localization.FractionRing +import Mathlib.RingTheory.SimpleRing.Basic /-! # Characteristics of algebras @@ -63,8 +64,8 @@ theorem RingHom.charP {R A : Type*} [NonAssocSemiring R] [NonAssocSemiring A] (f /-- If `R →+* A` is injective, then `R` is of characteristic `p` if and only if `A` is also of characteristic `p`. Similar to `RingHom.charZero_iff`. -/ -theorem RingHom.charP_iff {R A : Type*} [NonAssocSemiring R] [NonAssocSemiring A] (f : R →+* A) - (H : Function.Injective f) (p : ℕ) : CharP R p ↔ CharP A p := +protected theorem RingHom.charP_iff {R A : Type*} [NonAssocSemiring R] [NonAssocSemiring A] + (f : R →+* A) (H : Function.Injective f) (p : ℕ) : CharP R p ↔ CharP A p := ⟨fun _ ↦ charP_of_injective_ringHom H p, fun _ ↦ f.charP H p⟩ /-- If a ring homomorphism `R →+* A` is injective then `A` has the same exponential characteristic @@ -131,12 +132,15 @@ end QAlgebra An algebra over a field has the same characteristic as the field. -/ +lemma RingHom.charP_iff_charP {K L : Type*} [DivisionRing K] [Semiring L] [Nontrivial L] + (f : K →+* L) (p : ℕ) : CharP K p ↔ CharP L p := by + simp only [charP_iff, ← f.injective.eq_iff, map_natCast f, map_zero f] section variable (K L : Type*) [Field K] [CommSemiring L] [Nontrivial L] [Algebra K L] -theorem Algebra.charP_iff (p : ℕ) : CharP K p ↔ CharP L p := +protected theorem Algebra.charP_iff (p : ℕ) : CharP K p ↔ CharP L p := (algebraMap K L).charP_iff_charP p theorem Algebra.ringChar_eq : ringChar K = ringChar L := by diff --git a/Mathlib/Algebra/CharP/Basic.lean b/Mathlib/Algebra/CharP/Basic.lean index e0d2545c697fd..1a3eee8e323cf 100644 --- a/Mathlib/Algebra/CharP/Basic.lean +++ b/Mathlib/Algebra/CharP/Basic.lean @@ -3,11 +3,12 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Joey van Langen, Casper Putz -/ -import Mathlib.RingTheory.SimpleRing.Basic import Mathlib.Algebra.CharP.Defs import Mathlib.Algebra.Group.Fin.Basic import Mathlib.Algebra.Group.ULift import Mathlib.Data.Nat.Cast.Prod +import Mathlib.Data.ULift +import Mathlib.Order.Interval.Set.Defs /-! # Characteristic of semirings @@ -19,6 +20,7 @@ As such, we can probably reorganize and find a better home for most of these lem -/ assert_not_exists Finset +assert_not_exists TwoSidedIdeal open Set @@ -50,10 +52,6 @@ lemma intCast_injOn_Ico [IsRightCancelAdd R] : InjOn (Int.cast : ℤ → R) (Ico end AddGroupWithOne end CharP -lemma RingHom.charP_iff_charP {K L : Type*} [DivisionRing K] [Semiring L] [Nontrivial L] - (f : K →+* L) (p : ℕ) : CharP K p ↔ CharP L p := by - simp only [charP_iff, ← f.injective.eq_iff, map_natCast f, map_zero f] - namespace CharP section NonAssocSemiring diff --git a/Mathlib/Algebra/Homology/Bifunctor.lean b/Mathlib/Algebra/Homology/Bifunctor.lean index 77d33dba60377..587b5e562a1e3 100644 --- a/Mathlib/Algebra/Homology/Bifunctor.lean +++ b/Mathlib/Algebra/Homology/Bifunctor.lean @@ -21,6 +21,7 @@ bicomplex `(((F.mapBifunctorHomologicalComplex c₁ c₂).obj K₁).obj K₂)`. -/ +assert_not_exists TwoSidedIdeal open CategoryTheory Limits diff --git a/Mathlib/Algebra/Homology/BifunctorAssociator.lean b/Mathlib/Algebra/Homology/BifunctorAssociator.lean index e7935213a0d90..18612a3bc2861 100644 --- a/Mathlib/Algebra/Homology/BifunctorAssociator.lean +++ b/Mathlib/Algebra/Homology/BifunctorAssociator.lean @@ -34,6 +34,8 @@ the associator for the monoidal category structure on homological complexes. -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits namespace HomologicalComplex diff --git a/Mathlib/Algebra/Homology/BifunctorHomotopy.lean b/Mathlib/Algebra/Homology/BifunctorHomotopy.lean index 033002ed35b6b..4c000b592f3c1 100644 --- a/Mathlib/Algebra/Homology/BifunctorHomotopy.lean +++ b/Mathlib/Algebra/Homology/BifunctorHomotopy.lean @@ -17,6 +17,8 @@ the morphism `f₂` in `HomologicalComplex C c₂` (TODO). -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits variable {C₁ C₂ D I₁ I₂ J : Type*} [Category C₁] [Category C₂] [Category D] diff --git a/Mathlib/Algebra/Homology/BifunctorShift.lean b/Mathlib/Algebra/Homology/BifunctorShift.lean index ee9b7d4a75e32..83a5a29a3a8d2 100644 --- a/Mathlib/Algebra/Homology/BifunctorShift.lean +++ b/Mathlib/Algebra/Homology/BifunctorShift.lean @@ -23,6 +23,8 @@ that the two ways to deduce an isomorphism -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits variable {C₁ C₂ D : Type*} [Category C₁] [Category C₂] [Category D] diff --git a/Mathlib/Algebra/Homology/ComplexShapeSigns.lean b/Mathlib/Algebra/Homology/ComplexShapeSigns.lean index 224aa9d155bb6..d4728724fe0c1 100644 --- a/Mathlib/Algebra/Homology/ComplexShapeSigns.lean +++ b/Mathlib/Algebra/Homology/ComplexShapeSigns.lean @@ -24,6 +24,8 @@ satisfying certain properties (see `ComplexShape.TensorSigns`). -/ +assert_not_exists TwoSidedIdeal + variable {I₁ I₂ I₃ I₁₂ I₂₃ J : Type*} (c₁ : ComplexShape I₁) (c₂ : ComplexShape I₂) (c₃ : ComplexShape I₃) (c₁₂ : ComplexShape I₁₂) (c₂₃ : ComplexShape I₂₃) (c : ComplexShape J) diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean index da302f9893e1b..7d2a7a5dbdb08 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean @@ -60,6 +60,8 @@ or enough injectives). -/ +assert_not_exists TwoSidedIdeal + universe w v u open CategoryTheory Limits Pretriangulated diff --git a/Mathlib/Algebra/Homology/DerivedCategory/ExactFunctor.lean b/Mathlib/Algebra/Homology/DerivedCategory/ExactFunctor.lean index b10294eb1e50d..1602470be4200 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/ExactFunctor.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/ExactFunctor.lean @@ -14,6 +14,8 @@ abelian categories, then there is an induced triangulated functor -/ +assert_not_exists TwoSidedIdeal + universe w₁ w₂ v₁ v₂ u₁ u₂ open CategoryTheory Category Limits diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean index d12c1ff45e901..805216557b246 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean @@ -40,6 +40,8 @@ sheaves over `X` shall be in `Type u`. -/ +assert_not_exists TwoSidedIdeal + universe w'' w' w v u namespace CategoryTheory diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean index a8062d76e37e9..04d773c2ef94f 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean @@ -17,6 +17,8 @@ Similarly, if `Y : C`, there is a contravariant long exact sequence : -/ +assert_not_exists TwoSidedIdeal + universe w' w v u namespace CategoryTheory diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean index 93100f4ba0197..4797cdd3d03e0 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean @@ -15,6 +15,8 @@ in an abelian category, we construct the associated class in -/ +assert_not_exists TwoSidedIdeal + universe w' w v u namespace CategoryTheory diff --git a/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean b/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean index 2df568198c70f..35408dca9aac2 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean @@ -16,6 +16,8 @@ derived category. -/ +assert_not_exists TwoSidedIdeal + universe w v u open CategoryTheory Pretriangulated diff --git a/Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean b/Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean index 9d63d714f1f6e..119bc613a6444 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean @@ -17,6 +17,8 @@ in the derived category of `C`. -/ +assert_not_exists TwoSidedIdeal + universe w v u open CategoryTheory Category Pretriangulated diff --git a/Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean b/Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean index e4d1eff8ac407..8660fee520288 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean @@ -19,6 +19,8 @@ exact sequence in the heart of a t-structure -/ +assert_not_exists TwoSidedIdeal + universe w v u namespace CategoryTheory diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/DegreewiseSplit.lean b/Mathlib/Algebra/Homology/HomotopyCategory/DegreewiseSplit.lean index c454aa0ad7d69..c8b12b8072a71 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/DegreewiseSplit.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/DegreewiseSplit.lean @@ -5,7 +5,8 @@ Authors: Joël Riou -/ import Mathlib.Algebra.Homology.HomotopyCategory.Pretriangulated -/-! Degreewise split exact sequences of cochain complexes +/-! +# Degreewise split exact sequences of cochain complexes The main result of this file is the lemma `HomotopyCategory.distinguished_iff_iso_trianglehOfDegreewiseSplit` which asserts @@ -15,6 +16,8 @@ degreewise split short exact sequence of cochain complexes. -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits Pretriangulated Preadditive variable {C : Type*} [Category C] [Preadditive C] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean index 1a1ccf798106e..febea094e706d 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean @@ -31,6 +31,8 @@ We follow the signs conventions appearing in the introduction of -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits Preadditive universe v u diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean index 647dcd6a0dffb..f9518381c39e8 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplexShift.lean @@ -27,6 +27,8 @@ appearing in the introduction of -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits Preadditive universe v u diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/HomologicalFunctor.lean b/Mathlib/Algebra/Homology/HomotopyCategory/HomologicalFunctor.lean index f8e4b0ac524ff..45a640e54f6c3 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/HomologicalFunctor.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/HomologicalFunctor.lean @@ -19,6 +19,8 @@ sequence of a short exact sequences of homological complexes. -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory variable {C : Type*} [Category C] [Abelian C] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean index 42704741a95dc..57a474997c34a 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean @@ -18,6 +18,8 @@ we redefine it as `CochainComplex.mappingCone φ`. The API involves definitions -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Limits variable {C D : Type*} [Category C] [Category D] [Preadditive C] [Preadditive D] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean index c0a18009abb14..5ea65ccd6ce79 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean @@ -30,6 +30,8 @@ complexes. Here, we follow the original definitions in [Verdiers's thesis, I.3][ -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits CochainComplex.HomComplex Pretriangulated variable {C D : Type*} [Category C] [Category D] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean index 6738fed22098c..71e16fab72077 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean @@ -22,6 +22,8 @@ We also show that if `F : C ⥤ D` is an additive functor, then the functors -/ +assert_not_exists TwoSidedIdeal + universe v v' u u' open CategoryTheory diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean index 8146893f17131..cd32bec63e545 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean @@ -19,6 +19,8 @@ and `HomotopyCategory` namespaces. -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category ComplexShape Limits variable (C : Type*) [Category C] [Preadditive C] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean index e2dc209b90363..f752247e1d9b3 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean @@ -20,6 +20,8 @@ distinguished triangle attached to the mapping cone of `S.f`. -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category ComplexShape HomotopyCategory Limits HomologicalComplex.HomologySequence Pretriangulated Preadditive diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/SingleFunctors.lean b/Mathlib/Algebra/Homology/HomotopyCategory/SingleFunctors.lean index bbfa318b5da88..d771444bcd3cb 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/SingleFunctors.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/SingleFunctors.lean @@ -18,6 +18,8 @@ Similarly, we define -/ +assert_not_exists TwoSidedIdeal + universe v' u' v u open CategoryTheory Category Limits diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean index aaec3765b65ed..e21855ff3c3de 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean @@ -14,6 +14,8 @@ the pretriangulated category `HomotopyCategory C (ComplexShape.up ℤ)` is trian -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits Pretriangulated ComposableArrows variable {C : Type*} [Category C] [Preadditive C] [HasBinaryBiproducts C] diff --git a/Mathlib/Algebra/Homology/Monoidal.lean b/Mathlib/Algebra/Homology/Monoidal.lean index e0e185b0f0bec..c3510b7dda7ad 100644 --- a/Mathlib/Algebra/Homology/Monoidal.lean +++ b/Mathlib/Algebra/Homology/Monoidal.lean @@ -22,6 +22,8 @@ In particular, we obtain a monoidal category structure on -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Limits MonoidalCategory Category namespace HomologicalComplex diff --git a/Mathlib/Algebra/Homology/TotalComplex.lean b/Mathlib/Algebra/Homology/TotalComplex.lean index 15137d2628a9b..f17fa8eb8d849 100644 --- a/Mathlib/Algebra/Homology/TotalComplex.lean +++ b/Mathlib/Algebra/Homology/TotalComplex.lean @@ -25,6 +25,8 @@ differentials `(K.X p).X q ⟶ (K.X p).X (q + 1)`. -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits Preadditive namespace HomologicalComplex₂ diff --git a/Mathlib/Algebra/Homology/TotalComplexShift.lean b/Mathlib/Algebra/Homology/TotalComplexShift.lean index c1ab4298eb34f..7e3df4172bc6e 100644 --- a/Mathlib/Algebra/Homology/TotalComplexShift.lean +++ b/Mathlib/Algebra/Homology/TotalComplexShift.lean @@ -33,6 +33,8 @@ these two compositions of isomorphisms differ by the sign `(x * y).negOnePow`. -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Category ComplexShape Limits namespace HomologicalComplex₂ diff --git a/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean b/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean index be865c8ddd218..76a1db8a95279 100644 --- a/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean +++ b/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean @@ -20,6 +20,9 @@ are compatible `[TotalComplexShapeSymmetrySymmetry c₁ c₂ c]`, then the isomo -/ +assert_not_exists Ideal +assert_not_exists TwoSidedIdeal + open CategoryTheory Category Limits namespace HomologicalComplex₂ diff --git a/Mathlib/Algebra/Module/ZMod.lean b/Mathlib/Algebra/Module/ZMod.lean index 52d20b2efd9fe..280fceae0fb0c 100644 --- a/Mathlib/Algebra/Module/ZMod.lean +++ b/Mathlib/Algebra/Module/ZMod.lean @@ -10,6 +10,8 @@ import Mathlib.Data.ZMod.Basic # The `ZMod n`-module structure on Abelian groups whose elements have order dividing `n` -/ +assert_not_exists TwoSidedIdeal + variable {n : ℕ} {M M₁ : Type*} /-- The `ZMod n`-module structure on commutative monoids whose elements have order dividing `n ≠ 0`. diff --git a/Mathlib/Algebra/Order/ToIntervalMod.lean b/Mathlib/Algebra/Order/ToIntervalMod.lean index 7c76576582b5e..4d64c73ff7da2 100644 --- a/Mathlib/Algebra/Order/ToIntervalMod.lean +++ b/Mathlib/Algebra/Order/ToIntervalMod.lean @@ -29,6 +29,7 @@ interval. * `toIocMod hp a b` (where `hp : 0 < p`): Reduce `b` to the interval `Ioc a (a + p)`. -/ +assert_not_exists TwoSidedIdeal noncomputable section diff --git a/Mathlib/Algebra/Periodic.lean b/Mathlib/Algebra/Periodic.lean index 5cdb80ed09244..621cca880bcbd 100644 --- a/Mathlib/Algebra/Periodic.lean +++ b/Mathlib/Algebra/Periodic.lean @@ -31,6 +31,7 @@ Note that any `c`-antiperiodic function will necessarily also be `2 • c`-perio period, periodic, periodicity, antiperiodic -/ +assert_not_exists TwoSidedIdeal variable {α β γ : Type*} {f g : α → β} {c c₁ c₂ x : α} diff --git a/Mathlib/Algebra/Ring/NegOnePow.lean b/Mathlib/Algebra/Ring/NegOnePow.lean index b430be68969db..5b7a558be6b18 100644 --- a/Mathlib/Algebra/Ring/NegOnePow.lean +++ b/Mathlib/Algebra/Ring/NegOnePow.lean @@ -17,6 +17,8 @@ Johan Commelin to the Liquid Tensor Experiment. -/ +assert_not_exists TwoSidedIdeal + namespace Int /-- The map `ℤ → ℤˣ` which sends `n` to `(-1 : ℤˣ) ^ n`. -/ diff --git a/Mathlib/CategoryTheory/Localization/Triangulated.lean b/Mathlib/CategoryTheory/Localization/Triangulated.lean index 1be2f5f65a3cd..575cad9534bc8 100644 --- a/Mathlib/CategoryTheory/Localization/Triangulated.lean +++ b/Mathlib/CategoryTheory/Localization/Triangulated.lean @@ -20,6 +20,8 @@ and that it is triangulated. -/ +assert_not_exists TwoSidedIdeal + namespace CategoryTheory open Category Limits Pretriangulated Localization diff --git a/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean b/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean index 630cf7424298a..8268745878c88 100644 --- a/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean +++ b/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean @@ -31,6 +31,8 @@ of sets `yoneda.obj U` to `F`. -/ +assert_not_exists TwoSidedIdeal + universe w' w v u namespace CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/Adjunction.lean b/Mathlib/CategoryTheory/Triangulated/Adjunction.lean index 2308c4936e127..1a2b284a398e1 100644 --- a/Mathlib/CategoryTheory/Triangulated/Adjunction.lean +++ b/Mathlib/CategoryTheory/Triangulated/Adjunction.lean @@ -19,6 +19,8 @@ We deduce that, if `E : C ≌ D` is an equivalence of pretriangulated categories TODO: The case of left adjoints. -/ +assert_not_exists TwoSidedIdeal + namespace CategoryTheory open Category Limits Preadditive Pretriangulated Adjunction diff --git a/Mathlib/CategoryTheory/Triangulated/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Functor.lean index faa14d9b0ea07..acc43ade04895 100644 --- a/Mathlib/CategoryTheory/Triangulated/Functor.lean +++ b/Mathlib/CategoryTheory/Triangulated/Functor.lean @@ -19,6 +19,8 @@ distinguished triangles: this defines the typeclass `Functor.IsTriangulated`. -/ +assert_not_exists TwoSidedIdeal + namespace CategoryTheory open Category Limits Pretriangulated Preadditive diff --git a/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean index 16109ed271f3f..c83e89983d0b5 100644 --- a/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean +++ b/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean @@ -19,6 +19,8 @@ given by `CategoryTheory.Pretriangulated.triangleOpEquivalence`. -/ +assert_not_exists TwoSidedIdeal + namespace CategoryTheory variable {C D : Type*} [Category C] [Category D] [HasShift C ℤ] [HasShift D ℤ] (F : C ⥤ D) diff --git a/Mathlib/CategoryTheory/Triangulated/Opposite/Pretriangulated.lean b/Mathlib/CategoryTheory/Triangulated/Opposite/Pretriangulated.lean index dcec2c68e78ac..ef00385574aa3 100644 --- a/Mathlib/CategoryTheory/Triangulated/Opposite/Pretriangulated.lean +++ b/Mathlib/CategoryTheory/Triangulated/Opposite/Pretriangulated.lean @@ -31,6 +31,8 @@ in [Verdiers's thesis, p. 96][verdier1996] which would require that the triangle -/ +assert_not_exists TwoSidedIdeal + namespace CategoryTheory open Category Limits Preadditive ZeroObject diff --git a/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean b/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean index 1cbad40237ea8..bdaf65cf13c90 100644 --- a/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean +++ b/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean @@ -21,6 +21,7 @@ but not necessarily additive categories, as is assumed in some sources. TODO: generalise this to n-angulated categories as in https://arxiv.org/abs/1006.4592 -/ +assert_not_exists TwoSidedIdeal noncomputable section diff --git a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean index f662bd84a092a..cba2f222d1f29 100644 --- a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean +++ b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean @@ -36,6 +36,8 @@ of an additive category is not closed under isomorphisms. -/ +assert_not_exists TwoSidedIdeal + namespace CategoryTheory open Category Limits Preadditive ZeroObject diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean index 99dd35d10775c..6ffcb2daa9685 100644 --- a/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean @@ -38,6 +38,8 @@ use depending on the context. -/ +assert_not_exists TwoSidedIdeal + namespace CategoryTheory open Limits diff --git a/Mathlib/CategoryTheory/Triangulated/TriangleShift.lean b/Mathlib/CategoryTheory/Triangulated/TriangleShift.lean index c06cd41d963ae..f2c34532004d7 100644 --- a/Mathlib/CategoryTheory/Triangulated/TriangleShift.lean +++ b/Mathlib/CategoryTheory/Triangulated/TriangleShift.lean @@ -20,6 +20,8 @@ Johan Commelin and Andrew Yang during the Liquid Tensor Experiment. -/ +assert_not_exists TwoSidedIdeal + universe v u namespace CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/Triangulated.lean b/Mathlib/CategoryTheory/Triangulated/Triangulated.lean index 07efbd8b479b2..d626b0eb72e4d 100644 --- a/Mathlib/CategoryTheory/Triangulated/Triangulated.lean +++ b/Mathlib/CategoryTheory/Triangulated/Triangulated.lean @@ -13,6 +13,7 @@ pretriangulated categories which satisfy the octahedron axiom. -/ +assert_not_exists TwoSidedIdeal noncomputable section diff --git a/Mathlib/CategoryTheory/Triangulated/Yoneda.lean b/Mathlib/CategoryTheory/Triangulated/Yoneda.lean index 40fe591bc97b9..fb551b821caba 100644 --- a/Mathlib/CategoryTheory/Triangulated/Yoneda.lean +++ b/Mathlib/CategoryTheory/Triangulated/Yoneda.lean @@ -18,6 +18,8 @@ functors `preadditiveCoyoneda.obj A : C ⥤ AddCommGrp` for `A : Cᵒᵖ` and -/ +assert_not_exists TwoSidedIdeal + open CategoryTheory Limits variable {C : Type*} [Category C] [Preadditive C] [HasShift C ℤ] diff --git a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean index 5abb9581a1ef1..b0011c6fb5bbb 100644 --- a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean +++ b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean @@ -43,6 +43,9 @@ the size of the biggest 3AP-free subset of `{0, ..., n - 1}`. 3AP-free, Salem-Spencer, Roth, arithmetic progression, average, three-free -/ +assert_not_exists Ideal +assert_not_exists TwoSidedIdeal + open Finset Function open scoped Pointwise diff --git a/Mathlib/Combinatorics/Additive/Corner/Defs.lean b/Mathlib/Combinatorics/Additive/Corner/Defs.lean index c4db62ad8d856..3a5f751d136c7 100644 --- a/Mathlib/Combinatorics/Additive/Corner/Defs.lean +++ b/Mathlib/Combinatorics/Additive/Corner/Defs.lean @@ -17,6 +17,9 @@ property of being corner-free. * [Wikipedia, *Corners theorem*](https://en.wikipedia.org/wiki/Corners_theorem) -/ +assert_not_exists Ideal +assert_not_exists TwoSidedIdeal + open Set variable {G H : Type*} diff --git a/Mathlib/Combinatorics/Additive/FreimanHom.lean b/Mathlib/Combinatorics/Additive/FreimanHom.lean index bcd9d5b6fb774..d01782751e401 100644 --- a/Mathlib/Combinatorics/Additive/FreimanHom.lean +++ b/Mathlib/Combinatorics/Additive/FreimanHom.lean @@ -60,6 +60,9 @@ an `AddMonoid`/`Monoid` instead of the `AddMonoid`/`Monoid` itself. * Affine maps are Freiman homs. -/ +assert_not_exists Ideal +assert_not_exists TwoSidedIdeal + open Multiset Set open scoped Pointwise diff --git a/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean b/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean index 5904dc6245e9b..1bbee3625fc57 100644 --- a/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean +++ b/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean @@ -35,6 +35,7 @@ of the corresponding vertex and that (2) the map from darts to edges is 2-to-1. simple graphs, sums, degree-sum formula, handshaking lemma -/ +assert_not_exists TwoSidedIdeal open Finset diff --git a/Mathlib/Combinatorics/SimpleGraph/Matching.lean b/Mathlib/Combinatorics/SimpleGraph/Matching.lean index 1e27af2e43ad5..e98fe155b060b 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Matching.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Matching.lean @@ -46,6 +46,8 @@ one edge, and the edges of the subgraph represent the paired vertices. * Hall's Marriage Theorem (see `Mathlib.Combinatorics.Hall.Basic`) -/ +assert_not_exists TwoSidedIdeal + open Function namespace SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/UniversalVerts.lean b/Mathlib/Combinatorics/SimpleGraph/UniversalVerts.lean index 7c7f3b1cb0d0c..a144fe4148ce7 100644 --- a/Mathlib/Combinatorics/SimpleGraph/UniversalVerts.lean +++ b/Mathlib/Combinatorics/SimpleGraph/UniversalVerts.lean @@ -20,6 +20,8 @@ in the proof of Tutte's Theorem. * `G.deleteUniversalVerts` is the subgraph of `G` with the universal vertices removed. -/ +assert_not_exists TwoSidedIdeal + namespace SimpleGraph variable {V : Type*} {G : SimpleGraph V} diff --git a/Mathlib/Data/Nat/Periodic.lean b/Mathlib/Data/Nat/Periodic.lean index 0165a52cf2c76..d1128353419d6 100644 --- a/Mathlib/Data/Nat/Periodic.lean +++ b/Mathlib/Data/Nat/Periodic.lean @@ -15,6 +15,7 @@ This file identifies a few functions on `ℕ` which are periodic, and also prove periodic predicates which helps determine their cardinality when filtering intervals over them. -/ +assert_not_exists TwoSidedIdeal namespace Nat diff --git a/Mathlib/Data/ZMod/Aut.lean b/Mathlib/Data/ZMod/Aut.lean index 88711c2b14b8a..7b553f70fa2fd 100644 --- a/Mathlib/Data/ZMod/Aut.lean +++ b/Mathlib/Data/ZMod/Aut.lean @@ -10,6 +10,8 @@ import Mathlib.Data.ZMod.Basic # Automorphism Group of `ZMod`. -/ +assert_not_exists TwoSidedIdeal + namespace ZMod variable (n : ℕ) diff --git a/Mathlib/Data/ZMod/Basic.lean b/Mathlib/Data/ZMod/Basic.lean index e6ccd28f30073..dd6023f9ebd14 100644 --- a/Mathlib/Data/ZMod/Basic.lean +++ b/Mathlib/Data/ZMod/Basic.lean @@ -34,6 +34,7 @@ This is a ring hom if the ring has characteristic dividing `n` -/ assert_not_exists Submodule +assert_not_exists TwoSidedIdeal open Function ZMod diff --git a/Mathlib/Data/ZMod/Coprime.lean b/Mathlib/Data/ZMod/Coprime.lean index 17d998653bee9..91030c12cfdc1 100644 --- a/Mathlib/Data/ZMod/Coprime.lean +++ b/Mathlib/Data/ZMod/Coprime.lean @@ -14,6 +14,7 @@ We show that for prime `p`, the image of an integer `a` in `ZMod p` vanishes if `a` and `p` are not coprime. -/ +assert_not_exists TwoSidedIdeal namespace ZMod diff --git a/Mathlib/Data/ZMod/Factorial.lean b/Mathlib/Data/ZMod/Factorial.lean index fa997a870eef9..3843155001291 100644 --- a/Mathlib/Data/ZMod/Factorial.lean +++ b/Mathlib/Data/ZMod/Factorial.lean @@ -24,6 +24,8 @@ For the prime case and involving `factorial` rather than `descFactorial`, see Wi -/ +assert_not_exists TwoSidedIdeal + open Finset Nat namespace ZMod diff --git a/Mathlib/Data/ZMod/IntUnitsPower.lean b/Mathlib/Data/ZMod/IntUnitsPower.lean index 80e8edf23f8c4..02b0f8a883a92 100644 --- a/Mathlib/Data/ZMod/IntUnitsPower.lean +++ b/Mathlib/Data/ZMod/IntUnitsPower.lean @@ -23,6 +23,9 @@ by using `Module R (Additive M)` in its place, especially since this already has `R = ℕ` and `R = ℤ`. -/ +assert_not_exists Ideal +assert_not_exists TwoSidedIdeal + instance : SMul (ZMod 2) (Additive ℤˣ) where smul z au := .ofMul <| au.toMul ^ z.val diff --git a/Mathlib/Data/ZMod/Units.lean b/Mathlib/Data/ZMod/Units.lean index a39984a54cdcf..527428b0ddbd9 100644 --- a/Mathlib/Data/ZMod/Units.lean +++ b/Mathlib/Data/ZMod/Units.lean @@ -12,6 +12,7 @@ import Mathlib.RingTheory.Coprime.Lemmas # Lemmas about units in `ZMod`. -/ +assert_not_exists TwoSidedIdeal namespace ZMod diff --git a/Mathlib/FieldTheory/Perfect.lean b/Mathlib/FieldTheory/Perfect.lean index 6e4aecef5c66e..0a28f720b8a0c 100644 --- a/Mathlib/FieldTheory/Perfect.lean +++ b/Mathlib/FieldTheory/Perfect.lean @@ -3,9 +3,10 @@ Copyright (c) 2023 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ +import Mathlib.Algebra.CharP.Basic +import Mathlib.Algebra.CharP.Reduced import Mathlib.FieldTheory.Separable import Mathlib.FieldTheory.SplittingField.Construction -import Mathlib.Algebra.CharP.Reduced /-! diff --git a/Mathlib/GroupTheory/CommutingProbability.lean b/Mathlib/GroupTheory/CommutingProbability.lean index 48bb770f072ff..7d56673295222 100644 --- a/Mathlib/GroupTheory/CommutingProbability.lean +++ b/Mathlib/GroupTheory/CommutingProbability.lean @@ -21,6 +21,9 @@ This file introduces the commuting probability of finite groups. * Neumann's theorem. -/ +assert_not_exists Ideal +assert_not_exists TwoSidedIdeal + noncomputable section open scoped Classical diff --git a/Mathlib/GroupTheory/Coxeter/Inversion.lean b/Mathlib/GroupTheory/Coxeter/Inversion.lean index 749a9c240d1d2..c5961f1ab8c81 100644 --- a/Mathlib/GroupTheory/Coxeter/Inversion.lean +++ b/Mathlib/GroupTheory/Coxeter/Inversion.lean @@ -42,6 +42,8 @@ inversions of $w$ in some order, but we do not prove that in this file. -/ +assert_not_exists TwoSidedIdeal + namespace CoxeterSystem open List Matrix Function diff --git a/Mathlib/GroupTheory/Coxeter/Length.lean b/Mathlib/GroupTheory/Coxeter/Length.lean index fbc5887d029a5..aff28c1d3b685 100644 --- a/Mathlib/GroupTheory/Coxeter/Length.lean +++ b/Mathlib/GroupTheory/Coxeter/Length.lean @@ -46,6 +46,8 @@ prove analogous results. -/ +assert_not_exists TwoSidedIdeal + namespace CoxeterSystem open List Matrix Function Classical diff --git a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean index 443bfc56811c7..ba8587d7527f9 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean @@ -18,6 +18,7 @@ represents the rotations of the `n`-gon by `2πi/n`, and `sr i` represents the r `n`-gon. `DihedralGroup 0` corresponds to the infinite dihedral group. -/ +assert_not_exists TwoSidedIdeal /-- For `n ≠ 0`, `DihedralGroup n` represents the symmetry group of the regular `n`-gon. `r i` represents the rotations of the `n`-gon by `2πi/n`, and `sr i` represents the reflections of diff --git a/Mathlib/LinearAlgebra/Matrix/Determinant/Misc.lean b/Mathlib/LinearAlgebra/Matrix/Determinant/Misc.lean index 856717530ee1a..5ad760730b2b8 100644 --- a/Mathlib/LinearAlgebra/Matrix/Determinant/Misc.lean +++ b/Mathlib/LinearAlgebra/Matrix/Determinant/Misc.lean @@ -12,6 +12,8 @@ import Mathlib.Algebra.Ring.NegOnePow In this file, we collect various formulas about determinant of matrices. -/ +assert_not_exists TwoSidedIdeal + namespace Matrix variable {R : Type*} [CommRing R] diff --git a/Mathlib/NumberTheory/FLT/Four.lean b/Mathlib/NumberTheory/FLT/Four.lean index b6802f986775d..5803ad9288031 100644 --- a/Mathlib/NumberTheory/FLT/Four.lean +++ b/Mathlib/NumberTheory/FLT/Four.lean @@ -14,6 +14,7 @@ import Mathlib.Tactic.LinearCombination There are no non-zero integers `a`, `b` and `c` such that `a ^ 4 + b ^ 4 = c ^ 4`. -/ +assert_not_exists TwoSidedIdeal noncomputable section diff --git a/Mathlib/NumberTheory/LucasLehmer.lean b/Mathlib/NumberTheory/LucasLehmer.lean index 01356b10609e7..8a59a2f806ddd 100644 --- a/Mathlib/NumberTheory/LucasLehmer.lean +++ b/Mathlib/NumberTheory/LucasLehmer.lean @@ -30,6 +30,7 @@ This tactic was ported by Thomas Murrills to Lean 4, and then it was converted t extension and made to use kernel reductions by Kyle Miller. -/ +assert_not_exists TwoSidedIdeal /-- The Mersenne numbers, 2^p - 1. -/ def mersenne (p : ℕ) : ℕ := diff --git a/Mathlib/NumberTheory/PythagoreanTriples.lean b/Mathlib/NumberTheory/PythagoreanTriples.lean index 4d969268df6d1..7286c49b7dae7 100644 --- a/Mathlib/NumberTheory/PythagoreanTriples.lean +++ b/Mathlib/NumberTheory/PythagoreanTriples.lean @@ -25,6 +25,7 @@ analyze the parity of `x`, `y`, `m` and `n` and eliminate all the impossible cas the bulk of the proof below. -/ +assert_not_exists TwoSidedIdeal theorem sq_ne_two_fin_zmod_four (z : ZMod 4) : z * z ≠ 2 := by change Fin 4 at z diff --git a/Mathlib/RingTheory/Polynomial/Dickson.lean b/Mathlib/RingTheory/Polynomial/Dickson.lean index b563e9a572c2a..d1a85a4548180 100644 --- a/Mathlib/RingTheory/Polynomial/Dickson.lean +++ b/Mathlib/RingTheory/Polynomial/Dickson.lean @@ -3,13 +3,12 @@ Copyright (c) 2021 Julian Kuelshammer. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Julian Kuelshammer -/ +import Mathlib.Algebra.CharP.Algebra import Mathlib.Algebra.CharP.Invertible -import Mathlib.Data.ZMod.Basic -import Mathlib.RingTheory.Localization.FractionRing -import Mathlib.RingTheory.Polynomial.Chebyshev import Mathlib.Algebra.CharP.Lemmas import Mathlib.Algebra.EuclideanDomain.Field import Mathlib.Algebra.Polynomial.Roots +import Mathlib.RingTheory.Polynomial.Chebyshev /-! # Dickson polynomials From 4e6cc37012f75c9de40476ad722f02512a8b1f09 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 8 Jan 2025 13:46:35 +0000 Subject: [PATCH 083/681] feat: missing emultiplicity coercion lemma (#19753) https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/calculating.20multiplicities/near/486380567 --- Mathlib/RingTheory/Multiplicity.lean | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mathlib/RingTheory/Multiplicity.lean b/Mathlib/RingTheory/Multiplicity.lean index 19c092dd8f1ed..e6fcaadc0bb10 100644 --- a/Mathlib/RingTheory/Multiplicity.lean +++ b/Mathlib/RingTheory/Multiplicity.lean @@ -353,6 +353,10 @@ theorem FiniteMultiplicity.multiplicity_eq_iff (hf : FiniteMultiplicity a b) {n multiplicity a b = n ↔ a ^ n ∣ b ∧ ¬a ^ (n + 1) ∣ b := by simp [← emultiplicity_eq_coe, hf.emultiplicity_eq_multiplicity] +theorem emultiplicity_eq_ofNat {a b n : ℕ} [n.AtLeastTwo] : + emultiplicity a b = (ofNat(n) : ℕ∞) ↔ a ^ ofNat(n) ∣ b ∧ ¬a ^ (ofNat(n) + 1) ∣ b := + emultiplicity_eq_coe + @[deprecated (since := "2024-11-30")] alias multiplicity.Finite.multiplicity_eq_iff := FiniteMultiplicity.multiplicity_eq_iff From 60ae2db33d89b094c1126291436cf43b2e78acd3 Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Wed, 8 Jan 2025 16:06:16 +0000 Subject: [PATCH 084/681] =?UTF-8?q?feat(RingTheory/Smooth):=20calculate=20?= =?UTF-8?q?`H=C2=B9(L)`=20via=20formally=20smooth=20extensions=20(#20471)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib/RingTheory/Extension.lean | 29 +++++- Mathlib/RingTheory/Ideal/Cotangent.lean | 17 +++- .../RingTheory/Kaehler/CotangentComplex.lean | 33 ++++--- Mathlib/RingTheory/Smooth/Kaehler.lean | 98 +++++++++++++++++++ 4 files changed, 159 insertions(+), 18 deletions(-) diff --git a/Mathlib/RingTheory/Extension.lean b/Mathlib/RingTheory/Extension.lean index c11e2eff7f4ee..ebbc9fdab7e1a 100644 --- a/Mathlib/RingTheory/Extension.lean +++ b/Mathlib/RingTheory/Extension.lean @@ -115,6 +115,9 @@ def self : Extension R S where σ := _root_.id algebraMap_σ _ := rfl +/-- The kernel of an extension. -/ +abbrev ker : Ideal P.Ring := RingHom.ker (algebraMap P.Ring S) + section Localization variable (M : Submonoid S) {S' : Type*} [CommRing S'] [Algebra S S'] [IsLocalization M S'] @@ -232,10 +235,30 @@ end end Hom -section Cotangent +section Infinitesimal -/-- The kernel of an extension. -/ -abbrev ker : Ideal P.Ring := RingHom.ker (algebraMap P.Ring S) +/-- Given an `R`-algebra extension `0 → I → P → S → 0` of `S`, +the infinitesimal extension associated to it is `0 → I/I² → P/I² → S → 0`. -/ +noncomputable +def infinitesimal (P : Extension R S) : Extension R S where + Ring := P.Ring ⧸ P.ker ^ 2 + σ := Ideal.Quotient.mk _ ∘ P.σ + algebraMap_σ x := by dsimp; exact P.algebraMap_σ x + +/-- The canonical map `P → P/I²` as maps between extensions. -/ +noncomputable +def toInfinitesimal (P : Extension R S) : P.Hom P.infinitesimal where + toRingHom := Ideal.Quotient.mk _ + toRingHom_algebraMap _ := rfl + algebraMap_toRingHom _ := rfl + +lemma ker_infinitesimal (P : Extension R S) : + P.infinitesimal.ker = P.ker.cotangentIdeal := + AlgHom.ker_kerSquareLift _ + +end Infinitesimal + +section Cotangent /-- The cotangent space of an extension. This is a type synonym so that `P.Ring` can act on it through the action of `S` without creating diff --git a/Mathlib/RingTheory/Ideal/Cotangent.lean b/Mathlib/RingTheory/Ideal/Cotangent.lean index 9f2e89438bbbc..727ba571e6518 100644 --- a/Mathlib/RingTheory/Ideal/Cotangent.lean +++ b/Mathlib/RingTheory/Ideal/Cotangent.lean @@ -120,18 +120,31 @@ theorem cotangentIdeal_square (I : Ideal R) : I.cotangentIdeal ^ 2 = ⊥ := by rw [sub_zero, pow_two]; exact Ideal.mul_mem_mul hx hy · intro x y hx hy; exact add_mem hx hy -theorem to_quotient_square_range : +lemma mk_mem_cotangentIdeal {I : Ideal R} {x : R} : + Quotient.mk (I ^ 2) x ∈ I.cotangentIdeal ↔ x ∈ I := by + refine ⟨fun ⟨y, hy, e⟩ ↦ ?_, fun h ↦ ⟨x, h, rfl⟩⟩ + simpa using sub_mem hy (Ideal.pow_le_self two_ne_zero + ((Ideal.Quotient.mk_eq_mk_iff_sub_mem _ _).mp e)) + +lemma comap_cotangentIdeal (I : Ideal R) : + I.cotangentIdeal.comap (Quotient.mk (I ^ 2)) = I := + Ideal.ext fun _ ↦ mk_mem_cotangentIdeal + +theorem range_cotangentToQuotientSquare : LinearMap.range I.cotangentToQuotientSquare = I.cotangentIdeal.restrictScalars R := by trans LinearMap.range (I.cotangentToQuotientSquare.comp I.toCotangent) · rw [LinearMap.range_comp, I.toCotangent_range, Submodule.map_top] · rw [to_quotient_square_comp_toCotangent, LinearMap.range_comp, I.range_subtype]; ext; rfl +@[deprecated (since := "2025-01-04")] +alias to_quotient_square_range := range_cotangentToQuotientSquare + /-- The equivalence of the two definitions of `I / I ^ 2`, either as the quotient of `I` or the ideal of `R / I ^ 2`. -/ noncomputable def cotangentEquivIdeal : I.Cotangent ≃ₗ[R] I.cotangentIdeal := by refine { LinearMap.codRestrict (I.cotangentIdeal.restrictScalars R) I.cotangentToQuotientSquare - fun x => by { rw [← to_quotient_square_range]; exact LinearMap.mem_range_self _ _ }, + fun x => by rw [← range_cotangentToQuotientSquare]; exact LinearMap.mem_range_self _ _, Equiv.ofBijective _ ⟨?_, ?_⟩ with } · rintro x y e replace e := congr_arg Subtype.val e diff --git a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean index 819a67cdc7c96..2ca02e4c274e9 100644 --- a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean +++ b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean @@ -350,6 +350,23 @@ lemma H1Cotangent.map_comp map (g.comp f) = (map g).restrictScalars S ∘ₗ map f := by ext; simp [Cotangent.map_comp] +/-- Maps `P₁ → P₂` and `P₂ → P₁` between extensions +induce an isomorphism between `H¹(L_P₁)` and `H¹(L_P₂)`. -/ +@[simps! apply] +noncomputable +def H1Cotangent.equiv {P₁ P₂ : Extension R S} (f₁ : P₁.Hom P₂) (f₂ : P₂.Hom P₁) : + P₁.H1Cotangent ≃ₗ[S] P₂.H1Cotangent where + __ := map f₁ + invFun := map f₂ + left_inv x := + show (map f₂ ∘ₗ map f₁) x = LinearMap.id x by + rw [← Extension.H1Cotangent.map_id, eq_comm, map_eq _ (f₂.comp f₁), + Extension.H1Cotangent.map_comp]; rfl + right_inv x := + show (map f₁ ∘ₗ map f₂) x = LinearMap.id x by + rw [← Extension.H1Cotangent.map_id, eq_comm, map_eq _ (f₁.comp f₂), + Extension.H1Cotangent.map_comp]; rfl + end Extension namespace Generators @@ -423,19 +440,9 @@ open Extension.H1Cotangent in @[simps! apply] noncomputable def Generators.H1Cotangent.equiv (P : Generators R S) (P' : Generators R S) : - P.toExtension.H1Cotangent ≃ₗ[S] P'.toExtension.H1Cotangent where - __ := map (Generators.defaultHom P P').toExtensionHom - invFun := map (Generators.defaultHom P' P).toExtensionHom - left_inv x := - show ((map (defaultHom P' P).toExtensionHom) ∘ₗ - (map (defaultHom P P').toExtensionHom)) x = LinearMap.id x by - rw [← Extension.H1Cotangent.map_id, eq_comm, map_eq _ ((defaultHom P' P).toExtensionHom.comp - (defaultHom P P').toExtensionHom), Extension.H1Cotangent.map_comp]; rfl - right_inv x := - show ((map (defaultHom P P').toExtensionHom) ∘ₗ - (map (defaultHom P' P).toExtensionHom)) x = LinearMap.id x by - rw [← Extension.H1Cotangent.map_id, eq_comm, map_eq _ ((defaultHom P P').toExtensionHom.comp - (defaultHom P' P).toExtensionHom), Extension.H1Cotangent.map_comp]; rfl + P.toExtension.H1Cotangent ≃ₗ[S] P'.toExtension.H1Cotangent := + Extension.H1Cotangent.equiv + (Generators.defaultHom P P').toExtensionHom (Generators.defaultHom P' P).toExtensionHom variable {S' : Type*} [CommRing S'] [Algebra R S'] variable {T : Type w} [CommRing T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] diff --git a/Mathlib/RingTheory/Smooth/Kaehler.lean b/Mathlib/RingTheory/Smooth/Kaehler.lean index 47603d7179636..44d8ef22e6985 100644 --- a/Mathlib/RingTheory/Smooth/Kaehler.lean +++ b/Mathlib/RingTheory/Smooth/Kaehler.lean @@ -31,6 +31,8 @@ import Mathlib.Tactic.StacksAttribute then `S` is formally smooth iff `Ω[S/R]` is projective and `I/I² → S ⊗[P] Ω[P⁄R]` is injective. - `Algebra.FormallySmooth.iff_subsingleton_and_projective`: An algebra is formally smooth if and only if `H¹(L_{R/S}) = 0` and `Ω_{S/R}` is projective. +- `Algebra.Extension.equivH1CotangentOfFormallySmooth`: + Any formally smooth extension can be used to calculate `H¹(L_{S/R})`. ## Future projects @@ -472,3 +474,99 @@ theorem Algebra.FormallySmooth.iff_subsingleton_and_projective : instance [Algebra.FormallySmooth R S] : Subsingleton (Algebra.H1Cotangent R S) := (Algebra.FormallySmooth.iff_subsingleton_and_projective.mp ‹_›).1 + +namespace Algebra.Extension + +lemma CotangentSpace.map_toInfinitesimal_bijective (P : Extension.{u} R S) : + Function.Bijective (CotangentSpace.map P.toInfinitesimal) := by + suffices CotangentSpace.map P.toInfinitesimal = + (tensorKaehlerQuotKerSqEquiv _ _ _).symm.toLinearMap by + rw [this]; exact(tensorKaehlerQuotKerSqEquiv _ _ _).symm.bijective + letI : Algebra P.Ring P.infinitesimal.Ring := inferInstanceAs (Algebra P.Ring (P.Ring ⧸ _)) + have : IsScalarTower P.Ring P.infinitesimal.Ring S := .of_algebraMap_eq' rfl + apply LinearMap.restrictScalars_injective P.Ring + ext x a + dsimp + simp only [map_tmul, id.map_eq_id, RingHom.id_apply, Hom.toAlgHom_apply] + exact (tensorKaehlerQuotKerSqEquiv_symm_tmul_D _ _).symm + +lemma Cotangent.map_toInfinitesimal_bijective (P : Extension.{u} R S) : + Function.Bijective (Cotangent.map P.toInfinitesimal) := by + constructor + · rw [injective_iff_map_eq_zero] + intro x hx + obtain ⟨x, rfl⟩ := Cotangent.mk_surjective x + have hx : x.1 ∈ P.ker ^ 2 := by + apply_fun Cotangent.val at hx + simp only [map_mk, Hom.toAlgHom_apply, val_mk, val_zero, Ideal.toCotangent_eq_zero, + Extension.ker_infinitesimal] at hx + rw [Ideal.cotangentIdeal_square] at hx + simpa only [toInfinitesimal, Ideal.mem_bot, infinitesimal, + Ideal.Quotient.eq_zero_iff_mem] using hx + ext + simpa [Ideal.toCotangent_eq_zero] + · intro x + obtain ⟨⟨x, hx⟩, rfl⟩ := Cotangent.mk_surjective x + obtain ⟨x, rfl⟩ := Ideal.Quotient.mk_surjective x + rw [ker_infinitesimal, Ideal.mk_mem_cotangentIdeal] at hx + exact ⟨.mk ⟨x, hx⟩, rfl⟩ + +lemma H1Cotangent.map_toInfinitesimal_bijective (P : Extension.{u} R S) : + Function.Bijective (H1Cotangent.map P.toInfinitesimal) := by + constructor + · intro x y e + ext1 + exact (Cotangent.map_toInfinitesimal_bijective P).1 (congr_arg Subtype.val e) + · intro ⟨x, hx⟩ + obtain ⟨x, rfl⟩ := (Cotangent.map_toInfinitesimal_bijective P).2 x + refine ⟨⟨x, ?_⟩, rfl⟩ + simpa [← CotangentSpace.map_cotangentComplex, + map_eq_zero_iff _ (CotangentSpace.map_toInfinitesimal_bijective P).injective] using hx + +/-- +Given extensions `0 → I₁ → P₁ → S → 0` and `0 → I₂ → P₂ → S → 0` with `P₁` formally smooth, +this is an arbitrarily chosen map `P₁/I₁² → P₂/I₂²` of extensions. +-/ +noncomputable +def homInfinitesimal (P₁ P₂ : Extension R S) [FormallySmooth R P₁.Ring] : + P₁.infinitesimal.Hom P₂.infinitesimal := + letI lift : P₁.Ring →ₐ[R] P₂.infinitesimal.Ring := FormallySmooth.liftOfSurjective + (IsScalarTower.toAlgHom R P₁.Ring S) + (IsScalarTower.toAlgHom R P₂.infinitesimal.Ring S) + P₂.infinitesimal.algebraMap_surjective + ⟨2, show P₂.infinitesimal.ker ^ 2 = ⊥ by + rw [ker_infinitesimal]; exact Ideal.cotangentIdeal_square _⟩ + { toRingHom := (Ideal.Quotient.liftₐ (P₁.ker ^ 2) lift (by + show P₁.ker ^ 2 ≤ RingHom.ker lift + rw [pow_two, Ideal.mul_le] + have : ∀ r ∈ P₁.ker, lift r ∈ P₂.infinitesimal.ker := + fun r hr ↦ (FormallySmooth.liftOfSurjective_apply _ + (IsScalarTower.toAlgHom R P₂.infinitesimal.Ring S) _ _ r).trans hr + intro r hr s hs + rw [RingHom.mem_ker, map_mul, ← Ideal.mem_bot, ← P₂.ker.cotangentIdeal_square, + ← ker_infinitesimal, pow_two] + exact Ideal.mul_mem_mul (this r hr) (this s hs))).toRingHom + toRingHom_algebraMap := by simp + algebraMap_toRingHom x := by + obtain ⟨x, rfl⟩ := Ideal.Quotient.mk_surjective x + exact FormallySmooth.liftOfSurjective_apply _ + (IsScalarTower.toAlgHom R P₂.infinitesimal.Ring S) _ _ x } + +/-- Formally smooth extensions have isomorphic `H¹(L_P)`. -/ +noncomputable +def H1Cotangent.equivOfFormallySmooth (P₁ P₂ : Extension R S) + [FormallySmooth R P₁.Ring] [FormallySmooth R P₂.Ring] : + P₁.H1Cotangent ≃ₗ[S] P₂.H1Cotangent := + .ofBijective _ (H1Cotangent.map_toInfinitesimal_bijective P₁) ≪≫ₗ + H1Cotangent.equiv (Extension.homInfinitesimal _ _) (Extension.homInfinitesimal _ _) + ≪≫ₗ .symm (.ofBijective _ (H1Cotangent.map_toInfinitesimal_bijective P₂)) + +/-- Any formally smooth extension can be used to calculate `H¹(L_{S/R})`. -/ +noncomputable +def equivH1CotangentOfFormallySmooth (P : Extension R S) [FormallySmooth R P.Ring] : + P.H1Cotangent ≃ₗ[S] H1Cotangent R S := + have : FormallySmooth R (Generators.self R S).toExtension.Ring := + inferInstanceAs (FormallySmooth R (MvPolynomial _ _)) + H1Cotangent.equivOfFormallySmooth _ _ + +end Algebra.Extension From a2cbb66ec60152d0311cdf34cda859e6517f5afd Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Wed, 8 Jan 2025 16:29:29 +0000 Subject: [PATCH 085/681] feat(Topology/Algebra) finite modules over compact rings are compact (#20291) Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> Co-authored-by: Junyan Xu --- Mathlib.lean | 1 + Mathlib/Topology/Algebra/Module/Compact.lean | 36 ++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Mathlib/Topology/Algebra/Module/Compact.lean diff --git a/Mathlib.lean b/Mathlib.lean index 439e51e558829..498301a86bee1 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5094,6 +5094,7 @@ import Mathlib.Topology.Algebra.Module.Alternating.Topology import Mathlib.Topology.Algebra.Module.Basic import Mathlib.Topology.Algebra.Module.Cardinality import Mathlib.Topology.Algebra.Module.CharacterSpace +import Mathlib.Topology.Algebra.Module.Compact import Mathlib.Topology.Algebra.Module.Determinant import Mathlib.Topology.Algebra.Module.Equiv import Mathlib.Topology.Algebra.Module.FiniteDimension diff --git a/Mathlib/Topology/Algebra/Module/Compact.lean b/Mathlib/Topology/Algebra/Module/Compact.lean new file mode 100644 index 0000000000000..2d83f14aa83a8 --- /dev/null +++ b/Mathlib/Topology/Algebra/Module/Compact.lean @@ -0,0 +1,36 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.LinearAlgebra.Finsupp.LinearCombination +import Mathlib.RingTheory.Finiteness.Defs +import Mathlib.Topology.Algebra.Ring.Basic + +/-! + +# Compact submodules + +-/ + +variable {R M : Type*} [CommSemiring R] [TopologicalSpace R] [AddCommMonoid M] [Module R M] +variable [TopologicalSpace M] [ContinuousAdd M] [ContinuousSMul R M] + +lemma Submodule.isCompact_of_fg [CompactSpace R] {N : Submodule R M} (hN : N.FG) : + IsCompact (X := M) N := by + obtain ⟨s, hs⟩ := hN + have : LinearMap.range (Fintype.linearCombination R R (α := s) Subtype.val) = N := by + simp [Finsupp.range_linearCombination, hs] + rw [← this] + refine isCompact_range ?_ + simp only [Fintype.linearCombination, Finset.univ_eq_attach, smul_eq_mul, LinearMap.coe_mk, + AddHom.coe_mk] + continuity + +lemma Ideal.isCompact_of_fg [TopologicalSemiring R] [CompactSpace R] + {I : Ideal R} (hI : I.FG) : IsCompact (X := R) I := + Submodule.isCompact_of_fg hI + +variable (R M) in +lemma Module.Finite.compactSpace [CompactSpace R] [Module.Finite R M] : CompactSpace M := + ⟨Submodule.isCompact_of_fg (Module.Finite.fg_top (R := R))⟩ From c8899bb80292f11bc6f9541eff54abbb3e97273e Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Wed, 8 Jan 2025 18:19:07 +0000 Subject: [PATCH 086/681] feat(Ringtheory/DedekindDomain/AdicValuation); add mem_integers_of_valuation_le_one (#20523) A Lean 4 port of Junyan Xu's code [here](https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/Intersection.20of.20localisations/near/302954312). --- .../DedekindDomain/AdicValuation.lean | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean index 77f7b9998fedb..36a3b9f561a35 100644 --- a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean +++ b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean @@ -351,6 +351,33 @@ theorem valuation_uniformizer_ne_zero : Classical.choose (v.valuation_exists_uni haveI hu := Classical.choose_spec (v.valuation_exists_uniformizer K) (Valuation.ne_zero_iff _).mp (ne_of_eq_of_ne hu WithZero.coe_ne_zero) +theorem mem_integers_of_valuation_le_one (x : K) + (h : ∀ v : HeightOneSpectrum R, v.valuation x ≤ 1) : x ∈ (algebraMap R K).range := by + obtain ⟨⟨n, d, hd⟩, hx⟩ := IsLocalization.surj (nonZeroDivisors R) x + obtain rfl : x = IsLocalization.mk' K n ⟨d, hd⟩ := IsLocalization.eq_mk'_iff_mul_eq.mpr hx + obtain rfl | hn0 := eq_or_ne n 0 + · simp + have hd0 := nonZeroDivisors.ne_zero hd + suffices Ideal.span {d} ∣ (Ideal.span {n} : Ideal R) by + obtain ⟨z, rfl⟩ := Ideal.span_singleton_le_span_singleton.1 (Ideal.le_of_dvd this) + use z + rw [map_mul, mul_comm, mul_eq_mul_left_iff] at hx + exact (hx.resolve_right fun h => by simp [hd0] at h).symm + classical + have ine {r : R} : r ≠ 0 → Ideal.span {r} ≠ ⊥ := mt Ideal.span_singleton_eq_bot.mp + rw [← Associates.mk_le_mk_iff_dvd, ← Associates.factors_le, Associates.factors_mk _ (ine hn0), + Associates.factors_mk _ (ine hd0), WithTop.coe_le_coe, Multiset.le_iff_count] + rintro ⟨v, hv⟩ + obtain ⟨v, rfl⟩ := Associates.mk_surjective v + have hv' := hv + rw [Associates.irreducible_mk, irreducible_iff_prime] at hv + specialize h ⟨v, Ideal.isPrime_of_prime hv, hv.ne_zero⟩ + simp_rw [valuation_of_mk', intValuation, ← Valuation.toFun_eq_coe, + intValuationDef_if_neg _ hn0, intValuationDef_if_neg _ hd0, ← WithZero.coe_div, + ← WithZero.coe_one, WithZero.coe_le_coe, Associates.factors_mk _ (ine hn0), + Associates.factors_mk _ (ine hd0), Associates.count_some hv'] at h + simpa using h + /-! ### Completions with respect to adic valuations Given a Dedekind domain `R` with field of fractions `K` and a maximal ideal `v` of `R`, we define From 8421da8699ad0386cf29f4c0e67497a819e04cba Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Wed, 8 Jan 2025 18:30:16 +0000 Subject: [PATCH 087/681] feat(NumberTheory/NumberField/Basic): ringOfIntegersEquiv API (#20544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Andrew Yang's proof that the obvious triangle to `ℚ` commutes. --- Mathlib/NumberTheory/NumberField/Basic.lean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mathlib/NumberTheory/NumberField/Basic.lean b/Mathlib/NumberTheory/NumberField/Basic.lean index 126fff4db3bc6..65ce05f28dc8e 100644 --- a/Mathlib/NumberTheory/NumberField/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/Basic.lean @@ -393,6 +393,12 @@ instance numberField : NumberField ℚ where noncomputable def ringOfIntegersEquiv : 𝓞 ℚ ≃+* ℤ := RingOfIntegers.equiv ℤ +@[simp] +theorem coe_ringOfIntegersEquiv (z : 𝓞 ℚ) : + (Rat.ringOfIntegersEquiv z : ℚ) = algebraMap (𝓞 ℚ) ℚ z := by + obtain ⟨z, rfl⟩ := Rat.ringOfIntegersEquiv.symm.surjective z + simp + end Rat namespace AdjoinRoot From 1e45d5cd7e9c7679d447d81fc9def277b54fc02d Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Wed, 8 Jan 2025 20:49:15 +0000 Subject: [PATCH 088/681] feat(Algebra/Module): definition of `R`-lattices (#19902) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given an integral domain `R` and its fraction field `K`, we define an `R`-lattice in a `K`-vector space `V` to be a finitely generated `R`-submodule of `V` that generates `V` over `K`. If `R` is a PID a lattice is always a free `R`-module of rank `Module.rank K V`. The unit group of `R` naturally acts on the type of `R`-lattices in `V`. If `V = Fin 2 → K` and `R` is a discrete valuation ring, the quotient by this action are the vertices of the Bruhat-Tits tree of `GL (Fin 2) K`. In this PR the predicate `IsLattice` on a submodule `M` is defined and some basic stability properties are shown. From "Formalizing the Bruhat-Tits tree" Co-authored by: Judith Ludwig Co-authored-by: judithludwig Co-authored-by: Christian Merten <136261474+chrisflav@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Algebra/Algebra/Basic.lean | 23 ++- Mathlib/Algebra/Module/Lattice.lean | 208 +++++++++++++++++++++ Mathlib/Algebra/Module/ZLattice/Basic.lean | 5 + 4 files changed, 227 insertions(+), 10 deletions(-) create mode 100644 Mathlib/Algebra/Module/Lattice.lean diff --git a/Mathlib.lean b/Mathlib.lean index 498301a86bee1..d9da848ebdd31 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -545,6 +545,7 @@ import Mathlib.Algebra.Module.FinitePresentation import Mathlib.Algebra.Module.GradedModule import Mathlib.Algebra.Module.Hom import Mathlib.Algebra.Module.Injective +import Mathlib.Algebra.Module.Lattice import Mathlib.Algebra.Module.LinearMap.Basic import Mathlib.Algebra.Module.LinearMap.Defs import Mathlib.Algebra.Module.LinearMap.End diff --git a/Mathlib/Algebra/Algebra/Basic.lean b/Mathlib/Algebra/Algebra/Basic.lean index acb9e00edf3c5..c80fff780d07d 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -334,18 +334,21 @@ theorem algebra_compatible_smul (r : R) (m : M) : r • m = (algebraMap R A) r theorem algebraMap_smul (r : R) (m : M) : (algebraMap R A) r • m = r • m := (algebra_compatible_smul A r m).symm +/-- If `M` is `A`-torsion free and `algebraMap R A` is injective, `M` is also `R`-torsion free. -/ +lemma NoZeroSMulDivisors.of_algebraMap_injective' {R A M : Type*} [CommSemiring R] [Semiring A] + [Algebra R A] [AddCommMonoid M] [Module R M] [Module A M] [IsScalarTower R A M] + [NoZeroSMulDivisors A M] (h : Function.Injective (algebraMap R A)) : + NoZeroSMulDivisors R M where + eq_zero_or_eq_zero_of_smul_eq_zero hx := by + rw [← algebraMap_smul (A := A)] at hx + obtain (hc|hx) := eq_zero_or_eq_zero_of_smul_eq_zero hx + · exact Or.inl <| (map_eq_zero_iff _ h).mp hc + · exact Or.inr hx + theorem NoZeroSMulDivisors.trans (R A M : Type*) [CommRing R] [Ring A] [IsDomain A] [Algebra R A] [AddCommGroup M] [Module R M] [Module A M] [IsScalarTower R A M] [NoZeroSMulDivisors R A] - [NoZeroSMulDivisors A M] : NoZeroSMulDivisors R M := by - refine ⟨fun {r m} h => ?_⟩ - rw [algebra_compatible_smul A r m] at h - rcases smul_eq_zero.1 h with H | H - · have : Function.Injective (algebraMap R A) := - NoZeroSMulDivisors.iff_algebraMap_injective.1 inferInstance - left - exact (injective_iff_map_eq_zero _).1 this _ H - · right - exact H + [NoZeroSMulDivisors A M] : NoZeroSMulDivisors R M := + of_algebraMap_injective' (A := A) (NoZeroSMulDivisors.iff_algebraMap_injective.1 inferInstance) variable {A} diff --git a/Mathlib/Algebra/Module/Lattice.lean b/Mathlib/Algebra/Module/Lattice.lean new file mode 100644 index 0000000000000..b05bf47a40a73 --- /dev/null +++ b/Mathlib/Algebra/Module/Lattice.lean @@ -0,0 +1,208 @@ +/- +Copyright (c) 2024 Judith Ludwig, Christian Merten. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Judith Ludwig, Christian Merten +-/ +import Mathlib.LinearAlgebra.Dimension.Localization +import Mathlib.LinearAlgebra.FiniteDimensional +import Mathlib.LinearAlgebra.FreeModule.PID + +/-! +# Lattices + +Let `A` be an `R`-algebra and `V` an `A`-module. Then an `R`-submodule `M` of `V` is a lattice, +if `M` is finitely generated and spans `V` as an `A`-module. + +The typical use case is `A = K` is the fraction field of an integral domain `R` and `V = ι → K` +for some finite `ι`. The scalar multiple a lattice by a unit in `K` is again a lattice. This gives +rise to a homothety relation. + +When `R` is a DVR and `ι = Fin 2`, then by taking the quotient of the type of `R`-lattices in +`ι → K` by the homothety relation, one obtains the vertices of what is called the Bruhat-Tits tree +of `GL 2 K`. + +## Main definitions + +- `Submodule.IsLattice`: An `R`-submodule `M` of `V` is a lattice, if it is finitely generated + and its `A`-span is `V`. + +## Main properties + +Let `R` be a PID and `A = K` its field of fractions. + +- `Submodule.IsLattice.free`: Every lattice in `V` is `R`-free. +- `Basis.extendOfIsLattice`: Any `R`-basis of a lattice `M` in `V` defines a `K`-basis of `V`. +- `Submodule.IsLattice.rank`: The `R`-rank of a lattice in `V` is equal to the `K`-rank of `V`. +- `Submodule.IsLattice.inf`: The intersection of two lattices is a lattice. + +## Note + +In the case `R = ℤ` and `A = K` a field, there is also `IsZLattice` where the finitely +generated condition is replaced by having the discrete topology. This is for example used +for complex tori. +-/ + +universe u + +variable {R : Type*} [CommRing R] + +open Pointwise + +namespace Submodule + +/-- +An `R`-submodule `M` of `V` is a lattice if it is finitely generated +and spans `V` as an `A`-module. + +Note 1: `A` is marked as an `outParam` here. In practice this should not cause issues, since +`R` and `A` are fixed, where typically `A` is the fraction field of `R`. + +Note 2: In the case `R = ℤ` and `A = K` a field, there is also `IsZLattice` where the finitely +generated condition is replaced by having the discrete topology. -/ +class IsLattice (A : outParam Type*) [CommRing A] [Algebra R A] + {V : Type*} [AddCommMonoid V] [Module R V] [Module A V] [IsScalarTower R A V] + [Algebra R A] [IsScalarTower R A V] (M : Submodule R V) : Prop where + fg : M.FG + span_eq_top : Submodule.span A (M : Set V) = ⊤ + +namespace IsLattice + +section + +variable (A : Type*) [CommRing A] [Algebra R A] +variable {V : Type*} [AddCommGroup V] [Module R V] [Module A V] [IsScalarTower R A V] +variable (M : Submodule R V) + +/-- Any `R`-lattice is finite. -/ +instance finite [IsLattice A M] : Module.Finite R M := by + rw [Module.Finite.iff_fg] + exact IsLattice.fg + +/-- The action of `Aˣ` on `R`-submodules of `V` preserves `IsLattice`. -/ +instance smul [IsLattice A M] (a : Aˣ) : IsLattice A (a • M : Submodule R V) where + fg := by + obtain ⟨s, rfl⟩ := IsLattice.fg (M := M) + rw [Submodule.smul_span] + have : Finite (a • (s : Set V) : Set V) := Finite.Set.finite_image _ _ + exact Submodule.fg_span (Set.toFinite (a • (s : Set V))) + span_eq_top := by + rw [Submodule.coe_pointwise_smul, ← Submodule.smul_span, IsLattice.span_eq_top] + ext x + refine ⟨fun _ ↦ trivial, fun _ ↦ ?_⟩ + rw [show x = a • a⁻¹ • x by simp] + exact Submodule.smul_mem_pointwise_smul _ _ _ (by trivial) + +lemma of_le_of_isLattice_of_fg {M N : Submodule R V} (hle : M ≤ N) [IsLattice A M] + (hfg : N.FG) : IsLattice A N := + ⟨hfg, eq_top_iff.mpr <| + le_trans (by rw [IsLattice.span_eq_top]) (Submodule.span_mono hle)⟩ + +/-- The supremum of two lattices is a lattice. -/ +instance sup (M N : Submodule R V) [IsLattice A M] [IsLattice A N] : + IsLattice A (M ⊔ N) := + of_le_of_isLattice_of_fg A le_sup_left (Submodule.FG.sup IsLattice.fg IsLattice.fg) + +end + +section Field + +variable {K : Type*} [Field K] [Algebra R K] + +lemma _root_.Submodule.span_range_eq_top_of_injective_of_rank_le {M N : Type u} [IsDomain R] + [IsFractionRing R K] [AddCommGroup M] [Module R M] + [AddCommGroup N] [Module R N] [Module K N] [IsScalarTower R K N] [Module.Finite K N] + {f : M →ₗ[R] N} (hf : Function.Injective f) (h : Module.rank K N ≤ Module.rank R M) : + Submodule.span K (LinearMap.range f : Set N) = ⊤ := by + obtain ⟨s, hs, hli⟩ := exists_set_linearIndependent R M + replace hli := hli.map' f (LinearMap.ker_eq_bot.mpr hf) + rw [LinearIndependent.iff_fractionRing (R := R) (K := K)] at hli + replace hs : Cardinal.mk s = Module.rank K N := + le_antisymm (LinearIndependent.cardinal_le_rank hli) (hs ▸ h) + rw [← Module.finrank_eq_rank, Cardinal.mk_eq_nat_iff_fintype] at hs + obtain ⟨hfin, hcard⟩ := hs + have hsubset : Set.range (fun x : s ↦ f x.val) ⊆ (LinearMap.range f : Set N) := by + rintro x ⟨a, rfl⟩ + simp + rw [eq_top_iff, ← LinearIndependent.span_eq_top_of_card_eq_finrank' hli hcard] + exact Submodule.span_mono hsubset + +variable (K) {V : Type*} [AddCommGroup V] [Module K V] [Module R V] [IsScalarTower R K V] + +/-- Any basis of an `R`-lattice in `V` defines a `K`-basis of `V`. -/ +noncomputable def _root_.Basis.extendOfIsLattice [IsFractionRing R K] {κ : Type*} + {M : Submodule R V} [IsLattice K M] (b : Basis κ R M) : + Basis κ K V := + have hli : LinearIndependent K (fun i ↦ (b i).val) := by + rw [← LinearIndependent.iff_fractionRing (R := R), linearIndependent_iff'] + intro s g hs + simp_rw [← Submodule.coe_smul_of_tower, ← Submodule.coe_sum, Submodule.coe_eq_zero] at hs + exact linearIndependent_iff'.mp b.linearIndependent s g hs + have hsp : ⊤ ≤ span K (Set.range fun i ↦ (M.subtype ∘ b) i) := by + rw [← Submodule.span_span_of_tower R, Set.range_comp, ← Submodule.map_span] + simp [b.span_eq, Submodule.map_top, span_eq_top] + Basis.mk hli hsp + +@[simp] +lemma _root_.Basis.extendOfIsLattice_apply [IsFractionRing R K] {κ : Type*} + {M : Submodule R V} [IsLattice K M] (b : Basis κ R M) (k : κ) : + b.extendOfIsLattice K k = (b k).val := by + simp [Basis.extendOfIsLattice] + +variable [IsDomain R] + +/-- A finitely-generated `R`-submodule of `V` of rank at least the `K`-rank of `V` +is a lattice. -/ +lemma of_rank_le [Module.Finite K V] [IsFractionRing R K] {M : Submodule R V} + (hfg : M.FG) (hr : Module.rank K V ≤ Module.rank R M) : IsLattice K M where + fg := hfg + span_eq_top := by + simpa using Submodule.span_range_eq_top_of_injective_of_rank_le M.injective_subtype hr + +variable [IsPrincipalIdealRing R] + +/-- Any lattice over a PID is a free `R`-module. +Note that under our conditions, `NoZeroSMulDivisors R K` simply says that `algebraMap R K` is +injective. -/ +instance free [NoZeroSMulDivisors R K] (M : Submodule R V) [IsLattice K M] : Module.Free R M := by + haveI : NoZeroSMulDivisors R V := by + apply NoZeroSMulDivisors.of_algebraMap_injective' (A := K) + exact NoZeroSMulDivisors.algebraMap_injective R K + -- any torsion free finite module over a PID is free + infer_instance + +/-- Any lattice has `R`-rank equal to the `K`-rank of `V`. -/ +lemma rank' [IsFractionRing R K] (M : Submodule R V) [IsLattice K M] : + Module.rank R M = Module.rank K V := by + let b := Module.Free.chooseBasis R M + rw [rank_eq_card_basis b, ← rank_eq_card_basis (b.extendOfIsLattice K)] + +/-- Any `R`-lattice in `ι → K` has `#ι` as `R`-rank. -/ +lemma rank_of_pi {ι : Type*} [Fintype ι] [IsFractionRing R K] (M : Submodule R (ι → K)) + [IsLattice K M] : Module.rank R M = Fintype.card ι := by + rw [IsLattice.rank' K M] + simp + +/-- `Module.finrank` version of `IsLattice.rank`. -/ +lemma finrank_of_pi {ι : Type*} [Fintype ι] [IsFractionRing R K] (M : Submodule R (ι → K)) + [IsLattice K M] : Module.finrank R M = Fintype.card ι := + Module.finrank_eq_of_rank_eq (IsLattice.rank_of_pi K M) + +/-- The intersection of two lattices is a lattice. -/ +instance inf [Module.Finite K V] [IsFractionRing R K] (M N : Submodule R V) + [IsLattice K M] [IsLattice K N] : IsLattice K (M ⊓ N) where + fg := by + have : IsNoetherian R ↥(M ⊓ N) := isNoetherian_of_le inf_le_left + rw [← Module.Finite.iff_fg] + infer_instance + span_eq_top := by + rw [← range_subtype (M ⊓ N)] + apply Submodule.span_range_eq_top_of_injective_of_rank_le (M ⊓ N).injective_subtype + have h := Submodule.rank_sup_add_rank_inf_eq M N + rw [IsLattice.rank' K M, IsLattice.rank' K N, IsLattice.rank'] at h + rw [Cardinal.eq_of_add_eq_add_left h (Module.rank_lt_aleph0 K V)] + +end Field + +end IsLattice + +end Submodule diff --git a/Mathlib/Algebra/Module/ZLattice/Basic.lean b/Mathlib/Algebra/Module/ZLattice/Basic.lean index 737a89b8c79d1..59e405c795223 100644 --- a/Mathlib/Algebra/Module/ZLattice/Basic.lean +++ b/Mathlib/Algebra/Module/ZLattice/Basic.lean @@ -37,6 +37,11 @@ of `ℤ`-rank equal to the `K`-rank of `E` `L` by `e`. If `L` is a `IsZLattice` and `e` is a continuous linear equiv, then it is also a `IsZLattice`, see `instIsZLatticeComap`. +## Note + +There is also `Submodule.IsLattice` which has slightly different applications. There no +topology is needed and the discrete condition is replaced by finitely generated. + ## Implementation Notes A `ZLattice` could be defined either as a `AddSubgroup E` or a `Submodule ℤ E`. However, the module From 7abb84e37d3e17409640af226047bbddbb911d59 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 8 Jan 2025 23:01:02 +0000 Subject: [PATCH 089/681] feat: `cache get` warns if given module names rather than paths (#20589) Per [zulip](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Size.20issue/near/492507604) discussion. --- .github/build.in.yml | 2 +- .github/workflows/bors.yml | 2 +- .github/workflows/build.yml | 2 +- .github/workflows/build_fork.yml | 2 +- Cache/Hashing.lean | 5 ++++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/build.in.yml b/.github/build.in.yml index 69c40f7765dae..c6392a395e227 100644 --- a/.github/build.in.yml +++ b/.github/build.in.yml @@ -128,7 +128,7 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init + lake exe cache get Mathlib/Init.lean lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index 3149eccc52722..9fbfeec9e2e21 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -138,7 +138,7 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init + lake exe cache get Mathlib/Init.lean lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a3bc5d84c1b0..ca2af1df663fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -145,7 +145,7 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init + lake exe cache get Mathlib/Init.lean lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index d7ceebe6b73e3..a0f4d80a41155 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -142,7 +142,7 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init + lake exe cache get Mathlib/Init.lean lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean diff --git a/Cache/Hashing.lean b/Cache/Hashing.lean index 5ebc53b76db24..59e77ad0c37b4 100644 --- a/Cache/Hashing.lean +++ b/Cache/Hashing.lean @@ -90,7 +90,10 @@ partial def getFileHash (filePath : FilePath) : HashM <| Option UInt64 := do | none => let fixedPath := (← IO.getPackageDir filePath) / filePath if !(← fixedPath.pathExists) then - IO.println s!"Warning: {fixedPath} not found. Skipping all files that depend on it" + IO.println s!"Warning: {fixedPath} not found. Skipping all files that depend on it." + if fixedPath.extension != "lean" then + IO.println s!"Note that `lake exe cache get ...` expects file names \ + (e.g. `Mathlib/Init.lean`), not module names (e.g. `Mathlib.Init`)." modify fun stt => { stt with cache := stt.cache.insert filePath none } return none let content ← IO.FS.readFile fixedPath From d4891b46ecc82d3f6050dd51c2699fee91a2347b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 8 Jan 2025 23:18:58 +0000 Subject: [PATCH 090/681] =?UTF-8?q?feat:=20`a=20^=20n=20=E2=8A=94=20b=20^?= =?UTF-8?q?=20n=20=E2=89=A4=20(a=20=E2=8A=94=20b)=20^=20n`=20(#20577)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From GrowthInGroups (LeanCamCombi) --- .../Algebra/Order/Monoid/Unbundled/Pow.lean | 30 +++++++++++++++---- Mathlib/Algebra/Order/Ring/Basic.lean | 1 - 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean index 32f0ddb84013a..f1f71c008082b 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean @@ -58,24 +58,28 @@ end Left section Left -variable [MulLeftMono M] +variable [MulLeftMono M] {a : M} {n : ℕ} @[to_additive nsmul_left_monotone] -theorem pow_right_monotone {a : M} (ha : 1 ≤ a) : Monotone fun n : ℕ ↦ a ^ n := +theorem pow_right_monotone (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 := +theorem pow_le_pow_right' {n m : ℕ} (ha : 1 ≤ a) (h : n ≤ m) : a ^ n ≤ a ^ m := 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 := +theorem pow_le_pow_right_of_le_one' {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 := +theorem one_lt_pow' (ha : 1 < a) {k : ℕ} (hk : k ≠ 0) : 1 < a ^ k := pow_lt_one' (M := Mᵒᵈ) ha hk +@[to_additive] +lemma le_self_pow (ha : 1 ≤ a) (hn : n ≠ 0) : a ≤ a ^ n := by + simpa using pow_le_pow_right' ha (Nat.one_le_iff_ne_zero.2 hn) + end Left section LeftLt @@ -185,6 +189,22 @@ end CovariantLESwap end Preorder +section SemilatticeSup +variable [SemilatticeSup M] [MulLeftMono M] [MulRightMono M] {a b : M} {n : ℕ} + +lemma le_pow_sup : a ^ n ⊔ b ^ n ≤ (a ⊔ b) ^ n := + sup_le (pow_le_pow_left' le_sup_left _) (pow_le_pow_left' le_sup_right _) + +end SemilatticeSup + +section SemilatticeInf +variable [SemilatticeInf M] [MulLeftMono M] [MulRightMono M] {a b : M} {n : ℕ} + +lemma pow_inf_le : (a ⊓ b) ^ n ≤ a ^ n ⊓ b ^ n := + le_inf (pow_le_pow_left' inf_le_left _) (pow_le_pow_left' inf_le_right _) + +end SemilatticeInf + section LinearOrder variable [LinearOrder M] diff --git a/Mathlib/Algebra/Order/Ring/Basic.lean b/Mathlib/Algebra/Order/Ring/Basic.lean index 5085a583c3ee7..0761f4188a584 100644 --- a/Mathlib/Algebra/Order/Ring/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Basic.lean @@ -72,7 +72,6 @@ attribute [bound] pow_le_one₀ one_le_pow₀ @[deprecated (since := "2024-09-28")] alias one_lt_pow := one_lt_pow₀ @[deprecated (since := "2024-10-04")] alias pow_right_mono := pow_right_mono₀ @[deprecated (since := "2024-10-04")] alias pow_le_pow_right := pow_le_pow_right₀ -@[deprecated (since := "2024-10-04")] alias le_self_pow := le_self_pow₀ @[deprecated pow_le_pow_left₀ (since := "2024-11-13")] theorem pow_le_pow_left {a b : R} (ha : 0 ≤ a) (hab : a ≤ b) : ∀ n, a ^ n ≤ b ^ n := From f227e4af164386c81166cdc4e8e263323b586a36 Mon Sep 17 00:00:00 2001 From: smorel394 Date: Thu, 9 Jan 2025 08:10:32 +0000 Subject: [PATCH 091/681] feat(Algebra/Module/CharacterModule): a morphism of abelian groups is bijective if and only if its dual is bijective (#20512) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prove that a morphism of abelian groups `f` is surjective if and only if its dual is injective, deduce that `f` is bijective if and only if its dual is bijective. Note: here we use duality with coefficients in `ℚ ⧸ ℤ`. Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- Mathlib/Algebra/Module/CharacterModule.lean | 37 +++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Mathlib/Algebra/Module/CharacterModule.lean b/Mathlib/Algebra/Module/CharacterModule.lean index 1f39cb315264c..b4146d2497f6a 100644 --- a/Mathlib/Algebra/Module/CharacterModule.lean +++ b/Mathlib/Algebra/Module/CharacterModule.lean @@ -77,6 +77,24 @@ from `B⋆` to `A⋆`. map_add' := by aesop map_smul' r c := by ext x; exact congr(c $(f.map_smul r x)).symm +@[simp] +lemma dual_zero : dual (0 : A →ₗ[R] B) = 0 := by + ext f + exact map_zero f + +lemma dual_comp {C : Type*} [AddCommGroup C] [Module R C] (f : A →ₗ[R] B) (g : B →ₗ[R] C) : + dual (g.comp f) = (dual f).comp (dual g) := by + ext + rfl + +lemma dual_injective_of_surjective (f : A →ₗ[R] B) (hf : Function.Surjective f) : + Function.Injective (dual f) := by + intro φ ψ eq + ext x + obtain ⟨y, rfl⟩ := hf x + change (dual f) φ _ = (dual f) ψ _ + rw [eq] + lemma dual_surjective_of_injective (f : A →ₗ[R] B) (hf : Function.Injective f) : Function.Surjective (dual f) := (Module.Baer.of_divisible _).extension_property_addMonoidHom _ hf @@ -211,4 +229,23 @@ theorem _root_.rTensor_injective_iff_lcomp_surjective {f : A →ₗ[R] A'} : Function.Injective (f.rTensor B) ↔ Function.Surjective (f.lcomp R <| CharacterModule B) := by simp [← dual_rTensor_conj_homEquiv, dual_surjective_iff_injective] +lemma surjective_of_dual_injective (f : A →ₗ[R] A') (hf : Function.Injective (dual f)) : + Function.Surjective f := by + rw [← LinearMap.range_eq_top, ← Submodule.unique_quotient_iff_eq_top] + refine ⟨Unique.mk inferInstance fun a ↦ eq_zero_of_character_apply fun c ↦ ?_⟩ + obtain ⟨b, rfl⟩ := QuotientAddGroup.mk'_surjective _ a + suffices eq : dual (Submodule.mkQ _) c = 0 from congr($eq b) + refine hf ?_ + rw [← LinearMap.comp_apply, ← dual_comp, LinearMap.range_mkQ_comp, dual_zero] + rfl + +lemma dual_injective_iff_surjective {f : A →ₗ[R] A'} : + Function.Injective (dual f) ↔ Function.Surjective f := + ⟨fun h ↦ surjective_of_dual_injective f h, fun h ↦ dual_injective_of_surjective f h⟩ + +lemma dual_bijective_iff_bijective {f : A →ₗ[R] A'} : + Function.Bijective (dual f) ↔ Function.Bijective f := + ⟨fun h ↦ ⟨dual_surjective_iff_injective.mp h.2, dual_injective_iff_surjective.mp h.1⟩, + fun h ↦ ⟨dual_injective_iff_surjective.mpr h.2, dual_surjective_iff_injective.mpr h.1⟩⟩ + end CharacterModule From 5e91013b6241a6c6fd2977c23416a87fc61d9e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 9 Jan 2025 08:48:37 +0000 Subject: [PATCH 092/681] feat: pointwise set operations commute with cartesian product (#20579) From GrowthInGroups (LeanCamCombi) --- .../Algebra/Group/Pointwise/Finset/Basic.lean | 17 ++++++++++++++++ .../Algebra/Group/Pointwise/Set/Basic.lean | 20 ++++++++++++++++++- Mathlib/Algebra/MvPolynomial/Equiv.lean | 6 +++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean index a01f060a58f0e..a299acb8cadfe 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean @@ -178,6 +178,9 @@ lemma image_op_one [DecidableEq α] : (1 : Finset α).image op = 1 := rfl @[to_additive (attr := simp)] lemma map_op_one : (1 : Finset α).map opEquiv.toEmbedding = 1 := rfl +@[to_additive (attr := simp)] +lemma one_product_one [One β] : (1 ×ˢ 1 : Finset (α × β)) = 1 := by ext; simp [Prod.ext_iff] + end One /-! ### Finset negation/inversion -/ @@ -295,6 +298,10 @@ lemma inv_univ [Fintype α] : (univ : Finset α)⁻¹ = univ := by ext; simp @[to_additive (attr := simp)] lemma inv_inter (s t : Finset α) : (s ∩ t)⁻¹ = s⁻¹ ∩ t⁻¹ := coe_injective <| by simp +@[to_additive (attr := simp)] +lemma inv_product [DecidableEq β] [InvolutiveInv β] (s : Finset α) (t : Finset β) : + (s ×ˢ t)⁻¹ = s⁻¹ ×ˢ t⁻¹ := mod_cast s.toSet.inv_prod t.toSet + end InvolutiveInv /-! ### Scalar addition/multiplication of finsets -/ @@ -600,6 +607,11 @@ theorem image_mul [DecidableEq β] : (s * t).image (f : α → β) = s.image f * lemma image_op_mul (s t : Finset α) : (s * t).image op = t.image op * s.image op := image_image₂_antidistrib op_mul +@[to_additive (attr := simp)] +lemma product_mul_product_comm [DecidableEq β] (s₁ s₂ : Finset α) (t₁ t₂ : Finset β) : + (s₁ ×ˢ t₁) * (s₂ ×ˢ t₂) = (s₁ * s₂) ×ˢ (t₁ * t₂) := + mod_cast s₁.toSet.prod_mul_prod_comm s₂ t₁.toSet t₂ + @[to_additive] lemma map_op_mul (s t : Finset α) : (s * t).map opEquiv.toEmbedding = t.map opEquiv.toEmbedding * s.map opEquiv.toEmbedding := by @@ -1069,6 +1081,11 @@ lemma map_op_pow (s : Finset α) : | 0 => by simp [singleton_one] | n + 1 => by rw [pow_succ, pow_succ', map_op_mul, map_op_pow] +@[to_additive] +lemma product_pow [Monoid β] (s : Finset α) (t : Finset β) : ∀ n, (s ×ˢ t) ^ n = (s ^ n) ×ˢ (t ^ n) + | 0 => by simp + | n + 1 => by simp [pow_succ, product_pow _ _ n] + end Monoid section CommMonoid diff --git a/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean index 2582ba633719e..244cc84123a5a 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean @@ -1,9 +1,10 @@ /- Copyright (c) 2019 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin, Floris van Doorn +Authors: Johan Commelin, Floris van Doorn, Yaël Dillies -/ import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.Opposites import Mathlib.Algebra.Order.Monoid.Unbundled.Pow @@ -134,6 +135,9 @@ theorem coe_singletonOneHom : (singletonOneHom : α → Set α) = singleton := @[to_additive] lemma image_op_one : (1 : Set α).image op = 1 := image_singleton +@[to_additive (attr := simp)] +lemma one_prod_one [One β] : (1 ×ˢ 1 : Set (α × β)) = 1 := by ext; simp [Prod.ext_iff] + end One /-! ### Set negation/inversion -/ @@ -201,6 +205,9 @@ theorem sUnion_inv (S : Set (Set α)) : (⋃₀ S)⁻¹ = ⋃ s ∈ S, s⁻¹ := theorem compl_inv : sᶜ⁻¹ = s⁻¹ᶜ := preimage_compl +@[to_additive (attr := simp)] +lemma inv_prod [Inv β] (s : Set α) (t : Set β) : (s ×ˢ t)⁻¹ = s⁻¹ ×ˢ t⁻¹ := rfl + end Inv section InvolutiveInv @@ -467,6 +474,10 @@ open MulOpposite theorem image_op_mul : op '' (s * t) = op '' t * op '' s := image_image2_antidistrib op_mul +@[to_additive (attr := simp)] +lemma prod_mul_prod_comm [Mul β] (s₁ s₂: Set α) (t₁ t₂ : Set β) : + (s₁ ×ˢ t₁) * (s₂ ×ˢ t₂) = (s₁ * s₂) ×ˢ (t₁ * t₂) := by ext; simp [mem_mul]; aesop + end Mul /-! ### Set subtraction/division -/ @@ -1165,6 +1176,11 @@ theorem univ_pow : ∀ {n : ℕ}, n ≠ 0 → (univ : Set α) ^ n = univ protected theorem _root_.IsUnit.set : IsUnit a → IsUnit ({a} : Set α) := IsUnit.map (singletonMonoidHom : α →* Set α) +@[to_additive] +lemma prod_pow [Monoid β] (s : Set α) (t : Set β) : ∀ n, (s ×ˢ t) ^ n = (s ^ n) ×ˢ (t ^ n) + | 0 => by simp + | n + 1 => by simp [pow_succ, prod_pow _ _ n] + end Monoid section IsLeftCancelMul @@ -1495,3 +1511,5 @@ lemma MapsTo.div [DivisionCommMonoid β] {A : Set α} {B₁ B₂ : Set β} {f₁ end Pointwise end Set + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index 444676431d13e..9f7c660990ad0 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -367,12 +367,12 @@ theorem finSuccEquiv_coeff_coeff (m : Fin n →₀ ℕ) (f : MvPolynomial (Fin ( induction' f using MvPolynomial.induction_on' with j r p q hp hq generalizing i m swap · simp only [map_add, Polynomial.coeff_add, coeff_add, hp, hq] - simp only [finSuccEquiv_apply, coe_eval₂Hom, eval₂_monomial, RingHom.coe_comp, prod_pow, + simp only [finSuccEquiv_apply, coe_eval₂Hom, eval₂_monomial, RingHom.coe_comp, Finsupp.prod_pow, Polynomial.coeff_C_mul, coeff_C_mul, coeff_monomial, Fin.prod_univ_succ, Fin.cases_zero, Fin.cases_succ, ← map_prod, ← RingHom.map_pow, Function.comp_apply] rw [← mul_boole, mul_comm (Polynomial.X ^ j 0), Polynomial.coeff_C_mul_X_pow]; congr 1 obtain rfl | hjmi := eq_or_ne j (m.cons i) - · simpa only [cons_zero, cons_succ, if_pos rfl, monomial_eq, C_1, one_mul, prod_pow] using + · simpa only [cons_zero, cons_succ, if_pos rfl, monomial_eq, C_1, one_mul, Finsupp.prod_pow] using coeff_monomial m m (1 : R) · simp only [hjmi, if_false] obtain hij | rfl := ne_or_eq i (j 0) @@ -382,7 +382,7 @@ theorem finSuccEquiv_coeff_coeff (m : Fin n →₀ ℕ) (f : MvPolynomial (Fin ( rintro rfl rw [cons_tail] at hjmi contradiction - simpa only [monomial_eq, C_1, one_mul, prod_pow, Finsupp.tail_apply, if_neg hmj.symm] using + simpa only [monomial_eq, C_1, one_mul, Finsupp.prod_pow, tail_apply, if_neg hmj.symm] using coeff_monomial m j.tail (1 : R) theorem eval_eq_eval_mv_eval' (s : Fin n → R) (y : R) (f : MvPolynomial (Fin (n + 1)) R) : From 4755cdd41545a5cbb88c3a0c3092554467cd9886 Mon Sep 17 00:00:00 2001 From: Oliver Nash Date: Thu, 9 Jan 2025 09:30:49 +0000 Subject: [PATCH 093/681] feat: make spanning condition in `RootSystem` symmetric for roots and coroots. (#20564) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The key change here is the additional axiom which I have added to root systems demanding `span R (range coroot) = ⊤`. This means that certain root pairings no longer qualify as root systems. We're in uncharted territory here (the informal literature only considers more specialised situations and so avoids this issue) but I claim the most useful definition will be one with a perfect symmetry between roots and coroots. --- Mathlib/Algebra/Lie/Weights/RootSystem.lean | 2 ++ Mathlib/LinearAlgebra/RootSystem/Basic.lean | 29 ++++++++++++------- Mathlib/LinearAlgebra/RootSystem/Defs.lean | 8 +++-- .../RootSystem/Finite/Nondegenerate.lean | 10 ++++++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/Mathlib/Algebra/Lie/Weights/RootSystem.lean b/Mathlib/Algebra/Lie/Weights/RootSystem.lean index 052e935cc4836..73c1e4f1312b4 100644 --- a/Mathlib/Algebra/Lie/Weights/RootSystem.lean +++ b/Mathlib/Algebra/Lie/Weights/RootSystem.lean @@ -392,6 +392,8 @@ def rootSystem : Function.comp_apply, Set.mem_range, Subtype.exists, exists_prop] exact ⟨reflectRoot α β, (by simpa using reflectRoot_isNonZero α β <| by simpa using hβ), rfl⟩) (by convert span_weight_isNonZero_eq_top K L H; ext; simp) + (fun α β ↦ + ⟨chainBotCoeff β.1 α.1 - chainTopCoeff β.1 α.1, by simp [apply_coroot_eq_cast β.1 α.1]⟩) @[simp] lemma corootForm_rootSystem_eq_killing : diff --git a/Mathlib/LinearAlgebra/RootSystem/Basic.lean b/Mathlib/LinearAlgebra/RootSystem/Basic.lean index 749ec3364bcb0..c5cbc95411c77 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Basic.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash, Deepro Choudhury, Scott Carnahan -/ import Mathlib.LinearAlgebra.RootSystem.Defs +import Mathlib.LinearAlgebra.RootSystem.Finite.Nondegenerate /-! # Root data and root systems @@ -184,7 +185,7 @@ private lemma coroot_eq_coreflection_of_root_eq' [CharZero R] [NoZeroSMulDivisor /-- In characteristic zero if there is no torsion, to check that two finite families of roots and coroots form a root pairing, it is sufficient to check that they are stable under reflections. -/ -def mk' [Finite ι] [CharZero R] [NoZeroSMulDivisors R M] +def mk' [CharZero R] [NoZeroSMulDivisors R M] (p : PerfectPairing R M N) (root : ι ↪ M) (coroot : ι ↪ N) @@ -232,7 +233,7 @@ protected lemma ext [CharZero R] [NoZeroSMulDivisors R M] rintro P₁ P₂ he hr - ⟨i, rfl⟩ use i apply P₁.bijectiveRight.injective - apply Dual.eq_of_preReflection_mapsTo (finite_range P₁.root) P₁.span_eq_top + apply Dual.eq_of_preReflection_mapsTo (finite_range P₁.root) P₁.span_root_eq_top · exact hr ▸ he ▸ P₂.coroot_root_two i · exact hr ▸ he ▸ P₂.mapsTo_reflection_root i · exact P₁.coroot_root_two i @@ -268,22 +269,28 @@ private lemma coroot_eq_coreflection_of_root_eq_of_span_eq_top [CharZero R] [NoZ · rw [hk, hij] exact (hs i).comp <| (hs j).comp (hs i) -/-- In characteristic zero if there is no torsion, to check that a finite family of roots form a -root system, we do not need to check that the coroots are stable under reflections since this -follows from the corresponding property for the roots. -/ -def mk' [CharZero R] [NoZeroSMulDivisors R M] - (p : PerfectPairing R M N) +/-- Over a field of characteristic zero, to check that a finite family of roots form a +crystallographic root system, we do not need to check that the coroots are stable under reflections +since this follows from the corresponding property for the roots. Likewise, we do not need to +check that the coroots span. -/ +def mk' {k : Type*} [Field k] [CharZero k] [Module k M] [Module k N] + (p : PerfectPairing k M N) (root : ι ↪ M) (coroot : ι ↪ N) (hp : ∀ i, p.toLin (root i) (coroot i) = 2) (hs : ∀ i, MapsTo (preReflection (root i) (p.toLin.flip (coroot i))) (range root) (range root)) - (hsp : span R (range root) = ⊤) : - RootSystem ι R M N where - span_eq_top := hsp - toRootPairing := RootPairing.mk' p root coroot hp hs <| by + (hsp : span k (range root) = ⊤) + (h_int : ∀ i j, ∃ z : ℤ, z = p (root i) (coroot j)) : + RootSystem ι k M N := + let P := RootPairing.mk' p root coroot hp hs <| by rintro i - ⟨j, rfl⟩ use RootPairing.equiv_of_mapsTo p root coroot i hs hp j refine (coroot_eq_coreflection_of_root_eq_of_span_eq_top p root coroot hp hs hsp ?_) rw [equiv_of_mapsTo_apply, (exist_eq_reflection_of_mapsTo p root coroot i j hs).choose_spec] + have _i : P.IsCrystallographic := ⟨h_int⟩ + have _i : Fintype ι := Fintype.ofFinite ι + { toRootPairing := P, + span_root_eq_top := hsp, + span_coroot_eq_top := P.rootSpan_eq_top_iff.mp hsp } end RootSystem diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index 39c9941d22e0f..586c5dbb3ee6e 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -110,14 +110,16 @@ Note that the latter assumptions `[Free ℤ X₁] [Finite ℤ X₁] [Free ℤ X supplied as mixins. -/ abbrev RootDatum (X₁ X₂ : Type*) [AddCommGroup X₁] [AddCommGroup X₂] := RootPairing ι ℤ X₁ X₂ -/-- A root system is a root pairing for which the roots span their ambient module. +/-- A root system is a root pairing for which the roots and coroots span their ambient modules. Note that this is slightly more general than the usual definition in the sense that `N` is not required to be the dual of `M`. -/ structure RootSystem extends RootPairing ι R M N where - span_eq_top : span R (range root) = ⊤ + span_root_eq_top : span R (range root) = ⊤ + span_coroot_eq_top : span R (range coroot) = ⊤ -attribute [simp] RootSystem.span_eq_top +attribute [simp] RootSystem.span_root_eq_top +attribute [simp] RootSystem.span_coroot_eq_top namespace RootPairing diff --git a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean index 4157651396831..1d04a0c2f32ce 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean @@ -184,6 +184,14 @@ lemma orthogonal_corootSpan_eq : P.CorootForm.orthogonal P.corootSpan = LinearMap.ker P.CorootForm := P.flip.orthogonal_rootSpan_eq +lemma rootSpan_eq_top_iff : + P.rootSpan = ⊤ ↔ P.corootSpan = ⊤ := by + have := P.toPerfectPairing.reflexive_left + have := P.toPerfectPairing.reflexive_right + refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ <;> apply Submodule.eq_top_of_finrank_eq + · rw [P.finrank_corootSpan_eq, h, finrank_top, P.toPerfectPairing.finrank_eq] + · rw [← P.finrank_corootSpan_eq, h, finrank_top, P.toPerfectPairing.finrank_eq] + end Field section LinearOrderedCommRing @@ -215,7 +223,7 @@ lemma rootForm_pos_of_ne_zero {x : M} (hx : x ∈ P.rootSpan) (h : x ≠ 0) : lemma _root_.RootSystem.rootForm_anisotropic (P : RootSystem ι R M N) : P.RootForm.toQuadraticMap.Anisotropic := fun x ↦ P.eq_zero_of_mem_rootSpan_of_rootForm_self_eq_zero <| by - simpa only [rootSpan, P.span_eq_top] using Submodule.mem_top + simpa only [rootSpan, P.span_root_eq_top] using Submodule.mem_top end LinearOrderedCommRing From 30db47d28cc5409f8a08170d5ebdd55a9940a460 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 9 Jan 2025 10:01:44 +0000 Subject: [PATCH 094/681] feat: `simp` lemmas for degenerate uses of `IsCoprime` (#20569) @erdOne had another proof of `Nat.isCoprime_iff` [on Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Create.20instance.20.60CommSemiring.20.E2.84.95.2B.60.2C.20.20err.20.60expected.20structure.60/near/487351085) Also adds some unrelated `abs` lemmas. Co-authored-by: Eric Wieser --- .../Algebra/GroupWithZero/Divisibility.lean | 15 ++++++ Mathlib/RingTheory/Coprime/Basic.lean | 46 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/Mathlib/Algebra/GroupWithZero/Divisibility.lean b/Mathlib/Algebra/GroupWithZero/Divisibility.lean index c2ff18e038a60..7ba1e0c088569 100644 --- a/Mathlib/Algebra/GroupWithZero/Divisibility.lean +++ b/Mathlib/Algebra/GroupWithZero/Divisibility.lean @@ -168,3 +168,18 @@ lemma pow_dvd_pow_iff (ha₀ : a ≠ 0) (ha : ¬IsUnit a) : a ^ n ∣ a ^ m ↔ · apply pow_dvd_pow end CancelCommMonoidWithZero + +section GroupWithZero +variable [GroupWithZero α] + +/-- `∣` is not a useful definition if an inverse is available. -/ +@[simp] +lemma GroupWithZero.dvd_iff {m n : α} : m ∣ n ↔ (m = 0 → n = 0) := by + refine ⟨fun ⟨a, ha⟩ hm => ?_, fun h => ?_⟩ + · simp [hm, ha] + · refine ⟨m⁻¹ * n, ?_⟩ + obtain rfl | hn := eq_or_ne n 0 + · simp + · rw [mul_inv_cancel_left₀ (mt h hn)] + +end GroupWithZero diff --git a/Mathlib/RingTheory/Coprime/Basic.lean b/Mathlib/RingTheory/Coprime/Basic.lean index 0e608f5a7df62..71cc3bf259895 100644 --- a/Mathlib/RingTheory/Coprime/Basic.lean +++ b/Mathlib/RingTheory/Coprime/Basic.lean @@ -367,6 +367,29 @@ theorem neg_neg {x y : R} (h : IsCoprime x y) : IsCoprime (-x) (-y) := theorem neg_neg_iff (x y : R) : IsCoprime (-x) (-y) ↔ IsCoprime x y := (neg_left_iff _ _).trans (neg_right_iff _ _) +section abs + +variable [LinearOrder R] [AddLeftMono R] + +lemma abs_left_iff (x y : R) : IsCoprime |x| y ↔ IsCoprime x y := by + cases le_or_lt 0 x with + | inl h => rw [abs_of_nonneg h] + | inr h => rw [abs_of_neg h, IsCoprime.neg_left_iff] + +lemma abs_left {x y : R} (h : IsCoprime x y) : IsCoprime |x| y := abs_left_iff _ _ |>.2 h + +lemma abs_right_iff (x y : R) : IsCoprime x |y| ↔ IsCoprime x y := by + rw [isCoprime_comm, IsCoprime.abs_left_iff, isCoprime_comm] + +lemma abs_right {x y : R} (h : IsCoprime x y) : IsCoprime x |y| := abs_right_iff _ _ |>.2 h + +theorem abs_abs_iff (x y : R) : IsCoprime |x| |y| ↔ IsCoprime x y := + (abs_left_iff _ _).trans (abs_right_iff _ _) + +theorem abs_abs {x y : R} (h : IsCoprime x y) : IsCoprime |x| |y| := h.abs_left.abs_right + +end abs + end CommRing theorem sq_add_sq_ne_zero {R : Type*} [LinearOrderedCommRing R] {a b : R} (h : IsCoprime a b) : @@ -379,6 +402,29 @@ theorem sq_add_sq_ne_zero {R : Type*} [LinearOrderedCommRing R] {a b : R} (h : I end IsCoprime +/-- `IsCoprime` is not a useful definition for `Nat`; consider using `Nat.Coprime` instead. -/ +@[simp] +lemma Nat.isCoprime_iff {m n : ℕ} : IsCoprime m n ↔ m = 1 ∨ n = 1 := by + refine ⟨fun ⟨a, b, H⟩ => ?_, fun h => ?_⟩ + · simp_rw [Nat.add_eq_one_iff, mul_eq_one, mul_eq_zero] at H + exact H.symm.imp (·.1.2) (·.2.2) + · obtain rfl | rfl := h + · exact isCoprime_one_left + · exact isCoprime_one_right + +/-- `IsCoprime` is not a useful definition for `PNat`; consider using `Nat.Coprime` instead. -/ +lemma PNat.isCoprime_iff {m n : ℕ+} : IsCoprime (m : ℕ) n ↔ m = 1 ∨ n = 1 := by simp + +/-- `IsCoprime` is not a useful definition if an inverse is available. -/ +@[simp] +lemma Semifield.isCoprime_iff {R : Type*} [Semifield R] {m n : R} : + IsCoprime m n ↔ m ≠ 0 ∨ n ≠ 0 := by + obtain rfl | hn := eq_or_ne n 0 + · simp [isCoprime_zero_right] + suffices IsCoprime m n by simpa [hn] + refine ⟨0, n⁻¹, ?_⟩ + simp [inv_mul_cancel₀ hn] + namespace IsRelPrime variable {R} [CommRing R] {x y : R} From f3e168c002768d40a560865070513307c93feb0c Mon Sep 17 00:00:00 2001 From: blizzard_inc Date: Thu, 9 Jan 2025 10:38:10 +0000 Subject: [PATCH 095/681] feat: Add codeaction and widget to success_if_fail_with_msg tactic (#20378) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit make the `success_if_fail_with_msg` tactic give a codeaction when the tactics given fail with a different error, to update the expected error message. example: ```lean4 example : Nat → Nat → True := by success_if_fail_with_msg "no goals" -- Update with tactic error message: "no goals to be solved" intro intro trivial trivial intros; trivial ``` --- Mathlib/Tactic/SuccessIfFailWithMsg.lean | 19 +++++++++++++------ MathlibTest/success_if_fail_with_msg.lean | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Mathlib/Tactic/SuccessIfFailWithMsg.lean b/Mathlib/Tactic/SuccessIfFailWithMsg.lean index b3ef1a312fae9..4fb8d3260f959 100644 --- a/Mathlib/Tactic/SuccessIfFailWithMsg.lean +++ b/Mathlib/Tactic/SuccessIfFailWithMsg.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro, Simon Hudon, Sébastien Gouëzel, Kim Morrison, Thomas import Lean.Elab.Eval import Lean.Elab.Tactic.BuiltinTactic import Mathlib.Init +import Lean.Meta.Tactic.TryThis /-! # Success If Fail With Message @@ -16,7 +17,7 @@ It's mostly useful in tests, where we want to make sure that tactics fail in cer circumstances. -/ -open Lean Elab Tactic +open Lean Meta Elab Tactic namespace Mathlib.Tactic @@ -28,9 +29,9 @@ syntax (name := successIfFailWithMsg) "success_if_fail_with_msg " term:max tacti /-- Evaluates `tacs` and succeeds only if `tacs` both fails and throws an error equal (as a string) to `msg`. -/ -def successIfFailWithMessage {s α : Type} {m : Type → Type} - [Monad m] [MonadLiftT BaseIO m] [MonadBacktrack s m] [MonadError m] - (msg : String) (tacs : m α) (ref : Option Syntax := none) : m Unit := do +def successIfFailWithMessage {s α : Type} {m : Type → Type} [Monad m] [MonadLiftT BaseIO m] + [MonadLiftT MetaM m] [MonadBacktrack s m] [MonadError m] (msg : String) (tacs : m α) + (msgref : Option Syntax := none) (ref : Option Syntax := none) : m Unit := do let s ← saveState let err ← try _ ← tacs; pure none @@ -38,6 +39,12 @@ def successIfFailWithMessage {s α : Type} {m : Type → Type} restoreState s if let some err := err then unless msg.trim == err.trim do + if let .some msgref := msgref then + let suggestion : TryThis.Suggestion := + { suggestion := s!"\"{err.trim}\"" + toCodeActionTitle? := .some (fun _ => "Update with tactic error message")} + TryThis.addSuggestion msgref suggestion (header := "Update with tactic error message: ") + if let some ref := ref then throwErrorAt ref "tactic '{ref}' failed, but got different error message:\n\n{err}" else @@ -51,7 +58,7 @@ def successIfFailWithMessage {s α : Type} {m : Type → Type} elab_rules : tactic | `(tactic| success_if_fail_with_msg $msg:term $tacs:tacticSeq) => Term.withoutErrToSorry <| withoutRecover do - let msg ← unsafe Term.evalTerm String (.const ``String []) msg - successIfFailWithMessage msg (evalTacticSeq tacs) tacs + let msg' ← unsafe Term.evalTerm String (.const ``String []) msg + successIfFailWithMessage msg' (evalTacticSeq tacs) msg tacs end Mathlib.Tactic diff --git a/MathlibTest/success_if_fail_with_msg.lean b/MathlibTest/success_if_fail_with_msg.lean index dcbafdaf29dcb..946d9f5533ebf 100644 --- a/MathlibTest/success_if_fail_with_msg.lean +++ b/MathlibTest/success_if_fail_with_msg.lean @@ -11,6 +11,28 @@ example : Nat → Nat → True := by trivial intros; trivial +/-- +info: Update with tactic error message: "no goals to be solved" +--- +error: tactic ' + intro + intro + trivial + trivial' failed, but got different error message: + +no goals to be solved +-/ +#guard_msgs in +example : Nat → Nat → True := by + success_if_fail_with_msg "no goals" + intro + intro + trivial + trivial + intros; trivial + + + def err (t : Bool) := if t then "tactic 'rewrite' failed, equality or iff proof expected n ≤ n.succ From e1af5e86242cfaac0bc5682bf36dbaf9c8e1ff71 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Thu, 9 Jan 2025 10:38:11 +0000 Subject: [PATCH 096/681] chore(RingTheory/Ideal/Quotient): shorten proof of ringCon.mul' (#20586) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces four lines of proof with a single invocation of [`mul_sub_mul_mem](https://github.com/leanprover-community/mathlib4/blob/8421da8699ad0386cf29f4c0e67497a819e04cba/Mathlib/RingTheory/Ideal/Defs.lean#L144). The goal at this point in the proof is ```lean ... I : Ideal R a₁ b₁ a₂ b₂ : R h₁ : a₁ - b₁ ∈ I h₂ : a₂ - b₂ ∈ I ⊢ a₁ * a₂ - b₁ * b₂ ∈ I ``` which is exactly what `mul_sub_mul_mem` provides. Found via [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). --- Mathlib/RingTheory/Ideal/Quotient/Defs.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Mathlib/RingTheory/Ideal/Quotient/Defs.lean b/Mathlib/RingTheory/Ideal/Quotient/Defs.lean index a060399646f49..d7af0ce89bff8 100644 --- a/Mathlib/RingTheory/Ideal/Quotient/Defs.lean +++ b/Mathlib/RingTheory/Ideal/Quotient/Defs.lean @@ -58,10 +58,7 @@ protected def ringCon (I : Ideal R) : RingCon R := { QuotientAddGroup.con I.toAddSubgroup with mul' := fun {a₁ b₁ a₂ b₂} h₁ h₂ => by rw [Submodule.quotientRel_def] at h₁ h₂ ⊢ - have F := I.add_mem (I.mul_mem_left a₂ h₁) (I.mul_mem_right b₁ h₂) - have : a₁ * a₂ - b₁ * b₂ = a₂ * (a₁ - b₁) + (a₂ - b₂) * b₁ := by - rw [mul_sub, sub_mul, sub_add_sub_cancel, mul_comm, mul_comm b₁] - rwa [← this] at F } + exact mul_sub_mul_mem I h₁ h₂ } -- This instance makes use of the existing AddCommGroup instance to boost performance. instance commRing (I : Ideal R) : CommRing (R ⧸ I) where From bb6f0a357f5060a95d5460f0efaeb6e42b51359b Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 9 Jan 2025 12:02:00 +0000 Subject: [PATCH 097/681] chore: remove `erw`s (#20599) --- .../Algebra/Module/LocalizedModule/Basic.lean | 20 ++++++++++--------- Mathlib/Algebra/MonoidAlgebra/Basic.lean | 4 ++-- .../IsAlgClosed/AlgebraicClosure.lean | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean index b44b61b98fe6a..344dd8108df36 100644 --- a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean +++ b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean @@ -353,7 +353,7 @@ private theorem smul_add_aux (x : T) (p q : LocalizedModule S M) : · rw [mul_mul_mul_comm] -- ring does not work here private theorem smul_zero_aux (x : T) : x • (0 : LocalizedModule S M) = 0 := by - erw [smul_def, smul_zero, zero_mk] + conv => lhs; rw [← zero_mk 1, smul_def, smul_zero, zero_mk] private theorem add_smul_aux (x y : T) (p : LocalizedModule S M) : (x + y) • p = x • p + y • p := by @@ -399,7 +399,8 @@ noncomputable instance isModule' : Module R (LocalizedModule S M) := { Module.compHom (LocalizedModule S M) <| algebraMap R (Localization S) with } theorem smul'_mk (r : R) (s : S) (m : M) : r • mk m s = mk (r • m) s := by - erw [mk_smul_mk r m 1 s, one_mul] + erw [mk_smul_mk r m 1 s] + rw [one_mul] lemma smul_eq_iff_of_mem (r : R) (hr : r ∈ S) (x y : LocalizedModule S M) : @@ -632,13 +633,13 @@ theorem lift'_add (g : M →ₗ[R] M'') (h : ∀ x : S, IsUnit ((algebraMap R (M LocalizedModule.induction_on₂ (by intro a a' b b' - erw [LocalizedModule.lift'_mk, LocalizedModule.lift'_mk, LocalizedModule.lift'_mk] - -- Porting note: We remove `generalize_proofs h1 h2 h3`. This only generalize `h1`. + rw [mk_add_mk, LocalizedModule.lift'_mk, LocalizedModule.lift'_mk, LocalizedModule.lift'_mk] rw [map_add, Module.End_algebraMap_isUnit_inv_apply_eq_iff, smul_add, ← map_smul, ← map_smul, ← map_smul] congr 1 <;> symm - · erw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, mul_smul, ← map_smul] - rfl + · rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff] + simp only [Submonoid.coe_mul, LinearMap.map_smul_of_tower] + rw [mul_smul, Submonoid.smul_def] · dsimp rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, mul_comm, mul_smul, ← map_smul] rfl) @@ -710,8 +711,8 @@ instance localizedModuleIsLocalizedModule : surj' p := p.induction_on fun m t => by refine ⟨⟨m, t⟩, ?_⟩ - erw [LocalizedModule.smul'_mk, LocalizedModule.mkLinearMap_apply, Submonoid.coe_subtype, - LocalizedModule.mk_cancel t] + rw [Submonoid.smul_def, LocalizedModule.smul'_mk, LocalizedModule.mkLinearMap_apply, + ← Submonoid.smul_def, LocalizedModule.mk_cancel t] exists_of_eq eq1 := by simpa only [eq_comm, one_smul] using LocalizedModule.mk_eq.mp eq1 lemma IsLocalizedModule.of_restrictScalars (S : Submonoid R) @@ -848,7 +849,8 @@ theorem iso_symm_apply_aux (m : M') : apply_fun iso S f using LinearEquiv.injective (iso S f) rw [LinearEquiv.apply_symm_apply] simp only [iso_apply, LinearMap.toFun_eq_coe, fromLocalizedModule_mk] - erw [Module.End_algebraMap_isUnit_inv_apply_eq_iff', (surj' _).choose_spec] + rw [fromLocalizedModule'_mk, Module.End_algebraMap_isUnit_inv_apply_eq_iff', ← Submonoid.smul_def, + (surj' _).choose_spec] theorem iso_symm_apply' (m : M') (a : M) (b : S) (eq1 : b • m = f a) : (iso S f).symm m = LocalizedModule.mk a b := diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index a0db55e090c4b..cc2595e20de87 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -323,8 +323,8 @@ def equivariantOfLinearOfComm · intro g r c' _nm _nz w dsimp at * simp only [add_smul, f.map_add, w, add_left_inj, single_eq_algebraMap_mul_of, ← smul_smul] - erw [algebraMap_smul (MonoidAlgebra k G) r, algebraMap_smul (MonoidAlgebra k G) r, f.map_smul, - h g v, of_apply] + rw [algebraMap_smul (MonoidAlgebra k G) r, algebraMap_smul (MonoidAlgebra k G) r, f.map_smul, + of_apply, h g v] variable (h : ∀ (g : G) (v : V), f (single g (1 : k) • v) = single g (1 : k) • f v) diff --git a/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean b/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean index 38ba01a9abd26..90603a7ffdc85 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean @@ -159,8 +159,8 @@ theorem Monics.map_eq_prod {f : Monics k} : f.1.map (algebraMap k (AlgebraicClosure k)) = ∏ i, map (Ideal.Quotient.mk <| maxIdeal k) (X - C (MvPolynomial.X ⟨f, i⟩)) := by ext - -- erw due to `AlgebraicClosure k` not being reducibly defeq to the quotient by `maxIdeal k` - erw [← Ideal.Quotient.mk_comp_algebraMap, ← map_map, ← Polynomial.map_prod, ← sub_eq_zero, + dsimp [AlgebraicClosure] + rw [← Ideal.Quotient.mk_comp_algebraMap, ← map_map, ← Polynomial.map_prod, ← sub_eq_zero, ← coeff_sub, ← Polynomial.map_sub, ← subProdXSubC, coeff_map, Ideal.Quotient.eq_zero_iff_mem] refine le_maxIdeal _ (Ideal.subset_span ⟨⟨f, _⟩, rfl⟩) From ab7742ecee7a124d8eb89d28cbd570252ff517b5 Mon Sep 17 00:00:00 2001 From: Bryan Gin-ge Chen Date: Thu, 9 Jan 2025 12:56:57 +0000 Subject: [PATCH 098/681] ci: basic check on fields in 100.yaml and 1000.yaml (#20078) This PR makes `scripts/yaml_check.py` verify that `100.yaml` and `1000.yaml` only contain fields the webpage expects them to. Otherwise, changes in mathlib breaking the website won't be noticed until they are merged; this has happened several times in the last days. In particular, replace two occurrences of `note` in `1000.yaml` by `comment`. To this end, this PR copies the dataclass constructors which are used in the website script to `scripts/yaml_check.py` (along with a comment asking to keep them in sync). While at it, this PR documents the fields in `100.yaml` as well, and moves the documentation for `1000.yaml` to the copied dataclasses in `yaml_check.py`. In addition, validate that at most one of the fields `decl` and `decls` are passed: the webpage also does this; this avoids late surprises. Co-authored-by: grunweg Co-authored-by: Michael Rothgang --- docs/100.yaml | 7 ++++ docs/1000.yaml | 21 +++++------- scripts/yaml_check.py | 78 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 14 deletions(-) diff --git a/docs/100.yaml b/docs/100.yaml index e7f8eb83b68c0..b752b0e60340f 100644 --- a/docs/100.yaml +++ b/docs/100.yaml @@ -1,3 +1,10 @@ +# This file tracks the formalisation status of theorems from Freek Wiedijk's "Formalizing 100 +# Theorems" list at https://www.cs.ru.nl/~freek/100/ +# +# See yaml_check.py for documentation about the allowed fields in this file. +# The structure of this file is checked by `scripts/yaml_check.py` in this repo +# and by `make_site.py` in the leanprover-community.github.io repo. + 1: title : The Irrationality of the Square Root of 2 decl : irrational_sqrt_two diff --git a/docs/1000.yaml b/docs/1000.yaml index b7f982e4112d6..8261bce58958b 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -2,17 +2,12 @@ # 1000+ theorems project (https://1000-plus.github.io/). # This file and associated infrastructure are work in progress. # -# This file, contains for each theorem in the project, -# - an entry, labelled by its wikidata entry, -# - |title|: a human-readable title -# - (optional) |decl|: if a theorem is formalised in mathlib, the archive or counterexamples, -# the name of the corresponding declaration -# - (optional) |decls|: like |decl|, but a list of declarations -# (if one theorem is split into multiple declarations) -# - (optional) |author|: author(s) of a formalisation -# - (optional) |date|: date of completion of the first formalisation -# - (optional) |url|: for external projects, an URL referring to the result - +# See yaml_check.py for documentation about the allowed fields in this file. +# Note that the field names in this file should match the specification of the +# upstream project, hence should not be changed without due consideration. +# The structure of this file is checked by `scripts/yaml_check.py` in this repo +# and by `make_site.py` in the leanprover-community.github.io repo. +# # Current TODOs/unresolved questions: # - add infrastructure for updating the information upstream when formalisations are added # - perhaps add a wikidata version of the stacks attribute, and generate this file automatically @@ -661,7 +656,7 @@ Q670235: - UniqueFactorizationMonoid - UniqueFactorizationMonoid.factors_unique author: Chris Hughes - note: "it also has a generalized version, by showing that every Euclidean domain is a unique factorization domain, and showing that the integers form a Euclidean domain." + comment: "it also has a generalized version, by showing that every Euclidean domain is a unique factorization domain, and showing that the integers form a Euclidean domain." Q671663: title: Coleman–Mandula theorem @@ -880,7 +875,7 @@ Q853067: - Pell.eq_pell - Pell.exists_of_not_isSquare author: Mario Carneiro (first), Michael Stoll (second) - note: "In `pell.eq_pell`, `d` is defined to be `a*a - 1` for an arbitrary `a > 1`." + comment: "In `pell.eq_pell`, `d` is defined to be `a*a - 1` for an arbitrary `a > 1`." Q856032: title: CAP theorem diff --git a/scripts/yaml_check.py b/scripts/yaml_check.py index 7605122447a6d..bf31ad0b0ecda 100644 --- a/scripts/yaml_check.py +++ b/scripts/yaml_check.py @@ -9,7 +9,8 @@ of theorems. The order of these files is important.) """ -from typing import Dict, Optional, Union, Tuple, List +from typing import Dict, Mapping, Optional, Union, Tuple, List +from dataclasses import dataclass import yaml import json import sys @@ -37,6 +38,55 @@ def print_list(fn: str, pairs: List[Tuple[str, str]]) -> None: for (id, val) in pairs: out.write(f'{id}\n{val.strip()}\n\n') + + +# keep in sync with make_site.py in the leanprover-community.github.io repo +@dataclass +class HundredTheorem: + # this theorem's number in Freek's 100 theorems list + number: str + # a human-readable title + title: str + # if a theorem is formalised in mathlib, the archive or counterexamples, + # the name of the corresponding declaration (optional) + decl: Optional[str] = None + # like |decl|, but a list of declarations (if one theorem is split into multiple declarations) (optional) + decls: Optional[List[str]] = None + # name(s) of the author(s) of this formalization (optional) + author: Optional[str] = None + # Date of the formalization, in the form `YYYY`, `YYYY-MM` or `YYYY-MM-DD` (optional) + date: Optional[str] = None + links: Optional[Mapping[str, str]] = None + note: Optional[str] = None + +# keep in sync with make_site.py in the leanprover-community.github.io repo! +# These field names match the names in the data files of the 1000+ theorems project upstream. +# See https://github.com/1000-plus/1000-plus.github.io/blob/main/README.md#file-format +# for the specification. Compared to the README, +# - this |wikidata| field concatenates the upstream fielcs |wikidata| and |id_suffix| +# - we omit some fields (for now), e.g. the msc classification, and only care about Lean formalisations +@dataclass +class ThousandPlusTheorem: + # Wikidata identifier (the letter Q followed by a string as digits), + # optionally followed by a letter (such as "A", "B" or "X" for disambiguation). + # "Q1008566" and "Q4724004A" are valid identifiers, for example. + wikidata: str + # a human-readable title + title: str + # if a theorem is formalised in mathlib, the archive or counterexamples, + # the name of the corresponding declaration (optional) + decl: Optional[str] = None + # like |decl|, but a list of declarations (if one theorem is split into multiple declarations) (optional) + decls: Optional[List[str]] = None + # name(s) of the author(s) of this formalization (optional) + author: Optional[str] = None + # Date of the formalization, in the form `YYYY`, `YYYY-MM` or `YYYY-MM-DD` (optional) + date: Optional[str] = None + # for external projects, an URL referring to the result + url: Optional[str] = None + # any additional notes or comments + comment: Optional[str] = None + hundred_yaml = sys.argv[1] thousand_yaml = sys.argv[2] overview_yaml = sys.argv[3] @@ -53,7 +103,19 @@ def print_list(fn: str, pairs: List[Tuple[str, str]]) -> None: hundred_decls: List[Tuple[str, str]] = [] +errors = 0 for index, entry in hundred.items(): + # Check that the YAML fits the dataclass used in the website. + try: + _thm = HundredTheorem(index, **entry) + except TypeError as e: + print(f"error: entry for theorem {index} is invalid: {e}") + # Also verify that the |decl| and |decls| fields are not *both* provided. + if _thm.decl and _thm.decls: + print(f"warning: entry for theorem {index} has both a decl and a decls field; " + "please only provide one of these", file=sys.stderr) + errors += 1 + title = entry['title'] if 'decl' in entry: hundred_decls.append((f'{index} {title}', entry['decl'])) @@ -64,6 +126,17 @@ def print_list(fn: str, pairs: List[Tuple[str, str]]) -> None: thousand_decls: List[Tuple[str, str]] = [] for index, entry in thousand.items(): + # Check that the YAML fits the dataclass used in the website. + try: + _thm = ThousandPlusTheorem(index, **entry) + except TypeError as e: + print(f"error: entry for theorem {index} is invalid: {e}") + # Also verify that the |decl| and |decls| fields are not *both* provided. + if _thm.decl and _thm.decls: + print(f"warning: entry for theorem {index} has both a decl and a decls field; " + "please only provide one of these", file=sys.stderr) + errors += 1 + title = entry['title'] if 'decl' in entry: thousand_decls.append((f'{index} {title}', entry['decl'])) @@ -88,3 +161,6 @@ def print_list(fn: str, pairs: List[Tuple[str, str]]) -> None: json.dump(overview_decls, f) with open('undergrad.json', 'w', encoding='utf8') as f: json.dump(undergrad_decls, f) + +if errors: + sys.exit(errors) From dd2e6e36fc644490be7e80c67c2b1b949989f345 Mon Sep 17 00:00:00 2001 From: "Tristan F.-R." Date: Thu, 9 Jan 2025 13:16:03 +0000 Subject: [PATCH 099/681] chore(Combinatorics/SetFamily/AhlswedeZhang): golf simp (#20598) Unfortunately, I'm unsure about which change in lean4 fixed this. Co-authored-by: Tristan F. --- Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean b/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean index aaffbd0028f58..dbb6c16923f52 100644 --- a/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean +++ b/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean @@ -140,10 +140,7 @@ lemma map_truncatedSup [DecidableRel (α := β) (· ≤ ·)] (e : α ≃o β) (s simp_rw [truncatedSup, apply_dite e, map_finset_sup', map_top, this] congr with h simp only [filter_map, Function.comp_def, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, - OrderIso.le_iff_le, id] - rw [sup'_map] - -- TODO: Why can't `simp` use `Finset.sup'_map`? - simp only [sup'_map, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, Function.comp_apply] + OrderIso.le_iff_le, id, sup'_map] lemma truncatedSup_of_isAntichain (hs : IsAntichain (· ≤ ·) (s : Set α)) (ha : a ∈ s) : truncatedSup s a = a := by From b835401242941974a4e26e186a2e76e2032e8709 Mon Sep 17 00:00:00 2001 From: grunweg Date: Thu, 9 Jan 2025 14:40:21 +0000 Subject: [PATCH 100/681] =?UTF-8?q?refactor(lint-style):=20make=20sure=20t?= =?UTF-8?q?o=20read=20the=20nolints=20file=20outside=20of=20t=E2=80=A6=20(?= =?UTF-8?q?#19384)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …he linter implementation This way, we categorically prevent cache invalidation bugs caused by lake replaying unchanged inputs, and thus not reaction to changes in the linter exceptions. For *syntax linters*, such a bug actually occurred in mathlib. (With the current implementation of text-based linters, this issue won't occur; this is merely a defensive change.) Suggested in #19275. Co-authored-by: Jon Eugster --- Mathlib/Tactic/Linter/TextBased.lean | 9 ++++----- scripts/lint-style.lean | 10 +++++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Mathlib/Tactic/Linter/TextBased.lean b/Mathlib/Tactic/Linter/TextBased.lean index aa2c455269b43..c0df2b14e30da 100644 --- a/Mathlib/Tactic/Linter/TextBased.lean +++ b/Mathlib/Tactic/Linter/TextBased.lean @@ -276,14 +276,13 @@ def lintFile (path : FilePath) (exceptions : Array ErrorContext) : Print formatted errors for all unexpected style violations to standard output; correct automatically fixable style errors if configured so. Return the number of files which had new style errors. -`moduleNames` are all the modules to lint, +`nolints` is a list of style exceptions to take into account. +`moduleNames` are the names of all the modules to lint, `mode` specifies what kind of output this script should produce, `fix` configures whether fixable errors should be corrected in-place. -/ -def lintModules (moduleNames : Array Lean.Name) (style : ErrorFormat) (fix : Bool) : IO UInt32 := do - -- Read the `nolints` file, with manual exceptions for the linter. - let nolints ← IO.FS.lines ("scripts" / "nolints-style.txt") +def lintModules (nolints : Array String) (moduleNames : Array Lean.Name) (style : ErrorFormat) + (fix : Bool) : IO UInt32 := do let styleExceptions := parseStyleExceptions nolints - let mut numberErrorFiles : UInt32 := 0 let mut allUnexpectedErrors := #[] for module in moduleNames do diff --git a/scripts/lint-style.lean b/scripts/lint-style.lean index ac60073c999e1..b4b7d93b9f283 100644 --- a/scripts/lint-style.lean +++ b/scripts/lint-style.lean @@ -109,7 +109,15 @@ def lintStyleCli (args : Cli.Parsed) : IO UInt32 := do allModuleNames := allModuleNames.append (← findImports s) -- Note: since "Batteries" is added explicitly to "Mathlib.lean", we remove it here manually. allModuleNames := allModuleNames.erase `Batteries - let mut numberErrors ← lintModules allModuleNames style fix + + -- Read the `nolints` file, with manual exceptions for the linter. + -- NB. We pass these lints to `lintModules` explicitly to prevent cache invalidation bugs: + -- if the text-based linter read the file itself, replaying a cached build of that + -- file could re-use an outdated version of the nolints file. + -- (For syntax linters, such a bug actually occurred in mathlib.) + -- This script is re-run each time, hence is immune to such issues. + let nolints ← IO.FS.lines ("scripts" / "nolints-style.txt") + let mut numberErrors ← lintModules nolints allModuleNames style fix if ← checkInitImports then numberErrors := numberErrors + 1 if !(← allScriptsDocumented) then numberErrors := numberErrors + 1 -- If run with the `--fix` argument, return a zero exit code. From 3dff5d2cec1b740fa02835cb4127421688b85634 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Thu, 9 Jan 2025 15:36:23 +0000 Subject: [PATCH 101/681] feat: extend smoothness category of manifolds with corners to include analytic manifolds (#19696) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that `ContDiff` includes smoothness exponents up to analytic functions, we can do the same for manifolds. The PR renames `SmoothManifoldWithCorners` to `IsManifold`, and includes an additional smoothness exponent (ranging from 0 to infinity and omega). The docstring of `IsManifold` emphasizes that this allows (but does not mandate) corners or boundaries. The file `SmoothManifoldWithCorners` itself is not renamed, to avoid confusing git, and will be renamed in a follow-up PR. The current version of the PR also allows an additional smoothness exponent in the algebraic classes like `ContMDiffMul` or `LieGroup`. For all of these, we add a bunch of instances to deduce low smoothness from high smoothness versions (for example, `LieGroup I 2 G` is found by typeclass inference from `LieGroup I ∞ G`). This change makes it possible to do things with the correct assumptions. For instance, the tangent bundle is a fiber bundle assuming only that the manifold is `C^1` (but we have instances saying that it is `C^∞` if the manifold is `C^∞`, analytic if the manifold is analytic). Normally, I should have properly deprecated everything but instances. TODO in follow-up PRs: * rename `SmoothManifoldWithCorners.lean` to `IsManifold.lean` * deprecate the whole file `Manifold.Analytic.lean` Co-authored-by: Michael Rothgang --- Archive/Hairer.lean | 36 +-- .../InverseFunctionTheorem/ContDiff.lean | 2 +- Mathlib/Analysis/Calculus/SmoothSeries.lean | 4 +- .../Complex/UpperHalfPlane/Manifold.lean | 16 +- Mathlib/Analysis/Convolution.lean | 4 +- .../Distribution/AEEqOfIntegralContDiff.lean | 12 +- .../Analysis/SpecialFunctions/ExpDeriv.lean | 2 +- .../Algebra/LeftInvariantDerivation.lean | 11 +- .../Geometry/Manifold/Algebra/LieGroup.lean | 208 ++++++++----- Mathlib/Geometry/Manifold/Algebra/Monoid.lean | 233 +++++++++------ .../Manifold/Algebra/SmoothFunctions.lean | 204 ++++++------- .../Geometry/Manifold/Algebra/Structures.lean | 62 ++-- .../Geometry/Manifold/AnalyticManifold.lean | 15 +- Mathlib/Geometry/Manifold/BumpFunction.lean | 12 +- Mathlib/Geometry/Manifold/ChartedSpace.lean | 2 +- Mathlib/Geometry/Manifold/Complex.lean | 2 +- .../Geometry/Manifold/ContMDiff/Atlas.lean | 83 +++--- .../Geometry/Manifold/ContMDiff/Basic.lean | 47 +-- Mathlib/Geometry/Manifold/ContMDiff/Defs.lean | 237 ++++++++------- .../Manifold/ContMDiff/NormedSpace.lean | 2 +- .../Geometry/Manifold/ContMDiff/Product.lean | 10 +- .../Geometry/Manifold/ContMDiffMFDeriv.lean | 86 ++++-- Mathlib/Geometry/Manifold/ContMDiffMap.lean | 22 +- .../Geometry/Manifold/DerivationBundle.lean | 46 +-- Mathlib/Geometry/Manifold/Diffeomorph.lean | 46 +-- Mathlib/Geometry/Manifold/Instances/Real.lean | 13 +- .../Geometry/Manifold/Instances/Sphere.lean | 94 +++--- .../Instances/UnitsOfNormedAlgebra.lean | 25 +- .../Manifold/IntegralCurve/Basic.lean | 2 +- .../Manifold/IntegralCurve/ExistUnique.lean | 6 +- .../Manifold/IntegralCurve/UniformTime.lean | 4 +- .../Geometry/Manifold/InteriorBoundary.lean | 4 +- .../Geometry/Manifold/LocalDiffeomorph.lean | 2 +- Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean | 18 +- Mathlib/Geometry/Manifold/MFDeriv/Basic.lean | 37 +-- Mathlib/Geometry/Manifold/MFDeriv/Defs.lean | 18 +- .../Manifold/MFDeriv/NormedSpace.lean | 16 +- .../Geometry/Manifold/MFDeriv/Tangent.lean | 4 +- .../Manifold/MFDeriv/UniqueDifferential.lean | 12 +- .../Geometry/Manifold/PartitionOfUnity.lean | 50 ++-- .../Geometry/Manifold/PoincareConjecture.lean | 8 +- .../Manifold/Sheaf/LocallyRingedSpace.lean | 20 +- Mathlib/Geometry/Manifold/Sheaf/Smooth.lean | 51 ++-- .../Manifold/SmoothManifoldWithCorners.lean | 277 +++++++++++------- .../Geometry/Manifold/VectorBundle/Basic.lean | 254 +++++++++------- .../VectorBundle/FiberwiseLinear.lean | 101 ++++--- .../Geometry/Manifold/VectorBundle/Hom.lean | 46 +-- .../VectorBundle/MDifferentiable.lean | 30 +- .../Manifold/VectorBundle/Pullback.lean | 18 +- .../Manifold/VectorBundle/SmoothSection.lean | 15 +- .../Manifold/VectorBundle/Tangent.lean | 93 ++++-- .../Geometry/Manifold/WhitneyEmbedding.lean | 18 +- docs/overview.yaml | 6 +- scripts/nolints_prime_decls.txt | 4 - 54 files changed, 1483 insertions(+), 1167 deletions(-) diff --git a/Archive/Hairer.lean b/Archive/Hairer.lean index 6abb80f254220..40122c4ed1418 100644 --- a/Archive/Hairer.lean +++ b/Archive/Hairer.lean @@ -35,8 +35,8 @@ variable {𝕜 E F : Type*} [NontriviallyNormedField 𝕜] variable [NormedAddCommGroup E] [NormedSpace 𝕜 E] [NormedAddCommGroup F] [NormedSpace 𝕜 F] variable (𝕜 E F) in -/-- The set of smooth functions supported in a set `s`, as a submodule of the space of functions. -/ -def SmoothSupportedOn (n : ℕ∞) (s : Set E) : Submodule 𝕜 (E → F) where +/-- The set of `C^n` functions supported in a set `s`, as a submodule of the space of functions. -/ +def ContDiffSupportedOn (n : ℕ∞) (s : Set E) : Submodule 𝕜 (E → F) where carrier := { f : E → F | tsupport f ⊆ s ∧ ContDiff 𝕜 n f } add_mem' hf hg := ⟨tsupport_add.trans <| union_subset hf.1 hg.1, hf.2.add hg.2⟩ zero_mem' := @@ -44,49 +44,49 @@ def SmoothSupportedOn (n : ℕ∞) (s : Set E) : Submodule 𝕜 (E → F) where smul_mem' r f hf := ⟨(closure_mono <| support_const_smul_subset r f).trans hf.1, contDiff_const.smul hf.2⟩ -namespace SmoothSupportedOn +namespace ContDiffSupportedOn variable {n : ℕ∞} {s : Set E} -instance : FunLike (SmoothSupportedOn 𝕜 E F n s) E F where +instance : FunLike (ContDiffSupportedOn 𝕜 E F n s) E F where coe := Subtype.val coe_injective' := Subtype.coe_injective @[simp] -lemma coe_mk (f : E → F) (h) : (⟨f, h⟩ : SmoothSupportedOn 𝕜 E F n s) = f := rfl +lemma coe_mk (f : E → F) (h) : (⟨f, h⟩ : ContDiffSupportedOn 𝕜 E F n s) = f := rfl -lemma tsupport_subset (f : SmoothSupportedOn 𝕜 E F n s) : tsupport f ⊆ s := f.2.1 +lemma tsupport_subset (f : ContDiffSupportedOn 𝕜 E F n s) : tsupport f ⊆ s := f.2.1 -lemma support_subset (f : SmoothSupportedOn 𝕜 E F n s) : +lemma support_subset (f : ContDiffSupportedOn 𝕜 E F n s) : support f ⊆ s := subset_tsupport _ |>.trans (tsupport_subset f) -lemma contDiff (f : SmoothSupportedOn 𝕜 E F n s) : +lemma contDiff (f : ContDiffSupportedOn 𝕜 E F n s) : ContDiff 𝕜 n f := f.2.2 -theorem continuous (f : SmoothSupportedOn 𝕜 E F n s) : Continuous f := - (SmoothSupportedOn.contDiff _).continuous +theorem continuous (f : ContDiffSupportedOn 𝕜 E F n s) : Continuous f := + (ContDiffSupportedOn.contDiff _).continuous -lemma hasCompactSupport [ProperSpace E] (f : SmoothSupportedOn 𝕜 E F n (closedBall 0 1)) : +lemma hasCompactSupport [ProperSpace E] (f : ContDiffSupportedOn 𝕜 E F n (closedBall 0 1)) : HasCompactSupport f := HasCompactSupport.of_support_subset_isCompact (isCompact_closedBall 0 1) (support_subset f) theorem integrable_eval_mul (p : MvPolynomial ι ℝ) - (f : SmoothSupportedOn ℝ (EuclideanSpace ℝ ι) ℝ ⊤ (closedBall 0 1)) : + (f : ContDiffSupportedOn ℝ (EuclideanSpace ℝ ι) ℝ ⊤ (closedBall 0 1)) : Integrable fun (x : EuclideanSpace ℝ ι) ↦ eval x p * f x := - (p.continuous_eval.mul (SmoothSupportedOn.contDiff f).continuous).integrable_of_hasCompactSupport - (hasCompactSupport f).mul_left + p.continuous_eval.mul (ContDiffSupportedOn.contDiff f).continuous + |>.integrable_of_hasCompactSupport (hasCompactSupport f).mul_left -end SmoothSupportedOn +end ContDiffSupportedOn end normed -open SmoothSupportedOn +open ContDiffSupportedOn variable (ι) /-- Interpreting a multivariate polynomial as an element of the dual of smooth functions supported in the unit ball, via integration against Lebesgue measure. -/ def L : MvPolynomial ι ℝ →ₗ[ℝ] - Module.Dual ℝ (SmoothSupportedOn ℝ (EuclideanSpace ℝ ι) ℝ ⊤ (closedBall 0 1)) := - have int := SmoothSupportedOn.integrable_eval_mul (ι := ι) + Module.Dual ℝ (ContDiffSupportedOn ℝ (EuclideanSpace ℝ ι) ℝ ⊤ (closedBall 0 1)) := + have int := ContDiffSupportedOn.integrable_eval_mul (ι := ι) .mk₂ ℝ (fun p f ↦ ∫ x : EuclideanSpace ℝ ι, eval x p • f x) (fun p₁ p₂ f ↦ by simp [add_mul, integral_add (int p₁ f) (int p₂ f)]) (fun r p f ↦ by simp [mul_assoc, integral_mul_left]) diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean index 49b5c3a3c929c..f52e49644ceda 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean @@ -8,7 +8,7 @@ import Mathlib.Analysis.Calculus.ContDiff.RCLike import Mathlib.Analysis.Calculus.InverseFunctionTheorem.FDeriv /-! -# Inverse function theorem, smooth case +# Inverse function theorem, `C^r` case In this file we specialize the inverse function theorem to `C^r`-smooth functions. -/ diff --git a/Mathlib/Analysis/Calculus/SmoothSeries.lean b/Mathlib/Analysis/Calculus/SmoothSeries.lean index 073a4b2192939..734dd58db15a3 100644 --- a/Mathlib/Analysis/Calculus/SmoothSeries.lean +++ b/Mathlib/Analysis/Calculus/SmoothSeries.lean @@ -16,7 +16,7 @@ function in the series is and additionally suitable uniform summable bounds are More specifically, * `differentiable_tsum` ensures that a series of differentiable functions is differentiable. -* `contDiff_tsum` ensures that a series of smooth functions is smooth. +* `contDiff_tsum` ensures that a series of `C^n` functions is `C^n`. We also give versions of these statements which are localized to a set. -/ @@ -183,7 +183,7 @@ theorem deriv_tsum (hu : Summable u) (hg : ∀ n, Differentiable 𝕜 (g n)) /-! ### Higher smoothness -/ -/-- Consider a series of smooth functions, with summable uniform bounds on the successive +/-- Consider a series of `C^n` functions, with summable uniform bounds on the successive derivatives. Then the iterated derivative of the sum is the sum of the iterated derivative. -/ theorem iteratedFDeriv_tsum (hf : ∀ i, ContDiff 𝕜 N (f i)) (hv : ∀ k : ℕ, (k : ℕ∞) ≤ N → Summable (v k)) diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean index 9529dbcb764f2..b6440a07da940 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean @@ -15,27 +15,27 @@ In this file we define the complex manifold structure on the upper half-plane. open Filter -open scoped Manifold +open scoped Manifold ContDiff namespace UpperHalfPlane noncomputable instance : ChartedSpace ℂ ℍ := UpperHalfPlane.isOpenEmbedding_coe.singletonChartedSpace -instance : SmoothManifoldWithCorners 𝓘(ℂ) ℍ := - UpperHalfPlane.isOpenEmbedding_coe.singleton_smoothManifoldWithCorners +instance : IsManifold 𝓘(ℂ) ω ℍ := + UpperHalfPlane.isOpenEmbedding_coe.isManifold_singleton -/-- The inclusion map `ℍ → ℂ` is a smooth map of manifolds. -/ -theorem contMDiff_coe : ContMDiff 𝓘(ℂ) 𝓘(ℂ) ⊤ ((↑) : ℍ → ℂ) := fun _ => contMDiffAt_extChartAt +/-- The inclusion map `ℍ → ℂ` is an analytic map of manifolds. -/ +theorem contMDiff_coe : ContMDiff 𝓘(ℂ) 𝓘(ℂ) ω ((↑) : ℍ → ℂ) := fun _ => contMDiffAt_extChartAt @[deprecated (since := "2024-11-20")] alias smooth_coe := contMDiff_coe /-- The inclusion map `ℍ → ℂ` is a differentiable map of manifolds. -/ theorem mdifferentiable_coe : MDifferentiable 𝓘(ℂ) 𝓘(ℂ) ((↑) : ℍ → ℂ) := - contMDiff_coe.mdifferentiable (by simp) + contMDiff_coe.mdifferentiable le_top lemma contMDiffAt_ofComplex {z : ℂ} (hz : 0 < z.im) : - ContMDiffAt 𝓘(ℂ) 𝓘(ℂ) ⊤ ofComplex z := by + ContMDiffAt 𝓘(ℂ) 𝓘(ℂ) ω ofComplex z := by rw [contMDiffAt_iff] constructor · -- continuity at z @@ -54,7 +54,7 @@ lemma contMDiffAt_ofComplex {z : ℂ} (hz : 0 < z.im) : lemma mdifferentiableAt_ofComplex {z : ℂ} (hz : 0 < z.im) : MDifferentiableAt 𝓘(ℂ) 𝓘(ℂ) ofComplex z := - (contMDiffAt_ofComplex hz).mdifferentiableAt (by simp) + (contMDiffAt_ofComplex hz).mdifferentiableAt le_top lemma mdifferentiableAt_iff {f : ℍ → ℂ} {τ : ℍ} : MDifferentiableAt 𝓘(ℂ) 𝓘(ℂ) f τ ↔ DifferentiableAt ℂ (f ∘ ofComplex) ↑τ := by diff --git a/Mathlib/Analysis/Convolution.lean b/Mathlib/Analysis/Convolution.lean index 9834adcc2007f..4c7771cf3612f 100644 --- a/Mathlib/Analysis/Convolution.lean +++ b/Mathlib/Analysis/Convolution.lean @@ -1274,7 +1274,7 @@ theorem contDiffOn_convolution_right_with_param {f : G → E} {n : ℕ∞} (L : /-- The convolution `f * g` is `C^n` when `f` is locally integrable and `g` is `C^n` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`), -given in terms of composition with an additional smooth function. -/ +given in terms of composition with an additional `C^n` function. -/ theorem contDiffOn_convolution_right_with_param_comp {n : ℕ∞} (L : E →L[𝕜] E' →L[𝕜] F) {s : Set P} {v : P → G} (hv : ContDiffOn 𝕜 n v s) {f : G → E} {g : P → G → E'} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) (hgs : ∀ p, ∀ x, p ∈ s → x ∉ k → g p x = 0) (hf : LocallyIntegrable f μ) @@ -1296,7 +1296,7 @@ theorem contDiffOn_convolution_left_with_param [μ.IsAddLeftInvariant] [μ.IsNeg /-- The convolution `g * f` is `C^n` when `f` is locally integrable and `g` is `C^n` and compactly supported. Version where `g` depends on an additional parameter in an open subset `s` of a parameter space `P` (and the compact support `k` is independent of the parameter in `s`), -given in terms of composition with additional smooth functions. -/ +given in terms of composition with additional `C^n` functions. -/ theorem contDiffOn_convolution_left_with_param_comp [μ.IsAddLeftInvariant] [μ.IsNegInvariant] (L : E' →L[𝕜] E →L[𝕜] F) {s : Set P} {n : ℕ∞} {v : P → G} (hv : ContDiffOn 𝕜 n v s) {f : G → E} {g : P → G → E'} {k : Set G} (hs : IsOpen s) (hk : IsCompact k) diff --git a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean index 8aa816c388f41..fb149455f547a 100644 --- a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean +++ b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean @@ -32,7 +32,7 @@ variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimension section Manifold variable {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I ∞ M] [MeasurableSpace M] [BorelSpace M] [T2Space M] {f f' : M → F} {μ : Measure M} @@ -40,7 +40,7 @@ variable {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) when multiplied by any smooth compactly supported function, then `f` vanishes almost everywhere. -/ theorem ae_eq_zero_of_integral_smooth_smul_eq_zero [SigmaCompactSpace M] (hf : LocallyIntegrable f μ) - (h : ∀ g : M → ℝ, ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = 0) : + (h : ∀ g : M → ℝ, ContMDiff I 𝓘(ℝ) ∞ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, f x = 0 := by -- record topological properties of `M` have := I.locallyCompactSpace @@ -60,7 +60,7 @@ theorem ae_eq_zero_of_integral_smooth_smul_eq_zero [SigmaCompactSpace M] let v : ℕ → Set M := fun n ↦ thickening (u n) s obtain ⟨K, K_compact, vK⟩ : ∃ K, IsCompact K ∧ ∀ n, v n ⊆ K := ⟨_, hδ, fun n ↦ thickening_subset_cthickening_of_le (u_pos n).2.le _⟩ - have : ∀ n, ∃ (g : M → ℝ), support g = v n ∧ ContMDiff I 𝓘(ℝ) ⊤ g ∧ Set.range g ⊆ Set.Icc 0 1 + have : ∀ n, ∃ (g : M → ℝ), support g = v n ∧ ContMDiff I 𝓘(ℝ) ∞ g ∧ Set.range g ⊆ Set.Icc 0 1 ∧ ∀ x ∈ s, g x = 1 := by intro n rcases exists_msmooth_support_eq_eq_one_iff I isOpen_thickening hs.isClosed @@ -121,7 +121,7 @@ instance (U : Opens M) : BorelSpace U := inferInstanceAs (BorelSpace (U : Set M) nonrec theorem IsOpen.ae_eq_zero_of_integral_smooth_smul_eq_zero' {U : Set M} (hU : IsOpen U) (hSig : IsSigmaCompact U) (hf : LocallyIntegrableOn f U μ) (h : ∀ g : M → ℝ, - ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : + ContMDiff I 𝓘(ℝ) ∞ g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, x ∈ U → f x = 0 := by have meas_U := hU.measurableSet rw [← ae_restrict_iff' meas_U, ae_restrict_iff_subtype meas_U] @@ -146,7 +146,7 @@ variable [SigmaCompactSpace M] theorem IsOpen.ae_eq_zero_of_integral_smooth_smul_eq_zero {U : Set M} (hU : IsOpen U) (hf : LocallyIntegrableOn f U μ) (h : ∀ g : M → ℝ, - ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : + ContMDiff I 𝓘(ℝ) ∞ g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, x ∈ U → f x = 0 := haveI := I.locallyCompactSpace haveI := ChartedSpace.locallyCompactSpace H M @@ -160,7 +160,7 @@ theorem IsOpen.ae_eq_zero_of_integral_smooth_smul_eq_zero {U : Set M} (hU : IsOp when multiplied by any smooth compactly supported function, then they coincide almost everywhere. -/ theorem ae_eq_of_integral_smooth_smul_eq (hf : LocallyIntegrable f μ) (hf' : LocallyIntegrable f' μ) (h : ∀ (g : M → ℝ), - ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = ∫ x, g x • f' x ∂μ) : + ContMDiff I 𝓘(ℝ) ∞ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = ∫ x, g x • f' x ∂μ) : ∀ᵐ x ∂μ, f x = f' x := by have : ∀ᵐ x ∂μ, (f - f') x = 0 := by apply ae_eq_zero_of_integral_smooth_smul_eq_zero I (hf.sub hf') diff --git a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean index accf98401aed5..9fb53baf40655 100644 --- a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean @@ -12,7 +12,7 @@ import Mathlib.Analysis.SpecialFunctions.Exponential /-! # Complex and real exponential -In this file we prove that `Complex.exp` and `Real.exp` are infinitely smooth functions. +In this file we prove that `Complex.exp` and `Real.exp` are analytic functions. ## Tags diff --git a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean index 9e2358ae486b1..5d0c59e57bf63 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean @@ -22,14 +22,11 @@ implementing one of the possible definitions of the Lie algebra attached to a Li noncomputable section -open scoped LieGroup Manifold Derivation -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped LieGroup Manifold Derivation ContDiff -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) (G : Type*) - [TopologicalSpace G] [ChartedSpace H G] [Monoid G] [SmoothMul I G] (g h : G) + [TopologicalSpace G] [ChartedSpace H G] [Monoid G] [ContMDiffMul I ∞ G] (g h : G) -- Generate trivial has_sizeof instance. It prevents weird type class inference timeout problems -- Porting note (https://github.com/leanprover-community/mathlib4/issues/12096): removed @[nolint instance_priority], linter not ported yet @@ -227,7 +224,7 @@ instance : Bracket (LeftInvariantDerivation I G) (LeftInvariantDerivation I G) w have hY := Derivation.congr_fun (left_invariant' g Y) (X f) rw [hfdifferential_apply, fdifferential_apply, Derivation.evalAt_apply] at hX hY ⊢ rw [comp_L] at hX hY - rw [Derivation.commutator_apply, SmoothMap.coe_sub, Pi.sub_apply, coe_derivation] + rw [Derivation.commutator_apply, ContMDiffMap.coe_sub, Pi.sub_apply, coe_derivation] rw [coe_derivation] at hX hY ⊢ rw [hX, hY] rfl⟩ diff --git a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean index 2997b5c92169b..c2e0fef32f7a8 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean @@ -8,9 +8,9 @@ import Mathlib.Geometry.Manifold.Algebra.Monoid /-! # Lie groups -A Lie group is a group that is also a smooth manifold, in which the group operations of -multiplication and inversion are smooth maps. Smoothness of the group multiplication means that -multiplication is a smooth mapping of the product manifold `G` × `G` into `G`. +A Lie group is a group that is also a `C^n` manifold, in which the group operations of +multiplication and inversion are `C^n` maps. Regularity of the group multiplication means that +multiplication is a `C^n` mapping of the product manifold `G` × `G` into `G`. Note that, since a manifold here is not second-countable and Hausdorff a Lie group here is not guaranteed to be second-countable (even though it can be proved it is Hausdorff). Note also that Lie @@ -20,18 +20,18 @@ groups here are not necessarily finite dimensional. * `LieAddGroup I G` : a Lie additive group where `G` is a manifold on the model with corners `I`. * `LieGroup I G` : a Lie multiplicative group where `G` is a manifold on the model with corners `I`. -* `SmoothInv₀`: typeclass for smooth manifolds with `0` and `Inv` such that inversion is a smooth +* `ContMDiffInv₀`: typeclass for `C^n` manifolds with `0` and `Inv` such that inversion is `C^n` map at each non-zero point. This includes complete normed fields and (multiplicative) Lie groups. ## Main results * `ContMDiff.inv`, `ContMDiff.div` and variants: point-wise inversion and division of maps `M → G` - is smooth -* `ContMDiff.inv₀` and variants: if `SmoothInv₀ N`, point-wise inversion of smooth maps `f : M → N` - is smooth at all points at which `f` doesn't vanish. -* `ContMDiff.div₀` and variants: if also `SmoothMul N` (i.e., `N` is a Lie group except possibly - for smoothness of inversion at `0`), similar results hold for point-wise division. -* `normedSpaceLieAddGroup` : a normed vector space over a nontrivially normed field + is `C^n`. +* `ContMDiff.inv₀` and variants: if `ContMDiffInv₀ I n N`, point-wise inversion of `C^n` + maps `f : M → N` is `C^n` at all points at which `f` doesn't vanish. +* `ContMDiff.div₀` and variants: if also `ContMDiffMul I n N` (i.e., `N` is a Lie group except + possibly for smoothness of inversion at `0`), similar results hold for point-wise division. +* `instNormedSpaceLieAddGroup` : a normed vector space over a nontrivially normed field is an additive Lie group. * `Instances/UnitsOfNormedAlgebra` shows that the group of units of a complete normed `𝕜`-algebra is a multiplicative Lie group. @@ -49,73 +49,100 @@ so the definition does not apply. Hence the definition should be more general, a noncomputable section -open scoped Manifold +open scoped Manifold ContDiff -- See note [Design choices about smooth algebraic structures] -/-- An additive Lie group is a group and a smooth manifold at the same time in which -the addition and negation operations are smooth. -/ +/-- An additive Lie group is a group and a `C^n` manifold at the same time in which +the addition and negation operations are `C^n`. -/ class LieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) - [AddGroup G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothAdd I G : Prop where + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) + (n : WithTop ℕ∞) (G : Type*) + [AddGroup G] [TopologicalSpace G] [ChartedSpace H G] extends ContMDiffAdd I n G : Prop where /-- Negation is smooth in an additive Lie group. -/ - smooth_neg : ContMDiff I I ⊤ fun a : G => -a + contMDiff_neg : ContMDiff I I n fun a : G => -a -- See note [Design choices about smooth algebraic structures] -/-- A (multiplicative) Lie group is a group and a smooth manifold at the same time in which -the multiplication and inverse operations are smooth. -/ +/-- A (multiplicative) Lie group is a group and a `C^n` manifold at the same time in which +the multiplication and inverse operations are `C^n`. -/ @[to_additive] class LieGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) - [Group G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothMul I G : Prop where + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) + (n : WithTop ℕ∞) (G : Type*) + [Group G] [TopologicalSpace G] [ChartedSpace H G] extends ContMDiffMul I n G : Prop where /-- Inversion is smooth in a Lie group. -/ - smooth_inv : ContMDiff I I ⊤ fun a : G => a⁻¹ + contMDiff_inv : ContMDiff I I n fun a : G => a⁻¹ /-! ### Smoothness of inversion, negation, division and subtraction - Let `f : M → G` be a `C^n` or smooth functions into a Lie group, then `f` is point-wise + Let `f : M → G` be a `C^n` function into a Lie group, then `f` is point-wise invertible with smooth inverse `f`. If `f` and `g` are two such functions, the quotient - `f / g` (i.e., the point-wise product of `f` and the point-wise inverse of `g`) is also smooth. -/ + `f / g` (i.e., the point-wise product of `f` and the point-wise inverse of `g`) is also `C^n`. -/ section PointwiseDivision variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} - [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} - [TopologicalSpace G] [ChartedSpace H G] [Group G] [LieGroup I G] {E' : Type*} + [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {n : WithTop ℕ∞} {G : Type*} + [TopologicalSpace G] [ChartedSpace H G] [Group G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] - {n : ℕ∞} + +@[to_additive] +protected theorem LieGroup.of_le {m n : WithTop ℕ∞} (hmn : m ≤ n) + [h : LieGroup I n G] : LieGroup I m G := by + have : ContMDiffMul I m G := ContMDiffMul.of_le hmn + exact ⟨h.contMDiff_inv.of_le hmn⟩ + +@[to_additive] +instance {a : WithTop ℕ∞} [LieGroup I ∞ G] [h : ENat.LEInfty a] : LieGroup I a G := + LieGroup.of_le h.out + +@[to_additive] +instance {a : WithTop ℕ∞} [LieGroup I ω G] : LieGroup I a G := + LieGroup.of_le le_top + +@[to_additive] +instance [TopologicalGroup G] : LieGroup I 0 G := by + constructor + rw [contMDiff_zero_iff] + exact continuous_inv + +@[to_additive] +instance [LieGroup I 2 G] : LieGroup I 1 G := + LieGroup.of_le one_le_two + +variable [LieGroup I n G] section -variable (I) +variable (I n) -/-- In a Lie group, inversion is a smooth map. -/ +/-- In a Lie group, inversion is `C^n`. -/ @[to_additive "In an additive Lie group, inversion is a smooth map."] -theorem contMDiff_inv : ContMDiff I I ⊤ fun x : G => x⁻¹ := - LieGroup.smooth_inv +theorem contMDiff_inv : ContMDiff I I n fun x : G => x⁻¹ := + LieGroup.contMDiff_inv @[deprecated (since := "2024-11-21")] alias smooth_inv := contMDiff_inv @[deprecated (since := "2024-11-21")] alias smooth_neg := contMDiff_neg -include I in +include I n in /-- A Lie group is a topological group. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]. -/ @[to_additive "An additive Lie group is an additive topological group. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]."] theorem topologicalGroup_of_lieGroup : TopologicalGroup G := - { continuousMul_of_smooth I with continuous_inv := (contMDiff_inv I).continuous } + { continuousMul_of_contMDiffMul I n with continuous_inv := (contMDiff_inv I n).continuous } end @[to_additive] theorem ContMDiffWithinAt.inv {f : M → G} {s : Set M} {x₀ : M} (hf : ContMDiffWithinAt I' I n f s x₀) : ContMDiffWithinAt I' I n (fun x => (f x)⁻¹) s x₀ := - ((contMDiff_inv I).of_le le_top).contMDiffAt.contMDiffWithinAt.comp x₀ hf <| Set.mapsTo_univ _ _ + (contMDiff_inv I n).contMDiffAt.contMDiffWithinAt.comp x₀ hf <| Set.mapsTo_univ _ _ @[to_additive] theorem ContMDiffAt.inv {f : M → G} {x₀ : M} (hf : ContMDiffAt I' I n f x₀) : ContMDiffAt I' I n (fun x => (f x)⁻¹) x₀ := - ((contMDiff_inv I).of_le le_top).contMDiffAt.comp x₀ hf + (contMDiff_inv I n).contMDiffAt.comp x₀ hf @[to_additive] theorem ContMDiffOn.inv {f : M → G} {s : Set M} (hf : ContMDiffOn I' I n f s) : @@ -172,64 +199,98 @@ section Product -- Instance of product group @[to_additive] -instance {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} +instance {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} + {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} - [TopologicalSpace G] [ChartedSpace H G] [Group G] [LieGroup I G] {E' : Type*} + [TopologicalSpace G] [ChartedSpace H G] [Group G] [LieGroup I n G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {G' : Type*} [TopologicalSpace G'] [ChartedSpace H' G'] - [Group G'] [LieGroup I' G'] : LieGroup (I.prod I') (G × G') := - { SmoothMul.prod _ _ _ _ with smooth_inv := contMDiff_fst.inv.prod_mk contMDiff_snd.inv } + [Group G'] [LieGroup I' n G'] : LieGroup (I.prod I') n (G × G') := + { ContMDiffMul.prod _ _ _ _ with contMDiff_inv := contMDiff_fst.inv.prod_mk contMDiff_snd.inv } end Product /-! ### Normed spaces are Lie groups -/ -instance normedSpaceLieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} - [NormedAddCommGroup E] [NormedSpace 𝕜 E] : LieAddGroup 𝓘(𝕜, E) E where - smooth_neg := contDiff_neg.contMDiff +instance instNormedSpaceLieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] : LieAddGroup 𝓘(𝕜, E) n E where + contMDiff_neg := contDiff_neg.contMDiff -/-! ## Smooth manifolds with smooth inversion away from zero +/-! ## `C^n` manifolds with `C^n` inversion away from zero -Typeclass for smooth manifolds with `0` and `Inv` such that inversion is smooth at all non-zero +Typeclass for `C^n` manifolds with `0` and `Inv` such that inversion is `C^n` at all non-zero points. (This includes multiplicative Lie groups, but also complete normed semifields.) -Point-wise inversion is smooth when the function/denominator is non-zero. -/ -section SmoothInv₀ +Point-wise inversion is `C^n` when the function/denominator is non-zero. -/ +section ContMDiffInv₀ -- See note [Design choices about smooth algebraic structures] -/-- A smooth manifold with `0` and `Inv` such that `fun x ↦ x⁻¹` is smooth at all nonzero points. +/-- A `C^n` manifold with `0` and `Inv` such that `fun x ↦ x⁻¹` is `C^n` at all nonzero points. Any complete normed (semi)field has this property. -/ -class SmoothInv₀ {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) +class ContMDiffInv₀ {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) + (n : WithTop ℕ∞) (G : Type*) [Inv G] [Zero G] [TopologicalSpace G] [ChartedSpace H G] : Prop where - /-- Inversion is smooth away from `0`. -/ - smoothAt_inv₀ : ∀ ⦃x : G⦄, x ≠ 0 → ContMDiffAt I I ⊤ (fun y ↦ y⁻¹) x + /-- Inversion is `C^n` away from `0`. -/ + contMDiffAt_inv₀ : ∀ ⦃x : G⦄, x ≠ 0 → ContMDiffAt I I n (fun y ↦ y⁻¹) x + +@[deprecated (since := "2025-01-09")] alias SmoothInv₀ := ContMDiffInv₀ -instance {𝕜 : Type*} [NontriviallyNormedField 𝕜] : SmoothInv₀ 𝓘(𝕜) 𝕜 where - smoothAt_inv₀ x hx := by - change ContMDiffAt 𝓘(𝕜) 𝓘(𝕜) ⊤ Inv.inv x +instance {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} : ContMDiffInv₀ 𝓘(𝕜) n 𝕜 where + contMDiffAt_inv₀ x hx := by + change ContMDiffAt 𝓘(𝕜) 𝓘(𝕜) n Inv.inv x rw [contMDiffAt_iff_contDiffAt] exact contDiffAt_inv 𝕜 hx -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} + {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} - [TopologicalSpace G] [ChartedSpace H G] [Inv G] [Zero G] [SmoothInv₀ I G] {E' : Type*} + [TopologicalSpace G] [ChartedSpace H G] [Inv G] [Zero G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] - {n : ℕ∞} {f : M → G} + {f : M → G} + +protected theorem ContMDiffInv₀.of_le {m n : WithTop ℕ∞} (hmn : m ≤ n) + [h : ContMDiffInv₀ I n G] : ContMDiffInv₀ I m G := by + exact ⟨fun x hx ↦ (h.contMDiffAt_inv₀ hx).of_le hmn⟩ + +instance {a : WithTop ℕ∞} [ContMDiffInv₀ I ∞ G] [h : ENat.LEInfty a] : ContMDiffInv₀ I a G := + ContMDiffInv₀.of_le h.out + +instance {a : WithTop ℕ∞} [ContMDiffInv₀ I ω G] : ContMDiffInv₀ I a G := + ContMDiffInv₀.of_le le_top -theorem contMDiffAt_inv₀ {x : G} (hx : x ≠ 0) : ContMDiffAt I I ⊤ (fun y ↦ y⁻¹) x := - SmoothInv₀.smoothAt_inv₀ hx +instance [HasContinuousInv₀ G] : ContMDiffInv₀ I 0 G := by + have : T1Space G := I.t1Space G + constructor + have A : ContMDiffOn I I 0 (fun (x : G) ↦ x⁻¹) {0}ᶜ := by + rw [contMDiffOn_zero_iff] + exact continuousOn_inv₀ + intro x hx + have : ContMDiffWithinAt I I 0 (fun (x : G) ↦ x⁻¹) {0}ᶜ x := A x hx + apply ContMDiffWithinAt.contMDiffAt this + exact IsOpen.mem_nhds isOpen_compl_singleton hx + +instance [ContMDiffInv₀ I 2 G] : ContMDiffInv₀ I 1 G := + ContMDiffInv₀.of_le one_le_two + +variable [ContMDiffInv₀ I n G] + +theorem contMDiffAt_inv₀ {x : G} (hx : x ≠ 0) : ContMDiffAt I I n (fun y ↦ y⁻¹) x := + ContMDiffInv₀.contMDiffAt_inv₀ hx @[deprecated (since := "2024-11-21")] alias smoothAt_inv₀ := contMDiffAt_inv₀ -include I in -/-- In a manifold with smooth inverse away from `0`, the inverse is continuous away from `0`. +include I n in +/-- In a manifold with `C^n` inverse away from `0`, the inverse is continuous away from `0`. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]. -/ -theorem hasContinuousInv₀_of_hasSmoothInv₀ : HasContinuousInv₀ G := - { continuousAt_inv₀ := fun _ hx ↦ (contMDiffAt_inv₀ (I := I) hx).continuousAt } +theorem hasContinuousInv₀_of_hasContMDiffInv₀ : HasContinuousInv₀ G := + { continuousAt_inv₀ := fun _ hx ↦ (contMDiffAt_inv₀ (I := I) (n := n) hx).continuousAt } -theorem contMDiffOn_inv₀ : ContMDiffOn I I ⊤ (Inv.inv : G → G) {0}ᶜ := fun _x hx => +@[deprecated (since := "2025-01-09")] +alias hasContinuousInv₀_of_hasSmoothInv₀ := hasContinuousInv₀_of_hasContMDiffInv₀ + +theorem contMDiffOn_inv₀ : ContMDiffOn I I n (Inv.inv : G → G) {0}ᶜ := fun _x hx => (contMDiffAt_inv₀ hx).contMDiffWithinAt @[deprecated (since := "2024-11-21")] alias smoothOn_inv₀ := contMDiffOn_inv₀ @@ -239,11 +300,11 @@ variable {s : Set M} {a : M} theorem ContMDiffWithinAt.inv₀ (hf : ContMDiffWithinAt I' I n f s a) (ha : f a ≠ 0) : ContMDiffWithinAt I' I n (fun x => (f x)⁻¹) s a := - ((contMDiffAt_inv₀ ha).of_le le_top).comp_contMDiffWithinAt a hf + (contMDiffAt_inv₀ ha).comp_contMDiffWithinAt a hf theorem ContMDiffAt.inv₀ (hf : ContMDiffAt I' I n f a) (ha : f a ≠ 0) : ContMDiffAt I' I n (fun x ↦ (f x)⁻¹) a := - ((contMDiffAt_inv₀ ha).of_le le_top).comp a hf + (contMDiffAt_inv₀ ha).comp a hf theorem ContMDiff.inv₀ (hf : ContMDiff I' I n f) (h0 : ∀ x, f x ≠ 0) : ContMDiff I' I n (fun x ↦ (f x)⁻¹) := @@ -258,21 +319,24 @@ theorem ContMDiffOn.inv₀ (hf : ContMDiffOn I' I n f s) (h0 : ∀ x ∈ s, f x @[deprecated (since := "2024-11-21")] alias SmoothOn.inv₀ := ContMDiffOn.inv₀ @[deprecated (since := "2024-11-21")] alias Smooth.inv₀ := ContMDiff.inv₀ -end SmoothInv₀ +end ContMDiffInv₀ -/-! ### Point-wise division of smooth functions +/-! ### Point-wise division of `C^n` functions -If `[SmoothMul I N]` and `[SmoothInv₀ I N]`, point-wise division of smooth functions `f : M → N` -is smooth whenever the denominator is non-zero. (This includes `N` being a completely normed field.) +If `[ContMDiffMul I n N]` and `[ContMDiffInv₀ I n N]`, point-wise division of `C^n` +functions `f : M → N` is `C^n` whenever the denominator is non-zero. +(This includes `N` being a completely normed field.) -/ section Div -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} +{H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} - [TopologicalSpace G] [ChartedSpace H G] [GroupWithZero G] [SmoothInv₀ I G] [SmoothMul I G] + [TopologicalSpace G] [ChartedSpace H G] [GroupWithZero G] [ContMDiffInv₀ I n G] + [ContMDiffMul I n G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] - {f g : M → G} {s : Set M} {a : M} {n : ℕ∞} + {f g : M → G} {s : Set M} {a : M} theorem ContMDiffWithinAt.div₀ (hf : ContMDiffWithinAt I' I n f s a) (hg : ContMDiffWithinAt I' I n g s a) (h₀ : g a ≠ 0) : diff --git a/Mathlib/Geometry/Manifold/Algebra/Monoid.lean b/Mathlib/Geometry/Manifold/Algebra/Monoid.lean index dba923efb9653..1b93cf8ee9214 100644 --- a/Mathlib/Geometry/Manifold/Algebra/Monoid.lean +++ b/Mathlib/Geometry/Manifold/Algebra/Monoid.lean @@ -7,97 +7,125 @@ import Mathlib.Geometry.Manifold.ContMDiffMap import Mathlib.Geometry.Manifold.MFDeriv.Basic /-! -# Smooth monoid -A smooth monoid is a monoid that is also a smooth manifold, in which multiplication is a smooth map +# `C^n` monoid +A `C^n` monoid is a monoid that is also a `C^n` manifold, in which multiplication is a `C^n` map of the product manifold `G` × `G` into `G`. -In this file we define the basic structures to talk about smooth monoids: `SmoothMul` and its -additive counterpart `SmoothAdd`. These structures are general enough to also talk about smooth +In this file we define the basic structures to talk about `C^n` monoids: `ContMDiffMul` and its +additive counterpart `ContMDiffAdd`. These structures are general enough to also talk about `C^n` semigroups. -/ - -open scoped Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped Manifold ContDiff library_note "Design choices about smooth algebraic structures"/-- -1. All smooth algebraic structures on `G` are `Prop`-valued classes that extend -`SmoothManifoldWithCorners I G`. This way we save users from adding both -`[SmoothManifoldWithCorners I G]` and `[SmoothMul I G]` to the assumptions. While many API -lemmas hold true without the `SmoothManifoldWithCorners I G` assumption, we're not aware of a +1. All `C^n` algebraic structures on `G` are `Prop`-valued classes that extend +`IsManifold I n G`. This way we save users from adding both +`[IsManifold I n G]` and `[ContMDiffMul I n G]` to the assumptions. While many API +lemmas hold true without the `IsManifold I n G` assumption, we're not aware of a mathematically interesting monoid on a topological manifold such that (a) the space is not a -`SmoothManifoldWithCorners`; (b) the multiplication is smooth at `(a, b)` in the charts +`IsManifold`; (b) the multiplication is `C^n` at `(a, b)` in the charts `extChartAt I a`, `extChartAt I b`, `extChartAt I (a * b)`. 2. Because of `ModelProd` we can't assume, e.g., that a `LieGroup` is modelled on `𝓘(𝕜, E)`. So, we formulate the definitions and lemmas for any model. 3. While smoothness of an operation implies its continuity, lemmas like -`continuousMul_of_smooth` can't be instances becausen otherwise Lean would have to search for -`SmoothMul I G` with unknown `𝕜`, `E`, `H`, and `I : ModelWithCorners 𝕜 E H`. If users needs -`[ContinuousMul G]` in a proof about a smooth monoid, then they need to either add +`continuousMul_of_contMDiffMul` can't be instances because otherwise Lean would have to search for +`ContMDiffMul I n G` with unknown `𝕜`, `E`, `H`, and `I : ModelWithCorners 𝕜 E H`. If users needs +`[ContinuousMul G]` in a proof about a `C^n` monoid, then they need to either add `[ContinuousMul G]` as an assumption (worse) or use `haveI` in the proof (better). -/ -- See note [Design choices about smooth algebraic structures] -/-- Basic hypothesis to talk about a smooth (Lie) additive monoid or a smooth additive -semigroup. A smooth additive monoid over `α`, for example, is obtained by requiring both the -instances `AddMonoid α` and `SmoothAdd α`. -/ -class SmoothAdd {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) - [Add G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothManifoldWithCorners I G : +/-- Basic hypothesis to talk about a `C^n` (Lie) additive monoid or a `C^n` additive +semigroup. A `C^n` additive monoid over `G`, for example, is obtained by requiring both the +instances `AddMonoid G` and `ContMDiffAdd I n G`. -/ +class ContMDiffAdd {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + (I : ModelWithCorners 𝕜 E H) (n : WithTop ℕ∞) + (G : Type*) [Add G] [TopologicalSpace G] [ChartedSpace H G] extends IsManifold I n G : Prop where - smooth_add : ContMDiff (I.prod I) I ⊤ fun p : G × G => p.1 + p.2 + contMDiff_add : ContMDiff (I.prod I) I n fun p : G × G => p.1 + p.2 + +@[deprecated (since := "2025-01-09")] alias SmoothAdd := ContMDiffAdd -- See note [Design choices about smooth algebraic structures] -/-- Basic hypothesis to talk about a smooth (Lie) monoid or a smooth semigroup. -A smooth monoid over `G`, for example, is obtained by requiring both the instances `Monoid G` -and `SmoothMul I G`. -/ -@[to_additive] -class SmoothMul {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) - [Mul G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothManifoldWithCorners I G : +/-- Basic hypothesis to talk about a `C^n` (Lie) monoid or a `C^n` semigroup. +A `C^n` monoid over `G`, for example, is obtained by requiring both the instances `Monoid G` +and `ContMDiffMul I n G`. -/ +@[to_additive] +class ContMDiffMul {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + (I : ModelWithCorners 𝕜 E H) (n : WithTop ℕ∞) + (G : Type*) [Mul G] [TopologicalSpace G] [ChartedSpace H G] extends IsManifold I n G : Prop where - smooth_mul : ContMDiff (I.prod I) I ⊤ fun p : G × G => p.1 * p.2 + contMDiff_mul : ContMDiff (I.prod I) I n fun p : G × G => p.1 * p.2 -section SmoothMul +@[deprecated (since := "2025-01-09")] alias SmoothMul := ContMDiffMul + +section ContMDiffMul variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} - [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} [Mul G] - [TopologicalSpace G] [ChartedSpace H G] [SmoothMul I G] {E' : Type*} [NormedAddCommGroup E'] + [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {n : WithTop ℕ∞} + {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] +@[to_additive] +protected theorem ContMDiffMul.of_le {m n : WithTop ℕ∞} (hmn : m ≤ n) + [h : ContMDiffMul I n G] : ContMDiffMul I m G := by + have : IsManifold I m G := IsManifold.of_le hmn + exact ⟨h.contMDiff_mul.of_le hmn⟩ + +@[to_additive] +instance {a : WithTop ℕ∞} [ContMDiffMul I ∞ G] [h : ENat.LEInfty a] : ContMDiffMul I a G := + ContMDiffMul.of_le h.out + +@[to_additive] +instance {a : WithTop ℕ∞} [ContMDiffMul I ω G] : ContMDiffMul I a G := + ContMDiffMul.of_le le_top + +@[to_additive] +instance [ContinuousMul G] : ContMDiffMul I 0 G := by + constructor + rw [contMDiff_zero_iff] + exact continuous_mul + +@[to_additive] +instance [ContMDiffMul I 2 G] : ContMDiffMul I 1 G := + ContMDiffMul.of_le one_le_two + section -variable (I) +variable (I n) @[to_additive] -theorem contMDiff_mul : ContMDiff (I.prod I) I ⊤ fun p : G × G => p.1 * p.2 := - SmoothMul.smooth_mul +theorem contMDiff_mul [ContMDiffMul I n G] : ContMDiff (I.prod I) I n fun p : G × G => p.1 * p.2 := + ContMDiffMul.contMDiff_mul @[deprecated (since := "2024-11-20")] alias smooth_mul := contMDiff_mul @[deprecated (since := "2024-11-20")] alias smooth_add := contMDiff_add -include I in -/-- If the multiplication is smooth, then it is continuous. This is not an instance for technical +include I n in +/-- If the multiplication is `C^n`, then it is continuous. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]. -/ -@[to_additive "If the addition is smooth, then it is continuous. This is not an instance for +@[to_additive "If the addition is `C^n`, then it is continuous. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]."] -theorem continuousMul_of_smooth : ContinuousMul G := - ⟨(contMDiff_mul I).continuous⟩ +theorem continuousMul_of_contMDiffMul [ContMDiffMul I n G] : ContinuousMul G := + ⟨(contMDiff_mul I n).continuous⟩ + +@[deprecated (since := "2025-01-09")] alias continuousMul_of_smooth := continuousMul_of_contMDiffMul end section -variable {f g : M → G} {s : Set M} {x : M} {n : ℕ∞} +variable [ContMDiffMul I n G] {f g : M → G} {s : Set M} {x : M} @[to_additive] theorem ContMDiffWithinAt.mul (hf : ContMDiffWithinAt I' I n f s x) (hg : ContMDiffWithinAt I' I n g s x) : ContMDiffWithinAt I' I n (f * g) s x := - ((contMDiff_mul I).contMDiffAt.of_le le_top).comp_contMDiffWithinAt x (hf.prod_mk hg) + (contMDiff_mul I n).contMDiffAt.comp_contMDiffWithinAt x (hf.prod_mk hg) @[to_additive] nonrec theorem ContMDiffAt.mul (hf : ContMDiffAt I' I n f x) (hg : ContMDiffAt I' I n g x) : @@ -133,14 +161,6 @@ theorem contMDiff_mul_left {a : G} : ContMDiff I I n (a * ·) := theorem contMDiffAt_mul_left {a b : G} : ContMDiffAt I I n (a * ·) b := contMDiff_mul_left.contMDiffAt -@[to_additive] -theorem mdifferentiable_mul_left {a : G} : MDifferentiable I I (a * ·) := - contMDiff_mul_left.mdifferentiable le_rfl - -@[to_additive] -theorem mdifferentiableAt_mul_left {a b : G} : MDifferentiableAt I I (a * ·) b := - contMDiffAt_mul_left.mdifferentiableAt le_rfl - @[to_additive] theorem contMDiff_mul_right {a : G} : ContMDiff I I n (· * a) := contMDiff_id.mul contMDiff_const @@ -152,25 +172,44 @@ theorem contMDiff_mul_right {a : G} : ContMDiff I I n (· * a) := theorem contMDiffAt_mul_right {a b : G} : ContMDiffAt I I n (· * a) b := contMDiff_mul_right.contMDiffAt +end + +section + +variable [ContMDiffMul I 1 G] + +@[to_additive] +theorem mdifferentiable_mul_left {a : G} : MDifferentiable I I (a * ·) := + contMDiff_mul_left.mdifferentiable le_rfl + +@[to_additive] +theorem mdifferentiableAt_mul_left {a b : G} : + MDifferentiableAt I I (a * ·) b := + contMDiffAt_mul_left.mdifferentiableAt le_rfl + @[to_additive] theorem mdifferentiable_mul_right {a : G} : MDifferentiable I I (· * a) := contMDiff_mul_right.mdifferentiable le_rfl @[to_additive] -theorem mdifferentiableAt_mul_right {a b : G} : MDifferentiableAt I I (· * a) b := +theorem mdifferentiableAt_mul_right {a b : G} : + MDifferentiableAt I I (· * a) b := contMDiffAt_mul_right.mdifferentiableAt le_rfl end variable (I) (g h : G) +variable [ContMDiffMul I ∞ G] /-- Left multiplication by `g`. It is meant to mimic the usual notation in Lie groups. +Used mostly through the notation `𝑳`. Lemmas involving `smoothLeftMul` with the notation `𝑳` usually use `L` instead of `𝑳` in the names. -/ def smoothLeftMul : C^∞⟮I, G; I, G⟯ := ⟨leftMul g, contMDiff_mul_left⟩ /-- Right multiplication by `g`. It is meant to mimic the usual notation in Lie groups. +Used mostly through the notation `𝑹`. Lemmas involving `smoothRightMul` with the notation `𝑹` usually use `R` instead of `𝑹` in the names. -/ def smoothRightMul : C^∞⟮I, G; I, G⟯ := @@ -193,20 +232,20 @@ theorem R_apply : (𝑹 I g) h = h * g := rfl @[simp] -theorem L_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [SmoothMul I G] +theorem L_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I ∞ G] (g h : G) : 𝑳 I (g * h) = (𝑳 I g).comp (𝑳 I h) := by ext simp only [ContMDiffMap.comp_apply, L_apply, mul_assoc] @[simp] -theorem R_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [SmoothMul I G] +theorem R_mul {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I ∞ G] (g h : G) : 𝑹 I (g * h) = (𝑹 I h).comp (𝑹 I g) := by ext simp only [ContMDiffMap.comp_apply, R_apply, mul_assoc] section -variable {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H G'] [SmoothMul I G'] +variable {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H G'] [ContMDiffMul I ∞ G'] (g' : G') theorem smoothLeftMul_one : (𝑳 I g') 1 = g' := @@ -219,90 +258,95 @@ end -- Instance of product @[to_additive] -instance SmoothMul.prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} +instance ContMDiffMul.prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [Mul G] - [SmoothMul I G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} + [ContMDiffMul I n G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] (I' : ModelWithCorners 𝕜 E' H') (G' : Type*) [TopologicalSpace G'] - [ChartedSpace H' G'] [Mul G'] [SmoothMul I' G'] : SmoothMul (I.prod I') (G × G') := - { SmoothManifoldWithCorners.prod G G' with - smooth_mul := + [ChartedSpace H' G'] [Mul G'] [ContMDiffMul I' n G'] : ContMDiffMul (I.prod I') n (G × G') := + { IsManifold.prod G G' with + contMDiff_mul := ((contMDiff_fst.comp contMDiff_fst).mul (contMDiff_fst.comp contMDiff_snd)).prod_mk ((contMDiff_snd.comp contMDiff_fst).mul (contMDiff_snd.comp contMDiff_snd)) } -end SmoothMul +end ContMDiffMul section Monoid -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} + {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} {G : Type*} [Monoid G] - [TopologicalSpace G] [ChartedSpace H G] [SmoothMul I G] {H' : Type*} [TopologicalSpace H'] + [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I n G] {H' : Type*} [TopologicalSpace H'] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {I' : ModelWithCorners 𝕜 E' H'} - {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H' G'] [SmoothMul I' G'] + {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H' G'] [ContMDiffMul I' n G'] @[to_additive] -theorem contMDiff_pow : ∀ n : ℕ, ContMDiff I I ⊤ fun a : G => a ^ n +theorem contMDiff_pow : ∀ i : ℕ, ContMDiff I I n fun a : G => a ^ i | 0 => by simp only [pow_zero]; exact contMDiff_const | k + 1 => by simpa [pow_succ] using (contMDiff_pow _).mul contMDiff_id @[deprecated (since := "2024-11-21")] alias smooth_pow := contMDiff_pow @[deprecated (since := "2024-11-21")] alias smooth_nsmul := contMDiff_nsmul -/-- Morphism of additive smooth monoids. -/ -structure SmoothAddMonoidMorphism (I : ModelWithCorners 𝕜 E H) (I' : ModelWithCorners 𝕜 E' H') - (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [AddMonoid G] [SmoothAdd I G] +/-- Morphism of additive `C^n` monoids. -/ +structure ContMDiffAddMonoidMorphism (I : ModelWithCorners 𝕜 E H) (I' : ModelWithCorners 𝕜 E' H') + (n : WithTop ℕ∞) (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [AddMonoid G] (G' : Type*) [TopologicalSpace G'] [ChartedSpace H' G'] [AddMonoid G'] - [SmoothAdd I' G'] extends G →+ G' where - smooth_toFun : ContMDiff I I' ⊤ toFun + extends G →+ G' where + contMDiff_toFun : ContMDiff I I' n toFun + +@[deprecated (since := "2025-01-09")] alias SmoothAddMonoidMorphism := ContMDiffAddMonoidMorphism -/-- Morphism of smooth monoids. -/ +/-- Morphism of `C^n` monoids. -/ @[to_additive] -structure SmoothMonoidMorphism (I : ModelWithCorners 𝕜 E H) (I' : ModelWithCorners 𝕜 E' H') - (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [Monoid G] [SmoothMul I G] (G' : Type*) - [TopologicalSpace G'] [ChartedSpace H' G'] [Monoid G'] [SmoothMul I' G'] extends +structure ContMDiffMonoidMorphism (I : ModelWithCorners 𝕜 E H) (I' : ModelWithCorners 𝕜 E' H') + (n : WithTop ℕ∞) (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [Monoid G] (G' : Type*) + [TopologicalSpace G'] [ChartedSpace H' G'] [Monoid G'] extends G →* G' where - smooth_toFun : ContMDiff I I' ⊤ toFun + contMDiff_toFun : ContMDiff I I' n toFun + +@[deprecated (since := "2025-01-09")] alias SmoothMonoidMorphism := ContMDiffMonoidMorphism @[to_additive] -instance : One (SmoothMonoidMorphism I I' G G') := - ⟨{ smooth_toFun := contMDiff_const +instance : One (ContMDiffMonoidMorphism I I' n G G') := + ⟨{ contMDiff_toFun := contMDiff_const toMonoidHom := 1 }⟩ @[to_additive] -instance : Inhabited (SmoothMonoidMorphism I I' G G') := +instance : Inhabited (ContMDiffMonoidMorphism I I' n G G') := ⟨1⟩ @[to_additive] -instance : FunLike (SmoothMonoidMorphism I I' G G') G G' where +instance : FunLike (ContMDiffMonoidMorphism I I' n G G') G G' where coe a := a.toFun coe_injective' f g h := by cases f; cases g; congr; exact DFunLike.ext' h @[to_additive] -instance : MonoidHomClass (SmoothMonoidMorphism I I' G G') G G' where +instance : MonoidHomClass (ContMDiffMonoidMorphism I I' n G G') G G' where map_one f := f.map_one map_mul f := f.map_mul @[to_additive] -instance : ContinuousMapClass (SmoothMonoidMorphism I I' G G') G G' where - map_continuous f := f.smooth_toFun.continuous +instance : ContinuousMapClass (ContMDiffMonoidMorphism I I' n G G') G G' where + map_continuous f := f.contMDiff_toFun.continuous end Monoid /-! ### Differentiability of finite point-wise sums and products - Finite point-wise products (resp. sums) of differentiable/smooth functions `M → G` (at `x`/on `s`) - into a commutative monoid `G` are differentiable/smooth at `x`/on `s`. -/ + Finite point-wise products (resp. sums) of `C^n` functions `M → G` (at `x`/on `s`) + into a commutative monoid `G` are `C^n` at `x`/on `s`. -/ section CommMonoid open Function -variable {ι 𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] +variable {ι 𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} - {G : Type*} [CommMonoid G] [TopologicalSpace G] [ChartedSpace H G] [SmoothMul I G] + {G : Type*} [CommMonoid G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I n G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] - {s : Set M} {x x₀ : M} {t : Finset ι} {f : ι → M → G} {n : ℕ∞} {p : ι → Prop} + {s : Set M} {x x₀ : M} {t : Finset ι} {f : ι → M → G} {p : ι → Prop} @[to_additive] theorem ContMDiffWithinAt.prod (h : ∀ i ∈ t, ContMDiffWithinAt I' I n (f i) s x₀) : @@ -440,9 +484,9 @@ end CommMonoid section variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] + [NormedSpace 𝕜 E] {n : WithTop ℕ∞} -instance hasSmoothAddSelf : SmoothAdd 𝓘(𝕜, E) E := by +instance instContMDiffAddSelf : ContMDiffAdd 𝓘(𝕜, E) n E := by constructor rw [← modelWithCornersSelf_prod, chartedSpaceSelf_prod] exact contDiff_add.contMDiff @@ -451,14 +495,15 @@ end section DivConst -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} + {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {I : ModelWithCorners 𝕜 E H} - {G : Type*} [DivInvMonoid G] [TopologicalSpace G] [ChartedSpace H G] [SmoothMul I G] + {G : Type*} [DivInvMonoid G] [TopologicalSpace G] [ChartedSpace H G] [ContMDiffMul I n G] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] -variable {f : M → G} {s : Set M} {x : M} {n : ℕ∞} (c : G) +variable {f : M → G} {s : Set M} {x : M} (c : G) @[to_additive] theorem ContMDiffWithinAt.div_const (hf : ContMDiffWithinAt I' I n f s x) : diff --git a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean index db675c91210d4..071859f732ad3 100644 --- a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean +++ b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean @@ -6,18 +6,15 @@ Authors: Nicolò Cavalleri import Mathlib.Geometry.Manifold.Algebra.Structures /-! -# Algebraic structures over smooth functions +# Algebraic structures over `C^n` functions -In this file, we define instances of algebraic structures over smooth functions. +In this file, we define instances of algebraic structures over `C^n` functions. -/ noncomputable section -open scoped Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped Manifold ContDiff open TopologicalSpace @@ -27,46 +24,48 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom {I' : ModelWithCorners 𝕜 E' H'} {N : Type*} [TopologicalSpace N] [ChartedSpace H N] {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] {H'' : Type*} [TopologicalSpace H''] {I'' : ModelWithCorners 𝕜 E'' H''} {N' : Type*} [TopologicalSpace N'] [ChartedSpace H'' N'] + {n : WithTop ℕ∞} -namespace SmoothMap +namespace ContMDiffMap @[to_additive] protected instance instMul {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] - [SmoothMul I' G] : Mul C^∞⟮I, N; I', G⟯ := + [ContMDiffMul I' n G] : Mul C^n⟮I, N; I', G⟯ := ⟨fun f g => ⟨f * g, f.contMDiff.mul g.contMDiff⟩⟩ @[to_additive (attr := simp)] -theorem coe_mul {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] - (f g : C^∞⟮I, N; I', G⟯) : ⇑(f * g) = f * g := +theorem coe_mul {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [ContMDiffMul I' n G] + (f g : C^n⟮I, N; I', G⟯) : ⇑(f * g) = f * g := rfl @[to_additive (attr := simp)] -theorem mul_comp {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] - (f g : C^∞⟮I'', N'; I', G⟯) (h : C^∞⟮I, N; I'', N'⟯) : (f * g).comp h = f.comp h * g.comp h := +theorem mul_comp {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [ContMDiffMul I' n G] + (f g : C^n⟮I'', N'; I', G⟯) (h : C^n⟮I, N; I'', N'⟯) : (f * g).comp h = f.comp h * g.comp h := rfl @[to_additive] protected instance instOne {G : Type*} [One G] [TopologicalSpace G] [ChartedSpace H' G] : - One C^∞⟮I, N; I', G⟯ := + One C^n⟮I, N; I', G⟯ := ⟨ContMDiffMap.const (1 : G)⟩ @[to_additive (attr := simp)] theorem coe_one {G : Type*} [One G] [TopologicalSpace G] [ChartedSpace H' G] : - ⇑(1 : C^∞⟮I, N; I', G⟯) = 1 := + ⇑(1 : C^n⟮I, N; I', G⟯) = 1 := rfl instance instNSMul {G : Type*} [AddMonoid G] [TopologicalSpace G] [ChartedSpace H' G] - [SmoothAdd I' G] : SMul ℕ C^∞⟮I, N; I', G⟯ where + [ContMDiffAdd I' n G] : SMul ℕ C^n⟮I, N; I', G⟯ where smul n f := ⟨n • (f : N → G), (contMDiff_nsmul n).comp f.contMDiff⟩ @[to_additive existing] -instance instPow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] : - Pow C^∞⟮I, N; I', G⟯ ℕ where +instance instPow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] + [ContMDiffMul I' n G] : + Pow C^n⟮I, N; I', G⟯ ℕ where pow f n := ⟨(f : N → G) ^ n, (contMDiff_pow n).comp f.contMDiff⟩ @[to_additive (attr := simp)] -theorem coe_pow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] - (f : C^∞⟮I, N; I', G⟯) (n : ℕ) : +theorem coe_pow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] + [ContMDiffMul I' n G] (f : C^n⟮I, N; I', G⟯) (n : ℕ) : ⇑(f ^ n) = (f : N → G) ^ n := rfl @@ -75,53 +74,54 @@ section GroupStructure /-! ### Group structure -In this section we show that smooth functions valued in a Lie group inherit a group structure +In this section we show that `C^n` functions valued in a Lie group inherit a group structure under pointwise multiplication. -/ @[to_additive] instance semigroup {G : Type*} [Semigroup G] [TopologicalSpace G] [ChartedSpace H' G] - [SmoothMul I' G] : Semigroup C^∞⟮I, N; I', G⟯ := + [ContMDiffMul I' n G] : Semigroup C^n⟮I, N; I', G⟯ := DFunLike.coe_injective.semigroup _ coe_mul @[to_additive] instance monoid {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] - [SmoothMul I' G] : Monoid C^∞⟮I, N; I', G⟯ := + [ContMDiffMul I' n G] : Monoid C^n⟮I, N; I', G⟯ := DFunLike.coe_injective.monoid _ coe_one coe_mul coe_pow /-- Coercion to a function as a `MonoidHom`. Similar to `MonoidHom.coeFn`. -/ @[to_additive (attr := simps) "Coercion to a function as an `AddMonoidHom`. Similar to `AddMonoidHom.coeFn`."] def coeFnMonoidHom {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] - [SmoothMul I' G] : C^∞⟮I, N; I', G⟯ →* N → G where + [ContMDiffMul I' n G] : C^n⟮I, N; I', G⟯ →* N → G where toFun := DFunLike.coe map_one' := coe_one map_mul' := coe_mul variable (I N) -/-- For a manifold `N` and a smooth homomorphism `φ` between Lie groups `G'`, `G''`, the -'left-composition-by-`φ`' group homomorphism from `C^∞⟮I, N; I', G'⟯` to `C^∞⟮I, N; I'', G''⟯`. -/ -@[to_additive "For a manifold `N` and a smooth homomorphism `φ` between additive Lie groups `G'`, -`G''`, the 'left-composition-by-`φ`' group homomorphism from `C^∞⟮I, N; I', G'⟯` to -`C^∞⟮I, N; I'', G''⟯`."] +/-- For a manifold `N` and a `C^n` homomorphism `φ` between Lie groups `G'`, `G''`, the +'left-composition-by-`φ`' group homomorphism from `C^n⟮I, N; I', G'⟯` to `C^n⟮I, N; I'', G''⟯`. -/ +@[to_additive "For a manifold `N` and a `C^n` homomorphism `φ` between additive Lie groups `G'`, +`G''`, the 'left-composition-by-`φ`' group homomorphism from `C^n⟮I, N; I', G'⟯` to +`C^n⟮I, N; I'', G''⟯`."] def compLeftMonoidHom {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H' G'] - [SmoothMul I' G'] {G'' : Type*} [Monoid G''] [TopologicalSpace G''] [ChartedSpace H'' G''] - [SmoothMul I'' G''] (φ : G' →* G'') (hφ : ContMDiff I' I'' ⊤ φ) : - C^∞⟮I, N; I', G'⟯ →* C^∞⟮I, N; I'', G''⟯ where + [ContMDiffMul I' n G'] {G'' : Type*} [Monoid G''] [TopologicalSpace G''] [ChartedSpace H'' G''] + [ContMDiffMul I'' n G''] (φ : G' →* G'') (hφ : ContMDiff I' I'' n φ) : + C^n⟮I, N; I', G'⟯ →* C^n⟮I, N; I'', G''⟯ where toFun f := ⟨φ ∘ f, hφ.comp f.contMDiff⟩ map_one' := by ext; show φ 1 = 1; simp map_mul' f g := by ext x; show φ (f x * g x) = φ (f x) * φ (g x); simp variable (I') {N} --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: generalize to any smooth map instead of `Set.inclusion` +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): +-- TODO: generalize to any `C^n` map instead of `Set.inclusion` /-- For a Lie group `G` and open sets `U ⊆ V` in `N`, the 'restriction' group homomorphism from -`C^∞⟮I, V; I', G⟯` to `C^∞⟮I, U; I', G⟯`. -/ +`C^n⟮I, V; I', G⟯` to `C^n⟮I, U; I', G⟯`. -/ @[to_additive "For an additive Lie group `G` and open sets `U ⊆ V` in `N`, the 'restriction' group -homomorphism from `C^∞⟮I, V; I', G⟯` to `C^∞⟮I, U; I', G⟯`."] +homomorphism from `C^n⟮I, V; I', G⟯` to `C^n⟮I, U; I', G⟯`."] def restrictMonoidHom (G : Type*) [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] - [SmoothMul I' G] {U V : Opens N} (h : U ≤ V) : C^∞⟮I, V; I', G⟯ →* C^∞⟮I, U; I', G⟯ where + [ContMDiffMul I' n G] {U V : Opens N} (h : U ≤ V) : C^n⟮I, V; I', G⟯ →* C^n⟮I, U; I', G⟯ where toFun f := ⟨f ∘ Set.inclusion h, f.contMDiff.comp (contMDiff_inclusion h)⟩ map_one' := rfl map_mul' _ _ := rfl @@ -130,32 +130,32 @@ variable {I I'} @[to_additive] instance commMonoid {G : Type*} [CommMonoid G] [TopologicalSpace G] [ChartedSpace H' G] - [SmoothMul I' G] : CommMonoid C^∞⟮I, N; I', G⟯ := + [ContMDiffMul I' n G] : CommMonoid C^n⟮I, N; I', G⟯ := DFunLike.coe_injective.commMonoid _ coe_one coe_mul coe_pow @[to_additive] -instance group {G : Type*} [Group G] [TopologicalSpace G] [ChartedSpace H' G] [LieGroup I' G] : - Group C^∞⟮I, N; I', G⟯ := - { SmoothMap.monoid with +instance group {G : Type*} [Group G] [TopologicalSpace G] [ChartedSpace H' G] [LieGroup I' n G] : + Group C^n⟮I, N; I', G⟯ := + { ContMDiffMap.monoid with inv := fun f => ⟨fun x => (f x)⁻¹, f.contMDiff.inv⟩ inv_mul_cancel := fun a => by ext; exact inv_mul_cancel _ div := fun f g => ⟨f / g, f.contMDiff.div g.contMDiff⟩ div_eq_mul_inv := fun f g => by ext; exact div_eq_mul_inv _ _ } @[to_additive (attr := simp)] -theorem coe_inv {G : Type*} [Group G] [TopologicalSpace G] [ChartedSpace H' G] [LieGroup I' G] - (f : C^∞⟮I, N; I', G⟯) : ⇑f⁻¹ = (⇑f)⁻¹ := +theorem coe_inv {G : Type*} [Group G] [TopologicalSpace G] [ChartedSpace H' G] [LieGroup I' n G] + (f : C^n⟮I, N; I', G⟯) : ⇑f⁻¹ = (⇑f)⁻¹ := rfl @[to_additive (attr := simp)] -theorem coe_div {G : Type*} [Group G] [TopologicalSpace G] [ChartedSpace H' G] [LieGroup I' G] - (f g : C^∞⟮I, N; I', G⟯) : ⇑(f / g) = f / g := +theorem coe_div {G : Type*} [Group G] [TopologicalSpace G] [ChartedSpace H' G] [LieGroup I' n G] + (f g : C^n⟮I, N; I', G⟯) : ⇑(f / g) = f / g := rfl @[to_additive] instance commGroup {G : Type*} [CommGroup G] [TopologicalSpace G] [ChartedSpace H' G] - [LieGroup I' G] : CommGroup C^∞⟮I, N; I', G⟯ := - { SmoothMap.group, SmoothMap.commMonoid with } + [LieGroup I' n G] : CommGroup C^n⟮I, N; I', G⟯ := + { ContMDiffMap.group, ContMDiffMap.commMonoid with } end GroupStructure @@ -164,47 +164,48 @@ section RingStructure /-! ### Ring structure -In this section we show that smooth functions valued in a smooth ring `R` inherit a ring structure +In this section we show that `C^n` functions valued in a `C^n` ring `R` inherit a ring structure under pointwise multiplication. -/ instance semiring {R : Type*} [Semiring R] [TopologicalSpace R] [ChartedSpace H' R] - [SmoothRing I' R] : Semiring C^∞⟮I, N; I', R⟯ := - { SmoothMap.addCommMonoid, - SmoothMap.monoid with + [ContMDiffRing I' n R] : Semiring C^n⟮I, N; I', R⟯ := + { ContMDiffMap.addCommMonoid, + ContMDiffMap.monoid with left_distrib := fun a b c => by ext; exact left_distrib _ _ _ right_distrib := fun a b c => by ext; exact right_distrib _ _ _ zero_mul := fun a => by ext; exact zero_mul _ mul_zero := fun a => by ext; exact mul_zero _ } -instance ring {R : Type*} [Ring R] [TopologicalSpace R] [ChartedSpace H' R] [SmoothRing I' R] : - Ring C^∞⟮I, N; I', R⟯ := - { SmoothMap.semiring, SmoothMap.addCommGroup with } +instance ring {R : Type*} [Ring R] [TopologicalSpace R] [ChartedSpace H' R] [ContMDiffRing I' n R] : + Ring C^n⟮I, N; I', R⟯ := + { ContMDiffMap.semiring, ContMDiffMap.addCommGroup with } instance commRing {R : Type*} [CommRing R] [TopologicalSpace R] [ChartedSpace H' R] - [SmoothRing I' R] : CommRing C^∞⟮I, N; I', R⟯ := - { SmoothMap.semiring, SmoothMap.addCommGroup, SmoothMap.commMonoid with } + [ContMDiffRing I' n R] : CommRing C^n⟮I, N; I', R⟯ := + { ContMDiffMap.semiring, ContMDiffMap.addCommGroup, ContMDiffMap.commMonoid with } variable (I N) -/-- For a manifold `N` and a smooth homomorphism `φ` between smooth rings `R'`, `R''`, the -'left-composition-by-`φ`' ring homomorphism from `C^∞⟮I, N; I', R'⟯` to `C^∞⟮I, N; I'', R''⟯`. -/ +/-- For a manifold `N` and a `C^n` homomorphism `φ` between `C^n` rings `R'`, `R''`, the +'left-composition-by-`φ`' ring homomorphism from `C^n⟮I, N; I', R'⟯` to `C^n⟮I, N; I'', R''⟯`. -/ def compLeftRingHom {R' : Type*} [Ring R'] [TopologicalSpace R'] [ChartedSpace H' R'] - [SmoothRing I' R'] {R'' : Type*} [Ring R''] [TopologicalSpace R''] [ChartedSpace H'' R''] - [SmoothRing I'' R''] (φ : R' →+* R'') (hφ : ContMDiff I' I'' ⊤ φ) : - C^∞⟮I, N; I', R'⟯ →+* C^∞⟮I, N; I'', R''⟯ := - { SmoothMap.compLeftMonoidHom I N φ.toMonoidHom hφ, - SmoothMap.compLeftAddMonoidHom I N φ.toAddMonoidHom hφ with + [ContMDiffRing I' n R'] {R'' : Type*} [Ring R''] [TopologicalSpace R''] [ChartedSpace H'' R''] + [ContMDiffRing I'' n R''] (φ : R' →+* R'') (hφ : ContMDiff I' I'' n φ) : + C^n⟮I, N; I', R'⟯ →+* C^n⟮I, N; I'', R''⟯ := + { ContMDiffMap.compLeftMonoidHom I N φ.toMonoidHom hφ, + ContMDiffMap.compLeftAddMonoidHom I N φ.toAddMonoidHom hφ with toFun := fun f => ⟨φ ∘ f, hφ.comp f.contMDiff⟩ } variable (I') {N} -/-- For a "smooth ring" `R` and open sets `U ⊆ V` in `N`, the "restriction" ring homomorphism from -`C^∞⟮I, V; I', R⟯` to `C^∞⟮I, U; I', R⟯`. -/ -def restrictRingHom (R : Type*) [Ring R] [TopologicalSpace R] [ChartedSpace H' R] [SmoothRing I' R] - {U V : Opens N} (h : U ≤ V) : C^∞⟮I, V; I', R⟯ →+* C^∞⟮I, U; I', R⟯ := - { SmoothMap.restrictMonoidHom I I' R h, SmoothMap.restrictAddMonoidHom I I' R h with +/-- For a "`C^n` ring" `R` and open sets `U ⊆ V` in `N`, the "restriction" ring homomorphism from +`C^n⟮I, V; I', R⟯` to `C^n⟮I, U; I', R⟯`. -/ +def restrictRingHom (R : Type*) [Ring R] [TopologicalSpace R] [ChartedSpace H' R] + [ContMDiffRing I' n R] {U V : Opens N} (h : U ≤ V) : + C^n⟮I, V; I', R⟯ →+* C^n⟮I, U; I', R⟯ := + { ContMDiffMap.restrictMonoidHom I I' R h, ContMDiffMap.restrictAddMonoidHom I I' R h with toFun := fun f => ⟨f ∘ Set.inclusion h, f.contMDiff.comp (contMDiff_inclusion h)⟩ } variable {I I'} @@ -212,14 +213,14 @@ variable {I I'} /-- Coercion to a function as a `RingHom`. -/ @[simps] def coeFnRingHom {R : Type*} [CommRing R] [TopologicalSpace R] [ChartedSpace H' R] - [SmoothRing I' R] : C^∞⟮I, N; I', R⟯ →+* N → R := - { (coeFnMonoidHom : C^∞⟮I, N; I', R⟯ →* _), (coeFnAddMonoidHom : C^∞⟮I, N; I', R⟯ →+ _) with + [ContMDiffRing I' n R] : C^n⟮I, N; I', R⟯ →+* N → R := + { (coeFnMonoidHom : C^n⟮I, N; I', R⟯ →* _), (coeFnAddMonoidHom : C^n⟮I, N; I', R⟯ →+ _) with toFun := (↑) } -/-- `Function.eval` as a `RingHom` on the ring of smooth functions. -/ -def evalRingHom {R : Type*} [CommRing R] [TopologicalSpace R] [ChartedSpace H' R] [SmoothRing I' R] - (n : N) : C^∞⟮I, N; I', R⟯ →+* R := - (Pi.evalRingHom _ n : (N → R) →+* R).comp SmoothMap.coeFnRingHom +/-- `Function.eval` as a `RingHom` on the ring of `C^n` functions. -/ +def evalRingHom {R : Type*} [CommRing R] [TopologicalSpace R] [ChartedSpace H' R] + [ContMDiffRing I' n R] (m : N) : C^n⟮I, N; I', R⟯ →+* R := + (Pi.evalRingHom _ m : (N → R) →+* R).comp ContMDiffMap.coeFnRingHom end RingStructure @@ -228,34 +229,34 @@ section ModuleStructure /-! ### Semimodule structure -In this section we show that smooth functions valued in a vector space `M` over a normed +In this section we show that `C^n` functions valued in a vector space `M` over a normed field `𝕜` inherit a vector space structure. -/ instance instSMul {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : - SMul 𝕜 C^∞⟮I, N; 𝓘(𝕜, V), V⟯ := + SMul 𝕜 C^n⟮I, N; 𝓘(𝕜, V), V⟯ := ⟨fun r f => ⟨r • ⇑f, contMDiff_const.smul f.contMDiff⟩⟩ @[simp] theorem coe_smul {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] (r : 𝕜) - (f : C^∞⟮I, N; 𝓘(𝕜, V), V⟯) : ⇑(r • f) = r • ⇑f := + (f : C^n⟮I, N; 𝓘(𝕜, V), V⟯) : ⇑(r • f) = r • ⇑f := rfl @[simp] theorem smul_comp {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] (r : 𝕜) - (g : C^∞⟮I'', N'; 𝓘(𝕜, V), V⟯) (h : C^∞⟮I, N; I'', N'⟯) : (r • g).comp h = r • g.comp h := + (g : C^n⟮I'', N'; 𝓘(𝕜, V), V⟯) (h : C^n⟮I, N; I'', N'⟯) : (r • g).comp h = r • g.comp h := rfl instance module {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : - Module 𝕜 C^∞⟮I, N; 𝓘(𝕜, V), V⟯ := + Module 𝕜 C^n⟮I, N; 𝓘(𝕜, V), V⟯ := Function.Injective.module 𝕜 coeFnAddMonoidHom ContMDiffMap.coe_injective coe_smul /-- Coercion to a function as a `LinearMap`. -/ @[simps] def coeFnLinearMap {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : - C^∞⟮I, N; 𝓘(𝕜, V), V⟯ →ₗ[𝕜] N → V := - { (coeFnAddMonoidHom : C^∞⟮I, N; 𝓘(𝕜, V), V⟯ →+ _) with + C^n⟮I, N; 𝓘(𝕜, V), V⟯ →ₗ[𝕜] N → V := + { (coeFnAddMonoidHom : C^n⟮I, N; 𝓘(𝕜, V), V⟯ →+ _) with toFun := (↑) map_smul' := coe_smul } @@ -266,38 +267,38 @@ section AlgebraStructure /-! ### Algebra structure -In this section we show that smooth functions valued in a normed algebra `A` over a normed field `𝕜` +In this section we show that `C^n` functions valued in a normed algebra `A` over a normed field `𝕜` inherit an algebra structure. -/ -variable {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] [SmoothRing 𝓘(𝕜, A) A] +variable {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] [ContMDiffRing 𝓘(𝕜, A) n A] -/-- Smooth constant functions as a `RingHom`. -/ -def C : 𝕜 →+* C^∞⟮I, N; 𝓘(𝕜, A), A⟯ where +/-- `C^n` constant functions as a `RingHom`. -/ +def C : 𝕜 →+* C^n⟮I, N; 𝓘(𝕜, A), A⟯ where toFun := fun c : 𝕜 => ⟨fun _ => (algebraMap 𝕜 A) c, contMDiff_const⟩ map_one' := by ext; exact (algebraMap 𝕜 A).map_one map_mul' c₁ c₂ := by ext; exact (algebraMap 𝕜 A).map_mul _ _ map_zero' := by ext; exact (algebraMap 𝕜 A).map_zero map_add' c₁ c₂ := by ext; exact (algebraMap 𝕜 A).map_add _ _ -instance algebra : Algebra 𝕜 C^∞⟮I, N; 𝓘(𝕜, A), A⟯ := - { --SmoothMap.semiring with -- Porting note: Commented this out. +instance algebra : Algebra 𝕜 C^n⟮I, N; 𝓘(𝕜, A), A⟯ := + { --ContMDiffMap.semiring with -- Porting note: Commented this out. smul := fun r f => ⟨r • f, contMDiff_const.smul f.contMDiff⟩ - toRingHom := SmoothMap.C + toRingHom := ContMDiffMap.C commutes' := fun c f => by ext x; exact Algebra.commutes' _ _ smul_def' := fun c f => by ext x; exact Algebra.smul_def' _ _ } /-- Coercion to a function as an `AlgHom`. -/ @[simps] -def coeFnAlgHom : C^∞⟮I, N; 𝓘(𝕜, A), A⟯ →ₐ[𝕜] N → A where +def coeFnAlgHom : C^n⟮I, N; 𝓘(𝕜, A), A⟯ →ₐ[𝕜] N → A where toFun := (↑) commutes' _ := rfl - -- `(SmoothMap.coeFnRingHom : C^∞⟮I, N; 𝓘(𝕜, A), A⟯ →+* _) with` times out for some reason - map_zero' := SmoothMap.coe_zero - map_one' := SmoothMap.coe_one - map_add' := SmoothMap.coe_add - map_mul' := SmoothMap.coe_mul + -- `(ContMDiffMap.coeFnRingHom : C^n⟮I, N; 𝓘(𝕜, A), A⟯ →+* _) with` times out for some reason + map_zero' := ContMDiffMap.coe_zero + map_one' := ContMDiffMap.coe_one + map_add' := ContMDiffMap.coe_add + map_mul' := ContMDiffMap.coe_mul end AlgebraStructure @@ -306,22 +307,25 @@ section ModuleOverContinuousFunctions /-! ### Structure as module over scalar functions -If `V` is a module over `𝕜`, then we show that the space of smooth functions from `N` to `V` -is naturally a vector space over the ring of smooth functions from `N` to `𝕜`. -/ - +If `V` is a module over `𝕜`, then we show that the space of `C^n` functions from `N` to `V` +is naturally a vector space over the ring of `C^n` functions from `N` to `𝕜`. -/ +/-- `C^n` scalar-valued functions act by left-multiplication on `C^n` functions. -/ instance instSMul' {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : - SMul C^∞⟮I, N; 𝕜⟯ C^∞⟮I, N; 𝓘(𝕜, V), V⟯ := + SMul C^n⟮I, N; 𝕜⟯ C^n⟮I, N; 𝓘(𝕜, V), V⟯ := ⟨fun f g => ⟨fun x => f x • g x, ContMDiff.smul f.2 g.2⟩⟩ +/-- The left multiplication with a `C^n` scalar function commutes with composition. -/ @[simp] -theorem smul_comp' {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] (f : C^∞⟮I'', N'; 𝕜⟯) - (g : C^∞⟮I'', N'; 𝓘(𝕜, V), V⟯) (h : C^∞⟮I, N; I'', N'⟯) : +theorem smul_comp' {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] (f : C^n⟮I'', N'; 𝕜⟯) + (g : C^n⟮I'', N'; 𝓘(𝕜, V), V⟯) (h : C^n⟮I, N; I'', N'⟯) : (f • g).comp h = f.comp h • g.comp h := rfl +/-- The space of `C^n` functions with values in a space `V` is a module over the space of `C^n` +functions with values in `𝕜`. -/ instance module' {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : - Module C^∞⟮I, N; 𝓘(𝕜), 𝕜⟯ C^∞⟮I, N; 𝓘(𝕜, V), V⟯ where + Module C^n⟮I, N; 𝓘(𝕜), 𝕜⟯ C^n⟮I, N; 𝓘(𝕜, V), V⟯ where smul := (· • ·) smul_add c f g := by ext x; exact smul_add (c x) (f x) (g x) add_smul c₁ c₂ f := by ext x; exact add_smul (c₁ x) (c₂ x) (f x) @@ -332,4 +336,4 @@ instance module' {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : end ModuleOverContinuousFunctions -end SmoothMap +end ContMDiffMap diff --git a/Mathlib/Geometry/Manifold/Algebra/Structures.lean b/Mathlib/Geometry/Manifold/Algebra/Structures.lean index a20f6b529acf8..f0940a0e3ce75 100644 --- a/Mathlib/Geometry/Manifold/Algebra/Structures.lean +++ b/Mathlib/Geometry/Manifold/Algebra/Structures.lean @@ -6,46 +6,51 @@ Authors: Nicolò Cavalleri import Mathlib.Geometry.Manifold.Algebra.LieGroup /-! -# Smooth structures +# `C^n` structures -In this file we define smooth structures that build on Lie groups. We prefer using the term smooth -instead of Lie mainly because Lie ring has currently another use in mathematics. +In this file we define `C^n` structures that build on Lie groups. We prefer using the +term `ContMDiffRing` instead of Lie mainly because Lie ring has currently another use +in mathematics. -/ open scoped Manifold ContDiff -section SmoothRing +section ContMDiffRing variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] {E : Type*} - [NormedAddCommGroup E] [NormedSpace 𝕜 E] + [NormedAddCommGroup E] [NormedSpace 𝕜 E] {n : WithTop ℕ∞} -- See note [Design choices about smooth algebraic structures] -/-- A smooth (semi)ring is a (semi)ring `R` where addition and multiplication are smooth. -If `R` is a ring, then negation is automatically smooth, as it is multiplication with `-1`. -/ -class SmoothRing (I : ModelWithCorners 𝕜 E H) (R : Type*) [Semiring R] [TopologicalSpace R] - [ChartedSpace H R] extends SmoothAdd I R : Prop where - smooth_mul : ContMDiff (I.prod I) I ⊤ fun p : R × R => p.1 * p.2 +/-- A `C^n` (semi)ring is a (semi)ring `R` where addition and multiplication are `C^n`. +If `R` is a ring, then negation is automatically `C^n`, as it is multiplication with `-1`. -/ +class ContMDiffRing (I : ModelWithCorners 𝕜 E H) (n : WithTop ℕ∞) + (R : Type*) [Semiring R] [TopologicalSpace R] + [ChartedSpace H R] extends ContMDiffAdd I n R : Prop where + contMDiff_mul : ContMDiff (I.prod I) I n fun p : R × R => p.1 * p.2 + +@[deprecated (since := "2025-01-09")] alias SmoothRing := ContMDiffRing -- see Note [lower instance priority] -instance (priority := 100) SmoothRing.toSmoothMul (I : ModelWithCorners 𝕜 E H) (R : Type*) - [Semiring R] [TopologicalSpace R] [ChartedSpace H R] [h : SmoothRing I R] : - SmoothMul I R := +instance (priority := 100) ContMDiffRing.toContMDiffMul (I : ModelWithCorners 𝕜 E H) (R : Type*) + [Semiring R] [TopologicalSpace R] [ChartedSpace H R] [h : ContMDiffRing I n R] : + ContMDiffMul I n R := { h with } -- see Note [lower instance priority] -instance (priority := 100) SmoothRing.toLieAddGroup (I : ModelWithCorners 𝕜 E H) (R : Type*) - [Ring R] [TopologicalSpace R] [ChartedSpace H R] [SmoothRing I R] : LieAddGroup I R where - compatible := StructureGroupoid.compatible (contDiffGroupoid ∞ I) - smooth_add := contMDiff_add I - smooth_neg := by simpa only [neg_one_mul] using contMDiff_mul_left (G := R) (a := -1) +instance (priority := 100) ContMDiffRing.toLieAddGroup (I : ModelWithCorners 𝕜 E H) (R : Type*) + [Ring R] [TopologicalSpace R] [ChartedSpace H R] [ContMDiffRing I n R] : LieAddGroup I n R where + compatible := StructureGroupoid.compatible (contDiffGroupoid n I) + contMDiff_add := contMDiff_add I n + contMDiff_neg := by simpa only [neg_one_mul] using contMDiff_mul_left (G := R) (a := -1) -end SmoothRing +end ContMDiffRing -- see Note [lower instance priority] -instance (priority := 100) fieldSmoothRing {𝕜 : Type*} [NontriviallyNormedField 𝕜] : - SmoothRing 𝓘(𝕜) 𝕜 := - { normedSpaceLieAddGroup with - smooth_mul := by +instance (priority := 100) instFieldContMDiffRing + {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} : + ContMDiffRing 𝓘(𝕜) n 𝕜 := + { instNormedSpaceLieAddGroup with + contMDiff_mul := by rw [contMDiff_iff] refine ⟨continuous_mul, fun x y => ?_⟩ simp only [mfld_simps] @@ -54,8 +59,13 @@ instance (priority := 100) fieldSmoothRing {𝕜 : Type*} [NontriviallyNormedFie variable {𝕜 R E H : Type*} [TopologicalSpace R] [TopologicalSpace H] [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] [ChartedSpace H R] (I : ModelWithCorners 𝕜 E H) + (n : WithTop ℕ∞) -/-- A smooth (semi)ring is a topological (semi)ring. This is not an instance for technical reasons, +/-- A `C^n` (semi)ring is a topological (semi)ring. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]. -/ -theorem topologicalSemiring_of_smooth [Semiring R] [SmoothRing I R] : TopologicalSemiring R := - { continuousMul_of_smooth I, continuousAdd_of_smooth I with } +theorem topologicalSemiring_of_contMDiffRing [Semiring R] [ContMDiffRing I n R] : + TopologicalSemiring R := + { continuousMul_of_contMDiffMul I n, continuousAdd_of_contMDiffAdd I n with } + +@[deprecated (since := "2025-01-09")] +alias topologicalSemiring_of_smooth := topologicalSemiring_of_contMDiffRing diff --git a/Mathlib/Geometry/Manifold/AnalyticManifold.lean b/Mathlib/Geometry/Manifold/AnalyticManifold.lean index cecf164328810..5765ec3b44ce1 100644 --- a/Mathlib/Geometry/Manifold/AnalyticManifold.lean +++ b/Mathlib/Geometry/Manifold/AnalyticManifold.lean @@ -10,17 +10,18 @@ import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners # Analytic manifolds (possibly with boundary or corners) An analytic manifold is a manifold modelled on a normed vector space, or a subset like a -half-space (to get manifolds with boundaries) for which changes of coordinates are analytic in the -interior and smooth everywhere (including at the boundary). The definition mirrors -`SmoothManifoldWithCorners`, but using an `analyticGroupoid` in place of `contDiffGroupoid`. All -analytic manifolds are smooth manifolds. +half-space (to get manifolds with boundaries) for which changes of coordinates are analytic +everywhere. The definition mirrors `IsManifold`, but using an `analyticGroupoid` in +place of `contDiffGroupoid`. All analytic manifolds are smooth manifolds. + +TODO: deprecate the whole file: one should use `IsManifold I ω M` instead -/ noncomputable section open Set Filter Function -open scoped Manifold Filter Topology +open scoped Manifold Filter Topology ContDiff variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] @@ -162,9 +163,9 @@ instance AnalyticManifold.prod {E A : Type} [NormedAddCommGroup E] [NormedSpace (n.toHasGroupoid.compatible hf2 hg2) /-- Analytic manifolds are smooth manifolds. -/ -instance AnalyticManifold.smoothManifoldWithCorners [ChartedSpace H M] +instance AnalyticManifold.isManifold [ChartedSpace H M] [cm : AnalyticManifold I M] : - SmoothManifoldWithCorners I M where + IsManifold I ∞ M where compatible hf hg := ⟨(cm.compatible hf hg).1.contDiffOn I.uniqueDiffOn_preimage_source, (cm.compatible hg hf).1.contDiffOn I.uniqueDiffOn_preimage_source⟩ diff --git a/Mathlib/Geometry/Manifold/BumpFunction.lean b/Mathlib/Geometry/Manifold/BumpFunction.lean index 0c37faf328e8a..9949a3555e1b8 100644 --- a/Mathlib/Geometry/Manifold/BumpFunction.lean +++ b/Mathlib/Geometry/Manifold/BumpFunction.lean @@ -36,7 +36,7 @@ variable {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E] open Function Filter Module Set Metric -open scoped Topology Manifold +open scoped Topology Manifold ContDiff noncomputable section @@ -283,10 +283,10 @@ theorem nhds_basis_support {s : Set M} (hs : s ∈ 𝓝 c) : ((nhds_basis_tsupport c).restrict_subset hs).to_hasBasis' (fun f hf => ⟨f, hf.2, subset_closure⟩) fun f _ => f.support_mem_nhds -variable [SmoothManifoldWithCorners I M] +variable [IsManifold I ∞ M] /-- A smooth bump function is infinitely smooth. -/ -protected theorem contMDiff : ContMDiff I 𝓘(ℝ) ⊤ f := by +protected theorem contMDiff : ContMDiff I 𝓘(ℝ) ∞ f := by refine contMDiff_of_tsupport fun x hx => ?_ have : x ∈ (chartAt H c).source := f.tsupport_subset_chartAt_source hx refine ContMDiffAt.congr_of_eventuallyEq ?_ <| f.eqOn_source.eventuallyEq_of_mem <| @@ -295,7 +295,7 @@ protected theorem contMDiff : ContMDiff I 𝓘(ℝ) ⊤ f := by @[deprecated (since := "2024-11-20")] alias smooth := SmoothBumpFunction.contMDiff -protected theorem contMDiffAt {x} : ContMDiffAt I 𝓘(ℝ) ⊤ f x := +protected theorem contMDiffAt {x} : ContMDiffAt I 𝓘(ℝ) ∞ f x := f.contMDiff.contMDiffAt @[deprecated (since := "2024-11-20")] alias smoothAt := SmoothBumpFunction.contMDiffAt @@ -306,8 +306,8 @@ protected theorem continuous : Continuous f := /-- If `f : SmoothBumpFunction I c` is a smooth bump function and `g : M → G` is a function smooth on the source of the chart at `c`, then `f • g` is smooth on the whole manifold. -/ theorem contMDiff_smul {G} [NormedAddCommGroup G] [NormedSpace ℝ G] {g : M → G} - (hg : ContMDiffOn I 𝓘(ℝ, G) ⊤ g (chartAt H c).source) : - ContMDiff I 𝓘(ℝ, G) ⊤ fun x => f x • g x := by + (hg : ContMDiffOn I 𝓘(ℝ, G) ∞ g (chartAt H c).source) : + ContMDiff I 𝓘(ℝ, G) ∞ fun x => f x • g x := by refine contMDiff_of_tsupport fun x hx => ?_ have : x ∈ (chartAt H c).source := -- Porting note: was a more readable `calc` diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index 0e455da5da7e2..5dd4edfb1c285 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -628,7 +628,7 @@ theorem ChartedSpace.isOpen_iff (s : Set M) : simp only [(chartAt H _).isOpen_image_iff_of_subset_source inter_subset_left] /-- `achart H x` is the chart at `x`, considered as an element of the atlas. -Especially useful for working with `BasicSmoothVectorBundleCore`. -/ +Especially useful for working with `BasicContMDiffVectorBundleCore`. -/ def achart (x : M) : atlas H M := ⟨chartAt H x, chart_mem_atlas H x⟩ diff --git a/Mathlib/Geometry/Manifold/Complex.lean b/Mathlib/Geometry/Manifold/Complex.lean index 4d7fa4e80bc64..6d7f80f8dae88 100644 --- a/Mathlib/Geometry/Manifold/Complex.lean +++ b/Mathlib/Geometry/Manifold/Complex.lean @@ -43,7 +43,7 @@ variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] variable {H : Type*} [TopologicalSpace H] {I : ModelWithCorners ℂ E H} [I.Boundaryless] variable {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] + [IsManifold I 1 M] /-- **Maximum modulus principle**: if `f : M → F` is complex differentiable in a neighborhood of `c` and the norm `‖f z‖` has a local maximum at `c`, then `‖f z‖` is locally constant in a neighborhood diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean b/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean index 89d21876c78f7..6f0a766c2f28d 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean @@ -8,25 +8,25 @@ import Mathlib.Geometry.Manifold.ContMDiff.Basic /-! ## Smoothness of charts and local structomorphisms -We show that the model with corners, charts, extended charts and their inverses are smooth, -and that local structomorphisms are smooth with smooth inverses. +We show that the model with corners, charts, extended charts and their inverses are `C^n`, +and that local structomorphisms are `C^n` with `C^n` inverses. -/ -open Set ChartedSpace SmoothManifoldWithCorners +open Set ChartedSpace IsManifold open scoped Manifold ContDiff variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] - -- declare a smooth manifold `M` over the pair `(E, H)`. + -- declare a `C^n` manifold `M` over the pair `(E, H)`. {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] - {I : ModelWithCorners 𝕜 E H} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] + {I : ModelWithCorners 𝕜 E H} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {n : WithTop ℕ∞} + [IsManifold I n M] -- declare a topological space `M'`. {M' : Type*} [TopologicalSpace M'] -- declare functions, sets, points and smoothness indices - {e : PartialHomeomorph M H} {x : M} {n : ℕ∞} + {e : PartialHomeomorph M H} {x : M} -/-! ### Atlas members are smooth -/ +/-! ### Atlas members are `C^n` -/ section Atlas @@ -45,21 +45,22 @@ theorem contMDiffOn_model_symm : ContMDiffOn 𝓘(𝕜, E) I n I.symm (range I) exact contDiffOn_id.congr fun x' => I.right_inv /-- An atlas member is `C^n` for any `n`. -/ -theorem contMDiffOn_of_mem_maximalAtlas (h : e ∈ maximalAtlas I M) : ContMDiffOn I I n e e.source := - ContMDiffOn.of_le ((contDiffWithinAt_localInvariantProp ⊤).liftPropOn_of_mem_maximalAtlas - contDiffWithinAtProp_id h) le_top +theorem contMDiffOn_of_mem_maximalAtlas (h : e ∈ maximalAtlas I n M) : + ContMDiffOn I I n e e.source := + (contDiffWithinAt_localInvariantProp n).liftPropOn_of_mem_maximalAtlas + contDiffWithinAtProp_id h /-- The inverse of an atlas member is `C^n` for any `n`. -/ -theorem contMDiffOn_symm_of_mem_maximalAtlas (h : e ∈ maximalAtlas I M) : +theorem contMDiffOn_symm_of_mem_maximalAtlas (h : e ∈ maximalAtlas I n M) : ContMDiffOn I I n e.symm e.target := - ContMDiffOn.of_le ((contDiffWithinAt_localInvariantProp ⊤).liftPropOn_symm_of_mem_maximalAtlas - contDiffWithinAtProp_id h) le_top + (contDiffWithinAt_localInvariantProp n).liftPropOn_symm_of_mem_maximalAtlas + contDiffWithinAtProp_id h -theorem contMDiffAt_of_mem_maximalAtlas (h : e ∈ maximalAtlas I M) (hx : x ∈ e.source) : +theorem contMDiffAt_of_mem_maximalAtlas (h : e ∈ maximalAtlas I n M) (hx : x ∈ e.source) : ContMDiffAt I I n e x := (contMDiffOn_of_mem_maximalAtlas h).contMDiffAt <| e.open_source.mem_nhds hx -theorem contMDiffAt_symm_of_mem_maximalAtlas {x : H} (h : e ∈ maximalAtlas I M) +theorem contMDiffAt_symm_of_mem_maximalAtlas {x : H} (h : e ∈ maximalAtlas I n M) (hx : x ∈ e.target) : ContMDiffAt I I n e.symm x := (contMDiffOn_symm_of_mem_maximalAtlas h).contMDiffAt <| e.open_target.mem_nhds hx @@ -69,7 +70,7 @@ theorem contMDiffOn_chart : ContMDiffOn I I n (chartAt H x) (chartAt H x).source theorem contMDiffOn_chart_symm : ContMDiffOn I I n (chartAt H x).symm (chartAt H x).target := contMDiffOn_symm_of_mem_maximalAtlas <| chart_mem_maximalAtlas x -theorem contMDiffAt_extend {x : M} (he : e ∈ maximalAtlas I M) (hx : x ∈ e.source) : +theorem contMDiffAt_extend {x : M} (he : e ∈ maximalAtlas I n M) (hx : x ∈ e.source) : ContMDiffAt I 𝓘(𝕜, E) n (e.extend I) x := (contMDiff_model _).comp x <| contMDiffAt_of_mem_maximalAtlas he hx @@ -83,7 +84,7 @@ theorem contMDiffAt_extChartAt : ContMDiffAt I 𝓘(𝕜, E) n (extChartAt I x) theorem contMDiffOn_extChartAt : ContMDiffOn I 𝓘(𝕜, E) n (extChartAt I x) (chartAt H x).source := fun _x' hx' => (contMDiffAt_extChartAt' hx').contMDiffWithinAt -theorem contMDiffOn_extend_symm (he : e ∈ maximalAtlas I M) : +theorem contMDiffOn_extend_symm (he : e ∈ maximalAtlas I n M) : ContMDiffOn 𝓘(𝕜, E) I n (e.extend I).symm (I '' e.target) := by refine (contMDiffOn_symm_of_mem_maximalAtlas he).comp (contMDiffOn_model_symm.mono <| image_subset_range _ _) ?_ @@ -93,7 +94,9 @@ theorem contMDiffOn_extend_symm (he : e ∈ maximalAtlas I M) : theorem contMDiffOn_extChartAt_symm (x : M) : ContMDiffOn 𝓘(𝕜, E) I n (extChartAt I x).symm (extChartAt I x).target := by convert contMDiffOn_extend_symm (chart_mem_maximalAtlas (I := I) x) - rw [extChartAt_target, I.image_eq] + · rw [extChartAt_target, I.image_eq] + · infer_instance + · infer_instance theorem contMDiffWithinAt_extChartAt_symm_target (x : M) {y : E} (hy : y ∈ (extChartAt I x).target) : @@ -106,23 +109,23 @@ theorem contMDiffWithinAt_extChartAt_symm_range (contMDiffWithinAt_extChartAt_symm_target x hy).mono_of_mem_nhdsWithin (extChartAt_target_mem_nhdsWithin_of_mem hy) -/-- An element of `contDiffGroupoid ⊤ I` is `C^n` for any `n`. -/ +/-- An element of `contDiffGroupoid n I` is `C^n`. -/ theorem contMDiffOn_of_mem_contDiffGroupoid {e' : PartialHomeomorph H H} - (h : e' ∈ contDiffGroupoid ∞ I) : ContMDiffOn I I n e' e'.source := + (h : e' ∈ contDiffGroupoid n I) : ContMDiffOn I I n e' e'.source := (contDiffWithinAt_localInvariantProp n).liftPropOn_of_mem_groupoid contDiffWithinAtProp_id h end Atlas -/-! ### Smoothness of (local) structomorphisms -/ +/-! ### (local) structomorphisms are `C^n` -/ section IsLocalStructomorph -variable [ChartedSpace H M'] [IsM' : SmoothManifoldWithCorners I M'] +variable [ChartedSpace H M'] [IsM' : IsManifold I n M'] theorem isLocalStructomorphOn_contDiffGroupoid_iff_aux {f : PartialHomeomorph M M'} - (hf : LiftPropOn (contDiffGroupoid ∞ I).IsLocalStructomorphWithinAt f f.source) : - ContMDiffOn I I ⊤ f f.source := by - -- It suffices to show smoothness near each `x` + (hf : LiftPropOn (contDiffGroupoid n I).IsLocalStructomorphWithinAt f f.source) : + ContMDiffOn I I n f f.source := by + -- It suffices to show regularity near each `x` apply contMDiffOn_of_locally_contMDiffOn intro x hx let c := chartAt H x @@ -142,10 +145,10 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff_aux {f : PartialHomeomorph M -- We need to show `f` is `ContMDiffOn` the domain `s ∩ f.source`. We show this in two -- steps: `f` is equal to `c'.symm ∘ e ∘ c` on that domain and that function is -- `ContMDiffOn` it. - have H₁ : ContMDiffOn I I ⊤ (c'.symm ∘ e ∘ c) s := by - have hc' : ContMDiffOn I I ⊤ c'.symm _ := contMDiffOn_chart_symm - have he'' : ContMDiffOn I I ⊤ e _ := contMDiffOn_of_mem_contDiffGroupoid he - have hc : ContMDiffOn I I ⊤ c _ := contMDiffOn_chart + have H₁ : ContMDiffOn I I n (c'.symm ∘ e ∘ c) s := by + have hc' : ContMDiffOn I I n c'.symm _ := contMDiffOn_chart_symm + have he'' : ContMDiffOn I I n e _ := contMDiffOn_of_mem_contDiffGroupoid he + have hc : ContMDiffOn I I n c _ := contMDiffOn_chart refine (hc'.comp' (he''.comp' hc)).mono ?_ dsimp [s, c, c'] mfld_set_tac @@ -162,12 +165,12 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff_aux {f : PartialHomeomorph M refine (H₁.congr H₂).mono ?_ mfld_set_tac -/-- Let `M` and `M'` be smooth manifolds with the same model-with-corners, `I`. Then `f : M → M'` -is a local structomorphism for `I`, if and only if it is manifold-smooth on the domain of definition +/-- Let `M` and `M'` be manifolds with the same model-with-corners, `I`. Then `f : M → M'` +is a local structomorphism for `I`, if and only if it is manifold-`C^n` on the domain of definition in both directions. -/ theorem isLocalStructomorphOn_contDiffGroupoid_iff (f : PartialHomeomorph M M') : - LiftPropOn (contDiffGroupoid ∞ I).IsLocalStructomorphWithinAt f f.source ↔ - ContMDiffOn I I ⊤ f f.source ∧ ContMDiffOn I I ⊤ f.symm f.target := by + LiftPropOn (contDiffGroupoid n I).IsLocalStructomorphWithinAt f f.source ↔ + ContMDiffOn I I n f f.source ∧ ContMDiffOn I I n f.symm f.target := by constructor · intro h refine ⟨isLocalStructomorphOn_contDiffGroupoid_iff_aux h, @@ -182,7 +185,7 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff (f : PartialHomeomorph M M') refine ⟨(f.symm.continuousAt hX).continuousWithinAt, fun h2x => ?_⟩ obtain ⟨e, he, h2e, hef, hex⟩ : ∃ e : PartialHomeomorph H H, - e ∈ contDiffGroupoid ∞ I ∧ + e ∈ contDiffGroupoid n I ∧ e.source ⊆ (c.symm ≫ₕ f ≫ₕ c').source ∧ EqOn (c' ∘ f ∘ c.symm) e e.source ∧ c x ∈ e.source := by have h1 : c' = chartAt H (f x) := by simp only [x, c', f.right_inv hX] @@ -214,7 +217,7 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff (f : PartialHomeomorph M M') mfld_set_tac refine ⟨e.symm, StructureGroupoid.symm _ he, h3e, ?_⟩ rw [h2X]; exact e.mapsTo hex - · -- We now show the converse: a partial homeomorphism `f : M → M'` which is smooth in both + · -- We now show the converse: a partial homeomorphism `f : M → M'` which is `C^n` in both -- directions is a local structomorphism. We do this by proposing -- `((chart_at H x).symm.trans f).trans (chart_at H (f x))` as a candidate for a structomorphism -- of `H`. @@ -225,10 +228,10 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff (f : PartialHomeomorph M M') rintro (hx' : c x ∈ c.symm ⁻¹' f.source) -- propose `(c.symm.trans f).trans c'` as a candidate for a local structomorphism of `H` refine ⟨(c.symm.trans f).trans c', ⟨?_, ?_⟩, (?_ : EqOn (c' ∘ f ∘ c.symm) _ _), ?_⟩ - · -- smoothness of the candidate local structomorphism in the forward direction + · -- regularity of the candidate local structomorphism in the forward direction intro y hy simp only [mfld_simps] at hy - have H : ContMDiffWithinAt I I ⊤ f (f ≫ₕ c').source ((extChartAt I x).symm y) := by + have H : ContMDiffWithinAt I I n f (f ≫ₕ c').source ((extChartAt I x).symm y) := by refine (h₁ ((extChartAt I x).symm y) ?_).mono ?_ · simp only [c, hy, mfld_simps] · mfld_set_tac @@ -239,10 +242,10 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff (f : PartialHomeomorph M M') convert H.2.mono _ · simp only [c, hy, mfld_simps] · dsimp [c, c']; mfld_set_tac - · -- smoothness of the candidate local structomorphism in the reverse direction + · -- regularity of the candidate local structomorphism in the reverse direction intro y hy simp only [mfld_simps] at hy - have H : ContMDiffWithinAt I I ⊤ f.symm (f.symm ≫ₕ c).source + have H : ContMDiffWithinAt I I n f.symm (f.symm ≫ₕ c).source ((extChartAt I (f x)).symm y) := by refine (h₂ ((extChartAt I (f x)).symm y) ?_).mono ?_ · simp only [c', hy, mfld_simps] diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean index af107053b4705..5e2447f6fa0b2 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean @@ -6,15 +6,15 @@ Authors: Sébastien Gouëzel, Floris van Doorn import Mathlib.Geometry.Manifold.ContMDiff.Defs /-! -## Basic properties of smooth functions between manifolds +## Basic properties of `C^n` functions between manifolds -In this file, we show that standard operations on smooth maps between smooth manifolds are smooth: +In this file, we show that standard operations on `C^n` maps between manifolds are `C^n` : * `ContMDiffOn.comp` gives the invariance of the `Cⁿ` property under composition * `contMDiff_id` gives the smoothness of the identity * `contMDiff_const` gives the smoothness of constant functions -* `contMDiff_inclusion` shows that the inclusion between open sets of a topological space is smooth +* `contMDiff_inclusion` shows that the inclusion between open sets of a topological space is `C^n` * `contMDiff_isOpenEmbedding` shows that if `M` has a `ChartedSpace` structure induced by an open -embedding `e : M → H`, then `e` is smooth. +embedding `e : M → H`, then `e` is `C^n`. ## Tags chain rule, manifolds, higher derivative @@ -22,7 +22,7 @@ chain rule, manifolds, higher derivative -/ open Filter Function Set Topology -open scoped Manifold +open scoped Manifold ContDiff variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] -- declare the prerequisites for a charted space `M` over the pair `(E, H)`. @@ -41,9 +41,9 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] section ChartedSpace variable [ChartedSpace H M] [ChartedSpace H' M'] [ChartedSpace H'' M''] -- declare functions, sets, points and smoothness indices - {f : M → M'} {s : Set M} {x : M} {n : ℕ∞} + {f : M → M'} {s : Set M} {x : M} {n : WithTop ℕ∞} -/-! ### Smoothness of the composition of smooth functions between manifolds -/ +/-! ### Regularity of the composition of `C^n` functions between manifolds -/ section Composition @@ -151,7 +151,7 @@ theorem ContMDiffOn.comp_contMDiff {t : Set M'} {g : M' → M''} (hg : ContMDiff end Composition -/-! ### The identity is smooth -/ +/-! ### The identity is `C^n` -/ section id @@ -178,7 +178,7 @@ theorem contMDiffWithinAt_id : ContMDiffWithinAt I I n (id : M → M) s x := end id -/-! ### Constants are smooth -/ +/-! ### Constants are `C^n` -/ section id variable {c : M'} @@ -251,7 +251,7 @@ theorem contMDiff_of_mulTSupport [One M'] {f : M → M'} @[to_additive contMDiffWithinAt_of_not_mem] theorem contMDiffWithinAt_of_not_mem_mulTSupport {f : M → M'} [One M'] {x : M} - (hx : x ∉ mulTSupport f) (n : ℕ∞) (s : Set M) : ContMDiffWithinAt I I' n f s x := by + (hx : x ∉ mulTSupport f) (n : WithTop ℕ∞) (s : Set M) : ContMDiffWithinAt I I' n f s x := by apply contMDiffWithinAt_const.congr_of_eventuallyEq (eventually_nhdsWithin_of_eventually_nhds <| not_mem_mulTSupport_iff_eventuallyEq.mp hx) (image_eq_one_of_nmem_mulTSupport hx) @@ -259,27 +259,28 @@ theorem contMDiffWithinAt_of_not_mem_mulTSupport {f : M → M'} [One M'] {x : M} /-- `f` is continuously differentiable at each point outside of its `mulTSupport`. -/ @[to_additive contMDiffAt_of_not_mem] theorem contMDiffAt_of_not_mem_mulTSupport {f : M → M'} [One M'] {x : M} - (hx : x ∉ mulTSupport f) (n : ℕ∞) : ContMDiffAt I I' n f x := + (hx : x ∉ mulTSupport f) (n : WithTop ℕ∞) : ContMDiffAt I I' n f x := contMDiffWithinAt_of_not_mem_mulTSupport hx n univ -/-! ### The inclusion map from one open set to another is smooth -/ +/-! ### The inclusion map from one open set to another is `C^n` -/ section Inclusion open TopologicalSpace -theorem contMDiffAt_subtype_iff {n : ℕ∞} {U : Opens M} {f : M → M'} {x : U} : +theorem contMDiffAt_subtype_iff {n : WithTop ℕ∞} {U : Opens M} {f : M → M'} {x : U} : ContMDiffAt I I' n (fun x : U ↦ f x) x ↔ ContMDiffAt I I' n f x := ((contDiffWithinAt_localInvariantProp n).liftPropAt_iff_comp_subtype_val _ _).symm @[deprecated (since := "2024-11-20")] alias contMdiffAt_subtype_iff := contMDiffAt_subtype_iff -theorem contMDiff_subtype_val {n : ℕ∞} {U : Opens M} : ContMDiff I I n (Subtype.val : U → M) := +theorem contMDiff_subtype_val {n : WithTop ℕ∞} {U : Opens M} : + ContMDiff I I n (Subtype.val : U → M) := fun _ ↦ contMDiffAt_subtype_iff.mpr contMDiffAt_id @[to_additive] -theorem ContMDiff.extend_one [T2Space M] [One M'] {n : ℕ∞} {U : Opens M} {f : U → M'} +theorem ContMDiff.extend_one [T2Space M] [One M'] {n : WithTop ℕ∞} {U : Opens M} {f : U → M'} (supp : HasCompactMulSupport f) (diff : ContMDiff I I' n f) : ContMDiff I I' n (Subtype.val.extend f 1) := fun x ↦ by refine contMDiff_of_mulTSupport (fun x h ↦ ?_) _ @@ -290,7 +291,7 @@ theorem ContMDiff.extend_one [T2Space M] [One M'] {n : ℕ∞} {U : Opens M} {f rw [extend_comp Subtype.val_injective] exact diff.contMDiffAt -theorem contMDiff_inclusion {n : ℕ∞} {U V : Opens M} (h : U ≤ V) : +theorem contMDiff_inclusion {n : WithTop ℕ∞} {U V : Opens M} (h : U ≤ V) : ContMDiff I I n (Opens.inclusion h : U → V) := by rintro ⟨x, hx : x ∈ U⟩ apply (contDiffWithinAt_localInvariantProp n).liftProp_inclusion @@ -312,17 +313,17 @@ end Inclusion end ChartedSpace -/-! ### Open embeddings and their inverses are smooth -/ +/-! ### Open embeddings and their inverses are `C^n` -/ section -variable {e : M → H} (h : IsOpenEmbedding e) {n : WithTop ℕ} +variable {e : M → H} (h : IsOpenEmbedding e) {n : WithTop ℕ∞} /-- If the `ChartedSpace` structure on a manifold `M` is given by an open embedding `e : M → H`, -then `e` is smooth. -/ +then `e` is `C^n`. -/ lemma contMDiff_isOpenEmbedding [Nonempty M] : haveI := h.singletonChartedSpace; ContMDiff I I n e := by - haveI := h.singleton_smoothManifoldWithCorners (I := I) + haveI := h.isManifold_singleton (I := I) (n := ω) rw [@contMDiff_iff _ _ _ _ _ _ _ _ _ _ h.singletonChartedSpace] use h.continuous intros x y @@ -347,11 +348,11 @@ lemma contMDiff_isOpenEmbedding [Nonempty M] : alias contMDiff_openEmbedding := contMDiff_isOpenEmbedding /-- If the `ChartedSpace` structure on a manifold `M` is given by an open embedding `e : M → H`, -then the inverse of `e` is smooth. -/ +then the inverse of `e` is `C^n`. -/ lemma contMDiffOn_isOpenEmbedding_symm [Nonempty M] : haveI := h.singletonChartedSpace; ContMDiffOn I I n (IsOpenEmbedding.toPartialHomeomorph e h).symm (range e) := by - haveI := h.singleton_smoothManifoldWithCorners (I := I) + haveI := h.isManifold_singleton (I := I) (n := ω) rw [@contMDiffOn_iff] constructor · rw [← h.toPartialHomeomorph_target] @@ -376,7 +377,7 @@ variable [ChartedSpace H M] variable [Nonempty M'] {e' : M' → H'} (h' : IsOpenEmbedding e') /-- Let `M'` be a manifold whose chart structure is given by an open embedding `e'` into its model -space `H'`. Then the smoothness of `e' ∘ f : M → H'` implies the smoothness of `f`. +space `H'`. If `e' ∘ f : M → H'` is `C^n`, then `f` is `C^n`. This is useful, for example, when `e' ∘ f = g ∘ e` for smooth maps `e : M → X` and `g : X → H'`. -/ lemma ContMDiff.of_comp_isOpenEmbedding {f : M → M'} (hf : ContMDiff I I' n (e' ∘ f)) : diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean index 230bbb03463c0..c83d7d410a374 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean @@ -7,14 +7,14 @@ import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners import Mathlib.Geometry.Manifold.LocalInvariantProperties /-! -# Smooth functions between smooth manifolds +# `C^n` functions between manifolds -We define `Cⁿ` functions between smooth manifolds, as functions which are `Cⁿ` in charts, and prove -basic properties of these notions. +We define `Cⁿ` functions between manifolds, as functions which are `Cⁿ` in charts, and prove +basic properties of these notions. Here, `n` can be finite, or `∞`, or `ω`. ## Main definitions and statements -Let `M` and `M'` be two smooth manifolds, with respect to model with corners `I` and `I'`. Let +Let `M` and `M'` be two manifolds, with respect to models with corners `I` and `I'`. Let `f : M → M'`. * `ContMDiffWithinAt I I' n f s x` states that the function `f` is `Cⁿ` within the set `s` @@ -23,9 +23,9 @@ Let `M` and `M'` be two smooth manifolds, with respect to model with corners `I` * `ContMDiffOn I I' n f s` states that the function `f` is `Cⁿ` on the set `s` * `ContMDiff I I' n f` states that the function `f` is `Cⁿ`. -We also give some basic properties of smooth functions between manifolds, following the API of -smooth functions between vector spaces. -See `Basic.lean` for further basic properties of smooth functions between smooth manifolds, +We also give some basic properties of `Cⁿ` functions between manifolds, following the API of +`C^n` functions between vector spaces. +See `Basic.lean` for further basic properties of `Cⁿ` functions between manifolds, `NormedSpace.lean` for the equivalence of manifold-smoothness to usual smoothness, `Product.lean` for smoothness results related to the product of manifolds and `Atlas.lean` for smoothness of atlas members and local structomorphisms. @@ -33,7 +33,7 @@ See `Basic.lean` for further basic properties of smooth functions between smooth ## Implementation details Many properties follow for free from the corresponding properties of functions in vector spaces, -as being `Cⁿ` is a local property invariant under the smooth groupoid. We take advantage of the +as being `Cⁿ` is a local property invariant under the `Cⁿ` groupoid. We take advantage of the general machinery developed in `LocalInvariantProperties.lean` to get these properties automatically. For instance, the fact that being `Cⁿ` does not depend on the chart one considers is given by `liftPropWithinAt_indep_chart`. @@ -44,35 +44,35 @@ in terms of extended charts in `contMDiffOn_iff` and `contMDiff_iff`. -/ -open Set Function Filter ChartedSpace SmoothManifoldWithCorners +open Set Function Filter ChartedSpace IsManifold open scoped Topology Manifold ContDiff -/-! ### Definition of smooth functions between manifolds -/ +/-! ### Definition of `Cⁿ` functions between manifolds -/ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] - -- Prerequisite typeclasses to say that `M` is a smooth manifold over the pair `(E, H)` + -- Prerequisite typeclasses to say that `M` is a manifold over the pair `(E, H)` {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - -- Prerequisite typeclasses to say that `M'` is a smooth manifold over the pair `(E', H')` + -- Prerequisite typeclasses to say that `M'` is a manifold over the pair `(E', H')` {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - -- Prerequisite typeclasses to say that `M''` is a smooth manifold over the pair `(E'', H'')` + -- Prerequisite typeclasses to say that `M''` is a manifold over the pair `(E'', H'')` {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] {H'' : Type*} [TopologicalSpace H''] {I'' : ModelWithCorners 𝕜 E'' H''} {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H'' M''] -- declare functions, sets, points and smoothness indices {e : PartialHomeomorph M H} - {e' : PartialHomeomorph M' H'} {f f₁ : M → M'} {s s₁ t : Set M} {x : M} {m n : ℕ∞} + {e' : PartialHomeomorph M' H'} {f f₁ : M → M'} {s s₁ t : Set M} {x : M} {m n : WithTop ℕ∞} variable (I I') in /-- Property in the model space of a model with corners of being `C^n` within at set at a point, -when read in the model vector space. This property will be lifted to manifolds to define smooth +when read in the model vector space. This property will be lifted to manifolds to define `C^n` functions between manifolds. -/ -def ContDiffWithinAtProp (n : ℕ∞) (f : H → H') (s : Set H) (x : H) : Prop := +def ContDiffWithinAtProp (n : WithTop ℕ∞) (f : H → H') (s : Set H) (x : H) : Prop := ContDiffWithinAt 𝕜 n (I' ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ range I) (I x) theorem contDiffWithinAtProp_self_source {f : E → H'} {s : Set E} {x : E} : @@ -89,11 +89,11 @@ theorem contDiffWithinAtProp_self_target {f : H → E'} {s : Set H} {x : H} : ContDiffWithinAt 𝕜 n (f ∘ I.symm) (I.symm ⁻¹' s ∩ range I) (I x) := Iff.rfl -/-- Being `Cⁿ` in the model space is a local property, invariant under smooth maps. Therefore, -it will lift nicely to manifolds. -/ -theorem contDiffWithinAt_localInvariantProp (n : ℕ∞) : - (contDiffGroupoid ∞ I).LocalInvariantProp (contDiffGroupoid ∞ I') - (ContDiffWithinAtProp I I' n) where +/-- Being `Cⁿ` in the model space is a local property, invariant under `Cⁿ` maps. Therefore, +it lifts nicely to manifolds. -/ +theorem contDiffWithinAt_localInvariantProp_of_le (n m : WithTop ℕ∞) (hmn : m ≤ n) : + (contDiffGroupoid n I).LocalInvariantProp (contDiffGroupoid n I') + (ContDiffWithinAtProp I I' m) where is_local {s x u f} u_open xu := by have : I.symm ⁻¹' (s ∩ u) ∩ range I = I.symm ⁻¹' s ∩ range I ∩ I.symm ⁻¹' u := by simp only [inter_right_comm, preimage_inter] @@ -110,7 +110,7 @@ theorem contDiffWithinAt_localInvariantProp (n : ℕ∞) : rw [this] at h have : I (e x) ∈ I.symm ⁻¹' e.target ∩ range I := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he).2.contDiffWithinAt this - convert (h.comp_inter _ (this.of_le (mod_cast le_top))).mono_of_mem_nhdsWithin _ + convert (h.comp_inter _ (this.of_le hmn)).mono_of_mem_nhdsWithin _ using 1 · ext y; simp only [mfld_simps] refine mem_nhdsWithin.mpr @@ -128,12 +128,19 @@ theorem contDiffWithinAt_localInvariantProp (n : ℕ∞) : have A : (I' ∘ f ∘ I.symm) (I x) ∈ I'.symm ⁻¹' e'.source ∩ range I' := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he').1.contDiffWithinAt A - convert (this.of_le (mod_cast le_top)).comp _ h _ + convert (this.of_le hmn).comp _ h _ · ext y; simp only [mfld_simps] · intro y hy; simp only [mfld_simps] at hy; simpa only [hy, mfld_simps] using hs hy.1 +/-- Being `Cⁿ` in the model space is a local property, invariant under `C^n` maps. Therefore, +it lifts nicely to manifolds. -/ +theorem contDiffWithinAt_localInvariantProp (n : WithTop ℕ∞) : + (contDiffGroupoid n I).LocalInvariantProp (contDiffGroupoid n I') + (ContDiffWithinAtProp I I' n) := + contDiffWithinAt_localInvariantProp_of_le n n le_rfl + theorem contDiffWithinAtProp_mono_of_mem_nhdsWithin - (n : ℕ∞) ⦃s x t⦄ ⦃f : H → H'⦄ (hts : s ∈ 𝓝[t] x) + (n : WithTop ℕ∞) ⦃s x t⦄ ⦃f : H → H'⦄ (hts : s ∈ 𝓝[t] x) (h : ContDiffWithinAtProp I I' n f s x) : ContDiffWithinAtProp I I' n f t x := by refine h.mono_of_mem_nhdsWithin ?_ refine inter_mem ?_ (mem_of_superset self_mem_nhdsWithin inter_subset_right) @@ -153,7 +160,7 @@ variable (I I') in /-- A function is `n` times continuously differentiable within a set at a point in a manifold if it is continuous and it is `n` times continuously differentiable in this set around this point, when read in the preferred chart at this point. -/ -def ContMDiffWithinAt (n : ℕ∞) (f : M → M') (s : Set M) (x : M) := +def ContMDiffWithinAt (n : WithTop ℕ∞) (f : M → M') (s : Set M) (x : M) := LiftPropWithinAt (ContDiffWithinAtProp I I' n) f s x @[deprecated (since := "024-11-21")] alias SmoothWithinAt := ContMDiffWithinAt @@ -162,10 +169,10 @@ variable (I I') in /-- A function is `n` times continuously differentiable at a point in a manifold if it is continuous and it is `n` times continuously differentiable around this point, when read in the preferred chart at this point. -/ -def ContMDiffAt (n : ℕ∞) (f : M → M') (x : M) := +def ContMDiffAt (n : WithTop ℕ∞) (f : M → M') (x : M) := ContMDiffWithinAt I I' n f univ x -theorem contMDiffAt_iff {n : ℕ∞} {f : M → M'} {x : M} : +theorem contMDiffAt_iff {n : WithTop ℕ∞} {f : M → M'} {x : M} : ContMDiffAt I I' n f x ↔ ContinuousAt f x ∧ ContDiffWithinAt 𝕜 n (extChartAt I' (f x) ∘ f ∘ (extChartAt I x).symm) (range I) @@ -178,7 +185,7 @@ variable (I I') in /-- A function is `n` times continuously differentiable in a set of a manifold if it is continuous and, for any pair of points, it is `n` times continuously differentiable on this set in the charts around these points. -/ -def ContMDiffOn (n : ℕ∞) (f : M → M') (s : Set M) := +def ContMDiffOn (n : WithTop ℕ∞) (f : M → M') (s : Set M) := ∀ x ∈ s, ContMDiffWithinAt I I' n f s x @[deprecated (since := "024-11-21")] alias SmoothOn := ContMDiffOn @@ -187,7 +194,7 @@ variable (I I') in /-- A function is `n` times continuously differentiable in a manifold if it is continuous and, for any pair of points, it is `n` times continuously differentiable in the charts around these points. -/ -def ContMDiff (n : ℕ∞) (f : M → M') := +def ContMDiff (n : WithTop ℕ∞) (f : M → M') := ∀ x, ContMDiffAt I I' n f x @[deprecated (since := "024-11-21")] alias Smooth := ContMDiff @@ -209,7 +216,7 @@ theorem ContMDiffOn.of_le (hf : ContMDiffOn I I' n f s) (le : m ≤ n) : ContMDi theorem ContMDiff.of_le (hf : ContMDiff I I' n f) (le : m ≤ n) : ContMDiff I I' m f := fun x => (hf x).of_le le -/-! ### Basic properties of smooth functions between manifolds -/ +/-! ### Basic properties of `C^n` functions between manifolds -/ @[deprecated (since := "2024-11-20")] alias ContMDiff.smooth := ContMDiff.of_le @@ -244,8 +251,8 @@ theorem contMDiffOn_univ : ContMDiffOn I I' n f univ ↔ ContMDiff I I' n f := b @[deprecated (since := "2024-11-20")] alias smoothOn_univ := contMDiffOn_univ -/-- One can reformulate smoothness within a set at a point as continuity within this set at this -point, and smoothness in the corresponding extended chart. -/ +/-- One can reformulate being `C^n` within a set at a point as continuity within this set at this +point, and being `C^n` in the corresponding extended chart. -/ theorem contMDiffWithinAt_iff : ContMDiffWithinAt I I' n f s x ↔ ContinuousWithinAt f s x ∧ @@ -253,8 +260,8 @@ theorem contMDiffWithinAt_iff : ((extChartAt I x).symm ⁻¹' s ∩ range I) (extChartAt I x x) := by simp_rw [ContMDiffWithinAt, liftPropWithinAt_iff']; rfl -/-- One can reformulate smoothness within a set at a point as continuity within this set at this -point, and smoothness in the corresponding extended chart. This form states smoothness of `f` +/-- One can reformulate being `Cⁿ` within a set at a point as continuity within this set at this +point, and being `Cⁿ` in the corresponding extended chart. This form states regularity of `f` written in such a way that the set is restricted to lie within the domain/codomain of the corresponding charts. Even though this expression is more complicated than the one in `contMDiffWithinAt_iff`, it is @@ -272,8 +279,8 @@ theorem contMDiffWithinAt_iff' : exact and_congr_right fun hc => contDiffWithinAt_congr_set <| hc.extChartAt_symm_preimage_inter_range_eventuallyEq -/-- One can reformulate smoothness within a set at a point as continuity within this set at this -point, and smoothness in the corresponding extended chart in the target. -/ +/-- One can reformulate being `Cⁿ` within a set at a point as continuity within this set at this +point, and being `Cⁿ` in the corresponding extended chart in the target. -/ theorem contMDiffWithinAt_iff_target : ContMDiffWithinAt I I' n f s x ↔ ContinuousWithinAt f s x ∧ ContMDiffWithinAt I 𝓘(𝕜, E') n (extChartAt I' (f x) ∘ f) s x := by @@ -300,10 +307,10 @@ theorem contMDiffAt_iff_target {x : M} : @[deprecated (since := "2024-11-20")] alias smoothAt_iff_target := contMDiffAt_iff_target -section SmoothManifoldWithCorners +section IsManifold theorem contMDiffWithinAt_iff_source_of_mem_maximalAtlas - [SmoothManifoldWithCorners I M] (he : e ∈ maximalAtlas I M) (hx : x ∈ e.source) : + [IsManifold I n M] (he : e ∈ maximalAtlas I n M) (hx : x ∈ e.source) : ContMDiffWithinAt I I' n f s x ↔ ContMDiffWithinAt 𝓘(𝕜, E) I' n (f ∘ (e.extend I).symm) ((e.extend I).symm ⁻¹' s ∩ range I) (e.extend I x) := by @@ -316,20 +323,20 @@ theorem contMDiffWithinAt_iff_source_of_mem_maximalAtlas rfl theorem contMDiffWithinAt_iff_source_of_mem_source - [SmoothManifoldWithCorners I M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : + [IsManifold I n M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : ContMDiffWithinAt I I' n f s x' ↔ ContMDiffWithinAt 𝓘(𝕜, E) I' n (f ∘ (extChartAt I x).symm) ((extChartAt I x).symm ⁻¹' s ∩ range I) (extChartAt I x x') := contMDiffWithinAt_iff_source_of_mem_maximalAtlas (chart_mem_maximalAtlas x) hx' theorem contMDiffAt_iff_source_of_mem_source - [SmoothManifoldWithCorners I M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : + [IsManifold I n M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : ContMDiffAt I I' n f x' ↔ ContMDiffWithinAt 𝓘(𝕜, E) I' n (f ∘ (extChartAt I x).symm) (range I) (extChartAt I x x') := by simp_rw [ContMDiffAt, contMDiffWithinAt_iff_source_of_mem_source hx', preimage_univ, univ_inter] theorem contMDiffWithinAt_iff_target_of_mem_source - [SmoothManifoldWithCorners I' M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : + [IsManifold I' n M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : ContMDiffWithinAt I I' n f s x ↔ ContinuousWithinAt f s x ∧ ContMDiffWithinAt I 𝓘(𝕜, E') n (extChartAt I' y ∘ f) s x := by simp_rw [ContMDiffWithinAt] @@ -344,16 +351,16 @@ theorem contMDiffWithinAt_iff_target_of_mem_source rfl theorem contMDiffAt_iff_target_of_mem_source - [SmoothManifoldWithCorners I' M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : + [IsManifold I' n M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : ContMDiffAt I I' n f x ↔ ContinuousAt f x ∧ ContMDiffAt I 𝓘(𝕜, E') n (extChartAt I' y ∘ f) x := by rw [ContMDiffAt, contMDiffWithinAt_iff_target_of_mem_source hy, continuousWithinAt_univ, ContMDiffAt] -variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] +variable [IsManifold I n M] [IsManifold I' n M'] -theorem contMDiffWithinAt_iff_of_mem_maximalAtlas {x : M} (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hx : x ∈ e.source) (hy : f x ∈ e'.source) : +theorem contMDiffWithinAt_iff_of_mem_maximalAtlas {x : M} (he : e ∈ maximalAtlas I n M) + (he' : e' ∈ maximalAtlas I' n M') (hx : x ∈ e.source) (hy : f x ∈ e'.source) : ContMDiffWithinAt I I' n f s x ↔ ContinuousWithinAt f s x ∧ ContDiffWithinAt 𝕜 n (e'.extend I' ∘ f ∘ (e.extend I).symm) @@ -362,8 +369,9 @@ theorem contMDiffWithinAt_iff_of_mem_maximalAtlas {x : M} (he : e ∈ maximalAtl /-- An alternative formulation of `contMDiffWithinAt_iff_of_mem_maximalAtlas` if the set if `s` lies in `e.source`. -/ -theorem contMDiffWithinAt_iff_image {x : M} (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hs : s ⊆ e.source) (hx : x ∈ e.source) (hy : f x ∈ e'.source) : +theorem contMDiffWithinAt_iff_image {x : M} (he : e ∈ maximalAtlas I n M) + (he' : e' ∈ maximalAtlas I' n M') + (hs : s ⊆ e.source) (hx : x ∈ e.source) (hy : f x ∈ e'.source) : ContMDiffWithinAt I I' n f s x ↔ ContinuousWithinAt f s x ∧ ContDiffWithinAt 𝕜 n (e'.extend I' ∘ f ∘ (e.extend I).symm) (e.extend I '' s) @@ -372,8 +380,8 @@ theorem contMDiffWithinAt_iff_image {x : M} (he : e ∈ maximalAtlas I M) refine fun _ => contDiffWithinAt_congr_set ?_ simp_rw [e.extend_symm_preimage_inter_range_eventuallyEq hs hx] -/-- One can reformulate smoothness within a set at a point as continuity within this set at this -point, and smoothness in any chart containing that point. -/ +/-- One can reformulate being `C^n` within a set at a point as continuity within this set at this +point, and being `C^n` in any chart containing that point. -/ theorem contMDiffWithinAt_iff_of_mem_source {x' : M} {y : M'} (hx : x' ∈ (chartAt H x).source) (hy : f x' ∈ (chartAt H' y).source) : ContMDiffWithinAt I I' n f s x' ↔ @@ -410,23 +418,23 @@ theorem contMDiffAt_iff_of_mem_source {x' : M} {y : M'} (hx : x' ∈ (chartAt H (contMDiffWithinAt_iff_of_mem_source hx hy).trans <| by rw [continuousWithinAt_univ, preimage_univ, univ_inter] -theorem contMDiffOn_iff_of_mem_maximalAtlas (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : +theorem contMDiffOn_iff_of_mem_maximalAtlas (he : e ∈ maximalAtlas I n M) + (he' : e' ∈ maximalAtlas I' n M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : ContMDiffOn I I' n f s ↔ ContinuousOn f s ∧ ContDiffOn 𝕜 n (e'.extend I' ∘ f ∘ (e.extend I).symm) (e.extend I '' s) := by simp_rw [ContinuousOn, ContDiffOn, Set.forall_mem_image, ← forall_and, ContMDiffOn] exact forall₂_congr fun x hx => contMDiffWithinAt_iff_image he he' hs (hs hx) (h2s hx) -theorem contMDiffOn_iff_of_mem_maximalAtlas' (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : +theorem contMDiffOn_iff_of_mem_maximalAtlas' (he : e ∈ maximalAtlas I n M) + (he' : e' ∈ maximalAtlas I' n M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : ContMDiffOn I I' n f s ↔ ContDiffOn 𝕜 n (e'.extend I' ∘ f ∘ (e.extend I).symm) (e.extend I '' s) := (contMDiffOn_iff_of_mem_maximalAtlas he he' hs h2s).trans <| and_iff_right_of_imp fun h ↦ (e.continuousOn_writtenInExtend_iff hs h2s).1 h.continuousOn -/-- If the set where you want `f` to be smooth lies entirely in a single chart, and `f` maps it - into a single chart, the smoothness of `f` on that set can be expressed by purely looking in +/-- If the set where you want `f` to be `C^n` lies entirely in a single chart, and `f` maps it + into a single chart, the fact that `f` is `C^n` on that set can be expressed by purely looking in these charts. Note: this lemma uses `extChartAt I x '' s` instead of `(extChartAt I x).symm ⁻¹' s` to ensure that this set lies in `(extChartAt I x).target`. -/ @@ -438,8 +446,8 @@ theorem contMDiffOn_iff_of_subset_source {x : M} {y : M'} (hs : s ⊆ (chartAt H contMDiffOn_iff_of_mem_maximalAtlas (chart_mem_maximalAtlas x) (chart_mem_maximalAtlas y) hs h2s -/-- If the set where you want `f` to be smooth lies entirely in a single chart, and `f` maps it - into a single chart, the smoothness of `f` on that set can be expressed by purely looking in +/-- If the set where you want `f` to be `C^n` lies entirely in a single chart, and `f` maps it + into a single chart, the fact that `f` is `C^n` on that set can be expressed by purely looking in these charts. Note: this lemma uses `extChartAt I x '' s` instead of `(extChartAt I x).symm ⁻¹' s` to ensure that this set lies in `(extChartAt I x).target`. -/ @@ -451,7 +459,7 @@ theorem contMDiffOn_iff_of_subset_source' {x : M} {y : M'} (hs : s ⊆ (extChart exact contMDiffOn_iff_of_mem_maximalAtlas' (chart_mem_maximalAtlas x) (chart_mem_maximalAtlas y) hs h2s -/-- One can reformulate smoothness on a set as continuity on this set, and smoothness in any +/-- One can reformulate being `C^n` on a set as continuity on this set, and being `C^n` in any extended chart. -/ theorem contMDiffOn_iff : ContMDiffOn I I' n f s ↔ @@ -485,7 +493,7 @@ theorem contMDiffOn_zero_iff : rw [contMDiffOn_iff] refine ⟨fun h ↦ h.1, fun h ↦ ⟨h, ?_⟩⟩ intro x y - rw [WithTop.coe_zero, contDiffOn_zero] + rw [contDiffOn_zero] apply (continuousOn_extChartAt _).comp · apply h.comp ((continuousOn_extChartAt_symm _).mono inter_subset_left) (fun z hz ↦ ?_) simp only [preimage_inter, mem_inter_iff, mem_preimage] at hz @@ -494,7 +502,7 @@ theorem contMDiffOn_zero_iff : simp only [preimage_inter, mem_inter_iff, mem_preimage] at hz exact hz.2.2 -/-- One can reformulate smoothness on a set as continuity on this set, and smoothness in any +/-- One can reformulate being `C^n` on a set as continuity on this set, and being `C^n` in any extended chart in the target. -/ theorem contMDiffOn_iff_target : ContMDiffOn I I' n f s ↔ @@ -517,7 +525,7 @@ theorem contMDiffOn_iff_target : @[deprecated (since := "2024-11-20")] alias smoothOn_iff_target := contMDiffOn_iff_target -/-- One can reformulate smoothness as continuity and smoothness in any extended chart. -/ +/-- One can reformulate being `C^n` as continuity and being `C^n` in any extended chart. -/ theorem contMDiff_iff : ContMDiff I I' n f ↔ Continuous f ∧ @@ -527,7 +535,7 @@ theorem contMDiff_iff : (extChartAt I x).symm ⁻¹' (f ⁻¹' (extChartAt I' y).source)) := by simp [← contMDiffOn_univ, contMDiffOn_iff, continuous_iff_continuousOn_univ] -/-- One can reformulate smoothness as continuity and smoothness in any extended chart in the +/-- One can reformulate being `C^n` as continuity and being `C^n` in any extended chart in the target. -/ theorem contMDiff_iff_target : ContMDiff I I' n f ↔ @@ -545,26 +553,26 @@ theorem contMDiff_zero_iff : ContMDiff I I' 0 f ↔ Continuous f := by rw [← contMDiffOn_univ, continuous_iff_continuousOn_univ, contMDiffOn_zero_iff] -end SmoothManifoldWithCorners +end IsManifold -/-! ### Deducing smoothness from smoothness one step beyond -/ +/-! ### `C^(n+1)` functions are `C^n` -/ -theorem ContMDiffWithinAt.of_succ {n : ℕ} (h : ContMDiffWithinAt I I' n.succ f s x) : +theorem ContMDiffWithinAt.of_succ (h : ContMDiffWithinAt I I' (n + 1) f s x) : ContMDiffWithinAt I I' n f s x := - h.of_le (WithTop.coe_le_coe.2 (Nat.le_succ n)) + h.of_le le_self_add -theorem ContMDiffAt.of_succ {n : ℕ} (h : ContMDiffAt I I' n.succ f x) : ContMDiffAt I I' n f x := +theorem ContMDiffAt.of_succ (h : ContMDiffAt I I' (n + 1) f x) : ContMDiffAt I I' n f x := ContMDiffWithinAt.of_succ h -theorem ContMDiffOn.of_succ {n : ℕ} (h : ContMDiffOn I I' n.succ f s) : ContMDiffOn I I' n f s := +theorem ContMDiffOn.of_succ (h : ContMDiffOn I I' (n + 1) f s) : ContMDiffOn I I' n f s := fun x hx => (h x hx).of_succ -theorem ContMDiff.of_succ {n : ℕ} (h : ContMDiff I I' n.succ f) : ContMDiff I I' n f := fun x => +theorem ContMDiff.of_succ (h : ContMDiff I I' (n + 1) f) : ContMDiff I I' n f := fun x => (h x).of_succ -/-! ### Deducing continuity from smoothness -/ +/-! ### `C^n` functions are continuous -/ theorem ContMDiffWithinAt.continuousWithinAt (hf : ContMDiffWithinAt I I' n f s x) : ContinuousWithinAt f s x := @@ -579,27 +587,36 @@ theorem ContMDiffOn.continuousOn (hf : ContMDiffOn I I' n f s) : ContinuousOn f theorem ContMDiff.continuous (hf : ContMDiff I I' n f) : Continuous f := continuous_iff_continuousAt.2 fun x => (hf x).continuousAt -/-! ### `C^∞` smoothness -/ +/-! ### `C^∞` functions -/ -theorem contMDiffWithinAt_top : - ContMDiffWithinAt I I' ⊤ f s x ↔ ∀ n : ℕ, ContMDiffWithinAt I I' n f s x := +theorem contMDiffWithinAt_infty : + ContMDiffWithinAt I I' ∞ f s x ↔ ∀ n : ℕ, ContMDiffWithinAt I I' n f s x := ⟨fun h n => ⟨h.1, contDiffWithinAt_infty.1 h.2 n⟩, fun H => ⟨(H 0).1, contDiffWithinAt_infty.2 fun n => (H n).2⟩⟩ -theorem contMDiffAt_top : ContMDiffAt I I' ⊤ f x ↔ ∀ n : ℕ, ContMDiffAt I I' n f x := - contMDiffWithinAt_top +@[deprecated (since := "2025-01-09")] alias contMDiffWithinAt_top := contMDiffWithinAt_infty + +theorem contMDiffAt_infty : ContMDiffAt I I' ∞ f x ↔ ∀ n : ℕ, ContMDiffAt I I' n f x := + contMDiffWithinAt_infty + +@[deprecated (since := "2025-01-09")] alias contMDiffAt_top := contMDiffAt_infty + +theorem contMDiffOn_infty : ContMDiffOn I I' ∞ f s ↔ ∀ n : ℕ, ContMDiffOn I I' n f s := + ⟨fun h _ => h.of_le (mod_cast le_top), + fun h x hx => contMDiffWithinAt_infty.2 fun n => h n x hx⟩ -theorem contMDiffOn_top : ContMDiffOn I I' ⊤ f s ↔ ∀ n : ℕ, ContMDiffOn I I' n f s := - ⟨fun h _ => h.of_le le_top, fun h x hx => contMDiffWithinAt_top.2 fun n => h n x hx⟩ +@[deprecated (since := "2025-01-09")] alias contMDiffOn_top := contMDiffOn_infty -theorem contMDiff_top : ContMDiff I I' ⊤ f ↔ ∀ n : ℕ, ContMDiff I I' n f := - ⟨fun h _ => h.of_le le_top, fun h x => contMDiffWithinAt_top.2 fun n => h n x⟩ +theorem contMDiff_infty : ContMDiff I I' ∞ f ↔ ∀ n : ℕ, ContMDiff I I' n f := + ⟨fun h _ => h.of_le (mod_cast le_top), fun h x => contMDiffWithinAt_infty.2 fun n => h n x⟩ -theorem contMDiffWithinAt_iff_nat : +@[deprecated (since := "2025-01-09")] alias contMDiff_top := contMDiff_infty + +theorem contMDiffWithinAt_iff_nat {n : ℕ∞} : ContMDiffWithinAt I I' n f s x ↔ ∀ m : ℕ, (m : ℕ∞) ≤ n → ContMDiffWithinAt I I' m f s x := by - refine ⟨fun h m hm => h.of_le hm, fun h => ?_⟩ + refine ⟨fun h m hm => h.of_le (mod_cast hm), fun h => ?_⟩ cases' n with n - · exact contMDiffWithinAt_top.2 fun n => h n le_top + · exact contMDiffWithinAt_infty.2 fun n => h n le_top · exact h n le_rfl /-! ### Restriction to a smaller set -/ @@ -685,8 +702,8 @@ protected theorem ContMDiffOn.contMDiffAt (h : ContMDiffOn I I' n f s) (hx : s @[deprecated (since := "2024-11-20")] alias SmoothOn.smoothAt := ContMDiffOn.contMDiffAt -theorem contMDiffOn_iff_source_of_mem_maximalAtlas [SmoothManifoldWithCorners I M] - (he : e ∈ maximalAtlas I M) (hs : s ⊆ e.source) : +theorem contMDiffOn_iff_source_of_mem_maximalAtlas [IsManifold I n M] + (he : e ∈ maximalAtlas I n M) (hs : s ⊆ e.source) : ContMDiffOn I I' n f s ↔ ContMDiffOn 𝓘(𝕜, E) I' n (f ∘ (e.extend I).symm) (e.extend I '' s) := by simp_rw [ContMDiffOn, Set.forall_mem_image] @@ -696,10 +713,10 @@ theorem contMDiffOn_iff_source_of_mem_maximalAtlas [SmoothManifoldWithCorners I simp_rw [e.extend_symm_preimage_inter_range_eventuallyEq hs (hs hx)] -- Porting note: didn't compile; fixed by golfing the proof and moving parts to lemmas -/-- A function is `C^n` within a set at a point, for `n : ℕ`, if and only if it is `C^n` on -a neighborhood of this point. -/ +/-- A function is `C^n` within a set at a point, for `n : ℕ` or `n = ω`, +if and only if it is `C^n` on a neighborhood of this point. -/ theorem contMDiffWithinAt_iff_contMDiffOn_nhds - [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] {n : ℕ} : + [IsManifold I n M] [IsManifold I' n M'] (hn : n ≠ ∞) : ContMDiffWithinAt I I' n f s x ↔ ∃ u ∈ 𝓝[insert x s] x, ContMDiffOn I I' n f u := by -- WLOG, `x ∈ s`, otherwise we add `x` to `s` wlog hxs : x ∈ s generalizing s @@ -709,8 +726,8 @@ theorem contMDiffWithinAt_iff_contMDiffOn_nhds refine ⟨fun h ↦ ?_, fun ⟨u, hmem, hu⟩ ↦ (hu _ (mem_of_mem_nhdsWithin hxs hmem)).mono_of_mem_nhdsWithin hmem⟩ -- The property is true in charts. Let `v` be a good neighborhood in the chart where the function - -- is smooth. - rcases (contMDiffWithinAt_iff'.1 h).2.contDiffOn le_rfl (by simp) with ⟨v, hmem, hsub, hv⟩ + -- is `Cⁿ`. + rcases (contMDiffWithinAt_iff'.1 h).2.contDiffOn le_rfl (by simp [hn]) with ⟨v, hmem, hsub, hv⟩ have hxs' : extChartAt I x x ∈ (extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' (s ∩ f ⁻¹' (extChartAt I' (f x)).source) := ⟨(extChartAt I x).map_source (mem_extChartAt_source _), by rwa [extChartAt_to_inv], by @@ -730,42 +747,50 @@ theorem contMDiffWithinAt_iff_contMDiffOn_nhds exact hsub.trans inter_subset_left /-- If a function is `C^m` within a set at a point, for some finite `m`, then it is `C^m` within -this set on an open set around the basepoint. --/ +this set on an open set around the basepoint. -/ theorem ContMDiffWithinAt.contMDiffOn' - [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] - {m : ℕ} (hm : (m : ℕ∞) ≤ n) + [IsManifold I n M] [IsManifold I' n M'] + (hm : m ≤ n) (h' : m = ∞ → n = ω) (h : ContMDiffWithinAt I I' n f s x) : ∃ u, IsOpen u ∧ x ∈ u ∧ ContMDiffOn I I' m f (insert x s ∩ u) := by - rcases contMDiffWithinAt_iff_contMDiffOn_nhds.1 (h.of_le hm) with ⟨t, ht, h't⟩ - rcases mem_nhdsWithin.1 ht with ⟨u, u_open, xu, hu⟩ - rw [inter_comm] at hu - exact ⟨u, u_open, xu, h't.mono hu⟩ + have : IsManifold I m M := .of_le hm + have : IsManifold I' m M' := .of_le hm + match m with + | (m : ℕ) | ω => + rcases (contMDiffWithinAt_iff_contMDiffOn_nhds (by simp)).1 (h.of_le hm) with ⟨t, ht, h't⟩ + rcases mem_nhdsWithin.1 ht with ⟨u, u_open, xu, hu⟩ + rw [inter_comm] at hu + exact ⟨u, u_open, xu, h't.mono hu⟩ + | ∞ => + rcases (contMDiffWithinAt_iff_contMDiffOn_nhds (by simp [h'])).1 h with ⟨t, ht, h't⟩ + rcases mem_nhdsWithin.1 ht with ⟨u, u_open, xu, hu⟩ + rw [inter_comm] at hu + exact ⟨u, u_open, xu, (h't.mono hu).of_le hm⟩ /-- If a function is `C^m` within a set at a point, for some finite `m`, then it is `C^m` within this set on a neighborhood of the basepoint. -/ theorem ContMDiffWithinAt.contMDiffOn - [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] - {m : ℕ} (hm : (m : ℕ∞) ≤ n) + [IsManifold I n M] [IsManifold I' n M'] + (hm : m ≤ n) (h' : m = ∞ → n = ω) (h : ContMDiffWithinAt I I' n f s x) : ∃ u ∈ 𝓝[insert x s] x, u ⊆ insert x s ∧ ContMDiffOn I I' m f u := by - let ⟨_u, uo, xu, h⟩ := h.contMDiffOn' hm + let ⟨_u, uo, xu, h⟩ := h.contMDiffOn' hm h' exact ⟨_, inter_mem_nhdsWithin _ (uo.mem_nhds xu), inter_subset_left, h⟩ /-- A function is `C^n` at a point, for `n : ℕ`, if and only if it is `C^n` on a neighborhood of this point. -/ theorem contMDiffAt_iff_contMDiffOn_nhds - [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] {n : ℕ} : + [IsManifold I n M] [IsManifold I' n M'] (hn : n ≠ ∞) : ContMDiffAt I I' n f x ↔ ∃ u ∈ 𝓝 x, ContMDiffOn I I' n f u := by - simp [← contMDiffWithinAt_univ, contMDiffWithinAt_iff_contMDiffOn_nhds, nhdsWithin_univ] + simp [← contMDiffWithinAt_univ, contMDiffWithinAt_iff_contMDiffOn_nhds hn, nhdsWithin_univ] /-- Note: This does not hold for `n = ∞`. `f` being `C^∞` at `x` means that for every `n`, `f` is `C^n` on some neighborhood of `x`, but this neighborhood can depend on `n`. -/ theorem contMDiffAt_iff_contMDiffAt_nhds - [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] {n : ℕ} : + [IsManifold I n M] [IsManifold I' n M'] (hn : n ≠ ∞) : ContMDiffAt I I' n f x ↔ ∀ᶠ x' in 𝓝 x, ContMDiffAt I I' n f x' := by refine ⟨?_, fun h => h.self_of_nhds⟩ - rw [contMDiffAt_iff_contMDiffOn_nhds] + rw [contMDiffAt_iff_contMDiffOn_nhds hn] rintro ⟨u, hu, h⟩ refine (eventually_mem_nhds_iff.mpr hu).mono fun x' hx' => ?_ exact (h x' <| mem_of_mem_nhds hx').contMDiffAt hx' @@ -773,11 +798,11 @@ theorem contMDiffAt_iff_contMDiffAt_nhds /-- Note: This does not hold for `n = ∞`. `f` being `C^∞` at `x` means that for every `n`, `f` is `C^n` on some neighborhood of `x`, but this neighborhood can depend on `n`. -/ theorem contMDiffWithinAt_iff_contMDiffWithinAt_nhdsWithin - [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] {n : ℕ} : + [IsManifold I n M] [IsManifold I' n M'] (hn : n ≠ ∞) : ContMDiffWithinAt I I' n f s x ↔ ∀ᶠ x' in 𝓝[insert x s] x, ContMDiffWithinAt I I' n f s x' := by refine ⟨?_, fun h ↦ mem_of_mem_nhdsWithin (mem_insert x s) h⟩ - rw [contMDiffWithinAt_iff_contMDiffOn_nhds] + rw [contMDiffWithinAt_iff_contMDiffOn_nhds hn] rintro ⟨u, hu, h⟩ filter_upwards [hu, eventually_mem_nhdsWithin_iff.mpr hu] with x' h'x' hx' apply (h x' h'x').mono_of_mem_nhdsWithin diff --git a/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean b/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean index e11bb6f43fe1c..b885cfe9da077 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean @@ -31,7 +31,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] [NormedSpace 𝕜 F₂] {F₃ : Type*} [NormedAddCommGroup F₃] [NormedSpace 𝕜 F₃] {F₄ : Type*} [NormedAddCommGroup F₄] [NormedSpace 𝕜 F₄] -- declare functions, sets, points and smoothness indices - {s : Set M} {x : M} {n : ℕ∞} + {s : Set M} {x : M} {n : WithTop ℕ∞} section Module diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Product.lean b/Mathlib/Geometry/Manifold/ContMDiff/Product.lean index 5562db2312500..1b65f86ca26e9 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Product.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Product.lean @@ -9,13 +9,13 @@ import Mathlib.Geometry.Manifold.ContMDiff.Basic ## Smoothness of standard maps associated to the product of manifolds This file contains results about smoothness of standard maps associated to products of manifolds -- if `f` and `g` are smooth, so is their point-wise product. +- if `f` and `g` are `C^n`, so is their point-wise product. - the component projections from a product of manifolds are smooth. -- functions into a product (*pi type*) are smooth iff their components are +- functions into a product (*pi type*) are `C^n` iff their components are -/ -open Set Function Filter ChartedSpace SmoothManifoldWithCorners +open Set Function Filter ChartedSpace IsManifold open scoped Topology Manifold @@ -40,7 +40,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {F₁ : Type*} [NormedAddCommGroup F₁] [NormedSpace 𝕜 F₁] {F₂ : Type*} [NormedAddCommGroup F₂] [NormedSpace 𝕜 F₂] -- declare functions, sets, points and smoothness indices - {f : M → M'} {s : Set M} {x : M} {n : ℕ∞} + {f : M → M'} {s : Set M} {x : M} {n : WithTop ℕ∞} section ProdMk @@ -309,7 +309,7 @@ end prodMap section PiSpace /-! -### Smoothness of functions with codomain `Π i, F i` +### Regularity of functions with codomain `Π i, F i` We have no `ModelWithCorners.pi` yet, so we prove lemmas about functions `f : M → Π i, F i` and use `𝓘(𝕜, Π i, F i)` as the model space. diff --git a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean index e8a0505d2e9d8..05899ea8e11ac 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean @@ -21,14 +21,14 @@ and related notions. of a `Cⁿ` function is `Cᵐ` when `m + 1 ≤ n`. -/ -open Set Function Filter ChartedSpace SmoothManifoldWithCorners Bundle +open Set Function Filter ChartedSpace IsManifold Bundle open scoped Topology Manifold Bundle -/-! ### Definition of smooth functions between manifolds -/ +/-! ### Definition of `C^n` functions between manifolds -/ -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {m n : WithTop ℕ∞} -- declare a charted space `M` over the pair `(E, H)`. {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] @@ -37,26 +37,25 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - -- declare a smooth manifold `N` over the pair `(F, G)`. + -- declare a `C^n` manifold `N` over the pair `(F, G)`. {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type*} [TopologicalSpace G] {J : ModelWithCorners 𝕜 F G} {N : Type*} [TopologicalSpace N] [ChartedSpace G N] - [Js : SmoothManifoldWithCorners J N] + [Js : IsManifold J n N] -- declare a charted space `N'` over the pair `(F', G')`. {F' : Type*} [NormedAddCommGroup F'] [NormedSpace 𝕜 F'] {G' : Type*} [TopologicalSpace G'] {J' : ModelWithCorners 𝕜 F' G'} {N' : Type*} [TopologicalSpace N'] [ChartedSpace G' N'] - -- declare functions, sets, points and smoothness indices - {f : M → M'} - {s : Set M} {m n : ℕ∞} + -- declare functions, sets + {f : M → M'} {s : Set M} --- Porting note: section about deducing differentiability from smoothness moved to +-- Porting note: section about deducing differentiability for `C^n` functions moved to -- `Geometry.Manifold.MFDeriv.Basic` -/-! ### The derivative of a smooth function is smooth -/ +/-! ### The derivative of a `C^(n+1)` function is `C^n` -/ section mfderiv -variable [Is : SmoothManifoldWithCorners I M] [I's : SmoothManifoldWithCorners I' M'] +variable [Is : IsManifold I n M] [I's : IsManifold I' n M'] /-- The function that sends `x` to the `y`-derivative of `f (x, y)` at `g (x)` is `C^m` at `x₀`, where the derivative is taken as a continuous linear map. @@ -69,9 +68,15 @@ protected theorem ContMDiffWithinAt.mfderivWithin {x₀ : N} {f : N → M → M' (hf : ContMDiffWithinAt (J.prod I) I' n (Function.uncurry f) (t ×ˢ u) (x₀, g x₀)) (hg : ContMDiffWithinAt J I m g t x₀) (hx₀ : x₀ ∈ t) (hu : MapsTo g t u) (hmn : m + 1 ≤ n) (h'u : UniqueMDiffOn I u) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiffWithinAt J 𝓘(𝕜, E →L[𝕜] E') m (inTangentCoordinates I I' g (fun x => f x (g x)) (fun x => mfderivWithin I I' (f x) u (g x)) x₀) t x₀ := by + have : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + have : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) + have : IsManifold J 1 N := .of_le (le_trans le_add_self hmn) + have : IsManifold J m N := .of_le (le_trans le_self_add hmn) -- first localize the result to a smaller set, to make sure everything happens in chart domains let t' := t ∩ g ⁻¹' ((extChartAt I (g x₀)).source) have ht't : t' ⊆ t := inter_subset_left @@ -89,7 +94,7 @@ protected theorem ContMDiffWithinAt.mfderivWithin {x₀ : N} {f : N → M → M' refine ContinuousWithinAt.comp hf.continuousWithinAt ?_ (fun y hy ↦ by simp [hy, hu hy]) exact (continuousWithinAt_id.prod hg.continuousWithinAt) have h4f := h4f.preimage_mem_nhdsWithin (extChartAt_source_mem_nhds (I := I') (f x₀ (g x₀))) - have h3f := contMDiffWithinAt_iff_contMDiffWithinAt_nhdsWithin.mp + have h3f := (contMDiffWithinAt_iff_contMDiffWithinAt_nhdsWithin (by simp)).mp (hf.of_le <| (self_le_add_left 1 m).trans hmn) simp only [Nat.cast_one, hx₀gx₀, insert_eq_of_mem] at h3f have h2f : ∀ᶠ x₂ in 𝓝[t] x₀, ContMDiffWithinAt I I' 1 (f x₂) u (g x₂) := by @@ -101,7 +106,7 @@ protected theorem ContMDiffWithinAt.mfderivWithin {x₀ : N} {f : N → M → M' have h2g : g ⁻¹' (extChartAt I (g x₀)).source ∈ 𝓝[t] x₀ := hg.continuousWithinAt.preimage_mem_nhdsWithin (extChartAt_source_mem_nhds (g x₀)) -- key point: the derivative of `f` composed with extended charts, at the point `g x` read in the - -- chart, is smooth in the vector space sense. This follows from `ContDiffWithinAt.fderivWithin`, + -- chart, is `C^n` in the vector space sense. This follows from `ContDiffWithinAt.fderivWithin`, -- which is the vector space analogue of the result we are proving. have : ContDiffWithinAt 𝕜 m (fun x ↦ fderivWithin 𝕜 (extChartAt I' (f x₀ (g x₀)) ∘ f ((extChartAt J x₀).symm x) ∘ (extChartAt I (g x₀)).symm) @@ -133,7 +138,7 @@ protected theorem ContMDiffWithinAt.mfderivWithin {x₀ : N} {f : N → M → M' · simp · exact hg'.2 · exact UniqueMDiffOn.uniqueDiffOn_target_inter h'u (g x₀) - -- reformulate the previous point as smoothness in the manifold sense (but still for a map between + -- reformulate the previous point as `C^n` in the manifold sense (but still for a map between -- vector spaces) have : ContMDiffWithinAt J 𝓘(𝕜, E →L[𝕜] E') m @@ -145,7 +150,7 @@ protected theorem ContMDiffWithinAt.mfderivWithin {x₀ : N} {f : N → M → M' contMDiffWithinAt_iff_contDiffWithinAt, Function.comp_def] at this ⊢ exact this -- finally, argue that the map we control in the previous point coincides locally with the map we - -- want to prove the smoothness of, so smoothness of the latter follows from smoothness of the + -- want to prove the regularity of, so regularity of the latter follows from regularity of the -- former. apply this.congr_of_eventuallyEq_of_mem _ (by simp [t', hx₀]) apply nhdsWithin_mono _ ht't @@ -198,6 +203,8 @@ parameters and `g = id`. theorem ContMDiffWithinAt.mfderivWithin_const {x₀ : M} {f : M → M'} (hf : ContMDiffWithinAt I I' n f s x₀) (hmn : m + 1 ≤ n) (hx : x₀ ∈ s) (hs : UniqueMDiffOn I s) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiffWithinAt I 𝓘(𝕜, E →L[𝕜] E') m (inTangentCoordinates I I' id f (mfderivWithin I I' f s) x₀) s x₀ := by have : ContMDiffWithinAt (I.prod I) I' n (fun x : M × M => f x.2) (s ×ˢ s) (x₀, x₀) := @@ -218,6 +225,8 @@ theorem ContMDiffWithinAt.mfderivWithin_apply {x₀ : N'} (hg : ContMDiffWithinAt J I m g t (g₁ x₀)) (hg₁ : ContMDiffWithinAt J' J m g₁ v x₀) (hg₂ : ContMDiffWithinAt J' 𝓘(𝕜, E) m g₂ v x₀) (hmn : m + 1 ≤ n) (h'g₁ : MapsTo g₁ v t) (hg₁x₀ : g₁ x₀ ∈ t) (h'g : MapsTo g t u) (hu : UniqueMDiffOn I u) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiffWithinAt J' 𝓘(𝕜, E') m (fun x => (inTangentCoordinates I I' g (fun x => f x (g x)) (fun x => mfderivWithin I I' (f x) u (g x)) (g₁ x₀) (g₁ x)) (g₂ x)) v x₀ := @@ -227,12 +236,14 @@ theorem ContMDiffWithinAt.mfderivWithin_apply {x₀ : N'} where the derivative is taken as a continuous linear map. We have to assume that `f` is `C^n` at `(x₀, g(x₀))` for `n ≥ m + 1` and `g` is `C^m` at `x₀`. We have to insert a coordinate change from `x₀` to `x` to make the derivative sensible. -This result is used to show that maps into the 1-jet bundle and cotangent bundle are smooth. +This result is used to show that maps into the 1-jet bundle and cotangent bundle are `C^n`. `ContMDiffAt.mfderiv_const` is a special case of this. -/ protected theorem ContMDiffAt.mfderiv {x₀ : N} (f : N → M → M') (g : N → M) (hf : ContMDiffAt (J.prod I) I' n (Function.uncurry f) (x₀, g x₀)) (hg : ContMDiffAt J I m g x₀) (hmn : m + 1 ≤ n) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiffAt J 𝓘(𝕜, E →L[𝕜] E') m (inTangentCoordinates I I' g (fun x ↦ f x (g x)) (fun x ↦ mfderiv I I' (f x) (g x)) x₀) x₀ := by @@ -250,6 +261,8 @@ This is a special case of `ContMDiffAt.mfderiv` where `f` does not contain any p -/ theorem ContMDiffAt.mfderiv_const {x₀ : M} {f : M → M'} (hf : ContMDiffAt I I' n f x₀) (hmn : m + 1 ≤ n) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiffAt I 𝓘(𝕜, E →L[𝕜] E') m (inTangentCoordinates I I' id f (mfderiv I I' f) x₀) x₀ := haveI : ContMDiffAt (I.prod I) I' n (fun x : M × M => f x.2) (x₀, x₀) := ContMDiffAt.comp (x₀, x₀) hf contMDiffAt_snd @@ -267,6 +280,8 @@ theorem ContMDiffAt.mfderiv_apply {x₀ : N'} (f : N → M → M') (g : N → M) (hf : ContMDiffAt (J.prod I) I' n (Function.uncurry f) (g₁ x₀, g (g₁ x₀))) (hg : ContMDiffAt J I m g (g₁ x₀)) (hg₁ : ContMDiffAt J' J m g₁ x₀) (hg₂ : ContMDiffAt J' 𝓘(𝕜, E) m g₂ x₀) (hmn : m + 1 ≤ n) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiffAt J' 𝓘(𝕜, E') m (fun x => inTangentCoordinates I I' g (fun x => f x (g x)) (fun x => mfderiv I I' (f x) (g x)) (g₁ x₀) (g₁ x) (g₂ x)) x₀ := @@ -274,18 +289,23 @@ theorem ContMDiffAt.mfderiv_apply {x₀ : N'} (f : N → M → M') (g : N → M) end mfderiv -/-! ### The tangent map of a smooth function is smooth -/ +/-! ### The tangent map of a `C^(n+1)` function is `C^n` -/ section tangentMap +variable [Is : IsManifold I n M] [I's : IsManifold I' n M'] + /-- If a function is `C^n` on a domain with unique derivatives, then its bundled derivative is `C^m` when `m+1 ≤ n`. -/ theorem ContMDiffOn.contMDiffOn_tangentMapWithin - [Is : SmoothManifoldWithCorners I M] [I's : SmoothManifoldWithCorners I' M'] (hf : ContMDiffOn I I' n f s) (hmn : m + 1 ≤ n) (hs : UniqueMDiffOn I s) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiffOn I.tangent I'.tangent m (tangentMapWithin I I' f s) (π E (TangentSpace I) ⁻¹' s) := by + have : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + have : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) intro x₀ hx₀ let s' : Set (TangentBundle I M) := (π E (TangentSpace I) ⁻¹' s) let b₁ : TangentBundle I M → M := fun p ↦ p.1 @@ -316,28 +336,38 @@ alias ContMDiffOn.contMDiffOn_tangentMapWithin_aux := ContMDiffOn.contMDiffOn_ta @[deprecated (since := "2024-10-07")] alias ContMDiffOn.continuousOn_tangentMapWithin_aux := ContMDiffOn.contMDiffOn_tangentMapWithin -variable [Is : SmoothManifoldWithCorners I M] [I's : SmoothManifoldWithCorners I' M'] - /-- If a function is `C^n` on a domain with unique derivatives, with `1 ≤ n`, then its bundled derivative is continuous there. -/ theorem ContMDiffOn.continuousOn_tangentMapWithin (hf : ContMDiffOn I I' n f s) (hmn : 1 ≤ n) (hs : UniqueMDiffOn I s) : - ContinuousOn (tangentMapWithin I I' f s) (π E (TangentSpace I) ⁻¹' s) := - haveI : + haveI : IsManifold I 1 M := .of_le hmn + haveI : IsManifold I' 1 M' := .of_le hmn + ContinuousOn (tangentMapWithin I I' f s) (π E (TangentSpace I) ⁻¹' s) := by + have : IsManifold I 1 M := .of_le hmn + have : IsManifold I' 1 M' := .of_le hmn + have : ContMDiffOn I.tangent I'.tangent 0 (tangentMapWithin I I' f s) (π E (TangentSpace I) ⁻¹' s) := hf.contMDiffOn_tangentMapWithin hmn hs - this.continuousOn + exact this.continuousOn /-- If a function is `C^n`, then its bundled derivative is `C^m` when `m+1 ≤ n`. -/ theorem ContMDiff.contMDiff_tangentMap (hf : ContMDiff I I' n f) (hmn : m + 1 ≤ n) : + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) ContMDiff I.tangent I'.tangent m (tangentMap I I' f) := by + haveI : IsManifold I 1 M := .of_le (le_trans le_add_self hmn) + haveI : IsManifold I' 1 M' := .of_le (le_trans le_add_self hmn) rw [← contMDiffOn_univ] at hf ⊢ convert hf.contMDiffOn_tangentMapWithin hmn uniqueMDiffOn_univ rw [tangentMapWithin_univ] /-- If a function is `C^n`, with `1 ≤ n`, then its bundled derivative is continuous. -/ theorem ContMDiff.continuous_tangentMap (hf : ContMDiff I I' n f) (hmn : 1 ≤ n) : + haveI : IsManifold I 1 M := .of_le hmn + haveI : IsManifold I' 1 M' := .of_le hmn Continuous (tangentMap I I' f) := by + haveI : IsManifold I 1 M := .of_le hmn + haveI : IsManifold I' 1 M' := .of_le hmn rw [← contMDiffOn_univ] at hf rw [continuous_iff_continuousOn_univ] convert hf.continuousOn_tangentMapWithin hmn uniqueMDiffOn_univ @@ -365,7 +395,8 @@ coordinates on the tangent bundle in our definitions. So this statement is not a may seem. TODO define splittings of vector bundles; state this result invariantly. -/ -theorem tangentMap_tangentBundle_pure [Is : SmoothManifoldWithCorners I M] (p : TangentBundle I M) : +theorem tangentMap_tangentBundle_pure [Is : IsManifold I 1 M] + (p : TangentBundle I M) : tangentMap I I.tangent (zeroSection E (TangentSpace I)) p = ⟨⟨p.proj, 0⟩, ⟨p.2, 0⟩⟩ := by rcases p with ⟨x, v⟩ have N : I.symm ⁻¹' (chartAt H x).target ∈ 𝓝 (I ((chartAt H x) x)) := by @@ -403,16 +434,13 @@ namespace ContMDiffMap -- `Mathlib/Geometry/Manifold/ContMDiffMap.lean` to avoid needing to import this file there. -- (However as a consequence we import `Mathlib/Geometry/Manifold/ContMDiffMap.lean` here now.) -- They could be moved to another file (perhaps a new file) if desired. -open scoped Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped Manifold ContDiff protected theorem mdifferentiable' (f : C^n⟮I, M; I', M'⟯) (hn : 1 ≤ n) : MDifferentiable I I' f := f.contMDiff.mdifferentiable hn protected theorem mdifferentiable (f : C^∞⟮I, M; I', M'⟯) : MDifferentiable I I' f := - f.contMDiff.mdifferentiable le_top + f.contMDiff.mdifferentiable (mod_cast le_top) protected theorem mdifferentiableAt (f : C^∞⟮I, M; I', M'⟯) {x} : MDifferentiableAt I I' f x := f.mdifferentiable x diff --git a/Mathlib/Geometry/Manifold/ContMDiffMap.lean b/Mathlib/Geometry/Manifold/ContMDiffMap.lean index 2be46a551a705..c4d2dbbb08733 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMap.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMap.lean @@ -6,7 +6,7 @@ Authors: Nicolò Cavalleri import Mathlib.Geometry.Manifold.ContMDiff.NormedSpace /-! -# Smooth bundled map +# `C^n` bundled maps In this file we define the type `ContMDiffMap` of `n` times continuously differentiable bundled maps. @@ -22,7 +22,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom -- declare a manifold `N` over the pair `(F, G)`. {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type*} [TopologicalSpace G] - {J : ModelWithCorners 𝕜 F G} {N : Type*} [TopologicalSpace N] [ChartedSpace G N] (n : ℕ∞) + {J : ModelWithCorners 𝕜 F G} {N : Type*} [TopologicalSpace N] [ChartedSpace G N] (n : WithTop ℕ∞) variable (I I') in /-- Bundled `n` times continuously differentiable maps. -/ @@ -38,11 +38,7 @@ scoped[Manifold] notation "C^" n "⟮" I ", " M "; " I' ", " M' "⟯" => ContMDi scoped[Manifold] notation "C^" n "⟮" I ", " M "; " k "⟯" => ContMDiffMap I (modelWithCornersSelf k k) M k n -open scoped Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) - +open scoped Manifold ContDiff namespace ContMDiffMap @@ -79,11 +75,11 @@ theorem ext (h : ∀ x, f x = g x) : f = g := DFunLike.ext _ _ h instance : ContinuousMapClass C^n⟮I, M; I', M'⟯ M M' where map_continuous f := f.contMDiff.continuous -/-- The identity as a smooth map. -/ +/-- The identity as a `C^n` map. -/ nonrec def id : C^n⟮I, M; I, M⟯ := ⟨id, contMDiff_id⟩ -/-- The composition of smooth maps, as a smooth map. -/ +/-- The composition of `C^n` maps, as a `C^n` map. -/ def comp (f : C^n⟮I', M'; I'', M''⟯) (g : C^n⟮I, M; I', M'⟯) : C^n⟮I, M; I'', M''⟯ where val a := f (g a) property := f.contMDiff.comp g.contMDiff @@ -96,19 +92,19 @@ theorem comp_apply (f : C^n⟮I', M'; I'', M''⟯) (g : C^n⟮I, M; I', M'⟯) ( instance [Inhabited M'] : Inhabited C^n⟮I, M; I', M'⟯ := ⟨⟨fun _ => default, contMDiff_const⟩⟩ -/-- Constant map as a smooth map -/ +/-- Constant map as a `C^n` map -/ def const (y : M') : C^n⟮I, M; I', M'⟯ := ⟨fun _ => y, contMDiff_const⟩ -/-- The first projection of a product, as a smooth map. -/ +/-- The first projection of a product, as a `C^n` map. -/ def fst : C^n⟮I.prod I', M × M'; I, M⟯ := ⟨Prod.fst, contMDiff_fst⟩ -/-- The second projection of a product, as a smooth map. -/ +/-- The second projection of a product, as a `C^n` map. -/ def snd : C^n⟮I.prod I', M × M'; I', M'⟯ := ⟨Prod.snd, contMDiff_snd⟩ -/-- Given two smooth maps `f` and `g`, this is the smooth map `x ↦ (f x, g x)`. -/ +/-- Given two `C^n` maps `f` and `g`, this is the `C^n` map `x ↦ (f x, g x)`. -/ def prodMk (f : C^n⟮J, N; I, M⟯) (g : C^n⟮J, N; I', M'⟯) : C^n⟮J, N; I.prod I', M × M'⟯ := ⟨fun x => (f x, g x), f.2.prod_mk g.2⟩ diff --git a/Mathlib/Geometry/Manifold/DerivationBundle.lean b/Mathlib/Geometry/Manifold/DerivationBundle.lean index fb3dbd766186a..0cbb33ee8efac 100644 --- a/Mathlib/Geometry/Manifold/DerivationBundle.lean +++ b/Mathlib/Geometry/Manifold/DerivationBundle.lean @@ -22,12 +22,9 @@ of the Lie algebra for a Lie group. variable (𝕜 : Type*) [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) (M : Type*) - [TopologicalSpace M] [ChartedSpace H M] (n : ℕ∞) + [TopologicalSpace M] [ChartedSpace H M] (n : WithTop ℕ∞) -open scoped Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped Manifold ContDiff -- the following two instances prevent poorly understood type class inference timeout problems instance smoothFunctionsAlgebra : Algebra 𝕜 C^∞⟮I, M; 𝕜⟯ := by infer_instance @@ -37,15 +34,17 @@ instance smooth_functions_tower : IsScalarTower 𝕜 C^∞⟮I, M; 𝕜⟯ C^∞ /-- Type synonym, introduced to put a different `SMul` action on `C^n⟮I, M; 𝕜⟯` which is defined as `f • r = f(x) * r`. -/ @[nolint unusedArguments] -def PointedSmoothMap (_ : M) := +def PointedContMDiffMap (_ : M) := C^n⟮I, M; 𝕜⟯ +@[deprecated (since := "2025-01-09")] alias PointedSmoothMap := PointedContMDiffMap + @[inherit_doc] -scoped[Derivation] notation "C^" n "⟮" I ", " M "; " 𝕜 "⟯⟨" x "⟩" => PointedSmoothMap 𝕜 I M n x +scoped[Derivation] notation "C^" n "⟮" I ", " M "; " 𝕜 "⟯⟨" x "⟩" => PointedContMDiffMap 𝕜 I M n x variable {𝕜 M} -namespace PointedSmoothMap +namespace PointedContMDiffMap open scoped Derivation @@ -53,10 +52,10 @@ instance instFunLike {x : M} : FunLike C^∞⟮I, M; 𝕜⟯⟨x⟩ M 𝕜 := ContMDiffMap.instFunLike instance {x : M} : CommRing C^∞⟮I, M; 𝕜⟯⟨x⟩ := - SmoothMap.commRing + ContMDiffMap.commRing instance {x : M} : Algebra 𝕜 C^∞⟮I, M; 𝕜⟯⟨x⟩ := - SmoothMap.algebra + ContMDiffMap.algebra instance {x : M} : Inhabited C^∞⟮I, M; 𝕜⟯⟨x⟩ := ⟨0⟩ @@ -69,9 +68,9 @@ instance {x : M} : IsScalarTower 𝕜 C^∞⟮I, M; 𝕜⟯⟨x⟩ C^∞⟮I, M; variable {I} -/-- `SmoothMap.evalRingHom` gives rise to an algebra structure of `C^∞⟮I, M; 𝕜⟯` on `𝕜`. -/ +/-- `ContMDiffMap.evalRingHom` gives rise to an algebra structure of `C^∞⟮I, M; 𝕜⟯` on `𝕜`. -/ instance evalAlgebra {x : M} : Algebra C^∞⟮I, M; 𝕜⟯⟨x⟩ 𝕜 := - (SmoothMap.evalRingHom x : C^∞⟮I, M; 𝕜⟯⟨x⟩ →+* 𝕜).toAlgebra + (ContMDiffMap.evalRingHom x : C^∞⟮I, M; 𝕜⟯⟨x⟩ →+* 𝕜).toAlgebra /-- With the `evalAlgebra` algebra structure evaluation is actually an algebra morphism. -/ def eval (x : M) : C^∞⟮I, M; 𝕜⟯ →ₐ[C^∞⟮I, M; 𝕜⟯⟨x⟩] 𝕜 := @@ -82,9 +81,10 @@ theorem smul_def (x : M) (f : C^∞⟮I, M; 𝕜⟯⟨x⟩) (k : 𝕜) : f • k instance (x : M) : IsScalarTower 𝕜 C^∞⟮I, M; 𝕜⟯⟨x⟩ 𝕜 where smul_assoc k f h := by - rw [smul_def, smul_def, SmoothMap.coe_smul, Pi.smul_apply, smul_eq_mul, smul_eq_mul, mul_assoc] + rw [smul_def, smul_def, ContMDiffMap.coe_smul, Pi.smul_apply, smul_eq_mul, smul_eq_mul, + mul_assoc] -end PointedSmoothMap +end PointedContMDiffMap open scoped Derivation @@ -101,8 +101,10 @@ variable (X : Derivation 𝕜 C^∞⟮I, M; 𝕜⟯ C^∞⟮I, M; 𝕜⟯) (f : /-- Evaluation at a point gives rise to a `C^∞⟮I, M; 𝕜⟯`-linear map between `C^∞⟮I, M; 𝕜⟯` and `𝕜`. -/ -def SmoothFunction.evalAt (x : M) : C^∞⟮I, M; 𝕜⟯ →ₗ[C^∞⟮I, M; 𝕜⟯⟨x⟩] 𝕜 := - (PointedSmoothMap.eval x).toLinearMap +def ContMDiffFunction.evalAt (x : M) : C^∞⟮I, M; 𝕜⟯ →ₗ[C^∞⟮I, M; 𝕜⟯⟨x⟩] 𝕜 := + (PointedContMDiffMap.eval x).toLinearMap + +@[deprecated (since := "2025-01-09")] alias SmoothFunction.evalAt := ContMDiffFunction.evalAt namespace Derivation @@ -110,7 +112,7 @@ variable {I} /-- The evaluation at a point as a linear map. -/ def evalAt (x : M) : Derivation 𝕜 C^∞⟮I, M; 𝕜⟯ C^∞⟮I, M; 𝕜⟯ →ₗ[𝕜] PointDerivation I x := - (SmoothFunction.evalAt I x).compDer + (ContMDiffFunction.evalAt I x).compDer theorem evalAt_apply (x : M) : evalAt x X f = (X f) x := rfl @@ -129,14 +131,14 @@ def hfdifferential {f : C^∞⟮I, M; I', M'⟯} {x : M} {y : M'} (h : f x = y) toFun v := Derivation.mk' { toFun := fun g => v (g.comp f) - map_add' := fun g g' => by dsimp; rw [SmoothMap.add_comp, Derivation.map_add] + map_add' := fun g g' => by dsimp; rw [ContMDiffMap.add_comp, Derivation.map_add] map_smul' := fun k g => by - dsimp; rw [SmoothMap.smul_comp, Derivation.map_smul, smul_eq_mul] } + dsimp; rw [ContMDiffMap.smul_comp, Derivation.map_smul, smul_eq_mul] } fun g g' => by dsimp - rw [SmoothMap.mul_comp, Derivation.leibniz, - PointedSmoothMap.smul_def, ContMDiffMap.comp_apply, - PointedSmoothMap.smul_def, ContMDiffMap.comp_apply, h] + rw [ContMDiffMap.mul_comp, Derivation.leibniz, + PointedContMDiffMap.smul_def, ContMDiffMap.comp_apply, + PointedContMDiffMap.smul_def, ContMDiffMap.comp_apply, h] norm_cast map_smul' _ _ := rfl map_add' _ _ := rfl diff --git a/Mathlib/Geometry/Manifold/Diffeomorph.lean b/Mathlib/Geometry/Manifold/Diffeomorph.lean index ed39ae6e822cd..39b1fb3e9f0b4 100644 --- a/Mathlib/Geometry/Manifold/Diffeomorph.lean +++ b/Mathlib/Geometry/Manifold/Diffeomorph.lean @@ -27,7 +27,7 @@ This file implements diffeomorphisms. ## Notations * `M ≃ₘ^n⟮I, I'⟯ M'` := `Diffeomorph I J M N n` -* `M ≃ₘ⟮I, I'⟯ M'` := `Diffeomorph I J M N ⊤` +* `M ≃ₘ⟮I, I'⟯ M'` := `Diffeomorph I J M N ∞` * `E ≃ₘ^n[𝕜] E'` := `E ≃ₘ^n⟮𝓘(𝕜, E), 𝓘(𝕜, E')⟯ E'` * `E ≃ₘ[𝕜] E'` := `E ≃ₘ⟮𝓘(𝕜, E), 𝓘(𝕜, E')⟯ E'` @@ -57,7 +57,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom variable {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] {N : Type*} [TopologicalSpace N] [ChartedSpace G N] {N' : Type*} - [TopologicalSpace N'] [ChartedSpace G' N'] {n : ℕ∞} + [TopologicalSpace N'] [ChartedSpace G' N'] {n : WithTop ℕ∞} section Defs @@ -76,15 +76,13 @@ end Defs scoped[Manifold] notation M " ≃ₘ^" n:1000 "⟮" I ", " J "⟯ " N => Diffeomorph I J M N n /-- Infinitely differentiable diffeomorphism between `M` and `M'` with respect to `I` and `I'`. -/ -scoped[Manifold] notation M " ≃ₘ⟮" I ", " J "⟯ " N => Diffeomorph I J M N ⊤ +scoped[Manifold] notation M " ≃ₘ⟮" I ", " J "⟯ " N => Diffeomorph I J M N ∞ /-- `n`-times continuously differentiable diffeomorphism between `E` and `E'`. -/ scoped[Manifold] notation E " ≃ₘ^" n:1000 "[" 𝕜 "] " E' => Diffeomorph 𝓘(𝕜, E) 𝓘(𝕜, E') E E' n /-- Infinitely differentiable diffeomorphism between `E` and `E'`. -/ -scoped[Manifold] - notation3 E " ≃ₘ[" 𝕜 "] " E' => - Diffeomorph (modelWithCornersSelf 𝕜 E) (modelWithCornersSelf 𝕜 E') E E' ⊤ +scoped[Manifold] notation3 E " ≃ₘ[" 𝕜 "] " E' => Diffeomorph 𝓘(𝕜, E) 𝓘(𝕜, E') E E' ∞ namespace Diffeomorph @@ -437,13 +435,15 @@ end ContinuousLinearEquiv namespace ModelWithCorners -variable (I) (e : E ≃ₘ[𝕜] E') +variable (I) (e : E ≃ₘ^n⟮𝓘(𝕜, E), 𝓘(𝕜, E')⟯ E') [NeZero n] /-- Apply a diffeomorphism (e.g., a continuous linear equivalence) to the model vector space. -/ -def transDiffeomorph (I : ModelWithCorners 𝕜 E H) (e : E ≃ₘ[𝕜] E') : ModelWithCorners 𝕜 E' H where +def transDiffeomorph : ModelWithCorners 𝕜 E' H where toPartialEquiv := I.toPartialEquiv.trans e.toEquiv.toPartialEquiv source_eq := by simp - uniqueDiffOn' := by simp [range_comp e, I.uniqueDiffOn] + uniqueDiffOn' := by + have hn : 1 ≤ n := ENat.one_le_iff_ne_zero_withTop.mpr (NeZero.ne n) + simp [I.uniqueDiffOn, hn] target_subset_closure_interior := by simp only [PartialEquiv.trans_target, Equiv.toPartialEquiv_target, Equiv.toPartialEquiv_symm_apply, Diffeomorph.toEquiv_coe_symm, target_eq, univ_inter] @@ -483,13 +483,13 @@ end ModelWithCorners namespace Diffeomorph -variable (e : E ≃ₘ[𝕜] F) +variable [NeZero n] (e : E ≃ₘ^n⟮𝓘(𝕜, E), 𝓘(𝕜, F)⟯ F) -instance smoothManifoldWithCorners_transDiffeomorph [SmoothManifoldWithCorners I M] : - SmoothManifoldWithCorners (I.transDiffeomorph e) M := by - refine smoothManifoldWithCorners_of_contDiffOn (I.transDiffeomorph e) M fun e₁ e₂ h₁ h₂ => ?_ +instance instIsManifoldTransDiffeomorph [IsManifold I n M] : + IsManifold (I.transDiffeomorph e) n M := by + refine isManifold_of_contDiffOn (I.transDiffeomorph e) n M fun e₁ e₂ h₁ h₂ => ?_ refine e.contDiff.comp_contDiffOn - (((contDiffGroupoid ∞ I).compatible h₁ h₂).1.comp e.symm.contDiff.contDiffOn ?_) + (((contDiffGroupoid n I).compatible h₁ h₂).1.comp e.symm.contDiff.contDiffOn ?_) simp only [mapsTo_iff_subset_preimage] mfld_set_tac @@ -497,7 +497,7 @@ variable (I M) /-- The identity diffeomorphism between a manifold with model `I` and the same manifold with model `I.trans_diffeomorph e`. -/ -def toTransDiffeomorph (e : E ≃ₘ[𝕜] F) : M ≃ₘ⟮I, I.transDiffeomorph e⟯ M where +def toTransDiffeomorph (e : E ≃ₘ^n⟮𝓘(𝕜, E), 𝓘(𝕜, F)⟯ F) : M ≃ₘ^n⟮I, I.transDiffeomorph e⟯ M where toEquiv := Equiv.refl M contMDiff_toFun x := by refine contMDiffWithinAt_iff'.2 ⟨continuousWithinAt_id, ?_⟩ @@ -520,22 +520,22 @@ variable {I M} @[simp] theorem contMDiffWithinAt_transDiffeomorph_right {f : M' → M} {x s} : ContMDiffWithinAt I' (I.transDiffeomorph e) n f s x ↔ ContMDiffWithinAt I' I n f s x := - (toTransDiffeomorph I M e).contMDiffWithinAt_diffeomorph_comp_iff le_top + (toTransDiffeomorph I M e).contMDiffWithinAt_diffeomorph_comp_iff le_rfl @[simp] theorem contMDiffAt_transDiffeomorph_right {f : M' → M} {x} : ContMDiffAt I' (I.transDiffeomorph e) n f x ↔ ContMDiffAt I' I n f x := - (toTransDiffeomorph I M e).contMDiffAt_diffeomorph_comp_iff le_top + (toTransDiffeomorph I M e).contMDiffAt_diffeomorph_comp_iff le_rfl @[simp] theorem contMDiffOn_transDiffeomorph_right {f : M' → M} {s} : ContMDiffOn I' (I.transDiffeomorph e) n f s ↔ ContMDiffOn I' I n f s := - (toTransDiffeomorph I M e).contMDiffOn_diffeomorph_comp_iff le_top + (toTransDiffeomorph I M e).contMDiffOn_diffeomorph_comp_iff le_rfl @[simp] theorem contMDiff_transDiffeomorph_right {f : M' → M} : ContMDiff I' (I.transDiffeomorph e) n f ↔ ContMDiff I' I n f := - (toTransDiffeomorph I M e).contMDiff_diffeomorph_comp_iff le_top + (toTransDiffeomorph I M e).contMDiff_diffeomorph_comp_iff le_rfl @[deprecated (since := "2024-11-21")] alias smooth_transDiffeomorph_right := contMDiff_transDiffeomorph_right @@ -543,22 +543,22 @@ alias smooth_transDiffeomorph_right := contMDiff_transDiffeomorph_right @[simp] theorem contMDiffWithinAt_transDiffeomorph_left {f : M → M'} {x s} : ContMDiffWithinAt (I.transDiffeomorph e) I' n f s x ↔ ContMDiffWithinAt I I' n f s x := - ((toTransDiffeomorph I M e).contMDiffWithinAt_comp_diffeomorph_iff le_top).symm + ((toTransDiffeomorph I M e).contMDiffWithinAt_comp_diffeomorph_iff le_rfl).symm @[simp] theorem contMDiffAt_transDiffeomorph_left {f : M → M'} {x} : ContMDiffAt (I.transDiffeomorph e) I' n f x ↔ ContMDiffAt I I' n f x := - ((toTransDiffeomorph I M e).contMDiffAt_comp_diffeomorph_iff le_top).symm + ((toTransDiffeomorph I M e).contMDiffAt_comp_diffeomorph_iff le_rfl).symm @[simp] theorem contMDiffOn_transDiffeomorph_left {f : M → M'} {s} : ContMDiffOn (I.transDiffeomorph e) I' n f s ↔ ContMDiffOn I I' n f s := - ((toTransDiffeomorph I M e).contMDiffOn_comp_diffeomorph_iff le_top).symm + ((toTransDiffeomorph I M e).contMDiffOn_comp_diffeomorph_iff le_rfl).symm @[simp] theorem contMDiff_transDiffeomorph_left {f : M → M'} : ContMDiff (I.transDiffeomorph e) I' n f ↔ ContMDiff I I' n f := - ((toTransDiffeomorph I M e).contMDiff_comp_diffeomorph_iff le_top).symm + ((toTransDiffeomorph I M e).contMDiff_comp_diffeomorph_iff le_rfl).symm @[deprecated (since := "2024-11-21")] alias smooth_transDiffeomorph_left := contMDiff_transDiffeomorph_left diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index eb4aec7e8dbe9..f13382bb2dbcc 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -361,12 +361,12 @@ instance IccChartedSpace (x y : ℝ) [h : Fact (x < y)] : /-- The manifold structure on `[x, y]` is smooth. -/ -instance Icc_smoothManifoldWithCorners (x y : ℝ) [Fact (x < y)] : - SmoothManifoldWithCorners (𝓡∂ 1) (Icc x y) := by - have M : ContDiff ℝ ∞ (show EuclideanSpace ℝ (Fin 1) → EuclideanSpace ℝ (Fin 1) +instance instIsManifoldIcc (x y : ℝ) [Fact (x < y)] {n : WithTop ℕ∞} : + IsManifold (𝓡∂ 1) n (Icc x y) := by + have M : ContDiff ℝ n (show EuclideanSpace ℝ (Fin 1) → EuclideanSpace ℝ (Fin 1) from fun z i => -z i + (y - x)) := contDiff_id.neg.add contDiff_const - apply smoothManifoldWithCorners_of_contDiffOn + apply isManifold_of_contDiffOn intro e e' he he' simp only [atlas, mem_singleton_iff, mem_insert_iff] at he he' /- We need to check that any composition of two charts gives a `C^∞` function. Each chart can be @@ -400,12 +400,13 @@ instance Icc_smoothManifoldWithCorners (x y : ℝ) [Fact (x < y)] : exact (mem_groupoid_of_pregroupoid.mpr (symm_trans_mem_contDiffGroupoid _)).1 /-! Register the manifold structure on `Icc 0 1`. These are merely special cases of -`IccChartedSpace` and `Icc_smoothManifoldWithCorners`. -/ +`IccChartedSpace` and `instIsManifoldIcc`. -/ section instance : ChartedSpace (EuclideanHalfSpace 1) (Icc (0 : ℝ) 1) := by infer_instance -instance : SmoothManifoldWithCorners (𝓡∂ 1) (Icc (0 : ℝ) 1) := by infer_instance +instance {n : WithTop ℕ∞} : IsManifold (𝓡∂ 1) n (Icc (0 : ℝ) 1) := by + infer_instance end diff --git a/Mathlib/Geometry/Manifold/Instances/Sphere.lean b/Mathlib/Geometry/Manifold/Instances/Sphere.lean index 9ab63860e4d2a..8a68398674838 100644 --- a/Mathlib/Geometry/Manifold/Instances/Sphere.lean +++ b/Mathlib/Geometry/Manifold/Instances/Sphere.lean @@ -19,7 +19,7 @@ import Mathlib.Tactic.Module # Manifold structure on the sphere This file defines stereographic projection from the sphere in an inner product space `E`, and uses -it to put a smooth manifold structure on the sphere. +it to put an analytic manifold structure on the sphere. ## Main results @@ -27,26 +27,26 @@ For a unit vector `v` in `E`, the definition `stereographic` gives the stereogra centred at `v`, a partial homeomorphism from the sphere to `(ℝ ∙ v)ᗮ` (the orthogonal complement of `v`). -For finite-dimensional `E`, we then construct a smooth manifold instance on the sphere; the charts -here are obtained by composing the partial homeomorphisms `stereographic` with arbitrary isometries -from `(ℝ ∙ v)ᗮ` to Euclidean space. +For finite-dimensional `E`, we then construct an analytic manifold instance on the sphere; the +charts here are obtained by composing the partial homeomorphisms `stereographic` with arbitrary +isometries from `(ℝ ∙ v)ᗮ` to Euclidean space. -We prove two lemmas about smooth maps: -* `contMDiff_coe_sphere` states that the coercion map from the sphere into `E` is smooth; +We prove two lemmas about `C^n` maps: +* `contMDiff_coe_sphere` states that the coercion map from the sphere into `E` is analytic; this is a useful tool for constructing smooth maps *from* the sphere. * `contMDiff.codRestrict_sphere` states that a map from a manifold into the sphere is - smooth if its lift to a map to `E` is smooth; this is a useful tool for constructing smooth maps + `C^m` if its lift to a map to `E` is `C^m`; this is a useful tool for constructing `C^m` maps *to* the sphere. -As an application we prove `contMdiffNegSphere`, that the antipodal map is smooth. +As an application we prove `contMDiffNegSphere`, that the antipodal map is analytic. Finally, we equip the `Circle` (defined in `Analysis.Complex.Circle` to be the sphere in `ℂ` centred at `0` of radius `1`) with the following structure: * a charted space with model space `EuclideanSpace ℝ (Fin 1)` (inherited from `Metric.Sphere`) -* a Lie group with model with corners `𝓡 1` +* an analytic Lie group with model with corners `𝓡 1` We furthermore show that `Circle.exp` (defined in `Analysis.Complex.Circle` to be the natural -map `fun t ↦ exp (t * I)` from `ℝ` to `Circle`) is smooth. +map `fun t ↦ exp (t * I)` from `ℝ` to `Circle`) is analytic. ## Implementation notes @@ -95,7 +95,7 @@ theorem stereoToFun_apply (x : E) : rfl theorem contDiffOn_stereoToFun : - ContDiffOn ℝ ∞ (stereoToFun v) {x : E | innerSL _ v x ≠ (1 : ℝ)} := by + ContDiffOn ℝ ω (stereoToFun v) {x : E | innerSL _ v x ≠ (1 : ℝ)} := by refine ContDiffOn.smul ?_ (orthogonalProjection (ℝ ∙ v)ᗮ).contDiff.contDiffOn refine contDiff_const.contDiffOn.div ?_ ?_ · exact (contDiff_const.sub (innerSL ℝ v).contDiff).contDiffOn @@ -159,13 +159,13 @@ theorem hasFDerivAt_stereoInvFunAux_comp_coe (v : E) : hasFDerivAt_stereoInvFunAux v refine this.comp (0 : (ℝ ∙ v)ᗮ) (by apply ContinuousLinearMap.hasFDerivAt) -theorem contDiff_stereoInvFunAux : ContDiff ℝ ∞ (stereoInvFunAux v) := by - have h₀ : ContDiff ℝ ∞ fun w : E => ‖w‖ ^ 2 := contDiff_norm_sq ℝ - have h₁ : ContDiff ℝ ∞ fun w : E => (‖w‖ ^ 2 + 4)⁻¹ := by +theorem contDiff_stereoInvFunAux : ContDiff ℝ ω (stereoInvFunAux v) := by + have h₀ : ContDiff ℝ ω fun w : E => ‖w‖ ^ 2 := contDiff_norm_sq ℝ + have h₁ : ContDiff ℝ ω fun w : E => (‖w‖ ^ 2 + 4)⁻¹ := by refine (h₀.add contDiff_const).inv ?_ intro x nlinarith - have h₂ : ContDiff ℝ ∞ fun w => (4 : ℝ) • w + (‖w‖ ^ 2 - 4) • v := by + have h₂ : ContDiff ℝ ω fun w => (4 : ℝ) • w + (‖w‖ ^ 2 - 4) • v := by refine (contDiff_const.smul contDiff_id).add ?_ exact (h₀.sub contDiff_const).smul contDiff_const exact h₁.smul h₂ @@ -354,7 +354,7 @@ instance (n : ℕ) : end ChartedSpace -section SmoothManifold +section ContMDiffManifold open scoped InnerProductSpace @@ -370,13 +370,14 @@ theorem stereographic'_symm_apply {n : ℕ} [Fact (finrank ℝ E = n + 1)] (v : (‖(U.symm x : E)‖ ^ 2 + 4)⁻¹ • (‖(U.symm x : E)‖ ^ 2 - 4) • v.val := by simp [real_inner_comm, stereographic, stereographic', ← Submodule.coe_norm] -/-! ### Smooth manifold structure on the sphere -/ +/-! ### Analytic manifold structure on the sphere -/ -/-- The unit sphere in an `n + 1`-dimensional inner product space `E` is a smooth manifold, +/-- The unit sphere in an `n + 1`-dimensional inner product space `E` is an analytic manifold, modelled on the Euclidean space of dimension `n`. -/ -instance EuclideanSpace.instSmoothManifoldWithCornersSphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : - SmoothManifoldWithCorners (𝓡 n) (sphere (0 : E) 1) := - smoothManifoldWithCorners_of_contDiffOn (𝓡 n) (sphere (0 : E) 1) +instance EuclideanSpace.instIsManifoldSphere + {n : ℕ} [Fact (finrank ℝ E = n + 1)] : + IsManifold (𝓡 n) ω (sphere (0 : E) 1) := + isManifold_of_contDiffOn (𝓡 n) ω (sphere (0 : E) 1) (by rintro _ _ ⟨v, rfl⟩ ⟨v', rfl⟩ let U := @@ -391,7 +392,7 @@ instance EuclideanSpace.instSmoothManifoldWithCornersSphere {n : ℕ} [Fact (fin -- Porting note: need to help with implicit variables again have H₂ := (contDiff_stereoInvFunAux (v := v.val)|>.comp (ℝ ∙ (v : E))ᗮ.subtypeL.contDiff).comp U.symm.contDiff - convert H₁.comp_inter (H₂.contDiffOn : ContDiffOn ℝ ∞ _ Set.univ) using 1 + convert H₁.comp_inter (H₂.contDiffOn : ContDiffOn ℝ ω _ Set.univ) using 1 -- -- squeezed from `ext, simp [sphere_ext_iff, stereographic'_symm_apply, real_inner_comm]` simp only [PartialHomeomorph.trans_toPartialEquiv, PartialHomeomorph.symm_toPartialEquiv, PartialEquiv.trans_source, PartialEquiv.symm_source, stereographic'_target, @@ -402,16 +403,15 @@ instance EuclideanSpace.instSmoothManifoldWithCornersSphere {n : ℕ} [Fact (fin innerSL_apply, Ne, sphere_ext_iff, real_inner_comm (v' : E)] rfl) -instance (n : ℕ) : - SmoothManifoldWithCorners (𝓡 n) (sphere (0 : EuclideanSpace ℝ (Fin (n + 1))) 1) := +instance (n : ℕ) : IsManifold (𝓡 n) ω (sphere (0 : EuclideanSpace ℝ (Fin (n + 1))) 1) := haveI := Fact.mk (@finrank_euclideanSpace_fin ℝ _ (n + 1)) - EuclideanSpace.instSmoothManifoldWithCornersSphere + EuclideanSpace.instIsManifoldSphere -/-- The inclusion map (i.e., `coe`) from the sphere in `E` to `E` is smooth. -/ +/-- The inclusion map (i.e., `coe`) from the sphere in `E` to `E` is analytic. -/ theorem contMDiff_coe_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : - ContMDiff (𝓡 n) 𝓘(ℝ, E) ⊤ ((↑) : sphere (0 : E) 1 → E) := by + ContMDiff (𝓡 n) 𝓘(ℝ, E) ω ((↑) : sphere (0 : E) 1 → E) := by -- Porting note: trouble with filling these implicit variables in the instance - have := EuclideanSpace.instSmoothManifoldWithCornersSphere (E := E) (n := n) + have := EuclideanSpace.instIsManifoldSphere (E := E) (n := n) rw [contMDiff_iff] constructor · exact continuous_subtype_val @@ -424,13 +424,13 @@ theorem contMDiff_coe_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : ((contDiff_stereoInvFunAux.comp (ℝ ∙ (-v : E))ᗮ.subtypeL.contDiff).comp U.symm.contDiff).contDiffOn -variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] +variable {m : WithTop ℕ∞} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] variable {H : Type*} [TopologicalSpace H] {I : ModelWithCorners ℝ F H} -variable {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] +variable {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I m M] -/-- If a `ContMDiff` function `f : M → E`, where `M` is some manifold, takes values in the -sphere, then it restricts to a `ContMDiff` function from `M` to the sphere. -/ -theorem ContMDiff.codRestrict_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] {m : ℕ∞} {f : M → E} +/-- If a `C^m` function `f : M → E`, where `M` is some manifold, takes values in the +sphere, then it restricts to a `C^m` function from `M` to the sphere. -/ +theorem ContMDiff.codRestrict_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] {f : M → E} (hf : ContMDiff I 𝓘(ℝ, E) m f) (hf' : ∀ x, f x ∈ sphere (0 : E) 1) : ContMDiff I (𝓡 n) m (Set.codRestrict _ _ hf' : M → sphere (0 : E) 1) := by rw [contMDiff_iff_target] @@ -440,7 +440,7 @@ theorem ContMDiff.codRestrict_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] {m (-- Again, partially removing type ascription... Weird that this helps! OrthonormalBasis.fromOrthogonalSpanSingleton n (ne_zero_of_mem_unit_sphere (-v))).repr - have h : ContDiffOn ℝ ∞ _ Set.univ := U.contDiff.contDiffOn + have h : ContDiffOn ℝ ω _ Set.univ := U.contDiff.contDiffOn have H₁ := (h.comp_inter contDiffOn_stereoToFun).contMDiffOn have H₂ : ContMDiffOn _ _ _ _ Set.univ := hf.contMDiffOn convert (H₁.of_le le_top).comp' H₂ using 1 @@ -453,9 +453,9 @@ theorem ContMDiff.codRestrict_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] {m dsimp [chartAt, Set.codRestrict, ChartedSpace.chartAt] simp [not_iff_not, Subtype.ext_iff, hfxv, real_inner_comm] -/-- The antipodal map is smooth. -/ +/-- The antipodal map is analytic. -/ theorem contMDiff_neg_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : - ContMDiff (𝓡 n) (𝓡 n) ⊤ fun x : sphere (0 : E) 1 => -x := by + ContMDiff (𝓡 n) (𝓡 n) ω fun x : sphere (0 : E) 1 => -x := by -- this doesn't elaborate well in term mode apply ContMDiff.codRestrict_sphere apply contDiff_neg.contMDiff.comp _ @@ -532,7 +532,7 @@ theorem mfderiv_coe_sphere_injective {n : ℕ} [Fact (finrank ℝ E = n + 1)] (v rw [ContinuousLinearMap.coe_comp', ContinuousLinearEquiv.coe_coe] simpa [- Subtype.val_injective] using Subtype.val_injective -end SmoothManifold +end ContMDiffManifold section Circle @@ -549,29 +549,29 @@ follows by definition from the corresponding result for `Metric.Sphere`. -/ instance : ChartedSpace (EuclideanSpace ℝ (Fin 1)) Circle := EuclideanSpace.instChartedSpaceSphere -instance : SmoothManifoldWithCorners (𝓡 1) Circle := - EuclideanSpace.instSmoothManifoldWithCornersSphere (E := ℂ) +instance : IsManifold (𝓡 1) ω Circle := + EuclideanSpace.instIsManifoldSphere (E := ℂ) -/-- The unit circle in `ℂ` is a Lie group. -/ -instance : LieGroup (𝓡 1) Circle where - smooth_mul := by +/-- The unit circle in `ℂ` is an analytic Lie group. -/ +instance : LieGroup (𝓡 1) ω Circle where + contMDiff_mul := by apply ContMDiff.codRestrict_sphere let c : Circle → ℂ := (↑) - have h₂ : ContMDiff (𝓘(ℝ, ℂ).prod 𝓘(ℝ, ℂ)) 𝓘(ℝ, ℂ) ⊤ fun z : ℂ × ℂ => z.fst * z.snd := by + have h₂ : ContMDiff (𝓘(ℝ, ℂ).prod 𝓘(ℝ, ℂ)) 𝓘(ℝ, ℂ) ω fun z : ℂ × ℂ => z.fst * z.snd := by rw [contMDiff_iff] exact ⟨continuous_mul, fun x y => contDiff_mul.contDiffOn⟩ -- Porting note: needed to fill in first 3 arguments or could not figure out typeclasses - suffices h₁ : ContMDiff ((𝓡 1).prod (𝓡 1)) (𝓘(ℝ, ℂ).prod 𝓘(ℝ, ℂ)) ⊤ (Prod.map c c) from + suffices h₁ : ContMDiff ((𝓡 1).prod (𝓡 1)) (𝓘(ℝ, ℂ).prod 𝓘(ℝ, ℂ)) ω (Prod.map c c) from h₂.comp h₁ apply ContMDiff.prod_map <;> exact contMDiff_coe_sphere - smooth_inv := by + contMDiff_inv := by apply ContMDiff.codRestrict_sphere simp only [← Circle.coe_inv, Circle.coe_inv_eq_conj] exact Complex.conjCLE.contDiff.contMDiff.comp contMDiff_coe_sphere -/-- The map `fun t ↦ exp (t * I)` from `ℝ` to the unit circle in `ℂ` is smooth. -/ -theorem contMDiff_circleExp : ContMDiff 𝓘(ℝ, ℝ) (𝓡 1) ⊤ Circle.exp := +/-- The map `fun t ↦ exp (t * I)` from `ℝ` to the unit circle in `ℂ` is analytic. -/ +theorem contMDiff_circleExp : ContMDiff 𝓘(ℝ, ℝ) (𝓡 1) ω Circle.exp := (contDiff_exp.comp (contDiff_id.smul contDiff_const)).contMDiff.codRestrict_sphere _ @[deprecated (since := "2024-07-25")] alias contMDiff_expMapCircle := contMDiff_circleExp diff --git a/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean b/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean index b66b8302d348a..3be717519f7c6 100644 --- a/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean +++ b/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean @@ -9,7 +9,7 @@ import Mathlib.Geometry.Manifold.Algebra.LieGroup # Units of a normed algebra We construct the Lie group structure on the group of units of a complete normed `𝕜`-algebra `R`. The -group of units `Rˣ` has a natural smooth manifold structure modelled on `R` given by its embedding +group of units `Rˣ` has a natural `C^n` manifold structure modelled on `R` given by its embedding into `R`. Together with the smoothness of the multiplication and inverse of its elements, `Rˣ` forms a Lie group. @@ -26,14 +26,11 @@ example {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] [CompleteSpace V noncomputable section -open scoped Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped Manifold ContDiff namespace Units -variable {R : Type*} [NormedRing R] [CompleteSpace R] +variable {R : Type*} [NormedRing R] [CompleteSpace R] {n : WithTop ℕ∞} instance : ChartedSpace R Rˣ := isOpenEmbedding_val.singletonChartedSpace @@ -46,28 +43,28 @@ theorem chartAt_source {a : Rˣ} : (chartAt R a).source = Set.univ := variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] [NormedAlgebra 𝕜 R] -instance : SmoothManifoldWithCorners 𝓘(𝕜, R) Rˣ := - isOpenEmbedding_val.singleton_smoothManifoldWithCorners +instance : IsManifold 𝓘(𝕜, R) n Rˣ := + isOpenEmbedding_val.isManifold_singleton -/-- For a complete normed ring `R`, the embedding of the units `Rˣ` into `R` is a smooth map between +/-- For a complete normed ring `R`, the embedding of the units `Rˣ` into `R` is a `C^n` map between manifolds. -/ -lemma contMDiff_val {m : ℕ∞} : ContMDiff 𝓘(𝕜, R) 𝓘(𝕜, R) m (val : Rˣ → R) := +lemma contMDiff_val : ContMDiff 𝓘(𝕜, R) 𝓘(𝕜, R) n (val : Rˣ → R) := contMDiff_isOpenEmbedding Units.isOpenEmbedding_val /-- The units of a complete normed ring form a Lie group. -/ -instance : LieGroup 𝓘(𝕜, R) Rˣ where - smooth_mul := by +instance : LieGroup 𝓘(𝕜, R) n Rˣ where + contMDiff_mul := by apply ContMDiff.of_comp_isOpenEmbedding Units.isOpenEmbedding_val have : (val : Rˣ → R) ∘ (fun x : Rˣ × Rˣ => x.1 * x.2) = (fun x : R × R => x.1 * x.2) ∘ (fun x : Rˣ × Rˣ => (x.1, x.2)) := by ext; simp rw [this] - have : ContMDiff (𝓘(𝕜, R).prod 𝓘(𝕜, R)) 𝓘(𝕜, R × R) ∞ + have : ContMDiff (𝓘(𝕜, R).prod 𝓘(𝕜, R)) 𝓘(𝕜, R × R) n (fun x : Rˣ × Rˣ => ((x.1 : R), (x.2 : R))) := (contMDiff_val.comp contMDiff_fst).prod_mk_space (contMDiff_val.comp contMDiff_snd) refine ContMDiff.comp ?_ this rw [contMDiff_iff_contDiff] exact contDiff_mul - smooth_inv := by + contMDiff_inv := by apply ContMDiff.of_comp_isOpenEmbedding Units.isOpenEmbedding_val have : (val : Rˣ → R) ∘ (fun x : Rˣ => x⁻¹) = Ring.inverse ∘ val := by ext; simp rw [this, ContMDiff] diff --git a/Mathlib/Geometry/Manifold/IntegralCurve/Basic.lean b/Mathlib/Geometry/Manifold/IntegralCurve/Basic.lean index a8c2b1cc92e27..ded16e66a8c2c 100644 --- a/Mathlib/Geometry/Manifold/IntegralCurve/Basic.lean +++ b/Mathlib/Geometry/Manifold/IntegralCurve/Basic.lean @@ -134,7 +134,7 @@ lemma IsIntegralCurveAt.continuousAt (hγ : IsIntegralCurveAt γ v t₀) : lemma IsIntegralCurve.continuous (hγ : IsIntegralCurve γ v) : Continuous γ := continuous_iff_continuousAt.mpr fun _ ↦ (hγ.isIntegralCurveOn univ).continuousAt (mem_univ _) -variable [SmoothManifoldWithCorners I M] +variable [IsManifold I 1 M] /-- If `γ` is an integral curve of a vector field `v`, then `γ t` is tangent to `v (γ t)` when expressed in the local chart around the initial point `γ t₀`. -/ diff --git a/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean b/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean index bb586ece1fb8e..9a921471207e6 100644 --- a/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean +++ b/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean @@ -49,10 +49,10 @@ open Function Set variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I 1 M] {γ γ' : ℝ → M} {v : (x : M) → TangentSpace I x} {s s' : Set ℝ} (t₀ : ℝ) {x₀ : M} -/-- Existence of local integral curves for a $C^1$ vector field at interior points of a smooth +/-- Existence of local integral curves for a $C^1$ vector field at interior points of a `C^1` manifold. -/ theorem exists_isIntegralCurveAt_of_contMDiffAt [CompleteSpace E] (hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) x₀) @@ -106,7 +106,7 @@ theorem exists_isIntegralCurveAt_of_contMDiffAt [CompleteSpace E] rw [← (extChartAt I x₀).right_inv hf3'] exact hasFDerivWithinAt_tangentCoordChange ⟨hft1, hft2⟩ -/-- Existence of local integral curves for a $C^1$ vector field on a smooth manifold without +/-- Existence of local integral curves for a $C^1$ vector field on a `C^1` manifold without boundary. -/ lemma exists_isIntegralCurveAt_of_contMDiffAt_boundaryless [CompleteSpace E] [BoundarylessManifold I M] diff --git a/Mathlib/Geometry/Manifold/IntegralCurve/UniformTime.lean b/Mathlib/Geometry/Manifold/IntegralCurve/UniformTime.lean index 6d11987df7df6..dc59d2f38f78e 100644 --- a/Mathlib/Geometry/Manifold/IntegralCurve/UniformTime.lean +++ b/Mathlib/Geometry/Manifold/IntegralCurve/UniformTime.lean @@ -30,8 +30,8 @@ open Function Set variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] [T2Space M] - {γ γ' : ℝ → M} {v : (x : M) → TangentSpace I x} {s s' : Set ℝ} {t₀ : ℝ} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I 1 M] + [T2Space M] {γ γ' : ℝ → M} {v : (x : M) → TangentSpace I x} {s s' : Set ℝ} {t₀ : ℝ} /-- This is the uniqueness theorem of integral curves applied to a real-indexed family of integral curves with the same starting point. -/ diff --git a/Mathlib/Geometry/Manifold/InteriorBoundary.lean b/Mathlib/Geometry/Manifold/InteriorBoundary.lean index 2fc03bd7d0a9a..e0b0e8b3f65ff 100644 --- a/Mathlib/Geometry/Manifold/InteriorBoundary.lean +++ b/Mathlib/Geometry/Manifold/InteriorBoundary.lean @@ -36,8 +36,8 @@ manifold, interior, boundary similarly for the boundary. - the interior of `M` is open, hence the boundary is closed (and nowhere dense) In finite dimensions, this requires e.g. the homology of spheres. -- the interior of `M` is a smooth manifold without boundary -- `boundary M` is a smooth submanifold (possibly with boundary and corners): +- the interior of `M` is a manifold without boundary +- `boundary M` is a submanifold (possibly with boundary and corners): follows from the corresponding statement for the model with corners `I`; this requires a definition of submanifolds - if `M` is finite-dimensional, its boundary has measure zero diff --git a/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean b/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean index e41ff8cd8caa3..19fdac1d55a45 100644 --- a/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean +++ b/Mathlib/Geometry/Manifold/LocalDiffeomorph.lean @@ -64,7 +64,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {G : Type*} [TopologicalSpace G] (I : ModelWithCorners 𝕜 E H) (J : ModelWithCorners 𝕜 F G) (M : Type*) [TopologicalSpace M] [ChartedSpace H M] - (N : Type*) [TopologicalSpace N] [ChartedSpace G N] (n : ℕ∞) + (N : Type*) [TopologicalSpace N] [ChartedSpace G N] (n : WithTop ℕ∞) section PartialDiffeomorph /-- A partial diffeomorphism on `s` is a function `f : M → N` such that `f` restricts to a diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean index 92e871ba9dfed..fd0e0c104bb73 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean @@ -83,8 +83,8 @@ end ModelWithCorners section Charts -variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] - [SmoothManifoldWithCorners I'' M''] {e : PartialHomeomorph M H} +variable [IsManifold I 1 M] [IsManifold I' 1 M'] + [IsManifold I'' 1 M''] {e : PartialHomeomorph M H} theorem mdifferentiableAt_atlas (h : e ∈ atlas H M) {x : M} (hx : x ∈ e.source) : MDifferentiableAt I I e x := by @@ -93,13 +93,13 @@ theorem mdifferentiableAt_atlas (h : e ∈ atlas H M) {x : M} (hx : x ∈ e.sour have mem : I ((chartAt H x : M → H) x) ∈ I.symm ⁻¹' ((chartAt H x).symm ≫ₕ e).source ∩ range I := by simp only [hx, mfld_simps] - have : (chartAt H x).symm.trans e ∈ contDiffGroupoid ∞ I := + have : (chartAt H x).symm.trans e ∈ contDiffGroupoid 1 I := HasGroupoid.compatible (chart_mem_atlas H x) h have A : - ContDiffOn 𝕜 ∞ (I ∘ (chartAt H x).symm.trans e ∘ I.symm) + ContDiffOn 𝕜 1 (I ∘ (chartAt H x).symm.trans e ∘ I.symm) (I.symm ⁻¹' ((chartAt H x).symm.trans e).source ∩ range I) := this.1 - have B := A.differentiableOn (mod_cast le_top) (I ((chartAt H x : M → H) x)) mem + have B := A.differentiableOn le_rfl (I ((chartAt H x : M → H) x)) mem simp only [mfld_simps] at B rw [inter_comm, differentiableWithinAt_inter] at B · simpa only [mfld_simps] @@ -114,13 +114,13 @@ theorem mdifferentiableAt_atlas_symm (h : e ∈ atlas H M) {x : H} (hx : x ∈ e refine ⟨(e.continuousOn_symm x hx).continuousAt (e.open_target.mem_nhds hx), ?_⟩ have mem : I x ∈ I.symm ⁻¹' (e.symm ≫ₕ chartAt H (e.symm x)).source ∩ range I := by simp only [hx, mfld_simps] - have : e.symm.trans (chartAt H (e.symm x)) ∈ contDiffGroupoid ∞ I := + have : e.symm.trans (chartAt H (e.symm x)) ∈ contDiffGroupoid 1 I := HasGroupoid.compatible h (chart_mem_atlas H _) have A : - ContDiffOn 𝕜 ∞ (I ∘ e.symm.trans (chartAt H (e.symm x)) ∘ I.symm) + ContDiffOn 𝕜 1 (I ∘ e.symm.trans (chartAt H (e.symm x)) ∘ I.symm) (I.symm ⁻¹' (e.symm.trans (chartAt H (e.symm x))).source ∩ range I) := this.1 - have B := A.differentiableOn (mod_cast le_top) (I x) mem + have B := A.differentiableOn le_rfl (I x) mem simp only [mfld_simps] at B rw [inter_comm, differentiableWithinAt_inter] at B · simpa only [mfld_simps] @@ -224,7 +224,7 @@ end PartialHomeomorph.MDifferentiable section extChartAt -variable [SmoothManifoldWithCorners I M] {s : Set M} {x y : M} {z : E} +variable [IsManifold I 1 M] {s : Set M} {x y : M} {z : E} theorem hasMFDerivAt_extChartAt (h : y ∈ (chartAt H x).source) : HasMFDerivAt I 𝓘(𝕜, E) (extChartAt I x) y (mfderiv I I (chartAt H x) y :) := diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean index 7e2cc0458ea20..21412d03b673a 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean @@ -229,14 +229,14 @@ theorem mdifferentiableAt_iff_target {x : M} : rw [← mdifferentiableWithinAt_univ, ← mdifferentiableWithinAt_univ, mdifferentiableWithinAt_iff_target, continuousWithinAt_univ] -section SmoothManifoldWithCorners +section IsManifold variable {e : PartialHomeomorph M H} {e' : PartialHomeomorph M' H'} -open SmoothManifoldWithCorners +open IsManifold theorem mdifferentiableWithinAt_iff_source_of_mem_maximalAtlas - [SmoothManifoldWithCorners I M] (he : e ∈ maximalAtlas I M) (hx : x ∈ e.source) : + [IsManifold I 1 M] (he : e ∈ maximalAtlas I 1 M) (hx : x ∈ e.source) : MDifferentiableWithinAt I I' f s x ↔ MDifferentiableWithinAt 𝓘(𝕜, E) I' (f ∘ (e.extend I).symm) ((e.extend I).symm ⁻¹' s ∩ range I) (e.extend I x) := by @@ -249,14 +249,14 @@ theorem mdifferentiableWithinAt_iff_source_of_mem_maximalAtlas rfl theorem mdifferentiableWithinAt_iff_source_of_mem_source - [SmoothManifoldWithCorners I M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : + [IsManifold I 1 M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : MDifferentiableWithinAt I I' f s x' ↔ MDifferentiableWithinAt 𝓘(𝕜, E) I' (f ∘ (extChartAt I x).symm) ((extChartAt I x).symm ⁻¹' s ∩ range I) (extChartAt I x x') := mdifferentiableWithinAt_iff_source_of_mem_maximalAtlas (chart_mem_maximalAtlas x) hx' theorem mdifferentiableAt_iff_source_of_mem_source - [SmoothManifoldWithCorners I M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : + [IsManifold I 1 M] {x' : M} (hx' : x' ∈ (chartAt H x).source) : MDifferentiableAt I I' f x' ↔ MDifferentiableWithinAt 𝓘(𝕜, E) I' (f ∘ (extChartAt I x).symm) (range I) (extChartAt I x x') := by @@ -264,7 +264,7 @@ theorem mdifferentiableAt_iff_source_of_mem_source preimage_univ, univ_inter] theorem mdifferentiableWithinAt_iff_target_of_mem_source - [SmoothManifoldWithCorners I' M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : + [IsManifold I' 1 M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : MDifferentiableWithinAt I I' f s x ↔ ContinuousWithinAt f s x ∧ MDifferentiableWithinAt I 𝓘(𝕜, E') (extChartAt I' y ∘ f) s x := by simp_rw [MDifferentiableWithinAt] @@ -279,16 +279,16 @@ theorem mdifferentiableWithinAt_iff_target_of_mem_source rfl theorem mdifferentiableAt_iff_target_of_mem_source - [SmoothManifoldWithCorners I' M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : + [IsManifold I' 1 M'] {x : M} {y : M'} (hy : f x ∈ (chartAt H' y).source) : MDifferentiableAt I I' f x ↔ ContinuousAt f x ∧ MDifferentiableAt I 𝓘(𝕜, E') (extChartAt I' y ∘ f) x := by rw [← mdifferentiableWithinAt_univ, mdifferentiableWithinAt_iff_target_of_mem_source hy, continuousWithinAt_univ, ← mdifferentiableWithinAt_univ] -variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] +variable [IsManifold I 1 M] [IsManifold I' 1 M'] -theorem mdifferentiableWithinAt_iff_of_mem_maximalAtlas {x : M} (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hx : x ∈ e.source) (hy : f x ∈ e'.source) : +theorem mdifferentiableWithinAt_iff_of_mem_maximalAtlas {x : M} (he : e ∈ maximalAtlas I 1 M) + (he' : e' ∈ maximalAtlas I' 1 M') (hx : x ∈ e.source) (hy : f x ∈ e'.source) : MDifferentiableWithinAt I I' f s x ↔ ContinuousWithinAt f s x ∧ DifferentiableWithinAt 𝕜 (e'.extend I' ∘ f ∘ (e.extend I).symm) @@ -297,8 +297,9 @@ theorem mdifferentiableWithinAt_iff_of_mem_maximalAtlas {x : M} (he : e ∈ maxi /-- An alternative formulation of `mdifferentiableWithinAt_iff_of_mem_maximalAtlas` if the set if `s` lies in `e.source`. -/ -theorem mdifferentiableWithinAt_iff_image {x : M} (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hs : s ⊆ e.source) (hx : x ∈ e.source) (hy : f x ∈ e'.source) : +theorem mdifferentiableWithinAt_iff_image {x : M} (he : e ∈ maximalAtlas I 1 M) + (he' : e' ∈ maximalAtlas I' 1 M') (hs : s ⊆ e.source) (hx : x ∈ e.source) + (hy : f x ∈ e'.source) : MDifferentiableWithinAt I I' f s x ↔ ContinuousWithinAt f s x ∧ DifferentiableWithinAt 𝕜 (e'.extend I' ∘ f ∘ (e.extend I).symm) (e.extend I '' s) @@ -347,8 +348,8 @@ theorem mdifferentiableAt_iff_of_mem_source {x' : M} {y : M'} (hx : x' ∈ (char (mdifferentiableWithinAt_iff_of_mem_source hx hy).trans <| by rw [continuousWithinAt_univ, preimage_univ, univ_inter] -theorem mdifferentiableOn_iff_of_mem_maximalAtlas (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : +theorem mdifferentiableOn_iff_of_mem_maximalAtlas (he : e ∈ maximalAtlas I 1 M) + (he' : e' ∈ maximalAtlas I' 1 M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : MDifferentiableOn I I' f s ↔ ContinuousOn f s ∧ DifferentiableOn 𝕜 (e'.extend I' ∘ f ∘ (e.extend I).symm) (e.extend I '' s) := by @@ -356,8 +357,8 @@ theorem mdifferentiableOn_iff_of_mem_maximalAtlas (he : e ∈ maximalAtlas I M) exact forall₂_congr fun x hx => mdifferentiableWithinAt_iff_image he he' hs (hs hx) (h2s hx) /-- Differentiability on a set is equivalent to differentiability in the extended charts. -/ -theorem mdifferentiableOn_iff_of_mem_maximalAtlas' (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I' M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : +theorem mdifferentiableOn_iff_of_mem_maximalAtlas' (he : e ∈ maximalAtlas I 1 M) + (he' : e' ∈ maximalAtlas I' 1 M') (hs : s ⊆ e.source) (h2s : MapsTo f s e'.source) : MDifferentiableOn I I' f s ↔ DifferentiableOn 𝕜 (e'.extend I' ∘ f ∘ (e.extend I).symm) (e.extend I '' s) := (mdifferentiableOn_iff_of_mem_maximalAtlas he he' hs h2s).trans <| and_iff_right_of_imp fun h ↦ @@ -454,11 +455,11 @@ theorem mdifferentiable_iff_target : rw [← mdifferentiableOn_univ, mdifferentiableOn_iff_target] simp [continuous_iff_continuousOn_univ] -end SmoothManifoldWithCorners +end IsManifold /-! ### Deducing differentiability from smoothness -/ -variable {n : ℕ∞} +variable {n : WithTop ℕ∞} theorem ContMDiffWithinAt.mdifferentiableWithinAt (hf : ContMDiffWithinAt I I' n f s x) (hn : 1 ≤ n) : MDifferentiableWithinAt I I' f s x := by diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean index 1629d372ecce9..ff24fc3a520eb 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean @@ -7,9 +7,9 @@ import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners import Mathlib.Geometry.Manifold.LocalInvariantProperties /-! -# The derivative of functions between smooth manifolds +# The derivative of functions between manifolds -Let `M` and `M'` be two smooth manifolds with corners over a field `𝕜` (with respective models with +Let `M` and `M'` be two manifolds over a field `𝕜` (with respective models with corners `I` on `(E, H)` and `I'` on `(E', H')`), and let `f : M → M'`. We define the derivative of the function at a point, within a set or along the whole space, mimicking the API for (Fréchet) derivatives. It is denoted by `mfderiv I I' f x`, where "m" stands for "manifold" and @@ -23,7 +23,7 @@ for (Fréchet) derivatives. It is denoted by `mfderiv I I' f x`, where "m" stand and many properties will fail (for instance the chain rule). This is analogous to `UniqueDiffOn 𝕜 s` in a vector space. -Let `f` be a map between smooth manifolds. The following definitions follow the `fderiv` API. +Let `f` be a map between manifolds. The following definitions follow the `fderiv` API. * `mfderiv I I' f x` : the derivative of `f` at `x`, as a continuous linear map from the tangent space at `x` to the tangent space at `f x`. If the map is not differentiable, this is `0`. @@ -107,7 +107,7 @@ section DerivativesDefinitions /-! ### Derivative of maps between manifolds -The derivative of a smooth map `f` between smooth manifold `M` and `M'` at `x` is a bounded linear +The derivative of a map `f` between manifolds `M` and `M'` at `x` is a bounded linear map from the tangent space to `M` at `x`, to the tangent space to `M'` at `f x`. Since we defined the tangent space using one specific chart, the formula for the derivative is written in terms of this specific chart. @@ -147,7 +147,7 @@ theorem differentiableWithinAtProp_self_target {f : H → E'} {s : Set H} {x : H /-- Being differentiable in the model space is a local property, invariant under smooth maps. Therefore, it will lift nicely to manifolds. -/ theorem differentiableWithinAt_localInvariantProp : - (contDiffGroupoid ∞ I).LocalInvariantProp (contDiffGroupoid ∞ I') + (contDiffGroupoid 1 I).LocalInvariantProp (contDiffGroupoid 1 I') (DifferentiableWithinAtProp I I') := { is_local := by intro s x u f u_open xu @@ -167,7 +167,7 @@ theorem differentiableWithinAt_localInvariantProp : rw [this] at h have : I (e x) ∈ I.symm ⁻¹' e.target ∩ Set.range I := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he).2.contDiffWithinAt this - convert (h.comp' _ (this.differentiableWithinAt (mod_cast le_top))).mono_of_mem_nhdsWithin _ + convert (h.comp' _ (this.differentiableWithinAt le_rfl)).mono_of_mem_nhdsWithin _ using 1 · ext y; simp only [mfld_simps] refine @@ -188,7 +188,7 @@ theorem differentiableWithinAt_localInvariantProp : have A : (I' ∘ f ∘ I.symm) (I x) ∈ I'.symm ⁻¹' e'.source ∩ Set.range I' := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he').1.contDiffWithinAt A - convert (this.differentiableWithinAt (mod_cast le_top)).comp _ h _ + convert (this.differentiableWithinAt le_rfl).comp _ h _ · ext y; simp only [mfld_simps] · intro y hy; simp only [mfld_simps] at hy; simpa only [hy, mfld_simps] using hs hy.1 } @@ -323,7 +323,7 @@ def HasMFDerivAt (f : M → M') (x : M) (f' : TangentSpace I x →L[𝕜] Tangen open Classical in variable (I I') in -/-- Let `f` be a function between two smooth manifolds. Then `mfderivWithin I I' f s x` is the +/-- Let `f` be a function between two manifolds. Then `mfderivWithin I I' f s x` is the derivative of `f` at `x` within `s`, as a continuous linear map from the tangent space at `x` to the tangent space at `f x`. -/ def mfderivWithin (f : M → M') (s : Set M) (x : M) : TangentSpace I x →L[𝕜] TangentSpace I' (f x) := @@ -335,7 +335,7 @@ def mfderivWithin (f : M → M') (s : Set M) (x : M) : TangentSpace I x →L[ open Classical in variable (I I') in -/-- Let `f` be a function between two smooth manifolds. Then `mfderiv I I' f x` is the derivative of +/-- Let `f` be a function between two manifolds. Then `mfderiv I I' f x` is the derivative of `f` at `x`, as a continuous linear map from the tangent space at `x` to the tangent space at `f x`. -/ def mfderiv (f : M → M') (x : M) : TangentSpace I x →L[𝕜] TangentSpace I' (f x) := diff --git a/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean b/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean index 2e727c4ef5022..d920ed0074190 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean @@ -15,29 +15,29 @@ differentiability. -/ -open Set ChartedSpace SmoothManifoldWithCorners +open Set ChartedSpace IsManifold open scoped Topology Manifold -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} -- declare a charted space `M` over the pair `(E, H)`. {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - -- declare a smooth manifold `M'` over the pair `(E', H')`. + -- declare a `C^n` manifold `M'` over the pair `(E', H')`. {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - [SmoothManifoldWithCorners I' M'] - -- declare a smooth manifold `N` over the pair `(F, G)`. + [IsManifold I' n M'] + -- declare a `C^n` manifold `N` over the pair `(F, G)`. {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type*} [TopologicalSpace G] {J : ModelWithCorners 𝕜 F G} {N : Type*} [TopologicalSpace N] [ChartedSpace G N] - [SmoothManifoldWithCorners J N] - -- declare a smooth manifold `N'` over the pair `(F', G')`. + [IsManifold J n N] + -- declare a `C^n` manifold `N'` over the pair `(F', G')`. {F' : Type*} [NormedAddCommGroup F'] [NormedSpace 𝕜 F'] {G' : Type*} [TopologicalSpace G'] {J' : ModelWithCorners 𝕜 F' G'} {N' : Type*} [TopologicalSpace N'] [ChartedSpace G' N'] - [SmoothManifoldWithCorners J' N'] + [IsManifold J' n N'] -- F₁, F₂, F₃, F₄ are normed spaces {F₁ : Type*} [NormedAddCommGroup F₁] [NormedSpace 𝕜 F₁] {F₂ : Type*} [NormedAddCommGroup F₂] [NormedSpace 𝕜 F₂] {F₃ : Type*} [NormedAddCommGroup F₃] [NormedSpace 𝕜 F₃] {F₄ : Type*} diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Tangent.lean b/Mathlib/Geometry/Manifold/MFDeriv/Tangent.lean index 2c048b112606f..1493911dd2a26 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Tangent.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Tangent.lean @@ -22,10 +22,10 @@ open scoped Manifold variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] + [IsManifold I 1 M] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - [SmoothManifoldWithCorners I' M'] + [IsManifold I' 1 M'] /-- The derivative of the chart at a base point is the chart of the tangent bundle, composed with diff --git a/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean index 2382f7093e3f8..1c23a54eb9e67 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean @@ -82,7 +82,7 @@ theorem UniqueMDiffOn.uniqueMDiffOn_preimage (hs : UniqueMDiffOn I s) {e : Parti (he : e.MDifferentiable I I') : UniqueMDiffOn I' (e.target ∩ e.symm ⁻¹' s) := fun _x hx ↦ e.right_inv hx.1 ▸ (hs _ hx.2).preimage_partialHomeomorph he (e.map_target hx.1) -variable [SmoothManifoldWithCorners I M] in +variable [IsManifold I 1 M] in /-- If a set in a manifold has the unique derivative property, then its pullback by any extended chart, in the vector space, also has the unique derivative property. -/ theorem UniqueMDiffOn.uniqueMDiffOn_target_inter (hs : UniqueMDiffOn I s) (x : M) : @@ -94,21 +94,21 @@ theorem UniqueMDiffOn.uniqueMDiffOn_target_inter (hs : UniqueMDiffOn I s) (x : M (fun y hy ↦ hasMFDerivWithinAt_extChartAt hy.2) fun y hy ↦ ((mdifferentiable_chart _).mfderiv_surjective hy.2).denseRange -variable [SmoothManifoldWithCorners I M] in +variable [IsManifold I 1 M] in /-- If a set in a manifold has the unique derivative property, then its pullback by any extended chart, in the vector space, also has the unique derivative property. -/ theorem UniqueMDiffOn.uniqueDiffOn_target_inter (hs : UniqueMDiffOn I s) (x : M) : UniqueDiffOn 𝕜 ((extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' s) := (hs.uniqueMDiffOn_target_inter x).uniqueDiffOn -variable [SmoothManifoldWithCorners I M] in +variable [IsManifold I 1 M] in theorem UniqueMDiffOn.uniqueDiffWithinAt_range_inter (hs : UniqueMDiffOn I s) (x : M) (y : E) (hy : y ∈ (extChartAt I x).target ∩ (extChartAt I x).symm ⁻¹' s) : UniqueDiffWithinAt 𝕜 (range I ∩ (extChartAt I x).symm ⁻¹' s) y := by apply (hs.uniqueDiffOn_target_inter x y hy).mono apply inter_subset_inter_left _ (extChartAt_target_subset_range x) -variable [SmoothManifoldWithCorners I M] in +variable [IsManifold I 1 M] in /-- When considering functions between manifolds, this statement shows up often. It entails the unique differential of the pullback in extended charts of the set where the function can be read in the charts. -/ @@ -197,9 +197,9 @@ alias UniqueMDiffOn.smooth_bundle_preimage := UniqueMDiffOn.bundle_preimage /- TODO: move me to `Mathlib.Geometry.Manifold.VectorBundle.MDifferentiable` once #19636 is in. -/ variable [∀ b, AddCommMonoid (Z b)] [∀ b, Module 𝕜 (Z b)] [VectorBundle 𝕜 F Z] -theorem Trivialization.mdifferentiable [SmoothVectorBundle F Z I] +theorem Trivialization.mdifferentiable [ContMDiffVectorBundle 1 F Z I] (e : Trivialization F (π F Z)) [MemTrivializationAtlas e] : e.MDifferentiable (I.prod 𝓘(𝕜, F)) (I.prod 𝓘(𝕜, F)) := - ⟨e.contMDiffOn.mdifferentiableOn le_top, e.contMDiffOn_symm.mdifferentiableOn le_top⟩ + ⟨e.contMDiffOn.mdifferentiableOn le_rfl, e.contMDiffOn_symm.mdifferentiableOn le_rfl⟩ end UniqueMDiff diff --git a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean index 5a4131d403b71..ef5099d8835ea 100644 --- a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean +++ b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean @@ -58,10 +58,7 @@ smooth bump function, partition of unity universe uι uE uH uM uF open Function Filter Module Set -open scoped Topology Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped Topology Manifold ContDiff noncomputable section @@ -163,7 +160,7 @@ theorem sum_le_one (x : M) : ∑ᶠ i, f i x ≤ 1 := def toPartitionOfUnity : PartitionOfUnity ι M s := { f with toFun := fun i => f i } -theorem contMDiff_sum : ContMDiff I 𝓘(ℝ) ⊤ fun x => ∑ᶠ i, f i x := +theorem contMDiff_sum : ContMDiff I 𝓘(ℝ) ∞ fun x => ∑ᶠ i, f i x := contMDiff_finsum (fun i => (f i).contMDiff) f.locallyFinite @[deprecated (since := "2024-11-21")] alias smooth_sum := contMDiff_sum @@ -181,7 +178,8 @@ theorem finsum_smul_mem_convex {g : ι → M → F} {t : Set F} {x : M} (hx : x theorem contMDiff_smul {g : M → F} {i} (hg : ∀ x ∈ tsupport (f i), ContMDiffAt I 𝓘(ℝ, F) n g x) : ContMDiff I 𝓘(ℝ, F) n fun x => f i x • g x := contMDiff_of_tsupport fun x hx => - ((f i).contMDiff.contMDiffAt.of_le le_top).smul <| hg x <| tsupport_smul_subset_left _ _ hx + ((f i).contMDiff.contMDiffAt.of_le (mod_cast le_top)).smul <| hg x + <| tsupport_smul_subset_left _ _ hx @[deprecated (since := "2024-11-21")] alias smooth_smul := contMDiff_smul @@ -201,7 +199,7 @@ theorem contMDiffAt_finsum {x₀ : M} {g : ι → M → F} ContMDiffAt I 𝓘(ℝ, F) n (fun x ↦ ∑ᶠ i, f i x • g i x) x₀ := by refine _root_.contMDiffAt_finsum (f.locallyFinite.smul_left _) fun i ↦ ?_ by_cases hx : x₀ ∈ tsupport (f i) - · exact ContMDiffAt.smul ((f i).contMDiff.of_le le_top).contMDiffAt (hφ i hx) + · exact ContMDiffAt.smul ((f i).contMDiff.of_le (mod_cast le_top)).contMDiffAt (hφ i hx) · exact contMDiffAt_of_not_mem (compl_subset_compl.mpr (tsupport_smul_subset_left (f i) (g i)) hx) n @@ -300,11 +298,11 @@ end SmoothPartitionOfUnity namespace BumpCovering --- Repeat variables to drop `[FiniteDimensional ℝ E]` and `[SmoothManifoldWithCorners I M]` +-- Repeat variables to drop `[FiniteDimensional ℝ E]` and `[IsManifold I ∞ M]` theorem contMDiff_toPartitionOfUnity {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type uH} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} {M : Type uM} [TopologicalSpace M] [ChartedSpace H M] {s : Set M} (f : BumpCovering ι M s) - (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) (i : ι) : ContMDiff I 𝓘(ℝ) ⊤ (f.toPartitionOfUnity i) := + (hf : ∀ i, ContMDiff I 𝓘(ℝ) ∞ (f i)) (i : ι) : ContMDiff I 𝓘(ℝ) ∞ (f.toPartitionOfUnity i) := (hf i).mul <| (contMDiff_finprod_cond fun j _ => contMDiff_const.sub (hf j)) <| by simp only [Pi.sub_def, mulSupport_one_sub] exact f.locallyFinite @@ -321,24 +319,24 @@ In our formalization, not every `f : BumpCovering ι M s` with smooth functions `SmoothBumpCovering`; instead, a `SmoothBumpCovering` is a covering by supports of `SmoothBumpFunction`s. So, we define `BumpCovering.toSmoothPartitionOfUnity`, then reuse it in `SmoothBumpCovering.toSmoothPartitionOfUnity`. -/ -def toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) : +def toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ∞ (f i)) : SmoothPartitionOfUnity ι I M s := { f.toPartitionOfUnity with toFun := fun i => ⟨f.toPartitionOfUnity i, f.contMDiff_toPartitionOfUnity hf i⟩ } @[simp] theorem toSmoothPartitionOfUnity_toPartitionOfUnity (f : BumpCovering ι M s) - (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) : + (hf : ∀ i, ContMDiff I 𝓘(ℝ) ∞ (f i)) : (f.toSmoothPartitionOfUnity hf).toPartitionOfUnity = f.toPartitionOfUnity := rfl @[simp] -theorem coe_toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) +theorem coe_toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ∞ (f i)) (i : ι) : ⇑(f.toSmoothPartitionOfUnity hf i) = f.toPartitionOfUnity i := rfl theorem IsSubordinate.toSmoothPartitionOfUnity {f : BumpCovering ι M s} {U : ι → Set M} - (h : f.IsSubordinate U) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) : + (h : f.IsSubordinate U) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ∞ (f i)) : (f.toSmoothPartitionOfUnity hf).IsSubordinate U := h.toPartitionOfUnity @@ -366,7 +364,7 @@ theorem IsSubordinate.support_subset {fs : SmoothBumpCovering ι I M s} {U : M Subset.trans subset_closure (h i) variable (I) in -/-- Let `M` be a smooth manifold with corners modelled on a finite dimensional real vector space. +/-- Let `M` be a smooth manifold modelled on a finite dimensional real vector space. Suppose also that `M` is a Hausdorff `σ`-compact topological space. Let `s` be a closed set in `M` and `U : M → Set M` be a collection of sets such that `U x ∈ 𝓝 x` for every `x ∈ s`. Then there exists a smooth bump covering of `s` that is subordinate to `U`. -/ @@ -431,7 +429,7 @@ protected def fintype [CompactSpace M] : Fintype ι := fs.locallyFinite.fintypeOfCompact fun i => (fs i).nonempty_support variable [T2Space M] -variable [SmoothManifoldWithCorners I M] +variable [IsManifold I ∞ M] /-- Reinterpret a `SmoothBumpCovering` as a continuous `BumpCovering`. Note that not every `f : BumpCovering ι M s` with smooth functions `f i` is a `SmoothBumpCovering`. -/ @@ -493,7 +491,7 @@ end SmoothBumpCovering variable (I) variable [FiniteDimensional ℝ E] -variable [SmoothManifoldWithCorners I M] +variable [IsManifold I ∞ M] /-- Given two disjoint closed sets `s, t` in a Hausdorff σ-compact finite dimensional manifold, there exists an infinitely smooth function that is equal to `0` on `s` and to `1` on `t`. @@ -566,7 +564,7 @@ theorem exists_isSubordinate {s : Set M} (hs : IsClosed s) (U : ι → Set M) (h haveI : LocallyCompactSpace M := ChartedSpace.locallyCompactSpace H M -- porting note(https://github.com/leanprover/std4/issues/116): -- split `rcases` into `have` + `rcases` - have := BumpCovering.exists_isSubordinate_of_prop (ContMDiff I 𝓘(ℝ) ⊤) ?_ hs U ho hU + have := BumpCovering.exists_isSubordinate_of_prop (ContMDiff I 𝓘(ℝ) ∞) ?_ hs U ho hU · rcases this with ⟨f, hf, hfU⟩ exact ⟨f.toSmoothPartitionOfUnity hf, hfU.toSmoothPartitionOfUnity hf⟩ · intro s t hs ht hd @@ -614,7 +612,7 @@ Then there exists a smooth function `g : C^∞⟮I, M; 𝓘(ℝ, F), F⟯` such See also `exists_contMDiffOn_forall_mem_convex_of_local` and `exists_smooth_forall_mem_convex_of_local_const`. -/ theorem exists_smooth_forall_mem_convex_of_local (ht : ∀ x, Convex ℝ (t x)) - (Hloc : ∀ x : M, ∃ U ∈ 𝓝 x, ∃ g : M → F, ContMDiffOn I 𝓘(ℝ, F) ⊤ g U ∧ ∀ y ∈ U, g y ∈ t y) : + (Hloc : ∀ x : M, ∃ U ∈ 𝓝 x, ∃ g : M → F, ContMDiffOn I 𝓘(ℝ, F) ∞ g U ∧ ∀ y ∈ U, g y ∈ t y) : ∃ g : C^∞⟮I, M; 𝓘(ℝ, F), F⟯, ∀ x, g x ∈ t x := exists_contMDiffOn_forall_mem_convex_of_local I ht Hloc @@ -634,7 +632,7 @@ finite family of closed sets, let `U : ι → Set M` be a family of open sets su all `i`. Then there exists a positive smooth function `δ : M → ℝ≥0` such that for any `i` and `x ∈ K i`, we have `EMetric.closedBall x (δ x) ⊆ U i`. -/ theorem Emetric.exists_smooth_forall_closedBall_subset {M} [EMetricSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] [SigmaCompactSpace M] {K : ι → Set M} {U : ι → Set M} + [IsManifold I ∞ M] [SigmaCompactSpace M] {K : ι → Set M} {U : ι → Set M} (hK : ∀ i, IsClosed (K i)) (hU : ∀ i, IsOpen (U i)) (hKU : ∀ i, K i ⊆ U i) (hfin : LocallyFinite K) : ∃ δ : C^∞⟮I, M; 𝓘(ℝ, ℝ), ℝ⟯, @@ -649,7 +647,7 @@ family of closed sets, let `U : ι → Set M` be a family of open sets such that `i`. Then there exists a positive smooth function `δ : M → ℝ≥0` such that for any `i` and `x ∈ K i`, we have `Metric.closedBall x (δ x) ⊆ U i`. -/ theorem Metric.exists_smooth_forall_closedBall_subset {M} [MetricSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] [SigmaCompactSpace M] {K : ι → Set M} {U : ι → Set M} + [IsManifold I ∞ M] [SigmaCompactSpace M] {K : ι → Set M} {U : ι → Set M} (hK : ∀ i, IsClosed (K i)) (hU : ∀ i, IsOpen (U i)) (hKU : ∀ i, K i ⊆ U i) (hfin : LocallyFinite K) : ∃ δ : C^∞⟮I, M; 𝓘(ℝ, ℝ), ℝ⟯, @@ -660,7 +658,7 @@ theorem Metric.exists_smooth_forall_closedBall_subset {M} [MetricSpace M] [Chart exact hδ i x hx lemma IsOpen.exists_msmooth_support_eq_aux {s : Set H} (hs : IsOpen s) : - ∃ f : H → ℝ, f.support = s ∧ ContMDiff I 𝓘(ℝ) ⊤ f ∧ Set.range f ⊆ Set.Icc 0 1 := by + ∃ f : H → ℝ, f.support = s ∧ ContMDiff I 𝓘(ℝ) ∞ f ∧ Set.range f ⊆ Set.Icc 0 1 := by have h's : IsOpen (I.symm ⁻¹' s) := I.continuous_symm.isOpen_preimage _ hs rcases h's.exists_smooth_support_eq with ⟨f, f_supp, f_diff, f_range⟩ refine ⟨f ∘ I, ?_, ?_, ?_⟩ @@ -672,11 +670,11 @@ lemma IsOpen.exists_msmooth_support_eq_aux {s : Set H} (hs : IsOpen s) : /-- Given an open set in a finite-dimensional real manifold, there exists a nonnegative smooth function with support equal to `s`. -/ theorem IsOpen.exists_msmooth_support_eq {s : Set M} (hs : IsOpen s) : - ∃ f : M → ℝ, f.support = s ∧ ContMDiff I 𝓘(ℝ) ⊤ f ∧ ∀ x, 0 ≤ f x := by + ∃ f : M → ℝ, f.support = s ∧ ContMDiff I 𝓘(ℝ) ∞ f ∧ ∀ x, 0 ≤ f x := by rcases SmoothPartitionOfUnity.exists_isSubordinate_chartAt_source I M with ⟨f, hf⟩ have A : ∀ (c : M), ∃ g : H → ℝ, g.support = (chartAt H c).target ∩ (chartAt H c).symm ⁻¹' s ∧ - ContMDiff I 𝓘(ℝ) ⊤ g ∧ Set.range g ⊆ Set.Icc 0 1 := by + ContMDiff I 𝓘(ℝ) ∞ g ∧ Set.range g ⊆ Set.Icc 0 1 := by intro i apply IsOpen.exists_msmooth_support_eq_aux exact PartialHomeomorph.isOpen_inter_preimage_symm _ hs @@ -713,7 +711,7 @@ theorem IsOpen.exists_msmooth_support_eq {s : Set M} (hs : IsOpen s) : · apply SmoothPartitionOfUnity.contMDiff_finsum_smul intro c x hx apply (g_diff c (chartAt H c x)).comp - exact contMDiffAt_of_mem_maximalAtlas (SmoothManifoldWithCorners.chart_mem_maximalAtlas _) + exact contMDiffAt_of_mem_maximalAtlas (IsManifold.chart_mem_maximalAtlas _) (hf c hx) · intro x apply finsum_nonneg (fun c ↦ h''g c x) @@ -723,7 +721,7 @@ exists a smooth function with support equal to `s`, taking values in `[0,1]`, an exactly on `t`. -/ theorem exists_msmooth_support_eq_eq_one_iff {s t : Set M} (hs : IsOpen s) (ht : IsClosed t) (h : t ⊆ s) : - ∃ f : M → ℝ, ContMDiff I 𝓘(ℝ) ⊤ f ∧ range f ⊆ Icc 0 1 ∧ support f = s + ∃ f : M → ℝ, ContMDiff I 𝓘(ℝ) ∞ f ∧ range f ⊆ Icc 0 1 ∧ support f = s ∧ (∀ x, x ∈ t ↔ f x = 1) := by /- Take `f` with support equal to `s`, and `g` with support equal to `tᶜ`. Then `f / (f + g)` satisfies the conclusion of the theorem. -/ @@ -761,7 +759,7 @@ there exists an infinitely smooth function that is equal to `0` exactly on `s` a exactly on `t`. See also `exists_smooth_zero_one_of_isClosed` for a slightly weaker version. -/ theorem exists_msmooth_zero_iff_one_iff_of_isClosed {s t : Set M} (hs : IsClosed s) (ht : IsClosed t) (hd : Disjoint s t) : - ∃ f : M → ℝ, ContMDiff I 𝓘(ℝ) ⊤ f ∧ range f ⊆ Icc 0 1 ∧ (∀ x, x ∈ s ↔ f x = 0) + ∃ f : M → ℝ, ContMDiff I 𝓘(ℝ) ∞ f ∧ range f ⊆ Icc 0 1 ∧ (∀ x, x ∈ s ↔ f x = 0) ∧ (∀ x, x ∈ t ↔ f x = 1) := by rcases exists_msmooth_support_eq_eq_one_iff I hs.isOpen_compl ht hd.subset_compl_left with ⟨f, f_diff, f_range, fs, ft⟩ diff --git a/Mathlib/Geometry/Manifold/PoincareConjecture.lean b/Mathlib/Geometry/Manifold/PoincareConjecture.lean index 97601179316c1..35f1afcb078dd 100644 --- a/Mathlib/Geometry/Manifold/PoincareConjecture.lean +++ b/Mathlib/Geometry/Manifold/PoincareConjecture.lean @@ -19,7 +19,7 @@ and `≃ₘ⟮𝓡 n, 𝓡 n⟯` stands for a diffeomorphism, where `𝓡 n` is space viewed as a model space. -/ -open scoped Manifold +open scoped Manifold ContDiff open Metric (sphere) local macro:max "ℝ"n:superscript(term) : term => `(EuclideanSpace ℝ (Fin $(⟨n.raw[0]⟩))) @@ -46,7 +46,7 @@ proof_wanted SimplyConnectedSpace.nonempty_homeomorph_sphere_three /-- The 3-dimensional smooth Poincaré conjecture (proven by Perelman) -/ proof_wanted SimplyConnectedSpace.nonempty_diffeomorph_sphere_three - [T2Space M] [ChartedSpace ℝ³ M] [SmoothManifoldWithCorners (𝓡 3) M] + [T2Space M] [ChartedSpace ℝ³ M] [IsManifold (𝓡 3) ∞ M] [SimplyConnectedSpace M] [CompactSpace M] : Nonempty (M ≃ₘ⟮𝓡 3, 𝓡 3⟯ 𝕊³) @@ -54,13 +54,13 @@ proof_wanted SimplyConnectedSpace.nonempty_diffeomorph_sphere_three open for n = 4, and it is conjectured that there are no other n > 4 for which it is true (Conjecture 1.17, https://annals.math.princeton.edu/2017/186-2/p03). -/ def ContinuousMap.HomotopyEquiv.NonemptyDiffeomorphSphere (n : ℕ) : Prop := - ∀ (_ : ChartedSpace ℝⁿ M) (_ : SmoothManifoldWithCorners (𝓡 n) M), + ∀ (_ : ChartedSpace ℝⁿ M) (_ : IsManifold (𝓡 n) ∞ M), M ≃ₕ 𝕊ⁿ → Nonempty (M ≃ₘ⟮𝓡 n, 𝓡 n⟯ 𝕊ⁿ) /-- The existence of an exotic 7-sphere (due to John Milnor) -/ proof_wanted exists_homeomorph_isEmpty_diffeomorph_sphere_seven : ∃ (M : Type) (_ : TopologicalSpace M) (_ : ChartedSpace ℝ⁷ M) - (_ : SmoothManifoldWithCorners (𝓡 7) M) (_homeo : M ≃ₜ 𝕊⁷), + (_ : IsManifold (𝓡 7) ∞ M) (_homeo : M ≃ₜ 𝕊⁷), IsEmpty (M ≃ₘ⟮𝓡 7, 𝓡 7⟯ 𝕊⁷) /-- The existence of a small exotic ℝ⁴, i.e. an open subset of ℝ⁴ that is homeomorphic but diff --git a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean index 787dce0f8a583..108d4c93e2b2b 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean @@ -8,7 +8,7 @@ import Mathlib.Geometry.RingedSpace.LocallyRingedSpace /-! # Smooth manifolds as locally ringed spaces -This file equips a smooth manifold-with-corners with the structure of a locally ringed space. +This file equips a smooth manifold with the structure of a locally ringed space. ## Main results @@ -18,8 +18,7 @@ This file equips a smooth manifold-with-corners with the structure of a locally ## Main definitions -* `SmoothManifoldWithCorners.locallyRingedSpace`: A smooth manifold-with-corners can be considered - as a locally ringed space. +* `IsManifold.locallyRingedSpace`: A smooth manifold can be considered as a locally ringed space. ## TODO @@ -31,9 +30,7 @@ smooth manifolds. noncomputable section universe u -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped ContDiff variable {𝕜 : Type u} [NontriviallyNormedField 𝕜] {EM : Type*} [NormedAddCommGroup EM] [NormedSpace 𝕜 EM] @@ -81,7 +78,7 @@ theorem smoothSheafCommRing.isUnit_stalk_iff {x : M} -- Let `g` be the pointwise inverse of `f` on `V`, which is smooth since `f` is nonzero there let g : C^∞⟮IM, V; 𝓘(𝕜), 𝕜⟯ := ⟨(f ∘ Set.inclusion hUV)⁻¹, ?_⟩ -- The germ of `g` is inverse to the germ of `f`, so `f` is a unit - · refine ⟨⟨S.germ _ x (hxV) (SmoothMap.restrictRingHom IM 𝓘(𝕜) 𝕜 hUV f), S.germ _ x hxV g, + · refine ⟨⟨S.germ _ x (hxV) (ContMDiffMap.restrictRingHom IM 𝓘(𝕜) 𝕜 hUV f), S.germ _ x hxV g, ?_, ?_⟩, S.germ_res_apply hUV.hom x hxV f⟩ · rw [← map_mul] -- Qualified the name to avoid Lean not finding a `OneHomClass` https://github.com/leanprover-community/mathlib4/pull/8386 @@ -112,7 +109,7 @@ theorem smoothSheafCommRing.nonunits_stalk (x : M) : rw [mem_nonunits_iff, not_iff_comm, Iff.comm] apply smoothSheafCommRing.isUnit_stalk_iff -/-- The stalks of the structure sheaf of a smooth manifold-with-corners are local rings. -/ +/-- The stalks of the structure sheaf of a smooth manifold are local rings. -/ instance smoothSheafCommRing.instLocalRing_stalk (x : M) : IsLocalRing ((smoothSheafCommRing IM 𝓘(𝕜) M 𝕜).presheaf.stalk x) := by apply IsLocalRing.of_nonunits_add @@ -122,9 +119,12 @@ instance smoothSheafCommRing.instLocalRing_stalk (x : M) : variable (M) -/-- A smooth manifold-with-corners can be considered as a locally ringed space. -/ -def SmoothManifoldWithCorners.locallyRingedSpace : LocallyRingedSpace where +/-- A smooth manifold can be considered as a locally ringed space. -/ +def IsManifold.locallyRingedSpace : LocallyRingedSpace where carrier := TopCat.of M presheaf := smoothPresheafCommRing IM 𝓘(𝕜) M 𝕜 IsSheaf := (smoothSheafCommRing IM 𝓘(𝕜) M 𝕜).cond isLocalRing x := smoothSheafCommRing.instLocalRing_stalk IM x + +@[deprecated (since := "2025-01-09")] +noncomputable alias SmoothManifoldWithCorners.locallyRingedSpace := IsManifold.locallyRingedSpace diff --git a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean index 1489ae3daa633..a9c0591e29d4f 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean @@ -65,10 +65,7 @@ https://github.com/leanprover-community/mathlib4/pull/5726. noncomputable section open TopologicalSpace Opposite - -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped ContDiff universe u @@ -87,13 +84,13 @@ section TypeCat /-- The sheaf of smooth functions from `M` to `N`, as a sheaf of types. -/ def smoothSheaf : TopCat.Sheaf (Type u) (TopCat.of M) := - (contDiffWithinAt_localInvariantProp (I := IM) (I' := I) ⊤).sheaf M N + (contDiffWithinAt_localInvariantProp (I := IM) (I' := I) ∞).sheaf M N variable {M} instance smoothSheaf.coeFun (U : (Opens (TopCat.of M))ᵒᵖ) : CoeFun ((smoothSheaf IM I M N).presheaf.obj U) (fun _ ↦ ↑(unop U) → N) := - (contDiffWithinAt_localInvariantProp ⊤).sheafHasCoeToFun _ _ _ + (contDiffWithinAt_localInvariantProp ∞).sheafHasCoeToFun _ _ _ open Manifold in /-- The object of `smoothSheaf IM I M N` for the open set `U` in `M` is @@ -140,12 +137,12 @@ variable {IM I N} @[simp] lemma smoothSheaf.eval_germ (U : Opens M) (x : M) (hx : x ∈ U) (f : (smoothSheaf IM I M N).presheaf.obj (op U)) : smoothSheaf.eval IM I N (x : M) ((smoothSheaf IM I M N).presheaf.germ U x hx f) = f ⟨x, hx⟩ := - TopCat.stalkToFiber_germ ((contDiffWithinAt_localInvariantProp ⊤).localPredicate M N) _ _ _ _ + TopCat.stalkToFiber_germ ((contDiffWithinAt_localInvariantProp ∞).localPredicate M N) _ _ _ _ lemma smoothSheaf.contMDiff_section {U : (Opens (TopCat.of M))ᵒᵖ} (f : (smoothSheaf IM I M N).presheaf.obj U) : - ContMDiff IM I ⊤ f := - (contDiffWithinAt_localInvariantProp ⊤).section_spec _ _ _ _ + ContMDiff IM I ∞ f := + (contDiffWithinAt_localInvariantProp ∞).section_spec _ _ _ _ @[deprecated (since := "2024-11-21")] alias smoothSheaf.smooth_section := smoothSheaf.contMDiff_section @@ -153,13 +150,13 @@ alias smoothSheaf.smooth_section := smoothSheaf.contMDiff_section end TypeCat section LieGroup -variable [Group G] [LieGroup I G] +variable [Group G] [LieGroup I ∞ G] open Manifold in @[to_additive] noncomputable instance (U : (Opens (TopCat.of M))ᵒᵖ) : Group ((smoothSheaf IM I M G).presheaf.obj U) := - (SmoothMap.group : Group C^∞⟮IM, (unop U : Opens M); I, G⟯) + (ContMDiffMap.group : Group C^∞⟮IM, (unop U : Opens M); I, G⟯) /-- The presheaf of smooth functions from `M` to `G`, for `G` a Lie group, as a presheaf of groups. -/ @@ -168,7 +165,7 @@ presheaf of additive groups."] noncomputable def smoothPresheafGroup : TopCat.Presheaf Grp.{u} (TopCat.of M) := { obj := fun U ↦ Grp.of ((smoothSheaf IM I M G).presheaf.obj U) map := fun h ↦ Grp.ofHom <| - SmoothMap.restrictMonoidHom IM I G <| CategoryTheory.leOfHom h.unop + ContMDiffMap.restrictMonoidHom IM I G <| CategoryTheory.leOfHom h.unop map_id := fun _ ↦ rfl map_comp := fun _ _ ↦ rfl } @@ -185,12 +182,12 @@ noncomputable def smoothSheafGroup : TopCat.Sheaf Grp.{u} (TopCat.of M) := end LieGroup section CommLieGroup -variable [CommGroup A] [CommGroup A'] [LieGroup I A] [LieGroup I' A'] +variable [CommGroup A] [CommGroup A'] [LieGroup I ∞ A] [LieGroup I' ∞ A'] open Manifold in @[to_additive] noncomputable instance (U : (Opens (TopCat.of M))ᵒᵖ) : CommGroup ((smoothSheaf IM I M A).presheaf.obj U) := - (SmoothMap.commGroup : CommGroup C^∞⟮IM, (unop U : Opens M); I, A⟯) + (ContMDiffMap.commGroup : CommGroup C^∞⟮IM, (unop U : Opens M); I, A⟯) /-- The presheaf of smooth functions from `M` to `A`, for `A` an abelian Lie group, as a presheaf of abelian groups. -/ @@ -199,7 +196,7 @@ group, as a presheaf of additive abelian groups."] noncomputable def smoothPresheafCommGroup : TopCat.Presheaf CommGrp.{u} (TopCat.of M) := { obj := fun U ↦ CommGrp.of ((smoothSheaf IM I M A).presheaf.obj U) map := fun h ↦ CommGrp.ofHom <| - SmoothMap.restrictMonoidHom IM I A <| CategoryTheory.leOfHom h.unop + ContMDiffMap.restrictMonoidHom IM I A <| CategoryTheory.leOfHom h.unop map_id := fun _ ↦ rfl map_comp := fun _ _ ↦ rfl } @@ -220,27 +217,27 @@ noncomputable def smoothSheafCommGroup : TopCat.Sheaf CommGrp.{u} (TopCat.of M) @[to_additive "For a manifold `M` and a smooth homomorphism `φ` between abelian additive Lie groups `A`, `A'`, the 'left-composition-by-`φ`' morphism of sheaves from `smoothSheafAddCommGroup IM I M A` to `smoothSheafAddCommGroup IM I' M A'`."] -def smoothSheafCommGroup.compLeft (φ : A →* A') (hφ : ContMDiff I I' ⊤ φ) : +def smoothSheafCommGroup.compLeft (φ : A →* A') (hφ : ContMDiff I I' ∞ φ) : smoothSheafCommGroup IM I M A ⟶ smoothSheafCommGroup IM I' M A' := CategoryTheory.Sheaf.Hom.mk <| - { app := fun _ ↦ CommGrp.ofHom <| SmoothMap.compLeftMonoidHom _ _ φ hφ + { app := fun _ ↦ CommGrp.ofHom <| ContMDiffMap.compLeftMonoidHom _ _ φ hφ naturality := fun _ _ _ ↦ rfl } end CommLieGroup -section SmoothRing -variable [Ring R] [SmoothRing I R] +section ContMDiffRing +variable [Ring R] [ContMDiffRing I ∞ R] open Manifold in instance (U : (Opens (TopCat.of M))ᵒᵖ) : Ring ((smoothSheaf IM I M R).presheaf.obj U) := - (SmoothMap.ring : Ring C^∞⟮IM, (unop U : Opens M); I, R⟯) + (ContMDiffMap.ring : Ring C^∞⟮IM, (unop U : Opens M); I, R⟯) /-- The presheaf of smooth functions from `M` to `R`, for `R` a smooth ring, as a presheaf of rings. -/ def smoothPresheafRing : TopCat.Presheaf RingCat.{u} (TopCat.of M) := { obj := fun U ↦ RingCat.of ((smoothSheaf IM I M R).presheaf.obj U) map := fun h ↦ RingCat.ofHom <| - SmoothMap.restrictRingHom IM I R <| CategoryTheory.leOfHom h.unop + ContMDiffMap.restrictRingHom IM I R <| CategoryTheory.leOfHom h.unop map_id := fun _ ↦ rfl map_comp := fun _ _ ↦ rfl } @@ -252,21 +249,21 @@ def smoothSheafRing : TopCat.Sheaf RingCat.{u} (TopCat.of M) := rw [CategoryTheory.Presheaf.isSheaf_iff_isSheaf_forget _ _ (CategoryTheory.forget RingCat)] exact CategoryTheory.Sheaf.cond (smoothSheaf IM I M R) } -end SmoothRing +end ContMDiffRing section SmoothCommRing -variable [CommRing R] [SmoothRing I R] +variable [CommRing R] [ContMDiffRing I ∞ R] open Manifold in instance (U : (Opens (TopCat.of M))ᵒᵖ) : CommRing ((smoothSheaf IM I M R).presheaf.obj U) := - (SmoothMap.commRing : CommRing C^∞⟮IM, (unop U : Opens M); I, R⟯) + (ContMDiffMap.commRing : CommRing C^∞⟮IM, (unop U : Opens M); I, R⟯) /-- The presheaf of smooth functions from `M` to `R`, for `R` a smooth commutative ring, as a presheaf of commutative rings. -/ def smoothPresheafCommRing : TopCat.Presheaf CommRingCat.{u} (TopCat.of M) := { obj := fun U ↦ CommRingCat.of ((smoothSheaf IM I M R).presheaf.obj U) map := fun h ↦ CommRingCat.ofHom <| - SmoothMap.restrictRingHom IM I R <| CategoryTheory.leOfHom h.unop + ContMDiffMap.restrictRingHom IM I R <| CategoryTheory.leOfHom h.unop map_id := fun _ ↦ rfl map_comp := fun _ _ ↦ rfl } @@ -286,7 +283,7 @@ example : (CategoryTheory.sheafCompose _ (CategoryTheory.forget CommRingCat.{u}) instance smoothSheafCommRing.coeFun (U : (Opens (TopCat.of M))ᵒᵖ) : CoeFun ((smoothSheafCommRing IM I M R).presheaf.obj U) (fun _ ↦ ↑(unop U) → R) := - (contDiffWithinAt_localInvariantProp ⊤).sheafHasCoeToFun _ _ _ + (contDiffWithinAt_localInvariantProp ∞).sheafHasCoeToFun _ _ _ open CategoryTheory Limits @@ -321,7 +318,7 @@ def smoothSheafCommRing.forgetStalk (x : TopCat.of M) : `x : M`, the evaluation-at-`x` map to `R` from smooth functions from `U` to `R`. -/ def smoothSheafCommRing.evalAt (x : TopCat.of M) (U : OpenNhds x) : (smoothSheafCommRing IM I M R).presheaf.obj (Opposite.op U.1) ⟶ CommRingCat.of R := - CommRingCat.ofHom (SmoothMap.evalRingHom ⟨x, U.2⟩) + CommRingCat.ofHom (ContMDiffMap.evalRingHom ⟨x, U.2⟩) /-- Canonical ring homomorphism from the stalk of `smoothSheafCommRing IM I M R` at `x` to `R`, given by evaluating sections at `x`, considered as a morphism in the category of commutative rings. diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean index 4bf23adb82cdd..29e30318e722e 100644 --- a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean +++ b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean @@ -10,17 +10,16 @@ import Mathlib.Data.Bundle import Mathlib.Geometry.Manifold.ChartedSpace /-! -# Smooth manifolds (possibly with boundary or corners) +# `C^n` manifolds (possibly with boundary or corners) -A smooth manifold is a manifold modelled on a normed vector space, or a subset like a -half-space (to get manifolds with boundaries) for which the changes of coordinates are smooth maps. +A `C^n` manifold is a manifold modelled on a normed vector space, or a subset like a +half-space (to get manifolds with boundaries) for which the changes of coordinates are `C^n` maps. We define a model with corners as a map `I : H → E` embedding nicely the topological space `H` in the vector space `E` (or more precisely as a structure containing all the relevant properties). Given such a model with corners `I` on `(E, H)`, we define the groupoid of local -homeomorphisms of `H` which are smooth when read in `E` (for any regularity `n : ℕ∞`). +homeomorphisms of `H` which are `C^n` when read in `E` (for any regularity `n : WithTop ℕ∞`). With this groupoid at hand and the general machinery of charted spaces, we thus get the notion -of `C^n` manifold with respect to any model with corners `I` on `(E, H)`. We also introduce a -specific type class for `C^∞` manifolds as these are the most commonly used. +of `C^n` manifold with respect to any model with corners `I` on `(E, H)`. Some texts assume manifolds to be Hausdorff and second countable. We (in mathlib) assume neither, but add these assumptions later as needed. (Quite a few results still do not require them.) @@ -30,39 +29,41 @@ but add these assumptions later as needed. (Quite a few results still do not req * `ModelWithCorners 𝕜 E H` : a structure containing information on the way a space `H` embeds in a model vector space E over the field `𝕜`. This is all that is needed to - define a smooth manifold with model space `H`, and model vector space `E`. + define a `C^n` manifold with model space `H`, and model vector space `E`. * `modelWithCornersSelf 𝕜 E` : trivial model with corners structure on the space `E` embedded in itself by the identity. * `contDiffGroupoid n I` : when `I` is a model with corners on `(𝕜, E, H)`, this is the groupoid of partial homeos of `H` which are of class `C^n` over the normed field `𝕜`, when read in `E`. -* `SmoothManifoldWithCorners I M` : - a type class saying that the charted space `M`, modelled on the space `H`, has `C^∞` changes of +* `IsManifold I n M` : + a type class saying that the charted space `M`, modelled on the space `H`, has `C^n` changes of coordinates with respect to the model with corners `I` on `(𝕜, E, H)`. This type class is just - a shortcut for `HasGroupoid M (contDiffGroupoid ∞ I)`. + a shortcut for `HasGroupoid M (contDiffGroupoid n I)`. * `extChartAt I x`: - in a smooth manifold with corners with the model `I` on `(E, H)`, the charts take values in `H`, + in a `C^n` manifold with corners with the model `I` on `(E, H)`, the charts take values in `H`, but often we may want to use their `E`-valued version, obtained by composing the charts with `I`. Since the target is in general not open, we can not register them as partial homeomorphisms, but we register them as `PartialEquiv`s. `extChartAt I x` is the canonical such partial equiv around `x`. As specific examples of models with corners, we define (in `Geometry.Manifold.Instances.Real`) +* `modelWithCornersEuclideanHalfSpace n : + ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanHalfSpace n)` for the model space used to + define `n`-dimensional real manifolds without boundary + (with notation `𝓡 n` in the locale `Manifold`) * `modelWithCornersEuclideanHalfSpace n : ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanHalfSpace n)` for the model space - `n`-dimensional real manifolds without boundary (with notation `𝓡 n` in the locale `Manifold`) -* `ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanHalfSpace n)` for the model space used to define `n`-dimensional real manifolds with boundary (with notation `𝓡∂ n` in the locale `Manifold`) * `modelWithCornersEuclideanQuadrant n : ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanQuadrant n)` for the model space used to define `n`-dimensional real manifolds with corners -With these definitions at hand, to invoke an `n`-dimensional real manifold without boundary, +With these definitions at hand, to invoke an `n`-dimensional `C^∞` real manifold without boundary, one could use `variable {n : ℕ} {M : Type*} [TopologicalSpace M] [ChartedSpace (EuclideanSpace ℝ (Fin n)) M] - [SmoothManifoldWithCorners (𝓡 n) M]`. + [IsManifold (𝓡 n) ∞ M]`. However, this is not the recommended way: a theorem proved using this assumption would not apply for instance to the tangent space of such a manifold, which is modelled on @@ -75,7 +76,7 @@ the right properties, like `variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] {I : ModelWithCorners ℝ E E} [I.Boundaryless] - {M : Type*} [TopologicalSpace M] [ChartedSpace E M] [SmoothManifoldWithCorners I M]` + {M : Type*} [TopologicalSpace M] [ChartedSpace E M] [IsManifold I ∞ M]` Here, `I.Boundaryless` is a typeclass property ensuring that there is no boundary (this is for instance the case for `modelWithCornersSelf`, or products of these). Note that one could consider @@ -84,6 +85,10 @@ but again in product manifolds the natural model with corners will not be this o one (and they are not defeq as `(fun p : E × F ↦ (p.1, p.2))` is not defeq to the identity). So, it is important to use the above incantation to maximize the applicability of theorems. +Even better, if the result should apply in a parallel way to smooth manifolds and to analytic +manifolds, the last typeclass should be replaced with `[IsManifold I n M]` +for `n : WithTop ℕ∞`. + We also define `TangentSpace I (x : M)` as a type synonym of `E`, and `TangentBundle I M` as a type synonym for `Π (x : M), TangentSpace I x` (in the form of an abbrev of `Bundle.TotalSpace E (TangentSpace I : M → Type _)`). Apart from basic typeclasses on @@ -109,13 +114,6 @@ half space), and an embedding of `H` into `E` (which can be the identity for `H model with corners, and we encompass all the relevant properties (in particular the fact that the image of `H` in `E` should have unique differentials) in the definition of `ModelWithCorners`. -We concentrate on `C^∞` manifolds: all the definitions work equally well for `C^n` manifolds, but -later on it is a pain to carry all over the smoothness parameter, especially when one wants to deal -with `C^k` functions as there would be additional conditions `k ≤ n` everywhere. Since one deals -almost all the time with `C^∞` (or analytic) manifolds, this seems to be a reasonable choice that -one could revisit later if needed. `C^k` manifolds are still available, but they should be called -using `HasGroupoid M (contDiffGroupoid k I)` where `I` is the model with corners. - I have considered using the model with corners `I` as a typeclass argument, possibly `outParam`, to get lighter notations later on, but it did not turn out right, as on `E × F` there are two natural model with corners, the trivial (identity) one, and the product one, and they are not defeq and one @@ -142,7 +140,7 @@ open scoped Manifold Filter Topology ContDiff /-- A structure containing information on the way a space `H` embeds in a model vector space `E` over the field `𝕜`. This is all what is needed to -define a smooth manifold with model space `H`, and model vector space `E`. +define a `C^n` manifold with model space `H`, and model vector space `E`. We require two conditions `uniqueDiffOn'` and `target_subset_closure_interior`, which are satisfied in the relevant cases (where `range I = univ` or a half space or a quadrant) and @@ -524,7 +522,7 @@ end Boundaryless section contDiffGroupoid -/-! ### Smooth functions on models with corners -/ +/-! ### `C^n` functions on models with corners -/ variable {m n : WithTop ℕ∞} {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} @@ -619,10 +617,10 @@ theorem symm_trans_mem_contDiffGroupoid (e : PartialHomeomorph M H) : variable {E' H' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] [TopologicalSpace H'] -/-- The product of two smooth partial homeomorphisms is smooth. -/ +/-- The product of two `C^n` partial homeomorphisms is `C^n`. -/ theorem contDiffGroupoid_prod {I : ModelWithCorners 𝕜 E H} {I' : ModelWithCorners 𝕜 E' H'} - {e : PartialHomeomorph H H} {e' : PartialHomeomorph H' H'} (he : e ∈ contDiffGroupoid ∞ I) - (he' : e' ∈ contDiffGroupoid ∞ I') : e.prod e' ∈ contDiffGroupoid ∞ (I.prod I') := by + {e : PartialHomeomorph H H} {e' : PartialHomeomorph H' H'} (he : e ∈ contDiffGroupoid n I) + (he' : e' ∈ contDiffGroupoid n I') : e.prod e' ∈ contDiffGroupoid n (I.prod I') := by cases' he with he he_symm cases' he' with he' he'_symm simp only at he he_symm he' he'_symm @@ -648,72 +646,127 @@ instance : ClosedUnderRestriction (contDiffGroupoid n I) := end contDiffGroupoid -section SmoothManifoldWithCorners - -/-! ### Smooth manifolds with corners -/ +section IsManifold +/-! ### `C^n` manifolds (possibly with boundary or corners) -/ -/-- Typeclass defining smooth manifolds with corners with respect to a model with corners, over a -field `𝕜` and with infinite smoothness to simplify typeclass search and statements later on. -/ -class SmoothManifoldWithCorners {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} +/-- Typeclass defining manifolds with respect to a model with corners, over a +field `𝕜`. This definition includes the model with corners `I` (which might allow boundary, corners, +or not, so this class covers both manifolds with boundary and manifolds without boundary), and +a smoothness parameter `n : WithTop ℕ∞` (where `n = 0` means topological manifold, `n = ∞` means +smooth manifold and `n = ω` means analytic manifold). -/ +class IsManifold {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] - (I : ModelWithCorners 𝕜 E H) (M : Type*) [TopologicalSpace M] [ChartedSpace H M] extends - HasGroupoid M (contDiffGroupoid ∞ I) : Prop + (I : ModelWithCorners 𝕜 E H) (n : WithTop ℕ∞) (M : Type*) + [TopologicalSpace M] [ChartedSpace H M] extends + HasGroupoid M (contDiffGroupoid n I) : Prop -theorem SmoothManifoldWithCorners.mk' {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} +@[deprecated (since := "2025-01-09")] alias SmoothManifoldWithCorners := IsManifold + +/-- Building a `C^n` manifold from a `HasGroupoid` assumption. -/ +theorem IsManifold.mk' {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] - (I : ModelWithCorners 𝕜 E H) (M : Type*) [TopologicalSpace M] [ChartedSpace H M] - [gr : HasGroupoid M (contDiffGroupoid ∞ I)] : SmoothManifoldWithCorners I M := + (I : ModelWithCorners 𝕜 E H) (n : WithTop ℕ∞) + (M : Type*) [TopologicalSpace M] [ChartedSpace H M] + [gr : HasGroupoid M (contDiffGroupoid n I)] : IsManifold I n M := { gr with } -theorem smoothManifoldWithCorners_of_contDiffOn {𝕜 : Type*} [NontriviallyNormedField 𝕜] +@[deprecated (since := "2025-01-09")] alias SmoothManifoldWithCorners.mk' := IsManifold.mk' + +theorem isManifold_of_contDiffOn {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] - (I : ModelWithCorners 𝕜 E H) (M : Type*) [TopologicalSpace M] [ChartedSpace H M] + (I : ModelWithCorners 𝕜 E H) (n : WithTop ℕ∞) (M : Type*) + [TopologicalSpace M] [ChartedSpace H M] (h : ∀ e e' : PartialHomeomorph M H, e ∈ atlas H M → e' ∈ atlas H M → - ContDiffOn 𝕜 ∞ (I ∘ e.symm ≫ₕ e' ∘ I.symm) (I.symm ⁻¹' (e.symm ≫ₕ e').source ∩ range I)) : - SmoothManifoldWithCorners I M where + ContDiffOn 𝕜 n (I ∘ e.symm ≫ₕ e' ∘ I.symm) (I.symm ⁻¹' (e.symm ≫ₕ e').source ∩ range I)) : + IsManifold I n M where compatible := by - haveI : HasGroupoid M (contDiffGroupoid ∞ I) := hasGroupoid_of_pregroupoid _ (h _ _) + haveI : HasGroupoid M (contDiffGroupoid n I) := hasGroupoid_of_pregroupoid _ (h _ _) apply StructureGroupoid.compatible -/-- For any model with corners, the model space is a smooth manifold -/ -instance model_space_smooth {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} +@[deprecated (since := "2025-01-09")] +alias smoothManifoldWithCorners_of_contDiffOn := isManifold_of_contDiffOn + +/-- For any model with corners, the model space is a `C^n` manifold -/ +instance intIsManifoldModelSpace {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] - {I : ModelWithCorners 𝕜 E H} : SmoothManifoldWithCorners I H := + {I : ModelWithCorners 𝕜 E H} {n : WithTop ℕ∞} : IsManifold I n H := { hasGroupoid_model_space _ _ with } -end SmoothManifoldWithCorners +end IsManifold -namespace SmoothManifoldWithCorners +namespace IsManifold -/- We restate in the namespace `SmoothManifoldWithCorners` some lemmas that hold for general +/- We restate in the namespace `IsManifold` some lemmas that hold for general charted space with a structure groupoid, avoiding the need to specify the groupoid -`contDiffGroupoid ∞ I` explicitly. -/ +`contDiffGroupoid n I` explicitly. -/ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) (M : Type*) - [TopologicalSpace M] [ChartedSpace H M] + [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} + {n : WithTop ℕ∞} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + +protected theorem of_le {m n : WithTop ℕ∞} (hmn : m ≤ n) + [IsManifold I n M] : IsManifold I m M := by + have : HasGroupoid M (contDiffGroupoid m I) := + hasGroupoid_of_le (G₁ := contDiffGroupoid n I) (by infer_instance) + (contDiffGroupoid_le hmn) + exact mk' I m M + +/-- A typeclass registering that a smoothness exponent is smaller than `∞`. Used to deduce that +some manifolds are `C^n` when they are `C^∞`. -/ +class _root_.ENat.LEInfty (m : WithTop ℕ∞) where + out : m ≤ ∞ + +open ENat + +instance (n : ℕ) : LEInfty (n : WithTop ℕ∞) := ⟨mod_cast le_top⟩ +instance (n : ℕ) [n.AtLeastTwo] : LEInfty (no_index (OfNat.ofNat n) : WithTop ℕ∞) := + inferInstanceAs (LEInfty (n : WithTop ℕ∞)) +instance : LEInfty (1 : WithTop ℕ∞) := inferInstanceAs (LEInfty ((1 : ℕ) : WithTop ℕ∞)) +instance : LEInfty (0 : WithTop ℕ∞) := inferInstanceAs (LEInfty ((0 : ℕ) : WithTop ℕ∞)) + +instance {a : WithTop ℕ∞} [IsManifold I ∞ M] [h : LEInfty a] : + IsManifold I a M := + IsManifold.of_le h.out + +instance {a : WithTop ℕ∞} [IsManifold I ω M] : + IsManifold I a M := + IsManifold.of_le le_top + +instance : IsManifold I 0 M := by + suffices HasGroupoid M (contDiffGroupoid 0 I) from mk' I 0 M + constructor + intro e e' he he' + rw [contDiffGroupoid_zero_eq] + trivial + +instance [IsManifold I 2 M] : + IsManifold I 1 M := + IsManifold.of_le one_le_two -/-- The maximal atlas of `M` for the smooth manifold with corners structure corresponding to the +variable (I n M) in +/-- The maximal atlas of `M` for the `C^n` manifold with corners structure corresponding to the model with corners `I`. -/ def maximalAtlas := - (contDiffGroupoid ∞ I).maximalAtlas M - -variable {I M} + (contDiffGroupoid n I).maximalAtlas M -theorem subset_maximalAtlas [SmoothManifoldWithCorners I M] : atlas H M ⊆ maximalAtlas I M := +theorem subset_maximalAtlas [IsManifold I n M] : atlas H M ⊆ maximalAtlas I n M := StructureGroupoid.subset_maximalAtlas _ -theorem chart_mem_maximalAtlas [SmoothManifoldWithCorners I M] (x : M) : - chartAt H x ∈ maximalAtlas I M := +theorem chart_mem_maximalAtlas [IsManifold I n M] (x : M) : + chartAt H x ∈ maximalAtlas I n M := StructureGroupoid.chart_mem_maximalAtlas _ x -theorem compatible_of_mem_maximalAtlas {e e' : PartialHomeomorph M H} (he : e ∈ maximalAtlas I M) - (he' : e' ∈ maximalAtlas I M) : e.symm.trans e' ∈ contDiffGroupoid ∞ I := +theorem compatible_of_mem_maximalAtlas {e e' : PartialHomeomorph M H} (he : e ∈ maximalAtlas I n M) + (he' : e' ∈ maximalAtlas I n M) : e.symm.trans e' ∈ contDiffGroupoid n I := StructureGroupoid.compatible_of_mem_maximalAtlas he he' -/-- The empty set is a smooth manifold w.r.t. any charted space and model. -/ -instance empty [IsEmpty M] : SmoothManifoldWithCorners I M := by - apply smoothManifoldWithCorners_of_contDiffOn +lemma maximalAtlas_subset_of_le {m n : WithTop ℕ∞} (h : m ≤ n) : + maximalAtlas I n M ⊆ maximalAtlas I m M := + StructureGroupoid.maximalAtlas_mono (contDiffGroupoid_le h) + +/-- The empty set is a `C^n` manifold w.r.t. any charted space and model. -/ +instance empty [IsEmpty M] : IsManifold I n M := by + apply isManifold_of_contDiffOn intro e e' _ _ x hx set t := I.symm ⁻¹' (e.symm ≫ₕ e').source ∩ range I -- Since `M` is empty, the condition about compatibility of transition maps is vacuous. @@ -729,51 +782,61 @@ instance empty [IsEmpty M] : SmoothManifoldWithCorners I M := by _ = ∅ := empty_inter (range I) apply (this ▸ hx).elim -/-- The product of two smooth manifolds with corners is naturally a smooth manifold with corners. -/ +/-- The product of two `C^n` manifolds is naturally a `C^n` manifold. -/ instance prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} (M : Type*) [TopologicalSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] (M' : Type*) [TopologicalSpace M'] [ChartedSpace H' M'] - [SmoothManifoldWithCorners I' M'] : SmoothManifoldWithCorners (I.prod I') (M × M') where + [IsManifold I n M] (M' : Type*) [TopologicalSpace M'] [ChartedSpace H' M'] + [IsManifold I' n M'] : + IsManifold (I.prod I') n (M × M') where compatible := by rintro f g ⟨f1, hf1, f2, hf2, rfl⟩ ⟨g1, hg1, g2, hg2, rfl⟩ rw [PartialHomeomorph.prod_symm, PartialHomeomorph.prod_trans] - have h1 := (contDiffGroupoid ∞ I).compatible hf1 hg1 - have h2 := (contDiffGroupoid ∞ I').compatible hf2 hg2 + have h1 := (contDiffGroupoid n I).compatible hf1 hg1 + have h2 := (contDiffGroupoid n I').compatible hf2 hg2 exact contDiffGroupoid_prod h1 h2 -end SmoothManifoldWithCorners +end IsManifold -theorem PartialHomeomorph.singleton_smoothManifoldWithCorners +theorem PartialHomeomorph.isManifold_singleton {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] - {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} + {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {n : WithTop ℕ∞} {M : Type*} [TopologicalSpace M] (e : PartialHomeomorph M H) (h : e.source = Set.univ) : - @SmoothManifoldWithCorners 𝕜 _ E _ _ H _ I M _ (e.singletonChartedSpace h) := - @SmoothManifoldWithCorners.mk' _ _ _ _ _ _ _ _ _ _ (id _) <| - e.singleton_hasGroupoid h (contDiffGroupoid ∞ I) + @IsManifold 𝕜 _ E _ _ H _ I n M _ (e.singletonChartedSpace h) := + @IsManifold.mk' _ _ _ _ _ _ _ _ _ _ _ (id _) <| + e.singleton_hasGroupoid h (contDiffGroupoid n I) + +@[deprecated (since := "2025-01-09")] +alias PartialHomeomorph.singleton_smoothManifoldWithCorners := + PartialHomeomorph.isManifold_singleton -theorem Topology.IsOpenEmbedding.singleton_smoothManifoldWithCorners {𝕜 E H : Type*} +theorem Topology.IsOpenEmbedding.isManifold_singleton {𝕜 E H : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] [TopologicalSpace H] - {I : ModelWithCorners 𝕜 E H} {M : Type*} [TopologicalSpace M] [Nonempty M] {f : M → H} - (h : IsOpenEmbedding f) : - @SmoothManifoldWithCorners 𝕜 _ E _ _ H _ I M _ h.singletonChartedSpace := - (h.toPartialHomeomorph f).singleton_smoothManifoldWithCorners (by simp) + {I : ModelWithCorners 𝕜 E H} {n : WithTop ℕ∞} + {M : Type*} [TopologicalSpace M] [Nonempty M] {f : M → H} (h : IsOpenEmbedding f) : + @IsManifold 𝕜 _ E _ _ H _ I n M _ h.singletonChartedSpace := + (h.toPartialHomeomorph f).isManifold_singleton (by simp) + +@[deprecated (since := "2025-01-09")] +alias Topology.IsOpenEmbedding.singleton_smoothManifoldWithCorners := + Topology.IsOpenEmbedding.isManifold_singleton @[deprecated (since := "2024-10-18")] alias OpenEmbedding.singleton_smoothManifoldWithCorners := - IsOpenEmbedding.singleton_smoothManifoldWithCorners + Topology.IsOpenEmbedding.isManifold_singleton namespace TopologicalSpace.Opens open TopologicalSpace variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} - [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] (s : Opens M) + [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {n : WithTop ℕ∞} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I n M] + (s : Opens M) -instance : SmoothManifoldWithCorners I s := - { s.instHasGroupoid (contDiffGroupoid ∞ I) with } +instance : IsManifold I n s := + { s.instHasGroupoid (contDiffGroupoid n I) with } end TopologicalSpace.Opens @@ -782,14 +845,15 @@ section ExtendedCharts open scoped Topology variable {𝕜 E M H E' M' H' : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] - [NormedSpace 𝕜 E] [TopologicalSpace H] [TopologicalSpace M] (f f' : PartialHomeomorph M H) + [NormedSpace 𝕜 E] [TopologicalSpace H] [TopologicalSpace M] {n : WithTop ℕ∞} + (f f' : PartialHomeomorph M H) {I : ModelWithCorners 𝕜 E H} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] [TopologicalSpace H'] [TopologicalSpace M'] {I' : ModelWithCorners 𝕜 E' H'} {s t : Set M} /-! ### Extended charts -In a smooth manifold with corners, the model space is the space `H`. However, we will also +In a `C^n` manifold with corners, the model space is the space `H`. However, we will also need to use extended charts taking values in the model vector space `E`. These extended charts are not `PartialHomeomorph` as the target is not open in `E` in general, but we can still register them as `PartialEquiv`. @@ -1071,25 +1135,25 @@ theorem extend_coord_change_source_mem_nhdsWithin' {x : M} (hxf : x ∈ f.source variable {f f'} -open SmoothManifoldWithCorners +open IsManifold -theorem contDiffOn_extend_coord_change [ChartedSpace H M] (hf : f ∈ maximalAtlas I M) - (hf' : f' ∈ maximalAtlas I M) : - ContDiffOn 𝕜 ∞ (f.extend I ∘ (f'.extend I).symm) ((f'.extend I).symm ≫ f.extend I).source := by +theorem contDiffOn_extend_coord_change [ChartedSpace H M] (hf : f ∈ maximalAtlas I n M) + (hf' : f' ∈ maximalAtlas I n M) : + ContDiffOn 𝕜 n (f.extend I ∘ (f'.extend I).symm) ((f'.extend I).symm ≫ f.extend I).source := by rw [extend_coord_change_source, I.image_eq] exact (StructureGroupoid.compatible_of_mem_maximalAtlas hf' hf).1 -theorem contDiffWithinAt_extend_coord_change [ChartedSpace H M] (hf : f ∈ maximalAtlas I M) - (hf' : f' ∈ maximalAtlas I M) {x : E} (hx : x ∈ ((f'.extend I).symm ≫ f.extend I).source) : - ContDiffWithinAt 𝕜 ∞ (f.extend I ∘ (f'.extend I).symm) (range I) x := by +theorem contDiffWithinAt_extend_coord_change [ChartedSpace H M] (hf : f ∈ maximalAtlas I n M) + (hf' : f' ∈ maximalAtlas I n M) {x : E} (hx : x ∈ ((f'.extend I).symm ≫ f.extend I).source) : + ContDiffWithinAt 𝕜 n (f.extend I ∘ (f'.extend I).symm) (range I) x := by apply (contDiffOn_extend_coord_change hf hf' x hx).mono_of_mem_nhdsWithin rw [extend_coord_change_source] at hx ⊢ obtain ⟨z, hz, rfl⟩ := hx exact I.image_mem_nhdsWithin ((PartialHomeomorph.open_source _).mem_nhds hz) -theorem contDiffWithinAt_extend_coord_change' [ChartedSpace H M] (hf : f ∈ maximalAtlas I M) - (hf' : f' ∈ maximalAtlas I M) {x : M} (hxf : x ∈ f.source) (hxf' : x ∈ f'.source) : - ContDiffWithinAt 𝕜 ∞ (f.extend I ∘ (f'.extend I).symm) (range I) (f'.extend I x) := by +theorem contDiffWithinAt_extend_coord_change' [ChartedSpace H M] (hf : f ∈ maximalAtlas I n M) + (hf' : f' ∈ maximalAtlas I n M) {x : M} (hxf : x ∈ f.source) (hxf' : x ∈ f'.source) : + ContDiffWithinAt 𝕜 n (f.extend I ∘ (f'.extend I).symm) (range I) (f'.extend I x) := by refine contDiffWithinAt_extend_coord_change hf hf' ?_ rw [← extend_image_source_inter] exact mem_image_of_mem _ ⟨hxf', hxf⟩ @@ -1432,16 +1496,16 @@ theorem ext_coord_change_source (x x' : M) : I '' ((chartAt H x').symm ≫ₕ chartAt H x).source := extend_coord_change_source _ _ -open SmoothManifoldWithCorners +open IsManifold -theorem contDiffOn_ext_coord_change [SmoothManifoldWithCorners I M] (x x' : M) : - ContDiffOn 𝕜 ∞ (extChartAt I x ∘ (extChartAt I x').symm) +theorem contDiffOn_ext_coord_change [IsManifold I n M] (x x' : M) : + ContDiffOn 𝕜 n (extChartAt I x ∘ (extChartAt I x').symm) ((extChartAt I x').symm ≫ extChartAt I x).source := contDiffOn_extend_coord_change (chart_mem_maximalAtlas x) (chart_mem_maximalAtlas x') -theorem contDiffWithinAt_ext_coord_change [SmoothManifoldWithCorners I M] (x x' : M) {y : E} +theorem contDiffWithinAt_ext_coord_change [IsManifold I n M] (x x' : M) {y : E} (hy : y ∈ ((extChartAt I x').symm ≫ extChartAt I x).source) : - ContDiffWithinAt 𝕜 ∞ (extChartAt I x ∘ (extChartAt I x').symm) (range I) y := + ContDiffWithinAt 𝕜 n (extChartAt I x ∘ (extChartAt I x').symm) (range I) y := contDiffWithinAt_extend_coord_change (chart_mem_maximalAtlas x) (chart_mem_maximalAtlas x') hy variable (I I') in @@ -1565,7 +1629,7 @@ section TangentSpace /- We define the tangent space to `M` modelled on `I : ModelWithCorners 𝕜 E H` as a type synonym for `E`. This is enough to define linear maps between tangent spaces, for instance derivatives, but the interesting part is to define a manifold structure on the whole tangent bundle, which -requires that `M` is a smooth manifold with corners. The definition is put here to avoid importing +requires that `M` is a `C^n` manifold. The definition is put here to avoid importing all the smooth bundle structure when defining manifold derivatives. -/ set_option linter.unusedVariables false in @@ -1596,11 +1660,10 @@ instance : Inhabited (TangentSpace I x) := ⟨0⟩ variable (M) in -- is empty if the base manifold is empty -/-- The tangent bundle to a smooth manifold, as a Sigma type. Defined in terms of +/-- The tangent bundle to a manifold, as a Sigma type. Defined in terms of `Bundle.TotalSpace` to be able to put a suitable topology on it. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was nolint has_nonempty_instance -abbrev TangentBundle := - Bundle.TotalSpace E (TangentSpace I : M → Type _) +abbrev TangentBundle := Bundle.TotalSpace E (TangentSpace I : M → Type _) end TangentSpace diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean index 3fd4222c1daba..4b44eae1ac780 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean @@ -7,24 +7,24 @@ import Mathlib.Geometry.Manifold.ContMDiff.Atlas import Mathlib.Geometry.Manifold.VectorBundle.FiberwiseLinear import Mathlib.Topology.VectorBundle.Constructions -/-! # Smooth vector bundles +/-! # `C^n` vector bundles -This file defines smooth vector bundles over a smooth manifold. +This file defines `C^n` vector bundles over a manifold. Let `E` be a topological vector bundle, with model fiber `F` and base space `B`. We consider `E` as carrying a charted space structure given by its trivializations -- these are charts to `B × F`. Then, by "composition", if `B` is itself a charted space over `H` (e.g. a smooth manifold), then `E` is also a charted space over `H × F`. -Now, we define `SmoothVectorBundle` as the `Prop` of having smooth transition functions. -Recall the structure groupoid `smoothFiberwiseLinear` on `B × F` consisting of smooth, fiberwise -linear partial homeomorphisms. We show that our definition of "smooth vector bundle" implies +Now, we define `ContMDiffVectorBundle` as the `Prop` of having `C^n` transition functions. +Recall the structure groupoid `contMDiffFiberwiseLinear` on `B × F` consisting of `C^n`, fiberwise +linear partial homeomorphisms. We show that our definition of "`C^n` vector bundle" implies `HasGroupoid` for this groupoid, and show (by a "composition" of `HasGroupoid` instances) that -this means that a smooth vector bundle is a smooth manifold. +this means that a `C^n` vector bundle is a `C^n` manifold. -Since `SmoothVectorBundle` is a mixin, it should be easy to make variants and for many such -variants to coexist -- vector bundles can be smooth vector bundles over several different base -fields, they can also be C^k vector bundles, etc. +Since `ContMDiffVectorBundle` is a mixin, it should be easy to make variants and for many such +variants to coexist -- vector bundles can be `C^n` vector bundles over several different base +fields, etc. ## Main definitions and constructions @@ -34,27 +34,27 @@ fields, they can also be C^k vector bundles, etc. * `FiberBundle.chartedSpace'`: Let `B` be a charted space modelled on `HB`. Then a fiber bundle `E` over a base `B` with model fiber `F` is naturally a charted space modelled on `HB.prod F`. -* `SmoothVectorBundle`: Mixin class stating that a (topological) `VectorBundle` is smooth, in the - sense of having smooth transition functions. +* `ContMDiffVectorBundle`: Mixin class stating that a (topological) `VectorBundle` is `C^n`, in the + sense of having `C^n` transition functions, where the smoothness index `n` + belongs to `WithTop ℕ∞`. -* `SmoothFiberwiseLinear.hasGroupoid`: For a smooth vector bundle `E` over `B` with fiber +* `ContMDiffFiberwiseLinear.hasGroupoid`: For a `C^n` vector bundle `E` over `B` with fiber modelled on `F`, the change-of-co-ordinates between two trivializations `e`, `e'` for `E`, - considered as charts to `B × F`, is smooth and fiberwise linear, in the sense of belonging to the - structure groupoid `smoothFiberwiseLinear`. + considered as charts to `B × F`, is `C^n` and fiberwise linear, in the sense of belonging to the + structure groupoid `contMDiffFiberwiseLinear`. -* `Bundle.TotalSpace.smoothManifoldWithCorners`: A smooth vector bundle is naturally a smooth - manifold. +* `Bundle.TotalSpace.isManifold`: A `C^n` vector bundle is naturally a `C^n` manifold. -* `VectorBundleCore.smoothVectorBundle`: If a (topological) `VectorBundleCore` is smooth, - in the sense of having smooth transition functions (cf. `VectorBundleCore.IsSmooth`), - then the vector bundle constructed from it is a smooth vector bundle. +* `VectorBundleCore.instContMDiffVectorBundle`: If a (topological) `VectorBundleCore` is `C^n`, + in the sense of having `C^n` transition functions (cf. `VectorBundleCore.IsContMDiff`), + then the vector bundle constructed from it is a `C^n` vector bundle. -* `VectorPrebundle.smoothVectorBundle`: If a `VectorPrebundle` is smooth, - in the sense of having smooth transition functions (cf. `VectorPrebundle.IsSmooth`), - then the vector bundle constructed from it is a smooth vector bundle. +* `VectorPrebundle.contMDiffVectorBundle`: If a `VectorPrebundle` is `C^n`, + in the sense of having `C^n` transition functions (cf. `VectorPrebundle.IsContMDiff`), + then the vector bundle constructed from it is a `C^n` vector bundle. -* `Bundle.Prod.smoothVectorBundle`: The direct sum of two smooth vector bundles is a smooth vector - bundle. +* `Bundle.Prod.contMDiffVectorBundle`: The direct sum of two `C^n` vector bundles is a `C^n` + vector bundle. -/ assert_not_exists mfderiv @@ -65,9 +65,9 @@ open Function (id_def) open Filter -open scoped Manifold Bundle Topology +open scoped Manifold Bundle Topology ContDiff -variable {𝕜 B B' F M : Type*} {E : B → Type*} +variable {n : WithTop ℕ∞} {𝕜 B B' F M : Type*} {E : B → Type*} /-! ### Charted space structure on a fiber bundle -/ @@ -125,7 +125,6 @@ variable [NontriviallyNormedField 𝕜] [NormedAddCommGroup F] [NormedSpace 𝕜 {IB : ModelWithCorners 𝕜 EB HB} (E' : B → Type*) [∀ x, Zero (E' x)] {EM : Type*} [NormedAddCommGroup EM] [NormedSpace 𝕜 EM] {HM : Type*} [TopologicalSpace HM] {IM : ModelWithCorners 𝕜 EM HM} [TopologicalSpace M] [ChartedSpace HM M] - {n : ℕ∞} variable [TopologicalSpace B] [ChartedSpace HB B] [FiberBundle F E] @@ -157,15 +156,15 @@ theorem FiberBundle.writtenInExtChartAt_trivializationAt_symm {x : TotalSpace F (trivializationAt F E x.proj).toPartialHomeomorph.symm y = y := writtenInExtChartAt_chartAt_symm_comp _ hy -/-! ### Smoothness of maps in/out fiber bundles +/-! ### Regularity of maps in/out fiber bundles -Note: For these results we don't need that the bundle is a smooth vector bundle, or even a vector +Note: For these results we don't need that the bundle is a `C^n` vector bundle, or even a vector bundle at all, just that it is a fiber bundle over a charted base space. -/ namespace Bundle -/-- Characterization of C^n functions into a smooth vector bundle. -/ +/-- Characterization of `C^n` functions into a vector bundle. -/ theorem contMDiffWithinAt_totalSpace (f : M → TotalSpace F E) {s : Set M} {x₀ : M} : ContMDiffWithinAt IM (IB.prod 𝓘(𝕜, F)) n f s x₀ ↔ ContMDiffWithinAt IM IB n (fun x => (f x).proj) s x₀ ∧ @@ -186,20 +185,20 @@ theorem contMDiffWithinAt_totalSpace (f : M → TotalSpace F E) {s : Set M} {x exact hx · simp only [mfld_simps] -/-- Characterization of C^n functions into a smooth vector bundle. -/ +/-- Characterization of `C^n` functions into a vector bundle. -/ theorem contMDiffAt_totalSpace (f : M → TotalSpace F E) (x₀ : M) : ContMDiffAt IM (IB.prod 𝓘(𝕜, F)) n f x₀ ↔ ContMDiffAt IM IB n (fun x => (f x).proj) x₀ ∧ ContMDiffAt IM 𝓘(𝕜, F) n (fun x => (trivializationAt F E (f x₀).proj (f x)).2) x₀ := by simp_rw [← contMDiffWithinAt_univ]; exact contMDiffWithinAt_totalSpace f -/-- Characterization of C^n sections within a set at a point of a smooth vector bundle. -/ +/-- Characterization of `C^n` sections within a set at a point of a vector bundle. -/ theorem contMDiffWithinAt_section (s : ∀ x, E x) (a : Set B) (x₀ : B) : ContMDiffWithinAt IB (IB.prod 𝓘(𝕜, F)) n (fun x => TotalSpace.mk' F x (s x)) a x₀ ↔ ContMDiffWithinAt IB 𝓘(𝕜, F) n (fun x ↦ (trivializationAt F E x₀ ⟨x, s x⟩).2) a x₀ := by simp_rw [contMDiffWithinAt_totalSpace, and_iff_right_iff_imp]; intro; exact contMDiffWithinAt_id -/-- Characterization of C^n sections of a smooth vector bundle. -/ +/-- Characterization of `C^n` sections of a vector bundle. -/ theorem contMDiffAt_section (s : ∀ x, E x) (x₀ : B) : ContMDiffAt IB (IB.prod 𝓘(𝕜, F)) n (fun x => TotalSpace.mk' F x (s x)) x₀ ↔ ContMDiffAt IB 𝓘(𝕜, F) n (fun x ↦ (trivializationAt F E x₀ ⟨x, s x⟩).2) x₀ := by @@ -234,7 +233,7 @@ theorem contMDiffWithinAt_proj {s : Set (TotalSpace F E)} {p : TotalSpace F E} : variable (𝕜) [∀ x, AddCommMonoid (E x)] variable [∀ x, Module 𝕜 (E x)] [VectorBundle 𝕜 F E] -theorem contMDiff_zeroSection : ContMDiff IB (IB.prod 𝓘(𝕜, F)) ⊤ (zeroSection F E) := fun x ↦ by +theorem contMDiff_zeroSection : ContMDiff IB (IB.prod 𝓘(𝕜, F)) n (zeroSection F E) := fun x ↦ by unfold zeroSection rw [Bundle.contMDiffAt_section] apply (contMDiffAt_const (c := 0)).congr_of_eventuallyEq @@ -248,14 +247,14 @@ end Bundle end -/-! ### Smooth vector bundles -/ +/-! ### `C^n` vector bundles -/ variable [NontriviallyNormedField 𝕜] {EB : Type*} [NormedAddCommGroup EB] [NormedSpace 𝕜 EB] {HB : Type*} [TopologicalSpace HB] {IB : ModelWithCorners 𝕜 EB HB} [TopologicalSpace B] [ChartedSpace HB B] {EM : Type*} [NormedAddCommGroup EM] [NormedSpace 𝕜 EM] {HM : Type*} [TopologicalSpace HM] {IM : ModelWithCorners 𝕜 EM HM} - [TopologicalSpace M] [ChartedSpace HM M] {n : ℕ∞} + [TopologicalSpace M] [ChartedSpace HM M] [∀ x, AddCommMonoid (E x)] [∀ x, Module 𝕜 (E x)] [NormedAddCommGroup F] [NormedSpace 𝕜 F] section WithTopology @@ -263,20 +262,43 @@ section WithTopology variable [TopologicalSpace (TotalSpace F E)] [∀ x, TopologicalSpace (E x)] (F E) variable [FiberBundle F E] [VectorBundle 𝕜 F E] -variable (IB) in -/-- When `B` is a smooth manifold with corners with respect to a model `IB` and `E` is a -topological vector bundle over `B` with fibers isomorphic to `F`, then `SmoothVectorBundle F E IB` -registers that the bundle is smooth, in the sense of having smooth transition functions. -This is a mixin, not carrying any new data. -/ -class SmoothVectorBundle : Prop where +variable (n IB) in +/-- When `B` is a manifold with respect to a model `IB` and `E` is a +topological vector bundle over `B` with fibers isomorphic to `F`, +then `ContMDiffVectorBundle F E IB` registers that the bundle is `C^n`, in the sense of having +`C^n` transition functions. This is a mixin, not carrying any new data. -/ +class ContMDiffVectorBundle : Prop where protected contMDiffOn_coordChangeL : ∀ (e e' : Trivialization F (π F E)) [MemTrivializationAtlas e] [MemTrivializationAtlas e'], - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) (e.baseSet ∩ e'.baseSet) -variable [SmoothVectorBundle F E IB] +@[deprecated (since := "2025-01-09")] alias SmoothVectorBundle := ContMDiffVectorBundle + +variable {F E} in +protected theorem ContMDiffVectorBundle.of_le {m n : WithTop ℕ∞} (hmn : m ≤ n) + [h : ContMDiffVectorBundle n F E IB] : ContMDiffVectorBundle m F E IB := + ⟨fun e e' _ _ ↦ (h.contMDiffOn_coordChangeL e e').of_le hmn⟩ + +instance {a : WithTop ℕ∞} [ContMDiffVectorBundle ∞ F E IB] [h : ENat.LEInfty a] : + ContMDiffVectorBundle a F E IB := + ContMDiffVectorBundle.of_le h.out + +instance {a : WithTop ℕ∞} [ContMDiffVectorBundle ω F E IB] : ContMDiffVectorBundle a F E IB := + ContMDiffVectorBundle.of_le le_top -section SmoothCoordChange +instance [ContMDiffVectorBundle 2 F E IB] : ContMDiffVectorBundle 1 F E IB := + ContMDiffVectorBundle.of_le one_le_two + +instance : ContMDiffVectorBundle 0 F E IB := by + constructor + intro e e' he he' + rw [contMDiffOn_zero_iff] + exact VectorBundle.continuousOn_coordChange' e e' + +variable [ContMDiffVectorBundle n F E IB] + +section ContMDiffCoordChange variable {F E} variable (e e' : Trivialization F (π F E)) [MemTrivializationAtlas e] [MemTrivializationAtlas e'] @@ -284,14 +306,13 @@ variable (e e' : Trivialization F (π F E)) [MemTrivializationAtlas e] [MemTrivi theorem contMDiffOn_coordChangeL : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) (e.baseSet ∩ e'.baseSet) := - (SmoothVectorBundle.contMDiffOn_coordChangeL e e').of_le le_top + ContMDiffVectorBundle.contMDiffOn_coordChangeL e e' theorem contMDiffOn_symm_coordChangeL : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => ((e.coordChangeL 𝕜 e' b).symm : F →L[𝕜] F)) (e.baseSet ∩ e'.baseSet) := by - apply ContMDiffOn.of_le _ le_top rw [inter_comm] - refine (SmoothVectorBundle.contMDiffOn_coordChangeL e' e).congr fun b hb ↦ ?_ + refine (ContMDiffVectorBundle.contMDiffOn_coordChangeL e' e).congr fun b hb ↦ ?_ rw [e.symm_coordChangeL e' hb] @[deprecated (since := "2024-11-21")] alias smoothOn_coordChangeL := contMDiffOn_coordChangeL @@ -419,19 +440,19 @@ theorem Trivialization.contMDiffWithinAt_snd_comp_iff₂ {f : M → TotalSpace F ContMDiffWithinAt IM 𝓘(𝕜, F) n (fun y ↦ (e' (f y)).2) s x := ⟨(hp.change_section_trivialization · he he'), (hp.change_section_trivialization · he' he)⟩ -end SmoothCoordChange +end ContMDiffCoordChange -variable [SmoothManifoldWithCorners IB B] in -/-- For a smooth vector bundle `E` over `B` with fiber modelled on `F`, the change-of-co-ordinates -between two trivializations `e`, `e'` for `E`, considered as charts to `B × F`, is smooth and +variable [IsManifold IB n B] in +/-- For a `C^n` vector bundle `E` over `B` with fiber modelled on `F`, the change-of-co-ordinates +between two trivializations `e`, `e'` for `E`, considered as charts to `B × F`, is `C^n` and fiberwise linear. -/ -instance SmoothFiberwiseLinear.hasGroupoid : - HasGroupoid (TotalSpace F E) (smoothFiberwiseLinear B F IB) where +instance ContMDiffFiberwiseLinear.hasGroupoid : + HasGroupoid (TotalSpace F E) (contMDiffFiberwiseLinear B F IB n) where compatible := by rintro _ _ ⟨e, he, rfl⟩ ⟨e', he', rfl⟩ haveI : MemTrivializationAtlas e := ⟨he⟩ haveI : MemTrivializationAtlas e' := ⟨he'⟩ - rw [mem_smoothFiberwiseLinear_iff] + rw [mem_contMDiffFiberwiseLinear_iff] refine ⟨_, _, e.open_baseSet.inter e'.open_baseSet, contMDiffOn_coordChangeL e e', contMDiffOn_symm_coordChangeL e e', ?_⟩ refine PartialHomeomorph.eqOnSourceSetoid.symm ⟨?_, ?_⟩ @@ -440,13 +461,13 @@ instance SmoothFiberwiseLinear.hasGroupoid : · rintro ⟨b, v⟩ hb exact (e.apply_symm_apply_eq_coordChangeL e' hb.1 v).symm -variable [SmoothManifoldWithCorners IB B] in -/-- A smooth vector bundle `E` is naturally a smooth manifold. -/ -instance Bundle.TotalSpace.smoothManifoldWithCorners [SmoothManifoldWithCorners IB B] : - SmoothManifoldWithCorners (IB.prod 𝓘(𝕜, F)) (TotalSpace F E) := by - refine { StructureGroupoid.HasGroupoid.comp (smoothFiberwiseLinear B F IB) ?_ with } +variable [IsManifold IB n B] in +/-- A `C^n` vector bundle `E` is naturally a `C^n` manifold. -/ +instance Bundle.TotalSpace.isManifold : + IsManifold (IB.prod 𝓘(𝕜, F)) n (TotalSpace F E) := by + refine { StructureGroupoid.HasGroupoid.comp (contMDiffFiberwiseLinear B F IB n) ?_ with } intro e he - rw [mem_smoothFiberwiseLinear_iff] at he + rw [mem_contMDiffFiberwiseLinear_iff] at he obtain ⟨φ, U, hU, hφ, h2φ, heφ⟩ := he rw [isLocalStructomorphOn_contDiffGroupoid_iff] refine ⟨ContMDiffOn.congr ?_ (EqOnSource.eqOn heφ), @@ -504,13 +525,13 @@ alias Trivialization.smoothOn_iff := Trivialization.contMDiffOn_iff alias Trivialization.smooth_iff := Trivialization.contMDiff_iff theorem Trivialization.contMDiffOn (e : Trivialization F (π F E)) [MemTrivializationAtlas e] : - ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) ⊤ e e.source := by - have : ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) ⊤ id e.source := contMDiffOn_id + ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) n e e.source := by + have : ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) n id e.source := contMDiffOn_id rw [e.contMDiffOn_iff (mapsTo_id _)] at this exact (this.1.prod_mk this.2).congr fun x hx ↦ (e.mk_proj_snd hx).symm theorem Trivialization.contMDiffOn_symm (e : Trivialization F (π F E)) [MemTrivializationAtlas e] : - ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) ⊤ e.toPartialHomeomorph.symm e.target := by + ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) n e.toPartialHomeomorph.symm e.target := by rw [e.contMDiffOn_iff e.toPartialHomeomorph.symm_mapsTo] refine ⟨contMDiffOn_fst.congr fun x hx ↦ e.proj_symm_apply hx, contMDiffOn_snd.congr fun x hx ↦ ?_⟩ @@ -523,30 +544,32 @@ alias Trivialization.smoothOn_symm := Trivialization.contMDiffOn_symm end -/-! ### Core construction for smooth vector bundles -/ +/-! ### Core construction for `C^n` vector bundles -/ namespace VectorBundleCore variable {F} variable {ι : Type*} (Z : VectorBundleCore 𝕜 B F ι) -/-- Mixin for a `VectorBundleCore` stating smoothness (of transition functions). -/ -class IsSmooth (IB : ModelWithCorners 𝕜 EB HB) : Prop where +/-- Mixin for a `VectorBundleCore` stating that transition functions are `C^n`. -/ +class IsContMDiff (IB : ModelWithCorners 𝕜 EB HB) (n : WithTop ℕ∞) : Prop where contMDiffOn_coordChange : - ∀ i j, ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) + ∀ i j, ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) + +@[deprecated (since := "2025-01-09")] alias IsSmooth := IsContMDiff -theorem contMDiffOn_coordChange (IB : ModelWithCorners 𝕜 EB HB) [h : Z.IsSmooth IB] (i j : ι) : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) := +theorem contMDiffOn_coordChange (IB : ModelWithCorners 𝕜 EB HB) [h : Z.IsContMDiff IB n] (i j : ι) : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) := h.1 i j @[deprecated (since := "2024-11-21")] alias smoothOn_coordChange := contMDiffOn_coordChange -variable [Z.IsSmooth IB] +variable [Z.IsContMDiff IB n] -/-- If a `VectorBundleCore` has the `IsSmooth` mixin, then the vector bundle constructed from it -is a smooth vector bundle. -/ -instance smoothVectorBundle : SmoothVectorBundle F Z.Fiber IB where +/-- If a `VectorBundleCore` has the `IsContMDiff` mixin, then the vector bundle constructed from it +is a `C^n` vector bundle. -/ +instance instContMDiffVectorBundle : ContMDiffVectorBundle n F Z.Fiber IB where contMDiffOn_coordChangeL := by rintro - - ⟨i, rfl⟩ ⟨i', rfl⟩ refine (Z.contMDiffOn_coordChange IB i i').congr fun b hb ↦ ?_ @@ -555,10 +578,11 @@ instance smoothVectorBundle : SmoothVectorBundle F Z.Fiber IB where end VectorBundleCore -/-! ### The trivial smooth vector bundle -/ +/-! ### The trivial `C^n` vector bundle -/ -/-- A trivial vector bundle over a smooth manifold is a smooth vector bundle. -/ -instance Bundle.Trivial.smoothVectorBundle : SmoothVectorBundle F (Bundle.Trivial B F) IB where +/-- A trivial vector bundle over a manifold is a `C^n` vector bundle. -/ +instance Bundle.Trivial.contMDiffVectorBundle : + ContMDiffVectorBundle n F (Bundle.Trivial B F) IB where contMDiffOn_coordChangeL := by intro e e' he he' obtain rfl := Bundle.Trivial.eq_trivialization B F e @@ -566,7 +590,7 @@ instance Bundle.Trivial.smoothVectorBundle : SmoothVectorBundle F (Bundle.Trivia simp_rw [Bundle.Trivial.trivialization.coordChangeL] exact contMDiff_const.contMDiffOn -/-! ### Direct sums of smooth vector bundles -/ +/-! ### Direct sums of `C^n` vector bundles -/ section Prod @@ -578,13 +602,13 @@ variable (F₂ : Type*) [NormedAddCommGroup F₂] [NormedSpace 𝕜 F₂] (E₂ [TopologicalSpace (TotalSpace F₂ E₂)] [∀ x, AddCommMonoid (E₂ x)] [∀ x, Module 𝕜 (E₂ x)] variable [∀ x : B, TopologicalSpace (E₁ x)] [∀ x : B, TopologicalSpace (E₂ x)] [FiberBundle F₁ E₁] - [FiberBundle F₂ E₂] [VectorBundle 𝕜 F₁ E₁] [VectorBundle 𝕜 F₂ E₂] [SmoothVectorBundle F₁ E₁ IB] - [SmoothVectorBundle F₂ E₂ IB] + [FiberBundle F₂ E₂] [VectorBundle 𝕜 F₁ E₁] [VectorBundle 𝕜 F₂ E₂] + [ContMDiffVectorBundle n F₁ E₁ IB] [ContMDiffVectorBundle n F₂ E₂ IB] -variable [SmoothManifoldWithCorners IB B] +variable [IsManifold IB n B] -/-- The direct sum of two smooth vector bundles over the same base is a smooth vector bundle. -/ -instance Bundle.Prod.smoothVectorBundle : SmoothVectorBundle (F₁ × F₂) (E₁ ×ᵇ E₂) IB where +/-- The direct sum of two `C^n` vector bundles over the same base is a `C^n` vector bundle. -/ +instance Bundle.Prod.contMDiffVectorBundle : ContMDiffVectorBundle n (F₁ × F₂) (E₁ ×ᵇ E₂) IB where contMDiffOn_coordChangeL := by rintro _ _ ⟨e₁, e₂, i₁, i₂, rfl⟩ ⟨e₁', e₂', i₁', i₂', rfl⟩ refine ContMDiffOn.congr ?_ (e₁.coordChangeL_prod 𝕜 e₁' e₂ e₂') @@ -600,65 +624,79 @@ end Prod end WithTopology -/-! ### Prebundle construction for smooth vector bundles -/ +/-! ### Prebundle construction for `C^n` vector bundles -/ namespace VectorPrebundle variable [∀ x, TopologicalSpace (E x)] variable (IB) in -/-- Mixin for a `VectorPrebundle` stating smoothness of coordinate changes. -/ -class IsSmooth (a : VectorPrebundle 𝕜 F E) : Prop where - exists_smoothCoordChange : +/-- Mixin for a `VectorPrebundle` stating that coordinate changes are `C^n`. -/ +class IsContMDiff (a : VectorPrebundle 𝕜 F E) (n : WithTop ℕ∞) : Prop where + exists_contMDiffCoordChange : ∀ᵉ (e ∈ a.pretrivializationAtlas) (e' ∈ a.pretrivializationAtlas), ∃ f : B → F →L[𝕜] F, - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ f (e.baseSet ∩ e'.baseSet) ∧ + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n f (e.baseSet ∩ e'.baseSet) ∧ ∀ (b : B) (_ : b ∈ e.baseSet ∩ e'.baseSet) (v : F), f b v = (e' ⟨b, e.symm b v⟩).2 -variable (a : VectorPrebundle 𝕜 F E) [ha : a.IsSmooth IB] {e e' : Pretrivialization F (π F E)} +@[deprecated (since := "2025-01-09")] alias IsSmooth := IsContMDiff -variable (IB) in -/-- A randomly chosen coordinate change on a `SmoothVectorPrebundle`, given by - the field `exists_coordChange`. Note that `a.smoothCoordChange` need not be the same as +variable (a : VectorPrebundle 𝕜 F E) [ha : a.IsContMDiff IB n] {e e' : Pretrivialization F (π F E)} + +variable (IB n) in +/-- A randomly chosen coordinate change on a `VectorPrebundle` satisfying `IsContMDiff`, given by + the field `exists_coordChange`. Note that `a.contMDiffCoordChange` need not be the same as `a.coordChange`. -/ -noncomputable def smoothCoordChange (he : e ∈ a.pretrivializationAtlas) +noncomputable def contMDiffCoordChange (he : e ∈ a.pretrivializationAtlas) (he' : e' ∈ a.pretrivializationAtlas) (b : B) : F →L[𝕜] F := - Classical.choose (ha.exists_smoothCoordChange e he e' he') b + Classical.choose (ha.exists_contMDiffCoordChange e he e' he') b -theorem contMDiffOn_smoothCoordChange (he : e ∈ a.pretrivializationAtlas) +@[deprecated (since := "2025-01-09")] alias smoothCoordChange := contMDiffCoordChange + +theorem contMDiffOn_contMDiffCoordChange (he : e ∈ a.pretrivializationAtlas) (he' : e' ∈ a.pretrivializationAtlas) : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (a.smoothCoordChange IB he he') (e.baseSet ∩ e'.baseSet) := - (Classical.choose_spec (ha.exists_smoothCoordChange e he e' he')).1 + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (a.contMDiffCoordChange n IB he he') + (e.baseSet ∩ e'.baseSet) := + (Classical.choose_spec (ha.exists_contMDiffCoordChange e he e' he')).1 + +@[deprecated (since := "2025-01-09")] +alias contMDiffOn_smoothCoordChange := contMDiffOn_contMDiffCoordChange @[deprecated (since := "2024-11-21")] -alias smoothOn_smoothCoordChange := contMDiffOn_smoothCoordChange +alias smoothOn_smoothCoordChange := contMDiffOn_contMDiffCoordChange -theorem smoothCoordChange_apply (he : e ∈ a.pretrivializationAtlas) +theorem contMDiffCoordChange_apply (he : e ∈ a.pretrivializationAtlas) (he' : e' ∈ a.pretrivializationAtlas) {b : B} (hb : b ∈ e.baseSet ∩ e'.baseSet) (v : F) : - a.smoothCoordChange IB he he' b v = (e' ⟨b, e.symm b v⟩).2 := - (Classical.choose_spec (ha.exists_smoothCoordChange e he e' he')).2 b hb v + a.contMDiffCoordChange n IB he he' b v = (e' ⟨b, e.symm b v⟩).2 := + (Classical.choose_spec (ha.exists_contMDiffCoordChange e he e' he')).2 b hb v + +@[deprecated (since := "2025-01-09")] alias smoothCoordChange_apply := contMDiffCoordChange_apply -theorem mk_smoothCoordChange (he : e ∈ a.pretrivializationAtlas) +theorem mk_contMDiffCoordChange (he : e ∈ a.pretrivializationAtlas) (he' : e' ∈ a.pretrivializationAtlas) {b : B} (hb : b ∈ e.baseSet ∩ e'.baseSet) (v : F) : - (b, a.smoothCoordChange IB he he' b v) = e' ⟨b, e.symm b v⟩ := by + (b, a.contMDiffCoordChange n IB he he' b v) = e' ⟨b, e.symm b v⟩ := by ext · rw [e.mk_symm hb.1 v, e'.coe_fst', e.proj_symm_apply' hb.1] rw [e.proj_symm_apply' hb.1]; exact hb.2 - · exact a.smoothCoordChange_apply he he' hb v + · exact a.contMDiffCoordChange_apply he he' hb v + +@[deprecated (since := "2025-01-09")] alias mk_smoothCoordChange := mk_contMDiffCoordChange variable (IB) in -/-- Make a `SmoothVectorBundle` from a `SmoothVectorPrebundle`. -/ -theorem smoothVectorBundle : @SmoothVectorBundle +/-- Make a `ContMDiffVectorBundle` from a `ContMDiffVectorPrebundle`. -/ +theorem contMDiffVectorBundle : @ContMDiffVectorBundle n _ _ F E _ _ _ _ _ _ IB _ _ _ _ _ _ a.totalSpaceTopology _ a.toFiberBundle a.toVectorBundle := letI := a.totalSpaceTopology; letI := a.toFiberBundle; letI := a.toVectorBundle { contMDiffOn_coordChangeL := by rintro _ _ ⟨e, he, rfl⟩ ⟨e', he', rfl⟩ - refine (a.contMDiffOn_smoothCoordChange he he').congr ?_ + refine (a.contMDiffOn_contMDiffCoordChange he he').congr ?_ intro b hb ext v - rw [a.smoothCoordChange_apply he he' hb v, ContinuousLinearEquiv.coe_coe, + rw [a.contMDiffCoordChange_apply he he' hb v, ContinuousLinearEquiv.coe_coe, Trivialization.coordChangeL_apply] exacts [rfl, hb] } +@[deprecated (since := "2025-01-09")] alias smoothVectorBundle := contMDiffVectorBundle + end VectorPrebundle diff --git a/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean b/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean index 0bc3d2285bba8..c68e3c2255418 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean @@ -5,10 +5,10 @@ Authors: Floris van Doorn, Heather Macbeth -/ import Mathlib.Geometry.Manifold.ContMDiff.NormedSpace -/-! # The groupoid of smooth, fiberwise-linear maps +/-! # The groupoid of `C^n`, fiberwise-linear maps -This file contains preliminaries for the definition of a smooth vector bundle: an associated -`StructureGroupoid`, the groupoid of `smoothFiberwiseLinear` functions. +This file contains preliminaries for the definition of a `C^n` vector bundle: an associated +`StructureGroupoid`, the groupoid of `contMDiffFiberwiseLinear` functions. -/ noncomputable section @@ -17,7 +17,7 @@ open Set TopologicalSpace open scoped Manifold Topology -/-! ### The groupoid of smooth, fiberwise-linear maps -/ +/-! ### The groupoid of `C^n`, fiberwise-linear maps -/ variable {𝕜 B F : Type*} [TopologicalSpace B] @@ -95,22 +95,23 @@ variable {EB : Type*} [NormedAddCommGroup EB] [NormedSpace 𝕜 EB] {HB : Type*} [TopologicalSpace HB] [ChartedSpace HB B] {IB : ModelWithCorners 𝕜 EB HB} /-- Let `e` be a partial homeomorphism of `B × F`. Suppose that at every point `p` in the source of -`e`, there is some neighbourhood `s` of `p` on which `e` is equal to a bi-smooth fiberwise linear +`e`, there is some neighbourhood `s` of `p` on which `e` is equal to a bi-`C^n` fiberwise linear partial homeomorphism. Then the source of `e` is of the form `U ×ˢ univ`, for some set `U` in `B`, and, at any point `x` in -`U`, admits a neighbourhood `u` of `x` such that `e` is equal on `u ×ˢ univ` to some bi-smooth +`U`, admits a neighbourhood `u` of `x` such that `e` is equal on `u ×ˢ univ` to some bi-`C^n` fiberwise linear partial homeomorphism. -/ -theorem SmoothFiberwiseLinear.locality_aux₁ (e : PartialHomeomorph (B × F) (B × F)) +theorem ContMDiffFiberwiseLinear.locality_aux₁ + (n : WithTop ℕ∞) (e : PartialHomeomorph (B × F) (B × F)) (h : ∀ p ∈ e.source, ∃ s : Set (B × F), IsOpen s ∧ p ∈ s ∧ ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) - (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x : F →L[𝕜] F)) u) - (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((φ x).symm : F →L[𝕜] F)) u), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (φ x : F →L[𝕜] F)) u) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr s).EqOnSource (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : ∃ U : Set B, e.source = U ×ˢ univ ∧ ∀ x ∈ U, ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) (_huU : u ⊆ U) (_hux : x ∈ u), - ∃ (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x : F →L[𝕜] F)) u) - (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((φ x).symm : F →L[𝕜] F)) u), + ∃ (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (φ x : F →L[𝕜] F)) u) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr (u ×ˢ univ)).EqOnSource (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn) := by rw [SetCoe.forall'] at h @@ -140,28 +141,31 @@ theorem SmoothFiberwiseLinear.locality_aux₁ (e : PartialHomeomorph (B × F) (B · intro y hy; exact ⟨(y, 0), heu ⟨p, hp⟩ ⟨_, _⟩ hy, rfl⟩ · rw [← hesu, e.restr_source_inter]; exact heφ ⟨p, hp⟩ +@[deprecated (since := "2025-01-09")] +alias SmoothFiberwiseLinear.locality_aux₁ := ContMDiffFiberwiseLinear.locality_aux₁ + /-- Let `e` be a partial homeomorphism of `B × F` whose source is `U ×ˢ univ`, for some set `U` in `B`, and which, at any point `x` in `U`, admits a neighbourhood `u` of `x` such that `e` is equal -on `u ×ˢ univ` to some bi-smooth fiberwise linear partial homeomorphism. Then `e` itself -is equal to some bi-smooth fiberwise linear partial homeomorphism. +on `u ×ˢ univ` to some bi-`C^n` fiberwise linear partial homeomorphism. Then `e` itself +is equal to some bi-`C^n` fiberwise linear partial homeomorphism. This is the key mathematical point of the `locality` condition in the construction of the -`StructureGroupoid` of bi-smooth fiberwise linear partial homeomorphisms. The proof is by gluing -together the various bi-smooth fiberwise linear partial homeomorphism which exist locally. +`StructureGroupoid` of bi-`C^n` fiberwise linear partial homeomorphisms. The proof is by gluing +together the various bi-`C^n` fiberwise linear partial homeomorphism which exist locally. The `U` in the conclusion is the same `U` as in the hypothesis. We state it like this, because this -is exactly what we need for `smoothFiberwiseLinear`. -/ -theorem SmoothFiberwiseLinear.locality_aux₂ (e : PartialHomeomorph (B × F) (B × F)) (U : Set B) - (hU : e.source = U ×ˢ univ) +is exactly what we need for `contMDiffFiberwiseLinear`. -/ +theorem ContMDiffFiberwiseLinear.locality_aux₂ + (n : WithTop ℕ∞) (e : PartialHomeomorph (B × F) (B × F)) (U : Set B) (hU : e.source = U ×ˢ univ) (h : ∀ x ∈ U, ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) (_hUu : u ⊆ U) (_hux : x ∈ u) - (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x : F →L[𝕜] F)) u) - (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((φ x).symm : F →L[𝕜] F)) u), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (φ x : F →L[𝕜] F)) u) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr (u ×ˢ univ)).EqOnSource (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : ∃ (Φ : B → F ≃L[𝕜] F) (U : Set B) (hU₀ : IsOpen U) (hΦ : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (Φ x : F →L[𝕜] F)) U) (h2Φ : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((Φ x).symm : F →L[𝕜] F)) U), + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (Φ x : F →L[𝕜] F)) U) (h2Φ : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => ((Φ x).symm : F →L[𝕜] F)) U), e.EqOnSource (FiberwiseLinear.partialHomeomorph Φ hU₀ hΦ.continuousOn h2Φ.continuousOn) := by classical rw [SetCoe.forall'] at h @@ -192,14 +196,14 @@ theorem SmoothFiberwiseLinear.locality_aux₂ (e : PartialHomeomorph (B × F) (B intro x y hyu refine (hΦ y (hUu x hyu)).trans ?_ exact iUnionLift_mk ⟨y, hyu⟩ _ - have hΦ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun y => (Φ y : F →L[𝕜] F)) U := by + have hΦ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun y => (Φ y : F →L[𝕜] F)) U := by apply contMDiffOn_of_locally_contMDiffOn intro x hx refine ⟨u ⟨x, hx⟩, hu ⟨x, hx⟩, hux _, ?_⟩ refine (ContMDiffOn.congr (hφ ⟨x, hx⟩) ?_).mono inter_subset_right intro y hy rw [hΦφ ⟨x, hx⟩ y hy] - have h2Φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun y => ((Φ y).symm : F →L[𝕜] F)) U := by + have h2Φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun y => ((Φ y).symm : F →L[𝕜] F)) U := by apply contMDiffOn_of_locally_contMDiffOn intro x hx refine ⟨u ⟨x, hx⟩, hu ⟨x, hx⟩, hux _, ?_⟩ @@ -213,34 +217,36 @@ theorem SmoothFiberwiseLinear.locality_aux₂ (e : PartialHomeomorph (B × F) (B rw [hΦφ] apply hux -variable (F B IB) +@[deprecated (since := "2025-01-09")] +alias SmoothFiberwiseLinear.locality_aux₂ := ContMDiffFiberwiseLinear.locality_aux₂ -variable {F B IB} in -- Having this private lemma speeds up `simp` calls below a lot. -- TODO: understand why and fix the underlying issue (relatedly, the `simp` calls --- in `smoothFiberwiseLinear` are quite slow, even with this change) -private theorem mem_aux {e : PartialHomeomorph (B × F) (B × F)} : +-- in `contMDiffFiberwiseLinear` are quite slow, even with this change) +private theorem mem_aux {e : PartialHomeomorph (B × F) (B × F)} {n : WithTop ℕ∞} : (e ∈ ⋃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) - (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) - (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => φ x : B → F →L[𝕜] F) U) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (φ x).symm : B → F →L[𝕜] F) U), {e | e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn)}) ↔ ∃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) - (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) - (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => φ x : B → F →L[𝕜] F) U) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (φ x).symm : B → F →L[𝕜] F) U), e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := by simp only [mem_iUnion, mem_setOf_eq] +variable (F B IB) + /-- For `B` a manifold and `F` a normed space, the groupoid on `B × F` consisting of local -homeomorphisms which are bi-smooth and fiberwise linear, and induce the identity on `B`. -When a (topological) vector bundle is smooth, then the composition of charts associated +homeomorphisms which are bi-`C^n` and fiberwise linear, and induce the identity on `B`. +When a (topological) vector bundle is `C^n`, then the composition of charts associated to the vector bundle belong to this groupoid. -/ -def smoothFiberwiseLinear : StructureGroupoid (B × F) where +def contMDiffFiberwiseLinear (n : WithTop ℕ∞) : StructureGroupoid (B × F) where members := ⋃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) - (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) - (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => φ x : B → F →L[𝕜] F) U) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (φ x).symm : B → F →L[𝕜] F) U), {e | e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn)} trans' := by simp only [mem_aux] @@ -248,11 +254,11 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where refine ⟨fun b => (φ b).trans (φ' b), _, hU.inter hU', ?_, ?_, Setoid.trans (PartialHomeomorph.EqOnSource.trans' heφ heφ') ⟨?_, ?_⟩⟩ · show - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x : B => (φ' x).toContinuousLinearMap ∘L (φ x).toContinuousLinearMap) (U ∩ U') exact (hφ'.mono inter_subset_right).clm_comp (hφ.mono inter_subset_left) · show - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x : B => (φ x).symm.toContinuousLinearMap ∘L (φ' x).symm.toContinuousLinearMap) (U ∩ U') exact (h2φ.mono inter_subset_left).clm_comp (h2φ'.mono inter_subset_right) @@ -275,18 +281,23 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where -- the hard work has been extracted to `locality_aux₁` and `locality_aux₂` simp only [mem_aux] intro e he - obtain ⟨U, hU, h⟩ := SmoothFiberwiseLinear.locality_aux₁ e he - exact SmoothFiberwiseLinear.locality_aux₂ e U hU h + obtain ⟨U, hU, h⟩ := ContMDiffFiberwiseLinear.locality_aux₁ n e he + exact ContMDiffFiberwiseLinear.locality_aux₂ n e U hU h mem_of_eqOnSource' := by simp only [mem_aux] rintro e e' ⟨φ, U, hU, hφ, h2φ, heφ⟩ hee' exact ⟨φ, U, hU, hφ, h2φ, Setoid.trans hee' heφ⟩ +@[deprecated (since := "2025-01-09")] alias smoothFiberwiseLinear := contMDiffFiberwiseLinear + @[simp] -theorem mem_smoothFiberwiseLinear_iff (e : PartialHomeomorph (B × F) (B × F)) : - e ∈ smoothFiberwiseLinear B F IB ↔ +theorem mem_contMDiffFiberwiseLinear_iff {n : WithTop ℕ∞} (e : PartialHomeomorph (B × F) (B × F)) : + e ∈ contMDiffFiberwiseLinear B F IB n ↔ ∃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) (hφ : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun x => (φ x).symm : B → F →L[𝕜] F) U), e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := mem_aux + +@[deprecated (since := "2025-01-09")] +alias mem_smoothFiberwiseLinear_iff := mem_contMDiffFiberwiseLinear_iff diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean b/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean index d00cefedfa42b..b81193c0eae27 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean @@ -6,9 +6,9 @@ Authors: Floris van Doorn import Mathlib.Geometry.Manifold.VectorBundle.Basic import Mathlib.Topology.VectorBundle.Hom -/-! # Homs of smooth vector bundles over the same base space +/-! # Homs of `C^n` vector bundles over the same base space -Here we show that `Bundle.ContinuousLinearMap` is a smooth vector bundle. +Here we show that `Bundle.ContinuousLinearMap` is a `C^n` vector bundle. Note that we only do this for bundles of linear maps, not for bundles of arbitrary semilinear maps. To do it for semilinear maps, we would need to generalize `ContinuousLinearMap.contMDiff` @@ -24,7 +24,8 @@ open scoped Manifold Bundle Topology section -variable {𝕜 B F₁ F₂ M : Type*} {E₁ : B → Type*} {E₂ : B → Type*} [NontriviallyNormedField 𝕜] +variable {𝕜 B F₁ F₂ M : Type*} {n : WithTop ℕ∞} + {E₁ : B → Type*} {E₂ : B → Type*} [NontriviallyNormedField 𝕜] [∀ x, AddCommGroup (E₁ x)] [∀ x, Module 𝕜 (E₁ x)] [NormedAddCommGroup F₁] [NormedSpace 𝕜 F₁] [TopologicalSpace (TotalSpace F₁ E₁)] [∀ x, TopologicalSpace (E₁ x)] [∀ x, AddCommGroup (E₂ x)] [∀ x, Module 𝕜 (E₂ x)] [NormedAddCommGroup F₂] [NormedSpace 𝕜 F₂] @@ -42,13 +43,14 @@ local notation "LE₁E₂" => TotalSpace (F₁ →L[𝕜] F₂) (Bundle.Continuo -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11083): moved slow parts to separate lemmas theorem contMDiffOn_continuousLinearMapCoordChange - [SmoothVectorBundle F₁ E₁ IB] [SmoothVectorBundle F₂ E₂ IB] [MemTrivializationAtlas e₁] - [MemTrivializationAtlas e₁'] [MemTrivializationAtlas e₂] [MemTrivializationAtlas e₂'] : - ContMDiffOn IB 𝓘(𝕜, (F₁ →L[𝕜] F₂) →L[𝕜] F₁ →L[𝕜] F₂) ⊤ + [ContMDiffVectorBundle n F₁ E₁ IB] [ContMDiffVectorBundle n F₂ E₂ IB] + [MemTrivializationAtlas e₁] [MemTrivializationAtlas e₁'] + [MemTrivializationAtlas e₂] [MemTrivializationAtlas e₂'] : + ContMDiffOn IB 𝓘(𝕜, (F₁ →L[𝕜] F₂) →L[𝕜] F₁ →L[𝕜] F₂) n (continuousLinearMapCoordChange (RingHom.id 𝕜) e₁ e₁' e₂ e₂') (e₁.baseSet ∩ e₂.baseSet ∩ (e₁'.baseSet ∩ e₂'.baseSet)) := by - have h₁ := contMDiffOn_coordChangeL (IB := IB) e₁' e₁ (n := ⊤) - have h₂ := contMDiffOn_coordChangeL (IB := IB) e₂ e₂' (n := ⊤) + have h₁ := contMDiffOn_coordChangeL (IB := IB) e₁' e₁ (n := n) + have h₂ := contMDiffOn_coordChangeL (IB := IB) e₂ e₂' (n := n) refine (h₁.mono ?_).cle_arrowCongr (h₂.mono ?_) <;> mfld_set_tac @[deprecated (since := "2024-11-21")] @@ -73,19 +75,23 @@ theorem contMDiffAt_hom_bundle (f : M → LE₁E₂) {x₀ : M} {n : ℕ∞} : @[deprecated (since := "2024-11-21")] alias smoothAt_hom_bundle := contMDiffAt_hom_bundle -variable [SmoothVectorBundle F₁ E₁ IB] [SmoothVectorBundle F₂ E₂ IB] +variable [ContMDiffVectorBundle n F₁ E₁ IB] [ContMDiffVectorBundle n F₂ E₂ IB] -instance Bundle.ContinuousLinearMap.vectorPrebundle.isSmooth : - (Bundle.ContinuousLinearMap.vectorPrebundle (RingHom.id 𝕜) F₁ E₁ F₂ E₂).IsSmooth IB where - exists_smoothCoordChange := by +instance Bundle.ContinuousLinearMap.vectorPrebundle.isContMDiff : + (Bundle.ContinuousLinearMap.vectorPrebundle (RingHom.id 𝕜) F₁ E₁ F₂ E₂).IsContMDiff IB n where + exists_contMDiffCoordChange := by rintro _ ⟨e₁, e₂, he₁, he₂, rfl⟩ _ ⟨e₁', e₂', he₁', he₂', rfl⟩ exact ⟨continuousLinearMapCoordChange (RingHom.id 𝕜) e₁ e₁' e₂ e₂', contMDiffOn_continuousLinearMapCoordChange, continuousLinearMapCoordChange_apply (RingHom.id 𝕜) e₁ e₁' e₂ e₂'⟩ -instance SmoothVectorBundle.continuousLinearMap : - SmoothVectorBundle (F₁ →L[𝕜] F₂) (Bundle.ContinuousLinearMap (RingHom.id 𝕜) E₁ E₂) IB := - (Bundle.ContinuousLinearMap.vectorPrebundle (RingHom.id 𝕜) F₁ E₁ F₂ E₂).smoothVectorBundle IB +@[deprecated (since := "2025-01-09")] +alias Bundle.ContinuousLinearMap.vectorPrebundle.isSmooth := + Bundle.ContinuousLinearMap.vectorPrebundle.isContMDiff + +instance ContMDiffVectorBundle.continuousLinearMap : + ContMDiffVectorBundle n (F₁ →L[𝕜] F₂) (Bundle.ContinuousLinearMap (RingHom.id 𝕜) E₁ E₂) IB := + (Bundle.ContinuousLinearMap.vectorPrebundle (RingHom.id 𝕜) F₁ E₁ F₂ E₂).contMDiffVectorBundle IB end @@ -111,14 +117,14 @@ variable {𝕜 F₁ F₂ B₁ B₂ M : Type*} {E₁ : B₁ → Type*} {E₂ : B {EM : Type*} [NormedAddCommGroup EM] [NormedSpace 𝕜 EM] {HM : Type*} [TopologicalSpace HM] {IM : ModelWithCorners 𝕜 EM HM} [TopologicalSpace M] [ChartedSpace HM M] - {n : ℕ∞} [FiberBundle F₁ E₁] [VectorBundle 𝕜 F₁ E₁] + {n : WithTop ℕ∞} [FiberBundle F₁ E₁] [VectorBundle 𝕜 F₁ E₁] [FiberBundle F₂ E₂] [VectorBundle 𝕜 F₂ E₂] {b₁ : M → B₁} {b₂ : M → B₂} {m₀ : M} {ϕ : Π (m : M), E₁ (b₁ m) →L[𝕜] E₂ (b₂ m)} {v : Π (m : M), E₁ (b₁ m)} {s : Set M} -/-- Consider a smooth map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and +/-- Consider a `C^n` map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and another basemap `b₂ : M → B₂`. Given linear maps `ϕ m : E₁ (b₁ m) → E₂ (b₂ m)` depending smoothly -on `m`, one can apply `ϕ m` to `g m`, and the resulting map is smooth. +on `m`, one can apply `ϕ m` to `g m`, and the resulting map is `C^n`. Note that the smoothness of `ϕ` can not be always be stated as smoothness of a map into a manifold, as the pullback bundles `b₁ *ᵖ E₁` and `b₂ *ᵖ E₂` only make sense when `b₁` and `b₂` are globally @@ -154,9 +160,9 @@ lemma ContMDiffWithinAt.clm_apply_of_inCoordinates congr rw [Trivialization.symm_apply_apply_mk (trivializationAt F₁ E₁ (b₁ m₀)) hm (v m)] -/-- Consider a smooth map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and +/-- Consider a `C^n` map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and another basemap `b₂ : M → B₂`. Given linear maps `ϕ m : E₁ (b₁ m) → E₂ (b₂ m)` depending smoothly -on `m`, one can apply `ϕ m` to `g m`, and the resulting map is smooth. +on `m`, one can apply `ϕ m` to `g m`, and the resulting map is `C^n`. Note that the smoothness of `ϕ` can not be always be stated as smoothness of a map into a manifold, as the pullback bundles `b₁ *ᵖ E₁` and `b₂ *ᵖ E₂` only make sense when `b₁` and `b₂` are globally diff --git a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean index 3f9eae5d70e38..3e6a93a1a9fed 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean @@ -33,7 +33,7 @@ variable [NontriviallyNormedField 𝕜] [NormedAddCommGroup F] [NormedSpace 𝕜 variable [TopologicalSpace B] [ChartedSpace HB B] [FiberBundle F E] -/-- Characterization of differentiable functions into a smooth vector bundle. -/ +/-- Characterization of differentiable functions into a vector bundle. -/ theorem mdifferentiableWithinAt_totalSpace (f : M → TotalSpace F E) {s : Set M} {x₀ : M} : MDifferentiableWithinAt IM (IB.prod 𝓘(𝕜, F)) f s x₀ ↔ MDifferentiableWithinAt IM IB (fun x => (f x).proj) s x₀ ∧ @@ -85,14 +85,14 @@ variable {𝕜 F₁ F₂ B₁ B₂ M : Type*} {E₁ : B₁ → Type*} {E₂ : B {b₁ : M → B₁} {b₂ : M → B₂} {m₀ : M} {ϕ : Π (m : M), E₁ (b₁ m) →L[𝕜] E₂ (b₂ m)} {v : Π (m : M), E₁ (b₁ m)} {s : Set M} -/-- Consider a smooth map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and -another basemap `b₂ : M → B₂`. Given linear maps `ϕ m : E₁ (b₁ m) → E₂ (b₂ m)` depending smoothly -on `m`, one can apply `ϕ m` to `g m`, and the resulting map is smooth. +/-- Consider a differentiable map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and +another basemap `b₂ : M → B₂`. Given linear maps `ϕ m : E₁ (b₁ m) → E₂ (b₂ m)` depending +differentiably on `m`, one can apply `ϕ m` to `g m`, and the resulting map is differentiable. -Note that the smoothness of `ϕ` can not be always be stated as smoothness of a map into a manifold, -as the pullback bundles `b₁ *ᵖ E₁` and `b₂ *ᵖ E₂` only make sense when `b₁` and `b₂` are globally -smooth, but we want to apply this lemma with only local information. Therefore, we formulate it -using smoothness of `ϕ` read in coordinates. +Note that the differentiability of `ϕ` can not be always be stated as differentiability of a map +into a manifold, as the pullback bundles `b₁ *ᵖ E₁` and `b₂ *ᵖ E₂` only make sense when `b₁` +and `b₂` are globally smooth, but we want to apply this lemma with only local information. +Therefore, we formulate it using differentiability of `ϕ` read in coordinates. Version for `MDifferentiableWithinAt`. We also give a version for `MDifferentiableAt`, but no version for `MDifferentiableOn` or `MDifferentiable` as our assumption, written in coordinates, @@ -123,14 +123,14 @@ lemma MDifferentiableWithinAt.clm_apply_of_inCoordinates congr rw [Trivialization.symm_apply_apply_mk (trivializationAt F₁ E₁ (b₁ m₀)) hm (v m)] -/-- Consider a smooth map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and -another basemap `b₂ : M → B₂`. Given linear maps `ϕ m : E₁ (b₁ m) → E₂ (b₂ m)` depending smoothly -on `m`, one can apply `ϕ m` to `g m`, and the resulting map is smooth. +/-- Consider a differentiable map `v : M → E₁` to a vector bundle, over a basemap `b₁ : M → B₁`, and +another basemap `b₂ : M → B₂`. Given linear maps `ϕ m : E₁ (b₁ m) → E₂ (b₂ m)` depending +differentiably on `m`, one can apply `ϕ m` to `g m`, and the resulting map is differentiable. -Note that the smoothness of `ϕ` can not be always be stated as smoothness of a map into a manifold, -as the pullback bundles `b₁ *ᵖ E₁` and `b₂ *ᵖ E₂` only make sense when `b₁` and `b₂` are globally -smooth, but we want to apply this lemma with only local information. Therefore, we formulate it -using smoothness of `ϕ` read in coordinates. +Note that the differentiability of `ϕ` can not be always be stated as differentiability of a map +into a manifold, as the pullback bundles `b₁ *ᵖ E₁` and `b₂ *ᵖ E₂` only make sense when `b₁` +and `b₂` are globally smooth, but we want to apply this lemma with only local information. +Therefore, we formulate it using differentiability of `ϕ` read in coordinates. Version for `MDifferentiableAt`. We also give a version for `MDifferentiableWithinAt`, but no version for `MDifferentiableOn` or `MDifferentiable` as our assumption, written diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean b/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean index 7ba8cdb7b86d3..e40c7b3b20284 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean @@ -6,21 +6,21 @@ Authors: Floris van Doorn, Heather Macbeth import Mathlib.Geometry.Manifold.ContMDiffMap import Mathlib.Geometry.Manifold.VectorBundle.Basic -/-! # Pullbacks of smooth vector bundles +/-! # Pullbacks of `C^n` vector bundles -This file defines pullbacks of smooth vector bundles over a smooth manifold. +This file defines pullbacks of `C^n` vector bundles over a manifold. ## Main definitions -* `SmoothVectorBundle.pullback`: For a smooth vector bundle `E` over a manifold `B` and a smooth - map `f : B' → B`, the pullback vector bundle `f *ᵖ E` is a smooth vector bundle. +* `ContMDiffVectorBundle.pullback`: For a `C^n` vector bundle `E` over a manifold `B` and a `C^n` + map `f : B' → B`, the pullback vector bundle `f *ᵖ E` is a `C^n` vector bundle. -/ open Bundle Set open scoped Manifold -variable {𝕜 B B' : Type*} (F : Type*) (E : B → Type*) +variable {𝕜 B B' : Type*} (F : Type*) (E : B → Type*) {n : WithTop ℕ∞} variable [NontriviallyNormedField 𝕜] [∀ x, AddCommMonoid (E x)] [∀ x, Module 𝕜 (E x)] [NormedAddCommGroup F] [NormedSpace 𝕜 F] [TopologicalSpace (TotalSpace F E)] [∀ x, TopologicalSpace (E x)] {EB : Type*} [NormedAddCommGroup EB] [NormedSpace 𝕜 EB] @@ -28,11 +28,11 @@ variable [NontriviallyNormedField 𝕜] [∀ x, AddCommMonoid (E x)] [∀ x, Mod [ChartedSpace HB B] {EB' : Type*} [NormedAddCommGroup EB'] [NormedSpace 𝕜 EB'] {HB' : Type*} [TopologicalSpace HB'] (IB' : ModelWithCorners 𝕜 EB' HB') [TopologicalSpace B'] [ChartedSpace HB' B'] [FiberBundle F E] - [VectorBundle 𝕜 F E] [SmoothVectorBundle F E IB] (f : ContMDiffMap IB' IB B' B ⊤) + [VectorBundle 𝕜 F E] [ContMDiffVectorBundle n F E IB] (f : ContMDiffMap IB' IB B' B n) -/-- For a smooth vector bundle `E` over a manifold `B` and a smooth map `f : B' → B`, the pullback -vector bundle `f *ᵖ E` is a smooth vector bundle. -/ -instance SmoothVectorBundle.pullback : SmoothVectorBundle F (f *ᵖ E) IB' where +/-- For a `C^n` vector bundle `E` over a manifold `B` and a `C^n` map `f : B' → B`, the pullback +vector bundle `f *ᵖ E` is a `C^n` vector bundle. -/ +instance ContMDiffVectorBundle.pullback : ContMDiffVectorBundle n F (f *ᵖ E) IB' where contMDiffOn_coordChangeL := by rintro _ _ ⟨e, he, rfl⟩ ⟨e', he', rfl⟩ refine ((contMDiffOn_coordChangeL e e').comp f.contMDiff.contMDiffOn fun b hb => hb).congr ?_ diff --git a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean index 60a27aee36286..fa5a1a2036d04 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean @@ -9,19 +9,16 @@ import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Geometry.Manifold.VectorBundle.Basic /-! -# Smooth sections +# `C^n` sections In this file we define the type `ContMDiffSection` of `n` times continuously differentiable -sections of a smooth vector bundle over a manifold `M` and prove that it's a module. +sections of a vector bundle over a manifold `M` and prove that it's a module. -/ open Bundle Filter Function -open scoped Bundle Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) +open scoped Bundle Manifold ContDiff variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) @@ -29,7 +26,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom variable (F : Type*) [NormedAddCommGroup F] [NormedSpace 𝕜 F] -- `F` model fiber - (n : ℕ∞) + (n : WithTop ℕ∞) (V : M → Type*) [TopologicalSpace (TotalSpace F V)] -- `V` vector bundle [∀ x : M, TopologicalSpace (V x)] [FiberBundle F V] @@ -176,7 +173,7 @@ theorem coe_smul (r : 𝕜) (s : Cₛ^n⟮I; F, V⟯) : ⇑(r • s : Cₛ^n⟮I rfl variable (I F V n) in -/-- The additive morphism from smooth sections to dependent maps. -/ +/-- The additive morphism from `C^n` sections to dependent maps. -/ def coeAddHom : Cₛ^n⟮I; F, V⟯ →+ ∀ x, V x where toFun := (↑) map_zero' := coe_zero @@ -193,7 +190,7 @@ protected theorem mdifferentiable' (s : Cₛ^n⟮I; F, V⟯) (hn : 1 ≤ n) : protected theorem mdifferentiable (s : Cₛ^∞⟮I; F, V⟯) : MDifferentiable I (I.prod 𝓘(𝕜, F)) fun x => TotalSpace.mk' F x (s x : V x) := - s.contMDiff.mdifferentiable le_top + s.contMDiff.mdifferentiable (mod_cast le_top) protected theorem mdifferentiableAt (s : Cₛ^∞⟮I; F, V⟯) {x} : MDifferentiableAt I (I.prod 𝓘(𝕜, F)) (fun x => TotalSpace.mk' F x (s x : V x)) x := diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean b/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean index 25d2843cf2298..626c2c96a3159 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean @@ -7,13 +7,13 @@ import Mathlib.Geometry.Manifold.VectorBundle.Basic /-! # Tangent bundles -This file defines the tangent bundle as a smooth vector bundle. +This file defines the tangent bundle as a `C^n` vector bundle. Let `M` be a manifold with model `I` on `(E, H)`. The tangent space `TangentSpace I (x : M)` has already been defined as a type synonym for `E`, and the tangent bundle `TangentBundle I M` as an abbrev of `Bundle.TotalSpace E (TangentSpace I : M → Type _)`. -In this file, when `M` is smooth, we construct a smooth vector bundle structure +In this file, when `M` is `C^1`, we construct a vector bundle structure on `TangentBundle I M` using the `VectorBundleCore` construction indexed by the charts of `M` with fibers `E`. Given two charts `i, j : PartialHomeomorph M H`, the coordinate change between `i` and `j` at a point `x : M` is the derivative of the composite @@ -22,19 +22,19 @@ between `i` and `j` at a point `x : M` is the derivative of the composite E -----> H -----> M --> H --> E ``` within the set `range I ⊆ E` at `I (i x) : E`. -This defines a smooth vector bundle `TangentBundle` with fibers `TangentSpace`. +This defines a vector bundle `TangentBundle` with fibers `TangentSpace`. ## Main definitions and results * `tangentBundleCore I M` is the vector bundle core for the tangent bundle over `M`. -* When `M` is a smooth manifold with corners, `TangentBundle I M` has a smooth vector bundle +* When `M` is a `C^{n+1}` manifold, `TangentBundle I M` has a `C^n` vector bundle structure over `M`. In particular, it is a topological space, a vector bundle, a fiber bundle, -and a smooth manifold. +and a `C^n` manifold. -/ -open Bundle Set SmoothManifoldWithCorners PartialHomeomorph ContinuousLinearMap +open Bundle Set IsManifold PartialHomeomorph ContinuousLinearMap open scoped Manifold Topology Bundle ContDiff @@ -42,31 +42,34 @@ noncomputable section section General -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {n : WithTop ℕ∞} {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] - [SmoothManifoldWithCorners I' M'] {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] + {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] /-- Auxiliary lemma for tangent spaces: the derivative of a coordinate change between two charts is - smooth on its source. -/ -theorem contDiffOn_fderiv_coord_change (i j : atlas H M) : - ContDiffOn 𝕜 ∞ (fderivWithin 𝕜 (j.1.extend I ∘ (i.1.extend I).symm) (range I)) + `C^n` on its source. -/ +theorem contDiffOn_fderiv_coord_change [IsManifold I (n + 1) M] + (i j : atlas H M) : + ContDiffOn 𝕜 n (fderivWithin 𝕜 (j.1.extend I ∘ (i.1.extend I).symm) (range I)) ((i.1.extend I).symm ≫ j.1.extend I).source := by have h : ((i.1.extend I).symm ≫ j.1.extend I).source ⊆ range I := by rw [i.1.extend_coord_change_source]; apply image_subset_range intro x hx - refine (ContDiffWithinAt.fderivWithin_right ?_ I.uniqueDiffOn (n := ∞) (mod_cast le_top) + refine (ContDiffWithinAt.fderivWithin_right ?_ I.uniqueDiffOn le_rfl <| h hx).mono h refine (PartialHomeomorph.contDiffOn_extend_coord_change (subset_maximalAtlas j.2) (subset_maximalAtlas i.2) x hx).mono_of_mem_nhdsWithin ?_ exact i.1.extend_coord_change_source_mem_nhdsWithin j.1 hx -open SmoothManifoldWithCorners +open IsManifold + +variable [IsManifold I 1 M] [IsManifold I' 1 M'] variable (I M) in -/-- Let `M` be a smooth manifold with corners with model `I` on `(E, H)`. +/-- Let `M` be a `C^1` manifold with model `I` on `(E, H)`. Then `tangentBundleCore I M` is the vector bundle core for the tangent bundle over `M`. It is indexed by the atlas of `M`, with fiber `E` and its change of coordinates from the chart `i` to the chart `j` at point `x : M` is the derivative of the composite @@ -84,18 +87,20 @@ def tangentBundleCore : VectorBundleCore 𝕜 M E (atlas H M) where coordChange i j x := fderivWithin 𝕜 (j.1.extend I ∘ (i.1.extend I).symm) (range I) (i.1.extend I x) coordChange_self i x hx v := by - simp only + dsimp only rw [Filter.EventuallyEq.fderivWithin_eq, fderivWithin_id', ContinuousLinearMap.id_apply] · exact I.uniqueDiffWithinAt_image · filter_upwards [i.1.extend_target_mem_nhdsWithin hx] with y hy exact (i.1.extend I).right_inv hy · simp_rw [Function.comp_apply, i.1.extend_left_inv hx] continuousOn_coordChange i j := by - refine (contDiffOn_fderiv_coord_change i j).continuousOn.comp + have : IsManifold I (0 + 1) M := by simp; infer_instance + refine (contDiffOn_fderiv_coord_change (n := 0) i j).continuousOn.comp (i.1.continuousOn_extend.mono ?_) ?_ · rw [i.1.extend_source]; exact inter_subset_left simp_rw [← i.1.extend_image_source_inter, mapsTo_image] coordChange_comp := by + have : IsManifold I (0 + 1) M := by simp; infer_instance rintro i j k x ⟨⟨hxi, hxj⟩, hxk⟩ v rw [fderivWithin_fderivWithin, Filter.EventuallyEq.fderivWithin_eq] · have := i.1.extend_preimage_mem_nhds (I := I) hxi (j.1.extend_source_mem_nhds (I := I) hxj) @@ -103,9 +108,9 @@ def tangentBundleCore : VectorBundleCore 𝕜 M E (atlas H M) where simp_rw [Function.comp_apply, (j.1.extend I).left_inv hy] · simp_rw [Function.comp_apply, i.1.extend_left_inv hxi, j.1.extend_left_inv hxj] · exact (contDiffWithinAt_extend_coord_change' (subset_maximalAtlas k.2) - (subset_maximalAtlas j.2) hxk hxj).differentiableWithinAt (mod_cast le_top) + (subset_maximalAtlas j.2) hxk hxj).differentiableWithinAt le_rfl · exact (contDiffWithinAt_extend_coord_change' (subset_maximalAtlas j.2) - (subset_maximalAtlas i.2) hxj hxi).differentiableWithinAt (mod_cast le_top) + (subset_maximalAtlas i.2) hxj hxi).differentiableWithinAt le_rfl · intro x _; exact mem_range_self _ · exact I.uniqueDiffWithinAt_image · rw [Function.comp_apply, i.1.extend_left_inv hxi] @@ -154,7 +159,7 @@ lemma hasFDerivWithinAt_tangentCoordChange {x y z : M} have h' : extChartAt I x z ∈ ((extChartAt I x).symm ≫ (extChartAt I y)).source := by rw [PartialEquiv.trans_source'', PartialEquiv.symm_symm, PartialEquiv.symm_target] exact mem_image_of_mem _ h - ((contDiffWithinAt_ext_coord_change y x h').differentiableWithinAt (by simp)).hasFDerivWithinAt + ((contDiffWithinAt_ext_coord_change y x h').differentiableWithinAt le_rfl).hasFDerivWithinAt lemma continuousOn_tangentCoordChange (x y : M) : ContinuousOn (tangentCoordChange I x y) ((extChartAt I x).source ∩ (extChartAt I y).source) := by @@ -283,7 +288,11 @@ theorem continuousLinearMapAt_model_space (b b' : F) : end TangentBundle -instance tangentBundleCore.isSmooth : (tangentBundleCore I M).IsSmooth I := by +omit [IsManifold I 1 M] in +lemma tangentBundleCore.isContMDiff [h : IsManifold I (n + 1) M] : + haveI : IsManifold I 1 M := .of_le (n := n + 1) le_add_self + (tangentBundleCore I M).IsContMDiff I n := by + have : IsManifold I n M := .of_le (n := n + 1) (le_self_add) refine ⟨fun i j => ?_⟩ rw [contMDiffOn_iff_source_of_mem_maximalAtlas (subset_maximalAtlas i.2), contMDiffOn_iff_contDiffOn] @@ -293,8 +302,36 @@ instance tangentBundleCore.isSmooth : (tangentBundleCore I M).IsSmooth I := by · exact (i.1.extend_image_source_inter j.1).subset · apply inter_subset_left -instance TangentBundle.smoothVectorBundle : SmoothVectorBundle E (TangentSpace I : M → Type _) I := - (tangentBundleCore I M).smoothVectorBundle +@[deprecated (since := "2025-01-09")] +alias tangentBundleCore.isSmooth := tangentBundleCore.isContMDiff + +omit [IsManifold I 1 M] in +lemma TangentBundle.contMDiffVectorBundle [h : IsManifold I (n + 1) M] : + haveI : IsManifold I 1 M := .of_le (n := n + 1) le_add_self + ContMDiffVectorBundle n E (TangentSpace I : M → Type _) I := by + have : IsManifold I 1 M := .of_le (n := n + 1) le_add_self + have : (tangentBundleCore I M).IsContMDiff I n := tangentBundleCore.isContMDiff + exact (tangentBundleCore I M).instContMDiffVectorBundle + +@[deprecated (since := "2025-01-09")] +alias TangentBundle.smoothVectorBundle := TangentBundle.contMDiffVectorBundle + +omit [IsManifold I 1 M] in +instance [h : IsManifold I ∞ M] : + ContMDiffVectorBundle ∞ E (TangentSpace I : M → Type _) I := by + have : IsManifold I (∞ + 1) M := h + exact TangentBundle.contMDiffVectorBundle + +omit [IsManifold I 1 M] in +instance [IsManifold I ω M] : + ContMDiffVectorBundle ω E (TangentSpace I : M → Type _) I := + TangentBundle.contMDiffVectorBundle + +omit [IsManifold I 1 M] in +instance [h : IsManifold I 2 M] : + ContMDiffVectorBundle 1 E (TangentSpace I : M → Type _) I := by + have : IsManifold I (1 + 1) M := h + exact TangentBundle.contMDiffVectorBundle end TangentBundleInstances @@ -396,7 +433,7 @@ theorem contMDiff_tangentBundleModelSpaceHomeomorph_symm {n : ℕ∞} : exact ⟨rfl, rfl⟩ variable (H I) in -/-- In the tangent bundle to the model space, the second projection is smooth. -/ +/-- In the tangent bundle to the model space, the second projection is `C^n`. -/ lemma contMDiff_snd_tangentBundle_modelSpace {n : ℕ∞} : ContMDiff I.tangent 𝓘(𝕜, E) n (fun (p : TangentBundle I H) ↦ p.2) := by change ContMDiff I.tangent 𝓘(𝕜, E) n @@ -407,7 +444,7 @@ lemma contMDiff_snd_tangentBundle_modelSpace {n : ℕ∞} : rfl · exact contMDiff_tangentBundleModelSpaceHomeomorph -/-- A vector field on a vector space is smooth in the manifold sense iff it is smooth in the vector +/-- A vector field on a vector space is `C^n` in the manifold sense iff it is `C^n` in the vector space sense-/ lemma contMDiffWithinAt_vectorSpace_iff_contDiffWithinAt {V : Π (x : E), TangentSpace 𝓘(𝕜, E) x} {n : ℕ∞} {s : Set E} {x : E} : @@ -421,7 +458,7 @@ lemma contMDiffWithinAt_vectorSpace_iff_contDiffWithinAt convert h.contMDiffWithinAt with y simp -/-- A vector field on a vector space is smooth in the manifold sense iff it is smooth in the vector +/-- A vector field on a vector space is `C^n` in the manifold sense iff it is `C^n` in the vector space sense-/ lemma contMDiffAt_vectorSpace_iff_contDiffAt {V : Π (x : E), TangentSpace 𝓘(𝕜, E) x} {n : ℕ∞} {x : E} : @@ -430,7 +467,7 @@ lemma contMDiffAt_vectorSpace_iff_contDiffAt simp only [← contMDiffWithinAt_univ, ← contDiffWithinAt_univ, contMDiffWithinAt_vectorSpace_iff_contDiffWithinAt] -/-- A vector field on a vector space is smooth in the manifold sense iff it is smooth in the vector +/-- A vector field on a vector space is `C^n` in the manifold sense iff it is `C^n` in the vector space sense-/ lemma contMDiffOn_vectorSpace_iff_contDiffOn {V : Π (x : E), TangentSpace 𝓘(𝕜, E) x} {n : ℕ∞} {s : Set E} : @@ -438,7 +475,7 @@ lemma contMDiffOn_vectorSpace_iff_contDiffOn ContDiffOn 𝕜 n V s := by simp only [ContMDiffOn, ContDiffOn, contMDiffWithinAt_vectorSpace_iff_contDiffWithinAt ] -/-- A vector field on a vector space is smooth in the manifold sense iff it is smooth in the vector +/-- A vector field on a vector space is `C^n` in the manifold sense iff it is `C^n` in the vector space sense-/ lemma contMDiff_vectorSpace_iff_contDiff {V : Π (x : E), TangentSpace 𝓘(𝕜, E) x} {n : ℕ∞} : diff --git a/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean b/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean index a6416ab861ef1..98f721ecd53de 100644 --- a/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean +++ b/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean @@ -27,15 +27,13 @@ partition of unity, smooth bump function, whitney theorem universe uι uE uH uM +open Function Filter Module Set Topology +open scoped Manifold ContDiff + variable {ι : Type uι} {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] {H : Type uH} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} - {M : Type uM} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] + {M : Type uM} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I ∞ M] -open Function Filter Module Set Topology -open scoped Manifold -/- Next line is necessary while the manifold smoothness class is not extended to `ω`. -Later, replace with `open scoped ContDiff`. -/ -local notation "∞" => (⊤ : ℕ∞) noncomputable section @@ -85,7 +83,7 @@ theorem comp_embeddingPiTangent_mfderiv (x : M) (hx : x ∈ s) : (ContinuousLinearMap.fst ℝ E ℝ).comp (@ContinuousLinearMap.proj ℝ _ ι (fun _ => E × ℝ) _ _ (fun _ => inferInstance) (f.ind x hx)) have := L.hasMFDerivAt.comp x - (f.embeddingPiTangent.contMDiff.mdifferentiableAt le_top).hasMFDerivAt + (f.embeddingPiTangent.contMDiff.mdifferentiableAt (mod_cast le_top)).hasMFDerivAt convert hasMFDerivAt_unique this _ refine (hasMFDerivAt_extChartAt (f.mem_chartAt_ind_source x hx)).congr_of_eventuallyEq ?_ refine (f.eventuallyEq_one x hx).mono fun y hy => ?_ @@ -110,7 +108,7 @@ supports of bump functions, then for some `n` it can be immersed into the `n`-di Euclidean space. -/ theorem exists_immersion_euclidean {ι : Type*} [Finite ι] (f : SmoothBumpCovering ι I M) : ∃ (n : ℕ) (e : M → EuclideanSpace ℝ (Fin n)), - ContMDiff I (𝓡 n) ⊤ e ∧ Injective e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by + ContMDiff I (𝓡 n) ∞ e ∧ Injective e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by cases nonempty_fintype ι set F := EuclideanSpace ℝ (Fin <| finrank ℝ (ι → E × ℝ)) letI : IsNoetherian ℝ (E × ℝ) := IsNoetherian.iff_fg.2 inferInstance @@ -121,7 +119,7 @@ theorem exists_immersion_euclidean {ι : Type*} [Finite ι] (f : SmoothBumpCover eEF.toDiffeomorph.contMDiff.comp f.embeddingPiTangent.contMDiff, eEF.injective.comp f.embeddingPiTangent_injective, fun x => ?_⟩ rw [mfderiv_comp _ eEF.differentiableAt.mdifferentiableAt - (f.embeddingPiTangent.contMDiff.mdifferentiableAt le_top), + (f.embeddingPiTangent.contMDiff.mdifferentiableAt (mod_cast le_top)), eEF.mfderiv_eq] exact eEF.injective.comp (f.embeddingPiTangent_injective_mfderiv _ trivial) @@ -132,7 +130,7 @@ supports of bump functions, then for some `n` it can be embedded into the `n`-di Euclidean space. -/ theorem exists_embedding_euclidean_of_compact [T2Space M] [CompactSpace M] : ∃ (n : ℕ) (e : M → EuclideanSpace ℝ (Fin n)), - ContMDiff I (𝓡 n) ⊤ e ∧ IsClosedEmbedding e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by + ContMDiff I (𝓡 n) ∞ e ∧ IsClosedEmbedding e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by rcases SmoothBumpCovering.exists_isSubordinate I isClosed_univ fun (x : M) _ => univ_mem with ⟨ι, f, -⟩ haveI := f.fintype diff --git a/docs/overview.yaml b/docs/overview.yaml index 088401f11aefc..2d11b73912178 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -412,12 +412,12 @@ Geometry: angle: 'InnerProductGeometry.angle' Differentiable manifolds: - smooth manifold (with boundary and corners): 'SmoothManifoldWithCorners' - smooth map between manifolds: 'MDifferentiableAt' + smooth or analytic manifold (with boundary and corners): 'IsManifold' + smooth map between manifolds: 'ContMDiff' tangent bundle: 'TangentBundle' tangent map: 'tangentMap' Lie group: 'LieGroup' - sphere: 'EuclideanSpace.instSmoothManifoldWithCornersSphere' + sphere: 'EuclideanSpace.instIsManifoldSphere' Algebraic geometry: prime spectrum: 'PrimeSpectrum' diff --git a/scripts/nolints_prime_decls.txt b/scripts/nolints_prime_decls.txt index 253e549ada88b..6fdfdc2ba7ecd 100644 --- a/scripts/nolints_prime_decls.txt +++ b/scripts/nolints_prime_decls.txt @@ -4395,10 +4395,6 @@ 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' From 517700845089dac5fdccf6ab7f4ae6808465d42e Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 9 Jan 2025 15:44:38 +0000 Subject: [PATCH 102/681] feat: the `#find_syntax` command (#17986) The `#find_syntax` command takes as input a string `str` and retrieves from the environment all the candidates for `syntax` terms that contain the string `str`. It also makes a very crude effort at regenerating what the syntax looks like, by inspecting the `Expr`ession tree of the corresponding parser. [Zulip](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/Finding.20syntax) --- Mathlib.lean | 1 + Mathlib/Tactic.lean | 1 + Mathlib/Tactic/FindSyntax.lean | 93 ++++++++++++++++++++++++++++++++++ MathlibTest/FindSyntax.lean | 81 +++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+) create mode 100644 Mathlib/Tactic/FindSyntax.lean create mode 100644 MathlibTest/FindSyntax.lean diff --git a/Mathlib.lean b/Mathlib.lean index d9da848ebdd31..decf75bd1225b 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4871,6 +4871,7 @@ import Mathlib.Tactic.FailIfNoProgress import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.FinCases import Mathlib.Tactic.Find +import Mathlib.Tactic.FindSyntax import Mathlib.Tactic.Finiteness import Mathlib.Tactic.Finiteness.Attr import Mathlib.Tactic.FunProp diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index 86cf871b98d36..60f53209f5ed1 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -83,6 +83,7 @@ import Mathlib.Tactic.FailIfNoProgress import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.FinCases import Mathlib.Tactic.Find +import Mathlib.Tactic.FindSyntax import Mathlib.Tactic.Finiteness import Mathlib.Tactic.Finiteness.Attr import Mathlib.Tactic.FunProp diff --git a/Mathlib/Tactic/FindSyntax.lean b/Mathlib/Tactic/FindSyntax.lean new file mode 100644 index 0000000000000..e6582cd0d9bde --- /dev/null +++ b/Mathlib/Tactic/FindSyntax.lean @@ -0,0 +1,93 @@ +/- +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 +import Mathlib.Init + +/-! +# The `#find_syntax` command + +The `#find_syntax` command takes as input a string `str` and retrieves from the environment +all the candidates for `syntax` terms that contain the string `str`. + +It also makes a very crude effort at regenerating what the syntax looks like, by inspecting the +`Expr`ession tree of the corresponding parser. +-/ + +namespace Mathlib.FindSyntax + +open Lean Elab Command + +/-- +`extractSymbols expr` takes as input an `Expr`ession `expr`, assuming that it is the `value` +of a "parser". +It returns the array of all subterms of `expr` that are the `Expr.lit` argument to +`Lean.ParserDescr.symbol` and `Lean.ParserDescr.nonReservedSymbol` applications. + +The output array serves as a way of regenerating what the syntax tree of the input parser is. +-/ +def extractSymbols : Expr → Array Expr + | .app a b => + let rest := extractSymbols a ++ extractSymbols b + match a.constName with + | ``Lean.ParserDescr.symbol | ``Lean.ParserDescr.nonReservedSymbol => rest.push b + | _ => rest + | .letE _ a b c _ => extractSymbols a ++ extractSymbols b ++ extractSymbols c + | .lam _ a b _ => extractSymbols a ++ extractSymbols b + | .forallE _ a b _ => extractSymbols a ++ extractSymbols b + | .mdata _ a => extractSymbols a + | .proj _ _ a => extractSymbols a + | _ => #[] + +/-- +`litToString expr` converts the input `Expr`ession `expr` into the "natural" string that +it corresponds to, in case `expr` is a `String`/`Nat`-literal, returning the empty string `""` +otherwise. +-/ +def litToString : Expr → String + | .lit (.natVal v) => s!"{v}" + | .lit (.strVal v) => v + | _ => "" + +/-- +The `#find_syntax` command takes as input a string `str` and retrieves from the environment +all the candidates for `syntax` terms that contain the string `str`. + +It also makes a very crude effort at regenerating what the syntax looks like: +this is supposed to be just indicative of what the syntax may look like, but there is no +guarantee or expectation of correctness. + +The optional trailing `approx`, as in `#find_syntax "∘" approx`, is only intended to make tests +more stable: rather than outputting the exact count of the overall number of existing syntax +declarations, it returns its round-down to the previous multiple of 100. +-/ +elab "#find_syntax " id:str d:(&" approx")? : command => do + let prsr : Array Expr := #[.const ``ParserDescr [], .const ``TrailingParserDescr []] + let mut symbs : Std.HashSet (Name × Array Expr) := {} + -- We scan the environment in search of "parsers" whose name is not internal and that + -- contain some `symbol` information and we store them in `symbs` + for (declName, cinfo) in (← getEnv).constants do + if prsr.contains cinfo.type && cinfo.hasValue then + let ls := extractSymbols cinfo.value! + if !declName.isInternal && !ls.isEmpty then symbs := symbs.insert (declName, ls) + -- From among the parsers in `symbs`, we extract the ones whose `symbols` contain the input `str` + let mut msgs := #[] + for (nm, ar) in symbs.toList do + let rem : String := " _ ".intercalate (ar.map litToString).toList + -- If either the name of the parser or the regenerated syntax stub contains the input string, + -- then we include an entry into the final message. + if 2 ≤ (nm.toString.splitOn id.getString).length || 2 ≤ (rem.splitOn id.getString).length then + msgs := msgs.push <| .ofConstName nm ++ m!":\n '{rem.trim}'\n" + -- We sort the messages to produce a more stable output. + let msgsToString ← msgs.mapM (·.toString) + msgs := (msgs.zip msgsToString).qsort (·.2 < ·.2) |>.map (·.1) + let uses := msgs.size + let numSymbs := if d.isSome then s!"over {(symbs.size / 100) * 100}" else s!"{symbs.size}" + let head := m!"Found {uses} use{if uses == 1 then "" else "s"} \ + among {numSymbs} syntax declarations" + logInfo <| .joinSep (head::(msgs.push "").toList) "\n---\n\n" + +end Mathlib.FindSyntax diff --git a/MathlibTest/FindSyntax.lean b/MathlibTest/FindSyntax.lean new file mode 100644 index 0000000000000..fcbbceee4b0f1 --- /dev/null +++ b/MathlibTest/FindSyntax.lean @@ -0,0 +1,81 @@ +import Mathlib.Tactic.FindSyntax + +/-- +info: Found 1 use among over 500 syntax declarations +--- + +«term_∘_»: + '∘' + +--- +-/ +#guard_msgs in +#find_syntax "∘" approx -- an `infixr` + +/-- +info: Found 1 use among over 500 syntax declarations +--- + +«term_∣_»: + '∣' + +--- +-/ +#guard_msgs in +#find_syntax "∣" approx -- an `infix` + +/-- +info: Found 2 uses among over 500 syntax declarations +--- + +«stx_,*,?»: + ',*,?' + +--- + +«stx_,*»: + ',*' + +--- +-/ +#guard_msgs in +#find_syntax ",*" approx -- generated by a `macro` + +/-- +info: Found 1 use among over 500 syntax declarations +--- + +«term~~~_»: + '~~~' + +--- +-/ +#guard_msgs in +#find_syntax "~~~" approx -- a `prefix` + +/-- +info: Found 4 uses among over 500 syntax declarations +--- + +Lean.Parser.Tactic.refine': + 'refine'' + +--- + +Lean.Parser.Tactic.refine: + 'refine' + +--- + +Lean.Parser.Tactic.tacticRefine_lift'_: + 'refine_lift'' + +--- + +Lean.Parser.Tactic.tacticRefine_lift_: + 'refine_lift' + +--- +-/ +#guard_msgs in +#find_syntax "refine" approx -- a `nonReservedSymbol` From 1da931e93e05ed9f4695d02ef181c87d8528bc1e Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Thu, 9 Jan 2025 15:53:25 +0000 Subject: [PATCH 103/681] feat(RingTheory/StandardSmooth): pre-requisites for calculating the naive cotangent complex of a submersive presentation (#19749) Preparations for #19748 Co-authored-by: Christian Merten <136261474+chrisflav@users.noreply.github.com> --- Mathlib.lean | 1 + .../Algebra/BigOperators/Group/Finset.lean | 6 ++ Mathlib/Data/Matrix/Mul.lean | 18 ++++ Mathlib/LinearAlgebra/Basis/Exact.lean | 93 +++++++++++++++++++ Mathlib/LinearAlgebra/Dimension/Free.lean | 5 + Mathlib/LinearAlgebra/Finsupp/Defs.lean | 1 + Mathlib/LinearAlgebra/Matrix/ToLin.lean | 11 +++ Mathlib/RingTheory/Extension.lean | 4 + Mathlib/RingTheory/Presentation.lean | 5 + Mathlib/RingTheory/Smooth/StandardSmooth.lean | 63 ++++++++++++- 10 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 Mathlib/LinearAlgebra/Basis/Exact.lean diff --git a/Mathlib.lean b/Mathlib.lean index decf75bd1225b..a93997f28634d 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3366,6 +3366,7 @@ import Mathlib.LinearAlgebra.Basis.Basic import Mathlib.LinearAlgebra.Basis.Bilinear import Mathlib.LinearAlgebra.Basis.Cardinality import Mathlib.LinearAlgebra.Basis.Defs +import Mathlib.LinearAlgebra.Basis.Exact import Mathlib.LinearAlgebra.Basis.Flag import Mathlib.LinearAlgebra.Basis.VectorSpace import Mathlib.LinearAlgebra.BilinearForm.Basic diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index 47e77cc8c7ce4..47c2a0587a76d 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -543,6 +543,12 @@ theorem prod_disj_sum (s : Finset α) (t : Finset γ) (f : α ⊕ γ → β) : rw [← map_inl_disjUnion_map_inr, prod_disjUnion, prod_map, prod_map] rfl +@[to_additive] +lemma prod_sum_eq_prod_toLeft_mul_prod_toRight (s : Finset (α ⊕ γ)) (f : α ⊕ γ → β) : + ∏ x ∈ s, f x = (∏ x ∈ s.toLeft, f (Sum.inl x)) * ∏ x ∈ s.toRight, f (Sum.inr x) := by + rw [← Finset.toLeft_disjSum_toRight (u := s), Finset.prod_disj_sum, Finset.toLeft_disjSum, + Finset.toRight_disjSum] + @[to_additive] theorem prod_sum_elim (s : Finset α) (t : Finset γ) (f : α → β) (g : γ → β) : ∏ x ∈ s.disjSum t, Sum.elim f g x = (∏ x ∈ s, f x) * ∏ x ∈ t, g x := by simp diff --git a/Mathlib/Data/Matrix/Mul.lean b/Mathlib/Data/Matrix/Mul.lean index 3d4f563be4268..eeffd7a456162 100644 --- a/Mathlib/Data/Matrix/Mul.lean +++ b/Mathlib/Data/Matrix/Mul.lean @@ -890,6 +890,24 @@ theorem vecMul_mulVec [Fintype m] [Fintype n] (A : Matrix m n α) (B : Matrix m end NonUnitalCommSemiring +section Semiring + +variable [Semiring R] + +lemma mulVec_injective_of_isUnit [Fintype m] [DecidableEq m] {A : Matrix m m R} + (ha : IsUnit A) : Function.Injective A.mulVec := by + obtain ⟨B, hBl, hBr⟩ := isUnit_iff_exists.mp ha + intro x y hxy + simpa [hBr] using congrArg B.mulVec hxy + +lemma vecMul_injective_of_isUnit [Fintype m] [DecidableEq m] {A : Matrix m m R} + (ha : IsUnit A) : Function.Injective A.vecMul := by + obtain ⟨B, hBl, hBr⟩ := isUnit_iff_exists.mp ha + intro x y hxy + simpa [hBl] using congrArg B.vecMul hxy + +end Semiring + section CommSemiring variable [CommSemiring α] diff --git a/Mathlib/LinearAlgebra/Basis/Exact.lean b/Mathlib/LinearAlgebra/Basis/Exact.lean new file mode 100644 index 0000000000000..47863f1f81c7d --- /dev/null +++ b/Mathlib/LinearAlgebra/Basis/Exact.lean @@ -0,0 +1,93 @@ +/- +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.Algebra.Exact +import Mathlib.Algebra.Module.Submodule.Pointwise +import Mathlib.LinearAlgebra.Basis.Basic + +/-! +# Basis from a split exact sequence + +Let `0 → K → M → P → 0` be a split exact sequence of `R`-modules, let `s : M → K` be a +retraction of `f` and `v` be a basis of `M` indexed by `κ ⊕ σ`. Then +if `s vᵢ = 0` for `i : κ` and `(s vⱼ)ⱼ` is linear independent for `j : σ`, then +the images of `vᵢ` for `i : κ` form a basis of `P`. + +We treat linear independence and the span condition separately. For convenience this +is stated not for `κ ⊕ σ`, but for an arbitrary type `ι` with two maps `κ → ι` and `σ → ι`. +-/ + +variable {R M K P : Type*} [Ring R] [AddCommGroup M] [AddCommGroup K] [AddCommGroup P] +variable [Module R M] [Module R K] [Module R P] +variable {f : K →ₗ[R] M} {g : M →ₗ[R] P} {s : M →ₗ[R] K} +variable (hs : s ∘ₗ f = LinearMap.id) (hfg : Function.Exact f g) +variable {ι κ σ : Type*} {v : ι → M} {a : κ → ι} {b : σ → ι} +include hs hfg + +lemma LinearIndependent.linearIndependent_of_exact_of_retraction + (hainj : Function.Injective a) (hsa : ∀ i, s (v (a i)) = 0) + (hli : LinearIndependent R v) : + LinearIndependent R (g ∘ v ∘ a) := by + apply (LinearIndependent.comp hli a hainj).map + rw [Submodule.disjoint_def, hfg.linearMap_ker_eq] + rintro - hy ⟨y, rfl⟩ + have hz : s (f y) = 0 := by + revert hy + generalize f y = x + intro hy + induction' hy using Submodule.span_induction with m hm + · obtain ⟨i, rfl⟩ := hm + apply hsa + all_goals simp_all + replace hs := DFunLike.congr_fun hs y + simp only [LinearMap.coe_comp, Function.comp_apply, LinearMap.id_coe, id_eq] at hs + rw [← hs, hz, map_zero] + +private lemma top_le_span_of_aux (v : κ ⊕ σ → M) + (hg : Function.Surjective g) (hslzero : ∀ i, s (v (.inl i)) = 0) + (hli : LinearIndependent R (s ∘ v ∘ .inr)) (hsp : ⊤ ≤ Submodule.span R (Set.range v)) : + ⊤ ≤ Submodule.span R (Set.range <| g ∘ v ∘ .inl) := by + rintro p - + obtain ⟨m, rfl⟩ := hg p + wlog h : m ∈ LinearMap.ker s + · let x : M := f (s m) + rw [show g m = g (m - f (s m)) by simp [hfg.apply_apply_eq_zero]] + apply this hs hfg v hg hslzero hli hsp + replace hs := DFunLike.congr_fun hs (s m) + simp only [LinearMap.coe_comp, Function.comp_apply, LinearMap.id_coe, id_eq] at hs + simp [hs] + have : m ∈ Submodule.span R (Set.range v) := hsp trivial + obtain ⟨c, rfl⟩ := Finsupp.mem_span_range_iff_exists_finsupp.mp this + simp only [LinearMap.mem_ker, Finsupp.sum, map_sum, map_smul, + Finset.sum_sum_eq_sum_toLeft_add_sum_toRight, map_add, hslzero, smul_zero, + Finset.sum_const_zero, zero_add] at h + replace hli := (linearIndependent_iff'.mp hli) c.support.toRight (c ∘ .inr) h + simp only [Finset.mem_toRight, Finsupp.mem_support_iff, Function.comp_apply, not_imp_self] at hli + simp only [Finsupp.sum, Finset.sum_sum_eq_sum_toLeft_add_sum_toRight, hli, zero_smul, + Finset.sum_const_zero, add_zero, map_sum, map_smul] + exact Submodule.sum_mem _ (fun i hi ↦ Submodule.smul_mem _ _ <| Submodule.subset_span ⟨i, rfl⟩) + +lemma Submodule.top_le_span_of_exact_of_retraction (hg : Function.Surjective g) + (hsa : ∀ i, s (v (a i)) = 0) (hlib : LinearIndependent R (s ∘ v ∘ b)) + (hab : Codisjoint (Set.range a) (Set.range b)) + (hsp : ⊤ ≤ Submodule.span R (Set.range v)) : + ⊤ ≤ Submodule.span R (Set.range <| g ∘ v ∘ a) := by + apply top_le_span_of_aux hs hfg (Sum.elim (v ∘ a) (v ∘ b)) hg hsa hlib + simp only [codisjoint_iff, Set.sup_eq_union, Set.top_eq_univ] at hab + rwa [Set.Sum.elim_range, Set.range_comp, Set.range_comp, ← Set.image_union, hab, Set.image_univ] + +/-- Let `0 → K → M → P → 0` be a split exact sequence of `R`-modules, let `s : M → K` be a +retraction of `f` and `v` be a basis of `M` indexed by `κ ⊕ σ`. Then +if `s vᵢ = 0` for `i : κ` and `(s vⱼ)ⱼ` is linear independent for `j : σ`, then +the images of `vᵢ` for `i : κ` form a basis of `P`. + +For convenience this is stated for an arbitrary type `ι` with two maps `κ → ι` and `σ → ι`. -/ +noncomputable def Basis.ofSplitExact (hg : Function.Surjective g) (v : Basis ι R M) + (hainj : Function.Injective a) (hsa : ∀ i, s (v (a i)) = 0) + (hlib : LinearIndependent R (s ∘ v ∘ b)) + (hab : Codisjoint (Set.range a) (Set.range b)) : + Basis κ R P := + Basis.mk (v.linearIndependent.linearIndependent_of_exact_of_retraction hs hfg hainj hsa) + (Submodule.top_le_span_of_exact_of_retraction hs hfg hg hsa hlib hab (by rw [v.span_eq])) diff --git a/Mathlib/LinearAlgebra/Dimension/Free.lean b/Mathlib/LinearAlgebra/Dimension/Free.lean index 6eee759d4983d..a22d2a62026a5 100644 --- a/Mathlib/LinearAlgebra/Dimension/Free.lean +++ b/Mathlib/LinearAlgebra/Dimension/Free.lean @@ -165,6 +165,11 @@ variable {M M'} namespace Module +/-- A free module of rank zero is trivial. -/ +lemma subsingleton_of_rank_zero (h : Module.rank R M = 0) : Subsingleton M := by + rw [← Basis.mk_eq_rank'' (Module.Free.chooseBasis R M), Cardinal.mk_eq_zero_iff] at h + exact (Module.Free.repr R M).subsingleton + /-- See `rank_lt_aleph0` for the inverse direction without `Module.Free R M`. -/ lemma rank_lt_aleph0_iff : Module.rank R M < ℵ₀ ↔ Module.Finite R M := by rw [Free.rank_eq_card_chooseBasisIndex, mk_lt_aleph0_iff] diff --git a/Mathlib/LinearAlgebra/Finsupp/Defs.lean b/Mathlib/LinearAlgebra/Finsupp/Defs.lean index 209cf08595298..f75eb1bab340d 100644 --- a/Mathlib/LinearAlgebra/Finsupp/Defs.lean +++ b/Mathlib/LinearAlgebra/Finsupp/Defs.lean @@ -158,6 +158,7 @@ sending `l : β →₀ M` to the finitely supported function from `α` to `M` gi `l` with `f`. This is the linear version of `Finsupp.comapDomain`. -/ +@[simps] def lcomapDomain (f : α → β) (hf : Function.Injective f) : (β →₀ M) →ₗ[R] α →₀ M where toFun l := Finsupp.comapDomain f l hf.injOn map_add' x y := by ext; simp diff --git a/Mathlib/LinearAlgebra/Matrix/ToLin.lean b/Mathlib/LinearAlgebra/Matrix/ToLin.lean index 3bd4090a55052..942c5135c5ac8 100644 --- a/Mathlib/LinearAlgebra/Matrix/ToLin.lean +++ b/Mathlib/LinearAlgebra/Matrix/ToLin.lean @@ -115,6 +115,11 @@ theorem Matrix.vecMul_injective_iff {R : Type*} [CommRing R] {M : Matrix m n R} ext j simp [vecMul, dotProduct] +lemma Matrix.linearIndependent_rows_of_isUnit {R : Type*} [CommRing R] {A : Matrix m m R} + [DecidableEq m] (ha : IsUnit A) : LinearIndependent R (fun i ↦ A i) := by + rw [← Matrix.vecMul_injective_iff] + exact Matrix.vecMul_injective_of_isUnit ha + section variable [DecidableEq m] @@ -276,6 +281,12 @@ theorem Matrix.mulVec_injective_iff {R : Type*} [CommRing R] {M : Matrix m n R} change Function.Injective (fun x ↦ _) ↔ _ simp_rw [← M.vecMul_transpose, vecMul_injective_iff] +lemma Matrix.linearIndependent_cols_of_isUnit {R : Type*} [CommRing R] [Fintype m] + {A : Matrix m m R} [DecidableEq m] (ha : IsUnit A) : + LinearIndependent R (fun i ↦ A.transpose i) := by + rw [← Matrix.mulVec_injective_iff] + exact Matrix.mulVec_injective_of_isUnit ha + end mulVec section ToMatrix' diff --git a/Mathlib/RingTheory/Extension.lean b/Mathlib/RingTheory/Extension.lean index ebbc9fdab7e1a..47c439fb59c7b 100644 --- a/Mathlib/RingTheory/Extension.lean +++ b/Mathlib/RingTheory/Extension.lean @@ -360,6 +360,10 @@ lemma Cotangent.val_mk (x : P.ker) : (mk x).val = Ideal.toCotangent _ x := rfl lemma Cotangent.mk_surjective : Function.Surjective (mk (P := P)) := fun x ↦ Ideal.toCotangent_surjective P.ker x.val +lemma Cotangent.mk_eq_zero_iff {P : Extension R S} (x : P.ker) : + Cotangent.mk x = 0 ↔ x.val ∈ P.ker ^ 2 := by + simp [Cotangent.ext_iff, Ideal.toCotangent_eq_zero] + variable {P'} variable [Algebra R R'] [Algebra R' R''] [Algebra R' S''] variable [Algebra S S'] [Algebra S' S''] [Algebra S S''] diff --git a/Mathlib/RingTheory/Presentation.lean b/Mathlib/RingTheory/Presentation.lean index 1cca0b2f225c8..398f0c3b2efbc 100644 --- a/Mathlib/RingTheory/Presentation.lean +++ b/Mathlib/RingTheory/Presentation.lean @@ -73,6 +73,11 @@ lemma aeval_val_relation (i) : aeval P.val (P.relation i) = 0 := by rw [← RingHom.mem_ker, ← P.ker_eq_ker_aeval_val, ← P.span_range_relation_eq_ker] exact Ideal.subset_span ⟨i, rfl⟩ +lemma relation_mem_ker (i : P.rels) : P.relation i ∈ P.ker := by + rw [← P.span_range_relation_eq_ker] + apply Ideal.subset_span + use i + /-- The polynomial algebra wrt a family of generators modulo a family of relations. -/ protected abbrev Quotient : Type (max w u) := P.Ring ⧸ P.ker diff --git a/Mathlib/RingTheory/Smooth/StandardSmooth.lean b/Mathlib/RingTheory/Smooth/StandardSmooth.lean index 5efb276bcdc27..ed0f9e657caf2 100644 --- a/Mathlib/RingTheory/Smooth/StandardSmooth.lean +++ b/Mathlib/RingTheory/Smooth/StandardSmooth.lean @@ -135,6 +135,17 @@ noncomputable def differential : (P.rels → P.Ring) →ₗ[P.Ring] (P.rels → Basis.constr P.basis P.Ring (fun j i : P.rels ↦ MvPolynomial.pderiv (P.map i) (P.relation j)) +/-- `PreSubmersivePresentation.differential` pushed forward to `S` via `aeval P.val`. -/ +noncomputable def aevalDifferential : (P.rels → S) →ₗ[S] (P.rels → S) := + (Pi.basisFun S P.rels).constr S + (fun j i : P.rels ↦ aeval P.val <| pderiv (P.map i) (P.relation j)) + +@[simp] +lemma aevalDifferential_single [DecidableEq P.rels] (i j : P.rels) : + P.aevalDifferential (Pi.single i 1) j = aeval P.val (pderiv (P.map j) (P.relation i)) := by + dsimp only [aevalDifferential] + rw [← Pi.basisFun_apply, Basis.constr_basis] + /-- The jacobian of a `P : PreSubmersivePresentation` is the determinant of `P.differential` viewed as element of `S`. -/ noncomputable def jacobian : S := @@ -158,6 +169,13 @@ lemma jacobiMatrix_apply (i j : P.rels) : P.jacobiMatrix i j = MvPolynomial.pderiv (P.map i) (P.relation j) := by simp [jacobiMatrix, LinearMap.toMatrix, differential, basis] +lemma aevalDifferential_toMatrix'_eq_mapMatrix_jacobiMatrix : + P.aevalDifferential.toMatrix' = (aeval P.val).mapMatrix P.jacobiMatrix := by + ext i j : 1 + rw [← LinearMap.toMatrix_eq_toMatrix'] + rw [LinearMap.toMatrix_apply] + simp [jacobiMatrix_apply] + end Matrix section Constructions @@ -262,11 +280,12 @@ the lower-right block has determinant jacobian of `P`. -/ -variable [Fintype (Q.comp P).rels] +variable [DecidableEq (Q.comp P).rels] [Fintype (Q.comp P).rels] open scoped Classical in private lemma jacobiMatrix_comp_inl_inr (i : Q.rels) (j : P.rels) : (Q.comp P).jacobiMatrix (Sum.inl i) (Sum.inr j) = 0 := by + classical rw [jacobiMatrix_apply] refine MvPolynomial.pderiv_eq_zero_of_not_mem_vars (fun hmem ↦ ?_) apply MvPolynomial.vars_rename at hmem @@ -279,7 +298,7 @@ private lemma jacobiMatrix_comp_₁₂ : (Q.comp P).jacobiMatrix.toBlocks₁₂ section Q -variable [Fintype Q.rels] +variable [DecidableEq Q.rels] [Fintype Q.rels] open scoped Classical in private lemma jacobiMatrix_comp_inl_inl (i j : Q.rels) : @@ -303,7 +322,7 @@ end Q section P -variable [Fintype P.rels] +variable [Fintype P.rels] [DecidableEq P.rels] open scoped Classical in private lemma jacobiMatrix_comp_inr_inr (i j : P.rels) : @@ -471,6 +490,44 @@ end BaseChange end Constructions +variable {R S} + +open Classical in +/-- If `P` is submersive, `PreSubmersivePresentation.aevalDifferential` is an isomorphism. -/ +noncomputable def aevalDifferentialEquiv (P : SubmersivePresentation R S) : + (P.rels → S) ≃ₗ[S] (P.rels → S) := + haveI : Fintype P.rels := Fintype.ofFinite P.rels + have : IsUnit (LinearMap.toMatrix (Pi.basisFun S P.rels) (Pi.basisFun S P.rels) + P.aevalDifferential).det := by + convert P.jacobian_isUnit + rw [LinearMap.toMatrix_eq_toMatrix', jacobian_eq_jacobiMatrix_det, + aevalDifferential_toMatrix'_eq_mapMatrix_jacobiMatrix, P.algebraMap_eq] + simp [RingHom.map_det] + LinearEquiv.ofIsUnitDet this + +variable (P : SubmersivePresentation R S) + +@[simp] +lemma aevalDifferentialEquiv_apply (x : P.rels → S) : + P.aevalDifferentialEquiv x = P.aevalDifferential x := + rfl + +/-- If `P` is a submersive presentation, the partial derivatives of `P.relation i` by +`P.map j` form a basis of `P.rels → S`. -/ +noncomputable def basisDeriv (P : SubmersivePresentation R S) : Basis P.rels S (P.rels → S) := + Basis.map (Pi.basisFun S P.rels) P.aevalDifferentialEquiv + +@[simp] +lemma basisDeriv_apply (i j : P.rels) : + P.basisDeriv i j = (aeval P.val) (pderiv (P.map j) (P.relation i)) := by + classical + simp [basisDeriv] + +lemma linearIndependent_aeval_val_pderiv_relation : + LinearIndependent S (fun i j ↦ (aeval P.val) (pderiv (P.map j) (P.relation i))) := by + simp_rw [← SubmersivePresentation.basisDeriv_apply] + exact P.basisDeriv.linearIndependent + end SubmersivePresentation /-- From 7466910ec32964324f989f7c7bcb0a807a895417 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Thu, 9 Jan 2025 15:53:26 +0000 Subject: [PATCH 104/681] chore(Asymptotics/TVS): golf (#20596) `IsLittleOTVS.tendsto_inv_smul` using `isLittleOTVS_one`. --- Mathlib/Analysis/Asymptotics/TVS.lean | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/Mathlib/Analysis/Asymptotics/TVS.lean b/Mathlib/Analysis/Asymptotics/TVS.lean index 382c9bdb85964..ce294dcb4f385 100644 --- a/Mathlib/Analysis/Asymptotics/TVS.lean +++ b/Mathlib/Analysis/Asymptotics/TVS.lean @@ -151,28 +151,11 @@ lemma isLittleOTVS_one [ContinuousSMul 𝕜 E] {f : α → E} {l : Filter α} : lemma IsLittleOTVS.tendsto_inv_smul [ContinuousSMul 𝕜 E] {f : α → 𝕜} {g : α → E} {l : Filter α} (h : g =o[𝕜;l] f) : Tendsto (fun x ↦ (f x)⁻¹ • g x) l (𝓝 0) := by - rw [(basis_sets _).isLittleOTVS_iff nhds_basis_ball] at h - rw [(nhds_basis_balanced 𝕜 E).tendsto_right_iff] - rintro U ⟨hU, hUB⟩ - rcases h U hU with ⟨ε, hε₀, hε⟩ - lift ε to ℝ≥0 using hε₀.le; norm_cast at hε₀ - rcases NormedField.exists_one_lt_norm 𝕜 with ⟨c, hc⟩ - filter_upwards [hε (ε / 2 / ‖c‖₊) (ne_of_gt <| div_pos (half_pos hε₀) (one_pos.trans hc))] - with x hx - refine mem_of_egauge_lt_one hUB ?_ - rw [id, egauge_smul_right (fun _ ↦ Filter.nonempty_of_mem hU), nnnorm_inv] - calc - ↑‖f x‖₊⁻¹ * egauge 𝕜 U (g x) - ≤ (↑‖f x‖₊)⁻¹ * (↑(ε / 2 / ‖c‖₊) * egauge 𝕜 (ball 0 ε) (f x)) := - mul_le_mul' ENNReal.coe_inv_le hx - _ ≤ (↑‖f x‖₊)⁻¹ * ((ε / 2 / ‖c‖₊) * (‖c‖₊ * ‖f x‖₊ / ε)) := by - gcongr - · refine ENNReal.coe_div_le.trans ?_; gcongr; apply ENNReal.coe_div_le - · exact egauge_ball_le_of_one_lt_norm hc (.inl hε₀.ne') - _ = (‖f x‖₊ / ‖f x‖₊) * (ε / ε) * (‖c‖₊ / ‖c‖₊) * (1 / 2) := by - simp only [div_eq_mul_inv, one_mul]; ring - _ ≤ 1 * 1 * 1 * (1 / 2) := by gcongr <;> apply ENNReal.div_self_le_one - _ < 1 := by norm_num + rw [← isLittleOTVS_one (𝕜 := 𝕜)] + intro U hU + rcases h.smul_left f⁻¹ U hU with ⟨V, hV₀, hV⟩ + refine ⟨V, hV₀, fun ε hε ↦ (hV ε hε).mono fun x hx ↦ hx.trans ?_⟩ + by_cases hx₀ : f x = 0 <;> simp [hx₀, egauge_zero_right _ (Filter.nonempty_of_mem hV₀)] lemma isLittleOTVS_iff_tendsto_inv_smul [ContinuousSMul 𝕜 E] {f : α → 𝕜} {g : α → E} {l : Filter α} (h₀ : ∀ᶠ x in l, f x = 0 → g x = 0) : From efd3027baa9c0ae06c96e85ae0aa0d1e031994b9 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Thu, 9 Jan 2025 16:34:33 +0000 Subject: [PATCH 105/681] feat(Asymptotics): add `IsBigO.of_norm_eventuallyLE` (#20415) .. and `.of_norm_le`. Also use `of_bound'` instead of `of_bound 1`. --- Mathlib/Analysis/Analytic/Basic.lean | 6 ++---- Mathlib/Analysis/Analytic/RadiusLiminf.lean | 4 ++-- Mathlib/Analysis/Asymptotics/Asymptotics.lean | 16 +++++++++++---- .../Asymptotics/SuperpolynomialDecay.lean | 13 +++++------- Mathlib/Analysis/Asymptotics/Theta.lean | 15 +++++++++----- .../Analysis/Complex/PhragmenLindelof.lean | 20 +++++++++---------- .../Analysis/SpecialFunctions/CompareExp.lean | 5 ++--- .../SpecialFunctions/Pow/Asymptotics.lean | 20 +++++++++---------- Mathlib/Analysis/SpecificLimits/Normed.lean | 7 +++---- .../Extremal/RuzsaSzemeredi.lean | 7 +++---- 10 files changed, 59 insertions(+), 54 deletions(-) diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index b89802058d494..5ba72e13bc4f1 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -1134,10 +1134,8 @@ theorem HasFPowerSeriesWithinOnBall.isBigO_image_sub_image_sub_deriv_principal ((hasSum_geometric_of_norm_lt_one this).mul_left 2) exact hA.norm_le_of_bounded hBL hAB suffices L =O[𝓟 (EMetric.ball (x, x) r' ∩ ((insert x s) ×ˢ (insert x s)))] - fun y => ‖y - (x, x)‖ * ‖y.1 - y.2‖ by - refine (IsBigO.of_bound 1 (eventually_principal.2 fun y hy => ?_)).trans this - rw [one_mul] - exact (hL y hy).trans (le_abs_self _) + fun y => ‖y - (x, x)‖ * ‖y.1 - y.2‖ from + .trans (.of_norm_eventuallyLE (eventually_principal.2 hL)) this simp_rw [L, mul_right_comm _ (_ * _)] exact (isBigO_refl _ _).const_mul_left _ diff --git a/Mathlib/Analysis/Analytic/RadiusLiminf.lean b/Mathlib/Analysis/Analytic/RadiusLiminf.lean index 6aefcab0e900e..ee8c73c5c94e6 100644 --- a/Mathlib/Analysis/Analytic/RadiusLiminf.lean +++ b/Mathlib/Analysis/Analytic/RadiusLiminf.lean @@ -54,8 +54,8 @@ theorem radius_eq_liminf : H.mp ((eventually_gt_atTop 0).mono fun n hn₀ hn => (this _ hn₀).2 (NNReal.coe_le_coe.1 ?_)) push_cast exact (le_abs_self _).trans (hn.trans (pow_le_one₀ ha.1.le ha.2.le)) - · refine p.le_radius_of_isBigO (IsBigO.of_bound 1 ?_) - refine (eventually_lt_of_lt_liminf hr).mp ((eventually_gt_atTop 0).mono fun n hn₀ hn => ?_) + · refine p.le_radius_of_isBigO <| .of_norm_eventuallyLE ?_ + filter_upwards [eventually_lt_of_lt_liminf hr, eventually_gt_atTop 0] with n hn hn₀ simpa using NNReal.coe_le_coe.2 ((this _ hn₀).1 hn.le) end FormalMultilinearSeries diff --git a/Mathlib/Analysis/Asymptotics/Asymptotics.lean b/Mathlib/Analysis/Asymptotics/Asymptotics.lean index b38690a42c515..6585904d9c08b 100644 --- a/Mathlib/Analysis/Asymptotics/Asymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/Asymptotics.lean @@ -139,13 +139,19 @@ theorem IsBigO.of_bound (c : ℝ) (h : ∀ᶠ x in l, ‖f x‖ ≤ c * ‖g x isBigO_iff.2 ⟨c, h⟩ theorem IsBigO.of_bound' (h : ∀ᶠ x in l, ‖f x‖ ≤ ‖g x‖) : f =O[l] g := - IsBigO.of_bound 1 <| by - simp_rw [one_mul] - exact h + .of_bound 1 <| by simpa only [one_mul] using h theorem IsBigO.bound : f =O[l] g → ∃ c : ℝ, ∀ᶠ x in l, ‖f x‖ ≤ c * ‖g x‖ := isBigO_iff.1 +/-- See also `Filter.Eventually.isBigO`, which is the same lemma +stated using `Filter.Eventually` instead of `Filter.EventuallyLE`. -/ +theorem IsBigO.of_norm_eventuallyLE {g : α → ℝ} (h : (‖f ·‖) ≤ᶠ[l] g) : f =O[l] g := + .of_bound' <| h.mono fun _ h ↦ h.trans <| le_abs_self _ + +theorem IsBigO.of_norm_le {g : α → ℝ} (h : ∀ x, ‖f x‖ ≤ g x) : f =O[l] g := + .of_norm_eventuallyLE <| .of_forall h + /-- The Landau notation `f =o[l] g` where `f` and `g` are two functions on a type `α` and `l` is a filter on `α`, means that eventually for `l`, `‖f‖` is bounded by an arbitrarily small constant multiple of `‖g‖`. In other words, `‖f‖ / ‖g‖` tends to `0` along `l`, modulo division by zero @@ -482,9 +488,11 @@ theorem _root_.Filter.Eventually.trans_isBigO {f : α → E} {g : α → F'} {k (hfg : ∀ᶠ x in l, ‖f x‖ ≤ ‖g x‖) (hgk : g =O[l] k) : f =O[l] k := (IsBigO.of_bound' hfg).trans hgk +/-- See also `Asymptotics.IsBigO.of_norm_eventuallyLE`, which is the same lemma +stated using `Filter.EventuallyLE` instead of `Filter.Eventually`. -/ theorem _root_.Filter.Eventually.isBigO {f : α → E} {g : α → ℝ} {l : Filter α} (hfg : ∀ᶠ x in l, ‖f x‖ ≤ g x) : f =O[l] g := - IsBigO.of_bound' <| hfg.mono fun _x hx => hx.trans <| Real.le_norm_self _ + .of_norm_eventuallyLE hfg section diff --git a/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean b/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean index 857df80bfb27f..93000132bef6d 100644 --- a/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean +++ b/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean @@ -302,12 +302,9 @@ theorem superpolynomialDecay_iff_isBigO (hk : Tendsto k l atTop) : exact h (-z) · suffices (fun a : α => k a ^ z * f a) =O[l] fun a : α => (k a)⁻¹ from IsBigO.trans_tendsto this hk.inv_tendsto_atTop - refine - ((isBigO_refl (fun a => k a ^ z) l).mul (h (-(z + 1)))).trans - (IsBigO.of_bound 1 <| hk0.mono fun a ha0 => ?_) - simp only [one_mul, neg_add z 1, zpow_add₀ ha0, ← mul_assoc, zpow_neg, - mul_inv_cancel₀ (zpow_ne_zero z ha0), zpow_one] - rfl + refine ((isBigO_refl (fun a => k a ^ z) l).mul (h (-(z + 1)))).trans ?_ + refine .of_bound' <| hk0.mono fun a ha0 => ?_ + simp [← zpow_add₀ ha0] theorem superpolynomialDecay_iff_isLittleO (hk : Tendsto k l atTop) : SuperpolynomialDecay l k f ↔ ∀ z : ℤ, f =o[l] fun a : α => k a ^ z := by @@ -318,8 +315,8 @@ theorem superpolynomialDecay_iff_isLittleO (hk : Tendsto k l atTop) : (by simpa using hk.inv_tendsto_atTop) have : f =o[l] fun x : α => k x * k x ^ (z - 1) := by simpa using this.mul_isBigO ((superpolynomialDecay_iff_isBigO f hk).1 h <| z - 1) - refine this.trans_isBigO (IsBigO.of_bound 1 (hk0.mono fun x hkx => le_of_eq ?_)) - rw [one_mul, zpow_sub_one₀ hkx, mul_comm (k x), mul_assoc, inv_mul_cancel₀ hkx, mul_one] + refine this.trans_isBigO <| IsBigO.of_bound' <| hk0.mono fun x hkx => le_of_eq ?_ + simp [← zpow_one_add₀ hkx] end NormedLinearOrderedField diff --git a/Mathlib/Analysis/Asymptotics/Theta.lean b/Mathlib/Analysis/Asymptotics/Theta.lean index 2ec951024df70..9e460bf26ead9 100644 --- a/Mathlib/Analysis/Asymptotics/Theta.lean +++ b/Mathlib/Analysis/Asymptotics/Theta.lean @@ -144,12 +144,17 @@ alias ⟨IsTheta.of_norm_left, IsTheta.norm_left⟩ := isTheta_norm_left alias ⟨IsTheta.of_norm_right, IsTheta.norm_right⟩ := isTheta_norm_right -theorem isTheta_of_norm_eventuallyEq (h : (fun x ↦ ‖f x‖) =ᶠ[l] fun x ↦ ‖g x‖) : f =Θ[l] g := - ⟨IsBigO.of_bound 1 <| by simpa only [one_mul] using h.le, - IsBigO.of_bound 1 <| by simpa only [one_mul] using h.symm.le⟩ +theorem IsTheta.of_norm_eventuallyEq_norm (h : (fun x ↦ ‖f x‖) =ᶠ[l] fun x ↦ ‖g x‖) : f =Θ[l] g := + ⟨.of_bound' h.le, .of_bound' h.symm.le⟩ -theorem isTheta_of_norm_eventuallyEq' {g : α → ℝ} (h : (fun x ↦ ‖f' x‖) =ᶠ[l] g) : f' =Θ[l] g := - isTheta_of_norm_eventuallyEq <| h.mono fun x hx ↦ by simp only [← hx, norm_norm] +@[deprecated (since := "2025-01-03")] +alias isTheta_of_norm_eventuallyEq := IsTheta.of_norm_eventuallyEq_norm + +theorem IsTheta.of_norm_eventuallyEq {g : α → ℝ} (h : (fun x ↦ ‖f' x‖) =ᶠ[l] g) : f' =Θ[l] g := + of_norm_eventuallyEq_norm <| h.mono fun x hx ↦ by simp only [← hx, norm_norm] + +@[deprecated (since := "2025-01-03")] +alias isTheta_of_norm_eventuallyEq' := IsTheta.of_norm_eventuallyEq theorem IsTheta.isLittleO_congr_left (h : f' =Θ[l] g') : f' =o[l] k ↔ g' =o[l] k := ⟨h.symm.trans_isLittleO, h.trans_isLittleO⟩ diff --git a/Mathlib/Analysis/Complex/PhragmenLindelof.lean b/Mathlib/Analysis/Complex/PhragmenLindelof.lean index ca347d8adbcac..ee37b9bc62b36 100644 --- a/Mathlib/Analysis/Complex/PhragmenLindelof.lean +++ b/Mathlib/Analysis/Complex/PhragmenLindelof.lean @@ -79,9 +79,9 @@ theorem isBigO_sub_exp_rpow {a : ℝ} {f g : ℂ → E} {l : Filter ℂ} ∃ c < a, ∃ B, (f - g) =O[cobounded ℂ ⊓ l] fun z => expR (B * abs z ^ c) := by have : ∀ {c₁ c₂ B₁ B₂ : ℝ}, c₁ ≤ c₂ → 0 ≤ B₂ → B₁ ≤ B₂ → (fun z : ℂ => expR (B₁ * abs z ^ c₁)) =O[cobounded ℂ ⊓ l] - fun z => expR (B₂ * abs z ^ c₂) := fun hc hB₀ hB ↦ .of_bound 1 <| by + fun z => expR (B₂ * abs z ^ c₂) := fun hc hB₀ hB ↦ .of_norm_eventuallyLE <| by filter_upwards [(eventually_cobounded_le_norm 1).filter_mono inf_le_left] with z hz - simp only [one_mul, Real.norm_eq_abs, Real.abs_exp] + simp only [Real.norm_eq_abs, Real.abs_exp] gcongr; assumption rcases hBf with ⟨cf, hcf, Bf, hOf⟩; rcases hBg with ⟨cg, hcg, Bg, hOg⟩ refine ⟨max cf cg, max_lt hcf hcg, max 0 (max Bf Bg), ?_⟩ @@ -367,8 +367,8 @@ nonrec theorem quadrant_I (hd : DiffContOnCl ℂ f (Ioi 0 ×ℂ Ioi 0)) refine ⟨c, hc, max B 0, ?_⟩ rw [← comap_comap, comap_abs_atTop, comap_sup, inf_sup_right] -- We prove separately the estimates as `ζ.re → ∞` and as `ζ.re → -∞` - refine IsBigO.sup ?_ - ((hO.comp_tendsto <| tendsto_exp_comap_re_atTop.inf H.tendsto).trans <| .of_bound 1 ?_) + refine IsBigO.sup ?_ <| (hO.comp_tendsto <| tendsto_exp_comap_re_atTop.inf H.tendsto).trans <| + .of_norm_eventuallyLE ?_ · -- For the estimate as `ζ.re → -∞`, note that `f` is continuous within the first quadrant at -- zero, hence `f (exp ζ)` has a limit as `ζ.re → -∞`, `0 < ζ.im < π / 2`. have hc : ContinuousWithinAt f (Ioi 0 ×ℂ Ioi 0) 0 := by @@ -379,9 +379,9 @@ nonrec theorem quadrant_I (hd : DiffContOnCl ℂ f (Ioi 0 ×ℂ Ioi 0)) rw [norm_one, Real.norm_of_nonneg (Real.exp_pos _).le, Real.one_le_exp_iff] positivity · -- For the estimate as `ζ.re → ∞`, we reuse the upper estimate on `f` - simp only [eventually_inf_principal, eventually_comap, comp_apply, one_mul, + simp only [EventuallyLE, eventually_inf_principal, eventually_comap, comp_apply, one_mul, Real.norm_of_nonneg (Real.exp_pos _).le, abs_exp, ← Real.exp_mul, Real.exp_le_exp] - refine (eventually_ge_atTop 0).mono fun x hx z hz _ => ?_ + filter_upwards [eventually_ge_atTop 0] with x hx z hz _ rw [hz, _root_.abs_of_nonneg hx, mul_comm _ c] gcongr; apply le_max_left · -- If `ζ.im = 0`, then `Complex.exp ζ` is a positive real number @@ -732,9 +732,9 @@ theorem right_half_plane_of_bounded_on_real (hd : DiffContOnCl ℂ f {z | 0 < z. rw [norm_smul, norm_eq_abs, abs_exp, re_ofReal_mul] refine right_half_plane_of_tendsto_zero_on_real hd ?_ ?_ (fun y => ?_) hz · rcases hexp with ⟨c, hc, B, hO⟩ - refine ⟨c, hc, B, (IsBigO.of_bound 1 ?_).trans hO⟩ + refine ⟨c, hc, B, .trans (.of_bound' ?_) hO⟩ refine eventually_inf_principal.2 <| Eventually.of_forall fun z hz => ?_ - rw [hgn, one_mul] + rw [hgn] refine mul_le_of_le_one_left (norm_nonneg _) (Real.exp_le_one_iff.2 ?_) exact mul_nonpos_of_nonpos_of_nonneg ε₀.le (le_of_lt hz) · simp_rw [g, ← ofReal_mul, ← ofReal_exp, coe_smul] @@ -783,9 +783,9 @@ theorem eq_zero_on_right_half_plane_of_superexponential_decay (hd : DiffContOnCl · rcases hexp with ⟨c, hc, B, hO⟩ refine ⟨max c 1, max_lt hc one_lt_two, n + max B 0, .of_norm_left ?_⟩ simp only [hg] - refine ((isBigO_refl (fun z : ℂ => expR z.re ^ n) _).mul hO.norm_left).trans (.of_bound 1 ?_) + refine ((isBigO_refl (fun z : ℂ => expR z.re ^ n) _).mul hO.norm_left).trans (.of_bound' ?_) filter_upwards [(eventually_cobounded_le_norm 1).filter_mono inf_le_left] with z hz - simp only [← Real.exp_nat_mul, ← Real.exp_add, Real.norm_eq_abs, Real.abs_exp, add_mul, one_mul] + simp only [← Real.exp_nat_mul, ← Real.exp_add, Real.norm_eq_abs, Real.abs_exp, add_mul] gcongr · calc z.re ≤ abs z := re_le_abs _ diff --git a/Mathlib/Analysis/SpecialFunctions/CompareExp.lean b/Mathlib/Analysis/SpecialFunctions/CompareExp.lean index b025109d8a959..f50a2831cd0ed 100644 --- a/Mathlib/Analysis/SpecialFunctions/CompareExp.lean +++ b/Mathlib/Analysis/SpecialFunctions/CompareExp.lean @@ -112,13 +112,12 @@ This is the main lemma in the proof of `Complex.IsExpCmpFilter.isLittleO_cpow_ex theorem isLittleO_log_abs_re (hl : IsExpCmpFilter l) : (fun z => Real.log (abs z)) =o[l] re := calc (fun z => Real.log (abs z)) =O[l] fun z => Real.log (√2) + Real.log (max z.re |z.im|) := - IsBigO.of_bound 1 <| + .of_norm_eventuallyLE <| (hl.tendsto_re.eventually_ge_atTop 1).mono fun z hz => by have h2 : 0 < √2 := by simp have hz' : 1 ≤ abs z := hz.trans (re_le_abs z) have hm₀ : 0 < max z.re |z.im| := lt_max_iff.2 (Or.inl <| one_pos.trans_le hz) - rw [one_mul, Real.norm_eq_abs, _root_.abs_of_nonneg (Real.log_nonneg hz')] - refine le_trans ?_ (le_abs_self _) + simp only [Real.norm_of_nonneg (Real.log_nonneg hz')] rw [← Real.log_mul, Real.log_le_log_iff, ← _root_.abs_of_nonneg (le_trans zero_le_one hz)] exacts [abs_le_sqrt_two_mul_max z, one_pos.trans_le hz', mul_pos h2 hm₀, h2.ne', hm₀.ne'] _ =o[l] re := diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean index e6339d7d7c234..3f46d4370db46 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean @@ -207,11 +207,11 @@ theorem isTheta_cpow_rpow (hl_im : IsBoundedUnder (· ≤ ·) l fun x => |(g x). (fun x => f x ^ g x) =Θ[l] fun x => abs (f x) ^ (g x).re := calc (fun x => f x ^ g x) =Θ[l] - (show α → ℝ from fun x => abs (f x) ^ (g x).re / Real.exp (arg (f x) * im (g x))) := - isTheta_of_norm_eventuallyEq' <| hl.mono fun _ => abs_cpow_of_imp - _ =Θ[l] (show α → ℝ from fun x => abs (f x) ^ (g x).re / (1 : ℝ)) := - ((isTheta_refl _ _).div (isTheta_exp_arg_mul_im hl_im)) - _ =ᶠ[l] (show α → ℝ from fun x => abs (f x) ^ (g x).re) := by + (fun x => abs (f x) ^ (g x).re / Real.exp (arg (f x) * im (g x))) := + .of_norm_eventuallyEq <| hl.mono fun _ => abs_cpow_of_imp + _ =Θ[l] fun x => abs (f x) ^ (g x).re / (1 : ℝ) := + (isTheta_refl _ _).div (isTheta_exp_arg_mul_im hl_im) + _ =ᶠ[l] (fun x => abs (f x) ^ (g x).re) := by simp only [ofReal_one, div_one] rfl @@ -322,11 +322,11 @@ theorem isLittleO_log_rpow_rpow_atTop {s : ℝ} (r : ℝ) (hs : 0 < s) : have H : 0 < s / r' := div_pos hs hr calc (fun x => log x ^ r) =O[atTop] fun x => log x ^ r' := - IsBigO.of_bound 1 <| - (tendsto_log_atTop.eventually_ge_atTop 1).mono fun x hx => by - have hx₀ : 0 ≤ log x := zero_le_one.trans hx - simp [r', norm_eq_abs, abs_rpow_of_nonneg, abs_rpow_of_nonneg hx₀, - rpow_le_rpow_of_exponent_le (hx.trans (le_abs_self _))] + .of_norm_eventuallyLE <| by + filter_upwards [tendsto_log_atTop.eventually_ge_atTop 1] with x hx + rw [Real.norm_of_nonneg (by positivity)] + gcongr + exacts [hx, le_max_left _ _] _ =o[atTop] fun x => (x ^ (s / r')) ^ r' := ((isLittleO_log_rpow_atTop H).rpow hr <| (_root_.tendsto_rpow_atTop H).eventually <| eventually_ge_atTop 0) diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index cf5f9286f5bd2..53ca89f99b3f6 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -107,9 +107,8 @@ theorem TFAE_exists_lt_isLittleO_pow (f : ℕ → ℝ) (R : ℝ) : tfae_have 8 → 7 := fun ⟨a, ha, H⟩ ↦ ⟨a, ha.2, H⟩ tfae_have 7 → 3 | ⟨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] + refine ⟨a, A ⟨?_, ha⟩, .of_norm_eventuallyLE H⟩ + exact nonneg_of_eventually_pow_nonneg (H.mono fun n ↦ (abs_nonneg _).trans) tfae_finish /-- For any natural `k` and a real `r > 1` we have `n ^ k = o(r ^ n)` as `n → ∞`. -/ @@ -147,7 +146,7 @@ theorem isLittleO_pow_const_mul_const_pow_const_pow_of_norm_lt {R : Type*} [Norm 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', div_pow] using A.mul_isBigO this - exact IsBigO.of_bound 1 (by simpa using eventually_norm_pow_le r₁) + exact .of_norm_eventuallyLE <| eventually_norm_pow_le r₁ theorem tendsto_pow_const_div_const_pow_of_one_lt (k : ℕ) {r : ℝ} (hr : 1 < r) : Tendsto (fun n ↦ (n : ℝ) ^ k / r ^ n : ℕ → ℝ) atTop (𝓝 0) := diff --git a/Mathlib/Combinatorics/Extremal/RuzsaSzemeredi.lean b/Mathlib/Combinatorics/Extremal/RuzsaSzemeredi.lean index 59c4a36c6596f..b17f740b7900b 100644 --- a/Mathlib/Combinatorics/Extremal/RuzsaSzemeredi.lean +++ b/Mathlib/Combinatorics/Extremal/RuzsaSzemeredi.lean @@ -262,8 +262,7 @@ theorem ruzsaSzemerediNumberNat_asymptotic_lower_bound : · simp omega · omega - · refine .of_bound 1 ?_ - simp only [neg_mul, norm_eq_abs, norm_natCast, one_mul, eventually_atTop] - refine ⟨6, fun n hn ↦ ?_⟩ + · refine .of_norm_eventuallyLE ?_ + filter_upwards [eventually_ge_atTop 6] with n hn have : (0 : ℝ) ≤ n / 3 - 2 := by rify at hn; linarith - simpa using abs_le_abs_of_nonneg (by positivity) (ruzsaSzemerediNumberNat_lower_bound n) + simpa [neg_mul, abs_mul, abs_of_nonneg this] using ruzsaSzemerediNumberNat_lower_bound n From 6b7dfde272b808a3363af938e6bcee25dbe87487 Mon Sep 17 00:00:00 2001 From: grunweg Date: Thu, 9 Jan 2025 16:34:34 +0000 Subject: [PATCH 106/681] doc(Cache): add resp. tweak some documentation (#20606) - document two definitions - fix description of `get-` - mention `get-`, which also takes arguments Split from #20568. --- Cache/Main.lean | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Cache/Main.lean b/Cache/Main.lean index 06d2200b8865a..8b1d53a74c24d 100644 --- a/Cache/Main.lean +++ b/Cache/Main.lean @@ -13,7 +13,7 @@ Commands: # No privilege required get [ARGS] Download linked files missing on the local cache and decompress get! [ARGS] Download all linked files and decompress - get- [ARGS] Download linked files missing to the local cache, but do no compress + get- [ARGS] Download linked files missing to the local cache, but do not decompress pack Compress non-compressed build files into the local cache pack! Compress build files into the local cache (no skipping) unpack Decompress linked already downloaded files @@ -33,9 +33,9 @@ Commands: * Linked files refer to local cache files with corresponding Lean sources * Commands ending with '!' should be used manually, when hot-fixes are needed -# The arguments for 'get' and 'get!' +# The arguments for 'get', 'get!' and 'get-' -'get' and 'get!' can process list of paths, allowing the user to be more +'get', 'get!' and 'get-' can process a list of paths, allowing the user to be more specific about what should be downloaded. For example, with automatic glob expansion in shell, one can call: @@ -57,9 +57,11 @@ def toPaths (args : List String) : List FilePath := else mkFilePath (arg.toName.components.map Name.toString) |>.withExtension "lean" +/-- Commands which (potentially) call `curl` for downloading files -/ def curlArgs : List String := ["get", "get!", "get-", "put", "put!", "put-unpacked", "commit", "commit!"] +/-- Commands which (potentially) call `leantar` for decompressing downloaded files -/ def leanTarArgs : List String := ["get", "get!", "pack", "pack!", "unpack", "lookup"] From ae534e116d3527d1027af3ee480e6ff0bcc1f26d Mon Sep 17 00:00:00 2001 From: Artie Khovanov Date: Thu, 9 Jan 2025 16:34:35 +0000 Subject: [PATCH 107/681] chore(Algebra): add missing simp lemmas (#20610) * Tag some `*.closure_eq` lemmas as `simp`. Previously, these lemmas were tagged `simp` for some substructures but not others. --- Mathlib/Algebra/Field/Subfield/Basic.lean | 1 + Mathlib/Algebra/Ring/Subring/Basic.lean | 1 + Mathlib/Algebra/Ring/Subsemiring/Basic.lean | 1 + Mathlib/RingTheory/NonUnitalSubring/Basic.lean | 1 + Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean | 1 + 5 files changed, 5 insertions(+) diff --git a/Mathlib/Algebra/Field/Subfield/Basic.lean b/Mathlib/Algebra/Field/Subfield/Basic.lean index 099c6b0a8315d..f3fc41e161165 100644 --- a/Mathlib/Algebra/Field/Subfield/Basic.lean +++ b/Mathlib/Algebra/Field/Subfield/Basic.lean @@ -356,6 +356,7 @@ protected def gi : GaloisInsertion (@closure K _) (↑) where variable {K} /-- Closure of a subfield `S` equals `S`. -/ +@[simp] theorem closure_eq (s : Subfield K) : closure (s : Set K) = s := (Subfield.gi K).l_u_eq s diff --git a/Mathlib/Algebra/Ring/Subring/Basic.lean b/Mathlib/Algebra/Ring/Subring/Basic.lean index d81eb33fca30f..6e38a46a7b4a4 100644 --- a/Mathlib/Algebra/Ring/Subring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subring/Basic.lean @@ -606,6 +606,7 @@ protected def gi : GaloisInsertion (@closure R _) (↑) where variable {R} /-- Closure of a subring `S` equals `S`. -/ +@[simp] theorem closure_eq (s : Subring R) : closure (s : Set R) = s := (Subring.gi R).l_u_eq s diff --git a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean index db80142d9f7af..1043fb029fe82 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean @@ -528,6 +528,7 @@ protected def gi : GaloisInsertion (@closure R _) (↑) where variable {R} /-- Closure of a subsemiring `S` equals `S`. -/ +@[simp] theorem closure_eq (s : Subsemiring R) : closure (s : Set R) = s := (Subsemiring.gi R).l_u_eq s diff --git a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean index e09499939d3a0..35474da03eabb 100644 --- a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean @@ -515,6 +515,7 @@ protected def gi : GaloisInsertion (@closure R _) SetLike.coe where variable {R} /-- Closure of a `NonUnitalSubring` `S` equals `S`. -/ +@[simp] theorem closure_eq (s : NonUnitalSubring R) : closure (s : Set R) = s := (NonUnitalSubring.gi R).l_u_eq s diff --git a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean index a9859dcb69aec..61c5c358fc66c 100644 --- a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean @@ -477,6 +477,7 @@ variable [NonUnitalNonAssocSemiring S] variable {F : Type*} [FunLike F R S] [NonUnitalRingHomClass F R S] /-- Closure of a non-unital subsemiring `S` equals `S`. -/ +@[simp] theorem closure_eq (s : NonUnitalSubsemiring R) : closure (s : Set R) = s := (NonUnitalSubsemiring.gi R).l_u_eq s From 425a48954db36c563621ba3bc2199ca493e66e2c Mon Sep 17 00:00:00 2001 From: grunweg Date: Thu, 9 Jan 2025 17:21:40 +0000 Subject: [PATCH 108/681] chore(1000.yaml): re-enable comments, add more entries (#20554) Co-authored-by: Michael Rothgang Co-authored-by: grunweg --- docs/1000.yaml | 74 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/docs/1000.yaml b/docs/1000.yaml index 8261bce58958b..6fbfe1d7a786a 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -110,9 +110,10 @@ Q188745: Q189136: title: Mean value theorem - decl: exists_deriv_eq_slope - # XXX: other branch found exists_ratio_deriv_eq_ratio_slope, - # is about Cauchy's vs Lagrange's Mean Value Theorem, TODO decide! + # two versions: Cauchy's vs Lagrange's mean value theorem; the wikipedia article mentions both + decls: + - exists_deriv_eq_slope + - exists_ratio_deriv_eq_ratio_slope author: Yury G. Kudryashov date: 2019 @@ -248,9 +249,9 @@ Q248931: Q253214: title: Heine–Borel theorem - # TODO: two versions in mathlib, which one do we want? - # decl: Metric.isCompact_iff_isClosed_bounded - # decl: FiniteDimensional.proper + decls: + - Metric.isCompact_iff_isClosed_bounded + - FiniteDimensional.proper Q255996: title: Equipartition theorem @@ -311,7 +312,7 @@ Q288465: Q303402: title: Rank–nullity theorem - # TODO: this is also in mathlib, TODO add decl (and mention in overview) + decl: LinearMap.rank_range_add_rank_ker Q318767: title: Abel's theorem @@ -767,7 +768,7 @@ Q764287: Q765987: title: Heine–Cantor theorem - # XXX: does mathlib have this? + decl: CompactSpace.uniformContinuous_of_continuous Q766722: title: Liouville's theorem @@ -824,6 +825,9 @@ Q834211: Q837506: title: Theorem on friends and strangers + author: Bhavik Mehta + url: https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/Small.20Ramsey.20numbers/near/490303695 + comment: "will enter mathlib in 2024" Q837551: title: Frobenius theorem @@ -1033,7 +1037,7 @@ Q966837: Q967972: title: Open mapping theorem - # result in complex analysis. TODO does mathlib have this? + decl: AnalyticOnNhd.is_constant_or_isOpen Q973359: title: Rado's theorem @@ -1085,7 +1089,7 @@ Q1037559: Q1038716: title: Identity theorem - # complex analysis, holomorphic functions: TODO add decl! + decl: AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq Q1046232: title: Szemerédi's theorem @@ -1169,7 +1173,9 @@ Q1067156: Q1067156X: title: Bounded convergence theorem - # TODO: is this in mathlib already? + decls: + - MeasureTheory.FiniteMeasure.tendsto_lintegral_nn_of_le_const + - MeasureTheory.tendsto_lintegral_nn_filter_of_le_const Q1068085: title: Closed graph theorem @@ -1291,7 +1297,7 @@ Q1144897: title: Brouwer fixed-point theorem author: Brendan Seamas Murphy url: https://github.com/Shamrock-Frost/BrouwerFixedPoint/blob/master/src/brouwer_fixed_point.lean - note: "in Lean 3" + comment: "in Lean 3" Q1146791: title: Fermat polygonal number theorem @@ -1325,9 +1331,9 @@ Q1153441: Q1153584: title: Monotone convergence theorem - # TODO: many versions in mathlib, choose one - # e.g. integral_tendsto_of_tendsto_of_antitone (Bochner integral) - # or lintegral_tendsto_of_tendsto_of_monotone (Lebesgue integral) + decls: + - MeasureTheory.integral_tendsto_of_tendsto_of_antitone + - MeasureTheory.lintegral_tendsto_of_tendsto_of_monotone Q1166774: title: Stone's representation theorem for Boolean algebras @@ -1350,6 +1356,8 @@ Q1186808: Q1187646: title: Fundamental theorem on homomorphisms + # a.k.a. first isomorphism theorem + decl: QuotientGroup.quotientKerEquivRange Q1188048: title: Barbier's theorem @@ -1376,7 +1384,7 @@ Q1191862: Q1194053: title: Metrization theorems decl: TopologicalSpace.metrizableSpace_of_t3_secondCountable - # comment: "Urysohn's metrization theorem (only)" + comment: "Urysohn's metrization theorem (only)" Q1196538: title: Descartes's theorem @@ -1434,7 +1442,7 @@ Q1306092: Q1306095: title: Whitney embedding theorem decl: exists_embedding_euclidean_of_compact - # comment: "baby version: for compact manifolds; embedding into some *n*" + comment: "baby version: for compact manifolds; embedding into some *n*" Q1307676: title: Künneth theorem @@ -1727,18 +1735,22 @@ Q1809539: Q1816952: title: Schur's lemma + decl: CategoryTheory.finrank_endomorphism_simple_eq_one Q1841237: title: Fubini's theorem on differentiation + # XXX: does mathib have this already? Q1855610: title: Theorem of de Moivre–Laplace + # special case of the central limit theorem: binomial converges to the normal distribution Q1888583: title: Holditch's theorem Q1893717: title: Rice's theorem + decl: ComputablePred.rice Q1896455: title: Varignon's theorem @@ -1778,6 +1790,7 @@ Q1995468: Q1996305: title: Burnside's theorem + # an external project proved part of this: TODO mention in this comment Q2000090: title: Art gallery theorem @@ -1821,6 +1834,7 @@ Q2094241: Q2096184: title: Plancherel theorem + # also in undergrad.yml Q2109761: title: Uniformization theorem @@ -1981,6 +1995,7 @@ Q2379128: Q2379132: title: Going-up and going-down theorems + # TODO: does mathlib have these versions? add the right decls! Q2394548: title: Hurewicz theorem @@ -1999,6 +2014,7 @@ Q2449984X: Q2471737: title: Carathéodory's theorem + decl: convexHull_eq_union Q2473965: title: Ugly duckling theorem @@ -2259,6 +2275,7 @@ Q3527113: Q3527118: title: Mahler's theorem + decl: PadicInt.hasSum_mahler Q3527125: title: Monsky's theorem @@ -2274,9 +2291,11 @@ Q3527155: Q3527162: title: Sophie Germain's theorem + # special case of FLT, including all primes less than 100 Q3527166: title: Steinhaus theorem + # not difficult, but seemingly missing Q3527171: title: Synge's theorem @@ -2286,12 +2305,15 @@ Q3527185: Q3527189: title: Lattice theorem + # a.k.a. third or fourth isomorphism theorem + decl: QuotientGroup.quotientQuotientEquivQuotient Q3527196: title: Principal ideal theorem Q3527205: title: Dimension theorem for vector spaces + decl: mk_eq_mk_of_basis Q3527209: title: Hasse norm theorem @@ -2361,6 +2383,7 @@ Q3699212: Q3711848: title: Sobolev embedding theorem + # partial progress: Sobolev inequality MeasureTheory.eLpNorm_le_eLpNorm_fderiv_of_eq Q3757563: title: Intercept theorem @@ -2460,6 +2483,7 @@ Q4454973: Q4454976: title: Liouville's theorem + # theorem in conformal mappings Q4454989: title: Meusnier's theorem @@ -2904,6 +2928,8 @@ Q5436274: Q5437947: title: Fatou–Lebesgue theorem + # essentially Fatou's lemma in measure theory: let's count that as well + decl: MeasureTheory.lintegral_liminf_le Q5438320: title: Faustman–Ohlin theorem @@ -3134,6 +3160,7 @@ Q6402928: Q6403282: title: Lagrange's theorem + # number theory Q6407842: title: Killing–Hopf theorem @@ -3149,6 +3176,7 @@ Q6425088: Q6436753: title: Krener's theorem + # differential equations Q6442276: title: Kuiper's theorem @@ -3233,6 +3261,10 @@ Q6749789: Q6757284: title: Marcinkiewicz theorem + author: Jim Portegies + date: 2024-09-06 + url: https://github.com/fpvandoorn/carleson/blob/master/Carleson/RealInterpolation.lean + # will become part of mathlib; update URL in this case! Q6760432: title: Marginal value theorem @@ -3260,6 +3292,7 @@ Q6799039: Q6813106: title: Mellin inversion theorem + decl: mellin_inversion Q6859627: title: Milliken's tree theorem @@ -3425,6 +3458,8 @@ Q7308146: Q7309601: title: Whitney–Graustein Theorem + # there's an external project, deducing this from sphere-eversion + # TODO link statement (proof depends on some sorries about the winding number) Q7310041: title: Reider's theorem @@ -3437,6 +3472,7 @@ Q7318284: Q7322366: title: Ribet's theorem + # part of FLT, right? Q7323144: title: Rice–Shapiro theorem @@ -3470,6 +3506,7 @@ Q7432872: Q7432915: title: Schroeder–Bernstein theorem for measurable spaces + decl: MeasurableEmbedding.schroederBernstein Q7432918: title: Schröder–Bernstein theorems for operator algebras @@ -3602,7 +3639,7 @@ Q7818977: Q7820874: title: Tonelli's theorem - # TODO: this is on mathlib, right? + decl: MeasureTheory.lintegral_prod Q7824894: title: Topkis's theorem @@ -3715,6 +3752,7 @@ Q8081891: Q9993851: title: Lax–Milgram theorem + decl: IsCoercive.continuousLinearEquivOfBilin Q10369454: title: Noether's second theorem From 21543954f831a3d22a18ef13783b195f253e28b3 Mon Sep 17 00:00:00 2001 From: tukamilano Date: Thu, 9 Jan 2025 18:51:50 +0000 Subject: [PATCH 109/681] feat: independence formula(finite product case) (#20437) feat: independence formula(finite product case) Authored-by: Yuma Mizuno [mizuno.y.aj@gmail.com](mailto:mizuno.y.aj@gmail.com) Co-authored-by: tukamilano <107251402+tukamilano@users.noreply.github.com> --- Mathlib/Probability/Integration.lean | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Mathlib/Probability/Integration.lean b/Mathlib/Probability/Integration.lean index d1ed88afed840..77a6aa46b89e1 100644 --- a/Mathlib/Probability/Integration.lean +++ b/Mathlib/Probability/Integration.lean @@ -127,6 +127,28 @@ theorem lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun'' (h_meas_f : AEMea ∫⁻ ω, f ω * g ω ∂μ = (∫⁻ ω, f ω ∂μ) * ∫⁻ ω, g ω ∂μ := lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun' h_meas_f h_meas_g h_indep_fun +theorem lintegral_prod_eq_prod_lintegral_of_indepFun {ι : Type*} [DecidableEq ι] + (s : Finset ι) (X : ι → Ω → ℝ≥0∞) + (hX : iIndepFun (fun _ ↦ ENNReal.measurableSpace) X μ) + (x_mea : ∀ i, Measurable (X i)) : + ∫⁻ ω, ∏ i ∈ s, (X i ω) ∂μ = ∏ i ∈ s, ∫⁻ ω, X i ω ∂μ := by + have : IsProbabilityMeasure μ := hX.isProbabilityMeasure + induction s using Finset.induction + case empty => simp only [Finset.prod_empty, lintegral_const, measure_univ, mul_one] + case insert _ j s hj v => + calc ∫⁻ (ω : Ω), ∏ i ∈ insert j s, X i ω ∂μ + _ = ∫⁻ (ω : Ω), (∏ i ∈ insert j s, X i) ω ∂μ := by simp only [Finset.prod_apply] + _ = ∫⁻ (ω : Ω), (X j * ∏ i ∈ s, X i) ω ∂μ := + lintegral_congr fun ω ↦ congrFun (Finset.prod_insert hj) ω + _ = (∫⁻ ω, X j ω ∂μ) * ∫⁻ ω, (∏ i ∈ s, X i) ω ∂μ := by + apply lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun' + · exact (x_mea j).aemeasurable + · exact s.aemeasurable_prod' (fun i _ ↦ (x_mea i).aemeasurable) + · exact (iIndepFun.indepFun_finset_prod_of_not_mem hX (fun i ↦ x_mea i) hj).symm + _ = ∏ i' ∈ insert j s, ∫⁻ ω, X i' ω ∂μ := by + simp only [Finset.prod_apply] + rw [v, Finset.prod_insert hj] + /-- The product of two independent, integrable, real-valued random variables is integrable. -/ theorem IndepFun.integrable_mul {β : Type*} [MeasurableSpace β] {X Y : Ω → β} [NormedDivisionRing β] [BorelSpace β] (hXY : IndepFun X Y μ) (hX : Integrable X μ) From 921866e6217e1eb22ae62d51daf4a7d8fd4b54fd Mon Sep 17 00:00:00 2001 From: Bryan Gin-ge Chen Date: Thu, 9 Jan 2025 19:05:33 +0000 Subject: [PATCH 110/681] fix(scripts/yaml_check.py): more consistent error handling (#20614) Invalid fields in the 100.yaml and 1000.yaml files are slipping through CI at the moment, see e.g. [this log](https://github.com/leanprover-community/mathlib4/actions/runs/12690334474/job/35370960547#step:19:8). After this commit, all errors detected by `yaml_check.py` print a message and increment the `errors` variable, only failing at the end of the script (so that all entries can get checked). --- scripts/yaml_check.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/yaml_check.py b/scripts/yaml_check.py index bf31ad0b0ecda..5cf9cb9e00a06 100644 --- a/scripts/yaml_check.py +++ b/scripts/yaml_check.py @@ -110,6 +110,7 @@ class ThousandPlusTheorem: _thm = HundredTheorem(index, **entry) except TypeError as e: print(f"error: entry for theorem {index} is invalid: {e}") + errors += 1 # Also verify that the |decl| and |decls| fields are not *both* provided. if _thm.decl and _thm.decls: print(f"warning: entry for theorem {index} has both a decl and a decls field; " @@ -121,7 +122,8 @@ class ThousandPlusTheorem: hundred_decls.append((f'{index} {title}', entry['decl'])) elif 'decls' in entry: if not isinstance(entry['decls'], list): - raise ValueError(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") + print(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") + errors += 1 hundred_decls = hundred_decls + [(f'{index} {title}', d) for d in entry['decls']] thousand_decls: List[Tuple[str, str]] = [] @@ -131,6 +133,7 @@ class ThousandPlusTheorem: _thm = ThousandPlusTheorem(index, **entry) except TypeError as e: print(f"error: entry for theorem {index} is invalid: {e}") + errors += 1 # Also verify that the |decl| and |decls| fields are not *both* provided. if _thm.decl and _thm.decls: print(f"warning: entry for theorem {index} has both a decl and a decls field; " @@ -142,7 +145,8 @@ class ThousandPlusTheorem: thousand_decls.append((f'{index} {title}', entry['decl'])) elif 'decls' in entry: if not isinstance(entry['decls'], list): - raise ValueError(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") + print(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") + errors += 1 thousand_decls = thousand_decls + [(f'{index} {title}', d) for d in entry['decls']] overview_decls = tiered_extract(overview) @@ -163,4 +167,5 @@ class ThousandPlusTheorem: json.dump(undergrad_decls, f) if errors: - sys.exit(errors) + # Return an error code of at most 125 so this return value can be used further in shell scripts. + sys.exit(min(errors, 125)) From b85c65bbc770534ca8ae258dd2245a90b866d2dd Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 9 Jan 2025 23:52:41 +0000 Subject: [PATCH 111/681] chore: clean up some `erw` in cyclotomic polynomials (#20597) --- .../Polynomial/Cyclotomic/Basic.lean | 4 ++++ .../Polynomial/Cyclotomic/Eval.lean | 21 +++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean index 179f1fea4b15a..198c98c81527b 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Basic.lean @@ -267,6 +267,10 @@ theorem cyclotomic.eval_apply {R S : Type*} (q : R) (n : ℕ) [Ring R] [Ring S] eval (f q) (cyclotomic n S) = f (eval q (cyclotomic n R)) := by rw [← map_cyclotomic n f, eval_map, eval₂_at_apply] +@[simp] theorem cyclotomic.eval_apply_ofReal (q : ℝ) (n : ℕ) : + eval (q : ℂ) (cyclotomic n ℂ) = (eval q (cyclotomic n ℝ)) := + cyclotomic.eval_apply q n (algebraMap ℝ ℂ) + /-- The zeroth cyclotomic polyomial is `1`. -/ @[simp] theorem cyclotomic_zero (R : Type*) [Ring R] : cyclotomic 0 R = 1 := by diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean index 4729d0aab257a..979fe9e87f584 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean @@ -181,17 +181,15 @@ theorem sub_one_pow_totient_lt_cyclotomic_eval {n : ℕ} {q : ℝ} (hn' : 2 ≤ clear_value ζ rintro rfl linarith [hζ.unique IsPrimitiveRoot.one] - have : ¬eval (↑q) (cyclotomic n ℂ) = 0 := by - erw [cyclotomic.eval_apply q n (algebraMap ℝ ℂ)] - simpa only [Complex.coe_algebraMap, Complex.ofReal_eq_zero] using (cyclotomic_pos' n hq').ne' + have : ¬eval (↑q) (cyclotomic n ℂ) = 0 := by simpa using (cyclotomic_pos' n hq').ne' suffices Units.mk0 (Real.toNNReal (q - 1)) (by simp [hq']) ^ totient n < - Units.mk0 ‖(cyclotomic n ℂ).eval ↑q‖₊ (by simp [this]) by - simp only [← Units.val_lt_val, Units.val_pow_eq_pow_val, Units.val_mk0, ← NNReal.coe_lt_coe, + Units.mk0 ‖(cyclotomic n ℂ).eval ↑q‖₊ (by simp_all) by + simp [← Units.val_lt_val, Units.val_pow_eq_pow_val, Units.val_mk0, ← NNReal.coe_lt_coe, hq'.le, Real.toNNReal_lt_toNNReal_iff_of_nonneg, coe_nnnorm, Complex.norm_eq_abs, NNReal.coe_pow, Real.coe_toNNReal', max_eq_left, sub_nonneg] at this convert this - erw [cyclotomic.eval_apply q n (algebraMap ℝ ℂ), eq_comm] - simp only [cyclotomic_nonneg n hq'.le, Complex.coe_algebraMap, Complex.abs_ofReal, abs_eq_self] + rw [eq_comm] + simp [cyclotomic_nonneg n hq'.le] simp only [cyclotomic_eq_prod_X_sub_primitiveRoots hζ, eval_prod, eval_C, eval_X, eval_sub, nnnorm_prod, Units.mk0_prod] convert Finset.prod_lt_prod' (M := NNRealˣ) _ _ @@ -248,17 +246,14 @@ theorem cyclotomic_eval_lt_add_one_pow_totient {n : ℕ} {q : ℝ} (hn' : 3 ≤ linarith [hζ.unique <| IsPrimitiveRoot.neg_one 0 two_ne_zero.symm] · contrapose! hζ₀ apply Complex.ext <;> simp [hζ₀, h.2] - have : ¬eval (↑q) (cyclotomic n ℂ) = 0 := by - erw [cyclotomic.eval_apply q n (algebraMap ℝ ℂ)] - simp only [Complex.coe_algebraMap, Complex.ofReal_eq_zero] - exact (cyclotomic_pos' n hq').ne.symm - suffices Units.mk0 ‖(cyclotomic n ℂ).eval ↑q‖₊ (by simp [this]) < + have : ¬eval (↑q) (cyclotomic n ℂ) = 0 := by simpa using (cyclotomic_pos' n hq').ne.symm + suffices Units.mk0 ‖(cyclotomic n ℂ).eval ↑q‖₊ (by simp_all) < Units.mk0 (Real.toNNReal (q + 1)) (by simp; linarith) ^ totient n by simp only [← Units.val_lt_val, Units.val_pow_eq_pow_val, Units.val_mk0, ← NNReal.coe_lt_coe, hq'.le, Real.toNNReal_lt_toNNReal_iff_of_nonneg, coe_nnnorm, Complex.norm_eq_abs, NNReal.coe_pow, Real.coe_toNNReal', max_eq_left, sub_nonneg] at this convert this using 2 - · erw [cyclotomic.eval_apply q n (algebraMap ℝ ℂ), eq_comm] + · rw [eq_comm] simp [cyclotomic_nonneg n hq'.le] rw [eq_comm, max_eq_left_iff] linarith From 66b1e307fa9d40d9a0168376965ead6d5c250fb9 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 10 Jan 2025 00:02:55 +0000 Subject: [PATCH 112/681] chore: ext lemma for DirectSum (#20600) --- Mathlib/Algebra/DirectSum/Basic.lean | 3 +++ Mathlib/Algebra/DirectSum/Module.lean | 10 ++++--- Mathlib/Algebra/DirectSum/Ring.lean | 2 +- Mathlib/Algebra/Lie/DirectSum.lean | 26 +++++++++---------- .../AdicCompletion/Functoriality.lean | 4 +-- Mathlib/RingTheory/Flat/Basic.lean | 2 +- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Mathlib/Algebra/DirectSum/Basic.lean b/Mathlib/Algebra/DirectSum/Basic.lean index 83ed3a6e295fa..6863ccf291b4c 100644 --- a/Mathlib/Algebra/DirectSum/Basic.lean +++ b/Mathlib/Algebra/DirectSum/Basic.lean @@ -90,6 +90,9 @@ end AddCommGroup variable [∀ i, AddCommMonoid (β i)] +@[ext] theorem ext {x y : DirectSum ι β} (w : ∀ i, x i = y i) : x = y := + DFunLike.ext _ _ w + @[simp] theorem zero_apply (i : ι) : (0 : ⨁ i, β i) i = 0 := rfl diff --git a/Mathlib/Algebra/DirectSum/Module.lean b/Mathlib/Algebra/DirectSum/Module.lean index 73ae9c2eaa56f..d3db374ddf730 100644 --- a/Mathlib/Algebra/DirectSum/Module.lean +++ b/Mathlib/Algebra/DirectSum/Module.lean @@ -182,12 +182,14 @@ variable {ι M} theorem apply_eq_component (f : ⨁ i, M i) (i : ι) : f i = component R ι M i f := rfl -- Note(kmill): `@[ext]` cannot prove `ext_iff` because `R` is not determined by `f` or `g`. -@[ext (iff := false)] -theorem ext {f g : ⨁ i, M i} (h : ∀ i, component R ι M i f = component R ι M i g) : f = g := +-- This is not useful as an `@[ext]` lemma as the `ext` tactic can not infer `R`. +theorem ext_component {f g : ⨁ i, M i} (h : ∀ i, component R ι M i f = component R ι M i g) : + f = g := DFinsupp.ext h -theorem ext_iff {f g : ⨁ i, M i} : f = g ↔ ∀ i, component R ι M i f = component R ι M i g := - ⟨fun h _ ↦ by rw [h], ext R⟩ +theorem ext_component_iff {f g : ⨁ i, M i} : + f = g ↔ ∀ i, component R ι M i f = component R ι M i g := + ⟨fun h _ ↦ by rw [h], ext_component R⟩ @[simp] theorem lof_apply [DecidableEq ι] (i : ι) (b : M i) : ((lof R ι M i) b) i = b := diff --git a/Mathlib/Algebra/DirectSum/Ring.lean b/Mathlib/Algebra/DirectSum/Ring.lean index 1ad1ff8412c36..d49fefb87d54a 100644 --- a/Mathlib/Algebra/DirectSum/Ring.lean +++ b/Mathlib/Algebra/DirectSum/Ring.lean @@ -235,7 +235,7 @@ private theorem mul_assoc (a b c : ⨁ i, A i) : a * b * c = a * (b * c) := by simpa only [coe_comp, Function.comp_apply, AddMonoidHom.compHom_apply_apply, flip_apply, AddMonoidHom.flipHom_apply] using DFunLike.congr_fun (DFunLike.congr_fun (DFunLike.congr_fun this a) b) c - ext ai ax bi bx ci cx + ext ai ax bi bx ci cx : 6 dsimp only [coe_comp, Function.comp_apply, AddMonoidHom.compHom_apply_apply, flip_apply, AddMonoidHom.flipHom_apply] simp_rw [mulHom_of_of] diff --git a/Mathlib/Algebra/Lie/DirectSum.lean b/Mathlib/Algebra/Lie/DirectSum.lean index 6466bf3359efa..bed135465a358 100644 --- a/Mathlib/Algebra/Lie/DirectSum.lean +++ b/Mathlib/Algebra/Lie/DirectSum.lean @@ -43,13 +43,13 @@ variable [∀ i, LieRingModule L (M i)] [∀ i, LieModule R L (M i)] instance : LieRingModule L (⨁ i, M i) where bracket x m := m.mapRange (fun _ m' => ⁅x, m'⁆) fun _ => lie_zero x add_lie x y m := by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [mapRange_apply, add_apply, add_lie] lie_add x m n := by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [mapRange_apply, add_apply, lie_add] leibniz_lie x y m := by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [mapRange_apply, lie_lie, add_apply, sub_add_cancel] @[simp] @@ -58,10 +58,10 @@ theorem lie_module_bracket_apply (x : L) (m : ⨁ i, M i) (i : ι) : ⁅x, m⁆ instance : LieModule R L (⨁ i, M i) where smul_lie t x m := by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext i` + ext simp only [smul_lie, lie_module_bracket_apply, smul_apply] lie_smul t x m := by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext i` + ext simp only [lie_smul, lie_module_bracket_apply, smul_apply] variable (R ι L M) @@ -70,7 +70,7 @@ variable (R ι L M) def lieModuleOf [DecidableEq ι] (j : ι) : M j →ₗ⁅R,L⁆ ⨁ i, M i := { lof R ι M j with map_lie' := fun {x m} => by - refine DFinsupp.ext fun i => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext i` + ext i by_cases h : j = i · rw [← h]; simp · -- This used to be the end of the proof before https://github.com/leanprover/lean4/pull/2644 @@ -98,16 +98,16 @@ instance lieRing : LieRing (⨁ i, L i) := { (inferInstance : AddCommGroup _) with bracket := zipWith (fun _ => fun x y => ⁅x, y⁆) fun _ => lie_zero 0 add_lie := fun x y z => by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [zipWith_apply, add_apply, add_lie] lie_add := fun x y z => by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [zipWith_apply, add_apply, lie_add] lie_self := fun x => by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [zipWith_apply, add_apply, lie_self, zero_apply] leibniz_lie := fun x y z => by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [sub_apply, zipWith_apply, add_apply, zero_apply] apply leibniz_lie } @@ -121,7 +121,7 @@ theorem lie_of_same [DecidableEq ι] {i : ι} (x y : L i) : theorem lie_of_of_ne [DecidableEq ι] {i j : ι} (hij : i ≠ j) (x : L i) (y : L j) : ⁅of L i x, of L j y⁆ = 0 := by - refine DFinsupp.ext fun k => ?_ + ext k rw [bracket_apply] obtain rfl | hik := Decidable.eq_or_ne i k · rw [of_eq_of_ne _ _ _ hij.symm, lie_zero, zero_apply] @@ -137,7 +137,7 @@ theorem lie_of [DecidableEq ι] {i j : ι} (x : L i) (y : L j) : instance lieAlgebra : LieAlgebra R (⨁ i, L i) := { (inferInstance : Module R _) with lie_smul := fun c x y => by - refine DFinsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext` + ext simp only [zipWith_apply, smul_apply, bracket_apply, lie_smul] } variable (R ι) @@ -148,7 +148,7 @@ def lieAlgebraOf [DecidableEq ι] (j : ι) : L j →ₗ⁅R⁆ ⨁ i, L i := { lof R ι L j with toFun := of L j map_lie' := fun {x y} => by - refine DFinsupp.ext fun i => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): Originally `ext i` + ext i by_cases h : j = i · rw [← h] -- This used to be the end of the proof before https://github.com/leanprover/lean4/pull/2644 diff --git a/Mathlib/RingTheory/AdicCompletion/Functoriality.lean b/Mathlib/RingTheory/AdicCompletion/Functoriality.lean index 80039d291af17..bbd542f764a94 100644 --- a/Mathlib/RingTheory/AdicCompletion/Functoriality.lean +++ b/Mathlib/RingTheory/AdicCompletion/Functoriality.lean @@ -287,8 +287,8 @@ theorem sumInv_apply (x : AdicCompletion I (⨁ j, M j)) (j : ι) : variable [DecidableEq ι] theorem sumInv_comp_sum : sumInv I M ∘ₗ sum I M = LinearMap.id := by - ext j x - apply DirectSum.ext (AdicCompletion I R) (fun i ↦ ?_) + ext j x : 2 + apply DirectSum.ext_component (AdicCompletion I R) (fun i ↦ ?_) ext n simp only [LinearMap.coe_comp, Function.comp_apply, sum_lof, map_mk, component_sumInv, mk_apply_coe, AdicCauchySequence.map_apply_coe, Submodule.mkQ_apply, LinearMap.id_comp] diff --git a/Mathlib/RingTheory/Flat/Basic.lean b/Mathlib/RingTheory/Flat/Basic.lean index aa58cec320090..90816a27b68c2 100644 --- a/Mathlib/RingTheory/Flat/Basic.lean +++ b/Mathlib/RingTheory/Flat/Basic.lean @@ -195,7 +195,7 @@ instance directSum (ι : Type v) (M : ι → Type w) [(i : ι) → AddCommGroup by_cases h₂ : j = i · subst j; simp · simp [h₂] - intro a ha; rw [DirectSum.ext_iff R]; intro i + intro a ha; rw [DirectSum.ext_component_iff R]; intro i have f := LinearMap.congr_arg (f := (π i)) ha erw [LinearMap.congr_fun (h₁ i) a] at f rw [(map_zero (π i) : (π i) 0 = (0 : M i))] at f From e44f03d6ad3de67cd85286a2e2cf2970b0b6de65 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 10 Jan 2025 00:02:56 +0000 Subject: [PATCH 113/681] chore: remove more `erw`s (#20605) --- Mathlib/Algebra/Category/Grp/AB.lean | 2 +- Mathlib/Algebra/Order/Antidiag/Prod.lean | 7 +++---- Mathlib/Algebra/Order/Group/Pointwise/Interval.lean | 5 +++-- Mathlib/Algebra/Order/Monovary.lean | 8 ++++---- Mathlib/CategoryTheory/Limits/HasLimits.lean | 4 ++++ .../Combinatorics/SimpleGraph/Regularity/Chunk.lean | 7 +++---- Mathlib/Data/Finset/Prod.lean | 4 ++++ Mathlib/Order/BooleanAlgebra.lean | 7 +++---- Mathlib/Order/Filter/Bases.lean | 2 +- Mathlib/Order/Filter/Prod.lean | 4 ++-- Mathlib/Order/KrullDimension.lean | 3 ++- Mathlib/Order/RelSeries.lean | 10 ++++++---- 12 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Mathlib/Algebra/Category/Grp/AB.lean b/Mathlib/Algebra/Category/Grp/AB.lean index 7731a8f49c9fc..dde16f6cf9ea2 100644 --- a/Mathlib/Algebra/Category/Grp/AB.lean +++ b/Mathlib/Algebra/Category/Grp/AB.lean @@ -32,7 +32,7 @@ noncomputable instance : intro x (hx : _ = _) dsimp at hx rcases Concrete.colimit_exists_rep S.X₂ x with ⟨j, y, rfl⟩ - erw [← comp_apply, colimit.ι_map, comp_apply, + rw [← comp_apply, colimMap_eq, colimit.ι_map, comp_apply, ← map_zero (by exact colimit.ι S.X₃ j : (S.X₃).obj j →+ ↑(colimit S.X₃))] at hx rcases Concrete.colimit_exists_of_rep_eq.{u, u, u} S.X₃ _ _ hx with ⟨k, e₁, e₂, hk : _ = S.X₃.map e₂ 0⟩ diff --git a/Mathlib/Algebra/Order/Antidiag/Prod.lean b/Mathlib/Algebra/Order/Antidiag/Prod.lean index 1bd46120668a9..be149cefc1477 100644 --- a/Mathlib/Algebra/Order/Antidiag/Prod.lean +++ b/Mathlib/Algebra/Order/Antidiag/Prod.lean @@ -193,9 +193,8 @@ Note that this is not an instance, as for some times a more efficient algorithm abbrev antidiagonalOfLocallyFinite : HasAntidiagonal A where antidiagonal n := Finset.filter (fun uv => uv.fst + uv.snd = n) (Finset.product (Iic n) (Iic n)) mem_antidiagonal {n} {a} := by - simp only [Prod.forall, mem_filter, and_iff_right_iff_imp] - intro h; rw [← h] - erw [mem_product, mem_Iic, mem_Iic] - exact ⟨le_self_add, le_add_self⟩ + simp only [mem_filter, and_iff_right_iff_imp] + intro h + simp [← h] end Finset diff --git a/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean b/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean index 8a43aa8f926fc..e5ab380cbc190 100644 --- a/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean +++ b/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean @@ -796,8 +796,9 @@ theorem inv_Iio₀ {a : α} (ha : a < 0) : (Iio a)⁻¹ = Ioo a⁻¹ 0 := by theorem image_const_mul_Ioi_zero {k : Type*} [LinearOrderedField k] {x : k} (hx : 0 < x) : (fun y => x * y) '' Ioi (0 : k) = Ioi 0 := by - erw [(Units.mk0 x hx.ne').mulLeft.image_eq_preimage, - preimage_const_mul_Ioi 0 (inv_pos.mpr hx), zero_div] + have := (Units.mk0 x hx.ne').mulLeft.image_eq_preimage (Ioi 0) + simp at this + simp_all /-! ### Images under `x ↦ a * x + b` diff --git a/Mathlib/Algebra/Order/Monovary.lean b/Mathlib/Algebra/Order/Monovary.lean index 9ad0b00b7fa4d..237eb21305f97 100644 --- a/Mathlib/Algebra/Order/Monovary.lean +++ b/Mathlib/Algebra/Order/Monovary.lean @@ -245,11 +245,11 @@ lemma antivaryOn_inv_left₀ (hf : ∀ i ∈ s, 0 < f i) : AntivaryOn f⁻¹ g s @[simp] lemma monovaryOn_inv_right₀ (hg : ∀ i ∈ s, 0 < g i) : MonovaryOn f g⁻¹ s ↔ AntivaryOn f g s := - forall₂_swap.trans <| forall₄_congr fun i hi j hj ↦ by erw [inv_lt_inv₀ (hg _ hj) (hg _ hi)] + forall₂_swap.trans <| forall₄_congr fun i hi j hj ↦ by simp [inv_lt_inv₀ (hg _ hj) (hg _ hi)] @[simp] lemma antivaryOn_inv_right₀ (hg : ∀ i ∈ s, 0 < g i) : AntivaryOn f g⁻¹ s ↔ MonovaryOn f g s := - forall₂_swap.trans <| forall₄_congr fun i hi j hj ↦ by erw [inv_lt_inv₀ (hg _ hj) (hg _ hi)] + forall₂_swap.trans <| forall₄_congr fun i hi j hj ↦ by simp [inv_lt_inv₀ (hg _ hj) (hg _ hi)] lemma monovaryOn_inv₀ (hf : ∀ i ∈ s, 0 < f i) (hg : ∀ i ∈ s, 0 < g i) : MonovaryOn f⁻¹ g⁻¹ s ↔ MonovaryOn f g s := by @@ -265,10 +265,10 @@ lemma antivaryOn_inv₀ (hf : ∀ i ∈ s, 0 < f i) (hg : ∀ i ∈ s, 0 < g i) forall₃_congr fun _i _j _ ↦ inv_le_inv₀ (hf _) (hf _) @[simp] lemma monovary_inv_right₀ (hg : StrongLT 0 g) : Monovary f g⁻¹ ↔ Antivary f g := - forall_swap.trans <| forall₂_congr fun i j ↦ by erw [inv_lt_inv₀ (hg _) (hg _)] + forall_swap.trans <| forall₂_congr fun i j ↦ by simp [inv_lt_inv₀ (hg _) (hg _)] @[simp] lemma antivary_inv_right₀ (hg : StrongLT 0 g) : Antivary f g⁻¹ ↔ Monovary f g := - forall_swap.trans <| forall₂_congr fun i j ↦ by erw [inv_lt_inv₀ (hg _) (hg _)] + forall_swap.trans <| forall₂_congr fun i j ↦ by simp [inv_lt_inv₀ (hg _) (hg _)] lemma monovary_inv₀ (hf : StrongLT 0 f) (hg : StrongLT 0 g) : Monovary f⁻¹ g⁻¹ ↔ Monovary f g := by rw [monovary_inv_left₀ hf, antivary_inv_right₀ hg] diff --git a/Mathlib/CategoryTheory/Limits/HasLimits.lean b/Mathlib/CategoryTheory/Limits/HasLimits.lean index e9ece3954362f..ec913e2a6944d 100644 --- a/Mathlib/CategoryTheory/Limits/HasLimits.lean +++ b/Mathlib/CategoryTheory/Limits/HasLimits.lean @@ -467,6 +467,8 @@ end variable {G : J ⥤ C} (α : F ⟶ G) +theorem limMap_eq : limMap α = lim.map α := rfl + theorem limit.map_pre [HasLimitsOfShape K C] (E : K ⥤ J) : lim.map α ≫ limit.pre G E = limit.pre F E ≫ lim.map (whiskerLeft E α) := by ext @@ -992,6 +994,8 @@ end variable {G : J ⥤ C} (α : F ⟶ G) +theorem colimMap_eq : colimMap α = colim.map α := rfl + @[reassoc] theorem colimit.ι_map (j : J) : colimit.ι F j ≫ colim.map α = α.app j ≫ colimit.ι G j := by simp diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean index 067be4ae05806..cfbe8ee664232 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean @@ -333,7 +333,7 @@ private theorem average_density_near_total_density [Nonempty α] rw [sub_le_iff_le_add, ← sub_le_iff_le_add'] apply density_sub_eps_le_sum_density_div_card hPα hPε hA hB -private theorem edgeDensity_chunk_aux [Nonempty α] +private theorem edgeDensity_chunk_aux [Nonempty α] (hP) (hPα : #P.parts * 16 ^ #P.parts ≤ card α) (hPε : ↑100 ≤ ↑4 ^ #P.parts * ε ^ 5) (hU : U ∈ P.parts) (hV : V ∈ P.parts) : (G.edgeDensity U V : ℝ) ^ 2 - ε ^ 5 / ↑25 ≤ @@ -499,10 +499,9 @@ theorem edgeDensity_chunk_not_uniform [Nonempty α] (hPα : #P.parts * 16 ^ #P.p norm_num exact edgeDensity_star_not_uniform hPα hPε hε₁ hUVne hUV · rw [sp, card_product] - apply (edgeDensity_chunk_aux hPα hPε hU hV).trans + apply (edgeDensity_chunk_aux hP hPα hPε hU hV).trans · rw [card_chunk (m_pos hPα).ne', card_chunk (m_pos hPα).ne', ← mul_pow] - · norm_num - rfl + norm_num /-- Lower bound on the edge densities between parts of `SzemerediRegularity.increment`. This is the blanket lower bound used the uniform parts. -/ diff --git a/Mathlib/Data/Finset/Prod.lean b/Mathlib/Data/Finset/Prod.lean index 43f9f14b0d85f..0bdcfd29884d2 100644 --- a/Mathlib/Data/Finset/Prod.lean +++ b/Mathlib/Data/Finset/Prod.lean @@ -42,6 +42,10 @@ protected def product (s : Finset α) (t : Finset β) : Finset (α × β) := instance instSProd : SProd (Finset α) (Finset β) (Finset (α × β)) where sprod := Finset.product +@[simp] +theorem product_eq_sprod : Finset.product s t = s ×ˢ t := + rfl + @[simp] theorem product_val : (s ×ˢ t).1 = s.1 ×ˢ t.1 := rfl diff --git a/Mathlib/Order/BooleanAlgebra.lean b/Mathlib/Order/BooleanAlgebra.lean index cbe13b58400f7..72077474d6a28 100644 --- a/Mathlib/Order/BooleanAlgebra.lean +++ b/Mathlib/Order/BooleanAlgebra.lean @@ -512,10 +512,9 @@ abbrev GeneralizedBooleanAlgebra.toBooleanAlgebra [GeneralizedBooleanAlgebra α] compl a := ⊤ \ a inf_compl_le_bot _ := disjoint_sdiff_self_right.le_bot top_le_sup_compl _ := le_sup_sdiff - sdiff_eq _ _ := by - -- Porting note: changed `rw` to `erw` here. - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [← inf_sdiff_assoc, inf_top_eq] + sdiff_eq a b := by + change _ = a ⊓ (⊤ \ b) + rw [← inf_sdiff_assoc, inf_top_eq] section BooleanAlgebra diff --git a/Mathlib/Order/Filter/Bases.lean b/Mathlib/Order/Filter/Bases.lean index 9aeebbf245242..6a5d64a703e88 100644 --- a/Mathlib/Order/Filter/Bases.lean +++ b/Mathlib/Order/Filter/Bases.lean @@ -197,7 +197,7 @@ protected theorem mem_filter_iff (h : IsBasis p s) {U : Set α} : exists_exists_and_eq_and] theorem filter_eq_generate (h : IsBasis p s) : h.filter = generate { U | ∃ i, p i ∧ s i = U } := by - erw [h.filterBasis.generate]; rfl + rw [IsBasis.filter, ← h.filterBasis.generate, IsBasis.filterBasis] end IsBasis diff --git a/Mathlib/Order/Filter/Prod.lean b/Mathlib/Order/Filter/Prod.lean index 652a0c81b4dc6..0cfb61d651cd4 100644 --- a/Mathlib/Order/Filter/Prod.lean +++ b/Mathlib/Order/Filter/Prod.lean @@ -92,7 +92,7 @@ theorem eventually_prod_principal_iff {p : α × β → Prop} {s : Set β} : theorem comap_prod (f : α → β × γ) (b : Filter β) (c : Filter γ) : comap f (b ×ˢ c) = comap (Prod.fst ∘ f) b ⊓ comap (Prod.snd ∘ f) c := by - erw [comap_inf, Filter.comap_comap, Filter.comap_comap] + rw [prod_eq_inf, comap_inf, Filter.comap_comap, Filter.comap_comap] theorem comap_prodMap_prod (f : α → β) (g : γ → δ) (lb : Filter β) (ld : Filter δ) : comap (Prod.map f g) (lb ×ˢ ld) = comap f lb ×ˢ comap g ld := by @@ -326,7 +326,7 @@ theorem le_prod_map_fst_snd {f : Filter (α × β)} : f ≤ map Prod.fst f ×ˢ theorem Tendsto.prod_map {δ : Type*} {f : α → γ} {g : β → δ} {a : Filter α} {b : Filter β} {c : Filter γ} {d : Filter δ} (hf : Tendsto f a c) (hg : Tendsto g b d) : Tendsto (Prod.map f g) (a ×ˢ b) (c ×ˢ d) := by - erw [Tendsto, ← prod_map_map_eq] + rw [Tendsto, Prod.map_def, ← prod_map_map_eq] exact Filter.prod_mono hf hg protected theorem map_prod (m : α × β → γ) (f : Filter α) (g : Filter β) : diff --git a/Mathlib/Order/KrullDimension.lean b/Mathlib/Order/KrullDimension.lean index f9939bd2e168b..23dd08f1755a0 100644 --- a/Mathlib/Order/KrullDimension.lean +++ b/Mathlib/Order/KrullDimension.lean @@ -588,7 +588,8 @@ lemma krullDim_eq_top [InfiniteDimensionalOrder α] : | some ⊤, _ => le_refl _ | some (some m), hm => by refine (not_lt_of_le (hm (LTSeries.withLength _ (m + 1))) ?_).elim - erw [WithBot.coe_lt_coe, WithTop.coe_lt_coe] + rw [WithBot.some_eq_coe, ← WithBot.coe_natCast, WithBot.coe_lt_coe, + WithTop.some_eq_coe, ← WithTop.coe_natCast, WithTop.coe_lt_coe] simp @[deprecated (since := "2024-12-22")] diff --git a/Mathlib/Order/RelSeries.lean b/Mathlib/Order/RelSeries.lean index 6f705bc25482f..21940c227fda3 100644 --- a/Mathlib/Order/RelSeries.lean +++ b/Mathlib/Order/RelSeries.lean @@ -519,17 +519,19 @@ def smash (p q : RelSeries r) (connect : p.last = q.head) : RelSeries r where dsimp only by_cases h₂ : i.1 + 1 < p.length · have h₁ : i.1 < p.length := lt_trans (lt_add_one _) h₂ - erw [dif_pos h₁, dif_pos h₂] + simp only [Fin.coe_castSucc, Fin.val_succ] + rw [dif_pos h₁, dif_pos h₂] convert p.step ⟨i, h₁⟩ using 1 - · erw [dif_neg h₂] + · simp only [Fin.coe_castSucc, Fin.val_succ] + rw [dif_neg h₂] by_cases h₁ : i.1 < p.length - · erw [dif_pos h₁] + · rw [dif_pos h₁] have h₃ : p.length = i.1 + 1 := by omega convert p.step ⟨i, h₁⟩ using 1 convert connect.symm · aesop · congr; aesop - · erw [dif_neg h₁] + · rw [dif_neg h₁] convert q.step ⟨i.1 - p.length, _⟩ using 1 · congr change (i.1 + 1) - _ = _ From 0a078d0b0c7fdf68a3e718818265e90116a05612 Mon Sep 17 00:00:00 2001 From: Riccardo Brasca Date: Fri, 10 Jan 2025 00:48:41 +0000 Subject: [PATCH 114/681] feat: add normalizedFactorsMapEquivNormalizedFactorsMinPolyMk_symm_apply_eq_span (#19603) We add `normalizedFactorsMapEquivNormalizedFactorsMinPolyMk_symm_apply_eq_span`, that explicitely describes the image, via the Kummer Dedekind correspondence, of a factor of the minimal polynomial of the generator. --- Mathlib/NumberTheory/KummerDedekind.lean | 67 +++++++++++++++++++----- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/Mathlib/NumberTheory/KummerDedekind.lean b/Mathlib/NumberTheory/KummerDedekind.lean index aa1e1913d08e0..664ad5684a29a 100644 --- a/Mathlib/NumberTheory/KummerDedekind.lean +++ b/Mathlib/NumberTheory/KummerDedekind.lean @@ -30,6 +30,11 @@ with a formula). * `Ideal.irreducible_map_of_irreducible_minpoly` : `I.map (algebraMap R S)` is irreducible if `(map (Ideal.Quotient.mk I) (minpoly R pb.gen))` is irreducible, where `pb` is a power basis of `S` over `R`. + * `normalizedFactorsMapEquivNormalizedFactorsMinPolyMk_symm_apply_eq_span` : Let `Q` be a lift of + factor of the minimal polynomial of `x`, a generator of `S` over `R`, taken + `mod I`. Then (the reduction of) `Q` corresponds via + `normalizedFactorsMapEquivNormalizedFactorsMinPolyMk` to + `span (I.map (algebraMap R S) ∪ {Q.aeval x})`. ## TODO @@ -37,10 +42,6 @@ with a formula). * Prove the converse of `Ideal.irreducible_map_of_irreducible_minpoly`. - * Prove that `normalizedFactorsMapEquivNormalizedFactorsMinPolyMk` can be expressed as - `normalizedFactorsMapEquivNormalizedFactorsMinPolyMk g = ⟨I, G(α)⟩` for `g` a prime - factor of `f mod I` and `G` a lift of `g` to `R[X]`. - ## References * [J. Neukirch, *Algebraic Number Theory*][Neukirch1992] @@ -229,6 +230,28 @@ variable [NoZeroSMulDivisors R S] attribute [local instance] Ideal.Quotient.field +private noncomputable def f (hx : (conductor R x).comap (algebraMap R S) ⊔ I = ⊤) + (hx' : IsIntegral R x) : + S ⧸ I.map (algebraMap R S) ≃+* (R ⧸ I)[X] ⧸ span {(minpoly R x).map (Ideal.Quotient.mk I)} := + (quotAdjoinEquivQuotMap hx (NoZeroSMulDivisors.algebraMap_injective + (Algebra.adjoin R {x}) S)).symm.trans <| + ((Algebra.adjoin.powerBasis' hx').quotientEquivQuotientMinpolyMap I).toRingEquiv.trans <| + quotEquivOfEq (by rw [Algebra.adjoin.powerBasis'_minpoly_gen hx']) + +private lemma f_symm_aux (hx : (conductor R x).comap (algebraMap R S) ⊔ I = ⊤) + (hx' : IsIntegral R x) (Q : R[X]) : + (f hx hx').symm (Q.map (Ideal.Quotient.mk I)) = Q.aeval x := by + apply (f hx hx').injective + rw [f, AlgEquiv.toRingEquiv_eq_coe, RingEquiv.symm_trans_apply, RingEquiv.symm_symm, + RingEquiv.coe_trans, Function.comp_apply, RingEquiv.symm_apply_apply, + RingEquiv.symm_trans_apply, quotEquivOfEq_symm, quotEquivOfEq_mk] + congr + convert (adjoin.powerBasis' hx').quotientEquivQuotientMinpolyMap_symm_apply_mk I Q + apply (quotAdjoinEquivQuotMap hx + (NoZeroSMulDivisors.algebraMap_injective ((adjoin R {x})) S)).injective + simp only [RingEquiv.apply_symm_apply, adjoin.powerBasis'_gen, quotAdjoinEquivQuotMap_apply_mk, + coe_aeval_mk_apply] + open Classical in /-- The first half of the **Kummer-Dedekind Theorem** in the monogenic case, stating that the prime factors of `I*S` are in bijection with those of the minimal polynomial of the generator of `S` @@ -238,16 +261,7 @@ noncomputable def normalizedFactorsMapEquivNormalizedFactorsMinPolyMk (hI : IsMa {J : Ideal S | J ∈ normalizedFactors (I.map (algebraMap R S))} ≃ {d : (R ⧸ I)[X] | d ∈ normalizedFactors (Polynomial.map (Ideal.Quotient.mk I) (minpoly R x))} := by - -- Porting note: Lean needs to be reminded about this so it does not time out - have : IsPrincipalIdealRing (R ⧸ I)[X] := inferInstance - let f : S ⧸ map (algebraMap R S) I ≃+* - (R ⧸ I)[X] ⧸ span {Polynomial.map (Ideal.Quotient.mk I) (minpoly R x)} := by - refine (quotAdjoinEquivQuotMap hx ?_).symm.trans - (((Algebra.adjoin.powerBasis' - hx').quotientEquivQuotientMinpolyMap I).toRingEquiv.trans (quotEquivOfEq ?_)) - · exact NoZeroSMulDivisors.algebraMap_injective (Algebra.adjoin R {x}) S - · rw [Algebra.adjoin.powerBasis'_minpoly_gen hx'] - refine (normalizedFactorsEquivOfQuotEquiv f ?_ ?_).trans ?_ + refine (normalizedFactorsEquivOfQuotEquiv (f hx hx') ?_ ?_).trans ?_ · rwa [Ne, map_eq_bot_iff_of_injective (NoZeroSMulDivisors.algebraMap_injective R S), ← Ne] · by_contra h exact (show Polynomial.map (Ideal.Quotient.mk I) (minpoly R x) ≠ 0 from @@ -343,4 +357,29 @@ theorem Ideal.irreducible_map_of_irreducible_minpoly (hI : IsMaximal I) (hI' : I rw [Multiset.attach_map_val, Multiset.map_singleton, Subtype.coe_mk] exact normalizedFactors_irreducible hf +open Set Classical in +/-- Let `Q` be a lift of factor of the minimal polynomial of `x`, a generator of `S` over `R`, taken +`mod I`. Then (the reduction of) `Q` corresponds via +`normalizedFactorsMapEquivNormalizedFactorsMinPolyMk` to +`span (I.map (algebraMap R S) ∪ {Q.aeval x})`. -/ +theorem normalizedFactorsMapEquivNormalizedFactorsMinPolyMk_symm_apply_eq_span + (hI : I.IsMaximal) {Q : R[X]} + (hQ : Q.map (Ideal.Quotient.mk I) ∈ normalizedFactors ((minpoly R x).map (Ideal.Quotient.mk I))) + (hI' : I ≠ ⊥) (hx : (conductor R x).comap (algebraMap R S) ⊔ I = ⊤) (hx' : IsIntegral R x) : + ((normalizedFactorsMapEquivNormalizedFactorsMinPolyMk hI hI' hx hx').symm ⟨_, hQ⟩).val = + span (I.map (algebraMap R S) ∪ {Q.aeval x}) := by + dsimp [normalizedFactorsMapEquivNormalizedFactorsMinPolyMk, + normalizedFactorsEquivSpanNormalizedFactors] + rw [normalizedFactorsEquivOfQuotEquiv_symm] + dsimp [normalizedFactorsEquivOfQuotEquiv, idealFactorsEquivOfQuotEquiv, OrderIso.ofHomInv] + simp only [map_span, image_singleton, coe_coe,f_symm_aux hx hx' Q] + refine le_antisymm (fun a ha ↦ ?_) (span_le.mpr <| union_subset_iff.mpr <| + ⟨le_comap_of_map_le (by simp), by simp [mem_span_singleton]⟩) + rw [mem_comap, Ideal.mem_span_singleton] at ha + obtain ⟨a', ha'⟩ := ha + obtain ⟨b, hb⟩ := Ideal.Quotient.mk_surjective a' + rw [← hb, ← _root_.map_mul, Quotient.mk_eq_mk_iff_sub_mem] at ha' + rw [union_comm, span_union, span_eq, mem_span_singleton_sup] + exact ⟨b, a - Q.aeval x * b, ha', by ring⟩ + end KummerDedekind From 98c1c1655e0713091abf4d3d69165b418818dea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 01:30:05 +0000 Subject: [PATCH 115/681] chore(Algebra/CharP/Defs): do not import `Field` (#20566) --- Mathlib/Algebra/CharP/Defs.lean | 20 +++++--------------- Mathlib/Algebra/CharP/Invertible.lean | 2 ++ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Mathlib/Algebra/CharP/Defs.lean b/Mathlib/Algebra/CharP/Defs.lean index 0e34907443410..9c7fa12021669 100644 --- a/Mathlib/Algebra/CharP/Defs.lean +++ b/Mathlib/Algebra/CharP/Defs.lean @@ -4,10 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Joey van Langen, Casper Putz -/ import Mathlib.Data.Int.ModEq -import Mathlib.Data.Nat.Cast.Defs +import Mathlib.Data.Nat.Cast.Basic import Mathlib.Data.Nat.Find import Mathlib.Data.Nat.Prime.Defs -import Mathlib.Tactic.NormNum.Basic /-! # Characteristic of semirings @@ -20,6 +19,7 @@ import Mathlib.Tactic.NormNum.Basic prime characteristic `p`) -/ +assert_not_exists Field assert_not_exists Finset open Set @@ -189,19 +189,9 @@ lemma Nat.cast_ringChar : (ringChar R : R) = 0 := by rw [ringChar.spec] end ringChar lemma CharP.neg_one_ne_one [Ring R] (p : ℕ) [CharP R p] [Fact (2 < p)] : (-1 : R) ≠ (1 : R) := by - suffices (2 : R) ≠ 0 by - intro h - symm at h - rw [← sub_eq_zero, sub_neg_eq_add] at h - norm_num at h - exact this h - -- Porting note: this could probably be golfed - intro h - rw [show (2 : R) = (2 : ℕ) by norm_cast] at h - have := (CharP.cast_eq_zero_iff R p 2).mp h - have := Nat.le_of_dvd (by decide) this - rw [fact_iff] at * - omega + rw [ne_comm, ← sub_ne_zero, sub_neg_eq_add, one_add_one_eq_two, ← Nat.cast_two, Ne, + CharP.cast_eq_zero_iff R p 2] + exact fun h ↦ (Fact.out : 2 < p).not_le <| Nat.le_of_dvd Nat.zero_lt_two h namespace CharP diff --git a/Mathlib/Algebra/CharP/Invertible.lean b/Mathlib/Algebra/CharP/Invertible.lean index bdf5259b6cf73..cbb9420c8c970 100644 --- a/Mathlib/Algebra/CharP/Invertible.lean +++ b/Mathlib/Algebra/CharP/Invertible.lean @@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ import Mathlib.Algebra.CharP.Defs +import Mathlib.Algebra.Field.Defs +import Mathlib.Algebra.GroupWithZero.Invertible /-! # Invertibility of elements given a characteristic From 2d57ce73442c03289dc573f3983a40efa0df8fc5 Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Fri, 10 Jan 2025 01:57:22 +0000 Subject: [PATCH 116/681] refactor: Split `FieldTheory/Adjoin.lean` into `Defs.lean` and `Basic.lean` (#20333) The file `FieldTheory/Adjoin.lean` was getting rather long, so I've split it into `Defs.lean` (importing only `FieldTheory/IntermediateField/Basic.lean`) and `Basic.lean` (everything else). --- Mathlib.lean | 3 +- Mathlib/FieldTheory/Extension.lean | 2 +- .../Adjoin/Basic.lean} | 730 +---------------- .../IntermediateField/Adjoin/Defs.lean | 765 ++++++++++++++++++ Mathlib/FieldTheory/LinearDisjoint.lean | 2 +- Mathlib/FieldTheory/Minpoly/IsConjRoot.lean | 2 +- Mathlib/FieldTheory/Relrank.lean | 2 +- .../AlgebraicIndependent/Adjoin.lean | 2 +- .../TranscendenceBasis.lean | 2 +- Mathlib/RingTheory/Valuation/Minpoly.lean | 2 +- 10 files changed, 777 insertions(+), 735 deletions(-) rename Mathlib/FieldTheory/{Adjoin.lean => IntermediateField/Adjoin/Basic.lean} (62%) create mode 100644 Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index a93997f28634d..e831060db77b0 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3052,7 +3052,6 @@ import Mathlib.Dynamics.TopologicalEntropy.NetEntropy import Mathlib.Dynamics.TopologicalEntropy.Semiconj import Mathlib.FieldTheory.AbelRuffini import Mathlib.FieldTheory.AbsoluteGaloisGroup -import Mathlib.FieldTheory.Adjoin import Mathlib.FieldTheory.AlgebraicClosure import Mathlib.FieldTheory.AxGrothendieck import Mathlib.FieldTheory.CardinalEmb @@ -3070,6 +3069,8 @@ import Mathlib.FieldTheory.Galois.Basic import Mathlib.FieldTheory.Galois.GaloisClosure import Mathlib.FieldTheory.Galois.Infinite import Mathlib.FieldTheory.Galois.Profinite +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic +import Mathlib.FieldTheory.IntermediateField.Adjoin.Defs import Mathlib.FieldTheory.IntermediateField.Algebraic import Mathlib.FieldTheory.IntermediateField.Basic import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure diff --git a/Mathlib/FieldTheory/Extension.lean b/Mathlib/FieldTheory/Extension.lean index 131f0f917c5ff..7196af459c499 100644 --- a/Mathlib/FieldTheory/Extension.lean +++ b/Mathlib/FieldTheory/Extension.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Junyan Xu -/ import Mathlib.Data.Fintype.Order -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic /-! # Extension of field embeddings diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean similarity index 62% rename from Mathlib/FieldTheory/Adjoin.lean rename to Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean index e0d6ba6cd6a31..757f77d8c8c69 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Patrick Lutz -/ import Mathlib.Algebra.Algebra.Subalgebra.Directed +import Mathlib.FieldTheory.IntermediateField.Adjoin.Defs import Mathlib.FieldTheory.IntermediateField.Algebraic import Mathlib.FieldTheory.Separable import Mathlib.FieldTheory.SplittingField.IsSplittingField @@ -17,19 +18,7 @@ import Mathlib.LinearAlgebra.Dual /-! # Adjoining Elements to Fields -In this file we introduce the notion of adjoining elements to fields. -This isn't quite the same as adjoining elements to rings. -For example, `Algebra.adjoin K {x}` might not include `x⁻¹`. - -## Main results - -- `adjoin_adjoin_left`: adjoining S and then T is the same as adjoining `S ∪ T`. -- `bot_eq_top_of_rank_adjoin_eq_one`: if `F⟮x⟯` has dimension `1` over `F` for every `x` - in `E` then `F = E` - -## Notation - - - `F⟮α⟯`: adjoin a single element `α` to `F` (in scope `IntermediateField`). +This file contains many results about adjoining elements to fields. -/ open Module Polynomial @@ -38,20 +27,7 @@ namespace IntermediateField section AdjoinDef -variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] (S : Set E) - --- Porting note: not adding `neg_mem'` causes an error. -/-- `adjoin F S` extends a field `F` by adjoining a set `S ⊆ E`. -/ -@[stacks 09FZ "first part"] -def adjoin : IntermediateField F E := - { Subfield.closure (Set.range (algebraMap F E) ∪ S) with - algebraMap_mem' := fun x => Subfield.subset_closure (Or.inl (Set.mem_range_self x)) } - -@[simp] -theorem adjoin_toSubfield : - (adjoin F S).toSubfield = Subfield.closure (Set.range (algebraMap F E) ∪ S) := rfl - -variable {S} +variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] {S : Set E} theorem mem_adjoin_range_iff {ι : Type*} (i : ι → E) (x : E) : x ∈ adjoin F (Set.range i) ↔ ∃ r s : MvPolynomial ι F, @@ -75,453 +51,10 @@ theorem mem_adjoin_simple_iff {α : E} (x : E) : end AdjoinDef -section Lattice - -variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] - -@[simp] -theorem adjoin_le_iff {S : Set E} {T : IntermediateField F E} : adjoin F S ≤ T ↔ S ⊆ T := - ⟨fun H => le_trans (le_trans Set.subset_union_right Subfield.subset_closure) H, fun H => - (@Subfield.closure_le E _ (Set.range (algebraMap F E) ∪ S) T.toSubfield).mpr - (Set.union_subset (IntermediateField.set_range_subset T) H)⟩ - -theorem gc : GaloisConnection (adjoin F : Set E → IntermediateField F E) - (fun (x : IntermediateField F E) => (x : Set E)) := fun _ _ => - adjoin_le_iff - -/-- Galois insertion between `adjoin` and `coe`. -/ -def gi : GaloisInsertion (adjoin F : Set E → IntermediateField F E) - (fun (x : IntermediateField F E) => (x : Set E)) where - choice s hs := (adjoin F s).copy s <| le_antisymm (gc.le_u_l s) hs - gc := IntermediateField.gc - le_l_u S := (IntermediateField.gc (S : Set E) (adjoin F S)).1 <| le_rfl - choice_eq _ _ := copy_eq _ _ _ - -instance : CompleteLattice (IntermediateField F E) where - __ := GaloisInsertion.liftCompleteLattice IntermediateField.gi - bot := - { toSubalgebra := ⊥ - inv_mem' := by rintro x ⟨r, rfl⟩; exact ⟨r⁻¹, map_inv₀ _ _⟩ } - bot_le x := (bot_le : ⊥ ≤ x.toSubalgebra) - -theorem sup_def (S T : IntermediateField F E) : S ⊔ T = adjoin F (S ∪ T : Set E) := rfl - -theorem sSup_def (S : Set (IntermediateField F E)) : - sSup S = adjoin F (⋃₀ (SetLike.coe '' S)) := rfl - -instance : Inhabited (IntermediateField F E) := - ⟨⊤⟩ - -instance : Unique (IntermediateField F F) := - { inferInstanceAs (Inhabited (IntermediateField F F)) with - uniq := fun _ ↦ toSubalgebra_injective <| Subsingleton.elim _ _ } - -theorem coe_bot : ↑(⊥ : IntermediateField F E) = Set.range (algebraMap F E) := rfl - -theorem mem_bot {x : E} : x ∈ (⊥ : IntermediateField F E) ↔ x ∈ Set.range (algebraMap F E) := - Iff.rfl - -@[simp] -theorem bot_toSubalgebra : (⊥ : IntermediateField F E).toSubalgebra = ⊥ := rfl - -theorem bot_toSubfield : (⊥ : IntermediateField F E).toSubfield = (algebraMap F E).fieldRange := - rfl - -@[simp] -theorem coe_top : ↑(⊤ : IntermediateField F E) = (Set.univ : Set E) := - rfl - -@[simp] -theorem mem_top {x : E} : x ∈ (⊤ : IntermediateField F E) := - trivial - -@[simp] -theorem top_toSubalgebra : (⊤ : IntermediateField F E).toSubalgebra = ⊤ := - rfl - -@[simp] -theorem top_toSubfield : (⊤ : IntermediateField F E).toSubfield = ⊤ := - rfl - -@[simp, norm_cast] -theorem coe_inf (S T : IntermediateField F E) : (↑(S ⊓ T) : Set E) = (S : Set E) ∩ T := - rfl - -@[simp] -theorem mem_inf {S T : IntermediateField F E} {x : E} : x ∈ S ⊓ T ↔ x ∈ S ∧ x ∈ T := - Iff.rfl - -@[simp] -theorem inf_toSubalgebra (S T : IntermediateField F E) : - (S ⊓ T).toSubalgebra = S.toSubalgebra ⊓ T.toSubalgebra := - rfl - -@[simp] -theorem inf_toSubfield (S T : IntermediateField F E) : - (S ⊓ T).toSubfield = S.toSubfield ⊓ T.toSubfield := - rfl - -@[simp] -theorem sup_toSubfield (S T : IntermediateField F E) : - (S ⊔ T).toSubfield = S.toSubfield ⊔ T.toSubfield := by - rw [← S.toSubfield.closure_eq, ← T.toSubfield.closure_eq, ← Subfield.closure_union] - simp_rw [sup_def, adjoin_toSubfield, coe_toSubfield] - congr 1 - rw [Set.union_eq_right] - rintro _ ⟨x, rfl⟩ - exact Set.mem_union_left _ (algebraMap_mem S x) - -@[simp, norm_cast] -theorem coe_sInf (S : Set (IntermediateField F E)) : (↑(sInf S) : Set E) = - sInf ((fun (x : IntermediateField F E) => (x : Set E)) '' S) := - rfl - -@[simp] -theorem sInf_toSubalgebra (S : Set (IntermediateField F E)) : - (sInf S).toSubalgebra = sInf (toSubalgebra '' S) := - SetLike.coe_injective <| by simp [Set.sUnion_image] - -@[simp] -theorem sInf_toSubfield (S : Set (IntermediateField F E)) : - (sInf S).toSubfield = sInf (toSubfield '' S) := - SetLike.coe_injective <| by simp [Set.sUnion_image] - -@[simp] -theorem sSup_toSubfield (S : Set (IntermediateField F E)) (hS : S.Nonempty) : - (sSup S).toSubfield = sSup (toSubfield '' S) := by - have h : toSubfield '' S = Subfield.closure '' (SetLike.coe '' S) := by - rw [Set.image_image] - congr! with x - exact x.toSubfield.closure_eq.symm - rw [h, sSup_image, ← Subfield.closure_sUnion, sSup_def, adjoin_toSubfield] - congr 1 - rw [Set.union_eq_right] - rintro _ ⟨x, rfl⟩ - obtain ⟨y, hy⟩ := hS - simp only [Set.mem_sUnion, Set.mem_image, exists_exists_and_eq_and, SetLike.mem_coe] - exact ⟨y, hy, algebraMap_mem y x⟩ - -@[simp, norm_cast] -theorem coe_iInf {ι : Sort*} (S : ι → IntermediateField F E) : (↑(iInf S) : Set E) = ⋂ i, S i := by - simp [iInf] - -@[simp] -theorem iInf_toSubalgebra {ι : Sort*} (S : ι → IntermediateField F E) : - (iInf S).toSubalgebra = ⨅ i, (S i).toSubalgebra := - SetLike.coe_injective <| by simp [iInf] - -@[simp] -theorem iInf_toSubfield {ι : Sort*} (S : ι → IntermediateField F E) : - (iInf S).toSubfield = ⨅ i, (S i).toSubfield := - SetLike.coe_injective <| by simp [iInf] - -@[simp] -theorem iSup_toSubfield {ι : Sort*} [Nonempty ι] (S : ι → IntermediateField F E) : - (iSup S).toSubfield = ⨆ i, (S i).toSubfield := by - simp only [iSup, Set.range_nonempty, sSup_toSubfield, ← Set.range_comp, Function.comp_def] - -/-- Construct an algebra isomorphism from an equality of intermediate fields -/ -@[simps! apply] -def equivOfEq {S T : IntermediateField F E} (h : S = T) : S ≃ₐ[F] T := - Subalgebra.equivOfEq _ _ (congr_arg toSubalgebra h) - -@[simp] -theorem equivOfEq_symm {S T : IntermediateField F E} (h : S = T) : - (equivOfEq h).symm = equivOfEq h.symm := - rfl - -@[simp] -theorem equivOfEq_rfl (S : IntermediateField F E) : equivOfEq (rfl : S = S) = AlgEquiv.refl := by - ext; rfl - -@[simp] -theorem equivOfEq_trans {S T U : IntermediateField F E} (hST : S = T) (hTU : T = U) : - (equivOfEq hST).trans (equivOfEq hTU) = equivOfEq (hST.trans hTU) := - rfl - -variable (F E) - -/-- The bottom intermediate_field is isomorphic to the field. -/ -noncomputable def botEquiv : (⊥ : IntermediateField F E) ≃ₐ[F] F := - (Subalgebra.equivOfEq _ _ bot_toSubalgebra).trans (Algebra.botEquiv F E) - -variable {F E} - --- Porting note: this was tagged `simp`. -theorem botEquiv_def (x : F) : botEquiv F E (algebraMap F (⊥ : IntermediateField F E) x) = x := by - simp - -@[simp] -theorem botEquiv_symm (x : F) : (botEquiv F E).symm x = algebraMap F _ x := - rfl - -noncomputable instance algebraOverBot : Algebra (⊥ : IntermediateField F E) F := - (IntermediateField.botEquiv F E).toAlgHom.toRingHom.toAlgebra - -theorem coe_algebraMap_over_bot : - (algebraMap (⊥ : IntermediateField F E) F : (⊥ : IntermediateField F E) → F) = - IntermediateField.botEquiv F E := - rfl - -instance isScalarTower_over_bot : IsScalarTower (⊥ : IntermediateField F E) F E := - IsScalarTower.of_algebraMap_eq - (by - intro x - obtain ⟨y, rfl⟩ := (botEquiv F E).symm.surjective x - rw [coe_algebraMap_over_bot, (botEquiv F E).apply_symm_apply, botEquiv_symm, - IsScalarTower.algebraMap_apply F (⊥ : IntermediateField F E) E]) - -/-- The top `IntermediateField` is isomorphic to the field. - -This is the intermediate field version of `Subalgebra.topEquiv`. -/ -@[simps!] -def topEquiv : (⊤ : IntermediateField F E) ≃ₐ[F] E := - Subalgebra.topEquiv - --- Porting note: this theorem is now generated by the `@[simps!]` above. - -section RestrictScalars - -@[simp] -theorem restrictScalars_bot_eq_self (K : IntermediateField F E) : - (⊥ : IntermediateField K E).restrictScalars _ = K := - SetLike.coe_injective Subtype.range_coe - -variable {K : Type*} [Field K] [Algebra K E] [Algebra K F] [IsScalarTower K F E] - -@[simp] -theorem restrictScalars_top : (⊤ : IntermediateField F E).restrictScalars K = ⊤ := - rfl - -variable (K) -variable (L L' : IntermediateField F E) - -theorem restrictScalars_sup : - L.restrictScalars K ⊔ L'.restrictScalars K = (L ⊔ L').restrictScalars K := - toSubfield_injective (by simp) - -theorem restrictScalars_inf : - L.restrictScalars K ⊓ L'.restrictScalars K = (L ⊓ L').restrictScalars K := rfl - -end RestrictScalars - -variable {K : Type*} [Field K] [Algebra F K] - -@[simp] -theorem map_bot (f : E →ₐ[F] K) : - IntermediateField.map f ⊥ = ⊥ := - toSubalgebra_injective <| Algebra.map_bot _ - -theorem map_sup (s t : IntermediateField F E) (f : E →ₐ[F] K) : (s ⊔ t).map f = s.map f ⊔ t.map f := - (gc_map_comap f).l_sup - -theorem map_iSup {ι : Sort*} (f : E →ₐ[F] K) (s : ι → IntermediateField F E) : - (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 - -theorem _root_.AlgHom.map_fieldRange {L : Type*} [Field L] [Algebra F L] - (f : E →ₐ[F] K) (g : K →ₐ[F] L) : f.fieldRange.map g = (g.comp f).fieldRange := - SetLike.ext' (Set.range_comp g f).symm - -theorem _root_.AlgHom.fieldRange_eq_top {f : E →ₐ[F] K} : - f.fieldRange = ⊤ ↔ Function.Surjective f := - SetLike.ext'_iff.trans Set.range_eq_univ - -@[simp] -theorem _root_.AlgEquiv.fieldRange_eq_top (f : E ≃ₐ[F] K) : - (f : E →ₐ[F] K).fieldRange = ⊤ := - AlgHom.fieldRange_eq_top.mpr f.surjective - -end Lattice - -section equivMap - -variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] - {K : Type*} [Field K] [Algebra F K] (L : IntermediateField F E) (f : E →ₐ[F] K) - -theorem fieldRange_comp_val : (f.comp L.val).fieldRange = L.map f := toSubalgebra_injective <| by - rw [toSubalgebra_map, AlgHom.fieldRange_toSubalgebra, AlgHom.range_comp, range_val] - -/-- An intermediate field is isomorphic to its image under an `AlgHom` -(which is automatically injective) -/ -noncomputable def equivMap : L ≃ₐ[F] L.map f := - (AlgEquiv.ofInjective _ (f.comp L.val).injective).trans (equivOfEq (fieldRange_comp_val L f)) - -@[simp] -theorem coe_equivMap_apply (x : L) : ↑(equivMap L f x) = f x := rfl - -end equivMap - section AdjoinDef variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] (S : Set E) -theorem adjoin_eq_range_algebraMap_adjoin : - (adjoin F S : Set E) = Set.range (algebraMap (adjoin F S) E) := - Subtype.range_coe.symm - -theorem adjoin.algebraMap_mem (x : F) : algebraMap F E x ∈ adjoin F S := - IntermediateField.algebraMap_mem (adjoin F S) x - -theorem adjoin.range_algebraMap_subset : Set.range (algebraMap F E) ⊆ adjoin F S := by - intro x hx - cases' hx with f hf - rw [← hf] - exact adjoin.algebraMap_mem F S f - -instance adjoin.fieldCoe : CoeTC F (adjoin F S) where - coe x := ⟨algebraMap F E x, adjoin.algebraMap_mem F S x⟩ - -theorem subset_adjoin : S ⊆ adjoin F S := fun _ hx => Subfield.subset_closure (Or.inr hx) - -instance adjoin.setCoe : CoeTC S (adjoin F S) where coe x := ⟨x, subset_adjoin F S (Subtype.mem x)⟩ - -@[mono] -theorem adjoin.mono (T : Set E) (h : S ⊆ T) : adjoin F S ≤ adjoin F T := - GaloisConnection.monotone_l gc h - -theorem adjoin_contains_field_as_subfield (F : Subfield E) : (F : Set E) ⊆ adjoin F S := fun x hx => - adjoin.algebraMap_mem F S ⟨x, hx⟩ - -theorem subset_adjoin_of_subset_left {F : Subfield E} {T : Set E} (HT : T ⊆ F) : T ⊆ adjoin F S := - fun x hx => (adjoin F S).algebraMap_mem ⟨x, HT hx⟩ - -theorem subset_adjoin_of_subset_right {T : Set E} (H : T ⊆ S) : T ⊆ adjoin F S := fun _ hx => - subset_adjoin F S (H hx) - -@[simp] -theorem adjoin_empty (F E : Type*) [Field F] [Field E] [Algebra F E] : adjoin F (∅ : Set E) = ⊥ := - eq_bot_iff.mpr (adjoin_le_iff.mpr (Set.empty_subset _)) - -@[simp] -theorem adjoin_univ (F E : Type*) [Field F] [Field E] [Algebra F E] : - adjoin F (Set.univ : Set E) = ⊤ := - eq_top_iff.mpr <| subset_adjoin _ _ - -/-- If `K` is a field with `F ⊆ K` and `S ⊆ K` then `adjoin F S ≤ K`. -/ -theorem adjoin_le_subfield {K : Subfield E} (HF : Set.range (algebraMap F E) ⊆ K) (HS : S ⊆ K) : - (adjoin F S).toSubfield ≤ K := by - apply Subfield.closure_le.mpr - rw [Set.union_subset_iff] - exact ⟨HF, HS⟩ - -theorem adjoin_subset_adjoin_iff {F' : Type*} [Field F'] [Algebra F' E] {S S' : Set E} : - (adjoin F S : Set E) ⊆ adjoin F' S' ↔ - Set.range (algebraMap F E) ⊆ adjoin F' S' ∧ S ⊆ adjoin F' S' := - ⟨fun h => ⟨(adjoin.range_algebraMap_subset _ _).trans h, - (subset_adjoin _ _).trans h⟩, fun ⟨hF, hS⟩ => - (Subfield.closure_le (t := (adjoin F' S').toSubfield)).mpr (Set.union_subset hF hS)⟩ - -/-- `F[S][T] = F[S ∪ T]` -/ -theorem adjoin_adjoin_left (T : Set E) : - (adjoin (adjoin F S) T).restrictScalars _ = adjoin F (S ∪ T) := by - rw [SetLike.ext'_iff] - change (adjoin (adjoin F S) T : Set E) = _ - apply subset_antisymm <;> rw [adjoin_subset_adjoin_iff] <;> constructor - · rintro _ ⟨⟨x, hx⟩, rfl⟩; exact adjoin.mono _ _ _ Set.subset_union_left hx - · exact subset_adjoin_of_subset_right _ _ Set.subset_union_right - · exact Set.range_subset_iff.mpr fun f ↦ Subfield.subset_closure (.inl ⟨f, rfl⟩) - · exact Set.union_subset - (fun x hx ↦ Subfield.subset_closure <| .inl ⟨⟨x, Subfield.subset_closure (.inr hx)⟩, rfl⟩) - (fun x hx ↦ Subfield.subset_closure <| .inr hx) - -@[simp] -theorem adjoin_insert_adjoin (x : E) : - adjoin F (insert x (adjoin F S : Set E)) = adjoin F (insert x S) := - le_antisymm - (adjoin_le_iff.mpr - (Set.insert_subset_iff.mpr - ⟨subset_adjoin _ _ (Set.mem_insert _ _), - adjoin_le_iff.mpr (subset_adjoin_of_subset_right _ _ (Set.subset_insert _ _))⟩)) - (adjoin.mono _ _ _ (Set.insert_subset_insert (subset_adjoin _ _))) - -/-- `F[S][T] = F[T][S]` -/ -theorem adjoin_adjoin_comm (T : Set E) : - (adjoin (adjoin F S) T).restrictScalars F = (adjoin (adjoin F T) S).restrictScalars F := by - rw [adjoin_adjoin_left, adjoin_adjoin_left, Set.union_comm] - -theorem adjoin_map {E' : Type*} [Field E'] [Algebra F E'] (f : E →ₐ[F] E') : - (adjoin F S).map f = adjoin F (f '' S) := - le_antisymm - (map_le_iff_le_comap.mpr <| adjoin_le_iff.mpr fun x hx ↦ subset_adjoin _ _ ⟨x, hx, rfl⟩) - (adjoin_le_iff.mpr <| Set.monotone_image <| subset_adjoin _ _) - -@[simp] -theorem lift_adjoin (K : IntermediateField F E) (S : Set K) : - lift (adjoin F S) = adjoin F (Subtype.val '' S) := - adjoin_map _ _ _ - -theorem lift_adjoin_simple (K : IntermediateField F E) (α : K) : - lift (adjoin F {α}) = adjoin F {α.1} := by - simp only [lift_adjoin, Set.image_singleton] - -@[simp] -theorem lift_bot (K : IntermediateField F E) : - lift (F := K) ⊥ = ⊥ := map_bot _ - -@[simp] -theorem lift_top (K : IntermediateField F E) : - lift (F := K) ⊤ = K := by rw [lift, ← AlgHom.fieldRange_eq_map, fieldRange_val] - -@[simp] -theorem adjoin_self (K : IntermediateField F E) : - adjoin F K = K := le_antisymm (adjoin_le_iff.2 fun _ ↦ id) (subset_adjoin F _) - -theorem restrictScalars_adjoin (K : IntermediateField F E) (S : Set E) : - restrictScalars F (adjoin K S) = adjoin F (K ∪ S) := by - rw [← adjoin_self _ K, adjoin_adjoin_left, adjoin_self _ K] - -variable {F} in -theorem extendScalars_adjoin {K : IntermediateField F E} {S : Set E} (h : K ≤ adjoin F S) : - extendScalars h = adjoin K S := restrictScalars_injective F <| by - rw [extendScalars_restrictScalars, restrictScalars_adjoin] - exact le_antisymm (adjoin.mono F S _ Set.subset_union_right) <| adjoin_le_iff.2 <| - Set.union_subset h (subset_adjoin F S) - -theorem adjoin_union {S T : Set E} : adjoin F (S ∪ T) = adjoin F S ⊔ adjoin F T := - gc.l_sup - -theorem restrictScalars_adjoin_eq_sup (K : IntermediateField F E) (S : Set E) : - restrictScalars F (adjoin K S) = K ⊔ adjoin F S := by - rw [restrictScalars_adjoin, adjoin_union, adjoin_self] - -theorem adjoin_iUnion {ι} (f : ι → Set E) : adjoin F (⋃ i, f i) = ⨆ i, adjoin F (f i) := - gc.l_iSup - -theorem iSup_eq_adjoin {ι} (f : ι → IntermediateField F E) : - ⨆ i, f i = adjoin F (⋃ i, f i : Set E) := by - simp_rw [adjoin_iUnion, adjoin_self] - -variable {F} in -/-- If `E / L / F` and `E / L' / F` are two field extension towers, `L ≃ₐ[F] L'` is an isomorphism -compatible with `E / L` and `E / L'`, then for any subset `S` of `E`, `L(S)` and `L'(S)` are -equal as intermediate fields of `E / F`. -/ -theorem restrictScalars_adjoin_of_algEquiv - {L L' : Type*} [Field L] [Field L'] - [Algebra F L] [Algebra L E] [Algebra F L'] [Algebra L' E] - [IsScalarTower F L E] [IsScalarTower F L' E] (i : L ≃ₐ[F] L') - (hi : algebraMap L E = (algebraMap L' E) ∘ i) (S : Set E) : - (adjoin L S).restrictScalars F = (adjoin L' S).restrictScalars F := by - apply_fun toSubfield using (fun K K' h ↦ by - ext x; change x ∈ K.toSubfield ↔ x ∈ K'.toSubfield; rw [h]) - change Subfield.closure _ = Subfield.closure _ - congr - ext x - exact ⟨fun ⟨y, h⟩ ↦ ⟨i y, by rw [← h, hi]; rfl⟩, - fun ⟨y, h⟩ ↦ ⟨i.symm y, by rw [← h, hi, Function.comp_apply, AlgEquiv.apply_symm_apply]⟩⟩ - theorem algebra_adjoin_le_adjoin : Algebra.adjoin F S ≤ (adjoin F S).toSubalgebra := Algebra.adjoin_le (subset_adjoin _ _) @@ -545,112 +78,15 @@ theorem eq_adjoin_of_eq_algebra_adjoin (K : IntermediateField F E) theorem adjoin_eq_top_of_algebra (hS : Algebra.adjoin F S = ⊤) : adjoin F S = ⊤ := top_le_iff.mp (hS.symm.trans_le <| algebra_adjoin_le_adjoin F S) -@[elab_as_elim] -theorem adjoin_induction {s : Set E} {p : ∀ x ∈ adjoin F s, Prop} - (mem : ∀ x hx, p x (subset_adjoin _ _ hx)) - (algebraMap : ∀ x, p (algebraMap F E x) (algebraMap_mem _ _)) - (add : ∀ x y hx hy, p x hx → p y hy → p (x + y) (add_mem hx hy)) - (inv : ∀ x hx, p x hx → p x⁻¹ (inv_mem hx)) - (mul : ∀ x y hx hy, p x hx → p y hy → p (x * y) (mul_mem hx hy)) - {x} (h : x ∈ adjoin F s) : p x h := - Subfield.closure_induction - (fun x hx ↦ Or.casesOn hx (fun ⟨x, hx⟩ ↦ hx ▸ algebraMap x) (mem x)) - (by simp_rw [← (_root_.algebraMap F E).map_one]; exact algebraMap 1) add - (fun x _ h ↦ by - simp_rw [← neg_one_smul F x, Algebra.smul_def]; exact mul _ _ _ _ (algebraMap _) h) inv mul h - -section - -variable {K : Type*} [Semiring K] [Algebra F K] - -theorem adjoin_algHom_ext {s : Set E} ⦃φ₁ φ₂ : adjoin F s →ₐ[F] K⦄ - (h : ∀ x hx, φ₁ ⟨x, subset_adjoin _ _ hx⟩ = φ₂ ⟨x, subset_adjoin _ _ hx⟩) : - φ₁ = φ₂ := - AlgHom.ext fun ⟨x, hx⟩ ↦ adjoin_induction _ h (fun _ ↦ φ₂.commutes _ ▸ φ₁.commutes _) - (fun _ _ _ _ h₁ h₂ ↦ by convert congr_arg₂ (· + ·) h₁ h₂ <;> rw [← map_add] <;> rfl) - (fun _ _ ↦ eq_on_inv₀ _ _) - (fun _ _ _ _ h₁ h₂ ↦ by convert congr_arg₂ (· * ·) h₁ h₂ <;> rw [← map_mul] <;> rfl) - hx - -theorem algHom_ext_of_eq_adjoin {S : IntermediateField F E} {s : Set E} (hS : S = adjoin F s) - ⦃φ₁ φ₂ : S →ₐ[F] K⦄ - (h : ∀ x hx, φ₁ ⟨x, hS.ge (subset_adjoin _ _ hx)⟩ = φ₂ ⟨x, hS.ge (subset_adjoin _ _ hx)⟩) : - φ₁ = φ₂ := by - subst hS; exact adjoin_algHom_ext F h - -end - -/- Porting note (kmill): this notation is replacing the typeclass-based one I had previously -written, and it gives true `{x₁, x₂, ..., xₙ}` sets in the `adjoin` term. -/ - -open Lean in -/-- Supporting function for the `F⟮x₁,x₂,...,xₙ⟯` adjunction notation. -/ -private partial def mkInsertTerm {m : Type → Type} [Monad m] [MonadQuotation m] - (xs : TSyntaxArray `term) : m Term := run 0 where - run (i : Nat) : m Term := do - if i + 1 == xs.size then - ``(singleton $(xs[i]!)) - else if i < xs.size then - ``(insert $(xs[i]!) $(← run (i + 1))) - else - ``(EmptyCollection.emptyCollection) - -/-- If `x₁ x₂ ... xₙ : E` then `F⟮x₁,x₂,...,xₙ⟯` is the `IntermediateField F E` -generated by these elements. -/ -scoped macro:max K:term "⟮" xs:term,* "⟯" : term => do ``(adjoin $K $(← mkInsertTerm xs.getElems)) - -open Lean PrettyPrinter.Delaborator SubExpr in -@[app_delab IntermediateField.adjoin] -partial def delabAdjoinNotation : Delab := whenPPOption getPPNotation do - let e ← getExpr - guard <| e.isAppOfArity ``adjoin 6 - let F ← withNaryArg 0 delab - let xs ← withNaryArg 5 delabInsertArray - `($F⟮$(xs.toArray),*⟯) -where - delabInsertArray : DelabM (List Term) := do - let e ← getExpr - if e.isAppOfArity ``EmptyCollection.emptyCollection 2 then - return [] - else if e.isAppOfArity ``singleton 4 then - let x ← withNaryArg 3 delab - return [x] - else if e.isAppOfArity ``insert 5 then - let x ← withNaryArg 3 delab - let xs ← withNaryArg 4 delabInsertArray - return x :: xs - else failure - section AdjoinSimple variable (α : E) --- Porting note: in all the theorems below, mathport translated `F⟮α⟯` into `F⟮⟯`. -theorem mem_adjoin_simple_self : α ∈ F⟮α⟯ := - subset_adjoin F {α} (Set.mem_singleton α) - -/-- generator of `F⟮α⟯` -/ -def AdjoinSimple.gen : F⟮α⟯ := - ⟨α, mem_adjoin_simple_self F α⟩ - -@[simp] -theorem AdjoinSimple.coe_gen : (AdjoinSimple.gen F α : E) = α := - rfl - -theorem AdjoinSimple.algebraMap_gen : algebraMap F⟮α⟯ E (AdjoinSimple.gen F α) = α := - rfl - @[simp] theorem AdjoinSimple.isIntegral_gen : IsIntegral F (AdjoinSimple.gen F α) ↔ IsIntegral F α := by conv_rhs => rw [← AdjoinSimple.algebraMap_gen F α] rw [isIntegral_algebraMap_iff (algebraMap F⟮α⟯ E).injective] -theorem adjoin_simple_adjoin_simple (β : E) : F⟮α⟯⟮β⟯.restrictScalars F = F⟮α, β⟯ := - adjoin_adjoin_left _ _ _ - -theorem adjoin_simple_comm (β : E) : F⟮α⟯⟮β⟯.restrictScalars F = F⟮β⟯⟮α⟯.restrictScalars F := - adjoin_adjoin_comm _ _ _ - variable {F} {α} theorem adjoin_algebraic_toSubalgebra {S : Set E} (hS : ∀ x ∈ S, IsAlgebraic F x) : @@ -879,13 +315,6 @@ end Tower open Set CompleteLattice -/- Porting note: this was tagged `simp`, but the LHS can be simplified now that the notation -has been improved. -/ -theorem adjoin_simple_le_iff {K : IntermediateField F E} : F⟮α⟯ ≤ K ↔ α ∈ K := by simp - -theorem biSup_adjoin_simple : ⨆ x ∈ S, F⟮x⟯ = adjoin F S := by - rw [← iSup_subtype'', ← gc.l_iSup, iSup_subtype'']; congr; exact S.biUnion_of_singleton - /-- Adjoining a single element is compact in the lattice of intermediate fields. -/ theorem adjoin_simple_isCompactElement (x : E) : IsCompactElement F⟮x⟯ := by simp_rw [isCompactElement_iff_le_of_directed_sSup_le, @@ -956,33 +385,6 @@ section AdjoinIntermediateFieldLattice variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] {α : E} {S : Set E} -@[simp] -theorem adjoin_eq_bot_iff : adjoin F S = ⊥ ↔ S ⊆ (⊥ : IntermediateField F E) := by - rw [eq_bot_iff, adjoin_le_iff] - -/- Porting note: this was tagged `simp`. -/ -theorem adjoin_simple_eq_bot_iff : F⟮α⟯ = ⊥ ↔ α ∈ (⊥ : IntermediateField F E) := by - simp - -@[simp] -theorem adjoin_zero : F⟮(0 : E)⟯ = ⊥ := - adjoin_simple_eq_bot_iff.mpr (zero_mem ⊥) - -@[simp] -theorem adjoin_one : F⟮(1 : E)⟯ = ⊥ := - adjoin_simple_eq_bot_iff.mpr (one_mem ⊥) - -@[simp] -theorem adjoin_intCast (n : ℤ) : F⟮(n : E)⟯ = ⊥ := by - exact adjoin_simple_eq_bot_iff.mpr (intCast_mem ⊥ n) - -@[simp] -theorem adjoin_natCast (n : ℕ) : F⟮(n : E)⟯ = ⊥ := - adjoin_simple_eq_bot_iff.mpr (natCast_mem ⊥ n) - -@[deprecated (since := "2024-04-05")] alias adjoin_int := adjoin_intCast -@[deprecated (since := "2024-04-05")] alias adjoin_nat := adjoin_natCast - section AdjoinRank open Module Module @@ -1353,36 +755,6 @@ section Induction variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] -/-- An intermediate field `S` is finitely generated if there exists `t : Finset E` such that -`IntermediateField.adjoin F t = S`. -/ -@[stacks 09FZ "second part"] -def FG (S : IntermediateField F E) : Prop := - ∃ t : Finset E, adjoin F ↑t = S - -theorem fg_adjoin_finset (t : Finset E) : (adjoin F (↑t : Set E)).FG := - ⟨t, rfl⟩ - -theorem fg_def {S : IntermediateField F E} : S.FG ↔ ∃ t : Set E, Set.Finite t ∧ adjoin F t = S := - Iff.symm Set.exists_finite_iff_finset - -theorem fg_adjoin_of_finite {t : Set E} (h : Set.Finite t) : (adjoin F t).FG := - fg_def.mpr ⟨t, h, rfl⟩ - -theorem fg_bot : (⊥ : IntermediateField F E).FG := - -- Porting note: was `⟨∅, adjoin_empty F E⟩` - ⟨∅, by simp only [Finset.coe_empty, adjoin_empty]⟩ - -theorem fg_sup {S T : IntermediateField F E} (hS : S.FG) (hT : T.FG) : (S ⊔ T).FG := by - obtain ⟨s, rfl⟩ := hS; obtain ⟨t, rfl⟩ := hT - classical rw [← adjoin_union, ← Finset.coe_union] - exact fg_adjoin_finset _ - -theorem fg_iSup {ι : Sort*} [Finite ι] {S : ι → IntermediateField F E} (h : ∀ i, (S i).FG) : - (⨆ i, S i).FG := by - choose s hs using h - simp_rw [← hs, ← adjoin_iUnion] - exact fg_adjoin_of_finite (Set.finite_iUnion fun _ ↦ Finset.finite_toSet _) - theorem fg_of_fg_toSubalgebra (S : IntermediateField F E) (h : S.toSubalgebra.FG) : S.FG := by cases' h with t ht exact ⟨t, (eq_adjoin_of_eq_algebra_adjoin _ _ _ ht.symm).symm⟩ @@ -1392,21 +764,6 @@ theorem fg_of_fg_toSubalgebra (S : IntermediateField F E) (h : S.toSubalgebra.FG theorem fg_of_noetherian (S : IntermediateField F E) [IsNoetherian F E] : S.FG := S.fg_of_fg_toSubalgebra S.toSubalgebra.fg_of_noetherian -theorem induction_on_adjoin_finset (S : Finset E) (P : IntermediateField F E → Prop) (base : P ⊥) - (ih : ∀ (K : IntermediateField F E), ∀ x ∈ S, P K → P (K⟮x⟯.restrictScalars F)) : - P (adjoin F S) := by - classical - refine Finset.induction_on' S ?_ (fun ha _ _ h => ?_) - · simp [base] - · rw [Finset.coe_insert, Set.insert_eq, Set.union_comm, ← adjoin_adjoin_left] - exact ih (adjoin F _) _ ha h - -theorem induction_on_adjoin_fg (P : IntermediateField F E → Prop) (base : P ⊥) - (ih : ∀ (K : IntermediateField F E) (x : E), P K → P (K⟮x⟯.restrictScalars F)) - (K : IntermediateField F E) (hK : K.FG) : P K := by - obtain ⟨S, rfl⟩ := hK - exact induction_on_adjoin_finset S P base fun K x _ hK => ih K x hK - theorem induction_on_adjoin [FiniteDimensional F E] (P : IntermediateField F E → Prop) (base : P ⊥) (ih : ∀ (K : IntermediateField F E) (x : E), P K → P (K⟮x⟯.restrictScalars F)) (K : IntermediateField F E) : P K := @@ -1557,85 +914,6 @@ theorem equivAdjoinSimple_symm_gen (pb : PowerBasis K L) : end PowerBasis -namespace IntermediateField - -variable {K L L' : Type*} [Field K] [Field L] [Field L'] [Algebra K L] [Algebra K L'] - -theorem map_comap_eq (f : L →ₐ[K] L') (S : IntermediateField K L') : - (S.comap f).map f = S ⊓ f.fieldRange := - SetLike.coe_injective Set.image_preimage_eq_inter_range - -theorem map_comap_eq_self {f : L →ₐ[K] L'} {S : IntermediateField K L'} (h : S ≤ f.fieldRange) : - (S.comap f).map f = S := by - simpa only [inf_of_le_left h] using map_comap_eq f S - -theorem map_comap_eq_self_of_surjective {f : L →ₐ[K] L'} (hf : Function.Surjective f) - (S : IntermediateField K L') : (S.comap f).map f = S := - SetLike.coe_injective (Set.image_preimage_eq _ hf) - -theorem comap_map (f : L →ₐ[K] L') (S : IntermediateField K L) : (S.map f).comap f = S := - SetLike.coe_injective (Set.preimage_image_eq _ f.injective) - -end IntermediateField - -section ExtendScalars - -variable {K : Type*} [Field K] {L : Type*} [Field L] [Algebra K L] - -namespace Subfield - -variable (F : Subfield L) - -@[simp] -theorem extendScalars_self : extendScalars (le_refl F) = ⊥ := by - ext x - rw [mem_extendScalars, IntermediateField.mem_bot] - refine ⟨fun h ↦ ⟨⟨x, h⟩, rfl⟩, ?_⟩ - rintro ⟨y, rfl⟩ - exact y.2 - -@[simp] -theorem extendScalars_top : extendScalars (le_top : F ≤ ⊤) = ⊤ := - IntermediateField.toSubfield_injective (by simp) - -variable {F} -variable {E E' : Subfield L} (h : F ≤ E) (h' : F ≤ E') - -theorem extendScalars_sup : - extendScalars h ⊔ extendScalars h' = extendScalars (le_sup_of_le_left h : F ≤ E ⊔ E') := - ((extendScalars.orderIso F).map_sup ⟨_, h⟩ ⟨_, h'⟩).symm - -theorem extendScalars_inf : extendScalars h ⊓ extendScalars h' = extendScalars (le_inf h h') := - ((extendScalars.orderIso F).map_inf ⟨_, h⟩ ⟨_, h'⟩).symm - -end Subfield - -namespace IntermediateField - -variable (F : IntermediateField K L) - -@[simp] -theorem extendScalars_self : extendScalars (le_refl F) = ⊥ := - restrictScalars_injective K (by simp) - -@[simp] -theorem extendScalars_top : extendScalars (le_top : F ≤ ⊤) = ⊤ := - restrictScalars_injective K (by simp) - -variable {F} -variable {E E' : IntermediateField K L} (h : F ≤ E) (h' : F ≤ E') - -theorem extendScalars_sup : - extendScalars h ⊔ extendScalars h' = extendScalars (le_sup_of_le_left h : F ≤ E ⊔ E') := - ((extendScalars.orderIso F).map_sup ⟨_, h⟩ ⟨_, h'⟩).symm - -theorem extendScalars_inf : extendScalars h ⊓ extendScalars h' = extendScalars (le_inf h h') := - ((extendScalars.orderIso F).map_inf ⟨_, h⟩ ⟨_, h'⟩).symm - -end IntermediateField - -end ExtendScalars - namespace IsFractionRing variable {F A K L : Type*} [Field F] [CommRing A] [Algebra F A] @@ -1706,5 +984,3 @@ theorem cardinalMk_adjoin_le {E : Type u} [Field E] [Algebra F E] (s : Set E) : simpa using lift_cardinalMk_adjoin_le F s end IntermediateField - -set_option linter.style.longFile 1800 diff --git a/Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean b/Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean new file mode 100644 index 0000000000000..a0ebf9abfe400 --- /dev/null +++ b/Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean @@ -0,0 +1,765 @@ +/- +Copyright (c) 2020 Thomas Browning, Patrick Lutz. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Thomas Browning, Patrick Lutz +-/ +import Mathlib.FieldTheory.IntermediateField.Basic + +/-! +# Adjoining Elements to Fields + +In this file we introduce the notion of adjoining elements to fields. +This isn't quite the same as adjoining elements to rings. +For example, `Algebra.adjoin K {x}` might not include `x⁻¹`. + +## Notation + + - `F⟮α⟯`: adjoin a single element `α` to `F` (in scope `IntermediateField`). +-/ + +open Module Polynomial + +namespace IntermediateField + +section AdjoinDef + +variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] (S : Set E) + +-- Porting note: not adding `neg_mem'` causes an error. +/-- `adjoin F S` extends a field `F` by adjoining a set `S ⊆ E`. -/ +@[stacks 09FZ "first part"] +def adjoin : IntermediateField F E := + { Subfield.closure (Set.range (algebraMap F E) ∪ S) with + algebraMap_mem' := fun x => Subfield.subset_closure (Or.inl (Set.mem_range_self x)) } + +@[simp] +theorem adjoin_toSubfield : + (adjoin F S).toSubfield = Subfield.closure (Set.range (algebraMap F E) ∪ S) := rfl + +end AdjoinDef + +section Lattice + +variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] + +@[simp] +theorem adjoin_le_iff {S : Set E} {T : IntermediateField F E} : adjoin F S ≤ T ↔ S ⊆ T := + ⟨fun H => le_trans (le_trans Set.subset_union_right Subfield.subset_closure) H, fun H => + (@Subfield.closure_le E _ (Set.range (algebraMap F E) ∪ S) T.toSubfield).mpr + (Set.union_subset (IntermediateField.set_range_subset T) H)⟩ + +theorem gc : GaloisConnection (adjoin F : Set E → IntermediateField F E) + (fun (x : IntermediateField F E) => (x : Set E)) := fun _ _ => + adjoin_le_iff + +/-- Galois insertion between `adjoin` and `coe`. -/ +def gi : GaloisInsertion (adjoin F : Set E → IntermediateField F E) + (fun (x : IntermediateField F E) => (x : Set E)) where + choice s hs := (adjoin F s).copy s <| le_antisymm (gc.le_u_l s) hs + gc := IntermediateField.gc + le_l_u S := (IntermediateField.gc (S : Set E) (adjoin F S)).1 <| le_rfl + choice_eq _ _ := copy_eq _ _ _ + +instance : CompleteLattice (IntermediateField F E) where + __ := GaloisInsertion.liftCompleteLattice IntermediateField.gi + bot := + { toSubalgebra := ⊥ + inv_mem' := by rintro x ⟨r, rfl⟩; exact ⟨r⁻¹, map_inv₀ _ _⟩ } + bot_le x := (bot_le : ⊥ ≤ x.toSubalgebra) + +theorem sup_def (S T : IntermediateField F E) : S ⊔ T = adjoin F (S ∪ T : Set E) := rfl + +theorem sSup_def (S : Set (IntermediateField F E)) : + sSup S = adjoin F (⋃₀ (SetLike.coe '' S)) := rfl + +instance : Inhabited (IntermediateField F E) := + ⟨⊤⟩ + +instance : Unique (IntermediateField F F) := + { inferInstanceAs (Inhabited (IntermediateField F F)) with + uniq := fun _ ↦ toSubalgebra_injective <| Subsingleton.elim _ _ } + +theorem coe_bot : ↑(⊥ : IntermediateField F E) = Set.range (algebraMap F E) := rfl + +theorem mem_bot {x : E} : x ∈ (⊥ : IntermediateField F E) ↔ x ∈ Set.range (algebraMap F E) := + Iff.rfl + +@[simp] +theorem bot_toSubalgebra : (⊥ : IntermediateField F E).toSubalgebra = ⊥ := rfl + +theorem bot_toSubfield : (⊥ : IntermediateField F E).toSubfield = (algebraMap F E).fieldRange := + rfl + +@[simp] +theorem coe_top : ↑(⊤ : IntermediateField F E) = (Set.univ : Set E) := + rfl + +@[simp] +theorem mem_top {x : E} : x ∈ (⊤ : IntermediateField F E) := + trivial + +@[simp] +theorem top_toSubalgebra : (⊤ : IntermediateField F E).toSubalgebra = ⊤ := + rfl + +@[simp] +theorem top_toSubfield : (⊤ : IntermediateField F E).toSubfield = ⊤ := + rfl + +@[simp, norm_cast] +theorem coe_inf (S T : IntermediateField F E) : (↑(S ⊓ T) : Set E) = (S : Set E) ∩ T := + rfl + +@[simp] +theorem mem_inf {S T : IntermediateField F E} {x : E} : x ∈ S ⊓ T ↔ x ∈ S ∧ x ∈ T := + Iff.rfl + +@[simp] +theorem inf_toSubalgebra (S T : IntermediateField F E) : + (S ⊓ T).toSubalgebra = S.toSubalgebra ⊓ T.toSubalgebra := + rfl + +@[simp] +theorem inf_toSubfield (S T : IntermediateField F E) : + (S ⊓ T).toSubfield = S.toSubfield ⊓ T.toSubfield := + rfl + +@[simp] +theorem sup_toSubfield (S T : IntermediateField F E) : + (S ⊔ T).toSubfield = S.toSubfield ⊔ T.toSubfield := by + rw [← S.toSubfield.closure_eq, ← T.toSubfield.closure_eq, ← Subfield.closure_union] + simp_rw [sup_def, adjoin_toSubfield, coe_toSubfield] + congr 1 + rw [Set.union_eq_right] + rintro _ ⟨x, rfl⟩ + exact Set.mem_union_left _ (algebraMap_mem S x) + +@[simp, norm_cast] +theorem coe_sInf (S : Set (IntermediateField F E)) : (↑(sInf S) : Set E) = + sInf ((fun (x : IntermediateField F E) => (x : Set E)) '' S) := + rfl + +@[simp] +theorem sInf_toSubalgebra (S : Set (IntermediateField F E)) : + (sInf S).toSubalgebra = sInf (toSubalgebra '' S) := + SetLike.coe_injective <| by simp [Set.sUnion_image] + +@[simp] +theorem sInf_toSubfield (S : Set (IntermediateField F E)) : + (sInf S).toSubfield = sInf (toSubfield '' S) := + SetLike.coe_injective <| by simp [Set.sUnion_image] + +@[simp] +theorem sSup_toSubfield (S : Set (IntermediateField F E)) (hS : S.Nonempty) : + (sSup S).toSubfield = sSup (toSubfield '' S) := by + have h : toSubfield '' S = Subfield.closure '' (SetLike.coe '' S) := by + rw [Set.image_image] + congr! with x + exact x.toSubfield.closure_eq.symm + rw [h, sSup_image, ← Subfield.closure_sUnion, sSup_def, adjoin_toSubfield] + congr 1 + rw [Set.union_eq_right] + rintro _ ⟨x, rfl⟩ + obtain ⟨y, hy⟩ := hS + simp only [Set.mem_sUnion, Set.mem_image, exists_exists_and_eq_and, SetLike.mem_coe] + exact ⟨y, hy, algebraMap_mem y x⟩ + +@[simp, norm_cast] +theorem coe_iInf {ι : Sort*} (S : ι → IntermediateField F E) : (↑(iInf S) : Set E) = ⋂ i, S i := by + simp [iInf] + +@[simp] +theorem iInf_toSubalgebra {ι : Sort*} (S : ι → IntermediateField F E) : + (iInf S).toSubalgebra = ⨅ i, (S i).toSubalgebra := + SetLike.coe_injective <| by simp [iInf] + +@[simp] +theorem iInf_toSubfield {ι : Sort*} (S : ι → IntermediateField F E) : + (iInf S).toSubfield = ⨅ i, (S i).toSubfield := + SetLike.coe_injective <| by simp [iInf] + +@[simp] +theorem iSup_toSubfield {ι : Sort*} [Nonempty ι] (S : ι → IntermediateField F E) : + (iSup S).toSubfield = ⨆ i, (S i).toSubfield := by + simp only [iSup, Set.range_nonempty, sSup_toSubfield, ← Set.range_comp, Function.comp_def] + +/-- Construct an algebra isomorphism from an equality of intermediate fields -/ +@[simps! apply] +def equivOfEq {S T : IntermediateField F E} (h : S = T) : S ≃ₐ[F] T := + Subalgebra.equivOfEq _ _ (congr_arg toSubalgebra h) + +@[simp] +theorem equivOfEq_symm {S T : IntermediateField F E} (h : S = T) : + (equivOfEq h).symm = equivOfEq h.symm := + rfl + +@[simp] +theorem equivOfEq_rfl (S : IntermediateField F E) : equivOfEq (rfl : S = S) = AlgEquiv.refl := by + ext; rfl + +@[simp] +theorem equivOfEq_trans {S T U : IntermediateField F E} (hST : S = T) (hTU : T = U) : + (equivOfEq hST).trans (equivOfEq hTU) = equivOfEq (hST.trans hTU) := + rfl + +variable (F E) + +/-- The bottom intermediate_field is isomorphic to the field. -/ +noncomputable def botEquiv : (⊥ : IntermediateField F E) ≃ₐ[F] F := + (Subalgebra.equivOfEq _ _ bot_toSubalgebra).trans (Algebra.botEquiv F E) + +variable {F E} + +-- Porting note: this was tagged `simp`. +theorem botEquiv_def (x : F) : botEquiv F E (algebraMap F (⊥ : IntermediateField F E) x) = x := by + simp + +@[simp] +theorem botEquiv_symm (x : F) : (botEquiv F E).symm x = algebraMap F _ x := + rfl + +noncomputable instance algebraOverBot : Algebra (⊥ : IntermediateField F E) F := + (IntermediateField.botEquiv F E).toAlgHom.toRingHom.toAlgebra + +theorem coe_algebraMap_over_bot : + (algebraMap (⊥ : IntermediateField F E) F : (⊥ : IntermediateField F E) → F) = + IntermediateField.botEquiv F E := + rfl + +instance isScalarTower_over_bot : IsScalarTower (⊥ : IntermediateField F E) F E := + IsScalarTower.of_algebraMap_eq + (by + intro x + obtain ⟨y, rfl⟩ := (botEquiv F E).symm.surjective x + rw [coe_algebraMap_over_bot, (botEquiv F E).apply_symm_apply, botEquiv_symm, + IsScalarTower.algebraMap_apply F (⊥ : IntermediateField F E) E]) + +/-- The top `IntermediateField` is isomorphic to the field. + +This is the intermediate field version of `Subalgebra.topEquiv`. -/ +@[simps!] +def topEquiv : (⊤ : IntermediateField F E) ≃ₐ[F] E := + Subalgebra.topEquiv + +-- Porting note: this theorem is now generated by the `@[simps!]` above. + +section RestrictScalars + +@[simp] +theorem restrictScalars_bot_eq_self (K : IntermediateField F E) : + (⊥ : IntermediateField K E).restrictScalars _ = K := + SetLike.coe_injective Subtype.range_coe + +variable {K : Type*} [Field K] [Algebra K E] [Algebra K F] [IsScalarTower K F E] + +@[simp] +theorem restrictScalars_top : (⊤ : IntermediateField F E).restrictScalars K = ⊤ := + rfl + +variable (K) +variable (L L' : IntermediateField F E) + +theorem restrictScalars_sup : + L.restrictScalars K ⊔ L'.restrictScalars K = (L ⊔ L').restrictScalars K := + toSubfield_injective (by simp) + +theorem restrictScalars_inf : + L.restrictScalars K ⊓ L'.restrictScalars K = (L ⊓ L').restrictScalars K := rfl + +end RestrictScalars + +variable {K : Type*} [Field K] [Algebra F K] + +@[simp] +theorem map_bot (f : E →ₐ[F] K) : + IntermediateField.map f ⊥ = ⊥ := + toSubalgebra_injective <| Algebra.map_bot _ + +theorem map_sup (s t : IntermediateField F E) (f : E →ₐ[F] K) : (s ⊔ t).map f = s.map f ⊔ t.map f := + (gc_map_comap f).l_sup + +theorem map_iSup {ι : Sort*} (f : E →ₐ[F] K) (s : ι → IntermediateField F E) : + (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 + +theorem _root_.AlgHom.map_fieldRange {L : Type*} [Field L] [Algebra F L] + (f : E →ₐ[F] K) (g : K →ₐ[F] L) : f.fieldRange.map g = (g.comp f).fieldRange := + SetLike.ext' (Set.range_comp g f).symm + +theorem _root_.AlgHom.fieldRange_eq_top {f : E →ₐ[F] K} : + f.fieldRange = ⊤ ↔ Function.Surjective f := + SetLike.ext'_iff.trans Set.range_eq_univ + +@[simp] +theorem _root_.AlgEquiv.fieldRange_eq_top (f : E ≃ₐ[F] K) : + (f : E →ₐ[F] K).fieldRange = ⊤ := + AlgHom.fieldRange_eq_top.mpr f.surjective + +end Lattice + +section equivMap + +variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] + {K : Type*} [Field K] [Algebra F K] (L : IntermediateField F E) (f : E →ₐ[F] K) + +theorem fieldRange_comp_val : (f.comp L.val).fieldRange = L.map f := toSubalgebra_injective <| by + rw [toSubalgebra_map, AlgHom.fieldRange_toSubalgebra, AlgHom.range_comp, range_val] + +/-- An intermediate field is isomorphic to its image under an `AlgHom` +(which is automatically injective) -/ +noncomputable def equivMap : L ≃ₐ[F] L.map f := + (AlgEquiv.ofInjective _ (f.comp L.val).injective).trans (equivOfEq (fieldRange_comp_val L f)) + +@[simp] +theorem coe_equivMap_apply (x : L) : ↑(equivMap L f x) = f x := rfl + +end equivMap + +section AdjoinDef + +variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] (S : Set E) + +theorem adjoin_eq_range_algebraMap_adjoin : + (adjoin F S : Set E) = Set.range (algebraMap (adjoin F S) E) := + Subtype.range_coe.symm + +theorem adjoin.algebraMap_mem (x : F) : algebraMap F E x ∈ adjoin F S := + IntermediateField.algebraMap_mem (adjoin F S) x + +theorem adjoin.range_algebraMap_subset : Set.range (algebraMap F E) ⊆ adjoin F S := by + intro x hx + cases' hx with f hf + rw [← hf] + exact adjoin.algebraMap_mem F S f + +instance adjoin.fieldCoe : CoeTC F (adjoin F S) where + coe x := ⟨algebraMap F E x, adjoin.algebraMap_mem F S x⟩ + +theorem subset_adjoin : S ⊆ adjoin F S := fun _ hx => Subfield.subset_closure (Or.inr hx) + +instance adjoin.setCoe : CoeTC S (adjoin F S) where coe x := ⟨x, subset_adjoin F S (Subtype.mem x)⟩ + +@[mono] +theorem adjoin.mono (T : Set E) (h : S ⊆ T) : adjoin F S ≤ adjoin F T := + GaloisConnection.monotone_l gc h + +theorem adjoin_contains_field_as_subfield (F : Subfield E) : (F : Set E) ⊆ adjoin F S := fun x hx => + adjoin.algebraMap_mem F S ⟨x, hx⟩ + +theorem subset_adjoin_of_subset_left {F : Subfield E} {T : Set E} (HT : T ⊆ F) : T ⊆ adjoin F S := + fun x hx => (adjoin F S).algebraMap_mem ⟨x, HT hx⟩ + +theorem subset_adjoin_of_subset_right {T : Set E} (H : T ⊆ S) : T ⊆ adjoin F S := fun _ hx => + subset_adjoin F S (H hx) + +@[simp] +theorem adjoin_empty (F E : Type*) [Field F] [Field E] [Algebra F E] : adjoin F (∅ : Set E) = ⊥ := + eq_bot_iff.mpr (adjoin_le_iff.mpr (Set.empty_subset _)) + +@[simp] +theorem adjoin_univ (F E : Type*) [Field F] [Field E] [Algebra F E] : + adjoin F (Set.univ : Set E) = ⊤ := + eq_top_iff.mpr <| subset_adjoin _ _ + +/-- If `K` is a field with `F ⊆ K` and `S ⊆ K` then `adjoin F S ≤ K`. -/ +theorem adjoin_le_subfield {K : Subfield E} (HF : Set.range (algebraMap F E) ⊆ K) (HS : S ⊆ K) : + (adjoin F S).toSubfield ≤ K := by + apply Subfield.closure_le.mpr + rw [Set.union_subset_iff] + exact ⟨HF, HS⟩ + +theorem adjoin_subset_adjoin_iff {F' : Type*} [Field F'] [Algebra F' E] {S S' : Set E} : + (adjoin F S : Set E) ⊆ adjoin F' S' ↔ + Set.range (algebraMap F E) ⊆ adjoin F' S' ∧ S ⊆ adjoin F' S' := + ⟨fun h => ⟨(adjoin.range_algebraMap_subset _ _).trans h, + (subset_adjoin _ _).trans h⟩, fun ⟨hF, hS⟩ => + (Subfield.closure_le (t := (adjoin F' S').toSubfield)).mpr (Set.union_subset hF hS)⟩ + +/-- Adjoining S and then T is the same as adjoining `S ∪ T`. -/ +theorem adjoin_adjoin_left (T : Set E) : + (adjoin (adjoin F S) T).restrictScalars _ = adjoin F (S ∪ T) := by + rw [SetLike.ext'_iff] + change (adjoin (adjoin F S) T : Set E) = _ + apply subset_antisymm <;> rw [adjoin_subset_adjoin_iff] <;> constructor + · rintro _ ⟨⟨x, hx⟩, rfl⟩; exact adjoin.mono _ _ _ Set.subset_union_left hx + · exact subset_adjoin_of_subset_right _ _ Set.subset_union_right + · exact Set.range_subset_iff.mpr fun f ↦ Subfield.subset_closure (.inl ⟨f, rfl⟩) + · exact Set.union_subset + (fun x hx ↦ Subfield.subset_closure <| .inl ⟨⟨x, Subfield.subset_closure (.inr hx)⟩, rfl⟩) + (fun x hx ↦ Subfield.subset_closure <| .inr hx) + +@[simp] +theorem adjoin_insert_adjoin (x : E) : + adjoin F (insert x (adjoin F S : Set E)) = adjoin F (insert x S) := + le_antisymm + (adjoin_le_iff.mpr + (Set.insert_subset_iff.mpr + ⟨subset_adjoin _ _ (Set.mem_insert _ _), + adjoin_le_iff.mpr (subset_adjoin_of_subset_right _ _ (Set.subset_insert _ _))⟩)) + (adjoin.mono _ _ _ (Set.insert_subset_insert (subset_adjoin _ _))) + +/-- `F[S][T] = F[T][S]` -/ +theorem adjoin_adjoin_comm (T : Set E) : + (adjoin (adjoin F S) T).restrictScalars F = (adjoin (adjoin F T) S).restrictScalars F := by + rw [adjoin_adjoin_left, adjoin_adjoin_left, Set.union_comm] + +theorem adjoin_map {E' : Type*} [Field E'] [Algebra F E'] (f : E →ₐ[F] E') : + (adjoin F S).map f = adjoin F (f '' S) := + le_antisymm + (map_le_iff_le_comap.mpr <| adjoin_le_iff.mpr fun x hx ↦ subset_adjoin _ _ ⟨x, hx, rfl⟩) + (adjoin_le_iff.mpr <| Set.monotone_image <| subset_adjoin _ _) + +@[simp] +theorem lift_adjoin (K : IntermediateField F E) (S : Set K) : + lift (adjoin F S) = adjoin F (Subtype.val '' S) := + adjoin_map _ _ _ + +theorem lift_adjoin_simple (K : IntermediateField F E) (α : K) : + lift (adjoin F {α}) = adjoin F {α.1} := by + simp only [lift_adjoin, Set.image_singleton] + +@[simp] +theorem lift_bot (K : IntermediateField F E) : + lift (F := K) ⊥ = ⊥ := map_bot _ + +@[simp] +theorem lift_top (K : IntermediateField F E) : + lift (F := K) ⊤ = K := by rw [lift, ← AlgHom.fieldRange_eq_map, fieldRange_val] + +@[simp] +theorem adjoin_self (K : IntermediateField F E) : + adjoin F K = K := le_antisymm (adjoin_le_iff.2 fun _ ↦ id) (subset_adjoin F _) + +theorem restrictScalars_adjoin (K : IntermediateField F E) (S : Set E) : + restrictScalars F (adjoin K S) = adjoin F (K ∪ S) := by + rw [← adjoin_self _ K, adjoin_adjoin_left, adjoin_self _ K] + +variable {F} in +theorem extendScalars_adjoin {K : IntermediateField F E} {S : Set E} (h : K ≤ adjoin F S) : + extendScalars h = adjoin K S := restrictScalars_injective F <| by + rw [extendScalars_restrictScalars, restrictScalars_adjoin] + exact le_antisymm (adjoin.mono F S _ Set.subset_union_right) <| adjoin_le_iff.2 <| + Set.union_subset h (subset_adjoin F S) + +theorem adjoin_union {S T : Set E} : adjoin F (S ∪ T) = adjoin F S ⊔ adjoin F T := + gc.l_sup + +theorem restrictScalars_adjoin_eq_sup (K : IntermediateField F E) (S : Set E) : + restrictScalars F (adjoin K S) = K ⊔ adjoin F S := by + rw [restrictScalars_adjoin, adjoin_union, adjoin_self] + +theorem adjoin_iUnion {ι} (f : ι → Set E) : adjoin F (⋃ i, f i) = ⨆ i, adjoin F (f i) := + gc.l_iSup + +theorem iSup_eq_adjoin {ι} (f : ι → IntermediateField F E) : + ⨆ i, f i = adjoin F (⋃ i, f i : Set E) := by + simp_rw [adjoin_iUnion, adjoin_self] + +variable {F} in +/-- If `E / L / F` and `E / L' / F` are two field extension towers, `L ≃ₐ[F] L'` is an isomorphism +compatible with `E / L` and `E / L'`, then for any subset `S` of `E`, `L(S)` and `L'(S)` are +equal as intermediate fields of `E / F`. -/ +theorem restrictScalars_adjoin_of_algEquiv + {L L' : Type*} [Field L] [Field L'] + [Algebra F L] [Algebra L E] [Algebra F L'] [Algebra L' E] + [IsScalarTower F L E] [IsScalarTower F L' E] (i : L ≃ₐ[F] L') + (hi : algebraMap L E = (algebraMap L' E) ∘ i) (S : Set E) : + (adjoin L S).restrictScalars F = (adjoin L' S).restrictScalars F := by + apply_fun toSubfield using (fun K K' h ↦ by + ext x; change x ∈ K.toSubfield ↔ x ∈ K'.toSubfield; rw [h]) + change Subfield.closure _ = Subfield.closure _ + congr + ext x + exact ⟨fun ⟨y, h⟩ ↦ ⟨i y, by rw [← h, hi]; rfl⟩, + fun ⟨y, h⟩ ↦ ⟨i.symm y, by rw [← h, hi, Function.comp_apply, AlgEquiv.apply_symm_apply]⟩⟩ + +@[elab_as_elim] +theorem adjoin_induction {s : Set E} {p : ∀ x ∈ adjoin F s, Prop} + (mem : ∀ x hx, p x (subset_adjoin _ _ hx)) + (algebraMap : ∀ x, p (algebraMap F E x) (algebraMap_mem _ _)) + (add : ∀ x y hx hy, p x hx → p y hy → p (x + y) (add_mem hx hy)) + (inv : ∀ x hx, p x hx → p x⁻¹ (inv_mem hx)) + (mul : ∀ x y hx hy, p x hx → p y hy → p (x * y) (mul_mem hx hy)) + {x} (h : x ∈ adjoin F s) : p x h := + Subfield.closure_induction + (fun x hx ↦ Or.casesOn hx (fun ⟨x, hx⟩ ↦ hx ▸ algebraMap x) (mem x)) + (by simp_rw [← (_root_.algebraMap F E).map_one]; exact algebraMap 1) add + (fun x _ h ↦ by + simp_rw [← neg_one_smul F x, Algebra.smul_def]; exact mul _ _ _ _ (algebraMap _) h) inv mul h + +section + +variable {K : Type*} [Semiring K] [Algebra F K] + +theorem adjoin_algHom_ext {s : Set E} ⦃φ₁ φ₂ : adjoin F s →ₐ[F] K⦄ + (h : ∀ x hx, φ₁ ⟨x, subset_adjoin _ _ hx⟩ = φ₂ ⟨x, subset_adjoin _ _ hx⟩) : + φ₁ = φ₂ := + AlgHom.ext fun ⟨x, hx⟩ ↦ adjoin_induction _ h (fun _ ↦ φ₂.commutes _ ▸ φ₁.commutes _) + (fun _ _ _ _ h₁ h₂ ↦ by convert congr_arg₂ (· + ·) h₁ h₂ <;> rw [← map_add] <;> rfl) + (fun _ _ ↦ eq_on_inv₀ _ _) + (fun _ _ _ _ h₁ h₂ ↦ by convert congr_arg₂ (· * ·) h₁ h₂ <;> rw [← map_mul] <;> rfl) + hx + +theorem algHom_ext_of_eq_adjoin {S : IntermediateField F E} {s : Set E} (hS : S = adjoin F s) + ⦃φ₁ φ₂ : S →ₐ[F] K⦄ + (h : ∀ x hx, φ₁ ⟨x, hS.ge (subset_adjoin _ _ hx)⟩ = φ₂ ⟨x, hS.ge (subset_adjoin _ _ hx)⟩) : + φ₁ = φ₂ := by + subst hS; exact adjoin_algHom_ext F h + +end + +/- Porting note (kmill): this notation is replacing the typeclass-based one I had previously +written, and it gives true `{x₁, x₂, ..., xₙ}` sets in the `adjoin` term. -/ + +open Lean in +/-- Supporting function for the `F⟮x₁,x₂,...,xₙ⟯` adjunction notation. -/ +private partial def mkInsertTerm {m : Type → Type} [Monad m] [MonadQuotation m] + (xs : TSyntaxArray `term) : m Term := run 0 where + run (i : Nat) : m Term := do + if i + 1 == xs.size then + ``(singleton $(xs[i]!)) + else if i < xs.size then + ``(insert $(xs[i]!) $(← run (i + 1))) + else + ``(EmptyCollection.emptyCollection) + +/-- If `x₁ x₂ ... xₙ : E` then `F⟮x₁,x₂,...,xₙ⟯` is the `IntermediateField F E` +generated by these elements. -/ +scoped macro:max K:term "⟮" xs:term,* "⟯" : term => do ``(adjoin $K $(← mkInsertTerm xs.getElems)) + +open Lean PrettyPrinter.Delaborator SubExpr in +@[app_delab IntermediateField.adjoin] +partial def delabAdjoinNotation : Delab := whenPPOption getPPNotation do + let e ← getExpr + guard <| e.isAppOfArity ``adjoin 6 + let F ← withNaryArg 0 delab + let xs ← withNaryArg 5 delabInsertArray + `($F⟮$(xs.toArray),*⟯) +where + delabInsertArray : DelabM (List Term) := do + let e ← getExpr + if e.isAppOfArity ``EmptyCollection.emptyCollection 2 then + return [] + else if e.isAppOfArity ``singleton 4 then + let x ← withNaryArg 3 delab + return [x] + else if e.isAppOfArity ``insert 5 then + let x ← withNaryArg 3 delab + let xs ← withNaryArg 4 delabInsertArray + return x :: xs + else failure + +section AdjoinSimple + +variable (α : E) + +-- Porting note: in all the theorems below, mathport translated `F⟮α⟯` into `F⟮⟯`. +theorem mem_adjoin_simple_self : α ∈ F⟮α⟯ := + subset_adjoin F {α} (Set.mem_singleton α) + +/-- generator of `F⟮α⟯` -/ +def AdjoinSimple.gen : F⟮α⟯ := + ⟨α, mem_adjoin_simple_self F α⟩ + +@[simp] +theorem AdjoinSimple.coe_gen : (AdjoinSimple.gen F α : E) = α := + rfl + +theorem AdjoinSimple.algebraMap_gen : algebraMap F⟮α⟯ E (AdjoinSimple.gen F α) = α := + rfl + +theorem adjoin_simple_adjoin_simple (β : E) : F⟮α⟯⟮β⟯.restrictScalars F = F⟮α, β⟯ := + adjoin_adjoin_left _ _ _ + +theorem adjoin_simple_comm (β : E) : F⟮α⟯⟮β⟯.restrictScalars F = F⟮β⟯⟮α⟯.restrictScalars F := + adjoin_adjoin_comm _ _ _ + +variable {F} {α} + +/- Porting note: this was tagged `simp`, but the LHS can be simplified now that the notation +has been improved. -/ +theorem adjoin_simple_le_iff {K : IntermediateField F E} : F⟮α⟯ ≤ K ↔ α ∈ K := by simp + +theorem biSup_adjoin_simple : ⨆ x ∈ S, F⟮x⟯ = adjoin F S := by + rw [← iSup_subtype'', ← gc.l_iSup, iSup_subtype'']; congr; exact S.biUnion_of_singleton + +end AdjoinSimple + +end AdjoinDef + +section AdjoinIntermediateFieldLattice + +variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] {α : E} {S : Set E} + +@[simp] +theorem adjoin_eq_bot_iff : adjoin F S = ⊥ ↔ S ⊆ (⊥ : IntermediateField F E) := by + rw [eq_bot_iff, adjoin_le_iff] + +/- Porting note: this was tagged `simp`. -/ +theorem adjoin_simple_eq_bot_iff : F⟮α⟯ = ⊥ ↔ α ∈ (⊥ : IntermediateField F E) := by + simp + +@[simp] +theorem adjoin_zero : F⟮(0 : E)⟯ = ⊥ := + adjoin_simple_eq_bot_iff.mpr (zero_mem ⊥) + +@[simp] +theorem adjoin_one : F⟮(1 : E)⟯ = ⊥ := + adjoin_simple_eq_bot_iff.mpr (one_mem ⊥) + +@[simp] +theorem adjoin_intCast (n : ℤ) : F⟮(n : E)⟯ = ⊥ := by + exact adjoin_simple_eq_bot_iff.mpr (intCast_mem ⊥ n) + +@[simp] +theorem adjoin_natCast (n : ℕ) : F⟮(n : E)⟯ = ⊥ := + adjoin_simple_eq_bot_iff.mpr (natCast_mem ⊥ n) + +@[deprecated (since := "2024-04-05")] alias adjoin_int := adjoin_intCast +@[deprecated (since := "2024-04-05")] alias adjoin_nat := adjoin_natCast + +end AdjoinIntermediateFieldLattice + +section Induction + +variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] + +/-- An intermediate field `S` is finitely generated if there exists `t : Finset E` such that +`IntermediateField.adjoin F t = S`. -/ +@[stacks 09FZ "second part"] +def FG (S : IntermediateField F E) : Prop := + ∃ t : Finset E, adjoin F ↑t = S + +theorem fg_adjoin_finset (t : Finset E) : (adjoin F (↑t : Set E)).FG := + ⟨t, rfl⟩ + +theorem fg_def {S : IntermediateField F E} : S.FG ↔ ∃ t : Set E, Set.Finite t ∧ adjoin F t = S := + Iff.symm Set.exists_finite_iff_finset + +theorem fg_adjoin_of_finite {t : Set E} (h : Set.Finite t) : (adjoin F t).FG := + fg_def.mpr ⟨t, h, rfl⟩ + +theorem fg_bot : (⊥ : IntermediateField F E).FG := + -- Porting note: was `⟨∅, adjoin_empty F E⟩` + ⟨∅, by simp only [Finset.coe_empty, adjoin_empty]⟩ + +theorem fg_sup {S T : IntermediateField F E} (hS : S.FG) (hT : T.FG) : (S ⊔ T).FG := by + obtain ⟨s, rfl⟩ := hS; obtain ⟨t, rfl⟩ := hT + classical rw [← adjoin_union, ← Finset.coe_union] + exact fg_adjoin_finset _ + +theorem fg_iSup {ι : Sort*} [Finite ι] {S : ι → IntermediateField F E} (h : ∀ i, (S i).FG) : + (⨆ i, S i).FG := by + choose s hs using h + simp_rw [← hs, ← adjoin_iUnion] + exact fg_adjoin_of_finite (Set.finite_iUnion fun _ ↦ Finset.finite_toSet _) + +theorem induction_on_adjoin_finset (S : Finset E) (P : IntermediateField F E → Prop) (base : P ⊥) + (ih : ∀ (K : IntermediateField F E), ∀ x ∈ S, P K → P (K⟮x⟯.restrictScalars F)) : + P (adjoin F S) := by + classical + refine Finset.induction_on' S ?_ (fun ha _ _ h => ?_) + · simp [base] + · rw [Finset.coe_insert, Set.insert_eq, Set.union_comm, ← adjoin_adjoin_left] + exact ih (adjoin F _) _ ha h + +theorem induction_on_adjoin_fg (P : IntermediateField F E → Prop) (base : P ⊥) + (ih : ∀ (K : IntermediateField F E) (x : E), P K → P (K⟮x⟯.restrictScalars F)) + (K : IntermediateField F E) (hK : K.FG) : P K := by + obtain ⟨S, rfl⟩ := hK + exact induction_on_adjoin_finset S P base fun K x _ hK => ih K x hK + +end Induction + +end IntermediateField + +namespace IntermediateField + +variable {K L L' : Type*} [Field K] [Field L] [Field L'] [Algebra K L] [Algebra K L'] + +theorem map_comap_eq (f : L →ₐ[K] L') (S : IntermediateField K L') : + (S.comap f).map f = S ⊓ f.fieldRange := + SetLike.coe_injective Set.image_preimage_eq_inter_range + +theorem map_comap_eq_self {f : L →ₐ[K] L'} {S : IntermediateField K L'} (h : S ≤ f.fieldRange) : + (S.comap f).map f = S := by + simpa only [inf_of_le_left h] using map_comap_eq f S + +theorem map_comap_eq_self_of_surjective {f : L →ₐ[K] L'} (hf : Function.Surjective f) + (S : IntermediateField K L') : (S.comap f).map f = S := + SetLike.coe_injective (Set.image_preimage_eq _ hf) + +theorem comap_map (f : L →ₐ[K] L') (S : IntermediateField K L) : (S.map f).comap f = S := + SetLike.coe_injective (Set.preimage_image_eq _ f.injective) + +end IntermediateField + +section ExtendScalars + +variable {K : Type*} [Field K] {L : Type*} [Field L] [Algebra K L] + +namespace Subfield + +variable (F : Subfield L) + +@[simp] +theorem extendScalars_self : extendScalars (le_refl F) = ⊥ := by + ext x + rw [mem_extendScalars, IntermediateField.mem_bot] + refine ⟨fun h ↦ ⟨⟨x, h⟩, rfl⟩, ?_⟩ + rintro ⟨y, rfl⟩ + exact y.2 + +@[simp] +theorem extendScalars_top : extendScalars (le_top : F ≤ ⊤) = ⊤ := + IntermediateField.toSubfield_injective (by simp) + +variable {F} +variable {E E' : Subfield L} (h : F ≤ E) (h' : F ≤ E') + +theorem extendScalars_sup : + extendScalars h ⊔ extendScalars h' = extendScalars (le_sup_of_le_left h : F ≤ E ⊔ E') := + ((extendScalars.orderIso F).map_sup ⟨_, h⟩ ⟨_, h'⟩).symm + +theorem extendScalars_inf : extendScalars h ⊓ extendScalars h' = extendScalars (le_inf h h') := + ((extendScalars.orderIso F).map_inf ⟨_, h⟩ ⟨_, h'⟩).symm + +end Subfield + +namespace IntermediateField + +variable (F : IntermediateField K L) + +@[simp] +theorem extendScalars_self : extendScalars (le_refl F) = ⊥ := + restrictScalars_injective K (by simp) + +@[simp] +theorem extendScalars_top : extendScalars (le_top : F ≤ ⊤) = ⊤ := + restrictScalars_injective K (by simp) + +variable {F} +variable {E E' : IntermediateField K L} (h : F ≤ E) (h' : F ≤ E') + +theorem extendScalars_sup : + extendScalars h ⊔ extendScalars h' = extendScalars (le_sup_of_le_left h : F ≤ E ⊔ E') := + ((extendScalars.orderIso F).map_sup ⟨_, h⟩ ⟨_, h'⟩).symm + +theorem extendScalars_inf : extendScalars h ⊓ extendScalars h' = extendScalars (le_inf h h') := + ((extendScalars.orderIso F).map_inf ⟨_, h⟩ ⟨_, h'⟩).symm + +end IntermediateField + +end ExtendScalars diff --git a/Mathlib/FieldTheory/LinearDisjoint.lean b/Mathlib/FieldTheory/LinearDisjoint.lean index bec7e11730908..47fa1b206ee9b 100644 --- a/Mathlib/FieldTheory/LinearDisjoint.lean +++ b/Mathlib/FieldTheory/LinearDisjoint.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Jz Pan. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jz Pan -/ -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic import Mathlib.RingTheory.AlgebraicIndependent.RankAndCardinality import Mathlib.RingTheory.LinearDisjoint diff --git a/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean b/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean index d9c57dbc10fda..fe5e7910abb47 100644 --- a/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean +++ b/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jiedong Jiang -/ import Mathlib.FieldTheory.Minpoly.Basic -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic import Mathlib.FieldTheory.Normal /-! diff --git a/Mathlib/FieldTheory/Relrank.lean b/Mathlib/FieldTheory/Relrank.lean index 4c7805692e150..6b32cbc7d88e9 100644 --- a/Mathlib/FieldTheory/Relrank.lean +++ b/Mathlib/FieldTheory/Relrank.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Jz Pan. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jz Pan -/ -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic /-! diff --git a/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean b/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean index 53d2a48d0cf9b..86d46294c1730 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic import Mathlib.RingTheory.AlgebraicIndependent.Defs /-! diff --git a/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean b/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean index 9c1d64bd63250..fc0151cb337bd 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic import Mathlib.RingTheory.AlgebraicIndependent.Transcendental /-! diff --git a/Mathlib/RingTheory/Valuation/Minpoly.lean b/Mathlib/RingTheory/Valuation/Minpoly.lean index 00094cc933c86..6ec821d6d0c74 100644 --- a/Mathlib/RingTheory/Valuation/Minpoly.lean +++ b/Mathlib/RingTheory/Valuation/Minpoly.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 María Inés de Frutos-Fernández, Filippo A. E. Nuccio. All Released under Apache 2.0 license as described in the file LICENSE. Authors: María Inés de Frutos-Fernández, Filippo A. E. Nuccio -/ -import Mathlib.FieldTheory.Adjoin +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic import Mathlib.RingTheory.Valuation.Basic /-! From 5ce9aa28663c5b965e6e705c8874200189adea3d Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 10 Jan 2025 04:26:56 +0000 Subject: [PATCH 117/681] chore(Algebra/Lie/DirectSum): shorten proof of lieAlgebraOf.map_lie' (#20592) Uses the [`lie_of_same`](https://github.com/leanprover-community/mathlib4/blob/d4891b46ecc82d3f6050dd51c2699fee91a2347b/Mathlib/Algebra/Lie/DirectSum.lean#L118) lemma added in #8388 to shorten a 13-line proof down to a single line, removing two `erw`s and one porting note. According to `set_option trace.profiler true`, the new `lieAlgbraOf` declaration takes 135 milliseconds to elaborate, compared to 298 milliseconds for the declaration it replaces. Found via [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). --- Mathlib/Algebra/Lie/DirectSum.lean | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/Mathlib/Algebra/Lie/DirectSum.lean b/Mathlib/Algebra/Lie/DirectSum.lean index bed135465a358..67450707449dc 100644 --- a/Mathlib/Algebra/Lie/DirectSum.lean +++ b/Mathlib/Algebra/Lie/DirectSum.lean @@ -147,24 +147,7 @@ variable (R ι) def lieAlgebraOf [DecidableEq ι] (j : ι) : L j →ₗ⁅R⁆ ⨁ i, L i := { lof R ι L j with toFun := of L j - map_lie' := fun {x y} => by - ext i - by_cases h : j = i - · rw [← h] - -- This used to be the end of the proof before https://github.com/leanprover/lean4/pull/2644 - -- with `simp [of, singleAddHom]` - simp only [of, singleAddHom, bracket_apply] - erw [AddHom.coe_mk, single_apply, single_apply] - · simp? [h] says simp only [h, ↓reduceDIte, single_apply] - · intros - rw [single_add] - · -- This used to be the end of the proof before https://github.com/leanprover/lean4/pull/2644 - -- with `simp [of, singleAddHom]` - simp only [of, singleAddHom, bracket_apply] - erw [AddHom.coe_mk, single_apply, single_apply] - · simp only [h, dite_false, single_apply, lie_self] - · intros - rw [single_add] } + map_lie' := fun {x y} => (lie_of_same L x y).symm } /-- The projection map onto one component, as a morphism of Lie algebras. -/ @[simps] From a8fc4672fc8fcb87a55f495bb4dc1457b8255d5c Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 10 Jan 2025 04:48:34 +0000 Subject: [PATCH 118/681] chore: reduce Topology->Order imports by moving content (#20627) --- Mathlib.lean | 1 + Mathlib/Order/Category/Frm.lean | 16 ++---------- .../Order/Filter/ZeroAndBoundedAtFilter.lean | 1 - Mathlib/Topology/Category/CompHaus/Frm.lean | 26 +++++++++++++++++++ Mathlib/Topology/Category/Locale.lean | 1 + 5 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 Mathlib/Topology/Category/CompHaus/Frm.lean diff --git a/Mathlib.lean b/Mathlib.lean index e831060db77b0..f5757dc88b91e 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5174,6 +5174,7 @@ import Mathlib.Topology.CWComplex import Mathlib.Topology.Category.Born import Mathlib.Topology.Category.CompHaus.Basic import Mathlib.Topology.Category.CompHaus.EffectiveEpi +import Mathlib.Topology.Category.CompHaus.Frm import Mathlib.Topology.Category.CompHaus.Limits import Mathlib.Topology.Category.CompHaus.Projective import Mathlib.Topology.Category.CompHausLike.Basic diff --git a/Mathlib/Order/Category/Frm.lean b/Mathlib/Order/Category/Frm.lean index f09b81f241c54..53f71706b0dc2 100644 --- a/Mathlib/Order/Category/Frm.lean +++ b/Mathlib/Order/Category/Frm.lean @@ -5,8 +5,7 @@ Authors: Yaël Dillies -/ import Mathlib.Order.Category.Lat import Mathlib.Order.Hom.CompleteLattice -import Mathlib.Topology.Category.CompHaus.Basic -import Mathlib.Topology.Sets.Opens +import Mathlib.CategoryTheory.ConcreteCategory.Bundled /-! # The category of frames @@ -21,7 +20,7 @@ This file defines `Frm`, the category of frames. universe u -open CategoryTheory Opposite Order TopologicalSpace +open CategoryTheory Order /-- The category of frames. -/ @@ -83,14 +82,3 @@ def Iso.mk {α β : Frm.{u}} (e : α ≃o β) : α ≅ β where exact e.apply_symm_apply _ end Frm - -/-- The forgetful functor from `TopCatᵒᵖ` to `Frm`. -/ -@[simps] -def topCatOpToFrm : TopCatᵒᵖ ⥤ Frm where - obj X := Frm.of (Opens (unop X : TopCat)) - map f := Opens.comap <| Quiver.Hom.unop f - map_id _ := Opens.comap_id - --- Note, `CompHaus` is too strong. We only need `T0Space`. -instance CompHausOpToFrame.faithful : (compHausToTop.op ⋙ topCatOpToFrm.{u}).Faithful := - ⟨fun h => Quiver.Hom.unop_inj <| Opens.comap_injective h⟩ diff --git a/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean b/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean index fd33cad02fcd3..3a6c683e96c46 100644 --- a/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean +++ b/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck, David Loeffler -/ import Mathlib.Algebra.Module.Submodule.Basic -import Mathlib.Topology.Algebra.Monoid import Mathlib.Analysis.Asymptotics.Asymptotics import Mathlib.Algebra.Algebra.Pi diff --git a/Mathlib/Topology/Category/CompHaus/Frm.lean b/Mathlib/Topology/Category/CompHaus/Frm.lean new file mode 100644 index 0000000000000..3e04891277900 --- /dev/null +++ b/Mathlib/Topology/Category/CompHaus/Frm.lean @@ -0,0 +1,26 @@ +/- +Copyright (c) 2022 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies +-/ + +import Mathlib.Order.Category.Frm +import Mathlib.Topology.Category.CompHaus.Basic +import Mathlib.Topology.Sets.Opens + +/-! The forgetful functor from `TopCatᵒᵖ` to `Frm`. -/ + +universe u + +open TopologicalSpace Opposite CategoryTheory + +/-- The forgetful functor from `TopCatᵒᵖ` to `Frm`. -/ +@[simps] +def topCatOpToFrm : TopCatᵒᵖ ⥤ Frm where + obj X := Frm.of (Opens (unop X : TopCat)) + map f := Opens.comap <| Quiver.Hom.unop f + map_id _ := Opens.comap_id + +-- Note, `CompHaus` is too strong. We only need `T0Space`. +instance CompHausOpToFrame.faithful : (compHausToTop.op ⋙ topCatOpToFrm.{u}).Faithful := + ⟨fun h => Quiver.Hom.unop_inj <| Opens.comap_injective h⟩ diff --git a/Mathlib/Topology/Category/Locale.lean b/Mathlib/Topology/Category/Locale.lean index c7e58d104b1a8..208b21c604fbc 100644 --- a/Mathlib/Topology/Category/Locale.lean +++ b/Mathlib/Topology/Category/Locale.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Order.Category.Frm +import Mathlib.Topology.Category.CompHaus.Frm /-! # The category of locales From 07f59252c2973f6c7a7160e3c0724ecda2bd62ce Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 10 Jan 2025 04:57:35 +0000 Subject: [PATCH 119/681] chore: split Algebra/BigOperators/Group/List (#20625) --- Mathlib.lean | 4 +- .../Group/{List.lean => List/Basic.lean} | 287 +----------------- .../Algebra/BigOperators/Group/List/Defs.lean | 112 +++++++ .../BigOperators/Group/List/Lemmas.lean | 235 ++++++++++++++ .../Algebra/BigOperators/Group/Multiset.lean | 2 +- Mathlib/Algebra/BigOperators/Ring/List.lean | 2 +- Mathlib/Algebra/FreeMonoid/Basic.lean | 4 +- Mathlib/Algebra/GradedMonoid.lean | 2 +- .../Algebra/Group/Pointwise/Set/ListOfFn.lean | 2 +- .../Order/BigOperators/Group/List.lean | 2 +- .../BigOperators/GroupWithZero/List.lean | 2 +- .../Algebra/Order/BigOperators/Ring/List.lean | 2 +- Mathlib/Data/List/Prime.lean | 2 +- Mathlib/Data/Vector/Basic.lean | 2 +- .../GroupTheory/Congruence/BigOperators.lean | 2 +- Mathlib/GroupTheory/FreeGroup/Basic.lean | 3 +- scripts/noshake.json | 2 + 17 files changed, 374 insertions(+), 293 deletions(-) rename Mathlib/Algebra/BigOperators/Group/{List.lean => List/Basic.lean} (65%) create mode 100644 Mathlib/Algebra/BigOperators/Group/List/Defs.lean create mode 100644 Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean diff --git a/Mathlib.lean b/Mathlib.lean index f5757dc88b91e..2e824707ad03b 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -43,7 +43,9 @@ import Mathlib.Algebra.BigOperators.Fin import Mathlib.Algebra.BigOperators.Finprod import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.BigOperators.Group.Finset -import Mathlib.Algebra.BigOperators.Group.List +import Mathlib.Algebra.BigOperators.Group.List.Basic +import Mathlib.Algebra.BigOperators.Group.List.Defs +import Mathlib.Algebra.BigOperators.Group.List.Lemmas import Mathlib.Algebra.BigOperators.Group.Multiset import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.Algebra.BigOperators.GroupWithZero.Finset diff --git a/Mathlib/Algebra/BigOperators/Group/List.lean b/Mathlib/Algebra/BigOperators/Group/List/Basic.lean similarity index 65% rename from Mathlib/Algebra/BigOperators/Group/List.lean rename to Mathlib/Algebra/BigOperators/Group/List/Basic.lean index 5ff4cb25da33e..108d82d3138cd 100644 --- a/Mathlib/Algebra/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/BigOperators/Group/List/Basic.lean @@ -3,15 +3,15 @@ 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, Floris van Doorn, Sébastien Gouëzel, Alex J. Best -/ -import Mathlib.Algebra.Divisibility.Basic -import Mathlib.Algebra.Group.Int -import Mathlib.Data.List.Dedup -import Mathlib.Data.List.Flatten -import Mathlib.Data.List.Pairwise +import Mathlib.Algebra.BigOperators.Group.List.Defs +import Mathlib.Order.RelClasses +import Mathlib.Data.List.Basic +import Mathlib.Data.List.Forall2 import Mathlib.Data.List.Perm.Basic -import Mathlib.Data.List.ProdSigma -import Mathlib.Data.List.Range -import Mathlib.Data.List.Rotate +import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.Group.Commute.Defs +import Mathlib.Algebra.Group.Hom.Defs +import Mathlib.Algebra.Group.Nat.Basic /-! # Sums and products from lists @@ -20,80 +20,11 @@ This file provides basic results about `List.prod`, `List.sum`, which calculate of elements of a list and `List.alternatingProd`, `List.alternatingSum`, their alternating counterparts. -/ - assert_not_imported Mathlib.Algebra.Order.Group.Nat variable {ι α β M N P G : Type*} namespace List -section Defs - -/-- Product of a list. - -`List.prod [a, b, c] = ((1 * a) * b) * c` -/ -@[to_additive existing] -def prod {α} [Mul α] [One α] : List α → α := - foldr (· * ·) 1 - -/-- The alternating sum of a list. -/ -def alternatingSum {G : Type*} [Zero G] [Add G] [Neg G] : List G → G - | [] => 0 - | g :: [] => g - | g :: h :: t => g + -h + alternatingSum t - -/-- The alternating product of a list. -/ -@[to_additive existing] -def alternatingProd {G : Type*} [One G] [Mul G] [Inv G] : List G → G - | [] => 1 - | g :: [] => g - | g :: h :: t => g * h⁻¹ * alternatingProd t - -end Defs - -section Mul - -variable [Mul M] [One M] {l : List M} {a : M} - -@[to_additive existing, simp] -theorem prod_nil : ([] : List M).prod = 1 := - rfl - -@[to_additive existing, simp] -theorem prod_cons {a} {l : List M} : (a :: l).prod = a * l.prod := rfl - -@[to_additive] -lemma prod_induction - (p : M → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ l, p x) : - p l.prod := by - induction l with - | nil => simpa - | cons a l ih => - rw [List.prod_cons] - simp only [mem_cons, forall_eq_or_imp] at base - exact hom _ _ (base.1) (ih base.2) - -end Mul - -section MulOneClass - -variable [MulOneClass M] {l : List M} {a : M} - -@[to_additive] -theorem prod_singleton : [a].prod = a := - mul_one a - -@[to_additive] -theorem prod_one_cons : (1 :: l).prod = l.prod := by - rw [prod, foldr, one_mul] - -@[to_additive] -theorem prod_map_one {l : List ι} : - (l.map fun _ => (1 : M)).prod = 1 := by - induction l with - | nil => rfl - | cons hd tl ih => rw [map_cons, prod_one_cons, ih] - -end MulOneClass section Monoid @@ -125,24 +56,6 @@ theorem prod_flatten {l : List (List M)} : l.flatten.prod = (l.map List.prod).pr @[deprecated (since := "2024-10-15")] alias prod_join := prod_flatten @[deprecated (since := "2024-10-15")] alias sum_join := sum_flatten -@[to_additive] -theorem prod_eq_foldr {l : List M} : l.prod = foldr (· * ·) 1 l := rfl - -@[to_additive (attr := simp)] -theorem prod_replicate (n : ℕ) (a : M) : (replicate n a).prod = a ^ n := by - induction n with - | zero => rw [pow_zero, replicate_zero, prod_nil] - | succ n ih => rw [replicate_succ, prod_cons, ih, pow_succ'] - -@[to_additive sum_eq_card_nsmul] -theorem prod_eq_pow_card (l : List M) (m : M) (h : ∀ x ∈ l, x = m) : l.prod = m ^ l.length := by - rw [← prod_replicate, ← List.eq_replicate_iff.mpr ⟨rfl, h⟩] - -@[to_additive] -theorem prod_hom_rel (l : List ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 1 1) - (h₂ : ∀ ⦃i a b⦄, r a b → r (f i * a) (g i * b)) : r (l.map f).prod (l.map g).prod := - List.recOn l h₁ fun a l hl => by simp only [map_cons, prod_cons, h₂ hl] - @[to_additive] theorem rel_prod {R : M → N → Prop} (h : R 1 1) (hf : (R ⇒ R ⇒ R) (· * ·) (· * ·)) : (Forall₂ R ⇒ R) prod prod := @@ -182,23 +95,6 @@ theorem prod_map_hom (L : List ι) (f : ι → M) {G : Type*} [FunLike G M N] [M (g : G) : (L.map (g ∘ f)).prod = g (L.map f).prod := by rw [← prod_hom, map_map] -@[to_additive] -theorem prod_isUnit : ∀ {L : List M}, (∀ m ∈ L, IsUnit m) → IsUnit L.prod - | [], _ => by simp - | h :: t, u => by - simp only [List.prod_cons] - exact IsUnit.mul (u h (mem_cons_self h t)) (prod_isUnit fun m mt => u m (mem_cons_of_mem h mt)) - -@[to_additive] -theorem prod_isUnit_iff {α : Type*} [CommMonoid α] {L : List α} : - IsUnit L.prod ↔ ∀ m ∈ L, IsUnit m := by - refine ⟨fun h => ?_, prod_isUnit⟩ - induction L with - | nil => exact fun m' h' => False.elim (not_mem_nil m' h') - | cons m L ih => - rw [prod_cons, IsUnit.mul_iff] at h - exact fun m' h' ↦ Or.elim (eq_or_mem_of_mem_cons h') (fun H => H.substr h.1) fun H => ih h.2 _ H - @[to_additive (attr := simp)] theorem prod_take_mul_prod_drop (L : List M) (i : ℕ) : (L.take i).prod * (L.drop i).prod = L.prod := by @@ -322,20 +218,6 @@ lemma prod_eq_pow_single [DecidableEq M] (a : M) (h : ∀ a', a' ≠ a → a' l.prod = a ^ l.count a := _root_.trans (by rw [map_id]) (prod_map_eq_pow_single a id h) -/-- If elements of a list commute with each other, then their product does not -depend on the order of elements. -/ -@[to_additive "If elements of a list additively commute with each other, then their sum does not -depend on the order of elements."] -lemma Perm.prod_eq' (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) : l₁.prod = l₂.prod := by - refine h.foldr_eq' ?_ _ - apply Pairwise.forall_of_forall - · intro x y h z - exact (h z).symm - · intros; rfl - · apply hc.imp - intro a b h z - rw [← mul_assoc, ← mul_assoc, h] - end Monoid section CommMonoid @@ -444,15 +326,6 @@ theorem prod_range_div' (n : ℕ) (f : ℕ → G) : | succ n h => rw [range_succ, map_append, map_singleton, prod_append, prod_singleton, h, div_mul_div_cancel] -lemma prod_rotate_eq_one_of_prod_eq_one : - ∀ {l : List G} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1 - | [], _, _ => by simp - | a :: l, hl, n => by - have : n % List.length (a :: l) ≤ List.length (a :: l) := le_of_lt (Nat.mod_lt _ (by simp)) - rw [← List.take_append_drop (n % List.length (a :: l)) (a :: l)] at hl - rw [← rotate_mod, rotate_eq_drop_append_take this, List.prod_append, mul_eq_one_iff_inv_eq, - ← one_mul (List.prod _)⁻¹, ← hl, List.prod_append, mul_assoc, mul_inv_cancel, mul_one] - end Group section CommGroup @@ -581,38 +454,6 @@ lemma sum_int_mod (l : List ℤ) (n : ℤ) : l.sum % n = (l.map (· % n)).sum % lemma prod_int_mod (l : List ℤ) (n : ℤ) : l.prod % n = (l.map (· % n)).prod % n := by induction l <;> simp [Int.mul_emod, *] -variable [DecidableEq α] - -/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/ -theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) : - ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by - induction l with - | nil => simp - | cons a as h => - simp_rw [List.countP_cons, List.count_cons, List.sum_map_add] - congr 1 - · refine _root_.trans ?_ h - by_cases ha : a ∈ as - · simp [dedup_cons_of_mem ha] - · simp only [dedup_cons_of_not_mem ha, List.filter] - match p a with - | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add] - | false => simp only - · simp only [beq_iff_eq] - by_cases hp : p a - · refine _root_.trans (sum_map_eq_nsmul_single a _ fun _ h _ => by simp [h.symm]) ?_ - simp [hp, count_dedup] - · refine _root_.trans (List.sum_eq_zero fun n hn => ?_) (by simp [hp]) - obtain ⟨a', ha'⟩ := List.mem_map.1 hn - split_ifs at ha' with ha - · simp only [ha.symm, mem_filter, mem_dedup, find?, mem_cons, true_or, hp, - and_false, false_and, reduceCtorEq] at ha' - · exact ha'.2.symm - -theorem sum_map_count_dedup_eq_length (l : List α) : - (l.dedup.map fun x => l.count x).sum = l.length := by - simpa using sum_map_count_dedup_filter_eq_countP (fun _ => True) l - end List section MonoidHom @@ -638,27 +479,6 @@ end MonoidHom namespace List -lemma length_sigma {σ : α → Type*} (l₁ : List α) (l₂ : ∀ a, List (σ a)) : - length (l₁.sigma l₂) = (l₁.map fun a ↦ length (l₂ a)).sum := by - induction' l₁ with x l₁ IH - · rfl - · simp only [sigma_cons, length_append, length_map, IH, map, sum_cons] - -lemma ranges_flatten : ∀ (l : List ℕ), l.ranges.flatten = range l.sum - | [] => rfl - | a :: l => by simp [ranges, ← map_flatten, ranges_flatten, range_add] - -/-- The members of `l.ranges` have no duplicate -/ -theorem ranges_nodup {l s : List ℕ} (hs : s ∈ ranges l) : s.Nodup := - (List.pairwise_flatten.mp <| by rw [ranges_flatten]; exact nodup_range _).1 s hs - -@[deprecated (since := "2024-10-15")] alias ranges_join := ranges_flatten - -/-- Any entry of any member of `l.ranges` is strictly smaller than `l.sum`. -/ -lemma mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} : - (∃ s ∈ l.ranges, n ∈ s) ↔ n < l.sum := by - rw [← mem_range, ← ranges_flatten, mem_flatten] - @[deprecated (since := "2024-10-16")] alias length_bind := length_flatMap @[deprecated (since := "2024-10-16")] alias countP_bind := countP_flatMap @@ -685,38 +505,11 @@ lemma drop_sum_flatten (L : List (List α)) (i : ℕ) : @[deprecated (since := "2024-10-15")] alias drop_sum_join := drop_sum_flatten -/-- In a flatten of sublists, taking the slice between the indices `A` and `B - 1` gives back the -original sublist of index `i` if `A` is the sum of the lengths of sublists of index `< i`, and -`B` is the sum of the lengths of sublists of index `≤ i`. -/ -lemma drop_take_succ_flatten_eq_getElem (L : List (List α)) (i : Nat) (h : i < L.length) : - (L.flatten.take ((L.map length).take (i + 1)).sum).drop ((L.map length).take i).sum = L[i] := by - have : (L.map length).take i = ((L.take (i + 1)).map length).take i := by - simp [map_take, take_take, Nat.min_eq_left] - simp only [this, length_map, take_sum_flatten, drop_sum_flatten, - drop_take_succ_eq_cons_getElem, h, flatten, append_nil] - -@[deprecated (since := "2024-06-11")] -alias drop_take_succ_join_eq_getElem := drop_take_succ_flatten_eq_getElem - -@[deprecated drop_take_succ_flatten_eq_getElem (since := "2024-06-11")] -lemma drop_take_succ_join_eq_get (L : List (List α)) (i : Fin L.length) : - (L.flatten.take ((L.map length).take (i + 1)).sum).drop - ((L.map length).take i).sum = get L i := by - rw [drop_take_succ_flatten_eq_getElem _ _ i.2] - simp - end List namespace List -/-- If a product of integers is `-1`, then at least one factor must be `-1`. -/ -theorem neg_one_mem_of_prod_eq_neg_one {l : List ℤ} (h : l.prod = -1) : (-1 : ℤ) ∈ l := by - obtain ⟨x, h₁, h₂⟩ := exists_mem_ne_one_of_prod_ne_one (ne_of_eq_of_ne h (by decide)) - exact Or.resolve_left - (Int.isUnit_iff.mp (prod_isUnit_iff.mp - (h.symm ▸ ⟨⟨-1, -1, by decide, by decide⟩, rfl⟩ : IsUnit l.prod) x h₁)) h₂ ▸ h₁ - /-- If all elements in a list are bounded below by `1`, then the length of the list is bounded by the sum of the elements. -/ theorem length_le_sum_of_one_le (L : List ℕ) (h : ∀ i ∈ L, 1 ≤ i) : L.length ≤ L.sum := by @@ -726,68 +519,4 @@ theorem length_le_sum_of_one_le (L : List ℕ) (h : ∀ i ∈ L, 1 ≤ i) : L.le rw [sum_cons, length, add_comm] exact Nat.add_le_add (h _ (mem_cons_self _ _)) (IH fun i hi => h i (mem_cons.2 (Or.inr hi))) -theorem dvd_prod [CommMonoid M] {a} {l : List M} (ha : a ∈ l) : a ∣ l.prod := by - let ⟨s, t, h⟩ := append_of_mem ha - rw [h, prod_append, prod_cons, mul_left_comm] - exact dvd_mul_right _ _ - -theorem Sublist.prod_dvd_prod [CommMonoid M] {l₁ l₂ : List M} (h : l₁ <+ l₂) : - l₁.prod ∣ l₂.prod := by - obtain ⟨l, hl⟩ := h.exists_perm_append - rw [hl.prod_eq, prod_append] - exact dvd_mul_right _ _ - -section Alternating - -variable [CommGroup α] - -@[to_additive] -theorem alternatingProd_append : - ∀ l₁ l₂ : List α, - alternatingProd (l₁ ++ l₂) = alternatingProd l₁ * alternatingProd l₂ ^ (-1 : ℤ) ^ length l₁ - | [], l₂ => by simp - | a :: l₁, l₂ => by - simp_rw [cons_append, alternatingProd_cons, alternatingProd_append, length_cons, pow_succ', - Int.neg_mul, one_mul, zpow_neg, ← div_eq_mul_inv, div_div] - -@[to_additive] -theorem alternatingProd_reverse : - ∀ l : List α, alternatingProd (reverse l) = alternatingProd l ^ (-1 : ℤ) ^ (length l + 1) - | [] => by simp only [alternatingProd_nil, one_zpow, reverse_nil] - | a :: l => by - simp_rw [reverse_cons, alternatingProd_append, alternatingProd_reverse, - alternatingProd_singleton, alternatingProd_cons, length_reverse, length, pow_succ', - Int.neg_mul, one_mul, zpow_neg, inv_inv] - rw [mul_comm, ← div_eq_mul_inv, div_zpow] - -end Alternating - end List - -open List - -namespace MulOpposite -variable [Monoid M] - -lemma op_list_prod : ∀ l : List M, op l.prod = (l.map op).reverse.prod := by - intro l; induction l with - | nil => rfl - | cons x xs ih => - rw [List.prod_cons, List.map_cons, List.reverse_cons', List.prod_concat, op_mul, ih] - -lemma unop_list_prod (l : List Mᵐᵒᵖ) : l.prod.unop = (l.map unop).reverse.prod := by - rw [← op_inj, op_unop, MulOpposite.op_list_prod, map_reverse, map_map, reverse_reverse, - op_comp_unop, map_id] - -end MulOpposite - -section MonoidHom -variable [Monoid M] [Monoid N] - -/-- A morphism into the opposite monoid acts on the product by acting on the reversed elements. -/ -lemma unop_map_list_prod {F : Type*} [FunLike F M Nᵐᵒᵖ] [MonoidHomClass F M Nᵐᵒᵖ] - (f : F) (l : List M) : - (f l.prod).unop = (l.map (MulOpposite.unop ∘ f)).reverse.prod := by - rw [map_list_prod f l, MulOpposite.unop_list_prod, List.map_map] - -end MonoidHom diff --git a/Mathlib/Algebra/BigOperators/Group/List/Defs.lean b/Mathlib/Algebra/BigOperators/Group/List/Defs.lean new file mode 100644 index 0000000000000..1990074026d7c --- /dev/null +++ b/Mathlib/Algebra/BigOperators/Group/List/Defs.lean @@ -0,0 +1,112 @@ +/- +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, Floris van Doorn, Sébastien Gouëzel, Alex J. Best +-/ +import Mathlib.Algebra.Group.Defs + +/-! +# Sums and products from lists + +This file provides basic definitions for `List.prod`, `List.sum`, +which calculate the product and sum of elements of a list +and `List.alternatingProd`, `List.alternatingSum`, their alternating counterparts. +-/ + +variable {ι α β M N P G : Type*} + +namespace List +section Defs + +/-- Product of a list. + +`List.prod [a, b, c] = ((1 * a) * b) * c` -/ +@[to_additive existing] +def prod {α} [Mul α] [One α] : List α → α := + foldr (· * ·) 1 + +/-- The alternating sum of a list. -/ +def alternatingSum {G : Type*} [Zero G] [Add G] [Neg G] : List G → G + | [] => 0 + | g :: [] => g + | g :: h :: t => g + -h + alternatingSum t + +/-- The alternating product of a list. -/ +@[to_additive existing] +def alternatingProd {G : Type*} [One G] [Mul G] [Inv G] : List G → G + | [] => 1 + | g :: [] => g + | g :: h :: t => g * h⁻¹ * alternatingProd t + +end Defs + +section Mul + +variable [Mul M] [One M] {l : List M} {a : M} + +@[to_additive existing, simp] +theorem prod_nil : ([] : List M).prod = 1 := + rfl + +@[to_additive existing, simp] +theorem prod_cons {a} {l : List M} : (a :: l).prod = a * l.prod := rfl + +@[to_additive] +lemma prod_induction + (p : M → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ l, p x) : + p l.prod := by + induction l with + | nil => simpa + | cons a l ih => + rw [List.prod_cons] + simp only [mem_cons, forall_eq_or_imp] at base + exact hom _ _ (base.1) (ih base.2) + +end Mul + +section MulOneClass + +variable [MulOneClass M] {l : List M} {a : M} + +@[to_additive] +theorem prod_singleton : [a].prod = a := + mul_one a + +@[to_additive] +theorem prod_one_cons : (1 :: l).prod = l.prod := by + rw [prod, foldr, one_mul] + +@[to_additive] +theorem prod_map_one {l : List ι} : + (l.map fun _ => (1 : M)).prod = 1 := by + induction l with + | nil => rfl + | cons hd tl ih => rw [map_cons, prod_one_cons, ih] + +end MulOneClass + +section Monoid + +variable [Monoid M] [Monoid N] [Monoid P] {l l₁ l₂ : List M} {a : M} + +@[to_additive] +theorem prod_eq_foldr {l : List M} : l.prod = foldr (· * ·) 1 l := rfl + +@[to_additive (attr := simp)] +theorem prod_replicate (n : ℕ) (a : M) : (replicate n a).prod = a ^ n := by + induction n with + | zero => rw [pow_zero, replicate_zero, prod_nil] + | succ n ih => rw [replicate_succ, prod_cons, ih, pow_succ'] + +@[to_additive sum_eq_card_nsmul] +theorem prod_eq_pow_card (l : List M) (m : M) (h : ∀ x ∈ l, x = m) : l.prod = m ^ l.length := by + rw [← prod_replicate, ← List.eq_replicate_iff.mpr ⟨rfl, h⟩] + +@[to_additive] +theorem prod_hom_rel (l : List ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 1 1) + (h₂ : ∀ ⦃i a b⦄, r a b → r (f i * a) (g i * b)) : r (l.map f).prod (l.map g).prod := + List.recOn l h₁ fun a l hl => by simp only [map_cons, prod_cons, h₂ hl] + +end Monoid + +end List diff --git a/Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean b/Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean new file mode 100644 index 0000000000000..737c13893b736 --- /dev/null +++ b/Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean @@ -0,0 +1,235 @@ +/- +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, Floris van Doorn, Sébastien Gouëzel, Alex J. Best +-/ +import Mathlib.Algebra.BigOperators.Group.List.Basic +import Mathlib.Algebra.Divisibility.Basic +import Mathlib.Algebra.Group.Int +import Mathlib.Data.List.Dedup +import Mathlib.Data.List.Flatten +import Mathlib.Data.List.Pairwise +import Mathlib.Data.List.Perm.Basic +import Mathlib.Data.List.Range +import Mathlib.Data.List.Rotate +import Mathlib.Data.List.ProdSigma + +/-! +# Sums and products from lists + +This file provides further results about `List.prod`, `List.sum`, +which calculate the product and sum of elements of a list +and `List.alternatingProd`, `List.alternatingSum`, their alternating counterparts. +-/ +assert_not_imported Mathlib.Algebra.Order.Group.Nat + +variable {ι α β M N P G : Type*} + +namespace List + +section Monoid + +variable [Monoid M] [Monoid N] [Monoid P] {l l₁ l₂ : List M} {a : M} + +@[to_additive] +theorem prod_isUnit : ∀ {L : List M}, (∀ m ∈ L, IsUnit m) → IsUnit L.prod + | [], _ => by simp + | h :: t, u => by + simp only [List.prod_cons] + exact IsUnit.mul (u h (mem_cons_self h t)) (prod_isUnit fun m mt => u m (mem_cons_of_mem h mt)) + +@[to_additive] +theorem prod_isUnit_iff {α : Type*} [CommMonoid α] {L : List α} : + IsUnit L.prod ↔ ∀ m ∈ L, IsUnit m := by + refine ⟨fun h => ?_, prod_isUnit⟩ + induction L with + | nil => exact fun m' h' => False.elim (not_mem_nil m' h') + | cons m L ih => + rw [prod_cons, IsUnit.mul_iff] at h + exact fun m' h' ↦ Or.elim (eq_or_mem_of_mem_cons h') (fun H => H.substr h.1) fun H => ih h.2 _ H + +/-- If elements of a list commute with each other, then their product does not +depend on the order of elements. -/ +@[to_additive "If elements of a list additively commute with each other, then their sum does not +depend on the order of elements."] +lemma Perm.prod_eq' (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) : l₁.prod = l₂.prod := by + refine h.foldr_eq' ?_ _ + apply Pairwise.forall_of_forall + · intro x y h z + exact (h z).symm + · intros; rfl + · apply hc.imp + intro a b h z + rw [← mul_assoc, ← mul_assoc, h] + +end Monoid + +section Group + +variable [Group G] + +lemma prod_rotate_eq_one_of_prod_eq_one : + ∀ {l : List G} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1 + | [], _, _ => by simp + | a :: l, hl, n => by + have : n % List.length (a :: l) ≤ List.length (a :: l) := le_of_lt (Nat.mod_lt _ (by simp)) + rw [← List.take_append_drop (n % List.length (a :: l)) (a :: l)] at hl + rw [← rotate_mod, rotate_eq_drop_append_take this, List.prod_append, mul_eq_one_iff_inv_eq, + ← one_mul (List.prod _)⁻¹, ← hl, List.prod_append, mul_assoc, mul_inv_cancel, mul_one] + +end Group + +variable [DecidableEq α] + +/-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/ +theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) : + ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by + induction l with + | nil => simp + | cons a as h => + simp_rw [List.countP_cons, List.count_cons, List.sum_map_add] + congr 1 + · refine _root_.trans ?_ h + by_cases ha : a ∈ as + · simp [dedup_cons_of_mem ha] + · simp only [dedup_cons_of_not_mem ha, List.filter] + match p a with + | true => simp only [List.map_cons, List.sum_cons, List.count_eq_zero.2 ha, zero_add] + | false => simp only + · simp only [beq_iff_eq] + by_cases hp : p a + · refine _root_.trans (sum_map_eq_nsmul_single a _ fun _ h _ => by simp [h.symm]) ?_ + simp [hp, count_dedup] + · refine _root_.trans (List.sum_eq_zero fun n hn => ?_) (by simp [hp]) + obtain ⟨a', ha'⟩ := List.mem_map.1 hn + split_ifs at ha' with ha + · simp only [ha.symm, mem_filter, mem_dedup, find?, mem_cons, true_or, hp, + and_false, false_and, reduceCtorEq] at ha' + · exact ha'.2.symm + +theorem sum_map_count_dedup_eq_length (l : List α) : + (l.dedup.map fun x => l.count x).sum = l.length := by + simpa using sum_map_count_dedup_filter_eq_countP (fun _ => True) l + +end List + +namespace List + +lemma length_sigma {σ : α → Type*} (l₁ : List α) (l₂ : ∀ a, List (σ a)) : + length (l₁.sigma l₂) = (l₁.map fun a ↦ length (l₂ a)).sum := by + induction' l₁ with x l₁ IH + · rfl + · simp only [sigma_cons, length_append, length_map, IH, map, sum_cons] + +lemma ranges_flatten : ∀ (l : List ℕ), l.ranges.flatten = range l.sum + | [] => rfl + | a :: l => by simp [ranges, ← map_flatten, ranges_flatten, range_add] + +/-- The members of `l.ranges` have no duplicate -/ +theorem ranges_nodup {l s : List ℕ} (hs : s ∈ ranges l) : s.Nodup := + (List.pairwise_flatten.mp <| by rw [ranges_flatten]; exact nodup_range _).1 s hs + +@[deprecated (since := "2024-10-15")] alias ranges_join := ranges_flatten + +/-- Any entry of any member of `l.ranges` is strictly smaller than `l.sum`. -/ +lemma mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} : + (∃ s ∈ l.ranges, n ∈ s) ↔ n < l.sum := by + rw [← mem_range, ← ranges_flatten, mem_flatten] + +/-- In a flatten of sublists, taking the slice between the indices `A` and `B - 1` gives back the +original sublist of index `i` if `A` is the sum of the lengths of sublists of index `< i`, and +`B` is the sum of the lengths of sublists of index `≤ i`. -/ +lemma drop_take_succ_flatten_eq_getElem (L : List (List α)) (i : Nat) (h : i < L.length) : + (L.flatten.take ((L.map length).take (i + 1)).sum).drop ((L.map length).take i).sum = L[i] := by + have : (L.map length).take i = ((L.take (i + 1)).map length).take i := by + simp [map_take, take_take, Nat.min_eq_left] + simp only [this, length_map, take_sum_flatten, drop_sum_flatten, + drop_take_succ_eq_cons_getElem, h, flatten, append_nil] + +@[deprecated (since := "2024-06-11")] +alias drop_take_succ_join_eq_getElem := drop_take_succ_flatten_eq_getElem + +@[deprecated drop_take_succ_flatten_eq_getElem (since := "2024-06-11")] +lemma drop_take_succ_join_eq_get (L : List (List α)) (i : Fin L.length) : + (L.flatten.take ((L.map length).take (i + 1)).sum).drop + ((L.map length).take i).sum = get L i := by + rw [drop_take_succ_flatten_eq_getElem _ _ i.2] + simp + +end List + + +namespace List + +/-- If a product of integers is `-1`, then at least one factor must be `-1`. -/ +theorem neg_one_mem_of_prod_eq_neg_one {l : List ℤ} (h : l.prod = -1) : (-1 : ℤ) ∈ l := by + obtain ⟨x, h₁, h₂⟩ := exists_mem_ne_one_of_prod_ne_one (ne_of_eq_of_ne h (by decide)) + exact Or.resolve_left + (Int.isUnit_iff.mp (prod_isUnit_iff.mp + (h.symm ▸ ⟨⟨-1, -1, by decide, by decide⟩, rfl⟩ : IsUnit l.prod) x h₁)) h₂ ▸ h₁ + +theorem dvd_prod [CommMonoid M] {a} {l : List M} (ha : a ∈ l) : a ∣ l.prod := by + let ⟨s, t, h⟩ := append_of_mem ha + rw [h, prod_append, prod_cons, mul_left_comm] + exact dvd_mul_right _ _ + +theorem Sublist.prod_dvd_prod [CommMonoid M] {l₁ l₂ : List M} (h : l₁ <+ l₂) : + l₁.prod ∣ l₂.prod := by + obtain ⟨l, hl⟩ := h.exists_perm_append + rw [hl.prod_eq, prod_append] + exact dvd_mul_right _ _ + +section Alternating + +variable [CommGroup α] + +@[to_additive] +theorem alternatingProd_append : + ∀ l₁ l₂ : List α, + alternatingProd (l₁ ++ l₂) = alternatingProd l₁ * alternatingProd l₂ ^ (-1 : ℤ) ^ length l₁ + | [], l₂ => by simp + | a :: l₁, l₂ => by + simp_rw [cons_append, alternatingProd_cons, alternatingProd_append, length_cons, pow_succ', + Int.neg_mul, one_mul, zpow_neg, ← div_eq_mul_inv, div_div] + +@[to_additive] +theorem alternatingProd_reverse : + ∀ l : List α, alternatingProd (reverse l) = alternatingProd l ^ (-1 : ℤ) ^ (length l + 1) + | [] => by simp only [alternatingProd_nil, one_zpow, reverse_nil] + | a :: l => by + simp_rw [reverse_cons, alternatingProd_append, alternatingProd_reverse, + alternatingProd_singleton, alternatingProd_cons, length_reverse, length, pow_succ', + Int.neg_mul, one_mul, zpow_neg, inv_inv] + rw [mul_comm, ← div_eq_mul_inv, div_zpow] + +end Alternating + +end List + +open List + +namespace MulOpposite +variable [Monoid M] + +lemma op_list_prod : ∀ l : List M, op l.prod = (l.map op).reverse.prod := by + intro l; induction l with + | nil => rfl + | cons x xs ih => + rw [List.prod_cons, List.map_cons, List.reverse_cons', List.prod_concat, op_mul, ih] + +lemma unop_list_prod (l : List Mᵐᵒᵖ) : l.prod.unop = (l.map unop).reverse.prod := by + rw [← op_inj, op_unop, MulOpposite.op_list_prod, map_reverse, map_map, reverse_reverse, + op_comp_unop, map_id] + +end MulOpposite + +section MonoidHom +variable [Monoid M] [Monoid N] + +/-- A morphism into the opposite monoid acts on the product by acting on the reversed elements. -/ +lemma unop_map_list_prod {F : Type*} [FunLike F M Nᵐᵒᵖ] [MonoidHomClass F M Nᵐᵒᵖ] + (f : F) (l : List M) : + (f l.prod).unop = (l.map (MulOpposite.unop ∘ f)).reverse.prod := by + rw [map_list_prod f l, MulOpposite.unop_list_prod, List.map_map] + +end MonoidHom diff --git a/Mathlib/Algebra/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/BigOperators/Group/Multiset.lean index 9f83c37dae0a1..a7cfb50317a50 100644 --- a/Mathlib/Algebra/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Multiset.lean @@ -3,7 +3,7 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.BigOperators.Group.List +import Mathlib.Algebra.BigOperators.Group.List.Lemmas import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Algebra.Order.Sub.Unbundled.Basic diff --git a/Mathlib/Algebra/BigOperators/Ring/List.lean b/Mathlib/Algebra/BigOperators/Ring/List.lean index 5825782ff4ddb..6b108d85f28fe 100644 --- a/Mathlib/Algebra/BigOperators/Ring/List.lean +++ b/Mathlib/Algebra/BigOperators/Ring/List.lean @@ -3,12 +3,12 @@ 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, Floris van Doorn, Sébastien Gouëzel, Alex J. Best -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.GroupWithZero.Commute import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.Ring.Basic import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Algebra.Ring.Commute +import Mathlib.Algebra.BigOperators.Group.List.Basic /-! # Big operators on a list in rings diff --git a/Mathlib/Algebra/FreeMonoid/Basic.lean b/Mathlib/Algebra/FreeMonoid/Basic.lean index f0f1323592d86..2c1e153eed82f 100644 --- a/Mathlib/Algebra/FreeMonoid/Basic.lean +++ b/Mathlib/Algebra/FreeMonoid/Basic.lean @@ -3,9 +3,9 @@ Copyright (c) 2019 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon, Yury Kudryashov -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.Group.Action.Defs -import Mathlib.Algebra.Group.Units.Basic +import Mathlib.Algebra.Group.Units.Defs +import Mathlib.Algebra.BigOperators.Group.List.Basic /-! # Free monoid over a given alphabet diff --git a/Mathlib/Algebra/GradedMonoid.lean b/Mathlib/Algebra/GradedMonoid.lean index 85e9bb219662e..6a3b310015196 100644 --- a/Mathlib/Algebra/GradedMonoid.lean +++ b/Mathlib/Algebra/GradedMonoid.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.BigOperators.Group.List +import Mathlib.Algebra.BigOperators.Group.List.Lemmas import Mathlib.Algebra.Group.Action.End import Mathlib.Algebra.Group.Submonoid.Defs import Mathlib.Data.List.FinRange diff --git a/Mathlib/Algebra/Group/Pointwise/Set/ListOfFn.lean b/Mathlib/Algebra/Group/Pointwise/Set/ListOfFn.lean index 120059da9dfca..da348ff790ee3 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set/ListOfFn.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/ListOfFn.lean @@ -3,9 +3,9 @@ Copyright (c) 2022 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Data.List.OfFn +import Mathlib.Algebra.BigOperators.Group.List.Defs /-! # Pointwise operations with lists of sets diff --git a/Mathlib/Algebra/Order/BigOperators/Group/List.lean b/Mathlib/Algebra/Order/BigOperators/Group/List.lean index c48a37148e053..e2cec9a39e288 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/List.lean @@ -3,9 +3,9 @@ Copyright (c) 2021 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Monoid.Unbundled.OrderDual +import Mathlib.Algebra.BigOperators.Group.List.Basic /-! # Big operators on a list in ordered groups diff --git a/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean b/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean index e38120c46d7ac..0d52fba9130e4 100644 --- a/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Stuart Presnell. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Stuart Presnell, Daniel Weber -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.Order.GroupWithZero.Unbundled +import Mathlib.Algebra.BigOperators.Group.List.Defs /-! # Big operators on a list in ordered groups with zeros diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/List.lean b/Mathlib/Algebra/Order/BigOperators/Ring/List.lean index d728f2a6a84bf..f25734ab623a9 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/List.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Stuart Presnell. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Stuart Presnell -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.Order.Ring.Canonical +import Mathlib.Algebra.BigOperators.Group.List.Defs /-! # Big operators on a list in ordered rings diff --git a/Mathlib/Data/List/Prime.lean b/Mathlib/Data/List/Prime.lean index 2dce64c46d9df..4a6ec72427cc8 100644 --- a/Mathlib/Data/List/Prime.lean +++ b/Mathlib/Data/List/Prime.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Jens Wagemaker, Anne Baanen -/ import Mathlib.Algebra.Associated.Basic -import Mathlib.Algebra.BigOperators.Group.List +import Mathlib.Algebra.BigOperators.Group.List.Lemmas /-! # Products of lists of prime elements. diff --git a/Mathlib/Data/Vector/Basic.lean b/Mathlib/Data/Vector/Basic.lean index 7f7f4602004bc..40f05c5f9d267 100644 --- a/Mathlib/Data/Vector/Basic.lean +++ b/Mathlib/Data/Vector/Basic.lean @@ -3,12 +3,12 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Data.Vector.Defs import Mathlib.Data.List.Nodup import Mathlib.Data.List.OfFn import Mathlib.Control.Applicative import Mathlib.Control.Traversable.Basic +import Mathlib.Algebra.BigOperators.Group.List.Basic /-! # Additional theorems and definitions about the `Vector` type diff --git a/Mathlib/GroupTheory/Congruence/BigOperators.lean b/Mathlib/GroupTheory/Congruence/BigOperators.lean index d7acdc5c89d6d..a52506ce46ca0 100644 --- a/Mathlib/GroupTheory/Congruence/BigOperators.lean +++ b/Mathlib/GroupTheory/Congruence/BigOperators.lean @@ -6,7 +6,7 @@ Authors: Amelia Livingston import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.BigOperators.Group.Multiset -import Mathlib.Algebra.BigOperators.Group.List +import Mathlib.Algebra.BigOperators.Group.List.Lemmas import Mathlib.GroupTheory.Congruence.Defs /-! diff --git a/Mathlib/GroupTheory/FreeGroup/Basic.lean b/Mathlib/GroupTheory/FreeGroup/Basic.lean index e0ee2f9a2a72d..68238f351a2d5 100644 --- a/Mathlib/GroupTheory/FreeGroup/Basic.lean +++ b/Mathlib/GroupTheory/FreeGroup/Basic.lean @@ -3,8 +3,9 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ -import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.Group.Subgroup.Ker +import Mathlib.Algebra.Group.Int +import Mathlib.Algebra.BigOperators.Group.List.Basic /-! # Free groups diff --git a/scripts/noshake.json b/scripts/noshake.json index 8a935b90e4553..d896c7a46f6a8 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -456,6 +456,8 @@ ["Mathlib.CategoryTheory.ConcreteCategory.ReflectsIso"], "Mathlib.Algebra.Category.MonCat.Basic": ["Mathlib.Algebra.Ring.Action.Group"], + "Mathlib.Algebra.BigOperators.Group.List.Lemmas": + ["Mathlib.Data.List.ProdSigma"], "Mathlib.Algebra.BigOperators.Group.List": ["Mathlib.Data.List.ProdSigma"], "Mathlib.Algebra.Algebra.Subalgebra.Order": ["Mathlib.Algebra.Module.Submodule.Order"], From 2bd5a6b1cc0a776ca21b2c34db7b931fa3fa9e0f Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 10 Jan 2025 04:57:36 +0000 Subject: [PATCH 120/681] chore: cleanup imports in PrimePow/Divisors (#20626) Moves a theorem to reduce the `NumberTheory` -> `Algebra` imports. --- Mathlib/Algebra/IsPrimePow.lean | 12 ++++-------- Mathlib/Data/Nat/Factorization/PrimePow.lean | 1 + Mathlib/NumberTheory/Divisors.lean | 7 +++++++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Mathlib/Algebra/IsPrimePow.lean b/Mathlib/Algebra/IsPrimePow.lean index d9de71addc9b7..b39849544065e 100644 --- a/Mathlib/Algebra/IsPrimePow.lean +++ b/Mathlib/Algebra/IsPrimePow.lean @@ -4,14 +4,16 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta -/ import Mathlib.Algebra.Associated.Basic -import Mathlib.NumberTheory.Divisors +import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Order.Nat +import Mathlib.Data.Nat.Prime.Basic /-! # Prime powers This file deals with prime powers: numbers which are positive integer powers of a single prime. -/ - +assert_not_exists Nat.divisors variable {R : Type*} [CommMonoidWithZero R] (n p : R) (k : ℕ) @@ -87,12 +89,6 @@ theorem IsPrimePow.dvd {n m : ℕ} (hn : IsPrimePow n) (hm : m ∣ n) (hm₁ : m rintro rfl simp only [pow_zero, ne_eq, not_true_eq_false] at hm₁ -theorem Nat.disjoint_divisors_filter_isPrimePow {a b : ℕ} (hab : a.Coprime b) : - Disjoint (a.divisors.filter IsPrimePow) (b.divisors.filter IsPrimePow) := by - simp only [Finset.disjoint_left, Finset.mem_filter, and_imp, Nat.mem_divisors, not_and] - rintro n han _ha hn hbn _hb - - exact hn.ne_one (Nat.eq_one_of_dvd_coprimes hab han hbn) - theorem IsPrimePow.two_le : ∀ {n : ℕ}, IsPrimePow n → 2 ≤ n | 0, h => (not_isPrimePow_zero h).elim | 1, h => (not_isPrimePow_one h).elim diff --git a/Mathlib/Data/Nat/Factorization/PrimePow.lean b/Mathlib/Data/Nat/Factorization/PrimePow.lean index be263eea0756e..422a03cd5203f 100644 --- a/Mathlib/Data/Nat/Factorization/PrimePow.lean +++ b/Mathlib/Data/Nat/Factorization/PrimePow.lean @@ -6,6 +6,7 @@ Authors: Bhavik Mehta import Mathlib.Algebra.IsPrimePow import Mathlib.Data.Nat.Factorization.Basic import Mathlib.Data.Nat.Prime.Pow +import Mathlib.NumberTheory.Divisors /-! # Prime powers and factorizations diff --git a/Mathlib/NumberTheory/Divisors.lean b/Mathlib/NumberTheory/Divisors.lean index e0af39d898670..0a26a00f55e98 100644 --- a/Mathlib/NumberTheory/Divisors.lean +++ b/Mathlib/NumberTheory/Divisors.lean @@ -5,6 +5,7 @@ Authors: Aaron Anderson -/ import Mathlib.Algebra.Order.BigOperators.Group.Finset import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.IsPrimePow import Mathlib.Data.Nat.PrimeFin import Mathlib.Order.Interval.Finset.Nat @@ -521,4 +522,10 @@ theorem prod_div_divisors {α : Type*} [CommMonoid α] (n : ℕ) (f : ℕ → α rw [mem_divisors] at hx hy exact (div_eq_iff_eq_of_dvd_dvd hn hx.1 hy.1).mp h +theorem disjoint_divisors_filter_isPrimePow {a b : ℕ} (hab : a.Coprime b) : + Disjoint (a.divisors.filter IsPrimePow) (b.divisors.filter IsPrimePow) := by + simp only [Finset.disjoint_left, Finset.mem_filter, and_imp, Nat.mem_divisors, not_and] + rintro n han _ha hn hbn _hb - + exact hn.ne_one (Nat.eq_one_of_dvd_coprimes hab han hbn) + end Nat From 8448d4bb7aab7998632383c7a71975fecab9a9ee Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 10 Jan 2025 06:07:05 +0000 Subject: [PATCH 121/681] chore(GroupTheory/CoprodI): shorten proof of lift_word_prod_nontrivial_of_not_empty (#20587) Replaces 9 lines of proof with a single application of [`lift_word_prod_nontrivial_of_other_i`](https://github.com/leanprover-community/mathlib4/blob/1e45d5cd7e9c7679d447d81fc9def277b54fc02d/Mathlib/GroupTheory/CoprodI.lean#L844). I observe this change to speed up the time reported by `set_option trace profiler true` from 280 `milliseconds` to 140 milliseconds. Found via [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). --- Mathlib/GroupTheory/CoprodI.lean | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Mathlib/GroupTheory/CoprodI.lean b/Mathlib/GroupTheory/CoprodI.lean index dbb69a5fef864..09d71fbf32674 100644 --- a/Mathlib/GroupTheory/CoprodI.lean +++ b/Mathlib/GroupTheory/CoprodI.lean @@ -894,15 +894,7 @@ theorem lift_word_prod_nontrivial_of_not_empty {i j} (w : NeWord H i j) : simpa using heq · change i ≠ k at hh change j ≠ k at hl - obtain ⟨h, hn1, -⟩ := Cardinal.three_le hcard 1 1 - let w' : NeWord H k k := - NeWord.append (NeWord.append (NeWord.singleton h hn1) hh.symm w) hl - (NeWord.singleton h⁻¹ (inv_ne_one.mpr hn1)) - have hw' : lift f w'.prod ≠ 1 := - lift_word_prod_nontrivial_of_head_eq_last f X hXnonempty hXdisj hpp w' - intro heq1 - apply hw' - simp [w', heq1] + exact lift_word_prod_nontrivial_of_other_i f X hXnonempty hXdisj hpp w hh.symm hl.symm include hcard in theorem empty_of_word_prod_eq_one {w : Word H} (h : lift f w.prod = 1) : From 220e307b07f1ea9efa7fb3bf23fcafb03565e8ae Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Fri, 10 Jan 2025 07:05:30 +0000 Subject: [PATCH 122/681] chore: cleanup more `erw` (#20601) --- Mathlib/Algebra/Algebra/Operations.lean | 7 +++++-- Mathlib/Algebra/BigOperators/Finprod.lean | 3 ++- Mathlib/Algebra/BigOperators/Group/Finset.lean | 4 ++-- Mathlib/Algebra/GCDMonoid/Basic.lean | 3 ++- Mathlib/Algebra/Group/Subgroup/Basic.lean | 3 ++- Mathlib/Algebra/GroupWithZero/Basic.lean | 2 +- Mathlib/Algebra/Module/Hom.lean | 4 +++- Mathlib/Algebra/Ring/Subsemiring/Basic.lean | 14 ++++++++++---- Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean | 2 +- 9 files changed, 28 insertions(+), 14 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index 7a693780a741f..2fb899680781b 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -388,7 +388,8 @@ variable {R} (P Q) protected theorem mul_one : M * 1 = M := by conv_lhs => rw [one_eq_span, ← span_eq M] - erw [span_mul_span, mul_one, span_eq] + rw [span_mul_span] + simp protected theorem map_mul {A'} [Semiring A'] [Algebra R A'] (f : A →ₐ[R] A') : map f.toLinearMap (M * N) = map f.toLinearMap M * map f.toLinearMap N := @@ -832,7 +833,9 @@ protected theorem map_div {B : Type*} [CommSemiring B] [Algebra R B] (I J : Subm obtain ⟨xz, xz_mem, hxz⟩ := hx (h z) ⟨z, hz, rfl⟩ convert xz_mem apply h.injective - erw [map_mul, h.apply_symm_apply, hxz] + rw [map_mul, h.apply_symm_apply] + simp only [AlgEquiv.toLinearMap_apply] at hxz + rw [hxz] end Quotient diff --git a/Mathlib/Algebra/BigOperators/Finprod.lean b/Mathlib/Algebra/BigOperators/Finprod.lean index 9205acc2d2800..c884837950fd6 100644 --- a/Mathlib/Algebra/BigOperators/Finprod.lean +++ b/Mathlib/Algebra/BigOperators/Finprod.lean @@ -376,11 +376,12 @@ theorem finprod_eq_prod_of_fintype [Fintype α] (f : α → M) : ∏ᶠ i : α, theorem finprod_cond_eq_prod_of_cond_iff (f : α → M) {p : α → Prop} {t : Finset α} (h : ∀ {x}, f x ≠ 1 → (p x ↔ x ∈ t)) : (∏ᶠ (i) (_ : p i), f i) = ∏ i ∈ t, f i := by set s := { x | p x } + change ∏ᶠ (i : α) (_ : i ∈ s), f i = ∏ i ∈ t, f i have : mulSupport (s.mulIndicator f) ⊆ t := by rw [Set.mulSupport_mulIndicator] intro x hx exact (h hx.2).1 hx.1 - erw [finprod_mem_def, finprod_eq_prod_of_mulSupport_subset _ this] + rw [finprod_mem_def, finprod_eq_prod_of_mulSupport_subset _ this] refine Finset.prod_congr rfl fun x hx => mulIndicator_apply_eq_self.2 fun hxs => ?_ contrapose! hxs exact (h hxs).2 hx diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index 47c2a0587a76d..0d3b302694ee2 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -952,8 +952,8 @@ theorem prod_eq_mul {s : Finset α} {f : α → β} (a b : α) (hn : a ≠ b) "A sum over `s.subtype p` equals one over `{x ∈ s | p x}`."] theorem prod_subtype_eq_prod_filter (f : α → β) {p : α → Prop} [DecidablePred p] : ∏ x ∈ s.subtype p, f x = ∏ x ∈ s with p x, f x := by - conv_lhs => erw [← prod_map (s.subtype p) (Function.Embedding.subtype _) f] - exact prod_congr (subtype_map _) fun x _hx => rfl + have := prod_map (s.subtype p) (Function.Embedding.subtype _) f + simp_all /-- If all elements of a `Finset` satisfy the predicate `p`, a product over `s.subtype p` equals that product over `s`. -/ diff --git a/Mathlib/Algebra/GCDMonoid/Basic.lean b/Mathlib/Algebra/GCDMonoid/Basic.lean index 57c84854496c4..7fcc8bb52f7cd 100644 --- a/Mathlib/Algebra/GCDMonoid/Basic.lean +++ b/Mathlib/Algebra/GCDMonoid/Basic.lean @@ -1136,7 +1136,8 @@ noncomputable def normalizedGCDMonoidOfLCM [NormalizationMonoid α] [DecidableEq conv_lhs => congr rw [← normalize_lcm a b] - erw [← normalize.map_mul, ← Classical.choose_spec (exists_gcd a b), normalize_idem] + rw [← normalize_apply, ← normalize.map_mul, + ← Classical.choose_spec (exists_gcd a b), normalize_idem] lcm_zero_left := fun _ => eq_zero_of_zero_dvd (dvd_lcm_left _ _) lcm_zero_right := fun _ => eq_zero_of_zero_dvd (dvd_lcm_right _ _) gcd_dvd_left := fun a b => by diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index 954661ef44610..e8e540cca1c03 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -414,7 +414,8 @@ def conjugatesOfSet (s : Set G) : Set G := ⋃ a ∈ s, conjugatesOf a theorem mem_conjugatesOfSet_iff {x : G} : x ∈ conjugatesOfSet s ↔ ∃ a ∈ s, IsConj a x := by - erw [Set.mem_iUnion₂]; simp only [conjugatesOf, isConj_iff, Set.mem_setOf_eq, exists_prop] + rw [conjugatesOfSet, Set.mem_iUnion₂] + simp only [conjugatesOf, isConj_iff, Set.mem_setOf_eq, exists_prop] theorem subset_conjugatesOfSet : s ⊆ conjugatesOfSet s := fun (x : G) (h : x ∈ s) => mem_conjugatesOfSet_iff.2 ⟨x, h, IsConj.refl _⟩ diff --git a/Mathlib/Algebra/GroupWithZero/Basic.lean b/Mathlib/Algebra/GroupWithZero/Basic.lean index f242f9558df45..1222fa35f4af0 100644 --- a/Mathlib/Algebra/GroupWithZero/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Basic.lean @@ -397,7 +397,7 @@ lemma zero_zpow_eq_one₀ {n : ℤ} : (0 : G₀) ^ n = 1 ↔ n = 0 := by lemma zpow_add_one₀ (ha : a ≠ 0) : ∀ n : ℤ, a ^ (n + 1) = a ^ n * a | (n : ℕ) => by simp only [← Int.ofNat_succ, zpow_natCast, pow_succ] - | .negSucc 0 => by erw [zpow_zero, zpow_negSucc, pow_one, inv_mul_cancel₀ ha] + | .negSucc 0 => by simp [ha] | .negSucc (n + 1) => by rw [Int.negSucc_eq, zpow_neg, Int.neg_add, Int.neg_add_cancel_right, zpow_neg, ← Int.ofNat_succ, zpow_natCast, zpow_natCast, pow_succ' _ (n + 1), mul_inv_rev, mul_assoc, inv_mul_cancel₀ ha, diff --git a/Mathlib/Algebra/Module/Hom.lean b/Mathlib/Algebra/Module/Hom.lean index 8149ac54e6b58..f97087b13c9a2 100644 --- a/Mathlib/Algebra/Module/Hom.lean +++ b/Mathlib/Algebra/Module/Hom.lean @@ -69,7 +69,9 @@ instance instDomMulActModule add_smul s s' f := AddMonoidHom.ext fun m ↦ by simp_rw [AddMonoidHom.add_apply, DomMulAct.smul_addMonoidHom_apply, ← map_add, ← add_smul]; rfl zero_smul _ := AddMonoidHom.ext fun _ ↦ by - erw [DomMulAct.smul_addMonoidHom_apply, zero_smul, map_zero]; rfl + rw [DomMulAct.smul_addMonoidHom_apply] + -- TODO there should be a simp lemma for `DomMulAct.mk.symm 0` + simp [DomMulAct.mk, MulOpposite.opEquiv] end AddMonoidHom diff --git a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean index 1043fb029fe82..801d3c6d69cf1 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean @@ -793,12 +793,18 @@ theorem ofLeftInverseS_symm_apply {g : S → R} {f : R →+* S} (h : Function.Le /-- Given an equivalence `e : R ≃+* S` of semirings and a subsemiring `s` of `R`, `subsemiring_map e s` is the induced equivalence between `s` and `s.map e` -/ -@[simps!] -def subsemiringMap (e : R ≃+* S) (s : Subsemiring R) : s ≃+* s.map e.toRingHom := +def subsemiringMap (e : R ≃+* S) (s : Subsemiring R) : s ≃+* s.map (e : R →+* S) := { e.toAddEquiv.addSubmonoidMap s.toAddSubmonoid, e.toMulEquiv.submonoidMap s.toSubmonoid with } --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] RingEquiv.subsemiringMap_symm_apply_coe RingEquiv.subsemiringMap_apply_coe +@[simp] +theorem subsemiringMap_apply_coe (e : R ≃+* S) (s : Subsemiring R) (x : s) : + ((subsemiringMap e s) x : S) = e x := + rfl + +@[simp] +theorem subsemiringMap_symm_apply_coe (e : R ≃+* S) (s : Subsemiring R) (x : s.map e.toRingHom) : + ((subsemiringMap e s).symm x : R) = e.symm x := + rfl end RingEquiv diff --git a/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean b/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean index 9e0ab1536c2d5..41659e7b7b8be 100644 --- a/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean +++ b/Mathlib/GroupTheory/GroupAction/DomAct/Basic.lean @@ -112,7 +112,7 @@ run_cmd `RightCancelSemigroup, `MulOneClass, `Monoid, `CommMonoid, `LeftCancelMonoid, `RightCancelMonoid, `CancelMonoid, `CancelCommMonoid, `InvolutiveInv, `DivInvMonoid, `InvOneClass, `DivInvOneMonoid, `DivisionMonoid, `DivisionCommMonoid, `Group, - `CommGroup, `NonAssocSemiring, `NonUnitalSemiring, `NonAssocSemiring, `Semiring, + `CommGroup, `NonAssocSemiring, `NonUnitalSemiring, `Semiring, `Ring, `CommRing].map Lean.mkIdent do Lean.Elab.Command.elabCommand (← `( @[to_additive] instance [$n Mᵐᵒᵖ] : $n Mᵈᵐᵃ := ‹_› From d14cbfb754b9b5e8c420d9e52eadeff737178e79 Mon Sep 17 00:00:00 2001 From: Christopher Hoskin Date: Fri, 10 Jan 2025 07:43:09 +0000 Subject: [PATCH 123/681] feature(Algebra/Ring/Idempotents): product of an idempotent and its complement (#20286) Add a couple of simp lemmas. In a ring, the product of an idempotent and its complement is zero. Co-authored-by: Christopher Hoskin --- Mathlib/Algebra/Ring/Idempotents.lean | 8 ++++++++ Mathlib/Analysis/NormedSpace/MStructure.lean | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Ring/Idempotents.lean b/Mathlib/Algebra/Ring/Idempotents.lean index 8b7ce4e91aadd..c4ecbbfe757dd 100644 --- a/Mathlib/Algebra/Ring/Idempotents.lean +++ b/Mathlib/Algebra/Ring/Idempotents.lean @@ -67,6 +67,14 @@ theorem one_sub {p : R} (h : IsIdempotentElem p) : IsIdempotentElem (1 - p) := b theorem one_sub_iff {p : R} : IsIdempotentElem (1 - p) ↔ IsIdempotentElem p := ⟨fun h => sub_sub_cancel 1 p ▸ h.one_sub, IsIdempotentElem.one_sub⟩ +@[simp] +theorem mul_one_sub_self {p : R} (h : IsIdempotentElem p) : p * (1 - p) = 0 := by + rw [mul_sub, mul_one, h.eq, sub_self] + +@[simp] +theorem one_sub_mul_self {p : R} (h : IsIdempotentElem p) : (1 - p) * p = 0 := by + rw [sub_mul, one_mul, h.eq, sub_self] + theorem add_sub_mul_of_commute {R} [Ring R] {p q : R} (h : Commute p q) (hp : IsIdempotentElem p) (hq : IsIdempotentElem q) : IsIdempotentElem (p + q - p * q) := by diff --git a/Mathlib/Analysis/NormedSpace/MStructure.lean b/Mathlib/Analysis/NormedSpace/MStructure.lean index 82a509ef81673..daa293a5f0d87 100644 --- a/Mathlib/Analysis/NormedSpace/MStructure.lean +++ b/Mathlib/Analysis/NormedSpace/MStructure.lean @@ -241,7 +241,7 @@ theorem compl_mul {P : { P : M // IsLprojection X P }} {Q : M} : ↑Pᶜ * Q = Q rw [coe_compl, sub_mul, one_mul] theorem mul_compl_self {P : { P : M // IsLprojection X P }} : (↑P : M) * ↑Pᶜ = 0 := by - rw [coe_compl, mul_sub, mul_one, P.prop.proj.eq, sub_self] + rw [coe_compl, P.prop.proj.mul_one_sub_self] theorem distrib_lattice_lemma [FaithfulSMul M X] {P Q R : { P : M // IsLprojection X P }} : ((↑P : M) + ↑Pᶜ * R) * (↑P + ↑Q * ↑R * ↑Pᶜ) = ↑P + ↑Q * ↑R * ↑Pᶜ := by From 973fc78afb24119af738f370764bf7820a4e86a8 Mon Sep 17 00:00:00 2001 From: Michael Stoll Date: Fri, 10 Jan 2025 08:14:56 +0000 Subject: [PATCH 124/681] feat(Algebra/Order/Archimedean/Basic): powers between two elements (#20612) This adds two lemmas on linearly ordered semifields: if `0 < c < 1` and `a < b * c`, then (under suitable conditions on `b`) there is a power `c ^ n` (with `n` a natural number / an integer) strictly between `a` and `b`. --- Mathlib/Algebra/Order/Archimedean/Basic.lean | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Mathlib/Algebra/Order/Archimedean/Basic.lean b/Mathlib/Algebra/Order/Archimedean/Basic.lean index d650574b73cde..25474b8851fe4 100644 --- a/Mathlib/Algebra/Order/Archimedean/Basic.lean +++ b/Mathlib/Algebra/Order/Archimedean/Basic.lean @@ -300,6 +300,43 @@ theorem exists_nat_pow_near_of_lt_one (xpos : 0 < x) (hx : x ≤ 1) (ypos : 0 < · rwa [inv_pow, inv_lt_inv₀ xpos (pow_pos ypos _)] at h'n · rwa [inv_pow, inv_le_inv₀ (pow_pos ypos _) xpos] at hn +/-- If `a < b * c`, `0 < b ≤ 1` and `0 < c < 1`, then there is a power `c ^ n` with `n : ℕ` +strictly between `a` and `b`. -/ +lemma exists_pow_btwn_of_lt_mul {a b c : α} (h : a < b * c) (hb₀ : 0 < b) (hb₁ : b ≤ 1) + (hc₀ : 0 < c) (hc₁ : c < 1) : + ∃ n : ℕ, a < c ^ n ∧ c ^ n < b := by + have := exists_pow_lt_of_lt_one hb₀ hc₁ + refine ⟨Nat.find this, h.trans_le ?_, Nat.find_spec this⟩ + by_contra! H + have hn : Nat.find this ≠ 0 := by + intro hf + simp only [hf, pow_zero] at H + exact (H.trans <| Left.mul_lt_of_le_of_lt_one_of_pos hb₁ hc₁ hb₀).false + rw [(Nat.succ_pred_eq_of_ne_zero hn).symm, pow_succ, mul_lt_mul_right hc₀] at H + exact Nat.find_min this (Nat.sub_one_lt hn) H + +/-- If `a < b * c`, `b` is positive and `0 < c < 1`, then there is a power `c ^ n` with `n : ℤ` +strictly between `a` and `b`. -/ +lemma exists_zpow_btwn_of_lt_mul {a b c : α} (h : a < b * c) (hb₀ : 0 < b) (hc₀ : 0 < c) + (hc₁ : c < 1) : + ∃ n : ℤ, a < c ^ n ∧ c ^ n < b := by + rcases le_or_lt a 0 with ha | ha + · obtain ⟨n, hn⟩ := exists_pow_lt_of_lt_one hb₀ hc₁ + exact ⟨n, ha.trans_lt (zpow_pos hc₀ _), mod_cast hn⟩ + · rcases le_or_lt b 1 with hb₁ | hb₁ + · obtain ⟨n, hn⟩ := exists_pow_btwn_of_lt_mul h hb₀ hb₁ hc₀ hc₁ + exact ⟨n, mod_cast hn⟩ + · rcases lt_or_le a 1 with ha₁ | ha₁ + · refine ⟨0, ?_⟩ + rw [zpow_zero] + exact ⟨ha₁, hb₁⟩ + · have : b⁻¹ < a⁻¹ * c := by rwa [lt_inv_mul_iff₀' ha, inv_mul_lt_iff₀ hb₀] + obtain ⟨n, hn₁, hn₂⟩ := + exists_pow_btwn_of_lt_mul this (inv_pos_of_pos ha) (inv_le_one_of_one_le₀ ha₁) hc₀ hc₁ + refine ⟨-n, ?_, ?_⟩ + · rwa [lt_inv_comm₀ (pow_pos hc₀ n) ha, ← zpow_natCast, ← zpow_neg] at hn₂ + · rwa [inv_lt_comm₀ hb₀ (pow_pos hc₀ n), ← zpow_natCast, ← zpow_neg] at hn₁ + end LinearOrderedSemifield section LinearOrderedField From 593e78d77374d0f1be3f42745cf2818c7c4792a5 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Fri, 10 Jan 2025 09:20:15 +0000 Subject: [PATCH 125/681] chore(Data/Set): split the `CoeSort` instance to its own file (#19031) Although `Data.Set.Operations` is somewhat light-weight, it still pulls in a few imports. In particular, if we want to move the definition of `Set.Finite` to `Data.Finite.Defs`, then `Algebra.Group.Int` will complain that it's not allowed to import `Set.range` from `Data.Set.Operations`; this split will allow us to do the move without removing an `assert_not_exists`. See also this discussion on GitHub: https://github.com/leanprover-community/mathlib4/pull/18619#discussion_r1841131715 Zulip thread: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Splitting.20docs.23Set.2EinstCoeSortType.20to.20its.20own.20file.3F --- Mathlib.lean | 1 + Mathlib/Algebra/Group/Int.lean | 3 ++- Mathlib/CategoryTheory/Types.lean | 2 +- Mathlib/Data/Finite/Defs.lean | 2 +- Mathlib/Data/Set/CoeSort.lean | 38 +++++++++++++++++++++++++++++++ Mathlib/Data/Set/Operations.lean | 14 +----------- 6 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 Mathlib/Data/Set/CoeSort.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2e824707ad03b..bc07e3a6bf420 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2920,6 +2920,7 @@ import Mathlib.Data.Set.Accumulate import Mathlib.Data.Set.Basic import Mathlib.Data.Set.BoolIndicator import Mathlib.Data.Set.Card +import Mathlib.Data.Set.CoeSort import Mathlib.Data.Set.Constructions import Mathlib.Data.Set.Countable import Mathlib.Data.Set.Defs diff --git a/Mathlib/Algebra/Group/Int.lean b/Mathlib/Algebra/Group/Int.lean index 48a61e037e493..d2c72a3f581ca 100644 --- a/Mathlib/Algebra/Group/Int.lean +++ b/Mathlib/Algebra/Group/Int.lean @@ -16,8 +16,9 @@ This file contains the additive group and multiplicative monoid instances on the See note [foundational algebra order theory]. -/ -assert_not_exists Ring assert_not_exists DenselyOrdered +assert_not_exists Ring +assert_not_exists Set.range open Nat diff --git a/Mathlib/CategoryTheory/Types.lean b/Mathlib/CategoryTheory/Types.lean index 769ed82413b8d..12a318305da27 100644 --- a/Mathlib/CategoryTheory/Types.lean +++ b/Mathlib/CategoryTheory/Types.lean @@ -5,7 +5,7 @@ Authors: Stephen Morgan, Kim Morrison, Johannes Hölzl -/ import Mathlib.CategoryTheory.EpiMono import Mathlib.CategoryTheory.Functor.FullyFaithful -import Mathlib.Data.Set.Operations +import Mathlib.Data.Set.CoeSort import Mathlib.Tactic.PPWithUniv import Mathlib.Tactic.ToAdditive diff --git a/Mathlib/Data/Finite/Defs.lean b/Mathlib/Data/Finite/Defs.lean index c1396527a27c7..da0ccaeee91f3 100644 --- a/Mathlib/Data/Finite/Defs.lean +++ b/Mathlib/Data/Finite/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Mathlib.Data.Set.Operations +import Mathlib.Data.Set.CoeSort import Mathlib.Logic.Equiv.Defs import Mathlib.Tactic.Set import Mathlib.Util.AssertExists diff --git a/Mathlib/Data/Set/CoeSort.lean b/Mathlib/Data/Set/CoeSort.lean new file mode 100644 index 0000000000000..d92b9a1039789 --- /dev/null +++ b/Mathlib/Data/Set/CoeSort.lean @@ -0,0 +1,38 @@ +/- +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, Kim Morrison, Patrick Massot, Kyle Miller, +Minchao Wu, Yury Kudryashov, Floris van Doorn +-/ +import Mathlib.Data.Set.Defs + +/-! +# Coercing sets to types. + +This file defines `Set.Elem s` as the type of all elements of the set `s`. +More advanced theorems about these definitions are located in other files in `Mathlib/Data/Set`. + +## Main definitions + +- `Set.Elem`: coercion of a set to a type; it is reducibly equal to `{x // x ∈ s}`; +-/ + +namespace Set + +universe u v w + +variable {α : Type u} {β : Type v} {γ : Type w} + +-- Porting note: I've introduced this abbreviation, with the `@[coe]` attribute, +-- so that `norm_cast` has something to index on. +-- It is currently an abbreviation so that instance coming from `Subtype` are available. +-- If you're interested in making it a `def`, as it probably should be, +-- you'll then need to create additional instances (and possibly prove lemmas about them). +-- The first error should appear below at `monotoneOn_iff_monotone`. +/-- Given the set `s`, `Elem s` is the `Type` of element of `s`. -/ +@[coe, reducible] def Elem (s : Set α) : Type u := {x // x ∈ s} + +/-- Coercion from a set to the corresponding subtype. -/ +instance : CoeSort (Set α) (Type u) := ⟨Elem⟩ + +end Set diff --git a/Mathlib/Data/Set/Operations.lean b/Mathlib/Data/Set/Operations.lean index 8abbfac04aea9..728594a19a7e6 100644 --- a/Mathlib/Data/Set/Operations.lean +++ b/Mathlib/Data/Set/Operations.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Johannes Hölzl, Reid Barton, Kim Morrison, Patrick Massot, Kyle Miller, Minchao Wu, Yury Kudryashov, Floris van Doorn -/ +import Mathlib.Data.Set.CoeSort import Mathlib.Data.SProd import Mathlib.Data.Subtype import Mathlib.Order.Notation @@ -19,7 +20,6 @@ More advanced theorems about these definitions are located in other files in `Ma ## Main definitions - complement of a set and set difference; -- `Set.Elem`: coercion of a set to a type; it is reducibly equal to `{x // x ∈ s}`; - `Set.preimage f s`, a.k.a. `f ⁻¹' s`: preimage of a set; - `Set.range f`: the range of a function; it is more general than `f '' univ` because it allows functions from `Sort*`; @@ -89,18 +89,6 @@ theorem diff_eq (s t : Set α) : s \ t = s ∩ tᶜ := rfl theorem mem_diff_of_mem {s t : Set α} {x : α} (h1 : x ∈ s) (h2 : x ∉ t) : x ∈ s \ t := ⟨h1, h2⟩ --- Porting note: I've introduced this abbreviation, with the `@[coe]` attribute, --- so that `norm_cast` has something to index on. --- It is currently an abbreviation so that instance coming from `Subtype` are available. --- If you're interested in making it a `def`, as it probably should be, --- you'll then need to create additional instances (and possibly prove lemmas about them). --- The first error should appear below at `monotoneOn_iff_monotone`. -/-- Given the set `s`, `Elem s` is the `Type` of element of `s`. -/ -@[coe, reducible] def Elem (s : Set α) : Type u := {x // x ∈ s} - -/-- Coercion from a set to the corresponding subtype. -/ -instance : CoeSort (Set α) (Type u) := ⟨Elem⟩ - /-- The preimage of `s : Set β` by `f : α → β`, written `f ⁻¹' s`, is the set of `x : α` such that `f x ∈ s`. -/ def preimage (f : α → β) (s : Set β) : Set α := {x | f x ∈ s} From a34316ac0f573a1944c8c130c22431db6344357d Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Fri, 10 Jan 2025 10:37:16 +0000 Subject: [PATCH 126/681] chore(Data/Finsupp): split off extensionality from `Defs.lean` (#19092) These results depend on `Submonoid`, while nothing else in `Finsupp` does. So let's move them to their own file. --- Mathlib.lean | 1 + Mathlib/Algebra/BigOperators/Finsupp.lean | 1 + Mathlib/Data/Finsupp/Defs.lean | 47 +-------------- Mathlib/Data/Finsupp/Ext.lean | 72 +++++++++++++++++++++++ 4 files changed, 75 insertions(+), 46 deletions(-) create mode 100644 Mathlib/Data/Finsupp/Ext.lean diff --git a/Mathlib.lean b/Mathlib.lean index bc07e3a6bf420..9c115d50ad07e 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2557,6 +2557,7 @@ import Mathlib.Data.Finsupp.Basic import Mathlib.Data.Finsupp.BigOperators import Mathlib.Data.Finsupp.Defs import Mathlib.Data.Finsupp.Encodable +import Mathlib.Data.Finsupp.Ext import Mathlib.Data.Finsupp.Fin import Mathlib.Data.Finsupp.Fintype import Mathlib.Data.Finsupp.Indicator diff --git a/Mathlib/Algebra/BigOperators/Finsupp.lean b/Mathlib/Algebra/BigOperators/Finsupp.lean index 056c1427d57a0..274bc2fbb8ff2 100644 --- a/Mathlib/Algebra/BigOperators/Finsupp.lean +++ b/Mathlib/Algebra/BigOperators/Finsupp.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.BigOperators.Fin import Mathlib.Algebra.Group.Submonoid.BigOperators +import Mathlib.Data.Finsupp.Ext import Mathlib.Data.Finsupp.Fin import Mathlib.Data.Finsupp.Indicator diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index 525b7a364dc57..538a8cf25d50c 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -4,10 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.Group.Indicator -import Mathlib.Algebra.Group.Submonoid.Basic import Mathlib.Data.Finset.Max import Mathlib.Data.Set.Finite.Basic -import Mathlib.Algebra.Group.TypeTags.Hom /-! # Type of functions with finite support @@ -81,6 +79,7 @@ This file is a `noncomputable theory` and uses classical logic throughout. -/ +assert_not_exists Submonoid noncomputable section @@ -1130,50 +1129,6 @@ theorem induction_on_min₂ (f : α →₀ M) (h0 : p 0) end LinearOrder -@[simp] -theorem add_closure_setOf_eq_single : - AddSubmonoid.closure { f : α →₀ M | ∃ a b, f = single a b } = ⊤ := - top_unique fun x _hx => - Finsupp.induction x (AddSubmonoid.zero_mem _) fun a b _f _ha _hb hf => - AddSubmonoid.add_mem _ (AddSubmonoid.subset_closure <| ⟨a, b, rfl⟩) hf - -/-- If two additive homomorphisms from `α →₀ M` are equal on each `single a b`, -then they are equal. -/ -theorem addHom_ext [AddZeroClass N] ⦃f g : (α →₀ M) →+ N⦄ - (H : ∀ x y, f (single x y) = g (single x y)) : f = g := by - refine AddMonoidHom.eq_of_eqOn_denseM add_closure_setOf_eq_single ?_ - rintro _ ⟨x, y, rfl⟩ - apply H - -/-- If two additive homomorphisms from `α →₀ M` are equal on each `single a b`, -then they are equal. - -We formulate this using equality of `AddMonoidHom`s so that `ext` tactic can apply a type-specific -extensionality lemma after this one. E.g., if the fiber `M` is `ℕ` or `ℤ`, then it suffices to -verify `f (single a 1) = g (single a 1)`. -/ -@[ext high] -theorem addHom_ext' [AddZeroClass N] ⦃f g : (α →₀ M) →+ N⦄ - (H : ∀ x, f.comp (singleAddHom x) = g.comp (singleAddHom x)) : f = g := - addHom_ext fun x => DFunLike.congr_fun (H x) - -theorem mulHom_ext [MulOneClass N] ⦃f g : Multiplicative (α →₀ M) →* N⦄ - (H : ∀ x y, f (Multiplicative.ofAdd <| single x y) = g (Multiplicative.ofAdd <| single x y)) : - f = g := - MonoidHom.ext <| - DFunLike.congr_fun <| by - have := @addHom_ext α M (Additive N) _ _ - (MonoidHom.toAdditive'' f) (MonoidHom.toAdditive'' g) H - ext - rw [DFunLike.ext_iff] at this - apply this - -@[ext] -theorem mulHom_ext' [MulOneClass N] {f g : Multiplicative (α →₀ M) →* N} - (H : ∀ x, f.comp (AddMonoidHom.toMultiplicative (singleAddHom x)) = - g.comp (AddMonoidHom.toMultiplicative (singleAddHom x))) : - f = g := - mulHom_ext fun x => DFunLike.congr_fun (H x) - theorem mapRange_add [AddZeroClass N] {f : M → N} {hf : f 0 = 0} (hf' : ∀ x y, f (x + y) = f x + f y) (v₁ v₂ : α →₀ M) : mapRange f hf (v₁ + v₂) = mapRange f hf v₁ + mapRange f hf v₂ := diff --git a/Mathlib/Data/Finsupp/Ext.lean b/Mathlib/Data/Finsupp/Ext.lean new file mode 100644 index 0000000000000..14f8617ffb6f7 --- /dev/null +++ b/Mathlib/Data/Finsupp/Ext.lean @@ -0,0 +1,72 @@ +/- +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, Kim Morrison +-/ +import Mathlib.Algebra.Group.Submonoid.Basic +import Mathlib.Algebra.Group.TypeTags.Hom +import Mathlib.Data.Finsupp.Defs + +/-! +# Extensionality for maps on `Finsupp` + +This file contains some extensionality principles for maps on `Finsupp`. +These have been moved to their own file to avoid depending on submonoids when defining `Finsupp`. + +## Main results + +* `Finsupp.add_closure_setOf_eq_single`: `Finsupp` is generated by all the `single`s +* `Finsupp.addHom_ext`: additive homomorphisms that are equal on each `single` are equal everywhere +-/ + +variable {α M N : Type*} + +namespace Finsupp + +variable [AddZeroClass M] + +@[simp] +theorem add_closure_setOf_eq_single : + AddSubmonoid.closure { f : α →₀ M | ∃ a b, f = single a b } = ⊤ := + top_unique fun x _hx => + Finsupp.induction x (AddSubmonoid.zero_mem _) fun a b _f _ha _hb hf => + AddSubmonoid.add_mem _ (AddSubmonoid.subset_closure <| ⟨a, b, rfl⟩) hf + +/-- If two additive homomorphisms from `α →₀ M` are equal on each `single a b`, +then they are equal. -/ +theorem addHom_ext [AddZeroClass N] ⦃f g : (α →₀ M) →+ N⦄ + (H : ∀ x y, f (single x y) = g (single x y)) : f = g := by + refine AddMonoidHom.eq_of_eqOn_denseM add_closure_setOf_eq_single ?_ + rintro _ ⟨x, y, rfl⟩ + apply H + +/-- If two additive homomorphisms from `α →₀ M` are equal on each `single a b`, +then they are equal. + +We formulate this using equality of `AddMonoidHom`s so that `ext` tactic can apply a type-specific +extensionality lemma after this one. E.g., if the fiber `M` is `ℕ` or `ℤ`, then it suffices to +verify `f (single a 1) = g (single a 1)`. -/ +@[ext high] +theorem addHom_ext' [AddZeroClass N] ⦃f g : (α →₀ M) →+ N⦄ + (H : ∀ x, f.comp (singleAddHom x) = g.comp (singleAddHom x)) : f = g := + addHom_ext fun x => DFunLike.congr_fun (H x) + +theorem mulHom_ext [MulOneClass N] ⦃f g : Multiplicative (α →₀ M) →* N⦄ + (H : ∀ x y, f (Multiplicative.ofAdd <| single x y) = g (Multiplicative.ofAdd <| single x y)) : + f = g := + MonoidHom.ext <| + DFunLike.congr_fun <| by + have := @addHom_ext α M (Additive N) _ _ + (MonoidHom.toAdditive'' f) (MonoidHom.toAdditive'' g) H + ext + rw [DFunLike.ext_iff] at this + apply this + +@[ext] +theorem mulHom_ext' [MulOneClass N] {f g : Multiplicative (α →₀ M) →* N} + (H : ∀ x, f.comp (AddMonoidHom.toMultiplicative (singleAddHom x)) = + g.comp (AddMonoidHom.toMultiplicative (singleAddHom x))) : + f = g := + mulHom_ext fun x => DFunLike.congr_fun (H x) + +end Finsupp From e6e790275113b6bed3432cfc5a6929478604dc4e Mon Sep 17 00:00:00 2001 From: Michael Stoll Date: Fri, 10 Jan 2025 11:19:29 +0000 Subject: [PATCH 127/681] feat: AbsoluteValue.IsNontrivial (#20588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This introduces `v.IsNontrivial : Prop` for `v : AbsoluteValue R S`; this states that `v x ≠ 1` for some `x ≠ 0`. This is more convenient to use than `v ≠ .trivial` since it does not require additional assumptions on `R` or `S` (whereas `AbsoluteValue.trivial` needs `x = 0` to be decidable in `R`, `R` to have no zero divisors and `S` to be nontrivial). We also adapt `NumberTheory.Ostrowski` to use `IsNontrivial` instead of `≠ .trivial`. --- .../Algebra/Order/AbsoluteValue/Basic.lean | 56 +++++++++++++++++++ Mathlib/NumberTheory/Ostrowski.lean | 11 ++-- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Mathlib/Algebra/Order/AbsoluteValue/Basic.lean b/Mathlib/Algebra/Order/AbsoluteValue/Basic.lean index c9440b72f7831..39413e7dcbea8 100644 --- a/Mathlib/Algebra/Order/AbsoluteValue/Basic.lean +++ b/Mathlib/Algebra/Order/AbsoluteValue/Basic.lean @@ -312,6 +312,62 @@ lemma trivial_apply {x : R} (hx : x ≠ 0) : AbsoluteValue.trivial (S := S) x = end trivial +section nontrivial + +variable {R : Type*} [Semiring R] {S : Type*} [OrderedSemiring S] + +/-- An absolute value on a semiring `R` without zero divisors is *nontrivial* if it takes +a value `≠ 1` on a nonzero element. + +This has the advantage over `v ≠ .trivial` that it does not require decidability +of `· = 0` in `R`. -/ +def IsNontrivial (v : AbsoluteValue R S) : Prop := + ∃ x ≠ 0, v x ≠ 1 + +lemma isNontrivial_iff_ne_trivial [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R] + [Nontrivial S] (v : AbsoluteValue R S) : + v.IsNontrivial ↔ v ≠ .trivial := by + refine ⟨fun ⟨x, hx₀, hx₁⟩ h ↦ hx₁ <| h.symm ▸ trivial_apply hx₀, fun H ↦ ?_⟩ + contrapose! H + simp only [IsNontrivial] at H + push_neg at H + ext1 x + rcases eq_or_ne x 0 with rfl | hx + · simp + · simp [H, hx] + +lemma not_isNontrivial_iff (v : AbsoluteValue R S) : + ¬ v.IsNontrivial ↔ ∀ x ≠ 0, v x = 1 := by + simp only [IsNontrivial] + push_neg + rfl + +@[simp] +lemma not_isNontrivial_apply {v : AbsoluteValue R S} (hv : ¬ v.IsNontrivial) {x : R} (hx : x ≠ 0) : + v x = 1 := + v.not_isNontrivial_iff.mp hv _ hx + +lemma IsNontrivial.exists_abv_gt_one {F S : Type*} [Field F] [LinearOrderedField S] + {v : AbsoluteValue F S} (h : v.IsNontrivial) : + ∃ x, 1 < v x := by + obtain ⟨x, hx₀, hx₁⟩ := h + rcases hx₁.lt_or_lt with h | h + · refine ⟨x⁻¹, ?_⟩ + rw [map_inv₀] + exact (one_lt_inv₀ <| v.pos hx₀).mpr h + · exact ⟨x, h⟩ + +lemma IsNontrivial.exists_abv_lt_one {F S : Type*} [Field F] [LinearOrderedField S] + {v : AbsoluteValue F S} (h : v.IsNontrivial) : + ∃ x ≠ 0, v x < 1 := by + obtain ⟨y, hy⟩ := h.exists_abv_gt_one + have hy₀ := v.ne_zero_iff.mp <| (zero_lt_one.trans hy).ne' + refine ⟨y⁻¹, inv_ne_zero hy₀, ?_⟩ + rw [map_inv₀] + exact (inv_lt_one₀ <| v.pos hy₀).mpr hy + +end nontrivial + end AbsoluteValue -- Porting note: Removed [] in fields, see diff --git a/Mathlib/NumberTheory/Ostrowski.lean b/Mathlib/NumberTheory/Ostrowski.lean index 2deb7a4a4f251..292717210cee3 100644 --- a/Mathlib/NumberTheory/Ostrowski.lean +++ b/Mathlib/NumberTheory/Ostrowski.lean @@ -121,7 +121,7 @@ lemma padic_le_one (p : ℕ) [Fact p.Prime] (n : ℤ) : padic p n ≤ 1 := by -- ## Step 1: define `p = minimal n s. t. 0 < f n < 1` -variable (hf_nontriv : f ≠ .trivial) (bdd : ∀ n : ℕ, f n ≤ 1) +variable (hf_nontriv : f.IsNontrivial) (bdd : ∀ n : ℕ, f n ≤ 1) include hf_nontriv bdd in /-- There exists a minimal positive integer with absolute value smaller than 1. -/ @@ -130,11 +130,10 @@ lemma exists_minimal_nat_zero_lt_and_lt_one : -- There is a positive integer with absolute value different from one. obtain ⟨n, hn1, hn2⟩ : ∃ n : ℕ, n ≠ 0 ∧ f n ≠ 1 := by contrapose! hf_nontriv - rw [AbsoluteValue.trivial, ← eq_on_nat_iff_eq] - intro n - rcases eq_or_ne n 0 with rfl | hn0 + refine (isNontrivial_iff_ne_trivial f).not_left.mpr <| eq_on_nat_iff_eq.mp fun n ↦ ?_ + rcases eq_or_ne n 0 with rfl | hn · simp - · simp [hn0, hf_nontriv n hn0] + · simp [hf_nontriv, hn] set P := {m : ℕ | 0 < f ↑m ∧ f ↑m < 1} -- p is going to be the minimum of this set. have hP : P.Nonempty := ⟨n, map_pos_of_ne_zero f (Nat.cast_ne_zero.mpr hn1), lt_of_le_of_ne (bdd n) hn2⟩ @@ -465,7 +464,7 @@ end Archimedean /-- **Ostrowski's Theorem**: every absolute value (with values in `ℝ`) on `ℚ` is equivalent to either the standard absolute value or a `p`-adic absolute value for a prime `p`. -/ -theorem equiv_real_or_padic (f : AbsoluteValue ℚ ℝ) (hf_nontriv : f ≠ .trivial) : +theorem equiv_real_or_padic (f : AbsoluteValue ℚ ℝ) (hf_nontriv : f.IsNontrivial) : f ≈ real ∨ ∃! p, ∃ (_ : Fact p.Prime), f ≈ (padic p) := by by_cases bdd : ∀ n : ℕ, f n ≤ 1 · exact .inr <| equiv_padic_of_bounded hf_nontriv bdd From a3ae5436167119ddb305e6df2471883824d05bcc Mon Sep 17 00:00:00 2001 From: grunweg Date: Fri, 10 Jan 2025 13:09:55 +0000 Subject: [PATCH 128/681] chore(Geometry/Manifold): move SmoothManifoldWithCorners.lean to IsManifold.lean (#20611) Follow-up to #19696; split into a separate PR to not confuse git. --- Mathlib.lean | 2 +- Mathlib/Geometry/Manifold/AnalyticManifold.lean | 2 +- Mathlib/Geometry/Manifold/ContMDiff/Defs.lean | 2 +- Mathlib/Geometry/Manifold/Instances/Real.lean | 4 ++-- Mathlib/Geometry/Manifold/InteriorBoundary.lean | 2 +- .../{SmoothManifoldWithCorners.lean => IsManifold.lean} | 0 Mathlib/Geometry/Manifold/MFDeriv/Defs.lean | 2 +- Mathlib/Geometry/Manifold/Metrizable.lean | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) rename Mathlib/Geometry/Manifold/{SmoothManifoldWithCorners.lean => IsManifold.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 9c115d50ad07e..7f0699745d63a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3162,6 +3162,7 @@ import Mathlib.Geometry.Manifold.IntegralCurve.ExistUnique import Mathlib.Geometry.Manifold.IntegralCurve.Transform import Mathlib.Geometry.Manifold.IntegralCurve.UniformTime import Mathlib.Geometry.Manifold.InteriorBoundary +import Mathlib.Geometry.Manifold.IsManifold import Mathlib.Geometry.Manifold.LocalDiffeomorph import Mathlib.Geometry.Manifold.LocalInvariantProperties import Mathlib.Geometry.Manifold.MFDeriv.Atlas @@ -3178,7 +3179,6 @@ import Mathlib.Geometry.Manifold.PoincareConjecture import Mathlib.Geometry.Manifold.Sheaf.Basic import Mathlib.Geometry.Manifold.Sheaf.LocallyRingedSpace import Mathlib.Geometry.Manifold.Sheaf.Smooth -import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners import Mathlib.Geometry.Manifold.VectorBundle.Basic import Mathlib.Geometry.Manifold.VectorBundle.FiberwiseLinear import Mathlib.Geometry.Manifold.VectorBundle.Hom diff --git a/Mathlib/Geometry/Manifold/AnalyticManifold.lean b/Mathlib/Geometry/Manifold/AnalyticManifold.lean index 5765ec3b44ce1..9b6c9a3025046 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.Geometry.Manifold.SmoothManifoldWithCorners +import Mathlib.Geometry.Manifold.IsManifold /-! # Analytic manifolds (possibly with boundary or corners) diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean index c83d7d410a374..4bb05df82f4ff 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Floris van Doorn -/ -import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners +import Mathlib.Geometry.Manifold.IsManifold import Mathlib.Geometry.Manifold.LocalInvariantProperties /-! diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index f13382bb2dbcc..53744ed74a346 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 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.Geometry.Manifold.SmoothManifoldWithCorners +import Mathlib.Geometry.Manifold.IsManifold import Mathlib.Analysis.InnerProductSpace.PiL2 /-! @@ -31,7 +31,7 @@ For instance, if a manifold `M` is boundaryless, smooth and modelled on `Euclide and `N` is smooth with boundary modelled on `EuclideanHalfSpace n`, and `f : M → N` is a smooth map, then the derivative of `f` can be written simply as `mfderiv (𝓡 m) (𝓡∂ n) f` (as to why the model with corners can not be implicit, see the discussion in -`Geometry.Manifold.SmoothManifoldWithCorners`). +`Geometry.Manifold.IsManifold`). ## Implementation notes diff --git a/Mathlib/Geometry/Manifold/InteriorBoundary.lean b/Mathlib/Geometry/Manifold/InteriorBoundary.lean index e0b0e8b3f65ff..d3f2825cc0551 100644 --- a/Mathlib/Geometry/Manifold/InteriorBoundary.lean +++ b/Mathlib/Geometry/Manifold/InteriorBoundary.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Rothgang -/ -import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners +import Mathlib.Geometry.Manifold.IsManifold /-! # Interior and boundary of a manifold diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/IsManifold.lean similarity index 100% rename from Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean rename to Mathlib/Geometry/Manifold/IsManifold.lean diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean index ff24fc3a520eb..c269a880e9c26 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Floris van Doorn -/ -import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners +import Mathlib.Geometry.Manifold.IsManifold import Mathlib.Geometry.Manifold.LocalInvariantProperties /-! diff --git a/Mathlib/Geometry/Manifold/Metrizable.lean b/Mathlib/Geometry/Manifold/Metrizable.lean index c7f475ac0cda0..5427ae259b734 100644 --- a/Mathlib/Geometry/Manifold/Metrizable.lean +++ b/Mathlib/Geometry/Manifold/Metrizable.lean @@ -3,7 +3,7 @@ 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.Geometry.Manifold.SmoothManifoldWithCorners +import Mathlib.Geometry.Manifold.IsManifold import Mathlib.Topology.Compactness.Paracompact import Mathlib.Topology.Metrizable.Urysohn From 12958ea99bca55cd7aa6d5d1dcf4b825e2748299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 13:20:15 +0000 Subject: [PATCH 129/681] =?UTF-8?q?feat:=20`=E2=A8=85=20i,=20f=20i=20?= =?UTF-8?q?=E2=89=A4=20=E2=A8=86=20i,=20f=20i`=20(#20573)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From my PhD (LeanCamCombi) --- Mathlib/Data/Set/Lattice.lean | 5 +++++ Mathlib/Order/CompleteLattice.lean | 15 ++++++++++----- .../ConditionallyCompleteLattice/Indexed.lean | 4 ++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Mathlib/Data/Set/Lattice.lean b/Mathlib/Data/Set/Lattice.lean index 0a3b5101f9ede..31894eed4fc4a 100644 --- a/Mathlib/Data/Set/Lattice.lean +++ b/Mathlib/Data/Set/Lattice.lean @@ -248,6 +248,8 @@ theorem subset_iUnion : ∀ (s : ι → Set β) (i : ι), s i ⊆ ⋃ i, s i := theorem iInter_subset : ∀ (s : ι → Set β) (i : ι), ⋂ i, s i ⊆ s i := iInf_le +lemma iInter_subset_iUnion [Nonempty ι] {s : ι → Set α} : ⋂ i, s i ⊆ ⋃ i, s i := iInf_le_iSup + /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ theorem subset_iUnion₂ {s : ∀ i, κ i → Set α} (i : ι) (j : κ i) : s i j ⊆ ⋃ (i') (j'), s i' j' := le_iSup₂ i j @@ -728,6 +730,9 @@ theorem biInter_subset_of_mem {s : Set α} {t : α → Set β} {x : α} (xs : x ⋂ x ∈ s, t x ⊆ t x := iInter₂_subset x xs +lemma biInter_subset_biUnion {s : Set α} (hs : s.Nonempty) {t : α → Set β} : + ⋂ x ∈ s, t x ⊆ ⋃ x ∈ s, t x := biInf_le_biSup hs + theorem biUnion_subset_biUnion_left {s s' : Set α} {t : α → Set β} (h : s ⊆ s') : ⋃ x ∈ s, t x ⊆ ⋃ x ∈ s', t x := iUnion₂_subset fun _ hx => subset_biUnion_of_mem <| h hx diff --git a/Mathlib/Order/CompleteLattice.lean b/Mathlib/Order/CompleteLattice.lean index d1c676bce4fdf..e68234ef30fbb 100644 --- a/Mathlib/Order/CompleteLattice.lean +++ b/Mathlib/Order/CompleteLattice.lean @@ -632,6 +632,9 @@ theorem le_iSup (f : ι → α) (i : ι) : f i ≤ iSup f := theorem iInf_le (f : ι → α) (i : ι) : iInf f ≤ f i := sInf_le ⟨i, rfl⟩ +lemma iInf_le_iSup [Nonempty ι] : ⨅ i, f i ≤ ⨆ i, f i := + (iInf_le _ (Classical.arbitrary _)).trans <| le_iSup _ (Classical.arbitrary _) + @[deprecated le_iSup (since := "2024-12-13")] theorem le_iSup' (f : ι → α) (i : ι) : f i ≤ iSup f := le_iSup f i @@ -1033,14 +1036,16 @@ lemma Equiv.biInf_comp {ι ι' : Type*} {g : ι' → α} (e : ι ≃ ι') (s : S ⨅ i ∈ e.symm '' s, g (e i) = ⨅ i ∈ s, g i := e.biSup_comp s (α := αᵒᵈ) -lemma biInf_le {ι : Type*} {s : Set ι} (f : ι → α) {i : ι} (hi : i ∈ s) : - ⨅ i ∈ s, f i ≤ f i := by - simpa only [iInf_subtype'] using iInf_le (ι := s) (f := f ∘ (↑)) ⟨i, hi⟩ +lemma biInf_le {ι : Type*} {s : Set ι} (f : ι → α) {i : ι} (hi : i ∈ s) : ⨅ i ∈ s, f i ≤ f i := + iInf₂_le i hi -lemma le_biSup {ι : Type*} {s : Set ι} (f : ι → α) {i : ι} (hi : i ∈ s) : - f i ≤ ⨆ i ∈ s, f i := +lemma le_biSup {ι : Type*} {s : Set ι} (f : ι → α) {i : ι} (hi : i ∈ s) : f i ≤ ⨆ i ∈ s, f i := biInf_le (α := αᵒᵈ) f hi +lemma biInf_le_biSup {ι : Type*} {s : Set ι} (hs : s.Nonempty) {f : ι → α} : + ⨅ i ∈ s, f i ≤ ⨆ i ∈ s, f i := + (biInf_le _ hs.choose_spec).trans <| le_biSup _ hs.choose_spec + /- TODO: here is another example where more flexible pattern matching might help. diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Indexed.lean b/Mathlib/Order/ConditionallyCompleteLattice/Indexed.lean index 1d69aba7a1e11..d351a9cbdf890 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Indexed.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Indexed.lean @@ -151,6 +151,10 @@ theorem ciInf_set_le {f : β → α} {s : Set β} (H : BddBelow (f '' s)) {c : ⨅ i : s, f i ≤ f c := le_ciSup_set (α := αᵒᵈ) H hc +lemma ciInf_le_ciSup [Nonempty ι] {f : ι → α} (hf : BddBelow (range f)) (hf' : BddAbove (range f)) : + ⨅ i, f i ≤ ⨆ i, f i := + (ciInf_le hf (Classical.arbitrary _)).trans <| le_ciSup hf' (Classical.arbitrary _) + @[simp] theorem ciSup_const [hι : Nonempty ι] {a : α} : ⨆ _ : ι, a = a := by rw [iSup, range_const, csSup_singleton] From 804cb796736054b3535fd562bb4870aaabb222d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 13:20:16 +0000 Subject: [PATCH 130/681] =?UTF-8?q?feat:=20If=20`s=20=E2=88=86=20t`=20is?= =?UTF-8?q?=20finite,=20then=20`s=20=E2=88=86=20u`=20is=20finite=20iff=20`?= =?UTF-8?q?t=20=E2=88=86=20u`=20is=20(#20574)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also make `Set.Finite.diff` have one less explicit argument. From my PhD (LeanCamCombi) --- Mathlib/Data/Matroid/IndepAxioms.lean | 4 ++-- Mathlib/Data/Set/Card.lean | 14 +++++++------- Mathlib/Data/Set/Finite/Basic.lean | 13 ++++++++++--- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Mathlib/Data/Matroid/IndepAxioms.lean b/Mathlib/Data/Matroid/IndepAxioms.lean index a18f6951b4618..88e6c6559ce67 100644 --- a/Mathlib/Data/Matroid/IndepAxioms.lean +++ b/Mathlib/Data/Matroid/IndepAxioms.lean @@ -153,7 +153,7 @@ namespace IndepMatroid by_contra h; push_neg at h obtain ⟨I, e, -, hIe, h⟩ := h refine hIe <| indep_compact _ fun J hJss hJfin ↦ ?_ - exact indep_subset (h (J \ {e}) (by rwa [diff_subset_iff]) (hJfin.diff _)) (by simp) + exact indep_subset (h (J \ {e}) (by rwa [diff_subset_iff]) hJfin.diff) (by simp) IndepMatroid.mk (E := E) (Indep := Indep) @@ -177,7 +177,7 @@ namespace IndepMatroid have hchoose : ∀ (b : ↑(B₀ \ I)), ∃ Ib, Ib ⊆ I ∧ Ib.Finite ∧ ¬Indep (insert (b : α) Ib) := by rintro ⟨b, hb⟩; exact htofin I b hI (hcon b ⟨hB₀B hb.1, hb.2⟩) choose! f hf using hchoose - have := (hB₀fin.diff I).to_subtype + have : Finite ↑(B₀ \ I) := hB₀fin.diff.to_subtype refine ⟨iUnion f ∪ (B₀ ∩ I), union_subset (iUnion_subset (fun i ↦ (hf i).1)) inter_subset_right, (finite_iUnion fun i ↦ (hf i).2.1).union (hB₀fin.subset inter_subset_left), diff --git a/Mathlib/Data/Set/Card.lean b/Mathlib/Data/Set/Card.lean index 042625a24b33b..f1dbc517658f9 100644 --- a/Mathlib/Data/Set/Card.lean +++ b/Mathlib/Data/Set/Card.lean @@ -274,7 +274,7 @@ theorem eq_empty_or_encard_eq_top_or_encard_diff_singleton_lt (s : Set α) : refine s.eq_empty_or_nonempty.elim Or.inl (Or.inr ∘ fun ⟨a,ha⟩ ↦ (s.finite_or_infinite.elim (fun hfin ↦ Or.inr ⟨a, ha, ?_⟩) (Or.inl ∘ Infinite.encard_eq))) rw [← encard_diff_singleton_add_one ha]; nth_rw 1 [← add_zero (encard _)] - exact WithTop.add_lt_add_left (hfin.diff _).encard_lt_top.ne zero_lt_one + exact WithTop.add_lt_add_left hfin.diff.encard_lt_top.ne zero_lt_one end InsertErase @@ -423,7 +423,7 @@ theorem Finite.exists_injOn_of_encard_le [Nonempty β] {s : Set α} {t : Set β} rwa [← WithTop.add_le_add_iff_right WithTop.one_ne_top, encard_diff_singleton_add_one has, encard_diff_singleton_add_one hbt] - obtain ⟨f₀, hf₀s, hinj⟩ := exists_injOn_of_encard_le (hs.diff {a}) hle' + obtain ⟨f₀, hf₀s, hinj⟩ := exists_injOn_of_encard_le hs.diff hle' simp only [preimage_diff, subset_def, mem_diff, mem_singleton_iff, mem_preimage, and_imp] at hf₀s use Function.update f₀ a b @@ -584,7 +584,7 @@ theorem ncard_le_ncard_insert (a : α) (s : Set α) : s.ncard ≤ (insert a s).n @[simp] theorem ncard_diff_singleton_add_one {a : α} (h : a ∈ s) (hs : s.Finite := by toFinite_tac) : (s \ {a}).ncard + 1 = s.ncard := by - to_encard_tac; rw [hs.cast_ncard_eq, (hs.diff _).cast_ncard_eq, + to_encard_tac; rw [hs.cast_ncard_eq, hs.diff.cast_ncard_eq, encard_diff_singleton_add_one h] @[simp] theorem ncard_diff_singleton_of_mem {a : α} (h : a ∈ s) (hs : s.Finite := by toFinite_tac) : @@ -823,7 +823,7 @@ theorem ncard_union_eq (h : Disjoint s t) (hs : s.Finite := by toFinite_tac) theorem ncard_diff_add_ncard_of_subset (h : s ⊆ t) (ht : t.Finite := by toFinite_tac) : (t \ s).ncard + s.ncard = t.ncard := by to_encard_tac - rw [ht.cast_ncard_eq, (ht.subset h).cast_ncard_eq, (ht.diff _).cast_ncard_eq, + rw [ht.cast_ncard_eq, (ht.subset h).cast_ncard_eq, ht.diff.cast_ncard_eq, encard_diff_add_encard_of_subset h] theorem ncard_diff (hst : s ⊆ t) (hs : s.Finite := by toFinite_tac) : @@ -840,7 +840,7 @@ theorem ncard_le_ncard_diff_add_ncard (s t : Set α) (ht : t.Finite := by toFini s.ncard ≤ (s \ t).ncard + t.ncard := by cases' s.finite_or_infinite with hs hs · to_encard_tac - rw [ht.cast_ncard_eq, hs.cast_ncard_eq, (hs.diff _).cast_ncard_eq] + rw [ht.cast_ncard_eq, hs.cast_ncard_eq, hs.diff.cast_ncard_eq] apply encard_le_encard_diff_add_encard convert Nat.zero_le _ rw [hs.ncard] @@ -852,7 +852,7 @@ theorem le_ncard_diff (s t : Set α) (hs : s.Finite := by toFinite_tac) : theorem ncard_diff_add_ncard (s t : Set α) (hs : s.Finite := by toFinite_tac) (ht : t.Finite := by toFinite_tac) : (s \ t).ncard + t.ncard = (s ∪ t).ncard := by - rw [← ncard_union_eq disjoint_sdiff_left (hs.diff _) ht, diff_union_self] + rw [← ncard_union_eq disjoint_sdiff_left hs.diff ht, diff_union_self] theorem diff_nonempty_of_ncard_lt_ncard (h : s.ncard < t.ncard) (hs : s.Finite := by toFinite_tac) : (t \ s).Nonempty := by @@ -866,7 +866,7 @@ theorem exists_mem_not_mem_of_ncard_lt_ncard (h : s.ncard < t.ncard) @[simp] theorem ncard_inter_add_ncard_diff_eq_ncard (s t : Set α) (hs : s.Finite := by toFinite_tac) : (s ∩ t).ncard + (s \ t).ncard = s.ncard := by rw [← ncard_union_eq (disjoint_of_subset_left inter_subset_right disjoint_sdiff_right) - (hs.inter_of_left _) (hs.diff _), union_comm, diff_union_inter] + (hs.inter_of_left _) hs.diff, union_comm, diff_union_inter] theorem ncard_eq_ncard_iff_ncard_diff_eq_ncard_diff (hs : s.Finite := by toFinite_tac) (ht : t.Finite := by toFinite_tac) : s.ncard = t.ncard ↔ (s \ t).ncard = (t \ s).ncard := by diff --git a/Mathlib/Data/Set/Finite/Basic.lean b/Mathlib/Data/Set/Finite/Basic.lean index c775fbbcad06a..bddaef6f06011 100644 --- a/Mathlib/Data/Set/Finite/Basic.lean +++ b/Mathlib/Data/Set/Finite/Basic.lean @@ -42,6 +42,7 @@ assert_not_exists OrderedRing assert_not_exists MonoidWithZero open Set Function +open scoped symmDiff universe u v w x @@ -461,6 +462,7 @@ after possibly setting up some `Fintype` and classical `Decidable` instances. section SetFiniteConstructors +variable {s t u : Set α} @[nontriviality] theorem Finite.of_subsingleton [Subsingleton α] (s : Set α) : s.Finite := @@ -477,7 +479,7 @@ theorem Finite.subset {s : Set α} (hs : s.Finite) {t : Set α} (ht : t ⊆ s) : have := hs.to_subtype exact Finite.Set.subset _ ht -theorem Finite.union {s t : Set α} (hs : s.Finite) (ht : t.Finite) : (s ∪ t).Finite := by +theorem Finite.union (hs : s.Finite) (ht : t.Finite) : (s ∪ t).Finite := by rw [Set.Finite] at hs ht apply toFinite @@ -506,12 +508,17 @@ theorem Finite.inf_of_right {s : Set α} (h : s.Finite) (t : Set α) : (t ⊓ s) protected lemma Infinite.mono {s t : Set α} (h : s ⊆ t) : s.Infinite → t.Infinite := mt fun ht ↦ ht.subset h -theorem Finite.diff {s : Set α} (hs : s.Finite) (t : Set α) : (s \ t).Finite := - hs.subset diff_subset +theorem Finite.diff (hs : s.Finite) : (s \ t).Finite := hs.subset diff_subset theorem Finite.of_diff {s t : Set α} (hd : (s \ t).Finite) (ht : t.Finite) : s.Finite := (hd.union ht).subset <| subset_diff_union _ _ +lemma Finite.symmDiff (hs : s.Finite) (ht : t.Finite) : (s ∆ t).Finite := hs.diff.union ht.diff + +lemma Finite.symmDiff_congr (hst : (s ∆ t).Finite) : (s ∆ u).Finite ↔ (t ∆ u).Finite where + mp hsu := (hst.union hsu).subset (symmDiff_comm s t ▸ symmDiff_triangle ..) + mpr htu := (hst.union htu).subset (symmDiff_triangle ..) + @[simp] theorem finite_empty : (∅ : Set α).Finite := toFinite _ From b1178f181de6b53dfc90967c48c70fd5ac282e73 Mon Sep 17 00:00:00 2001 From: Michael Stoll Date: Fri, 10 Jan 2025 13:20:18 +0000 Subject: [PATCH 131/681] feat(Analysis/SpecialFunctions/Pow/Real): add some lemmas (#20608) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a few lemmas on powers with real exponents: * injectivity as a function of the exponent (when the base is positive and ≠ 1) * `(x ^ y) ^ n = (x ^ n) ^ y` when `y` is real and `n` is a natural number or an integer --- Mathlib/Analysis/SpecialFunctions/Pow/Real.lean | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index 7fa60d874f8d7..147304d54580d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -385,6 +385,12 @@ theorem rpow_mul {x : ℝ} (hx : 0 ≤ x) (y z : ℝ) : x ^ (y * z) = (x ^ y) ^ simp only [(Complex.ofReal_mul _ _).symm, (Complex.ofReal_log hx).symm, Complex.ofReal_im, neg_lt_zero, pi_pos, le_of_lt pi_pos] +lemma rpow_pow_comm {x : ℝ} (hx : 0 ≤ x) (y : ℝ) (n : ℕ) : (x ^ y) ^ n = (x ^ n) ^ y := by + simp_rw [← rpow_natCast, ← rpow_mul hx, mul_comm y] + +lemma rpow_zpow_comm {x : ℝ} (hx : 0 ≤ x) (y : ℝ) (n : ℤ) : (x ^ y) ^ n = (x ^ n) ^ y := by + simp_rw [← rpow_intCast, ← rpow_mul hx, mul_comm y] + lemma rpow_add_intCast {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℤ) : x ^ (y + n) = x ^ y * x ^ n := by rw [rpow_def, rpow_def, Complex.ofReal_add, Complex.cpow_add _ _ (Complex.ofReal_ne_zero.mpr hx), Complex.ofReal_intCast, @@ -896,6 +902,12 @@ lemma antitone_rpow_of_base_le_one {b : ℝ} (hb₀ : 0 < b) (hb₁ : b ≤ 1) : case inl => exact (strictAnti_rpow_of_base_lt_one hb₀ hb₁).antitone case inr => intro _ _ _; simp +lemma rpow_right_inj (hx₀ : 0 < x) (hx₁ : x ≠ 1) : x ^ y = x ^ z ↔ y = z := by + refine ⟨fun H ↦ ?_, fun H ↦ by rw [H]⟩ + rcases hx₁.lt_or_lt with h | h + · exact (strictAnti_rpow_of_base_lt_one hx₀ h).injective H + · exact (strictMono_rpow_of_base_gt_one h).injective H + /-- Guessing rule for the `bound` tactic: when trying to prove `x ^ y ≤ x ^ z`, we can either assume `1 ≤ x` or `0 < x ≤ 1`. -/ @[bound] lemma rpow_le_rpow_of_exponent_le_or_ge {x y z : ℝ} From 59439d6b49ca812966a9983d673809304d4a7a86 Mon Sep 17 00:00:00 2001 From: Etienne Date: Fri, 10 Jan 2025 17:21:36 +0000 Subject: [PATCH 132/681] feat: Make `PNat.recOn` induction eliminator (#20617) Following this discussion on Zulip: https://leanprover.zulipchat.com/#narrow/channel/113489-new-members/topic/Base.20Case.20for.20Induction.20on.20N.2B/near/492807806 --- Archive/Imo/Imo1982Q1.lean | 6 +++--- Mathlib/Algebra/Group/PNatPowAssoc.lean | 12 ++++++------ Mathlib/Data/PNat/Basic.lean | 14 +++++++------- Mathlib/Data/PNat/Find.lean | 12 +++++++----- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Archive/Imo/Imo1982Q1.lean b/Archive/Imo/Imo1982Q1.lean index 98a0dd60777a6..abb8eb4b63cc3 100644 --- a/Archive/Imo/Imo1982Q1.lean +++ b/Archive/Imo/Imo1982Q1.lean @@ -77,9 +77,9 @@ lemma superadditive {m n : ℕ+} : f m + f n ≤ f (m + n) := by · rw [hr]; nth_rewrite 1 [← add_zero (f n), ← add_assoc]; apply add_le_add_right (by norm_num) lemma superhomogeneous {m n : ℕ+} : ↑n * f m ≤ f (n * m) := by - induction n using PNat.recOn - case p1 => simp - case hp n' ih => + induction n with + | one => simp + | succ n' ih => calc ↑(n' + 1) * f m = ↑n' * f m + f m := by rw [PNat.add_coe, add_mul, PNat.val_ofNat, one_mul] _ ≤ f (n' * m) + f m := add_le_add_right ih (f m) diff --git a/Mathlib/Algebra/Group/PNatPowAssoc.lean b/Mathlib/Algebra/Group/PNatPowAssoc.lean index d87d4474a1756..12929673086a2 100644 --- a/Mathlib/Algebra/Group/PNatPowAssoc.lean +++ b/Mathlib/Algebra/Group/PNatPowAssoc.lean @@ -66,9 +66,9 @@ theorem ppow_mul_comm (m n : ℕ+) (x : M) : x ^ m * x ^ n = x ^ n * x ^ m := by simp only [← ppow_add, add_comm] theorem ppow_mul (x : M) (m n : ℕ+) : x ^ (m * n) = (x ^ m) ^ n := by - refine PNat.recOn n ?_ fun k hk ↦ ?_ - · rw [ppow_one, mul_one] - · rw [ppow_add, ppow_one, mul_add, ppow_add, mul_one, hk] + induction n with + | one => rw [ppow_one, mul_one] + | succ k hk => rw [ppow_add, ppow_one, mul_add, ppow_add, mul_one, hk] theorem ppow_mul' (x : M) (m n : ℕ+) : x ^ (m * n) = (x ^ n) ^ m := by rw [mul_comm] @@ -88,6 +88,6 @@ instance Prod.instPNatPowAssoc {N : Type*} [Mul M] [Pow M ℕ+] [PNatPowAssoc M] theorem ppow_eq_pow [Monoid M] [Pow M ℕ+] [PNatPowAssoc M] (x : M) (n : ℕ+) : x ^ n = x ^ (n : ℕ) := by - refine PNat.recOn n ?_ fun k hk ↦ ?_ - · rw [ppow_one, PNat.one_coe, pow_one] - · rw [ppow_add, ppow_one, PNat.add_coe, pow_add, PNat.one_coe, pow_one, ← hk] + induction n with + | one => rw [ppow_one, PNat.one_coe, pow_one] + | succ k hk => rw [ppow_add, ppow_one, PNat.add_coe, pow_add, PNat.one_coe, pow_one, ← hk] diff --git a/Mathlib/Data/PNat/Basic.lean b/Mathlib/Data/PNat/Basic.lean index 5b28b50869c1a..1fa3b23e82f47 100644 --- a/Mathlib/Data/PNat/Basic.lean +++ b/Mathlib/Data/PNat/Basic.lean @@ -161,22 +161,22 @@ def caseStrongInductionOn {p : ℕ+ → Sort*} (a : ℕ+) (hz : p 1) /-- An induction principle for `ℕ+`: it takes values in `Sort*`, so it applies also to Types, not only to `Prop`. -/ -@[elab_as_elim] -def recOn (n : ℕ+) {p : ℕ+ → Sort*} (p1 : p 1) (hp : ∀ n, p n → p (n + 1)) : p n := by +@[elab_as_elim, induction_eliminator] +def recOn (n : ℕ+) {p : ℕ+ → Sort*} (one : p 1) (succ : ∀ n, p n → p (n + 1)) : p n := by rcases n with ⟨n, h⟩ induction' n with n IH · exact absurd h (by decide) · cases' n with n - · exact p1 - · exact hp _ (IH n.succ_pos) + · exact one + · exact succ _ (IH n.succ_pos) @[simp] -theorem recOn_one {p} (p1 hp) : @PNat.recOn 1 p p1 hp = p1 := +theorem recOn_one {p} (one succ) : @PNat.recOn 1 p one succ = one := rfl @[simp] -theorem recOn_succ (n : ℕ+) {p : ℕ+ → Sort*} (p1 hp) : - @PNat.recOn (n + 1) p p1 hp = hp n (@PNat.recOn n p p1 hp) := by +theorem recOn_succ (n : ℕ+) {p : ℕ+ → Sort*} (one succ) : + @PNat.recOn (n + 1) p one succ = succ n (@PNat.recOn n p one succ) := by cases' n with n h cases n <;> [exact absurd h (by decide); rfl] diff --git a/Mathlib/Data/PNat/Find.lean b/Mathlib/Data/PNat/Find.lean index c97607782b14b..b299a426b6d2e 100644 --- a/Mathlib/Data/PNat/Find.lean +++ b/Mathlib/Data/PNat/Find.lean @@ -101,10 +101,12 @@ theorem find_le {h : ∃ n, p n} (hn : p n) : PNat.find h ≤ n := theorem find_comp_succ (h : ∃ n, p n) (h₂ : ∃ n, p (n + 1)) (h1 : ¬p 1) : PNat.find h = PNat.find h₂ + 1 := by - refine (find_eq_iff _).2 ⟨PNat.find_spec h₂, fun n => PNat.recOn n ?_ ?_⟩ - · simp [h1] - intro m _ hm - simp only [add_lt_add_iff_right, lt_find_iff] at hm - exact hm _ le_rfl + refine (find_eq_iff _).2 ⟨PNat.find_spec h₂, fun n ↦ ?_⟩ + induction n with + | one => simp [h1] + | succ m _ => + intro hm + simp only [add_lt_add_iff_right, lt_find_iff] at hm + exact hm _ le_rfl end PNat From d9e6deb2f265be11e29c50b92246f43f206c6f83 Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Fri, 10 Jan 2025 18:07:48 +0000 Subject: [PATCH 133/681] refactor: remove the `CompactSpace` field from `Unique{NonUnital}ContinuousFunctionalCalculus` (#20590) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was originally useful for the general theory in some places, but since that time, this field is included in `ContinuousFunctionalCalculus` itself. This PR removes this fields, which means that any topological `𝕜`-algebra is an instance of this class. (for `RCLike 𝕜`). Moreover, a topological `𝕜`-algebra `A` also has a `UniqueContinuousFunctionalCalculus ℝ≥0 A` instance. Previously, we only had this for *normed* `𝕜`-algebras because of the compact spectrum criterion. This avoids the need to assume `[UniqueContinuousFunctionalCalculus 𝕜 A]` pretty much throughout the library, replacing it with `[T2Space A]` and, in the case of `𝕜 := ℝ≥0`, `[TopologicalRing A]`. --- .../Instances.lean | 13 ++-- .../Isometric.lean | 8 +-- .../NonUnital.lean | 6 +- .../ContinuousFunctionalCalculus/Order.lean | 11 ++-- .../ContinuousFunctionalCalculus/Unique.lean | 63 +++++++------------ .../ContinuousFunctionalCalculus/Unital.lean | 6 +- .../ContinuousFunctionalCalculus/ExpLog.lean | 4 +- .../ContinuousFunctionalCalculus/PosPart.lean | 8 +-- .../ContinuousFunctionalCalculus/Rpow.lean | 42 +++++++------ .../Matrix/HermitianFunctionalCalculus.lean | 8 --- 10 files changed, 71 insertions(+), 98 deletions(-) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean index 3fe783ba69ee2..ad42b978ebfcd 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean @@ -611,8 +611,7 @@ end NonnegSpectrumClass section RealEqComplex variable {A : Type*} [TopologicalSpace A] [Ring A] [StarRing A] [Algebra ℂ A] - [ContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop)] - [UniqueContinuousFunctionalCalculus ℝ A] + [ContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop)] [T2Space A] lemma cfcHom_real_eq_restrict {a : A} (ha : IsSelfAdjoint a) : cfcHom ha = @@ -632,9 +631,8 @@ end RealEqComplex section RealEqComplexNonUnital variable {A : Type*} [TopologicalSpace A] [NonUnitalRing A] [StarRing A] [Module ℂ A] - [IsScalarTower ℂ A A] [SMulCommClass ℂ A A] + [IsScalarTower ℂ A A] [SMulCommClass ℂ A A] [T2Space A] [NonUnitalContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop)] - [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] lemma cfcₙHom_real_eq_restrict {a : A} (ha : IsSelfAdjoint a) : cfcₙHom ha = (ha.quasispectrumRestricts.2).nonUnitalStarAlgHom (cfcₙHom ha.isStarNormal) @@ -655,9 +653,8 @@ section NNRealEqReal open NNReal variable {A : Type*} [TopologicalSpace A] [Ring A] [PartialOrder A] [StarRing A] - [StarOrderedRing A] [Algebra ℝ A] [TopologicalRing A] + [StarOrderedRing A] [Algebra ℝ A] [TopologicalRing A] [T2Space A] [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] - [ContinuousFunctionalCalculus ℝ≥0 ((0 : A) ≤ ·)] [UniqueContinuousFunctionalCalculus ℝ A] [NonnegSpectrumClass ℝ A] lemma cfcHom_nnreal_eq_restrict {a : A} (ha : 0 ≤ a) : @@ -679,9 +676,7 @@ open NNReal variable {A : Type*} [TopologicalSpace A] [NonUnitalRing A] [PartialOrder A] [StarRing A] [StarOrderedRing A] [Module ℝ A] [TopologicalRing A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] - [NonUnitalContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] - [NonUnitalContinuousFunctionalCalculus ℝ≥0 ((0 : A) ≤ ·)] - [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] + [T2Space A] [NonUnitalContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] [NonnegSpectrumClass ℝ A] lemma cfcₙHom_nnreal_eq_restrict {a : A} (ha : 0 ≤ a) : diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean index 142e51cfa4b72..9494504949525 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean @@ -380,7 +380,7 @@ section NNReal variable {A : Type*} [NormedRing A] [PartialOrder A] [StarRing A] [StarOrderedRing A] variable [NormedAlgebra ℝ A] [IsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] -variable [NonnegSpectrumClass ℝ A] [UniqueContinuousFunctionalCalculus ℝ A] +variable [NonnegSpectrumClass ℝ A] open NNReal in instance Nonneg.instIsometricContinuousFunctionalCalculus : @@ -425,7 +425,7 @@ section NNReal variable {A : Type*} [NonUnitalNormedRing A] [PartialOrder A] [StarRing A] [StarOrderedRing A] variable [NormedSpace ℝ A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] variable [NonUnitalIsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] -variable [NonnegSpectrumClass ℝ A] [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] +variable [NonnegSpectrumClass ℝ A] open NNReal in instance Nonneg.instNonUnitalIsometricContinuousFunctionalCalculus : @@ -449,7 +449,7 @@ section Unital variable {A : Type*} [NormedRing A] [StarRing A] [NormedAlgebra ℝ A] [PartialOrder A] variable [StarOrderedRing A] [IsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] -variable [NonnegSpectrumClass ℝ A] [UniqueContinuousFunctionalCalculus ℝ A] +variable [NonnegSpectrumClass ℝ A] lemma IsGreatest.nnnorm_cfc_nnreal [Nontrivial A] (f : ℝ≥0 → ℝ≥0) (a : A) (hf : ContinuousOn f (σ ℝ≥0 a) := by cfc_cont_tac) (ha : 0 ≤ a := by cfc_tac) : @@ -509,7 +509,7 @@ section NonUnital variable {A : Type*} [NonUnitalNormedRing A] [StarRing A] [NormedSpace ℝ A] variable [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] [PartialOrder A] variable [StarOrderedRing A] [NonUnitalIsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] -variable [NonnegSpectrumClass ℝ A] [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] +variable [NonnegSpectrumClass ℝ A] lemma IsGreatest.nnnorm_cfcₙ_nnreal (f : ℝ≥0 → ℝ≥0) (a : A) (hf : ContinuousOn f (σₙ ℝ≥0 a) := by cfc_cont_tac) (hf0 : f 0 = 0 := by cfc_zero_tac) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean index 1ab96c124bab0..715cccb881a6d 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean @@ -98,7 +98,6 @@ class UniqueNonUnitalContinuousFunctionalCalculus (R A : Type*) [CommSemiring R] (φ ψ : C(s, R)₀ →⋆ₙₐ[R] A) (hφ : Continuous φ) (hψ : Continuous ψ) (h : φ (⟨.restrict s <| .id R, h0⟩) = ψ (⟨.restrict s <| .id R, h0⟩)) : φ = ψ - compactSpace_quasispectrum (a : A) : CompactSpace (σₙ R a) section Main @@ -113,10 +112,10 @@ lemma NonUnitalContinuousFunctionalCalculus.isCompact_quasispectrum (a : A) : isCompact_iff_compactSpace.mpr inferInstance lemma NonUnitalStarAlgHom.ext_continuousMap [UniqueNonUnitalContinuousFunctionalCalculus R A] - (a : A) (φ ψ : C(σₙ R a, R)₀ →⋆ₙₐ[R] A) (hφ : Continuous φ) (hψ : Continuous ψ) + (a : A) [CompactSpace (σₙ R a)] (φ ψ : C(σₙ R a, R)₀ →⋆ₙₐ[R] A) + (hφ : Continuous φ) (hψ : Continuous ψ) (h : φ ⟨.restrict (σₙ R a) <| .id R, rfl⟩ = ψ ⟨.restrict (σₙ R a) <| .id R, rfl⟩) : φ = ψ := - have := UniqueNonUnitalContinuousFunctionalCalculus.compactSpace_quasispectrum (R := R) a UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id _ (by simp) φ ψ hφ hψ h section cfcₙHom @@ -158,6 +157,7 @@ lemma cfcₙHom_predicate (f : C(σₙ R a, R)₀) : p (cfcₙHom ha f) := (NonUnitalContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2 f +open scoped NonUnitalContinuousFunctionalCalculus in lemma cfcₙHom_eq_of_continuous_of_map_id [UniqueNonUnitalContinuousFunctionalCalculus R A] (φ : C(σₙ R a, R)₀ →⋆ₙₐ[R] A) (hφ₁ : Continuous φ) (hφ₂ : φ ⟨.restrict (σₙ R a) <| .id R, rfl⟩ = a) : cfcₙHom ha = φ := diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean index 103afe35d71f9..ddd292f4a77d2 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean @@ -40,9 +40,9 @@ open scoped NNReal CStarAlgebra local notation "σₙ" => quasispectrum theorem cfc_tsub {A : Type*} [TopologicalSpace A] [Ring A] [PartialOrder A] [StarRing A] - [StarOrderedRing A] [Algebra ℝ A] [TopologicalRing A] + [StarOrderedRing A] [Algebra ℝ A] [TopologicalRing A] [T2Space A] [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] - [UniqueContinuousFunctionalCalculus ℝ A] [NonnegSpectrumClass ℝ A] (f g : ℝ≥0 → ℝ≥0) + [NonnegSpectrumClass ℝ A] (f g : ℝ≥0 → ℝ≥0) (a : A) (hfg : ∀ x ∈ spectrum ℝ≥0 a, g x ≤ f x) (ha : 0 ≤ a := by cfc_tac) (hf : ContinuousOn f (spectrum ℝ≥0 a) := by cfc_cont_tac) (hg : ContinuousOn g (spectrum ℝ≥0 a) := by cfc_cont_tac) : @@ -59,8 +59,8 @@ theorem cfc_tsub {A : Type*} [TopologicalSpace A] [Ring A] [PartialOrder A] [Sta theorem cfcₙ_tsub {A : Type*} [TopologicalSpace A] [NonUnitalRing A] [PartialOrder A] [StarRing A] [StarOrderedRing A] [Module ℝ A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] [TopologicalRing A] - [NonUnitalContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] - [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] [NonnegSpectrumClass ℝ A] (f g : ℝ≥0 → ℝ≥0) + [T2Space A] [NonUnitalContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] + [NonnegSpectrumClass ℝ A] (f g : ℝ≥0 → ℝ≥0) (a : A) (hfg : ∀ x ∈ σₙ ℝ≥0 a, g x ≤ f x) (ha : 0 ≤ a := by cfc_tac) (hf : ContinuousOn f (σₙ ℝ≥0 a) := by cfc_cont_tac) (hf0 : f 0 = 0 := by cfc_zero_tac) (hg : ContinuousOn g (σₙ ℝ≥0 a) := by cfc_cont_tac) (hg0 : g 0 = 0 := by cfc_zero_tac) : @@ -112,8 +112,7 @@ end Unitization However, this theorem still holds for `ℝ≥0` as long as the algebra `A` itself is an `ℝ`-algebra. -/ lemma cfc_nnreal_le_iff {A : Type*} [TopologicalSpace A] [Ring A] [StarRing A] [PartialOrder A] [StarOrderedRing A] [Algebra ℝ A] [TopologicalRing A] [NonnegSpectrumClass ℝ A] - [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] - [UniqueContinuousFunctionalCalculus ℝ A] + [T2Space A] [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] (f : ℝ≥0 → ℝ≥0) (g : ℝ≥0 → ℝ≥0) (a : A) (ha_spec : SpectrumRestricts a ContinuousMap.realToNNReal) (hf : ContinuousOn f (spectrum ℝ≥0 a) := by cfc_cont_tac) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean index 4ad6321414833..a00aad44e7849 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean @@ -3,9 +3,9 @@ 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.Analysis.Normed.Algebra.Spectrum import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital import Mathlib.Topology.ContinuousMap.StoneWeierstrass +import Mathlib.Analysis.InnerProductSpace.Basic /-! # Uniqueness of the continuous functional calculus @@ -32,18 +32,23 @@ section RCLike variable {𝕜 A : Type*} [RCLike 𝕜] -theorem RCLike.uniqueContinuousFunctionalCalculus_of_compactSpace_spectrum [TopologicalSpace A] - [T2Space A] [Ring A] [StarRing A] [Algebra 𝕜 A] [h : ∀ a : A, CompactSpace (spectrum 𝕜 a)] : +instance (priority := 100) RCLike.uniqueContinuousFunctionalCalculus [TopologicalSpace A] + [T2Space A] [Ring A] [StarRing A] [Algebra 𝕜 A] : UniqueContinuousFunctionalCalculus 𝕜 A where eq_of_continuous_of_map_id s _ φ ψ hφ hψ h := ContinuousMap.starAlgHom_ext_map_X hφ hψ <| by convert h using 1 all_goals exact congr_arg _ (by ext; simp) - compactSpace_spectrum := h -instance RCLike.instUniqueContinuousFunctionalCalculus [NormedRing A] [StarRing A] - [NormedAlgebra 𝕜 A] [CompleteSpace A] : UniqueContinuousFunctionalCalculus 𝕜 A := - RCLike.uniqueContinuousFunctionalCalculus_of_compactSpace_spectrum +instance Real.uniqueContinuousFunctionalCalculus [TopologicalSpace A] + [T2Space A] [Ring A] [StarRing A] [Algebra ℝ A] : + UniqueContinuousFunctionalCalculus ℝ A := + inferInstance + +instance Complex.uniqueContinuousFunctionalCalculus [TopologicalSpace A] + [T2Space A] [Ring A] [StarRing A] [Algebra ℂ A] : + UniqueContinuousFunctionalCalculus ℂ A := + inferInstance end RCLike @@ -165,13 +170,8 @@ end StarAlgHom variable [TopologicalSpace A] [TopologicalRing A] -instance NNReal.instUniqueContinuousFunctionalCalculus [UniqueContinuousFunctionalCalculus ℝ A] : +instance NNReal.instUniqueContinuousFunctionalCalculus [T2Space A] : UniqueContinuousFunctionalCalculus ℝ≥0 A where - compactSpace_spectrum a := by - have : CompactSpace (spectrum ℝ a) := UniqueContinuousFunctionalCalculus.compactSpace_spectrum a - rw [← isCompact_iff_compactSpace] at * - rw [← spectrum.preimage_algebraMap ℝ] - exact isClosed_nonneg.isClosedEmbedding_subtypeVal.isCompact_preimage <| by assumption eq_of_continuous_of_map_id s hs φ ψ hφ hψ h := by let s' : Set ℝ := (↑) '' s let e : s ≃ₜ s' := @@ -214,9 +214,9 @@ section RCLike variable {𝕜 A : Type*} [RCLike 𝕜] open NonUnitalStarAlgebra in -theorem RCLike.uniqueNonUnitalContinuousFunctionalCalculus_of_compactSpace_quasispectrum +instance RCLike.uniqueNonUnitalContinuousFunctionalCalculus [TopologicalSpace A] [T2Space A] [NonUnitalRing A] [StarRing A] [Module 𝕜 A] - [IsScalarTower 𝕜 A A] [SMulCommClass 𝕜 A A] [h : ∀ a : A, CompactSpace (quasispectrum 𝕜 a)] : + [IsScalarTower 𝕜 A A] [SMulCommClass 𝕜 A A] : UniqueNonUnitalContinuousFunctionalCalculus 𝕜 A where eq_of_continuous_of_map_id s hs _inst h0 φ ψ hφ hψ h := by rw [DFunLike.ext'_iff, ← Set.eqOn_univ, ← (ContinuousMapZero.adjoin_id_dense h0).closure_eq] @@ -225,12 +225,6 @@ theorem RCLike.uniqueNonUnitalContinuousFunctionalCalculus_of_compactSpace_quasi apply adjoin_le ?_ hf rw [Set.singleton_subset_iff] exact h - compactSpace_quasispectrum := h - -instance RCLike.instUniqueNonUnitalContinuousFunctionalCalculus [NonUnitalNormedRing A] - [StarRing A] [CompleteSpace A] [NormedSpace 𝕜 A] [IsScalarTower 𝕜 A A] [SMulCommClass 𝕜 A A] : - UniqueNonUnitalContinuousFunctionalCalculus 𝕜 A := - RCLike.uniqueNonUnitalContinuousFunctionalCalculus_of_compactSpace_quasispectrum end RCLike @@ -274,9 +268,6 @@ lemma toNNReal_neg_smul (r : ℝ≥0) (f : C(X, ℝ)₀) : (-(r • f)).toNNReal lemma toNNReal_mul_add_neg_mul_add_mul_neg_eq (f g : C(X, ℝ)₀) : ((f * g).toNNReal + (-f).toNNReal * g.toNNReal + f.toNNReal * (-g).toNNReal) = ((-(f * g)).toNNReal + f.toNNReal * g.toNNReal + (-f).toNNReal * (-g).toNNReal) := by - -- Without this, Lean fails to find the instance in time - have : SemilinearMapClass (C(X, ℝ≥0)₀ →⋆ₙₐ[ℝ≥0] C(X, ℝ≥0)) (RingHom.id ℝ≥0) - C(X, ℝ≥0)₀ C(X, ℝ≥0) := NonUnitalAlgHomClass.instLinearMapClass apply toContinuousMap_injective simpa only [← toContinuousMapHom_apply, map_add, map_mul, map_neg, toContinuousMapHom_toNNReal] using (f : C(X, ℝ)).toNNReal_mul_add_neg_mul_add_mul_neg_eq g @@ -284,9 +275,6 @@ lemma toNNReal_mul_add_neg_mul_add_mul_neg_eq (f g : C(X, ℝ)₀) : lemma toNNReal_add_add_neg_add_neg_eq (f g : C(X, ℝ)₀) : ((f + g).toNNReal + (-f).toNNReal + (-g).toNNReal) = ((-(f + g)).toNNReal + f.toNNReal + g.toNNReal) := by - -- Without this, Lean fails to find the instance in time - have : SemilinearMapClass (C(X, ℝ≥0)₀ →⋆ₙₐ[ℝ≥0] C(X, ℝ≥0)) (RingHom.id ℝ≥0) - C(X, ℝ≥0)₀ C(X, ℝ≥0) := NonUnitalAlgHomClass.instLinearMapClass apply toContinuousMap_injective simpa only [← toContinuousMapHom_apply, map_add, map_mul, map_neg, toContinuousMapHom_toNNReal] using (f : C(X, ℝ)).toNNReal_add_add_neg_add_neg_eq g @@ -371,14 +359,8 @@ open ContinuousMapZero instance NNReal.instUniqueNonUnitalContinuousFunctionalCalculus [TopologicalSpace A] [TopologicalRing A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] - [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] : + [T2Space A] : UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A where - compactSpace_quasispectrum a := by - have : CompactSpace (quasispectrum ℝ a) := - UniqueNonUnitalContinuousFunctionalCalculus.compactSpace_quasispectrum a - rw [← isCompact_iff_compactSpace] at * - rw [← quasispectrum.preimage_algebraMap ℝ] - exact isClosed_nonneg.isClosedEmbedding_subtypeVal.isCompact_preimage <| by assumption eq_of_continuous_of_map_id s hs _inst h0 φ ψ hφ hψ h := by let s' : Set ℝ := (↑) '' s let e : s ≃ₜ s' := @@ -408,6 +390,7 @@ instance NNReal.instUniqueNonUnitalContinuousFunctionalCalculus obtain ⟨hφ', hφ_id⟩ := this φ hφ obtain ⟨hψ', hψ_id⟩ := this ψ hψ have hs' : CompactSpace s' := e.compactSpace + have : UniqueNonUnitalContinuousFunctionalCalculus ℝ A := inferInstance have h' := UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id s' h0' _ _ hφ' hψ' (hφ_id ▸ hψ_id ▸ h) have h'' := congr($(h').comp <| @@ -425,7 +408,7 @@ end UniqueNonUnital section NonUnitalStarAlgHom -open scoped ContinuousMapZero +open scoped ContinuousMapZero NonUnitalContinuousFunctionalCalculus variable {F R S A B : Type*} {p : A → Prop} {q : B → Prop} [CommSemiring R] [Nontrivial R] [StarRing R] [MetricSpace R] [TopologicalSemiring R] @@ -443,7 +426,7 @@ include S in /-- Non-unital star algebra homomorphisms commute with the non-unital continuous functional calculus. -/ lemma NonUnitalStarAlgHomClass.map_cfcₙ (φ : F) (f : R → R) (a : A) - [CompactSpace (quasispectrum R a)] (hf : ContinuousOn f (quasispectrum R a) := by cfc_cont_tac) + (hf : ContinuousOn f (quasispectrum R a) := by cfc_cont_tac) (hf₀ : f 0 = 0 := by cfc_zero_tac) (hφ : Continuous φ := by fun_prop) (ha : p a := by cfc_tac) (hφa : q (φ a) := by cfc_tac) : φ (cfcₙ f a) = cfcₙ f (φ a) := by let ψ : A →⋆ₙₐ[R] B := (φ : A →⋆ₙₐ[S] B).restrictScalars R @@ -470,7 +453,7 @@ lemma NonUnitalStarAlgHomClass.map_cfcₙ (φ : F) (f : R → R) (a : A) /-- Non-unital star algebra homomorphisms commute with the non-unital continuous functional calculus. This version is specialized to `A →⋆ₙₐ[S] B` to allow for dot notation. -/ lemma NonUnitalStarAlgHom.map_cfcₙ (φ : A →⋆ₙₐ[S] B) (f : R → R) (a : A) - [CompactSpace (quasispectrum R a)] (hf : ContinuousOn f (quasispectrum R a) := by cfc_cont_tac) + (hf : ContinuousOn f (quasispectrum R a) := by cfc_cont_tac) (hf₀ : f 0 = 0 := by cfc_zero_tac) (hφ : Continuous φ := by fun_prop) (ha : p a := by cfc_tac) (hφa : q (φ a) := by cfc_tac) : φ (cfcₙ f a) = cfcₙ f (φ a) := NonUnitalStarAlgHomClass.map_cfcₙ φ f a @@ -479,6 +462,8 @@ end NonUnitalStarAlgHom section StarAlgHom +open scoped ContinuousFunctionalCalculus + variable {F R S A B : Type*} {p : A → Prop} {q : B → Prop} [CommSemiring R] [StarRing R] [MetricSpace R] [TopologicalSemiring R] [ContinuousStar R] [Ring A] [StarRing A] [TopologicalSpace A] [Algebra R A] @@ -491,7 +476,7 @@ variable {F R S A B : Type*} {p : A → Prop} {q : B → Prop} include S in /-- Star algebra homomorphisms commute with the continuous functional calculus. -/ lemma StarAlgHomClass.map_cfc (φ : F) (f : R → R) (a : A) - [CompactSpace (spectrum R a)] (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) + (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) (hφ : Continuous φ := by fun_prop) (ha : p a := by cfc_tac) (hφa : q (φ a) := by cfc_tac) : φ (cfc f a) = cfc f (φ a) := by let ψ : A →⋆ₐ[R] B := (φ : A →⋆ₐ[S] B).restrictScalars R @@ -515,7 +500,7 @@ lemma StarAlgHomClass.map_cfc (φ : F) (f : R → R) (a : A) /-- Star algebra homomorphisms commute with the continuous functional calculus. This version is specialized to `A →⋆ₐ[S] B` to allow for dot notation. -/ -lemma StarAlgHom.map_cfc (φ : A →⋆ₐ[S] B) (f : R → R) (a : A) [CompactSpace (spectrum R a)] +lemma StarAlgHom.map_cfc (φ : A →⋆ₐ[S] B) (f : R → R) (a : A) (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) (hφ : Continuous φ := by fun_prop) (ha : p a := by cfc_tac) (hφa : q (φ a) := by cfc_tac) : φ (cfc f a) = cfc f (φ a) := diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean index 0cf2fabda7a17..03543434ff6ae 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean @@ -197,7 +197,6 @@ class UniqueContinuousFunctionalCalculus (R A : Type*) [CommSemiring R] [StarRin (φ ψ : C(s, R) →⋆ₐ[R] A) (hφ : Continuous φ) (hψ : Continuous ψ) (h : φ (.restrict s <| .id R) = ψ (.restrict s <| .id R)) : φ = ψ - compactSpace_spectrum (a : A) : CompactSpace (spectrum R a) variable {R A : Type*} {p : A → Prop} [CommSemiring R] [StarRing R] [MetricSpace R] variable [TopologicalSemiring R] [ContinuousStar R] [TopologicalSpace A] [Ring A] [StarRing A] @@ -209,10 +208,10 @@ lemma ContinuousFunctionalCalculus.isCompact_spectrum (a : A) : isCompact_iff_compactSpace.mpr inferInstance lemma StarAlgHom.ext_continuousMap [UniqueContinuousFunctionalCalculus R A] - (a : A) (φ ψ : C(spectrum R a, R) →⋆ₐ[R] A) (hφ : Continuous φ) (hψ : Continuous ψ) + (a : A) [CompactSpace (spectrum R a)] (φ ψ : C(spectrum R a, R) →⋆ₐ[R] A) + (hφ : Continuous φ) (hψ : Continuous ψ) (h : φ (.restrict (spectrum R a) <| .id R) = ψ (.restrict (spectrum R a) <| .id R)) : φ = ψ := - have := UniqueContinuousFunctionalCalculus.compactSpace_spectrum (R := R) a UniqueContinuousFunctionalCalculus.eq_of_continuous_of_map_id (spectrum R a) φ ψ hφ hψ h section cfcHom @@ -260,6 +259,7 @@ lemma cfcHom_predicate (f : C(spectrum R a, R)) : p (cfcHom ha f) := (ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2 f +open scoped ContinuousFunctionalCalculus in lemma cfcHom_eq_of_continuous_of_map_id [UniqueContinuousFunctionalCalculus R A] (φ : C(spectrum R a, R) →⋆ₐ[R] A) (hφ₁ : Continuous φ) (hφ₂ : φ (.restrict (spectrum R a) <| .id R) = a) : cfcHom ha = φ := diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean index bdb5875943ebe..c44b9da0e8069 100644 --- a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean @@ -6,7 +6,7 @@ Authors: Frédéric Dupuis import Mathlib.Analysis.Normed.Algebra.Spectrum import Mathlib.Analysis.SpecialFunctions.Exponential -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unique import Mathlib.Topology.ContinuousMap.StarOrdered /-! @@ -127,8 +127,6 @@ protected lemma _root_.IsSelfAdjoint.log {a : A} : IsSelfAdjoint (log a) := cfc_ lemma log_algebraMap {r : ℝ} : log (algebraMap ℝ A r) = algebraMap ℝ A (Real.log r) := by simp [log] -variable [UniqueContinuousFunctionalCalculus ℝ A] - -- TODO: Relate the hypothesis to a notion of strict positivity lemma log_smul {r : ℝ} (a : A) (ha₂ : ∀ x ∈ spectrum ℝ a, 0 < x) (hr : 0 < r) (ha₁ : IsSelfAdjoint a := by cfc_tac) : diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean index b025d0d6c2621..abb22aaf6854f 100644 --- a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean @@ -7,7 +7,7 @@ Authors: Jireh Loreaux import Mathlib.Topology.ContinuousMap.StarOrdered import Mathlib.Analysis.InnerProductSpace.Basic import Mathlib.Topology.ContinuousMap.StoneWeierstrass -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unique /-! # The positive (and negative) parts of a selfadjoint element in a C⋆-algebra @@ -75,7 +75,7 @@ lemma posPart_sub_negPart (a : A) (ha : IsSelfAdjoint a := by cfc_tac) : a⁺ - section Unique -variable [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] +variable [T2Space A] @[simp] lemma posPart_neg (a : A) : (-a)⁺ = a⁻ := by @@ -205,7 +205,6 @@ local notation "σₙ" => quasispectrum open ContinuousMapZero -variable [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] variable [TopologicalRing A] [T2Space A] open NonUnitalContinuousFunctionalCalculus in @@ -265,6 +264,7 @@ lemma posPart_negPart_unique {a b c : A} (habc : a = b - c) (hbc : b * c = 0) zero_add] map_star' := fun f ↦ by simp [← map_star] } have key : (cfcₙHomSuperset ha has) = ψ := + have : UniqueNonUnitalContinuousFunctionalCalculus ℝ A := inferInstance UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id s rfl (cfcₙHomSuperset ha has) ψ (cfcₙHomSuperset_continuous ha has) ((cfcₙHomSuperset_continuous hb' hbs).add (cfcₙHomSuperset_continuous hc' hcs)) @@ -311,7 +311,7 @@ namespace CFC variable {A : Type*} [Ring A] [Algebra ℝ A] [StarRing A] [TopologicalSpace A] variable [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] -variable [UniqueNonUnitalContinuousFunctionalCalculus ℝ A] +variable [T2Space A] @[simp] lemma posPart_one : (1 : A)⁺ = 1 := by diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow.lean index 0bdd483e3237a..89d6038a11e76 100644 --- a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow.lean +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow.lean @@ -5,7 +5,7 @@ Authors: Frédéric Dupuis -/ import Mathlib.Analysis.SpecialFunctions.Pow.Real -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unique import Mathlib.Analysis.SpecialFunctions.Pow.Continuity /-! @@ -67,7 +67,7 @@ namespace CFC section NonUnital variable {A : Type*} [PartialOrder A] [NonUnitalRing A] [TopologicalSpace A] [StarRing A] - [Module ℝ≥0 A] [SMulCommClass ℝ≥0 A A] [IsScalarTower ℝ≥0 A A] + [Module ℝ A] [SMulCommClass ℝ A A] [IsScalarTower ℝ A A] [NonUnitalContinuousFunctionalCalculus ℝ≥0 (fun (a : A) => 0 ≤ a)] /- ## `nnrpow` -/ @@ -117,9 +117,12 @@ lemma nnrpow_three (a : A) (ha : 0 ≤ a := by cfc_tac) : a ^ (3 : ℝ≥0) = a @[simp] lemma zero_nnrpow {x : ℝ≥0} : (0 : A) ^ x = 0 := by simp [nnrpow_def] +section Unique + +variable [TopologicalRing A] [T2Space A] + @[simp] -lemma nnrpow_nnrpow [UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A] - {a : A} {x y : ℝ≥0} : (a ^ x) ^ y = a ^ (x * y) := by +lemma nnrpow_nnrpow {a : A} {x y : ℝ≥0} : (a ^ x) ^ y = a ^ (x * y) := by by_cases ha : 0 ≤ a case pos => obtain (rfl | hx) := eq_zero_or_pos x <;> obtain (rfl | hy) := eq_zero_or_pos y @@ -132,20 +135,21 @@ lemma nnrpow_nnrpow [UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A] case neg => simp [nnrpow_def, cfcₙ_apply_of_not_predicate a ha] -lemma nnrpow_nnrpow_inv [UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A] - (a : A) {x : ℝ≥0} (hx : x ≠ 0) (ha : 0 ≤ a := by cfc_tac) : (a ^ x) ^ x⁻¹ = a := by +lemma nnrpow_nnrpow_inv (a : A) {x : ℝ≥0} (hx : x ≠ 0) (ha : 0 ≤ a := by cfc_tac) : + (a ^ x) ^ x⁻¹ = a := by simp [mul_inv_cancel₀ hx, nnrpow_one _ ha] -lemma nnrpow_inv_nnrpow [UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A] - (a : A) {x : ℝ≥0} (hx : x ≠ 0) (ha : 0 ≤ a := by cfc_tac) : (a ^ x⁻¹) ^ x = a := by +lemma nnrpow_inv_nnrpow (a : A) {x : ℝ≥0} (hx : x ≠ 0) (ha : 0 ≤ a := by cfc_tac) : + (a ^ x⁻¹) ^ x = a := by simp [inv_mul_cancel₀ hx, nnrpow_one _ ha] -lemma nnrpow_inv_eq [UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A] - (a b : A) {x : ℝ≥0} (hx : x ≠ 0) (ha : 0 ≤ a := by cfc_tac) (hb : 0 ≤ b := by cfc_tac) : - a ^ x⁻¹ = b ↔ b ^ x = a := +lemma nnrpow_inv_eq (a b : A) {x : ℝ≥0} (hx : x ≠ 0) (ha : 0 ≤ a := by cfc_tac) + (hb : 0 ≤ b := by cfc_tac) : a ^ x⁻¹ = b ↔ b ^ x = a := ⟨fun h ↦ nnrpow_inv_nnrpow a hx ▸ congr($(h) ^ x).symm, fun h ↦ nnrpow_nnrpow_inv b hx ▸ congr($(h) ^ x⁻¹).symm⟩ +end Unique + /- ## `sqrt` -/ section sqrt @@ -165,7 +169,7 @@ lemma sqrt_eq_nnrpow {a : A} : sqrt a = a ^ (1 / 2 : ℝ≥0) := by @[simp] lemma sqrt_zero : sqrt (0 : A) = 0 := by simp [sqrt] -variable [UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A] +variable [TopologicalRing A] [T2Space A] @[simp] lemma nnrpow_sqrt {a : A} {x : ℝ≥0} : (sqrt a) ^ x = a ^ (x / 2) := by @@ -262,7 +266,7 @@ lemma rpow_add {a : A} {x y : ℝ} (ha : 0 ∉ spectrum ℝ≥0 a) : simp [NNReal.rpow_add this _ _] -- TODO: relate to a strict positivity condition -lemma rpow_rpow [UniqueContinuousFunctionalCalculus ℝ≥0 A] +lemma rpow_rpow [TopologicalRing A] [T2Space A] (a : A) (x y : ℝ) (ha₁ : 0 ∉ spectrum ℝ≥0 a) (hx : x ≠ 0) (ha₂ : 0 ≤ a := by cfc_tac) : (a ^ x) ^ y = a ^ (x * y) := by simp only [rpow_def] @@ -270,7 +274,7 @@ lemma rpow_rpow [UniqueContinuousFunctionalCalculus ℝ≥0 A] refine cfc_congr fun _ _ => ?_ simp [NNReal.rpow_mul] -lemma rpow_rpow_of_exponent_nonneg [UniqueContinuousFunctionalCalculus ℝ≥0 A] (a : A) (x y : ℝ) +lemma rpow_rpow_of_exponent_nonneg [TopologicalRing A] [T2Space A] (a : A) (x y : ℝ) (hx : 0 ≤ x) (hy : 0 ≤ y) (ha₂ : 0 ≤ a := by cfc_tac) : (a ^ x) ^ y = a ^ (x * y) := by simp only [rpow_def] rw [← cfc_comp _ _ a] @@ -295,7 +299,7 @@ lemma rpow_neg_one_eq_cfc_inv {A : Type*} [PartialOrder A] [NormedRing A] [StarR a ^ (-1 : ℝ) = cfc (·⁻¹ : ℝ≥0 → ℝ≥0) a := cfc_congr fun x _ ↦ NNReal.rpow_neg_one x -lemma rpow_neg [UniqueContinuousFunctionalCalculus ℝ≥0 A] (a : Aˣ) (x : ℝ) +lemma rpow_neg [TopologicalRing A] [T2Space A] (a : Aˣ) (x : ℝ) (ha' : (0 : A) ≤ a := by cfc_tac) : (a : A) ^ (-x) = (↑a⁻¹ : A) ^ x := by suffices h₁ : ContinuousOn (fun z ↦ z ^ x) (Inv.inv '' (spectrum ℝ≥0 (a : A))) by rw [← cfc_inv_id (R := ℝ≥0) a, rpow_def, rpow_def, @@ -314,7 +318,7 @@ lemma rpow_intCast (a : Aˣ) (n : ℤ) (ha : (0 : A) ≤ a := by cfc_tac) : section unital_vs_nonunital -variable [UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A] +variable [TopologicalRing A] [T2Space A] -- provides instance `ContinuousFunctionalCalculus.compactSpace_spectrum` open scoped ContinuousFunctionalCalculus @@ -344,7 +348,7 @@ lemma sqrt_algebraMap {r : ℝ≥0} : sqrt (algebraMap ℝ≥0 A r) = algebraMap lemma sqrt_one : sqrt (1 : A) = 1 := by simp [sqrt_eq_cfc] -- TODO: relate to a strict positivity condition -lemma sqrt_rpow [UniqueContinuousFunctionalCalculus ℝ≥0 A] {a : A} {x : ℝ} (h : 0 ∉ spectrum ℝ≥0 a) +lemma sqrt_rpow {a : A} {x : ℝ} (h : 0 ∉ spectrum ℝ≥0 a) (hx : x ≠ 0) : sqrt (a ^ x) = a ^ (x / 2) := by by_cases hnonneg : 0 ≤ a case pos => @@ -353,7 +357,7 @@ lemma sqrt_rpow [UniqueContinuousFunctionalCalculus ℝ≥0 A] {a : A} {x : ℝ} simp [sqrt_eq_cfc, rpow_def, cfc_apply_of_not_predicate a hnonneg] -- TODO: relate to a strict positivity condition -lemma rpow_sqrt [UniqueContinuousFunctionalCalculus ℝ≥0 A] (a : A) (x : ℝ) (h : 0 ∉ spectrum ℝ≥0 a) +lemma rpow_sqrt (a : A) (x : ℝ) (h : 0 ∉ spectrum ℝ≥0 a) (ha : 0 ≤ a := by cfc_tac) : (sqrt a) ^ x = a ^ (x / 2) := by rw [sqrt_eq_rpow, div_eq_mul_inv, one_mul, rpow_rpow _ _ _ h (by norm_num), inv_mul_eq_div] @@ -370,7 +374,7 @@ lemma sqrt_rpow_nnreal {a : A} {x : ℝ≥0} : sqrt (a ^ (x : ℝ)) = a ^ (x / 2 have h₃ : 0 < x / 2 := by positivity rw [← nnrpow_eq_rpow h₁, h₂, ← nnrpow_eq_rpow h₃, sqrt_nnrpow (A := A)] -lemma rpow_sqrt_nnreal [UniqueContinuousFunctionalCalculus ℝ≥0 A] {a : A} {x : ℝ≥0} +lemma rpow_sqrt_nnreal {a : A} {x : ℝ≥0} (ha : 0 ≤ a := by cfc_tac) : (sqrt a) ^ (x : ℝ) = a ^ (x / 2 : ℝ) := by by_cases hx : x = 0 case pos => diff --git a/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean b/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean index c9738d1e0bacc..5248086346b66 100644 --- a/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean +++ b/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean @@ -8,8 +8,6 @@ import Mathlib.LinearAlgebra.Matrix.Spectrum import Mathlib.LinearAlgebra.Eigenspace.Matrix import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unique import Mathlib.Topology.ContinuousMap.Units -import Mathlib.Analysis.Matrix -import Mathlib.Topology.UniformSpace.Matrix /-! # Continuous Functional Calculus for Hermitian Matrices @@ -149,12 +147,6 @@ instance instContinuousFunctionalCalculus : · exact eigenvalues_eq_spectrum_real ha ▸ Set.range_nonempty _ predicate_zero := .zero _ -instance instUniqueContinuousFunctionalCalculus : - UniqueContinuousFunctionalCalculus ℝ (Matrix n n 𝕜) := - let _ : NormedRing (Matrix n n 𝕜) := Matrix.linftyOpNormedRing - let _ : NormedAlgebra ℝ (Matrix n n 𝕜) := Matrix.linftyOpNormedAlgebra - inferInstance - /-- The continuous functional calculus of a Hermitian matrix as a triple product using the spectral theorem. Note that this actually operates on bare functions since every function is continuous on the spectrum of a matrix, since the spectrum is finite. This is shown to be equal to From 78b361bfbd7e0d9a3b13015c8fa1a6a2e88587aa Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Fri, 10 Jan 2025 18:18:59 +0000 Subject: [PATCH 134/681] feat(FieldTheory/Differential/Liouville): prove the algebraic case of Liouville's theorem (#16797) Co-authored-by: Daniel Weber <55664973+Command-Master@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/FieldTheory/Differential/Basic.lean | 113 +++++++++- .../FieldTheory/Differential/Liouville.lean | 207 ++++++++++++++++++ .../Derivation/DifferentialRing.lean | 1 + 4 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 Mathlib/FieldTheory/Differential/Liouville.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7f0699745d63a..e4f2f45397583 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3062,6 +3062,7 @@ import Mathlib.FieldTheory.CardinalEmb import Mathlib.FieldTheory.Cardinality import Mathlib.FieldTheory.ChevalleyWarning import Mathlib.FieldTheory.Differential.Basic +import Mathlib.FieldTheory.Differential.Liouville import Mathlib.FieldTheory.Extension import Mathlib.FieldTheory.Finite.Basic import Mathlib.FieldTheory.Finite.GaloisField diff --git a/Mathlib/FieldTheory/Differential/Basic.lean b/Mathlib/FieldTheory/Differential/Basic.lean index 05c4742401057..71a387955fa1e 100644 --- a/Mathlib/FieldTheory/Differential/Basic.lean +++ b/Mathlib/FieldTheory/Differential/Basic.lean @@ -3,10 +3,8 @@ Copyright (c) 2024 Daniel Weber. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Daniel Weber -/ -import Mathlib.Algebra.EuclideanDomain.Field -import Mathlib.RingTheory.Derivation.DifferentialRing -import Mathlib.RingTheory.LocalRing.Basic -import Mathlib.Tactic.FieldSimp +import Mathlib.RingTheory.Derivation.MapCoeffs +import Mathlib.FieldTheory.PrimitiveElement /-! # Differential Fields @@ -17,7 +15,7 @@ This is defined algebraically, compared to `logDeriv` which is analytical. namespace Differential -open algebraMap +open algebraMap Polynomial IntermediateField variable {R : Type*} [Field R] [Differential R] (a b : R) @@ -55,7 +53,7 @@ lemma logDeriv_pow (n : ℕ) (a : R) : logDeriv (a ^ n) = n * logDeriv a := by simp [hb] lemma logDeriv_eq_zero : logDeriv a = 0 ↔ a′ = 0 := - ⟨fun h ↦ by simp only [logDeriv, div_eq_zero_iff] at h; rcases h with h|h <;> simp [h], + ⟨fun h ↦ by simp only [logDeriv, _root_.div_eq_zero_iff] at h; rcases h with h|h <;> simp [h], fun h ↦ by unfold logDeriv at *; simp [h]⟩ lemma logDeriv_multisetProd {ι : Type*} (s : Multiset ι) {f : ι → R} (h : ∀ x ∈ s, f x ≠ 0) : @@ -89,4 +87,107 @@ lemma _root_.algebraMap.coe_logDeriv {F K : Type*} [Field F] [Field K] [Differen [Differential K] [Algebra F K] [DifferentialAlgebra F K] (a : F) : logDeriv a = logDeriv (a : K) := (logDeriv_algebraMap a).symm +variable {F : Type*} [Field F] [Differential F] [CharZero F] + +noncomputable instance (p : F[X]) [Fact (Irreducible p)] [Fact p.Monic] : + Differential (AdjoinRoot p) where + deriv := Derivation.liftOfSurjective (f := (AdjoinRoot.mk p).toIntAlgHom) AdjoinRoot.mk_surjective + (d := implicitDeriv <| AdjoinRoot.modByMonicHom Fact.out <| + - (aeval (AdjoinRoot.root p) (mapCoeffs p)) / (aeval (AdjoinRoot.root p) (derivative p))) (by + rintro x hx + simp_all only [RingHom.toIntAlgHom_apply, AdjoinRoot.mk_eq_zero] + obtain ⟨q, rfl⟩ := hx + simp only [Derivation.leibniz, smul_eq_mul] + apply dvd_add (dvd_mul_right ..) + apply dvd_mul_of_dvd_right + rw [← AdjoinRoot.mk_eq_zero] + unfold implicitDeriv + simp only [ne_eq, show p ≠ 0 from Irreducible.ne_zero Fact.out, not_false_eq_true, + AdjoinRoot.minpoly_root, show p.Monic from Fact.out, Monic.leadingCoeff, inv_one, map_one, + mul_one, AdjoinRoot.aeval_eq, Derivation.coe_add, Derivation.coe_smul, Pi.add_apply, + Pi.smul_apply, Derivation.restrictScalars_apply, derivative'_apply, smul_eq_mul, map_add, + map_mul, AdjoinRoot.mk_leftInverse Fact.out _] + rw [div_mul_cancel₀, add_neg_cancel] + simp only [ne_eq, AdjoinRoot.mk_eq_zero] + have : 0 < p.natDegree := Irreducible.natDegree_pos (Fact.out) + apply not_dvd_of_natDegree_lt + · intro nh + simp [natDegree_eq_zero_of_derivative_eq_zero nh] at this + apply natDegree_derivative_lt + exact Nat.not_eq_zero_of_lt this) + +instance (p : F[X]) [Fact (Irreducible p)] [Fact p.Monic] : + DifferentialAlgebra F (AdjoinRoot p) where + deriv_algebraMap a := by + change (Derivation.liftOfSurjective _ _) ((AdjoinRoot.mk p).toIntAlgHom (C a)) = _ + rw [Derivation.liftOfSurjective_apply, implicitDeriv_C] + rfl + +variable {K : Type*} [Field K] [Algebra F K] + +variable (F K) in + +/-- +If `K` is a finite field extension of `F` then we can define a differential algebra on `K`, by +choosing a primitive element of `K`, `k` and then using the equivalence to `AdjoinRoot (minpoly k)`. +-/ +@[reducible] +noncomputable def differentialFiniteDimensional [FiniteDimensional F K] : Differential K := + let k := (Field.exists_primitive_element F K).choose + have h : F⟮k⟯ = ⊤ := (Field.exists_primitive_element F K).choose_spec + have : Fact (minpoly F k).Monic := ⟨minpoly.monic (IsAlgebraic.of_finite ..).isIntegral⟩ + have : Fact (Irreducible (minpoly F k)) := + ⟨minpoly.irreducible (IsAlgebraic.of_finite ..).isIntegral⟩ + Differential.equiv (IntermediateField.adjoinRootEquivAdjoin F + (IsAlgebraic.of_finite F k).isIntegral |>.trans (IntermediateField.equivOfEq h) |>.trans + IntermediateField.topEquiv).symm.toRingEquiv + +lemma differentialAlgebraFiniteDimensional [FiniteDimensional F K] : + letI := differentialFiniteDimensional F K + DifferentialAlgebra F K := by + let k := (Field.exists_primitive_element F K).choose + haveI h : F⟮k⟯ = ⊤ := (Field.exists_primitive_element F K).choose_spec + haveI : Fact (minpoly F k).Monic := ⟨minpoly.monic (IsAlgebraic.of_finite ..).isIntegral⟩ + haveI : Fact (Irreducible (minpoly F k)) := + ⟨minpoly.irreducible (IsAlgebraic.of_finite ..).isIntegral⟩ + apply DifferentialAlgebra.equiv + +/-- +A finite extension of a differential field has a unique derivation which agrees with the one on the +base field. +-/ +noncomputable def uniqueDifferentialAlgebraFiniteDimensional [FiniteDimensional F K] : + Unique {_a : Differential K // DifferentialAlgebra F K} := by + let default : {_a : Differential K // DifferentialAlgebra F K} := + ⟨differentialFiniteDimensional F K, differentialAlgebraFiniteDimensional⟩ + refine ⟨⟨default⟩, fun ⟨a, ha⟩ ↦ ?_⟩ + ext x + apply_fun (aeval x (mapCoeffs (minpoly F x)) + aeval x (derivative (minpoly F x)) * ·) + · conv_lhs => apply (deriv_aeval_eq ..).symm + conv_rhs => apply (@deriv_aeval_eq _ _ _ _ _ default.1 _ default.2 _ _).symm + simp + · apply (add_right_injective _).comp + apply mul_right_injective₀ + rw [ne_eq, ← minpoly.dvd_iff] + have : 0 < (minpoly F x).natDegree := Irreducible.natDegree_pos + (minpoly.irreducible (Algebra.IsIntegral.isIntegral _)) + apply not_dvd_of_natDegree_lt + · intro nh + simp [natDegree_eq_zero_of_derivative_eq_zero nh] at this + apply natDegree_derivative_lt + exact Nat.not_eq_zero_of_lt this + +noncomputable instance (B : IntermediateField F K) [FiniteDimensional F B] : Differential B := + differentialFiniteDimensional F B + +instance (B : IntermediateField F K) [FiniteDimensional F B] : + DifferentialAlgebra F B := differentialAlgebraFiniteDimensional + +instance [Differential K] [DifferentialAlgebra F K] (B : IntermediateField F K) + [FiniteDimensional F B] : DifferentialAlgebra B K where + deriv_algebraMap a := by + change (B.val a)′ = B.val a′ + rw [algHom_deriv'] + exact Subtype.val_injective + end Differential diff --git a/Mathlib/FieldTheory/Differential/Liouville.lean b/Mathlib/FieldTheory/Differential/Liouville.lean new file mode 100644 index 0000000000000..cf9795aae7da6 --- /dev/null +++ b/Mathlib/FieldTheory/Differential/Liouville.lean @@ -0,0 +1,207 @@ +/- +Copyright (c) 2024 Daniel Weber. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Daniel Weber +-/ +import Mathlib.Algebra.Algebra.Field +import Mathlib.FieldTheory.Differential.Basic +import Mathlib.FieldTheory.Galois.Basic +import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure + +/-! +# Liouville's theorem + +A proof of Liouville's theorem. Follows +[Rosenlicht, M. Integration in finite terms][Rosenlicht_1972]. + +## Liouville field extension + +This file defines Liouville field extensions, which are differential field extensions which satisfy +a slight generalization of Liouville's theorem. Note that this definition doesn't appear in the +literature, and we introduce it as part of the formalization of Liouville's theorem. + +## Main declarations +- `IsLiouville`: A field extension being Liouville +- `isLiouville_of_finiteDimensional`: all finite dimensional field extensions + (of a field with characteristic 0) are Liouville. + +-/ + +open Differential algebraMap IntermediateField Finset Polynomial + +variable (F : Type*) (K : Type*) [Field F] [Field K] [Differential F] [Differential K] +variable [Algebra F K] [DifferentialAlgebra F K] + +/-- +We say that a differential field extension `K / F` is Liouville if, whenever an element `a ∈ F` can +be written as `a = v + ∑ cᵢ * logDeriv uᵢ` for `v, cᵢ, uᵢ ∈ K` and `cᵢ` constant, it can also be +written in that way with `v, cᵢ, uᵢ ∈ F`. +-/ +class IsLiouville : Prop where + isLiouville (a : F) (ι : Type) [Fintype ι] (c : ι → F) (hc : ∀ x, (c x)′ = 0) + (u : ι → K) (v : K) (h : a = ∑ x, c x * logDeriv (u x) + v′) : + ∃ (ι₀ : Type) (_ : Fintype ι₀) (c₀ : ι₀ → F) (_ : ∀ x, (c₀ x)′ = 0) + (u₀ : ι₀ → F) (v₀ : F), a = ∑ x, c₀ x * logDeriv (u₀ x) + v₀′ + +instance IsLiouville.rfl : IsLiouville F F where + isLiouville (a : F) (ι : Type) [Fintype ι] (c : ι → F) (hc : ∀ x, (c x)′ = 0) + (u : ι → F) (v : F) (h : a = ∑ x, c x * logDeriv (u x) + v′) := + ⟨ι, _, c, hc, u, v, h⟩ + +lemma IsLiouville.trans {A : Type*} [Field A] [Algebra K A] [Algebra F A] + [Differential A] [IsScalarTower F K A] [Differential.ContainConstants F K] + (inst1 : IsLiouville F K) (inst2 : IsLiouville K A) : IsLiouville F A where + isLiouville (a : F) (ι : Type) [Fintype ι] (c : ι → F) (hc : ∀ x, (c x)′ = 0) + (u : ι → A) (v : A) (h : a = ∑ x, c x * logDeriv (u x) + v′) := by + obtain ⟨ι₀, _, c₀, hc₀, u₀, v₀, h₀⟩ := inst2.isLiouville (a : K) ι + ((↑) ∘ c) + (fun _ ↦ by simp only [Function.comp_apply, ← coe_deriv, lift_map_eq_zero_iff, hc]) + ((↑) ∘ u) v (by simpa only [Function.comp_apply, ← IsScalarTower.algebraMap_apply]) + have hc (x : ι₀) := mem_range_of_deriv_eq_zero F (hc₀ x) + choose c₀ hc using hc + apply inst1.isLiouville a ι₀ c₀ _ u₀ v₀ + · rw [h₀] + simp [hc] + · intro + apply_fun ((↑) : F → K) + · simp only [Function.comp_apply, coe_deriv, hc, algebraMap.coe_zero] + apply hc₀ + · apply NoZeroSMulDivisors.algebraMap_injective + +section Algebraic +/- +The case of Liouville's theorem for algebraic extensions. +-/ + +variable {F K} [CharZero F] + +/-- +If `K` is a Liouville extension of `F` and `B` is a finite dimensional intermediate +field `K / B / F`, then it's also a Liouville extension of `F`. +-/ +instance (B : IntermediateField F K) + [FiniteDimensional F B] [inst : IsLiouville F K] : + IsLiouville F B where + isLiouville (a : F) (ι : Type) [Fintype ι] (c : ι → F) (hc : ∀ x, (c x)′ = 0) + (u : ι → B) (v : B) (h : a = ∑ x, c x * logDeriv (u x) + v′) := by + apply inst.isLiouville a ι c hc (B.val ∘ u) (B.val v) + dsimp only [coe_val, Function.comp_apply] + conv => + rhs + congr + · rhs + intro x + rhs + apply logDeriv_algebraMap (u x) + · apply (deriv_algebraMap v) + simp_rw [IsScalarTower.algebraMap_apply F B K] + norm_cast + + +/-- +Transfer an `IsLiouville` instance using an equivalence `K ≃ₐ[F] K'`. +Requires an algebraic `K'` to show that the equivalence commutes with the derivative. +-/ +lemma IsLiouville.equiv {K' : Type*} [Field K'] [Differential K'] [Algebra F K'] + [DifferentialAlgebra F K'] [Algebra.IsAlgebraic F K'] + [inst : IsLiouville F K] (e : K ≃ₐ[F] K') : IsLiouville F K' where + isLiouville (a : F) (ι : Type) [Fintype ι] (c : ι → F) (hc : ∀ x, (c x)′ = 0) + (u : ι → K') (v : K') (h : a = ∑ x, c x * logDeriv (u x) + v′) := by + apply inst.isLiouville a ι c hc (e.symm ∘ u) (e.symm v) + apply_fun e.symm at h + simpa [AlgEquiv.commutes, map_add, map_sum, map_mul, logDeriv, algEquiv_deriv'] using h + +/-- +A finite dimensional Galois extension of `F` is a Liouville extension. +This is private because it's generalized by all finite dimensional extensions being Liouville. +-/ +private local instance isLiouville_of_finiteDimensional_galois [FiniteDimensional F K] + [IsGalois F K] : IsLiouville F K where + isLiouville (a : F) (ι : Type) [Fintype ι] (c : ι → F) (hc : ∀ x, (c x)′ = 0) + (u : ι → K) (v : K) (h : a = ∑ x, c x * logDeriv (u x) + v′) := by + haveI : CharZero K := charZero_of_injective_algebraMap + (NoZeroSMulDivisors.algebraMap_injective F K) + -- We sum `e x` over all isomorphisms `e : K ≃ₐ[F] K`. + -- Because this is a Galois extension each of the relevant values will be in `F`. + -- We need to divide by `Fintype.card (K ≃ₐ[F] K)` to get the original answer. + let c₀ (i : ι) := (c i) / (Fintype.card (K ≃ₐ[F] K)) + -- logDeriv turns sums to products, so the new `u` will be the product of the old `u` over all + -- isomorphisms + let u₁ (i : ι) := ∏ x : (K ≃ₐ[F] K), x (u i) + -- Each of the values of u₁ are fixed by all isomorphisms. + have : ∀ i, u₁ i ∈ fixedField (⊤ : Subgroup (K ≃ₐ[F] K)) := by + rintro i ⟨e, _⟩ + change e (u₁ i) = u₁ i + simp only [u₁, map_prod] + apply Fintype.prod_equiv (Equiv.mulLeft e) + simp + have ffb : fixedField ⊤ = ⊥ := (IsGalois.tfae.out 0 1).mp (inferInstanceAs (IsGalois F K)) + simp_rw [ffb, IntermediateField.mem_bot, Set.mem_range] at this + -- Therefore they are all in `F`. We use `choose` to get their values in `F`. + choose u₀ hu₀ using this + -- We do almost the same thing for `v₁`, just with sum instead of product. + let v₁ := (∑ x : (K ≃ₐ[F] K), x v) / (Fintype.card ((K ≃ₐ[F] K))) + have : v₁ ∈ fixedField (⊤ : Subgroup (K ≃ₐ[F] K)) := by + rintro ⟨e, _⟩ + change e v₁ = v₁ + simp only [v₁, map_div₀, map_sum, map_natCast] + congr 1 + apply Fintype.sum_equiv (Equiv.mulLeft e) + simp + rw [ffb, IntermediateField.mem_bot] at this + obtain ⟨v₀, hv₀⟩ := this + exists ι, inferInstance, c₀, ?_, u₀, v₀ + · -- We need to prove that all `c₀` are constants. + -- This is true because they are the division of a constant by + -- a natural nubmer (which is also constant) + intro x + simp [c₀, Derivation.leibniz_div, hc] + · -- Proving that this works is mostly straightforward algebraic manipulation, + apply_fun (algebraMap F K) + case inj => + exact NoZeroSMulDivisors.algebraMap_injective F K + simp only [map_add, map_sum, map_mul, ← logDeriv_algebraMap, hu₀, ← deriv_algebraMap, hv₀] + unfold u₁ v₁ c₀ + clear c₀ u₁ u₀ hu₀ v₁ v₀ hv₀ + push_cast + rw [Derivation.leibniz_div_const, smul_eq_mul, inv_mul_eq_div] + case h => simp + simp only [map_sum, div_mul_eq_mul_div] + rw [← sum_div, ← add_div] + field_simp + -- Here we rewrite logDeriv (∏ x : K ≃ₐ[F] K, x (u i)) to ∑ x : K ≃ₐ[F] K, logDeriv (x (u i)) + conv => + enter [2, 1, 2, i, 2] + equals ∑ x : K ≃ₐ[F] K, logDeriv (x (u i)) => + by_cases h : u i = 0 <;> + simp [logDeriv_prod_of_eq_zero, logDeriv_prod, h] + simp_rw [mul_sum] + rw [sum_comm, ← sum_add_distrib] + trans ∑ _ : (K ≃ₐ[F] K), a + · simp [mul_comm] + · rcongr e + apply_fun e at h + simp only [AlgEquiv.commutes, map_add, map_sum, map_mul] at h + convert h using 2 + · rcongr x + simp [logDeriv, algEquiv_deriv'] + · rw [algEquiv_deriv'] + +/-- +We lift `isLiouville_of_finiteDimensional_galois` to non-Galois field extensions by using it for the +normal closure then obtaining it for `F`. +-/ +instance isLiouville_of_finiteDimensional [FiniteDimensional F K] : + IsLiouville F K := + let map := IsAlgClosed.lift (M := AlgebraicClosure F) (R := F) (S := K) + let K' := map.fieldRange + have : FiniteDimensional F K' := + LinearMap.finiteDimensional_range map.toLinearMap + let K'' := normalClosure F K' (AlgebraicClosure F) + let B : IntermediateField F K'' := IntermediateField.restrict + (F := K') (IntermediateField.le_normalClosure ..) + have kequiv : K ≃ₐ[F] ↥B := (show K ≃ₐ[F] K' from AlgEquiv.ofInjectiveField map).trans + (IntermediateField.restrict_algEquiv _) + IsLiouville.equiv kequiv.symm + +end Algebraic diff --git a/Mathlib/RingTheory/Derivation/DifferentialRing.lean b/Mathlib/RingTheory/Derivation/DifferentialRing.lean index a0d6e22ba7f17..f724ff2818ed3 100644 --- a/Mathlib/RingTheory/Derivation/DifferentialRing.lean +++ b/Mathlib/RingTheory/Derivation/DifferentialRing.lean @@ -13,6 +13,7 @@ use the x′ notation for the derivative of x. -/ /-- A derivation from a ring to itself, as a typeclass. -/ +@[ext] class Differential (R : Type*) [CommRing R] where /-- The `Derivation` associated with the ring. -/ deriv : Derivation ℤ R R From 0479fde8ab9553267f991d975d254e9cdfc4bec4 Mon Sep 17 00:00:00 2001 From: smorel394 Date: Fri, 10 Jan 2025 18:19:00 +0000 Subject: [PATCH 135/681] feat(CategoryTheory/Shift/Opposite and CategoryTheory/Shift/Pullback): `CommShift` structures on adjunctions are compatible with opposites and pullbacks (#20363) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suppose that we use categories `C` and `D` equiped with a shifts by an additive monoid `A`, functors `F,F' : C ⥤ D`, a functor `G : D ⥤ C`, a natural transformation `τ : F ⟶ F'` and an adjunction `adj` between `F` and `G`. * For any map of additive monoids `φ : B →+ A`, we define type synonyms `PullbackShift.functor F φ` for `F`, `PullbackShift.natTrans τ φ` for `τ`, and `PullbackShift.adjunction adj φ` for `adj`. We then prove that a `CommShift` structure on `F` (resp. `τ`, resp. `adj`) induces a `CommShift` structure on `PullbackShift.functor F φ` (resp. `PullbackShift.natTrans τ φ`, resp. `PullbackShift.adjunction adj φ` ). * Similarly, we define type synonyms `OppositeShift.functor A F` for `F.op`, `OppositeShift.natTrans A τ` for `τ.op` and `OppositeShift.adjunction A adj` for `adj.op`, and prove that a `CommShift` structure on `F` (resp. `τ`, resp. `adj`) induces a `CommShift` structure on `OppositeShift.functor A F` (resp. `OppositeShift.natTrans A τ`, resp. `OppositeShift.adjunction A adj` ) for the naive shifts on the opposite categories. * The point of the second part is to reserve `F.op` etc to carry `CommShift` structures for the modified shift on the opposite categories used in the theory of (pre)triangulated categories. We illustrate this by simplifying the definition of the instance `commShiftOpInt` (a `CommShift ℤ` instance on `F.op` for the modified shifts) in the file `Triangulated.Opposite.Functor`. - [x] depends on: #20364 Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- Mathlib/CategoryTheory/Shift/Opposite.lean | 167 ++++++++++++++-- Mathlib/CategoryTheory/Shift/Pullback.lean | 182 +++++++++++++++--- .../Triangulated/Opposite/Functor.lean | 8 +- 3 files changed, 316 insertions(+), 41 deletions(-) diff --git a/Mathlib/CategoryTheory/Shift/Opposite.lean b/Mathlib/CategoryTheory/Shift/Opposite.lean index fd57598711473..027409b829cae 100644 --- a/Mathlib/CategoryTheory/Shift/Opposite.lean +++ b/Mathlib/CategoryTheory/Shift/Opposite.lean @@ -3,7 +3,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 -/ -import Mathlib.CategoryTheory.Shift.CommShift +import Mathlib.CategoryTheory.Shift.Adjunction import Mathlib.CategoryTheory.Preadditive.Opposite /-! @@ -20,11 +20,35 @@ define the shift on `Cᵒᵖ` so that `shiftFunctor Cᵒᵖ n` for `n : ℤ` ide of the shift on `Cᵒᵖ` shall combine the shift on `OppositeShift C A` and another construction of the "pullback" of a shift by a monoid morphism like `n ↦ -n`. +If `F : C ⥤ D` is a functor between categories equipped with shifts by `A`, we define +a type synonym `OppositeShift.functor A F` for `F.op`. When `F` has a `CommShift` structure +by `A`, we define a `CommShift` structure by `A` on `OppositeShift.functor A F`. In this +way, we can make this an instance and reserve `F.op` for the `CommShift` instance by +the modified shift in the case of (pre)triangulated categories. + +Similarly,if `τ` is a natural transformation between functors `F,G : C ⥤ D`, we define +a type synonym for `τ.op` called +`OppositeShift.natTrans A τ : OppositeShift.functor A F ⟶ OppositeShift.functor A G`. +When `τ` has a `CommShift` structure by `A` (i.e. is compatible with `CommShift` structures +on `F` and `G`), we define a `CommShift` structure by `A` on `OppositeShift.natTrans A τ`. + +Finally, if we have an adjunction `F ⊣ G` (with `G : D ⥤ C`), we define a type synonym +`OppositeShift.adjunction A adj : OppositeShift.functor A G ⊣ OppositeShift.functor A F` +for `adj.op`, and we show that, if `adj` compatible with `CommShift` structures +on `F` and `G`, then `OppositeShift.adjunction A adj` is also compatible with the pulled back +`CommShift` structures. + +Given a `CommShift` structure on a functor `F`, we define a `CommShift` structure on `F.op` +(and vice versa). +We also prove that, if an adjunction `F ⊣ G` is compatible with `CommShift` structures on +`F` and `G`, then the opposite adjunction `G.op ⊣ F.op` is compatible with the opposite +`CommShift` structures. + -/ namespace CategoryTheory -open Limits +open Limits Category section @@ -114,18 +138,34 @@ lemma oppositeShiftFunctorAdd'_hom_app : end -variable {C D : Type*} [Category C] [Category D] (F : C ⥤ D) (A : Type*) [AddMonoid A] - [HasShift C A] [HasShift D A] +variable {C D : Type*} [Category C] [Category D] (A : Type*) [AddMonoid A] + [HasShift C A] [HasShift D A] (F : C ⥤ D) + +/-- +The functor `F.op`, seen as a functor from `OppositeShift C A` to `OppositeShift D A`. +(We will use this to carry a `CommShift` instance for the naive shifts on the opposite category. +Then, in the pretriangulated case, we will be able to put a `CommShift` instance on `F.op` +for the modified shifts and not deal with instance clashes. +-/ +def OppositeShift.functor : OppositeShift C A ⥤ OppositeShift D A := F.op + +variable {F} in +/-- +The natural transformation `τ`, seen as a natural transformation from `OppositeShift.functor F A` +to `OppositeShift.functor G A`.. +-/ +def OppositeShift.natTrans {G : C ⥤ D} (τ : F ⟶ G) : + OppositeShift.functor A G ⟶ OppositeShift.functor A F := + NatTrans.op τ namespace Functor /-- Given a `CommShift` structure on `F`, this is the corresponding `CommShift` structure on -`F.op` (for the naive shifts on the opposite categories). +`OppositeShift.functor F` (for the naive shifts on the opposite categories). -/ -@[simps] -noncomputable def commShiftOp [CommShift F A] : - CommShift (C := OppositeShift C A) (D := OppositeShift D A) F.op A where +noncomputable instance commShiftOp [CommShift F A] : + CommShift (OppositeShift.functor A F) A where iso a := (NatIso.op (F.commShiftIso a)).symm zero := by simp only @@ -144,15 +184,17 @@ noncomputable def commShiftOp [CommShift F A] : erw [oppositeShiftFunctorAdd_inv_app, oppositeShiftFunctorAdd_hom_app] rfl +lemma commShiftOp_iso_eq [CommShift F A] (a : A) : + (OppositeShift.functor A F).commShiftIso a = (NatIso.op (F.commShiftIso a)).symm := rfl + /-- -Given a `CommShift` structure on `F.op` (for the naive shifts on the opposite categories), -this is the corresponding `CommShift` structure on `F`. +Given a `CommShift` structure on `OppositeShift.functor F` (for the naive shifts on the opposite +categories), this is the corresponding `CommShift` structure on `F`. -/ @[simps] noncomputable def commShiftUnop - [CommShift (C := OppositeShift C A) (D := OppositeShift D A) F.op A] : CommShift F A where - iso a := NatIso.removeOp (F.op.commShiftIso (C := OppositeShift C A) - (D := OppositeShift D A) a).symm + [CommShift (OppositeShift.functor A F) A] : CommShift F A where + iso a := NatIso.removeOp ((OppositeShift.functor A F).commShiftIso a).symm zero := by simp only rw [commShiftIso_zero] @@ -173,4 +215,103 @@ noncomputable def commShiftUnop end Functor +namespace NatTrans + +attribute [local instance] Functor.commShiftOp + +variable {F} {G : C ⥤ D} [F.CommShift A] [G.CommShift A] + +open Opposite in +instance commShift_op (τ : F ⟶ G) [NatTrans.CommShift τ A] : + NatTrans.CommShift (OppositeShift.natTrans A τ) A where + shift_comm _ := by + ext + rw [← cancel_mono (((OppositeShift.functor A F).commShiftIso _ ).inv.app _), + ← cancel_epi (((OppositeShift.functor A G).commShiftIso _).inv.app _)] + dsimp + simp only [assoc, Iso.inv_hom_id_app_assoc, Iso.hom_inv_id_app, Functor.comp_obj, + Functor.op_obj, comp_id] + exact (op_inj_iff _ _).mpr (NatTrans.shift_app_comm τ _ (unop _)) + +end NatTrans + +namespace NatTrans + +variable (C) in +/-- The obvious isomorphism between the identity of `OppositeShift C A` and +`OppositeShift.functor (𝟙 C)`. +-/ +def OppositeShift.natIsoId : 𝟭 (OppositeShift C A) ≅ OppositeShift.functor A (𝟭 C) := Iso.refl _ + +/-- +The natural isomorphism `NatTrans.OppositeShift.natIsoId C A` commutes with shifts. +-/ +instance : NatTrans.CommShift (OppositeShift.natIsoId C A).hom A where + shift_comm _ := by + ext + dsimp [OppositeShift.natIsoId, Functor.commShiftOp_iso_eq] + simp only [Functor.commShiftIso_id_hom_app, Functor.comp_obj, Functor.id_obj, Functor.map_id, + comp_id, Functor.commShiftIso_id_inv_app, CategoryTheory.op_id, id_comp] + rfl + +variable {E : Type*} [Category E] [HasShift E A] (G : D ⥤ E) + +/-- The obvious isomorphism between `OppositeShift.functor (F ⋙ G)` and the +composition of `OppositeShift.functor F` and `OppositeShift.functor G`. +-/ +def OppositeShift.natIsoComp : OppositeShift.functor A (F ⋙ G) ≅ + OppositeShift.functor A F ⋙ OppositeShift.functor A G := Iso.refl _ + +instance [F.CommShift A] [G.CommShift A] : + NatTrans.CommShift (OppositeShift.natIsoComp A F G).hom A where + shift_comm _ := by + ext + dsimp [OppositeShift.natIsoComp, Functor.commShiftOp_iso_eq] + simp only [Functor.map_id, comp_id, id_comp] + rfl + +end NatTrans + +/-- +The adjunction `adj`, seen as an adjunction between `OppositeShift.functor G` +and `OppositeShift.functor F`. +-/ +@[simps (config := .lemmasOnly)] +def OppositeShift.adjunction {F} {G : D ⥤ C} (adj : F ⊣ G) : + OppositeShift.functor A G ⊣ OppositeShift.functor A F where + unit := (NatTrans.OppositeShift.natIsoId D A).hom ≫ + OppositeShift.natTrans A adj.counit ≫ (NatTrans.OppositeShift.natIsoComp A G F).hom + counit := (NatTrans.OppositeShift.natIsoComp A F G).inv ≫ + OppositeShift.natTrans A adj.unit ≫ (NatTrans.OppositeShift.natIsoId C A).inv + left_triangle_components _ := by + dsimp [OppositeShift.natTrans, NatTrans.OppositeShift.natIsoComp, + NatTrans.OppositeShift.natIsoId, OppositeShift.functor] + simp only [comp_id, id_comp, Quiver.Hom.unop_op] + rw [← op_comp, adj.right_triangle_components] + rfl + right_triangle_components _ := by + dsimp [OppositeShift.natTrans, NatTrans.OppositeShift.natIsoComp, + NatTrans.OppositeShift.natIsoId, OppositeShift.functor] + simp only [comp_id, id_comp, Quiver.Hom.unop_op] + rw [← op_comp, adj.left_triangle_components] + rfl + +namespace Adjunction + +attribute [local instance] Functor.commShiftOp NatTrans.commShift_op + +variable {F} {G : D ⥤ C} (adj : F ⊣ G) + +/-- +If an adjunction `F ⊣ G` is compatible with `CommShift` structures on `F` and `G`, then +the opposite adjunction `OppositeShift.adjunction adj` is compatible with the opposite +`CommShift` structures. +-/ +instance commShift_op [F.CommShift A] [G.CommShift A] [adj.CommShift A] : + Adjunction.CommShift (OppositeShift.adjunction A adj) A where + commShift_unit := by dsimp [OppositeShift.adjunction]; infer_instance + commShift_counit := by dsimp [OppositeShift.adjunction]; infer_instance + +end Adjunction + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Shift/Pullback.lean b/Mathlib/CategoryTheory/Shift/Pullback.lean index 0bce51f3ba6af..fde4d2b4db99c 100644 --- a/Mathlib/CategoryTheory/Shift/Pullback.lean +++ b/Mathlib/CategoryTheory/Shift/Pullback.lean @@ -3,7 +3,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 -/ -import Mathlib.CategoryTheory.Shift.CommShift +import Mathlib.CategoryTheory.Shift.Adjunction import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor /-! @@ -12,6 +12,22 @@ import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor Given a shift by a monoid `B` on a category `C` and a monoid morphism `φ : A →+ B`, we define a shift by `A` on a category `PullbackShift C φ` which is a type synonym for `C`. +If `F : C ⥤ D` is a functor between categories equipped with shifts by `B`, we define +a type synonym `PullbackShift.functor F φ` for `F`. When `F` has a `CommShift` structure +by `B`, we define a pulled back `CommShift` structure by `A` on `PullbackShift.functor F φ`. + +Similarly,if `τ` is a natural transformation between functors `F,G : C ⥤ D`, we define +a type synonym +`PullbackShift.natTrans τ φ : PullbackShift.functor F φ ⟶ PullbackShift.functor G φ`. +When `τ` has a `CommShift` structure by `B` (i.e. is compatible with `CommShift` structures +on `F` and `G`), we define a pulled back `CommShift` structure by `A` on +`PullbackShift.natTrans τ φ`. + +Finally, if we have an adjunction `F ⊣ G` (with `G : D ⥤ C`), we define a type synonym +`PullbackShift.adjunction adj φ : PullbackShift.functor F φ ⊣ PullbackShift.functor G φ` +and we show that, if `adj` compatible with `CommShift` structures +on `F` and `G`, then `PullbackShift.adjunction adj φ` iis also compatible with the pulled back +`CommShift` structures. -/ namespace CategoryTheory @@ -97,6 +113,7 @@ lemma pullbackShiftFunctorAdd'_inv_app : (pullbackShiftIso C φ a₃ b₃ h₃).inv.app X := by subst h₁ h₂ h obtain rfl : b₃ = φ a₁ + φ a₂ := by rw [h₃, φ.map_add] + simp erw [Functor.map_id, id_comp, id_comp, shiftFunctorAdd'_eq_shiftFunctorAdd, shiftFunctorAdd'_eq_shiftFunctorAdd] change _ ≫ _ = _ @@ -118,15 +135,32 @@ lemma pullbackShiftFunctorAdd'_hom_app : ← Functor.map_comp, Iso.hom_inv_id_app, Functor.map_id] rfl -namespace Functor - variable {D : Type*} [Category D] [HasShift D B] (F : C ⥤ D) [F.CommShift B] -/-- If `F : C ⥤ D` commutes with the shifts on `C` and `D`, then it also commutes with -their pullbacks by an additive map. +/-- +The functor `F`, seen as a functor from `PullbackShift C φ` to `PullbackShift D φ`. +Then a `CommShift B` instance on `F` will define a `CommShift A` instance on +`PullbackShift.functor F φ`, and we won't have to juggle with two `CommShift` instances +on `F`. +-/ +def PullbackShift.functor : PullbackShift C φ ⥤ PullbackShift D φ := F + +variable {F} in +/-- +The natural transformation `τ`, seen as a natural transformation from `PullbackShift.functor F φ` +to `PullbackShift.functor G φ`. Then a `CommShift B` instance on `τ` will define a `CommShift A` +instance on `PullbackShift.natTrans τ φ`, and we won't have to juggle with two `CommShift` +instances on `τ`. +-/ +def PullbackShift.natTrans {G : C ⥤ D} (τ : F ⟶ G) : + PullbackShift.functor φ F ⟶ PullbackShift.functor φ G := τ + +namespace Functor + +/-- If `F : C ⥤ D` commutes with the shifts on `C` and `D`, then `PullbackShift.functor F φ` +commutes with their pullbacks by an additive map `φ`. -/ -noncomputable def commShiftPullback : - F.CommShift A (C := PullbackShift C φ) (D := PullbackShift D φ) where +noncomputable instance commShiftPullback : (PullbackShift.functor φ F).CommShift A where iso a := isoWhiskerRight (pullbackShiftIso C φ a (φ a) rfl) F ≪≫ F.commShiftIso (φ a) ≪≫ isoWhiskerLeft _ (pullbackShiftIso D φ a (φ a) rfl).symm zero := by @@ -135,32 +169,30 @@ noncomputable def commShiftPullback : simp only [F.commShiftIso_zero' (A := B) (φ 0) (by rw [map_zero]), CommShift.isoZero'_hom_app, assoc, CommShift.isoZero_hom_app, pullbackShiftFunctorZero'_hom_app, map_comp, pullbackShiftFunctorZero'_inv_app] - dsimp rfl - add a b := by + add _ _ := by ext - dsimp - simp only [CommShift.isoAdd_hom_app, map_comp, assoc] - dsimp - rw [F.commShiftIso_add' (a := φ a) (b := φ b) (by rw [φ.map_add]), + simp only [PullbackShift.functor, comp_obj, Iso.trans_hom, isoWhiskerRight_hom, + isoWhiskerLeft_hom, Iso.symm_hom, NatTrans.comp_app, whiskerRight_app, whiskerLeft_app, + CommShift.isoAdd_hom_app, map_comp, assoc] + rw [F.commShiftIso_add' (φ.map_add _ _).symm, ← shiftFunctorAdd'_eq_shiftFunctorAdd, ← shiftFunctorAdd'_eq_shiftFunctorAdd, - pullbackShiftFunctorAdd'_hom_app φ _ a b (a + b) rfl (φ a) (φ b) (φ (a + b)) rfl rfl rfl, - pullbackShiftFunctorAdd'_inv_app φ _ a b (a + b) rfl (φ a) (φ b) (φ (a + b)) rfl rfl rfl] - dsimp + pullbackShiftFunctorAdd'_hom_app φ _ _ _ _ rfl _ _ _ rfl rfl rfl, + pullbackShiftFunctorAdd'_inv_app φ _ _ _ _ rfl _ _ _ rfl rfl rfl] simp only [CommShift.isoAdd'_hom_app, assoc, map_comp, NatTrans.naturality_assoc, Iso.inv_hom_id_app_assoc] slice_rhs 9 10 => rw [← map_comp, Iso.inv_hom_id_app, map_id] - erw [id_comp] - slice_rhs 6 7 => erw [← (CommShift.iso (φ b)).hom.naturality] - slice_rhs 4 5 => rw [← map_comp, (pullbackShiftIso C φ b (φ b) rfl).hom.naturality, map_comp] - simp only [comp_obj, Functor.comp_map, assoc] + simp only [comp_obj, id_comp] + rw [← Functor.comp_map F (shiftFunctor D _), ← (F.commShiftIso _).hom.naturality_assoc] + slice_rhs 4 5 => rw [← map_comp, (pullbackShiftIso C φ _ _ rfl).hom.naturality, map_comp] slice_rhs 3 4 => rw [← map_comp, Iso.inv_hom_id_app, map_id] - slice_rhs 4 5 => rw [← map_comp]; erw [← map_comp]; rw [Iso.inv_hom_id_app, map_id, map_id] - rw [id_comp, id_comp, assoc, assoc]; rfl + simp only [comp_obj, id_comp, comp_map, assoc] + slice_rhs 3 4 => rw [← map_comp, ← map_comp, Iso.inv_hom_id_app, map_id, map_id] + rw [id_comp, assoc, assoc] + rfl lemma commShiftPullback_iso_eq (a : A) (b : B) (h : b = φ a) : - letI : F.CommShift (C := PullbackShift C φ) (D := PullbackShift D φ) A := F.commShiftPullback φ - F.commShiftIso a (C := PullbackShift C φ) (D := PullbackShift D φ) = + (PullbackShift.functor φ F).commShiftIso a (C := PullbackShift C φ) (D := PullbackShift D φ) = isoWhiskerRight (pullbackShiftIso C φ a b h) F ≪≫ (F.commShiftIso b) ≪≫ isoWhiskerLeft F (pullbackShiftIso D φ a b h).symm := by obtain rfl : b = φ a := h @@ -168,4 +200,106 @@ lemma commShiftPullback_iso_eq (a : A) (b : B) (h : b = φ a) : end Functor +namespace NatTrans + +attribute [local instance] Functor.commShiftPullback + +variable {F} {G : C ⥤ D} [G.CommShift B] + +open Functor in +instance commShiftPullback (τ : F ⟶ G) [NatTrans.CommShift τ B] : + NatTrans.CommShift (PullbackShift.natTrans φ τ) A where + shift_comm _ := by + ext + dsimp [PullbackShift.natTrans] + simp only [commShiftPullback_iso_eq φ _ _ _ rfl, Iso.trans_hom, isoWhiskerRight_hom, + isoWhiskerLeft_hom, Iso.symm_hom, comp_app, comp_obj, whiskerRight_app, whiskerLeft_app, + assoc] + rw [← τ.naturality_assoc] + simp [← NatTrans.shift_app_comm_assoc] + +variable (C) in +/-- The natural isomorphism between the identity of `PullbackShift C φ` and the +pullback of the identity of `C`. +-/ +def PullbackShift.natIsoId : 𝟭 (PullbackShift C φ) ≅ PullbackShift.functor φ (𝟭 C) := Iso.refl _ + +/-- +This expresses the compatibility between two `CommShift` structures by `A` on (synonyms of) +`𝟭 C`: the canonical `CommShift` structure on `𝟭 (PullbackShift C φ)`, and the `CommShift` +structure on `PullbackShift.functor (𝟭 C) φ` (i.e the pullback of the canonical `CommShift` +structure on `𝟭 C`). +-/ +instance : NatTrans.CommShift (PullbackShift.natIsoId C φ).hom A where + shift_comm _ := by + ext + simp [PullbackShift.natIsoId, Functor.commShiftPullback_iso_eq] + +variable (F) {E : Type*} [Category E] [HasShift E B] (G : D ⥤ E) [G.CommShift B] + +/-- The natural isomorphism between the pullback of `F ⋙ G` and the +composition of the pullbacks of `F` and `G`. +-/ +def PullbackShift.natIsoComp : PullbackShift.functor φ (F ⋙ G) ≅ + PullbackShift.functor φ F ⋙ PullbackShift.functor φ G := Iso.refl _ + +/- +Suppose that `F` and `G` have `CommShift` structure by `B`. This expresses the +compatibility between two `CommShift` structures by `A` on (synonyms of) `F ⋙ G`: +the `CommShift` structure on `PullbackShift.functor (F ⋙ G) φ` (i.e the pullback of the +composition of `CommShift` structures by `B` on `F` and `G`), and that on +`PullbackShift.functor F φ ⋙ PullbackShift.functor G φ` (i.e. the one coming from +the composition of the pulled back `CommShift` structures on `F` and `G`). +-/ +open Functor in +instance : NatTrans.CommShift (PullbackShift.natIsoComp φ F G).hom A where + shift_comm _ := by + ext + dsimp [PullbackShift.natIsoComp] + simp only [commShiftPullback_iso_eq φ _ _ _ rfl, Iso.trans_hom, isoWhiskerRight_hom, + isoWhiskerLeft_hom, Iso.symm_hom, comp_app, comp_obj, whiskerRight_app, Functor.comp_map, + commShiftIso_comp_hom_app, whiskerLeft_app, assoc, map_id, comp_id, map_comp, id_comp] + dsimp [PullbackShift.functor] + slice_rhs 3 4 => rw [← G.map_comp, Iso.inv_hom_id_app] + simp + +end NatTrans + +/-- +The adjunction `adj`, seen as an adjunction between `PullbackShift.functor F φ` +and `PullbackShift.functor G φ`. +-/ +@[simps (config := .lemmasOnly)] +def PullbackShift.adjunction {F} {G : D ⥤ C} (adj : F ⊣ G) : + PullbackShift.functor φ F ⊣ PullbackShift.functor φ G where + unit := (NatTrans.PullbackShift.natIsoId C φ).hom ≫ + PullbackShift.natTrans φ adj.unit ≫ (NatTrans.PullbackShift.natIsoComp φ F G).hom + counit := (NatTrans.PullbackShift.natIsoComp φ G F).inv ≫ + PullbackShift.natTrans φ adj.counit ≫ (NatTrans.PullbackShift.natIsoId D φ).inv + left_triangle_components _ := by + simp [PullbackShift.natTrans, NatTrans.PullbackShift.natIsoComp, + NatTrans.PullbackShift.natIsoId, PullbackShift.functor] + right_triangle_components _ := by + simp [PullbackShift.natTrans, NatTrans.PullbackShift.natIsoComp, + NatTrans.PullbackShift.natIsoId, PullbackShift.functor] + +namespace Adjunction + +variable {F} {G : D ⥤ C} (adj : F ⊣ G) [G.CommShift B] + +/-- +If an adjunction `F ⊣ G` is compatible with `CommShift` structures on `F` and `G`, then +it is also compatible with the pulled back `CommShift` structures by an additive map +`φ : B →+ A`. +-/ +instance commShiftPullback [adj.CommShift B] : (PullbackShift.adjunction φ adj).CommShift A where + commShift_unit := by + dsimp [PullbackShift.adjunction] + infer_instance + commShift_counit := by + dsimp [PullbackShift.adjunction] + infer_instance + +end Adjunction + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean index c83e89983d0b5..46e03494d123a 100644 --- a/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean +++ b/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean @@ -31,10 +31,10 @@ namespace Pretriangulated.Opposite /-- If `F` commutes with shifts, so does `F.op`, for the shifts chosen on `Cᵒᵖ` in `CategoryTheory.Triangulated.Opposite.Basic`. -/ -noncomputable scoped instance commShiftOpInt : F.op.CommShift ℤ := by - letI F' : OppositeShift C ℤ ⥤ OppositeShift D ℤ := F.op - letI : F'.CommShift ℤ := F.commShiftOp ℤ - apply F'.commShiftPullback +noncomputable scoped instance commShiftOpInt : F.op.CommShift ℤ := + inferInstanceAs ((PullbackShift.functor + (AddMonoidHom.mk' (fun (n : ℤ) => -n) (by intros; dsimp; omega)) + (OppositeShift.functor ℤ F)).CommShift ℤ) end Pretriangulated.Opposite From ceb6589394fc3c771e2ed87ed51b9e24ae9f6af8 Mon Sep 17 00:00:00 2001 From: grunweg Date: Fri, 10 Jan 2025 18:19:02 +0000 Subject: [PATCH 136/681] chore: use ofNat more (#20546) When a theorem statement contains both ofNat and OfNat.ofNat, replace the latter by the former: as eric-wieser [says](https://github.com/leanprover-community/mathlib4/pull/20521#pullrequestreview-2532627381), these are mostly theorems that work forwards, but not backwards, with simp. Very much not exhaustive, there are perhaps 160 instances in mathlib remaining. Co-authored-by: grunweg --- Mathlib/Algebra/AddConstMap/Basic.lean | 14 +++++++------- Mathlib/Algebra/DirectSum/Internal.lean | 2 +- Mathlib/Algebra/Module/LinearMap/End.lean | 2 +- Mathlib/Algebra/Module/NatInt.lean | 2 +- Mathlib/Algebra/Order/SuccPred/WithBot.lean | 2 +- Mathlib/Algebra/Polynomial/Eval/Defs.lean | 8 ++++---- Mathlib/Algebra/Star/Basic.lean | 2 +- Mathlib/Analysis/Normed/Group/Basic.lean | 4 ++-- Mathlib/Data/Matrix/Kronecker.lean | 4 ++-- Mathlib/Data/Matrix/Notation.lean | 4 ++-- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Mathlib/Algebra/AddConstMap/Basic.lean b/Mathlib/Algebra/AddConstMap/Basic.lean index f71b10f9c82ba..dc5674fb8f1ef 100644 --- a/Mathlib/Algebra/AddConstMap/Basic.lean +++ b/Mathlib/Algebra/AddConstMap/Basic.lean @@ -87,7 +87,7 @@ theorem map_add_one [AddMonoidWithOne G] [Add H] [AddConstMapClass F G H 1 b] @[scoped simp] theorem map_add_ofNat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : - f (x + ofNat(n)) = f x + (OfNat.ofNat n : ℕ) • b := + f (x + ofNat(n)) = f x + (ofNat(n) : ℕ) • b := map_add_nat' f x n theorem map_add_nat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] @@ -95,7 +95,7 @@ theorem map_add_nat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass theorem map_add_ofNat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : - f (x + OfNat.ofNat n) = f x + OfNat.ofNat n := map_add_nat f x n + f (x + ofNat(n)) = f x + ofNat(n) := map_add_nat f x n @[scoped simp] theorem map_const [AddZeroClass G] [Add H] [AddConstMapClass F G H a b] (f : F) : @@ -118,7 +118,7 @@ theorem map_nat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] theorem map_ofNat' [AddMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] (f : F) (n : ℕ) [n.AtLeastTwo] : - f (OfNat.ofNat n) = f 0 + (OfNat.ofNat n : ℕ) • b := + f (ofNat(n)) = f 0 + (ofNat(n) : ℕ) • b := map_nat' f n theorem map_nat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] @@ -126,7 +126,7 @@ theorem map_nat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G theorem map_ofNat [AddMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] (f : F) (n : ℕ) [n.AtLeastTwo] : - f (OfNat.ofNat n) = f 0 + OfNat.ofNat n := map_nat f n + f ofNat(n) = f 0 + ofNat(n) := map_nat f n @[scoped simp] theorem map_const_add [AddCommSemigroup G] [Add H] [AddConstMapClass F G H a b] @@ -148,7 +148,7 @@ theorem map_nat_add' [AddCommMonoidWithOne G] [AddMonoid H] [AddConstMapClass F theorem map_ofNat_add' [AddCommMonoidWithOne G] [AddMonoid H] [AddConstMapClass F G H 1 b] (f : F) (n : ℕ) [n.AtLeastTwo] (x : G) : - f (OfNat.ofNat n + x) = f x + OfNat.ofNat n • b := + f (ofNat(n) + x) = f x + ofNat(n) • b := map_nat_add' f n x theorem map_nat_add [AddCommMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] @@ -156,7 +156,7 @@ theorem map_nat_add [AddCommMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapCl theorem map_ofNat_add [AddCommMonoidWithOne G] [AddMonoidWithOne H] [AddConstMapClass F G H 1 1] (f : F) (n : ℕ) [n.AtLeastTwo] (x : G) : - f (OfNat.ofNat n + x) = f x + OfNat.ofNat n := + f (ofNat(n) + x) = f x + ofNat(n) := map_nat_add f n x @[scoped simp] @@ -181,7 +181,7 @@ theorem map_sub_nat' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 @[scoped simp] theorem map_sub_ofNat' [AddGroupWithOne G] [AddGroup H] [AddConstMapClass F G H 1 b] (f : F) (x : G) (n : ℕ) [n.AtLeastTwo] : - f (x - ofNat(n)) = f x - OfNat.ofNat n • b := + f (x - ofNat(n)) = f x - ofNat(n) • b := map_sub_nat' f x n @[scoped simp] diff --git a/Mathlib/Algebra/DirectSum/Internal.lean b/Mathlib/Algebra/DirectSum/Internal.lean index fb7946b75ad16..7417729ccc95f 100644 --- a/Mathlib/Algebra/DirectSum/Internal.lean +++ b/Mathlib/Algebra/DirectSum/Internal.lean @@ -337,7 +337,7 @@ instance instSemiring : Semiring (A 0) := (subsemiring A).toSemiring @[simp, norm_cast] theorem coe_natCast (n : ℕ) : (n : A 0) = (n : R) := rfl @[simp, norm_cast] theorem coe_ofNat (n : ℕ) [n.AtLeastTwo] : - (ofNat(n) : A 0) = (OfNat.ofNat n : R) := rfl + (ofNat(n) : A 0) = (ofNat(n) : R) := rfl end Semiring diff --git a/Mathlib/Algebra/Module/LinearMap/End.lean b/Mathlib/Algebra/Module/LinearMap/End.lean index d7cac2488f1b0..713b1a4092176 100644 --- a/Mathlib/Algebra/Module/LinearMap/End.lean +++ b/Mathlib/Algebra/Module/LinearMap/End.lean @@ -89,7 +89,7 @@ theorem _root_.Module.End.natCast_apply (n : ℕ) (m : M) : (↑n : Module.End R @[simp] theorem _root_.Module.End.ofNat_apply (n : ℕ) [n.AtLeastTwo] (m : M) : - (ofNat(n) : Module.End R M) m = OfNat.ofNat n • m := rfl + (ofNat(n) : Module.End R M) m = ofNat(n) • m := rfl instance _root_.Module.End.ring : Ring (Module.End R N₁) := { Module.End.semiring, LinearMap.addCommGroup with diff --git a/Mathlib/Algebra/Module/NatInt.lean b/Mathlib/Algebra/Module/NatInt.lean index a0ef8033c90e5..606a7988f0fbe 100644 --- a/Mathlib/Algebra/Module/NatInt.lean +++ b/Mathlib/Algebra/Module/NatInt.lean @@ -103,7 +103,7 @@ lemma Nat.cast_smul_eq_nsmul (n : ℕ) (b : M) : (n : R) • b = n • b := by /-- `nsmul` is equal to any other module structure via a cast. -/ lemma ofNat_smul_eq_nsmul (n : ℕ) [n.AtLeastTwo] (b : M) : - (ofNat(n) : R) • b = OfNat.ofNat n • b := Nat.cast_smul_eq_nsmul .. + (ofNat(n) : R) • b = ofNat(n) • b := Nat.cast_smul_eq_nsmul .. /-- `nsmul` is equal to any other module structure via a cast. -/ @[deprecated Nat.cast_smul_eq_nsmul (since := "2024-07-23")] diff --git a/Mathlib/Algebra/Order/SuccPred/WithBot.lean b/Mathlib/Algebra/Order/SuccPred/WithBot.lean index 08d2abbd2dca9..9301775091c0b 100644 --- a/Mathlib/Algebra/Order/SuccPred/WithBot.lean +++ b/Mathlib/Algebra/Order/SuccPred/WithBot.lean @@ -24,6 +24,6 @@ lemma succ_one : succ (1 : WithBot α) = 2 := by simpa [one_add_one_eq_two] usin @[simp] lemma succ_ofNat (n : ℕ) [n.AtLeastTwo] : - succ (ofNat(n) : WithBot α) = OfNat.ofNat n + 1 := succ_natCast n + succ (ofNat(n) : WithBot α) = ofNat(n) + 1 := succ_natCast n end WithBot diff --git a/Mathlib/Algebra/Polynomial/Eval/Defs.lean b/Mathlib/Algebra/Polynomial/Eval/Defs.lean index 5b47a0237e819..088010ca51334 100644 --- a/Mathlib/Algebra/Polynomial/Eval/Defs.lean +++ b/Mathlib/Algebra/Polynomial/Eval/Defs.lean @@ -104,7 +104,7 @@ alias eval₂_nat_cast := eval₂_natCast @[simp] lemma eval₂_ofNat {S : Type*} [Semiring S] (n : ℕ) [n.AtLeastTwo] (f : R →+* S) (a : S) : - (ofNat(n) : R[X]).eval₂ f a = OfNat.ofNat n := by + (ofNat(n) : R[X]).eval₂ f a = ofNat(n) := by simp [OfNat.ofNat] variable [Semiring T] @@ -264,7 +264,7 @@ alias eval₂_at_nat_cast := eval₂_at_natCast @[simp] theorem eval₂_at_ofNat {S : Type*} [Semiring S] (f : R →+* S) (n : ℕ) [n.AtLeastTwo] : - p.eval₂ f ofNat(n) = f (p.eval (OfNat.ofNat n)) := by + p.eval₂ f ofNat(n) = f (p.eval (ofNat(n))) := by simp [OfNat.ofNat] @[simp] @@ -279,7 +279,7 @@ alias eval_nat_cast := eval_natCast @[simp] lemma eval_ofNat (n : ℕ) [n.AtLeastTwo] (a : R) : - (ofNat(n) : R[X]).eval a = OfNat.ofNat n := by + (ofNat(n) : R[X]).eval a = ofNat(n) := by simp only [OfNat.ofNat, eval_natCast] @[simp] @@ -549,7 +549,7 @@ alias map_nat_cast := map_natCast @[simp] protected theorem map_ofNat (n : ℕ) [n.AtLeastTwo] : - (ofNat(n) : R[X]).map f = OfNat.ofNat n := + (ofNat(n) : R[X]).map f = ofNat(n) := show (n : R[X]).map f = n by rw [Polynomial.map_natCast] --TODO rename to `map_dvd_map` diff --git a/Mathlib/Algebra/Star/Basic.lean b/Mathlib/Algebra/Star/Basic.lean index 929ae83b99d4a..26ed998ae7869 100644 --- a/Mathlib/Algebra/Star/Basic.lean +++ b/Mathlib/Algebra/Star/Basic.lean @@ -289,7 +289,7 @@ theorem star_natCast [NonAssocSemiring R] [StarRing R] (n : ℕ) : star (n : R) @[simp] theorem star_ofNat [NonAssocSemiring R] [StarRing R] (n : ℕ) [n.AtLeastTwo] : - star (ofNat(n) : R) = OfNat.ofNat n := + star (ofNat(n) : R) = ofNat(n) := star_natCast _ section diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index 493bd417df034..79417c8b0f215 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -1240,10 +1240,10 @@ theorem le_norm_self (r : ℝ) : r ≤ ‖r‖ := @[deprecated (since := "2024-04-05")] alias nnnorm_coe_nat := nnnorm_natCast @[simp 1100] lemma norm_ofNat (n : ℕ) [n.AtLeastTwo] : - ‖(ofNat(n) : ℝ)‖ = OfNat.ofNat n := norm_natCast n + ‖(ofNat(n) : ℝ)‖ = ofNat(n) := norm_natCast n @[simp 1100] lemma nnnorm_ofNat (n : ℕ) [n.AtLeastTwo] : - ‖(ofNat(n) : ℝ)‖₊ = OfNat.ofNat n := nnnorm_natCast n + ‖(ofNat(n) : ℝ)‖₊ = ofNat(n) := nnnorm_natCast n lemma norm_two : ‖(2 : ℝ)‖ = 2 := abs_of_pos zero_lt_two lemma nnnorm_two : ‖(2 : ℝ)‖₊ = 2 := NNReal.eq <| by simp diff --git a/Mathlib/Data/Matrix/Kronecker.lean b/Mathlib/Data/Matrix/Kronecker.lean index 0d5b9fc77bc99..525e8243ba190 100644 --- a/Mathlib/Data/Matrix/Kronecker.lean +++ b/Mathlib/Data/Matrix/Kronecker.lean @@ -314,13 +314,13 @@ theorem natCast_kronecker [NonAssocSemiring α] [DecidableEq l] (a : ℕ) (B : M theorem kronecker_ofNat [Semiring α] [DecidableEq n] (A : Matrix l m α) (b : ℕ) [b.AtLeastTwo] : A ⊗ₖ (ofNat(b) : Matrix n n α) = - blockDiagonal fun _ => A <• (OfNat.ofNat b : α) := + blockDiagonal fun _ => A <• (ofNat(b) : α) := kronecker_diagonal _ _ theorem ofNat_kronecker [Semiring α] [DecidableEq l] (a : ℕ) [a.AtLeastTwo] (B : Matrix m n α) : (ofNat(a) : Matrix l l α) ⊗ₖ B = Matrix.reindex (.prodComm _ _) (.prodComm _ _) - (blockDiagonal fun _ => (OfNat.ofNat a : α) • B) := + (blockDiagonal fun _ => (ofNat(a) : α) • B) := diagonal_kronecker _ _ theorem one_kronecker_one [MulZeroOneClass α] [DecidableEq m] [DecidableEq n] : diff --git a/Mathlib/Data/Matrix/Notation.lean b/Mathlib/Data/Matrix/Notation.lean index e29b479e13304..a4a408c1a9a64 100644 --- a/Mathlib/Data/Matrix/Notation.lean +++ b/Mathlib/Data/Matrix/Notation.lean @@ -420,12 +420,12 @@ theorem natCast_fin_three (n : ℕ) : theorem ofNat_fin_two (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : Matrix (Fin 2) (Fin 2) α) = - !![OfNat.ofNat n, 0; 0, OfNat.ofNat n] := + !![ofNat(n), 0; 0, ofNat(n)] := natCast_fin_two _ theorem ofNat_fin_three (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : Matrix (Fin 3) (Fin 3) α) = - !![OfNat.ofNat n, 0, 0; 0, OfNat.ofNat n, 0; 0, 0, OfNat.ofNat n] := + !![ofNat(n), 0, 0; 0, ofNat(n), 0; 0, 0, ofNat(n)] := natCast_fin_three _ end AddMonoidWithOne From acc35eb4da97e419bcedc5fd8ee1a0639c29c2ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 18:19:03 +0000 Subject: [PATCH 137/681] chore: make `FooHom.coe_id` a `norm_cast` lemma (#20576) From GrowthInGroups (LeanCamCombi) --- Mathlib/Algebra/Algebra/Hom.lean | 2 +- Mathlib/Algebra/Algebra/NonUnitalHom.lean | 2 +- Mathlib/Algebra/Lie/Basic.lean | 4 ++-- Mathlib/Algebra/Order/Hom/Monoid.lean | 2 +- Mathlib/Algebra/Order/Hom/Ring.lean | 2 +- Mathlib/Algebra/Ring/Hom/Defs.lean | 2 +- Mathlib/Algebra/Star/StarAlgHom.lean | 4 ++-- Mathlib/Algebra/Star/StarRingHom.lean | 2 +- Mathlib/Analysis/Normed/Affine/Isometry.lean | 2 +- Mathlib/Analysis/Normed/Operator/LinearIsometry.lean | 2 +- Mathlib/Data/PFun.lean | 2 +- Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean | 2 +- Mathlib/Order/Heyting/Hom.lean | 6 +++--- Mathlib/Order/Hom/Bounded.lean | 6 +++--- Mathlib/Order/Hom/CompleteLattice.lean | 8 ++++---- Mathlib/Order/Hom/Lattice.lean | 12 ++++++------ Mathlib/RingTheory/Bialgebra/Hom.lean | 2 +- Mathlib/RingTheory/Coalgebra/Hom.lean | 2 +- Mathlib/Topology/Bornology/Hom.lean | 2 +- Mathlib/Topology/ContinuousMap/Basic.lean | 2 +- Mathlib/Topology/ContinuousMap/CocompactMap.lean | 2 +- Mathlib/Topology/Hom/Open.lean | 2 +- Mathlib/Topology/Order/Hom/Basic.lean | 2 +- Mathlib/Topology/Order/Hom/Esakia.lean | 10 +++++----- Mathlib/Topology/Spectral/Hom.lean | 2 +- 25 files changed, 43 insertions(+), 43 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Hom.lean b/Mathlib/Algebra/Algebra/Hom.lean index 2640de8265822..d5e421d9d1b06 100644 --- a/Mathlib/Algebra/Algebra/Hom.lean +++ b/Mathlib/Algebra/Algebra/Hom.lean @@ -244,7 +244,7 @@ variable (R A) protected def id : A →ₐ[R] A := { RingHom.id A with commutes' := fun _ => rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(AlgHom.id R A) = id := rfl diff --git a/Mathlib/Algebra/Algebra/NonUnitalHom.lean b/Mathlib/Algebra/Algebra/NonUnitalHom.lean index 88d007dcb7961..d4e25752e01d4 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalHom.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalHom.lean @@ -255,7 +255,7 @@ protected def id (R A : Type*) [Monoid R] [NonUnitalNonAssocSemiring A] toFun := id map_smul' := fun _ _ => rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(NonUnitalAlgHom.id R A) = id := rfl diff --git a/Mathlib/Algebra/Lie/Basic.lean b/Mathlib/Algebra/Lie/Basic.lean index 7a022b824e648..9d53a393cf7e3 100644 --- a/Mathlib/Algebra/Lie/Basic.lean +++ b/Mathlib/Algebra/Lie/Basic.lean @@ -342,7 +342,7 @@ theorem map_zero (f : L₁ →ₗ⁅R⁆ L₂) : f 0 = 0 := def id : L₁ →ₗ⁅R⁆ L₁ := { (LinearMap.id : L₁ →ₗ[R] L₁) with map_lie' := rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(id : L₁ →ₗ⁅R⁆ L₁) = _root_.id := rfl @@ -703,7 +703,7 @@ theorem map_zero (f : M →ₗ⁅R,L⁆ N) : f 0 = 0 := def id : M →ₗ⁅R,L⁆ M := { (LinearMap.id : M →ₗ[R] M) with map_lie' := rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ((id : M →ₗ⁅R,L⁆ M) : M → M) = _root_.id := rfl diff --git a/Mathlib/Algebra/Order/Hom/Monoid.lean b/Mathlib/Algebra/Order/Hom/Monoid.lean index d7ee5915f5f32..3d500aac8d1f6 100644 --- a/Mathlib/Algebra/Order/Hom/Monoid.lean +++ b/Mathlib/Algebra/Order/Hom/Monoid.lean @@ -748,7 +748,7 @@ variable (α) protected def id : α →*₀o α := { MonoidWithZeroHom.id α, OrderHom.id with } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(OrderMonoidWithZeroHom.id α) = id := rfl diff --git a/Mathlib/Algebra/Order/Hom/Ring.lean b/Mathlib/Algebra/Order/Hom/Ring.lean index 323dff053b3b5..05433d9cf069a 100644 --- a/Mathlib/Algebra/Order/Hom/Ring.lean +++ b/Mathlib/Algebra/Order/Hom/Ring.lean @@ -219,7 +219,7 @@ protected def id : α →+*o α := instance : Inhabited (α →+*o α) := ⟨OrderRingHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(OrderRingHom.id α) = id := rfl diff --git a/Mathlib/Algebra/Ring/Hom/Defs.lean b/Mathlib/Algebra/Ring/Hom/Defs.lean index 1f3bf480a9abf..6822a2bebdc3b 100644 --- a/Mathlib/Algebra/Ring/Hom/Defs.lean +++ b/Mathlib/Algebra/Ring/Hom/Defs.lean @@ -542,7 +542,7 @@ def id (α : Type*) [NonAssocSemiring α] : α →+* α where instance : Inhabited (α →+* α) := ⟨id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(RingHom.id α) = _root_.id := rfl @[simp] diff --git a/Mathlib/Algebra/Star/StarAlgHom.lean b/Mathlib/Algebra/Star/StarAlgHom.lean index c1f51d104dfa9..642263d386463 100644 --- a/Mathlib/Algebra/Star/StarAlgHom.lean +++ b/Mathlib/Algebra/Star/StarAlgHom.lean @@ -178,7 +178,7 @@ variable (R A) protected def id : A →⋆ₙₐ[R] A := { (1 : A →ₙₐ[R] A) with map_star' := fun _ => rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(NonUnitalStarAlgHom.id R A) = id := rfl @@ -413,7 +413,7 @@ variable (R A) protected def id : A →⋆ₐ[R] A := { AlgHom.id _ _ with map_star' := fun _ => rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(StarAlgHom.id R A) = id := rfl diff --git a/Mathlib/Algebra/Star/StarRingHom.lean b/Mathlib/Algebra/Star/StarRingHom.lean index 539564a9df289..8982b9a718e46 100644 --- a/Mathlib/Algebra/Star/StarRingHom.lean +++ b/Mathlib/Algebra/Star/StarRingHom.lean @@ -151,7 +151,7 @@ variable (A) protected def id : A →⋆ₙ+* A := { (1 : A →ₙ+* A) with map_star' := fun _ => rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(NonUnitalStarRingHom.id A) = id := rfl diff --git a/Mathlib/Analysis/Normed/Affine/Isometry.lean b/Mathlib/Analysis/Normed/Affine/Isometry.lean index e3fbc948e36bf..b4f0354b00717 100644 --- a/Mathlib/Analysis/Normed/Affine/Isometry.lean +++ b/Mathlib/Analysis/Normed/Affine/Isometry.lean @@ -180,7 +180,7 @@ theorem comp_continuous_iff {α : Type*} [TopologicalSpace α] {g : α → P} : def id : P →ᵃⁱ[𝕜] P := ⟨AffineMap.id 𝕜 P, fun _ => rfl⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(id : P →ᵃⁱ[𝕜] P) = _root_.id := rfl diff --git a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean index a008d3d807bd5..03481455bb86d 100644 --- a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean +++ b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean @@ -309,7 +309,7 @@ theorem comp_continuous_iff {α : Type*} [TopologicalSpace α] {g : α → E} : def id : E →ₗᵢ[R] E := ⟨LinearMap.id, fun _ => rfl⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ((id : E →ₗᵢ[R] E) : E → E) = _root_.id := rfl diff --git a/Mathlib/Data/PFun.lean b/Mathlib/Data/PFun.lean index 3c24f0c13cc70..55b7f96902e05 100644 --- a/Mathlib/Data/PFun.lean +++ b/Mathlib/Data/PFun.lean @@ -468,7 +468,7 @@ theorem mem_toSubtype_iff {p : β → Prop} {f : α → β} {a : α} {b : Subtyp protected def id (α : Type*) : α →. α := Part.some -@[simp] +@[simp, norm_cast] theorem coe_id (α : Type*) : ((id : α → α) : α →. α) = PFun.id α := rfl diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean index 4cb74369937e0..1c84a55d720cc 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean @@ -331,7 +331,7 @@ nonrec def id : P1 →ᵃ[k] P1 where map_vadd' _ _ := rfl /-- The identity affine map acts as the identity. -/ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(id k P1) = _root_.id := rfl diff --git a/Mathlib/Order/Heyting/Hom.lean b/Mathlib/Order/Heyting/Hom.lean index 6a1e4f16688ce..8cd7522500cce 100644 --- a/Mathlib/Order/Heyting/Hom.lean +++ b/Mathlib/Order/Heyting/Hom.lean @@ -282,7 +282,7 @@ protected def id : HeytingHom α α := toLatticeHom := LatticeHom.id _ map_himp' := fun _ _ => rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(HeytingHom.id α) = id := rfl @@ -388,7 +388,7 @@ protected def id : CoheytingHom α α := toLatticeHom := LatticeHom.id _ map_sdiff' := fun _ _ => rfl } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(CoheytingHom.id α) = id := rfl @@ -492,7 +492,7 @@ variable (α) protected def id : BiheytingHom α α := { HeytingHom.id _, CoheytingHom.id _ with toLatticeHom := LatticeHom.id _ } -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(BiheytingHom.id α) = id := rfl diff --git a/Mathlib/Order/Hom/Bounded.lean b/Mathlib/Order/Hom/Bounded.lean index feb386498fb37..c1cca17f660b5 100644 --- a/Mathlib/Order/Hom/Bounded.lean +++ b/Mathlib/Order/Hom/Bounded.lean @@ -227,7 +227,7 @@ variable (α) protected def id : TopHom α α := ⟨id, rfl⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(TopHom.id α) = id := rfl @@ -400,7 +400,7 @@ variable (α) protected def id : BotHom α α := ⟨id, rfl⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(BotHom.id α) = id := rfl @@ -578,7 +578,7 @@ protected def id : BoundedOrderHom α α := instance : Inhabited (BoundedOrderHom α α) := ⟨BoundedOrderHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(BoundedOrderHom.id α) = id := rfl diff --git a/Mathlib/Order/Hom/CompleteLattice.lean b/Mathlib/Order/Hom/CompleteLattice.lean index 125753699728c..93db1da8448d5 100644 --- a/Mathlib/Order/Hom/CompleteLattice.lean +++ b/Mathlib/Order/Hom/CompleteLattice.lean @@ -271,7 +271,7 @@ protected def id : sSupHom α α := instance : Inhabited (sSupHom α α) := ⟨sSupHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(sSupHom.id α) = id := rfl @@ -392,7 +392,7 @@ protected def id : sInfHom α α := instance : Inhabited (sInfHom α α) := ⟨sInfHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(sInfHom.id α) = id := rfl @@ -519,7 +519,7 @@ protected def id : FrameHom α α := instance : Inhabited (FrameHom α α) := ⟨FrameHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(FrameHom.id α) = id := rfl @@ -626,7 +626,7 @@ protected def id : CompleteLatticeHom α α := instance : Inhabited (CompleteLatticeHom α α) := ⟨CompleteLatticeHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(CompleteLatticeHom.id α) = id := rfl diff --git a/Mathlib/Order/Hom/Lattice.lean b/Mathlib/Order/Hom/Lattice.lean index 3a2945e4b903f..8d090e9e4b22a 100644 --- a/Mathlib/Order/Hom/Lattice.lean +++ b/Mathlib/Order/Hom/Lattice.lean @@ -366,7 +366,7 @@ protected def id : SupHom α α := instance : Inhabited (SupHom α α) := ⟨SupHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(SupHom.id α) = id := rfl @@ -542,7 +542,7 @@ protected def id : InfHom α α := instance : Inhabited (InfHom α α) := ⟨InfHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(InfHom.id α) = id := rfl @@ -727,7 +727,7 @@ protected def id : SupBotHom α α := instance : Inhabited (SupBotHom α α) := ⟨SupBotHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(SupBotHom.id α) = id := rfl @@ -878,7 +878,7 @@ protected def id : InfTopHom α α := instance : Inhabited (InfTopHom α α) := ⟨InfTopHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(InfTopHom.id α) = id := rfl @@ -1023,7 +1023,7 @@ protected def id : LatticeHom α α where instance : Inhabited (LatticeHom α α) := ⟨LatticeHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(LatticeHom.id α) = id := rfl @@ -1204,7 +1204,7 @@ protected def id : BoundedLatticeHom α α := instance : Inhabited (BoundedLatticeHom α α) := ⟨BoundedLatticeHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(BoundedLatticeHom.id α) = id := rfl diff --git a/Mathlib/RingTheory/Bialgebra/Hom.lean b/Mathlib/RingTheory/Bialgebra/Hom.lean index bbb6a66995f90..b192a405646ac 100644 --- a/Mathlib/RingTheory/Bialgebra/Hom.lean +++ b/Mathlib/RingTheory/Bialgebra/Hom.lean @@ -224,7 +224,7 @@ variable (R A) variable {R A} -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(BialgHom.id R A) = id := rfl diff --git a/Mathlib/RingTheory/Coalgebra/Hom.lean b/Mathlib/RingTheory/Coalgebra/Hom.lean index 2c15ce54d3b1a..ddc39d6487506 100644 --- a/Mathlib/RingTheory/Coalgebra/Hom.lean +++ b/Mathlib/RingTheory/Coalgebra/Hom.lean @@ -200,7 +200,7 @@ variable (R A) variable {R A} -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(CoalgHom.id R A) = id := rfl diff --git a/Mathlib/Topology/Bornology/Hom.lean b/Mathlib/Topology/Bornology/Hom.lean index fb444353548de..53cc8172f36ed 100644 --- a/Mathlib/Topology/Bornology/Hom.lean +++ b/Mathlib/Topology/Bornology/Hom.lean @@ -123,7 +123,7 @@ protected def id : LocallyBoundedMap α α := instance : Inhabited (LocallyBoundedMap α α) := ⟨LocallyBoundedMap.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(LocallyBoundedMap.id α) = id := rfl diff --git a/Mathlib/Topology/ContinuousMap/Basic.lean b/Mathlib/Topology/ContinuousMap/Basic.lean index eb8f143e4e116..1d977a2f4cef9 100644 --- a/Mathlib/Topology/ContinuousMap/Basic.lean +++ b/Mathlib/Topology/ContinuousMap/Basic.lean @@ -71,7 +71,7 @@ variable (α) protected def id : C(α, α) where toFun := id -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(ContinuousMap.id α) = id := rfl diff --git a/Mathlib/Topology/ContinuousMap/CocompactMap.lean b/Mathlib/Topology/ContinuousMap/CocompactMap.lean index d5662c0299843..6784f1c801fed 100644 --- a/Mathlib/Topology/ContinuousMap/CocompactMap.lean +++ b/Mathlib/Topology/ContinuousMap/CocompactMap.lean @@ -121,7 +121,7 @@ variable (α) protected def id : CocompactMap α α := ⟨ContinuousMap.id _, tendsto_id⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(CocompactMap.id α) = id := rfl diff --git a/Mathlib/Topology/Hom/Open.lean b/Mathlib/Topology/Hom/Open.lean index 5daac366a7826..172c3803ea904 100644 --- a/Mathlib/Topology/Hom/Open.lean +++ b/Mathlib/Topology/Hom/Open.lean @@ -101,7 +101,7 @@ protected def id : α →CO α := instance : Inhabited (α →CO α) := ⟨ContinuousOpenMap.id _⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(ContinuousOpenMap.id α) = id := rfl diff --git a/Mathlib/Topology/Order/Hom/Basic.lean b/Mathlib/Topology/Order/Hom/Basic.lean index 2f4067dad99ae..388b05446c6d6 100644 --- a/Mathlib/Topology/Order/Hom/Basic.lean +++ b/Mathlib/Topology/Order/Hom/Basic.lean @@ -132,7 +132,7 @@ protected def id : α →Co α := instance : Inhabited (α →Co α) := ⟨ContinuousOrderHom.id _⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(ContinuousOrderHom.id α) = id := rfl diff --git a/Mathlib/Topology/Order/Hom/Esakia.lean b/Mathlib/Topology/Order/Hom/Esakia.lean index 853342e3d71d4..164d5ca4a1510 100644 --- a/Mathlib/Topology/Order/Hom/Esakia.lean +++ b/Mathlib/Topology/Order/Hom/Esakia.lean @@ -146,10 +146,10 @@ protected def id : PseudoEpimorphism α α := instance : Inhabited (PseudoEpimorphism α α) := ⟨PseudoEpimorphism.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(PseudoEpimorphism.id α) = id := rfl -@[simp] +@[simp, norm_cast] theorem coe_id_orderHom : (PseudoEpimorphism.id α : α →o α) = OrderHom.id := rfl variable {α} @@ -254,10 +254,10 @@ protected def id : EsakiaHom α α := instance : Inhabited (EsakiaHom α α) := ⟨EsakiaHom.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(EsakiaHom.id α) = id := rfl -@[simp] +@[simp, norm_cast] theorem coe_id_pseudoEpimorphism : (EsakiaHom.id α : PseudoEpimorphism α α) = PseudoEpimorphism.id α := rfl @@ -266,7 +266,7 @@ variable {α} @[simp] theorem id_apply (a : α) : EsakiaHom.id α a = a := rfl -@[simp] +@[simp, norm_cast] theorem coe_id_continuousOrderHom : (EsakiaHom.id α : α →Co α) = ContinuousOrderHom.id α := rfl /-- Composition of `EsakiaHom`s as an `EsakiaHom`. -/ diff --git a/Mathlib/Topology/Spectral/Hom.lean b/Mathlib/Topology/Spectral/Hom.lean index 1dd7d97f1c480..b812d4c3457b0 100644 --- a/Mathlib/Topology/Spectral/Hom.lean +++ b/Mathlib/Topology/Spectral/Hom.lean @@ -137,7 +137,7 @@ protected def id : SpectralMap α α := instance : Inhabited (SpectralMap α α) := ⟨SpectralMap.id α⟩ -@[simp] +@[simp, norm_cast] theorem coe_id : ⇑(SpectralMap.id α) = id := rfl From 88927defbedfccde92d9795bdecb8da5d0129f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 18:19:04 +0000 Subject: [PATCH 138/681] =?UTF-8?q?feat:=20`a=20=E2=88=88=20s=20^=20n`=20i?= =?UTF-8?q?ff=20there=20exists=20a=20sequence=20`f`=20of=20`n`=20elements?= =?UTF-8?q?=20of=20`s`=20such=20that=20`=E2=88=8F=20i,=20f=20i=20=3D=20a`?= =?UTF-8?q?=20(#20580)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean b/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean index c4675e6c8534d..03932943943de 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean @@ -70,6 +70,11 @@ theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) : exact ⟨g i, hg (is.mem_insert_self _), is.prod g, ⟨⟨g, fun hi ↦ hg (Finset.mem_insert_of_mem hi), rfl⟩, rfl⟩⟩ +@[to_additive] +lemma mem_pow_iff_prod {n : ℕ} {s : Set α} {a : α} : + a ∈ s ^ n ↔ ∃ f : Fin n → α, (∀ i, f i ∈ s) ∧ ∏ i, f i = a := by + simpa using mem_finset_prod (t := .univ) (f := fun _ : Fin n ↦ s) _ + /-- A version of `Set.mem_finset_prod` with a simpler RHS for products over a Fintype. -/ @[to_additive " A version of `Set.mem_finset_sum` with a simpler RHS for sums over a Fintype. "] theorem mem_fintype_prod [Fintype ι] (f : ι → Set α) (a : α) : From 93a78ce08172d64f34b00d48cee6c0cc12c949ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 18:19:06 +0000 Subject: [PATCH 139/681] feat: `Submodule.restrictScalars` commutes with `pow` (#20581) From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang --- Mathlib/Algebra/Algebra/Operations.lean | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index 2fb899680781b..a907db6ce7734 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -67,6 +67,7 @@ section Module variable {R : Type u} [Semiring R] {A : Type v} [Semiring A] [Module R A] +-- TODO: Why is this in a file about `Algebra`? /-- `1 : Submodule R A` is the submodule `R ∙ 1` of A. TODO: potentially change this back to `LinearMap.range (Algebra.linearMap R A)` once a version of `Algebra` without the `commutes'` field is introduced. @@ -324,6 +325,15 @@ theorem pow_subset_pow {n : ℕ} : (↑M : Set A) ^ n ⊆ ↑(M ^ n : Submodule theorem pow_mem_pow {x : A} (hx : x ∈ M) (n : ℕ) : x ^ n ∈ M ^ n := pow_subset_pow _ <| Set.pow_mem_pow hx +lemma restrictScalars_pow {A B C : Type*} [Semiring A] [Semiring B] + [Semiring C] [SMul A B] [Module A C] [Module B C] + [IsScalarTower A C C] [IsScalarTower B C C] [IsScalarTower A B C] + {I : Submodule B C} : + ∀ {n : ℕ}, (hn : n ≠ 0) → (I ^ n).restrictScalars A = I.restrictScalars A ^ n + | 1, _ => by simp [Submodule.pow_one] + | n + 2, _ => by + simp [Submodule.pow_succ (n := n + 1), restrictScalars_mul, restrictScalars_pow n.succ_ne_zero] + end Module variable {ι : Sort uι} From 111b4c0324c6f04beed09b8f01ef126b48c805c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 18:59:50 +0000 Subject: [PATCH 140/681] feat: product of subalgebras (#20202) From FLT Co-authored-by: Andrew Yang --- Mathlib.lean | 1 + Mathlib/Algebra/Algebra/Subalgebra/Pi.lean | 44 ++++++++++++++++++++++ Mathlib/Algebra/Group/Subgroup/Defs.lean | 6 +-- Mathlib/Algebra/Module/Submodule/Defs.lean | 2 + Mathlib/LinearAlgebra/Pi.lean | 8 ++-- 5 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 Mathlib/Algebra/Algebra/Subalgebra/Pi.lean diff --git a/Mathlib.lean b/Mathlib.lean index e4f2f45397583..c613c04977ec5 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -25,6 +25,7 @@ import Mathlib.Algebra.Algebra.Subalgebra.IsSimpleOrder import Mathlib.Algebra.Algebra.Subalgebra.MulOpposite import Mathlib.Algebra.Algebra.Subalgebra.Operations import Mathlib.Algebra.Algebra.Subalgebra.Order +import Mathlib.Algebra.Algebra.Subalgebra.Pi import Mathlib.Algebra.Algebra.Subalgebra.Pointwise import Mathlib.Algebra.Algebra.Subalgebra.Prod import Mathlib.Algebra.Algebra.Subalgebra.Rank diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Pi.lean b/Mathlib/Algebra/Algebra/Subalgebra/Pi.lean new file mode 100644 index 0000000000000..6d7a3a44802c2 --- /dev/null +++ b/Mathlib/Algebra/Algebra/Subalgebra/Pi.lean @@ -0,0 +1,44 @@ +/- +Copyright (c) 2024 Yaël Dillies, Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Andrew Yang +-/ +import Mathlib.Algebra.Algebra.Pi +import Mathlib.Algebra.Algebra.Subalgebra.Basic +import Mathlib.LinearAlgebra.Pi + +/-! +# Products of subalgebras + +In this file we define the product of subalgebras as a subalgebra of the product algebra. + +## Main definitions + + * `Subalgebra.pi`: the product of subalgebras. +-/ + +open Algebra + +namespace Subalgebra +variable {ι R : Type*} {S : ι → Type*} [CommSemiring R] [∀ i, Semiring (S i)] [∀ i, Algebra R (S i)] + {s : Set ι} {t t₁ t₂ : ∀ i, Subalgebra R (S i)} {x : ∀ i, S i} + +/-- The product of subalgebras as a subalgebra. -/ +@[simps coe toSubsemiring] +def pi (s : Set ι) (t : ∀ i, Subalgebra R (S i)) : Subalgebra R (Π i, S i) where + __ := Submodule.pi s fun i ↦ (t i).toSubmodule + mul_mem' hx hy i hi := (t i).mul_mem (hx i hi) (hy i hi) + algebraMap_mem' _ i _ := (t i).algebraMap_mem _ + +@[simp] lemma mem_pi : x ∈ pi s t ↔ ∀ i ∈ s, x i ∈ t i := .rfl + +open Subalgebra in +@[simp] lemma pi_toSubmodule : toSubmodule (pi s t) = .pi s fun i ↦ (t i).toSubmodule := rfl + +@[simp] +lemma pi_top (s : Set ι) : pi s (fun i ↦ (⊤ : Subalgebra R (S i))) = ⊤ := + SetLike.coe_injective <| Set.pi_univ _ + +@[gcongr] lemma pi_mono (h : ∀ i ∈ s, t₁ i ≤ t₂ i) : pi s t₁ ≤ pi s t₂ := Set.pi_mono h + +end Subalgebra diff --git a/Mathlib/Algebra/Group/Subgroup/Defs.lean b/Mathlib/Algebra/Group/Subgroup/Defs.lean index 9b08ce6457c62..2063e20c5c2ce 100644 --- a/Mathlib/Algebra/Group/Subgroup/Defs.lean +++ b/Mathlib/Algebra/Group/Subgroup/Defs.lean @@ -358,7 +358,7 @@ variable (H K : Subgroup G) /-- Copy of a subgroup with a new `carrier` equal to the old one. Useful to fix definitional equalities. -/ -@[to_additive +@[to_additive (attr := simps) "Copy of an additive subgroup with a new `carrier` equal to the old one. Useful to fix definitional equalities"] protected def copy (K : Subgroup G) (s : Set G) (hs : s = K) : Subgroup G where @@ -367,10 +367,6 @@ protected def copy (K : Subgroup G) (s : Set G) (hs : s = K) : Subgroup G where mul_mem' := hs.symm ▸ K.mul_mem' inv_mem' hx := by simpa [hs] using hx -- Porting note: `▸` didn't work here -@[to_additive (attr := simp)] -theorem coe_copy (K : Subgroup G) (s : Set G) (hs : s = ↑K) : (K.copy s hs : Set G) = s := - rfl - @[to_additive] theorem copy_eq (K : Subgroup G) (s : Set G) (hs : s = ↑K) : K.copy s hs = K := SetLike.coe_injective hs diff --git a/Mathlib/Algebra/Module/Submodule/Defs.lean b/Mathlib/Algebra/Module/Submodule/Defs.lean index 985489a5a1fbe..e97327b911fae 100644 --- a/Mathlib/Algebra/Module/Submodule/Defs.lean +++ b/Mathlib/Algebra/Module/Submodule/Defs.lean @@ -57,6 +57,8 @@ instance addSubmonoidClass : AddSubmonoidClass (Submodule R M) M where instance smulMemClass : SMulMemClass (Submodule R M) R M where smul_mem {s} c _ h := SubMulAction.smul_mem' s.toSubMulAction c h +initialize_simps_projections Submodule (carrier → coe, as_prefix coe) + @[simp] theorem mem_toAddSubmonoid (p : Submodule R M) (x : M) : x ∈ p.toAddSubmonoid ↔ x ∈ p := Iff.rfl diff --git a/Mathlib/LinearAlgebra/Pi.lean b/Mathlib/LinearAlgebra/Pi.lean index 62bc97d66935b..38d4beb411b38 100644 --- a/Mathlib/LinearAlgebra/Pi.lean +++ b/Mathlib/LinearAlgebra/Pi.lean @@ -326,22 +326,21 @@ open LinearMap /-- A version of `Set.pi` for submodules. Given an index set `I` and a family of submodules `p : (i : ι) → Submodule R (φ i)`, `pi I s` is the submodule of dependent functions `f : (i : ι) → φ i` such that `f i` belongs to `p a` whenever `i ∈ I`. -/ +@[simps] def pi (I : Set ι) (p : (i : ι) → Submodule R (φ i)) : Submodule R ((i : ι) → φ i) where carrier := Set.pi I fun i => p i zero_mem' i _ := (p i).zero_mem add_mem' {_ _} hx hy i hi := (p i).add_mem (hx i hi) (hy i hi) smul_mem' c _ hx i hi := (p i).smul_mem c (hx i hi) +attribute [norm_cast] coe_pi + variable {I : Set ι} {p q : (i : ι) → Submodule R (φ i)} {x : (i : ι) → φ i} @[simp] theorem mem_pi : x ∈ pi I p ↔ ∀ i ∈ I, x i ∈ p i := Iff.rfl -@[simp, norm_cast] -theorem coe_pi : (pi I p : Set ((i : ι) → φ i)) = Set.pi I fun i => p i := - rfl - @[simp] theorem pi_empty (p : (i : ι) → Submodule R (φ i)) : pi ∅ p = ⊤ := SetLike.coe_injective <| Set.empty_pi _ @@ -350,6 +349,7 @@ theorem pi_empty (p : (i : ι) → Submodule R (φ i)) : pi ∅ p = ⊤ := theorem pi_top (s : Set ι) : (pi s fun i : ι => (⊤ : Submodule R (φ i))) = ⊤ := SetLike.coe_injective <| Set.pi_univ _ +@[gcongr] theorem pi_mono {s : Set ι} (h : ∀ i ∈ s, p i ≤ q i) : pi s p ≤ pi s q := Set.pi_mono h From a5910d1db211ad5f71f1ce7e96c652a07b82a6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 18:59:51 +0000 Subject: [PATCH 141/681] =?UTF-8?q?feat:=20`s=20\=20t=20=E2=88=A9=20u=20?= =?UTF-8?q?=3D=20(s=20=E2=88=A9=20u)=20\=20t`=20(#20298)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From GrowthInGroups (LeanCamCombi) --- Mathlib/Data/Finset/Lattice/Basic.lean | 1 - Mathlib/Data/Finset/SDiff.lean | 14 ++++++++++---- Mathlib/Data/Set/Basic.lean | 13 +++++++++---- Mathlib/Order/BooleanAlgebra.lean | 13 ++++++++++--- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/Mathlib/Data/Finset/Lattice/Basic.lean b/Mathlib/Data/Finset/Lattice/Basic.lean index 79aeaeff8285a..f3cc10838069e 100644 --- a/Mathlib/Data/Finset/Lattice/Basic.lean +++ b/Mathlib/Data/Finset/Lattice/Basic.lean @@ -30,7 +30,6 @@ In Lean, we use lattice notation to talk about things involving unions and inter * `Finset.instUnionFinset`: see "The lattice structure on subsets of finsets" * `Finset.instInterFinset`: see "The lattice structure on subsets of finsets" -* `Finset.instSDiffFinset`: Defines the set difference `s \ t` for finsets `s` and `t`. ## Tags diff --git a/Mathlib/Data/Finset/SDiff.lean b/Mathlib/Data/Finset/SDiff.lean index 1b6228553e58b..76d887b4bdc7a 100644 --- a/Mathlib/Data/Finset/SDiff.lean +++ b/Mathlib/Data/Finset/SDiff.lean @@ -9,7 +9,8 @@ import Mathlib.Data.Finset.Lattice.Lemmas # Difference of finite sets ## Main declarations -* `Finset.instSDiffFinset`: Defines the set difference `s \ t` for finsets `s` and `t`. + +* `Finset.instSDiff`: Defines the set difference `s \ t` for finsets `s` and `t`. * `Finset.instGeneralizedBooleanAlgebra`: Finsets almost have a boolean algebra structure ## Tags @@ -46,7 +47,7 @@ section Sdiff variable [DecidableEq α] {s t u v : Finset α} {a b : α} /-- `s \ t` is the set consisting of the elements of `s` that are not in `t`. -/ -instance : SDiff (Finset α) := +instance instSDiff : SDiff (Finset α) := ⟨fun s₁ s₂ => ⟨s₁.1 - s₂.1, nodup_of_le (Multiset.sub_le_self ..) s₁.2⟩⟩ @[simp] @@ -81,8 +82,13 @@ theorem union_sdiff_of_subset (h : s ⊆ t) : s ∪ t \ s = t := theorem sdiff_union_of_subset {s₁ s₂ : Finset α} (h : s₁ ⊆ s₂) : s₂ \ s₁ ∪ s₁ = s₂ := (union_comm _ _).trans (union_sdiff_of_subset h) -lemma inter_sdiff_assoc (s t u : Finset α) : (s ∩ t) \ u = s ∩ (t \ u) := by - ext x; simp [and_assoc] +/-- See also `Finset.sdiff_inter_right_comm`. -/ +lemma inter_sdiff_assoc (s t u : Finset α) : (s ∩ t) \ u = s ∩ (t \ u) := inf_sdiff_assoc .. + +/-- See also `Finset.inter_sdiff_assoc`. -/ +lemma sdiff_inter_right_comm (s t u : Finset α) : s \ t ∩ u = (s ∩ u) \ t := sdiff_inf_right_comm .. + +lemma inter_sdiff_left_comm (s t u : Finset α) : s ∩ (t \ u) = t ∩ (s \ u) := inf_sdiff_left_comm .. @[deprecated inter_sdiff_assoc (since := "2024-05-01")] theorem inter_sdiff (s t u : Finset α) : s ∩ (t \ u) = (s ∩ t) \ u := (inter_sdiff_assoc _ _ _).symm diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 0a7d5df2df1b0..4b7c21083afe3 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -1266,6 +1266,14 @@ lemma disjoint_sdiff_right : Disjoint s (t \ s) := disjoint_sdiff_self_right theorem disjoint_sdiff_inter : Disjoint (s \ t) (s ∩ t) := disjoint_of_subset_right inter_subset_right disjoint_sdiff_left +/-- See also `Set.sdiff_inter_right_comm`. -/ +lemma inter_diff_assoc (a b c : Set α) : (a ∩ b) \ c = a ∩ (b \ c) := inf_sdiff_assoc .. + +/-- See also `Set.inter_diff_assoc`. -/ +lemma sdiff_inter_right_comm (s t u : Set α) : s \ t ∩ u = (s ∩ u) \ t := sdiff_inf_right_comm .. + +lemma inter_sdiff_left_comm (s t u : Set α) : s ∩ (t \ u) = t ∩ (s \ u) := inf_sdiff_left_comm .. + theorem diff_union_diff_cancel (hts : t ⊆ s) (hut : u ⊆ t) : s \ t ∪ t \ u = s \ u := sdiff_sup_sdiff_cancel hts hut @@ -1289,7 +1297,7 @@ lemma ssubset_iff_sdiff_singleton : s ⊂ t ↔ ∃ a ∈ t, s ⊆ t \ {a} := by theorem inter_diff_distrib_left (s t u : Set α) : s ∩ (t \ u) = (s ∩ t) \ (s ∩ u) := inf_sdiff_distrib_left _ _ _ -theorem inter_diff_distrib_right (s t u : Set α) : s \ t ∩ u = (s ∩ u) \ (t ∩ u) := +theorem inter_diff_distrib_right (s t u : Set α) : (s \ t) ∩ u = (s ∩ u) \ (t ∩ u) := inf_sdiff_distrib_right _ _ _ theorem disjoint_of_subset_iff_left_eq_empty (h : s ⊆ t) : @@ -1469,9 +1477,6 @@ theorem union_diff_right {s t : Set α} : (s ∪ t) \ t = s \ t := theorem union_diff_distrib {s t u : Set α} : (s ∪ t) \ u = s \ u ∪ t \ u := sup_sdiff -theorem inter_diff_assoc (a b c : Set α) : (a ∩ b) \ c = a ∩ (b \ c) := - inf_sdiff_assoc - @[simp] theorem inter_diff_self (a b : Set α) : a ∩ (b \ a) = ∅ := inf_sdiff_self_right diff --git a/Mathlib/Order/BooleanAlgebra.lean b/Mathlib/Order/BooleanAlgebra.lean index 72077474d6a28..ea8924624d601 100644 --- a/Mathlib/Order/BooleanAlgebra.lean +++ b/Mathlib/Order/BooleanAlgebra.lean @@ -407,7 +407,8 @@ theorem inf_sdiff : (x ⊓ y) \ z = x \ z ⊓ y \ z := x ⊓ y ⊓ z ⊓ (x \ z ⊓ y \ z) = x ⊓ y ⊓ (z ⊓ x \ z) ⊓ y \ z := by ac_rfl _ = ⊥ := by rw [inf_sdiff_self_right, inf_bot_eq, bot_inf_eq]) -theorem inf_sdiff_assoc : (x ⊓ y) \ z = x ⊓ y \ z := +/-- See also `sdiff_inf_right_comm`. -/ +theorem inf_sdiff_assoc (x y z : α) : (x ⊓ y) \ z = x ⊓ y \ z := sdiff_unique (calc x ⊓ y ⊓ z ⊔ x ⊓ y \ z = x ⊓ (y ⊓ z) ⊔ x ⊓ y \ z := by rw [inf_assoc] @@ -417,9 +418,15 @@ theorem inf_sdiff_assoc : (x ⊓ y) \ z = x ⊓ y \ z := x ⊓ y ⊓ z ⊓ (x ⊓ y \ z) = x ⊓ x ⊓ (y ⊓ z ⊓ y \ z) := by ac_rfl _ = ⊥ := by rw [inf_inf_sdiff, inf_bot_eq]) -theorem inf_sdiff_right_comm : x \ z ⊓ y = (x ⊓ y) \ z := by +/-- See also `inf_sdiff_assoc`. -/ +theorem sdiff_inf_right_comm (x y z : α) : x \ z ⊓ y = (x ⊓ y) \ z := by rw [inf_comm x, inf_comm, inf_sdiff_assoc] +lemma inf_sdiff_left_comm (a b c : α) : a ⊓ (b \ c) = b ⊓ (a \ c) := by + simp_rw [← inf_sdiff_assoc, inf_comm] + +@[deprecated (since := "2025-01-08")] alias inf_sdiff_right_comm := sdiff_inf_right_comm + theorem inf_sdiff_distrib_left (a b c : α) : a ⊓ b \ c = (a ⊓ b) \ (a ⊓ c) := by rw [sdiff_inf, sdiff_eq_bot_iff.2 inf_le_left, bot_sup_eq, inf_sdiff_assoc] @@ -427,7 +434,7 @@ theorem inf_sdiff_distrib_right (a b c : α) : a \ b ⊓ c = (a ⊓ c) \ (b ⊓ simp_rw [inf_comm _ c, inf_sdiff_distrib_left] theorem disjoint_sdiff_comm : Disjoint (x \ z) y ↔ Disjoint x (y \ z) := by - simp_rw [disjoint_iff, inf_sdiff_right_comm, inf_sdiff_assoc] + simp_rw [disjoint_iff, sdiff_inf_right_comm, inf_sdiff_assoc] theorem sup_eq_sdiff_sup_sdiff_sup_inf : x ⊔ y = x \ y ⊔ y \ x ⊔ x ⊓ y := Eq.symm <| From f8adbb936816ada86f2754a0d99f6d7a858a8c71 Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Fri, 10 Jan 2025 18:59:53 +0000 Subject: [PATCH 142/681] chore(TensorProduct): universe polymorphism in EquationalCriterion (#20452) Remove `exists_factorization_of_apply_eq_zero` as it's a special case of `exists_factorization_of_apply_eq_zero_of_free`. Remove one statement from the TFAE, but still keep the forward direction ` `exists_factorization_of_apply_eq_zero_of_free` and make it fully universe polymorphic. --- .../Algebra/Module/FinitePresentation.lean | 39 ++- .../TensorProduct/Vanishing.lean | 76 +++-- .../RingTheory/Flat/EquationalCriterion.lean | 265 +++++++++--------- 3 files changed, 203 insertions(+), 177 deletions(-) diff --git a/Mathlib/Algebra/Module/FinitePresentation.lean b/Mathlib/Algebra/Module/FinitePresentation.lean index f956657b81585..4c43da972ed6a 100644 --- a/Mathlib/Algebra/Module/FinitePresentation.lean +++ b/Mathlib/Algebra/Module/FinitePresentation.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ +import Mathlib.Algebra.Small.Module import Mathlib.LinearAlgebra.FreeModule.Finite.Basic import Mathlib.LinearAlgebra.TensorProduct.RightExactness import Mathlib.LinearAlgebra.Isomorphisms @@ -73,21 +74,33 @@ end Semiring section Ring -variable (R M N) [Ring R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] +section + +universe u v +variable (R : Type u) (M : Type*) [Ring R] [AddCommGroup M] [Module R M] + +theorem Module.FinitePresentation.exists_fin [fp : Module.FinitePresentation R M] : + ∃ (n : ℕ) (K : Submodule R (Fin n → R)) (_ : M ≃ₗ[R] (Fin n → R) ⧸ K), K.FG := by + have ⟨ι, ⟨hι₁, hι₂⟩⟩ := fp + refine ⟨_, LinearMap.ker (linearCombination R Subtype.val ∘ₗ + (lcongr ι.equivFin (.refl ..) ≪≫ₗ linearEquivFunOnFinite R R _).symm.toLinearMap), + (LinearMap.quotKerEquivOfSurjective _ <| LinearMap.range_eq_top.mp ?_).symm, ?_⟩ + · simpa [range_linearCombination] using hι₁ + · simpa [LinearMap.ker_comp, Submodule.comap_equiv_eq_map_symm] using hι₂.map _ -universe u in -variable (R M : Type u) [Ring R] [AddCommGroup M] [Module R M] in /-- A finitely presented module is isomorphic to the quotient of a finite free module by a finitely generated submodule. -/ -theorem Module.FinitePresentation.equiv_quotient [fp : Module.FinitePresentation R M] : - ∃ (L : Type u) (_ : AddCommGroup L) (_ : Module R L) (K : Submodule R L) (_ : M ≃ₗ[R] L ⧸ K), - Module.Free R L ∧ Module.Finite R L ∧ K.FG := by - obtain ⟨ι, ⟨hι₁, hι₂⟩⟩ := fp - use ι →₀ R, inferInstance, inferInstance - use LinearMap.ker (Finsupp.linearCombination R Subtype.val) - refine ⟨(LinearMap.quotKerEquivOfSurjective _ ?_).symm, inferInstance, inferInstance, hι₂⟩ - apply LinearMap.range_eq_top.mp - simpa only [Finsupp.range_linearCombination, Subtype.range_coe_subtype, Finset.setOf_mem] +theorem Module.FinitePresentation.equiv_quotient [Module.FinitePresentation R M] [Small.{v} R] : + ∃ (L : Type v) (_ : AddCommGroup L) (_ : Module R L) (K : Submodule R L) + (_ : M ≃ₗ[R] L ⧸ K), Module.Free R L ∧ Module.Finite R L ∧ K.FG := + have ⟨_n, _K, e, fg⟩ := Module.FinitePresentation.exists_fin R M + let es := linearEquivShrink + ⟨_, inferInstance, inferInstance, _, e ≪≫ₗ Submodule.Quotient.equiv _ _ (es ..) rfl, + .of_equiv (es ..), .equiv (es ..), fg.map (es ..).toLinearMap⟩ + +end + +variable (R M N) [Ring R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] -- Ideally this should be an instance but it makes mathlib much slower. lemma Module.finitePresentation_of_finite [IsNoetherianRing R] [h : Module.Finite R M] : @@ -446,7 +459,7 @@ lemma Module.FinitePresentation.exists_lift_equiv_of_isLocalizedModule inv_one, Units.val_one, LinearMap.one_apply, this] instance Module.FinitePresentation.isLocalizedModule_map [Module.FinitePresentation R M] : - IsLocalizedModule S (IsLocalizedModule.map S f g) := by + IsLocalizedModule S (IsLocalizedModule.map S f g) := by constructor · intro s rw [Module.End_isUnit_iff] diff --git a/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean b/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean index 846946cbd7deb..7de88075ca024 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2024 Mitchell Lee. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mitchell Lee +Authors: Mitchell Lee, Junyan Xu -/ import Mathlib.LinearAlgebra.TensorProduct.RightExactness import Mathlib.LinearAlgebra.TensorProduct.Finiteness @@ -16,11 +16,11 @@ expression vanishes. Let us say that an expression $\sum_{i \in \iota} m_i \otimes n_i$ in $M \otimes N$ *vanishes trivially* (`TensorProduct.VanishesTrivially`) if there exist a finite index type -$\kappa$, elements $(y_j)_{j \in \kappa}$ of $N$, and elements +$\kappa$ = `Fin k`, elements $(y_j)_{j \in \kappa}$ of $N$, and elements $(a_{ij})_{i \in \iota, j \in \kappa}$ of $R$ such that for all $i$, $$n_i = \sum_j a_{ij} y_j$$ and for all $j$, -$$\sum_{i} a_{ij} m_i = 0.$$ +$$\sum_i a_{ij} m_i = 0.$$ (The terminology "trivial" comes from [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK).) It is not difficult to show (`TensorProduct.sum_tmul_eq_zero_of_vanishesTrivially`) that if $\sum_i m_i \otimes n_i$ vanishes trivially, then it vanishes; that is, @@ -51,36 +51,49 @@ is injective for every submodule $M' \subseteq M$. ## TODO * Prove the same theorems with $M$ and $N$ swapped. -* Prove the same theorems with universe polymorphism. -/ -universe u - -variable (R : Type u) [CommRing R] -variable {M : Type u} [AddCommGroup M] [Module R M] -variable {N : Type u} [AddCommGroup N] [Module R N] +variable (R : Type*) [CommRing R] +variable {M : Type*} [AddCommGroup M] [Module R M] +variable {N : Type*} [AddCommGroup N] [Module R N] open DirectSum LinearMap Function Submodule Finsupp namespace TensorProduct -variable {ι : Type u} [Fintype ι] {m : ι → M} {n : ι → N} +variable {ι : Type*} [Fintype ι] {m : ι → M} {n : ι → N} variable (m n) in /-- An expression $\sum_i m_i \otimes n_i$ in $M \otimes N$ -*vanishes trivially* if there exist a finite index type $\kappa$, +*vanishes trivially* if there exist a finite index type $\kappa$ = `Fin k`, elements $(y_j)_{j \in \kappa}$ of $N$, and elements $(a_{ij})_{i \in \iota, j \in \kappa}$ of $R$ such that for all $i$, $$n_i = \sum_j a_{ij} y_j$$ and for all $j$, -$$\sum_{i} a_{ij} m_i = 0.$$ +$$\sum_i a_{ij} m_i = 0.$$ Note that this condition is not symmetric in $M$ and $N$. (The terminology "trivial" comes from [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK).)-/ abbrev VanishesTrivially : Prop := - ∃ (κ : Type u) (_ : Fintype κ) (a : ι → κ → R) (y : κ → N), + ∃ (k : ℕ) (a : ι → Fin k → R) (y : Fin k → N), (∀ i, n i = ∑ j, a i j • y j) ∧ ∀ j, ∑ i, a i j • m i = 0 +variable {R} + +theorem VanishesTrivially.of_fintype {κ} [Fintype κ] (a : ι → κ → R) (y : κ → N) + (hay : ∀ i, n i = ∑ j, a i j • y j) (ham : ∀ j, ∑ i, a i j • m i = 0) : + VanishesTrivially R m n := + have e := (Fintype.equivFin κ).symm + ⟨Fintype.card κ, (a · ∘ e), y ∘ e, by simpa only [← e.sum_comp] using hay, by + rwa [← e.forall_congr_right] at ham⟩ + +theorem _root_.Equiv.vanishesTrivially_comp {κ} [Fintype κ] (e : κ ≃ ι) : + VanishesTrivially R (m ∘ e) (n ∘ e) ↔ VanishesTrivially R m n := by + simp [VanishesTrivially, ← e.forall_congr_right, + ← (e.arrowCongr (.refl _)).exists_congr_right, ← e.sum_comp] + +variable (R) + /-- **Equational criterion for vanishing** [A. Altman and S. Kleiman, *A term of commutative algebra* (Lemma 8.16)][altman2021term], backward direction. @@ -89,7 +102,7 @@ If the expression $\sum_i m_i \otimes n_i$ vanishes trivially, then it vanishes. That is, $\sum_i m_i \otimes n_i = 0$. -/ theorem sum_tmul_eq_zero_of_vanishesTrivially (hmn : VanishesTrivially R m n) : ∑ i, m i ⊗ₜ n i = (0 : M ⊗[R] N) := by - obtain ⟨κ, _, a, y, h₁, h₂⟩ := hmn + obtain ⟨k, a, y, h₁, h₂⟩ := hmn simp_rw [h₁, tmul_sum, tmul_smul] rw [Finset.sum_comm] simp_rw [← tmul_smul, ← smul_tmul, ← sum_tmul, h₂, zero_tmul, Finset.sum_const_zero] @@ -129,17 +142,14 @@ theorem vanishesTrivially_of_sum_tmul_eq_zero (hm : Submodule.span R (Set.range Write it as a finite sum of pure tensors. -/ obtain ⟨kn, hkn⟩ := en_mem_range obtain ⟨ma, rfl : kn = ∑ kj ∈ ma, kj.1 ⊗ₜ[R] kj.2⟩ := exists_finset kn - use ↑↑ma, FinsetCoe.fintype ma /- Let $\sum_j k_j \otimes y_j$ be the sum obtained in the previous step. In order to show that $\sum_i m_i \otimes n_i$ vanishes trivially, it suffices to prove that there exist $(a_{ij})_{i, j}$ such that for all $i$, $$n_i = \sum_j a_{ij} y_j$$ and for all $j$, - $$\sum_{i} a_{ij} m_i = 0.$$ + $$\sum_i a_{ij} m_i = 0.$$ For this, take $a_{ij}$ to be the coefficient of $e_i$ in $k_j$. -/ - use fun i ⟨⟨kj, _⟩, _⟩ ↦ (kj : ι →₀ R) i - use fun ⟨⟨_, yj⟩, _⟩ ↦ yj - constructor + refine .of_fintype (κ := ma) (fun i ⟨⟨kj, _⟩, _⟩ ↦ (kj : ι →₀ R) i) (fun ⟨⟨_, yj⟩, _⟩ ↦ yj) ?_ ?_ · intro i classical apply_fun finsuppScalarLeft R N ι at hkn @@ -211,7 +221,7 @@ theorem vanishesTrivially_iff_sum_tmul_eq_zero_of_rTensor_injective Assume that every expression $\sum_i m_i \otimes n_i$ which vanishes also vanishes trivially. Then, for every submodule $M' \subseteq M$, the map $M' \otimes N \to M \otimes N$ is injective. -/ theorem rTensor_injective_of_forall_vanishesTrivially - (hMN : ∀ {ι : Type u} [Fintype ι] {m : ι → M} {n : ι → N}, + (hMN : ∀ {l : ℕ} {m : Fin l → M} {n : Fin l → N}, ∑ i, m i ⊗ₜ n i = (0 : M ⊗[R] N) → VanishesTrivially R m n) (M' : Submodule R M) : Injective (rTensor N M'.subtype) := by apply (injective_iff_map_eq_zero _).mpr @@ -220,9 +230,12 @@ theorem rTensor_injective_of_forall_vanishesTrivially rw [← Finset.sum_attach] apply sum_tmul_eq_zero_of_vanishesTrivially simp only [map_sum, rTensor_tmul, coe_subtype] at hx - have := hMN ((Finset.sum_attach s _).trans hx) + have e := (Fintype.equivFin s).symm + rw [← Finset.sum_coe_sort, ← e.sum_comp] at hx + have := hMN hx + rw [← e.vanishesTrivially_comp] unfold VanishesTrivially at this ⊢ - convert this with κ _ a y j + convert this symm convert (injective_iff_map_eq_zero' _).mp (injective_subtype M') _ simp @@ -230,35 +243,40 @@ theorem rTensor_injective_of_forall_vanishesTrivially /-- Every expression $\sum_i m_i \otimes n_i$ which vanishes also vanishes trivially if and only if for every submodule $M' \subseteq M$, the map $M' \otimes N \to M \otimes N$ is injective. -/ theorem forall_vanishesTrivially_iff_forall_rTensor_injective : - (∀ {ι : Type u} [Fintype ι] {m : ι → M} {n : ι → N}, + (∀ {l : ℕ} {m : Fin l → M} {n : Fin l → N}, ∑ i, m i ⊗ₜ n i = (0 : M ⊗[R] N) → VanishesTrivially R m n) ↔ ∀ M' : Submodule R M, Injective (rTensor N M'.subtype) := by constructor · intro h exact rTensor_injective_of_forall_vanishesTrivially R h - · intro h ι _ m n hmn + · intro h k m n hmn exact vanishesTrivially_of_sum_tmul_eq_zero_of_rTensor_injective R (h _) hmn /-- Every expression $\sum_i m_i \otimes n_i$ which vanishes also vanishes trivially if and only if for every finitely generated submodule $M' \subseteq M$, the map $M' \otimes N \to M \otimes N$ is injective. -/ -theorem forall_vanishesTrivially_iff_forall_FG_rTensor_injective : - (∀ {ι : Type u} [Fintype ι] {m : ι → M} {n : ι → N}, +theorem forall_vanishesTrivially_iff_forall_fg_rTensor_injective : + (∀ {l : ℕ} {m : Fin l → M} {n : Fin l → N}, ∑ i, m i ⊗ₜ n i = (0 : M ⊗[R] N) → VanishesTrivially R m n) ↔ ∀ (M' : Submodule R M) (_ : M'.FG), Injective (rTensor N M'.subtype) := by constructor · intro h M' _ exact rTensor_injective_of_forall_vanishesTrivially R h M' - · intro h ι _ m n hmn + · intro h k m n hmn exact vanishesTrivially_of_sum_tmul_eq_zero_of_rTensor_injective R (h _ (fg_span (Set.finite_range _))) hmn /-- If the map $M' \otimes N \to M \otimes N$ is injective for every finitely generated submodule $M' \subseteq M$, then it is in fact injective for every submodule $M' \subseteq M$. -/ -theorem rTensor_injective_of_forall_FG_rTensor_injective +theorem rTensor_injective_of_forall_fg_rTensor_injective (hMN : ∀ (M' : Submodule R M) (_ : M'.FG), Injective (rTensor N M'.subtype)) (M' : Submodule R M) : Injective (rTensor N M'.subtype) := (forall_vanishesTrivially_iff_forall_rTensor_injective R).mp - ((forall_vanishesTrivially_iff_forall_FG_rTensor_injective R).mpr hMN) M' + ((forall_vanishesTrivially_iff_forall_fg_rTensor_injective R).mpr hMN) M' + +@[deprecated (since := "2025-01-03")] alias forall_vanishesTrivially_iff_forall_FG_rTensor_injective + := forall_vanishesTrivially_iff_forall_fg_rTensor_injective +@[deprecated (since := "2025-01-03")] alias rTensor_injective_of_forall_FG_rTensor_injective := + rTensor_injective_of_forall_fg_rTensor_injective end TensorProduct diff --git a/Mathlib/RingTheory/Flat/EquationalCriterion.lean b/Mathlib/RingTheory/Flat/EquationalCriterion.lean index ccb3ba16c850c..cd762341f874b 100644 --- a/Mathlib/RingTheory/Flat/EquationalCriterion.lean +++ b/Mathlib/RingTheory/Flat/EquationalCriterion.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2024 Mitchell Lee. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mitchell Lee +Authors: Mitchell Lee, Junyan Xu -/ import Mathlib.RingTheory.Flat.Basic import Mathlib.LinearAlgebra.TensorProduct.Vanishing @@ -11,11 +11,11 @@ import Mathlib.Algebra.Module.FinitePresentation Let $M$ be a module over a commutative ring $R$. Let us say that a relation $\sum_{i \in \iota} f_i x_i = 0$ in $M$ is *trivial* (`Module.IsTrivialRelation`) if there exist a -finite index type $\kappa$, elements $(y_j)_{j \in \kappa}$ of $M$, +finite index type $\kappa$ = `Fin k`, elements $(y_j)_{j \in \kappa}$ of $M$, and elements $(a_{ij})_{i \in \iota, j \in \kappa}$ of $R$ such that for all $i$, $$x_i = \sum_j a_{ij} y_j$$ and for all $j$, -$$\sum_{i} f_i a_{ij} = 0.$$ +$$\sum_i f_i a_{ij} = 0.$$ The *equational criterion for flatness* [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK) (`Module.Flat.iff_forall_isTrivialRelation`) states that $M$ is flat if and only if every relation @@ -25,24 +25,25 @@ The equational criterion for flatness can be stated in the following form (`Module.Flat.iff_forall_exists_factorization`). Let $M$ be an $R$-module. Then the following two conditions are equivalent: * $M$ is flat. -* For all finite index types $\iota$, all elements $f \in R^{\iota}$, and all linear maps -$x \colon R^{\iota} \to M$ such that $x(f) = 0$, there exist a finite index type $\kappa$ and module -linear maps $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such +* For finite free modules $R^l$, all elements $f \in R^l$, and all linear maps +$x \colon R^l \to M$ such that $x(f) = 0$, there exist a finite free module $R^k$ and +linear maps $a \colon R^l \to R^k$ and $y \colon R^k \to M$ such that $x = y \circ a$ and $a(f) = 0$. -Of course, the module $R^\iota$ in this statement can be replaced by an arbitrary free module +Of course, the module $R^l$ in this statement can be replaced by an arbitrary free module (`Module.Flat.exists_factorization_of_apply_eq_zero_of_free`). We also have the following strengthening of the equational criterion for flatness (`Module.Flat.exists_factorization_of_comp_eq_zero_of_free`): Let $M$ be a flat module. Let $K$ and $N$ be finite $R$-modules with $N$ free, and let $f \colon K \to N$ and -$x \colon N \to M$ be linear maps such that $x \circ f = 0$. Then there exist a finite index type -$\kappa$ and $R$-linear maps $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such +$x \colon N \to M$ be linear maps such that $x \circ f = 0$. Then there exist a finite free module +$R^k$ and linear maps $a \colon N \to R^k$ and $y \colon R^k \to M$ such that $x = y \circ a$ and $a \circ f = 0$. We recover the usual equational criterion for flatness if -$K = R$ and $N = R^\iota$. This is used in the proof of Lazard's theorem. +$K = R$ and $N = R^l$. This is used in the proof of Lazard's theorem. We conclude that every linear map from a finitely presented module to a flat module factors -through a finite free module (`Module.Flat.exists_factorization_of_isFinitelyPresented`). +through a finite free module (`Module.Flat.exists_factorization_of_isFinitelyPresented`), and +every finitely presented flat module is projective (`Module.Flat.projective_of_finitePresentation`). ## References @@ -51,26 +52,24 @@ through a finite free module (`Module.Flat.exists_factorization_of_isFinitelyPre -/ -universe u - -variable {R M : Type u} [CommRing R] [AddCommGroup M] [Module R M] +variable {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] open LinearMap TensorProduct Finsupp namespace Module -variable {ι : Type u} [Fintype ι] (f : ι → R) (x : ι → M) +variable {ι : Type*} [Fintype ι] (f : ι → R) (x : ι → M) /-- The proposition that the relation $\sum_i f_i x_i = 0$ in $M$ is trivial. -That is, there exist a finite index type $\kappa$, elements +That is, there exist a finite index type $\kappa$ = `Fin k`, elements $(y_j)_{j \in \kappa}$ of $M$, and elements $(a_{ij})_{i \in \iota, j \in \kappa}$ of $R$ such that for all $i$, $$x_i = \sum_j a_{ij} y_j$$ and for all $j$, -$$\sum_{i} f_i a_{ij} = 0.$$ +$$\sum_i f_i a_{ij} = 0.$$ By `Module.sum_smul_eq_zero_of_isTrivialRelation`, this condition implies $\sum_i f_i x_i = 0$. -/ abbrev IsTrivialRelation : Prop := - ∃ (κ : Type u) (_ : Fintype κ) (a : ι → κ → R) (y : κ → M), + ∃ (k : ℕ) (a : ι → Fin k → R) (y : Fin k → M), (∀ i, x i = ∑ j, a i j • y j) ∧ ∀ j, ∑ i, f i * a i j = 0 variable {f x} @@ -81,9 +80,12 @@ theorem isTrivialRelation_iff_vanishesTrivially : IsTrivialRelation f x ↔ VanishesTrivially R f x := by simp only [IsTrivialRelation, VanishesTrivially, smul_eq_mul, mul_comm] +theorem _root_.Equiv.isTrivialRelation_comp {κ} [Fintype κ] (e : κ ≃ ι) : + IsTrivialRelation (f ∘ e) (x ∘ e) ↔ IsTrivialRelation f x := by + simp_rw [isTrivialRelation_iff_vanishesTrivially, e.vanishesTrivially_comp] /-- If the relation given by $(f_i)_{i \in \iota}$ and $(x_i)_{i \in \iota}$ is trivial, then -$\sum_{i} f_i x_i$ is actually equal to $0$. -/ +$\sum_i f_i x_i$ is actually equal to $0$. -/ theorem sum_smul_eq_zero_of_isTrivialRelation (h : IsTrivialRelation f x) : ∑ i, f i • x i = 0 := by simpa using @@ -95,44 +97,37 @@ end Module namespace Module.Flat variable (R M) in -/-- **Equational criterion for flatness** [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), -combined form. +/-- **Equational criterion for flatness**, combined form. Let $M$ be a module over a commutative ring $R$. The following are equivalent: * $M$ is flat. * For all ideals $I \subseteq R$, the map $I \otimes M \to M$ is injective. * Every $\sum_i f_i \otimes x_i$ that vanishes in $R \otimes M$ vanishes trivially. * Every relation $\sum_i f_i x_i = 0$ in $M$ is trivial. -* For all finite index types $\iota$, all elements $f \in R^{\iota}$, and all linear maps -$x \colon R^{\iota} \to M$ such that $x(f) = 0$, there exist a finite index type $\kappa$ and module -linear maps $a \colon R^{\iota} \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such +* For all finite free modules $R^l$, all elements $f \in R^l$, and all linear maps +$x \colon R^l \to M$ such that $x(f) = 0$, there exist a finite free module $R^k$ and +linear maps $a \colon R^l \to R^k$ and $y \colon R^k \to M$ such that $x = y \circ a$ and $a(f) = 0$. -* For all finite free modules $N$, all elements $f \in N$, and all linear maps $x \colon N \to M$ -such that $x(f) = 0$, there exist a finite index type $\kappa$ and $R$-linear maps -$a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and -$a(f) = 0$. -/ +-/ +@[stacks 00HK, stacks 058D "except (3)"] theorem tfae_equational_criterion : List.TFAE [ Flat R M, - ∀ (I : Ideal R), Function.Injective ⇑(rTensor M (Submodule.subtype I)), - ∀ {ι : Type u} [Fintype ι] {f : ι → R} {x : ι → M}, ∑ i, f i ⊗ₜ x i = (0 : R ⊗[R] M) → + ∀ I : Ideal R, Function.Injective (rTensor M I.subtype), + ∀ {l : ℕ} {f : Fin l → R} {x : Fin l → M}, ∑ i, f i ⊗ₜ x i = (0 : R ⊗[R] M) → VanishesTrivially R f x, - ∀ {ι : Type u} [Fintype ι] {f : ι → R} {x : ι → M}, ∑ i, f i • x i = 0 → IsTrivialRelation f x, - ∀ {ι : Type u} [Fintype ι] {f : ι →₀ R} {x : (ι →₀ R) →ₗ[R] M}, x f = 0 → - ∃ (κ : Type u) (_ : Fintype κ) (a : (ι →₀ R) →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), - x = y ∘ₗ a ∧ a f = 0, - ∀ {N : Type u} [AddCommGroup N] [Module R N] [Free R N] [Module.Finite R N] {f : N} - {x : N →ₗ[R] M}, x f = 0 → - ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), - x = y ∘ₗ a ∧ a f = 0] := by + ∀ {l : ℕ} {f : Fin l → R} {x : Fin l → M}, ∑ i, f i • x i = 0 → IsTrivialRelation f x, + ∀ {l : ℕ} {f : Fin l →₀ R} {x : (Fin l →₀ R) →ₗ[R] M}, x f = 0 → + ∃ (k : ℕ) (a : (Fin l →₀ R) →ₗ[R] (Fin k →₀ R)) (y : (Fin k →₀ R) →ₗ[R] M), + x = y ∘ₗ a ∧ a f = 0] := by classical 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 - | h₄, ι, hι, f, x, hfx => by - let f' : ι → R := f - let x' : ι → M := fun i ↦ x (single i 1) + | h₄, l, f, x, hfx => by + let f' : Fin l → R := f + let x' : Fin l → M := fun i ↦ x (single i 1) have := calc ∑ i, f' i • x' i _ = ∑ i, f i • x (single i 1) := rfl @@ -140,8 +135,8 @@ theorem tfae_equational_criterion : List.TFAE [ _ = x f := by simp_rw [smul_single, smul_eq_mul, mul_one, univ_sum_single] _ = 0 := hfx - obtain ⟨κ, hκ, a', y', ⟨ha'y', ha'⟩⟩ := h₄ this - use κ, hκ + obtain ⟨k, a', y', ⟨ha'y', ha'⟩⟩ := h₄ this + use k use Finsupp.linearCombination R (fun i ↦ equivFunOnFinite.symm (a' i)) use Finsupp.linearCombination R y' constructor @@ -152,144 +147,144 @@ 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 - | h₅, ι, hi, f, x, hfx => by - let f' : ι →₀ R := equivFunOnFinite.symm f - let x' : (ι →₀ R) →ₗ[R] M := Finsupp.linearCombination R x + | h₅, l, f, x, hfx => by + let f' : Fin l →₀ R := equivFunOnFinite.symm f + let x' : (Fin l →₀ R) →ₗ[R] M := Finsupp.linearCombination R x have : x' f' = 0 := by simpa [x', f', linearCombination_apply, sum_fintype] using hfx - obtain ⟨κ, hκ, a', y', ha'y', ha'⟩ := h₅ this - refine ⟨κ, hκ, fun i ↦ a' (single i 1), fun j ↦ y' (single j 1), fun i ↦ ?_, fun j ↦ ?_⟩ + obtain ⟨k, a', y', ha'y', ha'⟩ := h₅ this + refine ⟨k, fun i ↦ a' (single i 1), fun j ↦ y' (single j 1), fun i ↦ ?_, fun j ↦ ?_⟩ · simpa [x', ← map_smul, ← map_sum, smul_single] using LinearMap.congr_fun ha'y' (Finsupp.single i 1) · simp_rw [← smul_eq_mul, ← Finsupp.smul_apply, ← map_smul, ← finset_sum_apply, ← map_sum, smul_single, smul_eq_mul, mul_one, ← (fun _ ↦ equivFunOnFinite_symm_apply_toFun _ _ : ∀ x, f' x = f x), univ_sum_single] simpa using DFunLike.congr_fun ha' j - tfae_have 5 → 6 - | 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 - refine ⟨κ, hκ, a' ∘ₗ ϕ, y, ?_, ?_⟩ - · simpa [LinearMap.comp_assoc] using congrArg (fun g ↦ (g ∘ₗ ϕ : N →ₗ[R] M)) ha'y - · simpa using ha' - tfae_have 6 → 5 - | h₆, _, _, _, _, hfx => h₆ hfx tfae_finish -/-- **Equational criterion for flatness** [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK). - -A module $M$ is flat if and only if every relation $\sum_i f_i x_i = 0$ in $M$ is trivial. -/ -theorem iff_forall_isTrivialRelation : Flat R M ↔ ∀ {ι : Type u} [Fintype ι] {f : ι → R} - {x : ι → M}, ∑ i, f i • x i = 0 → IsTrivialRelation f x := +/-- **Equational criterion for flatness**: +a module $M$ is flat if and only if every relation $\sum_i f_i x_i = 0$ in $M$ is trivial. -/ +@[stacks 00HK] +theorem iff_forall_isTrivialRelation : Flat R M ↔ ∀ {l : ℕ} {f : Fin l → R} {x : Fin l → M}, + ∑ i, f i • x i = 0 → IsTrivialRelation f x := (tfae_equational_criterion R M).out 0 3 -/-- **Equational criterion for flatness** -[Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), forward direction. +/-- **Equational criterion for flatness**, forward direction. If $M$ is flat, then every relation $\sum_i f_i x_i = 0$ in $M$ is trivial. -/ -theorem isTrivialRelation_of_sum_smul_eq_zero [Flat R M] {ι : Type u} [Fintype ι] {f : ι → R} +@[stacks 00HK] +theorem isTrivialRelation_of_sum_smul_eq_zero [Flat R M] {ι : Type*} [Fintype ι] {f : ι → R} {x : ι → M} (h : ∑ i, f i • x i = 0) : IsTrivialRelation f x := - iff_forall_isTrivialRelation.mp ‹Flat R M› h + (Fintype.equivFin ι).symm.isTrivialRelation_comp.mp <| iff_forall_isTrivialRelation.mp ‹_› <| by + simpa only [← (Fintype.equivFin ι).symm.sum_comp] using h -/-- **Equational criterion for flatness** -[Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), backward direction. +/-- **Equational criterion for flatness**, backward direction. If every relation $\sum_i f_i x_i = 0$ in $M$ is trivial, then $M$ is flat. -/ -theorem of_forall_isTrivialRelation (hfx : ∀ {ι : Type u} [Fintype ι] {f : ι → R} {x : ι → M}, +@[stacks 00HK] +theorem of_forall_isTrivialRelation (hfx : ∀ {l : ℕ} {f : Fin l → R} {x : Fin l → M}, ∑ i, f i • x i = 0 → IsTrivialRelation f x) : Flat R M := iff_forall_isTrivialRelation.mpr hfx -/-- **Equational criterion for flatness** -[Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), alternate form. +/-- **Equational criterion for flatness**, alternate form. -A module $M$ is flat if and only if for all finite free modules $R^\iota$, -all $f \in R^{\iota}$, and all linear maps $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there -exist a finite free module $R^\kappa$ and linear maps $a \colon R^{\iota} \to R^{\kappa}$ and -$y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ +A module $M$ is flat if and only if for all finite free modules $R^l$, +all $f \in R^l$, and all linear maps $x \colon R^l \to M$ such that $x(f) = 0$, there +exist a finite free module $R^k$ and linear maps $a \colon R^l \to R^k$ and +$y \colon R^k \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ +@[stacks 058D "(1) ↔ (2)"] theorem iff_forall_exists_factorization : Flat R M ↔ - ∀ {ι : Type u} [Fintype ι] {f : ι →₀ R} {x : (ι →₀ R) →ₗ[R] M}, x f = 0 → - ∃ (κ : Type u) (_ : Fintype κ) (a : (ι →₀ R) →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), + ∀ {l : ℕ} {f : Fin l →₀ R} {x : (Fin l →₀ R) →ₗ[R] M}, x f = 0 → + ∃ (k : ℕ) (a : (Fin l →₀ R) →ₗ[R] (Fin k →₀ R)) (y : (Fin k →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0 := (tfae_equational_criterion R M).out 0 4 -/-- **Equational criterion for flatness** -[Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), forward direction, alternate form. - -Let $M$ be a flat module. Let $R^\iota$ be a finite free module, let $f \in R^{\iota}$ be an -element, and let $x \colon R^{\iota} \to M$ be a linear map such that $x(f) = 0$. Then there -exist a finite free module $R^\kappa$ and linear maps $a \colon R^{\iota} \to R^{\kappa}$ and -$y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ -theorem exists_factorization_of_apply_eq_zero [Flat R M] {ι : Type u} [_root_.Finite ι] - {f : ι →₀ R} {x : (ι →₀ R) →ₗ[R] M} (h : x f = 0) : - ∃ (κ : Type u) (_ : Fintype κ) (a : (ι →₀ R) →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), - x = y ∘ₗ a ∧ a f = 0 := - let ⟨_⟩ := nonempty_fintype ι; iff_forall_exists_factorization.mp ‹Flat R M› h - -/-- **Equational criterion for flatness** -[Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), backward direction, alternate form. - -Let $M$ be a module over a commutative ring $R$. Suppose that for all finite free modules $R^\iota$, -all $f \in R^{\iota}$, and all linear maps $x \colon R^{\iota} \to M$ such that $x(f) = 0$, there -exist a finite free module $R^\kappa$ and linear maps $a \colon R^{\iota} \to R^{\kappa}$ and -$y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. Then $M$ is flat. -/ -theorem of_forall_exists_factorization (h : ∀ {ι : Type u} [Fintype ι] {f : ι →₀ R} - {x : (ι →₀ R) →ₗ[R] M}, x f = 0 → - ∃ (κ : Type u) (_ : Fintype κ) (a : (ι →₀ R) →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), +/-- **Equational criterion for flatness**, backward direction, alternate form. + +Let $M$ be a module over a commutative ring $R$. Suppose that for all finite free modules $R^l$, +all $f \in R^l$, and all linear maps $x \colon R^l \to M$ such that $x(f) = 0$, there +exist a finite free module $R^k$ and linear maps $a \colon R^l \to R^k$ and +$y \colon R^k \to M$ such that $x = y \circ a$ and $a(f) = 0$. Then $M$ is flat. -/ +@[stacks 058D "(2) → (1)"] +theorem of_forall_exists_factorization + (h : ∀ {l : ℕ} {f : Fin l →₀ R} {x : (Fin l →₀ R) →ₗ[R] M}, x f = 0 → + ∃ (k : ℕ) (a : (Fin l →₀ R) →ₗ[R] (Fin k →₀ R)) (y : (Fin k →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0) : Flat R M := iff_forall_exists_factorization.mpr h -/-- **Equational criterion for flatness** [Stacks 00HK](https://stacks.math.columbia.edu/tag/00HK), -forward direction, second alternate form. +/-- **Equational criterion for flatness**, forward direction, second alternate form. Let $M$ be a flat module over a commutative ring $R$. Let $N$ be a finite free module over $R$, let $f \in N$, and let $x \colon N \to M$ be a linear map such that $x(f) = 0$. Then there exist a -finite index type $\kappa$ and $R$-linear maps $a \colon N \to R^{\kappa}$ and -$y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ -theorem exists_factorization_of_apply_eq_zero_of_free [Flat R M] {N : Type u} [AddCommGroup N] +finite free module $R^k$ and linear maps $a \colon N \to R^k$ and +$y \colon R^k \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ +@[stacks 058D "(1) → (2)"] +theorem exists_factorization_of_apply_eq_zero_of_free [Flat R M] {N : Type*} [AddCommGroup N] [Module R N] [Free R N] [Module.Finite R N] {f : N} {x : N →ₗ[R] M} (h : x f = 0) : - ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), - x = y ∘ₗ a ∧ a f = 0 := by - exact ((tfae_equational_criterion R M).out 0 5 rfl rfl).mp ‹Flat R M› h - -/-- Let $M$ be a flat module. Let $K$ and $N$ be finite $R$-modules with $N$ -free, and let $f \colon K \to N$ and $x \colon N \to M$ be linear maps such that -$x \circ f = 0$. Then there exist a finite index type $\kappa$ and $R$-linear maps -$a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and -$a \circ f = 0$. -/ -theorem exists_factorization_of_comp_eq_zero_of_free [Flat R M] {K N : Type u} [AddCommGroup K] - [Module R K] [Module.Finite R K] [AddCommGroup N] [Module R N] [Free R N] [Module.Finite R N] - {f : K →ₗ[R] N} {x : N →ₗ[R] M} (h : x ∘ₗ f = 0) : - ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), + ∃ (k : ℕ) (a : N →ₗ[R] (Fin k →₀ R)) (y : (Fin k →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0 := + have e := ((Module.Free.chooseBasis R N).reindex (Fintype.equivFin _)).repr.symm + have ⟨k, a, y, hya, haf⟩ := iff_forall_exists_factorization.mp ‹Flat R M› + (f := e.symm f) (x := x ∘ₗ e) (by simpa using h) + ⟨k, a ∘ₗ e.symm, y, by rwa [← comp_assoc, LinearEquiv.eq_comp_toLinearMap_symm], haf⟩ + +@[deprecated (since := "2025-01-03")] alias exists_factorization_of_apply_eq_zero := + exists_factorization_of_apply_eq_zero_of_free + +private theorem exists_factorization_of_comp_eq_zero_of_free_aux [Flat R M] {K : Type*} {n : ℕ} + [AddCommGroup K] [Module R K] [Module.Finite R K] {f : K →ₗ[R] Fin n →₀ R} + {x : (Fin n →₀ R) →ₗ[R] M} (h : x ∘ₗ f = 0) : + ∃ (k : ℕ) (a : (Fin n →₀ R) →ₗ[R] (Fin k →₀ R)) (y : (Fin k →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a ∘ₗ f = 0 := by - have (K' : Submodule R K) (hK' : K'.FG) : ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) - (y : (κ →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ K' ≤ LinearMap.ker (a ∘ₗ f) := by - revert N + have (K' : Submodule R K) (hK' : K'.FG) : ∃ (k : ℕ) (a : (Fin n →₀ R) →ₗ[R] (Fin k →₀ R)) + (y : (Fin k →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ K' ≤ LinearMap.ker (a ∘ₗ f) := by + revert n apply Submodule.fg_induction (N := K') (hN := hK') - · intro k N _ _ _ _ f x hfx + · intro k n f x hfx have : x (f k) = 0 := by simpa using LinearMap.congr_fun hfx k simpa using exists_factorization_of_apply_eq_zero_of_free this - · intro K₁ K₂ ih₁ ih₂ N _ _ _ _ f x hfx - obtain ⟨κ₁, _, a₁, y₁, rfl, ha₁⟩ := ih₁ hfx + · intro K₁ K₂ ih₁ ih₂ n f x hfx + obtain ⟨k₁, a₁, y₁, rfl, ha₁⟩ := ih₁ hfx have : y₁ ∘ₗ (a₁ ∘ₗ f) = 0 := by rw [← comp_assoc, hfx] - obtain ⟨κ₂, hκ₂, a₂, y₂, rfl, ha₂⟩ := ih₂ this - use κ₂, hκ₂, a₂ ∘ₗ a₁, y₂ + obtain ⟨k₂, a₂, y₂, rfl, ha₂⟩ := ih₂ this + use k₂, a₂ ∘ₗ a₁, y₂ simp_rw [comp_assoc] exact ⟨trivial, sup_le (ha₁.trans (ker_le_ker_comp _ _)) ha₂⟩ convert this ⊤ Finite.fg_top simp only [top_le_iff, ker_eq_top] -/-- Every linear map from a finitely presented module to a flat module factors through a finite +/-- Let $M$ be a flat module. Let $K$ and $N$ be finite $R$-modules with $N$ +free, and let $f \colon K \to N$ and $x \colon N \to M$ be linear maps such that +$x \circ f = 0$. Then there exist a finite free module $R^k$ and linear maps +$a \colon N \to R^k$ and $y \colon R^k \to M$ such that $x = y \circ a$ and +$a \circ f = 0$. -/ +@[stacks 058D "(1) → (4)"] +theorem exists_factorization_of_comp_eq_zero_of_free [Flat R M] {K N : Type*} [AddCommGroup K] + [Module R K] [Module.Finite R K] [AddCommGroup N] [Module R N] [Free R N] [Module.Finite R N] + {f : K →ₗ[R] N} {x : N →ₗ[R] M} (h : x ∘ₗ f = 0) : + ∃ (k : ℕ) (a : N →ₗ[R] (Fin k →₀ R)) (y : (Fin k →₀ R) →ₗ[R] M), + x = y ∘ₗ a ∧ a ∘ₗ f = 0 := + have e := ((Module.Free.chooseBasis R N).reindex (Fintype.equivFin _)).repr.symm + have ⟨k, a, y, hya, haf⟩ := exists_factorization_of_comp_eq_zero_of_free_aux + (f := e.symm ∘ₗ f) (x := x ∘ₗ e.toLinearMap) (by ext; simpa [comp_assoc] using congr($h _)) + ⟨k, a ∘ₗ e.symm, y, by rwa [← comp_assoc, LinearEquiv.eq_comp_toLinearMap_symm], by + rwa [comp_assoc]⟩ + +/-- Every homomorphism from a finitely presented module to a flat module factors through a finite free module. -/ -theorem exists_factorization_of_isFinitelyPresented [Flat R M] {P : Type u} [AddCommGroup P] +@[stacks 058E "only if"] +theorem exists_factorization_of_isFinitelyPresented [Flat R M] {P : Type*} [AddCommGroup P] [Module R P] [FinitePresentation R P] (h₁ : P →ₗ[R] M) : - ∃ (κ : Type u) (_ : Fintype κ) (h₂ : P →ₗ[R] (κ →₀ R)) (h₃ : (κ →₀ R) →ₗ[R] M), - h₁ = h₃ ∘ₗ h₂ := by - obtain ⟨L, _, _, K, ϕ, _, _, hK⟩ := FinitePresentation.equiv_quotient R P - haveI : Module.Finite R ↥K := Module.Finite.iff_fg.mpr hK + ∃ (k : ℕ) (h₂ : P →ₗ[R] (Fin k →₀ R)) (h₃ : (Fin k →₀ R) →ₗ[R] M), h₁ = h₃ ∘ₗ h₂ := by + have ⟨_, K, ϕ, hK⟩ := FinitePresentation.exists_fin R P + haveI : Module.Finite R K := Module.Finite.iff_fg.mpr hK have : (h₁ ∘ₗ ϕ.symm ∘ₗ K.mkQ) ∘ₗ K.subtype = 0 := by simp_rw [comp_assoc, (LinearMap.exact_subtype_mkQ K).linearMap_comp_eq_zero, comp_zero] - obtain ⟨κ, hκ, a, y, hay, ha⟩ := exists_factorization_of_comp_eq_zero_of_free this - use κ, hκ, (K.liftQ a (by rwa [← range_le_ker_iff, Submodule.range_subtype] at ha)) ∘ₗ ϕ, y + obtain ⟨k, a, y, hay, ha⟩ := exists_factorization_of_comp_eq_zero_of_free this + use k, (K.liftQ a (by rwa [← range_le_ker_iff, Submodule.range_subtype] at ha)) ∘ₗ ϕ, y apply (cancel_right ϕ.symm.surjective).mp apply (cancel_right K.mkQ_surjective).mp simpa [comp_assoc] +@[stacks 00NX "(1) → (2)"] +theorem projective_of_finitePresentation [Flat R M] [FinitePresentation R M] : Projective R M := + have ⟨_, f, g, eq⟩ := exists_factorization_of_isFinitelyPresented (.id (R := R) (M := M)) + .of_split f g eq.symm + end Module.Flat From 712c9d4818f0945fad7e58b770091881fd0692a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 18:59:54 +0000 Subject: [PATCH 143/681] feat: sets of doubling strictly less than 3/2 (#20572) From GrowthInGroups (LeanCamCombi) Co-authored-by: Bhavik Mehta (stabilizer G A : Set G) = A ∧ (stabilizer G A : Set G) <• a = A := by @@ -62,4 +79,251 @@ lemma smul_stabilizer_of_no_doubling (hA : #(A * A) ≤ #A) (ha : a ∈ A) : lemma op_smul_stabilizer_of_no_doubling (hA : #(A * A) ≤ #A) (ha : a ∈ A) : (stabilizer G A : Set G) <• a = A := (smul_stabilizer_of_no_doubling_aux hA ha).2 +/-! ### Doubling strictly less than `3 / 2` -/ + +private lemma big_intersection {x y : G} (hx : x ∈ A) (hy : y ∈ A) : + 2 * #A ≤ #((x • A) ∩ (y • A)) + #(A * A) := by + have : #((x • A) ∪ (y • A)) ≤ #(A * A) := by + refine card_le_card ?_ + rw [union_subset_iff] + exact ⟨smul_finset_subset_mul hx, smul_finset_subset_mul hy⟩ + refine (add_le_add_left this _).trans_eq' ?_ + rw [card_inter_add_card_union] + simp only [card_smul_finset, two_mul] + +private lemma mul_inv_eq_inv_mul_of_doubling_lt_two_aux (h : #(A * A) < 2 * #A) : + A⁻¹ * A ⊆ A * A⁻¹ := by + intro z + simp only [mem_mul, forall_exists_index, exists_and_left, and_imp, mem_inv, + exists_exists_and_eq_and] + rintro x hx y hy rfl + have ⟨t, ht⟩ : (x • A ∩ y • A).Nonempty := by + rw [← card_pos] + linarith [big_intersection hx hy] + simp only [mem_inter, mem_smul_finset, smul_eq_mul] at ht + obtain ⟨⟨z, hz, hzxwy⟩, w, hw, rfl⟩ := ht + refine ⟨z, hz, w, hw, ?_⟩ + rw [mul_inv_eq_iff_eq_mul, mul_assoc, ← hzxwy, inv_mul_cancel_left] + +-- TODO: is there a way to get wlog to make `mul_inv_eq_inv_mul_of_doubling_lt_two_aux` a goal? +-- ie wlog in the target rather than hypothesis +-- (BM: third time seeing this pattern) +-- I'm thinking something like wlog_suffices, where I could write +-- wlog_suffices : A⁻¹ * A ⊆ A * A⁻¹ +-- which reverts *everything* (just like wlog does) and makes the side goal A⁻¹ * A = A * A⁻¹ +-- under the assumption A⁻¹ * A ⊆ A * A⁻¹ +-- and changes the main goal to A⁻¹ * A ⊆ A * A⁻¹ +/-- If `A` has doubling strictly less than `2`, then `A * A⁻¹ = A⁻¹ * A`. -/ +lemma mul_inv_eq_inv_mul_of_doubling_lt_two (h : #(A * A) < 2 * #A) : A * A⁻¹ = A⁻¹ * A := by + refine Subset.antisymm ?_ (mul_inv_eq_inv_mul_of_doubling_lt_two_aux h) + simpa using + mul_inv_eq_inv_mul_of_doubling_lt_two_aux (A := A⁻¹) (by simpa [← mul_inv_rev] using h) + +private lemma weaken_doubling (h : #(A * A) < (3 / 2 : ℚ) * #A) : #(A * A) < 2 * #A := by + rw [← Nat.cast_lt (α := ℚ), Nat.cast_mul, Nat.cast_two] + linarith only [h] + +private lemma nonempty_of_doubling (h : #(A * A) < (3 / 2 : ℚ) * #A) : A.Nonempty := by + rw [nonempty_iff_ne_empty] + rintro rfl + simp at h + +/-- If `A` has doubling strictly less than `3 / 2`, then `A⁻¹ * A` is a subgroup. + +Note that this is sharp: `A = {0, 1}` in `ℤ` has doubling `3 / 2` and `A⁻¹ * A` isn't a subgroup. -/ +def invMulSubgroup (A : Finset G) (h : #(A * A) < (3 / 2 : ℚ) * #A) : Subgroup G where + carrier := A⁻¹ * A + one_mem' := by + have ⟨x, hx⟩ : A.Nonempty := nonempty_of_doubling h + exact ⟨x⁻¹, inv_mem_inv hx, x, by simp [hx]⟩ + inv_mem' := by + intro x + simp only [Set.mem_mul, Set.mem_inv, coe_inv, forall_exists_index, exists_and_left, mem_coe, + and_imp] + rintro a ha b hb rfl + exact ⟨b⁻¹, by simpa using hb, a⁻¹, ha, by simp⟩ + mul_mem' := by + norm_cast + have h₁ : ∀ x ∈ A, ∀ y ∈ A, (1 / 2 : ℚ) * #A < #(x • A ∩ y • A) := by + intro x hx y hy + have := big_intersection hx hy + rw [← Nat.cast_le (α := ℚ), Nat.cast_mul, Nat.cast_add, Nat.cast_two] at this + linarith + intro a c ha hc + simp only [mem_mul, mem_inv', exists_and_left] at ha hc + obtain ⟨a, ha, b, hb, rfl⟩ := ha + obtain ⟨c, hc, d, hd, rfl⟩ := hc + have h₂ : (1 / 2 : ℚ) * #A < #(A ∩ (a * b)⁻¹ • A) := by + refine (h₁ b hb _ ha).trans_le ?_ + rw [← card_smul_finset b⁻¹] + simp [smul_smul, smul_finset_inter] + have h₃ : (1 / 2 : ℚ) * #A < #(A ∩ (c * d) • A) := by + refine (h₁ _ hc d hd).trans_le ?_ + rw [← card_smul_finset c] + simp [smul_smul, smul_finset_inter] + have ⟨t, ht⟩ : ((A ∩ (c * d) • A) ∩ (A ∩ (a * b)⁻¹ • A)).Nonempty := by + rw [← card_pos, ← Nat.cast_pos (α := ℚ)] + have := card_inter_add_card_union (A ∩ (c * d) • A) (A ∩ (a * b)⁻¹ • A) + rw [← Nat.cast_inj (R := ℚ), Nat.cast_add, Nat.cast_add] at this + have : (#((A ∩ (c * d) • A) ∪ (A ∩ (a * b)⁻¹ • A)) : ℚ) ≤ #A := by + rw [Nat.cast_le, ← inter_union_distrib_left] + exact card_le_card inter_subset_left + linarith + simp only [inter_inter_inter_comm, inter_self, mem_inter, ← inv_smul_mem_iff, inv_inv, + smul_eq_mul, mul_assoc, mul_inv_rev] at ht + rw [← mul_inv_eq_inv_mul_of_doubling_lt_two (weaken_doubling h), mem_mul] + exact ⟨a * b * t, by simp [ht, mul_assoc], ((c * d)⁻¹ * t)⁻¹, by simp [ht, mul_assoc]⟩ + +lemma invMulSubgroup_eq_inv_mul (A : Finset G) (h) : (invMulSubgroup A h : Set G) = A⁻¹ * A := rfl + +lemma invMulSubgroup_eq_mul_inv (A : Finset G) (h) : (invMulSubgroup A h : Set G) = A * A⁻¹ := by + rw [invMulSubgroup_eq_inv_mul, eq_comm] + norm_cast + exact mul_inv_eq_inv_mul_of_doubling_lt_two (by qify at h ⊢; linarith) + +instance (A : Finset G) (h) : Fintype (invMulSubgroup A h) := by + simp only [invMulSubgroup, ← coe_mul, Subgroup.mem_mk, mem_coe]; infer_instance + +private lemma weak_invMulSubgroup_bound (h : #(A * A) < (3 / 2 : ℚ) * #A) : + #(A⁻¹ * A) < 2 * #A := by + have h₀ : A.Nonempty := nonempty_of_doubling h + have h₁ : ∀ x ∈ A, ∀ y ∈ A, (1 / 2 : ℚ) * #A < #((x • A) ∩ (y • A)) := by + intro x hx y hy + have := big_intersection hx hy + rw [← Nat.cast_le (α := ℚ), Nat.cast_mul, Nat.cast_add, Nat.cast_two] at this + linarith + have h₂ : ∀ a ∈ A⁻¹ * A, (1 / 2 : ℚ) * #A < #{xy ∈ A ×ˢ A | xy.1 * xy.2⁻¹ = a} := by + simp only [mem_mul, mem_product, Prod.forall, and_imp, mem_inv, exists_exists_and_eq_and, + forall_exists_index] + rintro _ a ha b hb rfl + refine (h₁ a ha b hb).trans_le ?_ + rw [Nat.cast_le] + refine card_le_card_of_injOn (fun t => (a⁻¹ * t, b⁻¹ * t)) ?_ (by simp [Set.InjOn]) + simp only [mem_inter, mem_product, and_imp, Prod.forall, mem_filter, mul_inv_rev, inv_inv, + exists_and_left, exists_eq_left, forall_exists_index, smul_eq_mul, + forall_apply_eq_imp_iff₂, inv_mul_cancel_left, inv_mul_cancel_right, mem_smul_finset] + rintro c hc d hd h + rw [mul_assoc, mul_inv_cancel_left, ← h, inv_mul_cancel_left] + simp [hd, hc] + have h₃ : ∀ x ∈ A ×ˢ A, (fun ⟨x, y⟩ => x * y⁻¹) x ∈ A⁻¹ * A := by + rw [← mul_inv_eq_inv_mul_of_doubling_lt_two (weaken_doubling h)] + simp only [mem_product, Prod.forall, mem_mul, and_imp, mem_inv] + intro a b ha hb + exact ⟨a, ha, b⁻¹, by simp [hb], rfl⟩ + have : ((1 / 2 : ℚ) * #A) * #(A⁻¹ * A) < (#A : ℚ) ^ 2 := by + rw [← Nat.cast_pow, sq, ← card_product, card_eq_sum_card_fiberwise h₃, Nat.cast_sum] + refine (sum_lt_sum_of_nonempty (by simp [h₀]) h₂).trans_eq' ?_ + simp only [sum_const, nsmul_eq_mul, mul_comm] + have : (0 : ℚ) < #A := by simpa [card_pos] + rw [← Nat.cast_lt (α := ℚ), Nat.cast_mul, Nat.cast_two] + -- passing between ℕ- and ℚ-inequalities is annoying, here and above + nlinarith + +private lemma A_subset_aH (a : G) (ha : a ∈ A) : A ⊆ a • (A⁻¹ * A) := by + rw [← smul_mul_assoc] + exact subset_mul_right _ (by simp [← inv_smul_mem_iff, inv_mem_inv ha]) + +private lemma subgroup_strong_bound_left (h : #(A * A) < (3 / 2 : ℚ) * #A) (a : G) (ha : a ∈ A) : + A * A ⊆ a • op a • (A⁻¹ * A) := by + have h₁ : (A⁻¹ * A) * (A⁻¹ * A) = A⁻¹ * A := by + rw [← coe_inj, coe_mul, coe_mul, ← invMulSubgroup_eq_inv_mul _ h, coe_mul_coe] + have h₂ : a • op a • (A⁻¹ * A) = (a • (A⁻¹ * A)) * (op a • (A⁻¹ * A)) := by + rw [mul_smul_comm, smul_mul_assoc, h₁, smul_comm] + rw [h₂] + refine mul_subset_mul (A_subset_aH a ha) ?_ + rw [← mul_inv_eq_inv_mul_of_doubling_lt_two (weaken_doubling h), ← mul_smul_comm] + exact subset_mul_left _ (by simp [← inv_smul_mem_iff, inv_mem_inv ha]) + +private lemma subgroup_strong_bound_right (h : #(A * A) < (3 / 2 : ℚ) * #A) (a : G) (ha : a ∈ A) : + a • op a • (A⁻¹ * A) ⊆ A * A := by + intro z hz + simp only [mem_smul_finset, smul_eq_mul_unop, unop_op, smul_eq_mul, mem_mul, mem_inv, + exists_exists_and_eq_and, exists_and_left] at hz + obtain ⟨d, ⟨b, hb, c, hc, rfl⟩, hz⟩ := hz + let l : Finset G := A ∩ ((z * a⁻¹) • (A⁻¹ * A)) + -- ^ set of x ∈ A st ∃ y ∈ H a with x y = z + let r : Finset G := (a • (A⁻¹ * A)) ∩ (z • A⁻¹) + -- ^ set of x ∈ a H st ∃ y ∈ A with x y = z + have : (A⁻¹ * A) * (A⁻¹ * A) = A⁻¹ * A := by + rw [← coe_inj, coe_mul, coe_mul, ← invMulSubgroup_eq_inv_mul _ h, coe_mul_coe] + have hl : l = A := by + rw [inter_eq_left, ← this, subset_smul_finset_iff] + simp only [← hz, mul_inv_rev, inv_inv, ← mul_assoc] + refine smul_finset_subset_mul ?_ + simp [mul_mem_mul, mem_inv, ha, hb, hc] + have hr : r = z • A⁻¹ := by + rw [inter_eq_right, ← this, mul_assoc _ A, + ← mul_inv_eq_inv_mul_of_doubling_lt_two (weaken_doubling h), subset_smul_finset_iff] + simp only [← mul_assoc, smul_smul] + refine smul_finset_subset_mul ?_ + simp [← hz, mul_mem_mul, ha, hb, hc, mem_inv] + have lr : l ∪ r ⊆ a • (A⁻¹ * A) := by + rw [union_subset_iff, hl] + exact ⟨A_subset_aH a ha, inter_subset_left⟩ + have : #l = #A := by rw [hl] + have : #r = #A := by rw [hr, card_smul_finset, card_inv] + have : #(l ∪ r) < 2 * #A := by + refine (card_le_card lr).trans_lt ?_ + rw [card_smul_finset] + exact weak_invMulSubgroup_bound h + have ⟨t, ht⟩ : (l ∩ r).Nonempty := by + rw [← card_pos] + linarith [card_inter_add_card_union l r] + simp only [hl, hr, mem_inter, ← inv_smul_mem_iff, smul_eq_mul, mem_inv', mul_inv_rev, + inv_inv] at ht + rw [mem_mul] + exact ⟨t, ht.1, t⁻¹ * z, ht.2, by simp⟩ + +open scoped RightActions in +lemma smul_inv_mul_opSMul_eq_mul_of_doubling_lt_three_halves (h : #(A * A) < (3 / 2 : ℚ) * #A) + (ha : a ∈ A) : a •> ((A⁻¹ * A) <• a) = A * A := + (subgroup_strong_bound_right h a ha).antisymm (subgroup_strong_bound_left h a ha) + +lemma card_inv_mul_of_doubling_lt_three_halves (h : #(A * A) < (3 / 2 : ℚ) * #A) : + #(A⁻¹ * A) = #(A * A) := by + obtain ⟨a, ha⟩ := nonempty_of_doubling h + simp_rw [← smul_inv_mul_opSMul_eq_mul_of_doubling_lt_three_halves h ha, card_smul_finset] + +lemma smul_inv_mul_eq_inv_mul_opSMul (h : #(A * A) < (3 / 2 : ℚ) * #A) (ha : a ∈ A) : + a •> (A⁻¹ * A) = (A⁻¹ * A) <• a := by + refine subset_antisymm ?_ ?_ + · rw [subset_smul_finset_iff, ← op_inv] + calc + a •> (A⁻¹ * A) <• a⁻¹ ⊆ a •> (A⁻¹ * A) * A⁻¹ := op_smul_finset_subset_mul (by simpa) + _ ⊆ A * (A⁻¹ * A) * A⁻¹ := by gcongr; exact smul_finset_subset_mul (by simpa) + _ = A⁻¹ * A := by + simp_rw [← coe_inj, coe_mul] + rw [← mul_assoc, ← invMulSubgroup_eq_mul_inv _ h, mul_assoc, + ← invMulSubgroup_eq_mul_inv _ h, coe_mul_coe, invMulSubgroup_eq_inv_mul] + · rw [subset_smul_finset_iff] + calc + a⁻¹ •> ((A⁻¹ * A) <• a) ⊆ A⁻¹ * (A⁻¹ * A) <• a := smul_finset_subset_mul (by simpa) + _ ⊆ A⁻¹ * ((A⁻¹ * A) * A) := by gcongr; exact op_smul_finset_subset_mul (by simpa) + _ = A⁻¹ * A := by + rw [← mul_inv_eq_inv_mul_of_doubling_lt_two <| weaken_doubling h] + simp_rw [← coe_inj, coe_mul] + rw [mul_assoc, ← invMulSubgroup_eq_inv_mul _ h, ← mul_assoc, + ← invMulSubgroup_eq_inv_mul _ h, ← invMulSubgroup_eq_mul_inv _ h, coe_mul_coe] + +open scoped RightActions in +/-- If `A` has doubling strictly less than `3 / 2`, then there exists a subgroup `H` of the +normaliser of `A` of size strictly less than `3 / 2 * #A` such that `A` is a subset of a coset of +`H` (in fact a subset of `a • H` for every `a ∈ A`). + +Note that this is sharp: `A = {0, 1}` in `ℤ` has doubling `3 / 2` and can't be covered by a subgroup +of size at most `2`. + +This is Theorem 2.2.1 in [tointon2020]. -/ +theorem doubling_lt_three_halves (h : #(A * A) < (3 / 2 : ℚ) * #A) : + ∃ (H : Subgroup G) (_ : Fintype H), Fintype.card H < (3 / 2 : ℚ) * #A ∧ ∀ a ∈ A, + (A : Set G) ⊆ a • H ∧ a •> (H : Set G) = H <• a := by + let H := invMulSubgroup A h + refine ⟨H, inferInstance, ?_, fun a ha ↦ ⟨?_, ?_⟩⟩ + · simp [← Nat.card_eq_fintype_card, invMulSubgroup, ← coe_mul, ← coe_inv, H] + rwa [Nat.card_eq_finsetCard, card_inv_mul_of_doubling_lt_three_halves h] + · rw [invMulSubgroup_eq_inv_mul] + exact_mod_cast A_subset_aH a ha + · simpa [H, invMulSubgroup_eq_inv_mul, ← coe_inv, ← coe_mul, ← coe_smul_finset] + using smul_inv_mul_eq_inv_mul_opSMul h ha + end Finset diff --git a/docs/references.bib b/docs/references.bib index 726943e64c4fe..8e48b5bc2aa1a 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -3560,6 +3560,19 @@ @Article{ tochiori_bertrand url = {https://www.chart.co.jp/subject/sugaku/suken_tsushin/76/76-8.pdf} } +@Book{ tointon2020, + author = {Tointon, Matthew C. H.}, + title = {Introduction to approximate groups}, + series = {London Mathematical Society Student Texts}, + volume = {94}, + publisher = {Cambridge University Press, Cambridge}, + year = {2020}, + pages = {xiii+205}, + isbn = {978-1-108-45644-9; 978-1-108-47073-5}, + mrclass = {20E07 (20F65)}, + mrnumber = {3971253} +} + @Book{ upmeier1987, author = {Harald {Upmeier}}, title = {{Jordan algebras in analysis, operator theory, and quantum From b626315263c22788302482b6763958b603dc967e Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Fri, 10 Jan 2025 18:59:56 +0000 Subject: [PATCH 144/681] refactor(IntermediateField/Adjoin): Split off relation to `Algebra.adjoin` (#20630) Part of `IntermediateField/Adjoin/Basic` is about the relation with `Algebra.adjoin` (e.g., assuming integrality). This PR splits off those results into their own file. Co-authored-by: Thomas Browning --- Mathlib.lean | 1 + .../IntermediateField/Adjoin/Algebra.lean | 214 ++++++++++++++++++ .../IntermediateField/Adjoin/Basic.lean | 203 +---------------- .../SplittingField/IsSplittingField.lean | 23 +- .../AlgebraicIndependent/Adjoin.lean | 2 +- .../RankAndCardinality.lean | 1 + .../TranscendenceBasis.lean | 2 +- 7 files changed, 241 insertions(+), 205 deletions(-) create mode 100644 Mathlib/FieldTheory/IntermediateField/Adjoin/Algebra.lean diff --git a/Mathlib.lean b/Mathlib.lean index c613c04977ec5..9fe2ca707ab71 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3075,6 +3075,7 @@ import Mathlib.FieldTheory.Galois.Basic import Mathlib.FieldTheory.Galois.GaloisClosure import Mathlib.FieldTheory.Galois.Infinite import Mathlib.FieldTheory.Galois.Profinite +import Mathlib.FieldTheory.IntermediateField.Adjoin.Algebra import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic import Mathlib.FieldTheory.IntermediateField.Adjoin.Defs import Mathlib.FieldTheory.IntermediateField.Algebraic diff --git a/Mathlib/FieldTheory/IntermediateField/Adjoin/Algebra.lean b/Mathlib/FieldTheory/IntermediateField/Adjoin/Algebra.lean new file mode 100644 index 0000000000000..2ee84f35be79e --- /dev/null +++ b/Mathlib/FieldTheory/IntermediateField/Adjoin/Algebra.lean @@ -0,0 +1,214 @@ +/- +Copyright (c) 2020 Thomas Browning, Patrick Lutz. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Thomas Browning, Patrick Lutz +-/ +import Mathlib.FieldTheory.IntermediateField.Adjoin.Defs +import Mathlib.FieldTheory.IntermediateField.Algebraic + +/-! +# Adjoining Elements to Fields + +This file relates `IntermediateField.adjoin` to `Algebra.adjoin`. +-/ + +open Module Polynomial + +namespace IntermediateField + +section AdjoinDef + +variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] (S : Set E) + +theorem algebra_adjoin_le_adjoin : Algebra.adjoin F S ≤ (adjoin F S).toSubalgebra := + Algebra.adjoin_le (subset_adjoin _ _) + +theorem adjoin_eq_algebra_adjoin (inv_mem : ∀ x ∈ Algebra.adjoin F S, x⁻¹ ∈ Algebra.adjoin F S) : + (adjoin F S).toSubalgebra = Algebra.adjoin F S := + le_antisymm + (show adjoin F S ≤ + { Algebra.adjoin F S with + inv_mem' := inv_mem } + from adjoin_le_iff.mpr Algebra.subset_adjoin) + (algebra_adjoin_le_adjoin _ _) + +theorem eq_adjoin_of_eq_algebra_adjoin (K : IntermediateField F E) + (h : K.toSubalgebra = Algebra.adjoin F S) : K = adjoin F S := by + apply toSubalgebra_injective + rw [h] + refine (adjoin_eq_algebra_adjoin F _ fun x ↦ ?_).symm + rw [← h] + exact K.inv_mem + +theorem adjoin_eq_top_of_algebra (hS : Algebra.adjoin F S = ⊤) : adjoin F S = ⊤ := + top_le_iff.mp (hS.symm.trans_le <| algebra_adjoin_le_adjoin F S) + +section AdjoinSimple + +variable (α : E) + +@[simp] +theorem AdjoinSimple.isIntegral_gen : IsIntegral F (AdjoinSimple.gen F α) ↔ IsIntegral F α := by + conv_rhs => rw [← AdjoinSimple.algebraMap_gen F α] + rw [isIntegral_algebraMap_iff (algebraMap F⟮α⟯ E).injective] + +variable {F} {α} + +theorem adjoin_algebraic_toSubalgebra {S : Set E} (hS : ∀ x ∈ S, IsAlgebraic F x) : + (IntermediateField.adjoin F S).toSubalgebra = Algebra.adjoin F S := + adjoin_eq_algebra_adjoin _ _ fun _ ↦ + (Algebra.IsIntegral.adjoin fun x hx ↦ (hS x hx).isIntegral).inv_mem + +theorem adjoin_simple_toSubalgebra_of_integral (hα : IsIntegral F α) : + F⟮α⟯.toSubalgebra = Algebra.adjoin F {α} := by + apply adjoin_algebraic_toSubalgebra + rintro x (rfl : x = α) + rwa [isAlgebraic_iff_isIntegral] + +section Supremum + +variable {K L : Type*} [Field K] [Field L] [Algebra K L] (E1 E2 : IntermediateField K L) + +theorem le_sup_toSubalgebra : E1.toSubalgebra ⊔ E2.toSubalgebra ≤ (E1 ⊔ E2).toSubalgebra := + sup_le (show E1 ≤ E1 ⊔ E2 from le_sup_left) (show E2 ≤ E1 ⊔ E2 from le_sup_right) + +theorem sup_toSubalgebra_of_isAlgebraic_right [Algebra.IsAlgebraic K E2] : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := by + have : (adjoin E1 (E2 : Set L)).toSubalgebra = _ := adjoin_algebraic_toSubalgebra fun x h ↦ + IsAlgebraic.tower_top E1 (isAlgebraic_iff.1 + (Algebra.IsAlgebraic.isAlgebraic (⟨x, h⟩ : E2))) + apply_fun Subalgebra.restrictScalars K at this + erw [← restrictScalars_toSubalgebra, restrictScalars_adjoin, + Algebra.restrictScalars_adjoin] at this + exact this + +theorem sup_toSubalgebra_of_isAlgebraic_left [Algebra.IsAlgebraic K E1] : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := by + have := sup_toSubalgebra_of_isAlgebraic_right E2 E1 + rwa [sup_comm (a := E1), sup_comm (a := E1.toSubalgebra)] + +/-- The compositum of two intermediate fields is equal to the compositum of them +as subalgebras, if one of them is algebraic over the base field. -/ +theorem sup_toSubalgebra_of_isAlgebraic + (halg : Algebra.IsAlgebraic K E1 ∨ Algebra.IsAlgebraic K E2) : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := + halg.elim (fun _ ↦ sup_toSubalgebra_of_isAlgebraic_left E1 E2) + (fun _ ↦ sup_toSubalgebra_of_isAlgebraic_right E1 E2) + +theorem sup_toSubalgebra_of_left [FiniteDimensional K E1] : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := + sup_toSubalgebra_of_isAlgebraic_left E1 E2 + +theorem sup_toSubalgebra_of_right [FiniteDimensional K E2] : + (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := + sup_toSubalgebra_of_isAlgebraic_right E1 E2 + +end Supremum + +section Tower + +variable (E) +variable {K : Type*} [Field K] [Algebra F K] [Algebra E K] [IsScalarTower F E K] + +/-- If `K / E / F` is a field extension tower, `L` is an intermediate field of `K / F`, such that +either `E / F` or `L / F` is algebraic, then `E(L) = E[L]`. -/ +theorem adjoin_toSubalgebra_of_isAlgebraic (L : IntermediateField F K) + (halg : Algebra.IsAlgebraic F E ∨ Algebra.IsAlgebraic F L) : + (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := by + let i := IsScalarTower.toAlgHom F E K + let E' := i.fieldRange + let i' : E ≃ₐ[F] E' := AlgEquiv.ofInjectiveField i + have hi : algebraMap E K = (algebraMap E' K) ∘ i' := by ext x; rfl + apply_fun _ using Subalgebra.restrictScalars_injective F + erw [← restrictScalars_toSubalgebra, restrictScalars_adjoin_of_algEquiv i' hi, + Algebra.restrictScalars_adjoin_of_algEquiv i' hi, restrictScalars_adjoin, + Algebra.restrictScalars_adjoin] + exact E'.sup_toSubalgebra_of_isAlgebraic L (halg.imp + (fun (_ : Algebra.IsAlgebraic F E) ↦ i'.isAlgebraic) id) + +theorem adjoin_toSubalgebra_of_isAlgebraic_left (L : IntermediateField F K) + [halg : Algebra.IsAlgebraic F E] : + (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := + adjoin_toSubalgebra_of_isAlgebraic E L (Or.inl halg) + +theorem adjoin_toSubalgebra_of_isAlgebraic_right (L : IntermediateField F K) + [halg : Algebra.IsAlgebraic F L] : + (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := + adjoin_toSubalgebra_of_isAlgebraic E L (Or.inr halg) + +end Tower + +end AdjoinSimple + +end AdjoinDef + +section Induction + +variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] + +theorem fg_of_fg_toSubalgebra (S : IntermediateField F E) (h : S.toSubalgebra.FG) : S.FG := by + cases' h with t ht + exact ⟨t, (eq_adjoin_of_eq_algebra_adjoin _ _ _ ht.symm).symm⟩ + +@[deprecated (since := "2024-10-28")] alias fG_of_fG_toSubalgebra := fg_of_fg_toSubalgebra + +theorem fg_of_noetherian (S : IntermediateField F E) [IsNoetherian F E] : S.FG := + S.fg_of_fg_toSubalgebra S.toSubalgebra.fg_of_noetherian + +theorem induction_on_adjoin [FiniteDimensional F E] (P : IntermediateField F E → Prop) + (base : P ⊥) (ih : ∀ (K : IntermediateField F E) (x : E), P K → P (K⟮x⟯.restrictScalars F)) + (K : IntermediateField F E) : P K := + letI : IsNoetherian F E := IsNoetherian.iff_fg.2 inferInstance + induction_on_adjoin_fg P base ih K K.fg_of_noetherian + +end Induction + +end IntermediateField + +namespace IsFractionRing + +variable {F A K L : Type*} [Field F] [CommRing A] [Algebra F A] + [Field K] [Algebra F K] [Algebra A K] [IsFractionRing A K] [Field L] [Algebra F L] + {g : A →ₐ[F] L} {f : K →ₐ[F] L} + +/-- If `F` is a field, `A` is an `F`-algebra with fraction field `K`, `L` is a field, +`g : A →ₐ[F] L` lifts to `f : K →ₐ[F] L`, +then the image of `f` is the field generated by the image of `g`. +Note: this does not require `IsScalarTower F A K`. -/ +theorem algHom_fieldRange_eq_of_comp_eq (h : RingHom.comp f (algebraMap A K) = (g : A →+* L)) : + f.fieldRange = IntermediateField.adjoin F g.range := by + apply IntermediateField.toSubfield_injective + simp_rw [AlgHom.fieldRange_toSubfield, IntermediateField.adjoin_toSubfield] + convert ringHom_fieldRange_eq_of_comp_eq h using 2 + exact Set.union_eq_self_of_subset_left fun _ ⟨x, hx⟩ ↦ ⟨algebraMap F A x, by simp [← hx]⟩ + +/-- If `F` is a field, `A` is an `F`-algebra with fraction field `K`, `L` is a field, +`g : A →ₐ[F] L` lifts to `f : K →ₐ[F] L`, +`s` is a set such that the image of `g` is the subalgebra generated by `s`, +then the image of `f` is the intermediate field generated by `s`. +Note: this does not require `IsScalarTower F A K`. -/ +theorem algHom_fieldRange_eq_of_comp_eq_of_range_eq + (h : RingHom.comp f (algebraMap A K) = (g : A →+* L)) + {s : Set L} (hs : g.range = Algebra.adjoin F s) : + f.fieldRange = IntermediateField.adjoin F s := by + apply IntermediateField.toSubfield_injective + simp_rw [AlgHom.fieldRange_toSubfield, IntermediateField.adjoin_toSubfield] + refine ringHom_fieldRange_eq_of_comp_eq_of_range_eq h ?_ + rw [← Algebra.adjoin_eq_ring_closure, ← hs]; rfl + +variable [IsScalarTower F A K] + +/-- The image of `IsFractionRing.liftAlgHom` is the intermediate field generated by the image +of the algebra hom. -/ +theorem liftAlgHom_fieldRange (hg : Function.Injective g) : + (liftAlgHom hg : K →ₐ[F] L).fieldRange = IntermediateField.adjoin F g.range := + algHom_fieldRange_eq_of_comp_eq (by ext; simp) + +/-- The image of `IsFractionRing.liftAlgHom` is the intermediate field generated by `s`, +if the image of the algebra hom is the subalgebra generated by `s`. -/ +theorem liftAlgHom_fieldRange_eq_of_range_eq (hg : Function.Injective g) + {s : Set L} (hs : g.range = Algebra.adjoin F s) : + (liftAlgHom hg : K →ₐ[F] L).fieldRange = IntermediateField.adjoin F s := + algHom_fieldRange_eq_of_comp_eq_of_range_eq (by ext; simp) hs + +end IsFractionRing diff --git a/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean b/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean index 757f77d8c8c69..c31d004b1f21e 100644 --- a/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean +++ b/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean @@ -49,116 +49,12 @@ theorem mem_adjoin_simple_iff {α : E} (x : E) : Algebra.adjoin_singleton_eq_range_aeval, AlgHom.mem_range, exists_exists_eq_and] tauto -end AdjoinDef - -section AdjoinDef - -variable (F : Type*) [Field F] {E : Type*} [Field E] [Algebra F E] (S : Set E) - -theorem algebra_adjoin_le_adjoin : Algebra.adjoin F S ≤ (adjoin F S).toSubalgebra := - Algebra.adjoin_le (subset_adjoin _ _) - -theorem adjoin_eq_algebra_adjoin (inv_mem : ∀ x ∈ Algebra.adjoin F S, x⁻¹ ∈ Algebra.adjoin F S) : - (adjoin F S).toSubalgebra = Algebra.adjoin F S := - le_antisymm - (show adjoin F S ≤ - { Algebra.adjoin F S with - inv_mem' := inv_mem } - from adjoin_le_iff.mpr Algebra.subset_adjoin) - (algebra_adjoin_le_adjoin _ _) - -theorem eq_adjoin_of_eq_algebra_adjoin (K : IntermediateField F E) - (h : K.toSubalgebra = Algebra.adjoin F S) : K = adjoin F S := by - apply toSubalgebra_injective - rw [h] - refine (adjoin_eq_algebra_adjoin F _ fun x ↦ ?_).symm - rw [← h] - exact K.inv_mem - -theorem adjoin_eq_top_of_algebra (hS : Algebra.adjoin F S = ⊤) : adjoin F S = ⊤ := - top_le_iff.mp (hS.symm.trans_le <| algebra_adjoin_le_adjoin F S) - -section AdjoinSimple - -variable (α : E) - -@[simp] -theorem AdjoinSimple.isIntegral_gen : IsIntegral F (AdjoinSimple.gen F α) ↔ IsIntegral F α := by - conv_rhs => rw [← AdjoinSimple.algebraMap_gen F α] - rw [isIntegral_algebraMap_iff (algebraMap F⟮α⟯ E).injective] - -variable {F} {α} - -theorem adjoin_algebraic_toSubalgebra {S : Set E} (hS : ∀ x ∈ S, IsAlgebraic F x) : - (IntermediateField.adjoin F S).toSubalgebra = Algebra.adjoin F S := - adjoin_eq_algebra_adjoin _ _ fun _ ↦ - (Algebra.IsIntegral.adjoin fun x hx ↦ (hS x hx).isIntegral).inv_mem - -theorem adjoin_simple_toSubalgebra_of_integral (hα : IsIntegral F α) : - F⟮α⟯.toSubalgebra = Algebra.adjoin F {α} := by - apply adjoin_algebraic_toSubalgebra - rintro x (rfl : x = α) - rwa [isAlgebraic_iff_isIntegral] - -/-- Characterize `IsSplittingField` with `IntermediateField.adjoin` instead of `Algebra.adjoin`. -/ -theorem _root_.isSplittingField_iff_intermediateField {p : F[X]} : - p.IsSplittingField F E ↔ p.Splits (algebraMap F E) ∧ adjoin F (p.rootSet E) = ⊤ := by - rw [← toSubalgebra_injective.eq_iff, - adjoin_algebraic_toSubalgebra fun _ ↦ isAlgebraic_of_mem_rootSet] - exact ⟨fun ⟨spl, adj⟩ ↦ ⟨spl, adj⟩, fun ⟨spl, adj⟩ ↦ ⟨spl, adj⟩⟩ - --- Note: p.Splits (algebraMap F E) also works -theorem isSplittingField_iff {p : F[X]} {K : IntermediateField F E} : - p.IsSplittingField F K ↔ p.Splits (algebraMap F K) ∧ K = adjoin F (p.rootSet E) := by - suffices _ → (Algebra.adjoin F (p.rootSet K) = ⊤ ↔ K = adjoin F (p.rootSet E)) by - exact ⟨fun h ↦ ⟨h.1, (this h.1).mp h.2⟩, fun h ↦ ⟨h.1, (this h.1).mpr h.2⟩⟩ - rw [← toSubalgebra_injective.eq_iff, - adjoin_algebraic_toSubalgebra fun x ↦ isAlgebraic_of_mem_rootSet] - refine fun hp ↦ (adjoin_rootSet_eq_range hp K.val).symm.trans ?_ - rw [← K.range_val, eq_comm] - -theorem adjoin_rootSet_isSplittingField {p : F[X]} (hp : p.Splits (algebraMap F E)) : - p.IsSplittingField F (adjoin F (p.rootSet E)) := - isSplittingField_iff.mpr ⟨splits_of_splits hp fun _ hx ↦ subset_adjoin F (p.rootSet E) hx, rfl⟩ +variable {F} section Supremum variable {K L : Type*} [Field K] [Field L] [Algebra K L] (E1 E2 : IntermediateField K L) -theorem le_sup_toSubalgebra : E1.toSubalgebra ⊔ E2.toSubalgebra ≤ (E1 ⊔ E2).toSubalgebra := - sup_le (show E1 ≤ E1 ⊔ E2 from le_sup_left) (show E2 ≤ E1 ⊔ E2 from le_sup_right) - -theorem sup_toSubalgebra_of_isAlgebraic_right [Algebra.IsAlgebraic K E2] : - (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := by - have : (adjoin E1 (E2 : Set L)).toSubalgebra = _ := adjoin_algebraic_toSubalgebra fun x h ↦ - IsAlgebraic.tower_top E1 (isAlgebraic_iff.1 - (Algebra.IsAlgebraic.isAlgebraic (⟨x, h⟩ : E2))) - apply_fun Subalgebra.restrictScalars K at this - erw [← restrictScalars_toSubalgebra, restrictScalars_adjoin, - Algebra.restrictScalars_adjoin] at this - exact this - -theorem sup_toSubalgebra_of_isAlgebraic_left [Algebra.IsAlgebraic K E1] : - (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := by - have := sup_toSubalgebra_of_isAlgebraic_right E2 E1 - rwa [sup_comm (a := E1), sup_comm (a := E1.toSubalgebra)] - -/-- The compositum of two intermediate fields is equal to the compositum of them -as subalgebras, if one of them is algebraic over the base field. -/ -theorem sup_toSubalgebra_of_isAlgebraic - (halg : Algebra.IsAlgebraic K E1 ∨ Algebra.IsAlgebraic K E2) : - (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := - halg.elim (fun _ ↦ sup_toSubalgebra_of_isAlgebraic_left E1 E2) - (fun _ ↦ sup_toSubalgebra_of_isAlgebraic_right E1 E2) - -theorem sup_toSubalgebra_of_left [FiniteDimensional K E1] : - (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := - sup_toSubalgebra_of_isAlgebraic_left E1 E2 - -theorem sup_toSubalgebra_of_right [FiniteDimensional K E2] : - (E1 ⊔ E2).toSubalgebra = E1.toSubalgebra ⊔ E2.toSubalgebra := - sup_toSubalgebra_of_isAlgebraic_right E1 E2 - instance finiteDimensional_sup [FiniteDimensional K E1] [FiniteDimensional K E2] : FiniteDimensional K (E1 ⊔ E2 : IntermediateField K L) := by let g := Algebra.TensorProduct.productMap E1.val E2.val @@ -263,32 +159,6 @@ section Tower variable (E) variable {K : Type*} [Field K] [Algebra F K] [Algebra E K] [IsScalarTower F E K] -/-- If `K / E / F` is a field extension tower, `L` is an intermediate field of `K / F`, such that -either `E / F` or `L / F` is algebraic, then `E(L) = E[L]`. -/ -theorem adjoin_toSubalgebra_of_isAlgebraic (L : IntermediateField F K) - (halg : Algebra.IsAlgebraic F E ∨ Algebra.IsAlgebraic F L) : - (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := by - let i := IsScalarTower.toAlgHom F E K - let E' := i.fieldRange - let i' : E ≃ₐ[F] E' := AlgEquiv.ofInjectiveField i - have hi : algebraMap E K = (algebraMap E' K) ∘ i' := by ext x; rfl - apply_fun _ using Subalgebra.restrictScalars_injective F - erw [← restrictScalars_toSubalgebra, restrictScalars_adjoin_of_algEquiv i' hi, - Algebra.restrictScalars_adjoin_of_algEquiv i' hi, restrictScalars_adjoin, - Algebra.restrictScalars_adjoin] - exact E'.sup_toSubalgebra_of_isAlgebraic L (halg.imp - (fun (_ : Algebra.IsAlgebraic F E) ↦ i'.isAlgebraic) id) - -theorem adjoin_toSubalgebra_of_isAlgebraic_left (L : IntermediateField F K) - [halg : Algebra.IsAlgebraic F E] : - (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := - adjoin_toSubalgebra_of_isAlgebraic E L (Or.inl halg) - -theorem adjoin_toSubalgebra_of_isAlgebraic_right (L : IntermediateField F K) - [halg : Algebra.IsAlgebraic F L] : - (adjoin E (L : Set K)).toSubalgebra = Algebra.adjoin E (L : Set K) := - adjoin_toSubalgebra_of_isAlgebraic E L (Or.inr halg) - /-- If `K / E / F` is a field extension tower, `L` is an intermediate field of `K / F`, such that either `E / F` or `L / F` is algebraic, then `[E(L) : E] ≤ [L : F]`. A corollary of `Subalgebra.adjoin_rank_le` since in this case `E(L) = E[L]`. -/ @@ -377,8 +247,6 @@ theorem exists_finset_of_mem_adjoin {S : Set E} {x : E} (hx : x ∈ adjoin F S) rintro _ h _ rfl exact subset_adjoin F _ ⟨_, h, rfl⟩ -end AdjoinSimple - end AdjoinDef section AdjoinIntermediateFieldLattice @@ -751,27 +619,6 @@ theorem _root_.Polynomial.irreducible_comp {f g : K[X]} (hfm : f.Monic) (hgm : g end AdjoinIntegralElement -section Induction - -variable {F : Type*} [Field F] {E : Type*} [Field E] [Algebra F E] - -theorem fg_of_fg_toSubalgebra (S : IntermediateField F E) (h : S.toSubalgebra.FG) : S.FG := by - cases' h with t ht - exact ⟨t, (eq_adjoin_of_eq_algebra_adjoin _ _ _ ht.symm).symm⟩ - -@[deprecated (since := "2024-10-28")] alias fG_of_fG_toSubalgebra := fg_of_fg_toSubalgebra - -theorem fg_of_noetherian (S : IntermediateField F E) [IsNoetherian F E] : S.FG := - S.fg_of_fg_toSubalgebra S.toSubalgebra.fg_of_noetherian - -theorem induction_on_adjoin [FiniteDimensional F E] (P : IntermediateField F E → Prop) - (base : P ⊥) (ih : ∀ (K : IntermediateField F E) (x : E), P K → P (K⟮x⟯.restrictScalars F)) - (K : IntermediateField F E) : P K := - letI : IsNoetherian F E := IsNoetherian.iff_fg.2 inferInstance - induction_on_adjoin_fg P base ih K K.fg_of_noetherian - -end Induction - end IntermediateField section Minpoly @@ -914,54 +761,6 @@ theorem equivAdjoinSimple_symm_gen (pb : PowerBasis K L) : end PowerBasis -namespace IsFractionRing - -variable {F A K L : Type*} [Field F] [CommRing A] [Algebra F A] - [Field K] [Algebra F K] [Algebra A K] [IsFractionRing A K] [Field L] [Algebra F L] - {g : A →ₐ[F] L} {f : K →ₐ[F] L} - -/-- If `F` is a field, `A` is an `F`-algebra with fraction field `K`, `L` is a field, -`g : A →ₐ[F] L` lifts to `f : K →ₐ[F] L`, -then the image of `f` is the field generated by the image of `g`. -Note: this does not require `IsScalarTower F A K`. -/ -theorem algHom_fieldRange_eq_of_comp_eq (h : RingHom.comp f (algebraMap A K) = (g : A →+* L)) : - f.fieldRange = IntermediateField.adjoin F g.range := by - apply IntermediateField.toSubfield_injective - simp_rw [AlgHom.fieldRange_toSubfield, IntermediateField.adjoin_toSubfield] - convert ringHom_fieldRange_eq_of_comp_eq h using 2 - exact Set.union_eq_self_of_subset_left fun _ ⟨x, hx⟩ ↦ ⟨algebraMap F A x, by simp [← hx]⟩ - -/-- If `F` is a field, `A` is an `F`-algebra with fraction field `K`, `L` is a field, -`g : A →ₐ[F] L` lifts to `f : K →ₐ[F] L`, -`s` is a set such that the image of `g` is the subalgebra generated by `s`, -then the image of `f` is the intermediate field generated by `s`. -Note: this does not require `IsScalarTower F A K`. -/ -theorem algHom_fieldRange_eq_of_comp_eq_of_range_eq - (h : RingHom.comp f (algebraMap A K) = (g : A →+* L)) - {s : Set L} (hs : g.range = Algebra.adjoin F s) : - f.fieldRange = IntermediateField.adjoin F s := by - apply IntermediateField.toSubfield_injective - simp_rw [AlgHom.fieldRange_toSubfield, IntermediateField.adjoin_toSubfield] - refine ringHom_fieldRange_eq_of_comp_eq_of_range_eq h ?_ - rw [← Algebra.adjoin_eq_ring_closure, ← hs]; rfl - -variable [IsScalarTower F A K] - -/-- The image of `IsFractionRing.liftAlgHom` is the intermediate field generated by the image -of the algebra hom. -/ -theorem liftAlgHom_fieldRange (hg : Function.Injective g) : - (liftAlgHom hg : K →ₐ[F] L).fieldRange = IntermediateField.adjoin F g.range := - algHom_fieldRange_eq_of_comp_eq (by ext; simp) - -/-- The image of `IsFractionRing.liftAlgHom` is the intermediate field generated by `s`, -if the image of the algebra hom is the subalgebra generated by `s`. -/ -theorem liftAlgHom_fieldRange_eq_of_range_eq (hg : Function.Injective g) - {s : Set L} (hs : g.range = Algebra.adjoin F s) : - (liftAlgHom hg : K →ₐ[F] L).fieldRange = IntermediateField.adjoin F s := - algHom_fieldRange_eq_of_comp_eq_of_range_eq (by ext; simp) hs - -end IsFractionRing - namespace IntermediateField universe u v diff --git a/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean b/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean index 941be4066c4e0..0178c38677943 100644 --- a/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean +++ b/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.RingTheory.Adjoin.Field -import Mathlib.FieldTheory.IntermediateField.Basic +import Mathlib.FieldTheory.IntermediateField.Adjoin.Algebra /-! # Splitting fields @@ -161,3 +161,24 @@ theorem IntermediateField.splits_iff_mem (h : p.Splits (algebraMap K L)) : theorem IsIntegral.mem_intermediateField_of_minpoly_splits {x : L} (int : IsIntegral K x) {F : IntermediateField K L} (h : Splits (algebraMap K F) (minpoly K x)) : x ∈ F := by rw [← F.fieldRange_val]; exact int.mem_range_algebraMap_of_minpoly_splits h + +/-- Characterize `IsSplittingField` with `IntermediateField.adjoin` instead of `Algebra.adjoin`. -/ +theorem isSplittingField_iff_intermediateField : p.IsSplittingField K L ↔ + p.Splits (algebraMap K L) ∧ IntermediateField.adjoin K (p.rootSet L) = ⊤ := by + rw [← IntermediateField.toSubalgebra_injective.eq_iff, + IntermediateField.adjoin_algebraic_toSubalgebra fun _ ↦ isAlgebraic_of_mem_rootSet] + exact ⟨fun ⟨spl, adj⟩ ↦ ⟨spl, adj⟩, fun ⟨spl, adj⟩ ↦ ⟨spl, adj⟩⟩ + +-- Note: p.Splits (algebraMap F E) also works +theorem IntermediateField.isSplittingField_iff : + p.IsSplittingField K F ↔ p.Splits (algebraMap K F) ∧ F = adjoin K (p.rootSet L) := by + suffices _ → (Algebra.adjoin K (p.rootSet F) = ⊤ ↔ F = adjoin K (p.rootSet L)) by + exact ⟨fun h ↦ ⟨h.1, (this h.1).mp h.2⟩, fun h ↦ ⟨h.1, (this h.1).mpr h.2⟩⟩ + rw [← toSubalgebra_injective.eq_iff, + adjoin_algebraic_toSubalgebra fun x ↦ isAlgebraic_of_mem_rootSet] + refine fun hp ↦ (adjoin_rootSet_eq_range hp F.val).symm.trans ?_ + rw [← F.range_val, eq_comm] + +theorem IntermediateField.adjoin_rootSet_isSplittingField (hp : p.Splits (algebraMap K L)) : + p.IsSplittingField K (adjoin K (p.rootSet L)) := + isSplittingField_iff.mpr ⟨splits_of_splits hp fun _ hx ↦ subset_adjoin K (p.rootSet L) hx, rfl⟩ diff --git a/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean b/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean index 86d46294c1730..46cb51be48adf 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic +import Mathlib.FieldTheory.IntermediateField.Adjoin.Algebra import Mathlib.RingTheory.AlgebraicIndependent.Defs /-! diff --git a/Mathlib/RingTheory/AlgebraicIndependent/RankAndCardinality.lean b/Mathlib/RingTheory/AlgebraicIndependent/RankAndCardinality.lean index e5df26045cf9a..f5becced2bfea 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/RankAndCardinality.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/RankAndCardinality.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic import Mathlib.FieldTheory.MvRatFunc.Rank import Mathlib.RingTheory.Algebraic.Cardinality import Mathlib.RingTheory.AlgebraicIndependent.Adjoin diff --git a/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean b/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean index fc0151cb337bd..47ba020c8b563 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/TranscendenceBasis.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic +import Mathlib.FieldTheory.IntermediateField.Adjoin.Algebra import Mathlib.RingTheory.AlgebraicIndependent.Transcendental /-! From 45970a9b06f9ed3e22243f8978a60d14486e0a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Fri, 10 Jan 2025 20:24:31 +0000 Subject: [PATCH 145/681] chore(CategoryTheory): moving/renaming Subpresheaf (#20583) From the file `CategoryTheory.Sites.Subsheaf`, the general definitions and properties of subpresheaves (of types) are moved to a new file `Category.Subpresheaf.Basic`, and it is renamed `Subpresheaf` instead of `GrothendieckTopology.Subpresheaf`. There will be subsequent PRs developing this notion, and it will be used in the context of simplicial sets. --- Mathlib.lean | 1 + .../Sites/LocallyInjective.lean | 6 +- Mathlib/CategoryTheory/Sites/Subsheaf.lean | 179 +-------------- Mathlib/CategoryTheory/Subpresheaf/Basic.lean | 208 ++++++++++++++++++ 4 files changed, 219 insertions(+), 175 deletions(-) create mode 100644 Mathlib/CategoryTheory/Subpresheaf/Basic.lean diff --git a/Mathlib.lean b/Mathlib.lean index 9fe2ca707ab71..e500e30da7061 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2213,6 +2213,7 @@ import Mathlib.CategoryTheory.Subobject.Limits import Mathlib.CategoryTheory.Subobject.MonoOver import Mathlib.CategoryTheory.Subobject.Types import Mathlib.CategoryTheory.Subobject.WellPowered +import Mathlib.CategoryTheory.Subpresheaf.Basic import Mathlib.CategoryTheory.Subterminal import Mathlib.CategoryTheory.Sums.Associator import Mathlib.CategoryTheory.Sums.Basic diff --git a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean index 782d1b84f0591..1d17353edb606 100644 --- a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean @@ -166,7 +166,7 @@ lemma isLocallyInjective_iff_injective_of_separated exact (hsep _ (equalizerSieve_mem J φ x y h)).ext (fun _ _ hf => hf) · apply isLocallyInjective_of_injective -instance (F : Cᵒᵖ ⥤ Type w) (G : GrothendieckTopology.Subpresheaf F) : +instance (F : Cᵒᵖ ⥤ Type w) (G : Subpresheaf F) : IsLocallyInjective J G.ι := isLocallyInjective_of_injective _ _ (fun X => by intro ⟨x, _⟩ ⟨y, _⟩ h @@ -243,8 +243,8 @@ lemma mono_of_isLocallyInjective [IsLocallyInjective φ] : Mono φ := by infer_instance instance {F G : Sheaf J (Type w)} (f : F ⟶ G) : - IsLocallyInjective (GrothendieckTopology.imageSheafι f) := by - dsimp [GrothendieckTopology.imageSheafι] + IsLocallyInjective (imageSheafι f) := by + dsimp [imageSheafι] infer_instance end Sheaf diff --git a/Mathlib/CategoryTheory/Sites/Subsheaf.lean b/Mathlib/CategoryTheory/Sites/Subsheaf.lean index b7b6807e53ccc..3e31f82d383ff 100644 --- a/Mathlib/CategoryTheory/Sites/Subsheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Subsheaf.lean @@ -8,6 +8,7 @@ import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono import Mathlib.Tactic.CategoryTheory.Elementwise import Mathlib.CategoryTheory.Adhesive import Mathlib.CategoryTheory.Sites.ConcreteSheafification +import Mathlib.CategoryTheory.Subpresheaf.Basic /-! @@ -17,14 +18,14 @@ We define the sub(pre)sheaf of a type valued presheaf. ## Main results -- `CategoryTheory.GrothendieckTopology.Subpresheaf` : +- `CategoryTheory.Subpresheaf` : A subpresheaf of a presheaf of types. -- `CategoryTheory.GrothendieckTopology.Subpresheaf.sheafify` : +- `CategoryTheory.Subpresheaf.sheafify` : The sheafification of a subpresheaf as a subpresheaf. Note that this is a sheaf only when the whole sheaf is. -- `CategoryTheory.GrothendieckTopology.Subpresheaf.sheafify_isSheaf` : +- `CategoryTheory.Subpresheaf.sheafify_isSheaf` : The sheafification is a sheaf -- `CategoryTheory.GrothendieckTopology.Subpresheaf.sheafifyLift` : +- `CategoryTheory.Subpresheaf.sheafifyLift` : The descent of a map into a sheaf to the sheafification. - `CategoryTheory.GrothendieckTopology.imageSheaf` : The image sheaf of a morphism. - `CategoryTheory.GrothendieckTopology.imageFactorization` : The image sheaf as a @@ -36,134 +37,12 @@ universe w v u open Opposite CategoryTheory -namespace CategoryTheory.GrothendieckTopology +namespace CategoryTheory variable {C : Type u} [Category.{v} C] (J : GrothendieckTopology C) -/-- A subpresheaf of a presheaf consists of a subset of `F.obj U` for every `U`, -compatible with the restriction maps `F.map i`. -/ -@[ext] -structure Subpresheaf (F : Cᵒᵖ ⥤ Type w) where - /-- If `G` is a sub-presheaf of `F`, then the sections of `G` on `U` forms a subset of sections of - `F` on `U`. -/ - obj : ∀ U, Set (F.obj U) - /-- If `G` is a sub-presheaf of `F` and `i : U ⟶ V`, then for each `G`-sections on `U` `x`, - `F i x` is in `F(V)`. -/ - map : ∀ {U V : Cᵒᵖ} (i : U ⟶ V), obj U ⊆ F.map i ⁻¹' obj V - variable {F F' F'' : Cᵒᵖ ⥤ Type w} (G G' : Subpresheaf F) -instance : PartialOrder (Subpresheaf F) := - PartialOrder.lift Subpresheaf.obj (fun _ _ => Subpresheaf.ext) - -instance : Top (Subpresheaf F) := - ⟨⟨fun _ => ⊤, @fun U _ _ x _ => by simp⟩⟩ - -instance : Nonempty (Subpresheaf F) := - inferInstance - -/-- The subpresheaf as a presheaf. -/ -@[simps!] -def Subpresheaf.toPresheaf : Cᵒᵖ ⥤ Type w where - obj U := G.obj U - map := @fun _ _ i x => ⟨F.map i x, G.map i x.prop⟩ - map_id X := by - ext ⟨x, _⟩ - dsimp - simp only [FunctorToTypes.map_id_apply] - map_comp := @fun X Y Z i j => by - ext ⟨x, _⟩ - dsimp - simp only [FunctorToTypes.map_comp_apply] - -instance {U} : CoeHead (G.toPresheaf.obj U) (F.obj U) where - coe := Subtype.val - -/-- The inclusion of a subpresheaf to the original presheaf. -/ -@[simps] -def Subpresheaf.ι : G.toPresheaf ⟶ F where app _ x := x - -instance : Mono G.ι := - ⟨@fun _ _ _ e => - NatTrans.ext <| - funext fun U => funext fun x => Subtype.ext <| congr_fun (congr_app e U) x⟩ - -/-- The inclusion of a subpresheaf to a larger subpresheaf -/ -@[simps] -def Subpresheaf.homOfLe {G G' : Subpresheaf F} (h : G ≤ G') : G.toPresheaf ⟶ G'.toPresheaf where - app U x := ⟨x, h U x.prop⟩ - -instance {G G' : Subpresheaf F} (h : G ≤ G') : Mono (Subpresheaf.homOfLe h) := - ⟨fun _ _ e => - NatTrans.ext <| - funext fun U => - funext fun x => - Subtype.ext <| (congr_arg Subtype.val <| (congr_fun (congr_app e U) x :) :)⟩ - -@[reassoc (attr := simp)] -theorem Subpresheaf.homOfLe_ι {G G' : Subpresheaf F} (h : G ≤ G') : - Subpresheaf.homOfLe h ≫ G'.ι = G.ι := by - ext - rfl - -instance : IsIso (Subpresheaf.ι (⊤ : Subpresheaf F)) := by - refine @NatIso.isIso_of_isIso_app _ _ _ _ _ _ _ ?_ - intro X - rw [isIso_iff_bijective] - exact ⟨Subtype.coe_injective, fun x => ⟨⟨x, _root_.trivial⟩, rfl⟩⟩ - -theorem Subpresheaf.eq_top_iff_isIso : G = ⊤ ↔ IsIso G.ι := by - constructor - · rintro rfl - infer_instance - · intro H - ext U x - apply (iff_of_eq (iff_true _)).mpr - rw [← IsIso.inv_hom_id_apply (G.ι.app U) x] - exact ((inv (G.ι.app U)) x).2 - -/-- If the image of a morphism falls in a subpresheaf, then the morphism factors through it. -/ -@[simps!] -def Subpresheaf.lift (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : F' ⟶ G.toPresheaf where - app U x := ⟨f.app U x, hf U x⟩ - naturality := by - have := elementwise_of% f.naturality - intros - refine funext fun x => Subtype.ext ?_ - simp only [toPresheaf_obj, types_comp_apply] - exact this _ _ - -@[reassoc (attr := simp)] -theorem Subpresheaf.lift_ι (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : - G.lift f hf ≫ G.ι = f := by - ext - rfl - -/-- Given a subpresheaf `G` of `F`, an `F`-section `s` on `U`, we may define a sieve of `U` -consisting of all `f : V ⟶ U` such that the restriction of `s` along `f` is in `G`. -/ -@[simps] -def Subpresheaf.sieveOfSection {U : Cᵒᵖ} (s : F.obj U) : Sieve (unop U) where - arrows V f := F.map f.op s ∈ G.obj (op V) - downward_closed := @fun V W i hi j => by - simp only [op_unop, op_comp, FunctorToTypes.map_comp_apply] - exact G.map _ hi - -/-- Given an `F`-section `s` on `U` and a subpresheaf `G`, we may define a family of elements in -`G` consisting of the restrictions of `s` -/ -def Subpresheaf.familyOfElementsOfSection {U : Cᵒᵖ} (s : F.obj U) : - (G.sieveOfSection s).1.FamilyOfElements G.toPresheaf := fun _ i hi => ⟨F.map i.op s, hi⟩ - -theorem Subpresheaf.family_of_elements_compatible {U : Cᵒᵖ} (s : F.obj U) : - (G.familyOfElementsOfSection s).Compatible := by - intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ e - refine Subtype.ext ?_ -- Porting note: `ext1` does not work here - change F.map g₁.op (F.map f₁.op s) = F.map g₂.op (F.map f₂.op s) - rw [← FunctorToTypes.map_comp_apply, ← FunctorToTypes.map_comp_apply, ← op_comp, ← op_comp, e] - -theorem Subpresheaf.nat_trans_naturality (f : F' ⟶ G.toPresheaf) {U V : Cᵒᵖ} (i : U ⟶ V) - (x : F'.obj U) : (f.app V (F'.map i x)).1 = F.map i (f.app U x).1 := - congr_arg Subtype.val (FunctorToTypes.naturality _ _ f i x) - /-- The sheafification of a subpresheaf as a subpresheaf. Note that this is a sheaf only when the whole presheaf is a sheaf. -/ def Subpresheaf.sheafify : Subpresheaf F where @@ -310,29 +189,6 @@ theorem Subpresheaf.sheafify_le (h : G ≤ G') (hF : Presieve.IsSheaf J F) section Image -/-- The image presheaf of a morphism, whose components are the set-theoretic images. -/ -@[simps] -def imagePresheaf (f : F' ⟶ F) : Subpresheaf F where - obj U := Set.range (f.app U) - map := by - rintro U V i _ ⟨x, rfl⟩ - have := elementwise_of% f.naturality - exact ⟨_, this i x⟩ - -@[simp] -theorem top_subpresheaf_obj (U) : (⊤ : Subpresheaf F).obj U = ⊤ := - rfl - -@[simp] -theorem imagePresheaf_id : imagePresheaf (𝟙 F) = ⊤ := by - ext - simp - -/-- A morphism factors through the image presheaf. -/ -@[simps!] -def toImagePresheaf (f : F' ⟶ F) : F' ⟶ (imagePresheaf f).toPresheaf := - (imagePresheaf f).lift f fun _ _ => Set.mem_range_self _ - variable (J) /-- A morphism factors through the sheafification of the image presheaf. -/ @@ -342,27 +198,6 @@ def toImagePresheafSheafify (f : F' ⟶ F) : F' ⟶ ((imagePresheaf f).sheafify variable {J} -@[reassoc (attr := simp)] -theorem toImagePresheaf_ι (f : F' ⟶ F) : toImagePresheaf f ≫ (imagePresheaf f).ι = f := - (imagePresheaf f).lift_ι _ _ - -theorem imagePresheaf_comp_le (f₁ : F ⟶ F') (f₂ : F' ⟶ F'') : - imagePresheaf (f₁ ≫ f₂) ≤ imagePresheaf f₂ := fun U _ hx => ⟨f₁.app U hx.choose, hx.choose_spec⟩ - -instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ (Type (max v w))} (f : F ⟶ F') [hf : Mono f] : - IsIso (toImagePresheaf f) := by - have : ∀ (X : Cᵒᵖ), IsIso ((toImagePresheaf f).app X) := by - intro X - rw [isIso_iff_bijective] - constructor - · intro x y e - have := (NatTrans.mono_iff_mono_app f).mp hf X - rw [mono_iff_injective] at this - exact this (congr_arg Subtype.val e :) - · rintro ⟨_, ⟨x, rfl⟩⟩ - exact ⟨x, rfl⟩ - apply NatIso.isIso_of_isIso_app - /-- The image sheaf of a morphism between sheaves, defined to be the sheafification of `image_presheaf`. -/ @[simps] @@ -444,4 +279,4 @@ instance : Limits.HasImages (Sheaf J (Type max v u)) := end Image -end CategoryTheory.GrothendieckTopology +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Subpresheaf/Basic.lean b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean new file mode 100644 index 0000000000000..e272dd86854b4 --- /dev/null +++ b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean @@ -0,0 +1,208 @@ +/- +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.CategoryTheory.Elementwise +import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono +import Mathlib.Tactic.CategoryTheory.Elementwise +import Mathlib.CategoryTheory.Sites.IsSheafFor + + +/-! + +# Subpresheaf of types + +We define the subpresheaf of a type valued presheaf. + +## Main results + +- `CategoryTheory.Subpresheaf` : + A subpresheaf of a presheaf of types. + +-/ + + +universe w v u + +open Opposite CategoryTheory + +namespace CategoryTheory + +variable {C : Type u} [Category.{v} C] + +/-- A subpresheaf of a presheaf consists of a subset of `F.obj U` for every `U`, +compatible with the restriction maps `F.map i`. -/ +@[ext] +structure Subpresheaf (F : Cᵒᵖ ⥤ Type w) where + /-- If `G` is a sub-presheaf of `F`, then the sections of `G` on `U` forms a subset of sections of + `F` on `U`. -/ + obj : ∀ U, Set (F.obj U) + /-- If `G` is a sub-presheaf of `F` and `i : U ⟶ V`, then for each `G`-sections on `U` `x`, + `F i x` is in `F(V)`. -/ + map : ∀ {U V : Cᵒᵖ} (i : U ⟶ V), obj U ⊆ F.map i ⁻¹' obj V + +@[deprecated (since := "2025-01-08")] alias GrothendieckTopology.Subpresheaf := Subpresheaf + +variable {F F' F'' : Cᵒᵖ ⥤ Type w} (G G' : Subpresheaf F) + +instance : PartialOrder (Subpresheaf F) := + PartialOrder.lift Subpresheaf.obj (fun _ _ => Subpresheaf.ext) + +instance : Top (Subpresheaf F) := + ⟨⟨fun _ => ⊤, @fun U _ _ x _ => by simp⟩⟩ + +instance : Nonempty (Subpresheaf F) := + inferInstance + +/-- The subpresheaf as a presheaf. -/ +@[simps!] +def Subpresheaf.toPresheaf : Cᵒᵖ ⥤ Type w where + obj U := G.obj U + map := @fun _ _ i x => ⟨F.map i x, G.map i x.prop⟩ + map_id X := by + ext ⟨x, _⟩ + dsimp + simp only [FunctorToTypes.map_id_apply] + map_comp := @fun X Y Z i j => by + ext ⟨x, _⟩ + dsimp + simp only [FunctorToTypes.map_comp_apply] + +instance {U} : CoeHead (G.toPresheaf.obj U) (F.obj U) where + coe := Subtype.val + +/-- The inclusion of a subpresheaf to the original presheaf. -/ +@[simps] +def Subpresheaf.ι : G.toPresheaf ⟶ F where app _ x := x + +instance : Mono G.ι := + ⟨@fun _ _ _ e => + NatTrans.ext <| + funext fun U => funext fun x => Subtype.ext <| congr_fun (congr_app e U) x⟩ + +/-- The inclusion of a subpresheaf to a larger subpresheaf -/ +@[simps] +def Subpresheaf.homOfLe {G G' : Subpresheaf F} (h : G ≤ G') : G.toPresheaf ⟶ G'.toPresheaf where + app U x := ⟨x, h U x.prop⟩ + +instance {G G' : Subpresheaf F} (h : G ≤ G') : Mono (Subpresheaf.homOfLe h) := + ⟨fun _ _ e => + NatTrans.ext <| + funext fun U => + funext fun x => + Subtype.ext <| (congr_arg Subtype.val <| (congr_fun (congr_app e U) x :) :)⟩ + +@[reassoc (attr := simp)] +theorem Subpresheaf.homOfLe_ι {G G' : Subpresheaf F} (h : G ≤ G') : + Subpresheaf.homOfLe h ≫ G'.ι = G.ι := by + ext + rfl + +instance : IsIso (Subpresheaf.ι (⊤ : Subpresheaf F)) := by + refine @NatIso.isIso_of_isIso_app _ _ _ _ _ _ _ ?_ + intro X + rw [isIso_iff_bijective] + exact ⟨Subtype.coe_injective, fun x => ⟨⟨x, _root_.trivial⟩, rfl⟩⟩ + +theorem Subpresheaf.eq_top_iff_isIso : G = ⊤ ↔ IsIso G.ι := by + constructor + · rintro rfl + infer_instance + · intro H + ext U x + apply (iff_of_eq (iff_true _)).mpr + rw [← IsIso.inv_hom_id_apply (G.ι.app U) x] + exact ((inv (G.ι.app U)) x).2 + +/-- If the image of a morphism falls in a subpresheaf, then the morphism factors through it. -/ +@[simps!] +def Subpresheaf.lift (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : F' ⟶ G.toPresheaf where + app U x := ⟨f.app U x, hf U x⟩ + naturality := by + have := elementwise_of% f.naturality + intros + refine funext fun x => Subtype.ext ?_ + simp only [toPresheaf_obj, types_comp_apply] + exact this _ _ + +@[reassoc (attr := simp)] +theorem Subpresheaf.lift_ι (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : + G.lift f hf ≫ G.ι = f := by + ext + rfl + +/-- Given a subpresheaf `G` of `F`, an `F`-section `s` on `U`, we may define a sieve of `U` +consisting of all `f : V ⟶ U` such that the restriction of `s` along `f` is in `G`. -/ +@[simps] +def Subpresheaf.sieveOfSection {U : Cᵒᵖ} (s : F.obj U) : Sieve (unop U) where + arrows V f := F.map f.op s ∈ G.obj (op V) + downward_closed := @fun V W i hi j => by + simp only [op_unop, op_comp, FunctorToTypes.map_comp_apply] + exact G.map _ hi + +/-- Given an `F`-section `s` on `U` and a subpresheaf `G`, we may define a family of elements in +`G` consisting of the restrictions of `s` -/ +def Subpresheaf.familyOfElementsOfSection {U : Cᵒᵖ} (s : F.obj U) : + (G.sieveOfSection s).1.FamilyOfElements G.toPresheaf := fun _ i hi => ⟨F.map i.op s, hi⟩ + +theorem Subpresheaf.family_of_elements_compatible {U : Cᵒᵖ} (s : F.obj U) : + (G.familyOfElementsOfSection s).Compatible := by + intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ e + refine Subtype.ext ?_ -- Porting note: `ext1` does not work here + change F.map g₁.op (F.map f₁.op s) = F.map g₂.op (F.map f₂.op s) + rw [← FunctorToTypes.map_comp_apply, ← FunctorToTypes.map_comp_apply, ← op_comp, ← op_comp, e] + +theorem Subpresheaf.nat_trans_naturality (f : F' ⟶ G.toPresheaf) {U V : Cᵒᵖ} (i : U ⟶ V) + (x : F'.obj U) : (f.app V (F'.map i x)).1 = F.map i (f.app U x).1 := + congr_arg Subtype.val (FunctorToTypes.naturality _ _ f i x) + +section Image + +/-- The image presheaf of a morphism, whose components are the set-theoretic images. -/ +@[simps] +def imagePresheaf (f : F' ⟶ F) : Subpresheaf F where + obj U := Set.range (f.app U) + map := by + rintro U V i _ ⟨x, rfl⟩ + have := elementwise_of% f.naturality + exact ⟨_, this i x⟩ + +@[simp] +theorem top_subpresheaf_obj (U) : (⊤ : Subpresheaf F).obj U = ⊤ := + rfl + +@[simp] +theorem imagePresheaf_id : imagePresheaf (𝟙 F) = ⊤ := by + ext + simp + +/-- A morphism factors through the image presheaf. -/ +@[simps!] +def toImagePresheaf (f : F' ⟶ F) : F' ⟶ (imagePresheaf f).toPresheaf := + (imagePresheaf f).lift f fun _ _ => Set.mem_range_self _ + +@[reassoc (attr := simp)] +theorem toImagePresheaf_ι (f : F' ⟶ F) : toImagePresheaf f ≫ (imagePresheaf f).ι = f := + (imagePresheaf f).lift_ι _ _ + +theorem imagePresheaf_comp_le (f₁ : F ⟶ F') (f₂ : F' ⟶ F'') : + imagePresheaf (f₁ ≫ f₂) ≤ imagePresheaf f₂ := fun U _ hx => ⟨f₁.app U hx.choose, hx.choose_spec⟩ + +instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ Type w} (f : F ⟶ F') [hf : Mono f] : + IsIso (toImagePresheaf f) := by + have : ∀ (X : Cᵒᵖ), IsIso ((toImagePresheaf f).app X) := by + intro X + rw [isIso_iff_bijective] + constructor + · intro x y e + have := (NatTrans.mono_iff_mono_app f).mp hf X + rw [mono_iff_injective] at this + exact this (congr_arg Subtype.val e :) + · rintro ⟨_, ⟨x, rfl⟩⟩ + exact ⟨x, rfl⟩ + apply NatIso.isIso_of_isIso_app + +end Image + +end CategoryTheory From 3949513a2c02bc38e369f9736c3300a82eba73bf Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Fri, 10 Jan 2025 20:46:58 +0000 Subject: [PATCH 146/681] feat(Order): Boolean algebra structure on idempotents (#20618) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We show that the idempotent in a commutative ring form a Boolean algebra, with complement given by `a ↦ 1 - a` and infimum given by multiplication. In a commutative semiring where subtraction is not available, it is still true that pairs of elements `(a, b)` satisfying `a * b = 0` and `a + b = 1` form a Boolean algebra (such elements are automatically idempotents, and such a pair is uniquely determined by either `a` or `b`). --- Mathlib.lean | 1 + Mathlib/Algebra/Ring/Idempotents.lean | 6 ++ Mathlib/Order/Idempotents.lean | 149 ++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 Mathlib/Order/Idempotents.lean diff --git a/Mathlib.lean b/Mathlib.lean index e500e30da7061..842bce26f64ba 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4164,6 +4164,7 @@ import Mathlib.Order.Hom.Lattice import Mathlib.Order.Hom.Order import Mathlib.Order.Hom.Set import Mathlib.Order.Ideal +import Mathlib.Order.Idempotents import Mathlib.Order.InitialSeg import Mathlib.Order.Interval.Basic import Mathlib.Order.Interval.Finset.Basic diff --git a/Mathlib/Algebra/Ring/Idempotents.lean b/Mathlib/Algebra/Ring/Idempotents.lean index c4ecbbfe757dd..9be312f90d4da 100644 --- a/Mathlib/Algebra/Ring/Idempotents.lean +++ b/Mathlib/Algebra/Ring/Idempotents.lean @@ -111,6 +111,12 @@ lemma map {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N] {e : M} (he : IsIdempotentElem e) (f : F) : IsIdempotentElem (f e) := by rw [IsIdempotentElem, ← map_mul, he.eq] +lemma of_mul_add {R} [Semiring R] {e₁ e₂ : R} (mul : e₁ * e₂ = 0) (add : e₁ + e₂ = 1) : + IsIdempotentElem e₁ ∧ IsIdempotentElem e₂ := by + simp_rw [IsIdempotentElem]; constructor + · conv_rhs => rw [← mul_one e₁, ← add, mul_add, mul, add_zero] + · conv_rhs => rw [← one_mul e₂, ← add, add_mul, mul, zero_add] + /-! ### Instances on `Subtype IsIdempotentElem` -/ diff --git a/Mathlib/Order/Idempotents.lean b/Mathlib/Order/Idempotents.lean new file mode 100644 index 0000000000000..e872f7be5ab00 --- /dev/null +++ b/Mathlib/Order/Idempotents.lean @@ -0,0 +1,149 @@ +/- +Copyright (c) 2025 Junyan Xu. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Junyan Xu +-/ +import Mathlib.Algebra.Ring.Idempotents +import Mathlib.Order.BooleanAlgebra +import Mathlib.Order.Hom.Basic + +/-! +# Boolean algebra structure on idempotents in a commutative (semi)ring + +We show that the idempotent in a commutative ring form a Boolean algebra, with complement given +by `a ↦ 1 - a` and infimum given by multiplication. In a commutative semiring where subtraction +is not available, it is still true that pairs of elements `(a, b)` satisfying `a * b = 0` and +`a + b = 1` form a Boolean algebra (such elements are automatically idempotents, and such a pair +is uniquely determined by either `a` or `b`). +-/ + +variable {α : Type*} + +instance [CommMonoid α] [AddCommMonoid α] : + HasCompl {a : α × α // a.1 * a.2 = 0 ∧ a.1 + a.2 = 1} where + compl a := ⟨(a.1.2, a.1.1), (mul_comm ..).trans a.2.1, (add_comm ..).trans a.2.2⟩ + +lemma eq_of_mul_eq_add_eq_one [Semiring α] (a : α) {b c : α} + (mul : a * b = c * a) (add_ab : a + b = 1) (add_ac : a + c = 1) : + b = c := + calc b = (a + c) * b := by rw [add_ac, one_mul] + _ = c * (a + b) := by rw [add_mul, mul, mul_add] + _ = c := by rw [add_ab, mul_one] + +section CommSemiring + +variable [CommSemiring α] {a b : {a : α × α // a.1 * a.2 = 0 ∧ a.1 + a.2 = 1}} + +lemma mul_eq_zero_add_eq_one_ext_left (eq : a.1.1 = b.1.1) : a = b := by + refine Subtype.ext <| Prod.ext_iff.mpr ⟨eq, eq_of_mul_eq_add_eq_one a.1.1 ?_ a.2.2 ?_⟩ + · rw [a.2.1, mul_comm, eq, b.2.1] + · rw [eq, b.2.2] + +lemma mul_eq_zero_add_eq_one_ext_right (eq : a.1.2 = b.1.2) : a = b := by + refine Subtype.ext <| Prod.ext_iff.mpr ⟨eq_of_mul_eq_add_eq_one a.1.2 ?_ ?_ ?_, eq⟩ + · rw [mul_comm, a.2.1, eq, b.2.1] + · rw [add_comm, a.2.2] + · rw [add_comm, eq, b.2.2] + +instance : PartialOrder {a : α × α // a.1 * a.2 = 0 ∧ a.1 + a.2 = 1} where + le a b := a.1.1 * b.1.1 = a.1.1 + le_refl a := (IsIdempotentElem.of_mul_add a.2.1 a.2.2).1 + le_trans a b c hab hbc := show _ = _ by rw [← hab, mul_assoc, hbc] + le_antisymm a b hab hba := mul_eq_zero_add_eq_one_ext_left <| by rw [← hab, mul_comm, hba] + +instance : SemilatticeSup {a : α × α // a.1 * a.2 = 0 ∧ a.1 + a.2 = 1} where + sup a b := ⟨(a.1.1 + a.1.2 * b.1.1, a.1.2 * b.1.2), by simp_rw [add_mul, + mul_mul_mul_comm _ b.1.1, b.2.1, mul_zero, ← mul_assoc, a.2.1, zero_mul, add_zero], by + simp_rw [add_assoc, ← mul_add, b.2.2, mul_one, a.2.2]⟩ + le_sup_left a b := by + simp_rw [(· ≤ ·), mul_add, ← mul_assoc, a.2.1, zero_mul, add_zero, + (IsIdempotentElem.of_mul_add a.2.1 a.2.2).1.eq] + le_sup_right a b := by + simp_rw [(· ≤ ·), mul_add, mul_comm a.1.2, ← mul_assoc, + (IsIdempotentElem.of_mul_add b.2.1 b.2.2).1.eq, ← mul_add, a.2.2, mul_one] + sup_le a b c hac hbc := by simp_rw [(· ≤ ·), add_mul, mul_assoc]; rw [hac, hbc] + +instance : BooleanAlgebra {a : α × α // a.1 * a.2 = 0 ∧ a.1 + a.2 = 1} where + inf a b := (aᶜ ⊔ bᶜ)ᶜ + inf_le_left a b := by simp_rw [(· ≤ ·), (· ⊔ ·), (·ᶜ), SemilatticeSup.sup, + mul_right_comm, (IsIdempotentElem.of_mul_add a.2.1 a.2.2).1.eq] + inf_le_right a b := by simp_rw [(· ≤ ·), (· ⊔ ·), (·ᶜ), SemilatticeSup.sup, + mul_assoc, (IsIdempotentElem.of_mul_add b.2.1 b.2.2).1.eq] + le_inf a b c hab hac := by + simp_rw [(· ≤ ·), (· ⊔ ·), (·ᶜ), SemilatticeSup.sup, ← mul_assoc]; rw [hab, hac] + le_sup_inf a b c := Eq.le <| mul_eq_zero_add_eq_one_ext_right <| by simp_rw [(· ⊔ ·), (· ⊓ ·), + (·ᶜ), SemilatticeInf.inf, SemilatticeSup.sup, add_mul, mul_add, mul_mul_mul_comm _ b.1.1, + (IsIdempotentElem.of_mul_add a.2.1 a.2.2).2.eq, ← mul_assoc, a.2.1, zero_mul, zero_add] + top := ⟨(1, 0), mul_zero _, add_zero _⟩ + bot := ⟨(0, 1), zero_mul _, zero_add _⟩ + inf_compl_le_bot a := Eq.le <| mul_eq_zero_add_eq_one_ext_right <| by + simp_rw [(· ⊔ ·), (· ⊓ ·), (·ᶜ), SemilatticeInf.inf, SemilatticeSup.sup, + (IsIdempotentElem.of_mul_add a.2.1 a.2.2).1.eq, add_comm, a.2.2] + top_le_sup_compl a := Eq.le <| mul_eq_zero_add_eq_one_ext_left <| by simp_rw [(· ⊔ ·), (·ᶜ), + SemilatticeSup.sup, (IsIdempotentElem.of_mul_add a.2.1 a.2.2).2.eq, a.2.2] + le_top _ := mul_one _ + bot_le _ := zero_mul _ + sdiff_eq _ _ := rfl + himp_eq _ _ := rfl + +end CommSemiring + +instance [CommSemigroup α] : SemilatticeInf {a : α // IsIdempotentElem a} where + le a b := a.1 * b = a + le_refl a := a.2 + le_trans a b c hab hbc := show _ = _ by rw [← hab, mul_assoc, hbc] + le_antisymm a b hab hba := Subtype.ext <| by rw [← hab, mul_comm, hba] + inf a b := ⟨_, a.2.mul b.2⟩ + inf_le_left a b := show _ = _ by simp_rw [mul_right_comm]; rw [a.2] + inf_le_right a b := show _ = _ by simp_rw [mul_assoc]; rw [b.2] + le_inf a b c hab hac := by simp_rw [← mul_assoc]; rw [hab, hac] + +instance [CommMonoid α] : OrderTop {a : α // IsIdempotentElem a} where + top := ⟨1, .one⟩ + le_top _ := mul_one _ + +instance [CommMonoidWithZero α] : OrderBot {a : α // IsIdempotentElem a} where + bot := ⟨0, .zero⟩ + bot_le _ := zero_mul _ + +section CommRing + +variable [CommRing α] + +instance : Lattice {a : α // IsIdempotentElem a} where + __ : SemilatticeInf _ := inferInstance + sup a b := ⟨_, a.2.add_sub_mul b.2⟩ + le_sup_left a b := show _ = _ by + simp_rw [mul_sub, mul_add]; rw [← mul_assoc, a.2, add_sub_cancel_right] + le_sup_right a b := show _ = _ by + simp_rw [mul_sub, mul_add]; rw [← mul_assoc, mul_right_comm, b.2, add_sub_cancel_left] + sup_le a b c hac hbc := show _ = _ by simp_rw [sub_mul, add_mul, mul_assoc]; rw [hbc, hac] + +instance : BooleanAlgebra {a : α // IsIdempotentElem a} where + __ : DistribLattice _ := .ofInfSupLe fun a b c ↦ Eq.le <| Subtype.ext <| by + simp_rw [(· ⊔ ·), (· ⊓ ·), SemilatticeSup.sup, SemilatticeInf.inf, Lattice.inf, + SemilatticeInf.inf, mul_sub, mul_add, mul_mul_mul_comm] + rw [a.2] + __ : OrderTop _ := inferInstance + __ : OrderBot _ := inferInstance + compl a := ⟨_, a.2.one_sub⟩ + inf_compl_le_bot a := (mul_zero _).trans ((mul_one_sub ..).trans <| by rw [a.2, sub_self]).symm + top_le_sup_compl a := (one_mul _).trans <| by + simp_rw [(· ⊔ ·), SemilatticeSup.sup, add_sub_cancel, mul_sub, mul_one] + rw [a.2, sub_self, sub_zero]; rfl + sdiff_eq _ _ := rfl + himp a b := ⟨_, (a.2.mul b.2.one_sub).one_sub⟩ + himp_eq a b := Subtype.ext <| by simp_rw [(· ⊔ ·), SemilatticeSup.sup, + add_comm b.1, add_sub_assoc, mul_sub, mul_one, sub_sub_cancel, sub_add, mul_comm] + +/-- In a commutative ring, the idempotents are in 1-1 correspondence with pairs of elements +whose product is 0 and whose sum is 1. The correspondence is given by `a ↔ (a, 1 - a)`. -/ +def OrderIso.isIdempotentElemMulZeroAddOne : + {a : α // IsIdempotentElem a} ≃o {a : α × α // a.1 * a.2 = 0 ∧ a.1 + a.2 = 1} where + toFun a := ⟨(a, 1 - a), by simp_rw [mul_sub, mul_one, a.2.eq, sub_self], by rw [add_sub_cancel]⟩ + invFun a := ⟨a.1.1, (IsIdempotentElem.of_mul_add a.2.1 a.2.2).1⟩ + left_inv _ := rfl + right_inv a := Subtype.ext <| Prod.ext rfl <| sub_eq_of_eq_add <| a.2.2.symm.trans (add_comm ..) + map_rel_iff' := Iff.rfl + +end CommRing From 013b3e6508935eaeb5a5b7f40afd6a6564128361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 10 Jan 2025 22:02:05 +0000 Subject: [PATCH 147/681] chore: `initialize_simps_projections` for `Submodule` (#20582) From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang --- Mathlib/Algebra/Module/Submodule/Defs.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Mathlib/Algebra/Module/Submodule/Defs.lean b/Mathlib/Algebra/Module/Submodule/Defs.lean index e97327b911fae..6430f82524dff 100644 --- a/Mathlib/Algebra/Module/Submodule/Defs.lean +++ b/Mathlib/Algebra/Module/Submodule/Defs.lean @@ -93,16 +93,13 @@ theorem carrier_inj : p.carrier = q.carrier ↔ p = q := /-- Copy of a submodule with a new `carrier` equal to the old one. Useful to fix definitional equalities. -/ +@[simps] protected def copy (p : Submodule R M) (s : Set M) (hs : s = ↑p) : Submodule R M where carrier := s zero_mem' := by simpa [hs] using p.zero_mem' add_mem' := hs.symm ▸ p.add_mem' smul_mem' := by simpa [hs] using p.smul_mem' -@[simp] -theorem coe_copy (S : Submodule R M) (s : Set M) (hs : s = ↑S) : (S.copy s hs : Set M) = s := - rfl - theorem copy_eq (S : Submodule R M) (s : Set M) (hs : s = ↑S) : S.copy s hs = S := SetLike.coe_injective hs From 975040004a8ec20a37b6521171162c15e7d20924 Mon Sep 17 00:00:00 2001 From: grunweg Date: Fri, 10 Jan 2025 22:52:13 +0000 Subject: [PATCH 148/681] feat: three lemmas related to Hausdorff distance (#20585) From sphere-eversion, I'm just submitting these. Co-authored-by: grunweg Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> --- Mathlib/Topology/ContinuousOn.lean | 28 +++++++++++++ .../MetricSpace/HausdorffDistance.lean | 4 ++ Mathlib/Topology/MetricSpace/Thickening.lean | 39 +++++++++++++++++++ Mathlib/Topology/NhdsSet.lean | 13 ------- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/Mathlib/Topology/ContinuousOn.lean b/Mathlib/Topology/ContinuousOn.lean index 9147bdcc6b1f6..6765f06a8b8dc 100644 --- a/Mathlib/Topology/ContinuousOn.lean +++ b/Mathlib/Topology/ContinuousOn.lean @@ -1494,3 +1494,31 @@ lemma ContinuousOn.union_continuousAt continuousOn_of_forall_continuousAt <| fun _ hx => hx.elim (fun h => ContinuousWithinAt.continuousAt (continuousWithinAt hs h) <| IsOpen.mem_nhds s_op h) (ht _) + +/-- If `f` is continuous on some neighbourhood `s'` of `s` and `f` maps `s` to `t`, +the preimage of a set neighbourhood of `t` is a set neighbourhood of `s`. -/ +-- See `Continuous.tendsto_nhdsSet` for a special case. +theorem ContinuousOn.tendsto_nhdsSet {f : α → β} {s s' : Set α} {t : Set β} + (hf : ContinuousOn f s') (hs' : s' ∈ 𝓝ˢ s) (hst : MapsTo f s t) : Tendsto f (𝓝ˢ s) (𝓝ˢ t) := by + obtain ⟨V, hV, hsV, hVs'⟩ := mem_nhdsSet_iff_exists.mp hs' + refine ((hasBasis_nhdsSet s).tendsto_iff (hasBasis_nhdsSet t)).mpr fun U hU ↦ + ⟨V ∩ f ⁻¹' U, ?_, fun _ ↦ ?_⟩ + · exact ⟨(hf.mono hVs').isOpen_inter_preimage hV hU.1, + subset_inter hsV (hst.mono Subset.rfl hU.2)⟩ + · intro h + rw [← mem_preimage] + exact mem_of_mem_inter_right h + +/-- Preimage of a set neighborhood of `t` under a continuous map `f` is a set neighborhood of `s` +provided that `f` maps `s` to `t`. -/ +theorem Continuous.tendsto_nhdsSet {f : α → β} {t : Set β} (hf : Continuous f) + (hst : MapsTo f s t) : Tendsto f (𝓝ˢ s) (𝓝ˢ t) := + hf.continuousOn.tendsto_nhdsSet univ_mem hst + +lemma Continuous.tendsto_nhdsSet_nhds + {b : β} {f : α → β} (h : Continuous f) (h' : EqOn f (fun _ ↦ b) s) : + Tendsto f (𝓝ˢ s) (𝓝 b) := by + rw [← nhdsSet_singleton] + exact h.tendsto_nhdsSet h' + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Topology/MetricSpace/HausdorffDistance.lean b/Mathlib/Topology/MetricSpace/HausdorffDistance.lean index cb1ae246d0e34..b4e7c3196471b 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDistance.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDistance.lean @@ -535,6 +535,10 @@ theorem infDist_zero_of_mem_closure (hx : x ∈ closure s) : infDist x s = 0 := theorem mem_closure_iff_infDist_zero (h : s.Nonempty) : x ∈ closure s ↔ infDist x s = 0 := by simp [mem_closure_iff_infEdist_zero, infDist, ENNReal.toReal_eq_zero_iff, infEdist_ne_top h] +theorem infDist_pos_iff_not_mem_closure (hs : s.Nonempty) : + x ∉ closure s ↔ 0 < infDist x s := + (mem_closure_iff_infDist_zero hs).not.trans infDist_nonneg.gt_iff_ne.symm + /-- Given a closed set `s`, a point belongs to `s` iff its infimum distance to this set vanishes -/ theorem _root_.IsClosed.mem_iff_infDist_zero (h : IsClosed s) (hs : s.Nonempty) : x ∈ s ↔ infDist x s = 0 := by rw [← mem_closure_iff_infDist_zero hs, h.closure_eq] diff --git a/Mathlib/Topology/MetricSpace/Thickening.lean b/Mathlib/Topology/MetricSpace/Thickening.lean index 67b4aa3b257bc..1b6948339b681 100644 --- a/Mathlib/Topology/MetricSpace/Thickening.lean +++ b/Mathlib/Topology/MetricSpace/Thickening.lean @@ -80,6 +80,7 @@ theorem thickening_of_nonpos (hδ : δ ≤ 0) (s : Set α) : thickening δ s = /-- The (open) thickening `Metric.thickening δ E` of a fixed subset `E` is an increasing function of the thickening radius `δ`. -/ +@[gcongr] theorem thickening_mono {δ₁ δ₂ : ℝ} (hle : δ₁ ≤ δ₂) (E : Set α) : thickening δ₁ E ⊆ thickening δ₂ E := preimage_mono (Iio_subset_Iio (ENNReal.ofReal_le_ofReal hle)) @@ -631,4 +632,42 @@ theorem frontier_cthickening_disjoint (A : Set α) : end Cthickening +theorem thickening_ball [PseudoMetricSpace α] (x : α) (ε δ : ℝ) : + thickening ε (ball x δ) ⊆ ball x (ε + δ) := by + rw [← thickening_singleton, ← thickening_singleton] + apply thickening_thickening_subset + end Metric + +open Metric in +theorem IsCompact.exists_thickening_image_subset + [PseudoEMetricSpace α] {β : Type*} [PseudoEMetricSpace β] + {f : α → β} {K : Set α} {U : Set β} (hK : IsCompact K) (ho : IsOpen U) + (hf : ∀ x ∈ K, ContinuousAt f x) (hKU : MapsTo f K U) : + ∃ ε > 0, ∃ V ∈ 𝓝ˢ K, thickening ε (f '' V) ⊆ U := by + apply hK.induction_on (p := fun K ↦ ∃ ε > 0, ∃ V ∈ 𝓝ˢ K, thickening ε (f '' V) ⊆ U) + · use 1, by positivity, ∅, by simp, by simp + · exact fun s t hst ⟨ε, hε, V, hV, hthickening⟩ ↦ ⟨ε, hε, V, nhdsSet_mono hst hV, hthickening⟩ + · rintro s t ⟨ε₁, hε₁, V₁, hV₁, hV₁thickening⟩ ⟨ε₂, hε₂, V₂, hV₂, hV₂thickening⟩ + refine ⟨min ε₁ ε₂, by positivity, V₁ ∪ V₂, union_mem_nhdsSet hV₁ hV₂, ?_⟩ + rw [image_union, thickening_union] + calc thickening (ε₁ ⊓ ε₂) (f '' V₁) ∪ thickening (ε₁ ⊓ ε₂) (f '' V₂) + _ ⊆ thickening ε₁ (f '' V₁) ∪ thickening ε₂ (f '' V₂) := by gcongr <;> norm_num + _ ⊆ U ∪ U := by gcongr + _ = U := union_self _ + · intro x hx + have : {f x} ⊆ U := by rw [singleton_subset_iff]; exact hKU hx + obtain ⟨δ, hδ, hthick⟩ := (isCompact_singleton (x := f x)).exists_thickening_subset_open ho this + let V := f ⁻¹' (thickening (δ / 2) {f x}) + have : V ∈ 𝓝 x := by + apply hf x hx + apply isOpen_thickening.mem_nhds + exact (self_subset_thickening (by positivity) _) rfl + refine ⟨K ∩ (interior V), inter_mem_nhdsWithin K (interior_mem_nhds.mpr this), + δ / 2, by positivity, V, by rw [← subset_interior_iff_mem_nhdsSet]; simp, ?_⟩ + calc thickening (δ / 2) (f '' V) + _ ⊆ thickening (δ / 2) (thickening (δ / 2) {f x}) := + thickening_subset_of_subset _ (image_preimage_subset f _) + _ ⊆ thickening ((δ / 2) + (δ / 2)) ({f x}) := + thickening_thickening_subset (δ / 2) (δ / 2) {f x} + _ ⊆ U := by simp [hthick] diff --git a/Mathlib/Topology/NhdsSet.lean b/Mathlib/Topology/NhdsSet.lean index f0aa111474378..e6c6ae3a6144f 100644 --- a/Mathlib/Topology/NhdsSet.lean +++ b/Mathlib/Topology/NhdsSet.lean @@ -143,19 +143,6 @@ theorem union_mem_nhdsSet (h₁ : s₁ ∈ 𝓝ˢ t₁) (h₂ : s₂ ∈ 𝓝ˢ theorem nhdsSet_insert (x : X) (s : Set X) : 𝓝ˢ (insert x s) = 𝓝 x ⊔ 𝓝ˢ s := by rw [insert_eq, nhdsSet_union, nhdsSet_singleton] -/-- Preimage of a set neighborhood of `t` under a continuous map `f` is a set neighborhood of `s` -provided that `f` maps `s` to `t`. -/ -theorem Continuous.tendsto_nhdsSet {f : X → Y} {t : Set Y} (hf : Continuous f) - (hst : MapsTo f s t) : Tendsto f (𝓝ˢ s) (𝓝ˢ t) := - ((hasBasis_nhdsSet s).tendsto_iff (hasBasis_nhdsSet t)).mpr fun U hU => - ⟨f ⁻¹' U, ⟨hU.1.preimage hf, hst.mono Subset.rfl hU.2⟩, fun _ => id⟩ - -lemma Continuous.tendsto_nhdsSet_nhds - {y : Y} {f : X → Y} (h : Continuous f) (h' : EqOn f (fun _ ↦ y) s) : - Tendsto f (𝓝ˢ s) (𝓝 y) := by - rw [← nhdsSet_singleton] - exact h.tendsto_nhdsSet h' - /- This inequality cannot be improved to an equality. For instance, if `X` has two elements and the coarse topology and `s` and `t` are distinct singletons then `𝓝ˢ (s ∩ t) = ⊥` while `𝓝ˢ s ⊓ 𝓝ˢ t = ⊤` and those are different. -/ From 64c71eb15f46221d81117ab02662046973e7e179 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Sat, 11 Jan 2025 00:45:45 +0000 Subject: [PATCH 149/681] chore: split `Mathlib/Algebra/Group/Int` (#20624) Follows the existing split for `Mathlib/Algebra/Group/Nat`. Co-authored-by: Matthew Ballard --- Mathlib.lean | 7 +- .../Algebra/BigOperators/Group/Finset.lean | 1 + .../BigOperators/Group/List/Basic.lean | 6 +- .../BigOperators/Group/List/Lemmas.lean | 3 +- Mathlib/Algebra/EuclideanDomain/Int.lean | 1 + Mathlib/Algebra/Group/Int.lean | 233 ------------------ Mathlib/Algebra/Group/Int/Defs.lean | 73 ++++++ Mathlib/Algebra/Group/Int/Even.lean | 90 +++++++ Mathlib/Algebra/Group/Int/TypeTags.lean | 30 +++ Mathlib/Algebra/Group/Int/Units.lean | 92 +++++++ .../Group/Nat/{Basic.lean => Defs.lean} | 0 Mathlib/Algebra/Group/Nat/Even.lean | 2 +- Mathlib/Algebra/Group/Nat/TypeTags.lean | 2 +- Mathlib/Algebra/Group/Nat/Units.lean | 2 +- .../Algebra/Group/Subgroup/ZPowers/Basic.lean | 2 +- .../Algebra/Group/Submonoid/Operations.lean | 2 +- Mathlib/Algebra/GroupPower/IterateHom.lean | 3 +- Mathlib/Algebra/GroupWithZero/Nat.lean | 2 +- Mathlib/Algebra/Order/Floor.lean | 3 +- Mathlib/Algebra/Order/Group/Int.lean | 2 +- Mathlib/Algebra/Order/Group/Multiset.lean | 2 +- Mathlib/Algebra/Order/Group/Nat.lean | 2 +- .../Algebra/Order/Group/Unbundled/Int.lean | 2 +- Mathlib/Algebra/Ring/Int/Defs.lean | 4 +- Mathlib/Algebra/Ring/Int/Parity.lean | 1 + Mathlib/Algebra/Ring/Int/Units.lean | 1 + Mathlib/Algebra/Ring/Rat.lean | 1 + Mathlib/CategoryTheory/GradedObject.lean | 2 +- Mathlib/Data/Finset/Image.lean | 4 +- Mathlib/Data/Finset/SymmDiff.lean | 3 +- Mathlib/Data/Fintype/Basic.lean | 1 + Mathlib/Data/Fintype/Parity.lean | 1 + Mathlib/Data/Int/GCD.lean | 2 +- Mathlib/Data/Int/NatPrime.lean | 2 +- Mathlib/Data/List/SplitLengths.lean | 2 +- Mathlib/Data/Nat/Bits.lean | 2 +- Mathlib/Data/Nat/PSub.lean | 2 +- Mathlib/Data/Nat/Prime/Int.lean | 1 + Mathlib/Data/Ordmap/Ordset.lean | 1 - Mathlib/Data/Set/Enumerate.lean | 2 +- Mathlib/GroupTheory/FreeGroup/Basic.lean | 1 - Mathlib/Order/Hom/CompleteLattice.lean | 2 +- .../DedekindDomain/SelmerGroup.lean | 1 + Mathlib/RingTheory/LaurentSeries.lean | 1 + Mathlib/Tactic/Sat/FromLRAT.lean | 2 +- MathlibTest/levenshtein.lean | 2 +- 46 files changed, 335 insertions(+), 268 deletions(-) delete mode 100644 Mathlib/Algebra/Group/Int.lean create mode 100644 Mathlib/Algebra/Group/Int/Defs.lean create mode 100644 Mathlib/Algebra/Group/Int/Even.lean create mode 100644 Mathlib/Algebra/Group/Int/TypeTags.lean create mode 100644 Mathlib/Algebra/Group/Int/Units.lean rename Mathlib/Algebra/Group/Nat/{Basic.lean => Defs.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 842bce26f64ba..e259e13653ae7 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -295,11 +295,14 @@ import Mathlib.Algebra.Group.Hom.End import Mathlib.Algebra.Group.Hom.Instances import Mathlib.Algebra.Group.Indicator import Mathlib.Algebra.Group.InjSurj -import Mathlib.Algebra.Group.Int +import Mathlib.Algebra.Group.Int.Defs +import Mathlib.Algebra.Group.Int.Even +import Mathlib.Algebra.Group.Int.TypeTags +import Mathlib.Algebra.Group.Int.Units import Mathlib.Algebra.Group.Invertible.Basic import Mathlib.Algebra.Group.Invertible.Defs import Mathlib.Algebra.Group.MinimalAxioms -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Group.Nat.Even import Mathlib.Algebra.Group.Nat.TypeTags import Mathlib.Algebra.Group.Nat.Units diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index 0d3b302694ee2..c7a1990d9cf1c 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Algebra.Group.Indicator +import Mathlib.Algebra.Group.Even import Mathlib.Data.Finset.Piecewise import Mathlib.Data.Finset.Powerset import Mathlib.Data.Finset.Preimage diff --git a/Mathlib/Algebra/BigOperators/Group/List/Basic.lean b/Mathlib/Algebra/BigOperators/Group/List/Basic.lean index 108d82d3138cd..17499ca3064d6 100644 --- a/Mathlib/Algebra/BigOperators/Group/List/Basic.lean +++ b/Mathlib/Algebra/BigOperators/Group/List/Basic.lean @@ -3,6 +3,8 @@ 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, Floris van Doorn, Sébastien Gouëzel, Alex J. Best -/ +import Mathlib.Algebra.Divisibility.Basic +import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.BigOperators.Group.List.Defs import Mathlib.Order.RelClasses import Mathlib.Data.List.Basic @@ -10,8 +12,8 @@ import Mathlib.Data.List.Forall2 import Mathlib.Data.List.Perm.Basic import Mathlib.Algebra.Group.Basic import Mathlib.Algebra.Group.Commute.Defs -import Mathlib.Algebra.Group.Hom.Defs -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs +import Mathlib.Algebra.Group.Int.Defs /-! # Sums and products from lists diff --git a/Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean b/Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean index 737c13893b736..0b1fac94d6687 100644 --- a/Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean +++ b/Mathlib/Algebra/BigOperators/Group/List/Lemmas.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Floris van Doorn, Sébastien Gouëzel, Alex J. Best -/ import Mathlib.Algebra.BigOperators.Group.List.Basic import Mathlib.Algebra.Divisibility.Basic -import Mathlib.Algebra.Group.Int +import Mathlib.Algebra.Group.Int.Units import Mathlib.Data.List.Dedup import Mathlib.Data.List.Flatten import Mathlib.Data.List.Pairwise @@ -13,6 +13,7 @@ import Mathlib.Data.List.Perm.Basic import Mathlib.Data.List.Range import Mathlib.Data.List.Rotate import Mathlib.Data.List.ProdSigma +import Mathlib.Algebra.Group.Opposite /-! # Sums and products from lists diff --git a/Mathlib/Algebra/EuclideanDomain/Int.lean b/Mathlib/Algebra/EuclideanDomain/Int.lean index cf153272fea14..d3efb38e7823a 100644 --- a/Mathlib/Algebra/EuclideanDomain/Int.lean +++ b/Mathlib/Algebra/EuclideanDomain/Int.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Louis Carlin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Louis Carlin, Mario Carneiro -/ +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.EuclideanDomain.Defs import Mathlib.Algebra.Order.Group.Unbundled.Int import Mathlib.Algebra.Ring.Int.Defs diff --git a/Mathlib/Algebra/Group/Int.lean b/Mathlib/Algebra/Group/Int.lean deleted file mode 100644 index d2c72a3f581ca..0000000000000 --- a/Mathlib/Algebra/Group/Int.lean +++ /dev/null @@ -1,233 +0,0 @@ -/- -Copyright (c) 2016 Jeremy Avigad. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jeremy Avigad --/ -import Mathlib.Algebra.Group.Nat.Even -import Mathlib.Algebra.Group.Nat.Units -import Mathlib.Algebra.Group.Units.Basic -import Mathlib.Data.Int.Sqrt - -/-! -# The integers form a group - -This file contains the additive group and multiplicative monoid instances on the integers. - -See note [foundational algebra order theory]. --/ - -assert_not_exists DenselyOrdered -assert_not_exists Ring -assert_not_exists Set.range - -open Nat - -namespace Int - -/-! ### Instances -/ - -instance instCommMonoid : CommMonoid ℤ where - mul_comm := Int.mul_comm - mul_one := Int.mul_one - one_mul := Int.one_mul - npow n x := x ^ n - npow_zero _ := rfl - npow_succ _ _ := rfl - mul_assoc := Int.mul_assoc - -instance instAddCommGroup : AddCommGroup ℤ where - add_comm := Int.add_comm - add_assoc := Int.add_assoc - add_zero := Int.add_zero - zero_add := Int.zero_add - neg_add_cancel := Int.add_left_neg - nsmul := (·*·) - nsmul_zero := Int.zero_mul - nsmul_succ n x := - show (n + 1 : ℤ) * x = n * x + x - by rw [Int.add_mul, Int.one_mul] - zsmul := (·*·) - zsmul_zero' := Int.zero_mul - zsmul_succ' m n := by - simp only [ofNat_succ, Int.add_mul, Int.add_comm, Int.one_mul] - zsmul_neg' m n := by simp only [negSucc_coe, ofNat_succ, Int.neg_mul] - sub_eq_add_neg _ _ := Int.sub_eq_add_neg - -/-! -### Extra instances to short-circuit type class resolution - -These also prevent non-computable instances like `Int.instNormedCommRing` being used to construct -these instances non-computably. --/ - -instance instAddCommMonoid : AddCommMonoid ℤ := by infer_instance -instance instAddMonoid : AddMonoid ℤ := by infer_instance -instance instMonoid : Monoid ℤ := by infer_instance -instance instCommSemigroup : CommSemigroup ℤ := by infer_instance -instance instSemigroup : Semigroup ℤ := by infer_instance -instance instAddGroup : AddGroup ℤ := by infer_instance -instance instAddCommSemigroup : AddCommSemigroup ℤ := by infer_instance -instance instAddSemigroup : AddSemigroup ℤ := by infer_instance - -/-! ### Miscellaneous lemmas -/ - -section Multiplicative - -open Multiplicative - -lemma toAdd_pow (a : Multiplicative ℤ) (b : ℕ) : (a ^ b).toAdd = a.toAdd * b := mul_comm _ _ - -lemma toAdd_zpow (a : Multiplicative ℤ) (b : ℤ) : (a ^ b).toAdd = a.toAdd * b := mul_comm _ _ - -@[simp] lemma ofAdd_mul (a b : ℤ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_zpow ..).symm - -end Multiplicative - -/-! #### Units -/ - -variable {u v : ℤ} - -lemma units_natAbs (u : ℤˣ) : natAbs u = 1 := - Units.ext_iff.1 <| - Nat.units_eq_one - ⟨natAbs u, natAbs ↑u⁻¹, by rw [← natAbs_mul, Units.mul_inv]; rfl, by - rw [← natAbs_mul, Units.inv_mul]; rfl⟩ - -@[simp] lemma natAbs_of_isUnit (hu : IsUnit u) : natAbs u = 1 := units_natAbs hu.unit - -lemma isUnit_eq_one_or (hu : IsUnit u) : u = 1 ∨ u = -1 := by - simpa only [natAbs_of_isUnit hu] using natAbs_eq u - -lemma isUnit_ne_iff_eq_neg (hu : IsUnit u) (hv : IsUnit v) : u ≠ v ↔ u = -v := by - obtain rfl | rfl := isUnit_eq_one_or hu <;> obtain rfl | rfl := isUnit_eq_one_or hv <;> decide - -lemma isUnit_eq_or_eq_neg (hu : IsUnit u) (hv : IsUnit v) : u = v ∨ u = -v := - or_iff_not_imp_left.2 (isUnit_ne_iff_eq_neg hu hv).1 - -lemma isUnit_iff : IsUnit u ↔ u = 1 ∨ u = -1 := by - refine ⟨fun h ↦ isUnit_eq_one_or h, fun h ↦ ?_⟩ - rcases h with (rfl | rfl) - · exact isUnit_one - · exact ⟨⟨-1, -1, by decide, by decide⟩, rfl⟩ - -lemma eq_one_or_neg_one_of_mul_eq_one (h : u * v = 1) : u = 1 ∨ u = -1 := - isUnit_iff.1 (isUnit_of_mul_eq_one u v h) - -lemma eq_one_or_neg_one_of_mul_eq_one' (h : u * v = 1) : u = 1 ∧ v = 1 ∨ u = -1 ∧ v = -1 := by - have h' : v * u = 1 := mul_comm u v ▸ h - obtain rfl | rfl := eq_one_or_neg_one_of_mul_eq_one h <;> - obtain rfl | rfl := eq_one_or_neg_one_of_mul_eq_one h' <;> tauto - -lemma eq_of_mul_eq_one (h : u * v = 1) : u = v := - (eq_one_or_neg_one_of_mul_eq_one' h).elim - (and_imp.2 (·.trans ·.symm)) (and_imp.2 (·.trans ·.symm)) - -lemma mul_eq_one_iff_eq_one_or_neg_one : u * v = 1 ↔ u = 1 ∧ v = 1 ∨ u = -1 ∧ v = -1 := by - refine ⟨eq_one_or_neg_one_of_mul_eq_one', fun h ↦ Or.elim h (fun H ↦ ?_) fun H ↦ ?_⟩ <;> - obtain ⟨rfl, rfl⟩ := H <;> rfl - -lemma eq_one_or_neg_one_of_mul_eq_neg_one' (h : u * v = -1) : u = 1 ∧ v = -1 ∨ u = -1 ∧ v = 1 := by - obtain rfl | rfl := isUnit_eq_one_or (IsUnit.mul_iff.mp (Int.isUnit_iff.mpr (Or.inr h))).1 - · exact Or.inl ⟨rfl, one_mul v ▸ h⟩ - · simpa [Int.neg_mul] using h - -lemma mul_eq_neg_one_iff_eq_one_or_neg_one : u * v = -1 ↔ u = 1 ∧ v = -1 ∨ u = -1 ∧ v = 1 := by - refine ⟨eq_one_or_neg_one_of_mul_eq_neg_one', fun h ↦ Or.elim h (fun H ↦ ?_) fun H ↦ ?_⟩ <;> - obtain ⟨rfl, rfl⟩ := H <;> rfl - -lemma isUnit_iff_natAbs_eq : IsUnit u ↔ u.natAbs = 1 := by simp [natAbs_eq_iff, isUnit_iff] - -alias ⟨IsUnit.natAbs_eq, _⟩ := isUnit_iff_natAbs_eq - --- Porting note: `rw` didn't work on `natAbs_ofNat`, so had to change to `simp`, --- presumably because `(n : ℤ)` is `Nat.cast` and not just `ofNat` -@[norm_cast] -lemma ofNat_isUnit {n : ℕ} : IsUnit (n : ℤ) ↔ IsUnit n := by simp [isUnit_iff_natAbs_eq] - -lemma isUnit_mul_self (hu : IsUnit u) : u * u = 1 := - (isUnit_eq_one_or hu).elim (fun h ↦ h.symm ▸ rfl) fun h ↦ h.symm ▸ rfl - -lemma isUnit_add_isUnit_eq_isUnit_add_isUnit {a b c d : ℤ} (ha : IsUnit a) (hb : IsUnit b) - (hc : IsUnit c) (hd : IsUnit d) : a + b = c + d ↔ a = c ∧ b = d ∨ a = d ∧ b = c := by - rw [isUnit_iff] at ha hb hc hd - aesop - -lemma eq_one_or_neg_one_of_mul_eq_neg_one (h : u * v = -1) : u = 1 ∨ u = -1 := - Or.elim (eq_one_or_neg_one_of_mul_eq_neg_one' h) (fun H => Or.inl H.1) fun H => Or.inr H.1 - -/-! #### Parity -/ - -variable {m n : ℤ} - -@[simp] lemma emod_two_ne_one : ¬n % 2 = 1 ↔ n % 2 = 0 := by - cases' emod_two_eq_zero_or_one n with h h <;> simp [h] - -@[simp] lemma one_emod_two : (1 : Int) % 2 = 1 := rfl - --- `EuclideanDomain.mod_eq_zero` uses (2 ∣ n) as normal form -@[local simp] lemma emod_two_ne_zero : ¬n % 2 = 0 ↔ n % 2 = 1 := by - cases' emod_two_eq_zero_or_one n with h h <;> simp [h] - -lemma even_iff : Even n ↔ n % 2 = 0 where - mp := fun ⟨m, hm⟩ ↦ by simp [← Int.two_mul, hm] - mpr h := ⟨n / 2, (emod_add_ediv n 2).symm.trans (by simp [← Int.two_mul, h])⟩ - -lemma not_even_iff : ¬Even n ↔ n % 2 = 1 := by rw [even_iff, emod_two_ne_zero] - -@[simp] lemma two_dvd_ne_zero : ¬2 ∣ n ↔ n % 2 = 1 := - (even_iff_exists_two_nsmul _).symm.not.trans not_even_iff - -instance : DecidablePred (Even : ℤ → Prop) := fun _ ↦ decidable_of_iff _ even_iff.symm - -/-- `IsSquare` can be decided on `ℤ` by checking against the square root. -/ -instance : DecidablePred (IsSquare : ℤ → Prop) := - fun m ↦ decidable_of_iff' (sqrt m * sqrt m = m) <| by - simp_rw [← exists_mul_self m, IsSquare, eq_comm] - -@[simp] lemma not_even_one : ¬Even (1 : ℤ) := by simp [even_iff] - -@[parity_simps] lemma even_add : Even (m + n) ↔ (Even m ↔ Even n) := by - cases' emod_two_eq_zero_or_one m with h₁ h₁ <;> - cases' emod_two_eq_zero_or_one n with h₂ h₂ <;> - simp [even_iff, h₁, h₂, Int.add_emod, one_add_one_eq_two, emod_self] - -lemma two_not_dvd_two_mul_add_one (n : ℤ) : ¬2 ∣ 2 * n + 1 := by simp [add_emod] - -@[parity_simps] -lemma even_sub : Even (m - n) ↔ (Even m ↔ Even n) := by simp [sub_eq_add_neg, parity_simps] - -@[parity_simps] lemma even_add_one : Even (n + 1) ↔ ¬Even n := by simp [even_add] - -@[parity_simps] lemma even_sub_one : Even (n - 1) ↔ ¬Even n := by simp [even_sub] - -@[parity_simps] lemma even_mul : Even (m * n) ↔ Even m ∨ Even n := by - cases' emod_two_eq_zero_or_one m with h₁ h₁ <;> - cases' emod_two_eq_zero_or_one n with h₂ h₂ <;> - simp [even_iff, h₁, h₂, Int.mul_emod] - -@[parity_simps] lemma even_pow {n : ℕ} : Even (m ^ n) ↔ Even m ∧ n ≠ 0 := by - induction n <;> simp [*, even_mul, pow_succ]; tauto - -lemma even_pow' {n : ℕ} (h : n ≠ 0) : Even (m ^ n) ↔ Even m := even_pow.trans <| and_iff_left h - -@[simp, norm_cast] lemma even_coe_nat (n : ℕ) : Even (n : ℤ) ↔ Even n := by - rw_mod_cast [even_iff, Nat.even_iff] - -lemma two_mul_ediv_two_of_even : Even n → 2 * (n / 2) = n := - fun h ↦ Int.mul_ediv_cancel' ((even_iff_exists_two_nsmul _).mp h) - -lemma ediv_two_mul_two_of_even : Even n → n / 2 * 2 = n := - fun h ↦ Int.ediv_mul_cancel ((even_iff_exists_two_nsmul _).mp h) - --- Here are examples of how `parity_simps` can be used with `Int`. -example (m n : ℤ) (h : Even m) : ¬Even (n + 3) ↔ Even (m ^ 2 + m + n) := by - simp +decide [*, (by decide : ¬2 = 0), parity_simps] - -example : ¬Even (25394535 : ℤ) := by decide - -end Int - --- TODO: Do we really need this lemma? This is just `smul_eq_mul` -lemma zsmul_int_int (a b : ℤ) : a • b = a * b := rfl - -lemma zsmul_int_one (n : ℤ) : n • (1 : ℤ) = n := mul_one _ diff --git a/Mathlib/Algebra/Group/Int/Defs.lean b/Mathlib/Algebra/Group/Int/Defs.lean new file mode 100644 index 0000000000000..8115336b8b189 --- /dev/null +++ b/Mathlib/Algebra/Group/Int/Defs.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad +-/ +import Mathlib.Algebra.Group.Defs + +/-! +# The integers form a group + +This file contains the additive group and multiplicative monoid instances on the integers. + +See note [foundational algebra order theory]. +-/ + +assert_not_exists Ring +assert_not_exists DenselyOrdered + +open Nat + +namespace Int + +/-! ### Instances -/ + +instance instCommMonoid : CommMonoid ℤ where + mul_comm := Int.mul_comm + mul_one := Int.mul_one + one_mul := Int.one_mul + npow n x := x ^ n + npow_zero _ := rfl + npow_succ _ _ := rfl + mul_assoc := Int.mul_assoc + +instance instAddCommGroup : AddCommGroup ℤ where + add_comm := Int.add_comm + add_assoc := Int.add_assoc + add_zero := Int.add_zero + zero_add := Int.zero_add + neg_add_cancel := Int.add_left_neg + nsmul := (·*·) + nsmul_zero := Int.zero_mul + nsmul_succ n x := + show (n + 1 : ℤ) * x = n * x + x + by rw [Int.add_mul, Int.one_mul] + zsmul := (·*·) + zsmul_zero' := Int.zero_mul + zsmul_succ' m n := by + simp only [ofNat_succ, Int.add_mul, Int.add_comm, Int.one_mul] + zsmul_neg' m n := by simp only [negSucc_coe, ofNat_succ, Int.neg_mul] + sub_eq_add_neg _ _ := Int.sub_eq_add_neg + +/-! +### Extra instances to short-circuit type class resolution + +These also prevent non-computable instances like `Int.instNormedCommRing` being used to construct +these instances non-computably. +-/ + +instance instAddCommMonoid : AddCommMonoid ℤ := by infer_instance +instance instAddMonoid : AddMonoid ℤ := by infer_instance +instance instMonoid : Monoid ℤ := by infer_instance +instance instCommSemigroup : CommSemigroup ℤ := by infer_instance +instance instSemigroup : Semigroup ℤ := by infer_instance +instance instAddGroup : AddGroup ℤ := by infer_instance +instance instAddCommSemigroup : AddCommSemigroup ℤ := by infer_instance +instance instAddSemigroup : AddSemigroup ℤ := by infer_instance + +end Int + +-- TODO: Do we really need this lemma? This is just `smul_eq_mul` +lemma zsmul_int_int (a b : ℤ) : a • b = a * b := rfl + +lemma zsmul_int_one (n : ℤ) : n • (1 : ℤ) = n := mul_one _ diff --git a/Mathlib/Algebra/Group/Int/Even.lean b/Mathlib/Algebra/Group/Int/Even.lean new file mode 100644 index 0000000000000..6feb1cec66adf --- /dev/null +++ b/Mathlib/Algebra/Group/Int/Even.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad +-/ +import Mathlib.Algebra.Group.Int.Defs +import Mathlib.Algebra.Group.Nat.Even +import Mathlib.Algebra.Group.Nat.Units +import Mathlib.Algebra.Group.Units.Basic +import Mathlib.Data.Int.Sqrt + +/-! +# Parity of integers +-/ + +open Nat + +namespace Int + +/-! #### Parity -/ + +variable {m n : ℤ} + +@[simp] lemma emod_two_ne_one : ¬n % 2 = 1 ↔ n % 2 = 0 := by + cases' emod_two_eq_zero_or_one n with h h <;> simp [h] + +@[simp] lemma one_emod_two : (1 : Int) % 2 = 1 := rfl + +-- `EuclideanDomain.mod_eq_zero` uses (2 ∣ n) as normal form +@[local simp] lemma emod_two_ne_zero : ¬n % 2 = 0 ↔ n % 2 = 1 := by + cases' emod_two_eq_zero_or_one n with h h <;> simp [h] + +lemma even_iff : Even n ↔ n % 2 = 0 where + mp := fun ⟨m, hm⟩ ↦ by simp [← Int.two_mul, hm] + mpr h := ⟨n / 2, (emod_add_ediv n 2).symm.trans (by simp [← Int.two_mul, h])⟩ + +lemma not_even_iff : ¬Even n ↔ n % 2 = 1 := by rw [even_iff, emod_two_ne_zero] + +@[simp] lemma two_dvd_ne_zero : ¬2 ∣ n ↔ n % 2 = 1 := + (even_iff_exists_two_nsmul _).symm.not.trans not_even_iff + +instance : DecidablePred (Even : ℤ → Prop) := fun _ ↦ decidable_of_iff _ even_iff.symm + +/-- `IsSquare` can be decided on `ℤ` by checking against the square root. -/ +instance : DecidablePred (IsSquare : ℤ → Prop) := + fun m ↦ decidable_of_iff' (sqrt m * sqrt m = m) <| by + simp_rw [← exists_mul_self m, IsSquare, eq_comm] + +@[simp] lemma not_even_one : ¬Even (1 : ℤ) := by simp [even_iff] + +@[parity_simps] lemma even_add : Even (m + n) ↔ (Even m ↔ Even n) := by + cases' emod_two_eq_zero_or_one m with h₁ h₁ <;> + cases' emod_two_eq_zero_or_one n with h₂ h₂ <;> + simp [even_iff, h₁, h₂, Int.add_emod, one_add_one_eq_two, emod_self] + +lemma two_not_dvd_two_mul_add_one (n : ℤ) : ¬2 ∣ 2 * n + 1 := by simp [add_emod] + +@[parity_simps] +lemma even_sub : Even (m - n) ↔ (Even m ↔ Even n) := by simp [sub_eq_add_neg, parity_simps] + +@[parity_simps] lemma even_add_one : Even (n + 1) ↔ ¬Even n := by simp [even_add] + +@[parity_simps] lemma even_sub_one : Even (n - 1) ↔ ¬Even n := by simp [even_sub] + +@[parity_simps] lemma even_mul : Even (m * n) ↔ Even m ∨ Even n := by + cases' emod_two_eq_zero_or_one m with h₁ h₁ <;> + cases' emod_two_eq_zero_or_one n with h₂ h₂ <;> + simp [even_iff, h₁, h₂, Int.mul_emod] + +@[parity_simps] lemma even_pow {n : ℕ} : Even (m ^ n) ↔ Even m ∧ n ≠ 0 := by + induction n <;> simp [*, even_mul, pow_succ]; tauto + +lemma even_pow' {n : ℕ} (h : n ≠ 0) : Even (m ^ n) ↔ Even m := even_pow.trans <| and_iff_left h + +@[simp, norm_cast] lemma even_coe_nat (n : ℕ) : Even (n : ℤ) ↔ Even n := by + rw_mod_cast [even_iff, Nat.even_iff] + +lemma two_mul_ediv_two_of_even : Even n → 2 * (n / 2) = n := + fun h ↦ Int.mul_ediv_cancel' ((even_iff_exists_two_nsmul _).mp h) + +lemma ediv_two_mul_two_of_even : Even n → n / 2 * 2 = n := + fun h ↦ Int.ediv_mul_cancel ((even_iff_exists_two_nsmul _).mp h) + +-- Here are examples of how `parity_simps` can be used with `Int`. +example (m n : ℤ) (h : Even m) : ¬Even (n + 3) ↔ Even (m ^ 2 + m + n) := by + simp +decide [*, (by decide : ¬2 = 0), parity_simps] + +example : ¬Even (25394535 : ℤ) := by decide + +end Int diff --git a/Mathlib/Algebra/Group/Int/TypeTags.lean b/Mathlib/Algebra/Group/Int/TypeTags.lean new file mode 100644 index 0000000000000..42958ea577c40 --- /dev/null +++ b/Mathlib/Algebra/Group/Int/TypeTags.lean @@ -0,0 +1,30 @@ +/- +Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad +-/ +import Mathlib.Algebra.Group.Int.Defs +import Mathlib.Algebra.Group.TypeTags.Basic + +/-! +# Lemmas about `Multiplicative ℤ`. +-/ + + +open Nat + +namespace Int + +section Multiplicative + +open Multiplicative + +lemma toAdd_pow (a : Multiplicative ℤ) (b : ℕ) : (a ^ b).toAdd = a.toAdd * b := mul_comm _ _ + +lemma toAdd_zpow (a : Multiplicative ℤ) (b : ℤ) : (a ^ b).toAdd = a.toAdd * b := mul_comm _ _ + +@[simp] lemma ofAdd_mul (a b : ℤ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_zpow ..).symm + +end Multiplicative + +end Int diff --git a/Mathlib/Algebra/Group/Int/Units.lean b/Mathlib/Algebra/Group/Int/Units.lean new file mode 100644 index 0000000000000..c5628f529793e --- /dev/null +++ b/Mathlib/Algebra/Group/Int/Units.lean @@ -0,0 +1,92 @@ +/- +Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad +-/ +import Mathlib.Tactic.Tauto +import Mathlib.Algebra.Group.Int.Defs +import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.Group.Nat.Units + +/-! +# Units in the integers +-/ + + +open Nat + +namespace Int + +/-! #### Units -/ + +variable {u v : ℤ} + +lemma units_natAbs (u : ℤˣ) : natAbs u = 1 := + Units.ext_iff.1 <| + Nat.units_eq_one + ⟨natAbs u, natAbs ↑u⁻¹, by rw [← natAbs_mul, Units.mul_inv]; rfl, by + rw [← natAbs_mul, Units.inv_mul]; rfl⟩ + +@[simp] lemma natAbs_of_isUnit (hu : IsUnit u) : natAbs u = 1 := units_natAbs hu.unit + +lemma isUnit_eq_one_or (hu : IsUnit u) : u = 1 ∨ u = -1 := by + simpa only [natAbs_of_isUnit hu] using natAbs_eq u + +lemma isUnit_ne_iff_eq_neg (hu : IsUnit u) (hv : IsUnit v) : u ≠ v ↔ u = -v := by + obtain rfl | rfl := isUnit_eq_one_or hu <;> obtain rfl | rfl := isUnit_eq_one_or hv <;> decide + +lemma isUnit_eq_or_eq_neg (hu : IsUnit u) (hv : IsUnit v) : u = v ∨ u = -v := + or_iff_not_imp_left.2 (isUnit_ne_iff_eq_neg hu hv).1 + +lemma isUnit_iff : IsUnit u ↔ u = 1 ∨ u = -1 := by + refine ⟨fun h ↦ isUnit_eq_one_or h, fun h ↦ ?_⟩ + rcases h with (rfl | rfl) + · exact isUnit_one + · exact ⟨⟨-1, -1, by decide, by decide⟩, rfl⟩ + +lemma eq_one_or_neg_one_of_mul_eq_one (h : u * v = 1) : u = 1 ∨ u = -1 := + isUnit_iff.1 (isUnit_of_mul_eq_one u v h) + +lemma eq_one_or_neg_one_of_mul_eq_one' (h : u * v = 1) : u = 1 ∧ v = 1 ∨ u = -1 ∧ v = -1 := by + have h' : v * u = 1 := mul_comm u v ▸ h + obtain rfl | rfl := eq_one_or_neg_one_of_mul_eq_one h <;> + obtain rfl | rfl := eq_one_or_neg_one_of_mul_eq_one h' <;> tauto + +lemma eq_of_mul_eq_one (h : u * v = 1) : u = v := + (eq_one_or_neg_one_of_mul_eq_one' h).elim + (and_imp.2 (·.trans ·.symm)) (and_imp.2 (·.trans ·.symm)) + +lemma mul_eq_one_iff_eq_one_or_neg_one : u * v = 1 ↔ u = 1 ∧ v = 1 ∨ u = -1 ∧ v = -1 := by + refine ⟨eq_one_or_neg_one_of_mul_eq_one', fun h ↦ Or.elim h (fun H ↦ ?_) fun H ↦ ?_⟩ <;> + obtain ⟨rfl, rfl⟩ := H <;> rfl + +lemma eq_one_or_neg_one_of_mul_eq_neg_one' (h : u * v = -1) : u = 1 ∧ v = -1 ∨ u = -1 ∧ v = 1 := by + obtain rfl | rfl := isUnit_eq_one_or (IsUnit.mul_iff.mp (Int.isUnit_iff.mpr (Or.inr h))).1 + · exact Or.inl ⟨rfl, one_mul v ▸ h⟩ + · simpa [Int.neg_mul] using h + +lemma mul_eq_neg_one_iff_eq_one_or_neg_one : u * v = -1 ↔ u = 1 ∧ v = -1 ∨ u = -1 ∧ v = 1 := by + refine ⟨eq_one_or_neg_one_of_mul_eq_neg_one', fun h ↦ Or.elim h (fun H ↦ ?_) fun H ↦ ?_⟩ <;> + obtain ⟨rfl, rfl⟩ := H <;> rfl + +lemma isUnit_iff_natAbs_eq : IsUnit u ↔ u.natAbs = 1 := by simp [natAbs_eq_iff, isUnit_iff] + +alias ⟨IsUnit.natAbs_eq, _⟩ := isUnit_iff_natAbs_eq + +-- Porting note: `rw` didn't work on `natAbs_ofNat`, so had to change to `simp`, +-- presumably because `(n : ℤ)` is `Nat.cast` and not just `ofNat` +@[norm_cast] +lemma ofNat_isUnit {n : ℕ} : IsUnit (n : ℤ) ↔ IsUnit n := by simp [isUnit_iff_natAbs_eq] + +lemma isUnit_mul_self (hu : IsUnit u) : u * u = 1 := + (isUnit_eq_one_or hu).elim (fun h ↦ h.symm ▸ rfl) fun h ↦ h.symm ▸ rfl + +lemma isUnit_add_isUnit_eq_isUnit_add_isUnit {a b c d : ℤ} (ha : IsUnit a) (hb : IsUnit b) + (hc : IsUnit c) (hd : IsUnit d) : a + b = c + d ↔ a = c ∧ b = d ∨ a = d ∧ b = c := by + rw [isUnit_iff] at ha hb hc hd + aesop + +lemma eq_one_or_neg_one_of_mul_eq_neg_one (h : u * v = -1) : u = 1 ∨ u = -1 := + Or.elim (eq_one_or_neg_one_of_mul_eq_neg_one' h) (fun H => Or.inl H.1) fun H => Or.inr H.1 + +end Int diff --git a/Mathlib/Algebra/Group/Nat/Basic.lean b/Mathlib/Algebra/Group/Nat/Defs.lean similarity index 100% rename from Mathlib/Algebra/Group/Nat/Basic.lean rename to Mathlib/Algebra/Group/Nat/Defs.lean diff --git a/Mathlib/Algebra/Group/Nat/Even.lean b/Mathlib/Algebra/Group/Nat/Even.lean index 4dd418f24a6cb..1f9afc95a09c7 100644 --- a/Mathlib/Algebra/Group/Nat/Even.lean +++ b/Mathlib/Algebra/Group/Nat/Even.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Algebra.Group.Even -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Data.Nat.Sqrt /-! diff --git a/Mathlib/Algebra/Group/Nat/TypeTags.lean b/Mathlib/Algebra/Group/Nat/TypeTags.lean index a312f69a4aab7..28c748cbc124e 100644 --- a/Mathlib/Algebra/Group/Nat/TypeTags.lean +++ b/Mathlib/Algebra/Group/Nat/TypeTags.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Group.TypeTags.Basic /-! diff --git a/Mathlib/Algebra/Group/Nat/Units.lean b/Mathlib/Algebra/Group/Nat/Units.lean index edc5970d8d2e4..8dfa832751d6e 100644 --- a/Mathlib/Algebra/Group/Nat/Units.lean +++ b/Mathlib/Algebra/Group/Nat/Units.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Group.Units.Defs import Mathlib.Logic.Unique diff --git a/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean b/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean index 357b32013f358..1747d8a83a4bb 100644 --- a/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean @@ -3,8 +3,8 @@ Copyright (c) 2020 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.Group.Int import Mathlib.Algebra.Group.Subgroup.Map +import Mathlib.Algebra.Group.Int.Defs /-! # Subgroups generated by an element diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index 8852316886684..9037ade39062b 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Kenny Lau, Johan Commelin, Mario Carneiro, Kevin Buzza Amelia Livingston, Yury Kudryashov -/ import Mathlib.Algebra.Group.Action.Faithful -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Submonoid.Basic import Mathlib.Algebra.Group.TypeTags.Basic diff --git a/Mathlib/Algebra/GroupPower/IterateHom.lean b/Mathlib/Algebra/GroupPower/IterateHom.lean index ae097ed297d67..1f4f7705b2573 100644 --- a/Mathlib/Algebra/GroupPower/IterateHom.lean +++ b/Mathlib/Algebra/GroupPower/IterateHom.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.Group.Action.Opposite -import Mathlib.Algebra.Group.Int import Mathlib.Logic.Function.Iterate import Mathlib.Tactic.Common +import Mathlib.Algebra.Group.Int.Defs +import Mathlib.Algebra.Group.Nat.Defs /-! # Iterates of monoid homomorphisms diff --git a/Mathlib/Algebra/GroupWithZero/Nat.lean b/Mathlib/Algebra/GroupWithZero/Nat.lean index da61db4e4caf8..90a47d00cdf09 100644 --- a/Mathlib/Algebra/GroupWithZero/Nat.lean +++ b/Mathlib/Algebra/GroupWithZero/Nat.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.GroupWithZero.Defs import Mathlib.Tactic.Spread diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index a4bf99e945b6e..d11212a76f386 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -5,7 +5,8 @@ Authors: Mario Carneiro, Kevin Kappelmann -/ import Mathlib.Algebra.CharZero.Lemmas import Mathlib.Algebra.Order.Interval.Set.Group -import Mathlib.Algebra.Group.Int +import Mathlib.Algebra.Group.Int.Even +import Mathlib.Algebra.Group.Int.Units import Mathlib.Data.Int.Lemmas import Mathlib.Data.Nat.Cast.Order.Field import Mathlib.Data.Set.Subsingleton diff --git a/Mathlib/Algebra/Order/Group/Int.lean b/Mathlib/Algebra/Order/Group/Int.lean index 597b9448da53d..c545ec92b97e7 100644 --- a/Mathlib/Algebra/Order/Group/Int.lean +++ b/Mathlib/Algebra/Order/Group/Int.lean @@ -3,8 +3,8 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Algebra.Group.Int import Mathlib.Algebra.Order.Group.Defs +import Mathlib.Algebra.Group.Int.Defs /-! # The integers form a linear ordered group diff --git a/Mathlib/Algebra/Order/Group/Multiset.lean b/Mathlib/Algebra/Order/Group/Multiset.lean index 970a962cfde9c..7263f676402f8 100644 --- a/Mathlib/Algebra/Order/Group/Multiset.lean +++ b/Mathlib/Algebra/Order/Group/Multiset.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Group.Hom.Defs -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Order.Monoid.Unbundled.ExistsOfLE import Mathlib.Algebra.Order.Sub.Defs import Mathlib.Data.Multiset.Dedup diff --git a/Mathlib/Algebra/Order/Group/Nat.lean b/Mathlib/Algebra/Order/Group/Nat.lean index 1385365e53779..573f796727abc 100644 --- a/Mathlib/Algebra/Order/Group/Nat.lean +++ b/Mathlib/Algebra/Order/Group/Nat.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Sub.Defs import Mathlib.Data.Nat.Defs diff --git a/Mathlib/Algebra/Order/Group/Unbundled/Int.lean b/Mathlib/Algebra/Order/Group/Unbundled/Int.lean index 2fad62292ee5a..c6a057822d4a8 100644 --- a/Mathlib/Algebra/Order/Group/Unbundled/Int.lean +++ b/Mathlib/Algebra/Order/Group/Unbundled/Int.lean @@ -3,8 +3,8 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Algebra.Group.Int import Mathlib.Algebra.Order.Group.Unbundled.Abs +import Mathlib.Algebra.Group.Int.Defs /-! # Facts about `ℤ` as an (unbundled) ordered group diff --git a/Mathlib/Algebra/Ring/Int/Defs.lean b/Mathlib/Algebra/Ring/Int/Defs.lean index 95b412d3aae19..2d8404b75fca8 100644 --- a/Mathlib/Algebra/Ring/Int/Defs.lean +++ b/Mathlib/Algebra/Ring/Int/Defs.lean @@ -3,9 +3,11 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ +import Mathlib.Tactic.Cases import Mathlib.Algebra.CharZero.Defs -import Mathlib.Algebra.Group.Int import Mathlib.Algebra.Ring.Defs +import Mathlib.Algebra.Group.Int.Defs +import Mathlib.Data.Int.Cast.Basic /-! # The integers are a ring diff --git a/Mathlib/Algebra/Ring/Int/Parity.lean b/Mathlib/Algebra/Ring/Int/Parity.lean index cd9699824a498..d7422545b1867 100644 --- a/Mathlib/Algebra/Ring/Int/Parity.lean +++ b/Mathlib/Algebra/Ring/Int/Parity.lean @@ -5,6 +5,7 @@ Authors: Jeremy Avigad -/ import Mathlib.Algebra.Ring.Parity import Mathlib.Algebra.Ring.Int.Defs +import Mathlib.Algebra.Group.Int.Even /-! # Basic parity lemmas for the ring `ℤ` diff --git a/Mathlib/Algebra/Ring/Int/Units.lean b/Mathlib/Algebra/Ring/Int/Units.lean index f6d6df97cb24c..99394628b4234 100644 --- a/Mathlib/Algebra/Ring/Int/Units.lean +++ b/Mathlib/Algebra/Ring/Int/Units.lean @@ -5,6 +5,7 @@ Authors: Jeremy Avigad -/ import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Algebra.Ring.Units +import Mathlib.Algebra.Group.Int.Units /-! # Basic lemmas for `ℤˣ`. diff --git a/Mathlib/Algebra/Ring/Rat.lean b/Mathlib/Algebra/Ring/Rat.lean index 6492e69b88a4d..41eedc7f8b08d 100644 --- a/Mathlib/Algebra/Ring/Rat.lean +++ b/Mathlib/Algebra/Ring/Rat.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.GroupWithZero.Units.Basic import Mathlib.Algebra.Ring.Basic import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Data.Rat.Defs +import Mathlib.Algebra.Group.Nat.Defs /-! # The rational numbers are a commutative ring diff --git a/Mathlib/CategoryTheory/GradedObject.lean b/Mathlib/CategoryTheory/GradedObject.lean index 2bc160aeba95d..103db592c7731 100644 --- a/Mathlib/CategoryTheory/GradedObject.lean +++ b/Mathlib/CategoryTheory/GradedObject.lean @@ -3,10 +3,10 @@ Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison, Joël Riou -/ -import Mathlib.Algebra.Group.Int import Mathlib.CategoryTheory.ConcreteCategory.Basic import Mathlib.CategoryTheory.Shift.Basic import Mathlib.Data.Set.Subsingleton +import Mathlib.Algebra.Group.Int.Defs /-! # The category of graded objects diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index 0efb04b75e74c..c418510df9688 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -31,9 +31,7 @@ choosing between `insert` and `Finset.cons`, or between `Finset.union` and `Fins Move the material about `Finset.range` so that the `Mathlib.Algebra.Group.Embedding` import can be removed. -/ - --- TODO --- assert_not_exists OrderedCommMonoid +assert_not_exists OrderedCommMonoid assert_not_exists MonoidWithZero assert_not_exists MulAction diff --git a/Mathlib/Data/Finset/SymmDiff.lean b/Mathlib/Data/Finset/SymmDiff.lean index 97e4c2053afea..d60f613afe82e 100644 --- a/Mathlib/Data/Finset/SymmDiff.lean +++ b/Mathlib/Data/Finset/SymmDiff.lean @@ -23,8 +23,7 @@ assert_not_exists List.sublistsLen assert_not_exists Multiset.powerset assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists Monoid open Multiset Subtype Function diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index 9b443d8cbf4da..34bbc0278f356 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro import Mathlib.Data.Finset.Image import Mathlib.Data.List.FinRange import Mathlib.Data.Finite.Defs +import Mathlib.Algebra.Group.TypeTags.Basic /-! # Finite types diff --git a/Mathlib/Data/Fintype/Parity.lean b/Mathlib/Data/Fintype/Parity.lean index 66b5f97260eda..33677801f51ca 100644 --- a/Mathlib/Data/Fintype/Parity.lean +++ b/Mathlib/Data/Fintype/Parity.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Fintype.Card +import Mathlib.Algebra.Group.Even /-! # The cardinality of `Fin 2` is even. diff --git a/Mathlib/Data/Int/GCD.lean b/Mathlib/Data/Int/GCD.lean index e6b7b6ec9f4e8..2216a7674165e 100644 --- a/Mathlib/Data/Int/GCD.lean +++ b/Mathlib/Data/Int/GCD.lean @@ -3,13 +3,13 @@ Copyright (c) 2018 Guy Leroy. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sangwoo Jo (aka Jason), Guy Leroy, Johannes Hölzl, Mario Carneiro -/ -import Mathlib.Algebra.Group.Int import Mathlib.Algebra.GroupWithZero.Semiconj import Mathlib.Algebra.Group.Commute.Units import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Set.Operations import Mathlib.Order.Basic import Mathlib.Order.Bounds.Defs +import Mathlib.Algebra.Group.Int.Defs /-! # Extended GCD and divisibility over ℤ diff --git a/Mathlib/Data/Int/NatPrime.lean b/Mathlib/Data/Int/NatPrime.lean index ee1e51f543988..8c7f788fb5287 100644 --- a/Mathlib/Data/Int/NatPrime.lean +++ b/Mathlib/Data/Int/NatPrime.lean @@ -3,8 +3,8 @@ Copyright (c) 2020 Bryan Gin-ge Chen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Lacker, Bryan Gin-ge Chen -/ -import Mathlib.Algebra.Group.Int import Mathlib.Data.Nat.Prime.Basic +import Mathlib.Algebra.Group.Int.Defs /-! # Lemmas about `Nat.Prime` using `Int`s diff --git a/Mathlib/Data/List/SplitLengths.lean b/Mathlib/Data/List/SplitLengths.lean index ae9a0052291fa..40a3f2f4b305e 100644 --- a/Mathlib/Data/List/SplitLengths.lean +++ b/Mathlib/Data/List/SplitLengths.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Daniel Weber. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Daniel Weber -/ -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Order.MinMax /-! diff --git a/Mathlib/Data/Nat/Bits.lean b/Mathlib/Data/Nat/Bits.lean index fcc0bc2b46077..07c5b6eae145e 100644 --- a/Mathlib/Data/Nat/Bits.lean +++ b/Mathlib/Data/Nat/Bits.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Praneeth Kolichala. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Praneeth Kolichala -/ -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Data.Nat.Defs import Mathlib.Data.Nat.BinaryRec import Mathlib.Data.List.Defs diff --git a/Mathlib/Data/Nat/PSub.lean b/Mathlib/Data/Nat/PSub.lean index dce691789a710..e14dffd139073 100644 --- a/Mathlib/Data/Nat/PSub.lean +++ b/Mathlib/Data/Nat/PSub.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Group.Basic -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs /-! # Partial predecessor and partial subtraction on the natural numbers diff --git a/Mathlib/Data/Nat/Prime/Int.lean b/Mathlib/Data/Nat/Prime/Int.lean index 474b170148988..7dcf095377198 100644 --- a/Mathlib/Data/Nat/Prime/Int.lean +++ b/Mathlib/Data/Nat/Prime/Int.lean @@ -5,6 +5,7 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Data.Nat.Prime.Basic +import Mathlib.Algebra.Group.Int.Units /-! # Prime numbers in the naturals and the integers diff --git a/Mathlib/Data/Ordmap/Ordset.lean b/Mathlib/Data/Ordmap/Ordset.lean index eee6810eabc6b..2e0c839b2f6dc 100644 --- a/Mathlib/Data/Ordmap/Ordset.lean +++ b/Mathlib/Data/Ordmap/Ordset.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Order.Ring.Defs -import Mathlib.Algebra.Group.Int import Mathlib.Data.Nat.Dist import Mathlib.Data.Ordmap.Ordnode import Mathlib.Tactic.Abel diff --git a/Mathlib/Data/Set/Enumerate.lean b/Mathlib/Data/Set/Enumerate.lean index c5858d0c5e375..49ae508a43e7e 100644 --- a/Mathlib/Data/Set/Enumerate.lean +++ b/Mathlib/Data/Set/Enumerate.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Algebra.Group.Basic -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Tactic.Common import Mathlib.Data.Set.Basic diff --git a/Mathlib/GroupTheory/FreeGroup/Basic.lean b/Mathlib/GroupTheory/FreeGroup/Basic.lean index 68238f351a2d5..cb68f0c4376cd 100644 --- a/Mathlib/GroupTheory/FreeGroup/Basic.lean +++ b/Mathlib/GroupTheory/FreeGroup/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.Algebra.Group.Subgroup.Ker -import Mathlib.Algebra.Group.Int import Mathlib.Algebra.BigOperators.Group.List.Basic /-! diff --git a/Mathlib/Order/Hom/CompleteLattice.lean b/Mathlib/Order/Hom/CompleteLattice.lean index 93db1da8448d5..5906860a70a7f 100644 --- a/Mathlib/Order/Hom/CompleteLattice.lean +++ b/Mathlib/Order/Hom/CompleteLattice.lean @@ -36,7 +36,7 @@ be satisfied by itself and all stricter types. Frame homs are Heyting homs. -/ - +assert_not_exists Monoid open Function OrderDual Set diff --git a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean index a0f933bb656fa..7dc77adaeda72 100644 --- a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean +++ b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean @@ -6,6 +6,7 @@ Authors: David Kurniadi Angdinata import Mathlib.Algebra.Group.Equiv.TypeTags import Mathlib.Data.ZMod.Quotient import Mathlib.RingTheory.DedekindDomain.AdicValuation +import Mathlib.Algebra.Group.Int.TypeTags /-! # Selmer groups of fraction fields of Dedekind domains diff --git a/Mathlib/RingTheory/LaurentSeries.lean b/Mathlib/RingTheory/LaurentSeries.lean index 454a359a1e689..dbbef917b461d 100644 --- a/Mathlib/RingTheory/LaurentSeries.lean +++ b/Mathlib/RingTheory/LaurentSeries.lean @@ -12,6 +12,7 @@ import Mathlib.RingTheory.PowerSeries.Inverse import Mathlib.RingTheory.PowerSeries.Trunc import Mathlib.RingTheory.Localization.FractionRing import Mathlib.Topology.UniformSpace.Cauchy +import Mathlib.Algebra.Group.Int.TypeTags /-! # Laurent Series diff --git a/Mathlib/Tactic/Sat/FromLRAT.lean b/Mathlib/Tactic/Sat/FromLRAT.lean index db7f18cb54a91..346fba59014b5 100644 --- a/Mathlib/Tactic/Sat/FromLRAT.lean +++ b/Mathlib/Tactic/Sat/FromLRAT.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Tactic.ByContra /-! diff --git a/MathlibTest/levenshtein.lean b/MathlibTest/levenshtein.lean index 53932d20b2d56..783d415ca50ca 100644 --- a/MathlibTest/levenshtein.lean +++ b/MathlibTest/levenshtein.lean @@ -1,5 +1,5 @@ import Mathlib.Data.List.EditDistance.Defs -import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Defs #guard (suffixLevenshtein Levenshtein.defaultCost "kitten".toList "sitting".toList).1 = From 34714fe90c019c1d2df9c9d5185cce381ec71287 Mon Sep 17 00:00:00 2001 From: grunweg Date: Sat, 11 Jan 2025 02:41:50 +0000 Subject: [PATCH 150/681] chore: unpin and bump batteries and importgraph (#20651) Includes leanprover-community/batteries#1090 and leanprover-community/batteries#1091. [Zulip discussion](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Upgrading.20mathlib.20dependencies) --- Mathlib/Tactic/MinImports.lean | 2 ++ lake-manifest.json | 8 ++++---- lakefile.lean | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Mathlib/Tactic/MinImports.lean b/Mathlib/Tactic/MinImports.lean index c9544b2b3bae9..b841e9bad9942 100644 --- a/Mathlib/Tactic/MinImports.lean +++ b/Mathlib/Tactic/MinImports.lean @@ -5,6 +5,8 @@ Authors: Damiano Testa -/ import Mathlib.Init import ImportGraph.Imports +import Lean.Elab.DefView +import Lean.Util.CollectAxioms /-! # `#min_imports in` a command to find minimal imports diff --git a/lake-manifest.json b/lake-manifest.json index 795e5c8c6acca..d5ee15bf474c6 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -25,10 +25,10 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "9cb79405471ae931ac718231d6299bfaffef9087", + "rev": "18d461b4acad559d6ec11ae42eeed0fe767e523b", "name": "importGraph", "manifestFile": "lake-manifest.json", - "inputRev": "v4.16.0-rc1", + "inputRev": "main", "inherited": false, "configFile": "lakefile.toml"}, {"url": "https://github.com/leanprover-community/ProofWidgets4", @@ -65,10 +65,10 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "b2e8b6868397fcd93c00aca7278b933c16c0ffb3", + "rev": "66225aab4f6bd1687053b03916105f7cab140507", "name": "batteries", "manifestFile": "lake-manifest.json", - "inputRev": "v4.16.0-rc1", + "inputRev": "main", "inherited": false, "configFile": "lakefile.toml"}, {"url": "https://github.com/leanprover/lean4-cli", diff --git a/lakefile.lean b/lakefile.lean index 8547cccd1b924..90f9004561b01 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -7,11 +7,11 @@ open Lake DSL ## Mathlib dependencies on upstream projects -/ -require "leanprover-community" / "batteries" @ git "v4.16.0-rc1" +require "leanprover-community" / "batteries" @ git "main" require "leanprover-community" / "Qq" @ git "v4.15.0" require "leanprover-community" / "aesop" @ git "v4.16.0-rc1" require "leanprover-community" / "proofwidgets" @ git "v0.0.50" -require "leanprover-community" / "importGraph" @ git "v4.16.0-rc1" +require "leanprover-community" / "importGraph" @ git "main" require "leanprover-community" / "LeanSearchClient" @ git "main" require "leanprover-community" / "plausible" @ git "v4.16.0-rc1" From e0a7afcfbf892b9c888ae3c680036a140eee6479 Mon Sep 17 00:00:00 2001 From: Chris Wong Date: Sat, 11 Jan 2025 03:34:49 +0000 Subject: [PATCH 151/681] feat(Computability/DFA): implement `isRegular_iff` (#19940) An alternative is to use `Fin` and `Fintype.equivFin`, which are available via the existing import of `Data.Fintype.Card`. However, since `Fin _ : Type 0`, it needs to be wrapped in `ULift` to be universe-polymorphic, so the result is messier than the `Small` approach. --- Mathlib/Computability/DFA.lean | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Mathlib/Computability/DFA.lean b/Mathlib/Computability/DFA.lean index 19f997e872be6..e55cb83d9c17c 100644 --- a/Mathlib/Computability/DFA.lean +++ b/Mathlib/Computability/DFA.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Fox Thomson, Chris Wong -/ import Mathlib.Computability.Language +import Mathlib.Data.Countable.Small import Mathlib.Data.Fintype.Card import Mathlib.Data.List.Indexes import Mathlib.Tactic.NormNum @@ -250,6 +251,20 @@ end DFA def Language.IsRegular {T : Type u} (L : Language T) : Prop := ∃ σ : Type, ∃ _ : Fintype σ, ∃ M : DFA T σ, M.accepts = L -proof_wanted Language.isRegular_iff {T : Type u} {L : Language T} : - L.IsRegular ↔ ∃ σ : Type v, ∃ _ : Fintype σ, ∃ M : DFA T σ, M.accepts = L --- probably needs `import Mathlib.Data.Countable.Small` +/-- Lifts the state type `σ` inside `Language.IsRegular` to a different universe. -/ +private lemma Language.isRegular_iff.helper.{v'} {T : Type u} {L : Language T} + (hL : ∃ σ : Type v, ∃ _ : Fintype σ, ∃ M : DFA T σ, M.accepts = L) : + ∃ σ' : Type v', ∃ _ : Fintype σ', ∃ M : DFA T σ', M.accepts = L := + have ⟨σ, _, M, hM⟩ := hL + have ⟨σ', ⟨f⟩⟩ := Small.equiv_small.{v', v} (α := σ) + ⟨σ', Fintype.ofEquiv σ f, M.reindex f, hM ▸ DFA.accepts_reindex M f⟩ + +/-- +A language is regular if and only if it is defined by a DFA with finite states. + +This is more general than using the definition of `Language.IsRegular` directly, as the state type +`σ` is universe-polymorphic. +-/ +theorem Language.isRegular_iff {T : Type u} {L : Language T} : + L.IsRegular ↔ ∃ σ : Type v, ∃ _ : Fintype σ, ∃ M : DFA T σ, M.accepts = L := + ⟨Language.isRegular_iff.helper, Language.isRegular_iff.helper⟩ From 8df90d17b85f8661f34243bc2fd1be2a9a06a6a2 Mon Sep 17 00:00:00 2001 From: Pieter Cuijpers Date: Sat, 11 Jan 2025 04:09:47 +0000 Subject: [PATCH 152/681] add a variable_alias for Quantale and AddQuantale (#19282) similar to #19212, but for Quantales, taken from the variable_alias docs. Zulip: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/why.20.5Bvariable_alias.5D.20attribute.20is.20not.20used.20in.20Mathlib.3F --- Mathlib/Algebra/Order/Quantale.lean | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/Mathlib/Algebra/Order/Quantale.lean b/Mathlib/Algebra/Order/Quantale.lean index d7e77dc3a5738..b24e2e0834eca 100644 --- a/Mathlib/Algebra/Order/Quantale.lean +++ b/Mathlib/Algebra/Order/Quantale.lean @@ -6,6 +6,7 @@ Authors: Pieter Cuijpers import Mathlib.Algebra.Group.Defs import Mathlib.Algebra.Order.Monoid.Unbundled.Basic import Mathlib.Order.CompleteLattice +import Mathlib.Tactic.Variable /-! # Theory of quantales @@ -32,6 +33,10 @@ integral, and involutive quantales easier to add on later. over a complete lattice, i.e satisfying `x * (sSup s) = ⨆ y ∈ s, x * y` and `(sSup s) * y = ⨆ x ∈ s, x * y`; +* `Quantale` and `AddQuantale` : Structures serving as a typeclass alias, so one can write + `variable? [Quantale α]` instead of `variable [Semigroup α] [CompleteLattice α] [IsQuantale α]`, + and similarly for the additive variant. + * `leftMulResiduation`, `rightMulResiduation`, `leftAddResiduation`, `rightAddResiduation` : Defining the left- and right- residuations of the semigroup (see notation below). @@ -61,6 +66,11 @@ class IsAddQuantale (α : Type*) [AddSemigroup α] [CompleteLattice α] where /-- Addition is distributive over join in a quantale -/ protected sSup_add_distrib (s : Set α) (y : α) : sSup s + y = ⨆ x ∈ s, x + y +/-- A quantale is a semigroup distributing over a complete lattice. -/ +@[variable_alias] +structure AddQuantale (α : Type*) + [AddSemigroup α] [CompleteLattice α] [IsAddQuantale α] + /-- A quantale is a semigroup distributing over a complete lattice. -/ @[to_additive] class IsQuantale (α : Type*) [Semigroup α] [CompleteLattice α] where @@ -69,6 +79,11 @@ class IsQuantale (α : Type*) [Semigroup α] [CompleteLattice α] where /-- Multiplication is distributive over join in a quantale -/ protected sSup_mul_distrib (s : Set α) (y : α) : sSup s * y = ⨆ x ∈ s, x * y +/-- A quantale is a semigroup distributing over a complete lattice. -/ +@[variable_alias, to_additive] +structure Quantale (α : Type*) + [Semigroup α] [CompleteLattice α] [IsQuantale α] + section variable {α : Type*} {ι : Type*} {x y z : α} {s : Set α} {f : ι → α} @@ -82,7 +97,7 @@ theorem sSup_mul_distrib : sSup s * x = ⨆ y ∈ s, y * x := IsQuantale.sSup_mu end -namespace IsAddQuantale +namespace AddQuantale variable {α : Type*} {ι : Type*} {x y z : α} {s : Set α} {f : ι → α} variable [AddSemigroup α] [CompleteLattice α] [IsAddQuantale α] @@ -103,21 +118,21 @@ scoped infixr:60 " ⇨ₗ " => leftAddResiduation @[inherit_doc] scoped infixr:60 " ⇨ᵣ " => rightAddResiduation -end IsAddQuantale +end AddQuantale -namespace IsQuantale +namespace Quantale variable {α : Type*} {ι : Type*} {x y z : α} {s : Set α} {f : ι → α} variable [Semigroup α] [CompleteLattice α] [IsQuantale α] -/-- Left- and right-residuation operators on an additive quantale are similar to the Heyting +/-- Left- and right-residuation operators on a quantale are similar to the Heyting operator on complete lattices, but for a non-commutative logic. I.e. `x ≤ y ⇨ₗ z ↔ x * y ≤ z` or alternatively `x ⇨ₗ y = sSup { z | z * x ≤ y }`. -/ @[to_additive existing] def leftMulResiduation (x y : α) := sSup {z | z * x ≤ y} -/-- Left- and right- residuation operators on an additive quantale are similar to the Heyting +/-- Left- and right- residuation operators on a quantale are similar to the Heyting operator on complete lattices, but for a non-commutative logic. I.e. `x ≤ y ⇨ᵣ z ↔ y * x ≤ z` or alternatively `x ⇨ₗ y = sSup { z | x * z ≤ y }`. -/ @@ -191,4 +206,4 @@ theorem mul_bot : x * ⊥ = ⊥ := by end Zero -end IsQuantale +end Quantale From cfd2a08073809065d4b5e28bb9afb715dddb023a Mon Sep 17 00:00:00 2001 From: peabrainiac Date: Sat, 11 Jan 2025 04:20:12 +0000 Subject: [PATCH 153/681] feat(Topology/Category): category of delta-generated spaces (#19499) Introduces the category of delta-generated spaces and shows that it is complete, cocomplete and coreflective in the category of topological spaces. Co-authored-by: peabrainiac <43812953+peabrainiac@users.noreply.github.com> Co-authored-by: Michael Rothgang --- Mathlib.lean | 1 + Mathlib/Topology/Category/DeltaGenerated.lean | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 Mathlib/Topology/Category/DeltaGenerated.lean diff --git a/Mathlib.lean b/Mathlib.lean index e259e13653ae7..dcfcba8a0d2fb 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5195,6 +5195,7 @@ import Mathlib.Topology.Category.CompHausLike.Limits import Mathlib.Topology.Category.CompHausLike.SigmaComparison import Mathlib.Topology.Category.CompactlyGenerated import Mathlib.Topology.Category.Compactum +import Mathlib.Topology.Category.DeltaGenerated import Mathlib.Topology.Category.FinTopCat import Mathlib.Topology.Category.LightProfinite.AsLimit import Mathlib.Topology.Category.LightProfinite.Basic diff --git a/Mathlib/Topology/Category/DeltaGenerated.lean b/Mathlib/Topology/Category/DeltaGenerated.lean new file mode 100644 index 0000000000000..86a2128d2d7e3 --- /dev/null +++ b/Mathlib/Topology/Category/DeltaGenerated.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2024 Ben Eltschig. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Ben Eltschig +-/ +import Mathlib.CategoryTheory.Monad.Limits +import Mathlib.Topology.Category.TopCat.Limits.Basic +import Mathlib.Topology.Compactness.DeltaGeneratedSpace + +/-! +# Delta-generated topological spaces + +The category of delta-generated spaces. + +See https://ncatlab.org/nlab/show/Delta-generated+topological+space. + +Adapted from `Mathlib.Topology.Category.CompactlyGenerated`. + +## TODO +* `DeltaGenerated` is cartesian-closed. +-/ + +universe u + +open CategoryTheory + +/-- The type of delta-generated topological spaces. -/ +structure DeltaGenerated where + /-- the underlying topological space -/ + toTop : TopCat.{u} + /-- The underlying topological space is delta-generated. -/ + deltaGenerated : DeltaGeneratedSpace toTop := by infer_instance + +namespace DeltaGenerated + +instance : CoeSort DeltaGenerated Type* := + ⟨fun X ↦ X.toTop⟩ + +attribute [instance] deltaGenerated + +instance : LargeCategory.{u} DeltaGenerated.{u} := + InducedCategory.category toTop + +instance : ConcreteCategory.{u} DeltaGenerated.{u} := + InducedCategory.concreteCategory _ + +/-- Constructor for objects of the category `DeltaGenerated` -/ +def of (X : Type u) [TopologicalSpace X] [DeltaGeneratedSpace X] : DeltaGenerated.{u} where + toTop := TopCat.of X + deltaGenerated := ‹_› + +/-- The forgetful functor `DeltaGenerated ⥤ TopCat` -/ +@[simps!] +def deltaGeneratedToTop : DeltaGenerated.{u} ⥤ TopCat.{u} := + inducedFunctor _ + +/-- `deltaGeneratedToTop` is fully faithful. -/ +def fullyFaithfulDeltaGeneratedToTop : deltaGeneratedToTop.{u}.FullyFaithful := + fullyFaithfulInducedFunctor _ + +instance : deltaGeneratedToTop.{u}.Full := fullyFaithfulDeltaGeneratedToTop.full + +instance : deltaGeneratedToTop.{u}.Faithful := fullyFaithfulDeltaGeneratedToTop.faithful + +/-- The faithful (but not full) functor taking each topological space to its delta-generated + coreflection. -/ +@[simps!] +def topToDeltaGenerated : TopCat.{u} ⥤ DeltaGenerated.{u} where + obj X := of (DeltaGeneratedSpace.of X) + map {_ Y} f := ⟨f, (continuous_to_deltaGenerated (Y := Y)).mpr <| + continuous_le_dom deltaGenerated_le f.continuous⟩ + +instance : topToDeltaGenerated.{u}.Faithful := + ⟨fun h ↦ by ext x; exact congrFun (congrArg ContinuousMap.toFun h) x⟩ + +/-- The adjunction between the forgetful functor `DeltaGenerated ⥤ TopCat` and its coreflector. -/ +def coreflectorAdjunction : deltaGeneratedToTop ⊣ topToDeltaGenerated := + Adjunction.mkOfUnitCounit { + unit := { + app X := ⟨id, continuous_iff_coinduced_le.mpr (eq_deltaGenerated (X := X)).le⟩ } + counit := { + app X := ⟨DeltaGeneratedSpace.counit, DeltaGeneratedSpace.continuous_counit⟩ }} + +/-- The category of delta-generated spaces is coreflective in the category of topological spaces. -/ +instance deltaGeneratedToTop.coreflective : Coreflective deltaGeneratedToTop where + R := topToDeltaGenerated + adj := coreflectorAdjunction + +noncomputable instance deltaGeneratedToTop.createsColimits : CreatesColimits deltaGeneratedToTop := + comonadicCreatesColimits deltaGeneratedToTop + +instance hasLimits : Limits.HasLimits DeltaGenerated := + hasLimits_of_coreflective deltaGeneratedToTop + +instance hasColimits : Limits.HasColimits DeltaGenerated := + hasColimits_of_hasColimits_createsColimits deltaGeneratedToTop + +end DeltaGenerated From 19a56d6afe9807b99d4c5a8f857e31beac494f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yuyang=20Zhao=20=E8=B5=B5=E9=9B=A8=E6=89=AC?= Date: Sat, 11 Jan 2025 04:44:21 +0000 Subject: [PATCH 154/681] feat: add some term elaborators for reduction (#15192) In #13795, `zeta%` and `reduceProj%` will be used to improve the performance of unifying some instances. --- Mathlib.lean | 2 +- Mathlib/Tactic/IrreducibleDef.lean | 11 +-- Mathlib/Util/TermBeta.lean | 41 --------- Mathlib/Util/TermReduce.lean | 90 +++++++++++++++++++ .../{TermBeta.lean => TermReduce.lean} | 47 +++++++++- scripts/noshake.json | 3 +- 6 files changed, 141 insertions(+), 53 deletions(-) delete mode 100644 Mathlib/Util/TermBeta.lean create mode 100644 Mathlib/Util/TermReduce.lean rename MathlibTest/{TermBeta.lean => TermReduce.lean} (52%) diff --git a/Mathlib.lean b/Mathlib.lean index dcfcba8a0d2fb..cef321f295446 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5550,7 +5550,7 @@ import Mathlib.Util.SleepHeartbeats import Mathlib.Util.Superscript import Mathlib.Util.SynthesizeUsing import Mathlib.Util.Tactic -import Mathlib.Util.TermBeta +import Mathlib.Util.TermReduce import Mathlib.Util.TransImports import Mathlib.Util.WhatsNew import Mathlib.Util.WithWeakNamespace diff --git a/Mathlib/Tactic/IrreducibleDef.lean b/Mathlib/Tactic/IrreducibleDef.lean index 4c123c5a59d82..e79d38ac8400d 100644 --- a/Mathlib/Tactic/IrreducibleDef.lean +++ b/Mathlib/Tactic/IrreducibleDef.lean @@ -3,8 +3,9 @@ Copyright (c) 2021 Gabriel Ebner. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner -/ -import Mathlib.Tactic.Eqns import Mathlib.Data.Subtype +import Mathlib.Tactic.Eqns +import Mathlib.Util.TermReduce /-! # Irreducible definitions @@ -31,14 +32,6 @@ namespace Lean.Elab.Command open Term Meta -/-- `delta% t` elaborates to a head-delta reduced version of `t`. -/ -elab "delta% " t:term : term <= expectedType => do - let t ← elabTerm t expectedType - synthesizeSyntheticMVars - let t ← instantiateMVars t - let some t ← delta? t | throwError "cannot delta reduce {t}" - pure t - /-- `eta_helper f = (· + 3)` elabs to `∀ x, f x = x + 3` -/ local elab "eta_helper " t:term : term => do let t ← elabTerm t none diff --git a/Mathlib/Util/TermBeta.lean b/Mathlib/Util/TermBeta.lean deleted file mode 100644 index 894ced6315fb4..0000000000000 --- a/Mathlib/Util/TermBeta.lean +++ /dev/null @@ -1,41 +0,0 @@ -/- -Copyright (c) 2023 Kyle Miller. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kyle Miller --/ -import Mathlib.Init -import Lean.Elab.Term - -/-! `beta%` term elaborator - -The `beta% f x1 ... xn` term elaborator elaborates the expression -`f x1 ... xn` and then does one level of beta reduction. -That is, if `f` is a lambda then it will substitute its arguments. - -The purpose of this is to support substitutions in notations such as -`∀ i, beta% p i` so that `p i` gets beta reduced when `p` is a lambda. --/ - -namespace Mathlib.Util.TermBeta - -open Lean Elab Term - -/-- `beta% t` elaborates `t` and then if the result is in the form -`f x1 ... xn` where `f` is a (nested) lambda expression, -it will substitute all of its arguments by beta reduction. -This does not recursively do beta reduction, nor will it do -beta reduction of subexpressions. - -In particular, `t` is elaborated, its metavariables are instantiated, -and then `Lean.Expr.headBeta` is applied. -/ -syntax (name := betaStx) "beta% " term : term - -@[term_elab betaStx, inherit_doc betaStx] -def elabBeta : TermElab := fun stx expectedType? => - match stx with - | `(beta% $t) => do - let e ← elabTerm t expectedType? - return (← instantiateMVars e).headBeta - | _ => throwUnsupportedSyntax - -end Mathlib.Util.TermBeta diff --git a/Mathlib/Util/TermReduce.lean b/Mathlib/Util/TermReduce.lean new file mode 100644 index 0000000000000..189bdb03363fd --- /dev/null +++ b/Mathlib/Util/TermReduce.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2023 Kyle Miller. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kyle Miller, Gabriel Ebner, Yuyang Zhao +-/ +import Lean.Meta.Tactic.Delta +import Mathlib.Lean.Expr.Basic + +/-! +# Term elaborators for reduction +-/ + +namespace Mathlib.Util.TermReduce + +open Lean Elab Term Meta + +/-! +The `beta% f x1 ... xn` term elaborator elaborates the expression +`f x1 ... xn` and then does one level of beta reduction. +That is, if `f` is a lambda then it will substitute its arguments. + +The purpose of this is to support substitutions in notations such as +`∀ i, beta% p i` so that `p i` gets beta reduced when `p` is a lambda. +-/ + +/-- `beta% t` elaborates `t` and then if the result is in the form +`f x1 ... xn` where `f` is a (nested) lambda expression, +it will substitute all of its arguments by beta reduction. +This does not recursively do beta reduction, nor will it do +beta reduction of subexpressions. + +In particular, `t` is elaborated, its metavariables are instantiated, +and then `Lean.Expr.headBeta` is applied. -/ +syntax (name := betaStx) "beta% " term : term + +@[term_elab betaStx, inherit_doc betaStx] +def elabBeta : TermElab := fun stx expectedType? => + match stx with + | `(beta% $t) => do + let e ← elabTerm t expectedType? + return (← instantiateMVars e).headBeta + | _ => throwUnsupportedSyntax + +/-- `delta% t` elaborates to a head-delta reduced version of `t`. -/ +syntax (name := deltaStx) "delta% " term : term + +@[term_elab deltaStx, inherit_doc deltaStx] +def elabDelta : TermElab := fun stx expectedType? => + match stx with + | `(delta% $t) => do + let t ← withSynthesize (postpone := .partial) do + elabTerm t expectedType? + synthesizeSyntheticMVars + let t ← instantiateMVars t + let some t ← delta? t | throwError "cannot delta reduce {t}" + pure t + | _ => throwUnsupportedSyntax + +/-- `zeta% t` elaborates to a zeta and zeta-delta reduced version of `t`. -/ +syntax (name := zetaStx) "zeta% " term : term + +@[term_elab zetaStx, inherit_doc zetaStx] +def elabZeta : TermElab := fun stx expectedType? => + match stx with + | `(zeta% $t) => do + let t ← withSynthesize (postpone := .partial) do + elabTerm t expectedType? + synthesizeSyntheticMVars + let t ← instantiateMVars t + let t ← zetaReduce t + pure t + | _ => throwUnsupportedSyntax + +/-- `reduceProj% t` apply `Expr.reduceProjStruct?` to all subexpressions of `t`. -/ +syntax (name := reduceProjStx) "reduceProj% " term : term + +@[term_elab reduceProjStx, inherit_doc reduceProjStx] +def elabReduceProj : TermElab := fun stx expectedType? => + match stx with + | `(reduceProj% $t) => do + let t ← withSynthesize (postpone := .partial) do + elabTerm t expectedType? + synthesizeSyntheticMVars + let t ← instantiateMVars t + let t ← Lean.Core.transform t (post := fun e ↦ do + return .continue (← Expr.reduceProjStruct? e)) + pure t + | _ => throwUnsupportedSyntax + +end Mathlib.Util.TermReduce diff --git a/MathlibTest/TermBeta.lean b/MathlibTest/TermReduce.lean similarity index 52% rename from MathlibTest/TermBeta.lean rename to MathlibTest/TermReduce.lean index f54d02ecde615..6aa3d761ba73d 100644 --- a/MathlibTest/TermBeta.lean +++ b/MathlibTest/TermReduce.lean @@ -1,4 +1,4 @@ -import Mathlib.Util.TermBeta +import Mathlib.Util.TermReduce -- On command line, tests format functions with => rather than ↦ without this. set_option linter.style.setOption false set_option pp.unicode.fun true @@ -34,3 +34,48 @@ abbrev reducibleId : Bool → Bool := fun x => x /-- info: reducibleId true : Bool -/ #guard_msgs in #check reducibleId true + +/-- info: id (id true) : Bool -/ +#guard_msgs in #check id (id true) + +/-- info: id true : Bool -/ +#guard_msgs in #check delta% id (id true) + +/-- info: true : Bool -/ +#guard_msgs in #check delta% delta% id (id true) + +/-- info: true : Bool -/ +#guard_msgs in #check delta% delta% by exact id (id true) + +/-- info: let x := true; x : Bool -/ +#guard_msgs in #check let x := true; x + +/-- info: true : Bool -/ +#guard_msgs in #check zeta% let x := true; x + +/-- info: let x := true; let y := x; y : Bool -/ +#guard_msgs in #check let x := true; let y := x; y + +/-- info: true : Bool -/ +#guard_msgs in #check zeta% let x := true; let y := x; y + +/-- info: true : Bool -/ +#guard_msgs in #check zeta% by exact let x := true; let y := x; y + +class A where + +class B extends A where + +class C extends A where + +instance c : C := + letI : B := {} + {} + +set_option pp.explicit true in +/-- info: @C.mk (@B.toA (@B.mk A.mk)) : C -/ +#guard_msgs in #check delta% c + +set_option pp.explicit true in +/-- info: @C.mk A.mk : C -/ +#guard_msgs in #check reduceProj% delta% c diff --git a/scripts/noshake.json b/scripts/noshake.json index d896c7a46f6a8..adffc77f1f757 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -246,7 +246,8 @@ "Mathlib.Tactic.LinearCombination": ["Mathlib.Tactic.LinearCombination.Lemmas"], "Mathlib.Tactic.Lemma": ["Lean.Parser.Command"], - "Mathlib.Tactic.IrreducibleDef": ["Mathlib.Data.Subtype"], + "Mathlib.Tactic.IrreducibleDef": + ["Mathlib.Data.Subtype", "Mathlib.Util.TermReduce"], "Mathlib.Tactic.ITauto": ["Batteries.Tactic.Init", "Mathlib.Logic.Basic"], "Mathlib.Tactic.Group": ["Mathlib.Algebra.Group.Commutator"], "Mathlib.Tactic.GCongr.Core": From c0cb03aa7c02c5a85719b6051ea6eb202b1b9a7c Mon Sep 17 00:00:00 2001 From: grunweg Date: Sat, 11 Jan 2025 05:59:10 +0000 Subject: [PATCH 155/681] feat: disjoint union of charted spaces (#20619) As the main technical tool to do so, we introduce a new definition `PartialHomeomorph.lift_openEmbedding`, lifting a PartialHomeomorph under an `OpenEmbedding`. (The left or right inclusion into a disjoint union are open embeddings; this abstract allows proving lemmas only once, and avoids having to deal with subtypes.) From the bordism theory project branch: future steps include proving that the disjoint union of `C^n` manifolds is a `C^n` manifold. --- Mathlib/Geometry/Manifold/ChartedSpace.lean | 53 ++++++++++++++++++ Mathlib/Topology/PartialHomeomorph.lean | 62 +++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index 5dd4edfb1c285..a862ca47f3f78 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -849,6 +849,59 @@ theorem piChartedSpace_chartAt {ι : Type*} [Finite ι] (H : ι → Type*) chartAt (H := ModelPi H) f = PartialHomeomorph.pi fun i ↦ chartAt (H i) (f i) := rfl +section sum + +variable [TopologicalSpace H] [TopologicalSpace M] [TopologicalSpace M'] + [cm : ChartedSpace H M] [cm' : ChartedSpace H M'] [Nonempty H] [Nonempty M] [Nonempty M'] + +/-- The disjoint union of two charted spaces on `H` is a charted space over `H`. -/ +instance ChartedSpace.sum : ChartedSpace H (M ⊕ M') where + atlas := ((fun e ↦ e.lift_openEmbedding IsOpenEmbedding.inl) '' cm.atlas) ∪ + ((fun e ↦ e.lift_openEmbedding IsOpenEmbedding.inr) '' cm'.atlas) + -- At `x : M`, the chart is the chart in `M`; at `x' ∈ M'`, it is the chart in `M'`. + chartAt := Sum.elim (fun x ↦ (cm.chartAt x).lift_openEmbedding IsOpenEmbedding.inl) + (fun x ↦ (cm'.chartAt x).lift_openEmbedding IsOpenEmbedding.inr) + mem_chart_source p := by + by_cases h : Sum.isLeft p + · let x := Sum.getLeft p h + rw [Sum.eq_left_getLeft_of_isLeft h, Sum.elim_inl, lift_openEmbedding_source, + ← PartialHomeomorph.lift_openEmbedding_source _ IsOpenEmbedding.inl] + use x, cm.mem_chart_source x + · have h' : Sum.isRight p := Sum.not_isLeft.mp h + let x := Sum.getRight p h' + rw [Sum.eq_right_getRight_of_isRight h', Sum.elim_inr, lift_openEmbedding_source, + ← PartialHomeomorph.lift_openEmbedding_source _ IsOpenEmbedding.inr] + use x, cm'.mem_chart_source x + chart_mem_atlas p := by + by_cases h : Sum.isLeft p + · rw [Sum.eq_left_getLeft_of_isLeft h, Sum.elim_inl] + left + let x := Sum.getLeft p h + use ChartedSpace.chartAt x, cm.chart_mem_atlas x + · have h' : Sum.isRight p := Sum.not_isLeft.mp h + rw [Sum.eq_right_getRight_of_isRight h', Sum.elim_inr] + right + let x := Sum.getRight p h' + use ChartedSpace.chartAt x, cm'.chart_mem_atlas x + +lemma ChartedSpace.sum_chartAt_inl (x : M) : + chartAt H (Sum.inl x) = (chartAt H x).lift_openEmbedding (X' := M ⊕ M') IsOpenEmbedding.inl := + rfl + +lemma ChartedSpace.sum_chartAt_inr (x' : M') : + chartAt H (Sum.inr x') = (chartAt H x').lift_openEmbedding (X' := M ⊕ M') IsOpenEmbedding.inr := + rfl + +lemma ChartedSpace.mem_atlas_sum {e : PartialHomeomorph (M ⊕ M') H} (he : e ∈ atlas H (M ⊕ M')) : + (∃ f : PartialHomeomorph M H, f ∈ (atlas H M) ∧ e = (f.lift_openEmbedding IsOpenEmbedding.inl)) + ∨ (∃ f' : PartialHomeomorph M' H, f' ∈ (atlas H M') ∧ + e = (f'.lift_openEmbedding IsOpenEmbedding.inr)) := by + obtain (⟨x, hx, hxe⟩ | ⟨x, hx, hxe⟩) := he + · rw [← hxe]; left; use x + · rw [← hxe]; right; use x + +end sum + end ChartedSpace /-! ### Constructing a topology from an atlas -/ diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index 20435dc149290..202d87d21c03f 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -1325,4 +1325,66 @@ theorem subtypeRestr_symm_eqOn_of_le {U V : Opens X} (hU : Nonempty U) (hV : Non end subtypeRestr +variable {X X' Z : Type*} [TopologicalSpace X] [TopologicalSpace X'] [TopologicalSpace Z] + [Nonempty X] [Nonempty Z] {f : X → X'} + +/-- Extend a partial homeomorphism `e : X → Z` to `X' → Z`, using an open embedding `ι : X → X'`. +On `ι(X)`, the extension is specified by `e`; its value elsewhere is arbitrary (and uninteresting). +-/ +noncomputable def lift_openEmbedding + (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + PartialHomeomorph X' Z where + toFun := extend f e (Classical.arbitrary (α := X' → Z)) + invFun := f ∘ e.invFun + source := f '' e.source + target := e.target + map_source' := by + rintro x ⟨x₀, hx₀, hxx₀⟩ + rw [← hxx₀, hf.injective.extend_apply e] + exact e.map_source' hx₀ + map_target' z hz := mem_image_of_mem f (e.map_target' hz) + left_inv' := by + intro x ⟨x₀, hx₀, hxx₀⟩ + rw [← hxx₀, hf.injective.extend_apply e, comp_apply] + congr + exact e.left_inv' hx₀ + right_inv' z hz := by simpa only [comp_apply, hf.injective.extend_apply e] using e.right_inv' hz + open_source := hf.isOpenMap _ e.open_source + open_target := e.open_target + continuousOn_toFun := by + set F := (extend f (↑e) (Classical.arbitrary (X' → Z))) with F_eq + have heq : EqOn F (e ∘ (hf.toPartialHomeomorph).symm) (f '' e.source) := by + intro x ⟨x₀, hx₀, hxx₀⟩ + rw [← hxx₀, F_eq, hf.injective.extend_apply e, comp_apply, hf.toPartialHomeomorph_left_inv] + have : ContinuousOn (e ∘ (hf.toPartialHomeomorph).symm) (f '' e.source) := by + apply e.continuousOn_toFun.comp; swap + · intro x' ⟨x, hx, hx'x⟩ + rw [← hx'x, hf.toPartialHomeomorph_left_inv]; exact hx + have : ContinuousOn (hf.toPartialHomeomorph).symm (f '' univ) := by + apply (hf.toPartialHomeomorph).continuousOn_invFun + apply this.mono; gcongr; exact fun ⦃a⦄ a ↦ trivial + apply ContinuousOn.congr this heq + continuousOn_invFun := hf.continuous.comp_continuousOn e.continuousOn_invFun + +@[simp] +lemma lift_openEmbedding_toFun (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf) = extend f e (Classical.arbitrary (α := (X' → Z))) := rfl + +lemma lift_openEmbedding_apply (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) {x : X} : + (lift_openEmbedding e hf) (f x) = e x := by + simp_rw [e.lift_openEmbedding_toFun] + apply hf.injective.extend_apply + +@[simp] +lemma lift_openEmbedding_symm (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf).symm = f ∘ e.symm := rfl + +@[simp] +lemma lift_openEmbedding_source (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf).source = f '' e.source := rfl + +@[simp] +lemma lift_openEmbedding_target (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf).target = e.target := rfl + end PartialHomeomorph From 3a798ee6b80f2b2c5d44dfab78d05245ef5ce126 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Sat, 11 Jan 2025 10:05:50 +0000 Subject: [PATCH 156/681] feat: use scoped trace nodes in linarith (#19855) Inspired by hacking done with @robertylewis and @hrmacbeth which resulted in #19771. The effect is that the traces messages are now hierarchical; though it's easy not to notice in VSCode without a better version of https://github.com/leanprover/lean4/pull/6345. See https://profiler.firefox.com/public/smkc5ffh9318w177gps2x9e5b6wy117s6f18e6g/flame-graph/?globalTrackOrder=0&thread=0&transforms=ff-2659&v=10 for an example output produced with ```bash lake lean MathlibTest/linarith.lean -- \ -Dtrace.profiler=true \ -Dtrace.profiler.threshold=1 \ -Dtrace.profiler.output.pp=true \ -Dtrace.profiler.output=linarith-profile.json ``` Some inconclusive discussion about best practices for `withTraceNode` is [on Zulip here](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Using.20withTraceNode/near/489198580). Co-authored-by: Eric Wieser --- Mathlib/Tactic/Linarith/Datatypes.lean | 46 ++++++++------ Mathlib/Tactic/Linarith/Frontend.lean | 26 +++++--- Mathlib/Tactic/Linarith/Preprocessing.lean | 34 ++++++----- Mathlib/Tactic/Linarith/Verification.lean | 71 +++++++++++++--------- 4 files changed, 103 insertions(+), 74 deletions(-) diff --git a/Mathlib/Tactic/Linarith/Datatypes.lean b/Mathlib/Tactic/Linarith/Datatypes.lean index 8b88a3db0e1ee..97222636fc0c4 100644 --- a/Mathlib/Tactic/Linarith/Datatypes.lean +++ b/Mathlib/Tactic/Linarith/Datatypes.lean @@ -23,13 +23,17 @@ initialize registerTraceClass `linarith.detail namespace Linarith +/-- A shorthand for getting the types of a list of proofs terms, to trace. -/ +def linarithGetProofsMessage (l : List Expr) : MetaM MessageData := do + return m!"{← l.mapM fun e => do instantiateMVars (← inferType e)}" + /-- A shorthand for tracing the types of a list of proof terms when the `trace.linarith` option is set to true. -/ def linarithTraceProofs {α} [ToMessageData α] (s : α) (l : List Expr) : MetaM Unit := do - trace[linarith] "{s}" - trace[linarith] (← l.mapM fun e => do instantiateMVars (← inferType e)) + if ← isTracingEnabledFor `linarith then + addRawTrace <| .trace { cls := `linarith } (toMessageData s) #[← linarithGetProofsMessage l] /-! ### Linear expressions -/ @@ -167,15 +171,20 @@ instance Comp.ToFormat : ToFormat Comp := /-! ### Control -/ +/-- Metadata about preprocessors, for trace output. -/ +structure PreprocessorBase : Type where + /-- The name of the preprocessor, populated automatically, to create linkable trace messages. -/ + name : Name := by exact decl_name% + /-- The description of the preprocessor. -/ + description : String + /-- A preprocessor transforms a proof of a proposition into a proof of a different proposition. The return type is `List Expr`, since some preprocessing steps may create multiple new hypotheses, and some may remove a hypothesis from the list. A "no-op" preprocessor should return its input as a singleton list. -/ -structure Preprocessor : Type where - /-- The name of the preprocessor, used in trace output. -/ - name : String +structure Preprocessor extends PreprocessorBase : Type where /-- Replace a hypothesis by a list of hypotheses. These expressions are the proof terms. -/ transform : Expr → MetaM (List Expr) @@ -184,9 +193,7 @@ Some preprocessors need to examine the full list of hypotheses instead of workin As with `Preprocessor`, the input to a `GlobalPreprocessor` is replaced by, not added to, its output. -/ -structure GlobalPreprocessor : Type where - /-- The name of the global preprocessor, used in trace output. -/ - name : String +structure GlobalPreprocessor extends PreprocessorBase : Type where /-- Replace the collection of all hypotheses with new hypotheses. These expressions are proof terms. -/ transform : List Expr → MetaM (List Expr) @@ -206,9 +213,7 @@ Each branch is independent, so hypotheses that appear in multiple branches shoul The preprocessor is responsible for making sure that each branch contains the correct goal metavariable. -/ -structure GlobalBranchingPreprocessor : Type where - /-- The name of the global branching preprocessor, used in trace output. -/ - name : String +structure GlobalBranchingPreprocessor extends PreprocessorBase : Type where /-- Given a goal, and a list of hypotheses, produce a list of pairs (consisting of a goal and list of hypotheses). -/ transform : MVarId → List Expr → MetaM (List Branch) @@ -217,14 +222,14 @@ structure GlobalBranchingPreprocessor : Type where A `Preprocessor` lifts to a `GlobalPreprocessor` by folding it over the input list. -/ def Preprocessor.globalize (pp : Preprocessor) : GlobalPreprocessor where - name := pp.name + __ := pp transform := List.foldrM (fun e ret => do return (← pp.transform e) ++ ret) [] /-- A `GlobalPreprocessor` lifts to a `GlobalBranchingPreprocessor` by producing only one branch. -/ def GlobalPreprocessor.branching (pp : GlobalPreprocessor) : GlobalBranchingPreprocessor where - name := pp.name + __ := pp transform := fun g l => do return [⟨g, ← pp.transform l⟩] /-- @@ -233,13 +238,14 @@ tracing the result if `trace.linarith` is on. -/ def GlobalBranchingPreprocessor.process (pp : GlobalBranchingPreprocessor) (g : MVarId) (l : List Expr) : MetaM (List Branch) := g.withContext do - let branches ← pp.transform g l - if branches.length > 1 then - trace[linarith] "Preprocessing: {pp.name} has branched, with branches:" - for ⟨goal, hyps⟩ in branches do - goal.withContext do - linarithTraceProofs m!"Preprocessing: {pp.name}" hyps - return branches + withTraceNode `linarith (fun e => + return m!"{exceptEmoji e} {.ofConstName pp.name}: {pp.description}") do + let branches ← pp.transform g l + if branches.length > 1 then + trace[linarith] "Preprocessing: {pp.name} has branched, with branches:" + for ⟨goal, hyps⟩ in branches do + trace[linarith] (← goal.withContext <| linarithGetProofsMessage hyps) + return branches instance PreprocessorToGlobalBranchingPreprocessor : Coe Preprocessor GlobalBranchingPreprocessor := diff --git a/Mathlib/Tactic/Linarith/Frontend.lean b/Mathlib/Tactic/Linarith/Frontend.lean index e76aaf4acb162..c85d90d235661 100644 --- a/Mathlib/Tactic/Linarith/Frontend.lean +++ b/Mathlib/Tactic/Linarith/Frontend.lean @@ -250,13 +250,14 @@ Given a list `ls` of lists of proofs of comparisons, `findLinarithContradiction prove `False` by calling `linarith` on each list in succession. It will stop at the first proof of `False`, and fail if no contradiction is found with any list. -/ -def findLinarithContradiction (cfg : LinarithConfig) (g : MVarId) (ls : List (List Expr)) : +def findLinarithContradiction (cfg : LinarithConfig) (g : MVarId) (ls : List (Expr × List Expr)) : MetaM Expr := try - ls.firstM (fun L => proveFalseByLinarith cfg.transparency cfg.oracle cfg.discharger g L) + ls.firstM (fun ⟨α, L⟩ => + withTraceNode `linarith (return m!"{exceptEmoji ·} running on type {α}") <| + proveFalseByLinarith cfg.transparency cfg.oracle cfg.discharger g L) catch e => throwError "linarith failed to find a contradiction\n{g}\n{e.toMessageData}" - /-- Given a list `hyps` of proofs of comparisons, `runLinarith cfg hyps prefType` preprocesses `hyps` according to the list of preprocessors in `cfg`. @@ -272,13 +273,20 @@ def runLinarith (cfg : LinarithConfig) (prefType : Option Expr) (g : MVarId) (hyps : List Expr) : MetaM Unit := do let singleProcess (g : MVarId) (hyps : List Expr) : MetaM Expr := g.withContext do linarithTraceProofs s!"after preprocessing, linarith has {hyps.length} facts:" hyps - let hyp_set ← partitionByType hyps + let mut hyp_set ← partitionByType hyps trace[linarith] "hypotheses appear in {hyp_set.size} different types" + -- If we have a preferred type, strip it from `hyp_set` and prepare a handler with a custom + -- trace message + let pref : MetaM _ ← do if let some t := prefType then let (i, vs) ← hyp_set.find t - proveFalseByLinarith cfg.transparency cfg.oracle cfg.discharger g vs <|> - findLinarithContradiction cfg g ((hyp_set.eraseIdxIfInBounds i).toList.map (·.2)) - else findLinarithContradiction cfg g (hyp_set.toList.map (·.2)) + hyp_set := hyp_set.eraseIdxIfInBounds i + pure <| + withTraceNode `linarith (return m!"{exceptEmoji ·} running on preferred type {t}") <| + proveFalseByLinarith cfg.transparency cfg.oracle cfg.discharger g vs + else + pure failure + pref <|> findLinarithContradiction cfg g hyp_set.toList let mut preprocessors := cfg.preprocessors if cfg.splitNe then preprocessors := Linarith.removeNe :: preprocessors @@ -318,8 +326,8 @@ partial def linarith (only_on : Bool) (hyps : List Expr) (cfg : LinarithConfig : if (← whnfR (← instantiateMVars (← g.getType))).isEq then trace[linarith] "target is an equality: splitting" if let some [g₁, g₂] ← try? (g.apply (← mkConst' ``eq_of_not_lt_of_not_gt)) then - linarith only_on hyps cfg g₁ - linarith only_on hyps cfg g₂ + withTraceNode `linarith (return m!"{exceptEmoji ·} proving ≥") <| linarith only_on hyps cfg g₁ + withTraceNode `linarith (return m!"{exceptEmoji ·} proving ≤") <| linarith only_on hyps cfg g₂ return /- If we are proving a comparison goal (and not just `False`), we consider the type of the diff --git a/Mathlib/Tactic/Linarith/Preprocessing.lean b/Mathlib/Tactic/Linarith/Preprocessing.lean index f714751349976..9aeedda4ada6c 100644 --- a/Mathlib/Tactic/Linarith/Preprocessing.lean +++ b/Mathlib/Tactic/Linarith/Preprocessing.lean @@ -39,7 +39,7 @@ open Batteries (RBSet) /-- Processor that recursively replaces `P ∧ Q` hypotheses with the pair `P` and `Q`. -/ partial def splitConjunctions : Preprocessor where - name := "split conjunctions" + description := "split conjunctions" transform := aux where /-- Implementation of the `splitConjunctions` preprocessor. -/ @@ -54,7 +54,7 @@ where Removes any expressions that are not proofs of inequalities, equalities, or negations thereof. -/ partial def filterComparisons : Preprocessor where - name := "filter terms that are not proofs of comparisons" + description := "filter terms that are not proofs of comparisons" transform h := do let tp ← instantiateMVars (← inferType h) try @@ -80,7 +80,7 @@ Replaces proofs of negations of comparisons with proofs of the reversed comparis For example, a proof of `¬ a < b` will become a proof of `a ≥ b`. -/ def removeNegations : Preprocessor where - name := "replace negations of comparisons" + description := "replace negations of comparisons" transform h := do let t : Q(Prop) ← whnfR (← inferType h) match t with @@ -147,7 +147,7 @@ It also adds the facts that the integers involved are nonnegative. To avoid adding the same nonnegativity facts many times, it is a global preprocessor. -/ def natToInt : GlobalBranchingPreprocessor where - name := "move nats to ints" + description := "move nats to ints" transform g l := do let l ← l.mapM fun h => do let t ← whnfR (← instantiateMVars (← inferType h)) @@ -192,7 +192,7 @@ def mkNonstrictIntProof (pf : Expr) : MetaM (Option Expr) := do /-- `strengthenStrictInt h` turns a proof `h` of a strict integer inequality `t1 < t2` into a proof of `t1 ≤ t2 + 1`. -/ def strengthenStrictInt : Preprocessor where - name := "strengthen strict inequalities over int" + description := "strengthen strict inequalities over int" transform h := return [(← mkNonstrictIntProof h).getD h] end strengthenStrictInt @@ -214,7 +214,7 @@ partial def rearrangeComparison (e : Expr) : MetaM (Option Expr) := do and turns it into a proof of a comparison `_ R 0`, where `R ∈ {=, ≤, <}`. -/ def compWithZero : Preprocessor where - name := "make comparisons with zero" + description := "make comparisons with zero" transform e := return (← rearrangeComparison e).toList end compWithZero @@ -247,7 +247,7 @@ def normalizeDenominatorsLHS (h lhs : Expr) : MetaM Expr := do it tries to scale `t` to cancel out division by numerals. -/ def cancelDenoms : Preprocessor where - name := "cancel denominators" + description := "cancel denominators" transform := fun pf => (do let (_, lhs) ← parseCompAndExpr (← inferType pf) guard <| lhs.containsConst <| fun n => @@ -288,7 +288,8 @@ partial def findSquares (s : RBSet (Nat × Bool) lexOrd.compare) (e : Expr) : | _ => e.foldlM findSquares s /-- Get proofs of `-x^2 ≤ 0` and `-(x*x) ≤ 0`, when those terms appear in `ls` -/ -private def nlinarithGetSquareProofs (ls : List Expr) : MetaM (List Expr) := do +private def nlinarithGetSquareProofs (ls : List Expr) : MetaM (List Expr) := + withTraceNode `linarith (return m!"{exceptEmoji ·} finding squares") do -- find the squares in `AtomM` to ensure deterministic behavior let s ← AtomM.run .reducible do let si ← ls.foldrM (fun h s' => do findSquares s' (← instantiateMVars (← inferType h))) @@ -297,8 +298,7 @@ private def nlinarithGetSquareProofs (ls : List Expr) : MetaM (List Expr) := do let new_es ← s.filterMapM fun (e, is_sq) => observing? <| mkAppM (if is_sq then ``sq_nonneg else ``mul_self_nonneg) #[e] let new_es ← compWithZero.globalize.transform new_es - trace[linarith] "nlinarith preprocessing found squares" - trace[linarith] "{s}" + trace[linarith] "found:{indentD <| toMessageData s}" linarithTraceProofs "so we added proofs" new_es return new_es @@ -308,7 +308,8 @@ Get proofs for products of inequalities from `ls`. Note that the length of the resulting list is proportional to `ls.length^2`, which can make a large amount of work for the linarith oracle. -/ -private def nlinarithGetProductsProofs (ls : List Expr) : MetaM (List Expr) := do +private def nlinarithGetProductsProofs (ls : List Expr) : MetaM (List Expr) := + withTraceNode `linarith (return m!"{exceptEmoji ·} adding product terms") do let with_comps ← ls.mapM (fun e => do let tp ← inferType e try @@ -341,7 +342,7 @@ private def nlinarithGetProductsProofs (ls : List Expr) : MetaM (List Expr) := d This preprocessor is typically run last, after all inputs have been canonized. -/ def nlinarithExtras : GlobalPreprocessor where - name := "nonlinear arithmetic extras" + description := "nonlinear arithmetic extras" transform ls := do let new_es ← nlinarithGetSquareProofs ls let products ← nlinarithGetProductsProofs (new_es ++ ls) @@ -374,7 +375,7 @@ by calling `linarith.removeNe_aux`. This produces `2^n` branches when there are `n` such hypotheses in the input. -/ def removeNe : GlobalBranchingPreprocessor where - name := "removeNe" + description := "case split on ≠" transform := removeNe_aux end removeNe @@ -394,7 +395,10 @@ Note that a preprocessor may produce multiple or no expressions from each input so the size of the list may change. -/ def preprocess (pps : List GlobalBranchingPreprocessor) (g : MVarId) (l : List Expr) : - MetaM (List Branch) := g.withContext <| - pps.foldlM (fun ls pp => return (← ls.mapM fun (g, l) => do pp.process g l).flatten) [(g, l)] + MetaM (List Branch) := do + withTraceNode `linarith (fun e => return m!"{exceptEmoji e} Running preprocessors") <| + g.withContext <| + pps.foldlM (init := [(g, l)]) fun ls pp => do + return (← ls.mapM fun (g, l) => do pp.process g l).flatten end Linarith diff --git a/Mathlib/Tactic/Linarith/Verification.lean b/Mathlib/Tactic/Linarith/Verification.lean index d9d9128bfee29..2a5e07a579937 100644 --- a/Mathlib/Tactic/Linarith/Verification.lean +++ b/Mathlib/Tactic/Linarith/Verification.lean @@ -191,41 +191,52 @@ def proveFalseByLinarith (transparency : TransparencyMode) (oracle : Certificate (discharger : TacticM Unit) : MVarId → List Expr → MetaM Expr | _, [] => throwError "no args to linarith" | g, l@(h::_) => do - trace[linarith.detail] "Beginning work in `proveFalseByLinarith`." Lean.Core.checkSystem decl_name%.toString -- for the elimination to work properly, we must add a proof of `-1 < 0` to the list, -- along with negated equality proofs. - let l' ← addNegEqProofs l - trace[linarith.detail] "... finished `addNegEqProofs`." - let inputs := (← mkNegOneLtZeroProof (← typeOfIneqProof h))::l'.reverse - trace[linarith.detail] "... finished `mkNegOneLtZeroProof`." - trace[linarith.detail] (← inputs.mapM inferType) - let (comps, max_var) ← linearFormsAndMaxVar transparency inputs - trace[linarith.detail] "... finished `linearFormsAndMaxVar`." - trace[linarith.detail] "{comps}" + let l' ← detailTrace "addNegEqProofs" <| addNegEqProofs l + let inputs ← detailTrace "mkNegOneLtZeroProof" <| + return (← mkNegOneLtZeroProof (← typeOfIneqProof h))::l'.reverse + trace[linarith.detail] "inputs:{indentD <| toMessageData (← inputs.mapM inferType)}" + let (comps, max_var) ← detailTrace "linearFormsAndMaxVar" <| + linearFormsAndMaxVar transparency inputs + trace[linarith.detail] "comps:{indentD <| toMessageData comps}" -- perform the elimination and fail if no contradiction is found. - let certificate : Std.HashMap Nat Nat ← try - oracle.produceCertificate comps max_var - catch e => - trace[linarith] e.toMessageData - throwError "linarith failed to find a contradiction" - 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[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 - -- let sm ← instantiateMVars sm - trace[linarith] "The expression\n {sm}\nshould be both 0 and negative" + let certificate : Std.HashMap Nat Nat ← + withTraceNode `linarith (return m!"{exceptEmoji ·} Invoking oracle") do + let certificate ← + try + oracle.produceCertificate comps max_var + catch e => + trace[linarith] e.toMessageData + throwError "linarith failed to find a contradiction" + trace[linarith] "found a contradiction: {certificate.toList}" + return certificate + let (sm, zip) ← + withTraceNode `linarith (return m!"{exceptEmoji ·} Building final expression") do + 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[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 + -- let sm ← instantiateMVars sm + trace[linarith] "{indentD sm}\nshould be both 0 and negative" + return (sm, zip) -- we prove that `sm = 0`, typically with `ring`. - let sm_eq_zero ← proveEqZeroUsing discharger sm + let sm_eq_zero ← detailTrace "proveEqZeroUsing" <| proveEqZeroUsing discharger sm -- we also prove that `sm < 0` - let sm_lt_zero ← mkLTZeroProof zip - -- this is a contradiction. - let pftp ← inferType sm_lt_zero - let ⟨_, nep, _⟩ ← g.rewrite pftp sm_eq_zero - let pf' ← mkAppM ``Eq.mp #[nep, sm_lt_zero] - mkAppM ``Linarith.lt_irrefl #[pf'] + let sm_lt_zero ← detailTrace "mkLTZeroProof" <| mkLTZeroProof zip + detailTrace "Linarith.lt_irrefl" do + -- this is a contradiction. + let pftp ← inferType sm_lt_zero + let ⟨_, nep, _⟩ ← g.rewrite pftp sm_eq_zero + let pf' ← mkAppM ``Eq.mp #[nep, sm_lt_zero] + mkAppM ``Linarith.lt_irrefl #[pf'] +where + /-- Log `f` under `linarith.detail`, with exception emojis and the provided name. -/ + detailTrace {α} (s : String) (f : MetaM α) : MetaM α := + withTraceNode `linarith.detail (return m!"{exceptEmoji ·} {s}") f end Linarith From 781c75b11cc46547f0f22ec4d138080a85b659ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 11 Jan 2025 10:36:57 +0000 Subject: [PATCH 157/681] feat: approximate subgroups (#20050) Define approximate subgroups of a group, namely symmetric sets `A` such that `A * A` can be covered by a small number of translates of `A`. From GrowthInGroups (LeanCamCombi) Co-authored-by: Bhavik Mehta --- Mathlib.lean | 1 + .../Additive/ApproximateSubgroup.lean | 210 ++++++++++++++++++ scripts/noshake.json | 2 + 3 files changed, 213 insertions(+) create mode 100644 Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean diff --git a/Mathlib.lean b/Mathlib.lean index cef321f295446..b768c39ed289f 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2244,6 +2244,7 @@ import Mathlib.CategoryTheory.WithTerminal import Mathlib.CategoryTheory.Yoneda import Mathlib.Combinatorics.Additive.AP.Three.Behrend import Mathlib.Combinatorics.Additive.AP.Three.Defs +import Mathlib.Combinatorics.Additive.ApproximateSubgroup import Mathlib.Combinatorics.Additive.CauchyDavenport import Mathlib.Combinatorics.Additive.Corner.Defs import Mathlib.Combinatorics.Additive.Corner.Roth diff --git a/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean b/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean new file mode 100644 index 0000000000000..208904c043257 --- /dev/null +++ b/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2024 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Bhavik Mehta +-/ +import Mathlib.Algebra.Group.Subgroup.Pointwise +import Mathlib.Combinatorics.Additive.CovBySMul +import Mathlib.Combinatorics.Additive.RuzsaCovering +import Mathlib.Combinatorics.Additive.SmallTripling + +/-! +# Approximate subgroups + +This file defines approximate subgroups of a group, namely symmetric sets `A` such that `A * A` can +be covered by a small number of translates of `A`. + +## Main results + +Approximate subgroups are a central concept in additive combinatorics, as a natural weakening and +flexible substitute of genuine subgroups. As such, they share numerous properties with subgroups: +* `IsApproximateSubgroup.image`: Group homomorphisms send approximate subgroups to approximate + subgroups +* `IsApproximateSubgroup.pow_inter_pow`: The intersection of (non-trivial powers of) two approximate + subgroups is an approximate subgroup. Warning: The intersection of two approximate subgroups isn't + an approximate subgroup in general. + +Approximate subgroups are close qualitatively and quantitatively to other concepts in additive +combinatorics: +* `IsApproximateSubgroup.card_pow_le`: An approximate subgroup has small powers. +* `IsApproximateSubgroup.of_small_tripling`: A set of small tripling can be made an approximate + subgroup by squaring. + +It can be readily confirmed that approximate subgroups are a weakening of subgroups: +* `isApproximateSubgroup_one`: A 1-approximate subgroup is the same thing as a subgroup. +-/ + +open scoped Finset Pointwise + +variable {G : Type*} [Group G] {A B : Set G} {K L : ℝ} {m n : ℕ} + +/-- +An approximate subgroup in a group is a symmetric set `A` containing the identity and such that +`A + A` can be covered by a small number of translates of `A`. + +In practice, we will take `K` fixed and `A` large but finite. +-/ +structure IsApproximateAddSubgroup {G : Type*} [AddGroup G] (K : ℝ) (A : Set G) : Prop where + zero_mem : 0 ∈ A + neg_eq_self : -A = A + two_nsmul_covByVAdd : CovByVAdd G K (2 • A) A + +/-- +An approximate subgroup in a group is a symmetric set `A` containing the identity and such that +`A * A` can be covered by a small number of translates of `A`. + +In practice, we will take `K` fixed and `A` large but finite. +-/ +@[to_additive] +structure IsApproximateSubgroup (K : ℝ) (A : Set G) : Prop where + one_mem : 1 ∈ A + inv_eq_self : A⁻¹ = A + sq_covBySMul : CovBySMul G K (A ^ 2) A + +namespace IsApproximateSubgroup + +@[to_additive] lemma nonempty (hA : IsApproximateSubgroup K A) : A.Nonempty := ⟨1, hA.one_mem⟩ + +@[to_additive one_le] +lemma one_le (hA : IsApproximateSubgroup K A) : 1 ≤ K := by + obtain ⟨F, hF, hSF⟩ := hA.sq_covBySMul + have hF₀ : F ≠ ∅ := by rintro rfl; simp [hA.nonempty.pow.ne_empty] at hSF + exact hF.trans' <| by simpa [Finset.nonempty_iff_ne_empty] + +@[to_additive] +lemma mono (hKL : K ≤ L) (hA : IsApproximateSubgroup K A) : IsApproximateSubgroup L A where + one_mem := hA.one_mem + inv_eq_self := hA.inv_eq_self + sq_covBySMul := hA.sq_covBySMul.mono hKL + +@[to_additive] +lemma card_pow_le [DecidableEq G] {A : Finset G} (hA : IsApproximateSubgroup K (A : Set G)) : + ∀ {n}, #(A ^ n) ≤ K ^ (n - 1) * #A + | 0 => by simpa using hA.nonempty + | 1 => by simp + | n + 2 => by + obtain ⟨F, hF, hSF⟩ := hA.sq_covBySMul + calc + (#(A ^ (n + 2)) : ℝ) ≤ #(F ^ (n + 1) * A) := by + gcongr; exact mod_cast Set.pow_subset_pow_mul_of_sq_subset_mul hSF (by omega) + _ ≤ #(F ^ (n + 1)) * #A := mod_cast Finset.card_mul_le + _ ≤ #F ^ (n + 1) * #A := by gcongr; exact mod_cast Finset.card_pow_le + _ ≤ K ^ (n + 1) * #A := by gcongr + +@[to_additive] +lemma card_mul_self_le [DecidableEq G] {A : Finset G} (hA : IsApproximateSubgroup K (A : Set G)) : + #(A * A) ≤ K * #A := by simpa [sq] using hA.card_pow_le (n := 2) + +@[to_additive] +lemma image {F H : Type*} [Group H] [FunLike F G H] [MonoidHomClass F G H] (f : F) + (hA : IsApproximateSubgroup K A) : IsApproximateSubgroup K (f '' A) where + one_mem := ⟨1, hA.one_mem, map_one _⟩ + inv_eq_self := by simp [← Set.image_inv, hA.inv_eq_self] + sq_covBySMul := by + classical + obtain ⟨F, hF, hAF⟩ := hA.sq_covBySMul + refine ⟨F.image f, ?_, ?_⟩ + · calc + (#(F.image f) : ℝ) ≤ #F := mod_cast F.card_image_le + _ ≤ K := hF + · simp only [← Set.image_pow, Finset.coe_image, ← Set.image_mul, smul_eq_mul] at hAF ⊢ + gcongr + +@[to_additive] +lemma subgroup {S : Type*} [SetLike S G] [SubgroupClass S G] {H : S} : + IsApproximateSubgroup 1 (H : Set G) where + one_mem := OneMemClass.one_mem H + inv_eq_self := inv_coe_set + sq_covBySMul := ⟨{1}, by simp⟩ + +open Finset in +@[to_additive] +lemma of_small_tripling [DecidableEq G] {A : Finset G} (hA₁ : 1 ∈ A) (hAsymm : A⁻¹ = A) + (hA : #(A ^ 3) ≤ K * #A) : IsApproximateSubgroup (K ^ 3) (A ^ 2 : Set G) where + one_mem := by rw [sq, ← one_mul 1]; exact Set.mul_mem_mul hA₁ hA₁ + inv_eq_self := by simp [← inv_pow, hAsymm, ← coe_inv] + sq_covBySMul := by + replace hA := calc (#(A ^ 4 * A) : ℝ) + _ = #(A ^ 5) := by rw [← pow_succ] + _ ≤ K ^ 3 * #A := small_pow_of_small_tripling' (by omega) hA hAsymm + have hA₀ : A.Nonempty := ⟨1, hA₁⟩ + obtain ⟨F, -, hF, hAF⟩ := ruzsa_covering_mul hA₀ hA + exact ⟨F, hF, by norm_cast; simpa [div_eq_mul_inv, pow_succ, mul_assoc, hAsymm] using hAF⟩ + +open Set in +@[to_additive] +lemma pow_inter_pow_covBySMul_sq_inter_sq + (hA : IsApproximateSubgroup K A) (hB : IsApproximateSubgroup L B) (hm : 2 ≤ m) (hn : 2 ≤ n) : + CovBySMul G (K ^ (m - 1) * L ^ (n - 1)) (A ^ m ∩ B ^ n) (A ^ 2 ∩ B ^ 2) := by + classical + obtain ⟨F₁, hF₁, hAF₁⟩ := hA.sq_covBySMul + obtain ⟨F₂, hF₂, hBF₂⟩ := hB.sq_covBySMul + have := hA.one_le + choose f hf using exists_smul_inter_smul_subset_smul_inv_mul_inter_inv_mul A B + refine ⟨.image₂ f (F₁ ^ (m - 1)) (F₂ ^ (n - 1)), ?_, ?_⟩ + · calc + (#(.image₂ f (F₁ ^ (m - 1)) (F₂ ^ (n - 1))) : ℝ) + _ ≤ #(F₁ ^ (m - 1)) * #(F₂ ^ (n - 1)) := mod_cast Finset.card_image₂_le .. + _ ≤ #F₁ ^ (m - 1) * #F₂ ^ (n - 1) := by gcongr <;> exact mod_cast Finset.card_pow_le + _ ≤ K ^ (m - 1) * L ^ (n - 1) := by gcongr + · calc + A ^ m ∩ B ^ n ⊆ (F₁ ^ (m - 1) * A) ∩ (F₂ ^ (n - 1) * B) := by + gcongr <;> apply pow_subset_pow_mul_of_sq_subset_mul <;> norm_cast <;> omega + _ = ⋃ (a ∈ F₁ ^ (m - 1)) (b ∈ F₂ ^ (n - 1)), a • A ∩ b • B := by + simp_rw [← smul_eq_mul, ← iUnion_smul_set, iUnion₂_inter_iUnion₂]; norm_cast + _ ⊆ ⋃ (a ∈ F₁ ^ (m - 1)) (b ∈ F₂ ^ (n - 1)), f a b • (A⁻¹ * A ∩ (B⁻¹ * B)) := by + gcongr; exact hf .. + _ = (Finset.image₂ f (F₁ ^ (m - 1)) (F₂ ^ (n - 1))) * (A ^ 2 ∩ B ^ 2) := by + simp_rw [hA.inv_eq_self, hB.inv_eq_self, ← sq] + rw [Finset.coe_image₂, ← smul_eq_mul, ← iUnion_smul_set, biUnion_image2] + simp_rw [Finset.mem_coe] + +open Set in +@[to_additive] +lemma pow_inter_pow (hA : IsApproximateSubgroup K A) (hB : IsApproximateSubgroup L B) (hm : 2 ≤ m) + (hn : 2 ≤ n) : + IsApproximateSubgroup (K ^ (2 * m - 1) * L ^ (2 * n - 1)) (A ^ m ∩ B ^ n) where + one_mem := ⟨Set.one_mem_pow hA.one_mem, Set.one_mem_pow hB.one_mem⟩ + inv_eq_self := by simp_rw [inter_inv, ← inv_pow, hA.inv_eq_self, hB.inv_eq_self] + sq_covBySMul := by + refine (hA.pow_inter_pow_covBySMul_sq_inter_sq hB (by omega) (by omega)).subset ?_ + (by gcongr; exacts [hA.one_mem, hB.one_mem]) + calc + (A ^ m ∩ B ^ n) ^ 2 ⊆ (A ^ m) ^ 2 ∩ (B ^ n) ^ 2 := Set.inter_pow_subset + _ = A ^ (2 * m) ∩ B ^ (2 * n) := by simp [pow_mul'] + +end IsApproximateSubgroup + +open Set in +/-- A `1`-approximate subgroup is the same thing as a subgroup. -/ +@[to_additive (attr := simp) +"A `1`-approximate subgroup is the same thing as a subgroup."] +lemma isApproximateSubgroup_one {A : Set G} : + IsApproximateSubgroup 1 (A : Set G) ↔ ∃ H : Subgroup G, H = A where + mp hA := by + suffices A * A ⊆ A from + let H : Subgroup G := + { carrier := A + one_mem' := hA.one_mem + inv_mem' hx := by dsimp; rwa [← hA.inv_eq_self, inv_mem_inv] + mul_mem' hx hy := this (mul_mem_mul hx hy) } + ⟨H, rfl⟩ + obtain ⟨x, hx⟩ : ∃ x : G, A * A ⊆ x • A := by + obtain ⟨K, hK, hKA⟩ := hA.sq_covBySMul + simp only [Nat.cast_le_one, Finset.card_le_one_iff_subset_singleton, + Finset.subset_singleton_iff] at hK + obtain ⟨x, rfl | rfl⟩ := hK + · simp [hA.nonempty.ne_empty] at hKA + · rw [Finset.coe_singleton, singleton_smul, sq] at hKA + use x + have hx' : x ⁻¹ • (A * A) ⊆ A := by rwa [← subset_set_smul_iff] + have hx_inv : x⁻¹ ∈ A := by + simpa using hx' (smul_mem_smul_set (mul_mem_mul hA.one_mem hA.one_mem)) + have hx_sq : x * x ∈ A := by + rw [← hA.inv_eq_self] + simpa using hx' (smul_mem_smul_set (mul_mem_mul hx_inv hA.one_mem)) + calc A * A ⊆ x • A := by assumption + _ = x⁻¹ • (x * x) • A := by simp [sq, smul_smul] + _ ⊆ x⁻¹ • (A • A) := smul_set_mono (smul_set_subset_smul hx_sq) + _ ⊆ A := hx' + mpr := by rintro ⟨H, rfl⟩; exact .subgroup diff --git a/scripts/noshake.json b/scripts/noshake.json index adffc77f1f757..246720f089eb3 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -406,6 +406,8 @@ ["Mathlib.Algebra.Order.Field.Basic"], "Mathlib.Combinatorics.SetFamily.AhlswedeZhang": ["Mathlib.Algebra.Order.Field.Basic"], + "Mathlib.Combinatorics.Additive.ApproximateSubgroup": + ["Mathlib.Tactic.Bound"], "Mathlib.CategoryTheory.Sites.IsSheafFor": ["Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono"], "Mathlib.CategoryTheory.Preadditive.Basic": ["Mathlib.Algebra.Module.End"], From c675cb586e7054488ba6962911a6e348356d8f33 Mon Sep 17 00:00:00 2001 From: Anthony D Date: Sat, 11 Jan 2025 13:16:38 +0000 Subject: [PATCH 158/681] feat(Data/List/ReduceOption): add replicate theorems (#20644) These theorems make it easier to prove statements about `List.reduceOption`, building up to a more general theorem, `reduceOption_eq_concat_iff`, which is useful for inductive proofs. --- Mathlib/Data/List/ReduceOption.lean | 63 ++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/Mathlib/Data/List/ReduceOption.lean b/Mathlib/Data/List/ReduceOption.lean index 8994967357edb..4e1c64731f5ac 100644 --- a/Mathlib/Data/List/ReduceOption.lean +++ b/Mathlib/Data/List/ReduceOption.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yakov Pechersky +Authors: Yakov Pechersky, Anthony DeRossi -/ import Mathlib.Data.List.Basic @@ -40,6 +40,67 @@ theorem reduceOption_append (l l' : List (Option α)) : (l ++ l').reduceOption = l.reduceOption ++ l'.reduceOption := filterMap_append l l' id +@[simp] +theorem reduceOption_replicate_none {n : ℕ} : (replicate n (@none α)).reduceOption = [] := by + dsimp [reduceOption] + rw [filterMap_replicate_of_none] + rfl + +theorem reduceOption_eq_nil_iff (l : List (Option α)) : + l.reduceOption = [] ↔ ∃ n, l = replicate n none := by + dsimp [reduceOption] + rw [filterMap_eq_nil_iff] + constructor + · intro h + exact ⟨l.length, eq_replicate_of_mem h⟩ + · intro ⟨_, h⟩ + simp_rw [h, mem_replicate] + tauto + +theorem reduceOption_eq_singleton_iff (l : List (Option α)) (a : α) : + l.reduceOption = [a] ↔ ∃ m n, l = replicate m none ++ some a :: replicate n none := by + dsimp [reduceOption] + constructor + · intro h + rw [filterMap_eq_cons_iff] at h + obtain ⟨l₁, _, l₂, h, hl₁, ⟨⟩, hl₂⟩ := h + rw [filterMap_eq_nil_iff] at hl₂ + apply eq_replicate_of_mem at hl₁ + apply eq_replicate_of_mem at hl₂ + rw [h, hl₁, hl₂] + use l₁.length, l₂.length + · intro ⟨_, _, h⟩ + simp only [h, filterMap_append, filterMap_cons_some, filterMap_replicate_of_none, id_eq, + nil_append, Option.some.injEq] + +theorem reduceOption_eq_append_iff (l : List (Option α)) (l'₁ l'₂ : List α) : + l.reduceOption = l'₁ ++ l'₂ ↔ + ∃ l₁ l₂, l = l₁ ++ l₂ ∧ l₁.reduceOption = l'₁ ∧ l₂.reduceOption = l'₂ := by + dsimp [reduceOption] + constructor + · intro h + rw [filterMap_eq_append_iff] at h + trivial + · intro ⟨_, _, h, hl₁, hl₂⟩ + rw [h, filterMap_append, hl₁, hl₂] + +theorem reduceOption_eq_concat_iff (l : List (Option α)) (l' : List α) (a : α) : + l.reduceOption = l'.concat a ↔ + ∃ l₁ l₂, l = l₁ ++ some a :: l₂ ∧ l₁.reduceOption = l' ∧ l₂.reduceOption = [] := by + rw [concat_eq_append] + constructor + · intro h + rw [reduceOption_eq_append_iff] at h + obtain ⟨l₁, _, h, hl₁, hl₂⟩ := h + rw [reduceOption_eq_singleton_iff] at hl₂ + obtain ⟨m, n, hl₂⟩ := hl₂ + use l₁ ++ replicate m none, replicate n none + simp_rw [h, reduceOption_append, reduceOption_replicate_none, append_assoc, append_nil, hl₁, + hl₂] + trivial + · intro ⟨_, _, h, hl₁, hl₂⟩ + rw [h, reduceOption_append, reduceOption_cons_of_some, hl₁, hl₂] + theorem reduceOption_length_eq {l : List (Option α)} : l.reduceOption.length = (l.filter Option.isSome).length := by induction' l with hd tl hl From cdcfe3a44b992d9706e9006312b82dab4acdc660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 11 Jan 2025 13:24:50 +0000 Subject: [PATCH 159/681] chore(CategoryTheory): make NormalEpi/MonoCategory and RegularEpi/MonoCategory props (#19548) The names are now prefixed with `Is`. As a result, the definition of an abelian category `Abelian` only involve props in addition to the `Preadditive` instance. With this design, we may avoid diamonds for `Abelian` instance in some future works (e.g. the abelian category structure on the heart of a t-structure). --- Mathlib/Algebra/Category/Grp/Abelian.lean | 5 +- .../Algebra/Category/ModuleCat/Abelian.lean | 4 +- .../Category/ModuleCat/Presheaf/Abelian.lean | 12 ++--- .../Homology/HomologicalComplexAbelian.lean | 12 ++--- Mathlib/CategoryTheory/Abelian/Basic.lean | 46 ++++++------------- .../Abelian/NonPreadditive.lean | 4 +- Mathlib/CategoryTheory/Abelian/Opposite.lean | 4 +- Mathlib/CategoryTheory/Adhesive.lean | 8 ++-- .../Limits/Shapes/NormalMono/Basic.lean | 42 +++++++++-------- .../Limits/Shapes/NormalMono/Equalizers.lean | 4 +- .../Limits/Shapes/RegularMono.lean | 38 ++++++++------- 11 files changed, 85 insertions(+), 94 deletions(-) diff --git a/Mathlib/Algebra/Category/Grp/Abelian.lean b/Mathlib/Algebra/Category/Grp/Abelian.lean index fb193bc6cc250..859f3a167bd1d 100644 --- a/Mathlib/Algebra/Category/Grp/Abelian.lean +++ b/Mathlib/Algebra/Category/Grp/Abelian.lean @@ -36,8 +36,7 @@ def normalEpi (_ : Epi f) : NormalEpi f := /-- The category of abelian groups is abelian. -/ instance : Abelian AddCommGrp.{u} where - has_finite_products := ⟨HasFiniteProducts.out⟩ - normalMonoOfMono := normalMono - normalEpiOfEpi := normalEpi + normalMonoOfMono f hf := ⟨normalMono f hf⟩ + normalEpiOfEpi f hf := ⟨normalEpi f hf⟩ end AddCommGrp diff --git a/Mathlib/Algebra/Category/ModuleCat/Abelian.lean b/Mathlib/Algebra/Category/ModuleCat/Abelian.lean index 2bb2a6d564458..7bc4d6d27d08d 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Abelian.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Abelian.lean @@ -71,8 +71,8 @@ def normalEpi (hf : Epi f) : NormalEpi f where /-- The category of R-modules is abelian. -/ instance abelian : Abelian (ModuleCat.{v} R) where has_cokernels := hasCokernels_moduleCat - normalMonoOfMono := normalMono - normalEpiOfEpi := normalEpi + normalMonoOfMono f hf := ⟨normalMono f hf⟩ + normalEpiOfEpi f hf := ⟨normalEpi f hf⟩ section ReflectsLimits diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean index 42747bed79af5..cb0173d079628 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean @@ -21,15 +21,15 @@ namespace PresheafOfModules variable {C : Type u₁} [Category.{v₁} C] (R : Cᵒᵖ ⥤ RingCat.{u}) -noncomputable instance : NormalEpiCategory (PresheafOfModules.{v} R) where - normalEpiOfEpi p _ := NormalEpi.mk _ (kernel.ι p) (kernel.condition _) +noncomputable instance : IsNormalEpiCategory (PresheafOfModules.{v} R) where + normalEpiOfEpi p _ := ⟨NormalEpi.mk _ (kernel.ι p) (kernel.condition _) (evaluationJointlyReflectsColimits _ _ (fun _ => - Abelian.isColimitMapCoconeOfCokernelCoforkOfπ _ _)) + Abelian.isColimitMapCoconeOfCokernelCoforkOfπ _ _))⟩ -noncomputable instance : NormalMonoCategory (PresheafOfModules.{v} R) where - normalMonoOfMono i _ := NormalMono.mk _ (cokernel.π i) (cokernel.condition _) +noncomputable instance : IsNormalMonoCategory (PresheafOfModules.{v} R) where + normalMonoOfMono i _ := ⟨NormalMono.mk _ (cokernel.π i) (cokernel.condition _) (evaluationJointlyReflectsLimits _ _ (fun _ => - Abelian.isLimitMapConeOfKernelForkOfι _ _)) + Abelian.isLimitMapConeOfKernelForkOfι _ _))⟩ noncomputable instance : Abelian (PresheafOfModules.{v} R) where diff --git a/Mathlib/Algebra/Homology/HomologicalComplexAbelian.lean b/Mathlib/Algebra/Homology/HomologicalComplexAbelian.lean index 3c09698a64498..b2edc9b29cd6d 100644 --- a/Mathlib/Algebra/Homology/HomologicalComplexAbelian.lean +++ b/Mathlib/Algebra/Homology/HomologicalComplexAbelian.lean @@ -23,15 +23,15 @@ namespace HomologicalComplex variable {C ι : Type*} {c : ComplexShape ι} [Category C] [Abelian C] -noncomputable instance : NormalEpiCategory (HomologicalComplex C c) := ⟨fun p _ => - NormalEpi.mk _ (kernel.ι p) (kernel.condition _) +noncomputable instance : IsNormalEpiCategory (HomologicalComplex C c) := ⟨fun p _ => + ⟨NormalEpi.mk _ (kernel.ι p) (kernel.condition _) (isColimitOfEval _ _ (fun _ => - Abelian.isColimitMapCoconeOfCokernelCoforkOfπ _ _))⟩ + Abelian.isColimitMapCoconeOfCokernelCoforkOfπ _ _))⟩⟩ -noncomputable instance : NormalMonoCategory (HomologicalComplex C c) := ⟨fun p _ => - NormalMono.mk _ (cokernel.π p) (cokernel.condition _) +noncomputable instance : IsNormalMonoCategory (HomologicalComplex C c) := ⟨fun p _ => + ⟨NormalMono.mk _ (cokernel.π p) (cokernel.condition _) (isLimitOfEval _ _ (fun _ => - Abelian.isLimitMapConeOfKernelForkOfι _ _))⟩ + Abelian.isLimitMapConeOfKernelForkOfι _ _))⟩⟩ noncomputable instance : Abelian (HomologicalComplex C c) where diff --git a/Mathlib/CategoryTheory/Abelian/Basic.lean b/Mathlib/CategoryTheory/Abelian/Basic.lean index cc0db03e5a10b..34d8b479eb65e 100644 --- a/Mathlib/CategoryTheory/Abelian/Basic.lean +++ b/Mathlib/CategoryTheory/Abelian/Basic.lean @@ -104,7 +104,7 @@ and every epimorphism is the cokernel of some morphism. finite products give a terminal object, and in a preadditive category any terminal object is a zero object.) -/ -class Abelian extends Preadditive C, NormalMonoCategory C, NormalEpiCategory C where +class Abelian extends Preadditive C, IsNormalMonoCategory C, IsNormalEpiCategory C where [has_finite_products : HasFiniteProducts C] [has_kernels : HasKernels C] [has_cokernels : HasCokernels C] @@ -183,9 +183,9 @@ attribute [local instance] Limits.HasFiniteBiproducts.of_hasFiniteProducts /-- A category with finite products in which coimage-image comparisons are all isomorphisms is a normal mono category. -/ -def normalMonoCategory : NormalMonoCategory C where - normalMonoOfMono f m := - { Z := _ +lemma isNormalMonoCategory : IsNormalMonoCategory C where + normalMonoOfMono f m := ⟨{ + Z := _ g := cokernel.π f w := by simp isLimit := by @@ -203,14 +203,14 @@ def normalMonoCategory : NormalMonoCategory C where simp only [KernelFork.ι_ofι, Category.assoc] convert limit.lift_π A WalkingParallelPair.zero using 2 rw [IsIso.inv_comp_eq, eq_comm] - exact (imageMonoFactorisation f).fac } + exact (imageMonoFactorisation f).fac }⟩ /-- A category with finite products in which coimage-image comparisons are all isomorphisms is a normal epi category. -/ -def normalEpiCategory : NormalEpiCategory C where - normalEpiOfEpi f m := - { W := kernel f +lemma isNormalEpiCategory : IsNormalEpiCategory C where + normalEpiOfEpi f m := ⟨{ + W := kernel f g := kernel.ι _ w := kernel.condition _ isColimit := by @@ -229,16 +229,16 @@ def normalEpiCategory : NormalEpiCategory C where simp only [CokernelCofork.π_ofπ, ← Category.assoc] convert colimit.ι_desc A WalkingParallelPair.one using 2 rw [IsIso.comp_inv_eq, IsIso.comp_inv_eq, eq_comm, ← imageMonoFactorisation_e'] - exact (imageMonoFactorisation f).fac } + exact (imageMonoFactorisation f).fac }⟩ end OfCoimageImageComparisonIsIso variable [∀ {X Y : C} (f : X ⟶ Y), IsIso (Abelian.coimageImageComparison f)] [Limits.HasFiniteProducts C] -attribute [local instance] OfCoimageImageComparisonIsIso.normalMonoCategory +attribute [local instance] OfCoimageImageComparisonIsIso.isNormalMonoCategory -attribute [local instance] OfCoimageImageComparisonIsIso.normalEpiCategory +attribute [local instance] OfCoimageImageComparisonIsIso.isNormalEpiCategory /-- A preadditive category with kernels, cokernels, and finite products, in which the coimage-image comparison morphism is always an isomorphism, @@ -763,25 +763,9 @@ namespace CategoryTheory.NonPreadditiveAbelian variable (C : Type u) [Category.{v} C] [NonPreadditiveAbelian C] /-- Every NonPreadditiveAbelian category can be promoted to an abelian category. -/ -def abelian : Abelian C := - {/- We need the `convert`s here because the instances we have are slightly different from the - instances we need: `HasKernels` depends on an instance of `HasZeroMorphisms`. In the - case of `NonPreadditiveAbelian`, this instance is an explicit argument. However, in the case - of `abelian`, the `HasZeroMorphisms` instance is derived from `Preadditive`. So we need to - transform an instance of "has kernels with NonPreadditiveAbelian.HasZeroMorphisms" to an - instance of "has kernels with NonPreadditiveAbelian.Preadditive.HasZeroMorphisms". - Luckily, we have a `subsingleton` instance for `HasZeroMorphisms`, so `convert` can - immediately close the goal it creates for the two instances of `HasZeroMorphisms`, - and the proof is complete. -/ - NonPreadditiveAbelian.preadditive with - has_finite_products := by infer_instance - has_kernels := by convert (by infer_instance : Limits.HasKernels C) - has_cokernels := by convert (by infer_instance : Limits.HasCokernels C) - normalMonoOfMono := by - intro _ _ f _ - convert normalMonoOfMono f - normalEpiOfEpi := by - intro _ _ f _ - convert normalEpiOfEpi f } +def abelian : Abelian C where + toPreadditive := NonPreadditiveAbelian.preadditive + normalMonoOfMono := fun f _ ↦ ⟨normalMonoOfMono f⟩ + normalEpiOfEpi := fun f _ ↦ ⟨normalEpiOfEpi f⟩ end CategoryTheory.NonPreadditiveAbelian diff --git a/Mathlib/CategoryTheory/Abelian/NonPreadditive.lean b/Mathlib/CategoryTheory/Abelian/NonPreadditive.lean index 8f4d7dda4a14c..d08fb1dbb492f 100644 --- a/Mathlib/CategoryTheory/Abelian/NonPreadditive.lean +++ b/Mathlib/CategoryTheory/Abelian/NonPreadditive.lean @@ -65,8 +65,8 @@ variable (C : Type u) [Category.{v} C] /-- We call a category `NonPreadditiveAbelian` if it has a zero object, kernels, cokernels, binary products and coproducts, and every monomorphism and every epimorphism is normal. -/ -class NonPreadditiveAbelian extends HasZeroMorphisms C, NormalMonoCategory C, - NormalEpiCategory C where +class NonPreadditiveAbelian extends HasZeroMorphisms C, IsNormalMonoCategory C, + IsNormalEpiCategory C where [has_zero_object : HasZeroObject C] [has_kernels : HasKernels C] [has_cokernels : HasCokernels C] diff --git a/Mathlib/CategoryTheory/Abelian/Opposite.lean b/Mathlib/CategoryTheory/Abelian/Opposite.lean index d0af389e041d3..32e1525ad0bee 100644 --- a/Mathlib/CategoryTheory/Abelian/Opposite.lean +++ b/Mathlib/CategoryTheory/Abelian/Opposite.lean @@ -30,8 +30,8 @@ instance : Abelian Cᵒᵖ := by -- Porting note: priorities of `Abelian.has_kernels` and `Abelian.has_cokernels` have -- been set to 90 in `Abelian.Basic` in order to prevent a timeout here exact { - normalMonoOfMono := fun f => normalMonoOfNormalEpiUnop _ (normalEpiOfEpi f.unop) - normalEpiOfEpi := fun f => normalEpiOfNormalMonoUnop _ (normalMonoOfMono f.unop) } + normalMonoOfMono := fun f => ⟨normalMonoOfNormalEpiUnop _ (normalEpiOfEpi f.unop)⟩ + normalEpiOfEpi := fun f => ⟨normalEpiOfNormalMonoUnop _ (normalMonoOfMono f.unop)⟩ } section diff --git a/Mathlib/CategoryTheory/Adhesive.lean b/Mathlib/CategoryTheory/Adhesive.lean index 1337051cd7b2a..f3442943b97d0 100644 --- a/Mathlib/CategoryTheory/Adhesive.lean +++ b/Mathlib/CategoryTheory/Adhesive.lean @@ -238,14 +238,14 @@ instance Type.adhesive : Adhesive (Type u) := (IsPushout.isVanKampen_inl _ (Types.isCoprodOfMono f) _ _ _ H.flip).flip⟩ noncomputable instance (priority := 100) Adhesive.toRegularMonoCategory [Adhesive C] : - RegularMonoCategory C := - ⟨fun f _ => - { Z := pushout f f + IsRegularMonoCategory C := + ⟨fun f _ => ⟨{ + Z := pushout f f left := pushout.inl _ _ right := pushout.inr _ _ w := pushout.condition isLimit := (Adhesive.isPullback_of_isPushout_of_mono_left - (IsPushout.of_hasPushout f f)).isLimitFork }⟩ + (IsPushout.of_hasPushout f f)).isLimitFork }⟩⟩ -- This then implies that adhesive categories are balanced example [Adhesive C] : Balanced C := diff --git a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean index 8fba6cab9585a..2dfe7ec370a0c 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean @@ -17,7 +17,7 @@ as well as the dual construction for normal epimorphisms. We show equivalences r monomorphisms (`CategoryTheory.equivalenceReflectsNormalMono`), and that the pullback of a normal monomorphism is normal (`CategoryTheory.normalOfIsPullbackSndOfNormal`). -We also define classes `NormalMonoCategory` and `NormalEpiCategory` for classes in which +We also define classes `IsNormalMonoCategory` and `IsNormalEpiCategory` for categories in which every monomorphism or epimorphism is normal, and deduce that these categories are `RegularMonoCategory`s resp. `RegularEpiCategory`s. @@ -114,23 +114,25 @@ section variable (C) /-- A normal mono category is a category in which every monomorphism is normal. -/ -class NormalMonoCategory where - normalMonoOfMono : ∀ {X Y : C} (f : X ⟶ Y) [Mono f], NormalMono f +class IsNormalMonoCategory : Prop where + normalMonoOfMono : ∀ {X Y : C} (f : X ⟶ Y) [Mono f], Nonempty (NormalMono f) -attribute [inherit_doc NormalMonoCategory] NormalMonoCategory.normalMonoOfMono +attribute [inherit_doc IsNormalMonoCategory] IsNormalMonoCategory.normalMonoOfMono + +@[deprecated (since := "2024-11-27")] alias NormalMonoCategory := IsNormalMonoCategory end /-- In a category in which every monomorphism is normal, we can express every monomorphism as a kernel. This is not an instance because it would create an instance loop. -/ -def normalMonoOfMono [NormalMonoCategory C] (f : X ⟶ Y) [Mono f] : NormalMono f := - NormalMonoCategory.normalMonoOfMono _ +def normalMonoOfMono [IsNormalMonoCategory C] (f : X ⟶ Y) [Mono f] : NormalMono f := + (IsNormalMonoCategory.normalMonoOfMono _).some -instance (priority := 100) regularMonoCategoryOfNormalMonoCategory [NormalMonoCategory C] : - RegularMonoCategory C where - regularMonoOfMono f _ := by +instance (priority := 100) regularMonoCategoryOfNormalMonoCategory [IsNormalMonoCategory C] : + IsRegularMonoCategory C where + regularMonoOfMono f _ := ⟨by haveI := normalMonoOfMono f - infer_instance + infer_instance⟩ end @@ -252,22 +254,24 @@ section variable (C) /-- A normal epi category is a category in which every epimorphism is normal. -/ -class NormalEpiCategory where - normalEpiOfEpi : ∀ {X Y : C} (f : X ⟶ Y) [Epi f], NormalEpi f +class IsNormalEpiCategory : Prop where + normalEpiOfEpi : ∀ {X Y : C} (f : X ⟶ Y) [Epi f], Nonempty (NormalEpi f) + +attribute [inherit_doc IsNormalEpiCategory] IsNormalEpiCategory.normalEpiOfEpi -attribute [inherit_doc NormalEpiCategory] NormalEpiCategory.normalEpiOfEpi +@[deprecated (since := "2024-11-27")] alias NormalEpiCategory := IsNormalEpiCategory end /-- In a category in which every epimorphism is normal, we can express every epimorphism as a kernel. This is not an instance because it would create an instance loop. -/ -def normalEpiOfEpi [NormalEpiCategory C] (f : X ⟶ Y) [Epi f] : NormalEpi f := - NormalEpiCategory.normalEpiOfEpi _ +def normalEpiOfEpi [IsNormalEpiCategory C] (f : X ⟶ Y) [Epi f] : NormalEpi f := + (IsNormalEpiCategory.normalEpiOfEpi _).some -instance (priority := 100) regularEpiCategoryOfNormalEpiCategory [NormalEpiCategory C] : - RegularEpiCategory C where - regularEpiOfEpi f _ := by +instance (priority := 100) regularEpiCategoryOfNormalEpiCategory [IsNormalEpiCategory C] : + IsRegularEpiCategory C where + regularEpiOfEpi f _ := ⟨by haveI := normalEpiOfEpi f - infer_instance + infer_instance⟩ end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Equalizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Equalizers.lean index 67d189d906d5d..0b297de94b8fa 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Equalizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Equalizers.lean @@ -23,7 +23,7 @@ variable {C : Type*} [Category C] [HasZeroMorphisms C] namespace CategoryTheory.NormalMonoCategory -variable [HasFiniteProducts C] [HasKernels C] [NormalMonoCategory C] +variable [HasFiniteProducts C] [HasKernels C] [IsNormalMonoCategory C] /-- The pullback of two monomorphisms exists. -/ @[irreducible, nolint defLemma] -- Porting note: changed to irreducible and a def @@ -173,7 +173,7 @@ end CategoryTheory.NormalMonoCategory namespace CategoryTheory.NormalEpiCategory -variable [HasFiniteCoproducts C] [HasCokernels C] [NormalEpiCategory C] +variable [HasFiniteCoproducts C] [HasCokernels C] [IsNormalEpiCategory C] /-- The pushout of two epimorphisms exists. -/ @[irreducible, nolint defLemma] -- Porting note: made a def and re-added irreducible diff --git a/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean b/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean index c568df46e30c4..dd53ef1090784 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/RegularMono.lean @@ -19,7 +19,7 @@ We give the constructions as well as the dual constructions for regular epimorphisms. Additionally, we give the construction * `RegularEpi ⟶ StrongEpi`. -We also define classes `RegularMonoCategory` and `RegularEpiCategory` for categories in which +We also define classes `IsRegularMonoCategory` and `IsRegularEpiCategory` for categories in which every monomorphism or epimorphism is regular, and deduce that these categories are `StrongMonoCategory`s resp. `StrongEpiCategory`s. @@ -142,24 +142,26 @@ section variable (C) /-- A regular mono category is a category in which every monomorphism is regular. -/ -class RegularMonoCategory where +class IsRegularMonoCategory : Prop where /-- Every monomorphism is a regular monomorphism -/ - regularMonoOfMono : ∀ {X Y : C} (f : X ⟶ Y) [Mono f], RegularMono f + regularMonoOfMono : ∀ {X Y : C} (f : X ⟶ Y) [Mono f], Nonempty (RegularMono f) + +@[deprecated (since := "2024-11-27")] alias RegularMonoCategory := IsRegularMonoCategory end /-- In a category in which every monomorphism is regular, we can express every monomorphism as an equalizer. This is not an instance because it would create an instance loop. -/ -def regularMonoOfMono [RegularMonoCategory C] (f : X ⟶ Y) [Mono f] : RegularMono f := - RegularMonoCategory.regularMonoOfMono _ +def regularMonoOfMono [IsRegularMonoCategory C] (f : X ⟶ Y) [Mono f] : RegularMono f := + (IsRegularMonoCategory.regularMonoOfMono _).some instance (priority := 100) regularMonoCategoryOfSplitMonoCategory [SplitMonoCategory C] : - RegularMonoCategory C where - regularMonoOfMono f _ := by + IsRegularMonoCategory C where + regularMonoOfMono f _ := ⟨by haveI := isSplitMono_of_mono f - infer_instance + infer_instance⟩ -instance (priority := 100) strongMonoCategory_of_regularMonoCategory [RegularMonoCategory C] : +instance (priority := 100) strongMonoCategory_of_regularMonoCategory [IsRegularMonoCategory C] : StrongMonoCategory C where strongMono_of_mono f _ := by haveI := regularMonoOfMono f @@ -278,24 +280,26 @@ section variable (C) /-- A regular epi category is a category in which every epimorphism is regular. -/ -class RegularEpiCategory where +class IsRegularEpiCategory : Prop where /-- Everyone epimorphism is a regular epimorphism -/ - regularEpiOfEpi : ∀ {X Y : C} (f : X ⟶ Y) [Epi f], RegularEpi f + regularEpiOfEpi : ∀ {X Y : C} (f : X ⟶ Y) [Epi f], Nonempty (RegularEpi f) + +@[deprecated (since := "2024-11-27")] alias RegularEpiCategory := IsRegularEpiCategory end /-- In a category in which every epimorphism is regular, we can express every epimorphism as a coequalizer. This is not an instance because it would create an instance loop. -/ -def regularEpiOfEpi [RegularEpiCategory C] (f : X ⟶ Y) [Epi f] : RegularEpi f := - RegularEpiCategory.regularEpiOfEpi _ +def regularEpiOfEpi [IsRegularEpiCategory C] (f : X ⟶ Y) [Epi f] : RegularEpi f := + (IsRegularEpiCategory.regularEpiOfEpi _).some instance (priority := 100) regularEpiCategoryOfSplitEpiCategory [SplitEpiCategory C] : - RegularEpiCategory C where - regularEpiOfEpi f _ := by + IsRegularEpiCategory C where + regularEpiOfEpi f _ := ⟨by haveI := isSplitEpi_of_epi f - infer_instance + infer_instance⟩ -instance (priority := 100) strongEpiCategory_of_regularEpiCategory [RegularEpiCategory C] : +instance (priority := 100) strongEpiCategory_of_regularEpiCategory [IsRegularEpiCategory C] : StrongEpiCategory C where strongEpi_of_epi f _ := by haveI := regularEpiOfEpi f From 85ca5b28aec713c9007232b98fb92ec2f43a0b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 11 Jan 2025 13:40:04 +0000 Subject: [PATCH 160/681] feat(AlgebraicTopology): model categories (#19158) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We formalize the axioms of Quillen's model categories. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 2 + .../ModelCategory/Basic.lean | 66 ++++++++ .../CategoryWithCofibrations.lean | 142 ++++++++++++++++++ docs/references.bib | 12 ++ 4 files changed, 222 insertions(+) create mode 100644 Mathlib/AlgebraicTopology/ModelCategory/Basic.lean create mode 100644 Mathlib/AlgebraicTopology/ModelCategory/CategoryWithCofibrations.lean diff --git a/Mathlib.lean b/Mathlib.lean index b768c39ed289f..da99906eaf208 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1079,6 +1079,8 @@ import Mathlib.AlgebraicTopology.FundamentalGroupoid.InducedMaps import Mathlib.AlgebraicTopology.FundamentalGroupoid.PUnit import Mathlib.AlgebraicTopology.FundamentalGroupoid.Product import Mathlib.AlgebraicTopology.FundamentalGroupoid.SimplyConnected +import Mathlib.AlgebraicTopology.ModelCategory.Basic +import Mathlib.AlgebraicTopology.ModelCategory.CategoryWithCofibrations import Mathlib.AlgebraicTopology.MooreComplex import Mathlib.AlgebraicTopology.Quasicategory.Basic import Mathlib.AlgebraicTopology.Quasicategory.Nerve diff --git a/Mathlib/AlgebraicTopology/ModelCategory/Basic.lean b/Mathlib/AlgebraicTopology/ModelCategory/Basic.lean new file mode 100644 index 0000000000000..3792ed8674c48 --- /dev/null +++ b/Mathlib/AlgebraicTopology/ModelCategory/Basic.lean @@ -0,0 +1,66 @@ +/- +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.CategoryTheory.Limits.Shapes.FiniteLimits +import Mathlib.CategoryTheory.Limits.Shapes.BinaryProducts +import Mathlib.CategoryTheory.MorphismProperty.Composition +import Mathlib.CategoryTheory.MorphismProperty.Factorization +import Mathlib.CategoryTheory.MorphismProperty.Retract +import Mathlib.AlgebraicTopology.ModelCategory.CategoryWithCofibrations + +/-! +# Model categories + +We introduce a typeclass `ModelCategory C` expressing that `C` is equipped with +classes of morphisms named "fibrations", "cofibrations" and "weak equivalences" +with satisfy the axioms of (closed) model categories. + +As a given category `C` may have several model category structures, it is advisable +to define only local instances of `ModelCategory`, or to set these instances on type synonyms. + +## References +* [Daniel G. Quillen, Homotopical algebra][Quillen1967] +* [Paul G. Goerss, John F. Jardine, Simplicial Homotopy Theory][goerss-jardine-2009] + +-/ + +universe v u + +namespace HomotopicalAlgebra + +open CategoryTheory Limits + +variable (C : Type u) [Category.{v} C] + +/-- A model category is a category equipped with classes of morphisms named cofibrations, +fibrations and weak equivalences which satisfies the axioms CM1/CM2/CM3/CM4/CM5 +of (closed) model categories. -/ +class ModelCategory where + categoryWithFibrations : CategoryWithFibrations C := by infer_instance + categoryWithCofibrations : CategoryWithCofibrations C := by infer_instance + categoryWithWeakEquivalences : CategoryWithWeakEquivalences C := by infer_instance + cm1a : HasFiniteLimits C := by infer_instance + cm1b : HasFiniteColimits C := by infer_instance + cm2 : (weakEquivalences C).HasTwoOutOfThreeProperty := by infer_instance + cm3a : (weakEquivalences C).IsStableUnderRetracts := by infer_instance + cm3b : (fibrations C).IsStableUnderRetracts := by infer_instance + cm3c : (cofibrations C).IsStableUnderRetracts := by infer_instance + cm4a {A B X Y : C} (i : A ⟶ B) (p : X ⟶ Y) [Cofibration i] [WeakEquivalence i] [Fibration p] : + HasLiftingProperty i p := by intros; infer_instance + cm4b {A B X Y : C} (i : A ⟶ B) (p : X ⟶ Y) [Cofibration i] [Fibration p] [WeakEquivalence p] : + HasLiftingProperty i p := by intros; infer_instance + cm5a : MorphismProperty.HasFactorization (trivialCofibrations C) (fibrations C) := by + infer_instance + cm5b : MorphismProperty.HasFactorization (cofibrations C) (trivialFibrations C) := by + infer_instance + +namespace ModelCategory + +attribute [instance] categoryWithFibrations categoryWithCofibrations categoryWithWeakEquivalences + cm1a cm1b cm2 cm3a cm3b cm3c cm4a cm4b cm5a cm5b + +end ModelCategory + +end HomotopicalAlgebra diff --git a/Mathlib/AlgebraicTopology/ModelCategory/CategoryWithCofibrations.lean b/Mathlib/AlgebraicTopology/ModelCategory/CategoryWithCofibrations.lean new file mode 100644 index 0000000000000..8f20e469f8375 --- /dev/null +++ b/Mathlib/AlgebraicTopology/ModelCategory/CategoryWithCofibrations.lean @@ -0,0 +1,142 @@ +/- +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.CategoryTheory.MorphismProperty.Basic + +/-! +# Categories with classes of fibrations, cofibrations, weak equivalences + +We introduce typeclasses `CategoryWithFibrations`, `CategoryWithCofibrations` and +`CategoryWithWeakEquivalences` to express that a category `C` is equipped with +classes of morphisms named "fibrations", "cofibrations" or "weak equivalences". + +-/ + +universe v u + +namespace HomotopicalAlgebra + +open CategoryTheory + +variable (C : Type u) [Category.{v} C] + +/-- A category with fibrations is a category equipped with +a class of morphisms named "fibrations". -/ +class CategoryWithFibrations where + /-- the class of fibrations -/ + fibrations : MorphismProperty C + +/-- A category with cofibrations is a category equipped with +a class of morphisms named "cofibrations". -/ +class CategoryWithCofibrations where + /-- the class of cofibrations -/ + cofibrations : MorphismProperty C + +/-- A category with weak equivalences is a category equipped with +a class of morphisms named "weak equivalences". -/ +class CategoryWithWeakEquivalences where + /-- the class of weak equivalences -/ + weakEquivalences : MorphismProperty C + +variable {X Y : C} (f : X ⟶ Y) + +section Fib + +variable [CategoryWithFibrations C] + +/-- The class of fibrations in a category with fibrations. -/ +def fibrations : MorphismProperty C := CategoryWithFibrations.fibrations + +variable {C} + +/-- A morphism `f` satisfies `[Fibration f]` if it belongs to `fibrations C`. -/ +@[mk_iff] +class Fibration : Prop where + mem : fibrations C f + +lemma mem_fibrations [Fibration f] : fibrations C f := Fibration.mem + +end Fib + +section Cof + +variable [CategoryWithCofibrations C] + +/-- The class of cofibrations in a category with cofibrations. -/ +def cofibrations : MorphismProperty C := CategoryWithCofibrations.cofibrations + +variable {C} + +/-- A morphism `f` satisfies `[Cofibration f]` if it belongs to `cofibrations C`. -/ +@[mk_iff] +class Cofibration : Prop where + mem : cofibrations C f + +lemma mem_cofibrations [Cofibration f] : cofibrations C f := Cofibration.mem + +end Cof + +section W + +variable [CategoryWithWeakEquivalences C] + +/-- The class of weak equivalences in a category with weak equivalences. -/ +def weakEquivalences : MorphismProperty C := CategoryWithWeakEquivalences.weakEquivalences + +variable {C} + +/-- A morphism `f` satisfies `[WeakEquivalence f]` if it belongs to `weakEquivalences C`. -/ +@[mk_iff] +class WeakEquivalence : Prop where + mem : weakEquivalences C f + +lemma mem_weakEquivalences [WeakEquivalence f] : weakEquivalences C f := WeakEquivalence.mem + +end W + +section TrivFib + +variable [CategoryWithFibrations C] [CategoryWithWeakEquivalences C] + +/-- A trivial fibration is a morphism that is both a fibration and a weak equivalence. -/ +def trivialFibrations : MorphismProperty C := fibrations C ⊓ weakEquivalences C + +lemma trivialFibrations_sub_fibrations : trivialFibrations C ≤ fibrations C := + fun _ _ _ hf ↦ hf.1 + +lemma trivialFibrations_sub_weakEquivalences : trivialFibrations C ≤ weakEquivalences C := + fun _ _ _ hf ↦ hf.2 + +variable {C} + +lemma mem_trivialFibrations [Fibration f] [WeakEquivalence f] : + trivialFibrations C f := + ⟨mem_fibrations f, mem_weakEquivalences f⟩ + +end TrivFib + +section TrivCof + +variable [CategoryWithCofibrations C] [CategoryWithWeakEquivalences C] + +/-- A trivial cofibration is a morphism that is both a cofibration and a weak equivalence. -/ +def trivialCofibrations : MorphismProperty C := cofibrations C ⊓ weakEquivalences C + +lemma trivialCofibrations_sub_cofibrations : trivialCofibrations C ≤ cofibrations C := + fun _ _ _ hf ↦ hf.1 + +lemma trivialCofibrations_sub_weakEquivalences : trivialCofibrations C ≤ weakEquivalences C := + fun _ _ _ hf ↦ hf.2 + + +variable {C} + +lemma mem_trivialCofibrations [Cofibration f] [WeakEquivalence f] : + trivialCofibrations C f := + ⟨mem_cofibrations f, mem_weakEquivalences f⟩ + +end TrivCof + +end HomotopicalAlgebra diff --git a/docs/references.bib b/docs/references.bib index 8e48b5bc2aa1a..6500fedc36403 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -3122,6 +3122,18 @@ @Article{ Prielipp1970 url = {http://www.jstor.org/stable/27958492} } +@Book{ Quillen1967, + author = {Quillen, Daniel G.}, + title = {Homotopical algebra}, + series = {Lecture Notes in Mathematics}, + volume = {No. 43}, + publisher = {Springer-Verlag, Berlin-New York}, + year = {1967}, + pages = {iv+156 pp. (not consecutively paged)}, + mrclass = {18.20 (55.00)}, + mrnumber = {223432} +} + @InCollection{ ribenboim1971, author = {Ribenboim, Paulo}, title = {\'{E}pimorphismes de modules qui sont n\'{e}cessairement From f5531f2346ba41af2d0af876917a40fd0cb8c732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 11 Jan 2025 16:30:18 +0000 Subject: [PATCH 161/681] feat(Algebra/Category/ModuleCat): pullback of presheaves of modules (#17366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this PR, we construct the pullback functor for presheaves of modules. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + .../Category/ModuleCat/Presheaf/Limits.lean | 2 + .../Category/ModuleCat/Presheaf/Pullback.lean | 95 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 Mathlib/Algebra/Category/ModuleCat/Presheaf/Pullback.lean diff --git a/Mathlib.lean b/Mathlib.lean index da99906eaf208..1e6e4332b430f 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -126,6 +126,7 @@ import Mathlib.Algebra.Category.ModuleCat.Presheaf.Free import Mathlib.Algebra.Category.ModuleCat.Presheaf.Generator import Mathlib.Algebra.Category.ModuleCat.Presheaf.Limits import Mathlib.Algebra.Category.ModuleCat.Presheaf.Monoidal +import Mathlib.Algebra.Category.ModuleCat.Presheaf.Pullback import Mathlib.Algebra.Category.ModuleCat.Presheaf.Pushforward import Mathlib.Algebra.Category.ModuleCat.Presheaf.Sheafification import Mathlib.Algebra.Category.ModuleCat.Presheaf.Sheafify diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean index e6ecca097ac2a..7d07e353fa2b9 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean @@ -139,6 +139,8 @@ variable [Small.{v} J] instance hasLimitsOfShape : HasLimitsOfShape J (PresheafOfModules.{v} R) where +instance hasLimitsOfSize : HasLimitsOfSize.{v, v} (PresheafOfModules.{v} R) where + noncomputable instance evaluation_preservesLimitsOfShape (X : Cᵒᵖ) : PreservesLimitsOfShape J (evaluation R X : PresheafOfModules.{v} R ⥤ _) where diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pullback.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pullback.lean new file mode 100644 index 0000000000000..6ce91e2eb04ed --- /dev/null +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pullback.lean @@ -0,0 +1,95 @@ +/- +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.Category.ModuleCat.Presheaf.Generator +import Mathlib.Algebra.Category.ModuleCat.Presheaf.Pushforward +import Mathlib.CategoryTheory.Adjunction.PartialAdjoint + +/-! +# Pullback of presheaves of modules + +Let `F : C ⥤ D` be a functor, `R : Dᵒᵖ ⥤ RingCat` and `S : Cᵒᵖ ⥤ RingCat` be presheaves +of rings, and `φ : S ⟶ F.op ⋙ R` be a morphism of presheaves of rings, +we introduce the pullback functor `pullback : PresheafOfModules S ⥤ PresheafOfModules R` +as the left adjoint of `pushforward : PresheafOfModules R ⥤ PresheafOfModules S`. +The existence of this left adjoint functor is obtained under suitable universe assumptions. + +-/ + +universe v v₁ v₂ u₁ u₂ u + +open CategoryTheory Limits Opposite + +namespace PresheafOfModules + +section + +variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] + {F : C ⥤ D} {R : Dᵒᵖ ⥤ RingCat.{u}} {S : Cᵒᵖ ⥤ RingCat.{u}} (φ : S ⟶ F.op ⋙ R) + [(pushforward.{v} φ).IsRightAdjoint] + +/-- The pullback functor `PresheafOfModules S ⥤ PresheafOfModules R` induced by +a morphism of presheaves of rings `S ⟶ F.op ⋙ R`, defined as the left adjoint +functor to the pushforward, when it exists. -/ +noncomputable def pullback : PresheafOfModules.{v} S ⥤ PresheafOfModules.{v} R := + (pushforward.{v} φ).leftAdjoint + +/-- Given a morphism of presheaves of rings `S ⟶ F.op ⋙ R`, this is the adjunction +between associated pullback and pushforward functors on the categories +of presheaves of modules. -/ +noncomputable def pullbackPushforwardAdjunction : pullback.{v} φ ⊣ pushforward.{v} φ := + Adjunction.ofIsRightAdjoint (pushforward φ) + +/-- Given a morphism of presheaves of rings `φ : S ⟶ F.op ⋙ R`, this is the property +that the (partial) left adjoint functor of `pushforward φ` is defined +on a certain object `M : PresheafOfModules S`. -/ +abbrev PullbackObjIsDefined : PresheafOfModules.{v} S → Prop := + (pushforward φ).LeftAdjointObjIsDefined + +end + +section + +variable {C D : Type u} [SmallCategory C] [SmallCategory D] + {F : C ⥤ D} {R : Dᵒᵖ ⥤ RingCat.{u}} {S : Cᵒᵖ ⥤ RingCat.{u}} (φ : S ⟶ F.op ⋙ R) + +/-- Given a morphism of presheaves of rings `φ : S ⟶ F.op ⋙ R`, where `F : C ⥤ D`, +`S : Cᵒᵖ ⥤ RingCat`, `R : Dᵒᵖ ⥤ RingCat` and `X : C`, the (partial) left adjoint +functor of `pushforward φ` is defined on the object `(free S).obj (yoneda.obj X)`: +this object shall be mapped to `(free R).obj (yoneda.obj (F.obj X))`. -/ +noncomputable def pushforwardCompCoyonedaFreeYonedaCorepresentableBy (X : C) : + (pushforward φ ⋙ coyoneda.obj (op ((free S).obj (yoneda.obj X)))).CorepresentableBy + ((free R).obj (yoneda.obj (F.obj X))) where + homEquiv {M} := (freeYonedaEquiv).trans + (freeYonedaEquiv (M := (pushforward φ).obj M)).symm + homEquiv_comp {M N} g f := freeYonedaEquiv.injective (by + dsimp + erw [Equiv.apply_symm_apply, freeYonedaEquiv_comp] + conv_rhs => erw [freeYonedaEquiv_comp] + erw [Equiv.apply_symm_apply] + rfl) + +lemma pullbackObjIsDefined_free_yoneda (X : C) : + PullbackObjIsDefined φ ((free S).obj (yoneda.obj X)) := + (pushforwardCompCoyonedaFreeYonedaCorepresentableBy φ X).isCorepresentable + +lemma pullbackObjIsDefined_eq_top : + PullbackObjIsDefined.{u} φ = ⊤ := by + ext M + simp only [Pi.top_apply, Prop.top_eq_true, iff_true] + apply Functor.leftAdjointObjIsDefined_of_isColimit + M.isColimitFreeYonedaCoproductsCokernelCofork + rintro (_ | _) + all_goals + apply Functor.leftAdjointObjIsDefined_colimit _ + (fun _ ↦ pullbackObjIsDefined_free_yoneda _ _) + +instance : (pushforward.{u} φ).IsRightAdjoint := + Functor.isRightAdjoint_of_leftAdjointObjIsDefined_eq_top + (pullbackObjIsDefined_eq_top φ) + +end + +end PresheafOfModules From 347912d7951da47784fcb92719b8a7501d97de6b Mon Sep 17 00:00:00 2001 From: Robin Carlier <57142648+robin-carlier@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:52:02 +0000 Subject: [PATCH 162/681] chore(CategoryTheory/Limits/Cones): functoriality of `mapCone` (#20641) Record a basic compatibility of `mapCone` with functor compositon, which seemed to be missing. Also record the corresponding statement for cocones. --- Mathlib/CategoryTheory/Limits/Cones.lean | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Limits/Cones.lean b/Mathlib/CategoryTheory/Limits/Cones.lean index 05e9c7a87a567..cb2edcc07c396 100644 --- a/Mathlib/CategoryTheory/Limits/Cones.lean +++ b/Mathlib/CategoryTheory/Limits/Cones.lean @@ -35,7 +35,7 @@ For more results about the category of cones, see `cone_category.lean`. -- morphism levels before object levels. See note [CategoryTheory universes]. -universe v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄ +universe v₁ v₂ v₃ v₄ v₅ u₁ u₂ u₃ u₄ u₅ open CategoryTheory @@ -43,6 +43,7 @@ variable {J : Type u₁} [Category.{v₁} J] variable {K : Type u₂} [Category.{v₂} K] variable {C : Type u₃} [Category.{v₃} C] variable {D : Type u₄} [Category.{v₄} D] +variable {E : Type u₅} [Category.{v₅} E] open CategoryTheory @@ -413,6 +414,11 @@ def functoriality : Cone F ⥤ Cone (F ⋙ G) where { hom := G.map f.hom w := fun j => by simp [-ConeMorphism.w, ← f.w j] } +/-- Functoriality is functorial. -/ +def functorialityCompFunctoriality (H : D ⥤ E) : + functoriality F G ⋙ functoriality (F ⋙ G) H ≅ functoriality F (G ⋙ H) := + NatIso.ofComponents (fun _ ↦ Iso.refl _) (by simp [functoriality]) + instance functoriality_full [G.Full] [G.Faithful] : (functoriality F G).Full where map_surjective t := ⟨{ hom := G.preimage t.hom @@ -611,6 +617,11 @@ def functoriality : Cocone F ⥤ Cocone (F ⋙ G) where { hom := G.map f.hom w := by intros; rw [← Functor.map_comp, CoconeMorphism.w] } +/-- Functoriality is functorial. -/ +def functorialityCompFunctoriality (H : D ⥤ E) : + functoriality F G ⋙ functoriality (F ⋙ G) H ≅ functoriality F (G ⋙ H) := + NatIso.ofComponents (fun _ ↦ Iso.refl _) (by simp [functoriality]) + instance functoriality_full [G.Full] [G.Faithful] : (functoriality F G).Full where map_surjective t := ⟨{ hom := G.preimage t.hom @@ -661,11 +672,21 @@ open CategoryTheory.Limits def mapCone (c : Cone F) : Cone (F ⋙ H) := (Cones.functoriality F H).obj c +/-- The construction `mapCone` respects functor composition. -/ +@[simps!] +noncomputable def mapConeMapCone {F : J ⥤ C} {H : C ⥤ D} {H' : D ⥤ E} (c : Cone F) : + H'.mapCone (H.mapCone c) ≅ (H ⋙ H').mapCone c := Cones.ext (Iso.refl _) + /-- The image of a cocone in C under a functor G : C ⥤ D is a cocone in D. -/ @[simps!] def mapCocone (c : Cocone F) : Cocone (F ⋙ H) := (Cocones.functoriality F H).obj c +/-- The construction `mapCocone` respects functor composition. -/ +@[simps!] +noncomputable def mapCoconeMapCocone {F : J ⥤ C} {H : C ⥤ D} {H' : D ⥤ E} (c : Cocone F) : + H'.mapCocone (H.mapCocone c) ≅ (H ⋙ H').mapCocone c := Cocones.ext (Iso.refl _) + /-- Given a cone morphism `c ⟶ c'`, construct a cone morphism on the mapped cones functorially. -/ def mapConeMorphism {c c' : Cone F} (f : c ⟶ c') : H.mapCone c ⟶ H.mapCone c' := (Cones.functoriality F H).map f From e01427c608acbdd4a049c6a62610ff080fabf570 Mon Sep 17 00:00:00 2001 From: ooovi Date: Sat, 11 Jan 2025 18:54:28 +0000 Subject: [PATCH 163/681] feat(Combinatorics/SimpleGraph): add independent sets (#18608) dualize the clique API to obtain independent sets, prove theorems about the dual relationship to cliques, dualize and add some theorems. Co-authored-by: FordUniver <61389961+FordUniver@users.noreply.github.com> Co-authored-by: Christoph Spiegel --- Mathlib/Combinatorics/SimpleGraph/Clique.lean | 217 +++++++++++++++++- 1 file changed, 213 insertions(+), 4 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Clique.lean b/Mathlib/Combinatorics/SimpleGraph/Clique.lean index ea2c7d7ec4dbc..7738b767a8d3a 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Clique.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Clique.lean @@ -21,10 +21,6 @@ A clique is a set of vertices that are pairwise adjacent. * `SimpleGraph.IsNClique`: Predicate for a set of vertices to be an `n`-clique. * `SimpleGraph.cliqueFinset`: Finset of `n`-cliques of a graph. * `SimpleGraph.CliqueFree`: Predicate for a graph to have no `n`-cliques. - -## TODO - -* Dualise all the API to get independent sets -/ open Finset Fintype Function SimpleGraph.Walk @@ -656,4 +652,217 @@ theorem cliqueFinset_map_of_equiv (e : α ≃ β) (n : ℕ) : end CliqueFinset +/-! ### Independent Sets -/ + +section IndepSet + +variable {s : Set α} + +/-- An independent set in a graph is a set of vertices that are pairwise not adjacent. -/ +abbrev IsIndepSet (s : Set α) : Prop := + s.Pairwise (fun v w ↦ ¬G.Adj v w) + +theorem isIndepSet_iff : G.IsIndepSet s ↔ s.Pairwise (fun v w ↦ ¬G.Adj v w) := + Iff.rfl + +/-- An independent set is a clique in the complement graph and vice versa. -/ +@[simp] theorem isClique_compl : Gᶜ.IsClique s ↔ G.IsIndepSet s := by + rw [isIndepSet_iff, isClique_iff]; repeat rw [Set.Pairwise] + simp_all [compl_adj] + +/-- An independent set in the complement graph is a clique and vice versa. -/ +@[simp] theorem isIndepSet_compl : Gᶜ.IsIndepSet s ↔ G.IsClique s := by + rw [isIndepSet_iff, isClique_iff]; repeat rw [Set.Pairwise] + simp_all [compl_adj] + +instance [DecidableEq α] [DecidableRel G.Adj] {s : Finset α} : Decidable (G.IsIndepSet s) := + decidable_of_iff' _ G.isIndepSet_iff + +/-- If `s` is an independent set, its complement meets every edge of `G`. -/ +lemma IsIndepSet.nonempty_mem_compl_mem_edge + [Fintype α] [DecidableEq α] {s : Finset α} (indA : G.IsIndepSet s) {e} (he : e ∈ G.edgeSet) : + { b ∈ sᶜ | b ∈ e }.Nonempty := by + obtain ⟨v , w⟩ := e + by_contra c + rw [IsIndepSet] at indA + rw [mem_edgeSet] at he + rw [not_nonempty_iff_eq_empty, filter_eq_empty_iff] at c + simp_rw [mem_compl, Sym2.mem_iff, not_or] at c + by_cases vins : v ∈ s + · have wins : w ∈ s := by by_contra wnins; exact (c wnins).right rfl + exact (indA vins wins (Adj.ne he)) he + · exact (c vins).left rfl + +/-- The neighbors of a vertex `v` form an independent set in a triangle free graph `G`. -/ +theorem isIndepSet_neighborSet_of_triangleFree [DecidableEq α] (h: G.CliqueFree 3) (v : α) : + G.IsIndepSet (G.neighborSet v) := by + by_contra nind + rw [IsIndepSet, Set.Pairwise] at nind + push_neg at nind + simp_rw [mem_neighborSet] at nind + obtain ⟨j, avj, k, avk, _, ajk⟩ := nind + exact h {v, j, k} (is3Clique_triple_iff.mpr (by simp [avj, avk, ajk])) + +end IndepSet + +/-! ### N-Independent sets -/ + + +section NIndepSet + +variable {n : ℕ} {s : Finset α} + +/-- An `n`-independent set in a graph is a set of `n` vertices which are pairwise nonadjacent. -/ +@[mk_iff] +structure IsNIndepSet (n : ℕ) (s : Finset α) : Prop where + isIndepSet : G.IsIndepSet s + card_eq : s.card = n + +/-- An `n`-independent set is an `n`-clique in the complement graph and vice versa. -/ +@[simp] theorem isNClique_compl : Gᶜ.IsNClique n s ↔ G.IsNIndepSet n s := by + rw [isNIndepSet_iff] + simp [isNClique_iff] + +/-- An `n`-independent set in the complement graph is an `n`-clique and vice versa. -/ +@[simp] theorem isNIndepSet_compl : Gᶜ.IsNIndepSet n s ↔ G.IsNClique n s := by + rw [isNClique_iff] + simp [isNIndepSet_iff] + +instance [DecidableEq α] [DecidableRel G.Adj] {n : ℕ} {s : Finset α} : + Decidable (G.IsNIndepSet n s) := + decidable_of_iff' _ (G.isNIndepSet_iff n s) + +end NIndepSet + +/-! ### Graphs without independent sets -/ + + +section IndepSetFree + +variable {n : ℕ} + +/-- `G.IndepSetFree n` means that `G` has no `n`-independent sets. -/ +def IndepSetFree (n : ℕ) : Prop := + ∀ t, ¬G.IsNIndepSet n t + +/-- An graph is `n`-independent set free iff its complement is `n`-clique free. -/ +@[simp] theorem cliqueFree_compl : Gᶜ.CliqueFree n ↔ G.IndepSetFree n := by + simp [IndepSetFree, CliqueFree] + +/-- An graph's complement is `n`-independent set free iff it is `n`-clique free. -/ +@[simp] theorem indepSetFree_compl : Gᶜ.IndepSetFree n ↔ G.CliqueFree n := by + simp [IndepSetFree, CliqueFree] + +/-- `G.IndepSetFreeOn s n` means that `G` has no `n`-independent sets contained in `s`. -/ +def IndepSetFreeOn (G : SimpleGraph α) (s : Set α) (n : ℕ) : Prop := + ∀ ⦃t⦄, ↑t ⊆ s → ¬G.IsNIndepSet n t + +end IndepSetFree + +/-! ### Set of independent sets-/ + + +section IndepSetSet + +variable {n : ℕ} {s : Finset α} + +/-- The `n`-independent sets in a graph as a set. -/ +def indepSetSet (n : ℕ) : Set (Finset α) := + { s | G.IsNIndepSet n s } + +variable {G} + +@[simp] +theorem mem_indepSetSet_iff : s ∈ G.indepSetSet n ↔ G.IsNIndepSet n s := + Iff.rfl + +end IndepSetSet + +/-! ### Independence Number-/ + + +section IndepNumber + +variable {α : Type*} {G : SimpleGraph α} + +/-- The maximal number of vertices of an independent set in a graph `G`. -/ +noncomputable def indepNum (G : SimpleGraph α) : ℕ := sSup {n | ∃ s, G.IsNIndepSet n s} + +@[simp] lemma cliqueNum_compl : Gᶜ.cliqueNum = G.indepNum := by + simp [indepNum, cliqueNum] + +@[simp] lemma indepNum_compl : Gᶜ.indepNum = G.cliqueNum := by + simp [indepNum, cliqueNum] + +theorem IsIndepSet.card_le_indepNum + [Fintype α] {t : Finset α} (tc : G.IsIndepSet t) : #t ≤ G.indepNum := by + rw[← isClique_compl] at tc + simp_rw [indepNum, ← isNClique_compl] + exact tc.card_le_cliqueNum + +lemma exists_isNIndepSet_indepNum [Fintype α] : ∃ s, G.IsNIndepSet G.indepNum s := by + simp_rw [indepNum, ← isNClique_compl] + exact exists_isNClique_cliqueNum + +/-- An independent set in a graph `G` such that there is no independent set with more vertices. -/ +@[mk_iff] +structure IsMaximumIndepSet [Fintype α] (G : SimpleGraph α) (s : Finset α) : Prop where + isIndepSet : G.IsIndepSet s + maximum : ∀ t : Finset α, G.IsIndepSet t → #t ≤ #s + +@[simp] lemma isMaximumClique_compl [Fintype α] (s : Finset α) : + Gᶜ.IsMaximumClique s ↔ G.IsMaximumIndepSet s := by + simp [isMaximumIndepSet_iff, isMaximumClique_iff] + +@[simp] lemma isMaximumIndepSet_compl [Fintype α] (s : Finset α) : + Gᶜ.IsMaximumIndepSet s ↔ G.IsMaximumClique s := by + simp [isMaximumIndepSet_iff, isMaximumClique_iff] + +/-- An independent set in a graph `G` that cannot be extended by adding more vertices. -/ +theorem isMaximalIndepSet_iff {s : Set α} : + Maximal G.IsIndepSet s ↔ G.IsIndepSet s ∧ ∀ t : Set α, G.IsIndepSet t → s ⊆ t → t ⊆ s := + Iff.rfl + +@[simp] lemma isMaximalClique_compl (s : Finset α) : + Maximal Gᶜ.IsClique s ↔ Maximal G.IsIndepSet s := by + simp [isMaximalIndepSet_iff, isMaximalClique_iff] + +@[simp] lemma isMaximalIndepSet_compl (s : Finset α) : + Maximal Gᶜ.IsIndepSet s ↔ Maximal G.IsClique s := by + simp [isMaximalIndepSet_iff, isMaximalClique_iff] + +lemma IsMaximumIndepSet.isMaximalIndepSet + [Fintype α] (s : Finset α) (M : G.IsMaximumIndepSet s) : Maximal G.IsIndepSet s := by + rw [← isMaximalClique_compl] + rw [← isMaximumClique_compl] at M + exact IsMaximumClique.isMaximalClique s M + +theorem maximumIndepSet_card_eq_indepNum + [Fintype α] (t : Finset α) (tmc : G.IsMaximumIndepSet t) : #t = G.indepNum := by + rw [← isMaximumClique_compl] at tmc + simp_rw [indepNum, ← isNClique_compl] + exact Gᶜ.maximumClique_card_eq_cliqueNum t tmc + +lemma maximumIndepSet_exists [Fintype α] : ∃ (s : Finset α), G.IsMaximumIndepSet s := by + simp [← isMaximumClique_compl, maximumClique_exists] + +end IndepNumber + +/-! ### Finset of independent sets -/ + + +section IndepSetFinset + +variable [Fintype α] [DecidableEq α] [DecidableRel G.Adj] {n : ℕ} {s : Finset α} + +/-- The `n`-independent sets in a graph as a finset. -/ +def indepSetFinset (n : ℕ) : Finset (Finset α) := {s | G.IsNIndepSet n s} + +variable {G} in +@[simp] +theorem mem_indepSetFinset_iff : s ∈ G.indepSetFinset n ↔ G.IsNIndepSet n s := + mem_filter.trans <| and_iff_right <| mem_univ _ + +end IndepSetFinset + end SimpleGraph From 24529d5e099fcb09dbb372700217b6e4c56f5bcc Mon Sep 17 00:00:00 2001 From: Matthew Robert Ballard Date: Sat, 11 Jan 2025 20:07:23 +0000 Subject: [PATCH 164/681] chore: de-simp `map_eq_zero_iff_eq_one` (#20662) The keys of this declaration are `@Eq _ (@DFunLike.coe _ _ _ _ _ _) 0` so it will fire whenever attempting to simplify `f x = 0` which is too generic for this specific setting. --- Mathlib/Algebra/Order/Hom/Basic.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Order/Hom/Basic.lean b/Mathlib/Algebra/Order/Hom/Basic.lean index a90bc7fe9e004..830396fcb7b3a 100644 --- a/Mathlib/Algebra/Order/Hom/Basic.lean +++ b/Mathlib/Algebra/Order/Hom/Basic.lean @@ -260,7 +260,7 @@ section GroupNormClass variable [Group α] [OrderedAddCommMonoid β] [GroupNormClass F α β] (f : F) {x : α} -@[to_additive (attr := simp)] +@[to_additive] theorem map_eq_zero_iff_eq_one : f x = 0 ↔ x = 1 := ⟨eq_one_of_map_eq_zero _, by rintro rfl From 0035201c0ba31f3d9c53d52281b6af9b841d6108 Mon Sep 17 00:00:00 2001 From: leanprover-community-bot-assistant Date: Sun, 12 Jan 2025 00:16:43 +0000 Subject: [PATCH 165/681] chore(scripts): update nolints.json (#20672) I am happy to remove some nolints for you! --- scripts/nolints.json | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/nolints.json b/scripts/nolints.json index 9c3201d0d844a..4720d32086c9d 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -259,7 +259,6 @@ ["docBlame", "ProbabilityTheory.«termEVar[_]»"], ["docBlame", "ProbabilityTheory.«termVar[_]»"], ["docBlame", "ProbabilityTheory.«term_=ₐₛ_»"], - ["docBlame", "ProbabilityTheory.«term_×ₖ_»"], ["docBlame", "ProbabilityTheory.«term_≤ₐₛ_»"], ["docBlame", "ProbabilityTheory.«term_⟦_|_⟧»"], ["docBlame", "ProbabilityTheory.termℙ"], From e81777e24e09968a273fe9120837f0a500381119 Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Sun, 12 Jan 2025 07:52:33 +0000 Subject: [PATCH 166/681] chore: update Mathlib dependencies 2025-01-12 (#20675) 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 d5ee15bf474c6..efe399c199805 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "66225aab4f6bd1687053b03916105f7cab140507", + "rev": "8690c0b6e759ab1a0c7e4287909ae5f897d3ab66", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 62f729a9c6c3a553e81c3384877e573fa40f21d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 12 Jan 2025 09:32:03 +0000 Subject: [PATCH 167/681] feat: `(C a * p).leadingCoeff = a * p.leadingCoeff` (#20575) From GrowthInGroups (LeanCamCombi) --- .../Algebra/Polynomial/Degree/Operations.lean | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Mathlib/Algebra/Polynomial/Degree/Operations.lean b/Mathlib/Algebra/Polynomial/Degree/Operations.lean index 21d80bcb9d741..eab53a116f2eb 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Operations.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Operations.lean @@ -375,6 +375,36 @@ theorem leadingCoeff_mul_monic {p q : R[X]} (hq : Monic q) : rw [leadingCoeff_mul', hq.leadingCoeff, mul_one] rwa [hq.leadingCoeff, mul_one] +lemma degree_C_mul_of_isUnit (ha : IsUnit a) (p : R[X]) : (C a * p).degree = p.degree := by + obtain rfl | hp := eq_or_ne p 0 + · simp + nontriviality R + rw [degree_mul', degree_C ha.ne_zero] + · simp + · simpa [ha.mul_right_eq_zero] + +lemma degree_mul_C_of_isUnit (ha : IsUnit a) (p : R[X]) : (p * C a).degree = p.degree := by + obtain rfl | hp := eq_or_ne p 0 + · simp + nontriviality R + rw [degree_mul', degree_C ha.ne_zero] + · simp + · simpa [ha.mul_left_eq_zero] + +lemma natDegree_C_mul_of_isUnit (ha : IsUnit a) (p : R[X]) : (C a * p).natDegree = p.natDegree := by + simp [natDegree, degree_C_mul_of_isUnit ha] + +lemma natDegree_mul_C_of_isUnit (ha : IsUnit a) (p : R[X]) : (p * C a).natDegree = p.natDegree := by + simp [natDegree, degree_mul_C_of_isUnit ha] + +lemma leadingCoeff_C_mul_of_isUnit (ha : IsUnit a) (p : R[X]) : + (C a * p).leadingCoeff = a * p.leadingCoeff := by + rwa [leadingCoeff, coeff_C_mul, natDegree_C_mul_of_isUnit, leadingCoeff] + +lemma leadingCoeff_mul_C_of_isUnit (ha : IsUnit a) (p : R[X]) : + (p * C a).leadingCoeff = p.leadingCoeff * a := by + rwa [leadingCoeff, coeff_mul_C, natDegree_mul_C_of_isUnit, leadingCoeff] + @[simp] theorem leadingCoeff_mul_X_pow {p : R[X]} {n : ℕ} : leadingCoeff (p * X ^ n) = leadingCoeff p := leadingCoeff_mul_monic (monic_X_pow n) From 0634717cdd24285ab4685a52cbf27141f2be1455 Mon Sep 17 00:00:00 2001 From: damiano Date: Sun, 12 Jan 2025 10:49:23 +0000 Subject: [PATCH 168/681] feat: allow several identifiers in assert_not_exists (#15994) Align the `assert_not_exists` syntax to `assert_not_imported`: they now both allow several identifiers. Co-authored-by: Jon Eugster --- Mathlib/Algebra/Algebra/Defs.lean | 4 +- Mathlib/Algebra/Associated/Basic.lean | 3 +- .../Algebra/BigOperators/Group/Finset.lean | 4 +- Mathlib/Algebra/CharP/Basic.lean | 3 +- Mathlib/Algebra/CharP/Defs.lean | 3 +- Mathlib/Algebra/CharP/Lemmas.lean | 4 +- Mathlib/Algebra/CharP/Two.lean | 3 +- Mathlib/Algebra/Group/Action/Opposite.lean | 3 +- Mathlib/Algebra/Group/Basic.lean | 3 +- Mathlib/Algebra/Group/Center.lean | 4 +- Mathlib/Algebra/Group/Commutator.lean | 3 +- Mathlib/Algebra/Group/Commute/Basic.lean | 3 +- Mathlib/Algebra/Group/Commute/Defs.lean | 3 +- Mathlib/Algebra/Group/Commute/Hom.lean | 3 +- Mathlib/Algebra/Group/Commute/Units.lean | 3 +- Mathlib/Algebra/Group/Conj.lean | 3 +- Mathlib/Algebra/Group/Defs.lean | 4 +- Mathlib/Algebra/Group/Embedding.lean | 3 +- Mathlib/Algebra/Group/Even.lean | 3 +- Mathlib/Algebra/Group/Ext.lean | 3 +- Mathlib/Algebra/Group/Fin/Basic.lean | 3 +- Mathlib/Algebra/Group/Hom/Instances.lean | 3 +- Mathlib/Algebra/Group/InjSurj.lean | 3 +- Mathlib/Algebra/Group/Int/Defs.lean | 3 +- Mathlib/Algebra/Group/Invertible/Basic.lean | 3 +- Mathlib/Algebra/Group/Invertible/Defs.lean | 3 +- Mathlib/Algebra/Group/MinimalAxioms.lean | 3 +- Mathlib/Algebra/Group/Nat/Defs.lean | 3 +- Mathlib/Algebra/Group/Nat/Even.lean | 3 +- Mathlib/Algebra/Group/Nat/TypeTags.lean | 3 +- Mathlib/Algebra/Group/Nat/Units.lean | 3 +- Mathlib/Algebra/Group/Operations.lean | 3 +- Mathlib/Algebra/Group/Opposite.lean | 4 +- Mathlib/Algebra/Group/Pi/Basic.lean | 5 +- Mathlib/Algebra/Group/Pi/Lemmas.lean | 3 +- .../Algebra/Group/Pointwise/Set/Basic.lean | 3 +- Mathlib/Algebra/Group/Prod.lean | 3 +- Mathlib/Algebra/Group/Semiconj/Basic.lean | 3 +- Mathlib/Algebra/Group/Semiconj/Defs.lean | 3 +- Mathlib/Algebra/Group/Semiconj/Units.lean | 3 +- Mathlib/Algebra/Group/Subgroup/Basic.lean | 4 +- Mathlib/Algebra/Group/Subgroup/Defs.lean | 4 +- Mathlib/Algebra/Group/Subgroup/Ker.lean | 4 +- Mathlib/Algebra/Group/Subgroup/Lattice.lean | 4 +- Mathlib/Algebra/Group/Subgroup/Map.lean | 4 +- Mathlib/Algebra/Group/Submonoid/Defs.lean | 3 +- Mathlib/Algebra/Group/Subsemigroup/Defs.lean | 3 +- Mathlib/Algebra/Group/TypeTags/Basic.lean | 5 +- Mathlib/Algebra/Group/TypeTags/Finite.lean | 3 +- Mathlib/Algebra/Group/ULift.lean | 3 +- Mathlib/Algebra/Group/UniqueProds/Basic.lean | 6 +-- Mathlib/Algebra/Group/Units/Basic.lean | 4 +- Mathlib/Algebra/Group/Units/Defs.lean | 4 +- Mathlib/Algebra/Group/Units/Equiv.lean | 3 +- Mathlib/Algebra/Group/Units/Hom.lean | 3 +- Mathlib/Algebra/Group/Units/Opposite.lean | 3 +- Mathlib/Algebra/Group/WithOne/Basic.lean | 3 +- Mathlib/Algebra/Group/WithOne/Defs.lean | 7 +-- Mathlib/Algebra/GroupPower/IterateHom.lean | 3 +- .../Algebra/GroupWithZero/Action/Defs.lean | 4 +- Mathlib/Algebra/GroupWithZero/Action/End.lean | 4 +- .../GroupWithZero/Action/Faithful.lean | 4 +- Mathlib/Algebra/GroupWithZero/Center.lean | 4 +- .../GroupWithZero/Pointwise/Set/Basic.lean | 3 +- .../Algebra/GroupWithZero/Units/Basic.lean | 5 +- .../Homology/TotalComplexSymmetry.lean | 3 +- Mathlib/Algebra/Module/Basic.lean | 3 +- Mathlib/Algebra/Module/Defs.lean | 8 +-- Mathlib/Algebra/Module/End.lean | 5 +- Mathlib/Algebra/Module/Equiv/Defs.lean | 3 +- Mathlib/Algebra/Module/LinearMap/Basic.lean | 4 +- Mathlib/Algebra/Module/LinearMap/Defs.lean | 6 +-- Mathlib/Algebra/Module/NatInt.lean | 6 +-- Mathlib/Algebra/Module/RingHom.lean | 6 +-- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 3 +- Mathlib/Algebra/NoZeroSMulDivisors/Basic.lean | 5 +- Mathlib/Algebra/NoZeroSMulDivisors/Defs.lean | 6 +-- Mathlib/Algebra/Order/CauSeq/Basic.lean | 6 +-- Mathlib/Algebra/Order/Group/Int.lean | 4 +- .../Algebra/Order/Group/Unbundled/Int.lean | 3 +- Mathlib/Algebra/Order/Hom/Ring.lean | 3 +- Mathlib/Algebra/Order/Ring/Rat.lean | 5 +- .../Algebra/Order/Ring/Unbundled/Basic.lean | 3 +- Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean | 6 +-- Mathlib/Algebra/Prime/Defs.lean | 3 +- Mathlib/Algebra/Prime/Lemmas.lean | 3 +- Mathlib/Algebra/Ring/Action/Basic.lean | 3 +- Mathlib/Algebra/Ring/Center.lean | 3 +- Mathlib/Algebra/Ring/Defs.lean | 3 +- Mathlib/Algebra/Ring/Equiv.lean | 3 +- Mathlib/Algebra/Ring/Hom/Defs.lean | 5 +- Mathlib/Algebra/Ring/Int/Defs.lean | 3 +- Mathlib/Algebra/Ring/Int/Parity.lean | 3 +- Mathlib/Algebra/Ring/Int/Units.lean | 3 +- Mathlib/Algebra/Ring/Parity.lean | 3 +- Mathlib/Algebra/Ring/Rat.lean | 6 +-- Mathlib/Algebra/Star/Basic.lean | 4 +- Mathlib/Analysis/Complex/RealDeriv.lean | 3 +- Mathlib/Analysis/Convex/Cone/Basic.lean | 4 +- Mathlib/Analysis/Normed/Field/Basic.lean | 12 ++--- .../SpecialFunctions/Complex/LogDeriv.lean | 3 +- .../Analysis/SpecialFunctions/ExpDeriv.lean | 3 +- .../ConcreteCategory/Basic.lean | 3 +- .../FilteredColimitCommutesFiniteLimit.lean | 3 +- .../Additive/AP/Three/Behrend.lean | 3 +- .../Combinatorics/Additive/AP/Three/Defs.lean | 3 +- .../Combinatorics/Additive/Corner/Defs.lean | 3 +- .../Combinatorics/Additive/FreimanHom.lean | 3 +- Mathlib/Data/Complex/Basic.lean | 3 +- Mathlib/Data/DFinsupp/Defs.lean | 3 +- Mathlib/Data/Fin/Basic.lean | 5 +- Mathlib/Data/Finite/Defs.lean | 4 +- Mathlib/Data/Finite/Prod.lean | 3 +- Mathlib/Data/Finset/Attach.lean | 7 +-- Mathlib/Data/Finset/Basic.lean | 7 +-- Mathlib/Data/Finset/Card.lean | 3 +- Mathlib/Data/Finset/Dedup.lean | 7 +-- Mathlib/Data/Finset/Defs.lean | 9 +--- Mathlib/Data/Finset/Disjoint.lean | 7 +-- Mathlib/Data/Finset/Empty.lean | 7 +-- Mathlib/Data/Finset/Erase.lean | 7 +-- Mathlib/Data/Finset/Filter.lean | 7 +-- Mathlib/Data/Finset/Fold.lean | 3 +- Mathlib/Data/Finset/Image.lean | 4 +- Mathlib/Data/Finset/Insert.lean | 7 +-- Mathlib/Data/Finset/Lattice/Basic.lean | 7 +-- Mathlib/Data/Finset/Lattice/Fold.lean | 3 +- Mathlib/Data/Finset/Lattice/Lemmas.lean | 7 +-- Mathlib/Data/Finset/Max.lean | 3 +- Mathlib/Data/Finset/Range.lean | 7 +-- Mathlib/Data/Finset/SDiff.lean | 7 +-- Mathlib/Data/Finset/SymmDiff.lean | 6 +-- Mathlib/Data/Finset/Union.lean | 3 +- Mathlib/Data/Fintype/Basic.lean | 3 +- Mathlib/Data/Fintype/Card.lean | 3 +- Mathlib/Data/Fintype/Option.lean | 3 +- Mathlib/Data/Fintype/Pi.lean | 3 +- Mathlib/Data/Int/Cast/Pi.lean | 3 +- Mathlib/Data/List/Basic.lean | 5 +- Mathlib/Data/List/Count.lean | 3 +- Mathlib/Data/Matrix/Defs.lean | 3 +- Mathlib/Data/Matrix/Diagonal.lean | 3 +- Mathlib/Data/Matrix/Mul.lean | 3 +- Mathlib/Data/Multiset/Antidiagonal.lean | 3 +- Mathlib/Data/Multiset/Bind.lean | 3 +- Mathlib/Data/Nat/Cast/Basic.lean | 7 +-- Mathlib/Data/Nat/ModEq.lean | 3 +- Mathlib/Data/Nat/Totient.lean | 3 +- Mathlib/Data/Rat/Cardinal.lean | 3 +- Mathlib/Data/Rat/Defs.lean | 5 +- Mathlib/Data/Rat/Denumerable.lean | 3 +- Mathlib/Data/Real/Basic.lean | 5 +- Mathlib/Data/Set/Finite/Basic.lean | 3 +- Mathlib/Data/Set/Finite/Lattice.lean | 3 +- Mathlib/Data/Set/Finite/Lemmas.lean | 3 +- Mathlib/Data/Set/Finite/List.lean | 3 +- Mathlib/Data/Set/Finite/Monad.lean | 3 +- Mathlib/Data/Set/Finite/Powerset.lean | 3 +- Mathlib/Data/Set/Finite/Range.lean | 3 +- Mathlib/Data/ZMod/Basic.lean | 3 +- Mathlib/Data/ZMod/IntUnitsPower.lean | 3 +- .../Euclidean/Angle/Unoriented/Basic.lean | 4 +- Mathlib/GroupTheory/Commutator/Basic.lean | 3 +- Mathlib/GroupTheory/CommutingProbability.lean | 3 +- .../GroupTheory/MonoidLocalization/Basic.lean | 3 +- .../GroupTheory/OreLocalization/Basic.lean | 3 +- Mathlib/GroupTheory/Subgroup/Center.lean | 3 +- Mathlib/LinearAlgebra/Basis/Defs.lean | 4 +- Mathlib/LinearAlgebra/FiniteDimensional.lean | 3 +- .../Function/SpecialFunctions/Basic.lean | 4 +- Mathlib/Order/CompleteLattice/Finset.lean | 3 +- Mathlib/Order/Filter/Basic.lean | 3 +- Mathlib/Order/Interval/Finset/Basic.lean | 3 +- Mathlib/RingTheory/Algebraic/Defs.lean | 5 +- Mathlib/RingTheory/Algebraic/Pi.lean | 5 +- Mathlib/RingTheory/Artinian/Module.lean | 3 +- Mathlib/RingTheory/Finiteness/Basic.lean | 5 +- Mathlib/RingTheory/Finiteness/Defs.lean | 5 +- Mathlib/RingTheory/Ideal/Maps.lean | 2 +- Mathlib/RingTheory/Ideal/Operations.lean | 2 +- Mathlib/RingTheory/Localization/Defs.lean | 3 +- Mathlib/RingTheory/Noetherian/Defs.lean | 4 +- .../UniqueFactorizationDomain/Defs.lean | 4 +- Mathlib/SetTheory/Cardinal/Aleph.lean | 4 +- Mathlib/SetTheory/Cardinal/Arithmetic.lean | 3 +- Mathlib/SetTheory/Ordinal/Arithmetic.lean | 3 +- Mathlib/SetTheory/Ordinal/Basic.lean | 3 +- Mathlib/Tactic/Abel.lean | 4 +- Mathlib/Topology/ContinuousMap/Periodic.lean | 3 +- Mathlib/Topology/EMetricSpace/Defs.lean | 5 +- Mathlib/Util/AssertExists.lean | 50 ++++++++++--------- MathlibTest/AssertExists.lean | 19 +++++++ 192 files changed, 241 insertions(+), 561 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Defs.lean b/Mathlib/Algebra/Algebra/Defs.lean index 40ac1bbeaf52e..40444543378de 100644 --- a/Mathlib/Algebra/Algebra/Defs.lean +++ b/Mathlib/Algebra/Algebra/Defs.lean @@ -80,9 +80,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 +assert_not_exists Field Finset Module.End universe u v w u₁ v₁ diff --git a/Mathlib/Algebra/Associated/Basic.lean b/Mathlib/Algebra/Associated/Basic.lean index 12ae9d5fdd160..5e6399d91ab42 100644 --- a/Mathlib/Algebra/Associated/Basic.lean +++ b/Mathlib/Algebra/Associated/Basic.lean @@ -21,8 +21,7 @@ Then we show that the quotient type `Associates` is a monoid and prove basic properties of this quotient. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists Multiset +assert_not_exists OrderedCommMonoid Multiset variable {M : Type*} diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index c7a1990d9cf1c..0a8f1edf33fc0 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -38,9 +38,7 @@ See the documentation of `to_additive.attr` for more information. -- TODO -- assert_not_exists AddCommMonoidWithOne -assert_not_exists MonoidWithZero -assert_not_exists MulAction -assert_not_exists OrderedCommMonoid +assert_not_exists MonoidWithZero MulAction OrderedCommMonoid variable {ι κ α β γ : Type*} diff --git a/Mathlib/Algebra/CharP/Basic.lean b/Mathlib/Algebra/CharP/Basic.lean index 1a3eee8e323cf..1305e6cb810a0 100644 --- a/Mathlib/Algebra/CharP/Basic.lean +++ b/Mathlib/Algebra/CharP/Basic.lean @@ -19,8 +19,7 @@ imports of `CharP/Lemmas.lean`. As such, we can probably reorganize and find a better home for most of these lemmas. -/ -assert_not_exists Finset -assert_not_exists TwoSidedIdeal +assert_not_exists Finset TwoSidedIdeal open Set diff --git a/Mathlib/Algebra/CharP/Defs.lean b/Mathlib/Algebra/CharP/Defs.lean index 9c7fa12021669..f94c2736a76d0 100644 --- a/Mathlib/Algebra/CharP/Defs.lean +++ b/Mathlib/Algebra/CharP/Defs.lean @@ -19,8 +19,7 @@ import Mathlib.Data.Nat.Prime.Defs prime characteristic `p`) -/ -assert_not_exists Field -assert_not_exists Finset +assert_not_exists Field Finset open Set diff --git a/Mathlib/Algebra/CharP/Lemmas.lean b/Mathlib/Algebra/CharP/Lemmas.lean index 68a618f1adec5..f5182dddfbd03 100644 --- a/Mathlib/Algebra/CharP/Lemmas.lean +++ b/Mathlib/Algebra/CharP/Lemmas.lean @@ -12,9 +12,7 @@ import Mathlib.Data.Nat.Choose.Sum # Characteristic of semirings -/ -assert_not_exists Algebra -assert_not_exists LinearMap -assert_not_exists orderOf +assert_not_exists Algebra LinearMap orderOf open Finset diff --git a/Mathlib/Algebra/CharP/Two.lean b/Mathlib/Algebra/CharP/Two.lean index 508390fa0fa72..395ae9f2dfa0b 100644 --- a/Mathlib/Algebra/CharP/Two.lean +++ b/Mathlib/Algebra/CharP/Two.lean @@ -15,8 +15,7 @@ The lemmas in this file with a `_sq` suffix are just special cases of the `_pow_ elsewhere, with a shorter name for ease of discovery, and no need for a `[Fact (Prime 2)]` argument. -/ -assert_not_exists Algebra -assert_not_exists LinearMap +assert_not_exists Algebra LinearMap variable {R ι : Type*} diff --git a/Mathlib/Algebra/Group/Action/Opposite.lean b/Mathlib/Algebra/Group/Action/Opposite.lean index 4f50ada545d73..cd669c1f44543 100644 --- a/Mathlib/Algebra/Group/Action/Opposite.lean +++ b/Mathlib/Algebra/Group/Action/Opposite.lean @@ -26,8 +26,7 @@ With `open scoped RightActions`, this provides: * `p <+ᵥ v` as an alias for `AddOpposite.op v +ᵥ p` -/ -assert_not_exists MonoidWithZero -assert_not_exists Units +assert_not_exists MonoidWithZero Units variable {M N α β : Type*} diff --git a/Mathlib/Algebra/Group/Basic.lean b/Mathlib/Algebra/Group/Basic.lean index bf22f85392085..342a421455323 100644 --- a/Mathlib/Algebra/Group/Basic.lean +++ b/Mathlib/Algebra/Group/Basic.lean @@ -19,8 +19,7 @@ one-liners from the corresponding axioms. For the definitions of semigroups, mon `Algebra/Group/Defs.lean`. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered open Function diff --git a/Mathlib/Algebra/Group/Center.lean b/Mathlib/Algebra/Group/Center.lean index 3af32138e4920..41e0a54020e35 100644 --- a/Mathlib/Algebra/Group/Center.lean +++ b/Mathlib/Algebra/Group/Center.lean @@ -36,9 +36,7 @@ We provide `Monoid.centralizer`, `AddMonoid.centralizer`, `Subgroup.centralizer` `AddSubgroup.centralizer` in other files. -/ -assert_not_exists Finset -assert_not_exists MonoidWithZero -assert_not_exists Subsemigroup +assert_not_exists Finset MonoidWithZero Subsemigroup variable {M : Type*} {S T : Set M} diff --git a/Mathlib/Algebra/Group/Commutator.lean b/Mathlib/Algebra/Group/Commutator.lean index fa8916f5ec370..b719453bc1f7a 100644 --- a/Mathlib/Algebra/Group/Commutator.lean +++ b/Mathlib/Algebra/Group/Commutator.lean @@ -10,8 +10,7 @@ import Mathlib.Data.Bracket # The bracket on a group given by commutator. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered /-- The commutator of two elements `g₁` and `g₂`. -/ instance commutatorElement {G : Type*} [Group G] : Bracket G G := diff --git a/Mathlib/Algebra/Group/Commute/Basic.lean b/Mathlib/Algebra/Group/Commute/Basic.lean index 15002695cae3b..87ed8a57a0594 100644 --- a/Mathlib/Algebra/Group/Commute/Basic.lean +++ b/Mathlib/Algebra/Group/Commute/Basic.lean @@ -11,8 +11,7 @@ import Mathlib.Algebra.Group.Semiconj.Basic -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered variable {G : Type*} diff --git a/Mathlib/Algebra/Group/Commute/Defs.lean b/Mathlib/Algebra/Group/Commute/Defs.lean index 4d77aadfd19ab..17e0735d1810d 100644 --- a/Mathlib/Algebra/Group/Commute/Defs.lean +++ b/Mathlib/Algebra/Group/Commute/Defs.lean @@ -24,8 +24,7 @@ This file defines only a few operations (`mul_left`, `inv_right`, etc). Other o Most of the proofs come from the properties of `SemiconjBy`. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered variable {G M S : Type*} diff --git a/Mathlib/Algebra/Group/Commute/Hom.lean b/Mathlib/Algebra/Group/Commute/Hom.lean index f95402d1287eb..2fb97a5525dc3 100644 --- a/Mathlib/Algebra/Group/Commute/Hom.lean +++ b/Mathlib/Algebra/Group/Commute/Hom.lean @@ -11,8 +11,7 @@ import Mathlib.Algebra.Group.Hom.Defs # Multiplicative homomorphisms respect semiconjugation and commutation. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered section Commute diff --git a/Mathlib/Algebra/Group/Commute/Units.lean b/Mathlib/Algebra/Group/Commute/Units.lean index fd7db4b5e9cbc..b137a7af7c509 100644 --- a/Mathlib/Algebra/Group/Commute/Units.lean +++ b/Mathlib/Algebra/Group/Commute/Units.lean @@ -11,8 +11,7 @@ import Mathlib.Algebra.Group.Semiconj.Units -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered variable {M : Type*} diff --git a/Mathlib/Algebra/Group/Conj.lean b/Mathlib/Algebra/Group/Conj.lean index 1c2dafc677b31..bdb76f3f65db7 100644 --- a/Mathlib/Algebra/Group/Conj.lean +++ b/Mathlib/Algebra/Group/Conj.lean @@ -12,8 +12,7 @@ import Mathlib.Algebra.Group.Semiconj.Units See also `MulAut.conj` and `Quandle.conj`. -/ -assert_not_exists MonoidWithZero -assert_not_exists Multiset +assert_not_exists MonoidWithZero Multiset universe u v diff --git a/Mathlib/Algebra/Group/Defs.lean b/Mathlib/Algebra/Group/Defs.lean index 9808a37d910f3..93ba85d9f7ca2 100644 --- a/Mathlib/Algebra/Group/Defs.lean +++ b/Mathlib/Algebra/Group/Defs.lean @@ -39,9 +39,7 @@ We register the following instances: -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered -assert_not_exists Function.Injective.eq_iff +assert_not_exists MonoidWithZero DenselyOrdered Function.Injective.eq_iff universe u v w diff --git a/Mathlib/Algebra/Group/Embedding.lean b/Mathlib/Algebra/Group/Embedding.lean index eb1a64cba0f52..6c7e5c09ca371 100644 --- a/Mathlib/Algebra/Group/Embedding.lean +++ b/Mathlib/Algebra/Group/Embedding.lean @@ -10,8 +10,7 @@ import Mathlib.Logic.Embedding.Basic # The embedding of a cancellative semigroup into itself by multiplication by a fixed element. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered variable {G : Type*} diff --git a/Mathlib/Algebra/Group/Even.lean b/Mathlib/Algebra/Group/Even.lean index 32a6d95f0fadf..dbfa138e3cb38 100644 --- a/Mathlib/Algebra/Group/Even.lean +++ b/Mathlib/Algebra/Group/Even.lean @@ -29,8 +29,7 @@ This file defines square and even elements in a monoid. `Mathlib.Algebra.Ring.Parity` for the definition of odd elements. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered open MulOpposite diff --git a/Mathlib/Algebra/Group/Ext.lean b/Mathlib/Algebra/Group/Ext.lean index 89a01542b52ff..0d8ef3472c5c0 100644 --- a/Mathlib/Algebra/Group/Ext.lean +++ b/Mathlib/Algebra/Group/Ext.lean @@ -25,8 +25,7 @@ former uses `HMul.hMul` which is the canonical spelling. monoid, group, extensionality -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered open Function diff --git a/Mathlib/Algebra/Group/Fin/Basic.lean b/Mathlib/Algebra/Group/Fin/Basic.lean index 06f0bb2f7ad67..5a34b7573582a 100644 --- a/Mathlib/Algebra/Group/Fin/Basic.lean +++ b/Mathlib/Algebra/Group/Fin/Basic.lean @@ -17,8 +17,7 @@ This file contains the additive and multiplicative monoid instances on `Fin n`. See note [foundational algebra order theory]. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidWithZero +assert_not_exists OrderedCommMonoid MonoidWithZero open Nat diff --git a/Mathlib/Algebra/Group/Hom/Instances.lean b/Mathlib/Algebra/Group/Hom/Instances.lean index f3371cbd05280..a74b5cfdf1412 100644 --- a/Mathlib/Algebra/Group/Hom/Instances.lean +++ b/Mathlib/Algebra/Group/Hom/Instances.lean @@ -19,8 +19,7 @@ operations. Finally, we provide the `Ring` structure on `AddMonoid.End`. -/ -assert_not_exists AddMonoidWithOne -assert_not_exists Ring +assert_not_exists AddMonoidWithOne Ring universe uM uN uP uQ diff --git a/Mathlib/Algebra/Group/InjSurj.lean b/Mathlib/Algebra/Group/InjSurj.lean index c25210c59545a..a647e99040a75 100644 --- a/Mathlib/Algebra/Group/InjSurj.lean +++ b/Mathlib/Algebra/Group/InjSurj.lean @@ -42,8 +42,7 @@ namespace Function ### Injective -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered namespace Injective diff --git a/Mathlib/Algebra/Group/Int/Defs.lean b/Mathlib/Algebra/Group/Int/Defs.lean index 8115336b8b189..f3a187d30a676 100644 --- a/Mathlib/Algebra/Group/Int/Defs.lean +++ b/Mathlib/Algebra/Group/Int/Defs.lean @@ -13,8 +13,7 @@ This file contains the additive group and multiplicative monoid instances on the See note [foundational algebra order theory]. -/ -assert_not_exists Ring -assert_not_exists DenselyOrdered +assert_not_exists Ring DenselyOrdered open Nat diff --git a/Mathlib/Algebra/Group/Invertible/Basic.lean b/Mathlib/Algebra/Group/Invertible/Basic.lean index 1112be6b7f258..2d62881f5ddf8 100644 --- a/Mathlib/Algebra/Group/Invertible/Basic.lean +++ b/Mathlib/Algebra/Group/Invertible/Basic.lean @@ -12,8 +12,7 @@ import Mathlib.Logic.Equiv.Defs -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered universe u diff --git a/Mathlib/Algebra/Group/Invertible/Defs.lean b/Mathlib/Algebra/Group/Invertible/Defs.lean index 44a1421f131e7..9384c1cc4fd0d 100644 --- a/Mathlib/Algebra/Group/Invertible/Defs.lean +++ b/Mathlib/Algebra/Group/Invertible/Defs.lean @@ -73,8 +73,7 @@ invertible, inverse element, invOf, a half, one half, a third, one third, ½, -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered universe u diff --git a/Mathlib/Algebra/Group/MinimalAxioms.lean b/Mathlib/Algebra/Group/MinimalAxioms.lean index bcc623c694479..bf3c3f9683885 100644 --- a/Mathlib/Algebra/Group/MinimalAxioms.lean +++ b/Mathlib/Algebra/Group/MinimalAxioms.lean @@ -21,8 +21,7 @@ equalities. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered universe u diff --git a/Mathlib/Algebra/Group/Nat/Defs.lean b/Mathlib/Algebra/Group/Nat/Defs.lean index 9d677accc18c3..05111a49950d6 100644 --- a/Mathlib/Algebra/Group/Nat/Defs.lean +++ b/Mathlib/Algebra/Group/Nat/Defs.lean @@ -13,8 +13,7 @@ This file contains the additive and multiplicative monoid instances on the natur See note [foundational algebra order theory]. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered namespace Nat diff --git a/Mathlib/Algebra/Group/Nat/Even.lean b/Mathlib/Algebra/Group/Nat/Even.lean index 1f9afc95a09c7..0cedd8a212532 100644 --- a/Mathlib/Algebra/Group/Nat/Even.lean +++ b/Mathlib/Algebra/Group/Nat/Even.lean @@ -11,8 +11,7 @@ import Mathlib.Data.Nat.Sqrt # `IsSquare` and `Even` for natural numbers -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered namespace Nat diff --git a/Mathlib/Algebra/Group/Nat/TypeTags.lean b/Mathlib/Algebra/Group/Nat/TypeTags.lean index 28c748cbc124e..e4675239184c8 100644 --- a/Mathlib/Algebra/Group/Nat/TypeTags.lean +++ b/Mathlib/Algebra/Group/Nat/TypeTags.lean @@ -10,8 +10,7 @@ import Mathlib.Algebra.Group.TypeTags.Basic # Lemmas about `Multiplicative ℕ` -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered open Multiplicative diff --git a/Mathlib/Algebra/Group/Nat/Units.lean b/Mathlib/Algebra/Group/Nat/Units.lean index 8dfa832751d6e..663c7eb6d3e70 100644 --- a/Mathlib/Algebra/Group/Nat/Units.lean +++ b/Mathlib/Algebra/Group/Nat/Units.lean @@ -11,8 +11,7 @@ import Mathlib.Logic.Unique # The unit of the natural numbers -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered namespace Nat diff --git a/Mathlib/Algebra/Group/Operations.lean b/Mathlib/Algebra/Group/Operations.lean index 74d54a8784207..72ef50266f6c9 100644 --- a/Mathlib/Algebra/Group/Operations.lean +++ b/Mathlib/Algebra/Group/Operations.lean @@ -27,8 +27,7 @@ See the module `Algebra.AddTorsor` for a motivating example for the name `VAdd` -/ -assert_not_exists One -assert_not_exists Function.Injective +assert_not_exists One Function.Injective universe u v w diff --git a/Mathlib/Algebra/Group/Opposite.lean b/Mathlib/Algebra/Group/Opposite.lean index 5d91ad7cacb87..a3dc612736a5c 100644 --- a/Mathlib/Algebra/Group/Opposite.lean +++ b/Mathlib/Algebra/Group/Opposite.lean @@ -14,9 +14,7 @@ import Mathlib.Tactic.Spread # Group structures on the multiplicative and additive opposites -/ -assert_not_exists DenselyOrdered -assert_not_exists MonoidWithZero -assert_not_exists Units +assert_not_exists MonoidWithZero DenselyOrdered Units variable {α : Type*} diff --git a/Mathlib/Algebra/Group/Pi/Basic.lean b/Mathlib/Algebra/Group/Pi/Basic.lean index 9016e7a5abc7f..135dc4111e6c8 100644 --- a/Mathlib/Algebra/Group/Pi/Basic.lean +++ b/Mathlib/Algebra/Group/Pi/Basic.lean @@ -23,10 +23,7 @@ comment `--pi_instance` is inserted before all fields which were previously deri -/ -- We enforce to only import `Algebra.Group.Defs` and basic logic -assert_not_exists Set.range -assert_not_exists MonoidHom -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists Set.range MonoidHom MonoidWithZero DenselyOrdered open Function diff --git a/Mathlib/Algebra/Group/Pi/Lemmas.lean b/Mathlib/Algebra/Group/Pi/Lemmas.lean index e9dd7d38a4ff0..697d42405d54c 100644 --- a/Mathlib/Algebra/Group/Pi/Lemmas.lean +++ b/Mathlib/Algebra/Group/Pi/Lemmas.lean @@ -15,8 +15,7 @@ This file proves lemmas about the instances defined in `Algebra.Group.Pi.Basic` imports. -/ -assert_not_exists AddMonoidWithOne -assert_not_exists MonoidWithZero +assert_not_exists AddMonoidWithOne MonoidWithZero universe u v w diff --git a/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean index 244cc84123a5a..3713828769d33 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean @@ -54,8 +54,7 @@ set multiplication, set addition, pointwise addition, pointwise multiplication, pointwise subtraction -/ -assert_not_exists MonoidWithZero -assert_not_exists OrderedAddCommMonoid +assert_not_exists MonoidWithZero OrderedAddCommMonoid library_note "pointwise nat action"/-- Pointwise monoids (`Set`, `Finset`, `Filter`) have derived pointwise actions of the form diff --git a/Mathlib/Algebra/Group/Prod.lean b/Mathlib/Algebra/Group/Prod.lean index de72f571ab908..aa462854b7086 100644 --- a/Mathlib/Algebra/Group/Prod.lean +++ b/Mathlib/Algebra/Group/Prod.lean @@ -29,10 +29,9 @@ We also prove trivial `simp` lemmas, and define the following operations on `Mon * `divMonoidHom`: Division bundled as a monoid homomorphism. -/ -assert_not_exists MonoidWithZero +assert_not_exists MonoidWithZero DenselyOrdered -- TODO: -- assert_not_exists AddMonoidWithOne -assert_not_exists DenselyOrdered variable {G : Type*} {H : Type*} {M : Type*} {N : Type*} {P : Type*} diff --git a/Mathlib/Algebra/Group/Semiconj/Basic.lean b/Mathlib/Algebra/Group/Semiconj/Basic.lean index 1aa1d51cc6094..4a120391662d6 100644 --- a/Mathlib/Algebra/Group/Semiconj/Basic.lean +++ b/Mathlib/Algebra/Group/Semiconj/Basic.lean @@ -11,8 +11,7 @@ import Mathlib.Algebra.Group.Basic -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered namespace SemiconjBy variable {G : Type*} diff --git a/Mathlib/Algebra/Group/Semiconj/Defs.lean b/Mathlib/Algebra/Group/Semiconj/Defs.lean index dc45b2afef400..aa97ad1f631ed 100644 --- a/Mathlib/Algebra/Group/Semiconj/Defs.lean +++ b/Mathlib/Algebra/Group/Semiconj/Defs.lean @@ -27,8 +27,7 @@ This file provides only basic operations (`mul_left`, `mul_right`, `inv_right` e operations (`pow_right`, field inverse etc) are in the files that define corresponding notions. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered variable {S M G : Type*} diff --git a/Mathlib/Algebra/Group/Semiconj/Units.lean b/Mathlib/Algebra/Group/Semiconj/Units.lean index 45c46f379e4c2..09fbea9af5e8b 100644 --- a/Mathlib/Algebra/Group/Semiconj/Units.lean +++ b/Mathlib/Algebra/Group/Semiconj/Units.lean @@ -27,8 +27,7 @@ This file provides only basic operations (`mul_left`, `mul_right`, `inv_right` e operations (`pow_right`, field inverse etc) are in the files that define corresponding notions. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered open scoped Int diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index e8e540cca1c03..d1c6c4df4c96f 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -45,9 +45,7 @@ membership of a subgroup's underlying set. subgroup, subgroups -/ -assert_not_exists OrderedAddCommMonoid -assert_not_exists Multiset -assert_not_exists Ring +assert_not_exists OrderedAddCommMonoid Multiset Ring open Function open scoped Int diff --git a/Mathlib/Algebra/Group/Subgroup/Defs.lean b/Mathlib/Algebra/Group/Subgroup/Defs.lean index 2063e20c5c2ce..eea53f4a65caf 100644 --- a/Mathlib/Algebra/Group/Subgroup/Defs.lean +++ b/Mathlib/Algebra/Group/Subgroup/Defs.lean @@ -47,9 +47,7 @@ membership of a subgroup's underlying set. subgroup, subgroups -/ -assert_not_exists OrderedAddCommMonoid -assert_not_exists Multiset -assert_not_exists Ring +assert_not_exists OrderedAddCommMonoid Multiset Ring open Function open scoped Int diff --git a/Mathlib/Algebra/Group/Subgroup/Ker.lean b/Mathlib/Algebra/Group/Subgroup/Ker.lean index b9f741deb62ee..9d903bdb6373c 100644 --- a/Mathlib/Algebra/Group/Subgroup/Ker.lean +++ b/Mathlib/Algebra/Group/Subgroup/Ker.lean @@ -42,9 +42,7 @@ membership of a subgroup's underlying set. subgroup, subgroups -/ -assert_not_exists OrderedAddCommMonoid -assert_not_exists Multiset -assert_not_exists Ring +assert_not_exists OrderedAddCommMonoid Multiset Ring open Function open scoped Int diff --git a/Mathlib/Algebra/Group/Subgroup/Lattice.lean b/Mathlib/Algebra/Group/Subgroup/Lattice.lean index 8d9277bb28c46..4bfc3f9f4d350 100644 --- a/Mathlib/Algebra/Group/Subgroup/Lattice.lean +++ b/Mathlib/Algebra/Group/Subgroup/Lattice.lean @@ -42,9 +42,7 @@ membership of a subgroup's underlying set. subgroup, subgroups -/ -assert_not_exists OrderedAddCommMonoid -assert_not_exists Multiset -assert_not_exists Ring +assert_not_exists OrderedAddCommMonoid Multiset Ring open Function open scoped Int diff --git a/Mathlib/Algebra/Group/Subgroup/Map.lean b/Mathlib/Algebra/Group/Subgroup/Map.lean index 76fdb39866cc6..0c8f0813a9bdc 100644 --- a/Mathlib/Algebra/Group/Subgroup/Map.lean +++ b/Mathlib/Algebra/Group/Subgroup/Map.lean @@ -45,9 +45,7 @@ membership of a subgroup's underlying set. subgroup, subgroups -/ -assert_not_exists OrderedAddCommMonoid -assert_not_exists Multiset -assert_not_exists Ring +assert_not_exists OrderedAddCommMonoid Multiset Ring open Function open scoped Int diff --git a/Mathlib/Algebra/Group/Submonoid/Defs.lean b/Mathlib/Algebra/Group/Submonoid/Defs.lean index 6e6914bae3bc7..4f7ad4ad1b945 100644 --- a/Mathlib/Algebra/Group/Submonoid/Defs.lean +++ b/Mathlib/Algebra/Group/Submonoid/Defs.lean @@ -44,8 +44,7 @@ numbers. `Submonoid` is implemented by extending `Subsemigroup` requiring `one_m submonoid, submonoids -/ -assert_not_exists CompleteLattice -assert_not_exists MonoidWithZero +assert_not_exists CompleteLattice MonoidWithZero variable {M : Type*} {N : Type*} diff --git a/Mathlib/Algebra/Group/Subsemigroup/Defs.lean b/Mathlib/Algebra/Group/Subsemigroup/Defs.lean index ef136ff0a76ab..24404d2fb09fc 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Defs.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Defs.lean @@ -45,8 +45,7 @@ numbers. subsemigroup, subsemigroups -/ -assert_not_exists CompleteLattice -assert_not_exists MonoidWithZero +assert_not_exists CompleteLattice MonoidWithZero variable {M : Type*} {N : Type*} diff --git a/Mathlib/Algebra/Group/TypeTags/Basic.lean b/Mathlib/Algebra/Group/TypeTags/Basic.lean index a856c3ad37498..c4358d690d519 100644 --- a/Mathlib/Algebra/Group/TypeTags/Basic.lean +++ b/Mathlib/Algebra/Group/TypeTags/Basic.lean @@ -29,10 +29,7 @@ This file is similar to `Order.Synonym`. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered -assert_not_exists MonoidHom -assert_not_exists Finite +assert_not_exists MonoidWithZero DenselyOrdered MonoidHom Finite universe u v diff --git a/Mathlib/Algebra/Group/TypeTags/Finite.lean b/Mathlib/Algebra/Group/TypeTags/Finite.lean index e3885696b373b..aab3bb90b4984 100644 --- a/Mathlib/Algebra/Group/TypeTags/Finite.lean +++ b/Mathlib/Algebra/Group/TypeTags/Finite.lean @@ -10,8 +10,7 @@ import Mathlib.Data.Finite.Defs # `Finite` and `Infinite` are preserved by `Additive` and `Multiplicative`. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered universe u v diff --git a/Mathlib/Algebra/Group/ULift.lean b/Mathlib/Algebra/Group/ULift.lean index f7088335116e8..3fa88a1bd715e 100644 --- a/Mathlib/Algebra/Group/ULift.lean +++ b/Mathlib/Algebra/Group/ULift.lean @@ -17,8 +17,7 @@ This file defines instances for group, monoid, semigroup and related structures We also provide `MulEquiv.ulift : ULift R ≃* R` (and its additive analogue). -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered universe u v diff --git a/Mathlib/Algebra/Group/UniqueProds/Basic.lean b/Mathlib/Algebra/Group/UniqueProds/Basic.lean index 2e38b8dc940aa..36b8aecd06af0 100644 --- a/Mathlib/Algebra/Group/UniqueProds/Basic.lean +++ b/Mathlib/Algebra/Group/UniqueProds/Basic.lean @@ -47,11 +47,7 @@ about the grading type and then a generic statement of the form "look at the coe The file `Algebra/MonoidAlgebra/NoZeroDivisors` contains several examples of this use. -/ -assert_not_exists Cardinal -assert_not_exists Subsemiring -assert_not_exists Algebra -assert_not_exists Submodule -assert_not_exists StarModule +assert_not_exists Cardinal Subsemiring Algebra Submodule StarModule open Finset diff --git a/Mathlib/Algebra/Group/Units/Basic.lean b/Mathlib/Algebra/Group/Units/Basic.lean index 3cb0df004f9d7..20b162ed67d8c 100644 --- a/Mathlib/Algebra/Group/Units/Basic.lean +++ b/Mathlib/Algebra/Group/Units/Basic.lean @@ -23,9 +23,7 @@ and unique types. The results here should be used to golf the basic `Group` lemmas. -/ -assert_not_exists Multiplicative -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists Multiplicative MonoidWithZero DenselyOrdered open Function diff --git a/Mathlib/Algebra/Group/Units/Defs.lean b/Mathlib/Algebra/Group/Units/Defs.lean index 70119cf974a97..62cfa10d66c99 100644 --- a/Mathlib/Algebra/Group/Units/Defs.lean +++ b/Mathlib/Algebra/Group/Units/Defs.lean @@ -30,9 +30,7 @@ resembling the notation $R^{\times}$ for the units of a ring, which is common in The results here should be used to golf the basic `Group` lemmas. -/ -assert_not_exists Multiplicative -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists Multiplicative MonoidWithZero DenselyOrdered open Function diff --git a/Mathlib/Algebra/Group/Units/Equiv.lean b/Mathlib/Algebra/Group/Units/Equiv.lean index 7118fdc79cf30..6227bf7099124 100644 --- a/Mathlib/Algebra/Group/Units/Equiv.lean +++ b/Mathlib/Algebra/Group/Units/Equiv.lean @@ -10,8 +10,7 @@ import Mathlib.Algebra.Group.Units.Hom # Multiplicative and additive equivalence acting on units. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered variable {F α M N G : Type*} diff --git a/Mathlib/Algebra/Group/Units/Hom.lean b/Mathlib/Algebra/Group/Units/Hom.lean index a2c7a435b6886..cdb9b99c3cec2 100644 --- a/Mathlib/Algebra/Group/Units/Hom.lean +++ b/Mathlib/Algebra/Group/Units/Hom.lean @@ -31,8 +31,7 @@ used to golf the basic `Group` lemmas. Add a `@[to_additive]` version of `IsLocalHom`. -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered open Function diff --git a/Mathlib/Algebra/Group/Units/Opposite.lean b/Mathlib/Algebra/Group/Units/Opposite.lean index cd898f2d7413b..5b1d120053c59 100644 --- a/Mathlib/Algebra/Group/Units/Opposite.lean +++ b/Mathlib/Algebra/Group/Units/Opposite.lean @@ -10,8 +10,7 @@ import Mathlib.Algebra.Group.Units.Defs # Units in multiplicative and additive opposites -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered variable {α : Type*} diff --git a/Mathlib/Algebra/Group/WithOne/Basic.lean b/Mathlib/Algebra/Group/WithOne/Basic.lean index b9d87ce1b04af..76a4286b0858d 100644 --- a/Mathlib/Algebra/Group/WithOne/Basic.lean +++ b/Mathlib/Algebra/Group/WithOne/Basic.lean @@ -18,8 +18,7 @@ that were not available in `Algebra/Group/WithOne/Defs`. * `WithOne.map`, `WithZero.map` -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered universe u v w diff --git a/Mathlib/Algebra/Group/WithOne/Defs.lean b/Mathlib/Algebra/Group/WithOne/Defs.lean index 39ed722267c5d..dc7d3fcec8135 100644 --- a/Mathlib/Algebra/Group/WithOne/Defs.lean +++ b/Mathlib/Algebra/Group/WithOne/Defs.lean @@ -34,12 +34,7 @@ longer typecheck. In Lean 4, both types are plain `def`s, so we don't need these -- Check that we haven't needed to import all the basic lemmas about groups, -- by asserting a random sample don't exist here: -assert_not_exists inv_involutive -assert_not_exists div_right_inj -assert_not_exists pow_ite - -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists inv_involutive div_right_inj pow_ite MonoidWithZero DenselyOrdered universe u v w diff --git a/Mathlib/Algebra/GroupPower/IterateHom.lean b/Mathlib/Algebra/GroupPower/IterateHom.lean index 1f4f7705b2573..9dc491701f4e8 100644 --- a/Mathlib/Algebra/GroupPower/IterateHom.lean +++ b/Mathlib/Algebra/GroupPower/IterateHom.lean @@ -26,8 +26,7 @@ We also prove formulas for iterates of add/mul left/right. homomorphism, iterate -/ -assert_not_exists MonoidWithZero -assert_not_exists DenselyOrdered +assert_not_exists MonoidWithZero DenselyOrdered open Function diff --git a/Mathlib/Algebra/GroupWithZero/Action/Defs.lean b/Mathlib/Algebra/GroupWithZero/Action/Defs.lean index f4420acfd2b38..50cdf5c5fbf84 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Defs.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Defs.lean @@ -34,9 +34,7 @@ More sophisticated lemmas belong in `GroupTheory.GroupAction`. group action -/ -assert_not_exists Equiv.Perm.equivUnitsEnd -assert_not_exists Prod.fst_mul -assert_not_exists Ring +assert_not_exists Equiv.Perm.equivUnitsEnd Prod.fst_mul Ring open Function diff --git a/Mathlib/Algebra/GroupWithZero/Action/End.lean b/Mathlib/Algebra/GroupWithZero/Action/End.lean index aac2431234328..79f3d7dc54538 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/End.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/End.lean @@ -12,9 +12,7 @@ import Mathlib.Algebra.GroupWithZero.Action.Units # Group actions and (endo)morphisms -/ -assert_not_exists Equiv.Perm.equivUnitsEnd -assert_not_exists Prod.fst_mul -assert_not_exists Ring +assert_not_exists Equiv.Perm.equivUnitsEnd Prod.fst_mul Ring open Function diff --git a/Mathlib/Algebra/GroupWithZero/Action/Faithful.lean b/Mathlib/Algebra/GroupWithZero/Action/Faithful.lean index c804420b658e9..fbb73d2353ea5 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Faithful.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Faithful.lean @@ -10,9 +10,7 @@ import Mathlib.Algebra.GroupWithZero.NeZero # Faithful actions involving groups with zero -/ -assert_not_exists Equiv.Perm.equivUnitsEnd -assert_not_exists Prod.fst_mul -assert_not_exists Ring +assert_not_exists Equiv.Perm.equivUnitsEnd Prod.fst_mul Ring open Function diff --git a/Mathlib/Algebra/GroupWithZero/Center.lean b/Mathlib/Algebra/GroupWithZero/Center.lean index 3f721aaa7d178..f38ccd5587ab2 100644 --- a/Mathlib/Algebra/GroupWithZero/Center.lean +++ b/Mathlib/Algebra/GroupWithZero/Center.lean @@ -10,9 +10,7 @@ import Mathlib.Algebra.GroupWithZero.Units.Basic # Center of a group with zero -/ -assert_not_exists Finset -assert_not_exists Ring -assert_not_exists Subsemigroup +assert_not_exists Finset Ring Subsemigroup variable {M₀ G₀ : Type*} diff --git a/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Basic.lean b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Basic.lean index 5946f5ed2505f..3059715ef02a4 100644 --- a/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Basic.lean @@ -17,8 +17,7 @@ set multiplication, set addition, pointwise addition, pointwise multiplication, pointwise subtraction -/ -assert_not_exists OrderedAddCommMonoid -assert_not_exists Ring +assert_not_exists OrderedAddCommMonoid Ring open Function open scoped Pointwise diff --git a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean index 5b98cfd3fad68..9c876dd881321 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean @@ -18,10 +18,7 @@ We also define `Ring.inverse`, a globally defined function on any ring -/ -- Guard against import creep -assert_not_exists DenselyOrdered -assert_not_exists Equiv -assert_not_exists Multiplicative -assert_not_exists Subtype.restrict +assert_not_exists DenselyOrdered Equiv Subtype.restrict Multiplicative variable {α M₀ G₀ : Type*} diff --git a/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean b/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean index 76a1db8a95279..055aafaffef78 100644 --- a/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean +++ b/Mathlib/Algebra/Homology/TotalComplexSymmetry.lean @@ -20,8 +20,7 @@ are compatible `[TotalComplexShapeSymmetrySymmetry c₁ c₂ c]`, then the isomo -/ -assert_not_exists Ideal -assert_not_exists TwoSidedIdeal +assert_not_exists Ideal TwoSidedIdeal open CategoryTheory Category Limits diff --git a/Mathlib/Algebra/Module/Basic.lean b/Mathlib/Algebra/Module/Basic.lean index 7ba518660f634..1c97089ef1615 100644 --- a/Mathlib/Algebra/Module/Basic.lean +++ b/Mathlib/Algebra/Module/Basic.lean @@ -16,8 +16,7 @@ import Mathlib.Algebra.Ring.Invertible -/ -assert_not_exists Nonneg.inv -assert_not_exists Multiset +assert_not_exists Nonneg.inv Multiset open Function Set diff --git a/Mathlib/Algebra/Module/Defs.lean b/Mathlib/Algebra/Module/Defs.lean index ebc9ab4254580..7fa247e864bfd 100644 --- a/Mathlib/Algebra/Module/Defs.lean +++ b/Mathlib/Algebra/Module/Defs.lean @@ -36,13 +36,7 @@ to use a canonical `Module` typeclass throughout. semimodule, module, vector space -/ -assert_not_exists Field -assert_not_exists Invertible -assert_not_exists Multiset -assert_not_exists Pi.single_smul₀ -assert_not_exists RingHom -assert_not_exists Set.indicator -assert_not_exists Units +assert_not_exists Field Invertible Pi.single_smul₀ RingHom Set.indicator Multiset Units open Function Set diff --git a/Mathlib/Algebra/Module/End.lean b/Mathlib/Algebra/Module/End.lean index 426b42dfa3ea6..fcc7b16410795 100644 --- a/Mathlib/Algebra/Module/End.lean +++ b/Mathlib/Algebra/Module/End.lean @@ -14,10 +14,7 @@ In this file, we define `Module.toAddMonoidEnd`, which is `(•)` as a monoid ho We use this to prove some results on scalar multiplication by integers. -/ -assert_not_exists Multiset -assert_not_exists Set.indicator -assert_not_exists Pi.single_smul₀ -assert_not_exists Field +assert_not_exists Multiset Set.indicator Pi.single_smul₀ Field open Function Set diff --git a/Mathlib/Algebra/Module/Equiv/Defs.lean b/Mathlib/Algebra/Module/Equiv/Defs.lean index 7bda130ecaced..678ac96dd6526 100644 --- a/Mathlib/Algebra/Module/Equiv/Defs.lean +++ b/Mathlib/Algebra/Module/Equiv/Defs.lean @@ -33,8 +33,7 @@ The group structure on automorphisms, `LinearEquiv.automorphismGroup`, is provid linear equiv, linear equivalences, linear isomorphism, linear isomorphic -/ -assert_not_exists Field -assert_not_exists Pi.module +assert_not_exists Field Pi.module open Function diff --git a/Mathlib/Algebra/Module/LinearMap/Basic.lean b/Mathlib/Algebra/Module/LinearMap/Basic.lean index b82258f2ecc03..43a9f72fd9bee 100644 --- a/Mathlib/Algebra/Module/LinearMap/Basic.lean +++ b/Mathlib/Algebra/Module/LinearMap/Basic.lean @@ -14,9 +14,7 @@ import Mathlib.GroupTheory.GroupAction.DomAct.Basic -/ -assert_not_exists Submonoid -assert_not_exists Finset -assert_not_exists Star +assert_not_exists Submonoid Finset Star open Function diff --git a/Mathlib/Algebra/Module/LinearMap/Defs.lean b/Mathlib/Algebra/Module/LinearMap/Defs.lean index 7041673c0691f..c99d8725f1947 100644 --- a/Mathlib/Algebra/Module/LinearMap/Defs.lean +++ b/Mathlib/Algebra/Module/LinearMap/Defs.lean @@ -51,11 +51,7 @@ linear map -/ -assert_not_exists Star -assert_not_exists DomMulAct -assert_not_exists Pi.module -assert_not_exists WCovBy -assert_not_exists Field +assert_not_exists Star DomMulAct Pi.module WCovBy Field open Function diff --git a/Mathlib/Algebra/Module/NatInt.lean b/Mathlib/Algebra/Module/NatInt.lean index 606a7988f0fbe..12ce588590dbe 100644 --- a/Mathlib/Algebra/Module/NatInt.lean +++ b/Mathlib/Algebra/Module/NatInt.lean @@ -26,11 +26,7 @@ This file concerns modules where the scalars are the natural numbers or the inte semimodule, module, vector space -/ -assert_not_exists Field -assert_not_exists Invertible -assert_not_exists Multiset -assert_not_exists Pi.single_smul₀ -assert_not_exists Set.indicator +assert_not_exists Field Invertible Multiset Pi.single_smul₀ Set.indicator open Function Set diff --git a/Mathlib/Algebra/Module/RingHom.lean b/Mathlib/Algebra/Module/RingHom.lean index ae178799ace69..89aa81870f16f 100644 --- a/Mathlib/Algebra/Module/RingHom.lean +++ b/Mathlib/Algebra/Module/RingHom.lean @@ -20,11 +20,7 @@ import Mathlib.Algebra.Ring.Hom.Defs semimodule, module, vector space -/ -assert_not_exists Field -assert_not_exists Invertible -assert_not_exists Multiset -assert_not_exists Pi.single_smul₀ -assert_not_exists Set.indicator +assert_not_exists Field Invertible Multiset Pi.single_smul₀ Set.indicator open Function Set diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index 379ff57f2cd6b..e75be2e4ec643 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -48,8 +48,7 @@ Similarly, I attempted to just define `Multiplicative G = G` leaks through everywhere, and seems impossible to use. -/ -assert_not_exists NonUnitalAlgHom -assert_not_exists AlgEquiv +assert_not_exists NonUnitalAlgHom AlgEquiv noncomputable section diff --git a/Mathlib/Algebra/NoZeroSMulDivisors/Basic.lean b/Mathlib/Algebra/NoZeroSMulDivisors/Basic.lean index c4b95955f40ac..54290677e5567 100644 --- a/Mathlib/Algebra/NoZeroSMulDivisors/Basic.lean +++ b/Mathlib/Algebra/NoZeroSMulDivisors/Basic.lean @@ -14,10 +14,7 @@ This file defines the `NoZeroSMulDivisors` class, and includes some tests for the vanishing of elements (especially in modules over division rings). -/ -assert_not_exists Multiset -assert_not_exists Set.indicator -assert_not_exists Pi.single_smul₀ -assert_not_exists Field +assert_not_exists Multiset Set.indicator Pi.single_smul₀ Field section NoZeroSMulDivisors diff --git a/Mathlib/Algebra/NoZeroSMulDivisors/Defs.lean b/Mathlib/Algebra/NoZeroSMulDivisors/Defs.lean index caa70e20f08e3..024d97cb288dd 100644 --- a/Mathlib/Algebra/NoZeroSMulDivisors/Defs.lean +++ b/Mathlib/Algebra/NoZeroSMulDivisors/Defs.lean @@ -12,11 +12,7 @@ This file defines the `NoZeroSMulDivisors` class, and includes some tests for the vanishing of elements (especially in modules over division rings). -/ -assert_not_exists Multiset -assert_not_exists Set.indicator -assert_not_exists Pi.single_smul₀ -assert_not_exists Field -assert_not_exists Module +assert_not_exists Multiset Set.indicator Pi.single_smul₀ Field Module section NoZeroSMulDivisors diff --git a/Mathlib/Algebra/Order/CauSeq/Basic.lean b/Mathlib/Algebra/Order/CauSeq/Basic.lean index 5ba2dc7d77f6f..fb76b07c2edb2 100644 --- a/Mathlib/Algebra/Order/CauSeq/Basic.lean +++ b/Mathlib/Algebra/Order/CauSeq/Basic.lean @@ -31,11 +31,7 @@ This is a concrete implementation that is useful for simplicity and computabilit sequence, cauchy, abs val, absolute value -/ -assert_not_exists Finset -assert_not_exists Module -assert_not_exists Submonoid -assert_not_exists FloorRing -assert_not_exists Module +assert_not_exists Finset Module Submonoid FloorRing Module variable {α β : Type*} diff --git a/Mathlib/Algebra/Order/Group/Int.lean b/Mathlib/Algebra/Order/Group/Int.lean index c545ec92b97e7..58c8705ef1795 100644 --- a/Mathlib/Algebra/Order/Group/Int.lean +++ b/Mathlib/Algebra/Order/Group/Int.lean @@ -16,9 +16,7 @@ See note [foundational algebra order theory]. -/ -- We should need only a minimal development of sets in order to get here. -assert_not_exists Set.Subsingleton - -assert_not_exists Ring +assert_not_exists Set.Subsingleton Ring open Function Nat diff --git a/Mathlib/Algebra/Order/Group/Unbundled/Int.lean b/Mathlib/Algebra/Order/Group/Unbundled/Int.lean index c6a057822d4a8..af82f1eae06a5 100644 --- a/Mathlib/Algebra/Order/Group/Unbundled/Int.lean +++ b/Mathlib/Algebra/Order/Group/Unbundled/Int.lean @@ -22,8 +22,7 @@ See note [foundational algebra order theory]. -/ -- We should need only a minimal development of sets in order to get here. -assert_not_exists Set.Subsingleton -assert_not_exists Ring +assert_not_exists Set.Subsingleton Ring open Function Nat diff --git a/Mathlib/Algebra/Order/Hom/Ring.lean b/Mathlib/Algebra/Order/Hom/Ring.lean index 05433d9cf069a..71fa34cb4fd5a 100644 --- a/Mathlib/Algebra/Order/Hom/Ring.lean +++ b/Mathlib/Algebra/Order/Hom/Ring.lean @@ -33,8 +33,7 @@ making some typeclasses and instances irrelevant. ordered ring homomorphism, order homomorphism -/ -assert_not_exists FloorRing -assert_not_exists Archimedean +assert_not_exists FloorRing Archimedean open Function diff --git a/Mathlib/Algebra/Order/Ring/Rat.lean b/Mathlib/Algebra/Order/Ring/Rat.lean index 12e6c49ad09a5..2be45468879ea 100644 --- a/Mathlib/Algebra/Order/Ring/Rat.lean +++ b/Mathlib/Algebra/Order/Ring/Rat.lean @@ -20,10 +20,7 @@ here because we need the order on `ℚ` to define `ℚ≥0`, which we itself nee rat, rationals, field, ℚ, numerator, denominator, num, denom, order, ordering -/ -assert_not_exists Field -assert_not_exists Finset -assert_not_exists Set.Icc -assert_not_exists GaloisConnection +assert_not_exists Field Finset Set.Icc GaloisConnection namespace Rat diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean index 99bd1f2cfd31c..12714755ede35 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean @@ -113,8 +113,7 @@ TODO: the mixin assumptiosn can be relaxed in most cases -/ -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidHom +assert_not_exists OrderedCommMonoid MonoidHom open Function diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean index bd7669e3210be..634978d7a31d5 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean @@ -21,11 +21,7 @@ For the bundled `LinearOrderedCommRing` instance on `ℚ`, see `Algebra.Order.Ri rat, rationals, field, ℚ, numerator, denominator, num, denom, order, ordering -/ -assert_not_exists OrderedCommMonoid -assert_not_exists Field -assert_not_exists Finset -assert_not_exists Set.Icc -assert_not_exists GaloisConnection +assert_not_exists OrderedCommMonoid Field Finset Set.Icc GaloisConnection namespace Rat diff --git a/Mathlib/Algebra/Prime/Defs.lean b/Mathlib/Algebra/Prime/Defs.lean index 86ec680140369..717576fa44ec4 100644 --- a/Mathlib/Algebra/Prime/Defs.lean +++ b/Mathlib/Algebra/Prime/Defs.lean @@ -24,8 +24,7 @@ In decomposition monoids (e.g., `ℕ`, `ℤ`), this predicate is equivalent to ` * `irreducible_iff_prime`: the two definitions are equivalent in a decomposition monoid. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists Multiset +assert_not_exists OrderedCommMonoid Multiset variable {M : Type*} diff --git a/Mathlib/Algebra/Prime/Lemmas.lean b/Mathlib/Algebra/Prime/Lemmas.lean index 6461b52529e62..f2cd1f36dcc2d 100644 --- a/Mathlib/Algebra/Prime/Lemmas.lean +++ b/Mathlib/Algebra/Prime/Lemmas.lean @@ -28,8 +28,7 @@ Then we show that the quotient type `Associates` is a monoid and prove basic properties of this quotient. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists Multiset +assert_not_exists OrderedCommMonoid Multiset variable {M N : Type*} diff --git a/Mathlib/Algebra/Ring/Action/Basic.lean b/Mathlib/Algebra/Ring/Action/Basic.lean index d29c1984e45d9..4aafdd6769161 100644 --- a/Mathlib/Algebra/Ring/Action/Basic.lean +++ b/Mathlib/Algebra/Ring/Action/Basic.lean @@ -25,8 +25,7 @@ group action, invariant subring -/ -assert_not_exists Equiv.Perm.equivUnitsEnd -assert_not_exists Prod.fst_mul +assert_not_exists Equiv.Perm.equivUnitsEnd Prod.fst_mul universe u v diff --git a/Mathlib/Algebra/Ring/Center.lean b/Mathlib/Algebra/Ring/Center.lean index 828c1c41ecadb..683046995007a 100644 --- a/Mathlib/Algebra/Ring/Center.lean +++ b/Mathlib/Algebra/Ring/Center.lean @@ -12,8 +12,7 @@ import Mathlib.Data.Int.Cast.Lemmas -/ -- Guard against import creep -assert_not_exists Finset -assert_not_exists Subsemigroup +assert_not_exists Finset Subsemigroup variable {M : Type*} diff --git a/Mathlib/Algebra/Ring/Defs.lean b/Mathlib/Algebra/Ring/Defs.lean index cb054eef56a71..b6f955aa7ec8f 100644 --- a/Mathlib/Algebra/Ring/Defs.lean +++ b/Mathlib/Algebra/Ring/Defs.lean @@ -42,8 +42,7 @@ files, without importing `.Basic` theory development. These `assert_not_exists` statements guard against this returning. -/ -assert_not_exists DivisionMonoid.toDivInvOneMonoid -assert_not_exists mul_rotate +assert_not_exists DivisionMonoid.toDivInvOneMonoid mul_rotate universe u v diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index f65b840107c50..c192e8ba6a766 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -38,8 +38,7 @@ Equiv, MulEquiv, AddEquiv, RingEquiv, MulAut, AddAut, RingAut -/ -- guard against import creep -assert_not_exists Field -assert_not_exists Fintype +assert_not_exists Field Fintype variable {F α β R S S' : Type*} diff --git a/Mathlib/Algebra/Ring/Hom/Defs.lean b/Mathlib/Algebra/Ring/Hom/Defs.lean index 6822a2bebdc3b..8374912c2e3ef 100644 --- a/Mathlib/Algebra/Ring/Hom/Defs.lean +++ b/Mathlib/Algebra/Ring/Hom/Defs.lean @@ -42,10 +42,7 @@ groups, we use the same structure `RingHom a β`, a.k.a. `α →+* β`, for both `RingHom`, `SemiringHom` -/ -assert_not_exists Function.Injective.mulZeroClass -assert_not_exists semigroupDvd -assert_not_exists Units.map -assert_not_exists Set.range +assert_not_exists Function.Injective.mulZeroClass semigroupDvd Units.map Set.range open Function diff --git a/Mathlib/Algebra/Ring/Int/Defs.lean b/Mathlib/Algebra/Ring/Int/Defs.lean index 2d8404b75fca8..cde4fc1192067 100644 --- a/Mathlib/Algebra/Ring/Int/Defs.lean +++ b/Mathlib/Algebra/Ring/Int/Defs.lean @@ -17,8 +17,7 @@ This file contains the commutative ring instance on `ℤ`. See note [foundational algebra order theory]. -/ -assert_not_exists DenselyOrdered -assert_not_exists Set.Subsingleton +assert_not_exists DenselyOrdered Set.Subsingleton namespace Int diff --git a/Mathlib/Algebra/Ring/Int/Parity.lean b/Mathlib/Algebra/Ring/Int/Parity.lean index d7422545b1867..95909efda8ec2 100644 --- a/Mathlib/Algebra/Ring/Int/Parity.lean +++ b/Mathlib/Algebra/Ring/Int/Parity.lean @@ -13,8 +13,7 @@ import Mathlib.Algebra.Group.Int.Even See note [foundational algebra order theory]. -/ -assert_not_exists DenselyOrdered -assert_not_exists Set.Subsingleton +assert_not_exists DenselyOrdered Set.Subsingleton namespace Int diff --git a/Mathlib/Algebra/Ring/Int/Units.lean b/Mathlib/Algebra/Ring/Int/Units.lean index 99394628b4234..83a91216937f2 100644 --- a/Mathlib/Algebra/Ring/Int/Units.lean +++ b/Mathlib/Algebra/Ring/Int/Units.lean @@ -19,8 +19,7 @@ This file contains lemmas on the units of `ℤ`. See note [foundational algebra order theory]. -/ -assert_not_exists DenselyOrdered -assert_not_exists Set.Subsingleton +assert_not_exists DenselyOrdered Set.Subsingleton namespace Int diff --git a/Mathlib/Algebra/Ring/Parity.lean b/Mathlib/Algebra/Ring/Parity.lean index 91d436c897684..0883314e27689 100644 --- a/Mathlib/Algebra/Ring/Parity.lean +++ b/Mathlib/Algebra/Ring/Parity.lean @@ -27,8 +27,7 @@ to `Algebra.Group.Even`. `Algebra.Group.Even` for the definition of even elements. -/ -assert_not_exists DenselyOrdered -assert_not_exists OrderedRing +assert_not_exists DenselyOrdered OrderedRing open MulOpposite diff --git a/Mathlib/Algebra/Ring/Rat.lean b/Mathlib/Algebra/Ring/Rat.lean index 41eedc7f8b08d..26cd561224df0 100644 --- a/Mathlib/Algebra/Ring/Rat.lean +++ b/Mathlib/Algebra/Ring/Rat.lean @@ -17,11 +17,7 @@ This file contains the commutative ring instance on the rational numbers. See note [foundational algebra order theory]. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists Field -assert_not_exists PNat -assert_not_exists Nat.dvd_mul -assert_not_exists IsDomain.toCancelMonoidWithZero +assert_not_exists OrderedCommMonoid Field PNat Nat.dvd_mul IsDomain.toCancelMonoidWithZero namespace Rat diff --git a/Mathlib/Algebra/Star/Basic.lean b/Mathlib/Algebra/Star/Basic.lean index 26ed998ae7869..674f376ed71eb 100644 --- a/Mathlib/Algebra/Star/Basic.lean +++ b/Mathlib/Algebra/Star/Basic.lean @@ -30,9 +30,7 @@ Our star rings are actually star non-unital, non-associative, semirings, but of `star_neg : star (-r) = - star r` when the underlying semiring is a ring. -/ -assert_not_exists Finset -assert_not_exists Subgroup -assert_not_exists Rat.instField +assert_not_exists Finset Subgroup Rat.instField universe u v w diff --git a/Mathlib/Analysis/Complex/RealDeriv.lean b/Mathlib/Analysis/Complex/RealDeriv.lean index 92f1c438dbbbb..3d214cf595f51 100644 --- a/Mathlib/Analysis/Complex/RealDeriv.lean +++ b/Mathlib/Analysis/Complex/RealDeriv.lean @@ -14,8 +14,7 @@ then its restriction to `ℝ` is differentiable over `ℝ`, with derivative the complex derivative. -/ -assert_not_exists IsConformalMap -assert_not_exists Conformal +assert_not_exists IsConformalMap Conformal section RealDerivOfComplex diff --git a/Mathlib/Analysis/Convex/Cone/Basic.lean b/Mathlib/Analysis/Convex/Cone/Basic.lean index e85e4d156f432..5c55ea258c2f8 100644 --- a/Mathlib/Analysis/Convex/Cone/Basic.lean +++ b/Mathlib/Analysis/Convex/Cone/Basic.lean @@ -37,9 +37,7 @@ While `Convex 𝕜` is a predicate on sets, `ConvexCone 𝕜 E` is a bundled con -/ -assert_not_exists NormedSpace -assert_not_exists Real -assert_not_exists Cardinal +assert_not_exists NormedSpace Real Cardinal open Set LinearMap Pointwise diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index 9d8514ced1889..0bc9524cf8635 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -27,15 +27,9 @@ ring/field are given in: -/ -- Guard against import creep. -assert_not_exists AddChar -assert_not_exists comap_norm_atTop -assert_not_exists DilationEquiv -assert_not_exists Finset.sup_mul_le_mul_sup_of_nonneg -assert_not_exists IsOfFinOrder -assert_not_exists Isometry.norm_map_of_map_one -assert_not_exists NNReal.isOpen_Ico_zero -assert_not_exists Rat.norm_cast_real -assert_not_exists RestrictScalars +assert_not_exists AddChar comap_norm_atTop DilationEquiv Finset.sup_mul_le_mul_sup_of_nonneg + IsOfFinOrder Isometry.norm_map_of_map_one NNReal.isOpen_Ico_zero Rat.norm_cast_real + RestrictScalars variable {α : Type*} {β : Type*} {ι : Type*} diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean b/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean index 8274b1696a1db..1d7c6fbb9d6cd 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/LogDeriv.lean @@ -13,8 +13,7 @@ import Mathlib.Analysis.SpecialFunctions.ExpDeriv -/ -assert_not_exists IsConformalMap -assert_not_exists Conformal +assert_not_exists IsConformalMap Conformal open Set Filter diff --git a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean index 9fb53baf40655..d13b1341c8a8d 100644 --- a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean @@ -19,8 +19,7 @@ In this file we prove that `Complex.exp` and `Real.exp` are analytic functions. exp, derivative -/ -assert_not_exists IsConformalMap -assert_not_exists Conformal +assert_not_exists IsConformalMap Conformal noncomputable section diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index ebeea719fe2dc..fb05317c1b822 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -34,8 +34,7 @@ related work. -/ -assert_not_exists CategoryTheory.CommSq -assert_not_exists CategoryTheory.Adjunction +assert_not_exists CategoryTheory.CommSq CategoryTheory.Adjunction universe w w' v v' v'' u u' u'' diff --git a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean index 494fe94ffdb41..0927649572779 100644 --- a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean +++ b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean @@ -27,8 +27,7 @@ colimit (over `K`) of the limits (over `J`) with the limit of the colimits is an -/ -- Various pieces of algebra that have previously been spuriously imported here: -assert_not_exists map_ne_zero -assert_not_exists Field +assert_not_exists map_ne_zero Field -- TODO: We should morally be able to strengthen this to `assert_not_exists GroupWithZero`, but -- finiteness currently relies on more algebra than it needs. diff --git a/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean b/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean index 2dd42b91269fb..b674715d5be5b 100644 --- a/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean +++ b/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean @@ -42,8 +42,7 @@ integer points on that sphere and map them onto `ℕ` in a way that preserves ar 3AP-free, Salem-Spencer, Behrend construction, arithmetic progression, sphere, strictly convex -/ -assert_not_exists IsConformalMap -assert_not_exists Conformal +assert_not_exists IsConformalMap Conformal open Nat hiding log open Finset Metric Real diff --git a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean index b0011c6fb5bbb..cd948718c6bfb 100644 --- a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean +++ b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean @@ -43,8 +43,7 @@ the size of the biggest 3AP-free subset of `{0, ..., n - 1}`. 3AP-free, Salem-Spencer, Roth, arithmetic progression, average, three-free -/ -assert_not_exists Ideal -assert_not_exists TwoSidedIdeal +assert_not_exists Ideal TwoSidedIdeal open Finset Function open scoped Pointwise diff --git a/Mathlib/Combinatorics/Additive/Corner/Defs.lean b/Mathlib/Combinatorics/Additive/Corner/Defs.lean index 3a5f751d136c7..c26f7248fb7f6 100644 --- a/Mathlib/Combinatorics/Additive/Corner/Defs.lean +++ b/Mathlib/Combinatorics/Additive/Corner/Defs.lean @@ -17,8 +17,7 @@ property of being corner-free. * [Wikipedia, *Corners theorem*](https://en.wikipedia.org/wiki/Corners_theorem) -/ -assert_not_exists Ideal -assert_not_exists TwoSidedIdeal +assert_not_exists Ideal TwoSidedIdeal open Set diff --git a/Mathlib/Combinatorics/Additive/FreimanHom.lean b/Mathlib/Combinatorics/Additive/FreimanHom.lean index d01782751e401..e602f4e2af960 100644 --- a/Mathlib/Combinatorics/Additive/FreimanHom.lean +++ b/Mathlib/Combinatorics/Additive/FreimanHom.lean @@ -60,8 +60,7 @@ an `AddMonoid`/`Monoid` instead of the `AddMonoid`/`Monoid` itself. * Affine maps are Freiman homs. -/ -assert_not_exists Ideal -assert_not_exists TwoSidedIdeal +assert_not_exists Ideal TwoSidedIdeal open Multiset Set open scoped Pointwise diff --git a/Mathlib/Data/Complex/Basic.lean b/Mathlib/Data/Complex/Basic.lean index bae81b9aa2c13..2ff347eef5e78 100644 --- a/Mathlib/Data/Complex/Basic.lean +++ b/Mathlib/Data/Complex/Basic.lean @@ -18,8 +18,7 @@ of characteristic zero. The result that the complex numbers are algebraically cl `FieldTheory.AlgebraicClosure`. -/ -assert_not_exists Multiset -assert_not_exists Algebra +assert_not_exists Multiset Algebra open Set Function diff --git a/Mathlib/Data/DFinsupp/Defs.lean b/Mathlib/Data/DFinsupp/Defs.lean index 30ed70de9b564..a8b854e30a101 100644 --- a/Mathlib/Data/DFinsupp/Defs.lean +++ b/Mathlib/Data/DFinsupp/Defs.lean @@ -38,8 +38,7 @@ the `Add` instance as noncomputable. This design difference is independent of th definitions, or introduce two more definitions for the other combinations of decisions. -/ -assert_not_exists Finset.prod -assert_not_exists Submonoid +assert_not_exists Finset.prod Submonoid universe u u₁ u₂ v v₁ v₂ v₃ w x y l diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 148cf433376f6..23ac84d65da1f 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -67,9 +67,8 @@ This file expands on the development in the core library. by `i ↦ n-(i+1)` -/ -assert_not_exists Monoid -assert_not_exists Fintype -universe u v + +assert_not_exists Monoid Fintype open Fin Nat Function diff --git a/Mathlib/Data/Finite/Defs.lean b/Mathlib/Data/Finite/Defs.lean index da0ccaeee91f3..562100f6b0530 100644 --- a/Mathlib/Data/Finite/Defs.lean +++ b/Mathlib/Data/Finite/Defs.lean @@ -58,9 +58,7 @@ instances since they do not compute anything. finite, fintype, finite sets -/ -assert_not_exists Finset -assert_not_exists MonoidWithZero -assert_not_exists OrderedRing +assert_not_exists Finset MonoidWithZero OrderedRing universe u v diff --git a/Mathlib/Data/Finite/Prod.lean b/Mathlib/Data/Finite/Prod.lean index 9d577868e5da9..4e065cb58e320 100644 --- a/Mathlib/Data/Finite/Prod.lean +++ b/Mathlib/Data/Finite/Prod.lean @@ -11,8 +11,7 @@ import Mathlib.Data.Fintype.Vector # Finiteness of products -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero variable {α β : Type*} diff --git a/Mathlib/Data/Finset/Attach.lean b/Mathlib/Data/Finset/Attach.lean index 46b568c43cd73..0f4c8de841075 100644 --- a/Mathlib/Data/Finset/Attach.lean +++ b/Mathlib/Data/Finset/Attach.lean @@ -21,12 +21,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index 30dcc372ee2cd..84a285a152f6a 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -43,12 +43,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists Monoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice Monoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index 8c8e3dba2f006..5395494d7237a 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -24,8 +24,7 @@ This defines the cardinality of a `Finset` and provides induction principles for * `Finset.Nonempty.strong_induction` -/ -assert_not_exists MonoidWithZero -assert_not_exists OrderedCommMonoid +assert_not_exists MonoidWithZero OrderedCommMonoid open Function Multiset Nat diff --git a/Mathlib/Data/Finset/Dedup.lean b/Mathlib/Data/Finset/Dedup.lean index 90fb4cfe8900b..9d30a3a3aa25d 100644 --- a/Mathlib/Data/Finset/Dedup.lean +++ b/Mathlib/Data/Finset/Dedup.lean @@ -19,12 +19,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Defs.lean b/Mathlib/Data/Finset/Defs.lean index e63e94579aaed..93ee27d0d49a1 100644 --- a/Mathlib/Data/Finset/Defs.lean +++ b/Mathlib/Data/Finset/Defs.lean @@ -56,14 +56,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists DirectedSystem - -assert_not_exists CompleteLattice - -assert_not_exists Monoid +assert_not_exists List.sublistsLen Multiset.powerset DirectedSystem CompleteLattice Monoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Disjoint.lean b/Mathlib/Data/Finset/Disjoint.lean index 4ef7defc5e0a6..2de51fa4f6def 100644 --- a/Mathlib/Data/Finset/Disjoint.lean +++ b/Mathlib/Data/Finset/Disjoint.lean @@ -22,12 +22,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists Monoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice Monoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Empty.lean b/Mathlib/Data/Finset/Empty.lean index 60a6034dfb73c..428fbe175f4b3 100644 --- a/Mathlib/Data/Finset/Empty.lean +++ b/Mathlib/Data/Finset/Empty.lean @@ -22,12 +22,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Erase.lean b/Mathlib/Data/Finset/Erase.lean index 235955330953f..4fc6d16d8841b 100644 --- a/Mathlib/Data/Finset/Erase.lean +++ b/Mathlib/Data/Finset/Erase.lean @@ -20,12 +20,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Filter.lean b/Mathlib/Data/Finset/Filter.lean index 746efb1723405..ffd3e96f0873e 100644 --- a/Mathlib/Data/Finset/Filter.lean +++ b/Mathlib/Data/Finset/Filter.lean @@ -21,12 +21,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Fold.lean b/Mathlib/Data/Finset/Fold.lean index fb9ed13966a4d..3fc9eb249cccd 100644 --- a/Mathlib/Data/Finset/Fold.lean +++ b/Mathlib/Data/Finset/Fold.lean @@ -10,8 +10,7 @@ import Mathlib.Data.Multiset.Fold # The fold operation for a commutative associative operation over a finset. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidWithZero +assert_not_exists OrderedCommMonoid MonoidWithZero namespace Finset diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index c418510df9688..27d7c37b2b821 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -31,9 +31,7 @@ choosing between `insert` and `Finset.cons`, or between `Finset.union` and `Fins Move the material about `Finset.range` so that the `Mathlib.Algebra.Group.Embedding` import can be removed. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidWithZero -assert_not_exists MulAction +assert_not_exists OrderedCommMonoid MonoidWithZero MulAction variable {α β γ : Type*} diff --git a/Mathlib/Data/Finset/Insert.lean b/Mathlib/Data/Finset/Insert.lean index 8d5f792fbf340..3c72a9bb66c17 100644 --- a/Mathlib/Data/Finset/Insert.lean +++ b/Mathlib/Data/Finset/Insert.lean @@ -32,12 +32,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Lattice/Basic.lean b/Mathlib/Data/Finset/Lattice/Basic.lean index f3cc10838069e..5f03a7c728d3f 100644 --- a/Mathlib/Data/Finset/Lattice/Basic.lean +++ b/Mathlib/Data/Finset/Lattice/Basic.lean @@ -39,12 +39,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Lattice/Fold.lean b/Mathlib/Data/Finset/Lattice/Fold.lean index 21cfa817f5ec8..ff436a9d458d3 100644 --- a/Mathlib/Data/Finset/Lattice/Fold.lean +++ b/Mathlib/Data/Finset/Lattice/Fold.lean @@ -22,8 +22,7 @@ See also `Mathlib/Order/CompleteLattice/Finset.lean`, which is instead concerned lattice or set operations behave when indexed by a finset. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidWithZero +assert_not_exists OrderedCommMonoid MonoidWithZero open Function Multiset OrderDual diff --git a/Mathlib/Data/Finset/Lattice/Lemmas.lean b/Mathlib/Data/Finset/Lattice/Lemmas.lean index 32963dd45c201..984c8a6634d29 100644 --- a/Mathlib/Data/Finset/Lattice/Lemmas.lean +++ b/Mathlib/Data/Finset/Lattice/Lemmas.lean @@ -20,12 +20,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists Monoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice Monoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Max.lean b/Mathlib/Data/Finset/Max.lean index dcd6e6ea7b3a8..b75b07e8b15e3 100644 --- a/Mathlib/Data/Finset/Max.lean +++ b/Mathlib/Data/Finset/Max.lean @@ -9,8 +9,7 @@ import Mathlib.Data.Finset.Lattice.Fold # Maximum and minimum of finite sets -/ -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidWithZero +assert_not_exists OrderedCommMonoid MonoidWithZero open Function Multiset OrderDual diff --git a/Mathlib/Data/Finset/Range.lean b/Mathlib/Data/Finset/Range.lean index 66a136dfa52cc..dbf606c086f59 100644 --- a/Mathlib/Data/Finset/Range.lean +++ b/Mathlib/Data/Finset/Range.lean @@ -25,12 +25,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/SDiff.lean b/Mathlib/Data/Finset/SDiff.lean index 76d887b4bdc7a..8e0c211942a4a 100644 --- a/Mathlib/Data/Finset/SDiff.lean +++ b/Mathlib/Data/Finset/SDiff.lean @@ -21,12 +21,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice - -assert_not_exists OrderedCommMonoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice OrderedCommMonoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/SymmDiff.lean b/Mathlib/Data/Finset/SymmDiff.lean index d60f613afe82e..919628e7d279c 100644 --- a/Mathlib/Data/Finset/SymmDiff.lean +++ b/Mathlib/Data/Finset/SymmDiff.lean @@ -19,11 +19,7 @@ finite sets, finset -- Assert that we define `Finset` without the material on `List.sublists`. -- Note that we cannot use `List.sublists` itself as that is defined very early. -assert_not_exists List.sublistsLen -assert_not_exists Multiset.powerset - -assert_not_exists CompleteLattice -assert_not_exists Monoid +assert_not_exists List.sublistsLen Multiset.powerset CompleteLattice Monoid open Multiset Subtype Function diff --git a/Mathlib/Data/Finset/Union.lean b/Mathlib/Data/Finset/Union.lean index 2aec959da13bf..42efbe5a93ae2 100644 --- a/Mathlib/Data/Finset/Union.lean +++ b/Mathlib/Data/Finset/Union.lean @@ -26,8 +26,7 @@ This file defines the union of a family `t : α → Finset β` of finsets bounde Remove `Finset.biUnion` in favour of `Finset.sup`. -/ -assert_not_exists MonoidWithZero -assert_not_exists MulAction +assert_not_exists MonoidWithZero MulAction variable {α β γ : Type*} {s s₁ s₂ : Finset α} {t t₁ t₂ : α → Finset β} diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index 34bbc0278f356..88ef9e29bbfa2 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -39,8 +39,7 @@ Types which have a surjection from/an injection to a `Fintype` are themselves fi See `Fintype.ofInjective` and `Fintype.ofSurjective`. -/ -assert_not_exists MonoidWithZero -assert_not_exists MulAction +assert_not_exists MonoidWithZero MulAction open Function diff --git a/Mathlib/Data/Fintype/Card.lean b/Mathlib/Data/Fintype/Card.lean index eaa7a6616ea92..3f87cfbea4fec 100644 --- a/Mathlib/Data/Fintype/Card.lean +++ b/Mathlib/Data/Fintype/Card.lean @@ -43,8 +43,7 @@ We provide `Infinite` instances for -/ -assert_not_exists MonoidWithZero -assert_not_exists MulAction +assert_not_exists MonoidWithZero MulAction open Function diff --git a/Mathlib/Data/Fintype/Option.lean b/Mathlib/Data/Fintype/Option.lean index 5bb9fafa8f916..3eacb0ff301c0 100644 --- a/Mathlib/Data/Fintype/Option.lean +++ b/Mathlib/Data/Fintype/Option.lean @@ -10,8 +10,7 @@ import Mathlib.Data.Finset.Option # fintype instances for option -/ -assert_not_exists MonoidWithZero -assert_not_exists MulAction +assert_not_exists MonoidWithZero MulAction open Function diff --git a/Mathlib/Data/Fintype/Pi.lean b/Mathlib/Data/Fintype/Pi.lean index 2d19a52f707a6..3ac74f7e5b949 100644 --- a/Mathlib/Data/Fintype/Pi.lean +++ b/Mathlib/Data/Fintype/Pi.lean @@ -12,8 +12,7 @@ import Mathlib.Data.Set.Finite.Basic # Fintype instances for pi types -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero open Finset Function diff --git a/Mathlib/Data/Int/Cast/Pi.lean b/Mathlib/Data/Int/Cast/Pi.lean index cfdb7b2de7b54..654d33c17c3f9 100644 --- a/Mathlib/Data/Int/Cast/Pi.lean +++ b/Mathlib/Data/Int/Cast/Pi.lean @@ -18,8 +18,7 @@ This file provides a (pointwise) cast from `ℤ` to function types. * `Pi.instIntCast`: map `n : ℤ` to the constant function `n : ∀ i, π i` -/ -assert_not_exists OrderedCommMonoid -assert_not_exists RingHom +assert_not_exists OrderedCommMonoid RingHom namespace Pi diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 6b908db84ff95..2f06384471cd1 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -18,10 +18,7 @@ import Mathlib.Tactic.Common # Basic properties of lists -/ -assert_not_exists Set.range -assert_not_exists GroupWithZero -assert_not_exists Ring -assert_not_exists Lattice +assert_not_exists Set.range GroupWithZero Ring Lattice open Function diff --git a/Mathlib/Data/List/Count.lean b/Mathlib/Data/List/Count.lean index c9608f6a4c96f..ff77b8257b8d5 100644 --- a/Mathlib/Data/List/Count.lean +++ b/Mathlib/Data/List/Count.lean @@ -13,8 +13,7 @@ This file proves basic properties of `List.countP` and `List.count`, which count elements of a list satisfying a predicate and equal to a given element respectively. -/ -assert_not_exists Monoid -assert_not_exists Set.range +assert_not_exists Monoid Set.range open Nat diff --git a/Mathlib/Data/Matrix/Defs.lean b/Mathlib/Data/Matrix/Defs.lean index cfe899da9503e..cee907c0593df 100644 --- a/Mathlib/Data/Matrix/Defs.lean +++ b/Mathlib/Data/Matrix/Defs.lean @@ -38,8 +38,7 @@ form `fun i j ↦ _` or even `(fun i j ↦ _ : Matrix m n α)`, as these are not as having the right type. Instead, `Matrix.of` should be used. -/ -assert_not_exists Algebra -assert_not_exists Star +assert_not_exists Algebra Star universe u u' v w diff --git a/Mathlib/Data/Matrix/Diagonal.lean b/Mathlib/Data/Matrix/Diagonal.lean index 89efdc3f4b838..3f6042398a5d2 100644 --- a/Mathlib/Data/Matrix/Diagonal.lean +++ b/Mathlib/Data/Matrix/Diagonal.lean @@ -19,8 +19,7 @@ This file defines diagonal matrices and the `AddCommMonoidWithOne` structure on * `Matrix.instAddCommMonoidWithOne`: matrices are an additive commutative monoid with one -/ -assert_not_exists Algebra -assert_not_exists Star +assert_not_exists Algebra Star universe u u' v w diff --git a/Mathlib/Data/Matrix/Mul.lean b/Mathlib/Data/Matrix/Mul.lean index eeffd7a456162..4f7140b712651 100644 --- a/Mathlib/Data/Matrix/Mul.lean +++ b/Mathlib/Data/Matrix/Mul.lean @@ -46,8 +46,7 @@ Under various conditions, multiplication of infinite matrices makes sense. These have not yet been implemented. -/ -assert_not_exists Algebra -assert_not_exists Star +assert_not_exists Algebra Star universe u u' v w diff --git a/Mathlib/Data/Multiset/Antidiagonal.lean b/Mathlib/Data/Multiset/Antidiagonal.lean index dea72ad65efc7..8fe6d50f5da60 100644 --- a/Mathlib/Data/Multiset/Antidiagonal.lean +++ b/Mathlib/Data/Multiset/Antidiagonal.lean @@ -12,8 +12,7 @@ The antidiagonal of a multiset `s` consists of all pairs `(t₁, t₂)` such that `t₁ + t₂ = s`. These pairs are counted with multiplicities. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists Ring +assert_not_exists OrderedCommMonoid Ring universe u diff --git a/Mathlib/Data/Multiset/Bind.lean b/Mathlib/Data/Multiset/Bind.lean index 766b7f70ea703..5cbe5c20afdd6 100644 --- a/Mathlib/Data/Multiset/Bind.lean +++ b/Mathlib/Data/Multiset/Bind.lean @@ -19,8 +19,7 @@ This file defines a few basic operations on `Multiset`, notably the monadic bind * `Multiset.sigma`: Disjoint sum of multisets in a sigma type. -/ -assert_not_exists MonoidWithZero -assert_not_exists MulAction +assert_not_exists MonoidWithZero MulAction universe v diff --git a/Mathlib/Data/Nat/Cast/Basic.lean b/Mathlib/Data/Nat/Cast/Basic.lean index 4d4457e98263a..d190cb22f4599 100644 --- a/Mathlib/Data/Nat/Cast/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Basic.lean @@ -21,11 +21,8 @@ the natural numbers into an additive monoid with a one (`Nat.cast`). * `castRingHom`: `cast` bundled as a `RingHom`. -/ -assert_not_exists OrderedCommGroup -assert_not_exists Commute.zero_right -assert_not_exists Commute.add_right -assert_not_exists abs_eq_max_neg -assert_not_exists NeZero.natCast_ne +assert_not_exists OrderedCommGroup Commute.zero_right Commute.add_right abs_eq_max_neg + NeZero.natCast_ne -- TODO: `MulOpposite.op_natCast` was not intended to be imported -- assert_not_exists MulOpposite.op_natCast diff --git a/Mathlib/Data/Nat/ModEq.lean b/Mathlib/Data/Nat/ModEq.lean index ebe5c44a758a4..b5e250857f4a5 100644 --- a/Mathlib/Data/Nat/ModEq.lean +++ b/Mathlib/Data/Nat/ModEq.lean @@ -23,8 +23,7 @@ and proves basic properties about it such as the Chinese Remainder Theorem ModEq, congruence, mod, MOD, modulo -/ -assert_not_exists OrderedAddCommMonoid -assert_not_exists Function.support +assert_not_exists OrderedAddCommMonoid Function.support namespace Nat diff --git a/Mathlib/Data/Nat/Totient.lean b/Mathlib/Data/Nat/Totient.lean index 6ee40d3c7761c..57626c563de64 100644 --- a/Mathlib/Data/Nat/Totient.lean +++ b/Mathlib/Data/Nat/Totient.lean @@ -20,8 +20,7 @@ We prove the divisor sum formula, namely that `n` equals `φ` summed over the di `totient_prime_pow`. -/ -assert_not_exists Algebra -assert_not_exists LinearMap +assert_not_exists Algebra LinearMap open Finset diff --git a/Mathlib/Data/Rat/Cardinal.lean b/Mathlib/Data/Rat/Cardinal.lean index 36332a7d1d4b5..b31cb4038ca5a 100644 --- a/Mathlib/Data/Rat/Cardinal.lean +++ b/Mathlib/Data/Rat/Cardinal.lean @@ -14,8 +14,7 @@ import Mathlib.SetTheory.Cardinal.Basic This file proves that the Cardinality of ℚ is ℵ₀ -/ -assert_not_exists Module -assert_not_exists Field +assert_not_exists Module Field open Cardinal diff --git a/Mathlib/Data/Rat/Defs.lean b/Mathlib/Data/Rat/Defs.lean index f848e1c3e14a3..59d83bde6c20c 100644 --- a/Mathlib/Data/Rat/Defs.lean +++ b/Mathlib/Data/Rat/Defs.lean @@ -31,10 +31,7 @@ The definition of the field structure on `ℚ` will be done in `Mathlib.Data.Rat -- TODO: If `Inv` was defined earlier than `Algebra.Group.Defs`, we could have -- assert_not_exists Monoid -assert_not_exists MonoidWithZero -assert_not_exists Lattice -assert_not_exists PNat -assert_not_exists Nat.dvd_mul +assert_not_exists MonoidWithZero Lattice PNat Nat.dvd_mul open Function diff --git a/Mathlib/Data/Rat/Denumerable.lean b/Mathlib/Data/Rat/Denumerable.lean index 116e03e72a7dd..d8b3c72dc080b 100644 --- a/Mathlib/Data/Rat/Denumerable.lean +++ b/Mathlib/Data/Rat/Denumerable.lean @@ -16,8 +16,7 @@ This file proves that ℚ is denumerable. The fact that ℚ has cardinality ℵ₀ is proved in `Mathlib.Data.Rat.Cardinal` -/ -assert_not_exists Module -assert_not_exists Field +assert_not_exists Module Field namespace Rat diff --git a/Mathlib/Data/Real/Basic.lean b/Mathlib/Data/Real/Basic.lean index b16bdaec3d484..65b39b8a38b14 100644 --- a/Mathlib/Data/Real/Basic.lean +++ b/Mathlib/Data/Real/Basic.lean @@ -23,10 +23,7 @@ The fact that the real numbers are a (trivial) *-ring has similarly been deferre -/ -assert_not_exists Finset -assert_not_exists Module -assert_not_exists Submonoid -assert_not_exists FloorRing +assert_not_exists Finset Module Submonoid FloorRing /-- The type `ℝ` of real numbers constructed as equivalence classes of Cauchy sequences of rational numbers. -/ diff --git a/Mathlib/Data/Set/Finite/Basic.lean b/Mathlib/Data/Set/Finite/Basic.lean index bddaef6f06011..96e8957b578b3 100644 --- a/Mathlib/Data/Set/Finite/Basic.lean +++ b/Mathlib/Data/Set/Finite/Basic.lean @@ -38,8 +38,7 @@ instances since they do not compute anything. finite sets -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero open Set Function open scoped symmDiff diff --git a/Mathlib/Data/Set/Finite/Lattice.lean b/Mathlib/Data/Set/Finite/Lattice.lean index 0f87a472988fd..4469adaeee8ee 100644 --- a/Mathlib/Data/Set/Finite/Lattice.lean +++ b/Mathlib/Data/Set/Finite/Lattice.lean @@ -20,8 +20,7 @@ and a `Set.Finite` constructor. finite sets -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero open Set Function diff --git a/Mathlib/Data/Set/Finite/Lemmas.lean b/Mathlib/Data/Set/Finite/Lemmas.lean index 29701fca18502..840b8850b14b7 100644 --- a/Mathlib/Data/Set/Finite/Lemmas.lean +++ b/Mathlib/Data/Set/Finite/Lemmas.lean @@ -20,8 +20,7 @@ If your proof has as *result* `Set.Finite`, then it should go to a more specific finite sets -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero open Set Function diff --git a/Mathlib/Data/Set/Finite/List.lean b/Mathlib/Data/Set/Finite/List.lean index 2b630c4dfa412..f2b00de16be8c 100644 --- a/Mathlib/Data/Set/Finite/List.lean +++ b/Mathlib/Data/Set/Finite/List.lean @@ -18,8 +18,7 @@ import Mathlib.Data.Finite.Vector finite sets -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero namespace List variable (α : Type*) [Finite α] (n : ℕ) diff --git a/Mathlib/Data/Set/Finite/Monad.lean b/Mathlib/Data/Set/Finite/Monad.lean index eb54e4a5396ba..b1b50cf7dcc71 100644 --- a/Mathlib/Data/Set/Finite/Monad.lean +++ b/Mathlib/Data/Set/Finite/Monad.lean @@ -15,8 +15,7 @@ import Mathlib.Data.Set.Functor finite sets -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero open Set Function diff --git a/Mathlib/Data/Set/Finite/Powerset.lean b/Mathlib/Data/Set/Finite/Powerset.lean index 55f30e0cb51b6..39f7df8b2704d 100644 --- a/Mathlib/Data/Set/Finite/Powerset.lean +++ b/Mathlib/Data/Set/Finite/Powerset.lean @@ -19,8 +19,7 @@ and a `Set.Finite` constructor. finite sets -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero open Set Function diff --git a/Mathlib/Data/Set/Finite/Range.lean b/Mathlib/Data/Set/Finite/Range.lean index d1f22cc150285..7a5dd0450e466 100644 --- a/Mathlib/Data/Set/Finite/Range.lean +++ b/Mathlib/Data/Set/Finite/Range.lean @@ -19,8 +19,7 @@ and a `Set.Finite` constructor. finite sets -/ -assert_not_exists OrderedRing -assert_not_exists MonoidWithZero +assert_not_exists OrderedRing MonoidWithZero open Set Function diff --git a/Mathlib/Data/ZMod/Basic.lean b/Mathlib/Data/ZMod/Basic.lean index dd6023f9ebd14..fec363551b146 100644 --- a/Mathlib/Data/ZMod/Basic.lean +++ b/Mathlib/Data/ZMod/Basic.lean @@ -33,8 +33,7 @@ This is a ring hom if the ring has characteristic dividing `n` -/ -assert_not_exists Submodule -assert_not_exists TwoSidedIdeal +assert_not_exists Submodule TwoSidedIdeal open Function ZMod diff --git a/Mathlib/Data/ZMod/IntUnitsPower.lean b/Mathlib/Data/ZMod/IntUnitsPower.lean index 02b0f8a883a92..878d454335e4f 100644 --- a/Mathlib/Data/ZMod/IntUnitsPower.lean +++ b/Mathlib/Data/ZMod/IntUnitsPower.lean @@ -23,8 +23,7 @@ by using `Module R (Additive M)` in its place, especially since this already has `R = ℕ` and `R = ℤ`. -/ -assert_not_exists Ideal -assert_not_exists TwoSidedIdeal +assert_not_exists Ideal TwoSidedIdeal instance : SMul (ZMod 2) (Additive ℤˣ) where smul z au := .ofMul <| au.toMul ^ z.val diff --git a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Basic.lean b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Basic.lean index 804654e42dff5..1d9a1d75fa816 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Basic.lean @@ -21,9 +21,7 @@ Prove the triangle inequality for the angle. -/ -assert_not_exists HasFDerivAt - -assert_not_exists ConformalAt +assert_not_exists HasFDerivAt ConformalAt noncomputable section diff --git a/Mathlib/GroupTheory/Commutator/Basic.lean b/Mathlib/GroupTheory/Commutator/Basic.lean index 8e4f605d4f565..38ed41f97f06e 100644 --- a/Mathlib/GroupTheory/Commutator/Basic.lean +++ b/Mathlib/GroupTheory/Commutator/Basic.lean @@ -19,8 +19,7 @@ is the subgroup of `G` generated by the commutators `h₁ * h₂ * h₁⁻¹ * h * `⁅H₁, H₂⁆` : the commutator of the subgroups `H₁` and `H₂`. -/ -assert_not_exists Cardinal -assert_not_exists Multiset +assert_not_exists Cardinal Multiset variable {G G' F : Type*} [Group G] [Group G'] [FunLike F G G'] [MonoidHomClass F G G'] variable (f : F) {g₁ g₂ g₃ g : G} diff --git a/Mathlib/GroupTheory/CommutingProbability.lean b/Mathlib/GroupTheory/CommutingProbability.lean index 7d56673295222..5e9481a5ee9dd 100644 --- a/Mathlib/GroupTheory/CommutingProbability.lean +++ b/Mathlib/GroupTheory/CommutingProbability.lean @@ -21,8 +21,7 @@ This file introduces the commuting probability of finite groups. * Neumann's theorem. -/ -assert_not_exists Ideal -assert_not_exists TwoSidedIdeal +assert_not_exists Ideal TwoSidedIdeal noncomputable section diff --git a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean index 0f8373c3bc0db..70d089f4ff23f 100644 --- a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean +++ b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean @@ -73,8 +73,7 @@ localization, monoid localization, quotient monoid, congruence relation, charact commutative monoid, grothendieck group -/ -assert_not_exists MonoidWithZero -assert_not_exists Ring +assert_not_exists MonoidWithZero Ring open Function namespace AddSubmonoid diff --git a/Mathlib/GroupTheory/OreLocalization/Basic.lean b/Mathlib/GroupTheory/OreLocalization/Basic.lean index 74c497348b850..135848a6b63f3 100644 --- a/Mathlib/GroupTheory/OreLocalization/Basic.lean +++ b/Mathlib/GroupTheory/OreLocalization/Basic.lean @@ -30,8 +30,7 @@ localization, Ore, non-commutative -/ -assert_not_exists MonoidWithZero -assert_not_exists Ring +assert_not_exists MonoidWithZero Ring universe u diff --git a/Mathlib/GroupTheory/Subgroup/Center.lean b/Mathlib/GroupTheory/Subgroup/Center.lean index a3733d06b31fb..6dd4dbfa41447 100644 --- a/Mathlib/GroupTheory/Subgroup/Center.lean +++ b/Mathlib/GroupTheory/Subgroup/Center.lean @@ -12,8 +12,7 @@ import Mathlib.GroupTheory.Submonoid.Center -/ -assert_not_exists Multiset -assert_not_exists Ring +assert_not_exists Multiset Ring variable {G : Type*} [Group G] diff --git a/Mathlib/LinearAlgebra/Basis/Defs.lean b/Mathlib/LinearAlgebra/Basis/Defs.lean index 2126dd106d9f1..6360e4a10928f 100644 --- a/Mathlib/LinearAlgebra/Basis/Defs.lean +++ b/Mathlib/LinearAlgebra/Basis/Defs.lean @@ -53,9 +53,7 @@ basis, bases -/ -assert_not_exists LinearMap.pi -assert_not_exists LinearIndependent -assert_not_exists Cardinal +assert_not_exists LinearMap.pi LinearIndependent Cardinal noncomputable section diff --git a/Mathlib/LinearAlgebra/FiniteDimensional.lean b/Mathlib/LinearAlgebra/FiniteDimensional.lean index 1a9987e8e47be..bc444e67a82e0 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional.lean @@ -19,8 +19,7 @@ Definitions and results that require fewer imports are in -/ -assert_not_exists Monoid.exponent -assert_not_exists Module.IsTorsion +assert_not_exists Monoid.exponent Module.IsTorsion universe u v v' diff --git a/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean b/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean index 2074623647f98..5cc12c4593425 100644 --- a/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean +++ b/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean @@ -18,9 +18,7 @@ See also `MeasureTheory.Function.SpecialFunctions.Arctan` and -/ -- Guard against import creep: -assert_not_exists InnerProductSpace -assert_not_exists Real.arctan -assert_not_exists FiniteDimensional.proper +assert_not_exists InnerProductSpace Real.arctan FiniteDimensional.proper noncomputable section diff --git a/Mathlib/Order/CompleteLattice/Finset.lean b/Mathlib/Order/CompleteLattice/Finset.lean index e5891f26b9252..0982d981ba4b3 100644 --- a/Mathlib/Order/CompleteLattice/Finset.lean +++ b/Mathlib/Order/CompleteLattice/Finset.lean @@ -15,8 +15,7 @@ See also `Mathlib/Data/Finset/Lattice.lean`, which is concerned with folding bin operations over a finset. -/ -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidWithZero +assert_not_exists OrderedCommMonoid MonoidWithZero open Function Multiset OrderDual diff --git a/Mathlib/Order/Filter/Basic.lean b/Mathlib/Order/Filter/Basic.lean index 6dd554714e2b1..cc58cdfb1c99c 100644 --- a/Mathlib/Order/Filter/Basic.lean +++ b/Mathlib/Order/Filter/Basic.lean @@ -61,8 +61,7 @@ we do *not* require. This gives `Filter X` better formal properties, in particul `[NeBot f]` in a number of lemmas and definitions. -/ -assert_not_exists OrderedSemiring -assert_not_exists Fintype +assert_not_exists OrderedSemiring Fintype open Function Set Order open scoped symmDiff diff --git a/Mathlib/Order/Interval/Finset/Basic.lean b/Mathlib/Order/Interval/Finset/Basic.lean index ef23dafd228db..4a58782628847 100644 --- a/Mathlib/Order/Interval/Finset/Basic.lean +++ b/Mathlib/Order/Interval/Finset/Basic.lean @@ -32,8 +32,7 @@ https://github.com/leanprover-community/mathlib/pull/14448#discussion_r906109235 for some ideas. -/ -assert_not_exists MonoidWithZero -assert_not_exists Finset.sum +assert_not_exists MonoidWithZero Finset.sum open Function OrderDual diff --git a/Mathlib/RingTheory/Algebraic/Defs.lean b/Mathlib/RingTheory/Algebraic/Defs.lean index 90f80b749d130..ce1c67994ff6e 100644 --- a/Mathlib/RingTheory/Algebraic/Defs.lean +++ b/Mathlib/RingTheory/Algebraic/Defs.lean @@ -26,10 +26,7 @@ An R-algebra is algebraic over R if and only if all its elements are algebraic o * `Subalgebra.isAlgebraic_iff`: a subalgebra is algebraic iff it is algebraic as an algebra. -/ -assert_not_exists IsIntegralClosure -assert_not_exists LinearIndependent -assert_not_exists LocalRing -assert_not_exists MvPolynomial +assert_not_exists IsIntegralClosure LinearIndependent LocalRing MvPolynomial universe u v w open Polynomial diff --git a/Mathlib/RingTheory/Algebraic/Pi.lean b/Mathlib/RingTheory/Algebraic/Pi.lean index c09c0c2414404..9c96ad3c87c64 100644 --- a/Mathlib/RingTheory/Algebraic/Pi.lean +++ b/Mathlib/RingTheory/Algebraic/Pi.lean @@ -11,10 +11,7 @@ import Mathlib.Algebra.Polynomial.AlgebraMap This file defines algebraic functions as the image of the `algebraMap R[X] (R → S)`. -/ -assert_not_exists IsIntegralClosure -assert_not_exists LinearIndependent -assert_not_exists LocalRing -assert_not_exists MvPolynomial +assert_not_exists IsIntegralClosure LinearIndependent LocalRing MvPolynomial open Polynomial diff --git a/Mathlib/RingTheory/Artinian/Module.lean b/Mathlib/RingTheory/Artinian/Module.lean index fb67850d6a654..3c1a202b25650 100644 --- a/Mathlib/RingTheory/Artinian/Module.lean +++ b/Mathlib/RingTheory/Artinian/Module.lean @@ -354,8 +354,7 @@ theorem isArtinian_of_tower (R) {S M} [Semiring R] [Semiring S] [AddCommMonoid M ⟨(Submodule.restrictScalarsEmbedding R S M).wellFounded h.wf⟩ -- See `Mathlib.RingTheory.Artinian.Ring` -assert_not_exists IsLocalization -assert_not_exists LocalRing +assert_not_exists IsLocalization LocalRing /-- A ring is Artinian if it is Artinian as a module over itself. diff --git a/Mathlib/RingTheory/Finiteness/Basic.lean b/Mathlib/RingTheory/Finiteness/Basic.lean index bb1058f07fbc1..ee6353f16e5b1 100644 --- a/Mathlib/RingTheory/Finiteness/Basic.lean +++ b/Mathlib/RingTheory/Finiteness/Basic.lean @@ -15,10 +15,7 @@ This file contains the basic results on `Submodule.FG` and `Module.Finite` that further imports. -/ -assert_not_exists Basis -assert_not_exists Ideal.radical -assert_not_exists Matrix -assert_not_exists Subalgebra +assert_not_exists Basis Ideal.radical Matrix Subalgebra open Function (Surjective) open Finsupp diff --git a/Mathlib/RingTheory/Finiteness/Defs.lean b/Mathlib/RingTheory/Finiteness/Defs.lean index 9c52d2ce2bd80..ecad5530162c4 100644 --- a/Mathlib/RingTheory/Finiteness/Defs.lean +++ b/Mathlib/RingTheory/Finiteness/Defs.lean @@ -25,10 +25,7 @@ In this file we define a notion of finiteness that is common in commutative alge -/ -assert_not_exists Basis -assert_not_exists Ideal.radical -assert_not_exists Matrix -assert_not_exists Subalgebra +assert_not_exists Basis Ideal.radical Matrix Subalgebra open Function (Surjective) open Finsupp diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index 16fd9d345f686..8191b555882cb 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -13,7 +13,7 @@ and `Submodule.annihilator`. -/ assert_not_exists Basis -- See `RingTheory.Ideal.Basis` -assert_not_exists Submodule.hasQuotient -- See `RingTheory.Ideal.Quotient.Operations` + Submodule.hasQuotient -- See `RingTheory.Ideal.Quotient.Operations` universe u v w x diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index 3b8ded22c58e1..9f3fae484fa06 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -15,7 +15,7 @@ import Mathlib.RingTheory.NonUnitalSubsemiring.Basic -/ assert_not_exists Basis -- See `RingTheory.Ideal.Basis` -assert_not_exists Submodule.hasQuotient -- See `RingTheory.Ideal.Quotient.Operations` + Submodule.hasQuotient -- See `RingTheory.Ideal.Quotient.Operations` universe u v w x diff --git a/Mathlib/RingTheory/Localization/Defs.lean b/Mathlib/RingTheory/Localization/Defs.lean index afe729f268f40..f2c81a6a1ef79 100644 --- a/Mathlib/RingTheory/Localization/Defs.lean +++ b/Mathlib/RingTheory/Localization/Defs.lean @@ -80,8 +80,7 @@ localization, ring localization, commutative ring localization, characteristic p commutative ring, field of fractions -/ -assert_not_exists AlgHom -assert_not_exists Ideal +assert_not_exists AlgHom Ideal open Function diff --git a/Mathlib/RingTheory/Noetherian/Defs.lean b/Mathlib/RingTheory/Noetherian/Defs.lean index 2385e93db6919..c0503b4cdbfa9 100644 --- a/Mathlib/RingTheory/Noetherian/Defs.lean +++ b/Mathlib/RingTheory/Noetherian/Defs.lean @@ -47,9 +47,7 @@ Noetherian, noetherian, Noetherian ring, Noetherian module, noetherian ring, noe -/ -assert_not_exists Finsupp.linearCombination -assert_not_exists Matrix -assert_not_exists Pi.basis +assert_not_exists Finsupp.linearCombination Matrix Pi.basis open Set Pointwise diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean index 5a7f8e147aaf6..ba36cf067ec92 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean @@ -19,9 +19,7 @@ import Mathlib.Order.WellFounded `Irreducible` is equivalent to `Prime` -/ -assert_not_exists Field -assert_not_exists Finsupp -assert_not_exists Ideal +assert_not_exists Field Finsupp Ideal variable {α : Type*} diff --git a/Mathlib/SetTheory/Cardinal/Aleph.lean b/Mathlib/SetTheory/Cardinal/Aleph.lean index 9e69e6a4684de..096a7dd858e7b 100644 --- a/Mathlib/SetTheory/Cardinal/Aleph.lean +++ b/Mathlib/SetTheory/Cardinal/Aleph.lean @@ -34,9 +34,7 @@ The following notations are scoped to the `Cardinal` namespace. `Mathlib.SetTheory.Cardinal.Continuum`. -/ -assert_not_exists Module -assert_not_exists Finsupp -assert_not_exists Cardinal.mul_eq_self +assert_not_exists Module Finsupp Cardinal.mul_eq_self noncomputable section diff --git a/Mathlib/SetTheory/Cardinal/Arithmetic.lean b/Mathlib/SetTheory/Cardinal/Arithmetic.lean index 59acdc7b0b398..b3bf57c0f1e5a 100644 --- a/Mathlib/SetTheory/Cardinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Cardinal/Arithmetic.lean @@ -25,8 +25,7 @@ ordinal numbers. This is done within this file. cardinal arithmetic (for infinite cardinals) -/ -assert_not_exists Module -assert_not_exists Finsupp +assert_not_exists Module Finsupp noncomputable section diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 058fe74f9c6cc..130cd19bed83e 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -50,8 +50,7 @@ Some properties of the operations are also used to discuss general tools on ordi Various other basic arithmetic results are given in `Principal.lean` instead. -/ -assert_not_exists Field -assert_not_exists Module +assert_not_exists Field Module noncomputable section diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 7f225262b4727..124a76a047b7c 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -54,8 +54,7 @@ for the empty set by convention. * `ω` is a notation for the first infinite ordinal in the locale `Ordinal`. -/ -assert_not_exists Module -assert_not_exists Field +assert_not_exists Module Field noncomputable section diff --git a/Mathlib/Tactic/Abel.lean b/Mathlib/Tactic/Abel.lean index 0326607cfdb06..9b313d44fdabb 100644 --- a/Mathlib/Tactic/Abel.lean +++ b/Mathlib/Tactic/Abel.lean @@ -15,9 +15,7 @@ Evaluate expressions in the language of additive, commutative monoids and groups -/ -- TODO: assert_not_exists NonUnitalNonAssociativeSemiring -assert_not_exists OrderedAddCommMonoid -assert_not_exists TopologicalSpace -assert_not_exists PseudoMetricSpace +assert_not_exists OrderedAddCommMonoid TopologicalSpace PseudoMetricSpace namespace Mathlib.Tactic.Abel open Lean Elab Meta Tactic Qq diff --git a/Mathlib/Topology/ContinuousMap/Periodic.lean b/Mathlib/Topology/ContinuousMap/Periodic.lean index 4f047d83c3462..c841c62c108a0 100644 --- a/Mathlib/Topology/ContinuousMap/Periodic.lean +++ b/Mathlib/Topology/ContinuousMap/Periodic.lean @@ -10,8 +10,7 @@ import Mathlib.Topology.ContinuousMap.Algebra # Sums of translates of a continuous function is a period continuous function. -/ -assert_not_exists StoneCech -assert_not_exists StarModule +assert_not_exists StoneCech StarModule namespace ContinuousMap diff --git a/Mathlib/Topology/EMetricSpace/Defs.lean b/Mathlib/Topology/EMetricSpace/Defs.lean index b1e16c0662680..e3582222d3610 100644 --- a/Mathlib/Topology/EMetricSpace/Defs.lean +++ b/Mathlib/Topology/EMetricSpace/Defs.lean @@ -25,9 +25,8 @@ theory of `PseudoEMetricSpace`, where we don't require `edist x y = 0 → x = y` to `EMetricSpace` at the end. -/ -assert_not_exists Nat.instLocallyFiniteOrder -assert_not_exists IsUniformEmbedding -assert_not_exists TendstoUniformlyOnFilter + +assert_not_exists Nat.instLocallyFiniteOrder IsUniformEmbedding TendstoUniformlyOnFilter open Filter Set Topology diff --git a/Mathlib/Util/AssertExists.lean b/Mathlib/Util/AssertExists.lean index 386f6f122afc9..dbbbe8363e9f9 100644 --- a/Mathlib/Util/AssertExists.lean +++ b/Mathlib/Util/AssertExists.lean @@ -78,8 +78,8 @@ elab "assert_exists " n:ident : command => do let _ ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo n /-- -`assert_not_exists n` is a user command that asserts that a declaration named `n` *does not exist* -in the current import scope. +`assert_not_exists d₁ d₂ ... dₙ` is a user command that asserts that the declarations named +`d₁ d₂ ... dₙ` *do not exist* in the current import scope. Be careful to use names (e.g. `Rat`) rather than notations (e.g. `ℚ`). @@ -95,28 +95,32 @@ You should *not* delete the `assert_not_exists` statement without careful discus `assert_not_exists` statements should generally live at the top of the file, after the module doc. -/ -elab "assert_not_exists " n:ident : command => do - let decl ← - try liftCoreM <| realizeGlobalConstNoOverloadWithInfo n - catch _ => - Mathlib.AssertNotExist.addDeclEntry true n.getId (← getMainModule) - return +elab "assert_not_exists " ns:ident+ : command => do let env ← getEnv - let c ← mkConstWithLevelParams decl - let msg ← (do - let mut some idx := env.getModuleIdxFor? decl - | pure m!"Declaration {c} is defined in this file." - let mut msg := m!"Declaration {c} is not allowed to be imported by this file.\n\ - It is defined in {env.header.moduleNames[idx.toNat]!}," - for i in [idx.toNat+1:env.header.moduleData.size] do - if env.header.moduleData[i]!.imports.any (·.module == env.header.moduleNames[idx.toNat]!) then - idx := i - msg := msg ++ m!"\n which is imported by {env.header.moduleNames[i]!}," - pure <| msg ++ m!"\n which is imported by this file.") - throw <| .error n m!"{msg}\n\n\ - These invariants are maintained by `assert_not_exists` statements, \ - and exist in order to ensure that \"complicated\" parts of the library \ - are not accidentally introduced as dependencies of \"simple\" parts of the library." + let modNames := env.header.moduleNames + let modData := env.header.moduleData + let modDataSize := modData.size + for n in ns do + let decl ← + try liftCoreM <| realizeGlobalConstNoOverloadWithInfo n + catch _ => + Mathlib.AssertNotExist.addDeclEntry true n.getId (← getMainModule) + continue + let c ← mkConstWithLevelParams decl + let msg ← (do + let mut some idx := env.getModuleIdxFor? decl + | pure m!"Declaration {c} is defined in this file." + let mut msg := m!"Declaration {c} is not allowed to be imported by this file.\n\ + It is defined in {modNames[idx.toNat]!}," + for i in [idx.toNat+1:modDataSize] do + if modData[i]!.imports.any (·.module == modNames[idx.toNat]!) then + idx := i + msg := msg ++ m!"\n which is imported by {modNames[i]!}," + pure <| msg ++ m!"\n which is imported by this file.") + logErrorAt n m!"{msg}\n\n\ + These invariants are maintained by `assert_not_exists` statements, \ + and exist in order to ensure that \"complicated\" parts of the library \ + are not accidentally introduced as dependencies of \"simple\" parts of the library." /-- `assert_not_imported m₁ m₂ ... mₙ` checks that each one of the modules `m₁ m₂ ... mₙ` is not among the transitive imports of the current file. diff --git a/MathlibTest/AssertExists.lean b/MathlibTest/AssertExists.lean index 70f896acd6399..0dfcbc255c34b 100644 --- a/MathlibTest/AssertExists.lean +++ b/MathlibTest/AssertExists.lean @@ -51,3 +51,22 @@ warning: -/ #guard_msgs in #check_assertions! +/-- +error: Declaration commandAssert_not_imported_ is not allowed to be imported by this file. +It is defined in Mathlib.Util.AssertExists, + which is imported by this file. + +These invariants are maintained by `assert_not_exists` statements, and exist in order to ensure that "complicated" parts of the library are not accidentally introduced as dependencies of "simple" parts of the library. +--- +error: Declaration commandAssert_not_exists_ is not allowed to be imported by this file. +It is defined in Mathlib.Util.AssertExists, + which is imported by this file. + +These invariants are maintained by `assert_not_exists` statements, and exist in order to ensure that "complicated" parts of the library are not accidentally introduced as dependencies of "simple" parts of the library. +-/ +#guard_msgs in +assert_not_exists + commandAssert_not_imported_ + Rat + commandAssert_not_exists_ + I_do_not_exist From 75213d9fc7d7f1dcec4a4eba9f5cb6940aa81c46 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Sun, 12 Jan 2025 11:33:56 +0000 Subject: [PATCH 169/681] chore: minor proof cleanup around `tauto` (#20673) While surveying uses of `tauto` in Mathlib, noticed a few proofs that can be cleaned up. Co-authored-by: grunweg --- Archive/Wiedijk100Theorems/BallotProblem.lean | 6 ++---- Mathlib/Algebra/Polynomial/Degree/Lemmas.lean | 5 +---- Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean | 8 +------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Archive/Wiedijk100Theorems/BallotProblem.lean b/Archive/Wiedijk100Theorems/BallotProblem.lean index 9ee2b014457bb..52325bd4a80e5 100644 --- a/Archive/Wiedijk100Theorems/BallotProblem.lean +++ b/Archive/Wiedijk100Theorems/BallotProblem.lean @@ -130,14 +130,12 @@ theorem counted_succ_succ (p q : ℕ) : · rw [List.count_cons, beq_self_eq_true, if_pos rfl, ht₀] · rw [List.count_cons, if_neg, ht₁] norm_num - · rintro x (_ | _) - exacts [Or.inl rfl, ht₂ x (by tauto)] + · simpa · refine ⟨?_, ?_, ?_⟩ · rw [List.count_cons, if_neg, ht₀] norm_num · rw [List.count_cons, beq_self_eq_true, if_pos rfl, ht₁] - · rintro x (_ | _) - exacts [Or.inr rfl, ht₂ x (by tauto)] + · simpa theorem countedSequence_finite : ∀ p q : ℕ, (countedSequence p q).Finite | 0, q => by simp diff --git a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean index e007ecda8074d..2d34e2ee59a96 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean @@ -277,10 +277,7 @@ theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} : rcases eq_or_ne (natDegree p) 0 with h|h · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le] have h2 : p ≠ 0 := by rintro rfl; simp at h - have h3 : degree p ≠ (0 : ℕ) := degree_ne_of_natDegree_ne h - simp_rw [h, or_false, natDegree, WithBot.unbot'_eq_unbot'_iff, degree_map_eq_iff] - simp [h, h2, h3] -- simp doesn't rewrite in the hypothesis for some reason - tauto + simp_all [natDegree, WithBot.unbot'_eq_unbot'_iff] theorem natDegree_pos_of_nextCoeff_ne_zero (h : p.nextCoeff ≠ 0) : 0 < p.natDegree := by rw [nextCoeff] at h diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean index 3f46d4370db46..1e9791803def9 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean @@ -218,13 +218,7 @@ theorem isTheta_cpow_rpow (hl_im : IsBoundedUnder (· ≤ ·) l fun x => |(g x). theorem isTheta_cpow_const_rpow {b : ℂ} (hl : b.re = 0 → b ≠ 0 → ∀ᶠ x in l, f x ≠ 0) : (fun x => f x ^ b) =Θ[l] fun x => abs (f x) ^ b.re := isTheta_cpow_rpow isBoundedUnder_const <| by - -- Porting note: was - -- simpa only [eventually_imp_distrib_right, Ne.def, ← not_frequently, not_imp_not, Imp.swap] - -- using hl - -- but including `Imp.swap` caused an infinite loop - convert hl - rw [eventually_imp_distrib_right] - tauto + simpa only [eventually_imp_distrib_right, not_imp_not, Imp.swap (a := b.re = 0)] using hl end From 3b86394e7e32e0a974e3db1584394ce2243535dc Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Sun, 12 Jan 2025 11:33:58 +0000 Subject: [PATCH 170/681] chore: replace manually ported proof with aesop (#20674) `itauto` wasn't available during the port, so someone pasted in a term proof. Now, either `itauto` or `aesop` handles this fine. I went with `aesop` as we don't actually use `itauto` anywhere in Mathlib currently, and if that's easy to preserve it seems valuable. --- .../Algebra/Order/Ring/Unbundled/Basic.lean | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean index 12714755ede35..49e310e9d0c35 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean @@ -588,24 +588,7 @@ theorem mul_nonneg_of_three [ExistsAddOfLE α] [MulPosStrictMono α] [PosMulStri have or_a := le_total 0 a have or_b := le_total 0 b have or_c := le_total 0 c - -- Porting note used to be by `itauto` from here - exact Or.elim or_c - (fun (h0 : 0 ≤ c) => - Or.elim or_b - (fun (h1 : 0 ≤ b) => - Or.elim or_a (fun (h2 : 0 ≤ a) => Or.inl (Or.inl ⟨h2, h1⟩)) - (fun (_ : a ≤ 0) => Or.inr (Or.inl (Or.inl ⟨h1, h0⟩)))) - (fun (h1 : b ≤ 0) => - Or.elim or_a (fun (h3 : 0 ≤ a) => Or.inr (Or.inr (Or.inl ⟨h0, h3⟩))) - (fun (h3 : a ≤ 0) => Or.inl (Or.inr ⟨h3, h1⟩)))) - (fun (h0 : c ≤ 0) => - Or.elim or_b - (fun (h4 : 0 ≤ b) => - Or.elim or_a (fun (h5 : 0 ≤ a) => Or.inl (Or.inl ⟨h5, h4⟩)) - (fun (h5 : a ≤ 0) => Or.inr (Or.inr (Or.inr ⟨h0, h5⟩)))) - (fun (h4 : b ≤ 0) => - Or.elim or_a (fun (_ : 0 ≤ a) => Or.inr (Or.inl (Or.inr ⟨h4, h0⟩))) - (fun (h6 : a ≤ 0) => Or.inl (Or.inr ⟨h6, h4⟩)))) + aesop lemma mul_nonneg_iff_pos_imp_nonneg [ExistsAddOfLE α] [PosMulStrictMono α] [MulPosStrictMono α] [AddLeftMono α] [AddLeftReflectLE α] : From 9a77cb537a0736b0853ae8784244895f3cf00531 Mon Sep 17 00:00:00 2001 From: James Sundstrom Date: Sun, 12 Jan 2025 11:33:59 +0000 Subject: [PATCH 171/681] doc: fix reference error (#20677) The documentation of Analysis.MeanInequalities referred to the nonexistent MeasureTheory.MeanInequalities rather than MeasureTheory.Integral.MeanInequalities. --- Mathlib/Analysis/MeanInequalities.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Analysis/MeanInequalities.lean b/Mathlib/Analysis/MeanInequalities.lean index ae574c56e55c6..0df7bdf004363 100644 --- a/Mathlib/Analysis/MeanInequalities.lean +++ b/Mathlib/Analysis/MeanInequalities.lean @@ -14,7 +14,7 @@ import Mathlib.Data.Real.ConjExponents In this file we prove several inequalities for finite sums, including AM-GM inequality, HM-GM inequality, Young's inequality, Hölder inequality, and Minkowski inequality. Versions for -integrals of some of these inequalities are available in `MeasureTheory.MeanInequalities`. +integrals of some of these inequalities are available in `MeasureTheory.Integral.MeanInequalities`. ## Main theorems From 858ac8a2e55aa8c63921535866ffad28fab9ad24 Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Sun, 12 Jan 2025 12:10:50 +0000 Subject: [PATCH 172/681] feat(GroupTheory/ZGroup): Cyclic groups are Z-groups (#20357) This PR adds an instance stating that cyclic groups are Z-groups. --- Mathlib/GroupTheory/SpecificGroups/ZGroup.lean | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean b/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean index 84f690ccc8fc3..957f463f0cde5 100644 --- a/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean +++ b/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean @@ -36,6 +36,9 @@ variable {G G' G'' f f'} namespace IsZGroup +instance [IsCyclic G] : IsZGroup G := + ⟨inferInstance⟩ + instance [IsZGroup G] {p : ℕ} [Fact p.Prime] (P : Sylow p G) : IsCyclic P := isZGroup p Fact.out P From 296f6b3ba19409738f306407ecb8cd9f39502811 Mon Sep 17 00:00:00 2001 From: smorel394 Date: Sun, 12 Jan 2025 15:00:08 +0000 Subject: [PATCH 173/681] feat(CategoryTheory/Triangulated/Adjunction): the left adjoint of a triangulated functor is triangulated (#20543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a functor `G : D ⥤ C` between pretriangulated categories is triangulated, and if we have an adjunction `F ⊣ G` (that commutes with the shifts), then `F` is also a triangulated functor. We prove this from the symmetric statement (`F` triangulated implies `G` triangulated) using opposite categories. - [ ] depends on: #20363 Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- Mathlib/CategoryTheory/Shift/Opposite.lean | 4 -- Mathlib/CategoryTheory/Shift/Pullback.lean | 2 - .../Triangulated/Adjunction.lean | 36 ++++++++++++-- .../Triangulated/Opposite/Functor.lean | 49 +++++++++++++++++-- 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/Mathlib/CategoryTheory/Shift/Opposite.lean b/Mathlib/CategoryTheory/Shift/Opposite.lean index 027409b829cae..683367784e9b6 100644 --- a/Mathlib/CategoryTheory/Shift/Opposite.lean +++ b/Mathlib/CategoryTheory/Shift/Opposite.lean @@ -217,8 +217,6 @@ end Functor namespace NatTrans -attribute [local instance] Functor.commShiftOp - variable {F} {G : C ⥤ D} [F.CommShift A] [G.CommShift A] open Opposite in @@ -298,8 +296,6 @@ def OppositeShift.adjunction {F} {G : D ⥤ C} (adj : F ⊣ G) : namespace Adjunction -attribute [local instance] Functor.commShiftOp NatTrans.commShift_op - variable {F} {G : D ⥤ C} (adj : F ⊣ G) /-- diff --git a/Mathlib/CategoryTheory/Shift/Pullback.lean b/Mathlib/CategoryTheory/Shift/Pullback.lean index fde4d2b4db99c..914f3a24544d6 100644 --- a/Mathlib/CategoryTheory/Shift/Pullback.lean +++ b/Mathlib/CategoryTheory/Shift/Pullback.lean @@ -202,8 +202,6 @@ end Functor namespace NatTrans -attribute [local instance] Functor.commShiftPullback - variable {F} {G : C ⥤ D} [G.CommShift B] open Functor in diff --git a/Mathlib/CategoryTheory/Triangulated/Adjunction.lean b/Mathlib/CategoryTheory/Triangulated/Adjunction.lean index 1a2b284a398e1..0e5b547954681 100644 --- a/Mathlib/CategoryTheory/Triangulated/Adjunction.lean +++ b/Mathlib/CategoryTheory/Triangulated/Adjunction.lean @@ -1,22 +1,34 @@ /- 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 +Authors: Joël Riou, Sophie Morel -/ import Mathlib.CategoryTheory.Triangulated.Functor import Mathlib.CategoryTheory.Shift.Adjunction import Mathlib.CategoryTheory.Adjunction.Additive +import Mathlib.CategoryTheory.Adjunction.Opposites +import Mathlib.CategoryTheory.Triangulated.Opposite.Functor /-! # The adjoint functor is triangulated If a functor `F : C ⥤ D` between pretriangulated categories is triangulated, and if we -have an adjunction `F ⊣ G`, then `G` is also a triangulated functor. - -We deduce that, if `E : C ≌ D` is an equivalence of pretriangulated categories, then +have an adjunction `F ⊣ G`, then `G` is also a triangulated functor. We deduce the +symmetric statement (if `G` is a triangulated functor, then so is `F`) using opposite +categories. + +We then introduce a class `IsTriangulated` for adjunctions: an adjunction `F ⊣ G` +is called triangulated if both `F` and `G` are triangulated, and if the adjunction +is compatible with the shifts by `ℤ` on `F` and `G` (in the sense of `Adjunction.CommShift`); +we prove that this is compatible with composition and that the identity adjunction is +triangulated. +Thanks to the results above, an adjunction carrying an `Adjunction.CommShift` instance +is triangulated as soon as one of the adjoint functors is triangulated. + +We finally specialize these structures to equivalences of categories, and prove that, +if `E : C ≌ D` is an equivalence of pretriangulated categories, then `E.functor` is triangulated if and only if `E.inverse` is triangulated. -TODO: The case of left adjoints. -/ assert_not_exists TwoSidedIdeal @@ -113,6 +125,15 @@ lemma isTriangulated_rightAdjoint [F.IsTriangulated] : G.IsTriangulated where Functor.commShiftIso_hom_naturality, ← adj.shift_unit_app_assoc, ← Functor.map_comp, right_triangle_components, Functor.map_id, comp_id] +include adj in +open Pretriangulated.Opposite Functor in +/-- +The left adjoint of a triangulated functor is triangulated. +-/ +lemma isTriangulated_leftAdjoint [G.IsTriangulated] : F.IsTriangulated := by + have := isTriangulated_rightAdjoint adj.op + exact F.isTriangulated_of_op + /-- We say that an adjunction `F ⊣ G` is triangulated if it is compatible with the `CommShift` structures on `F` and `G` (in the sense of `Adjunction.CommShift`) and if both `F` and `G` @@ -132,6 +153,11 @@ attribute [instance] commShift leftAdjoint_isTriangulated rightAdjoint_isTriangu lemma mk' [F.IsTriangulated] : adj.IsTriangulated where rightAdjoint_isTriangulated := adj.isTriangulated_rightAdjoint +/-- Constructor for `Adjunction.IsTriangulated`. +-/ +lemma mk'' [G.IsTriangulated] : adj.IsTriangulated where + leftAdjoint_isTriangulated := adj.isTriangulated_leftAdjoint + /-- The identity adjunction is triangulated. -/ instance id : (Adjunction.id (C := C)).IsTriangulated where diff --git a/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean index 46e03494d123a..83454ecd64c19 100644 --- a/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean +++ b/Mathlib/CategoryTheory/Triangulated/Opposite/Functor.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sophie Morel -/ import Mathlib.CategoryTheory.Triangulated.Opposite.Pretriangulated +import Mathlib.CategoryTheory.Adjunction.Opposites /-! # Opposites of functors between pretriangulated categories, @@ -26,22 +27,46 @@ namespace CategoryTheory variable {C D : Type*} [Category C] [Category D] [HasShift C ℤ] [HasShift D ℤ] (F : C ⥤ D) [F.CommShift ℤ] +open Category Limits Pretriangulated Opposite + namespace Pretriangulated.Opposite /-- If `F` commutes with shifts, so does `F.op`, for the shifts chosen on `Cᵒᵖ` in `CategoryTheory.Triangulated.Opposite.Basic`. -/ -noncomputable scoped instance commShiftOpInt : F.op.CommShift ℤ := +noncomputable scoped instance commShiftFunctorOpInt : F.op.CommShift ℤ := inferInstanceAs ((PullbackShift.functor (AddMonoidHom.mk' (fun (n : ℤ) => -n) (by intros; dsimp; omega)) (OppositeShift.functor ℤ F)).CommShift ℤ) +variable {F} + +noncomputable scoped instance commShift_natTrans_op_int {G : C ⥤ D} [G.CommShift ℤ] (τ : F ⟶ G) + [NatTrans.CommShift τ ℤ] : NatTrans.CommShift (NatTrans.op τ) ℤ := + inferInstanceAs (NatTrans.CommShift (PullbackShift.natTrans + (AddMonoidHom.mk' (fun (n : ℤ) => -n) (by intros; dsimp; omega)) + (OppositeShift.natTrans ℤ τ)) ℤ) + +noncomputable scoped instance commShift_adjunction_op_int {G : D ⥤ C} [G.CommShift ℤ] (adj : F ⊣ G) + [Adjunction.CommShift adj ℤ] : Adjunction.CommShift adj.op ℤ := by + have eq : adj.op = PullbackShift.adjunction + (AddMonoidHom.mk' (fun (n : ℤ) => -n) (by intros; dsimp; omega)) + (OppositeShift.adjunction ℤ adj) := by + ext + dsimp [PullbackShift.adjunction, NatTrans.PullbackShift.natIsoId, + NatTrans.PullbackShift.natIsoComp, PullbackShift.functor, PullbackShift.natTrans, + OppositeShift.adjunction, OppositeShift.natTrans, NatTrans.OppositeShift.natIsoId, + NatTrans.OppositeShift.natIsoComp, OppositeShift.functor] + simp only [Int.reduceNeg, Category.comp_id, Category.id_comp] + rw [eq] + exact inferInstanceAs (Adjunction.CommShift (PullbackShift.adjunction + (AddMonoidHom.mk' (fun (n : ℤ) => -n) (by intros; dsimp; omega)) + (OppositeShift.adjunction ℤ adj)) ℤ) + end Pretriangulated.Opposite namespace Functor -open Category Limits Pretriangulated Opposite - @[reassoc] lemma op_commShiftIso_hom_app (X : Cᵒᵖ) (n m : ℤ) (h : n + m = 0): (F.op.commShiftIso n).hom.app X = @@ -128,10 +153,14 @@ lemma map_opShiftFunctorEquivalence_counitIso_inv_app_unop (X : Cᵒᵖ) (n : Iso.inv_hom_id_app] simp +end Functor + variable [HasZeroObject C] [Preadditive C] [∀ (n : ℤ), (shiftFunctor C n).Additive] [Pretriangulated C] [HasZeroObject D] [Preadditive D] [∀ (n : ℤ), (shiftFunctor D n).Additive] [Pretriangulated D] +namespace Functor + /-- If `F : C ⥤ D` commutes with shifts, this expresses the compatibility of `F.mapTriangle` with the equivalences `Pretriangulated.triangleOpEquivalence` on `C` and `D`. @@ -188,15 +217,24 @@ noncomputable def opMapTriangleCompTriangleOpEquivalenceInverse : CatCommSq.iso (F.op.mapTriangle) (triangleOpEquivalence C).inverse (triangleOpEquivalence D).inverse F.mapTriangle.op +end Functor + +namespace Pretriangulated.Opposite + +open Functor in /-- If `F` is triangulated, so is `F.op`. -/ -lemma isTriangulated_op [F.IsTriangulated] : F.op.IsTriangulated where +scoped instance functor_isTriangulated_op [F.IsTriangulated] : F.op.IsTriangulated where map_distinguished T dT := by rw [mem_distTriang_op_iff] exact Pretriangulated.isomorphic_distinguished _ ((F.map_distinguished _ (unop_distinguished _ dT))) _ (((opMapTriangleCompTriangleOpEquivalenceInverse F).symm.app T).unop) +end Pretriangulated.Opposite + +namespace Functor + /-- If `F.op` is triangulated, so is `F`. -/ lemma isTriangulated_of_op [F.op.IsTriangulated] : F.IsTriangulated where @@ -213,10 +251,11 @@ lemma isTriangulated_of_op [F.op.IsTriangulated] : F.IsTriangulated where rw [← this, Functor.comp_obj, ← mem_distTriang_op_iff] at dT exact dT +open Pretriangulated.Opposite in /-- `F` is triangulated if and only if `F.op` is triangulated. -/ lemma op_isTriangulated_iff : F.op.IsTriangulated ↔ F.IsTriangulated := - ⟨fun _ ↦ F.isTriangulated_of_op, fun _ ↦ F.isTriangulated_op⟩ + ⟨fun _ ↦ F.isTriangulated_of_op, fun _ ↦ inferInstance⟩ end Functor From 650b029070b6d8ffb9ae0392ac7287468525cde1 Mon Sep 17 00:00:00 2001 From: WilliamCoram Date: Sun, 12 Jan 2025 20:14:04 +0000 Subject: [PATCH 174/681] feat: coe theorems in FiniteAdeleRing (#19814) add coercion theorems for: one, zero, add and mul; an interaction with algebraMap; and a theorem showing how algebraMaps of extensions are built. --- .../DedekindDomain/FiniteAdeleRing.lean | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean index c8cb32c58184a..d1ef588be6784 100644 --- a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean +++ b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean @@ -339,6 +339,24 @@ instance : IsScalarTower R K (FiniteAdeleRing R K) := instance : Coe (FiniteAdeleRing R K) (K_hat R K) where coe x := x.1 +@[simp, norm_cast] +theorem coe_one : (1 : FiniteAdeleRing R K) = (1 : K_hat R K) := rfl + +@[simp, norm_cast] +theorem coe_zero: (0 : FiniteAdeleRing R K) = (0 : K_hat R K) := rfl + +@[simp, norm_cast] +theorem coe_add (x y : FiniteAdeleRing R K) : (x + y : FiniteAdeleRing R K) = + (x : K_hat R K) + (y : K_hat R K) := rfl + +@[simp, norm_cast] +theorem coe_mul (x y : FiniteAdeleRing R K) : (x * y : FiniteAdeleRing R K) = + (x : K_hat R K) * (y : K_hat R K) := rfl + +@[simp, norm_cast] +theorem coe_algebraMap (x : K) : (((algebraMap K (FiniteAdeleRing R K)) x) : K_hat R K) = + (algebraMap K (ProdAdicCompletions R K)) x := rfl + @[ext] lemma ext {a₁ a₂ : FiniteAdeleRing R K} (h : (a₁ : K_hat R K) = a₂) : a₁ = a₂ := Subtype.ext h From 5bc9c5af41f290be14c9161ba3719d33a4b88d9a Mon Sep 17 00:00:00 2001 From: haitian-yuki <127060846+yukiniu@users.noreply.github.com> Date: Sun, 12 Jan 2025 20:22:32 +0000 Subject: [PATCH 175/681] feat(Data/Multiset/Order): add Dershowitz-Manna Ordering and Theorem (#14411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add Dershowitz-Manna Ordering and Theorem for Multisets Co-authored-by: Malvin Gattinger Co-authored-by: Yaël Dillies Co-authored-by: Malvin Gattinger Co-authored-by: Haitian Co-authored-by: Malvin Gattinger Co-authored-by: haitian-yuki <127060846+haitian-yuki@users.noreply.github.com> --- Mathlib.lean | 1 + .../Algebra/Order/Sub/Unbundled/Basic.lean | 9 + Mathlib/Data/Multiset/DershowitzManna.lean | 169 ++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 Mathlib/Data/Multiset/DershowitzManna.lean diff --git a/Mathlib.lean b/Mathlib.lean index 1e6e4332b430f..fbe165d18c5a3 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2738,6 +2738,7 @@ import Mathlib.Data.Multiset.Antidiagonal import Mathlib.Data.Multiset.Basic import Mathlib.Data.Multiset.Bind import Mathlib.Data.Multiset.Dedup +import Mathlib.Data.Multiset.DershowitzManna import Mathlib.Data.Multiset.FinsetOps import Mathlib.Data.Multiset.Fintype import Mathlib.Data.Multiset.Fold diff --git a/Mathlib/Algebra/Order/Sub/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Sub/Unbundled/Basic.lean index 899776822e162..2d172210de934 100644 --- a/Mathlib/Algebra/Order/Sub/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Sub/Unbundled/Basic.lean @@ -149,6 +149,11 @@ protected theorem tsub_lt_tsub_iff_left_of_le_of_le [AddLeftReflectLT α] a - b < a - c ↔ c < b := ⟨hb.lt_of_tsub_lt_tsub_left_of_le h₂, hab.tsub_lt_tsub_left_of_le h₁⟩ +@[simp] +protected lemma add_add_tsub_cancel (hc : AddLECancellable c) (hcb : c ≤ b) : + a + c + (b - c) = a + b := by + rw [← hc.add_tsub_assoc_of_le hcb, add_right_comm, hc.add_tsub_cancel_right] + @[simp] protected theorem add_tsub_tsub_cancel (hac : AddLECancellable (a - c)) (h : c ≤ a) : a + b - (a - c) = b + c := @@ -235,6 +240,10 @@ theorem tsub_lt_tsub_iff_left_of_le_of_le [AddLeftReflectLT α] (h₁ : b ≤ a) Contravariant.AddLECancellable.tsub_lt_tsub_iff_left_of_le_of_le Contravariant.AddLECancellable h₁ h₂ +@[simp] +lemma add_add_tsub_cancel (hcb : c ≤ b) : a + c + (b - c) = a + b := + Contravariant.AddLECancellable.add_add_tsub_cancel hcb + @[simp] theorem add_tsub_tsub_cancel (h : c ≤ a) : a + b - (a - c) = b + c := Contravariant.AddLECancellable.add_tsub_tsub_cancel h diff --git a/Mathlib/Data/Multiset/DershowitzManna.lean b/Mathlib/Data/Multiset/DershowitzManna.lean new file mode 100644 index 0000000000000..e88826a9b945f --- /dev/null +++ b/Mathlib/Data/Multiset/DershowitzManna.lean @@ -0,0 +1,169 @@ +/- +Copyright (c) 2024 Haitian Wang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Haitian Wang, Malvin Gattinger +-/ +import Mathlib.Algebra.Order.Sub.Unbundled.Basic +import Mathlib.Data.Multiset.OrderedMonoid + +/-! +# Dershowitz-Manna ordering + +In this file we define the _Dershowitz-Manna ordering_ on multisets. Specifically, for two multisets +`M` and `N` in a partial order `(S, <)`, `M` is smaller than `N` in the Dershowitz-Manna ordering if +`M` can be obtained from `N` by replacing one or more elements in `N` by some finite number of +elements from `S`, each of which is smaller (in the underling ordering over `S`) than one of the +replaced elements from `N`. We prove that, given a well-founded partial order on the underlying set, +the Dershowitz-Manna ordering defined over multisets is also well-founded. + +## Main results + +- `Multiset.IsDershowitzMannaLT` : the standard definition fo the `Dershowitz-Manna ordering`. +- `Multiset.wellFounded_isDershowitzMannaLT` : the main theorem about the +`Dershowitz-Manna ordering` being well-founded. + +## References + +* [Wikipedia, Dershowitz–Manna ordering*] +(https://en.wikipedia.org/wiki/Dershowitz%E2%80%93Manna_ordering) + +* [CoLoR](https://github.com/fblanqui/color), a Coq library on rewriting theory and termination. + Our code here is inspired by their formalization and the theorem is called `mOrd_wf` in the file + [MultisetList.v](https://github.com/fblanqui/color/blob/1.8.5/Util/Multiset/MultisetOrder.v). + +-/ + +open Relation + +namespace Multiset + +variable {α : Type*} [Preorder α] {M N P : Multiset α} {a : α} + +/-- The standard Dershowitz–Manna ordering. -/ +def IsDershowitzMannaLT (M N : Multiset α) : Prop := + ∃ X Y Z, + Z ≠ ∅ + ∧ M = X + Y + ∧ N = X + Z + ∧ ∀ y ∈ Y, ∃ z ∈ Z, y < z + +/-- `IsDershowitzMannaLT` is transitive. -/ +lemma IsDershowitzMannaLT.trans : + IsDershowitzMannaLT M N → IsDershowitzMannaLT N P → IsDershowitzMannaLT M P := by + classical + rintro ⟨X₁, Y₁, Z₁, -, rfl, rfl, hYZ₁⟩ ⟨X₂, Y₂, Z₂, hZ₂, hXZXY, rfl, hYZ₂⟩ + rw [add_comm X₁,add_comm X₂] at hXZXY + refine ⟨X₁ ∩ X₂, Y₁ + (Y₂ - Z₁), Z₂ + (Z₁ - Y₂), ?_, ?_, ?_, ?_⟩ + · simpa [-not_and, not_and_or] using .inl hZ₂ + · rwa [← add_assoc, add_right_comm, inter_add_sub_of_add_eq_add] + · rw [← add_assoc, add_right_comm, add_left_inj, inter_comm, inter_add_sub_of_add_eq_add] + rwa [eq_comm] + simp only [mem_add, or_imp, forall_and] + refine ⟨fun y hy ↦ ?_, fun y hy ↦ ?_⟩ + · obtain ⟨z, hz, hyz⟩ := hYZ₁ y hy + by_cases z_in : z ∈ Y₂ + · obtain ⟨w, hw, hzw⟩ := hYZ₂ z z_in + exact ⟨w, .inl hw, hyz.trans hzw⟩ + · exact ⟨z, .inr <| by rwa [mem_sub, count_eq_zero_of_not_mem z_in, count_pos], hyz⟩ + · obtain ⟨z, hz, hyz⟩ := hYZ₂ y <| mem_of_le (Multiset.sub_le_self ..) hy + exact ⟨z, .inl hz, hyz⟩ + +/-- A special case of `IsDershowitzMannaLT`. The transitive closure of it is used to define +an equivalent (proved later) version of the ordering. -/ +private def OneStep (M N : Multiset α) : Prop := + ∃ X Y a, + M = X + Y + ∧ N = X + {a} + ∧ ∀ y ∈ Y, y < a + +private lemma isDershowitzMannaLT_of_oneStep : OneStep M N → IsDershowitzMannaLT M N := by + rintro ⟨X, Y, a, M_def, N_def, ys_lt_a⟩ + use X, Y, {a}, by simp, M_def, N_def + · simpa + +private lemma isDershowitzMannaLT_singleton_insert (h : OneStep N (a ::ₘ M)) : + ∃ M', N = a ::ₘ M' ∧ OneStep M' M ∨ N = M + M' ∧ ∀ x ∈ M', x < a := by + classical + obtain ⟨X, Y, b, rfl, h0, h2⟩ := h + obtain rfl | hab := eq_or_ne a b + · refine ⟨Y, .inr ⟨?_, h2⟩⟩ + simpa [add_comm _ {a}, singleton_add, eq_comm] using h0 + refine ⟨Y + (M - {b}), .inl ⟨?_, M - {b}, Y, b, add_comm .., ?_, h2⟩⟩ + · rw [← singleton_add, add_comm] at h0 + rw [tsub_eq_tsub_of_add_eq_add h0, add_comm Y, ← singleton_add, ← add_assoc, + add_tsub_cancel_of_le] + have : a ∈ X + {b} := by simp [← h0] + simpa [hab] using this + · rw [tsub_add_cancel_of_le] + have : b ∈ a ::ₘ M := by simp [h0] + simpa [hab.symm] using this + +private lemma acc_oneStep_cons_of_acc_lt (ha : Acc LT.lt a) : + ∀ {M}, Acc OneStep M → Acc OneStep (a ::ₘ M) := by + induction' ha with a _ ha + rintro M hM + induction' hM with M hM ihM + refine .intro _ fun N hNM ↦ ?_ + obtain ⟨N, ⟨rfl, hNM'⟩ | ⟨rfl, hN⟩⟩ := isDershowitzMannaLT_singleton_insert hNM + · exact ihM _ hNM' + clear hNM + induction N using Multiset.induction with + | empty => + simpa using .intro _ hM + | @cons b N ihN => + simp only [mem_cons, forall_eq_or_imp, add_cons] at hN ⊢ + obtain ⟨hba, hN⟩ := hN + exact ha _ hba <| ihN hN + +/-- If all elements of a multiset `M` are accessible with `<`, then the multiset `M` is +accessible given the `OneStep` relation. -/ +private lemma acc_oneStep_of_acc_lt (hM : ∀ x ∈ M, Acc LT.lt x) : Acc OneStep M := by + induction M using Multiset.induction_on with + | empty => + constructor + simp [OneStep, eq_comm (b := _ + _)] + | cons a M ih => + exact acc_oneStep_cons_of_acc_lt (hM _ <| mem_cons_self ..) <| ih fun x hx ↦ + hM _ <| mem_cons_of_mem hx + +/-- Over a well-founded order, `OneStep` is well-founded. -/ +private lemma isDershowitzMannaLT_singleton_wf [WellFoundedLT α] : + WellFounded (OneStep : Multiset α → Multiset α → Prop) := + ⟨fun _M ↦ acc_oneStep_of_acc_lt fun a _ ↦ WellFoundedLT.apply a⟩ + +private lemma transGen_oneStep_of_isDershowitzMannaLT : + IsDershowitzMannaLT M N → TransGen OneStep M N := by + classical + rintro ⟨X, Y, Z, hZ, hM, hN, hYZ⟩ + induction' Z using Multiset.induction_on with z Z ih generalizing X Y M N + · simp at hZ + obtain rfl | hZ := eq_or_ne Z 0 + · exact .single ⟨X, Y, z, hM, hN, by simpa using hYZ⟩ + let Y' : Multiset α := Y.filter (· < z) + refine .tail (b := X + Y' + Z) (ih (X + Y') (Y - Y') hZ ?_ rfl fun y hy ↦ ?_) <| + ⟨X + Z, Y', z, add_right_comm .., by simp [hN, add_comm (_ + _)], by simp [Y']⟩ + · rw [add_add_tsub_cancel (filter_le ..), hM] + · simp only [sub_filter_eq_filter_not, mem_filter, Y'] at hy + simpa [hy.2] using hYZ y (by aesop) + +private lemma isDershowitzMannaLT_of_transGen_oneStep (hMN : TransGen OneStep M N) : + IsDershowitzMannaLT M N := + hMN.trans_induction_on (by rintro _ _ ⟨X, Y, a, rfl, rfl, hYa⟩; exact ⟨X, Y, {a}, by simpa⟩) + fun _ _ ↦ .trans + +/-- `TransGen OneStep` and `IsDershowitzMannaLT` are equivalent. -/ +private lemma transGen_oneStep_eq_isDershowitzMannaLT : + (TransGen OneStep : Multiset α → Multiset α → Prop) = IsDershowitzMannaLT := by + ext M N + exact ⟨isDershowitzMannaLT_of_transGen_oneStep, transGen_oneStep_of_isDershowitzMannaLT⟩ + +/-- Over a well-founded order, the Dershowitz-Manna order on multisets is well-founded. -/ +theorem wellFounded_isDershowitzMannaLT [WellFoundedLT α] : + WellFounded (IsDershowitzMannaLT : Multiset α → Multiset α → Prop) := by + rw [← transGen_oneStep_eq_isDershowitzMannaLT] + exact isDershowitzMannaLT_singleton_wf.transGen + +instance instWellFoundedisDershowitzMannaLT [WellFoundedLT α] : WellFoundedRelation (Multiset α) := + ⟨IsDershowitzMannaLT, wellFounded_isDershowitzMannaLT⟩ + +end Multiset From 238352d92d4e361c2358362a005cbbc0be527f2f Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Sun, 12 Jan 2025 20:22:33 +0000 Subject: [PATCH 176/681] feat(GroupTheory/SpecificGroups/Cyclic): Actions on cyclic groups factor through `ZMod` (#20359) This is a technical PR needed for the classification of Z-groups in #20358. Co-authored-by: Thomas Browning --- .../GroupTheory/SpecificGroups/Cyclic.lean | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index b469bc7d71d9f..23b0bc5cfb952 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -335,6 +335,34 @@ lemma IsCyclic.exists_ofOrder_eq_natCard [h : IsCyclic α] : ∃ g : α, orderOf rw [← card_zpowers g, (eq_top_iff' (zpowers g)).mpr hg] exact Nat.card_congr (Equiv.Set.univ α) +variable (G) in +/-- A distributive action of a monoid on a finite cyclic group of order `n` factors through an +action on `ZMod n`. -/ +noncomputable def MulDistribMulAction.toMonoidHomZModOfIsCyclic (M : Type*) [Monoid M] + [IsCyclic G] [MulDistribMulAction M G] {n : ℕ} (hn : Nat.card G = n) : M →* ZMod n where + toFun m := (MulDistribMulAction.toMonoidHom G m).map_cyclic.choose + map_one' := by + obtain ⟨g, hg⟩ := IsCyclic.exists_ofOrder_eq_natCard (α := G) + rw [← Int.cast_one, ZMod.intCast_eq_intCast_iff, ← hn, ← hg, ← zpow_eq_zpow_iff_modEq, + zpow_one, ← (MulDistribMulAction.toMonoidHom G 1).map_cyclic.choose_spec, + MulDistribMulAction.toMonoidHom_apply, one_smul] + map_mul' m n := by + obtain ⟨g, hg⟩ := IsCyclic.exists_ofOrder_eq_natCard (α := G) + rw [← Int.cast_mul, ZMod.intCast_eq_intCast_iff, ← hn, ← hg, ← zpow_eq_zpow_iff_modEq, + zpow_mul', ← (MulDistribMulAction.toMonoidHom G m).map_cyclic.choose_spec, + ← (MulDistribMulAction.toMonoidHom G n).map_cyclic.choose_spec, + ← (MulDistribMulAction.toMonoidHom G (m * n)).map_cyclic.choose_spec, + MulDistribMulAction.toMonoidHom_apply, MulDistribMulAction.toMonoidHom_apply, + MulDistribMulAction.toMonoidHom_apply, mul_smul] + +theorem MulDistribMulAction.toMonoidHomZModOfIsCyclic_apply {M : Type*} [Monoid M] [IsCyclic G] + [MulDistribMulAction M G] {n : ℕ} (hn : Nat.card G = n) (m : M) (g : G) (k : ℤ) + (h : toMonoidHomZModOfIsCyclic G M hn m = k) : m • g = g ^ k := by + rw [← MulDistribMulAction.toMonoidHom_apply, + (MulDistribMulAction.toMonoidHom G m).map_cyclic.choose_spec g, zpow_eq_zpow_iff_modEq] + apply Int.ModEq.of_dvd (Int.natCast_dvd_natCast.mpr (orderOf_dvd_natCard g)) + rwa [hn, ← ZMod.intCast_eq_intCast_iff] + section variable [Fintype α] From ea9d85f29b61f6476573535ac0d0ade59b4bd693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 12 Jan 2025 20:22:34 +0000 Subject: [PATCH 177/681] chore(Subalgebra/Unitization): move unrelated defs/lemmas earlier (#20526) The `Subobject.toNonUnitalSubobject` and `NonUnitalSubobject.toSubobject` functions (for `Subobject` = `Subsemiring`, `Subring`, `Subalgebra`, `StarSubalgebra`) were in `Algebra.Algebra.Subalgebra.Unitization` instead of where `Subobject` is defined. This PR moves them there, at the cost of importing `NonUnitalSubobject` when defining `Subobject` (which seems like a fine trade-off). Co-authored-by: Matthew Ballard --- Mathlib/Algebra/Algebra/Subalgebra/Basic.lean | 26 +++ .../Algebra/Subalgebra/Unitization.lean | 180 ------------------ Mathlib/Algebra/Ring/Subring/Defs.lean | 16 ++ Mathlib/Algebra/Ring/Subsemiring/Basic.lean | 7 + Mathlib/Algebra/Ring/Subsemiring/Defs.lean | 35 ++++ Mathlib/Algebra/Star/Subalgebra.lean | 50 ++++- Mathlib/RingTheory/Adjoin/Basic.lean | 19 ++ .../ContinuousMap/StoneWeierstrass.lean | 2 +- 8 files changed, 152 insertions(+), 183 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index edf843664e624..20dfa0a99eb8f 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -5,6 +5,7 @@ Authors: Kenny Lau, Yury Kudryashov -/ import Mathlib.RingTheory.SimpleRing.Basic import Mathlib.Algebra.Algebra.Operations +import Mathlib.Algebra.Algebra.NonUnitalSubalgebra /-! # Subalgebras over Commutative Semiring @@ -146,6 +147,14 @@ protected theorem prod_mem {R : Type u} {A : Type v} [CommSemiring R] [CommSemir (∏ x ∈ t, f x) ∈ S := prod_mem h +/-- Turn a `Subalgebra` into a `NonUnitalSubalgebra` by forgetting that it contains `1`. -/ +def toNonUnitalSubalgebra (S : Subalgebra R A) : NonUnitalSubalgebra R A where + __ := S + smul_mem' r _x hx := S.smul_mem hx r + +lemma one_mem_toNonUnitalSubalgebra (S : Subalgebra R A) : (1 : A) ∈ S.toNonUnitalSubalgebra := + S.one_mem + instance {R A : Type*} [CommRing R] [Ring A] [Algebra R A] : SubringClass (Subalgebra R A) A := { Subalgebra.SubsemiringClass with neg_mem := fun {S x} hx => neg_one_smul R x ▸ S.smul_mem hx _ } @@ -1245,3 +1254,20 @@ theorem comap_map_eq_self_of_injective end Subalgebra end MapComap + +variable {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] + +/-- Turn a non-unital subalgebra containing `1` into a subalgebra. -/ +def NonUnitalSubalgebra.toSubalgebra (S : NonUnitalSubalgebra R A) (h1 : (1 : A) ∈ S) : + Subalgebra R A := + { S with + one_mem' := h1 + algebraMap_mem' := fun r => + (Algebra.algebraMap_eq_smul_one (R := R) (A := A) r).symm ▸ SMulMemClass.smul_mem r h1 } + +lemma Subalgebra.toNonUnitalSubalgebra_toSubalgebra (S : Subalgebra R A) : + S.toNonUnitalSubalgebra.toSubalgebra S.one_mem = S := by cases S; rfl + +lemma NonUnitalSubalgebra.toSubalgebra_toNonUnitalSubalgebra (S : NonUnitalSubalgebra R A) + (h1 : (1 : A) ∈ S) : (NonUnitalSubalgebra.toSubalgebra S h1).toNonUnitalSubalgebra = S := by + cases S; rfl diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean b/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean index e1bf0603035cd..1cfc8f8284e79 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Algebra.Algebra.Unitization -import Mathlib.Algebra.Star.NonUnitalSubalgebra import Mathlib.Algebra.Star.Subalgebra import Mathlib.GroupTheory.GroupAction.Ring @@ -46,54 +45,6 @@ this map to be injective it suffices that the range omits `1`. In this setting w /-! ## Subalgebras -/ -section Subalgebra - -variable {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] - -/-- Turn a `Subalgebra` into a `NonUnitalSubalgebra` by forgetting that it contains `1`. -/ -def Subalgebra.toNonUnitalSubalgebra (S : Subalgebra R A) : NonUnitalSubalgebra R A := - { S with - smul_mem' := fun r _x hx => S.smul_mem hx r } - -theorem Subalgebra.one_mem_toNonUnitalSubalgebra (S : Subalgebra R A) : - (1 : A) ∈ S.toNonUnitalSubalgebra := - S.one_mem - -/-- Turn a non-unital subalgebra containing `1` into a subalgebra. -/ -def NonUnitalSubalgebra.toSubalgebra (S : NonUnitalSubalgebra R A) (h1 : (1 : A) ∈ S) : - Subalgebra R A := - { S with - one_mem' := h1 - algebraMap_mem' := fun r => - (Algebra.algebraMap_eq_smul_one (R := R) (A := A) r).symm ▸ SMulMemClass.smul_mem r h1 } - -theorem Subalgebra.toNonUnitalSubalgebra_toSubalgebra (S : Subalgebra R A) : - S.toNonUnitalSubalgebra.toSubalgebra S.one_mem = S := by cases S; rfl - -theorem NonUnitalSubalgebra.toSubalgebra_toNonUnitalSubalgebra (S : NonUnitalSubalgebra R A) - (h1 : (1 : A) ∈ S) : (NonUnitalSubalgebra.toSubalgebra S h1).toNonUnitalSubalgebra = S := by - cases S; rfl - -open Submodule in -lemma Algebra.adjoin_nonUnitalSubalgebra_eq_span (s : NonUnitalSubalgebra R A) : - Subalgebra.toSubmodule (adjoin R (s : Set A)) = span R {1} ⊔ s.toSubmodule := by - rw [adjoin_eq_span, Submonoid.closure_eq_one_union, span_union, ← NonUnitalAlgebra.adjoin_eq_span, - NonUnitalAlgebra.adjoin_eq] - -variable (R) - -lemma NonUnitalAlgebra.adjoin_le_algebra_adjoin (s : Set A) : - adjoin R s ≤ (Algebra.adjoin R s).toNonUnitalSubalgebra := - adjoin_le Algebra.subset_adjoin - -lemma Algebra.adjoin_nonUnitalSubalgebra (s : Set A) : - adjoin R (NonUnitalAlgebra.adjoin R s : Set A) = adjoin R s := - le_antisymm - (adjoin_le <| NonUnitalAlgebra.adjoin_le_algebra_adjoin R s) - (adjoin_le <| (NonUnitalAlgebra.subset_adjoin R).trans subset_adjoin) - -end Subalgebra - namespace Unitization variable {R A C : Type*} [CommSemiring R] [NonUnitalSemiring A] @@ -200,59 +151,6 @@ end NonUnitalSubalgebra /-! ## Subsemirings -/ -section Subsemiring - -variable {R : Type*} [NonAssocSemiring R] - -/-- Turn a `Subsemiring` into a `NonUnitalSubsemiring` by forgetting that it contains `1`. -/ -def Subsemiring.toNonUnitalSubsemiring (S : Subsemiring R) : NonUnitalSubsemiring R := - { S with } - -theorem Subsemiring.toNonUnitalSubsemiring_injective : - Function.Injective (toNonUnitalSubsemiring : Subsemiring R → _) := - fun S₁ S₂ h => SetLike.ext'_iff.2 ( - show (S₁.toNonUnitalSubsemiring : Set R) = S₂ from SetLike.ext'_iff.1 h) - -@[simp] -theorem Subsemiring.toNonUnitalSubsemiring_inj {S₁ S₂ : Subsemiring R} : - S₁.toNonUnitalSubsemiring = S₂.toNonUnitalSubsemiring ↔ S₁ = S₂ := - toNonUnitalSubsemiring_injective.eq_iff - -@[simp] -theorem Subsemiring.mem_toNonUnitalSubsemiring {S : Subsemiring R} - {x : R} : x ∈ S.toNonUnitalSubsemiring ↔ x ∈ S := Iff.rfl - -@[simp] -theorem Subsemiring.coe_toNonUnitalSubsemiring (S : Subsemiring R) : - (S.toNonUnitalSubsemiring : Set R) = S := rfl - -theorem Subsemiring.one_mem_toNonUnitalSubsemiring (S : Subsemiring R) : - (1 : R) ∈ S.toNonUnitalSubsemiring := - S.one_mem - -@[simp] -theorem Submonoid.subsemiringClosure_toNonUnitalSubsemiring {M : Submonoid R} : - M.subsemiringClosure.toNonUnitalSubsemiring = .closure M := by - refine Eq.symm (NonUnitalSubsemiring.closure_eq_of_le ?_ (fun _ hx => ?_)) - · simp [Submonoid.subsemiringClosure_coe] - · simp [Submonoid.subsemiringClosure_mem] at hx - induction hx using AddSubmonoid.closure_induction <;> aesop - -/-- Turn a non-unital subsemiring containing `1` into a subsemiring. -/ -def NonUnitalSubsemiring.toSubsemiring (S : NonUnitalSubsemiring R) (h1 : (1 : R) ∈ S) : - Subsemiring R := - { S with - one_mem' := h1 } - -theorem Subsemiring.toNonUnitalSubsemiring_toSubsemiring (S : Subsemiring R) : - S.toNonUnitalSubsemiring.toSubsemiring S.one_mem = S := by cases S; rfl - -theorem NonUnitalSubsemiring.toSubsemiring_toNonUnitalSubsemiring (S : NonUnitalSubsemiring R) - (h1 : (1 : R) ∈ S) : (NonUnitalSubsemiring.toSubsemiring S h1).toNonUnitalSubsemiring = S := by - cases S; rfl - -end Subsemiring - namespace NonUnitalSubsemiring variable {R S : Type*} [Semiring R] [SetLike S R] [hSR : NonUnitalSubsemiringClass S R] (s : S) @@ -275,31 +173,6 @@ end NonUnitalSubsemiring /-! ## Subrings -/ -section Subring - --- TODO: Maybe we could use `NonAssocRing` here but right now `Subring` takes a `Ring` argument. -variable {R : Type*} [Ring R] - -/-- Turn a `Subring` into a `NonUnitalSubring` by forgetting that it contains `1`. -/ -def Subring.toNonUnitalSubring (S : Subring R) : NonUnitalSubring R := - { S with } - -theorem Subring.one_mem_toNonUnitalSubring (S : Subring R) : (1 : R) ∈ S.toNonUnitalSubring := - S.one_mem - -/-- Turn a non-unital subring containing `1` into a subring. -/ -def NonUnitalSubring.toSubring (S : NonUnitalSubring R) (h1 : (1 : R) ∈ S) : Subring R := - { S with - one_mem' := h1 } - -theorem Subring.toNonUnitalSubring_toSubring (S : Subring R) : - S.toNonUnitalSubring.toSubring S.one_mem = S := by cases S; rfl - -theorem NonUnitalSubring.toSubring_toNonUnitalSubring (S : NonUnitalSubring R) (h1 : (1 : R) ∈ S) : - (NonUnitalSubring.toSubring S h1).toNonUnitalSubring = S := by cases S; rfl - -end Subring - namespace NonUnitalSubring variable {R S : Type*} [Ring R] [SetLike S R] [hSR : NonUnitalSubringClass S R] (s : S) @@ -322,59 +195,6 @@ end NonUnitalSubring /-! ## Star subalgebras -/ -section StarSubalgebra - -variable {R A : Type*} [CommSemiring R] [StarRing R] [Semiring A] [StarRing A] -variable [Algebra R A] [StarModule R A] - -/-- Turn a `StarSubalgebra` into a `NonUnitalStarSubalgebra` by forgetting that it contains `1`. -/ -def StarSubalgebra.toNonUnitalStarSubalgebra (S : StarSubalgebra R A) : - NonUnitalStarSubalgebra R A := - { S with - carrier := S.carrier - smul_mem' := fun r _x hx => S.smul_mem hx r } - -theorem StarSubalgebra.one_mem_toNonUnitalStarSubalgebra (S : StarSubalgebra R A) : - (1 : A) ∈ S.toNonUnitalStarSubalgebra := - S.one_mem' - -/-- Turn a non-unital star subalgebra containing `1` into a `StarSubalgebra`. -/ -def NonUnitalStarSubalgebra.toStarSubalgebra (S : NonUnitalStarSubalgebra R A) (h1 : (1 : A) ∈ S) : - StarSubalgebra R A := - { S with - carrier := S.carrier - one_mem' := h1 - algebraMap_mem' := fun r => - (Algebra.algebraMap_eq_smul_one (R := R) (A := A) r).symm ▸ SMulMemClass.smul_mem r h1 } - -theorem StarSubalgebra.toNonUnitalStarSubalgebra_toStarSubalgebra (S : StarSubalgebra R A) : - S.toNonUnitalStarSubalgebra.toStarSubalgebra S.one_mem' = S := by cases S; rfl - -theorem NonUnitalStarSubalgebra.toStarSubalgebra_toNonUnitalStarSubalgebra - (S : NonUnitalStarSubalgebra R A) (h1 : (1 : A) ∈ S) : - (S.toStarSubalgebra h1).toNonUnitalStarSubalgebra = S := by - cases S; rfl - -open Submodule in -lemma StarAlgebra.adjoin_nonUnitalStarSubalgebra_eq_span (s : NonUnitalStarSubalgebra R A) : - Subalgebra.toSubmodule (adjoin R (s : Set A)).toSubalgebra = span R {1} ⊔ s.toSubmodule := by - rw [adjoin_eq_span, Submonoid.closure_eq_one_union, span_union, - ← NonUnitalStarAlgebra.adjoin_eq_span, NonUnitalStarAlgebra.adjoin_eq] - -variable (R) - -lemma NonUnitalStarAlgebra.adjoin_le_starAlgebra_adjoin (s : Set A) : - adjoin R s ≤ (StarAlgebra.adjoin R s).toNonUnitalStarSubalgebra := - adjoin_le <| StarAlgebra.subset_adjoin R s - -lemma StarAlgebra.adjoin_nonUnitalStarSubalgebra (s : Set A) : - adjoin R (NonUnitalStarAlgebra.adjoin R s : Set A) = adjoin R s := - le_antisymm - (adjoin_le <| NonUnitalStarAlgebra.adjoin_le_starAlgebra_adjoin R s) - (adjoin_le <| (NonUnitalStarAlgebra.subset_adjoin R s).trans <| subset_adjoin R _) - -end StarSubalgebra - namespace Unitization variable {R A C : Type*} [CommSemiring R] [NonUnitalSemiring A] [StarRing R] [StarRing A] diff --git a/Mathlib/Algebra/Ring/Subring/Defs.lean b/Mathlib/Algebra/Ring/Subring/Defs.lean index 321e09cc9aa05..4ac441db39d99 100644 --- a/Mathlib/Algebra/Ring/Subring/Defs.lean +++ b/Mathlib/Algebra/Ring/Subring/Defs.lean @@ -166,6 +166,9 @@ instance : SubringClass (Subring R) R where initialize_simps_projections Subring (carrier → coe, as_prefix coe) +/-- Turn a `Subring` into a `NonUnitalSubring` by forgetting that it contains `1`. -/ +def toNonUnitalSubring (S : Subring R) : NonUnitalSubring R where __ := S + @[simp] theorem mem_toSubsemiring {s : Subring R} {x : R} : x ∈ s.toSubsemiring ↔ x ∈ s := Iff.rfl @@ -182,6 +185,8 @@ theorem mk_le_mk {S S' : Subsemiring R} (h₁ h₂) : (⟨S, h₁⟩ : Subring R) ≤ (⟨S', h₂⟩ : Subring R) ↔ S ≤ S' := Iff.rfl +lemma one_mem_toNonUnitalSubring (S : Subring R) : 1 ∈ S.toNonUnitalSubring := S.one_mem + /-- Two subrings are equal if they have the same elements. -/ @[ext] theorem ext {S T : Subring R} (h : ∀ x, x ∈ S ↔ x ∈ T) : S = T := @@ -363,6 +368,17 @@ theorem coe_toAddSubgroup (s : Subring R) : (s.toAddSubgroup : Set R) = s := end Subring +/-- Turn a non-unital subring containing `1` into a subring. -/ +def NonUnitalSubring.toSubring (S : NonUnitalSubring R) (h1 : (1 : R) ∈ S) : Subring R where + __ := S + one_mem' := h1 + +lemma Subring.toNonUnitalSubring_toSubring (S : Subring R) : + S.toNonUnitalSubring.toSubring S.one_mem = S := by cases S; rfl + +lemma NonUnitalSubring.toSubring_toNonUnitalSubring (S : NonUnitalSubring R) (h1 : (1 : R) ∈ S) : + (NonUnitalSubring.toSubring S h1).toNonUnitalSubring = S := by cases S; rfl + theorem AddSubgroup.int_mul_mem {G : AddSubgroup R} (k : ℤ) {g : R} (h : g ∈ G) : (k : R) * g ∈ G := by convert AddSubgroup.zsmul_mem G h k using 1 diff --git a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean index 801d3c6d69cf1..e38a8720a241a 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean @@ -399,6 +399,13 @@ theorem subsemiringClosure_toAddSubmonoid : M.subsemiringClosure.toAddSubmonoid = AddSubmonoid.closure (M : Set R) := rfl +@[simp] lemma subsemiringClosure_toNonUnitalSubsemiring (M : Submonoid R) : + M.subsemiringClosure.toNonUnitalSubsemiring = .closure M := by + refine Eq.symm (NonUnitalSubsemiring.closure_eq_of_le ?_ fun _ hx ↦ ?_) + · simp [Submonoid.subsemiringClosure_coe] + · simp [Submonoid.subsemiringClosure_mem] at hx + induction hx using AddSubmonoid.closure_induction <;> aesop + /-- The `Subsemiring` generated by a multiplicative submonoid coincides with the `Subsemiring.closure` of the submonoid itself . -/ theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by diff --git a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean index ada342ff44bd3..3d0186346b217 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean @@ -139,13 +139,23 @@ instance : SubsemiringClass (Subsemiring R) R where initialize_simps_projections Subsemiring (carrier → coe, as_prefix coe) +/-- Turn a `Subsemiring` into a `NonUnitalSubsemiring` by forgetting that it contains `1`. -/ +def toNonUnitalSubsemiring (S : Subsemiring R) : NonUnitalSubsemiring R where __ := S + @[simp] theorem mem_toSubmonoid {s : Subsemiring R} {x : R} : x ∈ s.toSubmonoid ↔ x ∈ s := Iff.rfl +@[simp] +lemma mem_toNonUnitalSubsemiring {S : Subsemiring R} {x : R} : + x ∈ S.toNonUnitalSubsemiring ↔ x ∈ S := .rfl + theorem mem_carrier {s : Subsemiring R} {x : R} : x ∈ s.carrier ↔ x ∈ s := Iff.rfl +@[simp] +lemma coe_toNonUnitalSubsemiring (S : Subsemiring R) : (S.toNonUnitalSubsemiring : Set R) = S := rfl + /-- Two subsemirings are equal if they have the same elements. -/ @[ext] theorem ext {S T : Subsemiring R} (h : ∀ x, x ∈ S ↔ x ∈ T) : S = T := @@ -167,6 +177,19 @@ theorem toAddSubmonoid_injective : Function.Injective (toAddSubmonoid : Subsemiring R → AddSubmonoid R) | _, _, h => ext (SetLike.ext_iff.mp h :) +lemma toNonUnitalSubsemiring_injective : + Function.Injective (toNonUnitalSubsemiring : Subsemiring R → _) := + fun S₁ S₂ h => SetLike.ext'_iff.2 ( + show (S₁.toNonUnitalSubsemiring : Set R) = S₂ from SetLike.ext'_iff.1 h) + +@[simp] +lemma toNonUnitalSubsemiring_inj {S₁ S₂ : Subsemiring R} : + S₁.toNonUnitalSubsemiring = S₂.toNonUnitalSubsemiring ↔ S₁ = S₂ := + toNonUnitalSubsemiring_injective.eq_iff + +lemma one_mem_toNonUnitalSubsemiring (S : Subsemiring R) : (1 : R) ∈ S.toNonUnitalSubsemiring := + S.one_mem + /-- Construct a `Subsemiring R` from a set `s`, a submonoid `sm`, and an additive submonoid `sa` such that `x ∈ s ↔ x ∈ sm ↔ x ∈ sa`. -/ @[simps coe] @@ -345,3 +368,15 @@ theorem eqLocusS_same (f : R →+* S) : f.eqLocusS f = ⊤ := SetLike.ext fun _ => eq_self_iff_true _ end RingHom + +/-- Turn a non-unital subsemiring containing `1` into a subsemiring. -/ +def NonUnitalSubsemiring.toSubsemiring (S : NonUnitalSubsemiring R) (h1 : 1 ∈ S) : + Subsemiring R where + __ := S + one_mem' := h1 + +lemma Subsemiring.toNonUnitalSubsemiring_toSubsemiring (S : Subsemiring R) : + S.toNonUnitalSubsemiring.toSubsemiring S.one_mem = S := rfl + +lemma NonUnitalSubsemiring.toSubsemiring_toNonUnitalSubsemiring (S : NonUnitalSubsemiring R) (h1) : + (NonUnitalSubsemiring.toSubsemiring S h1).toNonUnitalSubsemiring = S := rfl diff --git a/Mathlib/Algebra/Star/Subalgebra.lean b/Mathlib/Algebra/Star/Subalgebra.lean index 8761b250d94cb..815b95c21f2f4 100644 --- a/Mathlib/Algebra/Star/Subalgebra.lean +++ b/Mathlib/Algebra/Star/Subalgebra.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison, Jireh Loreaux -/ import Mathlib.Algebra.Star.Center +import Mathlib.Algebra.Star.NonUnitalSubalgebra import Mathlib.Algebra.Star.StarAlgHom import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.Star.Pointwise @@ -73,6 +74,14 @@ instance algebra (s : StarSubalgebra R A) : Algebra R s := instance starModule (s : StarSubalgebra R A) : StarModule R s where star_smul r a := Subtype.ext (star_smul r (a : A)) +/-- Turn a `StarSubalgebra` into a `NonUnitalStarSubalgebra` by forgetting that it contains `1`. -/ +def toNonUnitalStarSubalgebra (S : StarSubalgebra R A) : NonUnitalStarSubalgebra R A where + __ := S + smul_mem' r _x hx := S.smul_mem hx r + +lemma one_mem_toNonUnitalStarSubalgebra (S : StarSubalgebra R A) : + 1 ∈ S.toNonUnitalStarSubalgebra := S.one_mem' + theorem mem_carrier {s : StarSubalgebra R A} {x : A} : x ∈ s.carrier ↔ x ∈ s := Iff.rfl @@ -436,6 +445,12 @@ lemma adjoin_eq_span (s : Set A) : Subalgebra.toSubmodule (adjoin R s).toSubalgebra = span R (Submonoid.closure (s ∪ star s)) := by rw [adjoin_toSubalgebra, Algebra.adjoin_eq_span] +open Submodule in +lemma adjoin_nonUnitalStarSubalgebra_eq_span (s : NonUnitalStarSubalgebra R A) : + (adjoin R (s : Set A)).toSubalgebra.toSubmodule = span R {1} ⊔ s.toSubmodule := by + rw [adjoin_eq_span, Submonoid.closure_eq_one_union, span_union, + ← NonUnitalStarAlgebra.adjoin_eq_span, NonUnitalStarAlgebra.adjoin_eq] + theorem _root_.Subalgebra.starClosure_eq_adjoin (S : Subalgebra R A) : S.starClosure = adjoin R (S : Set A) := le_antisymm (Subalgebra.starClosure_le_iff.2 <| subset_adjoin R (S : Set A)) @@ -562,10 +577,10 @@ instance adjoinCommRingOfIsStarNormal (R : Type u) {A : Type v} [CommRing R] [St CommRing (adjoin R ({x} : Set A)) := { (adjoin R ({x} : Set A)).toSubalgebra.toRing with mul_comm := mul_comm } -/-! ### Complete lattice structure -/ - end StarAlgebra +/-! ### Complete lattice structure -/ + namespace StarSubalgebra variable {F R A B : Type*} [CommSemiring R] [StarRing R] @@ -803,3 +818,34 @@ theorem StarAlgEquiv.restrictScalars_injective : show f.restrictScalars R x = g.restrictScalars R x from DFunLike.congr_fun h x end RestrictScalars + +variable {R A : Type*} [CommSemiring R] [StarRing R] [Semiring A] [StarRing A] [Algebra R A] + [StarModule R A] + +/-- Turn a non-unital star subalgebra containing `1` into a `StarSubalgebra`. -/ +def NonUnitalStarSubalgebra.toStarSubalgebra (S : NonUnitalStarSubalgebra R A) (h1 : 1 ∈ S) : + StarSubalgebra R A where + __ := S + one_mem' := h1 + algebraMap_mem' r := + (Algebra.algebraMap_eq_smul_one (R := R) (A := A) r).symm ▸ SMulMemClass.smul_mem r h1 + +lemma StarSubalgebra.toNonUnitalStarSubalgebra_toStarSubalgebra (S : StarSubalgebra R A) : + S.toNonUnitalStarSubalgebra.toStarSubalgebra S.one_mem' = S := by cases S; rfl + +lemma NonUnitalStarSubalgebra.toStarSubalgebra_toNonUnitalStarSubalgebra + (S : NonUnitalStarSubalgebra R A) (h1 : (1 : A) ∈ S) : + (S.toStarSubalgebra h1).toNonUnitalStarSubalgebra = S := by + cases S; rfl + +variable (R) + +lemma NonUnitalStarAlgebra.adjoin_le_starAlgebra_adjoin (s : Set A) : + adjoin R s ≤ (StarAlgebra.adjoin R s).toNonUnitalStarSubalgebra := + adjoin_le <| StarAlgebra.subset_adjoin R s + +lemma StarAlgebra.adjoin_nonUnitalStarSubalgebra (s : Set A) : + adjoin R (NonUnitalStarAlgebra.adjoin R s : Set A) = adjoin R s := + le_antisymm + (adjoin_le <| NonUnitalStarAlgebra.adjoin_le_starAlgebra_adjoin R s) + (adjoin_le <| (NonUnitalStarAlgebra.subset_adjoin R s).trans <| subset_adjoin R _) diff --git a/Mathlib/RingTheory/Adjoin/Basic.lean b/Mathlib/RingTheory/Adjoin/Basic.lean index 7d4037bf5b2d6..01f1f94e0dfda 100644 --- a/Mathlib/RingTheory/Adjoin/Basic.lean +++ b/Mathlib/RingTheory/Adjoin/Basic.lean @@ -393,6 +393,11 @@ theorem pow_smul_mem_adjoin_smul (r : R) (s : Set A) {x : A} (hx : x ∈ adjoin ∃ n₀ : ℕ, ∀ n ≥ n₀, r ^ n • x ∈ adjoin R (r • s) := pow_smul_mem_of_smul_subset_of_mem_adjoin r s _ subset_adjoin hx (Subalgebra.algebraMap_mem _ _) +lemma adjoin_nonUnitalSubalgebra_eq_span (s : NonUnitalSubalgebra R A) : + Subalgebra.toSubmodule (adjoin R (s : Set A)) = span R {1} ⊔ s.toSubmodule := by + rw [adjoin_eq_span, Submonoid.closure_eq_one_union, span_union, ← NonUnitalAlgebra.adjoin_eq_span, + NonUnitalAlgebra.adjoin_eq] + end CommSemiring section Ring @@ -542,6 +547,20 @@ theorem Algebra.restrictScalars_adjoin_of_algEquiv end +section CommSemiring +variable (R) [CommSemiring R] [Ring A] [Algebra R A] [Ring B] [Algebra R B] + +lemma NonUnitalAlgebra.adjoin_le_algebra_adjoin (s : Set A) : + adjoin R s ≤ (Algebra.adjoin R s).toNonUnitalSubalgebra := adjoin_le Algebra.subset_adjoin + +lemma Algebra.adjoin_nonUnitalSubalgebra (s : Set A) : + adjoin R (NonUnitalAlgebra.adjoin R s : Set A) = adjoin R s := + le_antisymm + (adjoin_le <| NonUnitalAlgebra.adjoin_le_algebra_adjoin R s) + (adjoin_le <| (NonUnitalAlgebra.subset_adjoin R).trans subset_adjoin) + +end CommSemiring + namespace Subalgebra variable [CommSemiring R] [Ring A] [Algebra R A] [Ring B] [Algebra R B] diff --git a/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean b/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean index 9e88d03fbe726..130db30e6a031 100644 --- a/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean +++ b/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison, Heather Macbeth -/ -import Mathlib.Algebra.Algebra.Subalgebra.Unitization import Mathlib.Analysis.RCLike.Basic import Mathlib.Topology.Algebra.StarSubalgebra import Mathlib.Topology.ContinuousMap.ContinuousMapZero @@ -44,6 +43,7 @@ on non-compact spaces. -/ +assert_not_exists Unitization noncomputable section From 607d79801433180781f7bf13c0b064388969105a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Sun, 12 Jan 2025 21:12:02 +0000 Subject: [PATCH 178/681] refactor(SetTheory/Ordinal/NaturalOps): redefine natural addition without `blsub` (#19236) This is progress towards deprecating `Ordinal.blsub` (and `Ordinal.lsub`) altogether. --- Mathlib/SetTheory/Game/Birthday.lean | 19 ++--- Mathlib/SetTheory/Ordinal/Arithmetic.lean | 5 ++ Mathlib/SetTheory/Ordinal/Basic.lean | 9 ++- Mathlib/SetTheory/Ordinal/NaturalOps.lean | 86 +++++++++++++---------- 4 files changed, 74 insertions(+), 45 deletions(-) diff --git a/Mathlib/SetTheory/Game/Birthday.lean b/Mathlib/SetTheory/Game/Birthday.lean index 09a00361b6f86..f25e8c1fa8208 100644 --- a/Mathlib/SetTheory/Game/Birthday.lean +++ b/Mathlib/SetTheory/Game/Birthday.lean @@ -131,9 +131,9 @@ theorem neg_birthday_le : -x.birthday.toPGame ≤ x := by simpa only [birthday_neg, ← neg_le_iff] using le_birthday (-x) @[simp] -theorem birthday_add : ∀ x y : PGame, (x + y).birthday = x.birthday ♯ y.birthday +theorem birthday_add : ∀ x y : PGame.{u}, (x + y).birthday = x.birthday ♯ y.birthday | ⟨xl, xr, xL, xR⟩, ⟨yl, yr, yL, yR⟩ => by - rw [birthday_def, nadd_def, lsub_sum, lsub_sum] + rw [birthday_def, nadd, lsub_sum, lsub_sum] simp only [mk_add_moveLeft_inl, mk_add_moveLeft_inr, mk_add_moveRight_inl, mk_add_moveRight_inr, moveLeft_mk, moveRight_mk] -- Porting note: Originally `simp only [birthday_add]`, but this causes an error in @@ -145,13 +145,16 @@ theorem birthday_add : ∀ x y : PGame, (x + y).birthday = x.birthday ♯ y.birt rw [max_max_max_comm] congr <;> apply le_antisymm any_goals - exact - max_le_iff.2 - ⟨lsub_le_iff.2 fun i => lt_blsub _ _ (birthday_moveLeft_lt _), - lsub_le_iff.2 fun i => lt_blsub _ _ (birthday_moveRight_lt _)⟩ + refine max_le_iff.2 ⟨?_, ?_⟩ + all_goals + refine lsub_le_iff.2 fun i ↦ ?_ + rw [← Order.succ_le_iff] + refine Ordinal.le_iSup (fun _ : Set.Iio _ ↦ _) ⟨_, ?_⟩ + apply_rules [birthday_moveLeft_lt, birthday_moveRight_lt] all_goals - refine blsub_le_iff.2 fun i hi => ?_ - rcases lt_birthday_iff.1 hi with (⟨j, hj⟩ | ⟨j, hj⟩) + rw [Ordinal.iSup_le_iff] + rintro ⟨i, hi⟩ + obtain ⟨j, hj⟩ | ⟨j, hj⟩ := lt_birthday_iff.1 hi <;> rw [Order.succ_le_iff] · exact lt_max_of_lt_left ((nadd_le_nadd_right hj _).trans_lt (lt_lsub _ _)) · exact lt_max_of_lt_right ((nadd_le_nadd_right hj _).trans_lt (lt_lsub _ _)) · exact lt_max_of_lt_left ((nadd_le_nadd_left hj _).trans_lt (lt_lsub _ _)) diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 130cd19bed83e..c2e154cef7e9e 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -1356,6 +1356,11 @@ theorem sup_eq_of_range_eq {ι : Type u} {ι' : Type v} (h : Set.range f = Set.range g) : sup.{u, max v w} f = sup.{v, max u w} g := Ordinal.iSup_eq_of_range_eq h +theorem iSup_succ (o : Ordinal) : ⨆ a : Iio o, succ a.1 = o := by + apply (le_of_forall_lt _).antisymm' + · simp [Ordinal.iSup_le_iff] + · exact fun a ha ↦ (lt_succ a).trans_le <| Ordinal.le_iSup (fun x : Iio _ ↦ _) ⟨a, ha⟩ + -- TODO: generalize to conditionally complete lattices theorem iSup_sum {α β} (f : α ⊕ β → Ordinal.{u}) [Small.{u} α] [Small.{u} β]: iSup f = max (⨆ a, f (Sum.inl a)) (⨆ b, f (Sum.inr b)) := by diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 124a76a047b7c..d2a8aebee9c3b 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -357,6 +357,9 @@ instance : OrderBot Ordinal where theorem bot_eq_zero : (⊥ : Ordinal) = 0 := rfl +instance instIsEmptyIioZero : IsEmpty (Iio (0 : Ordinal)) := by + simp [← bot_eq_zero] + @[simp] protected theorem le_zero {o : Ordinal} : o ≤ 0 ↔ o = 0 := le_bot_iff @@ -966,9 +969,13 @@ theorem natCast_succ (n : ℕ) : ↑n.succ = succ (n : Ordinal) := alias nat_cast_succ := natCast_succ instance uniqueIioOne : Unique (Iio (1 : Ordinal)) where - default := ⟨0, by simp⟩ + default := ⟨0, zero_lt_one' Ordinal⟩ uniq a := Subtype.ext <| lt_one_iff_zero.1 a.2 +@[simp] +theorem Iio_one_default_eq : (default : Iio (1 : Ordinal)) = ⟨0, zero_lt_one' Ordinal⟩ := + rfl + instance uniqueToTypeOne : Unique (toType 1) where default := enum (α := toType 1) (· < ·) ⟨0, by simp⟩ uniq a := by diff --git a/Mathlib/SetTheory/Ordinal/NaturalOps.lean b/Mathlib/SetTheory/Ordinal/NaturalOps.lean index 58624fce3613b..12e1b08b3c471 100644 --- a/Mathlib/SetTheory/Ordinal/NaturalOps.lean +++ b/Mathlib/SetTheory/Ordinal/NaturalOps.lean @@ -41,13 +41,12 @@ between both types, we attempt to prove and state most results on `Ordinal`. universe u v -open Function Order +open Function Order Set noncomputable section /-! ### Basic casts between `Ordinal` and `NatOrdinal` -/ - /-- A type synonym for ordinals with natural addition and multiplication. -/ def NatOrdinal : Type _ := -- Porting note: used to derive LinearOrder & SuccOrder but need to manually define @@ -180,9 +179,10 @@ to normal ordinal addition, it is commutative. Natural addition can equivalently be characterized as the ordinal resulting from adding up corresponding coefficients in the Cantor normal forms of `a` and `b`. -/ -noncomputable def nadd (a b : Ordinal) : Ordinal := - max (blsub.{u, u} a fun a' _ => nadd a' b) (blsub.{u, u} b fun b' _ => nadd a b') +noncomputable def nadd (a b : Ordinal.{u}) : Ordinal.{u} := + max (⨆ x : Iio a, succ (nadd x.1 b)) (⨆ x : Iio b, succ (nadd a x.1)) termination_by (a, b) +decreasing_by all_goals cases x; decreasing_tactic @[inherit_doc] scoped[NaturalOps] infixl:65 " ♯ " => Ordinal.nadd @@ -206,18 +206,13 @@ scoped[NaturalOps] infixl:70 " ⨳ " => Ordinal.nmul /-! ### Natural addition -/ - -theorem nadd_def (a b : Ordinal) : - a ♯ b = max (blsub.{u, u} a fun a' _ => a' ♯ b) (blsub.{u, u} b fun b' _ => a ♯ b') := by - rw [nadd] - theorem lt_nadd_iff : a < b ♯ c ↔ (∃ b' < b, a ≤ b' ♯ c) ∨ ∃ c' < c, a ≤ b ♯ c' := by - rw [nadd_def] - simp [lt_blsub_iff] + rw [nadd] + simp [Ordinal.lt_iSup_iff] theorem nadd_le_iff : b ♯ c ≤ a ↔ (∀ b' < b, b' ♯ c < a) ∧ ∀ c' < c, b ♯ c' < a := by - rw [nadd_def] - simp [blsub_le_iff] + rw [← not_lt, lt_nadd_iff] + simp theorem nadd_lt_nadd_left (h : b < c) (a) : a ♯ b < a ♯ c := lt_nadd_iff.2 (Or.inr ⟨b, h, le_rfl⟩) @@ -238,13 +233,13 @@ theorem nadd_le_nadd_right (h : b ≤ c) (a) : b ♯ a ≤ c ♯ a := by variable (a b) theorem nadd_comm (a b) : a ♯ b = b ♯ a := by - rw [nadd_def, nadd_def, max_comm] - congr <;> ext <;> apply nadd_comm + rw [nadd, nadd, max_comm] + congr <;> ext x <;> cases x <;> apply congr_arg _ (nadd_comm _ _) termination_by (a, b) +@[deprecated "blsub will soon be deprecated" (since := "2024-11-18")] theorem blsub_nadd_of_mono {f : ∀ c < a ♯ b, Ordinal.{max u v}} (hf : ∀ {i j} (hi hj), i ≤ j → f i hi ≤ f j hj) : - -- Porting note: needed to add universe hint blsub.{u,v} in the line below blsub.{u,v} _ f = max (blsub.{u, v} a fun a' ha' => f (a' ♯ b) <| nadd_lt_nadd_right ha' b) (blsub.{u, v} b fun b' hb' => f (a ♯ b') <| nadd_lt_nadd_left hb' a) := by @@ -258,30 +253,48 @@ theorem blsub_nadd_of_mono {f : ∀ c < a ♯ b, Ordinal.{max u v}} rintro c ⟨d, hd, rfl⟩ apply mem_brange_self +private theorem iSup_nadd_of_monotone {a b} (f : Ordinal.{u} → Ordinal.{u}) (h : Monotone f) : + ⨆ x : Iio (a ♯ b), f x = max (⨆ a' : Iio a, f (a'.1 ♯ b)) (⨆ b' : Iio b, f (a ♯ b'.1)) := by + apply (max_le _ _).antisymm' + · rw [Ordinal.iSup_le_iff] + rintro ⟨i, hi⟩ + obtain ⟨x, hx, hi⟩ | ⟨x, hx, hi⟩ := lt_nadd_iff.1 hi + · exact le_max_of_le_left ((h hi).trans <| Ordinal.le_iSup (fun x : Iio a ↦ _) ⟨x, hx⟩) + · exact le_max_of_le_right ((h hi).trans <| Ordinal.le_iSup (fun x : Iio b ↦ _) ⟨x, hx⟩) + all_goals + apply csSup_le_csSup' (bddAbove_of_small _) + rintro _ ⟨⟨c, hc⟩, rfl⟩ + refine mem_range_self (⟨_, ?_⟩ : Iio _) + apply_rules [nadd_lt_nadd_left, nadd_lt_nadd_right] + theorem nadd_assoc (a b c) : a ♯ b ♯ c = a ♯ (b ♯ c) := by - rw [nadd_def a (b ♯ c), nadd_def, blsub_nadd_of_mono, blsub_nadd_of_mono, max_assoc] - · congr <;> ext <;> apply nadd_assoc - · exact fun _ _ h => nadd_le_nadd_left h a - · exact fun _ _ h => nadd_le_nadd_right h c + unfold nadd + rw [iSup_nadd_of_monotone fun a' ↦ succ (a' ♯ c), iSup_nadd_of_monotone fun b' ↦ succ (a ♯ b'), + max_assoc] + · congr <;> ext x <;> cases x <;> apply congr_arg _ (nadd_assoc _ _ _) + · exact succ_mono.comp fun x y h ↦ nadd_le_nadd_left h _ + · exact succ_mono.comp fun x y h ↦ nadd_le_nadd_right h _ termination_by (a, b, c) @[simp] -theorem nadd_zero : a ♯ 0 = a := by - induction' a using Ordinal.induction with a IH - rw [nadd_def, blsub_zero, max_zero_right] - convert blsub_id a - rename_i hb - exact IH _ hb +theorem nadd_zero (a : Ordinal) : a ♯ 0 = a := by + rw [nadd, ciSup_of_empty fun _ : Iio 0 ↦ _, sup_bot_eq] + convert iSup_succ a + rename_i x + cases x + exact nadd_zero _ +termination_by a @[simp] theorem zero_nadd : 0 ♯ a = a := by rw [nadd_comm, nadd_zero] @[simp] -theorem nadd_one : a ♯ 1 = succ a := by - induction' a using Ordinal.induction with a IH - rw [nadd_def, blsub_one, nadd_zero, max_eq_right_iff, blsub_le_iff] - intro i hi - rwa [IH i hi, succ_lt_succ_iff] +theorem nadd_one (a : Ordinal) : a ♯ 1 = succ a := by + rw [nadd, ciSup_unique (s := fun _ : Iio 1 ↦ _), Iio_one_default_eq, nadd_zero, + max_eq_right_iff, Ordinal.iSup_le_iff] + rintro ⟨i, hi⟩ + rwa [nadd_one, succ_le_succ_iff, succ_le_iff] +termination_by a @[simp] theorem one_nadd : 1 ♯ a = succ a := by rw [nadd_comm, nadd_one] @@ -305,8 +318,9 @@ theorem add_le_nadd : a + b ≤ a ♯ b := by | H₂ c h => rwa [add_succ, nadd_succ, succ_le_succ_iff] | H₃ c hc H => - simp_rw [← IsNormal.blsub_eq.{u, u} (isNormal_add_right a) hc, blsub_le_iff] - exact fun i hi => (H i hi).trans_lt (nadd_lt_nadd_left hi a) + rw [(isNormal_add_right a).apply_of_isLimit hc, Ordinal.iSup_le_iff] + rintro ⟨i, hi⟩ + exact (H i hi).trans (nadd_le_nadd_left hi.le a) end Ordinal @@ -436,7 +450,6 @@ theorem nadd_right_comm : ∀ a b c, a ♯ b ♯ c = a ♯ c ♯ b := /-! ### Natural multiplication -/ - variable {a b c d : Ordinal.{u}} @[deprecated "avoid using the definition of `nmul` directly" (since := "2024-11-19")] @@ -697,8 +710,9 @@ theorem mul_le_nmul (a b : Ordinal.{u}) : a * b ≤ a ⨳ b := by · intro c hc H rcases eq_zero_or_pos a with (rfl | ha) · simp - · rw [← IsNormal.blsub_eq.{u, u} (isNormal_mul_right ha) hc, blsub_le_iff] - exact fun i hi => (H i hi).trans_lt (nmul_lt_nmul_of_pos_left hi ha) + · rw [(isNormal_mul_right ha).apply_of_isLimit hc, Ordinal.iSup_le_iff] + rintro ⟨i, hi⟩ + exact (H i hi).trans (nmul_le_nmul_left hi.le a) @[deprecated mul_le_nmul (since := "2024-08-20")] alias _root_.NatOrdinal.mul_le_nmul := mul_le_nmul From 065c4f76e302db8fac80f43ef501d5feb49b027e Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Sun, 12 Jan 2025 21:34:33 +0000 Subject: [PATCH 179/681] feat(Topology/Algebra/Module/ModuleTopology): finite products of modules. (#20453) From FLT. Binary and finite products of modules with the module topology also have the module topology. --- .../Algebra/Module/ModuleTopology.lean | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/Mathlib/Topology/Algebra/Module/ModuleTopology.lean b/Mathlib/Topology/Algebra/Module/ModuleTopology.lean index f3dbbdbc95f79..d93e0243f2c58 100644 --- a/Mathlib/Topology/Algebra/Module/ModuleTopology.lean +++ b/Mathlib/Topology/Algebra/Module/ModuleTopology.lean @@ -413,4 +413,83 @@ lemma _root_.ModuleTopology.eq_coinduced_of_surjective end surjection +section Prod + +variable {R : Type*} [TopologicalSpace R] [Semiring R] +variable {M : Type*} [AddCommMonoid M] [Module R M] [TopologicalSpace M] [IsModuleTopology R M] +variable {N : Type*} [AddCommMonoid N] [Module R N] [TopologicalSpace N] [IsModuleTopology R N] + +/-- The product of the module topologies for two modules over a topological ring +is the module topology. -/ +instance instProd : IsModuleTopology R (M × N) := by + constructor + have : ContinuousAdd M := toContinuousAdd R M + have : ContinuousAdd N := toContinuousAdd R N + -- In this proof, `M × N` always denotes the product with its *product* topology. + -- Addition `(M × N)² → M × N` and scalar multiplication `R × (M × N) → M × N` + -- are continuous for the product topology (by results in the library), so the module topology + -- on `M × N` is finer than the product topology (as it's the Inf of such topologies). + -- It thus remains to show that the product topology is finer than the module topology. + refine le_antisymm ?_ <| sInf_le ⟨Prod.continuousSMul, Prod.continuousAdd⟩ + -- Or equivalently, if `P` denotes `M × N` with the module topology, + let P := M × N + let τP : TopologicalSpace P := moduleTopology R P + have : IsModuleTopology R P := ⟨rfl⟩ + have : ContinuousAdd P := ModuleTopology.continuousAdd R P + -- and if `i` denotes the identity map from `M × N` to `P` + let i : M × N → P := id + -- then we need to show that `i` is continuous. + rw [← continuous_id_iff_le] + change @Continuous (M × N) P instTopologicalSpaceProd τP i + -- But `i` can be written as (m, n) ↦ (m, 0) + (0, n) + -- or equivalently as i₁ ∘ pr₁ + i₂ ∘ pr₂, where prᵢ are the projections, + -- the iⱼ's are linear inclusions M → P and N → P, and the addition is P × P → P. + let i₁ : M →ₗ[R] P := LinearMap.inl R M N + let i₂ : N →ₗ[R] P := LinearMap.inr R M N + rw [show (i : M × N → P) = + (fun abcd ↦ abcd.1 + abcd.2 : P × P → P) ∘ + (fun ab ↦ (i₁ ab.1,i₂ ab.2)) by + ext ⟨a, b⟩ <;> aesop] + -- and these maps are all continuous, hence `i` is too + fun_prop + +end Prod + +section Pi + +variable {R : Type*} [TopologicalSpace R] [Semiring R] +variable {ι : Type*} [Finite ι] {A : ι → Type*} [∀ i, AddCommMonoid (A i)] + [∀ i, Module R (A i)] [∀ i, TopologicalSpace (A i)] + [∀ i, IsModuleTopology R (A i)] + +/-- The product of the module topologies for a finite family of modules over a topological ring +is the module topology. -/ +instance instPi : IsModuleTopology R (∀ i, A i) := by + -- This is an easy induction on the size of the finite type, given the result + -- for binary products above. We use a "decategorified" induction principle for finite types. + induction ι using Finite.induction_empty_option + · -- invariance under equivalence of the finite type we're taking the product over + case of_equiv X Y e _ _ _ _ _ => + exact iso (ContinuousLinearEquiv.piCongrLeft R A e) + · -- empty case + infer_instance + · -- "inductive step" is to check for product over `Option ι` case when known for product over `ι` + case h_option ι _ hind _ _ _ _ => + -- `Option ι` is a `Sum` of `ι` and `Unit` + let e : Option ι ≃ ι ⊕ Unit := Equiv.optionEquivSumPUnit ι + -- so suffices to check for a product of modules over `ι ⊕ Unit` + suffices IsModuleTopology R ((i' : ι ⊕ Unit) → A (e.symm i')) from iso (.piCongrLeft R A e.symm) + -- but such a product is isomorphic to a binary product + -- of (product over `ι`) and (product over `Unit`) + suffices IsModuleTopology R + (((s : ι) → A (e.symm (Sum.inl s))) × ((t : Unit) → A (e.symm (Sum.inr t)))) from + iso (ContinuousLinearEquiv.sumPiEquivProdPi R ι Unit _).symm + -- The product over `ι` has the module topology by the inductive hypothesis, + -- and the product over `Unit` is just a module which is assumed to have the module topology + have := iso (ContinuousLinearEquiv.piUnique R (fun t ↦ A (e.symm (Sum.inr t)))).symm + -- so the result follows from the previous lemma (binary products). + infer_instance + +end Pi + end IsModuleTopology From 039d0c764222c952a7433440024a4adb1aaebaba Mon Sep 17 00:00:00 2001 From: Suzuka Yu <109365723+Yu-Misaka@users.noreply.github.com> Date: Sun, 12 Jan 2025 21:56:32 +0000 Subject: [PATCH 180/681] doc(Mathlib/Algebra/CharP/LinearMaps.lean): Fix doc errors (#20679) 1. Fix the doc-string of `Mathlib/Algebra/CharP/LinearMaps.lean`: the name `CharP_if` is outdated and is now corrected as `Module.charP_end`. 2. Express the condition of `Module.charP_end` in the term of torsion. --- Mathlib/Algebra/CharP/LinearMaps.lean | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Mathlib/Algebra/CharP/LinearMaps.lean b/Mathlib/Algebra/CharP/LinearMaps.lean index 36f3baf18a80d..93009eaa7324f 100644 --- a/Mathlib/Algebra/CharP/LinearMaps.lean +++ b/Mathlib/Algebra/CharP/LinearMaps.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Wanyi He, Huanyu Zheng -/ import Mathlib.Algebra.CharP.Algebra +import Mathlib.Algebra.Module.Torsion /-! # Characteristic of the ring of linear Maps @@ -12,10 +13,9 @@ The characteristic of the ring of linear maps is determined by its base ring. ## Main Results -- `CharP_if` : For a commutative semiring `R` and a `R`-module `M`, +- `Module.charP_end` : For a commutative semiring `R` and a `R`-module `M`, the characteristic of `R` is equal to the characteristic of the `R`-linear - endomorphisms of `M` when `M` contains an element `x` such that - `r • x = 0` implies `r = 0`. + endomorphisms of `M` when `M` contains a non-torsion element `x`. ## Notations @@ -26,7 +26,7 @@ The characteristic of the ring of linear maps is determined by its base ring. One can also deduce similar result via `charP_of_injective_ringHom` and `R → (M →ₗ[R] M) : r ↦ (fun (x : M) ↦ r • x)`. But this will require stronger condition - compared to `CharP_if`. + compared to `Module.charP_end`. -/ @@ -35,12 +35,14 @@ namespace Module variable {R M : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] /-- For a commutative semiring `R` and a `R`-module `M`, if `M` contains an - element `x` such that `r • x = 0` implies `r = 0` (finding such element usually - depends on specific `•`), then the characteristic of `R` is equal to the + element `x` that is not torsion, then the characteristic of `R` is equal to the characteristic of the `R`-linear endomorphisms of `M`.-/ theorem charP_end {p : ℕ} [hchar : CharP R p] - (hreduction : ∃ x : M, ∀ r : R, r • x = 0 → r = 0) : CharP (M →ₗ[R] M) p where + (htorsion : ∃ x : M, Ideal.torsionOf R M x = ⊥) : CharP (M →ₗ[R] M) p where cast_eq_zero_iff' n := by + have hreduction : ∃ x : M, ∀ r : R, r • x = 0 → r = 0 := + Exists.casesOn htorsion fun x hx ↦ + Exists.intro x fun r a ↦ (hx ▸ Ideal.mem_torsionOf_iff x r).mpr a have exact : (n : M →ₗ[R] M) = (n : R) • 1 := by simp only [Nat.cast_smul_eq_nsmul, nsmul_eq_mul, mul_one] rw [exact, LinearMap.ext_iff, ← hchar.1] From 666dd63743750d3bf814c328bd6a1c86ffb52c8e Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Mon, 13 Jan 2025 05:50:15 +0000 Subject: [PATCH 181/681] chore: split `Algebra/BigOperators/Group/{Multiset,Finset}` (#20629) Follow on from #20625. Keeps only what is possible with the minimal imports required for the definitions themselves in the `Defs` file, and everything else moves to `Lemmas`. Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> --- Archive/Imo/Imo2013Q1.lean | 2 +- .../InverseTriangleSum.lean | 2 +- Mathlib.lean | 6 +- .../Group/{Finset.lean => Finset/Basic.lean} | 687 +-------------- .../BigOperators/Group/Finset/Defs.lean | 787 ++++++++++++++++++ .../{Multiset.lean => Multiset/Basic.lean} | 80 +- .../BigOperators/Group/Multiset/Defs.lean | 114 +++ .../BigOperators/GroupWithZero/Action.lean | 2 +- .../BigOperators/GroupWithZero/Finset.lean | 2 +- Mathlib/Algebra/BigOperators/Intervals.lean | 2 +- .../Algebra/BigOperators/NatAntidiagonal.lean | 2 +- Mathlib/Algebra/BigOperators/Option.lean | 2 +- .../Algebra/BigOperators/Ring/Multiset.lean | 2 +- Mathlib/Algebra/BigOperators/Ring/Nat.lean | 2 +- Mathlib/Algebra/BigOperators/RingEquiv.lean | 2 +- Mathlib/Algebra/BigOperators/Sym.lean | 2 +- Mathlib/Algebra/BigOperators/WithTop.lean | 2 +- Mathlib/Algebra/GradedMonoid.lean | 2 +- Mathlib/Algebra/Group/EvenFunction.lean | 2 +- .../Algebra/Group/Pointwise/Finset/Basic.lean | 2 +- .../Group/Pointwise/Set/BigOperators.lean | 2 +- .../Algebra/Module/Submodule/LinearMap.lean | 2 +- .../Order/BigOperators/Group/Finset.lean | 2 +- .../BigOperators/Group/LocallyFinite.lean | 2 +- .../Order/BigOperators/Group/Multiset.lean | 2 +- .../BigOperators/GroupWithZero/Multiset.lean | 2 +- .../Order/BigOperators/Ring/Multiset.lean | 2 +- Mathlib/Algebra/Order/Rearrangement.lean | 2 +- Mathlib/Algebra/Regular/Pow.lean | 2 +- Mathlib/Algebra/Ring/SumsOfSquares.lean | 2 +- Mathlib/Algebra/Star/BigOperators.lean | 2 +- Mathlib/Algebra/Tropical/BigOperators.lean | 2 +- Mathlib/CategoryTheory/Preadditive/Basic.lean | 2 +- .../Preadditive/Biproducts.lean | 1 + .../Preadditive/FunctorCategory.lean | 1 + Mathlib/CategoryTheory/Preadditive/Mat.lean | 2 +- Mathlib/CategoryTheory/Subobject/Lattice.lean | 1 + .../Combinatorics/Additive/Dissociation.lean | 2 +- Mathlib/Combinatorics/HalesJewett.lean | 2 +- Mathlib/Combinatorics/Hindman.lean | 2 +- Mathlib/Combinatorics/SetFamily/Shatter.lean | 2 +- Mathlib/Data/Finset/NoncommProd.lean | 2 +- Mathlib/Data/Finset/Slice.lean | 2 +- Mathlib/Data/Finsupp/BigOperators.lean | 2 +- Mathlib/Data/Holor.lean | 2 +- Mathlib/Data/Multiset/Bind.lean | 2 +- Mathlib/Data/Multiset/Fintype.lean | 2 +- .../Data/Nat/Factorial/DoubleFactorial.lean | 2 +- Mathlib/Data/Nat/Fib/Basic.lean | 2 +- Mathlib/Data/Nat/GCD/BigOperators.lean | 2 +- Mathlib/Data/PNat/Factors.lean | 2 +- Mathlib/Data/Rat/BigOperators.lean | 2 +- Mathlib/Data/Sym/Card.lean | 2 +- Mathlib/Deprecated/Submonoid.lean | 3 +- Mathlib/Dynamics/BirkhoffSum/Basic.lean | 2 +- .../GroupTheory/Congruence/BigOperators.lean | 4 +- Mathlib/GroupTheory/QuotientGroup/Basic.lean | 2 +- Mathlib/LinearAlgebra/Lagrange.lean | 2 +- Mathlib/Logic/Godel/GodelBetaFunction.lean | 3 + Mathlib/MeasureTheory/Measure/AddContent.lean | 2 +- .../Order/Filter/AtTopBot/BigOperators.lean | 2 +- Mathlib/Order/LiminfLimsup.lean | 2 +- Mathlib/Order/Partition/Finpartition.lean | 2 +- Mathlib/RingTheory/Localization/Defs.lean | 2 +- Mathlib/RingTheory/Multiplicity.lean | 2 +- Mathlib/RingTheory/Prime.lean | 2 +- .../UniqueFactorizationDomain/Defs.lean | 2 +- Mathlib/Tactic/NormNum/BigOperators.lean | 2 +- MathlibTest/apply_congr.lean | 2 +- MathlibTest/linarith.lean | 2 +- MathlibTest/matrix.lean | 20 +- scripts/noshake.json | 4 +- 72 files changed, 990 insertions(+), 839 deletions(-) rename Mathlib/Algebra/BigOperators/Group/{Finset.lean => Finset/Basic.lean} (72%) create mode 100644 Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean rename Mathlib/Algebra/BigOperators/Group/{Multiset.lean => Multiset/Basic.lean} (76%) create mode 100644 Mathlib/Algebra/BigOperators/Group/Multiset/Defs.lean diff --git a/Archive/Imo/Imo2013Q1.lean b/Archive/Imo/Imo2013Q1.lean index 6cd9697d983b5..3cf4b58d25a83 100644 --- a/Archive/Imo/Imo2013Q1.lean +++ b/Archive/Imo/Imo2013Q1.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 David Renshaw. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Renshaw -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Order.Field.Rat import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.Positivity.Basic diff --git a/Archive/Wiedijk100Theorems/InverseTriangleSum.lean b/Archive/Wiedijk100Theorems/InverseTriangleSum.lean index af36acfaa873d..7e52e9cc53a95 100644 --- a/Archive/Wiedijk100Theorems/InverseTriangleSum.lean +++ b/Archive/Wiedijk100Theorems/InverseTriangleSum.lean @@ -3,7 +3,7 @@ Copyright (c) 2020. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jalex Stark, Yury Kudryashov -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Real.Basic import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.Ring diff --git a/Mathlib.lean b/Mathlib.lean index fbe165d18c5a3..7df6dee99bbc6 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -43,11 +43,13 @@ import Mathlib.Algebra.BigOperators.Expect import Mathlib.Algebra.BigOperators.Fin import Mathlib.Algebra.BigOperators.Finprod import Mathlib.Algebra.BigOperators.Finsupp -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic +import Mathlib.Algebra.BigOperators.Group.Finset.Defs import Mathlib.Algebra.BigOperators.Group.List.Basic import Mathlib.Algebra.BigOperators.Group.List.Defs import Mathlib.Algebra.BigOperators.Group.List.Lemmas -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Basic +import Mathlib.Algebra.BigOperators.Group.Multiset.Defs import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.Algebra.BigOperators.GroupWithZero.Finset import Mathlib.Algebra.BigOperators.Intervals diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset/Basic.lean similarity index 72% rename from Mathlib/Algebra/BigOperators/Group/Finset.lean rename to Mathlib/Algebra/BigOperators/Group/Finset/Basic.lean index 0a8f1edf33fc0..a83b1bce754f2 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Algebra.Group.Indicator +import Mathlib.Algebra.BigOperators.Group.Finset.Defs import Mathlib.Algebra.Group.Even import Mathlib.Data.Finset.Piecewise import Mathlib.Data.Finset.Powerset @@ -46,248 +47,15 @@ open Fin Function namespace Finset -/-- `∏ x ∈ s, f x` is the product of `f x` as `x` ranges over the elements of the finite set `s`. - -When the index type is a `Fintype`, the notation `∏ x, f x`, is a shorthand for -`∏ x ∈ Finset.univ, f x`. -/ -@[to_additive "`∑ x ∈ s, f x` is the sum of `f x` as `x` ranges over the elements -of the finite set `s`. - -When the index type is a `Fintype`, the notation `∑ x, f x`, is a shorthand for -`∑ x ∈ Finset.univ, f x`."] -protected def prod [CommMonoid β] (s : Finset α) (f : α → β) : β := - (s.1.map f).prod - -@[to_additive (attr := simp)] -theorem prod_mk [CommMonoid β] (s : Multiset α) (hs : s.Nodup) (f : α → β) : - (⟨s, hs⟩ : Finset α).prod f = (s.map f).prod := - rfl - -@[to_additive (attr := simp)] -theorem prod_val [CommMonoid α] (s : Finset α) : s.1.prod = s.prod id := by - rw [Finset.prod, Multiset.map_id] - -end Finset - -library_note "operator precedence of big operators"/-- -There is no established mathematical convention -for the operator precedence of big operators like `∏` and `∑`. -We will have to make a choice. - -Online discussions, such as https://math.stackexchange.com/q/185538/30839 -seem to suggest that `∏` and `∑` should have the same precedence, -and that this should be somewhere between `*` and `+`. -The latter have precedence levels `70` and `65` respectively, -and we therefore choose the level `67`. - -In practice, this means that parentheses should be placed as follows: -```lean -∑ k ∈ K, (a k + b k) = ∑ k ∈ K, a k + ∑ k ∈ K, b k → - ∏ k ∈ K, a k * b k = (∏ k ∈ K, a k) * (∏ k ∈ K, b k) -``` -(Example taken from page 490 of Knuth's *Concrete Mathematics*.) --/ - -namespace BigOperators -open Batteries.ExtendedBinder Lean Meta - --- TODO: contribute this modification back to `extBinder` - -/-- A `bigOpBinder` is like an `extBinder` and has the form `x`, `x : ty`, or `x pred` -where `pred` is a `binderPred` like `< 2`. -Unlike `extBinder`, `x` is a term. -/ -syntax bigOpBinder := term:max ((" : " term) <|> binderPred)? -/-- A BigOperator binder in parentheses -/ -syntax bigOpBinderParenthesized := " (" bigOpBinder ")" -/-- A list of parenthesized binders -/ -syntax bigOpBinderCollection := bigOpBinderParenthesized+ -/-- A single (unparenthesized) binder, or a list of parenthesized binders -/ -syntax bigOpBinders := bigOpBinderCollection <|> (ppSpace bigOpBinder) - -/-- Collects additional binder/Finset pairs for the given `bigOpBinder`. -Note: this is not extensible at the moment, unlike the usual `bigOpBinder` expansions. -/ -def processBigOpBinder (processed : (Array (Term × Term))) - (binder : TSyntax ``bigOpBinder) : MacroM (Array (Term × Term)) := - set_option hygiene false in - withRef binder do - match binder with - | `(bigOpBinder| $x:term) => - match x with - | `(($a + $b = $n)) => -- Maybe this is too cute. - return processed |>.push (← `(⟨$a, $b⟩), ← `(Finset.Nat.antidiagonal $n)) - | _ => return processed |>.push (x, ← ``(Finset.univ)) - | `(bigOpBinder| $x : $t) => return processed |>.push (x, ← ``((Finset.univ : Finset $t))) - | `(bigOpBinder| $x ∈ $s) => return processed |>.push (x, ← `(finset% $s)) - | `(bigOpBinder| $x < $n) => return processed |>.push (x, ← `(Finset.Iio $n)) - | `(bigOpBinder| $x ≤ $n) => return processed |>.push (x, ← `(Finset.Iic $n)) - | `(bigOpBinder| $x > $n) => return processed |>.push (x, ← `(Finset.Ioi $n)) - | `(bigOpBinder| $x ≥ $n) => return processed |>.push (x, ← `(Finset.Ici $n)) - | _ => Macro.throwUnsupported - -/-- Collects the binder/Finset pairs for the given `bigOpBinders`. -/ -def processBigOpBinders (binders : TSyntax ``bigOpBinders) : - MacroM (Array (Term × Term)) := - match binders with - | `(bigOpBinders| $b:bigOpBinder) => processBigOpBinder #[] b - | `(bigOpBinders| $[($bs:bigOpBinder)]*) => bs.foldlM processBigOpBinder #[] - | _ => Macro.throwUnsupported - -/-- Collect the binderIdents into a `⟨...⟩` expression. -/ -def bigOpBindersPattern (processed : (Array (Term × Term))) : - MacroM Term := do - let ts := processed.map Prod.fst - if ts.size == 1 then - return ts[0]! - else - `(⟨$ts,*⟩) - -/-- Collect the terms into a product of sets. -/ -def bigOpBindersProd (processed : (Array (Term × Term))) : - MacroM Term := do - if processed.isEmpty then - `((Finset.univ : Finset Unit)) - else if processed.size == 1 then - return processed[0]!.2 - else - processed.foldrM (fun s p => `(SProd.sprod $(s.2) $p)) processed.back!.2 - (start := processed.size - 1) - -/-- -- `∑ x, f x` is notation for `Finset.sum Finset.univ f`. It is the sum of `f x`, - where `x` ranges over the finite domain of `f`. -- `∑ x ∈ s, f x` is notation for `Finset.sum s f`. It is the sum of `f x`, - where `x` ranges over the finite set `s` (either a `Finset` or a `Set` with a `Fintype` instance). -- `∑ x ∈ s with p x, f x` is notation for `Finset.sum (Finset.filter p s) f`. -- `∑ (x ∈ s) (y ∈ t), f x y` is notation for `Finset.sum (s ×ˢ t) (fun ⟨x, y⟩ ↦ f x y)`. - -These support destructuring, for example `∑ ⟨x, y⟩ ∈ s ×ˢ t, f x y`. - -Notation: `"∑" bigOpBinders* ("with" term)? "," term` -/ -syntax (name := bigsum) "∑ " bigOpBinders ("with " term)? ", " term:67 : term - -/-- -- `∏ x, f x` is notation for `Finset.prod Finset.univ f`. It is the product of `f x`, - where `x` ranges over the finite domain of `f`. -- `∏ x ∈ s, f x` is notation for `Finset.prod s f`. It is the product of `f x`, - where `x` ranges over the finite set `s` (either a `Finset` or a `Set` with a `Fintype` instance). -- `∏ x ∈ s with p x, f x` is notation for `Finset.prod (Finset.filter p s) f`. -- `∏ (x ∈ s) (y ∈ t), f x y` is notation for `Finset.prod (s ×ˢ t) (fun ⟨x, y⟩ ↦ f x y)`. - -These support destructuring, for example `∏ ⟨x, y⟩ ∈ s ×ˢ t, f x y`. - -Notation: `"∏" bigOpBinders* ("with" term)? "," term` -/ -syntax (name := bigprod) "∏ " bigOpBinders ("with " term)? ", " term:67 : term - -macro_rules (kind := bigsum) - | `(∑ $bs:bigOpBinders $[with $p?]?, $v) => do - let processed ← processBigOpBinders bs - let x ← bigOpBindersPattern processed - let s ← bigOpBindersProd processed - match p? with - | some p => `(Finset.sum (Finset.filter (fun $x ↦ $p) $s) (fun $x ↦ $v)) - | none => `(Finset.sum $s (fun $x ↦ $v)) - -macro_rules (kind := bigprod) - | `(∏ $bs:bigOpBinders $[with $p?]?, $v) => do - let processed ← processBigOpBinders bs - let x ← bigOpBindersPattern processed - let s ← bigOpBindersProd processed - match p? with - | some p => `(Finset.prod (Finset.filter (fun $x ↦ $p) $s) (fun $x ↦ $v)) - | none => `(Finset.prod $s (fun $x ↦ $v)) - -/-- (Deprecated, use `∑ x ∈ s, f x`) -`∑ x in s, f x` is notation for `Finset.sum s f`. It is the sum of `f x`, -where `x` ranges over the finite set `s`. -/ -syntax (name := bigsumin) "∑ " extBinder " in " term ", " term:67 : term -macro_rules (kind := bigsumin) - | `(∑ $x:ident in $s, $r) => `(∑ $x:ident ∈ $s, $r) - | `(∑ $x:ident : $t in $s, $r) => `(∑ $x:ident ∈ ($s : Finset $t), $r) - -/-- (Deprecated, use `∏ x ∈ s, f x`) -`∏ x in s, f x` is notation for `Finset.prod s f`. It is the product of `f x`, -where `x` ranges over the finite set `s`. -/ -syntax (name := bigprodin) "∏ " extBinder " in " term ", " term:67 : term -macro_rules (kind := bigprodin) - | `(∏ $x:ident in $s, $r) => `(∏ $x:ident ∈ $s, $r) - | `(∏ $x:ident : $t in $s, $r) => `(∏ $x:ident ∈ ($s : Finset $t), $r) - -open Lean Meta Parser.Term PrettyPrinter.Delaborator SubExpr -open scoped Batteries.ExtendedBinder - -/-- Delaborator for `Finset.prod`. The `pp.piBinderTypes` option controls whether -to show the domain type when the product is over `Finset.univ`. -/ -@[app_delab Finset.prod] def delabFinsetProd : Delab := - whenPPOption getPPNotation <| withOverApp 5 <| do - let #[_, _, _, s, f] := (← getExpr).getAppArgs | failure - guard <| f.isLambda - let ppDomain ← getPPOption getPPPiBinderTypes - let (i, body) ← withAppArg <| withBindingBodyUnusedName fun i => do - return (i, ← delab) - if s.isAppOfArity ``Finset.univ 2 then - let binder ← - if ppDomain then - let ty ← withNaryArg 0 delab - `(bigOpBinder| $(.mk i):ident : $ty) - else - `(bigOpBinder| $(.mk i):ident) - `(∏ $binder:bigOpBinder, $body) - else - let ss ← withNaryArg 3 <| delab - `(∏ $(.mk i):ident ∈ $ss, $body) - -/-- Delaborator for `Finset.sum`. The `pp.piBinderTypes` option controls whether -to show the domain type when the sum is over `Finset.univ`. -/ -@[app_delab Finset.sum] def delabFinsetSum : Delab := - whenPPOption getPPNotation <| withOverApp 5 <| do - let #[_, _, _, s, f] := (← getExpr).getAppArgs | failure - guard <| f.isLambda - let ppDomain ← getPPOption getPPPiBinderTypes - let (i, body) ← withAppArg <| withBindingBodyUnusedName fun i => do - return (i, ← delab) - if s.isAppOfArity ``Finset.univ 2 then - let binder ← - if ppDomain then - let ty ← withNaryArg 0 delab - `(bigOpBinder| $(.mk i):ident : $ty) - else - `(bigOpBinder| $(.mk i):ident) - `(∑ $binder:bigOpBinder, $body) - else - let ss ← withNaryArg 3 <| delab - `(∑ $(.mk i):ident ∈ $ss, $body) - -end BigOperators - -namespace Finset - variable {s s₁ s₂ : Finset α} {a : α} {f g : α → β} -@[to_additive] -theorem prod_eq_multiset_prod [CommMonoid β] (s : Finset α) (f : α → β) : - ∏ x ∈ s, f x = (s.1.map f).prod := - rfl - -@[to_additive (attr := simp)] -lemma prod_map_val [CommMonoid β] (s : Finset α) (f : α → β) : (s.1.map f).prod = ∏ a ∈ s, f a := - rfl - @[to_additive] theorem prod_eq_fold [CommMonoid β] (s : Finset α) (f : α → β) : ∏ x ∈ s, f x = s.fold ((· * ·) : β → β → β) 1 f := rfl -@[simp] -theorem sum_multiset_singleton (s : Finset α) : (s.sum fun x => {x}) = s.val := by - simp only [sum_eq_multiset_sum, Multiset.sum_map_singleton] - end Finset -@[to_additive (attr := simp)] -theorem map_prod [CommMonoid β] [CommMonoid γ] {G : Type*} [FunLike G β γ] [MonoidHomClass G β γ] - (g : G) (f : α → β) (s : Finset α) : g (∏ x ∈ s, f x) = ∏ x ∈ s, g (f x) := by - simp only [Finset.prod_eq_multiset_prod, map_multiset_prod, Multiset.map_map]; rfl - @[to_additive] theorem MonoidHom.coe_finset_prod [MulOneClass β] [CommMonoid γ] (f : α → β →* γ) (s : Finset α) : ⇑(∏ x ∈ s, f x) = ∏ x ∈ s, ⇑(f x) := @@ -310,17 +78,6 @@ section CommMonoid variable [CommMonoid β] -@[to_additive (attr := simp)] -theorem prod_empty : ∏ x ∈ ∅, f x = 1 := - rfl - -@[to_additive] -theorem prod_of_isEmpty [IsEmpty α] (s : Finset α) : ∏ i ∈ s, f i = 1 := by - rw [eq_empty_of_isEmpty s, prod_empty] - -@[deprecated (since := "2024-06-11")] alias prod_of_empty := prod_of_isEmpty -@[deprecated (since := "2024-06-11")] alias sum_of_empty := sum_of_isEmpty - @[to_additive (attr := simp)] theorem prod_cons (h : a ∉ s) : ∏ x ∈ cons a s h, f x = f a * ∏ x ∈ s, f x := fold_cons h @@ -359,20 +116,11 @@ theorem prod_pair [DecidableEq α] {a b : α} (h : a ≠ b) : (∏ x ∈ ({a, b} : Finset α), f x) = f a * f b := by rw [prod_insert (not_mem_singleton.2 h), prod_singleton] -@[to_additive (attr := simp)] -theorem prod_const_one : (∏ _x ∈ s, (1 : β)) = 1 := by - simp only [Finset.prod, Multiset.map_const', Multiset.prod_replicate, one_pow] - @[to_additive (attr := simp)] theorem prod_image [DecidableEq α] {s : Finset γ} {g : γ → α} : (∀ x ∈ s, ∀ y ∈ s, g x = g y → x = y) → ∏ x ∈ s.image g, f x = ∏ x ∈ s, f (g x) := fold_image -@[to_additive (attr := simp)] -theorem prod_map (s : Finset α) (e : α ↪ γ) (f : γ → β) : - ∏ x ∈ s.map e, f x = ∏ x ∈ s, f (e x) := by - rw [Finset.prod, Finset.map_val, Multiset.map_map]; rfl - @[to_additive] lemma prod_attach (s : Finset α) (f : α → β) : ∏ x ∈ s.attach, f x = ∏ x ∈ s, f x := by classical rw [← prod_image Subtype.coe_injective.injOn, attach_image_val] @@ -432,26 +180,6 @@ theorem prod_filter_xor (p q : α → Prop) [DecidablePred p] [DecidablePred q] classical rw [← prod_union (disjoint_filter_and_not_filter _ _), ← filter_or] simp only [Xor'] -section ToList - -@[to_additive (attr := simp)] -theorem prod_to_list (s : Finset α) (f : α → β) : (s.toList.map f).prod = s.prod f := by - rw [Finset.prod, ← Multiset.prod_coe, ← Multiset.map_coe, Finset.coe_toList] - -end ToList - -@[to_additive] -theorem _root_.Equiv.Perm.prod_comp (σ : Equiv.Perm α) (s : Finset α) (f : α → β) - (hs : { a | σ a ≠ a } ⊆ s) : (∏ x ∈ s, f (σ x)) = ∏ x ∈ s, f x := by - convert (prod_map s σ.toEmbedding f).symm - exact (map_perm hs).symm - -@[to_additive] -theorem _root_.Equiv.Perm.prod_comp' (σ : Equiv.Perm α) (s : Finset α) (f : α → α → β) - (hs : { a | σ a ≠ a } ⊆ s) : (∏ x ∈ s, f (σ x) x) = ∏ x ∈ s, f x (σ.symm x) := by - convert σ.prod_comp s (fun x => f x (σ.symm x)) hs - rw [Equiv.symm_apply_apply] - /-- A product over all subsets of `s ∪ {x}` is obtained by multiplying the product over all subsets of `s`, and over all subsets of `s` to which one adds `x`. -/ @[to_additive "A sum over all subsets of `s ∪ {x}` is obtained by summing the sum over all subsets @@ -576,112 +304,6 @@ theorem prod_sigma' {σ : α → Type*} (s : Finset α) (t : ∀ a, Finset (σ a section bij variable {ι κ α : Type*} [CommMonoid α] {s : Finset ι} {t : Finset κ} {f : ι → α} {g : κ → α} -/-- Reorder a product. - -The difference with `Finset.prod_bij'` is that the bijection is specified as a surjective injection, -rather than by an inverse function. - -The difference with `Finset.prod_nbij` is that the bijection is allowed to use membership of the -domain of the product, rather than being a non-dependent function. -/ -@[to_additive "Reorder a sum. - -The difference with `Finset.sum_bij'` is that the bijection is specified as a surjective injection, -rather than by an inverse function. - -The difference with `Finset.sum_nbij` is that the bijection is allowed to use membership of the -domain of the sum, rather than being a non-dependent function."] -theorem prod_bij (i : ∀ a ∈ s, κ) (hi : ∀ a ha, i a ha ∈ t) - (i_inj : ∀ a₁ ha₁ a₂ ha₂, i a₁ ha₁ = i a₂ ha₂ → a₁ = a₂) - (i_surj : ∀ b ∈ t, ∃ a ha, i a ha = b) (h : ∀ a ha, f a = g (i a ha)) : - ∏ x ∈ s, f x = ∏ x ∈ t, g x := - congr_arg Multiset.prod (Multiset.map_eq_map_of_bij_of_nodup f g s.2 t.2 i hi i_inj i_surj h) - -/-- Reorder a product. - -The difference with `Finset.prod_bij` is that the bijection is specified with an inverse, rather -than as a surjective injection. - -The difference with `Finset.prod_nbij'` is that the bijection and its inverse are allowed to use -membership of the domains of the products, rather than being non-dependent functions. -/ -@[to_additive "Reorder a sum. - -The difference with `Finset.sum_bij` is that the bijection is specified with an inverse, rather than -as a surjective injection. - -The difference with `Finset.sum_nbij'` is that the bijection and its inverse are allowed to use -membership of the domains of the sums, rather than being non-dependent functions."] -theorem prod_bij' (i : ∀ a ∈ s, κ) (j : ∀ a ∈ t, ι) (hi : ∀ a ha, i a ha ∈ t) - (hj : ∀ a ha, j a ha ∈ s) (left_inv : ∀ a ha, j (i a ha) (hi a ha) = a) - (right_inv : ∀ a ha, i (j a ha) (hj a ha) = a) (h : ∀ a ha, f a = g (i a ha)) : - ∏ x ∈ s, f x = ∏ x ∈ t, g x := by - refine prod_bij i hi (fun a1 h1 a2 h2 eq ↦ ?_) (fun b hb ↦ ⟨_, hj b hb, right_inv b hb⟩) h - rw [← left_inv a1 h1, ← left_inv a2 h2] - simp only [eq] - -/-- Reorder a product. - -The difference with `Finset.prod_nbij'` is that the bijection is specified as a surjective -injection, rather than by an inverse function. - -The difference with `Finset.prod_bij` is that the bijection is a non-dependent function, rather than -being allowed to use membership of the domain of the product. -/ -@[to_additive "Reorder a sum. - -The difference with `Finset.sum_nbij'` is that the bijection is specified as a surjective injection, -rather than by an inverse function. - -The difference with `Finset.sum_bij` is that the bijection is a non-dependent function, rather than -being allowed to use membership of the domain of the sum."] -lemma prod_nbij (i : ι → κ) (hi : ∀ a ∈ s, i a ∈ t) (i_inj : (s : Set ι).InjOn i) - (i_surj : (s : Set ι).SurjOn i t) (h : ∀ a ∈ s, f a = g (i a)) : - ∏ x ∈ s, f x = ∏ x ∈ t, g x := - prod_bij (fun a _ ↦ i a) hi i_inj (by simpa using i_surj) h - -/-- Reorder a product. - -The difference with `Finset.prod_nbij` is that the bijection is specified with an inverse, rather -than as a surjective injection. - -The difference with `Finset.prod_bij'` is that the bijection and its inverse are non-dependent -functions, rather than being allowed to use membership of the domains of the products. - -The difference with `Finset.prod_equiv` is that bijectivity is only required to hold on the domains -of the products, rather than on the entire types. --/ -@[to_additive "Reorder a sum. - -The difference with `Finset.sum_nbij` is that the bijection is specified with an inverse, rather -than as a surjective injection. - -The difference with `Finset.sum_bij'` is that the bijection and its inverse are non-dependent -functions, rather than being allowed to use membership of the domains of the sums. - -The difference with `Finset.sum_equiv` is that bijectivity is only required to hold on the domains -of the sums, rather than on the entire types."] -lemma prod_nbij' (i : ι → κ) (j : κ → ι) (hi : ∀ a ∈ s, i a ∈ t) (hj : ∀ a ∈ t, j a ∈ s) - (left_inv : ∀ a ∈ s, j (i a) = a) (right_inv : ∀ a ∈ t, i (j a) = a) - (h : ∀ a ∈ s, f a = g (i a)) : ∏ x ∈ s, f x = ∏ x ∈ t, g x := - prod_bij' (fun a _ ↦ i a) (fun b _ ↦ j b) hi hj left_inv right_inv h - -/-- Specialization of `Finset.prod_nbij'` that automatically fills in most arguments. - -See `Fintype.prod_equiv` for the version where `s` and `t` are `univ`. -/ -@[to_additive "`Specialization of `Finset.sum_nbij'` that automatically fills in most arguments. - -See `Fintype.sum_equiv` for the version where `s` and `t` are `univ`."] -lemma prod_equiv (e : ι ≃ κ) (hst : ∀ i, i ∈ s ↔ e i ∈ t) (hfg : ∀ i ∈ s, f i = g (e i)) : - ∏ i ∈ s, f i = ∏ i ∈ t, g i := by refine prod_nbij' e e.symm ?_ ?_ ?_ ?_ hfg <;> simp [hst] - -/-- Specialization of `Finset.prod_bij` that automatically fills in most arguments. - -See `Fintype.prod_bijective` for the version where `s` and `t` are `univ`. -/ -@[to_additive "`Specialization of `Finset.sum_bij` that automatically fills in most arguments. - -See `Fintype.sum_bijective` for the version where `s` and `t` are `univ`."] -lemma prod_bijective (e : ι → κ) (he : e.Bijective) (hst : ∀ i, i ∈ s ↔ e i ∈ t) - (hfg : ∀ i ∈ s, f i = g (e i)) : - ∏ i ∈ s, f i = ∏ i ∈ t, g i := prod_equiv (.ofBijective e he) hst hfg - @[to_additive] lemma prod_of_injOn (e : ι → κ) (he : Set.InjOn e s) (hest : Set.MapsTo e s t) (h' : ∀ i ∈ t, i ∉ e '' s → g i = 1) (h : ∀ i ∈ s, f i = g (e i)) : @@ -845,13 +467,6 @@ theorem prod_comm {s : Finset γ} {t : Finset α} {f : γ → α → β} : (∏ x ∈ s, ∏ y ∈ t, f x y) = ∏ y ∈ t, ∏ x ∈ s, f x y := prod_comm' fun _ _ => Iff.rfl -@[to_additive] -theorem prod_hom_rel [CommMonoid γ] {r : β → γ → Prop} {f : α → β} {g : α → γ} {s : Finset α} - (h₁ : r 1 1) (h₂ : ∀ a b c, r b c → r (f a * b) (g a * c)) : - r (∏ x ∈ s, f x) (∏ x ∈ s, g x) := by - delta Finset.prod - apply Multiset.prod_hom_rel <;> assumption - @[to_additive] theorem prod_filter_of_ne {p : α → Prop} [DecidablePred p] (hp : ∀ x ∈ s, f x ≠ 1 → p x) : ∏ x ∈ s with p x, f x = ∏ x ∈ s, f x := @@ -977,10 +592,6 @@ theorem prod_subtype_map_embedding {p : α → Prop} {s : Finset { x // p x }} { variable (f s) -@[to_additive] -theorem prod_coe_sort_eq_attach (f : s → β) : ∏ i : s, f i = ∏ i ∈ s.attach, f i := - rfl - @[to_additive] theorem prod_coe_sort : ∏ i : s, f i = ∏ i ∈ s, f i := prod_attach _ _ @@ -1181,22 +792,6 @@ theorem prod_ite_eq_of_mem' [DecidableEq α] (s : Finset α) (a : α) (b : α (∏ x ∈ s, if x = a then b x else 1) = b a := by simp only [prod_ite_eq', if_pos h] -@[to_additive] -theorem prod_ite_index (p : Prop) [Decidable p] (s t : Finset α) (f : α → β) : - ∏ x ∈ if p then s else t, f x = if p then ∏ x ∈ s, f x else ∏ x ∈ t, f x := - apply_ite (fun s => ∏ x ∈ s, f x) _ _ _ - -@[to_additive (attr := simp)] -theorem prod_ite_irrel (p : Prop) [Decidable p] (s : Finset α) (f g : α → β) : - ∏ x ∈ s, (if p then f x else g x) = if p then ∏ x ∈ s, f x else ∏ x ∈ s, g x := by - split_ifs with h <;> rfl - -@[to_additive (attr := simp)] -theorem prod_dite_irrel (p : Prop) [Decidable p] (s : Finset α) (f : p → α → β) (g : ¬p → α → β) : - ∏ x ∈ s, (if h : p then f h x else g h x) = - if h : p then ∏ x ∈ s, f h x else ∏ x ∈ s, g h x := by - split_ifs with h <;> rfl - @[to_additive (attr := simp)] theorem prod_pi_mulSingle' [DecidableEq α] (a : α) (x : β) (s : Finset α) : ∏ a' ∈ s, Pi.mulSingle a x a' = if a ∈ s then x else 1 := @@ -1313,10 +908,6 @@ theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ · refine (fun a ha => (mem_filter.mp ha).elim fun h₁ h₂ ↦ ?_) exact h a h₁ fun H ↦ by rw [H] at h₂; simp at h₂ -@[to_additive] -theorem nonempty_of_prod_ne_one (h : ∏ x ∈ s, f x ≠ 1) : s.Nonempty := - s.eq_empty_or_nonempty.elim (fun H => False.elim <| h <| H.symm ▸ prod_empty) id - @[to_additive] theorem exists_ne_one_of_prod_ne_one (h : ∏ x ∈ s, f x ≠ 1) : ∃ a ∈ s, f a ≠ 1 := by classical @@ -1361,9 +952,6 @@ theorem prod_range_add_div_prod_range {α : Type*} [CommGroup α] (f : ℕ → (∏ k ∈ range (n + m), f k) / ∏ k ∈ range n, f k = ∏ k ∈ Finset.range m, f (n + k) := div_eq_of_eq_mul' (prod_range_add f n m) -@[to_additive] -theorem prod_range_zero (f : ℕ → β) : ∏ k ∈ range 0, f k = 1 := by rw [range_zero, prod_empty] - @[to_additive sum_range_one] theorem prod_range_one (f : ℕ → β) : ∏ k ∈ range 1, f k = f 0 := by rw [range_one, prod_singleton] @@ -1402,10 +990,6 @@ theorem prod_list_count_of_subset [DecidableEq α] [CommMonoid α] (m : List α) rw [mem_toFinset] at hx rw [count_eq_zero_of_not_mem hx, pow_zero] -theorem sum_filter_count_eq_countP [DecidableEq α] (p : α → Prop) [DecidablePred p] (l : List α) : - ∑ x ∈ l.toFinset with p x, l.count x = l.countP p := by - simp [Finset.sum, sum_map_count_dedup_filter_eq_countP p l] - open Multiset @[to_additive] @@ -1428,31 +1012,6 @@ theorem prod_multiset_count_of_subset [DecidableEq α] [CommMonoid α] (m : Mult simp only [quot_mk_to_coe'', prod_coe, coe_count] apply prod_list_count_of_subset l s -@[to_additive] -theorem prod_mem_multiset [DecidableEq α] (m : Multiset α) (f : { x // x ∈ m } → β) (g : α → β) - (hfg : ∀ x, f x = g x) : ∏ x : { x // x ∈ m }, f x = ∏ x ∈ m.toFinset, g x := by - refine prod_bij' (fun x _ ↦ x) (fun x hx ↦ ⟨x, Multiset.mem_toFinset.1 hx⟩) ?_ ?_ ?_ ?_ ?_ <;> - simp [hfg] - -/-- To prove a property of a product, it suffices to prove that -the property is multiplicative and holds on factors. -/ -@[to_additive "To prove a property of a sum, it suffices to prove that -the property is additive and holds on summands."] -theorem prod_induction {M : Type*} [CommMonoid M] (f : α → M) (p : M → Prop) - (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ s, p <| f x) : - p <| ∏ x ∈ s, f x := - Multiset.prod_induction _ _ hom unit (Multiset.forall_mem_map_iff.mpr base) - -/-- To prove a property of a product, it suffices to prove that -the property is multiplicative and holds on factors. -/ -@[to_additive "To prove a property of a sum, it suffices to prove that -the property is additive and holds on summands."] -theorem prod_induction_nonempty {M : Type*} [CommMonoid M] (f : α → M) (p : M → Prop) - (hom : ∀ a b, p a → p b → p (a * b)) (nonempty : s.Nonempty) (base : ∀ x ∈ s, p <| f x) : - p <| ∏ x ∈ s, f x := - Multiset.prod_induction_nonempty p hom (by simp [nonempty_iff_ne_empty.mp nonempty]) - (Multiset.forall_mem_map_iff.mpr base) - /-- For any product along `{0, ..., n - 1}` of a commutative-monoid-valued function, we can verify that it's equal to a different function just by checking ratios of adjacent terms. @@ -1529,10 +1088,6 @@ theorem prod_mul_pow_card {b : β} : (∏ a ∈ s, f a) * b ^ #s = ∏ a ∈ s, @[to_additive] theorem pow_eq_prod_const (b : β) : ∀ n, b ^ n = ∏ _k ∈ range n, b := by simp -@[to_additive] -theorem prod_pow (s : Finset α) (n : ℕ) (f : α → β) : ∏ x ∈ s, f x ^ n = (∏ x ∈ s, f x) ^ n := - Multiset.prod_map_pow - @[to_additive sum_nsmul_assoc] lemma prod_pow_eq_pow_sum (s : Finset ι) (f : ι → ℕ) (a : β) : ∏ i ∈ s, a ^ f i = a ^ ∑ i ∈ s, f i := @@ -1764,10 +1319,6 @@ theorem prod_dvd_prod_of_dvd {S : Finset α} (g1 g2 : α → β) (h : ∀ a ∈ rw [Finset.forall_mem_cons] at h exact mul_dvd_mul h.1 <| IH h.2 -theorem prod_dvd_prod_of_subset {ι M : Type*} [CommMonoid M] (s t : Finset ι) (f : ι → M) - (h : s ⊆ t) : (∏ i ∈ s, f i) ∣ ∏ i ∈ t, f i := - Multiset.prod_dvd_prod_of_le <| Multiset.map_le_map <| by simpa - @[to_additive] lemma prod_mul_eq_prod_mul_of_exists {s : Finset α} {f : α → β} {b₁ b₂ : β} (a : α) (ha : a ∈ s) (h : f a * b₁ = f a * b₂) : @@ -1820,41 +1371,6 @@ lemma sum_card_fiberwise_eq_card_filter {κ : Type*} [DecidableEq κ] (s : Finse lemma card_filter (p) [DecidablePred p] (s : Finset ι) : #{i ∈ s | p i} = ∑ i ∈ s, ite (p i) 1 0 := by simp [sum_ite] -section Opposite - -open MulOpposite - -/-- Moving to the opposite additive commutative monoid commutes with summing. -/ -@[simp] -theorem op_sum [AddCommMonoid β] {s : Finset α} (f : α → β) : - op (∑ x ∈ s, f x) = ∑ x ∈ s, op (f x) := - map_sum (opAddEquiv : β ≃+ βᵐᵒᵖ) _ _ - -@[simp] -theorem unop_sum [AddCommMonoid β] {s : Finset α} (f : α → βᵐᵒᵖ) : - unop (∑ x ∈ s, f x) = ∑ x ∈ s, unop (f x) := - map_sum (opAddEquiv : β ≃+ βᵐᵒᵖ).symm _ _ - -end Opposite - -section DivisionCommMonoid - -variable [DivisionCommMonoid β] - -@[to_additive (attr := simp)] -theorem prod_inv_distrib : (∏ x ∈ s, (f x)⁻¹) = (∏ x ∈ s, f x)⁻¹ := - Multiset.prod_map_inv - -@[to_additive (attr := simp)] -theorem prod_div_distrib : ∏ x ∈ s, f x / g x = (∏ x ∈ s, f x) / ∏ x ∈ s, g x := - Multiset.prod_map_div - -@[to_additive] -theorem prod_zpow (f : α → β) (s : Finset α) (n : ℤ) : ∏ a ∈ s, f a ^ n = (∏ a ∈ s, f a) ^ n := - Multiset.prod_map_zpow - -end DivisionCommMonoid - section CommGroup variable [CommGroup β] [DecidableEq α] @@ -1918,22 +1434,6 @@ theorem prod_unique_nonempty {α β : Type*} [CommMonoid β] [Unique α] (s : Fi (h : s.Nonempty) : ∏ x ∈ s, f x = f default := by rw [h.eq_singleton_default, Finset.prod_singleton] -theorem sum_nat_mod (s : Finset α) (n : ℕ) (f : α → ℕ) : - (∑ i ∈ s, f i) % n = (∑ i ∈ s, f i % n) % n := - (Multiset.sum_nat_mod _ _).trans <| by rw [Finset.sum, Multiset.map_map]; rfl - -theorem prod_nat_mod (s : Finset α) (n : ℕ) (f : α → ℕ) : - (∏ i ∈ s, f i) % n = (∏ i ∈ s, f i % n) % n := - (Multiset.prod_nat_mod _ _).trans <| by rw [Finset.prod, Multiset.map_map]; rfl - -theorem sum_int_mod (s : Finset α) (n : ℤ) (f : α → ℤ) : - (∑ i ∈ s, f i) % n = (∑ i ∈ s, f i % n) % n := - (Multiset.sum_int_mod _ _).trans <| by rw [Finset.sum, Multiset.map_map]; rfl - -theorem prod_int_mod (s : Finset α) (n : ℤ) (f : α → ℤ) : - (∏ i ∈ s, f i) % n = (∏ i ∈ s, f i % n) % n := - (Multiset.prod_int_mod _ _).trans <| by rw [Finset.prod, Multiset.map_map]; rfl - end Finset namespace Fintype @@ -1944,39 +1444,6 @@ open Finset section CommMonoid variable [CommMonoid α] -/-- `Fintype.prod_bijective` is a variant of `Finset.prod_bij` that accepts `Function.Bijective`. - -See `Function.Bijective.prod_comp` for a version without `h`. -/ -@[to_additive "`Fintype.sum_bijective` is a variant of `Finset.sum_bij` that accepts -`Function.Bijective`. - -See `Function.Bijective.sum_comp` for a version without `h`. "] -lemma prod_bijective (e : ι → κ) (he : e.Bijective) (f : ι → α) (g : κ → α) - (h : ∀ x, f x = g (e x)) : ∏ x, f x = ∏ x, g x := - prod_equiv (.ofBijective e he) (by simp) (by simp [h]) - -@[to_additive] alias _root_.Function.Bijective.finset_prod := prod_bijective - -/-- `Fintype.prod_equiv` is a specialization of `Finset.prod_bij` that -automatically fills in most arguments. - -See `Equiv.prod_comp` for a version without `h`. --/ -@[to_additive "`Fintype.sum_equiv` is a specialization of `Finset.sum_bij` that -automatically fills in most arguments. - -See `Equiv.sum_comp` for a version without `h`."] -lemma prod_equiv (e : ι ≃ κ) (f : ι → α) (g : κ → α) (h : ∀ x, f x = g (e x)) : - ∏ x, f x = ∏ x, g x := prod_bijective _ e.bijective _ _ h - -@[to_additive] -lemma _root_.Function.Bijective.prod_comp {e : ι → κ} (he : e.Bijective) (g : κ → α) : - ∏ i, g (e i) = ∏ i, g i := prod_bijective _ he _ _ fun _ ↦ rfl - -@[to_additive] -lemma _root_.Equiv.prod_comp (e : ι ≃ κ) (g : κ → α) : ∏ i, g (e i) = ∏ i, g i := - prod_equiv e _ _ fun _ ↦ rfl - @[to_additive] lemma prod_of_injective (e : ι → κ) (he : Injective e) (f : ι → α) (g : κ → α) (h' : ∀ i ∉ Set.range e, g i = 1) (h : ∀ i, f i = g (e i)) : ∏ i, f i = ∏ j, g j := @@ -2000,11 +1467,6 @@ lemma prod_fiberwise' [DecidableEq κ] (g : ι → κ) (f : κ → α) : theorem prod_unique {α β : Type*} [CommMonoid β] [Unique α] [Fintype α] (f : α → β) : ∏ x : α, f x = f default := by rw [univ_unique, prod_singleton] -@[to_additive] -theorem prod_empty {α β : Type*} [CommMonoid β] [IsEmpty α] [Fintype α] (f : α → β) : - ∏ x : α, f x = 1 := - Finset.prod_of_isEmpty _ - @[to_additive] theorem prod_subsingleton {α β : Type*} [CommMonoid β] [Subsingleton α] [Fintype α] (f : α → β) (a : α) : ∏ x : α, f x = f a := by @@ -2072,22 +1534,6 @@ lemma prod_pi_mulSingle' (i : ι) (a : α) : ∏ j, Pi.mulSingle i a j = a := pr end CommMonoid end Fintype -namespace Finset -variable [CommMonoid α] - -@[to_additive (attr := simp)] -lemma prod_attach_univ [Fintype ι] (f : {i // i ∈ @univ ι _} → α) : - ∏ i ∈ univ.attach, f i = ∏ i, f ⟨i, mem_univ _⟩ := - Fintype.prod_equiv (Equiv.subtypeUnivEquiv mem_univ) _ _ <| by simp - -@[to_additive] -theorem prod_erase_attach [DecidableEq ι] {s : Finset ι} (f : ι → α) (i : ↑s) : - ∏ j ∈ s.attach.erase i, f ↑j = ∏ j ∈ s.erase ↑i, f j := by - rw [← Function.Embedding.coe_subtype, ← prod_map] - simp [attach_map_val] - -end Finset - namespace List @[to_additive] @@ -2107,42 +1553,6 @@ end List namespace Multiset -@[simp] -lemma card_sum (s : Finset ι) (f : ι → Multiset α) : card (∑ i ∈ s, f i) = ∑ i ∈ s, card (f i) := - map_sum cardHom .. - -theorem disjoint_list_sum_left {a : Multiset α} {l : List (Multiset α)} : - Disjoint l.sum a ↔ ∀ b ∈ l, Disjoint b a := by - induction l with - | nil => - simp only [zero_disjoint, List.not_mem_nil, IsEmpty.forall_iff, forall_const, List.sum_nil] - | cons b bs ih => - simp_rw [List.sum_cons, disjoint_add_left, List.mem_cons, forall_eq_or_imp] - simp [and_congr_left_iff, ih] - -theorem disjoint_list_sum_right {a : Multiset α} {l : List (Multiset α)} : - Disjoint a l.sum ↔ ∀ b ∈ l, Disjoint a b := by - simpa only [disjoint_comm (a := a)] using disjoint_list_sum_left - -theorem disjoint_sum_left {a : Multiset α} {i : Multiset (Multiset α)} : - Disjoint i.sum a ↔ ∀ b ∈ i, Disjoint b a := - Quotient.inductionOn i fun l => by - rw [quot_mk_to_coe, Multiset.sum_coe] - exact disjoint_list_sum_left - -theorem disjoint_sum_right {a : Multiset α} {i : Multiset (Multiset α)} : - Disjoint a i.sum ↔ ∀ b ∈ i, Disjoint a b := by - simpa only [disjoint_comm (a := a)] using disjoint_sum_left - -theorem disjoint_finset_sum_left {β : Type*} {i : Finset β} {f : β → Multiset α} {a : Multiset α} : - Disjoint (i.sum f) a ↔ ∀ b ∈ i, Disjoint (f b) a := by - convert @disjoint_sum_left _ a (map f i.val) - simp [and_congr_left_iff] - -theorem disjoint_finset_sum_right {β : Type*} {i : Finset β} {f : β → Multiset α} - {a : Multiset α} : Disjoint a (i.sum f) ↔ ∀ b ∈ i, Disjoint a (f b) := by - simpa only [disjoint_comm] using disjoint_finset_sum_left - @[simp] lemma mem_sum {s : Finset ι} {m : ι → Multiset α} : a ∈ ∑ i ∈ s, m i ↔ ∃ i ∈ s, a ∈ m i := by induction s using Finset.cons_induction <;> simp [*] @@ -2161,11 +1571,6 @@ theorem toFinset_sum_count_eq (s : Multiset α) : ∑ a in s.toFinset, s.count a @[deprecated sum_count_eq_card (since := "2024-07-21")] theorem sum_count_eq [Fintype α] (s : Multiset α) : ∑ a, s.count a = Multiset.card s := by simp -theorem count_sum' {s : Finset β} {a : α} {f : β → Multiset α} : - count a (∑ x ∈ s, f x) = ∑ x ∈ s, count a (f x) := by - dsimp only [Finset.sum] - rw [count_sum] - @[simp] theorem toFinset_sum_count_nsmul_eq (s : Multiset α) : ∑ a ∈ s.toFinset, s.count a • {a} = s := by @@ -2182,11 +1587,6 @@ theorem exists_smul_of_dvd_count (s : Multiset α) {k : ℕ} rw [← mul_nsmul', Nat.mul_div_cancel' (h x (mem_toFinset.mp hx))] rw [← Finset.sum_nsmul, h₂, toFinset_sum_count_nsmul_eq] -theorem toFinset_prod_dvd_prod [CommMonoid α] (S : Multiset α) : S.toFinset.prod id ∣ S.prod := by - rw [Finset.prod_eq_multiset_prod] - refine Multiset.prod_dvd_prod_of_le ?_ - simp [Multiset.dedup_le S] - @[to_additive] theorem prod_sum {α : Type*} {ι : Type*} [CommMonoid α] (f : ι → Multiset α) (s : Finset ι) : (∑ x ∈ s, f x).prod = ∏ x ∈ s, (f x).prod := by @@ -2196,11 +1596,6 @@ theorem prod_sum {α : Type*} {ι : Type*} [CommMonoid α] (f : ι → Multiset end Multiset -@[simp, norm_cast] -theorem Units.coe_prod {M : Type*} [CommMonoid M] (f : α → Mˣ) (s : Finset α) : - (↑(∏ i ∈ s, f i) : M) = ∏ i ∈ s, (f i : M) := - map_prod (Units.coeHom M) _ _ - @[to_additive (attr := simp)] lemma IsUnit.prod_iff [CommMonoid β] : IsUnit (∏ a ∈ s, f a) ↔ ∀ a ∈ s, IsUnit (f a) := by induction s using Finset.cons_induction with @@ -2219,82 +1614,4 @@ theorem nat_abs_sum_le {ι : Type*} (s : Finset ι) (f : ι → ℤ) : simp only [Finset.sum_cons, not_false_iff] exact (Int.natAbs_add_le _ _).trans (Nat.add_le_add_left IH _) -/-! ### `Additive`, `Multiplicative` -/ - - -open Additive Multiplicative - -section Monoid - -variable [Monoid α] - -@[simp] -theorem ofMul_list_prod (s : List α) : ofMul s.prod = (s.map ofMul).sum := by simp [ofMul]; rfl - -@[simp] -theorem toMul_list_sum (s : List (Additive α)) : s.sum.toMul = (s.map toMul).prod := by - simp [toMul, ofMul]; rfl - -end Monoid - -section AddMonoid - -variable [AddMonoid α] - -@[simp] -theorem ofAdd_list_prod (s : List α) : ofAdd s.sum = (s.map ofAdd).prod := by simp [ofAdd]; rfl - -@[simp] -theorem toAdd_list_sum (s : List (Multiplicative α)) : s.prod.toAdd = (s.map toAdd).sum := by - simp [toAdd, ofAdd]; rfl - -end AddMonoid - -section CommMonoid - -variable [CommMonoid α] - -@[simp] -theorem ofMul_multiset_prod (s : Multiset α) : ofMul s.prod = (s.map ofMul).sum := by - simp [ofMul]; rfl - -@[simp] -theorem toMul_multiset_sum (s : Multiset (Additive α)) : s.sum.toMul = (s.map toMul).prod := by - simp [toMul, ofMul]; rfl - -@[simp] -theorem ofMul_prod (s : Finset ι) (f : ι → α) : ofMul (∏ i ∈ s, f i) = ∑ i ∈ s, ofMul (f i) := - rfl - -@[simp] -theorem toMul_sum (s : Finset ι) (f : ι → Additive α) : - (∑ i ∈ s, f i).toMul = ∏ i ∈ s, (f i).toMul := - rfl - -end CommMonoid - -section AddCommMonoid - -variable [AddCommMonoid α] - -@[simp] -theorem ofAdd_multiset_prod (s : Multiset α) : ofAdd s.sum = (s.map ofAdd).prod := by - simp [ofAdd]; rfl - -@[simp] -theorem toAdd_multiset_sum (s : Multiset (Multiplicative α)) : - s.prod.toAdd = (s.map toAdd).sum := by - simp [toAdd, ofAdd]; rfl - -@[simp] -theorem ofAdd_sum (s : Finset ι) (f : ι → α) : ofAdd (∑ i ∈ s, f i) = ∏ i ∈ s, ofAdd (f i) := - rfl - -@[simp] -theorem toAdd_prod (s : Finset ι) (f : ι → Multiplicative α) : - (∏ i ∈ s, f i).toAdd = ∑ i ∈ s, (f i).toAdd := - rfl - -end AddCommMonoid - -set_option linter.style.longFile 2400 +set_option linter.style.longFile 1800 diff --git a/Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean b/Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean new file mode 100644 index 0000000000000..64683dca211e5 --- /dev/null +++ b/Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean @@ -0,0 +1,787 @@ +/- +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 +-/ +import Mathlib.Data.Fintype.Basic +import Mathlib.Algebra.BigOperators.Group.Multiset.Defs + +/-! +# Big operators + +In this file we define products and sums indexed by finite sets (specifically, `Finset`). + +## Notation + +We introduce the following notation. + +Let `s` be a `Finset α`, and `f : α → β` a function. + +* `∏ x ∈ s, f x` is notation for `Finset.prod s f` (assuming `β` is a `CommMonoid`) +* `∑ x ∈ s, f x` is notation for `Finset.sum s f` (assuming `β` is an `AddCommMonoid`) +* `∏ x, f x` is notation for `Finset.prod Finset.univ f` + (assuming `α` is a `Fintype` and `β` is a `CommMonoid`) +* `∑ x, f x` is notation for `Finset.sum Finset.univ f` + (assuming `α` is a `Fintype` and `β` is an `AddCommMonoid`) + +## Implementation Notes + +The first arguments in all definitions and lemmas is the codomain of the function of the big +operator. This is necessary for the heuristic in `@[to_additive]`. +See the documentation of `to_additive.attr` for more information. + +-/ + +-- TODO +-- assert_not_exists AddCommMonoidWithOne +assert_not_exists MonoidWithZero +assert_not_exists MulAction +assert_not_exists OrderedCommMonoid + +variable {ι κ α β γ : Type*} + +open Fin Function + +namespace Finset + +/-- `∏ x ∈ s, f x` is the product of `f x` as `x` ranges over the elements of the finite set `s`. + +When the index type is a `Fintype`, the notation `∏ x, f x`, is a shorthand for +`∏ x ∈ Finset.univ, f x`. -/ +@[to_additive "`∑ x ∈ s, f x` is the sum of `f x` as `x` ranges over the elements +of the finite set `s`. + +When the index type is a `Fintype`, the notation `∑ x, f x`, is a shorthand for +`∑ x ∈ Finset.univ, f x`."] +protected def prod [CommMonoid β] (s : Finset α) (f : α → β) : β := + (s.1.map f).prod + +@[to_additive (attr := simp)] +theorem prod_mk [CommMonoid β] (s : Multiset α) (hs : s.Nodup) (f : α → β) : + (⟨s, hs⟩ : Finset α).prod f = (s.map f).prod := + rfl + +@[to_additive (attr := simp)] +theorem prod_val [CommMonoid α] (s : Finset α) : s.1.prod = s.prod id := by + rw [Finset.prod, Multiset.map_id] + +end Finset + +library_note "operator precedence of big operators"/-- +There is no established mathematical convention +for the operator precedence of big operators like `∏` and `∑`. +We will have to make a choice. + +Online discussions, such as https://math.stackexchange.com/q/185538/30839 +seem to suggest that `∏` and `∑` should have the same precedence, +and that this should be somewhere between `*` and `+`. +The latter have precedence levels `70` and `65` respectively, +and we therefore choose the level `67`. + +In practice, this means that parentheses should be placed as follows: +```lean +∑ k ∈ K, (a k + b k) = ∑ k ∈ K, a k + ∑ k ∈ K, b k → + ∏ k ∈ K, a k * b k = (∏ k ∈ K, a k) * (∏ k ∈ K, b k) +``` +(Example taken from page 490 of Knuth's *Concrete Mathematics*.) +-/ + +namespace BigOperators +open Batteries.ExtendedBinder Lean Meta + +-- TODO: contribute this modification back to `extBinder` + +/-- A `bigOpBinder` is like an `extBinder` and has the form `x`, `x : ty`, or `x pred` +where `pred` is a `binderPred` like `< 2`. +Unlike `extBinder`, `x` is a term. -/ +syntax bigOpBinder := term:max ((" : " term) <|> binderPred)? +/-- A BigOperator binder in parentheses -/ +syntax bigOpBinderParenthesized := " (" bigOpBinder ")" +/-- A list of parenthesized binders -/ +syntax bigOpBinderCollection := bigOpBinderParenthesized+ +/-- A single (unparenthesized) binder, or a list of parenthesized binders -/ +syntax bigOpBinders := bigOpBinderCollection <|> (ppSpace bigOpBinder) + +/-- Collects additional binder/Finset pairs for the given `bigOpBinder`. +Note: this is not extensible at the moment, unlike the usual `bigOpBinder` expansions. -/ +def processBigOpBinder (processed : (Array (Term × Term))) + (binder : TSyntax ``bigOpBinder) : MacroM (Array (Term × Term)) := + set_option hygiene false in + withRef binder do + match binder with + | `(bigOpBinder| $x:term) => + match x with + | `(($a + $b = $n)) => -- Maybe this is too cute. + return processed |>.push (← `(⟨$a, $b⟩), ← `(Finset.Nat.antidiagonal $n)) + | _ => return processed |>.push (x, ← ``(Finset.univ)) + | `(bigOpBinder| $x : $t) => return processed |>.push (x, ← ``((Finset.univ : Finset $t))) + | `(bigOpBinder| $x ∈ $s) => return processed |>.push (x, ← `(finset% $s)) + | `(bigOpBinder| $x < $n) => return processed |>.push (x, ← `(Finset.Iio $n)) + | `(bigOpBinder| $x ≤ $n) => return processed |>.push (x, ← `(Finset.Iic $n)) + | `(bigOpBinder| $x > $n) => return processed |>.push (x, ← `(Finset.Ioi $n)) + | `(bigOpBinder| $x ≥ $n) => return processed |>.push (x, ← `(Finset.Ici $n)) + | _ => Macro.throwUnsupported + +/-- Collects the binder/Finset pairs for the given `bigOpBinders`. -/ +def processBigOpBinders (binders : TSyntax ``bigOpBinders) : + MacroM (Array (Term × Term)) := + match binders with + | `(bigOpBinders| $b:bigOpBinder) => processBigOpBinder #[] b + | `(bigOpBinders| $[($bs:bigOpBinder)]*) => bs.foldlM processBigOpBinder #[] + | _ => Macro.throwUnsupported + +/-- Collect the binderIdents into a `⟨...⟩` expression. -/ +def bigOpBindersPattern (processed : (Array (Term × Term))) : + MacroM Term := do + let ts := processed.map Prod.fst + if ts.size == 1 then + return ts[0]! + else + `(⟨$ts,*⟩) + +/-- Collect the terms into a product of sets. -/ +def bigOpBindersProd (processed : (Array (Term × Term))) : + MacroM Term := do + if processed.isEmpty then + `((Finset.univ : Finset Unit)) + else if processed.size == 1 then + return processed[0]!.2 + else + processed.foldrM (fun s p => `(SProd.sprod $(s.2) $p)) processed.back!.2 + (start := processed.size - 1) + +/-- +- `∑ x, f x` is notation for `Finset.sum Finset.univ f`. It is the sum of `f x`, + where `x` ranges over the finite domain of `f`. +- `∑ x ∈ s, f x` is notation for `Finset.sum s f`. It is the sum of `f x`, + where `x` ranges over the finite set `s` (either a `Finset` or a `Set` with a `Fintype` instance). +- `∑ x ∈ s with p x, f x` is notation for `Finset.sum (Finset.filter p s) f`. +- `∑ (x ∈ s) (y ∈ t), f x y` is notation for `Finset.sum (s ×ˢ t) (fun ⟨x, y⟩ ↦ f x y)`. + +These support destructuring, for example `∑ ⟨x, y⟩ ∈ s ×ˢ t, f x y`. + +Notation: `"∑" bigOpBinders* ("with" term)? "," term` -/ +syntax (name := bigsum) "∑ " bigOpBinders ("with " term)? ", " term:67 : term + +/-- +- `∏ x, f x` is notation for `Finset.prod Finset.univ f`. It is the product of `f x`, + where `x` ranges over the finite domain of `f`. +- `∏ x ∈ s, f x` is notation for `Finset.prod s f`. It is the product of `f x`, + where `x` ranges over the finite set `s` (either a `Finset` or a `Set` with a `Fintype` instance). +- `∏ x ∈ s with p x, f x` is notation for `Finset.prod (Finset.filter p s) f`. +- `∏ (x ∈ s) (y ∈ t), f x y` is notation for `Finset.prod (s ×ˢ t) (fun ⟨x, y⟩ ↦ f x y)`. + +These support destructuring, for example `∏ ⟨x, y⟩ ∈ s ×ˢ t, f x y`. + +Notation: `"∏" bigOpBinders* ("with" term)? "," term` -/ +syntax (name := bigprod) "∏ " bigOpBinders ("with " term)? ", " term:67 : term + +macro_rules (kind := bigsum) + | `(∑ $bs:bigOpBinders $[with $p?]?, $v) => do + let processed ← processBigOpBinders bs + let x ← bigOpBindersPattern processed + let s ← bigOpBindersProd processed + match p? with + | some p => `(Finset.sum (Finset.filter (fun $x ↦ $p) $s) (fun $x ↦ $v)) + | none => `(Finset.sum $s (fun $x ↦ $v)) + +macro_rules (kind := bigprod) + | `(∏ $bs:bigOpBinders $[with $p?]?, $v) => do + let processed ← processBigOpBinders bs + let x ← bigOpBindersPattern processed + let s ← bigOpBindersProd processed + match p? with + | some p => `(Finset.prod (Finset.filter (fun $x ↦ $p) $s) (fun $x ↦ $v)) + | none => `(Finset.prod $s (fun $x ↦ $v)) + +/-- (Deprecated, use `∑ x ∈ s, f x`) +`∑ x in s, f x` is notation for `Finset.sum s f`. It is the sum of `f x`, +where `x` ranges over the finite set `s`. -/ +syntax (name := bigsumin) "∑ " extBinder " in " term ", " term:67 : term +macro_rules (kind := bigsumin) + | `(∑ $x:ident in $s, $r) => `(∑ $x:ident ∈ $s, $r) + | `(∑ $x:ident : $t in $s, $r) => `(∑ $x:ident ∈ ($s : Finset $t), $r) + +/-- (Deprecated, use `∏ x ∈ s, f x`) +`∏ x in s, f x` is notation for `Finset.prod s f`. It is the product of `f x`, +where `x` ranges over the finite set `s`. -/ +syntax (name := bigprodin) "∏ " extBinder " in " term ", " term:67 : term +macro_rules (kind := bigprodin) + | `(∏ $x:ident in $s, $r) => `(∏ $x:ident ∈ $s, $r) + | `(∏ $x:ident : $t in $s, $r) => `(∏ $x:ident ∈ ($s : Finset $t), $r) + +open Lean Meta Parser.Term PrettyPrinter.Delaborator SubExpr +open scoped Batteries.ExtendedBinder + +/-- Delaborator for `Finset.prod`. The `pp.piBinderTypes` option controls whether +to show the domain type when the product is over `Finset.univ`. -/ +@[app_delab Finset.prod] def delabFinsetProd : Delab := + whenPPOption getPPNotation <| withOverApp 5 <| do + let #[_, _, _, s, f] := (← getExpr).getAppArgs | failure + guard <| f.isLambda + let ppDomain ← getPPOption getPPPiBinderTypes + let (i, body) ← withAppArg <| withBindingBodyUnusedName fun i => do + return (i, ← delab) + if s.isAppOfArity ``Finset.univ 2 then + let binder ← + if ppDomain then + let ty ← withNaryArg 0 delab + `(bigOpBinder| $(.mk i):ident : $ty) + else + `(bigOpBinder| $(.mk i):ident) + `(∏ $binder:bigOpBinder, $body) + else + let ss ← withNaryArg 3 <| delab + `(∏ $(.mk i):ident ∈ $ss, $body) + +/-- Delaborator for `Finset.sum`. The `pp.piBinderTypes` option controls whether +to show the domain type when the sum is over `Finset.univ`. -/ +@[app_delab Finset.sum] def delabFinsetSum : Delab := + whenPPOption getPPNotation <| withOverApp 5 <| do + let #[_, _, _, s, f] := (← getExpr).getAppArgs | failure + guard <| f.isLambda + let ppDomain ← getPPOption getPPPiBinderTypes + let (i, body) ← withAppArg <| withBindingBodyUnusedName fun i => do + return (i, ← delab) + if s.isAppOfArity ``Finset.univ 2 then + let binder ← + if ppDomain then + let ty ← withNaryArg 0 delab + `(bigOpBinder| $(.mk i):ident : $ty) + else + `(bigOpBinder| $(.mk i):ident) + `(∑ $binder:bigOpBinder, $body) + else + let ss ← withNaryArg 3 <| delab + `(∑ $(.mk i):ident ∈ $ss, $body) + +end BigOperators + +namespace Finset + +variable {s s₁ s₂ : Finset α} {a : α} {f g : α → β} + +@[to_additive] +theorem prod_eq_multiset_prod [CommMonoid β] (s : Finset α) (f : α → β) : + ∏ x ∈ s, f x = (s.1.map f).prod := + rfl + +@[to_additive (attr := simp)] +lemma prod_map_val [CommMonoid β] (s : Finset α) (f : α → β) : (s.1.map f).prod = ∏ a ∈ s, f a := + rfl + +@[simp] +theorem sum_multiset_singleton (s : Finset α) : (s.sum fun x => {x}) = s.val := by + simp only [sum_eq_multiset_sum, Multiset.sum_map_singleton] + +end Finset + +@[to_additive (attr := simp)] +theorem map_prod [CommMonoid β] [CommMonoid γ] {G : Type*} [FunLike G β γ] [MonoidHomClass G β γ] + (g : G) (f : α → β) (s : Finset α) : g (∏ x ∈ s, f x) = ∏ x ∈ s, g (f x) := by + simp only [Finset.prod_eq_multiset_prod, map_multiset_prod, Multiset.map_map]; rfl + +variable {s s₁ s₂ : Finset α} {a : α} {f g : α → β} + +namespace Finset + +section CommMonoid + +variable [CommMonoid β] + +@[to_additive (attr := simp)] +theorem prod_empty : ∏ x ∈ ∅, f x = 1 := + rfl + +@[to_additive] +theorem prod_of_isEmpty [IsEmpty α] (s : Finset α) : ∏ i ∈ s, f i = 1 := by + rw [eq_empty_of_isEmpty s, prod_empty] + +@[deprecated (since := "2024-06-11")] alias prod_of_empty := prod_of_isEmpty +@[deprecated (since := "2024-06-11")] alias sum_of_empty := sum_of_isEmpty + +@[to_additive (attr := simp)] +theorem prod_const_one : (∏ _x ∈ s, (1 : β)) = 1 := by + simp only [Finset.prod, Multiset.map_const', Multiset.prod_replicate, one_pow] + +@[to_additive (attr := simp)] +theorem prod_map (s : Finset α) (e : α ↪ γ) (f : γ → β) : + ∏ x ∈ s.map e, f x = ∏ x ∈ s, f (e x) := by + rw [Finset.prod, Finset.map_val, Multiset.map_map]; rfl + +section ToList + +@[to_additive (attr := simp)] +theorem prod_to_list (s : Finset α) (f : α → β) : (s.toList.map f).prod = s.prod f := by + rw [Finset.prod, ← Multiset.prod_coe, ← Multiset.map_coe, Finset.coe_toList] + +end ToList + +@[to_additive] +theorem _root_.Equiv.Perm.prod_comp (σ : Equiv.Perm α) (s : Finset α) (f : α → β) + (hs : { a | σ a ≠ a } ⊆ s) : (∏ x ∈ s, f (σ x)) = ∏ x ∈ s, f x := by + convert (prod_map s σ.toEmbedding f).symm + exact (map_perm hs).symm + +@[to_additive] +theorem _root_.Equiv.Perm.prod_comp' (σ : Equiv.Perm α) (s : Finset α) (f : α → α → β) + (hs : { a | σ a ≠ a } ⊆ s) : (∏ x ∈ s, f (σ x) x) = ∏ x ∈ s, f x (σ.symm x) := by + convert σ.prod_comp s (fun x => f x (σ.symm x)) hs + rw [Equiv.symm_apply_apply] + +end CommMonoid + +end Finset + +namespace Finset + +section CommMonoid + +variable [CommMonoid β] + +section bij +variable {ι κ α : Type*} [CommMonoid α] {s : Finset ι} {t : Finset κ} {f : ι → α} {g : κ → α} + +/-- Reorder a product. + +The difference with `Finset.prod_bij'` is that the bijection is specified as a surjective injection, +rather than by an inverse function. + +The difference with `Finset.prod_nbij` is that the bijection is allowed to use membership of the +domain of the product, rather than being a non-dependent function. -/ +@[to_additive "Reorder a sum. + +The difference with `Finset.sum_bij'` is that the bijection is specified as a surjective injection, +rather than by an inverse function. + +The difference with `Finset.sum_nbij` is that the bijection is allowed to use membership of the +domain of the sum, rather than being a non-dependent function."] +theorem prod_bij (i : ∀ a ∈ s, κ) (hi : ∀ a ha, i a ha ∈ t) + (i_inj : ∀ a₁ ha₁ a₂ ha₂, i a₁ ha₁ = i a₂ ha₂ → a₁ = a₂) + (i_surj : ∀ b ∈ t, ∃ a ha, i a ha = b) (h : ∀ a ha, f a = g (i a ha)) : + ∏ x ∈ s, f x = ∏ x ∈ t, g x := + congr_arg Multiset.prod (Multiset.map_eq_map_of_bij_of_nodup f g s.2 t.2 i hi i_inj i_surj h) + +/-- Reorder a product. + +The difference with `Finset.prod_bij` is that the bijection is specified with an inverse, rather +than as a surjective injection. + +The difference with `Finset.prod_nbij'` is that the bijection and its inverse are allowed to use +membership of the domains of the products, rather than being non-dependent functions. -/ +@[to_additive "Reorder a sum. + +The difference with `Finset.sum_bij` is that the bijection is specified with an inverse, rather than +as a surjective injection. + +The difference with `Finset.sum_nbij'` is that the bijection and its inverse are allowed to use +membership of the domains of the sums, rather than being non-dependent functions."] +theorem prod_bij' (i : ∀ a ∈ s, κ) (j : ∀ a ∈ t, ι) (hi : ∀ a ha, i a ha ∈ t) + (hj : ∀ a ha, j a ha ∈ s) (left_inv : ∀ a ha, j (i a ha) (hi a ha) = a) + (right_inv : ∀ a ha, i (j a ha) (hj a ha) = a) (h : ∀ a ha, f a = g (i a ha)) : + ∏ x ∈ s, f x = ∏ x ∈ t, g x := by + refine prod_bij i hi (fun a1 h1 a2 h2 eq ↦ ?_) (fun b hb ↦ ⟨_, hj b hb, right_inv b hb⟩) h + rw [← left_inv a1 h1, ← left_inv a2 h2] + simp only [eq] + +/-- Reorder a product. + +The difference with `Finset.prod_nbij'` is that the bijection is specified as a surjective +injection, rather than by an inverse function. + +The difference with `Finset.prod_bij` is that the bijection is a non-dependent function, rather than +being allowed to use membership of the domain of the product. -/ +@[to_additive "Reorder a sum. + +The difference with `Finset.sum_nbij'` is that the bijection is specified as a surjective injection, +rather than by an inverse function. + +The difference with `Finset.sum_bij` is that the bijection is a non-dependent function, rather than +being allowed to use membership of the domain of the sum."] +lemma prod_nbij (i : ι → κ) (hi : ∀ a ∈ s, i a ∈ t) (i_inj : (s : Set ι).InjOn i) + (i_surj : (s : Set ι).SurjOn i t) (h : ∀ a ∈ s, f a = g (i a)) : + ∏ x ∈ s, f x = ∏ x ∈ t, g x := + prod_bij (fun a _ ↦ i a) hi i_inj (by simpa using i_surj) h + +/-- Reorder a product. + +The difference with `Finset.prod_nbij` is that the bijection is specified with an inverse, rather +than as a surjective injection. + +The difference with `Finset.prod_bij'` is that the bijection and its inverse are non-dependent +functions, rather than being allowed to use membership of the domains of the products. + +The difference with `Finset.prod_equiv` is that bijectivity is only required to hold on the domains +of the products, rather than on the entire types. +-/ +@[to_additive "Reorder a sum. + +The difference with `Finset.sum_nbij` is that the bijection is specified with an inverse, rather +than as a surjective injection. + +The difference with `Finset.sum_bij'` is that the bijection and its inverse are non-dependent +functions, rather than being allowed to use membership of the domains of the sums. + +The difference with `Finset.sum_equiv` is that bijectivity is only required to hold on the domains +of the sums, rather than on the entire types."] +lemma prod_nbij' (i : ι → κ) (j : κ → ι) (hi : ∀ a ∈ s, i a ∈ t) (hj : ∀ a ∈ t, j a ∈ s) + (left_inv : ∀ a ∈ s, j (i a) = a) (right_inv : ∀ a ∈ t, i (j a) = a) + (h : ∀ a ∈ s, f a = g (i a)) : ∏ x ∈ s, f x = ∏ x ∈ t, g x := + prod_bij' (fun a _ ↦ i a) (fun b _ ↦ j b) hi hj left_inv right_inv h + +/-- Specialization of `Finset.prod_nbij'` that automatically fills in most arguments. + +See `Fintype.prod_equiv` for the version where `s` and `t` are `univ`. -/ +@[to_additive "`Specialization of `Finset.sum_nbij'` that automatically fills in most arguments. + +See `Fintype.sum_equiv` for the version where `s` and `t` are `univ`."] +lemma prod_equiv (e : ι ≃ κ) (hst : ∀ i, i ∈ s ↔ e i ∈ t) (hfg : ∀ i ∈ s, f i = g (e i)) : + ∏ i ∈ s, f i = ∏ i ∈ t, g i := by refine prod_nbij' e e.symm ?_ ?_ ?_ ?_ hfg <;> simp [hst] + +/-- Specialization of `Finset.prod_bij` that automatically fills in most arguments. + +See `Fintype.prod_bijective` for the version where `s` and `t` are `univ`. -/ +@[to_additive "`Specialization of `Finset.sum_bij` that automatically fills in most arguments. + +See `Fintype.sum_bijective` for the version where `s` and `t` are `univ`."] +lemma prod_bijective (e : ι → κ) (he : e.Bijective) (hst : ∀ i, i ∈ s ↔ e i ∈ t) + (hfg : ∀ i ∈ s, f i = g (e i)) : + ∏ i ∈ s, f i = ∏ i ∈ t, g i := prod_equiv (.ofBijective e he) hst hfg + +end bij + +@[to_additive] +theorem prod_hom_rel [CommMonoid γ] {r : β → γ → Prop} {f : α → β} {g : α → γ} {s : Finset α} + (h₁ : r 1 1) (h₂ : ∀ a b c, r b c → r (f a * b) (g a * c)) : + r (∏ x ∈ s, f x) (∏ x ∈ s, g x) := by + delta Finset.prod + apply Multiset.prod_hom_rel <;> assumption + +variable (f s) + +@[to_additive] +theorem prod_coe_sort_eq_attach (f : s → β) : ∏ i : s, f i = ∏ i ∈ s.attach, f i := + rfl + +variable {f s} + +@[to_additive] +theorem prod_ite_index (p : Prop) [Decidable p] (s t : Finset α) (f : α → β) : + ∏ x ∈ if p then s else t, f x = if p then ∏ x ∈ s, f x else ∏ x ∈ t, f x := + apply_ite (fun s => ∏ x ∈ s, f x) _ _ _ + +@[to_additive (attr := simp)] +theorem prod_ite_irrel (p : Prop) [Decidable p] (s : Finset α) (f g : α → β) : + ∏ x ∈ s, (if p then f x else g x) = if p then ∏ x ∈ s, f x else ∏ x ∈ s, g x := by + split_ifs with h <;> rfl + +@[to_additive (attr := simp)] +theorem prod_dite_irrel (p : Prop) [Decidable p] (s : Finset α) (f : p → α → β) (g : ¬p → α → β) : + ∏ x ∈ s, (if h : p then f h x else g h x) = + if h : p then ∏ x ∈ s, f h x else ∏ x ∈ s, g h x := by + split_ifs with h <;> rfl + +@[to_additive] +theorem nonempty_of_prod_ne_one (h : ∏ x ∈ s, f x ≠ 1) : s.Nonempty := + s.eq_empty_or_nonempty.elim (fun H => False.elim <| h <| H.symm ▸ prod_empty) id + +@[to_additive] +theorem prod_range_zero (f : ℕ → β) : ∏ k ∈ range 0, f k = 1 := by rw [range_zero, prod_empty] + +open List + +theorem sum_filter_count_eq_countP [DecidableEq α] (p : α → Prop) [DecidablePred p] (l : List α) : + ∑ x ∈ l.toFinset with p x, l.count x = l.countP p := by + simp [Finset.sum, sum_map_count_dedup_filter_eq_countP p l] + +open Multiset + + +@[to_additive] +theorem prod_mem_multiset [DecidableEq α] (m : Multiset α) (f : { x // x ∈ m } → β) (g : α → β) + (hfg : ∀ x, f x = g x) : ∏ x : { x // x ∈ m }, f x = ∏ x ∈ m.toFinset, g x := by + refine prod_bij' (fun x _ ↦ x) (fun x hx ↦ ⟨x, Multiset.mem_toFinset.1 hx⟩) ?_ ?_ ?_ ?_ ?_ <;> + simp [hfg] + +/-- To prove a property of a product, it suffices to prove that +the property is multiplicative and holds on factors. -/ +@[to_additive "To prove a property of a sum, it suffices to prove that +the property is additive and holds on summands."] +theorem prod_induction {M : Type*} [CommMonoid M] (f : α → M) (p : M → Prop) + (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ s, p <| f x) : + p <| ∏ x ∈ s, f x := + Multiset.prod_induction _ _ hom unit (Multiset.forall_mem_map_iff.mpr base) + +/-- To prove a property of a product, it suffices to prove that +the property is multiplicative and holds on factors. -/ +@[to_additive "To prove a property of a sum, it suffices to prove that +the property is additive and holds on summands."] +theorem prod_induction_nonempty {M : Type*} [CommMonoid M] (f : α → M) (p : M → Prop) + (hom : ∀ a b, p a → p b → p (a * b)) (nonempty : s.Nonempty) (base : ∀ x ∈ s, p <| f x) : + p <| ∏ x ∈ s, f x := + Multiset.prod_induction_nonempty p hom (by simp [nonempty_iff_ne_empty.mp nonempty]) + (Multiset.forall_mem_map_iff.mpr base) + +@[to_additive] +theorem prod_pow (s : Finset α) (n : ℕ) (f : α → β) : ∏ x ∈ s, f x ^ n = (∏ x ∈ s, f x) ^ n := + Multiset.prod_map_pow + +theorem prod_dvd_prod_of_subset {ι M : Type*} [CommMonoid M] (s t : Finset ι) (f : ι → M) + (h : s ⊆ t) : (∏ i ∈ s, f i) ∣ ∏ i ∈ t, f i := + Multiset.prod_dvd_prod_of_le <| Multiset.map_le_map <| by simpa + +end CommMonoid + +section Opposite + +open MulOpposite + +/-- Moving to the opposite additive commutative monoid commutes with summing. -/ +@[simp] +theorem op_sum [AddCommMonoid β] {s : Finset α} (f : α → β) : + op (∑ x ∈ s, f x) = ∑ x ∈ s, op (f x) := + map_sum (opAddEquiv : β ≃+ βᵐᵒᵖ) _ _ + +@[simp] +theorem unop_sum [AddCommMonoid β] {s : Finset α} (f : α → βᵐᵒᵖ) : + unop (∑ x ∈ s, f x) = ∑ x ∈ s, unop (f x) := + map_sum (opAddEquiv : β ≃+ βᵐᵒᵖ).symm _ _ + +end Opposite + +section DivisionCommMonoid + +variable [DivisionCommMonoid β] + +@[to_additive (attr := simp)] +theorem prod_inv_distrib : (∏ x ∈ s, (f x)⁻¹) = (∏ x ∈ s, f x)⁻¹ := + Multiset.prod_map_inv + +@[to_additive (attr := simp)] +theorem prod_div_distrib : ∏ x ∈ s, f x / g x = (∏ x ∈ s, f x) / ∏ x ∈ s, g x := + Multiset.prod_map_div + +@[to_additive] +theorem prod_zpow (f : α → β) (s : Finset α) (n : ℤ) : ∏ a ∈ s, f a ^ n = (∏ a ∈ s, f a) ^ n := + Multiset.prod_map_zpow + +end DivisionCommMonoid + +theorem sum_nat_mod (s : Finset α) (n : ℕ) (f : α → ℕ) : + (∑ i ∈ s, f i) % n = (∑ i ∈ s, f i % n) % n := + (Multiset.sum_nat_mod _ _).trans <| by rw [Finset.sum, Multiset.map_map]; rfl + +theorem prod_nat_mod (s : Finset α) (n : ℕ) (f : α → ℕ) : + (∏ i ∈ s, f i) % n = (∏ i ∈ s, f i % n) % n := + (Multiset.prod_nat_mod _ _).trans <| by rw [Finset.prod, Multiset.map_map]; rfl + +theorem sum_int_mod (s : Finset α) (n : ℤ) (f : α → ℤ) : + (∑ i ∈ s, f i) % n = (∑ i ∈ s, f i % n) % n := + (Multiset.sum_int_mod _ _).trans <| by rw [Finset.sum, Multiset.map_map]; rfl + +theorem prod_int_mod (s : Finset α) (n : ℤ) (f : α → ℤ) : + (∏ i ∈ s, f i) % n = (∏ i ∈ s, f i % n) % n := + (Multiset.prod_int_mod _ _).trans <| by rw [Finset.prod, Multiset.map_map]; rfl + +end Finset + +namespace Fintype +variable {ι κ α : Type*} [Fintype ι] [Fintype κ] + +open Finset + +section CommMonoid +variable [CommMonoid α] + +/-- `Fintype.prod_bijective` is a variant of `Finset.prod_bij` that accepts `Function.Bijective`. + +See `Function.Bijective.prod_comp` for a version without `h`. -/ +@[to_additive "`Fintype.sum_bijective` is a variant of `Finset.sum_bij` that accepts +`Function.Bijective`. + +See `Function.Bijective.sum_comp` for a version without `h`. "] +lemma prod_bijective (e : ι → κ) (he : e.Bijective) (f : ι → α) (g : κ → α) + (h : ∀ x, f x = g (e x)) : ∏ x, f x = ∏ x, g x := + prod_equiv (.ofBijective e he) (by simp) (by simp [h]) + +@[to_additive] alias _root_.Function.Bijective.finset_prod := prod_bijective + +/-- `Fintype.prod_equiv` is a specialization of `Finset.prod_bij` that +automatically fills in most arguments. + +See `Equiv.prod_comp` for a version without `h`. +-/ +@[to_additive "`Fintype.sum_equiv` is a specialization of `Finset.sum_bij` that +automatically fills in most arguments. + +See `Equiv.sum_comp` for a version without `h`."] +lemma prod_equiv (e : ι ≃ κ) (f : ι → α) (g : κ → α) (h : ∀ x, f x = g (e x)) : + ∏ x, f x = ∏ x, g x := prod_bijective _ e.bijective _ _ h + +@[to_additive] +lemma _root_.Function.Bijective.prod_comp {e : ι → κ} (he : e.Bijective) (g : κ → α) : + ∏ i, g (e i) = ∏ i, g i := prod_bijective _ he _ _ fun _ ↦ rfl + +@[to_additive] +lemma _root_.Equiv.prod_comp (e : ι ≃ κ) (g : κ → α) : ∏ i, g (e i) = ∏ i, g i := + prod_equiv e _ _ fun _ ↦ rfl + +@[to_additive] +theorem prod_empty {α β : Type*} [CommMonoid β] [IsEmpty α] [Fintype α] (f : α → β) : + ∏ x : α, f x = 1 := + Finset.prod_of_isEmpty _ + +end CommMonoid +end Fintype + +namespace Finset +variable [CommMonoid α] + +@[to_additive (attr := simp)] +lemma prod_attach_univ [Fintype ι] (f : {i // i ∈ @univ ι _} → α) : + ∏ i ∈ univ.attach, f i = ∏ i, f ⟨i, mem_univ _⟩ := + Fintype.prod_equiv (Equiv.subtypeUnivEquiv mem_univ) _ _ <| by simp + +@[to_additive] +theorem prod_erase_attach [DecidableEq ι] {s : Finset ι} (f : ι → α) (i : ↑s) : + ∏ j ∈ s.attach.erase i, f ↑j = ∏ j ∈ s.erase ↑i, f j := by + rw [← Function.Embedding.coe_subtype, ← prod_map] + simp [attach_map_val] + +end Finset + +namespace Multiset + +@[simp] +lemma card_sum (s : Finset ι) (f : ι → Multiset α) : card (∑ i ∈ s, f i) = ∑ i ∈ s, card (f i) := + map_sum cardHom .. + +theorem disjoint_list_sum_left {a : Multiset α} {l : List (Multiset α)} : + Disjoint l.sum a ↔ ∀ b ∈ l, Disjoint b a := by + induction l with + | nil => + simp only [zero_disjoint, List.not_mem_nil, IsEmpty.forall_iff, forall_const, List.sum_nil] + | cons b bs ih => + simp_rw [List.sum_cons, disjoint_add_left, List.mem_cons, forall_eq_or_imp] + simp [and_congr_left_iff, ih] + +theorem disjoint_list_sum_right {a : Multiset α} {l : List (Multiset α)} : + Disjoint a l.sum ↔ ∀ b ∈ l, Disjoint a b := by + simpa only [disjoint_comm (a := a)] using disjoint_list_sum_left + +theorem disjoint_sum_left {a : Multiset α} {i : Multiset (Multiset α)} : + Disjoint i.sum a ↔ ∀ b ∈ i, Disjoint b a := + Quotient.inductionOn i fun l => by + rw [quot_mk_to_coe, Multiset.sum_coe] + exact disjoint_list_sum_left + +theorem disjoint_sum_right {a : Multiset α} {i : Multiset (Multiset α)} : + Disjoint a i.sum ↔ ∀ b ∈ i, Disjoint a b := by + simpa only [disjoint_comm (a := a)] using disjoint_sum_left + +theorem disjoint_finset_sum_left {β : Type*} {i : Finset β} {f : β → Multiset α} {a : Multiset α} : + Disjoint (i.sum f) a ↔ ∀ b ∈ i, Disjoint (f b) a := by + convert @disjoint_sum_left _ a (map f i.val) + simp [and_congr_left_iff] + +theorem disjoint_finset_sum_right {β : Type*} {i : Finset β} {f : β → Multiset α} + {a : Multiset α} : Disjoint a (i.sum f) ↔ ∀ b ∈ i, Disjoint a (f b) := by + simpa only [disjoint_comm] using disjoint_finset_sum_left + +variable [DecidableEq α] + +theorem count_sum' {s : Finset β} {a : α} {f : β → Multiset α} : + count a (∑ x ∈ s, f x) = ∑ x ∈ s, count a (f x) := by + dsimp only [Finset.sum] + rw [count_sum] + +theorem toFinset_prod_dvd_prod [CommMonoid α] (S : Multiset α) : S.toFinset.prod id ∣ S.prod := by + rw [Finset.prod_eq_multiset_prod] + refine Multiset.prod_dvd_prod_of_le ?_ + simp [Multiset.dedup_le S] + +end Multiset + +@[simp, norm_cast] +theorem Units.coe_prod {M : Type*} [CommMonoid M] (f : α → Mˣ) (s : Finset α) : + (↑(∏ i ∈ s, f i) : M) = ∏ i ∈ s, (f i : M) := + map_prod (Units.coeHom M) _ _ + + +/-! ### `Additive`, `Multiplicative` -/ + + +open Additive Multiplicative + +section Monoid + +variable [Monoid α] + +@[simp] +theorem ofMul_list_prod (s : List α) : ofMul s.prod = (s.map ofMul).sum := by simp [ofMul]; rfl + +@[simp] +theorem toMul_list_sum (s : List (Additive α)) : s.sum.toMul = (s.map toMul).prod := by + simp [toMul, ofMul]; rfl + +end Monoid + +section AddMonoid + +variable [AddMonoid α] + +@[simp] +theorem ofAdd_list_prod (s : List α) : ofAdd s.sum = (s.map ofAdd).prod := by simp [ofAdd]; rfl + +@[simp] +theorem toAdd_list_sum (s : List (Multiplicative α)) : s.prod.toAdd = (s.map toAdd).sum := by + simp [toAdd, ofAdd]; rfl + +end AddMonoid + +section CommMonoid + +variable [CommMonoid α] + +@[simp] +theorem ofMul_multiset_prod (s : Multiset α) : ofMul s.prod = (s.map ofMul).sum := by + simp [ofMul]; rfl + +@[simp] +theorem toMul_multiset_sum (s : Multiset (Additive α)) : s.sum.toMul = (s.map toMul).prod := by + simp [toMul, ofMul]; rfl + +@[simp] +theorem ofMul_prod (s : Finset ι) (f : ι → α) : ofMul (∏ i ∈ s, f i) = ∑ i ∈ s, ofMul (f i) := + rfl + +@[simp] +theorem toMul_sum (s : Finset ι) (f : ι → Additive α) : + (∑ i ∈ s, f i).toMul = ∏ i ∈ s, (f i).toMul := + rfl + +end CommMonoid + +section AddCommMonoid + +variable [AddCommMonoid α] + +@[simp] +theorem ofAdd_multiset_prod (s : Multiset α) : ofAdd s.sum = (s.map ofAdd).prod := by + simp [ofAdd]; rfl + +@[simp] +theorem toAdd_multiset_sum (s : Multiset (Multiplicative α)) : + s.prod.toAdd = (s.map toAdd).sum := by + simp [toAdd, ofAdd]; rfl + +@[simp] +theorem ofAdd_sum (s : Finset ι) (f : ι → α) : ofAdd (∑ i ∈ s, f i) = ∏ i ∈ s, ofAdd (f i) := + rfl + +@[simp] +theorem toAdd_prod (s : Finset ι) (f : ι → Multiplicative α) : + (∏ i ∈ s, f i).toAdd = ∑ i ∈ s, (f i).toAdd := + rfl + +end AddCommMonoid diff --git a/Mathlib/Algebra/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/BigOperators/Group/Multiset/Basic.lean similarity index 76% rename from Mathlib/Algebra/BigOperators/Group/Multiset.lean rename to Mathlib/Algebra/BigOperators/Group/Multiset/Basic.lean index a7cfb50317a50..930c2689951fa 100644 --- a/Mathlib/Algebra/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Multiset/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.BigOperators.Group.List.Lemmas +import Mathlib.Algebra.BigOperators.Group.Multiset.Defs import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Algebra.Order.Sub.Unbundled.Basic @@ -31,40 +32,6 @@ section CommMonoid variable [CommMonoid α] [CommMonoid β] {s t : Multiset α} {a : α} {m : Multiset ι} {f g : ι → α} -/-- Product of a multiset given a commutative monoid structure on `α`. - `prod {a, b, c} = a * b * c` -/ -@[to_additive - "Sum of a multiset given a commutative additive monoid structure on `α`. - `sum {a, b, c} = a + b + c`"] -def prod : Multiset α → α := - foldr (· * ·) 1 - -@[to_additive] -theorem prod_eq_foldr (s : Multiset α) : - prod s = foldr (· * ·) 1 s := - rfl - -@[to_additive] -theorem prod_eq_foldl (s : Multiset α) : - prod s = foldl (· * ·) 1 s := - (foldr_swap _ _ _).trans (by simp [mul_comm]) - -@[to_additive (attr := simp, norm_cast)] -theorem prod_coe (l : List α) : prod ↑l = l.prod := rfl - -@[to_additive (attr := simp)] -theorem prod_toList (s : Multiset α) : s.toList.prod = s.prod := by - conv_rhs => rw [← coe_toList s] - rw [prod_coe] - -@[to_additive (attr := simp)] -theorem prod_zero : @prod α _ 0 = 1 := - rfl - -@[to_additive (attr := simp)] -theorem prod_cons (a : α) (s) : prod (a ::ₘ s) = a * prod s := - foldr_cons _ _ _ _ - @[to_additive (attr := simp)] theorem prod_erase [DecidableEq α] (h : a ∈ s) : a * (s.erase a).prod = s.prod := by rw [← s.coe_toList, coe_erase, prod_coe, prod_coe, List.prod_erase (mem_toList.2 h)] @@ -75,14 +42,6 @@ theorem prod_map_erase [DecidableEq ι] {a : ι} (h : a ∈ m) : rw [← m.coe_toList, coe_erase, map_coe, map_coe, prod_coe, prod_coe, List.prod_map_erase f (mem_toList.2 h)] -@[to_additive (attr := simp)] -theorem prod_singleton (a : α) : prod {a} = a := by - simp only [mul_one, prod_cons, ← cons_zero, eq_self_iff_true, prod_zero] - -@[to_additive] -theorem prod_pair (a b : α) : ({a, b} : Multiset α).prod = a * b := by - rw [insert_eq_cons, prod_cons, prod_singleton] - @[to_additive (attr := simp)] theorem prod_add (s t : Multiset α) : prod (s + t) = prod s * prod t := Quotient.inductionOn₂ s t fun l₁ l₂ => by simp @@ -99,10 +58,6 @@ theorem prod_filter_mul_prod_filter_not (p) [DecidablePred p] : (s.filter p).prod * (s.filter (fun a ↦ ¬ p a)).prod = s.prod := by rw [← prod_add, filter_add_not] -@[to_additive (attr := simp)] -theorem prod_replicate (n : ℕ) (a : α) : (replicate n a).prod = a ^ n := by - simp [replicate, List.prod_replicate] - @[to_additive] theorem prod_map_eq_pow_single [DecidableEq ι] (i : ι) (hf : ∀ i' ≠ i, i' ∈ m → f i' = 1) : (m.map f).prod = f i ^ m.count i := by @@ -118,10 +73,6 @@ theorem prod_eq_pow_single [DecidableEq α] (a : α) (h : ∀ a' ≠ a, a' ∈ s lemma prod_eq_one (h : ∀ x ∈ s, x = (1 : α)) : s.prod = 1 := by induction s using Quotient.inductionOn; simp [List.prod_eq_one h] -@[to_additive] -theorem pow_count [DecidableEq α] (a : α) : a ^ s.count a = (s.filter (Eq a)).prod := by - rw [filter_eq, prod_replicate] - @[to_additive] theorem prod_hom_ne_zero {s : Multiset α} (hs : s ≠ 0) {F : Type*} [FunLike F α β] [MulHomClass F α β] (f : F) : @@ -154,17 +105,6 @@ theorem prod_hom₂ [CommMonoid γ] (s : Multiset ι) (f : α → β → γ) Quotient.inductionOn s fun l => by simp only [l.prod_hom₂ f hf hf', quot_mk_to_coe, map_coe, prod_coe] -@[to_additive] -theorem prod_hom_rel (s : Multiset ι) {r : α → β → Prop} {f : ι → α} {g : ι → β} - (h₁ : r 1 1) (h₂ : ∀ ⦃a b c⦄, r b c → r (f a * b) (g a * c)) : - r (s.map f).prod (s.map g).prod := - Quotient.inductionOn s fun l => by - simp only [l.prod_hom_rel h₁ h₂, quot_mk_to_coe, map_coe, prod_coe] - -@[to_additive] -theorem prod_map_one : prod (m.map fun _ => (1 : α)) = 1 := by - rw [map_const', prod_replicate, one_pow] - @[to_additive (attr := simp)] theorem prod_map_mul : (m.map fun i => f i * g i).prod = (m.map f).prod * (m.map g).prod := m.prod_hom₂ (· * ·) mul_mul_mul_comm (mul_one _) _ _ @@ -179,24 +119,6 @@ theorem prod_map_prod_map (m : Multiset β') (n : Multiset γ) {f : β' → γ prod (n.map fun b => prod <| m.map fun a => f a b) := Multiset.induction_on m (by simp) fun a m ih => by simp [ih] -@[to_additive] -theorem prod_induction (p : α → Prop) (s : Multiset α) (p_mul : ∀ a b, p a → p b → p (a * b)) - (p_one : p 1) (p_s : ∀ a ∈ s, p a) : p s.prod := by - rw [prod_eq_foldr] - exact foldr_induction (· * ·) 1 p s p_mul p_one p_s - -@[to_additive] -theorem prod_induction_nonempty (p : α → Prop) (p_mul : ∀ a b, p a → p b → p (a * b)) (hs : s ≠ ∅) - (p_s : ∀ a ∈ s, p a) : p s.prod := by - induction s using Multiset.induction_on with - | empty => simp at hs - | cons a s hsa => - rw [prod_cons] - by_cases hs_empty : s = ∅ - · simp [hs_empty, p_s a] - have hps : ∀ x, x ∈ s → p x := fun x hxs => p_s x (mem_cons_of_mem hxs) - exact p_mul a s.prod (p_s a (mem_cons_self a s)) (hsa hs_empty hps) - theorem prod_dvd_prod_of_le (h : s ≤ t) : s.prod ∣ t.prod := by obtain ⟨z, rfl⟩ := exists_add_of_le h simp only [prod_add, dvd_mul_right] diff --git a/Mathlib/Algebra/BigOperators/Group/Multiset/Defs.lean b/Mathlib/Algebra/BigOperators/Group/Multiset/Defs.lean new file mode 100644 index 0000000000000..ee7bbaef19ecc --- /dev/null +++ b/Mathlib/Algebra/BigOperators/Group/Multiset/Defs.lean @@ -0,0 +1,114 @@ +/- +Copyright (c) 2015 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro +-/ +import Mathlib.Algebra.BigOperators.Group.List.Defs +import Mathlib.Algebra.Group.Basic +import Mathlib.Data.Multiset.Basic + +/-! +# Sums and products over multisets + +In this file we define products and sums indexed by multisets. This is later used to define products +and sums indexed by finite sets. + +## Main declarations + +* `Multiset.prod`: `s.prod f` is the product of `f i` over all `i ∈ s`. Not to be mistaken with + the cartesian product `Multiset.product`. +* `Multiset.sum`: `s.sum f` is the sum of `f i` over all `i ∈ s`. +-/ + +assert_not_exists MonoidWithZero + +variable {F ι α β β' γ : Type*} + +namespace Multiset + +section CommMonoid + +variable [CommMonoid α] [CommMonoid β] {s t : Multiset α} {a : α} {m : Multiset ι} {f g : ι → α} + +/-- Product of a multiset given a commutative monoid structure on `α`. + `prod {a, b, c} = a * b * c` -/ +@[to_additive + "Sum of a multiset given a commutative additive monoid structure on `α`. + `sum {a, b, c} = a + b + c`"] +def prod : Multiset α → α := + foldr (· * ·) 1 + +@[to_additive] +theorem prod_eq_foldr (s : Multiset α) : + prod s = foldr (· * ·) 1 s := + rfl + +@[to_additive] +theorem prod_eq_foldl (s : Multiset α) : + prod s = foldl (· * ·) 1 s := + (foldr_swap _ _ _).trans (by simp [mul_comm]) + +@[to_additive (attr := simp, norm_cast)] +theorem prod_coe (l : List α) : prod ↑l = l.prod := rfl + +@[to_additive (attr := simp)] +theorem prod_toList (s : Multiset α) : s.toList.prod = s.prod := by + conv_rhs => rw [← coe_toList s] + rw [prod_coe] + +@[to_additive (attr := simp)] +theorem prod_zero : @prod α _ 0 = 1 := + rfl + +@[to_additive (attr := simp)] +theorem prod_cons (a : α) (s) : prod (a ::ₘ s) = a * prod s := + foldr_cons _ _ _ _ + +@[to_additive (attr := simp)] +theorem prod_singleton (a : α) : prod {a} = a := by + simp only [mul_one, prod_cons, ← cons_zero, eq_self_iff_true, prod_zero] + +@[to_additive] +theorem prod_pair (a b : α) : ({a, b} : Multiset α).prod = a * b := by + rw [insert_eq_cons, prod_cons, prod_singleton] + +@[to_additive (attr := simp)] +theorem prod_replicate (n : ℕ) (a : α) : (replicate n a).prod = a ^ n := by + simp [replicate, List.prod_replicate] + +@[to_additive] +theorem pow_count [DecidableEq α] (a : α) : a ^ s.count a = (s.filter (Eq a)).prod := by + rw [filter_eq, prod_replicate] + +@[to_additive] +theorem prod_hom_rel (s : Multiset ι) {r : α → β → Prop} {f : ι → α} {g : ι → β} + (h₁ : r 1 1) (h₂ : ∀ ⦃a b c⦄, r b c → r (f a * b) (g a * c)) : + r (s.map f).prod (s.map g).prod := + Quotient.inductionOn s fun l => by + simp only [l.prod_hom_rel h₁ h₂, quot_mk_to_coe, map_coe, prod_coe] + +@[to_additive] +theorem prod_map_one : prod (m.map fun _ => (1 : α)) = 1 := by + rw [map_const', prod_replicate, one_pow] + +@[to_additive] +theorem prod_induction (p : α → Prop) (s : Multiset α) (p_mul : ∀ a b, p a → p b → p (a * b)) + (p_one : p 1) (p_s : ∀ a ∈ s, p a) : p s.prod := by + rw [prod_eq_foldr] + exact foldr_induction (· * ·) 1 p s p_mul p_one p_s + +@[to_additive] +theorem prod_induction_nonempty (p : α → Prop) (p_mul : ∀ a b, p a → p b → p (a * b)) (hs : s ≠ ∅) + (p_s : ∀ a ∈ s, p a) : p s.prod := by + induction s using Multiset.induction_on with + | empty => simp at hs + | cons a s hsa => + rw [prod_cons] + by_cases hs_empty : s = ∅ + · simp [hs_empty, p_s a] + have hps : ∀ x, x ∈ s → p x := fun x hxs => p_s x (mem_cons_of_mem hxs) + exact p_mul a s.prod (p_s a (mem_cons_self a s)) (hsa hs_empty hps) + +end CommMonoid + +end Multiset diff --git a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean index af5e65fe47cb5..fe873bf6f4c92 100644 --- a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean +++ b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.Finprod -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.GroupWithZero.Action.Defs import Mathlib.Algebra.Order.Group.Multiset import Mathlib.Data.Finset.Basic diff --git a/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean b/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean index 6031d188022c6..8caadacedf5a0 100644 --- a/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean +++ b/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean @@ -3,7 +3,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 -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.GroupWithZero.Units.Basic /-! diff --git a/Mathlib/Algebra/BigOperators/Intervals.lean b/Mathlib/Algebra/BigOperators/Intervals.lean index 46ef275235a38..b33aeb2db79cb 100644 --- a/Mathlib/Algebra/BigOperators/Intervals.lean +++ b/Mathlib/Algebra/BigOperators/Intervals.lean @@ -3,7 +3,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 -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Order.Interval.Finset import Mathlib.Order.Interval.Finset.Nat import Mathlib.Tactic.Linarith diff --git a/Mathlib/Algebra/BigOperators/NatAntidiagonal.lean b/Mathlib/Algebra/BigOperators/NatAntidiagonal.lean index c4d290c333cfa..c4c5943b1f984 100644 --- a/Mathlib/Algebra/BigOperators/NatAntidiagonal.lean +++ b/Mathlib/Algebra/BigOperators/NatAntidiagonal.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Aaron Anderson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Finset.NatAntidiagonal /-! diff --git a/Mathlib/Algebra/BigOperators/Option.lean b/Mathlib/Algebra/BigOperators/Option.lean index b473099bdad48..3d03beb486f3d 100644 --- a/Mathlib/Algebra/BigOperators/Option.lean +++ b/Mathlib/Algebra/BigOperators/Option.lean @@ -3,7 +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.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Finset.Option /-! diff --git a/Mathlib/Algebra/BigOperators/Ring/Multiset.lean b/Mathlib/Algebra/BigOperators/Ring/Multiset.lean index 3cacbdd944ec2..426bdc656c14e 100644 --- a/Mathlib/Algebra/BigOperators/Ring/Multiset.lean +++ b/Mathlib/Algebra/BigOperators/Ring/Multiset.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Bhavik Mehta, Eric Wieser -/ -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Basic import Mathlib.Algebra.BigOperators.Ring.List import Mathlib.Data.Multiset.Antidiagonal import Mathlib.Data.Multiset.Sections diff --git a/Mathlib/Algebra/BigOperators/Ring/Nat.lean b/Mathlib/Algebra/BigOperators/Ring/Nat.lean index dddf70506cb71..a621b8e510db6 100644 --- a/Mathlib/Algebra/BigOperators/Ring/Nat.lean +++ b/Mathlib/Algebra/BigOperators/Ring/Nat.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Pim Otte. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Pim Otte -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Ring.Parity /-! diff --git a/Mathlib/Algebra/BigOperators/RingEquiv.lean b/Mathlib/Algebra/BigOperators/RingEquiv.lean index 4719036850f10..d3d5e750a9160 100644 --- a/Mathlib/Algebra/BigOperators/RingEquiv.lean +++ b/Mathlib/Algebra/BigOperators/RingEquiv.lean @@ -3,9 +3,9 @@ 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, Callum Sutton, Yury Kudryashov -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Ring.Equiv import Mathlib.Algebra.Ring.Opposite +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Results about mapping big operators across ring equivalences diff --git a/Mathlib/Algebra/BigOperators/Sym.lean b/Mathlib/Algebra/BigOperators/Sym.lean index f8d0197ffd9d6..ea3a636310668 100644 --- a/Mathlib/Algebra/BigOperators/Sym.lean +++ b/Mathlib/Algebra/BigOperators/Sym.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Finset.Sym import Mathlib.Data.Sym.Sym2.Order diff --git a/Mathlib/Algebra/BigOperators/WithTop.lean b/Mathlib/Algebra/BigOperators/WithTop.lean index 17d569cd5b075..d700365dfba59 100644 --- a/Mathlib/Algebra/BigOperators/WithTop.lean +++ b/Mathlib/Algebra/BigOperators/WithTop.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Zhouhang Zhou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Zhouhang Zhou, Yaël Dillies -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Order.Ring.WithTop /-! diff --git a/Mathlib/Algebra/GradedMonoid.lean b/Mathlib/Algebra/GradedMonoid.lean index 6a3b310015196..e80df0d6b8559 100644 --- a/Mathlib/Algebra/GradedMonoid.lean +++ b/Mathlib/Algebra/GradedMonoid.lean @@ -9,7 +9,7 @@ import Mathlib.Algebra.Group.Submonoid.Defs import Mathlib.Data.List.FinRange import Mathlib.Data.SetLike.Basic import Mathlib.Data.Sigma.Basic -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Lean.Elab.Tactic /-! diff --git a/Mathlib/Algebra/Group/EvenFunction.lean b/Mathlib/Algebra/Group/EvenFunction.lean index 81ddf35dcd57c..5d7162b565b10 100644 --- a/Mathlib/Algebra/Group/EvenFunction.lean +++ b/Mathlib/Algebra/Group/EvenFunction.lean @@ -3,7 +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.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Group.Action.Pi import Mathlib.Algebra.NoZeroSMulDivisors.Basic diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean index a299acb8cadfe..af7620fdb7069 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Yaël Dillies -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Group.Action.Pi import Mathlib.Algebra.Group.Pointwise.Set.Finite import Mathlib.Algebra.Group.Pointwise.Set.ListOfFn diff --git a/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean b/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean index 03932943943de..0e3a22a5b8f85 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Group.Pointwise.Set.Basic /-! diff --git a/Mathlib/Algebra/Module/Submodule/LinearMap.lean b/Mathlib/Algebra/Module/Submodule/LinearMap.lean index c451705a60b4c..16b425c56cc37 100644 --- a/Mathlib/Algebra/Module/Submodule/LinearMap.lean +++ b/Mathlib/Algebra/Module/Submodule/LinearMap.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Module.LinearMap.End import Mathlib.Algebra.Module.Submodule.Defs +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean index 022aedf054d88..8da6b95c4a1f9 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean @@ -3,7 +3,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 -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Order.BigOperators.Group.Multiset import Mathlib.Algebra.Order.Group.Nat import Mathlib.Data.Multiset.OrderedMonoid diff --git a/Mathlib/Algebra/Order/BigOperators/Group/LocallyFinite.lean b/Mathlib/Algebra/Order/BigOperators/Group/LocallyFinite.lean index f43f25244887d..da4a09312184b 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/LocallyFinite.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/LocallyFinite.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Order.Interval.Finset.Basic /-! diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean index ad405fe75fb40..d77b13d8de6a0 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Basic import Mathlib.Algebra.Order.BigOperators.Group.List import Mathlib.Algebra.Order.Group.Abs import Mathlib.Data.List.MinMax diff --git a/Mathlib/Algebra/Order/BigOperators/GroupWithZero/Multiset.lean b/Mathlib/Algebra/Order/BigOperators/GroupWithZero/Multiset.lean index 7115296a5745e..ed35c4f413f61 100644 --- a/Mathlib/Algebra/Order/BigOperators/GroupWithZero/Multiset.lean +++ b/Mathlib/Algebra/Order/BigOperators/GroupWithZero/Multiset.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Ruben Van de Velde, Daniel Weber -/ import Mathlib.Algebra.Order.BigOperators.GroupWithZero.List -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Defs /-! # Big operators on a multiset in ordered groups with zeros diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean b/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean index 0b91673c65582..8bb7e4a3cdaed 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Ruben Van de Velde. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Ruben Van de Velde -/ -import Mathlib.Algebra.BigOperators.Group.Multiset import Mathlib.Algebra.Order.BigOperators.Ring.List +import Mathlib.Algebra.BigOperators.Group.Multiset.Defs /-! # Big operators on a multiset in ordered rings diff --git a/Mathlib/Algebra/Order/Rearrangement.lean b/Mathlib/Algebra/Order/Rearrangement.lean index a6c4bfabc5fbd..b44e25f7c4d85 100644 --- a/Mathlib/Algebra/Order/Rearrangement.lean +++ b/Mathlib/Algebra/Order/Rearrangement.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Mantas Bakšys. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mantas Bakšys -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Order.Module.OrderedSMul import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Data.Prod.Lex diff --git a/Mathlib/Algebra/Regular/Pow.lean b/Mathlib/Algebra/Regular/Pow.lean index 2907e177058fe..d1391c2075682 100644 --- a/Mathlib/Algebra/Regular/Pow.lean +++ b/Mathlib/Algebra/Regular/Pow.lean @@ -3,9 +3,9 @@ Copyright (c) 2021 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.Algebra.Regular.Basic +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Regular elements diff --git a/Mathlib/Algebra/Ring/SumsOfSquares.lean b/Mathlib/Algebra/Ring/SumsOfSquares.lean index cd768870f9db6..ed4e42b2c5c19 100644 --- a/Mathlib/Algebra/Ring/SumsOfSquares.lean +++ b/Mathlib/Algebra/Ring/SumsOfSquares.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Florent Schaffhauser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Florent Schaffhauser -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Group.Submonoid.Basic import Mathlib.Algebra.Order.Ring.Defs diff --git a/Mathlib/Algebra/Star/BigOperators.lean b/Mathlib/Algebra/Star/BigOperators.lean index 3be80b486aee5..359f9effa5852 100644 --- a/Mathlib/Algebra/Star/BigOperators.lean +++ b/Mathlib/Algebra/Star/BigOperators.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Star.Basic +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Big-operators lemmas about `star` algebraic operations diff --git a/Mathlib/Algebra/Tropical/BigOperators.lean b/Mathlib/Algebra/Tropical/BigOperators.lean index f6c25370a25b6..1eeb1dabbbb30 100644 --- a/Mathlib/Algebra/Tropical/BigOperators.lean +++ b/Mathlib/Algebra/Tropical/BigOperators.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.List.MinMax import Mathlib.Algebra.Tropical.Basic import Mathlib.Order.ConditionallyCompleteLattice.Finset diff --git a/Mathlib/CategoryTheory/Preadditive/Basic.lean b/Mathlib/CategoryTheory/Preadditive/Basic.lean index 7fade9b2835eb..576d91e0c552f 100644 --- a/Mathlib/CategoryTheory/Preadditive/Basic.lean +++ b/Mathlib/CategoryTheory/Preadditive/Basic.lean @@ -3,12 +3,12 @@ Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel, Jakob von Raumer -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.GroupWithZero.Action.Units import Mathlib.Algebra.Module.End import Mathlib.CategoryTheory.Endomorphism import Mathlib.CategoryTheory.Limits.Shapes.Kernels +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Preadditive categories diff --git a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean index 4a9c75efd68f9..b851909f82c19 100644 --- a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean +++ b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean @@ -10,6 +10,7 @@ import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Biproducts import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Products import Mathlib.CategoryTheory.Preadditive.Basic import Mathlib.Tactic.Abel +import Mathlib.Algebra.BigOperators.Group.Finset.Basic /-! # Basic facts about biproducts in preadditive categories. diff --git a/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean b/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean index 8df532c9e1251..7a0fb488e58fd 100644 --- a/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Preadditive/FunctorCategory.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ import Mathlib.CategoryTheory.Preadditive.Basic +import Mathlib.Algebra.BigOperators.Group.Finset.Basic /-! # Preadditive structure on functor categories diff --git a/Mathlib/CategoryTheory/Preadditive/Mat.lean b/Mathlib/CategoryTheory/Preadditive/Mat.lean index 4a2228de6b269..17cee933b9716 100644 --- a/Mathlib/CategoryTheory/Preadditive/Mat.lean +++ b/Mathlib/CategoryTheory/Preadditive/Mat.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.Opposites import Mathlib.Algebra.Ring.Opposite diff --git a/Mathlib/CategoryTheory/Subobject/Lattice.lean b/Mathlib/CategoryTheory/Subobject/Lattice.lean index 70d9b061a97da..97a4050b25127 100644 --- a/Mathlib/CategoryTheory/Subobject/Lattice.lean +++ b/Mathlib/CategoryTheory/Subobject/Lattice.lean @@ -6,6 +6,7 @@ Authors: Bhavik Mehta, Kim Morrison import Mathlib.CategoryTheory.Functor.Currying import Mathlib.CategoryTheory.Subobject.FactorThru import Mathlib.CategoryTheory.Subobject.WellPowered +import Mathlib.Data.Finset.Lattice.Fold /-! # The lattice of subobjects diff --git a/Mathlib/Combinatorics/Additive/Dissociation.lean b/Mathlib/Combinatorics/Additive/Dissociation.lean index f22b05d75f55d..a392c5291e1b9 100644 --- a/Mathlib/Combinatorics/Additive/Dissociation.lean +++ b/Mathlib/Combinatorics/Additive/Dissociation.lean @@ -3,7 +3,7 @@ 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 -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Group.Units.Equiv import Mathlib.Data.Fintype.Card diff --git a/Mathlib/Combinatorics/HalesJewett.lean b/Mathlib/Combinatorics/HalesJewett.lean index 0f4879e749f4f..082fd89e47b72 100644 --- a/Mathlib/Combinatorics/HalesJewett.lean +++ b/Mathlib/Combinatorics/HalesJewett.lean @@ -3,7 +3,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 -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Fintype.Option import Mathlib.Data.Fintype.Shrink import Mathlib.Data.Fintype.Sum diff --git a/Mathlib/Combinatorics/Hindman.lean b/Mathlib/Combinatorics/Hindman.lean index 25e45662baf0d..bc139a6efd3b9 100644 --- a/Mathlib/Combinatorics/Hindman.lean +++ b/Mathlib/Combinatorics/Hindman.lean @@ -3,7 +3,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 -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Stream.Init import Mathlib.Topology.Algebra.Semigroup import Mathlib.Topology.StoneCech diff --git a/Mathlib/Combinatorics/SetFamily/Shatter.lean b/Mathlib/Combinatorics/SetFamily/Shatter.lean index a9fb7d184ba69..4a5c674be02e9 100644 --- a/Mathlib/Combinatorics/SetFamily/Shatter.lean +++ b/Mathlib/Combinatorics/SetFamily/Shatter.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Combinatorics.SetFamily.Compression.Down import Mathlib.Data.Fintype.Powerset import Mathlib.Order.Interval.Finset.Nat diff --git a/Mathlib/Data/Finset/NoncommProd.lean b/Mathlib/Data/Finset/NoncommProd.lean index ccb90bcd3b3d0..c103380bb1a12 100644 --- a/Mathlib/Data/Finset/NoncommProd.lean +++ b/Mathlib/Data/Finset/NoncommProd.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Group.Commute.Hom import Mathlib.Data.Fintype.Card diff --git a/Mathlib/Data/Finset/Slice.lean b/Mathlib/Data/Finset/Slice.lean index 2bb65d43b3036..413b6ad9d925d 100644 --- a/Mathlib/Data/Finset/Slice.lean +++ b/Mathlib/Data/Finset/Slice.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Bhavik Mehta, Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta, Alena Gusakov, Yaël Dillies -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Fintype.Powerset import Mathlib.Order.Antichain import Mathlib.Order.Interval.Finset.Nat diff --git a/Mathlib/Data/Finsupp/BigOperators.lean b/Mathlib/Data/Finsupp/BigOperators.lean index ed77d4374edaa..47fafd873089e 100644 --- a/Mathlib/Data/Finsupp/BigOperators.lean +++ b/Mathlib/Data/Finsupp/BigOperators.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Finsupp.Defs import Mathlib.Data.Finset.Pairwise diff --git a/Mathlib/Data/Holor.lean b/Mathlib/Data/Holor.lean index b7fc524917add..c3205781035d2 100644 --- a/Mathlib/Data/Holor.lean +++ b/Mathlib/Data/Holor.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Alexander Bentkamp. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Alexander Bentkamp -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Module.Pi /-! diff --git a/Mathlib/Data/Multiset/Bind.lean b/Mathlib/Data/Multiset/Bind.lean index 5cbe5c20afdd6..d7b7ddbd79432 100644 --- a/Mathlib/Data/Multiset/Bind.lean +++ b/Mathlib/Data/Multiset/Bind.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Basic import Mathlib.Data.Multiset.Dedup /-! diff --git a/Mathlib/Data/Multiset/Fintype.lean b/Mathlib/Data/Multiset/Fintype.lean index 8fbb4eb3dcd32..ed70e899db4db 100644 --- a/Mathlib/Data/Multiset/Fintype.lean +++ b/Mathlib/Data/Multiset/Fintype.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Fintype.Card /-! diff --git a/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean b/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean index f84f9a8eb1912..515ad206dd699 100644 --- a/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean +++ b/Mathlib/Data/Nat/Factorial/DoubleFactorial.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Jake Levinson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jake Levinson -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Nat.Factorial.Basic import Mathlib.Tactic.Ring import Mathlib.Tactic.Positivity.Core diff --git a/Mathlib/Data/Nat/Fib/Basic.lean b/Mathlib/Data/Nat/Fib/Basic.lean index 399cabbe6107f..629b20bbbdd22 100644 --- a/Mathlib/Data/Nat/Fib/Basic.lean +++ b/Mathlib/Data/Nat/Fib/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Kevin Kappelmann. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Kappelmann, Kyle Miller, Mario Carneiro -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Finset.NatAntidiagonal import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Nat.BinaryRec diff --git a/Mathlib/Data/Nat/GCD/BigOperators.lean b/Mathlib/Data/Nat/GCD/BigOperators.lean index ced2ef1aa916b..9dfbea627d45c 100644 --- a/Mathlib/Data/Nat/GCD/BigOperators.lean +++ b/Mathlib/Data/Nat/GCD/BigOperators.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ import Batteries.Data.Nat.Gcd -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Lemmas about coprimality with big products. diff --git a/Mathlib/Data/PNat/Factors.lean b/Mathlib/Data/PNat/Factors.lean index 2a2367c5bbc13..59ecfa1addf1b 100644 --- a/Mathlib/Data/PNat/Factors.lean +++ b/Mathlib/Data/PNat/Factors.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Neil Strickland. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Neil Strickland -/ -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Basic import Mathlib.Data.PNat.Prime import Mathlib.Data.Nat.Factors import Mathlib.Data.Multiset.OrderedMonoid diff --git a/Mathlib/Data/Rat/BigOperators.lean b/Mathlib/Data/Rat/BigOperators.lean index b12524939f9d1..81e5b4f7129bf 100644 --- a/Mathlib/Data/Rat/BigOperators.lean +++ b/Mathlib/Data/Rat/BigOperators.lean @@ -3,8 +3,8 @@ Copyright (c) 2019 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Data.Rat.Cast.CharZero +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Casting lemmas for rational numbers involving sums and products -/ diff --git a/Mathlib/Data/Sym/Card.lean b/Mathlib/Data/Sym/Card.lean index b7033fc532861..531c4c705aaef 100644 --- a/Mathlib/Data/Sym/Card.lean +++ b/Mathlib/Data/Sym/Card.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yaël Dillies, Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Bhavik Mehta, Huỳnh Trần Khanh, Stuart Presnell -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Finset.Sym import Mathlib.Data.Fintype.Sum import Mathlib.Data.Fintype.Prod diff --git a/Mathlib/Deprecated/Submonoid.lean b/Mathlib/Deprecated/Submonoid.lean index 104e7376fd117..25e8af4f8368f 100644 --- a/Mathlib/Deprecated/Submonoid.lean +++ b/Mathlib/Deprecated/Submonoid.lean @@ -3,9 +3,10 @@ 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, Kenny Lau, Johan Commelin, Mario Carneiro, Kevin Buzzard -/ -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Group.Submonoid.Defs import Mathlib.Deprecated.Group +import Mathlib.Data.Set.Lattice +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Unbundled submonoids (deprecated) diff --git a/Mathlib/Dynamics/BirkhoffSum/Basic.lean b/Mathlib/Dynamics/BirkhoffSum/Basic.lean index de5f5ee5992f7..f8a7d0cab9d62 100644 --- a/Mathlib/Dynamics/BirkhoffSum/Basic.lean +++ b/Mathlib/Dynamics/BirkhoffSum/Basic.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.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Dynamics.FixedPoints.Basic /-! diff --git a/Mathlib/GroupTheory/Congruence/BigOperators.lean b/Mathlib/GroupTheory/Congruence/BigOperators.lean index a52506ce46ca0..f3885dd840efd 100644 --- a/Mathlib/GroupTheory/Congruence/BigOperators.lean +++ b/Mathlib/GroupTheory/Congruence/BigOperators.lean @@ -4,10 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Amelia Livingston -/ -import Mathlib.Algebra.BigOperators.Group.Finset -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Basic import Mathlib.Algebra.BigOperators.Group.List.Lemmas import Mathlib.GroupTheory.Congruence.Defs +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Interactions between `∑, ∏` and `(Add)Con` diff --git a/Mathlib/GroupTheory/QuotientGroup/Basic.lean b/Mathlib/GroupTheory/QuotientGroup/Basic.lean index ac753e21b448b..0c2b307c48094 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Basic.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Basic.lean @@ -10,7 +10,7 @@ import Mathlib.Data.Int.Cast.Lemmas import Mathlib.GroupTheory.Congruence.Hom import Mathlib.GroupTheory.Coset.Basic import Mathlib.GroupTheory.QuotientGroup.Defs -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Quotients of groups by normal subgroups diff --git a/Mathlib/LinearAlgebra/Lagrange.lean b/Mathlib/LinearAlgebra/Lagrange.lean index aa071b99f8158..e62cd1266df60 100644 --- a/Mathlib/LinearAlgebra/Lagrange.lean +++ b/Mathlib/LinearAlgebra/Lagrange.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Wrenna Robson -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Polynomial.FieldDivision import Mathlib.LinearAlgebra.Vandermonde import Mathlib.RingTheory.Polynomial.Basic diff --git a/Mathlib/Logic/Godel/GodelBetaFunction.lean b/Mathlib/Logic/Godel/GodelBetaFunction.lean index 092137dd0dea8..97b63dafdb67d 100644 --- a/Mathlib/Logic/Godel/GodelBetaFunction.lean +++ b/Mathlib/Logic/Godel/GodelBetaFunction.lean @@ -8,6 +8,9 @@ import Mathlib.Data.Nat.ModEq import Mathlib.Data.Nat.ChineseRemainder import Mathlib.Data.Nat.Prime.Defs import Mathlib.Data.Nat.Pairing +import Mathlib.Order.Fin.Basic +import Mathlib.Data.Finset.Lattice.Fold +import Mathlib.Data.Nat.Factorial.Basic /-! # Gödel's Beta Function Lemma diff --git a/Mathlib/MeasureTheory/Measure/AddContent.lean b/Mathlib/MeasureTheory/Measure/AddContent.lean index 835d2ea391739..40d6422e75b95 100644 --- a/Mathlib/MeasureTheory/Measure/AddContent.lean +++ b/Mathlib/MeasureTheory/Measure/AddContent.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Peter Pfaffelhuber -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.ENNReal.Basic import Mathlib.MeasureTheory.SetSemiring diff --git a/Mathlib/Order/Filter/AtTopBot/BigOperators.lean b/Mathlib/Order/Filter/AtTopBot/BigOperators.lean index bbc99acf7d7b1..b9953eb978436 100644 --- a/Mathlib/Order/Filter/AtTopBot/BigOperators.lean +++ b/Mathlib/Order/Filter/AtTopBot/BigOperators.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Order.Filter.AtTopBot /-! diff --git a/Mathlib/Order/LiminfLimsup.lean b/Mathlib/Order/LiminfLimsup.lean index 1b33f08a0dec9..e8cc02503ba11 100644 --- a/Mathlib/Order/LiminfLimsup.lean +++ b/Mathlib/Order/LiminfLimsup.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Johannes Hölzl, Rémy Degenne -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Group.Unbundled.Abs import Mathlib.Algebra.Order.GroupWithZero.Unbundled diff --git a/Mathlib/Order/Partition/Finpartition.lean b/Mathlib/Order/Partition/Finpartition.lean index 25b7f19c5d6e7..c44251b4be76b 100644 --- a/Mathlib/Order/Partition/Finpartition.lean +++ b/Mathlib/Order/Partition/Finpartition.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yaël Dillies, Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Bhavik Mehta -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Data.Fintype.Powerset import Mathlib.Data.Setoid.Basic import Mathlib.Order.Atoms diff --git a/Mathlib/RingTheory/Localization/Defs.lean b/Mathlib/RingTheory/Localization/Defs.lean index f2c81a6a1ef79..c3064920c345d 100644 --- a/Mathlib/RingTheory/Localization/Defs.lean +++ b/Mathlib/RingTheory/Localization/Defs.lean @@ -8,7 +8,7 @@ import Mathlib.GroupTheory.MonoidLocalization.MonoidWithZero import Mathlib.RingTheory.OreLocalization.Ring import Mathlib.Tactic.ApplyFun import Mathlib.Tactic.Ring -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Defs /-! # Localizations of commutative rings diff --git a/Mathlib/RingTheory/Multiplicity.lean b/Mathlib/RingTheory/Multiplicity.lean index e6fcaadc0bb10..2f13dce766244 100644 --- a/Mathlib/RingTheory/Multiplicity.lean +++ b/Mathlib/RingTheory/Multiplicity.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis, Chris Hughes, Daniel Weber -/ import Mathlib.Algebra.Associated.Basic -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Data.ENat.Basic diff --git a/Mathlib/RingTheory/Prime.lean b/Mathlib/RingTheory/Prime.lean index 331460fc59ec6..4c2891ff75dd2 100644 --- a/Mathlib/RingTheory/Prime.lean +++ b/Mathlib/RingTheory/Prime.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Algebra.Order.Group.Unbundled.Abs import Mathlib.Algebra.Prime.Defs diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean index ba36cf067ec92..45d4fd35b00b3 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Jens Wagemaker, Aaron Anderson -/ import Mathlib.Algebra.Associated.Basic -import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.Group.Multiset.Basic import Mathlib.Algebra.Group.Submonoid.Membership import Mathlib.Algebra.Group.Submonoid.BigOperators import Mathlib.Order.WellFounded diff --git a/Mathlib/Tactic/NormNum/BigOperators.lean b/Mathlib/Tactic/NormNum/BigOperators.lean index b6851faeaa70e..0e0a25dfa9fbb 100644 --- a/Mathlib/Tactic/NormNum/BigOperators.lean +++ b/Mathlib/Tactic/NormNum/BigOperators.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen, Floris van Doorn -/ import Mathlib.Tactic.NormNum.Basic -import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Data.List.FinRange +import Mathlib.Algebra.BigOperators.Group.Finset.Basic /-! # `norm_num` plugin for big operators diff --git a/MathlibTest/apply_congr.lean b/MathlibTest/apply_congr.lean index 25fe3d2608734..f921f29c2a72d 100644 --- a/MathlibTest/apply_congr.lean +++ b/MathlibTest/apply_congr.lean @@ -1,5 +1,5 @@ import Mathlib.Tactic.ApplyCongr -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic example (f g : ℤ → ℤ) (S : Finset ℤ) (h : ∀ m ∈ S, f m = g m) : Finset.sum S f = Finset.sum S g := by diff --git a/MathlibTest/linarith.lean b/MathlibTest/linarith.lean index 2341dfcd13359..2dd6331a67593 100644 --- a/MathlibTest/linarith.lean +++ b/MathlibTest/linarith.lean @@ -1,6 +1,6 @@ import Mathlib.Tactic.Linarith import Mathlib.Tactic.Linarith.Oracle.FourierMotzkin -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Order.Ring.Rat import Mathlib.Order.Interval.Finset.Nat diff --git a/MathlibTest/matrix.lean b/MathlibTest/matrix.lean index f6e84240f8d07..36e1a2a9d1c9a 100644 --- a/MathlibTest/matrix.lean +++ b/MathlibTest/matrix.lean @@ -153,22 +153,22 @@ example {α : Type _} [CommRing α] {a b c d : α} : Fin.default_eq_zero, submatrix_apply, Fin.succ_zero_eq_one, cons_val_one, head_fin_const, Fin.sum_univ_succ, Fin.val_zero, pow_zero, one_mul, Fin.zero_succAbove, head_cons, Finset.univ_unique, Fin.val_succ, Fin.val_eq_zero, zero_add, pow_one, cons_val_succ, neg_mul, - Fin.succ_succAbove_zero, Finset.sum_const, Finset.card_singleton, smul_neg, one_smul] + Fin.succ_succAbove_zero, Finset.sum_neg_distrib, Finset.sum_const, Finset.card_singleton, + one_smul] ring example {α : Type _} [CommRing α] {a b c d e f g h i : α} : Matrix.det !![a, b, c; d, e, f; g, h, i] = a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g := by simp? [Matrix.det_succ_row_zero, Fin.sum_univ_succ] says - simp only [det_succ_row_zero, Nat.succ_eq_add_one, Nat.reduceAdd, - Fin.isValue, of_apply, cons_val', empty_val', cons_val_fin_one, cons_val_zero, - submatrix_apply, Fin.succ_zero_eq_one, cons_val_one, head_cons, submatrix_submatrix, - det_unique, Fin.default_eq_zero, Function.comp_apply, Fin.succ_one_eq_two, cons_val_two, - tail_cons, head_fin_const, Fin.sum_univ_succ, Fin.val_zero, pow_zero, one_mul, - Fin.zero_succAbove, Finset.univ_unique, Fin.val_succ, Fin.val_eq_zero, zero_add, pow_one, - neg_mul, Fin.succ_succAbove_zero, Finset.sum_neg_distrib, Finset.sum_singleton, cons_val_succ, - Fin.succ_succAbove_one, even_two, Even.neg_pow, one_pow, Finset.sum_const, - Finset.card_singleton, one_smul] + simp only [det_succ_row_zero, Nat.succ_eq_add_one, Nat.reduceAdd, Fin.isValue, of_apply, + cons_val', empty_val', cons_val_fin_one, cons_val_zero, submatrix_apply, Fin.succ_zero_eq_one, + cons_val_one, head_cons, submatrix_submatrix, det_unique, Fin.default_eq_zero, + Function.comp_apply, Fin.succ_one_eq_two, cons_val_two, tail_cons, head_fin_const, + Fin.sum_univ_succ, Fin.val_zero, pow_zero, one_mul, Fin.zero_succAbove, Finset.univ_unique, + Fin.val_succ, Fin.val_eq_zero, zero_add, pow_one, neg_mul, Fin.succ_succAbove_zero, + Finset.sum_neg_distrib, Finset.sum_singleton, cons_val_succ, Fin.succ_succAbove_one, even_two, + Even.neg_pow, one_pow, Finset.sum_const, Finset.card_singleton, one_smul] ring example {R : Type*} [Semiring R] {a b c d : R} : diff --git a/scripts/noshake.json b/scripts/noshake.json index 246720f089eb3..d660d99ec4d73 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -235,7 +235,9 @@ "Mathlib.Data.PNat.Defs"], "Mathlib.Tactic.NormNum.Ineq": ["Mathlib.Algebra.Order.Field.Defs", "Mathlib.Algebra.Order.Monoid.WithTop"], - "Mathlib.Tactic.NormNum.BigOperators": ["Mathlib.Data.List.FinRange"], + "Mathlib.Tactic.NormNum.BigOperators": + ["Mathlib.Algebra.BigOperators.Group.Finset.Basic", + "Mathlib.Data.List.FinRange"], "Mathlib.Tactic.Nontriviality.Core": ["Mathlib.Logic.Nontrivial.Basic"], "Mathlib.Tactic.NoncommRing": ["Mathlib.Algebra.Group.Action.Defs"], "Mathlib.Tactic.MoveAdd": From 84086d44b6d565a2b7d525358ad9a19f698b8b24 Mon Sep 17 00:00:00 2001 From: grunweg Date: Mon, 13 Jan 2025 09:13:38 +0000 Subject: [PATCH 182/681] perf(ModelTheory/Algebra/Ring/Definability): re-squeeze a slow simp (#20549) Co-authored-by: grunweg --- Mathlib/ModelTheory/Algebra/Ring/Definability.lean | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Mathlib/ModelTheory/Algebra/Ring/Definability.lean b/Mathlib/ModelTheory/Algebra/Ring/Definability.lean index bc08d899f56f3..c80853d3fff67 100644 --- a/Mathlib/ModelTheory/Algebra/Ring/Definability.lean +++ b/Mathlib/ModelTheory/Algebra/Ring/Definability.lean @@ -38,8 +38,12 @@ theorem mvPolynomial_zeroLocus_definable {ι K : Type*} [Field K] (Sum.map (fun p => ⟨p.1.1.coeff p.2.1, by simp only [Set.mem_iUnion] exact ⟨p.1.1, p.1.2, Set.mem_image_of_mem _ p.2.2⟩⟩) id)) 0), ?_⟩ - simp [Formula.Realize, Term.equal, Function.comp_def, p'] - + -- Squeezing this simp slows it down significantly. Please measure before removing. + simp? [Formula.Realize, Term.equal, Function.comp_def, p'] says + simp only [Finset.mem_coe, Formula.Realize, Term.equal, Term.relabel_relabel, + Function.comp_def, realize_iInf, realize_bdEqual, Term.realize_relabel, Sum.elim_inl, + realize_termOfFreeCommRing, lift_genericPolyMap, Sum.map_inr, id_eq, Sum.elim_inr, Sum.map_inl, + MvPolynomialSupportLEEquiv_symm_apply_coeff, realize_zero, Subtype.forall, p'] end Ring From 6ee88ac3b2eceab3b4fbd2a91a9a87011c06a271 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 13 Jan 2025 09:34:11 +0000 Subject: [PATCH 183/681] feat: more results about `IsLittleOTVS` (#20220) It will be cleaner to generalize the results for `fderiv` after writing a few more of these lemmas, rather than shuffling everything around. Co-authored-by: Yury G. Kudryashov --- Mathlib/Analysis/Asymptotics/TVS.lean | 122 +++++++++++++++---- Mathlib/Analysis/Calculus/FDeriv/Basic.lean | 37 +++--- Mathlib/Analysis/Calculus/FDeriv/Linear.lean | 6 +- Mathlib/Analysis/Convex/EGauge.lean | 8 ++ Mathlib/Order/Filter/Bases.lean | 5 + 5 files changed, 136 insertions(+), 42 deletions(-) diff --git a/Mathlib/Analysis/Asymptotics/TVS.lean b/Mathlib/Analysis/Asymptotics/TVS.lean index ce294dcb4f385..e6a51f9b44c0b 100644 --- a/Mathlib/Analysis/Asymptotics/TVS.lean +++ b/Mathlib/Analysis/Asymptotics/TVS.lean @@ -81,17 +81,65 @@ def IsLittleOTVS (𝕜 : Type*) {α E F : Type*} @[inherit_doc] notation:100 f " =o[" 𝕜 ";" l "] " g:100 => IsLittleOTVS 𝕜 l f g -variable {α β 𝕜 E F : Type*} +variable {α β 𝕜 E F G : Type*} section TopologicalSpace variable [NontriviallyNormedField 𝕜] [AddCommGroup E] [TopologicalSpace E] [Module 𝕜 E] [AddCommGroup F] [TopologicalSpace F] [Module 𝕜 F] + [AddCommGroup G] [TopologicalSpace G] [Module 𝕜 G] + +section congr + +variable {f f₁ f₂ : α → E} {g g₁ g₂ : α → F} {l : Filter α} + +theorem isLittleOTVS_congr (hf : f₁ =ᶠ[l] f₂) (hg : g₁ =ᶠ[l] g₂) : + f₁ =o[𝕜;l] g₁ ↔ f₂ =o[𝕜;l] g₂ := by + simp only [IsLittleOTVS] + refine forall₂_congr fun U hU => exists_congr fun V => and_congr_right fun hV => + forall₂_congr fun ε hε => Filter.eventually_congr ?_ + filter_upwards [hf, hg] with _ e₁ e₂ + rw [e₁, e₂] + +/-- A stronger version of `IsLittleOTVS.congr` that requires the functions only agree along the +filter. -/ +theorem IsLittleOTVS.congr' (h : f₁ =o[𝕜;l] g₁) (hf : f₁ =ᶠ[l] f₂) (hg : g₁ =ᶠ[l] g₂) : + f₂ =o[𝕜;l] g₂ := + (isLittleOTVS_congr hf hg).mp h + +theorem IsLittleOTVS.congr (h : f₁ =o[𝕜;l] g₁) (hf : ∀ x, f₁ x = f₂ x) (hg : ∀ x, g₁ x = g₂ x) : + f₂ =o[𝕜;l] g₂ := + h.congr' (univ_mem' hf) (univ_mem' hg) + +theorem IsLittleOTVS.congr_left (h : f₁ =o[𝕜;l] g) (hf : ∀ x, f₁ x = f₂ x) : f₂ =o[𝕜;l] g := + h.congr hf fun _ => rfl + +theorem IsLittleOTVS.congr_right (h : f =o[𝕜;l] g₁) (hg : ∀ x, g₁ x = g₂ x) : f =o[𝕜;l] g₂ := + h.congr (fun _ => rfl) hg + +end congr + +variable {l l₁ l₂ : Filter α} {f : α → E} {g : α → F} + +@[trans] +theorem IsLittleOTVS.trans {k : α → G} (hfg : f =o[𝕜;l] g) (hgk : g =o[𝕜;l] k) : f =o[𝕜;l] k := by + intros U hU + obtain ⟨V, hV0, hV⟩ := hfg U hU + obtain ⟨W, hW0, hW⟩ := hgk V hV0 + refine ⟨W, hW0, fun ε hε => ?_⟩ + filter_upwards [hV ε hε, hW 1 one_ne_zero] with a hfga hgka + refine hfga.trans ?_ + gcongr + simpa using hgka + +instance transIsLittleOTVSIsLittleOTVS : + @Trans (α → E) (α → F) (α → G) (· =o[𝕜;l] ·) (· =o[𝕜;l] ·) (· =o[𝕜;l] ·) where + trans := IsLittleOTVS.trans theorem _root_.Filter.HasBasis.isLittleOTVS_iff {ιE ιF : Sort*} {pE : ιE → Prop} {pF : ιF → Prop} {sE : ιE → Set E} {sF : ιF → Set F} (hE : HasBasis (𝓝 (0 : E)) pE sE) - (hF : HasBasis (𝓝 (0 : F)) pF sF) {f : α → E} {g : α → F} {l : Filter α} : + (hF : HasBasis (𝓝 (0 : F)) pF sF) : f =o[𝕜;l] g ↔ ∀ i, pE i → ∃ j, pF j ∧ ∀ ε ≠ (0 : ℝ≥0), ∀ᶠ x in l, egauge 𝕜 (sE i) (f x) ≤ ε * egauge 𝕜 (sF j) (g x) := by refine (hE.forall_iff ?_).trans <| forall₂_congr fun _ _ ↦ hF.exists_iff ?_ @@ -100,13 +148,52 @@ theorem _root_.Filter.HasBasis.isLittleOTVS_iff {ιE ιF : Sort*} {pE : ιE → · refine fun s t hsub h ε hε ↦ (h ε hε).mono fun x hx ↦ hx.trans ?_ gcongr +theorem isLittleOTVS_iff_smallSets : + f =o[𝕜; l] g ↔ ∀ U ∈ 𝓝 0, ∀ᶠ V in (𝓝 0).smallSets, ∀ ε ≠ (0 : ℝ≥0), + ∀ᶠ x in l, egauge 𝕜 U (f x) ≤ ε * egauge 𝕜 V (g x) := + forall₂_congr fun U hU ↦ .symm <| eventually_smallSets' fun V₁ V₂ hV hV₂ ε hε ↦ + (hV₂ ε hε).mono fun x hx ↦ hx.trans <| by gcongr + +alias ⟨IsLittleOTVS.eventually_smallSets, _⟩ := isLittleOTVS_iff_smallSets + @[simp] -theorem isLittleOTVS_map {f : α → E} {g : α → F} {k : β → α} {l : Filter β} : +theorem isLittleOTVS_map {k : β → α} {l : Filter β} : f =o[𝕜; map k l] g ↔ (f ∘ k) =o[𝕜;l] (g ∘ k) := by simp [IsLittleOTVS] -protected lemma IsLittleOTVS.smul_left {f : α → E} {g : α → F} {l : Filter α} - (h : f =o[𝕜;l] g) (c : α → 𝕜) : +lemma IsLittleOTVS.mono (hf : f =o[𝕜;l₁] g) (h : l₂ ≤ l₁) : f =o[𝕜;l₂] g := + fun U hU => let ⟨V, hV0, hV⟩ := hf U hU; ⟨V, hV0, fun ε hε => (hV ε hε).filter_mono h⟩ + +lemma IsLittleOTVS.comp_tendsto {k : β → α} {lb : Filter β} (h : f =o[𝕜; l] g) + (hk : Tendsto k lb l) : (f ∘ k) =o[𝕜; lb] (g ∘ k) := + isLittleOTVS_map.mp (h.mono hk) + +lemma isLittleOTVS_sup : f =o[𝕜; l₁ ⊔ l₂] g ↔ f =o[𝕜; l₁] g ∧ f =o[𝕜; l₂] g := by + simp only [isLittleOTVS_iff_smallSets, ← forall_and, ← eventually_and, eventually_sup] + +lemma IsLittleOTVS.sup (hf₁ : f =o[𝕜; l₁] g) (hf₂ : f =o[𝕜; l₂] g) : f =o[𝕜; l₁ ⊔ l₂] g := + isLittleOTVS_sup.mpr ⟨hf₁, hf₂⟩ + +@[simp] +lemma IsLittleOTVS.zero (g : α → F) (l : Filter α) : (0 : α → E) =o[𝕜;l] g := by + intros U hU + simpa [egauge_zero_right _ (Filter.nonempty_of_mem hU)] using ⟨univ, by simp⟩ + +lemma isLittleOTVS_insert [TopologicalSpace α] {x : α} {s : Set α} (h : f x = 0) : + f =o[𝕜;(𝓝[insert x s] x)] g ↔ f =o[𝕜;(𝓝[s] x)] g := by + rw [nhdsWithin_insert, isLittleOTVS_sup, and_iff_right] + exact .congr' (.zero g _) h.symm .rfl + +lemma IsLittleOTVS.insert [TopologicalSpace α] {x : α} {s : Set α} + (h : f =o[𝕜;(𝓝[s] x)] g) (hf : f x = 0) : + f =o[𝕜;(𝓝[insert x s] x)] g := + (isLittleOTVS_insert hf).2 h + +@[simp] +lemma IsLittleOTVS.bot : f =o[𝕜;⊥] g := + fun u hU => ⟨univ, by simp⟩ + +protected lemma IsLittleOTVS.smul_left (h : f =o[𝕜;l] g) (c : α → 𝕜) : (fun x ↦ c x • f x) =o[𝕜;l] (fun x ↦ c x • g x) := by unfold IsLittleOTVS at * peel h with U hU V hV ε hε x hx @@ -114,8 +201,7 @@ protected lemma IsLittleOTVS.smul_left {f : α → E} {g : α → F} {l : Filter · gcongr all_goals exact fun _ ↦ Filter.nonempty_of_mem ‹_› -lemma isLittleOTVS_one [ContinuousSMul 𝕜 E] {f : α → E} {l : Filter α} : - f =o[𝕜;l] (1 : α → 𝕜) ↔ Tendsto f l (𝓝 0) := by +lemma isLittleOTVS_one [ContinuousSMul 𝕜 E] : f =o[𝕜;l] (1 : α → 𝕜) ↔ Tendsto f l (𝓝 0) := by constructor · intro hf rw [(basis_sets _).isLittleOTVS_iff nhds_basis_ball] at hf @@ -149,8 +235,8 @@ lemma isLittleOTVS_one [ContinuousSMul 𝕜 E] {f : α → E} {l : Filter α} : apply le_mul_of_one_le_right' simpa using le_egauge_ball_one 𝕜 (1 : 𝕜) -lemma IsLittleOTVS.tendsto_inv_smul [ContinuousSMul 𝕜 E] {f : α → 𝕜} {g : α → E} {l : Filter α} - (h : g =o[𝕜;l] f) : Tendsto (fun x ↦ (f x)⁻¹ • g x) l (𝓝 0) := by +lemma IsLittleOTVS.tendsto_inv_smul [ContinuousSMul 𝕜 E] {f : α → 𝕜} {g : α → E} (h : g =o[𝕜;l] f) : + Tendsto (fun x ↦ (f x)⁻¹ • g x) l (𝓝 0) := by rw [← isLittleOTVS_one (𝕜 := 𝕜)] intro U hU rcases h.smul_left f⁻¹ U hU with ⟨V, hV₀, hV⟩ @@ -160,19 +246,9 @@ lemma IsLittleOTVS.tendsto_inv_smul [ContinuousSMul 𝕜 E] {f : α → 𝕜} {g lemma isLittleOTVS_iff_tendsto_inv_smul [ContinuousSMul 𝕜 E] {f : α → 𝕜} {g : α → E} {l : Filter α} (h₀ : ∀ᶠ x in l, f x = 0 → g x = 0) : g =o[𝕜;l] f ↔ Tendsto (fun x ↦ (f x)⁻¹ • g x) l (𝓝 0) := by - refine ⟨IsLittleOTVS.tendsto_inv_smul, fun h U hU ↦ ?_⟩ - refine ⟨ball 0 1, ball_mem_nhds _ one_pos, fun ε hε ↦ ?_⟩ - rcases NormedField.exists_norm_lt 𝕜 hε.bot_lt with ⟨c, hc₀, hcε : ‖c‖₊ < ε⟩ - rw [norm_pos_iff] at hc₀ - filter_upwards [h₀, h <| (set_smul_mem_nhds_zero_iff hc₀).2 hU] - with x hx₀ (hx : (f x)⁻¹ • g x ∈ c • U) - rcases eq_or_ne (f x) 0 with hf₀ | hf₀ - · simp [hx₀ hf₀, Filter.nonempty_of_mem hU] - · rw [mem_smul_set_iff_inv_smul_mem₀ hc₀, smul_smul] at hx - refine (egauge_le_of_smul_mem_of_ne hx (by simp [*])).trans ?_ - simp_rw [nnnorm_mul, nnnorm_inv, mul_inv, inv_inv, ENNReal.coe_mul] - gcongr - apply le_egauge_ball_one + refine ⟨IsLittleOTVS.tendsto_inv_smul, fun h ↦ ?_⟩ + refine (((isLittleOTVS_one (𝕜 := 𝕜)).mpr h).smul_left f).congr' (h₀.mono fun x hx ↦ ?_) (by simp) + by_cases h : f x = 0 <;> simp [h, hx] end TopologicalSpace @@ -215,7 +291,7 @@ lemma isLittleOTVS_iff_isLittleO {f : α → E} {g : α → F} {l : Filter α} : _ = δ * ‖g x‖₊ := by simp _ ≤ δ * egauge 𝕜 (ball 0 1) (g x) := by gcongr; apply le_egauge_ball_one -alias ⟨isLittleOTVS.isLittleO, IsLittle.isLittleOTVS⟩ := isLittleOTVS_iff_isLittleO +alias ⟨isLittleOTVS.isLittleO, IsLittleO.isLittleOTVS⟩ := isLittleOTVS_iff_isLittleO end NormedSpace diff --git a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean index e49d2ade9920f..d632bf40052df 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean @@ -336,7 +336,7 @@ theorem hasFDerivAt_iff_isLittleO_nhds_zero : nonrec theorem HasFDerivAtFilter.mono (h : HasFDerivAtFilter f f' x L₂) (hst : L₁ ≤ L₂) : HasFDerivAtFilter f f' x L₁ := - .of_isLittleO <| h.isLittleO.mono hst + .of_isLittleOTVS <| h.isLittleOTVS.mono hst theorem HasFDerivWithinAt.mono_of_mem_nhdsWithin (h : HasFDerivWithinAt f f' t x) (hst : t ∈ 𝓝[s] x) : @@ -392,8 +392,8 @@ lemma hasFDerivWithinAt_of_isOpen (h : IsOpen s) (hx : x ∈ s) : theorem hasFDerivWithinAt_insert {y : E} : HasFDerivWithinAt f f' (insert y s) x ↔ HasFDerivWithinAt f f' s x := by rcases eq_or_ne x y with (rfl | h) - · simp_rw [HasFDerivWithinAt, hasFDerivAtFilter_iff_isLittleO] - apply Asymptotics.isLittleO_insert + · simp_rw [HasFDerivWithinAt, hasFDerivAtFilter_iff_isLittleOTVS] + apply isLittleOTVS_insert simp only [sub_self, map_zero] refine ⟨fun h => h.mono <| subset_insert y s, fun hf => hf.mono_of_mem_nhdsWithin ?_⟩ simp_rw [nhdsWithin_insert_of_ne h, self_mem_nhdsWithin] @@ -418,9 +418,9 @@ theorem HasFDerivAtFilter.isBigO_sub (h : HasFDerivAtFilter f f' x L) : @[fun_prop] protected theorem HasStrictFDerivAt.hasFDerivAt (hf : HasStrictFDerivAt f f' x) : - HasFDerivAt f f' x := by - rw [HasFDerivAt, hasFDerivAtFilter_iff_isLittleO, isLittleO_iff] - exact fun c hc => tendsto_id.prod_mk_nhds tendsto_const_nhds (isLittleO_iff.1 hf.isLittleO hc) + HasFDerivAt f f' x := + .of_isLittleOTVS <| by + simpa only using hf.isLittleOTVS.comp_tendsto (tendsto_id.prod_mk_nhds tendsto_const_nhds) protected theorem HasStrictFDerivAt.differentiableAt (hf : HasStrictFDerivAt f f' x) : DifferentiableAt 𝕜 f x := @@ -469,7 +469,7 @@ theorem hasFDerivWithinAt_inter (h : t ∈ 𝓝 x) : theorem HasFDerivWithinAt.union (hs : HasFDerivWithinAt f f' s x) (ht : HasFDerivWithinAt f f' t x) : HasFDerivWithinAt f f' (s ∪ t) x := by simp only [HasFDerivWithinAt, nhdsWithin_union] - exact .of_isLittleO <| hs.isLittleO.sup ht.isLittleO + exact .of_isLittleOTVS <| hs.isLittleOTVS.sup ht.isLittleOTVS theorem HasFDerivWithinAt.hasFDerivAt (h : HasFDerivWithinAt f f' s x) (hs : s ∈ 𝓝 x) : HasFDerivAt f f' x := by @@ -483,8 +483,9 @@ theorem DifferentiableWithinAt.differentiableAt (h : DifferentiableWithinAt 𝕜 as this statement is empty. -/ theorem HasFDerivWithinAt.of_nhdsWithin_eq_bot (h : 𝓝[s\{x}] x = ⊥) : HasFDerivWithinAt f f' s x := by - rw [← hasFDerivWithinAt_diff_singleton x, HasFDerivWithinAt, h, hasFDerivAtFilter_iff_isLittleO] - apply isLittleO_bot + rw [← hasFDerivWithinAt_diff_singleton x, HasFDerivWithinAt, h, + hasFDerivAtFilter_iff_isLittleOTVS] + exact .bot /-- If `x` is not in the closure of `s`, then `f` has any derivative at `x` within `s`, as this statement is empty. -/ @@ -783,8 +784,8 @@ theorem fderivWithin_eventually_congr_set (h : s =ᶠ[𝓝 x] t) : theorem Filter.EventuallyEq.hasStrictFDerivAt_iff (h : f₀ =ᶠ[𝓝 x] f₁) (h' : ∀ y, f₀' y = f₁' y) : HasStrictFDerivAt f₀ f₀' x ↔ HasStrictFDerivAt f₁ f₁' x := by - rw [hasStrictFDerivAt_iff_isLittleO, hasStrictFDerivAt_iff_isLittleO] - refine isLittleO_congr ((h.prod_mk_nhds h).mono ?_) .rfl + rw [hasStrictFDerivAt_iff_isLittleOTVS, hasStrictFDerivAt_iff_isLittleOTVS] + refine isLittleOTVS_congr ((h.prod_mk_nhds h).mono ?_) .rfl rintro p ⟨hp₁, hp₂⟩ simp only [*] @@ -805,8 +806,8 @@ theorem HasStrictFDerivAt.congr_of_eventuallyEq (h : HasStrictFDerivAt f f' x) theorem Filter.EventuallyEq.hasFDerivAtFilter_iff (h₀ : f₀ =ᶠ[L] f₁) (hx : f₀ x = f₁ x) (h₁ : ∀ x, f₀' x = f₁' x) : HasFDerivAtFilter f₀ f₀' x L ↔ HasFDerivAtFilter f₁ f₁' x L := by - simp only [hasFDerivAtFilter_iff_isLittleO] - exact isLittleO_congr (h₀.mono fun y hy => by simp only [hy, h₁, hx]) .rfl + simp only [hasFDerivAtFilter_iff_isLittleOTVS] + exact isLittleOTVS_congr (h₀.mono fun y hy => by simp only [hy, h₁, hx]) .rfl theorem HasFDerivAtFilter.congr_of_eventuallyEq (h : HasFDerivAtFilter f f' x L) (hL : f₁ =ᶠ[L] f) (hx : f₁ x = f x) : HasFDerivAtFilter f₁ f' x L := @@ -947,10 +948,10 @@ section id @[fun_prop] theorem hasStrictFDerivAt_id (x : E) : HasStrictFDerivAt id (id 𝕜 E) x := - .of_isLittleO <| (isLittleO_zero _ _).congr_left <| by simp + .of_isLittleOTVS <| (IsLittleOTVS.zero _ _).congr_left <| by simp theorem hasFDerivAtFilter_id (x : E) (L : Filter E) : HasFDerivAtFilter id (id 𝕜 E) x L := - .of_isLittleO <| (isLittleO_zero _ _).congr_left <| by simp + .of_isLittleOTVS <| (IsLittleOTVS.zero _ _).congr_left <| by simp @[fun_prop] theorem hasFDerivWithinAt_id (x : E) (s : Set E) : HasFDerivWithinAt id (id 𝕜 E) s x := @@ -1014,11 +1015,13 @@ section Const @[fun_prop] theorem hasStrictFDerivAt_const (c : F) (x : E) : HasStrictFDerivAt (fun _ => c) (0 : E →L[𝕜] F) x := - .of_isLittleO <| (isLittleO_zero _ _).congr_left fun _ => by simp only [zero_apply, sub_self] + .of_isLittleOTVS <| (IsLittleOTVS.zero _ _).congr_left fun _ => by + simp only [zero_apply, sub_self, Pi.zero_apply] theorem hasFDerivAtFilter_const (c : F) (x : E) (L : Filter E) : HasFDerivAtFilter (fun _ => c) (0 : E →L[𝕜] F) x L := - .of_isLittleO <| (isLittleO_zero _ _).congr_left fun _ => by simp only [zero_apply, sub_self] + .of_isLittleOTVS <| (IsLittleOTVS.zero _ _).congr_left fun _ => by + simp only [zero_apply, sub_self, Pi.zero_apply] @[fun_prop] theorem hasFDerivWithinAt_const (c : F) (x : E) (s : Set E) : diff --git a/Mathlib/Analysis/Calculus/FDeriv/Linear.lean b/Mathlib/Analysis/Calculus/FDeriv/Linear.lean index 04cb11b2e3743..7a7ffd50334e8 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Linear.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Linear.lean @@ -42,10 +42,12 @@ predicate `IsBoundedLinearMap`). We give statements for both versions. -/ @[fun_prop] protected theorem ContinuousLinearMap.hasStrictFDerivAt {x : E} : HasStrictFDerivAt e e x := - .of_isLittleO <| (isLittleO_zero _ _).congr_left fun x => by simp only [e.map_sub, sub_self] + .of_isLittleOTVS <| (IsLittleOTVS.zero _ _).congr_left fun x => by + simp only [e.map_sub, sub_self, Pi.zero_apply] protected theorem ContinuousLinearMap.hasFDerivAtFilter : HasFDerivAtFilter e e x L := - .of_isLittleO <| (isLittleO_zero _ _).congr_left fun x => by simp only [e.map_sub, sub_self] + .of_isLittleOTVS <| (IsLittleOTVS.zero _ _).congr_left fun x => by + simp only [e.map_sub, sub_self, Pi.zero_apply] @[fun_prop] protected theorem ContinuousLinearMap.hasFDerivWithinAt : HasFDerivWithinAt e e s x := diff --git a/Mathlib/Analysis/Convex/EGauge.lean b/Mathlib/Analysis/Convex/EGauge.lean index 6a61629fae9e7..5083bf5351560 100644 --- a/Mathlib/Analysis/Convex/EGauge.lean +++ b/Mathlib/Analysis/Convex/EGauge.lean @@ -61,6 +61,14 @@ lemma egauge_eq_top : egauge 𝕜 s x = ∞ ↔ ∀ c : 𝕜, x ∉ c • s := b lemma egauge_lt_iff : egauge 𝕜 s x < r ↔ ∃ c : 𝕜, x ∈ c • s ∧ ‖c‖₊ < r := by simp [egauge, iInf_lt_iff] +lemma egauge_union (s t : Set E) (x : E) : egauge 𝕜 (s ∪ t) x = egauge 𝕜 s x ⊓ egauge 𝕜 t x := by + unfold egauge + simp [smul_set_union, iInf_or, iInf_inf_eq] + +lemma le_egauge_inter (s t : Set E) (x : E) : + egauge 𝕜 s x ⊔ egauge 𝕜 t x ≤ egauge 𝕜 (s ∩ t) x := + max_le_iff.2 ⟨egauge_anti _ inter_subset_left _, egauge_anti _ inter_subset_right _⟩ + end SMul section SMulZero diff --git a/Mathlib/Order/Filter/Bases.lean b/Mathlib/Order/Filter/Bases.lean index 6a5d64a703e88..7a5323677a3f2 100644 --- a/Mathlib/Order/Filter/Bases.lean +++ b/Mathlib/Order/Filter/Bases.lean @@ -827,6 +827,11 @@ lemma eventually_prod_self_iff {r : α → α → Prop} : (∀ᶠ x in la ×ˢ la, r x.1 x.2) ↔ ∃ t ∈ la, ∀ x ∈ t, ∀ y ∈ t, r x y := mem_prod_self_iff.trans <| by simp only [prod_subset_iff, mem_setOf_eq] +/-- A version of `eventually_prod_self_iff` that is more suitable for forward rewriting. -/ +lemma eventually_prod_self_iff' {r : α × α → Prop} : + (∀ᶠ x in la ×ˢ la, r x) ↔ ∃ t ∈ la, ∀ x ∈ t, ∀ y ∈ t, r (x, y) := + Iff.symm eventually_prod_self_iff.symm + theorem HasAntitoneBasis.prod {ι : Type*} [LinearOrder ι] {f : Filter α} {g : Filter β} {s : ι → Set α} {t : ι → Set β} (hf : HasAntitoneBasis f s) (hg : HasAntitoneBasis g t) : HasAntitoneBasis (f ×ˢ g) fun n => s n ×ˢ t n := From afd9d57ac58fb2f91a780349c95217ee5a131ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 13 Jan 2025 10:02:37 +0000 Subject: [PATCH 184/681] feat: transversals of a finite index subgroup are finite (#19871) From FLT --- Mathlib/GroupTheory/Complement.lean | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Mathlib/GroupTheory/Complement.lean b/Mathlib/GroupTheory/Complement.lean index 4425a82f957a6..afafd4588a723 100644 --- a/Mathlib/GroupTheory/Complement.lean +++ b/Mathlib/GroupTheory/Complement.lean @@ -140,6 +140,27 @@ theorem isComplement_univ_right : IsComplement S univ ↔ ∃ g : G, S = {g} := lemma IsComplement.mul_eq (h : IsComplement S T) : S * T = univ := eq_univ_of_forall fun x ↦ by simpa [mem_mul] using (h.existsUnique x).exists +@[to_additive (attr := simp)] +lemma not_isComplement_empty_left : ¬ IsComplement ∅ T := + fun h ↦ by simpa [eq_comm (a := ∅)] using h.mul_eq + +@[to_additive (attr := simp)] +lemma not_isComplement_empty_right : ¬ IsComplement S ∅ := + fun h ↦ by simpa [eq_comm (a := ∅)] using h.mul_eq + +@[to_additive] +lemma IsComplement.nonempty_left (hst : IsComplement S T) : S.Nonempty := by + contrapose! hst; simp [hst] + +@[to_additive] +lemma IsComplement.nonempty_right (hst : IsComplement S T) : T.Nonempty := by + contrapose! hst; simp [hst] + +@[to_additive] lemma IsComplement.pairwiseDisjoint_smul (hst : IsComplement S T) : + S.PairwiseDisjoint (· • T) := fun a ha b hb hab ↦ disjoint_iff_forall_ne.2 <| by + rintro _ ⟨c, hc, rfl⟩ _ ⟨d, hd, rfl⟩ + exact hst.1.ne (a₁ := (⟨a, ha⟩, ⟨c, hc⟩)) (a₂:= (⟨b, hb⟩, ⟨d, hd⟩)) (by simp [hab]) + @[to_additive AddSubgroup.IsComplement.card_mul_card] lemma IsComplement.card_mul_card (h : IsComplement S T) : Nat.card S * Nat.card T = Nat.card G := (Nat.card_prod _ _).symm.trans <| Nat.card_congr <| Equiv.ofBijective _ h @@ -577,6 +598,9 @@ theorem finite_left_iff (h : IsComplement S H) : Finite S ↔ H.FiniteIndex := b @[deprecated (since := "2024-12-28")] alias _root_.Subgroup.MemLeftTransversals.finite_iff := finite_left_iff +@[to_additive] +lemma finite_left [H.FiniteIndex] (hS : IsComplement S H) : S.Finite := hS.finite_left_iff.2 ‹_› + @[to_additive] theorem quotientGroupMk_leftQuotientEquiv (hS : IsComplement S H) (q : G ⧸ H) : Quotient.mk'' (leftQuotientEquiv hS q : G) = q := @@ -638,6 +662,9 @@ theorem finite_right_iff (h : IsComplement H T) : Finite T ↔ H.FiniteIndex := @[deprecated (since := "2024-12-28")] alias _root_.Subgroup.MemRightTransversals.finite_iff := finite_right_iff +@[to_additive] +lemma finite_right [H.FiniteIndex] (hT : IsComplement H T) : T.Finite := hT.finite_right_iff.2 ‹_› + @[to_additive] theorem mk''_rightQuotientEquiv (hT : IsComplement H T) (q : Quotient (QuotientGroup.rightRel H)) : Quotient.mk'' (rightQuotientEquiv hT q : G) = q := From 4f2a1292fb83476bbef2f35037dfd06bf1e792ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 13 Jan 2025 10:02:39 +0000 Subject: [PATCH 185/681] feat(SetTheory): the predicate HasCardinalLT (#19959) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We introduce the universe-heterogeneous predicate `HasCardinalLT X κ` for `X : Type u` and `κ : Cardinal.{v}` saying that the cardinal of `X` is (strictly) less than `κ`. (This shall be used in the formalization of `κ`-filtered categories, which generalize filtered categories.) --- Mathlib.lean | 1 + Mathlib/SetTheory/Cardinal/HasCardinalLT.lean | 76 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 Mathlib/SetTheory/Cardinal/HasCardinalLT.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7df6dee99bbc6..64075586bf269 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4771,6 +4771,7 @@ import Mathlib.SetTheory.Cardinal.ENat import Mathlib.SetTheory.Cardinal.Finite import Mathlib.SetTheory.Cardinal.Finsupp import Mathlib.SetTheory.Cardinal.Free +import Mathlib.SetTheory.Cardinal.HasCardinalLT import Mathlib.SetTheory.Cardinal.SchroederBernstein import Mathlib.SetTheory.Cardinal.Subfield import Mathlib.SetTheory.Cardinal.ToNat diff --git a/Mathlib/SetTheory/Cardinal/HasCardinalLT.lean b/Mathlib/SetTheory/Cardinal/HasCardinalLT.lean new file mode 100644 index 0000000000000..b14bed334c1f0 --- /dev/null +++ b/Mathlib/SetTheory/Cardinal/HasCardinalLT.lean @@ -0,0 +1,76 @@ +/- +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.SetTheory.Ordinal.Basic + +/-! +# The property of being of cardinality less than a cardinal + +Given `X : Type u` and `κ : Cardinal.{v}`, we introduce a predicate +`HasCardinalLT X κ` expressing that +`Cardinal.lift.{v} (Cardinal.mk X) < Cardinal.lift κ`. + +-/ + +universe w v u u' + +/-- The property that the cardinal of a type `X : Type u` is less than `κ : Cardinal.{v}`. -/ +def HasCardinalLT (X : Type u) (κ : Cardinal.{v}) : Prop := + Cardinal.lift.{v} (Cardinal.mk X) < Cardinal.lift κ + +lemma hasCardinalLT_iff_cardinal_mk_lt (X : Type u) (κ : Cardinal.{u}) : + HasCardinalLT X κ ↔ Cardinal.mk X < κ := by + simp [HasCardinalLT] + +namespace HasCardinalLT + +section + +variable {X : Type u} {κ : Cardinal.{v}} (h : HasCardinalLT X κ) + +include h + +lemma small : Small.{v} X := by + dsimp [HasCardinalLT] at h + rw [← Cardinal.lift_lt.{_, v + 1}, Cardinal.lift_lift, Cardinal.lift_lift] at h + simpa only [Cardinal.small_iff_lift_mk_lt_univ] using h.trans (Cardinal.lift_lt_univ' κ) + +lemma of_le {κ' : Cardinal.{v}} (hκ' : κ ≤ κ') : + HasCardinalLT X κ' := + lt_of_lt_of_le h (by simpa only [Cardinal.lift_le] using hκ') + +variable {Y : Type u'} + +lemma of_injective (f : Y → X) (hf : Function.Injective f) : + HasCardinalLT Y κ := by + dsimp [HasCardinalLT] at h ⊢ + rw [← Cardinal.lift_lt.{_, u}, Cardinal.lift_lift, Cardinal.lift_lift] + rw [← Cardinal.lift_lt.{_, u'}, Cardinal.lift_lift, Cardinal.lift_lift] at h + exact lt_of_le_of_lt (Cardinal.mk_le_of_injective + (Function.Injective.comp ULift.up_injective + (Function.Injective.comp hf ULift.down_injective))) h + +lemma of_surjective (f : X → Y) (hf : Function.Surjective f) : + HasCardinalLT Y κ := by + dsimp [HasCardinalLT] at h ⊢ + rw [← Cardinal.lift_lt.{_, u}, Cardinal.lift_lift, Cardinal.lift_lift] + rw [← Cardinal.lift_lt.{_, u'}, Cardinal.lift_lift, Cardinal.lift_lift] at h + exact lt_of_le_of_lt (Cardinal.mk_le_of_surjective + (Function.Surjective.comp ULift.up_surjective (Function.Surjective.comp hf + ULift.down_surjective))) h + +end + +end HasCardinalLT + +lemma hasCardinalLT_iff_of_equiv {X : Type u} {Y : Type u'} (e : X ≃ Y) (κ : Cardinal.{v}) : + HasCardinalLT X κ ↔ HasCardinalLT Y κ := + ⟨fun h ↦ h.of_injective _ e.symm.injective, + fun h ↦ h.of_injective _ e.injective⟩ + +@[simp] +lemma hasCardinalLT_aleph0_iff (X : Type u) : + HasCardinalLT X Cardinal.aleph0.{v} ↔ Finite X := by + simpa [HasCardinalLT] using Cardinal.mk_lt_aleph0_iff From bc14fcf5e5df8280e2f0638462d890b9d40d79ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 13 Jan 2025 10:02:40 +0000 Subject: [PATCH 186/681] feat: the localization of `R[X]` at `S` is the polynomial ring over the localization of `R` at `S` (#20070) From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang Co-authored-by: Junyan Xu --- Mathlib/RingTheory/Localization/Algebra.lean | 22 ++++++++++++++++++- .../RingTheory/MvPolynomial/Localization.lean | 3 ++- Mathlib/RingTheory/PolynomialAlgebra.lean | 17 ++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Mathlib/RingTheory/Localization/Algebra.lean b/Mathlib/RingTheory/Localization/Algebra.lean index b52b401bdd5bf..a0808ee9ad79b 100644 --- a/Mathlib/RingTheory/Localization/Algebra.lean +++ b/Mathlib/RingTheory/Localization/Algebra.lean @@ -3,10 +3,12 @@ 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.Algebra.Module.LocalizedModule.Basic +import Mathlib.Algebra.Module.LocalizedModule.IsLocalization import Mathlib.RingTheory.Ideal.Maps +import Mathlib.RingTheory.Localization.BaseChange import Mathlib.RingTheory.Localization.Basic import Mathlib.RingTheory.Localization.Ideal +import Mathlib.RingTheory.PolynomialAlgebra /-! # Localization of algebra maps @@ -142,3 +144,21 @@ lemma AlgHom.toKerIsLocalization_isLocalizedModule (f : A →ₐ[R] B) : (algebraMapSubmonoid_map_eq M f) end Algebra + +namespace Polynomial + +/-- If `A` is the localization of `R` at a submonoid `S`, then `A[X]` is the localization of +`R[X]` at `S.map Polynomial.C`. + +See also `MvPolynomial.isLocalization` for the multivariate case. -/ +lemma isLocalization {R} [CommRing R] (S : Submonoid R) (A) [CommRing A] [Algebra R A] + [IsLocalization S A] : letI := (mapRingHom (algebraMap R A)).toAlgebra + IsLocalization (S.map C) A[X] := by + letI := (mapRingHom (algebraMap R A)).toAlgebra + have : IsScalarTower R R[X] A[X] := .of_algebraMap_eq fun _ ↦ (map_C _).symm + apply isLocalizedModule_iff_isLocalization.mp <| (isLocalizedModule_iff_isBaseChange S A _).mpr <| + .of_equiv (polyEquivTensor' R A).symm.toLinearEquiv fun _ ↦ ?_ + show _ = eval₂ .. + simp [eval₂, ← C_mul_X_pow_eq_monomial] + +end Polynomial diff --git a/Mathlib/RingTheory/MvPolynomial/Localization.lean b/Mathlib/RingTheory/MvPolynomial/Localization.lean index e3fb28794c4d7..3305ae399295c 100644 --- a/Mathlib/RingTheory/MvPolynomial/Localization.lean +++ b/Mathlib/RingTheory/MvPolynomial/Localization.lean @@ -37,7 +37,8 @@ attribute [local instance] algebraMvPolynomial /-- If `S` is the localization of `R` at a submonoid `M`, then `MvPolynomial σ S` is the localization of `MvPolynomial σ R` at `M.map MvPolynomial.C`. --/ + +See also `Polynomial.isLocalization` for the univariate case. -/ instance isLocalization : IsLocalization (M.map <| C (σ := σ)) (MvPolynomial σ S) := isLocalizedModule_iff_isLocalization.mp <| (isLocalizedModule_iff_isBaseChange M S _).mpr <| .of_equiv (algebraTensorAlgEquiv _ _).toLinearEquiv fun _ ↦ by simp diff --git a/Mathlib/RingTheory/PolynomialAlgebra.lean b/Mathlib/RingTheory/PolynomialAlgebra.lean index 545734d52795a..29d0e3114f3f3 100644 --- a/Mathlib/RingTheory/PolynomialAlgebra.lean +++ b/Mathlib/RingTheory/PolynomialAlgebra.lean @@ -185,6 +185,23 @@ theorem polyEquivTensor_symm_apply_tmul (a : A) (p : R[X]) : (polyEquivTensor R A).symm (a ⊗ₜ p) = p.sum fun n r => monomial n (a * algebraMap R A r) := toFunAlgHom_apply_tmul _ _ _ _ +section + +variable (A : Type*) [CommSemiring A] [Algebra R A] + +/-- The `A`-algebra isomorphism `A[X] ≃ₐ[A] A ⊗[R] R[X]` (when `A` is commutative). -/ +def polyEquivTensor' : A[X] ≃ₐ[A] A ⊗[R] R[X] where + __ := polyEquivTensor R A + commutes' a := by simp + +/-- `polyEquivTensor' R A` is the same as `polyEquivTensor R A` as a function. -/ +@[simp] theorem coe_polyEquivTensor' : ⇑(polyEquivTensor' R A) = polyEquivTensor R A := rfl + +@[simp] theorem coe_polyEquivTensor'_symm : + ⇑(polyEquivTensor' R A).symm = (polyEquivTensor R A).symm := rfl + +end + open DMatrix Matrix variable {R} From cf581dca789cad8b7749cf565ddbc941b298f2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 13 Jan 2025 10:02:42 +0000 Subject: [PATCH 187/681] =?UTF-8?q?feat:=20`(=E2=88=8F=E1=B6=A0=20i,=20f?= =?UTF-8?q?=20i)=20a=20=3D=20=E2=88=8F=E1=B6=A0=20i,=20f=20i=20a`=20(#2020?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From FLT Co-authored-by: Kevin Buzzard --- Mathlib/Algebra/BigOperators/Finprod.lean | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/BigOperators/Finprod.lean b/Mathlib/Algebra/BigOperators/Finprod.lean index c884837950fd6..8ae6102ffc0b9 100644 --- a/Mathlib/Algebra/BigOperators/Finprod.lean +++ b/Mathlib/Algebra/BigOperators/Finprod.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kexing Ying, Kevin Buzzard, Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.GroupWithZero.Finset +import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.Group.FiniteSupport import Mathlib.Algebra.NoZeroSMulDivisors.Basic import Mathlib.Algebra.Order.BigOperators.Group.Finset @@ -319,13 +320,17 @@ theorem finprod_eq_mulIndicator_apply (s : Set α) (f : α → M) (a : α) : classical convert finprod_eq_if (M := M) (p := a ∈ s) (x := f a) @[to_additive (attr := simp)] -theorem finprod_mem_mulSupport (f : α → M) (a : α) : ∏ᶠ _ : f a ≠ 1, f a = f a := by +theorem finprod_apply_ne_one (f : α → M) (a : α) : ∏ᶠ _ : f a ≠ 1, f a = f a := by rw [← mem_mulSupport, finprod_eq_mulIndicator_apply, mulIndicator_mulSupport] @[to_additive] theorem finprod_mem_def (s : Set α) (f : α → M) : ∏ᶠ a ∈ s, f a = ∏ᶠ a, mulIndicator s f a := finprod_congr <| finprod_eq_mulIndicator_apply s f +@[to_additive] +lemma finprod_mem_mulSupport (f : α → M) : ∏ᶠ a ∈ mulSupport f, f a = ∏ᶠ a, f a := by + rw [finprod_mem_def, mulIndicator_mulSupport] + @[to_additive] theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) : ∏ᶠ i, f i = ∏ i ∈ s, f i := by @@ -921,6 +926,16 @@ theorem finprod_mem_sUnion {t : Set (Set α)} (h : t.PairwiseDisjoint id) (ht₀ rw [Set.sUnion_eq_biUnion] exact finprod_mem_biUnion h ht₀ ht₁ +@[to_additive] +lemma finprod_option {f : Option α → M} (hf : (mulSupport (f ∘ some)).Finite) : + ∏ᶠ o, f o = f none * ∏ᶠ a, f (some a) := by + replace hf : (mulSupport f).Finite := by simpa [finite_option] + convert finprod_mem_insert' f (show none ∉ Set.range Option.some by aesop) + (hf.subset inter_subset_right) + · aesop + · rw [finprod_mem_range] + exact Option.some_injective _ + @[to_additive] theorem mul_finprod_cond_ne (a : α) (hf : (mulSupport f).Finite) : (f a * ∏ᶠ (i) (_ : i ≠ a), f i) = ∏ᶠ i, f i := by @@ -1008,6 +1023,15 @@ theorem finsum_mul {R : Type*} [Semiring R] (f : α → R) (r : R) (h : (support (∑ᶠ a : α, f a) * r = ∑ᶠ a : α, f a * r := (AddMonoidHom.mulRight r).map_finsum h +@[to_additive (attr := simp)] +lemma finprod_apply {α ι : Type*} {f : ι → α → N} (hf : (mulSupport f).Finite) (a : α) : + (∏ᶠ i, f i) a = ∏ᶠ i, f i a := by + classical + have hf' : (mulSupport fun i ↦ f i a).Finite := hf.subset (by aesop) + simp only [finprod_def, dif_pos, hf, hf', Finset.prod_apply] + symm + apply Finset.prod_subset <;> aesop + @[to_additive] theorem Finset.mulSupport_of_fiberwise_prod_subset_image [DecidableEq β] (s : Finset α) (f : α → M) (g : α → β) : (mulSupport fun b => (s.filter fun a => g a = b).prod f) ⊆ s.image g := by From ff261afd24ab0bfcc06443b5abf2c7f13a7e6b2a Mon Sep 17 00:00:00 2001 From: Quang Dao Date: Mon, 13 Jan 2025 10:02:43 +0000 Subject: [PATCH 188/681] feat(Data/Finsupp/Fin): Lemmas relating `Finsupp.{tail/update}` (#20361) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a sub-PR for #19315 as requested by Yaël It adds two lemmas relating `Finsupp.tail` with `Finsupp.update`, similar to the equivalent version on `Fin`. Co-authored-by: Quang Dao Co-authored-by: Yaël Dillies --- Mathlib/Data/Finsupp/Defs.lean | 3 +++ Mathlib/Data/Finsupp/Fin.lean | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index 538a8cf25d50c..d3ab7840c2b6f 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -197,6 +197,9 @@ def equivFunOnFinite [Finite α] : (α →₀ M) ≃ (α → M) where theorem equivFunOnFinite_symm_coe {α} [Finite α] (f : α →₀ M) : equivFunOnFinite.symm f = f := equivFunOnFinite.symm_apply_apply f +@[simp] +lemma coe_equivFunOnFinite_symm {α} [Finite α] (f : α → M) : ⇑(equivFunOnFinite.symm f) = f := rfl + /-- If `α` has a unique term, the type of finitely supported functions `α →₀ β` is equivalent to `β`. -/ diff --git a/Mathlib/Data/Finsupp/Fin.lean b/Mathlib/Data/Finsupp/Fin.lean index 4e7868d955fcf..146af1b20aee6 100644 --- a/Mathlib/Data/Finsupp/Fin.lean +++ b/Mathlib/Data/Finsupp/Fin.lean @@ -49,6 +49,12 @@ theorem cons_succ : cons y s i.succ = s i := theorem tail_cons : tail (cons y s) = s := ext fun k => by simp only [tail_apply, cons_succ] +@[simp] +theorem tail_update_zero : tail (update t 0 y) = tail t := by simp [tail] + +@[simp] +theorem tail_update_succ : tail (update t i.succ y) = update (tail t) i y := by ext; simp [tail] + @[simp] theorem cons_tail : cons (t 0) (tail t) = t := by ext a From 2c53e45019ee051ba652e9cbcd680eb0ea0e190e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Mon, 13 Jan 2025 10:02:44 +0000 Subject: [PATCH 189/681] =?UTF-8?q?feat:=20`IsSuccPrelimit=20a=20=E2=86=92?= =?UTF-8?q?=20IsLUB=20(Iio=20a)=20a`=20(#20496)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is somewhat more general than the statement involving `sSup`. --- .../Order/SuccPred/CompleteLinearOrder.lean | 5 +--- Mathlib/Order/SuccPred/Limit.lean | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Mathlib/Order/SuccPred/CompleteLinearOrder.lean b/Mathlib/Order/SuccPred/CompleteLinearOrder.lean index 66897b1f54ac7..6b5bcdc53e05f 100644 --- a/Mathlib/Order/SuccPred/CompleteLinearOrder.lean +++ b/Mathlib/Order/SuccPred/CompleteLinearOrder.lean @@ -142,10 +142,7 @@ alias IsLUB.exists_of_not_isSuccLimit := IsLUB.exists_of_not_isSuccPrelimit theorem Order.IsSuccPrelimit.sSup_Iio (h : IsSuccPrelimit x) : sSup (Iio x) = x := by obtain rfl | hx := eq_bot_or_bot_lt x · simp - · refine (csSup_le ⟨⊥, hx⟩ fun a ha ↦ ha.le).antisymm <| le_of_forall_lt fun a ha ↦ ?_ - rw [lt_csSup_iff' bddAbove_Iio] - obtain ⟨b, hb', hb⟩ := (not_covBy_iff ha).1 (h a) - use b, hb + · exact h.isLUB_Iio.csSup_eq ⟨⊥, hx⟩ theorem Order.IsSuccPrelimit.iSup_Iio (h : IsSuccPrelimit x) : ⨆ a : Iio x, a.1 = x := by rw [← sSup_eq_iSup', h.sSup_Iio] diff --git a/Mathlib/Order/SuccPred/Limit.lean b/Mathlib/Order/SuccPred/Limit.lean index 2497ef7e19efd..a5bf5787c8387 100644 --- a/Mathlib/Order/SuccPred/Limit.lean +++ b/Mathlib/Order/SuccPred/Limit.lean @@ -324,6 +324,20 @@ theorem IsSuccPrelimit.lt_iff_exists_lt (h : IsSuccPrelimit b) : a < b ↔ ∃ c theorem IsSuccLimit.lt_iff_exists_lt (h : IsSuccLimit b) : a < b ↔ ∃ c < b, a < c := h.isSuccPrelimit.lt_iff_exists_lt +theorem IsSuccPrelimit.isLUB_Iio (ha : IsSuccPrelimit a) : IsLUB (Iio a) a := by + refine ⟨fun _ ↦ le_of_lt, fun b hb ↦ le_of_forall_lt fun c hc ↦ ?_⟩ + obtain ⟨d, hd, hd'⟩ := ha.lt_iff_exists_lt.1 hc + exact hd'.trans_le (hb hd) + +theorem IsSuccLimit.isLUB_Iio (ha : IsSuccLimit a) : IsLUB (Iio a) a := + ha.isSuccPrelimit.isLUB_Iio + +theorem isLUB_Iio_iff_isSuccPrelimit : IsLUB (Iio a) a ↔ IsSuccPrelimit a := by + refine ⟨fun ha b hb ↦ ?_, IsSuccPrelimit.isLUB_Iio⟩ + rw [hb.Iio_eq] at ha + obtain rfl := isLUB_Iic.unique ha + cases hb.lt.false + variable [SuccOrder α] theorem IsSuccPrelimit.le_succ_iff (hb : IsSuccPrelimit b) : b ≤ succ a ↔ b ≤ a := @@ -620,6 +634,15 @@ theorem IsPredPrelimit.lt_iff_exists_lt (h : IsPredPrelimit b) : b < a ↔ ∃ c theorem IsPredLimit.lt_iff_exists_lt (h : IsPredLimit b) : b < a ↔ ∃ c, b < c ∧ c < a := h.dual.lt_iff_exists_lt +theorem IsPredPrelimit.isGLB_Ioi (ha : IsPredPrelimit a) : IsGLB (Ioi a) a := + ha.dual.isLUB_Iio + +theorem IsPredLimit.isGLB_Ioi (ha : IsPredLimit a) : IsGLB (Ioi a) a := + ha.dual.isLUB_Iio + +theorem isGLB_Ioi_iff_isPredPrelimit : IsGLB (Ioi a) a ↔ IsPredPrelimit a := by + simpa using isLUB_Iio_iff_isSuccPrelimit (a := toDual a) + variable [PredOrder α] theorem IsPredPrelimit.pred_le_iff (hb : IsPredPrelimit b) : pred a ≤ b ↔ a ≤ b := From 5cb027f051f6a73dc9ef20f57a0e76bd5086356f Mon Sep 17 00:00:00 2001 From: Michael Stoll Date: Mon, 13 Jan 2025 10:02:46 +0000 Subject: [PATCH 190/681] feat(Analysis/MeanInequalitiesPow): add Real.rpow versions of some lemmas (#20685) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds `Real.rpow` versions of four existing lemmas for `{E|}NNreal.rpow`. One of these is useful for showing that the `e`th power (with `0 < e ≤ 1`) of an absolute value is again an absolute value. We add the other three for consistency. --- Mathlib/Analysis/MeanInequalitiesPow.lean | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Mathlib/Analysis/MeanInequalitiesPow.lean b/Mathlib/Analysis/MeanInequalitiesPow.lean index fdee6d8fdbe46..b03fa232df370 100644 --- a/Mathlib/Analysis/MeanInequalitiesPow.lean +++ b/Mathlib/Analysis/MeanInequalitiesPow.lean @@ -184,6 +184,36 @@ theorem rpow_add_le_add_rpow {p : ℝ} (a b : ℝ≥0) (hp : 0 ≤ p) (hp1 : p end NNReal +namespace Real + +lemma add_rpow_le_rpow_add {p : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp1 : 1 ≤ p) : + a ^ p + b ^ p ≤ (a + b) ^ p := by + lift a to NNReal using ha + lift b to NNReal using hb + exact_mod_cast NNReal.add_rpow_le_rpow_add a b hp1 + +lemma rpow_add_rpow_le_add {p : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp1 : 1 ≤ p) : + (a ^ p + b ^ p) ^ (1 / p) ≤ a + b := by + lift a to NNReal using ha + lift b to NNReal using hb + exact_mod_cast NNReal.rpow_add_rpow_le_add a b hp1 + +lemma rpow_add_rpow_le {p q : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp_pos : 0 < p) + (hpq : p ≤ q) : + (a ^ q + b ^ q) ^ (1 / q) ≤ (a ^ p + b ^ p) ^ (1 / p) := by + lift a to NNReal using ha + lift b to NNReal using hb + exact_mod_cast NNReal.rpow_add_rpow_le a b hp_pos hpq + +lemma rpow_add_le_add_rpow {p : ℝ} {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hp : 0 ≤ p) + (hp1 : p ≤ 1) : + (a + b) ^ p ≤ a ^ p + b ^ p := by + lift a to NNReal using ha + lift b to NNReal using hb + exact_mod_cast NNReal.rpow_add_le_add_rpow a b hp hp1 + +end Real + namespace ENNReal /-- Weighted generalized mean inequality, version for sums over finite sets, with `ℝ≥0∞`-valued From 143aee40ea57134a8ab6457ff152cf265678dbef Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Mon, 13 Jan 2025 10:02:47 +0000 Subject: [PATCH 191/681] feat(GroupTheory/SpecificGroups/ZGroup): Commutator subgroup of a Z-group is a Hall subgroup (#20694) This PR proves that the commutator subgroup of a finite Z-group is a Hall subgroup. There are several intermediate results about p-groups and Sylow subgroups, but they require the heavy import of `FieldTheory/Finite/Basic`, so I decided to leave them in the Z-groups file. --- .../GroupTheory/SpecificGroups/ZGroup.lean | 123 +++++++++++++++++- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean b/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean index 957f463f0cde5..fe711a6712599 100644 --- a/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean +++ b/Mathlib/GroupTheory/SpecificGroups/ZGroup.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning -/ import Mathlib.Algebra.Squarefree.Basic +import Mathlib.FieldTheory.Finite.Basic import Mathlib.GroupTheory.Nilpotent -import Mathlib.GroupTheory.Transfer +import Mathlib.GroupTheory.SchurZassenhaus /-! # Z-Groups @@ -20,6 +21,8 @@ A Z-group is a group whose Sylow subgroups are all cyclic. * `IsZGroup.isCyclic_abelianization`: a finite Z-group has cyclic abelianization. * `IsZGroup.isCyclic_commutator`: a finite Z-group has cyclic commutator subgroup. +* `IsZGroup.coprime_commutator_index`: the commutator subgroup of a finite Z-group is a + Hall-subgroup (the commutator subgroup has cardinality coprime to its index). TODO: Show that if `G` is a Z-group with commutator subgroup `G'`, then `G = G' ⋊ G/G'` where `G'` and `G/G'` are cyclic of coprime orders. @@ -165,6 +168,122 @@ theorem isCyclic_commutator [Finite G] [IsZGroup G] : IsCyclic (commutator G) := end Commutator +end IsZGroup + +section Hall + +variable {p : ℕ} [Fact p.Prime] + +namespace IsPGroup + +/-- If a cyclic `p`-group `G` acts on a group `K` of coprime order, then the map `K × G → G` + defined by `(k, g) ↦ k • g * g⁻¹` is either trivial or surjective. -/ +theorem smul_mul_inv_trivial_or_surjective [IsCyclic G] (hG : IsPGroup p G) + {K : Type*} [Group K] [MulDistribMulAction K G] (hGK : (Nat.card G).Coprime (Nat.card K)) : + (∀ g : G, ∀ k : K, k • g * g⁻¹ = 1) ∨ (∀ g : G, ∃ k : K, ∃ q : G, k • q * q⁻¹ = g) := by + by_cases hc : Nat.card G = 0 + · rw [hc, Nat.coprime_zero_left, Nat.card_eq_one_iff_unique] at hGK + simp [← hGK.1.elim 1] + have := Nat.finite_of_card_ne_zero hc + let ϕ := MulDistribMulAction.toMonoidHomZModOfIsCyclic G K rfl + have h (g : G) (k : K) (n : ℤ) (h : ϕ k - 1 = n) : k • g * g⁻¹ = g ^ n := by + rw [sub_eq_iff_eq_add, ← Int.cast_one, ← Int.cast_add] at h + rw [MulDistribMulAction.toMonoidHomZModOfIsCyclic_apply rfl k g (n + 1) h, + zpow_add_one, mul_inv_cancel_right] + replace hG k : ϕ k = 1 ∨ IsUnit (ϕ k - 1) := by + obtain ⟨n, hn⟩ := hG.exists_card_eq + exact ZMod.eq_one_or_isUnit_sub_one hn (ϕ k) + (hGK.symm.coprime_dvd_left ((orderOf_map_dvd ϕ k).trans (orderOf_dvd_natCard k))) + rcases forall_or_exists_not (fun k : K ↦ ϕ k = 1) with hϕ | ⟨k, hk⟩ + · exact Or.inl fun p k ↦ by rw [h p k 0 (by rw [hϕ, sub_self, Int.cast_zero]), zpow_zero] + · obtain ⟨⟨u, v, -, hvu⟩, hu : u = ϕ k - 1⟩ := (hG k).resolve_left hk + rw [← u.intCast_zmod_cast] at hu hvu + rw [← v.intCast_zmod_cast, ← Int.cast_mul, ← Int.cast_one, ZMod.intCast_eq_intCast_iff] at hvu + refine Or.inr fun p ↦ zpow_one p ▸ ⟨k, p ^ (v.cast : ℤ), ?_⟩ + rw [h (p ^ v.cast) k u.cast hu.symm, ← zpow_mul, zpow_eq_zpow_iff_modEq] + exact hvu.of_dvd (Int.natCast_dvd_natCast.mpr (orderOf_dvd_natCard p)) + +/-- If a cyclic `p`-subgroup `P` acts by conjugation on a subgroup `K` of coprime order, then + either `⁅K, P⁆ = ⊥` or `⁅K, P⁆ = P`. -/ +theorem commutator_eq_bot_or_commutator_eq_self {P K : Subgroup G} [IsCyclic P] + (hP : IsPGroup p P) (hKP : K ≤ P.normalizer) (hPK : (Nat.card P).Coprime (Nat.card K)) : + ⁅K, P⁆ = ⊥ ∨ ⁅K, P⁆ = P := by + let _ := MulDistribMulAction.compHom P (P.normalizerMonoidHom.comp (Subgroup.inclusion hKP)) + refine (smul_mul_inv_trivial_or_surjective hP hPK).imp (fun h ↦ ?_) fun h ↦ ?_ + · rw [eq_bot_iff, Subgroup.commutator_le] + exact fun k hk g hg ↦ Subtype.ext_iff.mp (h ⟨g, hg⟩ ⟨k, hk⟩) + · rw [le_antisymm_iff, Subgroup.commutator_le] + refine ⟨fun k hk g hg ↦ P.mul_mem ((hKP hk g).mp hg) (P.inv_mem hg), fun g hg ↦ ?_⟩ + obtain ⟨k, q, hkq⟩ := h ⟨g, hg⟩ + rw [← Subtype.coe_mk g hg, ← hkq] + exact Subgroup.commutator_mem_commutator k.2 q.2 + +end IsPGroup + +namespace Sylow + +variable [Finite G] (P : Sylow p G) [IsCyclic P] + +/-- If a normal cyclic Sylow `p`-subgroup `P` has a complement `K`, then either `⁅K, P⁆ = ⊥` or + `⁅K, P⁆ = P`. -/ +theorem commutator_eq_bot_or_commutator_eq_self [P.Normal] {K : Subgroup G} + (h : K.IsComplement' P) : ⁅K, P.1⁆ = ⊥ ∨ ⁅K, P.1⁆ = P := + P.2.commutator_eq_bot_or_commutator_eq_self (P.normalizer_eq_top ▸ le_top) + (h.index_eq_card ▸ P.card_coprime_index) + +/-- A normal cyclic Sylow subgroup is either central or contained in the commutator subgroup. -/ +theorem le_center_or_le_commutator [P.Normal] : P ≤ Subgroup.center G ∨ P ≤ commutator G := by + obtain ⟨K, hK⟩ := Subgroup.exists_left_complement'_of_coprime P.card_coprime_index + refine (commutator_eq_bot_or_commutator_eq_self P hK).imp (fun h ↦ ?_) (fun h ↦ ?_) + · replace h := sup_le (Subgroup.commutator_eq_bot_iff_le_centralizer.mp h) P.le_centralizer + rwa [hK.sup_eq_top, top_le_iff, Subgroup.centralizer_eq_top_iff_subset] at h + · rw [← h, commutator_def] + exact Subgroup.commutator_mono le_top le_top + +/-- A cyclic Sylow subgroup is either central in its normalizer or contained in the commutator + subgroup. -/ +theorem normalizer_le_centralizer_or_le_commutator : + P.normalizer ≤ Subgroup.centralizer P ∨ P ≤ commutator G := by + let Q : Sylow p P.normalizer := P.subtype P.le_normalizer + have : Q.Normal := P.normal_in_normalizer + have : IsCyclic Q := + isCyclic_of_surjective _ (Subgroup.subgroupOfEquivOfLe P.le_normalizer).symm.surjective + refine (le_center_or_le_commutator Q).imp (fun h ↦ ?_) (fun h ↦ ?_) + · rw [← SetLike.coe_subset_coe, ← Subgroup.centralizer_eq_top_iff_subset, eq_top_iff, + ← Subgroup.map_subtype_le_map_subtype, ← MonoidHom.range_eq_map, + P.normalizer.range_subtype] at h + replace h := h.trans (Subgroup.map_centralizer_le_centralizer_image _ _) + rwa [← Subgroup.coe_map, P.coe_subtype, Subgroup.map_subgroupOf_eq_of_le P.le_normalizer] at h + · rw [P.coe_subtype, ← Subgroup.map_subtype_le_map_subtype, + Subgroup.map_subgroupOf_eq_of_le P.le_normalizer, Subgroup.map_subtype_commutator] at h + exact h.trans (Subgroup.commutator_mono le_top le_top) + +include P in +/-- If `G` has a cyclic Sylow `p`-subgroup, then the cardinality and index of the commutator + subgroup of `G` cannot both be divisible by `p`. -/ +theorem not_dvd_card_commutator_or_not_dvd_index_commutator : + ¬ p ∣ Nat.card (commutator G) ∨ ¬ p ∣ (commutator G).index := by + refine (normalizer_le_centralizer_or_le_commutator P).imp ?_ ?_ <;> + refine fun hP h ↦ P.not_dvd_index (h.trans ?_) + · rw [(MonoidHom.ker_transferSylow_isComplement' P hP).index_eq_card] + exact Subgroup.card_dvd_of_le (Abelianization.commutator_subset_ker _) + · exact Subgroup.index_dvd_of_le hP + +end Sylow + +variable (G) in +/-- If `G` is a finite Z-group, then `commutator G` is a Hall subgroup of `G`. -/ +theorem IsZGroup.coprime_commutator_index [Finite G] [IsZGroup G] : + (Nat.card (commutator G)).Coprime (commutator G).index := by + suffices h : ∀ p, p.Prime → (¬ p ∣ Nat.card (commutator G) ∨ ¬ p ∣ (commutator G).index) by + contrapose! h + exact Nat.Prime.not_coprime_iff_dvd.mp h + intro p hp + have := Fact.mk hp + exact Sylow.not_dvd_card_commutator_or_not_dvd_index_commutator default + +end Hall + section Classification /-- An extension of coprime Z-groups is a Z-group. -/ @@ -188,5 +307,3 @@ theorem isZGroup_of_coprime [Finite G] [IsZGroup G] [IsZGroup G''] rwa [← MonoidHom.ker_eq_bot_iff, P.ker_subgroupMap f', Subgroup.subgroupOf_eq_bot] end Classification - -end IsZGroup From ff8b24e8b384cb5ce44d174b7831b79fec97acd7 Mon Sep 17 00:00:00 2001 From: Lorenzo Luccioli Date: Mon, 13 Jan 2025 10:36:51 +0000 Subject: [PATCH 192/681] feat(EReal): add `toENNReal` (#18885) - Add definition of `EReal.toENNReal`. - Add some API lemmas for `toENNReal`. - Add measurability and continuity lemmas for `toENNReal`. Co-authored-by: Lorenzo Luccioli <71074618+LorenzoLuccioli@users.noreply.github.com> Co-authored-by: Remy Degenne --- Mathlib/Data/Real/EReal.lean | 139 +++++++++++++++++- .../Constructions/BorelSpace/Real.lean | 14 ++ Mathlib/Topology/Instances/EReal.lean | 44 ++++++ 3 files changed, 196 insertions(+), 1 deletion(-) diff --git a/Mathlib/Data/Real/EReal.lean b/Mathlib/Data/Real/EReal.lean index 66445295364a8..eb40ab8dbcdd0 100644 --- a/Mathlib/Data/Real/EReal.lean +++ b/Mathlib/Data/Real/EReal.lean @@ -683,6 +683,90 @@ theorem coe_ennreal_mul : ∀ x y : ℝ≥0∞, ((x * y : ℝ≥0∞) : EReal) = theorem coe_ennreal_nsmul (n : ℕ) (x : ℝ≥0∞) : (↑(n • x) : EReal) = n • (x : EReal) := map_nsmul (⟨⟨(↑), coe_ennreal_zero⟩, coe_ennreal_add⟩ : ℝ≥0∞ →+ EReal) _ _ +/-! ### toENNReal -/ + +/-- `x.toENNReal` returns `x` if it is nonnegative, `0` otherwise. -/ +noncomputable def toENNReal (x : EReal) : ℝ≥0∞ := + if x = ⊤ then ⊤ + else ENNReal.ofReal x.toReal + +@[simp] lemma toENNReal_top : (⊤ : EReal).toENNReal = ⊤ := rfl + +@[simp] +lemma toENNReal_of_ne_top {x : EReal} (hx : x ≠ ⊤) : x.toENNReal = ENNReal.ofReal x.toReal := + if_neg hx + +@[simp] +lemma toENNReal_eq_top_iff {x : EReal} : x.toENNReal = ⊤ ↔ x = ⊤ := by + by_cases h : x = ⊤ + · simp [h] + · simp [h, toENNReal] + +lemma toENNReal_ne_top_iff {x : EReal} : x.toENNReal ≠ ⊤ ↔ x ≠ ⊤ := toENNReal_eq_top_iff.not + +@[simp] +lemma toENNReal_of_nonpos {x : EReal} (hx : x ≤ 0) : x.toENNReal = 0 := by + rw [toENNReal, if_neg (fun h ↦ ?_)] + · exact ENNReal.ofReal_of_nonpos (toReal_nonpos hx) + · exact zero_ne_top <| top_le_iff.mp <| h ▸ hx + +lemma toENNReal_bot : (⊥ : EReal).toENNReal = 0 := toENNReal_of_nonpos bot_le +lemma toENNReal_zero : (0 : EReal).toENNReal = 0 := toENNReal_of_nonpos le_rfl + +lemma toENNReal_eq_zero_iff {x : EReal} : x.toENNReal = 0 ↔ x ≤ 0 := by + induction x <;> simp [toENNReal] + +lemma toENNReal_ne_zero_iff {x : EReal} : x.toENNReal ≠ 0 ↔ 0 < x := by + simp [toENNReal_eq_zero_iff.not] + +@[simp] +lemma coe_toENNReal {x : EReal} (hx : 0 ≤ x) : (x.toENNReal : EReal) = x := by + rw [toENNReal] + by_cases h_top : x = ⊤ + · rw [if_pos h_top, h_top] + rfl + rw [if_neg h_top] + simp only [coe_ennreal_ofReal, ge_iff_le, hx, toReal_nonneg, max_eq_left] + exact coe_toReal h_top fun _ ↦ by simp_all only [le_bot_iff, zero_ne_bot] + +lemma coe_toENNReal_eq_max {x : EReal} : x.toENNReal = max 0 x := by + rcases le_total 0 x with (hx | hx) + · rw [coe_toENNReal hx, max_eq_right hx] + · rw [toENNReal_of_nonpos hx, max_eq_left hx, coe_ennreal_zero] + +@[simp] +lemma toENNReal_coe {x : ℝ≥0∞} : (x : EReal).toENNReal = x := by + by_cases h_top : x = ⊤ + · rw [h_top, coe_ennreal_top, toENNReal_top] + rwa [toENNReal, if_neg _, toReal_coe_ennreal, ENNReal.ofReal_toReal_eq_iff] + simp [h_top] + +@[simp] lemma real_coe_toENNReal (x : ℝ) : (x : EReal).toENNReal = ENNReal.ofReal x := rfl + +@[simp] +lemma toReal_toENNReal {x : EReal} (hx : 0 ≤ x) : x.toENNReal.toReal = x.toReal := by + by_cases h : x = ⊤ + · simp [h] + · simp [h, toReal_nonneg hx] + +lemma toENNReal_eq_toENNReal {x y : EReal} (hx : 0 ≤ x) (hy : 0 ≤ y) : + x.toENNReal = y.toENNReal ↔ x = y := by + induction x <;> induction y <;> simp_all + +lemma toENNReal_le_toENNReal {x y : EReal} (h : x ≤ y) : x.toENNReal ≤ y.toENNReal := by + induction x + · simp + · by_cases hy_top : y = ⊤ + · simp [hy_top] + simp only [toENNReal, coe_ne_top, ↓reduceIte, toReal_coe, hy_top] + exact ENNReal.ofReal_le_ofReal <| EReal.toReal_le_toReal h (coe_ne_bot _) hy_top + · simp_all + +lemma toENNReal_lt_toENNReal {x y : EReal} (hx : 0 ≤ x) (hxy : x < y) : + x.toENNReal < y.toENNReal := + lt_of_le_of_ne (toENNReal_le_toENNReal hxy.le) + fun h ↦ hxy.ne <| (toENNReal_eq_toENNReal hx (hx.trans_lt hxy).le).mp h + /-! ### nat coercion -/ theorem coe_coe_eq_natCast (n : ℕ) : (n : ℝ) = (n : EReal) := rfl @@ -826,6 +910,17 @@ theorem toReal_add {x y : EReal} (hx : x ≠ ⊤) (h'x : x ≠ ⊥) (hy : y ≠ lift y to ℝ using ⟨hy, h'y⟩ rfl +lemma toENNReal_add {x y : EReal} (hx : 0 ≤ x) (hy : 0 ≤ y) : + (x + y).toENNReal = x.toENNReal + y.toENNReal := by + induction x <;> induction y <;> try {· simp_all} + norm_cast + simp_rw [real_coe_toENNReal] + simp_all [ENNReal.ofReal_add] + +lemma toENNReal_add_le {x y : EReal} : (x + y).toENNReal ≤ x.toENNReal + y.toENNReal := by + induction x <;> induction y <;> try {· simp} + exact ENNReal.ofReal_add_le + theorem addLECancellable_coe (x : ℝ) : AddLECancellable (x : EReal) | _, ⊤, _ => le_top | ⊥, _, _ => bot_le @@ -885,6 +980,16 @@ lemma add_ne_top_iff_ne_top_left {x y : EReal} (hy : y ≠ ⊥) (hy' : y ≠ ⊤ lemma add_ne_top_iff_ne_top_right {x y : EReal} (hx : x ≠ ⊥) (hx' : x ≠ ⊤) : x + y ≠ ⊤ ↔ y ≠ ⊤ := add_comm x y ▸ add_ne_top_iff_ne_top_left hx hx' +lemma add_ne_top_iff_of_ne_bot {x y : EReal} (hx : x ≠ ⊥) (hy : y ≠ ⊥) : + x + y ≠ ⊤ ↔ x ≠ ⊤ ∧ y ≠ ⊤ := by + refine ⟨?_, fun h ↦ add_ne_top h.1 h.2⟩ + induction x <;> simp_all + induction y <;> simp_all + +lemma add_ne_top_iff_of_ne_bot_of_ne_top {x y : EReal} (hy : y ≠ ⊥) (hy' : y ≠ ⊤) : + x + y ≠ ⊤ ↔ x ≠ ⊤ := by + induction x <;> simp [add_ne_top_iff_of_ne_bot, hy, hy'] + /-- We do not have a notion of `LinearOrderedAddCommMonoidWithBot` but we can at least make the order dual of the extended reals into a `LinearOrderedAddCommMonoidWithTop`. -/ instance : LinearOrderedAddCommMonoidWithTop ERealᵒᵈ where @@ -1084,6 +1189,17 @@ theorem toReal_sub {x y : EReal} (hx : x ≠ ⊤) (h'x : x ≠ ⊥) (hy : y ≠ lift y to ℝ using ⟨hy, h'y⟩ rfl +lemma toENNReal_sub {x y : EReal} (hy : 0 ≤ y) : + (x - y).toENNReal = x.toENNReal - y.toENNReal := by + induction x <;> induction y <;> try {· simp_all [zero_tsub, ENNReal.sub_top]} + rename_i x y + by_cases hxy : x ≤ y + · rw [toENNReal_of_nonpos <| sub_nonpos.mpr <| EReal.coe_le_coe_iff.mpr hxy] + exact (tsub_eq_zero_of_le <| toENNReal_le_toENNReal <| EReal.coe_le_coe_iff.mpr hxy).symm + · rw [toENNReal_of_ne_top (ne_of_beq_false rfl).symm, ← coe_sub, toReal_coe, + ofReal_sub x (EReal.coe_nonneg.mp hy)] + simp + lemma add_sub_cancel_right {a : EReal} {b : Real} : a + b - b = a := by cases a <;> norm_cast exact _root_.add_sub_cancel_right _ _ @@ -1428,6 +1544,27 @@ lemma mul_ne_bot (a b : EReal) : set_option push_neg.use_distrib true in push_neg rfl +/-- `EReal.toENNReal` is multiplicative. For the version with the nonnegativity +hypothesis on the second variable, see `EReal.toENNReal_mul'`. -/ +lemma toENNReal_mul {x y : EReal} (hx : 0 ≤ x) : + (x * y).toENNReal = x.toENNReal * y.toENNReal := by + induction x <;> induction y + <;> try {· simp_all [mul_nonpos_iff, ofReal_mul, ← coe_mul]} + · rcases eq_or_lt_of_le hx with (hx | hx) + · simp [← hx] + · simp_all [mul_top_of_pos hx] + · rename_i a + rcases lt_trichotomy a 0 with (ha | ha | ha) + · simp_all [le_of_lt, top_mul_of_neg (EReal.coe_neg'.mpr ha)] + · simp [ha] + · simp_all [top_mul_of_pos (EReal.coe_pos.mpr ha)] + +/-- `EReal.toENNReal` is multiplicative. For the version with the nonnegativity +hypothesis on the first variable, see `EReal.toENNReal_mul`. -/ +lemma toENNReal_mul' {x y : EReal} (hy : 0 ≤ y) : + (x * y).toENNReal = x.toENNReal * y.toENNReal := by + rw [EReal.mul_comm, toENNReal_mul hy, mul_comm] + lemma right_distrib_of_nonneg {a b c : EReal} (ha : 0 ≤ a) (hb : 0 ≤ b) : (a + b) * c = a * c + b * c := by rcases eq_or_lt_of_le ha with (rfl | a_pos) @@ -1946,4 +2083,4 @@ unsafe def positivity_coe_ennreal_ereal : expr → tactic strictness end Tactic -/ -set_option linter.style.longFile 2000 +set_option linter.style.longFile 2200 diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean index 7af987e92ef57..a92a3b76dd8e1 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean @@ -430,6 +430,20 @@ theorem AEMeasurable.coe_ereal_ennreal {f : α → ℝ≥0∞} {μ : Measure α} AEMeasurable (fun x => (f x : EReal)) μ := measurable_coe_ennreal_ereal.comp_aemeasurable hf +@[measurability] +theorem measurable_ereal_toENNReal : Measurable EReal.toENNReal := + EReal.measurable_of_measurable_real (by simpa using ENNReal.measurable_ofReal) + +@[measurability, fun_prop] +theorem Measurable.ereal_toENNReal {f : α → EReal} (hf : Measurable f) : + Measurable fun x => (f x).toENNReal := + measurable_ereal_toENNReal.comp hf + +@[measurability, fun_prop] +theorem AEMeasurable.ereal_toENNReal {f : α → EReal} {μ : Measure α} (hf : AEMeasurable f μ) : + AEMeasurable (fun x => (f x).toENNReal) μ := + measurable_ereal_toENNReal.comp_aemeasurable hf + namespace NNReal instance : MeasurableSMul₂ ℝ≥0 ℝ≥0∞ where diff --git a/Mathlib/Topology/Instances/EReal.lean b/Mathlib/Topology/Instances/EReal.lean index bb99c10fb4473..903c24814fc46 100644 --- a/Mathlib/Topology/Instances/EReal.lean +++ b/Mathlib/Topology/Instances/EReal.lean @@ -193,6 +193,50 @@ lemma tendsto_toReal_atBot : Tendsto EReal.toReal (𝓝[≠] ⊥) atBot := by rw [nhdsWithin_bot, tendsto_map'_iff] exact tendsto_id +/-! ### toENNReal -/ + +lemma continuous_toENNReal : Continuous EReal.toENNReal := by + refine continuous_iff_continuousAt.mpr fun x ↦ ?_ + by_cases h_top : x = ⊤ + · simp only [ContinuousAt, h_top, toENNReal_top] + refine ENNReal.tendsto_nhds_top fun n ↦ ?_ + filter_upwards [eventually_gt_nhds (coe_lt_top n)] with y hy + exact toENNReal_coe (x := n) ▸ toENNReal_lt_toENNReal (coe_ennreal_nonneg _) hy + refine ContinuousOn.continuousAt ?_ (compl_singleton_mem_nhds_iff.mpr h_top) + refine (continuousOn_of_forall_continuousAt fun x hx ↦ ?_).congr (fun _ h ↦ toENNReal_of_ne_top h) + by_cases h_bot : x = ⊥ + · refine tendsto_nhds_of_eventually_eq ?_ + rw [h_bot, nhds_bot_basis.eventually_iff] + simp [toReal_bot, ENNReal.ofReal_zero, ENNReal.ofReal_eq_zero, true_and] + exact ⟨0, fun _ hx ↦ toReal_nonpos hx.le⟩ + refine ENNReal.continuous_ofReal.continuousAt.comp' <| continuousOn_toReal.continuousAt + <| (toFinite _).isClosed.compl_mem_nhds ?_ + simp_all only [mem_compl_iff, mem_singleton_iff, mem_insert_iff, or_self, not_false_eq_true] + +@[fun_prop] +lemma _root_.Continous.ereal_toENNReal {α : Type*} [TopologicalSpace α] {f : α → EReal} + (hf : Continuous f) : + Continuous fun x => (f x).toENNReal := + continuous_toENNReal.comp hf + +@[fun_prop] +lemma _root_.ContinuousOn.ereal_toENNReal {α : Type*} [TopologicalSpace α] {s : Set α} + {f : α → EReal} (hf : ContinuousOn f s) : + ContinuousOn (fun x => (f x).toENNReal) s := + continuous_toENNReal.comp_continuousOn hf + +@[fun_prop] +lemma _root_.ContinuousWithinAt.ereal_toENNReal {α : Type*} [TopologicalSpace α] {f : α → EReal} + {s : Set α} {x : α} (hf : ContinuousWithinAt f s x) : + ContinuousWithinAt (fun x => (f x).toENNReal) s x := + continuous_toENNReal.continuousAt.comp_continuousWithinAt hf + +@[fun_prop] +lemma _root_.ContinuousAt.ereal_toENNReal {α : Type*} [TopologicalSpace α] {f : α → EReal} + {x : α} (hf : ContinuousAt f x) : + ContinuousAt (fun x => (f x).toENNReal) x := + continuous_toENNReal.continuousAt.comp hf + /-! ### Infs and Sups -/ variable {α : Type*} {u v : α → EReal} From ce6118d7a354a4d82a1cdd7cf0cc31a6ac89a112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 13 Jan 2025 10:56:16 +0000 Subject: [PATCH 193/681] chore(LpSpace): move results about the L^p norm earlier (#20541) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `MeasureTheory.Function.LpSpace` is supposed to be about the L^p space itself, but contains a bunch of results about the L^p norm as well. Move those results to `MeasureTheory.Function.LpSeminorm.Basic` and `MeasureTheory.Function.LpSeminorm.CompareExp`. Also rename lemmas about nesting of L^p norms. From LeanAPAP Moves: * `Memℒp.memℒp_of_exponent_le_of_measure_support_ne_top` -> `Memℒp.mono_exponent_of_measure_support_ne_top` * `Memℒp.memℒp_of_exponent_le` -> `Memℒp.mono_exponent` --- Mathlib/MeasureTheory/Function/L1Space.lean | 2 +- .../Function/LocallyIntegrable.lean | 4 +- .../Function/LpSeminorm/Basic.lean | 193 +++++++++++++++--- .../Function/LpSeminorm/CompareExp.lean | 21 +- Mathlib/MeasureTheory/Function/LpSpace.lean | 164 +-------------- .../MeasureTheory/Integral/IntegrableOn.lean | 2 +- 6 files changed, 190 insertions(+), 196 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 0005ef1d22c72..3f4082bc4289d 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -822,7 +822,7 @@ theorem Integrable.prod_mk {f : α → β} {g : α → γ} (hf : Integrable f μ theorem Memℒp.integrable {q : ℝ≥0∞} (hq1 : 1 ≤ q) {f : α → β} [IsFiniteMeasure μ] (hfq : Memℒp f q μ) : Integrable f μ := - memℒp_one_iff_integrable.mp (hfq.memℒp_of_exponent_le hq1) + memℒp_one_iff_integrable.mp (hfq.mono_exponent hq1) /-- A non-quantitative version of Markov inequality for integrable functions: the measure of points where `‖f x‖ ≥ ε` is finite for all positive `ε`. -/ diff --git a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean index d26cd9cc0d9c0..16af00073f1fa 100644 --- a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean @@ -252,7 +252,7 @@ theorem Memℒp.locallyIntegrable [IsLocallyFiniteMeasure μ] {f : X → E} {p : have : Fact (μ U < ⊤) := ⟨h'U⟩ refine ⟨U, hU, ?_⟩ rw [IntegrableOn, ← memℒp_one_iff_integrable] - apply (hf.restrict U).memℒp_of_exponent_le hp + apply (hf.restrict U).mono_exponent hp theorem locallyIntegrable_const [IsLocallyFiniteMeasure μ] (c : E) : LocallyIntegrable (fun _ => c) μ := @@ -504,7 +504,7 @@ theorem MonotoneOn.memℒp_top (hmono : MonotoneOn f s) {a b : X} theorem MonotoneOn.memℒp_of_measure_ne_top (hmono : MonotoneOn f s) {a b : X} (ha : IsLeast s a) (hb : IsGreatest s b) (hs : μ s ≠ ∞) (h's : MeasurableSet s) : Memℒp f p (μ.restrict s) := - (hmono.memℒp_top ha hb h's).memℒp_of_exponent_le_of_measure_support_ne_top (s := univ) + (hmono.memℒp_top ha hb h's).mono_exponent_of_measure_support_ne_top (s := univ) (by simp) (by simpa using hs) le_top theorem MonotoneOn.memℒp_isCompact [IsFiniteMeasureOnCompacts μ] (hs : IsCompact s) diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean index bc362c375e84d..783a4b1169548 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean @@ -346,21 +346,6 @@ theorem memℒp_neg_iff {f : α → E} : Memℒp (-f) p μ ↔ Memℒp f p μ := end Neg -theorem eLpNorm_indicator_eq_restrict {f : α → E} {s : Set α} (hs : MeasurableSet s) : - eLpNorm (s.indicator f) p μ = eLpNorm f p (μ.restrict s) := by - rcases eq_or_ne p ∞ with rfl | hp - · simp only [eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_nnnorm, - ← ENNReal.essSup_indicator_eq_essSup_restrict hs, ENNReal.coe_indicator, - nnnorm_indicator_eq_indicator_nnnorm] - · rcases eq_or_ne p 0 with rfl | hp₀; · simp - simp only [eLpNorm_eq_lintegral_rpow_nnnorm hp₀ hp, ← lintegral_indicator hs, - ENNReal.coe_indicator, nnnorm_indicator_eq_indicator_nnnorm] - congr with x - by_cases hx : x ∈ s <;> simp [ENNReal.toReal_pos, *] - -@[deprecated (since := "2024-07-27")] -alias snorm_indicator_eq_restrict := eLpNorm_indicator_eq_restrict - section Const theorem eLpNorm'_const (c : F) (hq_pos : 0 < q) : @@ -780,6 +765,39 @@ alias snorm_mono_measure := eLpNorm_mono_measure theorem Memℒp.mono_measure {f : α → E} (hμν : ν ≤ μ) (hf : Memℒp f p μ) : Memℒp f p ν := ⟨hf.1.mono_measure hμν, (eLpNorm_mono_measure f hμν).trans_lt hf.2⟩ +section Indicator +variable {c : F} {hf : AEStronglyMeasurable f μ} {s : Set α} + +lemma eLpNorm_indicator_eq_eLpNorm_restrict (hs : MeasurableSet s) : + eLpNorm (s.indicator f) p μ = eLpNorm f p (μ.restrict s) := by + by_cases hp_zero : p = 0 + · simp only [hp_zero, eLpNorm_exponent_zero] + by_cases hp_top : p = ∞ + · simp_rw [hp_top, eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_nnnorm, + nnnorm_indicator_eq_indicator_nnnorm, ENNReal.coe_indicator, + ENNReal.essSup_indicator_eq_essSup_restrict hs] + simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_zero hp_top] + suffices (∫⁻ x, (‖s.indicator f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) = + ∫⁻ x in s, (‖f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ by rw [this] + rw [← lintegral_indicator hs] + congr + simp_rw [nnnorm_indicator_eq_indicator_nnnorm, ENNReal.coe_indicator] + have h_zero : (fun x => x ^ p.toReal) (0 : ℝ≥0∞) = 0 := by + simp [ENNReal.toReal_pos hp_zero hp_top] + -- Porting note: The implicit argument should be specified because the elaborator can't deal with + -- `∘` well. + exact (Set.indicator_comp_of_zero (g := fun x : ℝ≥0∞ => x ^ p.toReal) h_zero).symm + +@[deprecated (since := "2024-07-27")] +alias snorm_indicator_eq_restrict := eLpNorm_indicator_eq_eLpNorm_restrict + +@[deprecated (since := "2025-01-07")] +alias eLpNorm_indicator_eq_restrict := eLpNorm_indicator_eq_eLpNorm_restrict + +lemma eLpNormEssSup_indicator_eq_eLpNormEssSup_restrict (hs : MeasurableSet s) : + eLpNormEssSup (s.indicator f) μ = eLpNormEssSup f (μ.restrict s) := by + simp_rw [← eLpNorm_exponent_top, eLpNorm_indicator_eq_eLpNorm_restrict hs] + lemma eLpNorm_restrict_le (f : α → F) (p : ℝ≥0∞) (μ : Measure α) (s : Set α) : eLpNorm f p (μ.restrict s) ≤ eLpNorm f p μ := eLpNorm_mono_measure f Measure.restrict_le_self @@ -787,6 +805,131 @@ lemma eLpNorm_restrict_le (f : α → F) (p : ℝ≥0∞) (μ : Measure α) (s : @[deprecated (since := "2024-07-27")] alias snorm_restrict_le := eLpNorm_restrict_le +lemma eLpNorm_indicator_le (f : α → E) : eLpNorm (s.indicator f) p μ ≤ eLpNorm f p μ := by + refine eLpNorm_mono_ae <| .of_forall fun x ↦ ?_ + suffices ‖s.indicator f x‖₊ ≤ ‖f x‖₊ by exact NNReal.coe_mono this + rw [nnnorm_indicator_eq_indicator_nnnorm] + exact s.indicator_le_self _ x + +lemma eLpNormEssSup_indicator_le (s : Set α) (f : α → G) : + eLpNormEssSup (s.indicator f) μ ≤ eLpNormEssSup f μ := by + refine essSup_mono_ae (Eventually.of_forall fun x => ?_) + simp_rw [enorm_eq_nnnorm, ENNReal.coe_le_coe, nnnorm_indicator_eq_indicator_nnnorm] + exact Set.indicator_le_self s _ x + +lemma eLpNormEssSup_indicator_const_le (s : Set α) (c : G) : + eLpNormEssSup (s.indicator fun _ : α => c) μ ≤ ‖c‖₊ := by + by_cases hμ0 : μ = 0 + · rw [hμ0, eLpNormEssSup_measure_zero] + exact zero_le _ + · exact (eLpNormEssSup_indicator_le s fun _ => c).trans (eLpNormEssSup_const c hμ0).le + +lemma eLpNormEssSup_indicator_const_eq (s : Set α) (c : G) (hμs : μ s ≠ 0) : + eLpNormEssSup (s.indicator fun _ : α => c) μ = ‖c‖₊ := by + refine le_antisymm (eLpNormEssSup_indicator_const_le s c) ?_ + by_contra! h + have h' := ae_iff.mp (ae_lt_of_essSup_lt h) + push_neg at h' + refine hμs (measure_mono_null (fun x hx_mem => ?_) h') + rw [Set.mem_setOf_eq, Set.indicator_of_mem hx_mem, enorm_eq_nnnorm] + +lemma eLpNorm_indicator_const₀ (hs : NullMeasurableSet s μ) (hp : p ≠ 0) (hp_top : p ≠ ∞) : + eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := + have hp_pos : 0 < p.toReal := ENNReal.toReal_pos hp hp_top + calc + eLpNorm (s.indicator fun _ => c) p μ + = (∫⁻ x, ((‖(s.indicator fun _ ↦ c) x‖₊ : ℝ≥0∞) ^ p.toReal) ∂μ) ^ (1 / p.toReal) := + eLpNorm_eq_lintegral_rpow_nnnorm hp hp_top + _ = (∫⁻ x, (s.indicator fun _ ↦ (‖c‖₊ : ℝ≥0∞) ^ p.toReal) x ∂μ) ^ (1 / p.toReal) := by + congr 2 + refine (Set.comp_indicator_const c (fun x ↦ (‖x‖₊ : ℝ≥0∞) ^ p.toReal) ?_) + simp [hp_pos] + _ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by + rw [lintegral_indicator_const₀ hs, ENNReal.mul_rpow_of_nonneg, ← ENNReal.rpow_mul, + mul_one_div_cancel hp_pos.ne', ENNReal.rpow_one] + positivity + +lemma eLpNorm_indicator_const (hs : MeasurableSet s) (hp : p ≠ 0) (hp_top : p ≠ ∞) : + eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := + eLpNorm_indicator_const₀ hs.nullMeasurableSet hp hp_top + +lemma eLpNorm_indicator_const' (hs : MeasurableSet s) (hμs : μ s ≠ 0) (hp : p ≠ 0) : + eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by + by_cases hp_top : p = ∞ + · simp [hp_top, eLpNormEssSup_indicator_const_eq s c hμs] + · exact eLpNorm_indicator_const hs hp hp_top + +lemma eLpNorm_indicator_const_le (c : G) (p : ℝ≥0∞) : + eLpNorm (s.indicator fun _ => c) p μ ≤ ‖c‖₊ * μ s ^ (1 / p.toReal) := by + obtain rfl | hp := eq_or_ne p 0 + · simp only [eLpNorm_exponent_zero, zero_le'] + obtain rfl | h'p := eq_or_ne p ∞ + · simp only [eLpNorm_exponent_top, ENNReal.top_toReal, _root_.div_zero, ENNReal.rpow_zero, + mul_one] + exact eLpNormEssSup_indicator_const_le _ _ + let t := toMeasurable μ s + calc + eLpNorm (s.indicator fun _ => c) p μ ≤ eLpNorm (t.indicator fun _ => c) p μ := + eLpNorm_mono (norm_indicator_le_of_subset (subset_toMeasurable _ _) _) + _ = ‖c‖₊ * μ t ^ (1 / p.toReal) := + eLpNorm_indicator_const (measurableSet_toMeasurable ..) hp h'p + _ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by rw [measure_toMeasurable] + +lemma Memℒp.indicator (hs : MeasurableSet s) (hf : Memℒp f p μ) : Memℒp (s.indicator f) p μ := + ⟨hf.aestronglyMeasurable.indicator hs, lt_of_le_of_lt (eLpNorm_indicator_le f) hf.eLpNorm_lt_top⟩ + +lemma memℒp_indicator_iff_restrict (hs : MeasurableSet s) : + Memℒp (s.indicator f) p μ ↔ Memℒp f p (μ.restrict s) := by + simp [Memℒp, aestronglyMeasurable_indicator_iff hs, eLpNorm_indicator_eq_eLpNorm_restrict hs] + +lemma memℒp_indicator_const (p : ℝ≥0∞) (hs : MeasurableSet s) (c : E) (hμsc : c = 0 ∨ μ s ≠ ∞) : + Memℒp (s.indicator fun _ => c) p μ := by + rw [memℒp_indicator_iff_restrict hs] + obtain rfl | hμ := hμsc + · exact zero_memℒp + · have := Fact.mk hμ.lt_top + apply memℒp_const + +lemma eLpNormEssSup_piecewise (f g : α → E) [DecidablePred (· ∈ s)] (hs : MeasurableSet s) : + eLpNormEssSup (Set.piecewise s f g) μ + = max (eLpNormEssSup f (μ.restrict s)) (eLpNormEssSup g (μ.restrict sᶜ)) := by + simp only [eLpNormEssSup, ← ENNReal.essSup_piecewise hs] + congr with x + by_cases hx : x ∈ s <;> simp [hx] + +lemma eLpNorm_top_piecewise (f g : α → E) [DecidablePred (· ∈ s)] (hs : MeasurableSet s) : + eLpNorm (Set.piecewise s f g) ∞ μ + = max (eLpNorm f ∞ (μ.restrict s)) (eLpNorm g ∞ (μ.restrict sᶜ)) := + eLpNormEssSup_piecewise f g hs + +protected lemma Memℒp.piecewise [DecidablePred (· ∈ s)] {g} (hs : MeasurableSet s) + (hf : Memℒp f p (μ.restrict s)) (hg : Memℒp g p (μ.restrict sᶜ)) : + Memℒp (s.piecewise f g) p μ := by + by_cases hp_zero : p = 0 + · simp only [hp_zero, memℒp_zero_iff_aestronglyMeasurable] + exact AEStronglyMeasurable.piecewise hs hf.1 hg.1 + refine ⟨AEStronglyMeasurable.piecewise hs hf.1 hg.1, ?_⟩ + obtain rfl | hp_top := eq_or_ne p ∞ + · rw [eLpNorm_top_piecewise f g hs] + exact max_lt hf.2 hg.2 + rw [eLpNorm_lt_top_iff_lintegral_rpow_nnnorm_lt_top hp_zero hp_top, ← lintegral_add_compl _ hs, + ENNReal.add_lt_top] + constructor + · have h : ∀ᵐ x ∂μ, x ∈ s → + (‖Set.piecewise s f g x‖₊ : ℝ≥0∞) ^ p.toReal = (‖f x‖₊ : ℝ≥0∞) ^ p.toReal := by + filter_upwards with a ha using by simp [ha] + rw [setLIntegral_congr_fun hs h] + exact lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hf.2 + · have h : ∀ᵐ x ∂μ, x ∈ sᶜ → + (‖Set.piecewise s f g x‖₊ : ℝ≥0∞) ^ p.toReal = (‖g x‖₊ : ℝ≥0∞) ^ p.toReal := by + filter_upwards with a ha + have ha' : a ∉ s := ha + simp [ha'] + rw [setLIntegral_congr_fun hs.compl h] + exact lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hg.2 + +end Indicator + /-- For a function `f` with support in `s`, the Lᵖ norms of `f` with respect to `μ` and `μ.restrict s` are the same. -/ theorem eLpNorm_restrict_eq_of_support_subset {s : Set α} {f : α → F} (hsf : f.support ⊆ s) : @@ -1049,23 +1192,9 @@ lemma eLpNorm_lt_top_of_finite [Finite α] [IsFiniteMeasure μ] : eLpNorm f p μ @[simp] lemma eLpNorm_of_isEmpty [IsEmpty α] (f : α → E) (p : ℝ≥0∞) : eLpNorm f p μ = 0 := by simp [Subsingleton.elim f 0] -lemma eLpNormEssSup_piecewise {s : Set α} (f g : α → E) [DecidablePred (· ∈ s)] - (hs : MeasurableSet s) : - eLpNormEssSup (Set.piecewise s f g) μ - = max (eLpNormEssSup f (μ.restrict s)) (eLpNormEssSup g (μ.restrict sᶜ)) := by - simp only [eLpNormEssSup, ← ENNReal.essSup_piecewise hs] - congr with x - by_cases hx : x ∈ s <;> simp [hx] - @[deprecated (since := "2024-07-27")] alias snormEssSup_piecewise := eLpNormEssSup_piecewise -lemma eLpNorm_top_piecewise {s : Set α} (f g : α → E) [DecidablePred (· ∈ s)] - (hs : MeasurableSet s) : - eLpNorm (Set.piecewise s f g) ∞ μ - = max (eLpNorm f ∞ (μ.restrict s)) (eLpNorm g ∞ (μ.restrict sᶜ)) := - eLpNormEssSup_piecewise f g hs - @[deprecated (since := "2024-07-27")] alias snorm_top_piecewise := eLpNorm_top_piecewise @@ -1462,8 +1591,8 @@ theorem Memℒp.exists_eLpNorm_indicator_compl_lt {β : Type*} [NormedAddCommGro · exact ((eLpNorm_lt_top_iff_lintegral_rpow_nnnorm_lt_top hp₀ hp_top).1 hf.2).ne · simp [*] refine ⟨s, hsm, hs, ?_⟩ - rwa [eLpNorm_indicator_eq_restrict hsm.compl, eLpNorm_eq_lintegral_rpow_nnnorm hp₀ hp_top, - one_div, ENNReal.rpow_inv_lt_iff] + rwa [eLpNorm_indicator_eq_eLpNorm_restrict hsm.compl, + eLpNorm_eq_lintegral_rpow_nnnorm hp₀ hp_top, one_div, ENNReal.rpow_inv_lt_iff] simp [ENNReal.toReal_pos, *] @[deprecated (since := "2024-07-27")] @@ -1473,3 +1602,5 @@ end UnifTight end ℒp end MeasureTheory + +set_option linter.style.longFile 1700 diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean index 6c1499cfe95ca..9661035b3d111 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean @@ -132,7 +132,7 @@ theorem eLpNorm'_lt_top_of_eLpNorm'_lt_top_of_exponent_le {p q : ℝ} [IsFiniteM alias snorm'_lt_top_of_snorm'_lt_top_of_exponent_le := eLpNorm'_lt_top_of_eLpNorm'_lt_top_of_exponent_le -theorem Memℒp.memℒp_of_exponent_le {p q : ℝ≥0∞} [IsFiniteMeasure μ] {f : α → E} (hfq : Memℒp f q μ) +theorem Memℒp.mono_exponent {p q : ℝ≥0∞} [IsFiniteMeasure μ] {f : α → E} (hfq : Memℒp f q μ) (hpq : p ≤ q) : Memℒp f p μ := by cases' hfq with hfq_m hfq_lt_top by_cases hp0 : p = 0 @@ -160,6 +160,25 @@ theorem Memℒp.memℒp_of_exponent_le {p q : ℝ≥0∞} [IsFiniteMeasure μ] { rw [eLpNorm_eq_eLpNorm' hq0 hq_top] at hfq_lt_top exact eLpNorm'_lt_top_of_eLpNorm'_lt_top_of_exponent_le hfq_m hfq_lt_top hp_pos.le hpq_real +@[deprecated (since := "2025-01-07")] alias Memℒp.memℒp_of_exponent_le := Memℒp.mono_exponent + +/-- If a function is supported on a finite-measure set and belongs to `ℒ^p`, then it belongs to +`ℒ^q` for any `q ≤ p`. -/ +lemma Memℒp.mono_exponent_of_measure_support_ne_top {p q : ℝ≥0∞} {f : α → E} (hfq : Memℒp f q μ) + {s : Set α} (hf : ∀ x, x ∉ s → f x = 0) (hs : μ s ≠ ∞) (hpq : p ≤ q) : Memℒp f p μ := by + have : (toMeasurable μ s).indicator f = f := by + apply Set.indicator_eq_self.2 + apply Function.support_subset_iff'.2 fun x hx ↦ hf x ?_ + contrapose! hx + exact subset_toMeasurable μ s hx + rw [← this, memℒp_indicator_iff_restrict (measurableSet_toMeasurable μ s)] at hfq ⊢ + have : Fact (μ (toMeasurable μ s) < ∞) := ⟨by simpa [lt_top_iff_ne_top] using hs⟩ + exact hfq.mono_exponent hpq + +@[deprecated (since := "2025-01-07")] +alias Memℒp.memℒp_of_exponent_le_of_measure_support_ne_top := + Memℒp.mono_exponent_of_measure_support_ne_top + end SameSpace section Bilinear diff --git a/Mathlib/MeasureTheory/Function/LpSpace.lean b/Mathlib/MeasureTheory/Function/LpSpace.lean index eb0051a02d1e2..ea88132fbc69c 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace.lean @@ -170,7 +170,7 @@ theorem mem_Lp_iff_memℒp {f : α →ₘ[μ] E} : f ∈ Lp E p μ ↔ Memℒp f simp [mem_Lp_iff_eLpNorm_lt_top, Memℒp, f.stronglyMeasurable.aestronglyMeasurable] protected theorem antitone [IsFiniteMeasure μ] {p q : ℝ≥0∞} (hpq : p ≤ q) : Lp E q μ ≤ Lp E p μ := - fun f hf => (Memℒp.memℒp_of_exponent_le ⟨f.aestronglyMeasurable, hf⟩ hpq).2 + fun f hf => (Memℒp.mono_exponent ⟨f.aestronglyMeasurable, hf⟩ hpq).2 @[simp] theorem coeFn_mk {f : α →ₘ[μ] E} (hf : eLpNorm f p μ < ∞) : ((⟨f, hf⟩ : Lp E p μ) : α → E) = f := @@ -495,165 +495,37 @@ For a set `s` with `(hs : MeasurableSet s)` and `(hμs : μ s < ∞)`, we build `indicatorConstLp p hs hμs c`, the element of `Lp` corresponding to `s.indicator (fun _ => c)`. -/ - -section Indicator - -variable {c : E} {f : α → E} {hf : AEStronglyMeasurable f μ} {s : Set α} - -theorem eLpNormEssSup_indicator_le (s : Set α) (f : α → G) : - eLpNormEssSup (s.indicator f) μ ≤ eLpNormEssSup f μ := by - refine essSup_mono_ae (Eventually.of_forall fun x => ?_) - simp_rw [enorm_eq_nnnorm, ENNReal.coe_le_coe, nnnorm_indicator_eq_indicator_nnnorm] - exact Set.indicator_le_self s _ x - @[deprecated (since := "2024-07-27")] alias snormEssSup_indicator_le := eLpNormEssSup_indicator_le -theorem eLpNormEssSup_indicator_const_le (s : Set α) (c : G) : - eLpNormEssSup (s.indicator fun _ : α => c) μ ≤ ‖c‖₊ := by - by_cases hμ0 : μ = 0 - · rw [hμ0, eLpNormEssSup_measure_zero] - exact zero_le _ - · exact (eLpNormEssSup_indicator_le s fun _ => c).trans (eLpNormEssSup_const c hμ0).le - @[deprecated (since := "2024-07-27")] alias snormEssSup_indicator_const_le := eLpNormEssSup_indicator_const_le -theorem eLpNormEssSup_indicator_const_eq (s : Set α) (c : G) (hμs : μ s ≠ 0) : - eLpNormEssSup (s.indicator fun _ : α => c) μ = ‖c‖₊ := by - refine le_antisymm (eLpNormEssSup_indicator_const_le s c) ?_ - by_contra! h - have h' := ae_iff.mp (ae_lt_of_essSup_lt h) - push_neg at h' - refine hμs (measure_mono_null (fun x hx_mem => ?_) h') - rw [Set.mem_setOf_eq, Set.indicator_of_mem hx_mem, enorm_eq_nnnorm] - @[deprecated (since := "2024-07-27")] alias snormEssSup_indicator_const_eq := eLpNormEssSup_indicator_const_eq -theorem eLpNorm_indicator_le (f : α → E) : eLpNorm (s.indicator f) p μ ≤ eLpNorm f p μ := by - refine eLpNorm_mono_ae (Eventually.of_forall fun x => ?_) - suffices ‖s.indicator f x‖₊ ≤ ‖f x‖₊ by exact NNReal.coe_mono this - rw [nnnorm_indicator_eq_indicator_nnnorm] - exact s.indicator_le_self _ x - @[deprecated (since := "2024-07-27")] alias snorm_indicator_le := eLpNorm_indicator_le -lemma eLpNorm_indicator_const₀ {c : G} (hs : NullMeasurableSet s μ) (hp : p ≠ 0) (hp_top : p ≠ ∞) : - eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := - have hp_pos : 0 < p.toReal := ENNReal.toReal_pos hp hp_top - calc - eLpNorm (s.indicator fun _ => c) p μ - = (∫⁻ x, ((‖(s.indicator fun _ ↦ c) x‖₊ : ℝ≥0∞) ^ p.toReal) ∂μ) ^ (1 / p.toReal) := - eLpNorm_eq_lintegral_rpow_nnnorm hp hp_top - _ = (∫⁻ x, (s.indicator fun _ ↦ (‖c‖₊ : ℝ≥0∞) ^ p.toReal) x ∂μ) ^ (1 / p.toReal) := by - congr 2 - refine (Set.comp_indicator_const c (fun x : G ↦ (‖x‖₊ : ℝ≥0∞) ^ p.toReal) ?_) - simp [hp_pos] - _ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by - rw [lintegral_indicator_const₀ hs, ENNReal.mul_rpow_of_nonneg, ← ENNReal.rpow_mul, - mul_one_div_cancel hp_pos.ne', ENNReal.rpow_one] - positivity - @[deprecated (since := "2024-07-27")] alias snorm_indicator_const₀ := eLpNorm_indicator_const₀ -theorem eLpNorm_indicator_const {c : G} (hs : MeasurableSet s) (hp : p ≠ 0) (hp_top : p ≠ ∞) : - eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := - eLpNorm_indicator_const₀ hs.nullMeasurableSet hp hp_top - @[deprecated (since := "2024-07-27")] alias snorm_indicator_const := eLpNorm_indicator_const -theorem eLpNorm_indicator_const' {c : G} (hs : MeasurableSet s) (hμs : μ s ≠ 0) (hp : p ≠ 0) : - eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by - by_cases hp_top : p = ∞ - · simp [hp_top, eLpNormEssSup_indicator_const_eq s c hμs] - · exact eLpNorm_indicator_const hs hp hp_top - @[deprecated (since := "2024-07-27")] alias snorm_indicator_const' := eLpNorm_indicator_const' -theorem eLpNorm_indicator_const_le (c : G) (p : ℝ≥0∞) : - eLpNorm (s.indicator fun _ => c) p μ ≤ ‖c‖₊ * μ s ^ (1 / p.toReal) := by - rcases eq_or_ne p 0 with (rfl | hp) - · simp only [eLpNorm_exponent_zero, zero_le'] - rcases eq_or_ne p ∞ with (rfl | h'p) - · simp only [eLpNorm_exponent_top, ENNReal.top_toReal, _root_.div_zero, ENNReal.rpow_zero, - mul_one] - exact eLpNormEssSup_indicator_const_le _ _ - let t := toMeasurable μ s - calc - eLpNorm (s.indicator fun _ => c) p μ ≤ eLpNorm (t.indicator fun _ => c) p μ := - eLpNorm_mono (norm_indicator_le_of_subset (subset_toMeasurable _ _) _) - _ = ‖c‖₊ * μ t ^ (1 / p.toReal) := - (eLpNorm_indicator_const (measurableSet_toMeasurable _ _) hp h'p) - _ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by rw [measure_toMeasurable] - @[deprecated (since := "2024-07-27")] alias snorm_indicator_const_le := eLpNorm_indicator_const_le -theorem Memℒp.indicator (hs : MeasurableSet s) (hf : Memℒp f p μ) : Memℒp (s.indicator f) p μ := - ⟨hf.aestronglyMeasurable.indicator hs, lt_of_le_of_lt (eLpNorm_indicator_le f) hf.eLpNorm_lt_top⟩ - -theorem eLpNormEssSup_indicator_eq_eLpNormEssSup_restrict {f : α → F} (hs : MeasurableSet s) : - eLpNormEssSup (s.indicator f) μ = eLpNormEssSup f (μ.restrict s) := by - simp_rw [eLpNormEssSup_eq_essSup_nnnorm, nnnorm_indicator_eq_indicator_nnnorm, - ENNReal.coe_indicator, ENNReal.essSup_indicator_eq_essSup_restrict hs] - @[deprecated (since := "2024-07-27")] alias snormEssSup_indicator_eq_snormEssSup_restrict := eLpNormEssSup_indicator_eq_eLpNormEssSup_restrict -theorem eLpNorm_indicator_eq_eLpNorm_restrict {f : α → F} (hs : MeasurableSet s) : - eLpNorm (s.indicator f) p μ = eLpNorm f p (μ.restrict s) := by - by_cases hp_zero : p = 0 - · simp only [hp_zero, eLpNorm_exponent_zero] - by_cases hp_top : p = ∞ - · simp_rw [hp_top, eLpNorm_exponent_top] - exact eLpNormEssSup_indicator_eq_eLpNormEssSup_restrict hs - simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_zero hp_top] - suffices (∫⁻ x, (‖s.indicator f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) = - ∫⁻ x in s, (‖f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ by rw [this] - rw [← lintegral_indicator hs] - congr - simp_rw [nnnorm_indicator_eq_indicator_nnnorm, ENNReal.coe_indicator] - have h_zero : (fun x => x ^ p.toReal) (0 : ℝ≥0∞) = 0 := by - simp [ENNReal.toReal_pos hp_zero hp_top] - -- Porting note: The implicit argument should be specified because the elaborator can't deal with - -- `∘` well. - exact (Set.indicator_comp_of_zero (g := fun x : ℝ≥0∞ => x ^ p.toReal) h_zero).symm - @[deprecated (since := "2024-07-27")] alias snorm_indicator_eq_snorm_restrict := eLpNorm_indicator_eq_eLpNorm_restrict -theorem memℒp_indicator_iff_restrict (hs : MeasurableSet s) : - Memℒp (s.indicator f) p μ ↔ Memℒp f p (μ.restrict s) := by - simp [Memℒp, aestronglyMeasurable_indicator_iff hs, eLpNorm_indicator_eq_eLpNorm_restrict hs] - -/-- If a function is supported on a finite-measure set and belongs to `ℒ^p`, then it belongs to -`ℒ^q` for any `q ≤ p`. -/ -theorem Memℒp.memℒp_of_exponent_le_of_measure_support_ne_top - {p q : ℝ≥0∞} {f : α → E} (hfq : Memℒp f q μ) {s : Set α} (hf : ∀ x, x ∉ s → f x = 0) - (hs : μ s ≠ ∞) (hpq : p ≤ q) : Memℒp f p μ := by - have : (toMeasurable μ s).indicator f = f := by - apply Set.indicator_eq_self.2 - apply Function.support_subset_iff'.2 (fun x hx ↦ hf x ?_) - contrapose! hx - exact subset_toMeasurable μ s hx - rw [← this, memℒp_indicator_iff_restrict (measurableSet_toMeasurable μ s)] at hfq ⊢ - have : Fact (μ (toMeasurable μ s) < ∞) := ⟨by simpa [lt_top_iff_ne_top] using hs⟩ - exact memℒp_of_exponent_le hfq hpq - -theorem memℒp_indicator_const (p : ℝ≥0∞) (hs : MeasurableSet s) (c : E) (hμsc : c = 0 ∨ μ s ≠ ∞) : - Memℒp (s.indicator fun _ => c) p μ := by - rw [memℒp_indicator_iff_restrict hs] - rcases hμsc with rfl | hμ - · exact zero_memℒp - · have := Fact.mk hμ.lt_top - apply memℒp_const - /-- The `ℒ^p` norm of the indicator of a set is uniformly small if the set itself has small measure, for any `p < ∞`. Given here as an existential `∀ ε > 0, ∃ η > 0, ...` to avoid later management of `ℝ≥0∞`-arithmetic. -/ @@ -685,34 +557,6 @@ theorem exists_eLpNorm_indicator_le (hp : p ≠ ∞) (c : E) {ε : ℝ≥0∞} ( @[deprecated (since := "2024-07-27")] alias exists_snorm_indicator_le := exists_eLpNorm_indicator_le -protected lemma Memℒp.piecewise [DecidablePred (· ∈ s)] {g} - (hs : MeasurableSet s) (hf : Memℒp f p (μ.restrict s)) (hg : Memℒp g p (μ.restrict sᶜ)) : - Memℒp (s.piecewise f g) p μ := by - by_cases hp_zero : p = 0 - · simp only [hp_zero, memℒp_zero_iff_aestronglyMeasurable] - exact AEStronglyMeasurable.piecewise hs hf.1 hg.1 - refine ⟨AEStronglyMeasurable.piecewise hs hf.1 hg.1, ?_⟩ - rcases eq_or_ne p ∞ with rfl | hp_top - · rw [eLpNorm_top_piecewise f g hs] - exact max_lt hf.2 hg.2 - rw [eLpNorm_lt_top_iff_lintegral_rpow_nnnorm_lt_top hp_zero hp_top, ← lintegral_add_compl _ hs, - ENNReal.add_lt_top] - constructor - · have h : ∀ᵐ (x : α) ∂μ, x ∈ s → - (‖Set.piecewise s f g x‖₊ : ℝ≥0∞) ^ p.toReal = (‖f x‖₊ : ℝ≥0∞) ^ p.toReal := by - filter_upwards with a ha using by simp [ha] - rw [setLIntegral_congr_fun hs h] - exact lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hf.2 - · have h : ∀ᵐ (x : α) ∂μ, x ∈ sᶜ → - (‖Set.piecewise s f g x‖₊ : ℝ≥0∞) ^ p.toReal = (‖g x‖₊ : ℝ≥0∞) ^ p.toReal := by - filter_upwards with a ha - have ha' : a ∉ s := ha - simp [ha'] - rw [setLIntegral_congr_fun hs.compl h] - exact lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hg.2 - -end Indicator - section Topology variable {X : Type*} [TopologicalSpace X] [MeasurableSpace X] {μ : Measure X} [IsFiniteMeasureOnCompacts μ] @@ -721,14 +565,14 @@ variable {X : Type*} [TopologicalSpace X] [MeasurableSpace X] theorem _root_.HasCompactSupport.memℒp_of_bound {f : X → E} (hf : HasCompactSupport f) (h2f : AEStronglyMeasurable f μ) (C : ℝ) (hfC : ∀ᵐ x ∂μ, ‖f x‖ ≤ C) : Memℒp f p μ := by have := memℒp_top_of_bound h2f C hfC - exact this.memℒp_of_exponent_le_of_measure_support_ne_top + exact this.mono_exponent_of_measure_support_ne_top (fun x ↦ image_eq_zero_of_nmem_tsupport) (hf.measure_lt_top.ne) le_top /-- A continuous function with compact support is in L^p. -/ theorem _root_.Continuous.memℒp_of_hasCompactSupport [OpensMeasurableSpace X] {f : X → E} (hf : Continuous f) (h'f : HasCompactSupport f) : Memℒp f p μ := by have := hf.memℒp_top_of_hasCompactSupport h'f μ - exact this.memℒp_of_exponent_le_of_measure_support_ne_top + exact this.mono_exponent_of_measure_support_ne_top (fun x ↦ image_eq_zero_of_nmem_tsupport) (h'f.measure_lt_top.ne) le_top end Topology @@ -1926,4 +1770,4 @@ end Lp end MeasureTheory -set_option linter.style.longFile 2100 +set_option linter.style.longFile 1900 diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index 7e608e2c81b0c..e63acf7f6abc1 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -332,7 +332,7 @@ theorem integrableOn_Lp_of_measure_ne_top {E} [NormedAddCommGroup E] {p : ℝ≥ have hμ_restrict_univ : (μ.restrict s) Set.univ < ∞ := by simpa only [Set.univ_inter, MeasurableSet.univ, Measure.restrict_apply, lt_top_iff_ne_top] haveI hμ_finite : IsFiniteMeasure (μ.restrict s) := ⟨hμ_restrict_univ⟩ - exact ((Lp.memℒp _).restrict s).memℒp_of_exponent_le hp + exact ((Lp.memℒp _).restrict s).mono_exponent hp theorem Integrable.lintegral_lt_top {f : α → ℝ} (hf : Integrable f μ) : (∫⁻ x, ENNReal.ofReal (f x) ∂μ) < ∞ := From 7c7c15f0b67354b61df5a9f736ab9041facaeba6 Mon Sep 17 00:00:00 2001 From: damiano Date: Mon, 13 Jan 2025 11:11:15 +0000 Subject: [PATCH 194/681] feat: `#count_heartbeats` for all declarations (#20421) The "countHeartbeats" linter counts the heartbeats of every declaration. The effect of the linter is similar to `#count_heartbeats in xxx`, except that it applies to all declarations. Note that the linter only counts heartbeats in "top-level" declarations: it looks inside `set_option ... in`, but not, for instance, inside `mutual` blocks. There is a convenience notation `#count_heartbeats` that simply sets the linter option to true. *Note*. I also renamed `count_heartbeats ...` to `#count_heartbeats ...`. [Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/count_heartbeats.20for.20all.20declarations.20in.20a.20file.3F) --- Mathlib/Util/CountHeartbeats.lean | 91 ++++++++++++++++++++++++++----- MathlibTest/CountHeartbeats.lean | 61 ++++++++++++++++++++- 2 files changed, 137 insertions(+), 15 deletions(-) diff --git a/Mathlib/Util/CountHeartbeats.lean b/Mathlib/Util/CountHeartbeats.lean index 65bb809fa657c..209f07273d42b 100644 --- a/Mathlib/Util/CountHeartbeats.lean +++ b/Mathlib/Util/CountHeartbeats.lean @@ -12,7 +12,7 @@ Defines a command wrapper that prints the number of heartbeats used in the enclo For example ``` -count_heartbeats in +#count_heartbeats in theorem foo : 42 = 6 * 7 := rfl ``` will produce an info message containing a number around 51. @@ -24,8 +24,6 @@ open Lean Elab Command Meta namespace Mathlib.CountHeartbeats - - open Tactic /-- @@ -62,15 +60,15 @@ def logVariation {m} [Monad m] [MonadLog m] [AddMessageContext m] [MonadOptions -- convert `[min, max, stddev]` to user-facing heartbeats logInfo s!"Min: {min / 1000} Max: {max / 1000} StdDev: {stddev / 10}%" -/-- Count the heartbeats used by a tactic, e.g.: `count_heartbeats simp`. -/ -elab "count_heartbeats " tac:tacticSeq : tactic => do +/-- Count the heartbeats used by a tactic, e.g.: `#count_heartbeats simp`. -/ +elab "#count_heartbeats " tac:tacticSeq : tactic => do logInfo s!"{← runTacForHeartbeats tac (revert := false)}" /-- -`count_heartbeats! in tac` runs a tactic 10 times, counting the heartbeats used, and logs the range -and standard deviation. The tactic `count_heartbeats! n in tac` runs it `n` times instead. +`#count_heartbeats! in tac` runs a tactic 10 times, counting the heartbeats used, and logs the range +and standard deviation. The tactic `#count_heartbeats! n in tac` runs it `n` times instead. -/ -elab "count_heartbeats! " n:(num)? "in" ppLine tac:tacticSeq : tactic => do +elab "#count_heartbeats! " n:(num)? "in" ppLine tac:tacticSeq : tactic => do let n := match n with | some j => j.getNat | none => 10 @@ -81,7 +79,8 @@ elab "count_heartbeats! " n:(num)? "in" ppLine tac:tacticSeq : tactic => do logVariation counts /-- -Count the heartbeats used in the enclosed command. +`#count_heartbeats in cmd` counts the heartbeats used in the enclosed command `cmd`. +Use `#count_heartbeats` to count the heartbeats in *all* the following declarations. This is most useful for setting sufficient but reasonable limits via `set_option maxHeartbeats` for long running declarations. @@ -97,7 +96,7 @@ Note that that internal heartbeat counter accessible via `IO.getNumHeartbeats` has granularity 1000 times finer that the limits set by `set_option maxHeartbeats`. As this is intended as a user command, we divide by 1000. -/ -elab "count_heartbeats " "in" ppLine cmd:command : command => do +elab "#count_heartbeats " "in" ppLine cmd:command : command => do let start ← IO.getNumHeartbeats try elabCommand (← `(command| set_option maxHeartbeats 0 in $cmd)) @@ -117,6 +116,14 @@ elab "count_heartbeats " "in" ppLine cmd:command : command => do Lean.Meta.Tactic.TryThis.addSuggestion (← getRef) (← set_option hygiene false in `(command| set_option maxHeartbeats $m in $cmd)) +/-- `count_heartbeats` is deprecated in favour of `#count_heartbeats` since "2025-01-12" -/ +elab "count_heartbeats" : tactic => + logWarning "`count_heartbeats` has been renamed to `#count_heartbeats`" + +/-- `count_heartbeats` is deprecated in favour of `#count_heartbeats` since "2025-01-12" -/ +elab "count_heartbeats" : command => + logWarning "`count_heartbeats` has been renamed to `#count_heartbeats`" + /-- Guard the minimal number of heartbeats used in the enclosed command. @@ -153,17 +160,17 @@ def elabForHeartbeats (cmd : TSyntax `command) (revert : Bool := true) : Command return (← IO.getNumHeartbeats) - start /-- -`count_heartbeats! in cmd` runs a command `10` times, reporting the range in heartbeats, and the -standard deviation. The command `count_heartbeats! n in cmd` runs it `n` times instead. +`#count_heartbeats! in cmd` runs a command `10` times, reporting the range in heartbeats, and the +standard deviation. The command `#count_heartbeats! n in cmd` runs it `n` times instead. Example usage: ``` -count_heartbeats! in +#count_heartbeats! in def f := 37 ``` displays the info message `Min: 7 Max: 8 StdDev: 14%`. -/ -elab "count_heartbeats! " n:(num)? "in" ppLine cmd:command : command => do +elab "#count_heartbeats! " n:(num)? "in" ppLine cmd:command : command => do let n := match n with | some j => j.getNat | none => 10 @@ -176,3 +183,59 @@ elab "count_heartbeats! " n:(num)? "in" ppLine cmd:command : command => do end CountHeartbeats end Mathlib + +/-! +# The "countHeartbeats" linter + +The "countHeartbeats" linter counts the hearbeats of every declaration. +-/ + +open Lean Elab Command + +namespace Mathlib.Linter + +/-- +The "countHeartbeats" linter counts the heartbeats of every declaration. + +The effect of the linter is similar to `#count_heartbeats in xxx`, except that it applies +to all declarations. + +Note that the linter only counts heartbeats in "top-level" declarations: +it looks inside `set_option ... in`, but not, for instance, inside `mutual` blocks. + +There is a convenience notation `#count_heartbeats` that simply sets the linter option to true. +-/ +register_option linter.countHeartbeats : Bool := { + defValue := false + descr := "enable the countHeartbeats linter" +} + +namespace CountHeartbeats + +@[inherit_doc Mathlib.Linter.linter.countHeartbeats] +def countHeartbeatsLinter : Linter where run := withSetOptionIn fun stx ↦ do + unless Linter.getLinterValue linter.countHeartbeats (← getOptions) do + return + if (← get).messages.hasErrors then + return + let mut msgs := #[] + if [``Lean.Parser.Command.declaration, `lemma].contains stx.getKind then + let s ← get + elabCommand (← `(command| #count_heartbeats in $(⟨stx⟩))) + msgs := (← get).messages.unreported.toArray.filter (·.severity != .error) + set s + match stx.find? (·.isOfKind ``Parser.Command.declId) with + | some decl => + for msg in msgs do logInfoAt decl m!"'{decl[0].getId}' {(← msg.toString).decapitalize}" + | none => + for msg in msgs do logInfoAt stx m!"{← msg.toString}" + +initialize addLinter countHeartbeatsLinter + +@[inherit_doc Mathlib.Linter.linter.countHeartbeats] +macro "#count_heartbeats" : command => + `(command| set_option linter.countHeartbeats true) + +end CountHeartbeats + +end Mathlib.Linter diff --git a/MathlibTest/CountHeartbeats.lean b/MathlibTest/CountHeartbeats.lean index ab017f739b3c7..d476ef76e955a 100644 --- a/MathlibTest/CountHeartbeats.lean +++ b/MathlibTest/CountHeartbeats.lean @@ -4,7 +4,7 @@ set_option linter.style.header false /-- info: Used 7 heartbeats, which is less than the current maximum of 200000. -/ #guard_msgs in -count_heartbeats in +#count_heartbeats in example (a : Nat) : a = a := rfl /-- info: Used 7 heartbeats, which is less than the minimum of 200000. -/ @@ -19,3 +19,62 @@ example (a : Nat) : a = a := rfl guard_min_heartbeats 1 in example (a : Nat) : a = a := rfl + +/-! +# Tests for the `countHeartbeats` linter +-/ + +section using_count_heartbeats + +-- sets the `countHeartbeats` linter option to `true` +#count_heartbeats + +mutual -- mutual declarations get ignored +theorem XY : True := trivial +end + +/-- info: Used 4 heartbeats, which is less than the current maximum of 200000. -/ +#guard_msgs in +-- we use two nested `set_option ... in` to test that the `heartBeats` linter enters both. +set_option linter.unusedTactic false in +set_option linter.unusedTactic false in +example : True := trivial + +/-- info: Used 4 heartbeats, which is less than the current maximum of 200000. -/ +#guard_msgs in +example : True := trivial + +/-- info: 'YX' used 2 heartbeats, which is less than the current maximum of 200000. -/ +#guard_msgs in +set_option linter.unusedTactic false in +set_option linter.unusedTactic false in +theorem YX : True := trivial + +end using_count_heartbeats + +section using_linter_option + +set_option linter.countHeartbeats true + +mutual -- mutual declarations get ignored +theorem XY' : True := trivial +end + +/-- info: Used 4 heartbeats, which is less than the current maximum of 200000. -/ +#guard_msgs in +-- we use two nested `set_option ... in` to test that the `heartBeats` linter enters both. +set_option linter.unusedTactic false in +set_option linter.unusedTactic false in +example : True := trivial + +/-- info: Used 4 heartbeats, which is less than the current maximum of 200000. -/ +#guard_msgs in +example : True := trivial + +/-- info: 'YX'' used 2 heartbeats, which is less than the current maximum of 200000. -/ +#guard_msgs in +set_option linter.unusedTactic false in +set_option linter.unusedTactic false in +theorem YX' : True := trivial + +end using_linter_option From 2b47f631fa44ab5fd1c3f74ff4edf2ad3f7c37b4 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 13 Jan 2025 11:54:09 +0000 Subject: [PATCH 195/681] chore(Data/List): move a `Prod` lemma from `Basic.lean` to `ProdSigma.lean` (#20702) Noticed in the late importers report: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Late.20importers.20report/near/493286162 `List/Basic.lean` is very low down in the hierarchy so saving a few imports here might cause a big change transitively. --- Mathlib/Data/List/Basic.lean | 15 +++++---------- Mathlib/Data/List/Chain.lean | 3 ++- Mathlib/Data/List/ProdSigma.lean | 11 +++++++++++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 2f06384471cd1..8955bf6337362 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -8,7 +8,6 @@ import Mathlib.Data.Nat.Defs import Mathlib.Data.Option.Basic import Mathlib.Data.List.Defs import Mathlib.Data.List.Monad -import Mathlib.Data.Prod.Basic import Mathlib.Logic.OpClass import Mathlib.Logic.Unique import Mathlib.Order.Basic @@ -18,7 +17,11 @@ import Mathlib.Tactic.Common # Basic properties of lists -/ -assert_not_exists Set.range GroupWithZero Ring Lattice +assert_not_exists GroupWithZero +assert_not_exists Lattice +assert_not_exists Prod.swap_eq_iff_eq_swap +assert_not_exists Ring +assert_not_exists Set.range open Function @@ -2218,14 +2221,6 @@ end Forall theorem get_attach (L : List α) (i) : (L.attach.get i).1 = L.get ⟨i, length_attach (L := L) ▸ i.2⟩ := by simp -@[simp 1100] -theorem mem_map_swap (x : α) (y : β) (xs : List (α × β)) : - (y, x) ∈ map Prod.swap xs ↔ (x, y) ∈ xs := by - induction' xs with x xs xs_ih - · simp only [not_mem_nil, map_nil] - · cases' x with a b - simp only [mem_cons, Prod.mk.inj_iff, map, Prod.swap_prod_mk, Prod.exists, xs_ih, and_comm] - theorem dropSlice_eq (xs : List α) (n m : ℕ) : dropSlice n m xs = xs.take n ++ xs.drop (n + m) := by induction n generalizing xs · cases xs <;> simp [dropSlice] diff --git a/Mathlib/Data/List/Chain.lean b/Mathlib/Data/List/Chain.lean index f209731a712ce..b58ee31e33ba4 100644 --- a/Mathlib/Data/List/Chain.lean +++ b/Mathlib/Data/List/Chain.lean @@ -3,9 +3,10 @@ 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, Yury Kudryashov -/ -import Mathlib.Logic.Relation import Mathlib.Data.List.Forall2 import Mathlib.Data.List.Lex +import Mathlib.Logic.Function.Iterate +import Mathlib.Logic.Relation /-! # Relation chain diff --git a/Mathlib/Data/List/ProdSigma.lean b/Mathlib/Data/List/ProdSigma.lean index 0009e348845a5..6e1aec6c08ded 100644 --- a/Mathlib/Data/List/ProdSigma.lean +++ b/Mathlib/Data/List/ProdSigma.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Mario Carneiro -/ import Mathlib.Data.List.Basic +import Mathlib.Data.Prod.Basic import Mathlib.Data.Sigma.Basic /-! @@ -83,4 +84,14 @@ theorem length_sigma' (l₁ : List α) (l₂ : ∀ a, List (σ a)) : · rfl · simp only [map, sigma_cons, length_append, length_map, IH, Nat.sum_cons] +/-! ### Miscellaneous lemmas -/ + +@[simp 1100] +theorem mem_map_swap (x : α) (y : β) (xs : List (α × β)) : + (y, x) ∈ map Prod.swap xs ↔ (x, y) ∈ xs := by + induction' xs with x xs xs_ih + · simp only [not_mem_nil, map_nil] + · cases' x with a b + simp only [mem_cons, Prod.mk.inj_iff, map, Prod.swap_prod_mk, Prod.exists, xs_ih, and_comm] + end List From c485bfa93b3584268a6c922609a85f9f73c1b1b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 13 Jan 2025 12:45:54 +0000 Subject: [PATCH 196/681] chore: review induction principles for `Set.Finite` (#20444) Rename `Set.Finite.dinduction_on` to `Set.Finite.induction_on` as this is the more useful induction principle (it works with `induction`). Rename `Set.Finite.induction_on'` to `Set.Finite.induction_on_subset` and make it dependent. Give the assumptions meaningful names. --- Mathlib/Data/Set/Card.lean | 2 +- Mathlib/Data/Set/Finite/Basic.lean | 55 +++++++++++-------- Mathlib/Data/Set/Finite/Lattice.lean | 10 ++-- .../IntermediateField/Adjoin/Basic.lean | 9 ++- .../TensorProduct/Finiteness.lean | 2 +- .../MeasureTheory/Integral/IntegrableOn.lean | 6 +- .../MeasureTheory/MeasurableSpace/Defs.lean | 2 +- Mathlib/NumberTheory/Cyclotomic/Basic.lean | 2 +- Mathlib/Order/Filter/Finite.lean | 2 +- Mathlib/Order/Filter/Ultrafilter.lean | 2 +- .../AlgebraicIndependent/Transcendental.lean | 2 +- Mathlib/RingTheory/Finiteness/Nakayama.lean | 2 +- .../IntegralClosure/IsIntegral/Basic.lean | 2 +- Mathlib/Topology/Basic.lean | 4 +- Mathlib/Topology/ContinuousOn.lean | 2 +- Mathlib/Topology/GDelta/Basic.lean | 6 +- .../Topology/MetricSpace/MetricSeparated.lean | 2 +- Mathlib/Topology/Separation/GDelta.lean | 2 +- 18 files changed, 60 insertions(+), 54 deletions(-) diff --git a/Mathlib/Data/Set/Card.lean b/Mathlib/Data/Set/Card.lean index f1dbc517658f9..8ffca3aba9675 100644 --- a/Mathlib/Data/Set/Card.lean +++ b/Mathlib/Data/Set/Card.lean @@ -112,7 +112,7 @@ theorem encard_insert_of_not_mem {a : α} (has : a ∉ s) : (insert a s).encard rw [← union_singleton, encard_union_eq (by simpa), encard_singleton] theorem Finite.encard_lt_top (h : s.Finite) : s.encard < ⊤ := by - refine h.induction_on (by simp) ?_ + refine h.induction_on _ (by simp) ?_ rintro a t hat _ ht' rw [encard_insert_of_not_mem hat] exact lt_tsub_iff_right.1 ht' diff --git a/Mathlib/Data/Set/Finite/Basic.lean b/Mathlib/Data/Set/Finite/Basic.lean index 96e8957b578b3..d279411aede6d 100644 --- a/Mathlib/Data/Set/Finite/Basic.lean +++ b/Mathlib/Data/Set/Finite/Basic.lean @@ -668,31 +668,40 @@ theorem finite_option {s : Set (Option α)} : s.Finite ↔ { x : α | some x ∈ ((h.image some).insert none).subset fun x => x.casesOn (fun _ => Or.inl rfl) fun _ hx => Or.inr <| mem_image_of_mem _ hx⟩ +/-- Induction principle for finite sets: To prove a property `motive` of a finite set `s`, it's +enough to prove for the empty set and to prove that `motive t → motive ({a} ∪ t)` for all `t`. + +See also `Set.Finite.induction_on` for the version requiring to check `motive t → motive ({a} ∪ t)` +only for `t ⊆ s`. -/ @[elab_as_elim] -theorem Finite.induction_on {C : Set α → Prop} {s : Set α} (h : s.Finite) (H0 : C ∅) - (H1 : ∀ {a s}, a ∉ s → Set.Finite s → C s → C (insert a s)) : C s := by - lift s to Finset α using h - induction' s using Finset.cons_induction_on with a s ha hs - · rwa [Finset.coe_empty] - · rw [Finset.coe_cons] - exact @H1 a s ha (Set.toFinite _) hs - -/-- Analogous to `Finset.induction_on'`. -/ +theorem Finite.induction_on {motive : ∀ s : Set α, s.Finite → Prop} (s : Set α) (hs : s.Finite) + (empty : motive ∅ finite_empty) + (insert : ∀ {a s}, a ∉ s → + ∀ hs : Set.Finite s, motive s hs → motive (insert a s) (hs.insert a)) : + motive s hs := by + lift s to Finset α using id hs + induction' s using Finset.cons_induction_on with a s ha ih + · simpa + · simpa using @insert a s ha (Set.toFinite _) (ih _) + +/-- Induction principle for finite sets: To prove a property `C` of a finite set `s`, it's enough +to prove for the empty set and to prove that `C t → C ({a} ∪ t)` for all `t ⊆ s`. + +This is analogous to `Finset.induction_on'`. See also `Set.Finite.induction_on` for the version +requiring `C t → C ({a} ∪ t)` for all `t`. -/ @[elab_as_elim] -theorem Finite.induction_on' {C : Set α → Prop} {S : Set α} (h : S.Finite) (H0 : C ∅) - (H1 : ∀ {a s}, a ∈ S → s ⊆ S → a ∉ s → C s → C (insert a s)) : C S := by - refine @Set.Finite.induction_on α (fun s => s ⊆ S → C s) S h (fun _ => H0) ?_ Subset.rfl +theorem Finite.induction_on_subset {motive : ∀ s : Set α, s.Finite → Prop} (s : Set α) + (hs : s.Finite) (empty : motive ∅ finite_empty) + (insert : ∀ {a t}, a ∈ s → ∀ hts : t ⊆ s, a ∉ t → motive t (hs.subset hts) → + motive (insert a t) ((hs.subset hts).insert a)) : motive s hs := by + refine Set.Finite.induction_on (motive := fun t _ => ∀ hts : t ⊆ s, motive t (hs.subset hts)) s hs + (fun _ => empty) ?_ .rfl intro a s has _ hCs haS rw [insert_subset_iff] at haS - exact H1 haS.1 haS.2 has (hCs haS.2) + exact insert haS.1 haS.2 has (hCs haS.2) -@[elab_as_elim] -theorem Finite.dinduction_on {C : ∀ s : Set α, s.Finite → Prop} (s : Set α) (h : s.Finite) - (H0 : C ∅ finite_empty) - (H1 : ∀ {a s}, a ∉ s → ∀ h : Set.Finite s, C s h → C (insert a s) (h.insert a)) : C s h := - have : ∀ h : s.Finite, C s h := - Finite.induction_on h (fun _ => H0) fun has hs ih _ => H1 has hs (ih _) - this h +@[deprecated (since := "2025-01-03")] alias Finite.induction_on' := Finite.induction_on_subset +@[deprecated (since := "2025-01-03")] alias Finite.dinduction_on := Finite.induction_on section @@ -908,9 +917,9 @@ theorem finite_range_findGreatest {P : α → ℕ → Prop} [∀ x, DecidablePre theorem Finite.exists_maximal_wrt [PartialOrder β] (f : α → β) (s : Set α) (h : s.Finite) (hs : s.Nonempty) : ∃ a ∈ s, ∀ a' ∈ s, f a ≤ f a' → f a = f a' := by - induction s, h using Set.Finite.dinduction_on with - | H0 => exact absurd hs not_nonempty_empty - | @H1 a s his _ ih => + induction s, h using Set.Finite.induction_on with + | empty => exact absurd hs not_nonempty_empty + | @insert a s his _ ih => rcases s.eq_empty_or_nonempty with h | h · use a simp [h] diff --git a/Mathlib/Data/Set/Finite/Lattice.lean b/Mathlib/Data/Set/Finite/Lattice.lean index 4469adaeee8ee..bfec945979328 100644 --- a/Mathlib/Data/Set/Finite/Lattice.lean +++ b/Mathlib/Data/Set/Finite/Lattice.lean @@ -276,9 +276,9 @@ lemma map_finite_iInf {F ι : Type*} [CompleteLattice α] [CompleteLattice β] [ theorem Finite.iSup_biInf_of_monotone {ι ι' α : Type*} [Preorder ι'] [Nonempty ι'] [IsDirected ι' (· ≤ ·)] [Order.Frame α] {s : Set ι} (hs : s.Finite) {f : ι → ι' → α} (hf : ∀ i ∈ s, Monotone (f i)) : ⨆ j, ⨅ i ∈ s, f i j = ⨅ i ∈ s, ⨆ j, f i j := by - induction s, hs using Set.Finite.dinduction_on with - | H0 => simp [iSup_const] - | H1 _ _ ihs => + induction s, hs using Set.Finite.induction_on with + | empty => simp [iSup_const] + | insert _ _ ihs => rw [forall_mem_insert] at hf simp only [iInf_insert, ← ihs hf.2] exact iSup_inf_of_monotone hf.1 fun j₁ j₂ hj => iInf₂_mono fun i hi => hf.2 i hi hj @@ -361,12 +361,12 @@ variable [Preorder α] [IsDirected α (· ≤ ·)] [Nonempty α] {s : Set α} /-- A finite set is bounded above. -/ protected theorem Finite.bddAbove (hs : s.Finite) : BddAbove s := - Finite.induction_on hs bddAbove_empty fun _ _ h => h.insert _ + Finite.induction_on _ hs bddAbove_empty fun _ _ h => h.insert _ /-- A finite union of sets which are all bounded above is still bounded above. -/ theorem Finite.bddAbove_biUnion {I : Set β} {S : β → Set α} (H : I.Finite) : BddAbove (⋃ i ∈ I, S i) ↔ ∀ i ∈ I, BddAbove (S i) := - Finite.induction_on H (by simp only [biUnion_empty, bddAbove_empty, forall_mem_empty]) + Finite.induction_on _ H (by simp only [biUnion_empty, bddAbove_empty, forall_mem_empty]) fun _ _ hs => by simp only [biUnion_insert, forall_mem_insert, bddAbove_union, hs] theorem infinite_of_not_bddAbove : ¬BddAbove s → s.Infinite := diff --git a/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean b/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean index c31d004b1f21e..b7716cd854478 100644 --- a/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean +++ b/Mathlib/FieldTheory/IntermediateField/Adjoin/Basic.lean @@ -110,11 +110,10 @@ theorem toSubalgebra_iSup_of_directed (dir : Directed (· ≤ ·) t) : instance finiteDimensional_iSup_of_finite [h : Finite ι] [∀ i, FiniteDimensional K (t i)] : FiniteDimensional K (⨆ i, t i : IntermediateField K L) := by rw [← iSup_univ] - let P : Set ι → Prop := fun s => FiniteDimensional K (⨆ i ∈ s, t i : IntermediateField K L) - change P Set.univ - apply Set.Finite.induction_on - all_goals dsimp only [P] - · exact Set.finite_univ + refine Set.Finite.induction_on + (motive := fun s _ => FiniteDimensional K (⨆ i ∈ s, t i : IntermediateField K L)) + _ Set.finite_univ ?_ ?_ + all_goals dsimp · rw [iSup_emptyset] exact (botEquiv K L).symm.toLinearEquiv.finiteDimensional · intro _ s _ _ hs diff --git a/Mathlib/LinearAlgebra/TensorProduct/Finiteness.lean b/Mathlib/LinearAlgebra/TensorProduct/Finiteness.lean index 629de363a7484..7e0494642828a 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Finiteness.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Finiteness.lean @@ -100,7 +100,7 @@ theorem exists_finite_submodule_of_finite (s : Set (M ⊗[R] N)) (hs : s.Finite) ∃ (M' : Submodule R M) (N' : Submodule R N), Module.Finite R M' ∧ Module.Finite R N' ∧ s ⊆ LinearMap.range (mapIncl M' N') := by simp_rw [Module.Finite.iff_fg] - refine hs.induction_on ⟨_, _, fg_bot, fg_bot, Set.empty_subset _⟩ ?_ + refine hs.induction_on _ ⟨_, _, fg_bot, fg_bot, Set.empty_subset _⟩ ?_ rintro a s - - ⟨M', N', hM', hN', h⟩ refine TensorProduct.induction_on a ?_ (fun x y ↦ ?_) fun x y hx hy ↦ ?_ · exact ⟨M', N', hM', hN', Set.insert_subset (zero_mem _) h⟩ diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index e63acf7f6abc1..4da7bce1104cf 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -171,10 +171,8 @@ theorem integrableOn_singleton_iff {x : α} [MeasurableSingletonClass α] : @[simp] theorem integrableOn_finite_biUnion {s : Set β} (hs : s.Finite) {t : β → Set α} : - IntegrableOn f (⋃ i ∈ s, t i) μ ↔ ∀ i ∈ s, IntegrableOn f (t i) μ := by - refine hs.induction_on ?_ ?_ - · simp - · intro a s _ _ hf; simp [hf, or_imp, forall_and] + IntegrableOn f (⋃ i ∈ s, t i) μ ↔ ∀ i ∈ s, IntegrableOn f (t i) μ := + hs.induction_on _ (by simp) <| by intro a s _ _ hf; simp [hf, or_imp, forall_and] @[simp] theorem integrableOn_finset_iUnion {s : Finset β} {t : β → Set α} : diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean index 862149cd14b11..50d132feadb48 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean @@ -264,7 +264,7 @@ theorem Set.Subsingleton.measurableSet {s : Set α} (hs : s.Subsingleton) : Meas hs.induction_on .empty .singleton theorem Set.Finite.measurableSet {s : Set α} (hs : s.Finite) : MeasurableSet s := - Finite.induction_on hs MeasurableSet.empty fun _ _ hsm => hsm.insert _ + Finite.induction_on _ hs .empty fun _ _ hsm => hsm.insert _ @[measurability] protected theorem Finset.measurableSet (s : Finset α) : MeasurableSet (↑s : Set α) := diff --git a/Mathlib/NumberTheory/Cyclotomic/Basic.lean b/Mathlib/NumberTheory/Cyclotomic/Basic.lean index c9e7e4599210e..5d5e4e175bd03 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Basic.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Basic.lean @@ -301,7 +301,7 @@ protected theorem finite [IsDomain B] [h₁ : Finite S] [h₂ : IsCyclotomicExte Module.Finite A B := by cases' nonempty_fintype S with h revert h₂ A B - refine Set.Finite.induction_on h₁ (fun A B => ?_) @fun n S _ _ H A B => ?_ + refine Set.Finite.induction_on _ h₁ (fun A B => ?_) @fun n S _ _ H A B => ?_ · intro _ _ _ _ _ refine Module.finite_def.2 ⟨({1} : Finset B), ?_⟩ simp [← top_toSubmodule, ← empty, toSubmodule_bot, Submodule.one_eq_span] diff --git a/Mathlib/Order/Filter/Finite.lean b/Mathlib/Order/Filter/Finite.lean index a10cfa503fa90..42a69449b8dda 100644 --- a/Mathlib/Order/Filter/Finite.lean +++ b/Mathlib/Order/Filter/Finite.lean @@ -25,7 +25,7 @@ variable {α : Type u} {f g : Filter α} {s t : Set α} @[simp] theorem biInter_mem {β : Type v} {s : β → Set α} {is : Set β} (hf : is.Finite) : (⋂ i ∈ is, s i) ∈ f ↔ ∀ i ∈ is, s i ∈ f := - Finite.induction_on hf (by simp) fun _ _ hs => by simp [hs] + Finite.induction_on _ hf (by simp) fun _ _ hs => by simp [hs] @[simp] theorem biInter_finset_mem {β : Type v} {s : β → Set α} (is : Finset β) : diff --git a/Mathlib/Order/Filter/Ultrafilter.lean b/Mathlib/Order/Filter/Ultrafilter.lean index f64833156e58c..2e3a26c64e31b 100644 --- a/Mathlib/Order/Filter/Ultrafilter.lean +++ b/Mathlib/Order/Filter/Ultrafilter.lean @@ -161,7 +161,7 @@ theorem eventually_imp : (∀ᶠ x in f, p x → q x) ↔ (∀ᶠ x in f, p x) simp only [imp_iff_not_or, eventually_or, eventually_not] theorem finite_sUnion_mem_iff {s : Set (Set α)} (hs : s.Finite) : ⋃₀ s ∈ f ↔ ∃ t ∈ s, t ∈ f := - Finite.induction_on hs (by simp) fun _ _ his => by + Finite.induction_on _ hs (by simp) fun _ _ his => by simp [union_mem_iff, his, or_and_right, exists_or] theorem finite_biUnion_mem_iff {is : Set β} {s : β → Set α} (his : is.Finite) : diff --git a/Mathlib/RingTheory/AlgebraicIndependent/Transcendental.lean b/Mathlib/RingTheory/AlgebraicIndependent/Transcendental.lean index e6c9a512fb501..a2cc1fda4ce35 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/Transcendental.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/Transcendental.lean @@ -88,7 +88,7 @@ theorem algebraicIndependent_of_finite_type' ∀ i : ι, i ∉ t → Transcendental (adjoin R (x '' t)) (x i)) : AlgebraicIndependent R x := by classical - refine algebraicIndependent_of_finite_type fun t hfin ↦ hfin.induction_on' + refine algebraicIndependent_of_finite_type fun t hfin ↦ hfin.induction_on_subset _ (algebraicIndependent_empty_type_iff.mpr hinj) fun {a u} ha hu ha' h ↦ ?_ convert ((Set.image_eq_range _ _ ▸ h.option_iff <| x a).2 <| H u (hfin.subset hu) h _ ha').comp _ (Set.subtypeInsertEquivOption ha').injective with x diff --git a/Mathlib/RingTheory/Finiteness/Nakayama.lean b/Mathlib/RingTheory/Finiteness/Nakayama.lean index 31a287872d3bf..a5ae263188b4d 100644 --- a/Mathlib/RingTheory/Finiteness/Nakayama.lean +++ b/Mathlib/RingTheory/Finiteness/Nakayama.lean @@ -46,7 +46,7 @@ theorem exists_sub_one_mem_and_smul_eq_zero_of_fg_of_le_smul {R : Type*} [CommRi · rw [← span_le, hs] clear hin hs revert this - refine Set.Finite.dinduction_on _ hfs (fun H => ?_) @fun i s _ _ ih H => ?_ + refine Set.Finite.induction_on _ hfs (fun H => ?_) @fun i s _ _ ih H => ?_ · rcases H with ⟨r, hr1, hrn, _⟩ refine ⟨r, hr1, fun n hn => ?_⟩ specialize hrn hn diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean index a8b4fdf450893..361784bfb1bc2 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean @@ -189,7 +189,7 @@ theorem isIntegral_iff_isIntegral_closure_finite {r : B} : @[stacks 09GH] theorem fg_adjoin_of_finite {s : Set A} (hfs : s.Finite) (his : ∀ x ∈ s, IsIntegral R x) : (Algebra.adjoin R s).toSubmodule.FG := - Set.Finite.induction_on hfs + Set.Finite.induction_on _ hfs (fun _ => ⟨{1}, Submodule.ext fun x => by diff --git a/Mathlib/Topology/Basic.lean b/Mathlib/Topology/Basic.lean index 04de611bd1b5b..c31f4875b6308 100644 --- a/Mathlib/Topology/Basic.lean +++ b/Mathlib/Topology/Basic.lean @@ -120,7 +120,7 @@ lemma isOpen_iff_of_cover {f : α → Set X} (ho : ∀ i, IsOpen (f i)) (hU : ( theorem Set.Finite.isOpen_sInter {s : Set (Set X)} (hs : s.Finite) : (∀ t ∈ s, IsOpen t) → IsOpen (⋂₀ s) := - Finite.induction_on hs (fun _ => by rw [sInter_empty]; exact isOpen_univ) fun _ _ ih h => by + Finite.induction_on _ hs (fun _ => by rw [sInter_empty]; exact isOpen_univ) fun _ _ ih h => by simp only [sInter_insert, forall_mem_insert] at h ⊢ exact h.1.inter (ih h.2) @@ -281,7 +281,7 @@ theorem interior_inter : interior (s ∩ t) = interior s ∩ interior t := theorem Set.Finite.interior_biInter {ι : Type*} {s : Set ι} (hs : s.Finite) (f : ι → Set X) : interior (⋂ i ∈ s, f i) = ⋂ i ∈ s, interior (f i) := - hs.induction_on (by simp) <| by intros; simp [*] + hs.induction_on _ (by simp) <| by intros; simp [*] theorem Set.Finite.interior_sInter {S : Set (Set X)} (hS : S.Finite) : interior (⋂₀ S) = ⋂ s ∈ S, interior s := by diff --git a/Mathlib/Topology/ContinuousOn.lean b/Mathlib/Topology/ContinuousOn.lean index 6765f06a8b8dc..cc4f207c7d615 100644 --- a/Mathlib/Topology/ContinuousOn.lean +++ b/Mathlib/Topology/ContinuousOn.lean @@ -233,7 +233,7 @@ theorem nhds_of_Ici_Iic [LinearOrder α] {b : α} theorem nhdsWithin_biUnion {ι} {I : Set ι} (hI : I.Finite) (s : ι → Set α) (a : α) : 𝓝[⋃ i ∈ I, s i] a = ⨆ i ∈ I, 𝓝[s i] a := - Set.Finite.induction_on hI (by simp) fun _ _ hT ↦ by + Set.Finite.induction_on _ hI (by simp) fun _ _ hT ↦ by simp only [hT, nhdsWithin_union, iSup_insert, biUnion_insert] theorem nhdsWithin_sUnion {S : Set (Set α)} (hS : S.Finite) (a : α) : diff --git a/Mathlib/Topology/GDelta/Basic.lean b/Mathlib/Topology/GDelta/Basic.lean index 250e1184d4569..0f4a97f1f77c7 100644 --- a/Mathlib/Topology/GDelta/Basic.lean +++ b/Mathlib/Topology/GDelta/Basic.lean @@ -132,9 +132,9 @@ theorem IsGδ.union {s t : Set X} (hs : IsGδ s) (ht : IsGδ t) : IsGδ (s ∪ t /-- The union of finitely many Gδ sets is a Gδ set, `Set.sUnion` version. -/ theorem IsGδ.sUnion {S : Set (Set X)} (hS : S.Finite) (h : ∀ s ∈ S, IsGδ s) : IsGδ (⋃₀ S) := by - induction S, hS using Set.Finite.dinduction_on with - | H0 => simp - | H1 _ _ ih => + induction S, hS using Set.Finite.induction_on with + | empty => simp + | insert _ _ ih => simp only [forall_mem_insert, sUnion_insert] at * exact h.1.union (ih h.2) diff --git a/Mathlib/Topology/MetricSpace/MetricSeparated.lean b/Mathlib/Topology/MetricSpace/MetricSeparated.lean index 520ee661e1219..daeaad8d7b97d 100644 --- a/Mathlib/Topology/MetricSpace/MetricSeparated.lean +++ b/Mathlib/Topology/MetricSpace/MetricSeparated.lean @@ -89,7 +89,7 @@ theorem union_right_iff {t'} : theorem finite_iUnion_left_iff {ι : Type*} {I : Set ι} (hI : I.Finite) {s : ι → Set X} {t : Set X} : IsMetricSeparated (⋃ i ∈ I, s i) t ↔ ∀ i ∈ I, IsMetricSeparated (s i) t := by - refine Finite.induction_on hI (by simp) @fun i I _ _ hI => ?_ + refine Finite.induction_on _ hI (by simp) @fun i I _ _ hI => ?_ rw [biUnion_insert, forall_mem_insert, union_left_iff, hI] alias ⟨_, finite_iUnion_left⟩ := finite_iUnion_left_iff diff --git a/Mathlib/Topology/Separation/GDelta.lean b/Mathlib/Topology/Separation/GDelta.lean index 57bc39f4a2d32..9a90073ad9e61 100644 --- a/Mathlib/Topology/Separation/GDelta.lean +++ b/Mathlib/Topology/Separation/GDelta.lean @@ -58,7 +58,7 @@ protected theorem IsGδ.singleton [FirstCountableTopology X] [T1Space X] (x : X) theorem Set.Finite.isGδ [FirstCountableTopology X] {s : Set X} [T1Space X] (hs : s.Finite) : IsGδ s := - Finite.induction_on hs .empty fun _ _ ↦ .union (.singleton _) + Finite.induction_on _ hs .empty fun _ _ ↦ .union (.singleton _) section PerfectlyNormal From f0d4a719f048d4f884169cc55d64680103a2ebb3 Mon Sep 17 00:00:00 2001 From: blizzard_inc Date: Mon, 13 Jan 2025 13:15:19 +0000 Subject: [PATCH 197/681] chore(Algebra/Algebra/Defs): add an `algebraMap` field to `Algebra` instead of extending `RingHom` (#20518) as proposed on [zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/too.20many.20.60out.60s/near/492053667) --- Mathlib/Algebra/Algebra/Basic.lean | 37 +++++++++-------- Mathlib/Algebra/Algebra/Defs.lean | 32 ++++++++------- Mathlib/Algebra/Algebra/Opposite.lean | 2 +- Mathlib/Algebra/Algebra/Pi.lean | 8 ++-- Mathlib/Algebra/Algebra/Prod.lean | 21 +++++----- Mathlib/Algebra/Algebra/Rat.lean | 4 +- Mathlib/Algebra/Algebra/RestrictScalars.lean | 10 ++--- Mathlib/Algebra/Algebra/Subalgebra/Basic.lean | 26 ++++++------ Mathlib/Algebra/Algebra/Unitization.lean | 26 ++++++------ Mathlib/Algebra/Algebra/ZMod.lean | 18 ++++----- Mathlib/Algebra/DirectSum/Algebra.lean | 17 ++++---- Mathlib/Algebra/FreeAlgebra.lean | 2 +- .../Algebra/Module/LocalizedModule/Basic.lean | 30 +++++++------- Mathlib/Algebra/MonoidAlgebra/Basic.lean | 40 +++++++++---------- Mathlib/Algebra/Polynomial/AlgebraMap.lean | 2 +- Mathlib/Algebra/Polynomial/Laurent.lean | 8 ++-- Mathlib/Algebra/Quaternion.lean | 11 ++--- Mathlib/Algebra/RingQuot.lean | 13 +++--- Mathlib/Algebra/TrivSqZeroExt.lean | 28 ++++++------- Mathlib/Analysis/CStarAlgebra/Multiplier.lean | 27 +++++++------ Mathlib/Analysis/RCLike/Basic.lean | 11 ++--- .../Monoidal/Internal/Module.lean | 19 ++++----- .../Enumerative/IncidenceAlgebra.lean | 37 ++++++++--------- Mathlib/Data/Complex/Module.lean | 10 ++--- Mathlib/Data/ENNReal/Operations.lean | 2 +- Mathlib/Data/Matrix/Basic.lean | 4 +- Mathlib/Data/NNReal/Defs.lean | 2 +- Mathlib/FieldTheory/Galois/Basic.lean | 11 ++--- Mathlib/FieldTheory/RatFunc/Basic.lean | 11 ++--- .../Manifold/Algebra/SmoothFunctions.lean | 11 +++-- Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean | 2 +- Mathlib/LinearAlgebra/Matrix/Reindex.lean | 2 +- .../TensorProduct/Graded/Internal.lean | 2 +- .../RingTheory/AdicCompletion/Algebra.lean | 26 ++++++------ Mathlib/RingTheory/Algebraic/Pi.lean | 23 ++++++----- .../DedekindDomain/AdicValuation.lean | 25 ++++++------ .../DedekindDomain/FiniteAdeleRing.lean | 11 ++--- Mathlib/RingTheory/Extension.lean | 2 +- .../HomogeneousLocalization.lean | 11 ++--- .../RingTheory/HahnSeries/Multiplication.lean | 2 +- Mathlib/RingTheory/Ideal/Operations.lean | 13 +++--- .../RingTheory/Ideal/Quotient/Operations.lean | 14 +++---- Mathlib/RingTheory/MvPowerSeries/Basic.lean | 18 ++++----- Mathlib/RingTheory/OreLocalization/Ring.lean | 2 +- Mathlib/RingTheory/PiTensorProduct.lean | 21 +++++----- Mathlib/RingTheory/TensorProduct/Basic.lean | 2 +- .../RingTheory/Valuation/ValExtension.lean | 2 +- .../Algebra/SeparationQuotient/Basic.lean | 2 +- Mathlib/Topology/Algebra/UniformRing.lean | 14 +++---- Mathlib/Topology/ContinuousMap/Algebra.lean | 2 +- .../Topology/ContinuousMap/Bounded/Basic.lean | 2 +- Mathlib/Topology/LocallyConstant/Algebra.lean | 2 +- 52 files changed, 349 insertions(+), 331 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Basic.lean b/Mathlib/Algebra/Algebra/Basic.lean index c80fff780d07d..303fe02c038bc 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -34,11 +34,12 @@ variable [Semiring A] [Algebra R A] section PUnit instance _root_.PUnit.algebra : Algebra R PUnit.{v + 1} where - toFun _ := PUnit.unit - map_one' := rfl - map_mul' _ _ := rfl - map_zero' := rfl - map_add' _ _ := rfl + algebraMap := + { toFun _ := PUnit.unit + map_one' := rfl + map_mul' _ _ := rfl + map_zero' := rfl + map_add' _ _ := rfl } commutes' _ _ := rfl smul_def' _ _ := rfl @@ -51,9 +52,10 @@ end PUnit section ULift instance _root_.ULift.algebra : Algebra R (ULift A) := - { ULift.module', - (ULift.ringEquiv : ULift A ≃+* A).symm.toRingHom.comp (algebraMap R A) with - toFun := fun r => ULift.up (algebraMap R A r) + { ULift.module' with + algebraMap := + { (ULift.ringEquiv : ULift A ≃+* A).symm.toRingHom.comp (algebraMap R A) with + toFun := fun r => ULift.up (algebraMap R A r) } commutes' := fun r x => ULift.down_injective <| Algebra.commutes r x.down smul_def' := fun r x => ULift.down_injective <| Algebra.smul_def' r x.down } @@ -69,7 +71,7 @@ end ULift /-- Algebra over a subsemiring. This builds upon `Subsemiring.module`. -/ instance ofSubsemiring (S : Subsemiring R) : Algebra S A where - toRingHom := (algebraMap R A).comp S.subtype + algebraMap := (algebraMap R A).comp S.subtype smul := (· • ·) commutes' r x := Algebra.commutes (r : R) x smul_def' r x := Algebra.smul_def (r : R) x @@ -87,7 +89,7 @@ theorem algebraMap_ofSubsemiring_apply (S : Subsemiring R) (x : S) : algebraMap /-- Algebra over a subring. This builds upon `Subring.module`. -/ instance ofSubring {R A : Type*} [CommRing R] [Ring A] [Algebra R A] (S : Subring R) : Algebra S A where -- Porting note: don't use `toSubsemiring` because of a timeout - toRingHom := (algebraMap R A).comp S.subtype + algebraMap := (algebraMap R A).comp S.subtype smul := (· • ·) commutes' r x := Algebra.commutes (r : R) x smul_def' r x := Algebra.smul_def (r : R) x @@ -143,11 +145,12 @@ abbrev semiringToRing (R : Type*) [CommRing R] [Semiring A] [Algebra R A] : Ring intCast_negSucc := fun z => by simp } instance {R : Type*} [Ring R] : Algebra (Subring.center R) R where - toFun := Subtype.val - map_one' := rfl - map_mul' _ _ := rfl - map_zero' := rfl - map_add' _ _ := rfl + algebraMap := + { toFun := Subtype.val + map_one' := rfl + map_mul' _ _ := rfl + map_zero' := rfl + map_add' _ _ := rfl } commutes' r x := (Subring.mem_center_iff.1 r.2 x).symm smul_def' _ _ := rfl @@ -235,7 +238,7 @@ variable {R : Type*} [Semiring R] instance (priority := 99) Semiring.toNatAlgebra : Algebra ℕ R where commutes' := Nat.cast_commute smul_def' _ _ := nsmul_eq_mul _ _ - toRingHom := Nat.castRingHom R + algebraMap := Nat.castRingHom R instance nat_algebra_subsingleton : Subsingleton (Algebra ℕ R) := ⟨fun P Q => by ext; simp⟩ @@ -253,7 +256,7 @@ variable (R : Type*) [Ring R] instance (priority := 99) Ring.toIntAlgebra : Algebra ℤ R where commutes' := Int.cast_commute smul_def' _ _ := zsmul_eq_mul _ _ - toRingHom := Int.castRingHom R + algebraMap := Int.castRingHom R /-- A special case of `eq_intCast'` that happens to be true definitionally -/ @[simp] diff --git a/Mathlib/Algebra/Algebra/Defs.lean b/Mathlib/Algebra/Algebra/Defs.lean index 40444543378de..8f9470e1325d7 100644 --- a/Mathlib/Algebra/Algebra/Defs.lean +++ b/Mathlib/Algebra/Algebra/Defs.lean @@ -96,16 +96,18 @@ section Prio See the implementation notes in this file for discussion of the details of this definition. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): unsupported @[nolint has_nonempty_instance] -class Algebra (R : Type u) (A : Type v) [CommSemiring R] [Semiring A] extends SMul R A, - R →+* A where - commutes' : ∀ r x, toRingHom r * x = x * toRingHom r - smul_def' : ∀ r x, r • x = toRingHom r * x +class Algebra (R : Type u) (A : Type v) [CommSemiring R] [Semiring A] extends SMul R A where + /-- Embedding `R →+* A` given by `Algebra` structure. + Use `algebraMap` from the root namespace instead.-/ + protected algebraMap : R →+* A + commutes' : ∀ r x, algebraMap r * x = x * algebraMap r + smul_def' : ∀ r x, r • x = algebraMap r * x end Prio /-- Embedding `R →+* A` given by `Algebra` structure. -/ def algebraMap (R : Type u) (A : Type v) [CommSemiring R] [Semiring A] [Algebra R A] : R →+* A := - Algebra.toRingHom + Algebra.algebraMap /-- Coercion from a commutative semiring to an algebra over this semiring. -/ @[coe, reducible] @@ -171,7 +173,7 @@ def RingHom.toAlgebra' {R S} [CommSemiring R] [Semiring S] (i : R →+* S) smul c x := i c * x commutes' := h smul_def' _ _ := rfl - toRingHom := i + algebraMap := i -- just simple lemmas for a declaration that is itself primed, no need for docstrings set_option linter.docPrime false in @@ -206,11 +208,12 @@ See note [reducible non-instances]. -/ abbrev ofModule' [CommSemiring R] [Semiring A] [Module R A] (h₁ : ∀ (r : R) (x : A), r • (1 : A) * x = r • x) (h₂ : ∀ (r : R) (x : A), x * r • (1 : A) = r • x) : Algebra R A where - toFun r := r • (1 : A) - map_one' := one_smul _ _ - map_mul' r₁ r₂ := by simp only [h₁, mul_smul] - map_zero' := zero_smul _ _ - map_add' r₁ r₂ := add_smul r₁ r₂ 1 + algebraMap := + { toFun r := r • (1 : A) + map_one' := one_smul _ _ + map_mul' r₁ r₂ := by simp only [h₁, mul_smul] + map_zero' := zero_smul _ _ + map_add' r₁ r₂ := add_smul r₁ r₂ 1 } commutes' r x := by simp [h₁, h₂] smul_def' r x := by simp [h₁] @@ -239,7 +242,7 @@ it suffices to check the `algebraMap`s agree. theorem algebra_ext {R : Type*} [CommSemiring R] {A : Type*} [Semiring A] (P Q : Algebra R A) (h : ∀ r : R, (haveI := P; algebraMap R A r) = haveI := Q; algebraMap R A r) : P = Q := by - replace h : P.toRingHom = Q.toRingHom := DFunLike.ext _ _ h + replace h : P.algebraMap = Q.algebraMap := DFunLike.ext _ _ h have h' : (haveI := P; (· • ·) : R → A → A) = (haveI := Q; (· • ·) : R → A → A) := by funext r a rw [P.smul_def', Q.smul_def', h] @@ -333,7 +336,7 @@ This is the algebra version of `Module.compHom`. -/ abbrev compHom : Algebra S A where smul s a := f s • a - toRingHom := (algebraMap R A).comp f + algebraMap := (algebraMap R A).comp f commutes' _ _ := Algebra.commutes _ _ smul_def' _ _ := Algebra.smul_def _ _ @@ -372,9 +375,8 @@ instance (priority := 1100) id : Algebra R R where -- We override `toFun` and `toSMul` because `RingHom.id` is not reducible and cannot -- be made so without a significant performance hit. -- see library note [reducible non-instances]. - toFun x := x toSMul := Mul.toSMul _ - __ := (RingHom.id R).toAlgebra + __ := ({RingHom.id R with toFun x := x}).toAlgebra variable {R A} diff --git a/Mathlib/Algebra/Algebra/Opposite.lean b/Mathlib/Algebra/Algebra/Opposite.lean index f98ba51332141..f5dfbff514a6d 100644 --- a/Mathlib/Algebra/Algebra/Opposite.lean +++ b/Mathlib/Algebra/Algebra/Opposite.lean @@ -38,7 +38,7 @@ variable [IsScalarTower R S A] namespace MulOpposite instance instAlgebra : Algebra R Aᵐᵒᵖ where - toRingHom := (algebraMap R A).toOpposite fun _ _ => Algebra.commutes _ _ + algebraMap := (algebraMap R A).toOpposite fun _ _ => Algebra.commutes _ _ smul_def' c x := unop_injective <| by simp only [unop_smul, RingHom.toOpposite_apply, Function.comp_apply, unop_mul, op_mul, Algebra.smul_def, Algebra.commutes, op_unop, unop_op] diff --git a/Mathlib/Algebra/Algebra/Pi.lean b/Mathlib/Algebra/Algebra/Pi.lean index ff52cbbf24423..188a138794019 100644 --- a/Mathlib/Algebra/Algebra/Pi.lean +++ b/Mathlib/Algebra/Algebra/Pi.lean @@ -34,10 +34,10 @@ variable (x y : ∀ i, f i) (i : I) variable (I f) instance algebra {r : CommSemiring R} [s : ∀ i, Semiring (f i)] [∀ i, Algebra R (f i)] : - Algebra R (∀ i : I, f i) := - { (Pi.ringHom fun i => algebraMap R (f i) : R →+* ∀ i : I, f i) with - commutes' := fun a f => by ext; simp [Algebra.commutes] - smul_def' := fun a f => by ext; simp [Algebra.smul_def] } + Algebra R (∀ i : I, f i) where + algebraMap := (Pi.ringHom fun i => algebraMap R (f i) : R →+* ∀ i : I, f i) + commutes' := fun a f => by ext; simp [Algebra.commutes] + smul_def' := fun a f => by ext; simp [Algebra.smul_def] theorem algebraMap_def {_ : CommSemiring R} [_s : ∀ i, Semiring (f i)] [∀ i, Algebra R (f i)] (a : R) : algebraMap R (∀ i, f i) a = fun i => algebraMap R (f i) a := diff --git a/Mathlib/Algebra/Algebra/Prod.lean b/Mathlib/Algebra/Algebra/Prod.lean index 312790886ed37..0c726579527a5 100644 --- a/Mathlib/Algebra/Algebra/Prod.lean +++ b/Mathlib/Algebra/Algebra/Prod.lean @@ -30,17 +30,16 @@ variable (R A B) open Algebra -instance algebra : Algebra R (A × B) := - { Prod.instModule, - RingHom.prod (algebraMap R A) (algebraMap R B) with - commutes' := by - rintro r ⟨a, b⟩ - dsimp - rw [commutes r a, commutes r b] - smul_def' := by - rintro r ⟨a, b⟩ - dsimp - rw [Algebra.smul_def r a, Algebra.smul_def r b] } +instance algebra : Algebra R (A × B) where + algebraMap := RingHom.prod (algebraMap R A) (algebraMap R B) + commutes' := by + rintro r ⟨a, b⟩ + dsimp + rw [commutes r a, commutes r b] + smul_def' := by + rintro r ⟨a, b⟩ + dsimp + rw [Algebra.smul_def r a, Algebra.smul_def r b] variable {R A B} diff --git a/Mathlib/Algebra/Algebra/Rat.lean b/Mathlib/Algebra/Algebra/Rat.lean index bfccd9246f030..8cdd3179627ce 100644 --- a/Mathlib/Algebra/Algebra/Rat.lean +++ b/Mathlib/Algebra/Algebra/Rat.lean @@ -49,7 +49,7 @@ variable [DivisionSemiring S] [CharZero S] instance _root_.DivisionSemiring.toNNRatAlgebra : Algebra ℚ≥0 R where smul_def' := smul_def - toRingHom := castHom _ + algebraMap := castHom _ commutes' := cast_commute instance _root_.RingHomClass.toLinearMapClassNNRat [FunLike F R S] [RingHomClass F R S] : @@ -89,7 +89,7 @@ variable [DivisionRing S] [CharZero S] instance _root_.DivisionRing.toRatAlgebra : Algebra ℚ R where smul_def' := smul_def - toRingHom := castHom _ + algebraMap := castHom _ commutes' := cast_commute instance _root_.RingHomClass.toLinearMapClassRat [FunLike F R S] [RingHomClass F R S] : diff --git a/Mathlib/Algebra/Algebra/RestrictScalars.lean b/Mathlib/Algebra/Algebra/RestrictScalars.lean index 20a38263fd74c..aa715010ba854 100644 --- a/Mathlib/Algebra/Algebra/RestrictScalars.lean +++ b/Mathlib/Algebra/Algebra/RestrictScalars.lean @@ -198,11 +198,11 @@ theorem RestrictScalars.ringEquiv_map_smul (r : R) (x : RestrictScalars R S A) : rfl /-- `R ⟶ S` induces `S-Alg ⥤ R-Alg` -/ -instance RestrictScalars.algebra : Algebra R (RestrictScalars R S A) := - { (algebraMap S A).comp (algebraMap R S) with - smul := (· • ·) - commutes' := fun _ _ ↦ Algebra.commutes' (A := A) _ _ - smul_def' := fun _ _ ↦ Algebra.smul_def' (A := A) _ _ } +instance RestrictScalars.algebra : Algebra R (RestrictScalars R S A) where + algebraMap := (algebraMap S A).comp (algebraMap R S) + smul := (· • ·) + commutes' := fun _ _ ↦ Algebra.commutes' (A := A) _ _ + smul_def' := fun _ _ ↦ Algebra.smul_def' (A := A) _ _ @[simp] theorem RestrictScalars.ringEquiv_algebraMap (r : R) : diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index 20dfa0a99eb8f..9b993db3f4eba 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -284,14 +284,13 @@ which can quickly get expensive. -/ instance (priority := 500) algebra' [CommSemiring R'] [SMul R' R] [Algebra R' A] [IsScalarTower R' R A] : - Algebra R' S := - { (algebraMap R' A).codRestrict S fun x => by - rw [Algebra.algebraMap_eq_smul_one, ← smul_one_smul R x (1 : A), ← - Algebra.algebraMap_eq_smul_one] - exact algebraMap_mem S - _ with - commutes' := fun _ _ => Subtype.eq <| Algebra.commutes _ _ - smul_def' := fun _ _ => Subtype.eq <| Algebra.smul_def _ _ } + Algebra R' S where + algebraMap := (algebraMap R' A).codRestrict S fun x => by + rw [Algebra.algebraMap_eq_smul_one, ← smul_one_smul R x (1 : A), ← + Algebra.algebraMap_eq_smul_one] + exact algebraMap_mem S _ + commutes' := fun _ _ => Subtype.eq <| Algebra.commutes _ _ + smul_def' := fun _ _ => Subtype.eq <| Algebra.smul_def _ _ instance algebra : Algebra R S := S.algebra' @@ -425,11 +424,12 @@ variable {S R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] variable [SetLike S A] [SubsemiringClass S A] [hSR : SMulMemClass S R A] (s : S) instance (priority := 75) toAlgebra : Algebra R s where - toFun r := ⟨algebraMap R A r, algebraMap_mem s r⟩ - map_one' := Subtype.ext <| by simp - map_mul' _ _ := Subtype.ext <| by simp - map_zero' := Subtype.ext <| by simp - map_add' _ _ := Subtype.ext <| by simp + algebraMap := { + toFun r := ⟨algebraMap R A r, algebraMap_mem s r⟩ + map_one' := Subtype.ext <| by simp + map_mul' _ _ := Subtype.ext <| by simp + map_zero' := Subtype.ext <| by simp + map_add' _ _ := Subtype.ext <| by simp} commutes' r x := Subtype.ext <| Algebra.commutes r (x : A) smul_def' r x := Subtype.ext <| (algebraMap_smul A r (x : A)).symm diff --git a/Mathlib/Algebra/Algebra/Unitization.lean b/Mathlib/Algebra/Algebra/Unitization.lean index 89f706b546d03..70f890609faf6 100644 --- a/Mathlib/Algebra/Algebra/Unitization.lean +++ b/Mathlib/Algebra/Algebra/Unitization.lean @@ -558,19 +558,19 @@ variable (S R A : Type*) [CommSemiring S] [CommSemiring R] [NonUnitalSemiring A] [IsScalarTower R A A] [SMulCommClass R A A] [Algebra S R] [DistribMulAction S A] [IsScalarTower S R A] -instance instAlgebra : Algebra S (Unitization R A) := - { (Unitization.inlRingHom R A).comp (algebraMap S R) with - commutes' := fun s x => by - induction x with - | inl_add_inr => - show inl (algebraMap S R s) * _ = _ * inl (algebraMap S R s) - rw [mul_add, add_mul, inl_mul_inl, inl_mul_inl, inl_mul_inr, inr_mul_inl, mul_comm] - smul_def' := fun s x => by - induction x with - | inl_add_inr => - show _ = inl (algebraMap S R s) * _ - rw [mul_add, smul_add,Algebra.algebraMap_eq_smul_one, inl_mul_inl, inl_mul_inr, - smul_one_mul, inl_smul, inr_smul, smul_one_smul] } +instance instAlgebra : Algebra S (Unitization R A) where + algebraMap := (Unitization.inlRingHom R A).comp (algebraMap S R) + commutes' := fun s x => by + induction x with + | inl_add_inr => + show inl (algebraMap S R s) * _ = _ * inl (algebraMap S R s) + rw [mul_add, add_mul, inl_mul_inl, inl_mul_inl, inl_mul_inr, inr_mul_inl, mul_comm] + smul_def' := fun s x => by + induction x with + | inl_add_inr => + show _ = inl (algebraMap S R s) * _ + rw [mul_add, smul_add,Algebra.algebraMap_eq_smul_one, inl_mul_inl, inl_mul_inr, + smul_one_mul, inl_smul, inr_smul, smul_one_smul] theorem algebraMap_eq_inl_comp : ⇑(algebraMap S (Unitization R A)) = inl ∘ algebraMap S R := rfl diff --git a/Mathlib/Algebra/Algebra/ZMod.lean b/Mathlib/Algebra/Algebra/ZMod.lean index 1318279bee0d5..4e52ebef7668a 100644 --- a/Mathlib/Algebra/Algebra/ZMod.lean +++ b/Mathlib/Algebra/Algebra/ZMod.lean @@ -25,15 +25,15 @@ variable {n : ℕ} (m : ℕ) [CharP R m] /-- The `ZMod n`-algebra structure on rings whose characteristic `m` divides `n`. See note [reducible non-instances]. -/ -abbrev algebra' (h : m ∣ n) : Algebra (ZMod n) R := - { ZMod.castHom h R with - smul := fun a r => cast a * r - commutes' := fun a r => - show (cast a * r : R) = r * cast a by - rcases ZMod.intCast_surjective a with ⟨k, rfl⟩ - show ZMod.castHom h R k * r = r * ZMod.castHom h R k - rw [map_intCast, Int.cast_comm] - smul_def' := fun _ _ => rfl } +abbrev algebra' (h : m ∣ n) : Algebra (ZMod n) R where + algebraMap := ZMod.castHom h R + smul := fun a r => cast a * r + commutes' := fun a r => + show (cast a * r : R) = r * cast a by + rcases ZMod.intCast_surjective a with ⟨k, rfl⟩ + show ZMod.castHom h R k * r = r * ZMod.castHom h R k + rw [map_intCast, Int.cast_comm] + smul_def' := fun _ _ => rfl end diff --git a/Mathlib/Algebra/DirectSum/Algebra.lean b/Mathlib/Algebra/DirectSum/Algebra.lean index 5db0ecc0efa46..7294186260b4b 100644 --- a/Mathlib/Algebra/DirectSum/Algebra.lean +++ b/Mathlib/Algebra/DirectSum/Algebra.lean @@ -68,14 +68,15 @@ instance _root_.GradedMonoid.isScalarTower_right : variable [DecidableEq ι] instance : Algebra R (⨁ i, A i) where - toFun := (DirectSum.of A 0).comp GAlgebra.toFun - map_zero' := AddMonoidHom.map_zero _ - map_add' := AddMonoidHom.map_add _ - map_one' := DFunLike.congr_arg (DirectSum.of A 0) GAlgebra.map_one - map_mul' a b := by - simp only [AddMonoidHom.comp_apply] - rw [of_mul_of] - apply DFinsupp.single_eq_of_sigma_eq (GAlgebra.map_mul a b) + algebraMap := + { toFun := (DirectSum.of A 0).comp GAlgebra.toFun + map_zero' := AddMonoidHom.map_zero _ + map_add' := AddMonoidHom.map_add _ + map_one' := DFunLike.congr_arg (DirectSum.of A 0) GAlgebra.map_one + map_mul' a b := by + simp only [AddMonoidHom.comp_apply] + rw [of_mul_of] + apply DFinsupp.single_eq_of_sigma_eq (GAlgebra.map_mul a b) } commutes' r x := by change AddMonoidHom.mul (DirectSum.of _ _ _) x = AddMonoidHom.mul.flip (DirectSum.of _ _ _) x apply DFunLike.congr_fun _ x diff --git a/Mathlib/Algebra/FreeAlgebra.lean b/Mathlib/Algebra/FreeAlgebra.lean index 34d8d6cff1349..cb67478cd887c 100644 --- a/Mathlib/Algebra/FreeAlgebra.lean +++ b/Mathlib/Algebra/FreeAlgebra.lean @@ -241,7 +241,7 @@ instance : Inhabited (FreeAlgebra R X) := ⟨0⟩ instance instAlgebra {A} [CommSemiring A] [Algebra R A] : Algebra R (FreeAlgebra A X) where - toRingHom := ({ + algebraMap := ({ toFun := fun r => Quot.mk _ r map_one' := rfl map_mul' := fun _ _ => Quot.sound Rel.mul_scalar diff --git a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean index 344dd8108df36..b806dbdd9c38e 100644 --- a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean +++ b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean @@ -457,21 +457,21 @@ instance : IsScalarTower R T (LocalizedModule S M) where smul'_mk, mul_smul] noncomputable instance algebra' {A : Type*} [Semiring A] [Algebra R A] : - Algebra R (LocalizedModule S A) := - { (algebraMap (Localization S) (LocalizedModule S A)).comp (algebraMap R <| Localization S), - show Module R (LocalizedModule S A) by infer_instance with - commutes' := by - intro r x - induction x using induction_on with | _ a s => _ - dsimp - rw [← Localization.mk_one_eq_algebraMap, algebraMap_mk, mk_mul_mk, mk_mul_mk, mul_comm, - Algebra.commutes] - smul_def' := by - intro r x - induction x using induction_on with | _ a s => _ - dsimp - rw [← Localization.mk_one_eq_algebraMap, algebraMap_mk, mk_mul_mk, smul'_mk, - Algebra.smul_def, one_mul] } + Algebra R (LocalizedModule S A) where + algebraMap := (algebraMap (Localization S) (LocalizedModule S A)).comp + (algebraMap R <| Localization S) + commutes' := by + intro r x + induction x using induction_on with | _ a s => _ + dsimp + rw [← Localization.mk_one_eq_algebraMap, algebraMap_mk, mk_mul_mk, mk_mul_mk, mul_comm, + Algebra.commutes] + smul_def' := by + intro r x + induction x using induction_on with | _ a s => _ + dsimp + rw [← Localization.mk_one_eq_algebraMap, algebraMap_mk, mk_mul_mk, smul'_mk, + Algebra.smul_def, one_mul] section diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index cc2595e20de87..fbea78035339d 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -106,16 +106,16 @@ section Algebra In particular this provides the instance `Algebra k (MonoidAlgebra k G)`. -/ instance algebra {A : Type*} [CommSemiring k] [Semiring A] [Algebra k A] [Monoid G] : - Algebra k (MonoidAlgebra A G) := - { singleOneRingHom.comp (algebraMap k A) with - smul_def' := fun r a => by - ext - -- Porting note: Newly required. - rw [Finsupp.coe_smul] - simp [single_one_mul_apply, Algebra.smul_def, Pi.smul_apply] - commutes' := fun r f => by - refine Finsupp.ext fun _ => ?_ - simp [single_one_mul_apply, mul_single_one_apply, Algebra.commutes] } + Algebra k (MonoidAlgebra A G) where + algebraMap := singleOneRingHom.comp (algebraMap k A) + smul_def' := fun r a => by + ext + -- Porting note: Newly required. + rw [Finsupp.coe_smul] + simp [single_one_mul_apply, Algebra.smul_def, Pi.smul_apply] + commutes' := fun r f => by + refine Finsupp.ext fun _ => ?_ + simp [single_one_mul_apply, mul_single_one_apply, Algebra.commutes] /-- `Finsupp.single 1` as an `AlgHom` -/ @[simps! apply] @@ -385,16 +385,16 @@ section Algebra In particular this provides the instance `Algebra k k[G]`. -/ instance algebra [CommSemiring R] [Semiring k] [Algebra R k] [AddMonoid G] : - Algebra R k[G] := - { singleZeroRingHom.comp (algebraMap R k) with - smul_def' := fun r a => by - ext - -- Porting note: Newly required. - rw [Finsupp.coe_smul] - simp [single_zero_mul_apply, Algebra.smul_def, Pi.smul_apply] - commutes' := fun r f => by - refine Finsupp.ext fun _ => ?_ - simp [single_zero_mul_apply, mul_single_zero_apply, Algebra.commutes] } + Algebra R k[G] where + algebraMap := singleZeroRingHom.comp (algebraMap R k) + smul_def' := fun r a => by + ext + -- Porting note: Newly required. + rw [Finsupp.coe_smul] + simp [single_zero_mul_apply, Algebra.smul_def, Pi.smul_apply] + commutes' := fun r f => by + refine Finsupp.ext fun _ => ?_ + simp [single_zero_mul_apply, mul_single_zero_apply, Algebra.commutes] /-- `Finsupp.single 0` as an `AlgHom` -/ @[simps! apply] diff --git a/Mathlib/Algebra/Polynomial/AlgebraMap.lean b/Mathlib/Algebra/Polynomial/AlgebraMap.lean index b58d9b56eb9b1..eeb486b820ed0 100644 --- a/Mathlib/Algebra/Polynomial/AlgebraMap.lean +++ b/Mathlib/Algebra/Polynomial/AlgebraMap.lean @@ -49,7 +49,7 @@ instance algebraOfAlgebra : Algebra R A[X] where dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply] simp_rw [toFinsupp_mul, toFinsupp_C] convert Algebra.commutes' r p.toFinsupp - toRingHom := C.comp (algebraMap R A) + algebraMap := C.comp (algebraMap R A) @[simp] theorem algebraMap_apply (r : R) : algebraMap R A[X] r = C (algebraMap R A r) := diff --git a/Mathlib/Algebra/Polynomial/Laurent.lean b/Mathlib/Algebra/Polynomial/Laurent.lean index edc3785ed472d..2116b5e76bff0 100644 --- a/Mathlib/Algebra/Polynomial/Laurent.lean +++ b/Mathlib/Algebra/Polynomial/Laurent.lean @@ -491,10 +491,10 @@ section CommSemiring variable [CommSemiring R] -instance algebraPolynomial (R : Type*) [CommSemiring R] : Algebra R[X] R[T;T⁻¹] := - { Polynomial.toLaurent with - commutes' := fun f l => by simp [mul_comm] - smul_def' := fun _ _ => rfl } +instance algebraPolynomial (R : Type*) [CommSemiring R] : Algebra R[X] R[T;T⁻¹] where + algebraMap := Polynomial.toLaurent + commutes' := fun f l => by simp [mul_comm] + smul_def' := fun _ _ => rfl theorem algebraMap_X_pow (n : ℕ) : algebraMap R[X] R[T;T⁻¹] (X ^ n) = T n := Polynomial.toLaurent_X_pow n diff --git a/Mathlib/Algebra/Quaternion.lean b/Mathlib/Algebra/Quaternion.lean index 9a6904b709e90..94837ea0cd371 100644 --- a/Mathlib/Algebra/Quaternion.lean +++ b/Mathlib/Algebra/Quaternion.lean @@ -484,11 +484,12 @@ theorem coe_mul : ((x * y : R) : ℍ[R,c₁,c₂]) = x * y := by ext <;> simp -- for `ℍ[R]`) instance [CommSemiring S] [Algebra S R] : Algebra S ℍ[R,c₁,c₂] where smul := (· • ·) - toFun s := coe (algebraMap S R s) - map_one' := by simp only [map_one, coe_one] - map_zero' := by simp only [map_zero, coe_zero] - map_mul' x y := by simp only [map_mul, coe_mul] - map_add' x y := by simp only [map_add, coe_add] + algebraMap := + { toFun s := coe (algebraMap S R s) + map_one' := by simp only [map_one, coe_one] + map_zero' := by simp only [map_zero, coe_zero] + map_mul' x y := by simp only [map_mul, coe_mul] + map_add' x y := by simp only [map_add, coe_add] } smul_def' s x := by ext <;> simp [Algebra.smul_def] commutes' s x := by ext <;> simp [Algebra.commutes] diff --git a/Mathlib/Algebra/RingQuot.lean b/Mathlib/Algebra/RingQuot.lean index 468b97fb7ad6c..1a801894c1ef2 100644 --- a/Mathlib/Algebra/RingQuot.lean +++ b/Mathlib/Algebra/RingQuot.lean @@ -36,7 +36,7 @@ namespace RingCon instance (c : RingCon A) : Algebra S c.Quotient where smul := (· • ·) - toRingHom := c.mk'.comp (algebraMap S A) + algebraMap := c.mk'.comp (algebraMap S A) commutes' _ := Quotient.ind' fun _ ↦ congr_arg Quotient.mk'' <| Algebra.commutes _ _ smul_def' _ := Quotient.ind' fun _ ↦ congr_arg Quotient.mk'' <| Algebra.smul_def _ _ @@ -378,11 +378,12 @@ instance instInhabited (r : R → R → Prop) : Inhabited (RingQuot r) := instance instAlgebra [Algebra S R] (r : R → R → Prop) : Algebra S (RingQuot r) where smul := (· • ·) - toFun r := ⟨Quot.mk _ (algebraMap S R r)⟩ - map_one' := by simp [← one_quot] - map_mul' := by simp [mul_quot] - map_zero' := by simp [← zero_quot] - map_add' := by simp [add_quot] + algebraMap := + { toFun r := ⟨Quot.mk _ (algebraMap S R r)⟩ + map_one' := by simp [← one_quot] + map_mul' := by simp [mul_quot] + map_zero' := by simp [← zero_quot] + map_add' := by simp [add_quot] } commutes' r := by rintro ⟨⟨a⟩⟩ simp [Algebra.commutes, mul_quot] diff --git a/Mathlib/Algebra/TrivSqZeroExt.lean b/Mathlib/Algebra/TrivSqZeroExt.lean index fd15145d858ba..027817e6fef82 100644 --- a/Mathlib/Algebra/TrivSqZeroExt.lean +++ b/Mathlib/Algebra/TrivSqZeroExt.lean @@ -875,20 +875,20 @@ variable [Algebra S R] [Module S M] [Module R M] [Module Rᵐᵒᵖ M] [SMulComm variable [IsScalarTower S R M] [IsScalarTower S Rᵐᵒᵖ M] variable [Module R' M] [Module R'ᵐᵒᵖ M] [IsCentralScalar R' M] -instance algebra' : Algebra S (tsze R M) := - { (TrivSqZeroExt.inlHom R M).comp (algebraMap S R) with - smul := (· • ·) - commutes' := fun s x => - ext (Algebra.commutes _ _) <| - show algebraMap S R s •> x.snd + (0 : M) <• x.fst - = x.fst •> (0 : M) + x.snd <• algebraMap S R s by - rw [smul_zero, smul_zero, add_zero, zero_add] - rw [Algebra.algebraMap_eq_smul_one, MulOpposite.op_smul, op_one, smul_assoc, - one_smul, smul_assoc, one_smul] - smul_def' := fun s x => - ext (Algebra.smul_def _ _) <| - show s • x.snd = algebraMap S R s •> x.snd + (0 : M) <• x.fst by - rw [smul_zero, add_zero, algebraMap_smul] } +instance algebra' : Algebra S (tsze R M) where + algebraMap := (TrivSqZeroExt.inlHom R M).comp (algebraMap S R) + smul := (· • ·) + commutes' := fun s x => + ext (Algebra.commutes _ _) <| + show algebraMap S R s •> x.snd + (0 : M) <• x.fst + = x.fst •> (0 : M) + x.snd <• algebraMap S R s by + rw [smul_zero, smul_zero, add_zero, zero_add] + rw [Algebra.algebraMap_eq_smul_one, MulOpposite.op_smul, op_one, smul_assoc, + one_smul, smul_assoc, one_smul] + smul_def' := fun s x => + ext (Algebra.smul_def _ _) <| + show s • x.snd = algebraMap S R s •> x.snd + (0 : M) <• x.fst by + rw [smul_zero, add_zero, algebraMap_smul] -- shortcut instance for the common case instance : Algebra R' (tsze R' M) := diff --git a/Mathlib/Analysis/CStarAlgebra/Multiplier.lean b/Mathlib/Analysis/CStarAlgebra/Multiplier.lean index 97b6d4406dc4b..2463324f04481 100644 --- a/Mathlib/Analysis/CStarAlgebra/Multiplier.lean +++ b/Mathlib/Analysis/CStarAlgebra/Multiplier.lean @@ -358,19 +358,20 @@ instance instModule {S : Type*} [Semiring S] [Module S A] [SMulCommClass 𝕜 S -- TODO: generalize to `Algebra S 𝓜(𝕜, A)` once `ContinuousLinearMap.algebra` is generalized. instance instAlgebra : Algebra 𝕜 𝓜(𝕜, A) where - toFun k := - { toProd := algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A)) k - central := fun x y => by - simp_rw [Prod.algebraMap_apply, Algebra.algebraMap_eq_smul_one, smul_apply, one_apply, - mul_smul_comm, smul_mul_assoc] } - map_one' := ext (𝕜 := 𝕜) (A := A) _ _ <| map_one <| algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A)) - map_mul' _ _ := - ext (𝕜 := 𝕜) (A := A) _ _ <| - Prod.ext (map_mul (algebraMap 𝕜 (A →L[𝕜] A)) _ _) - ((map_mul (algebraMap 𝕜 (A →L[𝕜] A)) _ _).trans (Algebra.commutes _ _)) - map_zero' := ext (𝕜 := 𝕜) (A := A) _ _ <| map_zero <| algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A)) - map_add' _ _ := ext (𝕜 := 𝕜) (A := A) _ _ <| - map_add (algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A))) _ _ + algebraMap := + { toFun k := + { toProd := algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A)) k + central := fun x y => by + simp_rw [Prod.algebraMap_apply, Algebra.algebraMap_eq_smul_one, smul_apply, one_apply, + mul_smul_comm, smul_mul_assoc] } + map_one' := ext (𝕜 := 𝕜) (A := A) _ _ <| map_one <| algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A)) + map_mul' _ _ := + ext (𝕜 := 𝕜) (A := A) _ _ <| + Prod.ext (map_mul (algebraMap 𝕜 (A →L[𝕜] A)) _ _) + ((map_mul (algebraMap 𝕜 (A →L[𝕜] A)) _ _).trans (Algebra.commutes _ _)) + map_zero' := ext (𝕜 := 𝕜) (A := A) _ _ <| map_zero <| algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A)) + map_add' _ _ := ext (𝕜 := 𝕜) (A := A) _ _ <| + map_add (algebraMap 𝕜 ((A →L[𝕜] A) × (A →L[𝕜] A))) _ _ } commutes' _ _ := ext (𝕜 := 𝕜) (A := A) _ _ <| Prod.ext (Algebra.commutes _ _) (Algebra.commutes _ _).symm smul_def' _ _ := ext (𝕜 := 𝕜) (A := A) _ _ <| diff --git a/Mathlib/Analysis/RCLike/Basic.lean b/Mathlib/Analysis/RCLike/Basic.lean index 38d66627fcf9a..efaf322fb9c49 100644 --- a/Mathlib/Analysis/RCLike/Basic.lean +++ b/Mathlib/Analysis/RCLike/Basic.lean @@ -1115,11 +1115,12 @@ noncomputable def RCLike.copy_of_normedField {𝕜 : Type*} (h : RCLike 𝕜) (h star_add := by subst h''; exact h.star_add -- algebra fields smul := (@Algebra.toSMul _ _ _ (_) (@NormedAlgebra.toAlgebra _ _ _ (_) h.toNormedAlgebra)).smul - toFun := @Algebra.toRingHom _ _ _ (_) (@NormedAlgebra.toAlgebra _ _ _ (_) h.toNormedAlgebra) - map_one' := by subst h''; exact h.map_one' - map_mul' := by subst h''; exact h.map_mul' - map_zero' := by subst h''; exact h.map_zero' - map_add' := by subst h''; exact h.map_add' + algebraMap := + { toFun := @Algebra.algebraMap _ _ _ (_) (@NormedAlgebra.toAlgebra _ _ _ (_) h.toNormedAlgebra) + map_one' := by subst h''; exact h.algebraMap.map_one' + map_mul' := by subst h''; exact h.algebraMap.map_mul' + map_zero' := by subst h''; exact h.algebraMap.map_zero' + map_add' := by subst h''; exact h.algebraMap.map_add' } commutes' := by subst h''; exact h.commutes' smul_def' := by subst h''; exact h.smul_def' norm_smul_le := by subst h''; exact h.norm_smul_le diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean index 94382ab42f817..88327db8743f3 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean @@ -65,20 +65,21 @@ instance Ring_of_Mon_ (A : Mon_ (ModuleCat.{u} R)) : Ring A.X := mul_zero := fun x => show A.mul _ = 0 by rw [TensorProduct.tmul_zero, map_zero] } -instance Algebra_of_Mon_ (A : Mon_ (ModuleCat.{u} R)) : Algebra R A.X := +instance Algebra_of_Mon_ (A : Mon_ (ModuleCat.{u} R)) : Algebra R A.X where + algebraMap := { A.one.hom with map_zero' := A.one.hom.map_zero map_one' := rfl map_mul' := fun x y => by have h := LinearMap.congr_fun (ModuleCat.hom_ext_iff.mp A.one_mul.symm) (x ⊗ₜ A.one y) - rwa [MonoidalCategory.leftUnitor_hom_apply, ← A.one.hom.map_smul] at h - commutes' := fun r a => by - dsimp - have h₁ := LinearMap.congr_fun (ModuleCat.hom_ext_iff.mp A.one_mul) (r ⊗ₜ a) - have h₂ := LinearMap.congr_fun (ModuleCat.hom_ext_iff.mp A.mul_one) (a ⊗ₜ r) - exact h₁.trans h₂.symm - smul_def' := fun r a => - (LinearMap.congr_fun (ModuleCat.hom_ext_iff.mp A.one_mul) (r ⊗ₜ a)).symm } + rwa [MonoidalCategory.leftUnitor_hom_apply, ← A.one.hom.map_smul] at h } + commutes' := fun r a => by + dsimp + have h₁ := LinearMap.congr_fun (ModuleCat.hom_ext_iff.mp A.one_mul) (r ⊗ₜ a) + have h₂ := LinearMap.congr_fun (ModuleCat.hom_ext_iff.mp A.mul_one) (a ⊗ₜ r) + exact h₁.trans h₂.symm + smul_def' := fun r a => + (LinearMap.congr_fun (ModuleCat.hom_ext_iff.mp A.one_mul) (r ⊗ₜ a)).symm @[simp] theorem algebraMap (A : Mon_ (ModuleCat.{u} R)) (r : R) : algebraMap R A.X r = A.one r := diff --git a/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean b/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean index cb22ef58fde04..2ba5461d3a0a6 100644 --- a/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean +++ b/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean @@ -297,24 +297,25 @@ instance moduleRight [Preorder α] [Semiring 𝕜] [AddCommMonoid 𝕝] [Module instance algebraRight [PartialOrder α] [LocallyFiniteOrder α] [DecidableEq α] [CommSemiring 𝕜] [CommSemiring 𝕝] [Algebra 𝕜 𝕝] : Algebra 𝕜 (IncidenceAlgebra 𝕝 α) where - toFun c := algebraMap 𝕜 𝕝 c • (1 : IncidenceAlgebra 𝕝 α) - map_one' := by - ext; simp only [mul_boole, one_apply, Algebra.id.smul_eq_mul, constSMul_apply, map_one] - map_mul' c d := by - ext a b - obtain rfl | h := eq_or_ne a b - · simp only [one_apply, Algebra.id.smul_eq_mul, mul_apply, Algebra.mul_smul_comm, - boole_smul, constSMul_apply, ← ite_and, map_mul, Algebra.smul_mul_assoc, - if_pos rfl, eq_comm, and_self_iff, Icc_self] - simp - · simp only [true_and, ite_self, le_rfl, one_apply, mul_one, Algebra.id.smul_eq_mul, - mul_apply, Algebra.mul_smul_comm, MulZeroClass.zero_mul, constSMul_apply, - ← ite_and, ite_mul, mul_ite, map_mul, mem_Icc, sum_ite_eq, - MulZeroClass.mul_zero, smul_zero, Algebra.smul_mul_assoc, if_pos rfl, if_neg h] - refine (sum_eq_zero fun x _ ↦ ?_).symm - exact if_neg fun hx ↦ h <| hx.2.trans hx.1 - map_zero' := by dsimp; rw [map_zero, zero_smul] - map_add' c d := by dsimp; rw [map_add, add_smul] + algebraMap := + { toFun c := algebraMap 𝕜 𝕝 c • (1 : IncidenceAlgebra 𝕝 α) + map_one' := by + ext; simp only [mul_boole, one_apply, Algebra.id.smul_eq_mul, constSMul_apply, map_one] + map_mul' c d := by + ext a b + obtain rfl | h := eq_or_ne a b + · simp only [one_apply, Algebra.id.smul_eq_mul, mul_apply, Algebra.mul_smul_comm, + boole_smul, constSMul_apply, ← ite_and, map_mul, Algebra.smul_mul_assoc, + if_pos rfl, eq_comm, and_self_iff, Icc_self] + simp + · simp only [true_and, ite_self, le_rfl, one_apply, mul_one, Algebra.id.smul_eq_mul, + mul_apply, Algebra.mul_smul_comm, MulZeroClass.zero_mul, constSMul_apply, + ← ite_and, ite_mul, mul_ite, map_mul, mem_Icc, sum_ite_eq, + MulZeroClass.mul_zero, smul_zero, Algebra.smul_mul_assoc, if_pos rfl, if_neg h] + refine (sum_eq_zero fun x _ ↦ ?_).symm + exact if_neg fun hx ↦ h <| hx.2.trans hx.1 + map_zero' := by dsimp; rw [map_zero, zero_smul] + map_add' c d := by dsimp; rw [map_add, add_smul] } commutes' c f := by classical ext a b hab; simp [if_pos hab, constSMul_apply, mul_comm] smul_def' c f := by classical ext a b hab; simp [if_pos hab, constSMul_apply, Algebra.smul_def] diff --git a/Mathlib/Data/Complex/Module.lean b/Mathlib/Data/Complex/Module.lean index 6f3a26e7e4225..242a2aa0a744b 100644 --- a/Mathlib/Data/Complex/Module.lean +++ b/Mathlib/Data/Complex/Module.lean @@ -92,11 +92,11 @@ instance (priority := 100) instModule [Semiring R] [Module R ℝ] : Module R ℂ zero_smul r := by ext <;> simp [smul_re, smul_im, zero_smul] -- priority manually adjusted in https://github.com/leanprover-community/mathlib4/pull/11980 -instance (priority := 95) instAlgebraOfReal [CommSemiring R] [Algebra R ℝ] : Algebra R ℂ := - { Complex.ofRealHom.comp (algebraMap R ℝ) with - smul := (· • ·) - smul_def' := fun r x => by ext <;> simp [smul_re, smul_im, Algebra.smul_def] - commutes' := fun r ⟨xr, xi⟩ => by ext <;> simp [smul_re, smul_im, Algebra.commutes] } +instance (priority := 95) instAlgebraOfReal [CommSemiring R] [Algebra R ℝ] : Algebra R ℂ where + algebraMap := Complex.ofRealHom.comp (algebraMap R ℝ) + smul := (· • ·) + smul_def' := fun r x => by ext <;> simp [smul_re, smul_im, Algebra.smul_def] + commutes' := fun r ⟨xr, xi⟩ => by ext <;> simp [smul_re, smul_im, Algebra.commutes] instance : StarModule ℝ ℂ := ⟨fun r x => by simp only [star_def, star_trivial, real_smul, map_mul, conj_ofReal]⟩ diff --git a/Mathlib/Data/ENNReal/Operations.lean b/Mathlib/Data/ENNReal/Operations.lean index e97cc16c959c7..ec458ac1544fb 100644 --- a/Mathlib/Data/ENNReal/Operations.lean +++ b/Mathlib/Data/ENNReal/Operations.lean @@ -534,7 +534,7 @@ noncomputable instance {A : Type*} [Semiring A] [Algebra ℝ≥0∞ A] : Algebra smul := (· • ·) commutes' r x := by simp [Algebra.commutes] smul_def' r x := by simp [← Algebra.smul_def (r : ℝ≥0∞) x, smul_def] - toRingHom := (algebraMap ℝ≥0∞ A).comp (ofNNRealHom : ℝ≥0 →+* ℝ≥0∞) + algebraMap := (algebraMap ℝ≥0∞ A).comp (ofNNRealHom : ℝ≥0 →+* ℝ≥0∞) -- verify that the above produces instances we might care about noncomputable example : Algebra ℝ≥0 ℝ≥0∞ := inferInstance diff --git a/Mathlib/Data/Matrix/Basic.lean b/Mathlib/Data/Matrix/Basic.lean index 80fc79d3e62f4..7206292180645 100644 --- a/Mathlib/Data/Matrix/Basic.lean +++ b/Mathlib/Data/Matrix/Basic.lean @@ -215,13 +215,13 @@ variable [Fintype n] [DecidableEq n] variable [CommSemiring R] [Semiring α] [Semiring β] [Algebra R α] [Algebra R β] instance instAlgebra : Algebra R (Matrix n n α) where - toRingHom := (Matrix.scalar n).comp (algebraMap R α) + algebraMap := (Matrix.scalar n).comp (algebraMap R α) commutes' _ _ := scalar_commute _ (fun _ => Algebra.commutes _ _) _ smul_def' r x := by ext; simp [Matrix.scalar, Algebra.smul_def r] theorem algebraMap_matrix_apply {r : R} {i j : n} : algebraMap R (Matrix n n α) r i j = if i = j then algebraMap R α r else 0 := by - dsimp [algebraMap, Algebra.toRingHom, Matrix.scalar] + dsimp [algebraMap, Algebra.algebraMap, Matrix.scalar] split_ifs with h <;> simp [h, Matrix.one_apply_ne] theorem algebraMap_eq_diagonal (r : R) : diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index dbf988eb67926..ba671cb7bf4fd 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -229,7 +229,7 @@ instance {A : Type*} [Semiring A] [Algebra ℝ A] : Algebra ℝ≥0 A where smul := (· • ·) commutes' r x := by simp [Algebra.commutes] smul_def' r x := by simp [← Algebra.smul_def (r : ℝ) x, smul_def] - toRingHom := (algebraMap ℝ A).comp (toRealHom : ℝ≥0 →+* ℝ) + algebraMap := (algebraMap ℝ A).comp (toRealHom : ℝ≥0 →+* ℝ) -- verify that the above produces instances we might care about example : Algebra ℝ≥0 ℝ := by infer_instance diff --git a/Mathlib/FieldTheory/Galois/Basic.lean b/Mathlib/FieldTheory/Galois/Basic.lean index 1213496da816d..e5dd455a5a331 100644 --- a/Mathlib/FieldTheory/Galois/Basic.lean +++ b/Mathlib/FieldTheory/Galois/Basic.lean @@ -226,11 +226,12 @@ instance fixedField.smul : SMul K (fixedField (fixingSubgroup K)) where rw [smul_mul', show ϕ • (x : E) = ↑x from ϕ.2 x, show ϕ • (y : E) = ↑y from y.2 ϕ]⟩ instance fixedField.algebra : Algebra K (fixedField (fixingSubgroup K)) where - toFun x := ⟨x, fun ϕ => Subtype.mem ϕ x⟩ - map_zero' := rfl - map_add' _ _ := rfl - map_one' := rfl - map_mul' _ _ := rfl + algebraMap := + { toFun x := ⟨x, fun ϕ => Subtype.mem ϕ x⟩ + map_zero' := rfl + map_add' _ _ := rfl + map_one' := rfl + map_mul' _ _ := rfl } commutes' _ _ := mul_comm _ _ smul_def' _ _ := rfl diff --git a/Mathlib/FieldTheory/RatFunc/Basic.lean b/Mathlib/FieldTheory/RatFunc/Basic.lean index bac8714ad63cd..348de8a75e63b 100644 --- a/Mathlib/FieldTheory/RatFunc/Basic.lean +++ b/Mathlib/FieldTheory/RatFunc/Basic.lean @@ -495,11 +495,12 @@ section IsDomain variable [IsDomain K] instance (R : Type*) [CommSemiring R] [Algebra R K[X]] : Algebra R (RatFunc K) where - toFun x := RatFunc.mk (algebraMap _ _ x) 1 - map_add' x y := by simp only [mk_one', RingHom.map_add, ofFractionRing_add] - map_mul' x y := by simp only [mk_one', RingHom.map_mul, ofFractionRing_mul] - map_one' := by simp only [mk_one', RingHom.map_one, ofFractionRing_one] - map_zero' := by simp only [mk_one', RingHom.map_zero, ofFractionRing_zero] + algebraMap := + { toFun x := RatFunc.mk (algebraMap _ _ x) 1 + map_add' x y := by simp only [mk_one', RingHom.map_add, ofFractionRing_add] + map_mul' x y := by simp only [mk_one', RingHom.map_mul, ofFractionRing_mul] + map_one' := by simp only [mk_one', RingHom.map_one, ofFractionRing_one] + map_zero' := by simp only [mk_one', RingHom.map_zero, ofFractionRing_zero] } smul := (· • ·) smul_def' c x := by induction' x using RatFunc.induction_on' with p q hq diff --git a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean index 071859f732ad3..ace864e66f99f 100644 --- a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean +++ b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean @@ -282,12 +282,11 @@ def C : 𝕜 →+* C^n⟮I, N; 𝓘(𝕜, A), A⟯ where map_zero' := by ext; exact (algebraMap 𝕜 A).map_zero map_add' c₁ c₂ := by ext; exact (algebraMap 𝕜 A).map_add _ _ -instance algebra : Algebra 𝕜 C^n⟮I, N; 𝓘(𝕜, A), A⟯ := - { --ContMDiffMap.semiring with -- Porting note: Commented this out. - smul := fun r f => ⟨r • f, contMDiff_const.smul f.contMDiff⟩ - toRingHom := ContMDiffMap.C - commutes' := fun c f => by ext x; exact Algebra.commutes' _ _ - smul_def' := fun c f => by ext x; exact Algebra.smul_def' _ _ } +instance algebra : Algebra 𝕜 C^n⟮I, N; 𝓘(𝕜, A), A⟯ where + smul := fun r f => ⟨r • f, contMDiff_const.smul f.contMDiff⟩ + algebraMap := ContMDiffMap.C + commutes' := fun c f => by ext x; exact Algebra.commutes' _ _ + smul_def' := fun c f => by ext x; exact Algebra.smul_def' _ _ /-- Coercion to a function as an `AlgHom`. -/ @[simps] diff --git a/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean b/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean index 70c17ee7b2097..f9ed787b6e7f8 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean @@ -37,7 +37,7 @@ theorem eigenspace_aeval_polynomial_degree_1 (f : End K V) (q : K[X]) (hq : degr rw [leadingCoeff_eq_zero_iff_deg_eq_bot.1 h] at hq cases hq _ = LinearMap.ker (aeval f (C q.leadingCoeff * X + C (q.coeff 0))) := by - rw [C_mul', aeval_def]; simp [algebraMap, Algebra.toRingHom] + rw [C_mul', aeval_def]; simp [algebraMap, Algebra.algebraMap] _ = LinearMap.ker (aeval f q) := by rwa [← eq_X_add_C_of_degree_eq_one] theorem ker_aeval_ring_hom'_unit_polynomial (f : End K V) (c : K[X]ˣ) : diff --git a/Mathlib/LinearAlgebra/Matrix/Reindex.lean b/Mathlib/LinearAlgebra/Matrix/Reindex.lean index aa9a280fecf7a..4228eb7ef46ae 100644 --- a/Mathlib/LinearAlgebra/Matrix/Reindex.lean +++ b/Mathlib/LinearAlgebra/Matrix/Reindex.lean @@ -113,7 +113,7 @@ def reindexAlgEquiv (e : m ≃ n) : Matrix m m A ≃ₐ[R] Matrix n n A := toFun := reindex e e map_mul' := fun a b => (reindexLinearEquiv_mul A A e e e a b).symm -- Porting note: `submatrix_smul` needed help - commutes' := fun r => by simp [algebraMap, Algebra.toRingHom, submatrix_smul _ 1] } + commutes' := fun r => by simp [algebraMap, Algebra.algebraMap, submatrix_smul _ 1] } @[simp] theorem reindexAlgEquiv_apply (e : m ≃ n) (M : Matrix m m A) : diff --git a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean index 5c48e5305772b..6a6d8eca87ae3 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean @@ -242,7 +242,7 @@ def includeLeftRingHom : A →+* 𝒜 ᵍ⊗[R] ℬ where SetLike.coe_gOne, one_mul] instance instAlgebra : Algebra R (𝒜 ᵍ⊗[R] ℬ) where - toRingHom := (includeLeftRingHom 𝒜 ℬ).comp (algebraMap R A) + algebraMap := (includeLeftRingHom 𝒜 ℬ).comp (algebraMap R A) commutes' r x := by dsimp [mul_def, mulHom_apply, auxEquiv_tmul] simp_rw [DirectSum.decompose_algebraMap, DirectSum.decompose_one, algebraMap_gradedMul, diff --git a/Mathlib/RingTheory/AdicCompletion/Algebra.lean b/Mathlib/RingTheory/AdicCompletion/Algebra.lean index 9c8babe6957b6..88851779d0e30 100644 --- a/Mathlib/RingTheory/AdicCompletion/Algebra.lean +++ b/Mathlib/RingTheory/AdicCompletion/Algebra.lean @@ -88,13 +88,14 @@ instance : CommRing (AdicCompletion I R) := (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) instance [Algebra S R] : Algebra S (AdicCompletion I R) where - toFun r := ⟨algebraMap S (∀ n, R ⧸ (I ^ n • ⊤ : Ideal R)) r, by - simp [-Ideal.Quotient.mk_algebraMap, - IsScalarTower.algebraMap_apply S R (R ⧸ (I ^ _ • ⊤ : Ideal R))]⟩ - map_one' := Subtype.ext <| map_one _ - map_mul' x y := Subtype.ext <| map_mul _ x y - map_zero' := Subtype.ext <| map_zero _ - map_add' x y := Subtype.ext <| map_add _ x y + algebraMap := + { toFun r := ⟨algebraMap S (∀ n, R ⧸ (I ^ n • ⊤ : Ideal R)) r, by + simp [-Ideal.Quotient.mk_algebraMap, + IsScalarTower.algebraMap_apply S R (R ⧸ (I ^ _ • ⊤ : Ideal R))]⟩ + map_one' := Subtype.ext <| map_one _ + map_mul' x y := Subtype.ext <| map_mul _ x y + map_zero' := Subtype.ext <| map_zero _ + map_add' x y := Subtype.ext <| map_add _ x y } commutes' r x := Subtype.ext <| Algebra.commutes' r x.val smul_def' r x := Subtype.ext <| Algebra.smul_def' r x.val @@ -155,11 +156,12 @@ instance : CommRing (AdicCauchySequence I R) := (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) instance : Algebra R (AdicCauchySequence I R) where - toFun r := ⟨algebraMap R (∀ _, R) r, fun _ ↦ rfl⟩ - map_one' := Subtype.ext <| map_one _ - map_mul' x y := Subtype.ext <| map_mul _ x y - map_zero' := Subtype.ext <| map_zero _ - map_add' x y := Subtype.ext <| map_add _ x y + algebraMap := + { toFun r := ⟨algebraMap R (∀ _, R) r, fun _ ↦ rfl⟩ + map_one' := Subtype.ext <| map_one _ + map_mul' x y := Subtype.ext <| map_mul _ x y + map_zero' := Subtype.ext <| map_zero _ + map_add' x y := Subtype.ext <| map_add _ x y } commutes' r x := Subtype.ext <| Algebra.commutes' r x.val smul_def' r x := Subtype.ext <| Algebra.smul_def' r x.val diff --git a/Mathlib/RingTheory/Algebraic/Pi.lean b/Mathlib/RingTheory/Algebraic/Pi.lean index 9c96ad3c87c64..5c51f5f6b3f3a 100644 --- a/Mathlib/RingTheory/Algebraic/Pi.lean +++ b/Mathlib/RingTheory/Algebraic/Pi.lean @@ -49,9 +49,10 @@ variable [CommSemiring R] [CommSemiring S] [CommSemiring T] [Algebra R S] [Algeb -- Porting note: the proofs in this definition used `funext` in term-mode, but I was not able -- to get them to work anymore. /-- This is not an instance for the same reasons as `Polynomial.hasSMulPi'`. -/ -noncomputable def Polynomial.algebraPi : Algebra R[X] (S → T) := - { Polynomial.hasSMulPi' R S T with - toFun := fun p z => algebraMap S T (aeval z p) +noncomputable def Polynomial.algebraPi : Algebra R[X] (S → T) where + __ := Polynomial.hasSMulPi' R S T + algebraMap := + { toFun := fun p z => algebraMap S T (aeval z p) map_one' := by funext z simp only [Polynomial.aeval_one, Pi.one_apply, map_one] @@ -63,14 +64,14 @@ noncomputable def Polynomial.algebraPi : Algebra R[X] (S → T) := simp only [Polynomial.aeval_zero, Pi.zero_apply, map_zero] map_add' := fun f g => by funext z - simp only [Polynomial.aeval_add, Pi.add_apply, map_add] - commutes' := fun p f => by - funext z - exact mul_comm _ _ - smul_def' := fun p f => by - funext z - simp only [polynomial_smul_apply', Algebra.algebraMap_eq_smul_one, RingHom.coe_mk, - MonoidHom.coe_mk, OneHom.coe_mk, Pi.mul_apply, Algebra.smul_mul_assoc, one_mul] } + simp only [Polynomial.aeval_add, Pi.add_apply, map_add] } + commutes' := fun p f => by + funext z + exact mul_comm _ _ + smul_def' := fun p f => by + funext z + simp only [polynomial_smul_apply', Algebra.algebraMap_eq_smul_one, RingHom.coe_mk, + MonoidHom.coe_mk, OneHom.coe_mk, Pi.mul_apply, Algebra.smul_mul_assoc, one_mul] attribute [local instance] Polynomial.algebraPi diff --git a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean index 36a3b9f561a35..82020896c6613 100644 --- a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean +++ b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean @@ -486,18 +486,19 @@ instance : Algebra R (v.adicCompletionIntegers K) where letI : Valued K ℤₘ₀ := adicValued v rw [mem_adicCompletionIntegers, h, Valued.valuedCompletion_apply] exact v.valuation_le_one _⟩ - toFun r := - ⟨(algebraMap R K r : adicCompletion K v), by - simpa only [mem_adicCompletionIntegers, Valued.valuedCompletion_apply] using - v.valuation_le_one _⟩ - map_one' := by simp only [map_one]; rfl - map_mul' x y := by - ext - simp only [map_mul, UniformSpace.Completion.coe_mul, MulMemClass.mk_mul_mk] - map_zero' := by simp only [map_zero]; rfl - map_add' x y := by - ext - simp only [map_add, UniformSpace.Completion.coe_add, AddMemClass.mk_add_mk] + algebraMap := + { toFun r := + ⟨(algebraMap R K r : adicCompletion K v), by + simpa only [mem_adicCompletionIntegers, Valued.valuedCompletion_apply] using + v.valuation_le_one _⟩ + map_one' := by simp only [map_one]; rfl + map_mul' x y := by + ext + simp only [map_mul, UniformSpace.Completion.coe_mul, MulMemClass.mk_mul_mk] + map_zero' := by simp only [map_zero]; rfl + map_add' x y := by + ext + simp only [map_add, UniformSpace.Completion.coe_add, AddMemClass.mk_add_mk] } commutes' r x := by rw [mul_comm] smul_def' r x := by diff --git a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean index d1ef588be6784..430f40de7ae58 100644 --- a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean +++ b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean @@ -367,11 +367,12 @@ instance : Algebra (R_hat R K) (FiniteAdeleRing R K) where simp only [mem_adicCompletionIntegers, mem_compl_iff, mem_setOf_eq, map_mul] at hv ⊢ exact mt (mul_le_one' (rhat v).2) hv ⟩ - toFun r := ⟨r, by simp_all⟩ - map_one' := by ext; rfl - map_mul' _ _ := by ext; rfl - map_zero' := by ext; rfl - map_add' _ _ := by ext; rfl + algebraMap := + { toFun r := ⟨r, by simp_all⟩ + map_one' := by ext; rfl + map_mul' _ _ := by ext; rfl + map_zero' := by ext; rfl + map_add' _ _ := by ext; rfl } commutes' _ _ := mul_comm _ _ smul_def' _ _ := rfl diff --git a/Mathlib/RingTheory/Extension.lean b/Mathlib/RingTheory/Extension.lean index 47c439fb59c7b..649d094f87f48 100644 --- a/Mathlib/RingTheory/Extension.lean +++ b/Mathlib/RingTheory/Extension.lean @@ -64,7 +64,7 @@ attribute [simp] algebraMap_σ noncomputable instance {R₀} [CommRing R₀] [Algebra R₀ R] [Algebra R₀ S] [IsScalarTower R₀ R S] : Algebra R₀ P.Ring where __ := Module.compHom P.Ring (algebraMap R₀ R) - __ := (algebraMap R P.Ring).comp (algebraMap R₀ R) + algebraMap := (algebraMap R P.Ring).comp (algebraMap R₀ R) smul_def' _ _ := smul_def _ _ commutes' _ _ := commutes _ _ diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean index d07c60a4fa0bb..d3a7fc8a87136 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean @@ -446,11 +446,12 @@ instance homogeneousLocalizationCommRing : CommRing (HomogeneousLocalization instance homogeneousLocalizationAlgebra : Algebra (HomogeneousLocalization 𝒜 x) (Localization x) where smul p q := p.val * q - toFun := val - map_one' := val_one - map_mul' := val_mul - map_zero' := val_zero - map_add' := val_add + algebraMap := + { toFun := val + map_one' := val_one + map_mul' := val_mul + map_zero' := val_zero + map_add' := val_add } commutes' _ _ := mul_comm _ _ smul_def' _ _ := rfl diff --git a/Mathlib/RingTheory/HahnSeries/Multiplication.lean b/Mathlib/RingTheory/HahnSeries/Multiplication.lean index 8660ddb736c28..21bb4bf80b1df 100644 --- a/Mathlib/RingTheory/HahnSeries/Multiplication.lean +++ b/Mathlib/RingTheory/HahnSeries/Multiplication.lean @@ -756,7 +756,7 @@ section Algebra variable [CommSemiring R] {A : Type*} [Semiring A] [Algebra R A] instance : Algebra R (HahnSeries Γ A) where - toRingHom := C.comp (algebraMap R A) + algebraMap := C.comp (algebraMap R A) smul_def' r x := by ext simp diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index 9f3fae484fa06..ee0467668b791 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -1216,12 +1216,13 @@ open Submodule instance algebraIdeal : Algebra (Ideal R) (Submodule R A) where __ := moduleSubmodule - toFun := map (Algebra.linearMap R A) - map_one' := by - rw [one_eq_span, map_span, Set.image_singleton, Algebra.linearMap_apply, map_one, one_eq_span] - map_mul' := (Submodule.map_mul · · <| Algebra.ofId R A) - map_zero' := map_bot _ - map_add' := (map_sup · · _) + algebraMap := + { toFun := map (Algebra.linearMap R A) + map_one' := by + rw [one_eq_span, map_span, Set.image_singleton, Algebra.linearMap_apply, map_one, one_eq_span] + map_mul' := (Submodule.map_mul · · <| Algebra.ofId R A) + map_zero' := map_bot _ + map_add' := (map_sup · · _) } commutes' I M := mul_comm_of_commute <| by rintro _ ⟨r, _, rfl⟩ a _; apply Algebra.commutes smul_def' I M := le_antisymm (smul_le.mpr fun r hr a ha ↦ by rw [Algebra.smul_def]; exact Submodule.mul_mem_mul ⟨r, hr, rfl⟩ ha) (Submodule.mul_le.mpr <| by diff --git a/Mathlib/RingTheory/Ideal/Quotient/Operations.lean b/Mathlib/RingTheory/Ideal/Quotient/Operations.lean index 81c079b7988ec..a71d12054e32b 100644 --- a/Mathlib/RingTheory/Ideal/Quotient/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Quotient/Operations.lean @@ -325,12 +325,12 @@ variable [CommSemiring R₁] [CommSemiring R₂] [CommRing A] variable [Algebra R₁ A] [Algebra R₂ A] /-- The `R₁`-algebra structure on `A/I` for an `R₁`-algebra `A` -/ -instance Quotient.algebra {I : Ideal A} : Algebra R₁ (A ⧸ I) := - { toRingHom := (Ideal.Quotient.mk I).comp (algebraMap R₁ A) - smul_def' := fun _ x => - Quotient.inductionOn' x fun _ => - ((Quotient.mk I).congr_arg <| Algebra.smul_def _ _).trans (RingHom.map_mul _ _ _) - commutes' := fun _ _ => mul_comm _ _ } +instance Quotient.algebra {I : Ideal A} : Algebra R₁ (A ⧸ I) where + algebraMap := (Ideal.Quotient.mk I).comp (algebraMap R₁ A) + smul_def' := fun _ x => + Quotient.inductionOn' x fun _ => + ((Quotient.mk I).congr_arg <| Algebra.smul_def _ _).trans (RingHom.map_mul _ _ _) + commutes' := fun _ _ => mul_comm _ _ -- Lean can struggle to find this instance later if we don't provide this shortcut -- Porting note: this can probably now be deleted @@ -588,7 +588,7 @@ end /-- If `P` lies over `p`, then `R / p` has a canonical map to `A / P`. -/ abbrev Quotient.algebraQuotientOfLEComap [Algebra R A] {p : Ideal R} {P : Ideal A} (h : p ≤ comap (algebraMap R A) P) : Algebra (R ⧸ p) (A ⧸ P) where - toRingHom := quotientMap P (algebraMap R A) h + algebraMap := quotientMap P (algebraMap R A) h smul := Quotient.lift₂ (⟦· • ·⟧) fun r₁ a₁ r₂ a₂ hr ha ↦ Quotient.sound <| by have := h (p.quotientRel_def.mp hr) rw [mem_comap, map_sub] at this diff --git a/Mathlib/RingTheory/MvPowerSeries/Basic.lean b/Mathlib/RingTheory/MvPowerSeries/Basic.lean index 1a27f73a40bef..f42900e728554 100644 --- a/Mathlib/RingTheory/MvPowerSeries/Basic.lean +++ b/Mathlib/RingTheory/MvPowerSeries/Basic.lean @@ -713,16 +713,14 @@ section Algebra variable {A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] -instance : Algebra R (MvPowerSeries σ A) := - { - show Module R (MvPowerSeries σ A) by infer_instance with - commutes' := fun a φ => by - ext n - simp [Algebra.commutes] - smul_def' := fun a σ => by - ext n - simp [(coeff A n).map_smul_of_tower a, Algebra.smul_def] - toRingHom := (MvPowerSeries.map σ (algebraMap R A)).comp (C σ R) } +instance : Algebra R (MvPowerSeries σ A) where + algebraMap := (MvPowerSeries.map σ (algebraMap R A)).comp (C σ R) + commutes' := fun a φ => by + ext n + simp [Algebra.commutes] + smul_def' := fun a σ => by + ext n + simp [(coeff A n).map_smul_of_tower a, Algebra.smul_def] theorem c_eq_algebraMap : C σ R = algebraMap R (MvPowerSeries σ R) := rfl diff --git a/Mathlib/RingTheory/OreLocalization/Ring.lean b/Mathlib/RingTheory/OreLocalization/Ring.lean index d76032bfbc512..0fc4afe522d4e 100644 --- a/Mathlib/RingTheory/OreLocalization/Ring.lean +++ b/Mathlib/RingTheory/OreLocalization/Ring.lean @@ -114,7 +114,7 @@ def numeratorRingHom : R →+* R[S⁻¹] where instance {R₀} [CommSemiring R₀] [Algebra R₀ R] : Algebra R₀ R[S⁻¹] where __ := inferInstanceAs (Module R₀ R[S⁻¹]) - __ := numeratorRingHom.comp (algebraMap R₀ R) + algebraMap := numeratorRingHom.comp (algebraMap R₀ R) commutes' r x := by induction' x using OreLocalization.ind with r₁ s₁ dsimp diff --git a/Mathlib/RingTheory/PiTensorProduct.lean b/Mathlib/RingTheory/PiTensorProduct.lean index 26d7db3188d1e..3563e432cceda 100644 --- a/Mathlib/RingTheory/PiTensorProduct.lean +++ b/Mathlib/RingTheory/PiTensorProduct.lean @@ -149,16 +149,17 @@ instance instSemiring : Semiring (⨂[R] i, A i) where instance instAlgebra : Algebra R' (⨂[R] i, A i) where __ := hasSMul' - toFun := (· • 1) - map_one' := by simp - map_mul' r s := show (r * s) • 1 = mul (r • 1) (s • 1) by - rw [LinearMap.map_smul_of_tower, LinearMap.map_smul_of_tower, LinearMap.smul_apply, mul_comm, - mul_smul] - congr - show (1 : ⨂[R] i, A i) = 1 * 1 - rw [mul_one] - map_zero' := by simp - map_add' := by simp [add_smul] + algebraMap := + { toFun := (· • 1) + map_one' := by simp + map_mul' r s := show (r * s) • 1 = mul (r • 1) (s • 1) by + rw [LinearMap.map_smul_of_tower, LinearMap.map_smul_of_tower, LinearMap.smul_apply, mul_comm, + mul_smul] + congr + show (1 : ⨂[R] i, A i) = 1 * 1 + rw [mul_one] + map_zero' := by simp + map_add' := by simp [add_smul] } commutes' r x := by simp only [RingHom.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk] change mul _ _ = mul _ _ diff --git a/Mathlib/RingTheory/TensorProduct/Basic.lean b/Mathlib/RingTheory/TensorProduct/Basic.lean index 7eeec368f0ac8..010c0ec9677b1 100644 --- a/Mathlib/RingTheory/TensorProduct/Basic.lean +++ b/Mathlib/RingTheory/TensorProduct/Basic.lean @@ -403,7 +403,7 @@ instance leftAlgebra [SMulCommClass R S A] : Algebra S (A ⊗[R] B) := smul_def' := fun r x => by dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply, includeLeftRingHom_apply] rw [algebraMap_eq_smul_one, ← smul_tmul', smul_mul_assoc, ← one_def, one_mul] - toRingHom := TensorProduct.includeLeftRingHom.comp (algebraMap S A) } + algebraMap := TensorProduct.includeLeftRingHom.comp (algebraMap S A) } example : (Semiring.toNatAlgebra : Algebra ℕ (ℕ ⊗[ℕ] B)) = leftAlgebra := rfl diff --git a/Mathlib/RingTheory/Valuation/ValExtension.lean b/Mathlib/RingTheory/Valuation/ValExtension.lean index 77ca147605411..61deb1c53bb99 100644 --- a/Mathlib/RingTheory/Valuation/ValExtension.lean +++ b/Mathlib/RingTheory/Valuation/ValExtension.lean @@ -112,7 +112,7 @@ theorem ofComapInteger (h : vA.integer.comap (algebraMap K A) = vK.integer) : instance instAlgebraInteger : Algebra vR.integer vA.integer where smul r a := ⟨r • a, Algebra.smul_def r (a : A) ▸ mul_mem ((val_map_le_one_iff vR vA _).mpr r.2) a.2⟩ - __ := (algebraMap R A).restrict vR.integer vA.integer + algebraMap := (algebraMap R A).restrict vR.integer vA.integer (by simp [Valuation.mem_integer_iff, val_map_le_one_iff vR vA]) commutes' _ _ := Subtype.ext (Algebra.commutes _ _) smul_def' _ _ := Subtype.ext (Algebra.smul_def _ _) diff --git a/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean b/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean index 536e68588f287..8cdb9ff16ff5c 100644 --- a/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean +++ b/Mathlib/Topology/Algebra/SeparationQuotient/Basic.lean @@ -386,7 +386,7 @@ variable {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] [TopologicalSpace A] [TopologicalSemiring A] [ContinuousConstSMul R A] instance instAlgebra : Algebra R (SeparationQuotient A) where - toRingHom := mkRingHom.comp (algebraMap R A) + algebraMap := mkRingHom.comp (algebraMap R A) commutes' r := Quotient.ind fun a => congrArg _ <| Algebra.commutes r a smul_def' r := Quotient.ind fun a => congrArg _ <| Algebra.smul_def r a diff --git a/Mathlib/Topology/Algebra/UniformRing.lean b/Mathlib/Topology/Algebra/UniformRing.lean index 5453277e0629f..fcc14122d8f6e 100644 --- a/Mathlib/Topology/Algebra/UniformRing.lean +++ b/Mathlib/Topology/Algebra/UniformRing.lean @@ -191,13 +191,13 @@ theorem map_smul_eq_mul_coe (r : R) : · exact isClosed_eq Completion.continuous_map (continuous_mul_left _) · simp_rw [map_coe (uniformContinuous_const_smul r) a, Algebra.smul_def, coe_mul] -instance algebra : Algebra R (Completion A) := - { (UniformSpace.Completion.coeRingHom : A →+* Completion A).comp (algebraMap R A) with - commutes' := fun r x => - Completion.induction_on x (isClosed_eq (continuous_mul_left _) (continuous_mul_right _)) - fun a => by - simpa only [coe_mul] using congr_arg ((↑) : A → Completion A) (Algebra.commutes r a) - smul_def' := fun r x => congr_fun (map_smul_eq_mul_coe A R r) x } +instance algebra : Algebra R (Completion A) where + algebraMap := (UniformSpace.Completion.coeRingHom : A →+* Completion A).comp (algebraMap R A) + commutes' := fun r x => + Completion.induction_on x (isClosed_eq (continuous_mul_left _) (continuous_mul_right _)) + fun a => by + simpa only [coe_mul] using congr_arg ((↑) : A → Completion A) (Algebra.commutes r a) + smul_def' := fun r x => congr_fun (map_smul_eq_mul_coe A R r) x theorem algebraMap_def (r : R) : algebraMap R (Completion A) r = (algebraMap R A r : Completion A) := diff --git a/Mathlib/Topology/ContinuousMap/Algebra.lean b/Mathlib/Topology/ContinuousMap/Algebra.lean index 5d745326a17a6..7d5a552739ded 100644 --- a/Mathlib/Topology/ContinuousMap/Algebra.lean +++ b/Mathlib/Topology/ContinuousMap/Algebra.lean @@ -670,7 +670,7 @@ theorem ContinuousMap.C_apply (r : R) (a : α) : ContinuousMap.C r a = algebraMa rfl instance ContinuousMap.algebra : Algebra R C(α, A) where - toRingHom := ContinuousMap.C + algebraMap := ContinuousMap.C commutes' c f := by ext x; exact Algebra.commutes' _ _ smul_def' c f := by ext x; exact Algebra.smul_def' _ _ diff --git a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean index 6a26326badb7b..d64c5cd7bdaa8 100644 --- a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean +++ b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean @@ -1318,7 +1318,7 @@ def C : 𝕜 →+* α →ᵇ γ where map_add' _ _ := ext fun _ => (algebraMap 𝕜 γ).map_add _ _ instance instAlgebra : Algebra 𝕜 (α →ᵇ γ) where - toRingHom := C + algebraMap := C commutes' _ _ := ext fun _ ↦ Algebra.commutes' _ _ smul_def' _ _ := ext fun _ ↦ Algebra.smul_def' _ _ diff --git a/Mathlib/Topology/LocallyConstant/Algebra.lean b/Mathlib/Topology/LocallyConstant/Algebra.lean index 986f83f29a8ac..34bc5a7d06151 100644 --- a/Mathlib/Topology/LocallyConstant/Algebra.lean +++ b/Mathlib/Topology/LocallyConstant/Algebra.lean @@ -247,7 +247,7 @@ section Algebra variable [CommSemiring R] [Semiring Y] [Algebra R Y] instance : Algebra R (LocallyConstant X Y) where - toRingHom := constRingHom.comp <| algebraMap R Y + algebraMap := constRingHom.comp <| algebraMap R Y commutes' := by intros ext From 71b88c46b98fce8a3f531102e0da56784da50dea Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 13 Jan 2025 13:56:40 +0000 Subject: [PATCH 198/681] chore(Data/Finsupp): split off material on `single`, `update`, `erase` (#19087) To clean up `Mathlib.Algebra.MonoidAlgebra.Defs` I would like to move material on `single` from `Mathlib.Data.Finsupp.Basic` into a smaller file. Although the specific lemmas could go into `Mathlib.Data.Finsupp.Defs`, that file is already rather big, so instead let's split off a file that sits in between `Defs` and `Basic`. --- Mathlib.lean | 1 + Mathlib/Data/Finsupp/Basic.lean | 16 - Mathlib/Data/Finsupp/Defs.lean | 624 ---------------------- Mathlib/Data/Finsupp/Ext.lean | 2 +- Mathlib/Data/Finsupp/Fin.lean | 2 +- Mathlib/Data/Finsupp/Fintype.lean | 2 +- Mathlib/Data/Finsupp/Indicator.lean | 2 +- Mathlib/Data/Finsupp/Notation.lean | 2 +- Mathlib/Data/Finsupp/Pointwise.lean | 2 +- Mathlib/Data/Finsupp/SMulWithZero.lean | 2 +- Mathlib/Data/Finsupp/Single.lean | 711 +++++++++++++++++++++++++ Mathlib/Data/List/ToFinsupp.lean | 2 +- scripts/noshake.json | 1 + 13 files changed, 721 insertions(+), 648 deletions(-) create mode 100644 Mathlib/Data/Finsupp/Single.lean diff --git a/Mathlib.lean b/Mathlib.lean index 64075586bf269..2c579f231ed42 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2583,6 +2583,7 @@ import Mathlib.Data.Finsupp.Order import Mathlib.Data.Finsupp.PWO import Mathlib.Data.Finsupp.Pointwise import Mathlib.Data.Finsupp.SMulWithZero +import Mathlib.Data.Finsupp.Single import Mathlib.Data.Finsupp.ToDFinsupp import Mathlib.Data.Finsupp.Weight import Mathlib.Data.Finsupp.WellFounded diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index 675105181e1fc..d7cfe97aeea59 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -997,22 +997,6 @@ theorem subtypeDomain_neg : (-v).subtypeDomain p = -v.subtypeDomain p := theorem subtypeDomain_sub : (v - v').subtypeDomain p = v.subtypeDomain p - v'.subtypeDomain p := ext fun _ => rfl -@[simp] -theorem single_neg (a : α) (b : G) : single a (-b) = -single a b := - (singleAddHom a : G →+ _).map_neg b - -@[simp] -theorem single_sub (a : α) (b₁ b₂ : G) : single a (b₁ - b₂) = single a b₁ - single a b₂ := - (singleAddHom a : G →+ _).map_sub b₁ b₂ - -@[simp] -theorem erase_neg (a : α) (f : α →₀ G) : erase a (-f) = -erase a f := - (eraseAddHom a : (_ →₀ G) →+ _).map_neg f - -@[simp] -theorem erase_sub (a : α) (f₁ f₂ : α →₀ G) : erase a (f₁ - f₂) = erase a f₁ - erase a f₂ := - (eraseAddHom a : (_ →₀ G) →+ _).map_sub f₁ f₂ - @[simp] theorem filter_neg (p : α → Prop) [DecidablePred p] (f : α →₀ G) : filter p (-f) = -filter p f := (filterAddHom p : (_ →₀ G) →+ _).map_neg f diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index d3ab7840c2b6f..56eb68dc8f217 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.Group.Indicator -import Mathlib.Data.Finset.Max import Mathlib.Data.Set.Finite.Basic /-! @@ -43,9 +42,6 @@ non-pointwise multiplication. ## Main declarations * `Finsupp`: The type of finitely supported functions from `α` to `β`. -* `Finsupp.single`: The `Finsupp` which is nonzero in exactly one point. -* `Finsupp.update`: Changes one value of a `Finsupp`. -* `Finsupp.erase`: Replaces one value of a `Finsupp` by `0`. * `Finsupp.onFinset`: The restriction of a function to a `Finset` as a `Finsupp`. * `Finsupp.mapRange`: Composition of a `ZeroHom` with a `Finsupp`. * `Finsupp.embDomain`: Maps the domain of a `Finsupp` by an embedding. @@ -213,406 +209,6 @@ theorem unique_ext [Unique α] {f g : α →₀ M} (h : f default = g default) : end Basic -/-! ### Declarations about `single` -/ - - -section Single - -variable [Zero M] {a a' : α} {b : M} - -/-- `single a b` is the finitely supported function with value `b` at `a` and zero otherwise. -/ -def single (a : α) (b : M) : α →₀ M where - support := - haveI := Classical.decEq M - if b = 0 then ∅ else {a} - toFun := - haveI := Classical.decEq α - Pi.single a b - mem_support_toFun a' := by - classical - obtain rfl | hb := eq_or_ne b 0 - · simp [Pi.single, update] - rw [if_neg hb, mem_singleton] - obtain rfl | ha := eq_or_ne a' a - · simp [hb, Pi.single, update] - simp [Pi.single_eq_of_ne' ha.symm, ha] - -theorem single_apply [Decidable (a = a')] : single a b a' = if a = a' then b else 0 := by - classical - simp_rw [@eq_comm _ a a'] - convert Pi.single_apply a b a' - -theorem single_apply_left {f : α → β} (hf : Function.Injective f) (x z : α) (y : M) : - single (f x) y (f z) = single x y z := by classical simp only [single_apply, hf.eq_iff] - -theorem single_eq_set_indicator : ⇑(single a b) = Set.indicator {a} fun _ => b := by - classical - ext - simp [single_apply, Set.indicator, @eq_comm _ a] - -@[simp] -theorem single_eq_same : (single a b : α →₀ M) a = b := by - classical exact Pi.single_eq_same (f := fun _ ↦ M) a b - -@[simp] -theorem single_eq_of_ne (h : a ≠ a') : (single a b : α →₀ M) a' = 0 := by - classical exact Pi.single_eq_of_ne' h _ - -theorem single_eq_update [DecidableEq α] (a : α) (b : M) : - ⇑(single a b) = Function.update (0 : _) a b := by - classical rw [single_eq_set_indicator, ← Set.piecewise_eq_indicator, Set.piecewise_singleton] - -theorem single_eq_pi_single [DecidableEq α] (a : α) (b : M) : ⇑(single a b) = Pi.single a b := - single_eq_update a b - -@[simp] -theorem single_zero (a : α) : (single a 0 : α →₀ M) = 0 := - DFunLike.coe_injective <| by - classical simpa only [single_eq_update, coe_zero] using Function.update_eq_self a (0 : α → M) - -theorem single_of_single_apply (a a' : α) (b : M) : - single a ((single a' b) a) = single a' (single a' b) a := by - classical - rw [single_apply, single_apply] - ext - split_ifs with h - · rw [h] - · rw [zero_apply, single_apply, ite_self] - -theorem support_single_ne_zero (a : α) (hb : b ≠ 0) : (single a b).support = {a} := - if_neg hb - -theorem support_single_subset : (single a b).support ⊆ {a} := by - classical show ite _ _ _ ⊆ _; split_ifs <;> [exact empty_subset _; exact Subset.refl _] - -theorem single_apply_mem (x) : single a b x ∈ ({0, b} : Set M) := by - rcases em (a = x) with (rfl | hx) <;> [simp; simp [single_eq_of_ne hx]] - -theorem range_single_subset : Set.range (single a b) ⊆ {0, b} := - Set.range_subset_iff.2 single_apply_mem - -/-- `Finsupp.single a b` is injective in `b`. For the statement that it is injective in `a`, see -`Finsupp.single_left_injective` -/ -theorem single_injective (a : α) : Function.Injective (single a : M → α →₀ M) := fun b₁ b₂ eq => by - have : (single a b₁ : α →₀ M) a = (single a b₂ : α →₀ M) a := by rw [eq] - rwa [single_eq_same, single_eq_same] at this - -theorem single_apply_eq_zero {a x : α} {b : M} : single a b x = 0 ↔ x = a → b = 0 := by - simp [single_eq_set_indicator] - -theorem single_apply_ne_zero {a x : α} {b : M} : single a b x ≠ 0 ↔ x = a ∧ b ≠ 0 := by - simp [single_apply_eq_zero] - -theorem mem_support_single (a a' : α) (b : M) : a ∈ (single a' b).support ↔ a = a' ∧ b ≠ 0 := by - simp [single_apply_eq_zero, not_or] - -theorem eq_single_iff {f : α →₀ M} {a b} : f = single a b ↔ f.support ⊆ {a} ∧ f a = b := by - refine ⟨fun h => h.symm ▸ ⟨support_single_subset, single_eq_same⟩, ?_⟩ - rintro ⟨h, rfl⟩ - ext x - by_cases hx : a = x <;> simp only [hx, single_eq_same, single_eq_of_ne, Ne, not_false_iff] - exact not_mem_support_iff.1 (mt (fun hx => (mem_singleton.1 (h hx)).symm) hx) - -theorem single_eq_single_iff (a₁ a₂ : α) (b₁ b₂ : M) : - single a₁ b₁ = single a₂ b₂ ↔ a₁ = a₂ ∧ b₁ = b₂ ∨ b₁ = 0 ∧ b₂ = 0 := by - constructor - · intro eq - by_cases h : a₁ = a₂ - · refine Or.inl ⟨h, ?_⟩ - rwa [h, (single_injective a₂).eq_iff] at eq - · rw [DFunLike.ext_iff] at eq - have h₁ := eq a₁ - have h₂ := eq a₂ - simp only [single_eq_same, single_eq_of_ne h, single_eq_of_ne (Ne.symm h)] at h₁ h₂ - exact Or.inr ⟨h₁, h₂.symm⟩ - · rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) - · rfl - · rw [single_zero, single_zero] - -/-- `Finsupp.single a b` is injective in `a`. For the statement that it is injective in `b`, see -`Finsupp.single_injective` -/ -theorem single_left_injective (h : b ≠ 0) : Function.Injective fun a : α => single a b := - fun _a _a' H => (((single_eq_single_iff _ _ _ _).mp H).resolve_right fun hb => h hb.1).left - -theorem single_left_inj (h : b ≠ 0) : single a b = single a' b ↔ a = a' := - (single_left_injective h).eq_iff - -theorem support_single_ne_bot (i : α) (h : b ≠ 0) : (single i b).support ≠ ⊥ := by - simpa only [support_single_ne_zero _ h] using singleton_ne_empty _ - -theorem support_single_disjoint {b' : M} (hb : b ≠ 0) (hb' : b' ≠ 0) {i j : α} : - Disjoint (single i b).support (single j b').support ↔ i ≠ j := by - rw [support_single_ne_zero _ hb, support_single_ne_zero _ hb', disjoint_singleton] - -@[simp] -theorem single_eq_zero : single a b = 0 ↔ b = 0 := by - simp [DFunLike.ext_iff, single_eq_set_indicator] - -theorem single_swap (a₁ a₂ : α) (b : M) : single a₁ b a₂ = single a₂ b a₁ := by - classical simp only [single_apply, eq_comm] - -instance instNontrivial [Nonempty α] [Nontrivial M] : Nontrivial (α →₀ M) := by - inhabit α - rcases exists_ne (0 : M) with ⟨x, hx⟩ - exact nontrivial_of_ne (single default x) 0 (mt single_eq_zero.1 hx) - -theorem unique_single [Unique α] (x : α →₀ M) : x = single default (x default) := - ext <| Unique.forall_iff.2 single_eq_same.symm - -@[simp] -theorem unique_single_eq_iff [Unique α] {b' : M} : single a b = single a' b' ↔ b = b' := by - rw [Finsupp.unique_ext_iff, Unique.eq_default a, Unique.eq_default a', single_eq_same, - single_eq_same] - -lemma apply_single' [Zero N] [Zero P] (e : N → P) (he : e 0 = 0) (a : α) (n : N) (b : α) : - e ((single a n) b) = single a (e n) b := by - classical - simp only [single_apply] - split_ifs - · rfl - · exact he - -lemma apply_single [Zero N] [Zero P] {F : Type*} [FunLike F N P] [ZeroHomClass F N P] - (e : F) (a : α) (n : N) (b : α) : - e ((single a n) b) = single a (e n) b := - apply_single' e (map_zero e) a n b - -theorem support_eq_singleton {f : α →₀ M} {a : α} : - f.support = {a} ↔ f a ≠ 0 ∧ f = single a (f a) := - ⟨fun h => - ⟨mem_support_iff.1 <| h.symm ▸ Finset.mem_singleton_self a, - eq_single_iff.2 ⟨subset_of_eq h, rfl⟩⟩, - fun h => h.2.symm ▸ support_single_ne_zero _ h.1⟩ - -theorem support_eq_singleton' {f : α →₀ M} {a : α} : - f.support = {a} ↔ ∃ b ≠ 0, f = single a b := - ⟨fun h => - let h := support_eq_singleton.1 h - ⟨_, h.1, h.2⟩, - fun ⟨_b, hb, hf⟩ => hf.symm ▸ support_single_ne_zero _ hb⟩ - -theorem card_support_eq_one {f : α →₀ M} : - #f.support = 1 ↔ ∃ a, f a ≠ 0 ∧ f = single a (f a) := by - simp only [card_eq_one, support_eq_singleton] - -theorem card_support_eq_one' {f : α →₀ M} : - #f.support = 1 ↔ ∃ a, ∃ b ≠ 0, f = single a b := by - simp only [card_eq_one, support_eq_singleton'] - -theorem support_subset_singleton {f : α →₀ M} {a : α} : f.support ⊆ {a} ↔ f = single a (f a) := - ⟨fun h => eq_single_iff.mpr ⟨h, rfl⟩, fun h => (eq_single_iff.mp h).left⟩ - -theorem support_subset_singleton' {f : α →₀ M} {a : α} : f.support ⊆ {a} ↔ ∃ b, f = single a b := - ⟨fun h => ⟨f a, support_subset_singleton.mp h⟩, fun ⟨b, hb⟩ => by - rw [hb, support_subset_singleton, single_eq_same]⟩ - -theorem card_support_le_one [Nonempty α] {f : α →₀ M} : - #f.support ≤ 1 ↔ ∃ a, f = single a (f a) := by - simp only [card_le_one_iff_subset_singleton, support_subset_singleton] - -theorem card_support_le_one' [Nonempty α] {f : α →₀ M} : - #f.support ≤ 1 ↔ ∃ a b, f = single a b := by - simp only [card_le_one_iff_subset_singleton, support_subset_singleton'] - -@[simp] -theorem equivFunOnFinite_single [DecidableEq α] [Finite α] (x : α) (m : M) : - Finsupp.equivFunOnFinite (Finsupp.single x m) = Pi.single x m := by - ext - simp [Finsupp.single_eq_pi_single, equivFunOnFinite] - -@[simp] -theorem equivFunOnFinite_symm_single [DecidableEq α] [Finite α] (x : α) (m : M) : - Finsupp.equivFunOnFinite.symm (Pi.single x m) = Finsupp.single x m := by - rw [← equivFunOnFinite_single, Equiv.symm_apply_apply] - -end Single - -/-! ### Declarations about `update` -/ - - -section Update - -variable [Zero M] (f : α →₀ M) (a : α) (b : M) (i : α) - -/-- Replace the value of a `α →₀ M` at a given point `a : α` by a given value `b : M`. -If `b = 0`, this amounts to removing `a` from the `Finsupp.support`. -Otherwise, if `a` was not in the `Finsupp.support`, it is added to it. - -This is the finitely-supported version of `Function.update`. -/ -def update (f : α →₀ M) (a : α) (b : M) : α →₀ M where - support := by - haveI := Classical.decEq α; haveI := Classical.decEq M - exact if b = 0 then f.support.erase a else insert a f.support - toFun := - haveI := Classical.decEq α - Function.update f a b - mem_support_toFun i := by - classical - rw [Function.update] - simp only [eq_rec_constant, dite_eq_ite, ne_eq] - split_ifs with hb ha ha <;> - try simp only [*, not_false_iff, iff_true, not_true, iff_false] - · rw [Finset.mem_erase] - simp - · rw [Finset.mem_erase] - simp [ha] - · rw [Finset.mem_insert] - simp [ha] - · rw [Finset.mem_insert] - simp [ha] - -@[simp, norm_cast] -theorem coe_update [DecidableEq α] : (f.update a b : α → M) = Function.update f a b := by - delta update Function.update - ext - dsimp - split_ifs <;> simp - -@[simp] -theorem update_self : f.update a (f a) = f := by - classical - ext - simp - -@[simp] -theorem zero_update : update 0 a b = single a b := by - classical - ext - rw [single_eq_update] - rfl - -theorem support_update [DecidableEq α] [DecidableEq M] : - support (f.update a b) = if b = 0 then f.support.erase a else insert a f.support := by - classical - dsimp only [update] - congr! - -@[simp] -theorem support_update_zero [DecidableEq α] : support (f.update a 0) = f.support.erase a := by - classical - simp only [update, ite_true, mem_support_iff, ne_eq, not_not] - congr! - -variable {b} - -theorem support_update_ne_zero [DecidableEq α] (h : b ≠ 0) : - support (f.update a b) = insert a f.support := by - classical - simp only [update, h, ite_false, mem_support_iff, ne_eq] - congr! - -theorem support_update_subset [DecidableEq α] : - support (f.update a b) ⊆ insert a f.support := by - classical - rw [support_update] - split_ifs - · exact (erase_subset _ _).trans (subset_insert _ _) - · rfl - -theorem update_comm (f : α →₀ M) {a₁ a₂ : α} (h : a₁ ≠ a₂) (m₁ m₂ : M) : - update (update f a₁ m₁) a₂ m₂ = update (update f a₂ m₂) a₁ m₁ := - letI := Classical.decEq α - DFunLike.coe_injective <| Function.update_comm h _ _ _ - -@[simp] theorem update_idem (f : α →₀ M) (a : α) (b c : M) : - update (update f a b) a c = update f a c := - letI := Classical.decEq α - DFunLike.coe_injective <| Function.update_idem _ _ _ - -end Update - -/-! ### Declarations about `erase` -/ - - -section Erase - -variable [Zero M] - -/-- -`erase a f` is the finitely supported function equal to `f` except at `a` where it is equal to `0`. -If `a` is not in the support of `f` then `erase a f = f`. --/ -def erase (a : α) (f : α →₀ M) : α →₀ M where - support := - haveI := Classical.decEq α - f.support.erase a - toFun a' := - haveI := Classical.decEq α - if a' = a then 0 else f a' - mem_support_toFun a' := by - classical - rw [mem_erase, mem_support_iff]; dsimp - split_ifs with h - · exact ⟨fun H _ => H.1 h, fun H => (H rfl).elim⟩ - · exact and_iff_right h - -@[simp] -theorem support_erase [DecidableEq α] {a : α} {f : α →₀ M} : - (f.erase a).support = f.support.erase a := by - classical - dsimp only [erase] - congr! - -@[simp] -theorem erase_same {a : α} {f : α →₀ M} : (f.erase a) a = 0 := by - classical simp only [erase, coe_mk, ite_true] - -@[simp] -theorem erase_ne {a a' : α} {f : α →₀ M} (h : a' ≠ a) : (f.erase a) a' = f a' := by - classical simp only [erase, coe_mk, h, ite_false] - -theorem erase_apply [DecidableEq α] {a a' : α} {f : α →₀ M} : - f.erase a a' = if a' = a then 0 else f a' := by - rw [erase, coe_mk] - convert rfl - -@[simp] -theorem erase_single {a : α} {b : M} : erase a (single a b) = 0 := by - ext s; by_cases hs : s = a - · rw [hs, erase_same] - rfl - · rw [erase_ne hs] - exact single_eq_of_ne (Ne.symm hs) - -theorem erase_single_ne {a a' : α} {b : M} (h : a ≠ a') : erase a (single a' b) = single a' b := by - ext s; by_cases hs : s = a - · rw [hs, erase_same, single_eq_of_ne h.symm] - · rw [erase_ne hs] - -@[simp] -theorem erase_of_not_mem_support {f : α →₀ M} {a} (haf : a ∉ f.support) : erase a f = f := by - ext b; by_cases hab : b = a - · rwa [hab, erase_same, eq_comm, ← not_mem_support_iff] - · rw [erase_ne hab] - -@[simp, nolint simpNF] -- Porting note: simpNF linter claims simp can prove this, it can not -theorem erase_zero (a : α) : erase a (0 : α →₀ M) = 0 := by - classical rw [← support_eq_empty, support_erase, support_zero, erase_empty] - -theorem erase_eq_update_zero (f : α →₀ M) (a : α) : f.erase a = update f a 0 := - letI := Classical.decEq α - ext fun _ => (Function.update_apply _ _ _ _).symm - --- The name matches `Finset.erase_insert_of_ne` -theorem erase_update_of_ne (f : α →₀ M) {a a' : α} (ha : a ≠ a') (b : M) : - erase a (update f a' b) = update (erase a f) a' b := by - rw [erase_eq_update_zero, erase_eq_update_zero, update_comm _ ha] - --- not `simp` as `erase_of_not_mem_support` can prove this -theorem erase_idem (f : α →₀ M) (a : α) : - erase a (erase a f) = erase a f := by - rw [erase_eq_update_zero, erase_eq_update_zero, update_idem] - -@[simp] theorem update_erase_eq_update (f : α →₀ M) (a : α) (b : M) : - update (erase a f) a b = update f a b := by - rw [erase_eq_update_zero, update_idem] - -@[simp] theorem erase_update_eq_erase (f : α →₀ M) (a : α) (b : M) : - erase a (update f a b) = erase a f := by - rw [erase_eq_update_zero, erase_eq_update_zero, update_idem] - -end Erase - /-! ### Declarations about `onFinset` -/ @@ -720,12 +316,6 @@ theorem support_mapRange {f : M → N} {hf : f 0 = 0} {g : α →₀ M} : (mapRange f hf g).support ⊆ g.support := support_onFinset_subset -@[simp] -theorem mapRange_single {f : M → N} {hf : f 0 = 0} {a : α} {b : M} : - mapRange f hf (single a b) = single a (f b) := - ext fun a' => by - classical simpa only [single_eq_pi_single] using Pi.apply_single _ (fun _ => hf) a _ a' - theorem support_mapRange_of_injective {e : M → N} (he0 : e 0 = 0) (f : ι →₀ M) (he : Function.Injective e) : (Finsupp.mapRange e he0 f).support = f.support := by ext @@ -834,37 +424,6 @@ theorem embDomain_mapRange (f : α ↪ β) (g : M → N) (p : α →₀ M) (hg : rw [mapRange_apply, embDomain_apply, embDomain_apply, mapRange_apply] · rw [mapRange_apply, embDomain_notin_range, embDomain_notin_range, ← hg] <;> assumption -theorem single_of_embDomain_single (l : α →₀ M) (f : α ↪ β) (a : β) (b : M) (hb : b ≠ 0) - (h : l.embDomain f = single a b) : ∃ x, l = single x b ∧ f x = a := by - classical - have h_map_support : Finset.map f l.support = {a} := by - rw [← support_embDomain, h, support_single_ne_zero _ hb] - have ha : a ∈ Finset.map f l.support := by simp only [h_map_support, Finset.mem_singleton] - rcases Finset.mem_map.1 ha with ⟨c, _hc₁, hc₂⟩ - use c - constructor - · ext d - rw [← embDomain_apply f l, h] - by_cases h_cases : c = d - · simp only [Eq.symm h_cases, hc₂, single_eq_same] - · rw [single_apply, single_apply, if_neg, if_neg h_cases] - by_contra hfd - exact h_cases (f.injective (hc₂.trans hfd)) - · exact hc₂ - -@[simp] -theorem embDomain_single (f : α ↪ β) (a : α) (m : M) : - embDomain f (single a m) = single (f a) m := by - classical - ext b - by_cases h : b ∈ Set.range f - · rcases h with ⟨a', rfl⟩ - simp [single_apply] - · simp only [embDomain_notin_range, h, single_apply, not_false_iff] - rw [if_neg] - rintro rfl - simp at h - end EmbDomain /-! ### Declarations about `zipWith` -/ @@ -895,15 +454,6 @@ theorem support_zipWith [D : DecidableEq α] {f : M → N → P} {hf : f 0 0 = 0 {g₂ : α →₀ N} : (zipWith f hf g₁ g₂).support ⊆ g₁.support ∪ g₂.support := by convert support_onFinset_subset -@[simp] -theorem zipWith_single_single (f : M → N → P) (hf : f 0 0 = 0) (a : α) (m : M) (n : N) : - zipWith f hf (single a m) (single a n) = single a (f m n) := by - ext a' - rw [zipWith_apply] - obtain rfl | ha' := eq_or_ne a a' - · rw [single_eq_same, single_eq_same, single_eq_same] - · rw [single_eq_of_ne ha', single_eq_of_ne ha', single_eq_of_ne ha', hf] - end ZipWith /-! ### Additive monoid structure on `α →₀ M` -/ @@ -936,24 +486,6 @@ theorem support_add_eq [DecidableEq α] {g₁ g₂ : α →₀ M} (h : Disjoint have : a ∉ g₁.support := disjoint_right.1 h ha simp only [mem_support_iff, not_not] at *; simpa only [add_apply, this, zero_add] -@[simp] -theorem single_add (a : α) (b₁ b₂ : M) : single a (b₁ + b₂) = single a b₁ + single a b₂ := - (zipWith_single_single _ _ _ _ _).symm - -theorem support_single_add {a : α} {b : M} {f : α →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) : - support (single a b + f) = cons a f.support ha := by - classical - have H := support_single_ne_zero a hb - rw [support_add_eq, H, cons_eq_insert, insert_eq] - rwa [H, disjoint_singleton_left] - -theorem support_add_single {a : α} {b : M} {f : α →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) : - support (f + single a b) = cons a f.support ha := by - classical - have H := support_single_ne_zero a hb - rw [support_add_eq, H, union_comm, cons_eq_insert, insert_eq] - rwa [H, disjoint_singleton_right] - instance instAddZeroClass : AddZeroClass (α →₀ M) := DFunLike.coe_injective.addZeroClass _ coe_zero coe_add @@ -973,25 +505,11 @@ noncomputable def _root_.AddEquiv.finsuppUnique {ι : Type*} [Unique ι] : __ := Equiv.finsuppUnique map_add' _ _ := rfl -lemma _root_.AddEquiv.finsuppUnique_symm {M : Type*} [AddZeroClass M] (d : M) : - AddEquiv.finsuppUnique.symm d = single () d := by - rw [Finsupp.unique_single (AddEquiv.finsuppUnique.symm d), Finsupp.unique_single_eq_iff] - simp [AddEquiv.finsuppUnique] - instance instIsRightCancelAdd [IsRightCancelAdd M] : IsRightCancelAdd (α →₀ M) where add_right_cancel _ _ _ h := ext fun x => add_right_cancel <| DFunLike.congr_fun h x instance instIsCancelAdd [IsCancelAdd M] : IsCancelAdd (α →₀ M) where -/-- `Finsupp.single` as an `AddMonoidHom`. - -See `Finsupp.lsingle` in `LinearAlgebra/Finsupp` for the stronger version as a linear map. -/ -@[simps] -def singleAddHom (a : α) : M →+ α →₀ M where - toFun := single a - map_zero' := single_zero a - map_add' := single_add a - /-- Evaluation of a function `f : α →₀ M` at a point as an additive monoid homomorphism. See `Finsupp.lapply` in `LinearAlgebra/Finsupp` for the stronger version as a linear map. -/ @@ -1008,130 +526,6 @@ noncomputable def coeFnAddHom : (α →₀ M) →+ α → M where map_zero' := coe_zero map_add' := coe_add -theorem update_eq_single_add_erase (f : α →₀ M) (a : α) (b : M) : - f.update a b = single a b + f.erase a := by - classical - ext j - rcases eq_or_ne a j with (rfl | h) - · simp - · simp [Function.update_of_ne h.symm, single_apply, h, erase_ne, h.symm] - -theorem update_eq_erase_add_single (f : α →₀ M) (a : α) (b : M) : - f.update a b = f.erase a + single a b := by - classical - ext j - rcases eq_or_ne a j with (rfl | h) - · simp - · simp [Function.update_of_ne h.symm, single_apply, h, erase_ne, h.symm] - -theorem single_add_erase (a : α) (f : α →₀ M) : single a (f a) + f.erase a = f := by - rw [← update_eq_single_add_erase, update_self] - -theorem erase_add_single (a : α) (f : α →₀ M) : f.erase a + single a (f a) = f := by - rw [← update_eq_erase_add_single, update_self] - -@[simp] -theorem erase_add (a : α) (f f' : α →₀ M) : erase a (f + f') = erase a f + erase a f' := by - ext s; by_cases hs : s = a - · rw [hs, add_apply, erase_same, erase_same, erase_same, add_zero] - rw [add_apply, erase_ne hs, erase_ne hs, erase_ne hs, add_apply] - -/-- `Finsupp.erase` as an `AddMonoidHom`. -/ -@[simps] -def eraseAddHom (a : α) : (α →₀ M) →+ α →₀ M where - toFun := erase a - map_zero' := erase_zero a - map_add' := erase_add a - -@[elab_as_elim] -protected theorem induction {p : (α →₀ M) → Prop} (f : α →₀ M) (h0 : p 0) - (ha : ∀ (a b) (f : α →₀ M), a ∉ f.support → b ≠ 0 → p f → p (single a b + f)) : p f := - suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl - fun s => - Finset.cons_induction_on s (fun f hf => by rwa [support_eq_empty.1 hf]) fun a s has ih f hf => by - suffices p (single a (f a) + f.erase a) by rwa [single_add_erase] at this - classical - apply ha - · rw [support_erase, mem_erase] - exact fun H => H.1 rfl - · rw [← mem_support_iff, hf] - exact mem_cons_self _ _ - · apply ih _ _ - rw [support_erase, hf, Finset.erase_cons] - -theorem induction₂ {p : (α →₀ M) → Prop} (f : α →₀ M) (h0 : p 0) - (ha : ∀ (a b) (f : α →₀ M), a ∉ f.support → b ≠ 0 → p f → p (f + single a b)) : p f := - suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl - fun s => - Finset.cons_induction_on s (fun f hf => by rwa [support_eq_empty.1 hf]) fun a s has ih f hf => by - suffices p (f.erase a + single a (f a)) by rwa [erase_add_single] at this - classical - apply ha - · rw [support_erase, mem_erase] - exact fun H => H.1 rfl - · rw [← mem_support_iff, hf] - exact mem_cons_self _ _ - · apply ih _ _ - rw [support_erase, hf, Finset.erase_cons] - -theorem induction_linear {p : (α →₀ M) → Prop} (f : α →₀ M) (h0 : p 0) - (hadd : ∀ f g : α →₀ M, p f → p g → p (f + g)) (hsingle : ∀ a b, p (single a b)) : p f := - induction₂ f h0 fun _a _b _f _ _ w => hadd _ _ w (hsingle _ _) - -section LinearOrder - -variable [LinearOrder α] {p : (α →₀ M) → Prop} - -/-- A finitely supported function can be built by adding up `single a b` for increasing `a`. - -The theorem `induction_on_max₂` swaps the argument order in the sum. -/ -theorem induction_on_max (f : α →₀ M) (h0 : p 0) - (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (single a b + f)) : - p f := by - suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl - refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_) - · rwa [support_eq_empty.1 h] - · have hs' : (erase a f).support = s := by - rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)] - rw [← single_add_erase a f] - refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs') - rw [← mem_support_iff, hs] - exact mem_insert_self a s - -/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`. - -The theorem `induction_on_min₂` swaps the argument order in the sum. -/ -theorem induction_on_min (f : α →₀ M) (h0 : p 0) - (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (single a b + f)) : - p f := - induction_on_max (α := αᵒᵈ) f h0 ha - -/-- A finitely supported function can be built by adding up `single a b` for increasing `a`. - -The theorem `induction_on_max` swaps the argument order in the sum. -/ -theorem induction_on_max₂ (f : α →₀ M) (h0 : p 0) - (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (f + single a b)) : - p f := by - suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl - refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_) - · rwa [support_eq_empty.1 h] - · have hs' : (erase a f).support = s := by - rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)] - rw [← erase_add_single a f] - refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs') - rw [← mem_support_iff, hs] - exact mem_insert_self a s - -/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`. - -The theorem `induction_on_min` swaps the argument order in the sum. -/ -theorem induction_on_min₂ (f : α →₀ M) (h0 : p 0) - (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (f + single a b)) : - p f := - induction_on_max₂ (α := αᵒᵈ) f h0 ha - -end LinearOrder - theorem mapRange_add [AddZeroClass N] {f : M → N} {hf : f 0 = 0} (hf' : ∀ x y, f (x + y) = f x + f y) (v₁ v₂ : α →₀ M) : mapRange f hf (v₁ + v₂) = mapRange f hf v₁ + mapRange f hf v₂ := @@ -1233,14 +627,6 @@ instance instAddCommGroup [AddCommGroup G] : AddCommGroup (α →₀ G) := (fun _ _ => rfl) fun _ _ => rfl with toAddGroup := Finsupp.instAddGroup } -theorem single_add_single_eq_single_add_single [AddCommMonoid M] {k l m n : α} {u v : M} - (hu : u ≠ 0) (hv : v ≠ 0) : - single k u + single l v = single m u + single n v ↔ - (k = m ∧ l = n) ∨ (u = v ∧ k = n ∧ l = m) ∨ (u + v = 0 ∧ k = l ∧ m = n) := by - classical - simp_rw [DFunLike.ext_iff, coe_add, single_eq_pi_single, ← funext_iff] - exact Pi.single_add_single_eq_single_add_single hu hv - @[simp] theorem support_neg [AddGroup G] (f : α →₀ G) : support (-f) = support f := Finset.Subset.antisymm support_mapRange @@ -1254,14 +640,4 @@ theorem support_sub [DecidableEq α] [AddGroup G] {f g : α →₀ G} : rw [sub_eq_add_neg, ← support_neg g] exact support_add -theorem erase_eq_sub_single [AddGroup G] (f : α →₀ G) (a : α) : f.erase a = f - single a (f a) := by - ext a' - rcases eq_or_ne a a' with (rfl | h) - · simp - · simp [erase_ne h.symm, single_eq_of_ne h] - -theorem update_eq_sub_add_single [AddGroup G] (f : α →₀ G) (a : α) (b : G) : - f.update a b = f - single a (f a) + single a b := by - rw [update_eq_erase_add_single, erase_eq_sub_single] - end Finsupp diff --git a/Mathlib/Data/Finsupp/Ext.lean b/Mathlib/Data/Finsupp/Ext.lean index 14f8617ffb6f7..9ad227d489a19 100644 --- a/Mathlib/Data/Finsupp/Ext.lean +++ b/Mathlib/Data/Finsupp/Ext.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.Group.Submonoid.Basic import Mathlib.Algebra.Group.TypeTags.Hom -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single /-! # Extensionality for maps on `Finsupp` diff --git a/Mathlib/Data/Finsupp/Fin.lean b/Mathlib/Data/Finsupp/Fin.lean index 146af1b20aee6..049744c5fa6a9 100644 --- a/Mathlib/Data/Finsupp/Fin.lean +++ b/Mathlib/Data/Finsupp/Fin.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Ivan Sadofschi Costa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Ivan Sadofschi Costa -/ -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single /-! # `cons` and `tail` for maps `Fin n →₀ M` diff --git a/Mathlib/Data/Finsupp/Fintype.lean b/Mathlib/Data/Finsupp/Fintype.lean index b347815decf83..1af258ead54dd 100644 --- a/Mathlib/Data/Finsupp/Fintype.lean +++ b/Mathlib/Data/Finsupp/Fintype.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Anne Baanen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen, Alex J. Best -/ -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single import Mathlib.Data.Fintype.BigOperators /-! diff --git a/Mathlib/Data/Finsupp/Indicator.lean b/Mathlib/Data/Finsupp/Indicator.lean index 5c4315a90b1c6..fd384ec21319c 100644 --- a/Mathlib/Data/Finsupp/Indicator.lean +++ b/Mathlib/Data/Finsupp/Indicator.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single /-! # Building finitely supported functions off finsets diff --git a/Mathlib/Data/Finsupp/Notation.lean b/Mathlib/Data/Finsupp/Notation.lean index 12c11f9e628e5..c67f3f53363cc 100644 --- a/Mathlib/Data/Finsupp/Notation.lean +++ b/Mathlib/Data/Finsupp/Notation.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single /-! # Notation for `Finsupp` diff --git a/Mathlib/Data/Finsupp/Pointwise.lean b/Mathlib/Data/Finsupp/Pointwise.lean index 04b6b2a36e9d5..f73752985deab 100644 --- a/Mathlib/Data/Finsupp/Pointwise.lean +++ b/Mathlib/Data/Finsupp/Pointwise.lean @@ -6,7 +6,7 @@ Authors: Kim Morrison import Mathlib.Algebra.Module.Defs import Mathlib.Algebra.Ring.InjSurj import Mathlib.Algebra.Ring.Pi -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single /-! # The pointwise product on `Finsupp`. diff --git a/Mathlib/Data/Finsupp/SMulWithZero.lean b/Mathlib/Data/Finsupp/SMulWithZero.lean index 79dda0d1067c9..237cae6aa24d4 100644 --- a/Mathlib/Data/Finsupp/SMulWithZero.lean +++ b/Mathlib/Data/Finsupp/SMulWithZero.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.Group.Action.Pi import Mathlib.Algebra.SMulWithZero -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single /-! # Scalar multiplication on `Finsupp` diff --git a/Mathlib/Data/Finsupp/Single.lean b/Mathlib/Data/Finsupp/Single.lean new file mode 100644 index 0000000000000..48342b59601d3 --- /dev/null +++ b/Mathlib/Data/Finsupp/Single.lean @@ -0,0 +1,711 @@ +/- +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, Kim Morrison +-/ +import Mathlib.Data.Finset.Max +import Mathlib.Data.Finsupp.Defs + +/-! +# Finitely supported functions on exactly one point + +This file contains definitions and basic results on defining/updating/removing `Finsupp`s +using one point of the domain. + +## Main declarations + +* `Finsupp.single`: The `Finsupp` which is nonzero in exactly one point. +* `Finsupp.update`: Changes one value of a `Finsupp`. +* `Finsupp.erase`: Replaces one value of a `Finsupp` by `0`. + +## Implementation notes + +This file is a `noncomputable theory` and uses classical logic throughout. +-/ + + +noncomputable section + +open Finset Function + +variable {α β γ ι M M' N P G H R S : Type*} + +namespace Finsupp + +/-! ### Declarations about `single` -/ + +section Single + +variable [Zero M] {a a' : α} {b : M} + +/-- `single a b` is the finitely supported function with value `b` at `a` and zero otherwise. -/ +def single (a : α) (b : M) : α →₀ M where + support := + haveI := Classical.decEq M + if b = 0 then ∅ else {a} + toFun := + haveI := Classical.decEq α + Pi.single a b + mem_support_toFun a' := by + classical + obtain rfl | hb := eq_or_ne b 0 + · simp [Pi.single, update] + rw [if_neg hb, mem_singleton] + obtain rfl | ha := eq_or_ne a' a + · simp [hb, Pi.single, update] + simp [Pi.single_eq_of_ne' ha.symm, ha] + +theorem single_apply [Decidable (a = a')] : single a b a' = if a = a' then b else 0 := by + classical + simp_rw [@eq_comm _ a a'] + convert Pi.single_apply a b a' + +theorem single_apply_left {f : α → β} (hf : Function.Injective f) (x z : α) (y : M) : + single (f x) y (f z) = single x y z := by classical simp only [single_apply, hf.eq_iff] + +theorem single_eq_set_indicator : ⇑(single a b) = Set.indicator {a} fun _ => b := by + classical + ext + simp [single_apply, Set.indicator, @eq_comm _ a] + +@[simp] +theorem single_eq_same : (single a b : α →₀ M) a = b := by + classical exact Pi.single_eq_same (f := fun _ ↦ M) a b + +@[simp] +theorem single_eq_of_ne (h : a ≠ a') : (single a b : α →₀ M) a' = 0 := by + classical exact Pi.single_eq_of_ne' h _ + +theorem single_eq_update [DecidableEq α] (a : α) (b : M) : + ⇑(single a b) = Function.update (0 : _) a b := by + classical rw [single_eq_set_indicator, ← Set.piecewise_eq_indicator, Set.piecewise_singleton] + +theorem single_eq_pi_single [DecidableEq α] (a : α) (b : M) : ⇑(single a b) = Pi.single a b := + single_eq_update a b + +@[simp] +theorem single_zero (a : α) : (single a 0 : α →₀ M) = 0 := + DFunLike.coe_injective <| by + classical simpa only [single_eq_update, coe_zero] using Function.update_eq_self a (0 : α → M) + +theorem single_of_single_apply (a a' : α) (b : M) : + single a ((single a' b) a) = single a' (single a' b) a := by + classical + rw [single_apply, single_apply] + ext + split_ifs with h + · rw [h] + · rw [zero_apply, single_apply, ite_self] + +theorem support_single_ne_zero (a : α) (hb : b ≠ 0) : (single a b).support = {a} := + if_neg hb + +theorem support_single_subset : (single a b).support ⊆ {a} := by + classical show ite _ _ _ ⊆ _; split_ifs <;> [exact empty_subset _; exact Subset.refl _] + +theorem single_apply_mem (x) : single a b x ∈ ({0, b} : Set M) := by + rcases em (a = x) with (rfl | hx) <;> [simp; simp [single_eq_of_ne hx]] + +theorem range_single_subset : Set.range (single a b) ⊆ {0, b} := + Set.range_subset_iff.2 single_apply_mem + +/-- `Finsupp.single a b` is injective in `b`. For the statement that it is injective in `a`, see +`Finsupp.single_left_injective` -/ +theorem single_injective (a : α) : Function.Injective (single a : M → α →₀ M) := fun b₁ b₂ eq => by + have : (single a b₁ : α →₀ M) a = (single a b₂ : α →₀ M) a := by rw [eq] + rwa [single_eq_same, single_eq_same] at this + +theorem single_apply_eq_zero {a x : α} {b : M} : single a b x = 0 ↔ x = a → b = 0 := by + simp [single_eq_set_indicator] + +theorem single_apply_ne_zero {a x : α} {b : M} : single a b x ≠ 0 ↔ x = a ∧ b ≠ 0 := by + simp [single_apply_eq_zero] + +theorem mem_support_single (a a' : α) (b : M) : a ∈ (single a' b).support ↔ a = a' ∧ b ≠ 0 := by + simp [single_apply_eq_zero, not_or] + +theorem eq_single_iff {f : α →₀ M} {a b} : f = single a b ↔ f.support ⊆ {a} ∧ f a = b := by + refine ⟨fun h => h.symm ▸ ⟨support_single_subset, single_eq_same⟩, ?_⟩ + rintro ⟨h, rfl⟩ + ext x + by_cases hx : a = x <;> simp only [hx, single_eq_same, single_eq_of_ne, Ne, not_false_iff] + exact not_mem_support_iff.1 (mt (fun hx => (mem_singleton.1 (h hx)).symm) hx) + +theorem single_eq_single_iff (a₁ a₂ : α) (b₁ b₂ : M) : + single a₁ b₁ = single a₂ b₂ ↔ a₁ = a₂ ∧ b₁ = b₂ ∨ b₁ = 0 ∧ b₂ = 0 := by + constructor + · intro eq + by_cases h : a₁ = a₂ + · refine Or.inl ⟨h, ?_⟩ + rwa [h, (single_injective a₂).eq_iff] at eq + · rw [DFunLike.ext_iff] at eq + have h₁ := eq a₁ + have h₂ := eq a₂ + simp only [single_eq_same, single_eq_of_ne h, single_eq_of_ne (Ne.symm h)] at h₁ h₂ + exact Or.inr ⟨h₁, h₂.symm⟩ + · rintro (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩) + · rfl + · rw [single_zero, single_zero] + +/-- `Finsupp.single a b` is injective in `a`. For the statement that it is injective in `b`, see +`Finsupp.single_injective` -/ +theorem single_left_injective (h : b ≠ 0) : Function.Injective fun a : α => single a b := + fun _a _a' H => (((single_eq_single_iff _ _ _ _).mp H).resolve_right fun hb => h hb.1).left + +theorem single_left_inj (h : b ≠ 0) : single a b = single a' b ↔ a = a' := + (single_left_injective h).eq_iff + +theorem support_single_ne_bot (i : α) (h : b ≠ 0) : (single i b).support ≠ ⊥ := by + simpa only [support_single_ne_zero _ h] using singleton_ne_empty _ + +theorem support_single_disjoint {b' : M} (hb : b ≠ 0) (hb' : b' ≠ 0) {i j : α} : + Disjoint (single i b).support (single j b').support ↔ i ≠ j := by + rw [support_single_ne_zero _ hb, support_single_ne_zero _ hb', disjoint_singleton] + +@[simp] +theorem single_eq_zero : single a b = 0 ↔ b = 0 := by + simp [DFunLike.ext_iff, single_eq_set_indicator] + +theorem single_swap (a₁ a₂ : α) (b : M) : single a₁ b a₂ = single a₂ b a₁ := by + classical simp only [single_apply, eq_comm] + +instance instNontrivial [Nonempty α] [Nontrivial M] : Nontrivial (α →₀ M) := by + inhabit α + rcases exists_ne (0 : M) with ⟨x, hx⟩ + exact nontrivial_of_ne (single default x) 0 (mt single_eq_zero.1 hx) + +theorem unique_single [Unique α] (x : α →₀ M) : x = single default (x default) := + ext <| Unique.forall_iff.2 single_eq_same.symm + +@[simp] +theorem unique_single_eq_iff [Unique α] {b' : M} : single a b = single a' b' ↔ b = b' := by + rw [Finsupp.unique_ext_iff, Unique.eq_default a, Unique.eq_default a', single_eq_same, + single_eq_same] + +lemma apply_single' [Zero N] [Zero P] (e : N → P) (he : e 0 = 0) (a : α) (n : N) (b : α) : + e ((single a n) b) = single a (e n) b := by + classical + simp only [single_apply] + split_ifs + · rfl + · exact he + +lemma apply_single [Zero N] [Zero P] {F : Type*} [FunLike F N P] [ZeroHomClass F N P] + (e : F) (a : α) (n : N) (b : α) : + e ((single a n) b) = single a (e n) b := + apply_single' e (map_zero e) a n b + +theorem support_eq_singleton {f : α →₀ M} {a : α} : + f.support = {a} ↔ f a ≠ 0 ∧ f = single a (f a) := + ⟨fun h => + ⟨mem_support_iff.1 <| h.symm ▸ Finset.mem_singleton_self a, + eq_single_iff.2 ⟨subset_of_eq h, rfl⟩⟩, + fun h => h.2.symm ▸ support_single_ne_zero _ h.1⟩ + +theorem support_eq_singleton' {f : α →₀ M} {a : α} : + f.support = {a} ↔ ∃ b ≠ 0, f = single a b := + ⟨fun h => + let h := support_eq_singleton.1 h + ⟨_, h.1, h.2⟩, + fun ⟨_b, hb, hf⟩ => hf.symm ▸ support_single_ne_zero _ hb⟩ + +theorem card_support_eq_one {f : α →₀ M} : + #f.support = 1 ↔ ∃ a, f a ≠ 0 ∧ f = single a (f a) := by + simp only [card_eq_one, support_eq_singleton] + +theorem card_support_eq_one' {f : α →₀ M} : + #f.support = 1 ↔ ∃ a, ∃ b ≠ 0, f = single a b := by + simp only [card_eq_one, support_eq_singleton'] + +theorem support_subset_singleton {f : α →₀ M} {a : α} : f.support ⊆ {a} ↔ f = single a (f a) := + ⟨fun h => eq_single_iff.mpr ⟨h, rfl⟩, fun h => (eq_single_iff.mp h).left⟩ + +theorem support_subset_singleton' {f : α →₀ M} {a : α} : f.support ⊆ {a} ↔ ∃ b, f = single a b := + ⟨fun h => ⟨f a, support_subset_singleton.mp h⟩, fun ⟨b, hb⟩ => by + rw [hb, support_subset_singleton, single_eq_same]⟩ + +theorem card_support_le_one [Nonempty α] {f : α →₀ M} : + #f.support ≤ 1 ↔ ∃ a, f = single a (f a) := by + simp only [card_le_one_iff_subset_singleton, support_subset_singleton] + +theorem card_support_le_one' [Nonempty α] {f : α →₀ M} : + #f.support ≤ 1 ↔ ∃ a b, f = single a b := by + simp only [card_le_one_iff_subset_singleton, support_subset_singleton'] + +@[simp] +theorem equivFunOnFinite_single [DecidableEq α] [Finite α] (x : α) (m : M) : + Finsupp.equivFunOnFinite (Finsupp.single x m) = Pi.single x m := by + ext + simp [Finsupp.single_eq_pi_single, equivFunOnFinite] + +@[simp] +theorem equivFunOnFinite_symm_single [DecidableEq α] [Finite α] (x : α) (m : M) : + Finsupp.equivFunOnFinite.symm (Pi.single x m) = Finsupp.single x m := by + rw [← equivFunOnFinite_single, Equiv.symm_apply_apply] + +end Single + +/-! ### Declarations about `update` -/ + + +section Update + +variable [Zero M] (f : α →₀ M) (a : α) (b : M) (i : α) + +/-- Replace the value of a `α →₀ M` at a given point `a : α` by a given value `b : M`. +If `b = 0`, this amounts to removing `a` from the `Finsupp.support`. +Otherwise, if `a` was not in the `Finsupp.support`, it is added to it. + +This is the finitely-supported version of `Function.update`. -/ +def update (f : α →₀ M) (a : α) (b : M) : α →₀ M where + support := by + haveI := Classical.decEq α; haveI := Classical.decEq M + exact if b = 0 then f.support.erase a else insert a f.support + toFun := + haveI := Classical.decEq α + Function.update f a b + mem_support_toFun i := by + classical + rw [Function.update] + simp only [eq_rec_constant, dite_eq_ite, ne_eq] + split_ifs with hb ha ha <;> + try simp only [*, not_false_iff, iff_true, not_true, iff_false] + · rw [Finset.mem_erase] + simp + · rw [Finset.mem_erase] + simp [ha] + · rw [Finset.mem_insert] + simp [ha] + · rw [Finset.mem_insert] + simp [ha] + +@[simp, norm_cast] +theorem coe_update [DecidableEq α] : (f.update a b : α → M) = Function.update f a b := by + delta update Function.update + ext + dsimp + split_ifs <;> simp + +@[simp] +theorem update_self : f.update a (f a) = f := by + classical + ext + simp + +@[simp] +theorem zero_update : update 0 a b = single a b := by + classical + ext + rw [single_eq_update] + rfl + +theorem support_update [DecidableEq α] [DecidableEq M] : + support (f.update a b) = if b = 0 then f.support.erase a else insert a f.support := by + classical + dsimp only [update] + congr! + +@[simp] +theorem support_update_zero [DecidableEq α] : support (f.update a 0) = f.support.erase a := by + classical + simp only [update, ite_true, mem_support_iff, ne_eq, not_not] + congr! + +variable {b} + +theorem support_update_ne_zero [DecidableEq α] (h : b ≠ 0) : + support (f.update a b) = insert a f.support := by + classical + simp only [update, h, ite_false, mem_support_iff, ne_eq] + congr! + +theorem support_update_subset [DecidableEq α] : + support (f.update a b) ⊆ insert a f.support := by + classical + rw [support_update] + split_ifs + · exact (erase_subset _ _).trans (subset_insert _ _) + · rfl + +theorem update_comm (f : α →₀ M) {a₁ a₂ : α} (h : a₁ ≠ a₂) (m₁ m₂ : M) : + update (update f a₁ m₁) a₂ m₂ = update (update f a₂ m₂) a₁ m₁ := + letI := Classical.decEq α + DFunLike.coe_injective <| Function.update_comm h _ _ _ + +@[simp] theorem update_idem (f : α →₀ M) (a : α) (b c : M) : + update (update f a b) a c = update f a c := + letI := Classical.decEq α + DFunLike.coe_injective <| Function.update_idem _ _ _ + +end Update + +/-! ### Declarations about `erase` -/ + + +section Erase + +variable [Zero M] + +/-- +`erase a f` is the finitely supported function equal to `f` except at `a` where it is equal to `0`. +If `a` is not in the support of `f` then `erase a f = f`. +-/ +def erase (a : α) (f : α →₀ M) : α →₀ M where + support := + haveI := Classical.decEq α + f.support.erase a + toFun a' := + haveI := Classical.decEq α + if a' = a then 0 else f a' + mem_support_toFun a' := by + classical + rw [mem_erase, mem_support_iff]; dsimp + split_ifs with h + · exact ⟨fun H _ => H.1 h, fun H => (H rfl).elim⟩ + · exact and_iff_right h + +@[simp] +theorem support_erase [DecidableEq α] {a : α} {f : α →₀ M} : + (f.erase a).support = f.support.erase a := by + classical + dsimp only [erase] + congr! + +@[simp] +theorem erase_same {a : α} {f : α →₀ M} : (f.erase a) a = 0 := by + classical simp only [erase, coe_mk, ite_true] + +@[simp] +theorem erase_ne {a a' : α} {f : α →₀ M} (h : a' ≠ a) : (f.erase a) a' = f a' := by + classical simp only [erase, coe_mk, h, ite_false] + +theorem erase_apply [DecidableEq α] {a a' : α} {f : α →₀ M} : + f.erase a a' = if a' = a then 0 else f a' := by + rw [erase, coe_mk] + convert rfl + +@[simp] +theorem erase_single {a : α} {b : M} : erase a (single a b) = 0 := by + ext s; by_cases hs : s = a + · rw [hs, erase_same] + rfl + · rw [erase_ne hs] + exact single_eq_of_ne (Ne.symm hs) + +theorem erase_single_ne {a a' : α} {b : M} (h : a ≠ a') : erase a (single a' b) = single a' b := by + ext s; by_cases hs : s = a + · rw [hs, erase_same, single_eq_of_ne h.symm] + · rw [erase_ne hs] + +@[simp] +theorem erase_of_not_mem_support {f : α →₀ M} {a} (haf : a ∉ f.support) : erase a f = f := by + ext b; by_cases hab : b = a + · rwa [hab, erase_same, eq_comm, ← not_mem_support_iff] + · rw [erase_ne hab] + +@[simp, nolint simpNF] -- Porting note: simpNF linter claims simp can prove this, it can not +theorem erase_zero (a : α) : erase a (0 : α →₀ M) = 0 := by + classical rw [← support_eq_empty, support_erase, support_zero, erase_empty] + +theorem erase_eq_update_zero (f : α →₀ M) (a : α) : f.erase a = update f a 0 := + letI := Classical.decEq α + ext fun _ => (Function.update_apply _ _ _ _).symm + +-- The name matches `Finset.erase_insert_of_ne` +theorem erase_update_of_ne (f : α →₀ M) {a a' : α} (ha : a ≠ a') (b : M) : + erase a (update f a' b) = update (erase a f) a' b := by + rw [erase_eq_update_zero, erase_eq_update_zero, update_comm _ ha] + +-- not `simp` as `erase_of_not_mem_support` can prove this +theorem erase_idem (f : α →₀ M) (a : α) : + erase a (erase a f) = erase a f := by + rw [erase_eq_update_zero, erase_eq_update_zero, update_idem] + +@[simp] theorem update_erase_eq_update (f : α →₀ M) (a : α) (b : M) : + update (erase a f) a b = update f a b := by + rw [erase_eq_update_zero, update_idem] + +@[simp] theorem erase_update_eq_erase (f : α →₀ M) (a : α) (b : M) : + erase a (update f a b) = erase a f := by + rw [erase_eq_update_zero, erase_eq_update_zero, update_idem] + +end Erase + +/-! ### Declarations about `mapRange` -/ + +section MapRange + +variable [Zero M] [Zero N] [Zero P] + +@[simp] +theorem mapRange_single {f : M → N} {hf : f 0 = 0} {a : α} {b : M} : + mapRange f hf (single a b) = single a (f b) := + ext fun a' => by + classical simpa only [single_eq_pi_single] using Pi.apply_single _ (fun _ => hf) a _ a' + +end MapRange + +/-! ### Declarations about `embDomain` -/ + + +section EmbDomain + +variable [Zero M] [Zero N] + +theorem single_of_embDomain_single (l : α →₀ M) (f : α ↪ β) (a : β) (b : M) (hb : b ≠ 0) + (h : l.embDomain f = single a b) : ∃ x, l = single x b ∧ f x = a := by + classical + have h_map_support : Finset.map f l.support = {a} := by + rw [← support_embDomain, h, support_single_ne_zero _ hb] + have ha : a ∈ Finset.map f l.support := by simp only [h_map_support, Finset.mem_singleton] + rcases Finset.mem_map.1 ha with ⟨c, _hc₁, hc₂⟩ + use c + constructor + · ext d + rw [← embDomain_apply f l, h] + by_cases h_cases : c = d + · simp only [Eq.symm h_cases, hc₂, single_eq_same] + · rw [single_apply, single_apply, if_neg, if_neg h_cases] + by_contra hfd + exact h_cases (f.injective (hc₂.trans hfd)) + · exact hc₂ + +@[simp] +theorem embDomain_single (f : α ↪ β) (a : α) (m : M) : + embDomain f (single a m) = single (f a) m := by + classical + ext b + by_cases h : b ∈ Set.range f + · rcases h with ⟨a', rfl⟩ + simp [single_apply] + · simp only [embDomain_notin_range, h, single_apply, not_false_iff] + rw [if_neg] + rintro rfl + simp at h + +end EmbDomain + +/-! ### Declarations about `zipWith` -/ + + +section ZipWith + +variable [Zero M] [Zero N] [Zero P] + +@[simp] +theorem zipWith_single_single (f : M → N → P) (hf : f 0 0 = 0) (a : α) (m : M) (n : N) : + zipWith f hf (single a m) (single a n) = single a (f m n) := by + ext a' + rw [zipWith_apply] + obtain rfl | ha' := eq_or_ne a a' + · rw [single_eq_same, single_eq_same, single_eq_same] + · rw [single_eq_of_ne ha', single_eq_of_ne ha', single_eq_of_ne ha', hf] + +end ZipWith + +/-! ### Additive monoid structure on `α →₀ M` -/ + + +section AddZeroClass + +variable [AddZeroClass M] + +@[simp] +theorem single_add (a : α) (b₁ b₂ : M) : single a (b₁ + b₂) = single a b₁ + single a b₂ := + (zipWith_single_single _ _ _ _ _).symm + +theorem support_single_add {a : α} {b : M} {f : α →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) : + support (single a b + f) = cons a f.support ha := by + classical + have H := support_single_ne_zero a hb + rw [support_add_eq, H, cons_eq_insert, insert_eq] + rwa [H, disjoint_singleton_left] + +theorem support_add_single {a : α} {b : M} {f : α →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) : + support (f + single a b) = cons a f.support ha := by + classical + have H := support_single_ne_zero a hb + rw [support_add_eq, H, union_comm, cons_eq_insert, insert_eq] + rwa [H, disjoint_singleton_right] + +lemma _root_.AddEquiv.finsuppUnique_symm {M : Type*} [AddZeroClass M] (d : M) : + AddEquiv.finsuppUnique.symm d = single () d := by + rw [Finsupp.unique_single (AddEquiv.finsuppUnique.symm d), Finsupp.unique_single_eq_iff] + simp [AddEquiv.finsuppUnique] + +/-- `Finsupp.single` as an `AddMonoidHom`. + +See `Finsupp.lsingle` in `LinearAlgebra/Finsupp` for the stronger version as a linear map. -/ +@[simps] +def singleAddHom (a : α) : M →+ α →₀ M where + toFun := single a + map_zero' := single_zero a + map_add' := single_add a + +theorem update_eq_single_add_erase (f : α →₀ M) (a : α) (b : M) : + f.update a b = single a b + f.erase a := by + classical + ext j + rcases eq_or_ne a j with (rfl | h) + · simp + · simp [Function.update_of_ne h.symm, single_apply, h, erase_ne, h.symm] + +theorem update_eq_erase_add_single (f : α →₀ M) (a : α) (b : M) : + f.update a b = f.erase a + single a b := by + classical + ext j + rcases eq_or_ne a j with (rfl | h) + · simp + · simp [Function.update_of_ne h.symm, single_apply, h, erase_ne, h.symm] + +theorem single_add_erase (a : α) (f : α →₀ M) : single a (f a) + f.erase a = f := by + rw [← update_eq_single_add_erase, update_self] + +theorem erase_add_single (a : α) (f : α →₀ M) : f.erase a + single a (f a) = f := by + rw [← update_eq_erase_add_single, update_self] + +@[simp] +theorem erase_add (a : α) (f f' : α →₀ M) : erase a (f + f') = erase a f + erase a f' := by + ext s; by_cases hs : s = a + · rw [hs, add_apply, erase_same, erase_same, erase_same, add_zero] + rw [add_apply, erase_ne hs, erase_ne hs, erase_ne hs, add_apply] + +/-- `Finsupp.erase` as an `AddMonoidHom`. -/ +@[simps] +def eraseAddHom (a : α) : (α →₀ M) →+ α →₀ M where + toFun := erase a + map_zero' := erase_zero a + map_add' := erase_add a + +@[elab_as_elim] +protected theorem induction {p : (α →₀ M) → Prop} (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), a ∉ f.support → b ≠ 0 → p f → p (single a b + f)) : p f := + suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl + fun s => + Finset.cons_induction_on s (fun f hf => by rwa [support_eq_empty.1 hf]) fun a s has ih f hf => by + suffices p (single a (f a) + f.erase a) by rwa [single_add_erase] at this + classical + apply ha + · rw [support_erase, mem_erase] + exact fun H => H.1 rfl + · rw [← mem_support_iff, hf] + exact mem_cons_self _ _ + · apply ih _ _ + rw [support_erase, hf, Finset.erase_cons] + +theorem induction₂ {p : (α →₀ M) → Prop} (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), a ∉ f.support → b ≠ 0 → p f → p (f + single a b)) : p f := + suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl + fun s => + Finset.cons_induction_on s (fun f hf => by rwa [support_eq_empty.1 hf]) fun a s has ih f hf => by + suffices p (f.erase a + single a (f a)) by rwa [erase_add_single] at this + classical + apply ha + · rw [support_erase, mem_erase] + exact fun H => H.1 rfl + · rw [← mem_support_iff, hf] + exact mem_cons_self _ _ + · apply ih _ _ + rw [support_erase, hf, Finset.erase_cons] + +theorem induction_linear {p : (α →₀ M) → Prop} (f : α →₀ M) (h0 : p 0) + (hadd : ∀ f g : α →₀ M, p f → p g → p (f + g)) (hsingle : ∀ a b, p (single a b)) : p f := + induction₂ f h0 fun _a _b _f _ _ w => hadd _ _ w (hsingle _ _) + +section LinearOrder + +variable [LinearOrder α] {p : (α →₀ M) → Prop} + +/-- A finitely supported function can be built by adding up `single a b` for increasing `a`. + +The theorem `induction_on_max₂` swaps the argument order in the sum. -/ +theorem induction_on_max (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (single a b + f)) : + p f := by + suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl + refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_) + · rwa [support_eq_empty.1 h] + · have hs' : (erase a f).support = s := by + rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)] + rw [← single_add_erase a f] + refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs') + rw [← mem_support_iff, hs] + exact mem_insert_self a s + +/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`. + +The theorem `induction_on_min₂` swaps the argument order in the sum. -/ +theorem induction_on_min (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (single a b + f)) : + p f := + induction_on_max (α := αᵒᵈ) f h0 ha + +/-- A finitely supported function can be built by adding up `single a b` for increasing `a`. + +The theorem `induction_on_max` swaps the argument order in the sum. -/ +theorem induction_on_max₂ (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (f + single a b)) : + p f := by + suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl + refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_) + · rwa [support_eq_empty.1 h] + · have hs' : (erase a f).support = s := by + rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)] + rw [← erase_add_single a f] + refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs') + rw [← mem_support_iff, hs] + exact mem_insert_self a s + +/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`. + +The theorem `induction_on_min` swaps the argument order in the sum. -/ +theorem induction_on_min₂ (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (f + single a b)) : + p f := + induction_on_max₂ (α := αᵒᵈ) f h0 ha + +end LinearOrder + +end AddZeroClass + +theorem single_add_single_eq_single_add_single [AddCommMonoid M] {k l m n : α} {u v : M} + (hu : u ≠ 0) (hv : v ≠ 0) : + single k u + single l v = single m u + single n v ↔ + (k = m ∧ l = n) ∨ (u = v ∧ k = n ∧ l = m) ∨ (u + v = 0 ∧ k = l ∧ m = n) := by + classical + simp_rw [DFunLike.ext_iff, coe_add, single_eq_pi_single, ← funext_iff] + exact Pi.single_add_single_eq_single_add_single hu hv + +theorem erase_eq_sub_single [AddGroup G] (f : α →₀ G) (a : α) : f.erase a = f - single a (f a) := by + ext a' + rcases eq_or_ne a a' with (rfl | h) + · simp + · simp [erase_ne h.symm, single_eq_of_ne h] + +theorem update_eq_sub_add_single [AddGroup G] (f : α →₀ G) (a : α) (b : G) : + f.update a b = f - single a (f a) + single a b := by + rw [update_eq_erase_add_single, erase_eq_sub_single] + +section Group + +variable [AddGroup G] {p : α → Prop} {v v' : α →₀ G} + +@[simp] +theorem single_neg (a : α) (b : G) : single a (-b) = -single a b := + (singleAddHom a : G →+ _).map_neg b + +@[simp] +theorem single_sub (a : α) (b₁ b₂ : G) : single a (b₁ - b₂) = single a b₁ - single a b₂ := + (singleAddHom a : G →+ _).map_sub b₁ b₂ + +@[simp] +theorem erase_neg (a : α) (f : α →₀ G) : erase a (-f) = -erase a f := + (eraseAddHom a : (_ →₀ G) →+ _).map_neg f + +@[simp] +theorem erase_sub (a : α) (f₁ f₂ : α →₀ G) : erase a (f₁ - f₂) = erase a f₁ - erase a f₂ := + (eraseAddHom a : (_ →₀ G) →+ _).map_sub f₁ f₂ + +end Group + +end Finsupp diff --git a/Mathlib/Data/List/ToFinsupp.lean b/Mathlib/Data/List/ToFinsupp.lean index d81d0387470a5..2e45c00adad82 100644 --- a/Mathlib/Data/List/ToFinsupp.lean +++ b/Mathlib/Data/List/ToFinsupp.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Data.Finsupp.Defs +import Mathlib.Data.Finsupp.Single import Mathlib.Data.List.GetD /-! diff --git a/scripts/noshake.json b/scripts/noshake.json index d660d99ec4d73..1c1f5e365a82b 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -396,6 +396,7 @@ "Mathlib.Data.Int.ConditionallyCompleteOrder": ["Mathlib.Order.ConditionallyCompleteLattice.Basic"], "Mathlib.Data.FunLike.Basic": ["Mathlib.Logic.Function.Basic"], + "Mathlib.Data.Finsupp.Notation": ["Mathlib.Data.Finsupp.Single"], "Mathlib.Data.Finset.Insert": ["Mathlib.Data.Finset.Attr"], "Mathlib.Data.ENat.Lattice": ["Mathlib.Algebra.Group.Action.Defs"], "Mathlib.Data.ByteArray": ["Batteries.Data.ByteSubarray"], From a7fbdf28e71d0a02e8ea8d41023b39554c8c74f4 Mon Sep 17 00:00:00 2001 From: Jon Eugster Date: Mon, 13 Jan 2025 14:29:35 +0000 Subject: [PATCH 199/681] feat(scripts/autolabel): add `dependency-bump` label automatically (#17538) Add `dependency-bump` label if `lake-manifest.json` has been modified. --- scripts/autolabel.lean | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/autolabel.lean b/scripts/autolabel.lean index 5225051d5e56a..7f1df923f4a21 100644 --- a/scripts/autolabel.lean +++ b/scripts/autolabel.lean @@ -136,7 +136,9 @@ def mathlibLabels : Array Label := #[ { label := "CI", dirs := #[".github"] }, { label := "IMO", - dirs := #["Archive" / "Imo"] } ] + dirs := #["Archive" / "Imo"] }, + { label := "dependency-bump", + dirs := #["lake-manifest.json"] } ] /-- Exceptions inside `Mathlib/` which are not covered by any label. -/ def mathlibUnlabelled : Array FilePath := #[ @@ -187,6 +189,9 @@ section Tests "Mathlib" / "Tactic"/ "Linter" / "Lint.lean", "Mathlib" / "Tactic" / "Abel.lean" ] == #["t-linter", "t-meta"] +-- Test targeting a file instead of a directory +#guard getMatchingLabels #["lake-manifest.json"] == #["dependency-bump"] + /-- Testing function to ensure the labels defined in `mathlibLabels` cover all subfolders of `Mathlib/`. -/ partial def findUncoveredPaths (path : FilePath) (exceptions : Array FilePath := #[]) : From 4879fd7fd621a46839f4404dbae3e0543a51327d Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 13 Jan 2025 14:29:37 +0000 Subject: [PATCH 200/681] chore(Algebra/Category/Ring): use unification hint to clean up proofs (#20075) (Everything below is written for `CommRingCat`, but also holds for the other `RingCat`s.) As a consequence of #19757, it became harder to unify `(forget ?C).obj R =?= CommRingCat.carrier R` since `?C =?= CommRingCat` would no longer be inferred. This PR adds a unification hint that helps with all but 2 cases where we need to hint `C := CommRingCat`. The current unification hint uses `CommRingCat` as the argument to `forget`, even though we would like it to be an arbitrary category `C`, which can then trigger downstream unification of `C =?= CommRingCat`. However, it seems that dependent unification hints do not work: I cannot get Lean to typecheck `C =?= CommRingCat; (instC : Category C) =?= CommRingCat.instCategory |- ...`. I tried doing this for `ModuleCat` too and it did not seem to fix any required hints. Perhaps because `ModuleCat R` depends on the `R`? --- .../Category/ModuleCat/Presheaf/Sheafify.lean | 2 +- Mathlib/Algebra/Category/Ring/Basic.lean | 27 +++++++++++++ Mathlib/AlgebraicGeometry/FunctionField.lean | 2 +- .../Morphisms/ClosedImmersion.lean | 2 +- .../Morphisms/OpenImmersion.lean | 3 +- .../Morphisms/Preimmersion.lean | 2 +- .../Morphisms/QuasiCompact.lean | 10 ++--- .../Morphisms/QuasiSeparated.lean | 39 +++++++++---------- .../Morphisms/RingHomProperties.lean | 2 +- .../Morphisms/SurjectiveOnStalks.lean | 2 +- Mathlib/AlgebraicGeometry/Scheme.lean | 3 +- .../Sites/SmallAffineZariski.lean | 2 +- Mathlib/AlgebraicGeometry/SpreadingOut.lean | 2 +- Mathlib/Geometry/Manifold/Sheaf/Smooth.lean | 1 - .../LocallyRingedSpace/HasColimits.lean | 3 +- Mathlib/Topology/Sheaves/CommRingCat.lean | 29 ++++++++------ 16 files changed, 80 insertions(+), 51 deletions(-) diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean index 440f20249af9e..8c9688b454ef9 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean @@ -61,7 +61,7 @@ lemma _root_.PresheafOfModules.Sheafify.app_eq_of_isLocallyInjective (hr₀ : α.app _ r₀ = α.app _ r₀') (hm₀ : φ.app _ m₀ = φ.app _ m₀') : φ.app _ (r₀ • m₀) = φ.app _ (r₀' • m₀') := by - apply hA _ (Presheaf.equalizerSieve (D := RingCat) r₀ r₀' ⊓ + apply hA _ (Presheaf.equalizerSieve r₀ r₀' ⊓ Presheaf.equalizerSieve (F := M₀.presheaf) m₀ m₀') · apply J.intersection_covering · exact Presheaf.equalizerSieve_mem J α _ _ hr₀ diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index 211d81e09bdde..c03ba09884376 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -126,6 +126,11 @@ instance : ConcreteCategory.{u} SemiRingCat where map := fun f => f.hom } forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ +/-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. -/ +unif_hint forget_obj_eq_coe (R R' : SemiRingCat) where + R ≟ R' ⊢ + (forget SemiRingCat).obj R ≟ SemiRingCat.carrier R' + lemma forget_obj {R : SemiRingCat} : (forget SemiRingCat).obj R = R := rfl lemma forget_map {R S : SemiRingCat} (f : R ⟶ S) : @@ -265,6 +270,15 @@ instance : ConcreteCategory.{u} RingCat where map := fun f => f.hom } forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ +/-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. + +An example where this is needed is in applying +`PresheafOfModules.Sheafify.app_eq_of_isLocallyInjective`. +-/ +unif_hint forget_obj_eq_coe (R R' : RingCat) where + R ≟ R' ⊢ + (forget RingCat).obj R ≟ RingCat.carrier R' + lemma forget_obj {R : RingCat} : (forget RingCat).obj R = R := rfl lemma forget_map {R S : RingCat} (f : R ⟶ S) : @@ -405,6 +419,11 @@ instance : ConcreteCategory.{u} CommSemiRingCat where map := fun f => f.hom } forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ +/-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. -/ +unif_hint forget_obj_eq_coe (R R' : CommSemiRingCat) where + R ≟ R' ⊢ + (forget CommSemiRingCat).obj R ≟ CommSemiRingCat.carrier R' + lemma forget_obj {R : CommSemiRingCat} : (forget CommSemiRingCat).obj R = R := rfl lemma forget_map {R S : CommSemiRingCat} (f : R ⟶ S) : @@ -549,6 +568,14 @@ instance : ConcreteCategory.{u} CommRingCat where lemma forget_obj {R : CommRingCat} : (forget CommRingCat).obj R = R := rfl +/-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. + +An example where this is needed is in applying `TopCat.Presheaf.restrictOpen` to commutative rings. +-/ +unif_hint forget_obj_eq_coe (R R' : CommRingCat) where + R ≟ R' ⊢ + (forget CommRingCat).obj R ≟ CommRingCat.carrier R' + lemma forget_map {R S : CommRingCat} (f : R ⟶ S) : (forget CommRingCat).map f = f := rfl diff --git a/Mathlib/AlgebraicGeometry/FunctionField.lean b/Mathlib/AlgebraicGeometry/FunctionField.lean index a814d14268a98..07827ad5f66ee 100644 --- a/Mathlib/AlgebraicGeometry/FunctionField.lean +++ b/Mathlib/AlgebraicGeometry/FunctionField.lean @@ -46,7 +46,7 @@ noncomputable instance [IrreducibleSpace X] (U : X.Opens) [Nonempty U] : noncomputable instance [IsIntegral X] : Field X.functionField := by refine .ofIsUnitOrEqZero fun a ↦ ?_ - obtain ⟨U, m, s, rfl⟩ := TopCat.Presheaf.germ_exist (C := CommRingCat) _ _ a + obtain ⟨U, m, s, rfl⟩ := TopCat.Presheaf.germ_exist _ _ a rw [or_iff_not_imp_right, ← (X.presheaf.germ _ _ m).hom.map_zero] intro ha replace ha := ne_of_apply_ne _ ha diff --git a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean index d0c8fb35f7b07..7aba92e4f57a5 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean @@ -75,7 +75,7 @@ instance (priority := 900) {X Y : Scheme} (f : X ⟶ Y) [IsClosedImmersion f] : /-- Isomorphisms are closed immersions. -/ instance {X Y : Scheme} (f : X ⟶ Y) [IsIso f] : IsClosedImmersion f where base_closed := Homeomorph.isClosedEmbedding <| TopCat.homeoOfIso (asIso f.base) - surj_on_stalks := fun _ ↦ (ConcreteCategory.bijective_of_isIso (C := CommRingCat) _).2 + surj_on_stalks := fun _ ↦ (ConcreteCategory.bijective_of_isIso _).2 instance : MorphismProperty.IsMultiplicative @IsClosedImmersion where id_mem _ := inferInstance diff --git a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean index 6cd62e8973f1b..3b9e3811ca311 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean @@ -46,8 +46,7 @@ instance : IsLocalAtTarget (stalkwise (fun f ↦ Function.Bijective f)) := by rw [RingHom.toMorphismProperty_respectsIso_iff] convert (inferInstanceAs (MorphismProperty.isomorphisms CommRingCat).RespectsIso) ext - -- Regression in https://github.com/leanprover-community/mathlib4/pull/17583: have to specify C explicitly below. - exact (ConcreteCategory.isIso_iff_bijective (C := CommRingCat) _).symm + exact (ConcreteCategory.isIso_iff_bijective _).symm instance isOpenImmersion_isLocalAtTarget : IsLocalAtTarget @IsOpenImmersion := isOpenImmersion_eq_inf ▸ inferInstance diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean index b930b47ba6a4c..17521b9d49d3e 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean @@ -59,7 +59,7 @@ instance : IsLocalAtTarget @IsPreimmersion := instance (priority := 900) {X Y : Scheme} (f : X ⟶ Y) [IsOpenImmersion f] : IsPreimmersion f where base_embedding := f.isOpenEmbedding.isEmbedding - surj_on_stalks _ := (ConcreteCategory.bijective_of_isIso (C := CommRingCat) _).2 + surj_on_stalks _ := (ConcreteCategory.bijective_of_isIso _).2 instance : MorphismProperty.IsMultiplicative @IsPreimmersion where id_mem _ := inferInstance diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean index ae913e2eda078..4fa80786dbe0c 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean @@ -245,7 +245,7 @@ theorem compact_open_induction_on {P : X.Opens → Prop} (S : X.Opens) theorem exists_pow_mul_eq_zero_of_res_basicOpen_eq_zero_of_isAffineOpen (X : Scheme) {U : X.Opens} (hU : IsAffineOpen U) (x f : Γ(X, U)) - (H : x |_ᵣ (X.basicOpen f) = 0) : + (H : x |_ (X.basicOpen f) = 0) : ∃ n : ℕ, f ^ n * x = 0 := by rw [← map_zero (X.presheaf.map (homOfLE <| X.basicOpen_le f : X.basicOpen f ⟶ U).op).hom] at H #adaptation_note @@ -263,7 +263,7 @@ theorem exists_pow_mul_eq_zero_of_res_basicOpen_eq_zero_of_isAffineOpen (X : Sch `f ^ n * x = 0` for some `n`. -/ theorem exists_pow_mul_eq_zero_of_res_basicOpen_eq_zero_of_isCompact (X : Scheme.{u}) {U : X.Opens} (hU : IsCompact U.1) (x f : Γ(X, U)) - (H : x |_ᵣ (X.basicOpen f) = 0) : + (H : x |_ (X.basicOpen f) = 0) : ∃ n : ℕ, f ^ n * x = 0 := by obtain ⟨s, hs, e⟩ := (isCompactOpen_iff_eq_finset_affine_union U.1).mp ⟨hU, U.2⟩ replace e : U = iSup fun i : s => (i : X.Opens) := by @@ -311,12 +311,12 @@ lemma Scheme.isNilpotent_iff_basicOpen_eq_bot_of_isCompact {X : Scheme.{u}} {U : X.Opens} (hU : IsCompact (U : Set X)) (f : Γ(X, U)) : IsNilpotent f ↔ X.basicOpen f = ⊥ := by refine ⟨X.basicOpen_eq_bot_of_isNilpotent U f, fun hf ↦ ?_⟩ - have h : (1 : Γ(X, U)) |_ᵣ (X.basicOpen f) = 0 := by + have h : (1 : Γ(X, U)) |_ (X.basicOpen f) = 0 := by have e : X.basicOpen f ≤ ⊥ := by rw [hf] - rw [← CommRingCat.presheaf_restrict_restrict X e bot_le] + rw [← TopCat.Presheaf.restrict_restrict e bot_le] have : Subsingleton Γ(X, ⊥) := CommRingCat.subsingleton_of_isTerminal X.sheaf.isTerminalOfEmpty - rw [Subsingleton.eq_zero (1 |_ᵣ ⊥)] + rw [Subsingleton.eq_zero (1 |_ ⊥)] show X.presheaf.map _ 0 = 0 rw [map_zero] obtain ⟨n, hn⟩ := exists_pow_mul_eq_zero_of_res_basicOpen_eq_zero_of_isCompact X hU 1 f h diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean index 5ca1ecc198340..1a8fab9fd2701 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean @@ -185,11 +185,10 @@ theorem QuasiSeparated.of_comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [Qua theorem exists_eq_pow_mul_of_isAffineOpen (X : Scheme) (U : X.Opens) (hU : IsAffineOpen U) (f : Γ(X, U)) (x : Γ(X, X.basicOpen f)) : - ∃ (n : ℕ) (y : Γ(X, U)), y |_ᵣ X.basicOpen f = (f |_ᵣ X.basicOpen f) ^ n * x := by + ∃ (n : ℕ) (y : Γ(X, U)), y |_ X.basicOpen f = (f |_ X.basicOpen f) ^ n * x := by have := (hU.isLocalization_basicOpen f).2 obtain ⟨⟨y, _, n, rfl⟩, d⟩ := this x use n, y - dsimp only [TopCat.Presheaf.restrictOpenCommRingCat_apply] simpa [mul_comm x] using d.symm theorem exists_eq_pow_mul_of_is_compact_of_quasi_separated_space_aux_aux {X : TopCat} @@ -197,11 +196,11 @@ theorem exists_eq_pow_mul_of_is_compact_of_quasi_separated_space_aux_aux {X : To {y₁ : F.obj (op U₁)} {y₂ : F.obj (op U₂)} {f : F.obj (op <| U₁ ⊔ U₂)} {x : F.obj (op U₃)} (h₄₁ : U₄ ≤ U₁) (h₄₂ : U₄ ≤ U₂) (h₅₁ : U₅ ≤ U₁) (h₅₃ : U₅ ≤ U₃) (h₆₂ : U₆ ≤ U₂) (h₆₃ : U₆ ≤ U₃) (h₇₄ : U₇ ≤ U₄) (h₇₅ : U₇ ≤ U₅) (h₇₆ : U₇ ≤ U₆) - (e₁ : y₁ |_ᵣ U₅ = (f |_ᵣ U₁ |_ᵣ U₅) ^ n₁ * x |_ᵣ U₅) - (e₂ : y₂ |_ᵣ U₆ = (f |_ᵣ U₂ |_ᵣ U₆) ^ n₂ * x |_ᵣ U₆) : - (((f |_ᵣ U₁) ^ n₂ * y₁) |_ᵣ U₄) |_ᵣ U₇ = (((f |_ᵣ U₂) ^ n₁ * y₂) |_ᵣ U₄) |_ᵣ U₇ := by - apply_fun (fun x : F.obj (op U₅) ↦ x |_ᵣ U₇) at e₁ - apply_fun (fun x : F.obj (op U₆) ↦ x |_ᵣ U₇) at e₂ + (e₁ : y₁ |_ U₅ = (f |_ U₁ |_ U₅) ^ n₁ * x |_ U₅) + (e₂ : y₂ |_ U₆ = (f |_ U₂ |_ U₆) ^ n₂ * x |_ U₆) : + (((f |_ U₁) ^ n₂ * y₁) |_ U₄) |_ U₇ = (((f |_ U₂) ^ n₁ * y₂) |_ U₄) |_ U₇ := by + apply_fun (fun x : F.obj (op U₅) ↦ x |_ U₇) at e₁ + apply_fun (fun x : F.obj (op U₆) ↦ x |_ U₇) at e₂ dsimp only [TopCat.Presheaf.restrictOpenCommRingCat_apply] at e₁ e₂ ⊢ simp only [map_mul, map_pow, ← op_comp, ← F.map_comp, homOfLE_comp, ← CommRingCat.comp_apply] at e₁ e₂ ⊢ @@ -211,17 +210,17 @@ theorem exists_eq_pow_mul_of_is_compact_of_quasi_separated_space_aux (X : Scheme (S : X.affineOpens) (U₁ U₂ : X.Opens) {n₁ n₂ : ℕ} {y₁ : Γ(X, U₁)} {y₂ : Γ(X, U₂)} {f : Γ(X, U₁ ⊔ U₂)} {x : Γ(X, X.basicOpen f)} (h₁ : S.1 ≤ U₁) (h₂ : S.1 ≤ U₂) - (e₁ : y₁ |_ᵣ X.basicOpen (f |_ᵣ U₁) = - ((f |_ᵣ U₁ |_ᵣ X.basicOpen _) ^ n₁) * x |_ᵣ X.basicOpen _) - (e₂ : y₂ |_ᵣ X.basicOpen (f |_ᵣ U₂) = - ((f |_ᵣ U₂ |_ᵣ X.basicOpen _) ^ n₂) * x |_ᵣ X.basicOpen _) : + (e₁ : y₁ |_ X.basicOpen (f |_ U₁) = + ((f |_ U₁ |_ X.basicOpen _) ^ n₁) * x |_ X.basicOpen _) + (e₂ : y₂ |_ X.basicOpen (f |_ U₂) = + ((f |_ U₂ |_ X.basicOpen _) ^ n₂) * x |_ X.basicOpen _) : ∃ n : ℕ, ∀ m, n ≤ m → - ((f |_ᵣ U₁) ^ (m + n₂) * y₁) |_ᵣ S.1 = ((f |_ᵣ U₂) ^ (m + n₁) * y₂) |_ᵣ S.1 := by + ((f |_ U₁) ^ (m + n₂) * y₁) |_ S.1 = ((f |_ U₂) ^ (m + n₁) * y₂) |_ S.1 := by obtain ⟨⟨_, n, rfl⟩, e⟩ := (@IsLocalization.eq_iff_exists _ _ _ _ _ _ - (S.2.isLocalization_basicOpen (f |_ᵣ S.1)) - (((f |_ᵣ U₁) ^ n₂ * y₁) |_ᵣ S.1) - (((f |_ᵣ U₂) ^ n₁ * y₂) |_ᵣ S.1)).mp <| by + (S.2.isLocalization_basicOpen (f |_ S.1)) + (((f |_ U₁) ^ n₂ * y₁) |_ S.1) + (((f |_ U₂) ^ n₁ * y₂) |_ S.1)).mp <| by apply exists_eq_pow_mul_of_is_compact_of_quasi_separated_space_aux_aux (e₁ := e₁) (e₂ := e₂) · show X.basicOpen _ ≤ _ simp only [TopCat.Presheaf.restrictOpenCommRingCat_apply, Scheme.basicOpen_res] @@ -239,7 +238,7 @@ theorem exists_eq_pow_mul_of_is_compact_of_quasi_separated_space_aux (X : Scheme theorem exists_eq_pow_mul_of_isCompact_of_isQuasiSeparated (X : Scheme.{u}) (U : X.Opens) (hU : IsCompact U.1) (hU' : IsQuasiSeparated U.1) (f : Γ(X, U)) (x : Γ(X, X.basicOpen f)) : - ∃ (n : ℕ) (y : Γ(X, U)), y |_ᵣ X.basicOpen f = (f |_ᵣ X.basicOpen f) ^ n * x := by + ∃ (n : ℕ) (y : Γ(X, U)), y |_ X.basicOpen f = (f |_ X.basicOpen f) ^ n * x := by dsimp only [TopCat.Presheaf.restrictOpenCommRingCat_apply] revert hU' f x refine compact_open_induction_on U hU ?_ ?_ @@ -347,19 +346,19 @@ theorem is_localization_basicOpen_of_qcqs {X : Scheme} {U : X.Opens} (hU : IsCom lemma exists_of_res_eq_of_qcqs {X : Scheme.{u}} {U : TopologicalSpace.Opens X} (hU : IsCompact U.carrier) (hU' : IsQuasiSeparated U.carrier) - {f g s : Γ(X, U)} (hfg : f |_ᵣ X.basicOpen s = g |_ᵣ X.basicOpen s) : + {f g s : Γ(X, U)} (hfg : f |_ X.basicOpen s = g |_ X.basicOpen s) : ∃ n, s ^ n * f = s ^ n * g := by obtain ⟨n, hc⟩ := (is_localization_basicOpen_of_qcqs hU hU' s).exists_of_eq s hfg use n lemma exists_of_res_eq_of_qcqs_of_top {X : Scheme.{u}} [CompactSpace X] [QuasiSeparatedSpace X] - {f g s : Γ(X, ⊤)} (hfg : f |_ᵣ X.basicOpen s = g |_ᵣ X.basicOpen s) : + {f g s : Γ(X, ⊤)} (hfg : f |_ X.basicOpen s = g |_ X.basicOpen s) : ∃ n, s ^ n * f = s ^ n * g := exists_of_res_eq_of_qcqs (U := ⊤) CompactSpace.isCompact_univ isQuasiSeparated_univ hfg lemma exists_of_res_zero_of_qcqs {X : Scheme.{u}} {U : TopologicalSpace.Opens X} (hU : IsCompact U.carrier) (hU' : IsQuasiSeparated U.carrier) - {f s : Γ(X, U)} (hf : f |_ᵣ X.basicOpen s = 0) : + {f s : Γ(X, U)} (hf : f |_ X.basicOpen s = 0) : ∃ n, s ^ n * f = 0 := by suffices h : ∃ n, s ^ n * f = s ^ n * 0 by simpa using h @@ -367,7 +366,7 @@ lemma exists_of_res_zero_of_qcqs {X : Scheme.{u}} {U : TopologicalSpace.Opens X} simpa lemma exists_of_res_zero_of_qcqs_of_top {X : Scheme} [CompactSpace X] [QuasiSeparatedSpace X] - {f s : Γ(X, ⊤)} (hf : f |_ᵣ X.basicOpen s = 0) : + {f s : Γ(X, ⊤)} (hf : f |_ X.basicOpen s = 0) : ∃ n, s ^ n * f = 0 := exists_of_res_zero_of_qcqs (U := ⊤) CompactSpace.isCompact_univ isQuasiSeparated_univ hf diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index 50a6ec8e3a3d0..6ab69b8308733 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -395,7 +395,7 @@ lemma isLocal_ringHomProperty_of_isLocalAtSource_of_isLocalAtTarget (CommRingCat.ofHom f) r)).mp (IsLocalAtTarget.restrict H (basicOpen r)) · intros R S _ _ f s hs H apply IsLocalAtSource.of_openCover (Scheme.affineOpenCoverOfSpanRangeEqTop - (R := CommRingCat.of S) (ι := s) (fun i : s ↦ (i : S)) (by simpa)).openCover + (fun i : s ↦ (i : S)) (by simpa)).openCover intro i simp only [CommRingCat.coe_of, Set.setOf_mem_eq, id_eq, eq_mpr_eq_cast, Scheme.AffineOpenCover.openCover_obj, Scheme.affineOpenCoverOfSpanRangeEqTop_obj_carrier, diff --git a/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean index 79e2e54a20a2b..b48dcf53606e8 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean @@ -39,7 +39,7 @@ theorem Scheme.Hom.stalkMap_surjective (f : X.Hom Y) [SurjectiveOnStalks f] (x) namespace SurjectiveOnStalks instance (priority := 900) [IsOpenImmersion f] : SurjectiveOnStalks f := - ⟨fun _ ↦ (ConcreteCategory.bijective_of_isIso (C := CommRingCat) _).2⟩ + ⟨fun _ ↦ (ConcreteCategory.bijective_of_isIso _).2⟩ instance : MorphismProperty.IsMultiplicative @SurjectiveOnStalks where id_mem _ := inferInstance diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index 6acbeea9a53e1..8b4bf90918159 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -548,8 +548,7 @@ theorem basicOpen_le : X.basicOpen f ≤ U := @[sheaf_restrict] lemma basicOpen_restrict (i : V ⟶ U) (f : Γ(X, U)) : - -- Help `restrict` to infer which forgetful functor we're taking - X.basicOpen (TopCat.Presheaf.restrict (C := CommRingCat) f i) ≤ X.basicOpen f := + X.basicOpen (TopCat.Presheaf.restrict f i) ≤ X.basicOpen f := (Scheme.basicOpen_res _ _ _).trans_le inf_le_right @[simp] diff --git a/Mathlib/AlgebraicGeometry/Sites/SmallAffineZariski.lean b/Mathlib/AlgebraicGeometry/Sites/SmallAffineZariski.lean index 04ec6147501ff..c80ae9d09ae17 100644 --- a/Mathlib/AlgebraicGeometry/Sites/SmallAffineZariski.lean +++ b/Mathlib/AlgebraicGeometry/Sites/SmallAffineZariski.lean @@ -155,7 +155,7 @@ lemma generate_presieveOfSections rw [X.basicOpen_mul, hf₃, inf_eq_right] exact X.basicOpen_le _ · rintro ⟨f₁, hf₁s, f₂, rfl⟩ - refine ⟨U.basicOpen f₁, ⟨f₂ |_ᵣ _, ?_⟩, ⟨f₁, rfl⟩, ⟨f₁, hf₁s, rfl⟩, rfl⟩ + refine ⟨U.basicOpen f₁, ⟨f₂ |_ _, ?_⟩, ⟨f₁, rfl⟩, ⟨f₁, hf₁s, rfl⟩, rfl⟩ exact (X.basicOpen_res _ _).trans (X.basicOpen_mul _ _).symm lemma generate_presieveOfSections_mem_grothendieckTopology diff --git a/Mathlib/AlgebraicGeometry/SpreadingOut.lean b/Mathlib/AlgebraicGeometry/SpreadingOut.lean index 5a69939cbb517..1e892ae1a99ac 100644 --- a/Mathlib/AlgebraicGeometry/SpreadingOut.lean +++ b/Mathlib/AlgebraicGeometry/SpreadingOut.lean @@ -211,7 +211,7 @@ lemma spread_out_unique_of_isGermInjective {x : X} [X.IsGermInjectiveAt x] congr 2 apply this <;> simp rintro U V rfl rfl - have := ConcreteCategory.mono_of_injective (C := CommRingCat) _ HU + have := ConcreteCategory.mono_of_injective _ HU rw [← cancel_mono (X.presheaf.germ U x hxU)] simp only [Scheme.Hom.appLE, Category.assoc, X.presheaf.germ_res', ← Scheme.stalkMap_germ, H] simp only [TopCat.Presheaf.germ_stalkSpecializes_assoc, Scheme.stalkMap_germ] diff --git a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean index a9c0591e29d4f..8cf460d004592 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean @@ -312,7 +312,6 @@ def smoothSheafCommRing.forgetStalk (x : TopCat.of M) : (colimit.ι ((OpenNhds.inclusion x).op ⋙ (smoothSheafCommRing IM I M R).presheaf) U) := by rw [Iso.comp_inv_eq, ← smoothSheafCommRing.ι_forgetStalk_hom, CommRingCat.forget_map] simp_rw [Functor.comp_obj, Functor.op_obj] - rfl /-- Given a smooth commutative ring `R` and a manifold `M`, and an open neighbourhood `U` of a point `x : M`, the evaluation-at-`x` map to `R` from smooth functions from `U` to `R`. -/ diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean index a3b61da96f50c..e05dffc7df37d 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean @@ -226,8 +226,7 @@ theorem coequalizer_π_stalk_isLocalHom (x : Y) : IsLocalHom ((coequalizer.π f.toShHom g.toShHom :).stalkMap x).hom := by constructor rintro a ha - rcases TopCat.Presheaf.germ_exist (C := CommRingCat) _ _ a with ⟨U, hU, s, rfl⟩ - -- need `erw` to see through `ConcreteCategory.instFunLike` + rcases TopCat.Presheaf.germ_exist _ _ a with ⟨U, hU, s, rfl⟩ rw [← CommRingCat.forget_map_apply, PresheafedSpace.stalkMap_germ_apply (coequalizer.π (C := SheafedSpace _) f.toShHom g.toShHom) U _ hU] at ha rw [CommRingCat.forget_map_apply] diff --git a/Mathlib/Topology/Sheaves/CommRingCat.lean b/Mathlib/Topology/Sheaves/CommRingCat.lean index 0b46eb90f16d8..3cb0213a5e86e 100644 --- a/Mathlib/Topology/Sheaves/CommRingCat.lean +++ b/Mathlib/Topology/Sheaves/CommRingCat.lean @@ -47,37 +47,44 @@ example (X : TopCat.{u₁}) (F : Presheaf CommRingCat.{u₁} X) F.IsSheaf := (isSheaf_iff_isSheaf_comp (forget CommRingCat) F).mpr h -/-- -Specialize `restrictOpen` to `CommRingCat` because inferring `C := CommRingCat` isn't reliable. -Instead of unfolding the definition, rewrite with `restrictOpenCommRingCat_apply` to ensure the -correct coercion to functions is taken. +/-- Deprecated: usage of this definition should be replaceable with `TopCat.Presheaf.restrictOpen`. + +Before, we had to specialze `restrictOpen` to `CommRingCat` because inferring `C := CommRingCat` +was not reliable. Unification hints appear to solve that issue. + +The following still holds for `restrictOpen`: instead of unfolding the definition, rewrite with +`restrictOpenCommRingCat_apply` to ensure the correct coercion to functions is taken. (The correct fix in the longer term is to redesign concrete categories so we don't use `forget` everywhere, but the correct `FunLike` instance for the morphisms of those categories.) -/ +@[deprecated TopCat.Presheaf.restrictOpen (since := "2024-12-19")] abbrev restrictOpenCommRingCat {X : TopCat} {F : Presheaf CommRingCat X} {V : Opens ↑X} (f : CommRingCat.carrier (F.obj (op V))) (U : Opens ↑X) (e : U ≤ V := by restrict_tac) : CommRingCat.carrier (F.obj (op U)) := - TopCat.Presheaf.restrictOpen (C := CommRingCat) f U e - -/-- Notation for `TopCat.Presheaf.restrictOpenCommRingCat`. -/ -scoped[AlgebraicGeometry] infixl:80 " |_ᵣ " => TopCat.Presheaf.restrictOpenCommRingCat + TopCat.Presheaf.restrictOpen f U e open AlgebraicGeometry in +/-- Unfold `restrictOpen` in the category of commutative rings (with the correct carrier type). + +Although unification hints help with applying `TopCat.Presheaf.restrictOpenCommRingCat`, +so it can be safely de-specialized, this lemma needs to be kept to ensure rewrites go right. +-/ lemma restrictOpenCommRingCat_apply {X : TopCat} {F : Presheaf CommRingCat X} {V : Opens ↑X} (f : CommRingCat.carrier (F.obj (op V))) (U : Opens ↑X) (e : U ≤ V := by restrict_tac) : - f |_ᵣ U = F.map (homOfLE e).op f := + f |_ U = F.map (homOfLE e).op f := rfl open AlgebraicGeometry in +@[deprecated TopCat.Presheaf.restrict_restrict (since := "2024-12-19")] lemma _root_.CommRingCat.presheaf_restrict_restrict (X : TopCat) {F : TopCat.Presheaf CommRingCat X} {U V W : Opens ↑X} (e₁ : U ≤ V := by restrict_tac) (e₂ : V ≤ W := by restrict_tac) (f : CommRingCat.carrier (F.obj (op W))) : - f |_ᵣ V |_ᵣ U = f |_ᵣ U := - TopCat.Presheaf.restrict_restrict (C := CommRingCat) e₁ e₂ f + f |_ V |_ U = f |_ U := + TopCat.Presheaf.restrict_restrict e₁ e₂ f section SubmonoidPresheaf From ed8e9d039965aba1aa4d8bf507623265f039d3e0 Mon Sep 17 00:00:00 2001 From: L Date: Mon, 13 Jan 2025 14:29:38 +0000 Subject: [PATCH 201/681] fix: `apply H at h` when type of `H h` depends on proof of `h` (#20623) This scenario caused two issues: 1. We were deriving the type of `H h` using `forAllTelescopeReducing`, which does not know the proof of `h`, only the type. 2. We were `tryClear`ing `h` before applying `H`, which does not account for the dependency introduced by `H h` itself. Co-authored-by: L Lllvvuu Co-authored-by: L --- Mathlib/Tactic/ApplyAt.lean | 12 +++++------- MathlibTest/ApplyAt.lean | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Mathlib/Tactic/ApplyAt.lean b/Mathlib/Tactic/ApplyAt.lean index 1bf1be33a22a4..982eaf4df55b6 100644 --- a/Mathlib/Tactic/ApplyAt.lean +++ b/Mathlib/Tactic/ApplyAt.lean @@ -27,16 +27,14 @@ elab "apply" t:term "at" i:ident : tactic => withSynthesize <| withMainContext d let f ← elabTermForApply t let some ldecl := (← getLCtx).findFromUserName? i.getId | throwErrorAt i m!"Identifier {i} not found" - let (mvs, bis, tp) ← forallMetaTelescopeReducingUntilDefEq (← inferType f) ldecl.type - let mainGoal ← getMainGoal - let mainGoal ← mainGoal.tryClear ldecl.fvarId + let (mvs, bis, _) ← forallMetaTelescopeReducingUntilDefEq (← inferType f) ldecl.type for (m, b) in mvs.zip bis do if b.isInstImplicit && !(← m.mvarId!.isAssigned) then try m.mvarId!.inferInstance catch _ => continue - let mainGoal ← mainGoal.assert ldecl.userName tp - (← mkAppOptM' f (mvs.pop.push ldecl.toExpr |>.map fun e => some e)) - let (_, mainGoal) ← mainGoal.intro1P - replaceMainGoal <| [mainGoal] ++ mvs.pop.toList.map fun e => e.mvarId! + let (_, mainGoal) ← (← getMainGoal).note ldecl.userName + (← mkAppOptM' f (mvs.pop.push ldecl.toExpr |>.map some)) + let mainGoal ← mainGoal.tryClear ldecl.fvarId + replaceMainGoal <| [mainGoal] ++ mvs.pop.toList.map (·.mvarId!) end Mathlib.Tactic diff --git a/MathlibTest/ApplyAt.lean b/MathlibTest/ApplyAt.lean index bf0a909e59473..37e085a1115c4 100644 --- a/MathlibTest/ApplyAt.lean +++ b/MathlibTest/ApplyAt.lean @@ -105,3 +105,19 @@ example (a b : ℝ) (h : -a * b = 0) : a = 0 ∨ b = 0 := by apply (congrArg (fun x => x / 1)) at h simp at h assumption + +/-- `apply H at h` when type of `H h` depends on proof of `h` (#20623) -/ +example (h : True) : True := by + have H (h : True) : h = h := rfl + apply H at h + simp at h + exact h + +/-- `apply H at h` when type of `H h` depends on proof of `h` (#20623) -/ +example (a : List Nat) (k : Nat) (hk : k < a.length) : True := by + have H (k : Nat) {xs ys : List Nat} (hk: k < xs.length) + (h : xs = ys) : xs[k] = ys[k]'(h ▸ hk) := h ▸ rfl + have h : a = a.map id := by simp + apply H k hk at h + simp at h + exact h From 15255752cde670026ec41594d6039b6baa1c7f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 13 Jan 2025 14:29:40 +0000 Subject: [PATCH 202/681] chore(ENat): don't import fields (#20698) Not sure why this wasn't picked up by shake --- Mathlib/Algebra/Group/ConjFinite.lean | 2 ++ Mathlib/Algebra/Group/Pointwise/Set/Card.lean | 2 ++ Mathlib/Algebra/Group/Subgroup/Finite.lean | 2 ++ Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean | 2 ++ Mathlib/Combinatorics/SimpleGraph/Coloring.lean | 2 ++ Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean | 2 ++ .../Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean | 2 ++ Mathlib/Combinatorics/SimpleGraph/Diam.lean | 2 ++ Mathlib/Combinatorics/SimpleGraph/Metric.lean | 1 + Mathlib/Combinatorics/SimpleGraph/Partition.lean | 1 + Mathlib/Data/ENat/Basic.lean | 3 ++- Mathlib/Data/ENat/BigOperators.lean | 2 ++ Mathlib/Data/ENat/Lattice.lean | 2 ++ Mathlib/Data/Finite/Card.lean | 1 + Mathlib/Data/Fintype/Units.lean | 1 + Mathlib/Data/Matroid/Basic.lean | 2 ++ Mathlib/Data/Matroid/Closure.lean | 2 ++ Mathlib/Data/Matroid/Constructions.lean | 2 ++ Mathlib/Data/Matroid/Dual.lean | 2 ++ Mathlib/Data/Matroid/IndepAxioms.lean | 2 ++ Mathlib/Data/Matroid/Map.lean | 2 ++ Mathlib/Data/Matroid/Restrict.lean | 2 ++ Mathlib/Data/Matroid/Sum.lean | 2 ++ Mathlib/GroupTheory/CommutingProbability.lean | 1 + Mathlib/GroupTheory/Coset/Card.lean | 2 ++ Mathlib/GroupTheory/HNNExtension.lean | 1 + Mathlib/GroupTheory/SpecificGroups/Alternating.lean | 3 ++- Mathlib/NumberTheory/Padics/PadicVal/Defs.lean | 2 ++ Mathlib/Order/Height.lean | 1 + Mathlib/Order/KrullDimension.lean | 2 ++ Mathlib/RingTheory/Multiplicity.lean | 2 ++ Mathlib/SetTheory/Cardinal/Aleph.lean | 2 +- Mathlib/SetTheory/Cardinal/ENat.lean | 2 ++ Mathlib/SetTheory/Cardinal/Finite.lean | 2 ++ Mathlib/SetTheory/Cardinal/ToNat.lean | 2 ++ 35 files changed, 62 insertions(+), 3 deletions(-) diff --git a/Mathlib/Algebra/Group/ConjFinite.lean b/Mathlib/Algebra/Group/ConjFinite.lean index 75b02165e48f9..86c5b5228d46f 100644 --- a/Mathlib/Algebra/Group/ConjFinite.lean +++ b/Mathlib/Algebra/Group/ConjFinite.lean @@ -10,6 +10,8 @@ import Mathlib.Data.Fintype.Units # Conjugacy of elements of finite groups -/ +assert_not_exists Field + -- TODO: the following `assert_not_exists` should work, but does not -- assert_not_exists MonoidWithZero diff --git a/Mathlib/Algebra/Group/Pointwise/Set/Card.lean b/Mathlib/Algebra/Group/Pointwise/Set/Card.lean index d6ccb0c30a835..c0105abec2601 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set/Card.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/Card.lean @@ -11,6 +11,8 @@ import Mathlib.SetTheory.Cardinal.Finite # Cardinalities of pointwise operations on sets -/ +assert_not_exists Field + open scoped Cardinal Pointwise namespace Set diff --git a/Mathlib/Algebra/Group/Subgroup/Finite.lean b/Mathlib/Algebra/Group/Subgroup/Finite.lean index 092fb9835528b..47f813cda8580 100644 --- a/Mathlib/Algebra/Group/Subgroup/Finite.lean +++ b/Mathlib/Algebra/Group/Subgroup/Finite.lean @@ -17,6 +17,8 @@ This file provides some result on multiplicative and additive subgroups in the f subgroup, subgroups -/ +assert_not_exists Field + variable {G : Type*} [Group G] variable {A : Type*} [AddGroup A] diff --git a/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean index 4e144b113a816..90856fbc7d2c0 100644 --- a/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean +++ b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean @@ -11,6 +11,8 @@ import Mathlib.SetTheory.Cardinal.Finite # Cardinality of sets under pointwise group with zero operations -/ +assert_not_exists Field + open scoped Cardinal Pointwise variable {G₀ M₀ : Type*} diff --git a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean index 7f5fe6d81b937..ad526f0fa08e0 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean @@ -53,6 +53,8 @@ the colors. * develop API for partial colorings, likely as colorings of subgraphs (`H.coe.Coloring α`) -/ +assert_not_exists Field + open Fintype Function universe u v diff --git a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean index fdb7e6b18af60..c3b78c334c5d1 100644 --- a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean +++ b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean @@ -17,6 +17,8 @@ This file defines colorings for some common graphs -/ +assert_not_exists Field + namespace SimpleGraph theorem two_le_chromaticNumber_of_adj {α} {G : SimpleGraph α} {u v : α} (hAdj : G.Adj u v) : diff --git a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean index 10adfe87aff11..23da61daf88c3 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean @@ -22,6 +22,8 @@ can also be useful as a recursive description of this set when `V` is finite. TODO: should this be extended further? -/ +assert_not_exists Field + open Finset Function universe u v w diff --git a/Mathlib/Combinatorics/SimpleGraph/Diam.lean b/Mathlib/Combinatorics/SimpleGraph/Diam.lean index 7e6b6d1920a5b..046c1bef655d6 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Diam.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Diam.lean @@ -24,6 +24,8 @@ vertices. -/ +assert_not_exists Field + namespace SimpleGraph variable {α : Type*} {G G' : SimpleGraph α} diff --git a/Mathlib/Combinatorics/SimpleGraph/Metric.lean b/Mathlib/Combinatorics/SimpleGraph/Metric.lean index 2f95492e595b1..348dcfeb6ad55 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Metric.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Metric.lean @@ -32,6 +32,7 @@ graph metric, distance -/ +assert_not_exists Field namespace SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Partition.lean b/Mathlib/Combinatorics/SimpleGraph/Partition.lean index 15f9c01e4e30f..f0e20a0f3bf58 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Partition.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Partition.lean @@ -42,6 +42,7 @@ graph colorings and back is the identity. -/ +assert_not_exists Field universe u v diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index 99492bb51fbaf..a2e20f7680348 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -3,7 +3,6 @@ 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.Algebra.CharZero.Lemmas import Mathlib.Algebra.Order.Ring.WithTop import Mathlib.Algebra.Order.Sub.WithTop import Mathlib.Data.ENat.Defs @@ -33,6 +32,8 @@ for all `b`), or that it's order-cancellable (`a + b ≤ a + c → b ≤ c` for similarly for multiplication. -/ +assert_not_exists Field + deriving instance Zero, CanonicallyOrderedCommSemiring, Nontrivial, LinearOrder, Bot, CanonicallyLinearOrderedAddCommMonoid, Sub, LinearOrderedAddCommMonoidWithTop, WellFoundedRelation diff --git a/Mathlib/Data/ENat/BigOperators.lean b/Mathlib/Data/ENat/BigOperators.lean index 479967f5c99f0..30d3a2149bc21 100644 --- a/Mathlib/Data/ENat/BigOperators.lean +++ b/Mathlib/Data/ENat/BigOperators.lean @@ -10,6 +10,8 @@ import Mathlib.Data.ENat.Lattice # Sum of suprema in `ENat` -/ +assert_not_exists Field + namespace ENat lemma sum_iSup {α ι : Type*} {s : Finset α} {f : α → ι → ℕ∞} diff --git a/Mathlib/Data/ENat/Lattice.lean b/Mathlib/Data/ENat/Lattice.lean index fd0d60e48e317..c6cd1ba359cbf 100644 --- a/Mathlib/Data/ENat/Lattice.lean +++ b/Mathlib/Data/ENat/Lattice.lean @@ -23,6 +23,8 @@ corresponding `noshake.json` entry. -/ +assert_not_exists Field + open Set -- Porting note: was `deriving instance` but "default handlers have not been implemented yet" diff --git a/Mathlib/Data/Finite/Card.lean b/Mathlib/Data/Finite/Card.lean index c47971873d694..626fa23819d85 100644 --- a/Mathlib/Data/Finite/Card.lean +++ b/Mathlib/Data/Finite/Card.lean @@ -25,6 +25,7 @@ it. We generally put such theorems into the `SetTheory.Cardinal.Finite` module. -/ +assert_not_exists Field noncomputable section diff --git a/Mathlib/Data/Fintype/Units.lean b/Mathlib/Data/Fintype/Units.lean index 114794a2f6663..0385c6dd5919b 100644 --- a/Mathlib/Data/Fintype/Units.lean +++ b/Mathlib/Data/Fintype/Units.lean @@ -12,6 +12,7 @@ import Mathlib.SetTheory.Cardinal.Finite # fintype instances relating to units -/ +assert_not_exists Field variable {α : Type*} diff --git a/Mathlib/Data/Matroid/Basic.lean b/Mathlib/Data/Matroid/Basic.lean index c18992ac8b4c4..54558d4e57700 100644 --- a/Mathlib/Data/Matroid/Basic.lean +++ b/Mathlib/Data/Matroid/Basic.lean @@ -166,6 +166,8 @@ There are a few design decisions worth discussing. Proc. Amer. Math. Soc. 144 (2016), 459-471] -/ +assert_not_exists Field + open Set /-- A predicate `P` on sets satisfies the **exchange property** if, diff --git a/Mathlib/Data/Matroid/Closure.lean b/Mathlib/Data/Matroid/Closure.lean index 534a3d8ddbc12..4dec4fadae6e9 100644 --- a/Mathlib/Data/Matroid/Closure.lean +++ b/Mathlib/Data/Matroid/Closure.lean @@ -76,6 +76,8 @@ In lemma names, the words `spanning` and `flat` are used as suffixes, for instance we have `ground_spanning` rather than `spanning_ground`. -/ +assert_not_exists Field + open Set namespace Matroid diff --git a/Mathlib/Data/Matroid/Constructions.lean b/Mathlib/Data/Matroid/Constructions.lean index 03e7c13276938..2d46aa252305c 100644 --- a/Mathlib/Data/Matroid/Constructions.lean +++ b/Mathlib/Data/Matroid/Constructions.lean @@ -29,6 +29,8 @@ and then construct the other examples using duality and restriction. -/ +assert_not_exists Field + variable {α : Type*} {M : Matroid α} {E B I X R J : Set α} namespace Matroid diff --git a/Mathlib/Data/Matroid/Dual.lean b/Mathlib/Data/Matroid/Dual.lean index 58c8ba4c472f3..a6b523bb31bc1 100644 --- a/Mathlib/Data/Matroid/Dual.lean +++ b/Mathlib/Data/Matroid/Dual.lean @@ -28,6 +28,8 @@ This is an abbreviation for `M✶.Indep X`, but has its own name for the sake of base `B` of `M`. -/ +assert_not_exists Field + open Set namespace Matroid diff --git a/Mathlib/Data/Matroid/IndepAxioms.lean b/Mathlib/Data/Matroid/IndepAxioms.lean index 88e6c6559ce67..562ae11604dbd 100644 --- a/Mathlib/Data/Matroid/IndepAxioms.lean +++ b/Mathlib/Data/Matroid/IndepAxioms.lean @@ -82,6 +82,8 @@ for the inverse of `e`). * `Matroid.ofBaseOfFinite` constructs a `Finite` matroid from its bases. -/ +assert_not_exists Field + open Set Matroid variable {α : Type*} diff --git a/Mathlib/Data/Matroid/Map.lean b/Mathlib/Data/Matroid/Map.lean index 0c72f58c69915..4994c430791a5 100644 --- a/Mathlib/Data/Matroid/Map.lean +++ b/Mathlib/Data/Matroid/Map.lean @@ -101,6 +101,8 @@ For this reason, `Matroid.map` requires injectivity to be well-defined in genera * [J. Oxley, Matroid Theory][oxley2011] -/ +assert_not_exists Field + open Set Function Set.Notation namespace Matroid variable {α β : Type*} {f : α → β} {E I : Set α} {M : Matroid α} {N : Matroid β} diff --git a/Mathlib/Data/Matroid/Restrict.lean b/Mathlib/Data/Matroid/Restrict.lean index beaa2c286c9ee..1eed5c8f2b783 100644 --- a/Mathlib/Data/Matroid/Restrict.lean +++ b/Mathlib/Data/Matroid/Restrict.lean @@ -62,6 +62,8 @@ We define the restriction order `≤r` to give a `PartialOrder` instance on the reserved for the more mathematically important 'minor' order. -/ +assert_not_exists Field + open Set namespace Matroid diff --git a/Mathlib/Data/Matroid/Sum.lean b/Mathlib/Data/Matroid/Sum.lean index 99c771b42c302..045fa56354a59 100644 --- a/Mathlib/Data/Matroid/Sum.lean +++ b/Mathlib/Data/Matroid/Sum.lean @@ -40,6 +40,8 @@ We only directly define a matroid for `Matroid.sigma`. All other versions of sum defined indirectly, using `Matroid.sigma` and the API in `Matroid.map`. -/ +assert_not_exists Field + universe u v open Set diff --git a/Mathlib/GroupTheory/CommutingProbability.lean b/Mathlib/GroupTheory/CommutingProbability.lean index 5e9481a5ee9dd..606360fa0cce6 100644 --- a/Mathlib/GroupTheory/CommutingProbability.lean +++ b/Mathlib/GroupTheory/CommutingProbability.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Thomas Browning. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning -/ +import Mathlib.Algebra.CharZero.Lemmas import Mathlib.GroupTheory.Abelianization import Mathlib.GroupTheory.GroupAction.CardCommute import Mathlib.GroupTheory.SpecificGroups.Dihedral diff --git a/Mathlib/GroupTheory/Coset/Card.lean b/Mathlib/GroupTheory/Coset/Card.lean index 4a76b7a706ad4..e136b4c656e3b 100644 --- a/Mathlib/GroupTheory/Coset/Card.lean +++ b/Mathlib/GroupTheory/Coset/Card.lean @@ -14,6 +14,8 @@ there is an analogous version for additive groups -/ +assert_not_exists Field + open scoped Pointwise namespace Subgroup diff --git a/Mathlib/GroupTheory/HNNExtension.lean b/Mathlib/GroupTheory/HNNExtension.lean index def2ac3cf71c4..74e53d4f30f72 100644 --- a/Mathlib/GroupTheory/HNNExtension.lean +++ b/Mathlib/GroupTheory/HNNExtension.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ +import Mathlib.Algebra.CharZero.Lemmas import Mathlib.Algebra.Ring.Int.Units import Mathlib.GroupTheory.Coprod.Basic import Mathlib.GroupTheory.Complement diff --git a/Mathlib/GroupTheory/SpecificGroups/Alternating.lean b/Mathlib/GroupTheory/SpecificGroups/Alternating.lean index f24b630fe1377..fccb3ab3bc881 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Alternating.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Alternating.lean @@ -3,10 +3,11 @@ Copyright (c) 2021 Aaron Anderson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ +import Mathlib.Algebra.CharZero.Lemmas +import Mathlib.Data.Fintype.Units import Mathlib.GroupTheory.Perm.Fin import Mathlib.GroupTheory.Subgroup.Simple import Mathlib.Tactic.IntervalCases -import Mathlib.Data.Fintype.Units /-! # Alternating Groups diff --git a/Mathlib/NumberTheory/Padics/PadicVal/Defs.lean b/Mathlib/NumberTheory/Padics/PadicVal/Defs.lean index 14fe173f895f0..46c363d9d0744 100644 --- a/Mathlib/NumberTheory/Padics/PadicVal/Defs.lean +++ b/Mathlib/NumberTheory/Padics/PadicVal/Defs.lean @@ -18,6 +18,8 @@ assumptions on `p`. The `p`-adic valuations on `ℕ` and `ℤ` agree with that o The valuation induces a norm on `ℚ`. This norm is defined in padicNorm.lean. -/ +assert_not_exists Field + universe u open Nat diff --git a/Mathlib/Order/Height.lean b/Mathlib/Order/Height.lean index be2eaa7acd45b..9a649ab3c42c0 100644 --- a/Mathlib/Order/Height.lean +++ b/Mathlib/Order/Height.lean @@ -40,6 +40,7 @@ This is defined as the maximum of the lengths of `Set.subchain`s, valued in `ℕ -/ +assert_not_exists Field open List hiding le_antisymm open OrderDual diff --git a/Mathlib/Order/KrullDimension.lean b/Mathlib/Order/KrullDimension.lean index 23dd08f1755a0..aecd91615f063 100644 --- a/Mathlib/Order/KrullDimension.lean +++ b/Mathlib/Order/KrullDimension.lean @@ -59,6 +59,8 @@ in this file would generalize as well. But we don't think it would be useful, so Krull dimension of a preorder. -/ +assert_not_exists Field + namespace Order section definitions diff --git a/Mathlib/RingTheory/Multiplicity.lean b/Mathlib/RingTheory/Multiplicity.lean index 2f13dce766244..c006029fa2951 100644 --- a/Mathlib/RingTheory/Multiplicity.lean +++ b/Mathlib/RingTheory/Multiplicity.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis, Chris Hughes, Daniel Weber -/ +import Batteries.Data.Nat.Gcd import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Ring.Divisibility.Basic @@ -25,6 +26,7 @@ several basic results on it. * `FiniteMultiplicity a b`: a predicate denoting that the multiplicity of `a` in `b` is finite. -/ +assert_not_exists Field variable {α β : Type*} diff --git a/Mathlib/SetTheory/Cardinal/Aleph.lean b/Mathlib/SetTheory/Cardinal/Aleph.lean index 096a7dd858e7b..e9b56fbe383cd 100644 --- a/Mathlib/SetTheory/Cardinal/Aleph.lean +++ b/Mathlib/SetTheory/Cardinal/Aleph.lean @@ -34,7 +34,7 @@ The following notations are scoped to the `Cardinal` namespace. `Mathlib.SetTheory.Cardinal.Continuum`. -/ -assert_not_exists Module Finsupp Cardinal.mul_eq_self +assert_not_exists Field Finsupp Module Cardinal.mul_eq_self noncomputable section diff --git a/Mathlib/SetTheory/Cardinal/ENat.lean b/Mathlib/SetTheory/Cardinal/ENat.lean index 5ad5cee75b2b2..c9847f9d78705 100644 --- a/Mathlib/SetTheory/Cardinal/ENat.lean +++ b/Mathlib/SetTheory/Cardinal/ENat.lean @@ -28,6 +28,8 @@ Since it is not registered as a coercion, the argument about delaboration does n set theory, cardinals, extended natural numbers -/ +assert_not_exists Field + open Function Set universe u v diff --git a/Mathlib/SetTheory/Cardinal/Finite.lean b/Mathlib/SetTheory/Cardinal/Finite.lean index afde38acbd05c..679fe87704ff2 100644 --- a/Mathlib/SetTheory/Cardinal/Finite.lean +++ b/Mathlib/SetTheory/Cardinal/Finite.lean @@ -21,6 +21,8 @@ import Mathlib.SetTheory.Cardinal.ENat (using the legacy definition `PartENat := Part ℕ`). If `α` is infinite, `PartENat.card α = ⊤`. -/ +assert_not_exists Field + open Cardinal Function noncomputable section diff --git a/Mathlib/SetTheory/Cardinal/ToNat.lean b/Mathlib/SetTheory/Cardinal/ToNat.lean index 296a181875639..067da2369b629 100644 --- a/Mathlib/SetTheory/Cardinal/ToNat.lean +++ b/Mathlib/SetTheory/Cardinal/ToNat.lean @@ -13,6 +13,8 @@ sending all infinite cardinals to zero. We also prove basic lemmas about this definition. -/ +assert_not_exists Field + universe u v open Function Set From 3aa8ab5d284fe7be7676dcc63a9814744ed18c7b Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Mon, 13 Jan 2025 14:29:41 +0000 Subject: [PATCH 203/681] chore: split Mathlib.Topology.Instances.*Real (#20707) Splits each of these files for `Real/EReal/NNReal/ENNReal` into a `Defs` file, containing all the instances and minimal imports, and a `Lemmas` file with all the remaining current content. --- Mathlib.lean | 12 ++- .../AlgebraicTopology/TopologicalSimplex.lean | 2 +- Mathlib/Analysis/Asymptotics/TVS.lean | 2 +- Mathlib/Analysis/Complex/HalfPlane.lean | 2 +- Mathlib/Analysis/Normed/Field/Lemmas.lean | 4 +- .../Analysis/Normed/Group/InfiniteSum.lean | 2 +- Mathlib/Analysis/Normed/Group/Lemmas.lean | 2 +- Mathlib/Analysis/Normed/Group/Quotient.lean | 1 + .../Analysis/NormedSpace/FunctionSeries.lean | 2 +- Mathlib/Analysis/SpecificLimits/Basic.lean | 2 +- Mathlib/Analysis/SpecificLimits/Normed.lean | 1 + Mathlib/Analysis/Subadditive.lean | 2 +- Mathlib/Analysis/SumOverResidueClass.lean | 2 +- Mathlib/Data/Complex/Exponential.lean | 1 + Mathlib/Data/Complex/FiniteDimensional.lean | 1 + Mathlib/Data/Real/Sqrt.lean | 2 +- .../RotationNumber/TranslationNumber.lean | 1 + .../Constructions/BorelSpace/Basic.lean | 2 +- .../Constructions/BorelSpace/Real.lean | 1 + .../MeasureTheory/Decomposition/Jordan.lean | 1 + .../Integral/VitaliCaratheodory.lean | 2 +- Mathlib/MeasureTheory/Measure/Stieltjes.lean | 1 + Mathlib/MeasureTheory/OuterMeasure/Basic.lean | 1 + Mathlib/MeasureTheory/OuterMeasure/Defs.lean | 3 +- Mathlib/Order/Filter/ENNReal.lean | 3 +- .../ProbabilityMassFunction/Basic.lean | 2 +- .../Topology/Algebra/InfiniteSum/ENNReal.lean | 2 +- .../Topology/Algebra/InfiniteSum/Real.lean | 2 +- .../Algebra/Module/Multilinear/Topology.lean | 1 + Mathlib/Topology/Instances/CantorSet.lean | 2 +- Mathlib/Topology/Instances/ENNReal/Defs.lean | 74 ++++++++++++++ .../{ENNReal.lean => ENNReal/Lemmas.lean} | 48 +-------- Mathlib/Topology/Instances/EReal/Defs.lean | 47 +++++++++ .../{EReal.lean => EReal/Lemmas.lean} | 21 +--- Mathlib/Topology/Instances/Irrational.lean | 1 + Mathlib/Topology/Instances/NNReal/Defs.lean | 97 +++++++++++++++++++ .../{NNReal.lean => NNReal/Lemmas.lean} | 76 +-------------- Mathlib/Topology/Instances/Rat.lean | 2 +- Mathlib/Topology/Instances/Real/Defs.lean | 72 ++++++++++++++ .../Instances/{Real.lean => Real/Lemmas.lean} | 50 +--------- Mathlib/Topology/Instances/ZMultiples.lean | 2 +- Mathlib/Topology/MetricSpace/Completion.lean | 2 +- .../MetricSpace/PartitionOfUnity.lean | 2 +- Mathlib/Topology/Order/Bounded.lean | 2 +- Mathlib/Topology/Semicontinuous.lean | 2 +- Mathlib/Topology/UnitInterval.lean | 2 +- MathlibTest/LibrarySearch/IsCompact.lean | 2 +- MathlibTest/peel.lean | 2 +- 48 files changed, 349 insertions(+), 219 deletions(-) create mode 100644 Mathlib/Topology/Instances/ENNReal/Defs.lean rename Mathlib/Topology/Instances/{ENNReal.lean => ENNReal/Lemmas.lean} (97%) create mode 100644 Mathlib/Topology/Instances/EReal/Defs.lean rename Mathlib/Topology/Instances/{EReal.lean => EReal/Lemmas.lean} (96%) create mode 100644 Mathlib/Topology/Instances/NNReal/Defs.lean rename Mathlib/Topology/Instances/{NNReal.lean => NNReal/Lemmas.lean} (77%) create mode 100644 Mathlib/Topology/Instances/Real/Defs.lean rename Mathlib/Topology/Instances/{Real.lean => Real/Lemmas.lean} (73%) diff --git a/Mathlib.lean b/Mathlib.lean index 2c579f231ed42..fa54d686380e0 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5337,18 +5337,22 @@ import Mathlib.Topology.Instances.AddCircle import Mathlib.Topology.Instances.CantorSet import Mathlib.Topology.Instances.Complex import Mathlib.Topology.Instances.Discrete -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Defs +import Mathlib.Topology.Instances.ENNReal.Lemmas import Mathlib.Topology.Instances.ENat -import Mathlib.Topology.Instances.EReal +import Mathlib.Topology.Instances.EReal.Defs +import Mathlib.Topology.Instances.EReal.Lemmas import Mathlib.Topology.Instances.Int import Mathlib.Topology.Instances.Irrational import Mathlib.Topology.Instances.Matrix -import Mathlib.Topology.Instances.NNReal +import Mathlib.Topology.Instances.NNReal.Defs +import Mathlib.Topology.Instances.NNReal.Lemmas import Mathlib.Topology.Instances.Nat import Mathlib.Topology.Instances.PNat import Mathlib.Topology.Instances.Rat import Mathlib.Topology.Instances.RatLemmas -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Defs +import Mathlib.Topology.Instances.Real.Lemmas import Mathlib.Topology.Instances.RealVectorSpace import Mathlib.Topology.Instances.Sign import Mathlib.Topology.Instances.TrivSqZeroExt diff --git a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean index 9ec3a106004a8..09fc36541fc97 100644 --- a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean +++ b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean @@ -5,7 +5,7 @@ Authors: Johan Commelin, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplexCategory import Mathlib.Topology.Category.TopCat.Basic -import Mathlib.Topology.Instances.NNReal +import Mathlib.Topology.Instances.NNReal.Defs /-! # Topological simplices diff --git a/Mathlib/Analysis/Asymptotics/TVS.lean b/Mathlib/Analysis/Asymptotics/TVS.lean index e6a51f9b44c0b..744a9ff13285f 100644 --- a/Mathlib/Analysis/Asymptotics/TVS.lean +++ b/Mathlib/Analysis/Asymptotics/TVS.lean @@ -8,7 +8,7 @@ import Mathlib.Analysis.Convex.EGauge import Mathlib.Analysis.LocallyConvex.BalancedCoreHull import Mathlib.Analysis.Seminorm import Mathlib.Tactic.Peel -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Asymptotics in a Topological Vector Space diff --git a/Mathlib/Analysis/Complex/HalfPlane.lean b/Mathlib/Analysis/Complex/HalfPlane.lean index 6d590710728ab..d2cf605ce5148 100644 --- a/Mathlib/Analysis/Complex/HalfPlane.lean +++ b/Mathlib/Analysis/Complex/HalfPlane.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Stoll -/ import Mathlib.Analysis.Complex.Basic -import Mathlib.Topology.Instances.EReal +import Mathlib.Topology.Instances.EReal.Lemmas /-! # Half-planes in ℂ are open diff --git a/Mathlib/Analysis/Normed/Field/Lemmas.lean b/Mathlib/Analysis/Normed/Field/Lemmas.lean index 6d1e3ee50a059..70d24fb6b5aae 100644 --- a/Mathlib/Analysis/Normed/Field/Lemmas.lean +++ b/Mathlib/Analysis/Normed/Field/Lemmas.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Johannes Hölzl -/ - +import Mathlib.GroupTheory.OrderOfElement import Mathlib.Algebra.Group.AddChar import Mathlib.Algebra.Group.TypeTags.Finite import Mathlib.Algebra.Order.GroupWithZero.Finset @@ -11,8 +11,8 @@ import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Analysis.Normed.Group.Bounded import Mathlib.Analysis.Normed.Group.Rat import Mathlib.Analysis.Normed.Group.Uniform -import Mathlib.Topology.Instances.NNReal import Mathlib.Topology.MetricSpace.DilationEquiv +import Mathlib.Topology.Instances.NNReal.Defs /-! # Normed fields diff --git a/Mathlib/Analysis/Normed/Group/InfiniteSum.lean b/Mathlib/Analysis/Normed/Group/InfiniteSum.lean index 2eb196f059adf..10812f0670088 100644 --- a/Mathlib/Analysis/Normed/Group/InfiniteSum.lean +++ b/Mathlib/Analysis/Normed/Group/InfiniteSum.lean @@ -5,7 +5,7 @@ Authors: Sébastien Gouëzel, Heather Macbeth, Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.Intervals import Mathlib.Analysis.Normed.Group.Uniform -import Mathlib.Topology.Instances.NNReal +import Mathlib.Topology.Instances.NNReal.Lemmas /-! # Infinite sums in (semi)normed groups diff --git a/Mathlib/Analysis/Normed/Group/Lemmas.lean b/Mathlib/Analysis/Normed/Group/Lemmas.lean index a7ea8957c7fa1..cd22b8ce0e350 100644 --- a/Mathlib/Analysis/Normed/Group/Lemmas.lean +++ b/Mathlib/Analysis/Normed/Group/Lemmas.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot -/ import Mathlib.Analysis.Normed.Group.Uniform -import Mathlib.Topology.Instances.NNReal +import Mathlib.Topology.Instances.NNReal.Defs /-! # Further lemmas about normed groups diff --git a/Mathlib/Analysis/Normed/Group/Quotient.lean b/Mathlib/Analysis/Normed/Group/Quotient.lean index 0009c2a130e4e..d931b9c66849f 100644 --- a/Mathlib/Analysis/Normed/Group/Quotient.lean +++ b/Mathlib/Analysis/Normed/Group/Quotient.lean @@ -7,6 +7,7 @@ import Mathlib.Analysis.Normed.Module.Basic import Mathlib.Analysis.Normed.Group.Hom import Mathlib.RingTheory.Ideal.Quotient.Operations import Mathlib.Topology.MetricSpace.HausdorffDistance +import Mathlib.Topology.Instances.Real.Lemmas /-! # Quotients of seminormed groups diff --git a/Mathlib/Analysis/NormedSpace/FunctionSeries.lean b/Mathlib/Analysis/NormedSpace/FunctionSeries.lean index 3f07c20513c97..99a048f2d05da 100644 --- a/Mathlib/Analysis/NormedSpace/FunctionSeries.lean +++ b/Mathlib/Analysis/NormedSpace/FunctionSeries.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.Normed.Group.InfiniteSum -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Continuity of series of functions diff --git a/Mathlib/Analysis/SpecificLimits/Basic.lean b/Mathlib/Analysis/SpecificLimits/Basic.lean index 40a14b4c0240c..5bf1e52490763 100644 --- a/Mathlib/Analysis/SpecificLimits/Basic.lean +++ b/Mathlib/Analysis/SpecificLimits/Basic.lean @@ -8,7 +8,7 @@ import Mathlib.Order.Filter.AtTopBot.Archimedean import Mathlib.Order.Iterate import Mathlib.Topology.Algebra.Algebra import Mathlib.Topology.Algebra.InfiniteSum.Real -import Mathlib.Topology.Instances.EReal +import Mathlib.Topology.Instances.EReal.Lemmas /-! # A collection of specific limit computations diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index 53ca89f99b3f6..7c06da09b65e4 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -15,6 +15,7 @@ import Mathlib.Data.Nat.Choose.Bounds import Mathlib.Order.Filter.AtTopBot.ModEq import Mathlib.RingTheory.Polynomial.Pochhammer import Mathlib.Tactic.NoncommRing +import Mathlib.Topology.Instances.Real.Lemmas /-! # A collection of specific limit computations diff --git a/Mathlib/Analysis/Subadditive.lean b/Mathlib/Analysis/Subadditive.lean index 7c69384f24472..5e98d0dec25f9 100644 --- a/Mathlib/Analysis/Subadditive.lean +++ b/Mathlib/Analysis/Subadditive.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Order.Filter.AtTopBot.Archimedean -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Defs /-! # Convergence of subadditive sequences diff --git a/Mathlib/Analysis/SumOverResidueClass.lean b/Mathlib/Analysis/SumOverResidueClass.lean index eb5a5d4f11043..8eb7637dc0dbf 100644 --- a/Mathlib/Analysis/SumOverResidueClass.lean +++ b/Mathlib/Analysis/SumOverResidueClass.lean @@ -5,7 +5,7 @@ Authors: Michael Stoll -/ import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Data.ZMod.Basic -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Sums over residue classes diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index f789146aa2884..22be41cb64513 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -9,6 +9,7 @@ import Mathlib.Data.Complex.Abs import Mathlib.Data.Complex.BigOperators import Mathlib.Data.Nat.Choose.Sum import Mathlib.Tactic.Bound.Attribute +import Mathlib.Algebra.CharP.Defs /-! # Exponential, trigonometric and hyperbolic trigonometric functions diff --git a/Mathlib/Data/Complex/FiniteDimensional.lean b/Mathlib/Data/Complex/FiniteDimensional.lean index ffefcea14aaed..a4df7fcb889b2 100644 --- a/Mathlib/Data/Complex/FiniteDimensional.lean +++ b/Mathlib/Data/Complex/FiniteDimensional.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Algebra.Rat import Mathlib.Data.Complex.Cardinality import Mathlib.Data.Complex.Module import Mathlib.LinearAlgebra.FiniteDimensional.Defs +import Mathlib.Order.Interval.Set.Infinite /-! # Complex number as a finite dimensional vector space over `ℝ` diff --git a/Mathlib/Data/Real/Sqrt.lean b/Mathlib/Data/Real/Sqrt.lean index 14d02f76715e2..be9a5908e835d 100644 --- a/Mathlib/Data/Real/Sqrt.lean +++ b/Mathlib/Data/Real/Sqrt.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Floris van Doorn, Yury Kudryashov -/ -import Mathlib.Topology.Instances.NNReal +import Mathlib.Topology.Instances.NNReal.Lemmas import Mathlib.Topology.Order.MonotoneContinuity /-! diff --git a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean index e403b3b59936a..4cacc2763a035 100644 --- a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean +++ b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean @@ -8,6 +8,7 @@ import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.Order.Iterate import Mathlib.Order.SemiconjSup import Mathlib.Topology.Order.MonotoneContinuity +import Mathlib.Algebra.CharP.Defs /-! # Translation number of a monotone real map that commutes with `x ↦ x + 1` diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean index 8767171c0332e..5e3021fc11e26 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Yury Kudryashov -/ import Mathlib.MeasureTheory.Group.Arithmetic import Mathlib.Topology.GDelta.UniformSpace -import Mathlib.Topology.Instances.EReal +import Mathlib.Topology.Instances.EReal.Lemmas import Mathlib.Topology.Instances.Rat /-! diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean index a92a3b76dd8e1..d7da8b88302ba 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl, Yury Kudryashov -/ import Mathlib.MeasureTheory.Constructions.BorelSpace.Order import Mathlib.MeasureTheory.MeasurableSpace.Prod +import Mathlib.Topology.Instances.Real.Lemmas /-! # Borel (measurable) spaces ℝ, ℝ≥0, ℝ≥0∞ diff --git a/Mathlib/MeasureTheory/Decomposition/Jordan.lean b/Mathlib/MeasureTheory/Decomposition/Jordan.lean index 12402fc826cce..ce9122ea87126 100644 --- a/Mathlib/MeasureTheory/Decomposition/Jordan.lean +++ b/Mathlib/MeasureTheory/Decomposition/Jordan.lean @@ -5,6 +5,7 @@ Authors: Kexing Ying -/ import Mathlib.MeasureTheory.Decomposition.SignedHahn import Mathlib.MeasureTheory.Measure.MutuallySingular +import Mathlib.Topology.Algebra.UniformMulAction /-! # Jordan decomposition diff --git a/Mathlib/MeasureTheory/Integral/VitaliCaratheodory.lean b/Mathlib/MeasureTheory/Integral/VitaliCaratheodory.lean index b19b0ab5ee009..8e588dd188a23 100644 --- a/Mathlib/MeasureTheory/Integral/VitaliCaratheodory.lean +++ b/Mathlib/MeasureTheory/Integral/VitaliCaratheodory.lean @@ -6,7 +6,7 @@ Authors: Sébastien Gouëzel import Mathlib.MeasureTheory.Measure.Regular import Mathlib.Topology.Semicontinuous import Mathlib.MeasureTheory.Integral.Bochner -import Mathlib.Topology.Instances.EReal +import Mathlib.Topology.Instances.EReal.Lemmas /-! # Vitali-Carathéodory theorem diff --git a/Mathlib/MeasureTheory/Measure/Stieltjes.lean b/Mathlib/MeasureTheory/Measure/Stieltjes.lean index 94d2b36c805e6..f8ce38896c98b 100644 --- a/Mathlib/MeasureTheory/Measure/Stieltjes.lean +++ b/Mathlib/MeasureTheory/Measure/Stieltjes.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl, Yury Kudryashov, Sébastien Gouëzel -/ import Mathlib.MeasureTheory.Constructions.BorelSpace.Order import Mathlib.Topology.Order.LeftRightLim +import Mathlib.Topology.Algebra.UniformMulAction /-! # Stieltjes measures on the real line diff --git a/Mathlib/MeasureTheory/OuterMeasure/Basic.lean b/Mathlib/MeasureTheory/OuterMeasure/Basic.lean index 24180bd2709cb..9ca65df0c95b1 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Basic.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Countable.Basic import Mathlib.Data.Fin.VecNotation import Mathlib.Order.Disjointed import Mathlib.MeasureTheory.OuterMeasure.Defs +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Outer Measures diff --git a/Mathlib/MeasureTheory/OuterMeasure/Defs.lean b/Mathlib/MeasureTheory/OuterMeasure/Defs.lean index 47b1684512889..eb6ddcee27050 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Defs.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Defs.lean @@ -3,7 +3,8 @@ 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, Mario Carneiro, Yury Kudryashov -/ -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Defs +import Mathlib.Topology.Algebra.InfiniteSum.Defs /-! # Definitions of an outer measure and the corresponding `FunLike` class diff --git a/Mathlib/Order/Filter/ENNReal.lean b/Mathlib/Order/Filter/ENNReal.lean index e6578ed67d021..8a722cfe0a58a 100644 --- a/Mathlib/Order/Filter/ENNReal.lean +++ b/Mathlib/Order/Filter/ENNReal.lean @@ -3,7 +3,8 @@ Copyright (c) 2021 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Defs +import Mathlib.Topology.Algebra.Order.LiminfLimsup /-! # Order properties of extended non-negative reals diff --git a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean index 14593d136558b..f5124ea768ad5 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean @@ -3,7 +3,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, Devon Tuma -/ -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas import Mathlib.MeasureTheory.Measure.Dirac /-! diff --git a/Mathlib/Topology/Algebra/InfiniteSum/ENNReal.lean b/Mathlib/Topology/Algebra/InfiniteSum/ENNReal.lean index 2e8e9cea6e74e..93bbde55a7c58 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/ENNReal.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/ENNReal.lean @@ -5,7 +5,7 @@ Authors: Edward van de Meent -/ import Mathlib.Data.Real.ENatENNReal import Mathlib.Data.Set.Card -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Infinite sums of ENNReal and Set.encard diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Real.lean b/Mathlib/Topology/Algebra/InfiniteSum/Real.lean index cfd31f628c2ee..561c084897481 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Real.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Real.lean @@ -5,7 +5,7 @@ Authors: Sébastien Gouëzel, Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.Intervals import Mathlib.Topology.Algebra.InfiniteSum.Order -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Infinite sum in the reals diff --git a/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean b/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean index a66d33e8123a5..138c67bdb9188 100644 --- a/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean +++ b/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean @@ -7,6 +7,7 @@ import Mathlib.Topology.Algebra.Module.Multilinear.Bounded import Mathlib.Topology.Algebra.Module.UniformConvergence import Mathlib.Topology.Algebra.SeparationQuotient.Section import Mathlib.Topology.Hom.ContinuousEvalConst +import Mathlib.Topology.Algebra.InfiniteSum.Basic /-! # Topology on continuous multilinear maps diff --git a/Mathlib/Topology/Instances/CantorSet.lean b/Mathlib/Topology/Instances/CantorSet.lean index b2223fb6f26d7..f93a29506cda8 100644 --- a/Mathlib/Topology/Instances/CantorSet.lean +++ b/Mathlib/Topology/Instances/CantorSet.lean @@ -6,7 +6,7 @@ Tomáš Jakl, Lorenzo Zanichelli, Alina Yan, Emilie Uthaiwat, Jana Göken, Filippo A. E. Nuccio -/ import Mathlib.Topology.Algebra.GroupWithZero -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Defs /-! # Ternary Cantor Set diff --git a/Mathlib/Topology/Instances/ENNReal/Defs.lean b/Mathlib/Topology/Instances/ENNReal/Defs.lean new file mode 100644 index 0000000000000..43bc095ad3502 --- /dev/null +++ b/Mathlib/Topology/Instances/ENNReal/Defs.lean @@ -0,0 +1,74 @@ +/- +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 +-/ +import Mathlib.Topology.Order.MonotoneContinuity +import Mathlib.Topology.EMetricSpace.Lipschitz +import Mathlib.Topology.Metrizable.Basic +import Mathlib.Topology.Order.T5 +import Mathlib.Topology.Instances.NNReal.Defs + +/-! +# Topology on extended non-negative reals +-/ + +noncomputable section + +open Filter Function Metric Set Topology +open scoped Finset ENNReal NNReal + +variable {α : Type*} {β : Type*} {γ : Type*} + +namespace ENNReal + +variable {a b : ℝ≥0∞} {r : ℝ≥0} {x : ℝ≥0∞} {ε : ℝ≥0∞} + +open TopologicalSpace + +/-- Topology on `ℝ≥0∞`. + +Note: this is different from the `EMetricSpace` topology. The `EMetricSpace` topology has +`IsOpen {∞}`, while this topology doesn't have singleton elements. -/ +instance : TopologicalSpace ℝ≥0∞ := Preorder.topology ℝ≥0∞ + +instance : OrderTopology ℝ≥0∞ := ⟨rfl⟩ + +-- short-circuit type class inference +instance : T2Space ℝ≥0∞ := inferInstance +instance : T5Space ℝ≥0∞ := inferInstance +instance : T4Space ℝ≥0∞ := inferInstance + +instance : SecondCountableTopology ℝ≥0∞ := + orderIsoUnitIntervalBirational.toHomeomorph.isEmbedding.secondCountableTopology + +instance : MetrizableSpace ENNReal := + orderIsoUnitIntervalBirational.toHomeomorph.isEmbedding.metrizableSpace + +theorem isEmbedding_coe : IsEmbedding ((↑) : ℝ≥0 → ℝ≥0∞) := + coe_strictMono.isEmbedding_of_ordConnected <| by rw [range_coe']; exact ordConnected_Iio + +@[norm_cast] +theorem tendsto_coe {f : Filter α} {m : α → ℝ≥0} {a : ℝ≥0} : + Tendsto (fun a => (m a : ℝ≥0∞)) f (𝓝 ↑a) ↔ Tendsto m f (𝓝 a) := + isEmbedding_coe.tendsto_nhds_iff.symm + +theorem isOpenEmbedding_coe : IsOpenEmbedding ((↑) : ℝ≥0 → ℝ≥0∞) := + ⟨isEmbedding_coe, by rw [range_coe']; exact isOpen_Iio⟩ + +theorem nhds_coe_coe {r p : ℝ≥0} : + 𝓝 ((r : ℝ≥0∞), (p : ℝ≥0∞)) = (𝓝 (r, p)).map fun p : ℝ≥0 × ℝ≥0 => (↑p.1, ↑p.2) := + ((isOpenEmbedding_coe.prodMap isOpenEmbedding_coe).map_nhds_eq (r, p)).symm + +instance : ContinuousAdd ℝ≥0∞ := by + refine ⟨continuous_iff_continuousAt.2 ?_⟩ + rintro ⟨_ | a, b⟩ + · exact tendsto_nhds_top_mono' continuousAt_fst fun p => le_add_right le_rfl + rcases b with (_ | b) + · exact tendsto_nhds_top_mono' continuousAt_snd fun p => le_add_left le_rfl + simp only [ContinuousAt, some_eq_coe, nhds_coe_coe, ← coe_add, tendsto_map'_iff, + Function.comp_def, tendsto_coe, tendsto_add] + +instance : ContinuousInv ℝ≥0∞ := ⟨OrderIso.invENNReal.continuous⟩ + +end ENNReal diff --git a/Mathlib/Topology/Instances/ENNReal.lean b/Mathlib/Topology/Instances/ENNReal/Lemmas.lean similarity index 97% rename from Mathlib/Topology/Instances/ENNReal.lean rename to Mathlib/Topology/Instances/ENNReal/Lemmas.lean index 93f04f375c31f..769d4aa27d05a 100644 --- a/Mathlib/Topology/Instances/ENNReal.lean +++ b/Mathlib/Topology/Instances/ENNReal/Lemmas.lean @@ -5,7 +5,8 @@ Authors: Johannes Hölzl -/ import Mathlib.Topology.Order.MonotoneContinuity import Mathlib.Topology.Algebra.Order.LiminfLimsup -import Mathlib.Topology.Instances.NNReal +import Mathlib.Topology.Instances.ENNReal.Defs +import Mathlib.Topology.Instances.NNReal.Lemmas import Mathlib.Topology.EMetricSpace.Lipschitz import Mathlib.Topology.Metrizable.Basic import Mathlib.Topology.Order.T5 @@ -31,28 +32,6 @@ section TopologicalSpace open TopologicalSpace -/-- Topology on `ℝ≥0∞`. - -Note: this is different from the `EMetricSpace` topology. The `EMetricSpace` topology has -`IsOpen {∞}`, while this topology doesn't have singleton elements. -/ -instance : TopologicalSpace ℝ≥0∞ := Preorder.topology ℝ≥0∞ - -instance : OrderTopology ℝ≥0∞ := ⟨rfl⟩ - --- short-circuit type class inference -instance : T2Space ℝ≥0∞ := inferInstance -instance : T5Space ℝ≥0∞ := inferInstance -instance : T4Space ℝ≥0∞ := inferInstance - -instance : SecondCountableTopology ℝ≥0∞ := - orderIsoUnitIntervalBirational.toHomeomorph.isEmbedding.secondCountableTopology - -instance : MetrizableSpace ENNReal := - orderIsoUnitIntervalBirational.toHomeomorph.isEmbedding.metrizableSpace - -theorem isEmbedding_coe : IsEmbedding ((↑) : ℝ≥0 → ℝ≥0∞) := - coe_strictMono.isEmbedding_of_ordConnected <| by rw [range_coe']; exact ordConnected_Iio - @[deprecated (since := "2024-10-26")] alias embedding_coe := isEmbedding_coe @@ -62,20 +41,12 @@ theorem isOpen_Ico_zero : IsOpen (Ico 0 b) := by rw [ENNReal.Ico_eq_Iio] exact isOpen_Iio -theorem isOpenEmbedding_coe : IsOpenEmbedding ((↑) : ℝ≥0 → ℝ≥0∞) := - ⟨isEmbedding_coe, by rw [range_coe']; exact isOpen_Iio⟩ - @[deprecated (since := "2024-10-18")] alias openEmbedding_coe := isOpenEmbedding_coe theorem coe_range_mem_nhds : range ((↑) : ℝ≥0 → ℝ≥0∞) ∈ 𝓝 (r : ℝ≥0∞) := IsOpen.mem_nhds isOpenEmbedding_coe.isOpen_range <| mem_range_self _ -@[norm_cast] -theorem tendsto_coe {f : Filter α} {m : α → ℝ≥0} {a : ℝ≥0} : - Tendsto (fun a => (m a : ℝ≥0∞)) f (𝓝 ↑a) ↔ Tendsto m f (𝓝 a) := - isEmbedding_coe.tendsto_nhds_iff.symm - @[fun_prop] theorem continuous_coe : Continuous ((↑) : ℝ≥0 → ℝ≥0∞) := isEmbedding_coe.continuous @@ -95,10 +66,6 @@ theorem continuousAt_coe_iff {α : Type*} [TopologicalSpace α] {x : ℝ≥0} {f ContinuousAt f ↑x ↔ ContinuousAt (f ∘ (↑) : ℝ≥0 → α) x := tendsto_nhds_coe_iff -theorem nhds_coe_coe {r p : ℝ≥0} : - 𝓝 ((r : ℝ≥0∞), (p : ℝ≥0∞)) = (𝓝 (r, p)).map fun p : ℝ≥0 × ℝ≥0 => (↑p.1, ↑p.2) := - ((isOpenEmbedding_coe.prodMap isOpenEmbedding_coe).map_nhds_eq (r, p)).symm - theorem continuous_ofReal : Continuous ENNReal.ofReal := (continuous_coe_iff.2 continuous_id).comp continuous_real_toNNReal @@ -275,15 +242,6 @@ protected theorem tendsto_atTop [Nonempty β] [SemilatticeSup β] {f : β → (ha : a ≠ ∞) : Tendsto f atTop (𝓝 a) ↔ ∀ ε > 0, ∃ N, ∀ n ≥ N, f n ∈ Icc (a - ε) (a + ε) := .trans (atTop_basis.tendsto_iff (hasBasis_nhds_of_ne_top ha)) (by simp only [true_and]; rfl) -instance : ContinuousAdd ℝ≥0∞ := by - refine ⟨continuous_iff_continuousAt.2 ?_⟩ - rintro ⟨_ | a, b⟩ - · exact tendsto_nhds_top_mono' continuousAt_fst fun p => le_add_right le_rfl - rcases b with (_ | b) - · exact tendsto_nhds_top_mono' continuousAt_snd fun p => le_add_left le_rfl - simp only [ContinuousAt, some_eq_coe, nhds_coe_coe, ← coe_add, tendsto_map'_iff, - Function.comp_def, tendsto_coe, tendsto_add] - protected theorem tendsto_atTop_zero [Nonempty β] [SemilatticeSup β] {f : β → ℝ≥0∞} : Tendsto f atTop (𝓝 0) ↔ ∀ ε > 0, ∃ N, ∀ n ≥ N, f n ≤ ε := .trans (atTop_basis.tendsto_iff nhds_zero_basis_Iic) (by simp only [true_and]; rfl) @@ -511,8 +469,6 @@ theorem inv_liminf {ι : Sort _} {x : ι → ℝ≥0∞} {l : Filter ι} : (liminf x l)⁻¹ = limsup (fun i => (x i)⁻¹) l := OrderIso.invENNReal.liminf_apply -instance : ContinuousInv ℝ≥0∞ := ⟨OrderIso.invENNReal.continuous⟩ - @[fun_prop] protected theorem continuous_zpow : ∀ n : ℤ, Continuous (· ^ n : ℝ≥0∞ → ℝ≥0∞) | (n : ℕ) => mod_cast ENNReal.continuous_pow n diff --git a/Mathlib/Topology/Instances/EReal/Defs.lean b/Mathlib/Topology/Instances/EReal/Defs.lean new file mode 100644 index 0000000000000..26ab7c9f569cb --- /dev/null +++ b/Mathlib/Topology/Instances/EReal/Defs.lean @@ -0,0 +1,47 @@ +/- +Copyright (c) 2021 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.Data.Rat.Encodable +import Mathlib.Data.Real.EReal +import Mathlib.Topology.Order.MonotoneContinuity +import Mathlib.Topology.Order.T5 +import Mathlib.Topology.Algebra.Group.Basic + +/-! +# Topological structure on `EReal` + +We endow `EReal` with the order topology. + +## Implementation + +Most proofs are adapted from the corresponding proofs on `ℝ≥0∞`. +-/ + +noncomputable section + +open Set Filter TopologicalSpace Topology +open scoped ENNReal + +variable {α : Type*} [TopologicalSpace α] + +namespace EReal + +instance : TopologicalSpace EReal := Preorder.topology EReal +instance : OrderTopology EReal := ⟨rfl⟩ +instance : T5Space EReal := inferInstance +instance : T2Space EReal := inferInstance + +lemma denseRange_ratCast : DenseRange (fun r : ℚ ↦ ((r : ℝ) : EReal)) := + dense_of_exists_between fun _ _ h => exists_range_iff.2 <| exists_rat_btwn_of_lt h + +instance : SecondCountableTopology EReal := + have : SeparableSpace EReal := ⟨⟨_, countable_range _, denseRange_ratCast⟩⟩ + .of_separableSpace_orderTopology _ + +/-! ### Negation -/ + +instance : ContinuousNeg EReal := ⟨negOrderIso.continuous⟩ + +end EReal diff --git a/Mathlib/Topology/Instances/EReal.lean b/Mathlib/Topology/Instances/EReal/Lemmas.lean similarity index 96% rename from Mathlib/Topology/Instances/EReal.lean rename to Mathlib/Topology/Instances/EReal/Lemmas.lean index 903c24814fc46..ea06c10f746c0 100644 --- a/Mathlib/Topology/Instances/EReal.lean +++ b/Mathlib/Topology/Instances/EReal/Lemmas.lean @@ -5,14 +5,15 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Data.Rat.Encodable import Mathlib.Data.Real.EReal -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.EReal.Defs +import Mathlib.Topology.Instances.ENNReal.Lemmas import Mathlib.Topology.Order.MonotoneContinuity import Mathlib.Topology.Semicontinuous /-! # Topological structure on `EReal` -We endow `EReal` with the order topology, and prove basic properties of this topology. +We prove basic properties of the topology on `EReal`. ## Main results @@ -35,18 +36,6 @@ variable {α : Type*} [TopologicalSpace α] namespace EReal -instance : TopologicalSpace EReal := Preorder.topology EReal -instance : OrderTopology EReal := ⟨rfl⟩ -instance : T5Space EReal := inferInstance -instance : T2Space EReal := inferInstance - -lemma denseRange_ratCast : DenseRange (fun r : ℚ ↦ ((r : ℝ) : EReal)) := - dense_of_exists_between fun _ _ h => exists_range_iff.2 <| exists_rat_btwn_of_lt h - -instance : SecondCountableTopology EReal := - have : SeparableSpace EReal := ⟨⟨_, countable_range _, denseRange_ratCast⟩⟩ - .of_separableSpace_orderTopology _ - /-! ### Real coercion -/ theorem isEmbedding_coe : IsEmbedding ((↑) : ℝ → EReal) := @@ -370,10 +359,6 @@ theorem continuousAt_add {p : EReal × EReal} (h : p.1 ≠ ⊤ ∨ p.2 ≠ ⊥) · exact continuousAt_add_top_coe _ · exact continuousAt_add_top_top -/-! ### Negation -/ - -instance : ContinuousNeg EReal := ⟨negOrderIso.continuous⟩ - /-! ### Continuity of multiplication -/ /- Outside of indeterminacies `(0, ±∞)` and `(±∞, 0)`, the multiplication on `EReal` is continuous. diff --git a/Mathlib/Topology/Instances/Irrational.lean b/Mathlib/Topology/Instances/Irrational.lean index 8b82916e9b93b..ad7316ca1ab3b 100644 --- a/Mathlib/Topology/Instances/Irrational.lean +++ b/Mathlib/Topology/Instances/Irrational.lean @@ -6,6 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Data.Real.Irrational import Mathlib.Data.Rat.Encodable import Mathlib.Topology.Separation.GDelta +import Mathlib.Topology.Instances.Real.Lemmas /-! # Topology of irrational numbers diff --git a/Mathlib/Topology/Instances/NNReal/Defs.lean b/Mathlib/Topology/Instances/NNReal/Defs.lean new file mode 100644 index 0000000000000..4ab30b14fb4b0 --- /dev/null +++ b/Mathlib/Topology/Instances/NNReal/Defs.lean @@ -0,0 +1,97 @@ +/- +Copyright (c) 2018 Johan Commelin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johan Commelin +-/ +import Mathlib.Data.NNReal.Star +import Mathlib.Topology.ContinuousMap.Basic +import Mathlib.Topology.MetricSpace.Isometry +import Mathlib.Topology.Instances.Real.Defs + +/-! +# Topology on `ℝ≥0` + +The natural topology on `ℝ≥0` (the one induced from `ℝ`), and a basic API. + +## Main definitions + +Instances for the following typeclasses are defined: + +* `TopologicalSpace ℝ≥0` +* `TopologicalSemiring ℝ≥0` +* `SecondCountableTopology ℝ≥0` +* `OrderTopology ℝ≥0` +* `ProperSpace ℝ≥0` +* `ContinuousSub ℝ≥0` +* `HasContinuousInv₀ ℝ≥0` (continuity of `x⁻¹` away from `0`) +* `ContinuousSMul ℝ≥0 α` (whenever `α` has a continuous `MulAction ℝ α`) + +Everything is inherited from the corresponding structures on the reals. + +-/ + +noncomputable section + +open Filter Metric Set TopologicalSpace Topology + +namespace NNReal + +instance : TopologicalSpace ℝ≥0 := inferInstance + +-- short-circuit type class inference +instance : TopologicalSemiring ℝ≥0 where + toContinuousAdd := continuousAdd_induced toRealHom + toContinuousMul := continuousMul_induced toRealHom + +instance : SecondCountableTopology ℝ≥0 := + inferInstanceAs (SecondCountableTopology { x : ℝ | 0 ≤ x }) + +instance : OrderTopology ℝ≥0 := + orderTopology_of_ordConnected (t := Ici 0) + +instance : CompleteSpace ℝ≥0 := + isClosed_Ici.completeSpace_coe + +instance : ContinuousStar ℝ≥0 where + continuous_star := continuous_id + +-- TODO: generalize this to a broader class of subtypes +instance : IsOrderBornology ℝ≥0 where + isBounded_iff_bddBelow_bddAbove s := by + refine ⟨fun bdd ↦ ?_, fun h ↦ isBounded_of_bddAbove_of_bddBelow h.2 h.1⟩ + obtain ⟨r, hr⟩ : ∃ r : ℝ≥0, s ⊆ Icc 0 r := by + obtain ⟨rreal, hrreal⟩ := bdd.subset_closedBall 0 + use rreal.toNNReal + simp only [← NNReal.closedBall_zero_eq_Icc', Real.coe_toNNReal'] + exact subset_trans hrreal (Metric.closedBall_subset_closedBall (le_max_left rreal 0)) + exact ⟨bddBelow_Icc.mono hr, bddAbove_Icc.mono hr⟩ + +theorem continuous_coe : Continuous ((↑) : ℝ≥0 → ℝ) := + continuous_subtype_val + +instance : ContinuousSub ℝ≥0 := + ⟨((continuous_coe.fst'.sub continuous_coe.snd').max continuous_const).subtype_mk _⟩ + +instance : HasContinuousInv₀ ℝ≥0 := inferInstance + +variable {α : Type*} + +instance [TopologicalSpace α] [MulAction ℝ α] [ContinuousSMul ℝ α] : + ContinuousSMul ℝ≥0 α where + continuous_smul := continuous_induced_dom.fst'.smul continuous_snd + +/-- Embedding of `ℝ≥0` to `ℝ` as a bundled continuous map. -/ +@[simps (config := .asFn)] +def _root_.ContinuousMap.coeNNRealReal : C(ℝ≥0, ℝ) := + ⟨(↑), continuous_coe⟩ + +instance ContinuousMap.canLift {X : Type*} [TopologicalSpace X] : + CanLift C(X, ℝ) C(X, ℝ≥0) ContinuousMap.coeNNRealReal.comp fun f => ∀ x, 0 ≤ f x where + prf f hf := ⟨⟨fun x => ⟨f x, hf x⟩, f.2.subtype_mk _⟩, DFunLike.ext' rfl⟩ + +instance instProperSpace : ProperSpace ℝ≥0 where + isCompact_closedBall x r := by + have emb : IsClosedEmbedding ((↑) : ℝ≥0 → ℝ) := Isometry.isClosedEmbedding fun _ ↦ congrFun rfl + exact emb.isCompact_preimage (K := Metric.closedBall x r) (isCompact_closedBall _ _) + +end NNReal diff --git a/Mathlib/Topology/Instances/NNReal.lean b/Mathlib/Topology/Instances/NNReal/Lemmas.lean similarity index 77% rename from Mathlib/Topology/Instances/NNReal.lean rename to Mathlib/Topology/Instances/NNReal/Lemmas.lean index b311766f89a48..f771e86fb0b39 100644 --- a/Mathlib/Topology/Instances/NNReal.lean +++ b/Mathlib/Topology/Instances/NNReal/Lemmas.lean @@ -8,27 +8,12 @@ import Mathlib.Topology.Algebra.InfiniteSum.Order import Mathlib.Topology.Algebra.InfiniteSum.Ring import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Topology.MetricSpace.Isometry -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.NNReal.Defs /-! # Topology on `ℝ≥0` -The natural topology on `ℝ≥0` (the one induced from `ℝ`), and a basic API. - -## Main definitions - -Instances for the following typeclasses are defined: - -* `TopologicalSpace ℝ≥0` -* `TopologicalSemiring ℝ≥0` -* `SecondCountableTopology ℝ≥0` -* `OrderTopology ℝ≥0` -* `ProperSpace ℝ≥0` -* `ContinuousSub ℝ≥0` -* `HasContinuousInv₀ ℝ≥0` (continuity of `x⁻¹` away from `0`) -* `ContinuousSMul ℝ≥0 α` (whenever `α` has a continuous `MulAction ℝ α`) - -Everything is inherited from the corresponding structures on the reals. +The basic lemmas for the natural topology on `ℝ≥0` . ## Main statements @@ -55,43 +40,13 @@ open Filter Metric Set TopologicalSpace Topology namespace NNReal -instance : TopologicalSpace ℝ≥0 := inferInstance - --- short-circuit type class inference -instance : TopologicalSemiring ℝ≥0 where - toContinuousAdd := continuousAdd_induced toRealHom - toContinuousMul := continuousMul_induced toRealHom - -instance : SecondCountableTopology ℝ≥0 := - inferInstanceAs (SecondCountableTopology { x : ℝ | 0 ≤ x }) - -instance : OrderTopology ℝ≥0 := - orderTopology_of_ordConnected (t := Ici 0) - -instance : CompleteSpace ℝ≥0 := - isClosed_Ici.completeSpace_coe - -instance : ContinuousStar ℝ≥0 where - continuous_star := continuous_id - --- TODO: generalize this to a broader class of subtypes -instance : IsOrderBornology ℝ≥0 where - isBounded_iff_bddBelow_bddAbove s := by - refine ⟨fun bdd ↦ ?_, fun h ↦ isBounded_of_bddAbove_of_bddBelow h.2 h.1⟩ - obtain ⟨r, hr⟩ : ∃ r : ℝ≥0, s ⊆ Icc 0 r := by - obtain ⟨rreal, hrreal⟩ := bdd.subset_closedBall 0 - use rreal.toNNReal - simp only [← NNReal.closedBall_zero_eq_Icc', Real.coe_toNNReal'] - exact subset_trans hrreal (Metric.closedBall_subset_closedBall (le_max_left rreal 0)) - exact ⟨bddBelow_Icc.mono hr, bddAbove_Icc.mono hr⟩ +variable {α : Type*} section coe lemma isOpen_Ico_zero {x : NNReal} : IsOpen (Set.Ico 0 x) := Ico_bot (a := x) ▸ isOpen_Iio -variable {α : Type*} - open Filter Finset theorem _root_.continuous_real_toNNReal : Continuous Real.toNNReal := @@ -102,23 +57,11 @@ theorem _root_.continuous_real_toNNReal : Continuous Real.toNNReal := noncomputable def _root_.ContinuousMap.realToNNReal : C(ℝ, ℝ≥0) := .mk Real.toNNReal continuous_real_toNNReal -theorem continuous_coe : Continuous ((↑) : ℝ≥0 → ℝ) := - continuous_subtype_val - lemma _root_.ContinuousOn.ofReal_map_toNNReal {f : ℝ≥0 → ℝ≥0} {s : Set ℝ} {t : Set ℝ≥0} (hf : ContinuousOn f t) (h : Set.MapsTo Real.toNNReal s t) : ContinuousOn (fun x ↦ f x.toNNReal : ℝ → ℝ) s := continuous_subtype_val.comp_continuousOn <| hf.comp continuous_real_toNNReal.continuousOn h -/-- Embedding of `ℝ≥0` to `ℝ` as a bundled continuous map. -/ -@[simps (config := .asFn)] -def _root_.ContinuousMap.coeNNRealReal : C(ℝ≥0, ℝ) := - ⟨(↑), continuous_coe⟩ - -instance ContinuousMap.canLift {X : Type*} [TopologicalSpace X] : - CanLift C(X, ℝ) C(X, ℝ≥0) ContinuousMap.coeNNRealReal.comp fun f => ∀ x, 0 ≤ f x where - prf f hf := ⟨⟨fun x => ⟨f x, hf x⟩, f.2.subtype_mk _⟩, DFunLike.ext' rfl⟩ - @[simp, norm_cast] theorem tendsto_coe {f : Filter α} {m : α → ℝ≥0} {x : ℝ≥0} : Tendsto (fun a => (m a : ℝ)) f (𝓝 (x : ℝ)) ↔ Tendsto m f (𝓝 x) := @@ -170,14 +113,6 @@ theorem nhds_zero : 𝓝 (0 : ℝ≥0) = ⨅ (a : ℝ≥0) (_ : a ≠ 0), 𝓟 ( theorem nhds_zero_basis : (𝓝 (0 : ℝ≥0)).HasBasis (fun a : ℝ≥0 => 0 < a) fun a => Iio a := nhds_bot_basis -instance : ContinuousSub ℝ≥0 := - ⟨((continuous_coe.fst'.sub continuous_coe.snd').max continuous_const).subtype_mk _⟩ - -instance : HasContinuousInv₀ ℝ≥0 := inferInstance - -instance [TopologicalSpace α] [MulAction ℝ α] [ContinuousSMul ℝ α] : - ContinuousSMul ℝ≥0 α where - continuous_smul := continuous_induced_dom.fst'.smul continuous_snd @[norm_cast] theorem hasSum_coe {f : α → ℝ≥0} {r : ℝ≥0} : HasSum (fun a => (f a : ℝ)) (r : ℝ) ↔ HasSum f r := by @@ -298,9 +233,4 @@ theorem tendsto_of_antitone {f : ℕ → ℝ≥0} (h_ant : Antitone f) : end Monotone -instance instProperSpace : ProperSpace ℝ≥0 where - isCompact_closedBall x r := by - have emb : IsClosedEmbedding ((↑) : ℝ≥0 → ℝ) := Isometry.isClosedEmbedding fun _ ↦ congrFun rfl - exact emb.isCompact_preimage (K := Metric.closedBall x r) (isCompact_closedBall _ _) - end NNReal diff --git a/Mathlib/Topology/Instances/Rat.lean b/Mathlib/Topology/Instances/Rat.lean index a8796eaca78bc..8539147838336 100644 --- a/Mathlib/Topology/Instances/Rat.lean +++ b/Mathlib/Topology/Instances/Rat.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Topology.Algebra.Order.Archimedean import Mathlib.Topology.Instances.Nat -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Defs /-! # Topology on the rational numbers diff --git a/Mathlib/Topology/Instances/Real/Defs.lean b/Mathlib/Topology/Instances/Real/Defs.lean new file mode 100644 index 0000000000000..93400ed393606 --- /dev/null +++ b/Mathlib/Topology/Instances/Real/Defs.lean @@ -0,0 +1,72 @@ +/- +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, Mario Carneiro +-/ +import Mathlib.Data.Real.Star +import Mathlib.Topology.Algebra.Order.Field +import Mathlib.Topology.Algebra.Star +import Mathlib.Topology.Instances.Int +import Mathlib.Topology.Order.Bornology +import Mathlib.Topology.Algebra.UniformGroup.Defs + +/-! +# Topological properties of ℝ +-/ +assert_not_exists UniformOnFun + +noncomputable section + +open Filter Int Metric Set TopologicalSpace Bornology +open scoped Topology Uniformity Interval + +universe u v w + +variable {α : Type u} {β : Type v} {γ : Type w} + +instance : NoncompactSpace ℝ := Int.isClosedEmbedding_coe_real.noncompactSpace + +theorem Real.uniformContinuous_add : UniformContinuous fun p : ℝ × ℝ => p.1 + p.2 := + Metric.uniformContinuous_iff.2 fun _ε ε0 => + let ⟨δ, δ0, Hδ⟩ := rat_add_continuous_lemma abs ε0 + ⟨δ, δ0, fun _ _ h => + let ⟨h₁, h₂⟩ := max_lt_iff.1 h + Hδ h₁ h₂⟩ + +theorem Real.uniformContinuous_neg : UniformContinuous (@Neg.neg ℝ _) := + Metric.uniformContinuous_iff.2 fun ε ε0 => + ⟨_, ε0, fun _ _ h => by simpa only [abs_sub_comm, Real.dist_eq, neg_sub_neg] using h⟩ + +instance : UniformAddGroup ℝ := + UniformAddGroup.mk' Real.uniformContinuous_add Real.uniformContinuous_neg + +-- short-circuit type class inference +instance : TopologicalAddGroup ℝ := by infer_instance +instance : TopologicalRing ℝ := inferInstance +instance : TopologicalDivisionRing ℝ := inferInstance + +instance : ProperSpace ℝ where + isCompact_closedBall x r := by + rw [Real.closedBall_eq_Icc] + apply isCompact_Icc + +instance : SecondCountableTopology ℝ := secondCountable_of_proper + +instance Real.instCompleteSpace : CompleteSpace ℝ := by + apply complete_of_cauchySeq_tendsto + intro u hu + let c : CauSeq ℝ abs := ⟨u, Metric.cauchySeq_iff'.1 hu⟩ + refine ⟨c.lim, fun s h => ?_⟩ + rcases Metric.mem_nhds_iff.1 h with ⟨ε, ε0, hε⟩ + have := c.equiv_lim ε ε0 + simp only [mem_map, mem_atTop_sets, mem_setOf_eq] + exact this.imp fun N hN n hn => hε (hN n hn) + +instance instIsOrderBornology : IsOrderBornology ℝ where + isBounded_iff_bddBelow_bddAbove s := by + refine ⟨fun bdd ↦ ?_, fun h ↦ isBounded_of_bddAbove_of_bddBelow h.2 h.1⟩ + obtain ⟨r, hr⟩ : ∃ r : ℝ, s ⊆ Icc (-r) r := by + simpa [Real.closedBall_eq_Icc] using bdd.subset_closedBall 0 + exact ⟨bddBelow_Icc.mono hr, bddAbove_Icc.mono hr⟩ + +instance : ContinuousStar ℝ := ⟨continuous_id⟩ diff --git a/Mathlib/Topology/Instances/Real.lean b/Mathlib/Topology/Instances/Real/Lemmas.lean similarity index 73% rename from Mathlib/Topology/Instances/Real.lean rename to Mathlib/Topology/Instances/Real/Lemmas.lean index 41f5e2e54a206..a1f50ca973a4c 100644 --- a/Mathlib/Topology/Instances/Real.lean +++ b/Mathlib/Topology/Instances/Real/Lemmas.lean @@ -12,11 +12,11 @@ import Mathlib.Topology.Algebra.UniformMulAction import Mathlib.Topology.Instances.Int import Mathlib.Topology.Order.Bornology import Mathlib.Topology.Algebra.UniformGroup.Defs +import Mathlib.Topology.Instances.Real.Defs /-! # Topological properties of ℝ -/ - assert_not_exists UniformOnFun noncomputable section @@ -28,36 +28,6 @@ universe u v w variable {α : Type u} {β : Type v} {γ : Type w} -instance : NoncompactSpace ℝ := Int.isClosedEmbedding_coe_real.noncompactSpace - -theorem Real.uniformContinuous_add : UniformContinuous fun p : ℝ × ℝ => p.1 + p.2 := - Metric.uniformContinuous_iff.2 fun _ε ε0 => - let ⟨δ, δ0, Hδ⟩ := rat_add_continuous_lemma abs ε0 - ⟨δ, δ0, fun _ _ h => - let ⟨h₁, h₂⟩ := max_lt_iff.1 h - Hδ h₁ h₂⟩ - -theorem Real.uniformContinuous_neg : UniformContinuous (@Neg.neg ℝ _) := - Metric.uniformContinuous_iff.2 fun ε ε0 => - ⟨_, ε0, fun _ _ h => by simpa only [abs_sub_comm, Real.dist_eq, neg_sub_neg] using h⟩ - -instance : ContinuousStar ℝ := ⟨continuous_id⟩ - -instance : UniformAddGroup ℝ := - UniformAddGroup.mk' Real.uniformContinuous_add Real.uniformContinuous_neg - --- short-circuit type class inference -instance : TopologicalAddGroup ℝ := by infer_instance -instance : TopologicalRing ℝ := inferInstance -instance : TopologicalDivisionRing ℝ := inferInstance - -instance : ProperSpace ℝ where - isCompact_closedBall x r := by - rw [Real.closedBall_eq_Icc] - apply isCompact_Icc - -instance : SecondCountableTopology ℝ := secondCountable_of_proper - theorem Real.isTopologicalBasis_Ioo_rat : @IsTopologicalBasis ℝ _ (⋃ (a : ℚ) (b : ℚ) (_ : a < b), {Ioo (a : ℝ) b}) := isTopologicalBasis_of_isOpen_of_nhds (by simp +contextual [isOpen_Ioo]) @@ -74,8 +44,6 @@ theorem Real.isTopologicalBasis_Ioo_rat : theorem Real.cobounded_eq : cobounded ℝ = atBot ⊔ atTop := by simp only [← comap_dist_right_atTop (0 : ℝ), Real.dist_eq, sub_zero, comap_abs_atTop] - - /- TODO(Mario): Prove that these are uniform isomorphisms instead of uniform embeddings lemma uniform_embedding_add_rat {r : ℚ} : uniform_embedding (fun p : ℚ => p + r) := _ @@ -113,15 +81,6 @@ theorem Real.uniformContinuous_mul (s : Set (ℝ × ℝ)) {r₁ r₂ : ℝ} -- Porting note: moved `TopologicalRing` instance up -instance Real.instCompleteSpace : CompleteSpace ℝ := by - apply complete_of_cauchySeq_tendsto - intro u hu - let c : CauSeq ℝ abs := ⟨u, Metric.cauchySeq_iff'.1 hu⟩ - refine ⟨c.lim, fun s h => ?_⟩ - rcases Metric.mem_nhds_iff.1 h with ⟨ε, ε0, hε⟩ - have := c.equiv_lim ε ε0 - simp only [mem_map, mem_atTop_sets, mem_setOf_eq] - exact this.imp fun N hN n hn => hε (hN n hn) theorem Real.totallyBounded_ball (x ε : ℝ) : TotallyBounded (ball x ε) := by rw [Real.ball_eq_Ioo]; apply totallyBounded_Ioo @@ -156,13 +115,6 @@ lemma closure_of_rat_image_le_le_eq {a b : ℚ} (hab : a ≤ b) : end -instance instIsOrderBornology : IsOrderBornology ℝ where - isBounded_iff_bddBelow_bddAbove s := by - refine ⟨fun bdd ↦ ?_, fun h ↦ isBounded_of_bddAbove_of_bddBelow h.2 h.1⟩ - obtain ⟨r, hr⟩ : ∃ r : ℝ, s ⊆ Icc (-r) r := by - simpa [Real.closedBall_eq_Icc] using bdd.subset_closedBall 0 - exact ⟨bddBelow_Icc.mono hr, bddAbove_Icc.mono hr⟩ - section Periodic namespace Function diff --git a/Mathlib/Topology/Instances/ZMultiples.lean b/Mathlib/Topology/Instances/ZMultiples.lean index f99057489c230..86d3af72f295c 100644 --- a/Mathlib/Topology/Instances/ZMultiples.lean +++ b/Mathlib/Topology/Instances/ZMultiples.lean @@ -6,8 +6,8 @@ Authors: Johannes Hölzl, Mario Carneiro import Mathlib.Algebra.Module.Rat import Mathlib.Algebra.Module.Submodule.Lattice import Mathlib.Topology.Algebra.UniformGroup.Basic -import Mathlib.Topology.Instances.Real import Mathlib.Topology.Metrizable.Basic +import Mathlib.Topology.Instances.Real.Defs /-! The subgroup "multiples of `a`" (`zmultiples a`) is a discrete subgroup of `ℝ`, i.e. its diff --git a/Mathlib/Topology/MetricSpace/Completion.lean b/Mathlib/Topology/MetricSpace/Completion.lean index e80a1ca356e08..6ee51920664d5 100644 --- a/Mathlib/Topology/MetricSpace/Completion.lean +++ b/Mathlib/Topology/MetricSpace/Completion.lean @@ -8,7 +8,7 @@ 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 +import Mathlib.Topology.Instances.Real.Defs /-! # The completion of a metric space diff --git a/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean b/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean index 418ac50aeec57..a7350021d85fd 100644 --- a/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean +++ b/Mathlib/Topology/MetricSpace/PartitionOfUnity.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Topology.EMetricSpace.Paracompact -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas import Mathlib.Analysis.Convex.PartitionOfUnity /-! diff --git a/Mathlib/Topology/Order/Bounded.lean b/Mathlib/Topology/Order/Bounded.lean index 39c572fe4f2d0..03593ab41f4ef 100644 --- a/Mathlib/Topology/Order/Bounded.lean +++ b/Mathlib/Topology/Order/Bounded.lean @@ -5,7 +5,7 @@ Authors: Kalle Kytölä -/ import Mathlib.Topology.Bornology.Basic import Mathlib.Order.LiminfLimsup -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Defs /-! # Relating order and metric boundedness diff --git a/Mathlib/Topology/Semicontinuous.lean b/Mathlib/Topology/Semicontinuous.lean index b569bcd00df4f..7e7a2722675a6 100644 --- a/Mathlib/Topology/Semicontinuous.lean +++ b/Mathlib/Topology/Semicontinuous.lean @@ -5,7 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Algebra.GroupWithZero.Indicator import Mathlib.Topology.ContinuousOn -import Mathlib.Topology.Instances.ENNReal +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Semicontinuous maps diff --git a/Mathlib/Topology/UnitInterval.lean b/Mathlib/Topology/UnitInterval.lean index 5cecb700fae18..791e5ef88fff0 100644 --- a/Mathlib/Topology/UnitInterval.lean +++ b/Mathlib/Topology/UnitInterval.lean @@ -5,7 +5,7 @@ Authors: Patrick Massot, Kim Morrison -/ import Mathlib.Algebra.Order.Interval.Set.Instances import Mathlib.Order.Interval.Set.ProjIcc -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Defs /-! # The unit interval, as a topological space diff --git a/MathlibTest/LibrarySearch/IsCompact.lean b/MathlibTest/LibrarySearch/IsCompact.lean index 0ac0af98ca6a4..04d55b1fadfad 100644 --- a/MathlibTest/LibrarySearch/IsCompact.lean +++ b/MathlibTest/LibrarySearch/IsCompact.lean @@ -1,4 +1,4 @@ -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Lemmas import Mathlib.Topology.Order.Compact -- TODO: uses sorry, but is hidden behind the `apply?` diff --git a/MathlibTest/peel.lean b/MathlibTest/peel.lean index 43417a45546b3..ad17535311985 100644 --- a/MathlibTest/peel.lean +++ b/MathlibTest/peel.lean @@ -1,5 +1,5 @@ import Mathlib.Tactic.Peel -import Mathlib.Topology.Instances.Real +import Mathlib.Topology.Instances.Real.Lemmas open Filter Topology From e9171f0aa94e85fb70e15de56c59956f613537e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20In=C3=A9s=20de=20Frutos-Fern=C3=A1ndez?= Date: Mon, 13 Jan 2025 15:16:20 +0000 Subject: [PATCH 204/681] feat(Algebra/Order/Ring/Unbundled/Nonneg.lean): add boundedness lemmas (#18172) Lemmas about limsup and bddAbove needed for #15373. Co-authored-by: Yury G. Kudryashov --- .../Order/GroupWithZero/Unbundled.lean | 19 +++++++-- .../Algebra/Order/Ring/Unbundled/Nonneg.lean | 23 +++++++++++ Mathlib/Order/LiminfLimsup.lean | 39 +++++++++++++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean index b9105af63bd8c..a3293d637c8a9 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean @@ -957,6 +957,21 @@ end LinearOrder end MulOneClass +section MulZero + +variable [Mul M₀] [Zero M₀] [Preorder M₀] [Preorder α] {f g : α → M₀} + +lemma Monotone.mul [PosMulMono M₀] [MulPosMono M₀] (hf : Monotone f) (hg : Monotone g) + (hf₀ : ∀ x, 0 ≤ f x) (hg₀ : ∀ x, 0 ≤ g x) : Monotone (f * g) := + fun _ _ h ↦ mul_le_mul (hf h) (hg h) (hg₀ _) (hf₀ _) + +lemma MonotoneOn.mul [PosMulMono M₀] [MulPosMono M₀] {s : Set α } (hf : MonotoneOn f s) + (hg : MonotoneOn g s) (hf₀ : ∀ x ∈ s, 0 ≤ f x) (hg₀ : ∀ x ∈ s, 0 ≤ g x) : + MonotoneOn (f * g) s := + fun _ ha _ hb h ↦ mul_le_mul (hf ha hb h) (hg ha hb h) (hg₀ _ ha) (hf₀ _ hb) + +end MulZero + section MonoidWithZero variable [MonoidWithZero M₀] @@ -1085,10 +1100,6 @@ lemma Antitone.mul_const [MulPosMono M₀] (hf : Antitone f) (ha : 0 ≤ a) : lemma Antitone.const_mul [PosMulMono M₀] (hf : Antitone f) (ha : 0 ≤ a) : Antitone fun x ↦ a * f x := (monotone_mul_left_of_nonneg ha).comp_antitone hf -lemma Monotone.mul [PosMulMono M₀] [MulPosMono M₀] (hf : Monotone f) (hg : Monotone g) - (hf₀ : ∀ x, 0 ≤ f x) (hg₀ : ∀ x, 0 ≤ g x) : Monotone (f * g) := - fun _ _ h ↦ mul_le_mul (hf h) (hg h) (hg₀ _) (hf₀ _) - end Preorder diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Nonneg.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Nonneg.lean index 1993a125516c0..69612ba8a75c1 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Nonneg.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Nonneg.lean @@ -324,3 +324,26 @@ theorem mk_sub_mk [Sub α] {x y : α} (hx : 0 ≤ x) (hy : 0 ≤ y) : end LinearOrder end Nonneg + +/-- A variant of `BddAbove.range_comp` that assumes that `f` is nonnegative and `g` is monotone on + nonnegative values. -/ +lemma BddAbove.range_comp_of_nonneg {α β γ : Type*} [Nonempty α] [Preorder β] [Zero β] [Preorder γ] + {f : α → β} {g : β → γ} (hf : BddAbove (range f)) (hf0 : 0 ≤ f) + (hg : MonotoneOn g {x : β | 0 ≤ x}) : BddAbove (range (fun x => g (f x))) := by + have hg' : BddAbove (g '' (range f)) := by + apply hg.map_bddAbove (by rintro x ⟨a, rfl⟩; exact hf0 a) + · obtain ⟨b, hb⟩ := hf + use b, hb + simp only [mem_upperBounds, mem_range, forall_exists_index, forall_apply_eq_imp_iff] at hb + exact le_trans (hf0 Classical.ofNonempty) (hb Classical.ofNonempty) + change BddAbove (range (g ∘ f)) + simpa only [Set.range_comp] using hg' + +/-- If `u v : α → β` are nonnegative and bounded above, then `u * v` is bounded above. -/ +theorem bddAbove_range_mul {α β : Type*} [Nonempty α] {u v : α → β} [Preorder β] [Zero β] [Mul β] + [PosMulMono β] [MulPosMono β] (hu : BddAbove (Set.range u)) (hu0 : 0 ≤ u) + (hv : BddAbove (Set.range v)) (hv0 : 0 ≤ v) : BddAbove (Set.range (u * v)) := + letI : Zero (β × β) := ⟨(0, 0)⟩ + BddAbove.range_comp_of_nonneg (f := fun i ↦ (u i, v i)) (g := fun x ↦ x.1 * x.2) + (bddAbove_range_prod.mpr ⟨hu, hv⟩) (fun x ↦ ⟨hu0 x, hv0 x⟩) ((monotone_fst.monotoneOn _).mul + (monotone_snd.monotoneOn _) (fun _ hx ↦ hx.1) (fun _ hx ↦ hx.2)) diff --git a/Mathlib/Order/LiminfLimsup.lean b/Mathlib/Order/LiminfLimsup.lean index e8cc02503ba11..5956cf5e2f2cf 100644 --- a/Mathlib/Order/LiminfLimsup.lean +++ b/Mathlib/Order/LiminfLimsup.lean @@ -1303,6 +1303,45 @@ theorem eventually_lt_of_limsup_lt {f : Filter α} [ConditionallyCompleteLinearO ∀ᶠ a in f, u a < b := eventually_lt_of_lt_liminf (β := βᵒᵈ) h hu +section ConditionallyCompleteLinearOrder + +variable [ConditionallyCompleteLinearOrder α] + +/-- If `Filter.limsup u atTop ≤ x`, then for all `ε > 0`, eventually we have `u b < x + ε`. -/ +theorem eventually_lt_add_pos_of_limsup_le [Preorder β] [AddMonoid α] [AddLeftStrictMono α] + {x ε : α} {u : β → α} (hu_bdd : IsBoundedUnder LE.le atTop u) (hu : Filter.limsup u atTop ≤ x) + (hε : 0 < ε) : + ∀ᶠ b : β in atTop, u b < x + ε := + eventually_lt_of_limsup_lt (lt_of_le_of_lt hu (lt_add_of_pos_right x hε)) hu_bdd + +/-- If `x ≤ Filter.liminf u atTop`, then for all `ε < 0`, eventually we have `x + ε < u b`. -/ +theorem eventually_add_neg_lt_of_le_liminf [Preorder β] [AddMonoid α] [AddLeftStrictMono α] + {x ε : α} {u : β → α} (hu_bdd : IsBoundedUnder GE.ge atTop u) (hu : x ≤ Filter.liminf u atTop ) + (hε : ε < 0) : + ∀ᶠ b : β in atTop, x + ε < u b := + eventually_lt_of_lt_liminf (lt_of_lt_of_le (add_lt_of_neg_right x hε) hu) hu_bdd + +/-- If `Filter.limsup u atTop ≤ x`, then for all `ε > 0`, there exists a positive natural + number `n` such that `u n < x + ε`. -/ +theorem exists_lt_of_limsup_le [AddMonoid α] [AddLeftStrictMono α] {x ε : α} {u : ℕ → α} + (hu_bdd : IsBoundedUnder LE.le atTop u) (hu : Filter.limsup u atTop ≤ x) (hε : 0 < ε) : + ∃ n : PNat, u n < x + ε := by + have h : ∀ᶠ n : ℕ in atTop, u n < x + ε := eventually_lt_add_pos_of_limsup_le hu_bdd hu hε + simp only [eventually_atTop] at h + obtain ⟨n, hn⟩ := h + exact ⟨⟨n + 1, Nat.succ_pos _⟩, hn (n + 1) (Nat.le_succ _)⟩ + +/-- If `x ≤ Filter.liminf u atTop`, then for all `ε < 0`, there exists a positive natural + number `n` such that ` x + ε < u n`. -/ +theorem exists_lt_of_le_liminf [AddMonoid α] [AddLeftStrictMono α] {x ε : α} {u : ℕ → α} + (hu_bdd : IsBoundedUnder GE.ge atTop u) (hu : x ≤ Filter.liminf u atTop) (hε : ε < 0) : + ∃ n : PNat, x + ε < u n := by + have h : ∀ᶠ n : ℕ in atTop, x + ε < u n := eventually_add_neg_lt_of_le_liminf hu_bdd hu hε + simp only [eventually_atTop] at h + obtain ⟨n, hn⟩ := h + exact ⟨⟨n + 1, Nat.succ_pos _⟩, hn (n + 1) (Nat.le_succ _)⟩ +end ConditionallyCompleteLinearOrder + theorem le_limsup_of_frequently_le {α β} [ConditionallyCompleteLinearOrder β] {f : Filter α} {u : α → β} {b : β} (hu_le : ∃ᶠ x in f, b ≤ u x) (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault) : From a45eba024b4a51c35873933a90d377b9e6428bb1 Mon Sep 17 00:00:00 2001 From: grunweg Date: Mon, 13 Jan 2025 15:16:22 +0000 Subject: [PATCH 205/681] chore(WittVector): document more notation (#20683) Co-authored-by: grunweg --- Mathlib/RingTheory/WittVector/Isocrystal.lean | 22 ++++++++++++++----- scripts/nolints.json | 7 ------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Mathlib/RingTheory/WittVector/Isocrystal.lean b/Mathlib/RingTheory/WittVector/Isocrystal.lean index 38d771bf5257c..6686048e8f6fd 100644 --- a/Mathlib/RingTheory/WittVector/Isocrystal.lean +++ b/Mathlib/RingTheory/WittVector/Isocrystal.lean @@ -61,6 +61,7 @@ namespace WittVector variable (p : ℕ) [Fact p.Prime] variable (k : Type*) [CommRing k] +/-- The fraction ring of the space of `p`-Witt vectors on `k` -/ scoped[Isocrystal] notation "K(" p ", " k ")" => FractionRing (WittVector p k) open Isocrystal @@ -76,10 +77,12 @@ variable [IsDomain k] [CharP k p] [PerfectRing k p] def FractionRing.frobenius : K(p, k) ≃+* K(p, k) := IsFractionRing.ringEquivOfRingEquiv (frobeniusEquiv p k) -/-- The Frobenius automorphism of `k` induces an endomorphism of `K`. For notation purposes. -/ +/-- The Frobenius automorphism of `k` induces an endomorphism of `K`. For notation purposes. +Notation `φ(p, k)` in the `Isocrystal` namespace. -/ def FractionRing.frobeniusRingHom : K(p, k) →+* K(p, k) := FractionRing.frobenius p k +@[inherit_doc] scoped[Isocrystal] notation "φ(" p ", " k ")" => WittVector.FractionRing.frobeniusRingHom p k instance inv_pair₁ : RingHomInvPair φ(p, k) (FractionRing.frobenius p k).symm := @@ -89,10 +92,12 @@ instance inv_pair₂ : RingHomInvPair ((FractionRing.frobenius p k).symm : K(p, (FractionRing.frobenius p k) := RingHomInvPair.of_ringEquiv (FractionRing.frobenius p k).symm +/-- The Frobenius automorphism of `k`, as a linear map -/ scoped[Isocrystal] notation3:50 M " →ᶠˡ[" p ", " k "] " M₂ => LinearMap (WittVector.FractionRing.frobeniusRingHom p k) M M₂ +/-- The Frobenius automorphism of `k`, as a linear equivalence -/ scoped[Isocrystal] notation3:50 M " ≃ᶠˡ[" p ", " k "] " M₂ => LinearEquiv (WittVector.FractionRing.frobeniusRingHom p k) M M₂ @@ -120,21 +125,26 @@ def Isocrystal.frobenius : V ≃ᶠˡ[p, k] V := variable (V) -scoped[Isocrystal] notation "Φ(" p ", " k ")" => WittVector.Isocrystal.frobenius p k +@[inherit_doc] scoped[Isocrystal] notation "Φ(" p ", " k ")" => WittVector.Isocrystal.frobenius p k -/-- A homomorphism between isocrystals respects the Frobenius map. -/ +/-- A homomorphism between isocrystals respects the Frobenius map. +Notation `M →ᶠⁱ [p, k]` in the `Isocrystal` namespace. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. @[nolint has_nonempty_instance] structure IsocrystalHom extends V →ₗ[K(p, k)] V₂ where frob_equivariant : ∀ x : V, Φ(p, k) (toLinearMap x) = toLinearMap (Φ(p, k) x) -/-- An isomorphism between isocrystals respects the Frobenius map. -/ +/-- An isomorphism between isocrystals respects the Frobenius map. + +Notation `M ≃ᶠⁱ [p, k]` in the `Isocrystal` namespace. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. @[nolint has_nonempty_instance] structure IsocrystalEquiv extends V ≃ₗ[K(p, k)] V₂ where frob_equivariant : ∀ x : V, Φ(p, k) (toLinearEquiv x) = toLinearEquiv (Φ(p, k) x) -scoped[Isocrystal] notation:50 M " →ᶠⁱ[" p ", " k "] " M₂ => WittVector.IsocrystalHom p k M M₂ +@[inherit_doc] scoped[Isocrystal] +notation:50 M " →ᶠⁱ[" p ", " k "] " M₂ => WittVector.IsocrystalHom p k M M₂ -scoped[Isocrystal] notation:50 M " ≃ᶠⁱ[" p ", " k "] " M₂ => WittVector.IsocrystalEquiv p k M M₂ +@[inherit_doc] scoped[Isocrystal] +notation:50 M " ≃ᶠⁱ[" p ", " k "] " M₂ => WittVector.IsocrystalEquiv p k M M₂ end PerfectRing diff --git a/scripts/nolints.json b/scripts/nolints.json index 4720d32086c9d..d2824c5a15099 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -158,13 +158,6 @@ ["docBlame", "Int.decNonneg"], ["docBlame", "IntermediateField.delabAdjoinNotation"], ["docBlame", "IsAdjoinRoot.map"], - ["docBlame", "Isocrystal.«termK(_,_)»"], - ["docBlame", "Isocrystal.«term_→ᶠˡ[_,_]_»"], - ["docBlame", "Isocrystal.«term_→ᶠⁱ[_,_]_»"], - ["docBlame", "Isocrystal.«term_≃ᶠˡ[_,_]_»"], - ["docBlame", "Isocrystal.«term_≃ᶠⁱ[_,_]_»"], - ["docBlame", "Isocrystal.«termΦ(_,_)»"], - ["docBlame", "Isocrystal.«termφ(_,_)»"], ["docBlame", "JordanHolderLattice.IsMaximal"], ["docBlame", "JordanHolderLattice.Iso"], ["docBlame", "Kronecker.«term_⊗ₖ_»"], From a1c2c42dff9005625384455a1415142d7fb04a98 Mon Sep 17 00:00:00 2001 From: blizzard_inc Date: Mon, 13 Jan 2025 15:16:23 +0000 Subject: [PATCH 206/681] chore(RingTheory/Extension): Simplify algebra instance by using def. (#20708) As suggested in the conversation around #20518 , the algebra instance has been subsumed by a definition, and this PR makes the replacement. --- Mathlib/RingTheory/Extension.lean | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Mathlib/RingTheory/Extension.lean b/Mathlib/RingTheory/Extension.lean index 649d094f87f48..b64aada4929d9 100644 --- a/Mathlib/RingTheory/Extension.lean +++ b/Mathlib/RingTheory/Extension.lean @@ -62,11 +62,7 @@ attribute [simp] algebraMap_σ -- We want to make sure `R₀` acts compatibly on `R` and `S` to avoid unsensical instances @[nolint unusedArguments] noncomputable instance {R₀} [CommRing R₀] [Algebra R₀ R] [Algebra R₀ S] [IsScalarTower R₀ R S] : - Algebra R₀ P.Ring where - __ := Module.compHom P.Ring (algebraMap R₀ R) - algebraMap := (algebraMap R P.Ring).comp (algebraMap R₀ R) - smul_def' _ _ := smul_def _ _ - commutes' _ _ := commutes _ _ + Algebra R₀ P.Ring := Algebra.compHom P.Ring (algebraMap R₀ R) instance {R₀} [CommRing R₀] [Algebra R₀ R] [Algebra R₀ S] [IsScalarTower R₀ R S] : IsScalarTower R₀ R P.Ring := IsScalarTower.of_algebraMap_eq' rfl From 3861c398b4dbb35f4114d77a1badfcf038a8586f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Mon, 13 Jan 2025 16:13:58 +0000 Subject: [PATCH 207/681] doc(Order/InitialSeg): Improve documentation (#15874) The file previously conflated initial segments and their embeddings. Our docstrings are now more careful about the distinction. --- Mathlib/Order/InitialSeg.lean | 82 +++++++++++++++++------------------ 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/Mathlib/Order/InitialSeg.lean b/Mathlib/Order/InitialSeg.lean index d00f90a854fe1..422bdd991e55c 100644 --- a/Mathlib/Order/InitialSeg.lean +++ b/Mathlib/Order/InitialSeg.lean @@ -12,16 +12,20 @@ import Mathlib.Order.WellFounded /-! # Initial and principal segments -This file defines initial and principal segments. +This file defines initial and principal segment embeddings. Though these definitions make sense for +arbitrary relations, they're intended for use with well orders. + +An initial segment is simply a lower set, i.e. if `x` belongs to the range, then any `y < x` also +belongs to the range. A principal segment is a set of the form `Set.Iio x` for some `x`. + +An initial segment embedding `r ≼i s` is an order embedding `r ↪ s` such that its range is an +initial segment. Likewise, a principal segment embedding `r ≺i s` has a principal segment for a +range. ## Main definitions -* `InitialSeg r s`: type of order embeddings of `r` into `s` for which the range is an initial - segment (i.e., if `b` belongs to the range, then any `b' < b` also belongs to the range). - It is denoted by `r ≼i s`. -* `PrincipalSeg r s`: Type of order embeddings of `r` into `s` for which the range is a principal - segment, i.e., an interval of the form `(-∞, top)` for some element `top`. It is denoted by - `r ≺i s`. +* `InitialSeg r s`: Type of initial segment embeddings of `r` into `s` , denoted by `r ≼i s`. +* `PrincipalSeg r s`: Type of principal segment embeddings of `r` into `s` , denoted by `r ≺i s`. The lemmas `Ordinal.type_le_iff` and `Ordinal.type_lt_iff` tell us that `≼i` corresponds to the `≤` relation on ordinals, while `≺i` corresponds to the `<` relation. This prompts us to think of @@ -37,14 +41,7 @@ These notations belong to the `InitialSeg` locale. * `α and_congr_left fun hx => IH _ hx ▸ Iff.rfl +/-- Given a well order `s`, there is at most one initial segment embedding of `r` into `s`. -/ instance [IsWellOrder β s] : Subsingleton (r ≼i s) := ⟨fun a => have := a.isWellFounded; Subsingleton.elim a⟩ @@ -185,8 +183,8 @@ alias ltOrEq_apply_right := eq_relIso private theorem antisymm_aux [IsWellOrder α r] (f : r ≼i s) (g : s ≼i r) : LeftInverse g f := (f.trans g).eq (InitialSeg.refl _) -/-- If we have order embeddings between `α` and `β` whose images are initial segments, and `β` -is a well-order then `α` and `β` are order-isomorphic. -/ +/-- If we have order embeddings between `α` and `β` whose ranges are initial segments, and `β` is a +well order, then `α` and `β` are order-isomorphic. -/ def antisymm [IsWellOrder β s] (f : r ≼i s) (g : s ≼i r) : r ≃r s := have := f.toRelEmbedding.isWellOrder ⟨⟨f, g, antisymm_aux f g, antisymm_aux g f⟩, f.map_rel_iff'⟩ @@ -200,6 +198,9 @@ theorem antisymm_symm [IsWellOrder α r] [IsWellOrder β s] (f : r ≼i s) (g : (antisymm f g).symm = antisymm g f := RelIso.coe_fn_injective rfl +/-- An initial segment embedding is either an isomorphism, or a principal segment embedding. + +See also `InitialSeg.ltOrEq`. -/ theorem eq_or_principal [IsWellOrder β s] (f : r ≼i s) : Surjective f ∨ ∃ b, ∀ x, x ∈ Set.range f ↔ s x b := by apply or_iff_not_imp_right.2 @@ -225,7 +226,7 @@ def codRestrict (p : Set β) (f : r ≼i s) (H : ∀ a, f a ∈ p) : r ≼i Subr theorem codRestrict_apply (p) (f : r ≼i s) (H a) : codRestrict p f H a = ⟨f a, H a⟩ := rfl -/-- Initial segment from an empty type. -/ +/-- Initial segment embedding from an empty type. -/ def ofIsEmpty (r : α → α → Prop) (s : β → β → Prop) [IsEmpty α] : r ≼i s := ⟨RelEmbedding.ofIsEmpty r s, isEmptyElim⟩ @@ -246,19 +247,11 @@ protected theorem acc (f : r ≼i s) (a : α) : Acc r a ↔ Acc s (f a) := end InitialSeg -/-! -### Principal segments - -Order embeddings whose range is a principal segment of `s` (i.e., an interval of the form -`(-∞, top)` for some element `top` of `β`). The type of these embeddings from `r` to `s` is called -`PrincipalSeg r s`, and denoted by `r ≺i s`. Principal segments are in particular initial -segments. --/ - +/-! ### Principal segments -/ -/-- If `r` is a relation on `α` and `s` in a relation on `β`, then `f : r ≺i s` is an order -embedding whose range is an open interval `(-∞, top)` for some element `top` of `β`. Such order -embeddings are called principal segments -/ +/-- If `r` is a relation on `α` and `s` in a relation on `β`, then `f : r ≺i s` is an initial +segment embedding whose range is `Set.Iio x` for some element `x`. If `β` is a well order, this is +equivalent to the embedding not being surjective. -/ structure PrincipalSeg {α β : Type*} (r : α → α → Prop) (s : β → β → Prop) extends r ↪r s where /-- The supremum of the principal segment -/ top : β @@ -326,7 +319,7 @@ theorem surjOn (f : r ≺i s) : Set.SurjOn f Set.univ { b | s b f.top } := by intro b h simpa using mem_range_of_rel_top _ h -/-- A principal segment is in particular an initial segment. -/ +/-- A principal segment embedding is in particular an initial segment embedding. -/ instance hasCoeInitialSeg [IsTrans β s] : Coe (r ≺i s) (r ≼i s) := ⟨fun f => ⟨f.toRelEmbedding, fun _ _ => f.mem_range_of_rel⟩⟩ @@ -365,7 +358,8 @@ theorem irrefl {r : α → α → Prop} [IsWellOrder α r] (f : r ≺i r) : Fals instance (r : α → α → Prop) [IsWellOrder α r] : IsEmpty (r ≺i r) := ⟨fun f => f.irrefl⟩ -/-- Composition of a principal segment with an initial segment, as a principal segment -/ +/-- Composition of a principal segment embedding with an initial segment embedding, as a principal +segment embedding -/ def transInitial (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 [g.exists_eq_iff_rel, ← PrincipalSeg.mem_range_iff_rel, exists_swap, ← exists_and_left]⟩ @@ -391,7 +385,7 @@ set_option linter.deprecated false in theorem lt_le_top (f : r ≺i s) (g : s ≼i t) : (f.ltLe g).top = g f.top := rfl -/-- Composition of two principal segments as a principal segment. -/ +/-- Composition of two principal segment embeddings as a principal segment embedding -/ @[trans] protected def trans [IsTrans γ t] (f : r ≺i s) (g : s ≺i t) : r ≺i t := transInitial f g @@ -404,7 +398,8 @@ theorem trans_apply [IsTrans γ t] (f : r ≺i s) (g : s ≺i t) (a : α) : f.tr theorem trans_top [IsTrans γ t] (f : r ≺i s) (g : s ≺i t) : (f.trans g).top = g f.top := rfl -/-- Composition of an order isomorphism with a principal segment, as a principal segment. -/ +/-- Composition of an order isomorphism with a principal segment embedding, as a principal +segment embedding -/ def relIsoTrans (f : r ≃r s) (g : s ≺i t) : r ≺i t := ⟨@RelEmbedding.trans _ _ _ r s t f g, g.top, fun c => by simp [g.mem_range_iff_rel]⟩ @@ -429,7 +424,8 @@ set_option linter.deprecated false in theorem equivLT_top (f : r ≃r s) (g : s ≺i t) : (equivLT f g).top = g.top := rfl -/-- Composition of a principal segment with an order isomorphism, as a principal segment -/ +/-- Composition of a principal segment embedding with a relation isomorphism, as a principal segment +embedding -/ def transRelIso (f : r ≺i s) (g : s ≃r t) : r ≺i t := transInitial f g.toInitialSeg @@ -462,7 +458,7 @@ theorem top_rel_top {r : α → α → Prop} {s : β → β → Prop} {t : γ @[deprecated top_rel_top (since := "2024-10-10")] alias topLTTop := top_rel_top -/-- Any element of a well order yields a principal segment. -/ +/-- Build a principal segment embedding into a given interval `{ b | r b a }`. -/ -- The explicit typing is required in order for `simp` to work properly. @[simps!] def ofElement {α : Type*} (r : α → α → Prop) (a : α) : @@ -489,7 +485,7 @@ theorem apply_subrelIso (f : r ≺i s) (b : {b | s b f.top}) : f (f.subrelIso b) theorem subrelIso_apply (f : r ≺i s) (a : α) : f.subrelIso ⟨f a, f.lt_top a⟩ = a := Equiv.ofInjective_symm_apply f.injective _ -/-- Restrict the codomain of a principal segment -/ +/-- Restrict the codomain of a principal segment embedding. -/ def codRestrict (p : Set β) (f : r ≺i s) (H : ∀ a, f a ∈ p) (H₂ : f.top ∈ p) : r ≺i Subrel s p := ⟨RelEmbedding.codRestrict p f H, ⟨f.top, H₂⟩, fun ⟨_, _⟩ => by simp [← f.mem_range_iff_rel]⟩ @@ -532,9 +528,8 @@ theorem wellFounded_iff_principalSeg.{u} {β : Type u} {s : β → β → Prop} namespace InitialSeg open Classical in -/-- To an initial segment taking values in a well order, one can associate either a principal -segment (if the range is not everything, taking the top the minimum of the complement of the range) -or an order isomorphism (if the range is everything). -/ +/-- Every initial segment embedding into a well order can be turned into an isomorphism if +surjective, or into a principal segment embedding if not. -/ noncomputable def principalSumRelIso [IsWellOrder β s] (f : r ≼i s) : (r ≺i s) ⊕ (r ≃r s) := if h : Surjective f then Sum.inr (RelIso.ofSurjective f h) @@ -543,7 +538,8 @@ noncomputable def principalSumRelIso [IsWellOrder β s] (f : r ≼i s) : (r ≺i @[deprecated principalSumRelIso (since := "2024-10-20")] alias ltOrEq := principalSumRelIso -/-- Composition of an initial segment taking values in a well order and a principal segment. -/ +/-- Composition of an initial segment embedding and a principal segment embedding as a principal +segment embedding -/ noncomputable def transPrincipal [IsWellOrder β s] [IsTrans γ t] (f : r ≼i s) (g : s ≺i t) : r ≺i t := match f.principalSumRelIso with From 90fd1e097d4c6f8b82893f4a2b4ba3f8d9823fc5 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 13 Jan 2025 17:00:55 +0000 Subject: [PATCH 208/681] chore: address some porting notes about coercions of equivs (#20714) I came across a few porting notes about removing `toFun_eq_coe`. We in fact do want to have this lemma for rewriting, but not as a `@[simp]` lemma. So readd the missing `toFun_eq_coe` lemmas, and turn some porting notes into doc comments. In those files, also clean up some other porting notes about coercions: it looks like there were some workarounds that are now unnecessary. --- Mathlib/Algebra/Algebra/Equiv.lean | 9 ++++----- Mathlib/Algebra/Group/Equiv/Basic.lean | 16 +++++++--------- Mathlib/LinearAlgebra/Finsupp/SumProd.lean | 5 +---- Mathlib/Topology/Hom/Open.lean | 3 ++- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index 37da0ae421201..32d000a5799d1 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -141,7 +141,9 @@ theorem coe_fun_injective : @Function.Injective (A₁ ≃ₐ[R] A₂) (A₁ → instance hasCoeToRingEquiv : CoeOut (A₁ ≃ₐ[R] A₂) (A₁ ≃+* A₂) := ⟨AlgEquiv.toRingEquiv⟩ --- Porting note: `toFun_eq_coe` no longer needed in Lean4 +@[simp] +theorem coe_toEquiv : ((e : A₁ ≃ A₂) : A₁ → A₂) = e := + rfl @[simp] theorem toRingEquiv_eq_coe : e.toRingEquiv = e := @@ -161,7 +163,6 @@ theorem coe_ringEquiv' : (e.toRingEquiv : A₁ → A₂) = e := theorem coe_ringEquiv_injective : Function.Injective ((↑) : (A₁ ≃ₐ[R] A₂) → A₁ ≃+* A₂) := fun _ _ h => ext <| RingEquiv.congr_fun h --- Porting note: Added [coe] attribute /-- Interpret an algebra equivalence as an algebra homomorphism. This definition is included for symmetry with the other `to*Hom` projections. @@ -285,7 +286,7 @@ theorem coe_coe_symm_apply_coe_apply {F : Type*} [EquivLike F A₁ A₂] [AlgEqu (f : A₁ ≃ₐ[R] A₂).symm (f x) = x := EquivLike.left_inv f x --- Porting note: `simp` normal form of `invFun_eq_symm` +/-- `simp` normal form of `invFun_eq_symm` -/ @[simp] theorem symm_toEquiv_eq_symm {e : A₁ ≃ₐ[R] A₂} : (e : A₁ ≃ A₂).symm = e.symm := rfl @@ -359,12 +360,10 @@ end symm section simps --- Porting note: the default simps projection was `e.toEquiv.toFun`, it should be `FunLike.coe` /-- See Note [custom simps projection] -/ def Simps.apply (e : A₁ ≃ₐ[R] A₂) : A₁ → A₂ := e --- Porting note: the default simps projection was `e.toEquiv`, it should be `EquivLike.toEquiv` /-- See Note [custom simps projection] -/ def Simps.toEquiv (e : A₁ ≃ₐ[R] A₂) : A₁ ≃ A₂ := e diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index 30605dc8e53f9..036274253a7de 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -214,19 +214,19 @@ theorem mk_coe (e : M ≃* N) (e' h₁ h₂ h₃) : (⟨⟨e, e', h₁, h₂⟩, theorem toEquiv_eq_coe (f : M ≃* N) : f.toEquiv = f := rfl --- Porting note: added, to simplify `f.toMulHom` back to the coercion via `MulHomClass.toMulHom`. +/-- The `simp`-normal form to turn something into a `MulHom` is via `MulHomClass.toMulHom`. -/ @[to_additive (attr := simp)] theorem toMulHom_eq_coe (f : M ≃* N) : f.toMulHom = ↑f := rfl --- Porting note: `to_fun_eq_coe` no longer needed in Lean4 +@[to_additive] +theorem toFun_eq_coe (f : M ≃* N) : f.toFun = f := rfl +/-- `simp`-normal form of `toFun_eq_coe`. -/ @[to_additive (attr := simp)] theorem coe_toEquiv (f : M ≃* N) : ⇑(f : M ≃ N) = f := rfl --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: `MulHom.coe_mk` simplifies `↑f.toMulHom` to `f.toMulHom.toFun`, --- not `f.toEquiv.toFun`; use higher priority as a workaround -@[to_additive (attr := simp 1100)] +@[to_additive (attr := simp)] theorem coe_toMulHom {f : M ≃* N} : (f.toMulHom : M → N) = f := rfl /-- Makes a multiplicative isomorphism from a bijection which preserves multiplication. -/ @@ -300,10 +300,10 @@ lemma symm_map_mul {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) (x y : N) : def symm {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) : N ≃* M := ⟨h.toEquiv.symm, h.symm_map_mul⟩ -@[to_additive] -- Porting note: no longer a `simp`, see below +@[to_additive] theorem invFun_eq_symm {f : M ≃* N} : f.invFun = f.symm := rfl --- Porting note: to_additive translated the name incorrectly in mathlib 3. +/-- `simp`-normal form of `invFun_eq_symm`. -/ @[to_additive (attr := simp)] theorem coe_toEquiv_symm (f : M ≃* N) : ((f : M ≃ N).symm : N → M) = f.symm := rfl @@ -313,8 +313,6 @@ theorem equivLike_inv_eq_symm (f : M ≃* N) : EquivLike.inv f = f.symm := rfl @[to_additive (attr := simp)] theorem toEquiv_symm (f : M ≃* N) : (f.symm : N ≃ M) = (f : M ≃ N).symm := rfl --- Porting note: `toEquiv_mk` no longer needed in Lean4 - @[to_additive (attr := simp)] theorem symm_symm (f : M ≃* N) : f.symm.symm = f := rfl diff --git a/Mathlib/LinearAlgebra/Finsupp/SumProd.lean b/Mathlib/LinearAlgebra/Finsupp/SumProd.lean index d907f5ab35ad0..71db91ba13f99 100644 --- a/Mathlib/LinearAlgebra/Finsupp/SumProd.lean +++ b/Mathlib/LinearAlgebra/Finsupp/SumProd.lean @@ -42,10 +42,7 @@ def sumFinsuppLEquivProdFinsupp {α β : Type*} : (α ⊕ β →₀ M) ≃ₗ[R] map_smul' := by intros ext <;> - -- Porting note: `add_equiv.to_fun_eq_coe` → - -- `Equiv.toFun_as_coe` & `AddEquiv.toEquiv_eq_coe` & `AddEquiv.coe_toEquiv` - simp only [Equiv.toFun_as_coe, AddEquiv.toEquiv_eq_coe, AddEquiv.coe_toEquiv, Prod.smul_fst, - Prod.smul_snd, smul_apply, + simp only [AddEquiv.toFun_eq_coe, Prod.smul_fst, Prod.smul_snd, smul_apply, snd_sumFinsuppAddEquivProdFinsupp, fst_sumFinsuppAddEquivProdFinsupp, RingHom.id_apply] } diff --git a/Mathlib/Topology/Hom/Open.lean b/Mathlib/Topology/Hom/Open.lean index 172c3803ea904..70852f265d096 100644 --- a/Mathlib/Topology/Hom/Open.lean +++ b/Mathlib/Topology/Hom/Open.lean @@ -73,7 +73,8 @@ instance : ContinuousOpenMapClass (α →CO β) α β where theorem toFun_eq_coe {f : α →CO β} : f.toFun = (f : α → β) := rfl -@[simp] -- Porting note: new, simpNF of `toFun_eq_coe` +/-- `simp`-normal form of `toFun_eq_coe`. -/ +@[simp] theorem coe_toContinuousMap (f : α →CO β) : (f.toContinuousMap : α → β) = f := rfl @[ext] From 14815c9c95b6dffe910b401aa93de70aab0e2d3d Mon Sep 17 00:00:00 2001 From: grunweg Date: Mon, 13 Jan 2025 17:41:10 +0000 Subject: [PATCH 209/681] feat: lemmas about the left and right boundary point under `Icc{Left,Right}Chart` (#15891) Another step towards proving that a non-empty the real interval $[x,y]$ has boundary ${ x,y }$ (as a manifold). Add missing `Icc.coe_top` and `Icc.coe_bot` lemmas. Co-authored-by: Michael Rothgang --- Mathlib/Geometry/Manifold/Instances/Real.lean | 50 +++++++++++++++++-- Mathlib/Order/LatticeIntervals.lean | 6 +++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index 53744ed74a346..55635af781f7f 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -39,7 +39,6 @@ The manifold structure on the interval `[x, y] = Icc x y` requires the assumptio typeclass. We provide it as `[Fact (x < y)]`. -/ - noncomputable section open Set Function @@ -78,6 +77,12 @@ instance [NeZero n] : Inhabited (EuclideanHalfSpace n) := instance : Inhabited (EuclideanQuadrant n) := ⟨⟨0, fun _ => le_rfl⟩⟩ +instance {n : ℕ} [NeZero n] : Zero (EuclideanHalfSpace n) where + zero := ⟨fun _ ↦ 0, by norm_num⟩ + +instance {n : ℕ} : Zero (EuclideanQuadrant n) where + zero := ⟨fun _ ↦ 0, by norm_num⟩ + @[ext] theorem EuclideanQuadrant.ext (x y : EuclideanQuadrant n) (h : x.1 = y.1) : x = y := Subtype.eq h @@ -229,6 +234,8 @@ scoped[Manifold] (modelWithCornersEuclideanHalfSpace n : ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanHalfSpace n)) +lemma modelWithCornersEuclideanHalfSpace_zero {n : ℕ} [NeZero n] : (𝓡∂ n) 0 = 0 := rfl + lemma range_modelWithCornersEuclideanHalfSpace (n : ℕ) [NeZero n] : range (𝓡∂ n) = { y | 0 ≤ y 0 } := range_euclideanHalfSpace n @@ -256,7 +263,7 @@ def IccLeftChart (x y : ℝ) [h : Fact (x < y)] : source := { z : Icc x y | z.val < y } target := { z : EuclideanHalfSpace 1 | z.val 0 < y - x } toFun := fun z : Icc x y => ⟨fun _ => z.val - x, sub_nonneg.mpr z.property.1⟩ - invFun z := ⟨min (z.val 0 + x) y, by simp [le_refl, z.prop, le_of_lt h.out]⟩ + invFun z := ⟨min (z.val 0 + x) y, by simp [le_refl, z.prop, h.out.le]⟩ map_source' := by simp only [imp_self, sub_lt_sub_iff_right, mem_setOf_eq, forall_true_iff] map_target' := by simp only [min_lt_iff, mem_setOf_eq]; intro z hz; left @@ -295,6 +302,33 @@ def IccLeftChart (x y : ℝ) [h : Fact (x < y)] : have B : Continuous fun z : EuclideanSpace ℝ (Fin 1) => z 0 := continuous_apply 0 exact (A.comp B).comp continuous_subtype_val +variable {x y : ℝ} [hxy : Fact (x < y)] + +namespace Fact.Manifold + +scoped instance : Fact (x ≤ y) := Fact.mk hxy.out.le + +end Fact.Manifold + +open Fact.Manifold + +lemma IccLeftChart_extend_bot : (IccLeftChart x y).extend (𝓡∂ 1) ⊥ = 0 := by + norm_num [IccLeftChart, modelWithCornersEuclideanHalfSpace_zero] + congr + +lemma iccLeftChart_extend_zero {p : Set.Icc x y} : + (IccLeftChart x y).extend (𝓡∂ 1) p 0 = p.val - x := rfl + +lemma IccLeftChart_extend_interior_pos {p : Set.Icc x y} (hp : x < p.val ∧ p.val < y) : + 0 < (IccLeftChart x y).extend (𝓡∂ 1) p 0 := by + simp_rw [iccLeftChart_extend_zero] + norm_num [hp.1] + +lemma IccLeftChart_extend_bot_mem_frontier : + (IccLeftChart x y).extend (𝓡∂ 1) ⊥ ∈ frontier (range (𝓡∂ 1)) := by + rw [IccLeftChart_extend_bot, frontier_range_modelWithCornersEuclideanHalfSpace, + mem_setOf, PiLp.zero_apply] + /-- The right chart for the topological space `[x, y]`, defined on `(x,y]` and sending `y` to `0` in `EuclideanHalfSpace 1`. -/ @@ -304,7 +338,7 @@ def IccRightChart (x y : ℝ) [h : Fact (x < y)] : target := { z : EuclideanHalfSpace 1 | z.val 0 < y - x } toFun z := ⟨fun _ => y - z.val, sub_nonneg.mpr z.property.2⟩ invFun z := - ⟨max (y - z.val 0) x, by simp [le_refl, z.prop, le_of_lt h.out, sub_eq_add_neg]⟩ + ⟨max (y - z.val 0) x, by simp [le_refl, z.prop, h.out.le, sub_eq_add_neg]⟩ map_source' := by simp only [imp_self, mem_setOf_eq, sub_lt_sub_iff_left, forall_true_iff] map_target' := by simp only [lt_max_iff, mem_setOf_eq]; intro z hz; left @@ -343,6 +377,16 @@ def IccRightChart (x y : ℝ) [h : Fact (x < y)] : have B : Continuous fun z : EuclideanSpace ℝ (Fin 1) => z 0 := continuous_apply 0 exact (A.comp B).comp continuous_subtype_val +lemma IccRightChart_extend_top : + (IccRightChart x y).extend (𝓡∂ 1) ⊤ = 0 := by + norm_num [IccRightChart, modelWithCornersEuclideanHalfSpace_zero] + congr + +lemma IccRightChart_extend_right_mem_frontier : + (IccRightChart x y).extend (𝓡∂ 1) ⊤ ∈ frontier (range (𝓡∂ 1)) := by + rw [IccRightChart_extend_top, frontier_range_modelWithCornersEuclideanHalfSpace, + mem_setOf, PiLp.zero_apply] + /-- Charted space structure on `[x, y]`, using only two charts taking values in `EuclideanHalfSpace 1`. -/ diff --git a/Mathlib/Order/LatticeIntervals.lean b/Mathlib/Order/LatticeIntervals.lean index 92db05327eddb..97cf68312a7b3 100644 --- a/Mathlib/Order/LatticeIntervals.lean +++ b/Mathlib/Order/LatticeIntervals.lean @@ -194,10 +194,16 @@ variable [Preorder α] [Fact (a ≤ b)] instance : OrderBot (Icc a b) := (isLeast_Icc Fact.out).orderBot +@[simp, norm_cast] +theorem coe_bot : ↑(⊥ : Icc a b) = a := rfl + /-- `Icc a b` has a top element whenever `a ≤ b`. -/ instance : OrderTop (Icc a b) := (isGreatest_Icc Fact.out).orderTop +@[simp, norm_cast] +theorem coe_top : ↑(⊤ : Icc a b) = b := rfl + /-- `Icc a b` is a `BoundedOrder` whenever `a ≤ b`. -/ instance : BoundedOrder (Icc a b) where From d3d990d01faa095f27f04449c3367dd5b02d9b80 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Mon, 13 Jan 2025 17:41:12 +0000 Subject: [PATCH 210/681] feat: Estimating a finite sum by an interval integral, for the product of a monotone and an antitone function (#20456) From the Carleson project --- Mathlib/Analysis/SumIntegralComparisons.lean | 133 +++++++++++++++++- Mathlib/MeasureTheory/Function/L1Space.lean | 8 ++ .../Function/LocallyIntegrable.lean | 2 +- .../Integral/IntervalIntegral.lean | 9 ++ 4 files changed, 146 insertions(+), 6 deletions(-) diff --git a/Mathlib/Analysis/SumIntegralComparisons.lean b/Mathlib/Analysis/SumIntegralComparisons.lean index b231f62b09887..d58146a6834ce 100644 --- a/Mathlib/Analysis/SumIntegralComparisons.lean +++ b/Mathlib/Analysis/SumIntegralComparisons.lean @@ -15,9 +15,8 @@ It is often the case that error terms in analysis can be computed by comparing an infinite sum to the improper integral of an antitone function. This file will eventually enable that. -At the moment it contains four lemmas in this direction: `AntitoneOn.integral_le_sum`, -`AntitoneOn.sum_le_integral` and versions for monotone functions, which can all be paired -with a `Filter.Tendsto` to estimate some errors. +At the moment it contains several lemmas in this direction, for antitone or monotone functions +(or products of antitone and monotone functions), formulated for sums on `range i` or `Ico a b`. `TODO`: Add more lemmas to the API to directly address limiting issues @@ -31,6 +30,10 @@ with a `Filter.Tendsto` to estimate some errors. values at integer steps aligning with the right-hand side of the interval * `MonotoneOn.sum_le_integral`: The sum of a monotone function along integer steps aligning with the left-hand side of the interval is at most the integral of the function along that interval +* `sum_mul_Ico_le_integral_of_monotone_antitone`: the sum of `f i * g i` on an interval is bounded + by the integral of `f x * g (x - 1)` if `f` is monotone and `g` is antitone. +* `integral_le_sum_mul_Ico_of_antitone_monotone`: the sum of `f i * g i` on an interval is bounded + below by the integral of `f x * g (x - 1)` if `f` is antitone and `g` is monotone. ## Tags @@ -38,9 +41,38 @@ analysis, comparison, asymptotics -/ -open Set MeasureTheory.MeasureSpace +open Set MeasureTheory MeasureSpace -variable {x₀ : ℝ} {a b : ℕ} {f : ℝ → ℝ} +variable {x₀ : ℝ} {a b : ℕ} {f g : ℝ → ℝ} + +lemma sum_Ico_le_integral_of_le + (hab : a ≤ b) (h : ∀ i ∈ Ico a b, ∀ x ∈ Ico (i : ℝ) (i + 1 : ℕ), f i ≤ g x) + (hg : IntegrableOn g (Set.Ico a b)) : + ∑ i ∈ Finset.Ico a b, f i ≤ ∫ x in a..b, g x := by + have A i (hi : i ∈ Finset.Ico a b) : IntervalIntegrable g volume i (i + 1 : ℕ) := by + rw [intervalIntegrable_iff_integrableOn_Ico_of_le (by simp)] + apply hg.mono _ le_rfl + rintro x ⟨hx, h'x⟩ + simp only [Finset.mem_Ico, mem_Ico] at hi ⊢ + exact ⟨le_trans (mod_cast hi.1) hx, h'x.trans_le (mod_cast hi.2)⟩ + calc + ∑ i ∈ Finset.Ico a b, f i + _ = ∑ i ∈ Finset.Ico a b, (∫ x in (i : ℝ)..(i + 1 : ℕ), f i) := by simp + _ ≤ ∑ i ∈ Finset.Ico a b, (∫ x in (i : ℝ)..(i + 1 : ℕ), g x) := by + apply Finset.sum_le_sum (fun i hi ↦ ?_) + apply intervalIntegral.integral_mono_on_of_le_Ioo (by simp) (by simp) (A _ hi) (fun x hx ↦ ?_) + exact h _ (by simpa using hi) _ (Ioo_subset_Ico_self hx) + _ = ∫ x in a..b, g x := by + rw [intervalIntegral.sum_integral_adjacent_intervals_Ico (a := fun i ↦ i) hab] + intro i hi + exact A _ (by simpa using hi) + +lemma integral_le_sum_Ico_of_le + (hab : a ≤ b) (h : ∀ i ∈ Ico a b, ∀ x ∈ Ico (i : ℝ) (i + 1 : ℕ), g x ≤ f i) + (hg : IntegrableOn g (Set.Ico a b)) : + ∫ x in a..b, g x ≤ ∑ i ∈ Finset.Ico a b, f i := by + convert neg_le_neg (sum_Ico_le_integral_of_le (f := -f) (g := -g) hab + (fun i hi x hx ↦ neg_le_neg (h i hi x hx)) hg.neg) <;> simp theorem AntitoneOn.integral_le_sum (hf : AntitoneOn f (Icc x₀ (x₀ + a))) : (∫ x in x₀..x₀ + a, f x) ≤ ∑ i ∈ Finset.range a, f (x₀ + i) := by @@ -160,3 +192,94 @@ theorem MonotoneOn.integral_le_sum_Ico (hab : a ≤ b) (hf : MonotoneOn f (Set.I (∫ x in a..b, f x) ≤ ∑ i ∈ Finset.Ico a b, f (i + 1 : ℕ) := by rw [← neg_le_neg_iff, ← Finset.sum_neg_distrib, ← intervalIntegral.integral_neg] exact hf.neg.sum_le_integral_Ico hab + +lemma sum_mul_Ico_le_integral_of_monotone_antitone + (hab : a ≤ b) (hf : MonotoneOn f (Icc a b)) (hg : AntitoneOn g (Icc (a - 1) (b - 1))) + (fpos : 0 ≤ f a) (gpos : 0 ≤ g (b - 1)) : + ∑ i ∈ Finset.Ico a b, f i * g i ≤ ∫ x in a..b, f x * g (x - 1) := by + apply sum_Ico_le_integral_of_le (f := fun x ↦ f x * g x) hab + · intro i hi x hx + simp only [Nat.cast_add, Nat.cast_one, mem_Ico] at hx hi + have I0 : (i : ℝ) ≤ b - 1 := by + simp only [le_sub_iff_add_le] + norm_cast + omega + have I1 : (i : ℝ) ∈ Icc (a - 1 : ℝ) (b - 1) := by + simp only [mem_Icc, tsub_le_iff_right] + exact ⟨by norm_cast; omega, I0⟩ + have I2 : x ∈ Icc (a : ℝ) b := by + refine ⟨le_trans (mod_cast hi.1) hx.1, hx.2.le.trans ?_⟩ + norm_cast + omega + apply mul_le_mul + · apply hf + · simp only [mem_Icc, Nat.cast_le] + exact ⟨hi.1, hi.2.le⟩ + · exact I2 + · exact hx.1 + · apply hg + · simp only [mem_Icc, tsub_le_iff_right, sub_add_cancel] + refine ⟨le_trans (mod_cast hi.1) hx.1, hx.2.le.trans ?_⟩ + norm_cast + omega + · exact I1 + · simpa [sub_le_iff_le_add] using hx.2.le + · apply gpos.trans + apply hg I1 (by simp [hab]) I0 + · apply fpos.trans + apply hf (by simp [hab]) I2 + exact le_trans (mod_cast hi.1) hx.1 + · apply Integrable.mono_measure _ (Measure.restrict_mono_set _ Ico_subset_Icc_self) + apply Integrable.mul_of_top_left + · exact hf.integrableOn_isCompact isCompact_Icc + · apply AntitoneOn.memℒp_isCompact isCompact_Icc + intro x hx y hy hxy + apply hg + · simpa using hx + · simpa using hy + · simpa using hxy + +lemma integral_le_sum_mul_Ico_of_antitone_monotone + (hab : a ≤ b) (hf : AntitoneOn f (Icc a b)) (hg : MonotoneOn g (Icc (a - 1) (b - 1))) + (fpos : 0 ≤ f b) (gpos : 0 ≤ g (a - 1)) : + ∫ x in a..b, f x * g (x - 1) ≤ ∑ i ∈ Finset.Ico a b, f i * g i := by + apply integral_le_sum_Ico_of_le (f := fun x ↦ f x * g x) hab + · intro i hi x hx + simp only [Nat.cast_add, Nat.cast_one, mem_Ico] at hx hi + have I0 : (i : ℝ) ≤ b - 1 := by + simp only [le_sub_iff_add_le] + norm_cast + omega + have I1 : (i : ℝ) ∈ Icc (a - 1 : ℝ) (b - 1) := by + simp only [mem_Icc, tsub_le_iff_right] + exact ⟨by norm_cast; omega, I0⟩ + have I2 : x ∈ Icc (a : ℝ) b := by + refine ⟨le_trans (mod_cast hi.1) hx.1, hx.2.le.trans ?_⟩ + norm_cast + omega + apply mul_le_mul + · apply hf + · simp only [mem_Icc, Nat.cast_le] + exact ⟨hi.1, hi.2.le⟩ + · exact I2 + · exact hx.1 + · apply hg + · simp only [mem_Icc, tsub_le_iff_right, sub_add_cancel] + refine ⟨le_trans (mod_cast hi.1) hx.1, hx.2.le.trans ?_⟩ + norm_cast + omega + · exact I1 + · simpa [sub_le_iff_le_add] using hx.2.le + · apply gpos.trans + apply hg (by simp [hab]) (by simpa using I2) (by simpa using I2.1) + · apply fpos.trans + apply hf ⟨mod_cast hi.1, mod_cast hi.2.le⟩ (by simpa using hab) (mod_cast hi.2.le) + · apply Integrable.mono_measure _ (Measure.restrict_mono_set _ Ico_subset_Icc_self) + apply Integrable.mul_of_top_left + · exact hf.integrableOn_isCompact isCompact_Icc + · apply MonotoneOn.memℒp_isCompact isCompact_Icc + intro x hx y hy hxy + apply hg + · simpa using hx + · simpa using hy + · simpa using hxy diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 3f4082bc4289d..61370ba5ba955 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -1195,6 +1195,14 @@ theorem Integrable.bdd_mul' {f g : α → 𝕜} {c : ℝ} (hg : Integrable g μ) rw [Pi.smul_apply, smul_eq_mul] exact (norm_mul_le _ _).trans (mul_le_mul_of_nonneg_right hx (norm_nonneg _)) +theorem Integrable.mul_of_top_right {f : α → 𝕜} {φ : α → 𝕜} (hf : Integrable f μ) + (hφ : Memℒp φ ∞ μ) : Integrable (φ * f) μ := + hf.smul_of_top_right hφ + +theorem Integrable.mul_of_top_left {f : α → 𝕜} {φ : α → 𝕜} (hφ : Integrable φ μ) + (hf : Memℒp f ∞ μ) : Integrable (φ * f) μ := + hφ.smul_of_top_left hf + end NormedRing section NormedDivisionRing diff --git a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean index 16af00073f1fa..2e3315ca60259 100644 --- a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean @@ -542,7 +542,7 @@ theorem AntitoneOn.integrableOn_of_measure_ne_top (hanti : AntitoneOn f s) {a b IntegrableOn f s μ := memℒp_one_iff_integrable.1 (hanti.memℒp_of_measure_ne_top ha hb hs h's) -theorem AntioneOn.integrableOn_isCompact [IsFiniteMeasureOnCompacts μ] (hs : IsCompact s) +theorem AntitoneOn.integrableOn_isCompact [IsFiniteMeasureOnCompacts μ] (hs : IsCompact s) (hanti : AntitoneOn f s) : IntegrableOn f s μ := memℒp_one_iff_integrable.1 (hanti.memℒp_isCompact hs) diff --git a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean index 2e2126e29a549..d1beb848fb44b 100644 --- a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean @@ -1071,6 +1071,15 @@ theorem integral_mono_on (h : ∀ x ∈ Icc a b, f x ≤ g x) : let H x hx := h x <| Ioc_subset_Icc_self hx simpa only [integral_of_le hab] using setIntegral_mono_on hf.1 hg.1 measurableSet_Ioc H +theorem integral_mono_on_of_le_Ioo [NoAtoms μ] (h : ∀ x ∈ Ioo a b, f x ≤ g x) : + (∫ u in a..b, f u ∂μ) ≤ ∫ u in a..b, g u ∂μ := by + simp only [integral_of_le hab, integral_Ioc_eq_integral_Ioo] + apply setIntegral_mono_on + · apply hf.1.mono Ioo_subset_Ioc_self le_rfl + · apply hg.1.mono Ioo_subset_Ioc_self le_rfl + · exact measurableSet_Ioo + · exact h + theorem integral_mono (h : f ≤ g) : (∫ u in a..b, f u ∂μ) ≤ ∫ u in a..b, g u ∂μ := integral_mono_ae hab hf hg <| ae_of_all _ h From 8c3ecf43d36962deb7d3848fe692943bff5d8a23 Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Mon, 13 Jan 2025 17:41:13 +0000 Subject: [PATCH 211/681] chore(Algebra/MvPolynomial/Eval): split file for eval off of basic (#20655) This PR directly splits `Algebra/MvPolynomial/Basic` at the point where `eval` related functions are defined. This addresses an instance of a file over 1500 lines long, and makes the `MvPolynomial/` directory structure slightly more like `Polynomial/`. --- Mathlib.lean | 1 + Mathlib/Algebra/MvPolynomial/Basic.lean | 716 ---------------- Mathlib/Algebra/MvPolynomial/Counit.lean | 2 +- Mathlib/Algebra/MvPolynomial/Eval.lean | 765 ++++++++++++++++++ Mathlib/Algebra/MvPolynomial/Rename.lean | 2 +- Mathlib/Analysis/Analytic/Polynomial.lean | 2 +- .../LinearAlgebra/Matrix/MvPolynomial.lean | 2 +- Mathlib/RingTheory/Adjoin/FG.lean | 2 +- Mathlib/RingTheory/MvPolynomial/Tower.lean | 2 +- Mathlib/RingTheory/MvPowerSeries/Basic.lean | 2 +- Mathlib/RingTheory/MvPowerSeries/Trunc.lean | 1 + .../TensorProduct/MvPolynomial.lean | 2 +- Mathlib/Topology/Algebra/MvPolynomial.lean | 2 +- scripts/noshake.json | 2 + 14 files changed, 778 insertions(+), 725 deletions(-) create mode 100644 Mathlib/Algebra/MvPolynomial/Eval.lean diff --git a/Mathlib.lean b/Mathlib.lean index fa54d686380e0..79bc49a205879 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -625,6 +625,7 @@ import Mathlib.Algebra.MvPolynomial.Degrees import Mathlib.Algebra.MvPolynomial.Derivation import Mathlib.Algebra.MvPolynomial.Division import Mathlib.Algebra.MvPolynomial.Equiv +import Mathlib.Algebra.MvPolynomial.Eval import Mathlib.Algebra.MvPolynomial.Expand import Mathlib.Algebra.MvPolynomial.Funext import Mathlib.Algebra.MvPolynomial.Invertible diff --git a/Mathlib/Algebra/MvPolynomial/Basic.lean b/Mathlib/Algebra/MvPolynomial/Basic.lean index 154517230d906..a9fe286b2e396 100644 --- a/Mathlib/Algebra/MvPolynomial/Basic.lean +++ b/Mathlib/Algebra/MvPolynomial/Basic.lean @@ -46,16 +46,6 @@ In the definitions below, we use the following notation: * `C a` : the constant polynomial with value `a` * `X i` : the degree one monomial corresponding to i; mathematically this might be denoted `Xᵢ`. * `coeff s p` : the coefficient of `s` in `p`. -* `eval₂ (f : R → S₁) (g : σ → S₁) p` : given a semiring homomorphism from `R` to another - semiring `S₁`, and a map `σ → S₁`, evaluates `p` at this valuation, returning a term of type `S₁`. - Note that `eval₂` can be made using `eval` and `map` (see below), and it has been suggested - that sticking to `eval` and `map` might make the code less brittle. -* `eval (g : σ → R) p` : given a map `σ → R`, evaluates `p` at this valuation, - returning a term of type `R` -* `map (f : R → S₁) p` : returns the multivariate polynomial obtained from `p` by the change of - coefficient semiring corresponding to `f` -* `aeval (g : σ → S₁) p` : evaluates the multivariate polynomial obtained from `p` by the change - of coefficient semiring corresponding to `g` (`a` stands for `Algebra`) ## Implementation notes @@ -879,712 +869,6 @@ theorem as_sum (p : MvPolynomial σ R) : p = ∑ v ∈ p.support, monomial v (co end AsSum -section Eval₂ - -variable (f : R →+* S₁) (g : σ → S₁) - -/-- Evaluate a polynomial `p` given a valuation `g` of all the variables - and a ring hom `f` from the scalar ring to the target -/ -def eval₂ (p : MvPolynomial σ R) : S₁ := - p.sum fun s a => f a * s.prod fun n e => g n ^ e - -theorem eval₂_eq (g : R →+* S₁) (X : σ → S₁) (f : MvPolynomial σ R) : - f.eval₂ g X = ∑ d ∈ f.support, g (f.coeff d) * ∏ i ∈ d.support, X i ^ d i := - rfl - -theorem eval₂_eq' [Fintype σ] (g : R →+* S₁) (X : σ → S₁) (f : MvPolynomial σ R) : - f.eval₂ g X = ∑ d ∈ f.support, g (f.coeff d) * ∏ i, X i ^ d i := by - simp only [eval₂_eq, ← Finsupp.prod_pow] - rfl - -@[simp] -theorem eval₂_zero : (0 : MvPolynomial σ R).eval₂ f g = 0 := - Finsupp.sum_zero_index - -section - -@[simp] -theorem eval₂_add : (p + q).eval₂ f g = p.eval₂ f g + q.eval₂ f g := by - classical exact Finsupp.sum_add_index (by simp [f.map_zero]) (by simp [add_mul, f.map_add]) - -@[simp] -theorem eval₂_monomial : (monomial s a).eval₂ f g = f a * s.prod fun n e => g n ^ e := - Finsupp.sum_single_index (by simp [f.map_zero]) - -@[simp] -theorem eval₂_C (a) : (C a).eval₂ f g = f a := by - rw [C_apply, eval₂_monomial, prod_zero_index, mul_one] - -@[simp] -theorem eval₂_one : (1 : MvPolynomial σ R).eval₂ f g = 1 := - (eval₂_C _ _ _).trans f.map_one - -@[simp] theorem eval₂_natCast (n : Nat) : (n : MvPolynomial σ R).eval₂ f g = n := - (eval₂_C _ _ _).trans (map_natCast f n) - -@[simp] theorem eval₂_ofNat (n : Nat) [n.AtLeastTwo] : - (ofNat(n) : MvPolynomial σ R).eval₂ f g = ofNat(n) := - eval₂_natCast f g n - -@[simp] -theorem eval₂_X (n) : (X n).eval₂ f g = g n := by - simp [eval₂_monomial, f.map_one, X, prod_single_index, pow_one] - -theorem eval₂_mul_monomial : - ∀ {s a}, (p * monomial s a).eval₂ f g = p.eval₂ f g * f a * s.prod fun n e => g n ^ e := by - classical - apply MvPolynomial.induction_on p - · intro a' s a - simp [C_mul_monomial, eval₂_monomial, f.map_mul] - · intro p q ih_p ih_q - simp [add_mul, eval₂_add, ih_p, ih_q] - · intro p n ih s a - exact - calc (p * X n * monomial s a).eval₂ f g - _ = (p * monomial (Finsupp.single n 1 + s) a).eval₂ f g := by - rw [monomial_single_add, pow_one, mul_assoc] - _ = (p * monomial (Finsupp.single n 1) 1).eval₂ f g * f a * s.prod fun n e => g n ^ e := by - simp [ih, prod_single_index, prod_add_index, pow_one, pow_add, mul_assoc, mul_left_comm, - f.map_one] - -theorem eval₂_mul_C : (p * C a).eval₂ f g = p.eval₂ f g * f a := - (eval₂_mul_monomial _ _).trans <| by simp - -@[simp] -theorem eval₂_mul : ∀ {p}, (p * q).eval₂ f g = p.eval₂ f g * q.eval₂ f g := by - apply MvPolynomial.induction_on q - · simp [eval₂_C, eval₂_mul_C] - · simp +contextual [mul_add, eval₂_add] - · simp +contextual [X, eval₂_monomial, eval₂_mul_monomial, ← mul_assoc] - -@[simp] -theorem eval₂_pow {p : MvPolynomial σ R} : ∀ {n : ℕ}, (p ^ n).eval₂ f g = p.eval₂ f g ^ n - | 0 => by - rw [pow_zero, pow_zero] - exact eval₂_one _ _ - | n + 1 => by rw [pow_add, pow_one, pow_add, pow_one, eval₂_mul, eval₂_pow] - -/-- `MvPolynomial.eval₂` as a `RingHom`. -/ -def eval₂Hom (f : R →+* S₁) (g : σ → S₁) : MvPolynomial σ R →+* S₁ where - toFun := eval₂ f g - map_one' := eval₂_one _ _ - map_mul' _ _ := eval₂_mul _ _ - map_zero' := eval₂_zero f g - map_add' _ _ := eval₂_add _ _ - -@[simp] -theorem coe_eval₂Hom (f : R →+* S₁) (g : σ → S₁) : ⇑(eval₂Hom f g) = eval₂ f g := - rfl - -theorem eval₂Hom_congr {f₁ f₂ : R →+* S₁} {g₁ g₂ : σ → S₁} {p₁ p₂ : MvPolynomial σ R} : - f₁ = f₂ → g₁ = g₂ → p₁ = p₂ → eval₂Hom f₁ g₁ p₁ = eval₂Hom f₂ g₂ p₂ := by - rintro rfl rfl rfl; rfl - -end - -@[simp] -theorem eval₂Hom_C (f : R →+* S₁) (g : σ → S₁) (r : R) : eval₂Hom f g (C r) = f r := - eval₂_C f g r - -@[simp] -theorem eval₂Hom_X' (f : R →+* S₁) (g : σ → S₁) (i : σ) : eval₂Hom f g (X i) = g i := - eval₂_X f g i - -@[simp] -theorem comp_eval₂Hom [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₁) (φ : S₁ →+* S₂) : - φ.comp (eval₂Hom f g) = eval₂Hom (φ.comp f) fun i => φ (g i) := by - apply MvPolynomial.ringHom_ext - · intro r - rw [RingHom.comp_apply, eval₂Hom_C, eval₂Hom_C, RingHom.comp_apply] - · intro i - rw [RingHom.comp_apply, eval₂Hom_X', eval₂Hom_X'] - -theorem map_eval₂Hom [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₁) (φ : S₁ →+* S₂) - (p : MvPolynomial σ R) : φ (eval₂Hom f g p) = eval₂Hom (φ.comp f) (fun i => φ (g i)) p := by - rw [← comp_eval₂Hom] - rfl - -theorem eval₂Hom_monomial (f : R →+* S₁) (g : σ → S₁) (d : σ →₀ ℕ) (r : R) : - eval₂Hom f g (monomial d r) = f r * d.prod fun i k => g i ^ k := by - simp only [monomial_eq, RingHom.map_mul, eval₂Hom_C, Finsupp.prod, map_prod, - RingHom.map_pow, eval₂Hom_X'] - -section - -theorem eval₂_comp_left {S₂} [CommSemiring S₂] (k : S₁ →+* S₂) (f : R →+* S₁) (g : σ → S₁) (p) : - k (eval₂ f g p) = eval₂ (k.comp f) (k ∘ g) p := by - apply MvPolynomial.induction_on p <;> - simp +contextual [eval₂_add, k.map_add, eval₂_mul, k.map_mul] - -end - -@[simp] -theorem eval₂_eta (p : MvPolynomial σ R) : eval₂ C X p = p := by - apply MvPolynomial.induction_on p <;> - simp +contextual [eval₂_add, eval₂_mul] - -theorem eval₂_congr (g₁ g₂ : σ → S₁) - (h : ∀ {i : σ} {c : σ →₀ ℕ}, i ∈ c.support → coeff c p ≠ 0 → g₁ i = g₂ i) : - p.eval₂ f g₁ = p.eval₂ f g₂ := by - apply Finset.sum_congr rfl - intro C hc; dsimp; congr 1 - apply Finset.prod_congr rfl - intro i hi; dsimp; congr 1 - apply h hi - rwa [Finsupp.mem_support_iff] at hc - -theorem eval₂_sum (s : Finset S₂) (p : S₂ → MvPolynomial σ R) : - eval₂ f g (∑ x ∈ s, p x) = ∑ x ∈ s, eval₂ f g (p x) := - map_sum (eval₂Hom f g) _ s - -@[to_additive existing (attr := simp)] -theorem eval₂_prod (s : Finset S₂) (p : S₂ → MvPolynomial σ R) : - eval₂ f g (∏ x ∈ s, p x) = ∏ x ∈ s, eval₂ f g (p x) := - map_prod (eval₂Hom f g) _ s - -theorem eval₂_assoc (q : S₂ → MvPolynomial σ R) (p : MvPolynomial S₂ R) : - eval₂ f (fun t => eval₂ f g (q t)) p = eval₂ f g (eval₂ C q p) := by - show _ = eval₂Hom f g (eval₂ C q p) - rw [eval₂_comp_left (eval₂Hom f g)]; congr with a; simp - -end Eval₂ - -section Eval - -variable {f : σ → R} - -/-- Evaluate a polynomial `p` given a valuation `f` of all the variables -/ -def eval (f : σ → R) : MvPolynomial σ R →+* R := - eval₂Hom (RingHom.id _) f - -theorem eval_eq (X : σ → R) (f : MvPolynomial σ R) : - eval X f = ∑ d ∈ f.support, f.coeff d * ∏ i ∈ d.support, X i ^ d i := - rfl - -theorem eval_eq' [Fintype σ] (X : σ → R) (f : MvPolynomial σ R) : - eval X f = ∑ d ∈ f.support, f.coeff d * ∏ i, X i ^ d i := - eval₂_eq' (RingHom.id R) X f - -theorem eval_monomial : eval f (monomial s a) = a * s.prod fun n e => f n ^ e := - eval₂_monomial _ _ - -@[simp] -theorem eval_C : ∀ a, eval f (C a) = a := - eval₂_C _ _ - -@[simp] -theorem eval_X : ∀ n, eval f (X n) = f n := - eval₂_X _ _ - -@[simp] theorem eval_ofNat (n : Nat) [n.AtLeastTwo] : - (ofNat(n) : MvPolynomial σ R).eval f = ofNat(n) := - map_ofNat _ n - -@[simp] -theorem smul_eval (x) (p : MvPolynomial σ R) (s) : eval x (s • p) = s * eval x p := by - rw [smul_eq_C_mul, (eval x).map_mul, eval_C] - -theorem eval_add : eval f (p + q) = eval f p + eval f q := - eval₂_add _ _ - -theorem eval_mul : eval f (p * q) = eval f p * eval f q := - eval₂_mul _ _ - -theorem eval_pow : ∀ n, eval f (p ^ n) = eval f p ^ n := - fun _ => eval₂_pow _ _ - -theorem eval_sum {ι : Type*} (s : Finset ι) (f : ι → MvPolynomial σ R) (g : σ → R) : - eval g (∑ i ∈ s, f i) = ∑ i ∈ s, eval g (f i) := - map_sum (eval g) _ _ - -@[to_additive existing] -theorem eval_prod {ι : Type*} (s : Finset ι) (f : ι → MvPolynomial σ R) (g : σ → R) : - eval g (∏ i ∈ s, f i) = ∏ i ∈ s, eval g (f i) := - map_prod (eval g) _ _ - -theorem eval_assoc {τ} (f : σ → MvPolynomial τ R) (g : τ → R) (p : MvPolynomial σ R) : - eval (eval g ∘ f) p = eval g (eval₂ C f p) := by - rw [eval₂_comp_left (eval g)] - unfold eval; simp only [coe_eval₂Hom] - congr with a; simp - -@[simp] -theorem eval₂_id {g : σ → R} (p : MvPolynomial σ R) : eval₂ (RingHom.id _) g p = eval g p := - rfl - -theorem eval_eval₂ {S τ : Type*} {x : τ → S} [CommSemiring S] - (f : R →+* MvPolynomial τ S) (g : σ → MvPolynomial τ S) (p : MvPolynomial σ R) : - eval x (eval₂ f g p) = eval₂ ((eval x).comp f) (fun s => eval x (g s)) p := by - apply induction_on p - · simp - · intro p q hp hq - simp [hp, hq] - · intro p n hp - simp [hp] - -end Eval - -section Map - -variable (f : R →+* S₁) - -/-- `map f p` maps a polynomial `p` across a ring hom `f` -/ -def map : MvPolynomial σ R →+* MvPolynomial σ S₁ := - eval₂Hom (C.comp f) X - -@[simp] -theorem map_monomial (s : σ →₀ ℕ) (a : R) : map f (monomial s a) = monomial s (f a) := - (eval₂_monomial _ _).trans monomial_eq.symm - -@[simp] -theorem map_C : ∀ a : R, map f (C a : MvPolynomial σ R) = C (f a) := - map_monomial _ _ - -@[simp] protected theorem map_ofNat (n : Nat) [n.AtLeastTwo] : - (ofNat(n) : MvPolynomial σ R).map f = ofNat(n) := - _root_.map_ofNat _ _ - -@[simp] -theorem map_X : ∀ n : σ, map f (X n : MvPolynomial σ R) = X n := - eval₂_X _ _ - -theorem map_id : ∀ p : MvPolynomial σ R, map (RingHom.id R) p = p := - eval₂_eta - -theorem map_map [CommSemiring S₂] (g : S₁ →+* S₂) (p : MvPolynomial σ R) : - map g (map f p) = map (g.comp f) p := - (eval₂_comp_left (map g) (C.comp f) X p).trans <| by - congr - · ext1 a - simp only [map_C, comp_apply, RingHom.coe_comp] - · ext1 n - simp only [map_X, comp_apply] - -theorem eval₂_eq_eval_map (g : σ → S₁) (p : MvPolynomial σ R) : p.eval₂ f g = eval g (map f p) := by - unfold map eval; simp only [coe_eval₂Hom] - - have h := eval₂_comp_left (eval₂Hom (RingHom.id S₁) g) (C.comp f) X p - -- Porting note: the Lean 3 version of `h` was full of metavariables which - -- were later unified during `rw [h]`. Also needed to add `-eval₂_id`. - dsimp [-eval₂_id] at h - rw [h] - congr - · ext1 a - simp only [coe_eval₂Hom, RingHom.id_apply, comp_apply, eval₂_C, RingHom.coe_comp] - · ext1 n - simp only [comp_apply, eval₂_X] - -theorem eval₂_comp_right {S₂} [CommSemiring S₂] (k : S₁ →+* S₂) (f : R →+* S₁) (g : σ → S₁) (p) : - k (eval₂ f g p) = eval₂ k (k ∘ g) (map f p) := by - apply MvPolynomial.induction_on p - · intro r - rw [eval₂_C, map_C, eval₂_C] - · intro p q hp hq - rw [eval₂_add, k.map_add, (map f).map_add, eval₂_add, hp, hq] - · intro p s hp - rw [eval₂_mul, k.map_mul, (map f).map_mul, eval₂_mul, map_X, hp, eval₂_X, eval₂_X] - rfl - -theorem map_eval₂ (f : R →+* S₁) (g : S₂ → MvPolynomial S₃ R) (p : MvPolynomial S₂ R) : - map f (eval₂ C g p) = eval₂ C (map f ∘ g) (map f p) := by - apply MvPolynomial.induction_on p - · intro r - rw [eval₂_C, map_C, map_C, eval₂_C] - · intro p q hp hq - rw [eval₂_add, (map f).map_add, hp, hq, (map f).map_add, eval₂_add] - · intro p s hp - rw [eval₂_mul, (map f).map_mul, hp, (map f).map_mul, map_X, eval₂_mul, eval₂_X, eval₂_X] - rfl - -theorem coeff_map (p : MvPolynomial σ R) : ∀ m : σ →₀ ℕ, coeff m (map f p) = f (coeff m p) := by - classical - apply MvPolynomial.induction_on p <;> clear p - · intro r m - rw [map_C] - simp only [coeff_C] - split_ifs - · rfl - rw [f.map_zero] - · intro p q hp hq m - simp only [hp, hq, (map f).map_add, coeff_add] - rw [f.map_add] - · intro p i hp m - simp only [hp, (map f).map_mul, map_X] - simp only [hp, mem_support_iff, coeff_mul_X'] - split_ifs - · rfl - rw [f.map_zero] - -theorem map_injective (hf : Function.Injective f) : - Function.Injective (map f : MvPolynomial σ R → MvPolynomial σ S₁) := by - intro p q h - simp only [MvPolynomial.ext_iff, coeff_map] at h ⊢ - intro m - exact hf (h m) - -theorem map_surjective (hf : Function.Surjective f) : - Function.Surjective (map f : MvPolynomial σ R → MvPolynomial σ S₁) := fun p => by - induction' p using MvPolynomial.induction_on' with i fr a b ha hb - · obtain ⟨r, rfl⟩ := hf fr - exact ⟨monomial i r, map_monomial _ _ _⟩ - · obtain ⟨a, rfl⟩ := ha - obtain ⟨b, rfl⟩ := hb - exact ⟨a + b, RingHom.map_add _ _ _⟩ - -/-- If `f` is a left-inverse of `g` then `map f` is a left-inverse of `map g`. -/ -theorem map_leftInverse {f : R →+* S₁} {g : S₁ →+* R} (hf : Function.LeftInverse f g) : - Function.LeftInverse (map f : MvPolynomial σ R → MvPolynomial σ S₁) (map g) := fun X => by - rw [map_map, (RingHom.ext hf : f.comp g = RingHom.id _), map_id] - -/-- If `f` is a right-inverse of `g` then `map f` is a right-inverse of `map g`. -/ -theorem map_rightInverse {f : R →+* S₁} {g : S₁ →+* R} (hf : Function.RightInverse f g) : - Function.RightInverse (map f : MvPolynomial σ R → MvPolynomial σ S₁) (map g) := - (map_leftInverse hf.leftInverse).rightInverse - -@[simp] -theorem eval_map (f : R →+* S₁) (g : σ → S₁) (p : MvPolynomial σ R) : - eval g (map f p) = eval₂ f g p := by - apply MvPolynomial.induction_on p <;> · simp +contextual - -theorem eval₂_comp (f : R →+* S₁) (g : σ → R) (p : MvPolynomial σ R) : - f (eval g p) = eval₂ f (f ∘ g) p := by - rw [← p.map_id, eval_map, eval₂_comp_right] - -@[simp] -theorem eval₂_map [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₂) (φ : S₁ →+* S₂) - (p : MvPolynomial σ R) : eval₂ φ g (map f p) = eval₂ (φ.comp f) g p := by - rw [← eval_map, ← eval_map, map_map] - -@[simp] -theorem eval₂Hom_map_hom [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₂) (φ : S₁ →+* S₂) - (p : MvPolynomial σ R) : eval₂Hom φ g (map f p) = eval₂Hom (φ.comp f) g p := - eval₂_map f g φ p - -@[simp] -theorem constantCoeff_map (f : R →+* S₁) (φ : MvPolynomial σ R) : - constantCoeff (MvPolynomial.map f φ) = f (constantCoeff φ) := - coeff_map f φ 0 - -theorem constantCoeff_comp_map (f : R →+* S₁) : - (constantCoeff : MvPolynomial σ S₁ →+* S₁).comp (MvPolynomial.map f) = f.comp constantCoeff := - by ext <;> simp - -theorem support_map_subset (p : MvPolynomial σ R) : (map f p).support ⊆ p.support := by - intro x - simp only [mem_support_iff] - contrapose! - change p.coeff x = 0 → (map f p).coeff x = 0 - rw [coeff_map] - intro hx - rw [hx] - exact RingHom.map_zero f - -theorem support_map_of_injective (p : MvPolynomial σ R) {f : R →+* S₁} (hf : Injective f) : - (map f p).support = p.support := by - apply Finset.Subset.antisymm - · exact MvPolynomial.support_map_subset _ _ - intro x hx - rw [mem_support_iff] - contrapose! hx - simp only [Classical.not_not, mem_support_iff] - replace hx : (map f p).coeff x = 0 := hx - rw [coeff_map, ← f.map_zero] at hx - exact hf hx - -theorem C_dvd_iff_map_hom_eq_zero (q : R →+* S₁) (r : R) (hr : ∀ r' : R, q r' = 0 ↔ r ∣ r') - (φ : MvPolynomial σ R) : C r ∣ φ ↔ map q φ = 0 := by - rw [C_dvd_iff_dvd_coeff, MvPolynomial.ext_iff] - simp only [coeff_map, coeff_zero, hr] - -theorem map_mapRange_eq_iff (f : R →+* S₁) (g : S₁ → R) (hg : g 0 = 0) (φ : MvPolynomial σ S₁) : - map f (Finsupp.mapRange g hg φ) = φ ↔ ∀ d, f (g (coeff d φ)) = coeff d φ := by - rw [MvPolynomial.ext_iff] - apply forall_congr'; intro m - rw [coeff_map] - apply eq_iff_eq_cancel_right.mpr - rfl - -/-- If `f : S₁ →ₐ[R] S₂` is a morphism of `R`-algebras, then so is `MvPolynomial.map f`. -/ -@[simps!] -def mapAlgHom [CommSemiring S₂] [Algebra R S₁] [Algebra R S₂] (f : S₁ →ₐ[R] S₂) : - MvPolynomial σ S₁ →ₐ[R] MvPolynomial σ S₂ := - { map (↑f : S₁ →+* S₂) with - commutes' := fun r => by - have h₁ : algebraMap R (MvPolynomial σ S₁) r = C (algebraMap R S₁ r) := rfl - have h₂ : algebraMap R (MvPolynomial σ S₂) r = C (algebraMap R S₂ r) := rfl - simp_rw [OneHom.toFun_eq_coe] - -- Porting note: we're missing some `simp` lemmas like `MonoidHom.coe_toOneHom` - change @DFunLike.coe (_ →+* _) _ _ _ _ _ = _ - rw [h₁, h₂, map, eval₂Hom_C, RingHom.comp_apply, AlgHom.coe_toRingHom, AlgHom.commutes] } - -@[simp] -theorem mapAlgHom_id [Algebra R S₁] : - mapAlgHom (AlgHom.id R S₁) = AlgHom.id R (MvPolynomial σ S₁) := - AlgHom.ext map_id - -@[simp] -theorem mapAlgHom_coe_ringHom [CommSemiring S₂] [Algebra R S₁] [Algebra R S₂] (f : S₁ →ₐ[R] S₂) : - ↑(mapAlgHom f : _ →ₐ[R] MvPolynomial σ S₂) = - (map ↑f : MvPolynomial σ S₁ →+* MvPolynomial σ S₂) := - RingHom.mk_coe _ _ _ _ _ - -end Map - -section Aeval - -/-! ### The algebra of multivariate polynomials -/ - - -variable [Algebra R S₁] [CommSemiring S₂] -variable (f : σ → S₁) - -@[simp] -theorem algebraMap_apply (r : R) : algebraMap R (MvPolynomial σ S₁) r = C (algebraMap R S₁ r) := rfl - -/-- A map `σ → S₁` where `S₁` is an algebra over `R` generates an `R`-algebra homomorphism -from multivariate polynomials over `σ` to `S₁`. -/ -def aeval : MvPolynomial σ R →ₐ[R] S₁ := - { eval₂Hom (algebraMap R S₁) f with commutes' := fun _r => eval₂_C _ _ _ } - -theorem aeval_def (p : MvPolynomial σ R) : aeval f p = eval₂ (algebraMap R S₁) f p := - rfl - -theorem aeval_eq_eval₂Hom (p : MvPolynomial σ R) : aeval f p = eval₂Hom (algebraMap R S₁) f p := - rfl - -@[simp] -lemma coe_aeval_eq_eval : RingHomClass.toRingHom (MvPolynomial.aeval f) = MvPolynomial.eval f := - rfl - -@[simp] -theorem aeval_X (s : σ) : aeval f (X s : MvPolynomial _ R) = f s := - eval₂_X _ _ _ - -theorem aeval_C (r : R) : aeval f (C r) = algebraMap R S₁ r := - eval₂_C _ _ _ - -@[simp] theorem aeval_ofNat (n : Nat) [n.AtLeastTwo] : - aeval f (ofNat(n) : MvPolynomial σ R) = ofNat(n) := - map_ofNat _ _ - -theorem aeval_unique (φ : MvPolynomial σ R →ₐ[R] S₁) : φ = aeval (φ ∘ X) := by - ext i - simp - -theorem aeval_X_left : aeval X = AlgHom.id R (MvPolynomial σ R) := - (aeval_unique (AlgHom.id R _)).symm - -theorem aeval_X_left_apply (p : MvPolynomial σ R) : aeval X p = p := - AlgHom.congr_fun aeval_X_left p - -theorem comp_aeval {B : Type*} [CommSemiring B] [Algebra R B] (φ : S₁ →ₐ[R] B) : - φ.comp (aeval f) = aeval fun i => φ (f i) := by - ext i - simp - -lemma comp_aeval_apply {B : Type*} [CommSemiring B] [Algebra R B] (φ : S₁ →ₐ[R] B) - (p : MvPolynomial σ R) : - φ (aeval f p) = aeval (fun i ↦ φ (f i)) p := by - rw [← comp_aeval, AlgHom.coe_comp, comp_apply] - -@[simp] -theorem map_aeval {B : Type*} [CommSemiring B] (g : σ → S₁) (φ : S₁ →+* B) (p : MvPolynomial σ R) : - φ (aeval g p) = eval₂Hom (φ.comp (algebraMap R S₁)) (fun i => φ (g i)) p := by - rw [← comp_eval₂Hom] - rfl - -@[simp] -theorem eval₂Hom_zero (f : R →+* S₂) : eval₂Hom f (0 : σ → S₂) = f.comp constantCoeff := by - ext <;> simp - -@[simp] -theorem eval₂Hom_zero' (f : R →+* S₂) : eval₂Hom f (fun _ => 0 : σ → S₂) = f.comp constantCoeff := - eval₂Hom_zero f - -theorem eval₂Hom_zero_apply (f : R →+* S₂) (p : MvPolynomial σ R) : - eval₂Hom f (0 : σ → S₂) p = f (constantCoeff p) := - RingHom.congr_fun (eval₂Hom_zero f) p - -theorem eval₂Hom_zero'_apply (f : R →+* S₂) (p : MvPolynomial σ R) : - eval₂Hom f (fun _ => 0 : σ → S₂) p = f (constantCoeff p) := - eval₂Hom_zero_apply f p - -@[simp] -theorem eval₂_zero_apply (f : R →+* S₂) (p : MvPolynomial σ R) : - eval₂ f (0 : σ → S₂) p = f (constantCoeff p) := - eval₂Hom_zero_apply _ _ - -@[simp] -theorem eval₂_zero'_apply (f : R →+* S₂) (p : MvPolynomial σ R) : - eval₂ f (fun _ => 0 : σ → S₂) p = f (constantCoeff p) := - eval₂_zero_apply f p - -@[simp] -theorem aeval_zero (p : MvPolynomial σ R) : - aeval (0 : σ → S₁) p = algebraMap _ _ (constantCoeff p) := - eval₂Hom_zero_apply (algebraMap R S₁) p - -@[simp] -theorem aeval_zero' (p : MvPolynomial σ R) : - aeval (fun _ => 0 : σ → S₁) p = algebraMap _ _ (constantCoeff p) := - aeval_zero p - -@[simp] -theorem eval_zero : eval (0 : σ → R) = constantCoeff := - eval₂Hom_zero _ - -@[simp] -theorem eval_zero' : eval (fun _ => 0 : σ → R) = constantCoeff := - eval₂Hom_zero _ - -theorem aeval_monomial (g : σ → S₁) (d : σ →₀ ℕ) (r : R) : - aeval g (monomial d r) = algebraMap _ _ r * d.prod fun i k => g i ^ k := - eval₂Hom_monomial _ _ _ _ - -theorem eval₂Hom_eq_zero (f : R →+* S₂) (g : σ → S₂) (φ : MvPolynomial σ R) - (h : ∀ d, φ.coeff d ≠ 0 → ∃ i ∈ d.support, g i = 0) : eval₂Hom f g φ = 0 := by - rw [φ.as_sum, map_sum] - refine Finset.sum_eq_zero fun d hd => ?_ - obtain ⟨i, hi, hgi⟩ : ∃ i ∈ d.support, g i = 0 := h d (Finsupp.mem_support_iff.mp hd) - rw [eval₂Hom_monomial, Finsupp.prod, Finset.prod_eq_zero hi, mul_zero] - rw [hgi, zero_pow] - rwa [← Finsupp.mem_support_iff] - -theorem aeval_eq_zero [Algebra R S₂] (f : σ → S₂) (φ : MvPolynomial σ R) - (h : ∀ d, φ.coeff d ≠ 0 → ∃ i ∈ d.support, f i = 0) : aeval f φ = 0 := - eval₂Hom_eq_zero _ _ _ h - -theorem aeval_sum {ι : Type*} (s : Finset ι) (φ : ι → MvPolynomial σ R) : - aeval f (∑ i ∈ s, φ i) = ∑ i ∈ s, aeval f (φ i) := - map_sum (MvPolynomial.aeval f) _ _ - -@[to_additive existing] -theorem aeval_prod {ι : Type*} (s : Finset ι) (φ : ι → MvPolynomial σ R) : - aeval f (∏ i ∈ s, φ i) = ∏ i ∈ s, aeval f (φ i) := - map_prod (MvPolynomial.aeval f) _ _ - -variable (R) - -theorem _root_.Algebra.adjoin_range_eq_range_aeval : - Algebra.adjoin R (Set.range f) = (MvPolynomial.aeval f).range := by - simp only [← Algebra.map_top, ← MvPolynomial.adjoin_range_X, AlgHom.map_adjoin, ← Set.range_comp, - Function.comp_def, MvPolynomial.aeval_X] - -theorem _root_.Algebra.adjoin_eq_range (s : Set S₁) : - Algebra.adjoin R s = (MvPolynomial.aeval ((↑) : s → S₁)).range := by - rw [← Algebra.adjoin_range_eq_range_aeval, Subtype.range_coe] - -end Aeval - -section AevalTower - -variable {S A B : Type*} [CommSemiring S] [CommSemiring A] [CommSemiring B] -variable [Algebra S R] [Algebra S A] [Algebra S B] - -/-- Version of `aeval` for defining algebra homs out of `MvPolynomial σ R` over a smaller base ring - than `R`. -/ -def aevalTower (f : R →ₐ[S] A) (X : σ → A) : MvPolynomial σ R →ₐ[S] A := - { eval₂Hom (↑f) X with - commutes' := fun r => by - simp [IsScalarTower.algebraMap_eq S R (MvPolynomial σ R), algebraMap_eq] } - -variable (g : R →ₐ[S] A) (y : σ → A) - -@[simp] -theorem aevalTower_X (i : σ) : aevalTower g y (X i) = y i := - eval₂_X _ _ _ - -@[simp] -theorem aevalTower_C (x : R) : aevalTower g y (C x) = g x := - eval₂_C _ _ _ - -@[simp] -theorem aevalTower_ofNat (n : Nat) [n.AtLeastTwo] : - aevalTower g y (ofNat(n) : MvPolynomial σ R) = ofNat(n) := - _root_.map_ofNat _ _ - -@[simp] -theorem aevalTower_comp_C : (aevalTower g y : MvPolynomial σ R →+* A).comp C = g := - RingHom.ext <| aevalTower_C _ _ - -theorem aevalTower_algebraMap (x : R) : aevalTower g y (algebraMap R (MvPolynomial σ R) x) = g x := - eval₂_C _ _ _ - -theorem aevalTower_comp_algebraMap : - (aevalTower g y : MvPolynomial σ R →+* A).comp (algebraMap R (MvPolynomial σ R)) = g := - aevalTower_comp_C _ _ - -theorem aevalTower_toAlgHom (x : R) : - aevalTower g y (IsScalarTower.toAlgHom S R (MvPolynomial σ R) x) = g x := - aevalTower_algebraMap _ _ _ - -@[simp] -theorem aevalTower_comp_toAlgHom : - (aevalTower g y).comp (IsScalarTower.toAlgHom S R (MvPolynomial σ R)) = g := - AlgHom.coe_ringHom_injective <| aevalTower_comp_algebraMap _ _ - -@[simp] -theorem aevalTower_id : - aevalTower (AlgHom.id S S) = (aeval : (σ → S) → MvPolynomial σ S →ₐ[S] S) := by - ext - simp only [aevalTower_X, aeval_X] - -@[simp] -theorem aevalTower_ofId : - aevalTower (Algebra.ofId S A) = (aeval : (σ → A) → MvPolynomial σ S →ₐ[S] A) := by - ext - simp only [aeval_X, aevalTower_X] - -end AevalTower - -section EvalMem - -variable {S subS : Type*} [CommSemiring S] [SetLike subS S] [SubsemiringClass subS S] - -theorem eval₂_mem {f : R →+* S} {p : MvPolynomial σ R} {s : subS} - (hs : ∀ i ∈ p.support, f (p.coeff i) ∈ s) {v : σ → S} (hv : ∀ i, v i ∈ s) : - MvPolynomial.eval₂ f v p ∈ s := by - classical - replace hs : ∀ i, f (p.coeff i) ∈ s := by - intro i - by_cases hi : i ∈ p.support - · exact hs i hi - · rw [MvPolynomial.not_mem_support_iff.1 hi, f.map_zero] - exact zero_mem s - induction' p using MvPolynomial.induction_on''' with a a b f ha _ ih - · simpa using hs 0 - rw [eval₂_add, eval₂_monomial] - refine add_mem (mul_mem ?_ <| prod_mem fun i _ => pow_mem (hv _) _) (ih fun i => ?_) - · have := hs a -- Porting note: was `simpa only [...]` - rwa [coeff_add, MvPolynomial.not_mem_support_iff.1 ha, add_zero, coeff_monomial, - if_pos rfl] at this - have := hs i - rw [coeff_add, coeff_monomial] at this - split_ifs at this with h - · subst h - rw [MvPolynomial.not_mem_support_iff.1 ha, map_zero] - exact zero_mem _ - · rwa [zero_add] at this - -theorem eval_mem {p : MvPolynomial σ S} {s : subS} (hs : ∀ i ∈ p.support, p.coeff i ∈ s) {v : σ → S} - (hv : ∀ i, v i ∈ s) : MvPolynomial.eval v p ∈ s := - eval₂_mem hs hv - -end EvalMem - -variable {S T : Type*} [CommSemiring S] [Algebra R S] [CommSemiring T] [Algebra R T] [Algebra S T] - [IsScalarTower R S T] - -lemma aeval_sum_elim {σ τ : Type*} (p : MvPolynomial (σ ⊕ τ) R) (f : τ → S) (g : σ → T) : - (aeval (Sum.elim g (algebraMap S T ∘ f))) p = - (aeval g) ((aeval (Sum.elim X (C ∘ f))) p) := by - induction' p using MvPolynomial.induction_on with r p q hp hq p i h - · simp [← IsScalarTower.algebraMap_apply] - · simp [hp, hq] - · cases i <;> simp [h] - end CommSemiring end MvPolynomial - -set_option linter.style.longFile 1700 diff --git a/Mathlib/Algebra/MvPolynomial/Counit.lean b/Mathlib/Algebra/MvPolynomial/Counit.lean index da0859fd7c50c..be5ce465ef3a6 100644 --- a/Mathlib/Algebra/MvPolynomial/Counit.lean +++ b/Mathlib/Algebra/MvPolynomial/Counit.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval /-! ## Counit morphisms for multivariate polynomials diff --git a/Mathlib/Algebra/MvPolynomial/Eval.lean b/Mathlib/Algebra/MvPolynomial/Eval.lean new file mode 100644 index 0000000000000..046543d81dd85 --- /dev/null +++ b/Mathlib/Algebra/MvPolynomial/Eval.lean @@ -0,0 +1,765 @@ +/- +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, Johan Commelin, Mario Carneiro +-/ +import Mathlib.Algebra.MvPolynomial.Basic + +/-! +# Multivariate polynomials + +This file defines functions for evaluating multivariate polynomials. +These include generically evaluating a polynomial given a valuation of all its variables, +and more advanced evaluations that allow one to map the coefficients to different rings. + +### Notation + +In the definitions below, we use the following notation: + ++ `σ : Type*` (indexing the variables) ++ `R : Type*` `[CommSemiring R]` (the coefficients) ++ `s : σ →₀ ℕ`, a function from `σ` to `ℕ` which is zero away from a finite set. + This will give rise to a monomial in `MvPolynomial σ R` which mathematicians might call `X^s` ++ `a : R` ++ `i : σ`, with corresponding monomial `X i`, often denoted `X_i` by mathematicians ++ `p : MvPolynomial σ R` + +### Definitions + +* `eval₂ (f : R → S₁) (g : σ → S₁) p` : given a semiring homomorphism from `R` to another + semiring `S₁`, and a map `σ → S₁`, evaluates `p` at this valuation, returning a term of type `S₁`. + Note that `eval₂` can be made using `eval` and `map` (see below), and it has been suggested + that sticking to `eval` and `map` might make the code less brittle. +* `eval (g : σ → R) p` : given a map `σ → R`, evaluates `p` at this valuation, + returning a term of type `R` +* `map (f : R → S₁) p` : returns the multivariate polynomial obtained from `p` by the change of + coefficient semiring corresponding to `f` +* `aeval (g : σ → S₁) p` : evaluates the multivariate polynomial obtained from `p` by the change + of coefficient semiring corresponding to `g` (`a` stands for `Algebra`) + +-/ + +noncomputable section + +open Set Function Finsupp AddMonoidAlgebra +open scoped Pointwise + +universe u v w x + +variable {R : Type u} {S₁ : Type v} {S₂ : Type w} {S₃ : Type x} + +namespace MvPolynomial + +variable {σ : Type*} {a a' a₁ a₂ : R} {e : ℕ} {n m : σ} {s : σ →₀ ℕ} + +section CommSemiring + +variable [CommSemiring R] [CommSemiring S₁] {p q : MvPolynomial σ R} + +section Eval₂ + +variable (f : R →+* S₁) (g : σ → S₁) + +/-- Evaluate a polynomial `p` given a valuation `g` of all the variables + and a ring hom `f` from the scalar ring to the target -/ +def eval₂ (p : MvPolynomial σ R) : S₁ := + p.sum fun s a => f a * s.prod fun n e => g n ^ e + +theorem eval₂_eq (g : R →+* S₁) (X : σ → S₁) (f : MvPolynomial σ R) : + f.eval₂ g X = ∑ d ∈ f.support, g (f.coeff d) * ∏ i ∈ d.support, X i ^ d i := + rfl + +theorem eval₂_eq' [Fintype σ] (g : R →+* S₁) (X : σ → S₁) (f : MvPolynomial σ R) : + f.eval₂ g X = ∑ d ∈ f.support, g (f.coeff d) * ∏ i, X i ^ d i := by + simp only [eval₂_eq, ← Finsupp.prod_pow] + rfl + +@[simp] +theorem eval₂_zero : (0 : MvPolynomial σ R).eval₂ f g = 0 := + Finsupp.sum_zero_index + +section + +@[simp] +theorem eval₂_add : (p + q).eval₂ f g = p.eval₂ f g + q.eval₂ f g := by + classical exact Finsupp.sum_add_index (by simp [f.map_zero]) (by simp [add_mul, f.map_add]) + +@[simp] +theorem eval₂_monomial : (monomial s a).eval₂ f g = f a * s.prod fun n e => g n ^ e := + Finsupp.sum_single_index (by simp [f.map_zero]) + +@[simp] +theorem eval₂_C (a) : (C a).eval₂ f g = f a := by + rw [C_apply, eval₂_monomial, prod_zero_index, mul_one] + +@[simp] +theorem eval₂_one : (1 : MvPolynomial σ R).eval₂ f g = 1 := + (eval₂_C _ _ _).trans f.map_one + +@[simp] theorem eval₂_natCast (n : Nat) : (n : MvPolynomial σ R).eval₂ f g = n := + (eval₂_C _ _ _).trans (map_natCast f n) + +@[simp] theorem eval₂_ofNat (n : Nat) [n.AtLeastTwo] : + (ofNat(n) : MvPolynomial σ R).eval₂ f g = ofNat(n) := + eval₂_natCast f g n + +@[simp] +theorem eval₂_X (n) : (X n).eval₂ f g = g n := by + simp [eval₂_monomial, f.map_one, X, prod_single_index, pow_one] + +theorem eval₂_mul_monomial : + ∀ {s a}, (p * monomial s a).eval₂ f g = p.eval₂ f g * f a * s.prod fun n e => g n ^ e := by + classical + apply MvPolynomial.induction_on p + · intro a' s a + simp [C_mul_monomial, eval₂_monomial, f.map_mul] + · intro p q ih_p ih_q + simp [add_mul, eval₂_add, ih_p, ih_q] + · intro p n ih s a + exact + calc (p * X n * monomial s a).eval₂ f g + _ = (p * monomial (Finsupp.single n 1 + s) a).eval₂ f g := by + rw [monomial_single_add, pow_one, mul_assoc] + _ = (p * monomial (Finsupp.single n 1) 1).eval₂ f g * f a * s.prod fun n e => g n ^ e := by + simp [ih, prod_single_index, prod_add_index, pow_one, pow_add, mul_assoc, mul_left_comm, + f.map_one] + +theorem eval₂_mul_C : (p * C a).eval₂ f g = p.eval₂ f g * f a := + (eval₂_mul_monomial _ _).trans <| by simp + +@[simp] +theorem eval₂_mul : ∀ {p}, (p * q).eval₂ f g = p.eval₂ f g * q.eval₂ f g := by + apply MvPolynomial.induction_on q + · simp [eval₂_C, eval₂_mul_C] + · simp +contextual [mul_add, eval₂_add] + · simp +contextual [X, eval₂_monomial, eval₂_mul_monomial, ← mul_assoc] + +@[simp] +theorem eval₂_pow {p : MvPolynomial σ R} : ∀ {n : ℕ}, (p ^ n).eval₂ f g = p.eval₂ f g ^ n + | 0 => by + rw [pow_zero, pow_zero] + exact eval₂_one _ _ + | n + 1 => by rw [pow_add, pow_one, pow_add, pow_one, eval₂_mul, eval₂_pow] + +/-- `MvPolynomial.eval₂` as a `RingHom`. -/ +def eval₂Hom (f : R →+* S₁) (g : σ → S₁) : MvPolynomial σ R →+* S₁ where + toFun := eval₂ f g + map_one' := eval₂_one _ _ + map_mul' _ _ := eval₂_mul _ _ + map_zero' := eval₂_zero f g + map_add' _ _ := eval₂_add _ _ + +@[simp] +theorem coe_eval₂Hom (f : R →+* S₁) (g : σ → S₁) : ⇑(eval₂Hom f g) = eval₂ f g := + rfl + +theorem eval₂Hom_congr {f₁ f₂ : R →+* S₁} {g₁ g₂ : σ → S₁} {p₁ p₂ : MvPolynomial σ R} : + f₁ = f₂ → g₁ = g₂ → p₁ = p₂ → eval₂Hom f₁ g₁ p₁ = eval₂Hom f₂ g₂ p₂ := by + rintro rfl rfl rfl; rfl + +end + +@[simp] +theorem eval₂Hom_C (f : R →+* S₁) (g : σ → S₁) (r : R) : eval₂Hom f g (C r) = f r := + eval₂_C f g r + +@[simp] +theorem eval₂Hom_X' (f : R →+* S₁) (g : σ → S₁) (i : σ) : eval₂Hom f g (X i) = g i := + eval₂_X f g i + +@[simp] +theorem comp_eval₂Hom [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₁) (φ : S₁ →+* S₂) : + φ.comp (eval₂Hom f g) = eval₂Hom (φ.comp f) fun i => φ (g i) := by + apply MvPolynomial.ringHom_ext + · intro r + rw [RingHom.comp_apply, eval₂Hom_C, eval₂Hom_C, RingHom.comp_apply] + · intro i + rw [RingHom.comp_apply, eval₂Hom_X', eval₂Hom_X'] + +theorem map_eval₂Hom [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₁) (φ : S₁ →+* S₂) + (p : MvPolynomial σ R) : φ (eval₂Hom f g p) = eval₂Hom (φ.comp f) (fun i => φ (g i)) p := by + rw [← comp_eval₂Hom] + rfl + +theorem eval₂Hom_monomial (f : R →+* S₁) (g : σ → S₁) (d : σ →₀ ℕ) (r : R) : + eval₂Hom f g (monomial d r) = f r * d.prod fun i k => g i ^ k := by + simp only [monomial_eq, RingHom.map_mul, eval₂Hom_C, Finsupp.prod, map_prod, + RingHom.map_pow, eval₂Hom_X'] + +section + +theorem eval₂_comp_left {S₂} [CommSemiring S₂] (k : S₁ →+* S₂) (f : R →+* S₁) (g : σ → S₁) (p) : + k (eval₂ f g p) = eval₂ (k.comp f) (k ∘ g) p := by + apply MvPolynomial.induction_on p <;> + simp +contextual [eval₂_add, k.map_add, eval₂_mul, k.map_mul] + +end + +@[simp] +theorem eval₂_eta (p : MvPolynomial σ R) : eval₂ C X p = p := by + apply MvPolynomial.induction_on p <;> + simp +contextual [eval₂_add, eval₂_mul] + +theorem eval₂_congr (g₁ g₂ : σ → S₁) + (h : ∀ {i : σ} {c : σ →₀ ℕ}, i ∈ c.support → coeff c p ≠ 0 → g₁ i = g₂ i) : + p.eval₂ f g₁ = p.eval₂ f g₂ := by + apply Finset.sum_congr rfl + intro C hc; dsimp; congr 1 + apply Finset.prod_congr rfl + intro i hi; dsimp; congr 1 + apply h hi + rwa [Finsupp.mem_support_iff] at hc + +theorem eval₂_sum (s : Finset S₂) (p : S₂ → MvPolynomial σ R) : + eval₂ f g (∑ x ∈ s, p x) = ∑ x ∈ s, eval₂ f g (p x) := + map_sum (eval₂Hom f g) _ s + +@[to_additive existing (attr := simp)] +theorem eval₂_prod (s : Finset S₂) (p : S₂ → MvPolynomial σ R) : + eval₂ f g (∏ x ∈ s, p x) = ∏ x ∈ s, eval₂ f g (p x) := + map_prod (eval₂Hom f g) _ s + +theorem eval₂_assoc (q : S₂ → MvPolynomial σ R) (p : MvPolynomial S₂ R) : + eval₂ f (fun t => eval₂ f g (q t)) p = eval₂ f g (eval₂ C q p) := by + show _ = eval₂Hom f g (eval₂ C q p) + rw [eval₂_comp_left (eval₂Hom f g)]; congr with a; simp + +end Eval₂ + +section Eval + +variable {f : σ → R} + +/-- Evaluate a polynomial `p` given a valuation `f` of all the variables -/ +def eval (f : σ → R) : MvPolynomial σ R →+* R := + eval₂Hom (RingHom.id _) f + +theorem eval_eq (X : σ → R) (f : MvPolynomial σ R) : + eval X f = ∑ d ∈ f.support, f.coeff d * ∏ i ∈ d.support, X i ^ d i := + rfl + +theorem eval_eq' [Fintype σ] (X : σ → R) (f : MvPolynomial σ R) : + eval X f = ∑ d ∈ f.support, f.coeff d * ∏ i, X i ^ d i := + eval₂_eq' (RingHom.id R) X f + +theorem eval_monomial : eval f (monomial s a) = a * s.prod fun n e => f n ^ e := + eval₂_monomial _ _ + +@[simp] +theorem eval_C : ∀ a, eval f (C a) = a := + eval₂_C _ _ + +@[simp] +theorem eval_X : ∀ n, eval f (X n) = f n := + eval₂_X _ _ + +@[simp] theorem eval_ofNat (n : Nat) [n.AtLeastTwo] : + (ofNat(n) : MvPolynomial σ R).eval f = ofNat(n) := + map_ofNat _ n + +@[simp] +theorem smul_eval (x) (p : MvPolynomial σ R) (s) : eval x (s • p) = s * eval x p := by + rw [smul_eq_C_mul, (eval x).map_mul, eval_C] + +theorem eval_add : eval f (p + q) = eval f p + eval f q := + eval₂_add _ _ + +theorem eval_mul : eval f (p * q) = eval f p * eval f q := + eval₂_mul _ _ + +theorem eval_pow : ∀ n, eval f (p ^ n) = eval f p ^ n := + fun _ => eval₂_pow _ _ + +theorem eval_sum {ι : Type*} (s : Finset ι) (f : ι → MvPolynomial σ R) (g : σ → R) : + eval g (∑ i ∈ s, f i) = ∑ i ∈ s, eval g (f i) := + map_sum (eval g) _ _ + +@[to_additive existing] +theorem eval_prod {ι : Type*} (s : Finset ι) (f : ι → MvPolynomial σ R) (g : σ → R) : + eval g (∏ i ∈ s, f i) = ∏ i ∈ s, eval g (f i) := + map_prod (eval g) _ _ + +theorem eval_assoc {τ} (f : σ → MvPolynomial τ R) (g : τ → R) (p : MvPolynomial σ R) : + eval (eval g ∘ f) p = eval g (eval₂ C f p) := by + rw [eval₂_comp_left (eval g)] + unfold eval; simp only [coe_eval₂Hom] + congr with a; simp + +@[simp] +theorem eval₂_id {g : σ → R} (p : MvPolynomial σ R) : eval₂ (RingHom.id _) g p = eval g p := + rfl + +theorem eval_eval₂ {S τ : Type*} {x : τ → S} [CommSemiring S] + (f : R →+* MvPolynomial τ S) (g : σ → MvPolynomial τ S) (p : MvPolynomial σ R) : + eval x (eval₂ f g p) = eval₂ ((eval x).comp f) (fun s => eval x (g s)) p := by + apply induction_on p + · simp + · intro p q hp hq + simp [hp, hq] + · intro p n hp + simp [hp] + +end Eval + +section Map + +variable (f : R →+* S₁) + +/-- `map f p` maps a polynomial `p` across a ring hom `f` -/ +def map : MvPolynomial σ R →+* MvPolynomial σ S₁ := + eval₂Hom (C.comp f) X + +@[simp] +theorem map_monomial (s : σ →₀ ℕ) (a : R) : map f (monomial s a) = monomial s (f a) := + (eval₂_monomial _ _).trans monomial_eq.symm + +@[simp] +theorem map_C : ∀ a : R, map f (C a : MvPolynomial σ R) = C (f a) := + map_monomial _ _ + +@[simp] protected theorem map_ofNat (n : Nat) [n.AtLeastTwo] : + (ofNat(n) : MvPolynomial σ R).map f = ofNat(n) := + _root_.map_ofNat _ _ + +@[simp] +theorem map_X : ∀ n : σ, map f (X n : MvPolynomial σ R) = X n := + eval₂_X _ _ + +theorem map_id : ∀ p : MvPolynomial σ R, map (RingHom.id R) p = p := + eval₂_eta + +theorem map_map [CommSemiring S₂] (g : S₁ →+* S₂) (p : MvPolynomial σ R) : + map g (map f p) = map (g.comp f) p := + (eval₂_comp_left (map g) (C.comp f) X p).trans <| by + congr + · ext1 a + simp only [map_C, comp_apply, RingHom.coe_comp] + · ext1 n + simp only [map_X, comp_apply] + +theorem eval₂_eq_eval_map (g : σ → S₁) (p : MvPolynomial σ R) : p.eval₂ f g = eval g (map f p) := by + unfold map eval; simp only [coe_eval₂Hom] + + have h := eval₂_comp_left (eval₂Hom (RingHom.id S₁) g) (C.comp f) X p + -- Porting note: the Lean 3 version of `h` was full of metavariables which + -- were later unified during `rw [h]`. Also needed to add `-eval₂_id`. + dsimp [-eval₂_id] at h + rw [h] + congr + · ext1 a + simp only [coe_eval₂Hom, RingHom.id_apply, comp_apply, eval₂_C, RingHom.coe_comp] + · ext1 n + simp only [comp_apply, eval₂_X] + +theorem eval₂_comp_right {S₂} [CommSemiring S₂] (k : S₁ →+* S₂) (f : R →+* S₁) (g : σ → S₁) (p) : + k (eval₂ f g p) = eval₂ k (k ∘ g) (map f p) := by + apply MvPolynomial.induction_on p + · intro r + rw [eval₂_C, map_C, eval₂_C] + · intro p q hp hq + rw [eval₂_add, k.map_add, (map f).map_add, eval₂_add, hp, hq] + · intro p s hp + rw [eval₂_mul, k.map_mul, (map f).map_mul, eval₂_mul, map_X, hp, eval₂_X, eval₂_X] + rfl + +theorem map_eval₂ (f : R →+* S₁) (g : S₂ → MvPolynomial S₃ R) (p : MvPolynomial S₂ R) : + map f (eval₂ C g p) = eval₂ C (map f ∘ g) (map f p) := by + apply MvPolynomial.induction_on p + · intro r + rw [eval₂_C, map_C, map_C, eval₂_C] + · intro p q hp hq + rw [eval₂_add, (map f).map_add, hp, hq, (map f).map_add, eval₂_add] + · intro p s hp + rw [eval₂_mul, (map f).map_mul, hp, (map f).map_mul, map_X, eval₂_mul, eval₂_X, eval₂_X] + rfl + +theorem coeff_map (p : MvPolynomial σ R) : ∀ m : σ →₀ ℕ, coeff m (map f p) = f (coeff m p) := by + classical + apply MvPolynomial.induction_on p <;> clear p + · intro r m + rw [map_C] + simp only [coeff_C] + split_ifs + · rfl + rw [f.map_zero] + · intro p q hp hq m + simp only [hp, hq, (map f).map_add, coeff_add] + rw [f.map_add] + · intro p i hp m + simp only [hp, (map f).map_mul, map_X] + simp only [hp, mem_support_iff, coeff_mul_X'] + split_ifs + · rfl + rw [f.map_zero] + +theorem map_injective (hf : Function.Injective f) : + Function.Injective (map f : MvPolynomial σ R → MvPolynomial σ S₁) := by + intro p q h + simp only [MvPolynomial.ext_iff, coeff_map] at h ⊢ + intro m + exact hf (h m) + +theorem map_surjective (hf : Function.Surjective f) : + Function.Surjective (map f : MvPolynomial σ R → MvPolynomial σ S₁) := fun p => by + induction' p using MvPolynomial.induction_on' with i fr a b ha hb + · obtain ⟨r, rfl⟩ := hf fr + exact ⟨monomial i r, map_monomial _ _ _⟩ + · obtain ⟨a, rfl⟩ := ha + obtain ⟨b, rfl⟩ := hb + exact ⟨a + b, RingHom.map_add _ _ _⟩ + +/-- If `f` is a left-inverse of `g` then `map f` is a left-inverse of `map g`. -/ +theorem map_leftInverse {f : R →+* S₁} {g : S₁ →+* R} (hf : Function.LeftInverse f g) : + Function.LeftInverse (map f : MvPolynomial σ R → MvPolynomial σ S₁) (map g) := fun X => by + rw [map_map, (RingHom.ext hf : f.comp g = RingHom.id _), map_id] + +/-- If `f` is a right-inverse of `g` then `map f` is a right-inverse of `map g`. -/ +theorem map_rightInverse {f : R →+* S₁} {g : S₁ →+* R} (hf : Function.RightInverse f g) : + Function.RightInverse (map f : MvPolynomial σ R → MvPolynomial σ S₁) (map g) := + (map_leftInverse hf.leftInverse).rightInverse + +@[simp] +theorem eval_map (f : R →+* S₁) (g : σ → S₁) (p : MvPolynomial σ R) : + eval g (map f p) = eval₂ f g p := by + apply MvPolynomial.induction_on p <;> · simp +contextual + +theorem eval₂_comp (f : R →+* S₁) (g : σ → R) (p : MvPolynomial σ R) : + f (eval g p) = eval₂ f (f ∘ g) p := by + rw [← p.map_id, eval_map, eval₂_comp_right] + +@[simp] +theorem eval₂_map [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₂) (φ : S₁ →+* S₂) + (p : MvPolynomial σ R) : eval₂ φ g (map f p) = eval₂ (φ.comp f) g p := by + rw [← eval_map, ← eval_map, map_map] + +@[simp] +theorem eval₂Hom_map_hom [CommSemiring S₂] (f : R →+* S₁) (g : σ → S₂) (φ : S₁ →+* S₂) + (p : MvPolynomial σ R) : eval₂Hom φ g (map f p) = eval₂Hom (φ.comp f) g p := + eval₂_map f g φ p + +@[simp] +theorem constantCoeff_map (f : R →+* S₁) (φ : MvPolynomial σ R) : + constantCoeff (MvPolynomial.map f φ) = f (constantCoeff φ) := + coeff_map f φ 0 + +theorem constantCoeff_comp_map (f : R →+* S₁) : + (constantCoeff : MvPolynomial σ S₁ →+* S₁).comp (MvPolynomial.map f) = f.comp constantCoeff := + by ext <;> simp + +theorem support_map_subset (p : MvPolynomial σ R) : (map f p).support ⊆ p.support := by + intro x + simp only [mem_support_iff] + contrapose! + change p.coeff x = 0 → (map f p).coeff x = 0 + rw [coeff_map] + intro hx + rw [hx] + exact RingHom.map_zero f + +theorem support_map_of_injective (p : MvPolynomial σ R) {f : R →+* S₁} (hf : Injective f) : + (map f p).support = p.support := by + apply Finset.Subset.antisymm + · exact MvPolynomial.support_map_subset _ _ + intro x hx + rw [mem_support_iff] + contrapose! hx + simp only [Classical.not_not, mem_support_iff] + replace hx : (map f p).coeff x = 0 := hx + rw [coeff_map, ← f.map_zero] at hx + exact hf hx + +theorem C_dvd_iff_map_hom_eq_zero (q : R →+* S₁) (r : R) (hr : ∀ r' : R, q r' = 0 ↔ r ∣ r') + (φ : MvPolynomial σ R) : C r ∣ φ ↔ map q φ = 0 := by + rw [C_dvd_iff_dvd_coeff, MvPolynomial.ext_iff] + simp only [coeff_map, coeff_zero, hr] + +theorem map_mapRange_eq_iff (f : R →+* S₁) (g : S₁ → R) (hg : g 0 = 0) (φ : MvPolynomial σ S₁) : + map f (Finsupp.mapRange g hg φ) = φ ↔ ∀ d, f (g (coeff d φ)) = coeff d φ := by + rw [MvPolynomial.ext_iff] + apply forall_congr'; intro m + rw [coeff_map] + apply eq_iff_eq_cancel_right.mpr + rfl + +/-- If `f : S₁ →ₐ[R] S₂` is a morphism of `R`-algebras, then so is `MvPolynomial.map f`. -/ +@[simps!] +def mapAlgHom [CommSemiring S₂] [Algebra R S₁] [Algebra R S₂] (f : S₁ →ₐ[R] S₂) : + MvPolynomial σ S₁ →ₐ[R] MvPolynomial σ S₂ := + { map (↑f : S₁ →+* S₂) with + commutes' := fun r => by + have h₁ : algebraMap R (MvPolynomial σ S₁) r = C (algebraMap R S₁ r) := rfl + have h₂ : algebraMap R (MvPolynomial σ S₂) r = C (algebraMap R S₂ r) := rfl + simp_rw [OneHom.toFun_eq_coe] + -- Porting note: we're missing some `simp` lemmas like `MonoidHom.coe_toOneHom` + change @DFunLike.coe (_ →+* _) _ _ _ _ _ = _ + rw [h₁, h₂, map, eval₂Hom_C, RingHom.comp_apply, AlgHom.coe_toRingHom, AlgHom.commutes] } + +@[simp] +theorem mapAlgHom_id [Algebra R S₁] : + mapAlgHom (AlgHom.id R S₁) = AlgHom.id R (MvPolynomial σ S₁) := + AlgHom.ext map_id + +@[simp] +theorem mapAlgHom_coe_ringHom [CommSemiring S₂] [Algebra R S₁] [Algebra R S₂] (f : S₁ →ₐ[R] S₂) : + ↑(mapAlgHom f : _ →ₐ[R] MvPolynomial σ S₂) = + (map ↑f : MvPolynomial σ S₁ →+* MvPolynomial σ S₂) := + RingHom.mk_coe _ _ _ _ _ + +end Map + +section Aeval + +/-! ### The algebra of multivariate polynomials -/ + + +variable [Algebra R S₁] [CommSemiring S₂] +variable (f : σ → S₁) + +@[simp] +theorem algebraMap_apply (r : R) : algebraMap R (MvPolynomial σ S₁) r = C (algebraMap R S₁ r) := rfl + +/-- A map `σ → S₁` where `S₁` is an algebra over `R` generates an `R`-algebra homomorphism +from multivariate polynomials over `σ` to `S₁`. -/ +def aeval : MvPolynomial σ R →ₐ[R] S₁ := + { eval₂Hom (algebraMap R S₁) f with commutes' := fun _r => eval₂_C _ _ _ } + +theorem aeval_def (p : MvPolynomial σ R) : aeval f p = eval₂ (algebraMap R S₁) f p := + rfl + +theorem aeval_eq_eval₂Hom (p : MvPolynomial σ R) : aeval f p = eval₂Hom (algebraMap R S₁) f p := + rfl + +@[simp] +lemma coe_aeval_eq_eval : RingHomClass.toRingHom (MvPolynomial.aeval f) = MvPolynomial.eval f := + rfl + +@[simp] +theorem aeval_X (s : σ) : aeval f (X s : MvPolynomial _ R) = f s := + eval₂_X _ _ _ + +theorem aeval_C (r : R) : aeval f (C r) = algebraMap R S₁ r := + eval₂_C _ _ _ + +@[simp] theorem aeval_ofNat (n : Nat) [n.AtLeastTwo] : + aeval f (ofNat(n) : MvPolynomial σ R) = ofNat(n) := + map_ofNat _ _ + +theorem aeval_unique (φ : MvPolynomial σ R →ₐ[R] S₁) : φ = aeval (φ ∘ X) := by + ext i + simp + +theorem aeval_X_left : aeval X = AlgHom.id R (MvPolynomial σ R) := + (aeval_unique (AlgHom.id R _)).symm + +theorem aeval_X_left_apply (p : MvPolynomial σ R) : aeval X p = p := + AlgHom.congr_fun aeval_X_left p + +theorem comp_aeval {B : Type*} [CommSemiring B] [Algebra R B] (φ : S₁ →ₐ[R] B) : + φ.comp (aeval f) = aeval fun i => φ (f i) := by + ext i + simp + +lemma comp_aeval_apply {B : Type*} [CommSemiring B] [Algebra R B] (φ : S₁ →ₐ[R] B) + (p : MvPolynomial σ R) : + φ (aeval f p) = aeval (fun i ↦ φ (f i)) p := by + rw [← comp_aeval, AlgHom.coe_comp, comp_apply] + +@[simp] +theorem map_aeval {B : Type*} [CommSemiring B] (g : σ → S₁) (φ : S₁ →+* B) (p : MvPolynomial σ R) : + φ (aeval g p) = eval₂Hom (φ.comp (algebraMap R S₁)) (fun i => φ (g i)) p := by + rw [← comp_eval₂Hom] + rfl + +@[simp] +theorem eval₂Hom_zero (f : R →+* S₂) : eval₂Hom f (0 : σ → S₂) = f.comp constantCoeff := by + ext <;> simp + +@[simp] +theorem eval₂Hom_zero' (f : R →+* S₂) : eval₂Hom f (fun _ => 0 : σ → S₂) = f.comp constantCoeff := + eval₂Hom_zero f + +theorem eval₂Hom_zero_apply (f : R →+* S₂) (p : MvPolynomial σ R) : + eval₂Hom f (0 : σ → S₂) p = f (constantCoeff p) := + RingHom.congr_fun (eval₂Hom_zero f) p + +theorem eval₂Hom_zero'_apply (f : R →+* S₂) (p : MvPolynomial σ R) : + eval₂Hom f (fun _ => 0 : σ → S₂) p = f (constantCoeff p) := + eval₂Hom_zero_apply f p + +@[simp] +theorem eval₂_zero_apply (f : R →+* S₂) (p : MvPolynomial σ R) : + eval₂ f (0 : σ → S₂) p = f (constantCoeff p) := + eval₂Hom_zero_apply _ _ + +@[simp] +theorem eval₂_zero'_apply (f : R →+* S₂) (p : MvPolynomial σ R) : + eval₂ f (fun _ => 0 : σ → S₂) p = f (constantCoeff p) := + eval₂_zero_apply f p + +@[simp] +theorem aeval_zero (p : MvPolynomial σ R) : + aeval (0 : σ → S₁) p = algebraMap _ _ (constantCoeff p) := + eval₂Hom_zero_apply (algebraMap R S₁) p + +@[simp] +theorem aeval_zero' (p : MvPolynomial σ R) : + aeval (fun _ => 0 : σ → S₁) p = algebraMap _ _ (constantCoeff p) := + aeval_zero p + +@[simp] +theorem eval_zero : eval (0 : σ → R) = constantCoeff := + eval₂Hom_zero _ + +@[simp] +theorem eval_zero' : eval (fun _ => 0 : σ → R) = constantCoeff := + eval₂Hom_zero _ + +theorem aeval_monomial (g : σ → S₁) (d : σ →₀ ℕ) (r : R) : + aeval g (monomial d r) = algebraMap _ _ r * d.prod fun i k => g i ^ k := + eval₂Hom_monomial _ _ _ _ + +theorem eval₂Hom_eq_zero (f : R →+* S₂) (g : σ → S₂) (φ : MvPolynomial σ R) + (h : ∀ d, φ.coeff d ≠ 0 → ∃ i ∈ d.support, g i = 0) : eval₂Hom f g φ = 0 := by + rw [φ.as_sum, map_sum] + refine Finset.sum_eq_zero fun d hd => ?_ + obtain ⟨i, hi, hgi⟩ : ∃ i ∈ d.support, g i = 0 := h d (Finsupp.mem_support_iff.mp hd) + rw [eval₂Hom_monomial, Finsupp.prod, Finset.prod_eq_zero hi, mul_zero] + rw [hgi, zero_pow] + rwa [← Finsupp.mem_support_iff] + +theorem aeval_eq_zero [Algebra R S₂] (f : σ → S₂) (φ : MvPolynomial σ R) + (h : ∀ d, φ.coeff d ≠ 0 → ∃ i ∈ d.support, f i = 0) : aeval f φ = 0 := + eval₂Hom_eq_zero _ _ _ h + +theorem aeval_sum {ι : Type*} (s : Finset ι) (φ : ι → MvPolynomial σ R) : + aeval f (∑ i ∈ s, φ i) = ∑ i ∈ s, aeval f (φ i) := + map_sum (MvPolynomial.aeval f) _ _ + +@[to_additive existing] +theorem aeval_prod {ι : Type*} (s : Finset ι) (φ : ι → MvPolynomial σ R) : + aeval f (∏ i ∈ s, φ i) = ∏ i ∈ s, aeval f (φ i) := + map_prod (MvPolynomial.aeval f) _ _ + +variable (R) + +theorem _root_.Algebra.adjoin_range_eq_range_aeval : + Algebra.adjoin R (Set.range f) = (MvPolynomial.aeval f).range := by + simp only [← Algebra.map_top, ← MvPolynomial.adjoin_range_X, AlgHom.map_adjoin, ← Set.range_comp, + Function.comp_def, MvPolynomial.aeval_X] + +theorem _root_.Algebra.adjoin_eq_range (s : Set S₁) : + Algebra.adjoin R s = (MvPolynomial.aeval ((↑) : s → S₁)).range := by + rw [← Algebra.adjoin_range_eq_range_aeval, Subtype.range_coe] + +end Aeval + +section AevalTower + +variable {S A B : Type*} [CommSemiring S] [CommSemiring A] [CommSemiring B] +variable [Algebra S R] [Algebra S A] [Algebra S B] + +/-- Version of `aeval` for defining algebra homs out of `MvPolynomial σ R` over a smaller base ring + than `R`. -/ +def aevalTower (f : R →ₐ[S] A) (X : σ → A) : MvPolynomial σ R →ₐ[S] A := + { eval₂Hom (↑f) X with + commutes' := fun r => by + simp [IsScalarTower.algebraMap_eq S R (MvPolynomial σ R), algebraMap_eq] } + +variable (g : R →ₐ[S] A) (y : σ → A) + +@[simp] +theorem aevalTower_X (i : σ) : aevalTower g y (X i) = y i := + eval₂_X _ _ _ + +@[simp] +theorem aevalTower_C (x : R) : aevalTower g y (C x) = g x := + eval₂_C _ _ _ + +@[simp] +theorem aevalTower_ofNat (n : Nat) [n.AtLeastTwo] : + aevalTower g y (ofNat(n) : MvPolynomial σ R) = ofNat(n) := + _root_.map_ofNat _ _ + +@[simp] +theorem aevalTower_comp_C : (aevalTower g y : MvPolynomial σ R →+* A).comp C = g := + RingHom.ext <| aevalTower_C _ _ + +theorem aevalTower_algebraMap (x : R) : aevalTower g y (algebraMap R (MvPolynomial σ R) x) = g x := + eval₂_C _ _ _ + +theorem aevalTower_comp_algebraMap : + (aevalTower g y : MvPolynomial σ R →+* A).comp (algebraMap R (MvPolynomial σ R)) = g := + aevalTower_comp_C _ _ + +theorem aevalTower_toAlgHom (x : R) : + aevalTower g y (IsScalarTower.toAlgHom S R (MvPolynomial σ R) x) = g x := + aevalTower_algebraMap _ _ _ + +@[simp] +theorem aevalTower_comp_toAlgHom : + (aevalTower g y).comp (IsScalarTower.toAlgHom S R (MvPolynomial σ R)) = g := + AlgHom.coe_ringHom_injective <| aevalTower_comp_algebraMap _ _ + +@[simp] +theorem aevalTower_id : + aevalTower (AlgHom.id S S) = (aeval : (σ → S) → MvPolynomial σ S →ₐ[S] S) := by + ext + simp only [aevalTower_X, aeval_X] + +@[simp] +theorem aevalTower_ofId : + aevalTower (Algebra.ofId S A) = (aeval : (σ → A) → MvPolynomial σ S →ₐ[S] A) := by + ext + simp only [aeval_X, aevalTower_X] + +end AevalTower + +section EvalMem + +variable {S subS : Type*} [CommSemiring S] [SetLike subS S] [SubsemiringClass subS S] + +theorem eval₂_mem {f : R →+* S} {p : MvPolynomial σ R} {s : subS} + (hs : ∀ i ∈ p.support, f (p.coeff i) ∈ s) {v : σ → S} (hv : ∀ i, v i ∈ s) : + MvPolynomial.eval₂ f v p ∈ s := by + classical + replace hs : ∀ i, f (p.coeff i) ∈ s := by + intro i + by_cases hi : i ∈ p.support + · exact hs i hi + · rw [MvPolynomial.not_mem_support_iff.1 hi, f.map_zero] + exact zero_mem s + induction' p using MvPolynomial.induction_on''' with a a b f ha _ ih + · simpa using hs 0 + rw [eval₂_add, eval₂_monomial] + refine add_mem (mul_mem ?_ <| prod_mem fun i _ => pow_mem (hv _) _) (ih fun i => ?_) + · have := hs a -- Porting note: was `simpa only [...]` + rwa [coeff_add, MvPolynomial.not_mem_support_iff.1 ha, add_zero, coeff_monomial, + if_pos rfl] at this + have := hs i + rw [coeff_add, coeff_monomial] at this + split_ifs at this with h + · subst h + rw [MvPolynomial.not_mem_support_iff.1 ha, map_zero] + exact zero_mem _ + · rwa [zero_add] at this + +theorem eval_mem {p : MvPolynomial σ S} {s : subS} (hs : ∀ i ∈ p.support, p.coeff i ∈ s) {v : σ → S} + (hv : ∀ i, v i ∈ s) : MvPolynomial.eval v p ∈ s := + eval₂_mem hs hv + +end EvalMem + +variable {S T : Type*} [CommSemiring S] [Algebra R S] [CommSemiring T] [Algebra R T] [Algebra S T] + [IsScalarTower R S T] + +lemma aeval_sum_elim {σ τ : Type*} (p : MvPolynomial (σ ⊕ τ) R) (f : τ → S) (g : σ → T) : + (aeval (Sum.elim g (algebraMap S T ∘ f))) p = + (aeval g) ((aeval (Sum.elim X (C ∘ f))) p) := by + induction' p using MvPolynomial.induction_on with r p q hp hq p i h + · simp [← IsScalarTower.algebraMap_apply] + · simp [hp, hq] + · cases i <;> simp [h] + +end CommSemiring + +end MvPolynomial diff --git a/Mathlib/Algebra/MvPolynomial/Rename.lean b/Mathlib/Algebra/MvPolynomial/Rename.lean index d89efbfdf0044..d503c6f6d6063 100644 --- a/Mathlib/Algebra/MvPolynomial/Rename.lean +++ b/Mathlib/Algebra/MvPolynomial/Rename.lean @@ -3,7 +3,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, Johan Commelin, Mario Carneiro -/ -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval /-! # Renaming variables of polynomials diff --git a/Mathlib/Analysis/Analytic/Polynomial.lean b/Mathlib/Analysis/Analytic/Polynomial.lean index 77e62fd5b542b..62ad3e6477c07 100644 --- a/Mathlib/Analysis/Analytic/Polynomial.lean +++ b/Mathlib/Analysis/Analytic/Polynomial.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Junyan Xu -/ import Mathlib.Algebra.Polynomial.AlgebraMap -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval import Mathlib.Analysis.Analytic.Constructions import Mathlib.Topology.Algebra.Module.FiniteDimension diff --git a/Mathlib/LinearAlgebra/Matrix/MvPolynomial.lean b/Mathlib/LinearAlgebra/Matrix/MvPolynomial.lean index 632400c9ae2eb..197b0715e6b17 100644 --- a/Mathlib/LinearAlgebra/Matrix/MvPolynomial.lean +++ b/Mathlib/LinearAlgebra/Matrix/MvPolynomial.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval import Mathlib.Algebra.MvPolynomial.CommRing import Mathlib.LinearAlgebra.Matrix.Determinant.Basic diff --git a/Mathlib/RingTheory/Adjoin/FG.lean b/Mathlib/RingTheory/Adjoin/FG.lean index fdbe2c43cbbaa..b98e44e79d735 100644 --- a/Mathlib/RingTheory/Adjoin/FG.lean +++ b/Mathlib/RingTheory/Adjoin/FG.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.Algebra.EuclideanDomain.Int -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval import Mathlib.RingTheory.Polynomial.Basic import Mathlib.RingTheory.PrincipalIdealDomain diff --git a/Mathlib/RingTheory/MvPolynomial/Tower.lean b/Mathlib/RingTheory/MvPolynomial/Tower.lean index 77228738a64aa..5d68e1ff6068d 100644 --- a/Mathlib/RingTheory/MvPolynomial/Tower.lean +++ b/Mathlib/RingTheory/MvPolynomial/Tower.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yuyang Zhao -/ import Mathlib.Algebra.Algebra.Tower -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval /-! # Algebra towers for multivariate polynomial diff --git a/Mathlib/RingTheory/MvPowerSeries/Basic.lean b/Mathlib/RingTheory/MvPowerSeries/Basic.lean index f42900e728554..76db7536ce0c4 100644 --- a/Mathlib/RingTheory/MvPowerSeries/Basic.lean +++ b/Mathlib/RingTheory/MvPowerSeries/Basic.lean @@ -4,12 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Kenny Lau -/ -import Mathlib.Algebra.MvPolynomial.Basic import Mathlib.Algebra.Order.Antidiag.Finsupp import Mathlib.Data.Finsupp.Antidiagonal import Mathlib.Data.Finsupp.Weight import Mathlib.Tactic.Linarith import Mathlib.LinearAlgebra.Pi +import Mathlib.Algebra.MvPolynomial.Eval /-! # Formal (multivariate) power series diff --git a/Mathlib/RingTheory/MvPowerSeries/Trunc.lean b/Mathlib/RingTheory/MvPowerSeries/Trunc.lean index 17bb1c78178bd..9ab013cfffe8c 100644 --- a/Mathlib/RingTheory/MvPowerSeries/Trunc.lean +++ b/Mathlib/RingTheory/MvPowerSeries/Trunc.lean @@ -6,6 +6,7 @@ Authors: Johan Commelin, Kenny Lau import Mathlib.RingTheory.MvPowerSeries.Basic import Mathlib.Data.Finsupp.Interval +import Mathlib.Algebra.MvPolynomial.Eval /-! diff --git a/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean b/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean index 78234992f9b1c..fe2bd104311dc 100644 --- a/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean +++ b/Mathlib/RingTheory/TensorProduct/MvPolynomial.lean @@ -5,7 +5,7 @@ Authors: Antoine Chambert-Loir -/ import Mathlib.LinearAlgebra.DirectSum.Finsupp -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval import Mathlib.RingTheory.TensorProduct.Basic import Mathlib.Algebra.MvPolynomial.Equiv /-! diff --git a/Mathlib/Topology/Algebra/MvPolynomial.lean b/Mathlib/Topology/Algebra/MvPolynomial.lean index 20b40fc537cde..ec1521fd4aede 100644 --- a/Mathlib/Topology/Algebra/MvPolynomial.lean +++ b/Mathlib/Topology/Algebra/MvPolynomial.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Ruben Van de Velde -/ -import Mathlib.Algebra.MvPolynomial.Basic +import Mathlib.Algebra.MvPolynomial.Eval import Mathlib.Topology.Algebra.Ring.Basic /-! diff --git a/scripts/noshake.json b/scripts/noshake.json index 1c1f5e365a82b..62e7ac4f7449b 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -318,6 +318,8 @@ "Mathlib.RingTheory.PowerSeries.Basic": ["Mathlib.Algebra.CharP.Defs", "Mathlib.Tactic.MoveAdd"], "Mathlib.RingTheory.PolynomialAlgebra": ["Mathlib.Data.Matrix.DMatrix"], + "Mathlib.RingTheory.MvPowerSeries.Basic": + ["Mathlib.Algebra.MvPolynomial.Eval"], "Mathlib.RingTheory.MvPolynomial.Homogeneous": ["Mathlib.Algebra.DirectSum.Internal"], "Mathlib.RingTheory.KrullDimension.Basic": From 54f1019549c91c86ea2fd01f1ee9389ac536af36 Mon Sep 17 00:00:00 2001 From: Vincent Beffara Date: Mon, 13 Jan 2025 18:19:35 +0000 Subject: [PATCH 212/681] feat(Topology/FiberBundle/Trivialization): local lifting through a Trivialization (#19056) Define versions of local lifting through a `Trivialization`. --- .../Topology/FiberBundle/Trivialization.lean | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Mathlib/Topology/FiberBundle/Trivialization.lean b/Mathlib/Topology/FiberBundle/Trivialization.lean index 4b30a7c20349a..2652c7590a667 100644 --- a/Mathlib/Topology/FiberBundle/Trivialization.lean +++ b/Mathlib/Topology/FiberBundle/Trivialization.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Data.Bundle import Mathlib.Data.Set.Image +import Mathlib.Topology.CompactOpen import Mathlib.Topology.PartialHomeomorph import Mathlib.Topology.Order.Basic @@ -742,4 +743,50 @@ noncomputable def disjointUnion (e e' : Trivialization F proj) (H : Disjoint e.b end Piecewise +section Lift + +/-- The local lifting through a Trivialization `T` from the base to the leaf containing `z`. -/ +def lift (T : Trivialization F proj) (z : Z) (b : B) : Z := T.invFun (b, (T z).2) + +variable {T : Trivialization F proj} {z : Z} {b : B} + +@[simp] +theorem lift_self (he : proj z ∈ T.baseSet) : T.lift z (proj z) = z := + symm_apply_mk_proj _ <| T.mem_source.2 he + +theorem proj_lift (hx : b ∈ T.baseSet) : proj (T.lift z b) = b := + T.proj_symm_apply <| T.mem_target.2 hx + +/-- The restriction of `lift` to the source and base set of `T`, as a bundled continuous map. -/ +def liftCM (T : Trivialization F proj) : C(T.source × T.baseSet, T.source) where + toFun ex := ⟨T.lift ex.1 ex.2, T.map_target (by simp [mem_target])⟩ + continuous_toFun := by + apply Continuous.subtype_mk + refine T.continuousOn_invFun.comp_continuous ?_ (by simp [mem_target]) + apply continuous_prod_mk.mpr ⟨by fun_prop, continuous_snd.comp ?_⟩ + exact T.continuousOn_toFun.comp_continuous (by fun_prop) (by simp) + +variable {ι : Type*} [TopologicalSpace ι] [LocallyCompactPair ι T.baseSet] + {γ : C(ι, T.baseSet)} {i : ι} {e : T.source} + +/-- Extension of `liftCM` to continuous maps taking values in `T.baseSet` (local version of +homotopy lifting).-/ +def clift (T : Trivialization F proj) [LocallyCompactPair ι T.baseSet] : + C(T.source × C(ι, T.baseSet), C(ι, T.source)) := by + let Ψ : C((T.source × C(ι, T.baseSet)) × ι, C(ι, T.baseSet) × ι) := + ⟨fun eγt => (eγt.1.2, eγt.2), by fun_prop⟩ + refine ContinuousMap.curry <| T.liftCM.comp <| ⟨fun eγt => ⟨eγt.1.1, eγt.1.2 eγt.2⟩, ?_⟩ + simpa using ⟨by fun_prop, ContinuousEval.continuous_eval.comp Ψ.continuous⟩ + +@[simp] +theorem clift_self (h : proj e.1 = γ i) : + T.clift (e, γ) i = e := by + have : proj e ∈ T.baseSet := by simp [h] + simp [clift, liftCM, ← h, lift_self, this] + +theorem proj_clift : proj (T.clift (e, γ) i) = γ i := by + simp [clift, liftCM, proj_lift] + +end Lift + end Trivialization From 5b601b69e6ae04f49914c47b7ab91ba542755739 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Mon, 13 Jan 2025 18:29:29 +0000 Subject: [PATCH 213/681] chore(RingTheory): move `FaithfullyFlat` into its own folder (#20716) Preparation for more results on faithfully flat algebras. --- Mathlib.lean | 2 +- Mathlib/Algebra/Category/Ring/LinearAlgebra.lean | 2 +- .../Flat/{FaithfullyFlat.lean => FaithfullyFlat/Basic.lean} | 0 Mathlib/RingTheory/TensorProduct/Nontrivial.lean | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename Mathlib/RingTheory/Flat/{FaithfullyFlat.lean => FaithfullyFlat/Basic.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 79bc49a205879..dadcd0fcb5789 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4447,7 +4447,7 @@ import Mathlib.RingTheory.Flat.Basic import Mathlib.RingTheory.Flat.CategoryTheory import Mathlib.RingTheory.Flat.Equalizer import Mathlib.RingTheory.Flat.EquationalCriterion -import Mathlib.RingTheory.Flat.FaithfullyFlat +import Mathlib.RingTheory.Flat.FaithfullyFlat.Basic import Mathlib.RingTheory.Flat.Localization import Mathlib.RingTheory.Flat.Stability import Mathlib.RingTheory.FractionalIdeal.Basic diff --git a/Mathlib/Algebra/Category/Ring/LinearAlgebra.lean b/Mathlib/Algebra/Category/Ring/LinearAlgebra.lean index d19320fcdcd54..056f49c7b389b 100644 --- a/Mathlib/Algebra/Category/Ring/LinearAlgebra.lean +++ b/Mathlib/Algebra/Category/Ring/LinearAlgebra.lean @@ -6,7 +6,7 @@ Authors: Christian Merten import Mathlib.Algebra.Category.Ring.Constructions import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq import Mathlib.LinearAlgebra.Basis.VectorSpace -import Mathlib.RingTheory.Flat.FaithfullyFlat +import Mathlib.RingTheory.Flat.FaithfullyFlat.Basic /-! # Results on the category of rings requiring linear algebra diff --git a/Mathlib/RingTheory/Flat/FaithfullyFlat.lean b/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean similarity index 100% rename from Mathlib/RingTheory/Flat/FaithfullyFlat.lean rename to Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean diff --git a/Mathlib/RingTheory/TensorProduct/Nontrivial.lean b/Mathlib/RingTheory/TensorProduct/Nontrivial.lean index ee304a244cbe6..c78b9bdcadd72 100644 --- a/Mathlib/RingTheory/TensorProduct/Nontrivial.lean +++ b/Mathlib/RingTheory/TensorProduct/Nontrivial.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jz Pan -/ import Mathlib.LinearAlgebra.Basis.VectorSpace -import Mathlib.RingTheory.Flat.FaithfullyFlat +import Mathlib.RingTheory.Flat.FaithfullyFlat.Basic import Mathlib.RingTheory.Localization.FractionRing /-! From 2b06bd42bb773436dae0db6119c16b294ea8d2aa Mon Sep 17 00:00:00 2001 From: damiano Date: Mon, 13 Jan 2025 21:09:53 +0000 Subject: [PATCH 214/681] feat: sort imports in import summary (#20701) This may make it easier to parse the report of the summary, when there are many import changes. I commented #20698 with the output of the new script, in case you want to see it in action. --- scripts/import_trans_difference.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/scripts/import_trans_difference.sh b/scripts/import_trans_difference.sh index a13bebc4957cf..30902e69f971e 100755 --- a/scripts/import_trans_difference.sh +++ b/scripts/import_trans_difference.sh @@ -85,15 +85,21 @@ printf '\n\n
Import changes for all files\n\n%s\n\n%s files%s
|%s|\n", nums[x], reds[x], x) } + sorted="" + split(reds[x], toSort, "\n") + asort(toSort) + for(i in toSort) {sorted=sorted toSort[i]} + if (nums[x] <= 2) { printf("|%s|%s|\n", sorted, x) } + else { printf("|
%s files%s
|%s|\n", nums[x], sorted, x) } } } }' transImports*.txt | sort -t'|' -n -k3 From 0ef9418b6aa70cab1ac33e37b88dd4ceb7fe1297 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Tue, 14 Jan 2025 01:19:30 +0000 Subject: [PATCH 215/681] chore: address `simps` porting notes (#20717) I searched for `porting note.*simps` and tried to fix or delete the ones that were easy to address. Broadly: * delete porting notes about replacing one form of `simps` with another * if the note complains about wrong lemmas or timeouts, check if that's still the case and delete if not. --- Mathlib/Algebra/Algebra/Equiv.lean | 10 +-------- Mathlib/Algebra/Category/Grp/Limits.lean | 2 -- Mathlib/Algebra/DirectSum/Decomposition.lean | 10 +-------- Mathlib/Algebra/Group/Equiv/Basic.lean | 22 +------------------ Mathlib/Algebra/Group/Units/Equiv.lean | 4 ---- Mathlib/Algebra/Group/WithOne/Basic.lean | 2 -- Mathlib/Algebra/Module/Submodule/Map.lean | 10 +-------- Mathlib/Algebra/Order/Hom/Ring.lean | 5 +++-- .../GammaSpecAdjunction.lean | 3 ++- Mathlib/AlgebraicGeometry/Restrict.lean | 13 +---------- Mathlib/AlgebraicGeometry/Spec.lean | 2 +- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 1 - .../AlgebraicTopology/DoldKan/NCompGamma.lean | 12 +--------- .../Analysis/Normed/Group/HomCompletion.lean | 2 +- Mathlib/CategoryTheory/Abelian/Ext.lean | 7 ------ Mathlib/CategoryTheory/Action/Basic.lean | 13 ----------- .../Adjunction/Lifting/Left.lean | 2 +- .../Bicategory/FunctorBicategory/Oplax.lean | 4 ---- .../CategoryTheory/ConnectedComponents.lean | 3 --- .../CategoryTheory/Endofunctor/Algebra.lean | 6 ----- Mathlib/CategoryTheory/Limits/Cones.lean | 2 -- Mathlib/CategoryTheory/Limits/HasLimits.lean | 2 +- Mathlib/CategoryTheory/Limits/Opposites.lean | 3 --- .../CategoryTheory/Limits/Shapes/Types.lean | 3 --- Mathlib/CategoryTheory/Monoidal/Category.lean | 3 --- Mathlib/CategoryTheory/Monoidal/CommMon_.lean | 1 - .../Preadditive/AdditiveFunctor.lean | 1 - .../IntermediateField/Adjoin/Defs.lean | 2 -- Mathlib/GroupTheory/FreeAbelianGroup.lean | 2 +- Mathlib/LinearAlgebra/Finsupp/Defs.lean | 12 ++-------- Mathlib/LinearAlgebra/Multilinear/Basic.lean | 1 - Mathlib/ModelTheory/LanguageMap.lean | 2 +- Mathlib/ModelTheory/Syntax.lean | 2 +- Mathlib/RingTheory/AdjoinRoot.lean | 2 +- Mathlib/RingTheory/PolynomialAlgebra.lean | 1 - .../Algebra/Module/StrongTopology.lean | 16 +------------- .../Topology/ContinuousMap/Bounded/Basic.lean | 2 +- Mathlib/Topology/ContinuousMap/Compact.lean | 15 +------------ Mathlib/Topology/PartialHomeomorph.lean | 2 +- 39 files changed, 25 insertions(+), 182 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index 32d000a5799d1..6d699d6775650 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -605,9 +605,7 @@ def ofRingEquiv {f : A₁ ≃+* A₂} (hf : ∀ x, f (algebraMap R A₁ x) = alg end OfRingEquiv --- Porting note: projections mul & one not found, removed [simps] and added theorems manually --- @[simps (config := .lemmasOnly) one] -@[stacks 09HR] +@[simps (config := .lemmasOnly) one mul, stacks 09HR] instance aut : Group (A₁ ≃ₐ[R] A₁) where mul ϕ ψ := ψ.trans ϕ mul_assoc _ _ _ := rfl @@ -617,12 +615,6 @@ instance aut : Group (A₁ ≃ₐ[R] A₁) where inv := symm inv_mul_cancel ϕ := ext <| symm_apply_apply ϕ -theorem aut_mul (ϕ ψ : A₁ ≃ₐ[R] A₁) : ϕ * ψ = ψ.trans ϕ := - rfl - -theorem aut_one : 1 = AlgEquiv.refl (R := R) (A₁ := A₁) := - rfl - @[simp] theorem one_apply (x : A₁) : (1 : A₁ ≃ₐ[R] A₁) x = x := rfl diff --git a/Mathlib/Algebra/Category/Grp/Limits.lean b/Mathlib/Algebra/Category/Grp/Limits.lean index af71b540c80c5..bf20b86b85b04 100644 --- a/Mathlib/Algebra/Category/Grp/Limits.lean +++ b/Mathlib/Algebra/Category/Grp/Limits.lean @@ -489,8 +489,6 @@ theorem kernelIsoKer_inv_comp_ι {G H : AddCommGrp.{u}} (f : G ⟶ H) : ext simp [kernelIsoKer] --- Porting note: explicitly add what to be synthesized under `simps!`, because other lemmas --- automatically generated is not in normal form /-- The categorical kernel inclusion for `f : G ⟶ H`, as an object over `G`, agrees with the `AddSubgroup.subtype` map. -/ diff --git a/Mathlib/Algebra/DirectSum/Decomposition.lean b/Mathlib/Algebra/DirectSum/Decomposition.lean index 68b4f5db83e65..41e504b6fe886 100644 --- a/Mathlib/Algebra/DirectSum/Decomposition.lean +++ b/Mathlib/Algebra/DirectSum/Decomposition.lean @@ -136,18 +136,10 @@ theorem degree_eq_of_mem_mem {x : M} {i j : ι} (hxi : x ∈ ℳ i) (hxj : x ∈ /-- If `M` is graded by `ι` with degree `i` component `ℳ i`, then it is isomorphic as an additive monoid to a direct sum of components. -/ --- Porting note: deleted [simps] and added the corresponding lemmas by hand +@[simps!] def decomposeAddEquiv : M ≃+ ⨁ i, ℳ i := AddEquiv.symm { (decompose ℳ).symm with map_add' := map_add (DirectSum.coeAddMonoidHom ℳ) } -@[simp] -lemma decomposeAddEquiv_apply (a : M) : - decomposeAddEquiv ℳ a = decompose ℳ a := rfl - -@[simp] -lemma decomposeAddEquiv_symm_apply (a : ⨁ i, ℳ i) : - (decomposeAddEquiv ℳ).symm a = (decompose ℳ).symm a := rfl - @[simp] theorem decompose_zero : decompose ℳ (0 : M) = 0 := map_zero (decomposeAddEquiv ℳ) diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index 036274253a7de..bde39ac2fdd19 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -563,8 +563,6 @@ for multiplicative maps from a monoid to a commutative monoid. @[to_additive (attr := simps apply) "An additive analogue of `Equiv.arrowCongr`, for additive maps from an additive monoid to a commutative additive monoid."] --- Porting note: @[simps apply] removed because it was making a lemma which --- wasn't in simp normal form. def monoidHomCongr {M N P Q} [MulOneClass M] [MulOneClass N] [CommMonoid P] [CommMonoid Q] (f : M ≃* N) (g : P ≃* Q) : (M →* P) ≃* (N →* Q) where toFun h := g.toMonoidHom.comp (h.comp f.symm.toMonoidHom) @@ -660,15 +658,11 @@ def postcompEquiv {α β : Type*} [Monoid α] [Monoid β] (e : α ≃* β) (γ : end MonoidHom --- Porting note: we want to add --- `@[simps (config := .asFn)]` --- here, but it generates simp lemmas which aren't in simp normal form --- (they have `toFun` in) /-- Given a pair of multiplicative homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`, returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This constructor is useful if the underlying type(s) have specialized `ext` lemmas for multiplicative homomorphisms. -/ -@[to_additive +@[to_additive (attr := simps (config := .asFn)) "Given a pair of additive homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`. This constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive @@ -681,20 +675,6 @@ def MulHom.toMulEquiv [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) (h₁ right_inv := DFunLike.congr_fun h₂ map_mul' := f.map_mul --- Porting note: the next two lemmas were added manually because `@[simps]` is generating --- lemmas with `toFun` in -@[to_additive (attr := simp)] -theorem MulHom.toMulEquiv_apply [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) - (h₁ : g.comp f = MulHom.id _) (h₂ : f.comp g = MulHom.id _) : - ((MulHom.toMulEquiv f g h₁ h₂) : M → N) = f := - rfl - -@[to_additive (attr := simp)] -theorem MulHom.toMulEquiv_symm_apply [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) - (h₁ : g.comp f = MulHom.id _) (h₂ : f.comp g = MulHom.id _) : - (MulEquiv.symm (MulHom.toMulEquiv f g h₁ h₂) : N → M) = ↑g := - rfl - /-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`, returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This constructor is useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/ diff --git a/Mathlib/Algebra/Group/Units/Equiv.lean b/Mathlib/Algebra/Group/Units/Equiv.lean index 6227bf7099124..b0afb2bca634e 100644 --- a/Mathlib/Algebra/Group/Units/Equiv.lean +++ b/Mathlib/Algebra/Group/Units/Equiv.lean @@ -172,10 +172,6 @@ def unitsEquivProdSubtype [Monoid α] : αˣ ≃ {p : α × α // p.1 * p.2 = 1 left_inv _ := Units.ext rfl right_inv _ := Subtype.ext <| Prod.ext rfl rfl --- Porting note: we don't put `@[simp]` on the additive version; --- mysteriously simp can already prove that one (although not the multiplicative one)! --- Porting note: `@[simps apply]` removed because right now it's generating lemmas which --- aren't in simp normal form (they contain a `toFun`) /-- In a `DivisionCommMonoid`, `Equiv.inv` is a `MulEquiv`. There is a variant of this `MulEquiv.inv' G : G ≃* Gᵐᵒᵖ` for the non-commutative case. -/ @[to_additive (attr := simps apply) diff --git a/Mathlib/Algebra/Group/WithOne/Basic.lean b/Mathlib/Algebra/Group/WithOne/Basic.lean index 76a4286b0858d..7a525e26b753b 100644 --- a/Mathlib/Algebra/Group/WithOne/Basic.lean +++ b/Mathlib/Algebra/Group/WithOne/Basic.lean @@ -110,8 +110,6 @@ theorem map_map (f : α →ₙ* β) (g : β →ₙ* γ) (x) : map g (map f x) = theorem map_comp (f : α →ₙ* β) (g : β →ₙ* γ) : map (g.comp f) = (map g).comp (map f) := MonoidHom.ext fun x => (map_map f g x).symm --- Porting note: this used to have `@[simps apply]` but it was generating lemmas which --- weren't in simp normal form. /-- A version of `Equiv.optionCongr` for `WithOne`. -/ @[to_additive (attr := simps apply) "A version of `Equiv.optionCongr` for `WithZero`."] def _root_.MulEquiv.withOneCongr (e : α ≃* β) : WithOne α ≃* WithOne β := diff --git a/Mathlib/Algebra/Module/Submodule/Map.lean b/Mathlib/Algebra/Module/Submodule/Map.lean index ac43875d2bd8a..fbb5ee47727bb 100644 --- a/Mathlib/Algebra/Module/Submodule/Map.lean +++ b/Mathlib/Algebra/Module/Submodule/Map.lean @@ -467,7 +467,7 @@ variable [Semiring R] [AddCommMonoid M] [Module R M] /-- If `s ≤ t`, then we can view `s` as a submodule of `t` by taking the comap of `t.subtype`. -/ -@[simps symm_apply] +@[simps apply_coe symm_apply] def comapSubtypeEquivOfLe {p q : Submodule R M} (hpq : p ≤ q) : comap q.subtype p ≃ₗ[R] p where toFun x := ⟨x, x.2⟩ invFun x := ⟨⟨x, hpq x.2⟩, x.2⟩ @@ -476,14 +476,6 @@ def comapSubtypeEquivOfLe {p q : Submodule R M} (hpq : p ≤ q) : comap q.subtyp map_add' _ _ := rfl map_smul' _ _ := rfl --- Porting note: The original theorem generated by `simps` was using `LinearEquiv.toLinearMap`, --- different from the theorem on Lean 3, and not simp-normal form. -@[simp] -theorem comapSubtypeEquivOfLe_apply_coe {p q : Submodule R M} (hpq : p ≤ q) - (x : comap q.subtype p) : - (comapSubtypeEquivOfLe hpq x : M) = (x : M) := - rfl - end Module end Submodule diff --git a/Mathlib/Algebra/Order/Hom/Ring.lean b/Mathlib/Algebra/Order/Hom/Ring.lean index 71fa34cb4fd5a..f0d4f29ca26ed 100644 --- a/Mathlib/Algebra/Order/Hom/Ring.lean +++ b/Mathlib/Algebra/Order/Hom/Ring.lean @@ -394,12 +394,13 @@ theorem symm_symm (e : α ≃+*o β) : e.symm.symm = e := rfl protected def trans (f : α ≃+*o β) (g : β ≃+*o γ) : α ≃+*o γ := ⟨f.toRingEquiv.trans g.toRingEquiv, (map_le_map_iff g).trans (map_le_map_iff f)⟩ -/- Porting note: Used to be generated by [simps] on `trans`, but the lhs of this simplifies under -simp, so problem with the simpNF linter. Removed [simps] attribute and added aux version below. -/ +/-- This lemma used to be generated by [simps] on `trans`, but the lhs of this simplifies under +simp. Removed [simps] attribute and added aux version below. -/ theorem trans_toRingEquiv (f : α ≃+*o β) (g : β ≃+*o γ) : (OrderRingIso.trans f g).toRingEquiv = RingEquiv.trans f.toRingEquiv g.toRingEquiv := rfl +/-- `simp`-normal form of `trans_toRingEquiv`. -/ @[simp] theorem trans_toRingEquiv_aux (f : α ≃+*o β) (g : β ≃+*o γ) : RingEquivClass.toRingEquiv (OrderRingIso.trans f g) diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index d50d424421ef6..b4331a3b7c954 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -311,7 +311,8 @@ theorem right_triangle (R : CommRingCat) : · intro r; apply toOpen_res /-- The adjunction `Γ ⊣ Spec` from `CommRingᵒᵖ` to `LocallyRingedSpace`. -/ --- Porting note: `simps` cause a time out, so `Unit` and `counit` will be added manually +-- Porting note: `simps` generates lemmas not in `simp` normal form, so `unit` and `counit` have to +-- be added manually def locallyRingedSpaceAdjunction : Γ.rightOp ⊣ Spec.toLocallyRingedSpace.{u} where unit := identityToΓSpec counit := (NatIso.op SpecΓIdentity).inv diff --git a/Mathlib/AlgebraicGeometry/Restrict.lean b/Mathlib/AlgebraicGeometry/Restrict.lean index 766c1a26259da..a0e2ce9e24ee9 100644 --- a/Mathlib/AlgebraicGeometry/Restrict.lean +++ b/Mathlib/AlgebraicGeometry/Restrict.lean @@ -260,10 +260,9 @@ instance (X : Scheme.{u}) {U V : X.Opens} (e : U ≤ V) : IsOpenImmersion (X.hom delta Scheme.homOfLE infer_instance --- Porting note: `simps` can't synthesize `obj_left, obj_hom, mapLeft` variable (X) in /-- The functor taking open subsets of `X` to open subschemes of `X`. -/ --- @[simps obj_left obj_hom mapLeft] +@[simps! obj_left obj_hom map_left] def Scheme.restrictFunctor : X.Opens ⥤ Over X where obj U := Over.mk U.ι map {U V} i := Over.homMk (X.homOfLE i.le) (by simp) @@ -274,16 +273,6 @@ def Scheme.restrictFunctor : X.Opens ⥤ Over X where ext1 exact (X.homOfLE_homOfLE i.le j.le).symm -@[simp] lemma Scheme.restrictFunctor_obj_left (U : X.Opens) : - (X.restrictFunctor.obj U).left = U := rfl - -@[simp] lemma Scheme.restrictFunctor_obj_hom (U : X.Opens) : - (X.restrictFunctor.obj U).hom = U.ι := rfl - -@[simp] -lemma Scheme.restrictFunctor_map_left {U V : X.Opens} (i : U ⟶ V) : - (X.restrictFunctor.map i).left = (X.homOfLE i.le) := rfl - @[deprecated (since := "2024-10-20")] alias Scheme.restrictFunctor_map_ofRestrict := Scheme.homOfLE_ι @[deprecated (since := "2024-10-20")] diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index 264ee6873f818..0769318a82148 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -75,7 +75,7 @@ theorem Spec.topMap_comp {R S T : CommRingCat.{u}} (f : R ⟶ S) (g : S ⟶ T) : -- if more is needed, add them here /-- The spectrum, as a contravariant functor from commutative rings to topological spaces. -/ -@[simps! obj map] +@[simps!] def Spec.toTop : CommRingCat.{u}ᵒᵖ ⥤ TopCat where obj R := Spec.topObj (unop R) map {_ _} f := Spec.topMap f.unop diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index e6e5296cb7084..b3cc9a3607da4 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -929,7 +929,6 @@ instance isIso_to_global : IsIso (toOpen R ⊤) := by infer_instance /-- The ring isomorphism between the ring `R` and the global sections `Γ(X, 𝒪ₓ)`. -/ --- Porting note: was @[simps (config := { rhsMd := Tactic.Transparency.semireducible })] @[simps!] def globalSectionsIso : CommRingCat.of R ≅ (structureSheaf R).1.obj (op ⊤) := asIso (toOpen R ⊤) diff --git a/Mathlib/AlgebraicTopology/DoldKan/NCompGamma.lean b/Mathlib/AlgebraicTopology/DoldKan/NCompGamma.lean index 05cf1193af780..0d240e27b3ec3 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/NCompGamma.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/NCompGamma.lean @@ -159,21 +159,11 @@ def natTrans : (N₁ : SimplicialObject C ⥤ _) ⋙ Γ₂ ⟶ toKaroubi _ where end Γ₂N₁ --- Porting note: removed @[simps] attribute because it was creating timeouts /-- The compatibility isomorphism relating `N₂ ⋙ Γ₂` and `N₁ ⋙ Γ₂`. -/ +@[simps! hom_app inv_app] def Γ₂N₂ToKaroubiIso : toKaroubi (SimplicialObject C) ⋙ N₂ ⋙ Γ₂ ≅ N₁ ⋙ Γ₂ := (Functor.associator _ _ _).symm ≪≫ isoWhiskerRight toKaroubiCompN₂IsoN₁ Γ₂ -@[simp] -lemma Γ₂N₂ToKaroubiIso_hom_app (X : SimplicialObject C) : - Γ₂N₂ToKaroubiIso.hom.app X = Γ₂.map (toKaroubiCompN₂IsoN₁.hom.app X) := by - simp [Γ₂N₂ToKaroubiIso] - -@[simp] -lemma Γ₂N₂ToKaroubiIso_inv_app (X : SimplicialObject C) : - Γ₂N₂ToKaroubiIso.inv.app X = Γ₂.map (toKaroubiCompN₂IsoN₁.inv.app X) := by - simp [Γ₂N₂ToKaroubiIso] - namespace Γ₂N₂ /-- The natural transformation `N₂ ⋙ Γ₂ ⟶ 𝟭 (SimplicialObject C)`. -/ diff --git a/Mathlib/Analysis/Normed/Group/HomCompletion.lean b/Mathlib/Analysis/Normed/Group/HomCompletion.lean index 3ef2814acd733..e37ddf7f47209 100644 --- a/Mathlib/Analysis/Normed/Group/HomCompletion.lean +++ b/Mathlib/Analysis/Normed/Group/HomCompletion.lean @@ -120,7 +120,7 @@ theorem NormedAddGroupHom.zero_completion : (0 : NormedAddGroupHom G H).completi normedAddGroupHomCompletionHom.map_zero /-- The map from a normed group to its completion, as a normed group hom. -/ -@[simps] -- Porting note: added `@[simps]` +@[simps] def NormedAddCommGroup.toCompl : NormedAddGroupHom G (Completion G) where toFun := (↑) map_add' := Completion.toCompl.map_add diff --git a/Mathlib/CategoryTheory/Abelian/Ext.lean b/Mathlib/CategoryTheory/Abelian/Ext.lean index 223c0b659b3b2..16fc11a38e93a 100644 --- a/Mathlib/CategoryTheory/Abelian/Ext.lean +++ b/Mathlib/CategoryTheory/Abelian/Ext.lean @@ -37,13 +37,6 @@ the first argument of `(X, Y) ↦ ModuleCat.of R (unop X ⟶ Y)` (which is the second argument of `linearYoneda`). -/ --- Porting note: the lemmas `Ext_obj` and `Ext_map` generated by `@[simps]` were --- being rejected by the type-checking linter; it's unclear exactly why. --- In any case, these lemmas were not actually used downstream in mathlib3, --- and seem unlikely to be directly useful (rather than lemmas in terms of resolutions), --- and so have been removed during porting: --- @[simps! obj map] - -- Porting note: the mathlib3 proofs of `map_id` and `map_comp` were timing out, -- but `aesop_cat` is fast if we leave them out. def Ext (n : ℕ) : Cᵒᵖ ⥤ C ⥤ ModuleCat R := diff --git a/Mathlib/CategoryTheory/Action/Basic.lean b/Mathlib/CategoryTheory/Action/Basic.lean index 7c61dd710f8eb..e46cc85367f18 100644 --- a/Mathlib/CategoryTheory/Action/Basic.lean +++ b/Mathlib/CategoryTheory/Action/Basic.lean @@ -223,19 +223,6 @@ instance : (FunctorCategoryEquivalence.functor (V := V) (G := G)).IsEquivalence instance : (FunctorCategoryEquivalence.inverse (V := V) (G := G)).IsEquivalence := (functorCategoryEquivalence V G).isEquivalence_inverse -/- -porting note: these two lemmas are redundant with the projections created by the @[simps] -attribute above - -theorem functorCategoryEquivalence.functor_def : - (functorCategoryEquivalence V G).functor = FunctorCategoryEquivalence.functor := - rfl - -theorem functorCategoryEquivalence.inverse_def : - (functorCategoryEquivalence V G).inverse = FunctorCategoryEquivalence.inverse := - rfl --/ - end section Forget diff --git a/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean b/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean index 96529915ca92b..432970c912ce8 100644 --- a/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean +++ b/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean @@ -130,7 +130,7 @@ flags `{ z : F.obj (U.obj X) ⟶ R.obj Y // _ }`. -/ set_option linter.unusedVariables false in /-- The homset equivalence which helps show that `R` is a right adjoint. -/ -@[simps!] -- Porting note: Originally `@[simps (config := { rhsMd := semireducible })]` +@[simps!] noncomputable def constructLeftAdjointEquiv [∀ X : B, RegularEpi (adj₁.counit.app X)] (Y : A) (X : B) : (constructLeftAdjointObj _ _ adj₁ adj₂ X ⟶ Y) ≃ (X ⟶ R.obj Y) := calc diff --git a/Mathlib/CategoryTheory/Bicategory/FunctorBicategory/Oplax.lean b/Mathlib/CategoryTheory/Bicategory/FunctorBicategory/Oplax.lean index a0058e9be01b0..ecac5080d5c9e 100644 --- a/Mathlib/CategoryTheory/Bicategory/FunctorBicategory/Oplax.lean +++ b/Mathlib/CategoryTheory/Bicategory/FunctorBicategory/Oplax.lean @@ -47,19 +47,16 @@ def whiskerRight {η θ : F ⟶ G} (Γ : η ⟶ θ) (ι : G ⟶ H) : η ≫ ι simp /-- Associator for the vertical composition of oplax natural transformations. -/ --- Porting note: verified that projections are correct and changed @[simps] to @[simps!] @[simps!] def associator (η : F ⟶ G) (θ : G ⟶ H) (ι : H ⟶ I) : (η ≫ θ) ≫ ι ≅ η ≫ θ ≫ ι := ModificationIso.ofComponents (fun a => α_ (η.app a) (θ.app a) (ι.app a)) (by simp) /-- Left unitor for the vertical composition of oplax natural transformations. -/ --- Porting note: verified that projections are correct and changed @[simps] to @[simps!] @[simps!] def leftUnitor (η : F ⟶ G) : 𝟙 F ≫ η ≅ η := ModificationIso.ofComponents (fun a => λ_ (η.app a)) (by simp) /-- Right unitor for the vertical composition of oplax natural transformations. -/ --- Porting note: verified that projections are correct and changed @[simps] to @[simps!] @[simps!] def rightUnitor (η : F ⟶ G) : η ≫ 𝟙 G ≅ η := ModificationIso.ofComponents (fun a => ρ_ (η.app a)) (by simp) @@ -69,7 +66,6 @@ end OplaxNatTrans variable (B C) /-- A bicategory structure on the oplax functors between bicategories. -/ --- Porting note: verified that projections are correct and changed @[simps] to @[simps!] @[simps!] instance OplaxFunctor.bicategory : Bicategory (OplaxFunctor B C) where whiskerLeft {_ _ _} η _ _ Γ := OplaxNatTrans.whiskerLeft η Γ diff --git a/Mathlib/CategoryTheory/ConnectedComponents.lean b/Mathlib/CategoryTheory/ConnectedComponents.lean index b3333b8445e13..4a1335583cfed 100644 --- a/Mathlib/CategoryTheory/ConnectedComponents.lean +++ b/Mathlib/CategoryTheory/ConnectedComponents.lean @@ -82,7 +82,6 @@ def Component (j : ConnectedComponents J) : Type u₁ := instance {j : ConnectedComponents J} : Category (Component j) := FullSubcategory.category _ --- Porting note: it was originally @[simps (config := { rhsMd := semireducible })] /-- The inclusion functor from a connected component to the whole category. -/ @[simps!] def Component.ι (j : ConnectedComponents J) : Component j ⥤ J := @@ -142,7 +141,6 @@ this abbreviation helps guide typeclass search to get the right category instanc abbrev inclusion (j : ConnectedComponents J) : Component j ⥤ Decomposed J := Sigma.incl _ --- Porting note: it was originally @[simps (config := { rhsMd := semireducible })] /-- The forward direction of the equivalence between the decomposed category and the original. -/ @[simps!] def decomposedTo (J : Type u₁) [Category.{v₁} J] : Decomposed J ⥤ J := @@ -172,7 +170,6 @@ instance : (decomposedTo J).EssSurj where mem_essImage j := ⟨⟨_, j, rfl⟩, instance : (decomposedTo J).IsEquivalence where --- Porting note: it was originally @[simps (config := { rhsMd := semireducible }) Functor] /-- This gives that any category is equivalent to a disjoint union of connected categories. -/ @[simps! functor] def decomposedEquiv : Decomposed J ≌ J := diff --git a/Mathlib/CategoryTheory/Endofunctor/Algebra.lean b/Mathlib/CategoryTheory/Endofunctor/Algebra.lean index 1b53aa148eb3a..fe740cc36ff77 100644 --- a/Mathlib/CategoryTheory/Endofunctor/Algebra.lean +++ b/Mathlib/CategoryTheory/Endofunctor/Algebra.lean @@ -158,13 +158,11 @@ def functorOfNatTrans {F G : C ⥤ C} (α : G ⟶ F) : Algebra F ⥤ Algebra G w map f := { f := f.1 } /-- The identity transformation induces the identity endofunctor on the category of algebras. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def functorOfNatTransId : functorOfNatTrans (𝟙 F) ≅ 𝟭 _ := NatIso.ofComponents fun X => isoMk (Iso.refl _) /-- A composition of natural transformations gives the composition of corresponding functors. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def functorOfNatTransComp {F₀ F₁ F₂ : C ⥤ C} (α : F₀ ⟶ F₁) (β : F₁ ⟶ F₂) : functorOfNatTrans (α ≫ β) ≅ functorOfNatTrans β ⋙ functorOfNatTrans α := @@ -176,7 +174,6 @@ are isomorphic. We define it like this as opposed to using `eq_to_iso` so that the components are nicer to prove lemmas about. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def functorOfNatTransEq {F G : C ⥤ C} {α β : F ⟶ G} (h : α = β) : functorOfNatTrans α ≅ functorOfNatTrans β := @@ -353,13 +350,11 @@ def functorOfNatTrans {F G : C ⥤ C} (α : F ⟶ G) : Coalgebra F ⥤ Coalgebra h := by rw [Category.assoc, ← α.naturality, ← Category.assoc, f.h, Category.assoc] } /-- The identity transformation induces the identity endofunctor on the category of coalgebras. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def functorOfNatTransId : functorOfNatTrans (𝟙 F) ≅ 𝟭 _ := NatIso.ofComponents fun X => isoMk (Iso.refl _) /-- A composition of natural transformations gives the composition of corresponding functors. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def functorOfNatTransComp {F₀ F₁ F₂ : C ⥤ C} (α : F₀ ⟶ F₁) (β : F₁ ⟶ F₂) : functorOfNatTrans (α ≫ β) ≅ functorOfNatTrans α ⋙ functorOfNatTrans β := @@ -370,7 +365,6 @@ them are isomorphic. We define it like this as opposed to using `eq_to_iso` so that the components are nicer to prove lemmas about. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def functorOfNatTransEq {F G : C ⥤ C} {α β : F ⟶ G} (h : α = β) : functorOfNatTrans α ≅ functorOfNatTrans β := diff --git a/Mathlib/CategoryTheory/Limits/Cones.lean b/Mathlib/CategoryTheory/Limits/Cones.lean index cb2edcc07c396..57bf33aa6b3ab 100644 --- a/Mathlib/CategoryTheory/Limits/Cones.lean +++ b/Mathlib/CategoryTheory/Limits/Cones.lean @@ -999,13 +999,11 @@ section variable (G : C ⥤ D) /-- The opposite cocone of the image of a cone is the image of the opposite cocone. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def mapConeOp (t : Cone F) : (mapCone G t).op ≅ mapCocone G.op t.op := Cocones.ext (Iso.refl _) /-- The opposite cone of the image of a cocone is the image of the opposite cone. -/ --- Porting note: removed @[simps (config := { rhsMd := semireducible })] and replaced with @[simps!] def mapCoconeOp {t : Cocone F} : (mapCocone G t).op ≅ mapCone G.op t.op := Cones.ext (Iso.refl _) diff --git a/Mathlib/CategoryTheory/Limits/HasLimits.lean b/Mathlib/CategoryTheory/Limits/HasLimits.lean index ec913e2a6944d..8ebca957d879b 100644 --- a/Mathlib/CategoryTheory/Limits/HasLimits.lean +++ b/Mathlib/CategoryTheory/Limits/HasLimits.lean @@ -985,7 +985,7 @@ section -- attribute [local simp] colimMap -- Porting note: errors out colim.map_id and map_comp now /-- `colimit F` is functorial in `F`, when `C` has all colimits of shape `J`. -/ -@[simps] -- Porting note: simps on all fields now +@[simps] def colim : (J ⥤ C) ⥤ C where obj F := colimit F map α := colimMap α diff --git a/Mathlib/CategoryTheory/Limits/Opposites.lean b/Mathlib/CategoryTheory/Limits/Opposites.lean index 7c040f35246ea..9cdb08b55dd77 100644 --- a/Mathlib/CategoryTheory/Limits/Opposites.lean +++ b/Mathlib/CategoryTheory/Limits/Opposites.lean @@ -871,7 +871,6 @@ def opSpan {X Y Z : C} (f : X ⟶ Y) (g : X ⟶ Z) : namespace PushoutCocone --- Porting note: it was originally @[simps (config := lemmasOnly)] /-- The obvious map `PushoutCocone f g → PullbackCone f.unop g.unop` -/ @[simps!] def unop {X Y Z : Cᵒᵖ} {f : X ⟶ Y} {g : X ⟶ Z} (c : PushoutCocone f g) : @@ -886,7 +885,6 @@ theorem unop_fst {X Y Z : Cᵒᵖ} {f : X ⟶ Y} {g : X ⟶ Z} (c : PushoutCocon theorem unop_snd {X Y Z : Cᵒᵖ} {f : X ⟶ Y} {g : X ⟶ Z} (c : PushoutCocone f g) : c.unop.snd = c.inr.unop := by simp --- Porting note: it was originally @[simps (config := lemmasOnly)] /-- The obvious map `PushoutCocone f.op g.op → PullbackCone f g` -/ @[simps!] def op {X Y Z : C} {f : X ⟶ Y} {g : X ⟶ Z} (c : PushoutCocone f g) : PullbackCone f.op g.op := @@ -903,7 +901,6 @@ end PushoutCocone namespace PullbackCone --- Porting note: it was originally @[simps (config := lemmasOnly)] /-- The obvious map `PullbackCone f g → PushoutCocone f.unop g.unop` -/ @[simps!] def unop {X Y Z : Cᵒᵖ} {f : X ⟶ Z} {g : Y ⟶ Z} (c : PullbackCone f g) : diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean index a7e173c76621e..5706484d58e29 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean @@ -208,9 +208,6 @@ theorem binaryProductIso_inv_comp_snd (X Y : Type u) : (binaryProductIso X Y).inv ≫ Limits.prod.snd = _root_.Prod.snd := limit.isoLimitCone_inv_π (binaryProductLimitCone X Y) ⟨WalkingPair.right⟩ --- Porting note: it was originally @[simps (config := { typeMd := reducible })] --- We add the option `type_md` to tell `@[simps]` to not treat homomorphisms `X ⟶ Y` in `Type*` as --- a function type /-- The functor which sends `X, Y` to the product type `X × Y`. -/ @[simps] def binaryProductFunctor : Type u ⥤ Type u ⥤ Type u where diff --git a/Mathlib/CategoryTheory/Monoidal/Category.lean b/Mathlib/CategoryTheory/Monoidal/Category.lean index a0d928049644b..f91baa59cfa43 100644 --- a/Mathlib/CategoryTheory/Monoidal/Category.lean +++ b/Mathlib/CategoryTheory/Monoidal/Category.lean @@ -818,19 +818,16 @@ abbrev tensorUnitRight : C ⥤ C := tensorRight (𝟙_ C) -- We can express the associator and the unitors, given componentwise above, -- as natural isomorphisms. --- Porting Note: Had to add a `simps!` because Lean was complaining this wasn't a constructor app. /-- The associator as a natural isomorphism. -/ @[simps!] def associatorNatIso : leftAssocTensor C ≅ rightAssocTensor C := NatIso.ofComponents (fun _ => MonoidalCategory.associator _ _ _) --- Porting Note: same as above /-- The left unitor as a natural isomorphism. -/ @[simps!] def leftUnitorNatIso : tensorUnitLeft C ≅ 𝟭 C := NatIso.ofComponents MonoidalCategory.leftUnitor --- Porting Note: same as above /-- The right unitor as a natural isomorphism. -/ @[simps!] def rightUnitorNatIso : tensorUnitRight C ≅ 𝟭 C := diff --git a/Mathlib/CategoryTheory/Monoidal/CommMon_.lean b/Mathlib/CategoryTheory/Monoidal/CommMon_.lean index 06cb8f63a5ee5..e9cbde0fc470c 100644 --- a/Mathlib/CategoryTheory/Monoidal/CommMon_.lean +++ b/Mathlib/CategoryTheory/Monoidal/CommMon_.lean @@ -137,7 +137,6 @@ def mapCommMon (F : C ⥤ D) [F.LaxBraided] : CommMon_ C ⥤ CommMon_ D where variable (C) (D) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/10688): added @[simps] to ease automation /-- `mapCommMon` is functorial in the lax braided functor. -/ @[simps] def mapCommMonFunctor : LaxBraidedFunctor C D ⥤ CommMon_ C ⥤ CommMon_ D where diff --git a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean index 4a0fd32e2e836..0c7bc7c4e3cc3 100644 --- a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean +++ b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean @@ -52,7 +52,6 @@ variable {C D E : Type*} [Category C] [Category D] [Category E] theorem map_add {X Y : C} {f g : X ⟶ Y} : F.map (f + g) = F.map f + F.map g := Functor.Additive.map_add --- Porting note: it was originally @[simps (config := .asFn)] /-- `F.mapAddHom` is an additive homomorphism whose underlying function is `F.map`. -/ @[simps!] def mapAddHom {X Y : C} : (X ⟶ Y) →+ (F.obj X ⟶ F.obj Y) := diff --git a/Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean b/Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean index a0ebf9abfe400..c0b0a9bb9f508 100644 --- a/Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean +++ b/Mathlib/FieldTheory/IntermediateField/Adjoin/Defs.lean @@ -241,8 +241,6 @@ This is the intermediate field version of `Subalgebra.topEquiv`. -/ def topEquiv : (⊤ : IntermediateField F E) ≃ₐ[F] E := Subalgebra.topEquiv --- Porting note: this theorem is now generated by the `@[simps!]` above. - section RestrictScalars @[simp] diff --git a/Mathlib/GroupTheory/FreeAbelianGroup.lean b/Mathlib/GroupTheory/FreeAbelianGroup.lean index 41d322ed1f481..030548d59fea5 100644 --- a/Mathlib/GroupTheory/FreeAbelianGroup.lean +++ b/Mathlib/GroupTheory/FreeAbelianGroup.lean @@ -179,7 +179,7 @@ theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α /-- If `g : FreeAbelianGroup X` and `A` is an abelian group then `liftAddGroupHom g` is the additive group homomorphism sending a function `X → A` to the term of type `A` corresponding to the evaluation of the induced map `FreeAbelianGroup X → A` at `g`. -/ -@[simps!] -- Porting note: Changed `simps` to `simps!`. +@[simps!] def liftAddGroupHom {α} (β) [AddCommGroup β] (a : FreeAbelianGroup α) : (α → β) →+ β := AddMonoidHom.mk' (fun f ↦ lift f a) (lift.add' a) diff --git a/Mathlib/LinearAlgebra/Finsupp/Defs.lean b/Mathlib/LinearAlgebra/Finsupp/Defs.lean index f75eb1bab340d..4b42fe2e28994 100644 --- a/Mathlib/LinearAlgebra/Finsupp/Defs.lean +++ b/Mathlib/LinearAlgebra/Finsupp/Defs.lean @@ -167,17 +167,13 @@ def lcomapDomain (f : α → β) (hf : Function.Injective f) : (β →₀ M) → end LComapDomain /-- `Finsupp.mapRange` as a `LinearMap`. -/ +@[simps apply] def mapRange.linearMap (f : M →ₗ[R] N) : (α →₀ M) →ₗ[R] α →₀ N := { mapRange.addMonoidHom f.toAddMonoidHom with toFun := (mapRange f f.map_zero : (α →₀ M) → α →₀ N) -- Porting note: `hf` should be specified. map_smul' := fun c v => mapRange_smul (hf := f.map_zero) c v (f.map_smul c) } --- Porting note: This was generated by `simps!`. -@[simp] -theorem mapRange.linearMap_apply (f : M →ₗ[R] N) (g : α →₀ M) : - mapRange.linearMap f g = mapRange f f.map_zero g := rfl - @[simp] theorem mapRange.linearMap_id : mapRange.linearMap LinearMap.id = (LinearMap.id : (α →₀ M) →ₗ[R] _) := @@ -196,17 +192,13 @@ theorem mapRange.linearMap_toAddMonoidHom (f : M →ₗ[R] N) : AddMonoidHom.ext fun _ => rfl /-- `Finsupp.mapRange` as a `LinearEquiv`. -/ +@[simps apply] def mapRange.linearEquiv (e : M ≃ₗ[R] N) : (α →₀ M) ≃ₗ[R] α →₀ N := { mapRange.linearMap e.toLinearMap, mapRange.addEquiv e.toAddEquiv with toFun := mapRange e e.map_zero invFun := mapRange e.symm e.symm.map_zero } --- Porting note: This was generated by `simps`. -@[simp] -theorem mapRange.linearEquiv_apply (e : M ≃ₗ[R] N) (g : α →₀ M) : - mapRange.linearEquiv e g = mapRange.linearMap e.toLinearMap g := rfl - @[simp] theorem mapRange.linearEquiv_refl : mapRange.linearEquiv (LinearEquiv.refl R M) = LinearEquiv.refl R (α →₀ M) := diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index 227f360fbe06f..a63088b6181d5 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -274,7 +274,6 @@ def ofSubsingleton [Subsingleton ι] (i : ι) : variable (M₁) {M₂} /-- The constant map is multilinear when `ι` is empty. -/ --- Porting note: Removed [simps] & added simpNF-approved version of the generated lemma manually. @[simps (config := .asFn)] def constOfIsEmpty [IsEmpty ι] (m : M₂) : MultilinearMap R M₁ M₂ where toFun := Function.const _ m diff --git a/Mathlib/ModelTheory/LanguageMap.lean b/Mathlib/ModelTheory/LanguageMap.lean index 6f637d83be0fc..68b4dec5d3686 100644 --- a/Mathlib/ModelTheory/LanguageMap.lean +++ b/Mathlib/ModelTheory/LanguageMap.lean @@ -389,7 +389,7 @@ theorem card_withConstants : rw [withConstants, card_sum, card_constantsOn] /-- The language map adding constants. -/ -@[simps!] -- Porting note: add `!` to `simps` +@[simps!] def lhomWithConstants : L →ᴸ L[[α]] := LHom.sumInl diff --git a/Mathlib/ModelTheory/Syntax.lean b/Mathlib/ModelTheory/Syntax.lean index ca64daf425250..b33bb96a524e6 100644 --- a/Mathlib/ModelTheory/Syntax.lean +++ b/Mathlib/ModelTheory/Syntax.lean @@ -703,7 +703,7 @@ theorem onFormula_symm (φ : L ≃ᴸ L') : rfl /-- Maps a sentence's symbols along a language equivalence. -/ -@[simps!] -- Porting note: add `!` to `simps` +@[simps!] def onSentence (φ : L ≃ᴸ L') : L.Sentence ≃ L'.Sentence := φ.onFormula diff --git a/Mathlib/RingTheory/AdjoinRoot.lean b/Mathlib/RingTheory/AdjoinRoot.lean index 36a2d4a72e50f..cddb3ce631d74 100644 --- a/Mathlib/RingTheory/AdjoinRoot.lean +++ b/Mathlib/RingTheory/AdjoinRoot.lean @@ -519,7 +519,7 @@ def powerBasisAux (hf : f ≠ 0) : Basis (Fin f.natDegree) K (AdjoinRoot f) := b /-- The power basis `1, root f, ..., root f ^ (d - 1)` for `AdjoinRoot f`, where `f` is an irreducible polynomial over a field of degree `d`. -/ -@[simps!] -- Porting note: was `[simps]` +@[simps!] def powerBasis (hf : f ≠ 0) : PowerBasis K (AdjoinRoot f) where gen := root f dim := f.natDegree diff --git a/Mathlib/RingTheory/PolynomialAlgebra.lean b/Mathlib/RingTheory/PolynomialAlgebra.lean index 29d0e3114f3f3..12ebc739f51b9 100644 --- a/Mathlib/RingTheory/PolynomialAlgebra.lean +++ b/Mathlib/RingTheory/PolynomialAlgebra.lean @@ -46,7 +46,6 @@ namespace PolyEquivTensor The function underlying `A ⊗[R] R[X] →ₐ[R] A[X]`, as a bilinear function of two arguments. -/ --- Porting note: was `@[simps apply_apply]` @[simps! apply_apply] def toFunBilinear : A →ₗ[A] R[X] →ₗ[R] A[X] := LinearMap.toSpanSingleton A _ (aeval (Polynomial.X : A[X])).toLinearMap diff --git a/Mathlib/Topology/Algebra/Module/StrongTopology.lean b/Mathlib/Topology/Algebra/Module/StrongTopology.lean index 543fab13c9fbb..1a77159696d88 100644 --- a/Mathlib/Topology/Algebra/Module/StrongTopology.lean +++ b/Mathlib/Topology/Algebra/Module/StrongTopology.lean @@ -610,7 +610,7 @@ variable {𝕜 : Type*} {𝕜₂ : Type*} {𝕜₃ : Type*} {𝕜₄ : Type*} {E /-- A pair of continuous (semi)linear equivalences generates a (semi)linear equivalence between the spaces of continuous (semi)linear maps. -/ -@[simps] +@[simps apply symm_apply toLinearEquiv_apply toLinearEquiv_symm_apply] def arrowCongrSL (e₁₂ : E ≃SL[σ₁₂] F) (e₄₃ : H ≃SL[σ₄₃] G) : (E →SL[σ₁₄] H) ≃SL[σ₄₃] F →SL[σ₂₃] G := { e₁₂.arrowCongrEquiv e₄₃ with @@ -625,20 +625,6 @@ def arrowCongrSL (e₁₂ : E ≃SL[σ₁₂] F) (e₄₃ : H ≃SL[σ₄₃] G) continuous_invFun := ((precomp H e₁₂.toContinuousLinearMap).comp (postcomp F e₄₃.symm.toContinuousLinearMap)).continuous } --- Porting note: the following two lemmas were autogenerated by `simps` in Lean3, but this is --- no longer the case. The first one can already be proven by `simp`, but the second can't. - -theorem arrowCongrSL_toLinearEquiv_apply (e₁₂ : E ≃SL[σ₁₂] F) (e₄₃ : H ≃SL[σ₄₃] G) - (L : E →SL[σ₁₄] H) : (e₁₂.arrowCongrSL e₄₃).toLinearEquiv L = - (e₄₃ : H →SL[σ₄₃] G).comp (L.comp (e₁₂.symm : F →SL[σ₂₁] E)) := - rfl - -@[simp] -theorem arrowCongrSL_toLinearEquiv_symm_apply (e₁₂ : E ≃SL[σ₁₂] F) (e₄₃ : H ≃SL[σ₄₃] G) - (L : F →SL[σ₂₃] G) : (e₁₂.arrowCongrSL e₄₃).toLinearEquiv.symm L = - (e₄₃.symm : G →SL[σ₃₄] H).comp (L.comp (e₁₂ : E →SL[σ₁₂] F)) := - rfl - end Semilinear section Linear diff --git a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean index d64c5cd7bdaa8..993d4a12a29a1 100644 --- a/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean +++ b/Mathlib/Topology/ContinuousMap/Bounded/Basic.lean @@ -262,7 +262,7 @@ alias embedding_coeFn := isEmbedding_coeFn variable (α) /-- Constant as a continuous bounded function. -/ -@[simps! (config := .asFn)] -- Porting note: Changed `simps` to `simps!` +@[simps! (config := .asFn)] def const (b : β) : α →ᵇ β := ⟨ContinuousMap.const α b, 0, by simp⟩ diff --git a/Mathlib/Topology/ContinuousMap/Compact.lean b/Mathlib/Topology/ContinuousMap/Compact.lean index 1e69d46a45e39..0c15211586699 100644 --- a/Mathlib/Topology/ContinuousMap/Compact.lean +++ b/Mathlib/Topology/ContinuousMap/Compact.lean @@ -73,23 +73,10 @@ alias uniformEmbedding_equivBoundedOfCompact := isUniformEmbedding_equivBoundedO /-- When `α` is compact, the bounded continuous maps `α →ᵇ 𝕜` are additively equivalent to `C(α, 𝕜)`. -/ --- Porting note: the following `simps` received a "maximum recursion depth" error --- @[simps! (config := .asFn) apply symm_apply] +@[simps! (config := .asFn) apply symm_apply] def addEquivBoundedOfCompact [AddMonoid β] [LipschitzAdd β] : C(α, β) ≃+ (α →ᵇ β) := ({ toContinuousMapAddHom α β, (equivBoundedOfCompact α β).symm with } : (α →ᵇ β) ≃+ C(α, β)).symm --- Porting note: added this `simp` lemma manually because of the `simps` error above -@[simp] -theorem addEquivBoundedOfCompact_symm_apply [AddMonoid β] [LipschitzAdd β] : - ⇑((addEquivBoundedOfCompact α β).symm) = toContinuousMapAddHom α β := - rfl - --- Porting note: added this `simp` lemma manually because of the `simps` error above -@[simp] -theorem addEquivBoundedOfCompact_apply [AddMonoid β] [LipschitzAdd β] : - ⇑(addEquivBoundedOfCompact α β) = mkOfCompact := - rfl - instance instPseudoMetricSpace : PseudoMetricSpace C(α, β) := (isUniformEmbedding_equivBoundedOfCompact α β).comapPseudoMetricSpace _ diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index 202d87d21c03f..a6da5bc6bc39a 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -1056,7 +1056,7 @@ def homeomorphOfImageSubsetSource {s : Set X} {t : Set Y} (hs : s ⊆ e.source) continuous_invFun := (e.continuousOn_symm.mono h₂).restrict_mapsTo h₃ } /-- A partial homeomorphism defines a homeomorphism between its source and target. -/ -@[simps!] -- Porting note: new `simps` +@[simps!] def toHomeomorphSourceTarget : e.source ≃ₜ e.target := e.homeomorphOfImageSubsetSource subset_rfl e.image_source_eq_target From 264ed5bc012ddbf38987412d0f9d604bab08f3dd Mon Sep 17 00:00:00 2001 From: sven-manthe Date: Tue, 14 Jan 2025 02:01:23 +0000 Subject: [PATCH 216/681] feat: add stream' lemmas (#19546) The orders of summands in some lemmas are changed and simp annotations are added to make the API closer to the one for lists. Co-authored-by: sven-manthe <147848313+sven-manthe@users.noreply.github.com> --- Mathlib/Combinatorics/Hindman.lean | 10 +-- Mathlib/Data/Stream/Init.lean | 106 ++++++++++++++++++++++++----- 2 files changed, 93 insertions(+), 23 deletions(-) diff --git a/Mathlib/Combinatorics/Hindman.lean b/Mathlib/Combinatorics/Hindman.lean index bc139a6efd3b9..59d2bb754770f 100644 --- a/Mathlib/Combinatorics/Hindman.lean +++ b/Mathlib/Combinatorics/Hindman.lean @@ -128,7 +128,7 @@ theorem exists_idempotent_ultrafilter_le_FP {M} [Semigroup M] (a : Stream' M) : · apply IsCompact.nonempty_iInter_of_sequence_nonempty_isCompact_isClosed · intro n U hU filter_upwards [hU] - rw [add_comm, ← Stream'.drop_drop, ← Stream'.tail_eq_drop] + rw [← Stream'.drop_drop, ← Stream'.tail_eq_drop] exact FP.tail _ · intro n exact ⟨pure _, mem_pure.mpr <| FP.head _⟩ @@ -144,7 +144,7 @@ theorem exists_idempotent_ultrafilter_le_FP {M} [Semigroup M] (a : Stream' M) : obtain ⟨n', hn⟩ := FP.mul hm filter_upwards [hV (n' + n)] with m' hm' apply hn - simpa only [Stream'.drop_drop] using hm' + simpa only [Stream'.drop_drop, add_comm] using hm' @[to_additive exists_FS_of_large] theorem exists_FP_of_large {M} [Semigroup M] (U : Ultrafilter M) (U_idem : U * U = U) (s₀ : Set M) @@ -208,7 +208,7 @@ theorem FP_drop_subset_FP {M} [Semigroup M] (a : Stream' M) (n : ℕ) : FP (a.dr induction n with | zero => rfl | succ n ih => - rw [Nat.add_comm, ← Stream'.drop_drop] + rw [← Stream'.drop_drop] exact _root_.trans (FP.tail _) ih @[to_additive] @@ -229,7 +229,7 @@ theorem FP.mul_two {M} [Semigroup M] (a : Stream' M) (i j : ℕ) (ij : i < j) : have := FP.singleton (a.drop i).tail d rw [Stream'.tail_eq_drop, Stream'.get_drop, Stream'.get_drop] at this convert this - rw [hd, add_comm, Nat.succ_add, Nat.add_succ] + omega @[to_additive] theorem FP.finset_prod {M} [CommMonoid M] (a : Stream' M) (s : Finset ℕ) (hs : s.Nonempty) : @@ -246,7 +246,7 @@ theorem FP.finset_prod {M} [CommMonoid M] (a : Stream' M) (s : Finset ℕ) (hs : have : s.min' hs + 1 ≤ (s.erase (s.min' hs)).min' h := Nat.succ_le_of_lt (Finset.min'_lt_of_mem_erase_min' _ _ <| Finset.min'_mem _ _) cases' Nat.exists_eq_add_of_le this with d hd - rw [hd, add_comm, ← Stream'.drop_drop] + rw [hd, ← Stream'.drop_drop, add_comm] apply FP_drop_subset_FP end Hindman diff --git a/Mathlib/Data/Stream/Init.lean b/Mathlib/Data/Stream/Init.lean index b893cc61acf48..c183450182074 100644 --- a/Mathlib/Data/Stream/Init.lean +++ b/Mathlib/Data/Stream/Init.lean @@ -20,13 +20,17 @@ namespace Stream' universe u v w variable {α : Type u} {β : Type v} {δ : Type w} +variable (m n : ℕ) (x y : List α) (a b : Stream' α) instance [Inhabited α] : Inhabited (Stream' α) := ⟨Stream'.const default⟩ -protected theorem eta (s : Stream' α) : (head s::tail s) = s := +@[simp] protected theorem eta (s : Stream' α) : head s :: tail s = s := funext fun i => by cases i <;> rfl +/-- Alias for `Stream'.eta` to match `List` API. -/ +alias cons_head_tail := Stream'.eta + @[ext] protected theorem ext {s₁ s₂ : Stream' α} : (∀ n, get s₁ n = get s₂ n) → s₁ = s₂ := fun h => funext h @@ -44,22 +48,23 @@ theorem tail_cons (a : α) (s : Stream' α) : tail (a::s) = s := rfl @[simp] -theorem get_drop (n m : ℕ) (s : Stream' α) : get (drop m s) n = get s (n + m) := +theorem get_drop (n m : ℕ) (s : Stream' α) : get (drop m s) n = get s (m + n) := by + rw [Nat.add_comm] rfl theorem tail_eq_drop (s : Stream' α) : tail s = drop 1 s := rfl @[simp] -theorem drop_drop (n m : ℕ) (s : Stream' α) : drop n (drop m s) = drop (n + m) s := by +theorem drop_drop (n m : ℕ) (s : Stream' α) : drop n (drop m s) = drop (m + n) s := by ext; simp [Nat.add_assoc] @[simp] theorem get_tail {n : ℕ} {s : Stream' α} : s.tail.get n = s.get (n + 1) := rfl -@[simp] theorem tail_drop' {i : ℕ} {s : Stream' α} : tail (drop i s) = s.drop (i+1) := by +@[simp] theorem tail_drop' {i : ℕ} {s : Stream' α} : tail (drop i s) = s.drop (i + 1) := by ext; simp [Nat.add_comm, Nat.add_assoc, Nat.add_left_comm] -@[simp] theorem drop_tail' {i : ℕ} {s : Stream' α} : drop i (tail s) = s.drop (i+1) := rfl +@[simp] theorem drop_tail' {i : ℕ} {s : Stream' α} : drop i (tail s) = s.drop (i + 1) := rfl theorem tail_drop (n : ℕ) (s : Stream' α) : tail (drop n s) = drop n (tail s) := by simp @@ -67,9 +72,14 @@ theorem get_succ (n : ℕ) (s : Stream' α) : get s (succ n) = get (tail s) n := rfl @[simp] -theorem get_succ_cons (n : ℕ) (s : Stream' α) (x : α) : get (x::s) n.succ = get s n := +theorem get_succ_cons (n : ℕ) (s : Stream' α) (x : α) : get (x :: s) n.succ = get s n := rfl +@[simp] lemma get_cons_append_zero {a : α} {x : List α} {s : Stream' α} : + (a :: x ++ₛ s).get 0 = a := rfl + +@[simp] lemma append_eq_cons {a : α} {as : Stream' α} : [a] ++ₛ as = a :: as := by rfl + @[simp] theorem drop_zero {s : Stream' α} : s.drop 0 = s := rfl theorem drop_succ (n : ℕ) (s : Stream' α) : drop (succ n) s = drop n (tail s) := @@ -251,15 +261,15 @@ def IsBisimulation := ∀ ⦃s₁ s₂⦄, s₁ ~ s₂ → head s₁ = head s₂ ∧ tail s₁ ~ tail s₂ -theorem get_of_bisim (bisim : IsBisimulation R) : - ∀ {s₁ s₂} (n), s₁ ~ s₂ → get s₁ n = get s₂ n ∧ drop (n + 1) s₁ ~ drop (n + 1) s₂ - | _, _, 0, h => bisim h - | _, _, n + 1, h => +theorem get_of_bisim (bisim : IsBisimulation R) {s₁ s₂} : + ∀ n, s₁ ~ s₂ → get s₁ n = get s₂ n ∧ drop (n + 1) s₁ ~ drop (n + 1) s₂ + | 0, h => bisim h + | n + 1, h => match bisim h with | ⟨_, trel⟩ => get_of_bisim bisim n trel -- If two streams are bisimilar, then they are equal -theorem eq_of_bisim (bisim : IsBisimulation R) : ∀ {s₁ s₂}, s₁ ~ s₂ → s₁ = s₂ := fun r => +theorem eq_of_bisim (bisim : IsBisimulation R) {s₁ s₂} : s₁ ~ s₂ → s₁ = s₂ := fun r => Stream'.ext fun n => And.left (get_of_bisim R bisim n r) end Bisim @@ -311,7 +321,7 @@ section Corec theorem corec_def (f : α → β) (g : α → α) (a : α) : corec f g a = map f (iterate g a) := rfl -theorem corec_eq (f : α → β) (g : α → α) (a : α) : corec f g a = f a::corec f g (g a) := by +theorem corec_eq (f : α → β) (g : α → α) (a : α) : corec f g a = f a :: corec f g (g a) := by rw [corec_def, map_eq, head_iterate, tail_iterate]; rfl theorem corec_id_id_eq_const (a : α) : corec id id a = const a := by @@ -324,12 +334,12 @@ end Corec section Corec' -theorem corec'_eq (f : α → β × α) (a : α) : corec' f a = (f a).1::corec' f (f a).2 := +theorem corec'_eq (f : α → β × α) (a : α) : corec' f a = (f a).1 :: corec' f (f a).2 := corec_eq _ _ _ end Corec' -theorem unfolds_eq (g : α → β) (f : α → α) (a : α) : unfolds g f a = g a::unfolds g f (f a) := by +theorem unfolds_eq (g : α → β) (f : α → α) (a : α) : unfolds g f a = g a :: unfolds g f (f a) := by unfold unfolds; rw [corec_eq] theorem get_unfolds_head_tail : ∀ (n : ℕ) (s : Stream' α), @@ -429,19 +439,42 @@ theorem mem_of_mem_even (a : α) (s : Stream' α) : a ∈ even s → a ∈ s := theorem mem_of_mem_odd (a : α) (s : Stream' α) : a ∈ odd s → a ∈ s := fun ⟨n, h⟩ => Exists.intro (2 * n + 1) (by rw [h, get_odd]) -theorem nil_append_stream (s : Stream' α) : appendStream' [] s = s := +@[simp] theorem nil_append_stream (s : Stream' α) : appendStream' [] s = s := rfl theorem cons_append_stream (a : α) (l : List α) (s : Stream' α) : appendStream' (a::l) s = a::appendStream' l s := rfl -theorem append_append_stream : ∀ (l₁ l₂ : List α) (s : Stream' α), +@[simp] theorem append_append_stream : ∀ (l₁ l₂ : List α) (s : Stream' α), l₁ ++ l₂ ++ₛ s = l₁ ++ₛ (l₂ ++ₛ s) | [], _, _ => rfl | List.cons a l₁, l₂, s => by rw [List.cons_append, cons_append_stream, cons_append_stream, append_append_stream l₁] +lemma get_append_left (h : n < x.length) : (x ++ₛ a).get n = x[n] := by + induction' x with b x ih generalizing n + · simp at h + · rcases n with (_ | n) + · simp + · simp [ih n (by simpa using h), cons_append_stream] + +@[simp] lemma get_append_right : (x ++ₛ a).get (x.length + n) = a.get n := by + induction' x <;> simp [Nat.succ_add, *, cons_append_stream] + +@[simp] lemma get_append_length : (x ++ₛ a).get x.length = a.get 0 := get_append_right 0 x a + +lemma append_right_injective (h : x ++ₛ a = x ++ₛ b) : a = b := by + ext n; replace h := congr_arg (fun a ↦ a.get (x.length + n)) h; simpa using h + +@[simp] lemma append_right_inj : x ++ₛ a = x ++ₛ b ↔ a = b := + ⟨append_right_injective x a b, by simp (config := {contextual := true})⟩ + +lemma append_left_injective (h : x ++ₛ a = y ++ₛ b) (hl : x.length = y.length) : x = y := by + apply List.ext_getElem hl + intros + rw [← get_append_left, ← get_append_left, h] + theorem map_append_stream (f : α → β) : ∀ (l : List α) (s : Stream' α), map f (l ++ₛ s) = List.map f l ++ₛ map f s | [], _ => rfl @@ -454,7 +487,7 @@ theorem drop_append_stream : ∀ (l : List α) (s : Stream' α), drop l.length ( rw [List.length_cons, drop_succ, cons_append_stream, tail_cons, drop_append_stream l s] theorem append_stream_head_tail (s : Stream' α) : [head s] ++ₛ tail s = s := by - rw [cons_append_stream, nil_append_stream, Stream'.eta] + simp theorem mem_append_stream_right : ∀ {a : α} (l : List α) {s : Stream' α}, a ∈ s → a ∈ l ++ₛ s | _, [], _, h => h @@ -495,7 +528,7 @@ theorem take_take {s : Stream' α} : ∀ {m n}, (s.take n).take m = s.take (min | m, 0 => by rw [Nat.zero_min, take_zero, List.take_nil] | m+1, n+1 => by rw [take_succ, List.take_succ_cons, Nat.succ_min_succ, take_succ, take_take] -@[simp] theorem concat_take_get {n : ℕ} {s : Stream' α} : s.take n ++ [s.get n] = s.take (n+1) := +@[simp] theorem concat_take_get {n : ℕ} {s : Stream' α} : s.take n ++ [s.get n] = s.take (n + 1) := (take_succ' n).symm theorem get?_take {s : Stream' α} : ∀ {k n}, k < n → (s.take n).get? k = s.get k @@ -522,6 +555,43 @@ theorem append_take_drop : ∀ (n : ℕ) (s : Stream' α), · intro s rw [take_succ, drop_succ, cons_append_stream, ih (tail s), Stream'.eta] +lemma append_take : x ++ (a.take n) = (x ++ₛ a).take (x.length + n) := by + induction' x <;> simp [take, Nat.add_comm, cons_append_stream, *] + +@[simp] lemma take_get (h : m < (a.take n).length) : (a.take n)[m] = a.get m := by + nth_rw 2 [← append_take_drop n a]; rw [get_append_left] + +theorem take_append_of_le_length (h : n ≤ x.length) : + (x ++ₛ a).take n = x.take n := by + apply List.ext_getElem (by simp [h]) + intro _ _ _; rw [List.getElem_take, take_get, get_append_left] + +lemma take_add : a.take (m + n) = a.take m ++ (a.drop m).take n := by + apply append_left_injective _ _ (a.drop (m + n)) ((a.drop m).drop n) <;> + simp [- drop_drop] + +@[gcongr] lemma take_prefix_take_left (h : m ≤ n) : a.take m <+: a.take n := by + rw [(by simp [h] : a.take m = (a.take n).take m)] + apply List.take_prefix + +@[simp] lemma take_prefix : a.take m <+: a.take n ↔ m ≤ n := + ⟨fun h ↦ by simpa using h.length_le, take_prefix_take_left m n a⟩ + +lemma map_take (f : α → β) : (a.take n).map f = (a.map f).take n := by + apply List.ext_getElem <;> simp + +lemma take_drop : (a.drop m).take n = (a.take (m + n)).drop m := by + apply List.ext_getElem <;> simp + +lemma drop_append_of_le_length (h : n ≤ x.length) : + (x ++ₛ a).drop n = x.drop n ++ₛ a := by + obtain ⟨m, hm⟩ := Nat.exists_eq_add_of_le h + ext k; rcases lt_or_ge k m with _ | hk + · rw [get_drop, get_append_left, get_append_left, List.getElem_drop]; simpa [hm] + · obtain ⟨p, rfl⟩ := Nat.exists_eq_add_of_le hk + have hm' : m = (x.drop n).length := by simp [hm] + simp_rw [get_drop, ← Nat.add_assoc, ← hm, get_append_right, hm', get_append_right] + -- Take theorem reduces a proof of equality of infinite streams to an -- induction over all their finite approximations. theorem take_theorem (s₁ s₂ : Stream' α) : (∀ n : ℕ, take n s₁ = take n s₂) → s₁ = s₂ := by From 26a7d97690cb8c3b073403c637b8ed3d8ac18dab Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 14 Jan 2025 02:01:24 +0000 Subject: [PATCH 217/681] doc: explain List.Vector vs Vector (#20693) --- Mathlib/Data/Vector/Defs.lean | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Mathlib/Data/Vector/Defs.lean b/Mathlib/Data/Vector/Defs.lean index db88601c6603b..342677efda76a 100644 --- a/Mathlib/Data/Vector/Defs.lean +++ b/Mathlib/Data/Vector/Defs.lean @@ -8,12 +8,25 @@ import Mathlib.Tactic.Common /-! The type `List.Vector` represents lists with fixed length. + +TODO: The API of `List.Vector` is quite incomplete relative to `Vector`, +and in particular does not use `x[i]` (that is `GetElem` notation) as the preferred accessor. +Any combination of reducing the use of `List.Vector` in Mathlib, or modernising its API, +would be welcome. -/ assert_not_exists Monoid universe u v w -/-- `Vector α n` is the type of lists of length `n` with elements of type `α`. -/ +/-- +`List.Vector α n` is the type of lists of length `n` with elements of type `α`. + +Note that there is also `Vector α n` in the root namespace, +which is the type of *arrays* of length `n` with elements of type `α`. + +Typically, if you are doing programming or verification, you will primarily use `Vector α n`, +and if you are doing mathematics, you may want to use `List.Vector α n` instead. +-/ def List.Vector (α : Type u) (n : ℕ) := { l : List α // l.length = n } From 266b0529b13922932b023f2a28a8dbc101455aa3 Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Tue, 14 Jan 2025 02:38:56 +0000 Subject: [PATCH 218/681] refactor: split `Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances` in a principled way (#20647) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this PR, there were three files in which one could find instances of continuous functional calculi: `Analysis.CStarAlgebra.ContinuousFunctionalCalculus.{Instances, Isometric, Unital}`, which contained, respectively, 1. All generic instances of the CFC over `ℂ`, `ℝ`, `ℝ≥0` for unital and non-unital algebras 2. All the instances of the isometric CFC. 3. The non-unital CFC for unital algebras. Note that importing `Instances` was therefore the general way to obtain a CFC on a `CStarAlgebra`. In this PR, the last one stays where it is, but there is a bit of shuffling for the others which we now explain. Here the problem with the above distribution of instances: if you are working on a generic CFC file (e.g., defining `CFC.abs a := CFC.sqrt (star a * a)`, then you want to work in maximum generality. But to apply `CFC.sqrt` you need an instance of the `ℝ≥0` functional calculus. The *correct* (i.e., well-behaved) way to do this is to assume that you have an `ℝ`-algebra (*not* an `ℝ≥0`-algebra, because those are ill-behaved) with the appropriate hypotheses. However, in order to get that instance, prior to this PR you would need to import `Instances`, which would pull in `CStarAlgebra` theory not relevant to the development of your file (and potentially, not even relevant to certain files downstream of the one on which you are working). The solution is to separate the instances which are *inferred from existing instances* (i.e., for obtaining `ℝ` from `ℂ`, or `ℝ≥0` from `ℝ`) from the *base level instances* (i.e., the ones for `ℂ` which require `CStarAlgebra`). The former instances are left in either `Instances` or `Isometric` as the case may be, and the latter are moved into `Basic`. This means that `Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic` is now the entry point for getting all the relevant CFC instances for a `CStarAlgebra`. The rest of the files in this folder are for the more generic development of the CFC (with the exception of `Order`, which should likely be moved outside of this subfolder at some point. This should explain the large changes in the import hierarchy. The purpose of this refactor is to allow for more principled development of generic CFC functions, without importing more than necessary. --- .../CStarAlgebra/ApproximateUnit.lean | 1 - .../ContinuousFunctionalCalculus/Basic.lean | 368 +++++++++++++++++- .../Instances.lean | 324 +-------------- .../Isometric.lean | 59 +-- .../ContinuousFunctionalCalculus/Order.lean | 2 +- .../SpecialFunctions/PosPart.lean | 2 +- .../Analysis/InnerProductSpace/StarOrder.lean | 2 +- 7 files changed, 379 insertions(+), 379 deletions(-) diff --git a/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean b/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean index 2f1dddf941c77..0479cfb3716ed 100644 --- a/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean +++ b/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Order -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Isometric import Mathlib.Analysis.CStarAlgebra.SpecialFunctions.PosPart import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow import Mathlib.Topology.ApproximateUnit diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean index ddc507110c3a9..f7ca1d318f5d0 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean @@ -3,8 +3,9 @@ Copyright (c) 2022 Jireh Loreaux. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Isometric import Mathlib.Analysis.CStarAlgebra.GelfandDuality -import Mathlib.Topology.Algebra.StarSubalgebra +import Mathlib.Analysis.CStarAlgebra.Unitization /-! # Continuous functional calculus @@ -40,6 +41,10 @@ relevant instances on C⋆-algebra can be found in the `Instances` file. by evaluating a character `φ` at `a`, and noting that `φ a ∈ spectrum ℂ a` since `φ` is an algebra homomorphism. Moreover, this map is continuous and bijective and since the spaces involved are compact Hausdorff, it is a homeomorphism. +* `IsStarNormal.instContinuousFunctionalCalculus`: the continuous functional calculus for normal + elements in a unital C⋆-algebra over `ℂ`. +* `CStarAlgebra.instNonnegSpectrumClass`: In a unital C⋆-algebra over `ℂ` which is also a + `StarOrderedRing`, the spectrum of a nonnegative element is nonnegative. -/ @@ -137,3 +142,364 @@ theorem continuousFunctionalCalculus_map_id : continuousFunctionalCalculus a ((ContinuousMap.id ℂ).restrict (spectrum ℂ a)) = ⟨a, self_mem ℂ a⟩ := (gelfandStarTransform (elemental ℂ a)).symm_apply_apply _ + +/-! +### Continuous functional calculus for normal elements +-/ + +local notation "σₙ" => quasispectrum + +section Normal + +instance IsStarNormal.instContinuousFunctionalCalculus {A : Type*} [CStarAlgebra A] : + ContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop) where + predicate_zero := .zero + spectrum_nonempty a _ := spectrum.nonempty a + exists_cfc_of_predicate a ha := by + refine ⟨(StarAlgebra.elemental ℂ a).subtype.comp <| continuousFunctionalCalculus a, + ?hom_isClosedEmbedding, ?hom_id, ?hom_map_spectrum, ?predicate_hom⟩ + case hom_isClosedEmbedding => + exact Isometry.isClosedEmbedding <| + isometry_subtype_coe.comp <| StarAlgEquiv.isometry (continuousFunctionalCalculus a) + case hom_id => exact congr_arg Subtype.val <| continuousFunctionalCalculus_map_id a + case hom_map_spectrum => + intro f + simp only [StarAlgHom.comp_apply, StarAlgHom.coe_coe, StarSubalgebra.coe_subtype] + rw [← StarSubalgebra.spectrum_eq (hS := StarAlgebra.elemental.isClosed ℂ a), + AlgEquiv.spectrum_eq (continuousFunctionalCalculus a), ContinuousMap.spectrum_eq_range] + case predicate_hom => exact fun f ↦ ⟨by rw [← map_star]; exact Commute.all (star f) f |>.map _⟩ + +lemma cfcHom_eq_of_isStarNormal {A : Type*} [CStarAlgebra A] (a : A) [ha : IsStarNormal a] : + cfcHom ha = (StarAlgebra.elemental ℂ a).subtype.comp (continuousFunctionalCalculus a) := by + refine cfcHom_eq_of_continuous_of_map_id ha _ ?_ ?_ + · exact continuous_subtype_val.comp <| + (StarAlgEquiv.isometry (continuousFunctionalCalculus a)).continuous + · simp [continuousFunctionalCalculus_map_id a] + +instance IsStarNormal.instNonUnitalContinuousFunctionalCalculus {A : Type*} + [NonUnitalCStarAlgebra A] : NonUnitalContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop) := + RCLike.nonUnitalContinuousFunctionalCalculus Unitization.isStarNormal_inr + +open Unitization CStarAlgebra in +lemma inr_comp_cfcₙHom_eq_cfcₙAux {A : Type*} [NonUnitalCStarAlgebra A] (a : A) + [ha : IsStarNormal a] : (inrNonUnitalStarAlgHom ℂ A).comp (cfcₙHom ha) = + cfcₙAux (isStarNormal_inr (R := ℂ) (A := A)) a ha := by + have h (a : A) := isStarNormal_inr (R := ℂ) (A := A) (a := a) + refine @UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id + _ _ _ _ _ _ _ _ _ _ _ inferInstance inferInstance _ (σₙ ℂ a) _ _ rfl _ _ ?_ ?_ ?_ + · show Continuous (fun f ↦ (cfcₙHom ha f : A⁺¹)); fun_prop + · exact isClosedEmbedding_cfcₙAux @(h) a ha |>.continuous + · trans (a : A⁺¹) + · congrm(inr $(cfcₙHom_id ha)) + · exact cfcₙAux_id @(h) a ha |>.symm + +end Normal + +/-! +### The spectrum of a nonnegative element is nonnegative +-/ + +section SpectrumRestricts + +open NNReal ENNReal + +variable {A : Type*} [CStarAlgebra A] + +lemma SpectrumRestricts.nnreal_iff_nnnorm {a : A} {t : ℝ≥0} (ha : IsSelfAdjoint a) (ht : ‖a‖₊ ≤ t) : + SpectrumRestricts a ContinuousMap.realToNNReal ↔ ‖algebraMap ℝ A t - a‖₊ ≤ t := by + have : IsSelfAdjoint (algebraMap ℝ A t - a) := IsSelfAdjoint.algebraMap A (.all (t : ℝ)) |>.sub ha + rw [← ENNReal.coe_le_coe, ← IsSelfAdjoint.spectralRadius_eq_nnnorm, + ← SpectrumRestricts.spectralRadius_eq (f := Complex.reCLM)] at ht ⊢ + · exact SpectrumRestricts.nnreal_iff_spectralRadius_le ht + all_goals + try apply IsSelfAdjoint.spectrumRestricts + assumption + +lemma SpectrumRestricts.nnreal_add {a b : A} (ha₁ : IsSelfAdjoint a) + (hb₁ : IsSelfAdjoint b) (ha₂ : SpectrumRestricts a ContinuousMap.realToNNReal) + (hb₂ : SpectrumRestricts b ContinuousMap.realToNNReal) : + SpectrumRestricts (a + b) ContinuousMap.realToNNReal := by + rw [SpectrumRestricts.nnreal_iff_nnnorm (ha₁.add hb₁) (nnnorm_add_le a b), NNReal.coe_add, + map_add, add_sub_add_comm] + refine nnnorm_add_le _ _ |>.trans ?_ + gcongr + all_goals rw [← SpectrumRestricts.nnreal_iff_nnnorm] <;> first | rfl | assumption + +lemma IsSelfAdjoint.sq_spectrumRestricts {a : A} (ha : IsSelfAdjoint a) : + SpectrumRestricts (a ^ 2) ContinuousMap.realToNNReal := by + rw [SpectrumRestricts.nnreal_iff, ← cfc_id (R := ℝ) a, ← cfc_pow .., cfc_map_spectrum ..] + rintro - ⟨x, -, rfl⟩ + exact sq_nonneg x + +open ComplexStarModule + +lemma SpectrumRestricts.eq_zero_of_neg {a : A} (ha : IsSelfAdjoint a) + (ha₁ : SpectrumRestricts a ContinuousMap.realToNNReal) + (ha₂ : SpectrumRestricts (-a) ContinuousMap.realToNNReal) : + a = 0 := by + nontriviality A + rw [SpectrumRestricts.nnreal_iff] at ha₁ ha₂ + apply CFC.eq_zero_of_spectrum_subset_zero (R := ℝ) a + rw [Set.subset_singleton_iff] + simp only [← spectrum.neg_eq, Set.mem_neg] at ha₂ + peel ha₁ with x hx _ + linarith [ha₂ (-x) ((neg_neg x).symm ▸ hx)] + +lemma SpectrumRestricts.smul_of_nonneg {A : Type*} [Ring A] [Algebra ℝ A] {a : A} + (ha : SpectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ} (hr : 0 ≤ r) : + SpectrumRestricts (r • a) ContinuousMap.realToNNReal := by + rw [SpectrumRestricts.nnreal_iff] at ha ⊢ + nontriviality A + intro x hx + by_cases hr' : r = 0 + · simp [hr'] at hx ⊢ + exact hx.symm.le + · lift r to ℝˣ using IsUnit.mk0 r hr' + rw [← Units.smul_def, spectrum.unit_smul_eq_smul, Set.mem_smul_set_iff_inv_smul_mem] at hx + refine le_of_smul_le_smul_left ?_ (inv_pos.mpr <| lt_of_le_of_ne hr <| ne_comm.mpr hr') + simpa [Units.smul_def] using ha _ hx + +lemma spectrum_star_mul_self_nonneg {b : A} : ∀ x ∈ spectrum ℝ (star b * b), 0 ≤ x := by + set a := star b * b + have a_def : a = star b * b := rfl + let a_neg : A := cfc (fun x ↦ (- ContinuousMap.id ℝ ⊔ 0) x) a + set c := b * a_neg + have h_eq_a_neg : - (star c * c) = a_neg ^ 3 := by + simp only [c, a_neg, star_mul] + rw [← mul_assoc, mul_assoc _ _ b, ← cfc_star, ← cfc_id' ℝ (star b * b), a_def, ← neg_mul] + rw [← cfc_mul _ _ (star b * b) (by simp; fun_prop), neg_mul] + simp only [ContinuousMap.coe_neg, ContinuousMap.coe_id, Pi.sup_apply, Pi.neg_apply, + star_trivial] + rw [← cfc_mul .., ← cfc_neg .., ← cfc_pow ..] + congr + ext x + by_cases hx : x ≤ 0 + · rw [← neg_nonneg] at hx + simp [sup_eq_left.mpr hx, pow_succ] + · rw [not_le, ← neg_neg_iff_pos] at hx + simp [sup_eq_right.mpr hx.le] + have h_c_spec₀ : SpectrumRestricts (- (star c * c)) (ContinuousMap.realToNNReal ·) := by + simp only [SpectrumRestricts.nnreal_iff, h_eq_a_neg] + rw [← cfc_pow _ _ (ha := .star_mul_self b)] + simp only [a, cfc_map_spectrum (R := ℝ) (fun x => (-ContinuousMap.id ℝ ⊔ 0) x ^ 3) (star b * b)] + rintro - ⟨x, -, rfl⟩ + simp + have c_eq := star_mul_self_add_self_mul_star c + rw [← eq_sub_iff_add_eq', sub_eq_add_neg, ← sq, ← sq] at c_eq + have h_c_spec₁ : SpectrumRestricts (c * star c) ContinuousMap.realToNNReal := by + rw [c_eq] + refine SpectrumRestricts.nnreal_add ?_ ?_ ?_ h_c_spec₀ + · exact IsSelfAdjoint.smul (by rfl) <| ((ℜ c).prop.pow 2).add ((ℑ c).prop.pow 2) + · exact (IsSelfAdjoint.star_mul_self c).neg + · rw [← Nat.cast_smul_eq_nsmul ℝ] + refine (ℜ c).2.sq_spectrumRestricts.nnreal_add ((ℜ c).2.pow 2) ((ℑ c).2.pow 2) + (ℑ c).2.sq_spectrumRestricts |>.smul_of_nonneg <| by norm_num + have h_c_spec₂ : SpectrumRestricts (star c * c) ContinuousMap.realToNNReal := by + rw [SpectrumRestricts.nnreal_iff] at h_c_spec₁ ⊢ + intro x hx + replace hx := Set.subset_diff_union _ {(0 : ℝ)} hx + rw [spectrum.nonzero_mul_eq_swap_mul, Set.diff_union_self, Set.union_singleton, + Set.mem_insert_iff] at hx + obtain (rfl | hx) := hx + exacts [le_rfl, h_c_spec₁ x hx] + rw [h_c_spec₂.eq_zero_of_neg (.star_mul_self c) h_c_spec₀, neg_zero] at h_eq_a_neg + simp only [a_neg] at h_eq_a_neg + rw [← cfc_pow _ _ (ha := .star_mul_self b), ← cfc_zero a (R := ℝ)] at h_eq_a_neg + intro x hx + by_contra! hx' + rw [← neg_pos] at hx' + apply (pow_pos hx' 3).ne + have h_eqOn := eqOn_of_cfc_eq_cfc (ha := IsSelfAdjoint.star_mul_self b) h_eq_a_neg + simpa [sup_eq_left.mpr hx'.le] using h_eqOn hx + +lemma IsSelfAdjoint.coe_mem_spectrum_complex {A : Type*} [TopologicalSpace A] [Ring A] + [StarRing A] [Algebra ℂ A] [ContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop)] + {a : A} {x : ℝ} (ha : IsSelfAdjoint a := by cfc_tac) : + (x : ℂ) ∈ spectrum ℂ a ↔ x ∈ spectrum ℝ a := by + simp [← ha.spectrumRestricts.algebraMap_image] + +end SpectrumRestricts + +section NonnegSpectrumClass + +variable {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A] + +instance CStarAlgebra.instNonnegSpectrumClass : NonnegSpectrumClass ℝ A := + .of_spectrum_nonneg fun a ha ↦ by + rw [StarOrderedRing.nonneg_iff] at ha + induction ha using AddSubmonoid.closure_induction with + | mem x hx => + obtain ⟨b, rfl⟩ := hx + exact spectrum_star_mul_self_nonneg + | one => + nontriviality A + simp + | mul x y x_mem y_mem hx hy => + rw [← SpectrumRestricts.nnreal_iff] at hx hy ⊢ + rw [← StarOrderedRing.nonneg_iff] at x_mem y_mem + exact hx.nnreal_add (.of_nonneg x_mem) (.of_nonneg y_mem) hy + +open ComplexOrder in +instance CStarAlgebra.instNonnegSpectrumClassComplexUnital : NonnegSpectrumClass ℂ A where + quasispectrum_nonneg_of_nonneg a ha x := by + rw [mem_quasispectrum_iff] + refine (Or.elim · ge_of_eq fun hx ↦ ?_) + obtain ⟨y, hy, rfl⟩ := (IsSelfAdjoint.of_nonneg ha).spectrumRestricts.algebraMap_image ▸ hx + simpa using spectrum_nonneg_of_nonneg ha hy + +end NonnegSpectrumClass + +section SpectralOrder + +variable (A : Type*) [CStarAlgebra A] + +/-- The partial order on a unital C⋆-algebra defined by `x ≤ y` if and only if `y - x` is +selfadjoint and has nonnegative spectrum. + +This is not declared as an instance because one may already have a partial order with better +definitional properties. However, it can be useful to invoke this as an instance in proofs. -/ +@[reducible] +def CStarAlgebra.spectralOrder : PartialOrder A where + le x y := IsSelfAdjoint (y - x) ∧ SpectrumRestricts (y - x) ContinuousMap.realToNNReal + le_refl := by + simp only [sub_self, IsSelfAdjoint.zero, true_and, forall_const] + rw [SpectrumRestricts.nnreal_iff] + nontriviality A + simp + le_antisymm x y hxy hyx := by + rw [← sub_eq_zero] + exact hyx.2.eq_zero_of_neg hyx.1 (neg_sub x y ▸ hxy.2) + le_trans x y z hxy hyz := + ⟨by simpa using hyz.1.add hxy.1, by simpa using hyz.2.nnreal_add hyz.1 hxy.1 hxy.2⟩ + +/-- The `CStarAlgebra.spectralOrder` on a unital C⋆-algebra is a `StarOrderedRing`. -/ +lemma CStarAlgebra.spectralOrderedRing : @StarOrderedRing A _ (CStarAlgebra.spectralOrder A) _ := + let _ := CStarAlgebra.spectralOrder A + { le_iff := by + intro x y + constructor + · intro h + obtain ⟨s, hs₁, _, hs₂⟩ := CFC.exists_sqrt_of_isSelfAdjoint_of_spectrumRestricts h.1 h.2 + refine ⟨s ^ 2, ?_, by rwa [eq_sub_iff_add_eq', eq_comm] at hs₂⟩ + exact AddSubmonoid.subset_closure ⟨s, by simp [hs₁.star_eq, sq]⟩ + · rintro ⟨p, hp, rfl⟩ + suffices IsSelfAdjoint p ∧ SpectrumRestricts p ContinuousMap.realToNNReal from + ⟨by simpa using this.1, by simpa using this.2⟩ + induction hp using AddSubmonoid.closure_induction with + | mem x hx => + obtain ⟨s, rfl⟩ := hx + refine ⟨IsSelfAdjoint.star_mul_self s, ?_⟩ + rw [SpectrumRestricts.nnreal_iff] + exact spectrum_star_mul_self_nonneg + | one => + rw [SpectrumRestricts.nnreal_iff] + nontriviality A + simp + | mul x y _ _ hx hy => + exact ⟨hx.1.add hy.1, hx.2.nnreal_add hx.1 hy.1 hy.2⟩ } + +end SpectralOrder + +section NonnegSpectrumClass + +variable {A : Type*} [NonUnitalCStarAlgebra A] [PartialOrder A] [StarOrderedRing A] + +open scoped CStarAlgebra in +instance CStarAlgebra.instNonnegSpectrumClass' : NonnegSpectrumClass ℝ A where + quasispectrum_nonneg_of_nonneg a ha := by + rw [Unitization.quasispectrum_eq_spectrum_inr' _ ℂ] + -- should this actually be an instance on the `Unitization`? (probably scoped) + let _ := CStarAlgebra.spectralOrder A⁺¹ + have := CStarAlgebra.spectralOrderedRing A⁺¹ + apply spectrum_nonneg_of_nonneg + rw [StarOrderedRing.nonneg_iff] at ha ⊢ + have := AddSubmonoid.mem_map_of_mem (Unitization.inrNonUnitalStarAlgHom ℂ A) ha + rw [AddMonoidHom.map_mclosure, ← Set.range_comp] at this + apply AddSubmonoid.closure_mono ?_ this + rintro _ ⟨s, rfl⟩ + exact ⟨s, by simp⟩ + +end NonnegSpectrumClass + +section cfc_inr + +open CStarAlgebra + +variable {A : Type*} [NonUnitalCStarAlgebra A] + +open scoped NonUnitalContinuousFunctionalCalculus in +/-- This lemma requires a lot from type class synthesis, and so one should instead favor the bespoke +versions for `ℝ≥0`, `ℝ`, and `ℂ`. -/ +lemma Unitization.cfcₙ_eq_cfc_inr {R : Type*} [Semifield R] [StarRing R] [MetricSpace R] + [TopologicalSemiring R] [ContinuousStar R] [Module R A] [IsScalarTower R A A] + [SMulCommClass R A A] [CompleteSpace R] [Algebra R ℂ] [IsScalarTower R ℂ A] + {p : A → Prop} {p' : A⁺¹ → Prop} [NonUnitalContinuousFunctionalCalculus R p] + [ContinuousFunctionalCalculus R p'] + [UniqueNonUnitalContinuousFunctionalCalculus R (Unitization ℂ A)] + (hp : ∀ {a : A}, p' (a : A⁺¹) ↔ p a) (a : A) (f : R → R) (hf₀ : f 0 = 0 := by cfc_zero_tac) : + cfcₙ f a = cfc f (a : A⁺¹) := by + by_cases h : ContinuousOn f (σₙ R a) ∧ p a + · obtain ⟨hf, ha⟩ := h + rw [← cfcₙ_eq_cfc (quasispectrum_inr_eq R ℂ a ▸ hf)] + exact (inrNonUnitalStarAlgHom ℂ A).map_cfcₙ f a + · obtain (hf | ha) := not_and_or.mp h + · rw [cfcₙ_apply_of_not_continuousOn a hf, inr_zero, + cfc_apply_of_not_continuousOn _ (quasispectrum_eq_spectrum_inr' R ℂ a ▸ hf)] + · rw [cfcₙ_apply_of_not_predicate a ha, inr_zero, + cfc_apply_of_not_predicate _ (not_iff_not.mpr hp |>.mpr ha)] + +lemma Unitization.complex_cfcₙ_eq_cfc_inr (a : A) (f : ℂ → ℂ) (hf₀ : f 0 = 0 := by cfc_zero_tac) : + cfcₙ f a = cfc f (a : A⁺¹) := + Unitization.cfcₙ_eq_cfc_inr isStarNormal_inr .. + +/-- note: the version for `ℝ≥0`, `Unization.nnreal_cfcₙ_eq_cfc_inr`, can be found in +`Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Order` -/ +lemma Unitization.real_cfcₙ_eq_cfc_inr (a : A) (f : ℝ → ℝ) (hf₀ : f 0 = 0 := by cfc_zero_tac) : + cfcₙ f a = cfc f (a : A⁺¹) := + Unitization.cfcₙ_eq_cfc_inr isSelfAdjoint_inr .. + +end cfc_inr + +/-! ### Instances of isometric continuous functional calculi -/ + +section Unital + +variable {A : Type*} [CStarAlgebra A] + +instance IsStarNormal.instIsometricContinuousFunctionalCalculus : + IsometricContinuousFunctionalCalculus ℂ A IsStarNormal where + isometric a ha := by + rw [cfcHom_eq_of_isStarNormal] + exact isometry_subtype_coe.comp <| StarAlgEquiv.isometry (continuousFunctionalCalculus a) + +instance IsSelfAdjoint.instIsometricContinuousFunctionalCalculus : + IsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint := + SpectrumRestricts.isometric_cfc Complex.reCLM Complex.isometry_ofReal (.zero _) + fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_spectrumRestricts + +end Unital + +section NonUnital + +variable {A : Type*} [NonUnitalCStarAlgebra A] + +open Unitization + +open ContinuousMapZero in +instance IsStarNormal.instNonUnitalIsometricContinuousFunctionalCalculus : + NonUnitalIsometricContinuousFunctionalCalculus ℂ A IsStarNormal where + isometric a ha := by + refine AddMonoidHomClass.isometry_of_norm _ fun f ↦ ?_ + rw [← norm_inr (𝕜 := ℂ), ← inrNonUnitalStarAlgHom_apply, ← NonUnitalStarAlgHom.comp_apply, + inr_comp_cfcₙHom_eq_cfcₙAux a, cfcₙAux] + simp only [NonUnitalStarAlgHom.comp_assoc, NonUnitalStarAlgHom.comp_apply, + toContinuousMapHom_apply, NonUnitalStarAlgHom.coe_coe] + rw [norm_cfcHom (a : Unitization ℂ A), StarAlgEquiv.norm_map] + rfl + +instance IsSelfAdjoint.instNonUnitalIsometricContinuousFunctionalCalculus : + NonUnitalIsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint := + QuasispectrumRestricts.isometric_cfc Complex.reCLM Complex.isometry_ofReal (.zero _) + fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_quasispectrumRestricts + +end NonUnital diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean index ad42b978ebfcd..9a5db6550e159 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean @@ -4,17 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Restrict -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic -import Mathlib.Analysis.CStarAlgebra.Spectrum -import Mathlib.Analysis.CStarAlgebra.Unitization import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unique +import Mathlib.Analysis.CStarAlgebra.Unitization +import Mathlib.Analysis.Normed.Algebra.Spectrum /-! # Instances of the continuous functional calculus ## Main theorems -* `IsStarNormal.instContinuousFunctionalCalculus`: the continuous functional calculus for normal - elements in a unital C⋆-algebra over `ℂ`. * `IsSelfAdjoint.instContinuousFunctionalCalculus`: the continuous functional calculus for selfadjoint elements in a `ℂ`-algebra with a continuous functional calculus for normal elements and where every element has compact spectrum. In particular, this includes unital C⋆-algebras @@ -23,8 +20,6 @@ import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unique elements in an `ℝ`-algebra with a continuous functional calculus for selfadjoint elements, where every element has compact spectrum, and where nonnegative elements have nonnegative spectrum. In particular, this includes unital C⋆-algebras over `ℝ`. -* `CStarAlgebra.instNonnegSpectrumClass`: In a unital C⋆-algebra over `ℂ` which is also a - `StarOrderedRing`, the spectrum of a nonnegative element is nonnegative. ## Tags @@ -147,56 +142,6 @@ theorem RCLike.nonUnitalContinuousFunctionalCalculus : end RCLike -/-! -### Continuous functional calculus for normal elements --/ - -section Normal - -instance IsStarNormal.instContinuousFunctionalCalculus {A : Type*} [CStarAlgebra A] : - ContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop) where - predicate_zero := .zero - spectrum_nonempty a _ := spectrum.nonempty a - exists_cfc_of_predicate a ha := by - refine ⟨(StarAlgebra.elemental ℂ a).subtype.comp <| continuousFunctionalCalculus a, - ?hom_isClosedEmbedding, ?hom_id, ?hom_map_spectrum, ?predicate_hom⟩ - case hom_isClosedEmbedding => - exact Isometry.isClosedEmbedding <| - isometry_subtype_coe.comp <| StarAlgEquiv.isometry (continuousFunctionalCalculus a) - case hom_id => exact congr_arg Subtype.val <| continuousFunctionalCalculus_map_id a - case hom_map_spectrum => - intro f - simp only [StarAlgHom.comp_apply, StarAlgHom.coe_coe, StarSubalgebra.coe_subtype] - rw [← StarSubalgebra.spectrum_eq (hS := StarAlgebra.elemental.isClosed ℂ a), - AlgEquiv.spectrum_eq (continuousFunctionalCalculus a), ContinuousMap.spectrum_eq_range] - case predicate_hom => exact fun f ↦ ⟨by rw [← map_star]; exact Commute.all (star f) f |>.map _⟩ - -lemma cfcHom_eq_of_isStarNormal {A : Type*} [CStarAlgebra A] (a : A) [ha : IsStarNormal a] : - cfcHom ha = (StarAlgebra.elemental ℂ a).subtype.comp (continuousFunctionalCalculus a) := by - refine cfcHom_eq_of_continuous_of_map_id ha _ ?_ ?_ - · exact continuous_subtype_val.comp <| - (StarAlgEquiv.isometry (continuousFunctionalCalculus a)).continuous - · simp [continuousFunctionalCalculus_map_id a] - -instance IsStarNormal.instNonUnitalContinuousFunctionalCalculus {A : Type*} - [NonUnitalCStarAlgebra A] : NonUnitalContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop) := - RCLike.nonUnitalContinuousFunctionalCalculus Unitization.isStarNormal_inr - -open Unitization CStarAlgebra in -lemma inr_comp_cfcₙHom_eq_cfcₙAux {A : Type*} [NonUnitalCStarAlgebra A] (a : A) - [ha : IsStarNormal a] : (inrNonUnitalStarAlgHom ℂ A).comp (cfcₙHom ha) = - cfcₙAux (isStarNormal_inr (R := ℂ) (A := A)) a ha := by - have h (a : A) := isStarNormal_inr (R := ℂ) (A := A) (a := a) - refine @UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id - _ _ _ _ _ _ _ _ _ _ _ inferInstance inferInstance _ (σₙ ℂ a) _ _ rfl _ _ ?_ ?_ ?_ - · show Continuous (fun f ↦ (cfcₙHom ha f : A⁺¹)); fun_prop - · exact isClosedEmbedding_cfcₙAux @(h) a ha |>.continuous - · trans (a : A⁺¹) - · congrm(inr $(cfcₙHom_id ha)) - · exact cfcₙAux_id @(h) a ha |>.symm - -end Normal - /-! ### Continuous functional calculus for selfadjoint elements -/ @@ -379,232 +324,6 @@ instance Nonneg.instContinuousFunctionalCalculus : end Nonneg -/-! -### The spectrum of a nonnegative element is nonnegative --/ - -section SpectrumRestricts - -open NNReal ENNReal - -variable {A : Type*} [CStarAlgebra A] - -lemma SpectrumRestricts.nnreal_iff_nnnorm {a : A} {t : ℝ≥0} (ha : IsSelfAdjoint a) (ht : ‖a‖₊ ≤ t) : - SpectrumRestricts a ContinuousMap.realToNNReal ↔ ‖algebraMap ℝ A t - a‖₊ ≤ t := by - have : IsSelfAdjoint (algebraMap ℝ A t - a) := IsSelfAdjoint.algebraMap A (.all (t : ℝ)) |>.sub ha - rw [← ENNReal.coe_le_coe, ← IsSelfAdjoint.spectralRadius_eq_nnnorm, - ← SpectrumRestricts.spectralRadius_eq (f := Complex.reCLM)] at ht ⊢ - · exact SpectrumRestricts.nnreal_iff_spectralRadius_le ht - all_goals - try apply IsSelfAdjoint.spectrumRestricts - assumption - -lemma SpectrumRestricts.nnreal_add {a b : A} (ha₁ : IsSelfAdjoint a) - (hb₁ : IsSelfAdjoint b) (ha₂ : SpectrumRestricts a ContinuousMap.realToNNReal) - (hb₂ : SpectrumRestricts b ContinuousMap.realToNNReal) : - SpectrumRestricts (a + b) ContinuousMap.realToNNReal := by - rw [SpectrumRestricts.nnreal_iff_nnnorm (ha₁.add hb₁) (nnnorm_add_le a b), NNReal.coe_add, - map_add, add_sub_add_comm] - refine nnnorm_add_le _ _ |>.trans ?_ - gcongr - all_goals rw [← SpectrumRestricts.nnreal_iff_nnnorm] <;> first | rfl | assumption - -lemma IsSelfAdjoint.sq_spectrumRestricts {a : A} (ha : IsSelfAdjoint a) : - SpectrumRestricts (a ^ 2) ContinuousMap.realToNNReal := by - rw [SpectrumRestricts.nnreal_iff, ← cfc_id (R := ℝ) a, ← cfc_pow .., cfc_map_spectrum ..] - rintro - ⟨x, -, rfl⟩ - exact sq_nonneg x - -open ComplexStarModule - -lemma SpectrumRestricts.eq_zero_of_neg {a : A} (ha : IsSelfAdjoint a) - (ha₁ : SpectrumRestricts a ContinuousMap.realToNNReal) - (ha₂ : SpectrumRestricts (-a) ContinuousMap.realToNNReal) : - a = 0 := by - nontriviality A - rw [SpectrumRestricts.nnreal_iff] at ha₁ ha₂ - apply CFC.eq_zero_of_spectrum_subset_zero (R := ℝ) a - rw [Set.subset_singleton_iff] - simp only [← spectrum.neg_eq, Set.mem_neg] at ha₂ - peel ha₁ with x hx _ - linarith [ha₂ (-x) ((neg_neg x).symm ▸ hx)] - -lemma SpectrumRestricts.smul_of_nonneg {A : Type*} [Ring A] [Algebra ℝ A] {a : A} - (ha : SpectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ} (hr : 0 ≤ r) : - SpectrumRestricts (r • a) ContinuousMap.realToNNReal := by - rw [SpectrumRestricts.nnreal_iff] at ha ⊢ - nontriviality A - intro x hx - by_cases hr' : r = 0 - · simp [hr'] at hx ⊢ - exact hx.symm.le - · lift r to ℝˣ using IsUnit.mk0 r hr' - rw [← Units.smul_def, spectrum.unit_smul_eq_smul, Set.mem_smul_set_iff_inv_smul_mem] at hx - refine le_of_smul_le_smul_left ?_ (inv_pos.mpr <| lt_of_le_of_ne hr <| ne_comm.mpr hr') - simpa [Units.smul_def] using ha _ hx - -lemma spectrum_star_mul_self_nonneg {b : A} : ∀ x ∈ spectrum ℝ (star b * b), 0 ≤ x := by - set a := star b * b - have a_def : a = star b * b := rfl - let a_neg : A := cfc (fun x ↦ (- ContinuousMap.id ℝ ⊔ 0) x) a - set c := b * a_neg - have h_eq_a_neg : - (star c * c) = a_neg ^ 3 := by - simp only [c, a_neg, star_mul] - rw [← mul_assoc, mul_assoc _ _ b, ← cfc_star, ← cfc_id' ℝ (star b * b), a_def, ← neg_mul] - rw [← cfc_mul _ _ (star b * b) (by simp; fun_prop), neg_mul] - simp only [ContinuousMap.coe_neg, ContinuousMap.coe_id, Pi.sup_apply, Pi.neg_apply, - star_trivial] - rw [← cfc_mul .., ← cfc_neg .., ← cfc_pow ..] - congr - ext x - by_cases hx : x ≤ 0 - · rw [← neg_nonneg] at hx - simp [sup_eq_left.mpr hx, pow_succ] - · rw [not_le, ← neg_neg_iff_pos] at hx - simp [sup_eq_right.mpr hx.le] - have h_c_spec₀ : SpectrumRestricts (- (star c * c)) (ContinuousMap.realToNNReal ·) := by - simp only [SpectrumRestricts.nnreal_iff, h_eq_a_neg] - rw [← cfc_pow _ _ (ha := .star_mul_self b)] - simp only [a, cfc_map_spectrum (R := ℝ) (fun x => (-ContinuousMap.id ℝ ⊔ 0) x ^ 3) (star b * b)] - rintro - ⟨x, -, rfl⟩ - simp - have c_eq := star_mul_self_add_self_mul_star c - rw [← eq_sub_iff_add_eq', sub_eq_add_neg, ← sq, ← sq] at c_eq - have h_c_spec₁ : SpectrumRestricts (c * star c) ContinuousMap.realToNNReal := by - rw [c_eq] - refine SpectrumRestricts.nnreal_add ?_ ?_ ?_ h_c_spec₀ - · exact IsSelfAdjoint.smul (by rfl) <| ((ℜ c).prop.pow 2).add ((ℑ c).prop.pow 2) - · exact (IsSelfAdjoint.star_mul_self c).neg - · rw [← Nat.cast_smul_eq_nsmul ℝ] - refine (ℜ c).2.sq_spectrumRestricts.nnreal_add ((ℜ c).2.pow 2) ((ℑ c).2.pow 2) - (ℑ c).2.sq_spectrumRestricts |>.smul_of_nonneg <| by norm_num - have h_c_spec₂ : SpectrumRestricts (star c * c) ContinuousMap.realToNNReal := by - rw [SpectrumRestricts.nnreal_iff] at h_c_spec₁ ⊢ - intro x hx - replace hx := Set.subset_diff_union _ {(0 : ℝ)} hx - rw [spectrum.nonzero_mul_eq_swap_mul, Set.diff_union_self, Set.union_singleton, - Set.mem_insert_iff] at hx - obtain (rfl | hx) := hx - exacts [le_rfl, h_c_spec₁ x hx] - rw [h_c_spec₂.eq_zero_of_neg (.star_mul_self c) h_c_spec₀, neg_zero] at h_eq_a_neg - simp only [a_neg] at h_eq_a_neg - rw [← cfc_pow _ _ (ha := .star_mul_self b), ← cfc_zero a (R := ℝ)] at h_eq_a_neg - intro x hx - by_contra! hx' - rw [← neg_pos] at hx' - apply (pow_pos hx' 3).ne - have h_eqOn := eqOn_of_cfc_eq_cfc (ha := IsSelfAdjoint.star_mul_self b) h_eq_a_neg - simpa [sup_eq_left.mpr hx'.le] using h_eqOn hx - -lemma IsSelfAdjoint.coe_mem_spectrum_complex {A : Type*} [TopologicalSpace A] [Ring A] - [StarRing A] [Algebra ℂ A] [ContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop)] - {a : A} {x : ℝ} (ha : IsSelfAdjoint a := by cfc_tac) : - (x : ℂ) ∈ spectrum ℂ a ↔ x ∈ spectrum ℝ a := by - simp [← ha.spectrumRestricts.algebraMap_image] - -end SpectrumRestricts - -section NonnegSpectrumClass - -variable {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A] - -instance CStarAlgebra.instNonnegSpectrumClass : NonnegSpectrumClass ℝ A := - .of_spectrum_nonneg fun a ha ↦ by - rw [StarOrderedRing.nonneg_iff] at ha - induction ha using AddSubmonoid.closure_induction with - | mem x hx => - obtain ⟨b, rfl⟩ := hx - exact spectrum_star_mul_self_nonneg - | one => - nontriviality A - simp - | mul x y x_mem y_mem hx hy => - rw [← SpectrumRestricts.nnreal_iff] at hx hy ⊢ - rw [← StarOrderedRing.nonneg_iff] at x_mem y_mem - exact hx.nnreal_add (.of_nonneg x_mem) (.of_nonneg y_mem) hy - -open ComplexOrder in -instance CStarAlgebra.instNonnegSpectrumClassComplexUnital : NonnegSpectrumClass ℂ A where - quasispectrum_nonneg_of_nonneg a ha x := by - rw [mem_quasispectrum_iff] - refine (Or.elim · ge_of_eq fun hx ↦ ?_) - obtain ⟨y, hy, rfl⟩ := (IsSelfAdjoint.of_nonneg ha).spectrumRestricts.algebraMap_image ▸ hx - simpa using spectrum_nonneg_of_nonneg ha hy - -end NonnegSpectrumClass - -section SpectralOrder - -variable (A : Type*) [CStarAlgebra A] - -/-- The partial order on a unital C⋆-algebra defined by `x ≤ y` if and only if `y - x` is -selfadjoint and has nonnegative spectrum. - -This is not declared as an instance because one may already have a partial order with better -definitional properties. However, it can be useful to invoke this as an instance in proofs. -/ -@[reducible] -def CStarAlgebra.spectralOrder : PartialOrder A where - le x y := IsSelfAdjoint (y - x) ∧ SpectrumRestricts (y - x) ContinuousMap.realToNNReal - le_refl := by - simp only [sub_self, IsSelfAdjoint.zero, true_and, forall_const] - rw [SpectrumRestricts.nnreal_iff] - nontriviality A - simp - le_antisymm x y hxy hyx := by - rw [← sub_eq_zero] - exact hyx.2.eq_zero_of_neg hyx.1 (neg_sub x y ▸ hxy.2) - le_trans x y z hxy hyz := - ⟨by simpa using hyz.1.add hxy.1, by simpa using hyz.2.nnreal_add hyz.1 hxy.1 hxy.2⟩ - -/-- The `CStarAlgebra.spectralOrder` on a unital C⋆-algebra is a `StarOrderedRing`. -/ -lemma CStarAlgebra.spectralOrderedRing : @StarOrderedRing A _ (CStarAlgebra.spectralOrder A) _ := - let _ := CStarAlgebra.spectralOrder A - { le_iff := by - intro x y - constructor - · intro h - obtain ⟨s, hs₁, _, hs₂⟩ := CFC.exists_sqrt_of_isSelfAdjoint_of_spectrumRestricts h.1 h.2 - refine ⟨s ^ 2, ?_, by rwa [eq_sub_iff_add_eq', eq_comm] at hs₂⟩ - exact AddSubmonoid.subset_closure ⟨s, by simp [hs₁.star_eq, sq]⟩ - · rintro ⟨p, hp, rfl⟩ - suffices IsSelfAdjoint p ∧ SpectrumRestricts p ContinuousMap.realToNNReal from - ⟨by simpa using this.1, by simpa using this.2⟩ - induction hp using AddSubmonoid.closure_induction with - | mem x hx => - obtain ⟨s, rfl⟩ := hx - refine ⟨IsSelfAdjoint.star_mul_self s, ?_⟩ - rw [SpectrumRestricts.nnreal_iff] - exact spectrum_star_mul_self_nonneg - | one => - rw [SpectrumRestricts.nnreal_iff] - nontriviality A - simp - | mul x y _ _ hx hy => - exact ⟨hx.1.add hy.1, hx.2.nnreal_add hx.1 hy.1 hy.2⟩ } - -end SpectralOrder - -section NonnegSpectrumClass - -variable {A : Type*} [NonUnitalCStarAlgebra A] [PartialOrder A] [StarOrderedRing A] - -open scoped CStarAlgebra in -instance CStarAlgebra.instNonnegSpectrumClass' : NonnegSpectrumClass ℝ A where - quasispectrum_nonneg_of_nonneg a ha := by - rw [Unitization.quasispectrum_eq_spectrum_inr' _ ℂ] - -- should this actually be an instance on the `Unitization`? (probably scoped) - let _ := CStarAlgebra.spectralOrder A⁺¹ - have := CStarAlgebra.spectralOrderedRing A⁺¹ - apply spectrum_nonneg_of_nonneg - rw [StarOrderedRing.nonneg_iff] at ha ⊢ - have := AddSubmonoid.mem_map_of_mem (Unitization.inrNonUnitalStarAlgHom ℂ A) ha - rw [AddMonoidHom.map_mclosure, ← Set.range_comp] at this - apply AddSubmonoid.closure_mono ?_ this - rintro _ ⟨s, rfl⟩ - exact ⟨s, by simp⟩ - -end NonnegSpectrumClass - /-! ### The restriction of a continuous functional calculus is equal to the original one -/ @@ -693,43 +412,4 @@ lemma cfcₙ_nnreal_eq_real {a : A} (f : ℝ≥0 → ℝ≥0) (ha : 0 ≤ a := b end NNRealEqRealNonUnital -section cfc_inr - -open CStarAlgebra - -variable {A : Type*} [NonUnitalCStarAlgebra A] - -open scoped NonUnitalContinuousFunctionalCalculus in -/-- This lemma requires a lot from type class synthesis, and so one should instead favor the bespoke -versions for `ℝ≥0`, `ℝ`, and `ℂ`. -/ -lemma Unitization.cfcₙ_eq_cfc_inr {R : Type*} [Semifield R] [StarRing R] [MetricSpace R] - [TopologicalSemiring R] [ContinuousStar R] [Module R A] [IsScalarTower R A A] - [SMulCommClass R A A] [CompleteSpace R] [Algebra R ℂ] [IsScalarTower R ℂ A] - {p : A → Prop} {p' : A⁺¹ → Prop} [NonUnitalContinuousFunctionalCalculus R p] - [ContinuousFunctionalCalculus R p'] - [UniqueNonUnitalContinuousFunctionalCalculus R (Unitization ℂ A)] - (hp : ∀ {a : A}, p' (a : A⁺¹) ↔ p a) (a : A) (f : R → R) (hf₀ : f 0 = 0 := by cfc_zero_tac) : - cfcₙ f a = cfc f (a : A⁺¹) := by - by_cases h : ContinuousOn f (σₙ R a) ∧ p a - · obtain ⟨hf, ha⟩ := h - rw [← cfcₙ_eq_cfc (quasispectrum_inr_eq R ℂ a ▸ hf)] - exact (inrNonUnitalStarAlgHom ℂ A).map_cfcₙ f a - · obtain (hf | ha) := not_and_or.mp h - · rw [cfcₙ_apply_of_not_continuousOn a hf, inr_zero, - cfc_apply_of_not_continuousOn _ (quasispectrum_eq_spectrum_inr' R ℂ a ▸ hf)] - · rw [cfcₙ_apply_of_not_predicate a ha, inr_zero, - cfc_apply_of_not_predicate _ (not_iff_not.mpr hp |>.mpr ha)] - -lemma Unitization.complex_cfcₙ_eq_cfc_inr (a : A) (f : ℂ → ℂ) (hf₀ : f 0 = 0 := by cfc_zero_tac) : - cfcₙ f a = cfc f (a : A⁺¹) := - Unitization.cfcₙ_eq_cfc_inr isStarNormal_inr .. - -/-- note: the version for `ℝ≥0`, `Unization.nnreal_cfcₙ_eq_cfc_inr`, can be found in -`Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Order` -/ -lemma Unitization.real_cfcₙ_eq_cfc_inr (a : A) (f : ℝ → ℝ) (hf₀ : f 0 = 0 := by cfc_zero_tac) : - cfcₙ f a = cfc f (a : A⁺¹) := - Unitization.cfcₙ_eq_cfc_inr isSelfAdjoint_inr .. - -end cfc_inr - end diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean index 9494504949525..d96bd2baa0244 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean @@ -353,31 +353,18 @@ end QuasispectrumRestricts end NonUnital -/-! ### Instances of isometric continuous functional calculi -/ +/-! ### Instances of isometric continuous functional calculi + +The instances for `ℝ` and `ℂ` can be found in +`Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic`, as those require an actual +`CStarAlgebra` instance on `A`, whereas the one for `ℝ≥0` is simply inherited from an existing +instance for `ℝ`. +-/ section Instances section Unital -section Complex - -variable {A : Type*} [CStarAlgebra A] - -instance IsStarNormal.instIsometricContinuousFunctionalCalculus : - IsometricContinuousFunctionalCalculus ℂ A IsStarNormal where - isometric a ha := by - rw [cfcHom_eq_of_isStarNormal] - exact isometry_subtype_coe.comp <| StarAlgEquiv.isometry (continuousFunctionalCalculus a) - -instance IsSelfAdjoint.instIsometricContinuousFunctionalCalculus : - IsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint := - SpectrumRestricts.isometric_cfc Complex.reCLM Complex.isometry_ofReal (.zero _) - fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_spectrumRestricts - -end Complex - -section NNReal - variable {A : Type*} [NormedRing A] [PartialOrder A] [StarRing A] [StarOrderedRing A] variable [NormedAlgebra ℝ A] [IsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] variable [NonnegSpectrumClass ℝ A] @@ -388,40 +375,10 @@ instance Nonneg.instIsometricContinuousFunctionalCalculus : SpectrumRestricts.isometric_cfc (q := IsSelfAdjoint) ContinuousMap.realToNNReal isometry_subtype_coe le_rfl (fun _ ↦ nonneg_iff_isSelfAdjoint_and_spectrumRestricts) -end NNReal - end Unital section NonUnital -section Complex - -variable {A : Type*} [NonUnitalCStarAlgebra A] - -open Unitization - - -open ContinuousMapZero in -instance IsStarNormal.instNonUnitalIsometricContinuousFunctionalCalculus : - NonUnitalIsometricContinuousFunctionalCalculus ℂ A IsStarNormal where - isometric a ha := by - refine AddMonoidHomClass.isometry_of_norm _ fun f ↦ ?_ - rw [← norm_inr (𝕜 := ℂ), ← inrNonUnitalStarAlgHom_apply, ← NonUnitalStarAlgHom.comp_apply, - inr_comp_cfcₙHom_eq_cfcₙAux a, cfcₙAux] - simp only [NonUnitalStarAlgHom.comp_assoc, NonUnitalStarAlgHom.comp_apply, - toContinuousMapHom_apply, NonUnitalStarAlgHom.coe_coe] - rw [norm_cfcHom (a : Unitization ℂ A), StarAlgEquiv.norm_map] - rfl - -instance IsSelfAdjoint.instNonUnitalIsometricContinuousFunctionalCalculus : - NonUnitalIsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint := - QuasispectrumRestricts.isometric_cfc Complex.reCLM Complex.isometry_ofReal (.zero _) - fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_quasispectrumRestricts - -end Complex - -section NNReal - variable {A : Type*} [NonUnitalNormedRing A] [PartialOrder A] [StarRing A] [StarOrderedRing A] variable [NormedSpace ℝ A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] variable [NonUnitalIsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] @@ -433,8 +390,6 @@ instance Nonneg.instNonUnitalIsometricContinuousFunctionalCalculus : QuasispectrumRestricts.isometric_cfc (q := IsSelfAdjoint) ContinuousMap.realToNNReal isometry_subtype_coe le_rfl (fun _ ↦ nonneg_iff_isSelfAdjoint_and_quasispectrumRestricts) -end NNReal - end NonUnital end Instances diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean index ddd292f4a77d2..c829c663a59c8 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Frédéric Dupuis -/ -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic import Mathlib.Analysis.CStarAlgebra.Unitization import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow import Mathlib.Topology.ContinuousMap.StarOrdered diff --git a/Mathlib/Analysis/CStarAlgebra/SpecialFunctions/PosPart.lean b/Mathlib/Analysis/CStarAlgebra/SpecialFunctions/PosPart.lean index de68421d1db20..66058503c0847 100644 --- a/Mathlib/Analysis/CStarAlgebra/SpecialFunctions/PosPart.lean +++ b/Mathlib/Analysis/CStarAlgebra/SpecialFunctions/PosPart.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.PosPart -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic /-! # C⋆-algebraic facts about `a⁺` and `a⁻`. -/ diff --git a/Mathlib/Analysis/InnerProductSpace/StarOrder.lean b/Mathlib/Analysis/InnerProductSpace/StarOrder.lean index 371413581895d..c41e46d241cad 100644 --- a/Mathlib/Analysis/InnerProductSpace/StarOrder.lean +++ b/Mathlib/Analysis/InnerProductSpace/StarOrder.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Analysis.InnerProductSpace.Positive -import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic import Mathlib.Analysis.CStarAlgebra.ContinuousLinearMap /-! From 15f16b1ec50f425147926be1aede7b4baa725380 Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Tue, 14 Jan 2025 03:50:37 +0000 Subject: [PATCH 219/681] chore: update Mathlib dependencies 2025-01-14 (#20726) This PR updates the Mathlib dependencies. --- lake-manifest.json | 4 ++-- lean-toolchain | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lake-manifest.json b/lake-manifest.json index efe399c199805..761d89f905070 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -25,7 +25,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "18d461b4acad559d6ec11ae42eeed0fe767e523b", + "rev": "f72319c9686788305a8ab059f3c4d8c724785c83", "name": "importGraph", "manifestFile": "lake-manifest.json", "inputRev": "main", @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "8690c0b6e759ab1a0c7e4287909ae5f897d3ab66", + "rev": "c104265c34eb8181af14e8dbc14c2f034292cb02", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", diff --git a/lean-toolchain b/lean-toolchain index 62ccd7170eb94..2ffc30ceba59b 100644 --- a/lean-toolchain +++ b/lean-toolchain @@ -1 +1 @@ -leanprover/lean4:v4.16.0-rc1 +leanprover/lean4:v4.16.0-rc2 \ No newline at end of file From 56f9c5ec3e4e97e78c743d0e589abd9f5e12d367 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 14 Jan 2025 04:13:36 +0000 Subject: [PATCH 220/681] feat: test the cache as if in a downstream project (#20532) Rather than just testing `lake exe cache get && lake build --no-build`, we run this test from a mini downstream project. Having this test in place would have alerted us to the problems in `v4.16.0-rc1` ahead of time. --- .github/build.in.yml | 8 +++++--- .github/workflows/bors.yml | 8 +++++--- .github/workflows/build.yml | 8 +++++--- .github/workflows/build_fork.yml | 8 +++++--- DownstreamTest/.gitignore | 3 +++ DownstreamTest/DownstreamTest.lean | 1 + DownstreamTest/README.md | 6 ++++++ DownstreamTest/lakefile.toml | 10 ++++++++++ 8 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 DownstreamTest/.gitignore create mode 100644 DownstreamTest/DownstreamTest.lean create mode 100644 DownstreamTest/README.md create mode 100644 DownstreamTest/lakefile.toml diff --git a/.github/build.in.yml b/.github/build.in.yml index c6392a395e227..4eb85a0b9604d 100644 --- a/.github/build.in.yml +++ b/.github/build.in.yml @@ -176,10 +176,12 @@ jobs: # Because the `lean-pr-testing-NNNN` branches use toolchains that are "updated in place" # the cache mechanism is unreliable, so we don't test it if we are on such a branch. if [[ ! $(cat lean-toolchain) =~ ^leanprover/lean4-pr-releases:pr-release-[0-9]+$ ]]; then - lake exe cache clean! - rm -rf .lake/build/lib/Mathlib + cd DownstreamTest + cp ../lean-toolchain . + MATHLIB_NO_CACHE_ON_UPDATE=1 lake update lake exe cache get || (sleep 1; lake exe cache get) - lake build --no-build + lake build Plausible ProofWidgets + lake build --no-build Mathlib fi - name: build archive diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index 9fbfeec9e2e21..fb5ff88ad3a1a 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -186,10 +186,12 @@ jobs: # Because the `lean-pr-testing-NNNN` branches use toolchains that are "updated in place" # the cache mechanism is unreliable, so we don't test it if we are on such a branch. if [[ ! $(cat lean-toolchain) =~ ^leanprover/lean4-pr-releases:pr-release-[0-9]+$ ]]; then - lake exe cache clean! - rm -rf .lake/build/lib/Mathlib + cd DownstreamTest + cp ../lean-toolchain . + MATHLIB_NO_CACHE_ON_UPDATE=1 lake update lake exe cache get || (sleep 1; lake exe cache get) - lake build --no-build + lake build Plausible ProofWidgets + lake build --no-build Mathlib fi - name: build archive diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca2af1df663fc..10dec2ea56665 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -193,10 +193,12 @@ jobs: # Because the `lean-pr-testing-NNNN` branches use toolchains that are "updated in place" # the cache mechanism is unreliable, so we don't test it if we are on such a branch. if [[ ! $(cat lean-toolchain) =~ ^leanprover/lean4-pr-releases:pr-release-[0-9]+$ ]]; then - lake exe cache clean! - rm -rf .lake/build/lib/Mathlib + cd DownstreamTest + cp ../lean-toolchain . + MATHLIB_NO_CACHE_ON_UPDATE=1 lake update lake exe cache get || (sleep 1; lake exe cache get) - lake build --no-build + lake build Plausible ProofWidgets + lake build --no-build Mathlib fi - name: build archive diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index a0f4d80a41155..b2ee7842e042e 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -190,10 +190,12 @@ jobs: # Because the `lean-pr-testing-NNNN` branches use toolchains that are "updated in place" # the cache mechanism is unreliable, so we don't test it if we are on such a branch. if [[ ! $(cat lean-toolchain) =~ ^leanprover/lean4-pr-releases:pr-release-[0-9]+$ ]]; then - lake exe cache clean! - rm -rf .lake/build/lib/Mathlib + cd DownstreamTest + cp ../lean-toolchain . + MATHLIB_NO_CACHE_ON_UPDATE=1 lake update lake exe cache get || (sleep 1; lake exe cache get) - lake build --no-build + lake build Plausible ProofWidgets + lake build --no-build Mathlib fi - name: build archive diff --git a/DownstreamTest/.gitignore b/DownstreamTest/.gitignore new file mode 100644 index 0000000000000..64729f11321a9 --- /dev/null +++ b/DownstreamTest/.gitignore @@ -0,0 +1,3 @@ +/.lake +lean-toolchain +lake-manifest.json diff --git a/DownstreamTest/DownstreamTest.lean b/DownstreamTest/DownstreamTest.lean new file mode 100644 index 0000000000000..0b4be76b1d496 --- /dev/null +++ b/DownstreamTest/DownstreamTest.lean @@ -0,0 +1 @@ +import Mathlib diff --git a/DownstreamTest/README.md b/DownstreamTest/README.md new file mode 100644 index 0000000000000..c9037e7cda1b6 --- /dev/null +++ b/DownstreamTest/README.md @@ -0,0 +1,6 @@ +# DownstreamTest + +This directory is used for testing that a basic downstream project can be built using mathlib, +and that the mathlib cache works. + +There is no `lean-toolchain` file, because CI will copy it from the main repo during testing. diff --git a/DownstreamTest/lakefile.toml b/DownstreamTest/lakefile.toml new file mode 100644 index 0000000000000..300b627bb63db --- /dev/null +++ b/DownstreamTest/lakefile.toml @@ -0,0 +1,10 @@ +name = "DownstreamTest" +version = "0.1.0" +defaultTargets = ["DownstreamTest"] + +[[require]] +name = "mathlib" +path = "../" + +[[lean_lib]] +name = "DownstreamTest" From c083085d05d098ff6bae992740c6d7eadf1c4cf1 Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Tue, 14 Jan 2025 06:06:33 +0000 Subject: [PATCH 221/681] refactor(FieldTheory/KummerExtension): Split off irreducibility of `X ^ p - a` (#20695) This PR splits of irreducibility of `X ^ p - a` from `FieldTheory/KummerExtension` since it has lighter imports and can be used to golf a proof in `FieldTheory/Perfect`. Co-authored-by: Thomas Browning --- Mathlib.lean | 1 + Mathlib/FieldTheory/KummerExtension.lean | 103 +----------------- Mathlib/FieldTheory/KummerPolynomial.lean | 124 ++++++++++++++++++++++ Mathlib/FieldTheory/Perfect.lean | 38 ++----- 4 files changed, 135 insertions(+), 131 deletions(-) create mode 100644 Mathlib/FieldTheory/KummerPolynomial.lean diff --git a/Mathlib.lean b/Mathlib.lean index dadcd0fcb5789..25bf80ea4e45a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3103,6 +3103,7 @@ import Mathlib.FieldTheory.Isaacs import Mathlib.FieldTheory.JacobsonNoether import Mathlib.FieldTheory.KrullTopology import Mathlib.FieldTheory.KummerExtension +import Mathlib.FieldTheory.KummerPolynomial import Mathlib.FieldTheory.Laurent import Mathlib.FieldTheory.LinearDisjoint import Mathlib.FieldTheory.Minpoly.Basic diff --git a/Mathlib/FieldTheory/KummerExtension.lean b/Mathlib/FieldTheory/KummerExtension.lean index fee360c7fd681..50462a0390dac 100644 --- a/Mathlib/FieldTheory/KummerExtension.lean +++ b/Mathlib/FieldTheory/KummerExtension.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.RingTheory.RootsOfUnity.PrimitiveRoots -import Mathlib.RingTheory.AdjoinRoot import Mathlib.FieldTheory.Galois.Basic +import Mathlib.FieldTheory.KummerPolynomial import Mathlib.LinearAlgebra.Eigenspace.Minpoly import Mathlib.RingTheory.Norm.Basic /-! @@ -31,8 +31,6 @@ then isomorphic to `Multiplicative (ZMod n)` whose inverse is given by ## Other results Criteria for `X ^ n - C a` to be irreducible is given: -- `X_pow_sub_C_irreducible_iff_of_prime`: - For `n = p` a prime, `X ^ n - C a` is irreducible iff `a` is not a `p`-power. - `X_pow_sub_C_irreducible_iff_of_prime_pow`: For `n = p ^ k` an odd prime power, `X ^ n - C a` is irreducible iff `a` is not a `p`-power. - `X_pow_sub_C_irreducible_iff_forall_prime_of_odd`: @@ -51,26 +49,6 @@ open Polynomial IntermediateField AdjoinRoot section Splits -lemma root_X_pow_sub_C_pow (n : ℕ) (a : K) : - (AdjoinRoot.root (X ^ n - C a)) ^ n = AdjoinRoot.of _ a := by - rw [← sub_eq_zero, ← AdjoinRoot.eval₂_root, eval₂_sub, eval₂_C, eval₂_pow, eval₂_X] - -lemma root_X_pow_sub_C_ne_zero {n : ℕ} (hn : 1 < n) (a : K) : - (AdjoinRoot.root (X ^ n - C a)) ≠ 0 := - mk_ne_zero_of_natDegree_lt (monic_X_pow_sub_C _ (Nat.not_eq_zero_of_lt hn)) - X_ne_zero <| by rwa [natDegree_X_pow_sub_C, natDegree_X] - -lemma root_X_pow_sub_C_ne_zero' {n : ℕ} {a : K} (hn : 0 < n) (ha : a ≠ 0) : - (AdjoinRoot.root (X ^ n - C a)) ≠ 0 := by - obtain (rfl|hn) := (Nat.succ_le_iff.mpr hn).eq_or_lt - · rw [pow_one] - intro e - refine mk_ne_zero_of_natDegree_lt (monic_X_sub_C a) (C_ne_zero.mpr ha) (by simp) ?_ - trans AdjoinRoot.mk (X - C a) (X - (X - C a)) - · rw [sub_sub_cancel] - · rw [map_sub, mk_self, sub_zero, mk_X, e] - · exact root_X_pow_sub_C_ne_zero hn a - theorem X_pow_sub_C_splits_of_isPrimitiveRoot {n : ℕ} {ζ : K} (hζ : IsPrimitiveRoot ζ n) {α a : K} (e : α ^ n = a) : (X ^ n - C a).Splits (RingHom.id _) := by @@ -105,85 +83,6 @@ end Splits section Irreducible -lemma ne_zero_of_irreducible_X_pow_sub_C {n : ℕ} {a : K} (H : Irreducible (X ^ n - C a)) : - n ≠ 0 := by - rintro rfl - rw [pow_zero, ← C.map_one, ← map_sub] at H - exact not_irreducible_C _ H - -lemma ne_zero_of_irreducible_X_pow_sub_C' {n : ℕ} (hn : n ≠ 1) {a : K} - (H : Irreducible (X ^ n - C a)) : a ≠ 0 := by - rintro rfl - rw [map_zero, sub_zero] at H - exact not_irreducible_pow hn H - -lemma root_X_pow_sub_C_eq_zero_iff {n : ℕ} {a : K} (H : Irreducible (X ^ n - C a)) : - (AdjoinRoot.root (X ^ n - C a)) = 0 ↔ a = 0 := by - have hn := Nat.pos_iff_ne_zero.mpr (ne_zero_of_irreducible_X_pow_sub_C H) - refine ⟨not_imp_not.mp (root_X_pow_sub_C_ne_zero' hn), ?_⟩ - rintro rfl - have := not_imp_not.mp (fun hn ↦ ne_zero_of_irreducible_X_pow_sub_C' hn H) rfl - rw [this, pow_one, map_zero, sub_zero, ← mk_X, mk_self] - -lemma root_X_pow_sub_C_ne_zero_iff {n : ℕ} {a : K} (H : Irreducible (X ^ n - C a)) : - (AdjoinRoot.root (X ^ n - C a)) ≠ 0 ↔ a ≠ 0 := - (root_X_pow_sub_C_eq_zero_iff H).not - -theorem pow_ne_of_irreducible_X_pow_sub_C {n : ℕ} {a : K} - (H : Irreducible (X ^ n - C a)) {m : ℕ} (hm : m ∣ n) (hm' : m ≠ 1) (b : K) : b ^ m ≠ a := by - have hn : n ≠ 0 := fun e ↦ not_irreducible_C - (1 - a) (by simpa only [e, pow_zero, ← C.map_one, ← map_sub] using H) - obtain ⟨k, rfl⟩ := hm - rintro rfl - obtain ⟨q, hq⟩ := sub_dvd_pow_sub_pow (X ^ k) (C b) m - rw [mul_comm, pow_mul, map_pow, hq] at H - have : degree q = 0 := by - simpa [isUnit_iff_degree_eq_zero, degree_X_pow_sub_C, - Nat.pos_iff_ne_zero, (mul_ne_zero_iff.mp hn).2] using H.2 _ q rfl - apply_fun degree at hq - simp only [this, ← pow_mul, mul_comm k m, degree_X_pow_sub_C, Nat.pos_iff_ne_zero.mpr hn, - Nat.pos_iff_ne_zero.mpr (mul_ne_zero_iff.mp hn).2, degree_mul, ← map_pow, add_zero, - Nat.cast_injective.eq_iff] at hq - exact hm' ((mul_eq_right₀ (mul_ne_zero_iff.mp hn).2).mp hq) - -/--Let `p` be a prime number. Let `K` be a field. -Let `t ∈ K` be an element which does not have a `p`th root in `K`. -Then the polynomial `x ^ p - t` is irreducible over `K`.-/ -@[stacks 09HF "We proved the result without the condition that `K` is char p in 09HF."] -theorem X_pow_sub_C_irreducible_of_prime {p : ℕ} (hp : p.Prime) {a : K} (ha : ∀ b : K, b ^ p ≠ a) : - Irreducible (X ^ p - C a) := by - -- First of all, We may find an irreducible factor `g` of `X ^ p - C a`. - have : ¬ IsUnit (X ^ p - C a) := by - rw [Polynomial.isUnit_iff_degree_eq_zero, degree_X_pow_sub_C hp.pos, Nat.cast_eq_zero] - exact hp.ne_zero - have ⟨g, hg, hg'⟩ := WfDvdMonoid.exists_irreducible_factor this (X_pow_sub_C_ne_zero hp.pos a) - -- It suffices to show that `deg g = p`. - suffices natDegree g = p from (associated_of_dvd_of_natDegree_le hg' - (X_pow_sub_C_ne_zero hp.pos a) (this.trans natDegree_X_pow_sub_C.symm).ge).irreducible hg - -- Suppose `deg g ≠ p`. - by_contra h - have : Fact (Irreducible g) := ⟨hg⟩ - -- Let `r` be a root of `g`, then `N_K(r) ^ p = N_K(r ^ p) = N_K(a) = a ^ (deg g)`. - have key : (Algebra.norm K (AdjoinRoot.root g)) ^ p = a ^ g.natDegree := by - have := eval₂_eq_zero_of_dvd_of_eval₂_eq_zero _ _ hg' (AdjoinRoot.eval₂_root g) - rw [eval₂_sub, eval₂_pow, eval₂_C, eval₂_X, sub_eq_zero] at this - rw [← map_pow, this, ← AdjoinRoot.algebraMap_eq, Algebra.norm_algebraMap, - ← finrank_top', ← IntermediateField.adjoin_root_eq_top g, - IntermediateField.adjoin.finrank, - AdjoinRoot.minpoly_root hg.ne_zero, natDegree_mul_C] - · simpa using hg.ne_zero - · exact AdjoinRoot.isIntegral_root hg.ne_zero - -- Since `a ^ (deg g)` is a `p`-power, and `p` is coprime to `deg g`, we conclude that `a` is - -- also a `p`-power, contradicting the hypothesis - have : p.Coprime (natDegree g) := hp.coprime_iff_not_dvd.mpr (fun e ↦ h (((natDegree_le_of_dvd hg' - (X_pow_sub_C_ne_zero hp.pos a)).trans_eq natDegree_X_pow_sub_C).antisymm (Nat.le_of_dvd - (natDegree_pos_iff_degree_pos.mpr <| Polynomial.degree_pos_of_irreducible hg) e))) - exact ha _ ((pow_mem_range_pow_of_coprime this.symm a).mp ⟨_, key⟩).choose_spec - -theorem X_pow_sub_C_irreducible_iff_of_prime {p : ℕ} (hp : p.Prime) {a : K} : - Irreducible (X ^ p - C a) ↔ ∀ b, b ^ p ≠ a := - ⟨(pow_ne_of_irreducible_X_pow_sub_C · dvd_rfl hp.ne_one), X_pow_sub_C_irreducible_of_prime hp⟩ - theorem X_pow_mul_sub_C_irreducible {n m : ℕ} {a : K} (hm : Irreducible (X ^ m - C a)) (hn : ∀ (E : Type u) [Field E] [Algebra K E] (x : E) (_ : minpoly K x = X ^ m - C a), diff --git a/Mathlib/FieldTheory/KummerPolynomial.lean b/Mathlib/FieldTheory/KummerPolynomial.lean new file mode 100644 index 0000000000000..a792e3376dba9 --- /dev/null +++ b/Mathlib/FieldTheory/KummerPolynomial.lean @@ -0,0 +1,124 @@ +/- +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.AdjoinRoot +import Mathlib.RingTheory.Norm.Defs +/-! +# Irreducibility of X ^ p - a + +## Main result +- `X_pow_sub_C_irreducible_iff_of_prime`: For `p` prime, `X ^ p - C a` is irreducible iff `a` is not + a `p`-power. This is not true for composite `n`. For example, `x^4+4=(x^2-2x+2)(x^2+2x+2)` but + `-4` is not a 4th power. + +-/ +universe u + +variable {K : Type u} [Field K] + +open Polynomial AdjoinRoot + +section Splits + +lemma root_X_pow_sub_C_pow (n : ℕ) (a : K) : + (AdjoinRoot.root (X ^ n - C a)) ^ n = AdjoinRoot.of _ a := by + rw [← sub_eq_zero, ← AdjoinRoot.eval₂_root, eval₂_sub, eval₂_C, eval₂_pow, eval₂_X] + +lemma root_X_pow_sub_C_ne_zero {n : ℕ} (hn : 1 < n) (a : K) : + (AdjoinRoot.root (X ^ n - C a)) ≠ 0 := + mk_ne_zero_of_natDegree_lt (monic_X_pow_sub_C _ (Nat.not_eq_zero_of_lt hn)) + X_ne_zero <| by rwa [natDegree_X_pow_sub_C, natDegree_X] + +lemma root_X_pow_sub_C_ne_zero' {n : ℕ} {a : K} (hn : 0 < n) (ha : a ≠ 0) : + (AdjoinRoot.root (X ^ n - C a)) ≠ 0 := by + obtain (rfl|hn) := (Nat.succ_le_iff.mpr hn).eq_or_lt + · rw [pow_one] + intro e + refine mk_ne_zero_of_natDegree_lt (monic_X_sub_C a) (C_ne_zero.mpr ha) (by simp) ?_ + trans AdjoinRoot.mk (X - C a) (X - (X - C a)) + · rw [sub_sub_cancel] + · rw [map_sub, mk_self, sub_zero, mk_X, e] + · exact root_X_pow_sub_C_ne_zero hn a + +end Splits + +section Irreducible + +lemma ne_zero_of_irreducible_X_pow_sub_C {n : ℕ} {a : K} (H : Irreducible (X ^ n - C a)) : + n ≠ 0 := by + rintro rfl + rw [pow_zero, ← C.map_one, ← map_sub] at H + exact not_irreducible_C _ H + +lemma ne_zero_of_irreducible_X_pow_sub_C' {n : ℕ} (hn : n ≠ 1) {a : K} + (H : Irreducible (X ^ n - C a)) : a ≠ 0 := by + rintro rfl + rw [map_zero, sub_zero] at H + exact not_irreducible_pow hn H + +lemma root_X_pow_sub_C_eq_zero_iff {n : ℕ} {a : K} (H : Irreducible (X ^ n - C a)) : + (AdjoinRoot.root (X ^ n - C a)) = 0 ↔ a = 0 := by + have hn := Nat.pos_iff_ne_zero.mpr (ne_zero_of_irreducible_X_pow_sub_C H) + refine ⟨not_imp_not.mp (root_X_pow_sub_C_ne_zero' hn), ?_⟩ + rintro rfl + have := not_imp_not.mp (fun hn ↦ ne_zero_of_irreducible_X_pow_sub_C' hn H) rfl + rw [this, pow_one, map_zero, sub_zero, ← mk_X, mk_self] + +lemma root_X_pow_sub_C_ne_zero_iff {n : ℕ} {a : K} (H : Irreducible (X ^ n - C a)) : + (AdjoinRoot.root (X ^ n - C a)) ≠ 0 ↔ a ≠ 0 := + (root_X_pow_sub_C_eq_zero_iff H).not + +theorem pow_ne_of_irreducible_X_pow_sub_C {n : ℕ} {a : K} + (H : Irreducible (X ^ n - C a)) {m : ℕ} (hm : m ∣ n) (hm' : m ≠ 1) (b : K) : b ^ m ≠ a := by + have hn : n ≠ 0 := fun e ↦ not_irreducible_C + (1 - a) (by simpa only [e, pow_zero, ← C.map_one, ← map_sub] using H) + obtain ⟨k, rfl⟩ := hm + rintro rfl + obtain ⟨q, hq⟩ := sub_dvd_pow_sub_pow (X ^ k) (C b) m + rw [mul_comm, pow_mul, map_pow, hq] at H + have : degree q = 0 := by + simpa [isUnit_iff_degree_eq_zero, degree_X_pow_sub_C, + Nat.pos_iff_ne_zero, (mul_ne_zero_iff.mp hn).2] using H.2 _ q rfl + apply_fun degree at hq + simp only [this, ← pow_mul, mul_comm k m, degree_X_pow_sub_C, Nat.pos_iff_ne_zero.mpr hn, + Nat.pos_iff_ne_zero.mpr (mul_ne_zero_iff.mp hn).2, degree_mul, ← map_pow, add_zero, + Nat.cast_injective.eq_iff] at hq + exact hm' ((mul_eq_right₀ (mul_ne_zero_iff.mp hn).2).mp hq) + +/--Let `p` be a prime number. Let `K` be a field. +Let `t ∈ K` be an element which does not have a `p`th root in `K`. +Then the polynomial `x ^ p - t` is irreducible over `K`.-/ +@[stacks 09HF "We proved the result without the condition that `K` is char p in 09HF."] +theorem X_pow_sub_C_irreducible_of_prime {p : ℕ} (hp : p.Prime) {a : K} (ha : ∀ b : K, b ^ p ≠ a) : + Irreducible (X ^ p - C a) := by + -- First of all, We may find an irreducible factor `g` of `X ^ p - C a`. + have : ¬ IsUnit (X ^ p - C a) := by + rw [Polynomial.isUnit_iff_degree_eq_zero, degree_X_pow_sub_C hp.pos, Nat.cast_eq_zero] + exact hp.ne_zero + have ⟨g, hg, hg'⟩ := WfDvdMonoid.exists_irreducible_factor this (X_pow_sub_C_ne_zero hp.pos a) + -- It suffices to show that `deg g = p`. + suffices natDegree g = p from (associated_of_dvd_of_natDegree_le hg' + (X_pow_sub_C_ne_zero hp.pos a) (this.trans natDegree_X_pow_sub_C.symm).ge).irreducible hg + -- Suppose `deg g ≠ p`. + by_contra h + have : Fact (Irreducible g) := ⟨hg⟩ + -- Let `r` be a root of `g`, then `N_K(r) ^ p = N_K(r ^ p) = N_K(a) = a ^ (deg g)`. + have key : (Algebra.norm K (AdjoinRoot.root g)) ^ p = a ^ g.natDegree := by + have := eval₂_eq_zero_of_dvd_of_eval₂_eq_zero _ _ hg' (AdjoinRoot.eval₂_root g) + rw [eval₂_sub, eval₂_pow, eval₂_C, eval₂_X, sub_eq_zero] at this + rw [← map_pow, this, ← AdjoinRoot.algebraMap_eq, Algebra.norm_algebraMap, + (powerBasis hg.ne_zero).finrank, powerBasis_dim hg.ne_zero] + -- Since `a ^ (deg g)` is a `p`-power, and `p` is coprime to `deg g`, we conclude that `a` is + -- also a `p`-power, contradicting the hypothesis + have : p.Coprime (natDegree g) := hp.coprime_iff_not_dvd.mpr (fun e ↦ h (((natDegree_le_of_dvd hg' + (X_pow_sub_C_ne_zero hp.pos a)).trans_eq natDegree_X_pow_sub_C).antisymm (Nat.le_of_dvd + (natDegree_pos_iff_degree_pos.mpr <| Polynomial.degree_pos_of_irreducible hg) e))) + exact ha _ ((pow_mem_range_pow_of_coprime this.symm a).mp ⟨_, key⟩).choose_spec + +theorem X_pow_sub_C_irreducible_iff_of_prime {p : ℕ} (hp : p.Prime) {a : K} : + Irreducible (X ^ p - C a) ↔ ∀ b, b ^ p ≠ a := + ⟨(pow_ne_of_irreducible_X_pow_sub_C · dvd_rfl hp.ne_one), X_pow_sub_C_irreducible_of_prime hp⟩ + +end Irreducible diff --git a/Mathlib/FieldTheory/Perfect.lean b/Mathlib/FieldTheory/Perfect.lean index 0a28f720b8a0c..0fd5aec0f0789 100644 --- a/Mathlib/FieldTheory/Perfect.lean +++ b/Mathlib/FieldTheory/Perfect.lean @@ -5,8 +5,8 @@ Authors: Oliver Nash -/ import Mathlib.Algebra.CharP.Basic import Mathlib.Algebra.CharP.Reduced +import Mathlib.FieldTheory.KummerPolynomial import Mathlib.FieldTheory.Separable -import Mathlib.FieldTheory.SplittingField.Construction /-! @@ -203,35 +203,15 @@ instance ofFinite [Finite K] : PerfectField K := by variable [PerfectField K] /-- A perfect field of characteristic `p` (prime) is a perfect ring. -/ -instance toPerfectRing (p : ℕ) [ExpChar K p] : PerfectRing K p := by +instance toPerfectRing (p : ℕ) [hp : ExpChar K p] : PerfectRing K p := by refine PerfectRing.ofSurjective _ _ fun y ↦ ?_ - let f : K[X] := X ^ p - C y - let L := f.SplittingField - let ι := algebraMap K L - have hf_deg : f.degree ≠ 0 := by - rw [degree_X_pow_sub_C (expChar_pos K p) y, p.cast_ne_zero]; exact (expChar_pos K p).ne' - let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg - have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg] - have ha_pow : a ^ p = ι y := by rwa [map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa - let g : K[X] := minpoly K a - suffices (g.map ι).natDegree = 1 by - rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this - obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this - refine ⟨a', NoZeroSMulDivisors.algebraMap_injective K L ?_⟩ - rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow] - have hg_dvd : g.map ι ∣ (X - C a) ^ p := by - convert Polynomial.map_dvd ι (minpoly.dvd K a hfa) - rw [sub_pow_expChar, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow] - have ha : IsIntegral K a := .of_finite K a - have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by - obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd - rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq, - natDegree_pow, natDegree_X_sub_C, mul_one] - have hg_sep : (g.map ι).Separable := (separable_of_irreducible <| minpoly.irreducible ha).map - rw [hg_pow] at hg_sep - refine (Separable.of_pow (not_isUnit_X_sub_C a) ?_ hg_sep).2 - rw [g.natDegree_map ι, ← Nat.pos_iff_ne_zero, natDegree_pos_iff_degree_pos] - exact minpoly.degree_pos ha + rcases hp with _ | hp + · simp [frobenius] + rw [← not_forall_not] + apply mt (X_pow_sub_C_irreducible_of_prime hp) + apply mt separable_of_irreducible + simp [separable_def, isCoprime_zero_right, isUnit_iff_degree_eq_zero, + degree_X_pow_sub_C hp.pos, hp.ne_zero] theorem separable_iff_squarefree {g : K[X]} : g.Separable ↔ Squarefree g := by refine ⟨Separable.squarefree, fun sqf ↦ isCoprime_of_irreducible_dvd (sqf.ne_zero ·.1) ?_⟩ From 9c0bf76ac298a4b44d6fc4cfc595a4d49f9b0289 Mon Sep 17 00:00:00 2001 From: Scott Carnahan <128885296+ScottCarnahan@users.noreply.github.com> Date: Tue, 14 Jan 2025 07:17:35 +0000 Subject: [PATCH 222/681] feat(Algebra/Lie): Define Lie algebra extensions (#20206) This PR defines extensions of Lie algebras. We follow the pattern used in defining extensions of groups. --- Mathlib.lean | 1 + Mathlib/Algebra/Lie/Extension.lean | 70 ++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 Mathlib/Algebra/Lie/Extension.lean diff --git a/Mathlib.lean b/Mathlib.lean index 25bf80ea4e45a..be92270eab6ee 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -509,6 +509,7 @@ import Mathlib.Algebra.Lie.Derivation.Killing import Mathlib.Algebra.Lie.DirectSum import Mathlib.Algebra.Lie.Engel import Mathlib.Algebra.Lie.EngelSubalgebra +import Mathlib.Algebra.Lie.Extension import Mathlib.Algebra.Lie.Free import Mathlib.Algebra.Lie.IdealOperations import Mathlib.Algebra.Lie.InvariantForm diff --git a/Mathlib/Algebra/Lie/Extension.lean b/Mathlib/Algebra/Lie/Extension.lean new file mode 100644 index 0000000000000..7c5d58a296609 --- /dev/null +++ b/Mathlib/Algebra/Lie/Extension.lean @@ -0,0 +1,70 @@ +/- +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.Algebra.Lie.Submodule + +/-! +# Extensions of Lie algebras +This file defines extensions of Lie algebras, given by short exact sequences of Lie algebra +homomorphisms. They are implemented in two ways: `IsExtension` is a `Prop`-valued class taking two +homomorphisms as parameters, and `Extension` is a structure that includes the middle Lie algebra. + +## Main definitions + * `LieAlgebra.IsExtension`: A `Prop`-valued class characterizing an extension of Lie algebras. + * `LieAlgebra.Extension`: A bundled structure giving an extension of Lie algebras. + * `LieAlgebra.IsExtension.extension`: A function that builds the bundled structure from the class. + +## TODO + * `IsCentral` - central extensions + * `Equiv` - equivalence of extensions + * `ofTwoCocycle` - construction of extensions from 2-cocycles + +## References +* [N. Bourbaki, *Lie Groups and Lie Algebras, Chapters 1--3*](bourbaki1975) + +-/ + +namespace LieAlgebra + +variable {R N L M : Type*} + +variable [CommRing R] [LieRing L] [LieAlgebra R L] [LieRing N] [LieAlgebra R N] [LieRing M] + [LieAlgebra R M] + +/-- A sequence of two Lie algebra homomorphisms is an extension if it is short exact. -/ +class IsExtension (i : N →ₗ⁅R⁆ L) (p : L →ₗ⁅R⁆ M) : Prop where + ker_eq_bot : i.ker = ⊥ + range_eq_top : p.range = ⊤ + exact : i.range = p.ker + +variable (R N M) in +/-- The type of all Lie extensions of `M` by `N`. That is, short exact sequences of `R`-Lie algebra +homomorphisms `0 → N → L → M → 0` where `R`, `M`, and `N` are fixed. -/ +structure Extension where + /-- The middle object in the sequence. -/ + L : Type* + /-- `L` is a Lie ring. -/ + instLieRing : LieRing L + /-- `L` is a Lie algebra over `R`. -/ + instLieAlgebra : LieAlgebra R L + /-- The inclusion homomorphism `N →ₗ⁅R⁆ L` -/ + incl : N →ₗ⁅R⁆ L + /-- The projection homomorphism `L →ₗ⁅R⁆ M` -/ + proj : L →ₗ⁅R⁆ M + IsExtension : IsExtension incl proj + +/-- The bundled `LieAlgebra.Extension` corresponding to `LieAlgebra.IsExtension` -/ +@[simps] def IsExtension.extension {i : N →ₗ⁅R⁆ L} {p : L →ₗ⁅R⁆ M} (h : IsExtension i p) : + Extension R N M := + ⟨L, _, _, i, p, h⟩ + +/-- A surjective Lie algebra homomorphism yields an extension. -/ +theorem isExtension_of_surjective (f : L →ₗ⁅R⁆ M) (hf : Function.Surjective f) : + IsExtension f.ker.incl f where + ker_eq_bot := LieIdeal.ker_incl f.ker + range_eq_top := (LieHom.range_eq_top f).mpr hf + exact := LieIdeal.incl_range f.ker + +end LieAlgebra From d2729325b0f8d06d3cf6e8a4e62f149aa93a08c4 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Tue, 14 Jan 2025 08:30:23 +0000 Subject: [PATCH 223/681] chore: move import of `Tactic.Common` downstream from `Pairwise` (#20710) Spotted in the late importers report: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Late.20importers.20report/near/493286162 `Logic.Pairwise` imports `Tactic.Common` but doesn't actually use anything from this file. By moving the import further downstream, we can clean up the hierarchy somewhat. --- Mathlib/Algebra/Order/Interval/Set/Group.lean | 1 + Mathlib/Data/Set/Lattice.lean | 1 + Mathlib/Data/Set/Pairwise/Basic.lean | 1 + Mathlib/GroupTheory/OreLocalization/Basic.lean | 1 + Mathlib/Logic/Pairwise.lean | 1 - Mathlib/Tactic/DeriveCountable.lean | 1 + 6 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Order/Interval/Set/Group.lean b/Mathlib/Algebra/Order/Interval/Set/Group.lean index 185f1f2c53353..74957b1640241 100644 --- a/Mathlib/Algebra/Order/Interval/Set/Group.lean +++ b/Mathlib/Algebra/Order/Interval/Set/Group.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.Order.Group.Basic import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Order.Interval.Set.Basic import Mathlib.Logic.Pairwise +import Mathlib.Tactic.Cases /-! ### Lemmas about arithmetic operations and intervals. -/ diff --git a/Mathlib/Data/Set/Lattice.lean b/Mathlib/Data/Set/Lattice.lean index 31894eed4fc4a..0a1edf84d64c4 100644 --- a/Mathlib/Data/Set/Lattice.lean +++ b/Mathlib/Data/Set/Lattice.lean @@ -7,6 +7,7 @@ import Mathlib.Logic.Pairwise import Mathlib.Order.CompleteBooleanAlgebra import Mathlib.Order.Directed import Mathlib.Order.GaloisConnection +import Mathlib.Tactic.Cases /-! # The set lattice diff --git a/Mathlib/Data/Set/Pairwise/Basic.lean b/Mathlib/Data/Set/Pairwise/Basic.lean index 0f0dfb0f03b60..8908611b7a7bd 100644 --- a/Mathlib/Data/Set/Pairwise/Basic.lean +++ b/Mathlib/Data/Set/Pairwise/Basic.lean @@ -6,6 +6,7 @@ Authors: Johannes Hölzl import Mathlib.Data.Set.Function import Mathlib.Logic.Pairwise import Mathlib.Logic.Relation +import Mathlib.Tactic.Cases /-! # Relations holding pairwise diff --git a/Mathlib/GroupTheory/OreLocalization/Basic.lean b/Mathlib/GroupTheory/OreLocalization/Basic.lean index 135848a6b63f3..24b43521f550b 100644 --- a/Mathlib/GroupTheory/OreLocalization/Basic.lean +++ b/Mathlib/GroupTheory/OreLocalization/Basic.lean @@ -5,6 +5,7 @@ Authors: Jakob von Raumer, Kevin Klinge, Andrew Yang -/ import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.GroupTheory.OreLocalization.OreSet +import Mathlib.Tactic.Common /-! diff --git a/Mathlib/Logic/Pairwise.lean b/Mathlib/Logic/Pairwise.lean index 13ae772203bbe..ba62702441eb9 100644 --- a/Mathlib/Logic/Pairwise.lean +++ b/Mathlib/Logic/Pairwise.lean @@ -5,7 +5,6 @@ Authors: Johannes Hölzl -/ import Mathlib.Logic.Function.Basic import Mathlib.Data.Set.Defs -import Mathlib.Tactic.Common /-! # Relations holding pairwise diff --git a/Mathlib/Tactic/DeriveCountable.lean b/Mathlib/Tactic/DeriveCountable.lean index 9b15d1388f40a..e248d768f7eeb 100644 --- a/Mathlib/Tactic/DeriveCountable.lean +++ b/Mathlib/Tactic/DeriveCountable.lean @@ -7,6 +7,7 @@ import Lean.Meta.Transform import Lean.Meta.Inductive import Lean.Elab.Deriving.Basic import Lean.Elab.Deriving.Util +import Batteries.Data.NameSet import Mathlib.Data.Countable.Defs import Mathlib.Data.Nat.Pairing From ed1d44ffe1d3eb1ca29f5284fe9de5cae7de9099 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 14 Jan 2025 09:10:18 +0000 Subject: [PATCH 224/681] chore: remove --loc flag from unused_in_pole.sh (#20729) When developing `unused_in_pole.sh`, the Speed Center was broken, so I used the `--loc` flag to compute the longest pole according to lines of code rather than instruction counts. Let's remove it again, as I think instructions are more useful, and that's what we usually do when looking at the longest pole. --- scripts/unused_in_pole.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/unused_in_pole.sh b/scripts/unused_in_pole.sh index 89d0761515351..2c8a7d7d9e808 100755 --- a/scripts/unused_in_pole.sh +++ b/scripts/unused_in_pole.sh @@ -11,4 +11,4 @@ # Default to Mathlib if no argument is provided target=${1:-Mathlib} -lake exe pole --loc --to $target | tail -n +3 | cut -f2 -d '|' | awk '{$1=$1; print}' | grep -v "Lean\." | grep -v "Init\." | grep -v "Tactic\." | grep -v "^Mathlib$" | grep -v "^Mathlib.Init$" | xargs lake exe unused +lake exe pole --to $target | tail -n +3 | cut -f2 -d '|' | awk '{$1=$1; print}' | grep -v "Lean\." | grep -v "Init\." | grep -v "Tactic\." | grep -v "^Mathlib$" | grep -v "^Mathlib.Init$" | xargs lake exe unused From 2a6c3d024da2695fe3dc592c6f746a2ed7e2df2d Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Tue, 14 Jan 2025 09:33:15 +0000 Subject: [PATCH 225/681] chore(RingTheory/MvPolynomial/WeightedHomogeneous): golf the proof a lemma (#20697) This simplifies a proof. --- .../RingTheory/MvPolynomial/WeightedHomogeneous.lean | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean index c0b99872fcf13..4d479bb19e431 100644 --- a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean @@ -359,16 +359,11 @@ theorem weightedHomogeneousComponent_eq_zero [SemilatticeSup M] [OrderBot M] theorem weightedHomogeneousComponent_finsupp : (Function.support fun m => weightedHomogeneousComponent w m φ).Finite := by - suffices - (Function.support fun m => weightedHomogeneousComponent w m φ) ⊆ - (fun d => weight w d) '' φ.support by - exact Finite.subset ((fun d : σ →₀ ℕ => (weight w) d) '' ↑(support φ)).toFinite this + apply Finite.subset ((fun d : σ →₀ ℕ => (weight w) d) '' (φ.support : Set (σ →₀ ℕ))).toFinite intro m hm by_contra hm' - apply hm - simp only [mem_support, Ne] at hm - simp only [Set.mem_image, not_exists, not_and] at hm' - exact weightedHomogeneousComponent_eq_zero' m φ hm' + apply hm (weightedHomogeneousComponent_eq_zero' m φ _) + simpa only [Set.mem_image, not_exists, not_and] using hm' variable (w) From a7b5e89018c3880ed1610530327aeb1ff9ac7b2c Mon Sep 17 00:00:00 2001 From: sgouezel Date: Tue, 14 Jan 2025 09:42:57 +0000 Subject: [PATCH 226/681] chore: remove useless assumption in `ae_restrict_le` (#20732) --- Mathlib/MeasureTheory/Measure/Restrict.lean | 4 ++-- Mathlib/Probability/Kernel/Condexp.lean | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Mathlib/MeasureTheory/Measure/Restrict.lean b/Mathlib/MeasureTheory/Measure/Restrict.lean index cfbce99dab3ec..9e089cff69ae1 100644 --- a/Mathlib/MeasureTheory/Measure/Restrict.lean +++ b/Mathlib/MeasureTheory/Measure/Restrict.lean @@ -648,8 +648,8 @@ theorem ae_restrict_eq (hs : MeasurableSet s) : ae (μ.restrict s) = ae μ ⊓ Classical.not_imp, fun a => and_comm (a := a ∈ s) (b := ¬a ∈ t)] rfl -lemma ae_restrict_le (hs : MeasurableSet s) : ae (μ.restrict s) ≤ ae μ := - ae_restrict_eq hs ▸ inf_le_left +lemma ae_restrict_le : ae (μ.restrict s) ≤ ae μ := + ae_mono restrict_le_self theorem ae_restrict_eq_bot {s} : ae (μ.restrict s) = ⊥ ↔ μ s = 0 := ae_eq_bot.trans restrict_eq_zero diff --git a/Mathlib/Probability/Kernel/Condexp.lean b/Mathlib/Probability/Kernel/Condexp.lean index f2b085aafd5f5..56675cbb11d1e 100644 --- a/Mathlib/Probability/Kernel/Condexp.lean +++ b/Mathlib/Probability/Kernel/Condexp.lean @@ -263,7 +263,7 @@ lemma condexpKernel_singleton_ae_eq_cond [StandardBorelSpace Ω] (hs : Measurabl condexpKernel μ (generateFrom {s}) ω t = μ[t|s] := by have : (fun ω ↦ (condexpKernel μ (generateFrom {s}) ω t).toReal) =ᵐ[μ.restrict s] μ⟦t | generateFrom {s}⟧ := - ae_restrict_le hs <| condexpKernel_ae_eq_condexp + ae_restrict_le <| condexpKernel_ae_eq_condexp (generateFrom_singleton_le hs) ht filter_upwards [condexp_set_generateFrom_singleton hs ht, this] with ω hω₁ hω₂ rwa [hω₁, ENNReal.toReal_eq_toReal (measure_ne_top _ t) (measure_ne_top _ t)] at hω₂ From d677d774e4dc693f6e6b8ed518c093154a7188fa Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 14 Jan 2025 10:52:46 +0000 Subject: [PATCH 227/681] feat(Data/Fintype/List): generalize `fintypeNodupList` (no `DecidableEq`) (#16656) Co-authored-by: Moritz Firsching --- Mathlib/Data/Fintype/List.lean | 92 +++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 23 deletions(-) diff --git a/Mathlib/Data/Fintype/List.lean b/Mathlib/Data/Fintype/List.lean index a93c79912ed44..484de8858d77e 100644 --- a/Mathlib/Data/Fintype/List.lean +++ b/Mathlib/Data/Fintype/List.lean @@ -3,47 +3,49 @@ Copyright (c) 2021 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Data.Fintype.Basic import Mathlib.Data.Finset.Powerset +import Mathlib.Data.Fintype.Basic import Mathlib.Data.List.Permutation /-! # Fintype instance for nodup lists -The subtype of `{l : List α // l.nodup}` over a `[Fintype α]` +The subtype of `{l : List α // l.Nodup}` over a `[Fintype α]` admits a `Fintype` instance. ## Implementation details To construct the `Fintype` instance, a function lifting a `Multiset α` -to the `Finset (List α)` that can construct it is provided. +to the `Multiset (List α)` is provided. This function is applied to the `Finset.powerset` of `Finset.univ`. -In general, a `DecidableEq` instance is not necessary to define this function, -but a proof of `(List.permutations l).nodup` is required to avoid it, -which is a TODO. - -/ -variable {α : Type*} [DecidableEq α] - +variable {α : Type*} open List namespace Multiset -/-- The `Finset` of `l : List α` that, given `m : Multiset α`, have the property `⟦l⟧ = m`. +/-- Given a `m : Multiset α`, we form the `Multiset` of `l : List α` with the property `⟦l⟧ = m`. -/ -def lists : Multiset α → Finset (List α) := fun s => - Quotient.liftOn s (fun l => l.permutations.toFinset) fun l l' (h : l ~ l') => by - ext sl +def lists : Multiset α → Multiset (List α) := fun s => + Quotient.liftOn s (fun l => l.permutations) fun l l' (h : l ~ l') => by simp only [mem_permutations, List.mem_toFinset] - exact ⟨fun hs => hs.trans h, fun hs => hs.trans h.symm⟩ + refine coe_eq_coe.mpr ?_ + exact Perm.permutations h @[simp] -theorem lists_coe (l : List α) : lists (l : Multiset α) = l.permutations.toFinset := +theorem lists_coe (l : List α) : lists (l : Multiset α) = l.permutations := rfl +@[simp] +theorem lists_nodup_finset (l : Finset α) : (lists (l.val)).Nodup := by + have h_nodup : l.val.Nodup := l.nodup + rw [← Finset.coe_toList l, Multiset.coe_nodup] at h_nodup + rw [← Finset.coe_toList l] + exact nodup_permutations l.val.toList (h_nodup) + @[simp] theorem mem_lists_iff (s : Multiset α) (l : List α) : l ∈ lists s ↔ s = ⟦l⟧ := by induction s using Quotient.inductionOn @@ -51,12 +53,56 @@ theorem mem_lists_iff (s : Multiset α) (l : List α) : l ∈ lists s ↔ s = end Multiset -instance fintypeNodupList [Fintype α] : Fintype { l : List α // l.Nodup } := - Fintype.subtype ((Finset.univ : Finset α).powerset.biUnion fun s => s.val.lists) fun l => by - suffices (∃ a : Finset α, a.val = ↑l) ↔ l.Nodup by simpa +@[simp] +theorem perm_toList {f₁ f₂ : Finset α} : f₁.toList ~ f₂.toList ↔ f₁ = f₂ := + ⟨fun h => Finset.ext_iff.mpr (fun x => by simpa [← Finset.mem_toList] using Perm.mem_iff h), + fun h ↦ Perm.of_eq <| congrArg Finset.toList h⟩ + +instance fintypeNodupList [Fintype α] : Fintype { l : List α // l.Nodup } := by + refine Fintype.ofFinset ?_ ?_ + · let univSubsets := ((Finset.univ : Finset α).powerset.1 : (Multiset (Finset α))) + let allPerms := Multiset.bind univSubsets (fun s => (Multiset.lists s.1)) + refine ⟨allPerms, Multiset.nodup_bind.mpr ?_⟩ + simp only [Multiset.lists_nodup_finset, implies_true, true_and] + unfold Multiset.Pairwise + use ((Finset.univ : Finset α).powerset.toList : (List (Finset α))) + constructor + · simp only [Finset.coe_toList] + rfl + · convert Finset.nodup_toList (Finset.univ.powerset : Finset (Finset α)) + ext l + unfold Nodup + refine Pairwise.iff ?_ + intro m n + simp only [_root_.Disjoint] + rw [← m.coe_toList, ← n.coe_toList, Multiset.lists_coe, Multiset.lists_coe] + have := Multiset.coe_disjoint m.toList.permutations n.toList.permutations + rw [_root_.Disjoint] at this + rw [this] + simp only [Multiset.coe_disjoint, ne_eq] + rw [List.disjoint_iff_ne] + constructor + · intro h + by_contra hc + rw [hc] at h + contrapose! h + use n.toList + simp + · intro h + simp only [mem_permutations] + intro a ha b hb + by_contra hab + absurd h + rw [hab] at ha + exact perm_toList.mp <| Perm.trans (id (Perm.symm ha)) hb + · intro l + simp only [Finset.mem_mk, Multiset.mem_bind, Finset.mem_val, Finset.mem_powerset, + Finset.subset_univ, Multiset.mem_lists_iff, Multiset.quot_mk_to_coe, true_and] constructor - · rintro ⟨s, hs⟩ - simpa [← Multiset.coe_nodup, ← hs] using s.nodup - · intro hl - refine ⟨⟨↑l, hl⟩, ?_⟩ - simp + · intro h + rcases h with ⟨f, hf⟩ + convert Set.mem_def.mpr f.nodup + rw [hf] + rfl + · intro h + exact CanLift.prf _ h From b37ce20cb9cfdfcaa286fb64ac51cf7c0a43d2f0 Mon Sep 17 00:00:00 2001 From: Winston Yin Date: Tue, 14 Jan 2025 12:01:03 +0000 Subject: [PATCH 228/681] feat: isometries from induced metrics (#20731) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If `f : α → β`, where `β` is a metric space, and the metric on `α` is induced by pullback along `f`, then `f` is an isometry. I add this trivial lemma for `PseudoEmetricSpace`, `PseudoMetricSpace`, `EMetricSpace`, and `MetricSpace`, as suggested by Junyan Xu in [this thread](https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/dist.20of.20induced.20metric/near/493459925). --- Mathlib/Topology/MetricSpace/Isometry.lean | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Mathlib/Topology/MetricSpace/Isometry.lean b/Mathlib/Topology/MetricSpace/Isometry.lean index e145a00ce470a..b4b370cbcce52 100644 --- a/Mathlib/Topology/MetricSpace/Isometry.lean +++ b/Mathlib/Topology/MetricSpace/Isometry.lean @@ -258,6 +258,18 @@ theorem Topology.IsEmbedding.to_isometry {α β} [TopologicalSpace α] [MetricSp @[deprecated (since := "2024-10-26")] alias Embedding.to_isometry := IsEmbedding.to_isometry +theorem PseudoEMetricSpace.isometry_induced (f : α → β) [m : PseudoEMetricSpace β] : + letI := m.induced f; Isometry f := fun _ _ ↦ rfl + +theorem PsuedoMetricSpace.isometry_induced (f : α → β) [m : PseudoMetricSpace β] : + letI := m.induced f; Isometry f := fun _ _ ↦ rfl + +theorem EMetricSpace.isometry_induced (f : α → β) (hf : f.Injective) [m : EMetricSpace β] : + letI := m.induced f hf; Isometry f := fun _ _ ↦ rfl + +theorem MetricSpace.isometry_induced (f : α → β) (hf : f.Injective) [m : MetricSpace β] : + letI := m.induced f hf; Isometry f := fun _ _ ↦ rfl + -- such a bijection need not exist /-- `α` and `β` are isometric if there is an isometric bijection between them. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] From cbbe71d575ebb4eaf6d722a695102608fcb31647 Mon Sep 17 00:00:00 2001 From: Michael Stoll Date: Tue, 14 Jan 2025 12:21:05 +0000 Subject: [PATCH 229/681] chore(Analysis/Normed/Ring/WithAbs): make equiv a ring equiv (#20713) Making `WithAbs.equiv` a ring equivalence (like `WithAbs.ringEquiv`) should make a lot of the API lemmas obsolete. --- Mathlib/Analysis/Normed/Ring/WithAbs.lean | 65 ++++++++++--------- .../NumberTheory/NumberField/Completion.lean | 2 +- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/Mathlib/Analysis/Normed/Ring/WithAbs.lean b/Mathlib/Analysis/Normed/Ring/WithAbs.lean index 9a69e4045dd4d..38feb9d2992d9 100644 --- a/Mathlib/Analysis/Normed/Ring/WithAbs.lean +++ b/Mathlib/Analysis/Normed/Ring/WithAbs.lean @@ -30,7 +30,9 @@ open Topology noncomputable section -variable {R S K : Type*} [Semiring R] [OrderedSemiring S] [Field K] +section definition + +variable {R R' S K : Type*} [Semiring R] [Ring R'] [OrderedSemiring S] [Field K] /-- Type synonym for a semiring which depends on an absolute value. This is a function that takes an absolute value on a semiring and returns the semiring. We use this to assign and infer instances @@ -40,10 +42,7 @@ def WithAbs : AbsoluteValue R S → Type _ := fun _ => R namespace WithAbs -variable (v : AbsoluteValue R ℝ) - -/-- Canonical equivalence between `WithAbs v` and `R`. -/ -def equiv : WithAbs v ≃ R := Equiv.refl (WithAbs v) +variable (v : AbsoluteValue R ℝ) (v' : AbsoluteValue R' ℝ) instance instNonTrivial [Nontrivial R] : Nontrivial (WithAbs v) := inferInstanceAs (Nontrivial R) @@ -51,56 +50,60 @@ instance instUnique [Unique R] : Unique (WithAbs v) := inferInstanceAs (Unique R instance instSemiring : Semiring (WithAbs v) := inferInstanceAs (Semiring R) -instance instRing [Ring R] : Ring (WithAbs v) := inferInstanceAs (Ring R) +instance instRing : Ring (WithAbs v') := inferInstanceAs (Ring R') instance instInhabited : Inhabited (WithAbs v) := ⟨0⟩ -instance normedRing {R : Type*} [Ring R] (v : AbsoluteValue R ℝ) : NormedRing (WithAbs v) := - v.toNormedRing +/-- The canonical (semiring) equivalence between `WithAbs v` and `R`. -/ +def equiv : WithAbs v ≃+* R := RingEquiv.refl _ + +instance normedRing : NormedRing (WithAbs v') := + v'.toNormedRing instance normedField (v : AbsoluteValue K ℝ) : NormedField (WithAbs v) := v.toNormedField /-! `WithAbs.equiv` preserves the ring structure. -/ +variable (x y : WithAbs v) (r s : R) (x' y' : WithAbs v') (r' s' : R') -variable (x y : WithAbs v) (r s : R) -@[simp] -theorem equiv_zero : WithAbs.equiv v 0 = 0 := rfl +@[deprecated "Use map_zero" (since := "2025-01-13"), simp] +theorem equiv_zero : equiv v 0 = 0 := rfl -@[simp] -theorem equiv_symm_zero : (WithAbs.equiv v).symm 0 = 0 := rfl +@[deprecated "Use map_zero" (since := "2025-01-13"), simp] +theorem equiv_symm_zero : (equiv v).symm 0 = 0 := rfl -@[simp] -theorem equiv_add : WithAbs.equiv v (x + y) = WithAbs.equiv v x + WithAbs.equiv v y := rfl +@[deprecated "Use map_add" (since := "2025-01-13"), simp] +theorem equiv_add : equiv v (x + y) = equiv v x + equiv v y := rfl -@[simp] +@[deprecated "Use map_add" (since := "2025-01-13"), simp] theorem equiv_symm_add : - (WithAbs.equiv v).symm (r + s) = (WithAbs.equiv v).symm r + (WithAbs.equiv v).symm s := + (equiv v).symm (r + s) = (equiv v).symm r + (equiv v).symm s := rfl -@[simp] -theorem equiv_sub [Ring R] : WithAbs.equiv v (x - y) = WithAbs.equiv v x - WithAbs.equiv v y := rfl +@[deprecated "Use map_sub" (since := "2025-01-13"), simp] +theorem equiv_sub : equiv v' (x' - y') = equiv v' x' - equiv v' y' := rfl -@[simp] -theorem equiv_symm_sub [Ring R] : - (WithAbs.equiv v).symm (r - s) = (WithAbs.equiv v).symm r - (WithAbs.equiv v).symm s := +@[deprecated "Use map_sub" (since := "2025-01-13"), simp] +theorem equiv_symm_sub : + (equiv v').symm (r' - s') = (equiv v').symm r' - (equiv v').symm s' := rfl -@[simp] -theorem equiv_neg [Ring R] : WithAbs.equiv v (-x) = - WithAbs.equiv v x := rfl +@[deprecated "Use map_neg" (since := "2025-01-13"), simp] +theorem equiv_neg : equiv v' (-x') = - equiv v' x' := rfl -@[simp] -theorem equiv_symm_neg [Ring R] : (WithAbs.equiv v).symm (-r) = - (WithAbs.equiv v).symm r := rfl +@[deprecated "Use map_neg" (since := "2025-01-13"), simp] +theorem equiv_symm_neg : (equiv v').symm (-r') = - (equiv v').symm r' := rfl -@[simp] -theorem equiv_mul : WithAbs.equiv v (x * y) = WithAbs.equiv v x * WithAbs.equiv v y := rfl +@[deprecated "Use map_mul" (since := "2025-01-13"), simp] +theorem equiv_mul : equiv v (x * y) = equiv v x * equiv v y := rfl -@[simp] +@[deprecated "Use map_mul" (since := "2025-01-13"), simp] theorem equiv_symm_mul : - (WithAbs.equiv v).symm (x * y) = (WithAbs.equiv v).symm x * (WithAbs.equiv v).symm y := + (equiv v).symm (x * y) = (equiv v).symm x * (equiv v).symm y := rfl /-- `WithAbs.equiv` as a ring equivalence. -/ +@[deprecated equiv (since := "2025-01-13")] def ringEquiv : WithAbs v ≃+* R := RingEquiv.refl _ /-! The completion of a field at an absolute value. -/ @@ -134,6 +137,8 @@ theorem isUniformInducing_of_comp (h : ∀ x, ‖f x‖ = v x) : IsUniformInduci end WithAbs +end definition + namespace AbsoluteValue open WithAbs diff --git a/Mathlib/NumberTheory/NumberField/Completion.lean b/Mathlib/NumberTheory/NumberField/Completion.lean index 9a37fd57f1c6b..df6daec6f3ded 100644 --- a/Mathlib/NumberTheory/NumberField/Completion.lean +++ b/Mathlib/NumberTheory/NumberField/Completion.lean @@ -83,7 +83,7 @@ instance : Algebra K v.Completion := lemma WithAbs.ratCast_equiv (v : InfinitePlace ℚ) (x : WithAbs v.1) : Rat.cast (WithAbs.equiv _ x) = (x : v.Completion) := (eq_ratCast (UniformSpace.Completion.coeRingHom.comp - (WithAbs.ringEquiv v.1).symm.toRingHom) x).symm + (WithAbs.equiv v.1).symm.toRingHom) x).symm lemma Rat.norm_infinitePlace_completion (v : InfinitePlace ℚ) (x : ℚ) : ‖(x : v.Completion)‖ = |x| := by From fb87eb74e965b2dfb422a211f7607a63c992236f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 14 Jan 2025 13:56:08 +0000 Subject: [PATCH 230/681] chore(AlgebraicTopology): fix the definition of Kan complexes (#20734) The definition of Kan complexes is fixed by taking into account Remark 2.3 at https://ncatlab.org/nlab/show/horn --- .../SimplicialSet/KanComplex.lean | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean index 87cf0ca7bf9e5..982bd19ff062b 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean @@ -16,22 +16,20 @@ we show that every Kan complex is a quasicategory. ## TODO - Show that the singular simplicial set of a topological space is a Kan complex. -- Generalize the definition to higher universes. - Since `Λ[n, i]` is an object of `SSet.{0}`, - the current definition of a Kan complex `S` - requires `S : SSet.{0}`. -/ +universe u + namespace SSet open CategoryTheory Simplicial /-- A simplicial set `S` is a *Kan complex* if it satisfies the following horn-filling condition: -for every `n : ℕ` and `0 ≤ i ≤ n`, +for every nonzero `n : ℕ` and `0 ≤ i ≤ n`, every map of simplicial sets `σ₀ : Λ[n, i] → S` can be extended to a map `σ : Δ[n] → S`. -/ -class KanComplex (S : SSet) : Prop where - hornFilling : ∀ ⦃n : ℕ⦄ ⦃i : Fin (n+1)⦄ (σ₀ : Λ[n, i] ⟶ S), - ∃ σ : Δ[n] ⟶ S, σ₀ = hornInclusion n i ≫ σ +class KanComplex (S : SSet.{u}) : Prop where + hornFilling : ∀ ⦃n : ℕ⦄ ⦃i : Fin (n + 2)⦄ (σ₀ : Λ[n + 1, i] ⟶ S), + ∃ σ : Δ[n + 1] ⟶ S, σ₀ = hornInclusion (n + 1) i ≫ σ end SSet From 4133a9f7274b0d8938100b9edd5bc770f9bd6251 Mon Sep 17 00:00:00 2001 From: LennyTaelman Date: Tue, 14 Jan 2025 14:07:39 +0000 Subject: [PATCH 231/681] feat: implement tauto_set tactic for set-theoretic trivialities (#20706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement a tactic that proves tautologies involving hypotheses and goals of the form `X ⊆ Y` or `X = Y`, where `X`, `Y` are expressions built using `∪`, `∩`, `\`, and `ᶜ` from finitely many variables of type `Set α`. It also unfolds `Disjoint` and `symmDiff`. Discussed in the zulip thread https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Trivialities.20about.20sets The file MathlibTest/TautoSet.lean contains many usage examples, including a list of lemma's from the Matroid Decomposition Theorem Verification project, which can now be golfed to a single tactic invocation. Co-authored-by: LennyTaelman <145012882+LennyTaelman@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Tactic.lean | 1 + Mathlib/Tactic/TautoSet.lean | 52 +++++++++++++ MathlibTest/TautoSet.lean | 147 +++++++++++++++++++++++++++++++++++ scripts/noshake.json | 1 + 5 files changed, 202 insertions(+) create mode 100644 Mathlib/Tactic/TautoSet.lean create mode 100644 MathlibTest/TautoSet.lean diff --git a/Mathlib.lean b/Mathlib.lean index be92270eab6ee..ac86b27e96b8d 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5053,6 +5053,7 @@ import Mathlib.Tactic.SuppressCompilation import Mathlib.Tactic.SwapVar import Mathlib.Tactic.TFAE import Mathlib.Tactic.Tauto +import Mathlib.Tactic.TautoSet import Mathlib.Tactic.TermCongr import Mathlib.Tactic.ToAdditive import Mathlib.Tactic.ToAdditive.Frontend diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index 60f53209f5ed1..c30277fabaaaf 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -239,6 +239,7 @@ import Mathlib.Tactic.SuppressCompilation import Mathlib.Tactic.SwapVar import Mathlib.Tactic.TFAE import Mathlib.Tactic.Tauto +import Mathlib.Tactic.TautoSet import Mathlib.Tactic.TermCongr import Mathlib.Tactic.ToAdditive import Mathlib.Tactic.ToAdditive.Frontend diff --git a/Mathlib/Tactic/TautoSet.lean b/Mathlib/Tactic/TautoSet.lean new file mode 100644 index 0000000000000..80962258bc3c3 --- /dev/null +++ b/Mathlib/Tactic/TautoSet.lean @@ -0,0 +1,52 @@ +/- +Copyright (c) 2025 Lenny Taelman. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Lenny Taelman +-/ + +import Mathlib.Data.Set.SymmDiff + +/-! +# The `tauto_set` tactic +-/ + +namespace Mathlib.Tactic.TautoSet + +open Lean Elab.Tactic + +/-- +`specialize_all x` runs `specialize h x` for all hypotheses `h` where this tactic succeeds. +-/ +elab (name := specialize_all) "specialize_all" x:term : tactic => withMainContext do + for h in ← getLCtx do + evalTactic (← `(tactic|specialize $(mkIdent h.userName) $x)) <|> pure () + + +/-- + `tauto_set` attempts to prove tautologies involving hypotheses and goals of the form `X ⊆ Y` + or `X = Y`, where `X`, `Y` are expressions built using ∪, ∩, \, and ᶜ from finitely many + variables of type `Set α`. It also unfolds expressions of the form `Disjoint A B` and + `symmDiff A B`. + + Examples: + ```lean + example {α} (A B C D : Set α) (h1 : A ⊆ B) (h2 : C ⊆ D) : C \ B ⊆ D \ A := by + tauto_set + + example {α} (A B C : Set α) (h1 : A ⊆ B ∪ C) : (A ∩ B) ∪ (A ∩ C) = A := by + tauto_set + ``` +-/ +macro "tauto_set" : tactic => `(tactic| + · simp_all only [ + Set.ext_iff, Set.subset_def, + Set.mem_union, Set.mem_compl_iff, Set.mem_inter_iff, + Set.symmDiff_def, Set.diff_eq, Set.disjoint_iff + ] + try intro x + try specialize_all x + <;> tauto +) + + +end Mathlib.Tactic.TautoSet diff --git a/MathlibTest/TautoSet.lean b/MathlibTest/TautoSet.lean new file mode 100644 index 0000000000000..6fb50960b8840 --- /dev/null +++ b/MathlibTest/TautoSet.lean @@ -0,0 +1,147 @@ +/- +Copyright (c) 2025 Lenny Taelman. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Lenny Taelman +-/ + +import Mathlib.Tactic.TautoSet + +variable {α : Type} {A B C D E : Set α} + + +example (h : B ∪ C ⊆ A ∪ A) : B ⊆ A := by tauto_set +example (h : B ∩ B ∩ C ⊇ A) : A ⊆ B := by tauto_set +example (hABC : A ⊆ B ∪ C) (hCD : C ⊆ D): A ⊆ B ∪ D := by tauto_set + +example (h : A = Aᶜ) : B = ∅ := by tauto_set +example (h : A = Aᶜ) : B = C := by tauto_set + +example (h : A ⊆ Aᶜ \ B) : A = ∅ := by tauto_set +example (h1 : A ⊆ B \ C) : A ⊆ B := by tauto_set + +example (h : Set.univ ⊆ ((A ∪ B) ∩ C) ∩ ((Aᶜ ∩ Bᶜ) ∪ Cᶜ)) : D \ B ⊆ E ∩ Aᶜ := by tauto_set + +example (h : A ∩ B ⊆ C) (h2 : C ∩ D ⊆ E) : A ∩ B ∩ D ⊆ E := by tauto_set +example (h : E = Aᶜᶜ ∩ Cᶜᶜᶜ ∩ D) : D ∩ (B ∪ Cᶜ) ∩ A = E ∪ (A ∩ Dᶜᶜ ∩ B)ᶜᶜ := by tauto_set +example (h : E ⊇ Aᶜᶜ ∩ Cᶜᶜᶜ ∩ D) : D ∩ (B ∪ Cᶜ) ∩ A ⊆ E ∪ (A ∩ Dᶜᶜ ∩ B)ᶜᶜ := by tauto_set + +example (h1 : A = B) : A = B := by tauto_set +example (h1 : A = B) (h2 : B ⊆ C): A ⊆ C := by tauto_set + +example (h1 : A ∩ B = Set.univ) : A = Set.univ := by tauto_set +example (h1 : A ∪ B = ∅) : A = ∅ := by tauto_set + +example (h: Aᶜ ⊆ ∅) : A = Set.univ := by tauto_set +example (h: Set.univ ⊆ Aᶜ) : A = ∅ := by tauto_set + +example : A ∩ ∅ = ∅ := by tauto_set +example : A ∪ Set.univ = Set.univ := by tauto_set + +example : ∅ ⊆ A := by tauto_set +example : A ⊆ Set.univ := by tauto_set + +example (hAB : A ⊆ B) (hBA: B ⊆ A) : A = B := by tauto_set + +example : A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C) := by tauto_set +example : A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C) := by tauto_set +example : A ∩ (B ∪ C) ⊆ (A ∩ B) ∪ (A ∩ C) := by tauto_set + +example : A ⊆ (A ∪ B) ∪ C := by tauto_set + +example : A ∩ B ⊆ A := by tauto_set +example : A ⊆ A ∪ B := by tauto_set + +example (hBA : B ⊆ A) (hB : Set.univ ⊆ B): Set.univ = A := by tauto_set + +example (hAB : A ⊆ B) (hCD : C ⊆ D) : C \ B ⊆ D \ A := by tauto_set + +example (hAB : Disjoint A B) (hCA : C ⊆ A) : Disjoint C (B \ D) := by tauto_set + +example : Aᶜᶜᶜ = Aᶜ := by tauto_set +example : Aᶜᶜ = A := by tauto_set + +example (hAB : A ⊆ B) (hBC : B ⊆ C) : A ⊆ C := by tauto_set + +example : (Aᶜ ∩ B ∩ Cᶜᶜ)ᶜᶜᶜᶜᶜ = Cᶜ ∪ Bᶜ ∪ ∅ ∪ A ∪ ∅ := by tauto_set + +example : D ∩ (B ∪ Cᶜ) ∩ A = (Aᶜᶜ ∩ Cᶜᶜᶜ ∩ D) ∪ (A ∩ Dᶜᶜ ∩ B)ᶜᶜ := by tauto_set + +example (hAB : A ⊆ B) (hBC : B ⊆ C) (hCD : C ⊆ D) (hDE : D = E) (hEA : E ⊆ A) : + (Aᶜ ∩ B ∪ (C ∩ Bᶜ)ᶜ ∩ (Eᶜ ∪ A))ᶜ ∩ (B ∪ Eᶜᶜ)ᶜ = + (Dᶜ ∩ C ∪ (B ∩ Aᶜ)ᶜ ∩ (Eᶜ ∪ E))ᶜ ∩ (D ∪ Cᶜᶜ)ᶜ := by tauto_set + + + +/- + Examples from the Matroid Decomposition Theorem Verification, + see https://github.com/Ivan-Sergeyev/seymour, and in particular + https://github.com/Ivan-Sergeyev/seymour/blob/d8fcfa23336efe50b09fa0939e8a4ec3a5601ae9/Seymour/ForMathlib/SetTheory.lean +-/ + +-- setminus_inter_union_eq_union +example : A \ (A ∩ B) ∪ B = A ∪ B := by tauto_set + +-- sub_parts_eq +example (hA : A ⊆ B ∪ C) : (A ∩ B) ∪ (A ∩ C) = A := by tauto_set + +-- elem_notin_set_minus_singleton +example (a : α) : a ∉ A \ {a} := by tauto_set + +-- sub_union_diff_sub_union +example (hA : A ⊆ B \ C) : A ⊆ B := by tauto_set + +-- singleton_inter_subset_left +example (hAB : A ∩ B = {a}) : {a} ⊆ A := by tauto_set + +-- singleton_inter_subset_right +example (hAB : A ∩ B = {a}) : {a} ⊆ B := by tauto_set + +-- diff_subset_parent +example (hAB : A ⊆ C) : A \ B ⊆ C := by tauto_set + +-- inter_subset_parent_left +example (hAC : A ⊆ C) : A ∩ B ⊆ C := by tauto_set + +-- inter_subset_parent_right +example (hBC : B ⊆ C) : A ∩ B ⊆ C := by tauto_set + +-- inter_subset_union +example : A ∩ B ⊆ A ∪ B := by tauto_set + +-- subset_diff_empty_eq +example (hAB : A ⊆ B) (hBA : B \ A = ∅) : A = B := by tauto_set + +-- Disjoint.ni_of_in +example (hAB : Disjoint A B) (ha : a ∈ A) : a ∉ B := by tauto_set + +-- disjoint_of_singleton_inter_left_wo +example (hAB : A ∩ B = {a}) : Disjoint (A \ {a}) B := by tauto_set + +-- disjoint_of_singleton_inter_right_wo +example (hAB : A ∩ B = {a}) : Disjoint A (B \ {a}) := by tauto_set + +-- disjoint_of_singleton_inter_both_wo +example (hAB : A ∩ B = {a}) : Disjoint (A \ {a}) (B \ {a}) := by tauto_set + +-- union_subset_union_iff +example (hAC : Disjoint A C) (hBC : Disjoint B C) : + A ∪ C ⊆ B ∪ C ↔ A ⊆ B := by + constructor <;> (intro; tauto_set) + +-- symmDiff_eq_alt +example : symmDiff A B = (A ∪ B) \ (A ∩ B) := by tauto_set + +-- symmDiff_disjoint_inter +example : Disjoint (symmDiff A B) (A ∩ B) := by tauto_set + +-- symmDiff_empty_eq +example : symmDiff A ∅ = A := by tauto_set + +-- empty_symmDiff_eq +example : symmDiff ∅ A = A := by tauto_set + +-- symmDiff_subset_ground_right +example (hC : symmDiff A B ⊆ C) (hA : A ⊆ C) : B ⊆ C := by tauto_set + +-- symmDiff_subset_ground_left +example (hC : symmDiff A B ⊆ C) (hB : B ⊆ C) : A ⊆ C := by tauto_set diff --git a/scripts/noshake.json b/scripts/noshake.json index 62e7ac4f7449b..ae281ef3f6f18 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -213,6 +213,7 @@ "Mathlib.Tactic.Widget.CommDiag": ["Mathlib.CategoryTheory.Category.Basic"], "Mathlib.Tactic.Use": ["Batteries.Logic"], "Mathlib.Tactic.TermCongr": ["Mathlib.Logic.Basic"], + "Mathlib.Tactic.TautoSet": ["Mathlib.Data.Set.SymmDiff"], "Mathlib.Tactic.Tauto": ["Mathlib.Logic.Basic"], "Mathlib.Tactic.TFAE": ["Mathlib.Data.List.TFAE", "Mathlib.Tactic.Have"], "Mathlib.Tactic.Subsingleton": ["Mathlib.Logic.Basic", "Std.Logic"], From 456d19bbf23d947d75ed05fa3c3d9a80f11ee412 Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Tue, 14 Jan 2025 14:39:03 +0000 Subject: [PATCH 232/681] feat(Order/PartialSups): allow general orders as domain (#20137) Currently `PartialSups` is only defined for Nat-indexed sequences. This generalises it to arbitrary preorders satisfying suitable typeclass assumptions. Co-authored-by: Johan Commelin Co-authored-by: Yury G. Kudryashov --- Mathlib.lean | 1 + Mathlib/Algebra/Order/PartialSups.lean | 20 ++ Mathlib/LinearAlgebra/Basis/Exact.lean | 1 - Mathlib/LinearAlgebra/Prod.lean | 3 +- .../OuterMeasure/Caratheodory.lean | 2 +- Mathlib/Order/Disjointed.lean | 16 +- Mathlib/Order/PartialSups.lean | 273 ++++++++++++------ Mathlib/RingTheory/Artinian/Module.lean | 4 +- Mathlib/RingTheory/Noetherian/Basic.lean | 5 +- Mathlib/Topology/Order/PartialSups.lean | 6 +- 10 files changed, 220 insertions(+), 111 deletions(-) create mode 100644 Mathlib/Algebra/Order/PartialSups.lean diff --git a/Mathlib.lean b/Mathlib.lean index ac86b27e96b8d..156b35b551c9f 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -767,6 +767,7 @@ import Mathlib.Algebra.Order.Nonneg.Field import Mathlib.Algebra.Order.Nonneg.Floor import Mathlib.Algebra.Order.Nonneg.Module import Mathlib.Algebra.Order.Nonneg.Ring +import Mathlib.Algebra.Order.PartialSups import Mathlib.Algebra.Order.Pi import Mathlib.Algebra.Order.Positive.Field import Mathlib.Algebra.Order.Positive.Ring diff --git a/Mathlib/Algebra/Order/PartialSups.lean b/Mathlib/Algebra/Order/PartialSups.lean new file mode 100644 index 0000000000000..074c74299111a --- /dev/null +++ b/Mathlib/Algebra/Order/PartialSups.lean @@ -0,0 +1,20 @@ +/- +Copyright (c) 2021 Kim Morrison. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kim Morrison +-/ +import Mathlib.Algebra.Order.SuccPred +import Mathlib.Order.PartialSups + +/-! +# `PartialSups` in a `SuccAddOrder` +-/ + +open Finset + +variable {α ι : Type*} [SemilatticeSup α] + +@[simp] +lemma partialSups_add_one [Add ι] [One ι] [LinearOrder ι] [LocallyFiniteOrderBot ι] [SuccAddOrder ι] + (f : ι → α) (i : ι) : partialSups f (i + 1) = partialSups f i ⊔ f (i + 1) := + Order.succ_eq_add_one i ▸ partialSups_succ f i diff --git a/Mathlib/LinearAlgebra/Basis/Exact.lean b/Mathlib/LinearAlgebra/Basis/Exact.lean index 47863f1f81c7d..88e09f3929bbd 100644 --- a/Mathlib/LinearAlgebra/Basis/Exact.lean +++ b/Mathlib/LinearAlgebra/Basis/Exact.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Christian Merten -/ import Mathlib.Algebra.Exact -import Mathlib.Algebra.Module.Submodule.Pointwise import Mathlib.LinearAlgebra.Basis.Basic /-! diff --git a/Mathlib/LinearAlgebra/Prod.lean b/Mathlib/LinearAlgebra/Prod.lean index ed5cd352af5bd..2f6e9cd67d6fb 100644 --- a/Mathlib/LinearAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/Prod.lean @@ -5,8 +5,9 @@ Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Eric W -/ import Mathlib.Algebra.Algebra.Prod import Mathlib.Algebra.Group.Graph +import Mathlib.Algebra.Order.PartialSups +import Mathlib.Data.Nat.SuccPred import Mathlib.LinearAlgebra.Span.Basic -import Mathlib.Order.PartialSups /-! ### Products of modules diff --git a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean index 167ea1437b67c..4916ae6d6fb95 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean @@ -96,7 +96,7 @@ lemma isCaratheodory_partialSups {s : ℕ → Set α} (h : ∀ i, m.IsCaratheodo m.IsCaratheodory (partialSups s i) := by induction i with | zero => exact h 0 - | succ i hi => exact m.isCaratheodory_union hi (h (i + 1)) + | succ i hi => exact partialSups_add_one s i ▸ m.isCaratheodory_union hi (h (i + 1)) lemma isCaratheodory_disjointed {s : ℕ → Set α} (h : ∀ i, m.IsCaratheodory (s i)) (i : ℕ) : m.IsCaratheodory (disjointed s i) := by diff --git a/Mathlib/Order/Disjointed.lean b/Mathlib/Order/Disjointed.lean index 1366a858c3dcd..62ea4568a5fa6 100644 --- a/Mathlib/Order/Disjointed.lean +++ b/Mathlib/Order/Disjointed.lean @@ -3,7 +3,8 @@ 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, Yaël Dillies -/ -import Mathlib.Order.PartialSups +import Mathlib.Algebra.Order.PartialSups +import Mathlib.Data.Nat.SuccPred /-! # Consecutive differences of sets @@ -85,7 +86,7 @@ def disjointedRec {f : ℕ → α} {p : α → Sort*} (hdiff : ∀ ⦃t i⦄, p rintro k induction' k with k ih · exact hdiff h - rw [partialSups_succ, ← sdiff_sdiff_left] + rw [partialSups_add_one, ← sdiff_sdiff_left] exact hdiff ih @[simp] @@ -106,7 +107,7 @@ theorem partialSups_disjointed (f : ℕ → α) : partialSups (disjointed f) = p ext n induction' n with k ih · rw [partialSups_zero, partialSups_zero, disjointed_zero] - · rw [partialSups_succ, partialSups_succ, disjointed_succ, ih, sup_sdiff_self_right] + · rw [partialSups_add_one, partialSups_add_one, disjointed_succ, ih, sup_sdiff_self_right] /-- `disjointed f` is the unique sequence that is pairwise disjoint and has the same partial sups as `f`. -/ @@ -115,14 +116,15 @@ theorem disjointed_unique {f d : ℕ → α} (hdisj : Pairwise (Disjoint on d)) ext n cases' n with n · rw [← partialSups_zero d, hsups, partialSups_zero, disjointed_zero] - suffices h : d n.succ = partialSups d n.succ \ partialSups d n by - rw [h, hsups, partialSups_succ, disjointed_succ, sup_sdiff, sdiff_self, bot_sup_eq] - rw [partialSups_succ, sup_sdiff, sdiff_self, bot_sup_eq, eq_comm, sdiff_eq_self_iff_disjoint] + suffices h : d (n + 1) = partialSups d (n + 1) \ partialSups d n by + rw [h, hsups, partialSups_add_one, disjointed_succ, sup_sdiff, sdiff_self, bot_sup_eq] + rw [partialSups_add_one, sup_sdiff, sdiff_self, bot_sup_eq, eq_comm, sdiff_eq_self_iff_disjoint] suffices h : ∀ m ≤ n, Disjoint (partialSups d m) (d n.succ) from h n le_rfl rintro m hm induction' m with m ih · exact hdisj (Nat.succ_ne_zero _).symm - rw [partialSups_succ, disjoint_iff, inf_sup_right, sup_eq_bot_iff, ← disjoint_iff, ← disjoint_iff] + rw [partialSups_add_one, disjoint_iff, inf_sup_right, sup_eq_bot_iff, + ← disjoint_iff, ← disjoint_iff] exact ⟨ih (Nat.le_of_succ_le hm), hdisj (Nat.lt_succ_of_le hm).ne⟩ end GeneralizedBooleanAlgebra diff --git a/Mathlib/Order/PartialSups.lean b/Mathlib/Order/PartialSups.lean index ee9a7e45473a8..e8b118442fd08 100644 --- a/Mathlib/Order/PartialSups.lean +++ b/Mathlib/Order/PartialSups.lean @@ -3,188 +3,275 @@ Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ -import Mathlib.Data.Finset.Lattice.Fold import Mathlib.Data.Set.Finite.Lattice import Mathlib.Order.ConditionallyCompleteLattice.Indexed -import Mathlib.Order.Hom.Basic +import Mathlib.Order.Interval.Finset.Nat +import Mathlib.Order.SuccPred.Basic /-! # The monotone sequence of partial supremums of a sequence -We define `partialSups : (ℕ → α) → ℕ →o α` inductively. For `f : ℕ → α`, `partialSups f` is -the sequence `f 0`, `f 0 ⊔ f 1`, `f 0 ⊔ f 1 ⊔ f 2`, ... The point of this definition is that -* it doesn't need a `⨆`, as opposed to `⨆ (i ≤ n), f i` (which also means the wrong thing on - `ConditionallyCompleteLattice`s). -* it doesn't need a `⊥`, as opposed to `(Finset.range (n + 1)).sup f`. -* it avoids needing to prove that `Finset.range (n + 1)` is nonempty to use `Finset.sup'`. +For `ι` a preorder in which all bounded-above intervals are finite (such as `ℕ`), and `α` a +`⊔`-semilattice, we define `partialSups : (ι → α) → ι →o α` by the formula +`partialSups f i = (Finset.Iic i).sup' ⋯ f`, where the `⋯` denotes a proof that `Finset.Iic i` is +nonempty. This is a way of spelling `⊔ k ≤ i, f k` which does not require a `α` to have a bottom +element, and makes sense in conditionally-complete lattices (where indexed suprema over sets are +badly-behaved). -Equivalence with those definitions is shown by `partialSups_eq_biSup`, `partialSups_eq_sup_range`, -and `partialSups_eq_sup'_range` respectively. +Under stronger hypotheses on `α` and `ι`, we show that this coincides with other candidate +definitions, see e.g. `partialSups_eq_biSup`, `partialSups_eq_sup_range`, +and `partialSups_eq_sup'_range`. + +We show this construction gives a Galois insertion between functions `ι → α` and monotone functions +`ι →o α`, see `partialSups.gi`. ## Notes -One might dispute whether this sequence should start at `f 0` or `⊥`. We choose the former because : +One might dispute whether this sequence should start at `f 0` or `⊥`. We choose the former because: * Starting at `⊥` requires... having a bottom element. -* `fun f n ↦ (Finset.range n).sup f` is already effectively the sequence starting at `⊥`. +* `fun f i ↦ (Finset.Iio i).sup f` is already effectively the sequence starting at `⊥`. * If we started at `⊥` we wouldn't have the Galois insertion. See `partialSups.gi`. -## TODO - -One could generalize `partialSups` to any locally finite bot preorder domain, in place of `ℕ`. -Necessary for the TODO in the module docstring of `Order.disjointed`. -/ +open Finset -variable {α : Type*} +variable {α ι : Type*} section SemilatticeSup variable [SemilatticeSup α] -/-- The monotone sequence whose value at `n` is the supremum of the `f m` where `m ≤ n`. -/ -def partialSups (f : ℕ → α) : ℕ →o α := - ⟨@Nat.rec (fun _ => α) (f 0) fun (n : ℕ) (a : α) => a ⊔ f (n + 1), - monotone_nat_of_le_succ fun _ => le_sup_left⟩ +section Preorder -@[simp] -theorem partialSups_zero (f : ℕ → α) : partialSups f 0 = f 0 := - rfl +variable [Preorder ι] [LocallyFiniteOrderBot ι] -@[simp] -theorem partialSups_succ (f : ℕ → α) (n : ℕ) : - partialSups f (n + 1) = partialSups f n ⊔ f (n + 1) := +/-- The monotone sequence whose value at `i` is the supremum of the `f j` where `j ≤ i`. -/ +def partialSups (f : ι → α) : ι →o α where + toFun i := (Iic i).sup' nonempty_Iic f + monotone' _ _ hmn := sup'_mono f (Iic_subset_Iic.mpr hmn) nonempty_Iic + +lemma partialSups_apply (f : ι → α) (i : ι) : + partialSups f i = (Iic i).sup' nonempty_Iic f := rfl -lemma partialSups_iff_forall {f : ℕ → α} (p : α → Prop) - (hp : ∀ {a b}, p (a ⊔ b) ↔ p a ∧ p b) : ∀ {n : ℕ}, p (partialSups f n) ↔ ∀ k ≤ n, p (f k) - | 0 => by simp - | (n + 1) => by simp [hp, partialSups_iff_forall, ← Nat.lt_succ_iff, ← Nat.forall_lt_succ] +lemma partialSups_iff_forall {f : ι → α} (p : α → Prop) + (hp : ∀ {a b}, p (a ⊔ b) ↔ p a ∧ p b) {i : ι} : + p (partialSups f i) ↔ ∀ j ≤ i, p (f j) := by + classical + rw [partialSups_apply, comp_sup'_eq_sup'_comp (γ := Propᵒᵈ) _ p, sup'_eq_sup] + · show (Iic i).inf (p ∘ f) ↔ _ + simp [Finset.inf_eq_iInf] + · intro x y + rw [hp] + rfl @[simp] -lemma partialSups_le_iff {f : ℕ → α} {n : ℕ} {a : α} : partialSups f n ≤ a ↔ ∀ k ≤ n, f k ≤ a := +lemma partialSups_le_iff {f : ι → α} {i : ι} {a : α} : + partialSups f i ≤ a ↔ ∀ j ≤ i, f j ≤ a := partialSups_iff_forall (· ≤ a) sup_le_iff -theorem le_partialSups_of_le (f : ℕ → α) {m n : ℕ} (h : m ≤ n) : f m ≤ partialSups f n := - partialSups_le_iff.1 le_rfl m h +theorem le_partialSups_of_le (f : ι → α) {i j : ι} (h : i ≤ j) : + f i ≤ partialSups f j := + partialSups_le_iff.1 le_rfl i h -theorem le_partialSups (f : ℕ → α) : f ≤ partialSups f := fun _n => le_partialSups_of_le f le_rfl +theorem le_partialSups (f : ι → α) : + f ≤ partialSups f := + fun _ => le_partialSups_of_le f le_rfl -theorem partialSups_le (f : ℕ → α) (n : ℕ) (a : α) (w : ∀ m, m ≤ n → f m ≤ a) : - partialSups f n ≤ a := +theorem partialSups_le (f : ι → α) (i : ι) (a : α) (w : ∀ j ≤ i, f j ≤ a) : + partialSups f i ≤ a := partialSups_le_iff.2 w @[simp] -lemma upperBounds_range_partialSups (f : ℕ → α) : +lemma upperBounds_range_partialSups (f : ι → α) : upperBounds (Set.range (partialSups f)) = upperBounds (Set.range f) := by ext a simp only [mem_upperBounds, Set.forall_mem_range, partialSups_le_iff] exact ⟨fun h _ ↦ h _ _ le_rfl, fun h _ _ _ ↦ h _⟩ @[simp] -theorem bddAbove_range_partialSups {f : ℕ → α} : +theorem bddAbove_range_partialSups {f : ι → α} : BddAbove (Set.range (partialSups f)) ↔ BddAbove (Set.range f) := .of_eq <| congr_arg Set.Nonempty <| upperBounds_range_partialSups f -theorem Monotone.partialSups_eq {f : ℕ → α} (hf : Monotone f) : (partialSups f : ℕ → α) = f := by - ext n - induction' n with n ih - · rfl - · rw [partialSups_succ, ih, sup_eq_right.2 (hf (Nat.le_succ _))] +theorem Monotone.partialSups_eq {f : ι → α} (hf : Monotone f) : + partialSups f = f := + funext fun i ↦ le_antisymm (partialSups_le _ _ _ (@hf · i)) (le_partialSups _ _) -theorem partialSups_mono : Monotone (partialSups : (ℕ → α) → ℕ →o α) := fun _f _g h _n ↦ - partialSups_le_iff.2 fun k hk ↦ (h k).trans (le_partialSups_of_le _ hk) +theorem partialSups_mono : + Monotone (partialSups : (ι → α) → ι →o α) := + fun _ _ h _ ↦ partialSups_le_iff.2 fun j hj ↦ (h j).trans (le_partialSups_of_le _ hj) -lemma partialSups_monotone (f : ℕ → α) : Monotone (partialSups f) := - fun n _ hnm ↦ partialSups_le f n _ (fun _ hm'n ↦ le_partialSups_of_le _ (hm'n.trans hnm)) +lemma partialSups_monotone (f : ι → α) : + Monotone (partialSups f) := + fun i _ hnm ↦ partialSups_le f i _ (fun _ hm'n ↦ le_partialSups_of_le _ (hm'n.trans hnm)) /-- `partialSups` forms a Galois insertion with the coercion from monotone functions to functions. -/ -def partialSups.gi : GaloisInsertion (partialSups : (ℕ → α) → ℕ →o α) (↑) where +def partialSups.gi : + GaloisInsertion (partialSups : (ι → α) → ι →o α) (↑) where choice f h := ⟨f, by convert (partialSups f).monotone using 1; exact (le_partialSups f).antisymm h⟩ gc f g := by - refine ⟨(le_partialSups f).trans, fun h => ?_⟩ + refine ⟨(le_partialSups f).trans, fun h ↦ ?_⟩ convert partialSups_mono h exact OrderHom.ext _ _ g.monotone.partialSups_eq.symm le_l_u f := le_partialSups f choice_eq f h := OrderHom.ext _ _ ((le_partialSups f).antisymm h) +protected lemma Pi.partialSups_apply {τ : Type*} {π : τ → Type*} [∀ t, SemilatticeSup (π t)] + (f : ι → (t : τ) → π t) (i : ι) (t : τ) : + partialSups f i t = partialSups (f · t) i := by + simp only [partialSups_apply, Finset.sup'_apply] + +end Preorder + +@[simp] +theorem partialSups_succ [LinearOrder ι] [LocallyFiniteOrderBot ι] [SuccOrder ι] + (f : ι → α) (i : ι) : + partialSups f (Order.succ i) = partialSups f i ⊔ f (Order.succ i) := by + suffices Iic (Order.succ i) = Iic i ∪ {Order.succ i} by simp only [partialSups_apply, this, + sup'_union nonempty_Iic ⟨_, mem_singleton_self _⟩ f, sup'_singleton] + ext + simp only [mem_Iic, mem_union, mem_singleton] + constructor + · exact fun h ↦ (Order.le_succ_iff_eq_or_le.mp h).symm + · exact fun h ↦ h.elim (le_trans · <| Order.le_succ _) le_of_eq + +@[simp] +theorem partialSups_bot [PartialOrder ι] [LocallyFiniteOrder ι] [OrderBot ι] + (f : ι → α) : partialSups f ⊥ = f ⊥ := by + simp only [partialSups_apply] + -- should we add a lemma `Finset.Iic_bot`? + suffices Iic (⊥ : ι) = {⊥} by simp only [this, sup'_singleton] + simp only [← coe_eq_singleton, coe_Iic, Set.Iic_bot] + +/-! +### Functions out of `ℕ` +-/ + +@[simp] +theorem partialSups_zero (f : ℕ → α) : partialSups f 0 = f 0 := + partialSups_bot f + theorem partialSups_eq_sup'_range (f : ℕ → α) (n : ℕ) : - partialSups f n = (Finset.range (n + 1)).sup' ⟨n, Finset.self_mem_range_succ n⟩ f := + partialSups f n = (Finset.range (n + 1)).sup' nonempty_range_succ f := eq_of_forall_ge_iff fun _ ↦ by simp [Nat.lt_succ_iff] -lemma partialSups_apply {ι : Type*} {π : ι → Type*} [(i : ι) → SemilatticeSup (π i)] - (f : ℕ → (i : ι) → π i) (n : ℕ) (i : ι) : partialSups f n i = partialSups (f · i) n := by - simp only [partialSups_eq_sup'_range, Finset.sup'_apply] +theorem partialSups_eq_sup_range [OrderBot α] (f : ℕ → α) (n : ℕ) : + partialSups f n = (Finset.range (n + 1)).sup f := + eq_of_forall_ge_iff fun _ ↦ by simp [Nat.lt_succ_iff] end SemilatticeSup -theorem partialSups_eq_sup_range [SemilatticeSup α] [OrderBot α] (f : ℕ → α) (n : ℕ) : - partialSups f n = (Finset.range (n + 1)).sup f := - eq_of_forall_ge_iff fun _ ↦ by simp [Nat.lt_succ_iff] +section DistribLattice + +/-! +### Functions valued in a distributive lattice + +These lemmas require the target to be a distributive lattice, so they are not useful (or true) in +situations such as submodules. +-/ + +variable [Preorder ι] [LocallyFiniteOrderBot ι] [DistribLattice α] [OrderBot α] @[simp] -lemma disjoint_partialSups_left [DistribLattice α] [OrderBot α] {f : ℕ → α} {n : ℕ} {x : α} : - Disjoint (partialSups f n) x ↔ ∀ k ≤ n, Disjoint (f k) x := +lemma disjoint_partialSups_left {f : ι → α} {i : ι} {x : α} : + Disjoint (partialSups f i) x ↔ ∀ j ≤ i, Disjoint (f j) x := partialSups_iff_forall (Disjoint · x) disjoint_sup_left @[simp] -lemma disjoint_partialSups_right [DistribLattice α] [OrderBot α] {f : ℕ → α} {n : ℕ} {x : α} : - Disjoint x (partialSups f n) ↔ ∀ k ≤ n, Disjoint x (f k) := +lemma disjoint_partialSups_right {f : ι → α} {i : ι} {x : α} : + Disjoint x (partialSups f i) ↔ ∀ j ≤ i, Disjoint x (f j) := partialSups_iff_forall (Disjoint x) disjoint_sup_right open scoped Function in -- required for scoped `on` notation /- Note this lemma requires a distributive lattice, so is not useful (or true) in situations such as submodules. -/ -theorem partialSups_disjoint_of_disjoint [DistribLattice α] [OrderBot α] (f : ℕ → α) - (h : Pairwise (Disjoint on f)) {m n : ℕ} (hmn : m < n) : Disjoint (partialSups f m) (f n) := - disjoint_partialSups_left.2 fun _k hk ↦ h <| (hk.trans_lt hmn).ne +theorem partialSups_disjoint_of_disjoint (f : ι → α) (h : Pairwise (Disjoint on f)) + {i j : ι} (hij : i < j) : + Disjoint (partialSups f i) (f j) := + disjoint_partialSups_left.2 fun _ hk ↦ h (hk.trans_lt hij).ne + +end DistribLattice section ConditionallyCompleteLattice -variable [ConditionallyCompleteLattice α] +/-! +### Lemmas about the supremum over the whole domain + +These lemmas require some completeness assumptions on the target space. +-/ +variable [Preorder ι] [LocallyFiniteOrderBot ι] -theorem partialSups_eq_ciSup_Iic (f : ℕ → α) (n : ℕ) : partialSups f n = ⨆ i : Set.Iic n, f i := - eq_of_forall_ge_iff fun _ ↦ by - rw [ciSup_set_le_iff Set.nonempty_Iic ((Set.finite_le_nat _).image _).bddAbove, - partialSups_le_iff]; rfl +theorem partialSups_eq_ciSup_Iic [ConditionallyCompleteLattice α] (f : ι → α) (i : ι) : + partialSups f i = ⨆ i : Set.Iic i, f i := by + simp only [partialSups_apply] + apply le_antisymm + · exact sup'_le _ _ fun j hj ↦ le_ciSup_of_le (Set.finite_range _).bddAbove + ⟨j, by simpa only [Set.mem_Iic, mem_Iic] using hj⟩ le_rfl + · exact ciSup_le fun ⟨j, hj⟩ ↦ le_sup' f (by simpa only [mem_Iic, Set.mem_Iic] using hj) @[simp] -theorem ciSup_partialSups_eq {f : ℕ → α} (h : BddAbove (Set.range f)) : - ⨆ n, partialSups f n = ⨆ n, f n := by - refine (ciSup_le fun n => ?_).antisymm (ciSup_mono ?_ <| le_partialSups f) - · rw [partialSups_eq_ciSup_Iic] - exact ciSup_le fun i => le_ciSup h _ - · rwa [bddAbove_range_partialSups] +theorem ciSup_partialSups_eq [ConditionallyCompleteLattice α] + {f : ι → α} (h : BddAbove (Set.range f)) : + ⨆ i, partialSups f i = ⨆ i, f i := by + by_cases hι : Nonempty ι + · refine (ciSup_le fun i ↦ ?_).antisymm (ciSup_mono ?_ <| le_partialSups f) + · simpa only [partialSups_eq_ciSup_Iic] using ciSup_le fun i ↦ le_ciSup h _ + · rwa [bddAbove_range_partialSups] + · exact congr_arg _ (funext (not_nonempty_iff.mp hι).elim) + +/-- Version of `ciSup_partialSups_eq` without boundedness assumptions, but requiring a +`ConditionallyCompleteLinearOrder` rather than just a `ConditionallyCompleteLattice`. -/ +@[simp] +theorem ciSup_partialSups_eq' [ConditionallyCompleteLinearOrder α] (f : ι → α) : + ⨆ i, partialSups f i = ⨆ i, f i := by + by_cases h : BddAbove (Set.range f) + · exact ciSup_partialSups_eq h + · rw [iSup, iSup, ConditionallyCompleteLinearOrder.csSup_of_not_bddAbove _ h, + ConditionallyCompleteLinearOrder.csSup_of_not_bddAbove _ + (bddAbove_range_partialSups.not.mpr h)] end ConditionallyCompleteLattice section CompleteLattice -theorem partialSups_eq_biSup [CompleteLattice α] (f : ℕ → α) (n : ℕ) : - partialSups f n = ⨆ i ≤ n, f i := by - simpa only [iSup_subtype] using partialSups_eq_ciSup_Iic f n - -lemma partialSups_eq_sUnion_image [DecidableEq (Set α)] (s : ℕ → Set α) (n : ℕ) : - partialSups s n = ⋃₀ ↑((Finset.range (n + 1)).image s) := by - ext; simp [partialSups_eq_biSup, Nat.lt_succ_iff] - -lemma partialSups_eq_biUnion_range (s : ℕ → Set α) (n : ℕ) : - partialSups s n = ⋃ i ∈ Finset.range (n + 1), s i := by - ext; simp [partialSups_eq_biSup, Nat.lt_succ] - -variable [CompleteLattice α] +variable [Preorder ι] [LocallyFiniteOrderBot ι] [CompleteLattice α] -theorem iSup_partialSups_eq (f : ℕ → α) : ⨆ n, partialSups f n = ⨆ n, f n := +/-- Version of `ciSup_partialSups_eq` without boundedness assumptions, but requiring a +`CompleteLattice` rather than just a `ConditionallyCompleteLattice`. -/ +theorem iSup_partialSups_eq (f : ι → α) : + ⨆ i, partialSups f i = ⨆ i, f i := ciSup_partialSups_eq <| OrderTop.bddAbove _ -theorem iSup_le_iSup_of_partialSups_le_partialSups {f g : ℕ → α} - (h : partialSups f ≤ partialSups g) : ⨆ n, f n ≤ ⨆ n, g n := by +theorem partialSups_eq_biSup (f : ι → α) (i : ι) : + partialSups f i = ⨆ j ≤ i, f j := by + simpa only [iSup_subtype] using partialSups_eq_ciSup_Iic f i + +theorem iSup_le_iSup_of_partialSups_le_partialSups {f g : ι → α} + (h : partialSups f ≤ partialSups g) : ⨆ i, f i ≤ ⨆ i, g i := by rw [← iSup_partialSups_eq f, ← iSup_partialSups_eq g] exact iSup_mono h -theorem iSup_eq_iSup_of_partialSups_eq_partialSups {f g : ℕ → α} - (h : partialSups f = partialSups g) : ⨆ n, f n = ⨆ n, g n := by +theorem iSup_eq_iSup_of_partialSups_eq_partialSups {f g : ι → α} + (h : partialSups f = partialSups g) : ⨆ i, f i = ⨆ i, g i := by simp_rw [← iSup_partialSups_eq f, ← iSup_partialSups_eq g, h] end CompleteLattice + +section Set +/-! +### Functions into `Set α` +-/ + +lemma partialSups_eq_sUnion_image [DecidableEq (Set α)] (s : ℕ → Set α) (n : ℕ) : + partialSups s n = ⋃₀ ↑((Finset.range (n + 1)).image s) := by + ext; simp [partialSups_eq_biSup, Nat.lt_succ_iff] + +lemma partialSups_eq_biUnion_range (s : ℕ → Set α) (n : ℕ) : + partialSups s n = ⋃ i ∈ Finset.range (n + 1), s i := by + ext; simp [partialSups_eq_biSup, Nat.lt_succ] + +end Set diff --git a/Mathlib/RingTheory/Artinian/Module.lean b/Mathlib/RingTheory/Artinian/Module.lean index 3c1a202b25650..60a200a8eda6d 100644 --- a/Mathlib/RingTheory/Artinian/Module.lean +++ b/Mathlib/RingTheory/Artinian/Module.lean @@ -189,8 +189,8 @@ theorem disjoint_partial_infs_eventually_top (f : ℕ → Submodule R M) · apply w exact Nat.succ_le_succ_iff.mp p obtain ⟨n, w⟩ := monotone_stabilizes (partialSups (OrderDual.toDual ∘ f)) - refine ⟨n, fun m p => ?_⟩ - exact (h m).eq_bot_of_ge (sup_eq_left.1 <| (w (m + 1) <| le_add_right p).symm.trans <| w m p) + refine ⟨n, fun m p ↦ (h m).eq_bot_of_ge <| sup_eq_left.mp ?_⟩ + simpa only [partialSups_add_one] using (w (m + 1) <| le_add_right p).symm.trans <| w m p end IsArtinian diff --git a/Mathlib/RingTheory/Noetherian/Basic.lean b/Mathlib/RingTheory/Noetherian/Basic.lean index 6ddbaf53f56f5..be7045b5493a5 100644 --- a/Mathlib/RingTheory/Noetherian/Basic.lean +++ b/Mathlib/RingTheory/Noetherian/Basic.lean @@ -278,9 +278,8 @@ theorem IsNoetherian.disjoint_partialSups_eventually_bot · apply w exact Nat.succ_le_succ_iff.mp p obtain ⟨n, w⟩ := monotone_stabilizes_iff_noetherian.mpr inferInstance (partialSups f) - exact - ⟨n, fun m p => - (h m).eq_bot_of_ge <| sup_eq_left.1 <| (w (m + 1) <| le_add_right p).symm.trans <| w m p⟩ + refine ⟨n, fun m p ↦ (h m).eq_bot_of_ge <| sup_eq_left.mp ?_⟩ + simpa only [partialSups_add_one] using (w (m + 1) <| le_add_right p).symm.trans <| w m p end diff --git a/Mathlib/Topology/Order/PartialSups.lean b/Mathlib/Topology/Order/PartialSups.lean index 954b72b9b03aa..97ad3b105ec5a 100644 --- a/Mathlib/Topology/Order/PartialSups.lean +++ b/Mathlib/Topology/Order/PartialSups.lean @@ -30,7 +30,7 @@ protected lemma partialSups (hf : ∀ k ≤ n, Tendsto (f k) l (𝓝 (g k))) : protected lemma partialSups_apply (hf : ∀ k ≤ n, Tendsto (f k) l (𝓝 (g k))) : Tendsto (fun a ↦ partialSups (f · a) n) l (𝓝 (partialSups g n)) := by - simpa only [← partialSups_apply] using Tendsto.partialSups hf + simpa only [← Pi.partialSups_apply] using Tendsto.partialSups hf end Filter.Tendsto @@ -42,7 +42,7 @@ protected lemma ContinuousAt.partialSups_apply (hf : ∀ k ≤ n, ContinuousAt ( protected lemma ContinuousAt.partialSups (hf : ∀ k ≤ n, ContinuousAt (f k) x) : ContinuousAt (partialSups f n) x := by - simpa only [← partialSups_apply] using ContinuousAt.partialSups_apply hf + simpa only [← Pi.partialSups_apply] using ContinuousAt.partialSups_apply hf protected lemma ContinuousWithinAt.partialSups_apply (hf : ∀ k ≤ n, ContinuousWithinAt (f k) s x) : ContinuousWithinAt (fun a ↦ partialSups (f · a) n) s x := @@ -50,7 +50,7 @@ protected lemma ContinuousWithinAt.partialSups_apply (hf : ∀ k ≤ n, Continuo protected lemma ContinuousWithinAt.partialSups (hf : ∀ k ≤ n, ContinuousWithinAt (f k) s x) : ContinuousWithinAt (partialSups f n) s x := by - simpa only [← partialSups_apply] using ContinuousWithinAt.partialSups_apply hf + simpa only [← Pi.partialSups_apply] using ContinuousWithinAt.partialSups_apply hf protected lemma ContinuousOn.partialSups_apply (hf : ∀ k ≤ n, ContinuousOn (f k) s) : ContinuousOn (fun a ↦ partialSups (f · a) n) s := fun x hx ↦ From 4a30ca3ef1757348aacd416b9a7b02c455de6afd Mon Sep 17 00:00:00 2001 From: Yakov Pechersky Date: Tue, 14 Jan 2025 16:01:34 +0000 Subject: [PATCH 233/681] feat(RingTheory/Valuation): valuation integers ring is a Principal Ideal ring iff the valuation range is not densely ordered (#16619) --- Mathlib.lean | 1 + Mathlib/Order/Hom/Basic.lean | 10 +++ Mathlib/RingTheory/Valuation/Archimedean.lean | 81 +++++++++++++++++++ Mathlib/RingTheory/Valuation/Basic.lean | 28 ++++++- Mathlib/RingTheory/Valuation/Integers.lean | 11 ++- 5 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 Mathlib/RingTheory/Valuation/Archimedean.lean diff --git a/Mathlib.lean b/Mathlib.lean index 156b35b551c9f..7973c54efafa5 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4733,6 +4733,7 @@ import Mathlib.RingTheory.Unramified.Finite import Mathlib.RingTheory.Unramified.Locus import Mathlib.RingTheory.Unramified.Pi import Mathlib.RingTheory.Valuation.AlgebraInstances +import Mathlib.RingTheory.Valuation.Archimedean import Mathlib.RingTheory.Valuation.Basic import Mathlib.RingTheory.Valuation.ExtendToLocalization import Mathlib.RingTheory.Valuation.Integers diff --git a/Mathlib/Order/Hom/Basic.lean b/Mathlib/Order/Hom/Basic.lean index 4e602339f6803..1356370c024a2 100644 --- a/Mathlib/Order/Hom/Basic.lean +++ b/Mathlib/Order/Hom/Basic.lean @@ -529,6 +529,11 @@ def uliftMap (f : α →o β) : ULift α →o ULift β := end OrderHom +-- See note [lower instance priority] +instance (priority := 90) OrderHomClass.toOrderHomClassOrderDual [LE α] [LE β] + [FunLike F α β] [OrderHomClass F α β] : OrderHomClass F αᵒᵈ βᵒᵈ where + map_rel f := map_rel f + /-- Embeddings of partial orders that preserve `<` also preserve `≤`. -/ def RelEmbedding.orderEmbeddingOfLTEmbedding [PartialOrder α] [PartialOrder β] (f : ((· < ·) : α → α → Prop) ↪r ((· < ·) : β → β → Prop)) : α ↪o β := @@ -1294,6 +1299,11 @@ end BoundedOrder end LatticeIsos +-- See note [lower instance priority] +instance (priority := 90) OrderIsoClass.toOrderIsoClassOrderDual [LE α] [LE β] + [EquivLike F α β] [OrderIsoClass F α β] : OrderIsoClass F αᵒᵈ βᵒᵈ where + map_le_map_iff f := map_le_map_iff f + section DenselyOrdered lemma denselyOrdered_iff_of_orderIsoClass {X Y F : Type*} [Preorder X] [Preorder Y] diff --git a/Mathlib/RingTheory/Valuation/Archimedean.lean b/Mathlib/RingTheory/Valuation/Archimedean.lean new file mode 100644 index 0000000000000..2f6d1e71bf789 --- /dev/null +++ b/Mathlib/RingTheory/Valuation/Archimedean.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2024 Yakov Pechersky. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yakov Pechersky +-/ +import Mathlib.Algebra.Order.Archimedean.Submonoid +import Mathlib.Algebra.Order.Monoid.Submonoid +import Mathlib.GroupTheory.ArchimedeanDensely +import Mathlib.RingTheory.PrincipalIdealDomain +import Mathlib.RingTheory.UniqueFactorizationDomain.Defs +import Mathlib.RingTheory.Valuation.Integers +import Mathlib.RingTheory.Valuation.ValuationRing + +/-! +# Ring of integers under a given valuation in an multiplicatively archimedean codomain + +-/ + +section Field + +variable {F Γ₀ O : Type*} [Field F] [LinearOrderedCommGroupWithZero Γ₀] + [CommRing O] [Algebra O F] {v : Valuation F Γ₀} + +instance : LinearOrderedCommGroupWithZero (MonoidHom.mrange v) where + __ : CommGroupWithZero (MonoidHom.mrange v) := inferInstance + __ : LinearOrder (MonoidHom.mrange v) := inferInstance + zero_le_one := Subtype.coe_le_coe.mp zero_le_one + mul_le_mul_left := by + simp only [Subtype.forall, MonoidHom.mem_mrange, forall_exists_index, Submonoid.mk_mul_mk, + Subtype.mk_le_mk, forall_apply_eq_imp_iff] + intro a b hab c + exact mul_le_mul_left' hab (v c) + +namespace Valuation.Integers + +open scoped Function in +lemma wfDvdMonoid_iff_wellFounded_gt_on_v (hv : Integers v O) : + WfDvdMonoid O ↔ WellFounded ((· > ·) on (v ∘ algebraMap O F)) := by + refine ⟨fun _ ↦ wellFounded_dvdNotUnit.mono ?_, fun h ↦ ⟨h.mono ?_⟩⟩ <;> + simp [Function.onFun, hv.dvdNotUnit_iff_lt] + +open scoped Function Multiplicative in +lemma wellFounded_gt_on_v_iff_discrete_mrange [Nontrivial (MonoidHom.mrange v)ˣ] + (hv : Integers v O) : + WellFounded ((· > ·) on (v ∘ algebraMap O F)) ↔ + Nonempty (MonoidHom.mrange v ≃*o ℤₘ₀) := by + rw [← LinearOrderedCommGroupWithZero.wellFoundedOn_setOf_ge_gt_iff_nonempty_discrete_of_ne_zero + one_ne_zero, ← Set.wellFoundedOn_range] + classical + refine ⟨fun h ↦ (h.mapsTo Subtype.val ?_).mono' (by simp), fun h ↦ (h.mapsTo ?_ ?_).mono' ?_⟩ + · rintro ⟨_, x, rfl⟩ + simp only [← Subtype.coe_le_coe, OneMemClass.coe_one, Set.mem_setOf_eq, Set.mem_range, + Function.comp_apply] + intro hx + obtain ⟨y, rfl⟩ := hv.exists_of_le_one hx + exact ⟨y, by simp⟩ + · exact fun x ↦ if hx : x ∈ MonoidHom.mrange v then ⟨x, hx⟩ else 1 + · intro + simp only [Set.mem_range, Function.comp_apply, MonoidHom.mem_mrange, Set.mem_setOf_eq, + forall_exists_index] + rintro x rfl + simp [← Subtype.coe_le_coe, hv.map_le_one] + · simp [Function.onFun] + +lemma isPrincipalIdealRing_iff_not_denselyOrdered [MulArchimedean Γ₀] (hv : Integers v O) : + IsPrincipalIdealRing O ↔ ¬ DenselyOrdered (Set.range v) := by + refine ⟨fun _ ↦ not_denselyOrdered_of_isPrincipalIdealRing hv, fun H ↦ ?_⟩ + rcases subsingleton_or_nontrivial (MonoidHom.mrange v)ˣ with hs|_ + · have := bijective_algebraMap_of_subsingleton_units_mrange hv + exact .of_surjective _ (RingEquiv.ofBijective _ this).symm.surjective + have : IsDomain O := hv.hom_inj.isDomain + have : ValuationRing O := ValuationRing.of_integers v hv + have : IsBezout O := ValuationRing.instIsBezout + have := ((IsBezout.TFAE (R := O)).out 1 3) + rw [this, hv.wfDvdMonoid_iff_wellFounded_gt_on_v, hv.wellFounded_gt_on_v_iff_discrete_mrange, + LinearOrderedCommGroupWithZero.discrete_iff_not_denselyOrdered] + exact H + +end Valuation.Integers + +end Field diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index ea3d9cfaa4ec3..5ff8726949782 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -892,8 +892,7 @@ end AddValuation namespace Valuation - -variable {Γ₀ : Type*} [Ring R] [LinearOrderedCommMonoidWithZero Γ₀] +variable {K Γ₀ : Type*} [Ring R] [LinearOrderedCommMonoidWithZero Γ₀] /-- The `AddValuation` associated to a `Valuation`. -/ def toAddValuation : Valuation R Γ₀ ≃ AddValuation R (Additive Γ₀)ᵒᵈ := @@ -928,4 +927,29 @@ theorem ofAddValuation_apply (v : AddValuation R (Additive Γ₀)ᵒᵈ) (r : R) ofAddValuation v r = Additive.toMul (OrderDual.ofDual (v r)) := rfl +instance (v : Valuation R Γ₀) : CommMonoidWithZero (MonoidHom.mrange v) where + zero := ⟨0, 0, by simp⟩ + zero_mul := by + intro a + exact Subtype.ext (zero_mul a.val) + mul_zero := by + intro a + exact Subtype.ext (mul_zero a.val) + +@[simp] +lemma val_mrange_zero (v : Valuation R Γ₀) : ((0 : MonoidHom.mrange v) : Γ₀) = 0 := rfl + +instance {Γ₀} [LinearOrderedCommGroupWithZero Γ₀] [DivisionRing K] (v : Valuation K Γ₀) : + CommGroupWithZero (MonoidHom.mrange v) where + inv := fun x ↦ ⟨x⁻¹, by + obtain ⟨y, hy⟩ := x.prop + simp_rw [← hy, ← v.map_inv] + exact MonoidHom.mem_mrange.mpr ⟨_, rfl⟩⟩ + exists_pair_ne := ⟨⟨v 0, by simp⟩, ⟨v 1, by simp [- _root_.map_one]⟩, by simp⟩ + inv_zero := Subtype.ext inv_zero + mul_inv_cancel := by + rintro ⟨a, ha⟩ h + simp only [ne_eq, Subtype.ext_iff] at h + simpa using mul_inv_cancel₀ h + end Valuation diff --git a/Mathlib/RingTheory/Valuation/Integers.lean b/Mathlib/RingTheory/Valuation/Integers.lean index 8068ec0d266e9..47d321a9d32fc 100644 --- a/Mathlib/RingTheory/Valuation/Integers.lean +++ b/Mathlib/RingTheory/Valuation/Integers.lean @@ -172,6 +172,15 @@ theorem eq_algebraMap_or_inv_eq_algebraMap (hv : Integers v O) (x : F) : obtain ⟨a, ha⟩ := exists_of_le_one hv h exacts [⟨a, Or.inl ha.symm⟩, ⟨a, Or.inr ha.symm⟩] +lemma bijective_algebraMap_of_subsingleton_units_mrange (hv : Integers v O) + [Subsingleton (MonoidHom.mrange v)ˣ] : + Function.Bijective (algebraMap O F) := by + refine ⟨hv.hom_inj, fun x ↦ hv.exists_of_le_one ?_⟩ + rcases eq_or_ne x 0 with rfl|hx + · simp + · exact (congr_arg Units.val (Subsingleton.elim (α := (MonoidHom.mrange v)ˣ) + ((isUnit_iff_ne_zero.mpr hx).unit.map v.toMonoidHom.mrangeRestrict) 1)).le + lemma isPrincipal_iff_exists_isGreatest (hv : Integers v O) {I : Ideal O} : I.IsPrincipal ↔ ∃ x, IsGreatest (v ∘ algebraMap O F '' I) x := by constructor <;> rintro ⟨x, hx⟩ @@ -230,8 +239,6 @@ lemma not_denselyOrdered_of_isPrincipalIdealRing [IsPrincipalIdealRing O] (hv : obtain ⟨z, rfl⟩ := hv.exists_of_le_one hy₁.le exact hy.not_le <| hx ⟨hy₁, mem_range_self _⟩ --- TODO: isPrincipalIdealRing_iff_not_denselyOrdered when MulArchimedean - end Integers end Field From 1b272a8b24271676a3200364b9168fe3d4ada86e Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Tue, 14 Jan 2025 16:46:13 +0000 Subject: [PATCH 234/681] feat: generalize `CStarAlgebra.spectralOrder` to non-unital algebras (#20728) --- Mathlib/Algebra/Algebra/Quasispectrum.lean | 10 ++++ .../ContinuousFunctionalCalculus/Basic.lean | 46 +++++++++++++------ 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Quasispectrum.lean b/Mathlib/Algebra/Algebra/Quasispectrum.lean index 712888eb8d3ff..5dce203059f77 100644 --- a/Mathlib/Algebra/Algebra/Quasispectrum.lean +++ b/Mathlib/Algebra/Algebra/Quasispectrum.lean @@ -574,6 +574,16 @@ theorem quasispectrumRestricts_iff_spectrumRestricts_inr (S : Type*) {R A : Type rw [quasispectrumRestricts_iff, spectrumRestricts_iff, ← Unitization.quasispectrum_eq_spectrum_inr'] +/-- The difference from `quasispectrumRestricts_iff_spectrumRestricts_inr` is that the +`Unitization` may be taken with respect to a different scalar field. -/ +lemma quasispectrumRestricts_iff_spectrumRestricts_inr' + {R S' A : Type*} (S : Type*) [Semifield R] [Semifield S'] [Field S] [NonUnitalRing A] + [Module R A] [Module S' A] [Module S A] [IsScalarTower S A A] [SMulCommClass S A A] + [Algebra R S'] [Algebra S' S] [Algebra R S] [IsScalarTower S' S A] [IsScalarTower R S A] + {a : A} {f : S' → R} : + QuasispectrumRestricts a f ↔ SpectrumRestricts (a : Unitization S A) f := by + simp only [quasispectrumRestricts_iff, SpectrumRestricts, Unitization.quasispectrum_inr_eq] + theorem quasispectrumRestricts_iff_spectrumRestricts {R S A : Type*} [Semifield R] [Semifield S] [Ring A] [Algebra R S] [Algebra R A] [Algebra S A] {a : A} {f : S → R} : QuasispectrumRestricts a f ↔ SpectrumRestricts a f := by diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean index f7ca1d318f5d0..4df7e6a636e68 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean @@ -351,51 +351,67 @@ end NonnegSpectrumClass section SpectralOrder -variable (A : Type*) [CStarAlgebra A] +variable (A : Type*) [NonUnitalCStarAlgebra A] -/-- The partial order on a unital C⋆-algebra defined by `x ≤ y` if and only if `y - x` is +open scoped CStarAlgebra +/-- The partial order on a C⋆-algebra defined by `x ≤ y` if and only if `y - x` is selfadjoint and has nonnegative spectrum. This is not declared as an instance because one may already have a partial order with better definitional properties. However, it can be useful to invoke this as an instance in proofs. -/ @[reducible] def CStarAlgebra.spectralOrder : PartialOrder A where - le x y := IsSelfAdjoint (y - x) ∧ SpectrumRestricts (y - x) ContinuousMap.realToNNReal + le x y := IsSelfAdjoint (y - x) ∧ QuasispectrumRestricts (y - x) ContinuousMap.realToNNReal le_refl := by simp only [sub_self, IsSelfAdjoint.zero, true_and, forall_const] - rw [SpectrumRestricts.nnreal_iff] + rw [quasispectrumRestricts_iff_spectrumRestricts_inr' ℂ, SpectrumRestricts.nnreal_iff] nontriviality A simp le_antisymm x y hxy hyx := by + simp only at hxy hyx + rw [← Unitization.isSelfAdjoint_inr (R := ℂ), + quasispectrumRestricts_iff_spectrumRestricts_inr' ℂ, Unitization.inr_sub ℂ] at hxy hyx rw [← sub_eq_zero] - exact hyx.2.eq_zero_of_neg hyx.1 (neg_sub x y ▸ hxy.2) - le_trans x y z hxy hyz := - ⟨by simpa using hyz.1.add hxy.1, by simpa using hyz.2.nnreal_add hyz.1 hxy.1 hxy.2⟩ - -/-- The `CStarAlgebra.spectralOrder` on a unital C⋆-algebra is a `StarOrderedRing`. -/ + apply Unitization.inr_injective (R := ℂ) + rw [Unitization.inr_zero, Unitization.inr_sub] + exact hyx.2.eq_zero_of_neg hyx.1 (neg_sub (x : A⁺¹) (y : A⁺¹) ▸ hxy.2) + le_trans x y z hxy hyz := by + simp +singlePass only [← Unitization.isSelfAdjoint_inr (R := ℂ), + quasispectrumRestricts_iff_spectrumRestricts_inr' ℂ, Unitization.inr_sub] at hxy hyz ⊢ + exact ⟨by simpa using hyz.1.add hxy.1, by simpa using hyz.2.nnreal_add hyz.1 hxy.1 hxy.2⟩ + +/-- The `CStarAlgebra.spectralOrder` on a C⋆-algebra is a `StarOrderedRing`. -/ lemma CStarAlgebra.spectralOrderedRing : @StarOrderedRing A _ (CStarAlgebra.spectralOrder A) _ := let _ := CStarAlgebra.spectralOrder A { le_iff := by intro x y constructor · intro h - obtain ⟨s, hs₁, _, hs₂⟩ := CFC.exists_sqrt_of_isSelfAdjoint_of_spectrumRestricts h.1 h.2 - refine ⟨s ^ 2, ?_, by rwa [eq_sub_iff_add_eq', eq_comm] at hs₂⟩ + obtain ⟨s, hs₁, _, hs₂⟩ := + CFC.exists_sqrt_of_isSelfAdjoint_of_quasispectrumRestricts h.1 h.2 + refine ⟨s * s, ?_, by rwa [eq_sub_iff_add_eq', eq_comm] at hs₂⟩ exact AddSubmonoid.subset_closure ⟨s, by simp [hs₁.star_eq, sq]⟩ · rintro ⟨p, hp, rfl⟩ - suffices IsSelfAdjoint p ∧ SpectrumRestricts p ContinuousMap.realToNNReal from - ⟨by simpa using this.1, by simpa using this.2⟩ + show IsSelfAdjoint (x + p - x) ∧ + QuasispectrumRestricts (x + p - x) ContinuousMap.realToNNReal + simp only [add_sub_cancel_left] + --suffices IsSelfAdjoint p ∧ SpectrumRestricts p ContinuousMap.realToNNReal from + --⟨by simpa using this.1, by simpa using this.2⟩ induction hp using AddSubmonoid.closure_induction with | mem x hx => obtain ⟨s, rfl⟩ := hx refine ⟨IsSelfAdjoint.star_mul_self s, ?_⟩ - rw [SpectrumRestricts.nnreal_iff] + rw [quasispectrumRestricts_iff_spectrumRestricts_inr' ℂ, + SpectrumRestricts.nnreal_iff, Unitization.inr_mul, Unitization.inr_star] exact spectrum_star_mul_self_nonneg | one => - rw [SpectrumRestricts.nnreal_iff] + rw [quasispectrumRestricts_iff_spectrumRestricts_inr' ℂ, SpectrumRestricts.nnreal_iff] nontriviality A simp | mul x y _ _ hx hy => + simp +singlePass only [← Unitization.isSelfAdjoint_inr (R := ℂ), + quasispectrumRestricts_iff_spectrumRestricts_inr' ℂ] at hx hy ⊢ + rw [Unitization.inr_add] exact ⟨hx.1.add hy.1, hx.2.nnreal_add hx.1 hy.1 hy.2⟩ } end SpectralOrder From 30b9d3c060c068cd5c82676bbab08f239b7a03de Mon Sep 17 00:00:00 2001 From: Kyle Miller Date: Tue, 14 Jan 2025 17:43:29 +0000 Subject: [PATCH 235/681] fix: `rename_bvar` now handles mdata and mvars (#20743) Reported by Patrick Massot [on Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/rename_bvar.20is.20broken/near/493593195) --- Mathlib/Lean/Expr/Basic.lean | 1 + Mathlib/Tactic/RenameBVar.lean | 1 + MathlibTest/renameBvar.lean | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/Mathlib/Lean/Expr/Basic.lean b/Mathlib/Lean/Expr/Basic.lean index e00f5ad914dd0..bfb1353ed2c58 100644 --- a/Mathlib/Lean/Expr/Basic.lean +++ b/Mathlib/Lean/Expr/Basic.lean @@ -359,6 +359,7 @@ def renameBVar (e : Expr) (old new : Name) : Expr := lam (if n == old then new else n) (ty.renameBVar old new) (bd.renameBVar old new) bi | forallE n ty bd bi => forallE (if n == old then new else n) (ty.renameBVar old new) (bd.renameBVar old new) bi + | mdata d e' => mdata d (e'.renameBVar old new) | e => e open Lean.Meta in diff --git a/Mathlib/Tactic/RenameBVar.lean b/Mathlib/Tactic/RenameBVar.lean index f1b7e26041efa..db76e7084b530 100644 --- a/Mathlib/Tactic/RenameBVar.lean +++ b/Mathlib/Tactic/RenameBVar.lean @@ -42,6 +42,7 @@ Note: name clashes are resolved automatically. -/ elab "rename_bvar " old:ident " → " new:ident loc?:(location)? : tactic => do let mvarId ← getMainGoal + instantiateMVarDeclMVars mvarId match loc? with | none => renameBVarTarget mvarId old.getId new.getId | some loc => diff --git a/MathlibTest/renameBvar.lean b/MathlibTest/renameBvar.lean index 07fe22319cebf..a3a673b4e376e 100644 --- a/MathlibTest/renameBvar.lean +++ b/MathlibTest/renameBvar.lean @@ -1,4 +1,8 @@ import Mathlib.Tactic.RenameBVar +import Lean + +set_option linter.unusedVariables false +axiom test_sorry {α : Sort _} : α /- This test is somewhat flaky since it depends on the pretty printer. -/ /-- @@ -32,3 +36,27 @@ example (P : ℕ → ℕ → Prop) (h : ∀ n, ∃ m, P n m) : ∀ l, ∃ m, P l rename_bvar l → m trace_state exact h + +/-- +info: case intro +a b c : Int +h2 : b ∣ c +k : Int +hk : b = a * k +⊢ ∃ k, c = a * k +--- +info: case intro +a b c : Int +h2 : b ∣ c +k : Int +hk : b = a * k +⊢ ∃ m, c = a * m +-/ +#guard_msgs in +example (a b c : Int) (h1 : a ∣ b) (h2 : b ∣ c) : a ∣ c := by + rcases h1 with ⟨k, hk⟩ + show ∃ k, c = a * k + trace_state + rename_bvar k → m + trace_state + exact test_sorry From 74fff29536e0a0eeca1aa8421089b76b157a3b2f Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Tue, 14 Jan 2025 22:21:33 +0000 Subject: [PATCH 236/681] feat(Order/Atoms): atoms, coatoms in SetLike (#20736) Add `SetLike.isAtom_iff`, `SetLike.isCoatom_iff`, `SetLike.covBy_iff` and `SetLike.covBy_iff'` that translate the properties of being an atom, a coatom, or covby in a `SetLike` type. Use it to golf the proof if `Ideal.isMaximal_iff`. `SetLike.isCoatom_iff` was written by @alreadydone . Co-authored-by: Oliver Nash <7734364+ocfnash@users.noreply.github.com> --- Mathlib/Order/Atoms.lean | 40 +++++++++++++++++++++++++++ Mathlib/RingTheory/Ideal/Maximal.lean | 12 ++------ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Mathlib/Order/Atoms.lean b/Mathlib/Order/Atoms.lean index 8b875265266cf..399af4db89220 100644 --- a/Mathlib/Order/Atoms.lean +++ b/Mathlib/Order/Atoms.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ import Mathlib.Data.Set.Lattice +import Mathlib.Data.SetLike.Basic import Mathlib.Order.ModularLattice import Mathlib.Order.SuccPred.Basic import Mathlib.Order.WellFounded @@ -183,6 +184,45 @@ theorem covBy_top_iff : a ⋖ ⊤ ↔ IsCoatom a := alias ⟨CovBy.isCoatom, IsCoatom.covBy_top⟩ := covBy_top_iff +namespace SetLike + +variable {A B : Type*} [SetLike A B] + +theorem isAtom_iff [OrderBot A] {K : A} : + IsAtom K ↔ K ≠ ⊥ ∧ ∀ H g, H ≤ K → g ∉ H → g ∈ K → H = ⊥ := by + simp_rw [IsAtom, lt_iff_le_not_le, SetLike.not_le_iff_exists, + and_comm (a := _ ≤ _), and_imp, exists_imp, ← and_imp, and_comm] + +theorem isCoatom_iff [OrderTop A] {K : A} : + IsCoatom K ↔ K ≠ ⊤ ∧ ∀ H g, K ≤ H → g ∉ K → g ∈ H → H = ⊤ := by + simp_rw [IsCoatom, lt_iff_le_not_le, SetLike.not_le_iff_exists, + and_comm (a := _ ≤ _), and_imp, exists_imp, ← and_imp, and_comm] + +theorem covBy_iff {K L : A} : + K ⋖ L ↔ K < L ∧ ∀ H g, K ≤ H → H ≤ L → g ∉ K → g ∈ H → H = L := by + refine and_congr_right fun _ ↦ forall_congr' fun H ↦ ?_ + rw [lt_iff_le_not_le, SetLike.not_le_iff_exists, lt_iff_le_not_le, not_and, not_not, + and_comm (a := _ ≤ _), and_imp, exists_imp] + refine forall_congr' fun b ↦ ?_ + simp only [← and_imp] + rw [and_comm, and_comm (b:= _ ∈ _), and_assoc] + refine imp_congr_right fun ⟨_, h, _⟩ ↦ ?_ + simp only [le_antisymm_iff, h, true_and] + +/-- Dual variant of `SetLike.covBy_iff` -/ +theorem covBy_iff' {K L : A} : + K ⋖ L ↔ K < L ∧ ∀ H g, K ≤ H → H ≤ L → g ∉ H → g ∈ L → H = K := by + refine and_congr_right fun _ ↦ forall_congr' fun H ↦ ?_ + rw [imp_not_comm, lt_iff_le_not_le, SetLike.not_le_iff_exists, lt_iff_le_not_le, not_and, not_not, + and_comm (a := _ ≤ _), and_imp, exists_imp] + refine forall_congr' fun b ↦ ?_ + simp only [← and_imp] + rw [and_comm (b := K ≤ _), and_comm, and_comm (b:= _ ∈ _), and_assoc] + refine imp_congr_right fun ⟨h, _⟩ ↦ ?_ + simp only [le_antisymm_iff, h, and_true] + +end SetLike + end PartialOrder theorem iInf_le_coatom [Order.Coframe α] {a : α} (ha : IsCoatom a) {f : ι → α} : diff --git a/Mathlib/RingTheory/Ideal/Maximal.lean b/Mathlib/RingTheory/Ideal/Maximal.lean index c3cb20cf054d0..bb913acd39e29 100644 --- a/Mathlib/RingTheory/Ideal/Maximal.lean +++ b/Mathlib/RingTheory/Ideal/Maximal.lean @@ -51,16 +51,8 @@ theorem IsMaximal.ne_top {I : Ideal α} (h : I.IsMaximal) : I ≠ ⊤ := (isMaximal_def.1 h).1 theorem isMaximal_iff {I : Ideal α} : - I.IsMaximal ↔ (1 : α) ∉ I ∧ ∀ (J : Ideal α) (x), I ≤ J → x ∉ I → x ∈ J → (1 : α) ∈ J := - isMaximal_def.trans <| - and_congr I.ne_top_iff_one <| - forall_congr' fun J => by - rw [lt_iff_le_not_le] - exact - ⟨fun H x h hx₁ hx₂ => J.eq_top_iff_one.1 <| H ⟨h, not_subset.2 ⟨_, hx₂, hx₁⟩⟩, - fun H ⟨h₁, h₂⟩ => - let ⟨x, xJ, xI⟩ := not_subset.1 h₂ - J.eq_top_iff_one.2 <| H x h₁ xI xJ⟩ + I.IsMaximal ↔ (1 : α) ∉ I ∧ ∀ (J : Ideal α) (x), I ≤ J → x ∉ I → x ∈ J → (1 : α) ∈ J := by + simp_rw [isMaximal_def, SetLike.isCoatom_iff, Ideal.ne_top_iff_one, ← Ideal.eq_top_iff_one] theorem IsMaximal.eq_of_le {I J : Ideal α} (hI : I.IsMaximal) (hJ : J ≠ ⊤) (IJ : I ≤ J) : I = J := eq_iff_le_not_lt.2 ⟨IJ, fun h => hJ (hI.1.2 _ h)⟩ From 881129a0609a61353297993027b0a26e068395b6 Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Tue, 14 Jan 2025 22:55:18 +0000 Subject: [PATCH 237/681] feat(Set/Function): prove surjectivity from composition (#20754) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These lemmas were present for `Function.Injective` and `Function.Surjective`, but not for their partial versions. Useful from the disproof of the Aharoni–Korman conjecture, https://github.com/leanprover-community/mathlib4/pull/20082. --- Mathlib/Data/Set/Function.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index c29e123ed9246..a0711752d0b0d 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -514,6 +514,9 @@ lemma injOn_id (s : Set α) : InjOn id s := injective_id.injOn theorem InjOn.comp (hg : InjOn g t) (hf : InjOn f s) (h : MapsTo f s t) : InjOn (g ∘ f) s := fun _ hx _ hy heq => hf hx hy <| hg (h hx) (h hy) heq +lemma InjOn.of_comp (h : InjOn (g ∘ f) s) : InjOn f s := + fun _ hx _ hy heq ↦ h hx hy (by simp [heq]) + lemma InjOn.image_of_comp (h : InjOn (g ∘ f) s) : InjOn g (f '' s) := forall_mem_image.2 fun _x hx ↦ forall_mem_image.2 fun _y hy heq ↦ congr_arg f <| h hx hy heq @@ -763,6 +766,11 @@ lemma surjOn_id (s : Set α) : SurjOn id s s := by simp [SurjOn, subset_rfl] theorem SurjOn.comp (hg : SurjOn g t p) (hf : SurjOn f s t) : SurjOn (g ∘ f) s p := Subset.trans hg <| Subset.trans (image_subset g hf) <| image_comp g f s ▸ Subset.refl _ +lemma SurjOn.of_comp (h : SurjOn (g ∘ f) s p) (hr : MapsTo f s t) : SurjOn g t p := by + intro z hz + obtain ⟨x, hx, rfl⟩ := h hz + exact ⟨f x, hr hx, rfl⟩ + lemma SurjOn.iterate {f : α → α} {s : Set α} (h : SurjOn f s s) : ∀ n, SurjOn f^[n] s s | 0 => surjOn_id _ | (n + 1) => (h.iterate n).comp h From decffa078a6c8823ac43c261a07a4f8b2d4fad5f Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Wed, 15 Jan 2025 01:11:06 +0000 Subject: [PATCH 238/681] chore: update Mathlib dependencies 2025-01-15 (#20762) 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 761d89f905070..7cc60c94958f9 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "c104265c34eb8181af14e8dbc14c2f034292cb02", + "rev": "5b23a1297aba9683f231c4b1a7ab4076af4ad53d", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From dc5b3f0c90e6e91580442a3ec4df5cf3ee638eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 15 Jan 2025 07:14:50 +0000 Subject: [PATCH 239/681] chore(Idempotent): split into `Group`, `GroupWithZero` and `Ring` parts (#20742) Split `Algebra.Idempotents` into `Algebra.Group.Idempotent`, `Algebra.GroupWithZero.Idempotent`, `Algebra.Ring.Idempotent`. Rename `Order.Idempotents` to `Algebra.Order.Ring.Idempotent`. --- Mathlib.lean | 6 +- Mathlib/Algebra/Group/Idempotent.lean | 98 +++++++++++ .../Algebra/Group/Submonoid/Membership.lean | 2 +- Mathlib/Algebra/GroupWithZero/Idempotent.lean | 39 +++++ .../Order/Ring/Idempotent.lean} | 2 +- Mathlib/Algebra/Ring/Idempotent.lean | 77 +++++++++ Mathlib/Algebra/Ring/Idempotents.lean | 158 ------------------ Mathlib/Analysis/NormedSpace/MStructure.lean | 2 +- Mathlib/LinearAlgebra/Span/Basic.lean | 1 - Mathlib/RingTheory/Filtration.lean | 2 +- Mathlib/RingTheory/Ideal/Cotangent.lean | 2 +- Mathlib/RingTheory/Ideal/IdempotentFG.lean | 2 +- Mathlib/RingTheory/Ideal/Span.lean | 1 + scripts/noshake.json | 2 + 14 files changed, 227 insertions(+), 167 deletions(-) create mode 100644 Mathlib/Algebra/Group/Idempotent.lean create mode 100644 Mathlib/Algebra/GroupWithZero/Idempotent.lean rename Mathlib/{Order/Idempotents.lean => Algebra/Order/Ring/Idempotent.lean} (99%) create mode 100644 Mathlib/Algebra/Ring/Idempotent.lean delete mode 100644 Mathlib/Algebra/Ring/Idempotents.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7973c54efafa5..66a8c3c4ffe4e 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -296,6 +296,7 @@ import Mathlib.Algebra.Group.Hom.CompTypeclasses import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Group.Hom.End import Mathlib.Algebra.Group.Hom.Instances +import Mathlib.Algebra.Group.Idempotent import Mathlib.Algebra.Group.Indicator import Mathlib.Algebra.Group.InjSurj import Mathlib.Algebra.Group.Int.Defs @@ -388,6 +389,7 @@ import Mathlib.Algebra.GroupWithZero.Conj import Mathlib.Algebra.GroupWithZero.Defs import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.GroupWithZero.Hom +import Mathlib.Algebra.GroupWithZero.Idempotent import Mathlib.Algebra.GroupWithZero.Indicator import Mathlib.Algebra.GroupWithZero.InjSurj import Mathlib.Algebra.GroupWithZero.Invertible @@ -780,6 +782,7 @@ import Mathlib.Algebra.Order.Ring.Cast import Mathlib.Algebra.Order.Ring.Cone import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.Ring.Finset +import Mathlib.Algebra.Order.Ring.Idempotent import Mathlib.Algebra.Order.Ring.InjSurj import Mathlib.Algebra.Order.Ring.Int import Mathlib.Algebra.Order.Ring.Nat @@ -904,7 +907,7 @@ import Mathlib.Algebra.Ring.Ext import Mathlib.Algebra.Ring.Fin import Mathlib.Algebra.Ring.Hom.Basic import Mathlib.Algebra.Ring.Hom.Defs -import Mathlib.Algebra.Ring.Idempotents +import Mathlib.Algebra.Ring.Idempotent import Mathlib.Algebra.Ring.Identities import Mathlib.Algebra.Ring.InjSurj import Mathlib.Algebra.Ring.Int.Defs @@ -4179,7 +4182,6 @@ import Mathlib.Order.Hom.Lattice import Mathlib.Order.Hom.Order import Mathlib.Order.Hom.Set import Mathlib.Order.Ideal -import Mathlib.Order.Idempotents import Mathlib.Order.InitialSeg import Mathlib.Order.Interval.Basic import Mathlib.Order.Interval.Finset.Basic diff --git a/Mathlib/Algebra/Group/Idempotent.lean b/Mathlib/Algebra/Group/Idempotent.lean new file mode 100644 index 0000000000000..af377dc9635a4 --- /dev/null +++ b/Mathlib/Algebra/Group/Idempotent.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2022 Christopher Hoskin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christopher Hoskin +-/ +import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.Group.Commute.Defs +import Mathlib.Algebra.Group.Hom.Defs +import Mathlib.Data.Subtype +import Mathlib.Tactic.MinImports + +/-! +# Idempotents + +This file defines idempotents for an arbitrary multiplication and proves some basic results, +including: + +* `IsIdempotentElem.mul_of_commute`: In a semigroup, the product of two commuting idempotents is + an idempotent; +* `IsIdempotentElem.pow_succ_eq`: In a monoid `a ^ (n+1) = a` for `a` an idempotent and `n` a + natural number. + +## Tags + +projection, idempotent +-/ + +assert_not_exists GroupWithZero + +variable {M N S : Type*} + +/-- An element `a` is said to be idempotent if `a * a = a`. -/ +def IsIdempotentElem [Mul M] (a : M) : Prop := a * a = a + +namespace IsIdempotentElem +section Mul +variable [Mul M] {a : M} + +lemma of_isIdempotent [Std.IdempotentOp (α := M) (· * ·)] (a : M) : IsIdempotentElem a := + Std.IdempotentOp.idempotent a + +lemma eq (ha : IsIdempotentElem a) : a * a = a := ha + +end Mul + +section Semigroup +variable [Semigroup S] {a b : S} + +lemma mul_of_commute (hab : Commute a b) (ha : IsIdempotentElem a) (hb : IsIdempotentElem b) : + IsIdempotentElem (a * b) := by rw [IsIdempotentElem, hab.symm.mul_mul_mul_comm, ha.eq, hb.eq] + +end Semigroup + +section CommSemigroup +variable [CommSemigroup S] {a b : S} + +lemma mul (ha : IsIdempotentElem a) (hb : IsIdempotentElem b) : IsIdempotentElem (a * b) := + ha.mul_of_commute (.all ..) hb + +end CommSemigroup + +section MulOneClass +variable [MulOneClass M] {a : M} + +lemma one : IsIdempotentElem (1 : M) := mul_one _ + +instance : One {a : M // IsIdempotentElem a} where one := ⟨1, one⟩ + +@[simp, norm_cast] lemma coe_one : ↑(1 : {a : M // IsIdempotentElem a}) = (1 : M) := rfl + +end MulOneClass + +section Monoid +variable [Monoid M] {a : M} + +lemma pow (n : ℕ) (h : IsIdempotentElem a) : IsIdempotentElem (a ^ n) := + Nat.recOn n ((pow_zero a).symm ▸ one) fun n _ => + show a ^ n.succ * a ^ n.succ = a ^ n.succ by + conv_rhs => rw [← h.eq] -- Porting note: was `nth_rw 3 [← h.eq]` + rw [← sq, ← sq, ← pow_mul, ← pow_mul'] + +lemma pow_succ_eq (n : ℕ) (h : IsIdempotentElem a) : a ^ (n + 1) = a := + Nat.recOn n ((Nat.zero_add 1).symm ▸ pow_one a) fun n ih => by rw [pow_succ, ih, h.eq] + +end Monoid + +section CancelMonoid +variable [CancelMonoid M] {a : M} + +@[simp] lemma iff_eq_one : IsIdempotentElem a ↔ a = 1 := by simp [IsIdempotentElem] + +end CancelMonoid + +lemma map {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N] {e : M} + (he : IsIdempotentElem e) (f : F) : IsIdempotentElem (f e) := by + rw [IsIdempotentElem, ← map_mul, he.eq] + +end IsIdempotentElem diff --git a/Mathlib/Algebra/Group/Submonoid/Membership.lean b/Mathlib/Algebra/Group/Submonoid/Membership.lean index 82f50808f2140..8121874d5e833 100644 --- a/Mathlib/Algebra/Group/Submonoid/Membership.lean +++ b/Mathlib/Algebra/Group/Submonoid/Membership.lean @@ -5,10 +5,10 @@ Authors: Johannes Hölzl, Kenny Lau, Johan Commelin, Mario Carneiro, Kevin Buzza Amelia Livingston, Yury Kudryashov -/ import Mathlib.Algebra.FreeMonoid.Basic +import Mathlib.Algebra.Group.Idempotent import Mathlib.Algebra.Group.Submonoid.MulOpposite import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.GroupWithZero.Divisibility -import Mathlib.Algebra.Ring.Idempotents import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Data.Fintype.Card import Mathlib.Data.Nat.Cast.Basic diff --git a/Mathlib/Algebra/GroupWithZero/Idempotent.lean b/Mathlib/Algebra/GroupWithZero/Idempotent.lean new file mode 100644 index 0000000000000..1b7907ca96787 --- /dev/null +++ b/Mathlib/Algebra/GroupWithZero/Idempotent.lean @@ -0,0 +1,39 @@ +/- +Copyright (c) 2022 Christopher Hoskin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christopher Hoskin +-/ +import Mathlib.Algebra.Group.Idempotent +import Mathlib.Algebra.GroupWithZero.Defs + +/-! +# Idempotent elements of a group with zero +-/ + +assert_not_exists Ring + +variable {M N S M₀ M₁ R G G₀ : Type*} +variable [MulOneClass M₁] [CancelMonoidWithZero G₀] + +namespace IsIdempotentElem +section MulZeroClass +variable [MulZeroClass M₀] + +lemma zero : IsIdempotentElem (0 : M₀) := mul_zero _ + +instance : Zero { p : M₀ // IsIdempotentElem p } where zero := ⟨0, zero⟩ + +@[simp] lemma coe_zero : ↑(0 : { p : M₀ // IsIdempotentElem p }) = (0 : M₀) := rfl + +end MulZeroClass + +section CancelMonoidWithZero +variable [CancelMonoidWithZero M₀] + +@[simp] +lemma iff_eq_zero_or_one {p : G₀} : IsIdempotentElem p ↔ p = 0 ∨ p = 1 where + mp h := or_iff_not_imp_left.mpr fun hp ↦ mul_left_cancel₀ hp (h.trans (mul_one p).symm) + mpr h := h.elim (fun hp => hp.symm ▸ zero) fun hp => hp.symm ▸ one + +end CancelMonoidWithZero +end IsIdempotentElem diff --git a/Mathlib/Order/Idempotents.lean b/Mathlib/Algebra/Order/Ring/Idempotent.lean similarity index 99% rename from Mathlib/Order/Idempotents.lean rename to Mathlib/Algebra/Order/Ring/Idempotent.lean index e872f7be5ab00..fd3c4ab4bc208 100644 --- a/Mathlib/Order/Idempotents.lean +++ b/Mathlib/Algebra/Order/Ring/Idempotent.lean @@ -3,7 +3,7 @@ Copyright (c) 2025 Junyan Xu. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Junyan Xu -/ -import Mathlib.Algebra.Ring.Idempotents +import Mathlib.Algebra.Ring.Idempotent import Mathlib.Order.BooleanAlgebra import Mathlib.Order.Hom.Basic diff --git a/Mathlib/Algebra/Ring/Idempotent.lean b/Mathlib/Algebra/Ring/Idempotent.lean new file mode 100644 index 0000000000000..71443f71deacd --- /dev/null +++ b/Mathlib/Algebra/Ring/Idempotent.lean @@ -0,0 +1,77 @@ +/- +Copyright (c) 2022 Christopher Hoskin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christopher Hoskin +-/ +import Mathlib.Algebra.GroupWithZero.Idempotent +import Mathlib.Algebra.Ring.Defs +import Mathlib.Order.Notation + +/-! +# Idempotent elements of a ring + +This file proves result about idempotent elements of a ring, like: +* `IsIdempotentElem.one_sub_iff`: In a (non-associative) ring, `a` is an idempotent if and only if + `1 - a` is an idempotent. +-/ + +variable {R : Type*} + +namespace IsIdempotentElem +section NonAssocRing +variable [NonAssocRing R] {a : R} + +lemma one_sub (h : IsIdempotentElem a) : IsIdempotentElem (1 - a) := by + rw [IsIdempotentElem, mul_sub, mul_one, sub_mul, one_mul, h.eq, sub_self, sub_zero] + +@[simp] +lemma one_sub_iff : IsIdempotentElem (1 - a) ↔ IsIdempotentElem a := + ⟨fun h => sub_sub_cancel 1 a ▸ h.one_sub, IsIdempotentElem.one_sub⟩ + +@[simp] +lemma mul_one_sub_self (h : IsIdempotentElem a) : a * (1 - a) = 0 := by + rw [mul_sub, mul_one, h.eq, sub_self] + +@[simp] +lemma one_sub_mul_self (h : IsIdempotentElem a) : (1 - a) * a = 0 := by + rw [sub_mul, one_mul, h.eq, sub_self] + +instance : HasCompl {a : R // IsIdempotentElem a} where compl a := ⟨1 - a, a.prop.one_sub⟩ + +@[simp] lemma coe_compl (a : {a : R // IsIdempotentElem a}) : ↑aᶜ = (1 : R) - ↑a := rfl + +@[simp] lemma compl_compl (a : {a : R // IsIdempotentElem a}) : aᶜᶜ = a := by ext; simp +@[simp] lemma zero_compl : (0 : {a : R // IsIdempotentElem a})ᶜ = 1 := by ext; simp +@[simp] lemma one_compl : (1 : {a : R // IsIdempotentElem a})ᶜ = 0 := by ext; simp + +end NonAssocRing + +section Semiring +variable [Semiring R] {a b : R} + +lemma of_mul_add (mul : a * b = 0) (add : a + b = 1) : IsIdempotentElem a ∧ IsIdempotentElem b := by + simp_rw [IsIdempotentElem]; constructor + · conv_rhs => rw [← mul_one a, ← add, mul_add, mul, add_zero] + · conv_rhs => rw [← one_mul b, ← add, add_mul, mul, zero_add] + +end Semiring + +section Ring +variable [Ring R] {a b : R} + +lemma add_sub_mul_of_commute (h : Commute a b) (hp : IsIdempotentElem a) (hq : IsIdempotentElem b) : + IsIdempotentElem (a + b - a * b) := by + convert (hp.one_sub.mul_of_commute ?_ hq.one_sub).one_sub using 1 + · simp_rw [sub_mul, mul_sub, one_mul, mul_one, sub_sub, sub_sub_cancel, add_sub, add_comm] + · simp_rw [commute_iff_eq, sub_mul, mul_sub, one_mul, mul_one, sub_sub, add_sub, add_comm, h.eq] + +end Ring + +section CommRing +variable [CommRing R] {a b : R} + +lemma add_sub_mul (hp : IsIdempotentElem a) (hq : IsIdempotentElem b) : + IsIdempotentElem (a + b - a * b) := add_sub_mul_of_commute (.all ..) hp hq + +end CommRing +end IsIdempotentElem diff --git a/Mathlib/Algebra/Ring/Idempotents.lean b/Mathlib/Algebra/Ring/Idempotents.lean deleted file mode 100644 index 9be312f90d4da..0000000000000 --- a/Mathlib/Algebra/Ring/Idempotents.lean +++ /dev/null @@ -1,158 +0,0 @@ -/- -Copyright (c) 2022 Christopher Hoskin. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Christopher Hoskin --/ -import Mathlib.Algebra.Group.Basic -import Mathlib.Algebra.Group.Commute.Defs -import Mathlib.Algebra.Group.Hom.Defs -import Mathlib.Algebra.Ring.Defs -import Mathlib.Data.Subtype -import Mathlib.Order.Notation - -/-! -# Idempotents - -This file defines idempotents for an arbitrary multiplication and proves some basic results, -including: - -* `IsIdempotentElem.mul_of_commute`: In a semigroup, the product of two commuting idempotents is - an idempotent; -* `IsIdempotentElem.one_sub_iff`: In a (non-associative) ring, `p` is an idempotent if and only if - `1-p` is an idempotent. -* `IsIdempotentElem.pow_succ_eq`: In a monoid `p ^ (n+1) = p` for `p` an idempotent and `n` a - natural number. - -## Tags - -projection, idempotent --/ - - -variable {M N S M₀ M₁ R G G₀ : Type*} -variable [Mul M] [Monoid N] [Semigroup S] [MulZeroClass M₀] [MulOneClass M₁] [NonAssocRing R] - [Group G] [CancelMonoidWithZero G₀] - -/-- An element `p` is said to be idempotent if `p * p = p` --/ -def IsIdempotentElem (p : M) : Prop := - p * p = p - -namespace IsIdempotentElem - -theorem of_isIdempotent [Std.IdempotentOp (α := M) (· * ·)] (a : M) : IsIdempotentElem a := - Std.IdempotentOp.idempotent a - -theorem eq {p : M} (h : IsIdempotentElem p) : p * p = p := - h - -theorem mul_of_commute {p q : S} (h : Commute p q) (h₁ : IsIdempotentElem p) - (h₂ : IsIdempotentElem q) : IsIdempotentElem (p * q) := by - rw [IsIdempotentElem, mul_assoc, ← mul_assoc q, ← h.eq, mul_assoc p, h₂.eq, ← mul_assoc, h₁.eq] - -lemma mul {M} [CommSemigroup M] {e₁ e₂ : M} - (he₁ : IsIdempotentElem e₁) (he₂ : IsIdempotentElem e₂) : IsIdempotentElem (e₁ * e₂) := - he₁.mul_of_commute (.all e₁ e₂) he₂ - -theorem zero : IsIdempotentElem (0 : M₀) := - mul_zero _ - -theorem one : IsIdempotentElem (1 : M₁) := - mul_one _ - -theorem one_sub {p : R} (h : IsIdempotentElem p) : IsIdempotentElem (1 - p) := by - rw [IsIdempotentElem, mul_sub, mul_one, sub_mul, one_mul, h.eq, sub_self, sub_zero] - -@[simp] -theorem one_sub_iff {p : R} : IsIdempotentElem (1 - p) ↔ IsIdempotentElem p := - ⟨fun h => sub_sub_cancel 1 p ▸ h.one_sub, IsIdempotentElem.one_sub⟩ - -@[simp] -theorem mul_one_sub_self {p : R} (h : IsIdempotentElem p) : p * (1 - p) = 0 := by - rw [mul_sub, mul_one, h.eq, sub_self] - -@[simp] -theorem one_sub_mul_self {p : R} (h : IsIdempotentElem p) : (1 - p) * p = 0 := by - rw [sub_mul, one_mul, h.eq, sub_self] - -theorem add_sub_mul_of_commute {R} [Ring R] {p q : R} (h : Commute p q) - (hp : IsIdempotentElem p) (hq : IsIdempotentElem q) : - IsIdempotentElem (p + q - p * q) := by - convert (hp.one_sub.mul_of_commute ?_ hq.one_sub).one_sub using 1 - · simp_rw [sub_mul, mul_sub, one_mul, mul_one, sub_sub, sub_sub_cancel, add_sub, add_comm] - · simp_rw [commute_iff_eq, sub_mul, mul_sub, one_mul, mul_one, sub_sub, add_sub, add_comm, h.eq] - -theorem add_sub_mul {R} [CommRing R] {p q : R} (hp : IsIdempotentElem p) (hq : IsIdempotentElem q) : - IsIdempotentElem (p + q - p * q) := - add_sub_mul_of_commute (mul_comm p q) hp hq - -theorem pow {p : N} (n : ℕ) (h : IsIdempotentElem p) : IsIdempotentElem (p ^ n) := - Nat.recOn n ((pow_zero p).symm ▸ one) fun n _ => - show p ^ n.succ * p ^ n.succ = p ^ n.succ by - conv_rhs => rw [← h.eq] -- Porting note: was `nth_rw 3 [← h.eq]` - rw [← sq, ← sq, ← pow_mul, ← pow_mul'] - -theorem pow_succ_eq {p : N} (n : ℕ) (h : IsIdempotentElem p) : p ^ (n + 1) = p := - Nat.recOn n ((Nat.zero_add 1).symm ▸ pow_one p) fun n ih => by rw [pow_succ, ih, h.eq] - -@[simp] -theorem iff_eq_one {p : G} : IsIdempotentElem p ↔ p = 1 := - Iff.intro (fun h => mul_left_cancel ((mul_one p).symm ▸ h.eq : p * p = p * 1)) fun h => - h.symm ▸ one - -@[simp] -theorem iff_eq_zero_or_one {p : G₀} : IsIdempotentElem p ↔ p = 0 ∨ p = 1 := by - refine - Iff.intro (fun h => or_iff_not_imp_left.mpr fun hp => ?_) fun h => - h.elim (fun hp => hp.symm ▸ zero) fun hp => hp.symm ▸ one - exact mul_left_cancel₀ hp (h.trans (mul_one p).symm) - -lemma map {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N] {e : M} - (he : IsIdempotentElem e) (f : F) : IsIdempotentElem (f e) := by - rw [IsIdempotentElem, ← map_mul, he.eq] - -lemma of_mul_add {R} [Semiring R] {e₁ e₂ : R} (mul : e₁ * e₂ = 0) (add : e₁ + e₂ = 1) : - IsIdempotentElem e₁ ∧ IsIdempotentElem e₂ := by - simp_rw [IsIdempotentElem]; constructor - · conv_rhs => rw [← mul_one e₁, ← add, mul_add, mul, add_zero] - · conv_rhs => rw [← one_mul e₂, ← add, add_mul, mul, zero_add] - -/-! ### Instances on `Subtype IsIdempotentElem` -/ - - -section Instances - -instance : Zero { p : M₀ // IsIdempotentElem p } where zero := ⟨0, zero⟩ - -@[simp] -theorem coe_zero : ↑(0 : { p : M₀ // IsIdempotentElem p }) = (0 : M₀) := - rfl - -instance : One { p : M₁ // IsIdempotentElem p } where one := ⟨1, one⟩ - -@[simp] -theorem coe_one : ↑(1 : { p : M₁ // IsIdempotentElem p }) = (1 : M₁) := - rfl - -instance : HasCompl { p : R // IsIdempotentElem p } := - ⟨fun p => ⟨1 - p, p.prop.one_sub⟩⟩ - -@[simp] -theorem coe_compl (p : { p : R // IsIdempotentElem p }) : ↑pᶜ = (1 : R) - ↑p := - rfl - -@[simp] -theorem compl_compl (p : { p : R // IsIdempotentElem p }) : pᶜᶜ = p := - Subtype.ext <| sub_sub_cancel _ _ - -@[simp] -theorem zero_compl : (0 : { p : R // IsIdempotentElem p })ᶜ = 1 := - Subtype.ext <| sub_zero _ - -@[simp] -theorem one_compl : (1 : { p : R // IsIdempotentElem p })ᶜ = 0 := - Subtype.ext <| sub_self _ - -end Instances - -end IsIdempotentElem diff --git a/Mathlib/Analysis/NormedSpace/MStructure.lean b/Mathlib/Analysis/NormedSpace/MStructure.lean index daa293a5f0d87..94758ad5cf291 100644 --- a/Mathlib/Analysis/NormedSpace/MStructure.lean +++ b/Mathlib/Analysis/NormedSpace/MStructure.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Christopher Hoskin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Christopher Hoskin -/ -import Mathlib.Algebra.Ring.Idempotents +import Mathlib.Algebra.Ring.Idempotent import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Order.Basic import Mathlib.Tactic.NoncommRing diff --git a/Mathlib/LinearAlgebra/Span/Basic.lean b/Mathlib/LinearAlgebra/Span/Basic.lean index 9da8fb60044f6..102160c3b2d27 100644 --- a/Mathlib/LinearAlgebra/Span/Basic.lean +++ b/Mathlib/LinearAlgebra/Span/Basic.lean @@ -9,7 +9,6 @@ import Mathlib.Algebra.Module.Submodule.EqLocus import Mathlib.Algebra.Module.Submodule.Equiv import Mathlib.Algebra.Module.Submodule.RestrictScalars import Mathlib.Algebra.NoZeroSMulDivisors.Basic -import Mathlib.Algebra.Ring.Idempotents import Mathlib.Data.Set.Pointwise.SMul import Mathlib.LinearAlgebra.Span.Defs import Mathlib.Order.CompactlyGenerated.Basic diff --git a/Mathlib/RingTheory/Filtration.lean b/Mathlib/RingTheory/Filtration.lean index ea599e0713283..e7e62f2646f48 100644 --- a/Mathlib/RingTheory/Filtration.lean +++ b/Mathlib/RingTheory/Filtration.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.Algebra.Polynomial.Module.Basic -import Mathlib.Algebra.Ring.Idempotents +import Mathlib.Algebra.Ring.Idempotent import Mathlib.Order.Basic import Mathlib.Order.Hom.Lattice import Mathlib.RingTheory.Finiteness.Nakayama diff --git a/Mathlib/RingTheory/Ideal/Cotangent.lean b/Mathlib/RingTheory/Ideal/Cotangent.lean index 727ba571e6518..611a2eabec2f7 100644 --- a/Mathlib/RingTheory/Ideal/Cotangent.lean +++ b/Mathlib/RingTheory/Ideal/Cotangent.lean @@ -5,7 +5,7 @@ Authors: Andrew Yang -/ import Mathlib.RingTheory.Ideal.Operations import Mathlib.Algebra.Module.Torsion -import Mathlib.Algebra.Ring.Idempotents +import Mathlib.Algebra.Ring.Idempotent import Mathlib.LinearAlgebra.Dimension.FreeAndStrongRankCondition import Mathlib.LinearAlgebra.FiniteDimensional.Defs import Mathlib.RingTheory.LocalRing.ResidueField.Basic diff --git a/Mathlib/RingTheory/Ideal/IdempotentFG.lean b/Mathlib/RingTheory/Ideal/IdempotentFG.lean index caeb5aba8980b..707f70ab3dad0 100644 --- a/Mathlib/RingTheory/Ideal/IdempotentFG.lean +++ b/Mathlib/RingTheory/Ideal/IdempotentFG.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Mario Carneiro, Kevin Buzzard. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kevin Buzzard -/ -import Mathlib.Algebra.Ring.Idempotents +import Mathlib.Algebra.Ring.Idempotent import Mathlib.Order.Basic import Mathlib.RingTheory.Finiteness.Nakayama diff --git a/Mathlib/RingTheory/Ideal/Span.lean b/Mathlib/RingTheory/Ideal/Span.lean index 1b10889acf12f..99edde40b397d 100644 --- a/Mathlib/RingTheory/Ideal/Span.lean +++ b/Mathlib/RingTheory/Ideal/Span.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Chris Hughes, Mario Carneiro -/ import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.Ring.Idempotent import Mathlib.Algebra.Ring.Regular import Mathlib.LinearAlgebra.Span.Basic import Mathlib.RingTheory.Ideal.Lattice diff --git a/scripts/noshake.json b/scripts/noshake.json index ae281ef3f6f18..34b33e5c76be3 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -122,6 +122,7 @@ "Mathlib.Tactic.Linter", "Mathlib.Tactic.Linter.Header", "Mathlib.Tactic.Measurability", + "Mathlib.Tactic.MinImports", "Mathlib.Tactic.MkIffOfInductiveProp", "Mathlib.Tactic.ModCases", "Mathlib.Tactic.Monotonicity", @@ -456,6 +457,7 @@ "Mathlib.Algebra.Module.LinearMap.Basic": ["Mathlib.Algebra.Star.Basic"], "Mathlib.Algebra.Module.Equiv": ["Mathlib.Algebra.Star.Basic"], "Mathlib.Algebra.Homology.ModuleCat": ["Mathlib.Algebra.Homology.Homotopy"], + "Mathlib.Algebra.Group.Idempotent": ["Mathlib.Data.Subtype"], "Mathlib.Algebra.Group.Units.Basic": ["Mathlib.Tactic.Subsingleton"], "Mathlib.Algebra.Group.Units": ["Mathlib.Tactic.Subsingleton"], "Mathlib.Algebra.Group.Pi.Basic": ["Batteries.Tactic.Classical"], From d2f7b08b793953e9ce82db4d52979668fe94d71b Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Wed, 15 Jan 2025 08:43:35 +0000 Subject: [PATCH 240/681] refactor(Order/Atoms): Slight golfs from #20736 (#20760) Very minor golfs that I was going to suggest on #20736. --- Mathlib/Order/Atoms.lean | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/Mathlib/Order/Atoms.lean b/Mathlib/Order/Atoms.lean index 399af4db89220..936ee64e16e19 100644 --- a/Mathlib/Order/Atoms.lean +++ b/Mathlib/Order/Atoms.lean @@ -200,26 +200,20 @@ theorem isCoatom_iff [OrderTop A] {K : A} : theorem covBy_iff {K L : A} : K ⋖ L ↔ K < L ∧ ∀ H g, K ≤ H → H ≤ L → g ∉ K → g ∈ H → H = L := by - refine and_congr_right fun _ ↦ forall_congr' fun H ↦ ?_ - rw [lt_iff_le_not_le, SetLike.not_le_iff_exists, lt_iff_le_not_le, not_and, not_not, - and_comm (a := _ ≤ _), and_imp, exists_imp] - refine forall_congr' fun b ↦ ?_ - simp only [← and_imp] - rw [and_comm, and_comm (b:= _ ∈ _), and_assoc] - refine imp_congr_right fun ⟨_, h, _⟩ ↦ ?_ - simp only [le_antisymm_iff, h, true_and] + refine and_congr_right fun _ ↦ forall_congr' fun H ↦ not_iff_not.mp ?_ + push_neg + rw [lt_iff_le_not_le, lt_iff_le_and_ne, and_and_and_comm] + simp_rw [exists_and_left, and_assoc, and_congr_right_iff, ← and_assoc, and_comm, exists_and_left, + SetLike.not_le_iff_exists, and_comm, implies_true] /-- Dual variant of `SetLike.covBy_iff` -/ theorem covBy_iff' {K L : A} : K ⋖ L ↔ K < L ∧ ∀ H g, K ≤ H → H ≤ L → g ∉ H → g ∈ L → H = K := by - refine and_congr_right fun _ ↦ forall_congr' fun H ↦ ?_ - rw [imp_not_comm, lt_iff_le_not_le, SetLike.not_le_iff_exists, lt_iff_le_not_le, not_and, not_not, - and_comm (a := _ ≤ _), and_imp, exists_imp] - refine forall_congr' fun b ↦ ?_ - simp only [← and_imp] - rw [and_comm (b := K ≤ _), and_comm, and_comm (b:= _ ∈ _), and_assoc] - refine imp_congr_right fun ⟨h, _⟩ ↦ ?_ - simp only [le_antisymm_iff, h, and_true] + refine and_congr_right fun _ ↦ forall_congr' fun H ↦ not_iff_not.mp ?_ + push_neg + rw [lt_iff_le_and_ne, lt_iff_le_not_le, and_and_and_comm] + simp_rw [exists_and_left, and_assoc, and_congr_right_iff, ← and_assoc, and_comm, exists_and_left, + SetLike.not_le_iff_exists, ne_comm, implies_true] end SetLike From 8a921747ab023ac46e98f80c91a691cac153d397 Mon Sep 17 00:00:00 2001 From: Stefan Kebekus Date: Wed, 15 Jan 2025 10:30:01 +0000 Subject: [PATCH 241/681] feat: establish integrability and integrals of Real.log on arbitrary intervals (#20682) Establish interval integrability for Real.log on arbitrary intervals, remove an unnecessary assumption in the theorem `integral_log` which computes the integrals, and remove the theorems `integral_log_of_pos` and `integral_log_of_neg` which are now superfluous. Add theorems concerning integrability of even/odd functions; these are used in the proof and might be of general interest. Minor docu change: Add a missing section heading in Mathlib/MeasureTheory/Integral/IntervalIntegral.lean Rationale: I considered adding a new theorem rather than changing `integral_log`, but I see no value in having a theorem with unnecessary assumptions. For improved compatibility, I also considered depreciating `integral_log_of_pos` and `integral_log_of_neg` rather than removing them, but then the linter complained about unused assumptions in those theorems. Breaking change: Deleted assumptions in `integral_log`. Removed theorems `integral_log_of_pos` and `integral_log_of_neg`. These are replaced by `integral_log`, which gives the same conclusion without assumption. --- .../Analysis/SpecialFunctions/Integrals.lean | 85 ++++++++++++++----- .../Integral/IntervalIntegral.lean | 63 ++++++++++++++ 2 files changed, 129 insertions(+), 19 deletions(-) diff --git a/Mathlib/Analysis/SpecialFunctions/Integrals.lean b/Mathlib/Analysis/SpecialFunctions/Integrals.lean index f8625c6a2ebeb..955ef029c7bb5 100644 --- a/Mathlib/Analysis/SpecialFunctions/Integrals.lean +++ b/Mathlib/Analysis/SpecialFunctions/Integrals.lean @@ -3,10 +3,11 @@ Copyright (c) 2021 Benjamin Davidson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Benjamin Davidson -/ -import Mathlib.MeasureTheory.Integral.FundThmCalculus -import Mathlib.Analysis.SpecialFunctions.Trigonometric.ArctanDeriv +import Mathlib.Analysis.SpecialFunctions.Log.NegMulLog import Mathlib.Analysis.SpecialFunctions.NonIntegrable import Mathlib.Analysis.SpecialFunctions.Pow.Deriv +import Mathlib.Analysis.SpecialFunctions.Trigonometric.ArctanDeriv +import Mathlib.MeasureTheory.Integral.FundThmCalculus /-! # Integration of specific interval integrals @@ -224,10 +225,39 @@ theorem _root_.IntervalIntegrable.log (hf : ContinuousOn f [[a, b]]) IntervalIntegrable (fun x => log (f x)) μ a b := (ContinuousOn.log hf h).intervalIntegrable +/-- See `intervalIntegrable_log'` for a version without any hypothesis on the interval, but +assuming the measure is volume. -/ @[simp] theorem intervalIntegrable_log (h : (0 : ℝ) ∉ [[a, b]]) : IntervalIntegrable log μ a b := IntervalIntegrable.log continuousOn_id fun _ hx => ne_of_mem_of_not_mem hx h +/-- The real logarithm is interval integrable (with respect to the volume measure) on every +interval. See `intervalIntegrable_log` for a version applying to any locally finite measure, +but with an additional hypothesis on the interval. -/ +@[simp] +theorem intervalIntegrable_log' : IntervalIntegrable log volume a b := by + -- Log is even, so it suffices to consider the case 0 < a and b = 0 + apply intervalIntegrable_of_even (log_neg_eq_log · |>.symm) + intro x hx + -- Split integral + apply IntervalIntegrable.trans (b := 1) + · -- Show integrability on [0…1] using non-negativity of the derivative + rw [← neg_neg log] + apply IntervalIntegrable.neg + apply intervalIntegrable_deriv_of_nonneg (g := fun x ↦ -(x * log x - x)) + · exact (continuous_mul_log.continuousOn.sub continuous_id.continuousOn).neg + · intro s ⟨hs, _⟩ + norm_num at * + simpa using (hasDerivAt_id s).sub (hasDerivAt_mul_log hs.ne.symm) + · intro s ⟨hs₁, hs₂⟩ + norm_num at * + exact (log_nonpos_iff hs₁).mpr hs₂.le + · -- Show integrability on [1…t] by continuity + apply ContinuousOn.intervalIntegrable + apply Real.continuousOn_log.mono + apply Set.not_mem_uIcc_of_lt zero_lt_one at hx + simpa + @[simp] theorem intervalIntegrable_sin : IntervalIntegrable sin μ a b := continuous_sin.intervalIntegrable a b @@ -452,26 +482,43 @@ theorem integral_exp_mul_complex {c : ℂ} (hc : c ≠ 0) : · ring · fun_prop -@[simp] -theorem integral_log (h : (0 : ℝ) ∉ [[a, b]]) : - ∫ x in a..b, log x = b * log b - a * log a - b + a := by - have h' := fun x (hx : x ∈ [[a, b]]) => ne_of_mem_of_not_mem hx h - have heq := fun x hx => mul_inv_cancel₀ (h' x hx) - convert integral_mul_deriv_eq_deriv_mul (fun x hx => hasDerivAt_log (h' x hx)) - (fun x _ => hasDerivAt_id x) (continuousOn_inv₀.mono <| - subset_compl_singleton_iff.mpr h).intervalIntegrable - continuousOn_const.intervalIntegrable using 1 <;> - simp [integral_congr heq, mul_comm, ← sub_add] +/-- Helper lemma for `integral_log`: case where `a = 0` and `b` is positive. -/ +lemma integral_log_from_zero_of_pos (ht : 0 < b) : ∫ s in (0)..b, log s = b * log b - b := by + -- Compute the integral by giving a primitive and considering it limit as x approaches 0 from the + -- right. The following lines were suggested by Gareth Ma on Zulip. + rw [integral_eq_sub_of_hasDerivAt_of_tendsto (f := fun x ↦ x * log x - x) + (fa := 0) (fb := b * log b - b) (hint := intervalIntegrable_log')] + · abel + · exact ht + · intro s ⟨hs, _ ⟩ + simpa using (hasDerivAt_mul_log hs.ne.symm).sub (hasDerivAt_id s) + · simpa [mul_comm] using ((tendsto_log_mul_rpow_nhds_zero zero_lt_one).sub + (tendsto_nhdsWithin_of_tendsto_nhds Filter.tendsto_id)) + · exact tendsto_nhdsWithin_of_tendsto_nhds (ContinuousAt.tendsto (by fun_prop)) + +/-- Helper lemma for `integral_log`: case where `a = 0`. -/ +lemma integral_log_from_zero {b : ℝ} : ∫ s in (0)..b, log s = b * log b - b := by + rcases lt_trichotomy b 0 with h | h | h + · -- If t is negative, use that log is an even function to reduce to the positive case. + conv => arg 1; arg 1; intro t; rw [← log_neg_eq_log] + rw [intervalIntegral.integral_comp_neg, intervalIntegral.integral_symm, neg_zero, + integral_log_from_zero_of_pos (Left.neg_pos_iff.mpr h), log_neg_eq_log] + ring + · simp [h] + · exact integral_log_from_zero_of_pos h @[simp] -theorem integral_log_of_pos (ha : 0 < a) (hb : 0 < b) : - ∫ x in a..b, log x = b * log b - a * log a - b + a := - integral_log <| not_mem_uIcc_of_lt ha hb +theorem integral_log : ∫ s in a..b, log s = b * log b - a * log a - b + a := by + rw [← intervalIntegral.integral_add_adjacent_intervals (b := 0)] + · rw [intervalIntegral.integral_symm, integral_log_from_zero, integral_log_from_zero] + ring + all_goals exact intervalIntegrable_log' -@[simp] -theorem integral_log_of_neg (ha : a < 0) (hb : b < 0) : - ∫ x in a..b, log x = b * log b - a * log a - b + a := - integral_log <| not_mem_uIcc_of_gt ha hb +@[deprecated (since := "2025-01-12")] +alias integral_log_of_pos := integral_log + +@[deprecated (since := "2025-01-12")] +alias integral_log_of_neg := integral_log @[simp] theorem integral_sin : ∫ x in a..b, sin x = cos a - cos b := by diff --git a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean index d1beb848fb44b..bfb8d81c0bd4a 100644 --- a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean @@ -373,6 +373,69 @@ theorem Antitone.intervalIntegrable {u : ℝ → E} {a b : ℝ} (hu : Antitone u end +/-! +## Interval integrability of functions with even or odd parity +-/ +section + +variable {f : ℝ → E} + +/-- An even function is interval integrable (with respect to the volume measure) on every interval +of the form `0..x` if it is interval integrable (with respect to the volume measure) on every +interval of the form `0..x`, for positive `x`. + +See `intervalIntegrable_of_even` for a stronger result.-/ +lemma intervalIntegrable_of_even₀ (h₁f : ∀ x, f x = f (-x)) + (h₂f : ∀ x, 0 < x → IntervalIntegrable f volume 0 x) (t : ℝ) : + IntervalIntegrable f volume 0 t := by + rcases lt_trichotomy t 0 with h | h | h + · rw [IntervalIntegrable.iff_comp_neg] + conv => arg 1; intro t; rw [← h₁f] + simp [h₂f (-t) (by norm_num [h])] + · rw [h] + · exact h₂f t h + +/-- An even function is interval integrable (with respect to the volume measure) on every interval +if it is interval integrable (with respect to the volume measure) on every interval of the form +`0..x`, for positive `x`. -/ +theorem intervalIntegrable_of_even + (h₁f : ∀ x, f x = f (-x)) (h₂f : ∀ x, 0 < x → IntervalIntegrable f volume 0 x) (a b : ℝ) : + IntervalIntegrable f volume a b := + -- Split integral and apply lemma + (intervalIntegrable_of_even₀ h₁f h₂f a).symm.trans (b := 0) + (intervalIntegrable_of_even₀ h₁f h₂f b) + +/-- An odd function is interval integrable (with respect to the volume measure) on every interval +of the form `0..x` if it is interval integrable (with respect to the volume measure) on every +interval of the form `0..x`, for positive `x`. + +See `intervalIntegrable_of_odd` for a stronger result.-/ +lemma intervalIntegrable_of_odd₀ + (h₁f : ∀ x, -f x = f (-x)) (h₂f : ∀ x, 0 < x → IntervalIntegrable f volume 0 x) (t : ℝ) : + IntervalIntegrable f volume 0 t := by + rcases lt_trichotomy t 0 with h | h | h + · rw [IntervalIntegrable.iff_comp_neg] + conv => arg 1; intro t; rw [← h₁f] + apply IntervalIntegrable.neg + simp [h₂f (-t) (by norm_num [h])] + · rw [h] + · exact h₂f t h + +/-- An odd function is interval integrable (with respect to the volume measure) on every interval +iff it is interval integrable (with respect to the volume measure) on every interval of the form +`0..x`, for positive `x`. -/ +theorem intervalIntegrable_of_odd + (h₁f : ∀ x, -f x = f (-x)) (h₂f : ∀ x, 0 < x → IntervalIntegrable f volume 0 x) (a b : ℝ) : + IntervalIntegrable f volume a b := + -- Split integral and apply lemma + (intervalIntegrable_of_odd₀ h₁f h₂f a).symm.trans (b := 0) (intervalIntegrable_of_odd₀ h₁f h₂f b) + +end + +/-! +## Limits of intervals +-/ + /-- Let `l'` be a measurably generated filter; let `l` be a of filter such that each `s ∈ l'` eventually includes `Ioc u v` as both `u` and `v` tend to `l`. Let `μ` be a measure finite at `l'`. From 59c1bde08d635af6a642bb929a9e4135db1aae05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Wed, 15 Jan 2025 12:34:36 +0000 Subject: [PATCH 242/681] refactor: split `RingTheory/{Prime,Maximal}Spectrum` into `RingTheory/Spectrum/{Prime,Maximal}/{Defs,Basic}` (#20772) Split off definitions of maximal and prime spectrum of a ring to be able to use it in other modules without pulling unnecessary imports. --- Mathlib.lean | 6 ++-- .../PrimeSpectrum/Basic.lean | 2 +- .../PrimeSpectrum/Maximal.lean | 2 +- Mathlib/RingTheory/DedekindDomain/Ideal.lean | 2 +- Mathlib/RingTheory/KrullDimension/Basic.lean | 2 +- Mathlib/RingTheory/Nullstellensatz.lean | 2 +- .../Maximal/Basic.lean} | 28 +++------------ Mathlib/RingTheory/Spectrum/Maximal/Defs.lean | 27 ++++++++++++++ .../Prime/Basic.lean} | 21 ++--------- Mathlib/RingTheory/Spectrum/Prime/Defs.lean | 36 +++++++++++++++++++ Mathlib/RingTheory/Support.lean | 2 +- .../Valuation/ValuationSubring.lean | 2 +- 12 files changed, 81 insertions(+), 51 deletions(-) rename Mathlib/RingTheory/{MaximalSpectrum.lean => Spectrum/Maximal/Basic.lean} (95%) create mode 100644 Mathlib/RingTheory/Spectrum/Maximal/Defs.lean rename Mathlib/RingTheory/{PrimeSpectrum.lean => Spectrum/Prime/Basic.lean} (97%) create mode 100644 Mathlib/RingTheory/Spectrum/Prime/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index 66a8c3c4ffe4e..0b7e7b13023a1 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4573,7 +4573,6 @@ import Mathlib.RingTheory.Localization.NormTrace import Mathlib.RingTheory.Localization.NumDen import Mathlib.RingTheory.Localization.Submodule import Mathlib.RingTheory.MatrixAlgebra -import Mathlib.RingTheory.MaximalSpectrum import Mathlib.RingTheory.Multiplicity import Mathlib.RingTheory.MvPolynomial import Mathlib.RingTheory.MvPolynomial.Basic @@ -4664,7 +4663,6 @@ import Mathlib.RingTheory.PowerSeries.Trunc import Mathlib.RingTheory.PowerSeries.WellKnown import Mathlib.RingTheory.Presentation import Mathlib.RingTheory.Prime -import Mathlib.RingTheory.PrimeSpectrum import Mathlib.RingTheory.PrincipalIdealDomain import Mathlib.RingTheory.PrincipalIdealDomainOfPrime import Mathlib.RingTheory.QuotSMulTop @@ -4701,6 +4699,10 @@ import Mathlib.RingTheory.Smooth.Kaehler import Mathlib.RingTheory.Smooth.Local import Mathlib.RingTheory.Smooth.Pi import Mathlib.RingTheory.Smooth.StandardSmooth +import Mathlib.RingTheory.Spectrum.Maximal.Basic +import Mathlib.RingTheory.Spectrum.Maximal.Defs +import Mathlib.RingTheory.Spectrum.Prime.Basic +import Mathlib.RingTheory.Spectrum.Prime.Defs import Mathlib.RingTheory.Support import Mathlib.RingTheory.SurjectiveOnStalks import Mathlib.RingTheory.TensorProduct.Basic diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index 5111ffb0d516b..36eabf32f2950 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -10,7 +10,7 @@ import Mathlib.RingTheory.KrullDimension.Basic import Mathlib.RingTheory.LocalRing.ResidueField.Defs import Mathlib.RingTheory.LocalRing.RingHom.Basic import Mathlib.RingTheory.Localization.Away.Basic -import Mathlib.RingTheory.MaximalSpectrum +import Mathlib.RingTheory.Spectrum.Maximal.Basic import Mathlib.Tactic.StacksAttribute import Mathlib.Topology.KrullDimension import Mathlib.Topology.Sober diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Maximal.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Maximal.lean index 09a9002985e01..bcf8cff5c9c80 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Maximal.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Maximal.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Kurniadi Angdinata -/ import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic -import Mathlib.RingTheory.MaximalSpectrum +import Mathlib.RingTheory.Spectrum.Maximal.Basic /-! # Maximal spectrum of a commutative ring diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index fe0bf42cd4973..fc03a46ef8d2b 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -5,7 +5,7 @@ Authors: Kenji Nakagawa, Anne Baanen, Filippo A. E. Nuccio -/ import Mathlib.Algebra.Algebra.Subalgebra.Pointwise import Mathlib.Algebra.Polynomial.FieldDivision -import Mathlib.RingTheory.MaximalSpectrum +import Mathlib.RingTheory.Spectrum.Maximal.Basic import Mathlib.RingTheory.ChainOfDivisors import Mathlib.RingTheory.DedekindDomain.Basic import Mathlib.RingTheory.FractionalIdeal.Operations diff --git a/Mathlib/RingTheory/KrullDimension/Basic.lean b/Mathlib/RingTheory/KrullDimension/Basic.lean index a726c8a8a17d7..b368cc66ae325 100644 --- a/Mathlib/RingTheory/KrullDimension/Basic.lean +++ b/Mathlib/RingTheory/KrullDimension/Basic.lean @@ -5,7 +5,7 @@ Authors: Fangming Li, Jujian Zhang -/ import Mathlib.Algebra.MvPolynomial.CommRing import Mathlib.Algebra.Polynomial.Basic -import Mathlib.RingTheory.PrimeSpectrum +import Mathlib.RingTheory.Spectrum.Prime.Basic import Mathlib.Order.KrullDimension /-! diff --git a/Mathlib/RingTheory/Nullstellensatz.lean b/Mathlib/RingTheory/Nullstellensatz.lean index a0a41f1573af9..54eacaaad7289 100644 --- a/Mathlib/RingTheory/Nullstellensatz.lean +++ b/Mathlib/RingTheory/Nullstellensatz.lean @@ -6,7 +6,7 @@ Authors: Devon Tuma import Mathlib.RingTheory.Jacobson.Ring import Mathlib.FieldTheory.IsAlgClosed.Basic import Mathlib.RingTheory.MvPolynomial -import Mathlib.RingTheory.PrimeSpectrum +import Mathlib.RingTheory.Spectrum.Prime.Basic /-! # Nullstellensatz diff --git a/Mathlib/RingTheory/MaximalSpectrum.lean b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean similarity index 95% rename from Mathlib/RingTheory/MaximalSpectrum.lean rename to Mathlib/RingTheory/Spectrum/Maximal/Basic.lean index 8db93538adf3f..b20eb41fd1340 100644 --- a/Mathlib/RingTheory/MaximalSpectrum.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean @@ -4,18 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Kurniadi Angdinata -/ import Mathlib.RingTheory.Localization.AsSubring -import Mathlib.RingTheory.PrimeSpectrum +import Mathlib.RingTheory.Spectrum.Maximal.Defs +import Mathlib.RingTheory.Spectrum.Prime.Basic /-! -# Maximal spectrum of a commutative ring +# Maximal spectrum of a commutative (semi)ring -The maximal spectrum of a commutative ring is the type of all maximal ideals. -It is naturally a subset of the prime spectrum endowed with the subspace topology. - -## Main definitions - -* `MaximalSpectrum R`: The maximal spectrum of a commutative ring `R`, - i.e., the set of all maximal ideals of `R`. +Basic properties the maximal spectrum of a ring. ## Implementation notes @@ -23,25 +18,16 @@ The Zariski topology on the maximal spectrum is defined as the subspace topology natural inclusion into the prime spectrum to avoid API duplication for zero loci. -/ - noncomputable section open scoped Classical variable (R S P : Type*) [CommSemiring R] [CommSemiring S] [CommSemiring P] -/-- The maximal spectrum of a commutative ring `R` is the type of all maximal ideals of `R`. -/ -@[ext] -structure MaximalSpectrum where - asIdeal : Ideal R - IsMaximal : asIdeal.IsMaximal - -attribute [instance] MaximalSpectrum.IsMaximal +namespace MaximalSpectrum variable {R} -namespace MaximalSpectrum - instance [Nontrivial R] : Nonempty <| MaximalSpectrum R := let ⟨I, hI⟩ := Ideal.exists_maximal R ⟨⟨I, hI⟩⟩ @@ -94,8 +80,6 @@ end PrimeSpectrum namespace MaximalSpectrum -variable (R) - /-- The product of localizations at all maximal ideals of a commutative semiring. -/ abbrev PiLocalization : Type _ := Π I : MaximalSpectrum R, Localization.AtPrime I.1 @@ -188,8 +172,6 @@ end MaximalSpectrum namespace PrimeSpectrum -variable (R) - /-- The product of localizations at all prime ideals of a commutative semiring. -/ abbrev PiLocalization : Type _ := Π p : PrimeSpectrum R, Localization p.asIdeal.primeCompl diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean b/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean new file mode 100644 index 0000000000000..5caa1d1bd0a23 --- /dev/null +++ b/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean @@ -0,0 +1,27 @@ +/- +Copyright (c) 2022 David Kurniadi Angdinata. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Kurniadi Angdinata +-/ +import Mathlib.RingTheory.Ideal.Maximal + +/-! +# Maximal spectrum of a commutative (semi)ring + +The maximal spectrum of a commutative (semi)ring is the type of all maximal ideals. +It is naturally a subset of the prime spectrum endowed with the subspace topology. + +## Main definitions + +* `MaximalSpectrum R`: The maximal spectrum of a commutative (semi)ring `R`, + i.e., the set of all maximal ideals of `R`. +-/ + +/-- The maximal spectrum of a commutative (semi)ring `R` is the type of all +maximal ideals of `R`. -/ +@[ext] +structure MaximalSpectrum (R : Type*) [CommSemiring R] where + asIdeal : Ideal R + IsMaximal : asIdeal.IsMaximal + +attribute [instance] MaximalSpectrum.IsMaximal diff --git a/Mathlib/RingTheory/PrimeSpectrum.lean b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean similarity index 97% rename from Mathlib/RingTheory/PrimeSpectrum.lean rename to Mathlib/RingTheory/Spectrum/Prime/Basic.lean index cee8d1be56b21..de8131c375121 100644 --- a/Mathlib/RingTheory/PrimeSpectrum.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean @@ -8,11 +8,10 @@ import Mathlib.RingTheory.Ideal.Prod import Mathlib.RingTheory.Localization.Ideal import Mathlib.RingTheory.Nilpotent.Lemmas import Mathlib.RingTheory.Noetherian.Basic +import Mathlib.RingTheory.Spectrum.Prime.Defs /-! -# Prime spectrum of a commutative (semi)ring as a type - -The prime spectrum of a commutative (semi)ring is the type of all prime ideals. +# Prime spectrum of a commutative (semi)ring For the Zariski topology, see `AlgebraicGeometry.PrimeSpectrum.Basic`. @@ -21,8 +20,6 @@ which is constructed in `AlgebraicGeometry.StructureSheaf`.) ## Main definitions -* `PrimeSpectrum R`: The prime spectrum of a commutative (semi)ring `R`, - i.e., the set of all prime ideals of `R`. * `zeroLocus s`: The zero locus of a subset `s` of `R` is the subset of `PrimeSpectrum R` consisting of all prime ideals that contain `s`. * `vanishingIdeal t`: The vanishing ideal of a subset `t` of `PrimeSpectrum R` @@ -52,20 +49,6 @@ universe u v variable (R : Type u) (S : Type v) -/-- The prime spectrum of a commutative (semi)ring `R` is the type of all prime ideals of `R`. - -It is naturally endowed with a topology (the Zariski topology), -and a sheaf of commutative rings (see `AlgebraicGeometry.StructureSheaf`). -It is a fundamental building block in algebraic geometry. -/ -@[ext] -structure PrimeSpectrum [CommSemiring R] where - asIdeal : Ideal R - isPrime : asIdeal.IsPrime - -@[deprecated (since := "2024-06-22")] alias PrimeSpectrum.IsPrime := PrimeSpectrum.isPrime - -attribute [instance] PrimeSpectrum.isPrime - namespace PrimeSpectrum section CommSemiRing diff --git a/Mathlib/RingTheory/Spectrum/Prime/Defs.lean b/Mathlib/RingTheory/Spectrum/Prime/Defs.lean new file mode 100644 index 0000000000000..48a06e9acaae1 --- /dev/null +++ b/Mathlib/RingTheory/Spectrum/Prime/Defs.lean @@ -0,0 +1,36 @@ +/- +Copyright (c) 2020 Johan Commelin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johan Commelin, Filippo A. E. Nuccio, Andrew Yang +-/ +import Mathlib.RingTheory.Ideal.Prime + +/-! +# Prime spectrum of a commutative (semi)ring as a type + +The prime spectrum of a commutative (semi)ring is the type of all prime ideals. + +For the Zariski topology, see `AlgebraicGeometry.PrimeSpectrum.Basic`. + +(It is also naturally endowed with a sheaf of rings, +which is constructed in `AlgebraicGeometry.StructureSheaf`.) + +## Main definitions + +* `PrimeSpectrum R`: The prime spectrum of a commutative (semi)ring `R`, + i.e., the set of all prime ideals of `R`. +-/ + +/-- The prime spectrum of a commutative (semi)ring `R` is the type of all prime ideals of `R`. + +It is naturally endowed with a topology (the Zariski topology), +and a sheaf of commutative rings (see `AlgebraicGeometry.StructureSheaf`). +It is a fundamental building block in algebraic geometry. -/ +@[ext] +structure PrimeSpectrum (R : Type*) [CommSemiring R] where + asIdeal : Ideal R + isPrime : asIdeal.IsPrime + +@[deprecated (since := "2024-06-22")] alias PrimeSpectrum.IsPrime := PrimeSpectrum.isPrime + +attribute [instance] PrimeSpectrum.isPrime diff --git a/Mathlib/RingTheory/Support.lean b/Mathlib/RingTheory/Support.lean index b868e9be62590..1048aa13ccabc 100644 --- a/Mathlib/RingTheory/Support.lean +++ b/Mathlib/RingTheory/Support.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.RingTheory.PrimeSpectrum +import Mathlib.RingTheory.Spectrum.Prime.Basic import Mathlib.RingTheory.Localization.AtPrime import Mathlib.Algebra.Exact import Mathlib.Algebra.Module.LocalizedModule.Basic diff --git a/Mathlib/RingTheory/Valuation/ValuationSubring.lean b/Mathlib/RingTheory/Valuation/ValuationSubring.lean index 8a87a29540687..d1f3ec7693c78 100644 --- a/Mathlib/RingTheory/Valuation/ValuationSubring.lean +++ b/Mathlib/RingTheory/Valuation/ValuationSubring.lean @@ -7,7 +7,7 @@ import Mathlib.RingTheory.Valuation.ValuationRing import Mathlib.RingTheory.Localization.AsSubring import Mathlib.Algebra.Ring.Subring.Pointwise import Mathlib.Algebra.Ring.Action.Field -import Mathlib.RingTheory.PrimeSpectrum +import Mathlib.RingTheory.Spectrum.Prime.Basic import Mathlib.RingTheory.LocalRing.ResidueField.Basic /-! From 62a32b1bc66a358775c20842bf6b3eb6ac83c0db Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Wed, 15 Jan 2025 14:00:47 +0000 Subject: [PATCH 243/681] feat(Order/Chain): condition for the union of chains to be a chain (#20758) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also show that monotone functions preserve chains, and use this lemma to golf another. Useful from the disproof of the Aharoni–Korman conjecture, #20082. --- Mathlib/Order/Chain.lean | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Mathlib/Order/Chain.lean b/Mathlib/Order/Chain.lean index dc6fc7aa7d720..4b93268a6ec0b 100644 --- a/Mathlib/Order/Chain.lean +++ b/Mathlib/Order/Chain.lean @@ -93,10 +93,18 @@ theorem IsChain.image (r : α → α → Prop) (s : β → β → Prop) (f : α fun _ ⟨_, ha₁, ha₂⟩ _ ⟨_, hb₁, hb₂⟩ => ha₂ ▸ hb₂ ▸ fun hxy => (hrc ha₁ hb₁ <| ne_of_apply_ne f hxy).imp (h _ _) (h _ _) +lemma isChain_union {s t : Set α} : + IsChain r (s ∪ t) ↔ IsChain r s ∧ IsChain r t ∧ ∀ a ∈ s, ∀ b ∈ t, a ≠ b → r a b ∨ r b a := by + rw [IsChain, IsChain, IsChain, pairwise_union_of_symmetric fun _ _ ↦ Or.symm] + +lemma Monotone.isChain_image [Preorder α] [Preorder β] {s : Set α} {f : α → β} + (hf : Monotone f) (hs : IsChain (· ≤ ·) s) : IsChain (· ≤ ·) (f '' s) := + hs.image _ _ _ (fun _ _ a ↦ hf a) + theorem Monotone.isChain_range [LinearOrder α] [Preorder β] {f : α → β} (hf : Monotone f) : IsChain (· ≤ ·) (range f) := by rw [← image_univ] - exact (isChain_of_trichotomous _).image (· ≤ ·) _ _ hf + exact hf.isChain_image (isChain_of_trichotomous _) theorem IsChain.lt_of_le [PartialOrder α] {s : Set α} (h : IsChain (· ≤ ·) s) : IsChain (· < ·) s := fun _a ha _b hb hne ↦ From 2d276016a1db489572a2c4eddeb7bc70e5c0a6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 15 Jan 2025 14:33:35 +0000 Subject: [PATCH 244/681] feat(LinearAlgebra/ExteriorPower): the pairing between the exterior power of the dual and the exterior power (#18651) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same is also done for tensor powers. Co-authored-by: sophie.morel@ens-lyon.fr Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 4 +- .../LinearAlgebra/ExteriorPower/Pairing.lean | 133 ++++++++++++++++++ .../TensorAlgebra/ToTensorPower.lean | 2 +- .../Basic.lean} | 0 .../LinearAlgebra/TensorPower/Pairing.lean | 70 +++++++++ 5 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 Mathlib/LinearAlgebra/ExteriorPower/Pairing.lean rename Mathlib/LinearAlgebra/{TensorPower.lean => TensorPower/Basic.lean} (100%) create mode 100644 Mathlib/LinearAlgebra/TensorPower/Pairing.lean diff --git a/Mathlib.lean b/Mathlib.lean index 0b7e7b13023a1..c470c177b5d38 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3454,6 +3454,7 @@ import Mathlib.LinearAlgebra.ExteriorAlgebra.Basic import Mathlib.LinearAlgebra.ExteriorAlgebra.Grading import Mathlib.LinearAlgebra.ExteriorAlgebra.OfAlternating import Mathlib.LinearAlgebra.ExteriorPower.Basic +import Mathlib.LinearAlgebra.ExteriorPower.Pairing import Mathlib.LinearAlgebra.FiniteDimensional import Mathlib.LinearAlgebra.FiniteDimensional.Defs import Mathlib.LinearAlgebra.FiniteSpan @@ -3595,7 +3596,8 @@ import Mathlib.LinearAlgebra.TensorAlgebra.Basic import Mathlib.LinearAlgebra.TensorAlgebra.Basis import Mathlib.LinearAlgebra.TensorAlgebra.Grading import Mathlib.LinearAlgebra.TensorAlgebra.ToTensorPower -import Mathlib.LinearAlgebra.TensorPower +import Mathlib.LinearAlgebra.TensorPower.Basic +import Mathlib.LinearAlgebra.TensorPower.Pairing import Mathlib.LinearAlgebra.TensorProduct.Basic import Mathlib.LinearAlgebra.TensorProduct.Basis import Mathlib.LinearAlgebra.TensorProduct.DirectLimit diff --git a/Mathlib/LinearAlgebra/ExteriorPower/Pairing.lean b/Mathlib/LinearAlgebra/ExteriorPower/Pairing.lean new file mode 100644 index 0000000000000..1613b9eeb36d8 --- /dev/null +++ b/Mathlib/LinearAlgebra/ExteriorPower/Pairing.lean @@ -0,0 +1,133 @@ +/- +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, Sophie Morel +-/ + +import Mathlib.LinearAlgebra.ExteriorPower.Basic +import Mathlib.LinearAlgebra.TensorPower.Pairing + +/-! +# The pairing between the exterior power of the dual and the exterior power + +We construct the pairing +`exteriorPower.pairingDual : ⋀[R]^n (Module.Dual R M) →ₗ[R] (Module.Dual R (⋀[R]^n M))`. + +-/ + +namespace exteriorPower + +open TensorProduct PiTensorProduct + +variable (R : Type*) (M : Type*) [CommRing R] [AddCommGroup M] [Module R M] + +/-- The linear map from the `n`th exterior power to the `n`th tensor power obtained by +`MultilinearMap.alternatization`. -/ +noncomputable def toTensorPower (n : ℕ) : ⋀[R]^n M →ₗ[R] ⨂[R]^n M := + alternatingMapLinearEquiv (MultilinearMap.alternatization (PiTensorProduct.tprod R)) + +variable {M} in +open Equiv in +@[simp] +lemma toTensorPower_apply_ιMulti {n : ℕ} (v : Fin n → M) : + toTensorPower R M n (ιMulti R n v) = + ∑ σ : Perm (Fin n), Perm.sign σ • PiTensorProduct.tprod R (fun i ↦ v (σ i)) := by + dsimp [toTensorPower] + simp only [alternatingMapLinearEquiv_apply_ιMulti, + MultilinearMap.alternatization_apply, MultilinearMap.domDomCongr_apply] + +/-- The canonical `n`-alternating map from the dual of the `R`-module `M` +to the dual of `⨂[R]^n M`. -/ +noncomputable def alternatingMapToDual (n : ℕ) : + AlternatingMap R (Module.Dual R M) (Module.Dual R (⋀[R]^n M)) (Fin n) where + toMultilinearMap := (toTensorPower R M n).dualMap.compMultilinearMap + (TensorPower.multilinearMapToDual R M n) + map_eq_zero_of_eq' f i j hf hij := by + ext v + suffices Matrix.det (n := Fin n) (.of (fun i j ↦ f j (v i))) = 0 by + simpa [Matrix.det_apply] using this + exact Matrix.det_zero_of_column_eq hij (by simp [hf]) + +variable {R M} in +open Equiv in +@[simp] +theorem alternatingMapToDual_apply_ιMulti {n : ℕ} + (f : (_ : Fin n) → Module.Dual R M) (v : Fin n → M) : + alternatingMapToDual R M n f (ιMulti _ _ v) = + Matrix.det (n := Fin n) (.of (fun i j ↦ f j (v i))) := by + simp [alternatingMapToDual, Matrix.det_apply] + +/-- The linear map from the exterior power of the dual to the dual of the exterior power. -/ +noncomputable def pairingDual (n : ℕ) : + ⋀[R]^n (Module.Dual R M) →ₗ[R] Module.Dual R (⋀[R]^n M) := + alternatingMapLinearEquiv (alternatingMapToDual R M n) + +variable {R M} in +open Equiv in +@[simp] +lemma pairingDual_ιMulti_ιMulti {n : ℕ} (f : (_ : Fin n) → Module.Dual R M) (v : Fin n → M) : + pairingDual R M n (ιMulti _ _ f) (ιMulti _ _ v) = + Matrix.det (n := Fin n) (.of (fun i j ↦ f j (v i))) := by + simp [pairingDual] + + +section + +/-! If a `R`-module `M` has a family of vectors `x : ι → M` and linear maps `f : ι → M` +such that `f i (x j)` is `1` or `0` depending on `i = j` or `i ≠ j`, then if `ι` has +a linear order, then a similar property regarding `pairingDual R M n` +applies to the family of vectors indexed +by `Fin n ↪o ι` in `⋀[R]^n M` and in `⋀[R]^n (Module.Dual R M)` that are obtained +by taking exterior products of the `x i` and the `f j`. (This shall be used in order +to construct a basis of `⋀[R]^n M` when `M` is a free module.) -/ + +variable {R M} {ι : Type*} [LinearOrder ι] + (x : ι → M) (f : ι → Module.Dual R M) + (h₁ : ∀ i, f i (x i) = 1) (h₀ : ∀ ⦃i j⦄, i ≠ j → f i (x j) = 0) (n : ℕ) + +include h₁ h₀ in +lemma pairingDual_apply_apply_eq_one (a : Fin n ↪o ι) : + pairingDual R M n (ιMulti _ _ (f ∘ a)) (ιMulti _ _ (x ∘ a)) = 1 := by + simp only [pairingDual_ιMulti_ιMulti, Function.comp_apply] + rw [← Matrix.det_one (n := Fin n)] + congr + ext i j + dsimp + by_cases hij : i = j + · subst hij + simp only [h₁, Matrix.one_apply_eq] + · rw [h₀ (by simpa using Ne.symm hij), Matrix.one_apply_ne hij] + +include h₀ in +lemma pairingDual_apply_apply_eq_one_zero (a b : Fin n ↪o ι) (h : a ≠ b) : + pairingDual R M n (ιMulti _ _ (f ∘ a)) (ιMulti _ _ (x ∘ b)) = 0 := by + simp only [pairingDual_ιMulti_ιMulti, Function.comp_apply, Matrix.det_apply] + refine Finset.sum_eq_zero (fun σ _ ↦ ?_) + simp only [Matrix.of_apply, smul_eq_iff_eq_inv_smul, smul_zero] + by_contra h' + apply h + have : a = b ∘ σ := by + ext i + by_contra hi + exact h' (Finset.prod_eq_zero (i := i) (by simp) (h₀ hi)) + have hσ : Monotone σ := fun i j hij ↦ by + have h'' := congr_fun this + dsimp at h'' + rw [← a.map_rel_iff] at hij + simpa only [← b.map_rel_iff, ← h''] + have hσ' : Monotone σ.symm := fun i j hij ↦ by + obtain ⟨i, rfl⟩ := σ.surjective i + obtain ⟨j, rfl⟩ := σ.surjective j + simp only [Equiv.symm_apply_apply] + by_contra! h + obtain rfl : i = j := σ.injective (le_antisymm hij (hσ h.le)) + simp only [lt_self_iff_false] at h + obtain rfl : σ = 1 := by + ext i : 1 + exact DFunLike.congr_fun (Subsingleton.elim (σ.toOrderIso hσ hσ') (OrderIso.refl _)) i + ext + apply congr_fun this + +end + +end exteriorPower diff --git a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean index 2e2d896b8fc54..5ba88c5e0b892 100644 --- a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean +++ b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.LinearAlgebra.TensorAlgebra.Basic -import Mathlib.LinearAlgebra.TensorPower +import Mathlib.LinearAlgebra.TensorPower.Basic /-! # Tensor algebras as direct sums of tensor powers diff --git a/Mathlib/LinearAlgebra/TensorPower.lean b/Mathlib/LinearAlgebra/TensorPower/Basic.lean similarity index 100% rename from Mathlib/LinearAlgebra/TensorPower.lean rename to Mathlib/LinearAlgebra/TensorPower/Basic.lean diff --git a/Mathlib/LinearAlgebra/TensorPower/Pairing.lean b/Mathlib/LinearAlgebra/TensorPower/Pairing.lean new file mode 100644 index 0000000000000..059556c200cf8 --- /dev/null +++ b/Mathlib/LinearAlgebra/TensorPower/Pairing.lean @@ -0,0 +1,70 @@ +/- +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.LinearAlgebra.Dual +import Mathlib.LinearAlgebra.TensorPower.Basic + +/-! +# The pairing between the tensor power of the dual and the tensor power + +We construct the pairing +`TensorPower.pairingDual : ⨂[R]^n (Module.Dual R M) →ₗ[R] (Module.Dual R (⨂[R]^n M))`. + +-/ + +open TensorProduct PiTensorProduct + +namespace TensorPower + +variable (R : Type*) (M : Type*) [CommSemiring R] [AddCommMonoid M] [Module R M] + (n : ℕ) + +open BigOperators + +/-- The canonical multilinear map from `n` copies of the dual of the module `M` +to the dual of `⨂[R]^n M`. -/ +noncomputable def multilinearMapToDual : + MultilinearMap R (fun (_ : Fin n) ↦ Module.Dual R M) + (Module.Dual R (⨂[R]^n M)) := + have : ∀ (_ : DecidableEq (Fin n)) (f : Fin n → Module.Dual R M) + (φ : Module.Dual R M) (i j : Fin n) (v : Fin n → M), + (Function.update f i φ) j (v j) = + Function.update (fun j ↦ f j (v j)) i (φ (v i)) j := fun _ f φ i j v ↦ by + by_cases h : j = i + · subst h + simp only [Function.update_self] + · simp only [Function.update_of_ne h] + { toFun := fun f ↦ PiTensorProduct.lift + (MultilinearMap.compLinearMap (MultilinearMap.mkPiRing R (Fin n) 1) f) + map_update_add' := fun f i φ₁ φ₂ ↦ by + ext v + dsimp + simp only [lift.tprod, MultilinearMap.compLinearMap_apply, this, + LinearMap.add_apply, MultilinearMap.map_update_add] + map_update_smul' := fun f i a φ ↦ by + ext v + dsimp + simp only [lift.tprod, MultilinearMap.compLinearMap_apply, this, + LinearMap.smul_apply, MultilinearMap.map_update_smul] + dsimp } + +variable {R M n} in +@[simp] +theorem multilinearMapToDual_apply_tprod (f : (_ : Fin n) → Module.Dual R M) (v : Fin n → M) : + multilinearMapToDual R M n f (tprod _ v) = ∏ i, (f i (v i)) := by + simp [multilinearMapToDual] + +/-- The linear map from the tensor power of the dual to the dual of the tensor power. -/ +noncomputable def pairingDual : + ⨂[R]^n (Module.Dual R M) →ₗ[R] (Module.Dual R (⨂[R]^n M)) := + PiTensorProduct.lift (multilinearMapToDual R M n) + +variable {R M n} in +@[simp] +lemma pairingDual_tprod_tprod (f : (_ : Fin n) → Module.Dual R M) (v : Fin n → M) : + pairingDual R M n (tprod _ f) (tprod _ v) = ∏ i, (f i (v i)) := by + simp [pairingDual] + +end TensorPower From 82b0bf24e6d335d57b61ff72184f51f8eed57aa9 Mon Sep 17 00:00:00 2001 From: Quang Dao Date: Wed, 15 Jan 2025 14:33:37 +0000 Subject: [PATCH 245/681] chore(Data/Fin/Basic): remove mention of `Fin.succAboveCases` (#20770) This is to reflect the "TODO" that `Fin.succAboveCases` is no longer defined in `Data/Fin/Basic.lean`, but instead in `Data/Fin/Tuple/Basic.lean`. Co-authored-by: Quang Dao --- Mathlib/Data/Fin/Basic.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 23ac84d65da1f..c4f67ec7c5759 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -37,10 +37,7 @@ This file expands on the development in the core library. * `Fin.lastCases`: define `f : Π i, Fin (n + 1), C i` by separately handling the cases `i = Fin.last n` and `i = Fin.castSucc j`, a special case of `Fin.reverseInduction`; * `Fin.addCases`: define a function on `Fin (m + n)` by separately handling the cases - `Fin.castAdd n i` and `Fin.natAdd m i`; -* `Fin.succAboveCases`: given `i : Fin (n + 1)`, define a function on `Fin (n + 1)` by separately - handling the cases `j = i` and `j = Fin.succAbove i k`, same as `Fin.insertNth` but marked - as eliminator and works for `Sort*`. -- Porting note: this is in another file + `Fin.castAdd n i` and `Fin.natAdd m i`. ### Embeddings and isomorphisms From e9a89abf183f6c63bc206f9fc913809c1da8e4dd Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Wed, 15 Jan 2025 15:07:10 +0000 Subject: [PATCH 246/681] chore: generalize more materials about linear independence over semirings (#20497) Also add `Finsupp.linearCombination_one_tmul` and `linearIndependent_one_tmul` that connects linear independence to flatness. --- Mathlib/LinearAlgebra/Basis/Basic.lean | 114 +++++++++--------- Mathlib/LinearAlgebra/DirectSum/Finsupp.lean | 11 +- .../Finsupp/LinearCombination.lean | 5 + Mathlib/RingTheory/Adjoin/PowerBasis.lean | 4 +- Mathlib/RingTheory/AdjoinRoot.lean | 2 +- Mathlib/RingTheory/AlgebraTower.lean | 35 ++---- Mathlib/RingTheory/Flat/Basic.lean | 6 + Mathlib/RingTheory/Localization/Module.lean | 81 +++++-------- Mathlib/RingTheory/TensorProduct/Basic.lean | 8 +- 9 files changed, 121 insertions(+), 145 deletions(-) diff --git a/Mathlib/LinearAlgebra/Basis/Basic.lean b/Mathlib/LinearAlgebra/Basis/Basic.lean index 662046a8624b8..d2945cbb493aa 100644 --- a/Mathlib/LinearAlgebra/Basis/Basic.lean +++ b/Mathlib/LinearAlgebra/Basis/Basic.lean @@ -161,61 +161,7 @@ theorem basis_singleton_iff {R M : Type*} [Ring R] [Nontrivial R] [AddCommGroup end Singleton -end Basis - -end Module - -section Module - -open LinearMap - -variable {v : ι → M} -variable [Ring R] [CommRing R₂] [AddCommGroup M] -variable [Module R M] [Module R₂ M] -variable {x y : M} -variable (b : Basis ι R M) - -theorem Basis.eq_bot_of_rank_eq_zero [NoZeroDivisors R] (b : Basis ι R M) (N : Submodule R M) - (rank_eq : ∀ {m : ℕ} (v : Fin m → N), LinearIndependent R ((↑) ∘ v : Fin m → M) → m = 0) : - N = ⊥ := by - rw [Submodule.eq_bot_iff] - intro x hx - contrapose! rank_eq with x_ne - refine ⟨1, fun _ => ⟨x, hx⟩, ?_, one_ne_zero⟩ - rw [Fintype.linearIndependent_iff] - rintro g sum_eq i - cases' i with _ hi - simp only [Function.const_apply, Fin.default_eq_zero, Submodule.coe_mk, Finset.univ_unique, - Function.comp_const, Finset.sum_singleton] at sum_eq - convert (b.smul_eq_zero.mp sum_eq).resolve_right x_ne - -namespace Basis - -/-- Any basis is a maximal linear independent set. --/ -theorem maximal [Nontrivial R] (b : Basis ι R M) : b.linearIndependent.Maximal := fun w hi h => by - -- If `w` is strictly bigger than `range b`, - apply le_antisymm h - -- then choose some `x ∈ w \ range b`, - intro x p - by_contra q - -- and write it in terms of the basis. - have e := b.linearCombination_repr x - -- This then expresses `x` as a linear combination - -- of elements of `w` which are in the range of `b`, - let u : ι ↪ w := - ⟨fun i => ⟨b i, h ⟨i, rfl⟩⟩, fun i i' r => - b.injective (by simpa only [Subtype.mk_eq_mk] using r)⟩ - simp_rw [Finsupp.linearCombination_apply] at e - change ((b.repr x).sum fun (i : ι) (a : R) ↦ a • (u i : M)) = ((⟨x, p⟩ : w) : M) at e - rw [← Finsupp.sum_embDomain (f := u) (g := fun x r ↦ r • (x : M)), - ← Finsupp.linearCombination_apply] at e - -- Now we can contradict the linear independence of `hi` - refine hi.linearCombination_ne_of_not_mem_support _ ?_ e - simp only [Finset.mem_map, Finsupp.support_embDomain] - rintro ⟨j, -, W⟩ - simp only [u, Embedding.coeFn_mk, Subtype.mk_eq_mk] at W - apply q ⟨j, W⟩ +variable {v : ι → M} {x y : M} section Mk @@ -333,6 +279,8 @@ theorem unitsSMul_apply {v : Basis ι R M} {w : ι → Rˣ} (i : ι) : unitsSMul mk_apply (LinearIndependent.units_smul v.linearIndependent w) (units_smul_span_eq_top v.span_eq).ge i +variable [CommSemiring R₂] [Module R₂ M] + @[simp] theorem coord_unitsSMul (e : Basis ι R₂ M) (w : ι → R₂ˣ) (i : ι) : (unitsSMul e w).coord i = (w i)⁻¹ • e.coord i := by @@ -363,6 +311,62 @@ theorem repr_isUnitSMul {v : Basis ι R₂ M} {w : ι → R₂} (hw : ∀ i, IsU (v.isUnitSMul hw).repr x i = (hw i).unit⁻¹ • v.repr x i := repr_unitsSMul _ _ _ _ +end Basis + +end Module + +section Module + +open LinearMap + +variable {v : ι → M} +variable [Ring R] [CommRing R₂] [AddCommGroup M] +variable [Module R M] [Module R₂ M] +variable {x y : M} +variable (b : Basis ι R M) + +theorem Basis.eq_bot_of_rank_eq_zero [NoZeroDivisors R] (b : Basis ι R M) (N : Submodule R M) + (rank_eq : ∀ {m : ℕ} (v : Fin m → N), LinearIndependent R ((↑) ∘ v : Fin m → M) → m = 0) : + N = ⊥ := by + rw [Submodule.eq_bot_iff] + intro x hx + contrapose! rank_eq with x_ne + refine ⟨1, fun _ => ⟨x, hx⟩, ?_, one_ne_zero⟩ + rw [Fintype.linearIndependent_iff] + rintro g sum_eq i + cases' i with _ hi + simp only [Function.const_apply, Fin.default_eq_zero, Submodule.coe_mk, Finset.univ_unique, + Function.comp_const, Finset.sum_singleton] at sum_eq + convert (b.smul_eq_zero.mp sum_eq).resolve_right x_ne + +namespace Basis + +/-- Any basis is a maximal linear independent set. +-/ +theorem maximal [Nontrivial R] (b : Basis ι R M) : b.linearIndependent.Maximal := fun w hi h => by + -- If `w` is strictly bigger than `range b`, + apply le_antisymm h + -- then choose some `x ∈ w \ range b`, + intro x p + by_contra q + -- and write it in terms of the basis. + have e := b.linearCombination_repr x + -- This then expresses `x` as a linear combination + -- of elements of `w` which are in the range of `b`, + let u : ι ↪ w := + ⟨fun i => ⟨b i, h ⟨i, rfl⟩⟩, fun i i' r => + b.injective (by simpa only [Subtype.mk_eq_mk] using r)⟩ + simp_rw [Finsupp.linearCombination_apply] at e + change ((b.repr x).sum fun (i : ι) (a : R) ↦ a • (u i : M)) = ((⟨x, p⟩ : w) : M) at e + rw [← Finsupp.sum_embDomain (f := u) (g := fun x r ↦ r • (x : M)), + ← Finsupp.linearCombination_apply] at e + -- Now we can contradict the linear independence of `hi` + refine hi.linearCombination_ne_of_not_mem_support _ ?_ e + simp only [Finset.mem_map, Finsupp.support_embDomain] + rintro ⟨j, -, W⟩ + simp only [u, Embedding.coeFn_mk, Subtype.mk_eq_mk] at W + apply q ⟨j, W⟩ + section Fin /-- Let `b` be a basis for a submodule `N` of `M`. If `y : M` is linear independent of `N` diff --git a/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean b/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean index 3f0c3dc8c955c..074a4a96fdf62 100644 --- a/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean +++ b/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean @@ -239,7 +239,14 @@ end TensorProduct variable (R S M N ι κ : Type*) [CommSemiring R] [AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] - [Semiring S] [Algebra R S] [Module S M] [IsScalarTower R S M] + [Semiring S] [Algebra R S] + +theorem Finsupp.linearCombination_one_tmul [DecidableEq ι] {v : ι → M} : + (linearCombination S ((1 : S) ⊗ₜ[R] v ·)).restrictScalars R = + (linearCombination R v).lTensor S ∘ₗ (finsuppScalarRight R S ι).symm := by + ext; simp [smul_tmul'] + +variable [Module S M] [IsScalarTower R S M] open scoped Classical in /-- The tensor product of `ι →₀ M` and `κ →₀ N` is linearly equivalent to `(ι × κ) →₀ (M ⊗ N)`. -/ @@ -362,3 +369,5 @@ theorem finsuppTensorFinsuppRid_self : finsuppTensorFinsuppRid R R ι κ = finsuppTensorFinsupp' R ι κ := by rw [finsuppTensorFinsupp', finsuppTensorFinsuppLid, finsuppTensorFinsuppRid, TensorProduct.lid_eq_rid] + +end diff --git a/Mathlib/LinearAlgebra/Finsupp/LinearCombination.lean b/Mathlib/LinearAlgebra/Finsupp/LinearCombination.lean index c1b6ee8d30eb5..0d551be4295be 100644 --- a/Mathlib/LinearAlgebra/Finsupp/LinearCombination.lean +++ b/Mathlib/LinearAlgebra/Finsupp/LinearCombination.lean @@ -252,6 +252,11 @@ theorem linearCombination_linearCombination {α β : Type*} (A : α → M) (B : @[deprecated (since := "2024-08-29")] alias total_total := linearCombination_linearCombination +theorem linearCombination_smul [Module R S] [Module S M] [IsScalarTower R S M] {w : α' → S} : + linearCombination R (fun i : α × α' ↦ w i.2 • v i.1) = (linearCombination S v).restrictScalars R + ∘ₗ mapRange.linearMap (linearCombination R w) ∘ₗ (finsuppProdLEquiv R).toLinearMap := by + ext; simp [finsuppProdLEquiv, finsuppProdEquiv, Finsupp.curry] + @[simp] theorem linearCombination_fin_zero (f : Fin 0 → M) : linearCombination R f = 0 := by ext i diff --git a/Mathlib/RingTheory/Adjoin/PowerBasis.lean b/Mathlib/RingTheory/Adjoin/PowerBasis.lean index 5b1c9fd4bce17..0e942ceabeb0a 100644 --- a/Mathlib/RingTheory/Adjoin/PowerBasis.lean +++ b/Mathlib/RingTheory/Adjoin/PowerBasis.lean @@ -33,9 +33,7 @@ noncomputable def adjoin.powerBasisAux {x : S} (hx : IsIntegral K x) : IsIntegral K (⟨x, subset_adjoin (Set.mem_singleton x)⟩ : adjoin K ({x} : Set S)) := by apply (isIntegral_algebraMap_iff hST).mp convert hx - apply - @Basis.mk (Fin (minpoly K x).natDegree) _ (adjoin K {x}) fun i => - ⟨x, subset_adjoin (Set.mem_singleton x)⟩ ^ (i : ℕ) + apply Basis.mk (v := fun i : Fin _ ↦ ⟨x, subset_adjoin (Set.mem_singleton x)⟩ ^ (i : ℕ)) · have : LinearIndependent K _ := linearIndependent_pow (⟨x, self_mem_adjoin_singleton _ _⟩ : adjoin K {x}) rwa [← minpoly.algebraMap_eq hST] at this diff --git a/Mathlib/RingTheory/AdjoinRoot.lean b/Mathlib/RingTheory/AdjoinRoot.lean index cddb3ce631d74..6d04333d192e0 100644 --- a/Mathlib/RingTheory/AdjoinRoot.lean +++ b/Mathlib/RingTheory/AdjoinRoot.lean @@ -506,7 +506,7 @@ def powerBasisAux (hf : f ≠ 0) : Basis (Fin f.natDegree) K (AdjoinRoot f) := b rw [natDegree_mul hf, natDegree_C, add_zero] · rwa [Ne, C_eq_zero, inv_eq_zero, leadingCoeff_eq_zero] have minpoly_eq : minpoly K (root f) = f' := minpoly_root hf - apply @Basis.mk _ _ _ fun i : Fin f.natDegree => root f ^ i.val + apply Basis.mk (v := fun i : Fin f.natDegree ↦ root f ^ i.val) · rw [← deg_f', ← minpoly_eq] exact linearIndependent_pow (root f) · rintro y - diff --git a/Mathlib/RingTheory/AlgebraTower.lean b/Mathlib/RingTheory/AlgebraTower.lean index abfe65fb0a6fe..cd4e432e660f0 100644 --- a/Mathlib/RingTheory/AlgebraTower.lean +++ b/Mathlib/RingTheory/AlgebraTower.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.Algebra.Algebra.Tower -import Mathlib.Algebra.Module.BigOperators import Mathlib.LinearAlgebra.Basis.Basic /-! @@ -27,9 +26,7 @@ base rings to be a field, so we also generalize the lemma to rings in this file. open Pointwise -universe u v w u₁ - -variable (R : Type u) (S : Type v) (A : Type w) (B : Type u₁) +variable (R S A B : Type*) namespace IsScalarTower @@ -39,7 +36,6 @@ variable [CommSemiring R] [CommSemiring S] [Semiring A] [Semiring B] variable [Algebra R S] [Algebra S A] [Algebra S B] [Algebra R A] [Algebra R B] variable [IsScalarTower R S A] [IsScalarTower R S B] - /-- Suppose that `R → S → A` is a tower of algebras. If an element `r : R` is invertible in `S`, then it is invertible in `A`. -/ def Invertible.algebraTower (r : R) [Invertible (algebraMap R S r)] : @@ -91,33 +87,19 @@ open Finsupp open scoped Classical -universe v₁ w₁ - variable {R S A} - -section -variable [Ring R] [Ring S] [AddCommGroup A] +variable [Semiring R] [Semiring S] [AddCommMonoid A] variable [Module R S] [Module S A] [Module R A] [IsScalarTower R S A] -theorem linearIndependent_smul {ι : Type v₁} {b : ι → S} {ι' : Type w₁} {c : ι' → A} +theorem linearIndependent_smul {ι : Type*} {b : ι → S} {ι' : Type*} {c : ι' → A} (hb : LinearIndependent R b) (hc : LinearIndependent S c) : - LinearIndependent R fun p : ι × ι' => b p.1 • c p.2 := by - rw [linearIndependent_iff'] at hb hc; rw [linearIndependent_iff'']; rintro s g hg hsg ⟨i, k⟩ - by_cases hik : (i, k) ∈ s - · have h1 : ∑ i ∈ s.image Prod.fst ×ˢ s.image Prod.snd, g i • b i.1 • c i.2 = 0 := by - rw [← hsg] - exact - (Finset.sum_subset Finset.subset_product fun p _ hp => - show g p • b p.1 • c p.2 = 0 by rw [hg p hp, zero_smul]).symm - rw [Finset.sum_product_right] at h1 - simp_rw [← smul_assoc, ← Finset.sum_smul] at h1 - exact hb _ _ (hc _ _ h1 k (Finset.mem_image_of_mem _ hik)) i (Finset.mem_image_of_mem _ hik) - exact hg _ hik -end + LinearIndependent R fun p : ι × ι' ↦ b p.1 • c p.2 := by + rw [← linearIndependent_equiv' (.prodComm ..) (g := fun p : ι' × ι ↦ b p.2 • c p.1) rfl, + LinearIndependent, linearCombination_smul] + simpa using Function.Injective.comp hc + ((mapRange_injective _ (map_zero _) hb).comp <| Equiv.injective _) variable (R) -variable [Semiring R] [Semiring S] [AddCommMonoid A] -variable [Module R S] [Module S A] [Module R A] [IsScalarTower R S A] -- LinearIndependent is enough if S is a ring rather than semiring. theorem Basis.isScalarTower_of_nonempty {ι} [Nonempty ι] (b : Basis ι S A) : IsScalarTower R S S := @@ -197,7 +179,6 @@ variable {A} {C D : Type*} [CommSemiring A] [CommSemiring C] [CommSemiring D] [A variable [CommSemiring B] [Algebra A B] [Algebra B C] [IsScalarTower A B C] (f : C →ₐ[A] D) - /-- Restrict the domain of an `AlgHom`. -/ def AlgHom.restrictDomain : B →ₐ[A] D := f.comp (IsScalarTower.toAlgHom A B C) diff --git a/Mathlib/RingTheory/Flat/Basic.lean b/Mathlib/RingTheory/Flat/Basic.lean index 90816a27b68c2..dfb5b054087df 100644 --- a/Mathlib/RingTheory/Flat/Basic.lean +++ b/Mathlib/RingTheory/Flat/Basic.lean @@ -274,6 +274,12 @@ theorem lTensor_preserves_injective_linearMap {N' : Type*} [AddCommGroup N'] [Mo Function.Injective (L.lTensor M) := (L.lTensor_inj_iff_rTensor_inj M).2 (rTensor_preserves_injective_linearMap L hL) +theorem linearIndependent_one_tmul {S} [Ring S] [Algebra R S] [Flat R S] {ι} {v : ι → M} + (hv : LinearIndependent R v) : LinearIndependent S ((1 : S) ⊗ₜ[R] v ·) := by + classical rw [LinearIndependent, ← LinearMap.coe_restrictScalars R, + Finsupp.linearCombination_one_tmul] + simpa using lTensor_preserves_injective_linearMap _ hv + variable (R M) in /-- `M` is flat if and only if `f ⊗ 𝟙 M` is injective whenever `f` is an injective linear map. See `Module.Flat.iff_rTensor_preserves_injective_linearMap` to specialize the universe of diff --git a/Mathlib/RingTheory/Localization/Module.lean b/Mathlib/RingTheory/Localization/Module.lean index 7020b2257a2bf..5a0ca2dd53acd 100644 --- a/Mathlib/RingTheory/Localization/Module.lean +++ b/Mathlib/RingTheory/Localization/Module.lean @@ -32,15 +32,11 @@ variable {R : Type*} (Rₛ : Type*) section IsLocalizedModule -section AddCommMonoid -variable [CommSemiring R] (S : Submonoid R) - open Submodule -variable [CommSemiring Rₛ] [Algebra R Rₛ] [hT : IsLocalization S Rₛ] -variable {M M' : Type*} [AddCommMonoid M] [Module R M] - [AddCommMonoid M'] [Module R M'] [Module Rₛ M'] [IsScalarTower R Rₛ M'] (f : M →ₗ[R] M') - [IsLocalizedModule S f] +variable [CommSemiring R] (S : Submonoid R) [CommSemiring Rₛ] [Algebra R Rₛ] [IsLocalization S Rₛ] + {M Mₛ : Type*} [AddCommMonoid M] [Module R M] [AddCommMonoid Mₛ] [Module R Mₛ] + [Module Rₛ Mₛ] [IsScalarTower R Rₛ Mₛ] (f : M →ₗ[R] Mₛ) [IsLocalizedModule S f] include S @@ -53,56 +49,33 @@ theorem span_eq_top_of_isLocalizedModule {v : Set M} (hv : span R v = ⊤) : rw [← LinearMap.coe_restrictScalars R, ← LinearMap.map_span, hv] exact mem_map_of_mem mem_top -end AddCommMonoid - -section AddCommGroup - -variable {R : Type*} (Rₛ : Type*) [CommRing R] (S : Submonoid R) -variable [CommRing Rₛ] [Algebra R Rₛ] [hT : IsLocalization S Rₛ] -variable {M M' : Type*} [AddCommGroup M] [Module R M] - [AddCommGroup M'] [Module R M'] [Module Rₛ M'] [IsScalarTower R Rₛ M'] (f : M →ₗ[R] M') - [IsLocalizedModule S f] - -include S - theorem LinearIndependent.of_isLocalizedModule {ι : Type*} {v : ι → M} (hv : LinearIndependent R v) : LinearIndependent Rₛ (f ∘ v) := by - rw [linearIndependent_iff'] at hv ⊢ - intro t g hg i hi - choose! a g' hg' using IsLocalization.exist_integer_multiples S t g - have h0 : f (∑ i ∈ t, g' i • v i) = 0 := by - apply_fun ((a : R) • ·) at hg - rw [smul_zero, Finset.smul_sum] at hg - rw [map_sum, ← hg] - refine Finset.sum_congr rfl fun i hi => ?_ - rw [← smul_assoc, ← hg' i hi, map_smul, Function.comp_apply, algebraMap_smul] - obtain ⟨s, hs⟩ := (IsLocalizedModule.eq_zero_iff S f).mp h0 - simp_rw [Finset.smul_sum, Submonoid.smul_def, smul_smul] at hs - specialize hv t _ hs i hi - rw [← (IsLocalization.map_units Rₛ a).mul_right_eq_zero, ← Algebra.smul_def, ← hg' i hi] - exact (IsLocalization.map_eq_zero_iff S _ _).2 ⟨s, hv⟩ - -variable [Module Rₛ M] [IsScalarTower R Rₛ M] - -theorem LinearIndependent.localization {ι : Type*} {b : ι → M} (hli : LinearIndependent R b) : + rw [linearIndependent_iff'ₛ] at hv ⊢ + intro t g₁ g₂ eq i hi + choose! a fg hfg using IsLocalization.exist_integer_multiples S (t.disjSum t) (Sum.elim g₁ g₂) + simp_rw [Sum.forall, Finset.inl_mem_disjSum, Sum.elim_inl, Finset.inr_mem_disjSum, Sum.elim_inr, + Subtype.forall'] at hfg + apply_fun ((a : R) • ·) at eq + simp_rw [← t.sum_coe_sort, Finset.smul_sum, ← smul_assoc, ← hfg, + algebraMap_smul, Function.comp_def, ← map_smul, ← map_sum, + t.sum_coe_sort (f := fun x ↦ fg (Sum.inl x) • v x), + t.sum_coe_sort (f := fun x ↦ fg (Sum.inr x) • v x)] at eq + have ⟨s, eq⟩ := IsLocalizedModule.exists_of_eq (S := S) eq + simp_rw [Finset.smul_sum, Submonoid.smul_def, smul_smul] at eq + have := congr(algebraMap R Rₛ $(hv t _ _ eq i hi)) + simpa only [map_mul, (IsLocalization.map_units Rₛ s).mul_right_inj, hfg.1 ⟨i, hi⟩, hfg.2 ⟨i, hi⟩, + Algebra.smul_def, (IsLocalization.map_units Rₛ a).mul_right_inj] using this + +theorem LinearIndependent.localization [Module Rₛ M] [IsScalarTower R Rₛ M] + {ι : Type*} {b : ι → M} (hli : LinearIndependent R b) : LinearIndependent Rₛ b := by have := isLocalizedModule_id S M Rₛ exact hli.of_isLocalizedModule Rₛ S .id -end AddCommGroup - - -variable [CommRing R] (S : Submonoid R) - section Basis -variable [CommRing Rₛ] [Algebra R Rₛ] [hT : IsLocalization S Rₛ] - -open Submodule - -variable {M Mₛ : Type*} [AddCommGroup M] [AddCommGroup Mₛ] [Module R M] [Module R Mₛ] - [Module Rₛ Mₛ] (f : M →ₗ[R] Mₛ) [IsLocalizedModule S f] [IsScalarTower R Rₛ Mₛ] - {ι : Type*} (b : Basis ι R M) +variable {ι : Type*} (b : Basis ι R M) /-- If `M` has an `R`-basis, then localizing `M` at `S` has a basis over `R` localized at `S`. -/ noncomputable def Basis.ofIsLocalizedModule : Basis ι Rₛ Mₛ := @@ -138,12 +111,12 @@ end IsLocalizedModule section LocalizationLocalization -variable [CommRing R] (S : Submonoid R) [CommRing Rₛ] [Algebra R Rₛ] -variable [hT : IsLocalization S Rₛ] -variable {A : Type*} [CommRing A] [Algebra R A] -variable (Aₛ : Type*) [CommRing Aₛ] [Algebra A Aₛ] +variable [CommSemiring R] (S : Submonoid R) [CommSemiring Rₛ] [Algebra R Rₛ] +variable [IsLocalization S Rₛ] +variable {A : Type*} [CommSemiring A] [Algebra R A] +variable (Aₛ : Type*) [CommSemiring Aₛ] [Algebra A Aₛ] variable [Algebra Rₛ Aₛ] [Algebra R Aₛ] [IsScalarTower R Rₛ Aₛ] [IsScalarTower R A Aₛ] -variable [hA : IsLocalization (Algebra.algebraMapSubmonoid A S) Aₛ] +variable [IsLocalization (Algebra.algebraMapSubmonoid A S) Aₛ] open Submodule diff --git a/Mathlib/RingTheory/TensorProduct/Basic.lean b/Mathlib/RingTheory/TensorProduct/Basic.lean index 010c0ec9677b1..06ad42f8fd9ac 100644 --- a/Mathlib/RingTheory/TensorProduct/Basic.lean +++ b/Mathlib/RingTheory/TensorProduct/Basic.lean @@ -1189,16 +1189,16 @@ variable {R M₁ M₂ ι ι₂ : Type*} (A : Type*) end LinearMap -lemma Algebra.baseChange_lmul {R B : Type*} [CommRing R] [CommRing B] [Algebra R B] - {A : Type*} [CommRing A] [Algebra R A] (f : B) : +lemma Algebra.baseChange_lmul {R B : Type*} [CommSemiring R] [Semiring B] [Algebra R B] + {A : Type*} [CommSemiring A] [Algebra R A] (f : B) : (Algebra.lmul R B f).baseChange A = Algebra.lmul A (A ⊗[R] B) (1 ⊗ₜ f) := by ext i simp namespace LinearMap -variable (R A M N : Type*) [CommRing R] [CommRing A] [Algebra R A] -variable [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] +variable (R A M N : Type*) [CommSemiring R] [CommSemiring A] [Algebra R A] +variable [AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] open Module open scoped TensorProduct From 6815c41915960a23ef48c0389ff68806f66dabbe Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Wed, 15 Jan 2025 15:07:12 +0000 Subject: [PATCH 247/681] feat(Order/Interval/Finset): map sectL and sectR on finset intervals (#20759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Useful from the disproof of the Aharoni–Korman conjecture, https://github.com/leanprover-community/mathlib4/pull/20082. --- Mathlib/Order/Interval/Finset/Basic.lean | 54 ++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Mathlib/Order/Interval/Finset/Basic.lean b/Mathlib/Order/Interval/Finset/Basic.lean index 4a58782628847..14f11002898d2 100644 --- a/Mathlib/Order/Interval/Finset/Basic.lean +++ b/Mathlib/Order/Interval/Finset/Basic.lean @@ -599,6 +599,60 @@ theorem card_Ioo_eq_card_Icc_sub_two (a b : α) : #(Ioo a b) = #(Icc a b) - 2 := end PartialOrder +section Prod + +variable {β : Type*} + +section sectL + +lemma uIcc_map_sectL [Lattice α] [Lattice β] [LocallyFiniteOrder α] [LocallyFiniteOrder β] + [DecidableRel (α := α × β) (· ≤ ·)] (a b : α) (c : β) : + (uIcc a b).map (.sectL _ c) = uIcc (a, c) (b, c) := by + aesop (add safe forward [le_antisymm]) + +variable [Preorder α] [PartialOrder β] [LocallyFiniteOrder α] [LocallyFiniteOrder β] + [DecidableRel (α := α × β) (· ≤ ·)] (a b : α) (c : β) + +lemma Icc_map_sectL : (Icc a b).map (.sectL _ c) = Icc (a, c) (b, c) := by + aesop (add safe forward [le_antisymm]) + +lemma Ioc_map_sectL : (Ioc a b).map (.sectL _ c) = Ioc (a, c) (b, c) := by + aesop (add safe forward [le_antisymm, le_of_lt]) + +lemma Ico_map_sectL : (Ico a b).map (.sectL _ c) = Ico (a, c) (b, c) := by + aesop (add safe forward [le_antisymm, le_of_lt]) + +lemma Ioo_map_sectL : (Ioo a b).map (.sectL _ c) = Ioo (a, c) (b, c) := by + aesop (add safe forward [le_antisymm, le_of_lt]) + +end sectL + +section sectR + +lemma uIcc_map_sectR [Lattice α] [Lattice β] [LocallyFiniteOrder α] [LocallyFiniteOrder β] + [DecidableRel (α := α × β) (· ≤ ·)] (c : α) (a b : β) : + (uIcc a b).map (.sectR c _) = uIcc (c, a) (c, b) := by + aesop (add safe forward [le_antisymm]) + +variable [PartialOrder α] [Preorder β] [LocallyFiniteOrder α] [LocallyFiniteOrder β] + [DecidableRel (α := α × β) (· ≤ ·)] (c : α) (a b : β) + +lemma Icc_map_sectR : (Icc a b).map (.sectR c _) = Icc (c, a) (c, b) := by + aesop (add safe forward [le_antisymm]) + +lemma Ioc_map_sectR : (Ioc a b).map (.sectR c _) = Ioc (c, a) (c, b) := by + aesop (add safe forward [le_antisymm, le_of_lt]) + +lemma Ico_map_sectR : (Ico a b).map (.sectR c _) = Ico (c, a) (c, b) := by + aesop (add safe forward [le_antisymm, le_of_lt]) + +lemma Ioo_map_sectR : (Ioo a b).map (.sectR c _) = Ioo (c, a) (c, b) := by + aesop (add safe forward [le_antisymm, le_of_lt]) + +end sectR + +end Prod + section BoundedPartialOrder variable [PartialOrder α] From 739d77706792a2fe1a9223e5c342ff46b17163b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Wed, 15 Jan 2025 15:41:33 +0000 Subject: [PATCH 248/681] =?UTF-8?q?refactor:=20redefine=20`Subrel`=20in=20?= =?UTF-8?q?terms=20of=20`=CE=B1=20=E2=86=92=20Prop`=20instead=20of=20`Set?= =?UTF-8?q?=20=CE=B1`=20(#20475)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, `Subrel r {x | p x}` interacts poorly with `simp`, as the type signature is rewritten from `↑{x | p x} → ↑{x | p x} → Prop` to `{x // p x} → {x // p x} → Prop`. This can be avoided by writing `Subrel r p` instead. --- Mathlib/Order/InitialSeg.lean | 17 ++++---- Mathlib/Order/RelIso/Set.lean | 49 ++++++++++------------ Mathlib/SetTheory/Cardinal/Cofinality.lean | 4 +- Mathlib/SetTheory/Ordinal/Basic.lean | 3 +- Mathlib/SetTheory/ZFC/Ordinal.lean | 17 ++++---- 5 files changed, 41 insertions(+), 49 deletions(-) diff --git a/Mathlib/Order/InitialSeg.lean b/Mathlib/Order/InitialSeg.lean index 422bdd991e55c..1835e0dcd4665 100644 --- a/Mathlib/Order/InitialSeg.lean +++ b/Mathlib/Order/InitialSeg.lean @@ -217,7 +217,7 @@ theorem eq_or_principal [IsWellOrder β s] (f : r ≼i s) : cases hy (Set.mem_range_self z) /-- 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 := +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.mem_range_of_rel h ⟨a', by subst e; rfl⟩⟩ @@ -458,11 +458,9 @@ theorem top_rel_top {r : α → α → Prop} {s : β → β → Prop} {t : γ @[deprecated top_rel_top (since := "2024-10-10")] alias topLTTop := top_rel_top -/-- Build a principal segment embedding into a given interval `{ b | r b a }`. -/ --- The explicit typing is required in order for `simp` to work properly. +/-- Any element of a well order yields a principal segment. -/ @[simps!] -def ofElement {α : Type*} (r : α → α → Prop) (a : α) : - @PrincipalSeg { b // r b a } α (Subrel r { b | r b a }) r := +def ofElement {α : Type*} (r : α → α → Prop) (a : α) : Subrel r (r · a) ≺i r := ⟨Subrel.relEmbedding _ _, a, fun _ => ⟨fun ⟨⟨_, h⟩, rfl⟩ => h, fun h => ⟨⟨_, h⟩, rfl⟩⟩⟩ @[simp] @@ -470,15 +468,13 @@ theorem ofElement_apply {α : Type*} (r : α → α → Prop) (a : α) (b) : ofE rfl /-- For any principal segment `r ≺i s`, there is a `Subrel` of `s` order isomorphic to `r`. -/ --- The explicit typing is required in order for `simp` to work properly. @[simps! symm_apply] -noncomputable def subrelIso (f : r ≺i s) : - @RelIso { b // s b f.top } α (Subrel s { b | s b f.top }) r := +noncomputable def subrelIso (f : r ≺i s) : Subrel s (s · f.top) ≃r r := RelIso.symm ⟨(Equiv.ofInjective f f.injective).trans (Equiv.setCongr (funext fun _ ↦ propext f.mem_range_iff_rel)), f.map_rel_iff⟩ @[simp] -theorem apply_subrelIso (f : r ≺i s) (b : {b | s b f.top}) : f (f.subrelIso b) = b := +theorem apply_subrelIso (f : r ≺i s) (b : {b // s b f.top}) : f (f.subrelIso b) = b := Equiv.apply_ofInjective_symm f.injective _ @[simp] @@ -486,7 +482,8 @@ theorem subrelIso_apply (f : r ≺i s) (a : α) : f.subrelIso ⟨f a, f.lt_top a Equiv.ofInjective_symm_apply f.injective _ /-- Restrict the codomain of a principal segment embedding. -/ -def codRestrict (p : Set β) (f : r ≺i s) (H : ∀ a, f a ∈ p) (H₂ : f.top ∈ p) : r ≺i Subrel s p := +def codRestrict (p : Set β) (f : r ≺i s) (H : ∀ a, f a ∈ p) (H₂ : f.top ∈ p) : + r ≺i Subrel s (· ∈ p) := ⟨RelEmbedding.codRestrict p f H, ⟨f.top, H₂⟩, fun ⟨_, _⟩ => by simp [← f.mem_range_iff_rel]⟩ @[simp] diff --git a/Mathlib/Order/RelIso/Set.lean b/Mathlib/Order/RelIso/Set.lean index e7e04319e0243..73c00fb2a9a04 100644 --- a/Mathlib/Order/RelIso/Set.lean +++ b/Mathlib/Order/RelIso/Set.lean @@ -45,66 +45,61 @@ theorem range_eq (e : r ≃r s) : Set.range e = Set.univ := end RelIso -/-- `Subrel r p` is the inherited relation on a subset. -/ -def Subrel (r : α → α → Prop) (p : Set α) : p → p → Prop := - (Subtype.val : p → α) ⁻¹'o r +/-- `Subrel r p` is the inherited relation on a subtype. + +We could also consider a Set.Subrel r s variant for dot notation, but this ends up interacting +poorly with `simpNF`. -/ +def Subrel (r : α → α → Prop) (p : α → Prop) : Subtype p → Subtype p → Prop := + Subtype.val ⁻¹'o r @[simp] -theorem subrel_val (r : α → α → Prop) (p : Set α) {a b} : Subrel r p a b ↔ r a.1 b.1 := +theorem subrel_val (r : α → α → Prop) (p : α → Prop) {a b} : Subrel r p a b ↔ r a.1 b.1 := Iff.rfl namespace Subrel /-- The relation embedding from the inherited relation on a subset. -/ -protected def relEmbedding (r : α → α → Prop) (p : Set α) : Subrel r p ↪r r := +protected def relEmbedding (r : α → α → Prop) (p : α → Prop) : Subrel r p ↪r r := ⟨Embedding.subtype _, Iff.rfl⟩ @[simp] theorem relEmbedding_apply (r : α → α → Prop) (p a) : Subrel.relEmbedding r p a = a.1 := rfl -/-- A set inclusion as a relation embedding. -/ -protected def inclusionEmbedding (r : α → α → Prop) {p q : Set α} (h : p ⊆ q) : - Subrel r p ↪r Subrel r q where +/-- `Set.inclusion` as a relation embedding. -/ +protected def inclusionEmbedding (r : α → α → Prop) {s t : Set α} (h : s ⊆ t) : + Subrel r (· ∈ s) ↪r Subrel r (· ∈ t) where toFun := Set.inclusion h inj' _ _ h := (Set.inclusion_inj _).mp h map_rel_iff' := Iff.rfl @[simp] -theorem coe_inclusionEmbedding (r : α → α → Prop) {p q : Set α} (h : p ⊆ q) : - (Subrel.inclusionEmbedding r h : p → q) = Set.inclusion h := +theorem coe_inclusionEmbedding (r : α → α → Prop) {s t : Set α} (h : s ⊆ t) : + (Subrel.inclusionEmbedding r h : s → t) = Set.inclusion h := rfl -instance (r : α → α → Prop) [IsWellOrder α r] (p : Set α) : IsWellOrder p (Subrel r p) := +instance (r : α → α → Prop) [IsWellOrder α r] (p : α → Prop) : IsWellOrder _ (Subrel r p) := RelEmbedding.isWellOrder (Subrel.relEmbedding r p) --- TODO: this instance is needed as `simp` automatically simplifies `↑{a // p a}` as `{a | p a}`. --- --- Should `Subrel` be redefined in terms of `p : α → Prop` instead of `p : Set α` to avoid --- this issue? -instance (r : α → α → Prop) (p : α → Prop) [IsWellOrder α r] : - IsWellOrder {a // p a} (Subrel r {a | p a}) := - instIsWellOrderElem _ _ - -instance (r : α → α → Prop) [IsRefl α r] (p : Set α) : IsRefl p (Subrel r p) := +instance (r : α → α → Prop) [IsRefl α r] (p : α → Prop) : IsRefl _ (Subrel r p) := ⟨fun x => @IsRefl.refl α r _ x⟩ -instance (r : α → α → Prop) [IsSymm α r] (p : Set α) : IsSymm p (Subrel r p) := +instance (r : α → α → Prop) [IsSymm α r] (p : α → Prop) : IsSymm _ (Subrel r p) := ⟨fun x y => @IsSymm.symm α r _ x y⟩ -instance (r : α → α → Prop) [IsAsymm α r] (p : Set α) : IsAsymm p (Subrel r p) := +instance (r : α → α → Prop) [IsAsymm α r] (p : α → Prop) : IsAsymm _ (Subrel r p) := ⟨fun x y => @IsAsymm.asymm α r _ x y⟩ -instance (r : α → α → Prop) [IsTrans α r] (p : Set α) : IsTrans p (Subrel r p) := +instance (r : α → α → Prop) [IsTrans α r] (p : α → Prop) : IsTrans _ (Subrel r p) := ⟨fun x y z => @IsTrans.trans α r _ x y z⟩ -instance (r : α → α → Prop) [IsIrrefl α r] (p : Set α) : IsIrrefl p (Subrel r p) := +instance (r : α → α → Prop) [IsIrrefl α r] (p : α → Prop) : IsIrrefl _ (Subrel r p) := ⟨fun x => @IsIrrefl.irrefl α r _ x⟩ end Subrel /-- Restrict the codomain of a relation embedding. -/ -def RelEmbedding.codRestrict (p : Set β) (f : r ↪r s) (H : ∀ a, f a ∈ p) : r ↪r Subrel s p := +def RelEmbedding.codRestrict (p : Set β) (f : r ↪r s) (H : ∀ a, f a ∈ p) : r ↪r Subrel s (· ∈ p) := ⟨f.toEmbedding.codRestrict p H, f.map_rel_iff'⟩ @[simp] @@ -123,12 +118,12 @@ theorem RelIso.preimage_eq_image_symm (e : r ≃r s) (t : Set β) : e ⁻¹' t = end image theorem Acc.of_subrel {r : α → α → Prop} [IsTrans α r] {b : α} (a : { a // r a b }) - (h : Acc (Subrel r { a | r a b }) a) : Acc r a.1 := + (h : Acc (Subrel r (r · b)) a) : Acc r a.1 := h.recOn fun a _ IH ↦ ⟨_, fun _ hb ↦ IH ⟨_, _root_.trans hb a.2⟩ hb⟩ /-- A relation `r` is well-founded iff every downward-interval `{ a | r a b }` of it is well-founded. -/ theorem wellFounded_iff_wellFounded_subrel {r : α → α → Prop} [IsTrans α r] : - WellFounded r ↔ ∀ b, WellFounded (Subrel r { a | r a b }) where + WellFounded r ↔ ∀ b, WellFounded (Subrel r (r · b)) where mp h _ := InvImage.wf Subtype.val h mpr h := ⟨fun a ↦ ⟨_, fun b hr ↦ ((h a).apply _).of_subrel ⟨b, hr⟩⟩⟩ diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index c165757a42992..7d7201ca375ba 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.lean @@ -157,7 +157,7 @@ theorem cof_eq (r : α → α → Prop) [IsWellOrder α r] : ∃ S, Unbounded r csInf_mem (Order.cof_nonempty (swap rᶜ)) theorem ord_cof_eq (r : α → α → Prop) [IsWellOrder α r] : - ∃ S, Unbounded r S ∧ type (Subrel r S) = (cof (type r)).ord := by + ∃ S, Unbounded r S ∧ type (Subrel r (· ∈ S)) = (cof (type r)).ord := by let ⟨S, hS, e⟩ := cof_eq r let ⟨s, _, e'⟩ := Cardinal.ord_eq S let T : Set α := { a | ∃ aS : a ∈ S, ∀ b : S, s b ⟨_, aS⟩ → r b a } @@ -570,7 +570,7 @@ theorem exists_fundamental_sequence (a : Ordinal.{u}) : rcases exists_lsub_cof a with ⟨ι, f, hf, hι⟩ rcases ord_eq ι with ⟨r, wo, hr⟩ haveI := wo - let r' := Subrel r { i | ∀ j, r j i → f j < f i } + let r' := Subrel r fun i ↦ ∀ j, r j i → f j < f i let hrr' : r' ↪r r := Subrel.relEmbedding _ _ haveI := hrr'.isWellOrder refine diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index d2a8aebee9c3b..710ae041e6110 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -437,7 +437,7 @@ theorem typein.principalSeg_coe (r : α → α → Prop) [IsWellOrder α r] : @[simp] theorem type_subrel (r : α → α → Prop) [IsWellOrder α r] (a : α) : - type (Subrel r { b | r b a }) = typein r a := + type (Subrel r (r · a)) = typein r a := rfl @[simp] @@ -515,6 +515,7 @@ theorem enum_le_enum (r : α → α → Prop) [IsWellOrder α r] {o₁ o₂ : Ii ¬r (enum r o₁) (enum r o₂) ↔ o₂ ≤ o₁ := by rw [enum_lt_enum (r := r), not_lt] +-- TODO: generalize to other well-orders @[simp] theorem enum_le_enum' (a : Ordinal) {o₁ o₂ : Iio (type (· < ·))} : enum (· < ·) o₁ ≤ enum (α := a.toType) (· < ·) o₂ ↔ o₁ ≤ o₂ := by diff --git a/Mathlib/SetTheory/ZFC/Ordinal.lean b/Mathlib/SetTheory/ZFC/Ordinal.lean index 7c46875d8c788..cd9d05f74ac26 100644 --- a/Mathlib/SetTheory/ZFC/Ordinal.lean +++ b/Mathlib/SetTheory/ZFC/Ordinal.lean @@ -118,13 +118,13 @@ theorem subset_of_mem (h : x.IsOrdinal) : y ∈ x → y ⊆ x := theorem mem_trans (h : z.IsOrdinal) : x ∈ y → y ∈ z → x ∈ z := h.isTransitive.mem_trans -protected theorem isTrans (h : x.IsOrdinal) : IsTrans x.toSet (Subrel (· ∈ ·) _) := +protected theorem isTrans (h : x.IsOrdinal) : IsTrans _ (Subrel (· ∈ ·) (· ∈ x)) := ⟨fun _ _ c hab hbc => h.mem_trans' hab hbc c.2⟩ /-- The simplified form of transitivity used within `IsOrdinal` yields an equivalent definition to the standard one. -/ theorem _root_.ZFSet.isOrdinal_iff_isTrans : - x.IsOrdinal ↔ x.IsTransitive ∧ IsTrans x.toSet (Subrel (· ∈ ·) _) where + x.IsOrdinal ↔ x.IsTransitive ∧ IsTrans _ (Subrel (· ∈ ·) (· ∈ x)) where mp h := ⟨h.isTransitive, h.isTrans⟩ mpr := by rintro ⟨h₁, ⟨h₂⟩⟩ @@ -134,8 +134,7 @@ theorem _root_.ZFSet.isOrdinal_iff_isTrans : protected theorem mem (hx : x.IsOrdinal) (hy : y ∈ x) : y.IsOrdinal := have := hx.isTrans - let f : Subrel (· ∈ ·) y.toSet ↪r Subrel (· ∈ ·) x.toSet := - Subrel.inclusionEmbedding (· ∈ ·) (hx.subset_of_mem hy) + let f : _ ↪r Subrel (· ∈ ·) (· ∈ x) := Subrel.inclusionEmbedding (· ∈ ·) (hx.subset_of_mem hy) isOrdinal_iff_isTrans.2 ⟨fun _ hz _ ha ↦ hx.mem_trans' ha hz hy, f.isTrans⟩ /-- An ordinal is a transitive set of transitive sets. -/ @@ -203,30 +202,30 @@ theorem mem_trichotomous (hx : x.IsOrdinal) (hy : y.IsOrdinal) : x ∈ y ∨ x = rw [eq_comm, ← subset_iff_eq_or_mem hy hx] exact mem_or_subset hx hy -protected theorem isTrichotomous (h : x.IsOrdinal) : IsTrichotomous x.toSet (Subrel (· ∈ ·) _) := +protected theorem isTrichotomous (h : x.IsOrdinal) : IsTrichotomous _ (Subrel (· ∈ ·) (· ∈ x)) := ⟨fun ⟨a, ha⟩ ⟨b, hb⟩ ↦ by simpa using mem_trichotomous (h.mem ha) (h.mem hb)⟩ /-- An ordinal is a transitive set, trichotomous under membership. -/ theorem _root_.ZFSet.isOrdinal_iff_isTrichotomous : - x.IsOrdinal ↔ x.IsTransitive ∧ IsTrichotomous x.toSet (Subrel (· ∈ ·) _) where + x.IsOrdinal ↔ x.IsTransitive ∧ IsTrichotomous _ (Subrel (· ∈ ·) (· ∈ x)) where mp h := ⟨h.isTransitive, h.isTrichotomous⟩ mpr := by rintro ⟨h₁, h₂⟩ rw [isOrdinal_iff_isTrans] refine ⟨h₁, ⟨@fun y z w hyz hzw ↦ ?_⟩⟩ - obtain hyw | rfl | hwy := trichotomous_of (Subrel (· ∈ ·) _) y w + obtain hyw | rfl | hwy := trichotomous_of (Subrel (· ∈ ·) (· ∈ x)) y w · exact hyw · cases asymm hyz hzw · cases mem_wf.asymmetric₃ _ _ _ hyz hzw hwy -protected theorem isWellOrder (h : x.IsOrdinal) : IsWellOrder x.toSet (Subrel (· ∈ ·) _) where +protected theorem isWellOrder (h : x.IsOrdinal) : IsWellOrder _ (Subrel (· ∈ ·) (· ∈ x)) where wf := (Subrel.relEmbedding _ _).wellFounded mem_wf trans := h.isTrans.1 trichotomous := h.isTrichotomous.1 /-- An ordinal is a transitive set, well-ordered under membership. -/ theorem _root_.ZFSet.isOrdinal_iff_isWellOrder : x.IsOrdinal ↔ - x.IsTransitive ∧ IsWellOrder x.toSet (Subrel (· ∈ ·) _) := by + x.IsTransitive ∧ IsWellOrder _ (Subrel (· ∈ ·) (· ∈ x)) := by use fun h ↦ ⟨h.isTransitive, h.isWellOrder⟩ rintro ⟨h₁, h₂⟩ refine isOrdinal_iff_isTrans.2 ⟨h₁, ?_⟩ From 753e8db210dbf020ebdccc1c23fd960dabb99321 Mon Sep 17 00:00:00 2001 From: JovanGerb Date: Wed, 15 Jan 2025 16:57:43 +0000 Subject: [PATCH 249/681] chore: remove last few instances of `set_option tactic.skipAssignedInstances false` (#20193) This PR removes the last few instances of the backward compatability option `set_option tactic.skipAssignedInstances false`. To achieve this, the `simp` tag from `Disjoint.of_image_finset` is removed, which I think shouldn't have been a simp lemma in the first place. Co-authored-by: JovanGerb <56355248+JovanGerb@users.noreply.github.com> --- Mathlib/Algebra/Group/Hom/CompTypeclasses.lean | 1 - Mathlib/CategoryTheory/Limits/Fubini.lean | 7 ++----- Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Internal/Module.lean | 2 -- Mathlib/Combinatorics/SetFamily/Shadow.lean | 1 - Mathlib/Data/Finset/Image.lean | 1 - Mathlib/Data/ZMod/Units.lean | 5 +++++ Mathlib/FieldTheory/RatFunc/Basic.lean | 1 - Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean | 3 +-- Mathlib/NumberTheory/DirichletCharacter/Basic.lean | 4 +--- Mathlib/RepresentationTheory/Rep.lean | 4 ---- Mathlib/RingTheory/Polynomial/ScaleRoots.lean | 5 ++--- Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean | 6 ++---- Mathlib/Topology/Order.lean | 3 +-- 14 files changed, 16 insertions(+), 31 deletions(-) diff --git a/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean b/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean index 0bdd4b963dd4a..db86ffcbf6234 100644 --- a/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean +++ b/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean @@ -93,7 +93,6 @@ lemma comp_apply ψ (φ x) = χ x := by rw [← h.comp_eq, MonoidHom.comp_apply] -@[simp] theorem comp_assoc {Q : Type*} [Monoid Q] {φ₁ : M →* N} {φ₂ : N →* P} {φ₁₂ : M →* P} (κ : CompTriple φ₁ φ₂ φ₁₂) diff --git a/Mathlib/CategoryTheory/Limits/Fubini.lean b/Mathlib/CategoryTheory/Limits/Fubini.lean index 9a6aedbc78108..b88719fff8455 100644 --- a/Mathlib/CategoryTheory/Limits/Fubini.lean +++ b/Mathlib/CategoryTheory/Limits/Fubini.lean @@ -435,8 +435,7 @@ noncomputable def limitIsoLimitCurryCompLim : limit G ≅ limit (curry.obj G ⋙ @[simp, reassoc] theorem limitIsoLimitCurryCompLim_hom_π_π {j} {k} : (limitIsoLimitCurryCompLim G).hom ≫ limit.π _ j ≫ limit.π _ k = limit.π _ (j, k) := by - set_option tactic.skipAssignedInstances false in - simp [limitIsoLimitCurryCompLim, Trans.simple, HasLimit.isoOfNatIso, limitUncurryIsoLimitCompLim] + simp [limitIsoLimitCurryCompLim, Trans.simple] -- Porting note: Added type annotation `limit (_ ⋙ lim) ⟶ _` @[simp, reassoc] @@ -469,9 +468,7 @@ noncomputable def colimitIsoColimitCurryCompColim : colimit G ≅ colimit (curry theorem colimitIsoColimitCurryCompColim_ι_ι_inv {j} {k} : colimit.ι ((curry.obj G).obj j) k ≫ colimit.ι (curry.obj G ⋙ colim) j ≫ (colimitIsoColimitCurryCompColim G).inv = colimit.ι _ (j, k) := by - set_option tactic.skipAssignedInstances false in - simp [colimitIsoColimitCurryCompColim, Trans.simple, HasColimit.isoOfNatIso, - colimitUncurryIsoColimitCompColim] + simp [colimitIsoColimitCurryCompColim, Trans.simple, colimitUncurryIsoColimitCompColim] @[simp, reassoc] theorem colimitIsoColimitCurryCompColim_ι_hom {j} {k} : diff --git a/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean b/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean index 8b946e7dc6aed..910625a02dc20 100644 --- a/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean +++ b/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean @@ -269,7 +269,6 @@ theorem normalize_naturality (n : NormalMonoidalObject C) {X Y : F C} (f : X ⟶ end -set_option tactic.skipAssignedInstances false in /-- The isomorphism between `n ⊗ X` and `normalize X n` is natural (in both `X` and `n`, but naturality in `n` is trivial and was "proved" in `normalizeIsoAux`). This is the real heart of our proof of the coherence theorem. -/ @@ -278,7 +277,8 @@ def normalizeIso : tensorFunc C ≅ normalize' C := intro X Y f ext ⟨n⟩ convert normalize_naturality n f using 1 - any_goals dsimp [NatIso.ofComponents]; congr; apply normalizeIsoApp_eq + any_goals dsimp; rw [normalizeIsoApp_eq] + rfl /-- The isomorphism between an object and its normal form is natural. -/ def fullNormalizeIso : 𝟭 (F C) ≅ fullNormalize C ⋙ inclusion := diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean index 88327db8743f3..bab5dcf1df792 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean @@ -134,12 +134,10 @@ def inverseObj (A : AlgebraCat.{u} R) : Mon_ (ModuleCat.{u} R) where dsimp mul_assoc := by ext : 1 - set_option tactic.skipAssignedInstances false in -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): `ext` did not pick up `TensorProduct.ext` refine TensorProduct.ext <| TensorProduct.ext <| LinearMap.ext fun x => LinearMap.ext fun y => LinearMap.ext fun z => ?_ dsimp only [compr₂_apply, TensorProduct.mk_apply] - rw [compr₂_apply, compr₂_apply] rw [hom_comp, LinearMap.comp_apply, hom_comp, LinearMap.comp_apply, hom_comp, LinearMap.comp_apply] erw [LinearMap.mul'_apply, LinearMap.mul'_apply] diff --git a/Mathlib/Combinatorics/SetFamily/Shadow.lean b/Mathlib/Combinatorics/SetFamily/Shadow.lean index 7e12901d9f2f6..98557ae4406a6 100644 --- a/Mathlib/Combinatorics/SetFamily/Shadow.lean +++ b/Mathlib/Combinatorics/SetFamily/Shadow.lean @@ -119,7 +119,6 @@ lemma mem_shadow_iterate_iff_exists_card : t ∈ ∂^[k] 𝒜 ↔ ∃ u : Finset α, #u = k ∧ Disjoint t u ∧ t ∪ u ∈ 𝒜 := by induction' k with k ih generalizing t · simp - set_option tactic.skipAssignedInstances false in simp only [mem_shadow_iff_insert_mem, ih, Function.iterate_succ_apply', card_eq_succ] aesop diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index 27d7c37b2b821..c05c5afa72d5d 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -488,7 +488,6 @@ theorem image_symmDiff [DecidableEq α] {f : α → β} (s t : Finset α) (hf : (s ∆ t).image f = s.image f ∆ t.image f := mod_cast Set.image_symmDiff hf s t -@[simp] theorem _root_.Disjoint.of_image_finset {s t : Finset α} {f : α → β} (h : Disjoint (s.image f) (t.image f)) : Disjoint s t := disjoint_iff_ne.2 fun _ ha _ hb => diff --git a/Mathlib/Data/ZMod/Units.lean b/Mathlib/Data/ZMod/Units.lean index 527428b0ddbd9..ff194571eb8a8 100644 --- a/Mathlib/Data/ZMod/Units.lean +++ b/Mathlib/Data/ZMod/Units.lean @@ -33,6 +33,11 @@ lemma unitsMap_comp {d : ℕ} (hm : n ∣ m) (hd : m ∣ d) : lemma unitsMap_self (n : ℕ) : unitsMap (dvd_refl n) = MonoidHom.id _ := by simp [unitsMap, castHom_self] +/-- `unitsMap_val` shows that coercing from `(ZMod m)ˣ` to `ZMod n` gives the same result +when going via `(ZMod n)ˣ` and `ZMod m`. -/ +lemma unitsMap_val (h : n ∣ m) (a : (ZMod m)ˣ) : + ↑(unitsMap h a) = ((a : ZMod m).cast : ZMod n) := rfl + lemma isUnit_cast_of_dvd (hm : n ∣ m) (a : Units (ZMod m)) : IsUnit (cast (a : ZMod m) : ZMod n) := Units.isUnit (unitsMap hm a) @[deprecated (since := "2024-12-16")] alias IsUnit_cast_of_dvd := isUnit_cast_of_dvd diff --git a/Mathlib/FieldTheory/RatFunc/Basic.lean b/Mathlib/FieldTheory/RatFunc/Basic.lean index 348de8a75e63b..c5ca7de7845f5 100644 --- a/Mathlib/FieldTheory/RatFunc/Basic.lean +++ b/Mathlib/FieldTheory/RatFunc/Basic.lean @@ -741,7 +741,6 @@ open GCDMonoid Polynomial variable [Field K] -set_option tactic.skipAssignedInstances false in /-- `RatFunc.numDenom` are numerator and denominator of a rational function over a field, normalized such that the denominator is monic. -/ def numDenom (x : RatFunc K) : K[X] × K[X] := diff --git a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean index 66b253e50a6c7..f52cccf477bc3 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean @@ -551,8 +551,7 @@ theorem ker_noncommProd_eq_of_supIndep_ker [FiniteDimensional K V] {ι : Type*} ker (s.noncommProd f comm) = ⨆ i ∈ s, ker (f i) := by classical induction' s using Finset.induction_on with i s hi ih - · set_option tactic.skipAssignedInstances false in - simpa using LinearMap.ker_id + · simp [one_eq_id] replace ih : ker (Finset.noncommProd s f <| Set.Pairwise.mono (s.subset_insert i) comm) = ⨆ x ∈ s, ker (f x) := ih _ (h.subset (s.subset_insert i)) rw [Finset.noncommProd_insert_of_not_mem _ _ _ _ hi, mul_eq_comp, diff --git a/Mathlib/NumberTheory/DirichletCharacter/Basic.lean b/Mathlib/NumberTheory/DirichletCharacter/Basic.lean index 2cc4463a984a0..a811a9135a7d5 100644 --- a/Mathlib/NumberTheory/DirichletCharacter/Basic.lean +++ b/Mathlib/NumberTheory/DirichletCharacter/Basic.lean @@ -93,9 +93,7 @@ lemma changeLevel_trans {m d : ℕ} (hm : n ∣ m) (hd : m ∣ d) : lemma changeLevel_eq_cast_of_dvd {m : ℕ} (hm : n ∣ m) (a : Units (ZMod m)) : (changeLevel hm χ) a = χ (ZMod.cast (a : ZMod m)) := by - set_option tactic.skipAssignedInstances false in - simpa [changeLevel_def, Function.comp_apply, MonoidHom.coe_comp] using - toUnitHom_eq_char' _ <| ZMod.isUnit_cast_of_dvd hm a + simp [changeLevel_def, ZMod.unitsMap_val] /-- `χ` of level `n` factors through a Dirichlet character `χ₀` of level `d` if `d ∣ n` and `χ₀ = χ ∘ (ZMod n → ZMod d)`. -/ diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index d5a61a690bbcc..4c2866323bf62 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -574,11 +574,7 @@ def counitIso (M : ModuleCat.{u} (MonoidAlgebra k G)) : LinearEquiv.toModuleIso { counitIsoAddEquiv with map_smul' := fun r x => by - set_option tactic.skipAssignedInstances false in dsimp [counitIsoAddEquiv] - /- Porting note: rest of broken proof was `simp`. -/ - rw [AddEquiv.trans_apply] - rw [AddEquiv.trans_apply] erw [@Representation.ofModule_asAlgebraHom_apply_apply k G _ _ _ _ (_)] exact AddEquiv.symm_apply_apply _ _} diff --git a/Mathlib/RingTheory/Polynomial/ScaleRoots.lean b/Mathlib/RingTheory/Polynomial/ScaleRoots.lean index 38ee5b2e41344..e6b88407e59d5 100644 --- a/Mathlib/RingTheory/Polynomial/ScaleRoots.lean +++ b/Mathlib/RingTheory/Polynomial/ScaleRoots.lean @@ -152,9 +152,8 @@ theorem scaleRoots_aeval_eq_zero [Algebra R A] {p : R[X]} {a : A} {r : R} (ha : theorem scaleRoots_eval₂_eq_zero_of_eval₂_div_eq_zero {p : S[X]} {f : S →+* K} (hf : Function.Injective f) {r s : S} (hr : eval₂ f (f r / f s) p = 0) (hs : s ∈ nonZeroDivisors S) : eval₂ f (f r) (scaleRoots p s) = 0 := by - -- The proof works without this option, but *much* slower. - set_option tactic.skipAssignedInstances false in - nontriviality S using Subsingleton.eq_zero + -- if we don't specify the type with `(_ : S)`, the proof is much slower + nontriviality S using Subsingleton.eq_zero (_ : S) convert @scaleRoots_eval₂_eq_zero _ _ _ _ p f _ s hr rw [← mul_div_assoc, mul_comm, mul_div_cancel_right₀] exact map_ne_zero_of_mem_nonZeroDivisors _ hf hs diff --git a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean index 1bc507cd752fd..bf7d634387ace 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean @@ -29,15 +29,13 @@ variable {X Y Z : TopCat.{u}} /-- The first projection from the pullback. -/ abbrev pullbackFst (f : X ⟶ Z) (g : Y ⟶ Z) : TopCat.of { p : X × Y // f p.1 = g p.2 } ⟶ X := - ⟨Prod.fst ∘ Subtype.val, by - apply Continuous.comp <;> set_option tactic.skipAssignedInstances false in continuity⟩ + ⟨Prod.fst ∘ Subtype.val, by fun_prop⟩ lemma pullbackFst_apply (f : X ⟶ Z) (g : Y ⟶ Z) (x) : pullbackFst f g x = x.1.1 := rfl /-- The second projection from the pullback. -/ abbrev pullbackSnd (f : X ⟶ Z) (g : Y ⟶ Z) : TopCat.of { p : X × Y // f p.1 = g p.2 } ⟶ Y := - ⟨Prod.snd ∘ Subtype.val, by - apply Continuous.comp <;> set_option tactic.skipAssignedInstances false in continuity⟩ + ⟨Prod.snd ∘ Subtype.val, by fun_prop⟩ lemma pullbackSnd_apply (f : X ⟶ Z) (g : Y ⟶ Z) (x) : pullbackSnd f g x = x.1.2 := rfl diff --git a/Mathlib/Topology/Order.lean b/Mathlib/Topology/Order.lean index 2bd638f106979..314a62a5ae142 100644 --- a/Mathlib/Topology/Order.lean +++ b/Mathlib/Topology/Order.lean @@ -883,9 +883,8 @@ theorem isOpen_sSup_iff {s : Set α} {T : Set (TopologicalSpace α)} : IsOpen[sSup T] s ↔ ∀ t ∈ T, IsOpen[t] s := by simp only [sSup_eq_iSup, isOpen_iSup_iff] -set_option tactic.skipAssignedInstances false in theorem isClosed_iSup_iff {s : Set α} : IsClosed[⨆ i, t i] s ↔ ∀ i, IsClosed[t i] s := by - simp [← @isOpen_compl_iff _ _ (⨆ i, t i), ← @isOpen_compl_iff _ _ (t _), isOpen_iSup_iff] + simp only [← @isOpen_compl_iff _ _ (⨆ i, t i), ← @isOpen_compl_iff _ _ (t _), isOpen_iSup_iff] theorem isClosed_sSup_iff {s : Set α} {T : Set (TopologicalSpace α)} : IsClosed[sSup T] s ↔ ∀ t ∈ T, IsClosed[t] s := by From 323670133cd32f548556c8896a9ebf2ee87537b2 Mon Sep 17 00:00:00 2001 From: JovanGerb Date: Wed, 15 Jan 2025 17:38:06 +0000 Subject: [PATCH 250/681] chore: fix some slow maxHeartbeats and backwards compatibility flags (#20214) This PR fixes some `set_option maxHeartbeats` and all `set_option backwards._` situations. In these possible ways: - writing the proof in a better way - overwriting the default `aesop_cat` with a more efficient proof - simply removing an unnecessary set_option. This saves quite a bit of time. closes #12534 closes #12535 Co-authored-by: JovanGerb <56355248+JovanGerb@users.noreply.github.com> --- Mathlib/Algebra/Homology/DifferentialObject.lean | 3 ++- Mathlib/Algebra/Polynomial/BigOperators.lean | 8 +++++--- Mathlib/CategoryTheory/Action/Monoidal.lean | 1 - Mathlib/CategoryTheory/Functor/Flat.lean | 6 ++++-- Mathlib/CategoryTheory/Monoidal/Mod_.lean | 6 ++++-- Mathlib/CategoryTheory/Monoidal/Mon_.lean | 11 ++++++++--- Mathlib/CategoryTheory/Triangulated/Functor.lean | 2 ++ .../Geometry/RingedSpace/PresheafedSpace/Gluing.lean | 9 ++++----- Mathlib/Topology/Order/DenselyOrdered.lean | 8 ++++---- 9 files changed, 33 insertions(+), 21 deletions(-) diff --git a/Mathlib/Algebra/Homology/DifferentialObject.lean b/Mathlib/Algebra/Homology/DifferentialObject.lean index d1b9484894419..b83a6ba0c7334 100644 --- a/Mathlib/Algebra/Homology/DifferentialObject.lean +++ b/Mathlib/Algebra/Homology/DifferentialObject.lean @@ -69,7 +69,6 @@ theorem d_eqToHom (X : HomologicalComplex V (ComplexShape.up' b)) {x y z : β} ( X.d x y ≫ eqToHom (congr_arg X.X h) = X.d x z := by cases h; simp open Classical in -set_option maxHeartbeats 400000 in /-- The functor from differential graded objects to homological complexes. -/ @[simps] @@ -93,6 +92,8 @@ def dgoToHomologicalComplex : -- Porting note: this `rw` used to be part of the `simp`. have : f.f i ≫ Y.d i = X.d i ≫ f.f _ := (congr_fun f.comm i).symm rw [reassoc_of% this] } + map_id _ := rfl -- the `aesop_cat` autoparam solves this but it's slow + map_comp _ _ := rfl -- the `aesop_cat` autoparam solves this but it's slow /-- The functor from homological complexes to differential graded objects. -/ diff --git a/Mathlib/Algebra/Polynomial/BigOperators.lean b/Mathlib/Algebra/Polynomial/BigOperators.lean index c9bce4884d32b..d4b8759c80c9b 100644 --- a/Mathlib/Algebra/Polynomial/BigOperators.lean +++ b/Mathlib/Algebra/Polynomial/BigOperators.lean @@ -42,9 +42,11 @@ section Semiring variable {S : Type*} [Semiring S] -set_option backward.isDefEq.lazyProjDelta false in -- See https://github.com/leanprover-community/mathlib4/issues/12535 -theorem natDegree_list_sum_le (l : List S[X]) : natDegree l.sum ≤ (l.map natDegree).foldr max 0 := - List.sum_le_foldr_max natDegree (by simp) natDegree_add_le _ +theorem natDegree_list_sum_le (l : List S[X]) : + natDegree l.sum ≤ (l.map natDegree).foldr max 0 := by + apply List.sum_le_foldr_max natDegree + · simp + · exact natDegree_add_le theorem natDegree_multiset_sum_le (l : Multiset S[X]) : natDegree l.sum ≤ (l.map natDegree).foldr max 0 := diff --git a/Mathlib/CategoryTheory/Action/Monoidal.lean b/Mathlib/CategoryTheory/Action/Monoidal.lean index 98d9b5620c1a2..cc31bc6edd902 100644 --- a/Mathlib/CategoryTheory/Action/Monoidal.lean +++ b/Mathlib/CategoryTheory/Action/Monoidal.lean @@ -255,7 +255,6 @@ variable {W : Type (u + 1)} [LargeCategory W] [MonoidalCategory V] [MonoidalCate open Functor.LaxMonoidal Functor.OplaxMonoidal Functor.Monoidal -set_option maxHeartbeats 400000 in /-- A lax monoidal functor induces a lax monoidal functor between the categories of `G`-actions within those categories. -/ instance [F.LaxMonoidal] : (F.mapAction G).LaxMonoidal where diff --git a/Mathlib/CategoryTheory/Functor/Flat.lean b/Mathlib/CategoryTheory/Functor/Flat.lean index 981c2d3094209..c7ee840f6e83f 100644 --- a/Mathlib/CategoryTheory/Functor/Flat.lean +++ b/Mathlib/CategoryTheory/Functor/Flat.lean @@ -82,7 +82,9 @@ theorem RepresentablyFlat.id : RepresentablyFlat (𝟭 C) := inferInstance theorem RepresentablyCoflat.id : RepresentablyCoflat (𝟭 C) := inferInstance -set_option maxHeartbeats 400000 in +-- this slow simp lemma causes a maxHeartbeats exception +attribute [-simp] CostructuredArrow.right_eq_id in + instance RepresentablyFlat.comp (G : D ⥤ E) [RepresentablyFlat F] [RepresentablyFlat G] : RepresentablyFlat (F ⋙ G) := by refine ⟨fun X => IsCofiltered.of_cone_nonempty.{0} _ (fun {J} _ _ H => ?_)⟩ @@ -94,7 +96,7 @@ instance RepresentablyFlat.comp (G : D ⥤ E) [RepresentablyFlat F] obtain ⟨c₂⟩ := IsCofiltered.cone_nonempty H₂ simp only [H₂] at c₂ exact ⟨⟨StructuredArrow.mk (c₁.pt.hom ≫ G.map c₂.pt.hom), - ⟨fun j => StructuredArrow.homMk (c₂.π.app j).right (by simp [← G.map_comp, (c₂.π.app j).w]), + ⟨fun j => StructuredArrow.homMk (c₂.π.app j).right (by simp [← G.map_comp]), fun j j' f => by simpa using (c₂.w f).symm⟩⟩⟩ section diff --git a/Mathlib/CategoryTheory/Monoidal/Mod_.lean b/Mathlib/CategoryTheory/Monoidal/Mod_.lean index da996f019d255..cfb9163cb552c 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mod_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mod_.lean @@ -91,11 +91,11 @@ open CategoryTheory.MonoidalCategory #adaptation_note /-- After https://github.com/leanprover/lean4/pull/6053 -we needed to increase the `maxHeartbeats` limit. +we needed to increase the `maxHeartbeats` limit if we didn't write an explicit proof for +`map_id` and `map_comp`. This may indicate a configuration problem in Aesop. -/ -set_option maxHeartbeats 400000 in /-- A morphism of monoid objects induces a "restriction" or "comap" functor between the categories of module objects. -/ @@ -125,6 +125,8 @@ def comap {A B : Mon_ C} (f : A ⟶ B) : Mod_ B ⥤ Mod_ A where slice_rhs 1 2 => rw [whisker_exchange] slice_rhs 2 3 => rw [← g.act_hom] rw [Category.assoc] } + map_id _ := rfl -- the `aesop_cat` autoparam solves this but it's slow + map_comp _ _ := rfl -- the `aesop_cat` autoparam solves this but it's slow -- Lots more could be said about `comap`, e.g. how it interacts with -- identities, compositions, and equalities of monoid object morphisms. diff --git a/Mathlib/CategoryTheory/Monoidal/Mon_.lean b/Mathlib/CategoryTheory/Monoidal/Mon_.lean index cff040d32fd90..f87726f0ec820 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mon_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mon_.lean @@ -249,11 +249,11 @@ variable {C} {D : Type u₂} [Category.{v₂} D] [MonoidalCategory.{v₂} D] #adaptation_note /-- After https://github.com/leanprover/lean4/pull/6053 -we needed to increase the `maxHeartbeats` limit. +we needed to increase the `maxHeartbeats` limit if we didn't write an explicit proof for +`map_id` and `map_comp`. This may indicate a configuration problem in Aesop. -/ -set_option maxHeartbeats 400000 in -- TODO: mapMod F A : Mod A ⥤ Mod (F.mapMon A) /-- A lax monoidal functor takes monoid objects to monoid objects. @@ -284,6 +284,12 @@ def mapMon (F : C ⥤ D) [F.LaxMonoidal] : Mon_ C ⥤ Mon_ D where mul_hom := by rw [Category.assoc, μ_natural_assoc, ← F.map_comp, ← F.map_comp, f.mul_hom] } + map_id _ := by -- the `aesop_cat` autoparam solves this but it's slow + simp only [Mon_.id_hom', map_id] + rfl + map_comp _ _ := by -- the `aesop_cat` autoparam solves this but it's slow + simp only [Mon_.comp_hom', map_comp] + rfl variable (C D) @@ -337,7 +343,6 @@ def monToLaxMonoidal : Mon_ C ⥤ LaxMonoidalFunctor (Discrete PUnit.{u + 1}) C attribute [local aesop safe tactic (rule_sets := [CategoryTheory])] CategoryTheory.Discrete.discreteCases -set_option maxHeartbeats 400000 in /-- Implementation of `Mon_.equivLaxMonoidalFunctorPUnit`. -/ @[simps!] def unitIso : diff --git a/Mathlib/CategoryTheory/Triangulated/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Functor.lean index acc43ade04895..74a974651429f 100644 --- a/Mathlib/CategoryTheory/Triangulated/Functor.lean +++ b/Mathlib/CategoryTheory/Triangulated/Functor.lean @@ -96,6 +96,8 @@ set_option maxHeartbeats 400000 in noncomputable instance [∀ (n : ℤ), (shiftFunctor C n).Additive] [∀ (n : ℤ), (shiftFunctor D n).Additive] : (F.mapTriangle).CommShift ℤ where iso := F.mapTriangleCommShiftIso + zero := by ext <;> simp -- the `aesop_cat` autoparam solves this but it's slower + add _ _ := by ext <;> simp -- the `aesop_cat` autoparam solves this but it's slower /-- `F.mapTriangle` commutes with the rotation of triangles. -/ @[simps!] diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index b689c08051fcb..867c314932f6a 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -173,7 +173,6 @@ theorem f_invApp_f_app (i j k : D.J) (U : Opens (D.V (i, j)).carrier) : erw [(D.V (i, k)).presheaf.map_id] rfl -set_option backward.isDefEq.lazyWhnfCore false in -- See https://github.com/leanprover-community/mathlib4/issues/12534 /-- We can prove the `eq` along with the lemma. Thus this is bundled together here, and the lemma itself is separated below. -/ @@ -206,10 +205,11 @@ theorem snd_invApp_t_app' (i j k : D.J) (U : Opens (pullback (D.f i j) (D.f i k) · rw [← IsIso.eq_inv_comp, IsOpenImmersion.inv_invApp, Category.assoc, (D.t' k i j).c.naturality_assoc] simp_rw [← Category.assoc] - erw [← comp_c_app] - rw [congr_app (D.t_fac k i j), comp_c_app] + dsimp + rw [← comp_c_app, congr_app (D.t_fac k i j), comp_c_app] + dsimp simp_rw [Category.assoc] - erw [IsOpenImmersion.inv_naturality, IsOpenImmersion.inv_naturality_assoc, + rw [IsOpenImmersion.inv_naturality, IsOpenImmersion.inv_naturality_assoc, IsOpenImmersion.app_inv_app'_assoc] · simp_rw [← (𝖣.V (k, i)).presheaf.map_comp]; rfl rintro x ⟨y, -, eq⟩ @@ -222,7 +222,6 @@ theorem snd_invApp_t_app' (i j k : D.J) (U : Opens (pullback (D.f i j) (D.f i k) congr 2 rw [IsIso.inv_comp_eq, 𝖣.t_fac_assoc, 𝖣.t_inv, Category.comp_id] -set_option backward.isDefEq.lazyWhnfCore false in -- See https://github.com/leanprover-community/mathlib4/issues/12534 /-- The red and the blue arrows in ![this diagram](https://i.imgur.com/q6X1GJ9.png) commute. -/ @[simp, reassoc] theorem snd_invApp_t_app (i j k : D.J) (U : Opens (pullback (D.f i j) (D.f i k)).carrier) : diff --git a/Mathlib/Topology/Order/DenselyOrdered.lean b/Mathlib/Topology/Order/DenselyOrdered.lean index 957c94d57c1e0..c41975f3dc353 100644 --- a/Mathlib/Topology/Order/DenselyOrdered.lean +++ b/Mathlib/Topology/Order/DenselyOrdered.lean @@ -239,11 +239,11 @@ theorem comap_coe_nhdsLT_of_Ioo_subset (hb : s ⊆ Iio b) (hs : s.Nonempty → @[deprecated (since := "2024-12-22")] alias comap_coe_nhdsWithin_Iio_of_Ioo_subset := comap_coe_nhdsLT_of_Ioo_subset -set_option backward.isDefEq.lazyWhnfCore false in -- See https://github.com/leanprover-community/mathlib4/issues/12534 theorem comap_coe_nhdsGT_of_Ioo_subset (ha : s ⊆ Ioi a) (hs : s.Nonempty → ∃ b > a, Ioo a b ⊆ s) : - comap ((↑) : s → α) (𝓝[>] a) = atBot := - comap_coe_nhdsLT_of_Ioo_subset (show ofDual ⁻¹' s ⊆ Iio (toDual a) from ha) fun h => by - simpa only [OrderDual.exists, dual_Ioo] using hs h + comap ((↑) : s → α) (𝓝[>] a) = atBot := by + apply comap_coe_nhdsLT_of_Ioo_subset (show ofDual ⁻¹' s ⊆ Iio (toDual a) from ha) + simp only [OrderDual.exists, dual_Ioo] + exact hs @[deprecated (since := "2024-12-22")] alias comap_coe_nhdsWithin_Ioi_of_Ioo_subset := comap_coe_nhdsGT_of_Ioo_subset From 5dd62b3c05f836b174cf580599b819ec4b7f29fc Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Wed, 15 Jan 2025 18:22:30 +0000 Subject: [PATCH 251/681] feat(ModularForms/QExpansion): define q-expansions (#20720) We define the q-expansion of a modular form (either as a power series or as a `FormalMultlinearSeries`), show it has radius of convergence at least 1, and show that it converges to the original form on the open unit ball. --- .../Analysis/Complex/UpperHalfPlane/Exp.lean | 30 ++++-- .../NumberTheory/ModularForms/QExpansion.lean | 91 ++++++++++++++++--- 2 files changed, 100 insertions(+), 21 deletions(-) diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Exp.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Exp.lean index 2a3e793b66711..e4fc4c4e8a2a1 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Exp.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Exp.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ import Mathlib.Analysis.SpecialFunctions.Trigonometric.Basic +import Mathlib.Analysis.Complex.Periodic import Mathlib.Analysis.Complex.UpperHalfPlane.Basic /-! @@ -13,11 +14,28 @@ This file contains lemmas about the exponential function on the upper half plane q-expansions of modular forms. -/ -open Real Complex UpperHalfPlane +open Real Complex UpperHalfPlane Function -theorem UpperHalfPlane.abs_exp_two_pi_I_lt_one (z : ℍ) : - ‖(Complex.exp (2 * π * Complex.I * z))‖ < 1 := by - simp only [coe_I, Complex.norm_eq_abs, Complex.abs_exp, mul_re, re_ofNat, ofReal_re, im_ofNat, - ofReal_im, mul_zero, sub_zero, Complex.I_re, mul_im, zero_mul, add_zero, Complex.I_im, mul_one, - sub_self, coe_re, coe_im, zero_sub, exp_lt_one_iff, Left.neg_neg_iff] +local notation "𝕢" => Periodic.qParam + +theorem Function.Periodic.im_invQParam_pos_of_abs_lt_one + {h : ℝ} (hh : 0 < h) {q : ℂ} (hq : q.abs < 1) (hq_ne : q ≠ 0) : + 0 < im (Periodic.invQParam h q) := + im_invQParam .. ▸ mul_pos_of_neg_of_neg + (div_neg_of_neg_of_pos (neg_lt_zero.mpr hh) Real.two_pi_pos) + ((Real.log_neg_iff (abs.pos hq_ne)).mpr hq) + +lemma Function.Periodic.abs_qParam_le_of_one_half_le_im {ξ : ℂ} (hξ : 1 / 2 ≤ ξ.im) : + ‖𝕢 1 ξ‖ ≤ rexp (-π) := by + rwa [Periodic.qParam, ofReal_one, div_one, Complex.norm_eq_abs, Complex.abs_exp, Real.exp_le_exp, + mul_right_comm, mul_I_re, neg_le_neg_iff, ← ofReal_ofNat, ← ofReal_mul, im_ofReal_mul, + mul_comm _ π, mul_assoc, le_mul_iff_one_le_right Real.pi_pos, ← div_le_iff₀' two_pos] + +theorem UpperHalfPlane.abs_qParam_lt_one (n : ℕ) [NeZero n] (τ : ℍ) : (𝕢 n τ).abs < 1 := by + rw [Periodic.abs_qParam, Real.exp_lt_one_iff, neg_mul, coe_im, neg_mul, neg_div, neg_lt_zero, + div_pos_iff_of_pos_right (mod_cast Nat.pos_of_ne_zero <| NeZero.ne _)] positivity + +theorem UpperHalfPlane.abs_exp_two_pi_I_lt_one (τ : ℍ) : + ‖(Complex.exp (2 * π * Complex.I * τ))‖ < 1 := by + simpa [Function.Periodic.abs_qParam, Complex.abs_exp] using τ.abs_qParam_lt_one 1 diff --git a/Mathlib/NumberTheory/ModularForms/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/QExpansion.lean index c8512f5b76f7e..27d4e3389e4bb 100644 --- a/Mathlib/NumberTheory/ModularForms/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/QExpansion.lean @@ -3,9 +3,11 @@ 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.Analysis.Complex.Periodic +import Mathlib.Analysis.Complex.TaylorSeries +import Mathlib.Analysis.Complex.UpperHalfPlane.Exp import Mathlib.NumberTheory.ModularForms.Basic import Mathlib.NumberTheory.ModularForms.Identities +import Mathlib.RingTheory.PowerSeries.Basic /-! # q-expansions of modular forms @@ -14,10 +16,25 @@ We show that a modular form of level `Γ(n)` can be written as `τ ↦ F (𝕢 n analytic on the open unit disc, and `𝕢 n` is the parameter `τ ↦ exp (2 * I * π * τ / n)`. As an application, we show that cusp forms decay exponentially to 0 as `im τ → ∞`. +We also define the `q`-expansion of a modular form, either as a power series or as a +`FormalMultlinearSeries`, and show that it converges to `f` on the upper half plane. + +## Main definitions and results + +* `SlashInvariantFormClass.cuspFunction`: for a level `n` slash-invariant form, this is the function + `F` such that `f τ = F (exp (2 * π * I * τ / n))`, extended by a choice of limit at `0`. +* `ModularFormClass.differentiableAt_cuspFunction`: when `f` is a modular form, its `cuspFunction` + is differentiable on the open unit disc (including at `0`). +* `ModularFormClass.qExpansion`: the `q`-expansion of a modular form (defined as the Taylor series + of its `cuspFunction`), bundled as a `PowerSeries`. +* `ModularFormClass.hasSum_qExpansion`: the `q`-expansion evaluated at `𝕢 n τ` sums to `f τ`, for + `τ` in the upper half plane. + ## TO DO: * generalise to handle arbitrary finite-index subgroups (not just `Γ(n)` for some `n`) -* define the `q`-expansion as a formal power series +* define the `q`-expansion map on modular form spaces as a linear map (or even a ring hom from + the graded ring of all modular forms?) -/ open ModularForm Complex Filter UpperHalfPlane Function @@ -31,19 +48,6 @@ variable {k : ℤ} {F : Type*} [FunLike F ℍ ℂ] {Γ : Subgroup SL(2, ℤ)} (n local notation "I∞" => comap Complex.im atTop local notation "𝕢" => Periodic.qParam -theorem Function.Periodic.im_invQParam_pos_of_abs_lt_one - {h : ℝ} (hh : 0 < h) {q : ℂ} (hq : q.abs < 1) (hq_ne : q ≠ 0) : - 0 < im (Periodic.invQParam h q) := - im_invQParam .. ▸ mul_pos_of_neg_of_neg - (div_neg_of_neg_of_pos (neg_lt_zero.mpr hh) Real.two_pi_pos) - ((Real.log_neg_iff (abs.pos hq_ne)).mpr hq) - -lemma Function.Periodic.abs_qParam_le_of_one_half_le_im {ξ : ℂ} (hξ : 1 / 2 ≤ ξ.im) : - ‖𝕢 1 ξ‖ ≤ rexp (-π) := by - rwa [Periodic.qParam, ofReal_one, div_one, norm_eq_abs, abs_exp, Real.exp_le_exp, - mul_right_comm, mul_I_re, neg_le_neg_iff, ← ofReal_ofNat, ← ofReal_mul, im_ofReal_mul, - mul_comm _ π, mul_assoc, le_mul_iff_one_le_right Real.pi_pos, ← div_le_iff₀' two_pos] - namespace SlashInvariantFormClass theorem periodic_comp_ofComplex [SlashInvariantFormClass F Γ(n) k] : @@ -104,6 +108,63 @@ lemma analyticAt_cuspFunction_zero [NeZero n] [ModularFormClass F Γ(n) k] : (fun q hq ↦ (differentiableAt_cuspFunction _ _ hq).differentiableWithinAt) (by simpa only [ball_zero_eq] using Metric.ball_mem_nhds (0 : ℂ) zero_lt_one) +/-- The `q`-expansion of a level `n` modular form, bundled as a `PowerSeries`. -/ +def qExpansion : PowerSeries ℂ := + .mk fun m ↦ (↑m.factorial)⁻¹ * iteratedDeriv m (cuspFunction n f) 0 + +lemma qExpansion_coeff (m : ℕ) : + (qExpansion n f).coeff ℂ m = (↑m.factorial)⁻¹ * iteratedDeriv m (cuspFunction n f) 0 := by + simp [qExpansion] + +lemma hasSum_qExpansion_of_abs_lt [NeZero n] [ModularFormClass F Γ(n) k] + {q : ℂ} (hq : q.abs < 1) : + HasSum (fun m : ℕ ↦ (qExpansion n f).coeff ℂ m • q ^ m) (cuspFunction n f q) := by + simp only [qExpansion_coeff, ← eq_cuspFunction n f] + have hdiff : DifferentiableOn ℂ (cuspFunction n f) (Metric.ball 0 1) := by + refine fun z hz ↦ (differentiableAt_cuspFunction n f ?_).differentiableWithinAt + simpa using hz + have qmem : q ∈ Metric.ball 0 1 := by simpa using hq + convert hasSum_taylorSeries_on_ball hdiff qmem using 2 with m + rw [sub_zero, smul_eq_mul, smul_eq_mul, mul_right_comm, smul_eq_mul, mul_assoc] + +lemma hasSum_qExpansion [NeZero n] [ModularFormClass F Γ(n) k] (τ : ℍ) : + HasSum (fun m : ℕ ↦ (qExpansion n f).coeff ℂ m • 𝕢 n τ ^ m) (f τ) := by + simpa only [eq_cuspFunction n f] using + hasSum_qExpansion_of_abs_lt n f (τ.abs_qParam_lt_one n) + +/-- +The `q`-expansion of a level `n` modular form, bundled as a `FormalMultilinearSeries`. + +TODO: Maybe get rid of this and instead define a general API for converting `PowerSeries` to +`FormalMultlinearSeries`. +-/ +def qExpansionFormalMultilinearSeries : FormalMultilinearSeries ℂ ℂ ℂ := + fun m ↦ (qExpansion n f).coeff ℂ m • ContinuousMultilinearMap.mkPiAlgebraFin ℂ m _ + +lemma qExpansionFormalMultilinearSeries_apply_norm (m : ℕ) : + ‖qExpansionFormalMultilinearSeries n f m‖ = ‖(qExpansion n f).coeff ℂ m‖ := by + rw [qExpansionFormalMultilinearSeries, + ← (ContinuousMultilinearMap.piFieldEquiv ℂ (Fin m) ℂ).symm.norm_map] + simp + +lemma qExpansionFormalMultilinearSeries_radius [NeZero n] [ModularFormClass F Γ(n) k] : + 1 ≤ (qExpansionFormalMultilinearSeries n f).radius := by + refine le_of_forall_ge_of_dense fun r hr ↦ ?_ + lift r to NNReal using hr.ne_top + apply FormalMultilinearSeries.le_radius_of_summable + simp only [qExpansionFormalMultilinearSeries_apply_norm] + rw [← r.abs_eq] + simp_rw [pow_abs, ← Complex.abs_ofReal, ofReal_pow, ← Complex.norm_eq_abs, ← norm_mul] + exact (hasSum_qExpansion_of_abs_lt n f (q := r) (by simpa using hr)).summable.norm + +/-- The `q`-expansion of `f` is an `FPowerSeries` representing `cuspFunction n f`. -/ +lemma hasFPowerSeries_cuspFunction [NeZero n] [ModularFormClass F Γ(n) k] : + HasFPowerSeriesOnBall (cuspFunction n f) (qExpansionFormalMultilinearSeries n f) 0 1 := by + refine ⟨qExpansionFormalMultilinearSeries_radius n f, zero_lt_one, fun hy ↦ ?_⟩ + rw [EMetric.mem_ball, edist_zero_right, ENNReal.coe_lt_one_iff, ← NNReal.coe_lt_one, + coe_nnnorm, norm_eq_abs] at hy + simpa [qExpansionFormalMultilinearSeries] using hasSum_qExpansion_of_abs_lt n f hy + end ModularFormClass open ModularFormClass From 42d20c7e189b75899f0a7b560539af852f42c841 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Wed, 15 Jan 2025 21:51:10 +0000 Subject: [PATCH 252/681] chore(Algebra/Group/Equiv): split into `Defs` and `Basic` (#20712) While looking at the import graph for `Mathlib.Data.NNRat.Defs`, I noticed that there isn't a `Defs` file for group equivs, while there is one for linear equivs. With this PR, the design of `Algebra/Group/Equiv` matches `Algebra/Module/Equiv` better. --- Mathlib.lean | 1 + Mathlib/Algebra/Category/Semigrp/Basic.lean | 2 +- Mathlib/Algebra/Free.lean | 3 +- Mathlib/Algebra/Group/Equiv/Basic.lean | 531 +--------------- Mathlib/Algebra/Group/Equiv/Defs.lean | 579 ++++++++++++++++++ Mathlib/Algebra/Group/Pi/Units.lean | 2 +- Mathlib/Algebra/Group/ULift.lean | 2 +- Mathlib/Algebra/Group/WithOne/Basic.lean | 3 +- Mathlib/Algebra/GroupWithZero/Action/End.lean | 2 +- Mathlib/Algebra/GroupWithZero/Hom.lean | 3 +- Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean | 2 +- Mathlib/CategoryTheory/Endomorphism.lean | 2 +- .../CategoryTheory/Groupoid/VertexGroup.lean | 3 +- Mathlib/Deprecated/Group.lean | 1 - 14 files changed, 596 insertions(+), 540 deletions(-) create mode 100644 Mathlib/Algebra/Group/Equiv/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index c470c177b5d38..331c6efcb0ded 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -282,6 +282,7 @@ import Mathlib.Algebra.Group.ConjFinite import Mathlib.Algebra.Group.Defs import Mathlib.Algebra.Group.Embedding import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.Group.Equiv.TypeTags import Mathlib.Algebra.Group.Even import Mathlib.Algebra.Group.EvenFunction diff --git a/Mathlib/Algebra/Category/Semigrp/Basic.lean b/Mathlib/Algebra/Category/Semigrp/Basic.lean index e6e54e5ccab88..ebcbd7a5584d3 100644 --- a/Mathlib/Algebra/Category/Semigrp/Basic.lean +++ b/Mathlib/Algebra/Category/Semigrp/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Julian Kuelshammer -/ import Mathlib.Algebra.PEmptyInstances -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.CategoryTheory.ConcreteCategory.BundledHom import Mathlib.CategoryTheory.Functor.ReflectsIso diff --git a/Mathlib/Algebra/Free.lean b/Mathlib/Algebra/Free.lean index 3d33bcd02d818..50961c7a71981 100644 --- a/Mathlib/Algebra/Free.lean +++ b/Mathlib/Algebra/Free.lean @@ -3,7 +3,8 @@ Copyright (c) 2019 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Control.Applicative import Mathlib.Control.Traversable.Basic import Mathlib.Logic.Equiv.Defs diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index bde39ac2fdd19..3ebc376b4f162 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -3,6 +3,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, Callum Sutton, Yury Kudryashov -/ +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.Group.Hom.Basic import Mathlib.Data.FunLike.Equiv import Mathlib.Logic.Equiv.Basic @@ -10,16 +11,7 @@ import Mathlib.Logic.Equiv.Basic /-! # Multiplicative and additive equivs -In this file we define two extensions of `Equiv` called `AddEquiv` and `MulEquiv`, which are -datatypes representing isomorphisms of `AddMonoid`s/`AddGroup`s and `Monoid`s/`Group`s. - -## Notations - -* ``infix ` ≃* `:25 := MulEquiv`` -* ``infix ` ≃+ `:25 := AddEquiv`` - -The extended equivs all have coercions to functions, and the coercions are the canonical -notation when treating the isomorphisms as maps. +This file contains basic results on `MulEquiv` and `AddEquiv`. ## Tags @@ -33,130 +25,10 @@ variable {F α β M N P G H : Type*} namespace EmbeddingLike variable [One M] [One N] [FunLike F M N] [EmbeddingLike F M N] [OneHomClass F M N] -@[to_additive (attr := simp)] -theorem map_eq_one_iff {f : F} {x : M} : - f x = 1 ↔ x = 1 := - _root_.map_eq_one_iff f (EmbeddingLike.injective f) - -@[to_additive] -theorem map_ne_one_iff {f : F} {x : M} : - f x ≠ 1 ↔ x ≠ 1 := - map_eq_one_iff.not - end EmbeddingLike -/-- `AddEquiv α β` is the type of an equiv `α ≃ β` which preserves addition. -/ -structure AddEquiv (A B : Type*) [Add A] [Add B] extends A ≃ B, AddHom A B - -/-- `AddEquivClass F A B` states that `F` is a type of addition-preserving morphisms. -You should extend this class when you extend `AddEquiv`. -/ -class AddEquivClass (F : Type*) (A B : outParam Type*) [Add A] [Add B] [EquivLike F A B] : - Prop where - /-- Preserves addition. -/ - map_add : ∀ (f : F) (a b), f (a + b) = f a + f b - -/-- The `Equiv` underlying an `AddEquiv`. -/ -add_decl_doc AddEquiv.toEquiv - -/-- The `AddHom` underlying an `AddEquiv`. -/ -add_decl_doc AddEquiv.toAddHom - -/-- `MulEquiv α β` is the type of an equiv `α ≃ β` which preserves multiplication. -/ -@[to_additive] -structure MulEquiv (M N : Type*) [Mul M] [Mul N] extends M ≃ N, M →ₙ* N - -/-- The `Equiv` underlying a `MulEquiv`. -/ -add_decl_doc MulEquiv.toEquiv - -/-- The `MulHom` underlying a `MulEquiv`. -/ -add_decl_doc MulEquiv.toMulHom - -/-- Notation for a `MulEquiv`. -/ -infixl:25 " ≃* " => MulEquiv - -/-- Notation for an `AddEquiv`. -/ -infixl:25 " ≃+ " => AddEquiv - -@[to_additive] -lemma MulEquiv.toEquiv_injective {α β : Type*} [Mul α] [Mul β] : - Function.Injective (toEquiv : (α ≃* β) → (α ≃ β)) - | ⟨_, _⟩, ⟨_, _⟩, rfl => rfl - -/-- `MulEquivClass F A B` states that `F` is a type of multiplication-preserving morphisms. -You should extend this class when you extend `MulEquiv`. -/ --- TODO: make this a synonym for MulHomClass? -@[to_additive] -class MulEquivClass (F : Type*) (A B : outParam Type*) [Mul A] [Mul B] [EquivLike F A B] : - Prop where - /-- Preserves multiplication. -/ - map_mul : ∀ (f : F) (a b), f (a * b) = f a * f b - -@[to_additive] -alias MulEquivClass.map_eq_one_iff := EmbeddingLike.map_eq_one_iff - --- `alias` doesn't add the deprecation suggestion to the `to_additive` version --- see https://github.com/leanprover-community/mathlib4/issues/19424 -attribute [deprecated EmbeddingLike.map_eq_one_iff (since := "2024-11-10")] -MulEquivClass.map_eq_one_iff -attribute [deprecated EmbeddingLike.map_eq_zero_iff (since := "2024-11-10")] -AddEquivClass.map_eq_zero_iff - - -@[to_additive] -alias MulEquivClass.map_ne_one_iff := EmbeddingLike.map_ne_one_iff - --- `alias` doesn't add the deprecation suggestion to the `to_additive` version --- see https://github.com/leanprover-community/mathlib4/issues/19424 -attribute [deprecated EmbeddingLike.map_ne_one_iff (since := "2024-11-10")] -MulEquivClass.map_ne_one_iff -attribute [deprecated EmbeddingLike.map_ne_zero_iff (since := "2024-11-10")] -AddEquivClass.map_ne_zero_iff - - -namespace MulEquivClass - -variable (F) -variable [EquivLike F M N] - --- See note [lower instance priority] -@[to_additive] -instance (priority := 100) instMulHomClass (F : Type*) - [Mul M] [Mul N] [EquivLike F M N] [h : MulEquivClass F M N] : MulHomClass F M N := - { h with } - --- See note [lower instance priority] -@[to_additive] -instance (priority := 100) instMonoidHomClass - [MulOneClass M] [MulOneClass N] [MulEquivClass F M N] : - MonoidHomClass F M N := - { MulEquivClass.instMulHomClass F with - map_one := fun e => - calc - e 1 = e 1 * 1 := (mul_one _).symm - _ = e 1 * e (EquivLike.inv e (1 : N) : M) := - congr_arg _ (EquivLike.right_inv e 1).symm - _ = e (EquivLike.inv e (1 : N)) := by rw [← map_mul, one_mul] - _ = 1 := EquivLike.right_inv e 1 } - -end MulEquivClass - variable [EquivLike F α β] -/-- Turn an element of a type `F` satisfying `MulEquivClass F α β` into an actual -`MulEquiv`. This is declared as the default coercion from `F` to `α ≃* β`. -/ -@[to_additive (attr := coe) -"Turn an element of a type `F` satisfying `AddEquivClass F α β` into an actual -`AddEquiv`. This is declared as the default coercion from `F` to `α ≃+ β`."] -def MulEquivClass.toMulEquiv [Mul α] [Mul β] [MulEquivClass F α β] (f : F) : α ≃* β := - { (f : α ≃ β), (f : α →ₙ* β) with } - -/-- Any type satisfying `MulEquivClass` can be cast into `MulEquiv` via -`MulEquivClass.toMulEquiv`. -/ -@[to_additive "Any type satisfying `AddEquivClass` can be cast into `AddEquiv` via -`AddEquivClass.toAddEquiv`. "] -instance [Mul α] [Mul β] [MulEquivClass F α β] : CoeTC F (α ≃* β) := - ⟨MulEquivClass.toMulEquiv⟩ - @[to_additive] theorem MulEquivClass.toMulEquiv_injective [Mul α] [Mul β] [MulEquivClass F α β] : Function.Injective ((↑) : F → α ≃* β) := @@ -166,280 +38,6 @@ namespace MulEquiv section Mul variable [Mul M] [Mul N] [Mul P] -section coe - -@[to_additive] -instance : EquivLike (M ≃* N) M N where - coe f := f.toFun - inv f := f.invFun - left_inv f := f.left_inv - right_inv f := f.right_inv - coe_injective' f g h₁ h₂ := by - cases f - cases g - congr - apply Equiv.coe_fn_injective h₁ - -@[to_additive] -- shortcut instance that doesn't generate any subgoals -instance : CoeFun (M ≃* N) fun _ ↦ M → N where - coe f := f - -@[to_additive] -instance : MulEquivClass (M ≃* N) M N where - map_mul f := f.map_mul' - -/-- Two multiplicative isomorphisms agree if they are defined by the -same underlying function. -/ -@[to_additive (attr := ext) - "Two additive isomorphisms agree if they are defined by the same underlying function."] -theorem ext {f g : MulEquiv M N} (h : ∀ x, f x = g x) : f = g := - DFunLike.ext f g h - -@[to_additive] -protected theorem congr_arg {f : MulEquiv M N} {x x' : M} : x = x' → f x = f x' := - DFunLike.congr_arg f - -@[to_additive] -protected theorem congr_fun {f g : MulEquiv M N} (h : f = g) (x : M) : f x = g x := - DFunLike.congr_fun h x - -@[to_additive (attr := simp)] -theorem coe_mk (f : M ≃ N) (hf : ∀ x y, f (x * y) = f x * f y) : (mk f hf : M → N) = f := rfl - -@[to_additive (attr := simp)] -theorem mk_coe (e : M ≃* N) (e' h₁ h₂ h₃) : (⟨⟨e, e', h₁, h₂⟩, h₃⟩ : M ≃* N) = e := - ext fun _ => rfl - -@[to_additive (attr := simp)] -theorem toEquiv_eq_coe (f : M ≃* N) : f.toEquiv = f := - rfl - -/-- The `simp`-normal form to turn something into a `MulHom` is via `MulHomClass.toMulHom`. -/ -@[to_additive (attr := simp)] -theorem toMulHom_eq_coe (f : M ≃* N) : f.toMulHom = ↑f := - rfl - -@[to_additive] -theorem toFun_eq_coe (f : M ≃* N) : f.toFun = f := rfl - -/-- `simp`-normal form of `toFun_eq_coe`. -/ -@[to_additive (attr := simp)] -theorem coe_toEquiv (f : M ≃* N) : ⇑(f : M ≃ N) = f := rfl - -@[to_additive (attr := simp)] -theorem coe_toMulHom {f : M ≃* N} : (f.toMulHom : M → N) = f := rfl - -/-- Makes a multiplicative isomorphism from a bijection which preserves multiplication. -/ -@[to_additive "Makes an additive isomorphism from a bijection which preserves addition."] -def mk' (f : M ≃ N) (h : ∀ x y, f (x * y) = f x * f y) : M ≃* N := ⟨f, h⟩ - -end coe - -section map - -/-- A multiplicative isomorphism preserves multiplication. -/ -@[to_additive "An additive isomorphism preserves addition."] -protected theorem map_mul (f : M ≃* N) : ∀ x y, f (x * y) = f x * f y := - map_mul f - -attribute [deprecated map_mul (since := "2024-08-08")] MulEquiv.map_mul -attribute [deprecated map_add (since := "2024-08-08")] AddEquiv.map_add - -end map - -section bijective - -@[to_additive] -protected theorem bijective (e : M ≃* N) : Function.Bijective e := - EquivLike.bijective e - -@[to_additive] -protected theorem injective (e : M ≃* N) : Function.Injective e := - EquivLike.injective e - -@[to_additive] -protected theorem surjective (e : M ≃* N) : Function.Surjective e := - EquivLike.surjective e - -@[to_additive] -theorem apply_eq_iff_eq (e : M ≃* N) {x y : M} : e x = e y ↔ x = y := - e.injective.eq_iff - -end bijective - -section refl - -/-- The identity map is a multiplicative isomorphism. -/ -@[to_additive (attr := refl) "The identity map is an additive isomorphism."] -def refl (M : Type*) [Mul M] : M ≃* M := - { Equiv.refl _ with map_mul' := fun _ _ => rfl } - -@[to_additive] -instance : Inhabited (M ≃* M) := ⟨refl M⟩ - -@[to_additive (attr := simp)] -theorem coe_refl : ↑(refl M) = id := rfl - -@[to_additive (attr := simp)] -theorem refl_apply (m : M) : refl M m = m := rfl - -end refl - -section symm - -/-- An alias for `h.symm.map_mul`. Introduced to fix the issue in -https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/!4.234183.20.60simps.60.20maximum.20recursion.20depth --/ -@[to_additive] -lemma symm_map_mul {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) (x y : N) : - h.symm (x * y) = h.symm x * h.symm y := - map_mul (h.toMulHom.inverse h.toEquiv.symm h.left_inv h.right_inv) x y - -/-- The inverse of an isomorphism is an isomorphism. -/ -@[to_additive (attr := symm) "The inverse of an isomorphism is an isomorphism."] -def symm {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) : N ≃* M := - ⟨h.toEquiv.symm, h.symm_map_mul⟩ - -@[to_additive] -theorem invFun_eq_symm {f : M ≃* N} : f.invFun = f.symm := rfl - -/-- `simp`-normal form of `invFun_eq_symm`. -/ -@[to_additive (attr := simp)] -theorem coe_toEquiv_symm (f : M ≃* N) : ((f : M ≃ N).symm : N → M) = f.symm := rfl - -@[to_additive (attr := simp)] -theorem equivLike_inv_eq_symm (f : M ≃* N) : EquivLike.inv f = f.symm := rfl - -@[to_additive (attr := simp)] -theorem toEquiv_symm (f : M ≃* N) : (f.symm : N ≃ M) = (f : M ≃ N).symm := rfl - -@[to_additive (attr := simp)] -theorem symm_symm (f : M ≃* N) : f.symm.symm = f := rfl - -@[to_additive] -theorem symm_bijective : Function.Bijective (symm : (M ≃* N) → N ≃* M) := - Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ - -@[to_additive (attr := simp)] -theorem mk_coe' (e : M ≃* N) (f h₁ h₂ h₃) : (MulEquiv.mk ⟨f, e, h₁, h₂⟩ h₃ : N ≃* M) = e.symm := - symm_bijective.injective <| ext fun _ => rfl - -@[to_additive (attr := simp)] -theorem symm_mk (f : M ≃ N) (h) : - (MulEquiv.mk f h).symm = ⟨f.symm, (MulEquiv.mk f h).symm_map_mul⟩ := rfl - -@[to_additive (attr := simp)] -theorem refl_symm : (refl M).symm = refl M := rfl - -/-- `e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`. -/ -@[to_additive (attr := simp) "`e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`."] -theorem apply_symm_apply (e : M ≃* N) (y : N) : e (e.symm y) = y := - e.toEquiv.apply_symm_apply y - -/-- `e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`. -/ -@[to_additive (attr := simp) "`e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`."] -theorem symm_apply_apply (e : M ≃* N) (x : M) : e.symm (e x) = x := - e.toEquiv.symm_apply_apply x - -@[to_additive (attr := simp)] -theorem symm_comp_self (e : M ≃* N) : e.symm ∘ e = id := - funext e.symm_apply_apply - -@[to_additive (attr := simp)] -theorem self_comp_symm (e : M ≃* N) : e ∘ e.symm = id := - funext e.apply_symm_apply - -@[to_additive] -theorem apply_eq_iff_symm_apply (e : M ≃* N) {x : M} {y : N} : e x = y ↔ x = e.symm y := - e.toEquiv.apply_eq_iff_eq_symm_apply - -@[to_additive] -theorem symm_apply_eq (e : M ≃* N) {x y} : e.symm x = y ↔ x = e y := - e.toEquiv.symm_apply_eq - -@[to_additive] -theorem eq_symm_apply (e : M ≃* N) {x y} : y = e.symm x ↔ e y = x := - e.toEquiv.eq_symm_apply - -@[to_additive] -theorem eq_comp_symm {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) : - f = g ∘ e.symm ↔ f ∘ e = g := - e.toEquiv.eq_comp_symm f g - -@[to_additive] -theorem comp_symm_eq {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) : - g ∘ e.symm = f ↔ g = f ∘ e := - e.toEquiv.comp_symm_eq f g - -@[to_additive] -theorem eq_symm_comp {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) : - f = e.symm ∘ g ↔ e ∘ f = g := - e.toEquiv.eq_symm_comp f g - -@[to_additive] -theorem symm_comp_eq {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) : - e.symm ∘ g = f ↔ g = e ∘ f := - e.toEquiv.symm_comp_eq f g - -@[to_additive (attr := simp)] -theorem _root_.MulEquivClass.apply_coe_symm_apply {α β} [Mul α] [Mul β] {F} [EquivLike F α β] - [MulEquivClass F α β] (e : F) (x : β) : - e ((e : α ≃* β).symm x) = x := - (e : α ≃* β).right_inv x - -@[to_additive (attr := simp)] -theorem _root_.MulEquivClass.coe_symm_apply_apply {α β} [Mul α] [Mul β] {F} [EquivLike F α β] - [MulEquivClass F α β] (e : F) (x : α) : - (e : α ≃* β).symm (e x) = x := - (e : α ≃* β).left_inv x - -end symm - -section simps - --- we don't hyperlink the note in the additive version, since that breaks syntax highlighting --- in the whole file. - -/-- See Note [custom simps projection] -/ -@[to_additive "See Note [custom simps projection]"] -- this comment fixes the syntax highlighting " -def Simps.symm_apply (e : M ≃* N) : N → M := - e.symm - -initialize_simps_projections AddEquiv (toFun → apply, invFun → symm_apply) - -initialize_simps_projections MulEquiv (toFun → apply, invFun → symm_apply) - -end simps - -section trans - -/-- Transitivity of multiplication-preserving isomorphisms -/ -@[to_additive (attr := trans) "Transitivity of addition-preserving isomorphisms"] -def trans (h1 : M ≃* N) (h2 : N ≃* P) : M ≃* P := - { h1.toEquiv.trans h2.toEquiv with - map_mul' := fun x y => show h2 (h1 (x * y)) = h2 (h1 x) * h2 (h1 y) by - rw [map_mul, map_mul] } - -@[to_additive (attr := simp)] -theorem coe_trans (e₁ : M ≃* N) (e₂ : N ≃* P) : ↑(e₁.trans e₂) = e₂ ∘ e₁ := rfl - -@[to_additive (attr := simp)] -theorem trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (m : M) : e₁.trans e₂ m = e₂ (e₁ m) := rfl - -@[to_additive (attr := simp)] -theorem symm_trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (p : P) : - (e₁.trans e₂).symm p = e₁.symm (e₂.symm p) := rfl - -@[to_additive (attr := simp)] -theorem symm_trans_self (e : M ≃* N) : e.symm.trans e = refl N := - DFunLike.ext _ _ e.apply_symm_apply - -@[to_additive (attr := simp)] -theorem self_trans_symm (e : M ≃* N) : e.trans e.symm = refl M := - DFunLike.ext _ _ e.symm_apply_apply - -end trans - section unique /-- The `MulEquiv` between two monoids with a unique element. -/ @@ -468,82 +66,6 @@ end Mul ## Monoids -/ -section MulOneClass -variable [MulOneClass M] [MulOneClass N] [MulOneClass P] - --- Porting note (https://github.com/leanprover-community/mathlib4/issues/10618): `simp` can prove this but it is a valid `dsimp` lemma. --- However, we would need to redesign the the `dsimp` set to make this `@[simp]`. -@[to_additive] -theorem coe_monoidHom_refl : (refl M : M →* M) = MonoidHom.id M := rfl - --- Porting note (https://github.com/leanprover-community/mathlib4/issues/10618): `simp` can prove this but it is a valid `dsimp` lemma. --- However, we would need to redesign the the `dsimp` set to make this `@[simp]`. -@[to_additive] -lemma coe_monoidHom_trans (e₁ : M ≃* N) (e₂ : N ≃* P) : - (e₁.trans e₂ : M →* P) = (e₂ : N →* P).comp ↑e₁ := rfl - -@[to_additive (attr := simp)] -lemma coe_monoidHom_comp_coe_monoidHom_symm (e : M ≃* N) : - (e : M →* N).comp e.symm = MonoidHom.id _ := by ext; simp - -@[to_additive (attr := simp)] -lemma coe_monoidHom_symm_comp_coe_monoidHom (e : M ≃* N) : - (e.symm : N →* M).comp e = MonoidHom.id _ := by ext; simp - -@[to_additive] -lemma comp_left_injective (e : M ≃* N) : Injective fun f : N →* P ↦ f.comp (e : M →* N) := - LeftInverse.injective (g := fun f ↦ f.comp e.symm) fun f ↦ by simp [MonoidHom.comp_assoc] - -@[to_additive] -lemma comp_right_injective (e : M ≃* N) : Injective fun f : P →* M ↦ (e : M →* N).comp f := - LeftInverse.injective (g := (e.symm : N →* M).comp) fun f ↦ by simp [← MonoidHom.comp_assoc] - -/-- A multiplicative isomorphism of monoids sends `1` to `1` (and is hence a monoid isomorphism). -/ -@[to_additive - "An additive isomorphism of additive monoids sends `0` to `0` - (and is hence an additive monoid isomorphism)."] -protected theorem map_one (h : M ≃* N) : h 1 = 1 := map_one h - -@[to_additive] -protected theorem map_eq_one_iff (h : M ≃* N) {x : M} : h x = 1 ↔ x = 1 := - EmbeddingLike.map_eq_one_iff - -@[to_additive] -theorem map_ne_one_iff (h : M ≃* N) {x : M} : h x ≠ 1 ↔ x ≠ 1 := - EmbeddingLike.map_ne_one_iff - -/-- A bijective `Semigroup` homomorphism is an isomorphism -/ -@[to_additive (attr := simps! apply) "A bijective `AddSemigroup` homomorphism is an isomorphism"] -noncomputable def ofBijective {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N] - (f : F) (hf : Bijective f) : M ≃* N := - { Equiv.ofBijective f hf with map_mul' := map_mul f } - --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: simplify `symm_apply` to `surjInv`? -@[to_additive (attr := simp)] -theorem ofBijective_apply_symm_apply {n : N} (f : M →* N) (hf : Bijective f) : - f ((ofBijective f hf).symm n) = n := (ofBijective f hf).apply_symm_apply n - -/-- Extract the forward direction of a multiplicative equivalence -as a multiplication-preserving function. --/ -@[to_additive "Extract the forward direction of an additive equivalence - as an addition-preserving function."] -def toMonoidHom (h : M ≃* N) : M →* N := - { h with map_one' := h.map_one } - -@[to_additive (attr := simp)] -theorem coe_toMonoidHom (e : M ≃* N) : ⇑e.toMonoidHom = e := rfl - -@[to_additive (attr := simp)] -theorem toMonoidHom_eq_coe (f : M ≃* N) : f.toMonoidHom = (f : M →* N) := - rfl - -@[to_additive] -theorem toMonoidHom_injective : Injective (toMonoidHom : M ≃* N → M →* N) := - Injective.of_comp (f := DFunLike.coe) DFunLike.coe_injective - -end MulOneClass - /-- A multiplicative analogue of `Equiv.arrowCongr`, where the equivalence between the targets is multiplicative. -/ @@ -612,22 +134,6 @@ def piUnique {ι : Type*} (M : ι → Type*) [∀ j, Mul (M j)] [Unique ι] : (∀ j, M j) ≃* M default := { Equiv.piUnique M with map_mul' := fun _ _ => Pi.mul_apply _ _ _ } -/-! -# Groups --/ - -/-- A multiplicative equivalence of groups preserves inversion. -/ -@[to_additive "An additive equivalence of additive groups preserves negation."] -protected theorem map_inv [Group G] [DivisionMonoid H] (h : G ≃* H) (x : G) : - h x⁻¹ = (h x)⁻¹ := - map_inv h x - -/-- A multiplicative equivalence of groups preserves division. -/ -@[to_additive "An additive equivalence of additive groups preserves subtractions."] -protected theorem map_div [Group G] [DivisionMonoid H] (h : G ≃* H) (x y : G) : - h (x / y) = h x / h y := - map_div h x y - end MulEquiv namespace MonoidHom @@ -658,39 +164,6 @@ def postcompEquiv {α β : Type*} [Monoid α] [Monoid β] (e : α ≃* β) (γ : end MonoidHom -/-- Given a pair of multiplicative homomorphisms `f`, `g` such that `g.comp f = id` and -`f.comp g = id`, returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This -constructor is useful if the underlying type(s) have specialized `ext` lemmas for multiplicative -homomorphisms. -/ -@[to_additive (attr := simps (config := .asFn)) - "Given a pair of additive homomorphisms `f`, `g` such that `g.comp f = id` and - `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`. This - constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive - homomorphisms."] -def MulHom.toMulEquiv [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) (h₁ : g.comp f = MulHom.id _) - (h₂ : f.comp g = MulHom.id _) : M ≃* N where - toFun := f - invFun := g - left_inv := DFunLike.congr_fun h₁ - right_inv := DFunLike.congr_fun h₂ - map_mul' := f.map_mul - -/-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`, -returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This constructor is -useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/ -@[to_additive (attr := simps (config := .asFn)) - "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id` - and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`. This - constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive - monoid homomorphisms."] -def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M) - (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N where - toFun := f - invFun := g - left_inv := DFunLike.congr_fun h₁ - right_inv := DFunLike.congr_fun h₂ - map_mul' := f.map_mul - namespace Equiv section InvolutiveInv diff --git a/Mathlib/Algebra/Group/Equiv/Defs.lean b/Mathlib/Algebra/Group/Equiv/Defs.lean new file mode 100644 index 0000000000000..fa555f0f0f70c --- /dev/null +++ b/Mathlib/Algebra/Group/Equiv/Defs.lean @@ -0,0 +1,579 @@ +/- +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, Callum Sutton, Yury Kudryashov +-/ +import Mathlib.Algebra.Group.Hom.Defs +import Mathlib.Data.FunLike.Equiv +import Mathlib.Logic.Equiv.Defs + +/-! +# Multiplicative and additive equivs + +In this file we define two extensions of `Equiv` called `AddEquiv` and `MulEquiv`, which are +datatypes representing isomorphisms of `AddMonoid`s/`AddGroup`s and `Monoid`s/`Group`s. + +## Main definitions +* `≃*` (`MulEquiv`), `≃+` (`AddEquiv`): bundled equivalences that preserve multiplication/addition + (and are therefore monoid and group isomorphisms). +* `MulEquivClass`, `AddEquivClass`: classes for types containing bundled equivalences that + preserve multiplication/addition. + +## Notations + +* ``infix ` ≃* `:25 := MulEquiv`` +* ``infix ` ≃+ `:25 := AddEquiv`` + +The extended equivs all have coercions to functions, and the coercions are the canonical +notation when treating the isomorphisms as maps. + +## Tags + +Equiv, MulEquiv, AddEquiv +-/ + +open Function + +variable {F α β M N P G H : Type*} + +namespace EmbeddingLike +variable [One M] [One N] [FunLike F M N] [EmbeddingLike F M N] [OneHomClass F M N] + +@[to_additive (attr := simp)] +theorem map_eq_one_iff {f : F} {x : M} : + f x = 1 ↔ x = 1 := + _root_.map_eq_one_iff f (EmbeddingLike.injective f) + +@[to_additive] +theorem map_ne_one_iff {f : F} {x : M} : + f x ≠ 1 ↔ x ≠ 1 := + map_eq_one_iff.not + +end EmbeddingLike + +/-- `AddEquiv α β` is the type of an equiv `α ≃ β` which preserves addition. -/ +structure AddEquiv (A B : Type*) [Add A] [Add B] extends A ≃ B, AddHom A B + +/-- `AddEquivClass F A B` states that `F` is a type of addition-preserving morphisms. +You should extend this class when you extend `AddEquiv`. -/ +class AddEquivClass (F : Type*) (A B : outParam Type*) [Add A] [Add B] [EquivLike F A B] : + Prop where + /-- Preserves addition. -/ + map_add : ∀ (f : F) (a b), f (a + b) = f a + f b + +/-- The `Equiv` underlying an `AddEquiv`. -/ +add_decl_doc AddEquiv.toEquiv + +/-- The `AddHom` underlying an `AddEquiv`. -/ +add_decl_doc AddEquiv.toAddHom + +/-- `MulEquiv α β` is the type of an equiv `α ≃ β` which preserves multiplication. -/ +@[to_additive] +structure MulEquiv (M N : Type*) [Mul M] [Mul N] extends M ≃ N, M →ₙ* N + +/-- The `Equiv` underlying a `MulEquiv`. -/ +add_decl_doc MulEquiv.toEquiv + +/-- The `MulHom` underlying a `MulEquiv`. -/ +add_decl_doc MulEquiv.toMulHom + +/-- Notation for a `MulEquiv`. -/ +infixl:25 " ≃* " => MulEquiv + +/-- Notation for an `AddEquiv`. -/ +infixl:25 " ≃+ " => AddEquiv + +@[to_additive] +lemma MulEquiv.toEquiv_injective {α β : Type*} [Mul α] [Mul β] : + Function.Injective (toEquiv : (α ≃* β) → (α ≃ β)) + | ⟨_, _⟩, ⟨_, _⟩, rfl => rfl + +/-- `MulEquivClass F A B` states that `F` is a type of multiplication-preserving morphisms. +You should extend this class when you extend `MulEquiv`. -/ +-- TODO: make this a synonym for MulHomClass? +@[to_additive] +class MulEquivClass (F : Type*) (A B : outParam Type*) [Mul A] [Mul B] [EquivLike F A B] : + Prop where + /-- Preserves multiplication. -/ + map_mul : ∀ (f : F) (a b), f (a * b) = f a * f b + +@[to_additive] +alias MulEquivClass.map_eq_one_iff := EmbeddingLike.map_eq_one_iff + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated EmbeddingLike.map_eq_one_iff (since := "2024-11-10")] +MulEquivClass.map_eq_one_iff +attribute [deprecated EmbeddingLike.map_eq_zero_iff (since := "2024-11-10")] +AddEquivClass.map_eq_zero_iff + + +@[to_additive] +alias MulEquivClass.map_ne_one_iff := EmbeddingLike.map_ne_one_iff + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated EmbeddingLike.map_ne_one_iff (since := "2024-11-10")] +MulEquivClass.map_ne_one_iff +attribute [deprecated EmbeddingLike.map_ne_zero_iff (since := "2024-11-10")] +AddEquivClass.map_ne_zero_iff + + +namespace MulEquivClass + +variable (F) +variable [EquivLike F M N] + +-- See note [lower instance priority] +@[to_additive] +instance (priority := 100) instMulHomClass (F : Type*) + [Mul M] [Mul N] [EquivLike F M N] [h : MulEquivClass F M N] : MulHomClass F M N := + { h with } + +-- See note [lower instance priority] +@[to_additive] +instance (priority := 100) instMonoidHomClass + [MulOneClass M] [MulOneClass N] [MulEquivClass F M N] : + MonoidHomClass F M N := + { MulEquivClass.instMulHomClass F with + map_one := fun e => + calc + e 1 = e 1 * 1 := (mul_one _).symm + _ = e 1 * e (EquivLike.inv e (1 : N) : M) := + congr_arg _ (EquivLike.right_inv e 1).symm + _ = e (EquivLike.inv e (1 : N)) := by rw [← map_mul, one_mul] + _ = 1 := EquivLike.right_inv e 1 } + +end MulEquivClass + +variable [EquivLike F α β] + +/-- Turn an element of a type `F` satisfying `MulEquivClass F α β` into an actual +`MulEquiv`. This is declared as the default coercion from `F` to `α ≃* β`. -/ +@[to_additive (attr := coe) +"Turn an element of a type `F` satisfying `AddEquivClass F α β` into an actual +`AddEquiv`. This is declared as the default coercion from `F` to `α ≃+ β`."] +def MulEquivClass.toMulEquiv [Mul α] [Mul β] [MulEquivClass F α β] (f : F) : α ≃* β := + { (f : α ≃ β), (f : α →ₙ* β) with } + +/-- Any type satisfying `MulEquivClass` can be cast into `MulEquiv` via +`MulEquivClass.toMulEquiv`. -/ +@[to_additive "Any type satisfying `AddEquivClass` can be cast into `AddEquiv` via +`AddEquivClass.toAddEquiv`. "] +instance [Mul α] [Mul β] [MulEquivClass F α β] : CoeTC F (α ≃* β) := + ⟨MulEquivClass.toMulEquiv⟩ + +namespace MulEquiv +section Mul +variable [Mul M] [Mul N] [Mul P] + +section coe + +@[to_additive] +instance : EquivLike (M ≃* N) M N where + coe f := f.toFun + inv f := f.invFun + left_inv f := f.left_inv + right_inv f := f.right_inv + coe_injective' f g h₁ h₂ := by + cases f + cases g + congr + apply Equiv.coe_fn_injective h₁ + +@[to_additive] -- shortcut instance that doesn't generate any subgoals +instance : CoeFun (M ≃* N) fun _ ↦ M → N where + coe f := f + +@[to_additive] +instance : MulEquivClass (M ≃* N) M N where + map_mul f := f.map_mul' + +/-- Two multiplicative isomorphisms agree if they are defined by the +same underlying function. -/ +@[to_additive (attr := ext) + "Two additive isomorphisms agree if they are defined by the same underlying function."] +theorem ext {f g : MulEquiv M N} (h : ∀ x, f x = g x) : f = g := + DFunLike.ext f g h + +@[to_additive] +protected theorem congr_arg {f : MulEquiv M N} {x x' : M} : x = x' → f x = f x' := + DFunLike.congr_arg f + +@[to_additive] +protected theorem congr_fun {f g : MulEquiv M N} (h : f = g) (x : M) : f x = g x := + DFunLike.congr_fun h x + +@[to_additive (attr := simp)] +theorem coe_mk (f : M ≃ N) (hf : ∀ x y, f (x * y) = f x * f y) : (mk f hf : M → N) = f := rfl + +@[to_additive (attr := simp)] +theorem mk_coe (e : M ≃* N) (e' h₁ h₂ h₃) : (⟨⟨e, e', h₁, h₂⟩, h₃⟩ : M ≃* N) = e := + ext fun _ => rfl + +@[to_additive (attr := simp)] +theorem toEquiv_eq_coe (f : M ≃* N) : f.toEquiv = f := + rfl + +/-- The `simp`-normal form to turn something into a `MulHom` is via `MulHomClass.toMulHom`. -/ +@[to_additive (attr := simp)] +theorem toMulHom_eq_coe (f : M ≃* N) : f.toMulHom = ↑f := + rfl + +@[to_additive] +theorem toFun_eq_coe (f : M ≃* N) : f.toFun = f := rfl + +/-- `simp`-normal form of `toFun_eq_coe`. -/ +@[to_additive (attr := simp)] +theorem coe_toEquiv (f : M ≃* N) : ⇑(f : M ≃ N) = f := rfl + +@[to_additive (attr := simp)] +theorem coe_toMulHom {f : M ≃* N} : (f.toMulHom : M → N) = f := rfl + +/-- Makes a multiplicative isomorphism from a bijection which preserves multiplication. -/ +@[to_additive "Makes an additive isomorphism from a bijection which preserves addition."] +def mk' (f : M ≃ N) (h : ∀ x y, f (x * y) = f x * f y) : M ≃* N := ⟨f, h⟩ + +end coe + +section map + +/-- A multiplicative isomorphism preserves multiplication. -/ +@[to_additive "An additive isomorphism preserves addition."] +protected theorem map_mul (f : M ≃* N) : ∀ x y, f (x * y) = f x * f y := + map_mul f + +attribute [deprecated map_mul (since := "2024-08-08")] MulEquiv.map_mul +attribute [deprecated map_add (since := "2024-08-08")] AddEquiv.map_add + +end map + +section bijective + +@[to_additive] +protected theorem bijective (e : M ≃* N) : Function.Bijective e := + EquivLike.bijective e + +@[to_additive] +protected theorem injective (e : M ≃* N) : Function.Injective e := + EquivLike.injective e + +@[to_additive] +protected theorem surjective (e : M ≃* N) : Function.Surjective e := + EquivLike.surjective e + +@[to_additive] +theorem apply_eq_iff_eq (e : M ≃* N) {x y : M} : e x = e y ↔ x = y := + e.injective.eq_iff + +end bijective + +section refl + +/-- The identity map is a multiplicative isomorphism. -/ +@[to_additive (attr := refl) "The identity map is an additive isomorphism."] +def refl (M : Type*) [Mul M] : M ≃* M := + { Equiv.refl _ with map_mul' := fun _ _ => rfl } + +@[to_additive] +instance : Inhabited (M ≃* M) := ⟨refl M⟩ + +@[to_additive (attr := simp)] +theorem coe_refl : ↑(refl M) = id := rfl + +@[to_additive (attr := simp)] +theorem refl_apply (m : M) : refl M m = m := rfl + +end refl + +section symm + +/-- An alias for `h.symm.map_mul`. Introduced to fix the issue in +https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/!4.234183.20.60simps.60.20maximum.20recursion.20depth +-/ +@[to_additive] +lemma symm_map_mul {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) (x y : N) : + h.symm (x * y) = h.symm x * h.symm y := + map_mul (h.toMulHom.inverse h.toEquiv.symm h.left_inv h.right_inv) x y + +/-- The inverse of an isomorphism is an isomorphism. -/ +@[to_additive (attr := symm) "The inverse of an isomorphism is an isomorphism."] +def symm {M N : Type*} [Mul M] [Mul N] (h : M ≃* N) : N ≃* M := + ⟨h.toEquiv.symm, h.symm_map_mul⟩ + +@[to_additive] +theorem invFun_eq_symm {f : M ≃* N} : f.invFun = f.symm := rfl + +/-- `simp`-normal form of `invFun_eq_symm`. -/ +@[to_additive (attr := simp)] +theorem coe_toEquiv_symm (f : M ≃* N) : ((f : M ≃ N).symm : N → M) = f.symm := rfl + +@[to_additive (attr := simp)] +theorem equivLike_inv_eq_symm (f : M ≃* N) : EquivLike.inv f = f.symm := rfl + +@[to_additive (attr := simp)] +theorem toEquiv_symm (f : M ≃* N) : (f.symm : N ≃ M) = (f : M ≃ N).symm := rfl + +@[to_additive (attr := simp)] +theorem symm_symm (f : M ≃* N) : f.symm.symm = f := rfl + +@[to_additive] +theorem symm_bijective : Function.Bijective (symm : (M ≃* N) → N ≃* M) := + Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ + +@[to_additive (attr := simp)] +theorem mk_coe' (e : M ≃* N) (f h₁ h₂ h₃) : (MulEquiv.mk ⟨f, e, h₁, h₂⟩ h₃ : N ≃* M) = e.symm := + symm_bijective.injective <| ext fun _ => rfl + +@[to_additive (attr := simp)] +theorem symm_mk (f : M ≃ N) (h) : + (MulEquiv.mk f h).symm = ⟨f.symm, (MulEquiv.mk f h).symm_map_mul⟩ := rfl + +@[to_additive (attr := simp)] +theorem refl_symm : (refl M).symm = refl M := rfl + +/-- `e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`. -/ +@[to_additive (attr := simp) "`e.symm` is a right inverse of `e`, written as `e (e.symm y) = y`."] +theorem apply_symm_apply (e : M ≃* N) (y : N) : e (e.symm y) = y := + e.toEquiv.apply_symm_apply y + +/-- `e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`. -/ +@[to_additive (attr := simp) "`e.symm` is a left inverse of `e`, written as `e.symm (e y) = y`."] +theorem symm_apply_apply (e : M ≃* N) (x : M) : e.symm (e x) = x := + e.toEquiv.symm_apply_apply x + +@[to_additive (attr := simp)] +theorem symm_comp_self (e : M ≃* N) : e.symm ∘ e = id := + funext e.symm_apply_apply + +@[to_additive (attr := simp)] +theorem self_comp_symm (e : M ≃* N) : e ∘ e.symm = id := + funext e.apply_symm_apply + +@[to_additive] +theorem apply_eq_iff_symm_apply (e : M ≃* N) {x : M} {y : N} : e x = y ↔ x = e.symm y := + e.toEquiv.apply_eq_iff_eq_symm_apply + +@[to_additive] +theorem symm_apply_eq (e : M ≃* N) {x y} : e.symm x = y ↔ x = e y := + e.toEquiv.symm_apply_eq + +@[to_additive] +theorem eq_symm_apply (e : M ≃* N) {x y} : y = e.symm x ↔ e y = x := + e.toEquiv.eq_symm_apply + +@[to_additive] +theorem eq_comp_symm {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) : + f = g ∘ e.symm ↔ f ∘ e = g := + e.toEquiv.eq_comp_symm f g + +@[to_additive] +theorem comp_symm_eq {α : Type*} (e : M ≃* N) (f : N → α) (g : M → α) : + g ∘ e.symm = f ↔ g = f ∘ e := + e.toEquiv.comp_symm_eq f g + +@[to_additive] +theorem eq_symm_comp {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) : + f = e.symm ∘ g ↔ e ∘ f = g := + e.toEquiv.eq_symm_comp f g + +@[to_additive] +theorem symm_comp_eq {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) : + e.symm ∘ g = f ↔ g = e ∘ f := + e.toEquiv.symm_comp_eq f g + +@[to_additive (attr := simp)] +theorem _root_.MulEquivClass.apply_coe_symm_apply {α β} [Mul α] [Mul β] {F} [EquivLike F α β] + [MulEquivClass F α β] (e : F) (x : β) : + e ((e : α ≃* β).symm x) = x := + (e : α ≃* β).right_inv x + +@[to_additive (attr := simp)] +theorem _root_.MulEquivClass.coe_symm_apply_apply {α β} [Mul α] [Mul β] {F} [EquivLike F α β] + [MulEquivClass F α β] (e : F) (x : α) : + (e : α ≃* β).symm (e x) = x := + (e : α ≃* β).left_inv x + +end symm + +section simps + +-- we don't hyperlink the note in the additive version, since that breaks syntax highlighting +-- in the whole file. + +/-- See Note [custom simps projection] -/ +@[to_additive "See Note [custom simps projection]"] -- this comment fixes the syntax highlighting " +def Simps.symm_apply (e : M ≃* N) : N → M := + e.symm + +initialize_simps_projections AddEquiv (toFun → apply, invFun → symm_apply) + +initialize_simps_projections MulEquiv (toFun → apply, invFun → symm_apply) + +end simps + +section trans + +/-- Transitivity of multiplication-preserving isomorphisms -/ +@[to_additive (attr := trans) "Transitivity of addition-preserving isomorphisms"] +def trans (h1 : M ≃* N) (h2 : N ≃* P) : M ≃* P := + { h1.toEquiv.trans h2.toEquiv with + map_mul' := fun x y => show h2 (h1 (x * y)) = h2 (h1 x) * h2 (h1 y) by + rw [map_mul, map_mul] } + +@[to_additive (attr := simp)] +theorem coe_trans (e₁ : M ≃* N) (e₂ : N ≃* P) : ↑(e₁.trans e₂) = e₂ ∘ e₁ := rfl + +@[to_additive (attr := simp)] +theorem trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (m : M) : e₁.trans e₂ m = e₂ (e₁ m) := rfl + +@[to_additive (attr := simp)] +theorem symm_trans_apply (e₁ : M ≃* N) (e₂ : N ≃* P) (p : P) : + (e₁.trans e₂).symm p = e₁.symm (e₂.symm p) := rfl + +@[to_additive (attr := simp)] +theorem symm_trans_self (e : M ≃* N) : e.symm.trans e = refl N := + DFunLike.ext _ _ e.apply_symm_apply + +@[to_additive (attr := simp)] +theorem self_trans_symm (e : M ≃* N) : e.trans e.symm = refl M := + DFunLike.ext _ _ e.symm_apply_apply + +end trans + +end Mul + +/-! +## Monoids +-/ + +section MulOneClass +variable [MulOneClass M] [MulOneClass N] [MulOneClass P] + +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/10618): `simp` can prove this but it is a valid `dsimp` lemma. +-- However, we would need to redesign the the `dsimp` set to make this `@[simp]`. +@[to_additive] +theorem coe_monoidHom_refl : (refl M : M →* M) = MonoidHom.id M := rfl + +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/10618): `simp` can prove this but it is a valid `dsimp` lemma. +-- However, we would need to redesign the the `dsimp` set to make this `@[simp]`. +@[to_additive] +lemma coe_monoidHom_trans (e₁ : M ≃* N) (e₂ : N ≃* P) : + (e₁.trans e₂ : M →* P) = (e₂ : N →* P).comp ↑e₁ := rfl + +@[to_additive (attr := simp)] +lemma coe_monoidHom_comp_coe_monoidHom_symm (e : M ≃* N) : + (e : M →* N).comp e.symm = MonoidHom.id _ := by ext; simp + +@[to_additive (attr := simp)] +lemma coe_monoidHom_symm_comp_coe_monoidHom (e : M ≃* N) : + (e.symm : N →* M).comp e = MonoidHom.id _ := by ext; simp + +@[to_additive] +lemma comp_left_injective (e : M ≃* N) : Injective fun f : N →* P ↦ f.comp (e : M →* N) := + LeftInverse.injective (g := fun f ↦ f.comp e.symm) fun f ↦ by simp [MonoidHom.comp_assoc] + +@[to_additive] +lemma comp_right_injective (e : M ≃* N) : Injective fun f : P →* M ↦ (e : M →* N).comp f := + LeftInverse.injective (g := (e.symm : N →* M).comp) fun f ↦ by simp [← MonoidHom.comp_assoc] + +/-- A multiplicative isomorphism of monoids sends `1` to `1` (and is hence a monoid isomorphism). -/ +@[to_additive + "An additive isomorphism of additive monoids sends `0` to `0` + (and is hence an additive monoid isomorphism)."] +protected theorem map_one (h : M ≃* N) : h 1 = 1 := map_one h + +@[to_additive] +protected theorem map_eq_one_iff (h : M ≃* N) {x : M} : h x = 1 ↔ x = 1 := + EmbeddingLike.map_eq_one_iff + +@[to_additive] +theorem map_ne_one_iff (h : M ≃* N) {x : M} : h x ≠ 1 ↔ x ≠ 1 := + EmbeddingLike.map_ne_one_iff + +/-- A bijective `Semigroup` homomorphism is an isomorphism -/ +@[to_additive (attr := simps! apply) "A bijective `AddSemigroup` homomorphism is an isomorphism"] +noncomputable def ofBijective {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N] + (f : F) (hf : Bijective f) : M ≃* N := + { Equiv.ofBijective f hf with map_mul' := map_mul f } + +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: simplify `symm_apply` to `surjInv`? +@[to_additive (attr := simp)] +theorem ofBijective_apply_symm_apply {n : N} (f : M →* N) (hf : Bijective f) : + f ((ofBijective f hf).symm n) = n := (ofBijective f hf).apply_symm_apply n + +/-- Extract the forward direction of a multiplicative equivalence +as a multiplication-preserving function. +-/ +@[to_additive "Extract the forward direction of an additive equivalence + as an addition-preserving function."] +def toMonoidHom (h : M ≃* N) : M →* N := + { h with map_one' := h.map_one } + +@[to_additive (attr := simp)] +theorem coe_toMonoidHom (e : M ≃* N) : ⇑e.toMonoidHom = e := rfl + +@[to_additive (attr := simp)] +theorem toMonoidHom_eq_coe (f : M ≃* N) : f.toMonoidHom = (f : M →* N) := + rfl + +@[to_additive] +theorem toMonoidHom_injective : Injective (toMonoidHom : M ≃* N → M →* N) := + Injective.of_comp (f := DFunLike.coe) DFunLike.coe_injective + +end MulOneClass + +/-! +# Groups +-/ + +/-- A multiplicative equivalence of groups preserves inversion. -/ +@[to_additive "An additive equivalence of additive groups preserves negation."] +protected theorem map_inv [Group G] [DivisionMonoid H] (h : G ≃* H) (x : G) : + h x⁻¹ = (h x)⁻¹ := + map_inv h x + +/-- A multiplicative equivalence of groups preserves division. -/ +@[to_additive "An additive equivalence of additive groups preserves subtractions."] +protected theorem map_div [Group G] [DivisionMonoid H] (h : G ≃* H) (x y : G) : + h (x / y) = h x / h y := + map_div h x y + +end MulEquiv + +/-- Given a pair of multiplicative homomorphisms `f`, `g` such that `g.comp f = id` and +`f.comp g = id`, returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This +constructor is useful if the underlying type(s) have specialized `ext` lemmas for multiplicative +homomorphisms. -/ +@[to_additive (attr := simps (config := .asFn)) + "Given a pair of additive homomorphisms `f`, `g` such that `g.comp f = id` and + `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`. This + constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive + homomorphisms."] +def MulHom.toMulEquiv [Mul M] [Mul N] (f : M →ₙ* N) (g : N →ₙ* M) (h₁ : g.comp f = MulHom.id _) + (h₂ : f.comp g = MulHom.id _) : M ≃* N where + toFun := f + invFun := g + left_inv := DFunLike.congr_fun h₁ + right_inv := DFunLike.congr_fun h₂ + map_mul' := f.map_mul + +/-- Given a pair of monoid homomorphisms `f`, `g` such that `g.comp f = id` and `f.comp g = id`, +returns a multiplicative equivalence with `toFun = f` and `invFun = g`. This constructor is +useful if the underlying type(s) have specialized `ext` lemmas for monoid homomorphisms. -/ +@[to_additive (attr := simps (config := .asFn)) + "Given a pair of additive monoid homomorphisms `f`, `g` such that `g.comp f = id` + and `f.comp g = id`, returns an additive equivalence with `toFun = f` and `invFun = g`. This + constructor is useful if the underlying type(s) have specialized `ext` lemmas for additive + monoid homomorphisms."] +def MonoidHom.toMulEquiv [MulOneClass M] [MulOneClass N] (f : M →* N) (g : N →* M) + (h₁ : g.comp f = MonoidHom.id _) (h₂ : f.comp g = MonoidHom.id _) : M ≃* N where + toFun := f + invFun := g + left_inv := DFunLike.congr_fun h₁ + right_inv := DFunLike.congr_fun h₂ + map_mul' := f.map_mul + +namespace Equiv + +end Equiv diff --git a/Mathlib/Algebra/Group/Pi/Units.lean b/Mathlib/Algebra/Group/Pi/Units.lean index ae0ecae78a6f7..ba43080762225 100644 --- a/Mathlib/Algebra/Group/Pi/Units.lean +++ b/Mathlib/Algebra/Group/Pi/Units.lean @@ -3,9 +3,9 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.Group.Pi.Basic import Mathlib.Algebra.Group.Units.Defs -import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Util.Delaborators /-! # Units in pi types -/ diff --git a/Mathlib/Algebra/Group/ULift.lean b/Mathlib/Algebra/Group/ULift.lean index 3fa88a1bd715e..17035e41f1191 100644 --- a/Mathlib/Algebra/Group/ULift.lean +++ b/Mathlib/Algebra/Group/ULift.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.Group.InjSurj import Mathlib.Logic.Nontrivial.Basic diff --git a/Mathlib/Algebra/Group/WithOne/Basic.lean b/Mathlib/Algebra/Group/WithOne/Basic.lean index 7a525e26b753b..5382fd1d0651a 100644 --- a/Mathlib/Algebra/Group/WithOne/Basic.lean +++ b/Mathlib/Algebra/Group/WithOne/Basic.lean @@ -3,7 +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, Johan Commelin -/ -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.Group.WithOne.Defs /-! diff --git a/Mathlib/Algebra/GroupWithZero/Action/End.lean b/Mathlib/Algebra/GroupWithZero/Action/End.lean index 79f3d7dc54538..35b8ca4a9efd4 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/End.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/End.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Yury Kudryashov -/ import Mathlib.Algebra.Group.Action.End -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.GroupWithZero.Action.Defs import Mathlib.Algebra.GroupWithZero.Action.Units diff --git a/Mathlib/Algebra/GroupWithZero/Hom.lean b/Mathlib/Algebra/GroupWithZero/Hom.lean index e4d19ee977799..f30ace0a86cbc 100644 --- a/Mathlib/Algebra/GroupWithZero/Hom.lean +++ b/Mathlib/Algebra/GroupWithZero/Hom.lean @@ -3,7 +3,8 @@ Copyright (c) 2020 Patrick Massot. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Equiv.Defs +import Mathlib.Algebra.Group.Hom.Basic import Mathlib.Algebra.GroupWithZero.Basic import Mathlib.Algebra.NeZero diff --git a/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean b/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean index 6d9cedb09fb7c..d96e46d3ccec1 100644 --- a/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean +++ b/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.Order.Sub.Defs -import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Algebra.Ring.Basic import Mathlib.Order.Hom.Basic /-! diff --git a/Mathlib/CategoryTheory/Endomorphism.lean b/Mathlib/CategoryTheory/Endomorphism.lean index 2c5d31f5dede1..4ae2f96f3fdc5 100644 --- a/Mathlib/CategoryTheory/Endomorphism.lean +++ b/Mathlib/CategoryTheory/Endomorphism.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Kim Morrison, Simon Hudon -/ import Mathlib.Algebra.Group.Action.Defs -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.Algebra.Group.Units.Basic import Mathlib.Algebra.Group.Units.Hom import Mathlib.CategoryTheory.Groupoid diff --git a/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean b/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean index 42789d4d9d7d6..c0f139812c0b1 100644 --- a/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean +++ b/Mathlib/CategoryTheory/Groupoid/VertexGroup.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Rémi Bottinelli. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémi Bottinelli -/ -import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.Group.Equiv.Defs import Mathlib.CategoryTheory.Groupoid import Mathlib.CategoryTheory.PathCategory.Basic import Mathlib.Combinatorics.Quiver.Path diff --git a/Mathlib/Deprecated/Group.lean b/Mathlib/Deprecated/Group.lean index 66bc94fe1317e..dd913b42c9bec 100644 --- a/Mathlib/Deprecated/Group.lean +++ b/Mathlib/Deprecated/Group.lean @@ -3,7 +3,6 @@ Copyright (c) 2019 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Algebra.Group.TypeTags.Basic From 34b0940aa7bc09a1fd3bd9e50476282989ba08a9 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Wed, 15 Jan 2025 22:33:20 +0000 Subject: [PATCH 253/681] chore: typos in Fderiv instead of FDeriv (#20775) --- Mathlib/Analysis/Calculus/ContDiff/Basic.lean | 7 +++++-- Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean | 2 +- Mathlib/Analysis/Calculus/Rademacher.lean | 15 ++++++++------- Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean | 4 ++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index 75de38f4c2f73..6bf66bf69047e 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -1134,7 +1134,7 @@ theorem ContDiffWithinAt.fderivWithin_right_apply contDiffWithinAt_id hk hs hmn hx₀s (by rw [preimage_id']) -- TODO: can we make a version of `ContDiffWithinAt.fderivWithin` for iterated derivatives? -theorem ContDiffWithinAt.iteratedFderivWithin_right {i : ℕ} (hf : ContDiffWithinAt 𝕜 n f s x₀) +theorem ContDiffWithinAt.iteratedFDerivWithin_right {i : ℕ} (hf : ContDiffWithinAt 𝕜 n f s x₀) (hs : UniqueDiffOn 𝕜 s) (hmn : m + i ≤ n) (hx₀s : x₀ ∈ s) : ContDiffWithinAt 𝕜 m (iteratedFDerivWithin 𝕜 i f s) s x₀ := by induction' i with i hi generalizing m @@ -1146,6 +1146,9 @@ theorem ContDiffWithinAt.iteratedFderivWithin_right {i : ℕ} (hf : ContDiffWith ((continuousMultilinearCurryLeftEquiv 𝕜 (fun _ : Fin (i+1) ↦ E) F).symm : _ →L[𝕜] E [×(i+1)]→L[𝕜] F) +@[deprecated (since := "2025-01-15")] +alias ContDiffWithinAt.iteratedFderivWithin_right := ContDiffWithinAt.iteratedFDerivWithin_right + /-- `x ↦ fderiv 𝕜 (f x) (g x)` is smooth at `x₀`. -/ protected theorem ContDiffAt.fderiv {f : E → F → G} {g : E → F} (hf : ContDiffAt 𝕜 n (Function.uncurry f) (x₀, g x₀)) (hg : ContDiffAt 𝕜 m g x₀) @@ -1163,7 +1166,7 @@ theorem ContDiffAt.fderiv_right (hf : ContDiffAt 𝕜 n f x₀) (hmn : m + 1 ≤ theorem ContDiffAt.iteratedFDeriv_right {i : ℕ} (hf : ContDiffAt 𝕜 n f x₀) (hmn : m + i ≤ n) : ContDiffAt 𝕜 m (iteratedFDeriv 𝕜 i f) x₀ := by rw [← iteratedFDerivWithin_univ, ← contDiffWithinAt_univ] at * - exact hf.iteratedFderivWithin_right uniqueDiffOn_univ hmn trivial + exact hf.iteratedFDerivWithin_right uniqueDiffOn_univ hmn trivial /-- `x ↦ fderiv 𝕜 (f x) (g x)` is smooth. -/ protected theorem ContDiff.fderiv {f : E → F → G} {g : E → F} diff --git a/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean b/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean index 67c304e3952ff..ccf4ec329f8cb 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean @@ -9,7 +9,7 @@ import Mathlib.Analysis.Calculus.FDeriv.Prod # The derivative of bounded bilinear maps For detailed documentation of the Fréchet derivative, -see the module docstring of `Analysis/Calculus/Fderiv/Basic.lean`. +see the module docstring of `Analysis/Calculus/FDeriv/Basic.lean`. This file contains the usual formulas (and existence assertions) for the derivative of bounded bilinear maps. diff --git a/Mathlib/Analysis/Calculus/Rademacher.lean b/Mathlib/Analysis/Calculus/Rademacher.lean index 1b737826d3f74..5750dc7396cc7 100644 --- a/Mathlib/Analysis/Calculus/Rademacher.lean +++ b/Mathlib/Analysis/Calculus/Rademacher.lean @@ -35,7 +35,7 @@ See `LipschitzWith.ae_lineDeriv_sum_eq`. is line-differentiable in all these directions and the line derivative is linear. Approximating any direction by a direction in `s` and using the fact that `f` is Lipschitz to control the error, it follows that `f` is Fréchet-differentiable at these points. -See `LipschitzWith.hasFderivAt_of_hasLineDerivAt_of_closure`. +See `LipschitzWith.hasFDerivAt_of_hasLineDerivAt_of_closure`. ## References @@ -257,13 +257,11 @@ theorem ae_exists_fderiv_of_countable have J : L v = lineDeriv ℝ f x v := by convert (hx v hv).symm <;> simp [L, B.sum_repr v] simpa [J] using (h'x v hv).hasLineDerivAt +omit [MeasurableSpace E] in /-- If a Lipschitz functions has line derivatives in a dense set of directions, all of them given by a single continuous linear map `L`, then it admits `L` as Fréchet derivative. -/ --- We redeclare `E` here as we do not need the `[MeasurableSpace E]` instance --- available in the rest of the file. -theorem hasFderivAt_of_hasLineDerivAt_of_closure - {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [ProperSpace E] {f : E → F} - (hf : LipschitzWith C f) {s : Set E} (hs : sphere 0 1 ⊆ closure s) +theorem hasFDerivAt_of_hasLineDerivAt_of_closure + {f : E → F} (hf : LipschitzWith C f) {s : Set E} (hs : sphere 0 1 ⊆ closure s) {L : E →L[ℝ] F} {x : E} (hL : ∀ v ∈ s, HasLineDerivAt ℝ f (L v) x v) : HasFDerivAt f L x := by rw [hasFDerivAt_iff_isLittleO_nhds_zero, isLittleO_iff] @@ -314,6 +312,9 @@ theorem hasFderivAt_of_hasLineDerivAt_of_closure _ = ((C + ‖L‖ + 1) * δ) * ρ := by ring _ = ε * ‖v‖ := by rw [hδ, hρ] +@[deprecated (since := "2025-01-15")] +alias hasFderivAt_of_hasLineDerivAt_of_closure := hasFDerivAt_of_hasLineDerivAt_of_closure + /-- A real-valued function on a finite-dimensional space which is Lipschitz is differentiable almost everywere. Superseded by `LipschitzWith.ae_differentiableAt` which works for functions taking value in any @@ -325,7 +326,7 @@ theorem ae_differentiableAt_of_real (hf : LipschitzWith C f) : have hs : sphere 0 1 ⊆ closure s := by rw [s_dense.closure_eq]; exact subset_univ _ filter_upwards [hf.ae_exists_fderiv_of_countable s_count] rintro x ⟨L, hL⟩ - exact (hf.hasFderivAt_of_hasLineDerivAt_of_closure hs hL).differentiableAt + exact (hf.hasFDerivAt_of_hasLineDerivAt_of_closure hs hL).differentiableAt end LipschitzWith diff --git a/Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean b/Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean index 91de1a8be395f..e10b93578965a 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/FDeriv.lean @@ -21,7 +21,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom [NormedSpace 𝕜 E] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {f : E → E'} {s : Set E} {x : E} -section MFDerivFderiv +section MFDerivFDeriv theorem uniqueMDiffWithinAt_iff_uniqueDiffWithinAt : UniqueMDiffWithinAt 𝓘(𝕜, E) s x ↔ UniqueDiffWithinAt 𝕜 s x := by @@ -110,4 +110,4 @@ theorem mfderiv_eq_fderiv : mfderiv 𝓘(𝕜, E) 𝓘(𝕜, E') f x = fderiv rw [← mfderivWithin_univ, ← fderivWithin_univ] exact mfderivWithin_eq_fderivWithin -end MFDerivFderiv +end MFDerivFDeriv From 79a5bf8f023fa8c52b3801b561be4bbbde2501a6 Mon Sep 17 00:00:00 2001 From: Oliver Nash Date: Wed, 15 Jan 2025 22:33:22 +0000 Subject: [PATCH 254/681] chore: split file `LinearAlgebra.PerfectPairing` (#20780) In preparation for some new material about restrictions of perfect pairings, it is useful first to split this file. --- Mathlib.lean | 3 +- .../LinearAlgebra/PerfectPairing/Basic.lean | 276 ++++++++++++ .../Restrict.lean} | 405 ++++-------------- Mathlib/LinearAlgebra/RootSystem/Defs.lean | 2 +- 4 files changed, 364 insertions(+), 322 deletions(-) create mode 100644 Mathlib/LinearAlgebra/PerfectPairing/Basic.lean rename Mathlib/LinearAlgebra/{PerfectPairing.lean => PerfectPairing/Restrict.lean} (52%) diff --git a/Mathlib.lean b/Mathlib.lean index 331c6efcb0ded..55f6e8d3c51a2 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3549,7 +3549,8 @@ import Mathlib.LinearAlgebra.Multilinear.Pi import Mathlib.LinearAlgebra.Multilinear.TensorProduct import Mathlib.LinearAlgebra.Orientation import Mathlib.LinearAlgebra.PID -import Mathlib.LinearAlgebra.PerfectPairing +import Mathlib.LinearAlgebra.PerfectPairing.Basic +import Mathlib.LinearAlgebra.PerfectPairing.Restrict import Mathlib.LinearAlgebra.Pi import Mathlib.LinearAlgebra.PiTensorProduct import Mathlib.LinearAlgebra.Prod diff --git a/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean b/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean new file mode 100644 index 0000000000000..51d24aee6ca24 --- /dev/null +++ b/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean @@ -0,0 +1,276 @@ +/- +Copyright (c) 2023 Oliver Nash. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Oliver Nash +-/ +import Mathlib.LinearAlgebra.Dual + +/-! +# Perfect pairings of modules + +A perfect pairing of two (left) modules may be defined either as: + 1. A bilinear map `M × N → R` such that the induced maps `M → Dual R N` and `N → Dual R M` are both + bijective. It follows from this that both `M` and `N` are reflexive modules. + 2. A linear equivalence `N ≃ Dual R M` for which `M` is reflexive. (It then follows that `N` is + reflexive.) + +In this file we provide a `PerfectPairing` definition corresponding to 1 above, together with logic +to connect 1 and 2. + +## Main definitions + + * `PerfectPairing` + * `PerfectPairing.flip` + * `PerfectPairing.dual` + * `PerfectPairing.toDualLeft` + * `PerfectPairing.toDualRight` + * `LinearEquiv.flip` + * `LinearEquiv.isReflexive_of_equiv_dual_of_isReflexive` + * `LinearEquiv.toPerfectPairing` + +-/ + +open Function Module + +noncomputable section + +variable (R M N : Type*) [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] + +/-- A perfect pairing of two (left) modules over a commutative ring. -/ +structure PerfectPairing where + toLin : M →ₗ[R] N →ₗ[R] R + bijectiveLeft : Bijective toLin + bijectiveRight : Bijective toLin.flip + +attribute [nolint docBlame] PerfectPairing.toLin + +variable {R M N} + +namespace PerfectPairing + +/-- If the coefficients are a field, and one of the spaces is finite-dimensional, it is sufficient +to check only injectivity instead of bijectivity of the bilinear form. -/ +def mkOfInjective {K V W : Type*} + [Field K] [AddCommGroup V] [Module K V] [AddCommGroup W] [Module K W] [FiniteDimensional K V] + (B : V →ₗ[K] W →ₗ[K] K) + (h : Injective B) + (h' : Injective B.flip) : + PerfectPairing K V W where + toLin := B + bijectiveLeft := ⟨h, by rwa [← B.flip_injective_iff₁]⟩ + bijectiveRight := ⟨h', by + have : FiniteDimensional K W := FiniteDimensional.of_injective B.flip h' + rwa [← B.flip.flip_injective_iff₁, LinearMap.flip_flip]⟩ + +/-- If the coefficients are a field, and one of the spaces is finite-dimensional, it is sufficient +to check only injectivity instead of bijectivity of the bilinear form. -/ +def mkOfInjective' {K V W : Type*} + [Field K] [AddCommGroup V] [Module K V] [AddCommGroup W] [Module K W] [FiniteDimensional K W] + (B : V →ₗ[K] W →ₗ[K] K) + (h : Injective B) + (h' : Injective B.flip) : + PerfectPairing K V W where + toLin := B + bijectiveLeft := ⟨h, by + have : FiniteDimensional K V := FiniteDimensional.of_injective B h + rwa [← B.flip_injective_iff₁]⟩ + bijectiveRight := ⟨h', by rwa [← B.flip.flip_injective_iff₁, LinearMap.flip_flip]⟩ + +instance instFunLike : FunLike (PerfectPairing R M N) M (N →ₗ[R] R) where + coe f := f.toLin + coe_injective' x y h := by cases x; cases y; simpa using h + +@[simp] +lemma toLin_apply (p : PerfectPairing R M N) {x : M} : p.toLin x = p x := by + rfl + +variable (p : PerfectPairing R M N) + +/-- Given a perfect pairing between `M` and `N`, we may interchange the roles of `M` and `N`. -/ +protected def flip : PerfectPairing R N M where + toLin := p.toLin.flip + bijectiveLeft := p.bijectiveRight + bijectiveRight := p.bijectiveLeft + +@[simp] +lemma flip_apply_apply {x : M} {y : N} : p.flip y x = p x y := + rfl + +@[simp] +lemma flip_flip : p.flip.flip = p := + rfl + +/-- The linear equivalence from `M` to `Dual R N` induced by a perfect pairing. -/ +def toDualLeft : M ≃ₗ[R] Dual R N := + LinearEquiv.ofBijective p.toLin p.bijectiveLeft + +@[simp] +theorem toDualLeft_apply (a : M) : p.toDualLeft a = p a := + rfl + +@[simp] +theorem apply_toDualLeft_symm_apply (f : Dual R N) (x : N) : p (p.toDualLeft.symm f) x = f x := by + have h := LinearEquiv.apply_symm_apply p.toDualLeft f + rw [toDualLeft_apply] at h + exact congrFun (congrArg DFunLike.coe h) x + +/-- The linear equivalence from `N` to `Dual R M` induced by a perfect pairing. -/ +def toDualRight : N ≃ₗ[R] Dual R M := + toDualLeft p.flip + +@[simp] +theorem toDualRight_apply (a : N) : p.toDualRight a = p.flip a := + rfl + +@[simp] +theorem apply_apply_toDualRight_symm (x : M) (f : Dual R M) : + (p x) (p.toDualRight.symm f) = f x := by + have h := LinearEquiv.apply_symm_apply p.toDualRight f + rw [toDualRight_apply] at h + exact congrFun (congrArg DFunLike.coe h) x + +theorem toDualLeft_of_toDualRight_symm (x : M) (f : Dual R M) : + (p.toDualLeft x) (p.toDualRight.symm f) = f x := by + rw [@toDualLeft_apply] + exact apply_apply_toDualRight_symm p x f + +theorem toDualRight_symm_toDualLeft (x : M) : + p.toDualRight.symm.dualMap (p.toDualLeft x) = Dual.eval R M x := by + ext f + simp only [LinearEquiv.dualMap_apply, Dual.eval_apply] + exact toDualLeft_of_toDualRight_symm p x f + +theorem toDualRight_symm_comp_toDualLeft : + p.toDualRight.symm.dualMap ∘ₗ (p.toDualLeft : M →ₗ[R] Dual R N) = Dual.eval R M := by + ext1 x + exact p.toDualRight_symm_toDualLeft x + +theorem bijective_toDualRight_symm_toDualLeft : + Bijective (fun x => p.toDualRight.symm.dualMap (p.toDualLeft x)) := + Bijective.comp (LinearEquiv.bijective p.toDualRight.symm.dualMap) + (LinearEquiv.bijective p.toDualLeft) + +include p in +theorem reflexive_left : IsReflexive R M where + bijective_dual_eval' := by + rw [← p.toDualRight_symm_comp_toDualLeft] + exact p.bijective_toDualRight_symm_toDualLeft + +include p in +theorem reflexive_right : IsReflexive R N := + p.flip.reflexive_left + +instance : EquivLike (PerfectPairing R M N) M (Dual R N) where + coe p := p.toDualLeft + inv p := p.toDualLeft.symm + left_inv p x := LinearEquiv.symm_apply_apply _ _ + right_inv p x := LinearEquiv.apply_symm_apply _ _ + coe_injective' p q h h' := by + cases p + cases q + simp only [mk.injEq] + ext m n + simp only [DFunLike.coe_fn_eq] at h + exact LinearMap.congr_fun (LinearEquiv.congr_fun h m) n + +instance : LinearEquivClass (PerfectPairing R M N) R M (Dual R N) where + map_add p m₁ m₂ := p.toLin.map_add m₁ m₂ + map_smulₛₗ p t m := p.toLin.map_smul t m + +include p in +theorem finrank_eq [Module.Finite R M] [Module.Free R M] : + finrank R M = finrank R N := + ((Module.Free.chooseBasis R M).toDualEquiv.trans p.toDualRight.symm).finrank_eq + +end PerfectPairing + +variable [IsReflexive R M] + +/-- A reflexive module has a perfect pairing with its dual. -/ +@[simps] +def IsReflexive.toPerfectPairingDual : PerfectPairing R (Dual R M) M where + toLin := LinearMap.id + 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 + +/-- For a reflexive module `M`, an equivalence `N ≃ₗ[R] Dual R M` naturally yields an equivalence +`M ≃ₗ[R] Dual R N`. Such equivalences are known as perfect pairings. -/ +def flip : M ≃ₗ[R] Dual R N := + (evalEquiv R M).trans e.dualMap + +@[simp] lemma coe_toLinearMap_flip : e.flip = (↑e : N →ₗ[R] Dual R M).flip := rfl + +@[simp] lemma flip_apply (m : M) (n : N) : e.flip m n = e n m := rfl + +lemma symm_flip : e.flip.symm = e.symm.dualMap.trans (evalEquiv R M).symm := rfl + +lemma trans_dualMap_symm_flip : e.trans e.flip.symm.dualMap = Dual.eval R N := by + ext; simp [symm_flip] + +include e in +/-- If `N` is in perfect pairing with `M`, then it is reflexive. -/ +lemma isReflexive_of_equiv_dual_of_isReflexive : IsReflexive R N := by + constructor + rw [← trans_dualMap_symm_flip e] + exact LinearEquiv.bijective _ + +@[simp] lemma flip_flip (h : IsReflexive R N := isReflexive_of_equiv_dual_of_isReflexive e) : + e.flip.flip = e := by + ext; rfl + +/-- If `M` is reflexive then a linear equivalence `N ≃ Dual R M` is a perfect pairing. -/ +@[simps] +def toPerfectPairing : PerfectPairing R N M where + toLin := e + bijectiveLeft := e.bijective + bijectiveRight := e.flip.bijective + +end LinearEquiv + +/-- A perfect pairing induces a perfect pairing between dual spaces. -/ +def PerfectPairing.dual (p : PerfectPairing R M N) : + PerfectPairing R (Dual R M) (Dual R N) := + let _i := p.reflexive_right + (p.toDualRight.symm.trans (evalEquiv R N)).toPerfectPairing + +namespace Submodule + +open LinearEquiv + +@[simp] +lemma dualCoannihilator_map_linearEquiv_flip (p : Submodule R M) : + (p.map e.flip).dualCoannihilator = p.dualAnnihilator.map e.symm := by + ext; simp [LinearEquiv.symm_apply_eq, Submodule.mem_dualCoannihilator] + +@[simp] +lemma map_dualAnnihilator_linearEquiv_flip_symm (p : Submodule R N) : + p.dualAnnihilator.map e.flip.symm = (p.map e).dualCoannihilator := by + have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive + rw [← dualCoannihilator_map_linearEquiv_flip, flip_flip] + +@[simp] +lemma map_dualCoannihilator_linearEquiv_flip (p : Submodule R (Dual R M)) : + p.dualCoannihilator.map e.flip = (p.map e.symm).dualAnnihilator := by + have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive + suffices (p.map e.symm).dualAnnihilator.map e.flip.symm = + (p.dualCoannihilator.map e.flip).map e.flip.symm by + exact (Submodule.map_injective_of_injective e.flip.symm.injective this).symm + erw [← dualCoannihilator_map_linearEquiv_flip, flip_flip, ← map_comp, ← map_comp] + simp [-coe_toLinearMap_flip] + +@[simp] +lemma dualAnnihilator_map_linearEquiv_flip_symm (p : Submodule R (Dual R N)) : + (p.map e.flip.symm).dualAnnihilator = p.dualCoannihilator.map e := by + have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive + rw [← map_dualCoannihilator_linearEquiv_flip, flip_flip] + +end Submodule diff --git a/Mathlib/LinearAlgebra/PerfectPairing.lean b/Mathlib/LinearAlgebra/PerfectPairing/Restrict.lean similarity index 52% rename from Mathlib/LinearAlgebra/PerfectPairing.lean rename to Mathlib/LinearAlgebra/PerfectPairing/Restrict.lean index 4227551192718..51513e7ee3b89 100644 --- a/Mathlib/LinearAlgebra/PerfectPairing.lean +++ b/Mathlib/LinearAlgebra/PerfectPairing/Restrict.lean @@ -1,191 +1,34 @@ /- -Copyright (c) 2023 Oliver Nash. All rights reserved. +Copyright (c) 2025 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ -import Mathlib.LinearAlgebra.Dual +import Mathlib.LinearAlgebra.PerfectPairing.Basic import Mathlib.LinearAlgebra.Matrix.Basis import Mathlib.LinearAlgebra.Matrix.BaseChange -import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix /-! -# Perfect pairings of modules - -A perfect pairing of two (left) modules may be defined either as: - 1. A bilinear map `M × N → R` such that the induced maps `M → Dual R N` and `N → Dual R M` are both - bijective. It follows from this that both `M` and `N` are reflexive modules. - 2. A linear equivalence `N ≃ Dual R M` for which `M` is reflexive. (It then follows that `N` is - reflexive.) - -In this file we provide a `PerfectPairing` definition corresponding to 1 above, together with logic -to connect 1 and 2. - +# Restriction to submodules and restriction of scalars for perfect pairings. +We provide API for restricting perfect pairings to submodules and for restricting their scalars. ## Main definitions - - * `PerfectPairing` - * `PerfectPairing.flip` - * `PerfectPairing.dual` - * `PerfectPairing.toDualLeft` - * `PerfectPairing.toDualRight` - * `PerfectPairing.restrict` - * `PerfectPairing.restrictScalars` - * `LinearEquiv.flip` - * `LinearEquiv.isReflexive_of_equiv_dual_of_isReflexive` - * `LinearEquiv.toPerfectPairing` - + * `PerfectPairing.restrict`: restriction of a perfect pairing to submodules. + * `PerfectPairing.restrictScalars`: restriction of scalars for a perfect pairing taking values in a + subring. + * `PerfectPairing.restrictScalarsField`: restriction of scalars for a perfect pairing taking values + in a subfield. -/ -open Function Module +open Function Module Set +open Submodule (span subset_span) noncomputable section -variable (R M N : Type*) [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] - -/-- A perfect pairing of two (left) modules over a commutative ring. -/ -structure PerfectPairing where - toLin : M →ₗ[R] N →ₗ[R] R - bijectiveLeft : Bijective toLin - bijectiveRight : Bijective toLin.flip - -attribute [nolint docBlame] PerfectPairing.toLin - -variable {R M N} - namespace PerfectPairing -/-- If the coefficients are a field, and one of the spaces is finite-dimensional, it is sufficient -to check only injectivity instead of bijectivity of the bilinear form. -/ -def mkOfInjective {K V W : Type*} - [Field K] [AddCommGroup V] [Module K V] [AddCommGroup W] [Module K W] [FiniteDimensional K V] - (B : V →ₗ[K] W →ₗ[K] K) - (h : Injective B) - (h' : Injective B.flip) : - PerfectPairing K V W where - toLin := B - bijectiveLeft := ⟨h, by rwa [← B.flip_injective_iff₁]⟩ - bijectiveRight := ⟨h', by - have : FiniteDimensional K W := FiniteDimensional.of_injective B.flip h' - rwa [← B.flip.flip_injective_iff₁, LinearMap.flip_flip]⟩ - -/-- If the coefficients are a field, and one of the spaces is finite-dimensional, it is sufficient -to check only injectivity instead of bijectivity of the bilinear form. -/ -def mkOfInjective' {K V W : Type*} - [Field K] [AddCommGroup V] [Module K V] [AddCommGroup W] [Module K W] [FiniteDimensional K W] - (B : V →ₗ[K] W →ₗ[K] K) - (h : Injective B) - (h' : Injective B.flip) : - PerfectPairing K V W where - toLin := B - bijectiveLeft := ⟨h, by - have : FiniteDimensional K V := FiniteDimensional.of_injective B h - rwa [← B.flip_injective_iff₁]⟩ - bijectiveRight := ⟨h', by rwa [← B.flip.flip_injective_iff₁, LinearMap.flip_flip]⟩ - -instance instFunLike : FunLike (PerfectPairing R M N) M (N →ₗ[R] R) where - coe f := f.toLin - coe_injective' x y h := by cases x; cases y; simpa using h - -@[simp] -lemma toLin_apply (p : PerfectPairing R M N) {x : M} : p.toLin x = p x := by - rfl - -variable (p : PerfectPairing R M N) - -/-- Given a perfect pairing between `M` and `N`, we may interchange the roles of `M` and `N`. -/ -protected def flip : PerfectPairing R N M where - toLin := p.toLin.flip - bijectiveLeft := p.bijectiveRight - bijectiveRight := p.bijectiveLeft - -@[simp] -lemma flip_apply_apply {x : M} {y : N} : p.flip y x = p x y := - rfl - -@[simp] -lemma flip_flip : p.flip.flip = p := - rfl - -/-- The linear equivalence from `M` to `Dual R N` induced by a perfect pairing. -/ -def toDualLeft : M ≃ₗ[R] Dual R N := - LinearEquiv.ofBijective p.toLin p.bijectiveLeft - -@[simp] -theorem toDualLeft_apply (a : M) : p.toDualLeft a = p a := - rfl - -@[simp] -theorem apply_toDualLeft_symm_apply (f : Dual R N) (x : N) : p (p.toDualLeft.symm f) x = f x := by - have h := LinearEquiv.apply_symm_apply p.toDualLeft f - rw [toDualLeft_apply] at h - exact congrFun (congrArg DFunLike.coe h) x - -/-- The linear equivalence from `N` to `Dual R M` induced by a perfect pairing. -/ -def toDualRight : N ≃ₗ[R] Dual R M := - toDualLeft p.flip - -@[simp] -theorem toDualRight_apply (a : N) : p.toDualRight a = p.flip a := - rfl - -@[simp] -theorem apply_apply_toDualRight_symm (x : M) (f : Dual R M) : - (p x) (p.toDualRight.symm f) = f x := by - have h := LinearEquiv.apply_symm_apply p.toDualRight f - rw [toDualRight_apply] at h - exact congrFun (congrArg DFunLike.coe h) x +section CommRing -theorem toDualLeft_of_toDualRight_symm (x : M) (f : Dual R M) : - (p.toDualLeft x) (p.toDualRight.symm f) = f x := by - rw [@toDualLeft_apply] - exact apply_apply_toDualRight_symm p x f - -theorem toDualRight_symm_toDualLeft (x : M) : - p.toDualRight.symm.dualMap (p.toDualLeft x) = Dual.eval R M x := by - ext f - simp only [LinearEquiv.dualMap_apply, Dual.eval_apply] - exact toDualLeft_of_toDualRight_symm p x f - -theorem toDualRight_symm_comp_toDualLeft : - p.toDualRight.symm.dualMap ∘ₗ (p.toDualLeft : M →ₗ[R] Dual R N) = Dual.eval R M := by - ext1 x - exact p.toDualRight_symm_toDualLeft x - -theorem bijective_toDualRight_symm_toDualLeft : - Bijective (fun x => p.toDualRight.symm.dualMap (p.toDualLeft x)) := - Bijective.comp (LinearEquiv.bijective p.toDualRight.symm.dualMap) - (LinearEquiv.bijective p.toDualLeft) - -include p in -theorem reflexive_left : IsReflexive R M where - bijective_dual_eval' := by - rw [← p.toDualRight_symm_comp_toDualLeft] - exact p.bijective_toDualRight_symm_toDualLeft - -include p in -theorem reflexive_right : IsReflexive R N := - p.flip.reflexive_left - -instance : EquivLike (PerfectPairing R M N) M (Dual R N) where - coe p := p.toDualLeft - inv p := p.toDualLeft.symm - left_inv p x := LinearEquiv.symm_apply_apply _ _ - right_inv p x := LinearEquiv.apply_symm_apply _ _ - coe_injective' p q h h' := by - cases p - cases q - simp only [mk.injEq] - ext m n - simp only [DFunLike.coe_fn_eq] at h - exact LinearMap.congr_fun (LinearEquiv.congr_fun h m) n - -instance : LinearEquivClass (PerfectPairing R M N) R M (Dual R N) where - map_add p m₁ m₂ := p.toLin.map_add m₁ m₂ - map_smulₛₗ p t m := p.toLin.map_smul t m - -include p in -theorem finrank_eq [Module.Finite R M] [Module.Free R M] : - finrank R M = finrank R N := - ((Module.Free.chooseBasis R M).toDualEquiv.trans p.toDualRight.symm).finrank_eq +variable {R M N : Type*} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] + (p : PerfectPairing R M N) private lemma restrict_aux {M' N' : Type*} [AddCommGroup M'] [Module R M'] [AddCommGroup N'] [Module R N'] @@ -230,63 +73,6 @@ def restrict {M' N' : Type*} [AddCommGroup M'] [Module R M'] [AddCommGroup N'] [ section RestrictScalars -open Submodule (span) - -/-- If a perfect pairing over a field `L` takes values in a subfield `K` along two `K`-subspaces -whose `L` span is full, then these subspaces induce a `K`-structure in the sense of -[*Algebra I*, Bourbaki : Chapter II, §8.1 Definition 1][bourbaki1989]. -/ -lemma exists_basis_basis_of_span_eq_top_of_mem_algebraMap - {K L : Type*} [Field K] [Field L] [Algebra K L] - [Module L M] [Module L N] [Module K M] [Module K N] [IsScalarTower K L M] - (p : PerfectPairing L M N) - (M' : Submodule K M) (N' : Submodule K N) - (hM : span L (M' : Set M) = ⊤) - (hN : span L (N' : Set N) = ⊤) - (hp : ∀ᵉ (x ∈ M') (y ∈ N'), p x y ∈ (algebraMap K L).range) : - ∃ (n : ℕ) (b : Basis (Fin n) L M) (b' : Basis (Fin n) K M'), ∀ i, b i = b' i := by - classical - have : IsReflexive L M := p.reflexive_left - have : IsReflexive L N := p.reflexive_right - obtain ⟨v, hv₁, hv₂, hv₃⟩ := exists_linearIndependent L (M' : Set M) - rw [hM] at hv₂ - let b : Basis _ L M := Basis.mk hv₃ <| by rw [← hv₂, Subtype.range_coe_subtype, Set.setOf_mem_eq] - have : Fintype v := Set.Finite.fintype <| Module.Finite.finite_basis b - set v' : v → M' := fun i ↦ ⟨i, hv₁ (Subtype.coe_prop i)⟩ - have hv' : LinearIndependent K v' := by - replace hv₃ := hv₃.restrict_scalars (R := K) <| by - simp_rw [← Algebra.algebraMap_eq_smul_one] - exact NoZeroSMulDivisors.algebraMap_injective K L - rw [show ((↑) : v → M) = M'.subtype ∘ v' from rfl] at hv₃ - exact hv₃.of_comp - suffices span K (Set.range v') = ⊤ by - let e := (Module.Finite.finite_basis b).equivFin - let b' : Basis _ K M' := Basis.mk hv' (by rw [this]) - exact ⟨_, b.reindex e, b'.reindex e, fun i ↦ by simp [b, b', v']⟩ - suffices span K v = M' by - apply Submodule.map_injective_of_injective M'.injective_subtype - rw [Submodule.map_span, ← Set.image_univ, Set.image_image] - simpa [v'] - refine le_antisymm (Submodule.span_le.mpr hv₁) fun m hm ↦ ?_ - obtain ⟨w, hw₁, hw₂, hw₃⟩ := exists_linearIndependent L (N' : Set N) - rw [hN] at hw₂ - let bN : Basis _ L N := Basis.mk hw₃ <| by rw [← hw₂, Subtype.range_coe_subtype, Set.setOf_mem_eq] - have : Fintype w := Set.Finite.fintype <| Module.Finite.finite_basis bN - have e : v ≃ w := Fintype.equivOfCardEq <| by rw [← Module.finrank_eq_card_basis b, - ← Module.finrank_eq_card_basis bN, p.finrank_eq] - let bM := bN.dualBasis.map p.toDualLeft.symm - have hbM (j : w) (x : M) (hx : x ∈ M') : bM.repr x j = p x (j : N) := by simp [bM, bN] - have hj (j : w) : bM.repr m j ∈ (algebraMap K L).range := (hbM _ _ hm) ▸ hp m hm j (hw₁ j.2) - replace hp (i : w) (j : v) : - (bN.dualBasis.map p.toDualLeft.symm).toMatrix b i j ∈ (algebraMap K L).fieldRange := by - simp only [Basis.toMatrix, Basis.map_repr, LinearEquiv.symm_symm, LinearEquiv.trans_apply, - toDualLeft_apply, Basis.dualBasis_repr] - exact hp (b j) (by simpa [b] using hv₁ j.2) (bN i) (by simpa [bN] using hw₁ i.2) - have hA (i j) : b.toMatrix bM i j ∈ (algebraMap K L).range := - Matrix.mem_subfield_of_mul_eq_one_of_mem_subfield_left e _ (by simp [bM]) hp i j - have h_span : span K v = span K (Set.range b) := by simp [b] - rw [h_span, Basis.mem_span_iff_repr_mem, ← Basis.toMatrix_mulVec_repr bM b m] - exact fun i ↦ Subring.sum_mem _ fun j _ ↦ Subring.mul_mem _ (hA i j) (hj j) - variable {S : Type*} [CommRing S] [Algebra S R] [Module S M] [Module S N] [IsScalarTower S R M] [IsScalarTower S R N] [NoZeroSMulDivisors S R] [Nontrivial R] @@ -352,6 +138,76 @@ def restrictScalars bijectiveRight := ⟨p.flip.restrictScalarsAux_injective j i hj hM (fun m n ↦ hp n m), p.flip.restrictScalarsAux_surjective j i h₂ (fun m n ↦ hp n m)⟩} +end RestrictScalars + +end CommRing + +section Field + +variable {K L M N M : Type*} [Field K] [Field L] [Algebra K L] + [AddCommGroup M] [AddCommGroup N] [Module L M] [Module L N] + [Module K M] [Module K N] [IsScalarTower K L M] + (p : PerfectPairing L M N) + +/-- If a perfect pairing over a field `L` takes values in a subfield `K` along two `K`-subspaces +whose `L` span is full, then these subspaces induce a `K`-structure in the sense of +[*Algebra I*, Bourbaki : Chapter II, §8.1 Definition 1][bourbaki1989]. -/ +lemma exists_basis_basis_of_span_eq_top_of_mem_algebraMap + {K L : Type*} [Field K] [Field L] [Algebra K L] + [Module L M] [Module L N] [Module K M] [Module K N] [IsScalarTower K L M] + (p : PerfectPairing L M N) + (M' : Submodule K M) (N' : Submodule K N) + (hM : span L (M' : Set M) = ⊤) + (hN : span L (N' : Set N) = ⊤) + (hp : ∀ᵉ (x ∈ M') (y ∈ N'), p x y ∈ (algebraMap K L).range) : + ∃ (n : ℕ) (b : Basis (Fin n) L M) (b' : Basis (Fin n) K M'), ∀ i, b i = b' i := by + classical + have : IsReflexive L M := p.reflexive_left + have : IsReflexive L N := p.reflexive_right + obtain ⟨v, hv₁, hv₂, hv₃⟩ := exists_linearIndependent L (M' : Set M) + rw [hM] at hv₂ + let b : Basis _ L M := Basis.mk hv₃ <| by rw [← hv₂, Subtype.range_coe_subtype, Set.setOf_mem_eq] + have : Fintype v := Set.Finite.fintype <| Module.Finite.finite_basis b + set v' : v → M' := fun i ↦ ⟨i, hv₁ (Subtype.coe_prop i)⟩ + have hv' : LinearIndependent K v' := by + replace hv₃ := hv₃.restrict_scalars (R := K) <| by + simp_rw [← Algebra.algebraMap_eq_smul_one] + exact NoZeroSMulDivisors.algebraMap_injective K L + rw [show ((↑) : v → M) = M'.subtype ∘ v' from rfl] at hv₃ + exact hv₃.of_comp + suffices span K (Set.range v') = ⊤ by + let e := (Module.Finite.finite_basis b).equivFin + let b' : Basis _ K M' := Basis.mk hv' (by rw [this]) + exact ⟨_, b.reindex e, b'.reindex e, fun i ↦ by simp [b, b', v']⟩ + suffices span K v = M' by + apply Submodule.map_injective_of_injective M'.injective_subtype + rw [Submodule.map_span, ← Set.image_univ, Set.image_image] + simpa [v'] + refine le_antisymm (Submodule.span_le.mpr hv₁) fun m hm ↦ ?_ + obtain ⟨w, hw₁, hw₂, hw₃⟩ := exists_linearIndependent L (N' : Set N) + rw [hN] at hw₂ + let bN : Basis _ L N := Basis.mk hw₃ <| by rw [← hw₂, Subtype.range_coe_subtype, Set.setOf_mem_eq] + have : Fintype w := Set.Finite.fintype <| Module.Finite.finite_basis bN + have e : v ≃ w := Fintype.equivOfCardEq <| by rw [← Module.finrank_eq_card_basis b, + ← Module.finrank_eq_card_basis bN, p.finrank_eq] + let bM := bN.dualBasis.map p.toDualLeft.symm + have hbM (j : w) (x : M) (hx : x ∈ M') : bM.repr x j = p x (j : N) := by simp [bM, bN] + have hj (j : w) : bM.repr m j ∈ (algebraMap K L).range := (hbM _ _ hm) ▸ hp m hm j (hw₁ j.2) + replace hp (i : w) (j : v) : + (bN.dualBasis.map p.toDualLeft.symm).toMatrix b i j ∈ (algebraMap K L).fieldRange := by + simp only [Basis.toMatrix, Basis.map_repr, LinearEquiv.symm_symm, LinearEquiv.trans_apply, + toDualLeft_apply, Basis.dualBasis_repr] + exact hp (b j) (by simpa [b] using hv₁ j.2) (bN i) (by simpa [bN] using hw₁ i.2) + have hA (i j) : b.toMatrix bM i j ∈ (algebraMap K L).range := + Matrix.mem_subfield_of_mul_eq_one_of_mem_subfield_left e _ (by simp [bM]) hp i j + have h_span : span K v = span K (Set.range b) := by simp [b] + rw [h_span, Basis.mem_span_iff_repr_mem, ← Basis.toMatrix_mulVec_repr bM b m] + exact fun i ↦ Subring.sum_mem _ fun j _ ↦ Subring.mul_mem _ (hA i j) (hj j) + +variable {M' N' : Type*} + [AddCommGroup M'] [AddCommGroup N'] [Module K M'] [Module K N'] [IsScalarTower K L N] + (i : M' →ₗ[K] M) (j : N' →ₗ[K] N) (hi : Injective i) (hj : Injective j) + /-- Restriction of scalars for a perfect pairing taking values in a subfield. -/ def restrictScalarsField {K L : Type*} [Field K] [Field L] [Algebra K L] [Module L M] [Module L N] [Module K M] [Module K N] [IsScalarTower K L M] [IsScalarTower K L N] @@ -371,97 +227,6 @@ def restrictScalarsField {K L : Type*} [Field K] [Field L] [Algebra K L] have : FiniteDimensional K (LinearMap.range i) := FiniteDimensional.of_fintype_basis b' exact Finite.equiv (LinearEquiv.ofInjective i hi).symm -end RestrictScalars +end Field end PerfectPairing - -variable [IsReflexive R M] - -/-- A reflexive module has a perfect pairing with its dual. -/ -@[simps] -def IsReflexive.toPerfectPairingDual : PerfectPairing R (Dual R M) M where - toLin := LinearMap.id - 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 - -/-- For a reflexive module `M`, an equivalence `N ≃ₗ[R] Dual R M` naturally yields an equivalence -`M ≃ₗ[R] Dual R N`. Such equivalences are known as perfect pairings. -/ -def flip : M ≃ₗ[R] Dual R N := - (evalEquiv R M).trans e.dualMap - -@[simp] lemma coe_toLinearMap_flip : e.flip = (↑e : N →ₗ[R] Dual R M).flip := rfl - -@[simp] lemma flip_apply (m : M) (n : N) : e.flip m n = e n m := rfl - -lemma symm_flip : e.flip.symm = e.symm.dualMap.trans (evalEquiv R M).symm := rfl - -lemma trans_dualMap_symm_flip : e.trans e.flip.symm.dualMap = Dual.eval R N := by - ext; simp [symm_flip] - -include e in -/-- If `N` is in perfect pairing with `M`, then it is reflexive. -/ -lemma isReflexive_of_equiv_dual_of_isReflexive : IsReflexive R N := by - constructor - rw [← trans_dualMap_symm_flip e] - exact LinearEquiv.bijective _ - -@[simp] lemma flip_flip (h : IsReflexive R N := isReflexive_of_equiv_dual_of_isReflexive e) : - e.flip.flip = e := by - ext; rfl - -/-- If `M` is reflexive then a linear equivalence `N ≃ Dual R M` is a perfect pairing. -/ -@[simps] -def toPerfectPairing : PerfectPairing R N M where - toLin := e - bijectiveLeft := e.bijective - bijectiveRight := e.flip.bijective - -end LinearEquiv - -/-- A perfect pairing induces a perfect pairing between dual spaces. -/ -def PerfectPairing.dual (p : PerfectPairing R M N) : - PerfectPairing R (Dual R M) (Dual R N) := - let _i := p.reflexive_right - (p.toDualRight.symm.trans (evalEquiv R N)).toPerfectPairing - -namespace Submodule - -open LinearEquiv - -@[simp] -lemma dualCoannihilator_map_linearEquiv_flip (p : Submodule R M) : - (p.map e.flip).dualCoannihilator = p.dualAnnihilator.map e.symm := by - ext; simp [LinearEquiv.symm_apply_eq, Submodule.mem_dualCoannihilator] - -@[simp] -lemma map_dualAnnihilator_linearEquiv_flip_symm (p : Submodule R N) : - p.dualAnnihilator.map e.flip.symm = (p.map e).dualCoannihilator := by - have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive - rw [← dualCoannihilator_map_linearEquiv_flip, flip_flip] - -@[simp] -lemma map_dualCoannihilator_linearEquiv_flip (p : Submodule R (Dual R M)) : - p.dualCoannihilator.map e.flip = (p.map e.symm).dualAnnihilator := by - have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive - suffices (p.map e.symm).dualAnnihilator.map e.flip.symm = - (p.dualCoannihilator.map e.flip).map e.flip.symm by - exact (Submodule.map_injective_of_injective e.flip.symm.injective this).symm - erw [← dualCoannihilator_map_linearEquiv_flip, flip_flip, ← map_comp, ← map_comp] - simp [-coe_toLinearMap_flip] - -@[simp] -lemma dualAnnihilator_map_linearEquiv_flip_symm (p : Submodule R (Dual R N)) : - (p.map e.flip.symm).dualAnnihilator = p.dualCoannihilator.map e := by - have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive - rw [← map_dualCoannihilator_linearEquiv_flip, flip_flip] - -end Submodule diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index 586c5dbb3ee6e..eaaf04a6c7bfd 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash, Deepro Choudhury, Scott Carnahan -/ -import Mathlib.LinearAlgebra.PerfectPairing +import Mathlib.LinearAlgebra.PerfectPairing.Basic import Mathlib.LinearAlgebra.Reflection /-! From 0c82aa8fcc382d16b6a8b7a33f806906fb0c8a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Wed, 15 Jan 2025 23:14:29 +0000 Subject: [PATCH 255/681] refactor: move files from `AlgebraicGeometry/PrimeSpectrum` to `RingTheory/Spectrum/Prime` (#20778) Move files from `AlgebraicGeometry/PrimeSpectrum` to `RingTheory/Spectrum/Prime` with renaming `Basic.lean` to `Topology.lean` as discussed [here](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Maximal.20spectrum.20of.20a.20ring). Move `RingTheory/Spectrum/Prime/Maximal.lean` to `RingTheory/Spectrum/Maximal/Topology.lean` for consistency. --- Mathlib.lean | 18 +++++++++--------- .../Morphisms/SurjectiveOnStalks.lean | 2 +- Mathlib/AlgebraicGeometry/Noetherian.lean | 2 +- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 2 +- Mathlib/RingTheory/Spectrum/Maximal/Basic.lean | 5 ----- .../Spectrum/Maximal/Topology.lean} | 12 ++---------- Mathlib/RingTheory/Spectrum/Prime/Basic.lean | 6 +++--- Mathlib/RingTheory/Spectrum/Prime/Defs.lean | 4 ++-- .../Spectrum/Prime}/FreeLocus.lean | 2 +- .../Spectrum/Prime}/IsOpenComapC.lean | 2 +- .../Spectrum/Prime}/Jacobson.lean | 2 +- .../Spectrum/Prime}/Module.lean | 2 +- .../Spectrum/Prime}/Noetherian.lean | 2 +- .../Spectrum/Prime}/Polynomial.lean | 2 +- .../Spectrum/Prime}/TensorProduct.lean | 2 +- .../Spectrum/Prime/Topology.lean} | 0 Mathlib/RingTheory/Support.lean | 6 +++--- Mathlib/RingTheory/Unramified/Locus.lean | 2 +- 18 files changed, 30 insertions(+), 43 deletions(-) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum/Maximal.lean => RingTheory/Spectrum/Maximal/Topology.lean} (79%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum => RingTheory/Spectrum/Prime}/FreeLocus.lean (99%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum => RingTheory/Spectrum/Prime}/IsOpenComapC.lean (98%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum => RingTheory/Spectrum/Prime}/Jacobson.lean (98%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum => RingTheory/Spectrum/Prime}/Module.lean (97%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum => RingTheory/Spectrum/Prime}/Noetherian.lean (95%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum => RingTheory/Spectrum/Prime}/Polynomial.lean (99%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum => RingTheory/Spectrum/Prime}/TensorProduct.lean (98%) rename Mathlib/{AlgebraicGeometry/PrimeSpectrum/Basic.lean => RingTheory/Spectrum/Prime/Topology.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 55f6e8d3c51a2..4188d8cbdc588 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1030,15 +1030,6 @@ import Mathlib.AlgebraicGeometry.Morphisms.UniversallyInjective import Mathlib.AlgebraicGeometry.Noetherian import Mathlib.AlgebraicGeometry.OpenImmersion import Mathlib.AlgebraicGeometry.Over -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic -import Mathlib.AlgebraicGeometry.PrimeSpectrum.FreeLocus -import Mathlib.AlgebraicGeometry.PrimeSpectrum.IsOpenComapC -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Jacobson -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Maximal -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Module -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Noetherian -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Polynomial -import Mathlib.AlgebraicGeometry.PrimeSpectrum.TensorProduct import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Basic import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Proper import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Scheme @@ -4705,8 +4696,17 @@ import Mathlib.RingTheory.Smooth.Pi import Mathlib.RingTheory.Smooth.StandardSmooth import Mathlib.RingTheory.Spectrum.Maximal.Basic import Mathlib.RingTheory.Spectrum.Maximal.Defs +import Mathlib.RingTheory.Spectrum.Maximal.Topology import Mathlib.RingTheory.Spectrum.Prime.Basic import Mathlib.RingTheory.Spectrum.Prime.Defs +import Mathlib.RingTheory.Spectrum.Prime.FreeLocus +import Mathlib.RingTheory.Spectrum.Prime.IsOpenComapC +import Mathlib.RingTheory.Spectrum.Prime.Jacobson +import Mathlib.RingTheory.Spectrum.Prime.Module +import Mathlib.RingTheory.Spectrum.Prime.Noetherian +import Mathlib.RingTheory.Spectrum.Prime.Polynomial +import Mathlib.RingTheory.Spectrum.Prime.TensorProduct +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.RingTheory.Support import Mathlib.RingTheory.SurjectiveOnStalks import Mathlib.RingTheory.TensorProduct.Basic diff --git a/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean index b48dcf53606e8..3d2e4bc11f7d8 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.Morphisms.RingHomProperties -import Mathlib.AlgebraicGeometry.PrimeSpectrum.TensorProduct +import Mathlib.RingTheory.Spectrum.Prime.TensorProduct import Mathlib.Topology.LocalAtTarget /-! diff --git a/Mathlib/AlgebraicGeometry/Noetherian.lean b/Mathlib/AlgebraicGeometry/Noetherian.lean index 6fbbeea98d0dc..7d1c4fff13747 100644 --- a/Mathlib/AlgebraicGeometry/Noetherian.lean +++ b/Mathlib/AlgebraicGeometry/Noetherian.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Geno Racklin Asher -/ import Mathlib.AlgebraicGeometry.Morphisms.QuasiSeparated -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Noetherian import Mathlib.RingTheory.Localization.Submodule +import Mathlib.RingTheory.Spectrum.Prime.Noetherian /-! # Noetherian and Locally Noetherian Schemes diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index b3cc9a3607da4..97504a41cbdea 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -7,8 +7,8 @@ import Mathlib.Algebra.Category.Ring.Colimits import Mathlib.Algebra.Category.Ring.Instances import Mathlib.Algebra.Category.Ring.Limits import Mathlib.Algebra.Ring.Subring.Basic -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic import Mathlib.RingTheory.Localization.AtPrime +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.Topology.Sheaves.LocalPredicate /-! diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean index b20eb41fd1340..a4d369561f3f8 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean @@ -11,11 +11,6 @@ import Mathlib.RingTheory.Spectrum.Prime.Basic # Maximal spectrum of a commutative (semi)ring Basic properties the maximal spectrum of a ring. - -## Implementation notes - -The Zariski topology on the maximal spectrum is defined as the subspace topology induced by the -natural inclusion into the prime spectrum to avoid API duplication for zero loci. -/ noncomputable section diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Maximal.lean b/Mathlib/RingTheory/Spectrum/Maximal/Topology.lean similarity index 79% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/Maximal.lean rename to Mathlib/RingTheory/Spectrum/Maximal/Topology.lean index bcf8cff5c9c80..56fc46274a3f4 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Maximal.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Topology.lean @@ -3,19 +3,11 @@ Copyright (c) 2022 David Kurniadi Angdinata. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Kurniadi Angdinata -/ -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic import Mathlib.RingTheory.Spectrum.Maximal.Basic +import Mathlib.RingTheory.Spectrum.Prime.Topology /-! -# Maximal spectrum of a commutative ring - -The maximal spectrum of a commutative ring is the type of all maximal ideals. -It is naturally a subset of the prime spectrum endowed with the subspace topology. - -## Main definitions - -* `MaximalSpectrum R`: The maximal spectrum of a commutative ring `R`, - i.e., the set of all maximal ideals of `R`. +# The Zariski topology on the maximal spectrum of a commutative (semi)ring ## Implementation notes diff --git a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean index de8131c375121..eb955307cdc44 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean @@ -13,7 +13,7 @@ import Mathlib.RingTheory.Spectrum.Prime.Defs /-! # Prime spectrum of a commutative (semi)ring -For the Zariski topology, see `AlgebraicGeometry.PrimeSpectrum.Basic`. +For the Zariski topology, see `Mathlib.RingTheory.Spectrum.Prime.Topology`. (It is also naturally endowed with a sheaf of rings, which is constructed in `AlgebraicGeometry.StructureSheaf`.) @@ -37,7 +37,7 @@ which has contributions from Ramon Fernandez Mir, Kevin Buzzard, Kenny Lau, and Chris Hughes (on an earlier repository). -/ --- A dividing line between this file and `AlgebraicGeometry.PrimeSpectrum.Basic` is +-- A dividing line between this file and `Mathlib.RingTheory.Spectrum.Prime.Topology` is -- that we should not depend on the Zariski topology here assert_not_exists TopologicalSpace @@ -375,7 +375,7 @@ section Order We endow `PrimeSpectrum R` with a partial order induced from the ideal lattice. This is exactly the specialization order. -See the corresponding section at `Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic`. +See the corresponding section at `Mathlib.RingTheory.Spectrum.Prime.Topology`. -/ instance : PartialOrder (PrimeSpectrum R) := diff --git a/Mathlib/RingTheory/Spectrum/Prime/Defs.lean b/Mathlib/RingTheory/Spectrum/Prime/Defs.lean index 48a06e9acaae1..93e0da1ca6ac5 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Defs.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Defs.lean @@ -10,7 +10,7 @@ import Mathlib.RingTheory.Ideal.Prime The prime spectrum of a commutative (semi)ring is the type of all prime ideals. -For the Zariski topology, see `AlgebraicGeometry.PrimeSpectrum.Basic`. +For the Zariski topology, see `Mathlib.RingTheory.Spectrum.Prime.Topology`. (It is also naturally endowed with a sheaf of rings, which is constructed in `AlgebraicGeometry.StructureSheaf`.) @@ -24,7 +24,7 @@ which is constructed in `AlgebraicGeometry.StructureSheaf`.) /-- The prime spectrum of a commutative (semi)ring `R` is the type of all prime ideals of `R`. It is naturally endowed with a topology (the Zariski topology), -and a sheaf of commutative rings (see `AlgebraicGeometry.StructureSheaf`). +and a sheaf of commutative rings (see `Mathlib.AlgebraicGeometry.StructureSheaf`). It is a fundamental building block in algebraic geometry. -/ @[ext] structure PrimeSpectrum (R : Type*) [CommSemiring R] where diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/FreeLocus.lean b/Mathlib/RingTheory/Spectrum/Prime/FreeLocus.lean similarity index 99% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/FreeLocus.lean rename to Mathlib/RingTheory/Spectrum/Prime/FreeLocus.lean index 8389295b32ac8..939f333072fac 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/FreeLocus.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/FreeLocus.lean @@ -3,12 +3,12 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic import Mathlib.RingTheory.Flat.Stability import Mathlib.RingTheory.LocalProperties.Projective import Mathlib.RingTheory.LocalRing.Module import Mathlib.RingTheory.Localization.Free import Mathlib.RingTheory.Localization.LocalizationLocalization +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.Topology.LocallyConstant.Basic import Mathlib.RingTheory.TensorProduct.Free diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/IsOpenComapC.lean b/Mathlib/RingTheory/Spectrum/Prime/IsOpenComapC.lean similarity index 98% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/IsOpenComapC.lean rename to Mathlib/RingTheory/Spectrum/Prime/IsOpenComapC.lean index 2c57736efcf0b..4a6c542cd5693 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/IsOpenComapC.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/IsOpenComapC.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic import Mathlib.RingTheory.Polynomial.Basic +import Mathlib.RingTheory.Spectrum.Prime.Topology /-! The morphism `Spec R[x] --> Spec R` induced by the natural inclusion `R --> R[x]` is an open map. diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Jacobson.lean b/Mathlib/RingTheory/Spectrum/Prime/Jacobson.lean similarity index 98% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/Jacobson.lean rename to Mathlib/RingTheory/Spectrum/Prime/Jacobson.lean index f7cf9b2d50040..22a0235463575 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Jacobson.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Jacobson.lean @@ -3,8 +3,8 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Noetherian import Mathlib.RingTheory.Jacobson.Ring +import Mathlib.RingTheory.Spectrum.Prime.Noetherian import Mathlib.Topology.JacobsonSpace /-! diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Module.lean b/Mathlib/RingTheory/Spectrum/Prime/Module.lean similarity index 97% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/Module.lean rename to Mathlib/RingTheory/Spectrum/Prime/Module.lean index c87937b5d6fd7..e7f608704c4c8 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Module.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Module.lean @@ -3,8 +3,8 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.RingTheory.Support -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic /-! diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean b/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean similarity index 95% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean rename to Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean index 54db36be2f8f2..c388f7d7331b7 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Filippo A. E. Nuccio. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Filippo A. E. Nuccio, Andrew Yang -/ -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.Topology.NoetherianSpace /-! diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Polynomial.lean b/Mathlib/RingTheory/Spectrum/Prime/Polynomial.lean similarity index 99% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/Polynomial.lean rename to Mathlib/RingTheory/Spectrum/Prime/Polynomial.lean index a9e0767866f44..ef44d600253f3 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Polynomial.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Polynomial.lean @@ -3,11 +3,11 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic import Mathlib.LinearAlgebra.Charpoly.BaseChange import Mathlib.LinearAlgebra.Eigenspace.Zero import Mathlib.RingTheory.AdjoinRoot import Mathlib.RingTheory.LocalRing.ResidueField.Ideal +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.RingTheory.TensorProduct.MvPolynomial /-! diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/TensorProduct.lean b/Mathlib/RingTheory/Spectrum/Prime/TensorProduct.lean similarity index 98% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/TensorProduct.lean rename to Mathlib/RingTheory/Spectrum/Prime/TensorProduct.lean index dce18ae5367d7..03393c92f5a1e 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/TensorProduct.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/TensorProduct.lean @@ -3,8 +3,8 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.RingTheory.SurjectiveOnStalks -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic /-! diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/RingTheory/Spectrum/Prime/Topology.lean similarity index 100% rename from Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean rename to Mathlib/RingTheory/Spectrum/Prime/Topology.lean diff --git a/Mathlib/RingTheory/Support.lean b/Mathlib/RingTheory/Support.lean index 1048aa13ccabc..cbb8bb690f8a4 100644 --- a/Mathlib/RingTheory/Support.lean +++ b/Mathlib/RingTheory/Support.lean @@ -21,8 +21,8 @@ import Mathlib.Algebra.Module.LocalizedModule.Basic - `LocalizedModule.exists_subsingleton_away`: If `M` is `R`-finite and `Mₚ = 0`, then `M[1/f] = 0` for some `p ∈ D(f)`. -Also see `AlgebraicGeometry/PrimeSpectrum/Module` for other results -depending on the zariski topology. +Also see `Mathlib.RingTheory.Spectrum.Prime.Module` for other results +depending on the Zariski topology. ## TODO - Connect to associated primes once we have them in mathlib. @@ -31,7 +31,7 @@ depending on the zariski topology. -/ -- Basic files in `RingTheory` should avoid depending on the Zariski topology --- See `AlgebraicGeometry/PrimeSpectrum/Module` +-- See `Mathlib.RingTheory.Spectrum.Prime.Module` assert_not_exists TopologicalSpace variable {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] {p : PrimeSpectrum R} diff --git a/Mathlib/RingTheory/Unramified/Locus.lean b/Mathlib/RingTheory/Unramified/Locus.lean index ec9cd9995a51e..44a5e740a4e0b 100644 --- a/Mathlib/RingTheory/Unramified/Locus.lean +++ b/Mathlib/RingTheory/Unramified/Locus.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ -import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic +import Mathlib.RingTheory.Spectrum.Prime.Topology import Mathlib.RingTheory.Etale.Kaehler import Mathlib.RingTheory.Support From 806f25718d02f849481421111a4c8db0c2da86b5 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 16 Jan 2025 00:33:41 +0000 Subject: [PATCH 256/681] chore: move Algebra/Group/ZeroOne/ to Data/ (#20622) Minor cleanup on the path to reducing dependencies from Data/ on other top-level directories. --- Mathlib.lean | 3 +- Mathlib/Algebra/Expr.lean | 2 +- Mathlib/Algebra/Group/Defs.lean | 2 +- Mathlib/Algebra/NeZero.lean | 2 +- Mathlib/Algebra/Order/Pi.lean | 1 + Mathlib/Algebra/Order/ZeroLEOne.lean | 1 + Mathlib/Algebra/ZeroOne/Lemmas.lean | 51 +++++++++++++++++++ Mathlib/Data/Num/Basic.lean | 2 +- .../Group/ZeroOne.lean => Data/One/Defs.lean} | 0 Mathlib/Data/PNat/Defs.lean | 1 + Mathlib/Data/Set/Basic.lean | 2 +- Mathlib/Data/Set/SymmDiff.lean | 2 +- Mathlib/Order/Basic.lean | 39 -------------- Mathlib/Tactic/Bound/Attribute.lean | 15 +++--- MathlibTest/byContra.lean | 1 + scripts/noshake.json | 2 + 16 files changed, 72 insertions(+), 54 deletions(-) create mode 100644 Mathlib/Algebra/ZeroOne/Lemmas.lean rename Mathlib/{Algebra/Group/ZeroOne.lean => Data/One/Defs.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 4188d8cbdc588..e646e831d9f6d 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -373,7 +373,6 @@ import Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.Group.Units.Opposite import Mathlib.Algebra.Group.WithOne.Basic import Mathlib.Algebra.Group.WithOne.Defs -import Mathlib.Algebra.Group.ZeroOne import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.Algebra.GroupWithZero.Action.Basic import Mathlib.Algebra.GroupWithZero.Action.Defs @@ -979,6 +978,7 @@ import Mathlib.Algebra.Tropical.BigOperators import Mathlib.Algebra.Tropical.Lattice import Mathlib.Algebra.Vertex.HVertexOperator import Mathlib.Algebra.Vertex.VertexOperator +import Mathlib.Algebra.ZeroOne.Lemmas import Mathlib.AlgebraicGeometry.AffineScheme import Mathlib.AlgebraicGeometry.AffineSpace import Mathlib.AlgebraicGeometry.Cover.MorphismProperty @@ -2846,6 +2846,7 @@ import Mathlib.Data.Num.Basic import Mathlib.Data.Num.Bitwise import Mathlib.Data.Num.Lemmas import Mathlib.Data.Num.Prime +import Mathlib.Data.One.Defs import Mathlib.Data.Opposite import Mathlib.Data.Option.Basic import Mathlib.Data.Option.Defs diff --git a/Mathlib/Algebra/Expr.lean b/Mathlib/Algebra/Expr.lean index df4e9330035a2..e7e2b0d79d3d9 100644 --- a/Mathlib/Algebra/Expr.lean +++ b/Mathlib/Algebra/Expr.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Algebra.Group.ZeroOne +import Mathlib.Data.One.Defs import Qq /-! # Helpers to invoke functions involving algebra at tactic time diff --git a/Mathlib/Algebra/Group/Defs.lean b/Mathlib/Algebra/Group/Defs.lean index 93ba85d9f7ca2..a3e6f1b235fd1 100644 --- a/Mathlib/Algebra/Group/Defs.lean +++ b/Mathlib/Algebra/Group/Defs.lean @@ -5,7 +5,7 @@ Authors: Jeremy Avigad, Leonardo de Moura, Simon Hudon, Mario Carneiro -/ import Mathlib.Data.Int.Notation import Mathlib.Data.Nat.BinaryRec -import Mathlib.Algebra.Group.ZeroOne +import Mathlib.Data.One.Defs import Mathlib.Algebra.Group.Operations import Mathlib.Logic.Function.Defs import Mathlib.Tactic.Simps.Basic diff --git a/Mathlib/Algebra/NeZero.lean b/Mathlib/Algebra/NeZero.lean index 35ba9754734ce..3c13f43278acf 100644 --- a/Mathlib/Algebra/NeZero.lean +++ b/Mathlib/Algebra/NeZero.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Rodriguez -/ import Mathlib.Logic.Basic -import Mathlib.Algebra.Group.ZeroOne +import Mathlib.Data.One.Defs import Mathlib.Order.Defs.PartialOrder /-! diff --git a/Mathlib/Algebra/Order/Pi.lean b/Mathlib/Algebra/Order/Pi.lean index 601b52a20fee9..da715df7e1d66 100644 --- a/Mathlib/Algebra/Order/Pi.lean +++ b/Mathlib/Algebra/Order/Pi.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon, Patrick Massot -/ +import Mathlib.Algebra.ZeroOne.Lemmas import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Ring.Pi diff --git a/Mathlib/Algebra/Order/ZeroLEOne.lean b/Mathlib/Algebra/Order/ZeroLEOne.lean index 538c8f6985b42..ccb9eefbcdbe0 100644 --- a/Mathlib/Algebra/Order/ZeroLEOne.lean +++ b/Mathlib/Algebra/Order/ZeroLEOne.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ import Mathlib.Order.Basic +import Mathlib.Data.One.Defs /-! # Typeclass expressing `0 ≤ 1`. diff --git a/Mathlib/Algebra/ZeroOne/Lemmas.lean b/Mathlib/Algebra/ZeroOne/Lemmas.lean new file mode 100644 index 0000000000000..fb46386ea2182 --- /dev/null +++ b/Mathlib/Algebra/ZeroOne/Lemmas.lean @@ -0,0 +1,51 @@ +/- +Copyright (c) 2023 Yael Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yael Dillies +-/ +import Batteries.Tactic.Init +import Mathlib.Data.One.Defs +import Mathlib.Tactic.ToAdditive +import Mathlib.Tactic.Lemma + +/-! # Lemmas about inequalities with `1`. -/ + +variable {α : Type _} + +section dite +variable [One α] {p : Prop} [Decidable p] {a : p → α} {b : ¬ p → α} + +@[to_additive dite_nonneg] +lemma one_le_dite [LE α] (ha : ∀ h, 1 ≤ a h) (hb : ∀ h, 1 ≤ b h) : 1 ≤ dite p a b := by + split; exacts [ha ‹_›, hb ‹_›] + +@[to_additive] +lemma dite_le_one [LE α] (ha : ∀ h, a h ≤ 1) (hb : ∀ h, b h ≤ 1) : dite p a b ≤ 1 := by + split; exacts [ha ‹_›, hb ‹_›] + +@[to_additive dite_pos] +lemma one_lt_dite [LT α] (ha : ∀ h, 1 < a h) (hb : ∀ h, 1 < b h) : 1 < dite p a b := by + split; exacts [ha ‹_›, hb ‹_›] + +@[to_additive] +lemma dite_lt_one [LT α] (ha : ∀ h, a h < 1) (hb : ∀ h, b h < 1) : dite p a b < 1 := by + split; exacts [ha ‹_›, hb ‹_›] + +end dite + +section +variable [One α] {p : Prop} [Decidable p] {a b : α} + +@[to_additive ite_nonneg] +lemma one_le_ite [LE α] (ha : 1 ≤ a) (hb : 1 ≤ b) : 1 ≤ ite p a b := by split <;> assumption + +@[to_additive] +lemma ite_le_one [LE α] (ha : a ≤ 1) (hb : b ≤ 1) : ite p a b ≤ 1 := by split <;> assumption + +@[to_additive ite_pos] +lemma one_lt_ite [LT α] (ha : 1 < a) (hb : 1 < b) : 1 < ite p a b := by split <;> assumption + +@[to_additive] +lemma ite_lt_one [LT α] (ha : a < 1) (hb : b < 1) : ite p a b < 1 := by split <;> assumption + +end diff --git a/Mathlib/Data/Num/Basic.lean b/Mathlib/Data/Num/Basic.lean index 25e1a56167888..3368287a5e296 100644 --- a/Mathlib/Data/Num/Basic.lean +++ b/Mathlib/Data/Num/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Mario Carneiro -/ import Lean.Linter.Deprecated -import Mathlib.Algebra.Group.ZeroOne +import Mathlib.Data.One.Defs import Mathlib.Data.Int.Notation import Mathlib.Data.Nat.BinaryRec import Mathlib.Tactic.TypeStar diff --git a/Mathlib/Algebra/Group/ZeroOne.lean b/Mathlib/Data/One/Defs.lean similarity index 100% rename from Mathlib/Algebra/Group/ZeroOne.lean rename to Mathlib/Data/One/Defs.lean diff --git a/Mathlib/Data/PNat/Defs.lean b/Mathlib/Data/PNat/Defs.lean index f1b5d5d414da3..bf3caf69054f7 100644 --- a/Mathlib/Data/PNat/Defs.lean +++ b/Mathlib/Data/PNat/Defs.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro, Neil Strickland -/ import Mathlib.Data.Nat.Defs import Mathlib.Data.PNat.Notation +import Mathlib.Data.One.Defs import Mathlib.Order.Basic import Mathlib.Tactic.Coe import Mathlib.Tactic.Lift diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 4b7c21083afe3..3ca8906f367ae 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ -import Mathlib.Algebra.Group.ZeroOne +import Mathlib.Data.One.Defs import Mathlib.Data.Set.Operations import Mathlib.Order.Basic import Mathlib.Order.BooleanAlgebra diff --git a/Mathlib/Data/Set/SymmDiff.lean b/Mathlib/Data/Set/SymmDiff.lean index 413d38cb10668..e0e409b5ac694 100644 --- a/Mathlib/Data/Set/SymmDiff.lean +++ b/Mathlib/Data/Set/SymmDiff.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ -import Mathlib.Algebra.Group.ZeroOne +import Mathlib.Data.One.Defs import Mathlib.Data.Set.Operations import Mathlib.Order.Basic import Mathlib.Order.BooleanAlgebra diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index 2db0d82f5aeed..0f96648eca68c 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Algebra.Group.ZeroOne import Mathlib.Data.Subtype import Mathlib.Order.Defs.LinearOrder import Mathlib.Order.Notation @@ -1375,41 +1374,3 @@ noncomputable instance AsLinearOrder.linearOrder [PartialOrder α] [IsTotal α ( __ := inferInstanceAs (PartialOrder α) le_total := @total_of α (· ≤ ·) _ decidableLE := Classical.decRel _ - -section dite -variable [One α] {p : Prop} [Decidable p] {a : p → α} {b : ¬ p → α} - -@[to_additive dite_nonneg] -lemma one_le_dite [LE α] (ha : ∀ h, 1 ≤ a h) (hb : ∀ h, 1 ≤ b h) : 1 ≤ dite p a b := by - split; exacts [ha ‹_›, hb ‹_›] - -@[to_additive] -lemma dite_le_one [LE α] (ha : ∀ h, a h ≤ 1) (hb : ∀ h, b h ≤ 1) : dite p a b ≤ 1 := by - split; exacts [ha ‹_›, hb ‹_›] - -@[to_additive dite_pos] -lemma one_lt_dite [LT α] (ha : ∀ h, 1 < a h) (hb : ∀ h, 1 < b h) : 1 < dite p a b := by - split; exacts [ha ‹_›, hb ‹_›] - -@[to_additive] -lemma dite_lt_one [LT α] (ha : ∀ h, a h < 1) (hb : ∀ h, b h < 1) : dite p a b < 1 := by - split; exacts [ha ‹_›, hb ‹_›] - -end dite - -section -variable [One α] {p : Prop} [Decidable p] {a b : α} - -@[to_additive ite_nonneg] -lemma one_le_ite [LE α] (ha : 1 ≤ a) (hb : 1 ≤ b) : 1 ≤ ite p a b := by split <;> assumption - -@[to_additive] -lemma ite_le_one [LE α] (ha : a ≤ 1) (hb : b ≤ 1) : ite p a b ≤ 1 := by split <;> assumption - -@[to_additive ite_pos] -lemma one_lt_ite [LT α] (ha : 1 < a) (hb : 1 < b) : 1 < ite p a b := by split <;> assumption - -@[to_additive] -lemma ite_lt_one [LT α] (ha : a < 1) (hb : b < 1) : ite p a b < 1 := by split <;> assumption - -end diff --git a/Mathlib/Tactic/Bound/Attribute.lean b/Mathlib/Tactic/Bound/Attribute.lean index 83685e229820e..a33c21e26456f 100644 --- a/Mathlib/Tactic/Bound/Attribute.lean +++ b/Mathlib/Tactic/Bound/Attribute.lean @@ -3,7 +3,6 @@ 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.Algebra.Group.ZeroOne import Mathlib.Tactic.Bound.Init import Qq import Aesop @@ -32,11 +31,11 @@ def isZero (e : Q($α)) : MetaM Bool := | _ => return false /-- Map the arguments of an inequality expression to a score -/ -def ineqPriority (a b : Q($α)) : MetaM ℕ := do +def ineqPriority (a b : Q($α)) : MetaM Nat := do return if (← isZero a) || (← isZero b) then 1 else 10 /-- Map a hypothesis type to a score -/ -partial def hypPriority (hyp : Q(Prop)) : MetaM ℕ := do +partial def hypPriority (hyp : Q(Prop)) : MetaM Nat := do match hyp with -- Conjunctions add scores | ~q($a ∧ $b) => pure <| (← hypPriority a) + (← hypPriority b) @@ -51,13 +50,13 @@ partial def hypPriority (hyp : Q(Prop)) : MetaM ℕ := do | _ => pure 0 /-- Map a type to a score -/ -def typePriority (decl : Lean.Name) (type : Lean.Expr) : MetaM ℕ := +def typePriority (decl : Lean.Name) (type : Lean.Expr) : MetaM Nat := Lean.Meta.forallTelescope type fun xs t ↦ do checkResult t - xs.foldlM (fun (t : ℕ) x ↦ do return t + (← argPriority x)) 0 + xs.foldlM (fun (t : Nat) x ↦ do return t + (← argPriority x)) 0 where /-- Score the type of argument `x` -/ - argPriority (x : Lean.Expr) : MetaM ℕ := do + argPriority (x : Lean.Expr) : MetaM Nat := do hypPriority (← Lean.Meta.inferType x) /-- Insist that our conclusion is an inequality -/ checkResult (t : Q(Prop)) : MetaM Unit := do match t with @@ -69,14 +68,14 @@ def typePriority (decl : Lean.Name) (type : Lean.Expr) : MetaM ℕ := it should be an inequality") /-- Map a theorem decl to a score (0 means `norm apply`, `0 <` means `safe apply`) -/ -def declPriority (decl : Lean.Name) : Lean.MetaM ℕ := do +def declPriority (decl : Lean.Name) : Lean.MetaM Nat := do match (← Lean.getEnv).find? decl with | some info => do typePriority decl info.type | none => throwError "unknown declaration {decl}" /-- Map a score to either `norm apply` or `safe apply ` -/ -def scoreToConfig (decl : Lean.Name) (score : ℕ) : Aesop.Frontend.RuleConfig := +def scoreToConfig (decl : Lean.Name) (score : Nat) : Aesop.Frontend.RuleConfig := let (phase, priority) := match score with | 0 => (Aesop.PhaseName.norm, 0) -- No hypotheses: this rule closes the goal immediately | s => (Aesop.PhaseName.safe, s) diff --git a/MathlibTest/byContra.lean b/MathlibTest/byContra.lean index 56a378b97d1e6..0f907c3706a40 100644 --- a/MathlibTest/byContra.lean +++ b/MathlibTest/byContra.lean @@ -3,6 +3,7 @@ import Mathlib.Tactic.ByContra import Mathlib.Tactic.Rename import Mathlib.Tactic.Set import Mathlib.Order.Basic +import Mathlib.Data.One.Defs import Mathlib.Data.Nat.Defs set_option autoImplicit true diff --git a/scripts/noshake.json b/scripts/noshake.json index 34b33e5c76be3..a956ff0c73f06 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -444,9 +444,11 @@ ["Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital"], "Mathlib.AlgebraicTopology.DoldKan.Notations": ["Mathlib.AlgebraicTopology.AlternatingFaceMapComplex"], + "Mathlib.Algebra.ZeroOne.Lemmas": ["Batteries.Tactic.Init"], "Mathlib.Algebra.Star.Module": ["Mathlib.Algebra.Module.LinearMap.Star"], "Mathlib.Algebra.Ring.CentroidHom": ["Mathlib.Algebra.Algebra.Defs"], "Mathlib.Algebra.Order.Quantale": ["Mathlib.Tactic.Variable"], + "Mathlib.Algebra.Order.Pi": ["Mathlib.Algebra.ZeroOne.Lemmas"], "Mathlib.Algebra.Order.CauSeq.Basic": ["Mathlib.Data.Setoid.Basic"], "Mathlib.Algebra.MonoidAlgebra.Basic": ["Mathlib.LinearAlgebra.Finsupp.SumProd"], From 918ca88b4f3d1edecee3f17f9dbaf0a0f28d704c Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 16 Jan 2025 01:18:50 +0000 Subject: [PATCH 257/681] fix(PR summary): use a file to store possibly long messages (#20761) May be a fix for the [issue reported on Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Strange.20error.20in.20CI). See #20767 for a successful run, where #20621 had problems. --- .github/workflows/PR_summary.yml | 6 ++++-- scripts/update_PR_comment.sh | 11 ++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/PR_summary.yml b/.github/workflows/PR_summary.yml index 6b854a59292d0..1c095f8a66f89 100644 --- a/.github/workflows/PR_summary.yml +++ b/.github/workflows/PR_summary.yml @@ -99,6 +99,8 @@ jobs: ## Technical debt changes techDebtVar="$(./scripts/technical-debt-metrics.sh pr_summary)" - message="$(printf '%s [%s](%s)%s\n\n%s\n\n---\n\n%s\n\n---\n\n%s\n' "${title}" "$(git rev-parse --short HEAD)" "${hashURL}" "${high_percentages}" "${importCount}" "${declDiff}" "${techDebtVar}")" + # store in a file, to avoid "long arguments" error. + printf '%s [%s](%s)%s\n\n%s\n\n---\n\n%s\n\n---\n\n%s\n' "${title}" "$(git rev-parse --short HEAD)" "${hashURL}" "${high_percentages}" "${importCount}" "${declDiff}" "${techDebtVar}" > messageFile.md - ./scripts/update_PR_comment.sh "${message}" "${title}" "${PR}" + cat messageFile.md + ./scripts/update_PR_comment.sh messageFile.md "${title}" "${PR}" diff --git a/scripts/update_PR_comment.sh b/scripts/update_PR_comment.sh index 0314cbb05c376..1add6e2b3f198 100755 --- a/scripts/update_PR_comment.sh +++ b/scripts/update_PR_comment.sh @@ -16,21 +16,21 @@ BASH_DOC_MODULE # If the first two arguments are missing, use the empty string as default value. -# the text of the message that will replace the current one +# the file containing the text of the message that will replace the current one message="${1:-}" # the start of the message to locate it among all messages in the PR comment_init="${2:-}" # But we do complain if the PR number is missing. PR="${3:-}" if [[ -z $PR ]]; then - echo "Usage: " + echo "Usage: " exit 1 fi -data=$(jq -n --arg msg "$message" '{"body": $msg}') + baseURL="https://api.github.com/repos/${GITHUB_REPOSITORY}/issues" printf 'Base url: %s\n' "${baseURL}" method="POST" -if [[ -n "$message" ]]; then +if [[ -f "$message" ]]; then url="${baseURL}/${PR}/comments" printf 'Base url: %s\n' "${url}" headers="Authorization: token ${GITHUB_TOKEN}" @@ -41,5 +41,6 @@ if [[ -n "$message" ]]; then url="${baseURL}/comments/${comment_id}" method="PATCH" fi - curl -s -S -H "Content-Type: application/json" -H "$headers" -X "$method" -d "$data" "$url" + jq -Rs -n -c '{"body": inputs}' "${message}" > "${message}.json" + curl -s -S -H "Content-Type: application/json" -H "$headers" -X "$method" -d @"${message}.json" "$url" fi From eec581e576bee4a9c19a608976f8a1e87c5b6ed5 Mon Sep 17 00:00:00 2001 From: Artie Khovanov Date: Thu, 16 Jan 2025 05:31:27 +0000 Subject: [PATCH 258/681] feat(Algebra/Ring): generalise and extend material about sums of squares and semireal rings (#16094) * Generalise definition of a semireal ring, as discussed at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Formally.20real.20fields * Add facts about multiplicative structure of sums of squares -- preserved under multiplication, form a semiring, set of sums of squares is the semiring generated by the squares. * Add some lemmas to simpset * Update documentation Deletions: * `mem_sumSq_of_isSquare` (statement changed to `IsSquare.isSumSq`) --- Mathlib/Algebra/Ring/Semireal/Defs.lean | 34 +++--- Mathlib/Algebra/Ring/SumsOfSquares.lean | 143 ++++++++++++++++++++---- 2 files changed, 140 insertions(+), 37 deletions(-) diff --git a/Mathlib/Algebra/Ring/Semireal/Defs.lean b/Mathlib/Algebra/Ring/Semireal/Defs.lean index cb5317abf618d..0904aa3454d2e 100644 --- a/Mathlib/Algebra/Ring/Semireal/Defs.lean +++ b/Mathlib/Algebra/Ring/Semireal/Defs.lean @@ -1,15 +1,14 @@ /- Copyright (c) 2024 Florent Schaffhauser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Florent Schaffhauser +Authors: Florent Schaffhauser, Artie Khovanov -/ import Mathlib.Algebra.Ring.SumsOfSquares /-! # Semireal rings -A semireal ring is a non-trivial commutative ring (with unit) in which `-1` is *not* a -sum of squares. +A semireal ring is a commutative ring (with unit) in which `-1` is *not* a sum of squares. For instance, linearly ordered rings are semireal, because sums of squares are positive and `-1` is not. @@ -24,22 +23,31 @@ not. [lam_1984](https://doi.org/10.1216/RMJ-1984-14-4-767) -/ -variable (R : Type*) +variable {R : Type*} +variable (R) in /-- -A semireal ring is a non-trivial commutative ring (with unit) in which `-1` is *not* a sum of -squares. We define the class `IsSemireal R` -for all additive monoids `R` equipped with a multiplication, a multiplicative unit and a negation. +A semireal ring is a commutative ring (with unit) in which `-1` is *not* a sum of +squares. We define the predicate `IsSemireal R` for structures `R` equipped with +a multiplication, an addition, a multiplicative unit and an additive unit. -/ @[mk_iff] -class IsSemireal [AddMonoid R] [Mul R] [One R] [Neg R] : Prop where - non_trivial : (0 : R) ≠ 1 - not_isSumSq_neg_one : ¬IsSumSq (-1 : R) +class IsSemireal [Add R] [Mul R] [One R] [Zero R] : Prop where + one_add_ne_zero {s : R} (hs : IsSumSq s) : 1 + s ≠ 0 @[deprecated (since := "2024-08-09")] alias isSemireal := IsSemireal + +/-- In a semireal ring, `-1` is not a sum of squares. -/ +theorem IsSemireal.not_isSumSq_neg_one [AddGroup R] [One R] [Mul R] [IsSemireal R]: + ¬ IsSumSq (-1 : R) := (by simpa using one_add_ne_zero ·) + @[deprecated (since := "2024-08-09")] alias isSemireal.neg_one_not_SumSq := IsSemireal.not_isSumSq_neg_one -instance [LinearOrderedRing R] : IsSemireal R where - non_trivial := zero_ne_one - not_isSumSq_neg_one := fun h ↦ (not_le (α := R)).2 neg_one_lt_zero h.nonneg +/-- +Linearly ordered semirings with the property `a ≤ b → ∃ c, a + c = b` (e.g. `ℕ`) +are semireal. +-/ +instance [LinearOrderedSemiring R] [ExistsAddOfLE R] : IsSemireal R where + one_add_ne_zero hs amo := zero_ne_one' R (le_antisymm zero_le_one + (le_of_le_of_eq (le_add_of_nonneg_right hs.nonneg) amo)) diff --git a/Mathlib/Algebra/Ring/SumsOfSquares.lean b/Mathlib/Algebra/Ring/SumsOfSquares.lean index ed4e42b2c5c19..0f777c8b0f1fd 100644 --- a/Mathlib/Algebra/Ring/SumsOfSquares.lean +++ b/Mathlib/Algebra/Ring/SumsOfSquares.lean @@ -1,12 +1,12 @@ /- Copyright (c) 2024 Florent Schaffhauser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Florent Schaffhauser +Authors: Florent Schaffhauser, Artie Khovanov -/ -import Mathlib.Algebra.BigOperators.Group.Finset.Basic -import Mathlib.Algebra.Group.Submonoid.Basic -import Mathlib.Algebra.Order.Ring.Defs - +import Mathlib.Algebra.Group.Subgroup.Even +import Mathlib.Algebra.Order.Ring.Basic +import Mathlib.Algebra.Ring.Subsemiring.Basic +import Mathlib.Tactic.ApplyFun /-! # Sums of squares @@ -18,7 +18,8 @@ We introduce a predicate for sums of squares in a ring. an inductive predicate defining the property of being a sum of squares in `R`. `0 : R` is a sum of squares and if `S` is a sum of squares, then, for all `a : R`, `a * a + s` is a sum of squares. -- `AddMonoid.sumSq R`: the submonoid of sums of squares in an additive monoid `R` +- `AddMonoid.sumSq R` and `Subsemiring.sumSq R`: respectively + the submonoid or subsemiring of sums of squares in an additive monoid or semiring `R` with multiplication. -/ @@ -37,6 +38,17 @@ inductive IsSumSq [Mul R] [Add R] [Zero R] : R → Prop @[deprecated (since := "2024-08-09")] alias isSumSq := IsSumSq +/-- Alternative induction scheme for `IsSumSq` which uses `IsSquare`. -/ +theorem IsSumSq.rec' [Mul R] [Add R] [Zero R] + {motive : (s : R) → (h : IsSumSq s) → Prop} + (zero : motive 0 zero) + (sq_add : ∀ {x s}, (hx : IsSquare x) → (hs : IsSumSq s) → motive s hs → + motive (x + s) (by rcases hx with ⟨_, rfl⟩; exact sq_add _ hs)) + {s : R} (h : IsSumSq s) : motive s h := + match h with + | .zero => zero + | .sq_add _ hs => sq_add (.mul_self _) hs (rec' zero sq_add _) + /-- In an additive monoid with multiplication, if `s₁` and `s₂` are sums of squares, then `s₁ + s₂` is a sum of squares. @@ -71,50 +83,133 @@ end AddSubmonoid @[deprecated (since := "2025-01-03")] alias sumSqIn := AddSubmonoid.sumSq @[deprecated (since := "2025-01-06")] alias sumSq := AddSubmonoid.sumSq +/-- In an additive unital magma with multiplication, `x * x` is a sum of squares for all `x`. -/ +@[simp] theorem IsSumSq.mul_self [AddZeroClass R] [Mul R] (a : R) : IsSumSq (a * a) := by + simpa using sq_add a zero + /-- -In an additive monoid with multiplication, squares are sums of squares +In an additive unital magma with multiplication, squares are sums of squares (see Mathlib.Algebra.Group.Even). -/ -theorem mem_sumSq_of_isSquare [AddMonoid R] [Mul R] {x : R} (hx : IsSquare x) : - x ∈ AddSubmonoid.sumSq R := by - rcases hx with ⟨y, hy⟩ - rw [hy, ← AddMonoid.add_zero (y * y)] - exact IsSumSq.sq_add _ IsSumSq.zero - -@[deprecated (since := "2024-08-09")] alias SquaresInSumSq := mem_sumSq_of_isSquare -@[deprecated (since := "2025-01-03")] alias mem_sumSqIn_of_isSquare := mem_sumSq_of_isSquare +theorem IsSquare.isSumSq [AddZeroClass R] [Mul R] {x : R} (hx : IsSquare x) : + IsSumSq x := by rcases hx with ⟨_, rfl⟩; apply IsSumSq.mul_self /-- In an additive monoid with multiplication `R`, the submonoid generated by the squares is the set of sums of squares in `R`. -/ +@[simp] theorem AddSubmonoid.closure_isSquare [AddMonoid R] [Mul R] : closure {x : R | IsSquare x} = sumSq R := by - refine le_antisymm (closure_le.2 (fun x hx ↦ mem_sumSq_of_isSquare hx)) (fun x hx ↦ ?_) - induction hx <;> aesop + refine closure_eq_of_le (fun x hx ↦ IsSquare.isSumSq hx) (fun x hx ↦ ?_) + induction hx with + | zero => apply zero_mem + | sq_add a hs ih => exact add_mem (subset_closure (IsSquare.mul_self a)) ih @[deprecated (since := "2024-08-09")] alias SquaresAddClosure := AddSubmonoid.closure_isSquare +/-- +In an additive commutative monoid with multiplication, a finite sum of sums of squares +is a sum of squares. +-/ +theorem IsSumSq.sum [AddCommMonoid R] [Mul R] {ι : Type*} {I : Finset ι} {s : ι → R} + (hs : ∀ i ∈ I, IsSumSq <| s i) : IsSumSq (∑ i ∈ I, s i) := by + simpa using sum_mem (S := AddSubmonoid.sumSq _) hs + +/-- +In an additive commutative monoid with multiplication, +`∑ i ∈ I, x i`, where each `x i` is a square, is a sum of squares. +-/ +theorem IsSumSq.sum_isSquare [AddCommMonoid R] [Mul R] {ι : Type*} (I : Finset ι) {x : ι → R} + (hx : ∀ i ∈ I, IsSquare <| x i) : IsSumSq (∑ i ∈ I, x i) := + .sum fun _ hi => IsSquare.isSumSq (hx _ hi) + /-- In an additive commutative monoid with multiplication, `∑ i ∈ I, a i * a i` is a sum of squares. -/ +@[simp] theorem IsSumSq.sum_mul_self [AddCommMonoid R] [Mul R] {ι : Type*} (I : Finset ι) (a : ι → R) : - IsSumSq (∑ i ∈ I, a i * a i) := by - induction I using Finset.cons_induction with - | empty => simpa using IsSumSq.zero - | cons i _ hi h => exact (Finset.sum_cons (β := R) hi) ▸ IsSumSq.sq_add (a i) h + IsSumSq (∑ i ∈ I, a i * a i) := .sum fun _ _ => .mul_self _ @[deprecated (since := "2024-12-27")] alias isSumSq_sum_mul_self := IsSumSq.sum_mul_self +namespace NonUnitalSubsemiring +variable {T : Type*} [NonUnitalCommSemiring T] + +variable (T) in +/-- +In a commutative (possibly non-unital) semiring `R`, `NonUnitalSubsemiring.sumSq R` is +the (possibly non-unital) subsemiring of sums of squares in `R`. +-/ +def sumSq : NonUnitalSubsemiring T := (Subsemigroup.square T).nonUnitalSubsemiringClosure + +@[simp] theorem sumSq_toAddSubmonoid : (sumSq T).toAddSubmonoid = .sumSq T := by + simp [sumSq, ← AddSubmonoid.closure_isSquare, + Subsemigroup.nonUnitalSubsemiringClosure_toAddSubmonoid] + +@[simp] +theorem mem_sumSq {s : T} : s ∈ sumSq T ↔ IsSumSq s := by + simp [← NonUnitalSubsemiring.mem_toAddSubmonoid] + +@[simp, norm_cast] theorem coe_sumSq : sumSq T = {s : T | IsSumSq s} := by ext; simp + +@[simp] theorem closure_isSquare : closure {x : T | IsSquare x} = sumSq T := by + simp [sumSq, Subsemigroup.nonUnitalSubsemiringClosure_eq_closure] + +end NonUnitalSubsemiring + +/-- +In a commutative (possibly non-unital) semiring, +if `s₁` and `s₂` are sums of squares, then `s₁ * s₂` is a sum of squares. +-/ +theorem IsSumSq.mul [NonUnitalCommSemiring R] {s₁ s₂ : R} + (h₁ : IsSumSq s₁) (h₂ : IsSumSq s₂) : IsSumSq (s₁ * s₂) := by + simpa using mul_mem (by simpa : _ ∈ NonUnitalSubsemiring.sumSq R) (by simpa) + +private theorem Submonoid.square_subsemiringClosure {T : Type*} [CommSemiring T] : + (Submonoid.square T).subsemiringClosure = .closure {x : T | IsSquare x} := by + simp [Submonoid.subsemiringClosure_eq_closure] + +namespace Subsemiring +variable {T : Type*} [CommSemiring T] + +variable (T) in +/-- +In a commutative semiring `R`, `Subsemiring.sumSq R` is the subsemiring of sums of squares in `R`. +-/ +def sumSq : Subsemiring T where + __ := NonUnitalSubsemiring.sumSq T + one_mem' := by simpa using IsSquare.one.isSumSq + +@[simp] theorem sumSq_toNonUnitalSubsemiring : + (sumSq T).toNonUnitalSubsemiring = .sumSq T := rfl + +@[simp] +theorem mem_sumSq {s : T} : s ∈ sumSq T ↔ IsSumSq s := by + simp [← Subsemiring.mem_toNonUnitalSubsemiring] + +@[simp, norm_cast] theorem coe_sumSq : sumSq T = {s : T | IsSumSq s} := by ext; simp + +@[simp] theorem closure_isSquare : closure {x : T | IsSquare x} = sumSq T := by + apply_fun toNonUnitalSubsemiring using toNonUnitalSubsemiring_injective + simp [← Submonoid.square_subsemiringClosure] + +end Subsemiring + +/-- In a commutative semiring, a finite product of sums of squares is a sum of squares. -/ +theorem IsSumSq.prod [CommSemiring R] {ι : Type*} {I : Finset ι} {x : ι → R} + (hx : ∀ i ∈ I, IsSumSq <| x i) : IsSumSq (∏ i ∈ I, x i) := by + simpa using prod_mem (S := Subsemiring.sumSq R) (by simpa) + /-- In a linearly ordered semiring with the property `a ≤ b → ∃ c, a + c = b` (e.g. `ℕ`), sums of squares are non-negative. -/ theorem IsSumSq.nonneg {R : Type*} [LinearOrderedSemiring R] [ExistsAddOfLE R] {s : R} (hs : IsSumSq s) : 0 ≤ s := by - induction hs with - | zero => simp only [le_refl] - | sq_add x _ ih => apply add_nonneg ?_ ih; simp only [← pow_two x, sq_nonneg] + induction hs using IsSumSq.rec' with + | zero => simp + | sq_add hx _ h => exact add_nonneg (IsSquare.nonneg hx) h @[deprecated (since := "2024-08-09")] alias isSumSq.nonneg := IsSumSq.nonneg From ad0b88318ef77eaa2aaa872b1dc26f29d69d0392 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Thu, 16 Jan 2025 07:31:27 +0000 Subject: [PATCH 259/681] =?UTF-8?q?feat:=20replace=20statement=20that=20sp?= =?UTF-8?q?ecific=20functions=20are=20C^=CF=89=20by=20the=20fact=20that=20?= =?UTF-8?q?they=20are=20C^n=20for=20all=20n=20(#20769)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is equivalent mathematically, but in applications the latter form is often more convenient. For instance, when proving that the composition is C^n, it's better to have right away the fact that the function is C^n. --- Mathlib/Analysis/Calculus/ContDiff/Basic.lean | 4 +-- .../Complex/UpperHalfPlane/Manifold.lean | 7 ++-- .../Geometry/Manifold/Instances/Sphere.lean | 35 ++++++++++--------- .../Geometry/Manifold/VectorBundle/Basic.lean | 2 +- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index 6bf66bf69047e..6eecb4ca014a6 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -1002,14 +1002,14 @@ Warning: if you think you need this lemma, it is likely that you can simplify yo reformulating the lemma that you're applying next using the tips in Note [continuity lemma statement] -/ -theorem contDiff_prodAssoc : ContDiff 𝕜 ω <| Equiv.prodAssoc E F G := +theorem contDiff_prodAssoc {n : WithTop ℕ∞} : ContDiff 𝕜 n <| Equiv.prodAssoc E F G := (LinearIsometryEquiv.prodAssoc 𝕜 E F G).contDiff /-- The natural equivalence `E × (F × G) ≃ (E × F) × G` is smooth. Warning: see remarks attached to `contDiff_prodAssoc` -/ -theorem contDiff_prodAssoc_symm : ContDiff 𝕜 ω <| (Equiv.prodAssoc E F G).symm := +theorem contDiff_prodAssoc_symm {n : WithTop ℕ∞} : ContDiff 𝕜 n <| (Equiv.prodAssoc E F G).symm := (LinearIsometryEquiv.prodAssoc 𝕜 E F G).symm.contDiff /-! ### Bundled derivatives are smooth -/ diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean index b6440a07da940..1e40786a364b5 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean @@ -26,7 +26,8 @@ instance : IsManifold 𝓘(ℂ) ω ℍ := UpperHalfPlane.isOpenEmbedding_coe.isManifold_singleton /-- The inclusion map `ℍ → ℂ` is an analytic map of manifolds. -/ -theorem contMDiff_coe : ContMDiff 𝓘(ℂ) 𝓘(ℂ) ω ((↑) : ℍ → ℂ) := fun _ => contMDiffAt_extChartAt +theorem contMDiff_coe {n : WithTop ℕ∞} : ContMDiff 𝓘(ℂ) 𝓘(ℂ) n ((↑) : ℍ → ℂ) := + fun _ => contMDiffAt_extChartAt @[deprecated (since := "2024-11-20")] alias smooth_coe := contMDiff_coe @@ -34,8 +35,8 @@ theorem contMDiff_coe : ContMDiff 𝓘(ℂ) 𝓘(ℂ) ω ((↑) : ℍ → ℂ) : theorem mdifferentiable_coe : MDifferentiable 𝓘(ℂ) 𝓘(ℂ) ((↑) : ℍ → ℂ) := contMDiff_coe.mdifferentiable le_top -lemma contMDiffAt_ofComplex {z : ℂ} (hz : 0 < z.im) : - ContMDiffAt 𝓘(ℂ) 𝓘(ℂ) ω ofComplex z := by +lemma contMDiffAt_ofComplex {n : WithTop ℕ∞} {z : ℂ} (hz : 0 < z.im) : + ContMDiffAt 𝓘(ℂ) 𝓘(ℂ) n ofComplex z := by rw [contMDiffAt_iff] constructor · -- continuity at z diff --git a/Mathlib/Geometry/Manifold/Instances/Sphere.lean b/Mathlib/Geometry/Manifold/Instances/Sphere.lean index 8a68398674838..d525541360b7d 100644 --- a/Mathlib/Geometry/Manifold/Instances/Sphere.lean +++ b/Mathlib/Geometry/Manifold/Instances/Sphere.lean @@ -94,8 +94,8 @@ theorem stereoToFun_apply (x : E) : stereoToFun v x = (2 / ((1 : ℝ) - innerSL ℝ v x)) • orthogonalProjection (ℝ ∙ v)ᗮ x := rfl -theorem contDiffOn_stereoToFun : - ContDiffOn ℝ ω (stereoToFun v) {x : E | innerSL _ v x ≠ (1 : ℝ)} := by +theorem contDiffOn_stereoToFun {n : WithTop ℕ∞} : + ContDiffOn ℝ n (stereoToFun v) {x : E | innerSL _ v x ≠ (1 : ℝ)} := by refine ContDiffOn.smul ?_ (orthogonalProjection (ℝ ∙ v)ᗮ).contDiff.contDiffOn refine contDiff_const.contDiffOn.div ?_ ?_ · exact (contDiff_const.sub (innerSL ℝ v).contDiff).contDiffOn @@ -104,7 +104,7 @@ theorem contDiffOn_stereoToFun : theorem continuousOn_stereoToFun : ContinuousOn (stereoToFun v) {x : E | innerSL _ v x ≠ (1 : ℝ)} := - contDiffOn_stereoToFun.continuousOn + (contDiffOn_stereoToFun (n := 0)).continuousOn variable (v) @@ -159,7 +159,7 @@ theorem hasFDerivAt_stereoInvFunAux_comp_coe (v : E) : hasFDerivAt_stereoInvFunAux v refine this.comp (0 : (ℝ ∙ v)ᗮ) (by apply ContinuousLinearMap.hasFDerivAt) -theorem contDiff_stereoInvFunAux : ContDiff ℝ ω (stereoInvFunAux v) := by +theorem contDiff_stereoInvFunAux {m : WithTop ℕ∞} : ContDiff ℝ m (stereoInvFunAux v) := by have h₀ : ContDiff ℝ ω fun w : E => ‖w‖ ^ 2 := contDiff_norm_sq ℝ have h₁ : ContDiff ℝ ω fun w : E => (‖w‖ ^ 2 + 4)⁻¹ := by refine (h₀.add contDiff_const).inv ?_ @@ -168,7 +168,7 @@ theorem contDiff_stereoInvFunAux : ContDiff ℝ ω (stereoInvFunAux v) := by have h₂ : ContDiff ℝ ω fun w => (4 : ℝ) • w + (‖w‖ ^ 2 - 4) • v := by refine (contDiff_const.smul contDiff_id).add ?_ exact (h₀.sub contDiff_const).smul contDiff_const - exact h₁.smul h₂ + exact (h₁.smul h₂).of_le le_top /-- Stereographic projection, reverse direction. This is a map from the orthogonal complement of a unit vector `v` in an inner product space `E` to the unit sphere in `E`. -/ @@ -195,7 +195,8 @@ theorem stereoInvFun_ne_north_pole (hv : ‖v‖ = 1) (w : (ℝ ∙ v)ᗮ) : · simpa using stereoInvFunAux_mem hv w.2 theorem continuous_stereoInvFun (hv : ‖v‖ = 1) : Continuous (stereoInvFun hv) := - continuous_induced_rng.2 (contDiff_stereoInvFunAux.continuous.comp continuous_subtype_val) + continuous_induced_rng.2 + ((contDiff_stereoInvFunAux (m := 0)).continuous.comp continuous_subtype_val) open scoped InnerProductSpace in attribute [-simp] AddSubgroupClass.coe_norm Submodule.coe_norm in @@ -388,9 +389,9 @@ instance EuclideanSpace.instIsManifoldSphere (-- Removed type ascription, and this helped for some reason with timeout issues? OrthonormalBasis.fromOrthogonalSpanSingleton (𝕜 := ℝ) n (ne_zero_of_mem_unit_sphere v')).repr - have H₁ := U'.contDiff.comp_contDiffOn contDiffOn_stereoToFun + have H₁ := U'.contDiff.comp_contDiffOn (contDiffOn_stereoToFun (n := ω)) -- Porting note: need to help with implicit variables again - have H₂ := (contDiff_stereoInvFunAux (v := v.val)|>.comp + have H₂ := (contDiff_stereoInvFunAux (m := ω) (v := v.val)|>.comp (ℝ ∙ (v : E))ᗮ.subtypeL.contDiff).comp U.symm.contDiff convert H₁.comp_inter (H₂.contDiffOn : ContDiffOn ℝ ω _ Set.univ) using 1 -- -- squeezed from `ext, simp [sphere_ext_iff, stereographic'_symm_apply, real_inner_comm]` @@ -408,8 +409,8 @@ instance (n : ℕ) : IsManifold (𝓡 n) ω (sphere (0 : EuclideanSpace ℝ (Fi EuclideanSpace.instIsManifoldSphere /-- The inclusion map (i.e., `coe`) from the sphere in `E` to `E` is analytic. -/ -theorem contMDiff_coe_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : - ContMDiff (𝓡 n) 𝓘(ℝ, E) ω ((↑) : sphere (0 : E) 1 → E) := by +theorem contMDiff_coe_sphere {m : WithTop ℕ∞} {n : ℕ} [Fact (finrank ℝ E = n + 1)] : + ContMDiff (𝓡 n) 𝓘(ℝ, E) m ((↑) : sphere (0 : E) 1 → E) := by -- Porting note: trouble with filling these implicit variables in the instance have := EuclideanSpace.instIsManifoldSphere (E := E) (n := n) rw [contMDiff_iff] @@ -454,18 +455,18 @@ theorem ContMDiff.codRestrict_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] {f simp [not_iff_not, Subtype.ext_iff, hfxv, real_inner_comm] /-- The antipodal map is analytic. -/ -theorem contMDiff_neg_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : - ContMDiff (𝓡 n) (𝓡 n) ω fun x : sphere (0 : E) 1 => -x := by +theorem contMDiff_neg_sphere {m : WithTop ℕ∞} {n : ℕ} [Fact (finrank ℝ E = n + 1)] : + ContMDiff (𝓡 n) (𝓡 n) m fun x : sphere (0 : E) 1 => -x := by -- this doesn't elaborate well in term mode apply ContMDiff.codRestrict_sphere apply contDiff_neg.contMDiff.comp _ exact contMDiff_coe_sphere private lemma stereographic'_neg {n : ℕ} [Fact (finrank ℝ E = n + 1)] (v : sphere (0 : E) 1) : - stereographic' n (-v) v = 0 := by - dsimp [stereographic'] - simp only [EmbeddingLike.map_eq_zero_iff] - apply stereographic_neg_apply + stereographic' n (-v) v = 0 := by + dsimp [stereographic'] + simp only [EmbeddingLike.map_eq_zero_iff] + apply stereographic_neg_apply /-- Consider the differential of the inclusion of the sphere in `E` at the point `v` as a continuous linear map from `TangentSpace (𝓡 n) v` to `E`. The range of this map is the orthogonal complement @@ -571,7 +572,7 @@ instance : LieGroup (𝓡 1) ω Circle where exact Complex.conjCLE.contDiff.contMDiff.comp contMDiff_coe_sphere /-- The map `fun t ↦ exp (t * I)` from `ℝ` to the unit circle in `ℂ` is analytic. -/ -theorem contMDiff_circleExp : ContMDiff 𝓘(ℝ, ℝ) (𝓡 1) ω Circle.exp := +theorem contMDiff_circleExp {m : WithTop ℕ∞} : ContMDiff 𝓘(ℝ, ℝ) (𝓡 1) m Circle.exp := (contDiff_exp.comp (contDiff_id.smul contDiff_const)).contMDiff.codRestrict_sphere _ @[deprecated (since := "2024-07-25")] alias contMDiff_expMapCircle := contMDiff_circleExp diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean index 4b44eae1ac780..9778f4de7dd8b 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean @@ -265,7 +265,7 @@ variable [FiberBundle F E] [VectorBundle 𝕜 F E] variable (n IB) in /-- When `B` is a manifold with respect to a model `IB` and `E` is a topological vector bundle over `B` with fibers isomorphic to `F`, -then `ContMDiffVectorBundle F E IB` registers that the bundle is `C^n`, in the sense of having +then `ContMDiffVectorBundle n F E IB` registers that the bundle is `C^n`, in the sense of having `C^n` transition functions. This is a mixin, not carrying any new data. -/ class ContMDiffVectorBundle : Prop where protected contMDiffOn_coordChangeL : From 0ec82d5aaaa6562ad1758c7b6569bce8a7f5cf8b Mon Sep 17 00:00:00 2001 From: Oliver Nash Date: Thu, 16 Jan 2025 07:44:09 +0000 Subject: [PATCH 260/681] feat: generalise `PerfectPairing.restrictScalarsField` (#20442) Also introduce the new definition `PerfectPairing.IsPerfectCompl` to simplify statements. --- .../LinearAlgebra/PerfectPairing/Basic.lean | 24 +++++ .../PerfectPairing/Restrict.lean | 96 +++++++++++++------ Mathlib/LinearAlgebra/Span/Basic.lean | 73 +++++++++++++- Mathlib/LinearAlgebra/Span/Defs.lean | 9 +- 4 files changed, 162 insertions(+), 40 deletions(-) diff --git a/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean b/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean index 51d24aee6ca24..50ffa39ec68c9 100644 --- a/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean +++ b/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean @@ -84,6 +84,11 @@ instance instFunLike : FunLike (PerfectPairing R M N) M (N →ₗ[R] R) where lemma toLin_apply (p : PerfectPairing R M N) {x : M} : p.toLin x = p x := by rfl +@[simp] +lemma mk_apply_apply {f : M →ₗ[R] N →ₗ[R] R} {hl} {hr} {x : M} : + (⟨f, hl, hr⟩ : PerfectPairing R M N) x = f x := + rfl + variable (p : PerfectPairing R M N) /-- Given a perfect pairing between `M` and `N`, we may interchange the roles of `M` and `N`. -/ @@ -182,6 +187,25 @@ theorem finrank_eq [Module.Finite R M] [Module.Free R M] : finrank R M = finrank R N := ((Module.Free.chooseBasis R M).toDualEquiv.trans p.toDualRight.symm).finrank_eq +/-- Given a perfect pairing `p` between `M` and `N`, we say a pair of submodules `U` in `M` and +`V` in `N` are perfectly complementary wrt `p` if their dual annihilators are complementary, using +`p` to identify `M` and `N` with dual spaces. -/ +structure IsPerfectCompl (U : Submodule R M) (V : Submodule R N) : Prop where + isCompl_left : IsCompl U (V.dualAnnihilator.map p.toDualLeft.symm) + isCompl_right : IsCompl V (U.dualAnnihilator.map p.toDualRight.symm) + +namespace IsPerfectCompl + +variable {p} +variable {U : Submodule R M} {V : Submodule R N} + +protected lemma flip (h : p.IsPerfectCompl U V) : + p.flip.IsPerfectCompl V U where + isCompl_left := h.isCompl_right + isCompl_right := h.isCompl_left + +end IsPerfectCompl + end PerfectPairing variable [IsReflexive R M] diff --git a/Mathlib/LinearAlgebra/PerfectPairing/Restrict.lean b/Mathlib/LinearAlgebra/PerfectPairing/Restrict.lean index 51513e7ee3b89..f9b217399a977 100644 --- a/Mathlib/LinearAlgebra/PerfectPairing/Restrict.lean +++ b/Mathlib/LinearAlgebra/PerfectPairing/Restrict.lean @@ -9,13 +9,16 @@ import Mathlib.LinearAlgebra.Matrix.BaseChange /-! # Restriction to submodules and restriction of scalars for perfect pairings. + We provide API for restricting perfect pairings to submodules and for restricting their scalars. + ## Main definitions * `PerfectPairing.restrict`: restriction of a perfect pairing to submodules. * `PerfectPairing.restrictScalars`: restriction of scalars for a perfect pairing taking values in a subring. - * `PerfectPairing.restrictScalarsField`: restriction of scalars for a perfect pairing taking values - in a subfield. + * `PerfectPairing.restrictScalarsField`: simultaneously restrict both the domains and scalars + of a perfect pairing with coefficients in a field. + -/ open Function Module Set @@ -30,12 +33,15 @@ section CommRing variable {R M N : Type*} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] (p : PerfectPairing R M N) -private lemma restrict_aux - {M' N' : Type*} [AddCommGroup M'] [Module R M'] [AddCommGroup N'] [Module R N'] - (i : M' →ₗ[R] M) (j : N' →ₗ[R] N) - (hM : IsCompl (LinearMap.range i) ((LinearMap.range j).dualAnnihilator.map p.toDualLeft.symm)) - (hN : IsCompl (LinearMap.range j) ((LinearMap.range i).dualAnnihilator.map p.toDualRight.symm)) - (hi : Injective i) (hj : Injective j) : +section Restrict + +variable {M' N' : Type*} [AddCommGroup M'] [Module R M'] [AddCommGroup N'] [Module R N'] + (i : M' →ₗ[R] M) (j : N' →ₗ[R] N) (hi : Injective i) (hj : Injective j) + (hij : p.IsPerfectCompl (LinearMap.range i) (LinearMap.range j)) + +include hi hj hij + +private lemma restrict_aux : Bijective (p.toLin.compl₁₂ i j) := by refine ⟨LinearMap.ker_eq_bot.mp <| eq_bot_iff.mpr fun m hm ↦ ?_, fun f ↦ ?_⟩ · replace hm : i m ∈ (LinearMap.range j).dualAnnihilator.map p.toDualLeft.symm := by @@ -44,11 +50,13 @@ private lemma restrict_aux rintro - ⟨n, rfl⟩ simpa using LinearMap.congr_fun hm n suffices i m ∈ (⊥ : Submodule R M) by simpa [hi] using this - simpa only [← hM.inf_eq_bot, Submodule.mem_inf] using ⟨LinearMap.mem_range_self i m, hm⟩ - · set F : Module.Dual R N := f ∘ₗ j.linearProjOfIsCompl _ hj hN with hF + simpa only [← hij.isCompl_left.inf_eq_bot, Submodule.mem_inf] + using ⟨LinearMap.mem_range_self i m, hm⟩ + · set F : Module.Dual R N := f ∘ₗ j.linearProjOfIsCompl _ hj hij.isCompl_right with hF have hF (n : N') : F (j n) = f n := by simp [hF] set m : M := p.toDualLeft.symm F with hm - obtain ⟨-, ⟨m₀, rfl⟩, y, hy, hm'⟩ := Submodule.exists_add_eq_of_codisjoint hM.codisjoint m + obtain ⟨-, ⟨m₀, rfl⟩, y, hy, hm'⟩ := + Submodule.exists_add_eq_of_codisjoint hij.isCompl_left.codisjoint m refine ⟨m₀, LinearMap.ext fun n ↦ ?_⟩ replace hy : (p y) (j n) = 0 := by simp only [Submodule.mem_map, Submodule.mem_dualAnnihilator] at hy @@ -61,22 +69,25 @@ private lemma restrict_aux /-- The restriction of a perfect pairing to submodules (expressed as injections to provide definitional control). -/ @[simps] -def restrict {M' N' : Type*} [AddCommGroup M'] [Module R M'] [AddCommGroup N'] [Module R N'] - (i : M' →ₗ[R] M) (j : N' →ₗ[R] N) - (hM : IsCompl (LinearMap.range i) ((LinearMap.range j).dualAnnihilator.map p.toDualLeft.symm)) - (hN : IsCompl (LinearMap.range j) ((LinearMap.range i).dualAnnihilator.map p.toDualRight.symm)) - (hi : Injective i) (hj : Injective j) : +def restrict : PerfectPairing R M' N' where toLin := p.toLin.compl₁₂ i j - bijectiveLeft := p.restrict_aux i j hM hN hi hj - bijectiveRight := p.flip.restrict_aux j i hN hM hj hi + bijectiveLeft := p.restrict_aux i j hi hj hij + bijectiveRight := p.flip.restrict_aux j i hj hi hij.flip + +@[simp] +lemma restrict_apply_apply (x : M') (y : N') : + p.restrict i j hi hj hij x y = p (i x) (j y) := + rfl + +end Restrict section RestrictScalars -variable {S : Type*} +variable {S M' N' : Type*} [CommRing S] [Algebra S R] [Module S M] [Module S N] [IsScalarTower S R M] [IsScalarTower S R N] [NoZeroSMulDivisors S R] [Nontrivial R] - {M' N' : Type*} [AddCommGroup M'] [Module S M'] [AddCommGroup N'] [Module S N'] + [AddCommGroup M'] [Module S M'] [AddCommGroup N'] [Module S N'] (i : M' →ₗ[S] M) (j : N' →ₗ[S] N) /-- An auxiliary definition used to construct `PerfectPairing.restrictScalars`. -/ @@ -144,7 +155,7 @@ end CommRing section Field -variable {K L M N M : Type*} [Field K] [Field L] [Algebra K L] +variable {K L M N : Type*} [Field K] [Field L] [Algebra K L] [AddCommGroup M] [AddCommGroup N] [Module L M] [Module L N] [Module K M] [Module K N] [IsScalarTower K L M] (p : PerfectPairing L M N) @@ -153,9 +164,6 @@ variable {K L M N M : Type*} [Field K] [Field L] [Algebra K L] whose `L` span is full, then these subspaces induce a `K`-structure in the sense of [*Algebra I*, Bourbaki : Chapter II, §8.1 Definition 1][bourbaki1989]. -/ lemma exists_basis_basis_of_span_eq_top_of_mem_algebraMap - {K L : Type*} [Field K] [Field L] [Algebra K L] - [Module L M] [Module L N] [Module K M] [Module K N] [IsScalarTower K L M] - (p : PerfectPairing L M N) (M' : Submodule K M) (N' : Submodule K N) (hM : span L (M' : Set M) = ⊤) (hN : span L (N' : Set N) = ⊤) @@ -208,15 +216,11 @@ variable {M' N' : Type*} [AddCommGroup M'] [AddCommGroup N'] [Module K M'] [Module K N'] [IsScalarTower K L N] (i : M' →ₗ[K] M) (j : N' →ₗ[K] N) (hi : Injective i) (hj : Injective j) -/-- Restriction of scalars for a perfect pairing taking values in a subfield. -/ -def restrictScalarsField {K L : Type*} [Field K] [Field L] [Algebra K L] - [Module L M] [Module L N] [Module K M] [Module K N] [IsScalarTower K L M] [IsScalarTower K L N] - [Module K M'] [Module K N'] - (i : M' →ₗ[K] M) (j : N' →ₗ[K] N) - (hi : Injective i) (hj : Injective j) +/-- An auxiliary definition used only to simplify the construction of the more general definition +`PerfectPairing.restrictScalarsField`. -/ +private def restrictScalarsFieldAux (hM : span L (LinearMap.range i : Set M) = ⊤) (hN : span L (LinearMap.range j : Set N) = ⊤) - (p : PerfectPairing L M N) (hp : ∀ m n, p (i m) (j n) ∈ (algebraMap K L).range) : PerfectPairing K M' N' := by suffices FiniteDimensional K M' from mkOfInjective _ (p.restrictScalarsAux_injective i j hi hN hp) @@ -227,6 +231,36 @@ def restrictScalarsField {K L : Type*} [Field K] [Field L] [Algebra K L] have : FiniteDimensional K (LinearMap.range i) := FiniteDimensional.of_fintype_basis b' exact Finite.equiv (LinearEquiv.ofInjective i hi).symm +/-- Simultaneously restrict both the domains and scalars of a perfect pairing with coefficients in a +field. -/ +def restrictScalarsField + (hij : p.IsPerfectCompl (span L <| LinearMap.range i) (span L <| LinearMap.range j)) + (hp : ∀ m n, p (i m) (j n) ∈ (algebraMap K L).range) : + PerfectPairing K M' N' := by + letI P : PerfectPairing L (span L <| LinearMap.range i) (span L <| LinearMap.range j) := + p.restrict (Submodule.subtype _) (Submodule.subtype _) (by simp) (by simp) (by simpa) + exact P.restrictScalarsFieldAux + ((LinearMap.range i).inclusionSpan L ∘ₗ i.rangeRestrict) + ((LinearMap.range j).inclusionSpan L ∘ₗ j.rangeRestrict) + (((LinearMap.range i).injective_inclusionSpan L).comp (by simpa)) + (((LinearMap.range j).injective_inclusionSpan L).comp (by simpa)) + (by rw [LinearMap.range_comp_of_range_eq_top _ (LinearMap.range_rangeRestrict _)] + exact (LinearMap.range i).span_range_inclusionSpan L) + (by rw [LinearMap.range_comp_of_range_eq_top _ (LinearMap.range_rangeRestrict _)] + exact (LinearMap.range j).span_range_inclusionSpan L) + (fun x y ↦ LinearMap.BilinMap.apply_apply_mem_of_mem_span + (LinearMap.range <| Algebra.linearMap K L) (range i) (range j) + ((LinearMap.restrictScalarsₗ K L _ _ _).comp (p.toLin.restrictScalars K)) + (by simpa) (i x) (j y) (subset_span (mem_range_self x)) (subset_span (mem_range_self y))) + +@[simp] lemma restrictScalarsField_apply_apply + (hij : p.IsPerfectCompl (span L <| LinearMap.range i) (span L <| LinearMap.range j)) + (hp : ∀ m n, p (i m) (j n) ∈ (algebraMap K L).range) + (x : M') (y : N') : + algebraMap K L (p.restrictScalarsField i j hi hj hij hp x y) = p (i x) (j y) := + LinearMap.restrictScalarsRange_apply i j (Algebra.linearMap K L) + (NoZeroSMulDivisors.algebraMap_injective K L) p.toLin hp x y + end Field end PerfectPairing diff --git a/Mathlib/LinearAlgebra/Span/Basic.lean b/Mathlib/LinearAlgebra/Span/Basic.lean index 102160c3b2d27..145579823242b 100644 --- a/Mathlib/LinearAlgebra/Span/Basic.lean +++ b/Mathlib/LinearAlgebra/Span/Basic.lean @@ -145,26 +145,72 @@ theorem coe_scott_continuous : OmegaCompletePartialOrder.ωScottContinuous.of_monotone_map_ωSup ⟨SetLike.coe_mono, coe_iSup_of_chain⟩ -variable (R S s) +section IsScalarTower + +variable (S) + +variable [Semiring S] [SMul R S] [Module S M] [IsScalarTower R S M] (p : Submodule R M) + +/-- The inclusion of an `R`-submodule into its `S`-span, as an `R`-linear map. -/ +@[simps] def inclusionSpan : + p →ₗ[R] span S (p : Set M) where + toFun x := ⟨x, subset_span x.property⟩ + map_add' x y := by simp + map_smul' t x := by simp + +lemma injective_inclusionSpan : + Injective (p.inclusionSpan S) := by + intro x y hxy + rw [Subtype.ext_iff] at hxy + simpa using hxy + +lemma span_range_inclusionSpan : + span S (range <| p.inclusionSpan S) = ⊤ := by + have : (span S (p : Set M)).subtype '' range (inclusionSpan S p) = p := by + ext; simpa [Subtype.ext_iff] using fun h ↦ subset_span h + apply map_injective_of_injective (span S (p : Set M)).injective_subtype + rw [map_subtype_top, map_span, this] + +variable (R s) /-- If `R` is "smaller" ring than `S` then the span by `R` is smaller than the span by `S`. -/ -theorem span_le_restrictScalars [Semiring S] [SMul R S] [Module S M] [IsScalarTower R S M] : +theorem span_le_restrictScalars : span R s ≤ (span S s).restrictScalars R := Submodule.span_le.2 Submodule.subset_span /-- A version of `Submodule.span_le_restrictScalars` with coercions. -/ @[simp] -theorem span_subset_span [Semiring S] [SMul R S] [Module S M] [IsScalarTower R S M] : +theorem span_subset_span : ↑(span R s) ⊆ (span S s : Set M) := span_le_restrictScalars R S s /-- Taking the span by a large ring of the span by the small ring is the same as taking the span by just the large ring. -/ -theorem span_span_of_tower [Semiring S] [SMul R S] [Module S M] [IsScalarTower R S M] : +@[simp] +theorem span_span_of_tower : span S (span R s : Set M) = span S s := le_antisymm (span_le.2 <| span_subset_span R S s) (span_mono subset_span) -variable {R S s} +variable {R S} in +lemma span_range_inclusion_eq_top (p : Submodule R M) (q : Submodule S M) + (h₁ : p ≤ q.restrictScalars R) (h₂ : q ≤ span S p) : + span S (range (inclusion h₁)) = ⊤ := by + suffices (span S (range (inclusion h₁))).map q.subtype = q by + apply map_injective_of_injective q.injective_subtype + rw [this, q.map_subtype_top] + rw [map_span] + suffices q.subtype '' ((LinearMap.range (inclusion h₁)) : Set <| q.restrictScalars R) = p by + refine this ▸ le_antisymm ?_ h₂ + simpa using span_mono (R := S) h₁ + ext x + simpa [range_inclusion] using fun hx ↦ h₁ hx + +@[simp] +theorem span_range_inclusion_restrictScalars_eq_top : + span S (range (inclusion <| span_le_restrictScalars R S s)) = ⊤ := + span_range_inclusion_eq_top _ _ _ <| by simp + +end IsScalarTower theorem span_singleton_eq_span_singleton {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M] {x y : M} : ((R ∙ x) = R ∙ y) ↔ ∃ z : Rˣ, z • x = y := by @@ -327,6 +373,23 @@ theorem prod_sup_prod : prod p q₁ ⊔ prod p' q₁' = prod (p ⊔ p') (q₁ rcases mem_sup.1 hyy with ⟨y, hy, y', hy', rfl⟩ exact mem_sup.2 ⟨(x, y), ⟨hx, hy⟩, (x', y'), ⟨hx', hy'⟩, rfl⟩ +/-- If a bilinear map takes values in a submodule along two sets, then the same is true along +the span of these sets. -/ +lemma _root_.LinearMap.BilinMap.apply_apply_mem_of_mem_span {R M N P : Type*} [CommSemiring R] + [AddCommGroup M] [AddCommMonoid N] [AddCommMonoid P] [Module R M] [Module R N] [Module R P] + (P' : Submodule R P) (s : Set M) (t : Set N) + (B : M →ₗ[R] N →ₗ[R] P) (hB : ∀ x ∈ s, ∀ y ∈ t, B x y ∈ P') + (x : M) (y : N) (hx : x ∈ span R s) (hy : y ∈ span R t) : + B x y ∈ P' := by + induction hx, hy using span_induction₂ with + | mem_mem u v hu hv => exact hB u hu v hv + | zero_left v hv => simp + | zero_right u hu => simp + | add_left u₁ u₂ v hu₁ hu₂ hv huv₁ huv₂ => simpa using add_mem huv₁ huv₂ + | add_right u v₁ v₂ hu hv₁ hv₂ huv₁ huv₂ => simpa using add_mem huv₁ huv₂ + | smul_left t u v hu hv huv => simpa using Submodule.smul_mem _ _ huv + | smul_right t u v hu hv huv => simpa using Submodule.smul_mem _ _ huv + end AddCommMonoid section AddCommGroup diff --git a/Mathlib/LinearAlgebra/Span/Defs.lean b/Mathlib/LinearAlgebra/Span/Defs.lean index 071461bc35a4f..ff45da3ce5905 100644 --- a/Mathlib/LinearAlgebra/Span/Defs.lean +++ b/Mathlib/LinearAlgebra/Span/Defs.lean @@ -135,15 +135,16 @@ alias span_induction' := span_induction /-- An induction principle for span membership. This is a version of `Submodule.span_induction` for binary predicates. -/ -theorem span_induction₂ {p : (x y : M) → x ∈ span R s → y ∈ span R s → Prop} - (mem_mem : ∀ (x) (y) (hx : x ∈ s) (hy : y ∈ s), p x y (subset_span hx) (subset_span hy)) +theorem span_induction₂ {N : Type*} [AddCommMonoid N] [Module R N] {t : Set N} + {p : (x : M) → (y : N) → x ∈ span R s → y ∈ span R t → Prop} + (mem_mem : ∀ (x) (y) (hx : x ∈ s) (hy : y ∈ t), p x y (subset_span hx) (subset_span hy)) (zero_left : ∀ y hy, p 0 y (zero_mem _) hy) (zero_right : ∀ x hx, p x 0 hx (zero_mem _)) (add_left : ∀ x y z hx hy hz, p x z hx hz → p y z hy hz → p (x + y) z (add_mem hx hy) hz) (add_right : ∀ x y z hx hy hz, p x y hx hy → p x z hx hz → p x (y + z) hx (add_mem hy hz)) (smul_left : ∀ (r : R) x y hx hy, p x y hx hy → p (r • x) y (smul_mem _ r hx) hy) (smul_right : ∀ (r : R) x y hx hy, p x y hx hy → p x (r • y) hx (smul_mem _ r hy)) - {a b : M} (ha : a ∈ Submodule.span R s) - (hb : b ∈ Submodule.span R s) : p a b ha hb := by + {a : M} {b : N} (ha : a ∈ Submodule.span R s) + (hb : b ∈ Submodule.span R t) : p a b ha hb := by induction hb using span_induction with | mem z hz => induction ha using span_induction with | mem _ h => exact mem_mem _ _ h hz From e9450cdc3e8f6ab0d8f2aaf93a66fb92350f8167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yuyang=20Zhao=20=E8=B5=B5=E9=9B=A8=E6=89=AC?= Date: Thu, 16 Jan 2025 10:00:34 +0000 Subject: [PATCH 261/681] refactor: make `CanonicallyOrdered...` mixin (#17444) This PR is the first step to migrate from semibundled ordered algebraic typeclasses to mixin typeclasses. This will significantly reduce the number of typeclasses and improve performance. See #20676. This PR introduces 2 typeclasses `CanonicallyOrderedAdd` `CanonicallyOrderedMul` and deprecates legacy semibundled `CanonicallyOrdered*` typeclasses. --- .../OxfordInvariants/Summer2021/Week3P1.lean | 2 +- .../CanonicallyOrderedCommSemiringTwoMul.lean | 27 +- Mathlib.lean | 3 +- .../Algebra/Associated/OrderedCommMonoid.lean | 3 +- Mathlib/Algebra/DirectSum/Internal.lean | 4 +- Mathlib/Algebra/GeomSum.lean | 17 +- Mathlib/Algebra/Lie/Subalgebra.lean | 12 +- .../Algebra/Module/Submodule/Pointwise.lean | 13 +- Mathlib/Algebra/Order/Antidiag/Finsupp.lean | 3 +- Mathlib/Algebra/Order/Antidiag/Pi.lean | 3 +- Mathlib/Algebra/Order/Antidiag/Prod.lean | 10 +- .../Order/BigOperators/Group/Finset.lean | 6 +- .../Order/BigOperators/Group/List.lean | 7 +- .../Order/BigOperators/Group/Multiset.lean | 6 +- .../Order/BigOperators/Ring/Finset.lean | 16 +- .../Algebra/Order/BigOperators/Ring/List.lean | 10 +- .../Order/BigOperators/Ring/Multiset.lean | 8 +- Mathlib/Algebra/Order/Field/Canonical.lean | 36 +++ .../Algebra/Order/Field/Canonical/Basic.lean | 22 -- .../Algebra/Order/Field/Canonical/Defs.lean | 31 --- Mathlib/Algebra/Order/Field/Rat.lean | 5 +- Mathlib/Algebra/Order/Group/Finset.lean | 4 +- Mathlib/Algebra/Order/Group/Indicator.lean | 6 +- Mathlib/Algebra/Order/Group/Nat.lean | 6 +- .../Order/GroupWithZero/Canonical.lean | 17 +- Mathlib/Algebra/Order/Kleene.lean | 12 +- .../Algebra/Order/Monoid/Canonical/Basic.lean | 3 +- .../Algebra/Order/Monoid/Canonical/Defs.lean | 257 +++++++++++++----- Mathlib/Algebra/Order/Monoid/Prod.lean | 8 +- Mathlib/Algebra/Order/Monoid/TypeTags.lean | 27 +- Mathlib/Algebra/Order/Monoid/WithTop.lean | 12 +- Mathlib/Algebra/Order/Nonneg/Field.lean | 8 +- Mathlib/Algebra/Order/Nonneg/Ring.lean | 19 +- Mathlib/Algebra/Order/Pi.lean | 7 +- Mathlib/Algebra/Order/Ring/Canonical.lean | 122 +++++---- Mathlib/Algebra/Order/Ring/Defs.lean | 2 - Mathlib/Algebra/Order/Ring/Finset.lean | 7 +- Mathlib/Algebra/Order/Ring/Nat.lean | 10 +- Mathlib/Algebra/Order/Ring/WithTop.lean | 104 ++++--- Mathlib/Algebra/Order/Sub/Basic.lean | 8 +- Mathlib/Algebra/Order/Sub/Defs.lean | 4 +- Mathlib/Algebra/Order/Sub/WithTop.lean | 3 +- Mathlib/Algebra/PUnitInstances/Order.lean | 3 +- Mathlib/Analysis/Analytic/Basic.lean | 1 - .../Calculus/LocalExtr/Polynomial.lean | 1 - Mathlib/Analysis/SumOverResidueClass.lean | 2 +- .../Combinatorics/Additive/AP/Three/Defs.lean | 2 +- Mathlib/Combinatorics/Enumerative/Bell.lean | 2 +- .../SetFamily/HarrisKleitman.lean | 3 +- .../SimpleGraph/Regularity/Equitabilise.lean | 1 + Mathlib/Computability/Halting.lean | 2 +- Mathlib/Computability/Primrec.lean | 4 +- Mathlib/Data/DFinsupp/Interval.lean | 3 +- Mathlib/Data/DFinsupp/Lex.lean | 3 +- Mathlib/Data/DFinsupp/Order.lean | 33 ++- Mathlib/Data/DFinsupp/WellFounded.lean | 6 +- Mathlib/Data/ENNReal/Basic.lean | 14 +- Mathlib/Data/ENNReal/Operations.lean | 4 +- Mathlib/Data/ENat/Basic.lean | 11 +- Mathlib/Data/Finite/Card.lean | 4 +- Mathlib/Data/Finsupp/Interval.lean | 2 +- Mathlib/Data/Finsupp/Lex.lean | 3 +- Mathlib/Data/Finsupp/Order.lean | 20 +- Mathlib/Data/Finsupp/Weight.lean | 2 +- Mathlib/Data/Finsupp/WellFounded.lean | 6 +- Mathlib/Data/List/EditDistance/Bounds.lean | 3 +- Mathlib/Data/List/EditDistance/Estimator.lean | 2 +- Mathlib/Data/Multiset/OrderedMonoid.lean | 5 +- Mathlib/Data/NNRat/Floor.lean | 1 + Mathlib/Data/NNRat/Order.lean | 5 +- Mathlib/Data/NNReal/Basic.lean | 2 +- Mathlib/Data/NNReal/Defs.lean | 19 +- Mathlib/Data/Nat/BitIndices.lean | 2 +- Mathlib/Data/Nat/Cast/Order/Ring.lean | 5 +- Mathlib/Data/Nat/Cast/SetInterval.lean | 4 +- Mathlib/Data/Nat/Dist.lean | 1 + Mathlib/Data/Nat/PartENat.lean | 8 +- Mathlib/Data/Nat/Squarefree.lean | 2 +- Mathlib/Data/Nat/SuccPred.lean | 5 +- Mathlib/Data/Nat/Upto.lean | 1 + Mathlib/Data/Nat/WithBot.lean | 5 +- Mathlib/Data/PNat/Basic.lean | 6 +- Mathlib/Data/PNat/Factors.lean | 13 +- Mathlib/Data/Rat/Floor.lean | 2 +- Mathlib/Data/Rat/Star.lean | 1 + Mathlib/Data/Set/Card.lean | 2 +- Mathlib/Data/Set/Semiring.lean | 13 +- Mathlib/Dynamics/Flow.lean | 11 +- Mathlib/MeasureTheory/Constructions/Pi.lean | 2 +- Mathlib/MeasureTheory/Group/Arithmetic.lean | 3 +- Mathlib/MeasureTheory/Measure/Prod.lean | 2 +- Mathlib/Order/Filter/Germ/OrderedMonoid.lean | 5 +- Mathlib/Order/Interval/Finset/Nat.lean | 2 +- Mathlib/Order/JordanHolder.lean | 2 +- Mathlib/Order/RelSeries.lean | 8 +- Mathlib/Probability/StrongLaw.lean | 2 +- Mathlib/RingTheory/GradedAlgebra/Basic.lean | 2 +- .../GradedAlgebra/HomogeneousIdeal.lean | 2 +- .../RingTheory/GradedAlgebra/Noetherian.lean | 2 +- Mathlib/RingTheory/Multiplicity.lean | 2 +- .../MvPolynomial/WeightedHomogeneous.lean | 26 +- Mathlib/SetTheory/Cardinal/Basic.lean | 55 ++-- Mathlib/Tactic/Positivity/Core.lean | 6 +- .../Topology/Algebra/InfiniteSum/Order.lean | 10 +- .../MetricSpace/ThickenedIndicator.lean | 2 +- scripts/noshake.json | 2 + 106 files changed, 714 insertions(+), 561 deletions(-) create mode 100644 Mathlib/Algebra/Order/Field/Canonical.lean delete mode 100644 Mathlib/Algebra/Order/Field/Canonical/Basic.lean delete mode 100644 Mathlib/Algebra/Order/Field/Canonical/Defs.lean diff --git a/Archive/OxfordInvariants/Summer2021/Week3P1.lean b/Archive/OxfordInvariants/Summer2021/Week3P1.lean index d14d56211fd18..785f19fbfa505 100644 --- a/Archive/OxfordInvariants/Summer2021/Week3P1.lean +++ b/Archive/OxfordInvariants/Summer2021/Week3P1.lean @@ -136,6 +136,6 @@ theorem OxfordInvariants.Week3P1 (n : ℕ) (a : ℕ → ℕ) (a_pos : ∀ i ≤ rw [← mul_div_assoc, ← mul_div_right_comm, mul_div_assoc, mul_div_cancel_right₀ _ (a_pos _ <| Nat.le_succ _).ne', mul_comm] -- Check the divisibility condition - · rw [mul_tsub, ← mul_assoc, Nat.mul_div_cancel' ha, add_mul, Nat.mul_div_cancel' han, + · rw [Nat.mul_sub, ← mul_assoc, Nat.mul_div_cancel' ha, add_mul, Nat.mul_div_cancel' han, add_tsub_tsub_cancel ha₀, add_tsub_cancel_right] exact dvd_mul_right _ _ diff --git a/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean b/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean index b2961dcf17622..59a7f0d9f5e26 100644 --- a/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean +++ b/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean @@ -9,16 +9,16 @@ import Mathlib.Algebra.Ring.Subsemiring.Order /-! -A `CanonicallyOrderedCommSemiring` with two different elements `a` and `b` such that +A canonically ordered commutative semiring with two different elements `a` and `b` such that `a ≠ b` and `2 * a = 2 * b`. Thus, multiplication by a fixed non-zero element of a canonically ordered semiring need not be injective. In particular, multiplying by a strictly positive element need not be strictly monotone. -Recall that a `CanonicallyOrderedCommSemiring` is a commutative semiring with a partial ordering -that is "canonical" in the sense that the inequality `a ≤ b` holds if and only if there is a `c` -such that `a + c = b`. There are several compatibility conditions among addition/multiplication -and the order relation. The point of the counterexample is to show that monotonicity of -multiplication cannot be strengthened to **strict** monotonicity. +Recall that a canonically ordered commutative semiring is a commutative semiring with a partial +ordering that is "canonical" in the sense that the inequality `a ≤ b` holds if and only if there is +a `c` such that `a + c = b`. There are several compatibility conditions among +addition/multiplication and the order relation. The point of the counterexample is to show that +monotonicity of multiplication cannot be strengthened to **strict** monotonicity. Reference: https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/canonically_ordered.20pathology @@ -201,13 +201,14 @@ theorem eq_zero_or_eq_zero_of_mul_eq_zero : ∀ a b : L, a * b = 0 → a = 0 ∨ · rfl · exact (hb rfl).elim -instance can : CanonicallyOrderedCommSemiring L := - { (inferInstance : OrderBot L), - (inferInstance : - OrderedCommSemiring L) with - exists_add_of_le := @(exists_add_of_le) - le_self_add := le_self_add - eq_zero_or_eq_zero_of_mul_eq_zero := @(eq_zero_or_eq_zero_of_mul_eq_zero) } +instance : OrderedCommSemiring L := inferInstance + +instance : CanonicallyOrderedAdd L where + exists_add_of_le := @(exists_add_of_le) + le_self_add := le_self_add + +instance : NoZeroDivisors L where + eq_zero_or_eq_zero_of_mul_eq_zero := @(eq_zero_or_eq_zero_of_mul_eq_zero) /-- The elements `(1,0)` and `(1,1)` of `L` are different, but their doubles coincide. -/ diff --git a/Mathlib.lean b/Mathlib.lean index e646e831d9f6d..d5225c3ad97f4 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -675,8 +675,7 @@ import Mathlib.Algebra.Order.CauSeq.Completion import Mathlib.Algebra.Order.Chebyshev import Mathlib.Algebra.Order.CompleteField import Mathlib.Algebra.Order.Field.Basic -import Mathlib.Algebra.Order.Field.Canonical.Basic -import Mathlib.Algebra.Order.Field.Canonical.Defs +import Mathlib.Algebra.Order.Field.Canonical import Mathlib.Algebra.Order.Field.Defs import Mathlib.Algebra.Order.Field.InjSurj import Mathlib.Algebra.Order.Field.Pi diff --git a/Mathlib/Algebra/Associated/OrderedCommMonoid.lean b/Mathlib/Algebra/Associated/OrderedCommMonoid.lean index ab1745e4359de..ba84dc929f4ea 100644 --- a/Mathlib/Algebra/Associated/OrderedCommMonoid.lean +++ b/Mathlib/Algebra/Associated/OrderedCommMonoid.lean @@ -30,9 +30,8 @@ namespace Associates 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 M) where +instance : CanonicallyOrderedMul (Associates M) where exists_mul_of_le h := h le_self_mul _ b := ⟨b, rfl⟩ - bot_le _ := one_le end Associates diff --git a/Mathlib/Algebra/DirectSum/Internal.lean b/Mathlib/Algebra/DirectSum/Internal.lean index 7417729ccc95f..35229ff31057a 100644 --- a/Mathlib/Algebra/DirectSum/Internal.lean +++ b/Mathlib/Algebra/DirectSum/Internal.lean @@ -213,7 +213,7 @@ end coe section CanonicallyOrderedAddCommMonoid variable [Semiring R] [SetLike σ R] [AddSubmonoidClass σ R] (A : ι → σ) -variable [CanonicallyOrderedAddCommMonoid ι] [SetLike.GradedMonoid A] +variable [AddCommMonoid ι] [PartialOrder ι] [CanonicallyOrderedAdd ι] [SetLike.GradedMonoid A] theorem coe_of_mul_apply_of_not_le {i : ι} (r : A i) (r' : ⨁ i, A i) (n : ι) (h : ¬i ≤ n) : ((of (fun i => A i) i r * r') n : R) = 0 := by @@ -240,7 +240,7 @@ theorem coe_mul_of_apply_of_not_le (r : ⨁ i, A i) {i : ι} (r' : A i) (n : ι) variable [Sub ι] [OrderedSub ι] [AddLeftReflectLE ι] /- The following two lemmas only require the same hypotheses as `eq_tsub_iff_add_eq_of_le`, but we - state them for `CanonicallyOrderedAddCommMonoid` + the above three typeclasses for convenience. -/ + state them for the above typeclasses for convenience. -/ theorem coe_mul_of_apply_of_le (r : ⨁ i, A i) {i : ι} (r' : A i) (n : ι) (h : i ≤ n) : ((r * of (fun i => A i) i r') n : R) = r (n - i) * r' := coe_mul_of_apply_aux _ _ _ fun _x => (eq_tsub_iff_add_eq_of_le h).symm diff --git a/Mathlib/Algebra/GeomSum.lean b/Mathlib/Algebra/GeomSum.lean index c845f551fee49..69be1e10b5d9d 100644 --- a/Mathlib/Algebra/GeomSum.lean +++ b/Mathlib/Algebra/GeomSum.lean @@ -269,12 +269,14 @@ theorem geom₂_sum [Field α] {x y : α} (h : x ≠ y) (n : ℕ) : ∑ i ∈ range n, x ^ i * y ^ (n - 1 - i) = (x ^ n - y ^ n) / (x - y) := (Commute.all x y).geom_sum₂ h n -theorem geom₂_sum_of_gt {α : Type*} [CanonicallyLinearOrderedSemifield α] [Sub α] [OrderedSub α] +theorem geom₂_sum_of_gt {α : Type*} [LinearOrderedSemifield α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] {x y : α} (h : y < x) (n : ℕ) : ∑ i ∈ range n, x ^ i * y ^ (n - 1 - i) = (x ^ n - y ^ n) / (x - y) := eq_div_of_mul_eq (tsub_pos_of_lt h).ne' (geom_sum₂_mul_of_ge h.le n) -theorem geom₂_sum_of_lt {α : Type*} [CanonicallyLinearOrderedSemifield α] [Sub α] [OrderedSub α] +theorem geom₂_sum_of_lt {α : Type*} [LinearOrderedSemifield α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] {x y : α} (h : x < y) (n : ℕ) : ∑ i ∈ range n, x ^ i * y ^ (n - 1 - i) = (y ^ n - x ^ n) / (y - x) := eq_div_of_mul_eq (tsub_pos_of_lt h).ne' (geom_sum₂_mul_of_le h.le n) @@ -284,19 +286,22 @@ theorem geom_sum_eq [DivisionRing α] {x : α} (h : x ≠ 1) (n : ℕ) : have : x - 1 ≠ 0 := by simp_all [sub_eq_iff_eq_add] rw [← geom_sum_mul, mul_div_cancel_right₀ _ this] -lemma geom_sum_of_one_lt {x : α} [CanonicallyLinearOrderedSemifield α] [Sub α] [OrderedSub α] +lemma geom_sum_of_one_lt {x : α} [LinearOrderedSemifield α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] (h : 1 < x) (n : ℕ) : ∑ i ∈ Finset.range n, x ^ i = (x ^ n - 1) / (x - 1) := eq_div_of_mul_eq (tsub_pos_of_lt h).ne' (geom_sum_mul_of_one_le h.le n) -lemma geom_sum_of_lt_one {x : α} [CanonicallyLinearOrderedSemifield α] [Sub α] [OrderedSub α] +lemma geom_sum_of_lt_one {x : α} [LinearOrderedSemifield α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] (h : x < 1) (n : ℕ) : ∑ i ∈ Finset.range n, x ^ i = (1 - x ^ n) / (1 - x) := eq_div_of_mul_eq (tsub_pos_of_lt h).ne' (geom_sum_mul_of_le_one h.le n) -theorem geom_sum_lt {x : α} [CanonicallyLinearOrderedSemifield α] [Sub α] [OrderedSub α] +theorem geom_sum_lt {x : α} [LinearOrderedSemifield α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] (h0 : x ≠ 0) (h1 : x < 1) (n : ℕ) : ∑ i ∈ range n, x ^ i < (1 - x)⁻¹ := by - rw [← zero_lt_iff] at h0 + rw [← pos_iff_ne_zero] at h0 rw [geom_sum_of_lt_one h1, div_lt_iff₀, inv_mul_cancel₀, tsub_lt_self_iff] · exact ⟨h0.trans h1, pow_pos h0 n⟩ · rwa [ne_eq, tsub_eq_zero_iff_le, not_le] diff --git a/Mathlib/Algebra/Lie/Subalgebra.lean b/Mathlib/Algebra/Lie/Subalgebra.lean index 42f52c2d75d0b..2e0cfb159ae3d 100644 --- a/Mathlib/Algebra/Lie/Subalgebra.lean +++ b/Mathlib/Algebra/Lie/Subalgebra.lean @@ -502,12 +502,12 @@ instance addCommMonoid : AddCommMonoid (LieSubalgebra R L) where add_comm := sup_comm nsmul := nsmulRec -instance : CanonicallyOrderedAddCommMonoid (LieSubalgebra R L) := - { LieSubalgebra.addCommMonoid, - LieSubalgebra.completeLattice with - add_le_add_left := fun _a _b ↦ sup_le_sup_left - exists_add_of_le := @fun _a b h ↦ ⟨b, (sup_eq_right.2 h).symm⟩ - le_self_add := fun _a _b ↦ le_sup_left } +instance : OrderedAddCommMonoid (LieSubalgebra R L) where + add_le_add_left _ _ := sup_le_sup_left + +instance : CanonicallyOrderedAdd (LieSubalgebra R L) where + exists_add_of_le {_a b} h := ⟨b, (sup_eq_right.2 h).symm⟩ + le_self_add _ _ := le_sup_left @[simp] theorem add_eq_sup : K + K' = K ⊔ K' := diff --git a/Mathlib/Algebra/Module/Submodule/Pointwise.lean b/Mathlib/Algebra/Module/Submodule/Pointwise.lean index 811814d19e270..4528cc709da6b 100644 --- a/Mathlib/Algebra/Module/Submodule/Pointwise.lean +++ b/Mathlib/Algebra/Module/Submodule/Pointwise.lean @@ -165,12 +165,13 @@ theorem add_eq_sup (p q : Submodule R M) : p + q = p ⊔ q := theorem zero_eq_bot : (0 : Submodule R M) = ⊥ := rfl -instance : CanonicallyOrderedAddCommMonoid (Submodule R M) := - { Submodule.pointwiseAddCommMonoid, - Submodule.completeLattice with - add_le_add_left := fun _a _b => sup_le_sup_left - exists_add_of_le := @fun _a b h => ⟨b, (sup_eq_right.2 h).symm⟩ - le_self_add := fun _a _b => le_sup_left } +instance : OrderedAddCommMonoid (Submodule R M) := + { Submodule.pointwiseAddCommMonoid with + add_le_add_left := fun _a _b => sup_le_sup_left } + +instance : CanonicallyOrderedAdd (Submodule R M) where + exists_add_of_le := @fun _a b h => ⟨b, (sup_eq_right.2 h).symm⟩ + le_self_add := fun _a _b => le_sup_left section diff --git a/Mathlib/Algebra/Order/Antidiag/Finsupp.lean b/Mathlib/Algebra/Order/Antidiag/Finsupp.lean index 0f45c2dc2ee32..d0e3eb971a429 100644 --- a/Mathlib/Algebra/Order/Antidiag/Finsupp.lean +++ b/Mathlib/Algebra/Order/Antidiag/Finsupp.lean @@ -135,7 +135,8 @@ lemma mapRange_finsuppAntidiag_eq {e : μ ≃+ μ'} {s : Finset ι} {n : μ} : end AddCommMonoid section CanonicallyOrderedAddCommMonoid -variable [DecidableEq ι] [DecidableEq μ] [CanonicallyOrderedAddCommMonoid μ] [HasAntidiagonal μ] +variable [DecidableEq ι] [DecidableEq μ] [OrderedAddCommMonoid μ] [CanonicallyOrderedAdd μ] + [HasAntidiagonal μ] @[simp] lemma finsuppAntidiag_zero (s : Finset ι) : finsuppAntidiag s (0 : μ) = {0} := by ext f; simp [finsuppAntidiag, ← DFunLike.coe_fn_eq (g := f), -mem_piAntidiag, eq_comm] diff --git a/Mathlib/Algebra/Order/Antidiag/Pi.lean b/Mathlib/Algebra/Order/Antidiag/Pi.lean index aa2f6b9fb2e4a..a507d68457b98 100644 --- a/Mathlib/Algebra/Order/Antidiag/Pi.lean +++ b/Mathlib/Algebra/Order/Antidiag/Pi.lean @@ -189,7 +189,8 @@ lemma piAntidiag_insert [DecidableEq (ι → μ)] (hi : i ∉ s) (n : μ) : end AddCancelCommMonoid section CanonicallyOrderedAddCommMonoid -variable [DecidableEq ι] [CanonicallyOrderedAddCommMonoid μ] [HasAntidiagonal μ] [DecidableEq μ] +variable [DecidableEq ι] [OrderedAddCommMonoid μ] [CanonicallyOrderedAdd μ] + [HasAntidiagonal μ] [DecidableEq μ] @[simp] lemma piAntidiag_zero (s : Finset ι) : piAntidiag s (0 : μ) = {0} := by ext; simp [Fintype.sum_eq_zero_iff_of_nonneg, funext_iff, not_imp_comm, ← forall_and] diff --git a/Mathlib/Algebra/Order/Antidiag/Prod.lean b/Mathlib/Algebra/Order/Antidiag/Prod.lean index be149cefc1477..f17f13c3d0308 100644 --- a/Mathlib/Algebra/Order/Antidiag/Prod.lean +++ b/Mathlib/Algebra/Order/Antidiag/Prod.lean @@ -122,8 +122,8 @@ lemma antidiagonal_congr' (hp : p ∈ antidiagonal n) (hq : q ∈ antidiagonal n end AddCancelCommMonoid -section CanonicallyOrderedAddCommMonoid -variable [CanonicallyOrderedAddCommMonoid A] [HasAntidiagonal A] +section CanonicallyOrderedAdd +variable [OrderedAddCommMonoid A] [CanonicallyOrderedAdd A] [HasAntidiagonal A] @[simp] theorem antidiagonal_zero : antidiagonal (0 : A) = {(0, 0)} := by @@ -140,10 +140,10 @@ theorem antidiagonal.snd_le {n : A} {kl : A × A} (hlk : kl ∈ antidiagonal n) use kl.1 rwa [mem_antidiagonal, eq_comm, add_comm] at hlk -end CanonicallyOrderedAddCommMonoid +end CanonicallyOrderedAdd section OrderedSub -variable [CanonicallyOrderedAddCommMonoid A] [Sub A] [OrderedSub A] +variable [OrderedAddCommMonoid A] [CanonicallyOrderedAdd A] [Sub A] [OrderedSub A] variable [AddLeftReflectLE A] variable [HasAntidiagonal A] @@ -184,7 +184,7 @@ def sigmaAntidiagonalEquivProd [AddMonoid A] [HasAntidiagonal A] : right_inv _ := rfl variable {A : Type*} - [CanonicallyOrderedAddCommMonoid A] + [OrderedAddCommMonoid A] [CanonicallyOrderedAdd A] [LocallyFiniteOrder A] [DecidableEq A] /-- In a canonically ordered add monoid, the antidiagonal can be construct by filtering. diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean index 8da6b95c4a1f9..411fb19700d73 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean @@ -337,9 +337,9 @@ theorem card_le_card_biUnion_add_one {s : Finset ι} {f : ι → Finset α} (hf end DoubleCounting -section CanonicallyOrderedCommMonoid +section CanonicallyOrderedMul -variable [CanonicallyOrderedCommMonoid M] {f : ι → M} {s t : Finset ι} +variable [OrderedCommMonoid M] [CanonicallyOrderedMul M] {f : ι → M} {s t : Finset ι} /-- In a canonically-ordered monoid, a product bounds each of its terms. @@ -375,7 +375,7 @@ theorem prod_le_prod_of_ne_one' (h : ∀ x ∈ s, f x ≠ 1 → x ∈ t) : (prod_le_one' <| by simp only [mem_filter, and_imp]; exact fun _ _ ↦ le_of_eq) (prod_le_prod_of_subset' <| by simpa only [subset_iff, mem_filter, and_imp] ) -end CanonicallyOrderedCommMonoid +end CanonicallyOrderedMul section OrderedCancelCommMonoid diff --git a/Mathlib/Algebra/Order/BigOperators/Group/List.lean b/Mathlib/Algebra/Order/BigOperators/Group/List.lean index e2cec9a39e288..96c263923b0ad 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/List.lean @@ -177,8 +177,8 @@ lemma all_one_of_le_one_le_of_prod_eq_one [OrderedCommMonoid M] {l : List M} (hl₁ : ∀ x ∈ l, (1 : M) ≤ x) (hl₂ : l.prod = 1) {x : M} (hx : x ∈ l) : x = 1 := _root_.le_antisymm (hl₂ ▸ single_le_prod hl₁ _ hx) (hl₁ x hx) -section CanonicallyOrderedCommMonoid -variable [CanonicallyOrderedCommMonoid M] {l : List M} +section CanonicallyOrderedMul +variable [OrderedCommMonoid M] [CanonicallyOrderedMul M] {l : List M} @[to_additive] lemma prod_eq_one_iff : l.prod = 1 ↔ ∀ x ∈ l, x = (1 : M) := ⟨all_one_of_le_one_le_of_prod_eq_one fun _ _ => one_le _, fun h => by @@ -206,5 +206,6 @@ theorem le_prod_of_mem {xs : List M} {x : M} (h₁ : x ∈ xs) : x ≤ xs.prod : simp only [List.prod_cons] exact le_mul_left ih -end CanonicallyOrderedCommMonoid +end CanonicallyOrderedMul + end List diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean index d77b13d8de6a0..3515746f19350 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean @@ -138,8 +138,8 @@ lemma prod_lt_prod_of_nonempty' (hs : s ≠ ∅) (hfg : ∀ i ∈ s, f i < g i) end OrderedCancelCommMonoid -section CanonicallyOrderedCommMonoid -variable [CanonicallyOrderedCommMonoid α] {m : Multiset α} {a : α} +section CanonicallyOrderedMul +variable [OrderedCommMonoid α] [CanonicallyOrderedMul α] {m : Multiset α} {a : α} @[to_additive] lemma prod_eq_one_iff : m.prod = 1 ↔ ∀ x ∈ m, x = (1 : α) := Quotient.inductionOn m fun l ↦ by simpa using List.prod_eq_one_iff @@ -149,7 +149,7 @@ variable [CanonicallyOrderedCommMonoid α] {m : Multiset α} {a : α} rw [prod_cons] exact _root_.le_mul_right (le_refl a) -end CanonicallyOrderedCommMonoid +end CanonicallyOrderedMul lemma max_le_of_forall_le {α : Type*} [LinearOrder α] [OrderBot α] (l : Multiset α) (n : α) (h : ∀ x ∈ l, x ≤ n) : l.fold max ⊥ ≤ n := by diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean index 96a7184d1eef9..a78ba5b506d74 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean @@ -131,16 +131,18 @@ theorem PNat.coe_prod {ι : Type*} (f : ι → ℕ+) (s : Finset ι) : ↑(∏ i ∈ s, f i) = (∏ i ∈ s, f i : ℕ) := map_prod PNat.coeMonoidHom _ _ -section CanonicallyOrderedCommSemiring -variable [CanonicallyOrderedCommSemiring R] {f g h : ι → R} {s : Finset ι} {i : ι} +section CanonicallyOrderedAdd +variable [CommSemiring R] [PartialOrder R] [CanonicallyOrderedAdd R] + {f g h : ι → R} {s : Finset ι} {i : ι} -/-- Note that the name is to match `CanonicallyOrderedCommSemiring.mul_pos`. -/ -@[simp] lemma _root_.CanonicallyOrderedCommSemiring.prod_pos [Nontrivial R] : +/-- Note that the name is to match `CanonicallyOrderedAdd.mul_pos`. -/ +@[simp] lemma _root_.CanonicallyOrderedAdd.prod_pos [NoZeroDivisors R] [Nontrivial R] : 0 < ∏ i ∈ s, f i ↔ (∀ i ∈ s, (0 : R) < f i) := - CanonicallyOrderedCommSemiring.multiset_prod_pos.trans Multiset.forall_mem_map_iff + CanonicallyOrderedAdd.multiset_prod_pos.trans Multiset.forall_mem_map_iff +attribute [local instance] CanonicallyOrderedAdd.toOrderedCommMonoid in /-- If `g, h ≤ f` and `g i + h i ≤ f i`, then the product of `f` over `s` is at least the - sum of the products of `g` and `h`. This is the version for `CanonicallyOrderedCommSemiring`. + sum of the products of `g` and `h`. This is the version for `CanonicallyOrderedAdd`. -/ lemma prod_add_prod_le' (hi : i ∈ s) (h2i : g i + h i ≤ f i) (hgf : ∀ j ∈ s, j ≠ i → g j ≤ f j) (hhf : ∀ j ∈ s, j ≠ i → h j ≤ f j) : ((∏ i ∈ s, g i) + ∏ i ∈ s, h i) ≤ ∏ i ∈ s, f i := by @@ -150,7 +152,7 @@ lemma prod_add_prod_le' (hi : i ∈ s) (h2i : g i + h i ≤ f i) (hgf : ∀ j rw [right_distrib] gcongr with j hj j hj <;> simp_all -end CanonicallyOrderedCommSemiring +end CanonicallyOrderedAdd /-! ### Named inequalities -/ diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/List.lean b/Mathlib/Algebra/Order/BigOperators/Ring/List.lean index f25734ab623a9..430a8c46ccb01 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/List.lean @@ -14,10 +14,10 @@ This file contains the results concerning the interaction of list big operators variable {R : Type*} -/-- A variant of `List.prod_pos` for `CanonicallyOrderedCommSemiring`. -/ -@[simp] lemma CanonicallyOrderedCommSemiring.list_prod_pos - {α : Type*} [CanonicallyOrderedCommSemiring α] [Nontrivial α] : +/-- A variant of `List.prod_pos` for `CanonicallyOrderedAdd`. -/ +@[simp] lemma CanonicallyOrderedAdd.list_prod_pos {α : Type*} + [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] [NoZeroDivisors α] [Nontrivial α] : ∀ {l : List α}, 0 < l.prod ↔ (∀ x ∈ l, (0 : α) < x) | [] => by simp - | (x :: xs) => by simp_rw [List.prod_cons, List.forall_mem_cons, - CanonicallyOrderedCommSemiring.mul_pos, list_prod_pos] + | (x :: xs) => by simp_rw [List.prod_cons, List.forall_mem_cons, CanonicallyOrderedAdd.mul_pos, + list_prod_pos] diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean b/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean index 8bb7e4a3cdaed..cd4c9e96c4d7a 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/Multiset.lean @@ -14,9 +14,9 @@ rings. -/ @[simp] -lemma CanonicallyOrderedCommSemiring.multiset_prod_pos {R : Type*} - [CanonicallyOrderedCommSemiring R] [Nontrivial R] {m : Multiset R} : - 0 < m.prod ↔ ∀ x ∈ m, 0 < x := by +lemma CanonicallyOrderedAdd.multiset_prod_pos {R : Type*} + [CommSemiring R] [PartialOrder R] [CanonicallyOrderedAdd R] [NoZeroDivisors R] [Nontrivial R] + {m : Multiset R} : 0 < m.prod ↔ ∀ x ∈ m, 0 < x := by rcases m with ⟨l⟩ rw [Multiset.quot_mk_to_coe'', Multiset.prod_coe] - exact CanonicallyOrderedCommSemiring.list_prod_pos + exact CanonicallyOrderedAdd.list_prod_pos diff --git a/Mathlib/Algebra/Order/Field/Canonical.lean b/Mathlib/Algebra/Order/Field/Canonical.lean new file mode 100644 index 0000000000000..512b93cdd1c40 --- /dev/null +++ b/Mathlib/Algebra/Order/Field/Canonical.lean @@ -0,0 +1,36 @@ +/- +Copyright (c) 2014 Robert Y. Lewis. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Robert Y. Lewis, Leonardo de Moura, Mario Carneiro, Floris van Doorn +-/ +import Mathlib.Algebra.Order.Field.Defs +import Mathlib.Algebra.Order.GroupWithZero.Canonical +import Mathlib.Algebra.Order.Ring.Canonical + +/-! +# Canonically ordered semifields +-/ + +set_option linter.deprecated false in +/-- A canonically linear ordered field is a linear ordered field in which `a ≤ b` iff there exists +`c` with `b = a + c`. -/ +@[deprecated "Use `[LinearOrderedSemifield α] [CanonicallyOrderedAdd α]` instead." + (since := "2025-01-13")] +structure CanonicallyLinearOrderedSemifield (α : Type*) extends CanonicallyOrderedCommSemiring α, + LinearOrderedSemifield α + +attribute [nolint docBlame] CanonicallyLinearOrderedSemifield.toLinearOrderedSemifield + +variable {α : Type*} [LinearOrderedSemifield α] [CanonicallyOrderedAdd α] + +-- See note [reducible non-instances] +/-- Construct a `LinearOrderedCommGroupWithZero` from a canonically ordered +`LinearOrderedSemifield`. -/ +abbrev LinearOrderedSemifield.toLinearOrderedCommGroupWithZero : + LinearOrderedCommGroupWithZero α := + { ‹LinearOrderedSemifield α› with + mul_le_mul_left := fun _ _ h _ ↦ mul_le_mul_of_nonneg_left h <| zero_le _ } + +variable [Sub α] [OrderedSub α] + +theorem tsub_div (a b c : α) : (a - b) / c = a / c - b / c := by simp_rw [div_eq_mul_inv, tsub_mul] diff --git a/Mathlib/Algebra/Order/Field/Canonical/Basic.lean b/Mathlib/Algebra/Order/Field/Canonical/Basic.lean deleted file mode 100644 index ac3b9f3e55d5d..0000000000000 --- a/Mathlib/Algebra/Order/Field/Canonical/Basic.lean +++ /dev/null @@ -1,22 +0,0 @@ -/- -Copyright (c) 2014 Robert Y. Lewis. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Robert Y. Lewis, Leonardo de Moura, Mario Carneiro, Floris van Doorn --/ -import Mathlib.Algebra.Order.Field.Canonical.Defs - -/-! -# Lemmas about canonically ordered semifields. - --/ - - -variable {α : Type*} - -section CanonicallyLinearOrderedSemifield - -variable [CanonicallyLinearOrderedSemifield α] [Sub α] [OrderedSub α] - -theorem tsub_div (a b c : α) : (a - b) / c = a / c - b / c := by simp_rw [div_eq_mul_inv, tsub_mul] - -end CanonicallyLinearOrderedSemifield diff --git a/Mathlib/Algebra/Order/Field/Canonical/Defs.lean b/Mathlib/Algebra/Order/Field/Canonical/Defs.lean deleted file mode 100644 index 0242074ec4697..0000000000000 --- a/Mathlib/Algebra/Order/Field/Canonical/Defs.lean +++ /dev/null @@ -1,31 +0,0 @@ -/- -Copyright (c) 2014 Robert Y. Lewis. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Robert Y. Lewis, Leonardo de Moura, Mario Carneiro, Floris van Doorn --/ -import Mathlib.Algebra.Order.Field.Defs -import Mathlib.Algebra.Order.Ring.Canonical -import Mathlib.Algebra.Order.GroupWithZero.Canonical - -/-! -# Canonically ordered semifields --/ - - -variable {α : Type*} - -/-- A canonically linear ordered field is a linear ordered field in which `a ≤ b` iff there exists -`c` with `b = a + c`. -/ -class CanonicallyLinearOrderedSemifield (α : Type*) extends CanonicallyOrderedCommSemiring α, - LinearOrderedSemifield α - --- See note [lower instance priority] -instance (priority := 100) CanonicallyLinearOrderedSemifield.toLinearOrderedCommGroupWithZero - [CanonicallyLinearOrderedSemifield α] : LinearOrderedCommGroupWithZero α := - { ‹CanonicallyLinearOrderedSemifield α› with - mul_le_mul_left := fun _ _ h _ ↦ mul_le_mul_of_nonneg_left h <| zero_le _ } - --- See note [lower instance priority] -instance (priority := 100) CanonicallyLinearOrderedSemifield.toCanonicallyLinearOrderedAddCommMonoid - [CanonicallyLinearOrderedSemifield α] : CanonicallyLinearOrderedAddCommMonoid α := - { ‹CanonicallyLinearOrderedSemifield α› with } diff --git a/Mathlib/Algebra/Order/Field/Rat.lean b/Mathlib/Algebra/Order/Field/Rat.lean index 7b6ba3bfd819a..05a7d3cf7f00c 100644 --- a/Mathlib/Algebra/Order/Field/Rat.lean +++ b/Mathlib/Algebra/Order/Field/Rat.lean @@ -28,7 +28,4 @@ instance instLinearOrderedField : LinearOrderedField ℚ where end Rat --- The `LinearOrderedSemifield` and `LinearOrderedCommGroupWithZero` instances are shortcut --- instances for performance -deriving instance CanonicallyLinearOrderedSemifield, LinearOrderedSemifield, - LinearOrderedCommGroupWithZero for NNRat +deriving instance LinearOrderedSemifield, LinearOrderedCommGroupWithZero for NNRat diff --git a/Mathlib/Algebra/Order/Group/Finset.lean b/Mathlib/Algebra/Order/Group/Finset.lean index e3f518734c79d..a5cf93a82ef0e 100644 --- a/Mathlib/Algebra/Order/Group/Finset.lean +++ b/Mathlib/Algebra/Order/Group/Finset.lean @@ -82,8 +82,8 @@ lemma mul_sup' [MulLeftMono G] (s : Finset ι) (f : ι → G) (a : G) (hs) : end Group section CanonicallyLinearOrderedAddCommMonoid -variable [CanonicallyLinearOrderedAddCommMonoid M] [Sub M] [AddLeftReflectLE M] [OrderedSub M] - {s : Finset ι} {t : Finset κ} +variable [LinearOrderedAddCommMonoid M] [CanonicallyOrderedAdd M] + [Sub M] [AddLeftReflectLE M] [OrderedSub M] {s : Finset ι} {t : Finset κ} /-- Also see `Finset.sup'_add` that works for ordered groups. -/ lemma sup'_add' (s : Finset ι) (f : ι → M) (a : M) (hs : s.Nonempty) : diff --git a/Mathlib/Algebra/Order/Group/Indicator.lean b/Mathlib/Algebra/Order/Group/Indicator.lean index 8815f20762709..bf3aeec078065 100644 --- a/Mathlib/Algebra/Order/Group/Indicator.lean +++ b/Mathlib/Algebra/Order/Group/Indicator.lean @@ -200,9 +200,9 @@ lemma iSup_mulIndicator {ι : Type*} [Preorder ι] [IsDirected ι (· ≤ ·)] { end CompleteLattice -section CanonicallyOrderedCommMonoid +section CanonicallyOrderedMul -variable [CanonicallyOrderedCommMonoid M] +variable [Monoid M] [PartialOrder M] [CanonicallyOrderedMul M] @[to_additive] lemma mulIndicator_le_self (s : Set α) (f : α → M) : mulIndicator s f ≤ f := @@ -218,7 +218,7 @@ lemma mulIndicator_le {s : Set α} {f g : α → M} (hfg : ∀ a ∈ s, f a ≤ mulIndicator s f ≤ g := mulIndicator_le' hfg fun _ _ ↦ one_le _ -end CanonicallyOrderedCommMonoid +end CanonicallyOrderedMul section LinearOrderedCommGroup variable [LinearOrderedCommGroup M] diff --git a/Mathlib/Algebra/Order/Group/Nat.lean b/Mathlib/Algebra/Order/Group/Nat.lean index 573f796727abc..0935b82a632e0 100644 --- a/Mathlib/Algebra/Order/Group/Nat.lean +++ b/Mathlib/Algebra/Order/Group/Nat.lean @@ -20,11 +20,11 @@ namespace Nat /-! ### Instances -/ -instance instCanonicallyLinearOrderedAddCommMonoid : CanonicallyLinearOrderedAddCommMonoid ℕ where +instance instLinearOrderedAddCommMonoid : LinearOrderedAddCommMonoid ℕ where __ := instLinearOrder - bot := 0 - bot_le := Nat.zero_le add_le_add_left := @Nat.add_le_add_left + +instance instCanonicallyOrderedAdd : CanonicallyOrderedAdd ℕ where le_self_add := Nat.le_add_right exists_add_of_le := Nat.exists_eq_add_of_le diff --git a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean index 5c4e16d2e9c36..2b1886a061185 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean @@ -43,8 +43,8 @@ instance (priority := 100) LinearOrderedCommMonoidWithZero.toZeroLeOneClass [LinearOrderedCommMonoidWithZero α] : ZeroLEOneClass α := { ‹LinearOrderedCommMonoidWithZero α› with } -instance (priority := 100) canonicallyOrderedAddCommMonoid.toZeroLeOneClass - [CanonicallyOrderedAddCommMonoid α] [One α] : ZeroLEOneClass α := +instance (priority := 100) CanonicallyOrderedAdd.toZeroLeOneClass + [AddZeroClass α] [LE α] [CanonicallyOrderedAdd α] [One α] : ZeroLEOneClass α := ⟨zero_le 1⟩ section LinearOrderedCommMonoidWithZero @@ -371,13 +371,10 @@ protected abbrev orderedAddCommMonoid [OrderedAddCommMonoid α] (zero_le : ∀ a { WithZero.partialOrder, WithZero.addCommMonoid with add_le_add_left := @add_le_add_left _ _ _ (WithZero.addLeftMono zero_le).. } --- This instance looks absurd: a monoid already has a zero /-- Adding a new zero to a canonically ordered additive monoid produces another one. -/ -instance canonicallyOrderedAddCommMonoid [CanonicallyOrderedAddCommMonoid α] : - CanonicallyOrderedAddCommMonoid (WithZero α) := - { WithZero.orderBot, - WithZero.orderedAddCommMonoid _root_.zero_le, - WithZero.existsAddOfLE with +instance canonicallyOrderedAdd [AddZeroClass α] [Preorder α] [CanonicallyOrderedAdd α] : + CanonicallyOrderedAdd (WithZero α) := + { WithZero.existsAddOfLE with le_self_add := fun a b => by induction a · exact bot_le @@ -385,10 +382,6 @@ instance canonicallyOrderedAddCommMonoid [CanonicallyOrderedAddCommMonoid α] : · exact le_rfl · exact WithZero.coe_le_coe.2 le_self_add } -instance canonicallyLinearOrderedAddCommMonoid [CanonicallyLinearOrderedAddCommMonoid α] : - CanonicallyLinearOrderedAddCommMonoid (WithZero α) := - { WithZero.canonicallyOrderedAddCommMonoid, WithZero.linearOrder with } - instance instLinearOrderedCommMonoidWithZero [LinearOrderedCommMonoid α] : LinearOrderedCommMonoidWithZero (WithZero α) := { WithZero.linearOrder, WithZero.commMonoidWithZero with diff --git a/Mathlib/Algebra/Order/Kleene.lean b/Mathlib/Algebra/Order/Kleene.lean index 96c7b6b8be108..d7ef7645143e0 100644 --- a/Mathlib/Algebra/Order/Kleene.lean +++ b/Mathlib/Algebra/Order/Kleene.lean @@ -160,13 +160,17 @@ theorem add_le (ha : a ≤ c) (hb : b ≤ c) : a + b ≤ c := add_le_iff.2 ⟨ha, hb⟩ -- See note [lower instance priority] -instance (priority := 100) IdemSemiring.toCanonicallyOrderedAddCommMonoid : - CanonicallyOrderedAddCommMonoid α := +instance (priority := 100) IdemSemiring.toOrderedAddCommMonoid : + OrderedAddCommMonoid α := { ‹IdemSemiring α› with add_le_add_left := fun a b hbc c ↦ by simp_rw [add_eq_sup] - exact sup_le_sup_left hbc _ - exists_add_of_le := fun h ↦ ⟨_, h.add_eq_right.symm⟩ + exact sup_le_sup_left hbc _ } + +-- See note [lower instance priority] +instance (priority := 100) IdemSemiring.toCanonicallyOrderedAdd : + CanonicallyOrderedAdd α := + { exists_add_of_le := fun h ↦ ⟨_, h.add_eq_right.symm⟩ le_self_add := fun a b ↦ add_eq_right_iff_le.1 <| by rw [← add_assoc, add_idem] } -- See note [lower instance priority] diff --git a/Mathlib/Algebra/Order/Monoid/Canonical/Basic.lean b/Mathlib/Algebra/Order/Monoid/Canonical/Basic.lean index 8ae63f4a7bd30..911a75a124c4b 100644 --- a/Mathlib/Algebra/Order/Monoid/Canonical/Basic.lean +++ b/Mathlib/Algebra/Order/Monoid/Canonical/Basic.lean @@ -11,7 +11,8 @@ import Mathlib.Data.Finset.Lattice.Fold -/ namespace Finset -variable {ι α : Type*} [CanonicallyLinearOrderedAddCommMonoid α] {s : Finset ι} {f : ι → α} +variable {ι α : Type*} [LinearOrderedAddCommMonoid α] [CanonicallyOrderedAdd α] + {s : Finset ι} {f : ι → α} @[simp] lemma sup_eq_zero : s.sup f = 0 ↔ ∀ i ∈ s, f i = 0 := by simp [← bot_eq_zero'] @[simp] lemma sup'_eq_zero (hs) : s.sup' hs f = 0 ↔ ∀ i ∈ s, f i = 0 := by simp [sup'_eq_sup] diff --git a/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean b/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean index 4812ae6f97d73..fac09c291a486 100644 --- a/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean +++ b/Mathlib/Algebra/Order/Monoid/Canonical/Defs.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, Leonardo de Moura, Mario Carneiro, Johannes Hölzl +Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl, Yuyang Zhao -/ import Mathlib.Algebra.Group.Units.Basic import Mathlib.Algebra.Order.Monoid.Defs @@ -17,20 +17,49 @@ universe u variable {α : Type u} +/-- An ordered additive monoid is `CanonicallyOrderedAdd` + if the ordering coincides with the subtractibility relation, + which is to say, `a ≤ b` iff there exists `c` with `b = a + c`. + This is satisfied by the natural numbers, for example, but not + the integers or other nontrivial `OrderedAddCommGroup`s. -/ +class CanonicallyOrderedAdd (α : Type*) [Add α] [LE α] extends + ExistsAddOfLE α : Prop where + /-- For any `a` and `b`, `a ≤ a + b` -/ + protected le_self_add : ∀ a b : α, a ≤ a + b + +attribute [instance 50] CanonicallyOrderedAdd.toExistsAddOfLE + +/-- An ordered monoid is `CanonicallyOrderedMul` + if the ordering coincides with the divisibility relation, + which is to say, `a ≤ b` iff there exists `c` with `b = a * c`. + Examples seem rare; it seems more likely that the `OrderDual` + of a naturally-occurring lattice satisfies this than the lattice + itself (for example, dual of the lattice of ideals of a PID or + Dedekind domain satisfy this; collections of all things ≤ 1 seem to + be more natural that collections of all things ≥ 1). -/ +@[to_additive] +class CanonicallyOrderedMul (α : Type*) [Mul α] [LE α] extends + ExistsMulOfLE α : Prop where + /-- For any `a` and `b`, `a ≤ a * b` -/ + protected le_self_mul : ∀ a b : α, a ≤ a * b + +attribute [instance 50] CanonicallyOrderedMul.toExistsMulOfLE + /-- A canonically ordered additive monoid is an ordered commutative additive monoid in which the ordering coincides with the subtractibility relation, which is to say, `a ≤ b` iff there exists `c` with `b = a + c`. This is satisfied by the natural numbers, for example, but not the integers or other nontrivial `OrderedAddCommGroup`s. -/ -class CanonicallyOrderedAddCommMonoid (α : Type*) extends OrderedAddCommMonoid α, OrderBot α where +@[deprecated "Use `[OrderedAddCommMonoid α] [CanonicallyOrderedAdd α]` instead." + (since := "2025-01-13")] +structure CanonicallyOrderedAddCommMonoid (α : Type*) extends + OrderedAddCommMonoid α, OrderBot α where /-- For `a ≤ b`, there is a `c` so `b = a + c`. -/ protected exists_add_of_le : ∀ {a b : α}, a ≤ b → ∃ c, b = a + c /-- For any `a` and `b`, `a ≤ a + b` -/ protected le_self_add : ∀ a b : α, a ≤ a + b --- see Note [lower instance priority] -attribute [instance 100] CanonicallyOrderedAddCommMonoid.toOrderBot - +set_option linter.existingAttributeWarning false in /-- A canonically ordered monoid is an ordered commutative monoid in which the ordering coincides with the divisibility relation, which is to say, `a ≤ b` iff there exists `c` with `b = a * c`. @@ -40,82 +69,124 @@ attribute [instance 100] CanonicallyOrderedAddCommMonoid.toOrderBot Dedekind domain satisfy this; collections of all things ≤ 1 seem to be more natural that collections of all things ≥ 1). -/ -@[to_additive] -class CanonicallyOrderedCommMonoid (α : Type*) extends OrderedCommMonoid α, OrderBot α where +@[to_additive, + deprecated "Use `[OrderedCommMonoid α] [CanonicallyOrderedMul α]` instead." + (since := "2025-01-13")] +structure CanonicallyOrderedCommMonoid (α : Type*) extends OrderedCommMonoid α, OrderBot α where /-- For `a ≤ b`, there is a `c` so `b = a * c`. -/ protected exists_mul_of_le : ∀ {a b : α}, a ≤ b → ∃ c, b = a * c /-- For any `a` and `b`, `a ≤ a * b` -/ protected le_self_mul : ∀ a b : α, a ≤ a * b --- see Note [lower instance priority] -attribute [instance 100] CanonicallyOrderedCommMonoid.toOrderBot +section Mul +variable [Mul α] + +section LE +variable [LE α] [CanonicallyOrderedMul α] {a b c : α} + +@[to_additive] +theorem le_self_mul : a ≤ a * b := + CanonicallyOrderedMul.le_self_mul _ _ + +@[to_additive (attr := simp)] +theorem self_le_mul_right (a b : α) : a ≤ a * b := + le_self_mul --- see Note [lower instance priority] @[to_additive] -instance (priority := 100) CanonicallyOrderedCommMonoid.existsMulOfLE (α : Type u) - [h : CanonicallyOrderedCommMonoid α] : ExistsMulOfLE α := - { h with } +theorem le_iff_exists_mul : a ≤ b ↔ ∃ c, b = a * c := + ⟨exists_mul_of_le, by + rintro ⟨c, rfl⟩ + exact le_self_mul⟩ -section CanonicallyOrderedCommMonoid +end LE -variable [CanonicallyOrderedCommMonoid α] {a b c : α} +section Preorder +variable [Preorder α] [CanonicallyOrderedMul α] {a b c : α} + +@[to_additive] +theorem le_of_mul_le_left : a * b ≤ c → a ≤ c := + le_self_mul.trans @[to_additive] -theorem le_self_mul : a ≤ a * c := - CanonicallyOrderedCommMonoid.le_self_mul _ _ +theorem le_mul_of_le_left : a ≤ b → a ≤ b * c := + le_self_mul.trans' + +@[to_additive] alias le_mul_right := le_mul_of_le_left + +end Preorder + +end Mul + +section CommMagma +variable [CommMagma α] + +section LE +variable [LE α] [CanonicallyOrderedMul α] {a b : α} @[to_additive] theorem le_mul_self : a ≤ b * a := by rw [mul_comm] exact le_self_mul -@[to_additive (attr := simp)] -theorem self_le_mul_right (a b : α) : a ≤ a * b := - le_self_mul - @[to_additive (attr := simp)] theorem self_le_mul_left (a b : α) : a ≤ b * a := le_mul_self -@[to_additive] -theorem le_of_mul_le_left : a * b ≤ c → a ≤ c := - le_self_mul.trans +end LE + +section Preorder +variable [Preorder α] [CanonicallyOrderedMul α] {a b c : α} @[to_additive] theorem le_of_mul_le_right : a * b ≤ c → b ≤ c := le_mul_self.trans -@[to_additive] -theorem le_mul_of_le_left : a ≤ b → a ≤ b * c := - le_self_mul.trans' - @[to_additive] theorem le_mul_of_le_right : a ≤ c → a ≤ b * c := le_mul_self.trans' -@[to_additive] -theorem le_iff_exists_mul : a ≤ b ↔ ∃ c, b = a * c := - ⟨exists_mul_of_le, by - rintro ⟨c, rfl⟩ - exact le_self_mul⟩ +@[to_additive] alias le_mul_left := le_mul_of_le_right @[to_additive] theorem le_iff_exists_mul' : a ≤ b ↔ ∃ c, b = c * a := by simp only [mul_comm _ a, le_iff_exists_mul] +end Preorder + +end CommMagma + +section MulOneClass +variable [MulOneClass α] + +section LE +variable [LE α] [CanonicallyOrderedMul α] {a b : α} + @[to_additive (attr := simp) zero_le] theorem one_le (a : α) : 1 ≤ a := - le_iff_exists_mul.mpr ⟨a, (one_mul _).symm⟩ + le_self_mul.trans_eq (one_mul _) @[to_additive] -theorem bot_eq_one : (⊥ : α) = 1 := - le_antisymm bot_le (one_le ⊥) +instance (priority := 10) CanonicallyOrderedMul.toOrderBot : OrderBot α where + bot := 1 + bot_le := one_le -@[to_additive] instance CanonicallyOrderedCommMonoid.toUniqueUnits : Unique αˣ where - uniq a := Units.ext ((mul_eq_one_iff_of_one_le (α := α) (one_le _) <| one_le _).1 a.mul_inv).1 +end LE -@[deprecated (since := "2024-07-24")] alias mul_eq_one_iff := mul_eq_one -@[deprecated (since := "2024-07-24")] alias add_eq_zero_iff := add_eq_zero +section Preorder +variable [Preorder α] [CanonicallyOrderedMul α] {a b : α} + +@[to_additive (attr := simp)] +theorem one_lt_of_gt (h : a < b) : 1 < b := + (one_le _).trans_lt h + +end Preorder + +section PartialOrder +variable [PartialOrder α] [CanonicallyOrderedMul α] {a b c : α} + +@[to_additive] +theorem bot_eq_one : (⊥ : α) = 1 := + le_antisymm bot_le (one_le ⊥) @[to_additive (attr := simp)] theorem le_one_iff_eq_one : a ≤ 1 ↔ a = 1 := @@ -132,10 +203,6 @@ theorem eq_one_or_one_lt (a : α) : a = 1 ∨ 1 < a := (one_le a).eq_or_lt.imp_l lemma one_not_mem_iff {s : Set α} : 1 ∉ s ↔ ∀ x ∈ s, 1 < x := bot_eq_one (α := α) ▸ bot_not_mem_iff -@[to_additive (attr := simp) add_pos_iff] -theorem one_lt_mul_iff : 1 < a * b ↔ 1 < a ∨ 1 < b := by - simp only [one_lt_iff_ne_one, Ne, mul_eq_one, not_and_or] - @[to_additive] theorem exists_one_lt_mul_of_lt (h : a < b) : ∃ (c : _) (_ : 1 < c), a * c = b := by obtain ⟨c, hc⟩ := le_iff_exists_mul.1 h.le @@ -143,18 +210,6 @@ theorem exists_one_lt_mul_of_lt (h : a < b) : ∃ (c : _) (_ : 1 < c), a * c = b rintro rfl simp [hc, lt_irrefl] at h -@[to_additive] -theorem le_mul_left (h : a ≤ c) : a ≤ b * c := - calc - a = 1 * a := by simp - _ ≤ b * c := mul_le_mul' (one_le _) h - -@[to_additive] -theorem le_mul_right (h : a ≤ b) : a ≤ b * c := - calc - a = a * 1 := by simp - _ ≤ b * c := mul_le_mul' h (one_le _) - @[to_additive] theorem lt_iff_exists_mul [MulLeftStrictMono α] : a < b ↔ ∃ c > 1, b = a * c := by rw [lt_iff_le_and_ne, le_iff_exists_mul, ← exists_and_right] @@ -170,47 +225,103 @@ theorem lt_iff_exists_mul [MulLeftStrictMono α] : a < b ↔ ∃ c > 1, b = a * · rw [← (self_le_mul_right a c).lt_iff_ne] apply lt_mul_of_one_lt_right' -end CanonicallyOrderedCommMonoid +end PartialOrder + +end MulOneClass -theorem pos_of_gt {M : Type*} [CanonicallyOrderedAddCommMonoid M] {n m : M} (h : n < m) : 0 < m := - lt_of_le_of_lt (zero_le _) h +section Semigroup +variable [Semigroup α] + +section LE +variable [LE α] [CanonicallyOrderedMul α] + +-- see Note [lower instance priority] +@[to_additive] +instance (priority := 10) CanonicallyOrderedMul.toMulLeftMono : + MulLeftMono α where + elim a b c hbc := by + obtain ⟨c, hc, rfl⟩ := exists_mul_of_le hbc + rw [le_iff_exists_mul] + exact ⟨c, (mul_assoc _ _ _).symm⟩ + +end LE + +end Semigroup + +section Monoid +variable [Monoid α] + +section PartialOrder +variable [PartialOrder α] [CanonicallyOrderedMul α] {a b c : α} + +@[to_additive] instance CanonicallyOrderedCommMonoid.toUniqueUnits : Unique αˣ where + uniq a := Units.ext <| le_one_iff_eq_one.mp (le_of_mul_le_left a.mul_inv.le) + +end PartialOrder + +end Monoid + +section CommMonoid +variable [CommMonoid α] + +section PartialOrder +variable [PartialOrder α] [CanonicallyOrderedMul α] {a b c : α} + +@[to_additive (attr := simp) add_pos_iff] +theorem one_lt_mul_iff : 1 < a * b ↔ 1 < a ∨ 1 < b := by + simp only [one_lt_iff_ne_one, Ne, mul_eq_one, not_and_or] + +end PartialOrder + +end CommMonoid + +@[deprecated (since := "2024-07-24")] alias mul_eq_one_iff := mul_eq_one +@[deprecated (since := "2024-07-24")] alias add_eq_zero_iff := add_eq_zero namespace NeZero -theorem pos {M} (a : M) [CanonicallyOrderedAddCommMonoid M] [NeZero a] : 0 < a := +theorem pos {M} [AddZeroClass M] [PartialOrder M] [CanonicallyOrderedAdd M] + (a : M) [NeZero a] : 0 < a := (zero_le a).lt_of_ne <| NeZero.out.symm -theorem of_gt {M} [CanonicallyOrderedAddCommMonoid M] {x y : M} (h : x < y) : NeZero y := +theorem of_gt {M} [AddZeroClass M] [Preorder M] [CanonicallyOrderedAdd M] + {x y : M} (h : x < y) : NeZero y := of_pos <| pos_of_gt h -- 1 < p is still an often-used `Fact`, due to `Nat.Prime` implying it, and it implying `Nontrivial` -- on `ZMod`'s ring structure. We cannot just set this to be any `x < y`, else that becomes a -- metavariable and it will hugely slow down typeclass inference. -instance (priority := 10) of_gt' {M : Type*} [CanonicallyOrderedAddCommMonoid M] [One M] {y : M} - -- Porting note: Fact.out has different type signature from mathlib3 - [Fact (1 < y)] : NeZero y := of_gt <| @Fact.out (1 < y) _ +instance (priority := 10) of_gt' {M : Type*} [AddZeroClass M] [Preorder M] [CanonicallyOrderedAdd M] + [One M] {y : M} + -- Porting note: Fact.out has different type signature from mathlib3 + [Fact (1 < y)] : NeZero y := of_gt <| @Fact.out (1 < y) _ end NeZero +set_option linter.deprecated false in /-- A canonically linear-ordered additive monoid is a canonically ordered additive monoid whose ordering is a linear order. -/ -class CanonicallyLinearOrderedAddCommMonoid (α : Type*) +@[deprecated "Use `[LinearOrderedAddCommMonoid α] [CanonicallyOrderedAdd α]` instead." + (since := "2025-01-13")] +structure CanonicallyLinearOrderedAddCommMonoid (α : Type*) extends CanonicallyOrderedAddCommMonoid α, LinearOrderedAddCommMonoid α +set_option linter.deprecated false in +set_option linter.existingAttributeWarning false in /-- A canonically linear-ordered monoid is a canonically ordered monoid whose ordering is a linear order. -/ -@[to_additive] -class CanonicallyLinearOrderedCommMonoid (α : Type*) +@[to_additive, + deprecated "Use `[LinearOrderedCommMonoid α] [CanonicallyOrderedMul α]` instead." + (since := "2025-01-13")] +structure CanonicallyLinearOrderedCommMonoid (α : Type*) extends CanonicallyOrderedCommMonoid α, LinearOrderedCommMonoid α -section CanonicallyLinearOrderedCommMonoid +attribute [nolint docBlame] CanonicallyLinearOrderedAddCommMonoid.toLinearOrderedAddCommMonoid +attribute [nolint docBlame] CanonicallyLinearOrderedCommMonoid.toLinearOrderedCommMonoid -variable [CanonicallyLinearOrderedCommMonoid α] +section CanonicallyLinearOrderedCommMonoid --- see Note [lower instance priority] -@[to_additive] -instance (priority := 100) CanonicallyLinearOrderedCommMonoid.semilatticeSup : SemilatticeSup α := - { LinearOrder.toLattice with } +variable [LinearOrderedCommMonoid α] [CanonicallyOrderedMul α] @[to_additive] theorem min_mul_distrib (a b c : α) : min a (b * c) = min a (min a b * min a c) := by diff --git a/Mathlib/Algebra/Order/Monoid/Prod.lean b/Mathlib/Algebra/Order/Monoid/Prod.lean index 0f5fe6e55021c..a245abb7cdf2b 100644 --- a/Mathlib/Algebra/Order/Monoid/Prod.lean +++ b/Mathlib/Algebra/Order/Monoid/Prod.lean @@ -36,10 +36,10 @@ instance [LE α] [LE β] [Mul α] [Mul β] [ExistsMulOfLE α] [ExistsMulOfLE β] ⟨(c, d), Prod.ext hc hd⟩⟩ @[to_additive] -instance [CanonicallyOrderedCommMonoid α] [CanonicallyOrderedCommMonoid β] : - CanonicallyOrderedCommMonoid (α × β) := - { (inferInstance : OrderedCommMonoid _), (inferInstance : OrderBot _), - (inferInstance : ExistsMulOfLE _) with +instance [Mul α] [LE α] [CanonicallyOrderedMul α] + [Mul β] [LE β] [CanonicallyOrderedMul β] : + CanonicallyOrderedMul (α × β) := + { (inferInstance : ExistsMulOfLE _) with le_self_mul := fun _ _ ↦ le_def.mpr ⟨le_self_mul, le_self_mul⟩ } namespace Lex diff --git a/Mathlib/Algebra/Order/Monoid/TypeTags.lean b/Mathlib/Algebra/Order/Monoid/TypeTags.lean index 31b5a417097b5..744e0457a4c4e 100644 --- a/Mathlib/Algebra/Order/Monoid/TypeTags.lean +++ b/Mathlib/Algebra/Order/Monoid/TypeTags.lean @@ -38,21 +38,12 @@ instance Additive.linearOrderedAddCommMonoid [LinearOrderedCommMonoid α] : LinearOrderedAddCommMonoid (Additive α) := { Additive.linearOrder, Additive.orderedAddCommMonoid with } -instance Multiplicative.canonicallyOrderedCommMonoid [CanonicallyOrderedAddCommMonoid α] : - CanonicallyOrderedCommMonoid (Multiplicative α) := - { Multiplicative.orderedCommMonoid, Multiplicative.orderBot, - Multiplicative.existsMulOfLe with le_self_mul := @le_self_add α _ } - -instance Additive.canonicallyOrderedAddCommMonoid [CanonicallyOrderedCommMonoid α] : - CanonicallyOrderedAddCommMonoid (Additive α) := - { Additive.orderedAddCommMonoid, Additive.orderBot, Additive.existsAddOfLe with - le_self_add := @le_self_mul α _ } - -instance Multiplicative.canonicallyLinearOrderedCommMonoid - [CanonicallyLinearOrderedAddCommMonoid α] : - CanonicallyLinearOrderedCommMonoid (Multiplicative α) := - { Multiplicative.canonicallyOrderedCommMonoid, Multiplicative.linearOrder with } - -instance [CanonicallyLinearOrderedCommMonoid α] : - CanonicallyLinearOrderedAddCommMonoid (Additive α) := - { Additive.canonicallyOrderedAddCommMonoid, Additive.linearOrder with } +instance Multiplicative.canonicallyOrderedMul + [AddMonoid α] [PartialOrder α] [CanonicallyOrderedAdd α] : + CanonicallyOrderedMul (Multiplicative α) where + le_self_mul _ _ := le_self_add (α := α) + +instance Additive.canonicallyOrderedAdd + [Monoid α] [PartialOrder α] [CanonicallyOrderedMul α] : + CanonicallyOrderedAdd (Additive α) where + le_self_add _ _ := le_self_mul (α := α) diff --git a/Mathlib/Algebra/Order/Monoid/WithTop.lean b/Mathlib/Algebra/Order/Monoid/WithTop.lean index b13f9b50c072b..951f6d11a0a4e 100644 --- a/Mathlib/Algebra/Order/Monoid/WithTop.lean +++ b/Mathlib/Algebra/Order/Monoid/WithTop.lean @@ -20,9 +20,9 @@ namespace WithTop instance orderedAddCommMonoid [OrderedAddCommMonoid α] : OrderedAddCommMonoid (WithTop α) where add_le_add_left _ _ := add_le_add_left -instance canonicallyOrderedAddCommMonoid [CanonicallyOrderedAddCommMonoid α] : - CanonicallyOrderedAddCommMonoid (WithTop α) := - { WithTop.orderBot, WithTop.orderedAddCommMonoid, WithTop.existsAddOfLE with +instance canonicallyOrderedAdd [Add α] [Preorder α] [CanonicallyOrderedAdd α] : + CanonicallyOrderedAdd (WithTop α) := + { WithTop.existsAddOfLE with le_self_add := fun a b => match a, b with | ⊤, ⊤ => le_rfl @@ -30,9 +30,9 @@ instance canonicallyOrderedAddCommMonoid [CanonicallyOrderedAddCommMonoid α] : | (a : α), (b : α) => WithTop.coe_le_coe.2 le_self_add | ⊤, (b : α) => le_rfl } -instance [CanonicallyLinearOrderedAddCommMonoid α] : - CanonicallyLinearOrderedAddCommMonoid (WithTop α) := - { WithTop.canonicallyOrderedAddCommMonoid, WithTop.linearOrder with } +instance [LinearOrderedAddCommMonoid α] : + LinearOrderedAddCommMonoid (WithTop α) := + { WithTop.orderedAddCommMonoid, WithTop.linearOrder with } end WithTop diff --git a/Mathlib/Algebra/Order/Nonneg/Field.lean b/Mathlib/Algebra/Order/Nonneg/Field.lean index d69aaf2a8dc28..49c06d2e70cdd 100644 --- a/Mathlib/Algebra/Order/Nonneg/Field.lean +++ b/Mathlib/Algebra/Order/Nonneg/Field.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ -import Mathlib.Algebra.Order.Field.Canonical.Defs +import Mathlib.Algebra.Order.Field.Canonical import Mathlib.Algebra.Order.Field.InjSurj import Mathlib.Algebra.Order.Nonneg.Ring import Mathlib.Data.Nat.Cast.Order.Ring @@ -101,12 +101,8 @@ instance linearOrderedSemifield : LinearOrderedSemifield { x : α // 0 ≤ x } : end LinearOrderedSemifield -instance canonicallyLinearOrderedSemifield [LinearOrderedField α] : - CanonicallyLinearOrderedSemifield { x : α // 0 ≤ x } := - { Nonneg.linearOrderedSemifield, Nonneg.canonicallyOrderedCommSemiring with } - instance linearOrderedCommGroupWithZero [LinearOrderedField α] : LinearOrderedCommGroupWithZero { x : α // 0 ≤ x } := - inferInstance + LinearOrderedSemifield.toLinearOrderedCommGroupWithZero end Nonneg diff --git a/Mathlib/Algebra/Order/Nonneg/Ring.lean b/Mathlib/Algebra/Order/Nonneg/Ring.lean index 87af067c65378..6ba3617f528dd 100644 --- a/Mathlib/Algebra/Order/Nonneg/Ring.lean +++ b/Mathlib/Algebra/Order/Nonneg/Ring.lean @@ -6,7 +6,6 @@ Authors: Floris van Doorn import Mathlib.Algebra.Order.GroupWithZero.Canonical import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg import Mathlib.Algebra.Order.Monoid.Unbundled.Pow -import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.Ring.InjSurj import Mathlib.Order.CompleteLatticeIntervals @@ -110,24 +109,18 @@ instance linearOrderedCommMonoidWithZero [LinearOrderedCommSemiring α] : { Nonneg.linearOrderedSemiring, Nonneg.orderedCommSemiring with mul_le_mul_left := fun _ _ h c ↦ mul_le_mul_of_nonneg_left h c.prop } -instance canonicallyOrderedAddCommMonoid [OrderedRing α] : - CanonicallyOrderedAddCommMonoid { x : α // 0 ≤ x } := - { Nonneg.orderedAddCommMonoid, Nonneg.orderBot with - le_self_add := fun _ b => le_add_of_nonneg_right b.2 +instance canonicallyOrderedAdd [OrderedRing α] : + CanonicallyOrderedAdd { x : α // 0 ≤ x } := + { le_self_add := fun _ b => le_add_of_nonneg_right b.2 exists_add_of_le := fun {a b} h => ⟨⟨b - a, sub_nonneg_of_le h⟩, Subtype.ext (add_sub_cancel _ _).symm⟩ } -instance canonicallyOrderedCommSemiring [OrderedCommRing α] [NoZeroDivisors α] : - CanonicallyOrderedCommSemiring { x : α // 0 ≤ x } := - { Nonneg.canonicallyOrderedAddCommMonoid, Nonneg.orderedCommSemiring with - eq_zero_or_eq_zero_of_mul_eq_zero := by +instance noZeroDivisors [OrderedSemiring α] [NoZeroDivisors α] : + NoZeroDivisors { x : α // 0 ≤ x } := + { eq_zero_or_eq_zero_of_mul_eq_zero := by rintro ⟨a, ha⟩ ⟨b, hb⟩ simp only [mk_mul_mk, mk_eq_zero, mul_eq_zero, imp_self]} -instance canonicallyLinearOrderedAddCommMonoid [LinearOrderedRing α] : - CanonicallyLinearOrderedAddCommMonoid { x : α // 0 ≤ x } := - { Subtype.instLinearOrder _, Nonneg.canonicallyOrderedAddCommMonoid with } - instance orderedSub [LinearOrderedRing α] : OrderedSub { x : α // 0 ≤ x } := ⟨by rintro ⟨a, ha⟩ ⟨b, hb⟩ ⟨c, hc⟩ diff --git a/Mathlib/Algebra/Order/Pi.lean b/Mathlib/Algebra/Order/Pi.lean index da715df7e1d66..5ae000421e747 100644 --- a/Mathlib/Algebra/Order/Pi.lean +++ b/Mathlib/Algebra/Order/Pi.lean @@ -42,10 +42,9 @@ instance existsMulOfLe {ι : Type*} {α : ι → Type*} [∀ i, LE (α i)] [∀ @[to_additive "The product of a family of canonically ordered additive monoids is a canonically ordered additive monoid."] -instance {ι : Type*} {Z : ι → Type*} [∀ i, CanonicallyOrderedCommMonoid (Z i)] : - CanonicallyOrderedCommMonoid (∀ i, Z i) where - __ := Pi.instOrderBot - __ := Pi.orderedCommMonoid +instance {ι : Type*} {Z : ι → Type*} [∀ i, Monoid (Z i)] [∀ i, PartialOrder (Z i)] + [∀ i, CanonicallyOrderedMul (Z i)] : + CanonicallyOrderedMul (∀ i, Z i) where __ := Pi.existsMulOfLe le_self_mul _ _ := fun _ => le_self_mul diff --git a/Mathlib/Algebra/Order/Ring/Canonical.lean b/Mathlib/Algebra/Order/Ring/Canonical.lean index 3c7a907838251..f0c061535dd82 100644 --- a/Mathlib/Algebra/Order/Ring/Canonical.lean +++ b/Mathlib/Algebra/Order/Ring/Canonical.lean @@ -10,16 +10,6 @@ import Mathlib.Algebra.Ring.Parity /-! # Canonically ordered rings and semirings. - -* `CanonicallyOrderedCommSemiring` - - `CanonicallyOrderedAddCommMonoid` & multiplication & `*` respects `≤` & no zero divisors - - `CommSemiring` & `a ≤ b ↔ ∃ c, b = a + c` & no zero divisors - -## TODO - -We're still missing some typeclasses, like -* `CanonicallyOrderedSemiring` -They have yet to come up in practice. -/ @@ -29,52 +19,66 @@ universe u variable {α : Type u} +set_option linter.deprecated false in /-- A canonically ordered commutative semiring is an ordered, commutative semiring in which `a ≤ b` iff there exists `c` with `b = a + c`. This is satisfied by the natural numbers, for example, but not the integers or other ordered groups. -/ -class CanonicallyOrderedCommSemiring (α : Type*) extends CanonicallyOrderedAddCommMonoid α, +@[deprecated "Use `[OrderedCommSemiring α] [CanonicallyOrderedAdd α] [NoZeroDivisors α]` instead." + (since := "2025-01-13")] +structure CanonicallyOrderedCommSemiring (α : Type*) extends CanonicallyOrderedAddCommMonoid α, CommSemiring α where /-- No zero divisors. -/ protected eq_zero_or_eq_zero_of_mul_eq_zero : ∀ {a b : α}, a * b = 0 → a = 0 ∨ b = 0 -section CanonicallyOrderedCommSemiring -variable [CanonicallyOrderedCommSemiring α] {a b c d : α} +attribute [nolint docBlame] CanonicallyOrderedCommSemiring.toCommSemiring --- this holds more generally in a `CanonicallyOrderedAddCommMonoid` if we refactor `Odd` to use --- either `2 • t` or `t + t` instead of `2 * t`. -lemma Odd.pos [Nontrivial α] : Odd a → 0 < a := by rintro ⟨k, rfl⟩; simp [pos_iff_ne_zero] +-- see Note [lower instance priority] +instance (priority := 10) CanonicallyOrderedAdd.toZeroLEOneClass + [AddZeroClass α] [One α] [LE α] [CanonicallyOrderedAdd α] : ZeroLEOneClass α where + zero_le_one := zero_le _ -namespace CanonicallyOrderedCommSemiring +-- this holds more generally if we refactor `Odd` to use +-- either `2 • t` or `t + t` instead of `2 * t`. +lemma Odd.pos [Semiring α] [PartialOrder α] [CanonicallyOrderedAdd α] [Nontrivial α] {a : α} : + Odd a → 0 < a := by + rintro ⟨k, rfl⟩; simp --- see Note [lower instance priority] -instance (priority := 100) toNoZeroDivisors : NoZeroDivisors α := - ⟨CanonicallyOrderedCommSemiring.eq_zero_or_eq_zero_of_mul_eq_zero⟩ +namespace CanonicallyOrderedAdd -- see Note [lower instance priority] -instance (priority := 100) toMulLeftMono : MulLeftMono α := by +instance (priority := 100) toMulLeftMono [NonUnitalNonAssocSemiring α] + [LE α] [CanonicallyOrderedAdd α] : MulLeftMono α := by refine ⟨fun a b c h => ?_⟩; dsimp rcases exists_add_of_le h with ⟨c, rfl⟩ rw [mul_add] apply self_le_add_right --- see Note [lower instance priority] -instance (priority := 100) toOrderedCommMonoid : OrderedCommMonoid α where - mul_le_mul_left := fun _ _ => mul_le_mul_left' +variable [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] --- see Note [lower instance priority] -instance (priority := 100) toOrderedCommSemiring : OrderedCommSemiring α := - { ‹CanonicallyOrderedCommSemiring α› with - zero_le_one := zero_le _, - mul_le_mul_of_nonneg_left := fun _ _ _ h _ => mul_le_mul_left' h _, - mul_le_mul_of_nonneg_right := fun _ _ _ h _ => mul_le_mul_right' h _ } +-- See note [reducible non-instances] +/-- Construct an `OrderedCommMonoid` from a canonically ordered `CommSemiring`. -/ +abbrev toOrderedCommMonoid : OrderedCommMonoid α where + mul_le_mul_left _ _ := mul_le_mul_left' + +-- See note [reducible non-instances] +/-- Construct an `OrderedCommSemiring` from a canonically ordered `CommSemiring`. -/ +abbrev toOrderedCommSemiring : OrderedCommSemiring α where + mul_comm := mul_comm + zero_le_one := zero_le _ + add_le_add_left _ _ := add_le_add_left + mul_le_mul_of_nonneg_left := fun _ _ _ h _ => mul_le_mul_left' h _ + mul_le_mul_of_nonneg_right := fun _ _ _ h _ => mul_le_mul_right' h _ @[simp] -protected theorem mul_pos : 0 < a * b ↔ 0 < a ∧ 0 < b := by +protected theorem mul_pos [NoZeroDivisors α] {a b : α} : + 0 < a * b ↔ 0 < a ∧ 0 < b := by simp only [pos_iff_ne_zero, ne_eq, mul_eq_zero, not_or] -lemma pow_pos (ha : 0 < a) (n : ℕ) : 0 < a ^ n := pos_iff_ne_zero.2 <| pow_ne_zero _ ha.ne' +lemma pow_pos [NoZeroDivisors α] {a : α} (ha : 0 < a) (n : ℕ) : 0 < a ^ n := + pos_iff_ne_zero.2 <| pow_ne_zero _ ha.ne' -protected lemma mul_lt_mul_of_lt_of_lt [PosMulStrictMono α] (hab : a < b) (hcd : c < d) : +protected lemma mul_lt_mul_of_lt_of_lt + [PosMulStrictMono α] {a b c d : α} (hab : a < b) (hcd : c < d) : a * c < b * d := by -- TODO: This should be an instance but it currently times out have := posMulStrictMono_iff_mulPosStrictMono.1 ‹_› @@ -83,26 +87,30 @@ protected lemma mul_lt_mul_of_lt_of_lt [PosMulStrictMono α] (hab : a < b) (hcd exact mul_pos ((zero_le _).trans_lt hab) hcd · exact mul_lt_mul_of_pos' hab hcd hc ((zero_le _).trans_lt hab) -end CanonicallyOrderedCommSemiring -end CanonicallyOrderedCommSemiring +end CanonicallyOrderedAdd section Sub -variable [CanonicallyOrderedCommSemiring α] {a b c : α} -variable [Sub α] [OrderedSub α] -variable [IsTotal α (· ≤ ·)] +section NonUnitalNonAssocSemiring + +variable [NonUnitalNonAssocSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] [IsTotal α (· ≤ ·)] namespace AddLECancellable -protected theorem mul_tsub (h : AddLECancellable (a * c)) : a * (b - c) = a * b - a * c := by - cases' total_of (· ≤ ·) b c with hbc hcb +protected theorem mul_tsub {a b c : α} + (h : AddLECancellable (a * c)) : a * (b - c) = a * b - a * c := by + obtain (hbc | hcb) := total_of (· ≤ ·) b c · rw [tsub_eq_zero_iff_le.2 hbc, mul_zero, tsub_eq_zero_iff_le.2 (mul_le_mul_left' hbc a)] · apply h.eq_tsub_of_add_eq rw [← mul_add, tsub_add_cancel_of_le hcb] -protected theorem tsub_mul (h : AddLECancellable (b * c)) : (a - b) * c = a * c - b * c := by - simp only [mul_comm _ c] at * - exact h.mul_tsub +protected theorem tsub_mul [MulRightMono α] {a b c : α} + (h : AddLECancellable (b * c)) : (a - b) * c = a * c - b * c := by + obtain (hab | hba) := total_of (· ≤ ·) a b + · rw [tsub_eq_zero_iff_le.2 hab, zero_mul, tsub_eq_zero_iff_le.2 (mul_le_mul_right' hab c)] + · apply h.eq_tsub_of_add_eq + rw [← add_mul, tsub_add_cancel_of_le hba] end AddLECancellable @@ -111,14 +119,32 @@ variable [AddLeftReflectLE α] theorem mul_tsub (a b c : α) : a * (b - c) = a * b - a * c := Contravariant.AddLECancellable.mul_tsub -theorem tsub_mul (a b c : α) : (a - b) * c = a * c - b * c := +theorem tsub_mul [MulRightMono α] (a b c : α) : + (a - b) * c = a * c - b * c := Contravariant.AddLECancellable.tsub_mul -lemma mul_tsub_one (a b : α) : a * (b - 1) = a * b - a := by rw [mul_tsub, mul_one] -lemma tsub_one_mul (a b : α) : (a - 1) * b = a * b - b := by rw [tsub_mul, one_mul] +end NonUnitalNonAssocSemiring + +section NonAssocSemiring + +variable [NonAssocSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] [IsTotal α (· ≤ ·)] + +lemma mul_tsub_one [AddLeftReflectLE α] (a b : α) : + a * (b - 1) = a * b - a := by rw [mul_tsub, mul_one] +lemma tsub_one_mul [MulRightMono α] [AddLeftReflectLE α] (a b : α) : + (a - 1) * b = a * b - b := by rw [tsub_mul, one_mul] + +end NonAssocSemiring + +section CommSemiring + +variable [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] [IsTotal α (· ≤ ·)] [AddLeftReflectLE α] /-- The `tsub` version of `mul_self_sub_mul_self`. Notably, this holds for `Nat` and `NNReal`. -/ -theorem mul_self_tsub_mul_self (a b : α) : a * a - b * b = (a + b) * (a - b) := by +theorem mul_self_tsub_mul_self (a b : α) : + a * a - b * b = (a + b) * (a - b) := by rw [mul_tsub, add_mul, add_mul, tsub_add_eq_tsub_tsub, mul_comm b a, add_tsub_cancel_right] /-- The `tsub` version of `sq_sub_sq`. Notably, this holds for `Nat` and `NNReal`. -/ @@ -128,4 +154,6 @@ theorem sq_tsub_sq (a b : α) : a ^ 2 - b ^ 2 = (a + b) * (a - b) := by theorem mul_self_tsub_one (a : α) : a * a - 1 = (a + 1) * (a - 1) := by rw [← mul_self_tsub_mul_self, mul_one] +end CommSemiring + end Sub diff --git a/Mathlib/Algebra/Order/Ring/Defs.lean b/Mathlib/Algebra/Order/Ring/Defs.lean index a8f2ee51df52a..6b1c7f820095d 100644 --- a/Mathlib/Algebra/Order/Ring/Defs.lean +++ b/Mathlib/Algebra/Order/Ring/Defs.lean @@ -49,8 +49,6 @@ For short, respects `<`. * `LinearOrderedCommRing`: Nontrivial commutative ring with a linear order such that `+` respects `≤` and `*` respects `<`. -* `CanonicallyOrderedCommSemiring`: Commutative semiring with a partial order such that `+` - respects `≤`, `*` respects `<`, and `a ≤ b ↔ ∃ c, b = a + c`. ## Hierarchy diff --git a/Mathlib/Algebra/Order/Ring/Finset.lean b/Mathlib/Algebra/Order/Ring/Finset.lean index 0b92b63875cd3..1d6e8e3b4eb80 100644 --- a/Mathlib/Algebra/Order/Ring/Finset.lean +++ b/Mathlib/Algebra/Order/Ring/Finset.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Eric Wieser, Yaël Dillies, Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser, Yaël Dillies, Andrew Yang -/ -import Mathlib.Algebra.Order.Field.Canonical.Defs import Mathlib.Data.Finset.Lattice.Fold import Mathlib.Data.Nat.Cast.Order.Ring @@ -29,11 +28,11 @@ set_option linter.docPrime false in lemma cast_finsetInf' (f : ι → ℕ) (hs) : (↑(s.inf' hs f) : R) = s.inf' hs fun i ↦ (f i : R) := comp_inf'_eq_inf'_comp _ _ cast_min -end LinearOrderedSemiring - @[simp, norm_cast] -lemma cast_finsetSup [CanonicallyLinearOrderedSemifield R] (s : Finset ι) (f : ι → ℕ) : +lemma cast_finsetSup [CanonicallyOrderedAdd R] (s : Finset ι) (f : ι → ℕ) : (↑(s.sup f) : R) = s.sup fun i ↦ (f i : R) := comp_sup_eq_sup_comp _ cast_max (by simp) +end LinearOrderedSemiring + end Nat diff --git a/Mathlib/Algebra/Order/Ring/Nat.lean b/Mathlib/Algebra/Order/Ring/Nat.lean index 3b3be2c922c0a..704a916d34b14 100644 --- a/Mathlib/Algebra/Order/Ring/Nat.lean +++ b/Mathlib/Algebra/Order/Ring/Nat.lean @@ -5,8 +5,8 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Algebra.Order.Group.Nat import Mathlib.Algebra.Order.GroupWithZero.Canonical -import Mathlib.Algebra.Order.Ring.Canonical -import Mathlib.Algebra.Ring.Nat +import Mathlib.Algebra.Order.Ring.Defs +import Mathlib.Algebra.Ring.Parity import Mathlib.Data.Set.Basic /-! @@ -36,12 +36,6 @@ instance instLinearOrderedCommMonoidWithZero : LinearOrderedCommMonoidWithZero __ : CommMonoidWithZero ℕ := inferInstance mul_le_mul_left _ _ h c := Nat.mul_le_mul_left c h -instance instCanonicallyOrderedCommSemiring : CanonicallyOrderedCommSemiring ℕ where - __ := instLinearOrderedCommSemiring - exists_add_of_le h := (Nat.le.dest h).imp fun _ => Eq.symm - le_self_add := Nat.le_add_right - eq_zero_or_eq_zero_of_mul_eq_zero := Nat.mul_eq_zero.mp - /-! ### Extra instances to short-circuit type class resolution diff --git a/Mathlib/Algebra/Order/Ring/WithTop.lean b/Mathlib/Algebra/Order/Ring/WithTop.lean index 367fc8972bce5..5ba1619244795 100644 --- a/Mathlib/Algebra/Order/Ring/WithTop.lean +++ b/Mathlib/Algebra/Order/Ring/WithTop.lean @@ -9,8 +9,8 @@ import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Algebra.Order.Monoid.WithTop /-! # Structures involving `*` and `0` on `WithTop` and `WithBot` -The main results of this section are `WithTop.canonicallyOrderedCommSemiring` and -`WithBot.orderedCommSemiring`. +The main results of this section are `WithTop.instOrderedCommSemiring` and +`WithBot.instOrderedCommSemiring`. -/ variable {α : Type*} @@ -164,38 +164,63 @@ instance instCommMonoidWithZero [CommMonoidWithZero α] [NoZeroDivisors α] [Non __ := instMonoidWithZero mul_comm a b := by simp_rw [mul_def]; exact if_congr or_comm rfl (Option.map₂_comm mul_comm) -variable [CanonicallyOrderedCommSemiring α] - -private theorem distrib' (a b c : WithTop α) : (a + b) * c = a * c + b * c := by - induction' c with c - · by_cases ha : a = 0 <;> simp [ha] - · by_cases hc : c = 0 - · simp [hc] - simp only [mul_coe_eq_bind hc] - cases a <;> cases b - repeat' first | rfl |exact congr_arg some (add_mul _ _ _) - -/-- This instance requires `CanonicallyOrderedCommSemiring` as it is the smallest class -that derives from both `NonAssocNonUnitalSemiring` and `CanonicallyOrderedAddCommMonoid`, both -of which are required for distributivity. -/ -instance commSemiring [Nontrivial α] : CommSemiring (WithTop α) := - { addCommMonoidWithOne, instCommMonoidWithZero with - right_distrib := distrib' - left_distrib := fun a b c => by - rw [mul_comm, distrib', mul_comm b, mul_comm c] } - -instance [Nontrivial α] : CanonicallyOrderedCommSemiring (WithTop α) := - { WithTop.commSemiring, WithTop.canonicallyOrderedAddCommMonoid with - eq_zero_or_eq_zero_of_mul_eq_zero := eq_zero_or_eq_zero_of_mul_eq_zero} +instance instNonUnitalNonAssocSemiring [NonUnitalNonAssocSemiring α] [PartialOrder α] + [CanonicallyOrderedAdd α] : NonUnitalNonAssocSemiring (WithTop α) where + toAddCommMonoid := WithTop.addCommMonoid + __ := WithTop.instMulZeroClass + right_distrib a b c := by + induction' c with c + · by_cases ha : a = 0 <;> simp [ha] + · by_cases hc : c = 0; · simp [hc] + simp only [mul_coe_eq_bind hc] + cases a <;> cases b <;> try rfl + exact congr_arg some (add_mul _ _ _) + left_distrib c a b := by + induction' c with c + · by_cases ha : a = 0 <;> simp [ha] + · by_cases hc : c = 0; · simp [hc] + simp only [coe_mul_eq_bind hc] + cases a <;> cases b <;> try rfl + exact congr_arg some (mul_add _ _ _) + +instance instNonAssocSemiring [NonAssocSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [Nontrivial α] : NonAssocSemiring (WithTop α) where + toNonUnitalNonAssocSemiring := instNonUnitalNonAssocSemiring + __ := WithTop.instMulZeroOneClass + __ := WithTop.addCommMonoidWithOne + +instance instNonUnitalSemiring [NonUnitalSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [NoZeroDivisors α] : NonUnitalSemiring (WithTop α) where + toNonUnitalNonAssocSemiring := WithTop.instNonUnitalNonAssocSemiring + __ := WithTop.instSemigroupWithZero + +instance instSemiring [Semiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [NoZeroDivisors α] [Nontrivial α] : Semiring (WithTop α) where + toNonUnitalSemiring := WithTop.instNonUnitalSemiring + __ := WithTop.instMonoidWithZero + __ := WithTop.addCommMonoidWithOne + +instance instCommSemiring [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [NoZeroDivisors α] [Nontrivial α] : CommSemiring (WithTop α) where + toSemiring := WithTop.instSemiring + __ := WithTop.instCommMonoidWithZero + +instance instOrderedCommSemiring [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [NoZeroDivisors α] [Nontrivial α] : OrderedCommSemiring (WithTop α) := + CanonicallyOrderedAdd.toOrderedCommSemiring /-- A version of `WithTop.map` for `RingHom`s. -/ @[simps (config := .asFn)] -protected def _root_.RingHom.withTopMap {R S : Type*} [CanonicallyOrderedCommSemiring R] - [DecidableEq R] [Nontrivial R] [CanonicallyOrderedCommSemiring S] [DecidableEq S] [Nontrivial S] +protected def _root_.RingHom.withTopMap {R S : Type*} + [NonAssocSemiring R] [PartialOrder R] [CanonicallyOrderedAdd R] + [DecidableEq R] [Nontrivial R] + [NonAssocSemiring S] [PartialOrder S] [CanonicallyOrderedAdd S] + [DecidableEq S] [Nontrivial S] (f : R →+* S) (hf : Function.Injective f) : WithTop R →+* WithTop S := {MonoidWithZeroHom.withTopMap f.toMonoidWithZeroHom hf, f.toAddMonoidHom.withTopMap with} -variable [PosMulStrictMono α] {a a₁ a₂ b₁ b₂ : WithTop α} +variable [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] [PosMulStrictMono α] + {a a₁ a₂ b₁ b₂ : WithTop α} @[gcongr] protected lemma mul_lt_mul (ha : a₁ < a₂) (hb : b₁ < b₂) : a₁ * b₁ < a₂ * b₂ := by @@ -306,12 +331,14 @@ instance instMonoidWithZero : MonoidWithZero (WithBot α) := WithTop.instMonoidW end MonoidWithZero -instance commMonoidWithZero [CommMonoidWithZero α] [NoZeroDivisors α] [Nontrivial α] : - CommMonoidWithZero (WithBot α) := WithTop.instCommMonoidWithZero +instance instCommMonoidWithZero [CommMonoidWithZero α] [NoZeroDivisors α] [Nontrivial α] : + CommMonoidWithZero (WithBot α) := + WithTop.instCommMonoidWithZero -instance commSemiring [CanonicallyOrderedCommSemiring α] [Nontrivial α] : +instance instCommSemiring [CommSemiring α] [PartialOrder α] [CanonicallyOrderedAdd α] + [NoZeroDivisors α] [Nontrivial α] : CommSemiring (WithBot α) := - WithTop.commSemiring + WithTop.instCommSemiring instance [MulZeroClass α] [Preorder α] [PosMulMono α] : PosMulMono (WithBot α) := ⟨by @@ -437,10 +464,13 @@ instance [MulZeroClass α] [Preorder α] [MulPosReflectLE α] : MulPosReflectLE norm_cast at x0 exact le_of_mul_le_mul_right h x0 ⟩ -instance orderedCommSemiring [CanonicallyOrderedCommSemiring α] [Nontrivial α] : - OrderedCommSemiring (WithBot α) := - { WithBot.zeroLEOneClass, WithBot.orderedAddCommMonoid, WithBot.commSemiring with - mul_le_mul_of_nonneg_left := fun _ _ _ => mul_le_mul_of_nonneg_left - mul_le_mul_of_nonneg_right := fun _ _ _ => mul_le_mul_of_nonneg_right } +instance instOrderedCommSemiring [OrderedCommSemiring α] [CanonicallyOrderedAdd α] + [NoZeroDivisors α] [Nontrivial α] : + OrderedCommSemiring (WithBot α) where + __ := WithBot.instCommSemiring + __ := WithBot.zeroLEOneClass + __ := WithBot.orderedAddCommMonoid + mul_le_mul_of_nonneg_left := fun _ _ _ => mul_le_mul_of_nonneg_left + mul_le_mul_of_nonneg_right := fun _ _ _ => mul_le_mul_of_nonneg_right end WithBot diff --git a/Mathlib/Algebra/Order/Sub/Basic.lean b/Mathlib/Algebra/Order/Sub/Basic.lean index 26fd792d3b9d5..d7b8771bbfec3 100644 --- a/Mathlib/Algebra/Order/Sub/Basic.lean +++ b/Mathlib/Algebra/Order/Sub/Basic.lean @@ -16,7 +16,8 @@ variable {α : Type*} section CanonicallyOrderedAddCommMonoid -variable [CanonicallyOrderedAddCommMonoid α] [Sub α] [OrderedSub α] {a b c : α} +variable [AddCommMonoid α] [PartialOrder α] [CanonicallyOrderedAdd α] + [Sub α] [OrderedSub α] {a b c : α} theorem add_tsub_cancel_iff_le : a + (b - a) = b ↔ a ≤ b := ⟨fun h => le_iff_exists_add.mpr ⟨b - a, h.symm⟩, add_tsub_cancel_of_le⟩ @@ -104,7 +105,8 @@ end CanonicallyOrderedAddCommMonoid section CanonicallyLinearOrderedAddCommMonoid -variable [CanonicallyLinearOrderedAddCommMonoid α] [Sub α] [OrderedSub α] {a b c : α} +variable [LinearOrderedAddCommMonoid α] [CanonicallyOrderedAdd α] [Sub α] [OrderedSub α] + {a b c : α} @[simp] theorem tsub_pos_iff_lt : 0 < a - b ↔ b < a := by rw [tsub_pos_iff_not_le, not_le] @@ -116,9 +118,11 @@ theorem tsub_eq_tsub_min (a b : α) : a - b = a - min a b := by namespace AddLECancellable +omit [CanonicallyOrderedAdd α] in protected theorem lt_tsub_iff_right (hc : AddLECancellable c) : a < b - c ↔ a + c < b := ⟨lt_imp_lt_of_le_imp_le tsub_le_iff_right.mpr, hc.lt_tsub_of_add_lt_right⟩ +omit [CanonicallyOrderedAdd α] in protected theorem lt_tsub_iff_left (hc : AddLECancellable c) : a < b - c ↔ c + a < b := ⟨lt_imp_lt_of_le_imp_le tsub_le_iff_left.mpr, hc.lt_tsub_of_add_lt_left⟩ diff --git a/Mathlib/Algebra/Order/Sub/Defs.lean b/Mathlib/Algebra/Order/Sub/Defs.lean index e4c6643431795..f370e5f6843db 100644 --- a/Mathlib/Algebra/Order/Sub/Defs.lean +++ b/Mathlib/Algebra/Order/Sub/Defs.lean @@ -19,9 +19,9 @@ subtraction on a canonically ordered monoid (`ℕ`, `Multiset`, `PartENat`, `ENN ## Implementation details `OrderedSub` is a mixin type-class, so that we can use the results in this file even in cases -where we don't have a `CanonicallyOrderedAddCommMonoid` instance +where we don't have a `CanonicallyOrderedAdd` instance (even though that is our main focus). Conversely, this means we can use -`CanonicallyOrderedAddCommMonoid` without necessarily having to define a subtraction. +`CanonicallyOrderedAdd` without necessarily having to define a subtraction. The results in this file are ordered by the type-class assumption needed to prove it. This means that similar results might not be close to each other. Furthermore, we don't prove diff --git a/Mathlib/Algebra/Order/Sub/WithTop.lean b/Mathlib/Algebra/Order/Sub/WithTop.lean index 5b2d1da2ff61f..cb2367c988bac 100644 --- a/Mathlib/Algebra/Order/Sub/WithTop.lean +++ b/Mathlib/Algebra/Order/Sub/WithTop.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ import Mathlib.Algebra.Order.Sub.Defs -import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop /-! @@ -65,7 +64,7 @@ theorem map_sub [Sub β] [Bot β] {f : α → β} (h : ∀ x y, f (x - y) = f x end -variable [CanonicallyOrderedAddCommMonoid α] [Sub α] [OrderedSub α] +variable [Add α] [LE α] [OrderBot α] [Sub α] [OrderedSub α] instance : OrderedSub (WithTop α) := by constructor diff --git a/Mathlib/Algebra/PUnitInstances/Order.lean b/Mathlib/Algebra/PUnitInstances/Order.lean index f88d99c80485b..a2757ff9eff22 100644 --- a/Mathlib/Algebra/PUnitInstances/Order.lean +++ b/Mathlib/Algebra/PUnitInstances/Order.lean @@ -15,9 +15,8 @@ This file collects facts about ordered algebraic structures on the one-element t namespace PUnit -instance canonicallyOrderedAddCommMonoid : CanonicallyOrderedAddCommMonoid PUnit where +instance canonicallyOrderedAdd : CanonicallyOrderedAdd PUnit where exists_add_of_le {_ _} _ := ⟨unit, by subsingleton⟩ - add_le_add_left _ _ _ _ := trivial le_self_add _ _ := trivial instance linearOrderedCancelAddCommMonoid : LinearOrderedCancelAddCommMonoid PUnit where diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index 5ba72e13bc4f1..d770f727726f8 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Yury Kudryashov -/ -import Mathlib.Algebra.Order.Star.Basic import Mathlib.Analysis.Calculus.FormalMultilinearSeries import Mathlib.Analysis.SpecificLimits.Normed import Mathlib.Logic.Equiv.Fin diff --git a/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean b/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean index 0713f40546373..7e5faca769f98 100644 --- a/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean +++ b/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Benjamin Davidson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Benjamin Davidson, Yury Kudryashov -/ -import Mathlib.Algebra.Order.Star.Basic import Mathlib.Analysis.Calculus.LocalExtr.Rolle import Mathlib.Analysis.Calculus.Deriv.Polynomial import Mathlib.Topology.Algebra.Polynomial diff --git a/Mathlib/Analysis/SumOverResidueClass.lean b/Mathlib/Analysis/SumOverResidueClass.lean index 8eb7637dc0dbf..6e45f5649227c 100644 --- a/Mathlib/Analysis/SumOverResidueClass.lean +++ b/Mathlib/Analysis/SumOverResidueClass.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Michael Stoll. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Stoll -/ -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Data.ZMod.Basic import Mathlib.Topology.Instances.ENNReal.Lemmas diff --git a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean index cd948718c6bfb..44d431a6eed63 100644 --- a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean +++ b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean @@ -433,7 +433,7 @@ theorem rothNumberNat_zero : rothNumberNat 0 = 0 := theorem addRothNumber_Ico (a b : ℕ) : addRothNumber (Ico a b) = rothNumberNat (b - a) := by obtain h | h := le_total b a - · rw [tsub_eq_zero_of_le h, Ico_eq_empty_of_le h, rothNumberNat_zero, addRothNumber_empty] + · rw [Nat.sub_eq_zero_of_le h, Ico_eq_empty_of_le h, rothNumberNat_zero, addRothNumber_empty] convert addRothNumber_map_add_left _ a rw [range_eq_Ico, map_eq_image] convert (image_add_left_Ico 0 (b - a) _).symm diff --git a/Mathlib/Combinatorics/Enumerative/Bell.lean b/Mathlib/Combinatorics/Enumerative/Bell.lean index 118746de144fb..8bb996c3dc80e 100644 --- a/Mathlib/Combinatorics/Enumerative/Bell.lean +++ b/Mathlib/Combinatorics/Enumerative/Bell.lean @@ -106,7 +106,7 @@ theorem bell_eq (m : Multiset ℕ) : apply Nat.dvd_mul_left · rw [← Nat.pos_iff_ne_zero] apply Nat.mul_pos - · simp only [gt_iff_lt, CanonicallyOrderedCommSemiring.multiset_prod_pos, mem_map, + · simp only [gt_iff_lt, CanonicallyOrderedAdd.multiset_prod_pos, mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] exact fun _ _ ↦ Nat.factorial_pos _ · apply Finset.prod_pos diff --git a/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean b/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean index 49205ae8ec3d0..914e001dc3401 100644 --- a/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean +++ b/Mathlib/Combinatorics/SetFamily/HarrisKleitman.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Combinatorics.SetFamily.Compression.Down -import Mathlib.Order.UpperLower.Basic import Mathlib.Data.Fintype.Powerset +import Mathlib.Order.UpperLower.Basic /-! # Harris-Kleitman inequality diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean index b82ae053e2ea0..bad7217bbede8 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Yaël Dillies, Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Bhavik Mehta -/ +import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Order.Partition.Equipartition /-! diff --git a/Mathlib/Computability/Halting.lean b/Mathlib/Computability/Halting.lean index 840833a0d356f..178d1f7afe681 100644 --- a/Mathlib/Computability/Halting.lean +++ b/Mathlib/Computability/Halting.lean @@ -350,7 +350,7 @@ theorem rfindOpt {n} {f : List.Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + ((prim Nat.Primrec'.pred).comp₁ Nat.pred hf)).of_eq fun v => Part.ext fun b => by - simp only [Nat.rfindOpt, exists_prop, tsub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff, + simp only [Nat.rfindOpt, exists_prop, Nat.sub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff, Part.mem_some_iff, Option.mem_def, Part.mem_coe] refine exists_congr fun a => (and_congr (iff_of_eq ?_) Iff.rfl).trans (and_congr_right fun h => ?_) diff --git a/Mathlib/Computability/Primrec.lean b/Mathlib/Computability/Primrec.lean index ec43f49acc828..722792093ba58 100644 --- a/Mathlib/Computability/Primrec.lean +++ b/Mathlib/Computability/Primrec.lean @@ -574,7 +574,7 @@ theorem nat_le : PrimrecRel ((· ≤ ·) : ℕ → ℕ → Prop) := (nat_casesOn nat_sub (const true) (const false).to₂).of_eq fun p => by dsimp [swap] cases' e : p.1 - p.2 with n - · simp [tsub_eq_zero_iff_le.1 e] + · simp [Nat.sub_eq_zero_iff_le.1 e] · simp [not_le.2 (Nat.lt_of_sub_eq_succ e)] theorem nat_min : Primrec₂ (@min ℕ _) := @@ -1344,7 +1344,7 @@ theorem if_lt {n a b f g} (ha : @Primrec' n a) (hb : @Primrec' n b) (hf : @Primr (hg : @Primrec' n g) : @Primrec' n fun v => if a v < b v then f v else g v := (prec' (sub.comp₂ _ hb ha) hg (tail <| tail hf)).of_eq fun v => by cases e : b v - a v - · simp [not_lt.2 (tsub_eq_zero_iff_le.mp e)] + · simp [not_lt.2 (Nat.sub_eq_zero_iff_le.mp e)] · simp [Nat.lt_of_sub_eq_succ e] theorem natPair : @Primrec' 2 fun v => v.head.pair v.tail.head := diff --git a/Mathlib/Data/DFinsupp/Interval.lean b/Mathlib/Data/DFinsupp/Interval.lean index 9088f791c1236..8c41b16f96c1d 100644 --- a/Mathlib/Data/DFinsupp/Interval.lean +++ b/Mathlib/Data/DFinsupp/Interval.lean @@ -183,7 +183,8 @@ end Lattice section CanonicallyOrdered variable [DecidableEq ι] [∀ i, DecidableEq (α i)] -variable [∀ i, CanonicallyOrderedAddCommMonoid (α i)] [∀ i, LocallyFiniteOrder (α i)] +variable [∀ i, AddCommMonoid (α i)] [∀ i, PartialOrder (α i)] [∀ i, CanonicallyOrderedAdd (α i)] + [∀ i, LocallyFiniteOrder (α i)] variable (f : Π₀ i, α i) lemma card_Iic : #(Iic f) = ∏ i ∈ f.support, #(Iic (f i)) := by diff --git a/Mathlib/Data/DFinsupp/Lex.lean b/Mathlib/Data/DFinsupp/Lex.lean index 3251cba793ca2..d3455126a9691 100644 --- a/Mathlib/Data/DFinsupp/Lex.lean +++ b/Mathlib/Data/DFinsupp/Lex.lean @@ -172,7 +172,8 @@ section OrderedAddMonoid variable [LinearOrder ι] -instance Lex.orderBot [∀ i, CanonicallyOrderedAddCommMonoid (α i)] : +instance Lex.orderBot [∀ i, AddCommMonoid (α i)] [∀ i, PartialOrder (α i)] + [∀ i, CanonicallyOrderedAdd (α i)] : OrderBot (Lex (Π₀ i, α i)) where bot := 0 bot_le _ := DFinsupp.toLex_monotone bot_le diff --git a/Mathlib/Data/DFinsupp/Order.lean b/Mathlib/Data/DFinsupp/Order.lean index 169143c17fecb..9201ee22c9791 100644 --- a/Mathlib/Data/DFinsupp/Order.lean +++ b/Mathlib/Data/DFinsupp/Order.lean @@ -181,11 +181,11 @@ instance instSMulPosReflectLT [∀ i, SMulPosReflectLT α (β i)] : SMulPosRefle end Module -section CanonicallyOrderedAddCommMonoid +section PartialOrder -- Porting note: Split into 2 lines to satisfy the unusedVariables linter. variable (α) -variable [∀ i, CanonicallyOrderedAddCommMonoid (α i)] +variable [∀ i, AddCommMonoid (α i)] [∀ i, PartialOrder (α i)] [∀ i, CanonicallyOrderedAdd (α i)] instance : OrderBot (Π₀ i, α i) where bot := 0 @@ -230,7 +230,8 @@ variable {α} end @[simp] -theorem single_le_iff {f : Π₀ i, α i} {i : ι} {a : α i} : single i a ≤ f ↔ a ≤ f i := by +theorem single_le_iff {f : Π₀ i, α i} {i : ι} {a : α i} : + single i a ≤ f ↔ a ≤ f i := by classical exact (le_iff' support_single_subset).trans <| by simp end LE @@ -259,15 +260,13 @@ variable (α) instance : OrderedSub (Π₀ i, α i) := ⟨fun _ _ _ ↦ forall_congr' fun _ ↦ tsub_le_iff_right⟩ -instance : CanonicallyOrderedAddCommMonoid (Π₀ i, α i) := - { (inferInstance : OrderBot (DFinsupp α)), - (inferInstance : OrderedAddCommMonoid (DFinsupp α)) with - exists_add_of_le := by - intro f g h - exists g - f - ext i - exact (add_tsub_cancel_of_le <| h i).symm - le_self_add := fun _ _ _ ↦ le_self_add } +instance [∀ i, CovariantClass (α i) (α i) (· + ·) (· ≤ ·)] : CanonicallyOrderedAdd (Π₀ i, α i) where + exists_add_of_le := by + intro f g h + exists g - f + ext i + exact (add_tsub_cancel_of_le <| h i).symm + le_self_add := fun _ _ _ ↦ le_self_add variable {α} [DecidableEq ι] @@ -287,11 +286,11 @@ theorem support_tsub : (f - g).support ⊆ f.support := by theorem subset_support_tsub : f.support \ g.support ⊆ (f - g).support := by simp +contextual [subset_iff] -end CanonicallyOrderedAddCommMonoid +end PartialOrder -section CanonicallyLinearOrderedAddCommMonoid - -variable [∀ i, CanonicallyLinearOrderedAddCommMonoid (α i)] [DecidableEq ι] {f g : Π₀ i, α i} +section LinearOrder +variable [∀ i, AddCommMonoid (α i)] [∀ i, LinearOrder (α i)] [∀ i, CanonicallyOrderedAdd (α i)] + [DecidableEq ι] {f g : Π₀ i, α i} @[simp] theorem support_inf : (f ⊓ g).support = f.support ∩ g.support := by @@ -310,6 +309,6 @@ nonrec theorem disjoint_iff : Disjoint f g ↔ Disjoint f.support g.support := b DFinsupp.support_inf] rfl -end CanonicallyLinearOrderedAddCommMonoid +end LinearOrder end DFinsupp diff --git a/Mathlib/Data/DFinsupp/WellFounded.lean b/Mathlib/Data/DFinsupp/WellFounded.lean index 082f7478b3b5e..4b312a0571ec7 100644 --- a/Mathlib/Data/DFinsupp/WellFounded.lean +++ b/Mathlib/Data/DFinsupp/WellFounded.lean @@ -163,7 +163,8 @@ theorem Lex.wellFounded' (hbot : ∀ ⦃i a⦄, ¬s i a 0) (hs : ∀ i, WellFoun end Zero instance Lex.wellFoundedLT [LT ι] [IsTrichotomous ι (· < ·)] [hι : WellFoundedGT ι] - [∀ i, CanonicallyOrderedAddCommMonoid (α i)] [hα : ∀ i, WellFoundedLT (α i)] : + [∀ i, AddMonoid (α i)] [∀ i, PartialOrder (α i)] [∀ i, CanonicallyOrderedAdd (α i)] + [hα : ∀ i, WellFoundedLT (α i)] : WellFoundedLT (Lex (Π₀ i, α i)) := ⟨Lex.wellFounded' (fun _ a => (zero_le a).not_lt) (fun i => (hα i).wf) hι.wf⟩ @@ -220,7 +221,8 @@ protected theorem DFinsupp.wellFoundedLT [∀ i, Zero (α i)] [∀ i, Preorder ( obtain ⟨i, he, hl⟩ := lex_lt_of_lt_of_preorder (Function.swap WellOrderingRel) h exact ⟨i, fun j hj ↦ Quot.sound (he j hj), hl⟩⟩ -instance DFinsupp.wellFoundedLT' [∀ i, CanonicallyOrderedAddCommMonoid (α i)] +instance DFinsupp.wellFoundedLT' + [∀ i, AddMonoid (α i)] [∀ i, PartialOrder (α i)] [∀ i, CanonicallyOrderedAdd (α i)] [∀ i, WellFoundedLT (α i)] : WellFoundedLT (Π₀ i, α i) := DFinsupp.wellFoundedLT fun _i a => (zero_le a).not_lt diff --git a/Mathlib/Data/ENNReal/Basic.lean b/Mathlib/Data/ENNReal/Basic.lean index 19de739a7c1ee..4ce8bf4d46529 100644 --- a/Mathlib/Data/ENNReal/Basic.lean +++ b/Mathlib/Data/ENNReal/Basic.lean @@ -110,16 +110,22 @@ instance : CharZero ℝ≥0∞ := inferInstanceAs (CharZero (WithTop ℝ≥0)) instance : Min ℝ≥0∞ := SemilatticeInf.toMin instance : Max ℝ≥0∞ := SemilatticeSup.toMax -noncomputable instance : CanonicallyOrderedCommSemiring ℝ≥0∞ := - inferInstanceAs (CanonicallyOrderedCommSemiring (WithTop ℝ≥0)) +noncomputable instance : OrderedCommSemiring ℝ≥0∞ := + inferInstanceAs (OrderedCommSemiring (WithTop ℝ≥0)) + +instance : CanonicallyOrderedAdd ℝ≥0∞ := + inferInstanceAs (CanonicallyOrderedAdd (WithTop ℝ≥0)) + +instance : NoZeroDivisors ℝ≥0∞ := + inferInstanceAs (NoZeroDivisors (WithTop ℝ≥0)) noncomputable instance : CompleteLinearOrder ℝ≥0∞ := inferInstanceAs (CompleteLinearOrder (WithTop ℝ≥0)) instance : DenselyOrdered ℝ≥0∞ := inferInstanceAs (DenselyOrdered (WithTop ℝ≥0)) -noncomputable instance : CanonicallyLinearOrderedAddCommMonoid ℝ≥0∞ := - inferInstanceAs (CanonicallyLinearOrderedAddCommMonoid (WithTop ℝ≥0)) +noncomputable instance : LinearOrderedAddCommMonoid ℝ≥0∞ := + inferInstanceAs (LinearOrderedAddCommMonoid (WithTop ℝ≥0)) noncomputable instance instSub : Sub ℝ≥0∞ := inferInstanceAs (Sub (WithTop ℝ≥0)) noncomputable instance : OrderedSub ℝ≥0∞ := inferInstanceAs (OrderedSub (WithTop ℝ≥0)) diff --git a/Mathlib/Data/ENNReal/Operations.lean b/Mathlib/Data/ENNReal/Operations.lean index ec458ac1544fb..24b26caf10c98 100644 --- a/Mathlib/Data/ENNReal/Operations.lean +++ b/Mathlib/Data/ENNReal/Operations.lean @@ -102,7 +102,7 @@ end Mul section OperationsAndOrder protected theorem pow_pos : 0 < a → ∀ n : ℕ, 0 < a ^ n := - CanonicallyOrderedCommSemiring.pow_pos + CanonicallyOrderedAdd.pow_pos protected theorem pow_ne_zero : a ≠ 0 → ∀ n : ℕ, a ^ n ≠ 0 := by simpa only [pos_iff_ne_zero] using ENNReal.pow_pos @@ -213,7 +213,7 @@ theorem mul_self_lt_top_iff {a : ℝ≥0∞} : a * a < ⊤ ↔ a < ⊤ := by exact zero_lt_top theorem mul_pos_iff : 0 < a * b ↔ 0 < a ∧ 0 < b := - CanonicallyOrderedCommSemiring.mul_pos + CanonicallyOrderedAdd.mul_pos theorem mul_pos (ha : a ≠ 0) (hb : b ≠ 0) : 0 < a * b := mul_pos_iff.2 ⟨pos_iff_ne_zero.2 ha, pos_iff_ne_zero.2 hb⟩ diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index a2e20f7680348..faee31c8187a7 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -3,12 +3,12 @@ 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.Algebra.Order.AddGroupWithTop import Mathlib.Algebra.Order.Ring.WithTop import Mathlib.Algebra.Order.Sub.WithTop import Mathlib.Data.ENat.Defs import Mathlib.Data.Nat.Cast.Order.Basic import Mathlib.Data.Nat.SuccPred -import Mathlib.Order.Nat /-! # Definition and basic properties of extended natural numbers @@ -34,8 +34,8 @@ similarly for multiplication. assert_not_exists Field -deriving instance Zero, CanonicallyOrderedCommSemiring, Nontrivial, - LinearOrder, Bot, CanonicallyLinearOrderedAddCommMonoid, Sub, +deriving instance Zero, OrderedCommSemiring, Nontrivial, + LinearOrder, Bot, LinearOrderedAddCommMonoid, Sub, LinearOrderedAddCommMonoidWithTop, WellFoundedRelation for ENat -- AddCommMonoidWithOne, @@ -47,6 +47,7 @@ deriving instance Zero, CanonicallyOrderedCommSemiring, Nontrivial, namespace ENat -- Porting note: instances that derive failed to find +instance : CanonicallyOrderedAdd ℕ∞ := WithTop.canonicallyOrderedAdd instance : OrderBot ℕ∞ := WithTop.orderBot instance : OrderTop ℕ∞ := WithTop.orderTop instance : OrderedSub ℕ∞ := inferInstanceAs (OrderedSub (WithTop ℕ)) @@ -452,8 +453,8 @@ protected def _root_.MonoidWithZeroHom.ENatMap {S : Type*} [MulZeroOneClass S] [ /-- A version of `ENat.map` for `RingHom`s. -/ @[simps (config := .asFn)] -protected def _root_.RingHom.ENatMap {S : Type*} [CanonicallyOrderedCommSemiring S] [DecidableEq S] - [Nontrivial S] (f : ℕ →+* S) (hf : Function.Injective f) : ℕ∞ →+* WithTop S := +protected def _root_.RingHom.ENatMap {S : Type*} [OrderedCommSemiring S] [CanonicallyOrderedAdd S] + [DecidableEq S] [Nontrivial S] (f : ℕ →+* S) (hf : Function.Injective f) : ℕ∞ →+* WithTop S := {MonoidWithZeroHom.ENatMap f.toMonoidWithZeroHom hf, f.toAddMonoidHom.ENatMap with} end ENat diff --git a/Mathlib/Data/Finite/Card.lean b/Mathlib/Data/Finite/Card.lean index 626fa23819d85..e67ab29b8eec6 100644 --- a/Mathlib/Data/Finite/Card.lean +++ b/Mathlib/Data/Finite/Card.lean @@ -106,7 +106,7 @@ theorem card_eq_zero_iff [Finite α] : Nat.card α = 0 ↔ IsEmpty α := by `Nat.card β = 0 → Nat.card α = 0` since `Nat.card` is defined to be `0` for infinite types. -/ theorem card_le_of_injective' {f : α → β} (hf : Function.Injective f) (h : Nat.card β = 0 → Nat.card α = 0) : Nat.card α ≤ Nat.card β := - (or_not_of_imp h).casesOn (fun h => le_of_eq_of_le h zero_le') fun h => + (or_not_of_imp h).casesOn (fun h => le_of_eq_of_le h (Nat.zero_le _)) fun h => @card_le_of_injective α β (Nat.finite_of_card_ne_zero h) f hf /-- If `f` is an embedding, then `Nat.card α ≤ Nat.card β`. We must also assume @@ -119,7 +119,7 @@ theorem card_le_of_embedding' (f : α ↪ β) (h : Nat.card β = 0 → Nat.card `Nat.card α = 0 → Nat.card β = 0` since `Nat.card` is defined to be `0` for infinite types. -/ theorem card_le_of_surjective' {f : α → β} (hf : Function.Surjective f) (h : Nat.card α = 0 → Nat.card β = 0) : Nat.card β ≤ Nat.card α := - (or_not_of_imp h).casesOn (fun h => le_of_eq_of_le h zero_le') fun h => + (or_not_of_imp h).casesOn (fun h => le_of_eq_of_le h (Nat.zero_le _)) fun h => @card_le_of_surjective α β (Nat.finite_of_card_ne_zero h) f hf /-- NB: `Nat.card` is defined to be `0` for infinite types. -/ diff --git a/Mathlib/Data/Finsupp/Interval.lean b/Mathlib/Data/Finsupp/Interval.lean index de42113086356..cdd213cd86319 100644 --- a/Mathlib/Data/Finsupp/Interval.lean +++ b/Mathlib/Data/Finsupp/Interval.lean @@ -132,7 +132,7 @@ end Lattice section CanonicallyOrdered -variable [CanonicallyOrderedAddCommMonoid α] [LocallyFiniteOrder α] +variable [AddCommMonoid α] [PartialOrder α] [CanonicallyOrderedAdd α] [LocallyFiniteOrder α] variable (f : ι →₀ α) theorem card_Iic : #(Iic f) = ∏ i ∈ f.support, #(Iic (f i)) := by diff --git a/Mathlib/Data/Finsupp/Lex.lean b/Mathlib/Data/Finsupp/Lex.lean index 87e567ec57773..d18f3ee749ed4 100644 --- a/Mathlib/Data/Finsupp/Lex.lean +++ b/Mathlib/Data/Finsupp/Lex.lean @@ -149,7 +149,8 @@ section OrderedAddMonoid variable [LinearOrder α] -instance Lex.orderBot [CanonicallyOrderedAddCommMonoid N] : OrderBot (Lex (α →₀ N)) where +instance Lex.orderBot [AddCommMonoid N] [PartialOrder N] [CanonicallyOrderedAdd N] : + OrderBot (Lex (α →₀ N)) where bot := 0 bot_le _ := Finsupp.toLex_monotone bot_le diff --git a/Mathlib/Data/Finsupp/Order.lean b/Mathlib/Data/Finsupp/Order.lean index ad9bfbd4b5485..58f85f4f5fe19 100644 --- a/Mathlib/Data/Finsupp/Order.lean +++ b/Mathlib/Data/Finsupp/Order.lean @@ -208,9 +208,9 @@ instance instSMulPosReflectLT [SMulPosReflectLT α β] : SMulPosReflectLT α (ι end SMulWithZero -section CanonicallyOrderedAddCommMonoid +section PartialOrder -variable [CanonicallyOrderedAddCommMonoid α] {f g : ι →₀ α} +variable [AddCommMonoid α] [PartialOrder α] [CanonicallyOrderedAdd α] {f g : ι →₀ α} instance orderBot : OrderBot (ι →₀ α) where bot := 0 @@ -256,11 +256,9 @@ instance tsub : Sub (ι →₀ α) := instance orderedSub : OrderedSub (ι →₀ α) := ⟨fun _n _m _k => forall_congr' fun _x => tsub_le_iff_right⟩ -instance : CanonicallyOrderedAddCommMonoid (ι →₀ α) := - { Finsupp.orderBot, - Finsupp.orderedAddCommMonoid with - exists_add_of_le := fun {f g} h => ⟨g - f, ext fun x => (add_tsub_cancel_of_le <| h x).symm⟩ - le_self_add := fun _f _g _x => le_self_add } +instance [CovariantClass α α (· + ·) (· ≤ ·)] : CanonicallyOrderedAdd (ι →₀ α) where + exists_add_of_le := fun {f g} h => ⟨g - f, ext fun x => (add_tsub_cancel_of_le <| h x).symm⟩ + le_self_add := fun _f _g _x => le_self_add @[simp, norm_cast] lemma coe_tsub (f g : ι →₀ α) : ⇑(f - g) = f - g := rfl @@ -282,11 +280,11 @@ theorem subset_support_tsub [DecidableEq ι] {f1 f2 : ι →₀ α} : f1.support \ f2.support ⊆ (f1 - f2).support := by simp +contextual [subset_iff] -end CanonicallyOrderedAddCommMonoid +end PartialOrder -section CanonicallyLinearOrderedAddCommMonoid +section LinearOrder -variable [CanonicallyLinearOrderedAddCommMonoid α] +variable [AddCommMonoid α] [LinearOrder α] [CanonicallyOrderedAdd α] @[simp] theorem support_inf [DecidableEq ι] (f g : ι →₀ α) : (f ⊓ g).support = f.support ∩ g.support := by @@ -307,7 +305,7 @@ nonrec theorem disjoint_iff {f g : ι →₀ α} : Disjoint f g ↔ Disjoint f.s Finsupp.support_inf] rfl -end CanonicallyLinearOrderedAddCommMonoid +end LinearOrder /-! ### Some lemmas about `ℕ` -/ diff --git a/Mathlib/Data/Finsupp/Weight.lean b/Mathlib/Data/Finsupp/Weight.lean index 65f0b2f4727d0..8b3984582b81b 100644 --- a/Mathlib/Data/Finsupp/Weight.lean +++ b/Mathlib/Data/Finsupp/Weight.lean @@ -153,7 +153,7 @@ end OrderedAddCommMonoid section CanonicallyOrderedAddCommMonoid -variable {M : Type*} [CanonicallyOrderedAddCommMonoid M] (w : σ → M) +variable {M : Type*} [OrderedAddCommMonoid M] [CanonicallyOrderedAdd M] (w : σ → M) theorem le_weight_of_ne_zero' {s : σ} {f : σ →₀ ℕ} (hs : f s ≠ 0) : w s ≤ weight w f := diff --git a/Mathlib/Data/Finsupp/WellFounded.lean b/Mathlib/Data/Finsupp/WellFounded.lean index 01fa1cb138541..336b2a1a6323b 100644 --- a/Mathlib/Data/Finsupp/WellFounded.lean +++ b/Mathlib/Data/Finsupp/WellFounded.lean @@ -49,7 +49,8 @@ theorem Lex.wellFounded' (hbot : ∀ ⦃n⦄, ¬s n 0) (hs : WellFounded s) InvImage.wf _ (DFinsupp.Lex.wellFounded' (fun _ => hbot) (fun _ => hs) hr) instance Lex.wellFoundedLT {α N} [LT α] [IsTrichotomous α (· < ·)] [hα : WellFoundedGT α] - [CanonicallyOrderedAddCommMonoid N] [hN : WellFoundedLT N] : WellFoundedLT (Lex (α →₀ N)) := + [AddMonoid N] [PartialOrder N] [CanonicallyOrderedAdd N] + [hN : WellFoundedLT N] : WellFoundedLT (Lex (α →₀ N)) := ⟨Lex.wellFounded' (fun n => (zero_le n).not_lt) hN.wf hα.wf⟩ variable (r) @@ -66,7 +67,8 @@ protected theorem wellFoundedLT [Preorder N] [WellFoundedLT N] (hbot : ∀ n : N WellFoundedLT (α →₀ N) := ⟨InvImage.wf toDFinsupp (DFinsupp.wellFoundedLT fun _ a => hbot a).wf⟩ -instance wellFoundedLT' {N} [CanonicallyOrderedAddCommMonoid N] [WellFoundedLT N] : +instance wellFoundedLT' {N} + [AddMonoid N] [PartialOrder N] [CanonicallyOrderedAdd N] [WellFoundedLT N] : WellFoundedLT (α →₀ N) := Finsupp.wellFoundedLT fun a => (zero_le a).not_lt diff --git a/Mathlib/Data/List/EditDistance/Bounds.lean b/Mathlib/Data/List/EditDistance/Bounds.lean index df199af6ccfa1..c03de0e023540 100644 --- a/Mathlib/Data/List/EditDistance/Bounds.lean +++ b/Mathlib/Data/List/EditDistance/Bounds.lean @@ -19,7 +19,8 @@ This allows us to use the intermediate steps of a Levenshtein distance calculati to produce lower bounds on the final result. -/ -variable {α β δ : Type*} {C : Levenshtein.Cost α β δ} [CanonicallyLinearOrderedAddCommMonoid δ] +variable {α β δ : Type*} {C : Levenshtein.Cost α β δ} + [LinearOrderedAddCommMonoid δ] [CanonicallyOrderedAdd δ] theorem suffixLevenshtein_minimum_le_levenshtein_cons (xs : List α) (y ys) : (suffixLevenshtein C xs ys).1.minimum ≤ levenshtein C xs (y :: ys) := by diff --git a/Mathlib/Data/List/EditDistance/Estimator.lean b/Mathlib/Data/List/EditDistance/Estimator.lean index e000b2bc0d02b..062231f934853 100644 --- a/Mathlib/Data/List/EditDistance/Estimator.lean +++ b/Mathlib/Data/List/EditDistance/Estimator.lean @@ -23,7 +23,7 @@ This is then used in the implementation of `rewrite_search` to avoid needing the entire edit distance calculation in unlikely search paths. -/ -variable {α : Type*} {β δ : Type} [CanonicallyLinearOrderedAddCommMonoid δ] +variable {α : Type*} {β δ : Type} [LinearOrderedAddCommMonoid δ] [CanonicallyOrderedAdd δ] (C : Levenshtein.Cost α β δ) (xs : List α) (ys : List β) /-- diff --git a/Mathlib/Data/Multiset/OrderedMonoid.lean b/Mathlib/Data/Multiset/OrderedMonoid.lean index a674512d9f22c..a678c0f63c742 100644 --- a/Mathlib/Data/Multiset/OrderedMonoid.lean +++ b/Mathlib/Data/Multiset/OrderedMonoid.lean @@ -9,7 +9,7 @@ import Mathlib.Algebra.Order.Monoid.Canonical.Defs /-! # Multisets as ordered monoids -The `OrderedCancelAddCommMonoid` and `CanonicallyOrderedAddCommMonoid` instances on `Multiset α` +The `OrderedCancelAddCommMonoid` and `CanonicallyOrderedAdd` instances on `Multiset α` -/ @@ -23,8 +23,7 @@ instance : OrderedCancelAddCommMonoid (Multiset α) where add_le_add_left := fun _ _ => add_le_add_left le_of_add_le_add_left := fun _ _ _ => le_of_add_le_add_left -instance : CanonicallyOrderedAddCommMonoid (Multiset α) where - __ := inferInstanceAs (OrderBot (Multiset α)) +instance : CanonicallyOrderedAdd (Multiset α) where le_self_add := le_add_right exists_add_of_le h := exists_add_of_le h diff --git a/Mathlib/Data/NNRat/Floor.lean b/Mathlib/Data/NNRat/Floor.lean index 02d70c2c3d123..59171dd49269e 100644 --- a/Mathlib/Data/NNRat/Floor.lean +++ b/Mathlib/Data/NNRat/Floor.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ +import Mathlib.Data.NNRat.Order import Mathlib.Data.Rat.Floor /-! diff --git a/Mathlib/Data/NNRat/Order.lean b/Mathlib/Data/NNRat/Order.lean index 4b09aedfa4560..3cb3542f8d69f 100644 --- a/Mathlib/Data/NNRat/Order.lean +++ b/Mathlib/Data/NNRat/Order.lean @@ -12,8 +12,9 @@ import Mathlib.Algebra.Order.Nonneg.Ring -/ -deriving instance CanonicallyOrderedCommSemiring for NNRat -deriving instance CanonicallyLinearOrderedAddCommMonoid for NNRat +deriving instance OrderedCommSemiring for NNRat +deriving instance LinearOrderedAddCommMonoid for NNRat -- TODO: `deriving instance OrderedSub for NNRat` doesn't work yet, so we add the instance manually instance NNRat.instOrderedSub : OrderedSub ℚ≥0 := Nonneg.orderedSub +instance NNRat.instCanonicallyOrderedAdd : CanonicallyOrderedAdd ℚ≥0 := Nonneg.canonicallyOrderedAdd diff --git a/Mathlib/Data/NNReal/Basic.lean b/Mathlib/Data/NNReal/Basic.lean index be8f76fd33712..740187c51b741 100644 --- a/Mathlib/Data/NNReal/Basic.lean +++ b/Mathlib/Data/NNReal/Basic.lean @@ -5,7 +5,7 @@ Authors: Johan Commelin -/ import Mathlib.Algebra.BigOperators.Expect import Mathlib.Algebra.Order.BigOperators.Ring.Finset -import Mathlib.Algebra.Order.Field.Canonical.Basic +import Mathlib.Algebra.Order.Field.Canonical import Mathlib.Algebra.Order.Nonneg.Floor import Mathlib.Data.Real.Pointwise import Mathlib.Data.NNReal.Defs diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index ba671cb7bf4fd..68c6a36bd742b 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -23,7 +23,7 @@ a.k.a. the interval `[0, ∞)`. We also define the following operations and stru - `LinearOrderedSemiring ℝ≥0`; - `OrderedCommSemiring ℝ≥0`; - - `CanonicallyOrderedCommSemiring ℝ≥0`; + - `CanonicallyOrderedAdd ℝ≥0`; - `LinearOrderedCommGroupWithZero ℝ≥0`; - `CanonicallyLinearOrderedAddCommMonoid ℝ≥0`; - `Archimedean ℝ≥0`; @@ -54,12 +54,14 @@ open Function def NNReal := { r : ℝ // 0 ≤ r } deriving Zero, One, Semiring, StrictOrderedSemiring, CommMonoidWithZero, CommSemiring, PartialOrder, SemilatticeInf, SemilatticeSup, DistribLattice, OrderedCommSemiring, - CanonicallyOrderedCommSemiring, Inhabited + OrderedCommMonoid, Nontrivial, Inhabited namespace NNReal scoped notation "ℝ≥0" => NNReal +instance : CanonicallyOrderedAdd ℝ≥0 := Nonneg.canonicallyOrderedAdd +instance : NoZeroDivisors ℝ≥0 := Nonneg.noZeroDivisors instance instDenselyOrdered : DenselyOrdered ℝ≥0 := Nonneg.instDenselyOrdered instance : OrderBot ℝ≥0 := inferInstance instance instArchimedean : Archimedean ℝ≥0 := Nonneg.instArchimedean @@ -69,8 +71,11 @@ instance : Max ℝ≥0 := SemilatticeSup.toMax noncomputable instance : Sub ℝ≥0 := Nonneg.sub noncomputable instance : OrderedSub ℝ≥0 := Nonneg.orderedSub -noncomputable instance : CanonicallyLinearOrderedSemifield ℝ≥0 := - Nonneg.canonicallyLinearOrderedSemifield +noncomputable instance : LinearOrderedSemifield ℝ≥0 := + Nonneg.linearOrderedSemifield + +noncomputable instance : LinearOrderedCommGroupWithZero ℝ≥0 := + Nonneg.linearOrderedCommGroupWithZero /-- Coercion `ℝ≥0 → ℝ`. -/ @[coe] def toReal : ℝ≥0 → ℝ := Subtype.val @@ -330,8 +335,6 @@ example : OrderBot ℝ≥0 := by infer_instance example : PartialOrder ℝ≥0 := by infer_instance -noncomputable example : CanonicallyLinearOrderedAddCommMonoid ℝ≥0 := by infer_instance - noncomputable example : LinearOrderedAddCommMonoid ℝ≥0 := by infer_instance example : DistribLattice ℝ≥0 := by infer_instance @@ -348,10 +351,6 @@ noncomputable example : LinearOrderedCommMonoid ℝ≥0 := by infer_instance noncomputable example : LinearOrderedCommMonoidWithZero ℝ≥0 := by infer_instance -noncomputable example : LinearOrderedCommGroupWithZero ℝ≥0 := by infer_instance - -example : CanonicallyOrderedCommSemiring ℝ≥0 := by infer_instance - example : DenselyOrdered ℝ≥0 := by infer_instance example : NoMaxOrder ℝ≥0 := by infer_instance diff --git a/Mathlib/Data/Nat/BitIndices.lean b/Mathlib/Data/Nat/BitIndices.lean index 8c4e3d74b89f5..5f23a8379c67d 100644 --- a/Mathlib/Data/Nat/BitIndices.lean +++ b/Mathlib/Data/Nat/BitIndices.lean @@ -5,7 +5,7 @@ Authors: Peter Nelson -/ import Mathlib.Algebra.BigOperators.Ring.List import Mathlib.Algebra.Order.BigOperators.Group.List -import Mathlib.Algebra.Order.Star.Basic +import Mathlib.Algebra.Order.Ring.Nat import Mathlib.Algebra.Order.Sub.Basic import Mathlib.Data.List.Sort import Mathlib.Data.Nat.Bitwise diff --git a/Mathlib/Data/Nat/Cast/Order/Ring.lean b/Mathlib/Data/Nat/Cast/Order/Ring.lean index 54269e96efeb0..7eb4e24e84de6 100644 --- a/Mathlib/Data/Nat/Cast/Order/Ring.lean +++ b/Mathlib/Data/Nat/Cast/Order/Ring.lean @@ -3,8 +3,9 @@ Copyright (c) 2014 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Order.Ring.Nat import Mathlib.Algebra.Order.Group.Unbundled.Abs +import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Order.Sub.Basic import Mathlib.Data.Nat.Cast.Order.Basic /-! @@ -69,7 +70,7 @@ end OrderedSemiring /-- A version of `Nat.cast_sub` that works for `ℝ≥0` and `ℚ≥0`. Note that this proof doesn't work for `ℕ∞` and `ℝ≥0∞`, so we use type-specific lemmas for these types. -/ @[simp, norm_cast] -theorem cast_tsub [CanonicallyOrderedCommSemiring α] [Sub α] [OrderedSub α] +theorem cast_tsub [OrderedCommSemiring α] [CanonicallyOrderedAdd α] [Sub α] [OrderedSub α] [AddLeftReflectLE α] (m n : ℕ) : ↑(m - n) = (m - n : α) := by rcases le_total m n with h | h · rw [Nat.sub_eq_zero_of_le h, cast_zero, tsub_eq_zero_of_le] diff --git a/Mathlib/Data/Nat/Cast/SetInterval.lean b/Mathlib/Data/Nat/Cast/SetInterval.lean index 1b7255ba22cca..1c5a391b8d65c 100644 --- a/Mathlib/Data/Nat/Cast/SetInterval.lean +++ b/Mathlib/Data/Nat/Cast/SetInterval.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.Order.Ring.Int -import Mathlib.Order.UpperLower.Basic -import Mathlib.Algebra.Order.Ring.Nat import Mathlib.Data.Nat.Cast.Order.Basic +import Mathlib.Order.Nat +import Mathlib.Order.UpperLower.Basic /-! # Images of intervals under `Nat.cast : ℕ → ℤ` diff --git a/Mathlib/Data/Nat/Dist.lean b/Mathlib/Data/Nat/Dist.lean index b207d03af6224..4ae4c2bacffe8 100644 --- a/Mathlib/Data/Nat/Dist.lean +++ b/Mathlib/Data/Nat/Dist.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Jeremy Avigad -/ import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Order.Ring.Canonical /-! # Distance function on ℕ diff --git a/Mathlib/Data/Nat/PartENat.lean b/Mathlib/Data/Nat/PartENat.lean index 22dbf8f8562ca..5b4dd68288d83 100644 --- a/Mathlib/Data/Nat/PartENat.lean +++ b/Mathlib/Data/Nat/PartENat.lean @@ -19,7 +19,7 @@ implementation. Use `ℕ∞` instead unless you care about computability. The following instances are defined: * `OrderedAddCommMonoid PartENat` -* `CanonicallyOrderedAddCommMonoid PartENat` +* `CanonicallyOrderedAdd PartENat` * `CompleteLinearOrder PartENat` There is no additive analogue of `MonoidWithZero`; if there were then `PartENat` could @@ -407,10 +407,8 @@ noncomputable instance lattice : Lattice PartENat := inf_le_right := min_le_right le_inf := fun _ _ _ => le_min } -noncomputable instance : CanonicallyOrderedAddCommMonoid PartENat := - { PartENat.semilatticeSup, PartENat.orderBot, - PartENat.orderedAddCommMonoid with - le_self_add := fun a b => +instance : CanonicallyOrderedAdd PartENat := + { le_self_add := fun a b => PartENat.casesOn b (le_top.trans_eq (add_top _).symm) fun _ => PartENat.casesOn a (top_add _).ge fun _ => (coe_le_coe.2 le_self_add).trans_eq (Nat.cast_add _ _) diff --git a/Mathlib/Data/Nat/Squarefree.lean b/Mathlib/Data/Nat/Squarefree.lean index 5560ced0e6857..c81e7815857a8 100644 --- a/Mathlib/Data/Nat/Squarefree.lean +++ b/Mathlib/Data/Nat/Squarefree.lean @@ -318,7 +318,7 @@ theorem sq_mul_squarefree_of_pos {n : ℕ} (hn : 0 < n) : simp only [S, Finset.mem_filter, Finset.mem_range] at hs obtain ⟨-, ⟨a, hsa⟩, ⟨b, hsb⟩⟩ := hs rw [hsa] at hn - obtain ⟨hlts, hlta⟩ := CanonicallyOrderedCommSemiring.mul_pos.mp hn + obtain ⟨hlts, hlta⟩ := CanonicallyOrderedAdd.mul_pos.mp hn rw [hsb] at hsa hn hlts refine ⟨a, b, hlta, (pow_pos_iff two_ne_zero).mp hlts, hsa.symm, ?_⟩ rintro x ⟨y, hy⟩ diff --git a/Mathlib/Data/Nat/SuccPred.lean b/Mathlib/Data/Nat/SuccPred.lean index 8f04e28fb1012..545e330d6012f 100644 --- a/Mathlib/Data/Nat/SuccPred.lean +++ b/Mathlib/Data/Nat/SuccPred.lean @@ -3,9 +3,12 @@ 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 -/ -import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Order.Group.Nat +import Mathlib.Algebra.Ring.Nat +import Mathlib.Algebra.Order.Sub.Unbundled.Basic import Mathlib.Algebra.Order.SuccPred import Mathlib.Data.Fin.Basic +import Mathlib.Order.Nat import Mathlib.Order.SuccPred.Archimedean /-! diff --git a/Mathlib/Data/Nat/Upto.lean b/Mathlib/Data/Nat/Upto.lean index f62ea9e9062d1..b3cc393700701 100644 --- a/Mathlib/Data/Nat/Upto.lean +++ b/Mathlib/Data/Nat/Upto.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Order.Sub.Basic /-! # `Nat.Upto` diff --git a/Mathlib/Data/Nat/WithBot.lean b/Mathlib/Data/Nat/WithBot.lean index 125eeae18ef2b..c5e509731a527 100644 --- a/Mathlib/Data/Nat/WithBot.lean +++ b/Mathlib/Data/Nat/WithBot.lean @@ -3,9 +3,8 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ - -import Mathlib.Algebra.Order.Ring.Nat -import Mathlib.Algebra.Order.Monoid.WithTop +import Mathlib.Algebra.Order.Group.Nat +import Mathlib.Algebra.Order.GroupWithZero.Canonical import Mathlib.Data.Nat.Cast.WithTop /-! diff --git a/Mathlib/Data/PNat/Basic.lean b/Mathlib/Data/PNat/Basic.lean index 1fa3b23e82f47..15856db6c2dff 100644 --- a/Mathlib/Data/PNat/Basic.lean +++ b/Mathlib/Data/PNat/Basic.lean @@ -3,11 +3,11 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Ralf Stephan, Neil Strickland, Ruben Van de Velde -/ -import Mathlib.Data.PNat.Equiv -import Mathlib.Algebra.Order.Ring.Nat import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.Order.Positive.Ring -import Mathlib.Order.Hom.Basic +import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Order.Sub.Basic +import Mathlib.Data.PNat.Equiv /-! # The positive natural numbers diff --git a/Mathlib/Data/PNat/Factors.lean b/Mathlib/Data/PNat/Factors.lean index 59ecfa1addf1b..542e0c2b3046e 100644 --- a/Mathlib/Data/PNat/Factors.lean +++ b/Mathlib/Data/PNat/Factors.lean @@ -27,14 +27,17 @@ the multiplicity of `p` in this factors multiset being the p-adic valuation of ` gives an equivalence between this set and ℕ+, as we will formalize below. -/ def PrimeMultiset := - Multiset Nat.Primes deriving Inhabited, CanonicallyOrderedAddCommMonoid, DistribLattice, + Multiset Nat.Primes deriving Inhabited, OrderedCancelAddCommMonoid, DistribLattice, SemilatticeSup, Sub -instance : OrderBot PrimeMultiset where - bot_le := by simp only [bot_le, forall_const] +instance : CanonicallyOrderedAdd PrimeMultiset := + inferInstanceAs (CanonicallyOrderedAdd (Multiset Nat.Primes)) -instance : OrderedSub PrimeMultiset where - tsub_le_iff_right _ _ _ := Multiset.sub_le_iff_le_add +instance : OrderBot PrimeMultiset := + inferInstanceAs (OrderBot (Multiset Nat.Primes)) + +instance : OrderedSub PrimeMultiset := + inferInstanceAs (OrderedSub (Multiset Nat.Primes)) namespace PrimeMultiset diff --git a/Mathlib/Data/Rat/Floor.lean b/Mathlib/Data/Rat/Floor.lean index a916bde474c7d..fa01f1ac3ee5f 100644 --- a/Mathlib/Data/Rat/Floor.lean +++ b/Mathlib/Data/Rat/Floor.lean @@ -58,7 +58,7 @@ protected theorem ceil_def (q : ℚ) : ⌈q⌉ = -(-q.num / ↑q.den) := by @[norm_cast] theorem floor_intCast_div_natCast (n : ℤ) (d : ℕ) : ⌊(↑n / ↑d : ℚ)⌋ = n / (↑d : ℤ) := by rw [Rat.floor_def] - obtain rfl | hd := @eq_zero_or_pos _ _ d + obtain rfl | hd := eq_zero_or_pos (a := d) · simp set q := (n : ℚ) / d with q_eq obtain ⟨c, n_eq_c_mul_num, d_eq_c_mul_denom⟩ : ∃ c, n = c * q.num ∧ (d : ℤ) = c * q.den := by diff --git a/Mathlib/Data/Rat/Star.lean b/Mathlib/Data/Rat/Star.lean index 1e69ef6c77136..f810f643d4a9e 100644 --- a/Mathlib/Data/Rat/Star.lean +++ b/Mathlib/Data/Rat/Star.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.Order.Field.Rat import Mathlib.Algebra.Order.Monoid.Submonoid import Mathlib.Algebra.Order.Ring.Abs import Mathlib.Algebra.Order.Star.Basic +import Mathlib.Data.NNRat.Order import Mathlib.Tactic.FieldSimp /-! diff --git a/Mathlib/Data/Set/Card.lean b/Mathlib/Data/Set/Card.lean index 8ffca3aba9675..3355f09f3689d 100644 --- a/Mathlib/Data/Set/Card.lean +++ b/Mathlib/Data/Set/Card.lean @@ -598,7 +598,7 @@ theorem ncard_diff_singleton_lt_of_mem {a : α} (h : a ∈ s) (hs : s.Finite := theorem ncard_diff_singleton_le (s : Set α) (a : α) : (s \ {a}).ncard ≤ s.ncard := by obtain hs | hs := s.finite_or_infinite · apply ncard_le_ncard diff_subset hs - convert @zero_le ℕ _ _ + convert zero_le (α := ℕ) _ exact (hs.diff (by simp : Set.Finite {a})).ncard theorem pred_ncard_le_ncard_diff_singleton (s : Set α) (a : α) : s.ncard - 1 ≤ (s \ {a}).ncard := by diff --git a/Mathlib/Data/Set/Semiring.lean b/Mathlib/Data/Set/Semiring.lean index ab57903aa99c4..f69b70815610c 100644 --- a/Mathlib/Data/Set/Semiring.lean +++ b/Mathlib/Data/Set/Semiring.lean @@ -200,13 +200,12 @@ instance [CommMonoid α] : IdemCommSemiring (SetSemiring α) := instance [CommMonoid α] : CommMonoid (SetSemiring α) := { (inferInstance : Monoid (SetSemiring α)), Set.commSemigroup with } -instance [CommMonoid α] : CanonicallyOrderedCommSemiring (SetSemiring α) := - { (inferInstance : Semiring (SetSemiring α)), (inferInstance : CommMonoid (SetSemiring α)), - (inferInstance : PartialOrder (SetSemiring α)), (inferInstance : OrderBot (SetSemiring α)), - (inferInstance : NoZeroDivisors (SetSemiring α)) with - add_le_add_left := fun _ _ => add_le_add_left - exists_add_of_le := fun {_ b} ab => ⟨b, (union_eq_right.2 ab).symm⟩ - le_self_add := fun _ _ => subset_union_left } +instance : CanonicallyOrderedAdd (SetSemiring α) where + exists_add_of_le {_ b} ab := ⟨b, (union_eq_right.2 ab).symm⟩ + le_self_add _ _ := subset_union_left + +instance [CommMonoid α] : OrderedCommSemiring (SetSemiring α) := + CanonicallyOrderedAdd.toOrderedCommSemiring /-- The image of a set under a multiplicative homomorphism is a ring homomorphism with respect to the pointwise operations on sets. -/ diff --git a/Mathlib/Dynamics/Flow.lean b/Mathlib/Dynamics/Flow.lean index bc7748dcf6949..cc99c3c250fdc 100644 --- a/Mathlib/Dynamics/Flow.lean +++ b/Mathlib/Dynamics/Flow.lean @@ -54,15 +54,16 @@ def IsFwInvariant [Preorder τ] [Zero τ] (ϕ : τ → α → α) (s : Set α) : theorem IsInvariant.isFwInvariant [Preorder τ] [Zero τ] {ϕ : τ → α → α} {s : Set α} (h : IsInvariant ϕ s) : IsFwInvariant ϕ s := fun t _ht => h t -/-- If `τ` is a `CanonicallyOrderedAddCommMonoid` (e.g., `ℕ` or `ℝ≥0`), then the notions +/-- If `τ` is a `CanonicallyOrderedAdd` monoid (e.g., `ℕ` or `ℝ≥0`), then the notions `IsFwInvariant` and `IsInvariant` are equivalent. -/ -theorem IsFwInvariant.isInvariant [CanonicallyOrderedAddCommMonoid τ] {ϕ : τ → α → α} {s : Set α} +theorem IsFwInvariant.isInvariant [AddMonoid τ] [PartialOrder τ] [CanonicallyOrderedAdd τ] + {ϕ : τ → α → α} {s : Set α} (h : IsFwInvariant ϕ s) : IsInvariant ϕ s := fun t => h (zero_le t) -/-- If `τ` is a `CanonicallyOrderedAddCommMonoid` (e.g., `ℕ` or `ℝ≥0`), then the notions +/-- If `τ` is a `CanonicallyOrderedAdd` monoid (e.g., `ℕ` or `ℝ≥0`), then the notions `IsFwInvariant` and `IsInvariant` are equivalent. -/ -theorem isFwInvariant_iff_isInvariant [CanonicallyOrderedAddCommMonoid τ] {ϕ : τ → α → α} - {s : Set α} : +theorem isFwInvariant_iff_isInvariant [AddMonoid τ] [PartialOrder τ] [CanonicallyOrderedAdd τ] + {ϕ : τ → α → α} {s : Set α} : IsFwInvariant ϕ s ↔ IsInvariant ϕ s := ⟨IsFwInvariant.isInvariant, IsInvariant.isFwInvariant⟩ diff --git a/Mathlib/MeasureTheory/Constructions/Pi.lean b/Mathlib/MeasureTheory/Constructions/Pi.lean index 102c61a082662..d2ad209b30457 100644 --- a/Mathlib/MeasureTheory/Constructions/Pi.lean +++ b/Mathlib/MeasureTheory/Constructions/Pi.lean @@ -551,7 +551,7 @@ instance pi.isOpenPosMeasure [∀ i, TopologicalSpace (α i)] [∀ i, IsOpenPosM obtain ⟨s, ⟨hs, hsU⟩⟩ := isOpen_pi_iff'.1 U_open a ha refine ne_of_gt (lt_of_lt_of_le ?_ (measure_mono hsU)) simp only [pi_pi] - rw [CanonicallyOrderedCommSemiring.prod_pos] + rw [CanonicallyOrderedAdd.prod_pos] intro i _ apply (hs i).1.measure_pos (μ i) ⟨a i, (hs i).2⟩ diff --git a/Mathlib/MeasureTheory/Group/Arithmetic.lean b/Mathlib/MeasureTheory/Group/Arithmetic.lean index 0d9b2426dd69b..02a6beaae2fd8 100644 --- a/Mathlib/MeasureTheory/Group/Arithmetic.lean +++ b/Mathlib/MeasureTheory/Group/Arithmetic.lean @@ -310,7 +310,8 @@ theorem measurableSet_eq_fun {m : MeasurableSpace α} {E} [MeasurableSpace E] [A simp_rw [Set.mem_setOf_eq, Pi.sub_apply, sub_eq_zero] @[measurability] -lemma measurableSet_eq_fun' {β : Type*} [CanonicallyOrderedAddCommMonoid β] [Sub β] [OrderedSub β] +lemma measurableSet_eq_fun' {β : Type*} [AddCommMonoid β] [PartialOrder β] + [CanonicallyOrderedAdd β] [Sub β] [OrderedSub β] {_ : MeasurableSpace β} [MeasurableSub₂ β] [MeasurableSingletonClass β] {f g : α → β} (hf : Measurable f) (hg : Measurable g) : MeasurableSet {x | f x = g x} := by diff --git a/Mathlib/MeasureTheory/Measure/Prod.lean b/Mathlib/MeasureTheory/Measure/Prod.lean index 951fd5c3bf2c4..6248de656ceb8 100644 --- a/Mathlib/MeasureTheory/Measure/Prod.lean +++ b/Mathlib/MeasureTheory/Measure/Prod.lean @@ -226,7 +226,7 @@ instance prod.instIsOpenPosMeasure {X Y : Type*} [TopologicalSpace X] [Topologic rintro U U_open ⟨⟨x, y⟩, hxy⟩ rcases isOpen_prod_iff.1 U_open x y hxy with ⟨u, v, u_open, v_open, xu, yv, huv⟩ refine ne_of_gt (lt_of_lt_of_le ?_ (measure_mono huv)) - simp only [prod_prod, CanonicallyOrderedCommSemiring.mul_pos] + simp only [prod_prod, CanonicallyOrderedAdd.mul_pos] constructor · exact u_open.measure_pos μ ⟨x, xu⟩ · exact v_open.measure_pos ν ⟨y, yv⟩ diff --git a/Mathlib/Order/Filter/Germ/OrderedMonoid.lean b/Mathlib/Order/Filter/Germ/OrderedMonoid.lean index a3446d9e484a3..a4b8e819d24cd 100644 --- a/Mathlib/Order/Filter/Germ/OrderedMonoid.lean +++ b/Mathlib/Order/Filter/Germ/OrderedMonoid.lean @@ -36,9 +36,8 @@ instance instOrderedCancelCommMonoid [OrderedCancelCommMonoid β] : fun _ ↦ le_of_mul_le_mul_left' @[to_additive] -instance instCanonicallyOrderedCommMonoid [CanonicallyOrderedCommMonoid β] : - CanonicallyOrderedCommMonoid (Germ l β) where - __ := instExistsMulOfLE +instance instCanonicallyOrderedMul [Mul β] [LE β] [CanonicallyOrderedMul β] : + CanonicallyOrderedMul (Germ l β) where le_self_mul x y := inductionOn₂ x y fun _ _ ↦ Eventually.of_forall fun _ ↦ le_self_mul end Filter.Germ diff --git a/Mathlib/Order/Interval/Finset/Nat.lean b/Mathlib/Order/Interval/Finset/Nat.lean index c768f296032a1..d446eb5f35743 100644 --- a/Mathlib/Order/Interval/Finset/Nat.lean +++ b/Mathlib/Order/Interval/Finset/Nat.lean @@ -13,7 +13,7 @@ intervals as finsets and fintypes. ## TODO -Some lemmas can be generalized using `OrderedGroup`, `CanonicallyOrderedCommMonoid` or `SuccOrder` +Some lemmas can be generalized using `OrderedGroup`, `CanonicallyOrderedMul` or `SuccOrder` and subsequently be moved upstream to `Order.Interval.Finset`. -/ diff --git a/Mathlib/Order/JordanHolder.lean b/Mathlib/Order/JordanHolder.lean index 433f6b9d1bf33..14643d82fa4aa 100644 --- a/Mathlib/Order/JordanHolder.lean +++ b/Mathlib/Order/JordanHolder.lean @@ -194,7 +194,7 @@ theorem head_le_of_mem {s : CompositionSeries X} {x : X} (hx : x ∈ s) : s.head hi ▸ head_le _ theorem last_eraseLast_le (s : CompositionSeries X) : s.eraseLast.last ≤ s.last := by - simp [eraseLast, last, s.strictMono.le_iff_le, Fin.le_iff_val_le_val, tsub_le_self] + simp [eraseLast, last, s.strictMono.le_iff_le, Fin.le_iff_val_le_val] theorem mem_eraseLast_of_ne_of_mem {s : CompositionSeries X} {x : X} (hx : x ≠ s.last) (hxs : x ∈ s) : x ∈ s.eraseLast := by diff --git a/Mathlib/Order/RelSeries.lean b/Mathlib/Order/RelSeries.lean index 21940c227fda3..81867c483651c 100644 --- a/Mathlib/Order/RelSeries.lean +++ b/Mathlib/Order/RelSeries.lean @@ -488,8 +488,8 @@ another series -/ @[simps] def eraseLast (p : RelSeries r) : RelSeries r where length := p.length - 1 - toFun i := p ⟨i, lt_of_lt_of_le i.2 (Nat.succ_le_succ tsub_le_self)⟩ - step i := p.step ⟨i, lt_of_lt_of_le i.2 tsub_le_self⟩ + toFun i := p ⟨i, lt_of_lt_of_le i.2 (Nat.succ_le_succ (Nat.sub_le _ _))⟩ + step i := p.step ⟨i, lt_of_lt_of_le i.2 (Nat.sub_le _ _)⟩ @[simp] lemma head_eraseLast (p : RelSeries r) : p.eraseLast.head = p.head := rfl @@ -555,7 +555,7 @@ lemma smash_succ_castAdd {p q : RelSeries r} (h : p.last = q.head) · simp only [Fin.val_succ, Fin.coe_castAdd] at H convert h.symm · congr - simp only [Fin.val_succ, Fin.coe_castAdd, Nat.zero_mod, tsub_eq_zero_iff_le] + simp only [Fin.val_succ, Fin.coe_castAdd, Nat.zero_mod, Nat.sub_eq_zero_iff_le] omega · congr ext @@ -581,7 +581,7 @@ lemma smash_succ_natAdd {p q : RelSeries r} (h : p.last = q.head) (i : Fin q.len @[simp] lemma head_smash {p q : RelSeries r} (h : p.last = q.head) : (smash p q h).head = p.head := by delta head smash - simp only [Fin.val_zero, Fin.zero_eta, zero_le, tsub_eq_zero_of_le, dite_eq_ite, + simp only [Fin.val_zero, Fin.zero_eta, zero_le, Nat.sub_eq_zero_of_le, dite_eq_ite, ite_eq_left_iff, not_lt, nonpos_iff_eq_zero] intro H; convert h.symm; congr; aesop diff --git a/Mathlib/Probability/StrongLaw.lean b/Mathlib/Probability/StrongLaw.lean index 0fadd8a41b7a2..42dd11637cec5 100644 --- a/Mathlib/Probability/StrongLaw.lean +++ b/Mathlib/Probability/StrongLaw.lean @@ -431,7 +431,7 @@ theorem strong_law_aux1 {c : ℝ} (c_one : 1 < c) {ε : ℝ} (εpos : 0 < ε) : all_goals simp _ ≤ ∑ j ∈ range (u (N - 1)), c ^ 5 * (c - 1)⁻¹ ^ 3 / ↑j ^ 2 * Var[Y j] := by apply sum_le_sum fun j hj => ?_ - rcases @eq_zero_or_pos _ _ j with (rfl | hj) + rcases eq_zero_or_pos j with (rfl | hj) · simp only [Nat.cast_zero, zero_pow, Ne, Nat.one_ne_zero, not_false_iff, div_zero, zero_mul] simp only [Y, Nat.cast_zero, truncation_zero, variance_zero, mul_zero, le_rfl] diff --git a/Mathlib/RingTheory/GradedAlgebra/Basic.lean b/Mathlib/RingTheory/GradedAlgebra/Basic.lean index 0121091f00ac2..295825d2de1f4 100644 --- a/Mathlib/RingTheory/GradedAlgebra/Basic.lean +++ b/Mathlib/RingTheory/GradedAlgebra/Basic.lean @@ -231,7 +231,7 @@ section CanonicalOrder open SetLike.GradedMonoid DirectSum variable [Semiring A] [DecidableEq ι] -variable [CanonicallyOrderedAddCommMonoid ι] +variable [AddCommMonoid ι] [PartialOrder ι] [CanonicallyOrderedAdd ι] variable [SetLike σ A] [AddSubmonoidClass σ A] (𝒜 : ι → σ) [GradedRing 𝒜] /-- If `A` is graded by a canonically ordered add monoid, then the projection map `x ↦ x₀` is a ring diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean index 9e6bb7c9c8207..bf7086a3d0598 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean @@ -562,7 +562,7 @@ section IrrelevantIdeal variable [Semiring A] variable [DecidableEq ι] -variable [CanonicallyOrderedAddCommMonoid ι] +variable [AddCommMonoid ι] [PartialOrder ι] [CanonicallyOrderedAdd ι] variable [SetLike σ A] [AddSubmonoidClass σ A] (𝒜 : ι → σ) [GradedRing 𝒜] open GradedRing SetLike.GradedMonoid DirectSum diff --git a/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean b/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean index 9bd8cc5122295..f85b7e1ad1f22 100644 --- a/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean +++ b/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean @@ -15,7 +15,7 @@ also a Noetherian ring. variable {ι A σ : Type*} variable [Ring A] [IsNoetherianRing A] -variable [DecidableEq ι] [CanonicallyOrderedAddCommMonoid ι] +variable [DecidableEq ι] [OrderedAddCommMonoid ι] [CanonicallyOrderedAdd ι] variable [SetLike σ A] [AddSubgroupClass σ A] variable (𝒜 : ι → σ) [GradedRing 𝒜] diff --git a/Mathlib/RingTheory/Multiplicity.lean b/Mathlib/RingTheory/Multiplicity.lean index c006029fa2951..73e3216579502 100644 --- a/Mathlib/RingTheory/Multiplicity.lean +++ b/Mathlib/RingTheory/Multiplicity.lean @@ -285,7 +285,7 @@ alias multiplicity.Finite.not_pow_dvd_of_multiplicity_lt := FiniteMultiplicity.not_pow_dvd_of_multiplicity_lt theorem multiplicity_pos_of_dvd (hdiv : a ∣ b) : 0 < multiplicity a b := by - refine zero_lt_iff.2 fun h => ?_ + refine Nat.pos_iff_ne_zero.2 fun h => ?_ simpa [hdiv] using FiniteMultiplicity.not_pow_dvd_of_multiplicity_lt (by by_contra! nh; simp [nh] at h) (lt_one_iff.mpr h) diff --git a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean index 4d479bb19e431..cbbe40a8f8b70 100644 --- a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean @@ -493,14 +493,15 @@ end WeightedHomogeneousComponent end AddCommMonoid -section CanonicallyOrderedAddCommMonoid +section OrderedAddCommMonoid -variable [CanonicallyOrderedAddCommMonoid M] {w : σ → M} (φ : MvPolynomial σ R) +variable [OrderedAddCommMonoid M] {w : σ → M} (φ : MvPolynomial σ R) -/-- If `M` is a `CanonicallyOrderedAddCommMonoid`, then the `weightedHomogeneousComponent` +/-- If `M` is a canonically `OrderedAddCommMonoid`, then the `weightedHomogeneousComponent` of weighted degree `0` of a polynomial is its constant coefficient. -/ @[simp] -theorem weightedHomogeneousComponent_zero [NoZeroSMulDivisors ℕ M] (hw : ∀ i : σ, w i ≠ 0) : +theorem weightedHomogeneousComponent_zero [CanonicallyOrderedAdd M] [NoZeroSMulDivisors ℕ M] + (hw : ∀ i : σ, w i ≠ 0) : weightedHomogeneousComponent w 0 φ = C (coeff 0 φ) := by classical ext1 d @@ -522,15 +523,10 @@ theorem nonTorsionWeight_of [NoZeroSMulDivisors ℕ M] (hw : ∀ i : σ, w i ≠ NonTorsionWeight w := fun _ x hnx => (smul_eq_zero_iff_left (hw x)).mp hnx -end CanonicallyOrderedAddCommMonoid - -section CanonicallyLinearOrderedMonoid - -variable [CanonicallyLinearOrderedAddCommMonoid M] {w : σ → M} (φ : MvPolynomial σ R) - /-- If `w` is a nontorsion weight function, then the finitely supported function `m : σ →₀ ℕ` has weighted degree zero if and only if `∀ x : σ, m x = 0`. -/ -theorem weightedDegree_eq_zero_iff (hw : NonTorsionWeight w) {m : σ →₀ ℕ} : +theorem weightedDegree_eq_zero_iff [CanonicallyOrderedAdd M] + (hw : NonTorsionWeight w) {m : σ →₀ ℕ} : weight w m = 0 ↔ ∀ x : σ, m x = 0 := by simp only [weight, Finsupp.linearCombination, LinearMap.toAddMonoidHom_coe, coe_lsum, LinearMap.coe_smulRight, LinearMap.id_coe, id_eq] @@ -545,6 +541,12 @@ theorem weightedDegree_eq_zero_iff (hw : NonTorsionWeight w) {m : σ →₀ ℕ} · intro hax _ simp only [hax, zero_smul] +end OrderedAddCommMonoid + +section LinearOrderedAddCommMonoid + +variable [LinearOrderedAddCommMonoid M] [CanonicallyOrderedAdd M] {w : σ → M} (φ : MvPolynomial σ R) + /-- A multivatiate polynomial is weighted homogeneous of weighted degree zero if and only if its weighted total degree is equal to zero. -/ theorem isWeightedHomogeneous_zero_iff_weightedTotalDegree_eq_zero {p : MvPolynomial σ R} : @@ -566,7 +568,7 @@ theorem weightedTotalDegree_eq_zero_iff (hw : NonTorsionWeight w) (p : MvPolynom intro _ exact weightedDegree_eq_zero_iff hw -end CanonicallyLinearOrderedMonoid +end LinearOrderedAddCommMonoid section GradedAlgebra diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index ca3df047a7bdc..cb2e3d4ea1420 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -3,6 +3,8 @@ 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, Mario Carneiro, Floris van Doorn -/ +import Mathlib.Algebra.Order.GroupWithZero.Canonical +import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Data.Fintype.BigOperators import Mathlib.Data.Fintype.Powerset import Mathlib.Data.Nat.Cast.Order.Basic @@ -14,8 +16,6 @@ import Mathlib.Order.ConditionallyCompleteLattice.Indexed import Mathlib.Order.InitialSeg import Mathlib.Order.SuccPred.CompleteLinearOrder import Mathlib.SetTheory.Cardinal.SchroederBernstein -import Mathlib.Algebra.Order.GroupWithZero.Canonical -import Mathlib.Algebra.Order.Ring.Canonical /-! # Cardinal Numbers @@ -43,7 +43,8 @@ We define cardinal numbers as a quotient of types under the equivalence relation ## Main instances -* Cardinals form a `CanonicallyOrderedCommSemiring` with the aforementioned sum and product. +* Cardinals form a `CanonicallyOrderedAdd` `OrderedCommSemiring` with the aforementioned sum and + product. * Cardinals form a `SuccOrder`. Use `Order.succ c` for the smallest cardinal greater than `c`. * The less than relation on cardinals forms a well-order. * Cardinals form a `ConditionallyCompleteLinearOrderBot`. Bounded sets for cardinals in universe @@ -632,30 +633,28 @@ instance addLeftMono : AddLeftMono Cardinal := instance addRightMono : AddRightMono Cardinal := ⟨fun _ _ _ h => add_le_add' h le_rfl⟩ -instance canonicallyOrderedCommSemiring : CanonicallyOrderedCommSemiring Cardinal.{u} := - { Cardinal.commSemiring, - Cardinal.partialOrder with - bot := 0 - bot_le := Cardinal.zero_le - add_le_add_left := fun _ _ => add_le_add_left - exists_add_of_le := fun {a b} => - inductionOn₂ a b fun α β ⟨⟨f, hf⟩⟩ => - have : α ⊕ ((range f)ᶜ : Set β) ≃ β := by - classical - exact (Equiv.sumCongr (Equiv.ofInjective f hf) (Equiv.refl _)).trans <| - Equiv.Set.sumCompl (range f) - ⟨#(↥(range f)ᶜ), mk_congr this.symm⟩ - le_self_add := fun a _ => (add_zero a).ge.trans <| add_le_add_left (Cardinal.zero_le _) _ - eq_zero_or_eq_zero_of_mul_eq_zero := fun {a b} => - inductionOn₂ a b fun α β => by - simpa only [mul_def, mk_eq_zero_iff, isEmpty_prod] using id } - -instance : CanonicallyLinearOrderedAddCommMonoid Cardinal.{u} := - { Cardinal.canonicallyOrderedCommSemiring, Cardinal.linearOrder with } +instance canonicallyOrderedAdd : CanonicallyOrderedAdd Cardinal.{u} where + exists_add_of_le {a b} := + inductionOn₂ a b fun α β ⟨⟨f, hf⟩⟩ => + have : α ⊕ ((range f)ᶜ : Set β) ≃ β := by + classical + exact (Equiv.sumCongr (Equiv.ofInjective f hf) (Equiv.refl _)).trans <| + Equiv.Set.sumCompl (range f) + ⟨#(↥(range f)ᶜ), mk_congr this.symm⟩ + le_self_add a _ := (add_zero a).ge.trans <| add_le_add_left (Cardinal.zero_le _) _ --- Computable instance to prevent a non-computable one being found via the one above -instance : CanonicallyOrderedAddCommMonoid Cardinal.{u} := - { Cardinal.canonicallyOrderedCommSemiring with } +instance orderedCommSemiring : OrderedCommSemiring Cardinal.{u} := + CanonicallyOrderedAdd.toOrderedCommSemiring + +instance : LinearOrderedAddCommMonoid Cardinal.{u} := + { Cardinal.orderedCommSemiring, Cardinal.linearOrder with } + +instance orderBot : OrderBot Cardinal.{u} := inferInstance + +instance noZeroDivisors : NoZeroDivisors Cardinal.{u} where + eq_zero_or_eq_zero_of_mul_eq_zero := fun {a b} => + inductionOn₂ a b fun α β => by + simpa only [mul_def, mk_eq_zero_iff, isEmpty_prod] using id instance : LinearOrderedCommMonoidWithZero Cardinal.{u} := { Cardinal.commSemiring, @@ -665,12 +664,12 @@ instance : LinearOrderedCommMonoidWithZero Cardinal.{u} := -- Computable instance to prevent a non-computable one being found via the one above instance : CommMonoidWithZero Cardinal.{u} := - { Cardinal.canonicallyOrderedCommSemiring with } + { Cardinal.orderedCommSemiring with } -- Porting note: new -- Computable instance to prevent a non-computable one being found via the one above instance : CommMonoid Cardinal.{u} := - { Cardinal.canonicallyOrderedCommSemiring with } + { Cardinal.orderedCommSemiring with } theorem zero_power_le (c : Cardinal.{u}) : (0 : Cardinal.{u}) ^ c ≤ 1 := by by_cases h : c = 0 diff --git a/Mathlib/Tactic/Positivity/Core.lean b/Mathlib/Tactic/Positivity/Core.lean index a56d312db10c5..7633d5763d0fc 100644 --- a/Mathlib/Tactic/Positivity/Core.lean +++ b/Mathlib/Tactic/Positivity/Core.lean @@ -213,9 +213,11 @@ def normNumPositivity (e : Q($α)) : MetaM (Strictness zα pα e) := catchNone d haveI' w : decide ($n < 0) =Q true := ⟨⟩ pure (.nonzero q(nz_of_isRat $p $w)) -/-- Attempts to prove that `e ≥ 0` using `zero_le` in a `CanonicallyOrderedAddCommMonoid`. -/ +/-- Attempts to prove that `e ≥ 0` using `zero_le` in a `CanonicallyOrderedAdd` monoid. -/ def positivityCanon (e : Q($α)) : MetaM (Strictness zα pα e) := do - let _i ← synthInstanceQ (q(CanonicallyOrderedAddCommMonoid $α) : Q(Type u)) + let _add ← synthInstanceQ (q(AddMonoid $α) : Q(Type u)) + let _le ← synthInstanceQ (q(PartialOrder $α) : Q(Type u)) + let _i ← synthInstanceQ (q(CanonicallyOrderedAdd $α) : Q(Prop)) assumeInstancesCommute pure (.nonnegative q(zero_le $e)) diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Order.lean b/Mathlib/Topology/Algebra/InfiniteSum/Order.lean index d44ae79ce1e98..c4c36e79fb1a3 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Order.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Order.lean @@ -198,10 +198,10 @@ theorem one_lt_tprod (hsum : Multipliable g) (hg : ∀ i, 1 ≤ g i) (i : ι) (h end OrderedCommGroup -section CanonicallyOrderedCommMonoid +section CanonicallyOrderedMul -variable [CanonicallyOrderedCommMonoid α] [TopologicalSpace α] [OrderClosedTopology α] - {f : ι → α} {a : α} +variable [OrderedCommMonoid α] [CanonicallyOrderedMul α] [TopologicalSpace α] + [OrderClosedTopology α] {f : ι → α} {a : α} @[to_additive] theorem le_hasProd' (hf : HasProd f a) (i : ι) : f i ≤ a := @@ -228,7 +228,7 @@ theorem isLUB_hasProd' (hf : HasProd f a) : IsLUB (Set.range fun s ↦ ∏ i ∈ classical exact isLUB_of_tendsto_atTop (Finset.prod_mono_set' f) hf -end CanonicallyOrderedCommMonoid +end CanonicallyOrderedMul section LinearOrder @@ -248,7 +248,7 @@ theorem hasProd_of_isLUB_of_one_le [LinearOrderedCommMonoid α] [TopologicalSpac tendsto_atTop_isLUB (Finset.prod_mono_set_of_one_le' h) hf @[to_additive] -theorem hasProd_of_isLUB [CanonicallyLinearOrderedCommMonoid α] [TopologicalSpace α] +theorem hasProd_of_isLUB [LinearOrderedCommMonoid α] [CanonicallyOrderedMul α] [TopologicalSpace α] [OrderTopology α] {f : ι → α} (b : α) (hf : IsLUB (Set.range fun s ↦ ∏ i ∈ s, f i) b) : HasProd f b := tendsto_atTop_isLUB (Finset.prod_mono_set' f) hf diff --git a/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean b/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean index b30ad210dc644..876bf59279937 100644 --- a/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean +++ b/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean @@ -60,7 +60,7 @@ theorem continuous_thickenedIndicatorAux {δ : ℝ} (δ_pos : 0 < δ) (E : Set theorem thickenedIndicatorAux_le_one (δ : ℝ) (E : Set α) (x : α) : thickenedIndicatorAux δ E x ≤ 1 := by - apply @tsub_le_self _ _ _ _ (1 : ℝ≥0∞) + apply tsub_le_self (α := ℝ≥0∞) theorem thickenedIndicatorAux_lt_top {δ : ℝ} {E : Set α} {x : α} : thickenedIndicatorAux δ E x < ∞ := diff --git a/scripts/noshake.json b/scripts/noshake.json index a956ff0c73f06..ef5a9e86f0813 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -474,6 +474,8 @@ "Mathlib.Algebra.BigOperators.Group.List": ["Mathlib.Data.List.ProdSigma"], "Mathlib.Algebra.Algebra.Subalgebra.Order": ["Mathlib.Algebra.Module.Submodule.Order"], + "Mathlib.Algebra.Order.Ring.Nat": + ["Mathlib.Algebra.Order.Group.Nat"], "Batteries.Tactic.OpenPrivate": ["Lean.Parser.Module"], "Batteries.Tactic.Omega.OmegaM": ["Batteries.Tactic.Omega.Int"], "Batteries.Tactic.Omega.Frontend": ["Batteries.Tactic.Omega.Logic"], From b73051c122f126bfd3e8df7c216bcf6ffae64d8c Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 16 Jan 2025 10:39:41 +0000 Subject: [PATCH 262/681] feat: split Mathlib/Algebra/Order/Ring/Unbundled/Nonneg (#20703) Motivated by the [longest pole](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/The.20long.20pole.20in.20mathlib/near/493326062). Co-authored-by: Anne C.A. Baanen --- Mathlib.lean | 4 +- .../Algebra/Order/GroupWithZero/Bounds.lean | 37 ++++++++++ .../Nonneg.lean => Nonneg/Basic.lean} | 71 +------------------ Mathlib/Algebra/Order/Nonneg/Floor.lean | 3 +- Mathlib/Algebra/Order/Nonneg/Lattice.lean | 64 +++++++++++++++++ Mathlib/Algebra/Order/Nonneg/Ring.lean | 3 +- Mathlib/Data/NNRat/Defs.lean | 3 +- Mathlib/GroupTheory/Commutator/Basic.lean | 1 + 8 files changed, 114 insertions(+), 72 deletions(-) create mode 100644 Mathlib/Algebra/Order/GroupWithZero/Bounds.lean rename Mathlib/Algebra/Order/{Ring/Unbundled/Nonneg.lean => Nonneg/Basic.lean} (69%) create mode 100644 Mathlib/Algebra/Order/Nonneg/Lattice.lean diff --git a/Mathlib.lean b/Mathlib.lean index d5225c3ad97f4..54a5940c1615a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -719,6 +719,7 @@ import Mathlib.Algebra.Order.Group.Unbundled.Basic import Mathlib.Algebra.Order.Group.Unbundled.Int import Mathlib.Algebra.Order.Group.Units import Mathlib.Algebra.Order.GroupWithZero.Action.Synonym +import Mathlib.Algebra.Order.GroupWithZero.Bounds import Mathlib.Algebra.Order.GroupWithZero.Canonical import Mathlib.Algebra.Order.GroupWithZero.Finset import Mathlib.Algebra.Order.GroupWithZero.Submonoid @@ -764,8 +765,10 @@ import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop import Mathlib.Algebra.Order.Monoid.Units import Mathlib.Algebra.Order.Monoid.WithTop import Mathlib.Algebra.Order.Monovary +import Mathlib.Algebra.Order.Nonneg.Basic import Mathlib.Algebra.Order.Nonneg.Field import Mathlib.Algebra.Order.Nonneg.Floor +import Mathlib.Algebra.Order.Nonneg.Lattice import Mathlib.Algebra.Order.Nonneg.Module import Mathlib.Algebra.Order.Nonneg.Ring import Mathlib.Algebra.Order.PartialSups @@ -792,7 +795,6 @@ import Mathlib.Algebra.Order.Ring.Rat import Mathlib.Algebra.Order.Ring.Star import Mathlib.Algebra.Order.Ring.Synonym import Mathlib.Algebra.Order.Ring.Unbundled.Basic -import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg import Mathlib.Algebra.Order.Ring.Unbundled.Rat import Mathlib.Algebra.Order.Ring.WithTop import Mathlib.Algebra.Order.Star.Basic diff --git a/Mathlib/Algebra/Order/GroupWithZero/Bounds.lean b/Mathlib/Algebra/Order/GroupWithZero/Bounds.lean new file mode 100644 index 0000000000000..a697535c76292 --- /dev/null +++ b/Mathlib/Algebra/Order/GroupWithZero/Bounds.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2025 María Inés de Frutos-Fernández . All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: María Inés de Frutos-Fernández +-/ +import Mathlib.Algebra.Order.GroupWithZero.Unbundled +import Mathlib.Order.Bounds.Basic +import Mathlib.Order.Bounds.Image + +/-! +# Lemmas about `BddAbove` +-/ + +open Set + +/-- A variant of `BddAbove.range_comp` that assumes that `f` is nonnegative and `g` is monotone on + nonnegative values. -/ +lemma BddAbove.range_comp_of_nonneg {α β γ : Type*} [Nonempty α] [Preorder β] [Zero β] [Preorder γ] + {f : α → β} {g : β → γ} (hf : BddAbove (range f)) (hf0 : 0 ≤ f) + (hg : MonotoneOn g {x : β | 0 ≤ x}) : BddAbove (range (fun x => g (f x))) := by + have hg' : BddAbove (g '' (range f)) := by + apply hg.map_bddAbove (by rintro x ⟨a, rfl⟩; exact hf0 a) + · obtain ⟨b, hb⟩ := hf + use b, hb + simp only [mem_upperBounds, mem_range, forall_exists_index, forall_apply_eq_imp_iff] at hb + exact le_trans (hf0 Classical.ofNonempty) (hb Classical.ofNonempty) + change BddAbove (range (g ∘ f)) + simpa only [Set.range_comp] using hg' + +/-- If `u v : α → β` are nonnegative and bounded above, then `u * v` is bounded above. -/ +theorem bddAbove_range_mul {α β : Type*} [Nonempty α] {u v : α → β} [Preorder β] [Zero β] [Mul β] + [PosMulMono β] [MulPosMono β] (hu : BddAbove (Set.range u)) (hu0 : 0 ≤ u) + (hv : BddAbove (Set.range v)) (hv0 : 0 ≤ v) : BddAbove (Set.range (u * v)) := + letI : Zero (β × β) := ⟨(0, 0)⟩ + BddAbove.range_comp_of_nonneg (f := fun i ↦ (u i, v i)) (g := fun x ↦ x.1 * x.2) + (bddAbove_range_prod.mpr ⟨hu, hv⟩) (fun x ↦ ⟨hu0 x, hv0 x⟩) ((monotone_fst.monotoneOn _).mul + (monotone_snd.monotoneOn _) (fun _ hx ↦ hx.1) (fun _ hx ↦ hx.2)) diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Nonneg.lean b/Mathlib/Algebra/Order/Nonneg/Basic.lean similarity index 69% rename from Mathlib/Algebra/Order/Ring/Unbundled/Nonneg.lean rename to Mathlib/Algebra/Order/Nonneg/Basic.lean index 69612ba8a75c1..31863d814ea0c 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Nonneg.lean +++ b/Mathlib/Algebra/Order/Nonneg/Basic.lean @@ -9,8 +9,6 @@ import Mathlib.Algebra.Order.ZeroLEOne import Mathlib.Algebra.Ring.Defs import Mathlib.Algebra.Ring.InjSurj import Mathlib.Data.Nat.Cast.Order.Basic -import Mathlib.Order.CompleteLatticeIntervals -import Mathlib.Order.LatticeIntervals /-! # The type of nonnegative elements @@ -32,8 +30,10 @@ equal, this often confuses the elaborator. Similar problems arise when doing cas The disadvantage is that we have to duplicate some instances about `Set.Ici` to this subtype. -/ - +assert_not_exists GeneralizedHeytingAlgebra assert_not_exists OrderedCommMonoid +-- TODO -- assert_not_exists PosMulMono +assert_not_exists mem_upperBounds open Set @@ -41,48 +41,6 @@ variable {α : Type*} namespace Nonneg -/-- This instance uses data fields from `Subtype.partialOrder` to help type-class inference. -The `Set.Ici` data fields are definitionally equal, but that requires unfolding semireducible -definitions, so type-class inference won't see this. -/ -instance orderBot [Preorder α] {a : α} : OrderBot { x : α // a ≤ x } := - { Set.Ici.orderBot with } - -theorem bot_eq [Preorder α] {a : α} : (⊥ : { x : α // a ≤ x }) = ⟨a, le_rfl⟩ := - rfl - -instance noMaxOrder [PartialOrder α] [NoMaxOrder α] {a : α} : NoMaxOrder { x : α // a ≤ x } := - show NoMaxOrder (Ici a) by infer_instance - -instance semilatticeSup [SemilatticeSup α] {a : α} : SemilatticeSup { x : α // a ≤ x } := - Set.Ici.semilatticeSup - -instance semilatticeInf [SemilatticeInf α] {a : α} : SemilatticeInf { x : α // a ≤ x } := - Set.Ici.semilatticeInf - -instance distribLattice [DistribLattice α] {a : α} : DistribLattice { x : α // a ≤ x } := - Set.Ici.distribLattice - -instance instDenselyOrdered [Preorder α] [DenselyOrdered α] {a : α} : - DenselyOrdered { x : α // a ≤ x } := - show DenselyOrdered (Ici a) from Set.instDenselyOrdered - -/-- If `sSup ∅ ≤ a` then `{x : α // a ≤ x}` is a `ConditionallyCompleteLinearOrder`. -/ -protected noncomputable abbrev conditionallyCompleteLinearOrder [ConditionallyCompleteLinearOrder α] - {a : α} : ConditionallyCompleteLinearOrder { x : α // a ≤ x } := - { @ordConnectedSubsetConditionallyCompleteLinearOrder α (Set.Ici a) _ ⟨⟨a, le_rfl⟩⟩ _ with } - -/-- If `sSup ∅ ≤ a` then `{x : α // a ≤ x}` is a `ConditionallyCompleteLinearOrderBot`. - -This instance uses data fields from `Subtype.linearOrder` to help type-class inference. -The `Set.Ici` data fields are definitionally equal, but that requires unfolding semireducible -definitions, so type-class inference won't see this. -/ -protected noncomputable abbrev conditionallyCompleteLinearOrderBot - [ConditionallyCompleteLinearOrder α] (a : α) : - ConditionallyCompleteLinearOrderBot { x : α // a ≤ x } := - { Nonneg.orderBot, Nonneg.conditionallyCompleteLinearOrder with - csSup_empty := by - rw [@subset_sSup_def α (Set.Ici a) _ _ ⟨⟨a, le_rfl⟩⟩]; simp [bot_eq] } - instance inhabited [Preorder α] {a : α} : Inhabited { x : α // a ≤ x } := ⟨⟨a, le_rfl⟩⟩ @@ -324,26 +282,3 @@ theorem mk_sub_mk [Sub α] {x y : α} (hx : 0 ≤ x) (hy : 0 ≤ y) : end LinearOrder end Nonneg - -/-- A variant of `BddAbove.range_comp` that assumes that `f` is nonnegative and `g` is monotone on - nonnegative values. -/ -lemma BddAbove.range_comp_of_nonneg {α β γ : Type*} [Nonempty α] [Preorder β] [Zero β] [Preorder γ] - {f : α → β} {g : β → γ} (hf : BddAbove (range f)) (hf0 : 0 ≤ f) - (hg : MonotoneOn g {x : β | 0 ≤ x}) : BddAbove (range (fun x => g (f x))) := by - have hg' : BddAbove (g '' (range f)) := by - apply hg.map_bddAbove (by rintro x ⟨a, rfl⟩; exact hf0 a) - · obtain ⟨b, hb⟩ := hf - use b, hb - simp only [mem_upperBounds, mem_range, forall_exists_index, forall_apply_eq_imp_iff] at hb - exact le_trans (hf0 Classical.ofNonempty) (hb Classical.ofNonempty) - change BddAbove (range (g ∘ f)) - simpa only [Set.range_comp] using hg' - -/-- If `u v : α → β` are nonnegative and bounded above, then `u * v` is bounded above. -/ -theorem bddAbove_range_mul {α β : Type*} [Nonempty α] {u v : α → β} [Preorder β] [Zero β] [Mul β] - [PosMulMono β] [MulPosMono β] (hu : BddAbove (Set.range u)) (hu0 : 0 ≤ u) - (hv : BddAbove (Set.range v)) (hv0 : 0 ≤ v) : BddAbove (Set.range (u * v)) := - letI : Zero (β × β) := ⟨(0, 0)⟩ - BddAbove.range_comp_of_nonneg (f := fun i ↦ (u i, v i)) (g := fun x ↦ x.1 * x.2) - (bddAbove_range_prod.mpr ⟨hu, hv⟩) (fun x ↦ ⟨hu0 x, hv0 x⟩) ((monotone_fst.monotoneOn _).mul - (monotone_snd.monotoneOn _) (fun _ hx ↦ hx.1) (fun _ hx ↦ hx.2)) diff --git a/Mathlib/Algebra/Order/Nonneg/Floor.lean b/Mathlib/Algebra/Order/Nonneg/Floor.lean index 1fdd9eefd1892..25cedc31a503e 100644 --- a/Mathlib/Algebra/Order/Nonneg/Floor.lean +++ b/Mathlib/Algebra/Order/Nonneg/Floor.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ import Mathlib.Algebra.Order.Floor -import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg +import Mathlib.Algebra.Order.Nonneg.Basic +import Mathlib.Algebra.Order.Nonneg.Lattice /-! # Nonnegative elements are archimedean diff --git a/Mathlib/Algebra/Order/Nonneg/Lattice.lean b/Mathlib/Algebra/Order/Nonneg/Lattice.lean new file mode 100644 index 0000000000000..18abb1fdcc127 --- /dev/null +++ b/Mathlib/Algebra/Order/Nonneg/Lattice.lean @@ -0,0 +1,64 @@ +/- +Copyright (c) 2021 Floris van Doorn. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Floris van Doorn +-/ +import Mathlib.Order.CompleteLatticeIntervals +import Mathlib.Order.LatticeIntervals + +/-! +# Lattice structures on the type of nonnegative elements + +-/ +assert_not_exists Ring +assert_not_exists OrderedCommMonoid + +open Set + +variable {α : Type*} + +namespace Nonneg + +/-- This instance uses data fields from `Subtype.partialOrder` to help type-class inference. +The `Set.Ici` data fields are definitionally equal, but that requires unfolding semireducible +definitions, so type-class inference won't see this. -/ +instance orderBot [Preorder α] {a : α} : OrderBot { x : α // a ≤ x } := + { Set.Ici.orderBot with } + +theorem bot_eq [Preorder α] {a : α} : (⊥ : { x : α // a ≤ x }) = ⟨a, le_rfl⟩ := + rfl + +instance noMaxOrder [PartialOrder α] [NoMaxOrder α] {a : α} : NoMaxOrder { x : α // a ≤ x } := + show NoMaxOrder (Ici a) by infer_instance + +instance semilatticeSup [SemilatticeSup α] {a : α} : SemilatticeSup { x : α // a ≤ x } := + Set.Ici.semilatticeSup + +instance semilatticeInf [SemilatticeInf α] {a : α} : SemilatticeInf { x : α // a ≤ x } := + Set.Ici.semilatticeInf + +instance distribLattice [DistribLattice α] {a : α} : DistribLattice { x : α // a ≤ x } := + Set.Ici.distribLattice + +instance instDenselyOrdered [Preorder α] [DenselyOrdered α] {a : α} : + DenselyOrdered { x : α // a ≤ x } := + show DenselyOrdered (Ici a) from Set.instDenselyOrdered + +/-- If `sSup ∅ ≤ a` then `{x : α // a ≤ x}` is a `ConditionallyCompleteLinearOrder`. -/ +protected noncomputable abbrev conditionallyCompleteLinearOrder [ConditionallyCompleteLinearOrder α] + {a : α} : ConditionallyCompleteLinearOrder { x : α // a ≤ x } := + { @ordConnectedSubsetConditionallyCompleteLinearOrder α (Set.Ici a) _ ⟨⟨a, le_rfl⟩⟩ _ with } + +/-- If `sSup ∅ ≤ a` then `{x : α // a ≤ x}` is a `ConditionallyCompleteLinearOrderBot`. + +This instance uses data fields from `Subtype.linearOrder` to help type-class inference. +The `Set.Ici` data fields are definitionally equal, but that requires unfolding semireducible +definitions, so type-class inference won't see this. -/ +protected noncomputable abbrev conditionallyCompleteLinearOrderBot + [ConditionallyCompleteLinearOrder α] (a : α) : + ConditionallyCompleteLinearOrderBot { x : α // a ≤ x } := + { Nonneg.orderBot, Nonneg.conditionallyCompleteLinearOrder with + csSup_empty := by + rw [@subset_sSup_def α (Set.Ici a) _ _ ⟨⟨a, le_rfl⟩⟩]; simp [bot_eq] } + +end Nonneg diff --git a/Mathlib/Algebra/Order/Nonneg/Ring.lean b/Mathlib/Algebra/Order/Nonneg/Ring.lean index 6ba3617f528dd..6c20dd04819c4 100644 --- a/Mathlib/Algebra/Order/Nonneg/Ring.lean +++ b/Mathlib/Algebra/Order/Nonneg/Ring.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ import Mathlib.Algebra.Order.GroupWithZero.Canonical -import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg +import Mathlib.Algebra.Order.Nonneg.Basic +import Mathlib.Algebra.Order.Nonneg.Lattice import Mathlib.Algebra.Order.Monoid.Unbundled.Pow import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.Ring.InjSurj diff --git a/Mathlib/Data/NNRat/Defs.lean b/Mathlib/Data/NNRat/Defs.lean index 05d7636202277..1847740ee58e0 100644 --- a/Mathlib/Data/NNRat/Defs.lean +++ b/Mathlib/Data/NNRat/Defs.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Bhavik Mehta -/ import Mathlib.Algebra.Order.Group.Unbundled.Int -import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg +import Mathlib.Algebra.Order.Nonneg.Basic import Mathlib.Algebra.Order.Ring.Unbundled.Rat import Mathlib.Algebra.Ring.Rat +import Mathlib.Order.GaloisConnection /-! # Nonnegative rationals diff --git a/Mathlib/GroupTheory/Commutator/Basic.lean b/Mathlib/GroupTheory/Commutator/Basic.lean index 38ed41f97f06e..662f43a5f5e18 100644 --- a/Mathlib/GroupTheory/Commutator/Basic.lean +++ b/Mathlib/GroupTheory/Commutator/Basic.lean @@ -5,6 +5,7 @@ Authors: Jordan Brown, Thomas Browning, Patrick Lutz -/ import Mathlib.GroupTheory.Subgroup.Centralizer import Mathlib.Tactic.Group +import Mathlib.Order.ConditionallyCompleteLattice.Basic /-! # Commutators of Subgroups From 3aacbc882ec92883af37dd7ddd54ef3f58efafa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Thu, 16 Jan 2025 10:39:42 +0000 Subject: [PATCH 263/681] style: correct `MaximalSpectrum.IsMaximal` for style conformance. (#20792) Rename `MaximalSpectrum.IsMaximal` to `MaximalSpectrum.isMaximal` and add deprecation note. --- Mathlib/RingTheory/DedekindDomain/Ideal.lean | 2 +- Mathlib/RingTheory/Spectrum/Maximal/Basic.lean | 2 +- Mathlib/RingTheory/Spectrum/Maximal/Defs.lean | 4 +++- Mathlib/RingTheory/Spectrum/Maximal/Topology.lean | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index fc03a46ef8d2b..68c9890c4641f 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -974,7 +974,7 @@ theorem associates_irreducible : Irreducible <| Associates.mk v.asIdeal := def equivMaximalSpectrum (hR : ¬IsField R) : HeightOneSpectrum R ≃ MaximalSpectrum R where toFun v := ⟨v.asIdeal, v.isPrime.isMaximal v.ne_bot⟩ invFun v := - ⟨v.asIdeal, v.IsMaximal.isPrime, Ring.ne_bot_of_isMaximal_of_not_isField v.IsMaximal hR⟩ + ⟨v.asIdeal, v.isMaximal.isPrime, Ring.ne_bot_of_isMaximal_of_not_isField v.isMaximal hR⟩ left_inv := fun ⟨_, _, _⟩ => rfl right_inv := fun ⟨_, _⟩ => rfl diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean index a4d369561f3f8..608db0b4cbfb6 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean @@ -29,7 +29,7 @@ instance [Nontrivial R] : Nonempty <| MaximalSpectrum R := /-- The natural inclusion from the maximal spectrum to the prime spectrum. -/ def toPrimeSpectrum (x : MaximalSpectrum R) : PrimeSpectrum R := - ⟨x.asIdeal, x.IsMaximal.isPrime⟩ + ⟨x.asIdeal, x.isMaximal.isPrime⟩ theorem toPrimeSpectrum_injective : (@toPrimeSpectrum R _).Injective := fun ⟨_, _⟩ ⟨_, _⟩ h => by simpa only [MaximalSpectrum.mk.injEq] using PrimeSpectrum.ext_iff.mp h diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean b/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean index 5caa1d1bd0a23..ab8109fe0112f 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean @@ -22,6 +22,8 @@ maximal ideals of `R`. -/ @[ext] structure MaximalSpectrum (R : Type*) [CommSemiring R] where asIdeal : Ideal R - IsMaximal : asIdeal.IsMaximal + isMaximal : asIdeal.IsMaximal + +@[deprecated (since := "2025-01-16")] alias MaximalSpectrum.IsMaximal := MaximalSpectrum.isMaximal attribute [instance] MaximalSpectrum.IsMaximal diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Topology.lean b/Mathlib/RingTheory/Spectrum/Maximal/Topology.lean index 56fc46274a3f4..9846b9ba92903 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Topology.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Topology.lean @@ -32,7 +32,7 @@ theorem toPrimeSpectrum_range : Set.range (@toPrimeSpectrum R _) = { x | IsClosed ({x} : Set <| PrimeSpectrum R) } := by simp only [isClosed_singleton_iff_isMaximal] ext ⟨x, _⟩ - exact ⟨fun ⟨y, hy⟩ => hy ▸ y.IsMaximal, fun hx => ⟨⟨x, hx⟩, rfl⟩⟩ + exact ⟨fun ⟨y, hy⟩ => hy ▸ y.isMaximal, fun hx => ⟨⟨x, hx⟩, rfl⟩⟩ /-- The Zariski topology on the maximal spectrum of a commutative ring is defined as the subspace topology induced by the natural inclusion into the prime spectrum. -/ @@ -41,7 +41,7 @@ instance zariskiTopology : TopologicalSpace <| MaximalSpectrum R := instance : T1Space <| MaximalSpectrum R := ⟨fun x => isClosed_induced_iff.mpr - ⟨{toPrimeSpectrum x}, (isClosed_singleton_iff_isMaximal _).mpr x.IsMaximal, by + ⟨{toPrimeSpectrum x}, (isClosed_singleton_iff_isMaximal _).mpr x.isMaximal, by simpa only [← image_singleton] using preimage_image_eq {x} toPrimeSpectrum_injective⟩⟩ theorem toPrimeSpectrum_continuous : Continuous <| @toPrimeSpectrum R _ := From 50b66b2ece281614847391cd85f5bc93c5ad37e2 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 16 Jan 2025 11:16:49 +0000 Subject: [PATCH 264/681] chore: survey of simp porting notes (#20787) I've removed many porting notes that had resulted from the `simpNF` linter. I've left in place all porting notes about removing `@[simp]` but where the proof is `rfl` or `Iff.rfl`. --- Mathlib/Algebra/Algebra/Equiv.lean | 4 ++-- Mathlib/Algebra/Algebra/Hom.lean | 2 -- Mathlib/Algebra/Algebra/Operations.lean | 3 +-- Mathlib/Algebra/Algebra/Subalgebra/Basic.lean | 2 -- Mathlib/Algebra/Category/Grp/Preadditive.lean | 10 ---------- .../Algebra/Category/ModuleCat/Adjunctions.lean | 3 --- Mathlib/Algebra/Group/Subgroup/Finite.lean | 5 ++--- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 9 +++------ Mathlib/Algebra/Order/Interval/Basic.lean | 4 ++-- Mathlib/Algebra/Polynomial/AlgebraMap.lean | 5 ----- Mathlib/Algebra/Quaternion.lean | 5 ++--- Mathlib/Algebra/Star/Subalgebra.lean | 3 +-- Mathlib/Analysis/InnerProductSpace/Basic.lean | 1 - .../Limits/Shapes/BinaryProducts.lean | 8 +------- Mathlib/CategoryTheory/Preadditive/Basic.lean | 11 +++++------ Mathlib/Data/Complex/Exponential.lean | 1 - Mathlib/Data/DFinsupp/BigOperators.lean | 2 +- Mathlib/Data/ENat/Basic.lean | 6 ------ Mathlib/Data/Finset/MulAntidiagonal.lean | 4 +--- Mathlib/Data/Finset/Powerset.lean | 8 ++------ Mathlib/Data/Finsupp/Basic.lean | 4 +--- Mathlib/Data/Finsupp/Single.lean | 3 +-- Mathlib/Data/Fintype/Basic.lean | 10 ++-------- Mathlib/Data/Int/Interval.lean | 14 +++++--------- Mathlib/Data/List/Rotate.lean | 8 ++------ Mathlib/Data/Multiset/FinsetOps.lean | 6 ++---- Mathlib/Data/Multiset/Pi.lean | 2 +- Mathlib/Data/Nat/Defs.lean | 1 - Mathlib/Data/PNat/Interval.lean | 5 ----- Mathlib/Data/Seq/Seq.lean | 4 ++-- .../Manifold/Algebra/LeftInvariantDerivation.lean | 15 +++++---------- Mathlib/GroupTheory/Congruence/Defs.lean | 4 +--- Mathlib/GroupTheory/GroupAction/Quotient.lean | 6 ++---- .../LinearAlgebra/Dimension/Constructions.lean | 4 +--- Mathlib/Logic/Denumerable.lean | 1 - Mathlib/Logic/Equiv/PartialEquiv.lean | 2 -- Mathlib/Order/BoundedOrder/Lattice.lean | 8 -------- Mathlib/RingTheory/Polynomial/Basic.lean | 14 +++++--------- Mathlib/SetTheory/Cardinal/Basic.lean | 1 - Mathlib/SetTheory/Game/Basic.lean | 4 +++- Mathlib/SetTheory/Game/Birthday.lean | 2 -- Mathlib/SetTheory/Surreal/Dyadic.lean | 1 - Mathlib/Tactic/NormNum/GCD.lean | 2 +- Mathlib/Topology/Algebra/InfiniteSum/Basic.lean | 1 - Mathlib/Topology/Algebra/Module/Equiv.lean | 8 +------- Mathlib/Topology/Category/TopCat/Basic.lean | 1 - Mathlib/Topology/Category/UniformSpace.lean | 2 -- Mathlib/Topology/Compactification/OnePoint.lean | 1 - Mathlib/Topology/Constructions.lean | 2 -- Mathlib/Topology/FiberBundle/Basic.lean | 1 - Mathlib/Topology/Gluing.lean | 5 +---- Mathlib/Topology/LocalAtTarget.lean | 9 +++------ Mathlib/Topology/MetricSpace/Dilation.lean | 1 - Mathlib/Topology/MetricSpace/GromovHausdorff.lean | 3 +-- Mathlib/Topology/Sets/Compacts.lean | 2 -- Mathlib/Topology/Sets/Opens.lean | 2 -- Mathlib/Topology/Sheaves/LocalPredicate.lean | 2 -- Mathlib/Topology/Sheaves/Presheaf.lean | 4 ---- Mathlib/Topology/Sheaves/Skyscraper.lean | 6 +++--- Mathlib/Topology/UniformSpace/Equiv.lean | 2 -- Mathlib/Topology/UniformSpace/OfCompactT2.lean | 3 +-- 61 files changed, 67 insertions(+), 205 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index 6d699d6775650..cd52e4afdabda 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -595,7 +595,7 @@ end OfLinearEquiv section OfRingEquiv /-- Promotes a linear `RingEquiv` to an `AlgEquiv`. -/ -@[simps apply symm_apply toEquiv] -- Porting note: don't want redundant `toEquiv_symm_apply` simps +@[simps apply symm_apply toEquiv] def ofRingEquiv {f : A₁ ≃+* A₂} (hf : ∀ x, f (algebraMap R A₁ x) = algebraMap R A₂ x) : A₁ ≃ₐ[R] A₂ := { f with @@ -757,7 +757,7 @@ variable [Group G] [MulSemiringAction G A] [SMulCommClass G R A] This is a stronger version of `MulSemiringAction.toRingEquiv` and `DistribMulAction.toLinearEquiv`. -/ -@[simps! apply symm_apply toEquiv] -- Porting note: don't want redundant simps lemma `toEquiv_symm` +@[simps! apply symm_apply toEquiv] def toAlgEquiv (g : G) : A ≃ₐ[R] A := { MulSemiringAction.toRingEquiv _ _ g, MulSemiringAction.toAlgHom R A g with } diff --git a/Mathlib/Algebra/Algebra/Hom.lean b/Mathlib/Algebra/Algebra/Hom.lean index d5e421d9d1b06..b813755c63742 100644 --- a/Mathlib/Algebra/Algebra/Hom.lean +++ b/Mathlib/Algebra/Algebra/Hom.lean @@ -127,8 +127,6 @@ def toAddMonoidHom' (f : A →ₐ[R] B) : A →+ B := (f : A →+* B) instance coeOutAddMonoidHom : CoeOut (A →ₐ[R] B) (A →+ B) := ⟨AlgHom.toAddMonoidHom'⟩ --- Porting note: Lean 3: `@[simp, norm_cast] coe_mk` --- Lean 4: `@[simp] coe_mk` & `@[norm_cast] coe_mks` @[simp] theorem coe_mk {f : A →+* B} (h) : ((⟨f, h⟩ : A →ₐ[R] B) : A → B) = f := rfl diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index a907db6ce7734..af762e1ce291b 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -92,8 +92,7 @@ theorem one_eq_span_one_set : (1 : Submodule R A) = span R 1 := @[simp] theorem one_le {P : Submodule R A} : (1 : Submodule R A) ≤ P ↔ (1 : A) ∈ P := by - -- Porting note: simpa no longer closes refl goals, so added `SetLike.mem_coe` - simp only [one_eq_span, span_le, Set.singleton_subset_iff, SetLike.mem_coe] + simp [one_eq_span] variable {M : Type*} [AddCommMonoid M] [Module R M] [Module A M] [IsScalarTower R A M] diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index 9b993db3f4eba..15b381c605224 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -468,8 +468,6 @@ def toSubalgebra (p : Submodule R A) (h_one : (1 : A) ∈ p) theorem mem_toSubalgebra {p : Submodule R A} {h_one h_mul} {x} : x ∈ p.toSubalgebra h_one h_mul ↔ x ∈ p := Iff.rfl --- Porting note: changed statement to reflect new structures --- @[simp] -- Porting note: as a result, it is no longer a great simp lemma theorem toSubalgebra_mk (s : Submodule R A) (h1 hmul) : s.toSubalgebra h1 hmul = Subalgebra.mk ⟨⟨⟨s, @hmul⟩, h1⟩, s.add_mem, s.zero_mem⟩ diff --git a/Mathlib/Algebra/Category/Grp/Preadditive.lean b/Mathlib/Algebra/Category/Grp/Preadditive.lean index c1608b313909a..229f324800fe3 100644 --- a/Mathlib/Algebra/Category/Grp/Preadditive.lean +++ b/Mathlib/Algebra/Category/Grp/Preadditive.lean @@ -23,16 +23,6 @@ instance (P Q : AddCommGrp) : AddCommGroup (P ⟶ Q) := @[simp] lemma hom_add_apply {P Q : AddCommGrp} (f g : P ⟶ Q) (x : P) : (f + g) x = f x + g x := rfl -section - --- Porting note: the simp attribute was locally deactivated here, --- otherwise Lean would try to infer `Preadditive AddCommGrp` --- in order to prove the axioms `add_comp` and `comp_add` in the --- next instance declaration -attribute [-simp] Preadditive.add_comp Preadditive.comp_add - instance : Preadditive AddCommGrp where -end - end AddCommGrp diff --git a/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean b/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean index 41760fe6fdefd..dbbc854bbc197 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean @@ -248,9 +248,6 @@ namespace Free section --- Porting note: removed local reducible attribute for categoryFree, adjusted dsimp invocations --- accordingly - instance : Preadditive (Free R C) where homGroup _ _ := Finsupp.instAddCommGroup add_comp X Y Z f f' g := by diff --git a/Mathlib/Algebra/Group/Subgroup/Finite.lean b/Mathlib/Algebra/Group/Subgroup/Finite.lean index 47f813cda8580..c5f14ed4bd10a 100644 --- a/Mathlib/Algebra/Group/Subgroup/Finite.lean +++ b/Mathlib/Algebra/Group/Subgroup/Finite.lean @@ -96,9 +96,8 @@ instance fintypeBot : Fintype (⊥ : Subgroup G) := rintro ⟨x, ⟨hx⟩⟩ exact Finset.mem_singleton_self _⟩ -@[to_additive] -- Porting note: removed `simp` because `simpNF` says it can prove it. -theorem card_bot : Nat.card (⊥ : Subgroup G) = 1 := - Nat.card_unique +@[to_additive] +theorem card_bot : Nat.card (⊥ : Subgroup G) = 1 := by simp @[to_additive] theorem card_top : Nat.card (⊤ : Subgroup G) = Nat.card G := diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index e75be2e4ec643..337f590109744 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -98,9 +98,9 @@ section variable [Semiring k] [NonUnitalNonAssocSemiring R] --- Porting note: `reducible` cannot be `local`, so we replace some definitions and theorems with --- new ones which have new types. - +-- TODO: This definition is very leaky, and we later have frequent problems conflating the two +-- versions of `single`. Perhaps someone wants to try making this a `def` rather than an `abbrev`? +-- In Mathlib 3 this was locally reducible. abbrev single (a : G) (b : k) : MonoidAlgebra k G := Finsupp.single a b theorem single_zero (a : G) : (single a 0 : MonoidAlgebra k G) = 0 := Finsupp.single_zero a @@ -807,9 +807,6 @@ protected noncomputable def opRingEquiv [Monoid G] : rw [MulOpposite.unop_mul (α := MonoidAlgebra k G), unop_op, unop_op, single_mul_single] simp } --- @[simp] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/10618): simp can prove this. --- More specifically, the LHS simplifies to `Finsupp.single`, which implies there's some --- defeq abuse going on. theorem opRingEquiv_single [Monoid G] (r : k) (x : G) : MonoidAlgebra.opRingEquiv (op (single x r)) = single (op x) (op r) := by simp diff --git a/Mathlib/Algebra/Order/Interval/Basic.lean b/Mathlib/Algebra/Order/Interval/Basic.lean index a8d682494ed1f..7b3bdacd679da 100644 --- a/Mathlib/Algebra/Order/Interval/Basic.lean +++ b/Mathlib/Algebra/Order/Interval/Basic.lean @@ -166,7 +166,7 @@ theorem bot_mul : ⊥ * t = ⊥ := theorem mul_bot : s * ⊥ = ⊥ := Option.map₂_none_right _ _ --- Porting note: simp can prove `add_bot` +-- simp can already prove `add_bot` attribute [simp] mul_bot end Interval @@ -247,7 +247,7 @@ theorem coe_pow_interval [OrderedCommMonoid α] (s : NonemptyInterval α) (n : ↑(s ^ n) = (s : Interval α) ^ n := map_pow (⟨⟨(↑), coe_one_interval⟩, coe_mul_interval⟩ : NonemptyInterval α →* Interval α) _ _ --- Porting note: simp can prove `coe_nsmul_interval` +-- simp can already prove `coe_nsmul_interval` attribute [simp] coe_pow_interval end NonemptyInterval diff --git a/Mathlib/Algebra/Polynomial/AlgebraMap.lean b/Mathlib/Algebra/Polynomial/AlgebraMap.lean index eeb486b820ed0..40e975a43fbfe 100644 --- a/Mathlib/Algebra/Polynomial/AlgebraMap.lean +++ b/Mathlib/Algebra/Polynomial/AlgebraMap.lean @@ -240,7 +240,6 @@ theorem algHom_ext {f g : R[X] →ₐ[R] B} (hX : f X = g X) : theorem aeval_def (p : R[X]) : aeval x p = eval₂ (algebraMap R A) x p := rfl --- Porting note: removed `@[simp]` because `simp` can prove this theorem aeval_zero : aeval x (0 : R[X]) = 0 := map_zero (aeval x) @@ -256,19 +255,15 @@ theorem aeval_C (r : R) : aeval x (C r) = algebraMap R A r := theorem aeval_monomial {n : ℕ} {r : R} : aeval x (monomial n r) = algebraMap _ _ r * x ^ n := eval₂_monomial _ _ --- Porting note: removed `@[simp]` because `simp` can prove this theorem aeval_X_pow {n : ℕ} : aeval x ((X : R[X]) ^ n) = x ^ n := eval₂_X_pow _ _ --- Porting note: removed `@[simp]` because `simp` can prove this theorem aeval_add : aeval x (p + q) = aeval x p + aeval x q := map_add _ _ _ --- Porting note: removed `@[simp]` because `simp` can prove this theorem aeval_one : aeval x (1 : R[X]) = 1 := map_one _ --- Porting note: removed `@[simp]` because `simp` can prove this theorem aeval_natCast (n : ℕ) : aeval x (n : R[X]) = n := map_natCast _ _ diff --git a/Mathlib/Algebra/Quaternion.lean b/Mathlib/Algebra/Quaternion.lean index 94837ea0cd371..fc5bcda77af79 100644 --- a/Mathlib/Algebra/Quaternion.lean +++ b/Mathlib/Algebra/Quaternion.lean @@ -148,7 +148,8 @@ theorem coe_injective : Function.Injective (coe : R → ℍ[R,c₁,c₂]) := fun theorem coe_inj {x y : R} : (x : ℍ[R,c₁,c₂]) = y ↔ x = y := coe_injective.eq_iff --- Porting note: removed `simps`, added simp lemmas manually. Should adjust `simps` to name properly +-- Porting note: removed `simps`, added simp lemmas manually. +-- Should adjust `simps` to name properly, i.e. as `zero_re` rather than `instZero_zero_re`. instance : Zero ℍ[R,c₁,c₂] := ⟨⟨0, 0, 0, 0⟩⟩ @[simp] theorem zero_re : (0 : ℍ[R,c₁,c₂]).re = 0 := rfl @@ -1349,7 +1350,6 @@ variable (R : Type*) [One R] [Neg R] theorem mk_quaternion : #(ℍ[R]) = #R ^ 4 := mk_quaternionAlgebra _ _ ---@[simp] Porting note: LHS can be simplified to `#R^4` theorem mk_quaternion_of_infinite [Infinite R] : #(ℍ[R]) = #R := mk_quaternionAlgebra_of_infinite _ _ @@ -1357,7 +1357,6 @@ theorem mk_quaternion_of_infinite [Infinite R] : #(ℍ[R]) = #R := theorem mk_univ_quaternion : #(Set.univ : Set ℍ[R]) = #R ^ 4 := mk_univ_quaternionAlgebra _ _ ---@[simp] Porting note: LHS can be simplified to `#R^4` theorem mk_univ_quaternion_of_infinite [Infinite R] : #(Set.univ : Set ℍ[R]) = #R := mk_univ_quaternionAlgebra_of_infinite _ _ diff --git a/Mathlib/Algebra/Star/Subalgebra.lean b/Mathlib/Algebra/Star/Subalgebra.lean index 815b95c21f2f4..e72e7f1c46f8a 100644 --- a/Mathlib/Algebra/Star/Subalgebra.lean +++ b/Mathlib/Algebra/Star/Subalgebra.lean @@ -328,9 +328,8 @@ instance involutiveStar : InvolutiveStar (Subalgebra R A) where theorem mem_star_iff (S : Subalgebra R A) (x : A) : x ∈ star S ↔ star x ∈ S := Iff.rfl --- Porting note: removed `@[simp]` tag because `simp` can prove this theorem star_mem_star_iff (S : Subalgebra R A) (x : A) : star x ∈ star S ↔ x ∈ S := by - simp only [mem_star_iff, star_star] + simp @[simp] theorem coe_star (S : Subalgebra R A) : ((star S : Subalgebra R A) : Set A) = star (S : Set A) := diff --git a/Mathlib/Analysis/InnerProductSpace/Basic.lean b/Mathlib/Analysis/InnerProductSpace/Basic.lean index 4ec4b09eb713c..a7b1ad9c52e66 100644 --- a/Mathlib/Analysis/InnerProductSpace/Basic.lean +++ b/Mathlib/Analysis/InnerProductSpace/Basic.lean @@ -216,7 +216,6 @@ theorem inner_neg_right (x y : E) : ⟪x, -y⟫ = -⟪x, y⟫ := by theorem inner_neg_neg (x y : E) : ⟪-x, -y⟫ = ⟪x, y⟫ := by simp --- Porting note: removed `simp` because it can prove it using `inner_conj_symm` theorem inner_self_conj (x : E) : ⟪x, x⟫† = ⟪x, x⟫ := inner_conj_symm _ _ theorem inner_sub_left (x y z : E) : ⟪x - y, z⟫ = ⟪x, z⟫ - ⟪y, z⟫ := by diff --git a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean index 511615f4ab4ea..5f3c1866a623d 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean @@ -728,17 +728,11 @@ end ProdLemmas noncomputable section CoprodLemmas --- @[reassoc (attr := simp)] -@[simp] -- Porting note: removing reassoc tag since result is not hygienic (two h's) +@[reassoc, simp] theorem coprod.desc_comp {V W X Y : C} [HasBinaryCoproduct X Y] (f : V ⟶ W) (g : X ⟶ V) (h : Y ⟶ V) : coprod.desc g h ≫ f = coprod.desc (g ≫ f) (h ≫ f) := by ext <;> simp --- Porting note: hand generated reassoc here. Simp can prove it -theorem coprod.desc_comp_assoc {C : Type u} [Category C] {V W X Y : C} - [HasBinaryCoproduct X Y] (f : V ⟶ W) (g : X ⟶ V) (h : Y ⟶ V) {Z : C} (l : W ⟶ Z) : - coprod.desc g h ≫ f ≫ l = coprod.desc (g ≫ f) (h ≫ f) ≫ l := by simp - theorem coprod.diag_comp {X Y : C} [HasBinaryCoproduct X X] (f : X ⟶ Y) : codiag X ≫ f = coprod.desc f f := by simp diff --git a/Mathlib/CategoryTheory/Preadditive/Basic.lean b/Mathlib/CategoryTheory/Preadditive/Basic.lean index 576d91e0c552f..dd3cf19b9e4d4 100644 --- a/Mathlib/CategoryTheory/Preadditive/Basic.lean +++ b/Mathlib/CategoryTheory/Preadditive/Basic.lean @@ -65,12 +65,11 @@ attribute [inherit_doc Preadditive] Preadditive.homGroup Preadditive.add_comp Pr attribute [instance] Preadditive.homGroup --- Porting note: simp can prove reassoc version +-- simp can already prove reassoc version attribute [reassoc, simp] Preadditive.add_comp attribute [reassoc] Preadditive.comp_add --- (the linter doesn't like `simp` on this lemma) attribute [simp] Preadditive.comp_add end CategoryTheory @@ -124,22 +123,22 @@ def compHom : (P ⟶ Q) →+ (Q ⟶ R) →+ (P ⟶ R) := AddMonoidHom.mk' (fun f => leftComp _ f) fun f₁ f₂ => AddMonoidHom.ext fun g => (rightComp _ g).map_add f₁ f₂ --- Porting note: simp can prove the reassoc version +-- simp can prove the reassoc version @[reassoc, simp] theorem sub_comp : (f - f') ≫ g = f ≫ g - f' ≫ g := map_sub (rightComp P g) f f' --- The redundant simp lemma linter says that simp can prove the reassoc version of this lemma. +-- simp can prove the reassoc version @[reassoc, simp] theorem comp_sub : f ≫ (g - g') = f ≫ g - f ≫ g' := map_sub (leftComp R f) g g' --- Porting note: simp can prove the reassoc version +-- simp can prove the reassoc version @[reassoc, simp] theorem neg_comp : (-f) ≫ g = -f ≫ g := map_neg (rightComp P g) f --- The redundant simp lemma linter says that simp can prove the reassoc version of this lemma. +-- simp can prove the reassoc version @[reassoc, simp] theorem comp_neg : f ≫ (-g) = -f ≫ g := map_neg (leftComp R f) g diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index 22be41cb64513..eb7b8802a1a40 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -47,7 +47,6 @@ def exp' (z : ℂ) : CauSeq ℂ Complex.abs := ⟨fun n => ∑ m ∈ range n, z ^ m / m.factorial, isCauSeq_exp z⟩ /-- The complex exponential function, defined via its Taylor series -/ --- Porting note: removed `irreducible` attribute, so I can prove things @[pp_nodot] def exp (z : ℂ) : ℂ := CauSeq.lim (exp' z) diff --git a/Mathlib/Data/DFinsupp/BigOperators.lean b/Mathlib/Data/DFinsupp/BigOperators.lean index 6232e6275e3f1..20adad039c4ac 100644 --- a/Mathlib/Data/DFinsupp/BigOperators.lean +++ b/Mathlib/Data/DFinsupp/BigOperators.lean @@ -307,7 +307,7 @@ def liftAddHom [∀ i, AddZeroClass (β i)] [AddCommMonoid γ] : -- This applies to roughly the remainder of the file. /-- The `DFinsupp` version of `Finsupp.liftAddHom_singleAddHom`,-/ -@[simp, nolint simpNF] -- Porting note: linter claims that simp can prove this, but it can not +@[simp, nolint simpNF] -- simpNF correctly complains that the LHS simplifies already theorem liftAddHom_singleAddHom [∀ i, AddCommMonoid (β i)] : liftAddHom (β := β) (singleAddHom β) = AddMonoidHom.id (Π₀ i, β i) := (liftAddHom (β := β)).toEquiv.apply_eq_iff_eq_symm_apply.2 rfl diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index faee31c8187a7..24f664b0250d9 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -66,18 +66,12 @@ theorem coe_inj {a b : ℕ} : (a : ℕ∞) = b ↔ a = b := WithTop.coe_inj 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 := rfl --- Porting note: `simp` and `norm_cast` can prove it ---@[simp, norm_cast] theorem coe_one : ((1 : ℕ) : ℕ∞) = 1 := rfl --- Porting note: `simp` and `norm_cast` can prove it ---@[simp, norm_cast] theorem coe_add (m n : ℕ) : ↑(m + n) = (m + n : ℕ∞) := rfl diff --git a/Mathlib/Data/Finset/MulAntidiagonal.lean b/Mathlib/Data/Finset/MulAntidiagonal.lean index 534b98c618c6b..578db83e70c6f 100644 --- a/Mathlib/Data/Finset/MulAntidiagonal.lean +++ b/Mathlib/Data/Finset/MulAntidiagonal.lean @@ -72,12 +72,10 @@ theorem mulAntidiagonal_mono_right (h : u ⊆ t) : mulAntidiagonal hs hu a ⊆ mulAntidiagonal hs ht a := Set.Finite.toFinset_mono <| Set.mulAntidiagonal_mono_right h --- Porting note: removed `(attr := simp)`. simp can prove this. @[to_additive] theorem swap_mem_mulAntidiagonal : x.swap ∈ Finset.mulAntidiagonal hs ht a ↔ x ∈ Finset.mulAntidiagonal ht hs a := by - simp only [mem_mulAntidiagonal, Prod.fst_swap, Prod.snd_swap, Set.swap_mem_mulAntidiagonal_aux, - Set.mem_mulAntidiagonal] + simp @[to_additive] theorem support_mulAntidiagonal_subset_mul : { a | (mulAntidiagonal hs ht a).Nonempty } ⊆ s * t := diff --git a/Mathlib/Data/Finset/Powerset.lean b/Mathlib/Data/Finset/Powerset.lean index 3989b2e6331c9..dc12dc7eccee3 100644 --- a/Mathlib/Data/Finset/Powerset.lean +++ b/Mathlib/Data/Finset/Powerset.lean @@ -39,13 +39,9 @@ theorem coe_powerset (s : Finset α) : ext simp --- Porting note: remove @[simp], simp can prove it -theorem empty_mem_powerset (s : Finset α) : ∅ ∈ powerset s := - mem_powerset.2 (empty_subset _) +theorem empty_mem_powerset (s : Finset α) : ∅ ∈ powerset s := by simp --- Porting note: remove @[simp], simp can prove it -theorem mem_powerset_self (s : Finset α) : s ∈ powerset s := - mem_powerset.2 Subset.rfl +theorem mem_powerset_self (s : Finset α) : s ∈ powerset s := by simp @[aesop safe apply (rule_sets := [finsetNonempty])] theorem powerset_nonempty (s : Finset α) : s.powerset.Nonempty := diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index d7cfe97aeea59..1ce490ed52759 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -1328,10 +1328,8 @@ theorem mapDomain_smul {_ : Monoid R} [AddCommMonoid M] [DistribMulAction R M] { (v : α →₀ M) : mapDomain f (b • v) = b • mapDomain f v := mapDomain_mapRange _ _ _ _ (smul_add b) --- Porting note: removed `simp` because `simpNF` can prove it. theorem smul_single' {_ : Semiring R} (c : R) (a : α) (b : R) : - c • Finsupp.single a b = Finsupp.single a (c * b) := - smul_single _ _ _ + c • Finsupp.single a b = Finsupp.single a (c * b) := by simp theorem smul_single_one [Semiring R] (a : α) (b : R) : b • single a (1 : R) = single a b := by rw [smul_single, smul_eq_mul, mul_one] diff --git a/Mathlib/Data/Finsupp/Single.lean b/Mathlib/Data/Finsupp/Single.lean index 48342b59601d3..c70ecd66b9325 100644 --- a/Mathlib/Data/Finsupp/Single.lean +++ b/Mathlib/Data/Finsupp/Single.lean @@ -403,9 +403,8 @@ theorem erase_of_not_mem_support {f : α →₀ M} {a} (haf : a ∉ f.support) : · rwa [hab, erase_same, eq_comm, ← not_mem_support_iff] · rw [erase_ne hab] -@[simp, nolint simpNF] -- Porting note: simpNF linter claims simp can prove this, it can not theorem erase_zero (a : α) : erase a (0 : α →₀ M) = 0 := by - classical rw [← support_eq_empty, support_erase, support_zero, erase_empty] + simp theorem erase_eq_update_zero (f : α →₀ M) (a : α) : f.erase a = update f a 0 := letI := Classical.decEq α diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index 88ef9e29bbfa2..ff4691dc54789 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -72,9 +72,7 @@ def univ : Finset α := theorem mem_univ (x : α) : x ∈ (univ : Finset α) := Fintype.complete x --- Porting note: removing @[simp], simp can prove it -theorem mem_univ_val : ∀ x, x ∈ (univ : Finset α).1 := - mem_univ +theorem mem_univ_val : ∀ x, x ∈ (univ : Finset α).1 := by simp theorem eq_univ_iff_forall : s = univ ↔ ∀ x, x ∈ s := by simp [Finset.ext_iff] @@ -733,9 +731,8 @@ theorem toFinset_setOf [Fintype α] (p : α → Prop) [DecidablePred p] [Fintype ext simp ---@[simp] Porting note: removing simp, simp can prove it theorem toFinset_ssubset_univ [Fintype α] {s : Set α} [Fintype s] : - s.toFinset ⊂ Finset.univ ↔ s ⊂ univ := by rw [← coe_ssubset, coe_toFinset, coe_univ] + s.toFinset ⊂ Finset.univ ↔ s ⊂ univ := by simp @[simp] theorem toFinset_image [DecidableEq β] (f : α → β) (s : Set α) [Fintype s] [Fintype (f '' s)] : @@ -857,11 +854,9 @@ since that relies on a subsingleton elimination for `Unique`. -/ instance Fintype.subtypeEq' (y : α) : Fintype { x // y = x } := Fintype.subtype {y} (by simp [eq_comm]) --- Porting note: removing @[simp], simp can prove it theorem Fintype.univ_empty : @univ Empty _ = ∅ := rfl ---@[simp] Porting note: removing simp, simp can prove it theorem Fintype.univ_pempty : @univ PEmpty _ = ∅ := rfl @@ -874,7 +869,6 @@ theorem Fintype.univ_unit : @univ Unit _ = {()} := instance PUnit.fintype : Fintype PUnit := Fintype.ofSubsingleton PUnit.unit ---@[simp] Porting note: removing simp, simp can prove it theorem Fintype.univ_punit : @univ PUnit _ = {PUnit.unit} := rfl diff --git a/Mathlib/Data/Int/Interval.lean b/Mathlib/Data/Int/Interval.lean index cd94ea340d1c5..37d0002e0603d 100644 --- a/Mathlib/Data/Int/Interval.lean +++ b/Mathlib/Data/Int/Interval.lean @@ -134,24 +134,20 @@ theorem Icc_eq_pair : Finset.Icc a (a + 1) = {a, a + 1} := by simp omega --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it theorem card_fintype_Icc : Fintype.card (Set.Icc a b) = (b + 1 - a).toNat := by - rw [← card_Icc, Fintype.card_ofFinset] + simp --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it theorem card_fintype_Ico : Fintype.card (Set.Ico a b) = (b - a).toNat := by - rw [← card_Ico, Fintype.card_ofFinset] + simp --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it theorem card_fintype_Ioc : Fintype.card (Set.Ioc a b) = (b - a).toNat := by - rw [← card_Ioc, Fintype.card_ofFinset] + simp --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it theorem card_fintype_Ioo : Fintype.card (Set.Ioo a b) = (b - a - 1).toNat := by - rw [← card_Ioo, Fintype.card_ofFinset] + simp theorem card_fintype_uIcc : Fintype.card (Set.uIcc a b) = (b - a).natAbs + 1 := by - rw [← card_uIcc, Fintype.card_ofFinset] + simp theorem card_fintype_Icc_of_le (h : a ≤ b + 1) : (Fintype.card (Set.Icc a b) : ℤ) = b + 1 - a := by rw [card_fintype_Icc, toNat_sub_of_le h] diff --git a/Mathlib/Data/List/Rotate.lean b/Mathlib/Data/List/Rotate.lean index 1e658d0fb7491..3e6a9a0204004 100644 --- a/Mathlib/Data/List/Rotate.lean +++ b/Mathlib/Data/List/Rotate.lean @@ -39,8 +39,7 @@ theorem rotate_nil (n : ℕ) : ([] : List α).rotate n = [] := by simp [rotate] @[simp] theorem rotate_zero (l : List α) : l.rotate 0 = l := by simp [rotate] --- Porting note: removing simp, simp can prove it -theorem rotate'_nil (n : ℕ) : ([] : List α).rotate' n = [] := by cases n <;> rfl +theorem rotate'_nil (n : ℕ) : ([] : List α).rotate' n = [] := by simp @[simp] theorem rotate'_zero (l : List α) : l.rotate' 0 = l := by cases l <;> rfl @@ -100,7 +99,7 @@ theorem rotate_eq_rotate' (l : List α) (n : ℕ) : l.rotate n = l.rotate' n := rotate'_eq_drop_append_take (le_of_lt (Nat.mod_lt _ (Nat.pos_of_ne_zero h)))] simp [rotate] -theorem rotate_cons_succ (l : List α) (a : α) (n : ℕ) : +@[simp] theorem rotate_cons_succ (l : List α) (a : α) (n : ℕ) : (a :: l : List α).rotate (n + 1) = (l ++ [a]).rotate n := by rw [rotate_eq_rotate', rotate_eq_rotate', rotate'_cons_succ] @@ -183,9 +182,6 @@ theorem zipWith_rotate_distrib {β γ : Type*} (f : α → β → γ) (l : List take_zipWith, List.length_zipWith, h, min_self] rw [length_drop, length_drop, h] -attribute [local simp] rotate_cons_succ - --- Porting note: removing @[simp], simp can prove it theorem zipWith_rotate_one {β : Type*} (f : α → α → β) (x y : α) (l : List α) : zipWith f (x :: y :: l) ((x :: y :: l).rotate 1) = f x y :: zipWith f (y :: l) (l ++ [x]) := by simp diff --git a/Mathlib/Data/Multiset/FinsetOps.lean b/Mathlib/Data/Multiset/FinsetOps.lean index 0a99e9258eaf2..93a8b24bcd05b 100644 --- a/Mathlib/Data/Multiset/FinsetOps.lean +++ b/Mathlib/Data/Multiset/FinsetOps.lean @@ -57,9 +57,7 @@ theorem mem_ndinsert {a b : α} {s : Multiset α} : a ∈ ndinsert b s ↔ a = b theorem le_ndinsert_self (a : α) (s : Multiset α) : s ≤ ndinsert a s := Quot.inductionOn s fun _ => (sublist_insert _ _).subperm --- Porting note: removing @[simp], simp can prove it -theorem mem_ndinsert_self (a : α) (s : Multiset α) : a ∈ ndinsert a s := - mem_ndinsert.2 (Or.inl rfl) +theorem mem_ndinsert_self (a : α) (s : Multiset α) : a ∈ ndinsert a s := by simp theorem mem_ndinsert_of_mem {a b : α} {s : Multiset α} (h : a ∈ s) : a ∈ ndinsert b s := mem_ndinsert.2 (Or.inr h) @@ -130,7 +128,7 @@ def ndunion (s t : Multiset α) : Multiset α := theorem coe_ndunion (l₁ l₂ : List α) : @ndunion α _ l₁ l₂ = (l₁ ∪ l₂ : List α) := rfl --- Porting note: removing @[simp], simp can prove it +-- Porting note: removed @[simp], original porting note incorrectly claimed that simp can prove it theorem zero_ndunion (s : Multiset α) : ndunion 0 s = s := Quot.inductionOn s fun _ => rfl diff --git a/Mathlib/Data/Multiset/Pi.lean b/Mathlib/Data/Multiset/Pi.lean index fc8dad8e16e55..8a0efb3620abf 100644 --- a/Mathlib/Data/Multiset/Pi.lean +++ b/Mathlib/Data/Multiset/Pi.lean @@ -57,7 +57,7 @@ theorem cons_swap {a a' : α} {b : δ a} {b' : δ a'} {m : Multiset α} {f : ∀ on_goal 1 => rcases Decidable.eq_or_ne a'' a' with (rfl | h₂) all_goals simp [*, Pi.cons_same, Pi.cons_ne] -@[simp, nolint simpNF] -- Porting note: false positive, this lemma can prove itself +@[simp] theorem cons_eta {m : Multiset α} {a : α} (f : ∀ a' ∈ a ::ₘ m, δ a') : (cons m a (f _ (mem_cons_self _ _)) fun a' ha' => f a' (mem_cons_of_mem ha')) = f := by ext a' h' diff --git a/Mathlib/Data/Nat/Defs.lean b/Mathlib/Data/Nat/Defs.lean index 5f52c3eb53cf2..415504a2a854d 100644 --- a/Mathlib/Data/Nat/Defs.lean +++ b/Mathlib/Data/Nat/Defs.lean @@ -102,7 +102,6 @@ lemma succ_injective : Injective Nat.succ := @succ.inj lemma succ_ne_succ : succ m ≠ succ n ↔ m ≠ n := succ_injective.ne_iff --- Porting note: no longer a simp lemma, as simp can prove this lemma succ_succ_ne_one (n : ℕ) : n.succ.succ ≠ 1 := by simp lemma one_lt_succ_succ (n : ℕ) : 1 < n.succ.succ := succ_lt_succ <| succ_pos n diff --git a/Mathlib/Data/PNat/Interval.lean b/Mathlib/Data/PNat/Interval.lean index c4b3b23d18a7e..769d2bd842c62 100644 --- a/Mathlib/Data/PNat/Interval.lean +++ b/Mathlib/Data/PNat/Interval.lean @@ -71,23 +71,18 @@ theorem card_Ioo : #(Ioo a b) = b - a - 1 := by theorem card_uIcc : #(uIcc a b) = (b - a : ℤ).natAbs + 1 := by rw [← Nat.card_uIcc, ← map_subtype_embedding_uIcc, card_map] --- Porting note: `simpNF` says `simp` can prove this theorem card_fintype_Icc : Fintype.card (Set.Icc a b) = b + 1 - a := by rw [← card_Icc, Fintype.card_ofFinset] --- Porting note: `simpNF` says `simp` can prove this theorem card_fintype_Ico : Fintype.card (Set.Ico a b) = b - a := by rw [← card_Ico, Fintype.card_ofFinset] --- Porting note: `simpNF` says `simp` can prove this theorem card_fintype_Ioc : Fintype.card (Set.Ioc a b) = b - a := by rw [← card_Ioc, Fintype.card_ofFinset] --- Porting note: `simpNF` says `simp` can prove this theorem card_fintype_Ioo : Fintype.card (Set.Ioo a b) = b - a - 1 := by rw [← card_Ioo, Fintype.card_ofFinset] --- Porting note: `simpNF` says `simp` can prove this theorem card_fintype_uIcc : Fintype.card (Set.uIcc a b) = (b - a : ℤ).natAbs + 1 := by rw [← card_uIcc, Fintype.card_ofFinset] diff --git a/Mathlib/Data/Seq/Seq.lean b/Mathlib/Data/Seq/Seq.lean index 8b25a1d0c7c0a..efcc4dfa696f6 100644 --- a/Mathlib/Data/Seq/Seq.lean +++ b/Mathlib/Data/Seq/Seq.lean @@ -816,11 +816,11 @@ instance : LawfulFunctor Seq where theorem join_nil : join nil = (nil : Seq α) := destruct_eq_nil rfl ---@[simp] -- Porting note: simp can prove: `join_cons` is more general +-- Not a simp lemmas as `join_cons` is more general theorem join_cons_nil (a : α) (S) : join (cons (a, nil) S) = cons a (join S) := destruct_eq_cons <| by simp [join] ---@[simp] -- Porting note: simp can prove: `join_cons` is more general +-- Not a simp lemmas as `join_cons` is more general theorem join_cons_cons (a b : α) (s S) : join (cons (a, cons b s) S) = cons a (join (cons (b, s) S)) := destruct_eq_cons <| by simp [join] diff --git a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean index 5d0c59e57bf63..f2b09a64b89b1 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean @@ -90,20 +90,15 @@ theorem left_invariant' : 𝒅ₕ (smoothLeftMul_one I g) (Derivation.evalAt (1 : G) ↑X) = Derivation.evalAt g ↑X := left_invariant'' X g --- Porting note: was `@[simp]` but `_root_.map_add` can prove it now -protected theorem map_add : X (f + f') = X f + X f' := map_add X f f' +protected theorem map_add : X (f + f') = X f + X f' := by simp --- Porting note: was `@[simp]` but `_root_.map_zero` can prove it now -protected theorem map_zero : X 0 = 0 := map_zero X +protected theorem map_zero : X 0 = 0 := by simp --- Porting note: was `@[simp]` but `_root_.map_neg` can prove it now -protected theorem map_neg : X (-f) = -X f := map_neg X f +protected theorem map_neg : X (-f) = -X f := by simp --- Porting note: was `@[simp]` but `_root_.map_sub` can prove it now -protected theorem map_sub : X (f - f') = X f - X f' := map_sub X f f' +protected theorem map_sub : X (f - f') = X f - X f' := by simp --- Porting note: was `@[simp]` but `_root_.map_smul` can prove it now -protected theorem map_smul : X (r • f) = r • X f := map_smul X r f +protected theorem map_smul : X (r • f) = r • X f := by simp @[simp] theorem leibniz : X (f * f') = f • X f' + f' • X f := diff --git a/Mathlib/GroupTheory/Congruence/Defs.lean b/Mathlib/GroupTheory/Congruence/Defs.lean index 909a38db18909..f3b58fe980782 100644 --- a/Mathlib/GroupTheory/Congruence/Defs.lean +++ b/Mathlib/GroupTheory/Congruence/Defs.lean @@ -426,13 +426,11 @@ additive congruence relation in which they are contained."] theorem conGen_of_con (c : Con M) : conGen c = c := le_antisymm (by rw [conGen_eq]; exact sInf_le fun _ _ => id) ConGen.Rel.of --- Porting note: removing simp, simp can prove it /-- The map sending a binary relation to the smallest congruence relation in which it is contained is idempotent. -/ @[to_additive addConGen_idem "The map sending a binary relation to the smallest additive congruence relation in which it is contained is idempotent."] -theorem conGen_idem (r : M → M → Prop) : conGen (conGen r) = conGen r := - conGen_of_con _ +theorem conGen_idem (r : M → M → Prop) : conGen (conGen r) = conGen r := by simp /-- The supremum of congruence relations `c, d` equals the smallest congruence relation containing the binary relation '`x` is related to `y` by `c` or `d`'. -/ diff --git a/Mathlib/GroupTheory/GroupAction/Quotient.lean b/Mathlib/GroupTheory/GroupAction/Quotient.lean index cdc8548a66f2c..c3fa3d099fb3d 100644 --- a/Mathlib/GroupTheory/GroupAction/Quotient.lean +++ b/Mathlib/GroupTheory/GroupAction/Quotient.lean @@ -95,10 +95,9 @@ theorem Quotient.smul_coe [QuotientAction β H] (b : β) (a : α) : theorem Quotient.mk_smul_out [QuotientAction β H] (b : β) (q : α ⧸ H) : QuotientGroup.mk (b • q.out) = b • q := by rw [← Quotient.smul_mk, QuotientGroup.out_eq'] --- Porting note: removed simp attribute, simp can prove this @[to_additive] -theorem Quotient.coe_smul_out [QuotientAction β H] (b : β) (q : α ⧸ H) : ↑(b • q.out) = b • q := - Quotient.mk_smul_out H b q +theorem Quotient.coe_smul_out [QuotientAction β H] (b : β) (q : α ⧸ H) : ↑(b • q.out) = b • q := by + simp theorem _root_.QuotientGroup.out_conj_pow_minimalPeriod_mem (a : α) (q : α ⧸ H) : q.out⁻¹ * a ^ Function.minimalPeriod (a • ·) q * q.out ∈ H := by @@ -114,7 +113,6 @@ attribute [deprecated Quotient.mk_smul_out (since := "2024-10-19")] Quotient.mk_ attribute [deprecated AddAction.Quotient.mk_vadd_out (since := "2024-10-19")] AddAction.Quotient.mk_vadd_out' --- Porting note: removed simp attribute, simp can prove this @[to_additive] alias Quotient.coe_smul_out' := Quotient.coe_smul_out diff --git a/Mathlib/LinearAlgebra/Dimension/Constructions.lean b/Mathlib/LinearAlgebra/Dimension/Constructions.lean index 81fbadfe29fce..427174ca24c09 100644 --- a/Mathlib/LinearAlgebra/Dimension/Constructions.lean +++ b/Mathlib/LinearAlgebra/Dimension/Constructions.lean @@ -153,10 +153,8 @@ theorem rank_finsupp' (ι : Type v) : Module.rank R (ι →₀ M) = #ι * Module simp [rank_finsupp] /-- The rank of `(ι →₀ R)` is `(#ι).lift`. -/ --- Porting note, this should not be `@[simp]`, as simp can prove it. --- @[simp] theorem rank_finsupp_self (ι : Type w) : Module.rank R (ι →₀ R) = Cardinal.lift.{u} #ι := by - simp [rank_finsupp] + simp /-- If `R` and `ι` lie in the same universe, the rank of `(ι →₀ R)` is `# ι`. -/ theorem rank_finsupp_self' {ι : Type u} : Module.rank R (ι →₀ R) = #ι := by simp diff --git a/Mathlib/Logic/Denumerable.lean b/Mathlib/Logic/Denumerable.lean index b45cea7453b1a..a71bc3defb551 100644 --- a/Mathlib/Logic/Denumerable.lean +++ b/Mathlib/Logic/Denumerable.lean @@ -148,7 +148,6 @@ end Sigma instance prod : Denumerable (α × β) := ofEquiv _ (Equiv.sigmaEquivProd α β).symm --- Porting note: removed @[simp] - simp can prove it theorem prod_ofNat_val (n : ℕ) : ofNat (α × β) n = (ofNat α (unpair n).1, ofNat β (unpair n).2) := by simp diff --git a/Mathlib/Logic/Equiv/PartialEquiv.lean b/Mathlib/Logic/Equiv/PartialEquiv.lean index 0a231722f6cfa..ff661bd6d8b3e 100644 --- a/Mathlib/Logic/Equiv/PartialEquiv.lean +++ b/Mathlib/Logic/Equiv/PartialEquiv.lean @@ -525,11 +525,9 @@ theorem refl_coe : (PartialEquiv.refl α : α → α) = id := theorem refl_symm : (PartialEquiv.refl α).symm = PartialEquiv.refl α := rfl --- Porting note: removed `simp` because `simp` can prove this @[mfld_simps] theorem refl_restr_source (s : Set α) : ((PartialEquiv.refl α).restr s).source = s := by simp --- Porting note: removed `simp` because `simp` can prove this @[mfld_simps] theorem refl_restr_target (s : Set α) : ((PartialEquiv.refl α).restr s).target = s := by change univ ∩ id ⁻¹' s = s diff --git a/Mathlib/Order/BoundedOrder/Lattice.lean b/Mathlib/Order/BoundedOrder/Lattice.lean index 3c06e09a51844..7d5a36cf574b9 100644 --- a/Mathlib/Order/BoundedOrder/Lattice.lean +++ b/Mathlib/Order/BoundedOrder/Lattice.lean @@ -34,11 +34,9 @@ section SemilatticeSupTop variable [SemilatticeSup α] [OrderTop α] --- Porting note: Not simp because simp can prove it theorem top_sup_eq (a : α) : ⊤ ⊔ a = ⊤ := sup_of_le_left le_top --- Porting note: Not simp because simp can prove it theorem sup_top_eq (a : α) : a ⊔ ⊤ = ⊤ := sup_of_le_right le_top @@ -48,11 +46,9 @@ section SemilatticeSupBot variable [SemilatticeSup α] [OrderBot α] {a b : α} --- Porting note: Not simp because simp can prove it theorem bot_sup_eq (a : α) : ⊥ ⊔ a = a := sup_of_le_right bot_le --- Porting note: Not simp because simp can prove it theorem sup_bot_eq (a : α) : a ⊔ ⊥ = a := sup_of_le_left bot_le @@ -65,10 +61,8 @@ section SemilatticeInfTop variable [SemilatticeInf α] [OrderTop α] {a b : α} --- Porting note: Not simp because simp can prove it lemma top_inf_eq (a : α) : ⊤ ⊓ a = a := inf_of_le_right le_top --- Porting note: Not simp because simp can prove it lemma inf_top_eq (a : α) : a ⊓ ⊤ = a := inf_of_le_left le_top @[simp] @@ -81,10 +75,8 @@ section SemilatticeInfBot variable [SemilatticeInf α] [OrderBot α] --- Porting note: Not simp because simp can prove it lemma bot_inf_eq (a : α) : ⊥ ⊓ a = ⊥ := inf_of_le_left bot_le --- Porting note: Not simp because simp can prove it lemma inf_bot_eq (a : α) : a ⊓ ⊥ = ⊥ := inf_of_le_right bot_le end SemilatticeInfBot diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index 3a13bb5216d8a..e6caeb702f390 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -153,10 +153,8 @@ def degreeLTEquiv (R) [Semiring R] (n : ℕ) : degreeLT R n ≃ₗ[R] Fin n → · intro h exact (h (Finset.mem_univ _)).elim --- Porting note: removed @[simp] as simp can prove this theorem degreeLTEquiv_eq_zero_iff_eq_zero {n : ℕ} {p : R[X]} (hp : p ∈ degreeLT R n) : - degreeLTEquiv _ _ ⟨p, hp⟩ = 0 ↔ p = 0 := by - rw [LinearEquiv.map_eq_zero_iff, Submodule.mk_eq_zero] + degreeLTEquiv _ _ ⟨p, hp⟩ = 0 ↔ p = 0 := by simp theorem eval_eq_sum_degreeLTEquiv {n : ℕ} {p : R[X]} (hp : p ∈ degreeLT R n) (x : R) : p.eval x = ∑ i, degreeLTEquiv _ _ ⟨p, hp⟩ i * x ^ (i : ℕ) := by @@ -359,9 +357,8 @@ theorem coeff_restriction {p : R[X]} {n : ℕ} : ↑(coeff (restriction p) n) = rfl · rfl --- Porting note: removed @[simp] as simp can prove this -theorem coeff_restriction' {p : R[X]} {n : ℕ} : (coeff (restriction p) n).1 = coeff p n := - coeff_restriction +theorem coeff_restriction' {p : R[X]} {n : ℕ} : (coeff (restriction p) n).1 = coeff p n := by + simp @[simp] theorem support_restriction (p : R[X]) : support (restriction p) = support p := by @@ -429,9 +426,8 @@ theorem coeff_toSubring {n : ℕ} : ↑(coeff (toSubring p T hp) n) = coeff p n rfl · rfl --- Porting note: removed @[simp] as simp can prove this -theorem coeff_toSubring' {n : ℕ} : (coeff (toSubring p T hp) n).1 = coeff p n := - coeff_toSubring _ _ hp +theorem coeff_toSubring' {n : ℕ} : (coeff (toSubring p T hp) n).1 = coeff p n := by + simp @[simp] theorem support_toSubring : support (toSubring p T hp) = support p := by diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index cb2e3d4ea1420..f6cc221b568da 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -604,7 +604,6 @@ theorem lift_mul (a b : Cardinal.{u}) : lift.{v} (a * b) = lift.{v} a * lift.{v} inductionOn₂ a b fun _ _ => mk_congr <| Equiv.ulift.trans (Equiv.prodCongr Equiv.ulift Equiv.ulift).symm --- Porting note: Proof used to be simp, needed to remind simp that 1 + 1 = 2 theorem lift_two : lift.{u, v} 2 = 2 := by simp [← one_add_one_eq_two] @[simp] diff --git a/Mathlib/SetTheory/Game/Basic.lean b/Mathlib/SetTheory/Game/Basic.lean index be2e92919662c..bc7e47200b09a 100644 --- a/Mathlib/SetTheory/Game/Basic.lean +++ b/Mathlib/SetTheory/Game/Basic.lean @@ -912,7 +912,9 @@ def inv'Zero : inv' 0 ≡r 1 := by refine ⟨?_, ?_, fun i => ?_, IsEmpty.elim ?_⟩ · apply Equiv.equivPUnit (InvTy _ _ _) · apply Equiv.equivPEmpty (InvTy _ _ _) - · -- Porting note: had to add `rfl`, because `simp` only uses the built-in `rfl`. + · -- Porting note: we added `rfl` after the `simp` + -- (because `simp` now uses `rfl` only at reducible transparency) + -- Can we improve the simp set so it is not needed? simp; rfl · dsimp infer_instance diff --git a/Mathlib/SetTheory/Game/Birthday.lean b/Mathlib/SetTheory/Game/Birthday.lean index f25e8c1fa8208..0479b655f681d 100644 --- a/Mathlib/SetTheory/Game/Birthday.lean +++ b/Mathlib/SetTheory/Game/Birthday.lean @@ -136,8 +136,6 @@ theorem birthday_add : ∀ x y : PGame.{u}, (x + y).birthday = x.birthday ♯ y. rw [birthday_def, nadd, lsub_sum, lsub_sum] simp only [mk_add_moveLeft_inl, mk_add_moveLeft_inr, mk_add_moveRight_inl, mk_add_moveRight_inr, moveLeft_mk, moveRight_mk] - -- Porting note: Originally `simp only [birthday_add]`, but this causes an error in - -- `termination_by`. Use a workaround. conv_lhs => left; left; right; intro a; rw [birthday_add (xL a) ⟨yl, yr, yL, yR⟩] conv_lhs => left; right; right; intro b; rw [birthday_add ⟨xl, xr, xL, xR⟩ (yL b)] conv_lhs => right; left; right; intro a; rw [birthday_add (xR a) ⟨yl, yr, yL, yR⟩] diff --git a/Mathlib/SetTheory/Surreal/Dyadic.lean b/Mathlib/SetTheory/Surreal/Dyadic.lean index 637708cb52d54..c8e06305fbe7a 100644 --- a/Mathlib/SetTheory/Surreal/Dyadic.lean +++ b/Mathlib/SetTheory/Surreal/Dyadic.lean @@ -240,7 +240,6 @@ theorem dyadicMap_apply (m : ℤ) (p : Submonoid.powers (2 : ℤ)) : m * powHalf (Submonoid.log p) := by rw [← Localization.mk_eq_mk']; rfl --- @[simp] -- Porting note: simp normal form is `dyadicMap_apply_pow'` theorem dyadicMap_apply_pow (m : ℤ) (n : ℕ) : dyadicMap (IsLocalization.mk' (Localization (Submonoid.powers 2)) m (Submonoid.pow 2 n)) = m • powHalf n := by diff --git a/Mathlib/Tactic/NormNum/GCD.lean b/Mathlib/Tactic/NormNum/GCD.lean index cf43344d0f6e3..c9bcc4f4c2c98 100644 --- a/Mathlib/Tactic/NormNum/GCD.lean +++ b/Mathlib/Tactic/NormNum/GCD.lean @@ -67,7 +67,7 @@ theorem nat_lcm_helper (x y d m : ℕ) (hd : Nat.gcd x y = d) (d0 : Nat.beq d 0 = false) (dm : x * y = d * m) : Nat.lcm x y = m := mul_right_injective₀ (Nat.ne_of_beq_eq_false d0) <| by - dsimp only -- Porting note: the `dsimp only` was not necessary in Lean3. + dsimp only rw [← dm, ← hd, Nat.gcd_mul_lcm] theorem int_gcd_helper {x y : ℤ} {x' y' d : ℕ} diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean index ba49c204bab72..1f17014592432 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean @@ -269,7 +269,6 @@ theorem hasProd_prod {f : γ → β → α} {a : γ → α} {s : Finset γ} : (∀ i ∈ s, HasProd (f i) (a i)) → HasProd (fun b ↦ ∏ i ∈ s, f i b) (∏ i ∈ s, a i) := by classical exact Finset.induction_on s (by simp only [hasProd_one, prod_empty, forall_true_iff]) <| by - -- Porting note: with some help, `simp` used to be able to close the goal simp +contextual only [mem_insert, forall_eq_or_imp, not_false_iff, prod_insert, and_imp] exact fun x s _ IH hx h ↦ hx.mul (IH h) diff --git a/Mathlib/Topology/Algebra/Module/Equiv.lean b/Mathlib/Topology/Algebra/Module/Equiv.lean index fb217bf9ceb00..8363cb3582442 100644 --- a/Mathlib/Topology/Algebra/Module/Equiv.lean +++ b/Mathlib/Topology/Algebra/Module/Equiv.lean @@ -799,13 +799,7 @@ linear equivalence `e` between `M` and `M₂ × f₁.ker` such that `(e x).2 = x def equivOfRightInverse (f₁ : M →L[R] M₂) (f₂ : M₂ →L[R] M) (h : Function.RightInverse f₂ f₁) : M ≃L[R] M₂ × ker f₁ := equivOfInverse (f₁.prod (f₁.projKerOfRightInverse f₂ h)) (f₂.coprod (ker f₁).subtypeL) - (fun x => by simp) fun ⟨x, y⟩ => by - -- Porting note: `simp` timeouts. - rw [ContinuousLinearMap.coprod_apply, - Submodule.subtypeL_apply, _root_.map_add, ContinuousLinearMap.prod_apply, h x, - ContinuousLinearMap.projKerOfRightInverse_comp_inv, - ContinuousLinearMap.prod_apply, LinearMap.map_coe_ker, - ContinuousLinearMap.projKerOfRightInverse_apply_idem, Prod.mk_add_mk, add_zero, zero_add] + (fun x => by simp) fun ⟨x, y⟩ => by simp [h x] @[simp] theorem fst_equivOfRightInverse (f₁ : M →L[R] M₂) (f₂ : M₂ →L[R] M) diff --git a/Mathlib/Topology/Category/TopCat/Basic.lean b/Mathlib/Topology/Category/TopCat/Basic.lean index 4a58d8d5da686..b9921302b97a7 100644 --- a/Mathlib/Topology/Category/TopCat/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Basic.lean @@ -165,7 +165,6 @@ lemma isIso_of_bijective_of_isClosedMap {X Y : TopCat.{u}} (f : X ⟶ Y) (Equiv.ofBijective f hfbij) f.continuous hfcl inferInstanceAs <| IsIso (TopCat.isoOfHomeo e).hom --- Porting note: simpNF requested partially simped version below theorem isOpenEmbedding_iff_comp_isIso {X Y Z : TopCat} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso g] : IsOpenEmbedding (f ≫ g) ↔ IsOpenEmbedding f := (TopCat.homeoOfIso (asIso g)).isOpenEmbedding.of_comp_iff f diff --git a/Mathlib/Topology/Category/UniformSpace.lean b/Mathlib/Topology/Category/UniformSpace.lean index 902bad56f52b1..c3671ce185d18 100644 --- a/Mathlib/Topology/Category/UniformSpace.lean +++ b/Mathlib/Topology/Category/UniformSpace.lean @@ -67,8 +67,6 @@ theorem coe_comp {X Y Z : UniformSpaceCat} (f : X ⟶ Y) (g : Y ⟶ Z) : (f ≫ theorem coe_id (X : UniformSpaceCat) : (𝟙 X : X → X) = id := rfl --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute --- due to `LEFT-HAND SIDE HAS VARIABLE AS HEAD SYMBOL.` theorem coe_mk {X Y : UniformSpaceCat} (f : X → Y) (hf : UniformContinuous f) : ((⟨f, hf⟩ : X ⟶ Y) : X → Y) = f := rfl diff --git a/Mathlib/Topology/Compactification/OnePoint.lean b/Mathlib/Topology/Compactification/OnePoint.lean index f5c6e77961501..7ceef5616e46b 100644 --- a/Mathlib/Topology/Compactification/OnePoint.lean +++ b/Mathlib/Topology/Compactification/OnePoint.lean @@ -122,7 +122,6 @@ protected def rec {C : OnePoint X → Sort*} (infty : C ∞) (coe : ∀ x : X, C theorem isCompl_range_coe_infty : IsCompl (range ((↑) : X → OnePoint X)) {∞} := isCompl_range_some_none X --- Porting note: moved @[simp] to a new lemma theorem range_coe_union_infty : range ((↑) : X → OnePoint X) ∪ {∞} = univ := range_some_union_none X diff --git a/Mathlib/Topology/Constructions.lean b/Mathlib/Topology/Constructions.lean index 5e5987a52ca6d..3eac03c81156e 100644 --- a/Mathlib/Topology/Constructions.lean +++ b/Mathlib/Topology/Constructions.lean @@ -1643,9 +1643,7 @@ variable {ι κ : Type*} {σ : ι → Type*} {τ : κ → Type*} [∀ i, Topolog theorem continuous_sigmaMk {i : ι} : Continuous (@Sigma.mk ι σ i) := continuous_iSup_rng continuous_coinduced_rng --- Porting note: the proof was `by simp only [isOpen_iSup_iff, isOpen_coinduced]` theorem isOpen_sigma_iff {s : Set (Sigma σ)} : IsOpen s ↔ ∀ i, IsOpen (Sigma.mk i ⁻¹' s) := by - delta instTopologicalSpaceSigma rw [isOpen_iSup_iff] rfl diff --git a/Mathlib/Topology/FiberBundle/Basic.lean b/Mathlib/Topology/FiberBundle/Basic.lean index 8f0275f8bef96..09a6da952e60f 100644 --- a/Mathlib/Topology/FiberBundle/Basic.lean +++ b/Mathlib/Topology/FiberBundle/Basic.lean @@ -285,7 +285,6 @@ theorem mem_trivializationAt_proj_source {x : TotalSpace F E} : x ∈ (trivializationAt F E x.proj).source := (Trivialization.mem_source _).mpr <| mem_baseSet_trivializationAt F E x.proj --- Porting note: removed `@[simp, mfld_simps]` because `simp` could already prove this theorem trivializationAt_proj_fst {x : TotalSpace F E} : ((trivializationAt F E x.proj) x).1 = x.proj := Trivialization.coe_fst' _ <| mem_baseSet_trivializationAt F E x.proj diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index 2b05f77e1de94..681b44bc53a60 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -235,10 +235,7 @@ theorem image_inter (i j : D.J) : -- Porting note (https://github.com/leanprover-community/mathlib4/issues/10745): was `simp [eq₁]` -- See https://github.com/leanprover-community/mathlib4/issues/5026 rw [TopCat.comp_app, CategoryTheory.IsIso.inv_hom_id_apply, eq₁]⟩ - · -- Porting note: was - -- dsimp only at *; substs e₁ eq₁; exact ⟨y, by simp⟩ - dsimp only at * - substs eq₁ + · subst eq₁ exact ⟨y, by simp [e₁]⟩ · rintro ⟨x, hx⟩ refine ⟨⟨D.f i j x, hx⟩, ⟨D.f j i (D.t _ _ x), ?_⟩⟩ diff --git a/Mathlib/Topology/LocalAtTarget.lean b/Mathlib/Topology/LocalAtTarget.lean index f1029b3df76df..3557289a1439f 100644 --- a/Mathlib/Topology/LocalAtTarget.lean +++ b/Mathlib/Topology/LocalAtTarget.lean @@ -113,12 +113,9 @@ theorem isOpen_iff_inter_of_iSup_eq_top (s : Set β) : IsOpen s ↔ ∀ i, IsOpe theorem isOpen_iff_coe_preimage_of_iSup_eq_top (s : Set β) : IsOpen s ↔ ∀ i, IsOpen ((↑) ⁻¹' s : Set (U i)) := by - -- Porting note: rewrote to avoid ´simp´ issues - rw [isOpen_iff_inter_of_iSup_eq_top hU s] - refine forall_congr' fun i => ?_ - rw [(U _).2.isOpenEmbedding_subtypeVal.isOpen_iff_image_isOpen] - erw [Set.image_preimage_eq_inter_range] - rw [Subtype.range_coe, Opens.carrier_eq_coe] + simp [isOpen_iff_inter_of_iSup_eq_top hU s, + (U _).2.isOpenEmbedding_subtypeVal.isOpen_iff_image_isOpen, + Set.image_preimage_eq_inter_range] theorem isClosed_iff_coe_preimage_of_iSup_eq_top (s : Set β) : IsClosed s ↔ ∀ i, IsClosed ((↑) ⁻¹' s : Set (U i)) := by diff --git a/Mathlib/Topology/MetricSpace/Dilation.lean b/Mathlib/Topology/MetricSpace/Dilation.lean index ee4cc20f7a1f3..a04bf9dd698c2 100644 --- a/Mathlib/Topology/MetricSpace/Dilation.lean +++ b/Mathlib/Topology/MetricSpace/Dilation.lean @@ -296,7 +296,6 @@ theorem coe_comp (g : β →ᵈ γ) (f : α →ᵈ β) : (g.comp f : α → γ) theorem comp_apply (g : β →ᵈ γ) (f : α →ᵈ β) (x : α) : (g.comp f : α → γ) x = g (f x) := rfl --- Porting note: removed `simp` because it's difficult to auto prove `hne` /-- Ratio of the composition `g.comp f` of two dilations is the product of their ratios. We assume that there exist two points in `α` at extended distance neither `0` nor `∞` because otherwise `Dilation.ratio (g.comp f) = Dilation.ratio f = 1` while `Dilation.ratio g` can be any number. This diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean index a19d3d5982139..c1899369609a7 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean @@ -426,8 +426,7 @@ instance : MetricSpace GHSpace where In this coupling, the two spaces are at zero Hausdorff distance, i.e., they coincide. Therefore, the original spaces are isometric. -/ rcases ghDist_eq_hausdorffDist x.Rep y.Rep with ⟨Φ, Ψ, Φisom, Ψisom, DΦΨ⟩ - rw [← dist_ghDist] at DΦΨ - simp_rw [hxy] at DΦΨ -- Porting note: I have no idea why this needed `simp_rw` versus `rw` + rw [← dist_ghDist, hxy] at DΦΨ have : range Φ = range Ψ := by have hΦ : IsCompact (range Φ) := isCompact_range Φisom.continuous have hΨ : IsCompact (range Ψ) := isCompact_range Ψisom.continuous diff --git a/Mathlib/Topology/Sets/Compacts.lean b/Mathlib/Topology/Sets/Compacts.lean index fea42e6322ded..65ac7d3760471 100644 --- a/Mathlib/Topology/Sets/Compacts.lean +++ b/Mathlib/Topology/Sets/Compacts.lean @@ -217,7 +217,6 @@ protected theorem ext {s t : NonemptyCompacts α} (h : (s : Set α) = t) : s = t theorem coe_mk (s : Compacts α) (h) : (mk s h : Set α) = s := rfl --- Porting note: `@[simp]` moved to `coe_toCompacts` theorem carrier_eq_coe (s : NonemptyCompacts α) : s.carrier = s := rfl @@ -311,7 +310,6 @@ protected theorem ext {s t : PositiveCompacts α} (h : (s : Set α) = t) : s = t theorem coe_mk (s : Compacts α) (h) : (mk s h : Set α) = s := rfl --- Porting note: `@[simp]` moved to a new lemma theorem carrier_eq_coe (s : PositiveCompacts α) : s.carrier = s := rfl diff --git a/Mathlib/Topology/Sets/Opens.lean b/Mathlib/Topology/Sets/Opens.lean index 955325b19092c..bac92aeaffc4e 100644 --- a/Mathlib/Topology/Sets/Opens.lean +++ b/Mathlib/Topology/Sets/Opens.lean @@ -91,7 +91,6 @@ theorem coe_mk {U : Set α} {hU : IsOpen U} : ↑(⟨U, hU⟩ : Opens α) = U := @[simp] theorem mem_mk {x : α} {U : Set α} {h : IsOpen U} : x ∈ mk U h ↔ x ∈ U := Iff.rfl --- Porting note: removed @[simp] because LHS simplifies to `∃ x, x ∈ U` protected theorem nonempty_coeSort {U : Opens α} : Nonempty U ↔ (U : Set α).Nonempty := Set.nonempty_coe_sort @@ -103,7 +102,6 @@ protected theorem nonempty_coe {U : Opens α} : (U : Set α).Nonempty ↔ ∃ x, theorem ext {U V : Opens α} (h : (U : Set α) = V) : U = V := SetLike.coe_injective h --- Porting note: removed @[simp], simp can prove it theorem coe_inj {U V : Opens α} : (U : Set α) = V ↔ U = V := SetLike.ext'_iff.symm diff --git a/Mathlib/Topology/Sheaves/LocalPredicate.lean b/Mathlib/Topology/Sheaves/LocalPredicate.lean index 3df254e59f928..f212a015ac7f6 100644 --- a/Mathlib/Topology/Sheaves/LocalPredicate.lean +++ b/Mathlib/Topology/Sheaves/LocalPredicate.lean @@ -215,8 +215,6 @@ def stalkToFiber (P : LocalPredicate T) (x : X) : (subsheafToTypes P).presheaf.s · exact f.1 ⟨x, (unop U).2⟩ · aesop --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute, --- due to left hand side is not in simple normal form. theorem stalkToFiber_germ (P : LocalPredicate T) (U : Opens X) (x : X) (hx : x ∈ U) (f) : stalkToFiber P x ((subsheafToTypes P).presheaf.germ U x hx f) = f.1 ⟨x, hx⟩ := by simp [Presheaf.germ, stalkToFiber] diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index 6bafe7f3b0815..a2aa72573878f 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -127,8 +127,6 @@ abbrev restrictOpen {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] { /-- restriction of a section to open subset -/ scoped[AlgebraicGeometry] infixl:80 " |_ " => TopCat.Presheaf.restrictOpen --- Porting note: linter tells this lemma is no going to be picked up by the simplifier, hence --- `@[simp]` is removed theorem restrict_restrict {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] {F : X.Presheaf C} {U V W : Opens X} (e₁ : U ≤ V) (e₂ : V ≤ W) (x : F.obj (op W)) : x |_ V |_ U = x |_ U := by @@ -136,8 +134,6 @@ theorem restrict_restrict {X : TopCat} {C : Type*} [Category C] [ConcreteCategor rw [← comp_apply, ← Functor.map_comp] rfl --- Porting note: linter tells this lemma is no going to be picked up by the simplifier, hence --- `@[simp]` is removed theorem map_restrict {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] {F G : X.Presheaf C} (e : F ⟶ G) {U V : Opens X} (h : U ≤ V) (x : F.obj (op V)) : e.app _ (x |_ U) = e.app _ x |_ U := by diff --git a/Mathlib/Topology/Sheaves/Skyscraper.lean b/Mathlib/Topology/Sheaves/Skyscraper.lean index 98806657614a2..259b736775448 100644 --- a/Mathlib/Topology/Sheaves/Skyscraper.lean +++ b/Mathlib/Topology/Sheaves/Skyscraper.lean @@ -143,7 +143,7 @@ noncomputable def skyscraperPresheafCoconeIsColimitOfSpecializes {y : X} (h : p IsColimit (skyscraperPresheafCoconeOfSpecializes p₀ A h) where desc c := eqToHom (if_pos trivial).symm ≫ c.ι.app (op ⊤) fac c U := by - dsimp -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11227):added a `dsimp` + dsimp rw [← c.w (homOfLE <| (le_top : unop U ≤ _)).op] change _ ≫ _ ≫ dite _ _ _ ≫ _ = _ rw [dif_pos] @@ -151,7 +151,7 @@ noncomputable def skyscraperPresheafCoconeIsColimitOfSpecializes {y : X} (h : p eqToHom_refl, Category.id_comp, unop_op, op_unop] · exact h.mem_open U.unop.1.2 U.unop.2 uniq c f h := by - dsimp -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11227):added a `dsimp` + dsimp rw [← h, skyscraperPresheafCoconeOfSpecializes_ι_app, eqToHom_trans_assoc, eqToHom_refl, Category.id_comp] @@ -195,7 +195,7 @@ noncomputable def skyscraperPresheafCoconeIsColimitOfNotSpecializes {y : X} (h : refine ((if_neg ?_).symm.ndrec terminalIsTerminal).hom_ext _ _ exact fun h => h1.choose_spec h.1 uniq := fun c f H => by - dsimp -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11227):added a `dsimp` + dsimp rw [← Category.id_comp f, ← H, ← Category.assoc] congr 1; apply terminalIsTerminal.hom_ext } diff --git a/Mathlib/Topology/UniformSpace/Equiv.lean b/Mathlib/Topology/UniformSpace/Equiv.lean index ae9e58b798857..8f0d5e13b5aaf 100644 --- a/Mathlib/Topology/UniformSpace/Equiv.lean +++ b/Mathlib/Topology/UniformSpace/Equiv.lean @@ -130,7 +130,6 @@ protected theorem continuous_symm (h : α ≃ᵤ β) : Continuous h.symm := h.uniformContinuous_symm.continuous /-- A uniform isomorphism as a homeomorphism. -/ --- @[simps] -- Porting note: removed, `simps?` produced no `simp` lemmas protected def toHomeomorph (e : α ≃ᵤ β) : α ≃ₜ β := { e.toEquiv with continuous_toFun := e.continuous @@ -372,7 +371,6 @@ def image (e : α ≃ᵤ β) (s : Set α) : s ≃ᵤ e '' s where end UniformEquiv /-- A uniform inducing equiv between uniform spaces is a uniform isomorphism. -/ --- @[simps] -- Porting note: removed, `simps?` produced no `simp` lemmas def Equiv.toUniformEquivOfIsUniformInducing [UniformSpace α] [UniformSpace β] (f : α ≃ β) (hf : IsUniformInducing f) : α ≃ᵤ β := { f with diff --git a/Mathlib/Topology/UniformSpace/OfCompactT2.lean b/Mathlib/Topology/UniformSpace/OfCompactT2.lean index 4c3a279c43064..4203cab46c26b 100644 --- a/Mathlib/Topology/UniformSpace/OfCompactT2.lean +++ b/Mathlib/Topology/UniformSpace/OfCompactT2.lean @@ -79,8 +79,7 @@ def uniformSpaceOfCompactT2 [TopologicalSpace γ] [CompactSpace γ] [T2Space γ] · simp only [W, mem_union, mem_prod, and_self_iff] exact (_root_.em _).imp_left fun h => union_subset_union VU₁ VU₂ h -- So W ○ W ∈ F by definition of F - have : W ○ W ∈ F := @mem_lift' _ _ _ (fun s => s ○ s) _ W_in - -- Porting note: was `by simpa only using mem_lift' W_in` + have : W ○ W ∈ F := by simpa only using mem_lift' W_in -- And V₁ ×ˢ V₂ ∈ 𝓝 (x, y) have hV₁₂ : V₁ ×ˢ V₂ ∈ 𝓝 (x, y) := prod_mem_nhds V₁_in V₂_in -- But (x, y) is also a cluster point of F so (V₁ ×ˢ V₂) ∩ (W ○ W) ≠ ∅ From a735a046975e54824906e4c1b96fa91aa75eabcc Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 16 Jan 2025 12:02:06 +0000 Subject: [PATCH 265/681] CI: merge `bot_fix_style` actions (#20789) This PR continues the series of merging CI actions that are triggered by `comment`s, `review`s and `review_comment`s. Specifically, we merge here the 3 `bot fix style` actions into a single one. #20791 tests that the new action works as intended. --- .github/workflows/bot_fix_style.yaml | 164 ++++++++++++++++++ .github/workflows/bot_fix_style_comment.yaml | 93 ---------- .github/workflows/bot_fix_style_review.yaml | 99 ----------- .../bot_fix_style_review_comment.yaml | 97 ----------- .github/workflows/lint_and_suggest_pr.yml | 8 +- 5 files changed, 168 insertions(+), 293 deletions(-) create mode 100644 .github/workflows/bot_fix_style.yaml delete mode 100644 .github/workflows/bot_fix_style_comment.yaml delete mode 100644 .github/workflows/bot_fix_style_review.yaml delete mode 100644 .github/workflows/bot_fix_style_review_comment.yaml diff --git a/.github/workflows/bot_fix_style.yaml b/.github/workflows/bot_fix_style.yaml new file mode 100644 index 0000000000000..b0c95b3902061 --- /dev/null +++ b/.github/workflows/bot_fix_style.yaml @@ -0,0 +1,164 @@ +name: bot fix style + +# triggers the action when +on: + issue_comment: + # the PR receives a comment, or a comment is edited + types: [created, edited] + pull_request_review: + # triggers on a review, whether or not it is accompanied by a comment + types: [submitted] + pull_request_review_comment: + # triggers on a review comment + types: [created, edited] + +jobs: + fix_style: + # we set some variables. The ones of the form `${{ X }}${{ Y }}` are typically not + # both set simultaneously: depending on the event that triggers the PR, usually only one is set + env: + AUTHOR: ${{ github.event.comment.user.login }}${{ github.event.review.user.login }} + COMMENT_EVENT: ${{ github.event.comment.body }} + COMMENT_REVIEW: ${{ github.event.review.body }} + COMMENT_REVIEW_COMMENT: ${{ github.event.pull_request_review_comment.body }} + name: Fix style issues from lint + # the `if` works with `comment`s, but not with `review`s or `review_comment`s + # if: github.event.issue.pull_request + # && (startsWith(github.event.comment.body, 'bot fix style') || contains(toJSON(github.event.comment.body), '\nbot fix style')) + runs-on: ubuntu-latest + steps: + - name: Find bot fix style + id: bot_fix_style + run: | + COMMENT="${COMMENT_EVENT}${COMMENT_REVIEW}${COMMENT_REVIEW_COMMENT}" + # we strip `\r` since line endings from GitHub contain this character + COMMENT="${COMMENT//$'\r'/}" + # for debugging, we print some information + printf '%s' "${COMMENT}" | hexdump -cC + printf 'Comment:"%s"\n' "${COMMENT}" + bot_fix_style="$(printf '%s' "${COMMENT}" | + sed -n 's=^bot fix style$=bot-fix-style=p' | head -1)" + + printf $'"bot fix style"? \'%s\'\n' "${bot_fix_style}" + printf $'AUTHOR: \'%s\'\n' "${AUTHOR}" + printf $'PR_NUMBER: \'%s\'\n' "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" + printf $'%s' "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" | hexdump -cC + + printf $'bot_fix_style=%s\n' "${bot_fix_style}" >> "${GITHUB_OUTPUT}" + # these final variables are probably not relevant for the bot_fix_style action + if [ "${AUTHOR}" == 'leanprover-community-mathlib4-bot' ] || + [ "${AUTHOR}" == 'leanprover-community-bot-assistant' ] + then + printf $'bot=true\n' + printf $'bot=true\n' >> "${GITHUB_OUTPUT}" + else + printf $'bot=false\n' + printf $'bot=false\n' >> "${GITHUB_OUTPUT}" + fi + + - id: user_permission + if: steps.bot_fix_style.outputs.bot_fix_style == 'bot-fix-style' + uses: actions-cool/check-user-permission@v2 + with: + require: 'write' + + # from now on, it is sufficient to just check `user_permission`: + # if the comment did not contain `bot fix style`, + # then `user_permission` would not have ran + - name: Add reaction (comment) + # reactions are only supported for `comment`s and `review_comment`s? + # This action only runs on `comment`s rather than `review`s or `review_comment`s + # Is the `id` check a good way to check that this is a `comment`? + if: ${{ steps.user_permission.outputs.require-result == 'true' && + ! github.event.comment.id == '' }} + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: rocket + + - name: Add reaction (review comment) + # this action only runs on `review_comment`s + # is the `id` check a good way to check that this is a `review_comment`? + if: ${{ steps.user_permission.outputs.require-result == 'true' && + ! github.event.pull_request_review_comment.id == '' }} + run: | + gh api --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/${{ github.repository_owner }}/${{ github.event.repository.name }}/pulls/comments/${{ github.event.comment.id }}/reactions \ + -f "content=rocket" + env: + GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: cleanup + if: steps.user_permission.outputs.require-result == 'true' + run: | + find . -name . -o -prune -exec rm -rf -- {} + + + - uses: actions/checkout@v4 + if: steps.user_permission.outputs.require-result == 'true' + with: + token: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: Checkout PR branch + if: steps.user_permission.outputs.require-result == 'true' + run: | + # covers `comment`s + gh pr checkout ${{ github.event.issue.number }} || + # covers `review`s and `review_comment`s + gh pr checkout ${{ github.event.pull_request.number }} + env: + GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: install Python + if: steps.user_permission.outputs.require-result == 'true' + uses: actions/setup-python@v5 + with: + python-version: 3.8 + + - name: install elan + if: steps.user_permission.outputs.require-result == 'true' + 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}" + + # run the same linting steps as in lint_and_suggest_pr.yaml + + - name: lint + if: steps.user_permission.outputs.require-result == 'true' + run: | + lake exe lint-style --fix + + - name: Install bibtool + if: steps.user_permission.outputs.require-result == 'true' + run: | + sudo apt-get update + sudo apt-get install -y bibtool + + - name: lint references.bib + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + ./scripts/lint-bib.sh || true + + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + lake exe mk_all || true + + - name: Commit and push changes + if: steps.user_permission.outputs.require-result == 'true' + run: | + # cleanup junk from build + rm elan-init + rm docs/references.bib.old + # setup commit and push + git config user.name "leanprover-community-mathlib4-bot" + git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" + git add . + # Don't fail if there's nothing to commit + git commit -m "commit changes from style linters" || true + git push origin HEAD diff --git a/.github/workflows/bot_fix_style_comment.yaml b/.github/workflows/bot_fix_style_comment.yaml deleted file mode 100644 index 5e0cbbbffd648..0000000000000 --- a/.github/workflows/bot_fix_style_comment.yaml +++ /dev/null @@ -1,93 +0,0 @@ -name: bot fix style (comment) - -on: - issue_comment: - types: [created, edited] - -jobs: - fix_style: - name: Fix style issues from lint - if: (github.event.issue.pull_request) && (startsWith(github.event.comment.body, 'bot fix style') || contains(toJSON(github.event.comment.body), '\nbot fix style')) - runs-on: ubuntu-latest - steps: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'write' - - - name: Add reaction - if: steps.user_permission.outputs.require-result == 'true' - uses: peter-evans/create-or-update-comment@v4 - with: - comment-id: ${{ github.event.comment.id }} - reactions: rocket - - - name: cleanup - if: steps.user_permission.outputs.require-result == 'true' - run: | - find . -name . -o -prune -exec rm -rf -- {} + - - - uses: actions/checkout@v4 - if: steps.user_permission.outputs.require-result == 'true' - with: - token: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: Checkout PR branch - if: steps.user_permission.outputs.require-result == 'true' - run: | - gh pr checkout ${{ github.event.issue.number }} - env: - GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: install Python - if: steps.user_permission.outputs.require-result == 'true' - uses: actions/setup-python@v5 - with: - python-version: 3.8 - - - name: install elan - if: steps.user_permission.outputs.require-result == 'true' - 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}" - - # run the same linting steps as in lint_and_suggest_pr.yaml - - - name: lint - if: steps.user_permission.outputs.require-result == 'true' - run: | - lake exe lint-style --fix - - - name: Install bibtool - if: steps.user_permission.outputs.require-result == 'true' - run: | - sudo apt-get update - sudo apt-get install -y bibtool - - - name: lint references.bib - if: steps.user_permission.outputs.require-result == 'true' - run: | - # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions - ./scripts/lint-bib.sh || true - - - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - if: steps.user_permission.outputs.require-result == 'true' - run: | - # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions - lake exe mk_all || true - - - name: Commit and push changes - if: steps.user_permission.outputs.require-result == 'true' - run: | - # cleanup junk from build - rm elan-init - rm docs/references.bib.old - # setup commit and push - git config user.name "leanprover-community-mathlib4-bot" - git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" - git add . - # Don't fail if there's nothing to commit - git commit -m "commit changes from style linters" || true - git push origin HEAD diff --git a/.github/workflows/bot_fix_style_review.yaml b/.github/workflows/bot_fix_style_review.yaml deleted file mode 100644 index ec389af5ce65b..0000000000000 --- a/.github/workflows/bot_fix_style_review.yaml +++ /dev/null @@ -1,99 +0,0 @@ -name: bot fix style (review) - -on: - pull_request_review: - # triggers on a review, whether or not it is accompanied by a comment - types: [submitted] - -jobs: - fix_style: - name: Fix style issues from lint - if: (startsWith(github.event.review.body, 'bot fix style') || contains(toJSON(github.event.review.body), '\nbot fix style')) - runs-on: ubuntu-latest - steps: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'write' - - # Maybe no API exists for this yet? - # - name: Add reaction - # if: steps.user_permission.outputs.require-result == 'true' - # run: | - # gh api --method POST \ - # -H "Accept: application/vnd.github+json" \ - # -H "X-GitHub-Api-Version: 2022-11-28" \ - # /repos/${{ github.repository_owner }}/${{ github.event.repository.name }}/pulls/${{ github.event.pull_request.number }}/reviews/${{ github.event.review.id }}/reactions \ - # -f "content=rocket" - # env: - # GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: cleanup - if: steps.user_permission.outputs.require-result == 'true' - run: | - find . -name . -o -prune -exec rm -rf -- {} + - - - uses: actions/checkout@v4 - if: steps.user_permission.outputs.require-result == 'true' - with: - token: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: Checkout PR branch - if: steps.user_permission.outputs.require-result == 'true' - run: | - gh pr checkout ${{ github.event.pull_request.number }} - env: - GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: install Python - if: steps.user_permission.outputs.require-result == 'true' - uses: actions/setup-python@v5 - with: - python-version: 3.8 - - - name: install elan - if: steps.user_permission.outputs.require-result == 'true' - 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}" - - # run the same linting steps as in lint_and_suggest_pr.yaml - - - name: lint - if: steps.user_permission.outputs.require-result == 'true' - run: | - lake exe lint-style --fix - - - name: Install bibtool - if: steps.user_permission.outputs.require-result == 'true' - run: | - sudo apt-get update - sudo apt-get install -y bibtool - - - name: lint references.bib - if: steps.user_permission.outputs.require-result == 'true' - run: | - # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions - ./scripts/lint-bib.sh || true - - - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - if: steps.user_permission.outputs.require-result == 'true' - run: | - # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions - lake exe mk_all || true - - - name: Commit and push changes - if: steps.user_permission.outputs.require-result == 'true' - run: | - # cleanup junk from build - rm elan-init - rm docs/references.bib.old - # setup commit and push - git config user.name "leanprover-community-mathlib4-bot" - git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" - git add . - # Don't fail if there's nothing to commit - git commit -m "commit changes from style linters" || true - git push origin HEAD diff --git a/.github/workflows/bot_fix_style_review_comment.yaml b/.github/workflows/bot_fix_style_review_comment.yaml deleted file mode 100644 index d997a6ad7989a..0000000000000 --- a/.github/workflows/bot_fix_style_review_comment.yaml +++ /dev/null @@ -1,97 +0,0 @@ -name: bot fix style (review comment) - -on: - pull_request_review_comment: - types: [created, edited] - -jobs: - fix_style: - name: Fix style issues from lint - if: (startsWith(github.event.comment.body, 'bot fix style') || contains(toJSON(github.event.comment.body), '\nbot fix style')) - runs-on: ubuntu-latest - steps: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'write' - - - name: Add reaction - if: steps.user_permission.outputs.require-result == 'true' - run: | - gh api --method POST \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - /repos/${{ github.repository_owner }}/${{ github.event.repository.name }}/pulls/comments/${{ github.event.comment.id }}/reactions \ - -f "content=rocket" - env: - GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: cleanup - if: steps.user_permission.outputs.require-result == 'true' - run: | - find . -name . -o -prune -exec rm -rf -- {} + - - - uses: actions/checkout@v4 - if: steps.user_permission.outputs.require-result == 'true' - with: - token: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: Checkout PR branch - if: steps.user_permission.outputs.require-result == 'true' - run: | - gh pr checkout ${{ github.event.pull_request.number }} - env: - GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} - - - name: install Python - if: steps.user_permission.outputs.require-result == 'true' - uses: actions/setup-python@v5 - with: - python-version: 3.8 - - - name: install elan - if: steps.user_permission.outputs.require-result == 'true' - 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}" - - # run the same linting steps as in lint_and_suggest_pr.yaml - - - name: lint - if: steps.user_permission.outputs.require-result == 'true' - run: | - lake exe lint-style --fix - - - name: Install bibtool - if: steps.user_permission.outputs.require-result == 'true' - run: | - sudo apt-get update - sudo apt-get install -y bibtool - - - name: lint references.bib - if: steps.user_permission.outputs.require-result == 'true' - run: | - # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions - ./scripts/lint-bib.sh || true - - - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - if: steps.user_permission.outputs.require-result == 'true' - run: | - # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions - lake exe mk_all || true - - - name: Commit and push changes - if: steps.user_permission.outputs.require-result == 'true' - run: | - # cleanup junk from build - rm elan-init - rm docs/references.bib.old - # setup commit and push - git config user.name "leanprover-community-mathlib4-bot" - git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" - git add . - # Don't fail if there's nothing to commit - git commit -m "commit changes from style linters" || true - git push origin HEAD diff --git a/.github/workflows/lint_and_suggest_pr.yml b/.github/workflows/lint_and_suggest_pr.yml index 47029833459db..0cb996133dfe6 100644 --- a/.github/workflows/lint_and_suggest_pr.yml +++ b/.github/workflows/lint_and_suggest_pr.yml @@ -28,7 +28,7 @@ jobs: ./elan-init -y --default-toolchain none echo "$HOME/.elan/bin" >> "${GITHUB_PATH}" - # if you update this step (or its dependencies), please also update them in bot_fix_style_comment.yaml + # if you update this step (or its dependencies), please also update them in bot_fix_style.yaml - name: lint run: | lake exe lint-style --fix @@ -43,7 +43,7 @@ jobs: sudo apt-get update sudo apt-get install -y bibtool - # if you update this step (or its dependencies), please also update them in bot_fix_style_comment.yaml + # if you update this step (or its dependencies), please also update them in bot_fix_style.yaml - name: lint references.bib run: | # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions @@ -72,9 +72,9 @@ jobs: ./elan-init -y --default-toolchain none echo "$HOME/.elan/bin" >> "${GITHUB_PATH}" - # if you update this step (or its dependencies), please also update them in bot_fix_style_comment.yaml + # if you update this step (or its dependencies), please also update them in bot_fix_style.yaml - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - run: + run: # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions lake exe mk_all || true From 71e670b6034537743f154aacb706a8d568216c54 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Thu, 16 Jan 2025 12:28:53 +0000 Subject: [PATCH 266/681] feat(Combinatorics/SimpleGraph): vertices in cycles (#20602) This adds various lemmas on vertices in cycles: Non-equality, and the exact neighbors and size of the neighborSet, along with some smaller supporting lemmas for walks. In preparation for Tutte's theorem. Co-authored-by: Pim Otte --- .../SimpleGraph/Connectivity/Subgraph.lean | 61 ++++++++++++++++++ Mathlib/Combinatorics/SimpleGraph/Path.lean | 62 +++++++++++++++++++ Mathlib/Combinatorics/SimpleGraph/Walk.lean | 4 ++ 3 files changed, 127 insertions(+) diff --git a/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean b/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean index e8007002668f3..352990904c131 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller, Rémi Bottinelli -/ import Mathlib.Combinatorics.SimpleGraph.Path +import Mathlib.Data.Set.Card /-! # Connectivity of subgraphs and induced graphs @@ -196,6 +197,15 @@ theorem toSubgraph_adj_getVert {u v} (w : G.Walk u v) {i : ℕ} (hi : i < w.leng right exact ih (Nat.succ_lt_succ_iff.mp hi) +theorem toSubgraph_adj_snd {u v} (w : G.Walk u v) (h : ¬ w.Nil) : w.toSubgraph.Adj u w.snd := by + simpa using w.toSubgraph_adj_getVert (not_nil_iff_lt_length.mp h) + +theorem toSubgraph_adj_penultimate {u v} (w : G.Walk u v) (h : ¬ w.Nil) : + w.toSubgraph.Adj w.penultimate v := by + rw [not_nil_iff_lt_length] at h + simpa [show w.length - 1 + 1 = w.length from by omega] + using w.toSubgraph_adj_getVert (by omega : w.length - 1 < w.length) + theorem toSubgraph_adj_iff {u v u' v'} (w : G.Walk u v) : w.toSubgraph.Adj u' v' ↔ ∃ i, s(w.getVert i, w.getVert (i + 1)) = s(u', v') ∧ i < w.length := by @@ -228,6 +238,57 @@ theorem toSubgraph_adj_iff {u v u' v'} (w : G.Walk u v) : rw [← Subgraph.mem_edgeSet, ← hi.1, Subgraph.mem_edgeSet] exact toSubgraph_adj_getVert _ hi.2 +namespace IsCycle + +lemma neighborSet_toSubgraph_endpoint {u} {p : G.Walk u u} (hpc : p.IsCycle) : + p.toSubgraph.neighborSet u = {p.snd, p.penultimate} := by + have hadj1 := p.toSubgraph_adj_snd hpc.not_nil + have hadj2 := (p.toSubgraph_adj_penultimate hpc.not_nil).symm + ext v + simp_all only [Subgraph.mem_neighborSet, Set.mem_insert_iff, Set.mem_singleton_iff, + SimpleGraph.Walk.toSubgraph_adj_iff, Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk] + refine ⟨?_, by aesop⟩ + rintro ⟨i, (hl | hr)⟩ + · rw [hpc.getVert_endpoint_iff (by omega)] at hl + cases hl.1 <;> aesop + · cases' (hpc.getVert_endpoint_iff (by omega)).mp hr.2 with h1 h2 + · contradiction + · simp only [penultimate, ← h2, add_tsub_cancel_right] + aesop + +lemma neighborSet_toSubgraph_internal {u} {i : ℕ} {p : G.Walk u u} (hpc : p.IsCycle) + (h : i ≠ 0) (h' : i < p.length) : + p.toSubgraph.neighborSet (p.getVert i) = {p.getVert (i - 1), p.getVert (i + 1)} := by + have hadj1 := ((show i - 1 + 1 = i from by omega) ▸ + p.toSubgraph_adj_getVert (by omega : (i - 1) < p.length)).symm + have hadj2 := p.toSubgraph_adj_getVert (by omega : i < p.length) + ext v + simp_all only [ne_eq, Subgraph.mem_neighborSet, Set.mem_insert_iff, Set.mem_singleton_iff, + SimpleGraph.Walk.toSubgraph_adj_iff, Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, + Prod.swap_prod_mk] + refine ⟨?_, by aesop⟩ + rintro ⟨i', (⟨hl1, hl2⟩ | ⟨hr1, hr2⟩)⟩ + · apply hpc.getVert_injOn' (by rw [Set.mem_setOf_eq]; omega) + (by rw [Set.mem_setOf_eq]; omega) at hl1 + aesop + · apply hpc.getVert_injOn (by rw [Set.mem_setOf_eq]; omega) + (by rw [Set.mem_setOf_eq]; omega) at hr2 + aesop + +lemma ncard_neighborSet_toSubgraph_eq_two {u v} {p : G.Walk u u} (hpc : p.IsCycle) + (h : v ∈ p.support) : (p.toSubgraph.neighborSet v).ncard = 2 := by + simp only [SimpleGraph.Walk.mem_support_iff_exists_getVert] at h ⊢ + obtain ⟨i, hi⟩ := h + by_cases he : i = 0 ∨ i = p.length + · have huv : u = v := by aesop + rw [← huv, hpc.neighborSet_toSubgraph_endpoint] + exact Set.ncard_pair hpc.snd_ne_penultimate + push_neg at he + rw [← hi.1, hpc.neighborSet_toSubgraph_internal he.1 (by omega)] + exact Set.ncard_pair (hpc.getVert_sub_one_neq_getVert_add_one (by omega)) + +end IsCycle + end Walk namespace Subgraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Path.lean b/Mathlib/Combinatorics/SimpleGraph/Path.lean index 25c395c316dff..6487fc983ad0a 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Path.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Path.lean @@ -242,6 +242,12 @@ lemma IsCycle.three_le_length {v : V} {p : G.Walk v v} (hp : p.IsCycle) : 3 ≤ | .cons _ (.cons _ .nil) => simp at hp | .cons _ (.cons _ (.cons _ _)) => simp_rw [SimpleGraph.Walk.length_cons]; omega +lemma not_nil_of_isCycle_cons {p : G.Walk u v} {h : G.Adj v u} (hc : (Walk.cons h p).IsCycle) : + ¬ p.Nil := by + have := Walk.length_cons _ _ ▸ Walk.IsCycle.three_le_length hc + rw [Walk.not_nil_iff_lt_length] + omega + theorem cons_isCycle_iff {u v : V} (p : G.Walk v u) (h : G.Adj u v) : (Walk.cons h p).IsCycle ↔ p.IsPath ∧ ¬s(u, v) ∈ p.edges := by simp only [Walk.isCycle_def, Walk.isPath_def, Walk.isTrail_def, edges_cons, List.nodup_cons, @@ -295,6 +301,62 @@ lemma IsPath.getVert_injOn {p : G.Walk u v} (hp : p.IsPath) : (by omega : (m - 1) ≤ p.length) hnm omega +/-! ### About cycles -/ + +-- TODO: These results could possibly be less laborious with a periodic function getCycleVert +lemma IsCycle.getVert_injOn {p : G.Walk u u} (hpc : p.IsCycle) : + Set.InjOn p.getVert {i | 1 ≤ i ∧ i ≤ p.length} := by + rw [← p.cons_tail_eq hpc.not_nil] at hpc + intro n hn m hm hnm + rw [← SimpleGraph.Walk.length_tail_add_one + (p.not_nil_of_tail_not_nil (not_nil_of_isCycle_cons hpc)), Set.mem_setOf] at hn hm + have := ((Walk.cons_isCycle_iff _ _).mp hpc).1.getVert_injOn + (by omega : n - 1 ≤ p.tail.length) (by omega : m - 1 ≤ p.tail.length) + (by simp_all [SimpleGraph.Walk.getVert_tail, show n - 1 + 1 = n from by omega, + show m - 1 + 1 = m from by omega]) + omega + +lemma IsCycle.getVert_injOn' {p : G.Walk u u} (hpc : p.IsCycle) : + Set.InjOn p.getVert {i | i ≤ p.length - 1} := by + intro n hn m hm hnm + simp only [Walk.length_reverse, Set.mem_setOf_eq, Nat.sub_le, and_true] at * + have := hpc.three_le_length + have : p.length - n = p.length - m := Walk.length_reverse _ ▸ hpc.reverse.getVert_injOn + (by simp only [Walk.length_reverse, Set.mem_setOf_eq]; omega) + (by simp only [Walk.length_reverse, Set.mem_setOf_eq]; omega) + (by simp [Walk.getVert_reverse, show p.length - (p.length - n) = n from by omega, hnm, + show p.length - (p.length - m) = m from by omega]) + omega + +lemma IsCycle.snd_ne_penultimate {p : G.Walk u u} (hp : p.IsCycle) : p.snd ≠ p.penultimate := by + intro h + have := hp.three_le_length + apply hp.getVert_injOn (by simp; omega) (by simp; omega) at h + omega + +lemma IsCycle.getVert_endpoint_iff {i : ℕ} {p : G.Walk u u} (hpc : p.IsCycle) (hl : i ≤ p.length) : + p.getVert i = u ↔ i = 0 ∨ i = p.length := by + refine ⟨?_, by aesop⟩ + intro h + by_cases hi : i = 0 + · left; exact hi + · right + exact hpc.getVert_injOn (by simp only [Set.mem_setOf_eq]; omega) + (by simp only [Set.mem_setOf_eq]; omega) (h.symm ▸ (Walk.getVert_length p).symm) + +lemma IsCycle.getVert_sub_one_neq_getVert_add_one {i : ℕ} {p : G.Walk u u} (hpc : p.IsCycle) + (h : i ≤ p.length) : p.getVert (i - 1) ≠ p.getVert (i + 1) := by + have hl := hpc.three_le_length + by_cases hi' : i ≥ p.length - 1 + · intro h' + rw [p.getVert_of_length_le (by omega : p.length ≤ i + 1), + hpc.getVert_endpoint_iff (by omega)] at h' + omega + intro h' + have := hpc.getVert_injOn' (by simp only [Set.mem_setOf_eq, Nat.sub_le_iff_le_add]; omega) + (by simp only [Set.mem_setOf_eq]; omega) h' + omega + /-! ### Walk decompositions -/ section WalkDecomp diff --git a/Mathlib/Combinatorics/SimpleGraph/Walk.lean b/Mathlib/Combinatorics/SimpleGraph/Walk.lean index af48c233e9bcd..935f0c84e508f 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Walk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Walk.lean @@ -921,6 +921,10 @@ lemma cons_tail_eq (p : G.Walk x y) (hp : ¬ p.Nil) : p.tail.length + 1 = p.length := by rw [← length_cons, cons_tail_eq _ hp] +protected lemma Nil.tail {p : G.Walk v w} (hp : p.Nil) : p.tail.Nil := by cases p <;> aesop + +lemma not_nil_of_tail_not_nil {p : G.Walk v w} (hp : ¬ p.tail.Nil) : ¬ p.Nil := mt Nil.tail hp + @[simp] lemma nil_copy {x' y' : V} {p : G.Walk x y} (hx : x = x') (hy : y = y') : (p.copy hx hy).Nil = p.Nil := by subst_vars; rfl From 84b31f6569ca247071ad16405b56d112834973c8 Mon Sep 17 00:00:00 2001 From: Nailin Guan <150537269+Thmoas-Guan@users.noreply.github.com> Date: Thu, 16 Jan 2025 12:40:23 +0000 Subject: [PATCH 267/681] feat(Topology/Group/Profinite): Profinite group is limit of finite group (#16992) Prove that any profinite group is limit of finite groups. --- Mathlib.lean | 1 + Mathlib/Algebra/Group/Subgroup/Basic.lean | 9 ++ .../Algebra/Category/ProfiniteGrp/Basic.lean | 9 ++ .../Algebra/Category/ProfiniteGrp/Limits.lean | 149 ++++++++++++++++++ Mathlib/Topology/Algebra/ClopenNhdofOne.lean | 13 ++ Mathlib/Topology/Algebra/OpenSubgroup.lean | 4 +- 6 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean diff --git a/Mathlib.lean b/Mathlib.lean index 54a5940c1615a..36f52b049b9b6 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5097,6 +5097,7 @@ import Mathlib.Topology.Algebra.Affine import Mathlib.Topology.Algebra.Algebra import Mathlib.Topology.Algebra.Algebra.Rat import Mathlib.Topology.Algebra.Category.ProfiniteGrp.Basic +import Mathlib.Topology.Algebra.Category.ProfiniteGrp.Limits import Mathlib.Topology.Algebra.ClopenNhdofOne import Mathlib.Topology.Algebra.ClosedSubgroup import Mathlib.Topology.Algebra.ConstMulAction diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index d1c6c4df4c96f..24c0f1946cbfa 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -849,6 +849,15 @@ theorem inf_subgroupOf_inf_normal_of_left {A' A : Subgroup G} (B : Subgroup G) ( instance normal_inf_normal (H K : Subgroup G) [hH : H.Normal] [hK : K.Normal] : (H ⊓ K).Normal := ⟨fun n hmem g => ⟨hH.conj_mem n hmem.1 g, hK.conj_mem n hmem.2 g⟩⟩ +@[to_additive] +theorem normal_iInf_normal {ι : Type*} {a : ι → Subgroup G} + (norm : ∀ i : ι , (a i).Normal) : (iInf a).Normal := by + constructor + intro g g_in_iInf h + rw [Subgroup.mem_iInf] at g_in_iInf ⊢ + intro i + exact (norm i).conj_mem g (g_in_iInf i) h + @[to_additive] theorem SubgroupNormal.mem_comm {H K : Subgroup G} (hK : H ≤ K) [hN : (H.subgroupOf K).Normal] {a b : G} (hb : b ∈ K) (h : a * b ∈ H) : b * a ∈ H := by diff --git a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean index c61566db4fee5..8abe8c4e96962 100644 --- a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean +++ b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean @@ -25,6 +25,14 @@ disconnected. * `ofClosedSubgroup` : A closed subgroup of a profinite group is profinite. +# TODO + +As discussion in `https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Refactor.20 +Category.20of.20ProfiniteGrp.20and.20ContinuousMulEquiv/near/493290115` + +* Refactor the category of `ProfiniteGrp` into one-field structure as in `AlgebraCat` + +* Prove `(forget ProfiniteGrp.{u}).ReflectsIsomorphisms` using `profiniteGrpToProfinite` -/ universe u v @@ -68,6 +76,7 @@ instance : CoeSort ProfiniteGrp (Type u) where attribute [instance] group topologicalGroup ProfiniteAddGrp.addGroup ProfiniteAddGrp.topologicalAddGroup +--TODO: Refactor into one-field structure as in `AlgebraCat` @[to_additive] instance : Category ProfiniteGrp where Hom A B := ContinuousMonoidHom A B diff --git a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean new file mode 100644 index 0000000000000..d231af692dbf8 --- /dev/null +++ b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean @@ -0,0 +1,149 @@ +/- +Copyright (c) 2024 Nailin Guan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Nailin Guan, Youle Fang, Jujian Zhang, Yuyang Zhao +-/ +import Mathlib.Topology.Algebra.Category.ProfiniteGrp.Basic +import Mathlib.Topology.Algebra.ClopenNhdofOne + +/-! +# A profinite group is the projective limit of finite groups + +We define the topological group isomorphism between a profinite group and the projective limit of +its quotients by open normal subgroups. + +## Main definitions + +* `toFiniteQuotientFunctor` : The functor from `OpenNormalSubgroup P` to `FiniteGrp` + sending an open normal subgroup `U` to `P ⧸ U`, where `P : ProfiniteGrp`. + +* `toLimit` : The continuous homomorphism from a profinite group `P` to + the projective limit of its quotients by open normal subgroups ordered by inclusion. + +* `ContinuousMulEquivLimittoFiniteQuotientFunctor` : The `toLimit` is a + `ContinuousMulEquiv` + +## Main Statements + +* `OpenNormalSubgroupSubClopenNhdsOfOne` : For any open neighborhood of `1` there is an + open normal subgroup contained in it. + +-/ + +universe u + +open CategoryTheory TopologicalGroup + +namespace ProfiniteGrp + +instance (P : ProfiniteGrp) : SmallCategory (OpenNormalSubgroup P) := + Preorder.smallCategory (OpenNormalSubgroup ↑P.toProfinite.toTop) + +/-- The functor from `OpenNormalSubgroup P` to `FiniteGrp` sending `U` to `P ⧸ U`, +where `P : ProfiniteGrp`. -/ +def toFiniteQuotientFunctor (P : ProfiniteGrp) : OpenNormalSubgroup P ⥤ FiniteGrp := { + obj := fun H => FiniteGrp.of (P ⧸ H.toSubgroup) + map := fun fHK => QuotientGroup.map _ _ (.id _) (leOfHom fHK) + map_id _ := QuotientGroup.map_id _ + map_comp f g := (QuotientGroup.map_comp_map + _ _ _ (.id _) (.id _) (leOfHom f) (leOfHom g)).symm } + +/--The `MonoidHom` from a profinite group `P` to the projective limit of its quotients by +open normal subgroups ordered by inclusion.-/ +def toLimit_fun (P : ProfiniteGrp.{u}) : P →* + limit (toFiniteQuotientFunctor P ⋙ forget₂ FiniteGrp ProfiniteGrp) where + toFun p := ⟨fun _ => QuotientGroup.mk p, fun _ => rfl⟩ + map_one' := Subtype.val_inj.mp rfl + map_mul' _ _ := Subtype.val_inj.mp rfl + +lemma toLimit_fun_continuous (P : ProfiniteGrp.{u}) : Continuous (toLimit_fun P) := by + apply continuous_induced_rng.mpr (continuous_pi _) + intro H + dsimp only [Functor.comp_obj, CompHausLike.toCompHausLike_obj, CompHausLike.compHausLikeToTop_obj, + CompHausLike.coe_of, Functor.comp_map, CompHausLike.toCompHausLike_map, + CompHausLike.compHausLikeToTop_map, Set.mem_setOf_eq, toLimit_fun, + MonoidHom.coe_mk, OneHom.coe_mk, Function.comp_apply] + apply Continuous.mk + intro s _ + rw [← (Set.biUnion_preimage_singleton QuotientGroup.mk s)] + refine isOpen_iUnion (fun i ↦ isOpen_iUnion (fun _ ↦ ?_)) + convert IsOpen.leftCoset H.toOpenSubgroup.isOpen' (Quotient.out i) + ext x + simp only [Set.mem_preimage, Set.mem_singleton_iff] + nth_rw 1 [← QuotientGroup.out_eq' i, eq_comm, QuotientGroup.eq] + exact Iff.symm (Set.mem_smul_set_iff_inv_smul_mem) + +/-- The morphism in the category of `ProfiniteGrp` from a profinite group `P` to +the projective limit of its quotients by open normal subgroups ordered by inclusion.-/ +def toLimit (P : ProfiniteGrp.{u}) : P ⟶ + limit (toFiniteQuotientFunctor P ⋙ forget₂ FiniteGrp ProfiniteGrp) := { + toLimit_fun P with + continuous_toFun := toLimit_fun_continuous P } + +/--An auxiliary result, superceded by `toLimit_surjective`.-/ +theorem denseRange_toLimit (P : ProfiniteGrp.{u}) : DenseRange (toLimit P) := by + apply dense_iff_inter_open.mpr + rintro U ⟨s, hsO, hsv⟩ ⟨⟨spc, hspc⟩, uDefaultSpec⟩ + simp_rw [← hsv, Set.mem_preimage] at uDefaultSpec + rcases (isOpen_pi_iff.mp hsO) _ uDefaultSpec with ⟨J, fJ, hJ1, hJ2⟩ + let M := iInf (fun (j : J) => j.1.1.1) + have hM : M.Normal := Subgroup.normal_iInf_normal fun j => j.1.isNormal' + have hMOpen : IsOpen (M : Set P) := by + rw [Subgroup.coe_iInf] + exact isOpen_iInter_of_finite fun i => i.1.1.isOpen' + let m : OpenNormalSubgroup P := { M with isOpen' := hMOpen } + rcases QuotientGroup.mk'_surjective M (spc m) with ⟨origin, horigin⟩ + use (toLimit P).toFun origin + refine ⟨?_, origin, rfl⟩ + rw [← hsv] + apply hJ2 + intro a a_in_J + let M_to_Na : m ⟶ a := (iInf_le (fun (j : J) => j.1.1.1) ⟨a, a_in_J⟩).hom + rw [← (P.toLimit.toFun origin).property M_to_Na] + show (P.toFiniteQuotientFunctor.map M_to_Na) (QuotientGroup.mk' M origin) ∈ _ + rw [horigin] + exact Set.mem_of_eq_of_mem (hspc M_to_Na) (hJ1 a a_in_J).2 + +theorem toLimit_surjective (P : ProfiniteGrp.{u}) : Function.Surjective (toLimit P) := by + have : IsClosed (Set.range P.toLimit) := + P.toLimit.continuous_toFun.isClosedMap.isClosed_range + rw [← Set.range_eq_univ, ← closure_eq_iff_isClosed.mpr this, + Dense.closure_eq (denseRange_toLimit P)] + +theorem toLimit_injective (P : ProfiniteGrp.{u}) : Function.Injective (toLimit P) := by + show Function.Injective (toLimit P).toMonoidHom + rw [← MonoidHom.ker_eq_bot_iff, Subgroup.eq_bot_iff_forall] + intro x h + by_contra xne1 + rcases exist_openNormalSubgroup_sub_open_nhd_of_one (isOpen_compl_singleton) + (Set.mem_compl_singleton_iff.mpr fun a => xne1 a.symm) with ⟨H, hH⟩ + exact hH ((QuotientGroup.eq_one_iff x).mp (congrFun (Subtype.val_inj.mpr h) H)) rfl + +/-- The topological group isomorphism between a profinite group and the projective limit of +its quotients by open normal subgroups -/ +noncomputable def continuousMulEquivLimittoFiniteQuotientFunctor (P : ProfiniteGrp.{u}) : + P ≃ₜ* (limit (toFiniteQuotientFunctor P ⋙ forget₂ FiniteGrp ProfiniteGrp)) := { + (Continuous.homeoOfEquivCompactToT2 (f := Equiv.ofBijective _ + ⟨toLimit_injective P, toLimit_surjective P⟩) + P.toLimit.continuous_toFun) + with + map_mul' := (toLimit P).map_mul' } + +--TODO : Refactor using `(forget ProfiniteGrp.{u}).ReflectsIsomorphisms` after it is proved. +/-- The isomorphism in the category of profinite group between a profinite group and +the projective limit of its quotients by open normal subgroups -/ +noncomputable def isoLimittoFiniteQuotientFunctor (P : ProfiniteGrp.{u}) : + P ≅ (limit (toFiniteQuotientFunctor P ⋙ forget₂ FiniteGrp ProfiniteGrp)) where + hom := P.toLimit + inv := { (continuousMulEquivLimittoFiniteQuotientFunctor P).symm.toMonoidHom with + continuous_toFun := (continuousMulEquivLimittoFiniteQuotientFunctor P).continuous_invFun} + hom_inv_id := by + ext x + exact ContinuousMulEquiv.symm_apply_apply + (continuousMulEquivLimittoFiniteQuotientFunctor P) x + inv_hom_id := by + ext x + exact ContinuousMulEquiv.apply_symm_apply + (continuousMulEquivLimittoFiniteQuotientFunctor P) x + +end ProfiniteGrp diff --git a/Mathlib/Topology/Algebra/ClopenNhdofOne.lean b/Mathlib/Topology/Algebra/ClopenNhdofOne.lean index 008bc484f08ed..02b7e4bbba5ff 100644 --- a/Mathlib/Topology/Algebra/ClopenNhdofOne.lean +++ b/Mathlib/Topology/Algebra/ClopenNhdofOne.lean @@ -6,6 +6,7 @@ Authors: Nailin Guan, Yi Song, Xuchun Li import Mathlib.GroupTheory.Index import Mathlib.Topology.Algebra.ClosedSubgroup import Mathlib.Topology.Algebra.OpenSubgroup +import Mathlib.Topology.Separation.Profinite /-! # Existence of an open normal subgroup in any clopen neighborhood of the neutral element @@ -28,3 +29,15 @@ theorem exist_openNormalSubgroup_sub_clopen_nhd_of_one {G : Type*} [Group G] [To exact fun _ b ↦ hH (H.normalCore_le b) end TopologicalGroup + +namespace ProfiniteGrp + +theorem exist_openNormalSubgroup_sub_open_nhd_of_one {G : Type*} [Group G] [TopologicalSpace G] + [TopologicalGroup G] [CompactSpace G] [TotallyDisconnectedSpace G] {U : Set G} + (UOpen : IsOpen U) (einU : 1 ∈ U) : ∃ H : OpenNormalSubgroup G, (H : Set G) ⊆ U := by + rcases ((Filter.HasBasis.mem_iff' ((nhds_basis_clopen (1 : G))) U ).mp <| + mem_nhds_iff.mpr (by use U)) with ⟨W, hW, h⟩ + rcases TopologicalGroup.exist_openNormalSubgroup_sub_clopen_nhd_of_one hW.2 hW.1 with ⟨H, hH⟩ + exact ⟨H, fun _ a ↦ h (hH a)⟩ + +end ProfiniteGrp diff --git a/Mathlib/Topology/Algebra/OpenSubgroup.lean b/Mathlib/Topology/Algebra/OpenSubgroup.lean index 2e9870f9de1f2..30d3bc8214c83 100644 --- a/Mathlib/Topology/Algebra/OpenSubgroup.lean +++ b/Mathlib/Topology/Algebra/OpenSubgroup.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, Nailin Guan +Authors: Johan Commelin, Nailin Guan, Yi Song, Xuchun Li -/ import Mathlib.Algebra.Module.Submodule.Lattice import Mathlib.RingTheory.Ideal.Defs @@ -10,7 +10,7 @@ import Mathlib.Topology.Algebra.Ring.Basic import Mathlib.Topology.Sets.Opens /-! -# Open subgroups of a topological groups +# Open subgroups of a topological group This files builds the lattice `OpenSubgroup G` of open subgroups in a topological group `G`, and its additive version `OpenAddSubgroup`. This lattice has a top element, the subgroup of all From 94099b4e3e03fbb365bb797d566a2168442c7a34 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 16 Jan 2025 12:40:25 +0000 Subject: [PATCH 268/681] chore: cleanup .gitignore files (#20795) --- .gitignore | 11 +++-------- DownstreamTest/.gitignore | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 9f41205d619e2..8cf42ebd21477 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,6 @@ # macOS leaves these files everywhere: .DS_Store # Created by `lake exe cache get` if no home directory is available -/.cache -# Prior to v4.3.0-rc2 lake stored files in these locations. -# We'll leave them in the `.gitignore` for a while for users switching between toolchains. -/build/ -/lake-packages/ -/lakefile.olean -# After v4.3.0-rc2 lake stores its files here: -/.lake/ +.cache +# `lake` stores its files here: +.lake diff --git a/DownstreamTest/.gitignore b/DownstreamTest/.gitignore index 64729f11321a9..cc3330a574084 100644 --- a/DownstreamTest/.gitignore +++ b/DownstreamTest/.gitignore @@ -1,3 +1,3 @@ -/.lake +.lake lean-toolchain lake-manifest.json From 1e69b5acbe47cd4d59c3e5614e5a4ae81054839a Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Thu, 16 Jan 2025 15:33:23 +0000 Subject: [PATCH 269/681] feat(Set/Finite): a set is finite if its image and fibers are finite (#20751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A useful lemma from the disproof of the Aharoni–Korman conjecture, #20082. Note this does not seem to follow from any of the existing preimage finiteness lemmas. --- Mathlib/Data/Set/Finite/Lattice.lean | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Mathlib/Data/Set/Finite/Lattice.lean b/Mathlib/Data/Set/Finite/Lattice.lean index bfec945979328..fe3a7ec42f430 100644 --- a/Mathlib/Data/Set/Finite/Lattice.lean +++ b/Mathlib/Data/Set/Finite/Lattice.lean @@ -198,6 +198,16 @@ theorem union_finset_finite_of_range_finite (f : α → Finset β) (h : (range f end SetFiniteConstructors +/-- +If the image of `s` under `f` is finite, and each fiber of `f` has a finite intersection +with `s`, then `s` is itself finite. + +It is useful to give `f` explicitly here so this can be used with `apply`. +-/ +lemma Finite.of_finite_fibers (f : α → β) {s : Set α} (himage : (f '' s).Finite) + (hfibers : ∀ x ∈ f '' s, (s ∩ f ⁻¹' {x}).Finite) : s.Finite := + (himage.biUnion hfibers).subset fun x ↦ by aesop + /-! ### Properties -/ theorem finite_subset_iUnion {s : Set α} (hs : s.Finite) {ι} {t : ι → Set α} (h : s ⊆ ⋃ i, t i) : From 78512f52a0949ede16aa5b246099d9f1c74a98cd Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Thu, 16 Jan 2025 16:08:08 +0000 Subject: [PATCH 270/681] feat(Order/WellFoundedSet): add convenience constructors for IsWF and IsPWO for WellFoundedLT types (#20752) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A useful lemma from the disproof of the Aharoni–Korman conjecture, https://github.com/leanprover-community/mathlib4/pull/20082. While these are easy to inline, they are hard to discover for an end user, since `WellFoundedLT` is never mentioned in this file. As such, this change improves discoverability, especially with `exact?`. --- Mathlib/Order/WellFoundedSet.lean | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Mathlib/Order/WellFoundedSet.lean b/Mathlib/Order/WellFoundedSet.lean index b021f89341c75..e0c2c0ea13063 100644 --- a/Mathlib/Order/WellFoundedSet.lean +++ b/Mathlib/Order/WellFoundedSet.lean @@ -208,6 +208,9 @@ theorem isWF_univ_iff : IsWF (univ : Set α) ↔ WellFounded ((· < ·) : α → theorem IsWF.mono (h : IsWF t) (st : s ⊆ t) : IsWF s := h.subset st +lemma IsWF.of_wellFoundedLT [WellFoundedLT α] : IsWF s := + (isWF_univ_iff.2 wellFounded_lt).mono (subset_univ _) + end LT section Preorder @@ -506,6 +509,12 @@ protected theorem IsWF.isPWO (hs : s.IsWF) : s.IsPWO := by theorem isWF_iff_isPWO : s.IsWF ↔ s.IsPWO := ⟨IsWF.isPWO, IsPWO.isWF⟩ +/-- +If `α` is a linear order with well-founded `<`, then any set in it is a partially well-ordered set. +Note this does not hold without the linearity assumption. +-/ +lemma IsPWO.of_linearOrder [WellFoundedLT α] : s.IsPWO := IsWF.of_wellFoundedLT.isPWO + end LinearOrder end Set From 0d3784625d21570a7f5e475ae27e34177107f6c3 Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Thu, 16 Jan 2025 16:08:09 +0000 Subject: [PATCH 271/681] feat(Data/Finset/Card): add `InjOn` and `SurjOn` versions of finset cardinality lemmas (#20753) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These lemmas are useful for dot notation, and help the interface between Set predicates and Finset cardinality. In this PR we: - Add two new lemmas for non-dependent functions, spelled with Set predicates - Use them to golf the dependent versions and improve readability Useful from the disproof of the Aharoni–Korman conjecture, https://github.com/leanprover-community/mathlib4/pull/20082. --- Mathlib/Data/Finset/Card.lean | 51 ++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index 5395494d7237a..9c9758dc56612 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -431,38 +431,39 @@ lemma le_card_of_inj_on_range (f : ℕ → α) (hf : ∀ i < n, f i ∈ s) n = #(range n) := (card_range n).symm _ ≤ #s := card_le_card_of_injOn f (by simpa only [mem_range]) (by simpa) +lemma surjOn_of_injOn_of_card_le (f : α → β) (hf : Set.MapsTo f s t) (hinj : Set.InjOn f s) + (hst : #t ≤ #s) : Set.SurjOn f s t := by + classical + suffices s.image f = t by simp [← this, Set.SurjOn] + have : s.image f ⊆ t := by aesop (add simp Finset.subset_iff) + exact eq_of_subset_of_card_le this (hst.trans_eq (card_image_of_injOn hinj).symm) + lemma surj_on_of_inj_on_of_card_le (f : ∀ a ∈ s, β) (hf : ∀ a ha, f a ha ∈ t) (hinj : ∀ a₁ a₂ ha₁ ha₂, f a₁ ha₁ = f a₂ ha₂ → a₁ = a₂) (hst : #t ≤ #s) : ∀ b ∈ t, ∃ a ha, b = f a ha := by + let f' : s → β := fun a ↦ f a a.2 + have hinj' : Set.InjOn f' s.attach := fun x hx y hy hxy ↦ Subtype.ext (hinj _ _ x.2 y.2 hxy) + have hmapsto' : Set.MapsTo f' s.attach t := fun x hx ↦ hf _ _ + intro b hb + obtain ⟨a, ha, rfl⟩ := surjOn_of_injOn_of_card_le _ hmapsto' hinj' (by rwa [card_attach]) hb + exact ⟨a, a.2, rfl⟩ + +lemma injOn_of_surjOn_of_card_le (f : α → β) (hf : Set.MapsTo f s t) (hsurj : Set.SurjOn f s t) + (hst : #s ≤ #t) : Set.InjOn f s := by classical - have h : #(s.attach.image fun a : s ↦ f a a.2) = #s := by - rw [← @card_attach _ s, card_image_of_injective] - intro ⟨_, _⟩ ⟨_, _⟩ h - exact Subtype.eq <| hinj _ _ _ _ h - obtain rfl : image (fun a : { a // a ∈ s } => f a a.prop) s.attach = t := - eq_of_subset_of_card_le (image_subset_iff.2 <| by simpa) (by simp [hst, h]) - simp only [mem_image, mem_attach, true_and, Subtype.exists, forall_exists_index] - exact fun b a ha hb ↦ ⟨a, ha, hb.symm⟩ + have : s.image f = t := Finset.coe_injective <| by simp [hsurj.image_eq_of_mapsTo hf] + have : #(s.image f) = #t := by rw [this] + have : #(s.image f) ≤ #s := card_image_le + rw [← card_image_iff] + omega theorem inj_on_of_surj_on_of_card_le (f : ∀ a ∈ s, β) (hf : ∀ a ha, f a ha ∈ t) (hsurj : ∀ b ∈ t, ∃ a ha, f a ha = b) (hst : #s ≤ #t) ⦃a₁⦄ (ha₁ : a₁ ∈ s) ⦃a₂⦄ - (ha₂ : a₂ ∈ s) (ha₁a₂ : f a₁ ha₁ = f a₂ ha₂) : a₁ = a₂ := - haveI : Inhabited { x // x ∈ s } := ⟨⟨a₁, ha₁⟩⟩ - let f' : { x // x ∈ s } → { x // x ∈ t } := fun x => ⟨f x.1 x.2, hf x.1 x.2⟩ - let g : { x // x ∈ t } → { x // x ∈ s } := - @surjInv _ _ f' fun x => - let ⟨y, hy₁, hy₂⟩ := hsurj x.1 x.2 - ⟨⟨y, hy₁⟩, Subtype.eq hy₂⟩ - have hg : Injective g := injective_surjInv _ - have hsg : Surjective g := fun x => - let ⟨y, hy⟩ := - surj_on_of_inj_on_of_card_le (fun (x : { x // x ∈ t }) (_ : x ∈ t.attach) => g x) - (fun x _ => show g x ∈ s.attach from mem_attach _ _) (fun _ _ _ _ hxy => hg hxy) (by simpa) - x (mem_attach _ _) - ⟨y, hy.snd.symm⟩ - have hif : Injective f' := - (leftInverse_of_surjective_of_rightInverse hsg (rightInverse_surjInv _)).injective - Subtype.ext_iff_val.1 (@hif ⟨a₁, ha₁⟩ ⟨a₂, ha₂⟩ (Subtype.eq ha₁a₂)) + (ha₂ : a₂ ∈ s) (ha₁a₂ : f a₁ ha₁ = f a₂ ha₂) : a₁ = a₂ := by + let f' : s → β := fun a ↦ f a a.2 + have hsurj' : Set.SurjOn f' s.attach t := fun x hx ↦ by simpa [f'] using hsurj x hx + have hinj' := injOn_of_surjOn_of_card_le f' (fun x hx ↦ hf _ _) hsurj' (by simpa) + exact congrArg Subtype.val (@hinj' ⟨a₁, ha₁⟩ (by simp) ⟨a₂, ha₂⟩ (by simp) ha₁a₂) end bij From fc139ddc9a65c27a3137fde26be8ef3beae73aec Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Thu, 16 Jan 2025 21:58:53 +0000 Subject: [PATCH 272/681] chore(Mathlib/Computability/TuringMachine): split file (#20790) This PR splits `Mathlib/Computability/TuringMachine` by moving to a new file the initial 600 or so lines, which deal with the definition of the tape data structure that a Turing machine uses. This reduces the size of this large file to less than 2100 lines. Co-authored-by: Kim Morrison --- Mathlib.lean | 1 + Mathlib/Computability/Tape.lean | 620 +++++++++++++++++++++++ Mathlib/Computability/TuringMachine.lean | 586 +-------------------- 3 files changed, 623 insertions(+), 584 deletions(-) create mode 100644 Mathlib/Computability/Tape.lean diff --git a/Mathlib.lean b/Mathlib.lean index 36f52b049b9b6..ea033a276b7cd 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2378,6 +2378,7 @@ import Mathlib.Computability.Reduce import Mathlib.Computability.RegularExpressions import Mathlib.Computability.TMComputable import Mathlib.Computability.TMToPartrec +import Mathlib.Computability.Tape import Mathlib.Computability.TuringMachine import Mathlib.Condensed.AB import Mathlib.Condensed.Basic diff --git a/Mathlib/Computability/Tape.lean b/Mathlib/Computability/Tape.lean new file mode 100644 index 0000000000000..64bf4d02f6936 --- /dev/null +++ b/Mathlib/Computability/Tape.lean @@ -0,0 +1,620 @@ +/- +Copyright (c) 2018 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro +-/ +import Mathlib.Data.Vector.Basic +import Mathlib.Logic.Function.Iterate +import Mathlib.Order.Basic +import Mathlib.Tactic.ApplyFun +import Mathlib.Data.List.GetD + +/-! +# Turing machine tapes + +This file defines the notion of a Turing machine tape, and the operations on it. A tape is a +bidirectional infinite sequence of cells, each of which stores an element of a given alphabet `Γ`. +All but finitely many of the cells are required to hold the blank symbol `default : Γ`. + +## Main definitions + +* `ListBlank Γ` is the type of one-directional tapes with alphabet `Γ`. Implemented as a quotient + of `List Γ` by extension by blanks at the end. +* `Tape Γ` is the type of Turing machine tapes with alphabet `Γ`. Implemented as two + `ListBlank Γ` instances, one for each direction, as well as a head symbol. + +-/ + +assert_not_exists MonoidWithZero + +open Function (iterate_succ iterate_succ_apply iterate_zero_apply) + +namespace Turing + +section ListBlank + +/-- The `BlankExtends` partial order holds of `l₁` and `l₂` if `l₂` is obtained by adding +blanks (`default : Γ`) to the end of `l₁`. -/ +def BlankExtends {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) : Prop := + ∃ n, l₂ = l₁ ++ List.replicate n default + +@[refl] +theorem BlankExtends.refl {Γ} [Inhabited Γ] (l : List Γ) : BlankExtends l l := + ⟨0, by simp⟩ + +@[trans] +theorem BlankExtends.trans {Γ} [Inhabited Γ] {l₁ l₂ l₃ : List Γ} : + BlankExtends l₁ l₂ → BlankExtends l₂ l₃ → BlankExtends l₁ l₃ := by + rintro ⟨i, rfl⟩ ⟨j, rfl⟩ + exact ⟨i + j, by simp⟩ + +theorem BlankExtends.below_of_le {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} : + BlankExtends l l₁ → BlankExtends l l₂ → l₁.length ≤ l₂.length → BlankExtends l₁ l₂ := by + rintro ⟨i, rfl⟩ ⟨j, rfl⟩ h; use j - i + simp only [List.length_append, Nat.add_le_add_iff_left, List.length_replicate] at h + simp only [← List.replicate_add, Nat.add_sub_cancel' h, List.append_assoc] + +/-- Any two extensions by blank `l₁,l₂` of `l` have a common join (which can be taken to be the +longer of `l₁` and `l₂`). -/ +def BlankExtends.above {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} (h₁ : BlankExtends l l₁) + (h₂ : BlankExtends l l₂) : { l' // BlankExtends l₁ l' ∧ BlankExtends l₂ l' } := + if h : l₁.length ≤ l₂.length then ⟨l₂, h₁.below_of_le h₂ h, BlankExtends.refl _⟩ + else ⟨l₁, BlankExtends.refl _, h₂.below_of_le h₁ (le_of_not_ge h)⟩ + +theorem BlankExtends.above_of_le {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} : + BlankExtends l₁ l → BlankExtends l₂ l → l₁.length ≤ l₂.length → BlankExtends l₁ l₂ := by + rintro ⟨i, rfl⟩ ⟨j, e⟩ h; use i - j + refine List.append_cancel_right (e.symm.trans ?_) + rw [List.append_assoc, ← List.replicate_add, Nat.sub_add_cancel] + apply_fun List.length at e + simp only [List.length_append, List.length_replicate] at e + rwa [← Nat.add_le_add_iff_left, e, Nat.add_le_add_iff_right] + +/-- `BlankRel` is the symmetric closure of `BlankExtends`, turning it into an equivalence +relation. Two lists are related by `BlankRel` if one extends the other by blanks. -/ +def BlankRel {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) : Prop := + BlankExtends l₁ l₂ ∨ BlankExtends l₂ l₁ + +@[refl] +theorem BlankRel.refl {Γ} [Inhabited Γ] (l : List Γ) : BlankRel l l := + Or.inl (BlankExtends.refl _) + +@[symm] +theorem BlankRel.symm {Γ} [Inhabited Γ] {l₁ l₂ : List Γ} : BlankRel l₁ l₂ → BlankRel l₂ l₁ := + Or.symm + +@[trans] +theorem BlankRel.trans {Γ} [Inhabited Γ] {l₁ l₂ l₃ : List Γ} : + BlankRel l₁ l₂ → BlankRel l₂ l₃ → BlankRel l₁ l₃ := by + rintro (h₁ | h₁) (h₂ | h₂) + · exact Or.inl (h₁.trans h₂) + · rcases le_total l₁.length l₃.length with h | h + · exact Or.inl (h₁.above_of_le h₂ h) + · exact Or.inr (h₂.above_of_le h₁ h) + · rcases le_total l₁.length l₃.length with h | h + · exact Or.inl (h₁.below_of_le h₂ h) + · exact Or.inr (h₂.below_of_le h₁ h) + · exact Or.inr (h₂.trans h₁) + +/-- Given two `BlankRel` lists, there exists (constructively) a common join. -/ +def BlankRel.above {Γ} [Inhabited Γ] {l₁ l₂ : List Γ} (h : BlankRel l₁ l₂) : + { l // BlankExtends l₁ l ∧ BlankExtends l₂ l } := by + refine + if hl : l₁.length ≤ l₂.length then ⟨l₂, Or.elim h id fun h' ↦ ?_, BlankExtends.refl _⟩ + else ⟨l₁, BlankExtends.refl _, Or.elim h (fun h' ↦ ?_) id⟩ + · exact (BlankExtends.refl _).above_of_le h' hl + · exact (BlankExtends.refl _).above_of_le h' (le_of_not_ge hl) + +/-- Given two `BlankRel` lists, there exists (constructively) a common meet. -/ +def BlankRel.below {Γ} [Inhabited Γ] {l₁ l₂ : List Γ} (h : BlankRel l₁ l₂) : + { l // BlankExtends l l₁ ∧ BlankExtends l l₂ } := by + refine + if hl : l₁.length ≤ l₂.length then ⟨l₁, BlankExtends.refl _, Or.elim h id fun h' ↦ ?_⟩ + else ⟨l₂, Or.elim h (fun h' ↦ ?_) id, BlankExtends.refl _⟩ + · exact (BlankExtends.refl _).above_of_le h' hl + · exact (BlankExtends.refl _).above_of_le h' (le_of_not_ge hl) + +theorem BlankRel.equivalence (Γ) [Inhabited Γ] : Equivalence (@BlankRel Γ _) := + ⟨BlankRel.refl, @BlankRel.symm _ _, @BlankRel.trans _ _⟩ + +/-- Construct a setoid instance for `BlankRel`. -/ +def BlankRel.setoid (Γ) [Inhabited Γ] : Setoid (List Γ) := + ⟨_, BlankRel.equivalence _⟩ + +/-- A `ListBlank Γ` is a quotient of `List Γ` by extension by blanks at the end. This is used to +represent half-tapes of a Turing machine, so that we can pretend that the list continues +infinitely with blanks. -/ +def ListBlank (Γ) [Inhabited Γ] := + Quotient (BlankRel.setoid Γ) + +instance ListBlank.inhabited {Γ} [Inhabited Γ] : Inhabited (ListBlank Γ) := + ⟨Quotient.mk'' []⟩ + +instance ListBlank.hasEmptyc {Γ} [Inhabited Γ] : EmptyCollection (ListBlank Γ) := + ⟨Quotient.mk'' []⟩ + +/-- A modified version of `Quotient.liftOn'` specialized for `ListBlank`, with the stronger +precondition `BlankExtends` instead of `BlankRel`. -/ +protected abbrev ListBlank.liftOn {Γ} [Inhabited Γ] {α} (l : ListBlank Γ) (f : List Γ → α) + (H : ∀ a b, BlankExtends a b → f a = f b) : α := + l.liftOn' f <| by rintro a b (h | h) <;> [exact H _ _ h; exact (H _ _ h).symm] + +/-- The quotient map turning a `List` into a `ListBlank`. -/ +def ListBlank.mk {Γ} [Inhabited Γ] : List Γ → ListBlank Γ := + Quotient.mk'' + +@[elab_as_elim] +protected theorem ListBlank.induction_on {Γ} [Inhabited Γ] {p : ListBlank Γ → Prop} + (q : ListBlank Γ) (h : ∀ a, p (ListBlank.mk a)) : p q := + Quotient.inductionOn' q h + +/-- The head of a `ListBlank` is well defined. -/ +def ListBlank.head {Γ} [Inhabited Γ] (l : ListBlank Γ) : Γ := by + apply l.liftOn List.headI + rintro a _ ⟨i, rfl⟩ + cases a + · cases i <;> rfl + rfl + +@[simp] +theorem ListBlank.head_mk {Γ} [Inhabited Γ] (l : List Γ) : + ListBlank.head (ListBlank.mk l) = l.headI := + rfl + +/-- The tail of a `ListBlank` is well defined (up to the tail of blanks). -/ +def ListBlank.tail {Γ} [Inhabited Γ] (l : ListBlank Γ) : ListBlank Γ := by + apply l.liftOn (fun l ↦ ListBlank.mk l.tail) + rintro a _ ⟨i, rfl⟩ + refine Quotient.sound' (Or.inl ?_) + cases a + · cases' i with i <;> [exact ⟨0, rfl⟩; exact ⟨i, rfl⟩] + exact ⟨i, rfl⟩ + +@[simp] +theorem ListBlank.tail_mk {Γ} [Inhabited Γ] (l : List Γ) : + ListBlank.tail (ListBlank.mk l) = ListBlank.mk l.tail := + rfl + +/-- We can cons an element onto a `ListBlank`. -/ +def ListBlank.cons {Γ} [Inhabited Γ] (a : Γ) (l : ListBlank Γ) : ListBlank Γ := by + apply l.liftOn (fun l ↦ ListBlank.mk (List.cons a l)) + rintro _ _ ⟨i, rfl⟩ + exact Quotient.sound' (Or.inl ⟨i, rfl⟩) + +@[simp] +theorem ListBlank.cons_mk {Γ} [Inhabited Γ] (a : Γ) (l : List Γ) : + ListBlank.cons a (ListBlank.mk l) = ListBlank.mk (a :: l) := + rfl + +@[simp] +theorem ListBlank.head_cons {Γ} [Inhabited Γ] (a : Γ) : ∀ l : ListBlank Γ, (l.cons a).head = a := + Quotient.ind' fun _ ↦ rfl + +@[simp] +theorem ListBlank.tail_cons {Γ} [Inhabited Γ] (a : Γ) : ∀ l : ListBlank Γ, (l.cons a).tail = l := + Quotient.ind' fun _ ↦ rfl + +/-- The `cons` and `head`/`tail` functions are mutually inverse, unlike in the case of `List` where +this only holds for nonempty lists. -/ +@[simp] +theorem ListBlank.cons_head_tail {Γ} [Inhabited Γ] : ∀ l : ListBlank Γ, l.tail.cons l.head = l := by + apply Quotient.ind' + refine fun l ↦ Quotient.sound' (Or.inr ?_) + cases l + · exact ⟨1, rfl⟩ + · rfl + +/-- The `cons` and `head`/`tail` functions are mutually inverse, unlike in the case of `List` where +this only holds for nonempty lists. -/ +theorem ListBlank.exists_cons {Γ} [Inhabited Γ] (l : ListBlank Γ) : + ∃ a l', l = ListBlank.cons a l' := + ⟨_, _, (ListBlank.cons_head_tail _).symm⟩ + +/-- The n-th element of a `ListBlank` is well defined for all `n : ℕ`, unlike in a `List`. -/ +def ListBlank.nth {Γ} [Inhabited Γ] (l : ListBlank Γ) (n : ℕ) : Γ := by + apply l.liftOn (fun l ↦ List.getI l n) + rintro l _ ⟨i, rfl⟩ + cases' lt_or_le n _ with h h + · rw [List.getI_append _ _ _ h] + rw [List.getI_eq_default _ h] + rcases le_or_lt _ n with h₂ | h₂ + · rw [List.getI_eq_default _ h₂] + rw [List.getI_eq_getElem _ h₂, List.getElem_append_right h, List.getElem_replicate] + +@[simp] +theorem ListBlank.nth_mk {Γ} [Inhabited Γ] (l : List Γ) (n : ℕ) : + (ListBlank.mk l).nth n = l.getI n := + rfl + +@[simp] +theorem ListBlank.nth_zero {Γ} [Inhabited Γ] (l : ListBlank Γ) : l.nth 0 = l.head := by + conv => lhs; rw [← ListBlank.cons_head_tail l] + exact Quotient.inductionOn' l.tail fun l ↦ rfl + +@[simp] +theorem ListBlank.nth_succ {Γ} [Inhabited Γ] (l : ListBlank Γ) (n : ℕ) : + l.nth (n + 1) = l.tail.nth n := by + conv => lhs; rw [← ListBlank.cons_head_tail l] + exact Quotient.inductionOn' l.tail fun l ↦ rfl + +@[ext] +theorem ListBlank.ext {Γ} [i : Inhabited Γ] {L₁ L₂ : ListBlank Γ} : + (∀ i, L₁.nth i = L₂.nth i) → L₁ = L₂ := by + refine ListBlank.induction_on L₁ fun l₁ ↦ ListBlank.induction_on L₂ fun l₂ H ↦ ?_ + wlog h : l₁.length ≤ l₂.length + · cases le_total l₁.length l₂.length <;> [skip; symm] <;> apply this <;> try assumption + intro + rw [H] + refine Quotient.sound' (Or.inl ⟨l₂.length - l₁.length, ?_⟩) + refine List.ext_getElem ?_ fun i h h₂ ↦ Eq.symm ?_ + · simp only [Nat.add_sub_cancel' h, List.length_append, List.length_replicate] + simp only [ListBlank.nth_mk] at H + cases' lt_or_le i l₁.length with h' h' + · simp [h', List.getElem_append _ h₂, ← List.getI_eq_getElem _ h, ← List.getI_eq_getElem _ h', H] + · rw [List.getElem_append_right h', List.getElem_replicate, + ← List.getI_eq_default _ h', H, List.getI_eq_getElem _ h] + +/-- Apply a function to a value stored at the nth position of the list. -/ +@[simp] +def ListBlank.modifyNth {Γ} [Inhabited Γ] (f : Γ → Γ) : ℕ → ListBlank Γ → ListBlank Γ + | 0, L => L.tail.cons (f L.head) + | n + 1, L => (L.tail.modifyNth f n).cons L.head + +theorem ListBlank.nth_modifyNth {Γ} [Inhabited Γ] (f : Γ → Γ) (n i) (L : ListBlank Γ) : + (L.modifyNth f n).nth i = if i = n then f (L.nth i) else L.nth i := by + induction' n with n IH generalizing i L + · cases i <;> simp only [ListBlank.nth_zero, if_true, ListBlank.head_cons, ListBlank.modifyNth, + ListBlank.nth_succ, if_false, ListBlank.tail_cons, reduceCtorEq] + · cases i + · rw [if_neg (Nat.succ_ne_zero _).symm] + simp only [ListBlank.nth_zero, ListBlank.head_cons, ListBlank.modifyNth] + · simp only [IH, ListBlank.modifyNth, ListBlank.nth_succ, ListBlank.tail_cons, Nat.succ.injEq] + +/-- A pointed map of `Inhabited` types is a map that sends one default value to the other. -/ +structure PointedMap.{u, v} (Γ : Type u) (Γ' : Type v) [Inhabited Γ] [Inhabited Γ'] : + Type max u v where + /-- The map underlying this instance. -/ + f : Γ → Γ' + map_pt' : f default = default + +instance {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] : Inhabited (PointedMap Γ Γ') := + ⟨⟨default, rfl⟩⟩ + +instance {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] : CoeFun (PointedMap Γ Γ') fun _ ↦ Γ → Γ' := + ⟨PointedMap.f⟩ + +-- @[simp] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/10685): dsimp can prove this +theorem PointedMap.mk_val {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : Γ → Γ') (pt) : + (PointedMap.mk f pt : Γ → Γ') = f := + rfl + +@[simp] +theorem PointedMap.map_pt {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') : + f default = default := + PointedMap.map_pt' _ + +@[simp] +theorem PointedMap.headI_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') + (l : List Γ) : (l.map f).headI = f l.headI := by + cases l <;> [exact (PointedMap.map_pt f).symm; rfl] + +/-- The `map` function on lists is well defined on `ListBlank`s provided that the map is +pointed. -/ +def ListBlank.map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (l : ListBlank Γ) : + ListBlank Γ' := by + apply l.liftOn (fun l ↦ ListBlank.mk (List.map f l)) + rintro l _ ⟨i, rfl⟩; refine Quotient.sound' (Or.inl ⟨i, ?_⟩) + simp only [PointedMap.map_pt, List.map_append, List.map_replicate] + +@[simp] +theorem ListBlank.map_mk {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (l : List Γ) : + (ListBlank.mk l).map f = ListBlank.mk (l.map f) := + rfl + +@[simp] +theorem ListBlank.head_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') + (l : ListBlank Γ) : (l.map f).head = f l.head := by + conv => lhs; rw [← ListBlank.cons_head_tail l] + exact Quotient.inductionOn' l fun a ↦ rfl + +@[simp] +theorem ListBlank.tail_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') + (l : ListBlank Γ) : (l.map f).tail = l.tail.map f := by + conv => lhs; rw [← ListBlank.cons_head_tail l] + exact Quotient.inductionOn' l fun a ↦ rfl + +@[simp] +theorem ListBlank.map_cons {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') + (l : ListBlank Γ) (a : Γ) : (l.cons a).map f = (l.map f).cons (f a) := by + refine (ListBlank.cons_head_tail _).symm.trans ?_ + simp only [ListBlank.head_map, ListBlank.head_cons, ListBlank.tail_map, ListBlank.tail_cons] + +@[simp] +theorem ListBlank.nth_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') + (l : ListBlank Γ) (n : ℕ) : (l.map f).nth n = f (l.nth n) := by + refine l.inductionOn fun l ↦ ?_ + -- Porting note: Added `suffices` to get `simp` to work. + suffices ((mk l).map f).nth n = f ((mk l).nth n) by exact this + simp only [ListBlank.map_mk, ListBlank.nth_mk, ← List.getD_default_eq_getI] + rw [← List.getD_map _ _ f] + simp + +/-- The `i`-th projection as a pointed map. -/ +def proj {ι : Type*} {Γ : ι → Type*} [∀ i, Inhabited (Γ i)] (i : ι) : + PointedMap (∀ i, Γ i) (Γ i) := + ⟨fun a ↦ a i, rfl⟩ + +theorem proj_map_nth {ι : Type*} {Γ : ι → Type*} [∀ i, Inhabited (Γ i)] (i : ι) (L n) : + (ListBlank.map (@proj ι Γ _ i) L).nth n = L.nth n i := by + rw [ListBlank.nth_map]; rfl + +theorem ListBlank.map_modifyNth {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (F : PointedMap Γ Γ') + (f : Γ → Γ) (f' : Γ' → Γ') (H : ∀ x, F (f x) = f' (F x)) (n) (L : ListBlank Γ) : + (L.modifyNth f n).map F = (L.map F).modifyNth f' n := by + induction' n with n IH generalizing L <;> + simp only [*, ListBlank.head_map, ListBlank.modifyNth, ListBlank.map_cons, ListBlank.tail_map] + +/-- Append a list on the left side of a `ListBlank`. -/ +@[simp] +def ListBlank.append {Γ} [Inhabited Γ] : List Γ → ListBlank Γ → ListBlank Γ + | [], L => L + | a :: l, L => ListBlank.cons a (ListBlank.append l L) + +@[simp] +theorem ListBlank.append_mk {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) : + ListBlank.append l₁ (ListBlank.mk l₂) = ListBlank.mk (l₁ ++ l₂) := by + induction l₁ <;> + simp only [*, ListBlank.append, List.nil_append, List.cons_append, ListBlank.cons_mk] + +theorem ListBlank.append_assoc {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) (l₃ : ListBlank Γ) : + ListBlank.append (l₁ ++ l₂) l₃ = ListBlank.append l₁ (ListBlank.append l₂ l₃) := by + refine l₃.inductionOn fun l ↦ ?_ + -- Porting note: Added `suffices` to get `simp` to work. + suffices append (l₁ ++ l₂) (mk l) = append l₁ (append l₂ (mk l)) by exact this + simp only [ListBlank.append_mk, List.append_assoc] + +/-- The `flatMap` function on lists is well defined on `ListBlank`s provided that the default +element is sent to a sequence of default elements. -/ +def ListBlank.flatMap {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ') + (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by + apply l.liftOn (fun l ↦ ListBlank.mk (List.flatMap l f)) + rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine Quotient.sound' (Or.inl ⟨i * n, ?_⟩) + rw [List.flatMap_append, mul_comm]; congr + induction' i with i IH + · rfl + simp only [IH, e, List.replicate_add, Nat.mul_succ, add_comm, List.replicate_succ, + List.flatMap_cons] + +@[deprecated (since := "2024-10-16")] alias ListBlank.bind := ListBlank.flatMap + +@[simp] +theorem ListBlank.flatMap_mk + {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : List Γ) (f : Γ → List Γ') (hf) : + (ListBlank.mk l).flatMap f hf = ListBlank.mk (l.flatMap f) := + rfl + +@[deprecated (since := "2024-10-16")] alias ListBlank.bind_mk := ListBlank.flatMap_mk + +@[simp] +theorem ListBlank.cons_flatMap {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (a : Γ) (l : ListBlank Γ) + (f : Γ → List Γ') (hf) : (l.cons a).flatMap f hf = (l.flatMap f hf).append (f a) := by + refine l.inductionOn fun l ↦ ?_ + -- Porting note: Added `suffices` to get `simp` to work. + suffices ((mk l).cons a).flatMap f hf = ((mk l).flatMap f hf).append (f a) by exact this + simp only [ListBlank.append_mk, ListBlank.flatMap_mk, ListBlank.cons_mk, List.flatMap_cons] + +@[deprecated (since := "2024-10-16")] alias ListBlank.cons_bind := ListBlank.cons_flatMap + +end ListBlank + +section Tape + +/-- The tape of a Turing machine is composed of a head element (which we imagine to be the +current position of the head), together with two `ListBlank`s denoting the portions of the tape +going off to the left and right. When the Turing machine moves right, an element is pulled from the +right side and becomes the new head, while the head element is `cons`ed onto the left side. -/ +structure Tape (Γ : Type*) [Inhabited Γ] where + /-- The current position of the head. -/ + head : Γ + /-- The portion of the tape going off to the left. -/ + left : ListBlank Γ + /-- The portion of the tape going off to the right. -/ + right : ListBlank Γ + +instance Tape.inhabited {Γ} [Inhabited Γ] : Inhabited (Tape Γ) := + ⟨by constructor <;> apply default⟩ + +/-- A direction for the Turing machine `move` command, either + left or right. -/ +inductive Dir + | left + | right + deriving DecidableEq, Inhabited + +/-- The "inclusive" left side of the tape, including both `left` and `head`. -/ +def Tape.left₀ {Γ} [Inhabited Γ] (T : Tape Γ) : ListBlank Γ := + T.left.cons T.head + +/-- The "inclusive" right side of the tape, including both `right` and `head`. -/ +def Tape.right₀ {Γ} [Inhabited Γ] (T : Tape Γ) : ListBlank Γ := + T.right.cons T.head + +/-- Move the tape in response to a motion of the Turing machine. Note that `T.move Dir.left` makes +`T.left` smaller; the Turing machine is moving left and the tape is moving right. -/ +def Tape.move {Γ} [Inhabited Γ] : Dir → Tape Γ → Tape Γ + | Dir.left, ⟨a, L, R⟩ => ⟨L.head, L.tail, R.cons a⟩ + | Dir.right, ⟨a, L, R⟩ => ⟨R.head, L.cons a, R.tail⟩ + +@[simp] +theorem Tape.move_left_right {Γ} [Inhabited Γ] (T : Tape Γ) : + (T.move Dir.left).move Dir.right = T := by + cases T; simp [Tape.move] + +@[simp] +theorem Tape.move_right_left {Γ} [Inhabited Γ] (T : Tape Γ) : + (T.move Dir.right).move Dir.left = T := by + cases T; simp [Tape.move] + +/-- Construct a tape from a left side and an inclusive right side. -/ +def Tape.mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) : Tape Γ := + ⟨R.head, L, R.tail⟩ + +@[simp] +theorem Tape.mk'_left {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).left = L := + rfl + +@[simp] +theorem Tape.mk'_head {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).head = R.head := + rfl + +@[simp] +theorem Tape.mk'_right {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).right = R.tail := + rfl + +@[simp] +theorem Tape.mk'_right₀ {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).right₀ = R := + ListBlank.cons_head_tail _ + +@[simp] +theorem Tape.mk'_left_right₀ {Γ} [Inhabited Γ] (T : Tape Γ) : Tape.mk' T.left T.right₀ = T := by + cases T + simp only [Tape.right₀, Tape.mk', ListBlank.head_cons, ListBlank.tail_cons, eq_self_iff_true, + and_self_iff] + +theorem Tape.exists_mk' {Γ} [Inhabited Γ] (T : Tape Γ) : ∃ L R, T = Tape.mk' L R := + ⟨_, _, (Tape.mk'_left_right₀ _).symm⟩ + +@[simp] +theorem Tape.move_left_mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) : + (Tape.mk' L R).move Dir.left = Tape.mk' L.tail (R.cons L.head) := by + simp only [Tape.move, Tape.mk', ListBlank.head_cons, eq_self_iff_true, ListBlank.cons_head_tail, + and_self_iff, ListBlank.tail_cons] + +@[simp] +theorem Tape.move_right_mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) : + (Tape.mk' L R).move Dir.right = Tape.mk' (L.cons R.head) R.tail := by + simp only [Tape.move, Tape.mk', ListBlank.head_cons, eq_self_iff_true, ListBlank.cons_head_tail, + and_self_iff, ListBlank.tail_cons] + +/-- Construct a tape from a left side and an inclusive right side. -/ +def Tape.mk₂ {Γ} [Inhabited Γ] (L R : List Γ) : Tape Γ := + Tape.mk' (ListBlank.mk L) (ListBlank.mk R) + +/-- Construct a tape from a list, with the head of the list at the TM head and the rest going +to the right. -/ +def Tape.mk₁ {Γ} [Inhabited Γ] (l : List Γ) : Tape Γ := + Tape.mk₂ [] l + +/-- The `nth` function of a tape is integer-valued, with index `0` being the head, negative indexes +on the left and positive indexes on the right. (Picture a number line.) -/ +def Tape.nth {Γ} [Inhabited Γ] (T : Tape Γ) : ℤ → Γ + | 0 => T.head + | (n + 1 : ℕ) => T.right.nth n + | -(n + 1 : ℕ) => T.left.nth n + +@[simp] +theorem Tape.nth_zero {Γ} [Inhabited Γ] (T : Tape Γ) : T.nth 0 = T.1 := + rfl + +theorem Tape.right₀_nth {Γ} [Inhabited Γ] (T : Tape Γ) (n : ℕ) : T.right₀.nth n = T.nth n := by + cases n <;> simp only [Tape.nth, Tape.right₀, Int.ofNat_zero, ListBlank.nth_zero, + ListBlank.nth_succ, ListBlank.head_cons, ListBlank.tail_cons] + +@[simp] +theorem Tape.mk'_nth_nat {Γ} [Inhabited Γ] (L R : ListBlank Γ) (n : ℕ) : + (Tape.mk' L R).nth n = R.nth n := by + rw [← Tape.right₀_nth, Tape.mk'_right₀] + +@[simp] +theorem Tape.move_left_nth {Γ} [Inhabited Γ] : + ∀ (T : Tape Γ) (i : ℤ), (T.move Dir.left).nth i = T.nth (i - 1) + | ⟨_, _, _⟩, -(_ + 1 : ℕ) => (ListBlank.nth_succ _ _).symm + | ⟨_, _, _⟩, 0 => (ListBlank.nth_zero _).symm + | ⟨_, _, _⟩, 1 => (ListBlank.nth_zero _).trans (ListBlank.head_cons _ _) + | ⟨a, L, R⟩, (n + 1 : ℕ) + 1 => by + rw [add_sub_cancel_right] + change (R.cons a).nth (n + 1) = R.nth n + rw [ListBlank.nth_succ, ListBlank.tail_cons] + +@[simp] +theorem Tape.move_right_nth {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℤ) : + (T.move Dir.right).nth i = T.nth (i + 1) := by + conv => rhs; rw [← T.move_right_left] + rw [Tape.move_left_nth, add_sub_cancel_right] + +@[simp] +theorem Tape.move_right_n_head {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℕ) : + ((Tape.move Dir.right)^[i] T).head = T.nth i := by + induction i generalizing T + · rfl + · simp only [*, Tape.move_right_nth, Int.ofNat_succ, iterate_succ, Function.comp_apply] + +/-- Replace the current value of the head on the tape. -/ +def Tape.write {Γ} [Inhabited Γ] (b : Γ) (T : Tape Γ) : Tape Γ := + { T with head := b } + +@[simp] +theorem Tape.write_self {Γ} [Inhabited Γ] : ∀ T : Tape Γ, T.write T.1 = T := by + rintro ⟨⟩; rfl + +@[simp] +theorem Tape.write_nth {Γ} [Inhabited Γ] (b : Γ) : + ∀ (T : Tape Γ) {i : ℤ}, (T.write b).nth i = if i = 0 then b else T.nth i + | _, 0 => rfl + | _, (_ + 1 : ℕ) => rfl + | _, -(_ + 1 : ℕ) => rfl + +@[simp] +theorem Tape.write_mk' {Γ} [Inhabited Γ] (a b : Γ) (L R : ListBlank Γ) : + (Tape.mk' L (R.cons a)).write b = Tape.mk' L (R.cons b) := by + simp only [Tape.write, Tape.mk', ListBlank.head_cons, ListBlank.tail_cons, eq_self_iff_true, + and_self_iff] + +/-- Apply a pointed map to a tape to change the alphabet. -/ +def Tape.map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) : Tape Γ' := + ⟨f T.1, T.2.map f, T.3.map f⟩ + +@[simp] +theorem Tape.map_fst {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') : + ∀ T : Tape Γ, (T.map f).1 = f T.1 := by + rintro ⟨⟩; rfl + +@[simp] +theorem Tape.map_write {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (b : Γ) : + ∀ T : Tape Γ, (T.write b).map f = (T.map f).write (f b) := by + rintro ⟨⟩; rfl + +-- Porting note: `simpNF` complains about LHS does not simplify when using the simp lemma on +-- itself, but it does indeed. +@[simp, nolint simpNF] +theorem Tape.write_move_right_n {Γ} [Inhabited Γ] (f : Γ → Γ) (L R : ListBlank Γ) (n : ℕ) : + ((Tape.move Dir.right)^[n] (Tape.mk' L R)).write (f (R.nth n)) = + (Tape.move Dir.right)^[n] (Tape.mk' L (R.modifyNth f n)) := by + induction' n with n IH generalizing L R + · simp only [ListBlank.nth_zero, ListBlank.modifyNth, iterate_zero_apply] + rw [← Tape.write_mk', ListBlank.cons_head_tail] + simp only [ListBlank.head_cons, ListBlank.nth_succ, ListBlank.modifyNth, Tape.move_right_mk', + ListBlank.tail_cons, iterate_succ_apply, IH] + +theorem Tape.map_move {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) (d) : + (T.move d).map f = (T.map f).move d := by + cases T + cases d <;> simp only [Tape.move, Tape.map, ListBlank.head_map, eq_self_iff_true, + ListBlank.map_cons, and_self_iff, ListBlank.tail_map] + +theorem Tape.map_mk' {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (L R : ListBlank Γ) : + (Tape.mk' L R).map f = Tape.mk' (L.map f) (R.map f) := by + simp only [Tape.mk', Tape.map, ListBlank.head_map, eq_self_iff_true, and_self_iff, + ListBlank.tail_map] + +theorem Tape.map_mk₂ {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (L R : List Γ) : + (Tape.mk₂ L R).map f = Tape.mk₂ (L.map f) (R.map f) := by + simp only [Tape.mk₂, Tape.map_mk', ListBlank.map_mk] + +theorem Tape.map_mk₁ {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (l : List Γ) : + (Tape.mk₁ l).map f = Tape.mk₁ (l.map f) := + Tape.map_mk₂ _ _ _ + +end Tape + +end Turing diff --git a/Mathlib/Computability/TuringMachine.lean b/Mathlib/Computability/TuringMachine.lean index 2d124e2707b94..19a73e31325fb 100644 --- a/Mathlib/Computability/TuringMachine.lean +++ b/Mathlib/Computability/TuringMachine.lean @@ -3,15 +3,11 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Mathlib.Computability.Tape import Mathlib.Data.Fintype.Option import Mathlib.Data.Fintype.Prod import Mathlib.Data.Fintype.Pi -import Mathlib.Data.Vector.Basic import Mathlib.Data.PFun -import Mathlib.Logic.Function.Iterate -import Mathlib.Order.Basic -import Mathlib.Tactic.ApplyFun -import Mathlib.Data.List.GetD /-! # Turing machines @@ -70,584 +66,6 @@ open Function (update iterate_succ iterate_succ_apply iterate_succ' iterate_succ namespace Turing -/-- The `BlankExtends` partial order holds of `l₁` and `l₂` if `l₂` is obtained by adding -blanks (`default : Γ`) to the end of `l₁`. -/ -def BlankExtends {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) : Prop := - ∃ n, l₂ = l₁ ++ List.replicate n default - -@[refl] -theorem BlankExtends.refl {Γ} [Inhabited Γ] (l : List Γ) : BlankExtends l l := - ⟨0, by simp⟩ - -@[trans] -theorem BlankExtends.trans {Γ} [Inhabited Γ] {l₁ l₂ l₃ : List Γ} : - BlankExtends l₁ l₂ → BlankExtends l₂ l₃ → BlankExtends l₁ l₃ := by - rintro ⟨i, rfl⟩ ⟨j, rfl⟩ - exact ⟨i + j, by simp⟩ - -theorem BlankExtends.below_of_le {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} : - BlankExtends l l₁ → BlankExtends l l₂ → l₁.length ≤ l₂.length → BlankExtends l₁ l₂ := by - rintro ⟨i, rfl⟩ ⟨j, rfl⟩ h; use j - i - simp only [List.length_append, Nat.add_le_add_iff_left, List.length_replicate] at h - simp only [← List.replicate_add, Nat.add_sub_cancel' h, List.append_assoc] - -/-- Any two extensions by blank `l₁,l₂` of `l` have a common join (which can be taken to be the -longer of `l₁` and `l₂`). -/ -def BlankExtends.above {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} (h₁ : BlankExtends l l₁) - (h₂ : BlankExtends l l₂) : { l' // BlankExtends l₁ l' ∧ BlankExtends l₂ l' } := - if h : l₁.length ≤ l₂.length then ⟨l₂, h₁.below_of_le h₂ h, BlankExtends.refl _⟩ - else ⟨l₁, BlankExtends.refl _, h₂.below_of_le h₁ (le_of_not_ge h)⟩ - -theorem BlankExtends.above_of_le {Γ} [Inhabited Γ] {l l₁ l₂ : List Γ} : - BlankExtends l₁ l → BlankExtends l₂ l → l₁.length ≤ l₂.length → BlankExtends l₁ l₂ := by - rintro ⟨i, rfl⟩ ⟨j, e⟩ h; use i - j - refine List.append_cancel_right (e.symm.trans ?_) - rw [List.append_assoc, ← List.replicate_add, Nat.sub_add_cancel] - apply_fun List.length at e - simp only [List.length_append, List.length_replicate] at e - rwa [← Nat.add_le_add_iff_left, e, Nat.add_le_add_iff_right] - -/-- `BlankRel` is the symmetric closure of `BlankExtends`, turning it into an equivalence -relation. Two lists are related by `BlankRel` if one extends the other by blanks. -/ -def BlankRel {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) : Prop := - BlankExtends l₁ l₂ ∨ BlankExtends l₂ l₁ - -@[refl] -theorem BlankRel.refl {Γ} [Inhabited Γ] (l : List Γ) : BlankRel l l := - Or.inl (BlankExtends.refl _) - -@[symm] -theorem BlankRel.symm {Γ} [Inhabited Γ] {l₁ l₂ : List Γ} : BlankRel l₁ l₂ → BlankRel l₂ l₁ := - Or.symm - -@[trans] -theorem BlankRel.trans {Γ} [Inhabited Γ] {l₁ l₂ l₃ : List Γ} : - BlankRel l₁ l₂ → BlankRel l₂ l₃ → BlankRel l₁ l₃ := by - rintro (h₁ | h₁) (h₂ | h₂) - · exact Or.inl (h₁.trans h₂) - · rcases le_total l₁.length l₃.length with h | h - · exact Or.inl (h₁.above_of_le h₂ h) - · exact Or.inr (h₂.above_of_le h₁ h) - · rcases le_total l₁.length l₃.length with h | h - · exact Or.inl (h₁.below_of_le h₂ h) - · exact Or.inr (h₂.below_of_le h₁ h) - · exact Or.inr (h₂.trans h₁) - -/-- Given two `BlankRel` lists, there exists (constructively) a common join. -/ -def BlankRel.above {Γ} [Inhabited Γ] {l₁ l₂ : List Γ} (h : BlankRel l₁ l₂) : - { l // BlankExtends l₁ l ∧ BlankExtends l₂ l } := by - refine - if hl : l₁.length ≤ l₂.length then ⟨l₂, Or.elim h id fun h' ↦ ?_, BlankExtends.refl _⟩ - else ⟨l₁, BlankExtends.refl _, Or.elim h (fun h' ↦ ?_) id⟩ - · exact (BlankExtends.refl _).above_of_le h' hl - · exact (BlankExtends.refl _).above_of_le h' (le_of_not_ge hl) - -/-- Given two `BlankRel` lists, there exists (constructively) a common meet. -/ -def BlankRel.below {Γ} [Inhabited Γ] {l₁ l₂ : List Γ} (h : BlankRel l₁ l₂) : - { l // BlankExtends l l₁ ∧ BlankExtends l l₂ } := by - refine - if hl : l₁.length ≤ l₂.length then ⟨l₁, BlankExtends.refl _, Or.elim h id fun h' ↦ ?_⟩ - else ⟨l₂, Or.elim h (fun h' ↦ ?_) id, BlankExtends.refl _⟩ - · exact (BlankExtends.refl _).above_of_le h' hl - · exact (BlankExtends.refl _).above_of_le h' (le_of_not_ge hl) - -theorem BlankRel.equivalence (Γ) [Inhabited Γ] : Equivalence (@BlankRel Γ _) := - ⟨BlankRel.refl, @BlankRel.symm _ _, @BlankRel.trans _ _⟩ - -/-- Construct a setoid instance for `BlankRel`. -/ -def BlankRel.setoid (Γ) [Inhabited Γ] : Setoid (List Γ) := - ⟨_, BlankRel.equivalence _⟩ - -/-- A `ListBlank Γ` is a quotient of `List Γ` by extension by blanks at the end. This is used to -represent half-tapes of a Turing machine, so that we can pretend that the list continues -infinitely with blanks. -/ -def ListBlank (Γ) [Inhabited Γ] := - Quotient (BlankRel.setoid Γ) - -instance ListBlank.inhabited {Γ} [Inhabited Γ] : Inhabited (ListBlank Γ) := - ⟨Quotient.mk'' []⟩ - -instance ListBlank.hasEmptyc {Γ} [Inhabited Γ] : EmptyCollection (ListBlank Γ) := - ⟨Quotient.mk'' []⟩ - -/-- A modified version of `Quotient.liftOn'` specialized for `ListBlank`, with the stronger -precondition `BlankExtends` instead of `BlankRel`. -/ -protected abbrev ListBlank.liftOn {Γ} [Inhabited Γ] {α} (l : ListBlank Γ) (f : List Γ → α) - (H : ∀ a b, BlankExtends a b → f a = f b) : α := - l.liftOn' f <| by rintro a b (h | h) <;> [exact H _ _ h; exact (H _ _ h).symm] - -/-- The quotient map turning a `List` into a `ListBlank`. -/ -def ListBlank.mk {Γ} [Inhabited Γ] : List Γ → ListBlank Γ := - Quotient.mk'' - -@[elab_as_elim] -protected theorem ListBlank.induction_on {Γ} [Inhabited Γ] {p : ListBlank Γ → Prop} - (q : ListBlank Γ) (h : ∀ a, p (ListBlank.mk a)) : p q := - Quotient.inductionOn' q h - -/-- The head of a `ListBlank` is well defined. -/ -def ListBlank.head {Γ} [Inhabited Γ] (l : ListBlank Γ) : Γ := by - apply l.liftOn List.headI - rintro a _ ⟨i, rfl⟩ - cases a - · cases i <;> rfl - rfl - -@[simp] -theorem ListBlank.head_mk {Γ} [Inhabited Γ] (l : List Γ) : - ListBlank.head (ListBlank.mk l) = l.headI := - rfl - -/-- The tail of a `ListBlank` is well defined (up to the tail of blanks). -/ -def ListBlank.tail {Γ} [Inhabited Γ] (l : ListBlank Γ) : ListBlank Γ := by - apply l.liftOn (fun l ↦ ListBlank.mk l.tail) - rintro a _ ⟨i, rfl⟩ - refine Quotient.sound' (Or.inl ?_) - cases a - · cases' i with i <;> [exact ⟨0, rfl⟩; exact ⟨i, rfl⟩] - exact ⟨i, rfl⟩ - -@[simp] -theorem ListBlank.tail_mk {Γ} [Inhabited Γ] (l : List Γ) : - ListBlank.tail (ListBlank.mk l) = ListBlank.mk l.tail := - rfl - -/-- We can cons an element onto a `ListBlank`. -/ -def ListBlank.cons {Γ} [Inhabited Γ] (a : Γ) (l : ListBlank Γ) : ListBlank Γ := by - apply l.liftOn (fun l ↦ ListBlank.mk (List.cons a l)) - rintro _ _ ⟨i, rfl⟩ - exact Quotient.sound' (Or.inl ⟨i, rfl⟩) - -@[simp] -theorem ListBlank.cons_mk {Γ} [Inhabited Γ] (a : Γ) (l : List Γ) : - ListBlank.cons a (ListBlank.mk l) = ListBlank.mk (a :: l) := - rfl - -@[simp] -theorem ListBlank.head_cons {Γ} [Inhabited Γ] (a : Γ) : ∀ l : ListBlank Γ, (l.cons a).head = a := - Quotient.ind' fun _ ↦ rfl - -@[simp] -theorem ListBlank.tail_cons {Γ} [Inhabited Γ] (a : Γ) : ∀ l : ListBlank Γ, (l.cons a).tail = l := - Quotient.ind' fun _ ↦ rfl - -/-- The `cons` and `head`/`tail` functions are mutually inverse, unlike in the case of `List` where -this only holds for nonempty lists. -/ -@[simp] -theorem ListBlank.cons_head_tail {Γ} [Inhabited Γ] : ∀ l : ListBlank Γ, l.tail.cons l.head = l := by - apply Quotient.ind' - refine fun l ↦ Quotient.sound' (Or.inr ?_) - cases l - · exact ⟨1, rfl⟩ - · rfl - -/-- The `cons` and `head`/`tail` functions are mutually inverse, unlike in the case of `List` where -this only holds for nonempty lists. -/ -theorem ListBlank.exists_cons {Γ} [Inhabited Γ] (l : ListBlank Γ) : - ∃ a l', l = ListBlank.cons a l' := - ⟨_, _, (ListBlank.cons_head_tail _).symm⟩ - -/-- The n-th element of a `ListBlank` is well defined for all `n : ℕ`, unlike in a `List`. -/ -def ListBlank.nth {Γ} [Inhabited Γ] (l : ListBlank Γ) (n : ℕ) : Γ := by - apply l.liftOn (fun l ↦ List.getI l n) - rintro l _ ⟨i, rfl⟩ - cases' lt_or_le n _ with h h - · rw [List.getI_append _ _ _ h] - rw [List.getI_eq_default _ h] - rcases le_or_lt _ n with h₂ | h₂ - · rw [List.getI_eq_default _ h₂] - rw [List.getI_eq_getElem _ h₂, List.getElem_append_right h, List.getElem_replicate] - -@[simp] -theorem ListBlank.nth_mk {Γ} [Inhabited Γ] (l : List Γ) (n : ℕ) : - (ListBlank.mk l).nth n = l.getI n := - rfl - -@[simp] -theorem ListBlank.nth_zero {Γ} [Inhabited Γ] (l : ListBlank Γ) : l.nth 0 = l.head := by - conv => lhs; rw [← ListBlank.cons_head_tail l] - exact Quotient.inductionOn' l.tail fun l ↦ rfl - -@[simp] -theorem ListBlank.nth_succ {Γ} [Inhabited Γ] (l : ListBlank Γ) (n : ℕ) : - l.nth (n + 1) = l.tail.nth n := by - conv => lhs; rw [← ListBlank.cons_head_tail l] - exact Quotient.inductionOn' l.tail fun l ↦ rfl - -@[ext] -theorem ListBlank.ext {Γ} [i : Inhabited Γ] {L₁ L₂ : ListBlank Γ} : - (∀ i, L₁.nth i = L₂.nth i) → L₁ = L₂ := by - refine ListBlank.induction_on L₁ fun l₁ ↦ ListBlank.induction_on L₂ fun l₂ H ↦ ?_ - wlog h : l₁.length ≤ l₂.length - · cases le_total l₁.length l₂.length <;> [skip; symm] <;> apply this <;> try assumption - intro - rw [H] - refine Quotient.sound' (Or.inl ⟨l₂.length - l₁.length, ?_⟩) - refine List.ext_getElem ?_ fun i h h₂ ↦ Eq.symm ?_ - · simp only [Nat.add_sub_cancel' h, List.length_append, List.length_replicate] - simp only [ListBlank.nth_mk] at H - cases' lt_or_le i l₁.length with h' h' - · simp [h', List.getElem_append _ h₂, ← List.getI_eq_getElem _ h, ← List.getI_eq_getElem _ h', H] - · rw [List.getElem_append_right h', List.getElem_replicate, - ← List.getI_eq_default _ h', H, List.getI_eq_getElem _ h] - -/-- Apply a function to a value stored at the nth position of the list. -/ -@[simp] -def ListBlank.modifyNth {Γ} [Inhabited Γ] (f : Γ → Γ) : ℕ → ListBlank Γ → ListBlank Γ - | 0, L => L.tail.cons (f L.head) - | n + 1, L => (L.tail.modifyNth f n).cons L.head - -theorem ListBlank.nth_modifyNth {Γ} [Inhabited Γ] (f : Γ → Γ) (n i) (L : ListBlank Γ) : - (L.modifyNth f n).nth i = if i = n then f (L.nth i) else L.nth i := by - induction' n with n IH generalizing i L - · cases i <;> simp only [ListBlank.nth_zero, if_true, ListBlank.head_cons, ListBlank.modifyNth, - ListBlank.nth_succ, if_false, ListBlank.tail_cons, reduceCtorEq] - · cases i - · rw [if_neg (Nat.succ_ne_zero _).symm] - simp only [ListBlank.nth_zero, ListBlank.head_cons, ListBlank.modifyNth] - · simp only [IH, ListBlank.modifyNth, ListBlank.nth_succ, ListBlank.tail_cons, Nat.succ.injEq] - -/-- A pointed map of `Inhabited` types is a map that sends one default value to the other. -/ -structure PointedMap.{u, v} (Γ : Type u) (Γ' : Type v) [Inhabited Γ] [Inhabited Γ'] : - Type max u v where - /-- The map underlying this instance. -/ - f : Γ → Γ' - map_pt' : f default = default - -instance {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] : Inhabited (PointedMap Γ Γ') := - ⟨⟨default, rfl⟩⟩ - -instance {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] : CoeFun (PointedMap Γ Γ') fun _ ↦ Γ → Γ' := - ⟨PointedMap.f⟩ - --- @[simp] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/10685): dsimp can prove this -theorem PointedMap.mk_val {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : Γ → Γ') (pt) : - (PointedMap.mk f pt : Γ → Γ') = f := - rfl - -@[simp] -theorem PointedMap.map_pt {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') : - f default = default := - PointedMap.map_pt' _ - -@[simp] -theorem PointedMap.headI_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') - (l : List Γ) : (l.map f).headI = f l.headI := by - cases l <;> [exact (PointedMap.map_pt f).symm; rfl] - -/-- The `map` function on lists is well defined on `ListBlank`s provided that the map is -pointed. -/ -def ListBlank.map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (l : ListBlank Γ) : - ListBlank Γ' := by - apply l.liftOn (fun l ↦ ListBlank.mk (List.map f l)) - rintro l _ ⟨i, rfl⟩; refine Quotient.sound' (Or.inl ⟨i, ?_⟩) - simp only [PointedMap.map_pt, List.map_append, List.map_replicate] - -@[simp] -theorem ListBlank.map_mk {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (l : List Γ) : - (ListBlank.mk l).map f = ListBlank.mk (l.map f) := - rfl - -@[simp] -theorem ListBlank.head_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') - (l : ListBlank Γ) : (l.map f).head = f l.head := by - conv => lhs; rw [← ListBlank.cons_head_tail l] - exact Quotient.inductionOn' l fun a ↦ rfl - -@[simp] -theorem ListBlank.tail_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') - (l : ListBlank Γ) : (l.map f).tail = l.tail.map f := by - conv => lhs; rw [← ListBlank.cons_head_tail l] - exact Quotient.inductionOn' l fun a ↦ rfl - -@[simp] -theorem ListBlank.map_cons {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') - (l : ListBlank Γ) (a : Γ) : (l.cons a).map f = (l.map f).cons (f a) := by - refine (ListBlank.cons_head_tail _).symm.trans ?_ - simp only [ListBlank.head_map, ListBlank.head_cons, ListBlank.tail_map, ListBlank.tail_cons] - -@[simp] -theorem ListBlank.nth_map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') - (l : ListBlank Γ) (n : ℕ) : (l.map f).nth n = f (l.nth n) := by - refine l.inductionOn fun l ↦ ?_ - -- Porting note: Added `suffices` to get `simp` to work. - suffices ((mk l).map f).nth n = f ((mk l).nth n) by exact this - simp only [ListBlank.map_mk, ListBlank.nth_mk, ← List.getD_default_eq_getI] - rw [← List.getD_map _ _ f] - simp - -/-- The `i`-th projection as a pointed map. -/ -def proj {ι : Type*} {Γ : ι → Type*} [∀ i, Inhabited (Γ i)] (i : ι) : - PointedMap (∀ i, Γ i) (Γ i) := - ⟨fun a ↦ a i, rfl⟩ - -theorem proj_map_nth {ι : Type*} {Γ : ι → Type*} [∀ i, Inhabited (Γ i)] (i : ι) (L n) : - (ListBlank.map (@proj ι Γ _ i) L).nth n = L.nth n i := by - rw [ListBlank.nth_map]; rfl - -theorem ListBlank.map_modifyNth {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (F : PointedMap Γ Γ') - (f : Γ → Γ) (f' : Γ' → Γ') (H : ∀ x, F (f x) = f' (F x)) (n) (L : ListBlank Γ) : - (L.modifyNth f n).map F = (L.map F).modifyNth f' n := by - induction' n with n IH generalizing L <;> - simp only [*, ListBlank.head_map, ListBlank.modifyNth, ListBlank.map_cons, ListBlank.tail_map] - -/-- Append a list on the left side of a `ListBlank`. -/ -@[simp] -def ListBlank.append {Γ} [Inhabited Γ] : List Γ → ListBlank Γ → ListBlank Γ - | [], L => L - | a :: l, L => ListBlank.cons a (ListBlank.append l L) - -@[simp] -theorem ListBlank.append_mk {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) : - ListBlank.append l₁ (ListBlank.mk l₂) = ListBlank.mk (l₁ ++ l₂) := by - induction l₁ <;> - simp only [*, ListBlank.append, List.nil_append, List.cons_append, ListBlank.cons_mk] - -theorem ListBlank.append_assoc {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) (l₃ : ListBlank Γ) : - ListBlank.append (l₁ ++ l₂) l₃ = ListBlank.append l₁ (ListBlank.append l₂ l₃) := by - refine l₃.inductionOn fun l ↦ ?_ - -- Porting note: Added `suffices` to get `simp` to work. - suffices append (l₁ ++ l₂) (mk l) = append l₁ (append l₂ (mk l)) by exact this - simp only [ListBlank.append_mk, List.append_assoc] - -/-- The `flatMap` function on lists is well defined on `ListBlank`s provided that the default -element is sent to a sequence of default elements. -/ -def ListBlank.flatMap {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ') - (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by - apply l.liftOn (fun l ↦ ListBlank.mk (List.flatMap l f)) - rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine Quotient.sound' (Or.inl ⟨i * n, ?_⟩) - rw [List.flatMap_append, mul_comm]; congr - induction' i with i IH - · rfl - simp only [IH, e, List.replicate_add, Nat.mul_succ, add_comm, List.replicate_succ, - List.flatMap_cons] - -@[deprecated (since := "2024-10-16")] alias ListBlank.bind := ListBlank.flatMap - -@[simp] -theorem ListBlank.flatMap_mk - {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : List Γ) (f : Γ → List Γ') (hf) : - (ListBlank.mk l).flatMap f hf = ListBlank.mk (l.flatMap f) := - rfl - -@[deprecated (since := "2024-10-16")] alias ListBlank.bind_mk := ListBlank.flatMap_mk - -@[simp] -theorem ListBlank.cons_flatMap {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (a : Γ) (l : ListBlank Γ) - (f : Γ → List Γ') (hf) : (l.cons a).flatMap f hf = (l.flatMap f hf).append (f a) := by - refine l.inductionOn fun l ↦ ?_ - -- Porting note: Added `suffices` to get `simp` to work. - suffices ((mk l).cons a).flatMap f hf = ((mk l).flatMap f hf).append (f a) by exact this - simp only [ListBlank.append_mk, ListBlank.flatMap_mk, ListBlank.cons_mk, List.flatMap_cons] - -@[deprecated (since := "2024-10-16")] alias ListBlank.cons_bind := ListBlank.cons_flatMap - -/-- The tape of a Turing machine is composed of a head element (which we imagine to be the -current position of the head), together with two `ListBlank`s denoting the portions of the tape -going off to the left and right. When the Turing machine moves right, an element is pulled from the -right side and becomes the new head, while the head element is `cons`ed onto the left side. -/ -structure Tape (Γ : Type*) [Inhabited Γ] where - /-- The current position of the head. -/ - head : Γ - /-- The portion of the tape going off to the left. -/ - left : ListBlank Γ - /-- The portion of the tape going off to the right. -/ - right : ListBlank Γ - -instance Tape.inhabited {Γ} [Inhabited Γ] : Inhabited (Tape Γ) := - ⟨by constructor <;> apply default⟩ - -/-- A direction for the Turing machine `move` command, either - left or right. -/ -inductive Dir - | left - | right - deriving DecidableEq, Inhabited - -/-- The "inclusive" left side of the tape, including both `left` and `head`. -/ -def Tape.left₀ {Γ} [Inhabited Γ] (T : Tape Γ) : ListBlank Γ := - T.left.cons T.head - -/-- The "inclusive" right side of the tape, including both `right` and `head`. -/ -def Tape.right₀ {Γ} [Inhabited Γ] (T : Tape Γ) : ListBlank Γ := - T.right.cons T.head - -/-- Move the tape in response to a motion of the Turing machine. Note that `T.move Dir.left` makes -`T.left` smaller; the Turing machine is moving left and the tape is moving right. -/ -def Tape.move {Γ} [Inhabited Γ] : Dir → Tape Γ → Tape Γ - | Dir.left, ⟨a, L, R⟩ => ⟨L.head, L.tail, R.cons a⟩ - | Dir.right, ⟨a, L, R⟩ => ⟨R.head, L.cons a, R.tail⟩ - -@[simp] -theorem Tape.move_left_right {Γ} [Inhabited Γ] (T : Tape Γ) : - (T.move Dir.left).move Dir.right = T := by - cases T; simp [Tape.move] - -@[simp] -theorem Tape.move_right_left {Γ} [Inhabited Γ] (T : Tape Γ) : - (T.move Dir.right).move Dir.left = T := by - cases T; simp [Tape.move] - -/-- Construct a tape from a left side and an inclusive right side. -/ -def Tape.mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) : Tape Γ := - ⟨R.head, L, R.tail⟩ - -@[simp] -theorem Tape.mk'_left {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).left = L := - rfl - -@[simp] -theorem Tape.mk'_head {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).head = R.head := - rfl - -@[simp] -theorem Tape.mk'_right {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).right = R.tail := - rfl - -@[simp] -theorem Tape.mk'_right₀ {Γ} [Inhabited Γ] (L R : ListBlank Γ) : (Tape.mk' L R).right₀ = R := - ListBlank.cons_head_tail _ - -@[simp] -theorem Tape.mk'_left_right₀ {Γ} [Inhabited Γ] (T : Tape Γ) : Tape.mk' T.left T.right₀ = T := by - cases T - simp only [Tape.right₀, Tape.mk', ListBlank.head_cons, ListBlank.tail_cons, eq_self_iff_true, - and_self_iff] - -theorem Tape.exists_mk' {Γ} [Inhabited Γ] (T : Tape Γ) : ∃ L R, T = Tape.mk' L R := - ⟨_, _, (Tape.mk'_left_right₀ _).symm⟩ - -@[simp] -theorem Tape.move_left_mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) : - (Tape.mk' L R).move Dir.left = Tape.mk' L.tail (R.cons L.head) := by - simp only [Tape.move, Tape.mk', ListBlank.head_cons, eq_self_iff_true, ListBlank.cons_head_tail, - and_self_iff, ListBlank.tail_cons] - -@[simp] -theorem Tape.move_right_mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) : - (Tape.mk' L R).move Dir.right = Tape.mk' (L.cons R.head) R.tail := by - simp only [Tape.move, Tape.mk', ListBlank.head_cons, eq_self_iff_true, ListBlank.cons_head_tail, - and_self_iff, ListBlank.tail_cons] - -/-- Construct a tape from a left side and an inclusive right side. -/ -def Tape.mk₂ {Γ} [Inhabited Γ] (L R : List Γ) : Tape Γ := - Tape.mk' (ListBlank.mk L) (ListBlank.mk R) - -/-- Construct a tape from a list, with the head of the list at the TM head and the rest going -to the right. -/ -def Tape.mk₁ {Γ} [Inhabited Γ] (l : List Γ) : Tape Γ := - Tape.mk₂ [] l - -/-- The `nth` function of a tape is integer-valued, with index `0` being the head, negative indexes -on the left and positive indexes on the right. (Picture a number line.) -/ -def Tape.nth {Γ} [Inhabited Γ] (T : Tape Γ) : ℤ → Γ - | 0 => T.head - | (n + 1 : ℕ) => T.right.nth n - | -(n + 1 : ℕ) => T.left.nth n - -@[simp] -theorem Tape.nth_zero {Γ} [Inhabited Γ] (T : Tape Γ) : T.nth 0 = T.1 := - rfl - -theorem Tape.right₀_nth {Γ} [Inhabited Γ] (T : Tape Γ) (n : ℕ) : T.right₀.nth n = T.nth n := by - cases n <;> simp only [Tape.nth, Tape.right₀, Int.ofNat_zero, ListBlank.nth_zero, - ListBlank.nth_succ, ListBlank.head_cons, ListBlank.tail_cons] - -@[simp] -theorem Tape.mk'_nth_nat {Γ} [Inhabited Γ] (L R : ListBlank Γ) (n : ℕ) : - (Tape.mk' L R).nth n = R.nth n := by - rw [← Tape.right₀_nth, Tape.mk'_right₀] - -@[simp] -theorem Tape.move_left_nth {Γ} [Inhabited Γ] : - ∀ (T : Tape Γ) (i : ℤ), (T.move Dir.left).nth i = T.nth (i - 1) - | ⟨_, _, _⟩, -(_ + 1 : ℕ) => (ListBlank.nth_succ _ _).symm - | ⟨_, _, _⟩, 0 => (ListBlank.nth_zero _).symm - | ⟨_, _, _⟩, 1 => (ListBlank.nth_zero _).trans (ListBlank.head_cons _ _) - | ⟨a, L, R⟩, (n + 1 : ℕ) + 1 => by - rw [add_sub_cancel_right] - change (R.cons a).nth (n + 1) = R.nth n - rw [ListBlank.nth_succ, ListBlank.tail_cons] - -@[simp] -theorem Tape.move_right_nth {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℤ) : - (T.move Dir.right).nth i = T.nth (i + 1) := by - conv => rhs; rw [← T.move_right_left] - rw [Tape.move_left_nth, add_sub_cancel_right] - -@[simp] -theorem Tape.move_right_n_head {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℕ) : - ((Tape.move Dir.right)^[i] T).head = T.nth i := by - induction i generalizing T - · rfl - · simp only [*, Tape.move_right_nth, Int.ofNat_succ, iterate_succ, Function.comp_apply] - -/-- Replace the current value of the head on the tape. -/ -def Tape.write {Γ} [Inhabited Γ] (b : Γ) (T : Tape Γ) : Tape Γ := - { T with head := b } - -@[simp] -theorem Tape.write_self {Γ} [Inhabited Γ] : ∀ T : Tape Γ, T.write T.1 = T := by - rintro ⟨⟩; rfl - -@[simp] -theorem Tape.write_nth {Γ} [Inhabited Γ] (b : Γ) : - ∀ (T : Tape Γ) {i : ℤ}, (T.write b).nth i = if i = 0 then b else T.nth i - | _, 0 => rfl - | _, (_ + 1 : ℕ) => rfl - | _, -(_ + 1 : ℕ) => rfl - -@[simp] -theorem Tape.write_mk' {Γ} [Inhabited Γ] (a b : Γ) (L R : ListBlank Γ) : - (Tape.mk' L (R.cons a)).write b = Tape.mk' L (R.cons b) := by - simp only [Tape.write, Tape.mk', ListBlank.head_cons, ListBlank.tail_cons, eq_self_iff_true, - and_self_iff] - -/-- Apply a pointed map to a tape to change the alphabet. -/ -def Tape.map {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) : Tape Γ' := - ⟨f T.1, T.2.map f, T.3.map f⟩ - -@[simp] -theorem Tape.map_fst {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') : - ∀ T : Tape Γ, (T.map f).1 = f T.1 := by - rintro ⟨⟩; rfl - -@[simp] -theorem Tape.map_write {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (b : Γ) : - ∀ T : Tape Γ, (T.write b).map f = (T.map f).write (f b) := by - rintro ⟨⟩; rfl - --- Porting note: `simpNF` complains about LHS does not simplify when using the simp lemma on --- itself, but it does indeed. -@[simp, nolint simpNF] -theorem Tape.write_move_right_n {Γ} [Inhabited Γ] (f : Γ → Γ) (L R : ListBlank Γ) (n : ℕ) : - ((Tape.move Dir.right)^[n] (Tape.mk' L R)).write (f (R.nth n)) = - (Tape.move Dir.right)^[n] (Tape.mk' L (R.modifyNth f n)) := by - induction' n with n IH generalizing L R - · simp only [ListBlank.nth_zero, ListBlank.modifyNth, iterate_zero_apply] - rw [← Tape.write_mk', ListBlank.cons_head_tail] - simp only [ListBlank.head_cons, ListBlank.nth_succ, ListBlank.modifyNth, Tape.move_right_mk', - ListBlank.tail_cons, iterate_succ_apply, IH] - -theorem Tape.map_move {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) (d) : - (T.move d).map f = (T.map f).move d := by - cases T - cases d <;> simp only [Tape.move, Tape.map, ListBlank.head_map, eq_self_iff_true, - ListBlank.map_cons, and_self_iff, ListBlank.tail_map] - -theorem Tape.map_mk' {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (L R : ListBlank Γ) : - (Tape.mk' L R).map f = Tape.mk' (L.map f) (R.map f) := by - simp only [Tape.mk', Tape.map, ListBlank.head_map, eq_self_iff_true, and_self_iff, - ListBlank.tail_map] - -theorem Tape.map_mk₂ {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (L R : List Γ) : - (Tape.mk₂ L R).map f = Tape.mk₂ (L.map f) (R.map f) := by - simp only [Tape.mk₂, Tape.map_mk', ListBlank.map_mk] - -theorem Tape.map_mk₁ {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (l : List Γ) : - (Tape.mk₁ l).map f = Tape.mk₁ (l.map f) := - Tape.map_mk₂ _ _ _ - /-- Run a state transition function `σ → Option σ` "to completion". The return value is the last state returned before a `none` result. If the state transition function always returns `some`, then the computation diverges, returning `Part.none`. -/ @@ -2569,4 +1987,4 @@ end TM2to1 end Turing -set_option linter.style.longFile 2700 +set_option linter.style.longFile 2100 From e6c7f46380cd18cb17d8759249c26429e6893b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 16 Jan 2025 22:07:20 +0000 Subject: [PATCH 273/681] feat(Algebra/Homology/Embedding): the morphism from a complex to its `truncGE` truncation (#19544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given an embedding `e` of complex shapes which satisfies `e.IsTruncGE`, we define the canonical (natural) epimorphism `K.πTruncGE e : K ⟶ K.truncGE e` from a complex to its canonical truncation. --- .../Algebra/Homology/Embedding/HomEquiv.lean | 7 + .../Algebra/Homology/Embedding/TruncGE.lean | 187 +++++++++++++++++- .../Limits/Shapes/ZeroObjects.lean | 6 + 3 files changed, 196 insertions(+), 4 deletions(-) diff --git a/Mathlib/Algebra/Homology/Embedding/HomEquiv.lean b/Mathlib/Algebra/Homology/Embedding/HomEquiv.lean index ae8a61b3f4536..28560a2613136 100644 --- a/Mathlib/Algebra/Homology/Embedding/HomEquiv.lean +++ b/Mathlib/Algebra/Homology/Embedding/HomEquiv.lean @@ -194,6 +194,13 @@ lemma homRestrict_precomp (α : K' ⟶ K) (ψ : K ⟶ L.extend e) : ext i simp [homRestrict_f _ _ rfl, restrictionXIso] +@[reassoc] +lemma homRestrict_comp_extendMap (ψ : K ⟶ L.extend e) (β : L ⟶ L') : + e.homRestrict (ψ ≫ extendMap β e) = + e.homRestrict ψ ≫ β := by + ext i + simp [homRestrict_f _ _ rfl, extendMap_f β e rfl] + variable (K L) /-- The bijection between `K ⟶ L.extend e` and the subtype of `K.restriction e ⟶ L` diff --git a/Mathlib/Algebra/Homology/Embedding/TruncGE.lean b/Mathlib/Algebra/Homology/Embedding/TruncGE.lean index 8bac0da93a294..aa2a959a8d2ac 100644 --- a/Mathlib/Algebra/Homology/Embedding/TruncGE.lean +++ b/Mathlib/Algebra/Homology/Embedding/TruncGE.lean @@ -3,8 +3,8 @@ 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.Homology.Embedding.Boundary -import Mathlib.Algebra.Homology.Embedding.Extend +import Mathlib.Algebra.Homology.Embedding.HomEquiv +import Mathlib.Algebra.Homology.Embedding.IsSupported import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex /-! @@ -31,9 +31,11 @@ following shape: where `Q` is in degree `p`. +We also construct the canonical epimorphism `K.πTruncGE e : K ⟶ K.truncGE e`. + ## TODO -* construct a morphism `K.πTruncGE e : K ⟶ K.truncGE e` and show that -it induces an isomorphism in homology in degrees in the image of `e.f`. +* show that `K.πTruncGE e : K ⟶ K.truncGE e` induces an isomorphism +in homology in degrees in the image of `e.f`. -/ @@ -219,6 +221,172 @@ lemma truncGEMap_comp : truncGEMap (φ ≫ φ') e = truncGEMap φ e ≫ truncGEM end +namespace restrictionToTruncGE' + +open Classical in +/-- Auxiliary definition for `HomologicalComplex.restrictionToTruncGE'`. -/ +noncomputable def f (i : ι) : (K.restriction e).X i ⟶ (K.truncGE' e).X i := + if hi : e.BoundaryGE i then + K.pOpcycles _ ≫ (K.truncGE'XIsoOpcycles e rfl hi).inv + else + (K.truncGE'XIso e rfl hi).inv + +lemma f_eq_iso_hom_pOpcycles_iso_inv {i : ι} {i' : ι'} (hi' : e.f i = i') (hi : e.BoundaryGE i) : + f K e i = (K.restrictionXIso e hi').hom ≫ K.pOpcycles i' ≫ + (K.truncGE'XIsoOpcycles e hi' hi).inv := by + dsimp [f] + rw [dif_pos hi] + subst hi' + simp [restrictionXIso] + +lemma f_eq_iso_hom_iso_inv {i : ι} {i' : ι'} (hi' : e.f i = i') (hi : ¬ e.BoundaryGE i) : + f K e i = (K.restrictionXIso e hi').hom ≫ (K.truncGE'XIso e hi' hi).inv := by + dsimp [f] + rw [dif_neg hi] + subst hi' + simp [restrictionXIso] + +@[reassoc (attr := simp)] +lemma comm (i j : ι) : + f K e i ≫ (K.truncGE' e).d i j = (K.restriction e).d i j ≫ f K e j := by + by_cases hij : c.Rel i j + · by_cases hi : e.BoundaryGE i + · rw [f_eq_iso_hom_pOpcycles_iso_inv K e rfl hi, + f_eq_iso_hom_iso_inv K e rfl (e.not_boundaryGE_next hij), + K.truncGE'_d_eq_fromOpcycles e hij rfl rfl hi] + simp [restrictionXIso] + · rw [f_eq_iso_hom_iso_inv K e rfl hi, + f_eq_iso_hom_iso_inv K e rfl (e.not_boundaryGE_next hij), + K.truncGE'_d_eq e hij rfl rfl hi] + simp [restrictionXIso] + · simp [HomologicalComplex.shape _ _ _ hij] + +end restrictionToTruncGE' + +/-- The canonical morphism `K.restriction e ⟶ K.truncGE' e`. -/ +noncomputable def restrictionToTruncGE' : K.restriction e ⟶ K.truncGE' e where + f := restrictionToTruncGE'.f K e + +lemma restrictionToTruncGE'_hasLift : e.HasLift (K.restrictionToTruncGE' e) := by + intro j hj i' _ + dsimp [restrictionToTruncGE'] + rw [restrictionToTruncGE'.f_eq_iso_hom_pOpcycles_iso_inv K e rfl hj] + simp [restrictionXIso] + +lemma restrictionToTruncGE'_f_eq_iso_hom_pOpcycles_iso_inv + {i : ι} {i' : ι'} (hi' : e.f i = i') (hi : e.BoundaryGE i) : + (K.restrictionToTruncGE' e).f i = (K.restrictionXIso e hi').hom ≫ K.pOpcycles i' ≫ + (K.truncGE'XIsoOpcycles e hi' hi).inv := by + apply restrictionToTruncGE'.f_eq_iso_hom_pOpcycles_iso_inv + +lemma restrictionToTruncGE'_f_eq_iso_hom_iso_inv {i : ι} {i' : ι'} (hi' : e.f i = i') + (hi : ¬ e.BoundaryGE i) : + (K.restrictionToTruncGE' e).f i = + (K.restrictionXIso e hi').hom ≫ (K.truncGE'XIso e hi' hi).inv := by + apply restrictionToTruncGE'.f_eq_iso_hom_iso_inv + +/-- `K.restrictionToTruncGE' e).f i` is an isomorphism when `¬ e.BoundaryGE i`. -/ +lemma isIso_restrictionToTruncGE' (i : ι) (hi : ¬ e.BoundaryGE i) : + IsIso ((K.restrictionToTruncGE' e).f i) := by + rw [K.restrictionToTruncGE'_f_eq_iso_hom_iso_inv e rfl hi] + infer_instance + +variable {K L} in +@[reassoc (attr := simp)] +lemma restrictionToTruncGE'_naturality : + K.restrictionToTruncGE' e ≫ truncGE'Map φ e = + restrictionMap φ e ≫ L.restrictionToTruncGE' e := by + ext i + by_cases hi : e.BoundaryGE i + · simp [restrictionToTruncGE'_f_eq_iso_hom_pOpcycles_iso_inv _ e rfl hi, + truncGE'Map_f_eq_opcyclesMap φ e hi rfl, restrictionXIso] + · simp [restrictionToTruncGE'_f_eq_iso_hom_iso_inv _ e rfl hi, + truncGE'Map_f_eq φ e hi rfl, restrictionXIso] + +attribute [local instance] epi_comp in +instance (i : ι) : Epi ((K.restrictionToTruncGE' e).f i) := by + by_cases hi : e.BoundaryGE i + · rw [K.restrictionToTruncGE'_f_eq_iso_hom_pOpcycles_iso_inv e rfl hi] + infer_instance + · have := K.isIso_restrictionToTruncGE' e i hi + infer_instance + +instance [K.IsStrictlySupported e] (i : ι) : + IsIso ((K.restrictionToTruncGE' e).f i) := by + by_cases hi : e.BoundaryGE i + · rw [K.restrictionToTruncGE'_f_eq_iso_hom_pOpcycles_iso_inv e rfl hi] + have : IsIso (K.pOpcycles (e.f i)) := K.isIso_pOpcycles _ _ rfl (by + obtain ⟨hi₁, hi₂⟩ := hi + apply IsZero.eq_of_src (K.isZero_X_of_isStrictlySupported e _ + (fun j hj ↦ hi₂ j (by simpa only [hj] using hi₁)))) + infer_instance + · rw [K.restrictionToTruncGE'_f_eq_iso_hom_iso_inv e rfl hi] + infer_instance + +section + +variable [HasZeroObject C] + +/-- The canonical morphism `K ⟶ K.truncGE e` when `e` is an embedding of complex +shapes which satisfy `e.IsTruncGE`. -/ +noncomputable def πTruncGE : K ⟶ K.truncGE e := + e.liftExtend (K.restrictionToTruncGE' e) (K.restrictionToTruncGE'_hasLift e) + +instance (i' : ι') : Epi ((K.πTruncGE e).f i') := by + by_cases hi' : ∃ i, e.f i = i' + · obtain ⟨i, hi⟩ := hi' + dsimp [πTruncGE] + rw [e.epi_liftExtend_f_iff _ _ hi] + infer_instance + · apply (isZero_extend_X _ _ _ (by simpa using hi')).epi + +instance : Epi (K.πTruncGE e) := epi_of_epi_f _ (fun _ => inferInstance) + +instance : (K.truncGE e).IsStrictlySupported e := by + dsimp [truncGE] + infer_instance + +variable {K L} in +@[reassoc (attr := simp)] +lemma πTruncGE_naturality : + K.πTruncGE e ≫ truncGEMap φ e = φ ≫ L.πTruncGE e := by + apply (e.homEquiv _ _).injective + ext1 + dsimp [truncGEMap, πTruncGE] + rw [e.homRestrict_comp_extendMap, e.homRestrict_liftExtend, e.homRestrict_precomp, + e.homRestrict_liftExtend, restrictionToTruncGE'_naturality] + +instance {ι'' : Type*} {c'' : ComplexShape ι''} (e' : c''.Embedding c') + [K.IsStrictlySupported e'] : (K.truncGE e).IsStrictlySupported e' where + isZero := by + intro i' hi' + by_cases hi'' : ∃ i, e.f i = i' + · obtain ⟨i, hi⟩ := hi'' + by_cases hi''' : e.BoundaryGE i + · rw [IsZero.iff_id_eq_zero, ← cancel_epi + ((K.truncGE' e).extendXIso e hi ≪≫ K.truncGE'XIsoOpcycles e hi hi''').inv, + ← cancel_epi (HomologicalComplex.pOpcycles _ _)] + apply (K.isZero_X_of_isStrictlySupported e' i' hi').eq_of_src + · exact (K.isZero_X_of_isStrictlySupported e' i' hi').of_iso + ((K.truncGE' e).extendXIso e hi ≪≫ K.truncGE'XIso e hi hi''') + · exact (K.truncGE e).isZero_X_of_isStrictlySupported e _ (by simpa using hi'') + +instance [K.IsStrictlySupported e] : IsIso (K.πTruncGE e) := by + suffices ∀ (i' : ι'), IsIso ((K.πTruncGE e).f i') by + apply Hom.isIso_of_components + intro i' + by_cases hn : ∃ i, e.f i = i' + · obtain ⟨i, hi⟩ := hn + dsimp [πTruncGE] + rw [e.isIso_liftExtend_f_iff _ _ hi] + infer_instance + · simp only [not_exists] at hn + refine ⟨0, ?_, ?_⟩ + all_goals + apply (isZero_X_of_isStrictlySupported _ e i' hn).eq_of_src + +end + end HomologicalComplex namespace ComplexShape.Embedding @@ -235,6 +403,12 @@ noncomputable def truncGE'Functor : obj K := K.truncGE' e map φ := HomologicalComplex.truncGE'Map φ e +/-- The natural transformation `K.restriction e ⟶ K.truncGE' e` for all `K`. -/ +@[simps] +noncomputable def restrictionToTruncGE'NatTrans : + e.restrictionFunctor C ⟶ e.truncGE'Functor C where + app K := K.restrictionToTruncGE' e + /-- Given an embedding `e : Embedding c c'` of complex shapes which satisfy `e.IsTruncGE`, this is the (canonical) truncation functor `HomologicalComplex C c' ⥤ HomologicalComplex C c'`. -/ @@ -244,4 +418,9 @@ noncomputable def truncGEFunctor : obj K := K.truncGE e map φ := HomologicalComplex.truncGEMap φ e +/-- The natural transformation `K.πTruncGE e : K ⟶ K.truncGE e` for all `K`. -/ +@[simps] +noncomputable def πTruncGENatTrans : 𝟭 _ ⟶ e.truncGEFunctor C where + app K := K.πTruncGE e + end ComplexShape.Embedding diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean b/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean index 54f3a9e56b996..dde1fdd1479ca 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ZeroObjects.lean @@ -75,6 +75,12 @@ theorem eq_of_src (hX : IsZero X) (f g : X ⟶ Y) : f = g := theorem eq_of_tgt (hX : IsZero X) (f g : Y ⟶ X) : f = g := (hX.eq_from f).trans (hX.eq_from g).symm +lemma epi (h : IsZero X) {Y : C} (f : Y ⟶ X) : Epi f where + left_cancellation _ _ _ := h.eq_of_src _ _ + +lemma mono (h : IsZero X) {Y : C} (f : X ⟶ Y) : Mono f where + right_cancellation _ _ _ := h.eq_of_tgt _ _ + /-- Any two zero objects are isomorphic. -/ def iso (hX : IsZero X) (hY : IsZero Y) : X ≅ Y where hom := hX.to_ Y From a76d7c91b5e43ff52e0505cb48cc8efcfd24cdcc Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Fri, 17 Jan 2025 03:48:42 +0000 Subject: [PATCH 274/681] refactor: rename `UniqueContinuousFunctionalCalculus` to `ContinuousMap.UniqueHom` (#20643) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that `UniqueContinuousFunctionalCalculus` no longer mentions `spectrum`, it really has very little to tie it to the ContinuousFunctionalCalculus. In some sense, it's just a property of `C(s, R)`, but because we want to allow `R := ℝ≥0`, the algebra `A` also matters. Because of this, we put the class within the `ContinuousMap` namespace. We also rename `UniqueNonUnitalContinuousFunctionalCalculus` to `ContinuousMapZero.UniqueHom`. --- .../ContinuousFunctionalCalculus/Basic.lean | 4 +- .../Isometric.lean | 4 +- .../NonUnital.lean | 28 +++++++------- .../Restrict.lean | 4 +- .../ContinuousFunctionalCalculus/Unique.lean | 38 +++++++++---------- .../ContinuousFunctionalCalculus/Unital.lean | 23 ++++++----- .../ContinuousFunctionalCalculus/PosPart.lean | 4 +- 7 files changed, 55 insertions(+), 50 deletions(-) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean index 4df7e6a636e68..8bbd95c101c6c 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean @@ -185,7 +185,7 @@ lemma inr_comp_cfcₙHom_eq_cfcₙAux {A : Type*} [NonUnitalCStarAlgebra A] (a : [ha : IsStarNormal a] : (inrNonUnitalStarAlgHom ℂ A).comp (cfcₙHom ha) = cfcₙAux (isStarNormal_inr (R := ℂ) (A := A)) a ha := by have h (a : A) := isStarNormal_inr (R := ℂ) (A := A) (a := a) - refine @UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id + refine @ContinuousMapZero.UniqueHom.eq_of_continuous_of_map_id _ _ _ _ _ _ _ _ _ _ _ inferInstance inferInstance _ (σₙ ℂ a) _ _ rfl _ _ ?_ ?_ ?_ · show Continuous (fun f ↦ (cfcₙHom ha f : A⁺¹)); fun_prop · exact isClosedEmbedding_cfcₙAux @(h) a ha |>.continuous @@ -451,7 +451,7 @@ lemma Unitization.cfcₙ_eq_cfc_inr {R : Type*} [Semifield R] [StarRing R] [Metr [SMulCommClass R A A] [CompleteSpace R] [Algebra R ℂ] [IsScalarTower R ℂ A] {p : A → Prop} {p' : A⁺¹ → Prop} [NonUnitalContinuousFunctionalCalculus R p] [ContinuousFunctionalCalculus R p'] - [UniqueNonUnitalContinuousFunctionalCalculus R (Unitization ℂ A)] + [ContinuousMapZero.UniqueHom R (Unitization ℂ A)] (hp : ∀ {a : A}, p' (a : A⁺¹) ↔ p a) (a : A) (f : R → R) (hf₀ : f 0 = 0 := by cfc_zero_tac) : cfcₙ f a = cfc f (a : A⁺¹) := by by_cases h : ContinuousOn f (σₙ R a) ∧ p a diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean index d96bd2baa0244..080dd2282f617 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean @@ -150,7 +150,7 @@ variable [Semifield S] [StarRing S] [MetricSpace S] [TopologicalSemiring S] [Con variable [Ring A] [StarRing A] [Algebra S A] variable [Algebra R S] [Algebra R A] [IsScalarTower R S A] [StarModule R S] [ContinuousSMul R S] variable [MetricSpace A] [IsometricContinuousFunctionalCalculus S A q] -variable [CompleteSpace R] [UniqueContinuousFunctionalCalculus R A] +variable [CompleteSpace R] [ContinuousMap.UniqueHom R A] open scoped ContinuousFunctionalCalculus in protected theorem isometric_cfc (f : C(S, R)) (halg : Isometry (algebraMap R S)) (h0 : p 0) @@ -321,7 +321,7 @@ variable [SMulCommClass S A A] variable [Algebra R S] [Module R A] [IsScalarTower R S A] [StarModule R S] [ContinuousSMul R S] variable [IsScalarTower R A A] [SMulCommClass R A A] variable [MetricSpace A] [NonUnitalIsometricContinuousFunctionalCalculus S A q] -variable [CompleteSpace R] [UniqueNonUnitalContinuousFunctionalCalculus R A] +variable [CompleteSpace R] [ContinuousMapZero.UniqueHom R A] open scoped NonUnitalContinuousFunctionalCalculus in protected theorem isometric_cfc (f : C(S, R)) (halg : Isometry (algebraMap R S)) (h0 : p 0) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean index 715cccb881a6d..18bf6f950c550 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean @@ -27,7 +27,7 @@ vanish at zero. More precisely, it is a continuous star algebra homomorphism `C(quasispectrum R a, R)₀ →⋆ₙₐ[R] A` that sends `(ContinuousMap.id R).restrict (quasispectrum R a)` to `a`. In all cases of interest (e.g., when `quasispectrum R a` is compact and `R` is `ℝ≥0`, `ℝ`, or `ℂ`), this is sufficient to uniquely determine the continuous functional calculus which is -encoded in the `UniqueNonUnitalContinuousFunctionalCalculus` class. +encoded in the `ContinuousMapZero.UniqueHom` class. ## Main declarations @@ -47,8 +47,7 @@ encoded in the `UniqueNonUnitalContinuousFunctionalCalculus` class. -/ local notation "σₙ" => quasispectrum -open Topology -open scoped ContinuousMapZero +open Topology ContinuousMapZero /-- A non-unital star `R`-algebra `A` has a *continuous functional calculus* for elements satisfying the property `p : A → Prop` if @@ -91,7 +90,7 @@ and the more common variant `cfcₙ_comp`. This class will have instances in each of the common cases `ℂ`, `ℝ` and `ℝ≥0` as a consequence of the Stone-Weierstrass theorem. -/ -class UniqueNonUnitalContinuousFunctionalCalculus (R A : Type*) [CommSemiring R] [StarRing R] +class ContinuousMapZero.UniqueHom (R A : Type*) [CommSemiring R] [StarRing R] [MetricSpace R] [TopologicalSemiring R] [ContinuousStar R] [NonUnitalRing A] [StarRing A] [TopologicalSpace A] [Module R A] [IsScalarTower R A A] [SMulCommClass R A A] : Prop where eq_of_continuous_of_map_id (s : Set R) [CompactSpace s] [Zero s] (h0 : (0 : s) = (0 : R)) @@ -99,6 +98,9 @@ class UniqueNonUnitalContinuousFunctionalCalculus (R A : Type*) [CommSemiring R] (h : φ (⟨.restrict s <| .id R, h0⟩) = ψ (⟨.restrict s <| .id R, h0⟩)) : φ = ψ +@[deprecated (since := "2025-01-10")] alias UniqueNonUnitalContinuousFunctionalCalculus := + ContinuousMapZero.UniqueHom + section Main variable {R A : Type*} {p : A → Prop} [CommSemiring R] [Nontrivial R] [StarRing R] [MetricSpace R] @@ -111,12 +113,12 @@ lemma NonUnitalContinuousFunctionalCalculus.isCompact_quasispectrum (a : A) : IsCompact (σₙ R a) := isCompact_iff_compactSpace.mpr inferInstance -lemma NonUnitalStarAlgHom.ext_continuousMap [UniqueNonUnitalContinuousFunctionalCalculus R A] +lemma NonUnitalStarAlgHom.ext_continuousMap [UniqueHom R A] (a : A) [CompactSpace (σₙ R a)] (φ ψ : C(σₙ R a, R)₀ →⋆ₙₐ[R] A) (hφ : Continuous φ) (hψ : Continuous ψ) (h : φ ⟨.restrict (σₙ R a) <| .id R, rfl⟩ = ψ ⟨.restrict (σₙ R a) <| .id R, rfl⟩) : φ = ψ := - UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id _ (by simp) φ ψ hφ hψ h + UniqueHom.eq_of_continuous_of_map_id _ (by simp) φ ψ hφ hψ h section cfcₙHom @@ -158,13 +160,13 @@ lemma cfcₙHom_predicate (f : C(σₙ R a, R)₀) : (NonUnitalContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2 f open scoped NonUnitalContinuousFunctionalCalculus in -lemma cfcₙHom_eq_of_continuous_of_map_id [UniqueNonUnitalContinuousFunctionalCalculus R A] +lemma cfcₙHom_eq_of_continuous_of_map_id [UniqueHom R A] (φ : C(σₙ R a, R)₀ →⋆ₙₐ[R] A) (hφ₁ : Continuous φ) (hφ₂ : φ ⟨.restrict (σₙ R a) <| .id R, rfl⟩ = a) : cfcₙHom ha = φ := (cfcₙHom ha).ext_continuousMap a φ (cfcₙHom_isClosedEmbedding ha).continuous hφ₁ <| by rw [cfcₙHom_id ha, hφ₂] -theorem cfcₙHom_comp [UniqueNonUnitalContinuousFunctionalCalculus R A] (f : C(σₙ R a, R)₀) +theorem cfcₙHom_comp [UniqueHom R A] (f : C(σₙ R a, R)₀) (f' : C(σₙ R a, σₙ R (cfcₙHom ha f))₀) (hff' : ∀ x, f x = f' x) (g : C(σₙ R (cfcₙHom ha f), R)₀) : cfcₙHom ha (g.comp f') = cfcₙHom (cfcₙHom_predicate ha f) g := by @@ -426,7 +428,7 @@ lemma cfcₙ_star_id : cfcₙ (star · : R → R) a = star a := by section Comp -variable [UniqueNonUnitalContinuousFunctionalCalculus R A] +variable [UniqueHom R A] lemma cfcₙ_comp (g f : R → R) (a : A) (hg : ContinuousOn g (f '' σₙ R a) := by cfc_cont_tac) (hg0 : g 0 = 0 := by cfc_zero_tac) @@ -552,7 +554,7 @@ lemma cfcₙ_neg_id (ha : p a := by cfc_tac) : cfcₙ (- · : R → R) a = -a := by rw [cfcₙ_neg .., cfcₙ_id' R a] -variable [UniqueNonUnitalContinuousFunctionalCalculus R A] +variable [UniqueHom R A] lemma cfcₙ_comp_neg (hf : ContinuousOn f ((- ·) '' (σₙ R a)) := by cfc_cont_tac) (h0 : f 0 = 0 := by cfc_zero_tac) (ha : p a := by cfc_tac) : @@ -790,9 +792,9 @@ instance ContinuousFunctionalCalculus.toNonUnital : NonUnitalContinuousFunctiona fun _ ↦ cfcHom_predicate ha _⟩ open scoped NonUnitalContinuousFunctionalCalculus in -lemma cfcₙHom_eq_cfcₙHom_of_cfcHom [UniqueNonUnitalContinuousFunctionalCalculus R A] {a : A} +lemma cfcₙHom_eq_cfcₙHom_of_cfcHom [ContinuousMapZero.UniqueHom R A] {a : A} (ha : p a) : cfcₙHom (R := R) ha = cfcₙHom_of_cfcHom R ha := by - refine UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id + refine ContinuousMapZero.UniqueHom.eq_of_continuous_of_map_id (σₙ R a) ?_ _ _ ?_ ?_ ?_ · simp · exact (cfcₙHom_isClosedEmbedding (R := R) ha).continuous @@ -801,7 +803,7 @@ lemma cfcₙHom_eq_cfcₙHom_of_cfcHom [UniqueNonUnitalContinuousFunctionalCalcu /-- When `cfc` is applied to a function that maps zero to zero, it is equivalent to using `cfcₙ`. -/ -lemma cfcₙ_eq_cfc [UniqueNonUnitalContinuousFunctionalCalculus R A] {f : R → R} {a : A} +lemma cfcₙ_eq_cfc [ContinuousMapZero.UniqueHom R A] {f : R → R} {a : A} (hf : ContinuousOn f (σₙ R a) := by cfc_cont_tac) (hf0 : f 0 = 0 := by cfc_zero_tac) : cfcₙ f a = cfc f a := by by_cases ha : p a diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean index 99c418deebe34..990fdf8c0562b 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean @@ -140,7 +140,7 @@ protected theorem cfc (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) obtain ⟨r, rfl⟩ := hs simp [((h a).mp ha).2.left_inv _] -variable [ContinuousFunctionalCalculus R p] [UniqueContinuousFunctionalCalculus R A] +variable [ContinuousFunctionalCalculus R p] [ContinuousMap.UniqueHom R A] lemma cfcHom_eq_restrict (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) {a : A} (hpa : p a) (hqa : q a) (h : SpectrumRestricts a f) : @@ -289,7 +289,7 @@ protected theorem cfc (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) simp [((h a).mp ha).2.left_inv _] variable [NonUnitalContinuousFunctionalCalculus R p] -variable [UniqueNonUnitalContinuousFunctionalCalculus R A] +variable [ContinuousMapZero.UniqueHom R A] lemma cfcₙHom_eq_restrict (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) {a : A} (hpa : p a) (hqa : q a) (h : QuasispectrumRestricts a f) : diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean index a00aad44e7849..20dd1bbbdc110 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean @@ -20,7 +20,7 @@ The same is true for `𝕜 := ℝ≥0`, so long as the algebra `A` is an `ℝ`-a by upgrading a map `C((s : Set ℝ≥0), ℝ≥0) →⋆ₐ[ℝ≥0] A` to `C(((↑) '' s : Set ℝ), ℝ) →⋆ₐ[ℝ] A` in the natural way, and then applying the uniqueness for `ℝ`-algebra homomorphisms. -This is the reason the `UniqueContinuousFunctionalCalculus` class exists in the first place, as +This is the reason the `ContinuousMap.UniqueHom` class exists in the first place, as opposed to simply appealing directly to Stone-Weierstrass to prove `StarAlgHom.ext_continuousMap`. -/ @@ -32,22 +32,22 @@ section RCLike variable {𝕜 A : Type*} [RCLike 𝕜] -instance (priority := 100) RCLike.uniqueContinuousFunctionalCalculus [TopologicalSpace A] +instance (priority := 100) RCLike.instContinuousMapUniqueHom [TopologicalSpace A] [T2Space A] [Ring A] [StarRing A] [Algebra 𝕜 A] : - UniqueContinuousFunctionalCalculus 𝕜 A where + ContinuousMap.UniqueHom 𝕜 A where eq_of_continuous_of_map_id s _ φ ψ hφ hψ h := ContinuousMap.starAlgHom_ext_map_X hφ hψ <| by convert h using 1 all_goals exact congr_arg _ (by ext; simp) -instance Real.uniqueContinuousFunctionalCalculus [TopologicalSpace A] +instance Real.instContinuousMapUniqueHom [TopologicalSpace A] [T2Space A] [Ring A] [StarRing A] [Algebra ℝ A] : - UniqueContinuousFunctionalCalculus ℝ A := + ContinuousMap.UniqueHom ℝ A := inferInstance -instance Complex.uniqueContinuousFunctionalCalculus [TopologicalSpace A] +instance Complex.instContinuousMapUniqueHom [TopologicalSpace A] [T2Space A] [Ring A] [StarRing A] [Algebra ℂ A] : - UniqueContinuousFunctionalCalculus ℂ A := + ContinuousMap.UniqueHom ℂ A := inferInstance end RCLike @@ -170,8 +170,8 @@ end StarAlgHom variable [TopologicalSpace A] [TopologicalRing A] -instance NNReal.instUniqueContinuousFunctionalCalculus [T2Space A] : - UniqueContinuousFunctionalCalculus ℝ≥0 A where +instance NNReal.instContinuousMap.UniqueHom [T2Space A] : + ContinuousMap.UniqueHom ℝ≥0 A where eq_of_continuous_of_map_id s hs φ ψ hφ hψ h := by let s' : Set ℝ := (↑) '' s let e : s ≃ₜ s' := @@ -194,7 +194,7 @@ instance NNReal.instUniqueContinuousFunctionalCalculus [T2Space A] : obtain ⟨hφ', hφ_id⟩ := this φ hφ obtain ⟨hψ', hψ_id⟩ := this ψ hψ have hs' : CompactSpace s' := e.compactSpace - have h' := UniqueContinuousFunctionalCalculus.eq_of_continuous_of_map_id s' _ _ hφ' hψ' + have h' := ContinuousMap.UniqueHom.eq_of_continuous_of_map_id s' _ _ hφ' hψ' (hφ_id ▸ hψ_id ▸ h) have h'' := congr($(h').comp <| ContinuousMap.compStarAlgHom' ℝ ℝ (e.symm : C(s', s))) have : (ContinuousMap.compStarAlgHom' ℝ ℝ (e : C(s, s'))).comp @@ -217,7 +217,7 @@ open NonUnitalStarAlgebra in instance RCLike.uniqueNonUnitalContinuousFunctionalCalculus [TopologicalSpace A] [T2Space A] [NonUnitalRing A] [StarRing A] [Module 𝕜 A] [IsScalarTower 𝕜 A A] [SMulCommClass 𝕜 A A] : - UniqueNonUnitalContinuousFunctionalCalculus 𝕜 A where + ContinuousMapZero.UniqueHom 𝕜 A where eq_of_continuous_of_map_id s hs _inst h0 φ ψ hφ hψ h := by rw [DFunLike.ext'_iff, ← Set.eqOn_univ, ← (ContinuousMapZero.adjoin_id_dense h0).closure_eq] refine Set.EqOn.closure (fun f hf ↦ ?_) hφ hψ @@ -357,10 +357,10 @@ end NonUnitalStarAlgHom open ContinuousMapZero -instance NNReal.instUniqueNonUnitalContinuousFunctionalCalculus +instance NNReal.instContinuousMapZero.UniqueHom [TopologicalSpace A] [TopologicalRing A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] [T2Space A] : - UniqueNonUnitalContinuousFunctionalCalculus ℝ≥0 A where + ContinuousMapZero.UniqueHom ℝ≥0 A where eq_of_continuous_of_map_id s hs _inst h0 φ ψ hφ hψ h := by let s' : Set ℝ := (↑) '' s let e : s ≃ₜ s' := @@ -390,8 +390,8 @@ instance NNReal.instUniqueNonUnitalContinuousFunctionalCalculus obtain ⟨hφ', hφ_id⟩ := this φ hφ obtain ⟨hψ', hψ_id⟩ := this ψ hψ have hs' : CompactSpace s' := e.compactSpace - have : UniqueNonUnitalContinuousFunctionalCalculus ℝ A := inferInstance - have h' := UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id + have : ContinuousMapZero.UniqueHom ℝ A := inferInstance + have h' := ContinuousMapZero.UniqueHom.eq_of_continuous_of_map_id s' h0' _ _ hφ' hψ' (hφ_id ▸ hψ_id ▸ h) have h'' := congr($(h').comp <| ContinuousMapZero.nonUnitalStarAlgHom_precomp ℝ ⟨(e.symm : C(s', s)), e0'⟩) @@ -419,7 +419,7 @@ variable {F R S A B : Type*} {p : A → Prop} {q : B → Prop} [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] - [UniqueNonUnitalContinuousFunctionalCalculus R B] [FunLike F A B] [NonUnitalAlgHomClass F S A B] + [ContinuousMapZero.UniqueHom R B] [FunLike F A B] [NonUnitalAlgHomClass F S A B] [StarHomClass F A B] include S in @@ -440,7 +440,7 @@ lemma NonUnitalStarAlgHomClass.map_cfcₙ (φ : F) (f : R → R) (a : A) have hf' : ContinuousOn f (quasispectrum R (ψ a)) := hf.mono h_spec rw [cfcₙ_apply .., cfcₙ_apply ..] exact DFunLike.congr_fun this _ - refine UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id _ rfl _ _ + refine ContinuousMapZero.UniqueHom.eq_of_continuous_of_map_id _ rfl _ _ ?_ ?_ ?apply_id case apply_id => trans cfcₙHom hψa ⟨.restrict (quasispectrum R (ψ a)) (.id R), rfl⟩ @@ -470,7 +470,7 @@ variable {F R S A B : Type*} {p : A → Prop} {q : B → Prop} [Ring B] [StarRing B] [TopologicalSpace B] [Algebra R B] [CommSemiring S] [Algebra R S] [Algebra S A] [Algebra S B] [IsScalarTower R S A] [IsScalarTower R S B] [ContinuousFunctionalCalculus R p] [ContinuousFunctionalCalculus R q] - [UniqueContinuousFunctionalCalculus R B] [FunLike F A B] [AlgHomClass F S A B] + [ContinuousMap.UniqueHom R B] [FunLike F A B] [AlgHomClass F S A B] [StarHomClass F A B] include S in @@ -489,7 +489,7 @@ lemma StarAlgHomClass.map_cfc (φ : F) (f : R → R) (a : A) have hf' : ContinuousOn f (spectrum R (ψ a)) := hf.mono h_spec rw [cfc_apply .., cfc_apply ..] congrm($(this) ⟨_, hf.restrict⟩) - refine UniqueContinuousFunctionalCalculus.eq_of_continuous_of_map_id _ _ _ ?_ ?_ ?apply_id + refine ContinuousMap.UniqueHom.eq_of_continuous_of_map_id _ _ _ ?_ ?_ ?apply_id case apply_id => trans cfcHom hψa (.restrict (spectrum R (ψ a)) (.id R)) · simp [cfcHom_id] diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean index 03543434ff6ae..3b649bac9e2ed 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean @@ -23,7 +23,7 @@ functions on `spectrum R a`. More precisely, it is a continuous star algebra hom `C(spectrum R a, R) →⋆ₐ[R] A` that sends `(ContinuousMap.id R).restrict (spectrum R a)` to `a`. In all cases of interest (e.g., when `spectrum R a` is compact and `R` is `ℝ≥0`, `ℝ`, or `ℂ`), this is sufficient to uniquely determine the continuous functional calculus which is encoded in the -`UniqueContinuousFunctionalCalculus` class. +`ContinuousMap.UniqueHom` class. Although these properties suffice to uniquely determine the continuous functional calculus, we choose to bundle more information into the class itself. Namely, we include that the star algebra @@ -139,7 +139,7 @@ the predicate `p`, it should be noted that these will only ever be of the form ` goals, but it can be modified to become more sophisticated as the need arises. -/ -open Topology +open Topology ContinuousMap section Basic @@ -190,7 +190,7 @@ This class is separate from `ContinuousFunctionalCalculus` primarily because we from one on a larger ring (i.e., to go from a continuous functional calculus over `ℂ` for normal elements to one over `ℝ` for selfadjoint elements), and proving this additional property is preserved would be burdensome or impossible. -/ -class UniqueContinuousFunctionalCalculus (R A : Type*) [CommSemiring R] [StarRing R] +class ContinuousMap.UniqueHom (R A : Type*) [CommSemiring R] [StarRing R] [MetricSpace R] [TopologicalSemiring R] [ContinuousStar R] [Ring A] [StarRing A] [TopologicalSpace A] [Algebra R A] : Prop where eq_of_continuous_of_map_id (s : Set R) [CompactSpace s] @@ -198,6 +198,9 @@ class UniqueContinuousFunctionalCalculus (R A : Type*) [CommSemiring R] [StarRin (h : φ (.restrict s <| .id R) = ψ (.restrict s <| .id R)) : φ = ψ +@[deprecated (since := "2025-01-10")] alias UniqueContinuousFunctionalCalculus := + ContinuousMap.UniqueHom + variable {R A : Type*} {p : A → Prop} [CommSemiring R] [StarRing R] [MetricSpace R] variable [TopologicalSemiring R] [ContinuousStar R] [TopologicalSpace A] [Ring A] [StarRing A] variable [Algebra R A] [instCFC : ContinuousFunctionalCalculus R p] @@ -207,12 +210,12 @@ lemma ContinuousFunctionalCalculus.isCompact_spectrum (a : A) : IsCompact (spectrum R a) := isCompact_iff_compactSpace.mpr inferInstance -lemma StarAlgHom.ext_continuousMap [UniqueContinuousFunctionalCalculus R A] +lemma StarAlgHom.ext_continuousMap [UniqueHom R A] (a : A) [CompactSpace (spectrum R a)] (φ ψ : C(spectrum R a, R) →⋆ₐ[R] A) (hφ : Continuous φ) (hψ : Continuous ψ) (h : φ (.restrict (spectrum R a) <| .id R) = ψ (.restrict (spectrum R a) <| .id R)) : φ = ψ := - UniqueContinuousFunctionalCalculus.eq_of_continuous_of_map_id (spectrum R a) φ ψ hφ hψ h + UniqueHom.eq_of_continuous_of_map_id (spectrum R a) φ ψ hφ hψ h section cfcHom @@ -260,13 +263,13 @@ lemma cfcHom_predicate (f : C(spectrum R a, R)) : (ContinuousFunctionalCalculus.exists_cfc_of_predicate a ha).choose_spec.2.2.2 f open scoped ContinuousFunctionalCalculus in -lemma cfcHom_eq_of_continuous_of_map_id [UniqueContinuousFunctionalCalculus R A] +lemma cfcHom_eq_of_continuous_of_map_id [UniqueHom R A] (φ : C(spectrum R a, R) →⋆ₐ[R] A) (hφ₁ : Continuous φ) (hφ₂ : φ (.restrict (spectrum R a) <| .id R) = a) : cfcHom ha = φ := (cfcHom ha).ext_continuousMap a φ (cfcHom_isClosedEmbedding ha).continuous hφ₁ <| by rw [cfcHom_id ha, hφ₂] -theorem cfcHom_comp [UniqueContinuousFunctionalCalculus R A] (f : C(spectrum R a, R)) +theorem cfcHom_comp [UniqueHom R A] (f : C(spectrum R a, R)) (f' : C(spectrum R a, spectrum R (cfcHom ha f))) (hff' : ∀ x, f x = f' x) (g : C(spectrum R (cfcHom ha f), R)) : cfcHom ha (g.comp f') = cfcHom (cfcHom_predicate ha f) g := by @@ -571,7 +574,7 @@ end Polynomial section Comp -variable [UniqueContinuousFunctionalCalculus R A] +variable [UniqueHom R A] lemma cfc_comp (g f : R → R) (a : A) (ha : p a := by cfc_tac) (hg : ContinuousOn g (f '' spectrum R a) := by cfc_cont_tac) @@ -812,7 +815,7 @@ lemma cfc_zpow (a : Aˣ) (n : ℤ) (ha : p a := by cfc_tac) : have := cfc_pow (fun x ↦ x⁻¹ : R → R) (n + 1) (a : A) exact this.trans <| congr($(cfc_inv_id a) ^ (n + 1)) -variable [UniqueContinuousFunctionalCalculus R A] +variable [UniqueHom R A] lemma cfc_comp_inv (f : R → R) (a : Aˣ) (hf : ContinuousOn f ((· ⁻¹) '' (spectrum R (a : A))) := by cfc_cont_tac) @@ -856,7 +859,7 @@ lemma cfc_neg : cfc (fun x ↦ - (f x)) a = - (cfc f a) := by lemma cfc_neg_id (ha : p a := by cfc_tac) : cfc (- · : R → R) a = -a := by rw [cfc_neg _ a, cfc_id' R a] -variable [UniqueContinuousFunctionalCalculus R A] +variable [UniqueHom R A] lemma cfc_comp_neg (hf : ContinuousOn f ((- ·) '' (spectrum R (a : A))) := by cfc_cont_tac) (ha : p a := by cfc_tac) : cfc (f <| - ·) a = cfc f (-a) := by diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean index abb22aaf6854f..cbd93166b4404 100644 --- a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/PosPart.lean @@ -264,8 +264,8 @@ lemma posPart_negPart_unique {a b c : A} (habc : a = b - c) (hbc : b * c = 0) zero_add] map_star' := fun f ↦ by simp [← map_star] } have key : (cfcₙHomSuperset ha has) = ψ := - have : UniqueNonUnitalContinuousFunctionalCalculus ℝ A := inferInstance - UniqueNonUnitalContinuousFunctionalCalculus.eq_of_continuous_of_map_id s rfl + have : ContinuousMapZero.UniqueHom ℝ A := inferInstance + ContinuousMapZero.UniqueHom.eq_of_continuous_of_map_id s rfl (cfcₙHomSuperset ha has) ψ (cfcₙHomSuperset_continuous ha has) ((cfcₙHomSuperset_continuous hb' hbs).add (cfcₙHomSuperset_continuous hc' hcs)) (by simpa [zero, ψ, -cfcₙHomSuperset_apply, cfcₙHomSuperset_id, sub_eq_add_neg] using habc) From 7f65e5d66204f990728f0f888f5fb3ad104a8768 Mon Sep 17 00:00:00 2001 From: Matthew Robert Ballard Date: Fri, 17 Jan 2025 05:44:52 +0000 Subject: [PATCH 275/681] chore: restore `def` to `adicCompletion` (#20796) #13020 turned this into an `abbrev`. The definition is kinda scary so I would argue we try to keep it behind the veil and only expose it when necessary. As a bonus, this fixes a crashing instance synthesis [Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/adic.20completion.20is.20commutative). --- .../NumberField/FinitePlaces.lean | 10 +++-- .../DedekindDomain/AdicValuation.lean | 44 +++++++++---------- .../DedekindDomain/FiniteAdeleRing.lean | 2 +- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/Mathlib/NumberTheory/NumberField/FinitePlaces.lean b/Mathlib/NumberTheory/NumberField/FinitePlaces.lean index 4f5c13216f2e0..d030b4900a54c 100644 --- a/Mathlib/NumberTheory/NumberField/FinitePlaces.lean +++ b/Mathlib/NumberTheory/NumberField/FinitePlaces.lean @@ -84,6 +84,7 @@ noncomputable instance instRankOneValuedAdicCompletion : nontrivial' := by rcases Submodule.exists_mem_ne_zero_of_ne_bot v.ne_bot with ⟨x, hx1, hx2⟩ use (x : K) + dsimp [adicCompletion] rw [valuedAdicCompletion_eq_valuation' v (x : K)] constructor · simpa only [ne_eq, map_eq_zero, NoZeroSMulDivisors.algebraMap_eq_zero_iff] @@ -110,10 +111,11 @@ lemma toNNReal_Valued_eq_vadicAbv (x : K) : /-- The norm of the image after the embedding associated to `v` is equal to the `v`-adic absolute value. -/ theorem FinitePlace.norm_def (x : K) : ‖embedding v x‖ = vadicAbv v x := by - simp only [NormedField.toNorm, instNormedFieldValuedAdicCompletion, Valued.toNormedField, - instFieldAdicCompletion, Valued.norm, Valuation.RankOne.hom, MonoidWithZeroHom.coe_mk, - ZeroHom.coe_mk, embedding, UniformSpace.Completion.coeRingHom, RingHom.coe_mk, MonoidHom.coe_mk, - OneHom.coe_mk, Valued.valuedCompletion_apply, toNNReal_Valued_eq_vadicAbv] + simp only [adicCompletion, NormedField.toNorm, instNormedFieldValuedAdicCompletion, + Valued.toNormedField, instFieldAdicCompletion, Valued.norm, Valuation.RankOne.hom, + MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk, embedding, UniformSpace.Completion.coeRingHom, + RingHom.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk, Valued.valuedCompletion_apply, + toNNReal_Valued_eq_vadicAbv] /-- The norm of the image after the embedding associated to `v` is equal to the norm of `v` raised to the power of the `v`-adic valuation. -/ diff --git a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean index 82020896c6613..110ec9cd323fb 100644 --- a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean +++ b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean @@ -397,32 +397,31 @@ theorem adicValued_apply {x : K} : v.adicValued.v x = v.valuation x := variable (K) /-- The completion of `K` with respect to its `v`-adic valuation. -/ -abbrev adicCompletion := +def adicCompletion := @UniformSpace.Completion K v.adicValued.toUniformSpace -instance : Field (v.adicCompletion K) := - @UniformSpace.Completion.instField K _ v.adicValued.toUniformSpace _ _ - v.adicValued.toUniformAddGroup +instance : Field (v.adicCompletion K) := inferInstanceAs <| + Field (@UniformSpace.Completion K v.adicValued.toUniformSpace) instance : Inhabited (v.adicCompletion K) := ⟨0⟩ -instance valuedAdicCompletion : Valued (v.adicCompletion K) ℤₘ₀ := - @Valued.valuedCompletion _ _ _ _ v.adicValued +instance valuedAdicCompletion : Valued (v.adicCompletion K) ℤₘ₀ := inferInstanceAs <| + Valued (@UniformSpace.Completion K v.adicValued.toUniformSpace) ℤₘ₀ theorem valuedAdicCompletion_def {x : v.adicCompletion K} : Valued.v x = @Valued.extension K _ _ _ (adicValued v) x := rfl -instance adicCompletion_completeSpace : CompleteSpace (v.adicCompletion K) := - @UniformSpace.Completion.completeSpace K v.adicValued.toUniformSpace +instance adicCompletion_completeSpace : CompleteSpace (v.adicCompletion K) := inferInstanceAs <| + CompleteSpace (@UniformSpace.Completion K v.adicValued.toUniformSpace) -- Porting note: replaced by `Coe` -- instance AdicCompletion.hasLiftT : HasLiftT K (v.adicCompletion K) := -- (inferInstance : HasLiftT K (@UniformSpace.Completion K v.adicValued.toUniformSpace)) instance adicCompletion.instCoe : Coe K (v.adicCompletion K) := - (inferInstance : Coe K (@UniformSpace.Completion K v.adicValued.toUniformSpace)) + inferInstanceAs <| Coe K (@UniformSpace.Completion K v.adicValued.toUniformSpace) /-- The ring of integers of `adicCompletion`. -/ def adicCompletionIntegers : ValuationSubring (v.adicCompletion K) := @@ -452,9 +451,8 @@ instance adicValued.uniformContinuousConstSMul : @UniformContinuousConstSMul K K v.adicValued.toUniformSpace _ := @Ring.uniformContinuousConstSMul K _ v.adicValued.toUniformSpace _ _ -instance adicCompletion.algebra' : Algebra R (v.adicCompletion K) := - @UniformSpace.Completion.algebra K _ v.adicValued.toUniformSpace _ _ R _ _ - (adicValued.has_uniform_continuous_const_smul' R K v) +instance adicCompletion.algebra' : Algebra R (v.adicCompletion K) := inferInstanceAs <| + Algebra R (@UniformSpace.Completion K v.adicValued.toUniformSpace) theorem coe_smul_adicCompletion (r : R) (x : K) : (↑(r • x) : v.adicCompletion K) = r • (↑x : v.adicCompletion K) := @@ -471,9 +469,15 @@ theorem algebraMap_adicCompletion : ⇑(algebraMap K <| v.adicCompletion K) = ((↑) : K → adicCompletion K v) := rfl -instance : IsScalarTower R K (v.adicCompletion K) := - @UniformSpace.Completion.instIsScalarTower R K K v.adicValued.toUniformSpace _ _ _ - (adicValued.has_uniform_continuous_const_smul' R K v) _ _ +instance : IsScalarTower R K (v.adicCompletion K) := inferInstanceAs <| + IsScalarTower R K (@UniformSpace.Completion K v.adicValued.toUniformSpace) + +theorem coe_algebraMap_mem (r : R) : ↑((algebraMap R K) r) ∈ adicCompletionIntegers K v := by + rw [mem_adicCompletionIntegers] + letI : Valued K ℤₘ₀ := adicValued v + dsimp only [adicCompletion] + rw [Valued.valuedCompletion_apply] + exact v.valuation_le_one _ instance : Algebra R (v.adicCompletionIntegers K) where smul r x := @@ -482,15 +486,11 @@ instance : Algebra R (v.adicCompletionIntegers K) where (algebraMap R (adicCompletion K v)) r = (algebraMap R K r : adicCompletion K v) := rfl rw [Algebra.smul_def] refine ValuationSubring.mul_mem _ _ _ ?_ x.2 - --Porting note (https://github.com/leanprover-community/mathlib4/issues/10754): added instance - letI : Valued K ℤₘ₀ := adicValued v - rw [mem_adicCompletionIntegers, h, Valued.valuedCompletion_apply] - exact v.valuation_le_one _⟩ + rw [h] + exact coe_algebraMap_mem _ _ v r⟩ algebraMap := { toFun r := - ⟨(algebraMap R K r : adicCompletion K v), by - simpa only [mem_adicCompletionIntegers, Valued.valuedCompletion_apply] using - v.valuation_le_one _⟩ + ⟨(algebraMap R K r : adicCompletion K v), coe_algebraMap_mem _ _ v r⟩ map_one' := by simp only [map_one]; rfl map_mul' x y := by ext diff --git a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean index 430f40de7ae58..45e9ac50e0e50 100644 --- a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean +++ b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean @@ -270,7 +270,7 @@ open scoped Multiplicative theorem algebraMap' (k : K) : (_root_.algebraMap K (K_hat R K) k).IsFiniteAdele := by rw [IsFiniteAdele, Filter.eventually_cofinite] simp_rw [mem_adicCompletionIntegers, ProdAdicCompletions.algebraMap_apply', - Valued.valuedCompletion_apply, not_le] + adicCompletion, Valued.valuedCompletion_apply, not_le] change {v : HeightOneSpectrum R | 1 < v.valuation k}.Finite -- The goal currently: if k ∈ K = field of fractions of a Dedekind domain R, -- then v(k)>1 for only finitely many v. From a1e497dbd8ab6aee101358fb175857be69067e96 Mon Sep 17 00:00:00 2001 From: Yudai Yamazaki Date: Fri, 17 Jan 2025 06:22:20 +0000 Subject: [PATCH 276/681] chore(GroupExtension/Defs): define `Section` and redefine `Splitting` (#20802) This PR: - defines `structure (Add)?GroupExtension.Section` as a right inverse to `rightHom` - redefines `structure (Add)?GroupExtension.Splitting` using `Section` - rewrites the definition of `structure (Add)?GroupExtension.Equiv` with `extends` As the first part of #19582, this PR contains only the changes to the `Defs` file. Moves: - GroupExtension.Splitting.sectionHom -> GroupExtension.Splitting.toMonoidHom - GroupExtension.Splitting.rightHom_comp_sectionHom -> GroupExtension.Splitting.rightInverse_rightHom --- Mathlib/GroupTheory/GroupExtension/Defs.lean | 108 ++++++++++++++----- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/Mathlib/GroupTheory/GroupExtension/Defs.lean b/Mathlib/GroupTheory/GroupExtension/Defs.lean index 68610f45d8160..0eb1a9aba61c8 100644 --- a/Mathlib/GroupTheory/GroupExtension/Defs.lean +++ b/Mathlib/GroupTheory/GroupExtension/Defs.lean @@ -32,8 +32,10 @@ For additive groups: ↘︎ E' ↗︎️ ``` -- `(Add?)GroupExtension.Splitting S`: structure for splittings of a group extension `S` of `G` by - `N` as section homomorphisms `G → E` +- `(Add?)GroupExtension.Section S`: structure for right inverses to `rightHom` of a group extension + `S` of `G` by `N` +- `(Add?)GroupExtension.Splitting S`: structure for section homomorphisms of a group extension `S` + of `G` by `N` - `SemidirectProduct.toGroupExtension φ`: the multiplicative group extension associated to the semidirect product coming from `φ : G →* MulAut N`, `1 → N → N ⋊[φ] G → G → 1` @@ -84,20 +86,24 @@ namespace AddGroupExtension variable [AddGroup N] [AddGroup E] [AddGroup G] (S : AddGroupExtension N E G) /-- `AddGroupExtension`s are equivalent iff there is a homomorphism making a commuting diagram. -/ -structure Equiv {E' : Type*} [AddGroup E'] (S' : AddGroupExtension N E' G) where - /-- The homomorphism -/ - toAddMonoidHom : E →+ E' +structure Equiv {E' : Type*} [AddGroup E'] (S' : AddGroupExtension N E' G) extends E →+ E' where /-- The left-hand side of the diagram commutes. -/ inl_comm : toAddMonoidHom.comp S.inl = S'.inl /-- The right-hand side of the diagram commutes. -/ rightHom_comm : S'.rightHom.comp toAddMonoidHom = S.rightHom +/-- `Section` of an additive group extension is a right inverse to `S.rightHom`. -/ +structure Section where + /-- The underlying function -/ + toFun : G → E + /-- `Section` is a right inverse to `S.rightHom` -/ + rightInverse_rightHom : Function.RightInverse toFun S.rightHom + /-- `Splitting` of an additive group extension is a section homomorphism. -/ -structure Splitting where - /-- A section homomorphism -/ - sectionHom : G →+ E - /-- The section is a left inverse of the projection map. -/ - rightHom_comp_sectionHom : S.rightHom.comp sectionHom = AddMonoidHom.id G +structure Splitting extends G →+ E, S.Section + +/-- A splitting of an additive group extension as a (set-theoretic) section. -/ +add_decl_doc Splitting.toSection end AddGroupExtension @@ -135,30 +141,58 @@ noncomputable def conjAct : E →* MulAut N where /-- The inclusion and a conjugation commute. -/ theorem inl_conjAct_comm {e : E} {n : N} : S.inl (S.conjAct e n) = e * S.inl n * e⁻¹ := by simp only [conjAct, MonoidHom.coe_mk, OneHom.coe_mk, MulEquiv.trans_apply, - MonoidHom.apply_ofInjective_symm] - rfl + MonoidHom.apply_ofInjective_symm, MulAut.conjNormal_apply, MonoidHom.ofInjective_apply] /-- `GroupExtension`s are equivalent iff there is a homomorphism making a commuting diagram. -/ @[to_additive] -structure Equiv {E' : Type*} [Group E'] (S' : GroupExtension N E' G) where - /-- The homomorphism -/ - toMonoidHom : E →* E' +structure Equiv {E' : Type*} [Group E'] (S' : GroupExtension N E' G) extends E →* E' where /-- The left-hand side of the diagram commutes. -/ inl_comm : toMonoidHom.comp S.inl = S'.inl /-- The right-hand side of the diagram commutes. -/ rightHom_comm : S'.rightHom.comp toMonoidHom = S.rightHom +/-- `Section` of a group extension is a right inverse to `S.rightHom`. -/ +@[to_additive] +structure Section where + /-- The underlying function -/ + toFun : G → E + /-- `Section` is a right inverse to `S.rightHom` -/ + rightInverse_rightHom : Function.RightInverse toFun S.rightHom + +namespace Section + +@[to_additive] +instance : FunLike S.Section G E where + coe := toFun + coe_injective' := fun ⟨_, _⟩ ⟨_, _⟩ _ ↦ by congr + +variable {S} + +@[to_additive (attr := simp)] +theorem coe_mk (σ : G → E) (hσ : Function.RightInverse σ S.rightHom) : (mk σ hσ : G → E) = σ := rfl + +variable (σ : S.Section) + +@[to_additive (attr := simp)] +theorem rightHom_section (g : G) : S.rightHom (σ g) = g := σ.rightInverse_rightHom g + +@[to_additive (attr := simp)] +theorem rightHom_comp_section : S.rightHom ∘ σ = id := σ.rightInverse_rightHom.comp_eq_id + +end Section + /-- `Splitting` of a group extension is a section homomorphism. -/ @[to_additive] -structure Splitting where - /-- A section homomorphism -/ - sectionHom : G →* E - /-- The section is a left inverse of the projection map. -/ - rightHom_comp_sectionHom : S.rightHom.comp sectionHom = MonoidHom.id G +structure Splitting extends G →* E, S.Section + +/-- A splitting of a group extension as a (set-theoretic) section. -/ +add_decl_doc Splitting.toSection + +namespace Splitting @[to_additive] instance : FunLike S.Splitting G E where - coe s := s.sectionHom + coe s := s.toFun coe_injective' := by intro ⟨_, _⟩ ⟨_, _⟩ h congr @@ -166,16 +200,36 @@ instance : FunLike S.Splitting G E where @[to_additive] instance : MonoidHomClass S.Splitting G E where - map_mul s := s.sectionHom.map_mul' - map_one s := s.sectionHom.map_one' + map_mul s := s.map_mul' + map_one s := s.map_one' + +variable {S} + +@[to_additive (attr := simp)] +theorem coe_mk (s : G →* E) (hs : Function.RightInverse s S.rightHom) : (mk s hs : G → E) = s := rfl + +@[to_additive (attr := simp)] +theorem coe_monoidHom_mk (s : G →* E) (hs : Function.RightInverse s S.rightHom) : + (mk s hs : G →* E) = s := rfl + +variable (s : S.Splitting) + +@[to_additive (attr := simp)] +theorem rightHom_splitting (g : G) : S.rightHom (s g) = g := s.rightInverse_rightHom g + +@[to_additive (attr := simp)] +theorem rightHom_comp_splitting : S.rightHom.comp s = MonoidHom.id G := by + ext g + simp only [MonoidHom.comp_apply, MonoidHom.id_apply, MonoidHom.coe_coe, rightHom_splitting] + +end Splitting /-- A splitting of an extension `S` is `N`-conjugate to another iff there exists `n : N` such that the section homomorphism is a conjugate of the other section homomorphism by `S.inl n`. -/ @[to_additive "A splitting of an extension `S` is `N`-conjugate to another iff there exists `n : N` such that the section homomorphism is a conjugate of the other section homomorphism by `S.inl n`."] -def IsConj (S : GroupExtension N E G) (s s' : S.Splitting) : Prop := - ∃ n : N, s.sectionHom = fun g ↦ S.inl n * s'.sectionHom g * (S.inl n)⁻¹ +def IsConj (s s' : S.Splitting) : Prop := ∃ n : N, s = fun g ↦ S.inl n * s' g * (S.inl n)⁻¹ end GroupExtension @@ -196,7 +250,7 @@ theorem toGroupExtension_rightHom : (toGroupExtension φ).rightHom = SemidirectP /-- A canonical splitting of the group extension associated to the semidirect product -/ def inr_splitting : (toGroupExtension φ).Splitting where - sectionHom := inr - rightHom_comp_sectionHom := rightHom_comp_inr + __ := inr + rightInverse_rightHom := rightHom_inr end SemidirectProduct From 767b25086e1c7caba55c09b8ed5e73254a16fa33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Fri, 17 Jan 2025 06:30:55 +0000 Subject: [PATCH 277/681] feat(RingTheory/LocalRing): add instance `Unique (MaximalSpectrum R)` for a local ring `R` (#20801) Introduce the instance `Unique (MaximalSpectrum R)` for a local ring `R`. I need this for simpler proofs, for example that a local reduced artinian ring is a field (using `RingEquiv.piUnique` introduced in #20794). I think it's generally useful. --- Mathlib/RingTheory/LocalRing/MaximalIdeal/Basic.lean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mathlib/RingTheory/LocalRing/MaximalIdeal/Basic.lean b/Mathlib/RingTheory/LocalRing/MaximalIdeal/Basic.lean index 1919f202cbf8f..f53e47c95c46b 100644 --- a/Mathlib/RingTheory/LocalRing/MaximalIdeal/Basic.lean +++ b/Mathlib/RingTheory/LocalRing/MaximalIdeal/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.RingTheory.Jacobson.Ideal import Mathlib.RingTheory.LocalRing.MaximalIdeal.Defs import Mathlib.RingTheory.Localization.Basic import Mathlib.RingTheory.Nilpotent.Lemmas +import Mathlib.RingTheory.Spectrum.Maximal.Defs /-! @@ -47,6 +48,11 @@ variable {R} theorem eq_maximalIdeal {I : Ideal R} (hI : I.IsMaximal) : I = maximalIdeal R := ExistsUnique.unique (maximal_ideal_unique R) hI <| maximalIdeal.isMaximal R +/-- The maximal spectrum of a local ring is a singleton. -/ +instance : Unique (MaximalSpectrum R) where + default := ⟨maximalIdeal R, maximalIdeal.isMaximal R⟩ + uniq := fun I ↦ MaximalSpectrum.ext_iff.mpr <| eq_maximalIdeal I.isMaximal + theorem le_maximalIdeal {J : Ideal R} (hJ : J ≠ ⊤) : J ≤ maximalIdeal R := by rcases Ideal.exists_le_maximal J hJ with ⟨M, hM1, hM2⟩ rwa [← eq_maximalIdeal hM1] From e2d098c40cd157f3395d8a65a41ea80ebf5ce702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Fri, 17 Jan 2025 06:53:30 +0000 Subject: [PATCH 278/681] feat(Algebra/Ring): `RingEquiv.piUnique` (#20794) Implement the ring-theoretic counterpart of `LinearEquiv.piUnique` and `Equiv.piUnique`. --- Mathlib/Algebra/Ring/Equiv.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index c192e8ba6a766..474e811d144ba 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -441,6 +441,14 @@ theorem ofBijective_apply [NonUnitalRingHomClass F R S] (f : F) (hf : Function.B (x : R) : ofBijective f hf x = f x := rfl +/-- Product of a singleton family of (non-unital non-associative semi)rings is isomorphic +to the only member of this family. -/ +def piUnique {ι : Type*} (R : ι → Type*) [Unique ι] [∀ i, NonUnitalNonAssocSemiring (R i)] : + (∀ i, R i) ≃+* R default where + __ := Equiv.piUnique R + map_add' _ _ := rfl + map_mul' _ _ := rfl + /-- A family of ring isomorphisms `∀ j, (R j ≃+* S j)` generates a ring isomorphisms between `∀ j, R j` and `∀ j, S j`. From b07a551a1451cbf8615f4e2a6c47052affadbae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Fri, 17 Jan 2025 07:19:44 +0000 Subject: [PATCH 279/681] feat(Algebra/Homology/Embedding): API for the homology of an extension of homological complex (#19203) Given an embedding `e : c.Embedding c'` of complex shapes, we provide definitions and lemmas in order to study the homology of the extension by `e` of a homological complex. --- .../Homology/Embedding/ExtendHomology.lean | 149 +++++++++++++++++- 1 file changed, 145 insertions(+), 4 deletions(-) diff --git a/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean b/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean index 200b3f46bb39a..5962382e8c31d 100644 --- a/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean +++ b/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean @@ -4,15 +4,16 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.Algebra.Homology.Embedding.Extend -import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex +import Mathlib.Algebra.Homology.Embedding.IsSupported +import Mathlib.Algebra.Homology.QuasiIso /-! # Homology of the extension of an homological complex Given an embedding `e : c.Embedding c'` and `K : HomologicalComplex C c`, we shall compute the homology of `K.extend e`. In degrees that are not in the image of `e.f`, -the homology is obviously zero. When `e.f j = j`, we shall construct an isomorphism -`(K.extend e).homology j' ≅ K.homology j` (TODO). +the homology is obviously zero. When `e.f j = j`, we construct an isomorphism +`(K.extend e).homology j' ≅ K.homology j`. -/ @@ -21,7 +22,8 @@ open CategoryTheory Limits Category namespace HomologicalComplex variable {ι ι' : Type*} {c : ComplexShape ι} {c' : ComplexShape ι'} - {C : Type*} [Category C] [HasZeroMorphisms C] [HasZeroObject C] + {C : Type*} [Category C] [HasZeroMorphisms C] + [HasZeroObject C] variable (K L M : HomologicalComplex C c) (φ : K ⟶ L) (φ' : L ⟶ M) (e : c.Embedding c') @@ -275,4 +277,143 @@ instance [∀ j, K.HasHomology j] (j' : ι') : (K.extend e).HasHomology j' := by end extend +lemma extend_exactAt (j' : ι') (hj' : ∀ j, e.f j ≠ j') : + (K.extend e).ExactAt j' := + exactAt_of_isSupported _ e j' hj' + +section + +variable {j : ι} {j' : ι'} (hj' : e.f j = j') [K.HasHomology j] [L.HasHomology j] + [(K.extend e).HasHomology j'] [(L.extend e).HasHomology j'] + +/-- The isomorphism `(K.extend e).cycles j' ≅ K.cycles j` when `e.f j = j'`. -/ +noncomputable def extendCyclesIso : + (K.extend e).cycles j' ≅ K.cycles j := + (extend.homologyData' K e hj' rfl rfl (K.sc j).homologyData).left.cyclesIso ≪≫ + (K.sc j).homologyData.left.cyclesIso.symm + +/-- The isomorphism `(K.extend e).opcycles j' ≅ K.opcycles j` when `e.f j = j'`. -/ +noncomputable def extendOpcyclesIso : + (K.extend e).opcycles j' ≅ K.opcycles j := + (extend.homologyData' K e hj' rfl rfl (K.sc j).homologyData).right.opcyclesIso ≪≫ + (K.sc j).homologyData.right.opcyclesIso.symm + +/-- The isomorphism `(K.extend e).homology j' ≅ K.homology j` when `e.f j = j'`. -/ +noncomputable def extendHomologyIso : + (K.extend e).homology j' ≅ K.homology j := + (extend.homologyData' K e hj' rfl rfl (K.sc j).homologyData).left.homologyIso ≪≫ + (K.sc j).homologyData.left.homologyIso.symm + +include hj' in +lemma extend_exactAt_iff : + (K.extend e).ExactAt j' ↔ K.ExactAt j := by + simp only [HomologicalComplex.exactAt_iff_isZero_homology] + exact (K.extendHomologyIso e hj').isZero_iff + +@[reassoc (attr := simp)] +lemma extendCyclesIso_hom_iCycles : + (K.extendCyclesIso e hj').hom ≫ K.iCycles j = + (K.extend e).iCycles j' ≫ (K.extendXIso e hj').hom := by + rw [← cancel_epi (K.extendCyclesIso e hj').inv, Iso.inv_hom_id_assoc] + dsimp [extendCyclesIso, iCycles] + rw [assoc, ShortComplex.LeftHomologyData.cyclesIso_inv_comp_iCycles_assoc] + dsimp + rw [assoc, Iso.inv_hom_id, comp_id, + ShortComplex.LeftHomologyData.cyclesIso_hom_comp_i] + +@[reassoc (attr := simp)] +lemma extendCyclesIso_inv_iCycles : + (K.extendCyclesIso e hj').inv ≫ (K.extend e).iCycles j' = + K.iCycles j ≫ (K.extendXIso e hj').inv := by + simp only [← cancel_epi (K.extendCyclesIso e hj').hom, Iso.hom_inv_id_assoc, + extendCyclesIso_hom_iCycles_assoc, Iso.hom_inv_id, comp_id] + +@[reassoc (attr := simp)] +lemma homologyπ_extendHomologyIso_hom : + (K.extend e).homologyπ j' ≫ (K.extendHomologyIso e hj').hom = + (K.extendCyclesIso e hj').hom ≫ K.homologyπ j := by + dsimp [extendHomologyIso, homologyπ] + rw [ShortComplex.LeftHomologyData.homologyπ_comp_homologyIso_hom_assoc, + ← cancel_mono (K.sc j).homologyData.left.homologyIso.hom, + assoc, assoc, assoc, Iso.inv_hom_id, comp_id, + ShortComplex.LeftHomologyData.homologyπ_comp_homologyIso_hom] + dsimp [extendCyclesIso] + simp only [assoc, Iso.inv_hom_id_assoc] + +@[reassoc (attr := simp)] +lemma homologyπ_extendHomologyIso_inv : + K.homologyπ j ≫ (K.extendHomologyIso e hj').inv = + (K.extendCyclesIso e hj').inv ≫ (K.extend e).homologyπ j' := by + simp only [← cancel_mono (K.extendHomologyIso e hj').hom, + assoc, Iso.inv_hom_id, comp_id, homologyπ_extendHomologyIso_hom, Iso.inv_hom_id_assoc] + +@[reassoc (attr := simp)] +lemma pOpcycles_extendOpcyclesIso_inv : + K.pOpcycles j ≫ (K.extendOpcyclesIso e hj').inv = + (K.extendXIso e hj').inv ≫ (K.extend e).pOpcycles j' := by + rw [← cancel_mono (K.extendOpcyclesIso e hj').hom, assoc, assoc, Iso.inv_hom_id, comp_id] + dsimp [extendOpcyclesIso, pOpcycles] + rw [ShortComplex.RightHomologyData.pOpcycles_comp_opcyclesIso_hom_assoc] + dsimp + rw [assoc, Iso.inv_hom_id_assoc, ShortComplex.RightHomologyData.p_comp_opcyclesIso_inv] + rfl + +@[reassoc (attr := simp)] +lemma pOpcycles_extendOpcyclesIso_hom : + (K.extend e).pOpcycles j' ≫ (K.extendOpcyclesIso e hj').hom = + (K.extendXIso e hj').hom ≫ K.pOpcycles j := by + simp only [← cancel_mono (K.extendOpcyclesIso e hj').inv, + assoc, Iso.hom_inv_id, comp_id, pOpcycles_extendOpcyclesIso_inv, Iso.hom_inv_id_assoc] + +@[reassoc (attr := simp)] +lemma extendHomologyIso_hom_homologyι : + (K.extendHomologyIso e hj').hom ≫ K.homologyι j = + (K.extend e).homologyι j' ≫ (K.extendOpcyclesIso e hj').hom := by + simp only [← cancel_epi ((K.extend e).homologyπ j'), + homologyπ_extendHomologyIso_hom_assoc, homology_π_ι, extendCyclesIso_hom_iCycles_assoc, + homology_π_ι_assoc, pOpcycles_extendOpcyclesIso_hom] + +@[reassoc (attr := simp)] +lemma extendHomologyIso_inv_homologyι : + (K.extendHomologyIso e hj').inv ≫ (K.extend e).homologyι j' = + K.homologyι j ≫ (K.extendOpcyclesIso e hj').inv := by + simp only [← cancel_epi (K.extendHomologyIso e hj').hom, + Iso.hom_inv_id_assoc, extendHomologyIso_hom_homologyι_assoc, Iso.hom_inv_id, comp_id] + +variable {K L} + +@[reassoc (attr := simp)] +lemma extendCyclesIso_hom_naturality : + cyclesMap (extendMap φ e) j' ≫ (L.extendCyclesIso e hj').hom = + (K.extendCyclesIso e hj').hom ≫ cyclesMap φ j := by + simp [← cancel_mono (L.iCycles j), extendMap_f φ e hj'] + +@[reassoc (attr := simp)] +lemma extendHomologyIso_hom_naturality : + homologyMap (extendMap φ e) j' ≫ (L.extendHomologyIso e hj').hom = + (K.extendHomologyIso e hj').hom ≫ homologyMap φ j := by + simp [← cancel_epi ((K.extend e).homologyπ _)] + +include hj' in +lemma quasiIsoAt_extendMap_iff : + QuasiIsoAt (extendMap φ e) j' ↔ QuasiIsoAt φ j := by + simp only [quasiIsoAt_iff_isIso_homologyMap] + exact (MorphismProperty.isomorphisms C).arrow_mk_iso_iff + (Arrow.isoMk (K.extendHomologyIso e hj') (L.extendHomologyIso e hj')) + +end + +lemma quasiIso_extendMap_iff [∀ j, K.HasHomology j] [∀ j, L.HasHomology j] : + QuasiIso (extendMap φ e) ↔ QuasiIso φ := by + simp only [quasiIso_iff, ← fun j ↦ quasiIsoAt_extendMap_iff φ e (j := j) (hj' := rfl)] + constructor + · tauto + · intro h j' + by_cases hj' : ∃ j, e.f j = j' + · obtain ⟨j, rfl⟩ := hj' + exact h j + · rw [quasiIsoAt_iff_exactAt] + all_goals + exact extend_exactAt _ _ _ (by simpa using hj') + end HomologicalComplex From 1af25077805df4670d88f3e48778af0c90c7aa98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Fri, 17 Jan 2025 07:28:07 +0000 Subject: [PATCH 280/681] feat(Algebra/Homology/Embedding): the canonical truncation truncLE (#19550) We dualize for `truncLE` the definitions and lemmas obtained for `truncGE` in PR #14734, #19543 and #19544. --- Mathlib.lean | 1 + Mathlib/Algebra/Homology/Embedding/Basic.lean | 9 + .../Algebra/Homology/Embedding/Boundary.lean | 3 + .../Homology/Embedding/IsSupported.lean | 27 ++ .../Algebra/Homology/Embedding/TruncLE.lean | 239 ++++++++++++++++++ 5 files changed, 279 insertions(+) create mode 100644 Mathlib/Algebra/Homology/Embedding/TruncLE.lean diff --git a/Mathlib.lean b/Mathlib.lean index ea033a276b7cd..eaf583adca718 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -438,6 +438,7 @@ import Mathlib.Algebra.Homology.Embedding.IsSupported import Mathlib.Algebra.Homology.Embedding.Restriction import Mathlib.Algebra.Homology.Embedding.StupidTrunc import Mathlib.Algebra.Homology.Embedding.TruncGE +import Mathlib.Algebra.Homology.Embedding.TruncLE import Mathlib.Algebra.Homology.ExactSequence import Mathlib.Algebra.Homology.Factorizations.Basic import Mathlib.Algebra.Homology.Functor diff --git a/Mathlib/Algebra/Homology/Embedding/Basic.lean b/Mathlib/Algebra/Homology/Embedding/Basic.lean index 0838372d944b7..00176a4d60d8d 100644 --- a/Mathlib/Algebra/Homology/Embedding/Basic.lean +++ b/Mathlib/Algebra/Homology/Embedding/Basic.lean @@ -84,6 +84,9 @@ lemma rel_iff [e.IsRelIff] (i₁ i₂ : ι) : c'.Rel (e.f i₁) (e.f i₂) ↔ c · apply IsRelIff.rel' · exact e.rel +instance [e.IsRelIff] : e.op.IsRelIff where + rel' i₁ i₂ h := (e.rel_iff i₂ i₁).1 h + section variable (c c') @@ -121,6 +124,12 @@ class IsTruncLE extends e.IsRelIff : Prop where lemma mem_prev [e.IsTruncLE] {i' : ι'} {j : ι} (h : c'.Rel i' (e.f j)) : ∃ i, e.f i = i' := IsTruncLE.mem_prev h +instance [e.IsTruncGE] : e.op.IsTruncLE where + mem_prev h := e.mem_next h + +instance [e.IsTruncLE] : e.op.IsTruncGE where + mem_next h := e.mem_prev h + open Classical in /-- The map `ι' → Option ι` which sends `e.f i` to `some i` and the other elements to `none`. -/ noncomputable def r (i' : ι') : Option ι := diff --git a/Mathlib/Algebra/Homology/Embedding/Boundary.lean b/Mathlib/Algebra/Homology/Embedding/Boundary.lean index 046809631f6a2..22deea7a94982 100644 --- a/Mathlib/Algebra/Homology/Embedding/Boundary.lean +++ b/Mathlib/Algebra/Homology/Embedding/Boundary.lean @@ -144,6 +144,9 @@ lemma BoundaryLE.false_of_isTruncGE {j : ι} (hj : e.BoundaryLE j) [e.IsTruncGE] obtain ⟨k, hk⟩ := e.mem_next hj.1 exact hj.2 k (by simpa only [hk] using hj.1) +@[simp] lemma op_boundaryLE_iff {j : ι} : e.op.BoundaryLE j ↔ e.BoundaryGE j := by rfl +@[simp] lemma op_boundaryGE_iff {j : ι} : e.op.BoundaryGE j ↔ e.BoundaryLE j := by rfl + end Embedding lemma boundaryGE_embeddingUpIntGE_iff (p : ℤ) (n : ℕ) : diff --git a/Mathlib/Algebra/Homology/Embedding/IsSupported.lean b/Mathlib/Algebra/Homology/Embedding/IsSupported.lean index 1504e486bb998..b049f1900fc3f 100644 --- a/Mathlib/Algebra/Homology/Embedding/IsSupported.lean +++ b/Mathlib/Algebra/Homology/Embedding/IsSupported.lean @@ -51,6 +51,17 @@ lemma isStrictlySupported_of_iso [K.IsStrictlySupported e] : L.IsStrictlySupport isZero i' hi' := (K.isZero_X_of_isStrictlySupported e i' hi').of_iso ((eval _ _ i').mapIso e'.symm) +@[simp] +lemma isStrictlySupported_op_iff : + K.op.IsStrictlySupported e.op ↔ K.IsStrictlySupported e := + ⟨(fun _ ↦ ⟨fun i' hi' ↦ (K.op.isZero_X_of_isStrictlySupported e.op i' hi').unop⟩), + (fun _ ↦ ⟨fun i' hi' ↦ (K.isZero_X_of_isStrictlySupported e i' hi').op⟩)⟩ + +instance [K.IsStrictlySupported e] : + K.op.IsStrictlySupported e.op := by + rw [isStrictlySupported_op_iff] + infer_instance + /-- If `K : HomologicalComplex C c'`, then `K.IsStrictlySupported e` holds for an embedding `e : c.Embedding c'` of complex shapes if `K` is exact at `i'` whenever `i'` is not of the form `e.f i` for some `i`.-/ @@ -72,16 +83,32 @@ instance [K.IsStrictlySupported e] : K.IsSupported e where rw [exactAt_iff] exact ShortComplex.exact_of_isZero_X₂ _ (K.isZero_X_of_isStrictlySupported e i' hi') +@[simp] +lemma isSupported_op_iff : + K.op.IsSupported e.op ↔ K.IsSupported e := + ⟨fun _ ↦ ⟨fun i' hi' ↦ (K.op.exactAt_of_isSupported e.op i' hi').unop⟩, + fun _ ↦ ⟨fun i' hi' ↦ (K.exactAt_of_isSupported e i' hi').op⟩⟩ + /-- If `K : HomologicalComplex C c'`, then `K.IsStrictlySupportedOutside e` holds for an embedding `e : c.Embedding c'` of complex shapes if `K.X (e.f i)` is zero for all `i`. -/ structure IsStrictlySupportedOutside : Prop where isZero (i : ι) : IsZero (K.X (e.f i)) +@[simp] +lemma isStrictlySupportedOutside_op_iff : + K.op.IsStrictlySupportedOutside e.op ↔ K.IsStrictlySupportedOutside e := + ⟨fun h ↦ ⟨fun i ↦ (h.isZero i).unop⟩, fun h ↦ ⟨fun i ↦ (h.isZero i).op⟩⟩ + /-- If `K : HomologicalComplex C c'`, then `K.IsSupportedOutside e` holds for an embedding `e : c.Embedding c'` of complex shapes if `K` is exact at `e.f i` for all `i`. -/ structure IsSupportedOutside : Prop where exactAt (i : ι) : K.ExactAt (e.f i) +@[simp] +lemma isSupportedOutside_op_iff : + K.op.IsSupportedOutside e.op ↔ K.IsSupportedOutside e := + ⟨fun h ↦ ⟨fun i ↦ (h.exactAt i).unop⟩, fun h ↦ ⟨fun i ↦ (h.exactAt i).op⟩⟩ + variable {K e} in lemma IsStrictlySupportedOutside.isSupportedOutside (h : K.IsStrictlySupportedOutside e) : K.IsSupportedOutside e where diff --git a/Mathlib/Algebra/Homology/Embedding/TruncLE.lean b/Mathlib/Algebra/Homology/Embedding/TruncLE.lean new file mode 100644 index 0000000000000..332d9cab3b796 --- /dev/null +++ b/Mathlib/Algebra/Homology/Embedding/TruncLE.lean @@ -0,0 +1,239 @@ +/- +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.Homology.Embedding.TruncGE + +/-! +# The canonical truncation + +Given an embedding `e : Embedding c c'` of complex shapes which +satisfies `e.IsTruncLE` and `K : HomologicalComplex C c'`, +we define `K.truncGE' e : HomologicalComplex C c` +and `K.truncLE e : HomologicalComplex C c'` which are the canonical +truncations of `K` relative to `e`. + +In order to achieve this, we dualize the constructions from the file +`Embedding.TruncGE`. + +-/ + +open CategoryTheory Limits ZeroObject Category + +variable {ι ι' : Type*} {c : ComplexShape ι} {c' : ComplexShape ι'} + {C : Type*} [Category C] [HasZeroMorphisms C] + +namespace HomologicalComplex + +variable (K L M : HomologicalComplex C c') (φ : K ⟶ L) (φ' : L ⟶ M) + (e : c.Embedding c') [e.IsTruncLE] + [∀ i', K.HasHomology i'] [∀ i', L.HasHomology i'] [∀ i', M.HasHomology i'] + +/-- The canonical truncation of a homological complex relative to an embedding +of complex shapes `e` which satisfies `e.IsTruncLE`. -/ +noncomputable def truncLE' : HomologicalComplex C c := (K.op.truncGE' e.op).unop + +/-- The isomorphism `(K.truncLE' e).X i ≅ K.X i'` when `e.f i = i'` +and `e.BoundaryLE i` does not hold. -/ +noncomputable def truncLE'XIso {i : ι} {i' : ι'} (hi' : e.f i = i') (hi : ¬ e.BoundaryLE i) : + (K.truncLE' e).X i ≅ K.X i' := + (K.op.truncGE'XIso e.op hi' (by simpa)).symm.unop + +/-- The isomorphism `(K.truncLE' e).X i ≅ K.cycles i'` when `e.f i = i'` +and `e.BoundaryLE i` holds. -/ +noncomputable def truncLE'XIsoCycles {i : ι} {i' : ι'} (hi' : e.f i = i') (hi : e.BoundaryLE i) : + (K.truncLE' e).X i ≅ K.cycles i' := + (K.op.truncGE'XIsoOpcycles e.op hi' (by simpa)).unop.symm ≪≫ + (K.opcyclesOpIso i').unop.symm + +lemma truncLE'_d_eq {i j : ι} (hij : c.Rel i j) {i' j' : ι'} + (hi' : e.f i = i') (hj' : e.f j = j') (hj : ¬ e.BoundaryLE j) : + (K.truncLE' e).d i j = (K.truncLE'XIso e hi' (e.not_boundaryLE_prev hij)).hom ≫ K.d i' j' ≫ + (K.truncLE'XIso e hj' hj).inv := + Quiver.Hom.op_inj (by simpa using K.op.truncGE'_d_eq e.op hij hj' hi' (by simpa)) + +lemma truncLE'_d_eq_toCycles {i j : ι} (hij : c.Rel i j) {i' j' : ι'} + (hi' : e.f i = i') (hj' : e.f j = j') (hj : e.BoundaryLE j) : + (K.truncLE' e).d i j = (K.truncLE'XIso e hi' (e.not_boundaryLE_prev hij)).hom ≫ + K.toCycles i' j' ≫ (K.truncLE'XIsoCycles e hj' hj).inv := + Quiver.Hom.op_inj (by + simpa [truncLE', truncLE'XIso, truncLE'XIsoCycles] + using K.op.truncGE'_d_eq_fromOpcycles e.op hij hj' hi' (by simpa)) + +section + +variable [HasZeroObject C] + +/-- The canonical truncation of a homological complex relative to an embedding +of complex shapes `e` which satisfies `e.IsTruncLE`. -/ +noncomputable def truncLE : HomologicalComplex C c' := (K.op.truncGE e.op).unop + +/-- The canonical isomorphism `K.truncLE e ≅ (K.truncLE' e).extend e`. -/ +noncomputable def truncLEIso : K.truncLE e ≅ (K.truncLE' e).extend e := + (unopFunctor C c'.symm).mapIso ((K.truncLE' e).extendOpIso e).symm.op + +/-- The isomorphism `(K.truncLE e).X i' ≅ K.X i'` when `e.f i = i'` +and `e.BoundaryLE i` does not hold. -/ +noncomputable def truncLEXIso {i : ι} {i' : ι'} (hi' : e.f i = i') (hi : ¬ e.BoundaryLE i) : + (K.truncLE e).X i' ≅ K.X i' := + (K.op.truncGEXIso e.op hi' (by simpa)).unop.symm + +/-- The isomorphism `(K.truncLE e).X i' ≅ K.cycles i'` when `e.f i = i'` +and `e.BoundaryLE i` holds. -/ +noncomputable def truncLEXIsoCycles {i : ι} {i' : ι'} (hi' : e.f i = i') (hi : e.BoundaryLE i) : + (K.truncLE e).X i' ≅ K.cycles i' := + (K.op.truncGEXIsoOpcycles e.op hi' (by simpa)).unop.symm ≪≫ + (K.opcyclesOpIso i').unop.symm + +end + +section + +variable {K L M} + +/-- The morphism `K.truncLE' e ⟶ L.truncLE' e` induced by a morphism `K ⟶ L`. -/ +noncomputable def truncLE'Map : K.truncLE' e ⟶ L.truncLE' e := + (unopFunctor C c.symm).map (truncGE'Map ((opFunctor C c').map φ.op) e.op).op + +lemma truncLE'Map_f_eq_cyclesMap {i : ι} (hi : e.BoundaryLE i) {i' : ι'} (h : e.f i = i') : + (truncLE'Map φ e).f i = + (K.truncLE'XIsoCycles e h hi).hom ≫ cyclesMap φ i' ≫ + (L.truncLE'XIsoCycles e h hi).inv := by + apply Quiver.Hom.op_inj + dsimp [truncLE'Map, truncLE'XIsoCycles] + rw [assoc, assoc, truncGE'Map_f_eq_opcyclesMap _ e.op (by simpa) h, + opcyclesOpIso_inv_naturality_assoc, Iso.hom_inv_id_assoc] + +lemma truncLE'Map_f_eq {i : ι} (hi : ¬ e.BoundaryLE i) {i' : ι'} (h : e.f i = i') : + (truncLE'Map φ e).f i = + (K.truncLE'XIso e h hi).hom ≫ φ.f i' ≫ (L.truncLE'XIso e h hi).inv := + Quiver.Hom.op_inj + (by simpa using truncGE'Map_f_eq ((opFunctor C c').map φ.op) e.op (by simpa) h) + +variable (K) in +@[simp] +lemma truncLE'Map_id : truncLE'Map (𝟙 K) e = 𝟙 _ := + (unopFunctor C c.symm).congr_map (congr_arg Quiver.Hom.op (K.op.truncGE'Map_id e.op)) + +@[reassoc, simp] +lemma truncLE'Map_comp : truncLE'Map (φ ≫ φ') e = truncLE'Map φ e ≫ truncLE'Map φ' e := + (unopFunctor C c.symm).congr_map (congr_arg Quiver.Hom.op + (truncGE'Map_comp ((opFunctor C c').map φ'.op) ((opFunctor C c').map φ.op) e.op)) + +variable [HasZeroObject C] + +/-- The morphism `K.truncLE e ⟶ L.truncLE e` induced by a morphism `K ⟶ L`. -/ +noncomputable def truncLEMap : K.truncLE e ⟶ L.truncLE e := + (unopFunctor C c'.symm).map (truncGEMap ((opFunctor C c').map φ.op) e.op).op + +variable (K) in +@[simp] +lemma truncLEMap_id : truncLEMap (𝟙 K) e = 𝟙 _ := + (unopFunctor C c'.symm).congr_map (congr_arg Quiver.Hom.op (K.op.truncGEMap_id e.op)) + +@[reassoc, simp] +lemma truncLEMap_comp : truncLEMap (φ ≫ φ') e = truncLEMap φ e ≫ truncLEMap φ' e := + (unopFunctor C c'.symm).congr_map (congr_arg Quiver.Hom.op + (truncGEMap_comp ((opFunctor C c').map φ'.op) ((opFunctor C c').map φ.op) e.op)) + +end + +/-- The canonical morphism `K.truncLE' e ⟶ K.restriction e`. -/ +noncomputable def truncLE'ToRestriction : K.truncLE' e ⟶ K.restriction e := + (unopFunctor C c.symm).map (K.op.restrictionToTruncGE' e.op).op + +/-- `(K.truncLE'ToRestriction e).f i` is an isomorphism when `¬ e.BoundaryLE i`. -/ +lemma isIso_truncLE'ToRestriction (i : ι) (hi : ¬ e.BoundaryLE i) : + IsIso ((K.truncLE'ToRestriction e).f i) := by + change IsIso ((K.op.restrictionToTruncGE' e.op).f i).unop + have := K.op.isIso_restrictionToTruncGE' e.op i (by simpa) + infer_instance + +variable {K L} in +@[reassoc (attr := simp)] +lemma truncLE'ToRestriction_naturality : + truncLE'Map φ e ≫ L.truncLE'ToRestriction e = + K.truncLE'ToRestriction e ≫ restrictionMap φ e := + (unopFunctor C c.symm).congr_map (congr_arg Quiver.Hom.op + (restrictionToTruncGE'_naturality ((opFunctor C c').map φ.op) e.op)) + +instance (i : ι) : Mono ((K.truncLE'ToRestriction e).f i) := + inferInstanceAs (Mono ((K.op.restrictionToTruncGE' e.op).f i).unop) + +instance [K.IsStrictlySupported e] (i : ι) : + IsIso ((K.truncLE'ToRestriction e).f i) := + inferInstanceAs (IsIso ((K.op.restrictionToTruncGE' e.op).f i).unop) + +section + +variable [HasZeroObject C] + +/-- The canonical morphism `K.truncLE e ⟶ K` when `e` is an embedding of complex +shapes which satisfy `e.IsTruncLE`. -/ +noncomputable def ιTruncLE : K.truncLE e ⟶ K := + (unopFunctor C c'.symm).map (K.op.πTruncGE e.op).op + +instance (i' : ι') : Mono ((K.ιTruncLE e).f i') := + inferInstanceAs (Mono ((K.op.πTruncGE e.op).f i').unop) + +instance : Mono (K.ιTruncLE e) := mono_of_mono_f _ (fun _ => inferInstance) + +instance : (K.truncLE e).IsStrictlySupported e := by + rw [← isStrictlySupported_op_iff] + exact inferInstanceAs ((K.op.truncGE e.op).IsStrictlySupported e.op) + +variable {K L} in +@[reassoc (attr := simp)] +lemma ιTruncLE_naturality : + truncLEMap φ e ≫ L.ιTruncLE e = K.ιTruncLE e ≫ φ := + (unopFunctor C c'.symm).congr_map (congr_arg Quiver.Hom.op + (πTruncGE_naturality ((opFunctor C c').map φ.op) e.op)) + +instance {ι'' : Type*} {c'' : ComplexShape ι''} (e' : c''.Embedding c') + [K.IsStrictlySupported e'] : (K.truncLE e).IsStrictlySupported e' := by + rw [← isStrictlySupported_op_iff] + exact inferInstanceAs ((K.op.truncGE e.op).IsStrictlySupported e'.op) + +instance [K.IsStrictlySupported e] : IsIso (K.ιTruncLE e) := + inferInstanceAs (IsIso ((unopFunctor C c'.symm).map (K.op.πTruncGE e.op).op)) + +end + +end HomologicalComplex + +namespace ComplexShape.Embedding + +variable (e : Embedding c c') [e.IsTruncLE] + (C : Type*) [Category C] [HasZeroMorphisms C] [HasZeroObject C] [CategoryWithHomology C] + +/-- Given an embedding `e : Embedding c c'` of complex shapes which satisfy `e.IsTruncLE`, +this is the (canonical) truncation functor +`HomologicalComplex C c' ⥤ HomologicalComplex C c`. -/ +@[simps] +noncomputable def truncLE'Functor : + HomologicalComplex C c' ⥤ HomologicalComplex C c where + obj K := K.truncLE' e + map φ := HomologicalComplex.truncLE'Map φ e + +/-- The natural transformation `K.truncGE' e ⟶ K.restriction e` for all `K`. -/ +@[simps] +noncomputable def truncLE'ToRestrictionNatTrans : + e.truncLE'Functor C ⟶ e.restrictionFunctor C where + app K := K.truncLE'ToRestriction e + +/-- Given an embedding `e : Embedding c c'` of complex shapes which satisfy `e.IsTruncLE`, +this is the (canonical) truncation functor +`HomologicalComplex C c' ⥤ HomologicalComplex C c'`. -/ +@[simps] +noncomputable def truncLEFunctor : + HomologicalComplex C c' ⥤ HomologicalComplex C c' where + obj K := K.truncLE e + map φ := HomologicalComplex.truncLEMap φ e + +/-- The natural transformation `K.ιTruncLE e : K.truncLE e ⟶ K` for all `K`. -/ +@[simps] +noncomputable def ιTruncLENatTrans : e.truncLEFunctor C ⟶ 𝟭 _ where + app K := K.ιTruncLE e + +end ComplexShape.Embedding From 66e14198c9acbb7f21fd32c34d0bba8c2ff3c7b6 Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Fri, 17 Jan 2025 07:37:39 +0000 Subject: [PATCH 281/681] feat(RingTheory): flatness over a semiring (#19115) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A module over a ring is said to be flat if tensoring with it preserves injective linear maps. The same definition remains reasonable over a semiring, because (1) injective linear maps still coincides with monomorphisms over a semiring*; (2) projective modules (in particular, free modules) and localizations are still examples of flat modules over a semiring; (3) we recently fixed the definition of linear independence over semirings (#18426), and flatness of S/R means `(1:S) ⊗[R] ·` preserves linear independence. In fact (2) is the main motivation for this PR: it allows us to unify results about free modules (e.g. polynomial algebras) and localizations over a semiring. There is a caveat in the definition: injective linear maps need to come from a particular universe, as we can't quantify over all universes. Over a ring, using Baer's criterion and character modules, we may restrict to inclusion maps of (f.g.) ideals, and that was the definition adopted in Mathlib. However, the proof doesn't work over a semiring due to three difficulties: (1) Baer's criterion for injective modules doesn't work over a semiring; (2) Q/Z isn't an injective object in the category of AddCommMonoids, in fact this category [doesn't have enough injectives](https://mathoverflow.net/questions/277284/which-semirings-have-enough-injectives-in-their-category-of-modules); (3) homs into Q/Z does not distinguish points in an AddCommMonoid. However, we can still show that it suffices to consider injective linear maps between modules in the same universe as the semiring, using the fact that every module is the direct limit of its f.g. submodules, and that taking tensor products commutes with taking direct limits: of course, f.g. modules fit in the same universe as the semiring. We therefore change the definition of flatness to state preservation of injectivity of inclusion of f.g. submodules into f.g. modules in the same universe as the semiring. As we reorder the lemmas in Flat/Basic.lean, We also change all the iff lemmas to use implicit arguments; several other files need to be fixed for this reason, and as we fix them, we also generalize them to CommSemirings and in some cases golf the proofs. (*) There are more epimorphisms than surjective homs, e.g. the inclusion of N in Z. --- .../AdicCompletion/AsTensorProduct.lean | 2 +- Mathlib/RingTheory/Flat/Basic.lean | 511 +++++++++--------- .../RingTheory/Flat/EquationalCriterion.lean | 2 +- .../RingTheory/Flat/FaithfullyFlat/Basic.lean | 2 +- Mathlib/RingTheory/Flat/Localization.lean | 41 +- Mathlib/RingTheory/Flat/Stability.lean | 106 +--- Mathlib/RingTheory/LinearDisjoint.lean | 2 +- Mathlib/RingTheory/LocalRing/Module.lean | 2 - Mathlib/RingTheory/RingHom/Flat.lean | 4 +- Mathlib/RingTheory/Unramified/Finite.lean | 2 +- docs/references.bib | 38 ++ 11 files changed, 359 insertions(+), 353 deletions(-) diff --git a/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean b/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean index 7327b43e29424..2c56bfd1a747e 100644 --- a/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean +++ b/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean @@ -376,7 +376,7 @@ end /-- Adic completion of a Noetherian ring `R` is flat over `R`. -/ instance flat_of_isNoetherian [IsNoetherianRing R] : Module.Flat R (AdicCompletion I R) := - (Module.Flat.iff_lTensor_injective' R (AdicCompletion I R)).mpr fun J ↦ + Module.Flat.iff_lTensor_injective'.mpr fun J ↦ tensor_map_id_left_injective_of_injective I (Submodule.injective_subtype J) end Noetherian diff --git a/Mathlib/RingTheory/Flat/Basic.lean b/Mathlib/RingTheory/Flat/Basic.lean index dfb5b054087df..851f3c79fcdfd 100644 --- a/Mathlib/RingTheory/Flat/Basic.lean +++ b/Mathlib/RingTheory/Flat/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Jujian Zhang, Yongle Hu -/ +import Mathlib.Algebra.Colimit.TensorProduct import Mathlib.Algebra.DirectSum.Finsupp import Mathlib.Algebra.DirectSum.Module import Mathlib.Algebra.Exact @@ -10,6 +11,7 @@ import Mathlib.Algebra.Module.CharacterModule import Mathlib.Algebra.Module.Injective import Mathlib.Algebra.Module.Projective import Mathlib.LinearAlgebra.DirectSum.TensorProduct +import Mathlib.RingTheory.Finiteness.Cardinality import Mathlib.LinearAlgebra.FreeModule.Basic import Mathlib.LinearAlgebra.TensorProduct.RightExactness import Mathlib.RingTheory.Finiteness.TensorProduct @@ -17,14 +19,22 @@ import Mathlib.RingTheory.Finiteness.TensorProduct /-! # Flat modules -A module `M` over a commutative ring `R` is *flat* -if for all finitely generated ideals `I` of `R`, -the canonical map `I ⊗ M →ₗ M` is injective. +A module `M` over a commutative semiring `R` is *mono-flat* if for all monomorphisms of modules +(i.e., injective linear maps) `N →ₗ[R] P`, the canonical map `N ⊗ M → P ⊗ M` is injective +(cf. [Katsov2004], [KatsovNam2011]). +To show a module is mono-flat, it suffices to check inclusions of finitely generated +submodules `N` into finitely generated modules `P`, and `P` can be further assumed to lie in +the same universe as `R`. -This is equivalent to the claim that for all injective `R`-linear maps `f : M₁ → M₂` -the induced map `M₁ ⊗ M → M₂ ⊗ M` is injective. +`M` is flat if `· ⊗ M` preserves finite limits (equivalently, pullbacks, or equalizers). +If `R` is a ring, an `R`-module `M` is flat if and only if it is mono-flat, and to show +a module is flat, it suffices to check inclusions of finitely generated ideals into `R`. See . +Currently, `Module.Flat` is defined to be equivalent to mono-flatness over a semiring. +It is left as a TODO item to introduce the genuine flatness over semirings and rename +the current `Module.Flat` to `Module.MonoFlat`. + ## Main declaration * `Module.Flat`: the predicate asserting that an `R`-module `M` is flat. @@ -49,11 +59,10 @@ See . ## TODO -* Generalize flatness to noncommutative rings. +* Generalize flatness to noncommutative semirings. -/ - universe v' u v w open TensorProduct @@ -64,268 +73,304 @@ open Function (Surjective) open LinearMap Submodule DirectSum -variable (R : Type u) (M : Type v) [CommRing R] [AddCommGroup M] [Module R M] +section Semiring + +/-! ### Flatness over a semiring -/ + +variable {R : Type u} {M : Type v} {N P Q : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + [AddCommMonoid N] [Module R N] [AddCommMonoid P] [Module R P] [AddCommMonoid Q] [Module R Q] + +theorem _root_.LinearMap.rTensor_injective_of_fg {f : N →ₗ[R] P} + (h : ∀ (N' : Submodule R N) (P' : Submodule R P), + N'.FG → P'.FG → ∀ h : N' ≤ P'.comap f, Function.Injective ((f.restrict h).rTensor M)) : + Function.Injective (f.rTensor M) := fun x y eq ↦ by + have ⟨N', Nfg, sub⟩ := Submodule.exists_fg_le_subset_range_rTensor_subtype {x, y} (by simp) + obtain ⟨x, rfl⟩ := sub (.inl rfl) + obtain ⟨y, rfl⟩ := sub (.inr rfl) + simp_rw [← rTensor_comp_apply, show f ∘ₗ N'.subtype = (N'.map f).subtype ∘ₗ f.submoduleMap N' + from rfl, rTensor_comp_apply] at eq + have ⟨P', Pfg, le, eq⟩ := (Nfg.map _).exists_rTensor_fg_inclusion_eq eq + simp_rw [← rTensor_comp_apply] at eq + rw [h _ _ Nfg Pfg (map_le_iff_le_comap.mp le) eq] + +lemma _root_.LinearMap.rTensor_injective_iff_subtype {f : N →ₗ[R] P} (hf : Function.Injective f) + (e : P ≃ₗ[R] Q) : Function.Injective (f.rTensor M) ↔ + Function.Injective ((range <| e.toLinearMap ∘ₗ f).subtype.rTensor M) := by + simp_rw [← EquivLike.injective_comp <| (LinearEquiv.ofInjective (e.toLinearMap ∘ₗ f) + (e.injective.comp hf)).rTensor M, ← EquivLike.comp_injective _ (e.rTensor M), + ← LinearEquiv.coe_coe, ← coe_comp, LinearEquiv.coe_rTensor, ← rTensor_comp] + rfl -/-- An `R`-module `M` is flat if for all finitely generated ideals `I` of `R`, -the canonical map `I ⊗ M →ₗ M` is injective. -/ +variable (R M) in +/-- An `R`-module `M` is flat if for every finitely generated submodule `N` of every +finitely generated `R`-module `P` in the same universe as `R`, +the canonical map `N ⊗ M → P ⊗ M` is injective. This implies the same is true for +arbitrary `R`-modules `N` and `P` and injective linear maps `N →ₗ[R] P`, see +`Flat.rTensor_preserves_injective_linearMap`. To show a module over a ring `R` is flat, it +suffices to consider the case `P = R`, see `Flat.iff_rTensor_injective`. -/ @[mk_iff] class Flat : Prop where - out : ∀ ⦃I : Ideal R⦄ (_ : I.FG), - Function.Injective (TensorProduct.lift ((lsmul R M).comp I.subtype)) + out ⦃P : Type u⦄ [AddCommMonoid P] [Module R P] [Module.Finite R P] (N : Submodule R P) : N.FG → + Function.Injective (N.subtype.rTensor M) namespace Flat -variable {R} in -instance instSubalgebraToSubmodule {S : Type v} [Ring S] [Algebra R S] - (A : Subalgebra R S) [Flat R A] : Flat R (Subalgebra.toSubmodule A) := ‹Flat R A› - -instance self (R : Type u) [CommRing R] : Flat R R := - ⟨by - intro I _ - rw [← Equiv.injective_comp (TensorProduct.rid R I).symm.toEquiv] +/-- If `M` is a flat module, then `f ⊗ 𝟙 M` is injective for all injective linear maps `f`. -/ +theorem rTensor_preserves_injective_linearMap [Flat R M] (f : N →ₗ[R] P) + (hf : Function.Injective f) : Function.Injective (f.rTensor M) := by + refine rTensor_injective_of_fg fun N P Nfg Pfg le ↦ ?_ + rw [← Finite.iff_fg] at Nfg Pfg + have := Finite.small R P + let se := (Shrink.linearEquiv.{_, u} P R).symm + have := Module.Finite.equiv se + rw [rTensor_injective_iff_subtype (fun _ _ ↦ (Subtype.ext <| hf <| Subtype.ext_iff.mp ·)) se] + exact (flat_iff R M).mp ‹_› _ (Finite.iff_fg.mp inferInstance) + +/-- If `M` is a flat module, then `𝟙 M ⊗ f` is injective for all injective linear maps `f`. -/ +theorem lTensor_preserves_injective_linearMap [Flat R M] (f : N →ₗ[R] P) + (hf : Function.Injective f) : Function.Injective (f.lTensor M) := + (f.lTensor_inj_iff_rTensor_inj M).2 (rTensor_preserves_injective_linearMap f hf) + +/-- `M` is flat if and only if `f ⊗ 𝟙 M` is injective whenever `f` is an injective linear map +in a universe that `R` fits in. -/ +lemma iff_rTensor_preserves_injective_linearMapₛ [Small.{v'} R] : Flat R M ↔ + ∀ ⦃N N' : Type v'⦄ [AddCommMonoid N] [AddCommMonoid N'] [Module R N] [Module R N'] + (f : N →ₗ[R] N'), Function.Injective f → Function.Injective (f.rTensor M) := + ⟨by introv _; apply rTensor_preserves_injective_linearMap, fun h ↦ ⟨fun P _ _ _ _ _ ↦ by + have := Finite.small.{v'} R P + rw [rTensor_injective_iff_subtype Subtype.val_injective (Shrink.linearEquiv.{_, v'} P R).symm] + exact h _ Subtype.val_injective⟩⟩ + +/-- `M` is flat if and only if `𝟙 M ⊗ f` is injective whenever `f` is an injective linear map +in a universe that `R` fits in. -/ +lemma iff_lTensor_preserves_injective_linearMapₛ [Small.{v'} R] : Flat R M ↔ + ∀ ⦃N N' : Type v'⦄ [AddCommMonoid N] [AddCommMonoid N'] [Module R N] [Module R N'] + (f : N →ₗ[R] N'), Function.Injective f → Function.Injective (f.lTensor M) := by + simp_rw [iff_rTensor_preserves_injective_linearMapₛ, LinearMap.lTensor_inj_iff_rTensor_inj] + +/-- An easier-to-use version of `Module.flat_iff`, with finiteness conditions removed. -/ +lemma iff_rTensor_injectiveₛ : Flat R M ↔ ∀ ⦃P : Type u⦄ [AddCommMonoid P] [Module R P] + (N : Submodule R P), Function.Injective (N.subtype.rTensor M) := + ⟨fun _ _ _ _ _ ↦ rTensor_preserves_injective_linearMap _ Subtype.val_injective, + fun h ↦ ⟨fun _ _ _ _ _ _ ↦ h _⟩⟩ + +lemma iff_lTensor_injectiveₛ : Flat R M ↔ ∀ ⦃P : Type u⦄ [AddCommMonoid P] [Module R P] + (N : Submodule R P), Function.Injective (N.subtype.lTensor M) := by + simp_rw [iff_rTensor_injectiveₛ, LinearMap.lTensor_inj_iff_rTensor_inj] + +instance instSubalgebraToSubmodule {S : Type v} [Semiring S] [Algebra R S] + (A : Subalgebra R S) [Flat R A] : Flat R A.toSubmodule := ‹Flat R A› + +instance self : Flat R R where + out _ _ _ _ I _ := by + rw [← (TensorProduct.rid R I).symm.injective_comp, ← (TensorProduct.rid R _).comp_injective] convert Subtype.coe_injective using 1 - ext x - simp only [Function.comp_apply, LinearEquiv.coe_toEquiv, rid_symm_apply, comp_apply, mul_one, - lift.tmul, Submodule.subtype_apply, Algebra.id.smul_eq_mul, lsmul_apply]⟩ - -/-- An `R`-module `M` is flat iff for all finitely generated ideals `I` of `R`, the -tensor product of the inclusion `I → R` and the identity `M → M` is injective. See -`iff_rTensor_injective'` to extend to all ideals `I`. --/ -lemma iff_rTensor_injective : - Flat R M ↔ ∀ ⦃I : Ideal R⦄ (_ : I.FG), Function.Injective (rTensor M I.subtype) := by - simp [flat_iff, ← lid_comp_rTensor] - -/-- An `R`-module `M` is flat iff for all ideals `I` of `R`, the tensor product of the -inclusion `I → R` and the identity `M → M` is injective. See `iff_rTensor_injective` to -restrict to finitely generated ideals `I`. --/ -theorem iff_rTensor_injective' : - Flat R M ↔ ∀ I : Ideal R, Function.Injective (rTensor M I.subtype) := by - rewrite [Flat.iff_rTensor_injective] - refine ⟨fun h I => ?_, fun h I _ => h I⟩ - rewrite [injective_iff_map_eq_zero] - intro x hx₀ - obtain ⟨J, hfg, hle, y, rfl⟩ := Submodule.exists_fg_le_eq_rTensor_inclusion x - rewrite [← rTensor_comp_apply] at hx₀ - rw [(injective_iff_map_eq_zero _).mp (h hfg) y hx₀, LinearMap.map_zero] - -/-- The `lTensor`-variant of `iff_rTensor_injective`. . -/ -theorem iff_lTensor_injective : - Module.Flat R M ↔ ∀ ⦃I : Ideal R⦄ (_ : I.FG), Function.Injective (lTensor M I.subtype) := by - simpa [← comm_comp_rTensor_comp_comm_eq] using Module.Flat.iff_rTensor_injective R M - -/-- The `lTensor`-variant of `iff_rTensor_injective'`. . -/ -theorem iff_lTensor_injective' : - Module.Flat R M ↔ ∀ (I : Ideal R), Function.Injective (lTensor M I.subtype) := by - simpa [← comm_comp_rTensor_comp_comm_eq] using Module.Flat.iff_rTensor_injective' R M - -variable (N : Type w) [AddCommGroup N] [Module R N] + ext; simp /-- A retract of a flat `R`-module is flat. -/ lemma of_retract [f : Flat R M] (i : N →ₗ[R] M) (r : M →ₗ[R] N) (h : r.comp i = LinearMap.id) : Flat R N := by - rw [iff_rTensor_injective] at * - intro I hI - have h₁ : Function.Injective (lTensor R i) := by - apply Function.RightInverse.injective (g := (lTensor R r)) - intro x - rw [← LinearMap.comp_apply, ← lTensor_comp, h] - simp - rw [← Function.Injective.of_comp_iff h₁ (rTensor N I.subtype), ← LinearMap.coe_comp] - rw [LinearMap.lTensor_comp_rTensor, ← LinearMap.rTensor_comp_lTensor] - rw [LinearMap.coe_comp, Function.Injective.of_comp_iff (f hI)] - apply Function.RightInverse.injective (g := lTensor _ r) - intro x - rw [← LinearMap.comp_apply, ← lTensor_comp, h] - simp + rw [iff_rTensor_injectiveₛ] at * + refine fun P _ _ Q ↦ .of_comp (f := lTensor P i) ?_ + rw [← coe_comp, lTensor_comp_rTensor, ← rTensor_comp_lTensor, coe_comp] + refine (f Q).comp (Function.RightInverse.injective (g := lTensor Q r) fun x ↦ ?_) + simp [← comp_apply, ← lTensor_comp, h] /-- A `R`-module linearly equivalent to a flat `R`-module is flat. -/ -lemma of_linearEquiv [f : Flat R M] (e : N ≃ₗ[R] M) : Flat R N := by - have h : e.symm.toLinearMap.comp e.toLinearMap = LinearMap.id := by simp - exact of_retract _ _ _ e.toLinearMap e.symm.toLinearMap h +lemma of_linearEquiv [Flat R M] (e : N ≃ₗ[R] M) : Flat R N := + of_retract e.toLinearMap e.symm (by simp) /-- If an `R`-module `M` is linearly equivalent to another `R`-module `N`, then `M` is flat if and only if `N` is flat. -/ lemma equiv_iff (e : M ≃ₗ[R] N) : Flat R M ↔ Flat R N := - ⟨fun _ => of_linearEquiv R M N e.symm, fun _ => of_linearEquiv R N M e⟩ + ⟨fun _ ↦ of_linearEquiv e.symm, fun _ ↦ of_linearEquiv e⟩ -instance ulift [Module.Flat R M] : Module.Flat R (ULift.{v'} M) := - of_linearEquiv R M (ULift.{v'} M) ULift.moduleEquiv +instance ulift [Flat R M] : Flat R (ULift.{v'} M) := + of_linearEquiv ULift.moduleEquiv -- Making this an instance causes an infinite sequence `M → ULift M → ULift (ULift M) → ...`. -lemma of_ulift [Module.Flat R (ULift.{v'} M)] : Module.Flat R M := - of_linearEquiv R (ULift.{v'} M) M ULift.moduleEquiv.symm +lemma of_ulift [Flat R (ULift.{v'} M)] : Flat R M := + of_linearEquiv ULift.moduleEquiv.symm -instance shrink [Small.{v'} M] [Module.Flat R M] : Module.Flat R (Shrink.{v'} M) := - of_linearEquiv R M (Shrink.{v'} M) (Shrink.linearEquiv M R) +instance shrink [Small.{v'} M] [Flat R M] : Flat R (Shrink.{v'} M) := + of_linearEquiv (Shrink.linearEquiv M R) -- Making this an instance causes an infinite sequence `M → Shrink M → Shrink (Shrink M) → ...`. -lemma of_shrink [Small.{v'} M] [Module.Flat R (Shrink.{v'} M)] : - Module.Flat R M := - of_linearEquiv R (Shrink.{v'} M) M (Shrink.linearEquiv M R).symm +lemma of_shrink [Small.{v'} M] [Flat R (Shrink.{v'} M)] : Flat R M := + of_linearEquiv (Shrink.linearEquiv M R).symm -/-- A direct sum of flat `R`-modules is flat. -/ -instance directSum (ι : Type v) (M : ι → Type w) [(i : ι) → AddCommGroup (M i)] - [(i : ι) → Module R (M i)] [F : (i : ι) → (Flat R (M i))] : Flat R (⨁ i, M i) := by - haveI := Classical.decEq ι - rw [iff_rTensor_injective] - intro I hI - -- This instance was added during PR https://github.com/leanprover-community/mathlib4/pull/10828, - -- see https://leanprover.zulipchat.com/#narrow/stream/144837-PR-reviews/topic/.2310828.20-.20generalizing.20CommRing.20to.20CommSemiring.20etc.2E/near/422684923 - letI : ∀ i, AddCommGroup (I ⊗[R] M i) := inferInstance - rw [← Equiv.comp_injective _ (TensorProduct.lid R (⨁ i, M i)).toEquiv] - set η₁ := TensorProduct.lid R (⨁ i, M i) - set η := fun i ↦ TensorProduct.lid R (M i) - set φ := fun i ↦ rTensor (M i) I.subtype - set π := fun i ↦ component R ι (fun j ↦ M j) i - set ψ := (TensorProduct.directSumRight R {x // x ∈ I} (fun i ↦ M i)).symm.toLinearMap with psi_def - set ρ := rTensor (⨁ i, M i) I.subtype - set τ := (fun i ↦ component R ι (fun j ↦ ({x // x ∈ I} ⊗[R] (M j))) i) - rw [← Equiv.injective_comp (TensorProduct.directSumRight _ _ _).symm.toEquiv] - rw [LinearEquiv.coe_toEquiv, ← LinearEquiv.coe_coe, ← LinearMap.coe_comp] - rw [LinearEquiv.coe_toEquiv, ← LinearEquiv.coe_coe, ← LinearMap.coe_comp] - rw [← psi_def, injective_iff_map_eq_zero ((η₁.comp ρ).comp ψ)] - have h₁ : ∀ (i : ι), (π i).comp ((η₁.comp ρ).comp ψ) = (η i).comp ((φ i).comp (τ i)) := by - intro i - apply DirectSum.linearMap_ext - intro j - apply TensorProduct.ext' - intro a m - simp only [ρ, ψ, φ, η, η₁, coe_comp, LinearEquiv.coe_coe, Function.comp_apply, - directSumRight_symm_lof_tmul, rTensor_tmul, Submodule.coe_subtype, lid_tmul, map_smul] - rw [DirectSum.component.of, DirectSum.component.of] - by_cases h₂ : j = i - · subst j; simp - · simp [h₂] - intro a ha; rw [DirectSum.ext_component_iff R]; intro i - have f := LinearMap.congr_arg (f := (π i)) ha - erw [LinearMap.congr_fun (h₁ i) a] at f - rw [(map_zero (π i) : (π i) 0 = (0 : M i))] at f - have h₂ := F i - rw [iff_rTensor_injective] at h₂ - have h₃ := h₂ hI - simp only [φ, τ, coe_comp, LinearEquiv.coe_coe, Function.comp_apply, - EmbeddingLike.map_eq_zero_iff, h₃, LinearMap.map_eq_zero_iff] at f - simp [f] - -open scoped Classical in -/-- Free `R`-modules over discrete types are flat. -/ -instance finsupp (ι : Type v) : Flat R (ι →₀ R) := - of_linearEquiv R _ _ (finsuppLEquivDirectSum R R ι) +section DirectSum -instance of_free [Free R M] : Flat R M := of_linearEquiv R _ _ (Free.repr R M) +variable {ι : Type v} {M : ι → Type w} [Π i, AddCommMonoid (M i)] [Π i, Module R (M i)] -/-- A projective module with a discrete type of generator is flat -/ -lemma of_projective_surjective (ι : Type w) [Projective R M] (p : (ι →₀ R) →ₗ[R] M) - (hp : Surjective p) : Flat R M := by - have h := Module.projective_lifting_property p (LinearMap.id) hp - cases h with - | _ e he => exact of_retract R _ _ _ _ he +theorem directSum_iff : Flat R (⨁ i, M i) ↔ ∀ i, Flat R (M i) := by + classical + simp_rw [iff_rTensor_injectiveₛ, ← EquivLike.comp_injective _ (directSumRight R _ _), + ← LinearEquiv.coe_coe, ← coe_comp, directSumRight_comp_rTensor, coe_comp, LinearEquiv.coe_coe, + EquivLike.injective_comp, lmap_injective] + constructor <;> (intro h; intros; apply h) -instance of_projective [h : Projective R M] : Flat R M := by - rw [Module.projective_def'] at h - cases h with - | _ e he => exact of_retract R _ _ _ _ he +theorem dfinsupp_iff : Flat R (Π₀ i, M i) ↔ ∀ i, Flat R (M i) := directSum_iff .. -/-- -Define the character module of `M` to be `M →+ ℚ ⧸ ℤ`. -The character module of `M` is an injective module if and only if - `L ⊗ 𝟙 M` is injective for any linear map `L` in the same universe as `M`. --/ -lemma injective_characterModule_iff_rTensor_preserves_injective_linearMap : - Module.Injective R (CharacterModule M) ↔ - ∀ ⦃N N' : Type v⦄ [AddCommGroup N] [AddCommGroup N'] [Module R N] [Module R N'] - (L : N →ₗ[R] N'), Function.Injective L → Function.Injective (L.rTensor M) := by - simp_rw [injective_iff, rTensor_injective_iff_lcomp_surjective, Surjective, DFunLike.ext_iff]; rfl +/-- A direct sum of flat `R`-modules is flat. -/ +instance directSum [∀ i, Flat R (M i)] : Flat R (⨁ i, M i) := directSum_iff.mpr ‹_› -variable {R M N} +instance dfinsupp [∀ i, Flat R (M i)] : Flat R (Π₀ i, M i) := dfinsupp_iff.mpr ‹_› -/-- `CharacterModule M` is Baer iff `M` is flat. -/ -theorem iff_characterModule_baer : Flat R M ↔ Module.Baer R (CharacterModule M) := by - simp_rw [iff_rTensor_injective', Baer, rTensor_injective_iff_lcomp_surjective, - Surjective, DFunLike.ext_iff, Subtype.forall]; rfl +end DirectSum -/-- `CharacterModule M` is an injective module iff `M` is flat. -See [Lambek_1964] for a self-contained proof. -/ -theorem iff_characterModule_injective [Small.{v} R] : - Flat R M ↔ Module.Injective R (CharacterModule M) := - iff_characterModule_baer.trans Module.Baer.iff_injective +/-- Free `R`-modules over discrete types are flat. -/ +instance finsupp (ι : Type v) : Flat R (ι →₀ R) := by + classical exact of_linearEquiv (finsuppLEquivDirectSum R R ι) -/-- -If `M` is a flat module, then `f ⊗ 𝟙 M` is injective for all injective linear maps `f`. --/ -theorem rTensor_preserves_injective_linearMap {N' : Type*} [AddCommGroup N'] [Module R N'] - [h : Flat R M] (L : N →ₗ[R] N') (hL : Function.Injective L) : - Function.Injective (L.rTensor M) := - rTensor_injective_iff_lcomp_surjective.2 ((iff_characterModule_baer.1 h).extension_property _ hL) - -instance {S} [CommRing S] [Algebra R S] [Module S M] [IsScalarTower R S M] [Flat S M] [Flat R N] : - Flat S (M ⊗[R] N) := - (iff_rTensor_injective' _ _).mpr fun I ↦ by +instance of_projective [Projective R M] : Flat R M := + have ⟨e, he⟩:= Module.projective_def'.mp ‹_› + of_retract _ _ he + +@[deprecated (since := "2024-12-26")] alias of_projective_surjective := of_projective + +instance of_free [Free R M] : Flat R M := inferInstance + +instance {S} [CommSemiring S] [Algebra R S] [Module S M] [IsScalarTower R S M] + [Flat S M] [Flat R N] : Flat S (M ⊗[R] N) := + iff_rTensor_injectiveₛ.mpr fun P _ _ I ↦ by + letI := RestrictScalars.moduleOrig R S P + change Submodule S (RestrictScalars R S P) at I + change Function.Injective (rTensor _ I.subtype) simpa [AlgebraTensorModule.rTensor_tensor] using rTensor_preserves_injective_linearMap (.restrictScalars R <| I.subtype.rTensor M) (rTensor_preserves_injective_linearMap _ I.injective_subtype) example [Flat R M] [Flat R N] : Flat R (M ⊗[R] N) := inferInstance -/-- -If `M` is a flat module, then `𝟙 M ⊗ f` is injective for all injective linear maps `f`. --/ -theorem lTensor_preserves_injective_linearMap {N' : Type*} [AddCommGroup N'] [Module R N'] - [Flat R M] (L : N →ₗ[R] N') (hL : Function.Injective L) : - Function.Injective (L.lTensor M) := - (L.lTensor_inj_iff_rTensor_inj M).2 (rTensor_preserves_injective_linearMap L hL) - -theorem linearIndependent_one_tmul {S} [Ring S] [Algebra R S] [Flat R S] {ι} {v : ι → M} +theorem linearIndependent_one_tmul {S} [Semiring S] [Algebra R S] [Flat R S] {ι} {v : ι → M} (hv : LinearIndependent R v) : LinearIndependent S ((1 : S) ⊗ₜ[R] v ·) := by classical rw [LinearIndependent, ← LinearMap.coe_restrictScalars R, Finsupp.linearCombination_one_tmul] simpa using lTensor_preserves_injective_linearMap _ hv -variable (R M) in +variable (p : Submodule R M) (q : Submodule R N) + +/-- If p and q are submodules of M and N respectively, and M and q are flat, +then `p ⊗ q → M ⊗ N` is injective. -/ +theorem tensorProduct_mapIncl_injective_of_right + [Flat R M] [Flat R q] : Function.Injective (mapIncl p q) := by + rw [mapIncl, ← lTensor_comp_rTensor] + exact (lTensor_preserves_injective_linearMap _ q.injective_subtype).comp + (rTensor_preserves_injective_linearMap _ p.injective_subtype) + +/-- If p and q are submodules of M and N respectively, and N and p are flat, +then `p ⊗ q → M ⊗ N` is injective. -/ +theorem tensorProduct_mapIncl_injective_of_left + [Flat R p] [Flat R N] : Function.Injective (mapIncl p q) := by + rw [mapIncl, ← rTensor_comp_lTensor] + exact (rTensor_preserves_injective_linearMap _ p.injective_subtype).comp + (lTensor_preserves_injective_linearMap _ q.injective_subtype) + +end Flat + +end Semiring + +namespace Flat + +/-! ### Flatness over a ring -/ + +variable {R : Type u} {M : Type v} [CommRing R] [AddCommGroup M] [Module R M] +variable {N : Type w} [AddCommGroup N] [Module R N] + /-- `M` is flat if and only if `f ⊗ 𝟙 M` is injective whenever `f` is an injective linear map. See `Module.Flat.iff_rTensor_preserves_injective_linearMap` to specialize the universe of `N, N', N''` to `Type (max u v)`. -/ -lemma iff_rTensor_preserves_injective_linearMap' [Small.{v'} R] [Small.{v'} M] : Flat R M ↔ +lemma iff_rTensor_preserves_injective_linearMap' [Small.{v'} R] : Flat R M ↔ ∀ ⦃N N' : Type v'⦄ [AddCommGroup N] [AddCommGroup N'] [Module R N] [Module R N'] - (f : N →ₗ[R] N') (_ : Function.Injective f), Function.Injective (f.rTensor M) := - (Module.Flat.equiv_iff R M (Shrink.{v'} M) (Shrink.linearEquiv M R).symm).trans <| - iff_characterModule_injective.trans <| - (injective_characterModule_iff_rTensor_preserves_injective_linearMap R (Shrink.{v'} M)).trans - <| forall₅_congr <| fun N N' _ _ _ => forall₃_congr <| fun _ f _ => - let frmu := f.rTensor (Shrink.{v'} M) - let frm := f.rTensor M - let emn := TensorProduct.congr (LinearEquiv.refl R N) (Shrink.linearEquiv M R) - let emn' := TensorProduct.congr (LinearEquiv.refl R N') (Shrink.linearEquiv M R) - have h : emn'.toLinearMap.comp frmu = frm.comp emn.toLinearMap := TensorProduct.ext rfl - (EquivLike.comp_injective frmu emn').symm.trans <| - (congrArg Function.Injective (congrArg DFunLike.coe h)).to_iff.trans <| - EquivLike.injective_comp emn frm + (f : N →ₗ[R] N'), Function.Injective f → Function.Injective (f.rTensor M) := + ⟨by introv _; apply rTensor_preserves_injective_linearMap, fun h ↦ + iff_rTensor_preserves_injective_linearMapₛ.mpr fun P N _ _ _ _ ↦ by + letI := Module.addCommMonoidToAddCommGroup R (M := P) + letI := Module.addCommMonoidToAddCommGroup R (M := N) + apply h⟩ -variable (R M) in /-- `M` is flat if and only if `f ⊗ 𝟙 M` is injective whenever `f` is an injective linear map. See `Module.Flat.iff_rTensor_preserves_injective_linearMap'` to generalize the universe of `N, N', N''` to any universe that is higher than `R` and `M`. -/ lemma iff_rTensor_preserves_injective_linearMap : Flat R M ↔ ∀ ⦃N N' : Type (max u v)⦄ [AddCommGroup N] [AddCommGroup N'] [Module R N] [Module R N'] - (f : N →ₗ[R] N') (_ : Function.Injective f), Function.Injective (f.rTensor M) := - iff_rTensor_preserves_injective_linearMap'.{max u v} R M + (f : N →ₗ[R] N'), Function.Injective f → Function.Injective (f.rTensor M) := + iff_rTensor_preserves_injective_linearMap' -variable (R M) in /-- `M` is flat if and only if `𝟙 M ⊗ f` is injective whenever `f` is an injective linear map. See `Module.Flat.iff_lTensor_preserves_injective_linearMap` to specialize the universe of `N, N', N''` to `Type (max u v)`. -/ -lemma iff_lTensor_preserves_injective_linearMap' [Small.{v'} R] [Small.{v'} M] : Flat R M ↔ +lemma iff_lTensor_preserves_injective_linearMap' [Small.{v'} R] : Flat R M ↔ ∀ ⦃N N' : Type v'⦄ [AddCommGroup N] [AddCommGroup N'] [Module R N] [Module R N'] - (L : N →ₗ[R] N'), Function.Injective L → Function.Injective (L.lTensor M) := by + (f : N →ₗ[R] N'), Function.Injective f → Function.Injective (f.lTensor M) := by simp_rw [iff_rTensor_preserves_injective_linearMap', LinearMap.lTensor_inj_iff_rTensor_inj] -variable (R M) in /-- `M` is flat if and only if `𝟙 M ⊗ f` is injective whenever `f` is an injective linear map. See `Module.Flat.iff_lTensor_preserves_injective_linearMap'` to generalize the universe of `N, N', N''` to any universe that is higher than `R` and `M`. -/ lemma iff_lTensor_preserves_injective_linearMap : Flat R M ↔ ∀ ⦃N N' : Type (max u v)⦄ [AddCommGroup N] [AddCommGroup N'] [Module R N] [Module R N'] - (f : N →ₗ[R] N') (_ : Function.Injective f), Function.Injective (f.lTensor M) := - iff_lTensor_preserves_injective_linearMap'.{max u v} R M + (f : N →ₗ[R] N'), Function.Injective f → Function.Injective (f.lTensor M) := + iff_lTensor_preserves_injective_linearMap' + +/-- +Define the character module of `M` to be `M →+ ℚ ⧸ ℤ`. +The character module of `M` is an injective module if and only if + `f ⊗ 𝟙 M` is injective for any linear map `f` in the same universe as `M`. +-/ +lemma injective_characterModule_iff_rTensor_preserves_injective_linearMap : + Module.Injective R (CharacterModule M) ↔ + ∀ ⦃N N' : Type v⦄ [AddCommGroup N] [AddCommGroup N'] [Module R N] [Module R N'] + (f : N →ₗ[R] N'), Function.Injective f → Function.Injective (f.rTensor M) := by + simp_rw [injective_iff, rTensor_injective_iff_lcomp_surjective, Surjective, DFunLike.ext_iff]; rfl + +/-- `CharacterModule M` is an injective module iff `M` is flat. +See [Lambek_1964] for a self-contained proof. -/ +theorem iff_characterModule_injective [Small.{v} R] : + Flat R M ↔ Module.Injective R (CharacterModule M) := by + rw [injective_characterModule_iff_rTensor_preserves_injective_linearMap, + iff_rTensor_preserves_injective_linearMap'] + +/-- `CharacterModule M` is Baer iff `M` is flat. -/ +theorem iff_characterModule_baer : Flat R M ↔ Baer R (CharacterModule M) := by + rw [equiv_iff (N := ULift.{u} M) ULift.moduleEquiv.symm, iff_characterModule_injective, + ← Baer.iff_injective, Baer.congr (CharacterModule.congr ULift.moduleEquiv)] + +/-- An `R`-module `M` is flat iff for all ideals `I` of `R`, the tensor product of the +inclusion `I → R` and the identity `M → M` is injective. See `iff_rTensor_injective` to +restrict to finitely generated ideals `I`. --/ +theorem iff_rTensor_injective' : + Flat R M ↔ ∀ I : Ideal R, Function.Injective (rTensor M I.subtype) := by + simp_rw [iff_characterModule_baer, Baer, rTensor_injective_iff_lcomp_surjective, + Surjective, DFunLike.ext_iff, Subtype.forall] + rfl + +/-- The `lTensor`-variant of `iff_rTensor_injective'`. . -/ +theorem iff_lTensor_injective' : + Flat R M ↔ ∀ (I : Ideal R), Function.Injective (lTensor M I.subtype) := by + simpa [← comm_comp_rTensor_comp_comm_eq] using iff_rTensor_injective' + +/-- A module `M` over a ring `R` is flat iff for all finitely generated ideals `I` of `R`, the +tensor product of the inclusion `I → R` and the identity `M → M` is injective. See +`iff_rTensor_injective'` to extend to all ideals `I`. -/ +lemma iff_rTensor_injective : + Flat R M ↔ ∀ ⦃I : Ideal R⦄, I.FG → Function.Injective (I.subtype.rTensor M) := by + refine iff_rTensor_injective'.trans ⟨fun h I _ ↦ h I, + fun h I ↦ (injective_iff_map_eq_zero _).mpr fun x hx ↦ ?_⟩ + obtain ⟨J, hfg, hle, y, rfl⟩ := Submodule.exists_fg_le_eq_rTensor_inclusion x + rw [← rTensor_comp_apply] at hx + rw [(injective_iff_map_eq_zero _).mp (h hfg) y hx, map_zero] + +/-- The `lTensor`-variant of `iff_rTensor_injective`. -/ +theorem iff_lTensor_injective : + Flat R M ↔ ∀ ⦃I : Ideal R⦄, I.FG → Function.Injective (I.subtype.lTensor M) := by + simpa [← comm_comp_rTensor_comp_comm_eq] using iff_rTensor_injective + +/-- An `R`-module `M` is flat if for all finitely generated ideals `I` of `R`, +the canonical map `I ⊗ M →ₗ M` is injective. -/ +lemma iff_lift_lsmul_comp_subtype_injective : Flat R M ↔ ∀ ⦃I : Ideal R⦄, I.FG → + Function.Injective (TensorProduct.lift ((lsmul R M).comp I.subtype)) := by + simp [iff_rTensor_injective, ← lid_comp_rTensor] variable (M) in /-- If `M` is flat then `M ⊗ -` is an exact functor. -/ @@ -342,7 +387,7 @@ lemma lTensor_exact [Flat R M] ⦃N N' N'' : Type*⦄ rw [show g = ι.comp π from rfl, lTensor_comp] exact exact1.comp_injective _ (lTensor_preserves_injective_linearMap ι <| by simpa [ι, - Subtype.val_injective] using Subtype.val_injective) (map_zero _) - exact _root_.lTensor_exact _ (fun x => by simp [π]) Quotient.mk''_surjective + exact _root_.lTensor_exact _ (fun x ↦ by simp [π]) Quotient.mk''_surjective variable (M) in /-- If `M` is flat then `- ⊗ M` is an exact functor. -/ @@ -359,18 +404,18 @@ lemma rTensor_exact [Flat R M] ⦃N N' N'' : Type*⦄ rw [show g = ι.comp π from rfl, rTensor_comp] exact exact1.comp_injective _ (rTensor_preserves_injective_linearMap ι <| by simpa [ι, - Subtype.val_injective] using Subtype.val_injective) (map_zero _) - exact _root_.rTensor_exact M (fun x => by simp [π]) Quotient.mk''_surjective + exact _root_.rTensor_exact M (fun x ↦ by simp [π]) Quotient.mk''_surjective /-- `M` is flat if and only if `M ⊗ -` is an exact functor. See `Module.Flat.iff_lTensor_exact` to specialize the universe of `N, N', N''` to `Type (max u v)`. -/ -theorem iff_lTensor_exact' [Small.{v'} R] [Small.{v'} M] : Flat R M ↔ +theorem iff_lTensor_exact' [Small.{v'} R] : Flat R M ↔ ∀ ⦃N N' N'' : Type v'⦄ [AddCommGroup N] [AddCommGroup N'] [AddCommGroup N''] [Module R N] [Module R N'] [Module R N''] ⦃f : N →ₗ[R] N'⦄ ⦃g : N' →ₗ[R] N''⦄, Function.Exact f g → Function.Exact (f.lTensor M) (g.lTensor M) := by - refine ⟨fun _ => lTensor_exact M, fun H => iff_lTensor_preserves_injective_linearMap' R M |>.mpr - fun N' N'' _ _ _ _ L hL => LinearMap.ker_eq_bot |>.mp <| eq_bot_iff |>.mpr - fun x (hx : _ = 0) => ?_⟩ - simpa [Eq.comm] using @H PUnit N' N'' _ _ _ _ _ _ 0 L (fun x => by + refine ⟨fun _ ↦ lTensor_exact _, fun H ↦ iff_lTensor_preserves_injective_linearMap'.mpr + fun N' N'' _ _ _ _ L hL ↦ LinearMap.ker_eq_bot |>.mp <| eq_bot_iff |>.mpr + fun x (hx : _ = 0) ↦ ?_⟩ + simpa [Eq.comm] using @H PUnit N' N'' _ _ _ _ _ _ 0 L (fun x ↦ by simp_rw [Set.mem_range, LinearMap.zero_apply, exists_const] exact (L.map_eq_zero_iff hL).trans eq_comm) x |>.mp hx @@ -381,20 +426,20 @@ theorem iff_lTensor_exact : Flat R M ↔ ∀ ⦃N N' N'' : Type (max u v)⦄ [AddCommGroup N] [AddCommGroup N'] [AddCommGroup N''] [Module R N] [Module R N'] [Module R N''] ⦃f : N →ₗ[R] N'⦄ ⦃g : N' →ₗ[R] N''⦄, Function.Exact f g → Function.Exact (f.lTensor M) (g.lTensor M) := - iff_lTensor_exact'.{max u v} + iff_lTensor_exact' /-- `M` is flat if and only if `- ⊗ M` is an exact functor. See `Module.Flat.iff_rTensor_exact` to specialize the universe of `N, N', N''` to `Type (max u v)`. -/ -theorem iff_rTensor_exact' [Small.{v'} R] [Small.{v'} M] : Flat R M ↔ +theorem iff_rTensor_exact' [Small.{v'} R] : Flat R M ↔ ∀ ⦃N N' N'' : Type v'⦄ [AddCommGroup N] [AddCommGroup N'] [AddCommGroup N''] [Module R N] [Module R N'] [Module R N''] ⦃f : N →ₗ[R] N'⦄ ⦃g : N' →ₗ[R] N''⦄, Function.Exact f g → Function.Exact (f.rTensor M) (g.rTensor M) := by - refine ⟨fun _ => rTensor_exact M, fun H => iff_rTensor_preserves_injective_linearMap' R M |>.mpr - fun N' N'' _ _ _ _ L hL => LinearMap.ker_eq_bot |>.mp <| eq_bot_iff |>.mpr - fun x (hx : _ = 0) => ?_⟩ - simpa [Eq.comm] using @H PUnit N' N'' _ _ _ _ _ _ 0 L (fun x => by + refine ⟨fun _ ↦ rTensor_exact _, fun H ↦ iff_rTensor_preserves_injective_linearMap'.mpr + fun N' N'' _ _ _ _ f hf ↦ LinearMap.ker_eq_bot |>.mp <| eq_bot_iff |>.mpr + fun x (hx : _ = 0) ↦ ?_⟩ + simpa [Eq.comm] using @H PUnit N' N'' _ _ _ _ _ _ 0 f (fun x ↦ by simp_rw [Set.mem_range, LinearMap.zero_apply, exists_const] - exact (L.map_eq_zero_iff hL).trans eq_comm) x |>.mp hx + exact (f.map_eq_zero_iff hf).trans eq_comm) x |>.mp hx /-- `M` is flat if and only if `- ⊗ M` is an exact functor. See `Module.Flat.iff_rTensor_exact'` to generalize the universe of @@ -403,25 +448,7 @@ theorem iff_rTensor_exact : Flat R M ↔ ∀ ⦃N N' N'' : Type (max u v)⦄ [AddCommGroup N] [AddCommGroup N'] [AddCommGroup N''] [Module R N] [Module R N'] [Module R N''] ⦃f : N →ₗ[R] N'⦄ ⦃g : N' →ₗ[R] N''⦄, Function.Exact f g → Function.Exact (f.rTensor M) (g.rTensor M) := - iff_rTensor_exact'.{max u v} - -variable (p : Submodule R M) (q : Submodule R N) - -/-- If p and q are submodules of M and N respectively, and M and q are flat, -then `p ⊗ q → M ⊗ N` is injective. -/ -theorem tensorProduct_mapIncl_injective_of_right - [Flat R M] [Flat R q] : Function.Injective (mapIncl p q) := by - rw [mapIncl, ← lTensor_comp_rTensor] - exact (lTensor_preserves_injective_linearMap _ q.injective_subtype).comp - (rTensor_preserves_injective_linearMap _ p.injective_subtype) - -/-- If p and q are submodules of M and N respectively, and N and p are flat, -then `p ⊗ q → M ⊗ N` is injective. -/ -theorem tensorProduct_mapIncl_injective_of_left - [Flat R p] [Flat R N] : Function.Injective (mapIncl p q) := by - rw [mapIncl, ← rTensor_comp_lTensor] - exact (rTensor_preserves_injective_linearMap _ p.injective_subtype).comp - (lTensor_preserves_injective_linearMap _ q.injective_subtype) + iff_rTensor_exact' end Flat @@ -429,7 +456,7 @@ end Module section Injective -variable {R S A B : Type*} [CommRing R] [Ring A] [Algebra R A] [Ring B] [Algebra R B] +variable {R S A B : Type*} [CommSemiring R] [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] [CommSemiring S] [Algebra S A] [SMulCommClass R S A] namespace Algebra.TensorProduct @@ -452,11 +479,11 @@ end Injective section Nontrivial -variable (R : Type*) [CommRing R] +variable (R : Type*) [CommSemiring R] namespace TensorProduct -variable (M N : Type*) [AddCommGroup M] [AddCommGroup N] [Module R M] [Module R N] +variable (M N : Type*) [AddCommMonoid M] [AddCommMonoid N] [Module R M] [Module R N] /-- If `M`, `N` are `R`-modules, there exists an injective `R`-linear map from `R` to `N`, and `M` is a nontrivial flat `R`-module, then `M ⊗[R] N` is nontrivial. -/ @@ -476,7 +503,7 @@ end TensorProduct namespace Algebra.TensorProduct -variable (A B : Type*) [CommRing A] [CommRing B] [Algebra R A] [Algebra R B] +variable (A B : Type*) [CommSemiring A] [CommSemiring B] [Algebra R A] [Algebra R B] /-- If `A`, `B` are `R`-algebras, `R` injects into `B`, and `A` is a nontrivial flat `R`-algebra, then `A ⊗[R] B` is nontrivial. -/ diff --git a/Mathlib/RingTheory/Flat/EquationalCriterion.lean b/Mathlib/RingTheory/Flat/EquationalCriterion.lean index cd762341f874b..5a653b089a00a 100644 --- a/Mathlib/RingTheory/Flat/EquationalCriterion.lean +++ b/Mathlib/RingTheory/Flat/EquationalCriterion.lean @@ -120,7 +120,7 @@ theorem tfae_equational_criterion : List.TFAE [ ∃ (k : ℕ) (a : (Fin l →₀ R) →ₗ[R] (Fin k →₀ R)) (y : (Fin k →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0] := by classical - tfae_have 1 ↔ 2 := iff_rTensor_injective' R M + tfae_have 1 ↔ 2 := iff_rTensor_injective' 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] diff --git a/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean b/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean index 600a25333f1bd..20f5be74403eb 100644 --- a/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean +++ b/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean @@ -183,7 +183,7 @@ end faithful lemma of_linearEquiv {N : Type*} [AddCommGroup N] [Module R N] [FaithfullyFlat R M] (e : N ≃ₗ[R] M) : FaithfullyFlat R N := by rw [iff_flat_and_lTensor_faithful] - exact ⟨Flat.of_linearEquiv R M N e, + exact ⟨Flat.of_linearEquiv e, fun P _ _ hP ↦ (TensorProduct.congr e (LinearEquiv.refl R P)).toEquiv.nontrivial⟩ section diff --git a/Mathlib/RingTheory/Flat/Localization.lean b/Mathlib/RingTheory/Flat/Localization.lean index b98a157a000a2..e2bd2690a03bc 100644 --- a/Mathlib/RingTheory/Flat/Localization.lean +++ b/Mathlib/RingTheory/Flat/Localization.lean @@ -24,19 +24,18 @@ In this file we show that localizations are flat, and flatness is a local proper open IsLocalizedModule LocalizedModule LinearMap TensorProduct -variable {R : Type*} (S : Type*) [CommRing R] [CommRing S] [Algebra R S] +variable {R : Type*} (S : Type*) [CommSemiring R] [CommSemiring S] [Algebra R S] variable (p : Submonoid R) [IsLocalization p S] -variable (M : Type*) [AddCommGroup M] [Module R M] [Module S M] [IsScalarTower R S M] +variable (M : Type*) [AddCommMonoid M] [Module R M] [Module S M] [IsScalarTower R S M] include p in -theorem IsLocalization.flat : Module.Flat R S := - (Module.Flat.iff_lTensor_injective' _ _).mpr fun I ↦ by - have h := (I.isLocalizedModule S p (Algebra.linearMap R S)).isBaseChange _ S _ - have : I.subtype.lTensor S = (TensorProduct.rid R S).symm.comp - ((Submodule.subtype _ ∘ₗ h.equiv.toLinearMap).restrictScalars R) := by - rw [LinearEquiv.eq_toLinearMap_symm_comp]; ext - simp [h.equiv_tmul, Algebra.smul_def, mul_comm, Algebra.ofId_apply] - simpa [this, - Subtype.val_injective] using Subtype.val_injective +theorem IsLocalization.flat : Module.Flat R S := by + refine Module.Flat.iff_lTensor_injectiveₛ.mpr fun P _ _ N ↦ ?_ + have h := ((range N.subtype).isLocalizedModule S p (TensorProduct.mk R S P 1)).isBaseChange _ S + let e := (LinearEquiv.ofInjective _ Subtype.val_injective).lTensor S ≪≫ₗ h.equiv.restrictScalars R + have : N.subtype.lTensor S = Submodule.subtype _ ∘ₗ e.toLinearMap := by + ext; show _ = (h.equiv _).1; simp [h.equiv_tmul, TensorProduct.smul_tmul'] + simpa [this] using e.injective instance Localization.flat : Module.Flat R (Localization p) := IsLocalization.flat _ p @@ -49,7 +48,7 @@ theorem flat_iff_of_isLocalization : Flat S M ↔ Flat R M := ⟨fun _ ↦ .trans R S M, fun _ ↦ .of_isLocalizedModule S p .id⟩ variable (Mₚ : ∀ (P : Ideal S) [P.IsMaximal], Type*) - [∀ (P : Ideal S) [P.IsMaximal], AddCommGroup (Mₚ P)] + [∀ (P : Ideal S) [P.IsMaximal], AddCommMonoid (Mₚ P)] [∀ (P : Ideal S) [P.IsMaximal], Module R (Mₚ P)] [∀ (P : Ideal S) [P.IsMaximal], Module S (Mₚ P)] [∀ (P : Ideal S) [P.IsMaximal], IsScalarTower R S (Mₚ P)] @@ -59,11 +58,12 @@ variable (Mₚ : ∀ (P : Ideal S) [P.IsMaximal], Type*) include f in theorem flat_of_isLocalized_maximal (H : ∀ (P : Ideal S) [P.IsMaximal], Flat R (Mₚ P)) : Module.Flat R M := by - simp_rw [Flat.iff_lTensor_injective'] at H ⊢ + simp_rw [Flat.iff_lTensor_injectiveₛ] at H ⊢ simp_rw [← AlgebraTensorModule.coe_lTensor (A := S)] - refine fun I ↦ injective_of_isLocalized_maximal _ (fun P ↦ AlgebraTensorModule.rTensor R _ (f P)) - _ (fun P ↦ AlgebraTensorModule.rTensor R _ (f P)) _ fun P hP ↦ ?_ - simpa [IsLocalizedModule.map_lTensor] using H P I + refine fun _ _ _ N ↦ injective_of_isLocalized_maximal _ + (fun P ↦ AlgebraTensorModule.rTensor R _ (f P)) _ + (fun P ↦ AlgebraTensorModule.rTensor R _ (f P)) _ fun P hP ↦ ?_ + simpa [IsLocalizedModule.map_lTensor] using H P N theorem flat_of_localized_maximal (h : ∀ (P : Ideal R) [P.IsMaximal], Flat R (LocalizedModule P.primeCompl M)) : @@ -72,7 +72,7 @@ theorem flat_of_localized_maximal variable (s : Set S) (spn : Ideal.span s = ⊤) (Mₛ : ∀ _ : s, Type*) - [∀ r : s, AddCommGroup (Mₛ r)] + [∀ r : s, AddCommMonoid (Mₛ r)] [∀ r : s, Module R (Mₛ r)] [∀ r : s, Module S (Mₛ r)] [∀ r : s, IsScalarTower R S (Mₛ r)] @@ -83,11 +83,12 @@ include spn include g in theorem flat_of_isLocalized_span (H : ∀ r : s, Module.Flat R (Mₛ r)) : Module.Flat R M := by - simp_rw [Flat.iff_lTensor_injective'] at H ⊢ + simp_rw [Flat.iff_lTensor_injectiveₛ] at H ⊢ simp_rw [← AlgebraTensorModule.coe_lTensor (A := S)] - refine fun I ↦ injective_of_isLocalized_span s spn _ (fun r ↦ AlgebraTensorModule.rTensor - R _ (g r)) _ (fun r ↦ AlgebraTensorModule.rTensor R _ (g r)) _ fun r ↦ ?_ - simpa [IsLocalizedModule.map_lTensor] using H r I + refine fun _ _ _ N ↦ injective_of_isLocalized_span s spn _ + (fun r ↦ AlgebraTensorModule.rTensor R _ (g r)) _ + (fun r ↦ AlgebraTensorModule.rTensor R _ (g r)) _ fun r ↦ ?_ + simpa [IsLocalizedModule.map_lTensor] using H r N theorem flat_of_localized_span (h : ∀ r : s, Flat S (LocalizedModule (.powers r.1) M)) : diff --git a/Mathlib/RingTheory/Flat/Stability.lean b/Mathlib/RingTheory/Flat/Stability.lean index 39fec41cfe501..94a41f076248e 100644 --- a/Mathlib/RingTheory/Flat/Stability.lean +++ b/Mathlib/RingTheory/Flat/Stability.lean @@ -40,62 +40,29 @@ section Composition /-! ### Composition Let `R` be a ring, `S` a flat `R`-algebra and `M` a flat `S`-module. To show that `M` is flat -as an `R`-module, we show that the inclusion of an `R`-ideal `I` into `R` tensored on the left with -`M` is injective. For this consider the composition of natural maps +as an `R`-module, we show that the inclusion of an `R`-submodule `N` into an `R`-module `P` +tensored on the left with `M` is injective. For this consider the composition of natural maps -`M ⊗[R] I ≃ M ⊗[S] (S ⊗[R] I) ≃ M ⊗[S] J → M ⊗[S] S ≃ M ≃ M ⊗[R] R` +`M ⊗[R] N ≃ M ⊗[S] (S ⊗[R] N) → M ⊗[S] (S ⊗[R] P) ≃ M ⊗[R] P`; -where `J` is the image of `S ⊗[R] I` under the (by flatness of `S`) injective map -`S ⊗[R] I → S`. One checks that this composition is precisely `I → R` tensored on the left -with `M` and it is injective as a composition of injective maps (note that -`M ⊗[S] J → M ⊗[S] S` is injective because `M` is `S`-flat). +`S ⊗[R] N → S ⊗[R] P` is injective by `R`-flatness of `S`, +so the middle map is injective by `S`-flatness of `M`. -/ variable (R : Type u) (S : Type v) (M : Type w) - [CommRing R] [CommRing S] [Algebra R S] - [AddCommGroup M] [Module R M] [Module S M] [IsScalarTower R S M] - -private noncomputable abbrev auxRightMul (I : Ideal R) : M ⊗[R] I →ₗ[S] M := by - letI i : M ⊗[R] I →ₗ[S] M ⊗[R] R := AlgebraTensorModule.map LinearMap.id I.subtype - letI e' : M ⊗[R] R →ₗ[S] M := AlgebraTensorModule.rid R S M - exact AlgebraTensorModule.rid R S M ∘ₗ i - -private noncomputable abbrev J (I : Ideal R) : Ideal S := LinearMap.range (auxRightMul R S S I) - -private noncomputable abbrev auxIso [Flat R S] {I : Ideal R} : - S ⊗[R] I ≃ₗ[S] J R S I := by - apply LinearEquiv.ofInjective (auxRightMul R S S I) - simp only [LinearMap.coe_comp, LinearEquiv.coe_coe, EquivLike.comp_injective] - exact (Flat.iff_lTensor_injective' R S).mp inferInstance I - -private noncomputable abbrev auxLTensor [Flat R S] (I : Ideal R) : - M ⊗[R] I →ₗ[S] M := by - letI e1 : M ⊗[R] I ≃ₗ[S] M ⊗[S] (S ⊗[R] I) := - (AlgebraTensorModule.cancelBaseChange R S S M I).symm - letI e2 : M ⊗[S] (S ⊗[R] I) ≃ₗ[S] M ⊗[S] (J R S I) := - TensorProduct.congr (LinearEquiv.refl S M) (auxIso R S) - letI e3 : M ⊗[S] (J R S I) →ₗ[S] M ⊗[S] S := lTensor M (J R S I).subtype - letI e4 : M ⊗[S] S →ₗ[S] M := TensorProduct.rid S M - exact e4 ∘ₗ e3 ∘ₗ (e1 ≪≫ₗ e2) - -private lemma auxLTensor_eq [Flat R S] {I : Ideal R} : - (auxLTensor R S M I : M ⊗[R] I →ₗ[R] M) = - TensorProduct.rid R M ∘ₗ lTensor M I.subtype := by - apply TensorProduct.ext' - intro m x - erw [TensorProduct.rid_tmul] - simp + [CommSemiring R] [CommSemiring S] [Algebra R S] + [AddCommMonoid M] [Module R M] [Module S M] [IsScalarTower R S M] +open AlgebraTensorModule in /-- If `S` is a flat `R`-algebra, then any flat `S`-Module is also `R`-flat. -/ theorem trans [Flat R S] [Flat S M] : Flat R M := by - rw [Flat.iff_lTensor_injective'] - intro I - rw [← EquivLike.comp_injective _ (TensorProduct.rid R M)] - haveI h : TensorProduct.rid R M ∘ lTensor M I.subtype = - TensorProduct.rid R M ∘ₗ lTensor M I.subtype := rfl - simp only [h, ← auxLTensor_eq R S M, LinearMap.coe_restrictScalars, LinearMap.coe_comp, - LinearEquiv.coe_coe, EquivLike.comp_injective, EquivLike.injective_comp] - exact (Flat.iff_lTensor_injective' S M).mp inferInstance _ + rw [Flat.iff_lTensor_injectiveₛ] + introv + rw [← coe_lTensor (A := S), ← EquivLike.injective_comp (cancelBaseChange R S S _ _), + ← LinearEquiv.coe_coe, ← LinearMap.coe_comp, lTensor_comp_cancelBaseChange, + LinearMap.coe_comp, LinearEquiv.coe_coe, EquivLike.comp_injective] + iterate 2 apply Flat.lTensor_preserves_injective_linearMap + exact Subtype.val_injective @[deprecated (since := "2024-11-03")] alias comp := trans @@ -105,56 +72,31 @@ section BaseChange /-! ### Base change -Let `R` be a ring, `M` a flat `R`-module and `S` an `R`-algebra. To show that -`S ⊗[R] M` is `S`-flat, we consider for an ideal `I` in `S` the composition of natural maps - -`I ⊗[S] (S ⊗[R] M) ≃ I ⊗[R] M → S ⊗[R] M ≃ S ⊗[S] (S ⊗[R] M)`. - -One checks that this composition is precisely the inclusion `I → S` tensored on the right -with `S ⊗[R] M` and that the former is injective (note that `I ⊗[R] M → S ⊗[R] M` is -injective, since `M` is `R`-flat). +Let `R` be a ring, `M` a flat `R`-module and `S` an `R`-algebra, then +`S ⊗[R] M` is a flat `S`-module. This is a special case of `Module.Flat.instTensorProduct`. -/ variable (R : Type u) (S : Type v) (M : Type w) - [CommRing R] [CommRing S] [Algebra R S] - [AddCommGroup M] [Module R M] - -private noncomputable abbrev auxRTensorBaseChange (I : Ideal S) : - I ⊗[S] (S ⊗[R] M) →ₗ[S] S ⊗[S] (S ⊗[R] M) := - letI e1 : I ⊗[S] (S ⊗[R] M) ≃ₗ[S] I ⊗[R] M := - AlgebraTensorModule.cancelBaseChange R S S I M - letI e2 : S ⊗[S] (S ⊗[R] M) ≃ₗ[S] S ⊗[R] M := - AlgebraTensorModule.cancelBaseChange R S S S M - letI f : I ⊗[R] M →ₗ[S] S ⊗[R] M := AlgebraTensorModule.map I.subtype LinearMap.id - e2.symm.toLinearMap ∘ₗ f ∘ₗ e1.toLinearMap - -private lemma auxRTensorBaseChange_eq (I : Ideal S) : - auxRTensorBaseChange R S M I = rTensor (S ⊗[R] M) I.subtype := by - ext - simp + [CommSemiring R] [CommSemiring S] [Algebra R S] + [AddCommMonoid M] [Module R M] /-- If `M` is a flat `R`-module and `S` is any `R`-algebra, `S ⊗[R] M` is `S`-flat. -/ -instance baseChange [Flat R M] : Flat S (S ⊗[R] M) := by - rw [Flat.iff_rTensor_injective'] - intro I - simp only [← auxRTensorBaseChange_eq, auxRTensorBaseChange, LinearMap.coe_comp, - LinearEquiv.coe_coe, EmbeddingLike.comp_injective, EquivLike.injective_comp] - exact rTensor_preserves_injective_linearMap (I.subtype : I →ₗ[R] S) Subtype.val_injective +instance baseChange [Flat R M] : Flat S (S ⊗[R] M) := inferInstance /-- A base change of a flat module is flat. -/ -theorem isBaseChange [Flat R M] (N : Type t) [AddCommGroup N] [Module R N] [Module S N] +theorem isBaseChange [Flat R M] (N : Type t) [AddCommMonoid N] [Module R N] [Module S N] [IsScalarTower R S N] {f : M →ₗ[R] N} (h : IsBaseChange S f) : Flat S N := - of_linearEquiv S (S ⊗[R] M) N (IsBaseChange.equiv h).symm + of_linearEquiv (IsBaseChange.equiv h).symm end BaseChange section Localization variable {R : Type u} {M Mp : Type*} (Rp : Type v) - [CommRing R] [AddCommGroup M] [Module R M] [CommRing Rp] [Algebra R Rp] - [AddCommGroup Mp] [Module R Mp] [Module Rp Mp] [IsScalarTower R Rp Mp] + [CommSemiring R] [AddCommMonoid M] [Module R M] [CommSemiring Rp] [Algebra R Rp] + [AddCommMonoid Mp] [Module R Mp] [Module Rp Mp] [IsScalarTower R Rp Mp] instance localizedModule [Flat R M] (S : Submonoid R) : Flat (Localization S) (LocalizedModule S M) := by diff --git a/Mathlib/RingTheory/LinearDisjoint.lean b/Mathlib/RingTheory/LinearDisjoint.lean index a297b6514c1c2..b5f37d80dd33a 100644 --- a/Mathlib/RingTheory/LinearDisjoint.lean +++ b/Mathlib/RingTheory/LinearDisjoint.lean @@ -543,7 +543,7 @@ theorem _root_.Algebra.TensorProduct.not_isField_of_transcendental haveI := hfb.isDomain fb.toRingHom haveI := ha.isDomain _ haveI : Module.Flat R (toSubmodule fa.range) := - .of_linearEquiv _ _ _ (AlgEquiv.ofInjective fa hfa).symm.toLinearEquiv + .of_linearEquiv (AlgEquiv.ofInjective fa hfa).symm.toLinearEquiv have key1 : Module.rank R ↥(fa.range ⊓ fb.range) ≤ 1 := (include_range R A B).rank_inf_le_one_of_flat_left let ga : R[X] →ₐ[R] A := aeval a diff --git a/Mathlib/RingTheory/LocalRing/Module.lean b/Mathlib/RingTheory/LocalRing/Module.lean index fdc9bee0bd9c1..d5c618603fb28 100644 --- a/Mathlib/RingTheory/LocalRing/Module.lean +++ b/Mathlib/RingTheory/LocalRing/Module.lean @@ -203,8 +203,6 @@ lemma exists_basis_of_basis_baseChange [Module.FinitePresentation R M] (g₁ := (LinearMap.ker i).subtype) (g₂ := i) (LinearMap.exact_subtype_mkQ 𝔪) (Submodule.mkQ_surjective _) (LinearMap.exact_subtype_ker_map i) hi H ?_ ?_ · apply Module.Flat.lTensor_preserves_injective_linearMap - (N := LinearMap.ker i) (N' := ι →₀ R) - (L := (LinearMap.ker i).subtype) exact Subtype.val_injective · apply hi'.injective rw [LinearMap.baseChange_eq_ltensor] diff --git a/Mathlib/RingTheory/RingHom/Flat.lean b/Mathlib/RingTheory/RingHom/Flat.lean index a18ee675fc72f..feb7b74a492ff 100644 --- a/Mathlib/RingTheory/RingHom/Flat.lean +++ b/Mathlib/RingTheory/RingHom/Flat.lean @@ -30,7 +30,7 @@ variable {R S T : Type*} [CommRing R] [CommRing S] [CommRing T] variable (R) in /-- The identity of a ring is flat. -/ lemma id : RingHom.Flat (RingHom.id R) := - Module.Flat.self R + Module.Flat.self /-- Composition of flat ring homomorphisms is flat. -/ lemma comp {f : R →+* S} {g : S →+* T} (hf : f.Flat) (hg : g.Flat) : Flat (g.comp f) := by @@ -40,7 +40,7 @@ lemma comp {f : R →+* S} {g : S →+* T} (hf : f.Flat) (hg : g.Flat) : Flat (g /-- Bijective ring maps are flat. -/ lemma of_bijective {f : R →+* S} (hf : Function.Bijective f) : Flat f := by algebraize [f] - exact Module.Flat.of_linearEquiv R R S (LinearEquiv.ofBijective (Algebra.linearMap R S) hf).symm + exact Module.Flat.of_linearEquiv (LinearEquiv.ofBijective (Algebra.linearMap R S) hf).symm lemma containsIdentities : ContainsIdentities Flat := id diff --git a/Mathlib/RingTheory/Unramified/Finite.lean b/Mathlib/RingTheory/Unramified/Finite.lean index 7abca42bd9322..18a6c92a8cef3 100644 --- a/Mathlib/RingTheory/Unramified/Finite.lean +++ b/Mathlib/RingTheory/Unramified/Finite.lean @@ -272,7 +272,7 @@ lemma comp_sec : /-- If `S` is an unramified `R`-algebra, then `R`-flat implies `S`-flat. Iversen I.2.7 -/ lemma flat_of_restrictScalars [Module.Flat R M] : Module.Flat S M := - Module.Flat.of_retract _ _ _ _ _ (comp_sec R S M) + Module.Flat.of_retract _ _ (comp_sec R S M) /-- If `S` is an unramified `R`-algebra, then `R`-projective implies `S`-projective. -/ lemma projective_of_restrictScalars [Module.Projective R M] : Module.Projective S M := diff --git a/docs/references.bib b/docs/references.bib index 6500fedc36403..3b10d744e44b5 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -502,6 +502,16 @@ @Article{ borcherds1986vertex doi = {10.1073/pnas.83.10.3068} } +@Misc{ BorgerJun2024, + title = {Facets of module theory over semirings}, + author = {James Borger and Jaiung Jun}, + year = {2024}, + eprint = {2405.18645}, + archiveprefix = {arXiv}, + primaryclass = {math.AG}, + url = {https://arxiv.org/abs/2405.18645} +} + @Book{ bosch-guntzer-remmert, title = {Non-Archimedean Analysis : A Systematic Approach to Rigid Analytic Geometry}, @@ -2371,6 +2381,34 @@ @Book{ Kassel1995 url = {https://doi.org/10.1007/978-1-4612-0783-2} } +@Article{ Katsov2004, + author = {Katsov, Y.}, + title = {On flat semimodules over semirings}, + journal = {Algebra Universalis}, + year = {2004}, + month = {Aug}, + day = {01}, + volume = {51}, + number = {2}, + pages = {287-299}, + issn = {1420-8911}, + doi = {10.1007/s00012-004-1865-1}, + url = {https://doi.org/10.1007/s00012-004-1865-1} +} + +@Article{ KatsovNam2011, + author = {Katsov, Y. and Nam, T. G.}, + title = {Morita equivalence and homological characterization of + semirings}, + journal = {Journal of Algebra and Its Applications}, + volume = {10}, + number = {03}, + pages = {445-473}, + year = {2011}, + doi = {10.1142/S0219498811004793}, + url = {https://doi.org/10.1142/S0219498811004793} +} + @Book{ katz_mazur, author = {Katz, Nicholas M. and Mazur, Barry}, title = {Arithmetic moduli of elliptic curves}, From e5ab45ea78696d399f7632d6fbc9007a1c32579f Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Fri, 17 Jan 2025 10:17:57 +0000 Subject: [PATCH 282/681] feat: definition of linear topologies (#14990) A topology on a module is linear if it is invariant by translation and if there is a basis of neighborhoods consisting of submodules. We are most interested in the case of rings: a topology on a ring is linear if it is linear for both the left- and right-module structures on R over itself. This is equivalent to being invariant by translation and admitting a basis of neighborhoods consisting of two-sided ideals. This will be used in a subsequent PR to evaluate multivariate power series. We will also show that the natural topology on `MvPowerSeries S R` is a linear topology when `S` has a linear topology (e.g the discrete topology). Co-authored-by: @mariainesdff and @ADedecker Co-authored-by: mariainesdff Co-authored-by: ADedecker --- Mathlib.lean | 1 + Mathlib/Topology/Algebra/LinearTopology.lean | 349 +++++++++++++++++++ docs/references.bib | 14 + 3 files changed, 364 insertions(+) create mode 100644 Mathlib/Topology/Algebra/LinearTopology.lean diff --git a/Mathlib.lean b/Mathlib.lean index eaf583adca718..4a69dea48edc2 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5132,6 +5132,7 @@ import Mathlib.Topology.Algebra.InfiniteSum.Nonarchimedean import Mathlib.Topology.Algebra.InfiniteSum.Order import Mathlib.Topology.Algebra.InfiniteSum.Real import Mathlib.Topology.Algebra.InfiniteSum.Ring +import Mathlib.Topology.Algebra.LinearTopology import Mathlib.Topology.Algebra.Localization import Mathlib.Topology.Algebra.Module.Alternating.Basic import Mathlib.Topology.Algebra.Module.Alternating.Topology diff --git a/Mathlib/Topology/Algebra/LinearTopology.lean b/Mathlib/Topology/Algebra/LinearTopology.lean new file mode 100644 index 0000000000000..b89ad49aba859 --- /dev/null +++ b/Mathlib/Topology/Algebra/LinearTopology.lean @@ -0,0 +1,349 @@ +/- +Copyright (c) 2024 Antoine Chambert-Loir, María Inés de Frutos-Fernández. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Antoine Chambert-Loir, María Inés de Frutos-Fernández, Anatole Dedecker +-/ + +import Mathlib.RingTheory.TwoSidedIdeal.Operations +import Mathlib.Topology.Algebra.Ring.Basic +import Mathlib.Topology.Algebra.OpenSubgroup + +/-! # Linear topologies on modules and rings + +Let `M` be a (left) module over a ring `R`. Following +[Stacks: Definition 15.36.1](https://stacks.math.columbia.edu/tag/07E8), we say that a +topology on `M` is *`R`-linear* if it is invariant by translations and admits a basis of +neighborhoods of 0 consisting of (left) `R`-submodules. + +If `M` is an `(R, R')`-bimodule, we show that a topology is both `R`-linear and `R'`-linear +if and only if there exists a basis of neighborhoods of 0 consisting of `(R, R')`-subbimodules. + +In particular, we say that a topology on the ring `R` is *linear* if it is linear if +it is linear when `R` is viewed as an `(R, Rᵐᵒᵖ)`-bimodule. By the previous results, +this means that there exists a basis of neighborhoods of 0 consisting of two-sided ideals, +hence our definition agrees with [N. Bourbaki, *Algebra II*, chapter 4, §2, n° 3][bourbaki1981]. + +## Main definitions and statements + +* `IsLinearTopology R M`: the topology on `M` is `R`-linear, meaning that there exists a basis +of neighborhoods of 0 consisting of `R`-submodules. Note that we don't impose that the topology +is invariant by translation, so you'll often want to add `ContinuousConstVAdd M M` to get +something meaningless. To express that the topology of a ring `R` is linear, use +`[IsLinearTopology R R] [IsLinearTopology Rᵐᵒᵖ R]`. +* `IsLinearTopology.mk_of_hasBasis`: a convenient constructor for `IsLinearTopology`. +See also `IsLinearTopology.mk_of_hasBasis'`. +* The discrete topology on `M` is `R`-linear (declared as an `instance`). +* `IsLinearTopology.hasBasis_subbimodule`: assume that `M` is an `(R, R')`-bimodule, +and that its topology is both `R`-linear and `R'`-linear. Then there exists a basis of neighborhoods +of 0 made of `(R, R')`-subbimodules. Note that this is not trivial, since the bases witnessing +`R`-linearity and `R'`-linearity may have nothing to do with each other +* `IsLinearTopology.tendsto_smul_zero`: assume that the topology on `M` is linear. +For `m : ι → M` such that `m i` tends to 0, `r i • m i` still tends to 0 for any `r : ι → R`. + +* `IsLinearTopology.hasBasis_twoSidedIdeal`: if the ring `R` is linearly topologized, +in the sense that we have both `IsLinearTopology R R` and `IsLinearTopology Rᵐᵒᵖ R`, +then there exists a basis of neighborhoods of 0 consisting of two-sided ideals. +* Conversely, to prove `IsLinearTopology R R` and `IsLinearTopology Rᵐᵒᵖ R` +from a basis of two-sided ideals, use `IsLinearTopology.mk_of_hasBasis'` twice. +* `IsLinearTopology.tendsto_mul_zero_of_left`: assume that the topology on `R` is (right-)linear. +For `f, g : ι → R` such that `f i` tends to `0`, `f i * g i` still tends to `0`. +* `IsLinearTopology.tendsto_mul_zero_of_right`: assume that the topology on `R` is (left-)linear. +For `f, g : ι → R` such that `g i` tends to `0`, `f i * g i` still tends to `0` +* If `R` is a commutative ring and its topology is left-linear, it is automatically +right-linear (declared as a low-priority instance). + +## Notes on the implementation + +* Some statements assume `ContinuousAdd M` where `ContinuousConstVAdd M M` +(invariance by translation) would be enough. In fact, in presence of `IsLinearTopology R M`, +invariance by translation implies that `M` is a topological additive group on which `R` acts +by homeomorphisms. Similarly, `IsLinearTopology R R` and `ContinuousConstVAdd R R` imply that +`R` is a topological ring. All of this will follow from PR#18437. + +Nevertheless, we don't plan on adding those facts as instances: one should use directly +results from PR#18437 to get `TopologicalAddGroup` and `TopologicalRing` instances. + +* The main constructor for `IsLinearTopology`, `IsLinearTopology.mk_of_hasBasis` +is formulated in terms of the subobject classes `AddSubmonoidClass` and `SMulMemClass` +to allow for more complicated types than `Submodule R M` or `Ideal R`. Unfortunately, the scalar +ring in `SMulMemClass` is an `outParam`, which means that Lean only considers one base ring for +a given subobject type. For example, Lean will *never* find `SMulMemClass (TwoSidedIdeal R) R R` +because it prioritizes the (later-defined) instance of `SMulMemClass (TwoSidedIdeal R) Rᵐᵒᵖ R`. + +This makes `IsLinearTopology.mk_of_hasBasis` un-applicable to `TwoSidedIdeal` (and probably other +types), thus we provide `IsLinearTopology.mk_of_hasBasis'` as an alternative not relying on +typeclass inference. +-/ + +open scoped Topology +open Filter + +namespace IsLinearTopology + +section Module + +variable {R R' M : Type*} [Ring R] [Ring R'] [AddCommGroup M] [Module R M] [Module R' M] + [SMulCommClass R R' M] [TopologicalSpace M] + +variable (R M) in +/-- Consider a (left-)module `M` over a ring `R`. A topology on `M` is *`R`-linear* +if the open sub-`R`-modules of `M` form a basis of neighborhoods of zero. + +Typically one would also that the topology is invariant by translation (`ContinuousConstVAdd M M`), +or equivalently that `M` is a topological group, but we do not assume it for the definition. + +In particular, we say that a topology on the ring `R` is *linear* if it is both +`R`-linear and `Rᵐᵒᵖ`-linear for the obvious module structures. To spell this in Lean, +simply use `[IsLinearTopology R R] [IsLinearTopology Rᵐᵒᵖ R]`. -/ +class _root_.IsLinearTopology where + hasBasis_submodule' : (𝓝 (0 : M)).HasBasis + (fun N : Submodule R M ↦ (N : Set M) ∈ 𝓝 0) (fun N : Submodule R M ↦ (N : Set M)) + +variable (R) in +lemma hasBasis_submodule [IsLinearTopology R M] : (𝓝 (0 : M)).HasBasis + (fun N : Submodule R M ↦ (N : Set M) ∈ 𝓝 0) (fun N : Submodule R M ↦ (N : Set M)) := + IsLinearTopology.hasBasis_submodule' + +variable (R) in +lemma hasBasis_open_submodule [ContinuousAdd M] [IsLinearTopology R M] : + (𝓝 (0 : M)).HasBasis + (fun N : Submodule R M ↦ IsOpen (N : Set M)) (fun N : Submodule R M ↦ (N : Set M)) := + hasBasis_submodule R |>.congr + (fun N ↦ ⟨N.toAddSubgroup.isOpen_of_mem_nhds, fun hN ↦ hN.mem_nhds (zero_mem N)⟩) + (fun _ _ ↦ rfl) + +variable (R) in +/-- A variant of `IsLinearTopology.mk_of_hasBasis` asking for an explicit proof that `S` +is a class of submodules instead of relying on (fragile) typeclass inference of `SMulCommClass`. -/ +lemma mk_of_hasBasis' {ι : Sort*} {S : Type*} [SetLike S M] + [AddSubmonoidClass S M] + {p : ι → Prop} {s : ι → S} + (h : (𝓝 0).HasBasis p (fun i ↦ (s i : Set M))) + (hsmul : ∀ s : S, ∀ r : R, ∀ m ∈ s, r • m ∈ s) : + IsLinearTopology R M where + hasBasis_submodule' := h.to_hasBasis + (fun i hi ↦ ⟨ + { carrier := s i, + add_mem' := add_mem, + zero_mem' := zero_mem _, + smul_mem' := hsmul _}, + h.mem_of_mem hi, subset_rfl⟩) + (fun _ ↦ h.mem_iff.mp) + +variable (R) in +/-- To show that `M` is linearly-topologized as an `R`-module, it suffices to show +that it has a basis of neighborhoods of zero made of `R`-submodules. + +Note: for technical reasons detailed in the module docstring, Lean sometimes struggle to find the +right `SMulMemClass` instance. See `IsLinearTopology.mk_of_hasBasis'` for a more +explicit variant. -/ +lemma mk_of_hasBasis {ι : Sort*} {S : Type*} [SetLike S M] + [SMulMemClass S R M] [AddSubmonoidClass S M] + {p : ι → Prop} {s : ι → S} + (h : (𝓝 0).HasBasis p (fun i ↦ (s i : Set M))) : + IsLinearTopology R M := + mk_of_hasBasis' R h fun _ ↦ SMulMemClass.smul_mem + +theorem _root_.isLinearTopology_iff_hasBasis_submodule : + IsLinearTopology R M ↔ (𝓝 0).HasBasis + (fun N : Submodule R M ↦ (N : Set M) ∈ 𝓝 0) (fun N : Submodule R M ↦ (N : Set M)) := + ⟨fun _ ↦ hasBasis_submodule R, fun h ↦ .mk_of_hasBasis R h⟩ + +theorem _root_.isLinearTopology_iff_hasBasis_open_submodule [ContinuousAdd M] : + IsLinearTopology R M ↔ (𝓝 0).HasBasis + (fun N : Submodule R M ↦ IsOpen (N : Set M)) (fun N : Submodule R M ↦ (N : Set M)) := + ⟨fun _ ↦ hasBasis_open_submodule R, fun h ↦ .mk_of_hasBasis R h⟩ + +/-- The discrete topology on any `R`-module is `R`-linear. -/ +instance [DiscreteTopology M] : IsLinearTopology R M := + have : HasBasis (𝓝 0 : Filter M) (fun _ ↦ True) (fun (_ : Unit) ↦ (⊥ : Submodule R M)) := by + rw [nhds_discrete] + exact hasBasis_pure _ + mk_of_hasBasis R this + +variable (R R') in +open Set Pointwise in +/-- Assume that `M` is a module over two rings `R` and `R'`, and that its topology +is linear with respect to each of these rings. Then, it has a basis of neighborhoods of zero +made of sub-`(R, R')`-bimodules. + +The proof is inspired by lemma 9 in [I. Kaplansky, *Topological Rings*](kaplansky_topological_1947). +TODO: Formalize the lemma in its full strength. + +Note: due to the lack of a satisfying theory of sub-bimodules, we use `AddSubgroup`s with +extra conditions. -/ +lemma hasBasis_subbimodule [IsLinearTopology R M] [IsLinearTopology R' M] : + (𝓝 (0 : M)).HasBasis + (fun I : AddSubgroup M ↦ (I : Set M) ∈ 𝓝 0 ∧ + (∀ r : R, ∀ x ∈ I, r • x ∈ I) ∧ (∀ r' : R', ∀ x ∈ I, r' • x ∈ I)) + (fun I : AddSubgroup M ↦ (I : Set M)) := by + -- Start from a neighborhood `V`. It contains some open sub-`R`-module `I`. + refine IsLinearTopology.hasBasis_submodule R |>.to_hasBasis (fun I hI ↦ ?_) + (fun I hI ↦ ⟨{I with smul_mem' := fun r x hx ↦ hI.2.1 r x hx}, hI.1, subset_rfl⟩) + -- `I` itself is a neighborhood of zero, so it contains some open sub-`R'`-module `J`. + rcases (hasBasis_submodule R').mem_iff.mp hI with ⟨J, hJ, J_sub_I⟩ + set uR : Set R := univ -- Convenient to avoid type ascriptions + set uR' : Set R' := univ + have hRR : uR * uR ⊆ uR := subset_univ _ + have hRI : uR • (I : Set M) ⊆ I := smul_subset_iff.mpr fun x _ i hi ↦ I.smul_mem x hi + have hR'J : uR' • (J : Set M) ⊆ J := smul_subset_iff.mpr fun x _ j hj ↦ J.smul_mem x hj + have hRJ : uR • (J : Set M) ⊆ I := subset_trans (smul_subset_smul_left J_sub_I) hRI + -- Note that, on top of the obvious `R • I ⊆ I` and `R' • J ⊆ J`, we have `R • J ⊆ R • I ⊆ I`. + -- Now set `S := J ∪ (R • J)`. We have: + -- 1. `R • S = (R • J) ∪ (R • R • J) ⊆ R • J ⊆ S`. + -- 2. `R' • S = (R' • J) ∪ (R' • R • J) ⊆ J ∪ (R • R' • J) ⊆ J ∪ (R • J) = S`. + -- Hence the subgroup `A` generated by `S` is a sub-`(R, R')`-bimodule, + -- which we claim is open and contained in `I`. + -- Indeed, we have `J ⊆ S ⊆ I`, hence `J ⊆ A ⊆ I`, and `J` is open by hypothesis. + set S : Set M := J ∪ uR • J + have S_sub_I : S ⊆ I := union_subset J_sub_I hRJ + have hRS : uR • S ⊆ S := calc + uR • S = uR • (J : Set M) ∪ (uR * uR) • (J : Set M) := by simp_rw [S, smul_union, mul_smul] + _ ⊆ uR • (J : Set M) ∪ uR • (J : Set M) := by gcongr + _ = uR • (J : Set M) := union_self _ + _ ⊆ S := subset_union_right + have hR'S : uR' • S ⊆ S := calc + uR' • S = uR' • (J : Set M) ∪ uR • uR' • (J : Set M) := by simp_rw [S, smul_union, smul_comm] + _ ⊆ J ∪ uR • J := by gcongr + _ = S := rfl + set A : AddSubgroup M := .closure S + have hRA : ∀ r : R, ∀ i ∈ A, r • i ∈ A := fun r i hi ↦ by + refine AddSubgroup.closure_induction (fun x hx => ?base) ?zero (fun x y _ _ hx hy ↦ ?add) + (fun x _ hx ↦ ?neg) hi + case base => exact AddSubgroup.subset_closure <| hRS <| Set.smul_mem_smul trivial hx + case zero => simp_rw [smul_zero]; exact zero_mem _ + case add => simp_rw [smul_add]; exact add_mem hx hy + case neg => simp_rw [smul_neg]; exact neg_mem hx + have hR'A : ∀ r' : R', ∀ i ∈ A, r' • i ∈ A := fun r' i hi ↦ by + refine AddSubgroup.closure_induction (fun x hx => ?base) ?zero (fun x y _ _ hx hy ↦ ?add) + (fun x _ hx ↦ ?neg) hi + case base => exact AddSubgroup.subset_closure <| hR'S <| Set.smul_mem_smul trivial hx + case zero => simp_rw [smul_zero]; exact zero_mem _ + case add => simp_rw [smul_add]; exact add_mem hx hy + case neg => simp_rw [smul_neg]; exact neg_mem hx + have A_sub_I : (A : Set M) ⊆ I := I.toAddSubgroup.closure_le.mpr S_sub_I + have J_sub_A : (J : Set M) ⊆ A := subset_trans subset_union_left AddSubgroup.subset_closure + exact ⟨A, ⟨mem_of_superset hJ J_sub_A, hRA, hR'A⟩, A_sub_I⟩ + +variable (R R') in +open Set Pointwise in +/-- A variant of `IsLinearTopology.hasBasis_subbimodule` using `IsOpen I` instead of `I ∈ 𝓝 0`. -/ +lemma hasBasis_open_subbimodule [ContinuousAdd M] [IsLinearTopology R M] [IsLinearTopology R' M] : + (𝓝 (0 : M)).HasBasis + (fun I : AddSubgroup M ↦ IsOpen (I : Set M) ∧ + (∀ r : R, ∀ x ∈ I, r • x ∈ I) ∧ (∀ r' : R', ∀ x ∈ I, r' • x ∈ I)) + (fun I : AddSubgroup M ↦ (I : Set M)) := + hasBasis_subbimodule R R' |>.congr + (fun N ↦ and_congr_left' ⟨N.isOpen_of_mem_nhds, fun hN ↦ hN.mem_nhds (zero_mem N)⟩) + (fun _ _ ↦ rfl) + +-- Even though `R` can be recovered from `a`, the nature of this lemma means that `a` will +-- often be left for Lean to infer, so making `R` explicit is useful in practice. +variable (R) in +/-- If `M` is a linearly topologized `R`-module and `i ↦ m i` tends to zero, +then `i ↦ a i • m i` still tends to zero for any family `a : ι → R`. -/ +theorem tendsto_smul_zero [IsLinearTopology R M] {ι : Type*} {f : Filter ι} + (a : ι → R) (m : ι → M) (ha : Tendsto m f (𝓝 0)) : + Tendsto (a • m) f (𝓝 0) := by + rw [hasBasis_submodule R |>.tendsto_right_iff] at ha ⊢ + intro I hI + filter_upwards [ha I hI] with i ai_mem + exact I.smul_mem _ ai_mem + +variable (R) in +/-- If the left and right actions of `R` on `M` coincide, then a topology is `Rᵐᵒᵖ`-linear +if and only if it is `R`-linear. -/ +theorem _root_.IsCentralScalar.isLinearTopology_iff [Module Rᵐᵒᵖ M] [IsCentralScalar R M] : + IsLinearTopology Rᵐᵒᵖ M ↔ IsLinearTopology R M := by + constructor <;> intro H + · exact mk_of_hasBasis' R (IsLinearTopology.hasBasis_submodule Rᵐᵒᵖ) + fun S r m hm ↦ op_smul_eq_smul r m ▸ S.smul_mem _ hm + · exact mk_of_hasBasis' Rᵐᵒᵖ (IsLinearTopology.hasBasis_submodule R) + fun S r m hm ↦ unop_smul_eq_smul r m ▸ S.smul_mem _ hm + +end Module + +section Ring + +variable {R : Type*} [Ring R] [TopologicalSpace R] + +theorem hasBasis_ideal [IsLinearTopology R R] : + (𝓝 0).HasBasis (fun I : Ideal R ↦ (I : Set R) ∈ 𝓝 0) (fun I : Ideal R ↦ (I : Set R)) := + hasBasis_submodule R + +theorem hasBasis_open_ideal [ContinuousAdd R] [IsLinearTopology R R] : + (𝓝 0).HasBasis (fun I : Ideal R ↦ IsOpen (I : Set R)) (fun I : Ideal R ↦ (I : Set R)) := + hasBasis_open_submodule R + +theorem _root_.isLinearTopology_iff_hasBasis_ideal : + IsLinearTopology R R ↔ (𝓝 0).HasBasis + (fun I : Ideal R ↦ (I : Set R) ∈ 𝓝 0) (fun I : Ideal R ↦ (I : Set R)) := + isLinearTopology_iff_hasBasis_submodule + +theorem _root_.isLinearTopology_iff_hasBasis_open_ideal [TopologicalRing R] : + IsLinearTopology R R ↔ (𝓝 0).HasBasis + (fun I : Ideal R ↦ IsOpen (I : Set R)) (fun I : Ideal R ↦ (I : Set R)) := + isLinearTopology_iff_hasBasis_open_submodule + +open Set Pointwise in +/-- If a ring `R` is linearly ordered as a left *and* right module over itself, +then it has a basis of neighborhoods of zero made of *two-sided* ideals. + +This is usually called a *linearly topologized ring*, but we do not add a specific spelling: +you should use `[IsLinearTopology R R] [IsLinearTopology Rᵐᵒᵖ R]` instead. -/ +lemma hasBasis_twoSidedIdeal [IsLinearTopology R R] [IsLinearTopology Rᵐᵒᵖ R] : + (𝓝 (0 : R)).HasBasis (fun I : TwoSidedIdeal R ↦ (I : Set R) ∈ 𝓝 0) + (fun I : TwoSidedIdeal R ↦ (I : Set R)) := + hasBasis_subbimodule R Rᵐᵒᵖ |>.to_hasBasis + (fun I ⟨hI, hRI, hRI'⟩ ↦ ⟨.mk' I (zero_mem _) add_mem neg_mem (hRI _ _) (hRI' _ _), + by simpa using hI, by simp⟩) + (fun I hI ↦ ⟨I.asIdeal.toAddSubgroup, + ⟨hI, I.mul_mem_left, fun r x hx ↦ I.mul_mem_right x (r.unop) hx⟩, subset_rfl⟩) + +lemma hasBasis_open_twoSidedIdeal [ContinuousAdd R] + [IsLinearTopology R R] [IsLinearTopology Rᵐᵒᵖ R] : + (𝓝 (0 : R)).HasBasis + (fun I : TwoSidedIdeal R ↦ IsOpen (I : Set R)) (fun I : TwoSidedIdeal R ↦ (I : Set R)) := + hasBasis_twoSidedIdeal.congr + (fun I ↦ ⟨I.asIdeal.toAddSubgroup.isOpen_of_mem_nhds, fun hI ↦ hI.mem_nhds (zero_mem I)⟩) + (fun _ _ ↦ rfl) + +theorem _root_.isLinearTopology_iff_hasBasis_twoSidedIdeal : + IsLinearTopology R R ∧ IsLinearTopology Rᵐᵒᵖ R ↔ + (𝓝 0).HasBasis + (fun I : TwoSidedIdeal R ↦ (I : Set R) ∈ 𝓝 0) (fun I : TwoSidedIdeal R ↦ (I : Set R)) := + ⟨fun ⟨_, _⟩ ↦ hasBasis_twoSidedIdeal, fun h ↦ + ⟨.mk_of_hasBasis' R h fun I r x hx ↦ I.mul_mem_left r x hx, + .mk_of_hasBasis' Rᵐᵒᵖ h fun I r x hx ↦ I.mul_mem_right x r.unop hx⟩⟩ + +theorem _root_.isLinearTopology_iff_hasBasis_open_twoSidedIdeal [ContinuousAdd R] : + IsLinearTopology R R ∧ IsLinearTopology Rᵐᵒᵖ R ↔ (𝓝 0).HasBasis + (fun I : TwoSidedIdeal R ↦ IsOpen (I : Set R)) (fun I : TwoSidedIdeal R ↦ (I : Set R)) := + ⟨fun ⟨_, _⟩ ↦ hasBasis_open_twoSidedIdeal, fun h ↦ + ⟨.mk_of_hasBasis' R h fun I r x hx ↦ I.mul_mem_left r x hx, + .mk_of_hasBasis' Rᵐᵒᵖ h fun I r x hx ↦ I.mul_mem_right x r.unop hx⟩⟩ + +theorem tendsto_mul_zero_of_left [IsLinearTopology Rᵐᵒᵖ R] {ι : Type*} {f : Filter ι} + (a b : ι → R) (ha : Tendsto a f (𝓝 0)) : + Tendsto (a * b) f (𝓝 0) := + tendsto_smul_zero (R := Rᵐᵒᵖ) _ _ ha + +theorem tendsto_mul_zero_of_right [IsLinearTopology R R] {ι : Type*} {f : Filter ι} + (a b : ι → R) (hb : Tendsto b f (𝓝 0)) : + Tendsto (a * b) f (𝓝 0) := + tendsto_smul_zero (R := R) _ _ hb + +end Ring + +section CommRing + +variable {R M : Type*} [CommRing R] [TopologicalSpace R] + +/-- If `R` is commutative and left-linearly topologized, it is also right-linearly topologized. -/ +instance (priority := 100) [IsLinearTopology R R] : + IsLinearTopology Rᵐᵒᵖ R := by + rwa [IsCentralScalar.isLinearTopology_iff] + +end CommRing + +end IsLinearTopology diff --git a/docs/references.bib b/docs/references.bib index 3b10d744e44b5..9136aacea3cb3 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -2339,6 +2339,20 @@ @Book{ kallenberg2021 url = {https://doi.org/10.1007/978-3-030-61871-1} } +@Article{ kaplansky_topological_1947, + author = {Kaplansky, Irving}, + title = {Topological {Rings}}, + journal = {American Journal of Mathematics}, + volume = {69}, + number = {1}, + year = {1947}, + pages = {153--183}, + publisher = {Johns Hopkins University Press}, + issn = {0002-9327}, + url = {https://www.jstor.org/stable/2371662}, + doi = {10.2307/2371662} +} + @Article{ Karner2004, author = {Karner, Georg}, title = {Continuous monoids and semirings}, From bad84cb577f82ce6827ae09269165e51ccdbfdcb Mon Sep 17 00:00:00 2001 From: Stefan Kebekus Date: Fri, 17 Jan 2025 12:14:21 +0000 Subject: [PATCH 283/681] feat: elementary estimate for Real.log (#20766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generalize the theorem `log_pos_iff'`, weakening the hypothesis `hx : 0 < x` to the (perhaps more natural) hypothesis `hx : 0 ≤ x`. Do the same for `log_nonpos_iff` and depreciate `log_nonpos_iff'`. Fix one trivial typo in a docstring of `Mathlib/NumberTheory/Bertrand.lean`. --- .../Analysis/SpecialFunctions/Integrals.lean | 2 +- .../Analysis/SpecialFunctions/Log/Basic.lean | 17 ++++++++++------- Mathlib/Analysis/SpecialFunctions/Pow/Real.lean | 6 +++--- Mathlib/NumberTheory/Bertrand.lean | 6 +++--- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Mathlib/Analysis/SpecialFunctions/Integrals.lean b/Mathlib/Analysis/SpecialFunctions/Integrals.lean index 955ef029c7bb5..23f0796e7d2ac 100644 --- a/Mathlib/Analysis/SpecialFunctions/Integrals.lean +++ b/Mathlib/Analysis/SpecialFunctions/Integrals.lean @@ -251,7 +251,7 @@ theorem intervalIntegrable_log' : IntervalIntegrable log volume a b := by simpa using (hasDerivAt_id s).sub (hasDerivAt_mul_log hs.ne.symm) · intro s ⟨hs₁, hs₂⟩ norm_num at * - exact (log_nonpos_iff hs₁).mpr hs₂.le + exact (log_nonpos_iff hs₁.le).mpr hs₂.le · -- Show integrability on [1…t] by continuity apply ContinuousOn.intervalIntegrable apply Real.continuousOn_log.mono diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean index 19a01e4add05d..3091ec96f13d0 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean @@ -139,13 +139,15 @@ theorem le_log_iff_exp_le (hy : 0 < y) : x ≤ log y ↔ exp x ≤ y := by rw [ theorem lt_log_iff_exp_lt (hy : 0 < y) : x < log y ↔ exp x < y := by rw [← exp_lt_exp, exp_log hy] -theorem log_pos_iff (hx : 0 < x) : 0 < log x ↔ 1 < x := by +theorem log_pos_iff (hx : 0 ≤ x) : 0 < log x ↔ 1 < x := by + rcases hx.eq_or_lt with (rfl | hx) + · simp [le_refl, zero_le_one] rw [← log_one] exact log_lt_log_iff zero_lt_one hx @[bound] theorem log_pos (hx : 1 < x) : 0 < log x := - (log_pos_iff (lt_trans zero_lt_one hx)).2 hx + (log_pos_iff (lt_trans zero_lt_one hx).le).2 hx theorem log_pos_of_lt_neg_one (hx : x < -1) : 0 < log x := by rw [← neg_neg x, log_neg_eq_log] @@ -172,16 +174,17 @@ theorem log_nonneg_iff (hx : 0 < x) : 0 ≤ log x ↔ 1 ≤ x := by rw [← not_ theorem log_nonneg (hx : 1 ≤ x) : 0 ≤ log x := (log_nonneg_iff (zero_lt_one.trans_le hx)).2 hx -theorem log_nonpos_iff (hx : 0 < x) : log x ≤ 0 ↔ x ≤ 1 := by rw [← not_lt, log_pos_iff hx, not_lt] - -theorem log_nonpos_iff' (hx : 0 ≤ x) : log x ≤ 0 ↔ x ≤ 1 := by +theorem log_nonpos_iff (hx : 0 ≤ x) : log x ≤ 0 ↔ x ≤ 1 := by rcases hx.eq_or_lt with (rfl | hx) · simp [le_refl, zero_le_one] - exact log_nonpos_iff hx + rw [← not_lt, log_pos_iff hx.le, not_lt] + +@[deprecated (since := "2025-01-16")] +alias log_nonpos_iff' := log_nonpos_iff @[bound] theorem log_nonpos (hx : 0 ≤ x) (h'x : x ≤ 1) : log x ≤ 0 := - (log_nonpos_iff' hx).2 h'x + (log_nonpos_iff hx).2 h'x theorem log_natCast_nonneg (n : ℕ) : 0 ≤ log n := by if hn : n = 0 then diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index 147304d54580d..7781b43786177 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -681,7 +681,7 @@ theorem one_le_rpow_of_pos_of_le_one_of_nonpos (hx1 : 0 < x) (hx2 : x ≤ 1) (hz exact (rpow_zero x).symm theorem rpow_lt_one_iff_of_pos (hx : 0 < x) : x ^ y < 1 ↔ 1 < x ∧ y < 0 ∨ x < 1 ∧ 0 < y := by - rw [rpow_def_of_pos hx, exp_lt_one_iff, mul_neg_iff, log_pos_iff hx, log_neg_iff hx] + rw [rpow_def_of_pos hx, exp_lt_one_iff, mul_neg_iff, log_pos_iff hx.le, log_neg_iff hx] theorem rpow_lt_one_iff (hx : 0 ≤ x) : x ^ y < 1 ↔ x = 0 ∧ y ≠ 0 ∨ 1 < x ∧ y < 0 ∨ x < 1 ∧ 0 < y := by @@ -694,7 +694,7 @@ theorem rpow_lt_one_iff' {x y : ℝ} (hx : 0 ≤ x) (hy : 0 < y) : rw [← Real.rpow_lt_rpow_iff hx zero_le_one hy, Real.one_rpow] theorem one_lt_rpow_iff_of_pos (hx : 0 < x) : 1 < x ^ y ↔ 1 < x ∧ 0 < y ∨ x < 1 ∧ y < 0 := by - rw [rpow_def_of_pos hx, one_lt_exp_iff, mul_pos_iff, log_pos_iff hx, log_neg_iff hx] + rw [rpow_def_of_pos hx, one_lt_exp_iff, mul_pos_iff, log_pos_iff hx.le, log_neg_iff hx] theorem one_lt_rpow_iff (hx : 0 ≤ x) : 1 < x ^ y ↔ 1 < x ∧ 0 < y ∨ 0 < x ∧ x < 1 ∧ y < 0 := by rcases hx.eq_or_lt with (rfl | hx) @@ -857,7 +857,7 @@ lemma zpow_lt_of_lt_log {n : ℤ} (hy : 0 < y) (h : log x < n * log y) : x < y ^ rpow_intCast _ _ ▸ rpow_lt_of_lt_log hy h theorem rpow_le_one_iff_of_pos (hx : 0 < x) : x ^ y ≤ 1 ↔ 1 ≤ x ∧ y ≤ 0 ∨ x ≤ 1 ∧ 0 ≤ y := by - rw [rpow_def_of_pos hx, exp_le_one_iff, mul_nonpos_iff, log_nonneg_iff hx, log_nonpos_iff hx] + rw [rpow_def_of_pos hx, exp_le_one_iff, mul_nonpos_iff, log_nonneg_iff hx, log_nonpos_iff hx.le] /-- Bound for `|log x * x ^ t|` in the interval `(0, 1]`, for positive real `t`. -/ theorem abs_log_mul_self_rpow_lt (x t : ℝ) (h1 : 0 < x) (h2 : x ≤ 1) (ht : 0 < t) : diff --git a/Mathlib/NumberTheory/Bertrand.lean b/Mathlib/NumberTheory/Bertrand.lean index 1f789e9d6cc1f..da4716454aa43 100644 --- a/Mathlib/NumberTheory/Bertrand.lean +++ b/Mathlib/NumberTheory/Bertrand.lean @@ -44,7 +44,7 @@ open Real namespace Bertrand -/-- A reified version of the `Bertrand.main_inequality` below. +/-- A refined version of the `Bertrand.main_inequality` below. This is not best possible: it actually holds for 464 ≤ x. -/ theorem real_main_inequality {x : ℝ} (x_large : (512 : ℝ) ≤ x) : @@ -61,7 +61,7 @@ theorem real_main_inequality {x : ℝ} (x_large : (512 : ℝ) ≤ x) : have h5 : 0 < x := lt_of_lt_of_le (by norm_num1) x_large rw [← div_le_one (rpow_pos_of_pos four_pos x), ← div_div_eq_mul_div, ← rpow_sub four_pos, ← mul_div 2 x, mul_div_left_comm, ← mul_one_sub, (by norm_num1 : (1 : ℝ) - 2 / 3 = 1 / 3), - mul_one_div, ← log_nonpos_iff (hf' x h5), ← hf x h5] + mul_one_div, ← log_nonpos_iff (hf' x h5).le, ← hf x h5] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11083): the proof was rewritten, because it was too slow have h : ConcaveOn ℝ (Set.Ioi 0.5) f := by apply ConcaveOn.sub @@ -88,7 +88,7 @@ theorem real_main_inequality {x : ℝ} (x_large : (512 : ℝ) ≤ x) : norm_num1 · have : √(2 * 512) = 32 := (sqrt_eq_iff_mul_self_eq_of_pos (by norm_num1)).mpr (by norm_num1) - rw [hf _ (by norm_num1), log_nonpos_iff (hf' _ (by norm_num1)), this, + rw [hf _ (by norm_num1), log_nonpos_iff (hf' _ (by norm_num1)).le, this, div_le_one (by positivity)] conv in 512 => equals 2 ^ 9 => norm_num1 conv in 2 * 512 => equals 2 ^ 10 => norm_num1 From 19129629cf3f59d049055d9a7abe17e366a10c85 Mon Sep 17 00:00:00 2001 From: grunweg Date: Fri, 17 Jan 2025 12:24:22 +0000 Subject: [PATCH 284/681] chore(yaml_check.py): re-format (#20807) In particular, make the file using four-space indentation. Auto-generated using ruff format (which is virtually equivalent to black), with a line-length set to 100 chars. Both tools are the de facto standard. --- scripts/yaml_check.py | 161 ++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 75 deletions(-) diff --git a/scripts/yaml_check.py b/scripts/yaml_check.py index 5cf9cb9e00a06..c02ca5b036a58 100644 --- a/scripts/yaml_check.py +++ b/scripts/yaml_check.py @@ -9,35 +9,38 @@ of theorems. The order of these files is important.) """ + from typing import Dict, Mapping, Optional, Union, Tuple, List from dataclasses import dataclass import yaml import json import sys -TieredDict = Dict[str, Union[Optional[str], 'TieredDict']] +TieredDict = Dict[str, Union[Optional[str], "TieredDict"]] + def tiered_extract(db: TieredDict) -> List[Tuple[List[str], str]]: - """From a nested dictionary, return a list of (key_path, values) - of the deepest level.""" - out = [] - for name, entry in db.items(): - if isinstance(entry, dict): - for subname, value in tiered_extract(entry): - out.append(([name] + subname, value)) - else: - if entry and '/' not in entry: - out.append(([name], entry)) - return out + """From a nested dictionary, return a list of (key_path, values) + of the deepest level.""" + out = [] + for name, entry in db.items(): + if isinstance(entry, dict): + for subname, value in tiered_extract(entry): + out.append(([name] + subname, value)) + else: + if entry and "/" not in entry: + out.append(([name], entry)) + return out + def flatten_names(data: List[Tuple[List[str], str]]) -> List[Tuple[str, str]]: - return [(' :: '.join(id), v) for id, v in data] + return [(" :: ".join(id), v) for id, v in data] -def print_list(fn: str, pairs: List[Tuple[str, str]]) -> None: - with open(fn, 'w', encoding='utf8') as out: - for (id, val) in pairs: - out.write(f'{id}\n{val.strip()}\n\n') +def print_list(fn: str, pairs: List[Tuple[str, str]]) -> None: + with open(fn, "w", encoding="utf8") as out: + for id, val in pairs: + out.write(f"{id}\n{val.strip()}\n\n") # keep in sync with make_site.py in the leanprover-community.github.io repo @@ -59,6 +62,7 @@ class HundredTheorem: links: Optional[Mapping[str, str]] = None note: Optional[str] = None + # keep in sync with make_site.py in the leanprover-community.github.io repo! # These field names match the names in the data files of the 1000+ theorems project upstream. # See https://github.com/1000-plus/1000-plus.github.io/blob/main/README.md#file-format @@ -87,67 +91,74 @@ class ThousandPlusTheorem: # any additional notes or comments comment: Optional[str] = None + hundred_yaml = sys.argv[1] thousand_yaml = sys.argv[2] overview_yaml = sys.argv[3] undergrad_yaml = sys.argv[4] -with open(hundred_yaml, 'r', encoding='utf8') as hy: - hundred = yaml.safe_load(hy) -with open(thousand_yaml, 'r', encoding='utf8') as hy: - thousand = yaml.safe_load(hy) -with open(overview_yaml, 'r', encoding='utf8') as hy: - overview = yaml.safe_load(hy) -with open(undergrad_yaml, 'r', encoding='utf8') as hy: - undergrad = yaml.safe_load(hy) +with open(hundred_yaml, "r", encoding="utf8") as hy: + hundred = yaml.safe_load(hy) +with open(thousand_yaml, "r", encoding="utf8") as hy: + thousand = yaml.safe_load(hy) +with open(overview_yaml, "r", encoding="utf8") as hy: + overview = yaml.safe_load(hy) +with open(undergrad_yaml, "r", encoding="utf8") as hy: + undergrad = yaml.safe_load(hy) hundred_decls: List[Tuple[str, str]] = [] errors = 0 for index, entry in hundred.items(): - # Check that the YAML fits the dataclass used in the website. - try: - _thm = HundredTheorem(index, **entry) - except TypeError as e: - print(f"error: entry for theorem {index} is invalid: {e}") - errors += 1 - # Also verify that the |decl| and |decls| fields are not *both* provided. - if _thm.decl and _thm.decls: - print(f"warning: entry for theorem {index} has both a decl and a decls field; " - "please only provide one of these", file=sys.stderr) - errors += 1 - - title = entry['title'] - if 'decl' in entry: - hundred_decls.append((f'{index} {title}', entry['decl'])) - elif 'decls' in entry: - if not isinstance(entry['decls'], list): - print(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") - errors += 1 - hundred_decls = hundred_decls + [(f'{index} {title}', d) for d in entry['decls']] + # Check that the YAML fits the dataclass used in the website. + try: + _thm = HundredTheorem(index, **entry) + except TypeError as e: + print(f"error: entry for theorem {index} is invalid: {e}") + errors += 1 + # Also verify that the |decl| and |decls| fields are not *both* provided. + if _thm.decl and _thm.decls: + print( + f"warning: entry for theorem {index} has both a decl and a decls field; " + "please only provide one of these", + file=sys.stderr, + ) + errors += 1 + + title = entry["title"] + if "decl" in entry: + hundred_decls.append((f"{index} {title}", entry["decl"])) + elif "decls" in entry: + if not isinstance(entry["decls"], list): + print(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") + errors += 1 + hundred_decls = hundred_decls + [(f"{index} {title}", d) for d in entry["decls"]] thousand_decls: List[Tuple[str, str]] = [] for index, entry in thousand.items(): - # Check that the YAML fits the dataclass used in the website. - try: - _thm = ThousandPlusTheorem(index, **entry) - except TypeError as e: - print(f"error: entry for theorem {index} is invalid: {e}") - errors += 1 - # Also verify that the |decl| and |decls| fields are not *both* provided. - if _thm.decl and _thm.decls: - print(f"warning: entry for theorem {index} has both a decl and a decls field; " - "please only provide one of these", file=sys.stderr) - errors += 1 - - title = entry['title'] - if 'decl' in entry: - thousand_decls.append((f'{index} {title}', entry['decl'])) - elif 'decls' in entry: - if not isinstance(entry['decls'], list): - print(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") - errors += 1 - thousand_decls = thousand_decls + [(f'{index} {title}', d) for d in entry['decls']] + # Check that the YAML fits the dataclass used in the website. + try: + _thm = ThousandPlusTheorem(index, **entry) + except TypeError as e: + print(f"error: entry for theorem {index} is invalid: {e}") + errors += 1 + # Also verify that the |decl| and |decls| fields are not *both* provided. + if _thm.decl and _thm.decls: + print( + f"warning: entry for theorem {index} has both a decl and a decls field; " + "please only provide one of these", + file=sys.stderr, + ) + errors += 1 + + title = entry["title"] + if "decl" in entry: + thousand_decls.append((f"{index} {title}", entry["decl"])) + elif "decls" in entry: + if not isinstance(entry["decls"], list): + print(f"For key {index} ({title}): did you mean `decl` instead of `decls`?") + errors += 1 + thousand_decls = thousand_decls + [(f"{index} {title}", d) for d in entry["decls"]] overview_decls = tiered_extract(overview) assert all(len(n) == 3 for n, _ in overview_decls) @@ -157,15 +168,15 @@ class ThousandPlusTheorem: assert all(len(n) >= 3 for n, _ in undergrad_decls) undergrad_decls = flatten_names(undergrad_decls) -with open('100.json', 'w', encoding='utf8') as f: - json.dump(hundred_decls, f) -with open('1000.json', 'w', encoding='utf8') as f: - json.dump(thousand_decls, f) -with open('overview.json', 'w', encoding='utf8') as f: - json.dump(overview_decls, f) -with open('undergrad.json', 'w', encoding='utf8') as f: - json.dump(undergrad_decls, f) +with open("100.json", "w", encoding="utf8") as f: + json.dump(hundred_decls, f) +with open("1000.json", "w", encoding="utf8") as f: + json.dump(thousand_decls, f) +with open("overview.json", "w", encoding="utf8") as f: + json.dump(overview_decls, f) +with open("undergrad.json", "w", encoding="utf8") as f: + json.dump(undergrad_decls, f) if errors: - # Return an error code of at most 125 so this return value can be used further in shell scripts. - sys.exit(min(errors, 125)) + # Return an error code of at most 125 so this return value can be used further in shell scripts. + sys.exit(min(errors, 125)) From 3830035266276d11cb8b1b72447c7f84874cfa63 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Fri, 17 Jan 2025 12:40:56 +0000 Subject: [PATCH 285/681] =?UTF-8?q?feat:=20`CommSemiring=20(NonemptyInterv?= =?UTF-8?q?al=20=E2=84=9A=E2=89=A50)`=20(#20783)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For rings with negation we need a total rewrite of `Mul`, which is a problem for a later PR. Co-authored-by: Eric Wieser --- Mathlib/Algebra/Order/Interval/Basic.lean | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Mathlib/Algebra/Order/Interval/Basic.lean b/Mathlib/Algebra/Order/Interval/Basic.lean index 7b3bdacd679da..3e9133cdbd6a2 100644 --- a/Mathlib/Algebra/Order/Interval/Basic.lean +++ b/Mathlib/Algebra/Order/Interval/Basic.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Group.Pointwise.Set.Basic +import Mathlib.Algebra.Ring.Prod import Mathlib.Algebra.Order.BigOperators.Group.Finset +import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Order.Interval.Basic import Mathlib.Tactic.Positivity.Core @@ -263,6 +265,40 @@ theorem bot_pow : ∀ {n : ℕ}, n ≠ 0 → (⊥ : Interval α) ^ n = ⊥ end Interval +/-! +### Semiring structure + +When `α` is a canonically `OrderedCommSemiring`, the previous `+` and `*` on `NonemptyInterval α` +form a `CommSemiring`. +-/ + +section NatCast +variable [Preorder α] [NatCast α] + +namespace NonemptyInterval + +instance : NatCast (NonemptyInterval α) where + natCast n := pure <| Nat.cast n + +theorem fst_natCast (n : ℕ) : (n : NonemptyInterval α).fst = n := rfl + +theorem snd_natCast (n : ℕ) : (n : NonemptyInterval α).snd = n := rfl + +@[simp] +theorem pure_natCast (n : ℕ) : pure (n : α) = n := rfl + +end NonemptyInterval + +end NatCast + +namespace NonemptyInterval + +instance [OrderedCommSemiring α] [CanonicallyOrderedAdd α] : CommSemiring (NonemptyInterval α) := + NonemptyInterval.toProd_injective.commSemiring _ + toProd_zero toProd_one toProd_add toProd_mul (swap toProd_nsmul) toProd_pow (fun _ => rfl) + +end NonemptyInterval + /-! ### Subtraction From 4335474d114588d0c07d2799dd9a4ac1e013cbe8 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Fri, 17 Jan 2025 14:00:28 +0000 Subject: [PATCH 286/681] chore(CategoryTheory): rename `ConcreteCategory` to `HasForget` (#20809) This is the first step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This commit was generated by find-and-replacing `ConcreteCategory` and `concreteCategory` with `HasForget` and `hasForget` respectively, making sure not to touch imports. I did not look too closely at the changes, since we should be going over everything during the redesign anyway. `ConcreteCategory` is now temporarily an alias for `HasForget`, with a deprecation warning. The `ConcreteCategory` namespace itself was not renamed, since we'll eventually be redoing those results for the new `ConcreteCategory` class. --- .../Algebra/Category/AlgebraCat/Basic.lean | 2 +- .../Algebra/Category/BialgebraCat/Basic.lean | 2 +- Mathlib/Algebra/Category/BoolRing.lean | 2 +- .../Algebra/Category/CoalgebraCat/Basic.lean | 2 +- .../Algebra/Category/FGModuleCat/Basic.lean | 4 +- Mathlib/Algebra/Category/Grp/Basic.lean | 4 +- Mathlib/Algebra/Category/Grp/FiniteGrp.lean | 2 +- Mathlib/Algebra/Category/GrpWithZero.lean | 2 +- .../Category/HopfAlgebraCat/Basic.lean | 2 +- Mathlib/Algebra/Category/ModuleCat/Basic.lean | 2 +- .../Category/ModuleCat/Presheaf/Sheafify.lean | 2 +- .../ModuleCat/Sheaf/ChangeOfRings.lean | 2 +- Mathlib/Algebra/Category/MonCat/Basic.lean | 10 +-- Mathlib/Algebra/Category/Ring/Basic.lean | 12 +-- Mathlib/Algebra/Category/Semigrp/Basic.lean | 20 ++--- .../Algebra/Homology/ConcreteCategory.lean | 4 +- Mathlib/Algebra/Homology/ImageToKernel.lean | 4 +- .../ShortComplex/ConcreteCategory.lean | 8 +- .../Homology/ShortComplex/ModuleCat.lean | 2 +- Mathlib/AlgebraicGeometry/OpenImmersion.lean | 2 +- .../ProjectiveSpectrum/StructureSheaf.lean | 2 +- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 2 +- .../AlgebraicTopology/SimplexCategory.lean | 2 +- .../AlgebraicTopology/TopologicalSimplex.lean | 4 +- .../Analysis/Normed/Group/SemiNormedGrp.lean | 8 +- Mathlib/CategoryTheory/Action/Basic.lean | 8 +- Mathlib/CategoryTheory/Action/Concrete.lean | 2 +- Mathlib/CategoryTheory/Action/Continuous.lean | 10 +-- Mathlib/CategoryTheory/Action/Limits.lean | 6 +- .../CategoryTheory/Category/Bipointed.lean | 2 +- Mathlib/CategoryTheory/Category/Pointed.lean | 2 +- Mathlib/CategoryTheory/Category/TwoP.lean | 4 +- .../ConcreteCategory/Basic.lean | 86 +++++++++++-------- .../ConcreteCategory/Bundled.lean | 4 +- .../ConcreteCategory/BundledHom.lean | 4 +- .../ConcreteCategory/EpiMono.lean | 12 +-- .../ConcreteCategory/ReflectsIso.lean | 4 +- .../CategoryTheory/DifferentialObject.lean | 4 +- Mathlib/CategoryTheory/FintypeCat.lean | 2 +- Mathlib/CategoryTheory/Functor/Flat.lean | 2 +- Mathlib/CategoryTheory/GradedObject.lean | 4 +- .../Limits/ConcreteCategory/Basic.lean | 12 +-- .../WithAlgebraicStructures.lean | 4 +- .../FilteredColimitCommutesFiniteLimit.lean | 2 +- Mathlib/CategoryTheory/Limits/MonoCoprod.lean | 2 +- .../Limits/Shapes/ConcreteCategory.lean | 22 ++--- .../MorphismProperty/Concrete.lean | 4 +- Mathlib/CategoryTheory/Sites/Adjunction.lean | 4 +- .../Sites/Coherent/LocallySurjective.lean | 4 +- .../Sites/CompatibleSheafification.lean | 2 +- .../Sites/ConcreteSheafification.lean | 14 +-- Mathlib/CategoryTheory/Sites/EpiMono.lean | 2 +- Mathlib/CategoryTheory/Sites/Equivalence.lean | 2 +- Mathlib/CategoryTheory/Sites/LeftExact.lean | 4 +- .../Sites/LocallyBijective.lean | 4 +- .../Sites/LocallyInjective.lean | 6 +- .../Sites/LocallySurjective.lean | 6 +- .../Sites/PreservesLocallyBijective.lean | 2 +- .../Sites/PreservesSheafification.lean | 4 +- Mathlib/CategoryTheory/Sites/Pullback.lean | 2 +- Mathlib/CategoryTheory/Sites/Sheaf.lean | 4 +- Mathlib/CategoryTheory/Sites/Whiskering.lean | 4 +- .../Condensed/Discrete/Characterization.lean | 2 +- Mathlib/Condensed/Discrete/Colimit.lean | 2 +- .../Condensed/Discrete/LocallyConstant.lean | 2 +- Mathlib/Condensed/Discrete/Module.lean | 2 +- Mathlib/Condensed/Epi.lean | 4 +- Mathlib/Condensed/Explicit.lean | 6 +- Mathlib/Condensed/Light/Epi.lean | 6 +- Mathlib/Condensed/Light/Explicit.lean | 2 +- Mathlib/Condensed/Light/TopCatAdjunction.lean | 2 +- Mathlib/Condensed/TopCatAdjunction.lean | 2 +- Mathlib/Condensed/TopComparison.lean | 2 +- Mathlib/Geometry/RingedSpace/Basic.lean | 8 +- .../Geometry/RingedSpace/OpenImmersion.lean | 2 +- .../Geometry/RingedSpace/SheafedSpace.lean | 8 +- .../QuadraticForm/QuadraticModuleCat.lean | 2 +- Mathlib/MeasureTheory/Category/MeasCat.lean | 6 +- Mathlib/Order/Category/BddDistLat.lean | 4 +- Mathlib/Order/Category/BddLat.lean | 2 +- Mathlib/Order/Category/BddOrd.lean | 2 +- Mathlib/Order/Category/BoolAlg.lean | 4 +- Mathlib/Order/Category/CompleteLat.lean | 2 +- Mathlib/Order/Category/DistLat.lean | 4 +- Mathlib/Order/Category/FinBddDistLat.lean | 4 +- Mathlib/Order/Category/FinBoolAlg.lean | 4 +- Mathlib/Order/Category/FinPartOrd.lean | 4 +- Mathlib/Order/Category/Frm.lean | 4 +- Mathlib/Order/Category/HeytAlg.lean | 2 +- Mathlib/Order/Category/Lat.lean | 4 +- Mathlib/Order/Category/LinOrd.lean | 4 +- Mathlib/Order/Category/NonemptyFinLinOrd.lean | 4 +- .../Category/OmegaCompletePartialOrder.lean | 6 +- Mathlib/Order/Category/PartOrd.lean | 4 +- Mathlib/Order/Category/Preord.lean | 4 +- Mathlib/Order/Category/Semilat.lean | 4 +- Mathlib/RepresentationTheory/FDRep.lean | 4 +- Mathlib/RepresentationTheory/Rep.lean | 2 +- .../Tactic/CategoryTheory/Elementwise.lean | 32 +++---- Mathlib/Tactic/Linter/GlobalAttributeIn.lean | 4 +- .../Algebra/Category/ProfiniteGrp/Basic.lean | 2 +- Mathlib/Topology/Category/Born.lean | 4 +- Mathlib/Topology/Category/CompHaus/Basic.lean | 2 +- .../Category/CompHaus/EffectiveEpi.lean | 2 +- .../Category/CompHaus/Projective.lean | 2 +- .../Topology/Category/CompHausLike/Basic.lean | 6 +- .../Category/CompHausLike/EffectiveEpi.lean | 2 +- .../Category/CompHausLike/Limits.lean | 2 +- .../Topology/Category/CompactlyGenerated.lean | 6 +- Mathlib/Topology/Category/Compactum.lean | 4 +- Mathlib/Topology/Category/DeltaGenerated.lean | 4 +- Mathlib/Topology/Category/FinTopCat.lean | 4 +- .../Category/LightProfinite/AsLimit.lean | 2 +- .../Category/LightProfinite/Basic.lean | 4 +- .../Category/LightProfinite/EffectiveEpi.lean | 2 +- .../Category/LightProfinite/Extend.lean | 2 +- .../Topology/Category/Profinite/Basic.lean | 2 +- .../Category/Profinite/CofilteredLimit.lean | 2 +- .../Category/Profinite/EffectiveEpi.lean | 2 +- .../Topology/Category/Profinite/Extend.lean | 2 +- .../Category/Profinite/Projective.lean | 2 +- Mathlib/Topology/Category/Sequential.lean | 6 +- Mathlib/Topology/Category/Stonean/Basic.lean | 2 +- .../Category/Stonean/EffectiveEpi.lean | 2 +- Mathlib/Topology/Category/Stonean/Limits.lean | 2 +- Mathlib/Topology/Category/TopCat/Basic.lean | 8 +- .../Category/TopCat/Limits/Pullbacks.lean | 2 +- Mathlib/Topology/Category/TopCommRingCat.lean | 2 +- Mathlib/Topology/Category/UniformSpace.lean | 10 +-- Mathlib/Topology/Order/Category/AlexDisc.lean | 4 +- .../Order/Category/FrameAdjunction.lean | 2 +- Mathlib/Topology/Sheaves/CommRingCat.lean | 4 +- Mathlib/Topology/Sheaves/Functors.lean | 2 +- .../Topology/Sheaves/LocallySurjective.lean | 4 +- Mathlib/Topology/Sheaves/Presheaf.lean | 12 +-- .../Sheaves/SheafCondition/UniqueGluing.lean | 12 +-- Mathlib/Topology/Sheaves/Stalks.lean | 24 +++--- MathlibTest/CategoryTheory/Elementwise.lean | 28 +++--- MathlibTest/slow_simp.lean | 2 +- 139 files changed, 369 insertions(+), 359 deletions(-) diff --git a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean index 1f4d18462f038..87dd242280419 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean @@ -127,7 +127,7 @@ lemma hom_inv_apply {A B : AlgebraCat.{v} R} (e : A ≅ B) (x : B) : e.hom (e.in instance : Inhabited (AlgebraCat R) := ⟨of R R⟩ -instance : ConcreteCategory.{v} (AlgebraCat.{v} R) where +instance : HasForget.{v} (AlgebraCat.{v} R) where forget := { obj := fun R => R map := fun f => f.hom } diff --git a/Mathlib/Algebra/Category/BialgebraCat/Basic.lean b/Mathlib/Algebra/Category/BialgebraCat/Basic.lean index 3dcc1b3f1497e..8b85af2ed6e36 100644 --- a/Mathlib/Algebra/Category/BialgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/BialgebraCat/Basic.lean @@ -95,7 +95,7 @@ abbrev ofHom {X Y : Type v} [Ring X] [Ring Y] Hom.toBialgHom (𝟙 M) = BialgHom.id _ _ := rfl -instance concreteCategory : ConcreteCategory.{v} (BialgebraCat.{v} R) where +instance hasForget : HasForget.{v} (BialgebraCat.{v} R) where forget := { obj := fun M => M map := fun f => f.toBialgHom } diff --git a/Mathlib/Algebra/Category/BoolRing.lean b/Mathlib/Algebra/Category/BoolRing.lean index 0a8e91f15a4fa..b0203ab1b4600 100644 --- a/Mathlib/Algebra/Category/BoolRing.lean +++ b/Mathlib/Algebra/Category/BoolRing.lean @@ -71,7 +71,7 @@ lemma hom_ext {R S : BoolRing} {f g : R ⟶ S} (hf : f.hom = g.hom) : f = g := abbrev ofHom {R S : Type u} [BooleanRing R] [BooleanRing S] (f : R →+* S) : of R ⟶ of S := ⟨f⟩ -instance : ConcreteCategory BoolRing where +instance : HasForget BoolRing where forget := { obj := fun R ↦ R map := fun f ↦ f.hom } diff --git a/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean b/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean index 362312b348546..f880f10b534ae 100644 --- a/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean @@ -96,7 +96,7 @@ abbrev ofHom {X Y : Type v} [AddCommGroup X] [Module R X] [AddCommGroup Y] [Modu Hom.toCoalgHom (𝟙 M) = CoalgHom.id _ _ := rfl -instance concreteCategory : ConcreteCategory.{v} (CoalgebraCat.{v} R) where +instance hasForget : HasForget.{v} (CoalgebraCat.{v} R) where forget := { obj := fun M => M map := fun f => f.toCoalgHom } diff --git a/Mathlib/Algebra/Category/FGModuleCat/Basic.lean b/Mathlib/Algebra/Category/FGModuleCat/Basic.lean index 07f1ca89ad5e6..227bef9faa458 100644 --- a/Mathlib/Algebra/Category/FGModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/FGModuleCat/Basic.lean @@ -46,7 +46,7 @@ def FGModuleCat := FullSubcategory fun V : ModuleCat.{u} R => Module.Finite R V -- Porting note: still no derive handler via `dsimp`. -- see https://github.com/leanprover-community/mathlib4/issues/5020 --- deriving LargeCategory, ConcreteCategory,Preadditive +-- deriving LargeCategory, HasForget,Preadditive variable {R} @@ -72,7 +72,7 @@ instance : LargeCategory (FGModuleCat R) := by dsimp [FGModuleCat] infer_instance -instance : ConcreteCategory (FGModuleCat R) := by +instance : HasForget (FGModuleCat R) := by dsimp [FGModuleCat] infer_instance diff --git a/Mathlib/Algebra/Category/Grp/Basic.lean b/Mathlib/Algebra/Category/Grp/Basic.lean index 7be93501da135..e84967eb2a42b 100644 --- a/Mathlib/Algebra/Category/Grp/Basic.lean +++ b/Mathlib/Algebra/Category/Grp/Basic.lean @@ -42,7 +42,7 @@ deriving instance LargeCategory for Grp attribute [to_additive] instGrpLargeCategory @[to_additive] -instance concreteCategory : ConcreteCategory Grp := by +instance hasForget : HasForget Grp := by dsimp only [Grp] infer_instance @@ -171,7 +171,7 @@ deriving instance LargeCategory for CommGrp attribute [to_additive] instCommGrpLargeCategory @[to_additive] -instance concreteCategory : ConcreteCategory CommGrp := by +instance hasForget : HasForget CommGrp := by dsimp only [CommGrp] infer_instance diff --git a/Mathlib/Algebra/Category/Grp/FiniteGrp.lean b/Mathlib/Algebra/Category/Grp/FiniteGrp.lean index ac01e3ac8ce3c..bd6b281b3d46d 100644 --- a/Mathlib/Algebra/Category/Grp/FiniteGrp.lean +++ b/Mathlib/Algebra/Category/Grp/FiniteGrp.lean @@ -44,7 +44,7 @@ instance : CoeSort FiniteGrp.{u} (Type u) where instance : Category FiniteGrp := InducedCategory.category FiniteGrp.toGrp @[to_additive] -instance : ConcreteCategory FiniteGrp := InducedCategory.concreteCategory FiniteGrp.toGrp +instance : HasForget FiniteGrp := InducedCategory.hasForget FiniteGrp.toGrp @[to_additive] instance (G : FiniteGrp) : Group G := inferInstanceAs <| Group G.toGrp diff --git a/Mathlib/Algebra/Category/GrpWithZero.lean b/Mathlib/Algebra/Category/GrpWithZero.lean index 4ab7a118180e7..217c743141244 100644 --- a/Mathlib/Algebra/Category/GrpWithZero.lean +++ b/Mathlib/Algebra/Category/GrpWithZero.lean @@ -56,7 +56,7 @@ lemma coe_id {X : GrpWithZero} : (𝟙 X : X → X) = id := rfl lemma coe_comp {X Y Z : GrpWithZero} {f : X ⟶ Y} {g : Y ⟶ Z} : (f ≫ g : X → Z) = g ∘ f := rfl -instance groupWithZeroConcreteCategory : ConcreteCategory GrpWithZero where +instance groupWithZeroHasForget : HasForget GrpWithZero where forget := { obj := fun G => G map := fun f => f.toFun } diff --git a/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean b/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean index c5b834197885e..81952cef5ef08 100644 --- a/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean @@ -94,7 +94,7 @@ abbrev ofHom {X Y : Type v} [Ring X] [Ring Y] Hom.toBialgHom (𝟙 M) = BialgHom.id _ _ := rfl -instance concreteCategory : ConcreteCategory.{v} (HopfAlgebraCat.{v} R) where +instance hasForget : HasForget.{v} (HopfAlgebraCat.{v} R) where forget := { obj := fun M => M map := fun f => f.toBialgHom } diff --git a/Mathlib/Algebra/Category/ModuleCat/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Basic.lean index 9d0fdd30373c1..4c63c2f7e9aea 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Basic.lean @@ -188,7 +188,7 @@ end instance : Inhabited (ModuleCat R) := ⟨of R R⟩ -instance moduleConcreteCategory : ConcreteCategory.{v} (ModuleCat.{v} R) where +instance moduleHasForget : HasForget.{v} (ModuleCat.{v} R) where forget := { obj := fun R => R map := fun f => f.hom } diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean index 8c9688b454ef9..4a8d0a5b70086 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean @@ -32,7 +32,7 @@ namespace CategoryTheory namespace Presieve.FamilyOfElements -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike section smul diff --git a/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean index c715193fc39b7..2b6696f1db2d2 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean @@ -53,7 +53,7 @@ noncomputable def restrictHomEquivOfIsLocallySurjective toFun f := (restrictScalars α).map f invFun g := homMk ((toPresheaf R).map g) (fun X r' m ↦ by apply hM₂.isSeparated _ _ (Presheaf.imageSieve_mem J α r') - -- Type-ascript `hr` so it uses `RingCat.Hom.hom` instead of `ConcreteCategory.instFunLike` + -- Type-ascript `hr` so it uses `RingCat.Hom.hom` instead of `HasForget.instFunLike` rintro Y p ⟨r : R.obj _, (hr : α.app (Opposite.op Y) r = R'.map p.op r')⟩ have hg : ∀ (z : M₁.obj X), g.app _ (M₁.map p.op z) = M₂.map p.op (g.app X z) := fun z ↦ congr_fun ((forget _).congr_map (g.naturality p.op)) z diff --git a/Mathlib/Algebra/Category/MonCat/Basic.lean b/Mathlib/Algebra/Category/MonCat/Basic.lean index c6438233e316f..d4f9913d7d062 100644 --- a/Mathlib/Algebra/Category/MonCat/Basic.lean +++ b/Mathlib/Algebra/Category/MonCat/Basic.lean @@ -3,9 +3,9 @@ Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ -import Mathlib.CategoryTheory.ConcreteCategory.BundledHom import Mathlib.Algebra.PUnitInstances.Algebra import Mathlib.Algebra.Group.ULift +import Mathlib.CategoryTheory.ConcreteCategory.BundledHom import Mathlib.CategoryTheory.Functor.ReflectsIso import Mathlib.Algebra.Ring.Action.Group @@ -55,8 +55,8 @@ attribute [to_additive instAddMonCatLargeCategory] instMonCatLargeCategory -- Porting note: https://github.com/leanprover-community/mathlib4/issues/5020 @[to_additive] -instance concreteCategory : ConcreteCategory MonCat := - BundledHom.concreteCategory _ +instance hasForget : HasForget MonCat := + BundledHom.hasForget _ @[to_additive] instance : CoeSort MonCat Type* where @@ -170,7 +170,7 @@ attribute [to_additive instAddCommMonCatLargeCategory] instCommMonCatLargeCatego -- Porting note: https://github.com/leanprover-community/mathlib4/issues/5020 @[to_additive] -instance concreteCategory : ConcreteCategory CommMonCat := by +instance hasForget : HasForget CommMonCat := by dsimp only [CommMonCat] infer_instance @@ -346,7 +346,7 @@ instance CommMonCat.forget_reflects_isos : (forget CommMonCat.{u}).ReflectsIsomo -- Porting note: this was added in order to ensure that `forget₂ CommMonCat MonCat` -- automatically reflects isomorphisms --- we could have used `CategoryTheory.ConcreteCategory.ReflectsIso` alternatively +-- we could have used `CategoryTheory.HasForget.ReflectsIso` alternatively @[to_additive] instance CommMonCat.forget₂_full : (forget₂ CommMonCat MonCat).Full where map_surjective f := ⟨f, rfl⟩ diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index c03ba09884376..6c70b9d5fdd78 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -120,7 +120,7 @@ lemma hom_inv_apply {R S : SemiRingCat} (e : R ≅ S) (s : S) : e.hom (e.inv s) instance : Inhabited SemiRingCat := ⟨of PUnit⟩ -instance : ConcreteCategory.{u} SemiRingCat where +instance : HasForget.{u} SemiRingCat where forget := { obj := fun R => R map := fun f => f.hom } @@ -264,7 +264,7 @@ lemma hom_inv_apply {R S : RingCat} (e : R ≅ S) (s : S) : e.hom (e.inv s) = s instance : Inhabited RingCat := ⟨of PUnit⟩ -instance : ConcreteCategory.{u} RingCat where +instance : HasForget.{u} RingCat where forget := { obj := fun R => R map := fun f => f.hom } @@ -413,7 +413,7 @@ lemma hom_inv_apply {R S : CommSemiRingCat} (e : R ≅ S) (s : S) : e.hom (e.inv instance : Inhabited CommSemiRingCat := ⟨of PUnit⟩ -instance : ConcreteCategory.{u} CommSemiRingCat where +instance : HasForget.{u} CommSemiRingCat where forget := { obj := fun R => R map := fun f => f.hom } @@ -560,7 +560,7 @@ lemma hom_inv_apply {R S : CommRingCat} (e : R ≅ S) (s : S) : e.hom (e.inv s) instance : Inhabited CommRingCat := ⟨of PUnit⟩ -instance : ConcreteCategory.{u} CommRingCat where +instance : HasForget.{u} CommRingCat where forget := { obj := fun R => R map := fun f => f.hom } @@ -669,10 +669,10 @@ abbrev CommRingCatMax.{u1, u2} := CommRingCat.{max u1 u2} lemma RingCat.forget_map_apply {R S : RingCat} (f : R ⟶ S) (x : (CategoryTheory.forget RingCat).obj R) : - @DFunLike.coe _ _ _ ConcreteCategory.instFunLike f x = f x := + @DFunLike.coe _ _ _ HasForget.instFunLike f x = f x := rfl lemma CommRingCat.forget_map_apply {R S : CommRingCat} (f : R ⟶ S) (x : (CategoryTheory.forget CommRingCat).obj R) : - @DFunLike.coe _ _ _ ConcreteCategory.instFunLike f x = f x := + @DFunLike.coe _ _ _ HasForget.instFunLike f x = f x := rfl diff --git a/Mathlib/Algebra/Category/Semigrp/Basic.lean b/Mathlib/Algebra/Category/Semigrp/Basic.lean index ebcbd7a5584d3..f020632a9ccb5 100644 --- a/Mathlib/Algebra/Category/Semigrp/Basic.lean +++ b/Mathlib/Algebra/Category/Semigrp/Basic.lean @@ -46,13 +46,13 @@ instance bundledHom : BundledHom @MulHom := ⟨@MulHom.toFun, @MulHom.id, @MulHom.comp, by intros; apply @DFunLike.coe_injective, by aesop_cat, by simp⟩ --- Porting note: deriving failed for `ConcreteCategory`, +-- Porting note: deriving failed for `HasForget`, -- "default handlers have not been implemented yet" -- https://github.com/leanprover-community/mathlib4/issues/5020 deriving instance LargeCategory for MagmaCat -instance instConcreteCategory : ConcreteCategory MagmaCat := BundledHom.concreteCategory MulHom +instance instHasForget : HasForget MagmaCat := BundledHom.hasForget MulHom -attribute [to_additive] instMagmaCatLargeCategory instConcreteCategory +attribute [to_additive] instMagmaCatLargeCategory instHasForget @[to_additive] instance : CoeSort MagmaCat Type* where @@ -90,7 +90,7 @@ theorem coe_of (R : Type u) [Mul R] : (MagmaCat.of R : Type u) = R := @[to_additive (attr := simp)] lemma mulEquiv_coe_eq {X Y : Type _} [Mul X] [Mul Y] (e : X ≃* Y) : (@DFunLike.coe (MagmaCat.of X ⟶ MagmaCat.of Y) _ (fun _ => (forget MagmaCat).obj _) - ConcreteCategory.instFunLike (e : X →ₙ* Y) : X → Y) = ↑e := + HasForget.instFunLike (e : X →ₙ* Y) : X → Y) = ↑e := rfl /-- Typecheck a `MulHom` as a morphism in `MagmaCat`. -/ @@ -125,13 +125,13 @@ instance : BundledHom.ParentProjection @Semigroup.toMul := ⟨⟩ deriving instance LargeCategory for Semigrp --- Porting note: deriving failed for `ConcreteCategory`, +-- Porting note: deriving failed for `HasForget`, -- "default handlers have not been implemented yet" -- https://github.com/leanprover-community/mathlib4/issues/5020 -instance instConcreteCategory : ConcreteCategory Semigrp := - BundledHom.concreteCategory (fun _ _ => _) +instance instHasForget : HasForget Semigrp := + BundledHom.hasForget (fun _ _ => _) -attribute [to_additive] instSemigrpLargeCategory Semigrp.instConcreteCategory +attribute [to_additive] instSemigrpLargeCategory Semigrp.instHasForget @[to_additive] instance : CoeSort Semigrp Type* where @@ -169,7 +169,7 @@ theorem coe_of (R : Type u) [Semigroup R] : (Semigrp.of R : Type u) = R := @[to_additive (attr := simp)] lemma mulEquiv_coe_eq {X Y : Type _} [Semigroup X] [Semigroup Y] (e : X ≃* Y) : (@DFunLike.coe (Semigrp.of X ⟶ Semigrp.of Y) _ (fun _ => (forget Semigrp).obj _) - ConcreteCategory.instFunLike (e : X →ₙ* Y) : X → Y) = ↑e := + HasForget.instFunLike (e : X →ₙ* Y) : X → Y) = ↑e := rfl /-- Typecheck a `MulHom` as a morphism in `Semigrp`. -/ @@ -279,7 +279,7 @@ instance Semigrp.forgetReflectsIsos : (forget Semigrp.{u}).ReflectsIsomorphisms -- Porting note: this was added in order to ensure that `forget₂ CommMonCat MonCat` -- automatically reflects isomorphisms --- we could have used `CategoryTheory.ConcreteCategory.ReflectsIso` alternatively +-- we could have used `CategoryTheory.HasForget.ReflectsIso` alternatively @[to_additive] instance Semigrp.forget₂_full : (forget₂ Semigrp MagmaCat).Full where map_surjective f := ⟨f, rfl⟩ diff --git a/Mathlib/Algebra/Homology/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ConcreteCategory.lean index ec495e24a7d91..f510e2876a6f3 100644 --- a/Mathlib/Algebra/Homology/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ConcreteCategory.lean @@ -10,7 +10,7 @@ import Mathlib.Algebra.Homology.ShortComplex.ConcreteCategory # Homology of complexes in concrete categories The homology of short complexes in concrete categories was studied in -`Mathlib.Algebra.Homology.ShortComplex.ConcreteCategory`. In this file, +`Mathlib.Algebra.Homology.ShortComplex.HasForget`. In this file, we introduce specific definitions and lemmas for the homology of homological complexes in concrete categories. In particular, we give a computation of the connecting homomorphism of @@ -22,7 +22,7 @@ open CategoryTheory universe v u -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] [HasForget₂ C Ab.{v}] +variable {C : Type u} [Category.{v} C] [HasForget.{v} C] [HasForget₂ C Ab.{v}] [Abelian C] [(forget₂ C Ab).Additive] [(forget₂ C Ab).PreservesHomology] {ι : Type*} {c : ComplexShape ι} diff --git a/Mathlib/Algebra/Homology/ImageToKernel.lean b/Mathlib/Algebra/Homology/ImageToKernel.lean index 16f064b89a76f..a1bb4fbbd7a6a 100644 --- a/Mathlib/Algebra/Homology/ImageToKernel.lean +++ b/Mathlib/Algebra/Homology/ImageToKernel.lean @@ -47,7 +47,7 @@ theorem subobject_ofLE_as_imageToKernel (w : f ≫ g = 0) (h) : Subobject.ofLE (imageSubobject f) (kernelSubobject g) h = imageToKernel f g w := rfl -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike -- Porting note: removed elementwise attribute which does not seem to be helpful here -- a more suitable lemma is added below @@ -57,7 +57,7 @@ theorem imageToKernel_arrow (w : f ≫ g = 0) : simp [imageToKernel] @[simp] -lemma imageToKernel_arrow_apply [ConcreteCategory V] (w : f ≫ g = 0) +lemma imageToKernel_arrow_apply [HasForget V] (w : f ≫ g = 0) (x : (forget V).obj (Subobject.underlying.obj (imageSubobject f))) : (kernelSubobject g).arrow (imageToKernel f g w x) = (imageSubobject f).arrow x := by diff --git a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean index dfd6dc033079a..92d14ea2564f5 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean @@ -25,7 +25,7 @@ open Limits section -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] [HasForget₂ C Ab] +variable {C : Type u} [Category.{v} C] [HasForget.{w} C] [HasForget₂ C Ab] @[simp] lemma ShortComplex.zero_apply @@ -81,7 +81,7 @@ lemma exact_iff_exact_map_forget₂ [S.HasHomology] : S.Exact ↔ (S.map (forget₂ C Ab)).Exact := (S.exact_map_iff_of_faithful (forget₂ C Ab)).symm -lemma exact_iff_of_concreteCategory [S.HasHomology] : +lemma exact_iff_of_hasForget [S.HasHomology] : S.Exact ↔ ∀ (x₂ : (forget₂ C Ab).obj S.X₂) (_ : ((forget₂ C Ab).map S.g) x₂ = 0), ∃ (x₁ : (forget₂ C Ab).obj S.X₁), ((forget₂ C Ab).map S.f) x₁ = x₂ := by rw [S.exact_iff_exact_map_forget₂, ab_exact_iff] @@ -123,10 +123,10 @@ end section abelian -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] [HasForget₂ C Ab] +variable {C : Type u} [Category.{v} C] [HasForget.{v} C] [HasForget₂ C Ab] [Abelian C] [(forget₂ C Ab).Additive] [(forget₂ C Ab).PreservesHomology] -attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort namespace ShortComplex diff --git a/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean b/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean index 87236bc52bb4d..3feb7503e5954 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean @@ -43,7 +43,7 @@ lemma moduleCat_zero_apply (x : S.X₁) : S.g (S.f x) = 0 := lemma moduleCat_exact_iff : S.Exact ↔ ∀ (x₂ : S.X₂) (_ : S.g x₂ = 0), ∃ (x₁ : S.X₁), S.f x₁ = x₂ := - S.exact_iff_of_concreteCategory + S.exact_iff_of_hasForget lemma moduleCat_exact_iff_ker_sub_range : S.Exact ↔ LinearMap.ker S.g.hom ≤ LinearMap.range S.f.hom := by diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index 754e130626539..990eb295b3aa0 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -180,7 +180,7 @@ theorem appIso_inv_app (U) : (PresheafedSpace.IsOpenImmersion.invApp_app _ _).trans (by rw [eqToHom_op]) /-- -`elementwise` generates the `ConcreteCategory.instFunLike` lemma, we want `CommRingCat.Hom.hom`. +`elementwise` generates the `HasForget.instFunLike` lemma, we want `CommRingCat.Hom.hom`. -/ theorem appIso_inv_app_apply' (U) (x) : f.app (f ''ᵁ U) ((f.appIso U).inv x) = X.presheaf.map (eqToHom (preimage_image_eq f U)).op x := diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean index 44912ce1425be..818f55693d133 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean @@ -309,7 +309,7 @@ def homogeneousLocalizationToStalk (x : ProjectiveSpectrum.top 𝒜) (y : at x) ProjectiveSpectrum.basicOpen 𝒜 g.den.1 ⊓ ProjectiveSpectrum.basicOpen 𝒜 c) ⟨⟨mem_basicOpen_den _ x f, mem_basicOpen_den _ x g⟩, hc⟩ (homOfLE inf_le_left ≫ homOfLE inf_le_left) (homOfLE inf_le_left ≫ homOfLE inf_le_right) - -- Go from `ConcreteCategory.instFunLike` to `CommRingCat.Hom.hom` + -- Go from `HasForget.instFunLike` to `CommRingCat.Hom.hom` show (Proj.structureSheaf 𝒜).presheaf.map (homOfLE inf_le_left ≫ homOfLE inf_le_left).op (sectionInBasicOpen 𝒜 x f) = (Proj.structureSheaf 𝒜).presheaf.map (homOfLE inf_le_left ≫ homOfLE inf_le_right).op diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index 97504a41cbdea..309e345b93978 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -532,7 +532,7 @@ def stalkIso (x : PrimeSpectrum.Top R) : exists_const _ _ s x hxU rw [← res_apply R U V iVU s ⟨x, hxV⟩, ← hs, const_apply, localizationToStalk_mk'] refine (structureSheaf R).presheaf.germ_ext V hxV (homOfLE hg) iVU ?_ - -- Replace the `ConcreteCategory.instFunLike` instance with `CommRingCat.hom`: + -- Replace the `HasForget.instFunLike` instance with `CommRingCat.hom`: show (structureSheaf R).presheaf.map (homOfLE hg).op _ = (structureSheaf R).presheaf.map iVU.op s rw [← hs, res_const'] diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index 156dc3423a3ca..fc1308dc19570 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -747,7 +747,7 @@ end Truncated section Concrete -instance : ConcreteCategory.{0} SimplexCategory where +instance : HasForget.{0} SimplexCategory where forget := { obj := fun i => Fin (i.len + 1) map := fun f => f.toOrderHom } diff --git a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean index 09fc36541fc97..7f2bbcf26e848 100644 --- a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean +++ b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean @@ -22,10 +22,10 @@ namespace SimplexCategory open Simplicial NNReal CategoryTheory -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike -- Porting note: added, should be moved -instance (x : SimplexCategory) : Fintype (ConcreteCategory.forget.obj x) := +instance (x : SimplexCategory) : Fintype (HasForget.forget.obj x) := inferInstanceAs (Fintype (Fin _)) /-- The topological simplex associated to `x : SimplexCategory`. diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean index 2910a2e00cda5..c6fb256ab5259 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean @@ -36,10 +36,10 @@ instance bundledHom : BundledHom @NormedAddGroupHom where deriving instance LargeCategory for SemiNormedGrp --- Porting note: deriving fails for ConcreteCategory, adding instance manually. +-- Porting note: deriving fails for HasForget, adding instance manually. -- See https://github.com/leanprover-community/mathlib4/issues/5020 --- deriving instance LargeCategory, ConcreteCategory for SemiRingCat -instance : ConcreteCategory SemiNormedGrp := by +-- deriving instance LargeCategory, HasForget for SemiRingCat +instance : HasForget SemiNormedGrp := by dsimp [SemiNormedGrp] infer_instance @@ -143,7 +143,7 @@ theorem hom_ext {M N : SemiNormedGrp₁} (f g : M ⟶ N) (w : (f : M → N) = (g f = g := Subtype.eq (NormedAddGroupHom.ext (congr_fun w)) -instance : ConcreteCategory.{u} SemiNormedGrp₁ where +instance : HasForget.{u} SemiNormedGrp₁ where forget := { obj := fun X => X map := fun f => f } diff --git a/Mathlib/CategoryTheory/Action/Basic.lean b/Mathlib/CategoryTheory/Action/Basic.lean index e46cc85367f18..1c61d3fcf4c62 100644 --- a/Mathlib/CategoryTheory/Action/Basic.lean +++ b/Mathlib/CategoryTheory/Action/Basic.lean @@ -231,7 +231,7 @@ variable (V G) /-- (implementation) The forgetful functor from bundled actions to the underlying objects. -Use the `CategoryTheory.forget` API provided by the `ConcreteCategory` instance below, +Use the `CategoryTheory.forget` API provided by the `HasForget` instance below, rather than using this directly. -/ @[simps] @@ -241,10 +241,10 @@ def forget : Action V G ⥤ V where instance : (forget V G).Faithful where map_injective w := Hom.ext w -instance [ConcreteCategory V] : ConcreteCategory (Action V G) where - forget := forget V G ⋙ ConcreteCategory.forget +instance [HasForget V] : HasForget (Action V G) where + forget := forget V G ⋙ HasForget.forget -instance hasForgetToV [ConcreteCategory V] : HasForget₂ (Action V G) V where forget₂ := forget V G +instance hasForgetToV [HasForget V] : HasForget₂ (Action V G) V where forget₂ := forget V G /-- The forgetful functor is intertwined by `functorCategoryEquivalence` with evaluation at `PUnit.star`. -/ diff --git a/Mathlib/CategoryTheory/Action/Concrete.lean b/Mathlib/CategoryTheory/Action/Concrete.lean index c38afc9a85c20..accafd5500e8d 100644 --- a/Mathlib/CategoryTheory/Action/Concrete.lean +++ b/Mathlib/CategoryTheory/Action/Concrete.lean @@ -167,7 +167,7 @@ end FintypeCat section ToMulAction -variable {V : Type (u + 1)} [LargeCategory V] [ConcreteCategory V] +variable {V : Type (u + 1)} [LargeCategory V] [HasForget V] instance instMulAction {G : MonCat.{u}} (X : Action V G) : MulAction G ((CategoryTheory.forget _).obj X) where diff --git a/Mathlib/CategoryTheory/Action/Continuous.lean b/Mathlib/CategoryTheory/Action/Continuous.lean index 15661630943e9..d229ddc3e57ff 100644 --- a/Mathlib/CategoryTheory/Action/Continuous.lean +++ b/Mathlib/CategoryTheory/Action/Continuous.lean @@ -28,7 +28,7 @@ universe u v open CategoryTheory Limits -variable (V : Type (u + 1)) [LargeCategory V] [ConcreteCategory V] [HasForget₂ V TopCat] +variable (V : Type (u + 1)) [LargeCategory V] [HasForget V] [HasForget₂ V TopCat] variable (G : MonCat.{u}) [TopologicalSpace G] namespace Action @@ -68,8 +68,8 @@ namespace ContAction instance : Category (ContAction V G) := FullSubcategory.category (IsContinuous (V := V) (G := G)) -instance : ConcreteCategory (ContAction V G) := - FullSubcategory.concreteCategory (IsContinuous (V := V) (G := G)) +instance : HasForget (ContAction V G) := + FullSubcategory.hasForget (IsContinuous (V := V) (G := G)) instance : HasForget₂ (ContAction V G) (Action V G) := FullSubcategory.hasForget₂ (IsContinuous (V := V) (G := G)) @@ -102,8 +102,8 @@ namespace DiscreteContAction instance : Category (DiscreteContAction V G) := FullSubcategory.category (IsDiscrete (V := V) (G := G)) -instance : ConcreteCategory (DiscreteContAction V G) := - FullSubcategory.concreteCategory (IsDiscrete (V := V) (G := G)) +instance : HasForget (DiscreteContAction V G) := + FullSubcategory.hasForget (IsDiscrete (V := V) (G := G)) instance : HasForget₂ (DiscreteContAction V G) (ContAction V G) := FullSubcategory.hasForget₂ (IsDiscrete (V := V) (G := G)) diff --git a/Mathlib/CategoryTheory/Action/Limits.lean b/Mathlib/CategoryTheory/Action/Limits.lean index a997429802737..22a33887e6908 100644 --- a/Mathlib/CategoryTheory/Action/Limits.lean +++ b/Mathlib/CategoryTheory/Action/Limits.lean @@ -219,7 +219,7 @@ instance : HasZeroMorphisms (Action V G) where instance forget_preservesZeroMorphisms : Functor.PreservesZeroMorphisms (forget V G) where -instance forget₂_preservesZeroMorphisms [ConcreteCategory V] : +instance forget₂_preservesZeroMorphisms [HasForget V] : Functor.PreservesZeroMorphisms (forget₂ (Action V G) V) where instance functorCategoryEquivalence_preservesZeroMorphisms : @@ -251,7 +251,7 @@ instance : Preadditive (Action V G) where instance forget_additive : Functor.Additive (forget V G) where -instance forget₂_additive [ConcreteCategory V] : Functor.Additive (forget₂ (Action V G) V) where +instance forget₂_additive [HasForget V] : Functor.Additive (forget₂ (Action V G) V) where instance functorCategoryEquivalence_additive : Functor.Additive (functorCategoryEquivalence V G).functor where @@ -289,7 +289,7 @@ instance : Linear R (Action V G) where instance forget_linear : Functor.Linear R (forget V G) where -instance forget₂_linear [ConcreteCategory V] : Functor.Linear R (forget₂ (Action V G) V) where +instance forget₂_linear [HasForget V] : Functor.Linear R (forget₂ (Action V G) V) where instance functorCategoryEquivalence_linear : Functor.Linear R (functorCategoryEquivalence V G).functor where diff --git a/Mathlib/CategoryTheory/Category/Bipointed.lean b/Mathlib/CategoryTheory/Category/Bipointed.lean index b8a57ae187af4..dd476b5539fcd 100644 --- a/Mathlib/CategoryTheory/Category/Bipointed.lean +++ b/Mathlib/CategoryTheory/Category/Bipointed.lean @@ -76,7 +76,7 @@ instance largeCategory : LargeCategory Bipointed where id := Hom.id comp := @Hom.comp -instance concreteCategory : ConcreteCategory Bipointed where +instance hasForget : HasForget Bipointed where forget := { obj := Bipointed.X map := @Hom.toFun } diff --git a/Mathlib/CategoryTheory/Category/Pointed.lean b/Mathlib/CategoryTheory/Category/Pointed.lean index d36dd860e3be1..836c154ecb746 100644 --- a/Mathlib/CategoryTheory/Category/Pointed.lean +++ b/Mathlib/CategoryTheory/Category/Pointed.lean @@ -82,7 +82,7 @@ instance largeCategory : LargeCategory Pointed where @[simp] lemma Hom.comp_toFun' {X Y Z : Pointed.{u}} (f : X ⟶ Y) (g : Y ⟶ Z) : (f ≫ g).toFun = g.toFun ∘ f.toFun := rfl -instance concreteCategory : ConcreteCategory Pointed where +instance hasForget : HasForget Pointed where forget := { obj := Pointed.X map := @Hom.toFun } diff --git a/Mathlib/CategoryTheory/Category/TwoP.lean b/Mathlib/CategoryTheory/Category/TwoP.lean index 49fda51da739c..458a2dae3c7b7 100644 --- a/Mathlib/CategoryTheory/Category/TwoP.lean +++ b/Mathlib/CategoryTheory/Category/TwoP.lean @@ -62,8 +62,8 @@ theorem coe_toBipointed (X : TwoP) : ↥X.toBipointed = ↥X := noncomputable instance largeCategory : LargeCategory TwoP := InducedCategory.category toBipointed -noncomputable instance concreteCategory : ConcreteCategory TwoP := - InducedCategory.concreteCategory toBipointed +noncomputable instance hasForget : HasForget TwoP := + InducedCategory.hasForget toBipointed noncomputable instance hasForgetToBipointed : HasForget₂ TwoP Bipointed := InducedCategory.hasForget₂ toBipointed diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index fb05317c1b822..0c1c8895b4fa5 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -9,7 +9,7 @@ import Mathlib.CategoryTheory.Types # Concrete categories A concrete category is a category `C` with a fixed faithful functor -`forget : C ⥤ Type*`. We define concrete categories using `class ConcreteCategory`. +`forget : C ⥤ Type*`. We define concrete categories using `class HasForget`. In particular, we impose no restrictions on the carrier type `C`, so `Type` is a concrete category with the identity forgetful functor. @@ -27,6 +27,11 @@ Two classes helping construct concrete categories in the two most common cases are provided in the files `BundledHom` and `UnbundledHom`, see their documentation for details. +## Implementation notes + +We are currently switching over from `HasForget` to a new class `ConcreteCategory`, +see Zulip thread: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign + ## References See [Ahrens and Lumsdaine, *Displayed Categories*][ahrens2017] for @@ -42,27 +47,32 @@ namespace CategoryTheory /-- A concrete category is a category `C` with a fixed faithful functor `Forget : C ⥤ Type`. -Note that `ConcreteCategory` potentially depends on three independent universe levels, +Note that `HasForget` potentially depends on three independent universe levels, * the universe level `w` appearing in `Forget : C ⥤ Type w` * the universe level `v` of the morphisms (i.e. we have a `Category.{v} C`) * the universe level `u` of the objects (i.e `C : Type u`) They are specified that order, to avoid unnecessary universe annotations. -/ -class ConcreteCategory (C : Type u) [Category.{v} C] where +class HasForget (C : Type u) [Category.{v} C] where /-- We have a functor to Type -/ protected forget : C ⥤ Type w /-- That functor is faithful -/ [forget_faithful : forget.Faithful] -attribute [inline, reducible] ConcreteCategory.forget -attribute [instance] ConcreteCategory.forget_faithful +@[deprecated HasForget + "`ConcreteCategory` will be refactored, use `HasForget` in the meantime" + (since := "2025-01-17")] +alias ConcreteCategory := HasForget + +attribute [inline, reducible] HasForget.forget +attribute [instance] HasForget.forget_faithful /-- The forgetful functor from a concrete category to `Type u`. -/ -abbrev forget (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] : C ⥤ Type w := - ConcreteCategory.forget +abbrev forget (C : Type u) [Category.{v} C] [HasForget.{w} C] : C ⥤ Type w := + HasForget.forget -- this is reducible because we want `forget (Type u)` to unfold to `𝟭 _` -@[instance] abbrev ConcreteCategory.types : ConcreteCategory.{u, u, u+1} (Type u) where +@[instance] abbrev HasForget.types : HasForget.{u, u, u+1} (Type u) where forget := 𝟭 _ /-- Provide a coercion to `Type u` for a concrete category. This is not marked as an instance @@ -70,24 +80,24 @@ as it could potentially apply to every type, and so is too expensive in typeclas You can use it on particular examples as: ``` -instance : HasCoeToSort X := ConcreteCategory.hasCoeToSort X +instance : HasCoeToSort X := HasForget.hasCoeToSort X ``` -/ -def ConcreteCategory.hasCoeToSort (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] : +def HasForget.hasCoeToSort (C : Type u) [Category.{v} C] [HasForget.{w} C] : CoeSort C (Type w) where coe X := (forget C).obj X section -attribute [local instance] ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.hasCoeToSort -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] +variable {C : Type u} [Category.{v} C] [HasForget.{w} C] /-- In any concrete category, `(forget C).map` is injective. -/ -abbrev ConcreteCategory.instFunLike {X Y : C} : FunLike (X ⟶ Y) X Y where +abbrev HasForget.instFunLike {X Y : C} : FunLike (X ⟶ Y) X Y where coe f := (forget C).map f coe_injective' _ _ h := (forget C).map_injective h -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike /-- In any concrete category, we can test equality of morphisms by pointwise evaluations. -/ @[ext low] -- Porting note: lowered priority @@ -134,47 +144,47 @@ end /-- `HasForget₂ C D`, where `C` and `D` are both concrete categories, provides a functor `forget₂ C D : C ⥤ D` and a proof that `forget₂ ⋙ (forget D) = forget C`. -/ -class HasForget₂ (C : Type u) (D : Type u') [Category.{v} C] [ConcreteCategory.{w} C] - [Category.{v'} D] [ConcreteCategory.{w} D] where +class HasForget₂ (C : Type u) (D : Type u') [Category.{v} C] [HasForget.{w} C] + [Category.{v'} D] [HasForget.{w} D] where /-- A functor from `C` to `D` -/ forget₂ : C ⥤ D - /-- It covers the `ConcreteCategory.forget` for `C` and `D` -/ + /-- It covers the `HasForget.forget` for `C` and `D` -/ forget_comp : forget₂ ⋙ forget D = forget C := by aesop /-- The forgetful functor `C ⥤ D` between concrete categories for which we have an instance `HasForget₂ C`. -/ -abbrev forget₂ (C : Type u) (D : Type u') [Category.{v} C] [ConcreteCategory.{w} C] - [Category.{v'} D] [ConcreteCategory.{w} D] [HasForget₂ C D] : C ⥤ D := +abbrev forget₂ (C : Type u) (D : Type u') [Category.{v} C] [HasForget.{w} C] + [Category.{v'} D] [HasForget.{w} D] [HasForget₂ C D] : C ⥤ D := HasForget₂.forget₂ -attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort -lemma forget₂_comp_apply {C : Type u} {D : Type u'} [Category.{v} C] [ConcreteCategory.{w} C] - [Category.{v'} D] [ConcreteCategory.{w} D] [HasForget₂ C D] {X Y Z : C} +lemma forget₂_comp_apply {C : Type u} {D : Type u'} [Category.{v} C] [HasForget.{w} C] + [Category.{v'} D] [HasForget.{w} D] [HasForget₂ C D] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (x : (forget₂ C D).obj X) : ((forget₂ C D).map (f ≫ g) x) = (forget₂ C D).map g ((forget₂ C D).map f x) := by rw [Functor.map_comp, comp_apply] -instance forget₂_faithful (C : Type u) (D : Type u') [Category.{v} C] [ConcreteCategory.{w} C] - [Category.{v'} D] [ConcreteCategory.{w} D] [HasForget₂ C D] : (forget₂ C D).Faithful := +instance forget₂_faithful (C : Type u) (D : Type u') [Category.{v} C] [HasForget.{w} C] + [Category.{v'} D] [HasForget.{w} D] [HasForget₂ C D] : (forget₂ C D).Faithful := HasForget₂.forget_comp.faithful_of_comp -instance InducedCategory.concreteCategory {C : Type u} {D : Type u'} - [Category.{v'} D] [ConcreteCategory.{w} D] (f : C → D) : - ConcreteCategory (InducedCategory D f) where +instance InducedCategory.hasForget {C : Type u} {D : Type u'} + [Category.{v'} D] [HasForget.{w} D] (f : C → D) : + HasForget (InducedCategory D f) where forget := inducedFunctor f ⋙ forget D instance InducedCategory.hasForget₂ {C : Type u} {D : Type u'} [Category.{v} D] - [ConcreteCategory.{w} D] (f : C → D) : HasForget₂ (InducedCategory D f) D where + [HasForget.{w} D] (f : C → D) : HasForget₂ (InducedCategory D f) D where forget₂ := inducedFunctor f forget_comp := rfl -instance FullSubcategory.concreteCategory {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] - (Z : C → Prop) : ConcreteCategory (FullSubcategory Z) where +instance FullSubcategory.hasForget {C : Type u} [Category.{v} C] [HasForget.{w} C] + (Z : C → Prop) : HasForget (FullSubcategory Z) where forget := fullSubcategoryInclusion Z ⋙ forget C -instance FullSubcategory.hasForget₂ {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] +instance FullSubcategory.hasForget₂ {C : Type u} [Category.{v} C] [HasForget.{w} C] (Z : C → Prop) : HasForget₂ (FullSubcategory Z) C where forget₂ := fullSubcategoryInclusion Z forget_comp := rfl @@ -182,8 +192,8 @@ instance FullSubcategory.hasForget₂ {C : Type u} [Category.{v} C] [ConcreteCat /-- In order to construct a “partially forgetting” functor, we do not need to verify functor laws; it suffices to ensure that compositions agree with `forget₂ C D ⋙ forget D = forget C`. -/ -def HasForget₂.mk' {C : Type u} {D : Type u'} [Category.{v} C] [ConcreteCategory.{w} C] - [Category.{v'} D] [ConcreteCategory.{w} D] +def HasForget₂.mk' {C : Type u} {D : Type u'} [Category.{v} C] [HasForget.{w} C] + [Category.{v'} D] [HasForget.{w} D] (obj : C → D) (h_obj : ∀ X, (forget D).obj (obj X) = (forget C).obj X) (map : ∀ {X Y}, (X ⟶ Y) → (obj X ⟶ obj Y)) (h_map : ∀ {X Y} {f : X ⟶ Y}, HEq ((forget D).map (map f)) ((forget C).map f)) : @@ -193,9 +203,9 @@ def HasForget₂.mk' {C : Type u} {D : Type u'} [Category.{v} C] [ConcreteCatego /-- Composition of `HasForget₂` instances. -/ @[reducible] -def HasForget₂.trans (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] - (D : Type u') [Category.{v'} D] [ConcreteCategory.{w} D] - (E : Type u'') [Category.{v''} E] [ConcreteCategory.{w} E] +def HasForget₂.trans (C : Type u) [Category.{v} C] [HasForget.{w} C] + (D : Type u') [Category.{v'} D] [HasForget.{w} D] + (E : Type u'') [Category.{v''} E] [HasForget.{w} E] [HasForget₂ C D] [HasForget₂ D E] : HasForget₂ C E where forget₂ := CategoryTheory.forget₂ C D ⋙ CategoryTheory.forget₂ D E forget_comp := by @@ -204,13 +214,13 @@ def HasForget₂.trans (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] /-- Every forgetful functor factors through the identity functor. This is not a global instance as it is prone to creating type class resolution loops. -/ -def hasForgetToType (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] : +def hasForgetToType (C : Type u) [Category.{v} C] [HasForget.{w} C] : HasForget₂ C (Type w) where forget₂ := forget C forget_comp := Functor.comp_id _ @[simp] -lemma NatTrans.naturality_apply {C D : Type*} [Category C] [Category D] [ConcreteCategory D] +lemma NatTrans.naturality_apply {C D : Type*} [Category C] [Category D] [HasForget D] {F G : C ⥤ D} (φ : F ⟶ G) {X Y : C} (f : X ⟶ Y) (x : F.obj X) : φ.app Y (F.map f x) = G.map f (φ.app X x) := by simpa only [Functor.map_comp] using congr_fun ((forget D).congr_map (φ.naturality f)) x diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean index 1fe01ebf2d14a..875403ebcf0f4 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean @@ -12,9 +12,9 @@ import Batteries.Tactic.Lint.Misc `Bundled c` provides a uniform structure for bundling a type equipped with a type class. We provide `Category` instances for these in -`Mathlib/CategoryTheory/ConcreteCategory/UnbundledHom.lean` +`Mathlib/CategoryTheory/HasForget/UnbundledHom.lean` (for categories with unbundled homs, e.g. topological spaces) -and in `Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean` +and in `Mathlib/CategoryTheory/HasForget/BundledHom.lean` (for categories with bundled homs, e.g. monoids). -/ diff --git a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean index 9c4cd7abf9e84..079ad83067593 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean @@ -66,7 +66,7 @@ instance category : Category (Bundled c) where id_comp _ := by apply 𝒞.hom_ext; simp /-- A category given by `BundledHom` is a concrete category. -/ -instance concreteCategory : ConcreteCategory.{u} (Bundled c) where +instance hasForget : HasForget.{u} (Bundled c) where forget := { obj := fun X => X map := @fun X Y f => 𝒞.toFun X.str Y.str f @@ -82,7 +82,7 @@ unif_hint (C : Bundled c) where variable {hom} -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike /-- A version of `HasForget₂.mk'` for categories defined using `@BundledHom`. -/ def mkHasForget₂ {d : Type u → Type u} {hom_d : ∀ ⦃α β : Type u⦄ (_ : d α) (_ : d β), Type u} diff --git a/Mathlib/CategoryTheory/ConcreteCategory/EpiMono.lean b/Mathlib/CategoryTheory/ConcreteCategory/EpiMono.lean index b076870df5fd9..76a6953da78bd 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/EpiMono.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/EpiMono.lean @@ -25,7 +25,7 @@ universe w v v' u u' namespace CategoryTheory -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] +variable {C : Type u} [Category.{v} C] [HasForget.{w} C] open Limits MorphismProperty @@ -33,14 +33,14 @@ namespace ConcreteCategory section -attribute [local instance] ConcreteCategory.instFunLike in +attribute [local instance] HasForget.instFunLike in /-- In any concrete category, injective morphisms are monomorphisms. -/ theorem mono_of_injective {X Y : C} (f : X ⟶ Y) (i : Function.Injective f) : Mono f := (forget C).mono_of_mono_map ((mono_iff_injective ((forget C).map f)).2 i) instance forget₂_preservesMonomorphisms (C : Type u) (D : Type u') - [Category.{v} C] [ConcreteCategory.{w} C] [Category.{v'} D] [ConcreteCategory.{w} D] + [Category.{v} C] [HasForget.{w} C] [Category.{v'} D] [HasForget.{w} D] [HasForget₂ C D] [(forget C).PreservesMonomorphisms] : (forget₂ C D).PreservesMonomorphisms := have : (forget₂ C D ⋙ forget D).PreservesMonomorphisms := by @@ -49,7 +49,7 @@ instance forget₂_preservesMonomorphisms (C : Type u) (D : Type u') Functor.preservesMonomorphisms_of_preserves_of_reflects _ (forget D) instance forget₂_preservesEpimorphisms (C : Type u) (D : Type u') - [Category.{v} C] [ConcreteCategory.{w} C] [Category.{v'} D] [ConcreteCategory.{w} D] + [Category.{v} C] [HasForget.{w} C] [Category.{v'} D] [HasForget.{w} D] [HasForget₂ C D] [(forget C).PreservesEpimorphisms] : (forget₂ C D).PreservesEpimorphisms := have : (forget₂ C D ⋙ forget D).PreservesEpimorphisms := by @@ -133,8 +133,8 @@ section open CategoryTheory.Limits -attribute [local instance] ConcreteCategory.hasCoeToSort -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort +attribute [local instance] HasForget.instFunLike theorem injective_of_mono_of_preservesPullback {X Y : C} (f : X ⟶ Y) [Mono f] [PreservesLimitsOfShape WalkingCospan (forget C)] : Function.Injective f := diff --git a/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean b/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean index 69e90e646f526..c38e5269196cb 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/ReflectsIso.lean @@ -18,8 +18,8 @@ namespace CategoryTheory instance : (forget (Type u)).ReflectsIsomorphisms where reflects _ _ _ {i} := i -variable (C : Type (u + 1)) [Category C] [ConcreteCategory.{u} C] -variable (D : Type (u + 1)) [Category D] [ConcreteCategory.{u} D] +variable (C : Type (u + 1)) [Category C] [HasForget.{u} C] +variable (D : Type (u + 1)) [Category D] [HasForget.{u} D] -- This should not be an instance, as it causes a typeclass loop -- with `CategoryTheory.hasForgetToType`. diff --git a/Mathlib/CategoryTheory/DifferentialObject.lean b/Mathlib/CategoryTheory/DifferentialObject.lean index 0a8114b1afc95..067ddda0ea0c1 100644 --- a/Mathlib/CategoryTheory/DifferentialObject.lean +++ b/Mathlib/CategoryTheory/DifferentialObject.lean @@ -208,10 +208,10 @@ end DifferentialObject namespace DifferentialObject variable (S : Type*) [AddMonoidWithOne S] -variable (C : Type (u + 1)) [LargeCategory C] [ConcreteCategory C] [HasZeroMorphisms C] +variable (C : Type (u + 1)) [LargeCategory C] [HasForget C] [HasZeroMorphisms C] variable [HasShift C S] -instance concreteCategoryOfDifferentialObjects : ConcreteCategory (DifferentialObject S C) where +instance hasForgetOfDifferentialObjects : HasForget (DifferentialObject S C) where forget := forget S C ⋙ CategoryTheory.forget C instance : HasForget₂ (DifferentialObject S C) C where diff --git a/Mathlib/CategoryTheory/FintypeCat.lean b/Mathlib/CategoryTheory/FintypeCat.lean index 871779a37dcf5..8eb20b5d8481b 100644 --- a/Mathlib/CategoryTheory/FintypeCat.lean +++ b/Mathlib/CategoryTheory/FintypeCat.lean @@ -53,7 +53,7 @@ def incl : FintypeCat ⥤ Type* := instance : incl.Full := InducedCategory.full _ instance : incl.Faithful := InducedCategory.faithful _ -instance concreteCategoryFintype : ConcreteCategory FintypeCat := +instance hasForgetFintype : HasForget FintypeCat := ⟨incl⟩ /- Help typeclass inference infer fullness of forgetful functor. -/ diff --git a/Mathlib/CategoryTheory/Functor/Flat.lean b/Mathlib/CategoryTheory/Functor/Flat.lean index c7ee840f6e83f..c828dd56ec407 100644 --- a/Mathlib/CategoryTheory/Functor/Flat.lean +++ b/Mathlib/CategoryTheory/Functor/Flat.lean @@ -307,7 +307,7 @@ noncomputable def lanEvaluationIsoColim (F : C ⥤ D) (X : D) ι_colimMap, whiskerLeft_app] rfl) -variable [ConcreteCategory.{u₁} E] [HasLimits E] [HasColimits E] +variable [HasForget.{u₁} E] [HasLimits E] [HasColimits E] variable [ReflectsLimits (forget E)] [PreservesFilteredColimits (forget E)] variable [PreservesLimits (forget E)] diff --git a/Mathlib/CategoryTheory/GradedObject.lean b/Mathlib/CategoryTheory/GradedObject.lean index 103db592c7731..60536139bb717 100644 --- a/Mathlib/CategoryTheory/GradedObject.lean +++ b/Mathlib/CategoryTheory/GradedObject.lean @@ -283,10 +283,10 @@ namespace GradedObject noncomputable section variable (β : Type) -variable (C : Type (u + 1)) [LargeCategory C] [ConcreteCategory C] [HasCoproducts.{0} C] +variable (C : Type (u + 1)) [LargeCategory C] [HasForget C] [HasCoproducts.{0} C] [HasZeroMorphisms C] -instance : ConcreteCategory (GradedObject β C) where forget := total β C ⋙ forget C +instance : HasForget (GradedObject β C) where forget := total β C ⋙ forget C instance : HasForget₂ (GradedObject β C) C where forget₂ := total β C diff --git a/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean index 2ecb02a4b57c2..49f2cf2ff7df8 100644 --- a/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean @@ -19,20 +19,20 @@ open CategoryTheory namespace CategoryTheory.Limits.Concrete -attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort section Limits /-- If a functor `G : J ⥤ C` to a concrete category has a limit and that `forget C` is corepresentable, then `(G ⋙ forget C).sections` is small. -/ lemma small_sections_of_hasLimit - {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] + {C : Type u} [Category.{v} C] [HasForget.{v} C] [(forget C).IsCorepresentable] {J : Type w} [Category.{t} J] (G : J ⥤ C) [HasLimit G] : Small.{v} (G ⋙ forget C).sections := by rw [← Types.hasLimit_iff_small_sections] infer_instance -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{max w v} C] {J : Type w} [Category.{t} J] +variable {C : Type u} [Category.{v} C] [HasForget.{max w v} C] {J : Type w} [Category.{t} J] (F : J ⥤ C) [PreservesLimit F (forget C)] theorem to_product_injective_of_isLimit {D : Cone F} (hD : IsLimit D) : @@ -64,7 +64,7 @@ section Surjective Given surjections `⋯ ⟶ Xₙ₊₁ ⟶ Xₙ ⟶ ⋯ ⟶ X₀` in a concrete category whose forgetful functor preserves sequential limits, the projection map `lim Xₙ ⟶ X₀` is surjective. -/ -lemma surjective_π_app_zero_of_surjective_map {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] +lemma surjective_π_app_zero_of_surjective_map {C : Type u} [Category.{v} C] [HasForget.{v} C] [PreservesLimitsOfShape ℕᵒᵖ (forget C)] {F : ℕᵒᵖ ⥤ C} {c : Cone F} (hc : IsLimit c) (hF : ∀ n, Function.Surjective (F.map (homOfLE (Nat.le_succ n)).op)) : Function.Surjective (c.π.app ⟨0⟩) := @@ -78,7 +78,7 @@ section Colimits section -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{t} C] {J : Type w} [Category.{r} J] +variable {C : Type u} [Category.{v} C] [HasForget.{t} C] {J : Type w} [Category.{r} J] (F : J ⥤ C) section @@ -124,7 +124,7 @@ end section FilteredColimits -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{max t w} C] {J : Type w} [Category.{r} J] +variable {C : Type u} [Category.{v} C] [HasForget.{max t w} C] {J : Type w} [Category.{r} J] (F : J ⥤ C) [PreservesColimit F (forget C)] [IsFiltered J] theorem isColimit_exists_of_rep_eq {D : Cocone F} {i j : J} (hD : IsColimit D) diff --git a/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean b/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean index 1496b467c1f8a..d5e68a50703d7 100644 --- a/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean +++ b/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean @@ -47,7 +47,7 @@ theorem colimit_rep_eq_zero ∃ (j' : J) (i : j ⟶ j'), (F.map i).hom x = 0 := by -- Break the abstraction barrier between homs and functions for `colimit_rep_eq_iff_exists`. have : ∀ (X Y : ModuleCat R) (f : X ⟶ Y), - DFunLike.coe f.hom = DFunLike.coe (self := ConcreteCategory.instFunLike) f := fun _ _ _ => rfl + DFunLike.coe f.hom = DFunLike.coe (self := HasForget.instFunLike) f := fun _ _ _ => rfl rw [show 0 = colimit.ι F j 0 by simp, this, colimit_rep_eq_iff_exists] at hx obtain ⟨j', i, y, g⟩ := hx exact ⟨j', i, g ▸ by simp [← this]⟩ @@ -68,7 +68,7 @@ lemma colimit_no_zero_smul_divisor -- Break the abstraction barrier between homs and functions for `Concrete.colimit_exists_rep`. have : ∀ (X Y : ModuleCat R) (f : X ⟶ Y), - DFunLike.coe f.hom = DFunLike.coe (self := ConcreteCategory.instFunLike) f := fun _ _ _ => rfl + DFunLike.coe f.hom = DFunLike.coe (self := HasForget.instFunLike) f := fun _ _ _ => rfl classical obtain ⟨j, x, rfl⟩ := Concrete.colimit_exists_rep F x rw [← this, ← map_smul (colimit.ι F j).hom] at hx diff --git a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean index 0927649572779..4ec8cd323dafb 100644 --- a/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean +++ b/Mathlib/CategoryTheory/Limits/FilteredColimitCommutesFiniteLimit.lean @@ -347,7 +347,7 @@ noncomputable instance filtered_colim_preservesFiniteLimits_of_types : · exact Functor.mapIso _ (hc.uniqueUpToIso (limit.isLimit F)) · exact asIso (colimitLimitToLimitColimitCone F) -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] +variable {C : Type u} [Category.{v} C] [HasForget.{v} C] section diff --git a/Mathlib/CategoryTheory/Limits/MonoCoprod.lean b/Mathlib/CategoryTheory/Limits/MonoCoprod.lean index 868732f7d96d1..dc5bc0023ed48 100644 --- a/Mathlib/CategoryTheory/Limits/MonoCoprod.lean +++ b/Mathlib/CategoryTheory/Limits/MonoCoprod.lean @@ -239,7 +239,7 @@ end Preservation section Concrete -instance [ConcreteCategory C] [PreservesColimitsOfShape (Discrete WalkingPair) (forget C)] +instance [HasForget C] [PreservesColimitsOfShape (Discrete WalkingPair) (forget C)] [ReflectsMonomorphisms (forget C)] : MonoCoprod C := monoCoprod_of_preservesCoprod_of_reflectsMono (forget C) diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean index d16936f661fa4..daeb064872fed 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean @@ -35,7 +35,7 @@ universe w w' v u t r namespace CategoryTheory.Limits.Concrete -attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort variable {C : Type u} [Category.{v} C] @@ -43,7 +43,7 @@ section Products section ProductEquiv -variable [ConcreteCategory.{max w v} C] {J : Type w} (F : J → C) +variable [HasForget.{max w v} C] {J : Type w} (F : J → C) [HasProduct F] [PreservesLimit (Discrete.functor F) (forget C)] /-- The equivalence `(forget C).obj (∏ᶜ F) ≃ ∀ j, F j` if `F : J → C` is a family of objects @@ -66,7 +66,7 @@ end ProductEquiv section ProductExt variable {J : Type w} (f : J → C) [HasProduct f] {D : Type t} [Category.{r} D] - [ConcreteCategory.{max w r} D] (F : C ⥤ D) + [HasForget.{max w r} D] (F : C ⥤ D) [PreservesLimit (Discrete.functor f) F] [HasProduct fun j => F.obj (f j)] [PreservesLimitsOfShape WalkingCospan (forget D)] @@ -89,7 +89,7 @@ end Products section Terminal -variable [ConcreteCategory.{w} C] +variable [HasForget.{w} C] /-- If `forget C` preserves terminals and `X` is terminal, then `(forget C).obj X` is a singleton. -/ @@ -124,7 +124,7 @@ end Terminal section Initial -variable [ConcreteCategory.{w} C] +variable [HasForget.{w} C] /-- If `forget C` preserves initials and `X` is initial, then `(forget C).obj X` is empty. -/ lemma empty_of_initial_of_preserves [PreservesColimit (Functor.empty.{0} C) (forget C)] (X : C) @@ -149,7 +149,7 @@ end Initial section BinaryProducts -variable [ConcreteCategory.{w} C] (X₁ X₂ : C) [HasBinaryProduct X₁ X₂] +variable [HasForget.{w} C] (X₁ X₂ : C) [HasBinaryProduct X₁ X₂] [PreservesLimit (pair X₁ X₂) (forget C)] /-- The equivalence `(forget C).obj (X₁ ⨯ X₂) ≃ ((forget C).obj X₁) × ((forget C).obj X₂)` @@ -183,7 +183,7 @@ end BinaryProducts section Pullbacks -variable [ConcreteCategory.{v} C] {X₁ X₂ S : C} (f₁ : X₁ ⟶ S) (f₂ : X₂ ⟶ S) +variable [HasForget.{v} C] {X₁ X₂ S : C} (f₁ : X₁ ⟶ S) (f₂ : X₂ ⟶ S) [HasPullback f₁ f₂] [PreservesLimit (cospan f₁ f₂) (forget C)] /-- In a concrete category `C`, given two morphisms `f₁ : X₁ ⟶ S` and `f₂ : X₂ ⟶ S`, @@ -220,7 +220,7 @@ end Pullbacks section WidePullback -variable [ConcreteCategory.{max w v} C] +variable [HasForget.{max w v} C] open WidePullback @@ -247,7 +247,7 @@ end WidePullback section Multiequalizer -variable [ConcreteCategory.{max w w' v} C] +variable [HasForget.{max w w' v} C] theorem multiequalizer_ext {I : MulticospanIndex.{w, w'} C} [HasMultiequalizer I] [PreservesLimit I.multicospan (forget C)] (x y : ↑(multiequalizer I)) @@ -315,7 +315,7 @@ open WidePushout open WidePushoutShape -variable [ConcreteCategory.{v} C] +variable [HasForget.{v} C] theorem widePushout_exists_rep {B : C} {α : Type _} {X : α → C} (f : ∀ j : α, B ⟶ X j) [HasWidePushout.{v} B X f] [PreservesColimit (wideSpan B X f) (forget C)] @@ -340,7 +340,7 @@ theorem widePushout_exists_rep' {B : C} {α : Type _} [Nonempty α] {X : α → end WidePushout -- We don't mark this as an `@[ext]` lemma as we don't always want to work elementwise. -theorem cokernel_funext {C : Type*} [Category C] [HasZeroMorphisms C] [ConcreteCategory C] +theorem cokernel_funext {C : Type*} [Category C] [HasZeroMorphisms C] [HasForget C] {M N K : C} {f : M ⟶ N} [HasCokernel f] {g h : cokernel f ⟶ K} (w : ∀ n : N, g (cokernel.π f n) = h (cokernel.π f n)) : g = h := by ext x diff --git a/Mathlib/CategoryTheory/MorphismProperty/Concrete.lean b/Mathlib/CategoryTheory/MorphismProperty/Concrete.lean index f343d8580e654..3b61bad3be2cd 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Concrete.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Concrete.lean @@ -25,13 +25,13 @@ universe v u namespace CategoryTheory -variable (C : Type u) [Category.{v} C] [ConcreteCategory C] +variable (C : Type u) [Category.{v} C] [HasForget C] namespace MorphismProperty open Function -attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort /-- Injectiveness (in a concrete category) as a `MorphismProperty` -/ protected def injective : MorphismProperty C := fun _ _ f => Injective f diff --git a/Mathlib/CategoryTheory/Sites/Adjunction.lean b/Mathlib/CategoryTheory/Sites/Adjunction.lean index eb19bd7cd03c8..112afb02311a0 100644 --- a/Mathlib/CategoryTheory/Sites/Adjunction.lean +++ b/Mathlib/CategoryTheory/Sites/Adjunction.lean @@ -28,7 +28,7 @@ variable {F : D ⥤ E} {G : E ⥤ D} /-- The forgetful functor from `Sheaf J D` to sheaves of types, for a concrete category `D` whose forgetful functor preserves the correct limits. -/ -abbrev sheafForget [ConcreteCategory D] [HasSheafCompose J (forget D)] : +abbrev sheafForget [HasForget D] [HasSheafCompose J (forget D)] : Sheaf J D ⥤ Sheaf J (Type _) := sheafCompose J (forget D) @@ -96,7 +96,7 @@ instance [G.IsLeftAdjoint] : J.PreservesSheafification G := section ForgetToType -variable [HasWeakSheafify J D] [ConcreteCategory D] [HasSheafCompose J (forget D)] +variable [HasWeakSheafify J D] [HasForget D] [HasSheafCompose J (forget D)] @[deprecated (since := "2024-11-26")] alias composeAndSheafifyFromTypes := composeAndSheafify diff --git a/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean b/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean index e7d77d4762d54..ec6878bf85ec5 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean @@ -31,11 +31,11 @@ universe w open CategoryTheory Sheaf Limits Opposite -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike namespace CategoryTheory -variable {C : Type*} (D : Type*) [Category C] [Category D] [ConcreteCategory.{w} D] +variable {C : Type*} (D : Type*) [Category C] [Category D] [HasForget.{w} D] lemma regularTopology.isLocallySurjective_iff [Preregular C] {F G : Cᵒᵖ ⥤ D} (f : F ⟶ G) : Presheaf.IsLocallySurjective (regularTopology C) f ↔ diff --git a/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean b/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean index ad79a0ec8cdd5..6552bd53ca448 100644 --- a/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean @@ -120,7 +120,7 @@ theorem toSheafify_comp_sheafifyCompIso_inv : section -- We will sheafify `D`-valued presheaves in this section. -variable [ConcreteCategory.{max v u} D] [PreservesLimits (forget D)] +variable [HasForget.{max v u} D] [PreservesLimits (forget D)] [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] [(forget D).ReflectsIsomorphisms] @[simp] diff --git a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean index 3f054c3979a0c..2997401067b07 100644 --- a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean @@ -30,9 +30,9 @@ variable {D : Type w} [Category.{max v u} D] section -variable [ConcreteCategory.{max v u} D] +variable [HasForget.{max v u} D] -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- A concrete version of the multiequalizer, to be used below. -/ @@ -44,9 +44,9 @@ end namespace Meq -variable [ConcreteCategory.{max v u} D] +variable [HasForget.{max v u} D] -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike instance {X} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) : CoeFun (Meq P S) fun _ => ∀ I : S.Arrow, P.obj (op I.Y) := @@ -128,9 +128,9 @@ namespace GrothendieckTopology namespace Plus -variable [ConcreteCategory.{max v u} D] +variable [HasForget.{max v u} D] -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike variable [PreservesLimits (forget D)] variable [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] @@ -541,7 +541,7 @@ theorem sheafifyMap_sheafifyLift {P Q R : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (γ : Q end GrothendieckTopology variable (J) -variable [ConcreteCategory.{max v u} D] [PreservesLimits (forget D)] +variable [HasForget.{max v u} D] [PreservesLimits (forget D)] [∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : J.Cover X), HasMultiequalizer (S.index P)] [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] [(forget D).ReflectsIsomorphisms] diff --git a/Mathlib/CategoryTheory/Sites/EpiMono.lean b/Mathlib/CategoryTheory/Sites/EpiMono.lean index 5483640b1b9e6..1b5e4db91b8f9 100644 --- a/Mathlib/CategoryTheory/Sites/EpiMono.lean +++ b/Mathlib/CategoryTheory/Sites/EpiMono.lean @@ -26,7 +26,7 @@ namespace CategoryTheory open Category ConcreteCategory variable {C : Type u} [Category.{v} C] (J : GrothendieckTopology C) - (A : Type u') [Category.{v'} A] [ConcreteCategory.{w} A] + (A : Type u') [Category.{v'} A] [HasForget.{w} A] [HasFunctorialSurjectiveInjectiveFactorization A] [J.WEqualsLocallyBijective A] diff --git a/Mathlib/CategoryTheory/Sites/Equivalence.lean b/Mathlib/CategoryTheory/Sites/Equivalence.lean index 9ae28dadabe3f..2290822fe0e3e 100644 --- a/Mathlib/CategoryTheory/Sites/Equivalence.lean +++ b/Mathlib/CategoryTheory/Sites/Equivalence.lean @@ -269,7 +269,7 @@ lemma PreservesSheafification.transport K.W_whiskerLeft_iff (G := G) (J := J) (f := whiskerRight f F)] at this variable [Functor.IsContinuous.{v₃} G K J] [(G.sheafPushforwardContinuous A K J).EssSurj] -variable [G.IsCocontinuous K J] [ConcreteCategory A] +variable [G.IsCocontinuous K J] [HasForget A] [K.WEqualsLocallyBijective A] lemma WEqualsLocallyBijective.transport (hG : CoverPreserving K J G) : diff --git a/Mathlib/CategoryTheory/Sites/LeftExact.lean b/Mathlib/CategoryTheory/Sites/LeftExact.lean index 4e6d5411bd86f..5a089a0b21dfa 100644 --- a/Mathlib/CategoryTheory/Sites/LeftExact.lean +++ b/Mathlib/CategoryTheory/Sites/LeftExact.lean @@ -112,7 +112,7 @@ instance preservesLimits_diagramFunctor (X : C) [HasLimits D] : apply preservesLimitsOfShape_diagramFunctor.{w, v, u} variable [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] -variable [ConcreteCategory.{max v u} D] +variable [HasForget.{max v u} D] variable [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] /-- An auxiliary definition to be used in the proof that `J.plusFunctor D` commutes @@ -227,7 +227,7 @@ section variable {D : Type w} [Category.{max v u} D] variable [∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : J.Cover X), HasMultiequalizer (S.index P)] variable [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] -variable [ConcreteCategory.{max v u} D] +variable [HasForget.{max v u} D] variable [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] variable [PreservesLimits (forget D)] variable [(forget D).ReflectsIsomorphisms] diff --git a/Mathlib/CategoryTheory/Sites/LocallyBijective.lean b/Mathlib/CategoryTheory/Sites/LocallyBijective.lean index fdf1758f20af6..8aabfc21cb4d4 100644 --- a/Mathlib/CategoryTheory/Sites/LocallyBijective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallyBijective.lean @@ -24,7 +24,7 @@ universe w' w v' v u' u namespace CategoryTheory variable {C : Type u} [Category.{v} C] {J : GrothendieckTopology C} - {A : Type u'} [Category.{v'} A] [ConcreteCategory.{w} A] + {A : Type u'} [Category.{v'} A] [HasForget.{w} A] namespace Sheaf @@ -144,7 +144,7 @@ lemma WEqualsLocallyBijective.mk' [HasWeakSheafify J A] [(forget A).ReflectsIsom CategoryTheory.toSheafify_naturality, Presheaf.comp_isLocallyInjective_iff, Presheaf.comp_isLocallySurjective_iff] -instance {D : Type w} [Category.{w'} D] [ConcreteCategory.{max u v} D] +instance {D : Type w} [Category.{w'} D] [HasForget.{max u v} D] [HasWeakSheafify J D] [J.HasSheafCompose (forget D)] [J.PreservesSheafification (forget D)] [(forget D).ReflectsIsomorphisms] : J.WEqualsLocallyBijective D := by diff --git a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean index 1d17353edb606..64b1d4140a669 100644 --- a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean @@ -29,10 +29,10 @@ namespace CategoryTheory open Opposite Limits variable {C : Type u} [Category.{v} C] - {D : Type u'} [Category.{v'} D] [ConcreteCategory.{w} D] + {D : Type u'} [Category.{v'} D] [HasForget.{w} D] (J : GrothendieckTopology C) -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike namespace Presheaf @@ -189,7 +189,7 @@ instance isLocallyInjective_toSheafify (P : Cᵒᵖ ⥤ Type max u v) : rw [GrothendieckTopology.plusMap_toPlus] infer_instance -instance isLocallyInjective_toSheafify' [ConcreteCategory.{max u v} D] +instance isLocallyInjective_toSheafify' [HasForget.{max u v} D] (P : Cᵒᵖ ⥤ D) [HasWeakSheafify J D] [J.HasSheafCompose (forget D)] [J.PreservesSheafification (forget D)] : IsLocallyInjective J (toSheafify J P) := by diff --git a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean index 289d2db4e05a6..e3c5a1393050f 100644 --- a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean @@ -33,9 +33,9 @@ namespace CategoryTheory variable {C : Type u} [Category.{v} C] (J : GrothendieckTopology C) -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike -variable {A : Type u'} [Category.{v'} A] [ConcreteCategory.{w'} A] +variable {A : Type u'} [Category.{v'} A] [HasForget.{w'} A] namespace Presheaf @@ -295,7 +295,7 @@ instance isLocallySurjective_toSheafify (P : Cᵒᵖ ⥤ Type max u v) : infer_instance instance isLocallySurjective_toSheafify' {D : Type*} [Category D] - [ConcreteCategory.{max u v} D] + [HasForget.{max u v} D] (P : Cᵒᵖ ⥤ D) [HasWeakSheafify J D] [J.HasSheafCompose (forget D)] [J.PreservesSheafification (forget D)] : IsLocallySurjective J (toSheafify J P) := by diff --git a/Mathlib/CategoryTheory/Sites/PreservesLocallyBijective.lean b/Mathlib/CategoryTheory/Sites/PreservesLocallyBijective.lean index ab499ecc7dfde..72b3eac6a2cc6 100644 --- a/Mathlib/CategoryTheory/Sites/PreservesLocallyBijective.lean +++ b/Mathlib/CategoryTheory/Sites/PreservesLocallyBijective.lean @@ -24,7 +24,7 @@ namespace CategoryTheory namespace Presheaf -variable [ConcreteCategory A] +variable [HasForget A] lemma isLocallyInjective_whisker [H.IsCocontinuous J K] [IsLocallyInjective K f] : IsLocallyInjective J (whiskerLeft H.op f) where diff --git a/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean b/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean index 2c7a0002cec28..203998c2c2073 100644 --- a/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean @@ -249,7 +249,7 @@ variable {D E : Type*} [Category.{max v u} D] [Category.{max v u} E] (F : D ⥤ [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ E] [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ F] [∀ (X : C) (W : J.Cover X) (P : Cᵒᵖ ⥤ D), PreservesLimit (W.index P).multicospan F] - [ConcreteCategory D] [ConcreteCategory E] + [HasForget D] [HasForget E] [∀ X, PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)] [∀ X, PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget E)] [PreservesLimits (forget D)] [PreservesLimits (forget E)] @@ -285,7 +285,7 @@ instance : PreservesSheafification J F := by end example {D : Type*} [Category.{max v u} D] - [ConcreteCategory.{max v u} D] [PreservesLimits (forget D)] + [HasForget.{max v u} D] [PreservesLimits (forget D)] [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] [∀ (α β : Type max u v) (fst snd : β → α), diff --git a/Mathlib/CategoryTheory/Sites/Pullback.lean b/Mathlib/CategoryTheory/Sites/Pullback.lean index 26b39bd096bdb..948dacbcb247d 100644 --- a/Mathlib/CategoryTheory/Sites/Pullback.lean +++ b/Mathlib/CategoryTheory/Sites/Pullback.lean @@ -105,7 +105,7 @@ variable {C : Type v₁} [SmallCategory C] {D : Type v₁} [SmallCategory D] (G (J : GrothendieckTopology C) (K : GrothendieckTopology D) -- The favourable assumptions under which we have sheafification -variable [ConcreteCategory.{v₁} A] [PreservesLimits (forget A)] [HasColimits A] [HasLimits A] +variable [HasForget.{v₁} A] [PreservesLimits (forget A)] [HasColimits A] [HasLimits A] [PreservesFilteredColimits (forget A)] [(forget A).ReflectsIsomorphisms] [Functor.IsContinuous.{v₁} G J K] diff --git a/Mathlib/CategoryTheory/Sites/Sheaf.lean b/Mathlib/CategoryTheory/Sites/Sheaf.lean index 04835ed2104f8..6f528a0d3f6a1 100644 --- a/Mathlib/CategoryTheory/Sites/Sheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Sheaf.lean @@ -75,10 +75,10 @@ https://stacks.math.columbia.edu/tag/00VR def IsSheaf (P : Cᵒᵖ ⥤ A) : Prop := ∀ E : A, Presieve.IsSheaf J (P ⋙ coyoneda.obj (op E)) -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike in +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike in /-- Condition that a presheaf with values in a concrete category is separated for a Grothendieck topology. -/ -def IsSeparated (P : Cᵒᵖ ⥤ A) [ConcreteCategory A] : Prop := +def IsSeparated (P : Cᵒᵖ ⥤ A) [HasForget A] : Prop := ∀ (X : C) (S : Sieve X) (_ : S ∈ J X) (x y : P.obj (op X)), (∀ (Y : C) (f : Y ⟶ X) (_ : S f), P.map f.op x = P.map f.op y) → x = y diff --git a/Mathlib/CategoryTheory/Sites/Whiskering.lean b/Mathlib/CategoryTheory/Sites/Whiskering.lean index 5f9c74a7af9c3..0a04e2a0627c2 100644 --- a/Mathlib/CategoryTheory/Sites/Whiskering.lean +++ b/Mathlib/CategoryTheory/Sites/Whiskering.lean @@ -141,13 +141,13 @@ instance hasSheafCompose_of_preservesLimitsOfSize [PreservesLimitsOfSize.{v₁, variable {J} -lemma Sheaf.isSeparated [ConcreteCategory A] [J.HasSheafCompose (forget A)] +lemma Sheaf.isSeparated [HasForget A] [J.HasSheafCompose (forget A)] (F : Sheaf J A) : Presheaf.IsSeparated J F.val := by rintro X S hS x y h exact (Presieve.isSeparated_of_isSheaf _ _ ((isSheaf_iff_isSheaf_of_type _ _).1 ((sheafCompose J (forget A)).obj F).2) S hS).ext (fun _ _ hf => h _ _ hf) -lemma Presheaf.IsSheaf.isSeparated {F : Cᵒᵖ ⥤ A} [ConcreteCategory A] +lemma Presheaf.IsSheaf.isSeparated {F : Cᵒᵖ ⥤ A} [HasForget A] [J.HasSheafCompose (forget A)] (hF : Presheaf.IsSheaf J F) : Presheaf.IsSeparated J F := Sheaf.isSeparated ⟨F, hF⟩ diff --git a/Mathlib/Condensed/Discrete/Characterization.lean b/Mathlib/Condensed/Discrete/Characterization.lean index 2a4d5db7d2127..166add8efd026 100644 --- a/Mathlib/Condensed/Discrete/Characterization.lean +++ b/Mathlib/Condensed/Discrete/Characterization.lean @@ -33,7 +33,7 @@ universe u open CategoryTheory Limits Functor FintypeCat -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace Condensed diff --git a/Mathlib/Condensed/Discrete/Colimit.lean b/Mathlib/Condensed/Discrete/Colimit.lean index b991d411c5c9a..fd62250dd9340 100644 --- a/Mathlib/Condensed/Discrete/Colimit.lean +++ b/Mathlib/Condensed/Discrete/Colimit.lean @@ -21,7 +21,7 @@ noncomputable section open CategoryTheory Functor Limits FintypeCat CompHausLike.LocallyConstant -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace Condensed diff --git a/Mathlib/Condensed/Discrete/LocallyConstant.lean b/Mathlib/Condensed/Discrete/LocallyConstant.lean index 40b0e6e7d03a9..bec3c4eba5068 100644 --- a/Mathlib/Condensed/Discrete/LocallyConstant.lean +++ b/Mathlib/Condensed/Discrete/LocallyConstant.lean @@ -69,7 +69,7 @@ universe u w open CategoryTheory Limits LocallyConstant TopologicalSpace.Fiber Opposite Function Fiber -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike variable {P : TopCat.{u} → Prop} diff --git a/Mathlib/Condensed/Discrete/Module.lean b/Mathlib/Condensed/Discrete/Module.lean index 75760ce80c094..79c0f44b9350d 100644 --- a/Mathlib/Condensed/Discrete/Module.lean +++ b/Mathlib/Condensed/Discrete/Module.lean @@ -24,7 +24,7 @@ universe w u open CategoryTheory LocallyConstant CompHausLike Functor Category Functor Opposite -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike variable {P : TopCat.{u} → Prop} diff --git a/Mathlib/Condensed/Epi.lean b/Mathlib/Condensed/Epi.lean index 2b558cdb9c975..b7275b79b38c1 100644 --- a/Mathlib/Condensed/Epi.lean +++ b/Mathlib/Condensed/Epi.lean @@ -21,11 +21,11 @@ universe v u w u' v' open CategoryTheory Sheaf Opposite Limits Condensed ConcreteCategory -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike namespace Condensed -variable (A : Type u') [Category.{v'} A] [ConcreteCategory.{v'} A] +variable (A : Type u') [Category.{v'} A] [HasForget.{v'} A] [HasFunctorialSurjectiveInjectiveFactorization A] variable {X Y : Condensed.{u} A} (f : X ⟶ Y) diff --git a/Mathlib/Condensed/Explicit.lean b/Mathlib/Condensed/Explicit.lean index 2efdfa8599be7..e85295d2c9160 100644 --- a/Mathlib/Condensed/Explicit.lean +++ b/Mathlib/Condensed/Explicit.lean @@ -54,7 +54,7 @@ forgetful functor preserves finite products. -/ noncomputable def ofSheafForgetStonean [∀ X, HasLimitsOfShape (StructuredArrow X Stonean.toCompHaus.op) A] - [ConcreteCategory A] [ReflectsFiniteProducts (CategoryTheory.forget A)] + [HasForget A] [ReflectsFiniteProducts (CategoryTheory.forget A)] (F : Stonean.{u}ᵒᵖ ⥤ A) [PreservesFiniteProducts (F ⋙ CategoryTheory.forget A)] : Condensed A := StoneanCompHaus.equivalence A |>.functor.obj { @@ -84,7 +84,7 @@ forgetful functor preserves finite products and satisfies the equalizer conditio -/ noncomputable def ofSheafForgetProfinite [∀ X, HasLimitsOfShape (StructuredArrow X profiniteToCompHaus.op) A] - [ConcreteCategory A] [ReflectsFiniteLimits (CategoryTheory.forget A)] + [HasForget A] [ReflectsFiniteLimits (CategoryTheory.forget A)] (F : Profinite.{u}ᵒᵖ ⥤ A) [PreservesFiniteProducts (F ⋙ CategoryTheory.forget A)] (hF : EqualizerCondition (F ⋙ CategoryTheory.forget A)) : Condensed A := @@ -112,7 +112,7 @@ The condensed object associated to a presheaf on `CompHaus` whose postcompositio forgetful functor preserves finite products and satisfies the equalizer condition. -/ noncomputable def ofSheafForgetCompHaus - [ConcreteCategory A] [ReflectsFiniteLimits (CategoryTheory.forget A)] + [HasForget A] [ReflectsFiniteLimits (CategoryTheory.forget A)] (F : CompHaus.{u}ᵒᵖ ⥤ A) [PreservesFiniteProducts (F ⋙ CategoryTheory.forget A)] (hF : EqualizerCondition (F ⋙ CategoryTheory.forget A)) : Condensed A where val := F diff --git a/Mathlib/Condensed/Light/Epi.lean b/Mathlib/Condensed/Light/Epi.lean index 795f7e9165f4b..5f757b75530ca 100644 --- a/Mathlib/Condensed/Light/Epi.lean +++ b/Mathlib/Condensed/Light/Epi.lean @@ -19,13 +19,13 @@ Further, we prove that the functor `lim : Discrete ℕ ⥤ LightCondMod R` prese universe v u w u' v' -open CategoryTheory Sheaf Limits ConcreteCategory GrothendieckTopology +open CategoryTheory Sheaf Limits HasForget GrothendieckTopology -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike namespace LightCondensed -variable (A : Type u') [Category.{v'} A] [ConcreteCategory.{w} A] +variable (A : Type u') [Category.{v'} A] [HasForget.{w} A] [PreservesFiniteProducts (CategoryTheory.forget A)] variable {X Y : LightCondensed.{u} A} (f : X ⟶ Y) diff --git a/Mathlib/Condensed/Light/Explicit.lean b/Mathlib/Condensed/Light/Explicit.lean index 1c5823f86695f..d983a56789754 100644 --- a/Mathlib/Condensed/Light/Explicit.lean +++ b/Mathlib/Condensed/Light/Explicit.lean @@ -50,7 +50,7 @@ the forgetful functor preserves finite products and satisfies the equalizer cond -/ @[simps] noncomputable def ofSheafForgetLightProfinite - [ConcreteCategory A] [ReflectsFiniteLimits (CategoryTheory.forget A)] + [HasForget A] [ReflectsFiniteLimits (CategoryTheory.forget A)] (F : LightProfinite.{u}ᵒᵖ ⥤ A) [PreservesFiniteProducts (F ⋙ CategoryTheory.forget A)] (hF : EqualizerCondition (F ⋙ CategoryTheory.forget A)) : LightCondensed A where val := F diff --git a/Mathlib/Condensed/Light/TopCatAdjunction.lean b/Mathlib/Condensed/Light/TopCatAdjunction.lean index 3be36032d682c..2201055ab0ffc 100644 --- a/Mathlib/Condensed/Light/TopCatAdjunction.lean +++ b/Mathlib/Condensed/Light/TopCatAdjunction.lean @@ -22,7 +22,7 @@ universe u open LightCondensed LightCondSet CategoryTheory LightProfinite -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace LightCondSet diff --git a/Mathlib/Condensed/TopCatAdjunction.lean b/Mathlib/Condensed/TopCatAdjunction.lean index b29f668f98484..af00f6cd79179 100644 --- a/Mathlib/Condensed/TopCatAdjunction.lean +++ b/Mathlib/Condensed/TopCatAdjunction.lean @@ -21,7 +21,7 @@ universe u open Condensed CondensedSet CategoryTheory CompHaus -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike variable (X : CondensedSet.{u}) diff --git a/Mathlib/Condensed/TopComparison.lean b/Mathlib/Condensed/TopComparison.lean index aea4064452d23..b849bc48d6588 100644 --- a/Mathlib/Condensed/TopComparison.lean +++ b/Mathlib/Condensed/TopComparison.lean @@ -25,7 +25,7 @@ universe w w' v u open CategoryTheory Opposite Limits regularTopology ContinuousMap Topology -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike variable {C : Type u} [Category.{v} C] (G : C ⥤ TopCat.{w}) (X : Type w') [TopologicalSpace X] diff --git a/Mathlib/Geometry/RingedSpace/Basic.lean b/Mathlib/Geometry/RingedSpace/Basic.lean index 69d6ef0396197..8b7da6e28f7cc 100644 --- a/Mathlib/Geometry/RingedSpace/Basic.lean +++ b/Mathlib/Geometry/RingedSpace/Basic.lean @@ -95,7 +95,7 @@ theorem isUnit_res_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) (x : /-- Specialize `TopCat.Presheaf.germ_res_apply` to sheaves of rings. This is unfortunately needed because the results on presheaves are stated using the -`ConcreteCategory.instFunLike` instance, which is not reducibly equal to the actual coercion of +`HasForget.instFunLike` instance, which is not reducibly equal to the actual coercion of morphisms in `CommRingCat` to functions. -/ lemma _root_.CommRingCat.germ_res_apply @@ -107,7 +107,7 @@ lemma _root_.CommRingCat.germ_res_apply /-- Specialize `TopCat.Presheaf.germ_res_apply'` to sheaves of rings. This is unfortunately needed because the results on presheaves are stated using the -`ConcreteCategory.instFunLike` instance, which is not reducibly equal to the actual coercion of +`HasForget.instFunLike` instance, which is not reducibly equal to the actual coercion of morphisms in `CommRingCat` to functions. -/ lemma _root_.CommRingCat.germ_res_apply' @@ -149,13 +149,13 @@ theorem isUnit_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) congr_arg (X.presheaf.germ (V y) z hzVy) (hg y), RingHom.map_one, RingHom.map_one] -- We claim that these local inverses glue together to a global inverse of `f`. obtain ⟨gl, gl_spec, -⟩ : - -- We need to rephrase the result from `ConcreteCategory` to `CommRingCat`. + -- We need to rephrase the result from `HasForget` to `CommRingCat`. ∃ gl : X.presheaf.obj (op U), (∀ i, ((sheaf X).val.map (iVU i).op) gl = g i) ∧ _ := X.sheaf.existsUnique_gluing' V U iVU hcover g ic apply isUnit_of_mul_eq_one f gl apply X.sheaf.eq_of_locally_eq' V U iVU hcover intro i - -- We need to rephrase the goal from `ConcreteCategory` to `CommRingCat`. + -- We need to rephrase the goal from `HasForget` to `CommRingCat`. show ((sheaf X).val.map (iVU i).op).hom (f * gl) = ((sheaf X).val.map (iVU i).op) 1 rw [RingHom.map_one, RingHom.map_mul, gl_spec] exact hg i diff --git a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean index 844ba7dddb0bc..aa63a2c5e4a93 100644 --- a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean +++ b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean @@ -718,7 +718,7 @@ end Pullback section OfStalkIso -variable [HasLimits C] [HasColimits C] [ConcreteCategory C] +variable [HasLimits C] [HasColimits C] [HasForget C] variable [(CategoryTheory.forget C).ReflectsIsomorphisms] [PreservesLimits (CategoryTheory.forget C)] diff --git a/Mathlib/Geometry/RingedSpace/SheafedSpace.lean b/Mathlib/Geometry/RingedSpace/SheafedSpace.lean index 1941ecd8cc471..70c3af7906587 100644 --- a/Mathlib/Geometry/RingedSpace/SheafedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/SheafedSpace.lean @@ -209,14 +209,14 @@ instance [HasLimits C] : HasColimits.{v} (SheafedSpace C) := noncomputable instance [HasLimits C] : PreservesColimits (forget.{_, _, v} C) := Limits.comp_preservesColimits forgetToPresheafedSpace (PresheafedSpace.forget C) -section ConcreteCategory +section HasForget -variable [ConcreteCategory.{v} C] [HasColimits C] [HasLimits C] +variable [HasForget.{v} C] [HasColimits C] [HasLimits C] variable [PreservesLimits (CategoryTheory.forget C)] variable [PreservesFilteredColimits (CategoryTheory.forget C)] variable [(CategoryTheory.forget C).ReflectsIsomorphisms] -attribute [local instance] ConcreteCategory.instFunLike in +attribute [local instance] HasForget.instFunLike in lemma hom_stalk_ext {X Y : SheafedSpace C} (f g : X ⟶ Y) (h : f.base = g.base) (h' : ∀ x, f.stalkMap x = (Y.presheaf.stalkCongr (h ▸ rfl)).hom ≫ g.stalkMap x) : f = g := by @@ -241,7 +241,7 @@ lemma mono_of_base_injective_of_stalk_epi {X Y : SheafedSpace C} (f : X ⟶ Y) ← PresheafedSpace.stalkMap.comp ⟨g, gc⟩ f, ← PresheafedSpace.stalkMap.comp ⟨g, hc⟩ f] congr 1 -end ConcreteCategory +end HasForget end SheafedSpace diff --git a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean index 5d6cf88a2bfcf..706844a3674d9 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean @@ -80,7 +80,7 @@ abbrev ofHom {X : Type v} [AddCommGroup X] [Module R X] Hom.toIsometry (𝟙 M) = Isometry.id _ := rfl -instance concreteCategory : ConcreteCategory.{v} (QuadraticModuleCat.{v} R) where +instance hasForget : HasForget.{v} (QuadraticModuleCat.{v} R) where forget := { obj := fun M => M map := fun f => f.toIsometry } diff --git a/Mathlib/MeasureTheory/Category/MeasCat.lean b/Mathlib/MeasureTheory/Category/MeasCat.lean index da8d44535068f..1d461ae522957 100644 --- a/Mathlib/MeasureTheory/Category/MeasCat.lean +++ b/Mathlib/MeasureTheory/Category/MeasCat.lean @@ -61,9 +61,9 @@ instance unbundledHom : UnbundledHom @Measurable := deriving instance LargeCategory for MeasCat --- Porting note: `deriving instance ConcreteCategory for MeasCat` didn't work. Define it manually. +-- Porting note: `deriving instance HasForget for MeasCat` didn't work. Define it manually. -- see https://github.com/leanprover-community/mathlib4/issues/5020 -instance : ConcreteCategory MeasCat := by +instance : HasForget MeasCat := by unfold MeasCat infer_instance @@ -71,7 +71,7 @@ instance : Inhabited MeasCat := ⟨MeasCat.of Empty⟩ -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike /-- `Measure X` is the measurable space of measures over the measurable space `X`. It is the weakest measurable space, s.t. `fun μ ↦ μ s` is measurable for all measurable sets `s` in `X`. An diff --git a/Mathlib/Order/Category/BddDistLat.lean b/Mathlib/Order/Category/BddDistLat.lean index 3ead1db99b5ec..6fd1e4b52372a 100644 --- a/Mathlib/Order/Category/BddDistLat.lean +++ b/Mathlib/Order/Category/BddDistLat.lean @@ -60,8 +60,8 @@ theorem coe_toBddLat (X : BddDistLat) : ↥X.toBddLat = ↥X := instance : LargeCategory.{u} BddDistLat := InducedCategory.category toBddLat -instance : ConcreteCategory BddDistLat := - InducedCategory.concreteCategory toBddLat +instance : HasForget BddDistLat := + InducedCategory.hasForget toBddLat instance hasForgetToDistLat : HasForget₂ BddDistLat DistLat where forget₂ := diff --git a/Mathlib/Order/Category/BddLat.lean b/Mathlib/Order/Category/BddLat.lean index b1f4e2931ddcb..994a24252c635 100644 --- a/Mathlib/Order/Category/BddLat.lean +++ b/Mathlib/Order/Category/BddLat.lean @@ -62,7 +62,7 @@ instance : LargeCategory.{u} BddLat where instance instFunLike (X Y : BddLat) : FunLike (X ⟶ Y) X Y := show FunLike (BoundedLatticeHom X Y) X Y from inferInstance -instance : ConcreteCategory BddLat where +instance : HasForget BddLat where forget := { obj := (↑) map := DFunLike.coe } diff --git a/Mathlib/Order/Category/BddOrd.lean b/Mathlib/Order/Category/BddOrd.lean index 89e1c988b0e68..68517e584cc17 100644 --- a/Mathlib/Order/Category/BddOrd.lean +++ b/Mathlib/Order/Category/BddOrd.lean @@ -59,7 +59,7 @@ instance largeCategory : LargeCategory.{u} BddOrd where instance instFunLike (X Y : BddOrd) : FunLike (X ⟶ Y) X Y := show FunLike (BoundedOrderHom X Y) X Y from inferInstance -instance concreteCategory : ConcreteCategory BddOrd where +instance hasForget : HasForget BddOrd where forget := { obj := (↥) map := DFunLike.coe } diff --git a/Mathlib/Order/Category/BoolAlg.lean b/Mathlib/Order/Category/BoolAlg.lean index 42c66fcc0c103..0bd412bf4a34f 100644 --- a/Mathlib/Order/Category/BoolAlg.lean +++ b/Mathlib/Order/Category/BoolAlg.lean @@ -53,8 +53,8 @@ theorem coe_toBddDistLat (X : BoolAlg) : ↥X.toBddDistLat = ↥X := instance : LargeCategory.{u} BoolAlg := InducedCategory.category toBddDistLat -instance : ConcreteCategory BoolAlg := - InducedCategory.concreteCategory toBddDistLat +instance : HasForget BoolAlg := + InducedCategory.hasForget toBddDistLat instance hasForgetToBddDistLat : HasForget₂ BoolAlg BddDistLat := InducedCategory.hasForget₂ toBddDistLat diff --git a/Mathlib/Order/Category/CompleteLat.lean b/Mathlib/Order/Category/CompleteLat.lean index fb66ec48a2763..7adccbb995f29 100644 --- a/Mathlib/Order/Category/CompleteLat.lean +++ b/Mathlib/Order/Category/CompleteLat.lean @@ -48,7 +48,7 @@ instance : BundledHom @CompleteLatticeHom where deriving instance LargeCategory for CompleteLat -instance : ConcreteCategory CompleteLat := by +instance : HasForget CompleteLat := by dsimp [CompleteLat]; infer_instance instance hasForgetToBddLat : HasForget₂ CompleteLat BddLat where diff --git a/Mathlib/Order/Category/DistLat.lean b/Mathlib/Order/Category/DistLat.lean index 94f1ecb564b71..89af39157e717 100644 --- a/Mathlib/Order/Category/DistLat.lean +++ b/Mathlib/Order/Category/DistLat.lean @@ -49,8 +49,8 @@ instance : BundledHom.ParentProjection @DistribLattice.toLattice := deriving instance LargeCategory for DistLat -instance : ConcreteCategory DistLat := - BundledHom.concreteCategory _ +instance : HasForget DistLat := + BundledHom.hasForget _ instance hasForgetToLat : HasForget₂ DistLat Lat := BundledHom.forget₂ _ _ diff --git a/Mathlib/Order/Category/FinBddDistLat.lean b/Mathlib/Order/Category/FinBddDistLat.lean index 0747d3df364a1..c488f859a3c76 100644 --- a/Mathlib/Order/Category/FinBddDistLat.lean +++ b/Mathlib/Order/Category/FinBddDistLat.lean @@ -56,8 +56,8 @@ instance : Inhabited FinBddDistLat := instance largeCategory : LargeCategory FinBddDistLat := InducedCategory.category toBddDistLat -instance concreteCategory : ConcreteCategory FinBddDistLat := - InducedCategory.concreteCategory toBddDistLat +instance hasForget : HasForget FinBddDistLat := + InducedCategory.hasForget toBddDistLat instance hasForgetToBddDistLat : HasForget₂ FinBddDistLat BddDistLat := InducedCategory.hasForget₂ FinBddDistLat.toBddDistLat diff --git a/Mathlib/Order/Category/FinBoolAlg.lean b/Mathlib/Order/Category/FinBoolAlg.lean index 58791b31ec741..9b88f6be50b09 100644 --- a/Mathlib/Order/Category/FinBoolAlg.lean +++ b/Mathlib/Order/Category/FinBoolAlg.lean @@ -66,8 +66,8 @@ instance : Inhabited FinBoolAlg := instance largeCategory : LargeCategory FinBoolAlg := InducedCategory.category FinBoolAlg.toBoolAlg -instance concreteCategory : ConcreteCategory FinBoolAlg := - InducedCategory.concreteCategory FinBoolAlg.toBoolAlg +instance hasForget : HasForget FinBoolAlg := + InducedCategory.hasForget FinBoolAlg.toBoolAlg instance instFunLike {X Y : FinBoolAlg} : FunLike (X ⟶ Y) X Y := BoundedLatticeHom.instFunLike diff --git a/Mathlib/Order/Category/FinPartOrd.lean b/Mathlib/Order/Category/FinPartOrd.lean index e520e1b739927..58d87401fa722 100644 --- a/Mathlib/Order/Category/FinPartOrd.lean +++ b/Mathlib/Order/Category/FinPartOrd.lean @@ -55,8 +55,8 @@ instance : Inhabited FinPartOrd := instance largeCategory : LargeCategory FinPartOrd := InducedCategory.category FinPartOrd.toPartOrd -instance concreteCategory : ConcreteCategory FinPartOrd := - InducedCategory.concreteCategory FinPartOrd.toPartOrd +instance hasForget : HasForget FinPartOrd := + InducedCategory.hasForget FinPartOrd.toPartOrd instance hasForgetToPartOrd : HasForget₂ FinPartOrd PartOrd := InducedCategory.hasForget₂ FinPartOrd.toPartOrd diff --git a/Mathlib/Order/Category/Frm.lean b/Mathlib/Order/Category/Frm.lean index 53f71706b0dc2..eb995e669ca48 100644 --- a/Mathlib/Order/Category/Frm.lean +++ b/Mathlib/Order/Category/Frm.lean @@ -56,11 +56,11 @@ instance bundledHom : BundledHom Hom where comp _ _ _ := FrameHom.comp hom_ext _ _ := DFunLike.coe_injective --- Porting note: Originally `deriving instance LargeCategory, ConcreteCategory for Frm` +-- Porting note: Originally `deriving instance LargeCategory, HasForget for Frm` -- see https://github.com/leanprover-community/mathlib4/issues/5020 deriving instance LargeCategory, Category for Frm -instance : ConcreteCategory Frm := by +instance : HasForget Frm := by unfold Frm infer_instance diff --git a/Mathlib/Order/Category/HeytAlg.lean b/Mathlib/Order/Category/HeytAlg.lean index d22ca239af421..6551ec391871b 100644 --- a/Mathlib/Order/Category/HeytAlg.lean +++ b/Mathlib/Order/Category/HeytAlg.lean @@ -50,7 +50,7 @@ deriving instance LargeCategory for HeytAlg -- Porting note: deriving failed. -- see https://github.com/leanprover-community/mathlib4/issues/5020 -instance : ConcreteCategory HeytAlg := by +instance : HasForget HeytAlg := by dsimp [HeytAlg] infer_instance diff --git a/Mathlib/Order/Category/Lat.lean b/Mathlib/Order/Category/Lat.lean index facad429e2002..9a3c1b735ba3c 100644 --- a/Mathlib/Order/Category/Lat.lean +++ b/Mathlib/Order/Category/Lat.lean @@ -57,8 +57,8 @@ instance : BundledHom @LatticeHom where instance : LargeCategory.{u} Lat := BundledHom.category LatticeHom -instance : ConcreteCategory Lat := - BundledHom.concreteCategory LatticeHom +instance : HasForget Lat := + BundledHom.hasForget LatticeHom instance hasForgetToPartOrd : HasForget₂ Lat PartOrd where forget₂ := diff --git a/Mathlib/Order/Category/LinOrd.lean b/Mathlib/Order/Category/LinOrd.lean index 8230540a0e9d0..e601d73f5d798 100644 --- a/Mathlib/Order/Category/LinOrd.lean +++ b/Mathlib/Order/Category/LinOrd.lean @@ -28,8 +28,8 @@ instance : BundledHom.ParentProjection @LinearOrder.toPartialOrder := deriving instance LargeCategory for LinOrd -- Porting note: Probably see https://github.com/leanprover-community/mathlib4/issues/5020 -instance : ConcreteCategory LinOrd := - BundledHom.concreteCategory _ +instance : HasForget LinOrd := + BundledHom.hasForget _ instance : CoeSort LinOrd Type* := Bundled.coeSort diff --git a/Mathlib/Order/Category/NonemptyFinLinOrd.lean b/Mathlib/Order/Category/NonemptyFinLinOrd.lean index ea21848f75410..b403f4df16856 100644 --- a/Mathlib/Order/Category/NonemptyFinLinOrd.lean +++ b/Mathlib/Order/Category/NonemptyFinLinOrd.lean @@ -59,8 +59,8 @@ instance : BundledHom.ParentProjection @NonemptyFiniteLinearOrder.toLinearOrder deriving instance LargeCategory for NonemptyFinLinOrd -- Porting note: probably see https://github.com/leanprover-community/mathlib4/issues/5020 -instance : ConcreteCategory NonemptyFinLinOrd := - BundledHom.concreteCategory _ +instance : HasForget NonemptyFinLinOrd := + BundledHom.hasForget _ instance : CoeSort NonemptyFinLinOrd Type* := Bundled.coeSort diff --git a/Mathlib/Order/Category/OmegaCompletePartialOrder.lean b/Mathlib/Order/Category/OmegaCompletePartialOrder.lean index 892d3d21f91b0..b0ec15ae5e8ec 100644 --- a/Mathlib/Order/Category/OmegaCompletePartialOrder.lean +++ b/Mathlib/Order/Category/OmegaCompletePartialOrder.lean @@ -19,7 +19,7 @@ an `OmegaCompletePartialOrder`. ## Main definitions * `ωCPO` - * an instance of `Category` and `ConcreteCategory` + * an instance of `Category` and `HasForget` -/ @@ -43,9 +43,9 @@ instance : BundledHom @ContinuousHom where comp := @ContinuousHom.comp hom_ext := @ContinuousHom.coe_inj --- Porting note: `deriving instance ConcreteCategory` didn't work. +-- Porting note: `deriving instance HasForget` didn't work. deriving instance LargeCategory for ωCPO -instance : ConcreteCategory ωCPO := by unfold ωCPO; infer_instance +instance : HasForget ωCPO := by unfold ωCPO; infer_instance instance : CoeSort ωCPO Type* := Bundled.coeSort diff --git a/Mathlib/Order/Category/PartOrd.lean b/Mathlib/Order/Category/PartOrd.lean index 7dde2cff81348..a771fa86e51d7 100644 --- a/Mathlib/Order/Category/PartOrd.lean +++ b/Mathlib/Order/Category/PartOrd.lean @@ -30,8 +30,8 @@ instance : BundledHom.ParentProjection @PartialOrder.toPreorder := deriving instance LargeCategory for PartOrd -- Porting note: probably see https://github.com/leanprover-community/mathlib4/issues/5020 -instance : ConcreteCategory PartOrd := - BundledHom.concreteCategory _ +instance : HasForget PartOrd := + BundledHom.hasForget _ instance : CoeSort PartOrd Type* := Bundled.coeSort diff --git a/Mathlib/Order/Category/Preord.lean b/Mathlib/Order/Category/Preord.lean index 128b690d6c380..cb92c9fb39d9a 100644 --- a/Mathlib/Order/Category/Preord.lean +++ b/Mathlib/Order/Category/Preord.lean @@ -35,8 +35,8 @@ instance : BundledHom @OrderHom where deriving instance LargeCategory for Preord -- Porting note: probably see https://github.com/leanprover-community/mathlib4/issues/5020 -instance : ConcreteCategory Preord := - BundledHom.concreteCategory _ +instance : HasForget Preord := + BundledHom.hasForget _ instance : CoeSort Preord Type* := Bundled.coeSort diff --git a/Mathlib/Order/Category/Semilat.lean b/Mathlib/Order/Category/Semilat.lean index c1fb5d0c10a9b..e1a9193a66004 100644 --- a/Mathlib/Order/Category/Semilat.lean +++ b/Mathlib/Order/Category/Semilat.lean @@ -67,7 +67,7 @@ instance : LargeCategory.{u} SemilatSupCat where instance instFunLike (X Y : SemilatSupCat) : FunLike (X ⟶ Y) X Y := show FunLike (SupBotHom X Y) X Y from inferInstance -instance : ConcreteCategory SemilatSupCat where +instance : HasForget SemilatSupCat where forget := { obj := SemilatSupCat.X map := DFunLike.coe } @@ -117,7 +117,7 @@ instance : LargeCategory.{u} SemilatInfCat where instance instFunLike (X Y : SemilatInfCat) : FunLike (X ⟶ Y) X Y := show FunLike (InfTopHom X Y) X Y from inferInstance -instance : ConcreteCategory SemilatInfCat where +instance : HasForget SemilatInfCat where forget := { obj := SemilatInfCat.X map := DFunLike.coe } diff --git a/Mathlib/RepresentationTheory/FDRep.lean b/Mathlib/RepresentationTheory/FDRep.lean index c3217c02d5c69..8eaedce3ed27a 100644 --- a/Mathlib/RepresentationTheory/FDRep.lean +++ b/Mathlib/RepresentationTheory/FDRep.lean @@ -57,14 +57,14 @@ variable {k G : Type u} [Field k] [Monoid G] -- Porting note: `@[derive]` didn't work for `FDRep`. Add the 4 instances here. instance : LargeCategory (FDRep k G) := inferInstance -instance : ConcreteCategory (FDRep k G) := inferInstance +instance : HasForget (FDRep k G) := inferInstance instance : Preadditive (FDRep k G) := inferInstance instance : HasFiniteLimits (FDRep k G) := inferInstance instance : Linear k (FDRep k G) := by infer_instance instance : CoeSort (FDRep k G) (Type u) := - ConcreteCategory.hasCoeToSort _ + HasForget.hasCoeToSort _ instance (V : FDRep k G) : AddCommGroup V := by change AddCommGroup ((forget₂ (FDRep k G) (FGModuleCat k)).obj V).obj; infer_instance diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index 4c2866323bf62..68e82a8670b12 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -48,7 +48,7 @@ section variable [Monoid G] instance : CoeSort (Rep k G) (Type u) := - ConcreteCategory.hasCoeToSort _ + HasForget.hasCoeToSort _ instance (V : Rep k G) : AddCommGroup V := by change AddCommGroup ((forget₂ (Rep k G) (ModuleCat k)).obj V); infer_instance diff --git a/Mathlib/Tactic/CategoryTheory/Elementwise.lean b/Mathlib/Tactic/CategoryTheory/Elementwise.lean index 656aab46bfe30..ff726b22fa41d 100644 --- a/Mathlib/Tactic/CategoryTheory/Elementwise.lean +++ b/Mathlib/Tactic/CategoryTheory/Elementwise.lean @@ -45,11 +45,11 @@ universe u theorem forall_congr_forget_Type (α : Type u) (p : α → Prop) : (∀ (x : (forget (Type u)).obj α), p x) ↔ ∀ (x : α), p x := Iff.rfl -attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort theorem forget_hom_Type (α β : Type u) (f : α ⟶ β) : DFunLike.coe f = f := rfl -theorem hom_elementwise {C : Type*} [Category C] [ConcreteCategory C] +theorem hom_elementwise {C : Type*} [Category C] [HasForget C] {X Y : C} {f g : X ⟶ Y} (h : f = g) (x : X) : f x = g x := by rw [h] end theorems @@ -67,11 +67,11 @@ def elementwiseThms : List Name := /-- Given an equation `f = g` between morphisms `X ⟶ Y` in a category `C` (possibly after a `∀` binder), produce the equation `∀ (x : X), f x = g x` or -`∀ [ConcreteCategory C] (x : X), f x = g x` as needed (after the `∀` binder), but +`∀ [HasForget C] (x : X), f x = g x` as needed (after the `∀` binder), but with compositions fully right associated and identities removed. Returns the proof of the new theorem along with (optionally) a new level metavariable -for the first universe parameter to `ConcreteCategory`. +for the first universe parameter to `HasForget`. The `simpSides` option controls whether to simplify both sides of the equality, for simpNF purposes. @@ -84,7 +84,7 @@ def elementwiseExpr (src : Name) (type pf : Expr) (simpSides := true) : -- First simplify using elementwise-specific lemmas let mut eqPf' ← simpType (simpOnlyNames elementwiseThms (config := { decide := false })) eqPf if (← inferType eqPf') == .const ``True [] then - throwError "elementwise lemma for {src} is trivial after applying ConcreteCategory \ + throwError "elementwise lemma for {src} is trivial after applying HasForget \ lemmas, which can be caused by how applications are unfolded. \ Using elementwise is unnecessary." if simpSides then @@ -115,16 +115,16 @@ where MetaM α := do let (C, instC) ← try extractCatInstance eqTy catch _ => throwError "elementwise expects equality of morphisms in a category" - -- First try being optimistic that there is already a ConcreteCategory instance. + -- First try being optimistic that there is already a HasForget instance. if let some eqPf' ← observing? (mkAppM ``hom_elementwise #[eqPf]) then k eqPf' none else -- That failed, so we need to introduce the instance, which takes creating - -- a fresh universe level for `ConcreteCategory`'s forgetful functor. + -- a fresh universe level for `HasForget`'s forgetful functor. let .app (.const ``Category [v, u]) _ ← inferType instC | throwError "internal error in elementwise" let w ← mkFreshLevelMVar - let cty : Expr := mkApp2 (.const ``ConcreteCategory [w, v, u]) C instC + let cty : Expr := mkApp2 (.const ``HasForget [w, v, u]) C instC withLocalDecl `inst .instImplicit cty fun cfvar => do let eqPf' ← mkAppM ``hom_elementwise #[eqPf] k eqPf' (some (w, cfvar)) @@ -143,7 +143,7 @@ private partial def mkUnusedName (names : List Name) (baseName : Name) : Name := loop 1 /-- The `elementwise` attribute can be added to a lemma proving an equation of morphisms, and it -creates a new lemma for a `ConcreteCategory` giving an equation with those morphisms applied +creates a new lemma for a `HasForget` giving an equation with those morphisms applied to some value. Syntax examples: @@ -165,16 +165,16 @@ produces ```lean lemma some_lemma_apply {C : Type*} [Category C] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (h : X ⟶ Z) (w : ...) - [ConcreteCategory C] (x : X) : g (f x) = h x := ... + [HasForget C] (x : X) : g (f x) = h x := ... ``` -Here `X` is being coerced to a type via `CategoryTheory.ConcreteCategory.hasCoeToSort` and -`f`, `g`, and `h` are being coerced to functions via `CategoryTheory.ConcreteCategory.hasCoeToFun`. +Here `X` is being coerced to a type via `CategoryTheory.HasForget.hasCoeToSort` and +`f`, `g`, and `h` are being coerced to functions via `CategoryTheory.HasForget.hasCoeToFun`. Further, we simplify the type using `CategoryTheory.coe_id : ((𝟙 X) : X → X) x = x` and `CategoryTheory.coe_comp : (f ≫ g) x = g (f x)`, replacing morphism composition with function composition. -The `[ConcreteCategory C]` argument will be omitted if it is possible to synthesize an instance. +The `[HasForget C]` argument will be omitted if it is possible to synthesize an instance. The name of the produced lemma can be specified with `@[elementwise other_lemma_name]`. If `simp` is added first, the generated lemma will also have the `simp` attribute. @@ -195,7 +195,7 @@ initialize registerBuiltinAttribute { let newLevels ← if let some level := level? then do let w := mkUnusedName levels `w unless ← isLevelDefEq level (mkLevelParam w) do - throwError "Could not create level parameter for ConcreteCategory instance" + throwError "Could not create level parameter for HasForget instance" pure <| w :: levels else pure levels @@ -215,8 +215,8 @@ example (M N K : MonCat) (f : M ⟶ N) (g : N ⟶ K) (h : M ⟶ K) (w : f ≫ g ``` In this case, `elementwise_of% w` generates the lemma `∀ (x : M), f (g x) = h x`. -Like the `@[elementwise]` attribute, `elementwise_of%` inserts a `ConcreteCategory` -instance argument if it can't synthesize a relevant `ConcreteCategory` instance. +Like the `@[elementwise]` attribute, `elementwise_of%` inserts a `HasForget` +instance argument if it can't synthesize a relevant `HasForget` instance. (Technical note: The forgetful functor's universe variable is instantiated with a fresh level metavariable in this case.) diff --git a/Mathlib/Tactic/Linter/GlobalAttributeIn.lean b/Mathlib/Tactic/Linter/GlobalAttributeIn.lean index 1599e047d00cf..fc651695cc6b0 100644 --- a/Mathlib/Tactic/Linter/GlobalAttributeIn.lean +++ b/Mathlib/Tactic/Linter/GlobalAttributeIn.lean @@ -21,11 +21,11 @@ hence, we lint against it. *Example*: before this was discovered, `Mathlib/Topology/Category/TopCat/Basic.lean` contained the following code: ``` -attribute [instance] ConcreteCategory.instFunLike in +attribute [instance] HasForget.instFunLike in instance (X Y : TopCat.{u}) : CoeFun (X ⟶ Y) fun _ => X → Y where coe f := f ``` -Despite the `in`, this makes `ConcreteCategory.instFunLike` a global instance. +Despite the `in`, this makes `HasForget.instFunLike` a global instance. This seems to apply to all attributes. For example: ```lean diff --git a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean index 8abe8c4e96962..a916bde9ffec6 100644 --- a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean +++ b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean @@ -96,7 +96,7 @@ instance (G H : ProfiniteGrp) : ContinuousMapClass (G ⟶ H) G H := inferInstanceAs <| ContinuousMapClass (ContinuousMonoidHom G H) G H @[to_additive] -instance : ConcreteCategory ProfiniteGrp where +instance : HasForget ProfiniteGrp where forget := { obj := fun G => G map := fun f => f } diff --git a/Mathlib/Topology/Category/Born.lean b/Mathlib/Topology/Category/Born.lean index 38806afe27ef2..e6810d7c8dbae 100644 --- a/Mathlib/Topology/Category/Born.lean +++ b/Mathlib/Topology/Category/Born.lean @@ -44,7 +44,7 @@ instance : BundledHom @LocallyBoundedMap where instance : LargeCategory.{u} Born := BundledHom.category LocallyBoundedMap -instance : ConcreteCategory Born := - BundledHom.concreteCategory LocallyBoundedMap +instance : HasForget Born := + BundledHom.hasForget LocallyBoundedMap end Born diff --git a/Mathlib/Topology/Category/CompHaus/Basic.lean b/Mathlib/Topology/Category/CompHaus/Basic.lean index 5e8f4bbf8a5ab..e3e5ac0e6628e 100644 --- a/Mathlib/Topology/Category/CompHaus/Basic.lean +++ b/Mathlib/Topology/Category/CompHaus/Basic.lean @@ -35,7 +35,7 @@ The category `CompHaus` is defined using the structure `CompHausLike`. See the f universe v u -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.instFunLike open CategoryTheory CompHausLike diff --git a/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean b/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean index 11338ba0c53d7..0c6a81f860057 100644 --- a/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/CompHaus/EffectiveEpi.lean @@ -29,7 +29,7 @@ universe u open CategoryTheory Limits CompHausLike -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace CompHaus diff --git a/Mathlib/Topology/Category/CompHaus/Projective.lean b/Mathlib/Topology/Category/CompHaus/Projective.lean index 7e9ded8434f0f..94949dbecb705 100644 --- a/Mathlib/Topology/Category/CompHaus/Projective.lean +++ b/Mathlib/Topology/Category/CompHaus/Projective.lean @@ -34,7 +34,7 @@ open CategoryTheory Function namespace CompHaus -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X) where factors {Y Z} f g hg := by diff --git a/Mathlib/Topology/Category/CompHausLike/Basic.lean b/Mathlib/Topology/Category/CompHausLike/Basic.lean index 90dc5c3dddfa4..7dd9915be9c18 100644 --- a/Mathlib/Topology/Category/CompHausLike/Basic.lean +++ b/Mathlib/Topology/Category/CompHausLike/Basic.lean @@ -64,7 +64,7 @@ universe u open CategoryTheory -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike variable (P : TopCat.{u} → Prop) @@ -89,8 +89,8 @@ instance : CoeSort (CompHausLike P) (Type u) := instance category : Category (CompHausLike P) := InducedCategory.category toTop -instance concreteCategory : ConcreteCategory (CompHausLike P) := - InducedCategory.concreteCategory _ +instance hasForget : HasForget (CompHausLike P) := + InducedCategory.hasForget _ instance hasForget₂ : HasForget₂ (CompHausLike P) TopCat := InducedCategory.hasForget₂ _ diff --git a/Mathlib/Topology/Category/CompHausLike/EffectiveEpi.lean b/Mathlib/Topology/Category/CompHausLike/EffectiveEpi.lean index 4cc30a158cd69..967d8531b8e53 100644 --- a/Mathlib/Topology/Category/CompHausLike/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/CompHausLike/EffectiveEpi.lean @@ -21,7 +21,7 @@ universe u open CategoryTheory Limits Topology -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace CompHausLike diff --git a/Mathlib/Topology/Category/CompHausLike/Limits.lean b/Mathlib/Topology/Category/CompHausLike/Limits.lean index 7739d95e40a78..a818fb4571e8b 100644 --- a/Mathlib/Topology/Category/CompHausLike/Limits.lean +++ b/Mathlib/Topology/Category/CompHausLike/Limits.lean @@ -40,7 +40,7 @@ namespace CompHausLike universe w u -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike section FiniteCoproducts diff --git a/Mathlib/Topology/Category/CompactlyGenerated.lean b/Mathlib/Topology/Category/CompactlyGenerated.lean index 2563c6dffb796..3defff92c5ca0 100644 --- a/Mathlib/Topology/Category/CompactlyGenerated.lean +++ b/Mathlib/Topology/Category/CompactlyGenerated.lean @@ -20,7 +20,7 @@ compact Hausdorff spaces `S` mapping continuously to `X`. * Every first-countable space is `u`-compactly generated for every universe `u`. -/ -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.instFunLike universe u w @@ -47,8 +47,8 @@ attribute [instance] is_compactly_generated instance : Category.{w, w+1} CompactlyGenerated.{u, w} := InducedCategory.category toTop -instance : ConcreteCategory.{w} CompactlyGenerated.{u, w} := - InducedCategory.concreteCategory _ +instance : HasForget.{w} CompactlyGenerated.{u, w} := + InducedCategory.hasForget _ variable (X : Type w) [TopologicalSpace X] [UCompactlyGeneratedSpace.{u} X] diff --git a/Mathlib/Topology/Category/Compactum.lean b/Mathlib/Topology/Category/Compactum.lean index c83b146268d5c..32dbfd00182a5 100644 --- a/Mathlib/Topology/Category/Compactum.lean +++ b/Mathlib/Topology/Category/Compactum.lean @@ -53,7 +53,7 @@ topological space which satisfies `CompactSpace` and `T2Space`. We also add wrappers around structures which already exist. Here are the main ones, all in the `Compactum` namespace: -- `forget : Compactum ⥤ Type*` is the forgetful functor, which induces a `ConcreteCategory` +- `forget : Compactum ⥤ Type*` is the forgetful functor, which induces a `HasForget` instance for `Compactum`. - `free : Type* ⥤ Compactum` is the left adjoint to `forget`, and the adjunction is in `adj`. - `str : Ultrafilter X → X` is the structure map for `X : Compactum`. @@ -102,7 +102,7 @@ def adj : free ⊣ forget := Monad.adj _ -- Basic instances -instance : ConcreteCategory Compactum where forget := forget +instance : HasForget Compactum where forget := forget -- Porting note: changed from forget to X.A instance : CoeSort Compactum Type* := diff --git a/Mathlib/Topology/Category/DeltaGenerated.lean b/Mathlib/Topology/Category/DeltaGenerated.lean index 86a2128d2d7e3..7024dfe3ba5b2 100644 --- a/Mathlib/Topology/Category/DeltaGenerated.lean +++ b/Mathlib/Topology/Category/DeltaGenerated.lean @@ -41,8 +41,8 @@ attribute [instance] deltaGenerated instance : LargeCategory.{u} DeltaGenerated.{u} := InducedCategory.category toTop -instance : ConcreteCategory.{u} DeltaGenerated.{u} := - InducedCategory.concreteCategory _ +instance : HasForget.{u} DeltaGenerated.{u} := + InducedCategory.hasForget _ /-- Constructor for objects of the category `DeltaGenerated` -/ def of (X : Type u) [TopologicalSpace X] [DeltaGeneratedSpace X] : DeltaGenerated.{u} where diff --git a/Mathlib/Topology/Category/FinTopCat.lean b/Mathlib/Topology/Category/FinTopCat.lean index 60e004c86238e..ff492e48cdfcf 100644 --- a/Mathlib/Topology/Category/FinTopCat.lean +++ b/Mathlib/Topology/Category/FinTopCat.lean @@ -38,8 +38,8 @@ attribute [instance] fintype instance : Category FinTopCat := InducedCategory.category toTop -instance : ConcreteCategory FinTopCat := - InducedCategory.concreteCategory _ +instance : HasForget FinTopCat := + InducedCategory.hasForget _ instance (X : FinTopCat) : TopologicalSpace ((forget FinTopCat).obj X) := inferInstanceAs <| TopologicalSpace X diff --git a/Mathlib/Topology/Category/LightProfinite/AsLimit.lean b/Mathlib/Topology/Category/LightProfinite/AsLimit.lean index bb092cf45b600..a7680b1ad8bb9 100644 --- a/Mathlib/Topology/Category/LightProfinite/AsLimit.lean +++ b/Mathlib/Topology/Category/LightProfinite/AsLimit.lean @@ -20,7 +20,7 @@ noncomputable section open CategoryTheory Limits CompHausLike -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace LightProfinite diff --git a/Mathlib/Topology/Category/LightProfinite/Basic.lean b/Mathlib/Topology/Category/LightProfinite/Basic.lean index bd67bbffa19ea..d294240517a43 100644 --- a/Mathlib/Topology/Category/LightProfinite/Basic.lean +++ b/Mathlib/Topology/Category/LightProfinite/Basic.lean @@ -36,7 +36,7 @@ universe v u Previously, this had accidentally been made a global instance, and we now turn it on locally when convenient. -/ -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.instFunLike open CategoryTheory Limits Opposite FintypeCat Topology TopologicalSpace CompHausLike @@ -261,7 +261,7 @@ def toProfinite (S : LightDiagram) : Profinite := S.cone.pt @[simps!] instance : Category LightDiagram := InducedCategory.category toProfinite -instance concreteCategory : ConcreteCategory LightDiagram := InducedCategory.concreteCategory _ +instance hasForget : HasForget LightDiagram := InducedCategory.hasForget _ end LightDiagram diff --git a/Mathlib/Topology/Category/LightProfinite/EffectiveEpi.lean b/Mathlib/Topology/Category/LightProfinite/EffectiveEpi.lean index 6c516dad05e1c..156e8287d0dc7 100644 --- a/Mathlib/Topology/Category/LightProfinite/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/LightProfinite/EffectiveEpi.lean @@ -19,7 +19,7 @@ universe u open CategoryTheory Limits CompHausLike -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace LightProfinite diff --git a/Mathlib/Topology/Category/LightProfinite/Extend.lean b/Mathlib/Topology/Category/LightProfinite/Extend.lean index 4f7e5eb315b90..ab090b9d20066 100644 --- a/Mathlib/Topology/Category/LightProfinite/Extend.lean +++ b/Mathlib/Topology/Category/LightProfinite/Extend.lean @@ -28,7 +28,7 @@ universe u open CategoryTheory Limits FintypeCat Functor -attribute [local instance] FintypeCat.discreteTopology ConcreteCategory.instFunLike +attribute [local instance] FintypeCat.discreteTopology HasForget.instFunLike namespace LightProfinite diff --git a/Mathlib/Topology/Category/Profinite/Basic.lean b/Mathlib/Topology/Category/Profinite/Basic.lean index 14be0aa96b9a9..fe5f7d2a47ee4 100644 --- a/Mathlib/Topology/Category/Profinite/Basic.lean +++ b/Mathlib/Topology/Category/Profinite/Basic.lean @@ -38,7 +38,7 @@ profinite -/ -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.instFunLike universe v u diff --git a/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean b/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean index cfafac5b2a871..35974372c30e3 100644 --- a/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean +++ b/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean @@ -27,7 +27,7 @@ namespace Profinite open CategoryTheory Limits -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike universe u v diff --git a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean index f6a2c77737320..ecdeb71c73112 100644 --- a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean @@ -25,7 +25,7 @@ universe u open CategoryTheory Limits -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace Profinite diff --git a/Mathlib/Topology/Category/Profinite/Extend.lean b/Mathlib/Topology/Category/Profinite/Extend.lean index bbdcf1c6b88fc..cfb6aa9416fa0 100644 --- a/Mathlib/Topology/Category/Profinite/Extend.lean +++ b/Mathlib/Topology/Category/Profinite/Extend.lean @@ -27,7 +27,7 @@ universe u w open CategoryTheory Limits FintypeCat Functor -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace Profinite diff --git a/Mathlib/Topology/Category/Profinite/Projective.lean b/Mathlib/Topology/Category/Profinite/Projective.lean index 450aa53e7a3e6..4a53a7e275187 100644 --- a/Mathlib/Topology/Category/Profinite/Projective.lean +++ b/Mathlib/Topology/Category/Profinite/Projective.lean @@ -31,7 +31,7 @@ universe u v w open CategoryTheory Function -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace Profinite diff --git a/Mathlib/Topology/Category/Sequential.lean b/Mathlib/Topology/Category/Sequential.lean index 65e73b4a4fcb7..0d0d338a0a45d 100644 --- a/Mathlib/Topology/Category/Sequential.lean +++ b/Mathlib/Topology/Category/Sequential.lean @@ -18,7 +18,7 @@ for defining categories of topological spaces, by giving it the induced category open CategoryTheory -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike universe u @@ -42,8 +42,8 @@ attribute [instance] is_sequential instance : Category.{u, u+1} Sequential.{u} := InducedCategory.category toTop -instance : ConcreteCategory.{u} Sequential.{u} := - InducedCategory.concreteCategory _ +instance : HasForget.{u} Sequential.{u} := + InducedCategory.hasForget _ variable (X : Type u) [TopologicalSpace X] [SequentialSpace X] diff --git a/Mathlib/Topology/Category/Stonean/Basic.lean b/Mathlib/Topology/Category/Stonean/Basic.lean index 9df5667c0cf2e..421a0327cf878 100644 --- a/Mathlib/Topology/Category/Stonean/Basic.lean +++ b/Mathlib/Topology/Category/Stonean/Basic.lean @@ -43,7 +43,7 @@ open CategoryTheory open scoped Topology -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike /-- `Stonean` is the category of extremally disconnected compact Hausdorff spaces. -/ abbrev Stonean := CompHausLike (fun X ↦ ExtremallyDisconnected X) diff --git a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean index 1901963fcc1a9..9d1ef396385b6 100644 --- a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean @@ -24,7 +24,7 @@ universe u open CategoryTheory Limits CompHausLike -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace Stonean diff --git a/Mathlib/Topology/Category/Stonean/Limits.lean b/Mathlib/Topology/Category/Stonean/Limits.lean index e2bd426c265d4..6e9904e8c16da 100644 --- a/Mathlib/Topology/Category/Stonean/Limits.lean +++ b/Mathlib/Topology/Category/Stonean/Limits.lean @@ -17,7 +17,7 @@ universe w u open CategoryTheory Limits CompHausLike Topology -attribute [local instance] ConcreteCategory.instFunLike +attribute [local instance] HasForget.instFunLike namespace Stonean diff --git a/Mathlib/Topology/Category/TopCat/Basic.lean b/Mathlib/Topology/Category/TopCat/Basic.lean index b9921302b97a7..31d2fe85ecda8 100644 --- a/Mathlib/Topology/Category/TopCat/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Basic.lean @@ -34,10 +34,10 @@ instance bundledHom : BundledHom @ContinuousMap where deriving instance LargeCategory for TopCat --- Porting note: currently no derive handler for ConcreteCategory +-- Porting note: currently no derive handler for HasForget -- see https://github.com/leanprover-community/mathlib4/issues/5020 -instance concreteCategory : ConcreteCategory TopCat := - inferInstanceAs <| ConcreteCategory (Bundled TopologicalSpace) +instance hasForget : HasForget TopCat := + inferInstanceAs <| HasForget (Bundled TopologicalSpace) instance : CoeSort TopCat Type* where coe X := X.α @@ -94,7 +94,7 @@ equal function coercion for a continuous map `C(X, Y)`. @[simp] theorem coe_of_of {X Y : Type u} [TopologicalSpace X] [TopologicalSpace Y] {f : C(X, Y)} {x} : @DFunLike.coe (TopCat.of X ⟶ TopCat.of Y) ((CategoryTheory.forget TopCat).obj (TopCat.of X)) - (fun _ ↦ (CategoryTheory.forget TopCat).obj (TopCat.of Y)) ConcreteCategory.instFunLike + (fun _ ↦ (CategoryTheory.forget TopCat).obj (TopCat.of Y)) HasForget.instFunLike f x = @DFunLike.coe C(X, Y) X (fun _ ↦ Y) _ diff --git a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean index bf7d634387ace..fe21e9bb40dc6 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean @@ -119,7 +119,7 @@ theorem pullbackIsoProdSubtype_hom_snd (f : X ⟶ Z) (g : Y ⟶ Z) : -- Porting note: why do I need to tell Lean to coerce pullback to a type theorem pullbackIsoProdSubtype_hom_apply {f : X ⟶ Z} {g : Y ⟶ Z} - (x : ConcreteCategory.forget.obj (pullback f g)) : + (x : HasForget.forget.obj (pullback f g)) : (pullbackIsoProdSubtype f g).hom x = ⟨⟨pullback.fst f g x, pullback.snd f g x⟩, by simpa using ConcreteCategory.congr_hom pullback.condition x⟩ := by diff --git a/Mathlib/Topology/Category/TopCommRingCat.lean b/Mathlib/Topology/Category/TopCommRingCat.lean index 27530487131f3..eedae4582314d 100644 --- a/Mathlib/Topology/Category/TopCommRingCat.lean +++ b/Mathlib/Topology/Category/TopCommRingCat.lean @@ -48,7 +48,7 @@ instance : Category TopCommRingCat.{u} where cases g dsimp; apply Continuous.comp <;> assumption⟩ -instance : ConcreteCategory TopCommRingCat.{u} where +instance : HasForget TopCommRingCat.{u} where forget := { obj := fun R => R map := fun f => f.val } diff --git a/Mathlib/Topology/Category/UniformSpace.lean b/Mathlib/Topology/Category/UniformSpace.lean index c3671ce185d18..37b17fb3b293d 100644 --- a/Mathlib/Topology/Category/UniformSpace.lean +++ b/Mathlib/Topology/Category/UniformSpace.lean @@ -36,8 +36,8 @@ instance : UnbundledHom @UniformContinuous := deriving instance LargeCategory for UniformSpaceCat -instance : ConcreteCategory UniformSpaceCat := - inferInstanceAs <| ConcreteCategory <| Bundled UniformSpace +instance : HasForget UniformSpaceCat := + inferInstanceAs <| HasForget <| Bundled UniformSpace instance : CoeSort UniformSpaceCat Type* := Bundled.coeSort @@ -126,8 +126,8 @@ instance category : LargeCategory CpltSepUniformSpace := InducedCategory.category toUniformSpace /-- The concrete category instance on `CpltSepUniformSpace`. -/ -instance concreteCategory : ConcreteCategory CpltSepUniformSpace := - InducedCategory.concreteCategory toUniformSpace +instance hasForget : HasForget CpltSepUniformSpace := + InducedCategory.hasForget toUniformSpace instance hasForgetToUniformSpace : HasForget₂ CpltSepUniformSpace UniformSpaceCat := InducedCategory.hasForget₂ toUniformSpace @@ -169,7 +169,7 @@ instance (X : UniformSpaceCat) : UniformSpace ((forget _).obj X) := show UniformSpace X from inferInstance -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike in +attribute [local instance] CategoryTheory.HasForget.instFunLike in @[simp] theorem extensionHom_val {X : UniformSpaceCat} {Y : CpltSepUniformSpace} (f : X ⟶ (forget₂ _ _).obj Y) (x) : (extensionHom f) x = Completion.extension f x := diff --git a/Mathlib/Topology/Order/Category/AlexDisc.lean b/Mathlib/Topology/Order/Category/AlexDisc.lean index 50493ec29ed76..fd44e293d4337 100644 --- a/Mathlib/Topology/Order/Category/AlexDisc.lean +++ b/Mathlib/Topology/Order/Category/AlexDisc.lean @@ -31,7 +31,7 @@ instance : BundledHom.ParentProjection @AlexandrovDiscreteSpace.toTopologicalSpa deriving instance LargeCategory for AlexDisc -instance instConcreteCategory : ConcreteCategory AlexDisc := BundledHom.concreteCategory _ +instance instHasForget : HasForget AlexDisc := BundledHom.hasForget _ instance instHasForgetToTop : HasForget₂ AlexDisc TopCat := BundledHom.forget₂ _ _ instance forgetToTop_full : (forget₂ AlexDisc TopCat).Full := BundledHom.forget₂_full _ _ instance forgetToTop_faithful : (forget₂ AlexDisc TopCat).Faithful where @@ -46,7 +46,7 @@ def of (α : Type*) [TopologicalSpace α] [AlexandrovDiscrete α] : AlexDisc := (forget₂ AlexDisc TopCat).obj (of α) = TopCat.of α := rfl -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.instFunLike /-- Constructs an equivalence between preorders from an order isomorphism between them. -/ @[simps] diff --git a/Mathlib/Topology/Order/Category/FrameAdjunction.lean b/Mathlib/Topology/Order/Category/FrameAdjunction.lean index 2dae4802f7045..2501e640cac85 100644 --- a/Mathlib/Topology/Order/Category/FrameAdjunction.lean +++ b/Mathlib/Topology/Order/Category/FrameAdjunction.lean @@ -77,7 +77,7 @@ lemma isOpen_iff (U : Set (PT L)) : IsOpen U ↔ ∃ u : L, {x | x u} = U := Iff end PT -- This was a global instance prior to https://github.com/leanprover-community/mathlib4/pull/13170. We may experiment with removing it. -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.instFunLike /-- The covariant functor `pt` from the category of locales to the category of topological spaces, which sends a locale `L` to the topological space `PT L` of homomorphisms diff --git a/Mathlib/Topology/Sheaves/CommRingCat.lean b/Mathlib/Topology/Sheaves/CommRingCat.lean index 3cb0213a5e86e..2bdba51313e3d 100644 --- a/Mathlib/Topology/Sheaves/CommRingCat.lean +++ b/Mathlib/Topology/Sheaves/CommRingCat.lean @@ -90,9 +90,9 @@ section SubmonoidPresheaf open scoped nonZeroDivisors -variable {X : TopCat.{w}} {C : Type u} [Category.{v} C] [ConcreteCategory C] +variable {X : TopCat.{w}} {C : Type u} [Category.{v} C] [HasForget C] -attribute [local instance 1000] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance 1000] HasForget.hasCoeToSort HasForget.instFunLike -- note: this was specialized to `CommRingCat` in #19757 /-- A subpresheaf with a submonoid structure on each of the components. -/ diff --git a/Mathlib/Topology/Sheaves/Functors.lean b/Mathlib/Topology/Sheaves/Functors.lean index 4bf77afd2c82a..5c05468fa1420 100644 --- a/Mathlib/Topology/Sheaves/Functors.lean +++ b/Mathlib/Topology/Sheaves/Functors.lean @@ -75,7 +75,7 @@ variable {C} @[simp] lemma pushforward_map (f : X ⟶ Y) {F F' : X.Sheaf C} (α : F ⟶ F') : ((pushforward C f).map α).1 = (Presheaf.pushforward C f).map α.1 := rfl -variable (A : Type*) [Category.{w} A] [ConcreteCategory.{w} A] [HasColimits A] [HasLimits A] +variable (A : Type*) [Category.{w} A] [HasForget.{w} A] [HasColimits A] [HasLimits A] variable [PreservesLimits (CategoryTheory.forget A)] variable [PreservesFilteredColimits (CategoryTheory.forget A)] variable [(CategoryTheory.forget A).ReflectsIsomorphisms] diff --git a/Mathlib/Topology/Sheaves/LocallySurjective.lean b/Mathlib/Topology/Sheaves/LocallySurjective.lean index 1e4b5176e114b..32921d1029957 100644 --- a/Mathlib/Topology/Sheaves/LocallySurjective.lean +++ b/Mathlib/Topology/Sheaves/LocallySurjective.lean @@ -30,7 +30,7 @@ We prove that these are equivalent. universe v u -attribute [local instance] CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.instFunLike noncomputable section @@ -46,7 +46,7 @@ section LocallySurjective open scoped AlgebraicGeometry -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] {X : TopCat.{v}} +variable {C : Type u} [Category.{v} C] [HasForget.{v} C] {X : TopCat.{v}} variable {ℱ 𝒢 : X.Presheaf C} /-- A map of presheaves `T : ℱ ⟶ 𝒢` is **locally surjective** if for any open set `U`, diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index a2aa72573878f..d509f463163f3 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -62,8 +62,8 @@ lemma ext {X : TopCat} {P Q : Presheaf C X} {f g : P ⟶ Q} induction U with | _ U => ?_ apply w -attribute [local instance] CategoryTheory.ConcreteCategory.hasCoeToSort - CategoryTheory.ConcreteCategory.instFunLike +attribute [local instance] CategoryTheory.HasForget.hasCoeToSort + CategoryTheory.HasForget.instFunLike /-- attribute `sheaf_restrict` to mark lemmas related to restricting sheaves -/ macro "sheaf_restrict" : attr => @@ -103,7 +103,7 @@ example {X} [CompleteLattice X] (v : Nat → X) (w x y z : X) (e : v 0 = v 1) (_ For `x : F.obj (op V)`, we provide the notation `x |_ₕ i` (`h` stands for `hom`) for `i : U ⟶ V`, and the notation `x |_ₗ U ⟪i⟫` (`l` stands for `le`) for `i : U ≤ V`. -/ -def restrict {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] {F : X.Presheaf C} +def restrict {X : TopCat} {C : Type*} [Category C] [HasForget C] {F : X.Presheaf C} {V : Opens X} (x : F.obj (op V)) {U : Opens X} (h : U ⟶ V) : F.obj (op U) := F.map h.op x @@ -118,7 +118,7 @@ open AlgebraicGeometry /-- The restriction of a section along an inclusion of open sets. For `x : F.obj (op V)`, we provide the notation `x |_ U`, where the proof `U ≤ V` is inferred by the tactic `Top.presheaf.restrict_tac'` -/ -abbrev restrictOpen {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] {F : X.Presheaf C} +abbrev restrictOpen {X : TopCat} {C : Type*} [Category C] [HasForget C] {F : X.Presheaf C} {V : Opens X} (x : F.obj (op V)) (U : Opens X) (e : U ≤ V := by restrict_tac) : F.obj (op U) := @@ -127,14 +127,14 @@ abbrev restrictOpen {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] { /-- restriction of a section to open subset -/ scoped[AlgebraicGeometry] infixl:80 " |_ " => TopCat.Presheaf.restrictOpen -theorem restrict_restrict {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] +theorem restrict_restrict {X : TopCat} {C : Type*} [Category C] [HasForget C] {F : X.Presheaf C} {U V W : Opens X} (e₁ : U ≤ V) (e₂ : V ≤ W) (x : F.obj (op W)) : x |_ V |_ U = x |_ U := by delta restrictOpen restrict rw [← comp_apply, ← Functor.map_comp] rfl -theorem map_restrict {X : TopCat} {C : Type*} [Category C] [ConcreteCategory C] +theorem map_restrict {X : TopCat} {C : Type*} [Category C] [HasForget C] {F G : X.Presheaf C} (e : F ⟶ G) {U V : Opens X} (h : U ≤ V) (x : F.obj (op V)) : e.app _ (x |_ U) = e.app _ x |_ U := by delta restrictOpen restrict diff --git a/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean b/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean index 5c7906eb4b4a4..43f8af284c79a 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean @@ -40,7 +40,7 @@ open TopCat TopCat.Presheaf CategoryTheory CategoryTheory.Limits universe v u x -variable {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] +variable {C : Type u} [Category.{v} C] [HasForget.{v} C] namespace TopCat @@ -48,7 +48,7 @@ namespace Presheaf section -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike variable {X : TopCat.{x}} (F : Presheaf C X) {ι : Type x} (U : ι → Opens X) @@ -135,7 +135,7 @@ end TypeValued section -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike variable [HasLimits C] [(forget C).ReflectsIsomorphisms] [PreservesLimits (forget C)] variable {X : TopCat.{v}} (F : Presheaf C X) @@ -159,10 +159,10 @@ open CategoryTheory section -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike -variable [HasLimits C] [(ConcreteCategory.forget (C := C)).ReflectsIsomorphisms] -variable [PreservesLimits (ConcreteCategory.forget (C := C))] +variable [HasLimits C] [(HasForget.forget (C := C)).ReflectsIsomorphisms] +variable [PreservesLimits (HasForget.forget (C := C))] variable {X : TopCat.{v}} (F : Sheaf C X) {ι : Type v} (U : ι → Opens X) /-- A more convenient way of obtaining a unique gluing of sections for a sheaf. diff --git a/Mathlib/Topology/Sheaves/Stalks.lean b/Mathlib/Topology/Sheaves/Stalks.lean index 3b24d1d5a253d..2b6e732ac1bea 100644 --- a/Mathlib/Topology/Sheaves/Stalks.lean +++ b/Mathlib/Topology/Sheaves/Stalks.lean @@ -110,19 +110,19 @@ lemma map_germ_eq_Γgerm (F : X.Presheaf C) {U : Opens X} {i : U ⟶ ⊤} (x : X F.map i.op ≫ F.germ U x hx = F.Γgerm x := germ_res F i x hx -attribute [local instance] ConcreteCategory.instFunLike in +attribute [local instance] HasForget.instFunLike in theorem germ_res_apply (F : X.Presheaf C) - {U V : Opens X} (i : U ⟶ V) (x : X) (hx : x ∈ U) [ConcreteCategory C] (s) : + {U V : Opens X} (i : U ⟶ V) (x : X) (hx : x ∈ U) [HasForget C] (s) : F.germ U x hx (F.map i.op s) = F.germ V x (i.le hx) s := by rw [← comp_apply, germ_res] -attribute [local instance] ConcreteCategory.instFunLike in +attribute [local instance] HasForget.instFunLike in theorem germ_res_apply' (F : X.Presheaf C) - {U V : Opens X} (i : op V ⟶ op U) (x : X) (hx : x ∈ U) [ConcreteCategory C] (s) : + {U V : Opens X} (i : op V ⟶ op U) (x : X) (hx : x ∈ U) [HasForget C] (s) : F.germ U x hx (F.map i s) = F.germ V x (i.unop.le hx) s := by rw [← comp_apply, germ_res'] -attribute [local instance] ConcreteCategory.instFunLike in +attribute [local instance] HasForget.instFunLike in lemma Γgerm_res_apply (F : X.Presheaf C) - {U : Opens X} {i : U ⟶ ⊤} (x : X) (hx : x ∈ U) [ConcreteCategory C] (s) : + {U : Opens X} {i : U ⟶ ⊤} (x : X) (hx : x ∈ U) [HasForget C] (s) : F.germ U x hx (F.map i.op s) = F.Γgerm x s := F.germ_res_apply i x hx s /-- A morphism from the stalk of `F` at `x` to some object `Y` is completely determined by its @@ -139,17 +139,17 @@ theorem stalkFunctor_map_germ {F G : X.Presheaf C} (U : Opens X) (x : X) (hx : x F.germ U x hx ≫ (stalkFunctor C x).map f = f.app (op U) ≫ G.germ U x hx := colimit.ι_map (whiskerLeft (OpenNhds.inclusion x).op f) (op ⟨U, hx⟩) -attribute [local instance] ConcreteCategory.instFunLike in -theorem stalkFunctor_map_germ_apply [ConcreteCategory C] +attribute [local instance] HasForget.instFunLike in +theorem stalkFunctor_map_germ_apply [HasForget C] {F G : X.Presheaf C} (U : Opens X) (x : X) (hx : x ∈ U) (f : F ⟶ G) (s) : (stalkFunctor C x).map f (F.germ U x hx s) = G.germ U x hx (f.app (op U) s) := by rw [← comp_apply, ← stalkFunctor_map_germ] exact (comp_apply _ _ _).symm -- a variant of `stalkFunctor_map_germ_apply` that makes simpNF happy. -attribute [local instance] ConcreteCategory.instFunLike in +attribute [local instance] HasForget.instFunLike in @[simp] -theorem stalkFunctor_map_germ_apply' [ConcreteCategory C] +theorem stalkFunctor_map_germ_apply' [HasForget C] {F G : X.Presheaf C} (U : Opens X) (x : X) (hx : x ∈ U) (f : F ⟶ G) (s) : DFunLike.coe (F := F.stalk x ⟶ G.stalk x) ((stalkFunctor C x).map f) (F.germ U x hx s) = G.germ U x hx (f.app (op U) s) := @@ -393,9 +393,9 @@ end stalkSpecializes section Concrete variable {C} -variable [ConcreteCategory.{v} C] +variable [HasForget.{v} C] -attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFunLike +attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: @[ext] attribute only applies to structures or lemmas proving x = y -- @[ext] diff --git a/MathlibTest/CategoryTheory/Elementwise.lean b/MathlibTest/CategoryTheory/Elementwise.lean index 4b8056c788b1f..fd9a3578265a6 100644 --- a/MathlibTest/CategoryTheory/Elementwise.lean +++ b/MathlibTest/CategoryTheory/Elementwise.lean @@ -8,22 +8,22 @@ open CategoryTheory attribute [simp] Iso.hom_inv_id Iso.inv_hom_id IsIso.hom_inv_id IsIso.inv_hom_id -attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort +attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort @[elementwise] -theorem ex1 [Category C] [ConcreteCategory C] (X : C) (f g h : X ⟶ X) (h' : g ≫ h = h ≫ g) : +theorem ex1 [Category C] [HasForget C] (X : C) (f g h : X ⟶ X) (h' : g ≫ h = h ≫ g) : f ≫ g ≫ h = f ≫ h ≫ g := by rw [h'] --- If there is already a `ConcreteCategory` instance, do not add a new argument. -example : ∀ C [Category C] [ConcreteCategory C] (X : C) (f g h : X ⟶ X) (_ : g ≫ h = h ≫ g) +-- If there is already a `HasForget` instance, do not add a new argument. +example : ∀ C [Category C] [HasForget C] (X : C) (f g h : X ⟶ X) (_ : g ≫ h = h ≫ g) (x : X), h (g (f x)) = g (h (f x)) := @ex1_apply @[elementwise] theorem ex2 [Category C] (X : C) (f g h : X ⟶ X) (h' : g ≫ h = h ≫ g) : f ≫ g ≫ h = f ≫ h ≫ g := by rw [h'] --- If there is not already a `ConcreteCategory` instance, insert a new argument. -example : ∀ C [Category C] (X : C) (f g h : X ⟶ X) (_ : g ≫ h = h ≫ g) [ConcreteCategory C] +-- If there is not already a `HasForget` instance, insert a new argument. +example : ∀ C [Category C] (X : C) (f g h : X ⟶ X) (_ : g ≫ h = h ≫ g) [HasForget C] (x : X), h (g (f x)) = g (h (f x)) := @ex2_apply -- Need nosimp on the following `elementwise` since the lemma can be proved by simp anyway. @@ -31,11 +31,11 @@ example : ∀ C [Category C] (X : C) (f g h : X ⟶ X) (_ : g ≫ h = h ≫ g) [ theorem ex3 [Category C] {X Y : C} (f : X ≅ Y) : f.hom ≫ f.inv = 𝟙 X := Iso.hom_inv_id _ -example : ∀ C [Category C] (X Y : C) (f : X ≅ Y) [ConcreteCategory C] (x : X), +example : ∀ C [Category C] (X Y : C) (f : X ≅ Y) [HasForget C] (x : X), f.inv (f.hom x) = x := @ex3_apply -- Make sure there's no `id x` in there: -example : ∀ C [Category C] (X Y : C) (f : X ≅ Y) [ConcreteCategory C] (x : X), +example : ∀ C [Category C] (X Y : C) (f : X ≅ Y) [HasForget C] (x : X), f.inv (f.hom x) = x := by intros; simp only [ex3_apply] @[elementwise] @@ -48,7 +48,7 @@ lemma foo' [Category C] {M N K : C} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) : f ≫ 𝟙 N ≫ g = h := by simp [w] -lemma bar [Category C] [ConcreteCategory C] +lemma bar [Category C] [HasForget C] {M N K : C} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : g (f x) = h x := by apply foo_apply w @@ -61,23 +61,23 @@ example {M N K : Type} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = example {M N K : Type} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : g (f x) = h x := (elementwise_of% w) x -example [Category C] [ConcreteCategory C] +example [Category C] [HasForget C] {M N K : C} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : g (f x) = h x := by have := elementwise_of% w guard_hyp this : ∀ (x : M), g (f x) = h x exact this x --- `elementwise_of%` allows a level metavariable for its `ConcreteCategory` instance. +-- `elementwise_of%` allows a level metavariable for its `HasForget` instance. -- Previously this example did not specify that the universe levels of `C` and `D` (inside `h`) -- were the same, and this constraint was added post-hoc by the proof term. -- After https://github.com/leanprover/lean4/pull/4493 this no longer works (happily!). -example {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] +example {C : Type u} [Category.{v} C] [HasForget.{w} C] (h : ∀ (D : Type u) [Category.{v} D] (X Y : D) (f : X ⟶ Y) (g : Y ⟶ X), f ≫ g = 𝟙 X) {M N : C} {f : M ⟶ N} {g : N ⟶ M} (x : M) : g (f x) = x := by have := elementwise_of% h guard_hyp this : ∀ D [Category D] (X Y : D) (f : X ⟶ Y) (g : Y ⟶ X) - [ConcreteCategory D] (x : X), g (f x) = x + [HasForget D] (x : X), g (f x) = x rw [this] section Mon @@ -126,7 +126,7 @@ lemma gh (X : C) : g X = h X := rfl @[elementwise] theorem fh (X : C) : f X = h X := gh X -variable (X : C) [ConcreteCategory C] (x : X) +variable (X : C) [HasForget C] (x : X) -- Prior to https://github.com/leanprover-community/mathlib4/pull/13413 this would produce -- `fh_apply X x : (g X) x = (h X) x`. diff --git a/MathlibTest/slow_simp.lean b/MathlibTest/slow_simp.lean index 651d0e10e6014..124ec08fb86dc 100644 --- a/MathlibTest/slow_simp.lean +++ b/MathlibTest/slow_simp.lean @@ -12,7 +12,7 @@ but took over 260,000 heartbeats with `import Mathlib`. After deleting some bad simp lemmas that were being tried everywhere (discovered using `set_option diagnostics true`): * Mathlib.MeasureTheory.coeFn_comp_toFiniteMeasure_eq_coeFn -* LightProfinite.concreteCategory_forget_obj +* LightProfinite.hasForget_forget_obj * CategoryTheory.sum_comp_inl * CategoryTheory.sum_comp_inr it is back down to 19,000 heartbeats even with `import Mathlib`. From 9ca037a4515aa07763af2ff45177b470d66d65a0 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Fri, 17 Jan 2025 15:43:37 +0000 Subject: [PATCH 287/681] feat(CategoryTheory): define unbundled `ConcreteCategory` class (#20810) This is a step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This PR defines a new class `ConcreteCategory` that unbundles the coercion of morphisms to functions and objects to types, in order to allow `ConcreteCategory` to coexist alongisde existing coercions to functions/sorts. No instances are included yet, since those can be declared in parallel. See e.g. `CommRingCat` on the `redesign-ConcreteCategory` branch for examples of what a concrete category instance will end up looking like. Co-authored-by: Anne Baanen --- .../Normed/Group/SemiNormedGrp/Kernels.lean | 2 +- .../ConcreteCategory/Basic.lean | 234 ++++++++++++++++-- 2 files changed, 216 insertions(+), 20 deletions(-) diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean index ba8df90a57055..47c42654e11cd 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean @@ -145,7 +145,7 @@ def cokernelCocone {X Y : SemiNormedGrp.{u}} (f : X ⟶ Y) : Cofork f 0 := ext a simp only [comp_apply, Limits.zero_comp] -- Porting note: `simp` not firing on the below - rw [comp_apply, NormedAddGroupHom.zero_apply] + rw [NormedAddGroupHom.zero_apply] -- Porting note: Lean 3 didn't need this instance letI : SeminormedAddCommGroup ((forget SemiNormedGrp).obj Y) := (inferInstance : SeminormedAddCommGroup Y) diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 0c1c8895b4fa5..55f2c36323721 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -8,20 +8,20 @@ import Mathlib.CategoryTheory.Types /-! # Concrete categories -A concrete category is a category `C` with a fixed faithful functor -`forget : C ⥤ Type*`. We define concrete categories using `class HasForget`. -In particular, we impose no restrictions on the -carrier type `C`, so `Type` is a concrete category with the identity -forgetful functor. - -Each concrete category `C` comes with a canonical faithful functor -`forget C : C ⥤ Type*`. We say that a concrete category `C` admits a -*forgetful functor* to a concrete category `D`, if it has a functor -`forget₂ C D : C ⥤ D` such that `(forget₂ C D) ⋙ (forget D) = forget C`, -see `class HasForget₂`. Due to `Faithful.div_comp`, it suffices -to verify that `forget₂.obj` and `forget₂.map` agree with the equality -above; then `forget₂` will satisfy the functor laws automatically, see -`HasForget₂.mk'`. +A concrete category is a category `C` where the objects and morphisms correspond with types and +(bundled) functions between these types. We define concrete categories using +`class ConcreteCategory`. To convert an object to a type, write `ToHom`. To convert a morphism +to a (bundled) function, write `hom`. + +Each concrete category `C` comes with a canonical faithful functor `forget C : C ⥤ Type*`, +see `class HasForget`. In particular, we impose no restrictions on the category `C`, so `Type` +has the identity forgetful functor. + +We say that a concrete category `C` admits a *forgetful functor* to a concrete category `D`, if it +has a functor `forget₂ C D : C ⥤ D` such that `(forget₂ C D) ⋙ (forget D) = forget C`, see +`class HasForget₂`. Due to `Faithful.div_comp`, it suffices to verify that `forget₂.obj` and +`forget₂.map` agree with the equality above; then `forget₂` will satisfy the functor laws +automatically, see `HasForget₂.mk'`. Two classes helping construct concrete categories in the two most common cases are provided in the files `BundledHom` and @@ -32,6 +32,23 @@ common cases are provided in the files `BundledHom` and We are currently switching over from `HasForget` to a new class `ConcreteCategory`, see Zulip thread: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign +Previously, `ConcreteCategory` had the same definition as now `HasForget`; the coercion of +objects/morphisms to types/functions was defined as `(forget C).obj` and `(forget C).map` +respectively. This leads to defeq issues since existing `CoeFun` and `FunLike` instances provide +their own casts. We replace this with a less bundled `ConcreteCategory` that does not directly +use these coercions. + +We do not use `CoeSort` to convert objects in a concrete category to types, since this would lead +to elaboration mismatches between results taking a `[ConcreteCategory C]` instance and specific +types `C` that hold a `ConcreteCategory C` instance: the first gets a literal `CoeSort.coe` and +the second gets unfolded to the actual `coe` field. + +`ToType` and `ToHom` are `abbrev`s so that we do not need to copy over instances such as `Ring` +or `RingHomClass` respectively. + +Since `X → Y` is not a `FunLike`, the category of types is not a `ConcreteCategory`, but it does +have a `HasForget` instance. + ## References See [Ahrens and Lumsdaine, *Displayed Categories*][ahrens2017] for @@ -59,11 +76,6 @@ class HasForget (C : Type u) [Category.{v} C] where /-- That functor is faithful -/ [forget_faithful : forget.Faithful] -@[deprecated HasForget - "`ConcreteCategory` will be refactored, use `HasForget` in the meantime" - (since := "2025-01-17")] -alias ConcreteCategory := HasForget - attribute [inline, reducible] HasForget.forget attribute [instance] HasForget.forget_faithful @@ -127,6 +139,7 @@ theorem coe_comp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) : (f ≫ g : X → Z) = @[simp] theorem comp_apply {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (x : X) : (f ≫ g) x = g (f x) := congr_fun ((forget _).map_comp _ _) x +/-- Variation of `ConcreteCategory.comp_apply` that uses `forget` instead. -/ theorem comp_apply' {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (x : X) : (forget C).map (f ≫ g) x = (forget C).map g ((forget C).map f x) := comp_apply f g x @@ -225,4 +238,187 @@ lemma NatTrans.naturality_apply {C D : Type*} [Category C] [Category D] [HasForg φ.app Y (F.map f x) = G.map f (φ.app X x) := by simpa only [Functor.map_comp] using congr_fun ((forget D).congr_map (φ.naturality f)) x +section ConcreteCategory + +/-- A concrete category is a category `C` where objects correspond to types and morphisms to +(bundled) functions between those types. + +In other words, it has a fixed faithful functor `forget : C ⥤ Type`. + +Note that `ConcreteCategory` potentially depends on three independent universe levels, +* the universe level `w` appearing in `forget : C ⥤ Type w` +* the universe level `v` of the morphisms (i.e. we have a `Category.{v} C`) +* the universe level `u` of the objects (i.e `C : Type u`) +They are specified that order, to avoid unnecessary universe annotations. +-/ +class ConcreteCategory (C : Type u) [Category.{v} C] + (FC : outParam <| C → C → Type*) {CC : outParam <| C → Type w} + [outParam <| ∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] where + /-- Convert a morphism of `C` to a bundled function. -/ + (hom : ∀ {X Y}, (X ⟶ Y) → FC X Y) + /-- Convert a bundled function to a morphism of `C`. -/ + (ofHom : ∀ {X Y}, FC X Y → (X ⟶ Y)) + (hom_ofHom : ∀ {X Y} (f : FC X Y), hom (ofHom f) = f := by aesop_cat) + (ofHom_hom : ∀ {X Y} (f : X ⟶ Y), ofHom (hom f) = f := by aesop_cat) + (id_apply : ∀ {X} (x : CC X), hom (𝟙 X) x = x := by aesop_cat) + (comp_apply : ∀ {X Y Z} (f : X ⟶ Y) (g : Y ⟶ Z) (x : CC X), + hom (f ≫ g) x = hom g (hom f x) := by aesop_cat) + +export ConcreteCategory (id_apply comp_apply) + +variable {C : Type u} [Category.{v} C] {FC : C → C → Type*} {CC : C → Type w} +variable [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] +variable [ConcreteCategory C FC] + +/-- `ToType X` converts the object `X` of the concrete category `C` to a type. + +This is an `abbrev` so that instances on `X` (e.g. `Ring`) do not need to be redeclared. +-/ +@[nolint unusedArguments] -- Need the instance to trigger unification that finds `CC`. +abbrev ToType [ConcreteCategory C FC] := CC + +/-- `ToHom X Y` is the type of (bundled) functions between objects `X Y : C`. + +This is an `abbrev` so that instances (e.g. `RingHomClass`) do not need to be redeclared. +-/ +@[nolint unusedArguments] -- Need the instance to trigger unification that finds `FC`. +abbrev ToHom [ConcreteCategory C FC] := FC + +namespace ConcreteCategory + +attribute [simp] id_apply comp_apply + +/-- We can apply morphisms of concrete categories by first casting them down +to the base functions. +-/ +instance {X Y : C} : CoeFun (X ⟶ Y) (fun _ ↦ ToType X → ToType Y) where + coe f := hom f + +/-- +`ConcreteCategory.hom` bundled as an `Equiv`. +-/ +def homEquiv {X Y : C} : (X ⟶ Y) ≃ ToHom X Y where + toFun := hom + invFun := ofHom + left_inv := ofHom_hom + right_inv := hom_ofHom + +lemma hom_bijective {X Y : C} : Function.Bijective (hom : (X ⟶ Y) → ToHom X Y) := + homEquiv.bijective + +lemma hom_injective {X Y : C} : Function.Injective (hom : (X ⟶ Y) → ToHom X Y) := + hom_bijective.injective + +/-- In any concrete category, we can test equality of morphisms by pointwise evaluations. -/ +@[ext] lemma ext {X Y : C} {f g : X ⟶ Y} (h : hom f = hom g) : f = g := + hom_injective h + +lemma coe_ext {X Y : C} {f g : X ⟶ Y} (h : ⇑(hom f) = ⇑(hom g)) : f = g := + ext (DFunLike.coe_injective h) + +lemma ext_apply {X Y : C} {f g : X ⟶ Y} (h : ∀ x, f x = g x) : f = g := + ext (DFunLike.ext _ _ h) + +/-- A concrete category comes with a forgetful functor to `Type`. + +Warning: because of the way that `ConcreteCategory` and `HasForget` are set up, we can't make +`forget Type` reducibly defeq to the identity functor. -/ +instance toHasForget : HasForget C where + forget.obj := ToType + forget.map f := ⇑(hom f) + forget_faithful.map_injective h := coe_ext h + +end ConcreteCategory + +theorem forget_obj (X : C) : (forget C).obj X = ToType X := by + with_reducible_and_instances rfl + +@[simp] +theorem ConcreteCategory.forget_map_eq_coe {X Y : C} (f : X ⟶ Y) : (forget C).map f = f := by + with_reducible_and_instances rfl + +/-- Analogue of `congr_fun h x`, +when `h : f = g` is an equality between morphisms in a concrete category. +-/ +protected theorem congr_fun {X Y : C} {f g : X ⟶ Y} (h : f = g) (x : ToType X) : f x = g x := + congrFun (congrArg (fun k : X ⟶ Y => (k : ToType X → ToType Y)) h) x + +/-- Analogue of `congr_arg f h`, +when `h : x = x'` is an equality between elements of objects in a concrete category. +-/ +protected theorem congr_arg {X Y : C} (f : X ⟶ Y) {x x' : ToType X} (h : x = x') : f x = f x' := + congrArg (f : ToType X → ToType Y) h + +theorem hom_id {X : C} : (𝟙 X : ToType X → ToType X) = id := + (forget _).map_id X + +theorem hom_comp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) : (f ≫ g : ToType X → ToType Z) = g ∘ f := + (forget _).map_comp f g + +section + +variable (C) + +/-- Build a coercion to functions out of `HasForget`. + +The intended usecase is to provide a `FunLike` instance in `HasForget.toConcreteCategory`. +See that definition for the considerations in making this an instance. + +See note [reducible non-instances]. +-/ +abbrev HasForget.toFunLike [HasForget C] (X Y : C) : + FunLike (X ⟶ Y) ((forget C).obj X) ((forget C).obj Y) where + coe := (forget C).map + coe_injective' _ _ h := Functor.Faithful.map_injective h + +/-- Build a concrete category out of `HasForget`. + +The intended usecase is to prove theorems referencing only `(forget C)` +and not `(forget C).obj X` nor `(forget C).map f`: those should be written +as `ToType X` and `ConcreteCategory.hom f` respectively. + +See note [reducible non-instances]. +-/ +abbrev HasForget.toConcreteCategory [HasForget C] : + ConcreteCategory C (· ⟶ ·) where + hom f := f + ofHom f := f + id_apply := congr_fun ((forget C).map_id _) + comp_apply _ _ := congr_fun ((forget C).map_comp _ _) + +/-- Check that the new `ConcreteCategory` has the same forgetful functor as we started with. -/ +example [inst : HasForget C] : + @forget C _ ((HasForget.toConcreteCategory _).toHasForget) = @forget C _ inst := by + with_reducible_and_instances rfl + +/-- +Note that the `ConcreteCategory` and `HasForget` instances here differ from `forget_map_eq_coe`. +-/ +theorem forget_eq_ConcreteCategory_hom [HasForget C] {X Y : C} (f : X ⟶ Y) : + (forget C).map f = @ConcreteCategory.hom _ _ _ _ _ (HasForget.toConcreteCategory C) _ _ f := by + with_reducible_and_instances rfl + +/-- A `FunLike` instance on plain functions, in order to instantiate a `ConcreteCategory` structure +on the category of types. + +This is not an instance (yet) because that would require a lot of downstream fixes. + +See note [reducible non-instances]. +-/ +abbrev Types.instFunLike : ∀ X Y : Type u, FunLike (X ⟶ Y) X Y := HasForget.toFunLike _ + +/-- The category of types is concrete, using the identity functor. + +This is not an instance (yet) because that would require a lot of downstream fixes. + +See note [reducible non-instances]. +-/ +abbrev Types.instConcreteCategory : ConcreteCategory (Type u) (fun X Y => X ⟶ Y) where + hom f := f + ofHom f := f + +end + +end ConcreteCategory + end CategoryTheory From 383fdb645cf41f8ef6a788ad3d12d3d3da5e6725 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Fri, 17 Jan 2025 18:04:09 +0000 Subject: [PATCH 288/681] feat(Tactic): basic ConcreteCategory support for elementwise (#20811) This is a step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This PR adds basic support for `ConcreteCategory` to the `elementwise` attribute and elaborator: it still uses `HasForget` when a fresh instance is needed, but now will replace the `forget`-based operations with `ConcreteCategory`-based ones. So as long as there is only a `HasForget` instance, or no instance at all, in scope, `elementwise` will behave the same. But when there is a `ConcreteCategory` instance, all the `(forget C).obj X`es turn into `ToType X` and `(forget C).map f`s turn into `hom f`. In the future, when we have replaced enough `HasForget` instances with `ConcreteCategory`, we can apply the changes from the branch `redesign-ConcreteCategory` to make `elementwise` use `ConcreteCategory` when it creates fresh instances. --- .../ConcreteCategory/Basic.lean | 7 + .../Tactic/CategoryTheory/Elementwise.lean | 10 +- MathlibTest/CategoryTheory/Elementwise.lean | 174 ++++++++++++++++++ 3 files changed, 189 insertions(+), 2 deletions(-) diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 55f2c36323721..5057020dc6114 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -355,6 +355,13 @@ theorem hom_id {X : C} : (𝟙 X : ToType X → ToType X) = id := theorem hom_comp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) : (f ≫ g : ToType X → ToType Z) = g ∘ f := (forget _).map_comp f g +/-- Using the `FunLike` coercion of `HasForget` does the same as the original coercion. +-/ +theorem coe_toHasForget_instFunLike {C : Type*} [Category C] {FC : C → C → Type*} {CC : C → Type*} + [inst : ∀ X Y : C, FunLike (FC X Y) (CC X) (CC Y)] [ConcreteCategory C FC] {X Y : C} + (f : X ⟶ Y) : + @DFunLike.coe (X ⟶ Y) (ToType X) (fun _ => ToType Y) HasForget.instFunLike f = f := rfl + section variable (C) diff --git a/Mathlib/Tactic/CategoryTheory/Elementwise.lean b/Mathlib/Tactic/CategoryTheory/Elementwise.lean index ff726b22fa41d..dc62fc50607d5 100644 --- a/Mathlib/Tactic/CategoryTheory/Elementwise.lean +++ b/Mathlib/Tactic/CategoryTheory/Elementwise.lean @@ -56,10 +56,16 @@ end theorems /-- List of simp lemmas to apply to the elementwise theorem. -/ def elementwiseThms : List Name := - [``CategoryTheory.coe_id, ``CategoryTheory.coe_comp, ``CategoryTheory.comp_apply, + [ -- HasForget lemmas + ``CategoryTheory.coe_id, ``CategoryTheory.coe_comp, ``CategoryTheory.comp_apply, ``CategoryTheory.id_apply, + -- ConcreteCategory lemmas + ``CategoryTheory.hom_id, ``CategoryTheory.hom_comp, ``id_eq, ``Function.comp_apply, -- further simplifications if the category is `Type` - ``forget_hom_Type, ``forall_congr_forget_Type, + ``forget_hom_Type, ``forall_congr_forget_Type, ``types_comp_apply, ``types_id_apply, + -- further simplifications to turn `HasForget` definitions into `ConcreteCategory` ones + -- (if available) + ``forget_obj, ``ConcreteCategory.forget_map_eq_coe, ``coe_toHasForget_instFunLike, -- simp can itself simplify trivial equalities into `true`. Adding this lemma makes it -- easier to detect when this has occurred. ``implies_true] diff --git a/MathlibTest/CategoryTheory/Elementwise.lean b/MathlibTest/CategoryTheory/Elementwise.lean index fd9a3578265a6..b2c18b4f5064c 100644 --- a/MathlibTest/CategoryTheory/Elementwise.lean +++ b/MathlibTest/CategoryTheory/Elementwise.lean @@ -6,6 +6,8 @@ set_option autoImplicit true namespace ElementwiseTest open CategoryTheory +namespace HasForget + attribute [simp] Iso.hom_inv_id Iso.inv_hom_id IsIso.hom_inv_id IsIso.inv_hom_id attribute [local instance] HasForget.instFunLike HasForget.hasCoeToSort @@ -134,4 +136,176 @@ variable (X : C) [HasForget C] (x : X) #guard_msgs in #check fh_apply X x +end HasForget + +namespace ConcreteCategory + +attribute [simp] Iso.hom_inv_id Iso.inv_hom_id IsIso.hom_inv_id IsIso.inv_hom_id + +attribute [simp] Iso.hom_inv_id Iso.inv_hom_id IsIso.hom_inv_id IsIso.inv_hom_id + +variable {C : Type*} {FC : C → C → Type*} {CC : C → Type*} +variable [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] + +@[elementwise] +theorem ex1 [Category C] [ConcreteCategory C FC] (X : C) (f g h : X ⟶ X) (h' : g ≫ h = h ≫ g) : + f ≫ g ≫ h = f ≫ h ≫ g := by rw [h'] + +-- If there is already a `ConcreteCategory` instance, do not add a new argument. +example : ∀ C {FC : C → C → Type*} {CC : C → Type*} [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] [Category C] [ConcreteCategory C FC] (X : C) (f g h : X ⟶ X) (_ : g ≫ h = h ≫ g) + (x : ToType X), h (g (f x)) = g (h (f x)) := @ex1_apply + +/- +-- TODO: `elementwise` currently uses `HasForget` to generate its lemmas. +-- Enable the commented-out tests below (and replace the corresponding tests above) +-- when we switch to `ConcreteCategory`. + +@[elementwise] +theorem ex2 [Category C] (X : C) (f g h : X ⟶ X) (h' : g ≫ h = h ≫ g) : + f ≫ g ≫ h = f ≫ h ≫ g := by rw [h'] + +-- If there is not already a `ConcreteCategory` instance, insert a new argument. +example : ∀ C [Category C] (X : C) (f g h : X ⟶ X) (_ : g ≫ h = h ≫ g) + {FC : C → C → Type _} {CC : C → Type _} [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] + [ConcreteCategory C FC] + (x : ToType X), h (g (f x)) = g (h (f x)) := @ex2_apply + +-- Need nosimp on the following `elementwise` since the lemma can be proved by simp anyway. +@[elementwise nosimp] +theorem ex3 [Category C] {X Y : C} (f : X ≅ Y) : f.hom ≫ f.inv = 𝟙 X := + Iso.hom_inv_id _ + +example : ∀ C [Category C] (X Y : C) (f : X ≅ Y) + {FC : C → C → Type _} {CC : C → Type _} [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] + [ConcreteCategory C FC] + (x : ToType X), + f.inv (f.hom x) = x := @ex3_apply + +-- Make sure there's no `id x` in there: +example : ∀ C [Category C] (X Y : C) (f : X ≅ Y) + {FC : C → C → Type _} {CC : C → Type _} [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] + [ConcreteCategory C FC] + (x : ToType X), + f.inv (f.hom x) = x := by intros; simp only [ex3_apply] +-/ + +@[elementwise] +lemma foo [Category C] + {M N K : C} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) : f ≫ 𝟙 N ≫ g = h := by + simp [w] + +@[elementwise] +lemma foo' [Category C] + {M N K : C} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) : f ≫ 𝟙 N ≫ g = h := by + simp [w] + +lemma bar [Category C] + {FC : C → C → Type _} {CC : C → Type _} [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] + [ConcreteCategory C FC] + {M N K : C} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : ToType M) : g (f x) = h x := by + apply foo_apply w + +example {M N K : Type} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : + g (f x) = h x := by + have := elementwise_of% w + guard_hyp this : ∀ (x : M), g (f x) = h x + exact this x + +example {M N K : Type} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : + g (f x) = h x := (elementwise_of% w) x + +example [Category C] {FC : C → C → Type _} {CC : C → Type _} + [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] [ConcreteCategory C FC] + {M N K : C} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : ToType M) : + g (f x) = h x := by + have := elementwise_of% w + guard_hyp this : ∀ (x : ToType M), g (f x) = h x + exact this x + +/- +-- TODO: `elementwise` currently uses `HasForget` to generate its lemmas. +-- Enable the commented-out tests below (and replace the corresponding tests above) +-- when we switch to `ConcreteCategory`. + +-- `elementwise_of%` allows level metavariables for its `ConcreteCategory` instance. +-- Previously this example did not specify that the universe levels of `C` and `D` (inside `h`) +-- were the same, and this constraint was added post-hoc by the proof term. +-- After https://github.com/leanprover/lean4/pull/4493 this no longer works (happily!). +example {C : Type u} [Category.{v} C] {FC : C → C → Type _} {CC : C → Type w} + [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] + [ConcreteCategory C FC] + (h : ∀ (D : Type u) [Category.{v} D] (X Y : D) (f : X ⟶ Y) (g : Y ⟶ X), f ≫ g = 𝟙 X) + {M N : C} {f : M ⟶ N} {g : N ⟶ M} (x : ToType M) : g (f x) = x := by + have := elementwise_of% h + guard_hyp this : ∀ D [Category D] (X Y : D) (f : X ⟶ Y) (g : Y ⟶ X) {FD : D → D → Type*} + {CD : D → Type*} [∀ X Y, FunLike (FD X Y) (CD X) (CD Y)] + [ConcreteCategory D FD] + (x : ToType X), g (f x) = x + rw [this] +-/ + +section Mon + +lemma bar' {M N K : MonCat} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : + g (f x) = h x := by exact foo_apply w x + +lemma bar'' {M N K : MonCat} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : + g (f x) = h x := by apply foo_apply w + +lemma bar''' {M N K : MonCat} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : + g (f x) = h x := by apply foo_apply w + +example (M N K : MonCat) (f : M ⟶ N) (g : N ⟶ K) (h : M ⟶ K) (w : f ≫ g = h) (m : M) : + g (f m) = h m := by rw [elementwise_of% w] + +example (M N K : MonCat) (f : M ⟶ N) (g : N ⟶ K) (h : M ⟶ K) (w : f ≫ g = h) (m : M) : + g (f m) = h m := by + -- Porting note: did not port `elementwise!` tactic + replace w := elementwise_of% w + apply w + +end Mon + +example {α β : Type} (f g : α ⟶ β) (w : f = g) (a : α) : f a = g a := by + -- Porting note: did not port `elementwise!` tactic + replace w := elementwise_of% w + guard_hyp w : ∀ (x : α), f x = g x + rw [w] + + +example {α β : Type} (f g : α ⟶ β) (w : f ≫ 𝟙 β = g) (a : α) : f a = g a := by + -- Porting note: did not port `elementwise!` tactic + replace w := elementwise_of% w + guard_hyp w : ∀ (x : α), f x = g x + rw [w] + +/- +-- TODO: `elementwise` currently uses `HasForget` to generate its lemmas. +-- Enable the commented-out tests below (and replace the corresponding tests above) +-- when we switch to `ConcreteCategory`. + +variable {C : Type*} [Category C] + +def f (X : C) : X ⟶ X := 𝟙 X +def g (X : C) : X ⟶ X := 𝟙 X +def h (X : C) : X ⟶ X := 𝟙 X + +lemma gh (X : C) : g X = h X := rfl + +@[elementwise] +theorem fh (X : C) : f X = h X := gh X + +variable (X : C) {FC : C → C → Type*} {CC : C → Type*} +variable [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] [ConcreteCategory C FC] +variable (x : ToType X) + +-- Prior to https://github.com/leanprover-community/mathlib4/pull/13413 this would produce +-- `fh_apply X x : (g X) x = (h X) x`. +/-- info: fh_apply X x : (ConcreteCategory.hom (f X)) x = (ConcreteCategory.hom (h X)) x -/ +#guard_msgs in +#check fh_apply X x +-/ + +end ConcreteCategory + end ElementwiseTest From 80283e82493b544a6a60aa1e61bb206268ee11f5 Mon Sep 17 00:00:00 2001 From: Oliver Nash Date: Fri, 17 Jan 2025 18:44:04 +0000 Subject: [PATCH 289/681] feat: define bases of root pairings (#20667) --- Mathlib.lean | 1 + Mathlib/LinearAlgebra/RootSystem/Base.lean | 214 +++++++++++++++++++++ Mathlib/LinearAlgebra/RootSystem/Defs.lean | 47 +++++ 3 files changed, 262 insertions(+) create mode 100644 Mathlib/LinearAlgebra/RootSystem/Base.lean diff --git a/Mathlib.lean b/Mathlib.lean index 4a69dea48edc2..4ac20c6ec4516 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3573,6 +3573,7 @@ import Mathlib.LinearAlgebra.Quotient.Defs import Mathlib.LinearAlgebra.Quotient.Pi import Mathlib.LinearAlgebra.Ray import Mathlib.LinearAlgebra.Reflection +import Mathlib.LinearAlgebra.RootSystem.Base import Mathlib.LinearAlgebra.RootSystem.Basic import Mathlib.LinearAlgebra.RootSystem.Defs import Mathlib.LinearAlgebra.RootSystem.Finite.CanonicalBilinear diff --git a/Mathlib/LinearAlgebra/RootSystem/Base.lean b/Mathlib/LinearAlgebra/RootSystem/Base.lean new file mode 100644 index 0000000000000..e21237212ee01 --- /dev/null +++ b/Mathlib/LinearAlgebra/RootSystem/Base.lean @@ -0,0 +1,214 @@ +/- +Copyright (c) 2025 Oliver Nash. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Oliver Nash +-/ +import Mathlib.LinearAlgebra.RootSystem.Defs + +/-! +# Bases for root pairings / systems + +This file contains a theory of bases for root pairings / systems. + +## Implementation details + +For reduced root pairings `RootSystem.Base` is equivalent to the usual definition appearing in the +informal literature (e.g., it follows from [serre1965](Ch. V, §8, Proposition 7) that +`RootSystem.Base` is equivalent to both [serre1965](Ch. V, §8, Definition 5) and +[bourbaki1968](Ch. VI, §1.5) for reduced pairings). However for non-reduced root pairings, it is +more restrictive because it includes axioms on coroots as well as on roots. For example by +`RootPairing.Base.eq_one_or_neg_one_of_mem_support_of_smul_mem` it is clear that the 1-dimensional +root system `{-2, -1, 0, 1, 2} ⊆ ℝ` has no base in the sense of `RootSystem.Base`. + +It is also worth remembering that it is only for reduced root systems that one has the simply +transitive action of the Weyl group on the set of bases, and that the Weyl group of a non-reduced +root system is the same as that of the reduced root system obtained by passing to the indivisible +roots. + +For infinite root systems, `RootSystem.Base` is usually not the right notion: linear independence +is too strong. + +## Main definitions / results: + * `RootSystem.Base`: a base of a root pairing. + +## TODO + + * Develop a theory of base / separation / positive roots for infinite systems which specialises to + the concept here for finite systems. + +-/ + +noncomputable section + +open Function Set Submodule + +variable {ι R M N : Type*} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] + +namespace RootPairing + +/-- A base of a root pairing. + +For reduced root pairings this definition is equivalent to the usual definition appearing in the +informal literature but not for non-reduced root pairings it is more restrictive. See the module +doc string for further remarks. -/ +structure Base (P : RootPairing ι R M N) where + /-- The set of roots / coroots belonging to the base. -/ + support : Set ι + linInd_root : LinearIndependent R fun i : support ↦ P.root i + linInd_coroot : LinearIndependent R fun i : support ↦ P.coroot i + root_mem_or_neg_mem (i : ι) : P.root i ∈ AddSubmonoid.closure (P.root '' support) ∨ + - P.root i ∈ AddSubmonoid.closure (P.root '' support) + coroot_mem_or_neg_mem (i : ι) : P.coroot i ∈ AddSubmonoid.closure (P.coroot '' support) ∨ + - P.coroot i ∈ AddSubmonoid.closure (P.coroot '' support) + +namespace Base + +section RootPairing + +variable {P : RootPairing ι R M N} (b : P.Base) + +/-- Interchanging roots and coroots, one still has a base of a root pairing. -/ +@[simps] protected def flip : + P.flip.Base where + support := b.support + linInd_root := b.linInd_coroot + linInd_coroot := b.linInd_root + root_mem_or_neg_mem := b.coroot_mem_or_neg_mem + coroot_mem_or_neg_mem := b.root_mem_or_neg_mem + +lemma root_mem_span_int (i : ι) : + P.root i ∈ span ℤ (P.root '' b.support) := by + have := b.root_mem_or_neg_mem i + simp only [← span_nat_eq_addSubmonoid_closure, mem_toAddSubmonoid] at this + rw [← span_span_of_tower (R := ℕ)] + rcases this with hi | hi + · exact subset_span hi + · rw [← neg_mem_iff] + exact subset_span hi + +lemma coroot_mem_span_int (i : ι) : + P.coroot i ∈ span ℤ (P.coroot '' b.support) := + b.flip.root_mem_span_int i + +@[simp] +lemma span_int_root_support : + span ℤ (P.root '' b.support) = span ℤ (range P.root) := by + refine le_antisymm (span_mono <| image_subset_range _ _) (span_le.mpr ?_) + rintro - ⟨i, rfl⟩ + exact b.root_mem_span_int i + +@[simp] +lemma span_int_coroot_support : + span ℤ (P.coroot '' b.support) = span ℤ (range P.coroot) := + b.flip.span_int_root_support + +@[simp] +lemma span_root_support : + span R (P.root '' b.support) = P.rootSpan := by + rw [← span_span_of_tower (R := ℤ), span_int_root_support, span_span_of_tower] + +@[simp] +lemma span_coroot_support : + span R (P.coroot '' b.support) = P.corootSpan := + b.flip.span_root_support + +open Finsupp in +lemma eq_one_or_neg_one_of_mem_support_of_smul_mem_aux [Finite ι] + [NoZeroSMulDivisors ℤ M] [NoZeroSMulDivisors ℤ N] + (i : ι) (h : i ∈ b.support) (t : R) (ht : t • P.root i ∈ range P.root) : + ∃ z : ℤ, z * t = 1 := by + classical + have : Fintype ι := Fintype.ofFinite ι + obtain ⟨j, hj⟩ := ht + obtain ⟨f, hf⟩ : ∃ f : b.support → ℤ, P.coroot i = ∑ i, (t * f i) • P.coroot i := by + have : P.coroot j ∈ span ℤ (P.coroot '' b.support) := b.coroot_mem_span_int j + rw [image_eq_range, mem_span_range_iff_exists_fun] at this + refine this.imp fun f hf ↦ ?_ + simp_rw [mul_smul, ← Finset.smul_sum, Int.cast_smul_eq_zsmul, hf, + coroot_eq_smul_coroot_iff.mpr hj] + use f ⟨i, h⟩ + replace hf : P.coroot i = linearCombination R (fun k : b.support ↦ P.coroot k) + (t • (linearEquivFunOnFinite R _ _).symm (fun x ↦ (f x : R))) := by + rw [map_smul, linearCombination_eq_fintype_linearCombination_apply R R, + Fintype.linearCombination_apply, hf] + simp_rw [mul_smul, ← Finset.smul_sum] + let g : b.support →₀ R := single ⟨i, h⟩ 1 + have hg : P.coroot i = linearCombination R (fun k : b.support ↦ P.coroot k) g := by simp [g] + rw [hg] at hf + have : Injective (linearCombination R fun k : b.support ↦ P.coroot k) := b.linInd_coroot + simpa [g, linearEquivFunOnFinite, mul_comm t] using (DFunLike.congr_fun (this hf) ⟨i, h⟩).symm + +lemma eq_one_or_neg_one_of_mem_support_of_smul_mem [Finite ι] [CharZero R] + [NoZeroSMulDivisors ℤ M] [NoZeroSMulDivisors ℤ N] + (i : ι) (h : i ∈ b.support) (t : R) (ht : t • P.root i ∈ range P.root) : + t = 1 ∨ t = - 1 := by + obtain ⟨z, hz⟩ := b.eq_one_or_neg_one_of_mem_support_of_smul_mem_aux i h t ht + obtain ⟨s, hs⟩ := IsUnit.exists_left_inv <| isUnit_of_mul_eq_one_right _ t hz + replace ht : s • P.coroot i ∈ range P.coroot := by + obtain ⟨j, hj⟩ := ht + simpa only [coroot_eq_smul_coroot_iff.mpr hj, smul_smul, hs, one_smul] using mem_range_self j + obtain ⟨w, hw⟩ := b.flip.eq_one_or_neg_one_of_mem_support_of_smul_mem_aux i h s ht + have : (z : R) * w = 1 := by + simpa [mul_mul_mul_comm _ t _ s, mul_comm t s, hs] using congr_arg₂ (· * ·) hz hw + suffices z = 1 ∨ z = - 1 by + rcases this with rfl | rfl + · left; simpa using hz + · right; simpa [neg_eq_iff_eq_neg] using hz + norm_cast at this + rw [Int.mul_eq_one_iff_eq_one_or_neg_one] at this + tauto + +end RootPairing + +section RootSystem + +variable {P : RootSystem ι R M N} (b : P.Base) + +/-- A base of a root system yields a basis of the root space. -/ +@[simps!] def toWeightBasis : + Basis b.support R M := + Basis.mk b.linInd_root <| by + change ⊤ ≤ span R (range <| P.root ∘ ((↑) : b.support → ι)) + rw [top_le_iff, range_comp, Subtype.range_coe_subtype, setOf_mem_eq, b.span_root_support] + exact P.span_root_eq_top + +/-- A base of a root system yields a basis of the coroot space. -/ +def toCoweightBasis : + Basis b.support R N := + Base.toWeightBasis (P := P.flip) b.flip + +include b +variable [Fintype ι] + +lemma exists_root_eq_sum_nat_or_neg (i : ι) : + ∃ f : ι → ℕ, P.root i = ∑ j, f j • P.root j ∨ P.root i = - ∑ j, f j • P.root j := by + classical + simp_rw [← neg_eq_iff_eq_neg] + suffices ∀ m ∈ AddSubmonoid.closure (P.root '' b.support), ∃ f : ι → ℕ, m = ∑ j, f j • P.root j by + rcases b.root_mem_or_neg_mem i with hi | hi + · obtain ⟨f, hf⟩ := this _ hi + exact ⟨f, Or.inl hf⟩ + · obtain ⟨f, hf⟩ := this _ hi + exact ⟨f, Or.inr hf⟩ + intro m hm + refine AddSubmonoid.closure_induction ?_ ⟨0, by simp⟩ ?_ hm + · rintro - ⟨j, hj, rfl⟩ + exact ⟨Pi.single j 1, by simp [Pi.single_apply]⟩ + · intro _ _ _ _ ⟨f, hf⟩ ⟨g, hg⟩ + exact ⟨f + g, by simp [hf, hg, add_smul, Finset.sum_add_distrib]⟩ + +lemma exists_root_eq_sum_int (i : ι) : + ∃ f : ι → ℤ, (0 ≤ f ∨ f ≤ 0) ∧ P.root i = ∑ j, f j • P.root j := by + obtain ⟨f, hf | hf⟩ := b.exists_root_eq_sum_nat_or_neg i + · exact ⟨ Nat.cast ∘ f, Or.inl fun _ ↦ by simp, by simp [hf]⟩ + · exact ⟨- Nat.cast ∘ f, Or.inr fun _ ↦ by simp, by simp [hf]⟩ + +lemma exists_coroot_eq_sum_int (i : ι) : + ∃ f : ι → ℤ, (0 ≤ f ∨ f ≤ 0) ∧ P.coroot i = ∑ j, f j • P.coroot j := + b.flip.exists_root_eq_sum_int i (P := P.flip) + +end RootSystem + +end Base + +end RootPairing diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index eaaf04a6c7bfd..8b01626b5d947 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -150,6 +150,33 @@ protected def flip : RootPairing ι R N M := lemma flip_flip : P.flip.flip = P := rfl +variable (ι R M N) in +/-- `RootPairing.flip` as an equivalence. -/ +@[simps] def flipEquiv : RootPairing ι R N M ≃ RootPairing ι R M N where + toFun P := P.flip + invFun P := P.flip + left_inv _ := rfl + right_inv _ := rfl + +/-- If we interchange the roles of `M` and `N`, we still have a root system. -/ +protected def _root_.RootSystem.flip (P : RootSystem ι R M N) : RootSystem ι R N M := + { toRootPairing := P.toRootPairing.flip + span_root_eq_top := P.span_coroot_eq_top + span_coroot_eq_top := P.span_root_eq_top } + +@[simp] +protected lemma _root_.RootSystem.flip_flip (P : RootSystem ι R M N) : + P.flip.flip = P := + rfl + +variable (ι R M N) in +/-- `RootSystem.flip` as an equivalence. -/ +@[simps] def _root_.RootSystem.flipEquiv : RootSystem ι R N M ≃ RootSystem ι R M N where + toFun P := P.flip + invFun P := P.flip + left_inv _ := rfl + right_inv _ := rfl + /-- Roots written as functionals on the coweight space. -/ abbrev root' (i : ι) : Dual R N := P.toPerfectPairing (P.root i) @@ -385,6 +412,26 @@ lemma isReduced_iff : P.IsReduced ↔ ∀ i j : ι, i ≠ j → · exact Or.inl (congrArg P.root h') · exact Or.inr (h i j h' hLin) +variable {P} in +lemma smul_coroot_eq_of_root_eq_smul [Finite ι] [NoZeroSMulDivisors ℤ N] (i j : ι) (t : R) + (h : P.root j = t • P.root i) : + t • P.coroot j = P.coroot i := by + have hij : t * P.pairing i j = 2 := by simpa using ((P.coroot' j).congr_arg h).symm + refine Module.eq_of_mapsTo_reflection_of_mem (f := P.root' i) (g := P.root' i) + (finite_range P.coroot) (by simp [hij]) (by simp) (by simp [hij]) (by simp) ?_ + (P.mapsTo_coreflection_coroot i) (mem_range_self i) + convert P.mapsTo_coreflection_coroot j + ext x + replace h : P.root' j = t • P.root' i := by ext; simp [h, root'] + simp [Module.preReflection_apply, coreflection_apply, h, smul_comm _ t, mul_smul] + +variable {P} in +@[simp] lemma coroot_eq_smul_coroot_iff [Finite ι] [NoZeroSMulDivisors ℤ M] [NoZeroSMulDivisors ℤ N] + {i j : ι} {t : R} : + P.coroot i = t • P.coroot j ↔ P.root j = t • P.root i := + ⟨fun h ↦ (P.flip.smul_coroot_eq_of_root_eq_smul j i t h).symm, + fun h ↦ (P.smul_coroot_eq_of_root_eq_smul i j t h).symm⟩ + /-- The linear span of roots. -/ abbrev rootSpan := span R (range P.root) From a4c5ecf11c62609afc9440d23079c3a952a22610 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Fri, 17 Jan 2025 19:10:14 +0000 Subject: [PATCH 290/681] feat(Algebra/Lie): a Lie algebra is solvable iff it is solvable after faithfully flat base change (#20808) --- Mathlib/Algebra/Lie/Nilpotent.lean | 1 - Mathlib/Algebra/Lie/Solvable.lean | 38 +++++++++++++++++++ .../RingTheory/Flat/FaithfullyFlat/Basic.lean | 16 ++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/Lie/Nilpotent.lean b/Mathlib/Algebra/Lie/Nilpotent.lean index 4e19fe0b77a4d..f190849ca1436 100644 --- a/Mathlib/Algebra/Lie/Nilpotent.lean +++ b/Mathlib/Algebra/Lie/Nilpotent.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ -import Mathlib.Algebra.Lie.BaseChange import Mathlib.Algebra.Lie.Solvable import Mathlib.Algebra.Lie.Quotient import Mathlib.Algebra.Lie.Normalizer diff --git a/Mathlib/Algebra/Lie/Solvable.lean b/Mathlib/Algebra/Lie/Solvable.lean index 7e9c2d579d51f..0a2796b4bdcc8 100644 --- a/Mathlib/Algebra/Lie/Solvable.lean +++ b/Mathlib/Algebra/Lie/Solvable.lean @@ -4,8 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.Algebra.Lie.Abelian +import Mathlib.Algebra.Lie.BaseChange import Mathlib.Algebra.Lie.IdealOperations import Mathlib.Order.Hom.Basic +import Mathlib.RingTheory.Flat.FaithfullyFlat.Basic /-! # Solvable Lie algebras @@ -121,6 +123,21 @@ theorem abelian_iff_derived_succ_eq_bot (I : LieIdeal R L) (k : ℕ) : IsLieAbelian (derivedSeriesOfIdeal R L k I) ↔ derivedSeriesOfIdeal R L (k + 1) I = ⊥ := by rw [add_comm, derivedSeriesOfIdeal_add I 1 k, abelian_iff_derived_one_eq_bot] +open TensorProduct in +@[simp] theorem derivedSeriesOfIdeal_baseChange {A : Type*} [CommRing A] [Algebra R A] (k : ℕ) : + derivedSeriesOfIdeal A (A ⊗[R] L) k (I.baseChange A) = + (derivedSeriesOfIdeal R L k I).baseChange A := by + induction k with + | zero => simp + | succ k ih => simp only [derivedSeriesOfIdeal_succ, ih, ← LieSubmodule.baseChange_top, + LieSubmodule.lie_baseChange] + +open TensorProduct in +@[simp] theorem derivedSeries_baseChange {A : Type*} [CommRing A] [Algebra R A] (k : ℕ) : + derivedSeries A (A ⊗[R] L) k = (derivedSeries R L k).baseChange A := by + rw [derivedSeries_def, derivedSeries_def, ← derivedSeriesOfIdeal_baseChange, + LieSubmodule.baseChange_top] + end LieAlgebra namespace LieIdeal @@ -262,6 +279,27 @@ theorem derivedSeries_lt_top_of_solvable [IsSolvable L] [Nontrivial L] : rw [LieIdeal.derivedSeries_eq_top n contra] at hn exact top_ne_bot hn +open TensorProduct in +instance {A : Type*} [CommRing A] [Algebra R A] [IsSolvable L] : IsSolvable (A ⊗[R] L) := by + obtain ⟨k, hk⟩ := IsSolvable.solvable R L + rw [isSolvable_iff A] + use k + rw [derivedSeries_baseChange, hk, LieSubmodule.baseChange_bot] + +open TensorProduct in +variable {A : Type*} [CommRing A] [Algebra R A] [Module.FaithfullyFlat R A] in +theorem isSolvable_tensorProduct_iff : IsSolvable (A ⊗[R] L) ↔ IsSolvable L := by + refine ⟨?_, fun _ ↦ inferInstance⟩ + rw [isSolvable_iff A, isSolvable_iff R] + rintro ⟨k, h⟩ + use k + rw [eq_bot_iff] at h ⊢ + intro x hx + rw [derivedSeries_baseChange] at h + specialize h <| Submodule.tmul_mem_baseChange_of_mem 1 hx + rw [LieSubmodule.mem_bot] at h ⊢ + rwa [Module.FaithfullyFlat.one_tmul_eq_zero_iff] at h + end LieAlgebra variable {R L} diff --git a/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean b/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean index 20f5be74403eb..8ec279aded6ee 100644 --- a/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean +++ b/Mathlib/RingTheory/Flat/FaithfullyFlat/Basic.lean @@ -426,6 +426,22 @@ lemma zero_iff_rTensor_zero [h: FaithfullyFlat R M] (by simpa using congr($h (m ⊗ₜ n))), fun h => by ext m n; exact (TensorProduct.comm R M N').injective <| (by simpa using congr($h (n ⊗ₜ m)))⟩ +/-- If `A` is a faithfully flat `R`-algebra, and `m` is a term of an `R`-module `M`, +then `1 ⊗ₜ[R] m = 0` if and only if `m = 0`. -/ +@[simp] +theorem one_tmul_eq_zero_iff {A : Type*} [CommRing A] [Algebra R A] [FaithfullyFlat R A] (m : M) : + (1:A) ⊗ₜ[R] m = 0 ↔ m = 0 := by + constructor; swap + · rintro rfl; rw [tmul_zero] + intro h + let f : R →ₗ[R] M := (LinearMap.lsmul R M).flip m + suffices f = 0 by simpa [f] using DFunLike.congr_fun this 1 + rw [Module.FaithfullyFlat.zero_iff_lTensor_zero R A] + ext a + apply_fun (a • ·) at h + rw [smul_zero, smul_tmul', smul_eq_mul, mul_one] at h + simpa [f] + end arbitrary_universe section fixed_universe From 73658685379287b6f21116441a34f6e08bfdac0b Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Sat, 18 Jan 2025 05:22:14 +0000 Subject: [PATCH 291/681] chore: eliminate porting notes about `deriving Fintype` (#20820) --- Mathlib/Computability/Encoding.lean | 12 ++++-------- Mathlib/Data/Sign.lean | 8 ++------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/Mathlib/Computability/Encoding.lean b/Mathlib/Computability/Encoding.lean index 911d03a50e087..67db006d7f41b 100644 --- a/Mathlib/Computability/Encoding.lean +++ b/Mathlib/Computability/Encoding.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Fintype.Basic import Mathlib.Data.Num.Lemmas import Mathlib.Data.Option.Basic import Mathlib.SetTheory.Cardinal.Basic +import Mathlib.Tactic.DeriveFintype /-! # Encodings @@ -55,12 +56,7 @@ inductive Γ' | bra | ket | comma - deriving DecidableEq - --- Porting note: A handler for `Fintype` had not been implemented yet. -instance Γ'.fintype : Fintype Γ' := - ⟨⟨{.blank, .bit true, .bit false, .bra, .ket, .comma}, by decide⟩, - by intro; cases_type* Γ' Bool <;> decide⟩ + deriving DecidableEq, Fintype instance inhabitedΓ' : Inhabited Γ' := ⟨Γ'.blank⟩ @@ -154,9 +150,9 @@ def encodingNatΓ' : Encoding ℕ where -- instead. rw [List.map_map, leftInverse_section_inclusion.id, List.map_id, decode_encodeNat] -/-- A binary fin_encoding of ℕ in Γ'. -/ +/-- A binary FinEncoding of ℕ in Γ'. -/ def finEncodingNatΓ' : FinEncoding ℕ := - ⟨encodingNatΓ', Γ'.fintype⟩ + ⟨encodingNatΓ', inferInstanceAs (Fintype Γ')⟩ /-- A unary encoding function of ℕ in bool. -/ def unaryEncodeNat : Nat → List Bool diff --git a/Mathlib/Data/Sign.lean b/Mathlib/Data/Sign.lean index 55941cf1dae35..b9ca1bae2f936 100644 --- a/Mathlib/Data/Sign.lean +++ b/Mathlib/Data/Sign.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.GroupWithZero.Units.Lemmas import Mathlib.Algebra.Order.BigOperators.Group.Finset import Mathlib.Algebra.Order.Ring.Cast import Mathlib.Data.Fintype.BigOperators +import Mathlib.Tactic.DeriveFintype /-! # Sign function @@ -15,13 +16,12 @@ This file defines the sign function for types with zero and a decidable less-tha proves some basic theorems about it. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11081): cannot automatically derive Fintype, added manually /-- The type of signs. -/ inductive SignType | zero | neg | pos - deriving DecidableEq, Inhabited + deriving DecidableEq, Inhabited, Fintype -- Porting note: these lemmas are autogenerated by the inductive definition and are not -- in simple form due to the below `x_eq_x` lemmas @@ -31,10 +31,6 @@ attribute [nolint simpNF] SignType.pos.sizeOf_spec namespace SignType --- Porting note: Added Fintype SignType manually -instance : Fintype SignType := - Fintype.ofMultiset (zero :: neg :: pos :: List.nil) (fun x ↦ by cases x <;> simp) - instance : Zero SignType := ⟨zero⟩ From 48a296cda0100e649fda683cef0262b9ae23e1ec Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Sat, 18 Jan 2025 14:49:41 +0000 Subject: [PATCH 292/681] chore: cleanup many porting notes in Combinatorics (#20823) --- Mathlib/Combinatorics/Additive/Energy.lean | 5 +---- Mathlib/Combinatorics/Configuration.lean | 3 --- Mathlib/Combinatorics/Derangements/Basic.lean | 3 +-- Mathlib/Combinatorics/Enumerative/Catalan.lean | 15 +-------------- .../Combinatorics/Enumerative/Composition.lean | 6 ------ Mathlib/Combinatorics/HalesJewett.lean | 1 - Mathlib/Combinatorics/Hindman.lean | 3 --- Mathlib/Combinatorics/Quiver/Covering.lean | 7 ++----- Mathlib/Combinatorics/Quiver/Prefunctor.lean | 1 - Mathlib/Combinatorics/Quiver/Subquiver.lean | 4 ++-- Mathlib/Combinatorics/Quiver/Symmetric.lean | 2 +- .../Combinatorics/SetFamily/Compression/Down.lean | 2 +- Mathlib/Combinatorics/SetFamily/LYM.lean | 2 -- Mathlib/Combinatorics/SetFamily/Shadow.lean | 4 +--- Mathlib/Combinatorics/SimpleGraph/Basic.lean | 6 ------ Mathlib/Combinatorics/SimpleGraph/Coloring.lean | 2 -- Mathlib/Combinatorics/SimpleGraph/Dart.lean | 3 --- Mathlib/Combinatorics/SimpleGraph/Density.lean | 3 +-- Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean | 2 +- Mathlib/Combinatorics/SimpleGraph/Finite.lean | 5 ----- Mathlib/Combinatorics/SimpleGraph/IncMatrix.lean | 8 ++------ Mathlib/Combinatorics/SimpleGraph/Path.lean | 4 +--- Mathlib/Combinatorics/SimpleGraph/Prod.lean | 2 -- .../SimpleGraph/Regularity/Bound.lean | 8 +++----- .../SimpleGraph/Regularity/Equitabilise.lean | 5 +---- .../SimpleGraph/StronglyRegular.lean | 5 +---- Mathlib/Combinatorics/SimpleGraph/Walk.lean | 6 +----- Mathlib/Combinatorics/Young/YoungDiagram.lean | 5 +---- 28 files changed, 22 insertions(+), 100 deletions(-) diff --git a/Mathlib/Combinatorics/Additive/Energy.lean b/Mathlib/Combinatorics/Additive/Energy.lean index e1f1d36d3e389..8e9f4b0c90c20 100644 --- a/Mathlib/Combinatorics/Additive/Energy.lean +++ b/Mathlib/Combinatorics/Additive/Energy.lean @@ -84,10 +84,7 @@ lemma mulEnergy_mono (hs : s₁ ⊆ s₂) (ht : t₁ ⊆ t₂) : Eₘ[s₁, t₁ @[to_additive] lemma le_mulEnergy : s.card * t.card ≤ Eₘ[s, t] := by rw [← card_product] refine - card_le_card_of_injOn (@fun x => ((x.1, x.1), x.2, x.2)) (by - -- Porting note: changed this from a `simp` proof without `only` because of a timeout - simp only [← and_imp, mem_product, Prod.forall, mem_filter, and_self, and_true, imp_self, - implies_true]) fun a _ b _ => ?_ + card_le_card_of_injOn (@fun x => ((x.1, x.1), x.2, x.2)) (by simp) fun a _ b _ => ?_ simp only [Prod.mk.inj_iff, and_self_iff, and_imp] exact Prod.ext diff --git a/Mathlib/Combinatorics/Configuration.lean b/Mathlib/Combinatorics/Configuration.lean index 91afb4626b98f..92e86eaa7e632 100644 --- a/Mathlib/Combinatorics/Configuration.lean +++ b/Mathlib/Combinatorics/Configuration.lean @@ -42,18 +42,15 @@ variable (P L : Type*) [Membership P L] def Dual := P --- Porting note: was `this` instead of `h` instance [h : Inhabited P] : Inhabited (Dual P) := h instance [Finite P] : Finite (Dual P) := ‹Finite P› --- Porting note: was `this` instead of `h` instance [h : Fintype P] : Fintype (Dual P) := h --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: figure out if this is needed. set_option synthInstance.checkSynthOrder false in instance : Membership (Dual L) (Dual P) := ⟨Function.swap (Membership.mem : L → P → Prop)⟩ diff --git a/Mathlib/Combinatorics/Derangements/Basic.lean b/Mathlib/Combinatorics/Derangements/Basic.lean index ac4e2f3b84276..de6307552ceae 100644 --- a/Mathlib/Combinatorics/Derangements/Basic.lean +++ b/Mathlib/Combinatorics/Derangements/Basic.lean @@ -96,9 +96,8 @@ def atMostOneFixedPointEquivSum_derangements [DecidableEq α] (a : α) : · rw [Set.eq_empty_iff_forall_not_mem] exact ⟨fun h x hx => h.2 (h.1 hx ▸ hx), fun h => ⟨fun x hx => (h _ hx).elim, h _⟩⟩ _ ≃ derangements ({a}ᶜ : Set α) ⊕ derangements α := by - -- Porting note: was `subtypeEquiv _` but now needs the placeholder to be provided explicitly refine - Equiv.sumCongr ((derangements.subtypeEquiv (· ∈ ({a}ᶜ : Set α))).trans <| + Equiv.sumCongr ((derangements.subtypeEquiv _).trans <| subtypeEquivRight fun x => ?_).symm (subtypeEquivRight fun f => mem_derangements_iff_fixedPoints_eq_empty.symm) rw [eq_comm, Set.ext_iff] diff --git a/Mathlib/Combinatorics/Enumerative/Catalan.lean b/Mathlib/Combinatorics/Enumerative/Catalan.lean index b69b6c29f6a33..0ba1191b7ca95 100644 --- a/Mathlib/Combinatorics/Enumerative/Catalan.lean +++ b/Mathlib/Combinatorics/Enumerative/Catalan.lean @@ -150,11 +150,7 @@ def treesOfNumNodesEq : ℕ → Finset (Tree Unit) | 0 => {nil} | n + 1 => (antidiagonal n).attach.biUnion fun ijh => - -- Porting note: `unusedHavesSuffices` linter is not happy with this. Commented out. - -- have := Nat.lt_succ_of_le (fst_le ijh.2) - -- have := Nat.lt_succ_of_le (snd_le ijh.2) pairwiseNode (treesOfNumNodesEq ijh.1.1) (treesOfNumNodesEq ijh.1.2) - -- Porting note: Add this to satisfy the linter. decreasing_by · simp_wf; have := fst_le ijh.2; omega · simp_wf; have := snd_le ijh.2; omega @@ -192,15 +188,6 @@ theorem treesOfNumNodesEq_card_eq_catalan (n : ℕ) : #(treesOfNumNodesEq n) = c rintro ⟨i, j⟩ H rw [card_map, card_product, ih _ (fst_le H), ih _ (snd_le H)] · simp_rw [disjoint_left] - rintro ⟨i, j⟩ _ ⟨i', j'⟩ _ - -- Porting note: was clear * -; tidy - intros h a - cases' a with a l r - · intro h; simp at h - · intro h1 h2 - apply h - trans (numNodes l, numNodes r) - · simp at h1; simp [h1] - · simp at h2; simp [h2] + aesop end Tree diff --git a/Mathlib/Combinatorics/Enumerative/Composition.lean b/Mathlib/Combinatorics/Enumerative/Composition.lean index e1bf3970d658a..b7b6c98651639 100644 --- a/Mathlib/Combinatorics/Enumerative/Composition.lean +++ b/Mathlib/Combinatorics/Enumerative/Composition.lean @@ -574,9 +574,6 @@ This makes sense mostly when `n = l.length`, but this is not necessary for the d def splitWrtComposition (l : List α) (c : Composition n) : List (List α) := splitWrtCompositionAux l c.blocks --- Porting note: can't refer to subeqn in Lean 4 this way, and seems to definitionally simp ---attribute [local simp] splitWrtCompositionAux.equations._eqn_1 - @[local simp] theorem splitWrtCompositionAux_cons (l : List α) (n ns) : l.splitWrtCompositionAux (n::ns) = take n l::(drop n l).splitWrtCompositionAux ns := by @@ -645,7 +642,6 @@ theorem getElem_splitWrtComposition' (l : List α) (c : Composition n) {i : ℕ} (l.splitWrtComposition c)[i] = (l.take (c.sizeUpTo (i + 1))).drop (c.sizeUpTo i) := getElem_splitWrtCompositionAux _ _ hi --- Porting note: restatement of `get_splitWrtComposition` theorem getElem_splitWrtComposition (l : List α) (c : Composition n) (i : Nat) (h : i < (l.splitWrtComposition c).length) : (l.splitWrtComposition c)[i] = (l.take (c.sizeUpTo (i + 1))).drop (c.sizeUpTo i) := @@ -666,7 +662,6 @@ theorem get_splitWrtComposition' (l : List α) (c : Composition n) {i : ℕ} (l.splitWrtComposition c).get ⟨i, hi⟩ = (l.take (c.sizeUpTo (i + 1))).drop (c.sizeUpTo i) := by simp [getElem_splitWrtComposition'] --- Porting note: restatement of `get_splitWrtComposition` @[deprecated getElem_splitWrtComposition (since := "2024-06-12")] theorem get_splitWrtComposition (l : List α) (c : Composition n) (i : Fin (l.splitWrtComposition c).length) : @@ -922,7 +917,6 @@ theorem Composition.toCompositionAsSet_blocks (c : Composition n) : eq_of_sum_take_eq length_eq H intro i hi have i_lt : i < d.boundaries.card := by - -- Porting note: relied on `convert` unfolding definitions, switched to using a `simpa` simpa [CompositionAsSet.blocks, length_ofFn, d.card_boundaries_eq_succ_length] using Nat.lt_succ_iff.2 hi have i_lt' : i < c.boundaries.card := i_lt diff --git a/Mathlib/Combinatorics/HalesJewett.lean b/Mathlib/Combinatorics/HalesJewett.lean index 082fd89e47b72..bc53c5115dbe1 100644 --- a/Mathlib/Combinatorics/HalesJewett.lean +++ b/Mathlib/Combinatorics/HalesJewett.lean @@ -420,7 +420,6 @@ private theorem exists_mono_in_high_dimension' : -- and adding to this the vertical line obtained by the focus point and `l`. refine Or.inl ⟨⟨(s.lines.map ?_).cons ⟨(l'.map some).vertical s.focus, C' s.focus, fun x => ?_⟩, Sum.elim s.focus (l'.map some none), ?_, ?_⟩, ?_⟩ - -- Porting note: Needed to reorder the following two goals -- The product lines are almost monochromatic. · refine fun p => ⟨p.line.prod (l'.map some), p.color, fun x => ?_⟩ rw [Line.prod_apply, Line.map_apply, ← p.has_color, ← congr_fun (hl' x)] diff --git a/Mathlib/Combinatorics/Hindman.lean b/Mathlib/Combinatorics/Hindman.lean index 59d2bb754770f..312ae28fa0af6 100644 --- a/Mathlib/Combinatorics/Hindman.lean +++ b/Mathlib/Combinatorics/Hindman.lean @@ -79,9 +79,6 @@ theorem Ultrafilter.continuous_mul_left {M} [Semigroup M] (V : Ultrafilter M) : namespace Hindman --- Porting note: mathport wants these names to be `fS`, `fP`, etc, but this does violence to --- mathematical naming conventions, as does `fs`, `fp`, so we just followed `mathlib` 3 here - /-- `FS a` is the set of finite sums in `a`, i.e. `m ∈ FS a` if `m` is the sum of a nonempty subsequence of `a`. We give a direct inductive definition instead of talking about subsequences. -/ inductive FS {M} [AddSemigroup M] : Stream' M → Set M diff --git a/Mathlib/Combinatorics/Quiver/Covering.lean b/Mathlib/Combinatorics/Quiver/Covering.lean index 0e30025d9de92..ba60602599454 100644 --- a/Mathlib/Combinatorics/Quiver/Covering.lean +++ b/Mathlib/Combinatorics/Quiver/Covering.lean @@ -190,11 +190,8 @@ theorem Prefunctor.pathStar_injective (hφ : ∀ u, Injective (φ.star u)) (u : rintro ⟨y₂, p₂⟩ <;> cases' p₂ with x₂ _ p₂ e₂ <;> intro h <;> - -- Porting note: added `Sigma.mk.inj_iff` - simp only [Prefunctor.pathStar_apply, Prefunctor.mapPath_nil, Prefunctor.mapPath_cons, - Sigma.mk.inj_iff] at h - · -- Porting note: goal not present in lean3. - rfl + simp at h + · rfl · exfalso cases' h with h h' rw [← Path.eq_cast_iff_heq rfl h.symm, Path.cast_cons] at h' diff --git a/Mathlib/Combinatorics/Quiver/Prefunctor.lean b/Mathlib/Combinatorics/Quiver/Prefunctor.lean index 2a0468c73b08f..fc0496ac6f85e 100644 --- a/Mathlib/Combinatorics/Quiver/Prefunctor.lean +++ b/Mathlib/Combinatorics/Quiver/Prefunctor.lean @@ -22,7 +22,6 @@ structure Prefunctor (V : Type u₁) [Quiver.{v₁} V] (W : Type u₂) [Quiver.{ namespace Prefunctor --- Porting note: added during port. -- These lemmas can not be `@[simp]` because after `whnfR` they have a variable on the LHS. -- Nevertheless they are sometimes useful when building functors. lemma mk_obj {V W : Type*} [Quiver V] [Quiver W] {obj : V → W} {map} {X : V} : diff --git a/Mathlib/Combinatorics/Quiver/Subquiver.lean b/Mathlib/Combinatorics/Quiver/Subquiver.lean index 6cf35fb02f3e5..365c0628c73d1 100644 --- a/Mathlib/Combinatorics/Quiver/Subquiver.lean +++ b/Mathlib/Combinatorics/Quiver/Subquiver.lean @@ -25,7 +25,7 @@ def WideSubquiver (V) [Quiver.{v + 1} V] := /-- A type synonym for `V`, when thought of as a quiver having only the arrows from some `WideSubquiver`. -/ --- Porting note: no hasNonemptyInstance linter yet +-- Porting note: no hasNonemptyInstance linter yet https://github.com/leanprover-community/mathlib4/issues/5171 @[nolint unusedArguments] def WideSubquiver.toType (V) [Quiver V] (_ : WideSubquiver V) : Type u := V @@ -50,7 +50,7 @@ noncomputable instance {V} [Quiver V] : Inhabited (WideSubquiver V) := -- TODO Unify with `CategoryTheory.Arrow`? (The fields have been named to match.) /-- `Total V` is the type of _all_ arrows of `V`. -/ --- Porting note: no hasNonemptyInstance linter yet +-- Porting note: no hasNonemptyInstance linter yet https://github.com/leanprover-community/mathlib4/issues/5171 @[ext] structure Total (V : Type u) [Quiver.{v} V] : Sort max (u + 1) v where /-- the source vertex of an arrow -/ diff --git a/Mathlib/Combinatorics/Quiver/Symmetric.lean b/Mathlib/Combinatorics/Quiver/Symmetric.lean index bb83a91439731..39e75756c695f 100644 --- a/Mathlib/Combinatorics/Quiver/Symmetric.lean +++ b/Mathlib/Combinatorics/Quiver/Symmetric.lean @@ -26,7 +26,7 @@ namespace Quiver /-- A type synonym for the symmetrized quiver (with an arrow both ways for each original arrow). NB: this does not work for `Prop`-valued quivers. It requires `[Quiver.{v+1} V]`. -/ --- Porting note: no hasNonemptyInstance linter yet +-- Porting note: no hasNonemptyInstance linter yet https://github.com/leanprover-community/mathlib4/issues/5171 def Symmetrify (V : Type*) := V instance symmetrifyQuiver (V : Type u) [Quiver V] : Quiver (Symmetrify V) := diff --git a/Mathlib/Combinatorics/SetFamily/Compression/Down.lean b/Mathlib/Combinatorics/SetFamily/Compression/Down.lean index c0a526d8fdd86..5b55945f6fd4f 100644 --- a/Mathlib/Combinatorics/SetFamily/Compression/Down.lean +++ b/Mathlib/Combinatorics/SetFamily/Compression/Down.lean @@ -212,7 +212,7 @@ def compression (a : α) (𝒜 : Finset (Finset α)) : Finset (Finset α) := @[inherit_doc] scoped[FinsetFamily] notation "𝓓 " => Down.compression --- Porting note: had to open this + open FinsetFamily /-- `a` is in the down-compressed family iff it's in the original and its compression is in the diff --git a/Mathlib/Combinatorics/SetFamily/LYM.lean b/Mathlib/Combinatorics/SetFamily/LYM.lean index 24ec53fa6da54..82b28f2f04888 100644 --- a/Mathlib/Combinatorics/SetFamily/LYM.lean +++ b/Mathlib/Combinatorics/SetFamily/LYM.lean @@ -71,8 +71,6 @@ theorem card_mul_le_card_shadow_mul (h𝒜 : (𝒜 : Set (Finset α)).Sized r) : refine le_trans ?_ tsub_tsub_le_tsub_add rw [← (Set.Sized.shadow h𝒜) hs, ← card_compl, ← card_image_of_injOn (insert_inj_on' _)] refine card_le_card fun t ht => ?_ - -- Porting note: commented out the following line - -- infer_instance rw [mem_bipartiteAbove] at ht have : ∅ ∉ 𝒜 := by rw [← mem_coe, h𝒜.empty_mem_iff, coe_eq_singleton] diff --git a/Mathlib/Combinatorics/SetFamily/Shadow.lean b/Mathlib/Combinatorics/SetFamily/Shadow.lean index 98557ae4406a6..ceaa40eb5da72 100644 --- a/Mathlib/Combinatorics/SetFamily/Shadow.lean +++ b/Mathlib/Combinatorics/SetFamily/Shadow.lean @@ -58,9 +58,8 @@ elements from any set in `𝒜`. -/ def shadow (𝒜 : Finset (Finset α)) : Finset (Finset α) := 𝒜.sup fun s => s.image (erase s) --- Porting note: added `inherit_doc` to calm linter @[inherit_doc] scoped[FinsetFamily] notation:max "∂ " => Finset.shadow --- Porting note: had to open FinsetFamily + open FinsetFamily /-- The shadow of the empty set is empty. -/ @@ -183,7 +182,6 @@ variable [DecidableEq α] [Fintype α] {𝒜 : Finset (Finset α)} {s t : Finset def upShadow (𝒜 : Finset (Finset α)) : Finset (Finset α) := 𝒜.sup fun s => sᶜ.image fun a => insert a s --- Porting note: added `inherit_doc` to calm linter @[inherit_doc] scoped[FinsetFamily] notation:max "∂⁺ " => Finset.upShadow /-- The upper shadow of the empty set is empty. -/ diff --git a/Mathlib/Combinatorics/SimpleGraph/Basic.lean b/Mathlib/Combinatorics/SimpleGraph/Basic.lean index 0c0f567f36892..6b07045236942 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Basic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Basic.lean @@ -37,13 +37,9 @@ This module defines simple graphs on a vertex type `V` as an irreflexive symmetr look like. -/ --- Porting note: using `aesop` for automation - --- Porting note: These attributes are needed to use `aesop` as a replacement for `obviously` attribute [aesop norm unfold (rule_sets := [SimpleGraph])] Symmetric attribute [aesop norm unfold (rule_sets := [SimpleGraph])] Irreflexive --- Porting note: a thin wrapper around `aesop` for graph lemmas, modelled on `aesop_cat` /-- A variant of the `aesop` tactic for use in the graph library. Changes relative to standard `aesop`: @@ -93,7 +89,6 @@ structure SimpleGraph (V : Type u) where Adj : V → V → Prop symm : Symmetric Adj := by aesop_graph loopless : Irreflexive Adj := by aesop_graph --- Porting note: changed `obviously` to `aesop` in the `structure` initialize_simps_projections SimpleGraph (Adj → adj) @@ -139,7 +134,6 @@ theorem SimpleGraph.fromRel_adj {V : Type u} (r : V → V → Prop) (v w : V) : (SimpleGraph.fromRel r).Adj v w ↔ v ≠ w ∧ (r v w ∨ r w v) := Iff.rfl --- Porting note: attributes needed for `completeGraph` attribute [aesop safe (rule_sets := [SimpleGraph])] Ne.symm attribute [aesop safe (rule_sets := [SimpleGraph])] Ne.irrefl diff --git a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean index ad526f0fa08e0..54483becc0906 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean @@ -105,8 +105,6 @@ theorem Coloring.colorClasses_finite [Finite α] : C.colorClasses.Finite := theorem Coloring.card_colorClasses_le [Fintype α] [Fintype C.colorClasses] : Fintype.card C.colorClasses ≤ Fintype.card α := by simp only [colorClasses] - -- Porting note: brute force instance declaration `[Fintype (Setoid.classes (Setoid.ker C))]` - haveI : Fintype (Setoid.classes (Setoid.ker C)) := by assumption convert Setoid.card_classes_ker_le C theorem Coloring.not_adj_of_mem_colorClass {c : α} {v w : V} (hv : v ∈ C.colorClass c) diff --git a/Mathlib/Combinatorics/SimpleGraph/Dart.lean b/Mathlib/Combinatorics/SimpleGraph/Dart.lean index 57d70b692b762..c36fe1186e465 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Dart.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Dart.lean @@ -37,9 +37,6 @@ theorem Dart.ext_iff (d₁ d₂ : G.Dart) : d₁ = d₂ ↔ d₁.toProd = d₂.t theorem Dart.ext (d₁ d₂ : G.Dart) (h : d₁.toProd = d₂.toProd) : d₁ = d₂ := (Dart.ext_iff d₁ d₂).mpr h --- Porting note: deleted `Dart.fst` and `Dart.snd` since they are now invalid declaration names, --- even though there is not actually a `SimpleGraph.Dart.fst` or `SimpleGraph.Dart.snd`. - @[simp] theorem Dart.fst_ne_snd (d : G.Dart) : d.fst ≠ d.snd := fun h ↦ G.irrefl (h ▸ d.adj) diff --git a/Mathlib/Combinatorics/SimpleGraph/Density.lean b/Mathlib/Combinatorics/SimpleGraph/Density.lean index 487d1b1620a3e..27c6603abcc93 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Density.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Density.lean @@ -338,8 +338,7 @@ theorem edgeDensity_add_edgeDensity_compl (hs : s.Nonempty) (ht : t.Nonempty) (h G.edgeDensity s t + Gᶜ.edgeDensity s t = 1 := by rw [edgeDensity_def, edgeDensity_def, div_add_div_same, div_eq_one_iff_eq] · exact mod_cast card_interedges_add_card_interedges_compl _ h - -- Porting note: Wrote a workaround for `positivity` tactic. - · apply mul_ne_zero <;> exact mod_cast Nat.pos_iff_ne_zero.1 (Nonempty.card_pos ‹_›) + · positivity end DecidableEq diff --git a/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean b/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean index 1f6be300ede03..3502f86120c33 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean @@ -84,7 +84,7 @@ protected def lift {β : Sort*} (f : ∀ ⦃v⦄ (_ : v ∉ K), β) · rintro h' exact (h u.prop v.prop a).trans (ih h'.of_cons) -@[elab_as_elim] -- Porting note: added +@[elab_as_elim] protected theorem ind {β : G.ComponentCompl K → Prop} (f : ∀ ⦃v⦄ (hv : v ∉ K), β (G.componentComplMk hv)) : ∀ C : G.ComponentCompl K, β C := by apply ConnectedComponent.ind diff --git a/Mathlib/Combinatorics/SimpleGraph/Finite.lean b/Mathlib/Combinatorics/SimpleGraph/Finite.lean index cd15c4a2cff97..6bfa2d702da52 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Finite.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Finite.lean @@ -136,7 +136,6 @@ theorem edgeFinset_deleteEdges [DecidableEq V] [Fintype G.edgeSet] (s : Finset ( section DeleteFar --- Porting note: added `Fintype (Sym2 V)` argument. variable {𝕜 : Type*} [OrderedRing 𝕜] [Fintype G.edgeSet] {p : SimpleGraph V → Prop} {r r₁ r₂ : 𝕜} @@ -205,10 +204,6 @@ theorem singleton_disjoint_neighborFinset : Disjoint {v} (G.neighborFinset v) := /-- `G.degree v` is the number of vertices adjacent to `v`. -/ def degree : ℕ := #(G.neighborFinset v) --- Porting note: in Lean 3 we could do `simp [← degree]`, but that gives --- "invalid '←' modifier, 'SimpleGraph.degree' is a declaration name to be unfolded". --- In any case, having this lemma is good since there's no guarantee we won't still change --- the definition of `degree`. @[simp] theorem card_neighborFinset_eq_degree : #(G.neighborFinset v) = G.degree v := rfl diff --git a/Mathlib/Combinatorics/SimpleGraph/IncMatrix.lean b/Mathlib/Combinatorics/SimpleGraph/IncMatrix.lean index 56b39afefb146..13f35d5e5fc37 100644 --- a/Mathlib/Combinatorics/SimpleGraph/IncMatrix.lean +++ b/Mathlib/Combinatorics/SimpleGraph/IncMatrix.lean @@ -94,12 +94,8 @@ theorem incMatrix_apply_eq_zero_iff : G.incMatrix R a e = 0 ↔ e ∉ G.incidenc simp only [incMatrix_apply, Set.indicator_apply_eq_zero, Pi.one_apply, one_ne_zero] theorem incMatrix_apply_eq_one_iff : G.incMatrix R a e = 1 ↔ e ∈ G.incidenceSet a := by - -- Porting note: was `convert one_ne_zero.ite_eq_left_iff; infer_instance` - unfold incMatrix Set.indicator - simp only [Pi.one_apply] - apply Iff.intro <;> intro h - · split at h <;> simp_all only [zero_ne_one] - · simp_all only [ite_true] + convert one_ne_zero.ite_eq_left_iff + infer_instance end MulZeroOneClass diff --git a/Mathlib/Combinatorics/SimpleGraph/Path.lean b/Mathlib/Combinatorics/SimpleGraph/Path.lean index 6487fc983ad0a..3211d0a9774fe 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Path.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Path.lean @@ -83,7 +83,7 @@ structure IsPath {u v : V} (p : G.Walk u v) extends IsTrail p : Prop where support_nodup : p.support.Nodup -- Porting note: used to use `extends to_trail : is_trail p` in structure -protected lemma IsPath.isTrail {p : Walk G u v}(h : IsPath p) : IsTrail p := h.toIsTrail +protected lemma IsPath.isTrail {p : Walk G u v} (h : IsPath p) : IsTrail p := h.toIsTrail /-- A *circuit* at `u : V` is a nonempty trail beginning and ending at `u`. -/ @[mk_iff isCircuit_def] @@ -376,7 +376,6 @@ protected theorem IsPath.takeUntil {u v w : V} {p : G.Walk v w} (hc : p.IsPath) (h : u ∈ p.support) : (p.takeUntil u h).IsPath := IsPath.of_append_left (q := p.dropUntil u h) (by rwa [← take_spec _ h] at hc) --- Porting note: p was previously accidentally an explicit argument protected theorem IsPath.dropUntil {u v w : V} {p : G.Walk v w} (hc : p.IsPath) (h : u ∈ p.support) : (p.dropUntil u h).IsPath := IsPath.of_append_right (p := p.takeUntil u h) (q := p.dropUntil u h) @@ -1203,7 +1202,6 @@ theorem reachable_deleteEdges_iff_exists_cycle.aux [DecidableEq V] {u v w : V} ← List.append_assoc, ← Walk.edges_append] at hc exact List.disjoint_of_nodup_append hc hbq hpq' --- Porting note: the unused variable checker helped eliminate a good amount of this proof (!) theorem adj_and_reachable_delete_edges_iff_exists_cycle {v w : V} : G.Adj v w ∧ (G \ fromEdgeSet {s(v, w)}).Reachable v w ↔ ∃ (u : V) (p : G.Walk u u), p.IsCycle ∧ s(v, w) ∈ p.edges := by diff --git a/Mathlib/Combinatorics/SimpleGraph/Prod.lean b/Mathlib/Combinatorics/SimpleGraph/Prod.lean index e094ff9729ec2..ee5c57ef5e760 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Prod.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Prod.lean @@ -30,8 +30,6 @@ variable {α β γ : Type*} namespace SimpleGraph --- Porting note: pruned variables to keep things out of local contexts, which --- can impact how generalization works, or what aesop does. variable {G : SimpleGraph α} {H : SimpleGraph β} /-- Box product of simple graphs. It relates `(a₁, b)` and `(a₂, b)` if `G` relates `a₁` and `a₂`, diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean index 038a7f498f743..6e1c8c2dbb00b 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean @@ -74,8 +74,6 @@ private theorem m_pos [Nonempty α] (hPα : #P.parts * 16 ^ #P.parts ≤ card α /-- Local extension for the `positivity` tactic: A few facts that are needed many times for the proof of Szemerédi's regularity lemma. -/ --- Porting note: positivity extensions must now be global, and this did not seem like a good --- match for positivity anymore, so I wrote a new tactic (kmill) scoped macro "sz_positivity" : tactic => `(tactic| { try have := m_pos ‹_› @@ -220,9 +218,9 @@ theorem add_div_le_sum_sq_div_card (hst : s ⊆ t) (f : ι → 𝕜) (d : 𝕜) have h₃ := mul_sq_le_sum_sq hst (fun i => (f i - (∑ j ∈ t, f j) / #t)) h₂ hscard.ne' apply (add_le_add_left h₃ _).trans -- Porting note: was - -- `simp [← mul_div_right_comm _ (#t : 𝕜), sub_div' _ _ _ htcard.ne', ← sum_div, ← add_div,` - -- ` mul_pow, div_le_iff₀ (sq_pos_of_ne_zero htcard.ne'), sub_sq, sum_add_distrib, ← sum_mul,` - -- ` ← mul_sum]` + -- simp [← mul_div_right_comm _ (#t : 𝕜), sub_div' _ _ _ htcard.ne', ← sum_div, ← add_div, + -- mul_pow, div_le_iff₀ (sq_pos_of_ne_zero htcard.ne'), sub_sq, sum_add_distrib, ← sum_mul, + -- ← mul_sum] simp_rw [sub_div' _ _ _ htcard.ne'] conv_lhs => enter [2, 2, x]; rw [div_pow] rw [div_pow, ← sum_div, ← mul_div_right_comm _ (#t : 𝕜), ← add_div, diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean index bad7217bbede8..899a2fefad2f7 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean @@ -119,10 +119,7 @@ theorem equitabilise_aux (hs : a * m + b * (m + 1) = #s) : refine (card_le_card fun i => ?_).trans (hR₂ (u \ t) <| P.mem_avoid.2 ⟨u, hu₁, fun i => hut <| i.antisymm htu, rfl⟩) - -- Porting note: `not_and` required because `∃ x ∈ s, p x` is defined differently - simp only [not_exists, not_and, mem_biUnion, and_imp, mem_union, mem_filter, mem_sdiff, - id, not_or] - exact fun hi₁ hi₂ hi₃ => + simpa using fun hi₁ hi₂ hi₃ => ⟨⟨hi₁, hi₂⟩, fun x hx hx' => hi₃ _ hx <| hx'.trans sdiff_subset⟩ · apply sdiff_subset_sdiff Subset.rfl (biUnion_subset_biUnion_of_subset_left _ _) exact filter_subset_filter _ (subset_insert _ _) diff --git a/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean b/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean index 191e072fd1e6e..40d4f961b4861 100644 --- a/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean +++ b/Mathlib/Combinatorics/SimpleGraph/StronglyRegular.lean @@ -80,10 +80,7 @@ theorem IsSRGWith.card_neighborFinset_union_eq {v w : V} (h : G.IsSRGWith n k 2 * k - Fintype.card (G.commonNeighbors v w) := by apply Nat.add_right_cancel (m := Fintype.card (G.commonNeighbors v w)) rw [Nat.sub_add_cancel, ← Set.toFinset_card] - -- Porting note: Set.toFinset_inter needs workaround to use unification to solve for one of the - -- instance arguments: - · simp [commonNeighbors, @Set.toFinset_inter _ _ _ _ _ _ (_), - ← neighborFinset_def, Finset.card_union_add_card_inter, card_neighborFinset_eq_degree, + · simp [commonNeighbors, ← neighborFinset_def, Finset.card_union_add_card_inter, h.regular.degree_eq, two_mul] · apply le_trans (card_commonNeighbors_le_degree_left _ _ _) simp [h.regular.degree_eq, two_mul] diff --git a/Mathlib/Combinatorics/SimpleGraph/Walk.lean b/Mathlib/Combinatorics/SimpleGraph/Walk.lean index 935f0c84e508f..06aaabee0f997 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Walk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Walk.lean @@ -596,8 +596,7 @@ theorem chain_dartAdj_darts {d : G.Dart} {v w : V} (h : d.snd = v) (p : G.Walk v List.Chain G.DartAdj d p.darts := by induction p generalizing d with | nil => exact List.Chain.nil - -- Porting note: needed to defer `h` and `rfl` to help elaboration - | cons h' p ih => exact List.Chain.cons (by exact h) (ih (by rfl)) + | cons h' p ih => exact List.Chain.cons h (ih rfl) theorem chain'_dartAdj_darts {u v : V} : ∀ (p : G.Walk u v), List.Chain' G.DartAdj p.darts | nil => trivial @@ -1304,9 +1303,6 @@ theorem support_transfer (hp) : (p.transfer H hp).support = p.support := by theorem length_transfer (hp) : (p.transfer H hp).length = p.length := by induction p <;> simp [*] --- Porting note: this failed the simpNF linter since it was originally of the form --- `(p.transfer H hp).transfer K hp' = p.transfer K hp''` with `hp'` a function of `hp` and `hp'`. --- This was a mistake and it's corrected here. @[simp] theorem transfer_transfer (hp) {K : SimpleGraph V} (hp') : (p.transfer H hp).transfer K hp' = p.transfer K (p.edges_transfer hp ▸ hp') := by diff --git a/Mathlib/Combinatorics/Young/YoungDiagram.lean b/Mathlib/Combinatorics/Young/YoungDiagram.lean index b4ca1dc27ecfb..7fcf8eff369ae 100644 --- a/Mathlib/Combinatorics/Young/YoungDiagram.lean +++ b/Mathlib/Combinatorics/Young/YoungDiagram.lean @@ -400,10 +400,7 @@ protected theorem mem_cellsOfRowLens {w : List ℕ} {c : ℕ × ℕ} : c ∈ YoungDiagram.cellsOfRowLens w ↔ ∃ h : c.fst < w.length, c.snd < w[c.fst] := by induction' w with w_hd w_tl w_ih generalizing c <;> rw [YoungDiagram.cellsOfRowLens] · simp [YoungDiagram.cellsOfRowLens] - · rcases c with ⟨⟨_, _⟩, _⟩ - · simp - -- Porting note: was `simpa` - · simp [w_ih, -Finset.singleton_product, Nat.succ_lt_succ_iff] + · rcases c with ⟨⟨_, _⟩, _⟩ <;> simp_all /-- Young diagram from a sorted list -/ def ofRowLens (w : List ℕ) (hw : w.Sorted (· ≥ ·)) : YoungDiagram where From ece4a15aaf323d49563b8001a6ae783909691bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 18 Jan 2025 15:45:07 +0000 Subject: [PATCH 293/681] feat(Algebra/Homology/Embedding): homology of truncGE' (#19570) Given an embedding of complex shapes `e : Embedding c c'`, and `K : HomologicalComplex C c'`, we study the homology of `K.truncGE' e`. --- Mathlib.lean | 2 + .../Algebra/Homology/Embedding/Boundary.lean | 14 +++ .../Embedding/RestrictionHomology.lean | 51 ++++++++ .../Homology/Embedding/TruncGEHomology.lean | 112 ++++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 Mathlib/Algebra/Homology/Embedding/RestrictionHomology.lean create mode 100644 Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean diff --git a/Mathlib.lean b/Mathlib.lean index 4ac20c6ec4516..00e5142447ce7 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -436,8 +436,10 @@ import Mathlib.Algebra.Homology.Embedding.ExtendHomology import Mathlib.Algebra.Homology.Embedding.HomEquiv import Mathlib.Algebra.Homology.Embedding.IsSupported import Mathlib.Algebra.Homology.Embedding.Restriction +import Mathlib.Algebra.Homology.Embedding.RestrictionHomology import Mathlib.Algebra.Homology.Embedding.StupidTrunc import Mathlib.Algebra.Homology.Embedding.TruncGE +import Mathlib.Algebra.Homology.Embedding.TruncGEHomology import Mathlib.Algebra.Homology.Embedding.TruncLE import Mathlib.Algebra.Homology.ExactSequence import Mathlib.Algebra.Homology.Factorizations.Basic diff --git a/Mathlib/Algebra/Homology/Embedding/Boundary.lean b/Mathlib/Algebra/Homology/Embedding/Boundary.lean index 22deea7a94982..cbb3a88d827ba 100644 --- a/Mathlib/Algebra/Homology/Embedding/Boundary.lean +++ b/Mathlib/Algebra/Homology/Embedding/Boundary.lean @@ -139,6 +139,20 @@ lemma next_f_of_not_boundaryLE [e.IsRelIff] {j k : ι} (hjk : c.next j = k) rw [c.next_eq' hk] at hjk exact hjk' (by simpa only [hjk] using hk) +lemma next_f [e.IsTruncGE] {j k : ι} (hjk : c.next j = k) : c'.next (e.f j) = e.f k := by + by_cases hj : c'.Rel (e.f j) (c'.next (e.f j)) + · obtain ⟨k', hk'⟩ := e.mem_next hj + rw [← hk', e.rel_iff] at hj + rw [← hk', ← c.next_eq' hj, hjk] + · rw [c'.next_eq_self _ hj, ← hjk, c.next_eq_self j] + intro hj' + apply hj + rw [← e.rel_iff] at hj' + simpa only [c'.next_eq' hj'] using hj' + +lemma prev_f [e.IsTruncLE] {i j : ι} (hij : c.prev j = i) : c'.prev (e.f j) = e.f i := + e.op.next_f hij + variable {e} in lemma BoundaryLE.false_of_isTruncGE {j : ι} (hj : e.BoundaryLE j) [e.IsTruncGE] : False := by obtain ⟨k, hk⟩ := e.mem_next hj.1 diff --git a/Mathlib/Algebra/Homology/Embedding/RestrictionHomology.lean b/Mathlib/Algebra/Homology/Embedding/RestrictionHomology.lean new file mode 100644 index 0000000000000..547d758f72aa3 --- /dev/null +++ b/Mathlib/Algebra/Homology/Embedding/RestrictionHomology.lean @@ -0,0 +1,51 @@ +/- +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.Homology.Embedding.Restriction +import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex + +/-! # The homology of a restriction + +Under extremely favourable circumstrnaces, we may relate the +homology of `K : HomologicalComplex C c'` in degree `j'` and +that of `K.restriction e` id a degree `j` when `e : Embedding c c'` +is an embedding of complex shapes. See `restriction.sc'Iso` +and `restriction.hasHomology`. + +-/ + +open CategoryTheory Category Limits ZeroObject + +variable {ι ι' : Type*} {c : ComplexShape ι} {c' : ComplexShape ι'} + +namespace HomologicalComplex + +variable {C : Type*} [Category C] [HasZeroMorphisms C] + (K : HomologicalComplex C c') (e : c.Embedding c') [e.IsRelIff] + +namespace restriction + +variable (i j k : ι) (hi : c.prev j = i) (hk : c.next j = k) + {i' j' k' : ι'} (hi' : e.f i = i') (hj' : e.f j = j') (hk' : e.f k = k') + (hi'' : c'.prev j' = i') (hk'' : c'.next j' = k') + +/-- The isomorphism `(K.restriction e).sc' i j k ≅ K.sc' i' j' k'` when +`e` is an embedding of complex shapes, `i'`, `j`, `k`' are the respective +images of `i`, `j`, `k` by `e.f`, `j` is the previous index of `i`, etc. -/ +@[simps!] +def sc'Iso : (K.restriction e).sc' i j k ≅ K.sc' i' j' k' := + ShortComplex.isoMk (K.restrictionXIso e hi') (K.restrictionXIso e hj') (K.restrictionXIso e hk') + (by subst hi' hj'; simp [restrictionXIso]) + (by subst hj' hk'; simp [restrictionXIso]) + +include hi hk hi' hj' hk' hi'' hk'' in +lemma hasHomology [K.HasHomology j'] : (K.restriction e).HasHomology j := + ShortComplex.hasHomology_of_iso (K.isoSc' i' j' k' hi'' hk'' ≪≫ + (sc'Iso K e i j k hi' hj' hk' hi'' hk'').symm ≪≫ + ((K.restriction e).isoSc' i j k hi hk).symm) + +end restriction + +end HomologicalComplex diff --git a/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean b/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean new file mode 100644 index 0000000000000..fff53bfea4947 --- /dev/null +++ b/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean @@ -0,0 +1,112 @@ +/- +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.Homology.Embedding.TruncGE +import Mathlib.Algebra.Homology.Embedding.RestrictionHomology +import Mathlib.Algebra.Homology.QuasiIso + +/-! # The homology of a canonical truncation + +Given an embedding of complex shapes `e : Embedding c c'`, we shall +relate the homology of `K : HomologicalComplex C c'` and of +`K.truncGE e : HomologicalComplex C c'` (TODO). + +So far, we only compute the homology of `K.truncGE' e : HomologicalComplex C c`. + +-/ + +open CategoryTheory Category Limits + +namespace HomologicalComplex + +variable {ι ι' : Type*} {c : ComplexShape ι} {c' : ComplexShape ι'} + {C : Type*} [Category C] [HasZeroMorphisms C] + (K : HomologicalComplex C c') (e : c.Embedding c') [e.IsTruncGE] + [∀ i', K.HasHomology i'] + +namespace truncGE' + +variable (i j k : ι) (hi : c.prev j = i) (hk : c.next j = k) + +include hi hk in +lemma hasHomology_sc'_of_not_mem_boundary (hj : ¬ e.BoundaryGE j) : + ((K.truncGE' e).sc' i j k).HasHomology := by + have : (K.restriction e).HasHomology j := + restriction.hasHomology K e i j k hi hk rfl rfl rfl + (e.prev_f_of_not_boundaryGE hi hj) (e.next_f hk) + have := ShortComplex.hasHomology_of_iso ((K.restriction e).isoSc' i j k hi hk) + let φ := (shortComplexFunctor' C c i j k).map (K.restrictionToTruncGE' e) + have : Epi φ.τ₁ := by dsimp [φ]; infer_instance + have : IsIso φ.τ₂ := K.isIso_restrictionToTruncGE' e j hj + have : IsIso φ.τ₃ := K.isIso_restrictionToTruncGE' e k (e.not_boundaryGE_next' hj hk) + exact ShortComplex.hasHomology_of_epi_of_isIso_of_mono φ + +lemma hasHomology_of_not_mem_boundary (hj : ¬ e.BoundaryGE j) : + (K.truncGE' e).HasHomology j := + hasHomology_sc'_of_not_mem_boundary K e _ j _ rfl rfl hj + +lemma quasiIsoAt_restrictionToTruncGE'_f (hj : ¬ e.BoundaryGE j) + [(K.restriction e).HasHomology j] [(K.truncGE' e).HasHomology j] : + QuasiIsoAt (K.restrictionToTruncGE' e) j := by + rw [quasiIsoAt_iff] + let φ := (shortComplexFunctor C c j).map (K.restrictionToTruncGE' e) + have : Epi φ.τ₁ := by dsimp [φ]; infer_instance + have : IsIso φ.τ₂ := K.isIso_restrictionToTruncGE' e j hj + have : IsIso φ.τ₃ := K.isIso_restrictionToTruncGE' e _ (e.not_boundaryGE_next' hj rfl) + exact ShortComplex.quasiIso_of_epi_of_isIso_of_mono φ + +section + +variable {j' : ι'} (hj' : e.f j = j') (hj : e.BoundaryGE j) + +lemma homologyι_truncGE'XIsoOpcycles_inv_d : + (K.homologyι j' ≫ (K.truncGE'XIsoOpcycles e hj' hj).inv) ≫ (K.truncGE' e).d j k = 0 := by + by_cases hjk : c.Rel j k + · rw [K.truncGE'_d_eq_fromOpcycles e hjk hj' rfl hj, assoc, Iso.inv_hom_id_assoc, + homologyι_comp_fromOpcycles_assoc, zero_comp] + · rw [shape _ _ _ hjk, comp_zero] + +/-- Auxiliary definition for `truncGE'.homologyData`. -/ +noncomputable def isLimitKernelFork : + IsLimit (KernelFork.ofι _ (homologyι_truncGE'XIsoOpcycles_inv_d K e j k hj' hj)) := by + have hk' : c'.next j' = e.f k := by simpa only [hj'] using e.next_f hk + by_cases hjk : c.Rel j k + · let e : parallelPair ((K.truncGE' e).d j k) 0 ≅ + parallelPair (K.fromOpcycles j' (e.f k)) 0 := + parallelPair.ext (K.truncGE'XIsoOpcycles e hj' hj) + (K.truncGE'XIso e rfl (e.not_boundaryGE_next hjk)) + (by simp [K.truncGE'_d_eq_fromOpcycles e hjk hj' rfl hj]) (by simp) + exact (IsLimit.postcomposeHomEquiv e _).1 + (IsLimit.ofIsoLimit (K.homologyIsKernel _ _ hk') + (Fork.ext (Iso.refl _) (by simp [e, Fork.ι]))) + · have := K.isIso_homologyι _ _ hk' + (shape _ _ _ (by simpa only [← hj', e.rel_iff] using hjk)) + exact IsLimit.ofIsoLimit (KernelFork.IsLimit.ofId _ (shape _ _ _ hjk)) + (Fork.ext ((truncGE'XIsoOpcycles K e hj' hj) ≪≫ (asIso (K.homologyι j')).symm)) + +/-- When `j` is at the boundary of the embedding `e` of complex shapes, +this is a homology data for `K.truncGE' e` in degree `j`: the homology is +given by `K.homology j'` where `e.f j = j'`. -/ +noncomputable def homologyData : + ((K.truncGE' e).sc' i j k).HomologyData := + ShortComplex.HomologyData.ofIsLimitKernelFork _ + ((K.truncGE' e).shape _ _ (fun hij => e.not_boundaryGE_next hij hj)) _ + (isLimitKernelFork K e j k hk hj' hj) + +/-- Computation of the `right.g'` field of `truncGE'.homologyData K e i j k hk hj' hj`. -/ +@[simp] +lemma homologyData_right_g' : + (homologyData K e i j k hk hj' hj).right.g' = (K.truncGE' e).d j k := rfl + +end + +instance truncGE'_hasHomology (i : ι) : (K.truncGE' e).HasHomology i := by + by_cases hi : e.BoundaryGE i + · exact ShortComplex.HasHomology.mk' (homologyData K e _ _ _ rfl rfl hi) + · exact hasHomology_of_not_mem_boundary K e i hi + +end truncGE' + +end HomologicalComplex From 3c8e6314aab60e7dbfa3739ca9471755405ef0b8 Mon Sep 17 00:00:00 2001 From: grunweg Date: Sat, 18 Jan 2025 18:58:59 +0000 Subject: [PATCH 294/681] feat(1000.yaml): allow statements of theorems also (#20637) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are three prominent examples of such statements in mathlib: FLT, the Riemann hypothesis and the Poincaré conjecture. Only the last is currently in the 1000+ theorems list. Add some statements of theorems. While at it, also comment on some more, and add a few more entries. Co-authored-by: grunweg --- .../OuterMeasure/Caratheodory.lean | 3 +- .../RingTheory/Polynomial/RationalRoot.lean | 3 +- docs/100.yaml | 2 + docs/1000.yaml | 37 +++++++++++++------ scripts/yaml_check.py | 15 +++++++- 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean index 4916ae6d6fb95..be505ddb8561a 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean @@ -14,7 +14,8 @@ for all sets `t` we have `m t = m (t ∩ s) + m (t \ s)`. This forms a measurabl ## Main definitions and statements -* `caratheodory` is the Carathéodory-measurable space of an outer measure. +* `MeasureTheory.OuterMeasure.caratheodory` is the Carathéodory-measurable space + of an outer measure. ## References diff --git a/Mathlib/RingTheory/Polynomial/RationalRoot.lean b/Mathlib/RingTheory/Polynomial/RationalRoot.lean index f2d43612bb31e..f2a038d309b96 100644 --- a/Mathlib/RingTheory/Polynomial/RationalRoot.lean +++ b/Mathlib/RingTheory/Polynomial/RationalRoot.lean @@ -11,7 +11,8 @@ import Mathlib.RingTheory.Polynomial.ScaleRoots # Rational root theorem and integral root theorem This file contains the rational root theorem and integral root theorem. -The rational root theorem for a unique factorization domain `A` +The rational root theorem (`num_dvd_of_is_root` and `den_dvd_of_is_root`) +for a unique factorization domain `A` with localization `S`, states that the roots of `p : A[X]` in `A`'s field of fractions are of the form `x / y` with `x y : A`, `x ∣ p.coeff 0` and `y ∣ p.leadingCoeff`. diff --git a/docs/100.yaml b/docs/100.yaml index b752b0e60340f..381ca2ffe57b6 100644 --- a/docs/100.yaml +++ b/docs/100.yaml @@ -130,6 +130,8 @@ title : The Four Color Problem 33: title : Fermat’s Last Theorem + statement: FermatLastTheorem + note: "Formalisation of the proof is on-going in https://imperialcollegelondon.github.io/FLT/." 34: title : Divergence of the Harmonic Series decl : Real.tendsto_sum_range_one_div_nat_succ_atTop diff --git a/docs/1000.yaml b/docs/1000.yaml index 6fbfe1d7a786a..a1aecd443a62c 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -11,8 +11,6 @@ # Current TODOs/unresolved questions: # - add infrastructure for updating the information upstream when formalisations are added # - perhaps add a wikidata version of the stacks attribute, and generate this file automatically -# (can this handle formalisation of *statements* also?) -# - complete the information which theorems are already formalised # # TODO: display a less ambiguous title for e.g. "Liouville's theorem" @@ -52,7 +50,8 @@ Q132427: Q132469: title: Fermat's Last Theorem - # See https://imperialcollegelondon.github.io/FLT/ + statement: FermatLastTheorem + comment: "Formalisation of the proof is on-going in https://imperialcollegelondon.github.io/FLT/." Q137164: title: Besicovitch covering theorem @@ -68,6 +67,7 @@ Q164262: Q172298: title: Lasker–Noether theorem + decl: Ideal.isPrimary_decomposition_pairwise_ne_radical Q174955: title: Mihăilescu's theorem @@ -86,9 +86,13 @@ Q179692: Q180345X: title: Integral root theorem + decl: isInteger_of_is_root_of_monic Q180345: title: Rational root theorem + decls: + - num_dvd_of_is_root + - den_dvd_of_is_root Q182505: title: Bayes' theorem @@ -163,6 +167,7 @@ Q193910: Q194919: title: Inverse eigenvalues theorem + # i.e. eigenvalue decomposition of a matrix Q195133: title: Wigner–Eckart theorem @@ -261,9 +266,15 @@ Q256303: Q257387: title: Vitali theorem + # i.e. existence of the Vitali set + author: Ching-Tsun Chou + url: https://github.com/ctchou/my_lean/blob/main/MyLean/NonMeasurable.lean + comment: "mathlib4 pull request at https://github.com/leanprover-community/mathlib4/pull/20722" Q258374: title: Carathéodory's theorem + decl: MeasureTheory.OuterMeasure.caratheodory + comment: Hard to say what exactly is meant. Q260928: title: Jordan curve theorem @@ -273,6 +284,7 @@ Q266291: Q268031: title: Abel's binomial theorem + # presumably not difficult Q268132: title: Gauss–Wantzel theorem @@ -602,7 +614,7 @@ Q646523: Q649469: title: Modularity theorem - # far away; FLT project is working on a special case + comment: "https://imperialcollegelondon.github.io/FLT is proving a special case" Q649977: title: Shirshov–Cohn theorem @@ -776,7 +788,9 @@ Q766722: Q776578: title: Artin–Wedderburn theorem - # WIP formalisation, but not complete yet (Dec 1, 2024) + # using proof_wanted, in Mathlib/RingTheory/SimpleModule.lean + statement: isSemisimpleRing_iff_pi_matrix_divisionRing + # WIP formalisation, but not complete yet (January 1, 2025) Q777924: title: Tijdeman's theorem @@ -1304,7 +1318,8 @@ Q1146791: Q1148215: title: Mitchell's embedding theorem - # there was a project talking about this; very in progress, I believe. statement exists. + # ongoing effort: going slowly; lots of work. see e.g. + # https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/Freyd-Mitchell.20embedding Q1149022: title: Fubini's theorem @@ -1995,7 +2010,7 @@ Q2379128: Q2379132: title: Going-up and going-down theorems - # TODO: does mathlib have these versions? add the right decls! + # TODO: does mathlib have these? Q2394548: title: Hurewicz theorem @@ -3458,8 +3473,8 @@ Q7308146: Q7309601: title: Whitney–Graustein Theorem - # there's an external project, deducing this from sphere-eversion - # TODO link statement (proof depends on some sorries about the winding number) + url: https://github.com/MetalCreator666/WhitneyGraustein/ + comment: "assumes some basic topology statements as axioms; use the sphere eversion project" Q7310041: title: Reider's theorem @@ -3472,7 +3487,7 @@ Q7318284: Q7322366: title: Ribet's theorem - # part of FLT, right? + # part of the original proof of Fermat's Last Theorem Q7323144: title: Rice–Shapiro theorem @@ -3652,7 +3667,7 @@ Q7825663: Q7827204: title: Mazur's torsion theorem - # TODO: is this used in FLT? + comment: "This is used to prove Fermat's last theorem (but a non-trivial project on its own)." Q7841060: title: Trichotomy theorem diff --git a/scripts/yaml_check.py b/scripts/yaml_check.py index c02ca5b036a58..d9e9a51cfc842 100644 --- a/scripts/yaml_check.py +++ b/scripts/yaml_check.py @@ -50,6 +50,8 @@ class HundredTheorem: number: str # a human-readable title title: str + # If a theorem is merely *stated* in mathlib, the name of the declaration + statement: Optional[str] = None # if a theorem is formalised in mathlib, the archive or counterexamples, # the name of the corresponding declaration (optional) decl: Optional[str] = None @@ -77,6 +79,8 @@ class ThousandPlusTheorem: wikidata: str # a human-readable title title: str + # If a theorem is merely *stated* in mathlib, the name of the declaration + statement: Optional[str] = None # if a theorem is formalised in mathlib, the archive or counterexamples, # the name of the corresponding declaration (optional) decl: Optional[str] = None @@ -140,16 +144,23 @@ class ThousandPlusTheorem: try: _thm = ThousandPlusTheorem(index, **entry) except TypeError as e: - print(f"error: entry for theorem {index} is invalid: {e}") + print(f"error: entry for theorem {index} is invalid: {e}", file=sys.stderr) errors += 1 # Also verify that the |decl| and |decls| fields are not *both* provided. if _thm.decl and _thm.decls: print( - f"warning: entry for theorem {index} has both a decl and a decls field; " + f"error: entry for theorem {index} has both a decl and a decls field; " "please only provide one of these", file=sys.stderr, ) errors += 1 + elif _thm.statement and (_thm.decl or _thm.decls): + print( + f"error: entry for theorem {index} has both a statement and a decl(s) field: " + "the former is superfluous; please remove it", + file=sys.stderr, + ) + errors += 1 title = entry["title"] if "decl" in entry: From 6cb9a2a295130c64c1eb645eedca8e369551f051 Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Sat, 18 Jan 2025 19:15:24 +0000 Subject: [PATCH 295/681] feat(CategoryTheory): condition for an induced functor between comma categories to be final (#20139) --- Mathlib.lean | 1 + Mathlib/CategoryTheory/Comma/Final.lean | 48 +++++++++- .../Comma/StructuredArrow/Basic.lean | 29 +++++- .../Comma/StructuredArrow/CommaMap.lean | 96 +++++++++++++++++++ Mathlib/CategoryTheory/Filtered/Final.lean | 22 ++++- 5 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean diff --git a/Mathlib.lean b/Mathlib.lean index 00e5142447ce7..2e0122d2de325 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1729,6 +1729,7 @@ import Mathlib.CategoryTheory.Comma.OverClass import Mathlib.CategoryTheory.Comma.Presheaf.Basic import Mathlib.CategoryTheory.Comma.Presheaf.Colimit import Mathlib.CategoryTheory.Comma.StructuredArrow.Basic +import Mathlib.CategoryTheory.Comma.StructuredArrow.CommaMap import Mathlib.CategoryTheory.Comma.StructuredArrow.Functor import Mathlib.CategoryTheory.Comma.StructuredArrow.Small import Mathlib.CategoryTheory.ComposableArrows diff --git a/Mathlib/CategoryTheory/Comma/Final.lean b/Mathlib/CategoryTheory/Comma/Final.lean index 6f84753766a80..6c77ce36c3afb 100644 --- a/Mathlib/CategoryTheory/Comma/Final.lean +++ b/Mathlib/CategoryTheory/Comma/Final.lean @@ -5,7 +5,9 @@ Authors: Jakob von Raumer -/ import Mathlib.CategoryTheory.Functor.KanExtension.Adjunction import Mathlib.CategoryTheory.Limits.IsConnected +import Mathlib.CategoryTheory.Filtered.Final import Mathlib.CategoryTheory.Grothendieck +import Mathlib.CategoryTheory.Comma.StructuredArrow.CommaMap /-! # Finality of Projections in Comma Categories @@ -14,12 +16,15 @@ We show that `fst L R` is final if `R` is and that `snd L R` is initial if `L` i As a corollary, we show that `Comma L R` with `L : A ⥤ T` and `R : B ⥤ T` is connected if `R` is final and `A` is connected. +We then use this in a proof that derives finality of `map` between two comma categories +on a quasi-commutative diagram of functors, some of which need to be final. + ## References -* [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Lemma 3.4.3 +* [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Lemma 3.4.3 & 3.4.4 -/ -universe v₁ v₂ v₃ u₁ u₂ u₃ +universe v₁ v₂ v₃ v₄ v₅ v₆ u₁ u₂ u₃ u₄ u₅ u₆ namespace CategoryTheory @@ -53,6 +58,8 @@ private lemma final_fst_small [R.Final] : (fst L R).Final := by end Small +section NonSmall + variable {A : Type u₁} [Category.{v₁} A] variable {B : Type u₂} [Category.{v₂} B] variable {T : Type u₃} [Category.{v₃} T] @@ -88,6 +95,43 @@ connected. -/ instance isConnected_comma_of_initial [IsConnected B] [L.Initial] : IsConnected (Comma L R) := by rwa [isConnected_iff_of_initial (snd L R)] +end NonSmall + +/-- Let the following diagram commute up to isomorphism: + + L R + A ---→ T ←--- B + | | | + | F | H | G + ↓ ↓ ↓ + A' ---→ T' ←--- B' + L' R' + +Let `F`, `G`, `R` and `R'` be final and `B` be filtered. Then, the induced functor between the comma +categories of the first and second row of the diagram is final. -/ +lemma map_final {A : Type u₁} [Category.{v₁} A] {B : Type u₂} [Category.{u₂} B] {T : Type u₃} + [Category.{v₃} T] {L : A ⥤ T} {R : B ⥤ T} {A' : Type u₄} [Category.{v₄} A'] {B' : Type u₅} + [Category.{v₅} B'] {T' : Type u₂} [Category.{u₂} T'] {L' : A' ⥤ T'} {R' : B' ⥤ T'} {F : A ⥤ A'} + {G : B ⥤ B'} {H : T ⥤ T'} (iL : F ⋙ L' ≅ L ⋙ H) (iR : G ⋙ R' ≅ R ⋙ H) [IsFiltered B] + [R.Final] [R'.Final] [F.Final] [G.Final] : + (Comma.map iL.hom iR.inv).Final := ⟨fun ⟨i₂, j₂, u₂⟩ => by + haveI := final_of_natIso iR + rw [isConnected_iff_of_equivalence (StructuredArrow.commaMapEquivalence iL.hom iR.inv _)] + have : StructuredArrow.map₂ u₂ iR.hom ≅ StructuredArrow.post j₂ G R' ⋙ + StructuredArrow.map₂ (G := 𝟭 _) (F := 𝟭 _) (R' := R ⋙ H) u₂ iR.hom ⋙ + StructuredArrow.pre _ R H := + eqToIso (by + congr + · simp + · ext; simp) ≪≫ + (StructuredArrow.map₂CompMap₂Iso _ _ _ _).symm ≪≫ + isoWhiskerLeft _ ((StructuredArrow.map₂CompMap₂Iso _ _ _ _).symm ≪≫ + isoWhiskerLeft _ (StructuredArrow.preIsoMap₂ _ _ _).symm) ≪≫ + isoWhiskerRight (StructuredArrow.postIsoMap₂ j₂ G R').symm _ + haveI := final_of_natIso this.symm + rw [IsIso.Iso.inv_inv] + infer_instance⟩ + end Comma end CategoryTheory diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean index 63d88f4bb3234..6b90ae8f3ff45 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean @@ -22,7 +22,7 @@ We prove that `𝟙 (T.obj Y)` is the initial object in `T`-structured objects w namespace CategoryTheory -- morphism levels before object levels. See note [CategoryTheory universes]. -universe v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄ +universe v₁ v₂ v₃ v₄ v₅ v₆ u₁ u₂ u₃ u₄ u₅ u₆ variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] @@ -327,6 +327,16 @@ noncomputable instance isEquivalenceMap₂ (map₂ α β).IsEquivalence := by apply Comma.isEquivalenceMap +/-- The composition of two applications of `map₂` is naturally isomorphic to a single such one. -/ +def map₂CompMap₂Iso {C' : Type u₆} [Category.{v₆} C'] {D' : Type u₅} [Category.{v₅} D'] + {L'' : D'} {R'' : C' ⥤ D'} {F' : C' ⥤ C} {G' : D' ⥤ D} (α' : L ⟶ G'.obj L'') + (β' : R'' ⋙ G' ⟶ F' ⋙ R) : + map₂ α' β' ⋙ map₂ α β ≅ + map₂ (α ≫ G.map α') + ((Functor.associator _ _ _).inv ≫ whiskerRight β' _ ≫ (Functor.associator _ _ _).hom ≫ + whiskerLeft _ β ≫ (Functor.associator _ _ _).inv) := + NatIso.ofComponents (fun X => isoMk (Iso.refl _)) + end /-- `StructuredArrow.post` is a special case of `StructuredArrow.map₂` up to natural isomorphism. -/ @@ -334,6 +344,15 @@ def postIsoMap₂ (S : C) (F : B ⥤ C) (G : C ⥤ D) : post S F G ≅ map₂ (F := 𝟭 _) (𝟙 _) (𝟙 (F ⋙ G)) := NatIso.ofComponents fun _ => isoMk <| Iso.refl _ +/-- `StructuredArrow.map` is a special case of `StructuredArrow.map₂` up to natural isomorphism. -/ +def mapIsoMap₂ {S S' : D} (f : S ⟶ S') : map (T := T) f ≅ map₂ (F := 𝟭 _) (G := 𝟭 _) f (𝟙 T) := + NatIso.ofComponents fun _ => isoMk <| Iso.refl _ + +/-- `StructuredArrow.pre` is a special case of `StructuredArrow.map₂` up to natural isomorphism. -/ +def preIsoMap₂ (S : D) (F : B ⥤ C) (G : C ⥤ D) : + pre S F G ≅ map₂ (G := 𝟭 _) (𝟙 _) (𝟙 (F ⋙ G)) := + NatIso.ofComponents fun _ => isoMk <| Iso.refl _ + /-- A structured arrow is called universal if it is initial. -/ abbrev IsUniversal (f : StructuredArrow S T) := IsInitial f @@ -910,10 +929,10 @@ def StructuredArrow.preEquivalence (f : StructuredArrow e G) : /-- The functor `StructuredArrow d T ⥤ StructuredArrow e (T ⋙ S)` that `u : e ⟶ S.obj d` induces via `StructuredArrow.map₂` can be expressed up to isomorphism by `StructuredArrow.preEquivalence` and `StructuredArrow.proj`. -/ -def StructuredArrow.map₂IsoPreEquivalenceInverseCompProj (T : C ⥤ D) (S : D ⥤ E) (d : D) (e : E) - (u : e ⟶ S.obj d) : - map₂ (F := 𝟭 _) u (𝟙 (T ⋙ S)) ≅ - (preEquivalence T (mk u)).inverse ⋙ proj (mk u) (pre _ T S) := +def StructuredArrow.map₂IsoPreEquivalenceInverseCompProj {T : C ⥤ D} {S : D ⥤ E} {T' : C ⥤ E} + (d : D) (e : E) (u : e ⟶ S.obj d) (α : T ⋙ S ⟶ T') : + map₂ (F := 𝟭 _) u α ≅ (preEquivalence T (mk u)).inverse ⋙ proj (mk u) (pre _ T S) ⋙ + map₂ (F := 𝟭 _) (G := 𝟭 _) (𝟙 _) α := NatIso.ofComponents fun _ => isoMk (Iso.refl _) /-- The functor establishing the equivalence `CostructuredArrow.preEquivalence`. -/ diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean new file mode 100644 index 0000000000000..5a2d0d2c79798 --- /dev/null +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2024 Jakob von Raumer. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jakob von Raumer +-/ +import Mathlib.CategoryTheory.Comma.StructuredArrow.Basic + +/-! +# Structured arrow categories on `Comma.map` + +We characterize structured arrow categories on arbitrary instances of `Comma.map` as a +comma category itself. +-/ + +namespace CategoryTheory + +namespace StructuredArrow + +universe v₁ v₂ v₃ v₄ v₅ v₆ u₁ u₂ u₃ u₄ u₅ u₆ + +noncomputable section + +variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] + {T : Type u₃} [Category.{v₃} T] {L : C ⥤ T} {R : D ⥤ T} + {C' : Type u₄} [Category.{v₄} C'] {D' : Type u₅} [Category.{v₅} D'] {T' : Type u₆} + [Category.{u₆} T'] {L' : C' ⥤ T'} {R' : D' ⥤ T'} {F₁ : C ⥤ C'} {F₂ : D ⥤ D'} {F : T ⥤ T'} + (α : F₁ ⋙ L' ⟶ L ⋙ F) (β : R ⋙ F ⟶ F₂ ⋙ R') + +/-- The functor establishing the equivalence `StructuredArrow.commaMapEquivalence`. -/ +@[simps] +def commaMapEquivalenceFunctor [IsIso β] (X : Comma L' R') : + StructuredArrow X (Comma.map α β) ⥤ Comma (map₂ (𝟙 _) α) (map₂ X.hom (inv β)) where + obj Y := ⟨mk Y.hom.left, mk Y.hom.right, + homMk Y.right.hom + (by simpa only [Functor.const_obj_obj, map₂_obj_left, mk_left, map₂_obj_right, mk_right, + map₂_obj_hom, mk_hom_eq_self, Category.id_comp, Category.assoc, NatIso.isIso_inv_app, + Functor.comp_obj, Comma.map_obj_right, Comma.map_obj_left, Comma.map_obj_hom, + IsIso.hom_inv_id, Category.comp_id] using + congrFun (congrArg CategoryStruct.comp Y.hom.w) (inv (β.app Y.right.right)))⟩ + map {Y Z} f := ⟨homMk f.right.left (congrArg CommaMorphism.left (StructuredArrow.w f)), + homMk f.right.right (congrArg CommaMorphism.right (StructuredArrow.w f)), + by simp only [Functor.const_obj_obj, map₂_obj_left, mk_left, map₂_obj_right, mk_right, + map₂_obj_hom, mk_hom_eq_self, Functor.comp_obj, id_eq, Comma.map_obj_right, + Comma.map_obj_left, Comma.map_obj_hom, eq_mp_eq_cast, eq_mpr_eq_cast, hom_eq_iff, comp_right, + map₂_map_right, homMk_right, CommaMorphism.w] ⟩ + map_id X := by ext <;> rfl + map_comp f g := by ext <;> rfl + +/-- The inverse functor establishing the equivalence `StructuredArrow.commaMapEquivalence`. -/ +@[simps] +def commaMapEquivalenceInverse [IsIso β] (X : Comma L' R') : + Comma (map₂ (𝟙 _) α) (map₂ X.hom (inv β)) ⥤ StructuredArrow X (Comma.map α β) where + obj Y := mk (Y := ⟨Y.left.right, Y.right.right, Y.hom.right⟩) + ⟨by exact Y.left.hom, by exact Y.right.hom, by + simpa using congrFun (congrArg CategoryStruct.comp (StructuredArrow.w Y.hom)) + (β.app Y.right.right)⟩ + map {Y Z} f := homMk ⟨by exact f.left.right, by exact f.right.right, + by exact congrArg CommaMorphism.right f.w⟩ (by + ext + <;> simp only [Comma.map_obj_right, Comma.map_obj_left, Comma.map_obj_hom, Functor.comp_obj, + map₂_obj_right, map₂_obj_left, Functor.const_obj_obj, map₂_obj_hom, eq_mp_eq_cast, id_eq, + mk_left, mk_right, mk_hom_eq_self, Comma.comp_left, Comma.map_map_left, w] + · simp only [Comma.map_obj_right, Comma.map_obj_left, Comma.map_obj_hom, Functor.comp_obj, + map₂_obj_right, map₂_obj_left, Functor.const_obj_obj, map₂_obj_hom, eq_mp_eq_cast, id_eq, + mk_left, mk_right, mk_hom_eq_self, Comma.comp_right, Comma.map_map_right, w] ) + map_id X := by ext <;> rfl + map_comp f g := by ext <;> rfl + +/-- The unit establishing the equivalence `StructuredArrow.commaMapEquivalence`. -/ +@[simps!] +def commaMapEquivalenceUnitIso [IsIso β] (X : Comma L' R') : + 𝟭 (StructuredArrow X (Comma.map α β)) ≅ + commaMapEquivalenceFunctor α β X ⋙ commaMapEquivalenceInverse α β X := + NatIso.ofComponents (fun _ => isoMk (Iso.refl _)) + +/-- The counit functor establishing the equivalence `StructuredArrow.commaMapEquivalence`. -/ +@[simps!] +def commaMapEquivalenceCounitIso [IsIso β] (X : Comma L' R') : + commaMapEquivalenceInverse α β X ⋙ commaMapEquivalenceFunctor α β X ≅ + 𝟭 (Comma (map₂ (𝟙 (L'.obj X.left)) α) (map₂ X.hom (inv β))) := + NatIso.ofComponents (fun _ => Comma.isoMk (Iso.refl _) (Iso.refl _)) + +/-- The structured arrow category on the functor `Comma.map α β`, with `β` a natural isomorphism, +is equivalent to a comma category on two instances of `StructuredArrow.map₂`. -/ +def commaMapEquivalence [IsIso β] (X : Comma L' R') : + StructuredArrow X (Comma.map α β) ≌ Comma (map₂ (𝟙 _) α) (map₂ X.hom (inv β)) where + functor := commaMapEquivalenceFunctor α β X + inverse := commaMapEquivalenceInverse α β X + unitIso := commaMapEquivalenceUnitIso α β X + counitIso := commaMapEquivalenceCounitIso α β X + +end + +end StructuredArrow + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Filtered/Final.lean b/Mathlib/CategoryTheory/Filtered/Final.lean index 98c6d31fcbbdb..dc5eaabbc2b35 100644 --- a/Mathlib/CategoryTheory/Filtered/Final.lean +++ b/Mathlib/CategoryTheory/Filtered/Final.lean @@ -353,11 +353,23 @@ instance CostructuredArrow.initial_proj_of_isCofiltered [IsCofilteredOrEmpty C] /-- The functor `StructuredArrow d T ⥤ StructuredArrow e (T ⋙ S)` that `u : e ⟶ S.obj d` induces via `StructuredArrow.map₂` is final, if `T` and `S` are final and the domain of `T` is filtered. -/ -instance StructuredArrow.final_map₂_id {C : Type v₁} [Category.{v₁} C] [IsFiltered C] {E : Type u₃} - [Category.{v₁} E] (T : C ⥤ D) [T.Final] (S : D ⥤ E) [S.Final] (d : D) (e : E) - (u : e ⟶ S.obj d) : Final (map₂ (R' := T ⋙ S) (F := 𝟭 _) u (𝟙 (T ⋙ S))) := by - have := (T ⋙ S).final_iff_isFiltered_structuredArrow.mp inferInstance e - apply final_of_natIso (map₂IsoPreEquivalenceInverseCompProj T S d e u).symm +instance StructuredArrow.final_map₂_id {D : Type u₂} [Category.{v₂} D] + {C : Type v₁} [Category.{v₁} C] [IsFiltered C] {E : Type u₃} [Category.{v₁} E] + {T : C ⥤ D} [T.Final] {S : D ⥤ E} [S.Final] {T' : C ⥤ E} + {d : D} {e : E} (u : e ⟶ S.obj d) (α : T ⋙ S ⟶ T') [IsIso α] : + Final (map₂ (F := 𝟭 _) u α) := by + haveI : IsFiltered (StructuredArrow e (T ⋙ S)) := + (T ⋙ S).final_iff_isFiltered_structuredArrow.mp inferInstance e + apply final_of_natIso (map₂IsoPreEquivalenceInverseCompProj d e u α).symm + +/-- `StructuredArrow.map` is final if the functor `T` is final` and its domain is filtered. -/ +instance StructuredArrow.final_map {C : Type v₁} [Category.{v₁} C] [IsFiltered C] + {D : Type v₁} [Category.{v₁} D] {S S' : D} (f : S ⟶ S') (T : C ⥤ D) [T.Final] : + Final (map (T := T) f) := by + haveI := NatIso.isIso_of_isIso_app (𝟙 T) + have : (map₂ (F := 𝟭 C) (G := 𝟭 D) f (𝟙 T)).Final := by + apply StructuredArrow.final_map₂_id (S := 𝟭 D) (T := T) (T' := T) f (𝟙 T) + apply final_of_natIso (mapIsoMap₂ f).symm /-- `StructuredArrow.post X T S` is final if `T` and `S` are final and the domain of `T` is filtered. -/ From af5ebc20fb24d9701b8c1bc66e073c3750880223 Mon Sep 17 00:00:00 2001 From: Etienne Date: Sat, 18 Jan 2025 19:15:26 +0000 Subject: [PATCH 296/681] doc: typo (#20829) --- Mathlib/Order/Restriction.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Order/Restriction.lean b/Mathlib/Order/Restriction.lean index 53d992f41e60b..ce47f3cc515be 100644 --- a/Mathlib/Order/Restriction.lean +++ b/Mathlib/Order/Restriction.lean @@ -59,7 +59,7 @@ variable [LocallyFiniteOrderBot α] open Finset -/-- Restrict domain of a function `f` indexed by `α` to elements `≤ α`, seen as a finite set. -/ +/-- Restrict domain of a function `f` indexed by `α` to elements `≤ a`, seen as a finite set. -/ def frestrictLe (a : α) := (Iic a).restrict (π := π) @[simp] From 95878d0079b8389255307f30c5f38f88942019be Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Sat, 18 Jan 2025 20:11:12 +0000 Subject: [PATCH 297/681] chore: split Mathlib.Analysis.Asymptotics.Asymptotics (#20785) This was a long file. Co-authored-by: Michael Rothgang --- Mathlib.lean | 3 +- .../Asymptotics/AsymptoticEquivalent.lean | 2 +- .../{Asymptotics.lean => Defs.lean} | 762 +---------------- Mathlib/Analysis/Asymptotics/Lemmas.lean | 785 ++++++++++++++++++ .../Asymptotics/SpecificAsymptotics.lean | 2 +- .../Asymptotics/SuperpolynomialDecay.lean | 2 +- Mathlib/Analysis/Asymptotics/TVS.lean | 2 +- Mathlib/Analysis/Asymptotics/Theta.lean | 2 +- Mathlib/Analysis/Calculus/FDeriv/Basic.lean | 1 + .../Analysis/Normed/Group/InfiniteSum.lean | 1 - .../NormedSpace/OperatorNorm/Asymptotics.lean | 2 +- Mathlib/Analysis/SpecificLimits/Normed.lean | 2 +- .../Order/Filter/ZeroAndBoundedAtFilter.lean | 2 +- 13 files changed, 799 insertions(+), 769 deletions(-) rename Mathlib/Analysis/Asymptotics/{Asymptotics.lean => Defs.lean} (61%) create mode 100644 Mathlib/Analysis/Asymptotics/Lemmas.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2e0122d2de325..b13b4427de5aa 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1123,7 +1123,8 @@ import Mathlib.Analysis.Analytic.RadiusLiminf import Mathlib.Analysis.Analytic.Uniqueness import Mathlib.Analysis.Analytic.Within import Mathlib.Analysis.Asymptotics.AsymptoticEquivalent -import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Defs +import Mathlib.Analysis.Asymptotics.Lemmas import Mathlib.Analysis.Asymptotics.SpecificAsymptotics import Mathlib.Analysis.Asymptotics.SuperpolynomialDecay import Mathlib.Analysis.Asymptotics.TVS diff --git a/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean b/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean index ef49406727787..aca2bbc1fa356 100644 --- a/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean +++ b/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Anatole Dedecker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker -/ -import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Lemmas import Mathlib.Analysis.Asymptotics.Theta import Mathlib.Analysis.Normed.Order.Basic diff --git a/Mathlib/Analysis/Asymptotics/Asymptotics.lean b/Mathlib/Analysis/Asymptotics/Defs.lean similarity index 61% rename from Mathlib/Analysis/Asymptotics/Asymptotics.lean rename to Mathlib/Analysis/Asymptotics/Defs.lean index 6585904d9c08b..b0534dd20c94b 100644 --- a/Mathlib/Analysis/Asymptotics/Asymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/Defs.lean @@ -3,11 +3,7 @@ Copyright (c) 2019 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Yury Kudryashov -/ -import Mathlib.Analysis.Normed.Group.Bounded -import Mathlib.Analysis.Normed.Group.InfiniteSum -import Mathlib.Analysis.Normed.MulAction -import Mathlib.Topology.Algebra.Order.LiminfLimsup -import Mathlib.Topology.PartialHomeomorph +import Mathlib.Analysis.Normed.Field.Basic /-! # Asymptotics @@ -45,6 +41,8 @@ it suffices to assume that `f` is zero wherever `g` is. (This generalization is the Fréchet derivative.) -/ +assert_not_exists BoundedSMul Summable PartialHomeomorph BoundedLENhdsClass + open Set Topology Filter NNReal namespace Asymptotics @@ -1107,168 +1105,8 @@ theorem isBigO_pure {x} : f'' =O[pure x] g'' ↔ g'' x = 0 → f'' x = 0 := end ZeroConst -@[simp] -theorem isBigOWith_principal {s : Set α} : IsBigOWith c (𝓟 s) f g ↔ ∀ x ∈ s, ‖f x‖ ≤ c * ‖g x‖ := by - rw [IsBigOWith_def, eventually_principal] - -theorem isBigO_principal {s : Set α} : f =O[𝓟 s] g ↔ ∃ c, ∀ x ∈ s, ‖f x‖ ≤ c * ‖g x‖ := by - simp_rw [isBigO_iff, eventually_principal] - -@[simp] -theorem isLittleO_principal {s : Set α} : f'' =o[𝓟 s] g' ↔ ∀ x ∈ s, f'' x = 0 := by - refine ⟨fun h x hx ↦ norm_le_zero_iff.1 ?_, fun h ↦ ?_⟩ - · simp only [isLittleO_iff, isBigOWith_principal] at h - have : Tendsto (fun c : ℝ => c * ‖g' x‖) (𝓝[>] 0) (𝓝 0) := - ((continuous_id.mul continuous_const).tendsto' _ _ (zero_mul _)).mono_left - inf_le_left - apply le_of_tendsto_of_tendsto tendsto_const_nhds this - apply eventually_nhdsWithin_iff.2 (Eventually.of_forall (fun c hc ↦ ?_)) - exact eventually_principal.1 (h hc) x hx - · apply (isLittleO_zero g' _).congr' ?_ EventuallyEq.rfl - exact fun x hx ↦ (h x hx).symm - -@[simp] -theorem isBigOWith_top : IsBigOWith c ⊤ f g ↔ ∀ x, ‖f x‖ ≤ c * ‖g x‖ := by - rw [IsBigOWith_def, eventually_top] - -@[simp] -theorem isBigO_top : f =O[⊤] g ↔ ∃ C, ∀ x, ‖f x‖ ≤ C * ‖g x‖ := by - simp_rw [isBigO_iff, eventually_top] - -@[simp] -theorem isLittleO_top : f'' =o[⊤] g' ↔ ∀ x, f'' x = 0 := by - simp only [← principal_univ, isLittleO_principal, mem_univ, forall_true_left] - -section - -variable (F) -variable [One F] [NormOneClass F] - -theorem isBigOWith_const_one (c : E) (l : Filter α) : - IsBigOWith ‖c‖ l (fun _x : α => c) fun _x => (1 : F) := by simp [isBigOWith_iff] - -theorem isBigO_const_one (c : E) (l : Filter α) : (fun _x : α => c) =O[l] fun _x => (1 : F) := - (isBigOWith_const_one F c l).isBigO - -theorem isLittleO_const_iff_isLittleO_one {c : F''} (hc : c ≠ 0) : - (f =o[l] fun _x => c) ↔ f =o[l] fun _x => (1 : F) := - ⟨fun h => h.trans_isBigOWith (isBigOWith_const_one _ _ _) (norm_pos_iff.2 hc), - fun h => h.trans_isBigO <| isBigO_const_const _ hc _⟩ - -@[simp] -theorem isLittleO_one_iff {f : α → E'''} : f =o[l] (fun _x => 1 : α → F) ↔ Tendsto f l (𝓝 0) := by - simp only [isLittleO_iff, norm_one, mul_one, Metric.nhds_basis_closedBall.tendsto_right_iff, - Metric.mem_closedBall, dist_zero_right] - -@[simp] -theorem isBigO_one_iff : f =O[l] (fun _x => 1 : α → F) ↔ - IsBoundedUnder (· ≤ ·) l fun x => ‖f x‖ := by - simp only [isBigO_iff, norm_one, mul_one, IsBoundedUnder, IsBounded, eventually_map] - -alias ⟨_, _root_.Filter.IsBoundedUnder.isBigO_one⟩ := isBigO_one_iff - -@[simp] -theorem isLittleO_one_left_iff : (fun _x => 1 : α → F) =o[l] f ↔ Tendsto (fun x => ‖f x‖) l atTop := - calc - (fun _x => 1 : α → F) =o[l] f ↔ ∀ n : ℕ, ∀ᶠ x in l, ↑n * ‖(1 : F)‖ ≤ ‖f x‖ := - isLittleO_iff_nat_mul_le_aux <| Or.inl fun _x => by simp only [norm_one, zero_le_one] - _ ↔ ∀ n : ℕ, True → ∀ᶠ x in l, ‖f x‖ ∈ Ici (n : ℝ) := by - simp only [norm_one, mul_one, true_imp_iff, mem_Ici] - _ ↔ Tendsto (fun x => ‖f x‖) l atTop := - atTop_hasCountableBasis_of_archimedean.1.tendsto_right_iff.symm - -theorem _root_.Filter.Tendsto.isBigO_one {c : E'} (h : Tendsto f' l (𝓝 c)) : - f' =O[l] (fun _x => 1 : α → F) := - h.norm.isBoundedUnder_le.isBigO_one F - -theorem IsBigO.trans_tendsto_nhds (hfg : f =O[l] g') {y : F'} (hg : Tendsto g' l (𝓝 y)) : - f =O[l] (fun _x => 1 : α → F) := - hfg.trans <| hg.isBigO_one F - -/-- The condition `f = O[𝓝[≠] a] 1` is equivalent to `f = O[𝓝 a] 1`. -/ -lemma isBigO_one_nhds_ne_iff [TopologicalSpace α] {a : α} : - f =O[𝓝[≠] a] (fun _ ↦ 1 : α → F) ↔ f =O[𝓝 a] (fun _ ↦ 1 : α → F) := by - refine ⟨fun h ↦ ?_, fun h ↦ h.mono nhdsWithin_le_nhds⟩ - simp only [isBigO_one_iff, IsBoundedUnder, IsBounded, eventually_map] at h ⊢ - obtain ⟨c, hc⟩ := h - use max c ‖f a‖ - filter_upwards [eventually_nhdsWithin_iff.mp hc] with b hb - rcases eq_or_ne b a with rfl | hb' - · apply le_max_right - · exact (hb hb').trans (le_max_left ..) - -end - -theorem isLittleO_const_iff {c : F''} (hc : c ≠ 0) : - (f'' =o[l] fun _x => c) ↔ Tendsto f'' l (𝓝 0) := - (isLittleO_const_iff_isLittleO_one ℝ hc).trans (isLittleO_one_iff _) - -theorem isLittleO_id_const {c : F''} (hc : c ≠ 0) : (fun x : E'' => x) =o[𝓝 0] fun _x => c := - (isLittleO_const_iff hc).mpr (continuous_id.tendsto 0) - -theorem _root_.Filter.IsBoundedUnder.isBigO_const (h : IsBoundedUnder (· ≤ ·) l (norm ∘ f)) - {c : F''} (hc : c ≠ 0) : f =O[l] fun _x => c := - (h.isBigO_one ℝ).trans (isBigO_const_const _ hc _) - -theorem isBigO_const_of_tendsto {y : E''} (h : Tendsto f'' l (𝓝 y)) {c : F''} (hc : c ≠ 0) : - f'' =O[l] fun _x => c := - h.norm.isBoundedUnder_le.isBigO_const hc - -theorem IsBigO.isBoundedUnder_le {c : F} (h : f =O[l] fun _x => c) : - IsBoundedUnder (· ≤ ·) l (norm ∘ f) := - let ⟨c', hc'⟩ := h.bound - ⟨c' * ‖c‖, eventually_map.2 hc'⟩ - -theorem isBigO_const_of_ne {c : F''} (hc : c ≠ 0) : - (f =O[l] fun _x => c) ↔ IsBoundedUnder (· ≤ ·) l (norm ∘ f) := - ⟨fun h => h.isBoundedUnder_le, fun h => h.isBigO_const hc⟩ - -theorem isBigO_const_iff {c : F''} : (f'' =O[l] fun _x => c) ↔ - (c = 0 → f'' =ᶠ[l] 0) ∧ IsBoundedUnder (· ≤ ·) l fun x => ‖f'' x‖ := by - refine ⟨fun h => ⟨fun hc => isBigO_zero_right_iff.1 (by rwa [← hc]), h.isBoundedUnder_le⟩, ?_⟩ - rintro ⟨hcf, hf⟩ - rcases eq_or_ne c 0 with (hc | hc) - exacts [(hcf hc).trans_isBigO (isBigO_zero _ _), hf.isBigO_const hc] - -theorem isBigO_iff_isBoundedUnder_le_div (h : ∀ᶠ x in l, g'' x ≠ 0) : - f =O[l] g'' ↔ IsBoundedUnder (· ≤ ·) l fun x => ‖f x‖ / ‖g'' x‖ := by - simp only [isBigO_iff, IsBoundedUnder, IsBounded, eventually_map] - exact - exists_congr fun c => - eventually_congr <| h.mono fun x hx => (div_le_iff₀ <| norm_pos_iff.2 hx).symm - -/-- `(fun x ↦ c) =O[l] f` if and only if `f` is bounded away from zero. -/ -theorem isBigO_const_left_iff_pos_le_norm {c : E''} (hc : c ≠ 0) : - (fun _x => c) =O[l] f' ↔ ∃ b, 0 < b ∧ ∀ᶠ x in l, b ≤ ‖f' x‖ := by - constructor - · intro h - rcases h.exists_pos with ⟨C, hC₀, hC⟩ - refine ⟨‖c‖ / C, div_pos (norm_pos_iff.2 hc) hC₀, ?_⟩ - exact hC.bound.mono fun x => (div_le_iff₀' hC₀).2 - · rintro ⟨b, hb₀, hb⟩ - refine IsBigO.of_bound (‖c‖ / b) (hb.mono fun x hx => ?_) - rw [div_mul_eq_mul_div, mul_div_assoc] - exact le_mul_of_one_le_right (norm_nonneg _) ((one_le_div hb₀).2 hx) - -theorem IsBigO.trans_tendsto (hfg : f'' =O[l] g'') (hg : Tendsto g'' l (𝓝 0)) : - Tendsto f'' l (𝓝 0) := - (isLittleO_one_iff ℝ).1 <| hfg.trans_isLittleO <| (isLittleO_one_iff ℝ).2 hg - -theorem IsLittleO.trans_tendsto (hfg : f'' =o[l] g'') (hg : Tendsto g'' l (𝓝 0)) : - Tendsto f'' l (𝓝 0) := - hfg.isBigO.trans_tendsto hg - -lemma isLittleO_id_one [One F''] [NeZero (1 : F'')] : (fun x : E'' => x) =o[𝓝 0] (1 : E'' → F'') := - isLittleO_id_const one_ne_zero - -theorem continuousAt_iff_isLittleO {α : Type*} {E : Type*} [NormedRing E] [NormOneClass E] - [TopologicalSpace α] {f : α → E} {x : α} : - (ContinuousAt f x) ↔ (fun (y : α) ↦ f y - f x) =o[𝓝 x] (fun (_ : α) ↦ (1 : E)) := by - simp [ContinuousAt, ← tendsto_sub_nhds_zero_iff] - /-! ### Multiplication by a constant -/ - theorem isBigOWith_const_mul_self (c : R) (f : α → R) (l : Filter α) : IsBigOWith ‖c‖ l (fun x => c * f x) f := isBigOWith_of_le' _ fun _x => norm_mul_le _ _ @@ -1375,7 +1213,6 @@ theorem isLittleO_const_mul_right_iff {g : α → 𝕜} {c : 𝕜} (hc : c ≠ 0 /-! ### Multiplication -/ - theorem IsBigOWith.mul {f₁ f₂ : α → R} {g₁ g₂ : α → 𝕜} {c₁ c₂ : ℝ} (h₁ : IsBigOWith c₁ l f₁ g₁) (h₂ : IsBigOWith c₂ l f₂ g₂) : IsBigOWith (c₁ * c₂) l (fun x => f₁ x * f₂ x) fun x => g₁ x * g₂ x := by @@ -1436,13 +1273,6 @@ theorem IsBigO.pow {f : α → R} {g : α → 𝕜} (h : f =O[l] g) (n : ℕ) : let ⟨_C, hC⟩ := h.isBigOWith isBigO_iff_isBigOWith.2 ⟨_, hC.pow' n⟩ -theorem IsBigO.of_pow {f : α → 𝕜} {g : α → R} {n : ℕ} (hn : n ≠ 0) (h : (f ^ n) =O[l] (g ^ n)) : - f =O[l] g := by - rcases h.exists_pos with ⟨C, _hC₀, hC⟩ - obtain ⟨c : ℝ, hc₀ : 0 ≤ c, hc : C ≤ c ^ n⟩ := - ((eventually_ge_atTop _).and <| (tendsto_pow_atTop hn).eventually_ge_atTop C).exists - exact (hC.of_pow hn hc hc₀).isBigO - theorem IsLittleO.pow {f : α → R} {g : α → 𝕜} (h : f =o[l] g) {n : ℕ} (hn : 0 < n) : (fun x => f x ^ n) =o[l] fun x => g x ^ n := by obtain ⟨n, rfl⟩ := Nat.exists_eq_succ_of_ne_zero hn.ne'; clear hn @@ -1474,104 +1304,8 @@ theorem IsLittleO.inv_rev {f : α → 𝕜} {g : α → 𝕜'} (h : f =o[l] g) (h₀ : ∀ᶠ x in l, f x = 0 → g x = 0) : (fun x => (g x)⁻¹) =o[l] fun x => (f x)⁻¹ := IsLittleO.of_isBigOWith fun _c hc => (h.def' hc).inv_rev h₀ -/-! ### Scalar multiplication -/ - - -section SMulConst - -variable [Module R E'] [BoundedSMul R E'] - -theorem IsBigOWith.const_smul_self (c' : R) : - IsBigOWith (‖c'‖) l (fun x => c' • f' x) f' := - isBigOWith_of_le' _ fun _ => norm_smul_le _ _ - -theorem IsBigO.const_smul_self (c' : R) : (fun x => c' • f' x) =O[l] f' := - (IsBigOWith.const_smul_self _).isBigO - -theorem IsBigOWith.const_smul_left (h : IsBigOWith c l f' g) (c' : R) : - IsBigOWith (‖c'‖ * c) l (fun x => c' • f' x) g := - .trans (.const_smul_self _) h (norm_nonneg _) - -theorem IsBigO.const_smul_left (h : f' =O[l] g) (c : R) : (c • f') =O[l] g := - let ⟨_b, hb⟩ := h.isBigOWith - (hb.const_smul_left _).isBigO - -theorem IsLittleO.const_smul_left (h : f' =o[l] g) (c : R) : (c • f') =o[l] g := - (IsBigO.const_smul_self _).trans_isLittleO h - -variable [Module 𝕜 E'] [BoundedSMul 𝕜 E'] - -theorem isBigO_const_smul_left {c : 𝕜} (hc : c ≠ 0) : (fun x => c • f' x) =O[l] g ↔ f' =O[l] g := by - have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc - rw [← isBigO_norm_left] - simp only [norm_smul] - rw [isBigO_const_mul_left_iff cne0, isBigO_norm_left] - -theorem isLittleO_const_smul_left {c : 𝕜} (hc : c ≠ 0) : - (fun x => c • f' x) =o[l] g ↔ f' =o[l] g := by - have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc - rw [← isLittleO_norm_left] - simp only [norm_smul] - rw [isLittleO_const_mul_left_iff cne0, isLittleO_norm_left] - -theorem isBigO_const_smul_right {c : 𝕜} (hc : c ≠ 0) : - (f =O[l] fun x => c • f' x) ↔ f =O[l] f' := by - have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc - rw [← isBigO_norm_right] - simp only [norm_smul] - rw [isBigO_const_mul_right_iff cne0, isBigO_norm_right] - -theorem isLittleO_const_smul_right {c : 𝕜} (hc : c ≠ 0) : - (f =o[l] fun x => c • f' x) ↔ f =o[l] f' := by - have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc - rw [← isLittleO_norm_right] - simp only [norm_smul] - rw [isLittleO_const_mul_right_iff cne0, isLittleO_norm_right] - -end SMulConst - -section SMul - -variable [Module R E'] [BoundedSMul R E'] [Module 𝕜' F'] [BoundedSMul 𝕜' F'] -variable {k₁ : α → R} {k₂ : α → 𝕜'} - -theorem IsBigOWith.smul (h₁ : IsBigOWith c l k₁ k₂) (h₂ : IsBigOWith c' l f' g') : - IsBigOWith (c * c') l (fun x => k₁ x • f' x) fun x => k₂ x • g' x := by - simp only [IsBigOWith_def] at * - filter_upwards [h₁, h₂] with _ hx₁ hx₂ - apply le_trans (norm_smul_le _ _) - convert mul_le_mul hx₁ hx₂ (norm_nonneg _) (le_trans (norm_nonneg _) hx₁) using 1 - rw [norm_smul, mul_mul_mul_comm] - -theorem IsBigO.smul (h₁ : k₁ =O[l] k₂) (h₂ : f' =O[l] g') : - (fun x => k₁ x • f' x) =O[l] fun x => k₂ x • g' x := by - obtain ⟨c₁, h₁⟩ := h₁.isBigOWith - obtain ⟨c₂, h₂⟩ := h₂.isBigOWith - exact (h₁.smul h₂).isBigO - -theorem IsBigO.smul_isLittleO (h₁ : k₁ =O[l] k₂) (h₂ : f' =o[l] g') : - (fun x => k₁ x • f' x) =o[l] fun x => k₂ x • g' x := by - simp only [IsLittleO_def] at * - intro c cpos - rcases h₁.exists_pos with ⟨c', c'pos, hc'⟩ - exact (hc'.smul (h₂ (div_pos cpos c'pos))).congr_const (mul_div_cancel₀ _ (ne_of_gt c'pos)) - -theorem IsLittleO.smul_isBigO (h₁ : k₁ =o[l] k₂) (h₂ : f' =O[l] g') : - (fun x => k₁ x • f' x) =o[l] fun x => k₂ x • g' x := by - simp only [IsLittleO_def] at * - intro c cpos - rcases h₂.exists_pos with ⟨c', c'pos, hc'⟩ - exact ((h₁ (div_pos cpos c'pos)).smul hc').congr_const (div_mul_cancel₀ _ (ne_of_gt c'pos)) - -theorem IsLittleO.smul (h₁ : k₁ =o[l] k₂) (h₂ : f' =o[l] g') : - (fun x => k₁ x • f' x) =o[l] fun x => k₂ x • g' x := - h₁.smul_isBigO h₂.isBigO - -end SMul - /-! ### Sum -/ - section Sum variable {ι : Type*} {A : ι → α → E'} {C : ι → ℝ} {s : Finset ι} @@ -1595,123 +1329,6 @@ theorem IsLittleO.sum (h : ∀ i ∈ s, A i =o[l] g') : (fun x => ∑ i ∈ s, A end Sum -section Prod -variable {ι : Type*} - -theorem IsBigO.listProd {L : List ι} {f : ι → α → R} {g : ι → α → 𝕜} - (hf : ∀ i ∈ L, f i =O[l] g i) : - (fun x ↦ (L.map (f · x)).prod) =O[l] (fun x ↦ (L.map (g · x)).prod) := by - induction L with - | nil => simp [isBoundedUnder_const] - | cons i L ihL => - simp only [List.map_cons, List.prod_cons, List.forall_mem_cons] at hf ⊢ - exact hf.1.mul (ihL hf.2) - -theorem IsBigO.multisetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] - {s : Multiset ι} {f : ι → α → R} {g : ι → α → 𝕜} (hf : ∀ i ∈ s, f i =O[l] g i) : - (fun x ↦ (s.map (f · x)).prod) =O[l] (fun x ↦ (s.map (g · x)).prod) := by - obtain ⟨l, rfl⟩ : ∃ l : List ι, ↑l = s := Quotient.mk_surjective s - exact mod_cast IsBigO.listProd hf - -theorem IsBigO.finsetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] - {s : Finset ι} {f : ι → α → R} {g : ι → α → 𝕜} - (hf : ∀ i ∈ s, f i =O[l] g i) : (∏ i ∈ s, f i ·) =O[l] (∏ i ∈ s, g i ·) := - .multisetProd hf - -theorem IsLittleO.listProd {L : List ι} {f : ι → α → R} {g : ι → α → 𝕜} - (h₁ : ∀ i ∈ L, f i =O[l] g i) (h₂ : ∃ i ∈ L, f i =o[l] g i) : - (fun x ↦ (L.map (f · x)).prod) =o[l] (fun x ↦ (L.map (g · x)).prod) := by - induction L with - | nil => simp at h₂ - | cons i L ihL => - simp only [List.map_cons, List.prod_cons, List.forall_mem_cons, List.exists_mem_cons_iff] - at h₁ h₂ ⊢ - cases h₂ with - | inl hi => exact hi.mul_isBigO <| .listProd h₁.2 - | inr hL => exact h₁.1.mul_isLittleO <| ihL h₁.2 hL - -theorem IsLittleO.multisetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] - {s : Multiset ι} {f : ι → α → R} {g : ι → α → 𝕜} (h₁ : ∀ i ∈ s, f i =O[l] g i) - (h₂ : ∃ i ∈ s, f i =o[l] g i) : - (fun x ↦ (s.map (f · x)).prod) =o[l] (fun x ↦ (s.map (g · x)).prod) := by - obtain ⟨l, rfl⟩ : ∃ l : List ι, ↑l = s := Quotient.mk_surjective s - exact mod_cast IsLittleO.listProd h₁ h₂ - -theorem IsLittleO.finsetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] - {s : Finset ι} {f : ι → α → R} {g : ι → α → 𝕜} (h₁ : ∀ i ∈ s, f i =O[l] g i) - (h₂ : ∃ i ∈ s, f i =o[l] g i) : (∏ i ∈ s, f i ·) =o[l] (∏ i ∈ s, g i ·) := - .multisetProd h₁ h₂ - -end Prod - -/-! ### Relation between `f = o(g)` and `f / g → 0` -/ - - -theorem IsLittleO.tendsto_div_nhds_zero {f g : α → 𝕜} (h : f =o[l] g) : - Tendsto (fun x => f x / g x) l (𝓝 0) := - (isLittleO_one_iff 𝕜).mp <| by - calc - (fun x => f x / g x) =o[l] fun x => g x / g x := by - simpa only [div_eq_mul_inv] using h.mul_isBigO (isBigO_refl _ _) - _ =O[l] fun _x => (1 : 𝕜) := isBigO_of_le _ fun x => by simp [div_self_le_one] - -theorem IsLittleO.tendsto_inv_smul_nhds_zero [Module 𝕜 E'] [BoundedSMul 𝕜 E'] - {f : α → E'} {g : α → 𝕜} - {l : Filter α} (h : f =o[l] g) : Tendsto (fun x => (g x)⁻¹ • f x) l (𝓝 0) := by - simpa only [div_eq_inv_mul, ← norm_inv, ← norm_smul, ← tendsto_zero_iff_norm_tendsto_zero] using - h.norm_norm.tendsto_div_nhds_zero - -theorem isLittleO_iff_tendsto' {f g : α → 𝕜} (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) : - f =o[l] g ↔ Tendsto (fun x => f x / g x) l (𝓝 0) := - ⟨IsLittleO.tendsto_div_nhds_zero, fun h => - (((isLittleO_one_iff _).mpr h).mul_isBigO (isBigO_refl g l)).congr' - (hgf.mono fun _x => div_mul_cancel_of_imp) (Eventually.of_forall fun _x => one_mul _)⟩ - -theorem isLittleO_iff_tendsto {f g : α → 𝕜} (hgf : ∀ x, g x = 0 → f x = 0) : - f =o[l] g ↔ Tendsto (fun x => f x / g x) l (𝓝 0) := - isLittleO_iff_tendsto' (Eventually.of_forall hgf) - -alias ⟨_, isLittleO_of_tendsto'⟩ := isLittleO_iff_tendsto' - -alias ⟨_, isLittleO_of_tendsto⟩ := isLittleO_iff_tendsto - -theorem isLittleO_const_left_of_ne {c : E''} (hc : c ≠ 0) : - (fun _x => c) =o[l] g ↔ Tendsto (fun x => ‖g x‖) l atTop := by - simp only [← isLittleO_one_left_iff ℝ] - exact ⟨(isBigO_const_const (1 : ℝ) hc l).trans_isLittleO, - (isBigO_const_one ℝ c l).trans_isLittleO⟩ - -@[simp] -theorem isLittleO_const_left {c : E''} : - (fun _x => c) =o[l] g'' ↔ c = 0 ∨ Tendsto (norm ∘ g'') l atTop := by - rcases eq_or_ne c 0 with (rfl | hc) - · simp only [isLittleO_zero, eq_self_iff_true, true_or] - · simp only [hc, false_or, isLittleO_const_left_of_ne hc]; rfl - -@[simp 1001] -- Porting note: increase priority so that this triggers before `isLittleO_const_left` -theorem isLittleO_const_const_iff [NeBot l] {d : E''} {c : F''} : - ((fun _x => d) =o[l] fun _x => c) ↔ d = 0 := by - have : ¬Tendsto (Function.const α ‖c‖) l atTop := - not_tendsto_atTop_of_tendsto_nhds tendsto_const_nhds - simp only [isLittleO_const_left, or_iff_left_iff_imp] - exact fun h => (this h).elim - -@[simp] -theorem isLittleO_pure {x} : f'' =o[pure x] g'' ↔ f'' x = 0 := - calc - f'' =o[pure x] g'' ↔ (fun _y : α => f'' x) =o[pure x] fun _ => g'' x := isLittleO_congr rfl rfl - _ ↔ f'' x = 0 := isLittleO_const_const_iff - -theorem isLittleO_const_id_cobounded (c : F'') : - (fun _ => c) =o[Bornology.cobounded E''] id := - isLittleO_const_left.2 <| .inr tendsto_norm_cobounded_atTop - -theorem isLittleO_const_id_atTop (c : E'') : (fun _x : ℝ => c) =o[atTop] id := - isLittleO_const_left.2 <| Or.inr tendsto_abs_atTop_atTop - -theorem isLittleO_const_id_atBot (c : E'') : (fun _x : ℝ => c) =o[atBot] id := - isLittleO_const_left.2 <| Or.inr tendsto_abs_atBot_atTop - /-! ### Eventually (u / v) * v = u @@ -1738,377 +1355,4 @@ theorem IsLittleO.eventually_mul_div_cancel (h : u =o[l] v) : u / v * v =ᶠ[l] end EventuallyMulDivCancel -/-! ### Equivalent definitions of the form `∃ φ, u =ᶠ[l] φ * v` in a `NormedField`. -/ - - -section ExistsMulEq - -variable {u v : α → 𝕜} - -/-- If `‖φ‖` is eventually bounded by `c`, and `u =ᶠ[l] φ * v`, then we have `IsBigOWith c u v l`. - This does not require any assumptions on `c`, which is why we keep this version along with - `IsBigOWith_iff_exists_eq_mul`. -/ -theorem isBigOWith_of_eq_mul {u v : α → R} (φ : α → R) (hφ : ∀ᶠ x in l, ‖φ x‖ ≤ c) - (h : u =ᶠ[l] φ * v) : - IsBigOWith c l u v := by - simp only [IsBigOWith_def] - refine h.symm.rw (fun x a => ‖a‖ ≤ c * ‖v x‖) (hφ.mono fun x hx => ?_) - simp only [Pi.mul_apply] - refine (norm_mul_le _ _).trans ?_ - gcongr - -theorem isBigOWith_iff_exists_eq_mul (hc : 0 ≤ c) : - IsBigOWith c l u v ↔ ∃ φ : α → 𝕜, (∀ᶠ x in l, ‖φ x‖ ≤ c) ∧ u =ᶠ[l] φ * v := by - constructor - · intro h - use fun x => u x / v x - refine ⟨Eventually.mono h.bound fun y hy => ?_, h.eventually_mul_div_cancel.symm⟩ - simpa using div_le_of_le_mul₀ (norm_nonneg _) hc hy - · rintro ⟨φ, hφ, h⟩ - exact isBigOWith_of_eq_mul φ hφ h - -theorem IsBigOWith.exists_eq_mul (h : IsBigOWith c l u v) (hc : 0 ≤ c) : - ∃ φ : α → 𝕜, (∀ᶠ x in l, ‖φ x‖ ≤ c) ∧ u =ᶠ[l] φ * v := - (isBigOWith_iff_exists_eq_mul hc).mp h - -theorem isBigO_iff_exists_eq_mul : - u =O[l] v ↔ ∃ φ : α → 𝕜, l.IsBoundedUnder (· ≤ ·) (norm ∘ φ) ∧ u =ᶠ[l] φ * v := by - constructor - · rintro h - rcases h.exists_nonneg with ⟨c, hnnc, hc⟩ - rcases hc.exists_eq_mul hnnc with ⟨φ, hφ, huvφ⟩ - exact ⟨φ, ⟨c, hφ⟩, huvφ⟩ - · rintro ⟨φ, ⟨c, hφ⟩, huvφ⟩ - exact isBigO_iff_isBigOWith.2 ⟨c, isBigOWith_of_eq_mul φ hφ huvφ⟩ - -alias ⟨IsBigO.exists_eq_mul, _⟩ := isBigO_iff_exists_eq_mul - -theorem isLittleO_iff_exists_eq_mul : - u =o[l] v ↔ ∃ φ : α → 𝕜, Tendsto φ l (𝓝 0) ∧ u =ᶠ[l] φ * v := by - constructor - · exact fun h => ⟨fun x => u x / v x, h.tendsto_div_nhds_zero, h.eventually_mul_div_cancel.symm⟩ - · simp only [IsLittleO_def] - rintro ⟨φ, hφ, huvφ⟩ c hpos - rw [NormedAddCommGroup.tendsto_nhds_zero] at hφ - exact isBigOWith_of_eq_mul _ ((hφ c hpos).mono fun x => le_of_lt) huvφ - -alias ⟨IsLittleO.exists_eq_mul, _⟩ := isLittleO_iff_exists_eq_mul - -end ExistsMulEq - -/-! ### Miscellaneous lemmas -/ - - -theorem div_isBoundedUnder_of_isBigO {α : Type*} {l : Filter α} {f g : α → 𝕜} (h : f =O[l] g) : - IsBoundedUnder (· ≤ ·) l fun x => ‖f x / g x‖ := by - obtain ⟨c, h₀, hc⟩ := h.exists_nonneg - refine ⟨c, eventually_map.2 (hc.bound.mono fun x hx => ?_)⟩ - rw [norm_div] - exact div_le_of_le_mul₀ (norm_nonneg _) h₀ hx - -theorem isBigO_iff_div_isBoundedUnder {α : Type*} {l : Filter α} {f g : α → 𝕜} - (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) : - f =O[l] g ↔ IsBoundedUnder (· ≤ ·) l fun x => ‖f x / g x‖ := by - refine ⟨div_isBoundedUnder_of_isBigO, fun h => ?_⟩ - obtain ⟨c, hc⟩ := h - simp only [eventually_map, norm_div] at hc - refine IsBigO.of_bound c (hc.mp <| hgf.mono fun x hx₁ hx₂ => ?_) - by_cases hgx : g x = 0 - · simp [hx₁ hgx, hgx] - · exact (div_le_iff₀ (norm_pos_iff.2 hgx)).mp hx₂ - -theorem isBigO_of_div_tendsto_nhds {α : Type*} {l : Filter α} {f g : α → 𝕜} - (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) (c : 𝕜) (H : Filter.Tendsto (f / g) l (𝓝 c)) : - f =O[l] g := - (isBigO_iff_div_isBoundedUnder hgf).2 <| H.norm.isBoundedUnder_le - -theorem IsLittleO.tendsto_zero_of_tendsto {α E 𝕜 : Type*} [NormedAddCommGroup E] [NormedField 𝕜] - {u : α → E} {v : α → 𝕜} {l : Filter α} {y : 𝕜} (huv : u =o[l] v) (hv : Tendsto v l (𝓝 y)) : - Tendsto u l (𝓝 0) := by - suffices h : u =o[l] fun _x => (1 : 𝕜) by - rwa [isLittleO_one_iff] at h - exact huv.trans_isBigO (hv.isBigO_one 𝕜) - -theorem isLittleO_pow_pow {m n : ℕ} (h : m < n) : (fun x : 𝕜 => x ^ n) =o[𝓝 0] fun x => x ^ m := by - rcases lt_iff_exists_add.1 h with ⟨p, hp0 : 0 < p, rfl⟩ - suffices (fun x : 𝕜 => x ^ m * x ^ p) =o[𝓝 0] fun x => x ^ m * 1 ^ p by - simpa only [pow_add, one_pow, mul_one] - exact IsBigO.mul_isLittleO (isBigO_refl _ _) - (IsLittleO.pow ((isLittleO_one_iff _).2 tendsto_id) hp0) - -theorem isLittleO_norm_pow_norm_pow {m n : ℕ} (h : m < n) : - (fun x : E' => ‖x‖ ^ n) =o[𝓝 0] fun x => ‖x‖ ^ m := - (isLittleO_pow_pow h).comp_tendsto tendsto_norm_zero - -theorem isLittleO_pow_id {n : ℕ} (h : 1 < n) : (fun x : 𝕜 => x ^ n) =o[𝓝 0] fun x => x := by - convert isLittleO_pow_pow h (𝕜 := 𝕜) - simp only [pow_one] - -theorem isLittleO_norm_pow_id {n : ℕ} (h : 1 < n) : - (fun x : E' => ‖x‖ ^ n) =o[𝓝 0] fun x => x := by - have := @isLittleO_norm_pow_norm_pow E' _ _ _ h - simp only [pow_one] at this - exact isLittleO_norm_right.mp this - -theorem IsBigO.eq_zero_of_norm_pow_within {f : E'' → F''} {s : Set E''} {x₀ : E''} {n : ℕ} - (h : f =O[𝓝[s] x₀] fun x => ‖x - x₀‖ ^ n) (hx₀ : x₀ ∈ s) (hn : n ≠ 0) : f x₀ = 0 := - mem_of_mem_nhdsWithin hx₀ h.eq_zero_imp <| by simp_rw [sub_self, norm_zero, zero_pow hn] - -theorem IsBigO.eq_zero_of_norm_pow {f : E'' → F''} {x₀ : E''} {n : ℕ} - (h : f =O[𝓝 x₀] fun x => ‖x - x₀‖ ^ n) (hn : n ≠ 0) : f x₀ = 0 := by - rw [← nhdsWithin_univ] at h - exact h.eq_zero_of_norm_pow_within (mem_univ _) hn - -theorem isLittleO_pow_sub_pow_sub (x₀ : E') {n m : ℕ} (h : n < m) : - (fun x => ‖x - x₀‖ ^ m) =o[𝓝 x₀] fun x => ‖x - x₀‖ ^ n := - haveI : Tendsto (fun x => ‖x - x₀‖) (𝓝 x₀) (𝓝 0) := by - apply tendsto_norm_zero.comp - rw [← sub_self x₀] - exact tendsto_id.sub tendsto_const_nhds - (isLittleO_pow_pow h).comp_tendsto this - -theorem isLittleO_pow_sub_sub (x₀ : E') {m : ℕ} (h : 1 < m) : - (fun x => ‖x - x₀‖ ^ m) =o[𝓝 x₀] fun x => x - x₀ := by - simpa only [isLittleO_norm_right, pow_one] using isLittleO_pow_sub_pow_sub x₀ h - -theorem IsBigOWith.right_le_sub_of_lt_one {f₁ f₂ : α → E'} (h : IsBigOWith c l f₁ f₂) (hc : c < 1) : - IsBigOWith (1 / (1 - c)) l f₂ fun x => f₂ x - f₁ x := - IsBigOWith.of_bound <| - mem_of_superset h.bound fun x hx => by - simp only [mem_setOf_eq] at hx ⊢ - rw [mul_comm, one_div, ← div_eq_mul_inv, le_div_iff₀, mul_sub, mul_one, mul_comm] - · exact le_trans (sub_le_sub_left hx _) (norm_sub_norm_le _ _) - · exact sub_pos.2 hc - -theorem IsBigOWith.right_le_add_of_lt_one {f₁ f₂ : α → E'} (h : IsBigOWith c l f₁ f₂) (hc : c < 1) : - IsBigOWith (1 / (1 - c)) l f₂ fun x => f₁ x + f₂ x := - (h.neg_right.right_le_sub_of_lt_one hc).neg_right.of_neg_left.congr rfl (fun _ ↦ rfl) fun x ↦ by - rw [neg_sub, sub_neg_eq_add] - -theorem IsLittleO.right_isBigO_sub {f₁ f₂ : α → E'} (h : f₁ =o[l] f₂) : - f₂ =O[l] fun x => f₂ x - f₁ x := - ((h.def' one_half_pos).right_le_sub_of_lt_one one_half_lt_one).isBigO - -theorem IsLittleO.right_isBigO_add {f₁ f₂ : α → E'} (h : f₁ =o[l] f₂) : - f₂ =O[l] fun x => f₁ x + f₂ x := - ((h.def' one_half_pos).right_le_add_of_lt_one one_half_lt_one).isBigO - -theorem IsLittleO.right_isBigO_add' {f₁ f₂ : α → E'} (h : f₁ =o[l] f₂) : - f₂ =O[l] (f₂ + f₁) := - add_comm f₁ f₂ ▸ h.right_isBigO_add - -/-- If `f x = O(g x)` along `cofinite`, then there exists a positive constant `C` such that -`‖f x‖ ≤ C * ‖g x‖` whenever `g x ≠ 0`. -/ -theorem bound_of_isBigO_cofinite (h : f =O[cofinite] g'') : - ∃ C > 0, ∀ ⦃x⦄, g'' x ≠ 0 → ‖f x‖ ≤ C * ‖g'' x‖ := by - rcases h.exists_pos with ⟨C, C₀, hC⟩ - rw [IsBigOWith_def, eventually_cofinite] at hC - rcases (hC.toFinset.image fun x => ‖f x‖ / ‖g'' x‖).exists_le with ⟨C', hC'⟩ - have : ∀ x, C * ‖g'' x‖ < ‖f x‖ → ‖f x‖ / ‖g'' x‖ ≤ C' := by simpa using hC' - refine ⟨max C C', lt_max_iff.2 (Or.inl C₀), fun x h₀ => ?_⟩ - rw [max_mul_of_nonneg _ _ (norm_nonneg _), le_max_iff, or_iff_not_imp_left, not_le] - exact fun hx => (div_le_iff₀ (norm_pos_iff.2 h₀)).1 (this _ hx) - -theorem isBigO_cofinite_iff (h : ∀ x, g'' x = 0 → f'' x = 0) : - f'' =O[cofinite] g'' ↔ ∃ C, ∀ x, ‖f'' x‖ ≤ C * ‖g'' x‖ := by - classical - exact ⟨fun h' => - let ⟨C, _C₀, hC⟩ := bound_of_isBigO_cofinite h' - ⟨C, fun x => if hx : g'' x = 0 then by simp [h _ hx, hx] else hC hx⟩, - fun h => (isBigO_top.2 h).mono le_top⟩ - -theorem bound_of_isBigO_nat_atTop {f : ℕ → E} {g'' : ℕ → E''} (h : f =O[atTop] g'') : - ∃ C > 0, ∀ ⦃x⦄, g'' x ≠ 0 → ‖f x‖ ≤ C * ‖g'' x‖ := - bound_of_isBigO_cofinite <| by rwa [Nat.cofinite_eq_atTop] - -theorem isBigO_nat_atTop_iff {f : ℕ → E''} {g : ℕ → F''} (h : ∀ x, g x = 0 → f x = 0) : - f =O[atTop] g ↔ ∃ C, ∀ x, ‖f x‖ ≤ C * ‖g x‖ := by - rw [← Nat.cofinite_eq_atTop, isBigO_cofinite_iff h] - -theorem isBigO_one_nat_atTop_iff {f : ℕ → E''} : - f =O[atTop] (fun _n => 1 : ℕ → ℝ) ↔ ∃ C, ∀ n, ‖f n‖ ≤ C := - Iff.trans (isBigO_nat_atTop_iff fun _ h => (one_ne_zero h).elim) <| by - simp only [norm_one, mul_one] - -theorem isBigOWith_pi {ι : Type*} [Fintype ι] {E' : ι → Type*} [∀ i, NormedAddCommGroup (E' i)] - {f : α → ∀ i, E' i} {C : ℝ} (hC : 0 ≤ C) : - IsBigOWith C l f g' ↔ ∀ i, IsBigOWith C l (fun x => f x i) g' := by - have : ∀ x, 0 ≤ C * ‖g' x‖ := fun x => mul_nonneg hC (norm_nonneg _) - simp only [isBigOWith_iff, pi_norm_le_iff_of_nonneg (this _), eventually_all] - -@[simp] -theorem isBigO_pi {ι : Type*} [Fintype ι] {E' : ι → Type*} [∀ i, NormedAddCommGroup (E' i)] - {f : α → ∀ i, E' i} : f =O[l] g' ↔ ∀ i, (fun x => f x i) =O[l] g' := by - simp only [isBigO_iff_eventually_isBigOWith, ← eventually_all] - exact eventually_congr (eventually_atTop.2 ⟨0, fun c => isBigOWith_pi⟩) - -@[simp] -theorem isLittleO_pi {ι : Type*} [Fintype ι] {E' : ι → Type*} [∀ i, NormedAddCommGroup (E' i)] - {f : α → ∀ i, E' i} : f =o[l] g' ↔ ∀ i, (fun x => f x i) =o[l] g' := by - simp +contextual only [IsLittleO_def, isBigOWith_pi, le_of_lt] - exact ⟨fun h i c hc => h hc i, fun h c hc i => h i hc⟩ - -theorem IsBigO.natCast_atTop {R : Type*} [StrictOrderedSemiring R] [Archimedean R] - {f : R → E} {g : R → F} (h : f =O[atTop] g) : - (fun (n : ℕ) => f n) =O[atTop] (fun n => g n) := - IsBigO.comp_tendsto h tendsto_natCast_atTop_atTop - -@[deprecated (since := "2024-04-17")] -alias IsBigO.nat_cast_atTop := IsBigO.natCast_atTop - -theorem IsLittleO.natCast_atTop {R : Type*} [StrictOrderedSemiring R] [Archimedean R] - {f : R → E} {g : R → F} (h : f =o[atTop] g) : - (fun (n : ℕ) => f n) =o[atTop] (fun n => g n) := - IsLittleO.comp_tendsto h tendsto_natCast_atTop_atTop - -@[deprecated (since := "2024-04-17")] -alias IsLittleO.nat_cast_atTop := IsLittleO.natCast_atTop - -theorem isBigO_atTop_iff_eventually_exists {α : Type*} [SemilatticeSup α] [Nonempty α] - {f : α → E} {g : α → F} : f =O[atTop] g ↔ ∀ᶠ n₀ in atTop, ∃ c, ∀ n ≥ n₀, ‖f n‖ ≤ c * ‖g n‖ := by - rw [isBigO_iff, exists_eventually_atTop] - -theorem isBigO_atTop_iff_eventually_exists_pos {α : Type*} - [SemilatticeSup α] [Nonempty α] {f : α → G} {g : α → G'} : - f =O[atTop] g ↔ ∀ᶠ n₀ in atTop, ∃ c > 0, ∀ n ≥ n₀, c * ‖f n‖ ≤ ‖g n‖ := by - simp_rw [isBigO_iff'', ← exists_prop, Subtype.exists', exists_eventually_atTop] - -lemma isBigO_mul_iff_isBigO_div {f g h : α → 𝕜} (hf : ∀ᶠ x in l, f x ≠ 0) : - (fun x ↦ f x * g x) =O[l] h ↔ g =O[l] (fun x ↦ h x / f x) := by - rw [isBigO_iff', isBigO_iff'] - refine ⟨fun ⟨c, hc, H⟩ ↦ ⟨c, hc, ?_⟩, fun ⟨c, hc, H⟩ ↦ ⟨c, hc, ?_⟩⟩ <;> - · refine H.congr <| Eventually.mp hf <| Eventually.of_forall fun x hx ↦ ?_ - rw [norm_mul, norm_div, ← mul_div_assoc, le_div_iff₀' (norm_pos_iff.mpr hx)] - end Asymptotics - -open Asymptotics - -theorem summable_of_isBigO {ι E} [SeminormedAddCommGroup E] [CompleteSpace E] - {f : ι → E} {g : ι → ℝ} (hg : Summable g) (h : f =O[cofinite] g) : Summable f := - let ⟨C, hC⟩ := h.isBigOWith - .of_norm_bounded_eventually (fun x => C * ‖g x‖) (hg.abs.mul_left _) hC.bound - -theorem summable_of_isBigO_nat {E} [SeminormedAddCommGroup E] [CompleteSpace E] - {f : ℕ → E} {g : ℕ → ℝ} (hg : Summable g) (h : f =O[atTop] g) : Summable f := - summable_of_isBigO hg <| Nat.cofinite_eq_atTop.symm ▸ h - -lemma Asymptotics.IsBigO.comp_summable_norm {ι E F : Type*} - [SeminormedAddCommGroup E] [SeminormedAddCommGroup F] {f : E → F} {g : ι → E} - (hf : f =O[𝓝 0] id) (hg : Summable (‖g ·‖)) : Summable (‖f <| g ·‖) := - summable_of_isBigO hg <| hf.norm_norm.comp_tendsto <| - tendsto_zero_iff_norm_tendsto_zero.2 hg.tendsto_cofinite_zero - -namespace PartialHomeomorph - -variable {α : Type*} {β : Type*} [TopologicalSpace α] [TopologicalSpace β] -variable {E : Type*} [Norm E] {F : Type*} [Norm F] - -/-- Transfer `IsBigOWith` over a `PartialHomeomorph`. -/ -theorem isBigOWith_congr (e : PartialHomeomorph α β) {b : β} (hb : b ∈ e.target) {f : β → E} - {g : β → F} {C : ℝ} : IsBigOWith C (𝓝 b) f g ↔ IsBigOWith C (𝓝 (e.symm b)) (f ∘ e) (g ∘ e) := - ⟨fun h => - h.comp_tendsto <| by - have := e.continuousAt (e.map_target hb) - rwa [ContinuousAt, e.rightInvOn hb] at this, - fun h => - (h.comp_tendsto (e.continuousAt_symm hb)).congr' rfl - ((e.eventually_right_inverse hb).mono fun _ hx => congr_arg f hx) - ((e.eventually_right_inverse hb).mono fun _ hx => congr_arg g hx)⟩ - -/-- Transfer `IsBigO` over a `PartialHomeomorph`. -/ -theorem isBigO_congr (e : PartialHomeomorph α β) {b : β} (hb : b ∈ e.target) {f : β → E} - {g : β → F} : f =O[𝓝 b] g ↔ (f ∘ e) =O[𝓝 (e.symm b)] (g ∘ e) := by - simp only [IsBigO_def] - exact exists_congr fun C => e.isBigOWith_congr hb - -/-- Transfer `IsLittleO` over a `PartialHomeomorph`. -/ -theorem isLittleO_congr (e : PartialHomeomorph α β) {b : β} (hb : b ∈ e.target) {f : β → E} - {g : β → F} : f =o[𝓝 b] g ↔ (f ∘ e) =o[𝓝 (e.symm b)] (g ∘ e) := by - simp only [IsLittleO_def] - exact forall₂_congr fun c _hc => e.isBigOWith_congr hb - -end PartialHomeomorph - -namespace Homeomorph - -variable {α : Type*} {β : Type*} [TopologicalSpace α] [TopologicalSpace β] -variable {E : Type*} [Norm E] {F : Type*} [Norm F] - -open Asymptotics - -/-- Transfer `IsBigOWith` over a `Homeomorph`. -/ -theorem isBigOWith_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F} {C : ℝ} : - IsBigOWith C (𝓝 b) f g ↔ IsBigOWith C (𝓝 (e.symm b)) (f ∘ e) (g ∘ e) := - e.toPartialHomeomorph.isBigOWith_congr trivial - -/-- Transfer `IsBigO` over a `Homeomorph`. -/ -theorem isBigO_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F} : - f =O[𝓝 b] g ↔ (f ∘ e) =O[𝓝 (e.symm b)] (g ∘ e) := by - simp only [IsBigO_def] - exact exists_congr fun C => e.isBigOWith_congr - -/-- Transfer `IsLittleO` over a `Homeomorph`. -/ -theorem isLittleO_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F} : - f =o[𝓝 b] g ↔ (f ∘ e) =o[𝓝 (e.symm b)] (g ∘ e) := by - simp only [IsLittleO_def] - exact forall₂_congr fun c _hc => e.isBigOWith_congr - -end Homeomorph - -namespace ContinuousOn - -variable {α E F : Type*} [TopologicalSpace α] {s : Set α} {f : α → E} {c : F} - -section IsBigO - -variable [SeminormedAddGroup E] [Norm F] - -protected theorem isBigOWith_principal - (hf : ContinuousOn f s) (hs : IsCompact s) (hc : ‖c‖ ≠ 0) : - IsBigOWith (sSup (Norm.norm '' (f '' s)) / ‖c‖) (𝓟 s) f fun _ => c := by - rw [isBigOWith_principal, div_mul_cancel₀ _ hc] - exact fun x hx ↦ hs.image_of_continuousOn hf |>.image continuous_norm - |>.isLUB_sSup (Set.image_nonempty.mpr <| Set.image_nonempty.mpr ⟨x, hx⟩) - |>.left <| Set.mem_image_of_mem _ <| Set.mem_image_of_mem _ hx - -protected theorem isBigO_principal (hf : ContinuousOn f s) (hs : IsCompact s) - (hc : ‖c‖ ≠ 0) : f =O[𝓟 s] fun _ => c := - (hf.isBigOWith_principal hs hc).isBigO - -end IsBigO - -section IsBigORev - -variable [NormedAddGroup E] [SeminormedAddGroup F] - -protected theorem isBigOWith_rev_principal - (hf : ContinuousOn f s) (hs : IsCompact s) (hC : ∀ i ∈ s, f i ≠ 0) (c : F) : - IsBigOWith (‖c‖ / sInf (Norm.norm '' (f '' s))) (𝓟 s) (fun _ => c) f := by - refine isBigOWith_principal.mpr fun x hx ↦ ?_ - rw [mul_comm_div] - replace hs := hs.image_of_continuousOn hf |>.image continuous_norm - have h_sInf := hs.isGLB_sInf <| Set.image_nonempty.mpr <| Set.image_nonempty.mpr ⟨x, hx⟩ - refine le_mul_of_one_le_right (norm_nonneg c) <| (one_le_div ?_).mpr <| - h_sInf.1 <| Set.mem_image_of_mem _ <| Set.mem_image_of_mem _ hx - obtain ⟨_, ⟨x, hx, hCx⟩, hnormCx⟩ := hs.sInf_mem h_sInf.nonempty - rw [← hnormCx, ← hCx] - exact (norm_ne_zero_iff.mpr (hC x hx)).symm.lt_of_le (norm_nonneg _) - -protected theorem isBigO_rev_principal (hf : ContinuousOn f s) - (hs : IsCompact s) (hC : ∀ i ∈ s, f i ≠ 0) (c : F) : (fun _ => c) =O[𝓟 s] f := - (hf.isBigOWith_rev_principal hs hC c).isBigO - -end IsBigORev - -end ContinuousOn - -/-- The (scalar) product of a sequence that tends to zero with a bounded one also tends to zero. -/ -lemma NormedField.tendsto_zero_smul_of_tendsto_zero_of_bounded {ι 𝕜 𝔸 : Type*} - [NormedDivisionRing 𝕜] [NormedAddCommGroup 𝔸] [Module 𝕜 𝔸] [BoundedSMul 𝕜 𝔸] {l : Filter ι} - {ε : ι → 𝕜} {f : ι → 𝔸} (hε : Tendsto ε l (𝓝 0)) (hf : IsBoundedUnder (· ≤ ·) l (norm ∘ f)) : - Tendsto (ε • f) l (𝓝 0) := by - rw [← isLittleO_one_iff 𝕜] at hε ⊢ - simpa using IsLittleO.smul_isBigO hε (hf.isBigO_const (one_ne_zero : (1 : 𝕜) ≠ 0)) - -set_option linter.style.longFile 2200 diff --git a/Mathlib/Analysis/Asymptotics/Lemmas.lean b/Mathlib/Analysis/Asymptotics/Lemmas.lean new file mode 100644 index 0000000000000..a42c822104f4a --- /dev/null +++ b/Mathlib/Analysis/Asymptotics/Lemmas.lean @@ -0,0 +1,785 @@ +/- +Copyright (c) 2019 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad, Yury Kudryashov +-/ +import Mathlib.Analysis.Asymptotics.Defs +import Mathlib.Analysis.Normed.Group.Bounded +import Mathlib.Analysis.Normed.Group.InfiniteSum +import Mathlib.Analysis.Normed.MulAction +import Mathlib.Topology.Algebra.Order.LiminfLimsup +import Mathlib.Topology.PartialHomeomorph + +/-! +# Further basic lemmas about asymptotics + +-/ + +open Set Topology Filter NNReal + +namespace Asymptotics + + +variable {α : Type*} {β : Type*} {E : Type*} {F : Type*} {G : Type*} {E' : Type*} + {F' : Type*} {G' : Type*} {E'' : Type*} {F'' : Type*} {G'' : Type*} {E''' : Type*} + {R : Type*} {R' : Type*} {𝕜 : Type*} {𝕜' : Type*} + +variable [Norm E] [Norm F] [Norm G] +variable [SeminormedAddCommGroup E'] [SeminormedAddCommGroup F'] [SeminormedAddCommGroup G'] + [NormedAddCommGroup E''] [NormedAddCommGroup F''] [NormedAddCommGroup G''] [SeminormedRing R] + [SeminormedAddGroup E'''] + [SeminormedRing R'] + +variable [NormedDivisionRing 𝕜] [NormedDivisionRing 𝕜'] +variable {c c' c₁ c₂ : ℝ} {f : α → E} {g : α → F} {k : α → G} +variable {f' : α → E'} {g' : α → F'} {k' : α → G'} +variable {f'' : α → E''} {g'' : α → F''} {k'' : α → G''} +variable {l l' : Filter α} +@[simp] +theorem isBigOWith_principal {s : Set α} : IsBigOWith c (𝓟 s) f g ↔ ∀ x ∈ s, ‖f x‖ ≤ c * ‖g x‖ := by + rw [IsBigOWith_def, eventually_principal] + +theorem isBigO_principal {s : Set α} : f =O[𝓟 s] g ↔ ∃ c, ∀ x ∈ s, ‖f x‖ ≤ c * ‖g x‖ := by + simp_rw [isBigO_iff, eventually_principal] + +@[simp] +theorem isLittleO_principal {s : Set α} : f'' =o[𝓟 s] g' ↔ ∀ x ∈ s, f'' x = 0 := by + refine ⟨fun h x hx ↦ norm_le_zero_iff.1 ?_, fun h ↦ ?_⟩ + · simp only [isLittleO_iff, isBigOWith_principal] at h + have : Tendsto (fun c : ℝ => c * ‖g' x‖) (𝓝[>] 0) (𝓝 0) := + ((continuous_id.mul continuous_const).tendsto' _ _ (zero_mul _)).mono_left + inf_le_left + apply le_of_tendsto_of_tendsto tendsto_const_nhds this + apply eventually_nhdsWithin_iff.2 (Eventually.of_forall (fun c hc ↦ ?_)) + exact eventually_principal.1 (h hc) x hx + · apply (isLittleO_zero g' _).congr' ?_ EventuallyEq.rfl + exact fun x hx ↦ (h x hx).symm + +@[simp] +theorem isBigOWith_top : IsBigOWith c ⊤ f g ↔ ∀ x, ‖f x‖ ≤ c * ‖g x‖ := by + rw [IsBigOWith_def, eventually_top] + +@[simp] +theorem isBigO_top : f =O[⊤] g ↔ ∃ C, ∀ x, ‖f x‖ ≤ C * ‖g x‖ := by + simp_rw [isBigO_iff, eventually_top] + +@[simp] +theorem isLittleO_top : f'' =o[⊤] g' ↔ ∀ x, f'' x = 0 := by + simp only [← principal_univ, isLittleO_principal, mem_univ, forall_true_left] + +section + +variable (F) +variable [One F] [NormOneClass F] + +theorem isBigOWith_const_one (c : E) (l : Filter α) : + IsBigOWith ‖c‖ l (fun _x : α => c) fun _x => (1 : F) := by simp [isBigOWith_iff] + +theorem isBigO_const_one (c : E) (l : Filter α) : (fun _x : α => c) =O[l] fun _x => (1 : F) := + (isBigOWith_const_one F c l).isBigO + +theorem isLittleO_const_iff_isLittleO_one {c : F''} (hc : c ≠ 0) : + (f =o[l] fun _x => c) ↔ f =o[l] fun _x => (1 : F) := + ⟨fun h => h.trans_isBigOWith (isBigOWith_const_one _ _ _) (norm_pos_iff.2 hc), + fun h => h.trans_isBigO <| isBigO_const_const _ hc _⟩ + +@[simp] +theorem isLittleO_one_iff {f : α → E'''} : f =o[l] (fun _x => 1 : α → F) ↔ Tendsto f l (𝓝 0) := by + simp only [isLittleO_iff, norm_one, mul_one, Metric.nhds_basis_closedBall.tendsto_right_iff, + Metric.mem_closedBall, dist_zero_right] + +@[simp] +theorem isBigO_one_iff : f =O[l] (fun _x => 1 : α → F) ↔ + IsBoundedUnder (· ≤ ·) l fun x => ‖f x‖ := by + simp only [isBigO_iff, norm_one, mul_one, IsBoundedUnder, IsBounded, eventually_map] + +alias ⟨_, _root_.Filter.IsBoundedUnder.isBigO_one⟩ := isBigO_one_iff + +@[simp] +theorem isLittleO_one_left_iff : (fun _x => 1 : α → F) =o[l] f ↔ Tendsto (fun x => ‖f x‖) l atTop := + calc + (fun _x => 1 : α → F) =o[l] f ↔ ∀ n : ℕ, ∀ᶠ x in l, ↑n * ‖(1 : F)‖ ≤ ‖f x‖ := + isLittleO_iff_nat_mul_le_aux <| Or.inl fun _x => by simp only [norm_one, zero_le_one] + _ ↔ ∀ n : ℕ, True → ∀ᶠ x in l, ‖f x‖ ∈ Ici (n : ℝ) := by + simp only [norm_one, mul_one, true_imp_iff, mem_Ici] + _ ↔ Tendsto (fun x => ‖f x‖) l atTop := + atTop_hasCountableBasis_of_archimedean.1.tendsto_right_iff.symm + +theorem _root_.Filter.Tendsto.isBigO_one {c : E'} (h : Tendsto f' l (𝓝 c)) : + f' =O[l] (fun _x => 1 : α → F) := + h.norm.isBoundedUnder_le.isBigO_one F + +theorem IsBigO.trans_tendsto_nhds (hfg : f =O[l] g') {y : F'} (hg : Tendsto g' l (𝓝 y)) : + f =O[l] (fun _x => 1 : α → F) := + hfg.trans <| hg.isBigO_one F + +/-- The condition `f = O[𝓝[≠] a] 1` is equivalent to `f = O[𝓝 a] 1`. -/ +lemma isBigO_one_nhds_ne_iff [TopologicalSpace α] {a : α} : + f =O[𝓝[≠] a] (fun _ ↦ 1 : α → F) ↔ f =O[𝓝 a] (fun _ ↦ 1 : α → F) := by + refine ⟨fun h ↦ ?_, fun h ↦ h.mono nhdsWithin_le_nhds⟩ + simp only [isBigO_one_iff, IsBoundedUnder, IsBounded, eventually_map] at h ⊢ + obtain ⟨c, hc⟩ := h + use max c ‖f a‖ + filter_upwards [eventually_nhdsWithin_iff.mp hc] with b hb + rcases eq_or_ne b a with rfl | hb' + · apply le_max_right + · exact (hb hb').trans (le_max_left ..) + +end + +theorem isLittleO_const_iff {c : F''} (hc : c ≠ 0) : + (f'' =o[l] fun _x => c) ↔ Tendsto f'' l (𝓝 0) := + (isLittleO_const_iff_isLittleO_one ℝ hc).trans (isLittleO_one_iff _) + +theorem isLittleO_id_const {c : F''} (hc : c ≠ 0) : (fun x : E'' => x) =o[𝓝 0] fun _x => c := + (isLittleO_const_iff hc).mpr (continuous_id.tendsto 0) + +theorem _root_.Filter.IsBoundedUnder.isBigO_const (h : IsBoundedUnder (· ≤ ·) l (norm ∘ f)) + {c : F''} (hc : c ≠ 0) : f =O[l] fun _x => c := + (h.isBigO_one ℝ).trans (isBigO_const_const _ hc _) + +theorem isBigO_const_of_tendsto {y : E''} (h : Tendsto f'' l (𝓝 y)) {c : F''} (hc : c ≠ 0) : + f'' =O[l] fun _x => c := + h.norm.isBoundedUnder_le.isBigO_const hc + +theorem IsBigO.isBoundedUnder_le {c : F} (h : f =O[l] fun _x => c) : + IsBoundedUnder (· ≤ ·) l (norm ∘ f) := + let ⟨c', hc'⟩ := h.bound + ⟨c' * ‖c‖, eventually_map.2 hc'⟩ + +theorem isBigO_const_of_ne {c : F''} (hc : c ≠ 0) : + (f =O[l] fun _x => c) ↔ IsBoundedUnder (· ≤ ·) l (norm ∘ f) := + ⟨fun h => h.isBoundedUnder_le, fun h => h.isBigO_const hc⟩ + +theorem isBigO_const_iff {c : F''} : (f'' =O[l] fun _x => c) ↔ + (c = 0 → f'' =ᶠ[l] 0) ∧ IsBoundedUnder (· ≤ ·) l fun x => ‖f'' x‖ := by + refine ⟨fun h => ⟨fun hc => isBigO_zero_right_iff.1 (by rwa [← hc]), h.isBoundedUnder_le⟩, ?_⟩ + rintro ⟨hcf, hf⟩ + rcases eq_or_ne c 0 with (hc | hc) + exacts [(hcf hc).trans_isBigO (isBigO_zero _ _), hf.isBigO_const hc] + +theorem isBigO_iff_isBoundedUnder_le_div (h : ∀ᶠ x in l, g'' x ≠ 0) : + f =O[l] g'' ↔ IsBoundedUnder (· ≤ ·) l fun x => ‖f x‖ / ‖g'' x‖ := by + simp only [isBigO_iff, IsBoundedUnder, IsBounded, eventually_map] + exact + exists_congr fun c => + eventually_congr <| h.mono fun x hx => (div_le_iff₀ <| norm_pos_iff.2 hx).symm + +/-- `(fun x ↦ c) =O[l] f` if and only if `f` is bounded away from zero. -/ +theorem isBigO_const_left_iff_pos_le_norm {c : E''} (hc : c ≠ 0) : + (fun _x => c) =O[l] f' ↔ ∃ b, 0 < b ∧ ∀ᶠ x in l, b ≤ ‖f' x‖ := by + constructor + · intro h + rcases h.exists_pos with ⟨C, hC₀, hC⟩ + refine ⟨‖c‖ / C, div_pos (norm_pos_iff.2 hc) hC₀, ?_⟩ + exact hC.bound.mono fun x => (div_le_iff₀' hC₀).2 + · rintro ⟨b, hb₀, hb⟩ + refine IsBigO.of_bound (‖c‖ / b) (hb.mono fun x hx => ?_) + rw [div_mul_eq_mul_div, mul_div_assoc] + exact le_mul_of_one_le_right (norm_nonneg _) ((one_le_div hb₀).2 hx) + +theorem IsBigO.trans_tendsto (hfg : f'' =O[l] g'') (hg : Tendsto g'' l (𝓝 0)) : + Tendsto f'' l (𝓝 0) := + (isLittleO_one_iff ℝ).1 <| hfg.trans_isLittleO <| (isLittleO_one_iff ℝ).2 hg + +theorem IsLittleO.trans_tendsto (hfg : f'' =o[l] g'') (hg : Tendsto g'' l (𝓝 0)) : + Tendsto f'' l (𝓝 0) := + hfg.isBigO.trans_tendsto hg + +lemma isLittleO_id_one [One F''] [NeZero (1 : F'')] : (fun x : E'' => x) =o[𝓝 0] (1 : E'' → F'') := + isLittleO_id_const one_ne_zero + +theorem continuousAt_iff_isLittleO {α : Type*} {E : Type*} [NormedRing E] [NormOneClass E] + [TopologicalSpace α] {f : α → E} {x : α} : + (ContinuousAt f x) ↔ (fun (y : α) ↦ f y - f x) =o[𝓝 x] (fun (_ : α) ↦ (1 : E)) := by + simp [ContinuousAt, ← tendsto_sub_nhds_zero_iff] + +/-! ### Multiplication -/ + +theorem IsBigO.of_pow {f : α → 𝕜} {g : α → R} {n : ℕ} (hn : n ≠ 0) (h : (f ^ n) =O[l] (g ^ n)) : + f =O[l] g := by + rcases h.exists_pos with ⟨C, _hC₀, hC⟩ + obtain ⟨c : ℝ, hc₀ : 0 ≤ c, hc : C ≤ c ^ n⟩ := + ((eventually_ge_atTop _).and <| (tendsto_pow_atTop hn).eventually_ge_atTop C).exists + exact (hC.of_pow hn hc hc₀).isBigO + +/-! ### Scalar multiplication -/ + +section SMulConst + +variable [Module R E'] [BoundedSMul R E'] + +theorem IsBigOWith.const_smul_self (c' : R) : + IsBigOWith (‖c'‖) l (fun x => c' • f' x) f' := + isBigOWith_of_le' _ fun _ => norm_smul_le _ _ + +theorem IsBigO.const_smul_self (c' : R) : (fun x => c' • f' x) =O[l] f' := + (IsBigOWith.const_smul_self _).isBigO + +theorem IsBigOWith.const_smul_left (h : IsBigOWith c l f' g) (c' : R) : + IsBigOWith (‖c'‖ * c) l (fun x => c' • f' x) g := + .trans (.const_smul_self _) h (norm_nonneg _) + +theorem IsBigO.const_smul_left (h : f' =O[l] g) (c : R) : (c • f') =O[l] g := + let ⟨_b, hb⟩ := h.isBigOWith + (hb.const_smul_left _).isBigO + +theorem IsLittleO.const_smul_left (h : f' =o[l] g) (c : R) : (c • f') =o[l] g := + (IsBigO.const_smul_self _).trans_isLittleO h + +variable [Module 𝕜 E'] [BoundedSMul 𝕜 E'] + +theorem isBigO_const_smul_left {c : 𝕜} (hc : c ≠ 0) : (fun x => c • f' x) =O[l] g ↔ f' =O[l] g := by + have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc + rw [← isBigO_norm_left] + simp only [norm_smul] + rw [isBigO_const_mul_left_iff cne0, isBigO_norm_left] + +theorem isLittleO_const_smul_left {c : 𝕜} (hc : c ≠ 0) : + (fun x => c • f' x) =o[l] g ↔ f' =o[l] g := by + have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc + rw [← isLittleO_norm_left] + simp only [norm_smul] + rw [isLittleO_const_mul_left_iff cne0, isLittleO_norm_left] + +theorem isBigO_const_smul_right {c : 𝕜} (hc : c ≠ 0) : + (f =O[l] fun x => c • f' x) ↔ f =O[l] f' := by + have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc + rw [← isBigO_norm_right] + simp only [norm_smul] + rw [isBigO_const_mul_right_iff cne0, isBigO_norm_right] + +theorem isLittleO_const_smul_right {c : 𝕜} (hc : c ≠ 0) : + (f =o[l] fun x => c • f' x) ↔ f =o[l] f' := by + have cne0 : ‖c‖ ≠ 0 := norm_ne_zero_iff.mpr hc + rw [← isLittleO_norm_right] + simp only [norm_smul] + rw [isLittleO_const_mul_right_iff cne0, isLittleO_norm_right] + +end SMulConst + +section SMul + +variable [Module R E'] [BoundedSMul R E'] [Module 𝕜' F'] [BoundedSMul 𝕜' F'] +variable {k₁ : α → R} {k₂ : α → 𝕜'} + +theorem IsBigOWith.smul (h₁ : IsBigOWith c l k₁ k₂) (h₂ : IsBigOWith c' l f' g') : + IsBigOWith (c * c') l (fun x => k₁ x • f' x) fun x => k₂ x • g' x := by + simp only [IsBigOWith_def] at * + filter_upwards [h₁, h₂] with _ hx₁ hx₂ + apply le_trans (norm_smul_le _ _) + convert mul_le_mul hx₁ hx₂ (norm_nonneg _) (le_trans (norm_nonneg _) hx₁) using 1 + rw [norm_smul, mul_mul_mul_comm] + +theorem IsBigO.smul (h₁ : k₁ =O[l] k₂) (h₂ : f' =O[l] g') : + (fun x => k₁ x • f' x) =O[l] fun x => k₂ x • g' x := by + obtain ⟨c₁, h₁⟩ := h₁.isBigOWith + obtain ⟨c₂, h₂⟩ := h₂.isBigOWith + exact (h₁.smul h₂).isBigO + +theorem IsBigO.smul_isLittleO (h₁ : k₁ =O[l] k₂) (h₂ : f' =o[l] g') : + (fun x => k₁ x • f' x) =o[l] fun x => k₂ x • g' x := by + simp only [IsLittleO_def] at * + intro c cpos + rcases h₁.exists_pos with ⟨c', c'pos, hc'⟩ + exact (hc'.smul (h₂ (div_pos cpos c'pos))).congr_const (mul_div_cancel₀ _ (ne_of_gt c'pos)) + +theorem IsLittleO.smul_isBigO (h₁ : k₁ =o[l] k₂) (h₂ : f' =O[l] g') : + (fun x => k₁ x • f' x) =o[l] fun x => k₂ x • g' x := by + simp only [IsLittleO_def] at * + intro c cpos + rcases h₂.exists_pos with ⟨c', c'pos, hc'⟩ + exact ((h₁ (div_pos cpos c'pos)).smul hc').congr_const (div_mul_cancel₀ _ (ne_of_gt c'pos)) + +theorem IsLittleO.smul (h₁ : k₁ =o[l] k₂) (h₂ : f' =o[l] g') : + (fun x => k₁ x • f' x) =o[l] fun x => k₂ x • g' x := + h₁.smul_isBigO h₂.isBigO + +end SMul + +section Prod +variable {ι : Type*} + +theorem IsBigO.listProd {L : List ι} {f : ι → α → R} {g : ι → α → 𝕜} + (hf : ∀ i ∈ L, f i =O[l] g i) : + (fun x ↦ (L.map (f · x)).prod) =O[l] (fun x ↦ (L.map (g · x)).prod) := by + induction L with + | nil => simp [isBoundedUnder_const] + | cons i L ihL => + simp only [List.map_cons, List.prod_cons, List.forall_mem_cons] at hf ⊢ + exact hf.1.mul (ihL hf.2) + +theorem IsBigO.multisetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] + {s : Multiset ι} {f : ι → α → R} {g : ι → α → 𝕜} (hf : ∀ i ∈ s, f i =O[l] g i) : + (fun x ↦ (s.map (f · x)).prod) =O[l] (fun x ↦ (s.map (g · x)).prod) := by + obtain ⟨l, rfl⟩ : ∃ l : List ι, ↑l = s := Quotient.mk_surjective s + exact mod_cast IsBigO.listProd hf + +theorem IsBigO.finsetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] + {s : Finset ι} {f : ι → α → R} {g : ι → α → 𝕜} + (hf : ∀ i ∈ s, f i =O[l] g i) : (∏ i ∈ s, f i ·) =O[l] (∏ i ∈ s, g i ·) := + .multisetProd hf + +theorem IsLittleO.listProd {L : List ι} {f : ι → α → R} {g : ι → α → 𝕜} + (h₁ : ∀ i ∈ L, f i =O[l] g i) (h₂ : ∃ i ∈ L, f i =o[l] g i) : + (fun x ↦ (L.map (f · x)).prod) =o[l] (fun x ↦ (L.map (g · x)).prod) := by + induction L with + | nil => simp at h₂ + | cons i L ihL => + simp only [List.map_cons, List.prod_cons, List.forall_mem_cons, List.exists_mem_cons_iff] + at h₁ h₂ ⊢ + cases h₂ with + | inl hi => exact hi.mul_isBigO <| .listProd h₁.2 + | inr hL => exact h₁.1.mul_isLittleO <| ihL h₁.2 hL + +theorem IsLittleO.multisetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] + {s : Multiset ι} {f : ι → α → R} {g : ι → α → 𝕜} (h₁ : ∀ i ∈ s, f i =O[l] g i) + (h₂ : ∃ i ∈ s, f i =o[l] g i) : + (fun x ↦ (s.map (f · x)).prod) =o[l] (fun x ↦ (s.map (g · x)).prod) := by + obtain ⟨l, rfl⟩ : ∃ l : List ι, ↑l = s := Quotient.mk_surjective s + exact mod_cast IsLittleO.listProd h₁ h₂ + +theorem IsLittleO.finsetProd {R 𝕜 : Type*} [SeminormedCommRing R] [NormedField 𝕜] + {s : Finset ι} {f : ι → α → R} {g : ι → α → 𝕜} (h₁ : ∀ i ∈ s, f i =O[l] g i) + (h₂ : ∃ i ∈ s, f i =o[l] g i) : (∏ i ∈ s, f i ·) =o[l] (∏ i ∈ s, g i ·) := + .multisetProd h₁ h₂ + +end Prod + +/-! ### Relation between `f = o(g)` and `f / g → 0` -/ + +theorem IsLittleO.tendsto_div_nhds_zero {f g : α → 𝕜} (h : f =o[l] g) : + Tendsto (fun x => f x / g x) l (𝓝 0) := + (isLittleO_one_iff 𝕜).mp <| by + calc + (fun x => f x / g x) =o[l] fun x => g x / g x := by + simpa only [div_eq_mul_inv] using h.mul_isBigO (isBigO_refl _ _) + _ =O[l] fun _x => (1 : 𝕜) := isBigO_of_le _ fun x => by simp [div_self_le_one] + +theorem IsLittleO.tendsto_inv_smul_nhds_zero [Module 𝕜 E'] [BoundedSMul 𝕜 E'] + {f : α → E'} {g : α → 𝕜} + {l : Filter α} (h : f =o[l] g) : Tendsto (fun x => (g x)⁻¹ • f x) l (𝓝 0) := by + simpa only [div_eq_inv_mul, ← norm_inv, ← norm_smul, ← tendsto_zero_iff_norm_tendsto_zero] using + h.norm_norm.tendsto_div_nhds_zero + +theorem isLittleO_iff_tendsto' {f g : α → 𝕜} (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) : + f =o[l] g ↔ Tendsto (fun x => f x / g x) l (𝓝 0) := + ⟨IsLittleO.tendsto_div_nhds_zero, fun h => + (((isLittleO_one_iff _).mpr h).mul_isBigO (isBigO_refl g l)).congr' + (hgf.mono fun _x => div_mul_cancel_of_imp) (Eventually.of_forall fun _x => one_mul _)⟩ + +theorem isLittleO_iff_tendsto {f g : α → 𝕜} (hgf : ∀ x, g x = 0 → f x = 0) : + f =o[l] g ↔ Tendsto (fun x => f x / g x) l (𝓝 0) := + isLittleO_iff_tendsto' (Eventually.of_forall hgf) + +alias ⟨_, isLittleO_of_tendsto'⟩ := isLittleO_iff_tendsto' + +alias ⟨_, isLittleO_of_tendsto⟩ := isLittleO_iff_tendsto + +theorem isLittleO_const_left_of_ne {c : E''} (hc : c ≠ 0) : + (fun _x => c) =o[l] g ↔ Tendsto (fun x => ‖g x‖) l atTop := by + simp only [← isLittleO_one_left_iff ℝ] + exact ⟨(isBigO_const_const (1 : ℝ) hc l).trans_isLittleO, + (isBigO_const_one ℝ c l).trans_isLittleO⟩ + +@[simp] +theorem isLittleO_const_left {c : E''} : + (fun _x => c) =o[l] g'' ↔ c = 0 ∨ Tendsto (norm ∘ g'') l atTop := by + rcases eq_or_ne c 0 with (rfl | hc) + · simp only [isLittleO_zero, eq_self_iff_true, true_or] + · simp only [hc, false_or, isLittleO_const_left_of_ne hc]; rfl + +@[simp 1001] -- Porting note: increase priority so that this triggers before `isLittleO_const_left` +theorem isLittleO_const_const_iff [NeBot l] {d : E''} {c : F''} : + ((fun _x => d) =o[l] fun _x => c) ↔ d = 0 := by + have : ¬Tendsto (Function.const α ‖c‖) l atTop := + not_tendsto_atTop_of_tendsto_nhds tendsto_const_nhds + simp only [isLittleO_const_left, or_iff_left_iff_imp] + exact fun h => (this h).elim + +@[simp] +theorem isLittleO_pure {x} : f'' =o[pure x] g'' ↔ f'' x = 0 := + calc + f'' =o[pure x] g'' ↔ (fun _y : α => f'' x) =o[pure x] fun _ => g'' x := isLittleO_congr rfl rfl + _ ↔ f'' x = 0 := isLittleO_const_const_iff + +theorem isLittleO_const_id_cobounded (c : F'') : + (fun _ => c) =o[Bornology.cobounded E''] id := + isLittleO_const_left.2 <| .inr tendsto_norm_cobounded_atTop + +theorem isLittleO_const_id_atTop (c : E'') : (fun _x : ℝ => c) =o[atTop] id := + isLittleO_const_left.2 <| Or.inr tendsto_abs_atTop_atTop + +theorem isLittleO_const_id_atBot (c : E'') : (fun _x : ℝ => c) =o[atBot] id := + isLittleO_const_left.2 <| Or.inr tendsto_abs_atBot_atTop + +/-! ### Equivalent definitions of the form `∃ φ, u =ᶠ[l] φ * v` in a `NormedField`. -/ + +section ExistsMulEq + +variable {u v : α → 𝕜} + +/-- If `‖φ‖` is eventually bounded by `c`, and `u =ᶠ[l] φ * v`, then we have `IsBigOWith c u v l`. + This does not require any assumptions on `c`, which is why we keep this version along with + `IsBigOWith_iff_exists_eq_mul`. -/ +theorem isBigOWith_of_eq_mul {u v : α → R} (φ : α → R) (hφ : ∀ᶠ x in l, ‖φ x‖ ≤ c) + (h : u =ᶠ[l] φ * v) : + IsBigOWith c l u v := by + simp only [IsBigOWith_def] + refine h.symm.rw (fun x a => ‖a‖ ≤ c * ‖v x‖) (hφ.mono fun x hx => ?_) + simp only [Pi.mul_apply] + refine (norm_mul_le _ _).trans ?_ + gcongr + +theorem isBigOWith_iff_exists_eq_mul (hc : 0 ≤ c) : + IsBigOWith c l u v ↔ ∃ φ : α → 𝕜, (∀ᶠ x in l, ‖φ x‖ ≤ c) ∧ u =ᶠ[l] φ * v := by + constructor + · intro h + use fun x => u x / v x + refine ⟨Eventually.mono h.bound fun y hy => ?_, h.eventually_mul_div_cancel.symm⟩ + simpa using div_le_of_le_mul₀ (norm_nonneg _) hc hy + · rintro ⟨φ, hφ, h⟩ + exact isBigOWith_of_eq_mul φ hφ h + +theorem IsBigOWith.exists_eq_mul (h : IsBigOWith c l u v) (hc : 0 ≤ c) : + ∃ φ : α → 𝕜, (∀ᶠ x in l, ‖φ x‖ ≤ c) ∧ u =ᶠ[l] φ * v := + (isBigOWith_iff_exists_eq_mul hc).mp h + +theorem isBigO_iff_exists_eq_mul : + u =O[l] v ↔ ∃ φ : α → 𝕜, l.IsBoundedUnder (· ≤ ·) (norm ∘ φ) ∧ u =ᶠ[l] φ * v := by + constructor + · rintro h + rcases h.exists_nonneg with ⟨c, hnnc, hc⟩ + rcases hc.exists_eq_mul hnnc with ⟨φ, hφ, huvφ⟩ + exact ⟨φ, ⟨c, hφ⟩, huvφ⟩ + · rintro ⟨φ, ⟨c, hφ⟩, huvφ⟩ + exact isBigO_iff_isBigOWith.2 ⟨c, isBigOWith_of_eq_mul φ hφ huvφ⟩ + +alias ⟨IsBigO.exists_eq_mul, _⟩ := isBigO_iff_exists_eq_mul + +theorem isLittleO_iff_exists_eq_mul : + u =o[l] v ↔ ∃ φ : α → 𝕜, Tendsto φ l (𝓝 0) ∧ u =ᶠ[l] φ * v := by + constructor + · exact fun h => ⟨fun x => u x / v x, h.tendsto_div_nhds_zero, h.eventually_mul_div_cancel.symm⟩ + · simp only [IsLittleO_def] + rintro ⟨φ, hφ, huvφ⟩ c hpos + rw [NormedAddCommGroup.tendsto_nhds_zero] at hφ + exact isBigOWith_of_eq_mul _ ((hφ c hpos).mono fun x => le_of_lt) huvφ + +alias ⟨IsLittleO.exists_eq_mul, _⟩ := isLittleO_iff_exists_eq_mul + +end ExistsMulEq + +/-! ### Miscellaneous lemmas -/ + +theorem div_isBoundedUnder_of_isBigO {α : Type*} {l : Filter α} {f g : α → 𝕜} (h : f =O[l] g) : + IsBoundedUnder (· ≤ ·) l fun x => ‖f x / g x‖ := by + obtain ⟨c, h₀, hc⟩ := h.exists_nonneg + refine ⟨c, eventually_map.2 (hc.bound.mono fun x hx => ?_)⟩ + rw [norm_div] + exact div_le_of_le_mul₀ (norm_nonneg _) h₀ hx + +theorem isBigO_iff_div_isBoundedUnder {α : Type*} {l : Filter α} {f g : α → 𝕜} + (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) : + f =O[l] g ↔ IsBoundedUnder (· ≤ ·) l fun x => ‖f x / g x‖ := by + refine ⟨div_isBoundedUnder_of_isBigO, fun h => ?_⟩ + obtain ⟨c, hc⟩ := h + simp only [eventually_map, norm_div] at hc + refine IsBigO.of_bound c (hc.mp <| hgf.mono fun x hx₁ hx₂ => ?_) + by_cases hgx : g x = 0 + · simp [hx₁ hgx, hgx] + · exact (div_le_iff₀ (norm_pos_iff.2 hgx)).mp hx₂ + +theorem isBigO_of_div_tendsto_nhds {α : Type*} {l : Filter α} {f g : α → 𝕜} + (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) (c : 𝕜) (H : Filter.Tendsto (f / g) l (𝓝 c)) : + f =O[l] g := + (isBigO_iff_div_isBoundedUnder hgf).2 <| H.norm.isBoundedUnder_le + +theorem IsLittleO.tendsto_zero_of_tendsto {α E 𝕜 : Type*} [NormedAddCommGroup E] [NormedField 𝕜] + {u : α → E} {v : α → 𝕜} {l : Filter α} {y : 𝕜} (huv : u =o[l] v) (hv : Tendsto v l (𝓝 y)) : + Tendsto u l (𝓝 0) := by + suffices h : u =o[l] fun _x => (1 : 𝕜) by + rwa [isLittleO_one_iff] at h + exact huv.trans_isBigO (hv.isBigO_one 𝕜) + +theorem isLittleO_pow_pow {m n : ℕ} (h : m < n) : (fun x : 𝕜 => x ^ n) =o[𝓝 0] fun x => x ^ m := by + rcases lt_iff_exists_add.1 h with ⟨p, hp0 : 0 < p, rfl⟩ + suffices (fun x : 𝕜 => x ^ m * x ^ p) =o[𝓝 0] fun x => x ^ m * 1 ^ p by + simpa only [pow_add, one_pow, mul_one] + exact IsBigO.mul_isLittleO (isBigO_refl _ _) + (IsLittleO.pow ((isLittleO_one_iff _).2 tendsto_id) hp0) + +theorem isLittleO_norm_pow_norm_pow {m n : ℕ} (h : m < n) : + (fun x : E' => ‖x‖ ^ n) =o[𝓝 0] fun x => ‖x‖ ^ m := + (isLittleO_pow_pow h).comp_tendsto tendsto_norm_zero + +theorem isLittleO_pow_id {n : ℕ} (h : 1 < n) : (fun x : 𝕜 => x ^ n) =o[𝓝 0] fun x => x := by + convert isLittleO_pow_pow h (𝕜 := 𝕜) + simp only [pow_one] + +theorem isLittleO_norm_pow_id {n : ℕ} (h : 1 < n) : + (fun x : E' => ‖x‖ ^ n) =o[𝓝 0] fun x => x := by + have := @isLittleO_norm_pow_norm_pow E' _ _ _ h + simp only [pow_one] at this + exact isLittleO_norm_right.mp this + +theorem IsBigO.eq_zero_of_norm_pow_within {f : E'' → F''} {s : Set E''} {x₀ : E''} {n : ℕ} + (h : f =O[𝓝[s] x₀] fun x => ‖x - x₀‖ ^ n) (hx₀ : x₀ ∈ s) (hn : n ≠ 0) : f x₀ = 0 := + mem_of_mem_nhdsWithin hx₀ h.eq_zero_imp <| by simp_rw [sub_self, norm_zero, zero_pow hn] + +theorem IsBigO.eq_zero_of_norm_pow {f : E'' → F''} {x₀ : E''} {n : ℕ} + (h : f =O[𝓝 x₀] fun x => ‖x - x₀‖ ^ n) (hn : n ≠ 0) : f x₀ = 0 := by + rw [← nhdsWithin_univ] at h + exact h.eq_zero_of_norm_pow_within (mem_univ _) hn + +theorem isLittleO_pow_sub_pow_sub (x₀ : E') {n m : ℕ} (h : n < m) : + (fun x => ‖x - x₀‖ ^ m) =o[𝓝 x₀] fun x => ‖x - x₀‖ ^ n := + haveI : Tendsto (fun x => ‖x - x₀‖) (𝓝 x₀) (𝓝 0) := by + apply tendsto_norm_zero.comp + rw [← sub_self x₀] + exact tendsto_id.sub tendsto_const_nhds + (isLittleO_pow_pow h).comp_tendsto this + +theorem isLittleO_pow_sub_sub (x₀ : E') {m : ℕ} (h : 1 < m) : + (fun x => ‖x - x₀‖ ^ m) =o[𝓝 x₀] fun x => x - x₀ := by + simpa only [isLittleO_norm_right, pow_one] using isLittleO_pow_sub_pow_sub x₀ h + +theorem IsBigOWith.right_le_sub_of_lt_one {f₁ f₂ : α → E'} (h : IsBigOWith c l f₁ f₂) (hc : c < 1) : + IsBigOWith (1 / (1 - c)) l f₂ fun x => f₂ x - f₁ x := + IsBigOWith.of_bound <| + mem_of_superset h.bound fun x hx => by + simp only [mem_setOf_eq] at hx ⊢ + rw [mul_comm, one_div, ← div_eq_mul_inv, le_div_iff₀, mul_sub, mul_one, mul_comm] + · exact le_trans (sub_le_sub_left hx _) (norm_sub_norm_le _ _) + · exact sub_pos.2 hc + +theorem IsBigOWith.right_le_add_of_lt_one {f₁ f₂ : α → E'} (h : IsBigOWith c l f₁ f₂) (hc : c < 1) : + IsBigOWith (1 / (1 - c)) l f₂ fun x => f₁ x + f₂ x := + (h.neg_right.right_le_sub_of_lt_one hc).neg_right.of_neg_left.congr rfl (fun _ ↦ rfl) fun x ↦ by + rw [neg_sub, sub_neg_eq_add] + +theorem IsLittleO.right_isBigO_sub {f₁ f₂ : α → E'} (h : f₁ =o[l] f₂) : + f₂ =O[l] fun x => f₂ x - f₁ x := + ((h.def' one_half_pos).right_le_sub_of_lt_one one_half_lt_one).isBigO + +theorem IsLittleO.right_isBigO_add {f₁ f₂ : α → E'} (h : f₁ =o[l] f₂) : + f₂ =O[l] fun x => f₁ x + f₂ x := + ((h.def' one_half_pos).right_le_add_of_lt_one one_half_lt_one).isBigO + +theorem IsLittleO.right_isBigO_add' {f₁ f₂ : α → E'} (h : f₁ =o[l] f₂) : + f₂ =O[l] (f₂ + f₁) := + add_comm f₁ f₂ ▸ h.right_isBigO_add + +/-- If `f x = O(g x)` along `cofinite`, then there exists a positive constant `C` such that +`‖f x‖ ≤ C * ‖g x‖` whenever `g x ≠ 0`. -/ +theorem bound_of_isBigO_cofinite (h : f =O[cofinite] g'') : + ∃ C > 0, ∀ ⦃x⦄, g'' x ≠ 0 → ‖f x‖ ≤ C * ‖g'' x‖ := by + rcases h.exists_pos with ⟨C, C₀, hC⟩ + rw [IsBigOWith_def, eventually_cofinite] at hC + rcases (hC.toFinset.image fun x => ‖f x‖ / ‖g'' x‖).exists_le with ⟨C', hC'⟩ + have : ∀ x, C * ‖g'' x‖ < ‖f x‖ → ‖f x‖ / ‖g'' x‖ ≤ C' := by simpa using hC' + refine ⟨max C C', lt_max_iff.2 (Or.inl C₀), fun x h₀ => ?_⟩ + rw [max_mul_of_nonneg _ _ (norm_nonneg _), le_max_iff, or_iff_not_imp_left, not_le] + exact fun hx => (div_le_iff₀ (norm_pos_iff.2 h₀)).1 (this _ hx) + +theorem isBigO_cofinite_iff (h : ∀ x, g'' x = 0 → f'' x = 0) : + f'' =O[cofinite] g'' ↔ ∃ C, ∀ x, ‖f'' x‖ ≤ C * ‖g'' x‖ := by + classical + exact ⟨fun h' => + let ⟨C, _C₀, hC⟩ := bound_of_isBigO_cofinite h' + ⟨C, fun x => if hx : g'' x = 0 then by simp [h _ hx, hx] else hC hx⟩, + fun h => (isBigO_top.2 h).mono le_top⟩ + +theorem bound_of_isBigO_nat_atTop {f : ℕ → E} {g'' : ℕ → E''} (h : f =O[atTop] g'') : + ∃ C > 0, ∀ ⦃x⦄, g'' x ≠ 0 → ‖f x‖ ≤ C * ‖g'' x‖ := + bound_of_isBigO_cofinite <| by rwa [Nat.cofinite_eq_atTop] + +theorem isBigO_nat_atTop_iff {f : ℕ → E''} {g : ℕ → F''} (h : ∀ x, g x = 0 → f x = 0) : + f =O[atTop] g ↔ ∃ C, ∀ x, ‖f x‖ ≤ C * ‖g x‖ := by + rw [← Nat.cofinite_eq_atTop, isBigO_cofinite_iff h] + +theorem isBigO_one_nat_atTop_iff {f : ℕ → E''} : + f =O[atTop] (fun _n => 1 : ℕ → ℝ) ↔ ∃ C, ∀ n, ‖f n‖ ≤ C := + Iff.trans (isBigO_nat_atTop_iff fun _ h => (one_ne_zero h).elim) <| by + simp only [norm_one, mul_one] + +theorem isBigOWith_pi {ι : Type*} [Fintype ι] {E' : ι → Type*} [∀ i, NormedAddCommGroup (E' i)] + {f : α → ∀ i, E' i} {C : ℝ} (hC : 0 ≤ C) : + IsBigOWith C l f g' ↔ ∀ i, IsBigOWith C l (fun x => f x i) g' := by + have : ∀ x, 0 ≤ C * ‖g' x‖ := fun x => mul_nonneg hC (norm_nonneg _) + simp only [isBigOWith_iff, pi_norm_le_iff_of_nonneg (this _), eventually_all] + +@[simp] +theorem isBigO_pi {ι : Type*} [Fintype ι] {E' : ι → Type*} [∀ i, NormedAddCommGroup (E' i)] + {f : α → ∀ i, E' i} : f =O[l] g' ↔ ∀ i, (fun x => f x i) =O[l] g' := by + simp only [isBigO_iff_eventually_isBigOWith, ← eventually_all] + exact eventually_congr (eventually_atTop.2 ⟨0, fun c => isBigOWith_pi⟩) + +@[simp] +theorem isLittleO_pi {ι : Type*} [Fintype ι] {E' : ι → Type*} [∀ i, NormedAddCommGroup (E' i)] + {f : α → ∀ i, E' i} : f =o[l] g' ↔ ∀ i, (fun x => f x i) =o[l] g' := by + simp +contextual only [IsLittleO_def, isBigOWith_pi, le_of_lt] + exact ⟨fun h i c hc => h hc i, fun h c hc i => h i hc⟩ + +theorem IsBigO.natCast_atTop {R : Type*} [StrictOrderedSemiring R] [Archimedean R] + {f : R → E} {g : R → F} (h : f =O[atTop] g) : + (fun (n : ℕ) => f n) =O[atTop] (fun n => g n) := + IsBigO.comp_tendsto h tendsto_natCast_atTop_atTop + +@[deprecated (since := "2024-04-17")] +alias IsBigO.nat_cast_atTop := IsBigO.natCast_atTop + +theorem IsLittleO.natCast_atTop {R : Type*} [StrictOrderedSemiring R] [Archimedean R] + {f : R → E} {g : R → F} (h : f =o[atTop] g) : + (fun (n : ℕ) => f n) =o[atTop] (fun n => g n) := + IsLittleO.comp_tendsto h tendsto_natCast_atTop_atTop + +@[deprecated (since := "2024-04-17")] +alias IsLittleO.nat_cast_atTop := IsLittleO.natCast_atTop + +theorem isBigO_atTop_iff_eventually_exists {α : Type*} [SemilatticeSup α] [Nonempty α] + {f : α → E} {g : α → F} : f =O[atTop] g ↔ ∀ᶠ n₀ in atTop, ∃ c, ∀ n ≥ n₀, ‖f n‖ ≤ c * ‖g n‖ := by + rw [isBigO_iff, exists_eventually_atTop] + +theorem isBigO_atTop_iff_eventually_exists_pos {α : Type*} + [SemilatticeSup α] [Nonempty α] {f : α → G} {g : α → G'} : + f =O[atTop] g ↔ ∀ᶠ n₀ in atTop, ∃ c > 0, ∀ n ≥ n₀, c * ‖f n‖ ≤ ‖g n‖ := by + simp_rw [isBigO_iff'', ← exists_prop, Subtype.exists', exists_eventually_atTop] + +lemma isBigO_mul_iff_isBigO_div {f g h : α → 𝕜} (hf : ∀ᶠ x in l, f x ≠ 0) : + (fun x ↦ f x * g x) =O[l] h ↔ g =O[l] (fun x ↦ h x / f x) := by + rw [isBigO_iff', isBigO_iff'] + refine ⟨fun ⟨c, hc, H⟩ ↦ ⟨c, hc, ?_⟩, fun ⟨c, hc, H⟩ ↦ ⟨c, hc, ?_⟩⟩ <;> + · refine H.congr <| Eventually.mp hf <| Eventually.of_forall fun x hx ↦ ?_ + rw [norm_mul, norm_div, ← mul_div_assoc, le_div_iff₀' (norm_pos_iff.mpr hx)] + +end Asymptotics + +open Asymptotics + +theorem summable_of_isBigO {ι E} [SeminormedAddCommGroup E] [CompleteSpace E] + {f : ι → E} {g : ι → ℝ} (hg : Summable g) (h : f =O[cofinite] g) : Summable f := + let ⟨C, hC⟩ := h.isBigOWith + .of_norm_bounded_eventually (fun x => C * ‖g x‖) (hg.abs.mul_left _) hC.bound + +theorem summable_of_isBigO_nat {E} [SeminormedAddCommGroup E] [CompleteSpace E] + {f : ℕ → E} {g : ℕ → ℝ} (hg : Summable g) (h : f =O[atTop] g) : Summable f := + summable_of_isBigO hg <| Nat.cofinite_eq_atTop.symm ▸ h + +lemma Asymptotics.IsBigO.comp_summable_norm {ι E F : Type*} + [SeminormedAddCommGroup E] [SeminormedAddCommGroup F] {f : E → F} {g : ι → E} + (hf : f =O[𝓝 0] id) (hg : Summable (‖g ·‖)) : Summable (‖f <| g ·‖) := + summable_of_isBigO hg <| hf.norm_norm.comp_tendsto <| + tendsto_zero_iff_norm_tendsto_zero.2 hg.tendsto_cofinite_zero + +namespace PartialHomeomorph + +variable {α : Type*} {β : Type*} [TopologicalSpace α] [TopologicalSpace β] +variable {E : Type*} [Norm E] {F : Type*} [Norm F] + +/-- Transfer `IsBigOWith` over a `PartialHomeomorph`. -/ +theorem isBigOWith_congr (e : PartialHomeomorph α β) {b : β} (hb : b ∈ e.target) {f : β → E} + {g : β → F} {C : ℝ} : IsBigOWith C (𝓝 b) f g ↔ IsBigOWith C (𝓝 (e.symm b)) (f ∘ e) (g ∘ e) := + ⟨fun h => + h.comp_tendsto <| by + have := e.continuousAt (e.map_target hb) + rwa [ContinuousAt, e.rightInvOn hb] at this, + fun h => + (h.comp_tendsto (e.continuousAt_symm hb)).congr' rfl + ((e.eventually_right_inverse hb).mono fun _ hx => congr_arg f hx) + ((e.eventually_right_inverse hb).mono fun _ hx => congr_arg g hx)⟩ + +/-- Transfer `IsBigO` over a `PartialHomeomorph`. -/ +theorem isBigO_congr (e : PartialHomeomorph α β) {b : β} (hb : b ∈ e.target) {f : β → E} + {g : β → F} : f =O[𝓝 b] g ↔ (f ∘ e) =O[𝓝 (e.symm b)] (g ∘ e) := by + simp only [IsBigO_def] + exact exists_congr fun C => e.isBigOWith_congr hb + +/-- Transfer `IsLittleO` over a `PartialHomeomorph`. -/ +theorem isLittleO_congr (e : PartialHomeomorph α β) {b : β} (hb : b ∈ e.target) {f : β → E} + {g : β → F} : f =o[𝓝 b] g ↔ (f ∘ e) =o[𝓝 (e.symm b)] (g ∘ e) := by + simp only [IsLittleO_def] + exact forall₂_congr fun c _hc => e.isBigOWith_congr hb + +end PartialHomeomorph + +namespace Homeomorph + +variable {α : Type*} {β : Type*} [TopologicalSpace α] [TopologicalSpace β] +variable {E : Type*} [Norm E] {F : Type*} [Norm F] + +open Asymptotics + +/-- Transfer `IsBigOWith` over a `Homeomorph`. -/ +theorem isBigOWith_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F} {C : ℝ} : + IsBigOWith C (𝓝 b) f g ↔ IsBigOWith C (𝓝 (e.symm b)) (f ∘ e) (g ∘ e) := + e.toPartialHomeomorph.isBigOWith_congr trivial + +/-- Transfer `IsBigO` over a `Homeomorph`. -/ +theorem isBigO_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F} : + f =O[𝓝 b] g ↔ (f ∘ e) =O[𝓝 (e.symm b)] (g ∘ e) := by + simp only [IsBigO_def] + exact exists_congr fun C => e.isBigOWith_congr + +/-- Transfer `IsLittleO` over a `Homeomorph`. -/ +theorem isLittleO_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F} : + f =o[𝓝 b] g ↔ (f ∘ e) =o[𝓝 (e.symm b)] (g ∘ e) := by + simp only [IsLittleO_def] + exact forall₂_congr fun c _hc => e.isBigOWith_congr + +end Homeomorph + +namespace ContinuousOn + +variable {α E F : Type*} [TopologicalSpace α] {s : Set α} {f : α → E} {c : F} + +section IsBigO + +variable [SeminormedAddGroup E] [Norm F] + +protected theorem isBigOWith_principal + (hf : ContinuousOn f s) (hs : IsCompact s) (hc : ‖c‖ ≠ 0) : + IsBigOWith (sSup (Norm.norm '' (f '' s)) / ‖c‖) (𝓟 s) f fun _ => c := by + rw [isBigOWith_principal, div_mul_cancel₀ _ hc] + exact fun x hx ↦ hs.image_of_continuousOn hf |>.image continuous_norm + |>.isLUB_sSup (Set.image_nonempty.mpr <| Set.image_nonempty.mpr ⟨x, hx⟩) + |>.left <| Set.mem_image_of_mem _ <| Set.mem_image_of_mem _ hx + +protected theorem isBigO_principal (hf : ContinuousOn f s) (hs : IsCompact s) + (hc : ‖c‖ ≠ 0) : f =O[𝓟 s] fun _ => c := + (hf.isBigOWith_principal hs hc).isBigO + +end IsBigO + +section IsBigORev + +variable [NormedAddGroup E] [SeminormedAddGroup F] + +protected theorem isBigOWith_rev_principal + (hf : ContinuousOn f s) (hs : IsCompact s) (hC : ∀ i ∈ s, f i ≠ 0) (c : F) : + IsBigOWith (‖c‖ / sInf (Norm.norm '' (f '' s))) (𝓟 s) (fun _ => c) f := by + refine isBigOWith_principal.mpr fun x hx ↦ ?_ + rw [mul_comm_div] + replace hs := hs.image_of_continuousOn hf |>.image continuous_norm + have h_sInf := hs.isGLB_sInf <| Set.image_nonempty.mpr <| Set.image_nonempty.mpr ⟨x, hx⟩ + refine le_mul_of_one_le_right (norm_nonneg c) <| (one_le_div ?_).mpr <| + h_sInf.1 <| Set.mem_image_of_mem _ <| Set.mem_image_of_mem _ hx + obtain ⟨_, ⟨x, hx, hCx⟩, hnormCx⟩ := hs.sInf_mem h_sInf.nonempty + rw [← hnormCx, ← hCx] + exact (norm_ne_zero_iff.mpr (hC x hx)).symm.lt_of_le (norm_nonneg _) + +protected theorem isBigO_rev_principal (hf : ContinuousOn f s) + (hs : IsCompact s) (hC : ∀ i ∈ s, f i ≠ 0) (c : F) : (fun _ => c) =O[𝓟 s] f := + (hf.isBigOWith_rev_principal hs hC c).isBigO + +end IsBigORev + +end ContinuousOn + +/-- The (scalar) product of a sequence that tends to zero with a bounded one also tends to zero. -/ +lemma NormedField.tendsto_zero_smul_of_tendsto_zero_of_bounded {ι 𝕜 𝔸 : Type*} + [NormedDivisionRing 𝕜] [NormedAddCommGroup 𝔸] [Module 𝕜 𝔸] [BoundedSMul 𝕜 𝔸] {l : Filter ι} + {ε : ι → 𝕜} {f : ι → 𝔸} (hε : Tendsto ε l (𝓝 0)) (hf : IsBoundedUnder (· ≤ ·) l (norm ∘ f)) : + Tendsto (ε • f) l (𝓝 0) := by + rw [← isLittleO_one_iff 𝕜] at hε ⊢ + simpa using IsLittleO.smul_isBigO hε (hf.isBigO_const (one_ne_zero : (1 : 𝕜) ≠ 0)) diff --git a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean index 1bd7adcc93eac..e1c0e57e890c5 100644 --- a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker -/ import Mathlib.Analysis.Normed.Order.Basic -import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Lemmas import Mathlib.Analysis.Normed.Module.Basic /-! diff --git a/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean b/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean index 93000132bef6d..ff1cf91885c22 100644 --- a/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean +++ b/Mathlib/Analysis/Asymptotics/SuperpolynomialDecay.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Devon Tuma -/ import Mathlib.Algebra.Polynomial.Eval.Defs -import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Lemmas import Mathlib.Analysis.Normed.Order.Basic import Mathlib.Topology.Algebra.Order.LiminfLimsup diff --git a/Mathlib/Analysis/Asymptotics/TVS.lean b/Mathlib/Analysis/Asymptotics/TVS.lean index 744a9ff13285f..5d0db2d9253a3 100644 --- a/Mathlib/Analysis/Asymptotics/TVS.lean +++ b/Mathlib/Analysis/Asymptotics/TVS.lean @@ -3,12 +3,12 @@ Copyright (c) 2023 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Eric Wieser -/ -import Mathlib.Analysis.Asymptotics.Asymptotics import Mathlib.Analysis.Convex.EGauge import Mathlib.Analysis.LocallyConvex.BalancedCoreHull import Mathlib.Analysis.Seminorm import Mathlib.Tactic.Peel import Mathlib.Topology.Instances.ENNReal.Lemmas +import Mathlib.Analysis.Asymptotics.Defs /-! # Asymptotics in a Topological Vector Space diff --git a/Mathlib/Analysis/Asymptotics/Theta.lean b/Mathlib/Analysis/Asymptotics/Theta.lean index 9e460bf26ead9..77b0500237375 100644 --- a/Mathlib/Analysis/Asymptotics/Theta.lean +++ b/Mathlib/Analysis/Asymptotics/Theta.lean @@ -3,7 +3,7 @@ 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.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Lemmas import Mathlib.Analysis.Normed.Module.Basic /-! diff --git a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean index d632bf40052df..4ea2f24c3e6cc 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean @@ -6,6 +6,7 @@ Authors: Jeremy Avigad, Sébastien Gouëzel, Yury Kudryashov import Mathlib.Analysis.Calculus.TangentCone import Mathlib.Analysis.NormedSpace.OperatorNorm.Asymptotics import Mathlib.Analysis.Asymptotics.TVS +import Mathlib.Analysis.Asymptotics.Lemmas /-! # The Fréchet derivative diff --git a/Mathlib/Analysis/Normed/Group/InfiniteSum.lean b/Mathlib/Analysis/Normed/Group/InfiniteSum.lean index 10812f0670088..ed07d83ddba3c 100644 --- a/Mathlib/Analysis/Normed/Group/InfiniteSum.lean +++ b/Mathlib/Analysis/Normed/Group/InfiniteSum.lean @@ -28,7 +28,6 @@ In a complete (semi)normed group, infinite series, absolute convergence, normed group -/ - open Topology NNReal open Finset Filter Metric diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Asymptotics.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Asymptotics.lean index 4c8582196cf3e..f0f057e73ce72 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Asymptotics.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Asymptotics.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jan-David Salchow, Sébastien Gouëzel, Jean Lo -/ import Mathlib.Analysis.NormedSpace.OperatorNorm.Basic -import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Defs /-! # Asymptotic statements about the operator norm diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index 7c06da09b65e4..ae93fb202eb70 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -6,7 +6,7 @@ Authors: Anatole Dedecker, Sébastien Gouëzel, Yury Kudryashov, Dylan MacKenzie import Mathlib.Algebra.BigOperators.Module import Mathlib.Algebra.Order.Field.Power import Mathlib.Algebra.Polynomial.Monic -import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Lemmas import Mathlib.Analysis.Normed.Field.InfiniteSum import Mathlib.Analysis.Normed.Module.Basic import Mathlib.Analysis.SpecificLimits.Basic diff --git a/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean b/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean index 3a6c683e96c46..18f1b02ec5d3a 100644 --- a/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean +++ b/Mathlib/Order/Filter/ZeroAndBoundedAtFilter.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck, David Loeffler -/ import Mathlib.Algebra.Module.Submodule.Basic -import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Asymptotics.Lemmas import Mathlib.Algebra.Algebra.Pi /-! From 0ccda7e900714aea4682d3aa952ae592ef396c7d Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Sat, 18 Jan 2025 20:44:55 +0000 Subject: [PATCH 298/681] feat(AlgebraicGeometry): scheme-theoretic fibre (#19427) --- Mathlib.lean | 1 + Mathlib/AlgebraicGeometry/Fiber.lean | 121 ++++++++++++++++++ .../AlgebraicGeometry/Morphisms/Affine.lean | 2 +- .../Morphisms/ClosedImmersion.lean | 15 +-- .../Morphisms/FiniteType.lean | 37 ++++++ .../Morphisms/Preimmersion.lean | 11 -- .../RingTheory/Spectrum/Prime/Noetherian.lean | 19 +++ 7 files changed, 184 insertions(+), 22 deletions(-) create mode 100644 Mathlib/AlgebraicGeometry/Fiber.lean diff --git a/Mathlib.lean b/Mathlib.lean index b13b4427de5aa..7ab6014732d76 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -999,6 +999,7 @@ import Mathlib.AlgebraicGeometry.EllipticCurve.NormalForms import Mathlib.AlgebraicGeometry.EllipticCurve.Projective import Mathlib.AlgebraicGeometry.EllipticCurve.VariableChange import Mathlib.AlgebraicGeometry.EllipticCurve.Weierstrass +import Mathlib.AlgebraicGeometry.Fiber import Mathlib.AlgebraicGeometry.FunctionField import Mathlib.AlgebraicGeometry.GammaSpecAdjunction import Mathlib.AlgebraicGeometry.Gluing diff --git a/Mathlib/AlgebraicGeometry/Fiber.lean b/Mathlib/AlgebraicGeometry/Fiber.lean new file mode 100644 index 0000000000000..351e6adbdf650 --- /dev/null +++ b/Mathlib/AlgebraicGeometry/Fiber.lean @@ -0,0 +1,121 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.AlgebraicGeometry.PullbackCarrier +import Mathlib.AlgebraicGeometry.Morphisms.Finite +import Mathlib.RingTheory.Spectrum.Prime.Jacobson + +/-! +# Scheme-theoretic fiber + +## Main result +- `AlgebraicGeometry.Scheme.Hom.fiber`: `f.fiber y` is the scheme theoretic fiber of `f` at `y`. +- `AlgebraicGeometry.Scheme.Hom.fiberHomeo`: `f.fiber y` is homeomorphic to `f ⁻¹' {y}`. +- `AlgebraicGeometry.Scheme.Hom.finite_preimage`: Finite morphisms have finite fibers. +- `AlgebraicGeometry.Scheme.Hom.discrete_fiber`: Finite morphisms have discrete fibers. + +-/ + +universe u + +noncomputable section + +open CategoryTheory Limits + +namespace AlgebraicGeometry + +variable {X Y : Scheme.{u}} + +/-- `f.fiber y` is the scheme theoretic fiber of `f` at `y`. -/ +def Scheme.Hom.fiber (f : X.Hom Y) (y : Y) : Scheme := pullback f (Y.fromSpecResidueField y) + +/-- `f.fiberι y : f.fiber y ⟶ X` is the embedding of the scheme theoretic fiber into `X`. -/ +def Scheme.Hom.fiberι (f : X.Hom Y) (y : Y) : f.fiber y ⟶ X := pullback.fst _ _ + +instance (f : X.Hom Y) (y : Y) : (f.fiber y).CanonicallyOver X where hom := f.fiberι y + +/-- The canonical map from the scheme theoretic fiber to the residue field. -/ +def Scheme.Hom.fiberToSpecResidueField (f : X.Hom Y) (y : Y) : + f.fiber y ⟶ Spec (Y.residueField y) := + pullback.snd _ _ + +/-- The fiber of `f` at `y` is naturally a `κ(y)`-scheme. -/ +@[reducible] def Scheme.Hom.fiberOverSpecResidueField + (f : X.Hom Y) (y : Y) : (f.fiber y).Over (Spec (Y.residueField y)) where + hom := f.fiberToSpecResidueField y + +lemma Scheme.Hom.fiberToSpecResidueField_apply (f : X.Hom Y) (y : Y) (x : f.fiber y) : + (f.fiberToSpecResidueField y).base x = IsLocalRing.closedPoint (Y.residueField y) := + Subsingleton.elim (α := PrimeSpectrum _) _ _ + +lemma Scheme.Hom.range_fiberι (f : X.Hom Y) (y : Y) : + Set.range (f.fiberι y).base = f.base ⁻¹' {y} := by + simp [fiber, fiberι, Scheme.Pullback.range_fst, Scheme.range_fromSpecResidueField] + +instance (f : X ⟶ Y) (y : Y) : IsPreimmersion (f.fiberι y) := + MorphismProperty.pullback_fst _ _ inferInstance + +/-- The scheme theoretic fiber of `f` at `y` is homeomorphic to `f ⁻¹' {y}`. -/ +def Scheme.Hom.fiberHomeo (f : X.Hom Y) (y : Y) : f.fiber y ≃ₜ f.base ⁻¹' {y} := + .trans (.ofIsEmbedding _ (f.fiberι y).isEmbedding) (.setCongr (f.range_fiberι y)) + +@[simp] +lemma Scheme.Hom.fiberHomeo_apply (f : X.Hom Y) (y : Y) (x : f.fiber y) : + (f.fiberHomeo y x).1 = (f.fiberι y).base x := rfl + +@[simp] +lemma Scheme.Hom.fiberι_fiberHomeo_symm (f : X.Hom Y) (y : Y) (x : f.base ⁻¹' {y}) : + (f.fiberι y).base ((f.fiberHomeo y).symm x) = x := + congr($((f.fiberHomeo y).apply_symm_apply x).1) + +/-- A point `x` as a point in the fiber of `f` at `f x`. -/ +def Scheme.Hom.asFiber (f : X.Hom Y) (x : X) : f.fiber (f.base x) := + (f.fiberHomeo (f.base x)).symm ⟨x, rfl⟩ + +@[simp] +lemma Scheme.Hom.fiberι_asFiber (f : X.Hom Y) (x : X) : (f.fiberι _).base (f.asFiber x) = x := + f.fiberι_fiberHomeo_symm _ _ + +instance (f : X ⟶ Y) [QuasiCompact f] (y : Y) : CompactSpace (f.fiber y) := + haveI : QuasiCompact (f.fiberToSpecResidueField y) := + MorphismProperty.pullback_snd _ _ inferInstance + HasAffineProperty.iff_of_isAffine (P := @QuasiCompact) + (f := f.fiberToSpecResidueField y).mp inferInstance + +lemma QuasiCompact.isCompact_preimage_singleton (f : X ⟶ Y) [QuasiCompact f] (y : Y) : + IsCompact (f.base ⁻¹' {y}) := + f.range_fiberι y ▸ isCompact_range (f.fiberι y).continuous + +instance (f : X ⟶ Y) [IsAffineHom f] (y : Y) : IsAffine (f.fiber y) := + haveI : IsAffineHom (f.fiberToSpecResidueField y) := + MorphismProperty.pullback_snd _ _ inferInstance + isAffine_of_isAffineHom (f.fiberToSpecResidueField y) + +instance (f : X ⟶ Y) (y : Y) [LocallyOfFiniteType f] : JacobsonSpace (f.fiber y) := + have : LocallyOfFiniteType (f.fiberToSpecResidueField y) := + MorphismProperty.pullback_snd _ _ inferInstance + LocallyOfFiniteType.jacobsonSpace (f.fiberToSpecResidueField y) + +instance (f : X ⟶ Y) (y : Y) [IsFinite f] : Finite (f.fiber y) := by + have H : IsFinite (f.fiberToSpecResidueField y) := MorphismProperty.pullback_snd _ _ inferInstance + have : IsArtinianRing Γ(f.fiber y, ⊤) := + @IsArtinianRing.of_finite (Y.residueField y) Γ(f.fiber y, ⊤) _ _ (show _ from _) _ + ((HasAffineProperty.iff_of_isAffine.mp H).2.comp (.of_surjective _ (Scheme.ΓSpecIso + (Y.residueField y)).commRingCatIsoToRingEquiv.symm.surjective)) + exact .of_injective (β := PrimeSpectrum _) _ (f.fiber y).isoSpec.hom.homeomorph.injective + +lemma IsFinite.finite_preimage_singleton (f : X ⟶ Y) [IsFinite f] (y : Y) : + (f.base ⁻¹' {y}).Finite := + f.range_fiberι y ▸ Set.finite_range (f.fiberι y).base + +lemma Scheme.Hom.finite_preimage (f : X.Hom Y) [IsFinite f] {s : Set Y} (hs : s.Finite) : + (f.base ⁻¹' s).Finite := by + rw [← Set.biUnion_of_singleton s, Set.preimage_iUnion₂] + exact hs.biUnion fun _ _ ↦ IsFinite.finite_preimage_singleton f _ + +instance Scheme.Hom.discrete_fiber (f : X ⟶ Y) (y : Y) [IsFinite f] : + DiscreteTopology (f.fiber y) := inferInstance + +end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean index ff4190d85fb10..985ad73e03749 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean @@ -168,7 +168,7 @@ instance : HasAffineProperty @IsAffineHom fun X _ _ _ ↦ IsAffine X where Subtype.forall, isAffineHom_iff] rfl -lemma isAffineHom_isStableUnderBaseChange : +instance isAffineHom_isStableUnderBaseChange : MorphismProperty.IsStableUnderBaseChange @IsAffineHom := by apply HasAffineProperty.isStableUnderBaseChange letI := HasAffineProperty.isLocal_affineProperty diff --git a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean index 7aba92e4f57a5..988096eeac24d 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean @@ -39,9 +39,8 @@ namespace AlgebraicGeometry /-- A morphism of schemes `X ⟶ Y` is a closed immersion if the underlying topological map is a closed embedding and the induced stalk maps are surjective. -/ @[mk_iff] -class IsClosedImmersion {X Y : Scheme} (f : X ⟶ Y) : Prop where +class IsClosedImmersion {X Y : Scheme} (f : X ⟶ Y) extends SurjectiveOnStalks f : Prop where base_closed : IsClosedEmbedding f.base - surj_on_stalks : ∀ x, Function.Surjective (f.stalkMap x) lemma Scheme.Hom.isClosedEmbedding {X Y : Scheme} (f : X.Hom Y) [IsClosedImmersion f] : IsClosedEmbedding f.base := @@ -55,15 +54,14 @@ alias isClosedEmbedding := Scheme.Hom.isClosedEmbedding alias closedEmbedding := isClosedEmbedding lemma eq_inf : @IsClosedImmersion = (topologically IsClosedEmbedding) ⊓ - stalkwise (fun f ↦ Function.Surjective f) := by + @SurjectiveOnStalks := by ext X Y f - rw [isClosedImmersion_iff] + rw [isClosedImmersion_iff, and_comm] rfl lemma iff_isPreimmersion {X Y : Scheme} {f : X ⟶ Y} : IsClosedImmersion f ↔ IsPreimmersion f ∧ IsClosed (Set.range f.base) := by - rw [isClosedImmersion_iff, isPreimmersion_iff, ← surjectiveOnStalks_iff, and_comm, and_assoc, - isClosedEmbedding_iff] + rw [isClosedImmersion_iff, isPreimmersion_iff, and_assoc, isClosedEmbedding_iff] lemma of_isPreimmersion {X Y : Scheme} (f : X ⟶ Y) [IsPreimmersion f] (hf : IsClosed (Set.range f.base)) : IsClosedImmersion f := @@ -79,10 +77,7 @@ instance {X Y : Scheme} (f : X ⟶ Y) [IsIso f] : IsClosedImmersion f where instance : MorphismProperty.IsMultiplicative @IsClosedImmersion where id_mem _ := inferInstance - comp_mem {X Y Z} f g hf hg := by - refine ⟨hg.base_closed.comp hf.base_closed, fun x ↦ ?_⟩ - rw [Scheme.stalkMap_comp] - exact (hf.surj_on_stalks x).comp (hg.surj_on_stalks (f.base x)) + comp_mem _ _ hf hg := ⟨hg.base_closed.comp hf.base_closed⟩ /-- Composition of closed immersions is a closed immersion. -/ instance comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [IsClosedImmersion f] diff --git a/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean b/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean index 23f3fa844445d..08927fcedc39b 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/FiniteType.lean @@ -5,6 +5,7 @@ Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.Morphisms.RingHomProperties import Mathlib.RingTheory.RingHom.FiniteType +import Mathlib.RingTheory.Spectrum.Prime.Jacobson /-! # Morphisms of finite type @@ -67,4 +68,40 @@ instance locallyOfFiniteType_isStableUnderBaseChange : MorphismProperty.IsStableUnderBaseChange @LocallyOfFiniteType := HasRingHomProperty.isStableUnderBaseChange RingHom.finiteType_isStableUnderBaseChange +instance {R} [CommRing R] [IsJacobsonRing R] : JacobsonSpace (Spec (.of R)) := + inferInstanceAs (JacobsonSpace (PrimeSpectrum R)) + +instance {R : CommRingCat} [IsJacobsonRing R] : JacobsonSpace (Spec R) := + inferInstanceAs (JacobsonSpace (PrimeSpectrum R)) + +nonrec lemma LocallyOfFiniteType.jacobsonSpace + (f : X ⟶ Y) [LocallyOfFiniteType f] [JacobsonSpace Y] : JacobsonSpace X := by + wlog hY : ∃ S, Y = Spec S + · rw [jacobsonSpace_iff_of_iSup_eq_top + (Scheme.OpenCover.iSup_opensRange (Y.affineCover.pullbackCover f))] + intro i + have inst : LocallyOfFiniteType (Y.affineCover.pullbackHom f i) := + MorphismProperty.pullback_snd _ _ inferInstance + have inst : JacobsonSpace Y := ‹_› -- TC gets stuck on the WLOG hypothesis without it. + have inst : JacobsonSpace (Y.affineCover.obj i) := + .of_isOpenEmbedding (Y.affineCover.map i).isOpenEmbedding + let e := Homeomorph.ofIsEmbedding _ + ((Y.affineCover.pullbackCover f).map i).isOpenEmbedding.isEmbedding + have := this (Y.affineCover.pullbackHom f i) ⟨_, rfl⟩ + exact .of_isClosedEmbedding e.symm.isClosedEmbedding + obtain ⟨R, rfl⟩ := hY + wlog hX : ∃ S, X = Spec S + · have inst : JacobsonSpace (Spec R) := ‹_› -- TC gets stuck on the WLOG hypothesis without it. + rw [jacobsonSpace_iff_of_iSup_eq_top (Scheme.OpenCover.iSup_opensRange X.affineCover)] + intro i + have := this _ (X.affineCover.map i ≫ f) ⟨_, rfl⟩ + let e := Homeomorph.ofIsEmbedding _ (X.affineCover.map i).isOpenEmbedding.isEmbedding + exact .of_isClosedEmbedding e.symm.isClosedEmbedding + obtain ⟨S, rfl⟩ := hX + obtain ⟨φ, rfl : Spec.map φ = f⟩ := Spec.homEquiv.symm.surjective f + have : RingHom.FiniteType φ.hom := HasRingHomProperty.Spec_iff.mp ‹_› + algebraize [φ.hom] + have := PrimeSpectrum.isJacobsonRing_iff_jacobsonSpace.mpr ‹_› + exact PrimeSpectrum.isJacobsonRing_iff_jacobsonSpace.mp (isJacobsonRing_of_finiteType (A := R)) + end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean index 17521b9d49d3e..8cb9106a16165 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean @@ -15,12 +15,6 @@ is an embedding and the induced morphisms of stalks are all surjective. This is in the literature but it is useful for generalizing results on immersions to other maps including `Spec 𝒪_{X, x} ⟶ X` and inclusions of fibers `κ(x) ×ₓ Y ⟶ Y`. -## TODO - -* Show preimmersions are local at the target. -* Show preimmersions are stable under pullback. -* Show that `Spec f` is a preimmersion for `f : R ⟶ S` if every `s : S` is of the form `f a / f b`. - -/ universe v u @@ -47,11 +41,6 @@ lemma isPreimmersion_eq_inf : rw [isPreimmersion_iff] rfl -/-- Being surjective on stalks is local at the target. -/ -instance isSurjectiveOnStalks_isLocalAtTarget : IsLocalAtTarget - (stalkwise (Function.Surjective ·)) := - stalkwiseIsLocalAtTarget_of_respectsIso RingHom.surjective_respectsIso - namespace IsPreimmersion instance : IsLocalAtTarget @IsPreimmersion := diff --git a/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean b/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean index c388f7d7331b7..4e38232fb5a13 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Filippo A. E. Nuccio, Andrew Yang -/ import Mathlib.RingTheory.Spectrum.Prime.Topology +import Mathlib.RingTheory.Artinian.Module import Mathlib.Topology.NoetherianSpace /-! @@ -17,6 +18,8 @@ namespace PrimeSpectrum open TopologicalSpace +section IsNoetherianRing + variable (R : Type u) [CommRing R] [IsNoetherianRing R] instance : NoetherianSpace (PrimeSpectrum R) := @@ -34,4 +37,20 @@ lemma finite_setOf_isMin : simp_rw [isMin_iff] exact (minimalPrimes.finite_of_isNoetherianRing R).subset (Set.image_preimage_subset _ _) +end IsNoetherianRing + +section IsArtinianRing + +variable (R : Type u) [CommRing R] [IsArtinianRing R] + +instance : Finite (PrimeSpectrum R) := + have : Finite {I : Ideal R // I.IsPrime} := IsArtinianRing.primeSpectrum_finite R + Finite.of_injective _ (equivSubtype R).injective + +instance : DiscreteTopology (PrimeSpectrum R) := + discreteTopology_iff_finite_and_isPrime_imp_isMaximal.mpr + ⟨inferInstance, fun _ _ ↦ inferInstance⟩ + +end IsArtinianRing + end PrimeSpectrum From da939cc7cc2cb70f321008af805cb52b259b51d3 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Sat, 18 Jan 2025 20:53:44 +0000 Subject: [PATCH 299/681] feat(AlgebraicGeometry): flat morphisms of schemes (#19790) ... and show that `Flat` can be checked on stalks. The latter is shown more generally for any morphism property of schemes associated to a property of ring maps satisfying `RingHom.OfLocalizationPrime`. --- Mathlib.lean | 1 + .../GammaSpecAdjunction.lean | 7 ++ Mathlib/AlgebraicGeometry/Morphisms/Flat.lean | 76 +++++++++++++++++++ .../Morphisms/RingHomProperties.lean | 66 +++++++++++++++- Mathlib/AlgebraicGeometry/Restrict.lean | 32 +++++++- Mathlib/AlgebraicGeometry/Scheme.lean | 9 +++ Mathlib/RingTheory/RingHom/Flat.lean | 24 ++++++ Mathlib/RingTheory/RingHomProperties.lean | 10 +++ 8 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 Mathlib/AlgebraicGeometry/Morphisms/Flat.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7ab6014732d76..9c21378b22550 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1017,6 +1017,7 @@ import Mathlib.AlgebraicGeometry.Morphisms.Etale import Mathlib.AlgebraicGeometry.Morphisms.Finite import Mathlib.AlgebraicGeometry.Morphisms.FinitePresentation import Mathlib.AlgebraicGeometry.Morphisms.FiniteType +import Mathlib.AlgebraicGeometry.Morphisms.Flat import Mathlib.AlgebraicGeometry.Morphisms.Immersion import Mathlib.AlgebraicGeometry.Morphisms.Integral import Mathlib.AlgebraicGeometry.Morphisms.IsIso diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index b4331a3b7c954..82314906f6c4c 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -545,6 +545,13 @@ variable (φ) in @[simp] lemma Spec.preimage_map : Spec.preimage (Spec.map φ) = φ := Spec.map_injective (Spec.map_preimage (Spec.map φ)) +/-- Useful for replacing `f` by `Spec.map φ` everywhere in proofs. -/ +lemma Spec.map_surjective {R S : CommRingCat} : + Function.Surjective (Spec.map : (R ⟶ S) → _) := by + intro f + use Spec.preimage f + simp + /-- Spec is fully faithful -/ @[simps] def Spec.homEquiv {R S : CommRingCat} : (Spec S ⟶ Spec R) ≃ (R ⟶ S) where diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Flat.lean b/Mathlib/AlgebraicGeometry/Morphisms/Flat.lean new file mode 100644 index 0000000000000..47b2e6d0b97dc --- /dev/null +++ b/Mathlib/AlgebraicGeometry/Morphisms/Flat.lean @@ -0,0 +1,76 @@ +/- +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.AlgebraicGeometry.Morphisms.RingHomProperties +import Mathlib.RingTheory.RingHom.Flat + +/-! +# Flat morphisms + +A morphism of schemes `f : X ⟶ Y` is flat if for each affine `U ⊆ Y` and +`V ⊆ f ⁻¹' U`, the induced map `Γ(Y, U) ⟶ Γ(X, V)` is flat. This is equivalent to +asking that all stalk maps are flat (see `AlgebraicGeometry.Flat.iff_flat_stalkMap`). + +We show that this property is local, and are stable under compositions and base change. + +-/ + +noncomputable section + +open CategoryTheory CategoryTheory.Limits Opposite TopologicalSpace + +universe v u + +namespace AlgebraicGeometry + +variable {X Y : Scheme.{u}} (f : X ⟶ Y) + +/-- A morphism of schemes `f : X ⟶ Y` is flat if for each affine `U ⊆ Y` and +`V ⊆ f ⁻¹' U`, the induced map `Γ(Y, U) ⟶ Γ(X, V)` is flat. This is equivalent to +asking that all stalk maps are flat (see `AlgebraicGeometry.Flat.iff_flat_stalkMap`). +-/ +@[mk_iff] +class Flat (f : X ⟶ Y) : Prop where + flat_of_affine_subset : + ∀ (U : Y.affineOpens) (V : X.affineOpens) (e : V.1 ≤ f ⁻¹ᵁ U.1), (f.appLE U V e).hom.Flat + +namespace Flat + +instance : HasRingHomProperty @Flat RingHom.Flat where + isLocal_ringHomProperty := RingHom.Flat.propertyIsLocal + eq_affineLocally' := by + ext X Y f + rw [flat_iff, affineLocally_iff_affineOpens_le] + +instance (priority := 900) [IsOpenImmersion f] : Flat f := + HasRingHomProperty.of_isOpenImmersion + RingHom.Flat.containsIdentities + +instance : MorphismProperty.IsStableUnderComposition @Flat := + HasRingHomProperty.stableUnderComposition RingHom.Flat.stableUnderComposition + +instance comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) + [hf : Flat f] [hg : Flat g] : Flat (f ≫ g) := + MorphismProperty.comp_mem _ f g hf hg + +instance : MorphismProperty.IsMultiplicative @Flat where + id_mem _ := inferInstance + +instance isStableUnderBaseChange : MorphismProperty.IsStableUnderBaseChange @Flat := + HasRingHomProperty.isStableUnderBaseChange RingHom.Flat.isStableUnderBaseChange + +lemma of_stalkMap (H : ∀ x, (f.stalkMap x).hom.Flat) : Flat f := + HasRingHomProperty.of_stalkMap RingHom.Flat.ofLocalizationPrime H + +lemma stalkMap [Flat f] (x : X) : (f.stalkMap x).hom.Flat := + HasRingHomProperty.stalkMap (P := @Flat) + (fun f hf J hJ ↦ hf.localRingHom J (J.comap f) rfl) ‹_› x + +lemma iff_flat_stalkMap : Flat f ↔ ∀ x, (f.stalkMap x).hom.Flat := + ⟨fun _ ↦ stalkMap f, fun H ↦ of_stalkMap f H⟩ + +end Flat + +end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index 6ab69b8308733..9f07373d33dce 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -537,7 +537,8 @@ private lemma respects_isOpenImmersion_aux let f' : (V s).toScheme ⟶ U.ι ⁻¹ᵁ s := f ∣_ U.ι ⁻¹ᵁ s have hf' : P f' := IsLocalAtTarget.restrict hf _ let e : (U.ι ⁻¹ᵁ s).toScheme ≅ s := IsOpenImmersion.isoOfRangeEq ((U.ι ⁻¹ᵁ s).ι ≫ U.ι) s.1.ι - (by simpa [Set.range_comp, Set.image_preimage_eq_iff, heq] using le_sSup s.2) + (by simpa only [Scheme.comp_coeBase, TopCat.coe_comp, Set.range_comp, Scheme.Opens.range_ι, + Opens.map_coe, Set.image_preimage_eq_iff, heq, Opens.coe_sSup] using le_sSup s.2) have heq : (V s).ι ≫ f ≫ U.ι = f' ≫ e.hom ≫ s.1.ι := by simp only [V, IsOpenImmersion.isoOfRangeEq_hom_fac, f', e, morphismRestrict_ι_assoc] rw [heq, ← Category.assoc] @@ -640,6 +641,69 @@ lemma locally_of_iff (hQl : LocalizationAwayPreserves Q) ext X Y f rw [h, iff_exists_appLE_locally (P := affineLocally (Locally Q)) hQa.left hQa.respectsIso] +/-- If `Q` is a property of ring maps that can be checked on prime ideals, the +associated property of scheme morphisms can be checked on stalks. -/ +lemma of_stalkMap (hQ : OfLocalizationPrime Q) (H : ∀ x, Q (f.stalkMap x).hom) : P f := by + have hQi := (HasRingHomProperty.isLocal_ringHomProperty P).respectsIso + wlog hY : IsAffine Y generalizing X Y f + · rw [IsLocalAtTarget.iff_of_iSup_eq_top (P := P) _ (iSup_affineOpens_eq_top _)] + intro U + refine this (fun x ↦ ?_) U.2 + exact (hQi.arrow_mk_iso_iff (AlgebraicGeometry.morphismRestrictStalkMap f U x)).mpr (H x.val) + wlog hX : IsAffine X generalizing X f + · rw [IsLocalAtSource.iff_of_iSup_eq_top (P := P) _ (iSup_affineOpens_eq_top _)] + intro U + refine this ?_ U.2 + intro x + rw [Scheme.stalkMap_comp, CommRingCat.hom_comp, hQi.cancel_right_isIso] + exact H x.val + wlog hXY : ∃ R S, Y = Spec R ∧ X = Spec S generalizing X Y + · rw [← P.cancel_right_of_respectsIso (g := Y.isoSpec.hom)] + rw [← P.cancel_left_of_respectsIso (f := X.isoSpec.inv)] + refine this inferInstance (fun x ↦ ?_) inferInstance ?_ + · rw [Scheme.stalkMap_comp, Scheme.stalkMap_comp, CommRingCat.hom_comp, + hQi.cancel_right_isIso, CommRingCat.hom_comp, hQi.cancel_left_isIso] + apply H + · use Γ(Y, ⊤), Γ(X, ⊤) + obtain ⟨R, S, rfl, rfl⟩ := hXY + obtain ⟨φ, rfl⟩ := Spec.map_surjective f + rw [Spec_iff (P := P)] + apply hQ + intro P hP + specialize H ⟨P, hP⟩ + rwa [hQi.arrow_mk_iso_iff (Scheme.arrowStalkMapSpecIso φ _)] at H + +/-- Let `Q` be a property of ring maps that is stable under localization. +Then if the associated property of scheme morphisms holds for `f`, `Q` holds on all stalks. -/ +lemma stalkMap + (hQ : ∀ {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) (_ : Q f) + (J : Ideal S) (_ : J.IsPrime), Q (Localization.localRingHom _ J f rfl)) + (hf : P f) (x : X) : Q (f.stalkMap x).hom := by + have hQi := (HasRingHomProperty.isLocal_ringHomProperty P).respectsIso + wlog h : IsAffine X ∧ IsAffine Y generalizing X Y f + · obtain ⟨U, hU, hfx, _⟩ := Opens.isBasis_iff_nbhd.mp (isBasis_affine_open Y) + (Opens.mem_top <| f.base x) + obtain ⟨V, hV, hx, e⟩ := Opens.isBasis_iff_nbhd.mp (isBasis_affine_open X) + (show x ∈ f ⁻¹ᵁ U from hfx) + rw [← hQi.arrow_mk_iso_iff (Scheme.Hom.resLEStalkMap f e ⟨x, hx⟩)] + exact this (IsLocalAtSource.resLE _ hf) _ ⟨hV, hU⟩ + obtain ⟨hX, hY⟩ := h + wlog hXY : ∃ R S, Y = Spec R ∧ X = Spec S generalizing X Y + · have : Q ((X.isoSpec.inv ≫ f ≫ Y.isoSpec.hom).stalkMap (X.isoSpec.hom.base x)).hom := by + refine this ?_ (X.isoSpec.hom.base x) inferInstance inferInstance ?_ + · rwa [P.cancel_left_of_respectsIso, P.cancel_right_of_respectsIso] + · use Γ(Y, ⊤), Γ(X, ⊤) + rw [Scheme.stalkMap_comp, Scheme.stalkMap_comp, CommRingCat.hom_comp, + hQi.cancel_right_isIso, CommRingCat.hom_comp, hQi.cancel_left_isIso] at this + have heq : (X.isoSpec.inv.base (X.isoSpec.hom.base x)) = x := by simp + rwa [hQi.arrow_mk_iso_iff + (Scheme.arrowStalkMapIsoOfEq f heq)] at this + obtain ⟨R, S, rfl, rfl⟩ := hXY + obtain ⟨φ, rfl⟩ := Spec.map_surjective f + rw [hQi.arrow_mk_iso_iff (Scheme.arrowStalkMapSpecIso φ _)] + rw [Spec_iff (P := P)] at hf + apply hQ _ hf + end HasRingHomProperty end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Restrict.lean b/Mathlib/AlgebraicGeometry/Restrict.lean index a0e2ce9e24ee9..1ce2fe0fcee26 100644 --- a/Mathlib/AlgebraicGeometry/Restrict.lean +++ b/Mathlib/AlgebraicGeometry/Restrict.lean @@ -47,9 +47,11 @@ def toScheme {X : Scheme.{u}} (U : X.Opens) : Scheme.{u} := instance : CoeOut X.Opens Scheme := ⟨toScheme⟩ /-- The restriction of a scheme to an open subset. -/ -@[simps! base_apply] def ι : ↑U ⟶ X := X.ofRestrict _ +@[simp] +lemma ι_base_apply (x : U) : U.ι.base x = x.val := rfl + instance : IsOpenImmersion U.ι := inferInstanceAs (IsOpenImmersion (X.ofRestrict _)) @[simps! over] instance : U.toScheme.CanonicallyOver X where @@ -147,6 +149,16 @@ lemma germ_stalkIso_inv {X : Scheme.{u}} (U : X.Opens) (V : U.toScheme.Opens) (x (U.stalkIso x).inv = U.toScheme.presheaf.germ V x hx := PresheafedSpace.restrictStalkIso_inv_eq_germ X.toPresheafedSpace U.isOpenEmbedding V x hx +lemma stalkIso_inv {X : Scheme.{u}} (U : X.Opens) (x : U) : + (U.stalkIso x).inv = U.ι.stalkMap x := by + rw [← Category.comp_id (U.stalkIso x).inv, Iso.inv_comp_eq] + apply TopCat.Presheaf.stalk_hom_ext + intro W hxW + simp only [Category.comp_id, U.germ_stalkIso_hom_assoc] + convert (Scheme.stalkMap_germ U.ι (U.ι ''ᵁ W) x ⟨_, hxW, rfl⟩).symm + refine (U.toScheme.presheaf.germ_res (homOfLE ?_) _ _).symm + exact (Set.preimage_image_eq _ Subtype.val_injective).le + end Scheme.Opens /-- If `U` is a family of open sets that covers `X`, then `X.restrict U` forms an `X.open_cover`. -/ @@ -302,7 +314,8 @@ noncomputable def Scheme.restrictRestrictComm (X : Scheme.{u}) (U V : X.Opens) : (U.ι ⁻¹ᵁ V).toScheme ≅ V.ι ⁻¹ᵁ U := IsOpenImmersion.isoOfRangeEq (Opens.ι _ ≫ U.ι) (Opens.ι _ ≫ V.ι) <| by - simp [Set.image_preimage_eq_inter_range, Set.inter_comm (U : Set X), Set.range_comp] + simp only [comp_coeBase, TopCat.coe_comp, Set.range_comp, Opens.range_ι, Opens.map_coe, + Set.image_preimage_eq_inter_range, Set.inter_comm (U : Set X)] /-- If `f : X ⟶ Y` is an open immersion, then for any `U : X.Opens`, we have the isomorphism `U ≅ f ''ᵁ U`. -/ @@ -694,6 +707,21 @@ lemma resLE_appLE {U : Y.Opens} {V : X.Opens} (e : V ≤ f ⁻¹ᵁ U) rw [← X.presheaf.map_comp, ← X.presheaf.map_comp] rfl +@[simp] +lemma coe_resLE_base (x : V) : ((f.resLE U V e).base x).val = f.base x := by + simp [resLE, morphismRestrict_base] + +/-- The stalk map of `f.resLE U V` at `x : V` is is the stalk map of `f` at `x`. -/ +def resLEStalkMap (x : V) : + Arrow.mk ((f.resLE U V e).stalkMap x) ≅ Arrow.mk (f.stalkMap x) := + Arrow.isoMk (U.stalkIso _ ≪≫ + (Y.presheaf.stalkCongr <| Inseparable.of_eq <| by simp)) (V.stalkIso x) <| by + dsimp + rw [Category.assoc, ← Iso.eq_inv_comp, ← Category.assoc, ← Iso.comp_inv_eq, + Opens.stalkIso_inv, Opens.stalkIso_inv, ← stalkMap_comp, + stalkMap_congr_hom _ _ (resLE_comp_ι f e), stalkMap_comp] + simp + end Scheme.Hom /-- `f.resLE U V` induces `f.appLE U V` on global sections. -/ diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index 8b4bf90918159..d0f1ae12a2b67 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -760,6 +760,15 @@ lemma stalkMap_germ_apply (U : Y.Opens) (x : X) (hx : f.base x ∈ U) (y) : X.presheaf.germ (f ⁻¹ᵁ U) x hx (f.app U y) := PresheafedSpace.stalkMap_germ_apply f.toPshHom U x hx y +/-- If `x = y`, the stalk maps are isomorphic. -/ +noncomputable def arrowStalkMapIsoOfEq {x y : X} + (h : x = y) : Arrow.mk (f.stalkMap x) ≅ Arrow.mk (f.stalkMap y) := + Arrow.isoMk (Y.presheaf.stalkCongr <| (Inseparable.of_eq h).map f.continuous) + (X.presheaf.stalkCongr <| Inseparable.of_eq h) <| by + simp only [Arrow.mk_left, Arrow.mk_right, Functor.id_obj, TopCat.Presheaf.stalkCongr_hom, + Arrow.mk_hom] + rw [Scheme.stalkSpecializes_stalkMap] + end Scheme end Stalks diff --git a/Mathlib/RingTheory/RingHom/Flat.lean b/Mathlib/RingTheory/RingHom/Flat.lean index feb7b74a492ff..5db5c6b9a9d1f 100644 --- a/Mathlib/RingTheory/RingHom/Flat.lean +++ b/Mathlib/RingTheory/RingHom/Flat.lean @@ -88,4 +88,28 @@ lemma propertyIsLocal : PropertyIsLocal Flat where (stableUnderComposition.stableUnderCompositionWithLocalizationAway holdsForLocalizationAway).right +lemma ofLocalizationPrime : OfLocalizationPrime Flat := by + introv R h + algebraize_only [f] + rw [RingHom.Flat] + apply Module.flat_of_isLocalized_maximal S S (fun P ↦ Localization.AtPrime P) + (fun P ↦ Algebra.linearMap S _) + intro P _ + algebraize_only [Localization.localRingHom (Ideal.comap f P) P f rfl] + have : IsScalarTower R (Localization.AtPrime (Ideal.comap f P)) (Localization.AtPrime P) := + .of_algebraMap_eq fun x ↦ (Localization.localRingHom_to_map _ _ _ rfl x).symm + replace h : Module.Flat (Localization.AtPrime (Ideal.comap f P)) (Localization.AtPrime P) := h .. + exact Module.Flat.trans R (Localization.AtPrime <| Ideal.comap f P) (Localization.AtPrime P) + +lemma localRingHom {f : R →+* S} (hf : f.Flat) + (P : Ideal S) [P.IsPrime] (Q : Ideal R) [Q.IsPrime] (hQP : Q = Ideal.comap f P) : + (Localization.localRingHom Q P f hQP).Flat := by + subst hQP + algebraize [f, Localization.localRingHom (Ideal.comap f P) P f rfl] + have : IsScalarTower R (Localization.AtPrime (Ideal.comap f P)) (Localization.AtPrime P) := + .of_algebraMap_eq fun x ↦ (Localization.localRingHom_to_map _ _ _ rfl x).symm + rw [RingHom.Flat, Module.flat_iff_of_isLocalization + (S := (Localization.AtPrime (Ideal.comap f P))) (p := (Ideal.comap f P).primeCompl)] + exact Module.Flat.trans R S (Localization.AtPrime P) + end RingHom.Flat diff --git a/Mathlib/RingTheory/RingHomProperties.lean b/Mathlib/RingTheory/RingHomProperties.lean index 3f6caf02c496d..c2ac311deb389 100644 --- a/Mathlib/RingTheory/RingHomProperties.lean +++ b/Mathlib/RingTheory/RingHomProperties.lean @@ -191,6 +191,16 @@ lemma toMorphismProperty_respectsIso_iff : exact MorphismProperty.RespectsIso.precomp (toMorphismProperty P) e.toCommRingCatIso.hom (CommRingCat.ofHom f) +/-- Variant of `MorphismProperty.arrow_mk_iso_iff` specialized to morphism properties in +`CommRingCat` given by ring hom properties. -/ +lemma RespectsIso.arrow_mk_iso_iff (hQ : RingHom.RespectsIso P) {A B A' B' : CommRingCat} + {f : A ⟶ B} {g : A' ⟶ B'} (e : Arrow.mk f ≅ Arrow.mk g) : + P f.hom ↔ P g.hom := by + have : (toMorphismProperty P).RespectsIso := by + rwa [← toMorphismProperty_respectsIso_iff] + change toMorphismProperty P _ ↔ toMorphismProperty P _ + rw [MorphismProperty.arrow_mk_iso_iff (toMorphismProperty P) e] + end ToMorphismProperty end RingHom From b10900e7459f021fb4b96f850210c68649dcfd67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 18 Jan 2025 21:34:46 +0000 Subject: [PATCH 300/681] chore(Associated): split out `Ring` results (#20737) --- Archive/Imo/Imo2001Q6.lean | 2 +- Mathlib.lean | 5 +++-- Mathlib/Algebra/BigOperators/Associated.lean | 2 +- Mathlib/Algebra/GCDMonoid/Basic.lean | 2 +- .../Associated.lean} | 20 +---------------- .../GroupWithZero/NonZeroDivisors.lean | 2 +- Mathlib/Algebra/IsPrimePow.lean | 1 - .../Monoid/Associated.lean} | 2 +- Mathlib/Algebra/Polynomial/Monic.lean | 1 - Mathlib/Algebra/Ring/Associated.lean | 22 +++++++++++++++++++ Mathlib/Data/Int/Associated.lean | 2 +- Mathlib/Data/List/Prime.lean | 2 +- Mathlib/Data/Nat/Prime/Basic.lean | 2 +- Mathlib/NumberTheory/Zsqrtd/Basic.lean | 2 +- Mathlib/RingTheory/Ideal/Basic.lean | 3 +-- Mathlib/RingTheory/Ideal/Span.lean | 2 +- Mathlib/RingTheory/Multiplicity.lean | 2 +- Mathlib/RingTheory/Nilpotent/Basic.lean | 1 - .../UniqueFactorizationDomain/Defs.lean | 2 +- MathlibTest/propose.lean | 2 +- 20 files changed, 40 insertions(+), 39 deletions(-) rename Mathlib/Algebra/{Associated/Basic.lean => GroupWithZero/Associated.lean} (97%) rename Mathlib/Algebra/{Associated/OrderedCommMonoid.lean => Order/Monoid/Associated.lean} (96%) create mode 100644 Mathlib/Algebra/Ring/Associated.lean diff --git a/Archive/Imo/Imo2001Q6.lean b/Archive/Imo/Imo2001Q6.lean index e31fc4fe2cd2f..3bc100f8abcea 100644 --- a/Archive/Imo/Imo2001Q6.lean +++ b/Archive/Imo/Imo2001Q6.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Sara Díaz Real. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sara Díaz Real -/ -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.Ring.Associated import Mathlib.Tactic.Linarith import Mathlib.Tactic.LinearCombination diff --git a/Mathlib.lean b/Mathlib.lean index 9c21378b22550..1d76efa276986 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -35,8 +35,6 @@ import Mathlib.Algebra.Algebra.Tower import Mathlib.Algebra.Algebra.Unitization import Mathlib.Algebra.Algebra.ZMod import Mathlib.Algebra.AlgebraicCard -import Mathlib.Algebra.Associated.Basic -import Mathlib.Algebra.Associated.OrderedCommMonoid import Mathlib.Algebra.BigOperators.Associated import Mathlib.Algebra.BigOperators.Balance import Mathlib.Algebra.BigOperators.Expect @@ -382,6 +380,7 @@ import Mathlib.Algebra.GroupWithZero.Action.Opposite import Mathlib.Algebra.GroupWithZero.Action.Pi import Mathlib.Algebra.GroupWithZero.Action.Prod import Mathlib.Algebra.GroupWithZero.Action.Units +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Algebra.GroupWithZero.Basic import Mathlib.Algebra.GroupWithZero.Center import Mathlib.Algebra.GroupWithZero.Commute @@ -747,6 +746,7 @@ import Mathlib.Algebra.Order.Module.OrderedSMul import Mathlib.Algebra.Order.Module.Pointwise import Mathlib.Algebra.Order.Module.Rat import Mathlib.Algebra.Order.Module.Synonym +import Mathlib.Algebra.Order.Monoid.Associated import Mathlib.Algebra.Order.Monoid.Basic import Mathlib.Algebra.Order.Monoid.Canonical.Basic import Mathlib.Algebra.Order.Monoid.Canonical.Defs @@ -895,6 +895,7 @@ import Mathlib.Algebra.Ring.Action.Group import Mathlib.Algebra.Ring.Action.Invariant import Mathlib.Algebra.Ring.Action.Subobjects import Mathlib.Algebra.Ring.AddAut +import Mathlib.Algebra.Ring.Associated import Mathlib.Algebra.Ring.Aut import Mathlib.Algebra.Ring.Basic import Mathlib.Algebra.Ring.BooleanRing diff --git a/Mathlib/Algebra/BigOperators/Associated.lean b/Mathlib/Algebra/BigOperators/Associated.lean index e9978f3214640..f6754712f5eea 100644 --- a/Mathlib/Algebra/BigOperators/Associated.lean +++ b/Mathlib/Algebra/BigOperators/Associated.lean @@ -3,9 +3,9 @@ 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, Jens Wagemaker, Anne Baanen -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.Group.Submonoid.Membership +import Mathlib.Algebra.GroupWithZero.Associated /-! # Products of associated, prime, and irreducible elements. diff --git a/Mathlib/Algebra/GCDMonoid/Basic.lean b/Mathlib/Algebra/GCDMonoid/Basic.lean index 7fcc8bb52f7cd..038d8736dedfe 100644 --- a/Mathlib/Algebra/GCDMonoid/Basic.lean +++ b/Mathlib/Algebra/GCDMonoid/Basic.lean @@ -3,7 +3,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, Jens Wagemaker -/ -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.Ring.Associated import Mathlib.Algebra.Ring.Regular /-! diff --git a/Mathlib/Algebra/Associated/Basic.lean b/Mathlib/Algebra/GroupWithZero/Associated.lean similarity index 97% rename from Mathlib/Algebra/Associated/Basic.lean rename to Mathlib/Algebra/GroupWithZero/Associated.lean index 5e6399d91ab42..f26266a8ec15e 100644 --- a/Mathlib/Algebra/Associated/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Associated.lean @@ -3,12 +3,6 @@ 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, Jens Wagemaker -/ -import Mathlib.Algebra.Group.Even -import Mathlib.Algebra.GroupWithZero.Divisibility -import Mathlib.Algebra.GroupWithZero.Hom -import Mathlib.Algebra.Group.Commute.Units -import Mathlib.Algebra.Group.Units.Equiv -import Mathlib.Algebra.Ring.Units import Mathlib.Algebra.Prime.Lemmas import Mathlib.Order.BoundedOrder.Basic @@ -21,7 +15,7 @@ Then we show that the quotient type `Associates` is a monoid and prove basic properties of this quotient. -/ -assert_not_exists OrderedCommMonoid Multiset +assert_not_exists OrderedCommMonoid Multiset Ring variable {M : Type*} @@ -218,18 +212,6 @@ theorem Associated.eq_zero_iff [MonoidWithZero M] {a b : M} (h : a ~ᵤ b) : a = theorem Associated.ne_zero_iff [MonoidWithZero M] {a b : M} (h : a ~ᵤ b) : a ≠ 0 ↔ b ≠ 0 := not_congr h.eq_zero_iff -theorem Associated.neg_left [Monoid M] [HasDistribNeg M] {a b : M} (h : Associated a b) : - Associated (-a) b := - let ⟨u, hu⟩ := h; ⟨-u, by simp [hu]⟩ - -theorem Associated.neg_right [Monoid M] [HasDistribNeg M] {a b : M} (h : Associated a b) : - Associated a (-b) := - h.symm.neg_left.symm - -theorem Associated.neg_neg [Monoid M] [HasDistribNeg M] {a b : M} (h : Associated a b) : - Associated (-a) (-b) := - h.neg_left.neg_right - protected theorem Associated.prime [CommMonoidWithZero M] {p q : M} (h : p ~ᵤ q) (hp : Prime p) : Prime q := ⟨h.ne_zero_iff.1 hp.ne_zero, diff --git a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean index 1cae6fca2dc4b..66ad8bce61f90 100644 --- a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean +++ b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean @@ -3,9 +3,9 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Devon Tuma, Oliver Nash -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.Group.Action.Opposite import Mathlib.Algebra.Group.Submonoid.Membership +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Algebra.GroupWithZero.Opposite /-! diff --git a/Mathlib/Algebra/IsPrimePow.lean b/Mathlib/Algebra/IsPrimePow.lean index b39849544065e..041a9d6c70bae 100644 --- a/Mathlib/Algebra/IsPrimePow.lean +++ b/Mathlib/Algebra/IsPrimePow.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.Order.Ring.Nat import Mathlib.Order.Nat import Mathlib.Data.Nat.Prime.Basic diff --git a/Mathlib/Algebra/Associated/OrderedCommMonoid.lean b/Mathlib/Algebra/Order/Monoid/Associated.lean similarity index 96% rename from Mathlib/Algebra/Associated/OrderedCommMonoid.lean rename to Mathlib/Algebra/Order/Monoid/Associated.lean index ba84dc929f4ea..36f80f3463e35 100644 --- a/Mathlib/Algebra/Associated/OrderedCommMonoid.lean +++ b/Mathlib/Algebra/Order/Monoid/Associated.lean @@ -3,7 +3,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, Jens Wagemaker -/ -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Algebra.Order.Monoid.Canonical.Defs /-! diff --git a/Mathlib/Algebra/Polynomial/Monic.lean b/Mathlib/Algebra/Polynomial/Monic.lean index f78aa81f906ba..034253114fea3 100644 --- a/Mathlib/Algebra/Polynomial/Monic.lean +++ b/Mathlib/Algebra/Polynomial/Monic.lean @@ -3,7 +3,6 @@ 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, Kim Morrison, Jens Wagemaker -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.Polynomial.Reverse import Mathlib.Algebra.Regular.SMul diff --git a/Mathlib/Algebra/Ring/Associated.lean b/Mathlib/Algebra/Ring/Associated.lean new file mode 100644 index 0000000000000..ae6b9f1c1a3bd --- /dev/null +++ b/Mathlib/Algebra/Ring/Associated.lean @@ -0,0 +1,22 @@ +/- +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, Jens Wagemaker +-/ +import Mathlib.Algebra.GroupWithZero.Associated +import Mathlib.Algebra.Ring.Units + +/-! +# Associated elements in rings +-/ + +assert_not_exists OrderedCommMonoid Multiset Field + +namespace Associated +variable {M : Type*} [Monoid M] [HasDistribNeg M] {a b : M} + +lemma neg_left (h : Associated a b) : Associated (-a) b := let ⟨u, hu⟩ := h; ⟨-u, by simp [hu]⟩ +lemma neg_right (h : Associated a b) : Associated a (-b) := h.symm.neg_left.symm +lemma neg_neg (h : Associated a b) : Associated (-a) (-b) := h.neg_left.neg_right + +end Associated diff --git a/Mathlib/Data/Int/Associated.lean b/Mathlib/Data/Int/Associated.lean index eea6f2550b9bb..237da2b63c7cf 100644 --- a/Mathlib/Data/Int/Associated.lean +++ b/Mathlib/Data/Int/Associated.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Anne Baanen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Algebra.Ring.Int.Units /-! # Associated elements and the integers diff --git a/Mathlib/Data/List/Prime.lean b/Mathlib/Data/List/Prime.lean index 4a6ec72427cc8..e7eaecf8d148d 100644 --- a/Mathlib/Data/List/Prime.lean +++ b/Mathlib/Data/List/Prime.lean @@ -3,8 +3,8 @@ 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, Jens Wagemaker, Anne Baanen -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.BigOperators.Group.List.Lemmas +import Mathlib.Algebra.GroupWithZero.Associated /-! # Products of lists of prime elements. diff --git a/Mathlib/Data/Nat/Prime/Basic.lean b/Mathlib/Data/Nat/Prime/Basic.lean index 8cb621b8201d1..4d61cc2acf3cd 100644 --- a/Mathlib/Data/Nat/Prime/Basic.lean +++ b/Mathlib/Data/Nat/Prime/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Algebra.Ring.Parity import Mathlib.Data.Nat.Prime.Defs diff --git a/Mathlib/NumberTheory/Zsqrtd/Basic.lean b/Mathlib/NumberTheory/Zsqrtd/Basic.lean index 5165598a7e5fe..1babdaa7537b8 100644 --- a/Mathlib/NumberTheory/Zsqrtd/Basic.lean +++ b/Mathlib/NumberTheory/Zsqrtd/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.Ring.Associated import Mathlib.Algebra.Star.Unitary import Mathlib.RingTheory.Int.Basic import Mathlib.RingTheory.PrincipalIdealDomain diff --git a/Mathlib/RingTheory/Ideal/Basic.lean b/Mathlib/RingTheory/Ideal/Basic.lean index b2409062e4537..864e9f84072c4 100644 --- a/Mathlib/RingTheory/Ideal/Basic.lean +++ b/Mathlib/RingTheory/Ideal/Basic.lean @@ -3,12 +3,11 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Chris Hughes, Mario Carneiro -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.Field.IsField import Mathlib.Data.Nat.Choose.Sum +import Mathlib.LinearAlgebra.Finsupp.LinearCombination import Mathlib.RingTheory.Ideal.Maximal import Mathlib.Tactic.FinCases -import Mathlib.LinearAlgebra.Finsupp.LinearCombination /-! diff --git a/Mathlib/RingTheory/Ideal/Span.lean b/Mathlib/RingTheory/Ideal/Span.lean index 99edde40b397d..259ced022f25c 100644 --- a/Mathlib/RingTheory/Ideal/Span.lean +++ b/Mathlib/RingTheory/Ideal/Span.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Chris Hughes, Mario Carneiro -/ -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Algebra.Ring.Idempotent import Mathlib.Algebra.Ring.Regular import Mathlib.LinearAlgebra.Span.Basic diff --git a/Mathlib/RingTheory/Multiplicity.lean b/Mathlib/RingTheory/Multiplicity.lean index 73e3216579502..56b13008a6c47 100644 --- a/Mathlib/RingTheory/Multiplicity.lean +++ b/Mathlib/RingTheory/Multiplicity.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis, Chris Hughes, Daniel Weber -/ import Batteries.Data.Nat.Gcd -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.BigOperators.Group.Finset.Basic +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Data.ENat.Basic diff --git a/Mathlib/RingTheory/Nilpotent/Basic.lean b/Mathlib/RingTheory/Nilpotent/Basic.lean index 602de4bcb8dbd..28cf3c372d7e3 100644 --- a/Mathlib/RingTheory/Nilpotent/Basic.lean +++ b/Mathlib/RingTheory/Nilpotent/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.GeomSum import Mathlib.Algebra.Group.Action.Prod import Mathlib.Algebra.GroupWithZero.NonZeroDivisors diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean index 45d4fd35b00b3..384d930456be9 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain/Defs.lean @@ -3,10 +3,10 @@ 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, Jens Wagemaker, Aaron Anderson -/ -import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.BigOperators.Group.Multiset.Basic import Mathlib.Algebra.Group.Submonoid.Membership import Mathlib.Algebra.Group.Submonoid.BigOperators +import Mathlib.Algebra.GroupWithZero.Associated import Mathlib.Order.WellFounded /-! diff --git a/MathlibTest/propose.lean b/MathlibTest/propose.lean index 9fb6910a4bd4a..e152e10bde73a 100644 --- a/MathlibTest/propose.lean +++ b/MathlibTest/propose.lean @@ -1,6 +1,6 @@ import Mathlib.Tactic.Propose import Mathlib.Tactic.GuardHypNums -import Mathlib.Algebra.Associated.Basic +import Mathlib.Algebra.Ring.Associated import Mathlib.Data.Set.Subsingleton import Batteries.Data.List.Lemmas From bdee03dd2e32e0a077a89013612f859d87ea21b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 18 Jan 2025 22:00:34 +0000 Subject: [PATCH 301/681] chore(Dynamics/PeriodicPts): don't import `MonoidWithZero` (#20765) For this, split the file into `.Defs` and `.Lemmas`. --- Archive/Imo/Imo2006Q5.lean | 2 +- Mathlib.lean | 3 +- .../Defs.lean} | 66 +++------------- Mathlib/Dynamics/PeriodicPts/Lemmas.lean | 75 +++++++++++++++++++ .../GroupTheory/GroupAction/FixedPoints.lean | 4 +- Mathlib/GroupTheory/GroupAction/Period.lean | 2 +- Mathlib/GroupTheory/GroupAction/Quotient.lean | 2 +- Mathlib/GroupTheory/OrderOfElement.lean | 1 + 8 files changed, 93 insertions(+), 62 deletions(-) rename Mathlib/Dynamics/{PeriodicPts.lean => PeriodicPts/Defs.lean} (89%) create mode 100644 Mathlib/Dynamics/PeriodicPts/Lemmas.lean diff --git a/Archive/Imo/Imo2006Q5.lean b/Archive/Imo/Imo2006Q5.lean index d317993a8c618..c35023a225451 100644 --- a/Archive/Imo/Imo2006Q5.lean +++ b/Archive/Imo/Imo2006Q5.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Violeta Hernández Palacios -/ import Mathlib.Algebra.Polynomial.Roots -import Mathlib.Dynamics.PeriodicPts +import Mathlib.Dynamics.PeriodicPts.Lemmas /-! # IMO 2006 Q5 diff --git a/Mathlib.lean b/Mathlib.lean index 1d76efa276986..a42fe7ba77e51 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3071,7 +3071,8 @@ import Mathlib.Dynamics.Flow import Mathlib.Dynamics.Minimal import Mathlib.Dynamics.Newton import Mathlib.Dynamics.OmegaLimit -import Mathlib.Dynamics.PeriodicPts +import Mathlib.Dynamics.PeriodicPts.Defs +import Mathlib.Dynamics.PeriodicPts.Lemmas import Mathlib.Dynamics.TopologicalEntropy.CoverEntropy import Mathlib.Dynamics.TopologicalEntropy.DynamicalEntourage import Mathlib.Dynamics.TopologicalEntropy.NetEntropy diff --git a/Mathlib/Dynamics/PeriodicPts.lean b/Mathlib/Dynamics/PeriodicPts/Defs.lean similarity index 89% rename from Mathlib/Dynamics/PeriodicPts.lean rename to Mathlib/Dynamics/PeriodicPts/Defs.lean index 28ed4478ac2af..7dcc0f82ad5b8 100644 --- a/Mathlib/Dynamics/PeriodicPts.lean +++ b/Mathlib/Dynamics/PeriodicPts/Defs.lean @@ -3,13 +3,11 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Algebra.GroupPower.IterateHom -import Mathlib.Algebra.Ring.Divisibility.Basic -import Mathlib.Algebra.Ring.Int.Defs +import Batteries.Data.Nat.Gcd +import Mathlib.Algebra.Order.Group.Nat +import Mathlib.Algebra.Order.Sub.Basic import Mathlib.Data.List.Cycle -import Mathlib.Data.Nat.GCD.Basic -import Mathlib.Data.Nat.Prime.Basic -import Mathlib.Data.PNat.Basic +import Mathlib.Data.PNat.Notation import Mathlib.Dynamics.FixedPoints.Basic /-! @@ -43,6 +41,8 @@ is a periodic point of `f` of period `n` if and only if `minimalPeriod f x | n`. -/ +assert_not_exists MonoidWithZero + open Set @@ -164,7 +164,7 @@ theorem eq_of_apply_eq_same (hx : IsPeriodicPt f n x) (hy : IsPeriodicPt f n y) then `x = y`. -/ theorem eq_of_apply_eq (hx : IsPeriodicPt f m x) (hy : IsPeriodicPt f n y) (hm : 0 < m) (hn : 0 < n) (h : f x = f y) : x = y := - (hx.mul_const n).eq_of_apply_eq_same (hy.const_mul m) (mul_pos hm hn) h + (hx.mul_const n).eq_of_apply_eq_same (hy.const_mul m) (Nat.mul_pos hm hn) h end IsPeriodicPt @@ -187,9 +187,6 @@ theorem bijOn_ptsOfPeriod (f : α → α) {n : ℕ} (hn : 0 < n) : ⟨f^[n.pred] x, hx.apply_iterate _, by rw [← comp_apply (f := f), comp_iterate_pred_of_pos f hn, hx.eq]⟩⟩ -theorem directed_ptsOfPeriod_pNat (f : α → α) : Directed (· ⊆ ·) fun n : ℕ+ => ptsOfPeriod f n := - fun m n => ⟨m * n, fun _ hx => hx.mul_const n, fun _ hx => hx.const_mul m⟩ - /-- The set of periodic points of a map `f : α → α`. -/ def periodicPts (f : α → α) : Set α := { x : α | ∃ n > 0, IsPeriodicPt f n x } @@ -208,7 +205,7 @@ theorem isPeriodicPt_of_mem_periodicPts_of_isPeriodicPt_iterate (hx : x ∈ peri change _ = _ convert (hm.apply_iterate ((n / r + 1) * r - n)).eq <;> rw [← iterate_add_apply, Nat.sub_add_cancel this, iterate_mul, (hr'.iterate _).eq] - rw [add_mul, one_mul] + rw [Nat.add_mul, one_mul] exact (Nat.lt_div_mul_add hr).le variable (f) @@ -219,10 +216,6 @@ theorem bUnion_ptsOfPeriod : ⋃ n > 0, ptsOfPeriod f n = periodicPts f := theorem iUnion_pNat_ptsOfPeriod : ⋃ n : ℕ+, ptsOfPeriod f n = periodicPts f := iSup_subtype.trans <| bUnion_ptsOfPeriod f -theorem bijOn_periodicPts : BijOn f (periodicPts f) (periodicPts f) := - iUnion_pNat_ptsOfPeriod f ▸ - bijOn_iUnion_of_directed (directed_ptsOfPeriod_pNat f) fun i => bijOn_ptsOfPeriod f i.pos - variable {f} theorem Semiconj.mapsTo_periodicPts {g : α → β} (h : Semiconj g fa fb) : @@ -339,7 +332,7 @@ theorem not_isPeriodicPt_of_pos_of_lt_minimalPeriod : | _ + 1, _, hn => fun hp => Nat.succ_ne_zero _ (hp.eq_zero_of_lt_minimalPeriod hn) theorem IsPeriodicPt.minimalPeriod_dvd (hx : IsPeriodicPt f n x) : minimalPeriod f x ∣ n := - (eq_or_lt_of_le <| n.zero_le).elim (fun hn0 => hn0 ▸ dvd_zero _) fun hn0 => + (eq_or_lt_of_le <| n.zero_le).elim (fun hn0 => hn0 ▸ Nat.dvd_zero _) fun hn0 => -- Porting note: `Nat.dvd_iff_mod_eq_zero` gained explicit arguments Nat.dvd_iff_mod_eq_zero.2 <| (hx.mod <| isPeriodicPt_minimalPeriod f x).eq_zero_of_lt_minimalPeriod <| @@ -354,40 +347,11 @@ theorem minimalPeriod_eq_minimalPeriod_iff {g : β → β} {y : β} : minimalPeriod f x = minimalPeriod g y ↔ ∀ n, IsPeriodicPt f n x ↔ IsPeriodicPt g n y := by simp_rw [isPeriodicPt_iff_minimalPeriod_dvd, dvd_right_iff_eq] -theorem minimalPeriod_eq_prime {p : ℕ} [hp : Fact p.Prime] (hper : IsPeriodicPt f p x) - (hfix : ¬IsFixedPt f x) : minimalPeriod f x = p := - (hp.out.eq_one_or_self_of_dvd _ hper.minimalPeriod_dvd).resolve_left - (mt minimalPeriod_eq_one_iff_isFixedPt.1 hfix) - -theorem minimalPeriod_eq_prime_pow {p k : ℕ} [hp : Fact p.Prime] (hk : ¬IsPeriodicPt f (p ^ k) x) - (hk1 : IsPeriodicPt f (p ^ (k + 1)) x) : minimalPeriod f x = p ^ (k + 1) := by - apply Nat.eq_prime_pow_of_dvd_least_prime_pow hp.out <;> - rwa [← isPeriodicPt_iff_minimalPeriod_dvd] - theorem Commute.minimalPeriod_of_comp_dvd_lcm {g : α → α} (h : Commute f g) : minimalPeriod (f ∘ g) x ∣ Nat.lcm (minimalPeriod f x) (minimalPeriod g x) := by rw [← isPeriodicPt_iff_minimalPeriod_dvd] exact (isPeriodicPt_minimalPeriod f x).comp_lcm h (isPeriodicPt_minimalPeriod g x) -theorem Commute.minimalPeriod_of_comp_dvd_mul {g : α → α} (h : Commute f g) : - minimalPeriod (f ∘ g) x ∣ minimalPeriod f x * minimalPeriod g x := - dvd_trans h.minimalPeriod_of_comp_dvd_lcm (lcm_dvd_mul _ _) - -theorem Commute.minimalPeriod_of_comp_eq_mul_of_coprime {g : α → α} (h : Commute f g) - (hco : Coprime (minimalPeriod f x) (minimalPeriod g x)) : - minimalPeriod (f ∘ g) x = minimalPeriod f x * minimalPeriod g x := by - apply h.minimalPeriod_of_comp_dvd_mul.antisymm - suffices - ∀ {f g : α → α}, - Commute f g → - Coprime (minimalPeriod f x) (minimalPeriod g x) → - minimalPeriod f x ∣ minimalPeriod (f ∘ g) x from - hco.mul_dvd_of_dvd_of_dvd (this h hco) (h.comp_eq.symm ▸ this h.symm hco.symm) - intro f g h hco - refine hco.dvd_of_dvd_mul_left (IsPeriodicPt.left_of_comp h ?_ ?_).minimalPeriod_dvd - · exact (isPeriodicPt_minimalPeriod _ _).const_mul _ - · exact (isPeriodicPt_minimalPeriod _ _).mul_const _ - private theorem minimalPeriod_iterate_eq_div_gcd_aux (h : 0 < gcd (minimalPeriod f x) n) : minimalPeriod f^[n] x = minimalPeriod f x / Nat.gcd (minimalPeriod f x) n := by apply Nat.dvd_antisymm @@ -521,16 +485,6 @@ theorem isPeriodicPt_prod_map (x : α × β) : IsPeriodicPt (Prod.map f g) n x ↔ IsPeriodicPt f n x.1 ∧ IsPeriodicPt g n x.2 := by simp [IsPeriodicPt] -theorem minimalPeriod_prod_map (f : α → α) (g : β → β) (x : α × β) : - minimalPeriod (Prod.map f g) x = (minimalPeriod f x.1).lcm (minimalPeriod g x.2) := - eq_of_forall_dvd <| by cases x; simp [← isPeriodicPt_iff_minimalPeriod_dvd, Nat.lcm_dvd_iff] - -theorem minimalPeriod_fst_dvd : minimalPeriod f x.1 ∣ minimalPeriod (Prod.map f g) x := by - rw [minimalPeriod_prod_map]; exact Nat.dvd_lcm_left _ _ - -theorem minimalPeriod_snd_dvd : minimalPeriod g x.2 ∣ minimalPeriod (Prod.map f g) x := by - rw [minimalPeriod_prod_map]; exact Nat.dvd_lcm_right _ _ - end Function namespace MulAction @@ -584,7 +538,7 @@ theorem zpow_smul_eq_iff_period_dvd {j : ℤ} {g : G} {a : α} : g ^ j • a = a ↔ (period g a : ℤ) ∣ j := by rcases j with n | n · rw [Int.ofNat_eq_coe, zpow_natCast, Int.natCast_dvd_natCast, pow_smul_eq_iff_period_dvd] - · rw [Int.negSucc_coe, zpow_neg, zpow_natCast, inv_smul_eq_iff, eq_comm, dvd_neg, + · rw [Int.negSucc_coe, zpow_neg, zpow_natCast, inv_smul_eq_iff, eq_comm, Int.dvd_neg, Int.natCast_dvd_natCast, pow_smul_eq_iff_period_dvd] @[to_additive (attr := simp)] diff --git a/Mathlib/Dynamics/PeriodicPts/Lemmas.lean b/Mathlib/Dynamics/PeriodicPts/Lemmas.lean new file mode 100644 index 0000000000000..f054709c6a3d4 --- /dev/null +++ b/Mathlib/Dynamics/PeriodicPts/Lemmas.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2020 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Data.Nat.GCD.Basic +import Mathlib.Data.Nat.Prime.Basic +import Mathlib.Data.PNat.Basic +import Mathlib.Dynamics.PeriodicPts.Defs + +/-! +# Extra lemmas about periodic points +-/ + +open Nat Set + +namespace Function +variable {α : Type*} {f : α → α} {x y : α} + +open Function (Commute) + +theorem directed_ptsOfPeriod_pNat (f : α → α) : Directed (· ⊆ ·) fun n : ℕ+ => ptsOfPeriod f n := + fun m n => ⟨m * n, fun _ hx => hx.mul_const n, fun _ hx => hx.const_mul m⟩ + +variable (f) in +theorem bijOn_periodicPts : BijOn f (periodicPts f) (periodicPts f) := + iUnion_pNat_ptsOfPeriod f ▸ + bijOn_iUnion_of_directed (directed_ptsOfPeriod_pNat f) fun i => bijOn_ptsOfPeriod f i.pos + +theorem minimalPeriod_eq_prime {p : ℕ} [hp : Fact p.Prime] (hper : IsPeriodicPt f p x) + (hfix : ¬IsFixedPt f x) : minimalPeriod f x = p := + (hp.out.eq_one_or_self_of_dvd _ hper.minimalPeriod_dvd).resolve_left + (mt minimalPeriod_eq_one_iff_isFixedPt.1 hfix) + +theorem minimalPeriod_eq_prime_pow {p k : ℕ} [hp : Fact p.Prime] (hk : ¬IsPeriodicPt f (p ^ k) x) + (hk1 : IsPeriodicPt f (p ^ (k + 1)) x) : minimalPeriod f x = p ^ (k + 1) := by + apply Nat.eq_prime_pow_of_dvd_least_prime_pow hp.out <;> + rwa [← isPeriodicPt_iff_minimalPeriod_dvd] + +theorem Commute.minimalPeriod_of_comp_dvd_mul {g : α → α} (h : Commute f g) : + minimalPeriod (f ∘ g) x ∣ minimalPeriod f x * minimalPeriod g x := + dvd_trans h.minimalPeriod_of_comp_dvd_lcm (lcm_dvd_mul _ _) + +theorem Commute.minimalPeriod_of_comp_eq_mul_of_coprime {g : α → α} (h : Commute f g) + (hco : Coprime (minimalPeriod f x) (minimalPeriod g x)) : + minimalPeriod (f ∘ g) x = minimalPeriod f x * minimalPeriod g x := by + apply h.minimalPeriod_of_comp_dvd_mul.antisymm + suffices + ∀ {f g : α → α}, + Commute f g → + Coprime (minimalPeriod f x) (minimalPeriod g x) → + minimalPeriod f x ∣ minimalPeriod (f ∘ g) x from + hco.mul_dvd_of_dvd_of_dvd (this h hco) (h.comp_eq.symm ▸ this h.symm hco.symm) + intro f g h hco + refine hco.dvd_of_dvd_mul_left (IsPeriodicPt.left_of_comp h ?_ ?_).minimalPeriod_dvd + · exact (isPeriodicPt_minimalPeriod _ _).const_mul _ + · exact (isPeriodicPt_minimalPeriod _ _).mul_const _ + +end Function + +namespace Function + +variable {α β : Type*} {f : α → α} {g : β → β} {x : α × β} {a : α} {b : β} {m n : ℕ} + +theorem minimalPeriod_prod_map (f : α → α) (g : β → β) (x : α × β) : + minimalPeriod (Prod.map f g) x = (minimalPeriod f x.1).lcm (minimalPeriod g x.2) := + eq_of_forall_dvd <| by cases x; simp [← isPeriodicPt_iff_minimalPeriod_dvd, Nat.lcm_dvd_iff] + +theorem minimalPeriod_fst_dvd : minimalPeriod f x.1 ∣ minimalPeriod (Prod.map f g) x := by + rw [minimalPeriod_prod_map]; exact Nat.dvd_lcm_left _ _ + +theorem minimalPeriod_snd_dvd : minimalPeriod g x.2 ∣ minimalPeriod (Prod.map f g) x := by + rw [minimalPeriod_prod_map]; exact Nat.dvd_lcm_right _ _ + +end Function diff --git a/Mathlib/GroupTheory/GroupAction/FixedPoints.lean b/Mathlib/GroupTheory/GroupAction/FixedPoints.lean index 214c7c2f51a38..ec44881e43a15 100644 --- a/Mathlib/GroupTheory/GroupAction/FixedPoints.lean +++ b/Mathlib/GroupTheory/GroupAction/FixedPoints.lean @@ -5,7 +5,7 @@ Authors: Emilie Burgun -/ import Mathlib.Algebra.Group.Commute.Basic import Mathlib.Data.Set.Pointwise.SMul -import Mathlib.Dynamics.PeriodicPts +import Mathlib.Dynamics.PeriodicPts.Defs import Mathlib.GroupTheory.GroupAction.Defs /-! @@ -83,7 +83,7 @@ theorem fixedBy_subset_fixedBy_zpow (g : G) (j : ℤ) : fixedBy α g ⊆ fixedBy α (g ^ j) := by intro a a_in_fixedBy rw [mem_fixedBy, zpow_smul_eq_iff_minimalPeriod_dvd, - minimalPeriod_eq_one_iff_fixedBy.mpr a_in_fixedBy, Nat.cast_one] + minimalPeriod_eq_one_iff_fixedBy.mpr a_in_fixedBy, Int.natCast_one] exact one_dvd j variable (M α) in diff --git a/Mathlib/GroupTheory/GroupAction/Period.lean b/Mathlib/GroupTheory/GroupAction/Period.lean index 0565b00fd0c9a..f93fd000e9688 100644 --- a/Mathlib/GroupTheory/GroupAction/Period.lean +++ b/Mathlib/GroupTheory/GroupAction/Period.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Emilie Burgun -/ -import Mathlib.Dynamics.PeriodicPts +import Mathlib.Dynamics.PeriodicPts.Lemmas import Mathlib.GroupTheory.Exponent import Mathlib.GroupTheory.GroupAction.Basic diff --git a/Mathlib/GroupTheory/GroupAction/Quotient.lean b/Mathlib/GroupTheory/GroupAction/Quotient.lean index c3fa3d099fb3d..f5e30c0a93fdf 100644 --- a/Mathlib/GroupTheory/GroupAction/Quotient.lean +++ b/Mathlib/GroupTheory/GroupAction/Quotient.lean @@ -6,7 +6,7 @@ Authors: Chris Hughes, Thomas Browning import Mathlib.Algebra.Group.Subgroup.Actions import Mathlib.Algebra.Group.Subgroup.ZPowers.Lemmas import Mathlib.Data.Fintype.BigOperators -import Mathlib.Dynamics.PeriodicPts +import Mathlib.Dynamics.PeriodicPts.Defs import Mathlib.GroupTheory.Commutator.Basic import Mathlib.GroupTheory.Coset.Basic import Mathlib.GroupTheory.GroupAction.Basic diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index 514fd7841f060..c89a47cd28aa4 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.Group.Subgroup.Finite import Mathlib.Algebra.Module.NatInt import Mathlib.Algebra.Order.Group.Action import Mathlib.Algebra.Order.Ring.Abs +import Mathlib.Dynamics.PeriodicPts.Lemmas import Mathlib.GroupTheory.Index import Mathlib.Order.Interval.Set.Infinite import Mathlib.Tactic.Positivity From 9b6fa8d7df3e565b081a2fea01571b9c1546bdf7 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Sun, 19 Jan 2025 08:58:10 +0000 Subject: [PATCH 302/681] feat: in one dimension, a point is either isolated or a point of unique differentiability (#20827) A point in a subset of a field is either a point of unique differentials, or isolated. In both cases, there is a definite value for the derivative of a map (its unique derivative in the former case, zero in the latter case). This means there is no choice involved, contrary to what happens in higher dimension. This remark means we can remove many `UniqueDiffWithinAt` assumptions in one-dimensional settings. This PR proves the new lemma that a point is either isolated or a point of unique differentiability. The application to cleanup the library will be in a further PR (#20816) --- Mathlib/Analysis/Calculus/TangentCone.lean | 141 +++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/Mathlib/Analysis/Calculus/TangentCone.lean b/Mathlib/Analysis/Calculus/TangentCone.lean index c818f6cfc6e58..68f5491fa0644 100644 --- a/Mathlib/Analysis/Calculus/TangentCone.lean +++ b/Mathlib/Analysis/Calculus/TangentCone.lean @@ -5,6 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.Convex.Topology import Mathlib.Analysis.Normed.Module.Basic +import Mathlib.Analysis.Seminorm import Mathlib.Analysis.SpecificLimits.Basic /-! @@ -207,6 +208,135 @@ theorem mem_tangentCone_of_segment_subset {s : Set G} {x y : G} (h : segment ℝ y - x ∈ tangentConeAt ℝ s x := mem_tangentCone_of_openSegment_subset ((openSegment_subset_segment ℝ x y).trans h) +/-- The tangent cone at a non-isolated point contains `0`. -/ +theorem zero_mem_tangentCone {s : Set E} {x : E} (hx : (𝓝[s \ {x}] x).NeBot) : + 0 ∈ tangentConeAt 𝕜 s x := by + /- Take a sequence `d n` tending to `0` such that `x + d n ∈ s`. Taking `c n` of the order + of `1 / (d n) ^ (1/2)`, then `c n` tends to infinity, but `c n • d n` tends to `0`. By definition, + this shows that `0` belongs to the tangent cone. -/ + obtain ⟨u, -, u_pos, u_lim⟩ : + ∃ u, StrictAnti u ∧ (∀ (n : ℕ), 0 < u n) ∧ Tendsto u atTop (𝓝 (0 : ℝ)) := + exists_seq_strictAnti_tendsto (0 : ℝ) + have A n : ((s \ {x}) ∩ Metric.ball x (u n * u n)).Nonempty := + NeBot.nonempty_of_mem hx (inter_mem_nhdsWithin _ + (Metric.ball_mem_nhds _ (mul_pos (u_pos n) (u_pos n)))) + choose v hv using A + let d n := v n - x + have M n : x + d n ∈ s \ {x} := by simpa [d] using (hv n).1 + let ⟨r, hr⟩ := exists_one_lt_norm 𝕜 + have W n := rescale_to_shell hr (u_pos n) (x := d n) (by simpa using (M n).2) + choose c c_ne c_le le_c hc using W + have c_lim : Tendsto (fun n ↦ ‖c n‖) atTop atTop := by + suffices Tendsto (fun n ↦ ‖c n‖⁻¹ ⁻¹) atTop atTop by simpa + apply tendsto_inv_nhdsGT_zero.comp + simp only [nhdsWithin, tendsto_inf, tendsto_principal, mem_Ioi, norm_pos_iff, ne_eq, + eventually_atTop, ge_iff_le] + have B (n : ℕ) : ‖c n‖⁻¹ ≤ ‖r‖ * u n := calc + ‖c n‖⁻¹ + _ ≤ (u n)⁻¹ * ‖r‖ * ‖d n‖ := hc n + _ ≤ (u n)⁻¹ * ‖r‖ * (u n * u n) := by + gcongr + · exact mul_nonneg (by simp [(u_pos n).le]) (norm_nonneg _) + · specialize hv n + simp only [mem_inter_iff, mem_diff, mem_singleton_iff, Metric.mem_ball, dist_eq_norm] + at hv + simpa using hv.2.le + _ = ‖r‖ * u n := by field_simp [(u_pos n).ne']; ring + refine ⟨?_, 0, fun n hn ↦ by simpa using c_ne n⟩ + apply squeeze_zero (fun n ↦ by positivity) B + simpa using u_lim.const_mul _ + refine ⟨c, d, Eventually.of_forall (fun n ↦ by simpa [d] using (hv n).1.1), c_lim, ?_⟩ + rw [tendsto_zero_iff_norm_tendsto_zero] + exact squeeze_zero (fun n ↦ by positivity) (fun n ↦ (c_le n).le) u_lim + +/-- In a proper space, the tangent cone at a non-isolated point is nontrivial. -/ +theorem tangentCone_nonempty_of_properSpace [ProperSpace E] + {s : Set E} {x : E} (hx : (𝓝[s \ {x}] x).NeBot) : + (tangentConeAt 𝕜 s x ∩ {0}ᶜ).Nonempty := by + /- Take a sequence `d n` tending to `0` such that `x + d n ∈ s`. Taking `c n` of the order + of `1 / d n`. Then `c n • d n` belongs to a fixed annulus. By compactness, one can extract + a subsequence converging to a limit `l`. Then `l` is nonzero, and by definition it belongs to + the tangent cone. -/ + obtain ⟨u, -, u_pos, u_lim⟩ : + ∃ u, StrictAnti u ∧ (∀ (n : ℕ), 0 < u n) ∧ Tendsto u atTop (𝓝 (0 : ℝ)) := + exists_seq_strictAnti_tendsto (0 : ℝ) + have A n : ((s \ {x}) ∩ Metric.ball x (u n)).Nonempty := by + apply NeBot.nonempty_of_mem hx (inter_mem_nhdsWithin _ (Metric.ball_mem_nhds _ (u_pos n))) + choose v hv using A + let d := fun n ↦ v n - x + have M n : x + d n ∈ s \ {x} := by simpa [d] using (hv n).1 + let ⟨r, hr⟩ := exists_one_lt_norm 𝕜 + have W n := rescale_to_shell hr zero_lt_one (x := d n) (by simpa using (M n).2) + choose c c_ne c_le le_c hc using W + have c_lim : Tendsto (fun n ↦ ‖c n‖) atTop atTop := by + suffices Tendsto (fun n ↦ ‖c n‖⁻¹ ⁻¹ ) atTop atTop by simpa + apply tendsto_inv_nhdsGT_zero.comp + simp only [nhdsWithin, tendsto_inf, tendsto_principal, mem_Ioi, norm_pos_iff, ne_eq, + eventually_atTop, ge_iff_le] + have B (n : ℕ) : ‖c n‖⁻¹ ≤ 1⁻¹ * ‖r‖ * u n := by + apply (hc n).trans + gcongr + specialize hv n + simp only [mem_inter_iff, mem_diff, mem_singleton_iff, Metric.mem_ball, dist_eq_norm] at hv + simpa using hv.2.le + refine ⟨?_, 0, fun n hn ↦ by simpa using c_ne n⟩ + apply squeeze_zero (fun n ↦ by positivity) B + simpa using u_lim.const_mul _ + obtain ⟨l, l_mem, φ, φ_strict, hφ⟩ : + ∃ l ∈ Metric.closedBall (0 : E) 1 \ Metric.ball (0 : E) (1 / ‖r‖), + ∃ (φ : ℕ → ℕ), StrictMono φ ∧ Tendsto ((fun n ↦ c n • d n) ∘ φ) atTop (𝓝 l) := by + apply IsCompact.tendsto_subseq _ (fun n ↦ ?_) + · exact (isCompact_closedBall 0 1).diff Metric.isOpen_ball + simp only [mem_diff, Metric.mem_closedBall, dist_zero_right, (c_le n).le, + Metric.mem_ball, not_lt, true_and, le_c n] + refine ⟨l, ?_, ?_⟩; swap + · simp only [mem_compl_iff, mem_singleton_iff] + contrapose! l_mem + simp only [one_div, l_mem, mem_diff, Metric.mem_closedBall, dist_self, zero_le_one, + Metric.mem_ball, inv_pos, norm_pos_iff, ne_eq, not_not, true_and] + contrapose! hr + simp [hr] + refine ⟨c ∘ φ, d ∘ φ, ?_, ?_, hφ⟩ + · exact Eventually.of_forall (fun n ↦ by simpa [d] using (hv (φ n)).1.1) + · exact c_lim.comp φ_strict.tendsto_atTop + +/-- The tangent cone at a non-isolated point in dimension 1 is the whole space. -/ +theorem tangentCone_eq_univ {s : Set 𝕜} {x : 𝕜} (hx : (𝓝[s \ {x}] x).NeBot) : + tangentConeAt 𝕜 s x = univ := by + apply eq_univ_iff_forall.2 (fun y ↦ ?_) + -- first deal with the case of `0`, which has to be handled separately. + rcases eq_or_ne y 0 with rfl | hy + · exact zero_mem_tangentCone hx + /- Assume now `y` is a fixed nonzero scalar. Take a sequence `d n` tending to `0` such + that `x + d n ∈ s`. Let `c n = y / d n`. Then `‖c n‖` tends to infinity, and `c n • d n` + converges to `y` (as it is equal to `y`). By definition, this shows that `y` belongs to the + tangent cone. -/ + obtain ⟨u, -, u_pos, u_lim⟩ : + ∃ u, StrictAnti u ∧ (∀ (n : ℕ), 0 < u n) ∧ Tendsto u atTop (𝓝 (0 : ℝ)) := + exists_seq_strictAnti_tendsto (0 : ℝ) + have A n : ((s \ {x}) ∩ Metric.ball x (u n)).Nonempty := by + apply NeBot.nonempty_of_mem hx (inter_mem_nhdsWithin _ (Metric.ball_mem_nhds _ (u_pos n))) + choose v hv using A + let d := fun n ↦ v n - x + have d_ne n : d n ≠ 0 := by + simp only [mem_inter_iff, mem_diff, mem_singleton_iff, Metric.mem_ball, d] at hv + simpa [d, sub_ne_zero] using (hv n).1.2 + refine ⟨fun n ↦ y * (d n)⁻¹, d, ?_, ?_, ?_⟩ + · exact Eventually.of_forall (fun n ↦ by simpa [d] using (hv n).1.1) + · simp only [norm_mul, norm_inv] + apply (tendsto_const_mul_atTop_of_pos (by simpa using hy)).2 + apply tendsto_inv_nhdsGT_zero.comp + simp only [nhdsWithin, tendsto_inf, tendsto_principal, mem_Ioi, norm_pos_iff, ne_eq, + eventually_atTop, ge_iff_le] + have B (n : ℕ) : ‖d n‖ ≤ u n := by + specialize hv n + simp only [mem_inter_iff, mem_diff, mem_singleton_iff, Metric.mem_ball, dist_eq_norm] at hv + simpa using hv.2.le + refine ⟨?_, 0, fun n hn ↦ by simpa using d_ne n⟩ + exact squeeze_zero (fun n ↦ by positivity) B u_lim + · convert tendsto_const_nhds (α := ℕ) (x := y) with n + simp [mul_assoc, inv_mul_cancel₀ (d_ne n)] + end TangentCone section UniqueDiff @@ -391,4 +521,15 @@ theorem uniqueDiffWithinAt_Ioi (a : ℝ) : UniqueDiffWithinAt ℝ (Ioi a) a := theorem uniqueDiffWithinAt_Iio (a : ℝ) : UniqueDiffWithinAt ℝ (Iio a) a := uniqueDiffWithinAt_convex (convex_Iio a) (by simp) (by simp) +/-- In one dimension, every point is either a point of unique differentiability, or isolated. -/ +theorem uniqueDiffWithinAt_or_nhdsWithin_eq_bot (s : Set 𝕜) (x : 𝕜) : + UniqueDiffWithinAt 𝕜 s x ∨ 𝓝[s \ {x}] x = ⊥ := by + rcases eq_or_neBot (𝓝[s \ {x}] x) with h | h + · exact Or.inr h + refine Or.inl ⟨?_, ?_⟩ + · simp [tangentCone_eq_univ h] + · simp only [mem_closure_iff_nhdsWithin_neBot] + apply neBot_of_le (hf := h) + exact nhdsWithin_mono _ diff_subset + end UniqueDiff From a58a89a28f740bc7878e82806f3ddf2f67bfd65a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Sun, 19 Jan 2025 09:13:31 +0000 Subject: [PATCH 303/681] feat: describe the interval of reals `t` where `exp (t * X)` is integrable (#20418) The set of reals `t` where `exp (t * X)` is integrable is an interval containing 0. Also prove integrability of other function for a parameter in that interval. Rename Probability/Moments to Probability/Moments/Basic Co-authored-by: RemyDegenne --- Mathlib.lean | 3 +- .../Analysis/SpecialFunctions/Pow/Real.lean | 6 + Mathlib/Data/Complex/Exponential.lean | 8 + Mathlib/MeasureTheory/Function/L1Space.lean | 6 + .../Probability/Distributions/Gaussian.lean | 2 +- .../{Moments.lean => Moments/Basic.lean} | 21 +- .../Probability/Moments/IntegrableExpMul.lean | 547 ++++++++++++++++++ 7 files changed, 590 insertions(+), 3 deletions(-) rename Mathlib/Probability/{Moments.lean => Moments/Basic.lean} (95%) create mode 100644 Mathlib/Probability/Moments/IntegrableExpMul.lean diff --git a/Mathlib.lean b/Mathlib.lean index a42fe7ba77e51..13611803961d6 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4332,7 +4332,8 @@ import Mathlib.Probability.Martingale.Convergence import Mathlib.Probability.Martingale.OptionalSampling import Mathlib.Probability.Martingale.OptionalStopping import Mathlib.Probability.Martingale.Upcrossing -import Mathlib.Probability.Moments +import Mathlib.Probability.Moments.Basic +import Mathlib.Probability.Moments.IntegrableExpMul import Mathlib.Probability.Notation import Mathlib.Probability.ProbabilityMassFunction.Basic import Mathlib.Probability.ProbabilityMassFunction.Binomial diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index 7781b43786177..a49168a3cabb8 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -719,6 +719,12 @@ theorem rpow_le_rpow_of_exponent_ge' (hx0 : 0 ≤ x) (hx1 : x ≤ 1) (hz : 0 ≤ x ^ y ≤ x ^ z := rpow_le_rpow_of_exponent_ge_of_imp hx0 hx1 hyz fun _ hy ↦ le_antisymm (hyz.trans_eq hy) hz +lemma rpow_max {x y p : ℝ} (hx : 0 ≤ x) (hy : 0 ≤ y) (hp : 0 ≤ p) : + (max x y) ^ p = max (x ^ p) (y ^ p) := by + rcases le_total x y with hxy | hxy + · rw [max_eq_right hxy, max_eq_right (rpow_le_rpow hx hxy hp)] + · rw [max_eq_left hxy, max_eq_left (rpow_le_rpow hy hxy hp)] + theorem self_le_rpow_of_le_one (h₁ : 0 ≤ x) (h₂ : x ≤ 1) (h₃ : y ≤ 1) : x ≤ x ^ y := by simpa only [rpow_one] using rpow_le_rpow_of_exponent_ge_of_imp h₁ h₂ h₃ fun _ ↦ (absurd · one_ne_zero) diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index eb7b8802a1a40..0b65e9e791485 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -1445,6 +1445,12 @@ theorem one_sub_div_pow_le_exp_neg {n : ℕ} {t : ℝ} (ht' : t ≤ n) : (1 - t · exact one_sub_le_exp_neg _ _ = rexp (-t) := by rw [← Real.exp_nat_mul, mul_neg, mul_comm, div_mul_cancel₀]; positivity +lemma le_inv_mul_exp (x : ℝ) {c : ℝ} (hc : 0 < c) : x ≤ c⁻¹ * exp (c * x) := by + rw [le_inv_mul_iff₀ hc] + calc c * x + _ ≤ c * x + 1 := le_add_of_nonneg_right zero_le_one + _ ≤ _ := Real.add_one_le_exp (c * x) + end Real namespace Mathlib.Meta.Positivity @@ -1495,3 +1501,5 @@ theorem abs_exp_eq_iff_re_eq {x y : ℂ} : abs (exp x) = abs (exp y) ↔ x.re = rw [abs_exp, abs_exp, Real.exp_eq_exp] end Complex + +set_option linter.style.longFile 1700 diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 61370ba5ba955..31148a529c769 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -485,6 +485,12 @@ theorem Memℒp.integrable_norm_rpow' [IsFiniteMeasure μ] {f : α → β} {p : · simp [h_top, integrable_const] exact hf.integrable_norm_rpow h_zero h_top +lemma integrable_norm_rpow_iff {f : α → β} {p : ℝ≥0∞} + (hf : AEStronglyMeasurable f μ) (p_zero : p ≠ 0) (p_top : p ≠ ∞) : + Integrable (fun x : α => ‖f x‖ ^ p.toReal) μ ↔ Memℒp f p μ := by + rw [← memℒp_norm_rpow_iff (q := p) hf p_zero p_top, ← memℒp_one_iff_integrable, + ENNReal.div_self p_zero p_top] + theorem Integrable.mono_measure {f : α → β} (h : Integrable f ν) (hμ : μ ≤ ν) : Integrable f μ := ⟨h.aestronglyMeasurable.mono_measure hμ, h.hasFiniteIntegral.mono_measure hμ⟩ diff --git a/Mathlib/Probability/Distributions/Gaussian.lean b/Mathlib/Probability/Distributions/Gaussian.lean index 41df4ffe5d082..11c870959f6a1 100644 --- a/Mathlib/Probability/Distributions/Gaussian.lean +++ b/Mathlib/Probability/Distributions/Gaussian.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Lorenzo Luccioli, Rémy Degenne, Alexander Bentkamp -/ import Mathlib.Analysis.SpecialFunctions.Gaussian.GaussianIntegral -import Mathlib.Probability.Moments +import Mathlib.Probability.Moments.Basic /-! # Gaussian distributions over ℝ diff --git a/Mathlib/Probability/Moments.lean b/Mathlib/Probability/Moments/Basic.lean similarity index 95% rename from Mathlib/Probability/Moments.lean rename to Mathlib/Probability/Moments/Basic.lean index 7e8db5fd848ce..702f6a22f7438 100644 --- a/Mathlib/Probability/Moments.lean +++ b/Mathlib/Probability/Moments/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ import Mathlib.Probability.IdentDistrib -import Mathlib.Probability.Variance /-! # Moments and moment generating function @@ -213,6 +212,26 @@ theorem mgf_const_add (α : ℝ) : mgf (fun ω => α + X ω) μ t = exp (t * α) theorem mgf_add_const (α : ℝ) : mgf (fun ω => X ω + α) μ t = mgf X μ t * exp (t * α) := by simp only [add_comm, mgf_const_add, mul_comm] +/-- The moment generating function is monotone in the random variable for `t ≥ 0`. -/ +lemma mgf_mono_of_nonneg {Y : Ω → ℝ} (hXY : X ≤ᵐ[μ] Y) (ht : 0 ≤ t) + (htY : Integrable (fun ω ↦ exp (t * Y ω)) μ) : + mgf X μ t ≤ mgf Y μ t := by + by_cases htX : Integrable (fun ω ↦ exp (t * X ω)) μ + · refine integral_mono_ae htX htY ?_ + filter_upwards [hXY] with ω hω using by gcongr + · rw [mgf_undef htX] + exact mgf_nonneg + +/-- The moment generating function is antitone in the random variable for `t ≤ 0`. -/ +lemma mgf_anti_of_nonpos {Y : Ω → ℝ} (hXY : X ≤ᵐ[μ] Y) (ht : t ≤ 0) + (htX : Integrable (fun ω ↦ exp (t * X ω)) μ) : + mgf Y μ t ≤ mgf X μ t := by + by_cases htY : Integrable (fun ω ↦ exp (t * Y ω)) μ + · refine integral_mono_ae htY htX ?_ + filter_upwards [hXY] with ω hω using exp_monotone <| mul_le_mul_of_nonpos_left hω ht + · rw [mgf_undef htY] + exact mgf_nonneg + section IndepFun /-- This is a trivial application of `IndepFun.comp` but it will come up frequently. -/ diff --git a/Mathlib/Probability/Moments/IntegrableExpMul.lean b/Mathlib/Probability/Moments/IntegrableExpMul.lean new file mode 100644 index 0000000000000..27e4cb7cfa305 --- /dev/null +++ b/Mathlib/Probability/Moments/IntegrableExpMul.lean @@ -0,0 +1,547 @@ +/- +Copyright (c) 2024 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.Function.L1Space +import Mathlib.MeasureTheory.Order.Group.Lattice + +/-! +# Domain of the moment generating function + +For `X` a real random variable and `μ` a finite measure, the set +`{t | Integrable (fun ω ↦ exp (t * X ω)) μ}` is an interval containing zero. This is the set of +points for which the moment generating function `mgf X μ t` is well defined. +We denote that set by `integrableExpSet X μ`. + +We prove the integrability of other functions for `t` in the interior of that interval. + +## Main definitions + +* `ProbabilityTheory.IntegrableExpSet`: the interval of reals for which `exp (t * X)` is integrable. + +## Main results + +* `ProbabilityTheory.integrable_exp_mul_of_le_of_le`: if `exp (u * X)` is integrable for `u = a` and + `u = b` then it is integrable on `[a, b]`. +* `ProbabilityTheory.convex_integrableExpSet`: `integrableExpSet X μ` is a convex set. +* `ProbabilityTheory.integrable_exp_mul_of_nonpos_of_ge`: if `exp (u * X)` is integrable for `u ≤ 0` + then it is integrable on `[u, 0]`. +* `ProbabilityTheory.integrable_rpow_abs_mul_exp_of_mem_interior`: for `v` in the interior of the + interval in which `exp (t * X)` is integrable, for all nonnegative `p : ℝ`, + `|X| ^ p * exp (v * X)` is integrable. +* `ProbabilityTheory.memℒp_of_mem_interior_integrableExpSet`: if 0 belongs to the interior of + `integrableExpSet X μ`, then `X` is in `ℒp` for all finite `p`. + +-/ + + +open MeasureTheory Filter Finset Real + +open scoped MeasureTheory ProbabilityTheory ENNReal NNReal Topology + +namespace ProbabilityTheory + +variable {Ω ι : Type*} {m : MeasurableSpace Ω} {X : Ω → ℝ} {μ : Measure Ω} {t u v : ℝ} + +section Interval + +lemma integrable_exp_mul_of_le_of_le {a b : ℝ} + (ha : Integrable (fun ω ↦ exp (a * X ω)) μ) (hb : Integrable (fun ω ↦ exp (b * X ω)) μ) + (hat : a ≤ t) (htb : t ≤ b) : + Integrable (fun ω ↦ exp (t * X ω)) μ := by + refine Integrable.mono (ha.add hb) ?_ (ae_of_all _ fun ω ↦ ?_) + · by_cases hab : a = b + · have ha_eq_t : a = t := le_antisymm hat (hab ▸ htb) + rw [← ha_eq_t] + exact ha.1 + · refine AEMeasurable.aestronglyMeasurable ?_ + refine measurable_exp.comp_aemeasurable (AEMeasurable.const_mul ?_ _) + by_cases ha_zero : a = 0 + · refine aemeasurable_of_aemeasurable_exp_mul ?_ hb.1.aemeasurable + rw [ha_zero] at hab + exact Ne.symm hab + · exact aemeasurable_of_aemeasurable_exp_mul ha_zero ha.1.aemeasurable + · simp only [norm_eq_abs, abs_exp, Pi.add_apply] + conv_rhs => rw [abs_of_nonneg (by positivity)] + rcases le_total 0 (X ω) with h | h + · calc exp (t * X ω) + _ ≤ exp (b * X ω) := exp_le_exp.mpr (mul_le_mul_of_nonneg_right htb h) + _ ≤ exp (a * X ω) + exp (b * X ω) := le_add_of_nonneg_left (exp_nonneg _) + · calc exp (t * X ω) + _ ≤ exp (a * X ω) := exp_le_exp.mpr (mul_le_mul_of_nonpos_right hat h) + _ ≤ exp (a * X ω) + exp (b * X ω) := le_add_of_nonneg_right (exp_nonneg _) + +/-- If `ω ↦ exp (u * X ω)` is integrable at `u` and `-u`, then it is integrable on `[-u, u]`. -/ +lemma integrable_exp_mul_of_abs_le + (hu_int_pos : Integrable (fun ω ↦ exp (u * X ω)) μ) + (hu_int_neg : Integrable (fun ω ↦ exp (- u * X ω)) μ) + (htu : |t| ≤ |u|) : + Integrable (fun ω ↦ exp (t * X ω)) μ := by + refine integrable_exp_mul_of_le_of_le (a := -|u|) (b := |u|) ?_ ?_ ?_ ?_ + · rcases le_total 0 u with hu | hu + · rwa [abs_of_nonneg hu] + · simpa [abs_of_nonpos hu] + · rcases le_total 0 u with hu | hu + · rwa [abs_of_nonneg hu] + · rwa [abs_of_nonpos hu] + · rw [neg_le] + exact (neg_le_abs t).trans htu + · exact (le_abs_self t).trans htu + +/-- If `ω ↦ exp (u * X ω)` is integrable at `u ≥ 0`, then it is integrable on `[0, u]`. -/ +lemma integrable_exp_mul_of_nonneg_of_le [IsFiniteMeasure μ] + (hu : Integrable (fun ω ↦ exp (u * X ω)) μ) (h_nonneg : 0 ≤ t) (htu : t ≤ u) : + Integrable (fun ω ↦ exp (t * X ω)) μ := + integrable_exp_mul_of_le_of_le (by simp) hu h_nonneg htu + +/-- If `ω ↦ exp (u * X ω)` is integrable at `u ≤ 0`, then it is integrable on `[u, 0]`. -/ +lemma integrable_exp_mul_of_nonpos_of_ge [IsFiniteMeasure μ] + (hu : Integrable (fun ω ↦ exp (u * X ω)) μ) (h_nonpos : t ≤ 0) (htu : u ≤ t) : + Integrable (fun ω ↦ exp (t * X ω)) μ := + integrable_exp_mul_of_le_of_le hu (by simp) htu h_nonpos + +end Interval + +section IntegrableExpSet + +/-- The interval of reals `t` for which `exp (t * X)` is integrable. -/ +def integrableExpSet (X : Ω → ℝ) (μ : Measure Ω) : Set ℝ := + {t | Integrable (fun ω ↦ exp (t * X ω)) μ} + +lemma integrable_of_mem_integrableExpSet (h : t ∈ integrableExpSet X μ) : + Integrable (fun ω ↦ exp (t * X ω)) μ := h + +/-- `integrableExpSet X μ` is a convex subset of `ℝ` (it is an interval). -/ +lemma convex_integrableExpSet : Convex ℝ (integrableExpSet X μ) := by + rintro t₁ ht₁ t₂ ht₂ a b ha hb hab + wlog h_le : t₁ ≤ t₂ + · rw [add_comm] at hab ⊢ + exact this ht₂ ht₁ hb ha hab (not_le.mp h_le).le + refine integrable_exp_mul_of_le_of_le ht₁ ht₂ ?_ ?_ + · simp only [smul_eq_mul] + calc t₁ + _ = a * t₁ + b * t₁ := by rw [← add_mul, hab, one_mul] + _ ≤ a * t₁ + b * t₂ := by gcongr + · simp only [smul_eq_mul] + calc a * t₁ + b * t₂ + _ ≤ a * t₂ + b * t₂ := by gcongr + _ = t₂ := by rw [← add_mul, hab, one_mul] + +end IntegrableExpSet + +section FiniteMoments + +lemma aemeasurable_of_integrable_exp_mul (huv : u ≠ v) + (hu_int : Integrable (fun ω ↦ exp (u * X ω)) μ) + (hv_int : Integrable (fun ω ↦ exp (v * X ω)) μ) : + AEMeasurable X μ := by + by_cases hu : u = 0 + · have hv : v ≠ 0 := fun h_eq ↦ huv (h_eq ▸ hu) + exact aemeasurable_of_aemeasurable_exp_mul hv hv_int.aemeasurable + · exact aemeasurable_of_aemeasurable_exp_mul hu hu_int.aemeasurable + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable, then +`ω ↦ exp (t * |X| + v * X)` is integrable. -/ +lemma integrable_exp_mul_abs_add (ht_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) : + Integrable (fun ω ↦ exp (t * |X ω| + v * X ω)) μ := by + have h_int_add : Integrable (fun a ↦ exp ((v + t) * X a) + exp ((v - t) * X a)) μ := + ht_int_pos.add <| by simpa using ht_int_neg + refine Integrable.mono h_int_add ?_ (ae_of_all _ fun ω ↦ ?_) + · by_cases ht : t = 0 + · simp only [ht, zero_mul, zero_add, add_zero] at ht_int_pos ⊢ + exact ht_int_pos.1 + have hX : AEMeasurable X μ := aemeasurable_of_integrable_exp_mul ?_ ht_int_pos ht_int_neg + swap; · rw [← sub_ne_zero]; simp [ht] + refine AEMeasurable.aestronglyMeasurable ?_ + exact measurable_exp.comp_aemeasurable ((hX.abs.const_mul _).add (hX.const_mul _)) + · simp only [norm_eq_abs, abs_exp] + conv_rhs => rw [abs_of_nonneg (by positivity)] + -- ⊢ exp (t * |X ω| + v * X ω) ≤ exp ((v + t) * X ω) + exp ((v - t) * X ω) + rcases le_total 0 (X ω) with h_nonneg | h_nonpos + · rw [abs_of_nonneg h_nonneg, ← add_mul, add_comm, le_add_iff_nonneg_right] + positivity + · rw [abs_of_nonpos h_nonpos, mul_neg, mul_comm, ← mul_neg, mul_comm, ← add_mul, add_comm, + ← sub_eq_add_neg, le_add_iff_nonneg_left] + positivity + +/-- If `ω ↦ exp (t * X ω)` is integrable at `t` and `-t`, then `ω ↦ exp (t * |X ω|)` is +integrable. -/ +lemma integrable_exp_mul_abs (ht_int_pos : Integrable (fun ω ↦ exp (t * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp (- t * X ω)) μ) : + Integrable (fun ω ↦ exp (t * |X ω|)) μ := by + have h := integrable_exp_mul_abs_add (t := t) (μ := μ) (X := X) (v := 0) ?_ ?_ + · simpa using h + · simpa using ht_int_pos + · simpa using ht_int_neg + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable, then +`ω ↦ exp (|t| * |X| + v * X)` is integrable. -/ +lemma integrable_exp_abs_mul_abs_add (ht_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) : + Integrable (fun ω ↦ exp (|t| * |X ω| + v * X ω)) μ := by + rcases le_total 0 t with ht_nonneg | ht_nonpos + · simp_rw [abs_of_nonneg ht_nonneg] + exact integrable_exp_mul_abs_add ht_int_pos ht_int_neg + · simp_rw [abs_of_nonpos ht_nonpos] + exact integrable_exp_mul_abs_add ht_int_neg (by simpa using ht_int_pos) + +/-- If `ω ↦ exp (t * X ω)` is integrable at `t` and `-t`, then `ω ↦ exp (|t| * |X ω|)` is +integrable. -/ +lemma integrable_exp_abs_mul_abs (ht_int_pos : Integrable (fun ω ↦ exp (t * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp (- t * X ω)) μ) : + Integrable (fun ω ↦ exp (|t| * |X ω|)) μ := by + rcases le_total 0 t with ht_nonneg | ht_nonpos + · simp_rw [abs_of_nonneg ht_nonneg] + exact integrable_exp_mul_abs ht_int_pos ht_int_neg + · simp_rw [abs_of_nonpos ht_nonpos] + exact integrable_exp_mul_abs ht_int_neg (by simpa using ht_int_pos) + +/-- Auxiliary lemma for `rpow_abs_le_mul_max_exp`. -/ +lemma rpow_abs_le_mul_max_exp_of_pos (x : ℝ) {t p : ℝ} (hp : 0 ≤ p) (ht : 0 < t) : + |x| ^ p ≤ (p / t) ^ p * max (exp (t * x)) (exp (- t * x)) := by + by_cases hp_zero : p = 0 + · simp only [hp_zero, rpow_zero, zero_div, neg_mul, one_mul, le_sup_iff, one_le_exp_iff, + Left.nonneg_neg_iff] + exact le_total 0 (t * x) + have h_x_le c (hc : 0 < c) : x ≤ c⁻¹ * exp (c * x) := le_inv_mul_exp x hc + have h_neg_x_le c (hc : 0 < c) : -x ≤ c⁻¹ * exp (- c * x) := by simpa using le_inv_mul_exp (-x) hc + have h_abs_le c (hc : 0 < c) : |x| ≤ c⁻¹ * max (exp (c * x)) (exp (- c * x)) := by + refine abs_le.mpr ⟨?_, ?_⟩ + · rw [neg_le] + refine (h_neg_x_le c hc).trans ?_ + gcongr + exact le_max_right _ _ + · refine (h_x_le c hc).trans ?_ + gcongr + exact le_max_left _ _ + calc |x| ^ p + _ ≤ ((t / p)⁻¹ * max (exp (t / p * x)) (exp (- t / p * x))) ^ p := by + refine rpow_le_rpow (abs_nonneg _) ?_ hp + convert h_abs_le (t / p) (div_pos ht (hp.lt_of_ne' hp_zero)) using 5 + rw [neg_div] + _ = (p / t) ^ p * max (exp (t * x)) (exp (- t * x)) := by + rw [mul_rpow (by positivity) (by positivity)] + congr + · field_simp + · rw [rpow_max (by positivity) (by positivity) hp, ← exp_mul, ← exp_mul] + ring_nf + congr <;> rw [mul_assoc, mul_inv_cancel₀ hp_zero, mul_one] + +lemma rpow_abs_le_mul_max_exp (x : ℝ) {t p : ℝ} (hp : 0 ≤ p) (ht : t ≠ 0) : + |x| ^ p ≤ (p / |t|) ^ p * max (exp (t * x)) (exp (- t * x)) := by + rcases lt_or_gt_of_ne ht with ht_neg | ht_pos + · rw [abs_of_nonpos ht_neg.le, sup_comm] + convert rpow_abs_le_mul_max_exp_of_pos x hp (t := -t) (by simp [ht_neg]) + simp + · rw [abs_of_nonneg ht_pos.le] + exact rpow_abs_le_mul_max_exp_of_pos x hp ht_pos + +lemma rpow_abs_le_mul_exp_abs (x : ℝ) {t p : ℝ} (hp : 0 ≤ p) (ht : t ≠ 0) : + |x| ^ p ≤ (p / |t|) ^ p * exp (|t| * |x|) := by + refine (rpow_abs_le_mul_max_exp_of_pos x hp (t := |t|) ?_).trans_eq ?_ + · simp [ht] + · congr + rcases le_total 0 x with hx | hx + · rw [abs_of_nonneg hx] + simp only [neg_mul, sup_eq_left, exp_le_exp, neg_le_self_iff] + positivity + · rw [abs_of_nonpos hx] + simp only [neg_mul, mul_neg, sup_eq_right, exp_le_exp, le_neg_self_iff] + exact mul_nonpos_of_nonneg_of_nonpos (abs_nonneg _) hx + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable +then for nonnegative `p : ℝ` and any `x ∈ [0, |t|)`, +`|X| ^ p * exp (v * X + x * |X|)` is integrable. -/ +lemma integrable_rpow_abs_mul_exp_add_of_integrable_exp_mul {x : ℝ} + (h_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (h_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) (h_nonneg : 0 ≤ x) (hx : x < |t|) + {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun a ↦ |X a| ^ p * exp (v * X a + x * |X a|)) μ := by + have ht : t ≠ 0 := by + suffices |t| ≠ 0 by simpa + exact (h_nonneg.trans_lt hx).ne' + have hX : AEMeasurable X μ := aemeasurable_of_integrable_exp_mul ?_ h_int_pos h_int_neg + swap; · rw [← sub_ne_zero]; simp [ht] + rw [← integrable_norm_iff] + swap + · refine AEMeasurable.aestronglyMeasurable ?_ + exact AEMeasurable.mul (by fun_prop) (measurable_exp.comp_aemeasurable (by fun_prop)) + simp only [norm_mul, norm_pow, norm_eq_abs, sq_abs, abs_exp] + have h_le a : |X a| ^ p * exp (v * X a + x * |X a|) + ≤ (p / (|t| - x)) ^ p * exp (v * X a + |t| * |X a|) := by + simp_rw [exp_add, mul_comm (exp (v * X a)), ← mul_assoc] + gcongr ?_ * _ + have : |t| = |t| - x + x := by simp + nth_rw 2 [this] + rw [add_mul, exp_add, ← mul_assoc] + gcongr ?_ * _ + convert rpow_abs_le_mul_exp_abs (X a) hp (t := |t| - x) _ using 4 + · nth_rw 2 [abs_of_nonneg] + simp [hx.le] + · nth_rw 2 [abs_of_nonneg] + simp [hx.le] + · rw [sub_ne_zero] + exact hx.ne' + refine Integrable.mono (g := fun a ↦ (p / (|t| - x)) ^ p * exp (v * X a + |t| * |X a|)) + ?_ ?_ <| ae_of_all _ fun ω ↦ ?_ + · refine Integrable.const_mul ?_ _ + simp_rw [add_comm (v * X _)] + exact integrable_exp_abs_mul_abs_add h_int_pos h_int_neg + · refine AEMeasurable.aestronglyMeasurable ?_ + exact AEMeasurable.mul (by fun_prop) (measurable_exp.comp_aemeasurable (by fun_prop)) + · simp only [sq_abs, norm_mul, norm_pow, norm_eq_abs, abs_exp, norm_div, norm_ofNat] + simp_rw [abs_rpow_of_nonneg (abs_nonneg _), abs_abs] + refine (h_le ω).trans_eq ?_ + congr + symm + simp only [abs_eq_self, sub_nonneg] + exact rpow_nonneg (div_nonneg hp (sub_nonneg_of_le hx.le)) _ + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable +then for any `n : ℕ` and any `x ∈ [0, |t|)`, +`|X| ^ n * exp (v * X + x * |X|)` is integrable. -/ +lemma integrable_pow_abs_mul_exp_add_of_integrable_exp_mul {x : ℝ} + (h_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (h_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) (h_nonneg : 0 ≤ x) (hx : x < |t|) + (n : ℕ) : + Integrable (fun a ↦ |X a| ^ n * exp (v * X a + x * |X a|)) μ := by + convert integrable_rpow_abs_mul_exp_add_of_integrable_exp_mul h_int_pos h_int_neg h_nonneg hx + n.cast_nonneg + simp + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable +then for nonnegative `p : ℝ`, `|X| ^ p * exp (v * X)` is integrable. -/ +lemma integrable_rpow_abs_mul_exp_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ |X ω| ^ p * exp (v * X ω)) μ := by + convert integrable_rpow_abs_mul_exp_add_of_integrable_exp_mul ht_int_pos ht_int_neg le_rfl _ hp + using 4 + · simp + · simp [ht] + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable, then for all `n : ℕ`, +`|X| ^ n * exp (v * X)` is integrable. -/ +lemma integrable_pow_abs_mul_exp_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) (n : ℕ) : + Integrable (fun ω ↦ |X ω| ^ n * exp (v * X ω)) μ := by + convert integrable_rpow_abs_mul_exp_of_integrable_exp_mul ht ht_int_pos ht_int_neg + (by positivity : 0 ≤ (n : ℝ)) with ω + simp + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable, then for all nonnegative `p : ℝ`, +`X ^ p * exp (v * X)` is integrable. -/ +lemma integrable_rpow_mul_exp_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ X ω ^ p * exp (v * X ω)) μ := by + have hX : AEMeasurable X μ := aemeasurable_of_integrable_exp_mul ?_ ht_int_pos ht_int_neg + swap; · rw [← sub_ne_zero]; simp [ht] + rw [← integrable_norm_iff] + · simp_rw [norm_eq_abs, abs_mul, abs_exp] + have h := integrable_rpow_abs_mul_exp_of_integrable_exp_mul ht ht_int_pos ht_int_neg hp + refine h.mono' ?_ ?_ + · exact ((hX.pow_const _).abs.mul + (measurable_exp.comp_aemeasurable (hX.const_mul _))).aestronglyMeasurable + · refine ae_of_all _ fun ω ↦ ?_ + simp only [norm_mul, norm_eq_abs, abs_abs, abs_exp] + gcongr + exact abs_rpow_le_abs_rpow _ _ + · exact ((hX.pow_const _).mul + (measurable_exp.comp_aemeasurable (hX.const_mul _))).aestronglyMeasurable + +/-- If `exp ((v + t) * X)` and `exp ((v - t) * X)` are integrable, then for all `n : ℕ`, +`X ^ n * exp (v * X)` is integrable. -/ +lemma integrable_pow_mul_exp_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp ((v + t) * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp ((v - t) * X ω)) μ) (n : ℕ) : + Integrable (fun ω ↦ X ω ^ n * exp (v * X ω)) μ := by + convert integrable_rpow_mul_exp_of_integrable_exp_mul ht ht_int_pos ht_int_neg + (by positivity : 0 ≤ (n : ℝ)) with ω + simp + +/-- If `ω ↦ exp (t * X ω)` is integrable at `t` and `-t` for `t ≠ 0`, then `ω ↦ |X ω| ^ p` is +integrable for all nonnegative `p : ℝ`. -/ +lemma integrable_rpow_abs_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp (t * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp (- t * X ω)) μ) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ |X ω| ^ p) μ := by + have h := integrable_rpow_abs_mul_exp_of_integrable_exp_mul (μ := μ) (X := X) ht (v := 0) ?_ ?_ hp + · simpa using h + · simpa using ht_int_pos + · simpa using ht_int_neg + +/-- If `ω ↦ exp (t * X ω)` is integrable at `t` and `-t` for `t ≠ 0`, then `ω ↦ |X ω| ^ n` is +integrable for all `n : ℕ`. That is, all moments of `X` are finite. -/ +lemma integrable_pow_abs_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp (t * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp (- t * X ω)) μ) (n : ℕ) : + Integrable (fun ω ↦ |X ω| ^ n) μ := by + convert integrable_rpow_abs_of_integrable_exp_mul ht ht_int_pos ht_int_neg + (by positivity : 0 ≤ (n : ℝ)) with ω + simp + +/-- If `ω ↦ exp (t * X ω)` is integrable at `t` and `-t` for `t ≠ 0`, then `ω ↦ X ω ^ p` is +integrable for all nonnegative `p : ℝ`. -/ +lemma integrable_rpow_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp (t * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp (- t * X ω)) μ) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ X ω ^ p) μ := by + have h := integrable_rpow_mul_exp_of_integrable_exp_mul (μ := μ) (X := X) ht (v := 0) ?_ ?_ hp + · simpa using h + · simpa using ht_int_pos + · simpa using ht_int_neg + +/-- If `ω ↦ exp (t * X ω)` is integrable at `t` and `-t` for `t ≠ 0`, then `ω ↦ X ω ^ n` is +integrable for all `n : ℕ`. -/ +lemma integrable_pow_of_integrable_exp_mul (ht : t ≠ 0) + (ht_int_pos : Integrable (fun ω ↦ exp (t * X ω)) μ) + (ht_int_neg : Integrable (fun ω ↦ exp (- t * X ω)) μ) (n : ℕ) : + Integrable (fun ω ↦ X ω ^ n) μ := by + convert integrable_rpow_of_integrable_exp_mul ht ht_int_pos ht_int_neg + (by positivity : 0 ≤ (n : ℝ)) with ω + simp + +section IntegrableExpSet + +lemma add_half_inf_sub_mem_Ioo {l u v : ℝ} (hv : v ∈ Set.Ioo l u) : + v + ((v - l) ⊓ (u - v)) / 2 ∈ Set.Ioo l u := by + have h_pos : 0 < (v - l) ⊓ (u - v) := by simp [hv.1, hv.2] + constructor + · calc l < v := hv.1 + _ ≤ v + ((v - l) ⊓ (u - v)) / 2 := le_add_of_nonneg_right (by positivity) + · calc v + ((v - l) ⊓ (u - v)) / 2 + _ < v + ((v - l) ⊓ (u - v)) := by gcongr; exact half_lt_self (by positivity) + _ ≤ v + (u - v) := by gcongr; exact inf_le_right + _ = u := by abel + +lemma sub_half_inf_sub_mem_Ioo {l u v : ℝ} (hv : v ∈ Set.Ioo l u) : + v - ((v - l) ⊓ (u - v)) / 2 ∈ Set.Ioo l u := by + have h_pos : 0 < (v - l) ⊓ (u - v) := by simp [hv.1, hv.2] + constructor + · calc l = v - (v - l) := by abel + _ ≤ v - ((v - l) ⊓ (u - v)) := by gcongr; exact inf_le_left + _ < v - ((v - l) ⊓ (u - v)) / 2 := by gcongr; exact half_lt_self (by positivity) + · calc v - ((v - l) ⊓ (u - v)) / 2 + _ ≤ v := by + rw [sub_le_iff_le_add] + exact le_add_of_nonneg_right (by positivity) + _ < u := hv.2 + +/-- If the interior of the interval `integrableExpSet X μ` is nonempty, +then `X` is a.e. measurable. -/ +lemma aemeasurable_of_mem_interior_integrableExpSet (hv : v ∈ interior (integrableExpSet X μ)) : + AEMeasurable X μ := by + rw [mem_interior_iff_mem_nhds, mem_nhds_iff_exists_Ioo_subset] at hv + obtain ⟨l, u, hvlu, h_subset⟩ := hv + let t := ((v - l) ⊓ (u - v)) / 2 + have h_pos : 0 < (v - l) ⊓ (u - v) := by simp [hvlu.1, hvlu.2] + have ht : 0 < t := half_pos h_pos + by_cases hvt : v + t = 0 + · have hvt' : v - t ≠ 0 := by + rw [sub_ne_zero] + refine fun h_eq ↦ ht.ne' ?_ + simpa [h_eq] using hvt + exact aemeasurable_of_aemeasurable_exp_mul hvt' + (h_subset (sub_half_inf_sub_mem_Ioo hvlu)).aemeasurable + · exact aemeasurable_of_aemeasurable_exp_mul hvt + (h_subset (add_half_inf_sub_mem_Ioo hvlu)).aemeasurable + +/-- If `v` belongs to the interior of the interval `integrableExpSet X μ`, +then `|X| ^ p * exp (v * X)` is integrable for all nonnegative `p : ℝ`. -/ +lemma integrable_rpow_abs_mul_exp_of_mem_interior_integrableExpSet + (hv : v ∈ interior (integrableExpSet X μ)) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ |X ω| ^ p * exp (v * X ω)) μ := by + rw [mem_interior_iff_mem_nhds, mem_nhds_iff_exists_Ioo_subset] at hv + obtain ⟨l, u, hvlu, h_subset⟩ := hv + have h_pos : 0 < (v - l) ⊓ (u - v) := by simp [hvlu.1, hvlu.2] + refine integrable_rpow_abs_mul_exp_of_integrable_exp_mul + (t := min (v - l) (u - v) / 2) ?_ ?_ ?_ hp + · positivity + · exact h_subset (add_half_inf_sub_mem_Ioo hvlu) + · exact h_subset (sub_half_inf_sub_mem_Ioo hvlu) + +/-- If `v` belongs to the interior of the interval `integrableExpSet X μ`, +then `|X| ^ n * exp (v * X)` is integrable for all `n : ℕ`. -/ +lemma integrable_pow_abs_mul_exp_of_mem_interior_integrableExpSet + (hv : v ∈ interior (integrableExpSet X μ)) (n : ℕ) : + Integrable (fun ω ↦ |X ω| ^ n * exp (v * X ω)) μ := by + convert integrable_rpow_abs_mul_exp_of_mem_interior_integrableExpSet hv + (by positivity : 0 ≤ (n : ℝ)) with ω + simp + +/-- If `v` belongs to the interior of the interval `integrableExpSet X μ`, +then `X ^ p * exp (v * X)` is integrable for all nonnegative `p : ℝ`. -/ +lemma integrable_rpow_mul_exp_of_mem_interior_integrableExpSet + (hv : v ∈ interior (integrableExpSet X μ)) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ X ω ^ p * exp (v * X ω)) μ := by + rw [mem_interior_iff_mem_nhds, mem_nhds_iff_exists_Ioo_subset] at hv + obtain ⟨l, u, hvlu, h_subset⟩ := hv + have h_pos : 0 < (v - l) ⊓ (u - v) := by simp [hvlu.1, hvlu.2] + refine integrable_rpow_mul_exp_of_integrable_exp_mul + (t := min (v - l) (u - v) / 2) ?_ ?_ ?_ hp + · positivity + · exact h_subset (add_half_inf_sub_mem_Ioo hvlu) + · exact h_subset (sub_half_inf_sub_mem_Ioo hvlu) + +/-- If `v` belongs to the interior of the interval `integrableExpSet X μ`, +then `X ^ n * exp (v * X)` is integrable for all `n : ℕ`. -/ +lemma integrable_pow_mul_exp_of_mem_interior_integrableExpSet + (hv : v ∈ interior (integrableExpSet X μ)) (n : ℕ) : + Integrable (fun ω ↦ X ω ^ n * exp (v * X ω)) μ := by + convert integrable_rpow_mul_exp_of_mem_interior_integrableExpSet hv + (by positivity : 0 ≤ (n : ℝ)) with ω + simp + +/-- If 0 belongs to the interior of the interval `integrableExpSet X μ`, +then `|X| ^ n` is integrable for all nonnegative `p : ℝ`. -/ +lemma integrable_rpow_abs_of_mem_interior_integrableExpSet + (h : 0 ∈ interior (integrableExpSet X μ)) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ |X ω| ^ p) μ := by + convert integrable_rpow_abs_mul_exp_of_mem_interior_integrableExpSet h hp using 1 + simp + +/-- If 0 belongs to the interior of the interval `integrableExpSet X μ`, +then `|X| ^ n` is integrable for all `n : ℕ`. -/ +lemma integrable_pow_abs_of_mem_interior_integrableExpSet + (h : 0 ∈ interior (integrableExpSet X μ)) (n : ℕ) : + Integrable (fun ω ↦ |X ω| ^ n) μ := by + convert integrable_pow_abs_mul_exp_of_mem_interior_integrableExpSet h n + simp + +/-- If 0 belongs to the interior of the interval `integrableExpSet X μ`, +then `X ^ n` is integrable for all nonnegative `p : ℝ`. -/ +lemma integrable_rpow_of_mem_interior_integrableExpSet + (h : 0 ∈ interior (integrableExpSet X μ)) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ X ω ^ p) μ := by + convert integrable_rpow_mul_exp_of_mem_interior_integrableExpSet h hp using 1 + simp + +/-- If 0 belongs to the interior of the interval `integrableExpSet X μ`, +then `X ^ n` is integrable for all `n : ℕ`. -/ +lemma integrable_pow_of_mem_interior_integrableExpSet + (h : 0 ∈ interior (integrableExpSet X μ)) (n : ℕ) : + Integrable (fun ω ↦ X ω ^ n) μ := by + convert integrable_pow_mul_exp_of_mem_interior_integrableExpSet h n + simp + +/-- If 0 belongs to the interior of `integrableExpSet X μ`, then `X` is in `ℒp` for all +finite `p`. -/ +lemma memℒp_of_mem_interior_integrableExpSet (h : 0 ∈ interior (integrableExpSet X μ)) (p : ℝ≥0) : + Memℒp X p μ := by + have hX : AEMeasurable X μ := aemeasurable_of_mem_interior_integrableExpSet h + by_cases hp_zero : p = 0 + · simp only [hp_zero, ENNReal.coe_zero, memℒp_zero_iff_aestronglyMeasurable] + exact hX.aestronglyMeasurable + rw [← integrable_norm_rpow_iff hX.aestronglyMeasurable (mod_cast hp_zero) (by simp)] + simp only [norm_eq_abs, ENNReal.coe_toReal] + exact integrable_rpow_abs_of_mem_interior_integrableExpSet h p.2 + +end IntegrableExpSet + +end FiniteMoments + +end ProbabilityTheory From 456abfe9dd573526b7af439f5a8bdbc7c8effe18 Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Sun, 19 Jan 2025 10:33:03 +0000 Subject: [PATCH 304/681] feat(CategoryTheory): infer filteredness from filteredness of costructured arrow categories (#19684) --- Mathlib.lean | 2 + .../Filtered/CostructuredArrow.lean | 49 +++++++++ .../OfColimitCommutesFiniteLimit.lean | 2 +- .../Limits/Preserves/Grothendieck.lean | 102 ++++++++++++++++++ .../Limits/Shapes/Grothendieck.lean | 46 ++++++-- 5 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean create mode 100644 Mathlib/CategoryTheory/Limits/Preserves/Grothendieck.lean diff --git a/Mathlib.lean b/Mathlib.lean index 13611803961d6..1dcce7d5ab2a0 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1782,6 +1782,7 @@ import Mathlib.CategoryTheory.FiberedCategory.Fibered import Mathlib.CategoryTheory.FiberedCategory.HomLift import Mathlib.CategoryTheory.Filtered.Basic import Mathlib.CategoryTheory.Filtered.Connected +import Mathlib.CategoryTheory.Filtered.CostructuredArrow import Mathlib.CategoryTheory.Filtered.Final import Mathlib.CategoryTheory.Filtered.Grothendieck import Mathlib.CategoryTheory.Filtered.OfColimitCommutesFiniteLimit @@ -1918,6 +1919,7 @@ import Mathlib.CategoryTheory.Limits.Preserves.Basic import Mathlib.CategoryTheory.Limits.Preserves.Filtered import Mathlib.CategoryTheory.Limits.Preserves.Finite import Mathlib.CategoryTheory.Limits.Preserves.FunctorCategory +import Mathlib.CategoryTheory.Limits.Preserves.Grothendieck import Mathlib.CategoryTheory.Limits.Preserves.Limits import Mathlib.CategoryTheory.Limits.Preserves.Opposites import Mathlib.CategoryTheory.Limits.Preserves.Presheaf diff --git a/Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean b/Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean new file mode 100644 index 0000000000000..042909b9caa30 --- /dev/null +++ b/Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean @@ -0,0 +1,49 @@ +/- +Copyright (c) 2024 Jakob von Raumer. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jakob von Raumer +-/ +import Mathlib.CategoryTheory.Filtered.OfColimitCommutesFiniteLimit +import Mathlib.CategoryTheory.Functor.KanExtension.Adjunction +import Mathlib.CategoryTheory.Limits.FilteredColimitCommutesFiniteLimit +import Mathlib.CategoryTheory.Limits.Preserves.Grothendieck +import Mathlib.CategoryTheory.Limits.Final + +/-! +# Inferring Filteredness from Filteredness of Costructured Arrow Categories + +# References + +* [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Proposition 3.1.8 + +-/ + +universe w v₁ u₁ + +namespace CategoryTheory + +open Limits Functor + +variable {A : Type u₁} [SmallCategory A] {B : Type u₁} [SmallCategory B] +variable {T : Type u₁} [SmallCategory T] + +/-- Given functors `L : A ⥤ T` and `R : B ⥤ T` with a common codomain we can conclude that `A` +is filtered given that `R` is final, `B` is filtered and each costructured arrow category +`CostructuredArrow L (R.obj b)` is filtered. -/ +theorem isFiltered_of_isFiltered_costructuredArrow (L : A ⥤ T) (R : B ⥤ T) + [IsFiltered B] [Final R] [∀ b, IsFiltered (CostructuredArrow L (R.obj b))] : IsFiltered A := + isFiltered_of_nonempty_limit_colimit_to_colimit_limit fun J {_ _} F => ⟨by + let R' := Grothendieck.pre (CostructuredArrow.functor L) R + haveI : ∀ b, PreservesLimitsOfShape J + (colim (J := (R ⋙ CostructuredArrow.functor L).obj b) (C := Type u₁)) := fun b => by + simp only [comp_obj, CostructuredArrow.functor_obj, Cat.of_α] + exact filtered_colim_preservesFiniteLimits + refine lim.map ((colimitIsoColimitGrothendieck L F.flip).hom ≫ + (inv (colimit.pre (CostructuredArrow.grothendieckProj L ⋙ F.flip) R'))) ≫ + (colimitLimitIso (R' ⋙ CostructuredArrow.grothendieckProj L ⋙ F.flip).flip).inv ≫ + colim.map ?_ ≫ + colimit.pre _ R' ≫ + (colimitIsoColimitGrothendieck L (limit F)).inv + exact (limitCompWhiskeringLeftIsoCompLimit F (R' ⋙ CostructuredArrow.grothendieckProj L)).hom⟩ + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Filtered/OfColimitCommutesFiniteLimit.lean b/Mathlib/CategoryTheory/Filtered/OfColimitCommutesFiniteLimit.lean index 45baf017ad8b0..0a993d2e227e7 100644 --- a/Mathlib/CategoryTheory/Filtered/OfColimitCommutesFiniteLimit.lean +++ b/Mathlib/CategoryTheory/Filtered/OfColimitCommutesFiniteLimit.lean @@ -18,7 +18,7 @@ variable {K : Type v} [SmallCategory K] open Limits -/-- A converse to `colimitLimitIsoLimitColimit`: if colimits of shape `K` commute with finite +/-- A converse to `colimitLimitIso`: if colimits of shape `K` commute with finite limits, then `K` is filtered. -/ theorem isFiltered_of_nonempty_limit_colimit_to_colimit_limit (h : ∀ {J : Type v} [SmallCategory J] [FinCategory J] (F : J ⥤ K ⥤ Type v), diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Grothendieck.lean b/Mathlib/CategoryTheory/Limits/Preserves/Grothendieck.lean new file mode 100644 index 0000000000000..c3504b261f99f --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Preserves/Grothendieck.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2024 Jakob von Raumer. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jakob von Raumer +-/ +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic +import Mathlib.CategoryTheory.Limits.Shapes.Grothendieck + +/-! +# Colimits on Grothendieck constructions preserving limits + +We characterize the condition in which colimits on Grothendieck constructions preserve limits: By +preserving limits on the Grothendieck construction's base category as well as on each of its fibers. +-/ + + +universe v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄ + +namespace CategoryTheory + +namespace Limits + +noncomputable section + +variable {C : Type u₁} [Category.{v₁} C] +variable {H : Type u₂} [Category.{v₂} H] +variable {J : Type u₃} [Category.{v₃} J] +variable {F : C ⥤ Cat.{v₄, u₄}} + +/-- If `colim` on each fiber `F.obj c` of a functor `F : C ⥤ Cat` preserves limits of shape `J`, +then the fiberwise colimit of the limit of a functor `K : J ⥤ Grothendieck F ⥤ H` is naturally +isomorphic to taking the limit of the composition `K ⋙ fiberwiseColim F H`. -/ +@[simps!] +def fiberwiseColimitLimitIso (K : J ⥤ Grothendieck F ⥤ H) + [∀ (c : C), HasColimitsOfShape (↑(F.obj c)) H] [HasLimitsOfShape J H] + [∀ c, PreservesLimitsOfShape J (colim (J := F.obj c) (C := H))] : + fiberwiseColimit (limit K) ≅ limit (K ⋙ fiberwiseColim F H) := + NatIso.ofComponents + (fun c => HasColimit.isoOfNatIso + (limitCompWhiskeringLeftIsoCompLimit K (Grothendieck.ι F c)).symm ≪≫ + preservesLimitIso colim _ ≪≫ + HasLimit.isoOfNatIso + (Functor.associator _ _ _ ≪≫ + isoWhiskerLeft _ (fiberwiseColimCompEvaluationIso _).symm ≪≫ + (Functor.associator _ _ _).symm) ≪≫ + (limitObjIsoLimitCompEvaluation _ c).symm) + fun {c₁ c₂} f => by + simp only [fiberwiseColimit_obj, fiberwiseColimit_map, Iso.trans_hom, Iso.symm_hom, + Category.assoc, limitObjIsoLimitCompEvaluation_inv_limit_map] + apply colimit.hom_ext + intro d + simp only [← Category.assoc] + congr 1 + apply limit.hom_ext + intro e + simp [← NatTrans.comp_app_assoc] + +variable (C) (F) in +/-- If `colim` on a category `C` preserves limits of shape `J` and if it does so for `colim` on +every `F.obj c` for a functor `F : C ⥤ Cat`, then `colim` on `Grothendieck F` also preserves limits +of shape `J`. -/ +instance preservesLimitsOfShape_colim_grothendieck [HasColimitsOfShape C H] [HasLimitsOfShape J H] + [∀ c, HasColimitsOfShape (↑(F.obj c)) H] [PreservesLimitsOfShape J (colim (J := C) (C := H))] + [∀ c, PreservesLimitsOfShape J (colim (J := F.obj c) (C := H))] : + PreservesLimitsOfShape J (colim (J := Grothendieck F) (C := H)) := by + constructor + intro K + let i₂ := calc colimit (limit K) + _ ≅ colimit (fiberwiseColimit (limit K)) := (colimitFiberwiseColimitIso _).symm + _ ≅ colimit (limit (K ⋙ fiberwiseColim _ _)) := + HasColimit.isoOfNatIso (fiberwiseColimitLimitIso _) + _ ≅ limit ((K ⋙ fiberwiseColim _ _) ⋙ colim) := + preservesLimitIso colim (K ⋙ fiberwiseColim _ _) + _ ≅ limit (K ⋙ colim) := + HasLimit.isoOfNatIso + (Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ fiberwiseColimCompColimIso) + haveI : IsIso (limit.post K colim) := by + convert Iso.isIso_hom i₂ + ext + simp only [colim_obj, Functor.comp_obj, limit.post_π, colim_map, Iso.instTransIso_trans, + Iso.trans_assoc, Iso.trans_hom, Category.assoc, HasLimit.isoOfNatIso_hom_π, + fiberwiseColim_obj, isoWhiskerLeft_hom, NatTrans.comp_app, Functor.associator_hom_app, + whiskerLeft_app, fiberwiseColimCompColimIso_hom_app, Category.id_comp, + preservesLimitIso_hom_π_assoc, i₂] + ext + simp only [ι_colimMap, Trans.trans, Iso.symm_hom, ι_colimitFiberwiseColimitIso_inv_assoc, + HasColimit.isoOfNatIso_ι_hom_assoc, fiberwiseColimit_obj, fiberwiseColimitLimitIso_hom_app, + ι_colimMap_assoc, Category.assoc, limitObjIsoLimitCompEvaluation_inv_π_app_assoc, + Functor.comp_obj, fiberwiseColim_obj, HasLimit.isoOfNatIso_hom_π_assoc, + whiskeringLeft_obj_obj, colim_obj, evaluation_obj_obj, Iso.trans_hom, isoWhiskerLeft_hom, + NatTrans.comp_app, Functor.associator_hom_app, whiskerLeft_app, + fiberwiseColimCompEvaluationIso_inv_app, Functor.associator_inv_app, Category.comp_id, + Category.id_comp, preservesLimitIso_hom_π_assoc, colim_map, Grothendieck.ι_obj, + ι_colimitFiberwiseColimitIso_hom] + simp [← Category.assoc, ← NatTrans.comp_app] + apply preservesLimit_of_isIso_post + +end + +end Limits + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Grothendieck.lean b/Mathlib/CategoryTheory/Limits/Shapes/Grothendieck.lean index ff2c149902ac8..6e478aa734361 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Grothendieck.lean @@ -75,6 +75,18 @@ def fiberwiseColimit : C ⥤ H where conv_rhs => enter [2, 1]; rw [eqToHom_map (F.map (𝟙 Z))] conv_rhs => rw [eqToHom_trans, eqToHom_trans] +variable (H) (F) in +/-- Similar to `colimit` and `colim`, taking fiberwise colimits is a functor +`(Grothendieck F ⥤ H) ⥤ (C ⥤ H)` between functor categories. -/ +@[simps] +def fiberwiseColim [∀ c, HasColimitsOfShape (F.obj c) H] : (Grothendieck F ⥤ H) ⥤ (C ⥤ H) where + obj G := fiberwiseColimit G + map α := + { app := fun c => colim.map (whiskerLeft _ α) + naturality := fun c₁ c₂ f => by apply colimit.hom_ext; simp } + map_id G := by ext; simp; apply Functor.map_id colim + map_comp α β := by ext; simp; apply Functor.map_comp colim + /-- Every functor `G : Grothendieck F ⥤ H` induces a natural transformation from `G` to the composition of the forgetful functor on `Grothendieck F` with the fiberwise colimit on `G`. -/ @[simps] @@ -111,9 +123,9 @@ def isColimitCoconeFiberwiseColimitOfCocone {c : Cocone G} (hc : IsColimit c) : uniq s m hm := hc.hom_ext fun X => by have := hm X.base simp only [Functor.const_obj_obj, IsColimit.fac, NatTrans.comp_app, Functor.comp_obj, - Grothendieck.forget_obj, fiberwiseColimit_obj, natTransIntoForgetCompFiberwiseColimit_app, + Grothendieck.forget_obj, fiberwiseColim_obj, natTransIntoForgetCompFiberwiseColimit_app, whiskerLeft_app] - simp only [fiberwiseColimit_obj, coconeFiberwiseColimitOfCocone_pt, Functor.const_obj_obj, + simp only [fiberwiseColim_obj, coconeFiberwiseColimitOfCocone_pt, Functor.const_obj_obj, coconeFiberwiseColimitOfCocone_ι_app] at this simp [← this] @@ -131,9 +143,9 @@ def coconeOfCoconeFiberwiseColimit (c : Cocone (fiberwiseColimit G)) : Cocone G naturality := fun {X Y} ⟨f, g⟩ => by simp only [Functor.const_obj_obj, Functor.const_obj_map, Category.comp_id] rw [← Category.assoc, ← c.w f, ← Category.assoc] - simp only [fiberwiseColimit_obj, fiberwiseColimit_map, ι_colimMap_assoc, Functor.comp_obj, - Grothendieck.ι_obj, NatTrans.comp_app, whiskerRight_app, Functor.associator_hom_app, - Category.comp_id, colimit.ι_pre] + simp only [fiberwiseColimit_obj, fiberwiseColimit_map, ι_colimMap_assoc, + Functor.comp_obj, Grothendieck.ι_obj, NatTrans.comp_app, whiskerRight_app, + Functor.associator_hom_app, Category.comp_id, colimit.ι_pre] rw [← colimit.w _ g, ← Category.assoc, Functor.comp_map, ← G.map_comp] congr <;> simp } @@ -180,7 +192,8 @@ lemma ι_colimitFiberwiseColimitIso_hom (X : C) (d : F.obj X) : @[reassoc (attr := simp)] lemma ι_colimitFiberwiseColimitIso_inv (X : Grothendieck F) : colimit.ι G X ≫ (colimitFiberwiseColimitIso G).inv = - colimit.ι (Grothendieck.ι F X.base ⋙ G) X.fiber ≫ colimit.ι (fiberwiseColimit G) X.base := by + colimit.ι (Grothendieck.ι F X.base ⋙ G) X.fiber ≫ + colimit.ι (fiberwiseColimit G) X.base := by rw [Iso.comp_inv_eq] simp @@ -191,6 +204,27 @@ theorem hasColimitsOfShape_grothendieck [∀ X, HasColimitsOfShape (F.obj X) H] [HasColimitsOfShape C H] : HasColimitsOfShape (Grothendieck F) H where has_colimit _ := hasColimit_of_hasColimit_fiberwiseColimit_of_hasColimit _ +noncomputable section FiberwiseColim + +variable [∀ (c : C), HasColimitsOfShape (↑(F.obj c)) H] [HasColimitsOfShape C H] + +/-- The isomorphism `colimitFiberwiseColimitIso` induces an isomorphism of functors `(J ⥤ C) ⥤ C` +between `fiberwiseColim F H ⋙ colim` and `colim`. -/ +@[simps!] +def fiberwiseColimCompColimIso : fiberwiseColim F H ⋙ colim ≅ colim := + NatIso.ofComponents (fun G => colimitFiberwiseColimitIso G) + fun _ => by (iterate 2 apply colimit.hom_ext; intro); simp + +/-- Composing `fiberwiseColim F H` with the evaluation functor `(evaluation C H).obj c` is +naturally isomorphic to precomposing the Grothendieck inclusion `Grothendieck.ι` to `colim`. -/ +@[simps!] +def fiberwiseColimCompEvaluationIso (c : C) : + fiberwiseColim F H ⋙ (evaluation C H).obj c ≅ + (whiskeringLeft _ _ _).obj (Grothendieck.ι F c) ⋙ colim := + Iso.refl _ + +end FiberwiseColim + end Limits end CategoryTheory From 23742102c631f65f72a472ba7244f6ef15f12114 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Sun, 19 Jan 2025 11:52:11 +0000 Subject: [PATCH 305/681] feat: remove `UniqueDiffWithinAt` assumptions for one-dimensional derivative (#20816) A point in a subset of a field is either a point of unique differentials, or isolated. In both cases, there is a definite value for the derivative of a map (its unique derivative in the former case, zero in the latter case). This means there is no choice involved, contrary to what happens in higher dimension. This remark means we can remove many `UniqueDiffWithinAt` assumptions in one-dimensional settings. --- Mathlib/Analysis/Calculus/Deriv/Add.lean | 59 ++++++++----- Mathlib/Analysis/Calculus/Deriv/Comp.lean | 37 ++++---- Mathlib/Analysis/Calculus/Deriv/Inv.lean | 17 ++-- Mathlib/Analysis/Calculus/Deriv/Mul.lean | 88 +++++++++++-------- Mathlib/Analysis/Calculus/Deriv/Pow.lean | 8 +- Mathlib/Analysis/Calculus/Deriv/Prod.lean | 10 ++- Mathlib/Analysis/Calculus/Deriv/Star.lean | 8 +- .../Analysis/Calculus/IteratedDeriv/Defs.lean | 38 ++++---- .../Calculus/IteratedDeriv/Lemmas.lean | 63 +++++++------ Mathlib/Analysis/Calculus/Taylor.lean | 12 +-- 10 files changed, 198 insertions(+), 142 deletions(-) diff --git a/Mathlib/Analysis/Calculus/Deriv/Add.lean b/Mathlib/Analysis/Calculus/Deriv/Add.lean index 3d6b994ca666b..d5ed6db3ab4cd 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Add.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Add.lean @@ -52,10 +52,12 @@ nonrec theorem HasDerivAt.add (hf : HasDerivAt f f' x) (hg : HasDerivAt g g' x) HasDerivAt (fun x => f x + g x) (f' + g') x := hf.add hg -theorem derivWithin_add (hxs : UniqueDiffWithinAt 𝕜 s x) (hf : DifferentiableWithinAt 𝕜 f s x) +theorem derivWithin_add (hf : DifferentiableWithinAt 𝕜 f s x) (hg : DifferentiableWithinAt 𝕜 g s x) : - derivWithin (fun y => f y + g y) s x = derivWithin f s x + derivWithin g s x := - (hf.hasDerivWithinAt.add hg.hasDerivWithinAt).derivWithin hxs + derivWithin (fun y => f y + g y) s x = derivWithin f s x + derivWithin g s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hf.hasDerivWithinAt.add hg.hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[simp] theorem deriv_add (hf : DifferentiableAt 𝕜 f x) (hg : DifferentiableAt 𝕜 g x) : @@ -78,9 +80,11 @@ nonrec theorem HasDerivAt.add_const (hf : HasDerivAt f f' x) (c : F) : HasDerivAt (fun x => f x + c) f' x := hf.add_const c -theorem derivWithin_add_const (hxs : UniqueDiffWithinAt 𝕜 s x) (c : F) : +theorem derivWithin_add_const (c : F) : derivWithin (fun y => f y + c) s x = derivWithin f s x := by - simp only [derivWithin, fderivWithin_add_const hxs] + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · simp only [derivWithin, fderivWithin_add_const hxs] + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_add_const (c : F) : deriv (fun y => f y + c) x = deriv f x := by simp only [deriv, fderiv_add_const] @@ -105,9 +109,11 @@ nonrec theorem HasDerivAt.const_add (c : F) (hf : HasDerivAt f f' x) : HasDerivAt (fun x => c + f x) f' x := hf.const_add c -theorem derivWithin_const_add (hxs : UniqueDiffWithinAt 𝕜 s x) (c : F) : +theorem derivWithin_const_add (c : F) : derivWithin (fun y => c + f y) s x = derivWithin f s x := by - simp only [derivWithin, fderivWithin_const_add hxs] + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · simp only [derivWithin, fderivWithin_const_add hxs] + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_const_add (c : F) : deriv (fun y => c + f y) x = deriv f x := by simp only [deriv, fderiv_const_add] @@ -160,10 +166,11 @@ theorem HasDerivAt.sum (h : ∀ i ∈ u, HasDerivAt (A i) (A' i) x) : HasDerivAt (fun y => ∑ i ∈ u, A i y) (∑ i ∈ u, A' i) x := HasDerivAtFilter.sum h -theorem derivWithin_sum (hxs : UniqueDiffWithinAt 𝕜 s x) - (h : ∀ i ∈ u, DifferentiableWithinAt 𝕜 (A i) s x) : - derivWithin (fun y => ∑ i ∈ u, A i y) s x = ∑ i ∈ u, derivWithin (A i) s x := - (HasDerivWithinAt.sum fun i hi => (h i hi).hasDerivWithinAt).derivWithin hxs +theorem derivWithin_sum (h : ∀ i ∈ u, DifferentiableWithinAt 𝕜 (A i) s x) : + derivWithin (fun y => ∑ i ∈ u, A i y) s x = ∑ i ∈ u, derivWithin (A i) s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (HasDerivWithinAt.sum fun i hi => (h i hi).hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[simp] theorem deriv_sum (h : ∀ i ∈ u, DifferentiableAt 𝕜 (A i) x) : @@ -189,9 +196,10 @@ nonrec theorem HasDerivAt.neg (h : HasDerivAt f f' x) : HasDerivAt (fun x => -f nonrec theorem HasStrictDerivAt.neg (h : HasStrictDerivAt f f' x) : HasStrictDerivAt (fun x => -f x) (-f') x := by simpa using h.neg.hasStrictDerivAt -theorem derivWithin.neg (hxs : UniqueDiffWithinAt 𝕜 s x) : - derivWithin (fun y => -f y) s x = -derivWithin f s x := by - simp only [derivWithin, fderivWithin_neg hxs, ContinuousLinearMap.neg_apply] +theorem derivWithin.neg : derivWithin (fun y => -f y) s x = -derivWithin f s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · simp only [derivWithin, fderivWithin_neg hxs, ContinuousLinearMap.neg_apply] + · simp [derivWithin_zero_of_isolated hxs] theorem deriv.neg : deriv (fun y => -f y) x = -deriv f x := by simp only [deriv, fderiv_neg, ContinuousLinearMap.neg_apply] @@ -276,10 +284,12 @@ theorem HasStrictDerivAt.sub (hf : HasStrictDerivAt f f' x) (hg : HasStrictDeriv HasStrictDerivAt (fun x => f x - g x) (f' - g') x := by simpa only [sub_eq_add_neg] using hf.add hg.neg -theorem derivWithin_sub (hxs : UniqueDiffWithinAt 𝕜 s x) (hf : DifferentiableWithinAt 𝕜 f s x) +theorem derivWithin_sub (hf : DifferentiableWithinAt 𝕜 f s x) (hg : DifferentiableWithinAt 𝕜 g s x) : - derivWithin (fun y => f y - g y) s x = derivWithin f s x - derivWithin g s x := - (hf.hasDerivWithinAt.sub hg.hasDerivWithinAt).derivWithin hxs + derivWithin (fun y => f y - g y) s x = derivWithin f s x - derivWithin g s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hf.hasDerivWithinAt.sub hg.hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[simp] theorem deriv_sub (hf : DifferentiableAt 𝕜 f x) (hg : DifferentiableAt 𝕜 g x) : @@ -298,9 +308,11 @@ nonrec theorem HasDerivAt.sub_const (hf : HasDerivAt f f' x) (c : F) : HasDerivAt (fun x => f x - c) f' x := hf.sub_const c -theorem derivWithin_sub_const (hxs : UniqueDiffWithinAt 𝕜 s x) (c : F) : +theorem derivWithin_sub_const (c : F) : derivWithin (fun y => f y - c) s x = derivWithin f s x := by - simp only [derivWithin, fderivWithin_sub_const hxs] + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · simp only [derivWithin, fderivWithin_sub_const hxs] + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_sub_const (c : F) : deriv (fun y => f y - c) x = deriv f x := by simp only [deriv, fderiv_sub_const] @@ -321,13 +333,14 @@ nonrec theorem HasDerivAt.const_sub (c : F) (hf : HasDerivAt f f' x) : HasDerivAt (fun x => c - f x) (-f') x := hf.const_sub c -theorem derivWithin_const_sub (hxs : UniqueDiffWithinAt 𝕜 s x) (c : F) : +theorem derivWithin_const_sub (c : F) : derivWithin (fun y => c - f y) s x = -derivWithin f s x := by - simp [derivWithin, fderivWithin_const_sub hxs] + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · simp [derivWithin, fderivWithin_const_sub hxs] + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_const_sub (c : F) : deriv (fun y => c - f y) x = -deriv f x := by - simp only [← derivWithin_univ, - derivWithin_const_sub (uniqueDiffWithinAt_univ : UniqueDiffWithinAt 𝕜 _ _)] + simp only [← derivWithin_univ, derivWithin_const_sub] lemma differentiableAt_comp_sub_const {a b : 𝕜} : DifferentiableAt 𝕜 (fun x ↦ f (x - b)) a ↔ DifferentiableAt 𝕜 f (a - b) := by diff --git a/Mathlib/Analysis/Calculus/Deriv/Comp.lean b/Mathlib/Analysis/Calculus/Deriv/Comp.lean index 015bd0a24acb8..b8fe2a15b8dee 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Comp.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Comp.lean @@ -127,15 +127,17 @@ theorem HasDerivAt.scomp_hasDerivWithinAt_of_eq (hg : HasDerivAt g₁ g₁' y) rw [hy] at hg; exact hg.scomp_hasDerivWithinAt x hh theorem derivWithin.scomp (hg : DifferentiableWithinAt 𝕜' g₁ t' (h x)) - (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s t') (hxs : UniqueDiffWithinAt 𝕜 s x) : - derivWithin (g₁ ∘ h) s x = derivWithin h s x • derivWithin g₁ t' (h x) := - (HasDerivWithinAt.scomp x hg.hasDerivWithinAt hh.hasDerivWithinAt hs).derivWithin hxs + (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s t') : + derivWithin (g₁ ∘ h) s x = derivWithin h s x • derivWithin g₁ t' (h x) := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (HasDerivWithinAt.scomp x hg.hasDerivWithinAt hh.hasDerivWithinAt hs).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem derivWithin.scomp_of_eq (hg : DifferentiableWithinAt 𝕜' g₁ t' y) - (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s t') (hxs : UniqueDiffWithinAt 𝕜 s x) + (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s t') (hy : y = h x) : derivWithin (g₁ ∘ h) s x = derivWithin h s x • derivWithin g₁ t' (h x) := by - rw [hy] at hg; exact derivWithin.scomp x hg hh hs hxs + rw [hy] at hg; exact derivWithin.scomp x hg hh hs theorem deriv.scomp (hg : DifferentiableAt 𝕜' g₁ (h x)) (hh : DifferentiableAt 𝕜 h x) : deriv (g₁ ∘ h) x = deriv h x • deriv g₁ (h x) := @@ -265,17 +267,19 @@ theorem HasDerivAt.comp_hasDerivWithinAt_of_eq (hh₂ : HasDerivAt h₂ h₂' y) rw [hy] at hh₂; exact hh₂.comp_hasDerivWithinAt x hh theorem derivWithin_comp (hh₂ : DifferentiableWithinAt 𝕜' h₂ s' (h x)) - (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s s') (hxs : UniqueDiffWithinAt 𝕜 s x) : - derivWithin (h₂ ∘ h) s x = derivWithin h₂ s' (h x) * derivWithin h s x := - (hh₂.hasDerivWithinAt.comp x hh.hasDerivWithinAt hs).derivWithin hxs + (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s s') : + derivWithin (h₂ ∘ h) s x = derivWithin h₂ s' (h x) * derivWithin h s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hh₂.hasDerivWithinAt.comp x hh.hasDerivWithinAt hs).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[deprecated (since := "2024-10-31")] alias derivWithin.comp := derivWithin_comp theorem derivWithin_comp_of_eq (hh₂ : DifferentiableWithinAt 𝕜' h₂ s' y) - (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s s') (hxs : UniqueDiffWithinAt 𝕜 s x) + (hh : DifferentiableWithinAt 𝕜 h s x) (hs : MapsTo h s s') (hy : h x = y) : derivWithin (h₂ ∘ h) s x = derivWithin h₂ s' (h x) * derivWithin h s x := by - subst hy; exact derivWithin_comp x hh₂ hh hs hxs + subst hy; exact derivWithin_comp x hh₂ hh hs @[deprecated (since := "2024-10-31")] alias derivWithin.comp_of_eq := derivWithin_comp_of_eq @@ -373,18 +377,19 @@ theorem HasStrictFDerivAt.comp_hasStrictDerivAt_of_eq (hl : HasStrictFDerivAt l rw [hy] at hl; exact hl.comp_hasStrictDerivAt x hf theorem fderivWithin_comp_derivWithin {t : Set F} (hl : DifferentiableWithinAt 𝕜 l t (f x)) - (hf : DifferentiableWithinAt 𝕜 f s x) (hs : MapsTo f s t) (hxs : UniqueDiffWithinAt 𝕜 s x) : - derivWithin (l ∘ f) s x = (fderivWithin 𝕜 l t (f x) : F → E) (derivWithin f s x) := - (hl.hasFDerivWithinAt.comp_hasDerivWithinAt x hf.hasDerivWithinAt hs).derivWithin hxs + (hf : DifferentiableWithinAt 𝕜 f s x) (hs : MapsTo f s t) : + derivWithin (l ∘ f) s x = (fderivWithin 𝕜 l t (f x) : F → E) (derivWithin f s x) := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hl.hasFDerivWithinAt.comp_hasDerivWithinAt x hf.hasDerivWithinAt hs).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[deprecated (since := "2024-10-31")] alias fderivWithin.comp_derivWithin := fderivWithin_comp_derivWithin theorem fderivWithin_comp_derivWithin_of_eq {t : Set F} (hl : DifferentiableWithinAt 𝕜 l t y) - (hf : DifferentiableWithinAt 𝕜 f s x) (hs : MapsTo f s t) (hxs : UniqueDiffWithinAt 𝕜 s x) - (hy : y = f x) : + (hf : DifferentiableWithinAt 𝕜 f s x) (hs : MapsTo f s t) (hy : y = f x) : derivWithin (l ∘ f) s x = (fderivWithin 𝕜 l t (f x) : F → E) (derivWithin f s x) := by - rw [hy] at hl; exact fderivWithin_comp_derivWithin x hl hf hs hxs + rw [hy] at hl; exact fderivWithin_comp_derivWithin x hl hf hs @[deprecated (since := "2024-10-31")] alias fderivWithin.comp_derivWithin_of_eq := fderivWithin_comp_derivWithin_of_eq diff --git a/Mathlib/Analysis/Calculus/Deriv/Inv.lean b/Mathlib/Analysis/Calculus/Deriv/Inv.lean index 082c6d0c809ed..605b8d06e2e87 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Inv.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Inv.lean @@ -106,10 +106,11 @@ theorem HasDerivAt.inv (hc : HasDerivAt c c' x) (hx : c x ≠ 0) : rw [← hasDerivWithinAt_univ] at * exact hc.inv hx -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 := - (hc.hasDerivWithinAt.inv hx).derivWithin hxs +theorem derivWithin_inv' (hc : DifferentiableWithinAt 𝕜 c s x) (hx : c x ≠ 0) : + derivWithin (fun x => (c x)⁻¹) s x = -derivWithin c s x / c x ^ 2 := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.inv hx).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[simp] theorem deriv_inv'' (hc : DifferentiableAt 𝕜 c x) (hx : c x ≠ 0) : @@ -163,10 +164,12 @@ theorem Differentiable.div (hc : Differentiable 𝕜 c) (hd : Differentiable Differentiable 𝕜 fun x => c x / d x := fun x => (hc x).div (hd x) (hx x) theorem derivWithin_div (hc : DifferentiableWithinAt 𝕜 c s x) (hd : DifferentiableWithinAt 𝕜 d s x) - (hx : d x ≠ 0) (hxs : UniqueDiffWithinAt 𝕜 s x) : + (hx : d x ≠ 0) : derivWithin (fun x => c x / d x) s x = - (derivWithin c s x * d x - c x * derivWithin d s x) / d x ^ 2 := - (hc.hasDerivWithinAt.div hd.hasDerivWithinAt hx).derivWithin hxs + (derivWithin c s x * d x - c x * derivWithin d s x) / d x ^ 2 := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.div hd.hasDerivWithinAt hx).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[simp] theorem deriv_div (hc : DifferentiableAt 𝕜 c x) (hd : DifferentiableAt 𝕜 d x) (hx : d x ≠ 0) : diff --git a/Mathlib/Analysis/Calculus/Deriv/Mul.lean b/Mathlib/Analysis/Calculus/Deriv/Mul.lean index b7b58303ed4e3..b97172a75dda6 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Mul.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Mul.lean @@ -61,11 +61,13 @@ theorem hasStrictDerivAt_of_bilinear (hu : HasStrictDerivAt u u' x) (hv : HasStr simpa using (B.hasStrictFDerivAt_of_bilinear hu.hasStrictFDerivAt hv.hasStrictFDerivAt).hasStrictDerivAt -theorem derivWithin_of_bilinear (hxs : UniqueDiffWithinAt 𝕜 s x) +theorem derivWithin_of_bilinear (hu : DifferentiableWithinAt 𝕜 u s x) (hv : DifferentiableWithinAt 𝕜 v s x) : derivWithin (fun y => B (u y) (v y)) s x = - B (u x) (derivWithin v s x) + B (derivWithin u s x) (v x) := - (B.hasDerivWithinAt_of_bilinear hu.hasDerivWithinAt hv.hasDerivWithinAt).derivWithin hxs + B (u x) (derivWithin v s x) + B (derivWithin u s x) (v x) := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (B.hasDerivWithinAt_of_bilinear hu.hasDerivWithinAt hv.hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_of_bilinear (hu : DifferentiableAt 𝕜 u x) (hv : DifferentiableAt 𝕜 v x) : deriv (fun y => B (u y) (v y)) x = B (u x) (deriv v x) + B (deriv u x) (v x) := @@ -94,10 +96,12 @@ nonrec theorem HasStrictDerivAt.smul (hc : HasStrictDerivAt c c' x) (hf : HasStr HasStrictDerivAt (fun y => c y • f y) (c x • f' + c' • f x) x := by simpa using (hc.smul hf).hasStrictDerivAt -theorem derivWithin_smul (hxs : UniqueDiffWithinAt 𝕜 s x) (hc : DifferentiableWithinAt 𝕜 c s x) +theorem derivWithin_smul (hc : DifferentiableWithinAt 𝕜 c s x) (hf : DifferentiableWithinAt 𝕜 f s x) : - derivWithin (fun y => c y • f y) s x = c x • derivWithin f s x + derivWithin c s x • f x := - (hc.hasDerivWithinAt.smul hf.hasDerivWithinAt).derivWithin hxs + derivWithin (fun y => c y • f y) s x = c x • derivWithin f s x + derivWithin c s x • f x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.smul hf.hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_smul (hc : DifferentiableAt 𝕜 c x) (hf : DifferentiableAt 𝕜 f x) : deriv (fun y => c y • f y) x = c x • deriv f x + deriv c x • f x := @@ -118,10 +122,11 @@ theorem HasDerivAt.smul_const (hc : HasDerivAt c c' x) (f : F) : rw [← hasDerivWithinAt_univ] at * exact hc.smul_const f -theorem derivWithin_smul_const (hxs : UniqueDiffWithinAt 𝕜 s x) - (hc : DifferentiableWithinAt 𝕜 c s x) (f : F) : - derivWithin (fun y => c y • f) s x = derivWithin c s x • f := - (hc.hasDerivWithinAt.smul_const f).derivWithin hxs +theorem derivWithin_smul_const (hc : DifferentiableWithinAt 𝕜 c s x) (f : F) : + derivWithin (fun y => c y • f) s x = derivWithin c s x • f := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.smul_const f).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_smul_const (hc : DifferentiableAt 𝕜 c x) (f : F) : deriv (fun y => c y • f) x = deriv c x • f := @@ -149,10 +154,11 @@ nonrec theorem HasDerivAt.const_smul (c : R) (hf : HasDerivAt f f' x) : HasDerivAt (fun y => c • f y) (c • f') x := hf.const_smul c -theorem derivWithin_const_smul (hxs : UniqueDiffWithinAt 𝕜 s x) (c : R) - (hf : DifferentiableWithinAt 𝕜 f s x) : - derivWithin (fun y => c • f y) s x = c • derivWithin f s x := - (hf.hasDerivWithinAt.const_smul c).derivWithin hxs +theorem derivWithin_const_smul (c : R) (hf : DifferentiableWithinAt 𝕜 f s x) : + derivWithin (fun y => c • f y) s x = c • derivWithin f s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hf.hasDerivWithinAt.const_smul c).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_const_smul (c : R) (hf : DifferentiableAt 𝕜 f x) : deriv (fun y => c • f y) x = c • deriv f x := @@ -204,10 +210,12 @@ theorem HasStrictDerivAt.mul (hc : HasStrictDerivAt c c' x) (hd : HasStrictDeriv ContinuousLinearMap.smulRight_apply, ContinuousLinearMap.one_apply, one_smul, one_smul, add_comm] at this -theorem derivWithin_mul (hxs : UniqueDiffWithinAt 𝕜 s x) (hc : DifferentiableWithinAt 𝕜 c s x) +theorem derivWithin_mul (hc : DifferentiableWithinAt 𝕜 c s x) (hd : DifferentiableWithinAt 𝕜 d s x) : - derivWithin (fun y => c y * d y) s x = derivWithin c s x * d x + c x * derivWithin d s x := - (hc.hasDerivWithinAt.mul hd.hasDerivWithinAt).derivWithin hxs + derivWithin (fun y => c y * d y) s x = derivWithin c s x * d x + c x * derivWithin d s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.mul hd.hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[simp] theorem deriv_mul (hc : DifferentiableAt 𝕜 c x) (hd : DifferentiableAt 𝕜 d x) : @@ -232,9 +240,11 @@ theorem HasStrictDerivAt.mul_const (hc : HasStrictDerivAt c c' x) (d : 𝔸) : convert hc.mul (hasStrictDerivAt_const x d) using 1 rw [mul_zero, add_zero] -theorem derivWithin_mul_const (hxs : UniqueDiffWithinAt 𝕜 s x) (hc : DifferentiableWithinAt 𝕜 c s x) - (d : 𝔸) : derivWithin (fun y => c y * d) s x = derivWithin c s x * d := - (hc.hasDerivWithinAt.mul_const d).derivWithin hxs +theorem derivWithin_mul_const (hc : DifferentiableWithinAt 𝕜 c s x) (d : 𝔸) : + derivWithin (fun y => c y * d) s x = derivWithin c s x * d := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.mul_const d).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_mul_const (hc : DifferentiableAt 𝕜 c x) (d : 𝔸) : deriv (fun y => c y * d) x = deriv c x * d := @@ -268,10 +278,11 @@ theorem HasStrictDerivAt.const_mul (c : 𝔸) (hd : HasStrictDerivAt d d' x) : convert (hasStrictDerivAt_const _ _).mul hd using 1 rw [zero_mul, zero_add] -theorem derivWithin_const_mul (hxs : UniqueDiffWithinAt 𝕜 s x) (c : 𝔸) - (hd : DifferentiableWithinAt 𝕜 d s x) : - derivWithin (fun y => c * d y) s x = c * derivWithin d s x := - (hd.hasDerivWithinAt.const_mul c).derivWithin hxs +theorem derivWithin_const_mul (c : 𝔸) (hd : DifferentiableWithinAt 𝕜 d s x) : + derivWithin (fun y => c * d y) s x = c * derivWithin d s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hd.hasDerivWithinAt.const_mul c).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_const_mul (c : 𝔸) (hd : DifferentiableAt 𝕜 d x) : deriv (fun y => c * d y) x = c * deriv d x := @@ -312,11 +323,13 @@ theorem deriv_finset_prod (hf : ∀ i ∈ u, DifferentiableAt 𝕜 (f i) x) : deriv (∏ i ∈ u, f i ·) x = ∑ i ∈ u, (∏ j ∈ u.erase i, f j x) • deriv (f i) x := (HasDerivAt.finset_prod fun i hi ↦ (hf i hi).hasDerivAt).deriv -theorem derivWithin_finset_prod (hxs : UniqueDiffWithinAt 𝕜 s x) +theorem derivWithin_finset_prod (hf : ∀ i ∈ u, DifferentiableWithinAt 𝕜 (f i) s x) : derivWithin (∏ i ∈ u, f i ·) s x = - ∑ i ∈ u, (∏ j ∈ u.erase i, f j x) • derivWithin (f i) s x := - (HasDerivWithinAt.finset_prod fun i hi ↦ (hf i hi).hasDerivWithinAt).derivWithin hxs + ∑ i ∈ u, (∏ j ∈ u.erase i, f j x) • derivWithin (f i) s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (HasDerivWithinAt.finset_prod fun i hi ↦ (hf i hi).hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] end HasDeriv @@ -383,10 +396,9 @@ theorem DifferentiableOn.div_const (hc : DifferentiableOn 𝕜 c s) (d : 𝕜') theorem Differentiable.div_const (hc : Differentiable 𝕜 c) (d : 𝕜') : Differentiable 𝕜 fun x => c x / d := fun x => (hc x).div_const d -theorem derivWithin_div_const (hc : DifferentiableWithinAt 𝕜 c s x) - (d : 𝕜') (hxs : UniqueDiffWithinAt 𝕜 s x) : +theorem derivWithin_div_const (hc : DifferentiableWithinAt 𝕜 c s x) (d : 𝕜') : derivWithin (fun x => c x / d) s x = derivWithin c s x / d := by - simp [div_eq_inv_mul, derivWithin_const_mul, hc, hxs] + simp [div_eq_inv_mul, derivWithin_const_mul, hc] @[simp] theorem deriv_div_const (d : 𝕜') : deriv (fun x => c x / d) x = deriv c x / d := by @@ -423,10 +435,12 @@ theorem HasDerivAt.clm_comp (hc : HasDerivAt c c' x) (hd : HasDerivAt d d' x) : exact hc.clm_comp hd theorem derivWithin_clm_comp (hc : DifferentiableWithinAt 𝕜 c s x) - (hd : DifferentiableWithinAt 𝕜 d s x) (hxs : UniqueDiffWithinAt 𝕜 s x) : + (hd : DifferentiableWithinAt 𝕜 d s x) : derivWithin (fun y => (c y).comp (d y)) s x = - (derivWithin c s x).comp (d x) + (c x).comp (derivWithin d s x) := - (hc.hasDerivWithinAt.clm_comp hd.hasDerivWithinAt).derivWithin hxs + (derivWithin c s x).comp (d x) + (c x).comp (derivWithin d s x) := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.clm_comp hd.hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_clm_comp (hc : DifferentiableAt 𝕜 c x) (hd : DifferentiableAt 𝕜 d x) : deriv (fun y => (c y).comp (d y)) x = (deriv c x).comp (d x) + (c x).comp (deriv d x) := @@ -451,10 +465,12 @@ theorem HasDerivAt.clm_apply (hc : HasDerivAt c c' x) (hu : HasDerivAt u u' x) : rwa [add_apply, comp_apply, flip_apply, smulRight_apply, smulRight_apply, one_apply, one_smul, one_smul, add_comm] at this -theorem derivWithin_clm_apply (hxs : UniqueDiffWithinAt 𝕜 s x) (hc : DifferentiableWithinAt 𝕜 c s x) +theorem derivWithin_clm_apply (hc : DifferentiableWithinAt 𝕜 c s x) (hu : DifferentiableWithinAt 𝕜 u s x) : - derivWithin (fun y => (c y) (u y)) s x = derivWithin c s x (u x) + c x (derivWithin u s x) := - (hc.hasDerivWithinAt.clm_apply hu.hasDerivWithinAt).derivWithin hxs + derivWithin (fun y => (c y) (u y)) s x = derivWithin c s x (u x) + c x (derivWithin u s x) := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.clm_apply hu.hasDerivWithinAt).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] theorem deriv_clm_apply (hc : DifferentiableAt 𝕜 c x) (hu : DifferentiableAt 𝕜 u x) : deriv (fun y => (c y) (u y)) x = deriv c x (u x) + c x (deriv u x) := diff --git a/Mathlib/Analysis/Calculus/Deriv/Pow.lean b/Mathlib/Analysis/Calculus/Deriv/Pow.lean index 07f1c232737a5..e20d8811626b5 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Pow.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Pow.lean @@ -76,9 +76,11 @@ theorem HasDerivAt.pow (hc : HasDerivAt c c' x) : rw [← hasDerivWithinAt_univ] at * exact hc.pow n -theorem derivWithin_pow' (hc : DifferentiableWithinAt 𝕜 c s x) (hxs : UniqueDiffWithinAt 𝕜 s x) : - derivWithin (fun x => c x ^ n) s x = (n : 𝕜) * c x ^ (n - 1) * derivWithin c s x := - (hc.hasDerivWithinAt.pow n).derivWithin hxs +theorem derivWithin_pow' (hc : DifferentiableWithinAt 𝕜 c s x) : + derivWithin (fun x => c x ^ n) s x = (n : 𝕜) * c x ^ (n - 1) * derivWithin c s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hc.hasDerivWithinAt.pow n).derivWithin hxs + · simp [derivWithin_zero_of_isolated hxs] @[simp] theorem deriv_pow'' (hc : DifferentiableAt 𝕜 c x) : diff --git a/Mathlib/Analysis/Calculus/Deriv/Prod.lean b/Mathlib/Analysis/Calculus/Deriv/Prod.lean index a6a1adbcdb78d..caa6c11683543 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Prod.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Prod.lean @@ -78,10 +78,12 @@ theorem hasDerivWithinAt_pi : HasDerivWithinAt φ φ' s x ↔ ∀ i, HasDerivWithinAt (fun x => φ x i) (φ' i) s x := hasDerivAtFilter_pi -theorem derivWithin_pi (h : ∀ i, DifferentiableWithinAt 𝕜 (fun x => φ x i) s x) - (hs : UniqueDiffWithinAt 𝕜 s x) : - derivWithin φ s x = fun i => derivWithin (fun x => φ x i) s x := - (hasDerivWithinAt_pi.2 fun i => (h i).hasDerivWithinAt).derivWithin hs +theorem derivWithin_pi (h : ∀ i, DifferentiableWithinAt 𝕜 (fun x => φ x i) s x) : + derivWithin φ s x = fun i => derivWithin (fun x => φ x i) s x := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact (hasDerivWithinAt_pi.2 fun i => (h i).hasDerivWithinAt).derivWithin hxs + · simp only [derivWithin_zero_of_isolated hxs] + rfl theorem deriv_pi (h : ∀ i, DifferentiableAt 𝕜 (fun x => φ x i) x) : deriv φ x = fun i => deriv (fun x => φ x i) x := diff --git a/Mathlib/Analysis/Calculus/Deriv/Star.lean b/Mathlib/Analysis/Calculus/Deriv/Star.lean index 2b4e197ec1c94..636a850b2f0e1 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Star.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Star.lean @@ -41,9 +41,11 @@ protected nonrec theorem HasDerivAt.star (h : HasDerivAt f f' x) : protected nonrec theorem HasStrictDerivAt.star (h : HasStrictDerivAt f f' x) : HasStrictDerivAt (fun x => star (f x)) (star f') x := by simpa using h.star.hasStrictDerivAt -protected theorem derivWithin.star (hxs : UniqueDiffWithinAt 𝕜 s x) : - derivWithin (fun y => star (f y)) s x = star (derivWithin f s x) := - DFunLike.congr_fun (fderivWithin_star hxs) _ +protected theorem derivWithin.star : + derivWithin (fun y => star (f y)) s x = star (derivWithin f s x) := by + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · exact DFunLike.congr_fun (fderivWithin_star hxs) _ + · simp [derivWithin_zero_of_isolated hxs] protected theorem deriv.star : deriv (fun y => star (f y)) x = star (deriv f x) := DFunLike.congr_fun fderiv_star _ diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean index a013a881fc12f..bd390d2a8ebcb 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean @@ -102,9 +102,12 @@ theorem iteratedDerivWithin_zero : iteratedDerivWithin 0 f s = f := by simp [iteratedDerivWithin] @[simp] -theorem iteratedDerivWithin_one {x : 𝕜} (h : UniqueDiffWithinAt 𝕜 s x) : +theorem iteratedDerivWithin_one {x : 𝕜} : iteratedDerivWithin 1 f s x = derivWithin f s x := by - simp only [iteratedDerivWithin, iteratedFDerivWithin_one_apply h]; rfl + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · simp only [iteratedDerivWithin, iteratedFDerivWithin_one_apply hxs]; rfl + · simp [derivWithin_zero_of_isolated hxs, iteratedDerivWithin, iteratedFDerivWithin, + fderivWithin_zero_of_isolated hxs] /-- If the first `n` derivatives within a set of a function are continuous, and its first `n-1` derivatives are differentiable, then the function is `C^n`. This is not an equivalence in general, @@ -170,30 +173,33 @@ theorem contDiffOn_nat_iff_continuousOn_differentiableOn_deriv {n : ℕ} (hs : U /-- The `n+1`-th iterated derivative within a set with unique derivatives can be obtained by differentiating the `n`-th iterated derivative. -/ -theorem iteratedDerivWithin_succ {x : 𝕜} (hxs : UniqueDiffWithinAt 𝕜 s x) : +theorem iteratedDerivWithin_succ {x : 𝕜} : iteratedDerivWithin (n + 1) f s x = derivWithin (iteratedDerivWithin n f s) s x := by - rw [iteratedDerivWithin_eq_iteratedFDerivWithin, iteratedFDerivWithin_succ_apply_left, - iteratedFDerivWithin_eq_equiv_comp, LinearIsometryEquiv.comp_fderivWithin _ hxs, derivWithin] - change ((ContinuousMultilinearMap.mkPiRing 𝕜 (Fin n) ((fderivWithin 𝕜 - (iteratedDerivWithin n f s) s x : 𝕜 → F) 1) : (Fin n → 𝕜) → F) fun _ : Fin n => 1) = - (fderivWithin 𝕜 (iteratedDerivWithin n f s) s x : 𝕜 → F) 1 - simp + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs + · rw [iteratedDerivWithin_eq_iteratedFDerivWithin, iteratedFDerivWithin_succ_apply_left, + iteratedFDerivWithin_eq_equiv_comp, LinearIsometryEquiv.comp_fderivWithin _ hxs, derivWithin] + change ((ContinuousMultilinearMap.mkPiRing 𝕜 (Fin n) ((fderivWithin 𝕜 + (iteratedDerivWithin n f s) s x : 𝕜 → F) 1) : (Fin n → 𝕜) → F) fun _ : Fin n => 1) = + (fderivWithin 𝕜 (iteratedDerivWithin n f s) s x : 𝕜 → F) 1 + simp + · simp [derivWithin_zero_of_isolated hxs, iteratedDerivWithin, iteratedFDerivWithin, + fderivWithin_zero_of_isolated hxs] /-- The `n`-th iterated derivative within a set with unique derivatives can be obtained by iterating `n` times the differentiation operation. -/ -theorem iteratedDerivWithin_eq_iterate {x : 𝕜} (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) : +theorem iteratedDerivWithin_eq_iterate {x : 𝕜} : iteratedDerivWithin n f s x = (fun g : 𝕜 → F => derivWithin g s)^[n] f x := by induction n generalizing x with | zero => simp | succ n IH => - rw [iteratedDerivWithin_succ (hs x hx), Function.iterate_succ'] - exact derivWithin_congr (fun y hy => IH hy) (IH hx) + rw [iteratedDerivWithin_succ, Function.iterate_succ'] + exact derivWithin_congr (fun y hy => IH) IH /-- The `n+1`-th iterated derivative within a set with unique derivatives can be obtained by taking the `n`-th derivative of the derivative. -/ -theorem iteratedDerivWithin_succ' {x : 𝕜} (hxs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) : +theorem iteratedDerivWithin_succ' {x : 𝕜} : iteratedDerivWithin (n + 1) f s x = (iteratedDerivWithin n (derivWithin f s) s) x := by - rw [iteratedDerivWithin_eq_iterate hxs hx, iteratedDerivWithin_eq_iterate hxs hx]; rfl + rw [iteratedDerivWithin_eq_iterate, iteratedDerivWithin_eq_iterate]; rfl /-! ### Properties of the iterated derivative on the whole space -/ @@ -270,14 +276,14 @@ iterated derivative. -/ theorem iteratedDeriv_succ : iteratedDeriv (n + 1) f = deriv (iteratedDeriv n f) := by ext x rw [← iteratedDerivWithin_univ, ← iteratedDerivWithin_univ, ← derivWithin_univ] - exact iteratedDerivWithin_succ uniqueDiffWithinAt_univ + exact iteratedDerivWithin_succ /-- The `n`-th iterated derivative can be obtained by iterating `n` times the differentiation operation. -/ theorem iteratedDeriv_eq_iterate : iteratedDeriv n f = deriv^[n] f := by ext x rw [← iteratedDerivWithin_univ] - convert iteratedDerivWithin_eq_iterate uniqueDiffOn_univ (F := F) (mem_univ x) + convert iteratedDerivWithin_eq_iterate (F := F) simp [derivWithin_univ] /-- The `n+1`-th iterated derivative can be obtained by taking the `n`-th derivative of the diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean index 01f21bd7293eb..fb639723208c3 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean @@ -24,7 +24,6 @@ variable {n : ℕ} {x : 𝕜} {s : Set 𝕜} (hx : x ∈ s) (h : UniqueDiffOn 𝕜 s) {f g : 𝕜 → F} section -include h theorem iteratedDerivWithin_congr (hfg : Set.EqOn f g s) : Set.EqOn (iteratedDerivWithin n f s) (iteratedDerivWithin n g s) s := by @@ -32,12 +31,10 @@ theorem iteratedDerivWithin_congr (hfg : Set.EqOn f g s) : | zero => rwa [iteratedDerivWithin_zero] | succ n IH => intro y hy - have : UniqueDiffWithinAt 𝕜 s y := h.uniqueDiffWithinAt hy - rw [iteratedDerivWithin_succ this, iteratedDerivWithin_succ this] + rw [iteratedDerivWithin_succ, iteratedDerivWithin_succ] exact derivWithin_congr (IH hfg) (IH hfg hy) -include hx - +include h hx in theorem iteratedDerivWithin_add (hf : ContDiffOn 𝕜 n f s) (hg : ContDiffOn 𝕜 n g s) : iteratedDerivWithin n (f + g) s x = iteratedDerivWithin n f s x + iteratedDerivWithin n g s x := by @@ -47,50 +44,61 @@ theorem iteratedDerivWithin_add (hf : ContDiffOn 𝕜 n f s) (hg : ContDiffOn theorem iteratedDerivWithin_const_add (hn : 0 < n) (c : F) : iteratedDerivWithin n (fun z => c + f z) s x = iteratedDerivWithin n f s x := by obtain ⟨n, rfl⟩ := n.exists_eq_succ_of_ne_zero hn.ne' - rw [iteratedDerivWithin_succ' h hx, iteratedDerivWithin_succ' h hx] - refine iteratedDerivWithin_congr h ?_ hx - intro y hy - exact derivWithin_const_add (h.uniqueDiffWithinAt hy) _ + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs; swap + · simp [iteratedDerivWithin_succ, derivWithin_zero_of_isolated hxs] + rw [iteratedDerivWithin_succ', iteratedDerivWithin_succ'] + congr with y + exact derivWithin_const_add _ theorem iteratedDerivWithin_const_sub (hn : 0 < n) (c : F) : iteratedDerivWithin n (fun z => c - f z) s x = iteratedDerivWithin n (fun z => -f z) s x := by obtain ⟨n, rfl⟩ := n.exists_eq_succ_of_ne_zero hn.ne' - rw [iteratedDerivWithin_succ' h hx, iteratedDerivWithin_succ' h hx] - refine iteratedDerivWithin_congr h ?_ hx - intro y hy - have : UniqueDiffWithinAt 𝕜 s y := h.uniqueDiffWithinAt hy - rw [derivWithin.neg this] - exact derivWithin_const_sub this _ + rcases uniqueDiffWithinAt_or_nhdsWithin_eq_bot s x with hxs | hxs; swap + · simp [iteratedDerivWithin_succ, derivWithin_zero_of_isolated hxs] + rw [iteratedDerivWithin_succ', iteratedDerivWithin_succ'] + congr with y + rw [derivWithin.neg] + exact derivWithin_const_sub _ @[deprecated (since := "2024-12-10")] alias iteratedDerivWithin_const_neg := iteratedDerivWithin_const_sub +include h hx in theorem iteratedDerivWithin_const_smul (c : R) (hf : ContDiffWithinAt 𝕜 n f s x) : iteratedDerivWithin n (c • f) s x = c • iteratedDerivWithin n f s x := by simp_rw [iteratedDerivWithin] rw [iteratedFDerivWithin_const_smul_apply hf h hx] simp only [ContinuousMultilinearMap.smul_apply] +include h hx in theorem iteratedDerivWithin_const_mul (c : 𝕜) {f : 𝕜 → 𝕜} (hf : ContDiffWithinAt 𝕜 n f s x) : iteratedDerivWithin n (fun z => c * f z) s x = c * iteratedDerivWithin n f s x := by simpa using iteratedDerivWithin_const_smul (F := 𝕜) hx h c hf variable (f) in +omit h hx in theorem iteratedDerivWithin_neg : iteratedDerivWithin n (-f) s x = -iteratedDerivWithin n f s x := by - rw [iteratedDerivWithin, iteratedDerivWithin, iteratedFDerivWithin_neg_apply h hx, - ContinuousMultilinearMap.neg_apply] + induction n generalizing x with + | zero => simp + | succ n IH => + simp only [iteratedDerivWithin_succ, derivWithin_neg] + rw [← derivWithin.neg] + congr with y + exact IH variable (f) in theorem iteratedDerivWithin_neg' : iteratedDerivWithin n (fun z => -f z) s x = -iteratedDerivWithin n f s x := - iteratedDerivWithin_neg hx h f + iteratedDerivWithin_neg f + +include h hx theorem iteratedDerivWithin_sub (hf : ContDiffOn 𝕜 n f s) (hg : ContDiffOn 𝕜 n g s) : iteratedDerivWithin n (f - g) s x = iteratedDerivWithin n f s x - iteratedDerivWithin n g s x := by rw [sub_eq_add_neg, sub_eq_add_neg, Pi.neg_def, iteratedDerivWithin_add hx h hf hg.neg, - iteratedDerivWithin_neg' hx h] + iteratedDerivWithin_neg'] theorem iteratedDerivWithin_comp_const_smul (hf : ContDiffOn 𝕜 n f s) (c : 𝕜) (hs : Set.MapsTo (c * ·) s s) : @@ -111,11 +119,11 @@ theorem iteratedDerivWithin_comp_const_smul (hf : ContDiffOn 𝕜 n f s) (c : · exact hf.differentiableOn_iteratedDerivWithin (Nat.cast_lt.mpr n.lt_succ_self) h _ hcx · exact differentiableWithinAt_id'.const_mul _ · exact hs - rw [iteratedDerivWithin_succ (h _ hx), derivWithin_congr h₀ (ih hx hf.of_succ), - derivWithin_const_smul (h _ hx) (c ^ n) h₂, iteratedDerivWithin_succ (h _ hcx), + rw [iteratedDerivWithin_succ, derivWithin_congr h₀ (ih hx hf.of_succ), + derivWithin_const_smul (c ^ n) h₂, iteratedDerivWithin_succ, ← Function.comp_def, - derivWithin.scomp x h₁ (differentiableWithinAt_id'.const_mul _) hs (h _ hx), - derivWithin_const_mul (h _ hx) _ differentiableWithinAt_id', derivWithin_id' _ _ (h _ hx), + derivWithin.scomp x h₁ (differentiableWithinAt_id'.const_mul _) hs, + derivWithin_const_mul _ differentiableWithinAt_id', derivWithin_id' _ _ (h _ hx), smul_smul, mul_one, pow_succ] end @@ -128,18 +136,15 @@ lemma iteratedDeriv_add (hf : ContDiff 𝕜 n f) (hg : ContDiff 𝕜 n g) : theorem iteratedDeriv_const_add (hn : 0 < n) (c : F) : iteratedDeriv n (fun z => c + f z) x = iteratedDeriv n f x := by - simpa only [iteratedDerivWithin_univ] using - iteratedDerivWithin_const_add (Set.mem_univ _) uniqueDiffOn_univ hn c + simpa only [← iteratedDerivWithin_univ] using iteratedDerivWithin_const_add hn c theorem iteratedDeriv_const_sub (hn : 0 < n) (c : F) : iteratedDeriv n (fun z => c - f z) x = iteratedDeriv n (-f) x := by - simpa only [iteratedDerivWithin_univ] using - iteratedDerivWithin_const_sub (Set.mem_univ _) uniqueDiffOn_univ hn c + simpa only [← iteratedDerivWithin_univ] using iteratedDerivWithin_const_sub hn c lemma iteratedDeriv_neg (n : ℕ) (f : 𝕜 → F) (a : 𝕜) : iteratedDeriv n (fun x ↦ -(f x)) a = -(iteratedDeriv n f a) := by - simpa only [iteratedDerivWithin_univ] using - iteratedDerivWithin_neg (Set.mem_univ a) uniqueDiffOn_univ f + simpa only [← iteratedDerivWithin_univ] using iteratedDerivWithin_neg f lemma iteratedDeriv_sub (hf : ContDiff 𝕜 n f) (hg : ContDiff 𝕜 n g) : iteratedDeriv n (f - g) x = iteratedDeriv n f x - iteratedDeriv n g x := by diff --git a/Mathlib/Analysis/Calculus/Taylor.lean b/Mathlib/Analysis/Calculus/Taylor.lean index 7d6b563e1c66a..a0021a92c18a4 100644 --- a/Mathlib/Analysis/Calculus/Taylor.lean +++ b/Mathlib/Analysis/Calculus/Taylor.lean @@ -145,7 +145,7 @@ theorem hasDerivWithinAt_taylor_coeff_within {f : ℝ → E} {x y : ℝ} {k : replace hf : HasDerivWithinAt (iteratedDerivWithin (k + 1) f s) (iteratedDerivWithin (k + 2) f s y) t y := by convert (hf.mono_of_mem_nhdsWithin hs).hasDerivWithinAt using 1 - rw [iteratedDerivWithin_succ (ht.mono_nhds (nhdsWithin_le_iff.mpr hs))] + rw [iteratedDerivWithin_succ] exact (derivWithin_of_mem_nhdsWithin hs ht hf).symm have : HasDerivWithinAt (fun t => ((k + 1 : ℝ) * k !)⁻¹ * (x - t) ^ (k + 1)) (-((k ! : ℝ)⁻¹ * (x - y) ^ k)) t y := by @@ -162,17 +162,19 @@ theorem hasDerivWithinAt_taylor_coeff_within {f : ℝ → E} {x y : ℝ} {k : Version for arbitrary sets -/ theorem hasDerivWithinAt_taylorWithinEval {f : ℝ → E} {x y : ℝ} {n : ℕ} {s s' : Set ℝ} - (hs'_unique : UniqueDiffWithinAt ℝ s' y) (hs_unique : UniqueDiffOn ℝ s) (hs' : s' ∈ 𝓝[s] y) + (hs_unique : UniqueDiffOn ℝ s) (hs' : s' ∈ 𝓝[s] y) (hy : y ∈ s') (h : s' ⊆ s) (hf : ContDiffOn ℝ n f s) (hf' : DifferentiableWithinAt ℝ (iteratedDerivWithin n f s) s y) : HasDerivWithinAt (fun t => taylorWithinEval f n s t x) (((n ! : ℝ)⁻¹ * (x - y) ^ n) • iteratedDerivWithin (n + 1) f s y) s' y := by + have hs'_unique : UniqueDiffWithinAt ℝ s' y := + UniqueDiffWithinAt.mono_nhds (hs_unique _ (h hy)) (nhdsWithin_le_iff.mpr hs') induction n with | zero => simp only [taylor_within_zero_eval, Nat.factorial_zero, Nat.cast_one, inv_one, pow_zero, mul_one, zero_add, one_smul] simp only [iteratedDerivWithin_zero] at hf' - rw [iteratedDerivWithin_one (hs_unique _ (h hy))] + rw [iteratedDerivWithin_one] exact hf'.hasDerivWithinAt.mono h | succ k hk => simp_rw [Nat.add_succ, taylorWithinEval_succ] @@ -195,7 +197,7 @@ theorem taylorWithinEval_hasDerivAt_Ioo {f : ℝ → E} {a b t : ℝ} (x : ℝ) (((n ! : ℝ)⁻¹ * (x - t) ^ n) • iteratedDerivWithin (n + 1) f (Icc a b) t) t := have h_nhds : Ioo a b ∈ 𝓝 t := isOpen_Ioo.mem_nhds ht have h_nhds' : Ioo a b ∈ 𝓝[Icc a b] t := nhdsWithin_le_nhds h_nhds - (hasDerivWithinAt_taylorWithinEval (uniqueDiffWithinAt_Ioo ht) (uniqueDiffOn_Icc hx) h_nhds' ht + (hasDerivWithinAt_taylorWithinEval (uniqueDiffOn_Icc hx) h_nhds' ht Ioo_subset_Icc_self hf <| (hf' t ht).mono_of_mem_nhdsWithin h_nhds').hasDerivAt h_nhds /-- Calculate the derivative of the Taylor polynomial with respect to `x₀`. @@ -206,7 +208,7 @@ theorem hasDerivWithinAt_taylorWithinEval_at_Icc {f : ℝ → E} {a b t : ℝ} ( (hf' : DifferentiableOn ℝ (iteratedDerivWithin n f (Icc a b)) (Icc a b)) : HasDerivWithinAt (fun y => taylorWithinEval f n (Icc a b) y x) (((n ! : ℝ)⁻¹ * (x - t) ^ n) • iteratedDerivWithin (n + 1) f (Icc a b) t) (Icc a b) t := - hasDerivWithinAt_taylorWithinEval (uniqueDiffOn_Icc hx t ht) (uniqueDiffOn_Icc hx) + hasDerivWithinAt_taylorWithinEval (uniqueDiffOn_Icc hx) self_mem_nhdsWithin ht rfl.subset hf (hf' t ht) /-! ### Taylor's theorem with mean value type remainder estimate -/ From e54baa929aa30add58937830b50a1fe40783623d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Sun, 19 Jan 2025 12:43:32 +0000 Subject: [PATCH 306/681] feat(Algebra/Ring): add `@[simps]` attribute to `RingEquiv.piUnique` (#20805) Add missing `@[simps]` attribute to `RingEquiv.piUnique`. --- Mathlib/Algebra/Ring/Equiv.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index 474e811d144ba..7288db996a5d0 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -443,6 +443,7 @@ theorem ofBijective_apply [NonUnitalRingHomClass F R S] (f : F) (hf : Function.B /-- Product of a singleton family of (non-unital non-associative semi)rings is isomorphic to the only member of this family. -/ +@[simps! (config := .asFn)] def piUnique {ι : Type*} (R : ι → Type*) [Unique ι] [∀ i, NonUnitalNonAssocSemiring (R i)] : (∀ i, R i) ≃+* R default where __ := Equiv.piUnique R From 0da1e288b990ae34d7f1f8712e9a0ecce8864098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 19 Jan 2025 13:20:41 +0000 Subject: [PATCH 307/681] feat(Algebra/Homology): acyclic complexes (#20834) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... and various additions to the homology API for #19572. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib/Algebra/Homology/QuasiIso.lean | 6 +++ .../ShortComplex/HomologicalComplex.lean | 13 +++++ .../Homology/ShortComplex/Homology.lean | 47 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/Mathlib/Algebra/Homology/QuasiIso.lean b/Mathlib/Algebra/Homology/QuasiIso.lean index 19e311240e6ed..46193c305d8b1 100644 --- a/Mathlib/Algebra/Homology/QuasiIso.lean +++ b/Mathlib/Algebra/Homology/QuasiIso.lean @@ -79,6 +79,12 @@ lemma quasiIsoAt_iff_exactAt' (f : K ⟶ L) (i : ι) [K.HasHomology i] [L.HasHom · intro hK exact ⟨⟨0, IsZero.eq_of_src hK _ _, IsZero.eq_of_tgt hL _ _⟩⟩ +lemma exactAt_iff_of_quasiIsoAt (f : K ⟶ L) (i : ι) + [K.HasHomology i] [L.HasHomology i] [QuasiIsoAt f i] : + K.ExactAt i ↔ L.ExactAt i := + ⟨fun hK => (quasiIsoAt_iff_exactAt f i hK).1 inferInstance, + fun hL => (quasiIsoAt_iff_exactAt' f i hL).1 inferInstance⟩ + instance (f : K ⟶ L) (i : ι) [K.HasHomology i] [L.HasHomology i] [hf : QuasiIsoAt f i] : IsIso (homologyMap f i) := by simpa only [quasiIsoAt_iff, ShortComplex.quasiIso_iff] using hf diff --git a/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean b/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean index 97bd4dc2b02fa..b906d28288a6e 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean @@ -614,6 +614,19 @@ lemma exactAt_iff_isZero_homology [K.HasHomology i] : dsimp [homology] rw [exactAt_iff, ShortComplex.exact_iff_isZero_homology] +/-- A homological complex `K` is acyclic if it is exact at `i` for any `i`. -/ +def Acyclic := ∀ i, K.ExactAt i + +lemma acyclic_iff : + K.Acyclic ↔ ∀ i, K.ExactAt i := by rfl + +lemma acyclic_of_isZero (hK : IsZero K) : + K.Acyclic := by + rw [acyclic_iff] + intro i + apply ShortComplex.exact_of_isZero_X₂ + exact (eval _ _ i).map_isZero hK + end HomologicalComplex namespace ChainComplex diff --git a/Mathlib/Algebra/Homology/ShortComplex/Homology.lean b/Mathlib/Algebra/Homology/ShortComplex/Homology.lean index 9f3d4faff0bed..8d34059412da3 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Homology.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Homology.lean @@ -1173,6 +1173,53 @@ instance epi_homologyMap_of_epi_cyclesMap Epi (homologyMap φ) := epi_homologyMap_of_epi_cyclesMap' φ inferInstance +/-- Given a short complex `S` such that `S.HasHomology`, this is the canonical +left homology data for `S` whose `K` and `H` fields are +respectively `S.cycles` and `S.homology`. -/ +@[simps!] +noncomputable def LeftHomologyData.canonical [S.HasHomology] : S.LeftHomologyData where + K := S.cycles + H := S.homology + i := S.iCycles + π := S.homologyπ + wi := by simp + hi := S.cyclesIsKernel + wπ := S.toCycles_comp_homologyπ + hπ := S.homologyIsCokernel + +/-- Computation of the `f'` field of `LeftHomologyData.canonical`. -/ +@[simp] +lemma LeftHomologyData.canonical_f' [S.HasHomology] : + (LeftHomologyData.canonical S).f' = S.toCycles := rfl + +/-- Given a short complex `S` such that `S.HasHomology`, this is the canonical +right homology data for `S` whose `Q` and `H` fields are +respectively `S.opcycles` and `S.homology`. -/ +@[simps!] +noncomputable def RightHomologyData.canonical [S.HasHomology] : S.RightHomologyData where + Q := S.opcycles + H := S.homology + p := S.pOpcycles + ι := S.homologyι + wp := by simp + hp := S.opcyclesIsCokernel + wι := S.homologyι_comp_fromOpcycles + hι := S.homologyIsKernel + +/-- Computation of the `g'` field of `RightHomologyData.canonical`. -/ +@[simp] +lemma RightHomologyData.canonical_g' [S.HasHomology] : + (RightHomologyData.canonical S).g' = S.fromOpcycles := rfl + +/-- Given a short complex `S` such that `S.HasHomology`, this is the canonical +homology data for `S` whose `left.K`, `left/right.H` and `right.Q` fields are +respectively `S.cycles`, `S.homology` and `S.opcycles`. -/ +@[simps!] +noncomputable def HomologyData.canonical [S.HasHomology] : S.HomologyData where + left := LeftHomologyData.canonical S + right := RightHomologyData.canonical S + iso := Iso.refl _ + end ShortComplex end CategoryTheory From 165731857a079f3712426d4d1da2a5ac32c6be56 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Sun, 19 Jan 2025 14:13:17 +0000 Subject: [PATCH 308/681] feat: start building an API for vector fields on manifolds (#20639) Notably, define the pullback of vector fields, and show that the pullback of a differentiable vector field under a C^2 map is differentiable. More API to come in further PRs. Once all the API is there, it will be easy to define the Lie algebra of a Lie group using left-invariant vector fields, in #18396. --- Mathlib.lean | 1 + Mathlib/Analysis/Calculus/ContDiff/Basic.lean | 7 + .../Analysis/Calculus/FDeriv/Symmetric.lean | 14 + Mathlib/Geometry/Manifold/VectorField.lean | 341 ++++++++++++++++++ 4 files changed, 363 insertions(+) create mode 100644 Mathlib/Geometry/Manifold/VectorField.lean diff --git a/Mathlib.lean b/Mathlib.lean index 1dcce7d5ab2a0..eed413e33a43f 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3214,6 +3214,7 @@ import Mathlib.Geometry.Manifold.VectorBundle.MDifferentiable import Mathlib.Geometry.Manifold.VectorBundle.Pullback import Mathlib.Geometry.Manifold.VectorBundle.SmoothSection import Mathlib.Geometry.Manifold.VectorBundle.Tangent +import Mathlib.Geometry.Manifold.VectorField import Mathlib.Geometry.Manifold.WhitneyEmbedding import Mathlib.Geometry.RingedSpace.Basic import Mathlib.Geometry.RingedSpace.LocallyRingedSpace diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index 6eecb4ca014a6..d433760da7719 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -1818,6 +1818,13 @@ theorem contDiffAt_map_inverse [CompleteSpace E] (e : E ≃L[𝕜] F) : convert contDiffAt_ring_inverse 𝕜 (1 : (E →L[𝕜] E)ˣ) simp [O₂, one_def] +/-- At an invertible map `e : M →L[R] M₂` between Banach spaces, the operation of +inversion is `C^n`, for all `n`. -/ +theorem ContinuousLinearMap.IsInvertible.contDiffAt_map_inverse [CompleteSpace E] {e : E →L[𝕜] F} + (he : e.IsInvertible) : ContDiffAt 𝕜 n inverse e := by + rcases he with ⟨M, rfl⟩ + exact _root_.contDiffAt_map_inverse M + end MapInverse section FunctionInverse diff --git a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean index b518f82c09cb7..d9ecb60adbc29 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean @@ -485,6 +485,20 @@ lemma le_minSmoothness {n : WithTop ℕ∞} : n ≤ minSmoothness 𝕜 n := by simp only [minSmoothness] split_ifs <;> simp +lemma minSmoothness_add {n m : WithTop ℕ∞} : minSmoothness 𝕜 (n + m) = minSmoothness 𝕜 n + m := by + simp only [minSmoothness] + split_ifs <;> simp + +lemma minSmoothness_monotone : Monotone (minSmoothness 𝕜) := by + intro m n hmn + simp only [minSmoothness] + split_ifs <;> simp [hmn] + +@[simp] lemma minSmoothness_eq_infty {n : WithTop ℕ∞} : + minSmoothness 𝕜 n = ∞ ↔ (n = ∞ ∧ IsRCLikeNormedField 𝕜) := by + simp only [minSmoothness] + split_ifs with h <;> simp [h] + /-- If `minSmoothness 𝕜 m ≤ n` for some (finite) integer `m`, then one can find `n' ∈ [minSmoothness 𝕜 m, n]` which is not `∞`: over `ℝ` or `ℂ`, just take `m`, and otherwise just take `ω`. The interest of this technical lemma is that, if a function is `C^{n'}` at a point diff --git a/Mathlib/Geometry/Manifold/VectorField.lean b/Mathlib/Geometry/Manifold/VectorField.lean new file mode 100644 index 0000000000000..cd573eaaa75b7 --- /dev/null +++ b/Mathlib/Geometry/Manifold/VectorField.lean @@ -0,0 +1,341 @@ +/- +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.Analysis.Calculus.VectorField +import Mathlib.Geometry.Manifold.ContMDiffMFDeriv +import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace +import Mathlib.Geometry.Manifold.VectorBundle.MDifferentiable + +/-! +# Vector fields in manifolds + +We study functions of the form `V : Π (x : M) → TangentSpace I x` on a manifold, i.e., +vector fields. + +We define the pullback of a vector field under a map, as +`VectorField.mpullback I I' f V x := (mfderiv I I' f x).inverse (V (f x))` +(together with the same notion within a set). Note that the pullback uses the junk-value pattern: +if the derivative of the map is not invertible, then pullback is given the junk value zero. + +We start developing API around this notion. + +All these are given in the `VectorField` namespace because pullbacks, Lie brackets, and so on, +are notions that make sense in a variety of contexts. We also prefix the notions with `m` to +distinguish the manifold notions from the vector space notions. + +For notions that come naturally in other namespaces for dot notation, we specify `vectorField` in +the name to lift ambiguities. For instance, the fact that the Lie bracket of two smooth vector +fields is smooth will be `ContMDiffAt.mlieBracket_vectorField`. + +Note that a smoothness assumption for a vector field is written by seeing the vector field as +a function from `M` to its tangent bundle through a coercion, as in: +`MDifferentiableWithinAt I I.tangent (fun y ↦ (V y : TangentBundle I M)) s x`. +-/ + +open Set Function Filter +open scoped Topology Manifold ContDiff + +noncomputable section + +/- We work in the `VectorField` namespace because pullbacks, Lie brackets, and so on, are notions +that make sense in a variety of contexts. We also prefix the notions with `m` to distinguish the +manifold notions from the vector spaces notions. For instance, the Lie bracket of two vector +fields in a manifold is denoted with `VectorField.mlieBracket I V W x`, where `I` is the relevant +model with corners, `V W : Π (x : M), TangentSpace I x` are the vector fields, and `x : M` is +the basepoint. +-/ + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {H : Type*} [TopologicalSpace H] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {I : ModelWithCorners 𝕜 E H} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + {H' : Type*} [TopologicalSpace H'] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] + {I' : ModelWithCorners 𝕜 E' H'} + {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] + {H'' : Type*} [TopologicalSpace H''] {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] + {I'' : ModelWithCorners 𝕜 E'' H''} + {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H'' M''] + {f : M → M'} {s t : Set M} {x x₀ : M} + +instance {n : ℕ} [n.AtLeastTwo] [IsManifold I (minSmoothness 𝕜 (ofNat(n))) M] : + IsManifold I (ofNat(n)) M := + IsManifold.of_le (n := minSmoothness 𝕜 n) le_minSmoothness + +instance [IsManifold I (minSmoothness 𝕜 1) M] : + IsManifold I 1 M := + IsManifold.of_le (n := minSmoothness 𝕜 1) le_minSmoothness + +instance [IsManifold I (minSmoothness 𝕜 3) M] : + IsManifold I (minSmoothness 𝕜 2) M := + IsManifold.of_le (n := minSmoothness 𝕜 3) (minSmoothness_monotone (by norm_cast)) + +instance [IsManifold I (minSmoothness 𝕜 2) M] : + IsManifold I (minSmoothness 𝕜 1) M := + IsManifold.of_le (n := minSmoothness 𝕜 2) (minSmoothness_monotone (by norm_cast)) + +namespace VectorField + +section Pullback + +/-! ### Pullback of vector fields in manifolds -/ + +open ContinuousLinearMap + +variable {V W V₁ W₁ : Π (x : M'), TangentSpace I' x} +variable {c : 𝕜} {m n : WithTop ℕ∞} {t : Set M'} {y₀ : M'} + +variable (I I') in +/-- The pullback of a vector field under a map between manifolds, within a set `s`. If the +derivative of the map within `s` is not invertible, then pullback is given the junk value zero.-/ +def mpullbackWithin (f : M → M') (V : Π (x : M'), TangentSpace I' x) (s : Set M) (x : M) : + TangentSpace I x := + (mfderivWithin I I' f s x).inverse (V (f x)) + +variable (I I') in +/-- The pullback of a vector field under a map between manifolds. If the derivative of the map is +not invertible, then pullback is given the junk value zero. -/ +def mpullback (f : M → M') (V : Π (x : M'), TangentSpace I' x) (x : M) : + TangentSpace I x := + (mfderiv I I' f x).inverse (V (f x)) + +lemma mpullbackWithin_apply : + mpullbackWithin I I' f V s x = (mfderivWithin I I' f s x).inverse (V (f x)) := rfl + +lemma mpullbackWithin_smul_apply : + mpullbackWithin I I' f (c • V) s x = c • mpullbackWithin I I' f V s x := by + simp [mpullbackWithin_apply] + +lemma mpullbackWithin_smul : + mpullbackWithin I I' f (c • V) s = c • mpullbackWithin I I' f V s := by + ext x + simp [mpullbackWithin_apply] + +lemma mpullbackWithin_add_apply : + mpullbackWithin I I' f (V + V₁) s x = + mpullbackWithin I I' f V s x + mpullbackWithin I I' f V₁ s x := by + simp [mpullbackWithin_apply] + +lemma mpullbackWithin_add : + mpullbackWithin I I' f (V + V₁) s = + mpullbackWithin I I' f V s + mpullbackWithin I I' f V₁ s := by + ext x + simp [mpullbackWithin_apply] + +lemma mpullbackWithin_neg_apply : + mpullbackWithin I I' f (-V) s x = - mpullbackWithin I I' f V s x := by + simp [mpullbackWithin_apply] + +lemma mpullbackWithin_neg : + mpullbackWithin I I' f (-V) s = - mpullbackWithin I I' f V s := by + ext x + simp [mpullbackWithin_apply] + +lemma mpullbackWithin_id {V : Π (x : M), TangentSpace I x} (h : UniqueMDiffWithinAt I s x) : + mpullbackWithin I I id V s x = V x := by + simp [mpullbackWithin_apply, mfderivWithin_id h] + +lemma mpullback_apply : + mpullback I I' f V x = (mfderiv I I' f x).inverse (V (f x)) := rfl + +lemma mpullback_smul_apply : + mpullback I I' f (c • V) x = c • mpullback I I' f V x := by + simp [mpullback] + +lemma mpullback_smul : + mpullback I I' f (c • V) = c • mpullback I I' f V := by + ext x + simp [mpullback_apply] + +lemma mpullback_add_apply : + mpullback I I' f (V + V₁) x = mpullback I I' f V x + mpullback I I' f V₁ x := by + simp [mpullback_apply] + +lemma mpullback_add : + mpullback I I' f (V + V₁) = mpullback I I' f V + mpullback I I' f V₁ := by + ext x + simp [mpullback_apply] + +lemma mpullback_neg_apply : + mpullback I I' f (-V) x = - mpullback I I' f V x := by + simp [mpullback_apply] + +lemma mpullback_neg : + mpullback I I' f (-V) = - mpullback I I' f V := by + ext x + simp [mpullback_apply] + +@[simp] lemma mpullbackWithin_univ : mpullbackWithin I I' f V univ = mpullback I I' f V := by + ext x + simp [mpullback_apply, mpullbackWithin_apply] + +lemma mpullbackWithin_eq_pullbackWithin {f : E → E'} {V : E' → E'} {s : Set E} : + mpullbackWithin 𝓘(𝕜, E) 𝓘(𝕜, E') f V s = pullbackWithin 𝕜 f V s := by + ext x + simp only [mpullbackWithin, mfderivWithin_eq_fderivWithin, pullbackWithin] + rfl + +lemma mpullback_eq_pullback {f : E → E'} {V : E' → E'} : + mpullback 𝓘(𝕜, E) 𝓘(𝕜, E') f V = pullback 𝕜 f V := by + simp only [← mpullbackWithin_univ, ← pullbackWithin_univ, mpullbackWithin_eq_pullbackWithin] + +@[simp] lemma mpullback_id {V : Π (x : M), TangentSpace I x} : mpullback I I id V = V := by + ext x + simp [mpullback] + +/-! ### Regularity of pullback of vector fields + +In this paragraph, we assume that the model space is complete, to ensure that the set of invertible +linear maps is open and that inversion is a smooth map there. Otherwise, the pullback of vector +fields could behave wildly, even at points where the derivative of the map is invertible. +-/ + +section MDifferentiability + +variable [IsManifold I 2 M] [IsManifold I' 2 M'] [CompleteSpace E] + +/-- The pullback of a differentiable vector field by a `C^n` function with `2 ≤ n` is +differentiable. Version within a set at a point. -/ +protected lemma _root_.MDifferentiableWithinAt.mpullbackWithin_vectorField_inter + (hV : MDifferentiableWithinAt I' I'.tangent + (fun (y : M') ↦ (V y : TangentBundle I' M')) t (f x₀)) + (hf : ContMDiffWithinAt I I' n f s x₀) (hf' : (mfderivWithin I I' f s x₀).IsInvertible) + (hx₀ : x₀ ∈ s) (hs : UniqueMDiffOn I s) (hmn : 2 ≤ n) : + MDifferentiableWithinAt I I.tangent + (fun (y : M) ↦ (mpullbackWithin I I' f V s y : TangentBundle I M)) (s ∩ f ⁻¹' t) x₀ := by + /- We want to apply the theorem `MDifferentiableWithinAt.clm_apply_of_inCoordinates`, + stating that applying linear maps to vector fields gives a smooth result when the linear map and + the vector field are smooth. This theorem is general, we will apply it to + `b₁ = f`, `b₂ = id`, `v = V ∘ f`, `ϕ = fun x ↦ (mfderivWithin I I' f s x).inverse`-/ + let b₁ := f + let b₂ : M → M := id + let v : Π (x : M), TangentSpace I' (f x) := V ∘ f + let ϕ : Π (x : M), TangentSpace I' (f x) →L[𝕜] TangentSpace I x := + fun x ↦ (mfderivWithin I I' f s x).inverse + have hv : MDifferentiableWithinAt I I'.tangent + (fun x ↦ (v x : TangentBundle I' M')) (s ∩ f ⁻¹' t) x₀ := by + apply hV.comp x₀ ((hf.mdifferentiableWithinAt (one_le_two.trans hmn)).mono inter_subset_left) + exact MapsTo.mono_left (mapsTo_preimage _ _) inter_subset_right + /- The only nontrivial fact, from which the conclusion follows, is + that `ϕ` depends smoothly on `x`. -/ + suffices hϕ : MDifferentiableWithinAt I 𝓘(𝕜, E' →L[𝕜] E) + (fun (x : M) ↦ ContinuousLinearMap.inCoordinates + E' (TangentSpace I' (M := M')) E (TangentSpace I (M := M)) + (b₁ x₀) (b₁ x) (b₂ x₀) (b₂ x) (ϕ x)) s x₀ from + MDifferentiableWithinAt.clm_apply_of_inCoordinates (hϕ.mono inter_subset_left) + hv mdifferentiableWithinAt_id + /- To prove that `ϕ` depends smoothly on `x`, we use that the derivative depends smoothly on `x` + (this is `ContMDiffWithinAt.mfderivWithin_const`), and that taking the inverse is a smooth + operation at an invertible map. -/ + -- the derivative in coordinates depends smoothly on the point + have : MDifferentiableWithinAt I 𝓘(𝕜, E →L[𝕜] E') + (fun (x : M) ↦ ContinuousLinearMap.inCoordinates + E (TangentSpace I (M := M)) E' (TangentSpace I' (M := M')) + x₀ x (f x₀) (f x) (mfderivWithin I I' f s x)) s x₀ := + ((hf.of_le hmn).mfderivWithin_const le_rfl hx₀ hs).mdifferentiableWithinAt le_rfl + -- therefore, its inverse in coordinates also depends smoothly on the point + have : MDifferentiableWithinAt I 𝓘(𝕜, E' →L[𝕜] E) + (ContinuousLinearMap.inverse ∘ (fun (x : M) ↦ ContinuousLinearMap.inCoordinates + E (TangentSpace I (M := M)) E' (TangentSpace I' (M := M')) + x₀ x (f x₀) (f x) (mfderivWithin I I' f s x))) s x₀ := by + apply MDifferentiableAt.comp_mdifferentiableWithinAt _ _ this + apply ContMDiffAt.mdifferentiableAt _ le_rfl + apply ContDiffAt.contMDiffAt + apply IsInvertible.contDiffAt_map_inverse + rw [inCoordinates_eq (FiberBundle.mem_baseSet_trivializationAt' x₀) + (FiberBundle.mem_baseSet_trivializationAt' (f x₀))] + exact isInvertible_equiv.comp (hf'.comp isInvertible_equiv) + -- the inverse in coordinates coincides with the in-coordinate version of the inverse, + -- therefore the previous point gives the conclusion + apply this.congr_of_eventuallyEq_of_mem _ hx₀ + have A : (trivializationAt E (TangentSpace I) x₀).baseSet ∈ 𝓝[s] x₀ := by + apply nhdsWithin_le_nhds + apply (trivializationAt _ _ _).open_baseSet.mem_nhds + exact FiberBundle.mem_baseSet_trivializationAt' _ + have B : f ⁻¹' (trivializationAt E' (TangentSpace I') (f x₀)).baseSet ∈ 𝓝[s] x₀ := by + apply hf.continuousWithinAt.preimage_mem_nhdsWithin + apply (trivializationAt _ _ _).open_baseSet.mem_nhds + exact FiberBundle.mem_baseSet_trivializationAt' _ + filter_upwards [A, B] with x hx h'x + simp only [Function.comp_apply] + rw [inCoordinates_eq hx h'x, inCoordinates_eq h'x (by exact hx)] + simp only [inverse_equiv_comp, inverse_comp_equiv, ContinuousLinearEquiv.symm_symm, ϕ] + rfl + +lemma _root_.MDifferentiableWithinAt.mpullbackWithin_vectorField_inter_of_eq + (hV : MDifferentiableWithinAt I' I'.tangent + (fun (y : M') ↦ (V y : TangentBundle I' M')) t y₀) + (hf : ContMDiffWithinAt I I' n f s x₀) (hf' : (mfderivWithin I I' f s x₀).IsInvertible) + (hx₀ : x₀ ∈ s) (hs : UniqueMDiffOn I s) (hmn : 2 ≤ n) (h : y₀ = f x₀) : + MDifferentiableWithinAt I I.tangent + (fun (y : M) ↦ (mpullbackWithin I I' f V s y : TangentBundle I M)) (s ∩ f⁻¹' t) x₀ := by + subst h + exact hV.mpullbackWithin_vectorField_inter hf hf' hx₀ hs hmn + +/-- The pullback of a differentiable vector field by a `C^n` function with `2 ≤ n` is +differentiable. Version on a set. -/ +protected lemma _root_.MDifferentiableOn.mpullbackWithin_vectorField_inter + (hV : MDifferentiableOn I' I'.tangent (fun (y : M') ↦ (V y : TangentBundle I' M')) t) + (hf : ContMDiffOn I I' n f s) (hf' : ∀ x ∈ s ∩ f ⁻¹' t, (mfderivWithin I I' f s x).IsInvertible) + (hs : UniqueMDiffOn I s) (hmn : 2 ≤ n) : + MDifferentiableOn I I.tangent + (fun (y : M) ↦ (mpullbackWithin I I' f V s y : TangentBundle I M)) (s ∩ f ⁻¹' t) := + fun _ hx₀ ↦ MDifferentiableWithinAt.mpullbackWithin_vectorField_inter + (hV _ hx₀.2) (hf _ hx₀.1) (hf' _ hx₀) hx₀.1 hs hmn + +/-- The pullback of a differentiable vector field by a `C^n` function with `2 ≤ n` is +differentiable. Version within a set at a point, but with full pullback. -/ +protected lemma _root_.MDifferentiableWithinAt.mpullback_vectorField_preimage + (hV : MDifferentiableWithinAt I' I'.tangent + (fun (y : M') ↦ (V y : TangentBundle I' M')) t (f x₀)) + (hf : ContMDiffAt I I' n f x₀) (hf' : (mfderiv I I' f x₀).IsInvertible) (hmn : 2 ≤ n) : + MDifferentiableWithinAt I I.tangent + (fun (y : M) ↦ (mpullback I I' f V y : TangentBundle I M)) (f ⁻¹' t) x₀ := by + simp only [← contMDiffWithinAt_univ, ← mfderivWithin_univ, ← mpullbackWithin_univ] at hV hf hf' ⊢ + simpa using hV.mpullbackWithin_vectorField_inter hf hf' (mem_univ _) uniqueMDiffOn_univ hmn + +/-- The pullback of a differentiable vector field by a `C^n` function with `2 ≤ n` is +differentiable. Version within a set at a point, but with full pullback. -/ +protected lemma _root_.MDifferentiableWithinAt.mpullback_vectorField_preimage_of_eq + (hV : MDifferentiableWithinAt I' I'.tangent (fun (y : M') ↦ (V y : TangentBundle I' M')) t y₀) + (hf : ContMDiffAt I I' n f x₀) (hf' : (mfderiv I I' f x₀).IsInvertible) (hmn : 2 ≤ n) + (hy₀ : y₀ = f x₀) : + MDifferentiableWithinAt I I.tangent + (fun (y : M) ↦ (mpullback I I' f V y : TangentBundle I M)) (f ⁻¹' t) x₀ := by + subst hy₀ + exact hV.mpullback_vectorField_preimage hf hf' hmn + +/-- The pullback of a differentiable vector field by a `C^n` function with `2 ≤ n` is +differentiable. Version on a set, but with full pullback -/ +protected lemma _root_.MDifferentiableOn.mpullback_vectorField_preimage + (hV : MDifferentiableOn I' I'.tangent (fun (y : M') ↦ (V y : TangentBundle I' M')) t) + (hf : ContMDiff I I' n f) (hf' : ∀ x ∈ f ⁻¹' t, (mfderiv I I' f x).IsInvertible) + (hmn : 2 ≤ n) : + MDifferentiableOn I I.tangent + (fun (y : M) ↦ (mpullback I I' f V y : TangentBundle I M)) (f ⁻¹' t) := + fun x₀ hx₀ ↦ MDifferentiableWithinAt.mpullback_vectorField_preimage + (hV _ hx₀) (hf x₀) (hf' _ hx₀) hmn + +/-- The pullback of a differentiable vector field by a `C^n` function with `2 ≤ n` is +differentiable. Version at a point. -/ +protected lemma _root_.MDifferentiableAt.mpullback_vectorField + (hV : MDifferentiableAt I' I'.tangent (fun (y : M') ↦ (V y : TangentBundle I' M')) (f x₀)) + (hf : ContMDiffAt I I' n f x₀) (hf' : (mfderiv I I' f x₀).IsInvertible) (hmn : 2 ≤ n) : + MDifferentiableAt I I.tangent + (fun (y : M) ↦ (mpullback I I' f V y : TangentBundle I M)) x₀ := by + simpa using MDifferentiableWithinAt.mpullback_vectorField_preimage hV hf hf' hmn + +/-- The pullback of a differentiable vector field by a `C^n` function with `2 ≤ n` is +differentiable. -/ +protected lemma _root_.MDifferentiable.mpullback_vectorField + (hV : MDifferentiable I' I'.tangent (fun (y : M') ↦ (V y : TangentBundle I' M'))) + (hf : ContMDiff I I' n f) (hf' : ∀ x, (mfderiv I I' f x).IsInvertible) (hmn : 2 ≤ n) : + MDifferentiable I I.tangent (fun (y : M) ↦ (mpullback I I' f V y : TangentBundle I M)) := + fun x ↦ MDifferentiableAt.mpullback_vectorField (hV (f x)) (hf x) (hf' x) hmn + +end MDifferentiability + +end Pullback + +end VectorField From d8c5782c149618659f95c5327e569376fd4db571 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Sun, 19 Jan 2025 20:42:55 +0000 Subject: [PATCH 309/681] feat: product of connected categories is connected (#20855) Co-authored-by: Markus Himmel --- Mathlib/CategoryTheory/IsConnected.lean | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Mathlib/CategoryTheory/IsConnected.lean b/Mathlib/CategoryTheory/IsConnected.lean index 62109a61f38ae..a2467f07e290a 100644 --- a/Mathlib/CategoryTheory/IsConnected.lean +++ b/Mathlib/CategoryTheory/IsConnected.lean @@ -119,6 +119,13 @@ theorem IsPreconnected.of_any_functor_const_on_obj IsPreconnected J where iso_constant := fun F j' => ⟨NatIso.ofComponents fun j => eqToIso (h F j j')⟩ +instance IsPreconnected.prod [IsPreconnected J] [IsPreconnected K] : IsPreconnected (J × K) := by + refine .of_any_functor_const_on_obj (fun {a} F ⟨j, k⟩ ⟨j', k'⟩ => ?_) + exact (any_functor_const_on_obj (Prod.sectL J k ⋙ F) j j').trans + (any_functor_const_on_obj (Prod.sectR j' K ⋙ F) k k') + +instance IsConnected.prod [IsConnected J] [IsConnected K] : IsConnected (J × K) where + /-- If any functor to a discrete category is constant on objects, J is connected. The converse of `any_functor_const_on_obj`. -/ From 39e7123358ea8664ccd08088f24622af61dc9544 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Sun, 19 Jan 2025 20:50:58 +0000 Subject: [PATCH 310/681] chore: generalize universes for final functors between filtered categories (#20852) Co-authored-by: Markus Himmel --- Mathlib/CategoryTheory/Filtered/Final.lean | 57 +++++++++++----------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/Mathlib/CategoryTheory/Filtered/Final.lean b/Mathlib/CategoryTheory/Filtered/Final.lean index dc5eaabbc2b35..69bd8fd66b993 100644 --- a/Mathlib/CategoryTheory/Filtered/Final.lean +++ b/Mathlib/CategoryTheory/Filtered/Final.lean @@ -39,8 +39,6 @@ namespace CategoryTheory open CategoryTheory.Limits CategoryTheory.Functor Opposite -section ArbitraryUniverses - variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] (F : C ⥤ D) /-- If `StructuredArrow d F` is filtered for any `d : D`, then `F : C ⥤ D` is final. This is @@ -224,12 +222,24 @@ instance Over.initial_forget [IsCofilteredOrEmpty C] (c : C) : Initial (Over.for simp only [forget_obj, mk_left, forget_map, homMk_left] rw [IsCofiltered.eq_condition]) -end ArbitraryUniverses - section LocallySmall variable {C : Type v₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₁} D] (F : C ⥤ D) +/-- Implementation; use `Functor.Final.exists_coeq instead`. -/ +theorem Functor.Final.exists_coeq_of_locally_small [IsFilteredOrEmpty C] [Final F] {d : D} {c : C} + (s s' : d ⟶ F.obj c) : ∃ (c' : C) (t : c ⟶ c'), s ≫ F.map t = s' ≫ F.map t := by + have : colimit.ι (F ⋙ coyoneda.obj (op d)) c s = colimit.ι (F ⋙ coyoneda.obj (op d)) c s' := by + apply (Final.colimitCompCoyonedaIso F d).toEquiv.injective + subsingleton + obtain ⟨c', t₁, t₂, h⟩ := (Types.FilteredColimit.colimit_eq_iff.{v₁, v₁, v₁} _).mp this + refine ⟨IsFiltered.coeq t₁ t₂, t₁ ≫ IsFiltered.coeqHom t₁ t₂, ?_⟩ + conv_rhs => rw [IsFiltered.coeq_condition t₁ t₂] + dsimp only [comp_obj, coyoneda_obj_obj, unop_op, Functor.comp_map, coyoneda_obj_map] at h + simp [reassoc_of% h] + +end LocallySmall + /-- If `C` is filtered, then we can give an explicit condition for a functor `F : C ⥤ D` to be final. -/ theorem Functor.final_iff_of_isFiltered [IsFilteredOrEmpty C] : @@ -239,15 +249,13 @@ theorem Functor.final_iff_of_isFiltered [IsFilteredOrEmpty C] : · intro d obtain ⟨f⟩ : Nonempty (StructuredArrow d F) := IsConnected.is_nonempty exact ⟨_, ⟨f.hom⟩⟩ - · intro d c s s' - have : colimit.ι (F ⋙ coyoneda.obj (op d)) c s = colimit.ι (F ⋙ coyoneda.obj (op d)) c s' := by - apply (Final.colimitCompCoyonedaIso F d).toEquiv.injective - subsingleton - obtain ⟨c', t₁, t₂, h⟩ := (Types.FilteredColimit.colimit_eq_iff.{v₁, v₁, v₁} _).mp this - refine ⟨IsFiltered.coeq t₁ t₂, t₁ ≫ IsFiltered.coeqHom t₁ t₂, ?_⟩ - conv_rhs => rw [IsFiltered.coeq_condition t₁ t₂] - dsimp only [comp_obj, coyoneda_obj_obj, unop_op, Functor.comp_map, coyoneda_obj_map] at h - simp [reassoc_of% h] + · let s₁ : C ≌ AsSmall.{max u₁ v₁ u₂ v₂} C := AsSmall.equiv + let s₂ : D ≌ AsSmall.{max u₁ v₁ u₂ v₂} D := AsSmall.equiv + have : IsFilteredOrEmpty (AsSmall.{max u₁ v₁ u₂ v₂} C) := .of_equivalence s₁ + intro d c s s' + obtain ⟨c', t, ht⟩ := Functor.Final.exists_coeq_of_locally_small (s₁.inverse ⋙ F ⋙ s₂.functor) + (AsSmall.up.map s) (AsSmall.up.map s') + exact ⟨AsSmall.down.obj c', AsSmall.down.map t, s₂.functor.map_injective (by simp_all [s₁, s₂])⟩ /-- If `C` is cofiltered, then we can give an explicit condition for a functor `F : C ⥤ D` to be initial. -/ @@ -312,10 +320,6 @@ instance [IsCofiltered C] (X : C × C) : IsCofiltered (CostructuredArrow (diag C instance Functor.initial_diag_of_isFiltered [IsCofiltered C] : Initial (Functor.diag C) := initial_of_isCofiltered_costructuredArrow _ -end LocallySmall - -variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] - /-- If `C` is filtered, then every functor `F : C ⥤ Discrete PUnit` is final. -/ theorem Functor.final_of_isFiltered_of_pUnit [IsFiltered C] (F : C ⥤ Discrete PUnit) : Final F := by @@ -353,8 +357,7 @@ instance CostructuredArrow.initial_proj_of_isCofiltered [IsCofilteredOrEmpty C] /-- The functor `StructuredArrow d T ⥤ StructuredArrow e (T ⋙ S)` that `u : e ⟶ S.obj d` induces via `StructuredArrow.map₂` is final, if `T` and `S` are final and the domain of `T` is filtered. -/ -instance StructuredArrow.final_map₂_id {D : Type u₂} [Category.{v₂} D] - {C : Type v₁} [Category.{v₁} C] [IsFiltered C] {E : Type u₃} [Category.{v₁} E] +instance StructuredArrow.final_map₂_id [IsFiltered C] {E : Type u₃} [Category.{v₃} E] {T : C ⥤ D} [T.Final] {S : D ⥤ E} [S.Final] {T' : C ⥤ E} {d : D} {e : E} (u : e ⟶ S.obj d) (α : T ⋙ S ⟶ T') [IsIso α] : Final (map₂ (F := 𝟭 _) u α) := by @@ -363,8 +366,7 @@ instance StructuredArrow.final_map₂_id {D : Type u₂} [Category.{v₂} D] apply final_of_natIso (map₂IsoPreEquivalenceInverseCompProj d e u α).symm /-- `StructuredArrow.map` is final if the functor `T` is final` and its domain is filtered. -/ -instance StructuredArrow.final_map {C : Type v₁} [Category.{v₁} C] [IsFiltered C] - {D : Type v₁} [Category.{v₁} D] {S S' : D} (f : S ⟶ S') (T : C ⥤ D) [T.Final] : +instance StructuredArrow.final_map [IsFiltered C] {S S' : D} (f : S ⟶ S') (T : C ⥤ D) [T.Final] : Final (map (T := T) f) := by haveI := NatIso.isIso_of_isIso_app (𝟙 T) have : (map₂ (F := 𝟭 C) (G := 𝟭 D) f (𝟙 T)).Final := by @@ -373,24 +375,23 @@ instance StructuredArrow.final_map {C : Type v₁} [Category.{v₁} C] [IsFilter /-- `StructuredArrow.post X T S` is final if `T` and `S` are final and the domain of `T` is filtered. -/ -instance StructuredArrow.final_post {C : Type v₁} [Category.{v₁} C] [IsFiltered C] {E : Type u₃} - [Category.{v₁} E] (X : D) (T : C ⥤ D) [T.Final] (S : D ⥤ E) [S.Final] : Final (post X T S) := by +instance StructuredArrow.final_post [IsFiltered C] {E : Type u₃} [Category.{v₃} E] (X : D) + (T : C ⥤ D) [T.Final] (S : D ⥤ E) [S.Final] : Final (post X T S) := by apply final_of_natIso (postIsoMap₂ X T S).symm /-- The functor `CostructuredArrow T d ⥤ CostructuredArrow (T ⋙ S) e` that `u : S.obj d ⟶ e` induces via `CostructuredArrow.map₂` is initial, if `T` and `S` are initial and the domain of `T` is filtered. -/ -instance CostructuredArrow.initial_map₂_id {C : Type v₁} [Category.{v₁} C] [IsCofiltered C] - {E : Type u₃} [Category.{v₁} E] (T : C ⥤ D) [T.Initial] (S : D ⥤ E) [S.Initial] (d : D) (e : E) +instance CostructuredArrow.initial_map₂_id [IsCofiltered C] {E : Type u₃} [Category.{v₃} E] + (T : C ⥤ D) [T.Initial] (S : D ⥤ E) [S.Initial] (d : D) (e : E) (u : S.obj d ⟶ e) : Initial (map₂ (F := 𝟭 _) (U := T ⋙ S) (𝟙 (T ⋙ S)) u) := by have := (T ⋙ S).initial_iff_isCofiltered_costructuredArrow.mp inferInstance e apply initial_of_natIso (map₂IsoPreEquivalenceInverseCompProj T S d e u).symm /-- `CostructuredArrow.post T S X` is initial if `T` and `S` are initial and the domain of `T` is cofiltered. -/ -instance CostructuredArrow.initial_post {C : Type v₁} [Category.{v₁} C] [IsCofiltered C] - {E : Type u₃} [Category.{v₁} E] (X : D) (T : C ⥤ D) [T.Initial] (S : D ⥤ E) [S.Initial] : - Initial (post T S X) := by +instance CostructuredArrow.initial_post [IsCofiltered C] {E : Type u₃} [Category.{v₃} E] (X : D) + (T : C ⥤ D) [T.Initial] (S : D ⥤ E) [S.Initial] : Initial (post T S X) := by apply initial_of_natIso (postIsoMap₂ X T S).symm section Pi From a1ad6eb36b78052c3a6b85acf1eeaa1f2bc99214 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Sun, 19 Jan 2025 20:50:59 +0000 Subject: [PATCH 311/681] feat: StructuredArrow of product of functors (#20854) Co-authored-by: Markus Himmel --- .../Comma/StructuredArrow/Basic.lean | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean index 6b90ae8f3ff45..4f4687b1fb578 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean @@ -975,4 +975,92 @@ def CostructuredArrow.map₂IsoPreEquivalenceInverseCompProj (T : C ⥤ D) (S : end Pre +section Prod + +section + +variable {C' : Type u₃} [Category.{v₃} C'] {D' : Type u₄} [Category.{v₄} D'] + (S : D) (S' : D') (T : C ⥤ D) (T' : C' ⥤ D') + +@[reassoc (attr := simp)] +theorem StructuredArrow.w_prod_fst {X Y : StructuredArrow (S, S') (T.prod T')} + (f : X ⟶ Y) : X.hom.1 ≫ T.map f.right.1 = Y.hom.1 := + congr_arg _root_.Prod.fst (StructuredArrow.w f) + +@[reassoc (attr := simp)] +theorem StructuredArrow.w_prod_snd {X Y : StructuredArrow (S, S') (T.prod T')} + (f : X ⟶ Y) : X.hom.2 ≫ T'.map f.right.2 = Y.hom.2 := + congr_arg _root_.Prod.snd (StructuredArrow.w f) + +/-- Implementation; see `StructuredArrow.prodEquivalence`. -/ +@[simps] +def StructuredArrow.prodFunctor : + StructuredArrow (S, S') (T.prod T') ⥤ StructuredArrow S T × StructuredArrow S' T' where + obj f := ⟨.mk f.hom.1, .mk f.hom.2⟩ + map η := ⟨StructuredArrow.homMk η.right.1 (by simp), + StructuredArrow.homMk η.right.2 (by simp)⟩ + +/-- Implementation; see `StructuredArrow.prodEquivalence`. -/ +@[simps] +def StructuredArrow.prodInverse : + StructuredArrow S T × StructuredArrow S' T' ⥤ StructuredArrow (S, S') (T.prod T') where + obj f := .mk (Y := (f.1.right, f.2.right)) ⟨f.1.hom, f.2.hom⟩ + map η := StructuredArrow.homMk ⟨η.1.right, η.2.right⟩ (by simp) + +/-- The natural equivalence +`StructuredArrow (S, S') (T.prod T') ≌ StructuredArrow S T × StructuredArrow S' T'`. -/ +@[simps] +def StructuredArrow.prodEquivalence : + StructuredArrow (S, S') (T.prod T') ≌ StructuredArrow S T × StructuredArrow S' T' where + functor := StructuredArrow.prodFunctor S S' T T' + inverse := StructuredArrow.prodInverse S S' T T' + unitIso := NatIso.ofComponents (fun f => Iso.refl _) (by simp) + counitIso := NatIso.ofComponents (fun f => Iso.refl _) (by simp) + +end + +section + +variable {C' : Type u₃} [Category.{v₃} C'] {D' : Type u₄} [Category.{v₄} D'] + (S : C ⥤ D) (S' : C' ⥤ D') (T : D) (T' : D') + +@[reassoc (attr := simp)] +theorem CostructuredArrow.w_prod_fst {A B : CostructuredArrow (S.prod S') (T, T')} (f : A ⟶ B) : + S.map f.left.1 ≫ B.hom.1 = A.hom.1 := + congr_arg _root_.Prod.fst (CostructuredArrow.w f) + +@[reassoc (attr := simp)] +theorem CostructuredArrow.w_prod_snd {A B : CostructuredArrow (S.prod S') (T, T')} (f : A ⟶ B) : + S'.map f.left.2 ≫ B.hom.2 = A.hom.2 := + congr_arg _root_.Prod.snd (CostructuredArrow.w f) + +/-- Implementation; see `CostructuredArrow.prodEquivalence`. -/ +@[simps] +def CostructuredArrow.prodFunctor : + CostructuredArrow (S.prod S') (T, T') ⥤ CostructuredArrow S T × CostructuredArrow S' T' where + obj f := ⟨.mk f.hom.1, .mk f.hom.2⟩ + map η := ⟨CostructuredArrow.homMk η.left.1 (by simp), + CostructuredArrow.homMk η.left.2 (by simp)⟩ + +/-- Implementation; see `CostructuredArrow.prodEquivalence`. -/ +@[simps] +def CostructuredArrow.prodInverse : + CostructuredArrow S T × CostructuredArrow S' T' ⥤ CostructuredArrow (S.prod S') (T, T') where + obj f := .mk (Y := (f.1.left, f.2.left)) ⟨f.1.hom, f.2.hom⟩ + map η := CostructuredArrow.homMk ⟨η.1.left, η.2.left⟩ (by simp) + +/-- The natural equivalence +`CostructuredArrow (S.prod S') (T, T') ≌ CostructuredArrow S T × CostructuredArrow S' T'`. -/ +@[simps] +def CostructuredArrow.prodEquivalence : + CostructuredArrow (S.prod S') (T, T') ≌ CostructuredArrow S T × CostructuredArrow S' T' where + functor := CostructuredArrow.prodFunctor S S' T T' + inverse := CostructuredArrow.prodInverse S S' T T' + unitIso := NatIso.ofComponents (fun f => Iso.refl _) (by simp) + counitIso := NatIso.ofComponents (fun f => Iso.refl _) (by simp) + +end + +end Prod + end CategoryTheory From 260650d98d17f201d368c7abf4600d01d4d8cf6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Sun, 19 Jan 2025 21:48:34 +0000 Subject: [PATCH 312/681] feat(Order/OrderIsoNat): sequence in well-founded order is not `StrictAnti` (#20851) --- Mathlib/Order/OrderIsoNat.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/Order/OrderIsoNat.lean b/Mathlib/Order/OrderIsoNat.lean index da0fabb452ad3..0c00be9047fa7 100644 --- a/Mathlib/Order/OrderIsoNat.lean +++ b/Mathlib/Order/OrderIsoNat.lean @@ -92,6 +92,14 @@ theorem not_wellFounded_of_decreasing_seq (f : ((· > ·) : ℕ → ℕ → Prop end RelEmbedding +theorem not_strictAnti_of_wellFoundedLT [Preorder α] [WellFoundedLT α] (f : ℕ → α) : + ¬ StrictAnti f := fun hf ↦ + (RelEmbedding.natGT f (fun n ↦ hf (by simp))).not_wellFounded_of_decreasing_seq wellFounded_lt + +theorem not_strictMono_of_wellFoundedGT [Preorder α] [WellFoundedGT α] (f : ℕ → α) : + ¬ StrictMono f := + not_strictAnti_of_wellFoundedLT (α := αᵒᵈ) f + namespace Nat variable (s : Set ℕ) [Infinite s] From b13cefd9ffb7ac26e82244692c47d94487f33731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 19 Jan 2025 22:57:39 +0000 Subject: [PATCH 313/681] feat: `Pi.ofNat_def` (#20857) --- Mathlib/Data/Nat/Cast/Basic.lean | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mathlib/Data/Nat/Cast/Basic.lean b/Mathlib/Data/Nat/Cast/Basic.lean index d190cb22f4599..6ad91dd172cc3 100644 --- a/Mathlib/Data/Nat/Cast/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Basic.lean @@ -286,6 +286,8 @@ theorem natCast_def (n : ℕ) : (n : ∀ a, π a) = fun _ ↦ ↑n := @[simp] theorem ofNat_apply (n : ℕ) [n.AtLeastTwo] (a : α) : (OfNat.ofNat n : ∀ a, π a) a = n := rfl +lemma ofNat_def (n : ℕ) [n.AtLeastTwo] : (OfNat.ofNat n : ∀ a, π a) = fun _ ↦ OfNat.ofNat n := rfl + end Pi theorem Sum.elim_natCast_natCast {α β γ : Type*} [NatCast γ] (n : ℕ) : From 68ea7d25dcbdd9f46072adf8927a684d4194abbb Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Sun, 19 Jan 2025 23:29:52 +0000 Subject: [PATCH 314/681] chore(Algebra/Order/Floor): Split off `round` section (#20831) This PR splits the `Algebra/Order/Floor.lean` file, addressing an instance of a long-file tech debt issue. It does this by moving `round` and related lemmas to a new file. --- Counterexamples/MapFloor.lean | 2 +- Mathlib.lean | 1 + .../Computation/Approximations.lean | 1 - Mathlib/Algebra/Order/Floor.lean | 189 ---------------- Mathlib/Algebra/Order/Round.lean | 214 ++++++++++++++++++ Mathlib/Data/Rat/Floor.lean | 2 +- 6 files changed, 217 insertions(+), 192 deletions(-) create mode 100644 Mathlib/Algebra/Order/Round.lean diff --git a/Counterexamples/MapFloor.lean b/Counterexamples/MapFloor.lean index 3263f315ca27f..5d7fef98f8954 100644 --- a/Counterexamples/MapFloor.lean +++ b/Counterexamples/MapFloor.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Algebra.Order.Floor +import Mathlib.Algebra.Order.Round import Mathlib.Algebra.Order.Group.PiLex import Mathlib.Algebra.Order.Hom.Ring import Mathlib.Algebra.Polynomial.Reverse diff --git a/Mathlib.lean b/Mathlib.lean index eed413e33a43f..aa9c14349ab99 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -800,6 +800,7 @@ import Mathlib.Algebra.Order.Ring.Synonym import Mathlib.Algebra.Order.Ring.Unbundled.Basic import Mathlib.Algebra.Order.Ring.Unbundled.Rat import Mathlib.Algebra.Order.Ring.WithTop +import Mathlib.Algebra.Order.Round import Mathlib.Algebra.Order.Star.Basic import Mathlib.Algebra.Order.Star.Conjneg import Mathlib.Algebra.Order.Star.Prod diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean index 079913152e68b..476ff787c924d 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean @@ -5,7 +5,6 @@ Authors: Kevin Kappelmann -/ import Mathlib.Algebra.ContinuedFractions.Determinant import Mathlib.Algebra.ContinuedFractions.Computation.CorrectnessTerminating -import Mathlib.Algebra.Order.Group.Basic import Mathlib.Algebra.Order.Ring.Basic import Mathlib.Data.Nat.Fib.Basic import Mathlib.Tactic.Monotonicity diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index d11212a76f386..c38c843eb9ed1 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kevin Kappelmann -/ import Mathlib.Algebra.CharZero.Lemmas -import Mathlib.Algebra.Order.Interval.Set.Group import Mathlib.Algebra.Group.Int.Even import Mathlib.Algebra.Group.Int.Units import Mathlib.Data.Int.Lemmas @@ -33,7 +32,6 @@ We define the natural- and integer-valued floor and ceil functions on linearly o * `Int.floor a`: Greatest integer `z` such that `z ≤ a`. * `Int.ceil a`: Least integer `z` such that `a ≤ z`. * `Int.fract a`: Fractional part of `a`, defined as `a - floor a`. -* `round a`: Nearest integer to `a`. It rounds halves towards infinity. ## Notations @@ -1324,177 +1322,6 @@ end Int open Int -/-! ### Round -/ - - -section round - -section LinearOrderedRing - -variable [LinearOrderedRing α] [FloorRing α] - -/-- `round` rounds a number to the nearest integer. `round (1 / 2) = 1` -/ -def round (x : α) : ℤ := - if 2 * fract x < 1 then ⌊x⌋ else ⌈x⌉ - -@[simp] -theorem round_zero : round (0 : α) = 0 := by simp [round] - -@[simp] -theorem round_one : round (1 : α) = 1 := by simp [round] - -@[simp] -theorem round_natCast (n : ℕ) : round (n : α) = n := by simp [round] - -@[simp] -theorem round_ofNat (n : ℕ) [n.AtLeastTwo] : round (ofNat(n) : α) = ofNat(n) := - round_natCast n - -@[simp] -theorem round_intCast (n : ℤ) : round (n : α) = n := by simp [round] - -@[simp] -theorem round_add_int (x : α) (y : ℤ) : round (x + y) = round x + y := by - rw [round, round, Int.fract_add_int, Int.floor_add_int, Int.ceil_add_int, ← apply_ite₂, ite_self] - -@[simp] -theorem round_add_one (a : α) : round (a + 1) = round a + 1 := by - -- Porting note: broken `convert round_add_int a 1` - rw [← round_add_int a 1, cast_one] - -@[simp] -theorem round_sub_int (x : α) (y : ℤ) : round (x - y) = round x - y := by - rw [sub_eq_add_neg] - norm_cast - rw [round_add_int, sub_eq_add_neg] - -@[simp] -theorem round_sub_one (a : α) : round (a - 1) = round a - 1 := by - -- Porting note: broken `convert round_sub_int a 1` - rw [← round_sub_int a 1, cast_one] - -@[simp] -theorem round_add_nat (x : α) (y : ℕ) : round (x + y) = round x + y := - mod_cast round_add_int x y - -@[simp] -theorem round_add_ofNat (x : α) (n : ℕ) [n.AtLeastTwo] : - round (x + ofNat(n)) = round x + ofNat(n) := - round_add_nat x n - -@[simp] -theorem round_sub_nat (x : α) (y : ℕ) : round (x - y) = round x - y := - mod_cast round_sub_int x y - -@[simp] -theorem round_sub_ofNat (x : α) (n : ℕ) [n.AtLeastTwo] : - round (x - ofNat(n)) = round x - ofNat(n) := - round_sub_nat x n - -@[simp] -theorem round_int_add (x : α) (y : ℤ) : round ((y : α) + x) = y + round x := by - rw [add_comm, round_add_int, add_comm] - -@[simp] -theorem round_nat_add (x : α) (y : ℕ) : round ((y : α) + x) = y + round x := by - rw [add_comm, round_add_nat, add_comm] - -@[simp] -theorem round_ofNat_add (n : ℕ) [n.AtLeastTwo] (x : α) : - round (ofNat(n) + x) = ofNat(n) + round x := - round_nat_add x n - -theorem abs_sub_round_eq_min (x : α) : |x - round x| = min (fract x) (1 - fract x) := by - simp_rw [round, min_def_lt, two_mul, ← lt_tsub_iff_left] - cases' lt_or_ge (fract x) (1 - fract x) with hx hx - · rw [if_pos hx, if_pos hx, self_sub_floor, abs_fract] - · have : 0 < fract x := by - replace hx : 0 < fract x + fract x := lt_of_lt_of_le zero_lt_one (tsub_le_iff_left.mp hx) - simpa only [← two_mul, mul_pos_iff_of_pos_left, zero_lt_two] using hx - rw [if_neg (not_lt.mpr hx), if_neg (not_lt.mpr hx), abs_sub_comm, ceil_sub_self_eq this.ne.symm, - abs_one_sub_fract] - -theorem round_le (x : α) (z : ℤ) : |x - round x| ≤ |x - z| := by - rw [abs_sub_round_eq_min, min_le_iff] - rcases le_or_lt (z : α) x with (hx | hx) <;> [left; right] - · conv_rhs => rw [abs_eq_self.mpr (sub_nonneg.mpr hx), ← fract_add_floor x, add_sub_assoc] - simpa only [le_add_iff_nonneg_right, sub_nonneg, cast_le] using le_floor.mpr hx - · rw [abs_eq_neg_self.mpr (sub_neg.mpr hx).le] - conv_rhs => rw [← fract_add_floor x] - rw [add_sub_assoc, add_comm, neg_add, neg_sub, le_add_neg_iff_add_le, sub_add_cancel, - le_sub_comm] - norm_cast - exact floor_le_sub_one_iff.mpr hx - -end LinearOrderedRing - -section LinearOrderedField - -variable [LinearOrderedField α] [FloorRing α] - -theorem round_eq (x : α) : round x = ⌊x + 1 / 2⌋ := by - simp_rw [round, (by simp only [lt_div_iff₀', two_pos] : 2 * fract x < 1 ↔ fract x < 1 / 2)] - cases' lt_or_le (fract x) (1 / 2) with hx hx - · conv_rhs => rw [← fract_add_floor x, add_assoc, add_left_comm, floor_int_add] - rw [if_pos hx, self_eq_add_right, floor_eq_iff, cast_zero, zero_add] - constructor - · linarith [fract_nonneg x] - · linarith - · have : ⌊fract x + 1 / 2⌋ = 1 := by - rw [floor_eq_iff] - constructor - · norm_num - linarith - · norm_num - linarith [fract_lt_one x] - rw [if_neg (not_lt.mpr hx), ← fract_add_floor x, add_assoc, add_left_comm, floor_int_add, - ceil_add_int, add_comm _ ⌊x⌋, add_right_inj, ceil_eq_iff, this, cast_one, sub_self] - constructor - · linarith - · linarith [fract_lt_one x] - -@[simp] -theorem round_two_inv : round (2⁻¹ : α) = 1 := by - simp only [round_eq, ← one_div, add_halves, floor_one] - -@[simp] -theorem round_neg_two_inv : round (-2⁻¹ : α) = 0 := by - simp only [round_eq, ← one_div, neg_add_cancel, floor_zero] - -@[simp] -theorem round_eq_zero_iff {x : α} : round x = 0 ↔ x ∈ Ico (-(1 / 2)) ((1 : α) / 2) := by - rw [round_eq, floor_eq_zero_iff, add_mem_Ico_iff_left] - norm_num - -theorem abs_sub_round (x : α) : |x - round x| ≤ 1 / 2 := by - rw [round_eq, abs_sub_le_iff] - have := floor_le (x + 1 / 2) - have := lt_floor_add_one (x + 1 / 2) - constructor <;> linarith - -theorem abs_sub_round_div_natCast_eq {m n : ℕ} : - |(m : α) / n - round ((m : α) / n)| = ↑(min (m % n) (n - m % n)) / n := by - rcases n.eq_zero_or_pos with (rfl | hn) - · simp - have hn' : 0 < (n : α) := by - norm_cast - rw [abs_sub_round_eq_min, Nat.cast_min, ← min_div_div_right hn'.le, - fract_div_natCast_eq_div_natCast_mod, Nat.cast_sub (m.mod_lt hn).le, sub_div, div_self hn'.ne'] - -@[bound] -theorem sub_half_lt_round (x : α) : x - 1 / 2 < round x := by - rw [round_eq x, show x - 1 / 2 = x + 1 / 2 - 1 by linarith] - exact Int.sub_one_lt_floor (x + 1 / 2) - -@[bound] -theorem round_le_add_half (x : α) : round x ≤ x + 1 / 2 := by - rw [round_eq x] - exact Int.floor_le (x + 1 / 2) - -end LinearOrderedField - -end round - namespace Nat variable [LinearOrderedSemiring α] [LinearOrderedSemiring β] [FloorSemiring α] [FloorSemiring β] @@ -1539,20 +1366,6 @@ theorem map_fract (f : F) (hf : StrictMono f) (a : α) : fract (f a) = f (fract end Int -namespace Int - -variable [LinearOrderedField α] [LinearOrderedField β] [FloorRing α] [FloorRing β] -variable [FunLike F α β] [RingHomClass F α β] {a : α} {b : β} - -theorem map_round (f : F) (hf : StrictMono f) (a : α) : round (f a) = round a := by - have H : f 2 = 2 := map_natCast f 2 - simp_rw [round_eq, ← map_floor _ hf, map_add, one_div, map_inv₀, H] - -- Porting note: was - -- simp_rw [round_eq, ← map_floor _ hf, map_add, one_div, map_inv₀, map_bit0, map_one] - -- Would have thought that `map_natCast` would replace `map_bit0, map_one` but seems not - -end Int - section FloorRingToSemiring variable [LinearOrderedRing α] [FloorRing α] @@ -1673,5 +1486,3 @@ def evalIntCeil : PositivityExt where eval {u α} _zα _pα e := do | _, _, _ => throwError "failed to match on Int.ceil application" end Mathlib.Meta.Positivity - -set_option linter.style.longFile 1800 diff --git a/Mathlib/Algebra/Order/Round.lean b/Mathlib/Algebra/Order/Round.lean new file mode 100644 index 0000000000000..126741c7c3750 --- /dev/null +++ b/Mathlib/Algebra/Order/Round.lean @@ -0,0 +1,214 @@ +/- +Copyright (c) 2018 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro, Kevin Kappelmann +-/ +import Mathlib.Algebra.Order.Floor +import Mathlib.Algebra.Order.Interval.Set.Group + +/-! +# Rounding + +This file defines the `round` function, which uses the `floor` or `ceil` function to round a number +to the nearest integer. + +## Main Definitions + +* `round a`: Nearest integer to `a`. It rounds halves towards infinity. + +## Tags + +rounding +-/ + +assert_not_exists Finset + +open Set + +variable {F α β : Type*} + +open Int + +/-! ### Round -/ + +section round + +section LinearOrderedRing + +variable [LinearOrderedRing α] [FloorRing α] + +/-- `round` rounds a number to the nearest integer. `round (1 / 2) = 1` -/ +def round (x : α) : ℤ := + if 2 * fract x < 1 then ⌊x⌋ else ⌈x⌉ + +@[simp] +theorem round_zero : round (0 : α) = 0 := by simp [round] + +@[simp] +theorem round_one : round (1 : α) = 1 := by simp [round] + +@[simp] +theorem round_natCast (n : ℕ) : round (n : α) = n := by simp [round] + +@[simp] +theorem round_ofNat (n : ℕ) [n.AtLeastTwo] : round (ofNat(n) : α) = ofNat(n) := + round_natCast n + +@[simp] +theorem round_intCast (n : ℤ) : round (n : α) = n := by simp [round] + +@[simp] +theorem round_add_int (x : α) (y : ℤ) : round (x + y) = round x + y := by + rw [round, round, Int.fract_add_int, Int.floor_add_int, Int.ceil_add_int, ← apply_ite₂, ite_self] + +@[simp] +theorem round_add_one (a : α) : round (a + 1) = round a + 1 := by + -- Porting note: broken `convert round_add_int a 1` + rw [← round_add_int a 1, cast_one] + +@[simp] +theorem round_sub_int (x : α) (y : ℤ) : round (x - y) = round x - y := by + rw [sub_eq_add_neg] + norm_cast + rw [round_add_int, sub_eq_add_neg] + +@[simp] +theorem round_sub_one (a : α) : round (a - 1) = round a - 1 := by + -- Porting note: broken `convert round_sub_int a 1` + rw [← round_sub_int a 1, cast_one] + +@[simp] +theorem round_add_nat (x : α) (y : ℕ) : round (x + y) = round x + y := + mod_cast round_add_int x y + +@[simp] +theorem round_add_ofNat (x : α) (n : ℕ) [n.AtLeastTwo] : + round (x + ofNat(n)) = round x + ofNat(n) := + round_add_nat x n + +@[simp] +theorem round_sub_nat (x : α) (y : ℕ) : round (x - y) = round x - y := + mod_cast round_sub_int x y + +@[simp] +theorem round_sub_ofNat (x : α) (n : ℕ) [n.AtLeastTwo] : + round (x - ofNat(n)) = round x - ofNat(n) := + round_sub_nat x n + +@[simp] +theorem round_int_add (x : α) (y : ℤ) : round ((y : α) + x) = y + round x := by + rw [add_comm, round_add_int, add_comm] + +@[simp] +theorem round_nat_add (x : α) (y : ℕ) : round ((y : α) + x) = y + round x := by + rw [add_comm, round_add_nat, add_comm] + +@[simp] +theorem round_ofNat_add (n : ℕ) [n.AtLeastTwo] (x : α) : + round (ofNat(n) + x) = ofNat(n) + round x := + round_nat_add x n + +theorem abs_sub_round_eq_min (x : α) : |x - round x| = min (fract x) (1 - fract x) := by + simp_rw [round, min_def_lt, two_mul, ← lt_tsub_iff_left] + cases' lt_or_ge (fract x) (1 - fract x) with hx hx + · rw [if_pos hx, if_pos hx, self_sub_floor, abs_fract] + · have : 0 < fract x := by + replace hx : 0 < fract x + fract x := lt_of_lt_of_le zero_lt_one (tsub_le_iff_left.mp hx) + simpa only [← two_mul, mul_pos_iff_of_pos_left, zero_lt_two] using hx + rw [if_neg (not_lt.mpr hx), if_neg (not_lt.mpr hx), abs_sub_comm, ceil_sub_self_eq this.ne.symm, + abs_one_sub_fract] + +theorem round_le (x : α) (z : ℤ) : |x - round x| ≤ |x - z| := by + rw [abs_sub_round_eq_min, min_le_iff] + rcases le_or_lt (z : α) x with (hx | hx) <;> [left; right] + · conv_rhs => rw [abs_eq_self.mpr (sub_nonneg.mpr hx), ← fract_add_floor x, add_sub_assoc] + simpa only [le_add_iff_nonneg_right, sub_nonneg, cast_le] using le_floor.mpr hx + · rw [abs_eq_neg_self.mpr (sub_neg.mpr hx).le] + conv_rhs => rw [← fract_add_floor x] + rw [add_sub_assoc, add_comm, neg_add, neg_sub, le_add_neg_iff_add_le, sub_add_cancel, + le_sub_comm] + norm_cast + exact floor_le_sub_one_iff.mpr hx + +end LinearOrderedRing + +section LinearOrderedField + +variable [LinearOrderedField α] [FloorRing α] + +theorem round_eq (x : α) : round x = ⌊x + 1 / 2⌋ := by + simp_rw [round, (by simp only [lt_div_iff₀', two_pos] : 2 * fract x < 1 ↔ fract x < 1 / 2)] + cases' lt_or_le (fract x) (1 / 2) with hx hx + · conv_rhs => rw [← fract_add_floor x, add_assoc, add_left_comm, floor_int_add] + rw [if_pos hx, self_eq_add_right, floor_eq_iff, cast_zero, zero_add] + constructor + · linarith [fract_nonneg x] + · linarith + · have : ⌊fract x + 1 / 2⌋ = 1 := by + rw [floor_eq_iff] + constructor + · norm_num + linarith + · norm_num + linarith [fract_lt_one x] + rw [if_neg (not_lt.mpr hx), ← fract_add_floor x, add_assoc, add_left_comm, floor_int_add, + ceil_add_int, add_comm _ ⌊x⌋, add_right_inj, ceil_eq_iff, this, cast_one, sub_self] + constructor + · linarith + · linarith [fract_lt_one x] + +@[simp] +theorem round_two_inv : round (2⁻¹ : α) = 1 := by + simp only [round_eq, ← one_div, add_halves, floor_one] + +@[simp] +theorem round_neg_two_inv : round (-2⁻¹ : α) = 0 := by + simp only [round_eq, ← one_div, neg_add_cancel, floor_zero] + +@[simp] +theorem round_eq_zero_iff {x : α} : round x = 0 ↔ x ∈ Ico (-(1 / 2)) ((1 : α) / 2) := by + rw [round_eq, floor_eq_zero_iff, add_mem_Ico_iff_left] + norm_num + +theorem abs_sub_round (x : α) : |x - round x| ≤ 1 / 2 := by + rw [round_eq, abs_sub_le_iff] + have := floor_le (x + 1 / 2) + have := lt_floor_add_one (x + 1 / 2) + constructor <;> linarith + +theorem abs_sub_round_div_natCast_eq {m n : ℕ} : + |(m : α) / n - round ((m : α) / n)| = ↑(min (m % n) (n - m % n)) / n := by + rcases n.eq_zero_or_pos with (rfl | hn) + · simp + have hn' : 0 < (n : α) := by + norm_cast + rw [abs_sub_round_eq_min, Nat.cast_min, ← min_div_div_right hn'.le, + fract_div_natCast_eq_div_natCast_mod, Nat.cast_sub (m.mod_lt hn).le, sub_div, div_self hn'.ne'] + +@[bound] +theorem sub_half_lt_round (x : α) : x - 1 / 2 < round x := by + rw [round_eq x, show x - 1 / 2 = x + 1 / 2 - 1 by linarith] + exact Int.sub_one_lt_floor (x + 1 / 2) + +@[bound] +theorem round_le_add_half (x : α) : round x ≤ x + 1 / 2 := by + rw [round_eq x] + exact Int.floor_le (x + 1 / 2) + +end LinearOrderedField + +end round + +namespace Int + +variable [LinearOrderedField α] [LinearOrderedField β] [FloorRing α] [FloorRing β] +variable [FunLike F α β] [RingHomClass F α β] {a : α} {b : β} + +theorem map_round (f : F) (hf : StrictMono f) (a : α) : round (f a) = round a := by + have H : f 2 = 2 := map_natCast f 2 + simp_rw [round_eq, ← map_floor _ hf, map_add, one_div, map_inv₀, H] + -- Porting note: was + -- simp_rw [round_eq, ← map_floor _ hf, map_add, one_div, map_inv₀, map_bit0, map_one] + -- Would have thought that `map_natCast` would replace `map_bit0, map_one` but seems not + +end Int diff --git a/Mathlib/Data/Rat/Floor.lean b/Mathlib/Data/Rat/Floor.lean index fa01f1ac3ee5f..42464ab2589e4 100644 --- a/Mathlib/Data/Rat/Floor.lean +++ b/Mathlib/Data/Rat/Floor.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Kappelmann -/ -import Mathlib.Algebra.Order.Floor +import Mathlib.Algebra.Order.Round import Mathlib.Data.Rat.Cast.Order import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.Ring From f09f967a6d4ee720ea781ad997e369eed8c046a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Mon, 20 Jan 2025 01:43:49 +0000 Subject: [PATCH 315/681] feat: inequalities on complex exponentials (#20844) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two inequalities on complex exponentials: ```lean abs (cexp x - ∑ m ∈ range n, x ^ m / m.factorial) ≤ Real.exp (abs x) - ∑ m ∈ range n, (abs x) ^ m / m.factorial abs (cexp x - ∑ m ∈ range n, x ^ m / m.factorial) ≤ abs x ^ n * Real.exp (abs x) ``` --- Mathlib/Data/Complex/Exponential.lean | 65 +++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index 0b65e9e791485..af666d90bb9c4 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -1175,6 +1175,71 @@ theorem abs_exp_sub_one_sub_id_le {x : ℂ} (hx : abs x ≤ 1) : abs (exp x - 1 _ ≤ abs x ^ 2 * 1 := by gcongr; norm_num [Nat.factorial] _ = abs x ^ 2 := by rw [mul_one] +lemma abs_exp_sub_sum_le_exp_abs_sub_sum (x : ℂ) (n : ℕ) : + abs (exp x - ∑ m ∈ range n, x ^ m / m.factorial) + ≤ Real.exp (abs x) - ∑ m ∈ range n, (abs x) ^ m / m.factorial := by + rw [← CauSeq.lim_const (abv := Complex.abs) (∑ m ∈ range n, _), Complex.exp, sub_eq_add_neg, + ← CauSeq.lim_neg, CauSeq.lim_add, ← lim_abs] + refine CauSeq.lim_le (CauSeq.le_of_exists ⟨n, fun j hj => ?_⟩) + simp_rw [← sub_eq_add_neg] + calc abs ((∑ m ∈ range j, x ^ m / m.factorial) - ∑ m ∈ range n, x ^ m / m.factorial) + _ ≤ (∑ m ∈ range j, abs x ^ m / m.factorial) - ∑ m ∈ range n, abs x ^ m / m.factorial := by + rw [sum_range_sub_sum_range hj, sum_range_sub_sum_range hj] + refine (IsAbsoluteValue.abv_sum Complex.abs ..).trans_eq ?_ + congr with i + simp + _ ≤ Real.exp (abs x) - ∑ m ∈ range n, (abs x) ^ m / m.factorial := by + gcongr + exact Real.sum_le_exp_of_nonneg (by exact AbsoluteValue.nonneg abs x) _ + +lemma abs_exp_le_exp_abs (x : ℂ) : abs (exp x) ≤ Real.exp (abs x) := by + convert abs_exp_sub_sum_le_exp_abs_sub_sum x 0 using 1 <;> simp + +lemma abs_exp_sub_sum_le_abs_mul_exp (x : ℂ) (n : ℕ) : + abs (exp x - ∑ m ∈ range n, x ^ m / m.factorial) ≤ abs x ^ n * Real.exp (abs x) := by + rw [← CauSeq.lim_const (abv := Complex.abs) (∑ m ∈ range n, _), Complex.exp, sub_eq_add_neg, + ← CauSeq.lim_neg, CauSeq.lim_add, ← lim_abs] + refine CauSeq.lim_le (CauSeq.le_of_exists ⟨n, fun j hj => ?_⟩) + simp_rw [← sub_eq_add_neg] + show abs ((∑ m ∈ range j, x ^ m / m.factorial) - ∑ m ∈ range n, x ^ m / m.factorial) ≤ _ + rw [sum_range_sub_sum_range hj] + calc + abs (∑ m ∈ range j with n ≤ m, (x ^ m / m.factorial : ℂ)) + = abs (∑ m ∈ range j with n ≤ m, (x ^ n * (x ^ (m - n) / m.factorial) : ℂ)) := by + refine congr_arg abs (sum_congr rfl fun m hm => ?_) + rw [mem_filter, mem_range] at hm + rw [← mul_div_assoc, ← pow_add, add_tsub_cancel_of_le hm.2] + _ ≤ ∑ m ∈ range j with n ≤ m, abs (x ^ n * (x ^ (m - n) / m.factorial)) := + IsAbsoluteValue.abv_sum Complex.abs .. + _ ≤ ∑ m ∈ range j with n ≤ m, abs x ^ n * (abs x ^ (m - n) / (m - n).factorial) := by + simp_rw [map_mul, map_pow, map_div₀, abs_natCast] + gcongr with i hi + · rw [IsAbsoluteValue.abv_pow abs] + · simp + _ = abs x ^ n * ∑ m ∈ range j with n ≤ m, (abs x ^ (m - n) / (m - n).factorial) := by + rw [← mul_sum] + _ = abs x ^ n * ∑ m ∈ range (j - n), (abs x ^ m / m.factorial) := by + congr 1 + refine (sum_bij (fun m hm ↦ m + n) ?_ ?_ ?_ ?_).symm + · intro a ha + simp only [mem_filter, mem_range, le_add_iff_nonneg_left, zero_le, and_true] + simp only [mem_range] at ha + rwa [← lt_tsub_iff_right] + · intro a ha b hb hab + simpa using hab + · intro b hb + simp only [mem_range, exists_prop] + simp only [mem_filter, mem_range] at hb + refine ⟨b - n, ?_, ?_⟩ + · rw [tsub_lt_tsub_iff_right hb.2] + exact hb.1 + · rw [tsub_add_cancel_of_le hb.2] + · simp + _ ≤ abs x ^ n * Real.exp (abs x) := by + gcongr + refine Real.sum_le_exp_of_nonneg ?_ _ + exact AbsoluteValue.nonneg abs x + end Complex namespace Real From 14f0a1382011ccb2deb1d64194683eaf7d3dc6b5 Mon Sep 17 00:00:00 2001 From: Alex Meiburg Date: Mon, 20 Jan 2025 03:19:41 +0000 Subject: [PATCH 316/681] doc(MeasurableSpace/CountablyGenerated): fix declaration names in module doc (#20863) Two docstrings had the wrong theorem name. --- Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean b/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean index 5d1379bf8604a..8216fb8b065b7 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean @@ -27,10 +27,10 @@ the space such that the measurable space is generated by the union of all partit ## Main statements -* `MeasurableSpace.measurable_equiv_nat_bool_of_countablyGenerated`: if a measurable space is +* `MeasurableSpace.measurableEquiv_nat_bool_of_countablyGenerated`: if a measurable space is countably generated and separates points, it is measure equivalent to a subset of the Cantor Space `ℕ → Bool` (equipped with the product sigma algebra). -* `MeasurableSpace.measurable_injection_nat_bool_of_countablyGenerated`: If a measurable space +* `MeasurableSpace.measurable_injection_nat_bool_of_countablySeparated`: If a measurable space admits a countable sequence of measurable sets separating points, it admits a measurable injection into the Cantor space `ℕ → Bool` `ℕ → Bool` (equipped with the product sigma algebra). From 510fdca8a0a1901e6a8d6ae7b3a417aaa9e90cba Mon Sep 17 00:00:00 2001 From: "Tristan F.-R." Date: Mon, 20 Jan 2025 04:11:09 +0000 Subject: [PATCH 317/681] feat(SetTheory/Order/Basic): not_lt_iff_not_le_or_ge (#19973) Adds `not_lt_iff_not_le_or_ge` to produce `not_lt` in complement of `not_lf` and `not_le`. Co-authored-by: Tristan F. Co-authored-by: Tristan F.-R. --- Mathlib/Order/Basic.lean | 3 +++ Mathlib/SetTheory/Game/PGame.lean | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index 0f96648eca68c..6b4dfb2191463 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -79,6 +79,9 @@ theorem lt_of_le_of_lt' : b ≤ c → a < b → a < c := theorem lt_of_lt_of_le' : b < c → a ≤ b → a < c := flip lt_of_le_of_lt +theorem not_lt_iff_not_le_or_ge : ¬a < b ↔ ¬a ≤ b ∨ b ≤ a := by + rw [lt_iff_le_not_le, Classical.not_and_iff_or_not_not, Classical.not_not] + end Preorder section PartialOrder diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 3ae1499b5e7eb..2b9242c3d6631 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -635,6 +635,8 @@ theorem lf_irrefl (x : PGame) : ¬x ⧏ x := instance : IsIrrefl _ (· ⧏ ·) := ⟨lf_irrefl⟩ +protected theorem not_lt {x y : PGame} : ¬ x < y ↔ y ⧏ x ∨ y ≤ x := not_lt_iff_not_le_or_ge + @[trans] theorem lf_of_le_of_lf {x y z : PGame} (h₁ : x ≤ y) (h₂ : y ⧏ z) : x ⧏ z := by rw [← PGame.not_le] at h₂ ⊢ From 0f52dbc81e1f931efb1b41f8ced91dae40d1d4f4 Mon Sep 17 00:00:00 2001 From: Oliver Nash Date: Mon, 20 Jan 2025 04:58:27 +0000 Subject: [PATCH 318/681] feat: restriction of scalars for root pairings with coefficients in a field (#20384) The headline result is `RootPairing.restrictScalars`. --- Mathlib.lean | 1 + .../LinearAlgebra/PerfectPairing/Basic.lean | 21 +++ .../LinearAlgebra/RootSystem/BaseChange.lean | 128 ++++++++++++++++++ Mathlib/LinearAlgebra/RootSystem/Defs.lean | 7 + .../RootSystem/Finite/Nondegenerate.lean | 25 ++++ 5 files changed, 182 insertions(+) create mode 100644 Mathlib/LinearAlgebra/RootSystem/BaseChange.lean diff --git a/Mathlib.lean b/Mathlib.lean index aa9c14349ab99..7ec4b7562084a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3586,6 +3586,7 @@ import Mathlib.LinearAlgebra.Quotient.Pi import Mathlib.LinearAlgebra.Ray import Mathlib.LinearAlgebra.Reflection import Mathlib.LinearAlgebra.RootSystem.Base +import Mathlib.LinearAlgebra.RootSystem.BaseChange import Mathlib.LinearAlgebra.RootSystem.Basic import Mathlib.LinearAlgebra.RootSystem.Defs import Mathlib.LinearAlgebra.RootSystem.Finite.CanonicalBilinear diff --git a/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean b/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean index 50ffa39ec68c9..6aaa7e342862c 100644 --- a/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean +++ b/Mathlib/LinearAlgebra/PerfectPairing/Basic.lean @@ -204,6 +204,27 @@ protected lemma flip (h : p.IsPerfectCompl U V) : isCompl_left := h.isCompl_right isCompl_right := h.isCompl_left +@[simp] +protected lemma flip_iff : + p.flip.IsPerfectCompl V U ↔ p.IsPerfectCompl U V := + ⟨fun h ↦ h.flip, fun h ↦ h.flip⟩ + +@[simp] +lemma left_top_iff : + p.IsPerfectCompl ⊤ V ↔ V = ⊤ := by + refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ + · exact eq_top_of_isCompl_bot <| by simpa using h.isCompl_right + · rw [h] + exact + { isCompl_left := by simpa using isCompl_top_bot + isCompl_right := by simpa using isCompl_top_bot } + +@[simp] +lemma right_top_iff : + p.IsPerfectCompl U ⊤ ↔ U = ⊤ := by + rw [← IsPerfectCompl.flip_iff] + exact left_top_iff + end IsPerfectCompl end PerfectPairing diff --git a/Mathlib/LinearAlgebra/RootSystem/BaseChange.lean b/Mathlib/LinearAlgebra/RootSystem/BaseChange.lean new file mode 100644 index 0000000000000..5b095cfca25a4 --- /dev/null +++ b/Mathlib/LinearAlgebra/RootSystem/BaseChange.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2025 Oliver Nash. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Oliver Nash +-/ +import Mathlib.Algebra.Algebra.Rat +import Mathlib.LinearAlgebra.PerfectPairing.Restrict +import Mathlib.LinearAlgebra.RootSystem.Defs + +/-! +# Base change for root pairings + +When the coefficients are a field, root pairings behave well with respect to restriction and +extension of scalars. + +## Main results: + * `RootPairing.restrict`: if `RootPairing.pairing` takes values in a subfield, we may restrict to + get a root _system_ with coefficients in the subfield. Of particular interest is the case when + the pairing takes values in its prime subfield (which happens for crystallographic pairings). + +## TODO + + * Extension of scalars + +-/ + +noncomputable section + +open Set Function +open Submodule (span injective_subtype span subset_span span_setOf_mem_eq_top) + +namespace RootPairing + +/-- We say a root pairing is balanced if the root span and coroot span are perfectly +complementary. + +All root systems are balanced and all finite root pairings over a field are balanced. -/ +class IsBalanced {ι R M N : Type*} [AddCommGroup M] [AddCommGroup N] + [CommRing R] [Module R M] [Module R N] (P : RootPairing ι R M N) : Prop where + isPerfectCompl : P.toPerfectPairing.IsPerfectCompl P.rootSpan P.corootSpan + +instance {ι R M N : Type*} [AddCommGroup M] [AddCommGroup N] + [CommRing R] [Module R M] [Module R N] (P : RootSystem ι R M N) : + P.IsBalanced where + isPerfectCompl := by simp + +variable {ι L M N : Type*} + [Field L] [AddCommGroup M] [AddCommGroup N] [Module L M] [Module L N] + (P : RootPairing ι L M N) + +section restrictScalars + +variable (K : Type*) [Field K] [Algebra K L] + [Module K M] [Module K N] [IsScalarTower K L M] [IsScalarTower K L N] + [P.IsBalanced] + +section SubfieldValued + +variable (hP : ∀ i j, P.pairing i j ∈ (algebraMap K L).range) + +/-- Restriction of scalars for a root pairing taking values in a subfield. + +Note that we obtain a root system (not just a root pairing). See also +`RootPairing.restrictScalars`. -/ +def restrictScalars' : + RootSystem ι K (span K (range P.root)) (span K (range P.coroot)) := + { toPerfectPairing := (P.toPerfectPairing.restrictScalarsField _ _ + (injective_subtype _) (injective_subtype _) (by simpa using IsBalanced.isPerfectCompl) + (fun x y ↦ LinearMap.BilinMap.apply_apply_mem_of_mem_span + (LinearMap.range (Algebra.linearMap K L)) (range P.root) (range P.coroot) + ((LinearMap.restrictScalarsₗ K L _ _ _) ∘ₗ (P.toPerfectPairing.toLin.restrictScalars K)) + (by rintro - ⟨i, rfl⟩ - ⟨j, rfl⟩; exact hP i j) _ _ x.property y.property)) + root := ⟨fun i ↦ ⟨_, subset_span (mem_range_self i)⟩, fun i j h ↦ by simpa using h⟩ + coroot := ⟨fun i ↦ ⟨_, subset_span (mem_range_self i)⟩, fun i j h ↦ by simpa using h⟩ + root_coroot_two i := by + have : algebraMap K L 2 = 2 := by + rw [← Int.cast_two (R := K), ← Int.cast_two (R := L), map_intCast] + exact NoZeroSMulDivisors.algebraMap_injective K L <| by simp [this] + reflection_perm := P.reflection_perm + reflection_perm_root i j := by + ext; simpa [algebra_compatible_smul L] using P.reflection_perm_root i j + reflection_perm_coroot i j := by + ext; simpa [algebra_compatible_smul L] using P.reflection_perm_coroot i j + span_root_eq_top := by + rw [← span_setOf_mem_eq_top] + congr + ext ⟨x, hx⟩ + simp + span_coroot_eq_top := by + rw [← span_setOf_mem_eq_top] + congr + ext ⟨x, hx⟩ + simp } + +@[simp] lemma restrictScalars_toPerfectPairing_apply_apply + (x : span K (range P.root)) (y : span K (range P.coroot)) : + algebraMap K L ((P.restrictScalars' K hP).toPerfectPairing x y) = P.toPerfectPairing x y := by + simp [restrictScalars'] + +@[simp] lemma restrictScalars_coe_root (i : ι) : + (P.restrictScalars' K hP).root i = P.root i := + rfl + +@[simp] lemma restrictScalars_coe_coroot (i : ι) : + (P.restrictScalars' K hP).coroot i = P.coroot i := + rfl + +@[simp] lemma restrictScalars_pairing (i j : ι) : + algebraMap K L ((P.restrictScalars' K hP).pairing i j) = P.pairing i j := by + simp only [pairing, restrictScalars_toPerfectPairing_apply_apply, restrictScalars_coe_root, + restrictScalars_coe_coroot] + +end SubfieldValued + +/-- Restriction of scalars for a crystallographic root pairing. -/ +abbrev restrictScalars [P.IsCrystallographic] : + RootSystem ι K (span K (range P.root)) (span K (range P.coroot)) := + P.restrictScalars' K <| IsCrystallographic.mem_range_algebraMap P K + +/-- Restriction of scalars to `ℚ` for a crystallographic root pairing in characteristic zero. -/ +abbrev restrictScalarsRat [CharZero L] [P.IsCrystallographic] := + let _i : Module ℚ M := Module.compHom M (algebraMap ℚ L) + let _i : Module ℚ N := Module.compHom N (algebraMap ℚ L) + P.restrictScalars ℚ + +end restrictScalars + +end RootPairing diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index 8b01626b5d947..8216ae6e996a4 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -397,6 +397,13 @@ instance [P.IsCrystallographic] : P.flip.IsCrystallographic := by rw [isCrystallographic_iff, forall_comm] exact P.exists_int +lemma IsCrystallographic.mem_range_algebraMap [P.IsCrystallographic] + (S : Type*) [CommRing S] [Algebra S R] (i j : ι) : + P.pairing i j ∈ (algebraMap S R).range := by + obtain ⟨k, hk⟩ := P.exists_int i j + simp only [RingHom.mem_range] + exact ⟨k, by simpa⟩ + /-- A root pairing is said to be reduced if any linearly dependent pair of roots is related by a sign. -/ def IsReduced : Prop := diff --git a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean index 1d04a0c2f32ce..60b73071e6aae 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean @@ -7,6 +7,7 @@ import Mathlib.LinearAlgebra.BilinearForm.Basic import Mathlib.LinearAlgebra.BilinearForm.Orthogonal import Mathlib.LinearAlgebra.Dimension.Localization import Mathlib.LinearAlgebra.QuadraticForm.Basic +import Mathlib.LinearAlgebra.RootSystem.BaseChange import Mathlib.LinearAlgebra.RootSystem.Finite.CanonicalBilinear /-! @@ -159,6 +160,30 @@ lemma isCompl_corootSpan_ker_corootForm : IsCompl P.corootSpan (LinearMap.ker P.CorootForm) := P.flip.isCompl_rootSpan_ker_rootForm +lemma ker_rootForm_eq_dualAnnihilator : + LinearMap.ker P.RootForm = P.corootSpan.dualAnnihilator.map P.toDualLeft.symm := by + have _iM : IsReflexive R M := PerfectPairing.reflexive_left P.toPerfectPairing + have _iN : IsReflexive R N := PerfectPairing.reflexive_right P.toPerfectPairing + suffices finrank R (LinearMap.ker P.RootForm) = finrank R P.corootSpan.dualAnnihilator by + refine (Submodule.eq_of_le_of_finrank_eq P.corootSpan_dualAnnihilator_le_ker_rootForm ?_).symm + rw [this] + apply LinearEquiv.finrank_map_eq + have aux0 := Subspace.finrank_add_finrank_dualAnnihilator_eq P.corootSpan + have aux1 := Submodule.finrank_add_eq_of_isCompl P.isCompl_rootSpan_ker_rootForm + rw [← P.finrank_corootSpan_eq, P.toPerfectPairing.finrank_eq] at aux1 + omega + +lemma ker_corootForm_eq_dualAnnihilator : + LinearMap.ker P.CorootForm = P.rootSpan.dualAnnihilator.map P.toDualRight.symm := + P.flip.ker_rootForm_eq_dualAnnihilator + +instance : P.IsBalanced where + isPerfectCompl := + { isCompl_left := by + simpa only [ker_rootForm_eq_dualAnnihilator] using P.isCompl_rootSpan_ker_rootForm + isCompl_right := by + simpa only [ker_corootForm_eq_dualAnnihilator] using P.isCompl_corootSpan_ker_corootForm } + /-- See also `RootPairing.rootForm_restrict_nondegenerate_of_ordered`. Note that this applies to crystallographic root systems in characteristic zero via From c4510a08da413b6c60c3eb8d5304aa45426b3b64 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 20 Jan 2025 08:54:15 +0000 Subject: [PATCH 319/681] =?UTF-8?q?feat:=20make=20`Sub=20=E2=84=9D?= =?UTF-8?q?=E2=89=A50`=20and=20`Sub=20=E2=84=9D=E2=89=A50=E2=88=9E`=20comp?= =?UTF-8?q?utable=20(#20856)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This comes for free by relaxing some unnecessarily-strong typeclass requirements. (as a reminder, `LinearOrder NNReal` is noncomputable as it contains noncomputable `Decidable` instances) --- Mathlib/Algebra/Order/Nonneg/Basic.lean | 22 +++++++++++++--------- Mathlib/Data/ENNReal/Basic.lean | 8 ++++---- Mathlib/Data/NNReal/Defs.lean | 10 +++++----- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Mathlib/Algebra/Order/Nonneg/Basic.lean b/Mathlib/Algebra/Order/Nonneg/Basic.lean index 31863d814ea0c..b802e57fd0526 100644 --- a/Mathlib/Algebra/Order/Nonneg/Basic.lean +++ b/Mathlib/Algebra/Order/Nonneg/Basic.lean @@ -242,13 +242,12 @@ instance commMonoidWithZero : CommMonoidWithZero { x : α // 0 ≤ x } := inferI end CommSemiring -section LinearOrder - -variable [Zero α] [LinearOrder α] +section SemilatticeSup +variable [Zero α] [SemilatticeSup α] /-- The function `a ↦ max a 0` of type `α → {x : α // 0 ≤ x}`. -/ def toNonneg (a : α) : { x : α // 0 ≤ x } := - ⟨max a 0, le_max_right _ _⟩ + ⟨max a 0, le_sup_right⟩ @[simp] theorem coe_toNonneg {a : α} : (toNonneg a : α) = max a 0 := @@ -266,11 +265,6 @@ theorem toNonneg_le {a : α} {b : { x : α // 0 ≤ x }} : toNonneg a ≤ b ↔ cases' b with b hb simp [toNonneg, hb] -@[simp] -theorem toNonneg_lt {a : { x : α // 0 ≤ x }} {b : α} : a < toNonneg b ↔ ↑a < b := by - cases' a with a ha - simp [toNonneg, ha.not_lt] - instance sub [Sub α] : Sub { x : α // 0 ≤ x } := ⟨fun x y => toNonneg (x - y)⟩ @@ -279,6 +273,16 @@ theorem mk_sub_mk [Sub α] {x y : α} (hx : 0 ≤ x) (hy : 0 ≤ y) : (⟨x, hx⟩ : { x : α // 0 ≤ x }) - ⟨y, hy⟩ = toNonneg (x - y) := rfl +end SemilatticeSup + +section LinearOrder +variable [Zero α] [LinearOrder α] + +@[simp] +theorem toNonneg_lt {a : { x : α // 0 ≤ x }} {b : α} : a < toNonneg b ↔ ↑a < b := by + cases' a with a ha + simp [toNonneg, ha.not_lt] + end LinearOrder end Nonneg diff --git a/Mathlib/Data/ENNReal/Basic.lean b/Mathlib/Data/ENNReal/Basic.lean index 4ce8bf4d46529..9ff94a4245b6a 100644 --- a/Mathlib/Data/ENNReal/Basic.lean +++ b/Mathlib/Data/ENNReal/Basic.lean @@ -127,8 +127,8 @@ instance : DenselyOrdered ℝ≥0∞ := inferInstanceAs (DenselyOrdered (WithTop noncomputable instance : LinearOrderedAddCommMonoid ℝ≥0∞ := inferInstanceAs (LinearOrderedAddCommMonoid (WithTop ℝ≥0)) -noncomputable instance instSub : Sub ℝ≥0∞ := inferInstanceAs (Sub (WithTop ℝ≥0)) -noncomputable instance : OrderedSub ℝ≥0∞ := inferInstanceAs (OrderedSub (WithTop ℝ≥0)) +instance instSub : Sub ℝ≥0∞ := inferInstanceAs (Sub (WithTop ℝ≥0)) +instance : OrderedSub ℝ≥0∞ := inferInstanceAs (OrderedSub (WithTop ℝ≥0)) noncomputable instance : LinearOrderedAddCommMonoidWithTop ℝ≥0∞ := inferInstanceAs (LinearOrderedAddCommMonoidWithTop (WithTop ℝ≥0)) @@ -152,7 +152,7 @@ noncomputable instance : LinearOrderedCommMonoidWithZero ℝ≥0∞ := mul_le_mul_left := fun _ _ => mul_le_mul_left' zero_le_one := zero_le 1 } -noncomputable instance : Unique (AddUnits ℝ≥0∞) where +instance : Unique (AddUnits ℝ≥0∞) where default := 0 uniq a := AddUnits.ext <| le_zero_iff.1 <| by rw [← a.add_neg]; exact le_self_add @@ -192,7 +192,7 @@ protected def toNNReal : ℝ≥0∞ → ℝ≥0 := WithTop.untop' 0 protected def toReal (a : ℝ≥0∞) : Real := a.toNNReal /-- `ofReal x` returns `x` if it is nonnegative, `0` otherwise. -/ -protected noncomputable def ofReal (r : Real) : ℝ≥0∞ := r.toNNReal +protected def ofReal (r : Real) : ℝ≥0∞ := r.toNNReal @[simp, norm_cast] lemma toNNReal_coe (r : ℝ≥0) : (r : ℝ≥0∞).toNNReal = r := rfl diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index 68c6a36bd742b..61436b72dc932 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -68,8 +68,8 @@ instance instArchimedean : Archimedean ℝ≥0 := Nonneg.instArchimedean instance instMulArchimedean : MulArchimedean ℝ≥0 := Nonneg.instMulArchimedean instance : Min ℝ≥0 := SemilatticeInf.toMin instance : Max ℝ≥0 := SemilatticeSup.toMax -noncomputable instance : Sub ℝ≥0 := Nonneg.sub -noncomputable instance : OrderedSub ℝ≥0 := Nonneg.orderedSub +instance : Sub ℝ≥0 := Nonneg.sub +instance : OrderedSub ℝ≥0 := Nonneg.orderedSub noncomputable instance : LinearOrderedSemifield ℝ≥0 := Nonneg.linearOrderedSemifield @@ -105,7 +105,7 @@ protected theorem «exists» {p : ℝ≥0 → Prop} : Subtype.exists /-- Reinterpret a real number `r` as a non-negative real number. Returns `0` if `r < 0`. -/ -noncomputable def _root_.Real.toNNReal (r : ℝ) : ℝ≥0 := +def _root_.Real.toNNReal (r : ℝ) : ℝ≥0 := ⟨max r 0, le_max_right _ _⟩ theorem _root_.Real.coe_toNNReal (r : ℝ) (hr : 0 ≤ r) : (Real.toNNReal r : ℝ) = r := @@ -127,7 +127,7 @@ example : One ℝ≥0 := by infer_instance example : Add ℝ≥0 := by infer_instance -noncomputable example : Sub ℝ≥0 := by infer_instance +example : Sub ℝ≥0 := by infer_instance example : Mul ℝ≥0 := by infer_instance @@ -325,7 +325,7 @@ theorem _root_.Real.toNNReal_ofNat (n : ℕ) [n.AtLeastTwo] : toNNReal_coe_nat n /-- `Real.toNNReal` and `NNReal.toReal : ℝ≥0 → ℝ` form a Galois insertion. -/ -noncomputable def gi : GaloisInsertion Real.toNNReal (↑) := +def gi : GaloisInsertion Real.toNNReal (↑) := GaloisInsertion.monotoneIntro NNReal.coe_mono Real.toNNReal_mono Real.le_coe_toNNReal fun _ => Real.toNNReal_coe From f68a59e8c389d12bafbaf4fada2bfc33c37105f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yuyang=20Zhao=20=E8=B5=B5=E9=9B=A8=E6=89=AC?= Date: Mon, 20 Jan 2025 10:01:34 +0000 Subject: [PATCH 320/681] =?UTF-8?q?feat:=20more=20`PGame.identical`=20`PGa?= =?UTF-8?q?me.mem=E2=82=97`=20`PGame.mem=E1=B5=A3`=20APIs=20(#5901)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR is the first step to remove `PGame.Relabelling` (which is only for implementing things in lean and not real identity) and define games with identity as `Eq`. [Zulip](https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/Well-founded.20recursion.20for.20pgames/near/338664567) Co-authored-by: hwatheod Co-authored-by: Theodore Hwa Co-authored-by: Violeta Hernández --- Mathlib/SetTheory/Game/Basic.lean | 71 +++++++++-- Mathlib/SetTheory/Game/PGame.lean | 192 +++++++++++++++++++++++++++--- 2 files changed, 237 insertions(+), 26 deletions(-) diff --git a/Mathlib/SetTheory/Game/Basic.lean b/Mathlib/SetTheory/Game/Basic.lean index bc7e47200b09a..4e69a754b14ff 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, Kim Morrison, Apurva Nakade +Authors: Reid Barton, Mario Carneiro, Isabel Longbottom, Kim Morrison, Apurva Nakade, Yuyang Zhao -/ import Mathlib.Algebra.Order.Group.Defs import Mathlib.SetTheory.Game.PGame @@ -27,8 +27,6 @@ namespace SetTheory open Function PGame -open PGame - universe u -- Porting note: moved the setoid instance to PGame.lean @@ -340,25 +338,25 @@ theorem mul_moveRight_inr {x y : PGame} {i j} : cases y rfl --- @[simp] -- Porting note: simpNF linter complains +@[simp] theorem neg_mk_mul_moveLeft_inl {xl xr yl yr} {xL xR yL yR} {i j} : (-(mk xl xr xL xR * mk yl yr yL yR)).moveLeft (Sum.inl (i, j)) = -(xL i * mk yl yr yL yR + mk xl xr xL xR * yR j - xL i * yR j) := rfl --- @[simp] -- Porting note: simpNF linter complains +@[simp] theorem neg_mk_mul_moveLeft_inr {xl xr yl yr} {xL xR yL yR} {i j} : (-(mk xl xr xL xR * mk yl yr yL yR)).moveLeft (Sum.inr (i, j)) = -(xR i * mk yl yr yL yR + mk xl xr xL xR * yL j - xR i * yL j) := rfl --- @[simp] -- Porting note: simpNF linter complains +@[simp] theorem neg_mk_mul_moveRight_inl {xl xr yl yr} {xL xR yL yR} {i j} : (-(mk xl xr xL xR * mk yl yr yL yR)).moveRight (Sum.inl (i, j)) = -(xL i * mk yl yr yL yR + mk xl xr xL xR * yL j - xL i * yL j) := rfl --- @[simp] -- Porting note: simpNF linter complains +@[simp] theorem neg_mk_mul_moveRight_inr {xl xr yl yr} {xL xR yL yR} {i j} : (-(mk xl xr xL xR * mk yl yr yL yR)).moveRight (Sum.inr (i, j)) = -(xR i * mk yl yr yL yR + mk xl xr xL xR * yR j - xR i * yR j) := @@ -380,6 +378,17 @@ theorem rightMoves_mul_cases {x y : PGame} (k) {P : (x * y).RightMoves → Prop} · apply hl · apply hr +/-- `x * y` and `y * x` have the same moves. -/ +protected lemma mul_comm (x y : PGame) : x * y ≡ y * x := + match x, y with + | ⟨xl, xr, xL, xR⟩, ⟨yl, yr, yL, yR⟩ => by + refine Identical.of_equiv ((Equiv.prodComm _ _).sumCongr (Equiv.prodComm _ _)) + ((Equiv.sumComm _ _).trans ((Equiv.prodComm _ _).sumCongr (Equiv.prodComm _ _))) ?_ ?_ <;> + · rintro (⟨_, _⟩ | ⟨_, _⟩) <;> + exact ((((PGame.mul_comm _ (mk _ _ _ _)).add (PGame.mul_comm (mk _ _ _ _) _)).trans + (PGame.add_comm _ _)).sub (PGame.mul_comm _ _)) + termination_by (x, y) + /-- `x * y` and `y * x` have the same moves. -/ def mulCommRelabelling (x y : PGame.{u}) : x * y ≡r y * x := match x, y with @@ -415,6 +424,9 @@ instance isEmpty_rightMoves_mul (x y : PGame.{u}) cases y assumption +/-- `x * 0` has exactly the same moves as `0`. -/ +protected lemma mul_zero (x : PGame) : x * 0 ≡ 0 := identical_zero _ + /-- `x * 0` has exactly the same moves as `0`. -/ def mulZeroRelabelling (x : PGame) : x * 0 ≡r 0 := Relabelling.isEmpty _ @@ -427,6 +439,9 @@ theorem mul_zero_equiv (x : PGame) : x * 0 ≈ 0 := theorem quot_mul_zero (x : PGame) : (⟦x * 0⟧ : Game) = 0 := game_eq x.mul_zero_equiv +/-- `0 * x` has exactly the same moves as `0`. -/ +protected lemma zero_mul (x : PGame) : 0 * x ≡ 0 := identical_zero _ + /-- `0 * x` has exactly the same moves as `0`. -/ def zeroMulRelabelling (x : PGame) : 0 * x ≡r 0 := Relabelling.isEmpty _ @@ -458,6 +473,23 @@ def negMulRelabelling (x y : PGame.{u}) : -x * y ≡r -(x * y) := exact (negMulRelabelling _ _).symm termination_by (x, y) +/-- `x * -y` and `-(x * y)` have the same moves. -/ +@[simp] +lemma mul_neg (x y : PGame) : x * -y = -(x * y) := + match x, y with + | mk xl xr xL xR, mk yl yr yL yR => by + refine ext rfl rfl ?_ ?_ <;> rintro (⟨i, j⟩ | ⟨i, j⟩) _ ⟨rfl⟩ + all_goals + dsimp + rw [PGame.neg_sub', PGame.neg_add] + congr + exacts [mul_neg _ (mk ..), mul_neg .., mul_neg ..] +termination_by (x, y) + +/-- `-x * y` and `-(x * y)` have the same moves. -/ +lemma neg_mul (x y : PGame) : -x * y ≡ -(x * y) := + ((PGame.mul_comm _ _).trans (of_eq (mul_neg _ _))).trans (PGame.mul_comm _ _).neg + @[simp] theorem quot_neg_mul (x y : PGame) : (⟦-x * y⟧ : Game) = -⟦x * y⟧ := game_eq (negMulRelabelling x y).equiv @@ -466,7 +498,6 @@ theorem quot_neg_mul (x y : PGame) : (⟦-x * y⟧ : Game) = -⟦x * y⟧ := def mulNegRelabelling (x y : PGame) : x * -y ≡r -(x * y) := (mulCommRelabelling x _).trans <| (negMulRelabelling _ x).trans (mulCommRelabelling y x).negCongr -@[simp] theorem quot_mul_neg (x y : PGame) : ⟦x * -y⟧ = (-⟦x * y⟧ : Game) := game_eq (mulNegRelabelling x y).equiv @@ -608,6 +639,18 @@ def mulOneRelabelling : ∀ x : PGame.{u}, x * 1 ≡r x exact (addZeroRelabelling _).trans <| (((mulOneRelabelling _).addCongr (mulZeroRelabelling _)).trans <| addZeroRelabelling _) } +/-- `1 * x` has the same moves as `x`. -/ +protected lemma one_mul : ∀ (x : PGame), 1 * x ≡ x + | ⟨xl, xr, xL, xR⟩ => by + refine Identical.of_equiv ((Equiv.sumEmpty _ _).trans (Equiv.punitProd _)) + ((Equiv.sumEmpty _ _).trans (Equiv.punitProd _)) ?_ ?_ <;> + · rintro (⟨⟨⟩, _⟩ | ⟨⟨⟩, _⟩) + exact ((((PGame.zero_mul (mk _ _ _ _)).add (PGame.one_mul _)).trans (PGame.zero_add _)).sub + (PGame.zero_mul _)).trans (PGame.sub_zero _) + +/-- `x * 1` has the same moves as `x`. -/ +protected lemma mul_one (x : PGame) : x * 1 ≡ x := (x.mul_comm _).trans x.one_mul + @[simp] theorem quot_mul_one (x : PGame) : (⟦x * 1⟧ : Game) = ⟦x⟧ := game_eq <| PGame.Relabelling.equiv <| mulOneRelabelling x @@ -922,6 +965,13 @@ def inv'Zero : inv' 0 ≡r 1 := by theorem inv'_zero_equiv : inv' 0 ≈ 1 := inv'Zero.equiv +/-- `inv' 1` has exactly the same moves as `1`. -/ +lemma inv'_one : inv' 1 ≡ 1 := by + rw [Identical.ext_iff] + constructor + · simp [memₗ_def, inv', isEmpty_subtype] + · simp [memᵣ_def, inv', isEmpty_subtype] + /-- `inv' 1` has exactly the same moves as `1`. -/ def inv'One : inv' 1 ≡r (1 : PGame.{u}) := by change Relabelling (mk _ _ _ _) 1 @@ -957,6 +1007,11 @@ theorem inv_eq_of_pos {x : PGame} (h : 0 < x) : x⁻¹ = inv' x := by theorem inv_eq_of_lf_zero {x : PGame} (h : x ⧏ 0) : x⁻¹ = -inv' (-x) := by classical exact (if_neg h.not_equiv).trans (if_neg h.not_gt) +/-- `1⁻¹` has exactly the same moves as `1`. -/ +lemma inv_one : 1⁻¹ ≡ 1 := by + rw [inv_eq_of_pos PGame.zero_lt_one] + exact inv'_one + /-- `1⁻¹` has exactly the same moves as `1`. -/ def invOne : 1⁻¹ ≡r 1 := by rw [inv_eq_of_pos PGame.zero_lt_one] diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 2b9242c3d6631..8186fa7fea3eb 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -25,7 +25,8 @@ game after making a move). We may denote a game as $\{L | R\}$, where $L$ and $R$ stand for the collections of left and right moves. This notation is not currently used in Mathlib. -Combinatorial games themselves, as a quotient of pregames, are constructed in `Game.lean`. +Combinatorial games themselves, as a quotient of pregames, are constructed in +`SetTheory.Game.Basic`. ## Conway induction @@ -150,6 +151,16 @@ theorem rightMoves_mk {xl xr xL xR} : (⟨xl, xr, xL, xR⟩ : PGame).RightMoves theorem moveRight_mk {xl xr xL xR} : (⟨xl, xr, xL, xR⟩ : PGame).moveRight = xR := rfl +lemma ext {x y : PGame} (hl : x.LeftMoves = y.LeftMoves) (hr : x.RightMoves = y.RightMoves) + (hL : ∀ i j, HEq i j → x.moveLeft i = y.moveLeft j) + (hR : ∀ i j, HEq i j → x.moveRight i = y.moveRight j) : + x = y := by + cases x + cases y + subst hl hr + simp only [leftMoves_mk, rightMoves_mk, heq_eq_eq, forall_eq', mk.injEq, true_and] at * + exact ⟨funext hL, funext hR⟩ + -- TODO define this at the level of games, as well, and perhaps also for finsets of games. /-- Construct a pre-game from list of pre-games describing the available moves for Left and Right. -/ @@ -1242,7 +1253,7 @@ instance : Neg PGame := ⟨neg⟩ @[simp] -theorem neg_def {xl xr xL xR} : -mk xl xr xL xR = mk xr xl (fun j => -xR j) fun i => -xL i := +theorem neg_def {xl xr xL xR} : -mk xl xr xL xR = mk xr xl (-xR ·) (-xL ·) := rfl instance : InvolutiveNeg PGame := @@ -1352,20 +1363,38 @@ theorem moveRight_neg_symm {x : PGame} (i) : theorem moveRight_neg_symm' {x : PGame} (i) : x.moveRight i = -(-x).moveLeft (toLeftMovesNeg i) := by simp -@[simp] theorem neg_identical_neg_iff : ∀ {x y : PGame.{u}}, -x ≡ -y ↔ x ≡ y - | mk xl xr xL xR, mk yl yr yL yR => by - rw [neg_def, identical_iff, identical_iff, ← neg_def, and_comm] - simp only [neg_def, rightMoves_mk, moveRight_mk, leftMoves_mk, moveLeft_mk] - apply and_congr <;> - · constructor - · conv in (_ ≡ _) => rw [neg_identical_neg_iff] - simp only [imp_self] - · conv in (_ ≡ _) => rw [← neg_identical_neg_iff] - simp only [imp_self] -termination_by x y => (x, y) +theorem leftMoves_neg_cases {x : PGame} (k) {P : (-x).LeftMoves → Prop} + (h : ∀ i, P <| toLeftMovesNeg i) : + P k := by + rw [← toLeftMovesNeg.apply_symm_apply k] + exact h _ -theorem Identical.neg {x y : PGame} : x ≡ y ↔ -x ≡ -y := - neg_identical_neg_iff.symm +theorem rightMoves_neg_cases {x : PGame} (k) {P : (-x).RightMoves → Prop} + (h : ∀ i, P <| toRightMovesNeg i) : + P k := by + rw [← toRightMovesNeg.apply_symm_apply k] + exact h _ + +/-- If `x` has the same moves as `y`, then `-x` has the sames moves as `-y`. -/ +lemma Identical.neg : ∀ {x₁ x₂ : PGame}, x₁ ≡ x₂ → -x₁ ≡ -x₂ + | mk _ _ _ _, mk _ _ _ _, ⟨⟨hL₁, hL₂⟩, ⟨hR₁, hR₂⟩⟩ => + ⟨⟨fun i ↦ (hR₁ i).imp (fun _ ↦ Identical.neg), fun j ↦ (hR₂ j).imp (fun _ ↦ Identical.neg)⟩, + ⟨fun i ↦ (hL₁ i).imp (fun _ ↦ Identical.neg), fun j ↦ (hL₂ j).imp (fun _ ↦ Identical.neg)⟩⟩ + +/-- If `-x` has the same moves as `-y`, then `x` has the sames moves as `y`. -/ +lemma Identical.of_neg : ∀ {x₁ x₂ : PGame}, -x₁ ≡ -x₂ → x₁ ≡ x₂ + | mk x₁l x₁r x₁L x₁R, mk x₂l x₂r x₂L x₂R => by + simpa using Identical.neg (x₁ := mk _ _ (-x₁R ·) (-x₁L ·)) (x₂ := mk _ _ (-x₂R ·) (-x₂L ·)) + +lemma memₗ_neg_iff : ∀ {x y : PGame}, + x ∈ₗ -y ↔ ∃ z ∈ᵣ y, x ≡ -z + | mk _ _ _ _, mk _ _ _ _ => + ⟨fun ⟨_i, hi⟩ ↦ ⟨_, ⟨_, refl _⟩, hi⟩, fun ⟨_, ⟨i, hi⟩, h⟩ ↦ ⟨i, h.trans hi.neg⟩⟩ + +lemma memᵣ_neg_iff : ∀ {x y : PGame}, + x ∈ᵣ -y ↔ ∃ z ∈ₗ y, x ≡ -z + | mk _ _ _ _, mk _ _ _ _ => + ⟨fun ⟨_i, hi⟩ ↦ ⟨_, ⟨_, refl _⟩, hi⟩, fun ⟨_, ⟨i, hi⟩, h⟩ ↦ ⟨i, h.trans hi.neg⟩⟩ /-- If `x` has the same moves as `y`, then `-x` has the same moves as `-y`. -/ def Relabelling.negCongr : ∀ {x y : PGame}, x ≡r y → -x ≡r -y @@ -1395,7 +1424,11 @@ theorem neg_lt_neg_iff {x y : PGame} : -y < -x ↔ x < y := by rw [lt_iff_le_and_lf, lt_iff_le_and_lf, neg_le_neg_iff, neg_lf_neg_iff] @[simp] -theorem neg_equiv_neg_iff {x y : PGame} : (-x ≈ -y) ↔ (x ≈ y) := by +theorem neg_identical_neg {x y : PGame} : -x ≡ -y ↔ x ≡ y := + ⟨Identical.of_neg, Identical.neg⟩ + +@[simp] +theorem neg_equiv_neg_iff {x y : PGame} : -x ≈ -y ↔ x ≈ y := by show Equiv (-x) (-y) ↔ Equiv x y rw [Equiv, Equiv, neg_le_neg_iff, neg_le_neg_iff, and_comm] @@ -1465,6 +1498,16 @@ instance : Add PGame.{u} := · exact fun i => IHxr i y · exact IHyr⟩ +theorem mk_add_moveLeft {xl xr yl yr} {xL xR yL yR} {i} : + (mk xl xr xL xR + mk yl yr yL yR).moveLeft i = + i.rec (xL · + mk yl yr yL yR) (mk xl xr xL xR + yL ·) := + rfl + +theorem mk_add_moveRight {xl xr yl yr} {xL xR yL yR} {i} : + (mk xl xr xL xR + mk yl yr yL yR).moveRight i = + i.rec (xR · + mk yl yr yL yR) (mk xl xr xL xR + yR ·) := + rfl + /-- The pre-game `((0 + 1) + ⋯) + 1`. Note that this is **not** the usual recursive definition `n = {0, 1, … | }`. For instance, @@ -1612,6 +1655,110 @@ instance isEmpty_nat_rightMoves : ∀ n : ℕ, IsEmpty (RightMoves n) rw [PGame.nat_succ, rightMoves_add] infer_instance +/-- `x + y` has exactly the same moves as `y + x`. -/ +protected lemma add_comm (x y : PGame) : x + y ≡ y + x := + match x, y with + | mk xl xr xL xR, mk yl yr yL yR => by + refine Identical.of_equiv (Equiv.sumComm _ _) (Equiv.sumComm _ _) ?_ ?_ <;> + · rintro (_ | _) <;> + · dsimp; exact PGame.add_comm _ _ + termination_by (x, y) + +/-- `(x + y) + z` has exactly the same moves as `x + (y + z)`. -/ +protected lemma add_assoc (x y z : PGame) : x + y + z ≡ x + (y + z) := + match x, y, z with + | mk xl xr xL xR, mk yl yr yL yR, mk zl zr zL zR => by + refine Identical.of_equiv (Equiv.sumAssoc _ _ _) (Equiv.sumAssoc _ _ _) ?_ ?_ <;> + · rintro ((_ | _) | _) + · exact PGame.add_assoc _ _ _ + · exact PGame.add_assoc (mk _ _ _ _) _ _ + · exact PGame.add_assoc (mk _ _ _ _) (mk _ _ _ _) _ + termination_by (x, y, z) + +/-- `x + 0` has exactly the same moves as `x`. -/ +protected lemma add_zero : ∀ (x : PGame), x + 0 ≡ x + | mk xl xr xL xR => by + refine Identical.of_equiv (Equiv.sumEmpty _ _) (Equiv.sumEmpty _ _) ?_ ?_ <;> + · rintro (_ | ⟨⟨⟩⟩) + exact PGame.add_zero _ + +/-- `0 + x` has exactly the same moves as `x`. -/ +protected lemma zero_add (x : PGame) : 0 + x ≡ x := + (PGame.add_comm _ _).trans x.add_zero + +/-- `-(x + y)` has exactly the same moves as `-x + -y`. -/ +protected lemma neg_add (x y : PGame) : -(x + y) = -x + -y := + match x, y with + | mk xl xr xL xR, mk yl yr yL yR => by + refine ext rfl rfl ?_ ?_ <;> + · rintro (i | i) _ ⟨rfl⟩ + · exact PGame.neg_add _ _ + · simpa [Equiv.refl, mk_add_moveLeft, mk_add_moveRight] using PGame.neg_add _ _ + termination_by (x, y) + +/-- `-(x + y)` has exactly the same moves as `-y + -x`. -/ +protected lemma neg_add_rev (x y : PGame) : -(x + y) ≡ -y + -x := + Identical.trans (of_eq (x.neg_add y)) (PGame.add_comm _ _) + +lemma identical_zero_iff : ∀ (x : PGame), + x ≡ 0 ↔ IsEmpty x.LeftMoves ∧ IsEmpty x.RightMoves + | mk xl xr xL xR => by + constructor + · rintro ⟨h₁, h₂⟩ + dsimp [Relator.BiTotal, Relator.LeftTotal, Relator.RightTotal] at h₁ h₂ + simp_rw [IsEmpty.forall_iff, and_true, IsEmpty.exists_iff] at h₁ h₂ + exact ⟨⟨h₁⟩, ⟨h₂⟩⟩ + · rintro ⟨h₁, h₂⟩ + exact identical_of_isEmpty _ _ + +/-- Any game without left or right moves is identical to 0. -/ +lemma identical_zero (x : PGame) [IsEmpty x.LeftMoves] [IsEmpty x.RightMoves] : x ≡ 0 := + x.identical_zero_iff.mpr ⟨by infer_instance, by infer_instance⟩ + +protected lemma add_eq_zero : ∀ {x y : PGame}, x + y ≡ 0 ↔ x ≡ 0 ∧ y ≡ 0 + | mk xl xr xL xR, mk yl yr yL yR => by + simp_rw [identical_zero_iff, leftMoves_add, rightMoves_add, isEmpty_sum] + tauto + +lemma Identical.add_right {x₁ x₂ y} : x₁ ≡ x₂ → x₁ + y ≡ x₂ + y := + match x₁, x₂, y with + | mk x₁l x₁r x₁L x₁R, mk x₂l x₂r x₂L x₂R, mk yl yr yL yR => by + intro h + refine ⟨⟨?_, ?_⟩, ⟨?_, ?_⟩⟩ <;> rintro (_ | _) <;> try exact ⟨.inr _, h.add_right⟩ + · exact (h.1.1 _).elim (⟨.inl ·, ·.add_right⟩) + · exact (h.1.2 _).elim (⟨.inl ·, ·.add_right⟩) + · exact (h.2.1 _).elim (⟨.inl ·, ·.add_right⟩) + · exact (h.2.2 _).elim (⟨.inl ·, ·.add_right⟩) + termination_by (x₁, x₂, y) + +lemma Identical.add_left {x y₁ y₂} (hy : y₁ ≡ y₂) : x + y₁ ≡ x + y₂ := + (x.add_comm y₁).trans (hy.add_right.trans (y₂.add_comm x)) + +/-- 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`. -/ +lemma Identical.add {x₁ x₂ y₁ y₂ : PGame.{u}} (hx : x₁ ≡ x₂) (hy : y₁ ≡ y₂) : x₁ + y₁ ≡ x₂ + y₂ := + hx.add_right.trans hy.add_left + +lemma memₗ_add_iff {x y₁ y₂ : PGame} : + x ∈ₗ y₁ + y₂ ↔ (∃ z ∈ₗ y₁, x ≡ z + y₂) ∨ (∃ z ∈ₗ y₂, x ≡ y₁ + z) := by + cases' y₁ with y₁l y₁r y₁L y₁R + cases' y₂ with y₂l y₂r y₂L y₂R + constructor + · rintro ⟨(i | i), hi⟩ + exacts [.inl ⟨y₁L i, moveLeft_memₗ _ _, hi⟩, .inr ⟨y₂L i, moveLeft_memₗ _ _, hi⟩] + · rintro (⟨_, ⟨i, hi⟩, h⟩ | ⟨_, ⟨i, hi⟩, h⟩) + exacts [⟨.inl i, h.trans hi.add_right⟩, ⟨.inr i, h.trans hi.add_left⟩] + +lemma memᵣ_add_iff {x y₁ y₂ : PGame} : + x ∈ᵣ y₁ + y₂ ↔ (∃ z ∈ᵣ y₁, x ≡ z + y₂) ∨ (∃ z ∈ᵣ y₂, x ≡ y₁ + z) := by + cases' y₁ with y₁l y₁r y₁L y₁R + cases' y₂ with y₂l y₂r y₂L y₂R + constructor + · rintro ⟨(i | i), hi⟩ + exacts [.inl ⟨y₁R i, moveRight_memᵣ _ _, hi⟩, .inr ⟨y₂R i, moveRight_memᵣ _ _, hi⟩] + · rintro (⟨_, ⟨i, hi⟩, h⟩ | ⟨_, ⟨i, hi⟩, h⟩) + exacts [⟨.inl i, h.trans hi.add_right⟩, ⟨.inr i, h.trans hi.add_left⟩] + /-- 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.addCongr : ∀ {w x y z : PGame.{u}}, w ≡r x → y ≡r z → w + y ≡r x + z @@ -1633,7 +1780,16 @@ instance : Sub PGame := 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 +protected lemma sub_zero (x : PGame) : x - 0 ≡ x := + _root_.trans (of_eq x.sub_zero_eq_add_zero) x.add_zero + +/-- This lemma is named to match `neg_sub'`. -/ +protected lemma neg_sub' (x y : PGame) : -(x - y) = -x - -y := PGame.neg_add _ _ + +/-- 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`. -/ +lemma Identical.sub {x₁ x₂ y₁ y₂ : PGame.{u}} (hx : x₁ ≡ x₂) (hy : y₁ ≡ y₂) : x₁ - y₁ ≡ x₂ - y₂ := + hx.add hy.neg /-- 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`. -/ @@ -2029,4 +2185,4 @@ end PGame end SetTheory -set_option linter.style.longFile 2100 +set_option linter.style.longFile 2300 From e43c7732f3e074817dad5659dbc751a3a3bc9b1c Mon Sep 17 00:00:00 2001 From: smorel394 Date: Mon, 20 Jan 2025 10:42:39 +0000 Subject: [PATCH 321/681] feat(Algebra/Category/Grp/LargeColimits): large colimits in the category of commutative additive groups (#20522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If `F : J ⥤ AddCommGrp.{w}` is a functor, we show that `F` admits a colimit if and only if `Colimits.Quot F` (the quotient of the direct sum of the commutative groups `F.obj j` by the relations given by the morphisms in the diagram) is `w`-small. - [x] depends on: #20416 - [x] depends on: #20512 Co-authored-by: smorel394 <67864981+smorel394@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Algebra/Category/Grp/Basic.lean | 14 ++++ Mathlib/Algebra/Category/Grp/Colimits.lean | 2 +- .../Algebra/Category/Grp/LargeColimits.lean | 73 +++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 Mathlib/Algebra/Category/Grp/LargeColimits.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7ec4b7562084a..8518b9ada16e4 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -88,6 +88,7 @@ import Mathlib.Algebra.Category.Grp.ForgetCorepresentable import Mathlib.Algebra.Category.Grp.Images import Mathlib.Algebra.Category.Grp.Injective import Mathlib.Algebra.Category.Grp.Kernels +import Mathlib.Algebra.Category.Grp.LargeColimits import Mathlib.Algebra.Category.Grp.Limits import Mathlib.Algebra.Category.Grp.Preadditive import Mathlib.Algebra.Category.Grp.Subobject diff --git a/Mathlib/Algebra/Category/Grp/Basic.lean b/Mathlib/Algebra/Category/Grp/Basic.lean index e84967eb2a42b..356b887d22a5c 100644 --- a/Mathlib/Algebra/Category/Grp/Basic.lean +++ b/Mathlib/Algebra/Category/Grp/Basic.lean @@ -132,6 +132,13 @@ theorem ofHom_apply {X Y : Type _} [Group X] [Group Y] (f : X →* Y) (x : X) : (ofHom f) x = f x := rfl +@[to_additive] +lemma ofHom_injective {X Y : Type u} [Group X] [Group Y] : + Function.Injective (fun (f : X →* Y) ↦ ofHom f) := by + intro _ _ h + ext + apply DFunLike.congr_fun h + @[to_additive] instance ofUnique (G : Type*) [Group G] [i : Unique G] : Unique (Grp.of G) := i @@ -276,6 +283,13 @@ theorem ofHom_apply {X Y : Type _} [CommGroup X] [CommGroup Y] (f : X →* Y) (x @DFunLike.coe (X →* Y) X (fun _ ↦ Y) _ (ofHom f) x = f x := rfl +@[to_additive] +lemma ofHom_injective {X Y : Type u} [CommGroup X] [CommGroup Y] : + Function.Injective (fun (f : X →* Y) ↦ ofHom f) := by + intro _ _ h + ext + apply DFunLike.congr_fun h + -- We verify that simp lemmas apply when coercing morphisms to functions. @[to_additive] example {R S : CommGrp} (i : R ⟶ S) (r : R) (h : r = 1) : i r = 1 := by simp [h] diff --git a/Mathlib/Algebra/Category/Grp/Colimits.lean b/Mathlib/Algebra/Category/Grp/Colimits.lean index a7d7824126397..80b1c46458597 100644 --- a/Mathlib/Algebra/Category/Grp/Colimits.lean +++ b/Mathlib/Algebra/Category/Grp/Colimits.lean @@ -12,7 +12,7 @@ import Mathlib.GroupTheory.QuotientGroup.Defs /-! # The category of additive commutative groups has all colimits. -This file constructs colimits in the categpry of additive commutative groups, as +This file constructs colimits in the category of additive commutative groups, as quotients of finitely supported functions. -/ diff --git a/Mathlib/Algebra/Category/Grp/LargeColimits.lean b/Mathlib/Algebra/Category/Grp/LargeColimits.lean new file mode 100644 index 0000000000000..9f9628925dad5 --- /dev/null +++ b/Mathlib/Algebra/Category/Grp/LargeColimits.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2025 Sophie Morel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sophie Morel +-/ +import Mathlib.Algebra.Category.Grp.Colimits +import Mathlib.Algebra.Module.CharacterModule +import Mathlib.Algebra.Group.Equiv.Basic + +/-! +# Existence of "big" colimits in the category of additive commutative groups + +If `F : J ⥤ AddCommGrp.{w}` is a functor, we show that `F` admits a colimit if and only +if `Colimits.Quot F` (the quotient of the direct sum of the commutative groups `F.obj j` +by the relations given by the morphisms in the diagram) is `w`-small. + +-/ + +universe w u v + +open CategoryTheory Limits + +namespace AddCommGrp + +variable {J : Type u} [Category.{v} J] {F : J ⥤ AddCommGrp.{w}} (c : Cocone F) + +open Colimits + +/-- +If `c` is a cocone of `F` such that `Quot.desc F c` is bijective, then `c` is a colimit +cocone of `F`. +-/ +lemma isColimit_iff_bijective_desc [DecidableEq J] : + Nonempty (IsColimit c) ↔ Function.Bijective (Quot.desc F c) := by + refine ⟨fun ⟨hc⟩ => ?_, fun h ↦ Nonempty.intro (isColimit_of_bijective_desc F c h)⟩ + change Function.Bijective (Quot.desc F c).toIntLinearMap + rw [← CharacterModule.dual_bijective_iff_bijective] + refine ⟨fun χ ψ eq ↦ ?_, fun χ ↦ ?_⟩ + · apply (AddMonoidHom.postcompEquiv (@AddEquiv.ulift (AddCircle (1 : ℚ)) _).symm _).injective + apply ofHom_injective + refine hc.hom_ext (fun j ↦ ?_) + ext x + rw [comp_apply, comp_apply, ← Quot.ι_desc _ c j x] + exact ULift.down_injective (DFunLike.congr_fun eq (Quot.ι F j x)) + · set c' : Cocone F := + { pt := AddCommGrp.of (ULift (AddCircle (1 : ℚ))) + ι := + { app j := AddCommGrp.ofHom (((@AddEquiv.ulift _ _).symm.toAddMonoidHom.comp χ).comp + (Quot.ι F j)) + naturality {j j'} u := by + ext + change ofHom ((AddEquiv.ulift.symm.toAddMonoidHom.comp χ).comp _) (F.map u _) = _ + dsimp + rw [Quot.map_ι F (f := u)] + rfl } } + use AddEquiv.ulift.toAddMonoidHom.comp (hc.desc c') + refine Quot.addMonoidHom_ext _ (fun j x ↦ ?_) + dsimp + rw [Quot.ι_desc] + change AddEquiv.ulift ((c.ι.app j ≫ hc.desc c') x) = _ + rw [hc.fac] + dsimp [c'] + rw [AddEquiv.apply_symm_apply] + +/-- +A functor `F : J ⥤ AddCommGrp.{w}` has a colimit if and only if `Colimits.Quot F` is +`w`-small. +-/ +lemma hasColimit_iff_small_quot [DecidableEq J] : HasColimit F ↔ Small.{w} (Quot F) := + ⟨fun _ ↦ Small.mk ⟨_, ⟨(Equiv.ofBijective _ ((isColimit_iff_bijective_desc (colimit.cocone F)).mp + ⟨colimit.isColimit _⟩))⟩⟩, hasColimit_of_small_quot F⟩ + +end AddCommGrp From 1b34e3c465be11c640713935e6014bd820dcc1a0 Mon Sep 17 00:00:00 2001 From: xyzw12345 Date: Mon, 20 Jan 2025 10:56:11 +0000 Subject: [PATCH 322/681] feat(RingTheory/Ideal): the height of an ideal (#20741) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this PR, we ported a part of Andrew Yang's lean3 repository at [this repository](https://github.com/erdOne/lean-AG-morphisms), which is appoved by @erdOne after his discussion with @chrisflav . Andrew defined `Ideal.primeHeight` and `Ideal.height` in this repository (it's at /dimension_theory/height), we ported this, changed the definition of `Ideal.primeHeight` to `Order.height (⟨I, hI⟩ : PrimeSpectrum R)` and ported some basic lemmas about it. Co-authored-by: @erdOne @Xuchun-Li @jjdishere @Blackfeather007 <2100017455@stu.pku.edu.cn> Co-authored-by: Blackfeather007 <95499908+Blackfeather007@users.noreply.github.com> Co-authored-by: jjdishere Co-authored-by: Xuchun-Li Co-authored-by: Blackfeather007 <2100017455@stu.pku.edu.cn> --- Mathlib.lean | 1 + Mathlib/Order/KrullDimension.lean | 26 ++++ Mathlib/RingTheory/Ideal/Height.lean | 124 +++++++++++++++++++ Mathlib/RingTheory/Ideal/MinimalPrime.lean | 39 ++++++ Mathlib/RingTheory/KrullDimension/Basic.lean | 2 +- 5 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 Mathlib/RingTheory/Ideal/Height.lean diff --git a/Mathlib.lean b/Mathlib.lean index 8518b9ada16e4..7f7a4f749f425 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4497,6 +4497,7 @@ import Mathlib.RingTheory.Ideal.BigOperators import Mathlib.RingTheory.Ideal.Colon import Mathlib.RingTheory.Ideal.Cotangent import Mathlib.RingTheory.Ideal.Defs +import Mathlib.RingTheory.Ideal.Height import Mathlib.RingTheory.Ideal.IdempotentFG import Mathlib.RingTheory.Ideal.IsPrimary import Mathlib.RingTheory.Ideal.IsPrincipal diff --git a/Mathlib/Order/KrullDimension.lean b/Mathlib/Order/KrullDimension.lean index aecd91615f063..8b7daccbce618 100644 --- a/Mathlib/Order/KrullDimension.lean +++ b/Mathlib/Order/KrullDimension.lean @@ -275,11 +275,37 @@ private lemma height_add_const (a : α) (n : ℕ∞) : have := length_le_height_last (p := p.snoc y (by simp [*])) simpa using this +lemma height_add_one_le {a b : α} (hab : a < b) : height a + 1 ≤ height b := by + cases hfin : height a with + | top => + have : ⊤ ≤ height b := by + rw [← hfin] + gcongr + simp [this] + | coe n => + apply Order.add_one_le_of_lt + rw [← hfin] + gcongr + simp [hfin] + /- For elements of finite height, `coheight` is strictly antitone. -/ @[gcongr] lemma coheight_strictAnti {x y : α} (hyx : y < x) (hfin : coheight x < ⊤) : coheight x < coheight y := height_strictMono (α := αᵒᵈ) hyx hfin +lemma coheight_add_one_le {a b : α} (hab : b < a) : coheight a + 1 ≤ coheight b := by + cases hfin : coheight a with + | top => + have : ⊤ ≤ coheight b := by + rw [← hfin] + gcongr + simp [this] + | coe n => + apply Order.add_one_le_of_lt + rw [← hfin] + gcongr + simp [hfin] + lemma height_le_height_apply_of_strictMono (f : α → β) (hf : StrictMono f) (x : α) : height x ≤ height (f x) := by simp only [height_eq_iSup_last_eq] diff --git a/Mathlib/RingTheory/Ideal/Height.lean b/Mathlib/RingTheory/Ideal/Height.lean new file mode 100644 index 0000000000000..965faae6a18cf --- /dev/null +++ b/Mathlib/RingTheory/Ideal/Height.lean @@ -0,0 +1,124 @@ +/- +Copyright (c) 2025 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jiedong Jiang, Jingting Wang, Andrew Yang +-/ +import Mathlib.Order.KrullDimension +import Mathlib.RingTheory.Ideal.MinimalPrime +import Mathlib.RingTheory.Spectrum.Prime.Basic +/-! +# The Height of an Ideal + +In this file, we define the height of a prime ideal and the height of an ideal. + +# Main definitions + +* `Ideal.primeHeight` : The height of a prime ideal $\mathfrak{p}$. We define it as the supremum of + the lengths of strictly decreasing chains of prime ideals below it. This definition is implemented + via `Order.height`. + +* `Ideal.height` : The height of an ideal. We defined it as the infimum of the `primeHeight` of the +minimal prime ideals of I. + +-/ + + +variable {R : Type*} [CommRing R] (I : Ideal R) + +open Ideal + +/-- The height of a prime ideal is defined as the supremum of the lengths of strictly decreasing +chains of prime ideals below it. -/ +noncomputable def Ideal.primeHeight [hI : I.IsPrime] : ℕ∞ := + Order.height (⟨I, hI⟩ : PrimeSpectrum R) + +/-- The height of an ideal is defined as the infimum of the heights of its minimal prime ideals. -/ +noncomputable def Ideal.height : ℕ∞ := + ⨅ J ∈ I.minimalPrimes, @Ideal.primeHeight _ _ J (minimalPrimes_isPrime ‹_›) + +/-- For a prime ideal, its height equals its prime height. -/ +lemma Ideal.height_eq_primeHeight [I.IsPrime] : I.height = I.primeHeight := by + unfold height primeHeight + simp_rw [Ideal.minimalPrimes_eq_subsingleton_self] + simp + +/-- An ideal has finite height if it is either the unit ideal or its height is finite. +We include the unit ideal in order to have the instance `IsNoetherianRing R → FiniteHeight I`. -/ +class Ideal.FiniteHeight : Prop where + eq_top_or_height_ne_top : I = ⊤ ∨ I.height ≠ ⊤ + +lemma Ideal.finiteHeight_iff_lt {I : Ideal R} : + Ideal.FiniteHeight I ↔ I = ⊤ ∨ I.height < ⊤ := by + constructor + · intro h + cases h.eq_top_or_height_ne_top with + | inl h => exact Or.inl h + | inr h => exact Or.inr (lt_of_le_of_ne le_top h) + · intro h + constructor + cases h with + | inl h => exact Or.inl h + | inr h => exact Or.inr (ne_top_of_lt h) + +lemma Ideal.height_ne_top {I : Ideal R} (hI : I ≠ ⊤) [h : I.FiniteHeight] : + I.height ≠ ⊤ := + (h.eq_top_or_height_ne_top).resolve_left hI + +lemma Ideal.height_lt_top {I : Ideal R} (hI : I ≠ ⊤) [h : I.FiniteHeight] : + I.height < ⊤ := + lt_of_le_of_ne le_top (Ideal.height_ne_top hI) + +lemma Ideal.primeHeight_ne_top (I : Ideal R) [I.FiniteHeight] [h : I.IsPrime] : + I.primeHeight ≠ ⊤ := by + rw [← I.height_eq_primeHeight] + exact Ideal.height_ne_top (by exact h.ne_top) + +lemma Ideal.primeHeight_lt_top (I : Ideal R) [I.FiniteHeight] [h : I.IsPrime] : + I.primeHeight < ⊤ := by + rw [← I.height_eq_primeHeight] + exact Ideal.height_lt_top (by exact h.ne_top) + +@[gcongr] +lemma Ideal.primeHeight_mono {I J : Ideal R} [I.IsPrime] [J.IsPrime] (h : I ≤ J) : + I.primeHeight ≤ J.primeHeight := by + unfold primeHeight + gcongr + exact h + +lemma Ideal.primeHeight_add_one_le_of_lt {I J : Ideal R} [I.IsPrime] [J.IsPrime] (h : I < J) : + I.primeHeight + 1 ≤ J.primeHeight := by + unfold primeHeight + exact Order.height_add_one_le h + +@[gcongr] +lemma Ideal.primeHeight_strict_mono {I J : Ideal R} [I.IsPrime] [J.IsPrime] + (h : I < J) [I.FiniteHeight] : + I.primeHeight < J.primeHeight := by + unfold primeHeight + gcongr + · exact I.primeHeight_ne_top.lt_top + · exact h + +@[simp] +theorem Ideal.height_top : (⊤ : Ideal R).height = ⊤ := by + simp only [height, minimalPrimes_top] + rw [iInf₂_eq_top]; intro i hi; exact False.elim hi + +@[gcongr] +theorem Ideal.height_mono {I J : Ideal R} (h : I ≤ J) : I.height ≤ J.height := by + simp only [height] + apply le_iInf₂; intro p hp; haveI := hp.1.1 + obtain ⟨q, hq, e⟩ := Ideal.exists_minimalPrimes_le (h.trans hp.1.2) + haveI := hq.1.1 + exact (iInf₂_le q hq).trans (Ideal.primeHeight_mono e) + +@[gcongr] +lemma Ideal.height_strict_mono_of_is_prime {I J : Ideal R} [I.IsPrime] + (h : I < J) [I.FiniteHeight] : I.height < J.height := by + rw [Ideal.height_eq_primeHeight I] + by_cases hJ : J = ⊤ + · rw [hJ, height_top]; exact I.primeHeight_lt_top + · rw [← ENat.add_one_le_iff I.primeHeight_ne_top, Ideal.height] + apply le_iInf₂; intro K hK; haveI := hK.1.1 + have : I < K := lt_of_lt_of_le h hK.1.2 + exact Ideal.primeHeight_add_one_le_of_lt this diff --git a/Mathlib/RingTheory/Ideal/MinimalPrime.lean b/Mathlib/RingTheory/Ideal/MinimalPrime.lean index 3db1a63fcb0df..13079f23b3398 100644 --- a/Mathlib/RingTheory/Ideal/MinimalPrime.lean +++ b/Mathlib/RingTheory/Ideal/MinimalPrime.lean @@ -49,6 +49,9 @@ lemma minimalPrimes_eq_minimals : minimalPrimes R = {x | Minimal Ideal.IsPrime x variable {I J} +theorem Ideal.minimalPrimes_isPrime {p : Ideal R} (h : p ∈ I.minimalPrimes) : p.IsPrime := + h.1.1 + theorem Ideal.exists_minimalPrimes_le [J.IsPrime] (e : I ≤ J) : ∃ p ∈ I.minimalPrimes, p ≤ J := by set S := { p : (Ideal R)ᵒᵈ | Ideal.IsPrime p ∧ I ≤ OrderDual.ofDual p } suffices h : ∃ m, OrderDual.toDual J ≤ m ∧ Maximal (· ∈ S) m by @@ -67,6 +70,16 @@ theorem Ideal.exists_minimalPrimes_le [J.IsPrime] (e : I ≤ J) : ∃ p ∈ I.mi rw [OrderDual.le_toDual] exact sInf_le hz +theorem Ideal.nonempty_minimalPrimes (h : I ≠ ⊤) : Nonempty I.minimalPrimes := by + obtain ⟨m, hm, hle⟩ := Ideal.exists_le_maximal I h + obtain ⟨p, hp, -⟩ := Ideal.exists_minimalPrimes_le hle + exact ⟨p, hp⟩ + +theorem Ideal.eq_bot_of_minimalPrimes_eq_empty (h : I.minimalPrimes = ∅) : I = ⊤ := by + by_contra hI + obtain ⟨p, hp⟩ := Ideal.nonempty_minimalPrimes hI + exact Set.not_mem_empty p (h ▸ hp) + @[simp] theorem Ideal.radical_minimalPrimes : I.radical.minimalPrimes = I.minimalPrimes := by rw [Ideal.minimalPrimes, Ideal.minimalPrimes] @@ -235,3 +248,29 @@ theorem nilpotent_iff_not_unit_of_minimal {x : Localization I.primeCompl} : simpa only [← IsLocalRing.mem_maximalIdeal] using nilpotent_iff_mem_maximal_of_minimal hMin end Localization.AtPrime + +section + +variable {R : Type*} [CommSemiring R] + +theorem Ideal.minimalPrimes_top : (⊤ : Ideal R).minimalPrimes = ∅ := by + ext p + constructor + · intro h + exact False.elim (h.1.1.ne_top (top_le_iff.mp h.1.2)) + · intro h + exact False.elim (Set.not_mem_empty p h) + +theorem Ideal.minimalPrimes_eq_empty_iff (I : Ideal R) : + I.minimalPrimes = ∅ ↔ I = ⊤ := by + constructor + · intro e + by_contra h + have ⟨M, hM, hM'⟩ := Ideal.exists_le_maximal I h + have ⟨p, hp⟩ := Ideal.exists_minimalPrimes_le hM' + show p ∈ (∅ : Set (Ideal R)) + rw [← e]; exact hp.1 + · intro h; rw [h] + exact Ideal.minimalPrimes_top + +end diff --git a/Mathlib/RingTheory/KrullDimension/Basic.lean b/Mathlib/RingTheory/KrullDimension/Basic.lean index b368cc66ae325..2318aef3d4f73 100644 --- a/Mathlib/RingTheory/KrullDimension/Basic.lean +++ b/Mathlib/RingTheory/KrullDimension/Basic.lean @@ -21,7 +21,7 @@ open Order /-- The ring theoretic Krull dimension is the Krull dimension of its spectrum ordered by inclusion. -/ -noncomputable def ringKrullDim (R : Type*) [CommRing R] : WithBot (WithTop ℕ) := +noncomputable def ringKrullDim (R : Type*) [CommRing R] : WithBot ℕ∞ := krullDim (PrimeSpectrum R) variable {R S : Type*} [CommRing R] [CommRing S] From f09056efcfff05bf2713ad589c8da7030441fd7a Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Mon, 20 Jan 2025 11:09:02 +0000 Subject: [PATCH 323/681] feat(RingTheory): prime is restriction of a prime iff it is the restriction of its extension (#20700) Co-authored by: Sihan Su Co-authored by: Yi Song Co-authored-by: Christian Merten <136261474+chrisflav@users.noreply.github.com> --- Mathlib/RingTheory/Ideal/Over.lean | 12 ++++++++++++ Mathlib/RingTheory/Localization/AtPrime.lean | 6 ++++++ Mathlib/RingTheory/Localization/Ideal.lean | 11 +++++++++++ 3 files changed, 29 insertions(+) diff --git a/Mathlib/RingTheory/Ideal/Over.lean b/Mathlib/RingTheory/Ideal/Over.lean index c3fd963f5f2d3..48ef1022ba6d0 100644 --- a/Mathlib/RingTheory/Ideal/Over.lean +++ b/Mathlib/RingTheory/Ideal/Over.lean @@ -37,6 +37,18 @@ section CommRing variable {S : Type*} [CommRing S] {f : R →+* S} {I J : Ideal S} +/-- For a prime ideal `p` of `R`, `p` extended to `S` and +restricted back to `R` is `p` if and only if `p` is the restriction of a prime in `S`. -/ +lemma comap_map_eq_self_iff_of_isPrime (p : Ideal R) [p.IsPrime] : + (p.map f).comap f = p ↔ (∃ (q : Ideal S), q.IsPrime ∧ q.comap f = p) := by + refine ⟨fun hp ↦ ?_, ?_⟩ + · obtain ⟨q, hq₁, hq₂, hq₃⟩ := Ideal.exists_le_prime_disjoint _ _ + (disjoint_map_primeCompl_iff_comap_le.mpr hp.le) + exact ⟨q, hq₁, le_antisymm (disjoint_map_primeCompl_iff_comap_le.mp hq₃) + (map_le_iff_le_comap.mp hq₂)⟩ + · rintro ⟨q, hq, rfl⟩ + simp + theorem coeff_zero_mem_comap_of_root_mem_of_eval_mem {r : S} (hr : r ∈ I) {p : R[X]} (hp : p.eval₂ f r ∈ I) : p.coeff 0 ∈ I.comap f := by rw [← p.divX_mul_X_add, eval₂_add, eval₂_C, eval₂_mul, eval₂_X] at hp diff --git a/Mathlib/RingTheory/Localization/AtPrime.lean b/Mathlib/RingTheory/Localization/AtPrime.lean index e8d94b851a13e..aa913923a7e8f 100644 --- a/Mathlib/RingTheory/Localization/AtPrime.lean +++ b/Mathlib/RingTheory/Localization/AtPrime.lean @@ -49,6 +49,12 @@ def primeCompl : Submonoid R where theorem primeCompl_le_nonZeroDivisors [NoZeroDivisors R] : P.primeCompl ≤ nonZeroDivisors R := le_nonZeroDivisors_of_noZeroDivisors <| not_not_intro P.zero_mem +lemma disjoint_map_primeCompl_iff_comap_le {S : Type*} [Semiring S] {f : R →+* S} + {p : Ideal R} {I : Ideal S} [p.IsPrime] : + Disjoint (I : Set S) (p.primeCompl.map f) ↔ I.comap f ≤ p := by + rw [disjoint_comm] + simp [Set.disjoint_iff, Set.ext_iff, Ideal.primeCompl, not_imp_not, SetLike.le_def] + end Ideal /-- Given a prime ideal `P`, the typeclass `IsLocalization.AtPrime S P` states that `S` is diff --git a/Mathlib/RingTheory/Localization/Ideal.lean b/Mathlib/RingTheory/Localization/Ideal.lean index fc1af5344f892..5238e642ff74e 100644 --- a/Mathlib/RingTheory/Localization/Ideal.lean +++ b/Mathlib/RingTheory/Localization/Ideal.lean @@ -80,6 +80,17 @@ lemma mk'_mem_map_algebraMap_iff (I : Ideal R) (x : R) (s : M) : exact ⟨fun ⟨⟨y, t⟩, c, h⟩ ↦ ⟨_, (c * t).2, h ▸ I.mul_mem_left c.1 y.2⟩, fun ⟨s, hs, h⟩ ↦ ⟨⟨⟨_, h⟩, ⟨s, hs⟩⟩, 1, by simp⟩⟩ +lemma algebraMap_mem_map_algebraMap_iff (I : Ideal R) (x : R) : + algebraMap R S x ∈ I.map (algebraMap R S) ↔ + ∃ m ∈ M, m * x ∈ I := by + rw [← IsLocalization.mk'_one (M := M), mk'_mem_map_algebraMap_iff] + +lemma map_algebraMap_ne_top_iff_disjoint (I : Ideal R) : + I.map (algebraMap R S) ≠ ⊤ ↔ Disjoint (M : Set R) (I : Set R) := by + simp only [ne_eq, Ideal.eq_top_iff_one, ← map_one (algebraMap R S), not_iff_comm, + IsLocalization.algebraMap_mem_map_algebraMap_iff M] + simp [Set.disjoint_left] + include M in theorem map_comap (J : Ideal S) : Ideal.map (algebraMap R S) (Ideal.comap (algebraMap R S) J) = J := From 43e08d280881807e728b07b8cbe1b4a0b10fe980 Mon Sep 17 00:00:00 2001 From: Arend Mellendijk Date: Mon, 20 Jan 2025 11:09:04 +0000 Subject: [PATCH 324/681] feat(BigOperators): ite_prod_one / ite_sum_zero (#20779) These lemmas were useful for manipulating nested sums while working on the Selberg sieve. They can be used to push a condition from the outer sum into an inner sum. --- Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean b/Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean index 64683dca211e5..8264c7339228d 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset/Defs.lean @@ -481,6 +481,16 @@ theorem prod_dite_irrel (p : Prop) [Decidable p] (s : Finset α) (f : p → α if h : p then ∏ x ∈ s, f h x else ∏ x ∈ s, g h x := by split_ifs with h <;> rfl +@[to_additive] +theorem ite_prod_one (p : Prop) [Decidable p] (s : Finset α) (f : α → β) : + (if p then (∏ x ∈ s, f x) else 1) = ∏ x ∈ s, if p then f x else 1 := by + simp only [prod_ite_irrel, prod_const_one] + +@[to_additive] +theorem ite_one_prod (p : Prop) [Decidable p] (s : Finset α) (f : α → β) : + (if p then 1 else (∏ x ∈ s, f x)) = ∏ x ∈ s, if p then 1 else f x := by + simp only [prod_ite_irrel, prod_const_one] + @[to_additive] theorem nonempty_of_prod_ne_one (h : ∏ x ∈ s, f x ≠ 1) : s.Nonempty := s.eq_empty_or_nonempty.elim (fun H => False.elim <| h <| H.symm ▸ prod_empty) id From 3bf4857ada81ea603d1208f124c23c0c8543ece8 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 20 Jan 2025 11:09:05 +0000 Subject: [PATCH 325/681] chore(Order): split `GaloisConnection` into `Defs.lean` and `Basic.lean` (#20798) The main reason for this PR is noticing that `NNRat` brings in a lot of order theory: [Mathlib.Data.NNRat.Defs.pdf](https://github.com/user-attachments/files/18442420/Mathlib.Data.NNRat.Defs.pdf). We don't actually need to know what a boolean algebra is, or even a complete lattice, to define `NNRat`. --- Mathlib.lean | 3 +- Mathlib/Algebra/Order/Floor.lean | 1 - Mathlib/Algebra/Order/Floor/Div.lean | 1 - .../Category/GaloisConnection.lean | 2 +- .../CategoryTheory/Groupoid/Subgroupoid.lean | 1 - Mathlib/Data/NNRat/Defs.lean | 6 +- Mathlib/Data/Rel.lean | 3 +- Mathlib/Data/Set/Lattice.lean | 2 +- Mathlib/Data/Setoid/Basic.lean | 3 +- Mathlib/Order/Closure.lean | 1 - Mathlib/Order/Cofinal.lean | 4 +- .../Basic.lean} | 350 +--------------- Mathlib/Order/GaloisConnection/Defs.lean | 395 ++++++++++++++++++ Mathlib/Order/Heyting/Regular.lean | 2 +- Mathlib/Order/Hom/Order.lean | 2 +- Mathlib/Order/ModularLattice.lean | 2 +- Mathlib/Order/Rel/GaloisConnection.lean | 1 - 17 files changed, 416 insertions(+), 363 deletions(-) rename Mathlib/Order/{GaloisConnection.lean => GaloisConnection/Basic.lean} (57%) create mode 100644 Mathlib/Order/GaloisConnection/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7f7a4f749f425..13ab333ccad4c 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4181,7 +4181,8 @@ import Mathlib.Order.Filter.ZeroAndBoundedAtFilter import Mathlib.Order.Fin.Basic import Mathlib.Order.Fin.Tuple import Mathlib.Order.FixedPoints -import Mathlib.Order.GaloisConnection +import Mathlib.Order.GaloisConnection.Basic +import Mathlib.Order.GaloisConnection.Defs import Mathlib.Order.GameAdd import Mathlib.Order.Grade import Mathlib.Order.Height diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index c38c843eb9ed1..f42a9e7c4cfb8 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -9,7 +9,6 @@ import Mathlib.Algebra.Group.Int.Units import Mathlib.Data.Int.Lemmas 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 diff --git a/Mathlib/Algebra/Order/Floor/Div.lean b/Mathlib/Algebra/Order/Floor/Div.lean index 92562cfb116a0..5b20fe4336d57 100644 --- a/Mathlib/Algebra/Order/Floor/Div.lean +++ b/Mathlib/Algebra/Order/Floor/Div.lean @@ -7,7 +7,6 @@ import Mathlib.Algebra.GroupWithZero.Action.Pi import Mathlib.Algebra.Order.Module.Defs import Mathlib.Algebra.Order.Pi import Mathlib.Data.Finsupp.Order -import Mathlib.Order.GaloisConnection /-! # Flooring, ceiling division diff --git a/Mathlib/CategoryTheory/Category/GaloisConnection.lean b/Mathlib/CategoryTheory/Category/GaloisConnection.lean index a79e29a39e4c2..df642c01f6f1e 100644 --- a/Mathlib/CategoryTheory/Category/GaloisConnection.lean +++ b/Mathlib/CategoryTheory/Category/GaloisConnection.lean @@ -5,7 +5,7 @@ Authors: Stephen Morgan, Kim Morrison, Johannes Hölzl, Reid Barton -/ import Mathlib.CategoryTheory.Category.Preorder import Mathlib.CategoryTheory.Adjunction.Basic -import Mathlib.Order.GaloisConnection +import Mathlib.Order.GaloisConnection.Defs /-! diff --git a/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean b/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean index 7f4c9c681866e..9534f673817a0 100644 --- a/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean +++ b/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean @@ -8,7 +8,6 @@ import Mathlib.CategoryTheory.Groupoid.VertexGroup import Mathlib.CategoryTheory.Groupoid.Basic import Mathlib.CategoryTheory.Groupoid import Mathlib.Data.Set.Lattice -import Mathlib.Order.GaloisConnection /-! # Subgroupoid diff --git a/Mathlib/Data/NNRat/Defs.lean b/Mathlib/Data/NNRat/Defs.lean index 1847740ee58e0..19f0f15d8fa34 100644 --- a/Mathlib/Data/NNRat/Defs.lean +++ b/Mathlib/Data/NNRat/Defs.lean @@ -7,7 +7,9 @@ import Mathlib.Algebra.Order.Group.Unbundled.Int import Mathlib.Algebra.Order.Nonneg.Basic import Mathlib.Algebra.Order.Ring.Unbundled.Rat import Mathlib.Algebra.Ring.Rat -import Mathlib.Order.GaloisConnection +import Mathlib.Data.Set.Operations +import Mathlib.Order.Bounds.Defs +import Mathlib.Order.GaloisConnection.Defs /-! # Nonnegative rationals @@ -33,7 +35,7 @@ Whenever you state a lemma about the coercion `ℚ≥0 → ℚ`, check that Lean `Subtype.val`. Else your lemma will never apply. -/ -assert_not_exists OrderedCommMonoid +assert_not_exists CompleteLattice OrderedCommMonoid library_note "specialised high priority simp lemma" /-- It sometimes happens that a `@[simp]` lemma declared early in the library can be proved by `simp` diff --git a/Mathlib/Data/Rel.lean b/Mathlib/Data/Rel.lean index 9717d93d288df..ced1fb359df56 100644 --- a/Mathlib/Data/Rel.lean +++ b/Mathlib/Data/Rel.lean @@ -3,9 +3,8 @@ Copyright (c) 2018 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Order.CompleteLattice -import Mathlib.Order.GaloisConnection import Mathlib.Data.Set.Lattice +import Mathlib.Order.CompleteLattice import Mathlib.Tactic.AdaptationNote /-! diff --git a/Mathlib/Data/Set/Lattice.lean b/Mathlib/Data/Set/Lattice.lean index 0a1edf84d64c4..69708f8597b2d 100644 --- a/Mathlib/Data/Set/Lattice.lean +++ b/Mathlib/Data/Set/Lattice.lean @@ -6,7 +6,7 @@ Authors: Jeremy Avigad, Leonardo de Moura, Johannes Hölzl, Mario Carneiro import Mathlib.Logic.Pairwise import Mathlib.Order.CompleteBooleanAlgebra import Mathlib.Order.Directed -import Mathlib.Order.GaloisConnection +import Mathlib.Order.GaloisConnection.Basic import Mathlib.Tactic.Cases /-! diff --git a/Mathlib/Data/Setoid/Basic.lean b/Mathlib/Data/Setoid/Basic.lean index 48dc6951f8870..dac555b84fad5 100644 --- a/Mathlib/Data/Setoid/Basic.lean +++ b/Mathlib/Data/Setoid/Basic.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Amelia Livingston, Bryan Gin-ge Chen -/ import Mathlib.Logic.Relation -import Mathlib.Order.GaloisConnection +import Mathlib.Order.CompleteLattice +import Mathlib.Order.GaloisConnection.Defs /-! # Equivalence relations diff --git a/Mathlib/Order/Closure.lean b/Mathlib/Order/Closure.lean index 8fb5b69f0275c..6353db8a7b166 100644 --- a/Mathlib/Order/Closure.lean +++ b/Mathlib/Order/Closure.lean @@ -5,7 +5,6 @@ Authors: Bhavik Mehta, Yaël Dillies -/ import Mathlib.Data.Set.Lattice import Mathlib.Data.SetLike.Basic -import Mathlib.Order.GaloisConnection import Mathlib.Order.Hom.Basic /-! diff --git a/Mathlib/Order/Cofinal.lean b/Mathlib/Order/Cofinal.lean index 532481a8f4cbe..fb434c2720926 100644 --- a/Mathlib/Order/Cofinal.lean +++ b/Mathlib/Order/Cofinal.lean @@ -3,7 +3,9 @@ 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.Order.GaloisConnection +import Mathlib.Order.GaloisConnection.Defs +import Mathlib.Order.Interval.Set.Basic +import Mathlib.Order.WellFounded /-! # Cofinal sets diff --git a/Mathlib/Order/GaloisConnection.lean b/Mathlib/Order/GaloisConnection/Basic.lean similarity index 57% rename from Mathlib/Order/GaloisConnection.lean rename to Mathlib/Order/GaloisConnection/Basic.lean index c5ad8900514d8..e27bddfa66024 100644 --- a/Mathlib/Order/GaloisConnection.lean +++ b/Mathlib/Order/GaloisConnection/Basic.lean @@ -3,24 +3,15 @@ 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 -/ -import Mathlib.Order.CompleteLattice -import Mathlib.Order.Synonym -import Mathlib.Order.Hom.Set import Mathlib.Order.Bounds.Image +import Mathlib.Order.CompleteLattice +import Mathlib.Order.GaloisConnection.Defs /-! # Galois connections, insertions and coinsertions -Galois connections are order theoretic adjoints, i.e. a pair of functions `u` and `l`, -such that `∀ a b, l a ≤ b ↔ a ≤ u b`. - -## Main definitions - -* `GaloisConnection`: A Galois connection is a pair of functions `l` and `u` satisfying - `l a ≤ b ↔ a ≤ u b`. They are special cases of adjoint functors in category theory, - but do not depend on the category theory library in mathlib. -* `GaloisInsertion`: A Galois insertion is a Galois connection where `l ∘ u = id` -* `GaloisCoinsertion`: A Galois coinsertion is a Galois connection where `u ∘ l = id` +This file contains basic results on Galois connections, insertions and coinsertions in various +order structures, and provides constructions that lift order structures from one type to another. ## Implementation details @@ -53,54 +44,15 @@ universe u v w x variable {α : Type u} {β : Type v} {γ : Type w} {ι : Sort x} {κ : ι → Sort*} {a₁ a₂ : α} {b₁ b₂ : β} -/-- A Galois connection is a pair of functions `l` and `u` satisfying -`l a ≤ b ↔ a ≤ u b`. They are special cases of adjoint functors in category theory, -but do not depend on the category theory library in mathlib. -/ -def GaloisConnection [Preorder α] [Preorder β] (l : α → β) (u : β → α) := - ∀ a b, l a ≤ b ↔ a ≤ u b - -/-- Makes a Galois connection from an order-preserving bijection. -/ -theorem OrderIso.to_galoisConnection [Preorder α] [Preorder β] (oi : α ≃o β) : - GaloisConnection oi oi.symm := fun _ _ => oi.rel_symm_apply.symm - namespace GaloisConnection section variable [Preorder α] [Preorder β] {l : α → β} {u : β → α} -theorem monotone_intro (hu : Monotone u) (hl : Monotone l) (hul : ∀ a, a ≤ u (l a)) - (hlu : ∀ a, l (u a) ≤ a) : GaloisConnection l u := fun _ _ => - ⟨fun h => (hul _).trans (hu h), fun h => (hl h).trans (hlu _)⟩ - -protected theorem dual {l : α → β} {u : β → α} (gc : GaloisConnection l u) : - GaloisConnection (OrderDual.toDual ∘ u ∘ OrderDual.ofDual) - (OrderDual.toDual ∘ l ∘ OrderDual.ofDual) := - fun a b => (gc b a).symm - variable (gc : GaloisConnection l u) include gc -theorem le_iff_le {a : α} {b : β} : l a ≤ b ↔ a ≤ u b := - gc _ _ - -theorem l_le {a : α} {b : β} : a ≤ u b → l a ≤ b := - (gc _ _).mpr - -theorem le_u {a : α} {b : β} : l a ≤ b → a ≤ u b := - (gc _ _).mp - -theorem le_u_l (a) : a ≤ u (l a) := - gc.le_u <| le_rfl - -theorem l_u_le (a) : l (u a) ≤ a := - gc.l_le <| le_rfl - -theorem monotone_u : Monotone u := fun a _ H => gc.le_u ((gc.l_u_le a).trans H) - -theorem monotone_l : Monotone l := - gc.dual.monotone_u.dual - theorem upperBounds_l_image (s : Set α) : upperBounds (l '' s) = u ⁻¹' upperBounds s := Set.ext fun b => by simp [upperBounds, gc _ _] @@ -134,96 +86,8 @@ theorem isGLB_l {a : α} : IsGLB { b | a ≤ u b } (l a) := theorem isLUB_u {b : β} : IsLUB { a | l a ≤ b } (u b) := gc.isGreatest_u.isLUB -/-- If `(l, u)` is a Galois connection, then the relation `x ≤ u (l y)` is a transitive relation. -If `l` is a closure operator (`Submodule.span`, `Subgroup.closure`, ...) and `u` is the coercion to -`Set`, this reads as "if `U` is in the closure of `V` and `V` is in the closure of `W` then `U` is -in the closure of `W`". -/ -theorem le_u_l_trans {x y z : α} (hxy : x ≤ u (l y)) (hyz : y ≤ u (l z)) : x ≤ u (l z) := - hxy.trans (gc.monotone_u <| gc.l_le hyz) - -theorem l_u_le_trans {x y z : β} (hxy : l (u x) ≤ y) (hyz : l (u y) ≤ z) : l (u x) ≤ z := - (gc.monotone_l <| gc.le_u hxy).trans hyz - end -section PartialOrder - -variable [PartialOrder α] [Preorder β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) -include gc - -theorem u_l_u_eq_u (b : β) : u (l (u b)) = u b := - (gc.monotone_u (gc.l_u_le _)).antisymm (gc.le_u_l _) - -theorem u_l_u_eq_u' : u ∘ l ∘ u = u := - funext gc.u_l_u_eq_u - -theorem u_unique {l' : α → β} {u' : β → α} (gc' : GaloisConnection l' u') (hl : ∀ a, l a = l' a) - {b : β} : u b = u' b := - le_antisymm (gc'.le_u <| hl (u b) ▸ gc.l_u_le _) (gc.le_u <| (hl (u' b)).symm ▸ gc'.l_u_le _) - -/-- If there exists a `b` such that `a = u a`, then `b = l a` is one such element. -/ -theorem exists_eq_u (a : α) : (∃ b : β, a = u b) ↔ a = u (l a) := - ⟨fun ⟨_, hS⟩ => hS.symm ▸ (gc.u_l_u_eq_u _).symm, fun HI => ⟨_, HI⟩⟩ - -theorem u_eq {z : α} {y : β} : u y = z ↔ ∀ x, x ≤ z ↔ l x ≤ y := by - constructor - · rintro rfl x - exact (gc x y).symm - · intro H - exact ((H <| u y).mpr (gc.l_u_le y)).antisymm ((gc _ _).mp <| (H z).mp le_rfl) - -end PartialOrder - -section PartialOrder - -variable [Preorder α] [PartialOrder β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) -include gc - -theorem l_u_l_eq_l (a : α) : l (u (l a)) = l a := gc.dual.u_l_u_eq_u _ - -theorem l_u_l_eq_l' : l ∘ u ∘ l = l := funext gc.l_u_l_eq_l - -theorem l_unique {l' : α → β} {u' : β → α} (gc' : GaloisConnection l' u') (hu : ∀ b, u b = u' b) - {a : α} : l a = l' a := - gc.dual.u_unique gc'.dual hu - -/-- If there exists an `a` such that `b = l a`, then `a = u b` is one such element. -/ -theorem exists_eq_l (b : β) : (∃ a : α, b = l a) ↔ b = l (u b) := gc.dual.exists_eq_u _ - -theorem l_eq {x : α} {z : β} : l x = z ↔ ∀ y, z ≤ y ↔ x ≤ u y := gc.dual.u_eq - -end PartialOrder - -section OrderTop - -variable [PartialOrder α] [Preorder β] [OrderTop α] - -theorem u_eq_top {l : α → β} {u : β → α} (gc : GaloisConnection l u) {x} : u x = ⊤ ↔ l ⊤ ≤ x := - top_le_iff.symm.trans gc.le_iff_le.symm - -theorem u_top [OrderTop β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) : u ⊤ = ⊤ := - gc.u_eq_top.2 le_top - -theorem u_l_top {l : α → β} {u : β → α} (gc : GaloisConnection l u) : u (l ⊤) = ⊤ := - gc.u_eq_top.mpr le_rfl - -end OrderTop - -section OrderBot - -variable [Preorder α] [PartialOrder β] [OrderBot β] - -theorem l_eq_bot {l : α → β} {u : β → α} (gc : GaloisConnection l u) {x} : l x = ⊥ ↔ x ≤ u ⊥ := - gc.dual.u_eq_top - -theorem l_bot [OrderBot α] {l : α → β} {u : β → α} (gc : GaloisConnection l u) : l ⊥ = ⊥ := - gc.dual.u_top - -theorem l_u_bot {l : α → β} {u : β → α} (gc : GaloisConnection l u) : l (u ⊥) = ⊥ := - gc.l_eq_bot.mpr le_rfl - -end OrderBot - section SemilatticeSup variable [SemilatticeSup α] [SemilatticeSup β] {l : α → β} {u : β → α} @@ -272,31 +136,9 @@ theorem u_sInf {s : Set β} : u (sInf s) = ⨅ a ∈ s, u a := end CompleteLattice -section LinearOrder - -variable [LinearOrder α] [LinearOrder β] {l : α → β} {u : β → α} - -theorem lt_iff_lt (gc : GaloisConnection l u) {a : α} {b : β} : b < l a ↔ u b < a := - lt_iff_lt_of_le_iff_le (gc a b) - -end LinearOrder - -- Constructing Galois connections section Constructions -protected theorem id [pα : Preorder α] : @GaloisConnection α α pα pα id id := fun _ _ => - Iff.intro (fun x => x) fun x => x - -protected theorem compose [Preorder α] [Preorder β] [Preorder γ] {l1 : α → β} {u1 : β → α} - {l2 : β → γ} {u2 : γ → β} (gc1 : GaloisConnection l1 u1) (gc2 : GaloisConnection l2 u2) : - GaloisConnection (l2 ∘ l1) (u1 ∘ u2) := fun _ _ ↦ (gc2 _ _).trans (gc1 _ _) - -protected theorem dfun {ι : Type u} {α : ι → Type v} {β : ι → Type w} [∀ i, Preorder (α i)] - [∀ i, Preorder (β i)] (l : ∀ i, α i → β i) (u : ∀ i, β i → α i) - (gc : ∀ i, GaloisConnection (l i) (u i)) : - GaloisConnection (fun (a : ∀ i, α i) i => l i (a i)) fun b i => u i (b i) := fun a b => - forall_congr' fun i => gc i (a i) (b i) - protected theorem compl [BooleanAlgebra α] [BooleanAlgebra β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) : GaloisConnection (compl ∘ u ∘ compl) (compl ∘ l ∘ compl) := fun a b ↦ by @@ -305,30 +147,6 @@ protected theorem compl [BooleanAlgebra α] [BooleanAlgebra β] {l : α → β} end Constructions -theorem l_comm_of_u_comm {X : Type*} [Preorder X] {Y : Type*} [Preorder Y] {Z : Type*} - [Preorder Z] {W : Type*} [PartialOrder W] {lYX : X → Y} {uXY : Y → X} - (hXY : GaloisConnection lYX uXY) {lWZ : Z → W} {uZW : W → Z} (hZW : GaloisConnection lWZ uZW) - {lWY : Y → W} {uYW : W → Y} (hWY : GaloisConnection lWY uYW) {lZX : X → Z} {uXZ : Z → X} - (hXZ : GaloisConnection lZX uXZ) (h : ∀ w, uXZ (uZW w) = uXY (uYW w)) {x : X} : - lWZ (lZX x) = lWY (lYX x) := - (hXZ.compose hZW).l_unique (hXY.compose hWY) h - -theorem u_comm_of_l_comm {X : Type*} [PartialOrder X] {Y : Type*} [Preorder Y] {Z : Type*} - [Preorder Z] {W : Type*} [Preorder W] {lYX : X → Y} {uXY : Y → X} - (hXY : GaloisConnection lYX uXY) {lWZ : Z → W} {uZW : W → Z} (hZW : GaloisConnection lWZ uZW) - {lWY : Y → W} {uYW : W → Y} (hWY : GaloisConnection lWY uYW) {lZX : X → Z} {uXZ : Z → X} - (hXZ : GaloisConnection lZX uXZ) (h : ∀ x, lWZ (lZX x) = lWY (lYX x)) {w : W} : - uXZ (uZW w) = uXY (uYW w) := - (hXZ.compose hZW).u_unique (hXY.compose hWY) h - -theorem l_comm_iff_u_comm {X : Type*} [PartialOrder X] {Y : Type*} [Preorder Y] {Z : Type*} - [Preorder Z] {W : Type*} [PartialOrder W] {lYX : X → Y} {uXY : Y → X} - (hXY : GaloisConnection lYX uXY) {lWZ : Z → W} {uZW : W → Z} (hZW : GaloisConnection lWZ uZW) - {lWY : Y → W} {uYW : W → Y} (hWY : GaloisConnection lWY uYW) {lZX : X → Z} {uXZ : Z → X} - (hXZ : GaloisConnection lZX uXZ) : - (∀ w : W, uXZ (uZW w) = uXY (uYW w)) ↔ ∀ x : X, lWZ (lZX x) = lWY (lYX x) := - ⟨hXY.l_comm_of_u_comm hZW hWY hXZ, hXY.u_comm_of_l_comm hZW hWY hXZ⟩ - end GaloisConnection section @@ -413,73 +231,10 @@ theorem galoisConnection_mul_div {k : ℕ} (h : 0 < k) : end Nat --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this used to have a `@[nolint has_nonempty_instance]` -/-- A Galois insertion is a Galois connection where `l ∘ u = id`. It also contains a constructive -choice function, to give better definitional equalities when lifting order structures. Dual -to `GaloisCoinsertion` -/ -structure GaloisInsertion {α β : Type*} [Preorder α] [Preorder β] (l : α → β) (u : β → α) where - /-- A contructive choice function for images of `l`. -/ - choice : ∀ x : α, u (l x) ≤ x → β - /-- The Galois connection associated to a Galois insertion. -/ - gc : GaloisConnection l u - /-- Main property of a Galois insertion. -/ - le_l_u : ∀ x, x ≤ l (u x) - /-- Property of the choice function. -/ - choice_eq : ∀ a h, choice a h = l a - -/-- A constructor for a Galois insertion with the trivial `choice` function. -/ -def GaloisInsertion.monotoneIntro {α β : Type*} [Preorder α] [Preorder β] {l : α → β} {u : β → α} - (hu : Monotone u) (hl : Monotone l) (hul : ∀ a, a ≤ u (l a)) (hlu : ∀ b, l (u b) = b) : - GaloisInsertion l u where - choice x _ := l x - gc := GaloisConnection.monotone_intro hu hl hul fun b => le_of_eq (hlu b) - le_l_u b := le_of_eq <| (hlu b).symm - choice_eq _ _ := rfl - -/-- Makes a Galois insertion from an order-preserving bijection. -/ -protected def OrderIso.toGaloisInsertion [Preorder α] [Preorder β] (oi : α ≃o β) : - GaloisInsertion oi oi.symm where - choice b _ := oi b - gc := oi.to_galoisConnection - le_l_u g := le_of_eq (oi.right_inv g).symm - choice_eq _ _ := rfl - -/-- Make a `GaloisInsertion l u` from a `GaloisConnection l u` such that `∀ b, b ≤ l (u b)` -/ -def GaloisConnection.toGaloisInsertion {α β : Type*} [Preorder α] [Preorder β] {l : α → β} - {u : β → α} (gc : GaloisConnection l u) (h : ∀ b, b ≤ l (u b)) : GaloisInsertion l u := - { choice := fun x _ => l x - gc - le_l_u := h - choice_eq := fun _ _ => rfl } - -/-- Lift the bottom along a Galois connection -/ -def GaloisConnection.liftOrderBot {α β : Type*} [Preorder α] [OrderBot α] [PartialOrder β] - {l : α → β} {u : β → α} (gc : GaloisConnection l u) : - OrderBot β where - bot := l ⊥ - bot_le _ := gc.l_le <| bot_le - namespace GaloisInsertion variable {l : α → β} {u : β → α} -theorem l_u_eq [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) (b : β) : l (u b) = b := - (gi.gc.l_u_le _).antisymm (gi.le_l_u _) - -theorem leftInverse_l_u [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) : - LeftInverse l u := - gi.l_u_eq - -theorem l_top [Preorder α] [PartialOrder β] [OrderTop α] [OrderTop β] - (gi : GaloisInsertion l u) : l ⊤ = ⊤ := - top_unique <| (gi.le_l_u _).trans <| gi.gc.monotone_l le_top - -theorem l_surjective [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) : Surjective l := - gi.leftInverse_l_u.surjective - -theorem u_injective [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) : Injective u := - gi.leftInverse_l_u.injective - theorem l_sup_u [SemilatticeSup α] [SemilatticeSup β] (gi : GaloisInsertion l u) (a b : β) : l (u a ⊔ u b) = a ⊔ b := calc @@ -530,12 +285,6 @@ theorem l_biInf_of_ul_eq_self [CompleteLattice α] [CompleteLattice β] (gi : Ga rw [iInf_subtype', iInf_subtype'] exact gi.l_iInf_of_ul_eq_self _ fun _ => hf _ _ -theorem u_le_u_iff [Preorder α] [Preorder β] (gi : GaloisInsertion l u) {a b} : u a ≤ u b ↔ a ≤ b := - ⟨fun h => (gi.le_l_u _).trans (gi.gc.l_le h), fun h => gi.gc.monotone_u h⟩ - -theorem strictMono_u [Preorder α] [Preorder β] (gi : GaloisInsertion l u) : StrictMono u := - strictMono_of_le_iff_le fun _ _ => gi.u_le_u_iff.symm - theorem isLUB_of_u_image [Preorder α] [Preorder β] (gi : GaloisInsertion l u) {s : Set β} {a : α} (hs : IsLUB (u '' s) a) : IsLUB s (l a) := ⟨fun x hx => (gi.le_l_u x).trans <| gi.gc.monotone_l <| hs.1 <| mem_image_of_mem _ hx, fun _ hx => @@ -612,94 +361,10 @@ end lift end GaloisInsertion --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this used to have a `@[nolint has_nonempty_instance]` -/-- A Galois coinsertion is a Galois connection where `u ∘ l = id`. It also contains a constructive -choice function, to give better definitional equalities when lifting order structures. Dual to -`GaloisInsertion` -/ -structure GaloisCoinsertion [Preorder α] [Preorder β] (l : α → β) (u : β → α) where - /-- A contructive choice function for images of `u`. -/ - choice : ∀ x : β, x ≤ l (u x) → α - /-- The Galois connection associated to a Galois coinsertion. -/ - gc : GaloisConnection l u - /-- Main property of a Galois coinsertion. -/ - u_l_le : ∀ x, u (l x) ≤ x - /-- Property of the choice function. -/ - choice_eq : ∀ a h, choice a h = u a - -/-- Make a `GaloisInsertion` between `αᵒᵈ` and `βᵒᵈ` from a `GaloisCoinsertion` between `α` and -`β`. -/ -def GaloisCoinsertion.dual [Preorder α] [Preorder β] {l : α → β} {u : β → α} : - GaloisCoinsertion l u → GaloisInsertion (toDual ∘ u ∘ ofDual) (toDual ∘ l ∘ ofDual) := - fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ - -/-- Make a `GaloisCoinsertion` between `αᵒᵈ` and `βᵒᵈ` from a `GaloisInsertion` between `α` and -`β`. -/ -def GaloisInsertion.dual [Preorder α] [Preorder β] {l : α → β} {u : β → α} : - GaloisInsertion l u → GaloisCoinsertion (toDual ∘ u ∘ ofDual) (toDual ∘ l ∘ ofDual) := - fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ - -/-- Make a `GaloisInsertion` between `α` and `β` from a `GaloisCoinsertion` between `αᵒᵈ` and -`βᵒᵈ`. -/ -def GaloisCoinsertion.ofDual [Preorder α] [Preorder β] {l : αᵒᵈ → βᵒᵈ} {u : βᵒᵈ → αᵒᵈ} : - GaloisCoinsertion l u → GaloisInsertion (ofDual ∘ u ∘ toDual) (ofDual ∘ l ∘ toDual) := - fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ - -/-- Make a `GaloisCoinsertion` between `α` and `β` from a `GaloisInsertion` between `αᵒᵈ` and -`βᵒᵈ`. -/ -def GaloisInsertion.ofDual [Preorder α] [Preorder β] {l : αᵒᵈ → βᵒᵈ} {u : βᵒᵈ → αᵒᵈ} : - GaloisInsertion l u → GaloisCoinsertion (ofDual ∘ u ∘ toDual) (ofDual ∘ l ∘ toDual) := - fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ - -/-- Makes a Galois coinsertion from an order-preserving bijection. -/ -protected def OrderIso.toGaloisCoinsertion [Preorder α] [Preorder β] (oi : α ≃o β) : - GaloisCoinsertion oi oi.symm where - choice b _ := oi.symm b - gc := oi.to_galoisConnection - u_l_le g := le_of_eq (oi.left_inv g) - choice_eq _ _ := rfl - -/-- A constructor for a Galois coinsertion with the trivial `choice` function. -/ -def GaloisCoinsertion.monotoneIntro [Preorder α] [Preorder β] {l : α → β} {u : β → α} - (hu : Monotone u) (hl : Monotone l) (hlu : ∀ b, l (u b) ≤ b) (hul : ∀ a, u (l a) = a) : - GaloisCoinsertion l u := - (GaloisInsertion.monotoneIntro hl.dual hu.dual hlu hul).ofDual - -/-- Make a `GaloisCoinsertion l u` from a `GaloisConnection l u` such that `∀ a, u (l a) ≤ a` -/ -def GaloisConnection.toGaloisCoinsertion {α β : Type*} [Preorder α] [Preorder β] {l : α → β} - {u : β → α} (gc : GaloisConnection l u) (h : ∀ a, u (l a) ≤ a) : GaloisCoinsertion l u := - { choice := fun x _ => u x - gc - u_l_le := h - choice_eq := fun _ _ => rfl } - -/-- Lift the top along a Galois connection -/ -def GaloisConnection.liftOrderTop {α β : Type*} [PartialOrder α] [Preorder β] [OrderTop β] - {l : α → β} {u : β → α} (gc : GaloisConnection l u) : - OrderTop α where - top := u ⊤ - le_top _ := gc.le_u <| le_top - namespace GaloisCoinsertion variable {l : α → β} {u : β → α} -theorem u_l_eq [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) (a : α) : u (l a) = a := - gi.dual.l_u_eq a - -theorem u_l_leftInverse [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) : - LeftInverse u l := - gi.u_l_eq - -theorem u_bot [PartialOrder α] [Preorder β] [OrderBot α] [OrderBot β] (gi : GaloisCoinsertion l u) : - u ⊥ = ⊥ := - gi.dual.l_top - -theorem u_surjective [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) : Surjective u := - gi.dual.l_surjective - -theorem l_injective [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) : Injective l := - gi.dual.u_injective - theorem u_inf_l [SemilatticeInf α] [SemilatticeInf β] (gi : GaloisCoinsertion l u) (a b : α) : u (l a ⊓ l b) = a ⊓ b := gi.dual.l_sup_u a b @@ -737,13 +402,6 @@ theorem u_biSup_of_lu_eq_self [CompleteLattice α] [CompleteLattice β] (gi : Ga u (⨆ (i) (hi), f i hi) = ⨆ (i) (hi), u (f i hi) := gi.dual.l_biInf_of_ul_eq_self _ hf -theorem l_le_l_iff [Preorder α] [Preorder β] (gi : GaloisCoinsertion l u) {a b} : - l a ≤ l b ↔ a ≤ b := - gi.dual.u_le_u_iff - -theorem strictMono_l [Preorder α] [Preorder β] (gi : GaloisCoinsertion l u) : StrictMono l := - fun _ _ h => gi.dual.strictMono_u h - theorem isGLB_of_l_image [Preorder α] [Preorder β] (gi : GaloisCoinsertion l u) {s : Set α} {a : β} (hs : IsGLB (l '' s) a) : IsGLB s (u a) := gi.dual.isLUB_of_u_image hs diff --git a/Mathlib/Order/GaloisConnection/Defs.lean b/Mathlib/Order/GaloisConnection/Defs.lean new file mode 100644 index 0000000000000..42e6d95b14602 --- /dev/null +++ b/Mathlib/Order/GaloisConnection/Defs.lean @@ -0,0 +1,395 @@ +/- +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 +-/ +import Mathlib.Order.BoundedOrder.Basic +import Mathlib.Order.Hom.Basic +import Mathlib.Order.Monotone.Basic + +/-! +# Galois connections, insertions and coinsertions + +Galois connections are order theoretic adjoints, i.e. a pair of functions `u` and `l`, +such that `∀ a b, l a ≤ b ↔ a ≤ u b`. + +## Main definitions + +* `GaloisConnection`: A Galois connection is a pair of functions `l` and `u` satisfying + `l a ≤ b ↔ a ≤ u b`. They are special cases of adjoint functors in category theory, + but do not depend on the category theory library in mathlib. +* `GaloisInsertion`: A Galois insertion is a Galois connection where `l ∘ u = id` +* `GaloisCoinsertion`: A Galois coinsertion is a Galois connection where `u ∘ l = id` +-/ + +assert_not_exists CompleteLattice + +open Function OrderDual Set + +universe u v w x + +variable {α : Type u} {β : Type v} {γ : Type w} {ι : Sort x} {κ : ι → Sort*} {a₁ a₂ : α} + {b₁ b₂ : β} + +/-- A Galois connection is a pair of functions `l` and `u` satisfying +`l a ≤ b ↔ a ≤ u b`. They are special cases of adjoint functors in category theory, +but do not depend on the category theory library in mathlib. -/ +def GaloisConnection [Preorder α] [Preorder β] (l : α → β) (u : β → α) := + ∀ a b, l a ≤ b ↔ a ≤ u b + +/-- Makes a Galois connection from an order-preserving bijection. -/ +theorem OrderIso.to_galoisConnection [Preorder α] [Preorder β] (oi : α ≃o β) : + GaloisConnection oi oi.symm := fun _ _ => oi.rel_symm_apply.symm + +namespace GaloisConnection + +section + +variable [Preorder α] [Preorder β] {l : α → β} {u : β → α} + +theorem monotone_intro (hu : Monotone u) (hl : Monotone l) (hul : ∀ a, a ≤ u (l a)) + (hlu : ∀ a, l (u a) ≤ a) : GaloisConnection l u := fun _ _ => + ⟨fun h => (hul _).trans (hu h), fun h => (hl h).trans (hlu _)⟩ + +protected theorem dual {l : α → β} {u : β → α} (gc : GaloisConnection l u) : + GaloisConnection (OrderDual.toDual ∘ u ∘ OrderDual.ofDual) + (OrderDual.toDual ∘ l ∘ OrderDual.ofDual) := + fun a b => (gc b a).symm + +variable (gc : GaloisConnection l u) +include gc + +theorem le_iff_le {a : α} {b : β} : l a ≤ b ↔ a ≤ u b := + gc _ _ + +theorem l_le {a : α} {b : β} : a ≤ u b → l a ≤ b := + (gc _ _).mpr + +theorem le_u {a : α} {b : β} : l a ≤ b → a ≤ u b := + (gc _ _).mp + +theorem le_u_l (a) : a ≤ u (l a) := + gc.le_u <| le_rfl + +theorem l_u_le (a) : l (u a) ≤ a := + gc.l_le <| le_rfl + +theorem monotone_u : Monotone u := fun a _ H => gc.le_u ((gc.l_u_le a).trans H) + +theorem monotone_l : Monotone l := + gc.dual.monotone_u.dual + +/-- If `(l, u)` is a Galois connection, then the relation `x ≤ u (l y)` is a transitive relation. +If `l` is a closure operator (`Submodule.span`, `Subgroup.closure`, ...) and `u` is the coercion to +`Set`, this reads as "if `U` is in the closure of `V` and `V` is in the closure of `W` then `U` is +in the closure of `W`". -/ +theorem le_u_l_trans {x y z : α} (hxy : x ≤ u (l y)) (hyz : y ≤ u (l z)) : x ≤ u (l z) := + hxy.trans (gc.monotone_u <| gc.l_le hyz) + +theorem l_u_le_trans {x y z : β} (hxy : l (u x) ≤ y) (hyz : l (u y) ≤ z) : l (u x) ≤ z := + (gc.monotone_l <| gc.le_u hxy).trans hyz + +end + +section PartialOrder + +variable [PartialOrder α] [Preorder β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) +include gc + +theorem u_l_u_eq_u (b : β) : u (l (u b)) = u b := + (gc.monotone_u (gc.l_u_le _)).antisymm (gc.le_u_l _) + +theorem u_l_u_eq_u' : u ∘ l ∘ u = u := + funext gc.u_l_u_eq_u + +theorem u_unique {l' : α → β} {u' : β → α} (gc' : GaloisConnection l' u') (hl : ∀ a, l a = l' a) + {b : β} : u b = u' b := + le_antisymm (gc'.le_u <| hl (u b) ▸ gc.l_u_le _) (gc.le_u <| (hl (u' b)).symm ▸ gc'.l_u_le _) + +/-- If there exists a `b` such that `a = u a`, then `b = l a` is one such element. -/ +theorem exists_eq_u (a : α) : (∃ b : β, a = u b) ↔ a = u (l a) := + ⟨fun ⟨_, hS⟩ => hS.symm ▸ (gc.u_l_u_eq_u _).symm, fun HI => ⟨_, HI⟩⟩ + +theorem u_eq {z : α} {y : β} : u y = z ↔ ∀ x, x ≤ z ↔ l x ≤ y := by + constructor + · rintro rfl x + exact (gc x y).symm + · intro H + exact ((H <| u y).mpr (gc.l_u_le y)).antisymm ((gc _ _).mp <| (H z).mp le_rfl) + +end PartialOrder + +section PartialOrder + +variable [Preorder α] [PartialOrder β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) +include gc + +theorem l_u_l_eq_l (a : α) : l (u (l a)) = l a := gc.dual.u_l_u_eq_u _ + +theorem l_u_l_eq_l' : l ∘ u ∘ l = l := funext gc.l_u_l_eq_l + +theorem l_unique {l' : α → β} {u' : β → α} (gc' : GaloisConnection l' u') (hu : ∀ b, u b = u' b) + {a : α} : l a = l' a := + gc.dual.u_unique gc'.dual hu + +/-- If there exists an `a` such that `b = l a`, then `a = u b` is one such element. -/ +theorem exists_eq_l (b : β) : (∃ a : α, b = l a) ↔ b = l (u b) := gc.dual.exists_eq_u _ + +theorem l_eq {x : α} {z : β} : l x = z ↔ ∀ y, z ≤ y ↔ x ≤ u y := gc.dual.u_eq + +end PartialOrder + +section OrderTop + +variable [PartialOrder α] [Preorder β] [OrderTop α] + +theorem u_eq_top {l : α → β} {u : β → α} (gc : GaloisConnection l u) {x} : u x = ⊤ ↔ l ⊤ ≤ x := + top_le_iff.symm.trans gc.le_iff_le.symm + +theorem u_top [OrderTop β] {l : α → β} {u : β → α} (gc : GaloisConnection l u) : u ⊤ = ⊤ := + gc.u_eq_top.2 le_top + +theorem u_l_top {l : α → β} {u : β → α} (gc : GaloisConnection l u) : u (l ⊤) = ⊤ := + gc.u_eq_top.mpr le_rfl + +end OrderTop + +section OrderBot + +variable [Preorder α] [PartialOrder β] [OrderBot β] + +theorem l_eq_bot {l : α → β} {u : β → α} (gc : GaloisConnection l u) {x} : l x = ⊥ ↔ x ≤ u ⊥ := + gc.dual.u_eq_top + +theorem l_bot [OrderBot α] {l : α → β} {u : β → α} (gc : GaloisConnection l u) : l ⊥ = ⊥ := + gc.dual.u_top + +theorem l_u_bot {l : α → β} {u : β → α} (gc : GaloisConnection l u) : l (u ⊥) = ⊥ := + gc.l_eq_bot.mpr le_rfl + +end OrderBot + +section LinearOrder + +variable [LinearOrder α] [LinearOrder β] {l : α → β} {u : β → α} + +theorem lt_iff_lt (gc : GaloisConnection l u) {a : α} {b : β} : b < l a ↔ u b < a := + lt_iff_lt_of_le_iff_le (gc a b) + +end LinearOrder + +-- Constructing Galois connections +section Constructions + +protected theorem id [pα : Preorder α] : @GaloisConnection α α pα pα id id := fun _ _ => + Iff.intro (fun x => x) fun x => x + +protected theorem compose [Preorder α] [Preorder β] [Preorder γ] {l1 : α → β} {u1 : β → α} + {l2 : β → γ} {u2 : γ → β} (gc1 : GaloisConnection l1 u1) (gc2 : GaloisConnection l2 u2) : + GaloisConnection (l2 ∘ l1) (u1 ∘ u2) := fun _ _ ↦ (gc2 _ _).trans (gc1 _ _) + +protected theorem dfun {ι : Type u} {α : ι → Type v} {β : ι → Type w} [∀ i, Preorder (α i)] + [∀ i, Preorder (β i)] (l : ∀ i, α i → β i) (u : ∀ i, β i → α i) + (gc : ∀ i, GaloisConnection (l i) (u i)) : + GaloisConnection (fun (a : ∀ i, α i) i => l i (a i)) fun b i => u i (b i) := fun a b => + forall_congr' fun i => gc i (a i) (b i) + +end Constructions + +theorem l_comm_of_u_comm {X : Type*} [Preorder X] {Y : Type*} [Preorder Y] {Z : Type*} + [Preorder Z] {W : Type*} [PartialOrder W] {lYX : X → Y} {uXY : Y → X} + (hXY : GaloisConnection lYX uXY) {lWZ : Z → W} {uZW : W → Z} (hZW : GaloisConnection lWZ uZW) + {lWY : Y → W} {uYW : W → Y} (hWY : GaloisConnection lWY uYW) {lZX : X → Z} {uXZ : Z → X} + (hXZ : GaloisConnection lZX uXZ) (h : ∀ w, uXZ (uZW w) = uXY (uYW w)) {x : X} : + lWZ (lZX x) = lWY (lYX x) := + (hXZ.compose hZW).l_unique (hXY.compose hWY) h + +theorem u_comm_of_l_comm {X : Type*} [PartialOrder X] {Y : Type*} [Preorder Y] {Z : Type*} + [Preorder Z] {W : Type*} [Preorder W] {lYX : X → Y} {uXY : Y → X} + (hXY : GaloisConnection lYX uXY) {lWZ : Z → W} {uZW : W → Z} (hZW : GaloisConnection lWZ uZW) + {lWY : Y → W} {uYW : W → Y} (hWY : GaloisConnection lWY uYW) {lZX : X → Z} {uXZ : Z → X} + (hXZ : GaloisConnection lZX uXZ) (h : ∀ x, lWZ (lZX x) = lWY (lYX x)) {w : W} : + uXZ (uZW w) = uXY (uYW w) := + (hXZ.compose hZW).u_unique (hXY.compose hWY) h + +theorem l_comm_iff_u_comm {X : Type*} [PartialOrder X] {Y : Type*} [Preorder Y] {Z : Type*} + [Preorder Z] {W : Type*} [PartialOrder W] {lYX : X → Y} {uXY : Y → X} + (hXY : GaloisConnection lYX uXY) {lWZ : Z → W} {uZW : W → Z} (hZW : GaloisConnection lWZ uZW) + {lWY : Y → W} {uYW : W → Y} (hWY : GaloisConnection lWY uYW) {lZX : X → Z} {uXZ : Z → X} + (hXZ : GaloisConnection lZX uXZ) : + (∀ w : W, uXZ (uZW w) = uXY (uYW w)) ↔ ∀ x : X, lWZ (lZX x) = lWY (lYX x) := + ⟨hXY.l_comm_of_u_comm hZW hWY hXZ, hXY.u_comm_of_l_comm hZW hWY hXZ⟩ + +end GaloisConnection + +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this used to have a `@[nolint has_nonempty_instance]` +/-- A Galois insertion is a Galois connection where `l ∘ u = id`. It also contains a constructive +choice function, to give better definitional equalities when lifting order structures. Dual +to `GaloisCoinsertion` -/ +structure GaloisInsertion {α β : Type*} [Preorder α] [Preorder β] (l : α → β) (u : β → α) where + /-- A contructive choice function for images of `l`. -/ + choice : ∀ x : α, u (l x) ≤ x → β + /-- The Galois connection associated to a Galois insertion. -/ + gc : GaloisConnection l u + /-- Main property of a Galois insertion. -/ + le_l_u : ∀ x, x ≤ l (u x) + /-- Property of the choice function. -/ + choice_eq : ∀ a h, choice a h = l a + +/-- Makes a Galois insertion from an order-preserving bijection. -/ +protected def OrderIso.toGaloisInsertion [Preorder α] [Preorder β] (oi : α ≃o β) : + GaloisInsertion oi oi.symm where + choice b _ := oi b + gc := oi.to_galoisConnection + le_l_u g := le_of_eq (oi.right_inv g).symm + choice_eq _ _ := rfl + +/-- A constructor for a Galois insertion with the trivial `choice` function. -/ +def GaloisInsertion.monotoneIntro {α β : Type*} [Preorder α] [Preorder β] {l : α → β} {u : β → α} + (hu : Monotone u) (hl : Monotone l) (hul : ∀ a, a ≤ u (l a)) (hlu : ∀ b, l (u b) = b) : + GaloisInsertion l u where + choice x _ := l x + gc := GaloisConnection.monotone_intro hu hl hul fun b => le_of_eq (hlu b) + le_l_u b := le_of_eq <| (hlu b).symm + choice_eq _ _ := rfl + +/-- Make a `GaloisInsertion l u` from a `GaloisConnection l u` such that `∀ b, b ≤ l (u b)` -/ +def GaloisConnection.toGaloisInsertion {α β : Type*} [Preorder α] [Preorder β] {l : α → β} + {u : β → α} (gc : GaloisConnection l u) (h : ∀ b, b ≤ l (u b)) : GaloisInsertion l u := + { choice := fun x _ => l x + gc + le_l_u := h + choice_eq := fun _ _ => rfl } + +/-- Lift the bottom along a Galois connection -/ +def GaloisConnection.liftOrderBot {α β : Type*} [Preorder α] [OrderBot α] [PartialOrder β] + {l : α → β} {u : β → α} (gc : GaloisConnection l u) : + OrderBot β where + bot := l ⊥ + bot_le _ := gc.l_le <| bot_le + +namespace GaloisInsertion + +variable {l : α → β} {u : β → α} + +theorem l_u_eq [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) (b : β) : l (u b) = b := + (gi.gc.l_u_le _).antisymm (gi.le_l_u _) + +theorem leftInverse_l_u [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) : + LeftInverse l u := + gi.l_u_eq + +theorem l_top [Preorder α] [PartialOrder β] [OrderTop α] [OrderTop β] + (gi : GaloisInsertion l u) : l ⊤ = ⊤ := + top_unique <| (gi.le_l_u _).trans <| gi.gc.monotone_l le_top + +theorem l_surjective [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) : Surjective l := + gi.leftInverse_l_u.surjective + +theorem u_injective [Preorder α] [PartialOrder β] (gi : GaloisInsertion l u) : Injective u := + gi.leftInverse_l_u.injective + +theorem u_le_u_iff [Preorder α] [Preorder β] (gi : GaloisInsertion l u) {a b} : u a ≤ u b ↔ a ≤ b := + ⟨fun h => (gi.le_l_u _).trans (gi.gc.l_le h), fun h => gi.gc.monotone_u h⟩ + +theorem strictMono_u [Preorder α] [Preorder β] (gi : GaloisInsertion l u) : StrictMono u := + strictMono_of_le_iff_le fun _ _ => gi.u_le_u_iff.symm + +end GaloisInsertion + +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this used to have a `@[nolint has_nonempty_instance]` +/-- A Galois coinsertion is a Galois connection where `u ∘ l = id`. It also contains a constructive +choice function, to give better definitional equalities when lifting order structures. Dual to +`GaloisInsertion` -/ +structure GaloisCoinsertion [Preorder α] [Preorder β] (l : α → β) (u : β → α) where + /-- A contructive choice function for images of `u`. -/ + choice : ∀ x : β, x ≤ l (u x) → α + /-- The Galois connection associated to a Galois coinsertion. -/ + gc : GaloisConnection l u + /-- Main property of a Galois coinsertion. -/ + u_l_le : ∀ x, u (l x) ≤ x + /-- Property of the choice function. -/ + choice_eq : ∀ a h, choice a h = u a + +/-- Makes a Galois coinsertion from an order-preserving bijection. -/ +protected def OrderIso.toGaloisCoinsertion [Preorder α] [Preorder β] (oi : α ≃o β) : + GaloisCoinsertion oi oi.symm where + choice b _ := oi.symm b + gc := oi.to_galoisConnection + u_l_le g := le_of_eq (oi.left_inv g) + choice_eq _ _ := rfl + +/-- Make a `GaloisInsertion` between `αᵒᵈ` and `βᵒᵈ` from a `GaloisCoinsertion` between `α` and +`β`. -/ +def GaloisCoinsertion.dual [Preorder α] [Preorder β] {l : α → β} {u : β → α} : + GaloisCoinsertion l u → GaloisInsertion (toDual ∘ u ∘ ofDual) (toDual ∘ l ∘ ofDual) := + fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ + +/-- Make a `GaloisCoinsertion` between `αᵒᵈ` and `βᵒᵈ` from a `GaloisInsertion` between `α` and +`β`. -/ +def GaloisInsertion.dual [Preorder α] [Preorder β] {l : α → β} {u : β → α} : + GaloisInsertion l u → GaloisCoinsertion (toDual ∘ u ∘ ofDual) (toDual ∘ l ∘ ofDual) := + fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ + +/-- Make a `GaloisInsertion` between `α` and `β` from a `GaloisCoinsertion` between `αᵒᵈ` and +`βᵒᵈ`. -/ +def GaloisCoinsertion.ofDual [Preorder α] [Preorder β] {l : αᵒᵈ → βᵒᵈ} {u : βᵒᵈ → αᵒᵈ} : + GaloisCoinsertion l u → GaloisInsertion (ofDual ∘ u ∘ toDual) (ofDual ∘ l ∘ toDual) := + fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ + +/-- Make a `GaloisCoinsertion` between `α` and `β` from a `GaloisInsertion` between `αᵒᵈ` and +`βᵒᵈ`. -/ +def GaloisInsertion.ofDual [Preorder α] [Preorder β] {l : αᵒᵈ → βᵒᵈ} {u : βᵒᵈ → αᵒᵈ} : + GaloisInsertion l u → GaloisCoinsertion (ofDual ∘ u ∘ toDual) (ofDual ∘ l ∘ toDual) := + fun x => ⟨x.1, x.2.dual, x.3, x.4⟩ + +/-- A constructor for a Galois coinsertion with the trivial `choice` function. -/ +def GaloisCoinsertion.monotoneIntro [Preorder α] [Preorder β] {l : α → β} {u : β → α} + (hu : Monotone u) (hl : Monotone l) (hlu : ∀ b, l (u b) ≤ b) (hul : ∀ a, u (l a) = a) : + GaloisCoinsertion l u := + (GaloisInsertion.monotoneIntro hl.dual hu.dual hlu hul).ofDual + +/-- Make a `GaloisCoinsertion l u` from a `GaloisConnection l u` such that `∀ a, u (l a) ≤ a` -/ +def GaloisConnection.toGaloisCoinsertion {α β : Type*} [Preorder α] [Preorder β] {l : α → β} + {u : β → α} (gc : GaloisConnection l u) (h : ∀ a, u (l a) ≤ a) : GaloisCoinsertion l u := + { choice := fun x _ => u x + gc + u_l_le := h + choice_eq := fun _ _ => rfl } + +/-- Lift the top along a Galois connection -/ +def GaloisConnection.liftOrderTop {α β : Type*} [PartialOrder α] [Preorder β] [OrderTop β] + {l : α → β} {u : β → α} (gc : GaloisConnection l u) : + OrderTop α where + top := u ⊤ + le_top _ := gc.le_u <| le_top + +namespace GaloisCoinsertion + +variable {l : α → β} {u : β → α} + +theorem u_l_eq [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) (a : α) : u (l a) = a := + gi.dual.l_u_eq a + +theorem u_l_leftInverse [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) : + LeftInverse u l := + gi.u_l_eq + +theorem u_bot [PartialOrder α] [Preorder β] [OrderBot α] [OrderBot β] (gi : GaloisCoinsertion l u) : + u ⊥ = ⊥ := + gi.dual.l_top + +theorem u_surjective [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) : Surjective u := + gi.dual.l_surjective + +theorem l_injective [PartialOrder α] [Preorder β] (gi : GaloisCoinsertion l u) : Injective l := + gi.dual.u_injective + +theorem l_le_l_iff [Preorder α] [Preorder β] (gi : GaloisCoinsertion l u) {a b} : + l a ≤ l b ↔ a ≤ b := + gi.dual.u_le_u_iff + +theorem strictMono_l [Preorder α] [Preorder β] (gi : GaloisCoinsertion l u) : StrictMono l := + fun _ _ h => gi.dual.strictMono_u h + +end GaloisCoinsertion diff --git a/Mathlib/Order/Heyting/Regular.lean b/Mathlib/Order/Heyting/Regular.lean index e58ab2d79ed47..6af155458a241 100644 --- a/Mathlib/Order/Heyting/Regular.lean +++ b/Mathlib/Order/Heyting/Regular.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Order.GaloisConnection +import Mathlib.Order.GaloisConnection.Basic /-! # Heyting regular elements diff --git a/Mathlib/Order/Hom/Order.lean b/Mathlib/Order/Hom/Order.lean index 730ef64eb8a36..e543b1d530b51 100644 --- a/Mathlib/Order/Hom/Order.lean +++ b/Mathlib/Order/Hom/Order.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Anne Baanen -/ import Mathlib.Logic.Function.Iterate -import Mathlib.Order.GaloisConnection +import Mathlib.Order.GaloisConnection.Basic import Mathlib.Order.Hom.Basic /-! diff --git a/Mathlib/Order/ModularLattice.lean b/Mathlib/Order/ModularLattice.lean index 7b2b7f77ae7f8..0f8ca712abcc2 100644 --- a/Mathlib/Order/ModularLattice.lean +++ b/Mathlib/Order/ModularLattice.lean @@ -5,7 +5,7 @@ Authors: Aaron Anderson, Yaël Dillies -/ import Mathlib.Order.Cover import Mathlib.Order.LatticeIntervals -import Mathlib.Order.GaloisConnection +import Mathlib.Order.GaloisConnection.Defs /-! # Modular Lattices diff --git a/Mathlib/Order/Rel/GaloisConnection.lean b/Mathlib/Order/Rel/GaloisConnection.lean index 9666eb999ee6b..a6899c904cc0a 100644 --- a/Mathlib/Order/Rel/GaloisConnection.lean +++ b/Mathlib/Order/Rel/GaloisConnection.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anthony Bordg -/ import Mathlib.Data.Rel -import Mathlib.Order.GaloisConnection /-! # The Galois Connection Induced by a Relation From 30e9b28af312fc11653ad106b3612b87370f1a76 Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Mon, 20 Jan 2025 11:48:37 +0000 Subject: [PATCH 326/681] =?UTF-8?q?feat(RingTheory):=20`H=C2=B9(L)`=20unde?= =?UTF-8?q?r=20localization=20(#20591)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib/RingTheory/Etale/Basic.lean | 21 ++ Mathlib/RingTheory/Etale/Kaehler.lean | 328 ++++++++++++++++++++++++- Mathlib/RingTheory/Extension.lean | 9 + Mathlib/RingTheory/Smooth/Kaehler.lean | 18 ++ 4 files changed, 374 insertions(+), 2 deletions(-) diff --git a/Mathlib/RingTheory/Etale/Basic.lean b/Mathlib/RingTheory/Etale/Basic.lean index ca33968558ff3..127e6a5b37aeb 100644 --- a/Mathlib/RingTheory/Etale/Basic.lean +++ b/Mathlib/RingTheory/Etale/Basic.lean @@ -214,3 +214,24 @@ theorem of_isLocalization_Away (r : R) [IsLocalization.Away r A] : Etale R A whe end Etale end Algebra + +namespace RingHom + +variable {R S : Type u} [CommRing R] [CommRing S] + +/-- +A ring homomorphism `R →+* A` is formally etale if it is formally unramified and formally smooth. +See `Algebra.FormallyEtale`. +-/ +@[algebraize Algebra.FormallyEtale] +def FormallyEtale (f : R →+* S) : Prop := + letI := f.toAlgebra + Algebra.FormallyEtale R S + +lemma formallyEtale_algebraMap [Algebra R S] : + (algebraMap R S).FormallyEtale ↔ Algebra.FormallyEtale R S := by + delta FormallyEtale + congr! + exact Algebra.algebra_ext _ _ fun _ ↦ rfl + +end RingHom diff --git a/Mathlib/RingTheory/Etale/Kaehler.lean b/Mathlib/RingTheory/Etale/Kaehler.lean index 509af402e838f..58bb20c889400 100644 --- a/Mathlib/RingTheory/Etale/Kaehler.lean +++ b/Mathlib/RingTheory/Etale/Kaehler.lean @@ -7,13 +7,16 @@ import Mathlib.RingTheory.Etale.Basic import Mathlib.RingTheory.Kaehler.JacobiZariski import Mathlib.RingTheory.Localization.BaseChange import Mathlib.RingTheory.Smooth.Kaehler +import Mathlib.RingTheory.Flat.Localization /-! # The differential module and etale algebras ## Main results -`KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale`: -The canonical isomorphism `T ⊗[S] Ω[S⁄R] ≃ₗ[T] Ω[T⁄R]` for `T` a formally etale `S`-algebra. +- `KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale`: + The canonical isomorphism `T ⊗[S] Ω[S⁄R] ≃ₗ[T] Ω[T⁄R]` for `T` a formally etale `S`-algebra. +- `Algebra.tensorH1CotangentOfIsLocalization`: + The canonical isomorphism `T ⊗[S] H¹(L_{S⁄R}) ≃ₗ[T] H¹(L_{T⁄R})` for `T` a localization of `S`. -/ universe u @@ -37,6 +40,12 @@ def KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale [Algebra.FormallyEtale obtain ⟨x, rfl⟩ := (Algebra.H1Cotangent.exact_δ_mapBaseChange R S T x).mp hx rw [Subsingleton.elim x 0, map_zero] +lemma KaehlerDifferential.tensorKaehlerEquivOfFormallyEtale_symm_D_algebraMap + [Algebra.FormallyEtale S T] (s : S) : + (tensorKaehlerEquivOfFormallyEtale R S T).symm (D R T (algebraMap S T s)) = 1 ⊗ₜ D R S s := by + rw [LinearEquiv.symm_apply_eq, tensorKaehlerEquivOfFormallyEtale_apply, mapBaseChange_tmul, + one_smul, map_D] + lemma KaehlerDifferential.isBaseChange_of_formallyEtale [Algebra.FormallyEtale S T] : IsBaseChange T (map R R S T) := by show Function.Bijective _ @@ -51,3 +60,318 @@ instance KaehlerDifferential.isLocalizedModule_map (M : Submonoid S) [IsLocaliza IsLocalizedModule M (map R R S T) := have := Algebra.FormallyEtale.of_isLocalization (Rₘ := T) M (isLocalizedModule_iff_isBaseChange M T _).mpr (isBaseChange_of_formallyEtale R S T) + +namespace Algebra.Extension + +open KaehlerDifferential + +attribute [local instance] SMulCommClass.of_commMonoid + +variable {R S T} + +/-! +Suppose we have a morphism of extensions of `R`-algebras +``` +0 → J → Q → T → 0 + ↑ ↑ ↑ +0 → I → P → S → 0 +``` +-/ +variable {P : Extension.{u} R S} {Q : Extension.{u} R T} (f : P.Hom Q) + +/-- If `P → Q` is formally etale, then `T ⊗ₛ (S ⊗ₚ Ω[P/R]) ≃ T ⊗_Q Ω[Q/R]`. -/ +noncomputable +def tensorCotangentSpace + (H : f.toRingHom.FormallyEtale) : + T ⊗[S] P.CotangentSpace ≃ₗ[T] Q.CotangentSpace := + letI := f.toRingHom.toAlgebra + haveI : IsScalarTower R P.Ring Q.Ring := + .of_algebraMap_eq fun r ↦ (f.toRingHom_algebraMap r).symm + letI := ((algebraMap S T).comp (algebraMap P.Ring S)).toAlgebra + haveI : IsScalarTower P.Ring S T := .of_algebraMap_eq' rfl + haveI : IsScalarTower P.Ring Q.Ring T := + .of_algebraMap_eq fun r ↦ (f.algebraMap_toRingHom r).symm + haveI : FormallyEtale P.Ring Q.Ring := ‹_› + { __ := (CotangentSpace.map f).liftBaseChange T + invFun := LinearMap.liftBaseChange T (by + refine LinearMap.liftBaseChange _ ?_ ∘ₗ + (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).symm.toLinearMap + exact (TensorProduct.mk _ _ _ 1).restrictScalars P.Ring ∘ₗ + (TensorProduct.mk _ _ _ 1).restrictScalars P.Ring) + left_inv x := by + show (LinearMap.liftBaseChange _ _ ∘ₗ LinearMap.liftBaseChange _ _) x = + LinearMap.id (R := T) x + congr 1 + ext : 4 + refine Derivation.liftKaehlerDifferential_unique + (R := R) (S := P.Ring) (M := T ⊗[S] P.CotangentSpace) _ _ ?_ + ext a + have : (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).symm + ((D R Q.Ring) (f.toRingHom a)) = 1 ⊗ₜ D _ _ a := + tensorKaehlerEquivOfFormallyEtale_symm_D_algebraMap R P.Ring Q.Ring a + simp [this] + right_inv x := by + show (LinearMap.liftBaseChange _ _ ∘ₗ LinearMap.liftBaseChange _ _) x = + LinearMap.id (R := T) x + congr 1 + ext a + dsimp + obtain ⟨x, hx⟩ := (tensorKaehlerEquivOfFormallyEtale R P.Ring _).surjective (D R Q.Ring a) + simp only [one_smul, ← hx, LinearEquiv.symm_apply_apply] + show (((CotangentSpace.map f).liftBaseChange T).restrictScalars Q.Ring ∘ₗ + LinearMap.liftBaseChange _ _) x = ((TensorProduct.mk _ _ _ 1) ∘ₗ + (tensorKaehlerEquivOfFormallyEtale R P.Ring Q.Ring).toLinearMap) x + congr 1 + ext a + simp; rfl } + +/-- (Implementation) +If `J ≃ Q ⊗ₚ I` (e.g. when `T = Q ⊗ₚ S` and `P → Q` is flat), then `T ⊗ₛ I/I² ≃ J/J²`. +This is the inverse. -/ +noncomputable +def tensorCotangentInvFun + [alg : Algebra P.Ring Q.Ring] (halg : algebraMap P.Ring Q.Ring = f.toRingHom) + (H : Function.Bijective ((f.mapKer halg).liftBaseChange Q.Ring)) : + Q.Cotangent →+ T ⊗[S] P.Cotangent := + letI := ((algebraMap S T).comp (algebraMap P.Ring S)).toAlgebra + haveI : IsScalarTower P.Ring S T := .of_algebraMap_eq' rfl + haveI : IsScalarTower P.Ring Q.Ring T := + .of_algebraMap_eq fun r ↦ halg ▸ (f.algebraMap_toRingHom r).symm + letI e := LinearEquiv.ofBijective _ H + letI f' : Q.ker →ₗ[Q.Ring] T ⊗[S] P.Cotangent := + (LinearMap.liftBaseChange _ + ((TensorProduct.mk _ _ _ 1).restrictScalars _ ∘ₗ Cotangent.mk)) ∘ₗ e.symm.toLinearMap + QuotientAddGroup.lift _ f' <| by + intro x hx + refine Submodule.smul_induction_on hx ?_ fun _ _ ↦ add_mem + clear x hx + rintro a ha b - + obtain ⟨x, hx⟩ := e.surjective ⟨a, ha⟩ + obtain rfl : (e x).1 = a := congr_arg Subtype.val hx + obtain ⟨y, rfl⟩ := e.surjective b + simp only [AddMonoidHom.mem_ker, AddMonoidHom.coe_coe, map_smul, + LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, + LinearEquiv.symm_apply_apply, f'] + clear hx ha + induction x with + | zero => simp only [LinearEquiv.map_zero, ZeroMemClass.coe_zero, zero_smul] + | add x y _ _ => + simp only [LinearEquiv.map_add, Submodule.coe_add, add_smul, zero_add, *] + | tmul a b => + induction y with + | zero => simp only [LinearEquiv.map_zero, LinearMap.map_zero, smul_zero] + | add x y hx hy => simp only [LinearMap.map_add, smul_add, hx, hy, zero_add] + | tmul c d => + simp only [LinearMap.liftBaseChange_tmul, LinearMap.coe_comp, SetLike.val_smul, + LinearMap.coe_restrictScalars, Function.comp_apply, mk_apply, smul_eq_mul, e, + LinearMap.liftBaseChange_tmul, LinearEquiv.ofBijective_apply] + have h₂ : b.1 • Cotangent.mk d = 0 := by ext; simp [Cotangent.smul_eq_zero_of_mem _ b.2] + rw [TensorProduct.smul_tmul', mul_smul, f.mapKer_apply_coe, ← halg, + algebraMap_smul, ← TensorProduct.tmul_smul, h₂, tmul_zero, smul_zero] + +omit [IsScalarTower R S T] in +lemma tensorCotangentInvFun_smul_mk + [alg : Algebra P.Ring Q.Ring] (halg : algebraMap P.Ring Q.Ring = f.toRingHom) + (H : Function.Bijective ((f.mapKer halg).liftBaseChange Q.Ring)) (x : Q.Ring) (y : P.ker) : + tensorCotangentInvFun f halg H (x • .mk ⟨f.toRingHom y, (f.mapKer halg y).2⟩) = + x • 1 ⊗ₜ .mk y := by + letI := ((algebraMap S T).comp (algebraMap P.Ring S)).toAlgebra + haveI : IsScalarTower P.Ring S T := .of_algebraMap_eq' rfl + haveI : IsScalarTower P.Ring Q.Ring T := + .of_algebraMap_eq fun r ↦ halg ▸ (f.algebraMap_toRingHom r).symm + letI e := LinearEquiv.ofBijective _ H + trans tensorCotangentInvFun f halg H (.mk ((f.mapKer halg).liftBaseChange Q.Ring (x ⊗ₜ y))) + · simp; rfl + show ((TensorProduct.mk _ _ _ 1).restrictScalars _ ∘ₗ Cotangent.mk).liftBaseChange _ + (e.symm (e (x ⊗ₜ y))) = _ + rw [e.symm_apply_apply] + simp + +/-- If `J ≃ Q ⊗ₚ I` (e.g. when `T = Q ⊗ₚ S` and `P → Q` is flat), then `T ⊗ₛ I/I² ≃ J/J²`. -/ +noncomputable +def tensorCotangent [alg : Algebra P.Ring Q.Ring] (halg : algebraMap P.Ring Q.Ring = f.toRingHom) + (H : Function.Bijective ((f.mapKer halg).liftBaseChange Q.Ring)) : + T ⊗[S] P.Cotangent ≃ₗ[T] Q.Cotangent := + { __ := (Cotangent.map f).liftBaseChange T + invFun := tensorCotangentInvFun f halg H + left_inv x := by + simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom] + induction x with + | zero => simp only [map_zero] + | add x y _ _ => simp only [map_add, *] + | tmul a b => + obtain ⟨b, rfl⟩ := Cotangent.mk_surjective b + obtain ⟨a, rfl⟩ := Q.algebraMap_surjective a + simp only [LinearMap.liftBaseChange_tmul, Cotangent.map_mk, Hom.toAlgHom_apply, + algebraMap_smul, map_smul] + refine (tensorCotangentInvFun_smul_mk f halg H a b).trans ?_ + simp [algebraMap_eq_smul_one, TensorProduct.smul_tmul'] + right_inv x := by + obtain ⟨x, rfl⟩ := Cotangent.mk_surjective x + obtain ⟨x, rfl⟩ := H.surjective x + simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom] + induction x with + | zero => simp only [map_zero] + | add x y _ _ => simp only [map_add, *] + | tmul a b => + simp only [LinearMap.liftBaseChange_tmul, map_smul] + erw [tensorCotangentInvFun_smul_mk] + simp + rfl } + +/-- If `J ≃ Q ⊗ₚ I`, `S → T` is flat and `P → Q` is formally etale, then `T ⊗ H¹(L_P) ≃ H¹(L_Q)`. -/ +noncomputable +def tensorH1Cotangent [alg : Algebra P.Ring Q.Ring] (halg : algebraMap P.Ring Q.Ring = f.toRingHom) + [Module.Flat S T] + (H₁ : f.toRingHom.FormallyEtale) + (H₂ : Function.Bijective ((f.mapKer halg).liftBaseChange Q.Ring)) : + T ⊗[S] P.H1Cotangent ≃ₗ[T] Q.H1Cotangent := by + refine .ofBijective ((H1Cotangent.map f).liftBaseChange T) ?_ + constructor + · rw [injective_iff_map_eq_zero] + intro x hx + apply Module.Flat.lTensor_preserves_injective_linearMap _ h1Cotangentι_injective + apply (Extension.tensorCotangent f halg H₂).injective + simp only [map_zero] + rw [← h1Cotangentι.map_zero, ← hx] + show ((Cotangent.map f).liftBaseChange T ∘ₗ h1Cotangentι.baseChange T) x = + (h1Cotangentι ∘ₗ _) x + congr 1 + ext x + simp + · intro x + have : Function.Exact (h1Cotangentι.baseChange T) (P.cotangentComplex.baseChange T) := + Module.Flat.lTensor_exact T (LinearMap.exact_subtype_ker_map _) + obtain ⟨a, ha⟩ := (this ((Extension.tensorCotangent f halg H₂).symm x.1)).mp (by + apply (Extension.tensorCotangentSpace f H₁).injective + rw [map_zero, ← x.2] + have : (CotangentSpace.map f).liftBaseChange T ∘ₗ P.cotangentComplex.baseChange T = + Q.cotangentComplex ∘ₗ (Cotangent.map f).liftBaseChange T := by + ext x; obtain ⟨x, rfl⟩ := Cotangent.mk_surjective x; dsimp + simp only [CotangentSpace.map_tmul, + map_one, Hom.toAlgHom_apply, one_smul, cotangentComplex_mk] + exact (DFunLike.congr_fun this _).trans (DFunLike.congr_arg Q.cotangentComplex + ((tensorCotangent f halg H₂).apply_symm_apply x.1))) + refine ⟨a, Subtype.ext (.trans ?_ ((LinearEquiv.eq_symm_apply _).mp ha))⟩ + show (h1Cotangentι ∘ₗ (H1Cotangent.map f).liftBaseChange T) _ = + ((Cotangent.map f).liftBaseChange T ∘ₗ h1Cotangentι.baseChange T) _ + congr 1 + ext; simp + +end Extension + +variable {S} + +/-- let `p` be a submonoid of an `R`-algebra `S`. Then `Sₚ ⊗ H¹(L_{S/R}) ≃ H¹(L_{Sₚ/R})`. -/ +noncomputable +def tensorH1CotangentOfIsLocalization (M : Submonoid S) [IsLocalization M T] : + T ⊗[S] H1Cotangent R S ≃ₗ[T] H1Cotangent R T := by + letI P : Extension R S := (Generators.self R S).toExtension + letI M' := M.comap (algebraMap P.Ring S) + letI fQ : Localization M' →ₐ[R] T := IsLocalization.liftAlgHom (M := M') + (f := (IsScalarTower.toAlgHom R S T).comp (IsScalarTower.toAlgHom R P.Ring S)) (fun ⟨y, hy⟩ ↦ + by simpa using IsLocalization.map_units T ⟨algebraMap P.Ring S y, hy⟩) + letI Q : Extension R T := .ofSurjective fQ (by + intro x + obtain ⟨x, ⟨s, hs⟩, rfl⟩ := IsLocalization.mk'_surjective M x + obtain ⟨x, rfl⟩ := P.algebraMap_surjective x + obtain ⟨s, rfl⟩ := P.algebraMap_surjective s + refine ⟨IsLocalization.mk' _ x ⟨s, show s ∈ M' from hs⟩, ?_⟩ + simp only [fQ, IsLocalization.coe_liftAlgHom, AlgHom.toRingHom_eq_coe] + rw [IsLocalization.lift_mk'_spec] + simp) + letI f : P.Hom Q := + { toRingHom := algebraMap P.Ring (Localization M') + toRingHom_algebraMap x := (IsScalarTower.algebraMap_apply R P.Ring (Localization M') _).symm + algebraMap_toRingHom x := @IsLocalization.lift_eq .. } + haveI : FormallySmooth R P.Ring := inferInstanceAs (FormallySmooth R (MvPolynomial _ _)) + haveI : FormallySmooth P.Ring (Localization M') := .of_isLocalization M' + haveI : FormallySmooth R Q.Ring := .comp R P.Ring (Localization M') + haveI : Module.Flat S T := IsLocalization.flat T M + letI : Algebra P.Ring Q.Ring := inferInstanceAs (Algebra P.Ring (Localization M')) + letI := ((algebraMap S T).comp (algebraMap P.Ring S)).toAlgebra + letI := fQ.toRingHom.toAlgebra + haveI : IsScalarTower P.Ring S T := .of_algebraMap_eq' rfl + haveI : IsScalarTower P.Ring (Localization M') T := + .of_algebraMap_eq fun r ↦ (f.algebraMap_toRingHom r).symm + haveI : IsLocalizedModule M' (IsScalarTower.toAlgHom P.Ring S T).toLinearMap := by + rw [isLocalizedModule_iff_isLocalization] + convert ‹IsLocalization M T› using 1 + exact Submonoid.map_comap_eq_of_surjective P.algebraMap_surjective _ + refine Extension.tensorH1Cotangent f rfl ?_ ?_ ≪≫ₗ Extension.equivH1CotangentOfFormallySmooth _ + · exact RingHom.formallyEtale_algebraMap.mpr + (FormallyEtale.of_isLocalization (M := M') (Rₘ := Localization M')) + · let F : P.ker →ₗ[P.Ring] RingHom.ker fQ := f.mapKer rfl + refine (isLocalizedModule_iff_isBaseChange M' (Localization M') F).mp ?_ + have : (Algebra.linearMap P.Ring S).ker.localized' (Localization M') M' + (Algebra.linearMap P.Ring (Localization M')) = RingHom.ker fQ := by + rw [LinearMap.localized'_ker_eq_ker_localizedMap (Localization M') M' + (Algebra.linearMap P.Ring (Localization M')) + (f' := (IsScalarTower.toAlgHom P.Ring S T).toLinearMap)] + ext x + obtain ⟨x, ⟨s, hs⟩, rfl⟩ := IsLocalization.mk'_surjective M' x + simp only [LinearMap.mem_ker, LinearMap.extendScalarsOfIsLocalization_apply', RingHom.mem_ker, + IsLocalization.coe_liftAlgHom, AlgHom.toRingHom_eq_coe, IsLocalization.lift_mk'_spec, + RingHom.coe_coe, AlgHom.coe_comp, IsScalarTower.coe_toAlgHom', Function.comp_apply, + mul_zero, fQ] + have : IsLocalization.mk' (Localization M') x ⟨s, hs⟩ = + IsLocalizedModule.mk' (Algebra.linearMap P.Ring (Localization M')) x ⟨s, hs⟩ := by + rw [IsLocalization.mk'_eq_iff_eq_mul, mul_comm, ← Algebra.smul_def, ← Submonoid.smul_def, + IsLocalizedModule.mk'_cancel'] + rfl + simp [this, ← IsScalarTower.algebraMap_apply] + have : F = ((LinearEquiv.ofEq _ _ this).restrictScalars P.Ring).toLinearMap ∘ₗ + P.ker.toLocalized' (Localization M') M' (Algebra.linearMap P.Ring (Localization M')) := by + ext; rfl + rw [this] + exact IsLocalizedModule.of_linearEquiv _ _ _ + +lemma tensorH1CotangentOfIsLocalization_toLinearMap + (M : Submonoid S) [IsLocalization M T] : + (tensorH1CotangentOfIsLocalization R T M).toLinearMap = + (Algebra.H1Cotangent.map R R S T).liftBaseChange T := by + ext x : 3 + simp only [AlgebraTensorModule.curry_apply, curry_apply, LinearMap.coe_restrictScalars, + LinearEquiv.coe_coe, LinearMap.liftBaseChange_tmul, one_smul] + simp only [tensorH1CotangentOfIsLocalization, Generators.toExtension_Ring, + Generators.toExtension_commRing, Generators.self_vars, Generators.toExtension_algebra₂, + Generators.self_algebra, AlgHom.toRingHom_eq_coe, Extension.tensorH1Cotangent, + LinearEquiv.ofBijective_apply, LinearMap.liftBaseChange_tmul, one_smul, + Extension.equivH1CotangentOfFormallySmooth, LinearEquiv.trans_apply] + letI P : Extension R S := (Generators.self R S).toExtension + letI M' := M.comap (algebraMap P.Ring S) + letI fQ : Localization M' →ₐ[R] T := IsLocalization.liftAlgHom (M := M') + (f := (IsScalarTower.toAlgHom R S T).comp (IsScalarTower.toAlgHom R P.Ring S)) (fun ⟨y, hy⟩ ↦ + by simpa using IsLocalization.map_units T ⟨algebraMap P.Ring S y, hy⟩) + letI Q : Extension R T := .ofSurjective fQ (by + intro x + obtain ⟨x, ⟨s, hs⟩, rfl⟩ := IsLocalization.mk'_surjective M x + obtain ⟨x, rfl⟩ := P.algebraMap_surjective x + obtain ⟨s, rfl⟩ := P.algebraMap_surjective s + refine ⟨IsLocalization.mk' _ x ⟨s, show s ∈ M' from hs⟩, ?_⟩ + simp only [fQ, IsLocalization.coe_liftAlgHom, AlgHom.toRingHom_eq_coe] + rw [IsLocalization.lift_mk'_spec] + simp) + letI f : (Generators.self R T).toExtension.Hom Q := + { toRingHom := (MvPolynomial.aeval Q.σ).toRingHom + toRingHom_algebraMap := (MvPolynomial.aeval Q.σ).commutes + algebraMap_toRingHom := by + have : (IsScalarTower.toAlgHom R Q.Ring T).comp (MvPolynomial.aeval Q.σ) = + IsScalarTower.toAlgHom _ (Generators.self R T).toExtension.Ring _ := by + ext i + show _ = algebraMap (Generators.self R T).Ring _ (.X i) + simp + exact DFunLike.congr_fun this } + rw [← Extension.H1Cotangent.equivOfFormallySmooth_symm, LinearEquiv.symm_apply_eq, + @Extension.H1Cotangent.equivOfFormallySmooth_apply (f := f), + Algebra.H1Cotangent.map, ← (Extension.H1Cotangent.map f).coe_restrictScalars S, + ← LinearMap.comp_apply, ← Extension.H1Cotangent.map_comp, Extension.H1Cotangent.map_eq] + +instance H1Cotangent.isLocalizedModule (M : Submonoid S) [IsLocalization M T] : + IsLocalizedModule M (Algebra.H1Cotangent.map R R S T) := by + rw [isLocalizedModule_iff_isBaseChange M T] + show Function.Bijective ((Algebra.H1Cotangent.map R R S T).liftBaseChange T) + rw [← tensorH1CotangentOfIsLocalization_toLinearMap R T M] + exact (tensorH1CotangentOfIsLocalization R T M).bijective + +end Algebra diff --git a/Mathlib/RingTheory/Extension.lean b/Mathlib/RingTheory/Extension.lean index b64aada4929d9..019a131967157 100644 --- a/Mathlib/RingTheory/Extension.lean +++ b/Mathlib/RingTheory/Extension.lean @@ -227,6 +227,15 @@ lemma Hom.comp_id (f : Hom P P') : f.comp (Hom.id P) = f := by ext; simp lemma Hom.id_comp (f : Hom P P') : (Hom.id P').comp f = f := by ext; simp [Hom.id, aeval_X_left] +/-- A map between extensions induce a map between kernels. -/ +@[simps] +def Hom.mapKer (f : P.Hom P') + [alg : Algebra P.Ring P'.Ring] (halg : algebraMap P.Ring P'.Ring = f.toRingHom) : + P.ker →ₗ[P.Ring] P'.ker where + toFun x := ⟨f.toRingHom x, by simp [show algebraMap P.Ring S x = 0 from x.2]⟩ + map_add' _ _ := Subtype.ext (map_add _ _ _) + map_smul' := by simp [Algebra.smul_def, ← halg] + end end Hom diff --git a/Mathlib/RingTheory/Smooth/Kaehler.lean b/Mathlib/RingTheory/Smooth/Kaehler.lean index 44d8ef22e6985..e0f903639dfed 100644 --- a/Mathlib/RingTheory/Smooth/Kaehler.lean +++ b/Mathlib/RingTheory/Smooth/Kaehler.lean @@ -561,6 +561,24 @@ def H1Cotangent.equivOfFormallySmooth (P₁ P₂ : Extension R S) H1Cotangent.equiv (Extension.homInfinitesimal _ _) (Extension.homInfinitesimal _ _) ≪≫ₗ .symm (.ofBijective _ (H1Cotangent.map_toInfinitesimal_bijective P₂)) +lemma H1Cotangent.equivOfFormallySmooth_toLinearMap {P₁ P₂ : Extension R S} (f : P₁.Hom P₂) + [FormallySmooth R P₁.Ring] [FormallySmooth R P₂.Ring] : + (H1Cotangent.equivOfFormallySmooth P₁ P₂).toLinearMap = map f := by + ext1 x + refine (LinearEquiv.symm_apply_eq _).mpr ?_ + show ((map (P₁.homInfinitesimal P₂)).restrictScalars S ∘ₗ map P₁.toInfinitesimal) x = + ((map P₂.toInfinitesimal).restrictScalars S ∘ₗ map f) x + rw [← map_comp, ← map_comp, map_eq] + +lemma H1Cotangent.equivOfFormallySmooth_apply {P₁ P₂ : Extension R S} (f : P₁.Hom P₂) + [FormallySmooth R P₁.Ring] [FormallySmooth R P₂.Ring] (x) : + H1Cotangent.equivOfFormallySmooth P₁ P₂ x = map f x := by + rw [← equivOfFormallySmooth_toLinearMap]; rfl + +lemma H1Cotangent.equivOfFormallySmooth_symm (P₁ P₂ : Extension R S) + [FormallySmooth R P₁.Ring] [FormallySmooth R P₂.Ring] : + (equivOfFormallySmooth P₁ P₂).symm = equivOfFormallySmooth P₂ P₁ := rfl + /-- Any formally smooth extension can be used to calculate `H¹(L_{S/R})`. -/ noncomputable def equivH1CotangentOfFormallySmooth (P : Extension R S) [FormallySmooth R P.Ring] : From 049c0a24e48a9ac602ec44f9b0dfde21ece8a230 Mon Sep 17 00:00:00 2001 From: Stefan Kebekus Date: Mon, 20 Jan 2025 11:48:38 +0000 Subject: [PATCH 327/681] feat: add lemmas for working with orders of analytic functions (#20813) Add three simple lemmas to the AnalyticAt namespace, to simplify working with orders of analytic functions. These lemmas are used in [Project VD](https://github.com/kebekus/ProjectVD), which aims to formalize Value Distribution Theory for meromorphic functions on the complex plane. --- Mathlib/Analysis/Analytic/IsolatedZeros.lean | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index 7b5636ce8c665..de1d205483fbb 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -217,6 +217,29 @@ lemma order_eq_nat_iff (hf : AnalyticAt 𝕜 f z₀) (n : ℕ) : hf.order = ↑n refine ⟨fun hn ↦ (WithTop.coe_inj.mp hn : h.choose = n) ▸ h.choose_spec, fun h' ↦ ?_⟩ rw [unique_eventuallyEq_pow_smul_nonzero h.choose_spec h'] +/- An analytic function `f` has finite order at a point `z₀` iff it locally looks + like `(z - z₀) ^ order • g`, where `g` is analytic and does not vanish at + `z₀`. -/ +lemma order_neq_top_iff (hf : AnalyticAt 𝕜 f z₀) : + hf.order ≠ ⊤ ↔ ∃ (g : 𝕜 → E), AnalyticAt 𝕜 g z₀ ∧ g z₀ ≠ 0 + ∧ f =ᶠ[𝓝 z₀] fun z ↦ (z - z₀) ^ (hf.order.toNat) • g z := by + simp only [← ENat.coe_toNat_eq_self, Eq.comm, EventuallyEq, ← hf.order_eq_nat_iff] + +/- An analytic function has order zero at a point iff it does not vanish there. -/ +lemma order_eq_zero_iff (hf : AnalyticAt 𝕜 f z₀) : + hf.order = 0 ↔ f z₀ ≠ 0 := by + rw [← ENat.coe_zero, order_eq_nat_iff hf 0] + constructor + · intro ⟨g, _, _, hg⟩ + simpa [hg.self_of_nhds] + · exact fun hz ↦ ⟨f, hf, hz, by simp⟩ + +/- An analytic function vanishes at a point if its order is nonzero when converted to ℕ. -/ +lemma apply_eq_zero_of_order_toNat_ne_zero (hf : AnalyticAt 𝕜 f z₀) : + hf.order.toNat ≠ 0 → f z₀ = 0 := by + simp [hf.order_eq_zero_iff] + tauto + end AnalyticAt namespace AnalyticOnNhd From edaed4a2258bea3719771efaa48adf6c2e06cf7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Mon, 20 Jan 2025 12:00:54 +0000 Subject: [PATCH 328/681] refactor(RingTheory): split off heavy results from `Mathlib/RingTheory/Spectrum/*/Basic.lean` (#20845) Split off heavy results from `Mathlib/RingTheory/Spectrum/Prime/Basic.lean` and `Mathlib/RingTheory/Spectrum/Maximal/Basic.lean` to be able to import these files where only definitions and basic results are needed. --- Mathlib.lean | 1 + Mathlib/RingTheory/DedekindDomain/Ideal.lean | 2 +- Mathlib/RingTheory/KrullDimension/Basic.lean | 1 + .../RingTheory/Spectrum/Maximal/Basic.lean | 244 +--------------- Mathlib/RingTheory/Spectrum/Maximal/Defs.lean | 2 +- .../Spectrum/Maximal/Localization.lean | 267 ++++++++++++++++++ Mathlib/RingTheory/Spectrum/Prime/Basic.lean | 24 -- .../RingTheory/Spectrum/Prime/Topology.lean | 24 +- 8 files changed, 295 insertions(+), 270 deletions(-) create mode 100644 Mathlib/RingTheory/Spectrum/Maximal/Localization.lean diff --git a/Mathlib.lean b/Mathlib.lean index 13ab333ccad4c..0d2e2c071186b 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4718,6 +4718,7 @@ import Mathlib.RingTheory.Smooth.Pi import Mathlib.RingTheory.Smooth.StandardSmooth import Mathlib.RingTheory.Spectrum.Maximal.Basic import Mathlib.RingTheory.Spectrum.Maximal.Defs +import Mathlib.RingTheory.Spectrum.Maximal.Localization import Mathlib.RingTheory.Spectrum.Maximal.Topology import Mathlib.RingTheory.Spectrum.Prime.Basic import Mathlib.RingTheory.Spectrum.Prime.Defs diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index 68c9890c4641f..d426dd8bc4573 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -5,7 +5,7 @@ Authors: Kenji Nakagawa, Anne Baanen, Filippo A. E. Nuccio -/ import Mathlib.Algebra.Algebra.Subalgebra.Pointwise import Mathlib.Algebra.Polynomial.FieldDivision -import Mathlib.RingTheory.Spectrum.Maximal.Basic +import Mathlib.RingTheory.Spectrum.Maximal.Localization import Mathlib.RingTheory.ChainOfDivisors import Mathlib.RingTheory.DedekindDomain.Basic import Mathlib.RingTheory.FractionalIdeal.Operations diff --git a/Mathlib/RingTheory/KrullDimension/Basic.lean b/Mathlib/RingTheory/KrullDimension/Basic.lean index 2318aef3d4f73..13baff3915c07 100644 --- a/Mathlib/RingTheory/KrullDimension/Basic.lean +++ b/Mathlib/RingTheory/KrullDimension/Basic.lean @@ -5,6 +5,7 @@ Authors: Fangming Li, Jujian Zhang -/ import Mathlib.Algebra.MvPolynomial.CommRing import Mathlib.Algebra.Polynomial.Basic +import Mathlib.RingTheory.Ideal.Quotient.Defs import Mathlib.RingTheory.Spectrum.Prime.Basic import Mathlib.Order.KrullDimension diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean index 608db0b4cbfb6..536e6f256c14d 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean @@ -3,9 +3,8 @@ Copyright (c) 2022 David Kurniadi Angdinata. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Kurniadi Angdinata -/ -import Mathlib.RingTheory.Localization.AsSubring import Mathlib.RingTheory.Spectrum.Maximal.Defs -import Mathlib.RingTheory.Spectrum.Prime.Basic +import Mathlib.RingTheory.Spectrum.Prime.Defs /-! # Maximal spectrum of a commutative (semi)ring @@ -34,245 +33,4 @@ def toPrimeSpectrum (x : MaximalSpectrum R) : PrimeSpectrum R := theorem toPrimeSpectrum_injective : (@toPrimeSpectrum R _).Injective := fun ⟨_, _⟩ ⟨_, _⟩ h => by simpa only [MaximalSpectrum.mk.injEq] using PrimeSpectrum.ext_iff.mp h -open PrimeSpectrum Set - -variable (R : Type*) -variable [CommRing R] [IsDomain R] (K : Type*) [Field K] [Algebra R K] [IsFractionRing R K] - -/-- An integral domain is equal to the intersection of its localizations at all its maximal ideals -viewed as subalgebras of its field of fractions. -/ -theorem iInf_localization_eq_bot : (⨅ v : MaximalSpectrum R, - Localization.subalgebra.ofField K _ v.asIdeal.primeCompl_le_nonZeroDivisors) = ⊥ := by - ext x - rw [Algebra.mem_bot, Algebra.mem_iInf] - constructor - · contrapose - intro hrange hlocal - let denom : Ideal R := (1 : Submodule R K).comap (LinearMap.toSpanSingleton R K x) - have hdenom : (1 : R) ∉ denom := by simpa [denom] using hrange - rcases denom.exists_le_maximal (denom.ne_top_iff_one.mpr hdenom) with ⟨max, hmax, hle⟩ - rcases hlocal ⟨max, hmax⟩ with ⟨n, d, hd, rfl⟩ - exact hd (hle ⟨n, by simp [denom, Algebra.smul_def, mul_left_comm, mul_inv_cancel₀ <| - (map_ne_zero_iff _ <| IsFractionRing.injective R K).mpr fun h ↦ hd (h ▸ max.zero_mem :)]⟩) - · rintro ⟨y, rfl⟩ ⟨v, hv⟩ - exact ⟨y, 1, v.ne_top_iff_one.mp hv.ne_top, by rw [map_one, inv_one, mul_one]⟩ - -end MaximalSpectrum - -namespace PrimeSpectrum - -variable (R : Type*) -variable [CommRing R] [IsDomain R] (K : Type*) [Field K] [Algebra R K] [IsFractionRing R K] - -/-- An integral domain is equal to the intersection of its localizations at all its prime ideals -viewed as subalgebras of its field of fractions. -/ -theorem iInf_localization_eq_bot : ⨅ v : PrimeSpectrum R, - Localization.subalgebra.ofField K _ (v.asIdeal.primeCompl_le_nonZeroDivisors) = ⊥ := by - refine bot_unique (.trans (fun _ ↦ ?_) (MaximalSpectrum.iInf_localization_eq_bot R K).le) - simpa only [Algebra.mem_iInf] using fun hx ⟨v, hv⟩ ↦ hx ⟨v, hv.isPrime⟩ - -end PrimeSpectrum - -namespace MaximalSpectrum - -/-- The product of localizations at all maximal ideals of a commutative semiring. -/ -abbrev PiLocalization : Type _ := Π I : MaximalSpectrum R, Localization.AtPrime I.1 - -/-- The canonical ring homomorphism from a commutative semiring to the product of its -localizations at all maximal ideals. It is always injective. -/ -def toPiLocalization : R →+* PiLocalization R := algebraMap R _ - -theorem toPiLocalization_injective : Function.Injective (toPiLocalization R) := fun r r' eq ↦ by - rw [← one_mul r, ← one_mul r'] - by_contra ne - have ⟨I, mI, hI⟩ := (Module.eqIdeal R r r').exists_le_maximal ((Ideal.ne_top_iff_one _).mpr ne) - have ⟨s, hs⟩ := (IsLocalization.eq_iff_exists I.primeCompl _).mp (congr_fun eq ⟨I, mI⟩) - exact s.2 (hI hs) - -theorem toPiLocalization_apply_apply {r I} : toPiLocalization R r I = algebraMap R _ r := rfl - -variable {R S} (f : R →+* S) (g : S →+* P) (hf : Function.Bijective f) (hg : Function.Bijective g) - -/-- Functoriality of `PiLocalization` but restricted to bijective ring homs. -If R and S are commutative rings, surjectivity would be enough. -/ -noncomputable def mapPiLocalization : PiLocalization R →+* PiLocalization S := - Pi.ringHom fun I ↦ (Localization.localRingHom _ _ f rfl).comp <| - Pi.evalRingHom _ (⟨_, I.2.comap_bijective f hf⟩ : MaximalSpectrum R) - -theorem mapPiLocalization_naturality : - (mapPiLocalization f hf).comp (toPiLocalization R) = - (toPiLocalization S).comp f := by - ext r I - show Localization.localRingHom _ _ _ rfl (algebraMap _ _ r) = algebraMap _ _ (f r) - simp_rw [← IsLocalization.mk'_one (M := (I.1.comap f).primeCompl), Localization.localRingHom_mk', - ← IsLocalization.mk'_one (M := I.1.primeCompl), Submonoid.coe_one, map_one f] - rfl - -theorem mapPiLocalization_id : mapPiLocalization (.id R) Function.bijective_id = .id _ := - RingHom.ext fun _ ↦ funext fun _ ↦ congr($(Localization.localRingHom_id _) _) - -theorem mapPiLocalization_comp : - mapPiLocalization (g.comp f) (hg.comp hf) = - (mapPiLocalization g hg).comp (mapPiLocalization f hf) := - RingHom.ext fun _ ↦ funext fun _ ↦ congr($(Localization.localRingHom_comp _ _ _ _ rfl _ rfl) _) - -theorem mapPiLocalization_bijective : Function.Bijective (mapPiLocalization f hf) := by - let f := RingEquiv.ofBijective f hf - let e := RingEquiv.ofRingHom (mapPiLocalization f hf) - (mapPiLocalization (f.symm : S →+* R) f.symm.bijective) ?_ ?_ - · exact e.bijective - · rw [← mapPiLocalization_comp] - simp_rw [RingEquiv.comp_symm, mapPiLocalization_id] - · rw [← mapPiLocalization_comp] - simp_rw [RingEquiv.symm_comp, mapPiLocalization_id] - -section Pi - -variable {ι} (R : ι → Type*) [∀ i, CommSemiring (R i)] [∀ i, Nontrivial (R i)] - -theorem toPiLocalization_not_surjective_of_infinite [Infinite ι] : - ¬ Function.Surjective (toPiLocalization (Π i, R i)) := fun surj ↦ by - have ⟨J, max, nmem⟩ := PrimeSpectrum.exists_maximal_nmem_range_sigmaToPi_of_infinite R - obtain ⟨r, hr⟩ := surj (Function.update 0 ⟨J, max⟩ 1) - have : r = 0 := funext fun i ↦ toPiLocalization_injective _ <| funext fun I ↦ by - replace hr := congr_fun hr ⟨_, I.2.comap_piEvalRingHom⟩ - dsimp only [toPiLocalization_apply_apply, Subtype.coe_mk] at hr - simp_rw [toPiLocalization_apply_apply, - ← Localization.AtPrime.mapPiEvalRingHom_algebraMap_apply, hr] - rw [Function.update_of_ne]; · simp_rw [Pi.zero_apply, map_zero] - exact fun h ↦ nmem ⟨⟨i, I.1, I.2.isPrime⟩, PrimeSpectrum.ext congr($h.1)⟩ - replace hr := congr_fun hr ⟨J, max⟩ - rw [this, map_zero, Function.update_self] at hr - exact zero_ne_one hr - -variable {R} - -theorem finite_of_toPiLocalization_pi_surjective - (h : Function.Surjective (toPiLocalization (Π i, R i))) : - Finite ι := by - contrapose h; rw [not_finite_iff_infinite] at h - exact toPiLocalization_not_surjective_of_infinite _ - -end Pi - -theorem finite_of_toPiLocalization_surjective - (surj : Function.Surjective (toPiLocalization R)) : - Finite (MaximalSpectrum R) := by - replace surj := mapPiLocalization_bijective _ ⟨toPiLocalization_injective R, surj⟩ - |>.2.comp surj - rw [← RingHom.coe_comp, mapPiLocalization_naturality, RingHom.coe_comp] at surj - exact finite_of_toPiLocalization_pi_surjective surj.of_comp - end MaximalSpectrum - -namespace PrimeSpectrum - -/-- The product of localizations at all prime ideals of a commutative semiring. -/ -abbrev PiLocalization : Type _ := Π p : PrimeSpectrum R, Localization p.asIdeal.primeCompl - -/-- The canonical ring homomorphism from a commutative semiring to the product of its -localizations at all prime ideals. It is always injective. -/ -def toPiLocalization : R →+* PiLocalization R := algebraMap R _ - -theorem toPiLocalization_injective : Function.Injective (toPiLocalization R) := - fun _ _ eq ↦ MaximalSpectrum.toPiLocalization_injective R <| - funext fun I ↦ congr_fun eq I.toPrimeSpectrum - -/-- The projection from the product of localizations at primes to the product of -localizations at maximal ideals. -/ -def piLocalizationToMaximal : PiLocalization R →+* MaximalSpectrum.PiLocalization R := - Pi.ringHom fun I ↦ Pi.evalRingHom _ I.toPrimeSpectrum - -theorem piLocalizationToMaximal_surjective : Function.Surjective (piLocalizationToMaximal R) := - fun r ↦ ⟨fun I ↦ if h : I.1.IsMaximal then r ⟨_, h⟩ else 0, funext fun _ ↦ dif_pos _⟩ - -variable {R} - -/-- If R has Krull dimension ≤ 0, then `piLocalizationToIsMaximal R` is an isomorphism. -/ -def piLocalizationToMaximalEquiv (h : ∀ I : Ideal R, I.IsPrime → I.IsMaximal) : - PiLocalization R ≃+* MaximalSpectrum.PiLocalization R where - __ := piLocalizationToMaximal R - invFun := Pi.ringHom fun I ↦ Pi.evalRingHom _ (⟨_, h _ I.2⟩ : MaximalSpectrum R) - left_inv _ := rfl - right_inv _ := rfl - -theorem piLocalizationToMaximal_bijective (h : ∀ I : Ideal R, I.IsPrime → I.IsMaximal) : - Function.Bijective (piLocalizationToMaximal R) := - (piLocalizationToMaximalEquiv h).bijective - -theorem piLocalizationToMaximal_comp_toPiLocalization : - (piLocalizationToMaximal R).comp (toPiLocalization R) = MaximalSpectrum.toPiLocalization R := - rfl - -variable {S} - -theorem isMaximal_of_toPiLocalization_surjective (surj : Function.Surjective (toPiLocalization R)) - (I : PrimeSpectrum R) : I.1.IsMaximal := by - have ⟨J, max, le⟩ := I.1.exists_le_maximal I.2.ne_top - obtain ⟨r, hr⟩ := surj (Function.update 0 ⟨J, max.isPrime⟩ 1) - by_contra h - have hJ : algebraMap _ _ r = _ := (congr_fun hr _).trans (Function.update_self ..) - have hI : algebraMap _ _ r = _ := congr_fun hr I - rw [← IsLocalization.lift_eq (M := J.primeCompl) (S := Localization J.primeCompl), hJ, map_one, - Function.update_of_ne] at hI - · exact one_ne_zero hI - · intro eq; have : I.1 = J := congr_arg (·.1) eq; exact h (this ▸ max) - · exact fun ⟨s, hs⟩ ↦ IsLocalization.map_units (M := I.1.primeCompl) _ ⟨s, fun h ↦ hs (le h)⟩ - -variable (f : R →+* S) - -/-- A ring homomorphism induces a homomorphism between the products of localizations at primes. -/ -noncomputable def mapPiLocalization : PiLocalization R →+* PiLocalization S := - Pi.ringHom fun I ↦ (Localization.localRingHom _ I.1 f rfl).comp (Pi.evalRingHom _ (f.specComap I)) - -theorem mapPiLocalization_naturality : - (mapPiLocalization f).comp (toPiLocalization R) = (toPiLocalization S).comp f := by - ext r I - show Localization.localRingHom _ _ _ rfl (algebraMap _ _ r) = algebraMap _ _ (f r) - simp_rw [← IsLocalization.mk'_one (M := (I.1.comap f).primeCompl), Localization.localRingHom_mk', - ← IsLocalization.mk'_one (M := I.1.primeCompl), Submonoid.coe_one, map_one f] - rfl - -theorem mapPiLocalization_id : mapPiLocalization (.id R) = .id _ := by - ext; exact congr($(Localization.localRingHom_id _) _) - -theorem mapPiLocalization_comp (g : S →+* P) : - mapPiLocalization (g.comp f) = (mapPiLocalization g).comp (mapPiLocalization f) := by - ext; exact congr($(Localization.localRingHom_comp _ _ _ _ rfl _ rfl) _) - -theorem mapPiLocalization_bijective (hf : Function.Bijective f) : - Function.Bijective (mapPiLocalization f) := by - let f := RingEquiv.ofBijective f hf - let e := RingEquiv.ofRingHom (mapPiLocalization (f : R →+* S)) (mapPiLocalization f.symm) ?_ ?_ - · exact e.bijective - · rw [← mapPiLocalization_comp, RingEquiv.comp_symm, mapPiLocalization_id] - · rw [← mapPiLocalization_comp, RingEquiv.symm_comp, mapPiLocalization_id] - -section Pi - -variable {ι} (R : ι → Type*) [∀ i, CommSemiring (R i)] [∀ i, Nontrivial (R i)] - -theorem toPiLocalization_not_surjective_of_infinite [Infinite ι] : - ¬ Function.Surjective (toPiLocalization (Π i, R i)) := - fun surj ↦ MaximalSpectrum.toPiLocalization_not_surjective_of_infinite R <| by - rw [← piLocalizationToMaximal_comp_toPiLocalization] - exact (piLocalizationToMaximal_surjective _).comp surj - -variable {R} - -theorem finite_of_toPiLocalization_pi_surjective - (h : Function.Surjective (toPiLocalization (Π i, R i))) : - Finite ι := by - contrapose h; rw [not_finite_iff_infinite] at h - exact toPiLocalization_not_surjective_of_infinite _ - -end Pi - -theorem finite_of_toPiLocalization_surjective - (surj : Function.Surjective (toPiLocalization R)) : - Finite (PrimeSpectrum R) := by - replace surj := (mapPiLocalization_bijective _ ⟨toPiLocalization_injective R, surj⟩).2.comp surj - rw [← RingHom.coe_comp, mapPiLocalization_naturality, RingHom.coe_comp] at surj - exact finite_of_toPiLocalization_pi_surjective surj.of_comp - -end PrimeSpectrum diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean b/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean index ab8109fe0112f..0a798a9410e85 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Defs.lean @@ -26,4 +26,4 @@ structure MaximalSpectrum (R : Type*) [CommSemiring R] where @[deprecated (since := "2025-01-16")] alias MaximalSpectrum.IsMaximal := MaximalSpectrum.isMaximal -attribute [instance] MaximalSpectrum.IsMaximal +attribute [instance] MaximalSpectrum.isMaximal diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Localization.lean b/Mathlib/RingTheory/Spectrum/Maximal/Localization.lean new file mode 100644 index 0000000000000..d0723e00ec9b5 --- /dev/null +++ b/Mathlib/RingTheory/Spectrum/Maximal/Localization.lean @@ -0,0 +1,267 @@ +/- +Copyright (c) 2022 David Kurniadi Angdinata. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Kurniadi Angdinata +-/ +import Mathlib.RingTheory.Localization.AsSubring +import Mathlib.RingTheory.Spectrum.Maximal.Basic +import Mathlib.RingTheory.Spectrum.Prime.Basic + +/-! +# Maximal spectrum of a commutative (semi)ring + +Localization results. +-/ + +noncomputable section + +open scoped Classical + +variable (R S P : Type*) [CommSemiring R] [CommSemiring S] [CommSemiring P] + +namespace MaximalSpectrum + +variable {R} + +open PrimeSpectrum Set + +variable (R : Type*) +variable [CommRing R] [IsDomain R] (K : Type*) [Field K] [Algebra R K] [IsFractionRing R K] + +/-- An integral domain is equal to the intersection of its localizations at all its maximal ideals +viewed as subalgebras of its field of fractions. -/ +theorem iInf_localization_eq_bot : (⨅ v : MaximalSpectrum R, + Localization.subalgebra.ofField K _ v.asIdeal.primeCompl_le_nonZeroDivisors) = ⊥ := by + ext x + rw [Algebra.mem_bot, Algebra.mem_iInf] + constructor + · contrapose + intro hrange hlocal + let denom : Ideal R := (1 : Submodule R K).comap (LinearMap.toSpanSingleton R K x) + have hdenom : (1 : R) ∉ denom := by simpa [denom] using hrange + rcases denom.exists_le_maximal (denom.ne_top_iff_one.mpr hdenom) with ⟨max, hmax, hle⟩ + rcases hlocal ⟨max, hmax⟩ with ⟨n, d, hd, rfl⟩ + exact hd (hle ⟨n, by simp [denom, Algebra.smul_def, mul_left_comm, mul_inv_cancel₀ <| + (map_ne_zero_iff _ <| IsFractionRing.injective R K).mpr fun h ↦ hd (h ▸ max.zero_mem :)]⟩) + · rintro ⟨y, rfl⟩ ⟨v, hv⟩ + exact ⟨y, 1, v.ne_top_iff_one.mp hv.ne_top, by rw [map_one, inv_one, mul_one]⟩ + +end MaximalSpectrum + +namespace PrimeSpectrum + +variable (R : Type*) +variable [CommRing R] [IsDomain R] (K : Type*) [Field K] [Algebra R K] [IsFractionRing R K] + +/-- An integral domain is equal to the intersection of its localizations at all its prime ideals +viewed as subalgebras of its field of fractions. -/ +theorem iInf_localization_eq_bot : ⨅ v : PrimeSpectrum R, + Localization.subalgebra.ofField K _ (v.asIdeal.primeCompl_le_nonZeroDivisors) = ⊥ := by + refine bot_unique (.trans (fun _ ↦ ?_) (MaximalSpectrum.iInf_localization_eq_bot R K).le) + simpa only [Algebra.mem_iInf] using fun hx ⟨v, hv⟩ ↦ hx ⟨v, hv.isPrime⟩ + +end PrimeSpectrum + +namespace MaximalSpectrum + +/-- The product of localizations at all maximal ideals of a commutative semiring. -/ +abbrev PiLocalization : Type _ := Π I : MaximalSpectrum R, Localization.AtPrime I.1 + +/-- The canonical ring homomorphism from a commutative semiring to the product of its +localizations at all maximal ideals. It is always injective. -/ +def toPiLocalization : R →+* PiLocalization R := algebraMap R _ + +theorem toPiLocalization_injective : Function.Injective (toPiLocalization R) := fun r r' eq ↦ by + rw [← one_mul r, ← one_mul r'] + by_contra ne + have ⟨I, mI, hI⟩ := (Module.eqIdeal R r r').exists_le_maximal ((Ideal.ne_top_iff_one _).mpr ne) + have ⟨s, hs⟩ := (IsLocalization.eq_iff_exists I.primeCompl _).mp (congr_fun eq ⟨I, mI⟩) + exact s.2 (hI hs) + +theorem toPiLocalization_apply_apply {r I} : toPiLocalization R r I = algebraMap R _ r := rfl + +variable {R S} (f : R →+* S) (g : S →+* P) (hf : Function.Bijective f) (hg : Function.Bijective g) + +/-- Functoriality of `PiLocalization` but restricted to bijective ring homs. +If R and S are commutative rings, surjectivity would be enough. -/ +noncomputable def mapPiLocalization : PiLocalization R →+* PiLocalization S := + Pi.ringHom fun I ↦ (Localization.localRingHom _ _ f rfl).comp <| + Pi.evalRingHom _ (⟨_, I.2.comap_bijective f hf⟩ : MaximalSpectrum R) + +theorem mapPiLocalization_naturality : + (mapPiLocalization f hf).comp (toPiLocalization R) = + (toPiLocalization S).comp f := by + ext r I + show Localization.localRingHom _ _ _ rfl (algebraMap _ _ r) = algebraMap _ _ (f r) + simp_rw [← IsLocalization.mk'_one (M := (I.1.comap f).primeCompl), Localization.localRingHom_mk', + ← IsLocalization.mk'_one (M := I.1.primeCompl), Submonoid.coe_one, map_one f] + rfl + +theorem mapPiLocalization_id : mapPiLocalization (.id R) Function.bijective_id = .id _ := + RingHom.ext fun _ ↦ funext fun _ ↦ congr($(Localization.localRingHom_id _) _) + +theorem mapPiLocalization_comp : + mapPiLocalization (g.comp f) (hg.comp hf) = + (mapPiLocalization g hg).comp (mapPiLocalization f hf) := + RingHom.ext fun _ ↦ funext fun _ ↦ congr($(Localization.localRingHom_comp _ _ _ _ rfl _ rfl) _) + +theorem mapPiLocalization_bijective : Function.Bijective (mapPiLocalization f hf) := by + let f := RingEquiv.ofBijective f hf + let e := RingEquiv.ofRingHom (mapPiLocalization f hf) + (mapPiLocalization (f.symm : S →+* R) f.symm.bijective) ?_ ?_ + · exact e.bijective + · rw [← mapPiLocalization_comp] + simp_rw [RingEquiv.comp_symm, mapPiLocalization_id] + · rw [← mapPiLocalization_comp] + simp_rw [RingEquiv.symm_comp, mapPiLocalization_id] + +section Pi + +variable {ι} (R : ι → Type*) [∀ i, CommSemiring (R i)] [∀ i, Nontrivial (R i)] + +theorem toPiLocalization_not_surjective_of_infinite [Infinite ι] : + ¬ Function.Surjective (toPiLocalization (Π i, R i)) := fun surj ↦ by + have ⟨J, max, nmem⟩ := PrimeSpectrum.exists_maximal_nmem_range_sigmaToPi_of_infinite R + obtain ⟨r, hr⟩ := surj (Function.update 0 ⟨J, max⟩ 1) + have : r = 0 := funext fun i ↦ toPiLocalization_injective _ <| funext fun I ↦ by + replace hr := congr_fun hr ⟨_, I.2.comap_piEvalRingHom⟩ + dsimp only [toPiLocalization_apply_apply, Subtype.coe_mk] at hr + simp_rw [toPiLocalization_apply_apply, + ← Localization.AtPrime.mapPiEvalRingHom_algebraMap_apply, hr] + rw [Function.update_of_ne]; · simp_rw [Pi.zero_apply, map_zero] + exact fun h ↦ nmem ⟨⟨i, I.1, I.2.isPrime⟩, PrimeSpectrum.ext congr($h.1)⟩ + replace hr := congr_fun hr ⟨J, max⟩ + rw [this, map_zero, Function.update_self] at hr + exact zero_ne_one hr + +variable {R} + +theorem finite_of_toPiLocalization_pi_surjective + (h : Function.Surjective (toPiLocalization (Π i, R i))) : + Finite ι := by + contrapose h; rw [not_finite_iff_infinite] at h + exact toPiLocalization_not_surjective_of_infinite _ + +end Pi + +theorem finite_of_toPiLocalization_surjective + (surj : Function.Surjective (toPiLocalization R)) : + Finite (MaximalSpectrum R) := by + replace surj := mapPiLocalization_bijective _ ⟨toPiLocalization_injective R, surj⟩ + |>.2.comp surj + rw [← RingHom.coe_comp, mapPiLocalization_naturality, RingHom.coe_comp] at surj + exact finite_of_toPiLocalization_pi_surjective surj.of_comp + +end MaximalSpectrum + +namespace PrimeSpectrum + +/-- The product of localizations at all prime ideals of a commutative semiring. -/ +abbrev PiLocalization : Type _ := Π p : PrimeSpectrum R, Localization p.asIdeal.primeCompl + +/-- The canonical ring homomorphism from a commutative semiring to the product of its +localizations at all prime ideals. It is always injective. -/ +def toPiLocalization : R →+* PiLocalization R := algebraMap R _ + +theorem toPiLocalization_injective : Function.Injective (toPiLocalization R) := + fun _ _ eq ↦ MaximalSpectrum.toPiLocalization_injective R <| + funext fun I ↦ congr_fun eq I.toPrimeSpectrum + +/-- The projection from the product of localizations at primes to the product of +localizations at maximal ideals. -/ +def piLocalizationToMaximal : PiLocalization R →+* MaximalSpectrum.PiLocalization R := + Pi.ringHom fun I ↦ Pi.evalRingHom _ I.toPrimeSpectrum + +theorem piLocalizationToMaximal_surjective : Function.Surjective (piLocalizationToMaximal R) := + fun r ↦ ⟨fun I ↦ if h : I.1.IsMaximal then r ⟨_, h⟩ else 0, funext fun _ ↦ dif_pos _⟩ + +variable {R} + +/-- If R has Krull dimension ≤ 0, then `piLocalizationToIsMaximal R` is an isomorphism. -/ +def piLocalizationToMaximalEquiv (h : ∀ I : Ideal R, I.IsPrime → I.IsMaximal) : + PiLocalization R ≃+* MaximalSpectrum.PiLocalization R where + __ := piLocalizationToMaximal R + invFun := Pi.ringHom fun I ↦ Pi.evalRingHom _ (⟨_, h _ I.2⟩ : MaximalSpectrum R) + left_inv _ := rfl + right_inv _ := rfl + +theorem piLocalizationToMaximal_bijective (h : ∀ I : Ideal R, I.IsPrime → I.IsMaximal) : + Function.Bijective (piLocalizationToMaximal R) := + (piLocalizationToMaximalEquiv h).bijective + +theorem piLocalizationToMaximal_comp_toPiLocalization : + (piLocalizationToMaximal R).comp (toPiLocalization R) = MaximalSpectrum.toPiLocalization R := + rfl + +variable {S} + +theorem isMaximal_of_toPiLocalization_surjective (surj : Function.Surjective (toPiLocalization R)) + (I : PrimeSpectrum R) : I.1.IsMaximal := by + have ⟨J, max, le⟩ := I.1.exists_le_maximal I.2.ne_top + obtain ⟨r, hr⟩ := surj (Function.update 0 ⟨J, max.isPrime⟩ 1) + by_contra h + have hJ : algebraMap _ _ r = _ := (congr_fun hr _).trans (Function.update_self ..) + have hI : algebraMap _ _ r = _ := congr_fun hr I + rw [← IsLocalization.lift_eq (M := J.primeCompl) (S := Localization J.primeCompl), hJ, map_one, + Function.update_of_ne] at hI + · exact one_ne_zero hI + · intro eq; have : I.1 = J := congr_arg (·.1) eq; exact h (this ▸ max) + · exact fun ⟨s, hs⟩ ↦ IsLocalization.map_units (M := I.1.primeCompl) _ ⟨s, fun h ↦ hs (le h)⟩ + +variable (f : R →+* S) + +/-- A ring homomorphism induces a homomorphism between the products of localizations at primes. -/ +noncomputable def mapPiLocalization : PiLocalization R →+* PiLocalization S := + Pi.ringHom fun I ↦ (Localization.localRingHom _ I.1 f rfl).comp (Pi.evalRingHom _ (f.specComap I)) + +theorem mapPiLocalization_naturality : + (mapPiLocalization f).comp (toPiLocalization R) = (toPiLocalization S).comp f := by + ext r I + show Localization.localRingHom _ _ _ rfl (algebraMap _ _ r) = algebraMap _ _ (f r) + simp_rw [← IsLocalization.mk'_one (M := (I.1.comap f).primeCompl), Localization.localRingHom_mk', + ← IsLocalization.mk'_one (M := I.1.primeCompl), Submonoid.coe_one, map_one f] + rfl + +theorem mapPiLocalization_id : mapPiLocalization (.id R) = .id _ := by + ext; exact congr($(Localization.localRingHom_id _) _) + +theorem mapPiLocalization_comp (g : S →+* P) : + mapPiLocalization (g.comp f) = (mapPiLocalization g).comp (mapPiLocalization f) := by + ext; exact congr($(Localization.localRingHom_comp _ _ _ _ rfl _ rfl) _) + +theorem mapPiLocalization_bijective (hf : Function.Bijective f) : + Function.Bijective (mapPiLocalization f) := by + let f := RingEquiv.ofBijective f hf + let e := RingEquiv.ofRingHom (mapPiLocalization (f : R →+* S)) (mapPiLocalization f.symm) ?_ ?_ + · exact e.bijective + · rw [← mapPiLocalization_comp, RingEquiv.comp_symm, mapPiLocalization_id] + · rw [← mapPiLocalization_comp, RingEquiv.symm_comp, mapPiLocalization_id] + +section Pi + +variable {ι} (R : ι → Type*) [∀ i, CommSemiring (R i)] [∀ i, Nontrivial (R i)] + +theorem toPiLocalization_not_surjective_of_infinite [Infinite ι] : + ¬ Function.Surjective (toPiLocalization (Π i, R i)) := + fun surj ↦ MaximalSpectrum.toPiLocalization_not_surjective_of_infinite R <| by + rw [← piLocalizationToMaximal_comp_toPiLocalization] + exact (piLocalizationToMaximal_surjective _).comp surj + +variable {R} + +theorem finite_of_toPiLocalization_pi_surjective + (h : Function.Surjective (toPiLocalization (Π i, R i))) : + Finite ι := by + contrapose h; rw [not_finite_iff_infinite] at h + exact toPiLocalization_not_surjective_of_infinite _ + +end Pi + +theorem finite_of_toPiLocalization_surjective + (surj : Function.Surjective (toPiLocalization R)) : + Finite (PrimeSpectrum R) := by + replace surj := (mapPiLocalization_bijective _ ⟨toPiLocalization_injective R, surj⟩).2.comp surj + rw [← RingHom.coe_comp, mapPiLocalization_naturality, RingHom.coe_comp] at surj + exact finite_of_toPiLocalization_pi_surjective surj.of_comp + +end PrimeSpectrum diff --git a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean index eb955307cdc44..c789426f03c36 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean @@ -5,7 +5,6 @@ Authors: Johan Commelin, Filippo A. E. Nuccio, Andrew Yang -/ import Mathlib.LinearAlgebra.Finsupp.SumProd import Mathlib.RingTheory.Ideal.Prod -import Mathlib.RingTheory.Localization.Ideal import Mathlib.RingTheory.Nilpotent.Lemmas import Mathlib.RingTheory.Noetherian.Basic import Mathlib.RingTheory.Spectrum.Prime.Defs @@ -549,29 +548,6 @@ def comapEquiv (e : R ≃+* S) : PrimeSpectrum R ≃ PrimeSpectrum S where RingEquiv.toRingHom_eq_coe, RingEquiv.comp_symm] rfl -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 - section Pi variable {ι} (R : ι → Type*) [∀ i, CommSemiring (R i)] diff --git a/Mathlib/RingTheory/Spectrum/Prime/Topology.lean b/Mathlib/RingTheory/Spectrum/Prime/Topology.lean index 36eabf32f2950..818c5fbc7a98f 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Topology.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Topology.lean @@ -10,7 +10,8 @@ import Mathlib.RingTheory.KrullDimension.Basic import Mathlib.RingTheory.LocalRing.ResidueField.Defs import Mathlib.RingTheory.LocalRing.RingHom.Basic import Mathlib.RingTheory.Localization.Away.Basic -import Mathlib.RingTheory.Spectrum.Maximal.Basic +import Mathlib.RingTheory.Localization.Ideal +import Mathlib.RingTheory.Spectrum.Maximal.Localization import Mathlib.Tactic.StacksAttribute import Mathlib.Topology.KrullDimension import Mathlib.Topology.Sober @@ -285,6 +286,27 @@ theorem comap_injective_of_surjective (f : R →+* S) (hf : Function.Surjective 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 [RingHom.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 + theorem localization_comap_isInducing [Algebra R S] (M : Submonoid R) [IsLocalization M S] : IsInducing (comap (algebraMap R S)) := by refine ⟨TopologicalSpace.ext_isClosed fun Z ↦ ?_⟩ From 6313738aeb18ad4aadb1d0c890a4baae06fd8180 Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Mon, 20 Jan 2025 12:14:24 +0000 Subject: [PATCH 329/681] feat(RingTheory/Idempotents): generalize to Semiring, add Corner and direct product decomposition (#20531) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + Add `CompleteOrthogonalIdempotents.iff_ortho_complete`: if a family is complete orthogonal, it consists of idempotents. + Add `CompleteOrthogonalIdempotents.pair_iff'ₛ`: x and y form a complete orthogonal family iff `x * y = y * x = 0` and `x + y = 1`. Golf `pair_iff`. + Given an element `e` in a semigroup R, define `Subsemigroup.corner` = eRe. If R is a non-unital semiring and `e` is an idempotent, then eRe is a semiring. Define `IsIdempotentElem.Corner` as the Type version of `corner`, and provide unital (commutative) (semi)ring instances on it. + `CompleteOrthogonalIdempotents.mulEquivOfIsMulCentral`: A complete orthogonal family of central idempotents in a semiring give rise to a direct product decomposition. There exists `CompleteOrthogonalIdempotents.bijective_pi` but it uses subtraction and quotient so it's not suitable for semirings. --- Mathlib/Algebra/DirectSum/Idempotents.lean | 15 +- Mathlib/RingTheory/Idempotents.lean | 359 ++++++++++++++------- 2 files changed, 250 insertions(+), 124 deletions(-) diff --git a/Mathlib/Algebra/DirectSum/Idempotents.lean b/Mathlib/Algebra/DirectSum/Idempotents.lean index bb76018d54b2c..e4a61553e8176 100644 --- a/Mathlib/Algebra/DirectSum/Idempotents.lean +++ b/Mathlib/Algebra/DirectSum/Idempotents.lean @@ -7,9 +7,9 @@ import Mathlib.RingTheory.Idempotents import Mathlib.Algebra.DirectSum.Decomposition /-! -# Decomposition of the identity of a ring into orthogonal idempotents +# Decomposition of the identity of a semiring into orthogonal idempotents -In this file we show that if a ring `R` can be decomposed into a direct sum +In this file we show that if a semiring `R` can be decomposed into a direct sum of (left) ideals `R = V₁ ⊕ V₂ ⊕ ⬝ ⬝ ⬝ ⊕ Vₙ` then in the corresponding decomposition `1 = e₁ + e₂ + ⬝ ⬝ ⬝ + eₙ` with `eᵢ ∈ Vᵢ`, each `eᵢ` is an idempotent and the `eᵢ`'s form a family of complete orthogonal idempotents. @@ -19,26 +19,25 @@ namespace DirectSum section OrthogonalIdempotents -variable {R I : Type*} [Ring R] [DecidableEq I] (V : I → Ideal R) [Decomposition V] +variable {R I : Type*} [Semiring R] [DecidableEq I] (V : I → Ideal R) [Decomposition V] /-- The decomposition of `(1 : R)` where `1 = e₁ + e₂ + ⬝ ⬝ ⬝ + eₙ` which is induced by - the decomposition of the ring `R = V1 ⊕ V2 ⊕ ⬝ ⬝ ⬝ ⊕ Vn`.-/ + the decomposition of the semiring `R = V1 ⊕ V2 ⊕ ⬝ ⬝ ⬝ ⊕ Vn`.-/ def idempotent (i : I) : R := decompose V 1 i -lemma decompose_eq_mul_idempotent - (x : R) (i : I) : decompose V x i = x * idempotent V i := by +lemma decompose_eq_mul_idempotent (x : R) (i : I) : decompose V x i = x * idempotent V i := by rw [← smul_eq_mul (a := x), idempotent, ← Submodule.coe_smul, ← smul_apply, ← decompose_smul, smul_eq_mul, mul_one] lemma isIdempotentElem_idempotent (i : I) : IsIdempotentElem (idempotent V i : R) := by rw [IsIdempotentElem, ← decompose_eq_mul_idempotent, idempotent, decompose_coe, of_eq_same] -/-- If a ring can be decomposed into direct sum of finite left ideals `Vᵢ` +/-- If a semiring can be decomposed into direct sum of finite left ideals `Vᵢ` where `1 = e₁ + ... + eₙ` and `eᵢ ∈ Vᵢ`, then `eᵢ` is a family of complete orthogonal idempotents.-/ theorem completeOrthogonalIdempotents_idempotent [Fintype I]: - CompleteOrthogonalIdempotents fun i ↦ idempotent V i where + CompleteOrthogonalIdempotents (idempotent V) where idem := isIdempotentElem_idempotent V ortho i j hij := by simp only diff --git a/Mathlib/RingTheory/Idempotents.lean b/Mathlib/RingTheory/Idempotents.lean index c7b091ec93c93..9d42bb3accc80 100644 --- a/Mathlib/RingTheory/Idempotents.lean +++ b/Mathlib/RingTheory/Idempotents.lean @@ -35,74 +35,10 @@ In this file we provide various results regarding idempotent elements in rings. If `R` is commutative, then a family `{ eᵢ }` of complete orthogonal idempotent elements induces a ring isomorphism `R ≃ ∏ R ⧸ ⟨1 - eᵢ⟩`. -/ -section Ring -variable {R S : Type*} [Ring R] [Ring S] (f : R →+* S) - -theorem isIdempotentElem_one_sub_one_sub_pow_pow - (x : R) (n : ℕ) (hx : (x - x ^ 2) ^ n = 0) : - IsIdempotentElem (1 - (1 - x ^ n) ^ n) := by - let P : Polynomial ℤ := 1 - (1 - .X ^ n) ^ n - have : (.X - .X ^ 2) ^ n ∣ P - P ^ 2 := by - have H₁ : .X ^ n ∣ P := by - have := sub_dvd_pow_sub_pow 1 ((1 : Polynomial ℤ) - Polynomial.X ^ n) n - rwa [sub_sub_cancel, one_pow] at this - have H₂ : (1 - .X) ^ n ∣ 1 - P := by - simp only [sub_sub_cancel, P] - simpa using pow_dvd_pow_of_dvd (sub_dvd_pow_sub_pow (α := Polynomial ℤ) 1 Polynomial.X n) n - have := mul_dvd_mul H₁ H₂ - simpa only [← mul_pow, mul_sub, mul_one, ← pow_two] using this - have := map_dvd (Polynomial.aeval x) this - simp only [map_pow, map_sub, Polynomial.aeval_X, hx, map_one, zero_dvd_iff, P] at this - rwa [sub_eq_zero, eq_comm, pow_two] at this - -theorem exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent_aux - (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) - (e₁ : S) (he : e₁ ∈ f.range) (he₁ : IsIdempotentElem e₁) - (e₂ : R) (he₂ : IsIdempotentElem e₂) (he₁e₂ : e₁ * f e₂ = 0) : - ∃ e' : R, IsIdempotentElem e' ∧ f e' = e₁ ∧ e' * e₂ = 0 := by - obtain ⟨e₁, rfl⟩ := he - cases subsingleton_or_nontrivial R - · exact ⟨_, Subsingleton.elim _ _, rfl, Subsingleton.elim _ _⟩ - let a := e₁ - e₁ * e₂ - have ha : f a = f e₁ := by rw [map_sub, map_mul, he₁e₂, sub_zero] - have ha' : a * e₂ = 0 := by rw [sub_mul, mul_assoc, he₂.eq, sub_self] - have hx' : a - a ^ 2 ∈ RingHom.ker f := by - simp [RingHom.mem_ker, mul_sub, pow_two, ha, he₁.eq] - obtain ⟨n, hn⟩ := h _ hx' - refine ⟨_, isIdempotentElem_one_sub_one_sub_pow_pow _ _ hn, ?_, ?_⟩ - · cases' n with n - · simp at hn - simp only [map_sub, map_one, map_pow, ha, he₁.pow_succ_eq, - he₁.one_sub.pow_succ_eq, sub_sub_cancel] - · obtain ⟨k, hk⟩ := (Commute.one_left (MulOpposite.op <| 1 - a ^ n)).sub_dvd_pow_sub_pow n - apply_fun MulOpposite.unop at hk - have : 1 - (1 - a ^ n) ^ n = MulOpposite.unop k * a ^ n := by simpa using hk - rw [this, mul_assoc] - cases' n with n - · simp at hn - rw [pow_succ, mul_assoc, ha', mul_zero, mul_zero] - -/-- Orthogonal idempotents lift along nil ideals. -/ -theorem exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent - (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) - (e₁ : S) (he : e₁ ∈ f.range) (he₁ : IsIdempotentElem e₁) - (e₂ : R) (he₂ : IsIdempotentElem e₂) (he₁e₂ : e₁ * f e₂ = 0) (he₂e₁ : f e₂ * e₁ = 0) : - ∃ e' : R, IsIdempotentElem e' ∧ f e' = e₁ ∧ e' * e₂ = 0 ∧ e₂ * e' = 0 := by - obtain ⟨e', h₁, rfl, h₂⟩ := exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent_aux - f h e₁ he he₁ e₂ he₂ he₁e₂ - refine ⟨(1 - e₂) * e', ?_, ?_, ?_, ?_⟩ - · rw [IsIdempotentElem, mul_assoc, ← mul_assoc e', mul_sub, mul_one, h₂, sub_zero, h₁.eq] - · rw [map_mul, map_sub, map_one, sub_mul, one_mul, he₂e₁, sub_zero] - · rw [mul_assoc, h₂, mul_zero] - · rw [← mul_assoc, mul_sub, mul_one, he₂.eq, sub_self, zero_mul] - -/-- Idempotents lift along nil ideals. -/ -theorem exists_isIdempotentElem_eq_of_ker_isNilpotent (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) - (e : S) (he : e ∈ f.range) (he' : IsIdempotentElem e) : - ∃ e' : R, IsIdempotentElem e' ∧ f e' = e := by - simpa using exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent f h e he he' 0 .zero (by simp) +section Semiring +variable {R S : Type*} [Semiring R] [Semiring S] (f : R →+* S) variable {I : Type*} (e : I → R) /-- A family `{ eᵢ }` of idempotent elements is orthogonal if `eᵢ * eⱼ = 0` for all `i ≠ j`. -/ @@ -176,33 +112,6 @@ lemma OrthogonalIdempotents.option (he : OrthogonalIdempotents e) [Fintype I] (x Finset.sum_ite_eq, Finset.mem_univ, ↓reduceIte, mul_zero] using congr_arg (e i * ·) hx₂ · exact he.ortho (Option.some_inj.ne.mp ne) -lemma OrthogonalIdempotents.lift_of_isNilpotent_ker_aux - (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) - {n} {e : Fin n → S} (he : OrthogonalIdempotents e) (he' : ∀ i, e i ∈ f.range) : - ∃ e' : Fin n → R, OrthogonalIdempotents e' ∧ f ∘ e' = e := by - induction' n with n IH - · refine ⟨0, ⟨finZeroElim, finZeroElim⟩, funext finZeroElim⟩ - · obtain ⟨e', h₁, h₂⟩ := IH (he.embedding (Fin.succEmb n)) (fun i ↦ he' _) - have h₂' (i) : f (e' i) = e i.succ := congr_fun h₂ i - obtain ⟨e₀, h₃, h₄, h₅, h₆⟩ := - exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent f h _ (he' 0) (he.idem 0) _ - h₁.isIdempotentElem_sum - (by simp [Finset.mul_sum, h₂', he.mul_eq, Fin.succ_ne_zero, eq_comm]) - (by simp [Finset.sum_mul, h₂', he.mul_eq, Fin.succ_ne_zero]) - refine ⟨_, (h₁.option _ h₃ h₅ h₆).embedding (finSuccEquiv n).toEmbedding, funext fun i ↦ ?_⟩ - obtain ⟨_ | i, rfl⟩ := (finSuccEquiv n).symm.surjective i <;> simp [*] - -/-- A family of orthogonal idempotents lift along nil ideals. -/ -lemma OrthogonalIdempotents.lift_of_isNilpotent_ker [Finite I] - (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) - {e : I → S} (he : OrthogonalIdempotents e) (he' : ∀ i, e i ∈ f.range) : - ∃ e' : I → R, OrthogonalIdempotents e' ∧ f ∘ e' = e := by - cases nonempty_fintype I - obtain ⟨e', h₁, h₂⟩ := lift_of_isNilpotent_ker_aux f h - (he.embedding (Fintype.equivFin I).symm.toEmbedding) (fun _ ↦ he' _) - refine ⟨_, h₁.embedding (Fintype.equivFin I).toEmbedding, - by ext x; simpa using congr_fun h₂ (Fintype.equivFin I x)⟩ - variable [Fintype I] /-- @@ -214,31 +123,31 @@ A family `{ eᵢ }` of idempotent elements is complete orthogonal if structure CompleteOrthogonalIdempotents (e : I → R) extends OrthogonalIdempotents e : Prop where complete : ∑ i, e i = 1 +/-- If a family is complete orthogonal, it consists of idempotents. -/ +lemma CompleteOrthogonalIdempotents.iff_ortho_complete : + CompleteOrthogonalIdempotents e ↔ Pairwise (e · * e · = 0) ∧ ∑ i, e i = 1 := by + rw [completeOrthogonalIdempotents_iff, orthogonalIdempotents_iff, and_assoc, and_iff_right_of_imp] + intro ⟨ortho, complete⟩ i + apply_fun (e i * ·) at complete + rwa [Finset.mul_sum, Finset.sum_eq_single i (fun _ _ ne ↦ ortho ne.symm) (by simp at ·), mul_one] + at complete + +lemma CompleteOrthogonalIdempotents.pair_iff'ₛ {x y : R} : + CompleteOrthogonalIdempotents ![x, y] ↔ x * y = 0 ∧ y * x = 0 ∧ x + y = 1 := by + simp [iff_ortho_complete, Pairwise, Fin.forall_fin_two, and_assoc] + +lemma CompleteOrthogonalIdempotents.pair_iffₛ {R} [CommSemiring R] {x y : R} : + CompleteOrthogonalIdempotents ![x, y] ↔ x * y = 0 ∧ x + y = 1 := by + rw [pair_iff'ₛ, and_left_comm, and_iff_right_of_imp]; exact (mul_comm x y ▸ ·.1) + lemma CompleteOrthogonalIdempotents.unique_iff [Unique I] : CompleteOrthogonalIdempotents e ↔ e default = 1 := by rw [completeOrthogonalIdempotents_iff, OrthogonalIdempotents.unique, Fintype.sum_unique, and_iff_right_iff_imp] exact (· ▸ IsIdempotentElem.one) -lemma CompleteOrthogonalIdempotents.pair_iff {x y : R} : - CompleteOrthogonalIdempotents ![x, y] ↔ IsIdempotentElem x ∧ y = 1 - x := by - rw [completeOrthogonalIdempotents_iff, orthogonalIdempotents_iff, and_assoc, Pairwise] - simp only [Nat.succ_eq_add_one, Nat.reduceAdd, Fin.forall_fin_two, Fin.isValue, - Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.head_cons, ne_eq, not_true_eq_false, - false_implies, zero_ne_one, not_false_eq_true, true_implies, true_and, one_ne_zero, - and_true, and_self, Fin.sum_univ_two, eq_sub_iff_add_eq, @add_comm _ _ y] - constructor - · exact fun h ↦ ⟨h.1.1, h.2.2⟩ - · rintro ⟨h₁, h₂⟩ - obtain rfl := eq_sub_iff_add_eq'.mpr h₂ - exact ⟨⟨h₁, h₁.one_sub⟩, ⟨by simp [mul_sub, h₁.eq], by simp [sub_mul, h₁.eq]⟩, h₂⟩ - -lemma CompleteOrthogonalIdempotents.of_isIdempotentElem {e : R} (he : IsIdempotentElem e) : - CompleteOrthogonalIdempotents ![e, 1 - e] := - pair_iff.mpr ⟨he, rfl⟩ - lemma CompleteOrthogonalIdempotents.single {I : Type*} [Fintype I] [DecidableEq I] - (R : I → Type*) [∀ i, Ring (R i)] : + (R : I → Type*) [∀ i, Semiring (R i)] : CompleteOrthogonalIdempotents (Pi.single (f := R) · 1) := by refine ⟨⟨by simp [IsIdempotentElem, ← Pi.single_mul], ?_⟩, Finset.univ_sum_single 1⟩ intros i j hij @@ -262,6 +171,122 @@ lemma CompleteOrthogonalIdempotents.equiv {J} [Fintype J] (i : J ≃ I) : simp only [completeOrthogonalIdempotents_iff, OrthogonalIdempotents.equiv, Function.comp_apply, and_congr_right_iff, Fintype.sum_equiv i _ e (fun _ ↦ rfl)] +@[nontriviality] +lemma CompleteOrthogonalIdempotents.of_subsingleton [Subsingleton R] : + CompleteOrthogonalIdempotents e := + ⟨⟨fun _ ↦ Subsingleton.elim _ _, fun _ _ _ ↦ Subsingleton.elim _ _⟩, Subsingleton.elim _ _⟩ + +end Semiring + +section Ring + +variable {R S : Type*} [Ring R] [Ring S] (f : R →+* S) + +theorem isIdempotentElem_one_sub_one_sub_pow_pow + (x : R) (n : ℕ) (hx : (x - x ^ 2) ^ n = 0) : + IsIdempotentElem (1 - (1 - x ^ n) ^ n) := by + let P : Polynomial ℤ := 1 - (1 - .X ^ n) ^ n + have : (.X - .X ^ 2) ^ n ∣ P - P ^ 2 := by + have H₁ : .X ^ n ∣ P := by + have := sub_dvd_pow_sub_pow 1 ((1 : Polynomial ℤ) - Polynomial.X ^ n) n + rwa [sub_sub_cancel, one_pow] at this + have H₂ : (1 - .X) ^ n ∣ 1 - P := by + simp only [sub_sub_cancel, P] + simpa using pow_dvd_pow_of_dvd (sub_dvd_pow_sub_pow (α := Polynomial ℤ) 1 Polynomial.X n) n + have := mul_dvd_mul H₁ H₂ + simpa only [← mul_pow, mul_sub, mul_one, ← pow_two] using this + have := map_dvd (Polynomial.aeval x) this + simp only [map_pow, map_sub, Polynomial.aeval_X, hx, map_one, zero_dvd_iff, P] at this + rwa [sub_eq_zero, eq_comm, pow_two] at this + +theorem exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent_aux + (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) + (e₁ : S) (he : e₁ ∈ f.range) (he₁ : IsIdempotentElem e₁) + (e₂ : R) (he₂ : IsIdempotentElem e₂) (he₁e₂ : e₁ * f e₂ = 0) : + ∃ e' : R, IsIdempotentElem e' ∧ f e' = e₁ ∧ e' * e₂ = 0 := by + obtain ⟨e₁, rfl⟩ := he + cases subsingleton_or_nontrivial R + · exact ⟨_, Subsingleton.elim _ _, rfl, Subsingleton.elim _ _⟩ + let a := e₁ - e₁ * e₂ + have ha : f a = f e₁ := by rw [map_sub, map_mul, he₁e₂, sub_zero] + have ha' : a * e₂ = 0 := by rw [sub_mul, mul_assoc, he₂.eq, sub_self] + have hx' : a - a ^ 2 ∈ RingHom.ker f := by + simp [RingHom.mem_ker, mul_sub, pow_two, ha, he₁.eq] + obtain ⟨n, hn⟩ := h _ hx' + refine ⟨_, isIdempotentElem_one_sub_one_sub_pow_pow _ _ hn, ?_, ?_⟩ + · cases' n with n + · simp at hn + simp only [map_sub, map_one, map_pow, ha, he₁.pow_succ_eq, + he₁.one_sub.pow_succ_eq, sub_sub_cancel] + · obtain ⟨k, hk⟩ := (Commute.one_left (MulOpposite.op <| 1 - a ^ n)).sub_dvd_pow_sub_pow n + apply_fun MulOpposite.unop at hk + have : 1 - (1 - a ^ n) ^ n = MulOpposite.unop k * a ^ n := by simpa using hk + rw [this, mul_assoc] + cases' n with n + · simp at hn + rw [pow_succ, mul_assoc, ha', mul_zero, mul_zero] + +/-- Orthogonal idempotents lift along nil ideals. -/ +theorem exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent + (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) + (e₁ : S) (he : e₁ ∈ f.range) (he₁ : IsIdempotentElem e₁) + (e₂ : R) (he₂ : IsIdempotentElem e₂) (he₁e₂ : e₁ * f e₂ = 0) (he₂e₁ : f e₂ * e₁ = 0) : + ∃ e' : R, IsIdempotentElem e' ∧ f e' = e₁ ∧ e' * e₂ = 0 ∧ e₂ * e' = 0 := by + obtain ⟨e', h₁, rfl, h₂⟩ := exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent_aux + f h e₁ he he₁ e₂ he₂ he₁e₂ + refine ⟨(1 - e₂) * e', ?_, ?_, ?_, ?_⟩ + · rw [IsIdempotentElem, mul_assoc, ← mul_assoc e', mul_sub, mul_one, h₂, sub_zero, h₁.eq] + · rw [map_mul, map_sub, map_one, sub_mul, one_mul, he₂e₁, sub_zero] + · rw [mul_assoc, h₂, mul_zero] + · rw [← mul_assoc, mul_sub, mul_one, he₂.eq, sub_self, zero_mul] + +/-- Idempotents lift along nil ideals. -/ +theorem exists_isIdempotentElem_eq_of_ker_isNilpotent (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) + (e : S) (he : e ∈ f.range) (he' : IsIdempotentElem e) : + ∃ e' : R, IsIdempotentElem e' ∧ f e' = e := by + simpa using exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent f h e he he' 0 .zero (by simp) + +lemma OrthogonalIdempotents.lift_of_isNilpotent_ker_aux + (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) + {n} {e : Fin n → S} (he : OrthogonalIdempotents e) (he' : ∀ i, e i ∈ f.range) : + ∃ e' : Fin n → R, OrthogonalIdempotents e' ∧ f ∘ e' = e := by + induction' n with n IH + · refine ⟨0, ⟨finZeroElim, finZeroElim⟩, funext finZeroElim⟩ + · obtain ⟨e', h₁, h₂⟩ := IH (he.embedding (Fin.succEmb n)) (fun i ↦ he' _) + have h₂' (i) : f (e' i) = e i.succ := congr_fun h₂ i + obtain ⟨e₀, h₃, h₄, h₅, h₆⟩ := + exists_isIdempotentElem_mul_eq_zero_of_ker_isNilpotent f h _ (he' 0) (he.idem 0) _ + h₁.isIdempotentElem_sum + (by simp [Finset.mul_sum, h₂', he.mul_eq, Fin.succ_ne_zero, eq_comm]) + (by simp [Finset.sum_mul, h₂', he.mul_eq, Fin.succ_ne_zero]) + refine ⟨_, (h₁.option _ h₃ h₅ h₆).embedding (finSuccEquiv n).toEmbedding, funext fun i ↦ ?_⟩ + obtain ⟨_ | i, rfl⟩ := (finSuccEquiv n).symm.surjective i <;> simp [*] + +variable {I : Type*} {e : I → R} + +/-- A family of orthogonal idempotents lift along nil ideals. -/ +lemma OrthogonalIdempotents.lift_of_isNilpotent_ker [Finite I] + (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) + {e : I → S} (he : OrthogonalIdempotents e) (he' : ∀ i, e i ∈ f.range) : + ∃ e' : I → R, OrthogonalIdempotents e' ∧ f ∘ e' = e := by + cases nonempty_fintype I + obtain ⟨e', h₁, h₂⟩ := lift_of_isNilpotent_ker_aux f h + (he.embedding (Fintype.equivFin I).symm.toEmbedding) (fun _ ↦ he' _) + refine ⟨_, h₁.embedding (Fintype.equivFin I).toEmbedding, + by ext x; simpa using congr_fun h₂ (Fintype.equivFin I x)⟩ + +lemma CompleteOrthogonalIdempotents.pair_iff {x y : R} : + CompleteOrthogonalIdempotents ![x, y] ↔ IsIdempotentElem x ∧ y = 1 - x := by + rw [pair_iff'ₛ, ← eq_sub_iff_add_eq', ← and_assoc, and_congr_left_iff] + rintro rfl + simp [mul_sub, sub_mul, IsIdempotentElem, sub_eq_zero, eq_comm] + +lemma CompleteOrthogonalIdempotents.of_isIdempotentElem {e : R} (he : IsIdempotentElem e) : + CompleteOrthogonalIdempotents ![e, 1 - e] := + pair_iff.mpr ⟨he, rfl⟩ + +variable [Fintype I] + lemma CompleteOrthogonalIdempotents.option (he : OrthogonalIdempotents e) : CompleteOrthogonalIdempotents (Option.elim · (1 - ∑ i, e i) e) where __ := he.option _ he.isIdempotentElem_sum.one_sub @@ -270,11 +295,6 @@ lemma CompleteOrthogonalIdempotents.option (he : OrthogonalIdempotents e) : rw [Fintype.sum_option] exact sub_add_cancel _ _ -@[nontriviality] -lemma CompleteOrthogonalIdempotents.of_subsingleton [Subsingleton R] : - CompleteOrthogonalIdempotents e := - ⟨⟨fun _ ↦ Subsingleton.elim _ _, fun _ _ _ ↦ Subsingleton.elim _ _⟩, Subsingleton.elim _ _⟩ - lemma CompleteOrthogonalIdempotents.lift_of_isNilpotent_ker_aux (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) {n} {e : Fin n → S} (he : CompleteOrthogonalIdempotents e) (he' : ∀ i, e i ∈ f.range) : @@ -426,3 +446,110 @@ lemma bijective_pi_of_isIdempotentElem (e : I → R) ⟨fun i ↦ (he i).one_sub, he₁⟩ (by simpa using he₂)).bijective_pi' end CommRing + +section corner + +variable {R : Type*} (e : R) + +namespace Subsemigroup + +variable [Semigroup R] + +/-- The corner associated to an element `e` in a semigroup +is the subsemigroup of all elements of the form `e * r * e`. -/ +def corner : Subsemigroup R where + carrier := Set.range (e * · * e) + mul_mem' := by rintro _ _ ⟨a, rfl⟩ ⟨b, rfl⟩; exact ⟨a * e * e * b, by simp_rw [mul_assoc]⟩ + +variable {e} (idem : IsIdempotentElem e) +include idem + +lemma mem_corner_iff {r : R} : r ∈ corner e ↔ e * r = r ∧ r * e = r := + ⟨by rintro ⟨r, rfl⟩; simp_rw [← mul_assoc, idem.eq, mul_assoc, idem.eq, true_and], + (⟨r, by simp_rw [·]⟩)⟩ + +lemma mem_corner_iff_mul_left (hc : IsMulCentral e) {r : R} : r ∈ corner e ↔ e * r = r := by + rw [mem_corner_iff idem, and_iff_left_of_imp]; intro; rwa [← hc.comm] + +lemma mem_corner_iff_mul_right (hc : IsMulCentral e) {r : R} : r ∈ corner e ↔ r * e = r := by + rw [mem_corner_iff_mul_left idem hc, hc.comm] + +lemma mem_corner_iff_mem_range_mul_left (hc : IsMulCentral e) {r : R} : + r ∈ corner e ↔ r ∈ Set.range (e * ·) := by + simp_rw [corner, mem_mk, Set.mem_range, ← hc.comm, ← mul_assoc, idem.eq] + +lemma mem_corner_iff_mem_range_mul_right (hc : IsMulCentral e) {r : R} : + r ∈ corner e ↔ r ∈ Set.range (· * e) := by + simp_rw [mem_corner_iff_mem_range_mul_left idem hc, hc.comm] + +/-- The corner associated to an idempotent `e` in a semiring without 1 +is the semiring with `e` as 1 consisting of all element of the form `e * r * e`. -/ +@[nolint unusedArguments] +def _root_.IsIdempotentElem.Corner (_ : IsIdempotentElem e) : Type _ := Subsemigroup.corner e + +end Subsemigroup + +/-- The corner associated to an element `e` in a semiring without 1 +is the subsemiring without 1 of all elements of the form `e * r * e`. -/ +def NonUnitalSubsemiring.corner [NonUnitalSemiring R] : NonUnitalSubsemiring R where + __ := Subsemigroup.corner e + add_mem' := by rintro _ _ ⟨a, rfl⟩ ⟨b, rfl⟩; exact ⟨a + b, by simp_rw [mul_add, add_mul]⟩ + zero_mem' := ⟨0, by simp_rw [mul_zero, zero_mul]⟩ + +/-- The corner associated to an element `e` in a ring without ` +is the subring without 1 of all elements of the form `e * r * e`. -/ +def NonUnitalRing.corner [NonUnitalRing R] : NonUnitalSubring R where + __ := NonUnitalSubsemiring.corner e + neg_mem' := by rintro _ ⟨a, rfl⟩; exact ⟨-a, by simp_rw [mul_neg, neg_mul]⟩ + +instance [NonUnitalSemiring R] (idem : IsIdempotentElem e) : Semiring idem.Corner where + __ : NonUnitalSemiring (NonUnitalSubsemiring.corner e) := inferInstance + one := ⟨e, e, by simp_rw [idem.eq]⟩ + one_mul r := Subtype.ext ((Subsemigroup.mem_corner_iff idem).mp r.2).1 + mul_one r := Subtype.ext ((Subsemigroup.mem_corner_iff idem).mp r.2).2 + +instance [NonUnitalCommSemiring R] (idem : IsIdempotentElem e) : CommSemiring idem.Corner where + __ : NonUnitalCommSemiring (NonUnitalSubsemiring.corner e) := inferInstance + __ : Semiring idem.Corner := inferInstance + +instance [NonUnitalRing R] (idem : IsIdempotentElem e) : Ring idem.Corner where + __ : NonUnitalRing (NonUnitalRing.corner e) := inferInstance + __ : Semiring idem.Corner := inferInstance + +instance [NonUnitalCommRing R] (idem : IsIdempotentElem e) : CommRing idem.Corner where + __ : NonUnitalCommRing (NonUnitalRing.corner e) := inferInstance + __ : Semiring idem.Corner := inferInstance + +variable {I : Type*} [Fintype I] {e : I → R} + +/-- A complete orthogonal family of central idempotents in a semiring +give rise to a direct product decomposition. -/ +def CompleteOrthogonalIdempotents.mulEquivOfIsMulCentral [Semiring R] + (he : CompleteOrthogonalIdempotents e) (hc : ∀ i, IsMulCentral (e i)) : + R ≃+* Π i, (he.idem i).Corner where + toFun r i := ⟨_, r, rfl⟩ + invFun r := ∑ i, (r i).1 + left_inv r := by + simp_rw [(hc _).comm, mul_assoc, (he.idem _).eq, ← Finset.mul_sum, he.complete, mul_one] + right_inv r := funext fun i ↦ Subtype.ext <| by + simp_rw [Finset.mul_sum, Finset.sum_mul] + rw [Finset.sum_eq_single i _ (by simp at ·)] + · have ⟨r', eq⟩ := (r i).2 + rw [← eq]; simp_rw [← mul_assoc, (he.idem i).eq, mul_assoc, (he.idem i).eq] + · intro j _ ne; have ⟨r', eq⟩ := (r j).2 + rw [← eq]; simp_rw [← mul_assoc, he.ortho ne.symm, zero_mul] + map_mul' r₁ r₂ := funext fun i ↦ Subtype.ext <| + calc e i * (r₁ * r₂) * e i + _ = e i * (r₁ * e i * r₂) * e i := by simp_rw [← (hc i).comm r₁, ← mul_assoc, (he.idem i).eq] + _ = e i * r₁ * e i * (e i * r₂ * e i) := by + conv in (r₁ * _ * r₂) => rw [← (he.idem i).eq] + simp_rw [mul_assoc] + map_add' r₁ r₂ := funext fun i ↦ Subtype.ext <| by simpa [mul_add] using add_mul .. + +/-- A complete orthogonal family of idempotents in a commutative semiring +give rise to a direct product decomposition. -/ +def CompleteOrthogonalIdempotents.mulEquivOfComm [CommSemiring R] + (he : CompleteOrthogonalIdempotents e) : R ≃+* Π i, (he.idem i).Corner := + he.mulEquivOfIsMulCentral fun _ ↦ Semigroup.mem_center_iff.mpr fun _ ↦ mul_comm .. + +end corner From b73345245881a2456b80e6050b0815f40940318d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 20 Jan 2025 13:12:26 +0000 Subject: [PATCH 330/681] feat(CategoryTheory): localization of trifunctors (#20788) In this PR, we study the localization of functors in three variables (similarly as #19894 was the case of functors in two variables). This shall be used in #12728 in order to obtain a monoidal structure on certain localized categories. --- Mathlib.lean | 1 + .../Localization/Trifunctor.lean | 225 ++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 Mathlib/CategoryTheory/Localization/Trifunctor.lean diff --git a/Mathlib.lean b/Mathlib.lean index 0d2e2c071186b..407bb7a2cd533 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2022,6 +2022,7 @@ import Mathlib.CategoryTheory.Localization.SmallHom import Mathlib.CategoryTheory.Localization.SmallShiftedHom import Mathlib.CategoryTheory.Localization.StructuredArrow import Mathlib.CategoryTheory.Localization.Triangulated +import Mathlib.CategoryTheory.Localization.Trifunctor import Mathlib.CategoryTheory.Monad.Adjunction import Mathlib.CategoryTheory.Monad.Algebra import Mathlib.CategoryTheory.Monad.Basic diff --git a/Mathlib/CategoryTheory/Localization/Trifunctor.lean b/Mathlib/CategoryTheory/Localization/Trifunctor.lean new file mode 100644 index 0000000000000..782b08c753808 --- /dev/null +++ b/Mathlib/CategoryTheory/Localization/Trifunctor.lean @@ -0,0 +1,225 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Localization.Bifunctor +import Mathlib.CategoryTheory.Functor.CurryingThree +import Mathlib.CategoryTheory.Products.Associator + +/-! +# Lifting of trifunctors + +In this file, in the context of the localization of categories, we extend the notion +of lifting of functors to the case of trifunctors +(see also the file `Localization.Bifunctor` for the case of bifunctors). +The main result in this file is that we can localize "associator" isomorphisms +(see the definition `Localization.associator`). + +-/ + +namespace CategoryTheory + +variable {C₁ C₂ C₃ C₁₂ C₂₃ D₁ D₂ D₃ D₁₂ D₂₃ C D E : Type*} + [Category C₁] [Category C₂] [Category C₃] [Category D₁] [Category D₂] [Category D₃] + [Category C₁₂] [Category C₂₃] [Category D₁₂] [Category D₂₃] + [Category C] [Category D] [Category E] + +namespace MorphismProperty + +/-- Classes of morphisms `W₁ : MorphismProperty C₁`, `W₂ : MorphismProperty C₂` and +`W₃ : MorphismProperty C₃` are said to be inverted by `F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E` if +`W₁.prod (W₂.prod W₃)` is inverted by the +functor `currying₃.functor.obj F : C₁ × C₂ × C₃ ⥤ E`. -/ +def IsInvertedBy₃ (W₁ : MorphismProperty C₁) (W₂ : MorphismProperty C₂) + (W₃ : MorphismProperty C₃) (F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E) : Prop := + (W₁.prod (W₂.prod W₃)).IsInvertedBy (currying₃.functor.obj F) + +end MorphismProperty + +namespace Localization + +section + +variable (L₁ : C₁ ⥤ D₁) (L₂ : C₂ ⥤ D₂) (L₃ : C₃ ⥤ D₃) + +/-- Given functors `L₁ : C₁ ⥤ D₁`, `L₂ : C₂ ⥤ D₂`, `L₃ : C₃ ⥤ D₃`, +morphisms properties `W₁` on `C₁`, `W₂` on `C₂`, `W₃` on `C₃`, and +functors `F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E` and `F' : D₁ ⥤ D₂ ⥤ D₃ ⥤ E`, we say +`Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F F'` holds if `F` is induced by `F'`, up to an isomorphism. -/ +class Lifting₃ (W₁ : MorphismProperty C₁) (W₂ : MorphismProperty C₂) + (W₃ : MorphismProperty C₃) + (F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E) (F' : D₁ ⥤ D₂ ⥤ D₃ ⥤ E) where + /-- the isomorphism `((((whiskeringLeft₃ E).obj L₁).obj L₂).obj L₃).obj F' ≅ F` expressing + that `F` is induced by `F'` up to an isomorphism -/ + iso' : ((((whiskeringLeft₃ E).obj L₁).obj L₂).obj L₃).obj F' ≅ F + +variable (W₁ : MorphismProperty C₁) (W₂ : MorphismProperty C₂) (W₃ : MorphismProperty C₃) + (F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E) (F' : D₁ ⥤ D₂ ⥤ D₃ ⥤ E) [Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F F'] + +/-- The isomorphism `((((whiskeringLeft₃ E).obj L₁).obj L₂).obj L₃).obj F' ≅ F` +when `Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F F'` holds. -/ +noncomputable def Lifting₃.iso : + ((((whiskeringLeft₃ E).obj L₁).obj L₂).obj L₃).obj F' ≅ F := + Lifting₃.iso' W₁ W₂ W₃ + +variable (F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E) (F' : D₁ ⥤ D₂ ⥤ D₃ ⥤ E) + +noncomputable instance Lifting₃.uncurry [Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F F'] : + Lifting (L₁.prod (L₂.prod L₃)) (W₁.prod (W₂.prod W₃)) + (uncurry₃.obj F) (uncurry₃.obj F') where + iso' := uncurry₃.mapIso (Lifting₃.iso L₁ L₂ L₃ W₁ W₂ W₃ F F') + +end + +section + +variable (F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E) {W₁ : MorphismProperty C₁} {W₂ : MorphismProperty C₂} + {W₃ : MorphismProperty C₃} + (hF : MorphismProperty.IsInvertedBy₃ W₁ W₂ W₃ F) + (L₁ : C₁ ⥤ D₁) (L₂ : C₂ ⥤ D₂) (L₃ : C₃ ⥤ D₃) + [L₁.IsLocalization W₁] [L₂.IsLocalization W₂] [L₃.IsLocalization W₃] + [W₁.ContainsIdentities] [W₂.ContainsIdentities] [W₃.ContainsIdentities] + +/-- Given localization functor `L₁ : C₁ ⥤ D₁`, `L₂ : C₂ ⥤ D₂` and `L₃ : C₃ ⥤ D₃` +with respect to `W₁ : MorphismProperty C₁`, `W₂ : MorphismProperty C₂` and +`W₃ : MorphismProperty C₃` respectively, and a trifunctor `F : C₁ ⥤ C₂ ⥤ C₃ ⥤ E` +which inverts `W₁`, `W₂` and `W₃`, this is the induced localized +trifunctor `D₁ ⥤ D₂ ⥤ D₃ ⥤ E`. -/ +noncomputable def lift₃ : D₁ ⥤ D₂ ⥤ D₃ ⥤ E := + curry₃.obj (lift (uncurry₃.obj F) hF (L₁.prod (L₂.prod L₃))) + +noncomputable instance : Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F (lift₃ F hF L₁ L₂ L₃) where + iso' := + (curry₃ObjProdComp L₁ L₂ L₃ _).symm ≪≫ + curry₃.mapIso (fac (uncurry₃.obj F) hF (L₁.prod (L₂.prod L₃))) ≪≫ + currying₃.unitIso.symm.app F + +end + +section + +variable (L₁ : C₁ ⥤ D₁) (L₂ : C₂ ⥤ D₂) (L₃ : C₃ ⥤ D₃) + (W₁ : MorphismProperty C₁) (W₂ : MorphismProperty C₂) (W₃ : MorphismProperty C₃) + [L₁.IsLocalization W₁] [L₂.IsLocalization W₂] [L₃.IsLocalization W₃] + [W₁.ContainsIdentities] [W₂.ContainsIdentities] [W₃.ContainsIdentities] + (F₁ F₂ : C₁ ⥤ C₂ ⥤ C₃ ⥤ E) (F₁' F₂' : D₁ ⥤ D₂ ⥤ D₃ ⥤ E) + [Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F₁ F₁'] [Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F₂ F₂'] (τ : F₁ ⟶ F₂) + (e : F₁ ≅ F₂) + +/-- The natural transformation `F₁' ⟶ F₂'` of trifunctors induced by a +natural transformation `τ : F₁ ⟶ F₂` when `Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F₁ F₁'` +and `Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F₂ F₂'` hold. -/ +noncomputable def lift₃NatTrans : F₁' ⟶ F₂' := + fullyFaithfulUncurry₃.preimage + (liftNatTrans (L₁.prod (L₂.prod L₃)) (W₁.prod (W₂.prod W₃)) (uncurry₃.obj F₁) + (uncurry₃.obj F₂) (uncurry₃.obj F₁') (uncurry₃.obj F₂') (uncurry₃.map τ)) + +@[simp] +theorem lift₃NatTrans_app_app_app (X₁ : C₁) (X₂ : C₂) (X₃ : C₃) : + (((lift₃NatTrans L₁ L₂ L₃ W₁ W₂ W₃ F₁ F₂ F₁' F₂' τ).app + (L₁.obj X₁)).app (L₂.obj X₂)).app (L₃.obj X₃) = + (((Lifting₃.iso L₁ L₂ L₃ W₁ W₂ W₃ F₁ F₁').hom.app X₁).app X₂).app X₃ ≫ + ((τ.app X₁).app X₂).app X₃ ≫ + (((Lifting₃.iso L₁ L₂ L₃ W₁ W₂ W₃ F₂ F₂').inv.app X₁).app X₂).app X₃ := by + dsimp [lift₃NatTrans, fullyFaithfulUncurry₃, Equivalence.fullyFaithfulFunctor] + simp only [currying₃_unitIso_hom_app_app_app_app, Functor.id_obj, + currying₃_unitIso_inv_app_app_app_app, Functor.comp_obj, + Category.comp_id, Category.id_comp] + exact liftNatTrans_app _ _ _ _ (uncurry₃.obj F₁') (uncurry₃.obj F₂') (uncurry₃.map τ) ⟨X₁, X₂, X₃⟩ + +variable {F₁' F₂'} in +include W₁ W₂ W₃ in +theorem natTrans₃_ext {τ τ' : F₁' ⟶ F₂'} + (h : ∀ (X₁ : C₁) (X₂ : C₂) (X₃ : C₃), ((τ.app (L₁.obj X₁)).app (L₂.obj X₂)).app (L₃.obj X₃) = + ((τ'.app (L₁.obj X₁)).app (L₂.obj X₂)).app (L₃.obj X₃)) : τ = τ' := + uncurry₃.map_injective (natTrans_ext (L₁.prod (L₂.prod L₃)) (W₁.prod (W₂.prod W₃)) + (fun _ ↦ h _ _ _)) + +/-- The natural isomorphism `F₁' ≅ F₂'` of trifunctors induced by a +natural isomorphism `e : F₁ ≅ F₂` when `Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F₁ F₁'` +and `Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ F₂ F₂'` hold. -/ +@[simps] +noncomputable def lift₃NatIso : F₁' ≅ F₂' where + hom := lift₃NatTrans L₁ L₂ L₃ W₁ W₂ W₃ F₁ F₂ F₁' F₂' e.hom + inv := lift₃NatTrans L₁ L₂ L₃ W₁ W₂ W₃ F₂ F₁ F₂' F₁' e.inv + hom_inv_id := natTrans₃_ext L₁ L₂ L₃ W₁ W₂ W₃ (by aesop_cat) + inv_hom_id := natTrans₃_ext L₁ L₂ L₃ W₁ W₂ W₃ (by aesop_cat) + +end + +section + +variable + (L₁ : C₁ ⥤ D₁) (L₂ : C₂ ⥤ D₂) (L₃ : C₃ ⥤ D₃) (L₁₂ : C₁₂ ⥤ D₁₂) (L₂₃ : C₂₃ ⥤ D₂₃) (L : C ⥤ D) + (W₁ : MorphismProperty C₁) (W₂ : MorphismProperty C₂) (W₃ : MorphismProperty C₃) + (W₁₂ : MorphismProperty C₁₂) (W₂₃ : MorphismProperty C₂₃) (W : MorphismProperty C) + [W₁.ContainsIdentities] [W₂.ContainsIdentities] [W₃.ContainsIdentities] + [L₁.IsLocalization W₁] [L₂.IsLocalization W₂] [L₃.IsLocalization W₃] [L.IsLocalization W] + (F₁₂ : C₁ ⥤ C₂ ⥤ C₁₂) (G : C₁₂ ⥤ C₃ ⥤ C) + (F : C₁ ⥤ C₂₃ ⥤ C) (G₂₃ : C₂ ⥤ C₃ ⥤ C₂₃) + (iso : bifunctorComp₁₂ F₁₂ G ≅ bifunctorComp₂₃ F G₂₃) + (F₁₂' : D₁ ⥤ D₂ ⥤ D₁₂) (G' : D₁₂ ⥤ D₃ ⥤ D) + (F' : D₁ ⥤ D₂₃ ⥤ D) (G₂₃' : D₂ ⥤ D₃ ⥤ D₂₃) + [Lifting₂ L₁ L₂ W₁ W₂ (F₁₂ ⋙ (whiskeringRight _ _ _).obj L₁₂) F₁₂'] + [Lifting₂ L₁₂ L₃ W₁₂ W₃ (G ⋙ (whiskeringRight _ _ _).obj L) G'] + [Lifting₂ L₁ L₂₃ W₁ W₂₃ (F ⋙ (whiskeringRight _ _ _).obj L) F'] + [Lifting₂ L₂ L₃ W₂ W₃ (G₂₃ ⋙ (whiskeringRight _ _ _).obj L₂₃) G₂₃'] + +/-- The construction `bifunctorComp₁₂` of a trifunctor by composition of bifunctors +is compatible with localization. -/ +noncomputable def Lifting₃.bifunctorComp₁₂ : + Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ + ((Functor.postcompose₃.obj L).obj (bifunctorComp₁₂ F₁₂ G)) + (bifunctorComp₁₂ F₁₂' G') where + iso' := + ((whiskeringRight C₁ _ _).obj + ((whiskeringRight C₂ _ _).obj ((whiskeringLeft _ _ D).obj L₃))).mapIso + ((bifunctorComp₁₂Functor.mapIso + (Lifting₂.iso L₁ L₂ W₁ W₂ (F₁₂ ⋙ (whiskeringRight _ _ _).obj L₁₂) F₁₂')).app G') ≪≫ + (bifunctorComp₁₂Functor.obj F₁₂).mapIso + (Lifting₂.iso L₁₂ L₃ W₁₂ W₃ (G ⋙ (whiskeringRight _ _ _).obj L) G') + +/-- The construction `bifunctorComp₂₃` of a trifunctor by composition of bifunctors +is compatible with localization. -/ +noncomputable def Lifting₃.bifunctorComp₂₃ : + Lifting₃ L₁ L₂ L₃ W₁ W₂ W₃ + ((Functor.postcompose₃.obj L).obj (bifunctorComp₂₃ F G₂₃)) + (bifunctorComp₂₃ F' G₂₃') where + iso' := + ((whiskeringLeft _ _ _).obj L₁).mapIso ((bifunctorComp₂₃Functor.obj F').mapIso + (Lifting₂.iso L₂ L₃ W₂ W₃ (G₂₃ ⋙ (whiskeringRight _ _ _).obj L₂₃) G₂₃')) ≪≫ + (bifunctorComp₂₃Functor.mapIso + (Lifting₂.iso L₁ L₂₃ W₁ W₂₃ (F ⋙ (whiskeringRight _ _ _).obj L) F')).app G₂₃ + +variable {F₁₂ G F G₂₃} + +/-- The associator isomorphism obtained by localization. -/ +noncomputable def associator : bifunctorComp₁₂ F₁₂' G' ≅ bifunctorComp₂₃ F' G₂₃' := + letI := Lifting₃.bifunctorComp₁₂ L₁ L₂ L₃ L₁₂ L W₁ W₂ W₃ W₁₂ F₁₂ G F₁₂' G' + letI := Lifting₃.bifunctorComp₂₃ L₁ L₂ L₃ L₂₃ L W₁ W₂ W₃ W₂₃ F G₂₃ F' G₂₃' + lift₃NatIso L₁ L₂ L₃ W₁ W₂ W₃ _ _ _ _ ((Functor.postcompose₃.obj L).mapIso iso) + +lemma associator_hom_app_app_app (X₁ : C₁) (X₂ : C₂) (X₃ : C₃) : + (((associator L₁ L₂ L₃ L₁₂ L₂₃ L W₁ W₂ W₃ W₁₂ W₂₃ iso F₁₂' G' F' G₂₃').hom.app (L₁.obj X₁)).app + (L₂.obj X₂)).app (L₃.obj X₃) = + (G'.map (((Lifting₂.iso L₁ L₂ W₁ W₂ + (F₁₂ ⋙ (whiskeringRight C₂ C₁₂ D₁₂).obj L₁₂) F₁₂').hom.app X₁).app X₂)).app (L₃.obj X₃) ≫ + ((Lifting₂.iso L₁₂ L₃ W₁₂ W₃ (G ⋙ (whiskeringRight C₃ C D).obj L) G').hom.app + ((F₁₂.obj X₁).obj X₂)).app X₃ ≫ + L.map (((iso.hom.app X₁).app X₂).app X₃) ≫ + ((Lifting₂.iso L₁ L₂₃ W₁ W₂₃ + (F ⋙ (whiskeringRight _ _ _).obj L) F').inv.app X₁).app ((G₂₃.obj X₂).obj X₃) ≫ + (F'.obj (L₁.obj X₁)).map + (((Lifting₂.iso L₂ L₃ W₂ W₃ + (G₂₃ ⋙ (whiskeringRight _ _ _).obj L₂₃) G₂₃').inv.app X₂).app X₃) := by + dsimp [associator] + rw [lift₃NatTrans_app_app_app] + dsimp [Lifting₃.iso, Lifting₃.bifunctorComp₁₂, Lifting₃.bifunctorComp₂₃] + simp only [Category.assoc] + +end + +end Localization + +end CategoryTheory From 3368abb800806a35414e591aa3df6d74938dc0bc Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Mon, 20 Jan 2025 13:22:26 +0000 Subject: [PATCH 331/681] chore(LinearAlgebra): generalize results on ranks to semirings (#20774) --- Mathlib/FieldTheory/CardinalEmb.lean | 1 + Mathlib/FieldTheory/Relrank.lean | 1 + Mathlib/LinearAlgebra/Basis/Basic.lean | 52 +++++------ Mathlib/LinearAlgebra/Basis/Cardinality.lean | 76 ++++++---------- Mathlib/LinearAlgebra/Dimension/Basic.lean | 88 ++++++++++++------- .../Dimension/Constructions.lean | 73 ++++++++------- Mathlib/LinearAlgebra/Dimension/Finrank.lean | 10 +-- Mathlib/LinearAlgebra/Dimension/Free.lean | 10 +-- .../LinearAlgebra/Dimension/RankNullity.lean | 1 + .../Dimension/StrongRankCondition.lean | 19 ++-- Mathlib/LinearAlgebra/LinearIndependent.lean | 31 ++++--- 11 files changed, 194 insertions(+), 168 deletions(-) diff --git a/Mathlib/FieldTheory/CardinalEmb.lean b/Mathlib/FieldTheory/CardinalEmb.lean index 0bcfea73f5a13..3f51c66e061a4 100644 --- a/Mathlib/FieldTheory/CardinalEmb.lean +++ b/Mathlib/FieldTheory/CardinalEmb.lean @@ -122,6 +122,7 @@ def leastExt : ι → ι := rw [adjoin_basis_eq_top, ← eq_top_iff] at this apply_fun Module.rank F at this refine ne_of_lt ?_ this + let _ : AddCommMonoid (⊤ : IntermediateField F E) := inferInstance conv_rhs => rw [topEquiv.toLinearEquiv.rank_eq] have := mk_Iio_ord_toType i obtain eq | lt := rank_inf.out.eq_or_lt diff --git a/Mathlib/FieldTheory/Relrank.lean b/Mathlib/FieldTheory/Relrank.lean index 6b32cbc7d88e9..2ed666bbdae0a 100644 --- a/Mathlib/FieldTheory/Relrank.lean +++ b/Mathlib/FieldTheory/Relrank.lean @@ -125,6 +125,7 @@ theorem relfinrank_top_left : relfinrank ⊤ A = 1 := relfinrank_eq_one_of_le le set_option synthInstance.maxHeartbeats 400000 in @[simp] theorem relrank_top_right : relrank A ⊤ = Module.rank A E := by + let _ : AddCommMonoid (⊤ : IntermediateField A E) := inferInstance rw [relrank_eq_rank_of_le (show A ≤ ⊤ from le_top), extendScalars_top, IntermediateField.topEquiv.toLinearEquiv.rank_eq] diff --git a/Mathlib/LinearAlgebra/Basis/Basic.lean b/Mathlib/LinearAlgebra/Basis/Basic.lean index d2945cbb493aa..dfdec73ed3c15 100644 --- a/Mathlib/LinearAlgebra/Basis/Basic.lean +++ b/Mathlib/LinearAlgebra/Basis/Basic.lean @@ -311,6 +311,32 @@ theorem repr_isUnitSMul {v : Basis ι R₂ M} {w : ι → R₂} (hw : ∀ i, IsU (v.isUnitSMul hw).repr x i = (hw i).unit⁻¹ • v.repr x i := repr_unitsSMul _ _ _ _ +/-- Any basis is a maximal linear independent set. +-/ +theorem maximal [Nontrivial R] (b : Basis ι R M) : b.linearIndependent.Maximal := fun w hi h => by + -- If `w` is strictly bigger than `range b`, + apply le_antisymm h + -- then choose some `x ∈ w \ range b`, + intro x p + by_contra q + -- and write it in terms of the basis. + have e := b.linearCombination_repr x + -- This then expresses `x` as a linear combination + -- of elements of `w` which are in the range of `b`, + let u : ι ↪ w := + ⟨fun i => ⟨b i, h ⟨i, rfl⟩⟩, fun i i' r => + b.injective (by simpa only [Subtype.mk_eq_mk] using r)⟩ + simp_rw [Finsupp.linearCombination_apply] at e + change ((b.repr x).sum fun (i : ι) (a : R) ↦ a • (u i : M)) = ((⟨x, p⟩ : w) : M) at e + rw [← Finsupp.sum_embDomain (f := u) (g := fun x r ↦ r • (x : M)), + ← Finsupp.linearCombination_apply] at e + -- Now we can contradict the linear independence of `hi` + refine hi.linearCombination_ne_of_not_mem_support _ ?_ e + simp only [Finset.mem_map, Finsupp.support_embDomain] + rintro ⟨j, -, W⟩ + simp only [u, Embedding.coeFn_mk, Subtype.mk_eq_mk] at W + apply q ⟨j, W⟩ + end Basis end Module @@ -341,32 +367,6 @@ theorem Basis.eq_bot_of_rank_eq_zero [NoZeroDivisors R] (b : Basis ι R M) (N : namespace Basis -/-- Any basis is a maximal linear independent set. --/ -theorem maximal [Nontrivial R] (b : Basis ι R M) : b.linearIndependent.Maximal := fun w hi h => by - -- If `w` is strictly bigger than `range b`, - apply le_antisymm h - -- then choose some `x ∈ w \ range b`, - intro x p - by_contra q - -- and write it in terms of the basis. - have e := b.linearCombination_repr x - -- This then expresses `x` as a linear combination - -- of elements of `w` which are in the range of `b`, - let u : ι ↪ w := - ⟨fun i => ⟨b i, h ⟨i, rfl⟩⟩, fun i i' r => - b.injective (by simpa only [Subtype.mk_eq_mk] using r)⟩ - simp_rw [Finsupp.linearCombination_apply] at e - change ((b.repr x).sum fun (i : ι) (a : R) ↦ a • (u i : M)) = ((⟨x, p⟩ : w) : M) at e - rw [← Finsupp.sum_embDomain (f := u) (g := fun x r ↦ r • (x : M)), - ← Finsupp.linearCombination_apply] at e - -- Now we can contradict the linear independence of `hi` - refine hi.linearCombination_ne_of_not_mem_support _ ?_ e - simp only [Finset.mem_map, Finsupp.support_embDomain] - rintro ⟨j, -, W⟩ - simp only [u, Embedding.coeFn_mk, Subtype.mk_eq_mk] at W - apply q ⟨j, W⟩ - section Fin /-- Let `b` be a basis for a submodule `N` of `M`. If `y : M` is linear independent of `N` diff --git a/Mathlib/LinearAlgebra/Basis/Cardinality.lean b/Mathlib/LinearAlgebra/Basis/Cardinality.lean index 64108a9f48908..406b7974e64e3 100644 --- a/Mathlib/LinearAlgebra/Basis/Cardinality.lean +++ b/Mathlib/LinearAlgebra/Basis/Cardinality.lean @@ -73,7 +73,7 @@ end Semiring section Ring -variable [Ring R] [AddCommGroup M] [Nontrivial R] [Module R M] +variable [Semiring R] [AddCommMonoid M] [Nontrivial R] [Module R M] -- From [Les familles libres maximales d'un module ont-elles le meme cardinal?][lazarus1973] /-- Over any ring `R`, if `b` is a basis for a module `M`, @@ -81,63 +81,43 @@ and `s` is a maximal linearly independent set, then the union of the supports of `x ∈ s` (when written out in the basis `b`) is all of `b`. -/ theorem union_support_maximal_linearIndependent_eq_range_basis {ι : Type w} (b : Basis ι R M) - {κ : Type w'} (v : κ → M) (i : LinearIndependent R v) (m : i.Maximal) : + {κ : Type w'} (v : κ → M) (ind : LinearIndependent R v) (m : ind.Maximal) : ⋃ k, ((b.repr (v k)).support : Set ι) = Set.univ := by -- If that's not the case, by_contra h simp only [← Ne.eq_def, ne_univ_iff_exists_not_mem, mem_iUnion, not_exists_not, Finsupp.mem_support_iff, Finset.mem_coe] at h - -- We have some basis element `b b'` which is not in the support of any of the `v i`. - obtain ⟨b', w⟩ := h + -- We have some basis element `b i` which is not in the support of any of the `v k`. + obtain ⟨i, w⟩ := h + have repr_eq_zero (l) : b.repr (linearCombination R v l) i = 0 := by + simp [linearCombination_apply, Finsupp.sum, w] -- Using this, we'll construct a linearly independent family strictly larger than `v`, - -- by also using this `b b'`. - let v' : Option κ → M := fun o => o.elim (b b') v - have r : range v ⊆ range v' := by - rintro - ⟨k, rfl⟩ - use some k - simp only [v', Option.elim_some] - have r' : b b' ∉ range v := by - rintro ⟨k, p⟩ - simpa [w] using congr_arg (fun m => (b.repr m) b') p - have r'' : range v ≠ range v' := by - intro e - have p : b b' ∈ range v' := by - use none - simp only [v', Option.elim_none] - rw [← e] at p - exact r' p + -- by also using this `b i`. + let v' (o : Option κ) : M := o.elim (b i) v + have r : range v ⊆ range v' := by rintro - ⟨k, rfl⟩; exact ⟨some k, rfl⟩ + have r' : b i ∉ range v := fun ⟨k, p⟩ ↦ by simpa [w] using congr(b.repr $p i) + have r'' : range v ≠ range v' := (r' <| · ▸ ⟨none, rfl⟩) -- The key step in the proof is checking that this strictly larger family is linearly independent. have i' : LinearIndependent R ((↑) : range v' → M) := by apply LinearIndependent.to_subtype_range - rw [linearIndependent_iff] - intro l z - rw [Finsupp.linearCombination_option] at z - simp only [v', Option.elim'] at z - change _ + Finsupp.linearCombination R v l.some = 0 at z - -- We have some linear combination of `b b'` and the `v i`, which we want to show is trivial. - -- We'll first show the coefficient of `b b'` is zero, - -- by expressing the `v i` in the basis `b`, and using that the `v i` have no `b b'` term. - have l₀ : l none = 0 := by - rw [← eq_neg_iff_add_eq_zero] at z - replace z := neg_eq_iff_eq_neg.mpr z - apply_fun fun x => b.repr x b' at z - simp only [repr_self, map_smul, mul_one, Finsupp.single_eq_same, Pi.neg_apply, - Finsupp.smul_single', map_neg, Finsupp.coe_neg] at z - erw [DFunLike.congr_fun (apply_linearCombination R (b.repr : M →ₗ[R] ι →₀ R) v l.some) b'] - at z - simpa [Finsupp.linearCombination_apply, w] using z - -- Then all the other coefficients are zero, because `v` is linear independent. - have l₁ : l.some = 0 := by - rw [l₀, zero_smul, zero_add] at z - exact linearIndependent_iff.mp i _ z - -- Finally we put those facts together to show the linear combination is trivial. + rw [linearIndependent_iffₛ] + intro l l' z + simp_rw [linearCombination_option, v', Option.elim'] at z + change _ + linearCombination R v l.some = _ + linearCombination R v l'.some at z + -- We have some equality between linear combinations of `b i` and the `v k`, + -- and want to show the coefficients are equal. ext (_ | a) - · simp only [l₀, Finsupp.coe_zero, Pi.zero_apply] - · erw [DFunLike.congr_fun l₁ a] - simp only [Finsupp.coe_zero, Pi.zero_apply] - rw [LinearIndependent.Maximal] at m - specialize m (range v') i' r - exact r'' m + -- We'll first show the coefficient of `b i` is zero, + -- by expressing the `v k` in the basis `b`, and using that the `v k` have no `b i` term. + · simpa [repr_eq_zero] using congr(b.repr $z i) + -- All the other coefficients are also equal, because `v` is linear independent, + -- by comparing the coefficients in the basis `b`. + have l₁ : l.some = l'.some := ind <| b.repr.injective <| ext fun j ↦ by + obtain rfl | ne := eq_or_ne i j + · simp_rw [repr_eq_zero] + classical simpa [single_apply, ne] using congr(b.repr $z j) + exact DFunLike.congr_fun l₁ a + exact r'' (m (range v') i' r) /-- Over any ring `R`, if `b` is an infinite basis for a module `M`, and `s` is a maximal linearly independent set, diff --git a/Mathlib/LinearAlgebra/Dimension/Basic.lean b/Mathlib/LinearAlgebra/Dimension/Basic.lean index 124960fd5f2ea..6d009c49a152c 100644 --- a/Mathlib/LinearAlgebra/Dimension/Basic.lean +++ b/Mathlib/LinearAlgebra/Dimension/Basic.lean @@ -95,81 +95,107 @@ end LinearIndependent section SurjectiveInjective -section Module -variable [Ring R] [AddCommGroup M] [Module R M] [Ring R'] +section Semiring +variable [Semiring R] [AddCommMonoid M] [Module R M] [Semiring R'] section -variable [AddCommGroup M'] [Module R' M'] +variable [AddCommMonoid M'] [Module R' M'] -/-- If `M / R` and `M' / R'` are modules, `i : R' → R` is a map which sends non-zero elements to -non-zero elements, `j : M →+ M'` is an injective group homomorphism, such that the scalar +/-- If `M / R` and `M' / R'` are modules, `i : R' → R` is an injective map +non-zero elements, `j : M →+ M'` is an injective monoid homomorphism, such that the scalar multiplications on `M` and `M'` are compatible, then the rank of `M / R` is smaller than or equal to the rank of `M' / R'`. As a special case, taking `R = R'` it is `LinearMap.lift_rank_le_of_injective`. -/ -theorem lift_rank_le_of_injective_injective (i : R' → R) (j : M →+ M') - (hi : ∀ r, i r = 0 → r = 0) (hj : Injective j) +theorem lift_rank_le_of_injective_injectiveₛ (i : R' → R) (j : M →+ M') + (hi : Injective i) (hj : Injective j) (hc : ∀ (r : R') (m : M), j (i r • m) = r • j m) : lift.{v'} (Module.rank R M) ≤ lift.{v} (Module.rank R' M') := by simp_rw [Module.rank, lift_iSup (bddAbove_range _)] exact ciSup_mono' (bddAbove_range _) fun ⟨s, h⟩ ↦ ⟨⟨j '' s, - (h.map_of_injective_injective i j hi (fun _ _ ↦ hj <| by rwa [j.map_zero]) hc).image⟩, + (h.map_of_injective_injectiveₛ i j hi hj hc).image⟩, lift_mk_le'.mpr ⟨(Equiv.Set.image j s hj).toEmbedding⟩⟩ -/-- If `M / R` and `M' / R'` are modules, `i : R → R'` is a surjective map which maps zero to zero, -`j : M →+ M'` is an injective group homomorphism, such that the scalar multiplications on `M` and +/-- If `M / R` and `M' / R'` are modules, `i : R → R'` is a surjective map, and +`j : M →+ M'` is an injective monoid homomorphism, such that the scalar multiplications on `M` and `M'` are compatible, then the rank of `M / R` is smaller than or equal to the rank of `M' / R'`. As a special case, taking `R = R'` it is `LinearMap.lift_rank_le_of_injective`. -/ -theorem lift_rank_le_of_surjective_injective (i : ZeroHom R R') (j : M →+ M') +theorem lift_rank_le_of_surjective_injective (i : R → R') (j : M →+ M') (hi : Surjective i) (hj : Injective j) (hc : ∀ (r : R) (m : M), j (r • m) = i r • j m) : lift.{v'} (Module.rank R M) ≤ lift.{v} (Module.rank R' M') := by obtain ⟨i', hi'⟩ := hi.hasRightInverse - refine lift_rank_le_of_injective_injective i' j (fun _ h ↦ ?_) hj fun r m ↦ ?_ + refine lift_rank_le_of_injective_injectiveₛ i' j (fun _ _ h ↦ ?_) hj fun r m ↦ ?_ · apply_fun i at h - rwa [hi', i.map_zero] at h + rwa [hi', hi'] at h rw [hc (i' r) m, hi'] /-- If `M / R` and `M' / R'` are modules, `i : R → R'` is a bijective map which maps zero to zero, `j : M ≃+ M'` is a group isomorphism, such that the scalar multiplications on `M` and `M'` are compatible, then the rank of `M / R` is equal to the rank of `M' / R'`. As a special case, taking `R = R'` it is `LinearEquiv.lift_rank_eq`. -/ -theorem lift_rank_eq_of_equiv_equiv (i : ZeroHom R R') (j : M ≃+ M') +theorem lift_rank_eq_of_equiv_equiv (i : R → R') (j : M ≃+ M') (hi : Bijective i) (hc : ∀ (r : R) (m : M), j (r • m) = i r • j m) : lift.{v'} (Module.rank R M) = lift.{v} (Module.rank R' M') := (lift_rank_le_of_surjective_injective i j hi.2 j.injective hc).antisymm <| - lift_rank_le_of_injective_injective i j.symm (fun _ _ ↦ hi.1 <| by rwa [i.map_zero]) + lift_rank_le_of_injective_injectiveₛ i j.symm hi.1 j.symm.injective fun _ _ ↦ j.symm_apply_eq.2 <| by erw [hc, j.apply_symm_apply] end section -variable [AddCommGroup M₁] [Module R' M₁] +variable [AddCommMonoid M₁] [Module R' M₁] /-- The same-universe version of `lift_rank_le_of_injective_injective`. -/ -theorem rank_le_of_injective_injective (i : R' → R) (j : M →+ M₁) - (hi : ∀ r, i r = 0 → r = 0) (hj : Injective j) +theorem rank_le_of_injective_injectiveₛ (i : R' → R) (j : M →+ M₁) + (hi : Injective i) (hj : Injective j) (hc : ∀ (r : R') (m : M), j (i r • m) = r • j m) : Module.rank R M ≤ Module.rank R' M₁ := by - simpa only [lift_id] using lift_rank_le_of_injective_injective i j hi hj hc + simpa only [lift_id] using lift_rank_le_of_injective_injectiveₛ i j hi hj hc /-- The same-universe version of `lift_rank_le_of_surjective_injective`. -/ -theorem rank_le_of_surjective_injective (i : ZeroHom R R') (j : M →+ M₁) +theorem rank_le_of_surjective_injective (i : R → R') (j : M →+ M₁) (hi : Surjective i) (hj : Injective j) (hc : ∀ (r : R) (m : M), j (r • m) = i r • j m) : Module.rank R M ≤ Module.rank R' M₁ := by simpa only [lift_id] using lift_rank_le_of_surjective_injective i j hi hj hc /-- The same-universe version of `lift_rank_eq_of_equiv_equiv`. -/ -theorem rank_eq_of_equiv_equiv (i : ZeroHom R R') (j : M ≃+ M₁) +theorem rank_eq_of_equiv_equiv (i : R → R') (j : M ≃+ M₁) (hi : Bijective i) (hc : ∀ (r : R) (m : M), j (r • m) = i r • j m) : Module.rank R M = Module.rank R' M₁ := by simpa only [lift_id] using lift_rank_eq_of_equiv_equiv i j hi hc end -end Module +end Semiring + +section Ring +variable [Ring R] [AddCommGroup M] [Module R M] [Ring R'] + +/-- If `M / R` and `M' / R'` are modules, `i : R' → R` is a map which sends non-zero elements to +non-zero elements, `j : M →+ M'` is an injective group homomorphism, such that the scalar +multiplications on `M` and `M'` are compatible, then the rank of `M / R` is smaller than or equal to +the rank of `M' / R'`. As a special case, taking `R = R'` it is +`LinearMap.lift_rank_le_of_injective`. -/ +theorem lift_rank_le_of_injective_injective [AddCommGroup M'] [Module R' M'] + (i : R' → R) (j : M →+ M') (hi : ∀ r, i r = 0 → r = 0) (hj : Injective j) + (hc : ∀ (r : R') (m : M), j (i r • m) = r • j m) : + lift.{v'} (Module.rank R M) ≤ lift.{v} (Module.rank R' M') := by + simp_rw [Module.rank, lift_iSup (bddAbove_range _)] + exact ciSup_mono' (bddAbove_range _) fun ⟨s, h⟩ ↦ ⟨⟨j '' s, + (h.map_of_injective_injective i j hi (fun _ _ ↦ hj <| by rwa [j.map_zero]) hc).image⟩, + lift_mk_le'.mpr ⟨(Equiv.Set.image j s hj).toEmbedding⟩⟩ + +/-- The same-universe version of `lift_rank_le_of_injective_injective`. -/ +theorem rank_le_of_injective_injective [AddCommGroup M₁] [Module R' M₁] + (i : R' → R) (j : M →+ M₁) (hi : ∀ r, i r = 0 → r = 0) (hj : Injective j) + (hc : ∀ (r : R') (m : M), j (i r • m) = r • j m) : + Module.rank R M ≤ Module.rank R' M₁ := by + simpa only [lift_id] using lift_rank_le_of_injective_injective i j hi hj hc + +end Ring namespace Algebra -variable {R : Type w} {S : Type v} [CommRing R] [Ring S] [Algebra R S] - {R' : Type w'} {S' : Type v'} [CommRing R'] [Ring S'] [Algebra R' S'] +variable {R : Type w} {S : Type v} [CommSemiring R] [Semiring S] [Algebra R S] + {R' : Type w'} {S' : Type v'} [CommSemiring R'] [Semiring S'] [Algebra R' S'] /-- If `S / R` and `S' / R'` are algebras, `i : R' →+* R` and `j : S →+* S'` are injective ring homomorphisms, such that `R' → R → S → S'` and `R' → S'` commute, then the rank of `S / R` is @@ -178,8 +204,7 @@ theorem lift_rank_le_of_injective_injective (i : R' →+* R) (j : S →+* S') (hi : Injective i) (hj : Injective j) (hc : (j.comp (algebraMap R S)).comp i = algebraMap R' S') : lift.{v'} (Module.rank R S) ≤ lift.{v} (Module.rank R' S') := by - refine _root_.lift_rank_le_of_injective_injective i j - (fun _ _ ↦ hi <| by rwa [i.map_zero]) hj fun r _ ↦ ?_ + refine _root_.lift_rank_le_of_injective_injectiveₛ i j hi hj fun r _ ↦ ?_ have := congr($hc r) simp only [RingHom.coe_comp, comp_apply] at this simp_rw [smul_def, AddMonoidHom.coe_coe, map_mul, this] @@ -207,7 +232,7 @@ theorem lift_rank_eq_of_equiv_equiv (i : R ≃+* R') (j : S ≃+* S') simp only [RingEquiv.toRingHom_eq_coe, RingHom.coe_comp, RingHom.coe_coe, comp_apply] at this simp only [smul_def, RingEquiv.coe_toAddEquiv, map_mul, ZeroHom.coe_coe, this] -variable {S' : Type v} [Ring S'] [Algebra R' S'] +variable {S' : Type v} [Semiring S'] [Algebra R' S'] /-- The same-universe version of `Algebra.lift_rank_le_of_injective_injective`. -/ theorem rank_le_of_injective_injective @@ -233,16 +258,15 @@ end Algebra end SurjectiveInjective -variable [Ring R] [AddCommGroup M] [Module R M] - [Ring R'] - [AddCommGroup M'] [AddCommGroup M₁] +variable [Semiring R] [AddCommMonoid M] [Module R M] + [Semiring R'] [AddCommMonoid M'] [AddCommMonoid M₁] [Module R M'] [Module R M₁] [Module R' M'] [Module R' M₁] section theorem LinearMap.lift_rank_le_of_injective (f : M →ₗ[R] M') (i : Injective f) : Cardinal.lift.{v'} (Module.rank R M) ≤ Cardinal.lift.{v} (Module.rank R M') := - lift_rank_le_of_injective_injective (RingHom.id R) f (fun _ h ↦ h) i f.map_smul + lift_rank_le_of_injective_injectiveₛ (RingHom.id R) f (fun _ _ h ↦ h) i f.map_smul theorem LinearMap.rank_le_of_injective (f : M →ₗ[R] M₁) (i : Injective f) : Module.rank R M ≤ Module.rank R M₁ := @@ -350,7 +374,7 @@ theorem rank_subsingleton [Subsingleton R] : Module.rank R M = 1 := by apply subsingleton_of_subsingleton intro w hw refine ⟨⟨{0}, ?_⟩, ?_⟩ - · rw [linearIndependent_iff'] + · rw [linearIndependent_iff'ₛ] subsingleton · exact hw.trans_eq (Cardinal.mk_singleton _).symm diff --git a/Mathlib/LinearAlgebra/Dimension/Constructions.lean b/Mathlib/LinearAlgebra/Dimension/Constructions.lean index 427174ca24c09..5cdfb7e8f22f7 100644 --- a/Mathlib/LinearAlgebra/Dimension/Constructions.lean +++ b/Mathlib/LinearAlgebra/Dimension/Constructions.lean @@ -5,7 +5,6 @@ Authors: Mario Carneiro, Johannes Hölzl, Sander Dahmen, Kim Morrison, Chris Hug -/ import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.LinearAlgebra.Dimension.Free -import Mathlib.LinearAlgebra.Isomorphisms /-! # Rank of various constructions @@ -38,15 +37,15 @@ variable {ι : Type w} {ι' : Type w'} {η : Type u₁'} {φ : η → Type*} open Basis Cardinal DirectSum Function Module Set Submodule +section Quotient + variable [Ring R] [CommRing S] [AddCommGroup M] [AddCommGroup M'] [AddCommGroup M₁] variable [Module R M] -section Quotient - theorem LinearIndependent.sum_elim_of_quotient {M' : Submodule R M} {ι₁ ι₂} {f : ι₁ → M'} (hf : LinearIndependent R f) (g : ι₂ → M) (hg : LinearIndependent R (Submodule.Quotient.mk (p := M') ∘ g)) : - LinearIndependent R (Sum.elim (f · : ι₁ → M) g) := by + LinearIndependent R (Sum.elim (f · : ι₁ → M) g) := by refine .sum_type (hf.map' M'.subtype M'.ker_subtype) (.of_comp M'.mkQ hg) ?_ refine disjoint_def.mpr fun x h₁ h₂ ↦ ?_ have : x ∈ M' := span_le.mpr (Set.range_subset_iff.mpr fun i ↦ (f i).prop) h₁ @@ -54,9 +53,9 @@ theorem LinearIndependent.sum_elim_of_quotient simp_rw [← Quotient.mk_eq_zero, ← mkQ_apply, map_finsupp_sum, map_smul, mkQ_apply] at this rw [linearIndependent_iff.mp hg _ this, Finsupp.sum_zero_index] -theorem LinearIndependent.union_of_quotient - {M' : Submodule R M} {s : Set M} (hs : s ⊆ M') (hs' : LinearIndependent (ι := s) R Subtype.val) - {t : Set M} (ht : LinearIndependent (ι := t) R (Submodule.Quotient.mk (p := M') ∘ Subtype.val)) : +theorem LinearIndependent.union_of_quotient {M' : Submodule R M} + {s : Set M} (hs : s ⊆ M') (hs' : LinearIndependent (ι := s) R Subtype.val) {t : Set M} + (ht : LinearIndependent (ι := t) R (Submodule.Quotient.mk (p := M') ∘ Subtype.val)) : LinearIndependent (ι := (s ∪ t :)) R Subtype.val := by refine (LinearIndependent.sum_elim_of_quotient (f := Set.embeddingOfSubset s M' hs) (of_comp M'.subtype (by simpa using hs')) Subtype.val ht).to_subtype_range' ?_ @@ -76,8 +75,17 @@ theorem rank_quotient_add_rank_le [Nontrivial R] (M' : Submodule R M) : theorem rank_quotient_le (p : Submodule R M) : Module.rank R (M ⧸ p) ≤ Module.rank R M := (mkQ p).rank_le_of_surjective Quot.mk_surjective +/-- The dimension of a quotient is bounded by the dimension of the ambient space. -/ +theorem Submodule.finrank_quotient_le [StrongRankCondition R] [Module.Finite R M] + (s : Submodule R M) : finrank R (M ⧸ s) ≤ finrank R M := + toNat_le_toNat ((Submodule.mkQ s).rank_le_of_surjective Quot.mk_surjective) + (rank_lt_aleph0 _ _) + end Quotient +variable [Semiring R] [CommSemiring S] [AddCommMonoid M] [AddCommMonoid M'] [AddCommMonoid M₁] +variable [Module R M] + section ULift @[simp] @@ -95,20 +103,20 @@ section Prod variable (R M M') variable [Module R M₁] [Module R M'] -open LinearMap in -theorem lift_rank_add_lift_rank_le_rank_prod [Nontrivial R] : - lift.{v'} (Module.rank R M) + lift.{v} (Module.rank R M') ≤ Module.rank R (M × M') := by - convert rank_quotient_add_rank_le (ker <| LinearMap.fst R M M') - · refine Eq.trans ?_ (lift_id'.{v, v'} _) - rw [(quotKerEquivRange _).lift_rank_eq, - rank_range_of_surjective _ fst_surjective, lift_umax.{v, v'}] - · refine Eq.trans ?_ (lift_id'.{v', v} _) - rw [ker_fst, ← (LinearEquiv.ofInjective _ <| inr_injective (M := M) (M₂ := M')).lift_rank_eq, - lift_umax.{v', v}] - theorem rank_add_rank_le_rank_prod [Nontrivial R] : Module.rank R M + Module.rank R M₁ ≤ Module.rank R (M × M₁) := by - convert ← lift_rank_add_lift_rank_le_rank_prod R M M₁ <;> apply lift_id + conv_lhs => simp only [Module.rank_def] + have := nonempty_linearIndependent_set R M + have := nonempty_linearIndependent_set R M₁ + rw [Cardinal.ciSup_add_ciSup _ (bddAbove_range _) _ (bddAbove_range _)] + exact ciSup_le fun ⟨s, hs⟩ ↦ ciSup_le fun ⟨t, ht⟩ ↦ + (linearIndependent_inl_union_inr' hs ht).cardinal_le_rank + +theorem lift_rank_add_lift_rank_le_rank_prod [Nontrivial R] : + lift.{v'} (Module.rank R M) + lift.{v} (Module.rank R M') ≤ Module.rank R (M × M') := by + rw [← rank_ulift, ← rank_ulift] + exact (rank_add_rank_le_rank_prod R _).trans_eq + (ULift.moduleEquiv.prod ULift.moduleEquiv).rank_eq variable {R M M'} variable [StrongRankCondition R] [Module.Free R M] [Module.Free R M'] [Module.Free R M₁] @@ -161,7 +169,7 @@ theorem rank_finsupp_self' {ι : Type u} : Module.rank R (ι →₀ R) = #ι := /-- The rank of the direct sum is the sum of the ranks. -/ @[simp] -theorem rank_directSum {ι : Type v} (M : ι → Type w) [∀ i : ι, AddCommGroup (M i)] +theorem rank_directSum {ι : Type v} (M : ι → Type w) [∀ i : ι, AddCommMonoid (M i)] [∀ i : ι, Module R (M i)] [∀ i : ι, Module.Free R (M i)] : Module.rank R (⨁ i, M i) = Cardinal.sum fun i => Module.rank R (M i) := by let B i := chooseBasis R (M i) @@ -222,7 +230,7 @@ theorem finrank_finsupp_self {ι : Type v} [Fintype ι] : finrank R (ι →₀ R /-- The finrank of the direct sum is the sum of the finranks. -/ @[simp] -theorem finrank_directSum {ι : Type v} [Fintype ι] (M : ι → Type w) [∀ i : ι, AddCommGroup (M i)] +theorem finrank_directSum {ι : Type v} [Fintype ι] (M : ι → Type w) [∀ i : ι, AddCommMonoid (M i)] [∀ i : ι, Module R (M i)] [∀ i : ι, Module.Free R (M i)] [∀ i : ι, Module.Finite R (M i)] : finrank R (⨁ i, M i) = ∑ i, finrank R (M i) := by letI := nontrivial_of_invariantBasisNumber R @@ -241,7 +249,7 @@ end Finsupp section Pi variable [StrongRankCondition R] [Module.Free R M] -variable [∀ i, AddCommGroup (φ i)] [∀ i, Module R (φ i)] [∀ i, Module.Free R (φ i)] +variable [∀ i, AddCommMonoid (φ i)] [∀ i, Module R (φ i)] [∀ i, Module.Free R (φ i)] open Module.Free @@ -267,7 +275,7 @@ theorem Module.finrank_pi {ι : Type v} [Fintype ι] : --TODO: this should follow from `LinearEquiv.finrank_eq`, that is over a field. /-- The finrank of a finite product is the sum of the finranks. -/ theorem Module.finrank_pi_fintype - {ι : Type v} [Fintype ι] {M : ι → Type w} [∀ i : ι, AddCommGroup (M i)] + {ι : Type v} [Fintype ι] {M : ι → Type w} [∀ i : ι, AddCommMonoid (M i)] [∀ i : ι, Module R (M i)] [∀ i : ι, Module.Free R (M i)] [∀ i : ι, Module.Finite R (M i)] : finrank R (∀ i, M i) = ∑ i, finrank R (M i) := by letI := nontrivial_of_invariantBasisNumber R @@ -277,7 +285,7 @@ theorem Module.finrank_pi_fintype variable {R} variable [Fintype η] -theorem rank_fun {M η : Type u} [Fintype η] [AddCommGroup M] [Module R M] [Module.Free R M] : +theorem rank_fun {M η : Type u} [Fintype η] [AddCommMonoid M] [Module R M] [Module.Free R M] : Module.rank R (η → M) = Fintype.card η * Module.rank R M := by rw [rank_pi, Cardinal.sum_const', Cardinal.mk_fintype] @@ -378,12 +386,6 @@ theorem Submodule.finrank_le [Module.Finite R M] (s : Submodule R M) : finrank R s ≤ finrank R M := toNat_le_toNat (Submodule.rank_le s) (rank_lt_aleph0 _ _) -/-- The dimension of a quotient is bounded by the dimension of the ambient space. -/ -theorem Submodule.finrank_quotient_le [Module.Finite R M] (s : Submodule R M) : - finrank R (M ⧸ s) ≤ finrank R M := - toNat_le_toNat ((Submodule.mkQ s).rank_le_of_surjective Quot.mk_surjective) - (rank_lt_aleph0 _ _) - /-- Pushforwards of finite submodules have a smaller finrank. -/ theorem Submodule.finrank_map_le [Module R M'] (f : M →ₗ[R] M') (p : Submodule R M) [Module.Finite R p] : @@ -485,7 +487,9 @@ section SubalgebraRank open Module -variable {F E : Type*} [CommRing F] [Ring E] [Algebra F E] +section Semiring + +variable {F E : Type*} [CommSemiring F] [Semiring E] [Algebra F E] @[simp] theorem Subalgebra.rank_toSubmodule (S : Subalgebra F E) : @@ -511,8 +515,11 @@ theorem Subalgebra.rank_top : Module.rank F (⊤ : Subalgebra F E) = Module.rank rw [subalgebra_top_rank_eq_submodule_top_rank] exact _root_.rank_top F E -section +end Semiring +section Ring + +variable {F E : Type*} [CommRing F] [Ring E] [Algebra F E] variable [StrongRankCondition F] [NoZeroSMulDivisors F E] [Nontrivial E] @[simp] @@ -526,6 +533,6 @@ theorem Subalgebra.rank_bot : Module.rank F (⊥ : Subalgebra F E) = 1 := theorem Subalgebra.finrank_bot : finrank F (⊥ : Subalgebra F E) = 1 := finrank_eq_of_rank_eq (by simp) -end +end Ring end SubalgebraRank diff --git a/Mathlib/LinearAlgebra/Dimension/Finrank.lean b/Mathlib/LinearAlgebra/Dimension/Finrank.lean index 90041e059c7a2..229fc22554cce 100644 --- a/Mathlib/LinearAlgebra/Dimension/Finrank.lean +++ b/Mathlib/LinearAlgebra/Dimension/Finrank.lean @@ -36,11 +36,11 @@ universe u v w open Cardinal Submodule Module Function variable {R : Type u} {M : Type v} {N : Type w} -variable [Ring R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] +variable [Semiring R] [AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] namespace Module -section Ring +section Semiring /-- The rank of a module as a natural number. @@ -51,7 +51,7 @@ of `M` over `R`. Note that it is possible to have `M` with `¬(Module.Finite R M)` but `finrank R M ≠ 0`, for example `ℤ × ℚ/ℤ` has `finrank` equal to `1`. -/ -noncomputable def finrank (R M : Type*) [Semiring R] [AddCommGroup M] [Module R M] : ℕ := +noncomputable def finrank (R M : Type*) [Semiring R] [AddCommMonoid M] [Module R M] : ℕ := Cardinal.toNat (Module.rank R M) @[deprecated (since := "2024-10-01")] protected alias _root_.FiniteDimensional.finrank := finrank @@ -94,7 +94,7 @@ theorem finrank_le_finrank_of_rank_le_rank (h' : Module.rank R N < ℵ₀) : finrank R M ≤ finrank R N := by simpa only [toNat_lift] using toNat_le_toNat h (lift_lt_aleph0.mpr h') -end Ring +end Semiring end Module @@ -102,7 +102,7 @@ open Module namespace LinearEquiv -variable {R M M₂ : Type*} [Ring R] [AddCommGroup M] [AddCommGroup M₂] +variable {R M M₂ : Type*} [Semiring R] [AddCommMonoid M] [AddCommMonoid M₂] variable [Module R M] [Module R M₂] /-- The dimension of a finite dimensional space is preserved under linear equivalence. -/ diff --git a/Mathlib/LinearAlgebra/Dimension/Free.lean b/Mathlib/LinearAlgebra/Dimension/Free.lean index a22d2a62026a5..2b06cd9f409f4 100644 --- a/Mathlib/LinearAlgebra/Dimension/Free.lean +++ b/Mathlib/LinearAlgebra/Dimension/Free.lean @@ -30,7 +30,7 @@ open Cardinal Basis Submodule Function Set DirectSum Module section Tower variable (F : Type u) (K : Type v) (A : Type w) -variable [Ring F] [Ring K] [AddCommGroup A] +variable [Semiring F] [Semiring K] [AddCommMonoid A] variable [Module F K] [Module K A] [Module F A] [IsScalarTower F K A] variable [StrongRankCondition F] [StrongRankCondition K] [Module.Free F K] [Module.Free K A] @@ -67,10 +67,10 @@ theorem Module.finrank_mul_finrank : finrank F K * finrank K A = finrank F A := end Tower variable {R : Type u} {M M₁ : Type v} {M' : Type v'} -variable [Ring R] [StrongRankCondition R] -variable [AddCommGroup M] [Module R M] [Module.Free R M] -variable [AddCommGroup M'] [Module R M'] [Module.Free R M'] -variable [AddCommGroup M₁] [Module R M₁] [Module.Free R M₁] +variable [Semiring R] [StrongRankCondition R] +variable [AddCommMonoid M] [Module R M] [Module.Free R M] +variable [AddCommMonoid M'] [Module R M'] [Module.Free R M'] +variable [AddCommMonoid M₁] [Module R M₁] [Module.Free R M₁] namespace Module.Free diff --git a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean index 48fd4277e7c4f..a8da7666e5135 100644 --- a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean +++ b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean @@ -5,6 +5,7 @@ Authors: Andrew Yang -/ import Mathlib.LinearAlgebra.Dimension.Constructions import Mathlib.LinearAlgebra.Dimension.Finite +import Mathlib.LinearAlgebra.Isomorphisms /-! diff --git a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean index 71be346b20eaa..55bb014a486dd 100644 --- a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean +++ b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean @@ -41,7 +41,7 @@ noncomputable section universe u v w w' -variable {R : Type u} {M : Type v} [Ring R] [AddCommGroup M] [Module R M] +variable {R : Type u} {M : Type v} [Semiring R] [AddCommMonoid M] [Module R M] variable {ι : Type w} {ι' : Type w'} open Cardinal Basis Submodule Function Set @@ -181,8 +181,7 @@ theorem linearIndependent_le_span_aux' {ι : Type*} [Fintype ι] (v : ι → M) apply_fun linearCombination R ((↑) : w → M) at h simp only [linearCombination_linearCombination, Submodule.coe_mk, Span.finsupp_linearCombination_repr] at h - rw [← sub_eq_zero, ← LinearMap.map_sub] at h - exact sub_eq_zero.mp (linearIndependent_iff.mp i _ h) + exact i h /-- If `R` satisfies the strong rank condition, then any linearly independent family `v : ι → M` @@ -320,12 +319,13 @@ theorem Basis.card_le_card_of_linearIndependent {ι : Type*} [Fintype ι] (b : B theorem Basis.card_le_card_of_submodule (N : Submodule R M) [Fintype ι] (b : Basis ι R M) [Fintype ι'] (b' : Basis ι' R N) : Fintype.card ι' ≤ Fintype.card ι := - b.card_le_card_of_linearIndependent (b'.linearIndependent.map' N.subtype N.ker_subtype) + b.card_le_card_of_linearIndependent + (b'.linearIndependent.map_injOn N.subtype N.injective_subtype.injOn) theorem Basis.card_le_card_of_le {N O : Submodule R M} (hNO : N ≤ O) [Fintype ι] (b : Basis ι R O) [Fintype ι'] (b' : Basis ι' R N) : Fintype.card ι' ≤ Fintype.card ι := b.card_le_card_of_linearIndependent - (b'.linearIndependent.map' (Submodule.inclusion hNO) (N.ker_inclusion O _)) + (b'.linearIndependent.map_injOn (inclusion hNO) (N.inclusion_injective _).injOn) theorem Basis.mk_eq_rank (v : Basis ι R M) : Cardinal.lift.{v} #ι = Cardinal.lift.{w} (Module.rank R M) := by @@ -351,9 +351,10 @@ theorem rank_span_set {s : Set M} (hs : LinearIndependent R (fun x => x : s → finite free module `M`. A property is true for all submodules of `M` if it satisfies the following "inductive step": the property is true for a submodule `N` if it's true for all submodules `N'` of `N` with the property that there exists `0 ≠ x ∈ N` such that the sum `N' + Rx` is direct. -/ -def Submodule.inductionOnRank [IsDomain R] [Finite ι] (b : Basis ι R M) - (P : Submodule R M → Sort*) (ih : ∀ N : Submodule R M, - (∀ N' ≤ N, ∀ x ∈ N, (∀ (c : R), ∀ y ∈ N', c • x + y = (0 : M) → c = 0) → P N') → P N) +def Submodule.inductionOnRank {R M} [Ring R] [StrongRankCondition R] [AddCommGroup M] [Module R M] + [IsDomain R] [Finite ι] (b : Basis ι R M) (P : Submodule R M → Sort*) + (ih : ∀ N : Submodule R M, + (∀ N' ≤ N, ∀ x ∈ N, (∀ (c : R), ∀ y ∈ N', c • x + y = (0 : M) → c = 0) → P N') → P N) (N : Submodule R M) : P N := letI := Fintype.ofFinite ι Submodule.inductionOnRankAux b P ih (Fintype.card ι) N fun hs hli => by @@ -455,7 +456,7 @@ end Module open Module -variable {M'} [AddCommGroup M'] [Module R M'] +variable {M'} [AddCommMonoid M'] [Module R M'] theorem LinearMap.finrank_le_finrank_of_injective [Module.Finite R M'] {f : M →ₗ[R] M'} (hf : Function.Injective f) : finrank R M ≤ finrank R M' := diff --git a/Mathlib/LinearAlgebra/LinearIndependent.lean b/Mathlib/LinearAlgebra/LinearIndependent.lean index 81a9e0d48fe9e..1b216c6e08dc5 100644 --- a/Mathlib/LinearAlgebra/LinearIndependent.lean +++ b/Mathlib/LinearAlgebra/LinearIndependent.lean @@ -297,16 +297,31 @@ theorem Submodule.range_ker_disjoint {f : M →ₗ[R] M'} such that they are both injective, and compatible with the scalar multiplications on `M` and `M'`, then `j` sends linearly independent families of vectors to linearly independent families of vectors. As a special case, taking `R = R'` -it is `LinearIndependent.map'`. -/ +it is `LinearIndependent.map_injOn`. -/ theorem LinearIndependent.map_of_injective_injectiveₛ {R' M' : Type*} [Semiring R'] [AddCommMonoid M'] [Module R' M'] (hv : LinearIndependent R v) - (i : R' → R) (j : M →+ M') (hi : Function.Injective i) (hj : Function.Injective j) + (i : R' → R) (j : M →+ M') (hi : Injective i) (hj : Injective j) (hc : ∀ (r : R') (m : M), j (i r • m) = r • j m) : LinearIndependent R' (j ∘ v) := by rw [linearIndependent_iff'ₛ] at hv ⊢ intro S r₁ r₂ H s hs simp_rw [comp_apply, ← hc, ← map_sum] at H exact hi <| hv _ _ _ (hj H) s hs +/-- If `M / R` and `M' / R'` are modules, `i : R → R'` is a surjective map, +and `j : M →+ M'` is an injective monoid map, such that the scalar multiplications +on `M` and `M'` are compatible, then `j` sends linearly independent families +of vectors to linearly independent families of vectors. As a special case, taking `R = R'` +it is `LinearIndependent.map_injOn`. -/ +theorem LinearIndependent.map_of_surjective_injectiveₛ {R' M' : Type*} + [Semiring R'] [AddCommMonoid M'] [Module R' M'] (hv : LinearIndependent R v) + (i : R → R') (j : M →+ M') (hi : Surjective i) (hj : Injective j) + (hc : ∀ (r : R) (m : M), j (r • m) = i r • j m) : LinearIndependent R' (j ∘ v) := by + obtain ⟨i', hi'⟩ := hi.hasRightInverse + refine hv.map_of_injective_injectiveₛ i' j (fun _ _ h ↦ ?_) hj fun r m ↦ ?_ + · apply_fun i at h + rwa [hi', hi'] at h + rw [hc (i' r) m, hi'] + /-- If the image of a family of vectors under a linear map is linearly independent, then so is the original family. -/ theorem LinearIndependent.of_comp (f : M →ₗ[R] M') (hfv : LinearIndependent R (f ∘ v)) : @@ -925,15 +940,11 @@ theorem LinearIndependent.map_of_injective_injective {R' M' : Type*} scalar multiplications on `M` and `M'` are compatible, then `j` sends linearly independent families of vectors to linearly independent families of vectors. As a special case, taking `R = R'` it is `LinearIndependent.map'`. -/ -theorem LinearIndependent.map_of_surjective_injective {R' : Type*} {M' : Type*} +theorem LinearIndependent.map_of_surjective_injective {R' M' : Type*} [Ring R'] [AddCommGroup M'] [Module R' M'] (hv : LinearIndependent R v) - (i : ZeroHom R R') (j : M →+ M') (hi : Surjective i) (hj : ∀ m, j m = 0 → m = 0) - (hc : ∀ (r : R) (m : M), j (r • m) = i r • j m) : LinearIndependent R' (j ∘ v) := by - obtain ⟨i', hi'⟩ := hi.hasRightInverse - refine hv.map_of_injective_injective i' j (fun _ h ↦ ?_) hj fun r m ↦ ?_ - · apply_fun i at h - rwa [hi', i.map_zero] at h - rw [hc (i' r) m, hi'] + (i : R → R') (j : M →+ M') (hi : Surjective i) (hj : ∀ m, j m = 0 → m = 0) + (hc : ∀ (r : R) (m : M), j (r • m) = i r • j m) : LinearIndependent R' (j ∘ v) := + hv.map_of_surjective_injectiveₛ i _ hi ((injective_iff_map_eq_zero _).mpr hj) hc /-- If `f` is an injective linear map, then the family `f ∘ v` is linearly independent if and only if the family `v` is linearly independent. -/ From 3081121080131d9898e9581f3472f7b2179212c8 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:06:08 +0000 Subject: [PATCH 332/681] chore(Data/Matroid/Basic): a few tweaks to `Matroid.Basic` (#19836) We make a few small QOL changes to `Matroid.Basic`: - added `@[mk_iff]` to a few typeclass defs, in one case replacing the manually defined lemma with the automatic one in the places it's later used. - added a lemma about base exchanges - added a lemma proving that a `Nonempty` matroid lives in a `Nonempty` type. --- Mathlib/Data/Matroid/Basic.lean | 26 +++++++++++++++++-------- Mathlib/Data/Matroid/Constructions.lean | 4 ++-- Mathlib/Data/Matroid/Dual.lean | 2 +- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Mathlib/Data/Matroid/Basic.lean b/Mathlib/Data/Matroid/Basic.lean index 54558d4e57700..81021b42ad6b0 100644 --- a/Mathlib/Data/Matroid/Basic.lean +++ b/Mathlib/Data/Matroid/Basic.lean @@ -218,7 +218,7 @@ namespace Matroid variable {α : Type*} {M : Matroid α} /-- Typeclass for a matroid having finite ground set. Just a wrapper for `M.E.Finite`-/ -protected class Finite (M : Matroid α) : Prop where +@[mk_iff] protected class Finite (M : Matroid α) : Prop where /-- The ground set is finite -/ (ground_finite : M.E.Finite) @@ -233,6 +233,9 @@ theorem ground_nonempty (M : Matroid α) [M.Nonempty] : M.E.Nonempty := theorem ground_nonempty_iff (M : Matroid α) : M.E.Nonempty ↔ M.Nonempty := ⟨fun h ↦ ⟨h⟩, fun ⟨h⟩ ↦ h⟩ +lemma nonempty_type (M : Matroid α) [h : M.Nonempty] : Nonempty α := + ⟨M.ground_nonempty.some⟩ + theorem ground_finite (M : Matroid α) [M.Finite] : M.E.Finite := Finite.ground_finite @@ -243,7 +246,7 @@ instance finite_of_finite [Finite α] {M : Matroid α} : M.Finite := ⟨Set.toFinite _⟩ /-- A `FiniteRk` matroid is one whose bases are finite -/ -class FiniteRk (M : Matroid α) : Prop where +@[mk_iff] class FiniteRk (M : Matroid α) : Prop where /-- There is a finite base -/ exists_finite_base : ∃ B, M.Base B ∧ B.Finite @@ -251,17 +254,16 @@ instance finiteRk_of_finite (M : Matroid α) [M.Finite] : FiniteRk M := ⟨M.exists_base.imp (fun B hB ↦ ⟨hB, M.set_finite B (M.subset_ground _ hB)⟩)⟩ /-- An `InfiniteRk` matroid is one whose bases are infinite. -/ -class InfiniteRk (M : Matroid α) : Prop where +@[mk_iff] class InfiniteRk (M : Matroid α) : Prop where /-- There is an infinite base -/ exists_infinite_base : ∃ B, M.Base B ∧ B.Infinite /-- A `RkPos` matroid is one whose bases are nonempty. -/ -class RkPos (M : Matroid α) : Prop where +@[mk_iff] class RkPos (M : Matroid α) : Prop where /-- The empty set isn't a base -/ empty_not_base : ¬M.Base ∅ -theorem rkPos_iff_empty_not_base : M.RkPos ↔ ¬M.Base ∅ := - ⟨fun ⟨h⟩ ↦ h, fun h ↦ ⟨h⟩⟩ +@[deprecated (since := "2025-01-20")] alias rkPos_iff_empty_not_base := rkPos_iff section exchange namespace ExchangeProperty @@ -434,7 +436,7 @@ theorem Base.nonempty [RkPos M] (hB : M.Base B) : B.Nonempty := by rw [nonempty_iff_ne_empty]; rintro rfl; exact M.empty_not_base hB theorem Base.rkPos_of_nonempty (hB : M.Base B) (h : B.Nonempty) : M.RkPos := by - rw [rkPos_iff_empty_not_base] + rw [rkPos_iff] intro he obtain rfl := he.eq_of_subset_base hB (empty_subset B) simp at h @@ -636,6 +638,14 @@ theorem Base.exchange_base_of_indep' (hB : M.Base B) (he : e ∈ B) (hf : f ∉ rw [← insert_diff_singleton_comm hfe] at * exact hB.exchange_base_of_indep hf hI +lemma insert_base_of_insert_indep {M : Matroid α} {I : Set α} {e f : α} + (he : e ∉ I) (hf : f ∉ I) (heI : M.Base (insert e I)) (hfI : M.Indep (insert f I)) : + M.Base (insert f I) := by + obtain rfl | hef := eq_or_ne e f + · assumption + simpa [diff_singleton_eq_self he, hfI] + using heI.exchange_base_of_indep (e := e) (f := f) (by simp [hef.symm, hf]) + theorem Base.insert_dep (hB : M.Base B) (h : e ∈ M.E \ B) : M.Dep (insert e B) := by rw [← not_indep_iff (insert_subset h.1 hB.subset_ground)] exact h.2 ∘ (fun hi ↦ insert_eq_self.mp (hB.eq_of_subset_indep hi (subset_insert e B)).symm) @@ -705,7 +715,7 @@ lemma ext_base_indep {M₁ M₂ : Matroid α} (hE : M₁.E = M₂.E) (hM₁ : /-- A `Finitary` matroid is one where a set is independent if and only if it all its finite subsets are independent, or equivalently a matroid whose circuits are finite. -/ -class Finitary (M : Matroid α) : Prop where +@[mk_iff] class Finitary (M : Matroid α) : Prop where /-- `I` is independent if all its finite subsets are independent. -/ indep_of_forall_finite : ∀ I, (∀ J, J ⊆ I → J.Finite → M.Indep J) → M.Indep I diff --git a/Mathlib/Data/Matroid/Constructions.lean b/Mathlib/Data/Matroid/Constructions.lean index 2d46aa252305c..e886f458dbe70 100644 --- a/Mathlib/Data/Matroid/Constructions.lean +++ b/Mathlib/Data/Matroid/Constructions.lean @@ -123,10 +123,10 @@ theorem empty_base_iff : M.Base ∅ ↔ M = loopyOn M.E := by exact ⟨fun h I _ ↦ ⟨@h _, fun hI ↦ by simp [hI]⟩, fun h I hI ↦ (h hI.subset_ground).1 hI⟩ theorem eq_loopyOn_or_rkPos (M : Matroid α) : M = loopyOn M.E ∨ RkPos M := by - rw [← empty_base_iff, rkPos_iff_empty_not_base]; apply em + rw [← empty_base_iff, rkPos_iff]; apply em theorem not_rkPos_iff : ¬RkPos M ↔ M = loopyOn M.E := by - rw [rkPos_iff_empty_not_base, not_iff_comm, empty_base_iff] + rw [rkPos_iff, not_iff_comm, empty_base_iff] end LoopyOn diff --git a/Mathlib/Data/Matroid/Dual.lean b/Mathlib/Data/Matroid/Dual.lean index a6b523bb31bc1..4061f8c33178f 100644 --- a/Mathlib/Data/Matroid/Dual.lean +++ b/Mathlib/Data/Matroid/Dual.lean @@ -206,7 +206,7 @@ theorem base_iff_dual_base_compl (hB : B ⊆ M.E := by aesop_mat) : rw [dual_base_iff, diff_diff_cancel_left hB] theorem ground_not_base (M : Matroid α) [h : RkPos M✶] : ¬M.Base M.E := by - rwa [rkPos_iff_empty_not_base, dual_base_iff, diff_empty] at h + rwa [rkPos_iff, dual_base_iff, diff_empty] at h theorem Base.ssubset_ground [h : RkPos M✶] (hB : M.Base B) : B ⊂ M.E := hB.subset_ground.ssubset_of_ne (by rintro rfl; exact M.ground_not_base hB) From f033341c29027b524efda42ef0e579be9fbb786f Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Mon, 20 Jan 2025 15:06:09 +0000 Subject: [PATCH 333/681] feat(RingTheory): minimal primes are contained in zero divisors (#20306) --- Mathlib/RingTheory/Ideal/MinimalPrime.lean | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/Mathlib/RingTheory/Ideal/MinimalPrime.lean b/Mathlib/RingTheory/Ideal/MinimalPrime.lean index 13079f23b3398..018eb06f8338f 100644 --- a/Mathlib/RingTheory/Ideal/MinimalPrime.lean +++ b/Mathlib/RingTheory/Ideal/MinimalPrime.lean @@ -105,6 +105,59 @@ theorem Ideal.sInf_minimalPrimes : sInf I.minimalPrimes = I.radical := by intro I hI exact hI.1.symm +theorem Ideal.iUnion_minimalPrimes : + ⋃ p ∈ I.minimalPrimes, p = { x | ∃ y ∉ I.radical, x * y ∈ I.radical } := by + classical + ext x + simp only [Set.mem_iUnion, SetLike.mem_coe, exists_prop, Set.mem_setOf_eq] + constructor + · rintro ⟨p, ⟨⟨hp₁, hp₂⟩, hp₃⟩, hxp⟩ + have : p.map (algebraMap R (Localization.AtPrime p)) ≤ (I.map (algebraMap _ _)).radical := by + rw [Ideal.radical_eq_sInf, le_sInf_iff] + rintro q ⟨hq', hq⟩ + obtain ⟨h₁, h₂⟩ := ((IsLocalization.AtPrime.orderIsoOfPrime _ p) ⟨q, hq⟩).2 + rw [Ideal.map_le_iff_le_comap] at hq' ⊢ + exact hp₃ ⟨h₁, hq'⟩ h₂ + obtain ⟨n, hn⟩ := this (Ideal.mem_map_of_mem _ hxp) + rw [IsLocalization.mem_map_algebraMap_iff (M := p.primeCompl)] at hn + obtain ⟨⟨a, b⟩, hn⟩ := hn + rw [← map_pow, ← _root_.map_mul, IsLocalization.eq_iff_exists p.primeCompl] at hn + obtain ⟨t, ht⟩ := hn + refine ⟨t * b, fun h ↦ (t * b).2 (hp₁.radical_le_iff.mpr hp₂ h), n + 1, ?_⟩ + simp only at ht + have : (x * (t.1 * b.1)) ^ (n + 1) = (t.1 ^ n * b.1 ^ n * x * t.1) * a := by + rw [mul_assoc, ← ht]; ring + rw [this] + exact I.mul_mem_left _ a.2 + · rintro ⟨y, hy, hx⟩ + obtain ⟨p, hp, hyp⟩ : ∃ p ∈ I.minimalPrimes, y ∉ p := by + simpa [← Ideal.sInf_minimalPrimes] using hy + refine ⟨p, hp, (hp.1.1.mem_or_mem ?_).resolve_right hyp⟩ + exact hp.1.1.radical_le_iff.mpr hp.1.2 hx + +theorem Ideal.exists_mul_mem_of_mem_minimalPrimes + {p : Ideal R} (hp : p ∈ I.minimalPrimes) {x : R} (hx : x ∈ p) : + ∃ y ∉ I, x * y ∈ I := by + classical + obtain ⟨y, hy, n, hx⟩ := Ideal.iUnion_minimalPrimes.subset (Set.mem_biUnion hp hx) + have H : ∃ m, x ^ m * y ^ n ∈ I := ⟨n, mul_pow x y n ▸ hx⟩ + have : Nat.find H ≠ 0 := + fun h ↦ hy ⟨n, by simpa only [h, pow_zero, one_mul] using Nat.find_spec H⟩ + refine ⟨x ^ (Nat.find H - 1) * y ^ n, Nat.find_min H (Nat.sub_one_lt this), ?_⟩ + rw [← mul_assoc, ← pow_succ', tsub_add_cancel_of_le (Nat.one_le_iff_ne_zero.mpr this)] + exact Nat.find_spec H + +/-- minimal primes are contained in zero divisors. -/ +lemma Ideal.disjoint_nonZeroDivisors_of_mem_minimalPrimes {p : Ideal R} (hp : p ∈ minimalPrimes R) : + Disjoint (p : Set R) (nonZeroDivisors R) := by + classical + rw [← Set.subset_compl_iff_disjoint_right, Set.subset_def] + simp only [SetLike.mem_coe, Set.mem_compl_iff, mem_nonZeroDivisors_iff, not_forall, + Classical.not_imp] + intro x hxp + simp_rw [exists_prop, @and_comm (_ * _ = _), ← mul_comm x] + exact Ideal.exists_mul_mem_of_mem_minimalPrimes hp hxp + theorem Ideal.exists_comap_eq_of_mem_minimalPrimes_of_injective {f : R →+* S} (hf : Function.Injective f) (p) (H : p ∈ minimalPrimes R) : ∃ p' : Ideal S, p'.IsPrime ∧ p'.comap f = p := by From 3f57df84d5d9781f66f1880399a6ca1563c91f63 Mon Sep 17 00:00:00 2001 From: Chris Wong Date: Mon, 20 Jan 2025 15:19:41 +0000 Subject: [PATCH 334/681] =?UTF-8?q?feat:=20Myhill=E2=80=93Nerode=20theorem?= =?UTF-8?q?=20(#11311)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I take a different approach to the [`lean-automata` version](https://github.com/atarnoam/lean-automata/blob/main/src/regular_languages.lean) by @atarnoam. Rather than taking a `Quotient` by the Nerode relation, I instead talk about the the function `leftQuotient := fun x => { y | x ++ y ∈ L }`. This is more direct as it avoids going through the `Quotient` API. The Nerode relation can be defined later (not in this PR) as the [kernel](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Setoid/Basic.html#Setoid.ker) of this function. --- Mathlib.lean | 1 + Mathlib/Computability/MyhillNerode.lean | 103 ++++++++++++++++++++++++ docs/1000.yaml | 6 +- 3 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 Mathlib/Computability/MyhillNerode.lean diff --git a/Mathlib.lean b/Mathlib.lean index 407bb7a2cd533..b6a15d338929b 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2383,6 +2383,7 @@ import Mathlib.Computability.Encoding import Mathlib.Computability.EpsilonNFA import Mathlib.Computability.Halting import Mathlib.Computability.Language +import Mathlib.Computability.MyhillNerode import Mathlib.Computability.NFA import Mathlib.Computability.Partrec import Mathlib.Computability.PartrecCode diff --git a/Mathlib/Computability/MyhillNerode.lean b/Mathlib/Computability/MyhillNerode.lean new file mode 100644 index 0000000000000..0ab520eb65238 --- /dev/null +++ b/Mathlib/Computability/MyhillNerode.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2024 Google. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Wong +-/ +import Mathlib.Computability.DFA +import Mathlib.Data.Set.Finite.Basic + +/-! +# Myhill–Nerode theorem + +This file proves the Myhill–Nerode theorem using left quotients. + +Given a language `L` and a word `x`, the *left quotient* of `L` by `x` is the set of suffixes `y` +such that `x ++ y` is in `L`. The *Myhill–Nerode theorem* shows that each left quotient, in fact, +corresponds to the state of an automaton that matches `L`, and that `L` is regular if and only if +there are finitely many such states. + +## References + +* +-/ + +universe u v +variable {α : Type u} {σ : Type v} {L : Language α} + +namespace Language + +variable (L) in +/-- The *left quotient* of `x` is the set of suffixes `y` such that `x ++ y` is in `L`. -/ +def leftQuotient (x : List α) : Language α := { y | x ++ y ∈ L } + +variable (L) in +@[simp] +theorem leftQuotient_nil : L.leftQuotient [] = L := rfl + +variable (L) in +theorem leftQuotient_append (x y : List α) : + L.leftQuotient (x ++ y) = (L.leftQuotient x).leftQuotient y := by + simp [leftQuotient, Language] + +@[simp] +theorem mem_leftQuotient (x y : List α) : y ∈ L.leftQuotient x ↔ x ++ y ∈ L := Iff.rfl + +theorem leftQuotient_accepts_apply (M : DFA α σ) (x : List α) : + leftQuotient M.accepts x = M.acceptsFrom (M.eval x) := by + ext y + simp [DFA.mem_accepts, DFA.mem_acceptsFrom, DFA.eval, DFA.evalFrom_of_append] + +theorem leftQuotient_accepts (M : DFA α σ) : leftQuotient M.accepts = M.acceptsFrom ∘ M.eval := + funext <| leftQuotient_accepts_apply M + +theorem IsRegular.finite_range_leftQuotient (h : L.IsRegular) : + (Set.range L.leftQuotient).Finite := by + have ⟨σ, x, M, hM⟩ := h + rw [← hM, leftQuotient_accepts] + exact Set.finite_of_finite_preimage (Set.toFinite _) + (Set.range_comp_subset_range M.eval M.acceptsFrom) + +variable (L) in +/-- The left quotients of a language are the states of an automaton that accepts the language. -/ +def toDFA : DFA α (Set.range L.leftQuotient) where + step s a := by + refine ⟨s.val.leftQuotient [a], ?_⟩ + obtain ⟨y, hy⟩ := s.prop + exists y ++ [a] + rw [← hy, leftQuotient_append] + start := ⟨L, by exists []⟩ + accept := { s | [] ∈ s.val } + +@[simp] +theorem mem_accept_toDFA (s : Set.range L.leftQuotient) : s ∈ L.toDFA.accept ↔ [] ∈ s.val := Iff.rfl + +@[simp] +theorem step_toDFA (s : Set.range L.leftQuotient) (a : α) : + (L.toDFA.step s a).val = s.val.leftQuotient [a] := rfl + +variable (L) in +@[simp] +theorem start_toDFA : L.toDFA.start.val = L := rfl + +variable (L) in +@[simp] +theorem accepts_toDFA : L.toDFA.accepts = L := by + ext x + rw [DFA.mem_accepts] + suffices L.toDFA.eval x = L.leftQuotient x by simp [this] + induction x using List.list_reverse_induction with + | base => simp + | ind x a ih => simp [ih, leftQuotient_append] + +theorem IsRegular.of_finite_range_leftQuotient (h : Set.Finite (Set.range L.leftQuotient)) : + L.IsRegular := + Language.isRegular_iff.mpr ⟨_, h.fintype, L.toDFA, by simp⟩ + +/-- +**Myhill–Nerode theorem**. A language is regular if and only if the set of left quotients is finite. +-/ +theorem isRegular_iff_finite_range_leftQuotient : + L.IsRegular ↔ (Set.range L.leftQuotient).Finite := + ⟨IsRegular.finite_range_leftQuotient, .of_finite_range_leftQuotient⟩ + +end Language diff --git a/docs/1000.yaml b/docs/1000.yaml index a1aecd443a62c..d2a6645ea7a96 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -401,9 +401,9 @@ Q420714: Q422187: title: Myhill–Nerode theorem - # two in-progress formalisations, none merged as of end of 2024 - # https://github.com/atarnoam/lean-automata/blob/main/src/regular_languages.lean - # https://github.com/leanprover-community/mathlib4/pull/11311 + decl: Language.isRegular_iff_finite_range_leftQuotient + author: Chris Wong + date: 2024-03-24 Q425432: title: Laurent expansion theorem From 914ded280ba36b9fefd047679ff2e7eb562370af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 20 Jan 2025 15:19:43 +0000 Subject: [PATCH 335/681] feat: the pairs `{t, insert a t}` are pairwise disjoint (#20062) This will be used to prove the existence of symmetric chain decompositions. From LeanCamCombi --- Mathlib/Data/Finset/Basic.lean | 5 +++++ Mathlib/Data/Finset/Defs.lean | 2 ++ Mathlib/Data/Finset/Powerset.lean | 11 +++++++++++ Mathlib/Data/Set/Basic.lean | 17 +++++++++++++---- Mathlib/Data/Set/Pairwise/Lattice.lean | 12 ++++++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index 84a285a152f6a..afb347e53972a 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -92,6 +92,11 @@ theorem disjoint_of_subset_iff_left_eq_empty (h : s ⊆ t) : Disjoint s t ↔ s = ∅ := disjoint_of_le_iff_left_eq_bot h +lemma pairwiseDisjoint_iff {ι : Type*} {s : Set ι} {f : ι → Finset α} : + s.PairwiseDisjoint f ↔ ∀ ⦃i⦄, i ∈ s → ∀ ⦃j⦄, j ∈ s → (f i ∩ f j).Nonempty → i = j := by + simp [Set.PairwiseDisjoint, Set.Pairwise, Function.onFun, not_imp_comm (a := _ = _), + not_disjoint_iff_nonempty_inter] + end Lattice instance isDirected_le : IsDirected (Finset α) (· ≤ ·) := by classical infer_instance diff --git a/Mathlib/Data/Finset/Defs.lean b/Mathlib/Data/Finset/Defs.lean index 93ee27d0d49a1..334d0c01cd155 100644 --- a/Mathlib/Data/Finset/Defs.lean +++ b/Mathlib/Data/Finset/Defs.lean @@ -253,6 +253,8 @@ theorem mem_of_subset {s₁ s₂ : Finset α} {a : α} : s₁ ⊆ s₂ → a ∈ theorem not_mem_mono {s t : Finset α} (h : s ⊆ t) {a : α} : a ∉ t → a ∉ s := mt <| @h _ +alias not_mem_subset := not_mem_mono + theorem Subset.antisymm {s₁ s₂ : Finset α} (H₁ : s₁ ⊆ s₂) (H₂ : s₂ ⊆ s₁) : s₁ = s₂ := ext fun a => ⟨@H₁ a, @H₂ a⟩ diff --git a/Mathlib/Data/Finset/Powerset.lean b/Mathlib/Data/Finset/Powerset.lean index dc12dc7eccee3..8c387f738be55 100644 --- a/Mathlib/Data/Finset/Powerset.lean +++ b/Mathlib/Data/Finset/Powerset.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Finset.Lattice.Fold import Mathlib.Data.Multiset.Powerset +import Mathlib.Data.Set.Pairwise.Lattice /-! # The powerset of a finset @@ -93,6 +94,16 @@ theorem powerset_insert [DecidableEq α] (s : Finset α) (a : α) : · have : ¬∃ u : Finset α, u ⊆ s ∧ insert a u = t := by simp [Ne.symm (ne_insert_of_not_mem _ _ h)] simp [Finset.erase_eq_of_not_mem h, this] +lemma pairwiseDisjoint_pair_insert [DecidableEq α] {a : α} (ha : a ∉ s) : + (s.powerset : Set (Finset α)).PairwiseDisjoint fun t ↦ ({t, insert a t} : Set (Finset α)) := by + simp_rw [Set.pairwiseDisjoint_iff, mem_coe, mem_powerset] + rintro i hi j hj + simp only [Set.Nonempty, Set.mem_inter_iff, Set.mem_insert_iff, Set.mem_singleton_iff, + exists_eq_or_imp, exists_eq_left, or_imp, imp_self, true_and] + refine ⟨?_, ?_, insert_erase_invOn.2.injOn (not_mem_mono hi ha) (not_mem_mono hj ha)⟩ <;> + rintro rfl <;> + cases Finset.not_mem_mono ‹_› ha (Finset.mem_insert_self _ _) + /-- For predicate `p` decidable on subsets, it is decidable whether `p` holds for any subset. -/ instance decidableExistsOfDecidableSubsets {s : Finset α} {p : ∀ t ⊆ s, Prop} [∀ (t) (h : t ⊆ s), Decidable (p t h)] : Decidable (∃ (t : _) (h : t ⊆ s), p t h) := diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 3ca8906f367ae..8e3156f8d4973 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -956,10 +956,6 @@ theorem insert_inter_distrib (a : α) (s t : Set α) : insert a (s ∩ t) = inse theorem insert_union_distrib (a : α) (s t : Set α) : insert a (s ∪ t) = insert a s ∪ insert a t := ext fun _ => or_or_distrib_left -theorem insert_inj (ha : a ∉ s) : insert a s = insert b s ↔ a = b := - ⟨fun h => eq_of_not_mem_of_mem_insert (h ▸ mem_insert a s) ha, - congr_arg (fun x => insert x s)⟩ - -- useful in proofs by induction theorem forall_of_forall_insert {P : α → Prop} {a : α} {s : Set α} (H : ∀ x, x ∈ insert a s → P x) (x) (h : x ∈ s) : P x := @@ -1060,6 +1056,8 @@ theorem singleton_subset_iff {a : α} {s : Set α} : {a} ⊆ s ↔ a ∈ s := theorem singleton_subset_singleton : ({a} : Set α) ⊆ {b} ↔ a = b := by simp +@[gcongr] protected alias ⟨_, GCongr.singleton_subset_singleton⟩ := singleton_subset_singleton + theorem set_compr_eq_eq_singleton {a : α} : { b | b = a } = {a} := rfl @@ -1591,6 +1589,17 @@ theorem insert_diff_self_of_not_mem {a : α} {s : Set α} (h : a ∉ s) : insert ext x simp [and_iff_left_of_imp (ne_of_mem_of_not_mem · h)] +lemma insert_diff_self_of_mem (ha : a ∈ s) : insert a (s \ {a}) = s := by + ext; simp +contextual [or_and_left, em, ha] + +lemma insert_erase_invOn : + InvOn (insert a) (fun s ↦ s \ {a}) {s : Set α | a ∈ s} {s : Set α | a ∉ s} := + ⟨fun _s ha ↦ insert_diff_self_of_mem ha, fun _s ↦ insert_diff_self_of_not_mem⟩ + +theorem insert_inj (ha : a ∉ s) : insert a s = insert b s ↔ a = b := + ⟨fun h => eq_of_not_mem_of_mem_insert (h ▸ mem_insert a s) ha, + congr_arg (fun x => insert x s)⟩ + @[simp] theorem insert_diff_eq_singleton {a : α} {s : Set α} (h : a ∉ s) : insert a s \ s = {a} := by ext diff --git a/Mathlib/Data/Set/Pairwise/Lattice.lean b/Mathlib/Data/Set/Pairwise/Lattice.lean index 644704f5ff134..018037bee624d 100644 --- a/Mathlib/Data/Set/Pairwise/Lattice.lean +++ b/Mathlib/Data/Set/Pairwise/Lattice.lean @@ -133,6 +133,18 @@ section variable {f : ι → Set α} {s t : Set ι} +lemma Set.pairwiseDisjoint_iff : + s.PairwiseDisjoint f ↔ ∀ ⦃i⦄, i ∈ s → ∀ ⦃j⦄, j ∈ s → (f i ∩ f j).Nonempty → i = j := by + simp [Set.PairwiseDisjoint, Set.Pairwise, Function.onFun, not_imp_comm (a := _ = _), + not_disjoint_iff_nonempty_inter] + +lemma Set.pairwiseDisjoint_pair_insert {s : Set α} {a : α} (ha : a ∉ s) : + s.powerset.PairwiseDisjoint fun t ↦ ({t, insert a t} : Set (Set α)) := by + rw [pairwiseDisjoint_iff] + rintro i hi j hj + have := insert_erase_invOn.2.injOn (not_mem_subset hi ha) (not_mem_subset hj ha) + aesop (add simp [Set.Nonempty, Set.subset_def]) + theorem Set.PairwiseDisjoint.subset_of_biUnion_subset_biUnion (h₀ : (s ∪ t).PairwiseDisjoint f) (h₁ : ∀ i ∈ s, (f i).Nonempty) (h : ⋃ i ∈ s, f i ⊆ ⋃ i ∈ t, f i) : s ⊆ t := by rintro i hi From 981f44b2bea879297a9828fe3a00878ce23f6135 Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Mon, 20 Jan 2025 15:19:44 +0000 Subject: [PATCH 336/681] feat(RingTheory/Invariant): Galois extensions satisfy `Algebra.IsInvariant` (#20106) This PR shows that Galois extensions satisfy `Algebra.IsInvariant`. This enables the theory of Frobenius elements to be applied to Galois extensions. --- Mathlib/RingTheory/Invariant.lean | 37 ++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Mathlib/RingTheory/Invariant.lean b/Mathlib/RingTheory/Invariant.lean index 075f78efeb749..fe8623572f750 100644 --- a/Mathlib/RingTheory/Invariant.lean +++ b/Mathlib/RingTheory/Invariant.lean @@ -3,8 +3,9 @@ Copyright (c) 2024 Thomas Browning. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning -/ -import Mathlib.FieldTheory.Fixed +import Mathlib.FieldTheory.Galois.Basic import Mathlib.RingTheory.Ideal.Over +import Mathlib.RingTheory.IntegralClosure.IntegralRestrict /-! # Invariant Extensions of Rings and Frobenius Elements @@ -46,6 +47,40 @@ by `G` is `smul_algebraMap` (assuming `SMulCommClass A B G`). -/ end Algebra +section Galois + +variable (A K L B : Type*) [CommRing A] [CommRing B] [Field K] [Field L] + [Algebra A K] [Algebra B L] [IsFractionRing A K] [IsFractionRing B L] + [Algebra A B] [Algebra K L] [Algebra A L] [IsScalarTower A K L] [IsScalarTower A B L] + [IsIntegrallyClosed A] [IsIntegralClosure B A L] + +/-- In the AKLB setup, the Galois group of `L/K` acts on `B`. -/ +noncomputable def IsIntegralClosure.MulSemiringAction [Algebra.IsAlgebraic K L] : + MulSemiringAction (L ≃ₐ[K] L) B := + MulSemiringAction.compHom B (galRestrict A K L B).toMonoidHom + +/-- In the AKLB setup, every fixed point of `B` lies in the image of `A`. -/ +theorem Algebra.isInvariant_of_isGalois [FiniteDimensional K L] [h : IsGalois K L] : + letI := IsIntegralClosure.MulSemiringAction A K L B + Algebra.IsInvariant A B (L ≃ₐ[K] L) := by + replace h := ((IsGalois.tfae (F := K) (E := L)).out 0 1).mp h + letI := IsIntegralClosure.MulSemiringAction A K L B + refine ⟨fun b hb ↦ ?_⟩ + replace hb : algebraMap B L b ∈ IntermediateField.fixedField (⊤ : Subgroup (L ≃ₐ[K] L)) := by + rintro ⟨g, -⟩ + exact (algebraMap_galRestrict_apply A g b).symm.trans (congrArg (algebraMap B L) (hb g)) + rw [h, IntermediateField.mem_bot] at hb + obtain ⟨k, hk⟩ := hb + have hb : IsIntegral A b := IsIntegralClosure.isIntegral A L b + rw [← isIntegral_algebraMap_iff (NoZeroSMulDivisors.algebraMap_injective B L), ← hk, + isIntegral_algebraMap_iff (NoZeroSMulDivisors.algebraMap_injective K L)] at hb + obtain ⟨a, rfl⟩ := IsIntegrallyClosed.algebraMap_eq_of_integral hb + rw [← IsScalarTower.algebraMap_apply, IsScalarTower.algebraMap_apply A B L, + (NoZeroSMulDivisors.algebraMap_injective B L).eq_iff] at hk + exact ⟨a, hk⟩ + +end Galois + section transitivity variable (A B G : Type*) [CommRing A] [CommRing B] [Algebra A B] [Group G] [MulSemiringAction G B] From fb0f8faff15013e2e140fa7b29cd8e42fa5bef58 Mon Sep 17 00:00:00 2001 From: Yakov Pechersky Date: Mon, 20 Jan 2025 15:19:45 +0000 Subject: [PATCH 337/681] chore(Algebra/CharP): `prime_ringChar` and `isPrimePow_card` (#20860) small helper lemmas that didn't exist for finite fields --- Mathlib/Algebra/CharP/Lemmas.lean | 4 ++++ Mathlib/FieldTheory/Finite/Basic.lean | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Mathlib/Algebra/CharP/Lemmas.lean b/Mathlib/Algebra/CharP/Lemmas.lean index f5182dddfbd03..a1a94ee942c82 100644 --- a/Mathlib/Algebra/CharP/Lemmas.lean +++ b/Mathlib/Algebra/CharP/Lemmas.lean @@ -273,6 +273,10 @@ variable (R) [Ring R] [NoZeroDivisors R] [Nontrivial R] [Finite R] theorem char_is_prime (p : ℕ) [CharP R p] : p.Prime := Or.resolve_right (char_is_prime_or_zero R p) (char_ne_zero_of_finite R p) +lemma prime_ringChar : Nat.Prime (ringChar R) := by + apply CharP.char_prime_of_ne_zero R + exact CharP.ringChar_ne_zero_of_finite R + end Ring end CharP diff --git a/Mathlib/FieldTheory/Finite/Basic.lean b/Mathlib/FieldTheory/Finite/Basic.lean index 134c9b94c12f6..9f98c44c3ceac 100644 --- a/Mathlib/FieldTheory/Finite/Basic.lean +++ b/Mathlib/FieldTheory/Finite/Basic.lean @@ -249,6 +249,10 @@ theorem card' : ∃ (p : ℕ) (n : ℕ+), Nat.Prime p ∧ Fintype.card K = p ^ ( let ⟨p, hc⟩ := CharP.exists K ⟨p, @FiniteField.card K _ _ p hc⟩ +lemma isPrimePow_card : IsPrimePow (Fintype.card K) := by + obtain ⟨p, n, hp, hn⟩ := card' K + exact ⟨p, n, Nat.prime_iff.mp hp, n.prop, hn.symm⟩ + -- Porting note: this was a `simp` lemma with a 5 lines proof. theorem cast_card_eq_zero : (q : K) = 0 := by simp From 5426682c823fbfd4fa56b9652cefe627a54139ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Mon, 20 Jan 2025 15:19:46 +0000 Subject: [PATCH 338/681] feat(RingTheory/Trace): the trace from a ring `R` to itself is the identity (#20865) Proof that `Algebra.trace R R a = a`. --- Mathlib/RingTheory/Trace/Defs.lean | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Mathlib/RingTheory/Trace/Defs.lean b/Mathlib/RingTheory/Trace/Defs.lean index e351aa7d74b4a..6a3eecd5d778a 100644 --- a/Mathlib/RingTheory/Trace/Defs.lean +++ b/Mathlib/RingTheory/Trace/Defs.lean @@ -92,6 +92,13 @@ theorem trace_algebraMap_of_basis (b : Basis ι R S) (x : R) : convert Finset.sum_const x simp [-coe_lmul_eq_mul] + +/-- The trace map from `R` to itself is the identity map. -/ +@[simp] theorem trace_self : trace R R = LinearMap.id := by + ext; simpa using trace_algebraMap_of_basis (.singleton (Fin 1) R) 1 + +theorem trace_self_apply (a) : trace R R a = a := by simp + /-- If `x` is in the base field `K`, then the trace is `[L : K] * x`. (If `L` is not finite-dimensional over `K`, then `trace` and `finrank` return `0`.) From b823988b264f8fec1d1de31d2d373310d97ba239 Mon Sep 17 00:00:00 2001 From: Floris van Doorn Date: Mon, 20 Jan 2025 16:09:37 +0000 Subject: [PATCH 339/681] feat: use to_additive for Monoid.End (#19687) * Rename `Monoid.coe_one` and `Monoid.coe_mul` to `Monoid.End.coe_one` and `Monoid.End.coe_mul`, which is already the name for `AddMonoid.End`. I made the deprecations `protected` in order to not cause overloading issues. * Change some instance names to increase consistency in names (no deprecations added) --- Mathlib/Algebra/Group/Hom/Defs.lean | 55 +++++++----------------- Mathlib/Algebra/Group/Hom/End.lean | 4 +- Mathlib/Algebra/Group/Hom/Instances.lean | 12 +++--- 3 files changed, 25 insertions(+), 46 deletions(-) diff --git a/Mathlib/Algebra/Group/Hom/Defs.lean b/Mathlib/Algebra/Group/Hom/Defs.lean index 7231ae1d40d90..2ffc6457f0b71 100644 --- a/Mathlib/Algebra/Group/Hom/Defs.lean +++ b/Mathlib/Algebra/Group/Hom/Defs.lean @@ -884,17 +884,23 @@ namespace Monoid variable (M) [MulOneClass M] /-- The monoid of endomorphisms. -/ +@[to_additive "The monoid of endomorphisms.", to_additive_dont_translate] protected def End := M →* M namespace End +@[to_additive] instance instFunLike : FunLike (Monoid.End M) M M := MonoidHom.instFunLike +@[to_additive] instance instMonoidHomClass : MonoidHomClass (Monoid.End M) M M := MonoidHom.instMonoidHomClass +@[to_additive instOne] instance instOne : One (Monoid.End M) where one := .id _ +@[to_additive instMul] instance instMul : Mul (Monoid.End M) where mul := .comp -instance : Monoid (Monoid.End M) where +@[to_additive instMonoid] +instance instMonoid : Monoid (Monoid.End M) where mul := MonoidHom.comp one := MonoidHom.id M mul_assoc _ _ _ := MonoidHom.comp_assoc _ _ _ @@ -903,53 +909,24 @@ instance : Monoid (Monoid.End M) where npow n f := (npowRec n f).copy f^[n] <| by induction n <;> simp [npowRec, *] <;> rfl npow_succ _ _ := DFunLike.coe_injective <| Function.iterate_succ _ _ +@[to_additive] instance : Inhabited (Monoid.End M) := ⟨1⟩ -@[simp, norm_cast] lemma coe_pow (f : Monoid.End M) (n : ℕ) : (↑(f ^ n) : M → M) = f^[n] := rfl +@[to_additive (attr := simp, norm_cast) coe_pow] +lemma coe_pow (f : Monoid.End M) (n : ℕ) : (↑(f ^ n) : M → M) = f^[n] := rfl -end End - -@[simp] +@[to_additive (attr := simp) coe_one] theorem coe_one : ((1 : Monoid.End M) : M → M) = id := rfl -@[simp] +@[to_additive (attr := simp) coe_mul] theorem coe_mul (f g) : ((f * g : Monoid.End M) : M → M) = f ∘ g := rfl -end Monoid - -namespace AddMonoid - -variable (A : Type*) [AddZeroClass A] - -/-- The monoid of endomorphisms. -/ -protected def End := A →+ A - -namespace End - -instance instFunLike : FunLike (AddMonoid.End A) A A := AddMonoidHom.instFunLike -instance instAddMonoidHomClass : AddMonoidHomClass (AddMonoid.End A) A A := - AddMonoidHom.instAddMonoidHomClass - -instance instOne : One (AddMonoid.End A) where one := .id _ -instance instMul : Mul (AddMonoid.End A) where mul := .comp - -@[simp, norm_cast] lemma coe_one : ((1 : AddMonoid.End A) : A → A) = id := rfl - -@[simp, norm_cast] lemma coe_mul (f g : AddMonoid.End A) : (f * g : A → A) = f ∘ g := rfl - -instance monoid : Monoid (AddMonoid.End A) where - mul_assoc _ _ _ := AddMonoidHom.comp_assoc _ _ _ - mul_one := AddMonoidHom.comp_id - one_mul := AddMonoidHom.id_comp - npow n f := (npowRec n f).copy (Nat.iterate f n) <| by induction n <;> simp [npowRec, *] <;> rfl - npow_succ _ _ := DFunLike.coe_injective <| Function.iterate_succ _ _ - -@[simp, norm_cast] lemma coe_pow (f : AddMonoid.End A) (n : ℕ) : (↑(f ^ n) : A → A) = f^[n] := rfl +end End -instance : Inhabited (AddMonoid.End A) := ⟨1⟩ +@[deprecated (since := "2024-11-20")] protected alias coe_one := End.coe_one +@[deprecated (since := "2024-11-20")] protected alias coe_mul := End.coe_mul -end End -end AddMonoid +end Monoid end End diff --git a/Mathlib/Algebra/Group/Hom/End.lean b/Mathlib/Algebra/Group/Hom/End.lean index f3538c92cd2d9..faba093247ff3 100644 --- a/Mathlib/Algebra/Group/Hom/End.lean +++ b/Mathlib/Algebra/Group/Hom/End.lean @@ -38,7 +38,9 @@ lemma natCast_apply [AddCommMonoid M] (n : ℕ) (m : M) : (↑n : AddMonoid.End (ofNat(n) : AddMonoid.End M) m = n • m := rfl instance instSemiring [AddCommMonoid M] : Semiring (AddMonoid.End M) := - { AddMonoid.End.monoid M, AddMonoidHom.addCommMonoid, AddMonoid.End.instAddMonoidWithOne M with + { AddMonoid.End.instMonoid M, + AddMonoidHom.instAddCommMonoid, + AddMonoid.End.instAddMonoidWithOne M with zero_mul := fun _ => AddMonoidHom.ext fun _ => rfl, mul_zero := fun _ => AddMonoidHom.ext fun _ => AddMonoidHom.map_zero _, left_distrib := fun _ _ _ => AddMonoidHom.ext fun _ => AddMonoidHom.map_add _ _ _, diff --git a/Mathlib/Algebra/Group/Hom/Instances.lean b/Mathlib/Algebra/Group/Hom/Instances.lean index a74b5cfdf1412..eb5b76b157ba5 100644 --- a/Mathlib/Algebra/Group/Hom/Instances.lean +++ b/Mathlib/Algebra/Group/Hom/Instances.lean @@ -27,7 +27,7 @@ variable {M : Type uM} {N : Type uN} {P : Type uP} {Q : Type uQ} /-- `(M →* N)` is a `CommMonoid` if `N` is commutative. -/ @[to_additive "`(M →+ N)` is an `AddCommMonoid` if `N` is commutative."] -instance MonoidHom.commMonoid [MulOneClass M] [CommMonoid N] : +instance MonoidHom.instCommMonoid [MulOneClass M] [CommMonoid N] : CommMonoid (M →* N) where mul := (· * ·) mul_assoc := by intros; ext; apply mul_assoc @@ -47,8 +47,8 @@ instance MonoidHom.commMonoid [MulOneClass M] [CommMonoid N] : /-- If `G` is a commutative group, then `M →* G` is a commutative group too. -/ @[to_additive "If `G` is an additive commutative group, then `M →+ G` is an additive commutative group too."] -instance MonoidHom.commGroup {M G} [MulOneClass M] [CommGroup G] : CommGroup (M →* G) := - { MonoidHom.commMonoid with +instance MonoidHom.instCommGroup {M G} [MulOneClass M] [CommGroup G] : CommGroup (M →* G) := + { MonoidHom.instCommMonoid with inv := Inv.inv, div := Div.div, div_eq_mul_inv := by @@ -71,18 +71,18 @@ instance MonoidHom.commGroup {M G} [MulOneClass M] [CommGroup G] : CommGroup (M simp [zpow_natCast, -Int.natCast_add] } instance AddMonoid.End.instAddCommMonoid [AddCommMonoid M] : AddCommMonoid (AddMonoid.End M) := - AddMonoidHom.addCommMonoid + AddMonoidHom.instAddCommMonoid @[simp] theorem AddMonoid.End.zero_apply [AddCommMonoid M] (m : M) : (0 : AddMonoid.End M) m = 0 := rfl --- Note: `@[simp]` omitted because `(1 : AddMonoid.End M) = id` by `AddMonoid.coe_one` +-- Note: `@[simp]` omitted because `(1 : AddMonoid.End M) = id` by `AddMonoid.End.coe_one` theorem AddMonoid.End.one_apply [AddCommMonoid M] (m : M) : (1 : AddMonoid.End M) m = m := rfl instance AddMonoid.End.instAddCommGroup [AddCommGroup M] : AddCommGroup (AddMonoid.End M) := - AddMonoidHom.addCommGroup + AddMonoidHom.instAddCommGroup instance AddMonoid.End.instIntCast [AddCommGroup M] : IntCast (AddMonoid.End M) := { intCast := fun z => z • (1 : AddMonoid.End M) } From 9ebb5ca0fb6cde0dee787c4eacb7237e5e384958 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:09:38 +0000 Subject: [PATCH 340/681] feat(Data/Matroid/Restrict): added a few matroid restriction lemmas (#19838) We add a few qol lemmas to `Matroid.Restrict`, specifically - a lemma about `Basis'` and `Basis` in the restriction to `univ`. - iff versions of lemmas about independence/bases with a `Matroid.Restriction` assumption. - a `Finset` version of the independence augmentation lemma. --- Mathlib/Data/Matroid/Restrict.lean | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Mathlib/Data/Matroid/Restrict.lean b/Mathlib/Data/Matroid/Restrict.lean index 1eed5c8f2b783..fbb0716dcb9e3 100644 --- a/Mathlib/Data/Matroid/Restrict.lean +++ b/Mathlib/Data/Matroid/Restrict.lean @@ -195,6 +195,9 @@ theorem basis_restrict_iff (hR : R ⊆ M.E := by aesop_mat) : intro hXR rw [← basis'_iff_basis_inter_ground, basis'_iff_basis] +lemma basis'_iff_basis_restrict_univ : M.Basis' I X ↔ (M ↾ univ).Basis I X := by + rw [basis_restrict_iff', basis'_iff_basis_inter_ground, and_iff_left (subset_univ _)] + theorem restrict_eq_restrict_iff (M M' : Matroid α) (X : Set α) : M ↾ X = M' ↾ X ↔ ∀ I, I ⊆ X → (M.Indep I ↔ M'.Indep I) := by refine ⟨fun h I hIX ↦ ?_, fun h ↦ ext_indep rfl fun I (hI : I ⊆ X) ↦ ?_⟩ @@ -354,6 +357,9 @@ theorem Indep.of_restriction (hI : N.Indep I) (hNM : N ≤r M) : M.Indep I := by theorem Indep.indep_restriction (hI : M.Indep I) (hNM : N ≤r M) (hIN : I ⊆ N.E) : N.Indep I := by obtain ⟨R, -, rfl⟩ := hNM; simpa [hI] +theorem Restriction.indep_iff (hMN : N ≤r M) : N.Indep I ↔ M.Indep I ∧ I ⊆ N.E := + ⟨fun h ↦ ⟨h.of_restriction hMN, h.subset_ground⟩, fun h ↦ h.1.indep_restriction hMN h.2⟩ + theorem Basis.basis_restriction (hI : M.Basis I X) (hNM : N ≤r M) (hX : X ⊆ N.E) : N.Basis I X := by obtain ⟨R, hR, rfl⟩ := hNM; rwa [basis_restrict_iff, and_iff_left (show X ⊆ R from hX)] @@ -363,6 +369,13 @@ theorem Basis.of_restriction (hI : N.Basis I X) (hNM : N ≤r M) : M.Basis I X : theorem Base.basis_of_restriction (hI : N.Base I) (hNM : N ≤r M) : M.Basis I N.E := by obtain ⟨R, hR, rfl⟩ := hNM; rwa [base_restrict_iff] at hI +theorem Restriction.base_iff (hMN : N ≤r M) {B : Set α} : N.Base B ↔ M.Basis B N.E := + ⟨fun h ↦ Base.basis_of_restriction h hMN, + fun h ↦ by simpa [hMN.eq_restrict] using h.restrict_base⟩ + +theorem Restriction.basis_iff (hMN : N ≤r M) : N.Basis I X ↔ M.Basis I X ∧ X ⊆ N.E := + ⟨fun h ↦ ⟨h.of_restriction hMN, h.subset_ground⟩, fun h ↦ h.1.basis_restriction hMN h.2⟩ + theorem Dep.of_restriction (hX : N.Dep X) (hNM : N ≤r M) : M.Dep X := by obtain ⟨R, hR, rfl⟩ := hNM rw [restrict_dep_iff] at hX @@ -372,6 +385,9 @@ theorem Dep.dep_restriction (hX : M.Dep X) (hNM : N ≤r M) (hXE : X ⊆ N.E := N.Dep X := by obtain ⟨R, -, rfl⟩ := hNM; simpa [hX.not_indep] +theorem Restriction.dep_iff (hMN : N ≤r M) : N.Dep X ↔ M.Dep X ∧ X ⊆ N.E := + ⟨fun h ↦ ⟨h.of_restriction hMN, h.subset_ground⟩, fun h ↦ h.1.dep_restriction hMN h.2⟩ + end Restriction /-! @@ -440,6 +456,12 @@ theorem Indep.augment (hI : M.Indep I) (hJ : M.Indep J) (hIJ : I.encard < J.enca rw [← hJ'.encard_eq_encard hb] at hIJ exact hIJ.not_le (encard_mono hJJ') +lemma Indep.augment_finset {I J : Finset α} (hI : M.Indep I) (hJ : M.Indep J) + (hIJ : I.card < J.card) : ∃ e ∈ J, e ∉ I ∧ M.Indep (insert e I) := by + obtain ⟨x, hx, hxI⟩ := hI.augment hJ (by simpa [encard_eq_coe_toFinset_card] ) + simp only [mem_diff, Finset.mem_coe] at hx + exact ⟨x, hx.1, hx.2, hxI⟩ + end Basis end Matroid From 006641492734e60b369ac830260c46c2dcdb7342 Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Mon, 20 Jan 2025 16:09:40 +0000 Subject: [PATCH 341/681] feat(Analysis/Pow/Deriv): add some results about differentiability of cpow (#19944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add several results that exists for `rpow` but not for `cpow`: - * `DifferentiableAt.cpow_const`, `DifferentiableWithinAt.cpow_const` and `DifferentiableOn.cpow_const` about the differentiability of `z ↦ (f z) ^ c` - * `Complex.deriv_cpow_const` and `deriv_cpow_const` for computing `deriv` * Add also an alternate version of `hasDerivAt_ofReal_cpow` on the differentiability of `fun y : ℝ => (y : ℂ) ^ c` and the corresponding `DifferentiableAt` and `deriv` results that follow. * Add the equivalent for `fun y : ℝ => (y : ℂ) ^ c` of `isTheta_deriv_rpow_const_atTop` and `isBigO_deriv_rpow_const_atTop` This PR doesn't add new maths since all the results proved are direct consequences of existing results. Co-authored-by: Xavier Roblot <46200072+xroblot@users.noreply.github.com> --- .../Analysis/SpecialFunctions/Integrals.lean | 4 +- .../Analysis/SpecialFunctions/Pow/Deriv.lean | 64 ++++++++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/Mathlib/Analysis/SpecialFunctions/Integrals.lean b/Mathlib/Analysis/SpecialFunctions/Integrals.lean index 23f0796e7d2ac..ee0b68c3a430b 100644 --- a/Mathlib/Analysis/SpecialFunctions/Integrals.lean +++ b/Mathlib/Analysis/SpecialFunctions/Integrals.lean @@ -353,7 +353,7 @@ theorem integral_cpow {r : ℂ} (h : -1 < r.re ∨ r ≠ -1 ∧ (0 : ℝ) ∉ [[ by_cases hab : (0 : ℝ) ∉ [[a, b]] · apply integral_eq_sub_of_hasDerivAt (fun x hx => ?_) (intervalIntegrable_cpow (r := r) <| Or.inr hab) - refine hasDerivAt_ofReal_cpow (ne_of_mem_of_not_mem hx hab) ?_ + refine hasDerivAt_ofReal_cpow_const' (ne_of_mem_of_not_mem hx hab) ?_ contrapose! hr; rwa [add_eq_zero_iff_eq_neg] replace h : -1 < r.re := by tauto suffices ∀ c : ℝ, (∫ x : ℝ in (0)..c, (x : ℂ) ^ r) = @@ -365,7 +365,7 @@ theorem integral_cpow {r : ℂ} (h : -1 < r.re ∨ r ≠ -1 ∧ (0 : ℝ) ∉ [[ apply integral_eq_sub_of_hasDeriv_right · refine ((Complex.continuous_ofReal_cpow_const ?_).div_const _).continuousOn rwa [Complex.add_re, Complex.one_re, ← neg_lt_iff_pos_add] - · refine fun x hx => (hasDerivAt_ofReal_cpow ?_ ?_).hasDerivWithinAt + · refine fun x hx => (hasDerivAt_ofReal_cpow_const' ?_ ?_).hasDerivWithinAt · rcases le_total c 0 with (hc | hc) · rw [max_eq_left hc] at hx; exact hx.2.ne · rw [min_eq_left hc] at hx; exact hx.1.ne' diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean index 5dd15f48d3220..901b5b2038c02 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean @@ -105,6 +105,10 @@ theorem DifferentiableAt.const_cpow (hf : DifferentiableAt ℂ f x) (h0 : c ≠ DifferentiableAt ℂ (fun x => c ^ f x) x := (hf.hasFDerivAt.const_cpow h0).differentiableAt +theorem DifferentiableAt.cpow_const (hf : DifferentiableAt ℂ f x) (h0 : f x ∈ slitPlane) : + DifferentiableAt ℂ (fun x => f x ^ c) x := + hf.cpow (differentiableAt_const c) h0 + theorem DifferentiableWithinAt.cpow (hf : DifferentiableWithinAt ℂ f s x) (hg : DifferentiableWithinAt ℂ g s x) (h0 : f x ∈ slitPlane) : DifferentiableWithinAt ℂ (fun x => f x ^ g x) s x := @@ -114,6 +118,11 @@ theorem DifferentiableWithinAt.const_cpow (hf : DifferentiableWithinAt ℂ f s x (h0 : c ≠ 0 ∨ f x ≠ 0) : DifferentiableWithinAt ℂ (fun x => c ^ f x) s x := (hf.hasFDerivWithinAt.const_cpow h0).differentiableWithinAt +theorem DifferentiableWithinAt.cpow_const (hf : DifferentiableWithinAt ℂ f s x) + (h0 : f x ∈ slitPlane) : + DifferentiableWithinAt ℂ (fun x => f x ^ c) s x := + hf.cpow (differentiableWithinAt_const c) h0 + theorem DifferentiableOn.cpow (hf : DifferentiableOn ℂ f s) (hg : DifferentiableOn ℂ g s) (h0 : Set.MapsTo f s slitPlane) : DifferentiableOn ℂ (fun x ↦ f x ^ g x) s := fun x hx ↦ (hf x hx).cpow (hg x hx) (h0 hx) @@ -122,6 +131,11 @@ theorem DifferentiableOn.const_cpow (hf : DifferentiableOn ℂ f s) (h0 : c ≠ 0 ∨ ∀ x ∈ s, f x ≠ 0) : DifferentiableOn ℂ (fun x ↦ c ^ f x) s := fun x hx ↦ (hf x hx).const_cpow (h0.imp_right fun h ↦ h x hx) +theorem DifferentiableOn.cpow_const (hf : DifferentiableOn ℂ f s) + (h0 : ∀ x ∈ s, f x ∈ slitPlane) : + DifferentiableOn ℂ (fun x => f x ^ c) s := + hf.cpow (differentiableOn_const c) h0 + theorem Differentiable.cpow (hf : Differentiable ℂ f) (hg : Differentiable ℂ g) (h0 : ∀ x, f x ∈ slitPlane) : Differentiable ℂ (fun x ↦ f x ^ g x) := fun x ↦ (hf x).cpow (hg x) (h0 x) @@ -204,8 +218,9 @@ theorem HasDerivWithinAt.cpow_const (hf : HasDerivWithinAt f f' s x) (Complex.hasStrictDerivAt_cpow_const h0).hasDerivAt.comp_hasDerivWithinAt x hf /-- Although `fun x => x ^ r` for fixed `r` is *not* complex-differentiable along the negative real -line, it is still real-differentiable, and the derivative is what one would formally expect. -/ -theorem hasDerivAt_ofReal_cpow {x : ℝ} (hx : x ≠ 0) {r : ℂ} (hr : r ≠ -1) : +line, it is still real-differentiable, and the derivative is what one would formally expect. +See `hasDerivAt_ofReal_cpow_const` for an alternate formulation. -/ +theorem hasDerivAt_ofReal_cpow_const' {x : ℝ} (hx : x ≠ 0) {r : ℂ} (hr : r ≠ -1) : HasDerivAt (fun y : ℝ => (y : ℂ) ^ (r + 1) / (r + 1)) (x ^ r) x := by rw [Ne, ← add_eq_zero_iff_eq_neg, ← Ne] at hr rcases lt_or_gt_of_ne hx.symm with (hx | hx) @@ -248,6 +263,51 @@ theorem hasDerivAt_ofReal_cpow {x : ℝ} (hx : x ≠ 0) {r : ℂ} (hr : r ≠ -1 · exact hasDerivAt_id ((-x : ℝ) : ℂ) · simp [hx] +@[deprecated (since := "2024-12-15")] alias hasDerivAt_ofReal_cpow := hasDerivAt_ofReal_cpow_const' + +/-- An alternate formulation of `hasDerivAt_ofReal_cpow_const'`. -/ +theorem hasDerivAt_ofReal_cpow_const {x : ℝ} (hx : x ≠ 0) {r : ℂ} (hr : r ≠ 0) : + HasDerivAt (fun y : ℝ => (y : ℂ) ^ r) (r * x ^ (r - 1)) x := by + have := HasDerivAt.const_mul r <| hasDerivAt_ofReal_cpow_const' hx + (by rwa [ne_eq, sub_eq_neg_self]) + simpa [sub_add_cancel, mul_div_cancel₀ _ hr] using this + +/-- A version of `DifferentiableAt.cpow_const` for a real function. -/ +theorem DifferentiableAt.ofReal_cpow_const {f : ℝ → ℝ} {x : ℝ} (hf : DifferentiableAt ℝ f x) + (h0 : f x ≠ 0) (h1 : c ≠ 0) : + DifferentiableAt ℝ (fun (y : ℝ) => (f y : ℂ) ^ c) x := + (hasDerivAt_ofReal_cpow_const h0 h1).differentiableAt.comp x hf + +theorem Complex.deriv_cpow_const (hx : x ∈ Complex.slitPlane) : + deriv (fun (x : ℂ) ↦ x ^ c) x = c * x ^ (c - 1) := + (hasStrictDerivAt_cpow_const hx).hasDerivAt.deriv + +/-- A version of `Complex.deriv_cpow_const` for a real variable. -/ +theorem Complex.deriv_ofReal_cpow_const {x : ℝ} (hx : x ≠ 0) (hc : c ≠ 0) : + deriv (fun x : ℝ ↦ (x : ℂ) ^ c) x = c * x ^ (c - 1) := + (hasDerivAt_ofReal_cpow_const hx hc).deriv + +theorem deriv_cpow_const (hf : DifferentiableAt ℂ f x) (hx : f x ∈ Complex.slitPlane) : + deriv (fun (x : ℂ) ↦ f x ^ c) x = c * f x ^ (c - 1) * deriv f x := + (hf.hasDerivAt.cpow_const hx).deriv + +theorem isTheta_deriv_ofReal_cpow_const_atTop {c : ℂ} (hc : c ≠ 0) : + deriv (fun (x : ℝ) => (x : ℂ) ^ c) =Θ[atTop] fun x => x ^ (c.re - 1) := by + calc + _ =ᶠ[atTop] fun x : ℝ ↦ c * x ^ (c - 1) := by + filter_upwards [eventually_ne_atTop 0] with x hx using by rw [deriv_ofReal_cpow_const hx hc] + _ =Θ[atTop] fun x : ℝ ↦ ‖(x : ℂ) ^ (c - 1)‖ := + (Asymptotics.IsTheta.of_norm_eventuallyEq EventuallyEq.rfl).const_mul_left hc + _ =ᶠ[atTop] fun x ↦ x ^ (c.re - 1) := by + filter_upwards [eventually_gt_atTop 0] with x hx + rw [norm_eq_abs, abs_cpow_eq_rpow_re_of_pos hx, sub_re, one_re] + +theorem isBigO_deriv_ofReal_cpow_const_atTop (c : ℂ) : + deriv (fun (x : ℝ) => (x : ℂ) ^ c) =O[atTop] fun x => x ^ (c.re - 1) := by + obtain rfl | hc := eq_or_ne c 0 + · simp_rw [cpow_zero, deriv_const', Asymptotics.isBigO_zero] + · exact (isTheta_deriv_ofReal_cpow_const_atTop hc).1 + end deriv namespace Real From 8b8fcb5ba863eb53131957aefeb609a8206ce925 Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Mon, 20 Jan 2025 16:09:41 +0000 Subject: [PATCH 342/681] feat(AlgebraicGeometry): Instances regarding affine spaces (#20314) --- Mathlib/AlgebraicGeometry/AffineSpace.lean | 105 +++++++++++++++++- Mathlib/AlgebraicGeometry/Limits.lean | 5 + .../Morphisms/FinitePresentation.lean | 2 +- .../RingTheory/Spectrum/Prime/Polynomial.lean | 12 ++ 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/AffineSpace.lean b/Mathlib/AlgebraicGeometry/AffineSpace.lean index 20441b03528a1..e845edc496140 100644 --- a/Mathlib/AlgebraicGeometry/AffineSpace.lean +++ b/Mathlib/AlgebraicGeometry/AffineSpace.lean @@ -4,7 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.Algebra.MvPolynomial.Monad -import Mathlib.AlgebraicGeometry.Limits +import Mathlib.AlgebraicGeometry.Morphisms.Finite +import Mathlib.AlgebraicGeometry.Morphisms.FinitePresentation +import Mathlib.RingTheory.Spectrum.Prime.Polynomial +import Mathlib.AlgebraicGeometry.PullbackCarrier /-! # Affine space @@ -32,12 +35,12 @@ universe v u variable (n : Type v) (S : Scheme.{max u v}) local notation3 "ℤ[" n "]" => CommRingCat.of (MvPolynomial n (ULift ℤ)) -local notation3 "ℤ[" n "].{" u "}" => CommRingCat.of (MvPolynomial n (ULift.{u} ℤ)) +local notation3 "ℤ[" n "].{" u "," v "}" => CommRingCat.of (MvPolynomial n (ULift.{max u v} ℤ)) /-- `𝔸(n; S)` is the affine `n`-space over `S`. Note that `n` is an arbitrary index type (e.g. `Fin m`). -/ def AffineSpace (n : Type v) (S : Scheme.{max u v}) : Scheme.{max u v} := - pullback (terminal.from S) (terminal.from (Spec ℤ[n])) + pullback (terminal.from S) (terminal.from (Spec ℤ[n].{u, v})) namespace AffineSpace @@ -62,7 +65,7 @@ instance over : 𝔸(n; S).CanonicallyOver S where hom := pullback.fst _ _ /-- The map from the affine `n`-space over `S` to the integral model `Spec ℤ[n]`. -/ -def toSpecMvPoly : 𝔸(n; S) ⟶ Spec ℤ[n] := pullback.snd _ _ +def toSpecMvPoly : 𝔸(n; S) ⟶ Spec ℤ[n].{u, v} := pullback.snd _ _ variable {X : Scheme.{max u v}} @@ -293,6 +296,13 @@ lemma map_appTop_coord {S T : Scheme.{max u v}} (f : S ⟶ T) (i) : (map n f).appTop (coord T i) = coord S i := homOfVector_appTop_coord _ _ _ +@[reassoc (attr := simp)] +lemma map_toSpecMvPoly {S T : Scheme.{max u v}} (f : S ⟶ T) : + map n f ≫ toSpecMvPoly n T = toSpecMvPoly n S := by + apply (toSpecMvPolyIntEquiv _).injective + ext i + rw [toSpecMvPolyIntEquiv_comp, ← coord, map_appTop_coord, coord] + @[simp] lemma map_id : map n (𝟙 S) = 𝟙 𝔸(n; S) := by ext1 <;> simp @@ -321,11 +331,18 @@ lemma map_Spec_map {R S : CommRingCat.{max u v}} (φ : R ⟶ S) : CommRingCat.comp_apply, map_X] /-- The map between affine spaces over affine bases is -isomorphic to the natural map between polynomial rings. -/ +isomorphic to the natural map between polynomial rings. -/ def mapSpecMap {R S : CommRingCat.{max u v}} (φ : R ⟶ S) : Arrow.mk (map n (Spec.map φ)) ≅ Arrow.mk (Spec.map (CommRingCat.ofHom (MvPolynomial.map (σ := n) φ.hom))) := - Arrow.isoMk (SpecIso n S) (SpecIso n R) (by simp [map_Spec_map]) + Arrow.isoMk (SpecIso n S) (SpecIso n R) (by have := (SpecIso n R).inv_hom_id; simp [map_Spec_map]) + +lemma isPullback_map {S T : Scheme.{max u v}} (f : S ⟶ T) : + IsPullback (map n f) (𝔸(n; S) ↘ S) (𝔸(n; T) ↘ T) f := by + refine (IsPullback.paste_horiz_iff (.flip <| .of_hasPullback _ _) (map_over f)).mp ?_ + simp only [terminal.comp_from, ] + convert (IsPullback.of_hasPullback _ _).flip + rw [← toSpecMvPoly, ← toSpecMvPoly, map_toSpecMvPoly] /-- `𝔸(n; S)` is functorial wrt `n`. -/ def reindex {n m : Type v} (i : m → n) (S : Scheme.{max u v}) : 𝔸(n; S) ⟶ 𝔸(m; S) := @@ -369,6 +386,82 @@ def functor : (Type v)ᵒᵖ ⥤ Scheme.{max u v} ⥤ Scheme.{max u v} where map_comp f g := by ext: 2; dsimp; exact reindex_comp _ _ _ end functorial +section instances + +instance : IsAffineHom (𝔸(n; S) ↘ S) := MorphismProperty.pullback_fst _ _ inferInstance + +instance : Surjective (𝔸(n; S) ↘ S) := MorphismProperty.pullback_fst _ _ <| by + have := isIso_of_isTerminal specULiftZIsTerminal terminalIsTerminal (terminal.from _) + rw [← terminal.comp_from (Spec.map (CommRingCat.ofHom C)), + MorphismProperty.cancel_right_of_respectsIso (P := @Surjective)] + exact ⟨MvPolynomial.comap_C_surjective⟩ + +instance [Finite n] : LocallyOfFinitePresentation (𝔸(n; S) ↘ S) := + MorphismProperty.pullback_fst _ _ <| by + have := isIso_of_isTerminal specULiftZIsTerminal.{max u v} terminalIsTerminal (terminal.from _) + rw [← terminal.comp_from (Spec.map (CommRingCat.ofHom C)), + MorphismProperty.cancel_right_of_respectsIso (P := @LocallyOfFinitePresentation), + HasRingHomProperty.Spec_iff (P := @LocallyOfFinitePresentation), RingHom.FinitePresentation] + convert (inferInstanceAs (Algebra.FinitePresentation (ULift ℤ) ℤ[n])) + exact Algebra.algebra_ext _ _ fun _ ↦ rfl + +lemma isOpenMap_over : IsOpenMap (𝔸(n; S) ↘ S).base := by + show topologically @IsOpenMap _ + wlog hS : ∃ R, S = Spec R + · refine (IsLocalAtTarget.iff_of_openCover (P := topologically @IsOpenMap) S.affineCover).mpr ?_ + intro i + have := this (n := n) (S.affineCover.obj i) ⟨_, rfl⟩ + rwa [← (isPullback_map (n := n) (S.affineCover.map i)).isoPullback_hom_snd, + MorphismProperty.cancel_left_of_respectsIso (P := topologically @IsOpenMap)] at this + obtain ⟨R, rfl⟩ := hS + rw [← MorphismProperty.cancel_left_of_respectsIso (P := topologically @IsOpenMap) + (SpecIso n R).inv, SpecIso_inv_over] + exact MvPolynomial.isOpenMap_comap_C + +open MorphismProperty in +instance [IsEmpty n] : IsIso (𝔸(n; S) ↘ S) := pullback_fst + (P := isomorphisms _) _ _ <| by + rw [← terminal.comp_from (Spec.map (CommRingCat.ofHom C))] + apply IsStableUnderComposition.comp_mem + · rw [HasAffineProperty.iff_of_isAffine (P := isomorphisms _), ← isomorphisms, + ← arrow_mk_iso_iff (isomorphisms _) (arrowIsoΓSpecOfIsAffine _)] + exact ⟨inferInstance, (ConcreteCategory.isIso_iff_bijective _).mpr + ⟨C_injective n _, C_surjective _⟩⟩ + · exact isIso_of_isTerminal specULiftZIsTerminal terminalIsTerminal (terminal.from _) + +lemma isIntegralHom_over_iff_isEmpty : IsIntegralHom (𝔸(n; S) ↘ S) ↔ IsEmpty S ∨ IsEmpty n := by + constructor + · intro h + cases isEmpty_or_nonempty S + · exact .inl ‹_› + refine .inr ?_ + wlog hS : ∃ R, S = Spec R + · obtain ⟨x⟩ := ‹Nonempty S› + obtain ⟨y, hy⟩ := S.affineCover.covers x + exact this (S.affineCover.obj x) (MorphismProperty.IsStableUnderBaseChange.of_isPullback + (isPullback_map (S.affineCover.map x)) h) ⟨y⟩ ⟨_, rfl⟩ + obtain ⟨R, rfl⟩ := hS + have : Nontrivial R := (subsingleton_or_nontrivial R).resolve_left fun H ↦ + not_isEmpty_of_nonempty (Spec R) (inferInstanceAs (IsEmpty (PrimeSpectrum R))) + constructor + intro i + have := RingHom.toMorphismProperty_respectsIso_iff.mp RingHom.isIntegral_respectsIso.{max u v} + rw [← MorphismProperty.cancel_left_of_respectsIso @IsIntegralHom (SpecIso n R).inv, + SpecIso_inv_over, HasAffineProperty.iff_of_isAffine (P := @IsIntegralHom)] at h + obtain ⟨p : Polynomial R, hp, hp'⟩ := + (MorphismProperty.arrow_mk_iso_iff (RingHom.toMorphismProperty RingHom.IsIntegral) + (arrowIsoΓSpecOfIsAffine _)).mpr h.2 (X i) + have : (rename fun _ ↦ i).comp (pUnitAlgEquiv.{_, v} _).symm.toAlgHom p = 0 := by + simp [← hp', ← algebraMap_eq] + rw [AlgHom.comp_apply, map_eq_zero_iff _ (rename_injective _ (fun _ _ _ ↦ rfl))] at this + simp only [AlgEquiv.toAlgHom_eq_coe, AlgHom.coe_coe, EmbeddingLike.map_eq_zero_iff] at this + simp [this] at hp + · rintro (_ | _) <;> infer_instance + +lemma not_isIntegralHom [Nonempty S] [Nonempty n] : ¬ IsIntegralHom (𝔸(n; S) ↘ S) := by + simp [isIntegralHom_over_iff_isEmpty] + +end instances end AffineSpace diff --git a/Mathlib/AlgebraicGeometry/Limits.lean b/Mathlib/AlgebraicGeometry/Limits.lean index 6ca38222835bb..6983cda062f3b 100644 --- a/Mathlib/AlgebraicGeometry/Limits.lean +++ b/Mathlib/AlgebraicGeometry/Limits.lean @@ -38,6 +38,11 @@ noncomputable def specZIsTerminal : IsTerminal (Spec (CommRingCat.of ℤ)) := @IsTerminal.isTerminalObj _ _ _ _ Scheme.Spec _ inferInstance (terminalOpOfInitial CommRingCat.zIsInitial) +/-- `Spec ℤ` is the terminal object in the category of schemes. -/ +noncomputable def specULiftZIsTerminal : IsTerminal (Spec (.of (ULift.{u} ℤ))) := + @IsTerminal.isTerminalObj _ _ _ _ Scheme.Spec _ inferInstance + (terminalOpOfInitial CommRingCat.isInitial) + instance : HasTerminal Scheme := hasTerminal_of_hasTerminal_of_preservesLimit Scheme.Spec diff --git a/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean b/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean index 4c3998ab096ac..dc98b92581f92 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean @@ -59,7 +59,7 @@ instance locallyOfFinitePresentation_comp {X Y Z : Scheme.{u}} (f : X ⟶ Y) (g LocallyOfFinitePresentation (f ≫ g) := MorphismProperty.comp_mem _ f g hf hg -lemma locallyOfFinitePresentation_isStableUnderBaseChange : +instance locallyOfFinitePresentation_isStableUnderBaseChange : MorphismProperty.IsStableUnderBaseChange @LocallyOfFinitePresentation := HasRingHomProperty.isStableUnderBaseChange RingHom.finitePresentation_isStableUnderBaseChange diff --git a/Mathlib/RingTheory/Spectrum/Prime/Polynomial.lean b/Mathlib/RingTheory/Spectrum/Prime/Polynomial.lean index ef44d600253f3..7dfebf9a5be4b 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Polynomial.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Polynomial.lean @@ -161,6 +161,12 @@ lemma isOpenMap_comap_C : IsOpenMap (comap (R := R) C) := by simp only [image_comap_C_basicOpen] exact (isClosed_zeroLocus _).isOpen_compl +lemma comap_C_surjective : Function.Surjective (comap (R := R) C) := by + intro x + refine ⟨comap (evalRingHom 0) x, ?_⟩ + rw [← comap_comp_apply, (show (evalRingHom 0).comp C = .id R by ext; simp), + comap_id, ContinuousMap.id_apply] + lemma exists_image_comap_of_monic (f g : R[X]) (hg : g.Monic) : ∃ t : Finset R, comap C '' (zeroLocus {g} \ zeroLocus {f}) = (zeroLocus t)ᶜ := by apply (config := { allowSynthFailures := true }) exists_image_comap_of_finite_of_free @@ -218,4 +224,10 @@ lemma isOpenMap_comap_C : IsOpenMap (comap (R := R) (C (σ := σ))) := by simp only [image_comap_C_basicOpen] exact (isClosed_zeroLocus _).isOpen_compl +lemma comap_C_surjective : Function.Surjective (comap (R := R) (C (σ := σ))) := by + intro x + refine ⟨comap (eval₂Hom (.id _) 0) x, ?_⟩ + rw [← comap_comp_apply, (show (eval₂Hom (.id _) 0).comp C = .id R by ext; simp), + comap_id, ContinuousMap.id_apply] + end MvPolynomial From 80485942f29bdd2ea5d99608ea2268b82b3002ce Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Mon, 20 Jan 2025 16:09:43 +0000 Subject: [PATCH 343/681] feat(AlgebraicGeometry): Formally unramified morphisms (#20603) Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib.lean | 1 + .../Morphisms/AffineAnd.lean | 8 +- .../AlgebraicGeometry/Morphisms/Finite.lean | 2 +- .../Morphisms/FormallyUnramified.lean | 99 +++++++++++++++++++ .../AlgebraicGeometry/Morphisms/Integral.lean | 2 +- .../Morphisms/OpenImmersion.lean | 33 +++++++ 6 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 Mathlib/AlgebraicGeometry/Morphisms/FormallyUnramified.lean diff --git a/Mathlib.lean b/Mathlib.lean index b6a15d338929b..6d13b7b8f9c00 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1021,6 +1021,7 @@ import Mathlib.AlgebraicGeometry.Morphisms.Finite import Mathlib.AlgebraicGeometry.Morphisms.FinitePresentation import Mathlib.AlgebraicGeometry.Morphisms.FiniteType import Mathlib.AlgebraicGeometry.Morphisms.Flat +import Mathlib.AlgebraicGeometry.Morphisms.FormallyUnramified import Mathlib.AlgebraicGeometry.Morphisms.Immersion import Mathlib.AlgebraicGeometry.Morphisms.Integral import Mathlib.AlgebraicGeometry.Morphisms.IsIso diff --git a/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean b/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean index 54716daaae092..63edc5c703b73 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean @@ -56,7 +56,7 @@ lemma affineAnd_respectsIso (hP : RingHom.RespectsIso Q) : simpa [AffineTargetMorphismProperty.toProperty, isAffine_of_isIso e.inv, hP.cancel_left_isIso] /-- `affineAnd P` is local if `P` is local on the (algebraic) source. -/ -lemma affineAnd_isLocal (hPi : RingHom.RespectsIso Q) (hQl : RingHom.LocalizationPreserves Q) +lemma affineAnd_isLocal (hPi : RingHom.RespectsIso Q) (hQl : RingHom.LocalizationAwayPreserves Q) (hQs : RingHom.OfLocalizationSpan Q) : (affineAnd Q).IsLocal where respectsIso := affineAnd_respectsIso hPi to_basicOpen {X Y _} f r := fun ⟨hX, hf⟩ ↦ by @@ -96,6 +96,10 @@ lemma affineAnd_isLocal (hPi : RingHom.RespectsIso Q) (hQl : RingHom.Localizatio rw [(isAffineOpen_top Y).app_basicOpen_eq_away_map _ (isAffineOpen_top X)] at hf rwa [CommRingCat.hom_comp, hPi.cancel_right_isIso] at hf +lemma affineAnd_isLocal_of_propertyIsLocal + (hPi : RingHom.PropertyIsLocal Q) : (affineAnd Q).IsLocal := + affineAnd_isLocal hPi.respectsIso hPi.localizationAwayPreserves hPi.ofLocalizationSpan + /-- If `P` is stable under base change, so is `affineAnd P`. -/ lemma affineAnd_isStableUnderBaseChange (hQi : RingHom.RespectsIso Q) (hQb : RingHom.IsStableUnderBaseChange Q) : @@ -219,7 +223,7 @@ lemma HasAffineProperty.affineAnd_containsIdentities {P : MorphismProperty Schem /-- A convenience constructor for `HasAffineProperty P (affineAnd Q)`. The `IsAffineHom` is bundled, since this goes well with defining morphism properties via `extends IsAffineHom`. -/ lemma HasAffineProperty.affineAnd_iff (P : MorphismProperty Scheme.{u}) - (hQi : RingHom.RespectsIso Q) (hQl : RingHom.LocalizationPreserves Q) + (hQi : RingHom.RespectsIso Q) (hQl : RingHom.LocalizationAwayPreserves Q) (hQs : RingHom.OfLocalizationSpan Q) : HasAffineProperty P (affineAnd Q) ↔ ∀ {X Y : Scheme.{u}} (f : X ⟶ Y), P f ↔ diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean b/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean index dcef9ad69d7b4..c674ed3fe7590 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean @@ -41,7 +41,7 @@ instance : HasAffineProperty @IsFinite (fun X _ f _ ↦ IsAffine X ∧ RingHom.Finite (f.appTop).hom) := by show HasAffineProperty @IsFinite (affineAnd RingHom.Finite) rw [HasAffineProperty.affineAnd_iff _ RingHom.finite_respectsIso - RingHom.finite_localizationPreserves RingHom.finite_ofLocalizationSpan] + RingHom.finite_localizationPreserves.away RingHom.finite_ofLocalizationSpan] simp [isFinite_iff] instance : IsStableUnderComposition @IsFinite := diff --git a/Mathlib/AlgebraicGeometry/Morphisms/FormallyUnramified.lean b/Mathlib/AlgebraicGeometry/Morphisms/FormallyUnramified.lean new file mode 100644 index 0000000000000..4182443309f6f --- /dev/null +++ b/Mathlib/AlgebraicGeometry/Morphisms/FormallyUnramified.lean @@ -0,0 +1,99 @@ +/- +Copyright (c) 2025 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.AlgebraicGeometry.Morphisms.RingHomProperties +import Mathlib.AlgebraicGeometry.Morphisms.OpenImmersion +import Mathlib.RingTheory.RingHom.Unramified + +/-! +# Formally unramified morphisms + +A morphism of schemes `f : X ⟶ Y` is formally unramified if for each affine `U ⊆ Y` and +`V ⊆ f ⁻¹' U`, the induced map `Γ(Y, U) ⟶ Γ(X, V)` is formally unramified. + +We show that these properties are local, and are stable under compositions and base change. + +-/ + + +noncomputable section + +open CategoryTheory CategoryTheory.Limits Opposite TopologicalSpace + +universe v u + +namespace AlgebraicGeometry + +variable {X Y : Scheme.{u}} (f : X ⟶ Y) + +/-- A morphism of schemes `f : X ⟶ Y` is formally unramified if for each affine `U ⊆ Y` and +`V ⊆ f ⁻¹' U`, The induced map `Γ(Y, U) ⟶ Γ(X, V)` is formally unramified. -/ +@[mk_iff] +class FormallyUnramified (f : X ⟶ Y) : Prop where + formallyUnramified_of_affine_subset : + ∀ (U : Y.affineOpens) (V : X.affineOpens) (e : V.1 ≤ f ⁻¹ᵁ U.1), + (f.appLE U V e).hom.FormallyUnramified + +namespace FormallyUnramified + +instance : HasRingHomProperty @FormallyUnramified RingHom.FormallyUnramified where + isLocal_ringHomProperty := RingHom.FormallyUnramified.propertyIsLocal + eq_affineLocally' := by + ext X Y f + rw [formallyUnramified_iff, affineLocally_iff_affineOpens_le] + +instance : MorphismProperty.IsStableUnderComposition @FormallyUnramified := + HasRingHomProperty.stableUnderComposition RingHom.FormallyUnramified.stableUnderComposition + +/-- `f : X ⟶ S` is formally unramified if `X ⟶ X ×ₛ X` is an open immersion. +In particular, monomorphisms (e.g. immersions) are formally unramified. +The converse is true if `f` is locally of finite type. -/ +instance (priority := 900) [IsOpenImmersion (pullback.diagonal f)] : FormallyUnramified f := by + wlog hY : ∃ R, Y = Spec R + · rw [IsLocalAtTarget.iff_of_openCover (P := @FormallyUnramified) Y.affineCover] + intro i + have inst : IsOpenImmersion (pullback.diagonal (pullback.snd f (Y.affineCover.map i))) := + MorphismProperty.pullback_snd (P := .diagonal @IsOpenImmersion) _ _ ‹_› + exact this (pullback.snd _ _) ⟨_, rfl⟩ + obtain ⟨R, rfl⟩ := hY + wlog hX : ∃ S, X = Spec S generalizing X + · rw [IsLocalAtSource.iff_of_openCover (P := @FormallyUnramified) X.affineCover] + intro i + have inst : IsOpenImmersion (pullback.diagonal (X.affineCover.map i ≫ f)) := + MorphismProperty.comp_mem (.diagonal @IsOpenImmersion) _ _ + (inferInstanceAs (IsOpenImmersion _)) ‹_› + exact this (_ ≫ _) ⟨_, rfl⟩ + obtain ⟨S, rfl⟩ := hX + obtain ⟨φ, rfl : Spec.map φ = f⟩ := Spec.homEquiv.symm.surjective f + rw [HasRingHomProperty.Spec_iff (P := @FormallyUnramified)] + algebraize [φ.hom] + let F := (Algebra.TensorProduct.lmul' R (S := S)).toRingHom + have hF : Function.Surjective F := fun x ↦ ⟨.mk _ _ _ x 1, by simp [F]⟩ + have : IsOpenImmersion (Spec.map (CommRingCat.ofHom F)) := by + rwa [← MorphismProperty.cancel_right_of_respectsIso (P := @IsOpenImmersion) _ + (pullbackSpecIso R S S).inv, ← AlgebraicGeometry.diagonal_Spec_map R S] + obtain ⟨e, he, he'⟩ := (isOpenImmersion_SpecMap_iff_of_surjective _ hF).mp this + refine ⟨subsingleton_of_forall_eq 0 fun x ↦ ?_⟩ + obtain ⟨⟨x, hx⟩, rfl⟩ := Ideal.toCotangent_surjective _ x + obtain ⟨x, rfl⟩ := Ideal.mem_span_singleton.mp (he'.le hx) + refine (Ideal.toCotangent_eq_zero _ _).mpr ?_ + rw [pow_two, Subtype.coe_mk, ← he, mul_assoc] + exact Ideal.mul_mem_mul (he'.ge (Ideal.mem_span_singleton_self e)) hx + +theorem of_comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) + [FormallyUnramified (f ≫ g)] : FormallyUnramified f := + HasRingHomProperty.of_comp (fun {R S T _ _ _} f g H ↦ by + algebraize [f, g, g.comp f] + exact Algebra.FormallyUnramified.of_comp R S T) ‹_› + +instance : MorphismProperty.IsMultiplicative @FormallyUnramified where + id_mem _ := inferInstance + +instance : MorphismProperty.IsStableUnderBaseChange @FormallyUnramified := + HasRingHomProperty.isStableUnderBaseChange RingHom.FormallyUnramified.isStableUnderBaseChange + +end FormallyUnramified + +end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Integral.lean b/Mathlib/AlgebraicGeometry/Morphisms/Integral.lean index c6a2c5393bdfa..72aed7577ed99 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Integral.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Integral.lean @@ -42,7 +42,7 @@ instance hasAffineProperty : HasAffineProperty @IsIntegralHom fun X _ f _ ↦ IsAffine X ∧ RingHom.IsIntegral (f.app ⊤).hom := by show HasAffineProperty @IsIntegralHom (affineAnd RingHom.IsIntegral) rw [HasAffineProperty.affineAnd_iff _ RingHom.isIntegral_respectsIso - RingHom.isIntegral_isStableUnderBaseChange.localizationPreserves + RingHom.isIntegral_isStableUnderBaseChange.localizationPreserves.away RingHom.isIntegral_ofLocalizationSpan] simp [isIntegralHom_iff] diff --git a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean index 3b9e3811ca311..60ffa081d3d76 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean @@ -26,6 +26,39 @@ universe u namespace AlgebraicGeometry +/-- `Spec (R ⧸ I) ⟶ Spec R` is an open immersion iff `I` is generated by an idempotent. -/ +lemma isOpenImmersion_SpecMap_iff_of_surjective {R S : CommRingCat} + (f : R ⟶ S) (hf : Function.Surjective f.hom) : + IsOpenImmersion (Spec.map f) ↔ + ∃ e, IsIdempotentElem e ∧ RingHom.ker f.hom = Ideal.span {e} := by + constructor + · intro H + obtain ⟨e, he, he'⟩ := PrimeSpectrum.isClopen_iff_zeroLocus.mp + ⟨PrimeSpectrum.isClosed_range_comap_of_surjective _ _ hf, + (Spec.map f).isOpenEmbedding.isOpen_range⟩ + refine ⟨e, he, ?_⟩ + let φ : R ⟶ _ := (CommRingCat.ofHom (Ideal.Quotient.mk (.span {e}))) + have : IsOpenImmersion (Spec.map φ) := + have : IsLocalization.Away (1 - e) (↑R ⧸ Ideal.span {e}) := + IsLocalization.away_of_isIdempotentElem he.one_sub (by simp) Ideal.Quotient.mk_surjective + IsOpenImmersion.of_isLocalization (1 - e) + have H : Set.range (Spec.map φ).base = Set.range (Spec.map f).base := + ((PrimeSpectrum.range_comap_of_surjective _ _ + Ideal.Quotient.mk_surjective).trans (by simp [φ])).trans he'.symm + let i : S ≅ .of _ := (Scheme.Spec.preimageIso + (IsOpenImmersion.isoOfRangeEq (Spec.map φ) (Spec.map f) H)).unop + have hi : Function.Injective i.inv.hom := (ConcreteCategory.bijective_of_isIso i.inv).1 + have : f = φ ≫ i.inv := by apply Spec.map_injective; simp [i, ← Scheme.Spec_map] + rw [this, CommRingCat.hom_comp, RingHom.ker_eq_comap_bot, ← Ideal.comap_comap, + ← RingHom.ker_eq_comap_bot, (RingHom.injective_iff_ker_eq_bot i.inv.hom).mp hi, + ← RingHom.ker_eq_comap_bot] + simp [φ] + · rintro ⟨e, he, he'⟩ + letI := f.hom.toAlgebra + have : IsLocalization.Away (1 - e) S := + IsLocalization.away_of_isIdempotentElem he.one_sub (by simpa using he') hf + exact IsOpenImmersion.of_isLocalization (1 - e) + variable {X Y : Scheme.{u}} theorem isOpenImmersion_iff_stalk {f : X ⟶ Y} : IsOpenImmersion f ↔ From 4e3f39f83ba8248e3374e83e23eec2128ff3bea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 20 Jan 2025 16:09:44 +0000 Subject: [PATCH 344/681] feat(CategoryTheory/Localization): HasLocalization holds iff the localized category is locally small (#20670) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this file, given `W : MorphismProperty C` and a universe `w`, we show that there exists a term in `HasLocaliaation.{w} W` if and only if there exists (or for all) localization functors `L : C ⥤ D` for `W`, the category `D` is locally `w`-small. Co-authored-by: Johan Commelin --- Mathlib.lean | 1 + .../Localization/LocallySmall.lean | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 Mathlib/CategoryTheory/Localization/LocallySmall.lean diff --git a/Mathlib.lean b/Mathlib.lean index 6d13b7b8f9c00..f16130975e6c6 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2014,6 +2014,7 @@ import Mathlib.CategoryTheory.Localization.FiniteProducts import Mathlib.CategoryTheory.Localization.HasLocalization import Mathlib.CategoryTheory.Localization.HomEquiv import Mathlib.CategoryTheory.Localization.LocalizerMorphism +import Mathlib.CategoryTheory.Localization.LocallySmall import Mathlib.CategoryTheory.Localization.Opposite import Mathlib.CategoryTheory.Localization.Pi import Mathlib.CategoryTheory.Localization.Predicate diff --git a/Mathlib/CategoryTheory/Localization/LocallySmall.lean b/Mathlib/CategoryTheory/Localization/LocallySmall.lean new file mode 100644 index 0000000000000..12c04e06860ef --- /dev/null +++ b/Mathlib/CategoryTheory/Localization/LocallySmall.lean @@ -0,0 +1,71 @@ +/- +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.CategoryTheory.Localization.HasLocalization +import Mathlib.CategoryTheory.EssentiallySmall + +/-! +# Locally small localizations + +In this file, given `W : MorphismProperty C` and a universe `w`, we show +that there exists a term in `HasLocalization.{w} W` if and only if +there exists (or for all) localization functors `L : C ⥤ D` for `W`, +the category `D` is locally `w`-small. + +-/ + +universe w v₁ v₂ u₁ u₂ + +namespace CategoryTheory.MorphismProperty + +variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C) + +/-- If `L : C ⥤ D` is a localization functor for a class of morphisms +`W : MorphismProperty C`, and `D` is locally `w`-small, we may obtain +a `HasLocalization.{w} W` instance by shrinking the morphisms in `D`. +(This version assumes that the types of objects of the categories +`C` and `D` are in the same universe.) -/ +noncomputable def hasLocalizationOfLocallySmall + {D : Type u₁} [Category.{v₂} D] [LocallySmall.{w} D] + (L : C ⥤ D) [L.IsLocalization W] : + HasLocalization.{w} W where + D := ShrinkHoms D + L := L ⋙ (ShrinkHoms.equivalence D).functor + +/-- If `L : C ⥤ D` is a localization functor for a class of morphisms +`W : MorphismProperty C`, and `D` is locally `w`-small, we may obtain +a `HasLocalization.{w} W` instance. This should be used only in the +unlikely situation where the types of objects of `C` and `D` are in +different universes. Otherwise, use `hasLocalizationOfLocallySmall`. -/ +noncomputable irreducible_def hasLocalizationOfLocallySmall' + {D : Type u₂} [Category.{v₂} D] [LocallySmall.{w} D] + (L : C ⥤ D) [L.IsLocalization W] : + HasLocalization.{w} W := by + have : LocallySmall.{w} (InducedCategory _ L.obj) := + ⟨fun X Y ↦ inferInstanceAs (Small.{w} (L.obj X ⟶ L.obj Y))⟩ + let L' : C ⥤ (InducedCategory _ L.obj) := + { obj X := X + map f := L.map f } + have := Localization.essSurj L W + have : (inducedFunctor L.obj).EssSurj := ⟨fun Y ↦ ⟨_, ⟨L.objObjPreimageIso Y⟩⟩⟩ + have : (inducedFunctor L.obj).IsEquivalence := { } + let e := (inducedFunctor L.obj).asEquivalence + let e' : (L' ⋙ e.functor) ⋙ e.inverse ≅ L' := + Functor.associator _ _ _ ≪≫ isoWhiskerLeft L' e.unitIso.symm ≪≫ L'.rightUnitor + have : L'.IsLocalization W := + Functor.IsLocalization.of_iso W (L₁ := L ⋙ e.inverse) e' + exact hasLocalizationOfLocallySmall.{w} W L' + +/-- If a class of morphisms `W : MorphismProperty C` satisfies `HasLocalization.{w} W`, +then any localized category for `W` (i.e. any target of a localization functor +`L : C ⥤ D` for `W`) is locally `w`-small. -/ +lemma locallySmall_of_hasLocalization {D : Type u₂} [Category.{v₂} D] + (L : C ⥤ D) [L.IsLocalization W] [HasLocalization.{w} W] : + LocallySmall.{w} D where + hom_small _ _ := small_of_injective (fun _ _ h ↦ + (Localization.uniq L W.Q' W).functor.map_injective h) + +end CategoryTheory.MorphismProperty From dfa76e7f7237a5d71aa907375cf5f76546a82136 Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Mon, 20 Jan 2025 16:09:45 +0000 Subject: [PATCH 345/681] feat(Order/Chain): adapt linear order lemmas to chains (#20757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a series of lemmas for chains in a preorder. Each of these are true in a linear order, but remain true under the weaker assumption that both elements are in a chain. Used in the disproof of the Aharoni–Korman conjecture, https://github.com/leanprover-community/mathlib4/pull/20082. --- Mathlib/Order/Chain.lean | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Mathlib/Order/Chain.lean b/Mathlib/Order/Chain.lean index 4b93268a6ec0b..60ab154fab092 100644 --- a/Mathlib/Order/Chain.lean +++ b/Mathlib/Order/Chain.lean @@ -137,6 +137,24 @@ theorem IsChain.exists3 (hchain : IsChain r s) [IsTrans α r] {a b c} (mem1 : a end Total +lemma IsChain.le_of_not_lt [Preorder α] (hs : IsChain (· ≤ ·) s) + {x y : α} (hx : x ∈ s) (hy : y ∈ s) (h : ¬ x < y) : y ≤ x := by + cases hs.total hx hy with + | inr h' => exact h' + | inl h' => simpa [lt_iff_le_not_le, h'] using h + +lemma IsChain.not_lt [Preorder α] (hs : IsChain (· ≤ ·) s) + {x y : α} (hx : x ∈ s) (hy : y ∈ s) : ¬ x < y ↔ y ≤ x := + ⟨(hs.le_of_not_lt hx hy ·), fun h h' ↦ h'.not_le h⟩ + +lemma IsChain.lt_of_not_le [Preorder α] (hs : IsChain (· ≤ ·) s) + {x y : α} (hx : x ∈ s) (hy : y ∈ s) (h : ¬ x ≤ y) : y < x := + (hs.total hx hy).elim (h · |>.elim) (lt_of_le_not_le · h) + +lemma IsChain.not_le [Preorder α] (hs : IsChain (· ≤ ·) s) + {x y : α} (hx : x ∈ s) (hy : y ∈ s) : ¬ x ≤ y ↔ y < x := + ⟨(hs.lt_of_not_le hx hy ·), fun h h' ↦ h'.not_lt h⟩ + theorem IsMaxChain.isChain (h : IsMaxChain r s) : IsChain r s := h.1 From 9f8c595d918428ed11986fa7bfd70fa840b38580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 20 Jan 2025 16:09:47 +0000 Subject: [PATCH 346/681] style: replace `field x y := match x, y with` with `field` (#20866) This is valid and shorter syntax. --- Mathlib/Algebra/Group/WithOne/Defs.lean | 4 +- Mathlib/Algebra/GroupWithZero/WithZero.lean | 56 ++++++++----------- .../Algebra/Module/Presentation/Cokernel.lean | 2 +- .../Module/Presentation/Tautological.lean | 2 +- .../Algebra/Module/Presentation/Tensor.lean | 2 +- Mathlib/Algebra/Order/Ring/WithTop.lean | 10 ++-- .../Limits/Shapes/BinaryProducts.lean | 16 +++--- Mathlib/Combinatorics/Quiver/Symmetric.lean | 2 +- Mathlib/Combinatorics/SimpleGraph/Sum.lean | 4 +- Mathlib/Data/Sum/Lattice.lean | 16 +++--- .../GroupTheory/SpecificGroups/Dihedral.lean | 12 ++-- .../LinearAlgebra/ExteriorPower/Basic.lean | 2 +- Mathlib/Logic/Equiv/Basic.lean | 12 ++-- Mathlib/Order/Booleanisation.lean | 40 ++++++------- Mathlib/Order/OmegaCompletePartialOrder.lean | 2 +- .../AdicCompletion/AsTensorProduct.lean | 16 +++--- 16 files changed, 93 insertions(+), 105 deletions(-) diff --git a/Mathlib/Algebra/Group/WithOne/Defs.lean b/Mathlib/Algebra/Group/WithOne/Defs.lean index dc7d3fcec8135..135c6d8b35e74 100644 --- a/Mathlib/Algebra/Group/WithOne/Defs.lean +++ b/Mathlib/Algebra/Group/WithOne/Defs.lean @@ -170,7 +170,7 @@ lemma coe_mul [Mul α] (a b : α) : (↑(a * b) : WithOne α) = a * b := rfl @[to_additive] instance monoid [Semigroup α] : Monoid (WithOne α) where __ := mulOneClass - mul_assoc a b c := match a, b, c with + mul_assoc | 1, b, c => by simp | (a : α), 1, c => by simp | (a : α), (b : α), 1 => by simp @@ -178,7 +178,7 @@ instance monoid [Semigroup α] : Monoid (WithOne α) where @[to_additive] instance commMonoid [CommSemigroup α] : CommMonoid (WithOne α) where - mul_comm := fun a b => match a, b with + mul_comm | (a : α), (b : α) => congr_arg some (mul_comm a b) | (_ : α), 1 => rfl | 1, (_ : α) => rfl diff --git a/Mathlib/Algebra/GroupWithZero/WithZero.lean b/Mathlib/Algebra/GroupWithZero/WithZero.lean index 8acf0b8bcb620..43ea0028206c0 100644 --- a/Mathlib/Algebra/GroupWithZero/WithZero.lean +++ b/Mathlib/Algebra/GroupWithZero/WithZero.lean @@ -142,7 +142,7 @@ section Pow variable [One α] [Pow α ℕ] instance pow : Pow (WithZero α) ℕ where - pow x n := match x, n with + pow | none, 0 => 1 | none, _ + 1 => 0 | some x, n => ↑(x ^ n) @@ -155,12 +155,12 @@ instance monoidWithZero [Monoid α] : MonoidWithZero (WithZero α) where __ := mulZeroOneClass __ := semigroupWithZero npow n a := a ^ n - npow_zero a := match a with - | none => rfl + npow_zero + | 0 => rfl | some _ => congr_arg some (pow_zero _) - npow_succ n a := match a with - | none => by change 0 ^ (n + 1) = 0 ^ n * 0; simp only [mul_zero]; rfl - | some _ => congr_arg some <| pow_succ _ _ + npow_succ + | n, 0 => by simp only [mul_zero]; rfl + | n, some _ => congr_arg some <| pow_succ _ _ instance commMonoidWithZero [CommMonoid α] : CommMonoidWithZero (WithZero α) := { WithZero.monoidWithZero, WithZero.commSemigroup with } @@ -193,7 +193,7 @@ section ZPow variable [One α] [Pow α ℤ] instance : Pow (WithZero α) ℤ where - pow a n := match a, n with + pow | none, Int.ofNat 0 => 1 | none, Int.ofNat (Nat.succ _) => 0 | none, Int.negSucc _ => 0 @@ -205,20 +205,20 @@ end ZPow instance divInvMonoid [DivInvMonoid α] : DivInvMonoid (WithZero α) where __ := monoidWithZero - div_eq_mul_inv a b := match a, b with + div_eq_mul_inv | none, _ => rfl | some _, none => rfl | some a, some b => congr_arg some (div_eq_mul_inv a b) zpow n a := a ^ n - zpow_zero' a := match a with + zpow_zero' | none => rfl | some _ => congr_arg some (zpow_zero _) - zpow_succ' n a := match a with - | none => by change 0 ^ _ = 0 ^ _ * 0; simp only [mul_zero]; rfl - | some _ => congr_arg some (DivInvMonoid.zpow_succ' _ _) - zpow_neg' _ a := match a with - | none => rfl - | some _ => congr_arg some (DivInvMonoid.zpow_neg' _ _) + zpow_succ' + | n, none => by change 0 ^ _ = 0 ^ _ * 0; simp only [mul_zero]; rfl + | n, some _ => congr_arg some (DivInvMonoid.zpow_succ' _ _) + zpow_neg' + | n, none => rfl + | n, some _ => congr_arg some (DivInvMonoid.zpow_neg' _ _) instance divInvOneMonoid [DivInvOneMonoid α] : DivInvOneMonoid (WithZero α) where __ := divInvMonoid @@ -230,16 +230,14 @@ instance involutiveInv [InvolutiveInv α] : InvolutiveInv (WithZero α) where instance divisionMonoid [DivisionMonoid α] : DivisionMonoid (WithZero α) where __ := divInvMonoid __ := involutiveInv - mul_inv_rev a b := match a, b with + mul_inv_rev | none, none => rfl | none, some _ => rfl | some _, none => rfl | some _, some _ => congr_arg some (mul_inv_rev _ _) - inv_eq_of_mul a b := match a, b with - | none, none => fun _ ↦ rfl - | none, some b => fun _ ↦ by contradiction - | some a, none => fun _ ↦ by contradiction - | some _, some _ => fun h ↦ + inv_eq_of_mul + | none, none, _ => rfl + | some _, some _, h => congr_arg some <| inv_eq_of_mul_eq_one_right <| Option.some_injective _ h instance divisionCommMonoid [DivisionCommMonoid α] : DivisionCommMonoid (WithZero α) where @@ -260,7 +258,6 @@ instance groupWithZero : GroupWithZero (WithZero α) where norm_cast apply mul_inv_cancel - /-- Any group is isomorphic to the units of itself adjoined with `0`. -/ def unitsWithZeroEquiv : (WithZero α)ˣ ≃* α where toFun a := unzero a.ne_zero @@ -277,9 +274,7 @@ def withZeroUnitsEquiv {G : Type*} [GroupWithZero G] invFun a := if h : a = 0 then 0 else (Units.mk0 a h : Gˣ) left_inv := (by induction · <;> simp) right_inv _ := by simp only; split <;> simp_all - map_mul' x y := by - induction x <;> induction y <;> - simp [← WithZero.coe_mul, ← Units.val_mul] + map_mul' := (by induction · <;> induction · <;> simp [← WithZero.coe_mul]) /-- A version of `Equiv.optionCongr` for `WithZero`. -/ noncomputable def _root_.MulEquiv.withZero [Group β] (e : α ≃* β) : @@ -288,9 +283,7 @@ noncomputable def _root_.MulEquiv.withZero [Group β] (e : α ≃* β) : invFun := map' e.symm.toMonoidHom left_inv := (by induction · <;> simp) right_inv := (by induction · <;> simp) - map_mul' x y := by - induction x <;> induction y <;> - simp + map_mul' := (by induction · <;> induction · <;> simp) /-- The inverse of `MulEquiv.withZero`. -/ protected noncomputable def _root_.MulEquiv.unzero [Group β] (e : WithZero α ≃* WithZero β) : @@ -314,11 +307,6 @@ instance commGroupWithZero [CommGroup α] : CommGroupWithZero (WithZero α) := instance addMonoidWithOne [AddMonoidWithOne α] : AddMonoidWithOne (WithZero α) where natCast n := if n = 0 then 0 else (n : α) natCast_zero := rfl - natCast_succ n := by - cases n with - | zero => show (((1 : ℕ) : α) : WithZero α) = 0 + 1; · rw [Nat.cast_one, coe_one, zero_add] - | succ n => - show (((n + 2 : ℕ) : α) : WithZero α) = ((n + 1 : ℕ) : α) + 1 - rw [Nat.cast_succ, coe_add, coe_one] + natCast_succ n := by cases n <;> simp end WithZero diff --git a/Mathlib/Algebra/Module/Presentation/Cokernel.lean b/Mathlib/Algebra/Module/Presentation/Cokernel.lean index ceaa3b65c0451..d9f2c84e6cd05 100644 --- a/Mathlib/Algebra/Module/Presentation/Cokernel.lean +++ b/Mathlib/Algebra/Module/Presentation/Cokernel.lean @@ -71,7 +71,7 @@ and one for each generator of `M₁`. -/ def cokernelRelations : Relations A where G := pres₂.G R := Sum pres₂.R ι - relation x := match x with + relation | .inl r => pres₂.relation r | .inr i => data.lift i diff --git a/Mathlib/Algebra/Module/Presentation/Tautological.lean b/Mathlib/Algebra/Module/Presentation/Tautological.lean index 72fa47899f48e..b73d5ed63d3bf 100644 --- a/Mathlib/Algebra/Module/Presentation/Tautological.lean +++ b/Mathlib/Algebra/Module/Presentation/Tautological.lean @@ -33,7 +33,7 @@ inductive tautological.R noncomputable def tautologicalRelations : Relations A where G := M R := tautological.R A M - relation r := match r with + relation | .add m₁ m₂ => Finsupp.single m₁ 1 + Finsupp.single m₂ 1 - Finsupp.single (m₁ + m₂) 1 | .smul a m => a • Finsupp.single m 1 - Finsupp.single (a • m) 1 diff --git a/Mathlib/Algebra/Module/Presentation/Tensor.lean b/Mathlib/Algebra/Module/Presentation/Tensor.lean index f1a1b39c41ac8..c941b59b9f7e6 100644 --- a/Mathlib/Algebra/Module/Presentation/Tensor.lean +++ b/Mathlib/Algebra/Module/Presentation/Tensor.lean @@ -32,7 +32,7 @@ noncomputable def tensor : Relations A where G := relations₁.G × relations₂.G R := Sum (relations₁.R × relations₂.G) (relations₁.G × relations₂.R) - relation r := match r with + relation | .inl ⟨r₁, g₂⟩ => Finsupp.embDomain (Function.Embedding.sectL relations₁.G g₂) (relations₁.relation r₁) | .inr ⟨g₁, r₂⟩ => Finsupp.embDomain (Function.Embedding.sectR g₁ relations₂.G) diff --git a/Mathlib/Algebra/Order/Ring/WithTop.lean b/Mathlib/Algebra/Order/Ring/WithTop.lean index 5ba1619244795..894e0aabbc46c 100644 --- a/Mathlib/Algebra/Order/Ring/WithTop.lean +++ b/Mathlib/Algebra/Order/Ring/WithTop.lean @@ -24,15 +24,15 @@ variable [MulZeroClass α] {a b : WithTop α} instance instMulZeroClass : MulZeroClass (WithTop α) where zero := 0 - mul a b := match a, b with + mul | (a : α), (b : α) => ↑(a * b) | (a : α), ⊤ => if a = 0 then 0 else ⊤ | ⊤, (b : α) => if b = 0 then 0 else ⊤ | ⊤, ⊤ => ⊤ - mul_zero a := match a with + mul_zero | (a : α) => congr_arg some <| mul_zero _ | ⊤ => if_pos rfl - zero_mul b := match b with + zero_mul | (b : α) => congr_arg some <| zero_mul _ | ⊤ => if_pos rfl @@ -93,10 +93,10 @@ end MulZeroClass /-- `Nontrivial α` is needed here as otherwise we have `1 * ⊤ = ⊤` but also `0 * ⊤ = 0`. -/ instance instMulZeroOneClass [MulZeroOneClass α] [Nontrivial α] : MulZeroOneClass (WithTop α) where __ := instMulZeroClass - one_mul a := match a with + one_mul | ⊤ => mul_top (mt coe_eq_coe.1 one_ne_zero) | (a : α) => by rw [← coe_one, ← coe_mul, one_mul] - mul_one a := match a with + mul_one | ⊤ => top_mul (mt coe_eq_coe.1 one_ne_zero) | (a : α) => by rw [← coe_one, ← coe_mul, mul_one] diff --git a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean index 5f3c1866a623d..02ed48104a196 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean @@ -46,14 +46,14 @@ open WalkingPair /-- The equivalence swapping left and right. -/ def WalkingPair.swap : WalkingPair ≃ WalkingPair where - toFun j := match j with + toFun | left => right | right => left - invFun j := match j with + invFun | left => right | right => left - left_inv j := by cases j; repeat rfl - right_inv j := by cases j; repeat rfl + left_inv j := by cases j <;> rfl + right_inv j := by cases j <;> rfl @[simp] theorem WalkingPair.swap_apply_left : WalkingPair.swap left = right := @@ -74,13 +74,13 @@ theorem WalkingPair.swap_symm_apply_ff : WalkingPair.swap.symm right = left := /-- An equivalence from `WalkingPair` to `Bool`, sometimes useful when reindexing limits. -/ def WalkingPair.equivBool : WalkingPair ≃ Bool where - toFun j := match j with + toFun | left => true | right => false -- to match equiv.sum_equiv_sigma_bool invFun b := Bool.recOn b right left - left_inv j := by cases j; repeat rfl - right_inv b := by cases b; repeat rfl + left_inv j := by cases j <;> rfl + right_inv b := by cases b <;> rfl @[simp] theorem WalkingPair.equivBool_apply_left : WalkingPair.equivBool left = true := @@ -136,7 +136,7 @@ attribute [local aesop safe tactic (rule_sets := [CategoryTheory])] /-- The natural transformation between two functors out of the walking pair, specified by its components. -/ def mapPair : F ⟶ G where - app j := match j with + app | ⟨left⟩ => f | ⟨right⟩ => g naturality := fun ⟨X⟩ ⟨Y⟩ ⟨⟨u⟩⟩ => by aesop_cat diff --git a/Mathlib/Combinatorics/Quiver/Symmetric.lean b/Mathlib/Combinatorics/Quiver/Symmetric.lean index 39e75756c695f..dc7abe0e3f8c3 100644 --- a/Mathlib/Combinatorics/Quiver/Symmetric.lean +++ b/Mathlib/Combinatorics/Quiver/Symmetric.lean @@ -160,7 +160,7 @@ variable {V' : Type*} [Quiver.{v' + 1} V'] def lift [HasReverse V'] (φ : Prefunctor V V') : Prefunctor (Symmetrify V) V' where obj := φ.obj - map f := match f with + map | Sum.inl g => φ.map g | Sum.inr g => reverse (φ.map g) diff --git a/Mathlib/Combinatorics/SimpleGraph/Sum.lean b/Mathlib/Combinatorics/SimpleGraph/Sum.lean index fb0baffa19abc..25de075d43605 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Sum.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Sum.lean @@ -29,11 +29,11 @@ namespace SimpleGraph /-- Disjoint sum of `G` and `H`. -/ @[simps!] protected def sum (G : SimpleGraph α) (H : SimpleGraph β) : SimpleGraph (α ⊕ β) where - Adj u v := match u, v with + Adj | Sum.inl u, Sum.inl v => G.Adj u v | Sum.inr u, Sum.inr v => H.Adj u v | _, _ => false - symm u v := match u, v with + symm | Sum.inl u, Sum.inl v => G.adj_symm | Sum.inr u, Sum.inr v => H.adj_symm | Sum.inl _, Sum.inr _ | Sum.inr _, Sum.inl _ => id diff --git a/Mathlib/Data/Sum/Lattice.lean b/Mathlib/Data/Sum/Lattice.lean index 72e63dc5fa589..cf1ae58eec0b1 100644 --- a/Mathlib/Data/Sum/Lattice.lean +++ b/Mathlib/Data/Sum/Lattice.lean @@ -24,22 +24,22 @@ variable [SemilatticeSup α] [SemilatticeSup β] -- The linter significantly hinders readability here. set_option linter.unusedVariables false in instance instSemilatticeSup : SemilatticeSup (α ⊕ₗ β) where - sup x y := match x, y with + sup | inlₗ a₁, inlₗ a₂ => inl (a₁ ⊔ a₂) | inlₗ a₁, inrₗ b₂ => inr b₂ | inrₗ b₁, inlₗ a₂ => inr b₁ | inrₗ b₁, inrₗ b₂ => inr (b₁ ⊔ b₂) - le_sup_left x y := match x, y with + le_sup_left | inlₗ a₁, inlₗ a₂ => inl_le_inl_iff.2 le_sup_left | inlₗ a₁, inrₗ b₂ => inl_le_inr _ _ | inrₗ b₁, inlₗ a₂ => le_rfl | inrₗ b₁, inrₗ b₂ => inr_le_inr_iff.2 le_sup_left - le_sup_right x y := match x, y with + le_sup_right | inlₗ a₁, inlₗ a₂ => inl_le_inl_iff.2 le_sup_right | inlₗ a₁, inrₗ b₂ => le_rfl | inrₗ b₁, inlₗ a₂ => inl_le_inr _ _ | inrₗ b₁, inrₗ b₂ => inr_le_inr_iff.2 le_sup_right - sup_le x y z hxz hyz := match x, y, z, hxz, hyz with + sup_le | inlₗ a₁, inlₗ a₂, inlₗ a₃, Lex.inl h₁₃, Lex.inl h₂₃ => inl_le_inl_iff.2 <| sup_le h₁₃ h₂₃ | inlₗ a₁, inlₗ a₂, inrₗ b₃, Lex.sep _ _, Lex.sep _ _ => Lex.sep _ _ | inlₗ a₁, inrₗ b₂, inrₗ b₃, Lex.sep _ _, Lex.inr h₂₃ => inr_le_inr_iff.2 h₂₃ @@ -57,22 +57,22 @@ variable [SemilatticeInf α] [SemilatticeInf β] -- The linter significantly hinders readability here. set_option linter.unusedVariables false in instance instSemilatticeInf : SemilatticeInf (α ⊕ₗ β) where - inf x y := match x, y with + inf | inlₗ a₁, inlₗ a₂ => inl (a₁ ⊓ a₂) | inlₗ a₁, inrₗ b₂ => inl a₁ | inrₗ b₁, inlₗ a₂ => inl a₂ | inrₗ b₁, inrₗ b₂ => inr (b₁ ⊓ b₂) - inf_le_left x y := match x, y with + inf_le_left | inlₗ a₁, inlₗ a₂ => inl_le_inl_iff.2 inf_le_left | inlₗ a₁, inrₗ b₂ => le_rfl | inrₗ b₁, inlₗ a₂ => inl_le_inr _ _ | inrₗ b₁, inrₗ b₂ => inr_le_inr_iff.2 inf_le_left - inf_le_right x y := match x, y with + inf_le_right | inlₗ a₁, inlₗ a₂ => inl_le_inl_iff.2 inf_le_right | inlₗ a₁, inrₗ b₂ => inl_le_inr _ _ | inrₗ b₁, inlₗ a₂ => le_rfl | inrₗ b₁, inrₗ b₂ => inr_le_inr_iff.2 inf_le_right - le_inf x y z hzx hzy := match x, y, z, hzx, hzy with + le_inf | inlₗ a₁, inlₗ a₂, inlₗ a₃, Lex.inl h₁₃, Lex.inl h₂₃ => inl_le_inl_iff.2 <| le_inf h₁₃ h₂₃ | inlₗ a₁, inlₗ a₂, inrₗ b₃, Lex.inl h₁₃, Lex.sep _ _ => inl_le_inl_iff.2 h₁₃ | inlₗ a₁, inrₗ b₂, inlₗ a₃, Lex.sep _ _, Lex.inl h₂₃ => inl_le_inl_iff.2 h₂₃ diff --git a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean index ba8587d7527f9..4f4b580852404 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean @@ -103,12 +103,12 @@ theorem one_def : (1 : DihedralGroup n) = r 0 := rfl private def fintypeHelper : (ZMod n) ⊕ (ZMod n) ≃ DihedralGroup n where - invFun i := match i with - | r j => Sum.inl j - | sr j => Sum.inr j - toFun i := match i with - | Sum.inl j => r j - | Sum.inr j => sr j + invFun + | r j => .inl j + | sr j => .inr j + toFun + | .inl j => r j + | .inr j => sr j left_inv := by rintro (x | x) <;> rfl right_inv := by rintro (x | x) <;> rfl diff --git a/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean b/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean index e02ccb29fa8ea..1eeeb2f33aea4 100644 --- a/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean +++ b/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean @@ -82,7 +82,7 @@ noncomputable def relations (ι : Type*) [DecidableEq ι] (M : Type*) Module.Relations R where G := ι → M R := Rels R ι M - relation r := match r with + relation | .add m i x y => Finsupp.single (update m i x) 1 + Finsupp.single (update m i y) 1 - Finsupp.single (update m i (x + y)) 1 diff --git a/Mathlib/Logic/Equiv/Basic.lean b/Mathlib/Logic/Equiv/Basic.lean index 52c2e153e76e9..645bea7d22304 100644 --- a/Mathlib/Logic/Equiv/Basic.lean +++ b/Mathlib/Logic/Equiv/Basic.lean @@ -286,12 +286,12 @@ theorem sumCongr_refl {α β} : /-- A subtype of a sum is equivalent to a sum of subtypes. -/ def subtypeSum {α β} {p : α ⊕ β → Prop} : {c // p c} ≃ {a // p (Sum.inl a)} ⊕ {b // p (Sum.inr b)} where - toFun c := match h : c.1 with - | Sum.inl a => Sum.inl ⟨a, h ▸ c.2⟩ - | Sum.inr b => Sum.inr ⟨b, h ▸ c.2⟩ - invFun c := match c with - | Sum.inl a => ⟨Sum.inl a, a.2⟩ - | Sum.inr b => ⟨Sum.inr b, b.2⟩ + toFun + | ⟨.inl a, h⟩ => .inl ⟨a, h⟩ + | ⟨.inr b, h⟩ => .inr ⟨b, h⟩ + invFun + | .inl a => ⟨.inl a, a.2⟩ + | .inr b => ⟨.inr b, b.2⟩ left_inv := by rintro ⟨a | b, h⟩ <;> rfl right_inv := by rintro (a | b) <;> rfl diff --git a/Mathlib/Order/Booleanisation.lean b/Mathlib/Order/Booleanisation.lean index 6d5ee593160b5..736b9fbe34360 100644 --- a/Mathlib/Order/Booleanisation.lean +++ b/Mathlib/Order/Booleanisation.lean @@ -51,7 +51,7 @@ algebra. -/ /-- The complement operator on `Booleanisation α` sends `a` to `aᶜ` and `aᶜ` to `a`, for `a : α`. -/ instance instCompl : HasCompl (Booleanisation α) where - compl x := match x with + compl | lift a => comp a | comp a => lift a @@ -94,7 +94,7 @@ instance instLT : LT (Booleanisation α) where * `aᶜ ⊔ b` is `(a \ b)ᶜ` * `aᶜ ⊔ bᶜ` is `(a ⊓ b)ᶜ` -/ instance instSup : Max (Booleanisation α) where - max x y := match x, y with + max | lift a, lift b => lift (a ⊔ b) | lift a, comp b => comp (b \ a) | comp a, lift b => comp (a \ b) @@ -106,7 +106,7 @@ instance instSup : Max (Booleanisation α) where * `aᶜ ⊓ b` is `b \ a` * `aᶜ ⊓ bᶜ` is `(a ⊔ b)ᶜ` -/ instance instInf : Min (Booleanisation α) where - min x y := match x, y with + min | lift a, lift b => lift (a ⊓ b) | lift a, comp b => lift (a \ b) | comp a, lift b => lift (b \ a) @@ -126,7 +126,7 @@ instance instTop : Top (Booleanisation α) where * `aᶜ \ b` is `(a ⊔ b)ᶜ` * `aᶜ \ bᶜ` is `b \ a` -/ instance instSDiff : SDiff (Booleanisation α) where - sdiff x y := match x, y with + sdiff | lift a, lift b => lift (a \ b) | lift a, comp b => lift (a ⊓ b) | comp a, lift b => comp (a ⊔ b) @@ -162,22 +162,22 @@ instance instSDiff : SDiff (Booleanisation α) where instance instPreorder : Preorder (Booleanisation α) where lt := (· < ·) - lt_iff_le_not_le x y := match x, y with + lt_iff_le_not_le | lift a, lift b => by simp [lt_iff_le_not_le] | lift a, comp b => by simp | comp a, lift b => by simp | comp a, comp b => by simp [lt_iff_le_not_le] - le_refl x := match x with + le_refl | lift _ => LE.lift le_rfl | comp _ => LE.comp le_rfl - le_trans x y z hxy hyz := match x, y, z, hxy, hyz with + le_trans | lift _, lift _, lift _, LE.lift hab, LE.lift hbc => LE.lift <| hab.trans hbc | lift _, lift _, comp _, LE.lift hab, LE.sep hbc => LE.sep <| hbc.mono_left hab | lift _, comp _, comp _, LE.sep hab, LE.comp hcb => LE.sep <| hab.mono_right hcb | comp _, comp _, comp _, LE.comp hba, LE.comp hcb => LE.comp <| hcb.trans hba instance instPartialOrder : PartialOrder (Booleanisation α) where - le_antisymm x y hxy hyx := match x, y, hxy, hyx with + le_antisymm | lift a, lift b, LE.lift hab, LE.lift hba => by rw [hab.antisymm hba] | comp a, comp b, LE.comp hab, LE.comp hba => by rw [hab.antisymm hba] @@ -185,17 +185,17 @@ instance instPartialOrder : PartialOrder (Booleanisation α) where set_option linter.unusedVariables false in instance instSemilatticeSup : SemilatticeSup (Booleanisation α) where sup x y := max x y - le_sup_left x y := match x, y with + le_sup_left | lift a, lift b => LE.lift le_sup_left | lift a, comp b => LE.sep disjoint_sdiff_self_right | comp a, lift b => LE.comp sdiff_le | comp a, comp b => LE.comp inf_le_left - le_sup_right x y := match x, y with + le_sup_right | lift a, lift b => LE.lift le_sup_right | lift a, comp b => LE.comp sdiff_le | comp a, lift b => LE.sep disjoint_sdiff_self_right | comp a, comp b => LE.comp inf_le_right - sup_le x y z hxz hyz := match x, y, z, hxz, hyz with + sup_le | lift a, lift b, lift c, LE.lift hac, LE.lift hbc => LE.lift <| sup_le hac hbc | lift a, lift b, comp c, LE.sep hac, LE.sep hbc => LE.sep <| hac.sup_left hbc | lift a, comp b, comp c, LE.sep hac, LE.comp hcb => LE.comp <| le_sdiff.2 ⟨hcb, hac.symm⟩ @@ -206,17 +206,17 @@ instance instSemilatticeSup : SemilatticeSup (Booleanisation α) where set_option linter.unusedVariables false in instance instSemilatticeInf : SemilatticeInf (Booleanisation α) where inf x y := min x y - inf_le_left x y := match x, y with + inf_le_left | lift a, lift b => LE.lift inf_le_left | lift a, comp b => LE.lift sdiff_le | comp a, lift b => LE.sep disjoint_sdiff_self_left | comp a, comp b => LE.comp le_sup_left - inf_le_right x y := match x, y with + inf_le_right | lift a, lift b => LE.lift inf_le_right | lift a, comp b => LE.sep disjoint_sdiff_self_left | comp a, lift b => LE.lift sdiff_le | comp a, comp b => LE.comp le_sup_right - le_inf x y z hxz hyz := match x, y, z, hxz, hyz with + le_inf | lift a, lift b, lift c, LE.lift hab, LE.lift hac => LE.lift <| le_inf hab hac | lift a, lift b, comp c, LE.lift hab, LE.sep hac => LE.lift <| le_sdiff.2 ⟨hab, hac⟩ | lift a, comp b, lift c, LE.sep hab, LE.lift hac => LE.lift <| le_sdiff.2 ⟨hac, hab⟩ @@ -227,7 +227,7 @@ instance instDistribLattice : DistribLattice (Booleanisation α) where inf_le_left _ _ := inf_le_left inf_le_right _ _ := inf_le_right le_inf _ _ _ := le_inf - le_sup_inf x y z := match x, y, z with + le_sup_inf | lift _, lift _, lift _ => LE.lift le_sup_inf | lift a, lift b, comp c => LE.lift <| by simp [sup_left_comm, sup_comm, sup_assoc] | lift a, comp b, lift c => LE.lift <| by @@ -241,23 +241,23 @@ instance instDistribLattice : DistribLattice (Booleanisation α) where -- The linter significantly hinders readability here. set_option linter.unusedVariables false in instance instBoundedOrder : BoundedOrder (Booleanisation α) where - le_top x := match x with + le_top | lift a => LE.sep disjoint_bot_right | comp a => LE.comp bot_le - bot_le x := match x with + bot_le | lift a => LE.lift bot_le | comp a => LE.sep disjoint_bot_left instance instBooleanAlgebra : BooleanAlgebra (Booleanisation α) where le_top _ := le_top bot_le _ := bot_le - inf_compl_le_bot x := match x with + inf_compl_le_bot | lift a => by simp | comp a => by simp - top_le_sup_compl x := match x with + top_le_sup_compl | lift a => by simp | comp a => by simp - sdiff_eq x y := match x, y with + sdiff_eq | lift a, lift b => by simp | lift a, comp b => by simp | comp a, lift b => by simp diff --git a/Mathlib/Order/OmegaCompletePartialOrder.lean b/Mathlib/Order/OmegaCompletePartialOrder.lean index 9e76dd904111b..c1fe4b32ab082 100644 --- a/Mathlib/Order/OmegaCompletePartialOrder.lean +++ b/Mathlib/Order/OmegaCompletePartialOrder.lean @@ -134,7 +134,7 @@ def zip (c₀ : Chain α) (c₁ : Chain β) : Chain (α × β) := /-- An example of a `Chain` constructed from an ordered pair. -/ def pair (a b : α) (hab : a ≤ b) : Chain α where - toFun n := match n with + toFun | 0 => a | _ => b monotone' _ _ _ := by aesop diff --git a/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean b/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean index 2c56bfd1a747e..94d41ee47a20a 100644 --- a/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean +++ b/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean @@ -256,10 +256,10 @@ private def secondRow : ComposableArrows (ModuleCat (AdicCompletion I R)) 4 := include hf private lemma firstRow_exact : (firstRow I M f).Exact where - zero k _ := match k with - | 0 => ModuleCat.hom_ext (tens_exact I M f hf).linearMap_comp_eq_zero - | 1 => ModuleCat.hom_ext (LinearMap.zero_comp _) - | 2 => ModuleCat.hom_ext (LinearMap.zero_comp 0) + zero + | 0, _ => ModuleCat.hom_ext (tens_exact I M f hf).linearMap_comp_eq_zero + | 1, _ => ModuleCat.hom_ext (LinearMap.zero_comp _) + | 2, _ => ModuleCat.hom_ext (LinearMap.zero_comp 0) exact k _ := by rw [ShortComplex.moduleCat_exact_iff] match k with @@ -268,10 +268,10 @@ private lemma firstRow_exact : (firstRow I M f).Exact where | 2 => intro _ _; exact ⟨0, rfl⟩ private lemma secondRow_exact [Fintype ι] [IsNoetherianRing R] : (secondRow I M f).Exact where - zero k _ := match k with - | 0 => ModuleCat.hom_ext (adic_exact I M f hf).linearMap_comp_eq_zero - | 1 => ModuleCat.hom_ext (LinearMap.zero_comp (map I f)) - | 2 => ModuleCat.hom_ext (LinearMap.zero_comp 0) + zero + | 0, _ => ModuleCat.hom_ext (adic_exact I M f hf).linearMap_comp_eq_zero + | 1, _ => ModuleCat.hom_ext (LinearMap.zero_comp (map I f)) + | 2, _ => ModuleCat.hom_ext (LinearMap.zero_comp 0) exact k _ := by rw [ShortComplex.moduleCat_exact_iff] match k with From 82838c6a7d2ef0bea319e1c8228a5f432aaefa4b Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:09:49 +0000 Subject: [PATCH 347/681] feat(Data/Matroid/IndepAxioms): Another constructor for finitary matroids (#20877) This PR adds a new constructor for a finitary matroid, via `IndepMatroid`. The constructor uses the infinite independence augmentation axiom, together with a compactness assumption for independence. We name it `IndepMatroid.ofFinitary`, and rename the already existing variant with that name `IndepMatroid.ofFinitaryCardAugment`, since the former is really more canonical. This was motivated by the application of algebraic matroids to transcendence degrees, as discussed on [zulip](https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/Transcendence.20degree.3F) --- Mathlib/Data/Matroid/IndepAxioms.lean | 202 +++++++++++++++----------- 1 file changed, 117 insertions(+), 85 deletions(-) diff --git a/Mathlib/Data/Matroid/IndepAxioms.lean b/Mathlib/Data/Matroid/IndepAxioms.lean index 562ae11604dbd..89808d55cb1a6 100644 --- a/Mathlib/Data/Matroid/IndepAxioms.lean +++ b/Mathlib/Data/Matroid/IndepAxioms.lean @@ -61,6 +61,9 @@ for the inverse of `e`). in the special case where independence of a set is determined only by that of its finite subsets. This construction uses Zorn's lemma. +* `IndepMatroid.ofFinitaryCardAugment` is a variant of `IndepMatroid.ofFinitary` where the + augmentation axiom resembles the finite augmentation axiom. + * `IndepMatroid.ofBdd` constructs an `IndepMatroid` in the case where there is some known absolute upper bound on the size of an independent set. This uses the infinite version of the augmentation axiom; the corresponding `Matroid` is `FiniteRk`. @@ -139,88 +142,23 @@ namespace IndepMatroid @[simp] theorem matroid_indep_iff {M : IndepMatroid α} {I : Set α} : M.matroid.Indep I ↔ M.Indep I := Iff.rfl -/-- An independence predicate satisfying the finite matroid axioms determines a matroid, - provided independence is determined by its behaviour on finite sets. - This fundamentally needs choice, since it can be used to prove that every vector space - has a basis. -/ +/-- If `Indep` has the 'compactness' property that each set `I` satisfies `Indep I` if and only if +`Indep J` for every finite subset `J` of `I`, +then an `IndepMatroid` can be constructed without proving the maximality axiom. +This needs choice, since it can be used to prove that every vector space has a basis. -/ @[simps E] protected def ofFinitary (E : Set α) (Indep : Set α → Prop) (indep_empty : Indep ∅) (indep_subset : ∀ ⦃I J⦄, Indep J → I ⊆ J → Indep I) - (indep_aug : ∀ ⦃I J⦄, Indep I → I.Finite → Indep J → J.Finite → I.ncard < J.ncard → - ∃ e ∈ J, e ∉ I ∧ Indep (insert e I)) + (indep_aug : ∀ ⦃I B⦄, Indep I → ¬ Maximal Indep I → Maximal Indep B → + ∃ x ∈ B \ I, Indep (insert x I)) (indep_compact : ∀ I, (∀ J, J ⊆ I → J.Finite → Indep J) → Indep I) - (subset_ground : ∀ I, Indep I → I ⊆ E) : IndepMatroid α := - have htofin : ∀ I e, Indep I → ¬ Indep (insert e I) → - ∃ I₀, I₀ ⊆ I ∧ I₀.Finite ∧ ¬ Indep (insert e I₀) := by - by_contra h; push_neg at h - obtain ⟨I, e, -, hIe, h⟩ := h - refine hIe <| indep_compact _ fun J hJss hJfin ↦ ?_ - exact indep_subset (h (J \ {e}) (by rwa [diff_subset_iff]) hJfin.diff) (by simp) - IndepMatroid.mk - (E := E) - (Indep := Indep) - (indep_empty := indep_empty) - (indep_subset := indep_subset) - (indep_aug := by - intro I B hI hImax hBmax - obtain ⟨e, heI, hins⟩ := exists_insert_of_not_maximal indep_subset hI hImax - by_cases heB : e ∈ B - · exact ⟨e, ⟨heB, heI⟩, hins⟩ - by_contra hcon; push_neg at hcon - - have heBdep := hBmax.not_prop_of_ssuperset (ssubset_insert heB) - - -- There is a finite subset `B₀` of `B` so that `B₀ + e` is dependent - obtain ⟨B₀, hB₀B, hB₀fin, hB₀e⟩ := htofin B e hBmax.1 heBdep - have hB₀ := indep_subset hBmax.1 hB₀B - - -- `I` has a finite subset `I₀` that doesn't extend into `B₀` - have hexI₀ : ∃ I₀, I₀ ⊆ I ∧ I₀.Finite ∧ ∀ x, x ∈ B₀ \ I₀ → ¬Indep (insert x I₀) := by - have hchoose : ∀ (b : ↑(B₀ \ I)), ∃ Ib, Ib ⊆ I ∧ Ib.Finite ∧ ¬Indep (insert (b : α) Ib) := by - rintro ⟨b, hb⟩; exact htofin I b hI (hcon b ⟨hB₀B hb.1, hb.2⟩) - choose! f hf using hchoose - have : Finite ↑(B₀ \ I) := hB₀fin.diff.to_subtype - refine ⟨iUnion f ∪ (B₀ ∩ I), - union_subset (iUnion_subset (fun i ↦ (hf i).1)) inter_subset_right, - (finite_iUnion fun i ↦ (hf i).2.1).union (hB₀fin.subset inter_subset_left), - fun x ⟨hxB₀, hxn⟩ hi ↦ ?_⟩ - have hxI : x ∉ I := fun hxI ↦ hxn <| Or.inr ⟨hxB₀, hxI⟩ - refine (hf ⟨x, ⟨hxB₀, hxI⟩⟩).2.2 (indep_subset hi <| insert_subset_insert ?_) - apply subset_union_of_subset_left - apply subset_iUnion - - obtain ⟨I₀, hI₀I, hI₀fin, hI₀⟩ := hexI₀ - - set E₀ := insert e (I₀ ∪ B₀) - have hE₀fin : E₀.Finite := (hI₀fin.union hB₀fin).insert e - - -- Extend `B₀` to a maximal independent subset of `I₀ ∪ B₀ + e` - obtain ⟨J, ⟨hB₀J, hJ, hJss⟩, hJmax⟩ := Finite.exists_maximal_wrt (f := id) - (s := {J | B₀ ⊆ J ∧ Indep J ∧ J ⊆ E₀}) - (hE₀fin.finite_subsets.subset (by simp)) - ⟨B₀, Subset.rfl, hB₀, subset_union_right.trans (subset_insert _ _)⟩ - - have heI₀ : e ∉ I₀ := not_mem_subset hI₀I heI - have heI₀i : Indep (insert e I₀) := indep_subset hins (insert_subset_insert hI₀I) - - have heJ : e ∉ J := fun heJ ↦ hB₀e (indep_subset hJ <| insert_subset heJ hB₀J) - - have hJfin := hE₀fin.subset hJss - - -- We have `|I₀ + e| ≤ |J|`, since otherwise we could extend the maximal set `J` - have hcard : (insert e I₀).ncard ≤ J.ncard := by - refine not_lt.1 fun hlt ↦ ?_ - obtain ⟨f, hfI, hfJ, hfi⟩ := indep_aug hJ hJfin heI₀i (hI₀fin.insert e) hlt - have hfE₀ : f ∈ E₀ := mem_of_mem_of_subset hfI (insert_subset_insert subset_union_left) - refine hfJ (insert_eq_self.1 <| Eq.symm (hJmax _ - ⟨hB₀J.trans <| subset_insert _ _,hfi,insert_subset hfE₀ hJss⟩ (subset_insert _ _))) - - -- But this means `|I₀| < |J|`, and extending `I₀` into `J` gives a contradiction - rw [ncard_insert_of_not_mem heI₀ hI₀fin, ← Nat.lt_iff_add_one_le] at hcard - - obtain ⟨f, hfJ, hfI₀, hfi⟩ := indep_aug (indep_subset hI hI₀I) hI₀fin hJ hJfin hcard - exact hI₀ f ⟨Or.elim (hJss hfJ) (fun hfe ↦ (heJ <| hfe ▸ hfJ).elim) (by aesop), hfI₀⟩ hfi) - (indep_maximal := by + (subset_ground : ∀ I, Indep I → I ⊆ E) : IndepMatroid α where + E := E + Indep := Indep + indep_empty := indep_empty + indep_subset := indep_subset + indep_aug := indep_aug + indep_maximal := by refine fun X _ I hI hIX ↦ zorn_subset_nonempty {Y | Indep Y ∧ Y ⊆ X} ?_ I ⟨hI, hIX⟩ refine fun Is hIs hchain _ ↦ ⟨⋃₀ Is, ⟨?_, sUnion_subset fun Y hY ↦ (hIs hY).2⟩, fun _ ↦ subset_sUnion_of_mem⟩ @@ -232,12 +170,12 @@ namespace IndepMatroid refine indep_subset (hIs (hf x hxJ).1).1 fun y hyJ ↦ ?_ obtain (hle | hle) := hchain.total (hf _ hxJ).1 (hf _ hyJ).1 · rw [hxmax _ hyJ hle]; exact (hf _ hyJ).2 - exact hle (hf _ hyJ).2) - - (subset_ground := subset_ground) + exact hle (hf _ hyJ).2 + subset_ground := subset_ground @[simp] theorem ofFinitary_indep (E : Set α) (Indep : Set α → Prop) - indep_empty indep_subset indep_aug indep_compact subset_ground : (IndepMatroid.ofFinitary + indep_empty indep_subset indep_aug indep_compact subset_ground : + (IndepMatroid.ofFinitary E Indep indep_empty indep_subset indep_aug indep_compact subset_ground).Indep = Indep := rfl instance ofFinitary_finitary (E : Set α) (Indep : Set α → Prop) @@ -246,6 +184,100 @@ instance ofFinitary_finitary (E : Set α) (Indep : Set α → Prop) E Indep indep_empty indep_subset indep_aug indep_compact subset_ground).matroid := ⟨by simpa⟩ +/-- An independence predicate satisfying the finite matroid axioms determines a matroid, +provided independence is determined by its behaviour on finite sets. -/ +@[simps! E] protected def ofFinitaryCardAugment (E : Set α) (Indep : Set α → Prop) + (indep_empty : Indep ∅) + (indep_subset : ∀ ⦃I J⦄, Indep J → I ⊆ J → Indep I) + (indep_aug : ∀ ⦃I J⦄, Indep I → I.Finite → Indep J → J.Finite → I.ncard < J.ncard → + ∃ e ∈ J, e ∉ I ∧ Indep (insert e I)) + (indep_compact : ∀ I, (∀ J, J ⊆ I → J.Finite → Indep J) → Indep I) + (subset_ground : ∀ I, Indep I → I ⊆ E) : IndepMatroid α := + IndepMatroid.ofFinitary + (E := E) + (Indep := Indep) + (indep_empty := indep_empty) + (indep_subset := indep_subset) + (indep_compact := indep_compact) + (indep_aug := by + have htofin : ∀ I e, Indep I → ¬ Indep (insert e I) → + ∃ I₀, I₀ ⊆ I ∧ I₀.Finite ∧ ¬ Indep (insert e I₀) := by + by_contra h; push_neg at h + obtain ⟨I, e, -, hIe, h⟩ := h + refine hIe <| indep_compact _ fun J hJss hJfin ↦ ?_ + exact indep_subset (h (J \ {e}) (by rwa [diff_subset_iff]) hJfin.diff) (by simp) + + intro I B hI hImax hBmax + obtain ⟨e, heI, hins⟩ := exists_insert_of_not_maximal indep_subset hI hImax + by_cases heB : e ∈ B + · exact ⟨e, ⟨heB, heI⟩, hins⟩ + by_contra hcon; push_neg at hcon + + have heBdep := hBmax.not_prop_of_ssuperset (ssubset_insert heB) + + -- There is a finite subset `B₀` of `B` so that `B₀ + e` is dependent + obtain ⟨B₀, hB₀B, hB₀fin, hB₀e⟩ := htofin B e hBmax.1 heBdep + have hB₀ := indep_subset hBmax.1 hB₀B + + -- `I` has a finite subset `I₀` that doesn't extend into `B₀` + have hexI₀ : ∃ I₀, I₀ ⊆ I ∧ I₀.Finite ∧ ∀ x, x ∈ B₀ \ I₀ → ¬Indep (insert x I₀) := by + have hch : ∀ (b : ↑(B₀ \ I)), ∃ Ib, Ib ⊆ I ∧ Ib.Finite ∧ ¬Indep (insert (b : α) Ib) := by + rintro ⟨b, hb⟩; exact htofin I b hI (hcon b ⟨hB₀B hb.1, hb.2⟩) + choose! f hf using hch + have : Finite ↑(B₀ \ I) := hB₀fin.diff.to_subtype + refine ⟨iUnion f ∪ (B₀ ∩ I), + union_subset (iUnion_subset (fun i ↦ (hf i).1)) inter_subset_right, + (finite_iUnion fun i ↦ (hf i).2.1).union (hB₀fin.subset inter_subset_left), + fun x ⟨hxB₀, hxn⟩ hi ↦ ?_⟩ + have hxI : x ∉ I := fun hxI ↦ hxn <| Or.inr ⟨hxB₀, hxI⟩ + refine (hf ⟨x, ⟨hxB₀, hxI⟩⟩).2.2 (indep_subset hi <| insert_subset_insert ?_) + apply subset_union_of_subset_left + apply subset_iUnion + + obtain ⟨I₀, hI₀I, hI₀fin, hI₀⟩ := hexI₀ + + set E₀ := insert e (I₀ ∪ B₀) + have hE₀fin : E₀.Finite := (hI₀fin.union hB₀fin).insert e + + -- Extend `B₀` to a maximal independent subset of `I₀ ∪ B₀ + e` + obtain ⟨J, ⟨hB₀J, hJ, hJss⟩, hJmax⟩ := Finite.exists_maximal_wrt (f := id) + (s := {J | B₀ ⊆ J ∧ Indep J ∧ J ⊆ E₀}) + (hE₀fin.finite_subsets.subset (by simp)) + ⟨B₀, Subset.rfl, hB₀, subset_union_right.trans (subset_insert _ _)⟩ + + have heI₀ : e ∉ I₀ := not_mem_subset hI₀I heI + have heI₀i : Indep (insert e I₀) := indep_subset hins (insert_subset_insert hI₀I) + + have heJ : e ∉ J := fun heJ ↦ hB₀e (indep_subset hJ <| insert_subset heJ hB₀J) + + have hJfin := hE₀fin.subset hJss + + -- We have `|I₀ + e| ≤ |J|`, since otherwise we could extend the maximal set `J` + have hcard : (insert e I₀).ncard ≤ J.ncard := by + refine not_lt.1 fun hlt ↦ ?_ + obtain ⟨f, hfI, hfJ, hfi⟩ := indep_aug hJ hJfin heI₀i (hI₀fin.insert e) hlt + have hfE₀ : f ∈ E₀ := mem_of_mem_of_subset hfI (insert_subset_insert subset_union_left) + refine hfJ (insert_eq_self.1 <| Eq.symm (hJmax _ + ⟨hB₀J.trans <| subset_insert _ _,hfi,insert_subset hfE₀ hJss⟩ (subset_insert _ _))) + + -- But this means `|I₀| < |J|`, and extending `I₀` into `J` gives a contradiction + rw [ncard_insert_of_not_mem heI₀ hI₀fin, ← Nat.lt_iff_add_one_le] at hcard + + obtain ⟨f, hfJ, hfI₀, hfi⟩ := indep_aug (indep_subset hI hI₀I) hI₀fin hJ hJfin hcard + exact hI₀ f ⟨Or.elim (hJss hfJ) (fun hfe ↦ (heJ <| hfe ▸ hfJ).elim) (by aesop), hfI₀⟩ hfi ) + (subset_ground := subset_ground) + +@[simp] theorem ofFinitaryCardAugment_indep (E : Set α) (Indep : Set α → Prop) + indep_empty indep_subset indep_aug indep_compact subset_ground : + (IndepMatroid.ofFinitaryCardAugment + E Indep indep_empty indep_subset indep_aug indep_compact subset_ground).Indep = Indep := rfl + +instance ofFinitaryCardAugment_finitary (E : Set α) (Indep : Set α → Prop) + indep_empty indep_subset indep_aug indep_compact subset_ground : Finitary + (IndepMatroid.ofFinitaryCardAugment + E Indep indep_empty indep_subset indep_aug indep_compact subset_ground).matroid := + ⟨by simpa⟩ + /-- If there is an absolute upper bound on the size of a set satisfying `P`, then the maximal subset property always holds. -/ theorem _root_.Matroid.existsMaximalSubsetProperty_of_bdd {P : Set α → Prop} @@ -380,7 +412,7 @@ protected def ofFinset [DecidableEq α] (E : Set α) (Indep : Finset α → Prop (indep_subset : ∀ ⦃I J⦄, Indep J → I ⊆ J → Indep I) (indep_aug : ∀ ⦃I J⦄, Indep I → Indep J → I.card < J.card → ∃ e ∈ J, e ∉ I ∧ Indep (insert e I)) (subset_ground : ∀ ⦃I⦄, Indep I → (I : Set α) ⊆ E) : IndepMatroid α := - IndepMatroid.ofFinitary + IndepMatroid.ofFinitaryCardAugment (E := E) (Indep := (fun I ↦ (∀ (J : Finset α), (J : Set α) ⊆ I → Indep J))) (indep_empty := by simpa [subset_empty_iff]) @@ -402,7 +434,7 @@ protected def ofFinset [DecidableEq α] (E : Set α) (Indep : Finset α → Prop @[simp] theorem ofFinset_indep [DecidableEq α] (E : Set α) Indep indep_empty indep_subset indep_aug subset_ground {I : Finset α} : (IndepMatroid.ofFinset E Indep indep_empty indep_subset indep_aug subset_ground).Indep I ↔ Indep I := by - simp only [IndepMatroid.ofFinset, ofFinitary_indep, Finset.coe_subset] + simp only [IndepMatroid.ofFinset, ofFinitaryCardAugment_indep, Finset.coe_subset] exact ⟨fun h ↦ h _ Subset.rfl, fun h J hJI ↦ indep_subset h hJI⟩ /-- This can't be `@[simp]`, because it would cause the more useful @@ -411,7 +443,7 @@ theorem ofFinset_indep' [DecidableEq α] (E : Set α) Indep indep_empty indep_su subset_ground {I : Set α} : (IndepMatroid.ofFinset E Indep indep_empty indep_subset indep_aug subset_ground).Indep I ↔ ∀ (J : Finset α), (J : Set α) ⊆ I → Indep J := by - simp only [IndepMatroid.ofFinset, ofFinitary_indep] + simp only [IndepMatroid.ofFinset, ofFinitaryCardAugment_indep] end IndepMatroid From 8f68dc4817a03cc315767a8a1b15684281fd504e Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:09:50 +0000 Subject: [PATCH 348/681] chore: rename ENNReal lemmas to mul_{left,right}_inj for consistency (#20880) --- Mathlib/Data/ENNReal/Operations.lean | 16 +++++++++++----- Mathlib/MeasureTheory/Measure/Haar/Unique.lean | 6 +++--- Mathlib/Probability/Independence/ZeroOne.lean | 2 +- Mathlib/Topology/MetricSpace/Dilation.lean | 4 ++-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Mathlib/Data/ENNReal/Operations.lean b/Mathlib/Data/ENNReal/Operations.lean index 24b26caf10c98..df6744aa82316 100644 --- a/Mathlib/Data/ENNReal/Operations.lean +++ b/Mathlib/Data/ENNReal/Operations.lean @@ -68,12 +68,18 @@ theorem mul_left_strictMono (h0 : a ≠ 0) (hinf : a ≠ ∞) : StrictMono (a * mul_comm b a ▸ mul_comm c a ▸ ENNReal.mul_left_strictMono h0 hinf bc -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: generalize to `WithTop` -theorem mul_eq_mul_left (h0 : a ≠ 0) (hinf : a ≠ ∞) : a * b = a * c ↔ b = c := +protected theorem mul_right_inj (h0 : a ≠ 0) (hinf : a ≠ ∞) : a * b = a * c ↔ b = c := (mul_left_strictMono h0 hinf).injective.eq_iff +@[deprecated (since := "2025-01-20")] +alias mul_eq_mul_left := ENNReal.mul_right_inj + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: generalize to `WithTop` -theorem mul_eq_mul_right : c ≠ 0 → c ≠ ∞ → (a * c = b * c ↔ a = b) := - mul_comm c a ▸ mul_comm c b ▸ mul_eq_mul_left +protected theorem mul_left_inj (h0 : c ≠ 0) (hinf : c ≠ ∞) : a * c = b * c ↔ a = b := + mul_comm c a ▸ mul_comm c b ▸ ENNReal.mul_right_inj h0 hinf + +@[deprecated (since := "2025-01-20")] +alias mul_eq_mul_right := ENNReal.mul_left_inj -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: generalize to `WithTop` theorem mul_le_mul_left (h0 : a ≠ 0) (hinf : a ≠ ∞) : a * b ≤ a * c ↔ b ≤ c := @@ -92,10 +98,10 @@ theorem mul_lt_mul_right : c ≠ 0 → c ≠ ∞ → (a * c < b * c ↔ a < b) : mul_comm c a ▸ mul_comm c b ▸ mul_lt_mul_left protected lemma mul_eq_left (ha₀ : a ≠ 0) (ha : a ≠ ∞) : a * b = a ↔ b = 1 := by - simpa using ENNReal.mul_eq_mul_left ha₀ ha (c := 1) + simpa using ENNReal.mul_right_inj ha₀ ha (c := 1) protected lemma mul_eq_right (hb₀ : b ≠ 0) (hb : b ≠ ∞) : a * b = b ↔ a = 1 := by - simpa using ENNReal.mul_eq_mul_right hb₀ hb (b := 1) + simpa using ENNReal.mul_left_inj hb₀ hb (b := 1) end Mul diff --git a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean index a4ed925b7ac08..3a14731891763 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean @@ -921,7 +921,7 @@ theorem _root_.MonoidHom.measurePreserving have : C * ν univ = 1 * ν univ := by rw [one_mul, ← smul_eq_mul, ← ENNReal.smul_def, ← smul_apply, ← hC, map_apply hcont.measurable .univ, preimage_univ, huniv] - rwa [ENNReal.mul_eq_mul_right (NeZero.ne _) (measure_ne_top _ _), ENNReal.coe_eq_one] at this + rwa [ENNReal.mul_left_inj (NeZero.ne _) (measure_ne_top _ _), ENNReal.coe_eq_one] at this end Group @@ -950,7 +950,7 @@ instance (priority := 100) IsHaarMeasure.isInvInvariant_of_regular conv_rhs => rw [μeq] simp have : c ^ 2 = 1 ^ 2 := - (ENNReal.mul_eq_mul_right (measure_pos_of_nonempty_interior _ K.interior_nonempty).ne' + (ENNReal.mul_left_inj (measure_pos_of_nonempty_interior _ K.interior_nonempty).ne' K.isCompact.measure_lt_top.ne).1 this have : c = 1 := (ENNReal.pow_right_strictMono two_ne_zero).injective this rw [hc, this, one_smul] @@ -975,7 +975,7 @@ instance (priority := 100) IsHaarMeasure.isInvInvariant_of_innerRegular conv_rhs => rw [μeq] simp have : c ^ 2 = 1 ^ 2 := - (ENNReal.mul_eq_mul_right (measure_pos_of_nonempty_interior _ K.interior_nonempty).ne' + (ENNReal.mul_left_inj (measure_pos_of_nonempty_interior _ K.interior_nonempty).ne' K.isCompact.measure_lt_top.ne).1 this have : c = 1 := (ENNReal.pow_right_strictMono two_ne_zero).injective this rw [hc, this, one_smul] diff --git a/Mathlib/Probability/Independence/ZeroOne.lean b/Mathlib/Probability/Independence/ZeroOne.lean index 06403152bcee2..f5d9ea44f6bd9 100644 --- a/Mathlib/Probability/Independence/ZeroOne.lean +++ b/Mathlib/Probability/Independence/ZeroOne.lean @@ -38,7 +38,7 @@ theorem Kernel.measure_eq_zero_or_one_or_top_of_indepSet_self {t : Set Ω} · exact Or.inl h0 by_cases h_top : κ a t = ∞ · exact Or.inr (Or.inr h_top) - rw [← one_mul (κ a (t ∩ t)), Set.inter_self, ENNReal.mul_eq_mul_right h0 h_top] at ha + rw [← one_mul (κ a (t ∩ t)), Set.inter_self, ENNReal.mul_left_inj h0 h_top] at ha exact Or.inr (Or.inl ha.symm) theorem measure_eq_zero_or_one_or_top_of_indepSet_self {t : Set Ω} diff --git a/Mathlib/Topology/MetricSpace/Dilation.lean b/Mathlib/Topology/MetricSpace/Dilation.lean index a04bf9dd698c2..8f1af1685861c 100644 --- a/Mathlib/Topology/MetricSpace/Dilation.lean +++ b/Mathlib/Topology/MetricSpace/Dilation.lean @@ -170,7 +170,7 @@ theorem dist_eq {α β F : Type*} [PseudoMetricSpace α] [PseudoMetricSpace β] `dist` and `nndist` versions below -/ theorem ratio_unique [DilationClass F α β] {f : F} {x y : α} {r : ℝ≥0} (h₀ : edist x y ≠ 0) (htop : edist x y ≠ ⊤) (hr : edist (f x) (f y) = r * edist x y) : r = ratio f := by - simpa only [hr, ENNReal.mul_eq_mul_right h₀ htop, ENNReal.coe_inj] using edist_eq f x y + simpa only [hr, ENNReal.mul_left_inj h₀ htop, ENNReal.coe_inj] using edist_eq f x y /-- The `ratio` is equal to the distance ratio for any two points with nonzero finite distance; `nndist` version -/ @@ -305,7 +305,7 @@ theorem ratio_comp' {g : β →ᵈ γ} {f : α →ᵈ β} (hne : ∃ x y : α, edist x y ≠ 0 ∧ edist x y ≠ ⊤) : ratio (g.comp f) = ratio g * ratio f := by rcases hne with ⟨x, y, hα⟩ have hgf := (edist_eq (g.comp f) x y).symm - simp_rw [coe_comp, Function.comp, edist_eq, ← mul_assoc, ENNReal.mul_eq_mul_right hα.1 hα.2] + simp_rw [coe_comp, Function.comp, edist_eq, ← mul_assoc, ENNReal.mul_left_inj hα.1 hα.2] at hgf rwa [← ENNReal.coe_inj, ENNReal.coe_mul] From 88adf8aa26c862ca962c253cbfb7d039861917fa Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Mon, 20 Jan 2025 16:38:02 +0000 Subject: [PATCH 349/681] doc(Order/KrullDimension): clarify docstring of height, coheight (#20868) --- Mathlib/Order/KrullDimension.lean | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Mathlib/Order/KrullDimension.lean b/Mathlib/Order/KrullDimension.lean index 8b7daccbce618..f55cfb93fbc83 100644 --- a/Mathlib/Order/KrullDimension.lean +++ b/Mathlib/Order/KrullDimension.lean @@ -76,14 +76,18 @@ noncomputable def krullDim (α : Type*) [Preorder α] : WithBot ℕ∞ := /-- The **height** of an element `a` in a preorder `α` is the supremum of the rightmost index of all -relation series of `α` ordered by `<` and ending below or at `a`. +relation series of `α` ordered by `<` and ending below or at `a`. In other words, it is +the largest `n` such that there's a series `a₀ < a₁ < ... < aₙ = a` (or `∞` if there is +no largest `n`). -/ noncomputable def height {α : Type*} [Preorder α] (a : α) : ℕ∞ := ⨆ (p : LTSeries α) (_ : p.last ≤ a), p.length /-- The **coheight** of an element `a` in a preorder `α` is the supremum of the rightmost index of all -relation series of `α` ordered by `<` and beginning with `a`. +relation series of `α` ordered by `<` and beginning with `a`. In other words, it is +the largest `n` such that there's a series `a = a₀ < a₁ < ... < aₙ` (or `∞` if there is +no largest `n`). The definition of `coheight` is via the `height` in the dual order, in order to easily transfer theorems between `height` and `coheight`. See `coheight_eq` for the definition with a From 0fecf8fc70de9830bd6e00dc09c867d4129b3ed7 Mon Sep 17 00:00:00 2001 From: grunweg Date: Mon, 20 Jan 2025 16:38:03 +0000 Subject: [PATCH 350/681] chore(100,1000.yaml): name the authors field 'authors' (#20875) Currently, there is some annoying inconsistency - the 1000 theorems project calls the field 'authors' - the 1000.yaml file calls it 'author', deviating from this - the 100.yaml file calls it 'author'. Change them all to 'authors' for consistency. Since formalisations are usually work of multiple people, this seems more appropriate, and matches the 1000+ theorem. --- docs/100.yaml | 162 ++++++++++++++++++------------------ docs/1000.yaml | 188 +++++++++++++++++++++--------------------- scripts/yaml_check.py | 4 +- 3 files changed, 177 insertions(+), 177 deletions(-) diff --git a/docs/100.yaml b/docs/100.yaml index 381ca2ffe57b6..2e1768b687e6a 100644 --- a/docs/100.yaml +++ b/docs/100.yaml @@ -8,24 +8,24 @@ 1: title : The Irrationality of the Square Root of 2 decl : irrational_sqrt_two - author : mathlib + authors: mathlib 2: title : Fundamental Theorem of Algebra decl : Complex.exists_root - author : Chris Hughes + authors: Chris Hughes 3: title : The Denumerability of the Rational Numbers decl : Rat.instDenumerable - author : Chris Hughes + authors: Chris Hughes 4: title : Pythagorean Theorem decl : EuclideanGeometry.dist_sq_eq_dist_sq_add_dist_sq_iff_angle_eq_pi_div_two - author : Joseph Myers + authors: Joseph Myers 5: title : Prime Number Theorem 6: title : Gödel’s Incompleteness Theorem - author : Shogo Saito + authors: Shogo Saito links : First incompleteness theorem: https://github.com/FormalizedFormalLogic/Incompleteness/blob/master/Incompleteness/Arith/First.lean Second incompleteness theorem: https://github.com/FormalizedFormalLogic/Incompleteness/blob/master/Incompleteness/Arith/Second.lean @@ -35,21 +35,21 @@ decls : - legendreSym.quadratic_reciprocity - jacobiSym.quadratic_reciprocity - author : Chris Hughes (first) and Michael Stoll (second) + authors: Chris Hughes (first) and Michael Stoll (second) 8: title : The Impossibility of Trisecting the Angle and Doubling the Cube 9: title : The Area of a Circle decl : Theorems100.area_disc - author : James Arthur and Benjamin Davidson and Andrew Souther + authors: James Arthur and Benjamin Davidson and Andrew Souther 10: title : Euler’s Generalization of Fermat’s Little Theorem decl : Nat.ModEq.pow_totient - author : Chris Hughes + authors: Chris Hughes 11: title : The Infinitude of Primes decl : Nat.exists_infinite_primes - author : Jeremy Avigad + authors: Jeremy Avigad 12: title : The Independence of the Parallel Postulate 13: @@ -57,46 +57,46 @@ 14: title : Euler’s Summation of 1 + (1/2)^2 + (1/3)^2 + …. decl : hasSum_zeta_two - author : Marc Masdeu and David Loeffler + authors: Marc Masdeu and David Loeffler 15: title : Fundamental Theorem of Integral Calculus decls : - intervalIntegral.integral_hasStrictDerivAt_of_tendsto_ae_right - intervalIntegral.integral_eq_sub_of_hasDeriv_right_of_le - author : Yury G. Kudryashov (first) and Benjamin Davidson (second) + authors: Yury G. Kudryashov (first) and Benjamin Davidson (second) 16: title : Insolvability of General Higher Degree Equations (Abel-Ruffini Theorem) - author : Thomas Browning + authors: Thomas Browning decl : AbelRuffini.exists_not_solvable_by_rad 17: title : De Moivre’s Formula decl : Complex.cos_add_sin_mul_I_pow - author : Abhimanyu Pallavi Sudhir + authors: Abhimanyu Pallavi Sudhir 18: title : Liouville’s Theorem and the Construction of Transcendental Numbers - author : Jujian Zhang + authors: Jujian Zhang decl : Liouville.transcendental 19: title : Four Squares Theorem decl : Nat.sum_four_squares - author : Chris Hughes + authors: Chris Hughes 20: title : All Primes (1 mod 4) Equal the Sum of Two Squares decl : Nat.Prime.sq_add_sq - author : Chris Hughes + authors: Chris Hughes 21: title : Green’s Theorem 22: title : The Non-Denumerability of the Continuum decl : Cardinal.not_countable_real - author : Floris van Doorn + authors: Floris van Doorn 23: title : Formula for Pythagorean Triples decl : PythagoreanTriple.classification - author : Paul van Wamelen + authors: Paul van Wamelen 24: title : The Independence of the Continuum Hypothesis - author : Jesse Michael Han and Floris van Doorn + authors: Jesse Michael Han and Floris van Doorn links : result: https://github.com/flypitch/flypitch/blob/master/src/summary.lean website: https://flypitch.github.io/ @@ -104,26 +104,26 @@ 25: title : Schroeder-Bernstein Theorem decl : Function.Embedding.schroeder_bernstein - author : Mario Carneiro + authors: Mario Carneiro 26: title : Leibniz’s Series for Pi decl : Real.tendsto_sum_pi_div_four - author : Benjamin Davidson + authors: Benjamin Davidson 27: title : Sum of the Angles of a Triangle decl : EuclideanGeometry.angle_add_angle_add_angle_eq_pi - author : Joseph Myers + authors: Joseph Myers 28: title : Pascal’s Hexagon Theorem 29: title : Feuerbach’s Theorem 30: title : The Ballot Problem - author : Bhavik Mehta and Kexing Ying + authors: Bhavik Mehta and Kexing Ying decl : Ballot.ballot_problem 31: title : Ramsey’s Theorem - author : Bhavik Mehta + authors: Bhavik Mehta links : result: https://github.com/b-mehta/combinatorics/blob/extras/src/inf_ramsey.lean 32: @@ -135,156 +135,156 @@ 34: title : Divergence of the Harmonic Series decl : Real.tendsto_sum_range_one_div_nat_succ_atTop - author : Anatole Dedecker and Yury Kudryashov + authors: Anatole Dedecker and Yury Kudryashov 35: title : Taylor’s Theorem decls : - taylor_mean_remainder_lagrange - taylor_mean_remainder_cauchy - author : Moritz Doll + authors: Moritz Doll 36: title : Brouwer Fixed Point Theorem - author : Brendan Seamas Murphy + authors: Brendan Seamas Murphy links : result: https://github.com/Shamrock-Frost/BrouwerFixedPoint/blob/master/src/brouwer_fixed_point.lean 37: title : The Solution of a Cubic - author : Jeoff Lee + authors: Jeoff Lee decl : Theorems100.cubic_eq_zero_iff 38: title : Arithmetic Mean/Geometric Mean decl : Real.geom_mean_le_arith_mean_weighted - author : Yury G. Kudryashov + authors: Yury G. Kudryashov 39: title : Solutions to Pell’s Equation decls : - Pell.eq_pell - Pell.exists_of_not_isSquare - author : Mario Carneiro (first), Michael Stoll (second) + authors: Mario Carneiro (first), Michael Stoll (second) note : "In `pell.eq_pell`, `d` is defined to be `a*a - 1` for an arbitrary `a > 1`." 40: title : Minkowski’s Fundamental Theorem decl : MeasureTheory.exists_ne_zero_mem_lattice_of_measure_mul_two_pow_lt_measure - author : Alex J. Best and Yaël Dillies + authors: Alex J. Best and Yaël Dillies 41: title : Puiseux’s Theorem 42: title : Sum of the Reciprocals of the Triangular Numbers - author : Jalex Stark and Yury Kudryashov + authors: Jalex Stark and Yury Kudryashov decl : Theorems100.inverse_triangle_sum 43: title : The Isoperimetric Theorem 44: title : The Binomial Theorem decl : add_pow - author : Chris Hughes + authors: Chris Hughes 45: title : The Partition Theorem - author : Bhavik Mehta and Aaron Anderson + authors: Bhavik Mehta and Aaron Anderson decl : Theorems100.partition_theorem 46: title : The Solution of the General Quartic Equation decl : Theorems100.quartic_eq_zero_iff - author : Thomas Zhu + authors: Thomas Zhu 47: title : The Central Limit Theorem 48: title : Dirichlet’s Theorem decl : Nat.setOf_prime_and_eq_mod_infinite - author : David Loeffler, Michael Stoll + authors: David Loeffler, Michael Stoll 49: title : The Cayley-Hamilton Theorem decl : Matrix.aeval_self_charpoly - author : Kim Morrison + authors: Kim Morrison 50: title : The Number of Platonic Solids 51: title : Wilson’s Lemma decl : ZMod.wilsons_lemma - author : Chris Hughes + authors: Chris Hughes 52: title : The Number of Subsets of a Set decl : Finset.card_powerset - author : mathlib + authors: mathlib 53: title : Pi is Transcendental 54: title : Königsberg Bridges Problem decl : Konigsberg.not_isEulerian - author : Kyle Miller + authors: Kyle Miller 55: title : Product of Segments of Chords decl : EuclideanGeometry.mul_dist_eq_mul_dist_of_cospherical_of_angle_eq_pi - author : Manuel Candales + authors: Manuel Candales 56: title : The Hermite-Lindemann Transcendence Theorem 57: title : Heron’s Formula decl : Theorems100.heron - author : Matt Kempster + authors: Matt Kempster 58: title : Formula for the Number of Combinations decls : - Finset.card_powersetCard - Finset.mem_powersetCard - author : mathlib + authors: mathlib 59: title : The Laws of Large Numbers decl : ProbabilityTheory.strong_law_ae - author : Sébastien Gouëzel + authors: Sébastien Gouëzel 60: title : Bezout’s Theorem decl : Nat.gcd_eq_gcd_ab - author : mathlib + authors: mathlib 61: title : Theorem of Ceva 62: title : Fair Games Theorem decl : MeasureTheory.submartingale_iff_expected_stoppedValue_mono - author : Kexing Ying + authors: Kexing Ying 63: title : Cantor’s Theorem decl: Function.cantor_surjective - author : Johannes Hölzl and Mario Carneiro + authors: Johannes Hölzl and Mario Carneiro 64: title : L’Hopital’s Rule decl : deriv.lhopital_zero_nhds - author : Anatole Dedecker + authors: Anatole Dedecker 65: title : Isosceles Triangle Theorem decl : EuclideanGeometry.angle_eq_angle_of_dist_eq - author : Joseph Myers + authors: Joseph Myers 66: title : Sum of a Geometric Series decls : - geom_sum_Ico - NNReal.hasSum_geometric - author : Sander R. Dahmen (finite) and Johannes Hölzl (infinite) + authors: Sander R. Dahmen (finite) and Johannes Hölzl (infinite) 67: title : e is Transcendental - author : Jujian Zhang + authors: Jujian Zhang links : result: https://github.com/jjaassoonn/transcendental/blob/master/src/e_transcendental.lean website: https://jjaassoonn.github.io/transcendental/ 68: title : Sum of an arithmetic series decl : Finset.sum_range_id - author : Johannes Hölzl + authors: Johannes Hölzl 69: title : Greatest Common Divisor Algorithm decls : - EuclideanDomain.gcd - EuclideanDomain.gcd_dvd - EuclideanDomain.dvd_gcd - author : mathlib + authors: mathlib 70: title : The Perfect Number Theorem decl : Theorems100.Nat.eq_two_pow_mul_prime_mersenne_of_even_perfect - author : Aaron Anderson + authors: Aaron Anderson 71: title : Order of a Subgroup decl : Subgroup.card_subgroup_dvd_card - author : mathlib + authors: mathlib 72: title : Sylow’s Theorem decls : @@ -292,42 +292,42 @@ - Sylow.isPretransitive_of_finite - Sylow.card_dvd_index - card_sylow_modEq_one - author : Chris Hughes + authors: Chris Hughes 73: title : Ascending or Descending Sequences (Erdős–Szekeres Theorem) decl : Theorems100.erdos_szekeres - author : Bhavik Mehta + authors: Bhavik Mehta 74: title : The Principle of Mathematical Induction decl : Nat note : Automatically generated when defining the natural numbers - author : Leonardo de Moura + authors: Leonardo de Moura 75: title : The Mean Value Theorem decl : exists_deriv_eq_slope - author : Yury G. Kudryashov + authors: Yury G. Kudryashov 76: title : Fourier Series decls : - fourierCoeff - hasSum_fourier_series_L2 - author : Heather Macbeth + authors: Heather Macbeth 77: title : Sum of kth powers decls : - sum_range_pow - sum_Ico_pow - author : Moritz Firsching and Fabian Kruse and Ashvni Narayanan + authors: Moritz Firsching and Fabian Kruse and Ashvni Narayanan 78: title : The Cauchy-Schwarz Inequality decls : - inner_mul_inner_self_le - norm_inner_le_norm - author : Zhouhang Zhou + authors: Zhouhang Zhou 79: title : The Intermediate Value Theorem decl : intermediate_value_Icc - author : Rob Lewis and Chris Hughes + authors: Rob Lewis and Chris Hughes 80: title : The Fundamental Theorem of Arithmetic decls : @@ -336,33 +336,33 @@ - EuclideanDomain.to_principal_ideal_domain - UniqueFactorizationMonoid - UniqueFactorizationMonoid.factors_unique - author : Chris Hughes + authors: Chris Hughes note : "it also has a generalized version, by showing that every Euclidean domain is a unique factorization domain, and showing that the integers form a Euclidean domain." 81: title : Divergence of the Prime Reciprocal Series decls : - Theorems100.Real.tendsto_sum_one_div_prime_atTop - not_summable_one_div_on_primes - author : Manuel Candales (archive), Michael Stoll (mathlib) + authors: Manuel Candales (archive), Michael Stoll (mathlib) 82: title : Dissection of Cubes (J.E. Littlewood’s ‘elegant’ proof) decl : Theorems100.«82».cannot_cube_a_cube - author : Floris van Doorn + authors: Floris van Doorn 83: title : The Friendship Theorem decl : Theorems100.friendship_theorem - author : Aaron Anderson and Jalex Stark and Kyle Miller + authors: Aaron Anderson and Jalex Stark and Kyle Miller 84: title : Morley’s Theorem 85: title : Divisibility by 3 Rule - author : Kim Morrison + authors: Kim Morrison decls : - Nat.three_dvd_iff 86: title : Lebesgue Measure and Integration decl : MeasureTheory.lintegral - author : Johannes Hölzl + authors: Johannes Hölzl 87: title : Desargues’s Theorem 88: @@ -370,22 +370,22 @@ decls : - card_derangements_eq_numDerangements - numDerangements_sum - author : Henry Swanson + authors: Henry Swanson 89: title : The Factor and Remainder Theorems decls : - Polynomial.dvd_iff_isRoot - Polynomial.mod_X_sub_C_eq_C_eval - author : Chris Hughes + authors: Chris Hughes 90: title : Stirling’s Formula decls : - Stirling.tendsto_stirlingSeq_sqrt_pi - author : Moritz Firsching and Fabian Kruse and Nikolas Kuhn and Heather Macbeth + authors: Moritz Firsching and Fabian Kruse and Nikolas Kuhn and Heather Macbeth 91: title : The Triangle Inequality decl : norm_add_le - author : Zhouhang Zhou + authors: Zhouhang Zhou 92: title : Pick’s Theorem 93: @@ -393,15 +393,15 @@ decls : - Theorems100.birthday - Theorems100.birthday_measure - author : Eric Rodriguez + authors: Eric Rodriguez 94: title : The Law of Cosines decl : EuclideanGeometry.dist_sq_eq_dist_sq_add_dist_sq_sub_two_mul_dist_mul_dist_mul_cos_angle - author : Joseph Myers + authors: Joseph Myers 95: title : Ptolemy’s Theorem decl : EuclideanGeometry.mul_dist_add_mul_dist_eq_mul_dist_of_cospherical - author : Manuel Candales + authors: Manuel Candales 96: title : Principle of Inclusion/Exclusion decls : @@ -411,24 +411,24 @@ - Finset.inclusion_exclusion_card_inf_compl links : github : https://github.com/NeilStrickland/lean_lib/blob/f88d162da2f990b87c4d34f5f46bbca2bbc5948e/src/combinatorics/matching.lean#L304 - author : Neil Strickland (outside mathlib), Yaël Dillies (in mathlib) + authors: Neil Strickland (outside mathlib), Yaël Dillies (in mathlib) 97: title : Cramer’s Rule decl : Matrix.mulVec_cramer - author : Anne Baanen + authors: Anne Baanen 98: title : Bertrand’s Postulate decl : Nat.bertrand - author : Bolton Bailey and Patrick Stevens + authors: Bolton Bailey and Patrick Stevens 99: title : Buffon Needle Problem links : decls : - BuffonsNeedle.buffon_short - BuffonsNeedle.buffon_long - author : Enrico Z. Borba + authors: Enrico Z. Borba 100: title : Descartes Rule of Signs links : github : https://github.com/Timeroot/lean-descartes-signs/ - author : Alex Meiburg + authors: Alex Meiburg diff --git a/docs/1000.yaml b/docs/1000.yaml index d2a6645ea7a96..fc2fe3e686f5e 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -17,7 +17,7 @@ Q11518: title: Pythagorean theorem decl: EuclideanGeometry.dist_sq_eq_dist_sq_add_dist_sq_iff_angle_eq_pi_div_two - author: Joseph Myers + authors: Joseph Myers Q12524: title: Schwenk's theorem @@ -25,14 +25,14 @@ Q12524: Q26708: title: Binomial theorem decl: add_pow - author: Chris Hughes + authors: Chris Hughes Q32182: title: Balinski's theorem Q33481: title: Arrow's impossibility theorem - author: Benjamin Davidson, Andrew Souther + authors: Benjamin Davidson, Andrew Souther date: 2021 url: https://github.com/asouther4/lean-social-choice/blob/master/src/arrows_theorem.lean @@ -56,7 +56,7 @@ Q132469: Q137164: title: Besicovitch covering theorem decl: Besicovitch.exists_disjoint_closedBall_covering_ae - author: Sébastien Gouëzel + authors: Sébastien Gouëzel date: 2021 Q154210: @@ -75,7 +75,7 @@ Q174955: Q179208: title: Cayley's theorem decl: Equiv.Perm.subgroupOfMulAction - author: Eric Wieser + authors: Eric Wieser date: 2021 Q179467: @@ -97,7 +97,7 @@ Q180345: Q182505: title: Bayes' theorem decl: ProbabilityTheory.cond_eq_inv_mul_cond_mul - author: Rishikesh Vaishnav + authors: Rishikesh Vaishnav date: 2022 Q184410: @@ -106,7 +106,7 @@ Q184410: Q188295: title: Fermat's little theorem decl: ZMod.pow_card_sub_one_eq_one - author: Aaron Anderson + authors: Aaron Anderson date: 2020 Q188745: @@ -118,7 +118,7 @@ Q189136: decls: - exists_deriv_eq_slope - exists_ratio_deriv_eq_ratio_slope - author: Yury G. Kudryashov + authors: Yury G. Kudryashov date: 2019 Q190026: @@ -134,25 +134,25 @@ Q190391: Q190556: title: De Moivre's theorem decl: Complex.cos_add_sin_mul_I_pow - author: Abhimanyu Pallavi Sudhir + authors: Abhimanyu Pallavi Sudhir date: 2019 Q191693: title: Lebesgue's decomposition theorem decl: MeasureTheory.Measure.haveLebesgueDecomposition_of_sigmaFinite - author: Kexing Ying + authors: Kexing Ying date: 2021 Q192760: title: Fundamental theorem of algebra decl: Complex.isAlgClosed - author: Chris Hughes + authors: Chris Hughes date: 2019 Q193286: title: Rolle's theorem decl: exists_deriv_eq_zero - author: Yury G. Kudryashov + authors: Yury G. Kudryashov date: 2019 Q193878: @@ -174,7 +174,7 @@ Q195133: Q200787: title: Gödel's incompleteness theorem - author: Shogo Saito + authors: Shogo Saito # TODO: how to display this data nicely? want two URLs, right? # results: # - First: https://github.com/FormalizedFormalLogic/Incompleteness/blob/master/Incompleteness/Arith/First.lean @@ -184,7 +184,7 @@ Q200787: Q203565: title: Solutions of a general cubic equation decl: Theorems100.cubic_eq_zero_iff - author: Jeoff Lee + authors: Jeoff Lee date: 2022 Q204884: @@ -202,7 +202,7 @@ Q207244: Q208416: title: Independence of the continuum hypothesis url: https://github.com/flypitch/flypitch/blob/d72904c17fbb874f01ffe168667ba12663a7b853/src/summary.lean#L90 - author: Floris van Doorn and Jesse Michael Han + authors: Floris van Doorn and Jesse Michael Han date: 2019-09-17 Q208756: @@ -240,7 +240,7 @@ Q242045: Q245098: title: Intermediate value theorem decl: intermediate_value_Icc - author: Rob Lewis and Chris Hughes + authors: Rob Lewis and Chris Hughes Q245098X: title: Bolzano's theorem @@ -267,7 +267,7 @@ Q256303: Q257387: title: Vitali theorem # i.e. existence of the Vitali set - author: Ching-Tsun Chou + authors: Ching-Tsun Chou url: https://github.com/ctchou/my_lean/blob/main/MyLean/NonMeasurable.lean comment: "mathlib4 pull request at https://github.com/leanprover-community/mathlib4/pull/20722" @@ -295,7 +295,7 @@ Q273037: Q276082: title: Wilson's theorem decl: ZMod.wilsons_lemma - author: Chris Hughes + authors: Chris Hughes Q280116: title: Odd number theorem @@ -331,7 +331,7 @@ Q318767: decls: - Complex.tendsto_tsum_powerSeries_nhdsWithin_stolzCone - Real.tendsto_tsum_powerSeries_nhdsWithin_lt - author: Jeremy Tan + authors: Jeremy Tan Q321237: title: Green's theorem @@ -402,7 +402,7 @@ Q420714: Q422187: title: Myhill–Nerode theorem decl: Language.isRegular_iff_finite_range_leftQuotient - author: Chris Wong + authors: Chris Wong date: 2024-03-24 Q425432: @@ -414,7 +414,7 @@ Q428134: Q459547: title: Ptolemy's theorem decl: EuclideanGeometry.mul_dist_add_mul_dist_eq_mul_dist_of_cospherical - author: Manuel Candales + authors: Manuel Candales Q467205: title: Fundamental theorems of welfare economics @@ -431,25 +431,25 @@ Q468391: Q470877: title: Stirling's theorem decl: Stirling.tendsto_stirlingSeq_sqrt_pi - author: Moritz Firsching and Fabian Kruse and Nikolas Kuhn and Heather Macbeth + authors: Moritz Firsching and Fabian Kruse and Nikolas Kuhn and Heather Macbeth Q472883: title: Quadratic reciprocity theorem decls: - legendreSym.quadratic_reciprocity - jacobiSym.quadratic_reciprocity - author: Chris Hughes (first) and Michael Stoll (second) + authors: Chris Hughes (first) and Michael Stoll (second) Q474881: title: Cantor's theorem # a.k.a. Cantor's diagonal argument decl: Function.cantor_surjective - author: Johannes Hölzl and Mario Carneiro + authors: Johannes Hölzl and Mario Carneiro Q476776: title: Solutions of a general quartic equation decl: Theorems100.quartic_eq_zero_iff - author: Thomas Zhu + authors: Thomas Zhu Q487132: title: Infinite monkey theorem @@ -510,7 +510,7 @@ Q544369: Q550402: title: Dirichlet's theorem on arithmetic progressions decl: Nat.setOf_prime_and_eq_mod_infinite - author: David Loeffler, Michael Stoll + authors: David Loeffler, Michael Stoll Q552367: title: Berge's theorem @@ -564,7 +564,7 @@ Q608294: Q609612: title: Knaster–Tarski theorem decl: fixedPoints.completeLattice - author: Kenny Lau + authors: Kenny Lau date: 2018 Q612021: @@ -591,7 +591,7 @@ Q632546X: Q632546: title: Bertrand's postulate decl: Nat.bertrand - author: Bolton Bailey and Patrick Stevens + authors: Bolton Bailey and Patrick Stevens Q637418: title: Napoleon's theorem @@ -599,7 +599,7 @@ Q637418: Q642620: title: Krein–Milman theorem decl: closure_convexHull_extremePoints - author: Yaël Dillies + authors: Yaël Dillies date: 2022 Q643513: @@ -639,7 +639,7 @@ Q656645: Q656772: title: Cayley–Hamilton theorem decl: Matrix.aeval_self_charpoly - author: Kim Morrison + authors: Kim Morrison Q657469: title: Lefschetz fixed-point theorem @@ -649,7 +649,7 @@ Q657469X: Q657482: title: Abel–Ruffini theorem - author: Thomas Browning + authors: Thomas Browning decl: AbelRuffini.exists_not_solvable_by_rad Q657903: @@ -668,7 +668,7 @@ Q670235: - EuclideanDomain.to_principal_ideal_domain - UniqueFactorizationMonoid - UniqueFactorizationMonoid.factors_unique - author: Chris Hughes + authors: Chris Hughes comment: "it also has a generalized version, by showing that every Euclidean domain is a unique factorization domain, and showing that the integers form a Euclidean domain." Q671663: @@ -692,13 +692,13 @@ Q693083: Q716171: title: Erdős–Ginzburg–Ziv theorem decl: ZMod.erdos_ginzburg_ziv - author: Yaël Dillies + authors: Yaël Dillies date: 2023 Q718875: title: Erdős–Ko–Rado theorem decl: Finset.erdos_ko_rado - author: Bhavik Mehta, Yaël Dillies + authors: Bhavik Mehta, Yaël Dillies date: 2020 Q719966: @@ -707,7 +707,7 @@ Q719966: Q720469: title: Chevalley–Warning theorem decl: char_dvd_card_solutions_of_sum_lt - author: Johan Commelin + authors: Johan Commelin date: 2019 Q721695: @@ -747,7 +747,7 @@ Q744440: Q748233: title: Sylvester–Gallai theorem - author: Bhavik Mehta + authors: Bhavik Mehta url: https://github.com/YaelDillies/LeanCamCombi/blob/6a6a670f324b2af82ae17f21f9d51ac0bc859f6f/LeanCamCombi/SylvesterChvatal.lean#L610 date: 2022 @@ -757,7 +757,7 @@ Q751120: Q752375: title: Extreme value theorem decl: IsCompact.exists_isMinOn - author: Sébastien Gouëzel + authors: Sébastien Gouëzel date: 2018 Q755986: @@ -769,13 +769,13 @@ Q755991: Q756946: title: Lagrange's four-square theorem decl: Nat.sum_four_squares - author: Chris Hughes + authors: Chris Hughes date: 2019 Q764287: title: Van der Waerden's theorem decl: Combinatorics.exists_mono_homothetic_copy - author: David Wärn + authors: David Wärn # TODO: this is only some version; should this entry be modified accordingly? Q765987: @@ -831,7 +831,7 @@ Q830513: Q834025: title: Cauchy integral theorem decl: Complex.circleIntegral_div_sub_of_differentiable_on_off_countable - author: Yury Kudryashov + authors: Yury Kudryashov date: 2021 Q834211: @@ -839,7 +839,7 @@ Q834211: Q837506: title: Theorem on friends and strangers - author: Bhavik Mehta + authors: Bhavik Mehta url: https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/Small.20Ramsey.20numbers/near/490303695 comment: "will enter mathlib in 2024" @@ -853,7 +853,7 @@ Q841893: Q842953: title: Lebesgue's density theorem decl: Besicovitch.ae_tendsto_measure_inter_div - author: Oliver Nash + authors: Oliver Nash date: 2022 Q844612: @@ -892,7 +892,7 @@ Q853067: decls: - Pell.eq_pell - Pell.exists_of_not_isSquare - author: Mario Carneiro (first), Michael Stoll (second) + authors: Mario Carneiro (first), Michael Stoll (second) comment: "In `pell.eq_pell`, `d` is defined to be `a*a - 1` for an arbitrary `a > 1`." Q856032: @@ -969,14 +969,14 @@ Q913849: Q914517: title: Fermat's theorem on sums of two squares decl: Nat.Prime.sq_add_sq - author: Chris Hughes + authors: Chris Hughes Q915474: title: Robin's theorem Q918099: title: Ramsey's theorem - author: Bhavik Mehta + authors: Bhavik Mehta url: https://github.com/b-mehta/combinatorics/blob/extras/src/inf_ramsey.lean Q922012: @@ -1013,7 +1013,7 @@ Q931404: Q939927: title: Stone–Weierstrass theorem decl: ContinuousMap.subalgebra_topologicalClosure_eq_top_of_separatesPoints - author: Scott Morrison and Heather Macbeth + authors: Scott Morrison and Heather Macbeth date: 2021-05-01 Q942046: @@ -1030,7 +1030,7 @@ Q944297: Q948664: title: Kneser's addition theorem - author: Mantas Bakšys, Yaël Dillies + authors: Mantas Bakšys, Yaël Dillies url: https://github.com/YaelDillies/LeanCamCombi/blob/master/LeanCamCombi/Kneser/Kneser.lean date: 2022 @@ -1065,7 +1065,7 @@ Q976033: Q976607: title: Erdős–Szekeres theorem decl: Theorems100.erdos_szekeres - author: Bhavik Mehta + authors: Bhavik Mehta Q977912: title: Stolper–Samuelson theorem @@ -1091,12 +1091,12 @@ Q1008566: Q1032886: title: Hales–Jewett theorem decl: Combinatorics.Line.exists_mono_in_high_dimension - author: David Wärn + authors: David Wärn Q1033910: title: Cantor–Bernstein–Schroeder theorem decl: Function.Embedding.schroeder_bernstein - author: Mario Carneiro + authors: Mario Carneiro Q1037559: title: Pólya enumeration theorem @@ -1111,7 +1111,7 @@ Q1046232: Q1047749: title: Turán's theorem decl: SimpleGraph.isTuranMaximal_iff_nonempty_iso_turanGraph - author: Jeremy Tan + authors: Jeremy Tan Q1048589: title: Hohenberg–Kohn theorems @@ -1130,7 +1130,7 @@ Q1050203: Q1050932: title: Hartogs's theorem url: https://github.com/girving/ray/blob/main/Ray/Hartogs/Hartogs.lean - author: Geoffrey Irving + authors: Geoffrey Irving Q1051404: title: Cesàro's theorem @@ -1220,7 +1220,7 @@ Q1077741: Q1082910: title: Euler's partition theorem - author: Bhavik Mehta and Aaron Anderson + authors: Bhavik Mehta and Aaron Anderson decl: Theorems100.partition_theorem Q1095330: @@ -1231,7 +1231,7 @@ Q1095330: Q1097021: title: Minkowski's theorem decl: MeasureTheory.exists_ne_zero_mem_lattice_of_measure_mul_two_pow_lt_measure - author: Alex J. Best and Yaël Dillies + authors: Alex J. Best and Yaël Dillies date: 2021 Q1103054: @@ -1282,7 +1282,7 @@ Q1137206: decls: - taylor_mean_remainder_lagrange - taylor_mean_remainder_cauchy - author: Moritz Doll + authors: Moritz Doll Q1139041: title: Cauchy's theorem @@ -1309,7 +1309,7 @@ Q1143540: Q1144897: title: Brouwer fixed-point theorem - author: Brendan Seamas Murphy + authors: Brendan Seamas Murphy url: https://github.com/Shamrock-Frost/BrouwerFixedPoint/blob/master/src/brouwer_fixed_point.lean comment: "in Lean 3" @@ -1391,7 +1391,7 @@ Q1191319: Q1191709: title: Egorov's theorem decl: MeasureTheory.tendstoUniformlyOn_of_ae_tendsto - author: Kexing Ying + authors: Kexing Ying Q1191862: title: Rouché's theorem @@ -1418,7 +1418,7 @@ Q1217677: decls: - intervalIntegral.integral_hasStrictDerivAt_of_tendsto_ae_right - intervalIntegral.integral_eq_sub_of_hasDeriv_right_of_le - author: Yury G. Kudryashov (first) and Benjamin Davidson (second) + authors: Yury G. Kudryashov (first) and Benjamin Davidson (second) Q1227061: title: Khinchin's theorem @@ -1435,7 +1435,7 @@ Q1242398: Q1243340: title: Birkhoff–Von Neumann theorem decl: doublyStochastic_eq_convexHull_permMatrix - author: Bhavik Mehta + authors: Bhavik Mehta date: 2024 Q1249069: @@ -1544,7 +1544,7 @@ Q1425529: Q1426292: title: Banach–Steinhaus theorem decl: banach_steinhaus - author: Jireh Loreaux + authors: Jireh Loreaux date: 2021 Q1434158: @@ -1581,7 +1581,7 @@ Q1505529: Q1506253: title: Euclid's theorem decl: Nat.exists_infinite_primes - author: Jeremy Avigad + authors: Jeremy Avigad Q1529941: title: Peter–Weyl theorem @@ -1595,7 +1595,7 @@ Q1535225: Q1542114: title: Bézout's theorem decl: Nat.gcd_eq_gcd_ab - author: mathlib + authors: mathlib Q1543149: title: Sokhatsky–Weierstrass theorem @@ -1615,7 +1615,7 @@ Q1564541: Q1566341: title: Hindman's theorem decl: Hindman.FP_partition_regular - author: David Wärn + authors: David Wärn Q1566372: title: Haag's theorem @@ -1626,7 +1626,7 @@ Q1568612: Q1568811: title: Hahn decomposition theorem decl: MeasureTheory.SignedMeasure.exists_isCompl_positive_negative - author: Kexing Ying + authors: Kexing Ying date: 2021 Q1572474: @@ -1659,7 +1659,7 @@ Q1632301: Q1632433: title: Helly's theorem - author: Vasily Nesterov + authors: Vasily Nesterov decl: Convex.helly_theorem date: 2023 @@ -1678,7 +1678,7 @@ Q1683356: Q1687147: title: Sprague–Grundy theorem decl: SetTheory.PGame.equiv_nim_grundyValue - author: Fox Thomson + authors: Fox Thomson date: 2020 Q1694565: @@ -1822,7 +1822,7 @@ Q2022775: Q2027347: title: Optional stopping theorem decl: MeasureTheory.submartingale_iff_expected_stoppedValue_mono - author: Kexing Ying, Rémy Degenne + authors: Kexing Ying, Rémy Degenne date: 2022 Q2028341: @@ -1918,13 +1918,13 @@ Q2226774: Q2226786: title: Sperner's theorem decl: IsAntichain.sperner - author: Bhavik Mehta, Alena Gusakov, Yaël Dillies + authors: Bhavik Mehta, Alena Gusakov, Yaël Dillies date: 2022 Q2226800: title: Schur–Zassenhaus theorem decl: Subgroup.exists_left_complement'_of_coprime - author: Thomas Browning + authors: Thomas Browning date: 2021 Q2226803: @@ -1936,7 +1936,7 @@ Q2226807: Q2226855: title: Sharkovskii's theorem # TODO: Find the code - author: Bhavik Mehta + authors: Bhavik Mehta date: 2022 Q2226868: @@ -1947,7 +1947,7 @@ Q2226962: Q2253746: title: Bertrand's ballot theorem - author: Bhavik Mehta and Kexing Ying + authors: Bhavik Mehta and Kexing Ying decl: Ballot.ballot_problem Q2266397: @@ -1965,7 +1965,7 @@ Q2270905: Q2275191: title: Lebesgue differentiation theorem decl: VitaliFamily.ae_tendsto_lintegral_div - author: Sébastien Gouëzel + authors: Sébastien Gouëzel date: 2021 Q2277040: @@ -2120,7 +2120,7 @@ Q2916568: Q2919401: title: Ostrowski's theorem decl: Rat.AbsoluteValue.equiv_real_or_padic - author: David Kurniadi Angdinata, Fabrizio Barroero, Laura Capuano, Nirvana Coppola, María Inés de Frutos-Fernández, Sam van Gool, Silvain Rideau-Kikuchi, Amos Turchet, Francesco Veneziano + authors: David Kurniadi Angdinata, Fabrizio Barroero, Laura Capuano, Nirvana Coppola, María Inés de Frutos-Fernández, Sam van Gool, Silvain Rideau-Kikuchi, Amos Turchet, Francesco Veneziano date: 2024 Q2981012: @@ -2168,7 +2168,7 @@ Q3229335: Q3229352: title: Vitali covering theorem decl: Vitali.exists_disjoint_covering_ae - author: Sébastien Gouëzel + authors: Sébastien Gouëzel date: 2021 Q3345678: @@ -2206,7 +2206,7 @@ Q3526993: Q3526996: title: Kolmogorov extension theorem - author: Rémy Degenne, Peter Pfaffelhuber + authors: Rémy Degenne, Peter Pfaffelhuber date: 2023 url: https://github.com/RemyDegenne/kolmogorov_extension4 @@ -2279,7 +2279,7 @@ Q3527100: Q3527102: title: Kruskal–Katona theorem decl: Finset.kruskal_katona - author: Bhavik Mehta, Yaël Dillies + authors: Bhavik Mehta, Yaël Dillies date: 2020 Q3527110: @@ -2339,7 +2339,7 @@ Q3527214: Q3527215: title: Hilbert projection theorem decl: exists_norm_eq_iInf_of_complete_convex - author: Zhouhang Zhou + authors: Zhouhang Zhou date: 2019 Q3527217: @@ -2372,13 +2372,13 @@ Q3527247: Q3527250: title: Hadamard three-lines theorem decl: Complex.HadamardThreeLines.norm_le_interpStrip_of_mem_verticalClosedStrip - author: Xavier Généreux + authors: Xavier Généreux date: 2023 Q3527263: title: Kleene fixed-point theorem decl: fixedPoints.lfp_eq_sSup_iterate - author: Ira Fesefeldt + authors: Ira Fesefeldt date: 2024 Q3527279: @@ -2436,7 +2436,7 @@ Q3984052: Q3984053: title: Fourier inversion theorem decl: Continuous.fourier_inversion - author: Sébastien Gouëzel + authors: Sébastien Gouëzel date: 2024 Q3984056: @@ -2469,7 +2469,7 @@ Q4272645: Q4378868: title: Phragmén–Lindelöf theorem decl: PhragmenLindelof.horizontal_strip - author: Yury G. Kudryashov + authors: Yury G. Kudryashov date: 2022 Q4378889: @@ -2560,7 +2560,7 @@ Q4677985: Q4695203: title: Four functions theorem decl: four_functions_theorem - author: Yaël Dillies + authors: Yaël Dillies date: 2023 Q4700718: @@ -2632,7 +2632,7 @@ Q4827308: Q4830725: title: Ax–Grothendieck theorem decl: ax_grothendieck_zeroLocus - author: Chris Hughes + authors: Chris Hughes date: 2023 Q4832965: @@ -2848,7 +2848,7 @@ Q5166389: Q5171652: title: Corners theorem decl: corners_theorem_nat - author: Yaël Dillies, Bhavik Mehta + authors: Yaël Dillies, Bhavik Mehta date: 2022 Q5172143: @@ -3000,7 +3000,7 @@ Q5503689: Q5504427: title: Friendship theorem decl: Theorems100.friendship_theorem - author: Aaron Anderson and Jalex Stark and Kyle Miller + authors: Aaron Anderson and Jalex Stark and Kyle Miller Q5505098: title: Frobenius determinant theorem @@ -3276,7 +3276,7 @@ Q6749789: Q6757284: title: Marcinkiewicz theorem - author: Jim Portegies + authors: Jim Portegies date: 2024-09-06 url: https://github.com/fpvandoorn/carleson/blob/master/Carleson/RealInterpolation.lean # will become part of mathlib; update URL in this case! @@ -3532,7 +3532,7 @@ Q7433034: Q7433182: title: Schwartz–Zippel theorem decl: MvPolynomial.schwartz_zippel_sup_sum - author: Bolton Bailey, Yaël Dillies + authors: Bolton Bailey, Yaël Dillies date: 2023 Q7433295: @@ -3693,7 +3693,7 @@ Q7857350: Q7888360: title: Structure theorem for finitely generated modules over a principal ideal domain decl: Module.equiv_free_prod_directSum - author: Pierre-Alexandre Bazin + authors: Pierre-Alexandre Bazin date: 2022 Q7894110: @@ -3759,7 +3759,7 @@ Q8066795: Q8074796: title: Zsigmondy's theorem # TODO: Find the code - author: Mantas Bakšys + authors: Mantas Bakšys date: 2022 Q8081891: @@ -3781,7 +3781,7 @@ Q10942247: Q11352023: title: Vitali convergence theorem decl: MeasureTheory.tendstoInMeasure_iff_tendsto_Lp - author: Igor Khavkine + authors: Igor Khavkine date: 2024 Q11573495: @@ -3820,7 +3820,7 @@ Q15895894: Q16251580: title: Matiyasevich's theorem decl: Pell.matiyasevic - author: Mario Carneiro + authors: Mario Carneiro date: 2017 Q16680059: @@ -3841,7 +3841,7 @@ Q17003552: Q17005116: title: Birkhoff's representation theorem decl: LatticeHom.birkhoffSet - author: Yaël Dillies + authors: Yaël Dillies date: 2022 Q17008559: @@ -3911,7 +3911,7 @@ Q18206266: title: Euclid–Euler theorem # a.k.a. perfect number theorem decl: Theorems100.Nat.eq_two_pow_mul_prime_mersenne_of_even_perfect - author: Aaron Anderson + authors: Aaron Anderson Q18630480: title: Euler's quadrilateral theorem @@ -3931,7 +3931,7 @@ Q20971632: Q22952648: title: Uncountability of the continuum decl: Cardinal.not_countable_real - author: Floris van Doorn + authors: Floris van Doorn Q25099402: title: Kolmogorov–Arnold representation theorem diff --git a/scripts/yaml_check.py b/scripts/yaml_check.py index d9e9a51cfc842..cc375456c8c6f 100644 --- a/scripts/yaml_check.py +++ b/scripts/yaml_check.py @@ -58,7 +58,7 @@ class HundredTheorem: # like |decl|, but a list of declarations (if one theorem is split into multiple declarations) (optional) decls: Optional[List[str]] = None # name(s) of the author(s) of this formalization (optional) - author: Optional[str] = None + authors: Optional[str] = None # Date of the formalization, in the form `YYYY`, `YYYY-MM` or `YYYY-MM-DD` (optional) date: Optional[str] = None links: Optional[Mapping[str, str]] = None @@ -87,7 +87,7 @@ class ThousandPlusTheorem: # like |decl|, but a list of declarations (if one theorem is split into multiple declarations) (optional) decls: Optional[List[str]] = None # name(s) of the author(s) of this formalization (optional) - author: Optional[str] = None + authors: Optional[str] = None # Date of the formalization, in the form `YYYY`, `YYYY-MM` or `YYYY-MM-DD` (optional) date: Optional[str] = None # for external projects, an URL referring to the result From 2a250b52ea6fbc4c6e5701e1ca35c27b3df6380e Mon Sep 17 00:00:00 2001 From: grunweg Date: Mon, 20 Jan 2025 16:38:04 +0000 Subject: [PATCH 351/681] fix(Linter/Style.lean): fix some outdated comments (#20879) --- Mathlib/Tactic/Linter/Style.lean | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Mathlib/Tactic/Linter/Style.lean b/Mathlib/Tactic/Linter/Style.lean index bbe2f16f58a98..efae3b7795163 100644 --- a/Mathlib/Tactic/Linter/Style.lean +++ b/Mathlib/Tactic/Linter/Style.lean @@ -17,7 +17,7 @@ but do not affect correctness nor global coherence of mathlib. Historically, some of these were ported from the `lint-style.py` Python script. This file defines the following linters: -- the `set_option` linter checks for the presence of `set_option` commands activating +- the `setOption` linter checks for the presence of `set_option` commands activating options disallowed in mathlib: these are meant to be temporary, and not for polished code - the `missingEnd` linter checks for sections or namespaces which are not closed by the end of the file: enforcing this invariant makes minimising files or moving code between files easier @@ -26,12 +26,10 @@ this is allowed Lean syntax, but it is nicer to be uniform - the `dollarSyntax` linter checks for use of the dollar sign `$` instead of the `<|` pipe operator: similarly, both symbols have the same meaning, but mathlib prefers `<|` for the symmetry with the `|>` symbol -- the `lambdaSyntax` linter checks for uses of the `λ` symbol for ananomous functions, +- the `lambdaSyntax` linter checks for uses of the `λ` symbol for anonymous functions, instead of the `fun` keyword: mathlib prefers the latter for reasons of readability -(This linter is still under review in PR #15896.) +- the `longFile` linter checks for files which have more than 1500 lines - the `longLine` linter checks for lines which have more than 100 characters -- the `longFile` linter checks for files which have more than 1500 lines: -this linter is still under development in PR #15610. All of these linters are enabled in mathlib by default, but disabled globally since they enforce conventions which are inherently subjective. From 535a874a33e8f661b09763c4001184ae6ab4ebb2 Mon Sep 17 00:00:00 2001 From: Peiran Wu <15968905+wupr@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:23:57 +0000 Subject: [PATCH 352/681] feat(GroupTheory/SpecificGroups): dihedral groups are not cyclic (with one exception) (#20817) --- Mathlib/Data/ZMod/Basic.lean | 3 ++ .../GroupTheory/SpecificGroups/Cyclic.lean | 29 ++++++++++++++----- .../GroupTheory/SpecificGroups/Dihedral.lean | 17 ++++++++++- .../GroupTheory/SpecificGroups/KleinFour.lean | 4 +-- Mathlib/GroupTheory/Transfer.lean | 5 +--- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/Mathlib/Data/ZMod/Basic.lean b/Mathlib/Data/ZMod/Basic.lean index fec363551b146..ef6d34d2aedac 100644 --- a/Mathlib/Data/ZMod/Basic.lean +++ b/Mathlib/Data/ZMod/Basic.lean @@ -705,6 +705,9 @@ theorem val_injective (n : ℕ) [NeZero n] : Function.Injective (val : ZMod n theorem val_one_eq_one_mod (n : ℕ) : (1 : ZMod n).val = 1 % n := by rw [← Nat.cast_one, val_natCast] +theorem val_two_eq_two_mod (n : ℕ) : (2 : ZMod n).val = 2 % n := by + rw [← Nat.cast_two, val_natCast] + theorem val_one (n : ℕ) [Fact (1 < n)] : (1 : ZMod n).val = 1 := by rw [val_one_eq_one_mod] exact Nat.mod_eq_of_lt Fact.out diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index 23b0bc5cfb952..faf9e2b92885d 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -8,6 +8,7 @@ import Mathlib.Data.Nat.Totient import Mathlib.Data.ZMod.Aut import Mathlib.Data.ZMod.Quotient import Mathlib.GroupTheory.OrderOfElement +import Mathlib.GroupTheory.SpecificGroups.Dihedral import Mathlib.GroupTheory.Subgroup.Simple import Mathlib.Tactic.Group import Mathlib.GroupTheory.Exponent @@ -73,21 +74,25 @@ theorem isAddCyclic_additive_iff [Group α] : IsAddCyclic (Additive α) ↔ IsCy instance isAddCyclic_additive [Group α] [IsCyclic α] : IsAddCyclic (Additive α) := isAddCyclic_additive_iff.mpr inferInstance +@[to_additive] +instance IsCyclic.commutative [Group α] [IsCyclic α] : + Std.Commutative (· * · : α → α → α) where + comm x y := + let ⟨_, hg⟩ := IsCyclic.exists_generator (α := α) + let ⟨_, hx⟩ := hg x + let ⟨_, hy⟩ := hg y + hy ▸ hx ▸ zpow_mul_comm _ _ _ + /-- A cyclic group is always commutative. This is not an `instance` because often we have a better proof of `CommGroup`. -/ @[to_additive "A cyclic group is always commutative. This is not an `instance` because often we have a better proof of `AddCommGroup`."] def IsCyclic.commGroup [hg : Group α] [IsCyclic α] : CommGroup α := - { hg with - mul_comm := fun x y => - let ⟨_, hg⟩ := IsCyclic.exists_generator (α := α) - let ⟨_, hn⟩ := hg x - let ⟨_, hm⟩ := hg y - hm ▸ hn ▸ zpow_mul_comm _ _ _ } + { hg with mul_comm := commutative.comm } instance [Group G] (H : Subgroup G) [IsCyclic H] : H.IsCommutative := - ⟨⟨IsCyclic.commGroup.mul_comm⟩⟩ + ⟨IsCyclic.commutative⟩ variable [Group α] [Group G] [Group G'] @@ -858,3 +863,13 @@ lemma mulEquivOfOrderOfEq_symm_apply_gen : (mulEquivOfOrderOfEq hg hg' h).symm g end mulEquiv end generator + +lemma DihedralGroup.not_isCyclic {n : ℕ} (h1 : n ≠ 1) : ¬IsCyclic (DihedralGroup n) := fun h' => by + by_cases h2 : n = 2 + · simpa [exponent, card, h2] using h'.exponent_eq_card + · exact not_commutative h1 h2 h'.commutative + +lemma DihedralGroup.isCyclic_iff {n : ℕ} : + IsCyclic (DihedralGroup n) ↔ n = 1 where + mp := by contrapose; exact not_isCyclic + mpr := by rintro rfl; exact isCyclic_of_prime_card (p := 2) nat_card diff --git a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean index 4f4b580852404..49a2df71269d5 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean @@ -3,10 +3,10 @@ Copyright (c) 2020 Shing Tak Lam. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Shing Tak Lam -/ +import Mathlib.Data.Finite.Sum import Mathlib.Data.ZMod.Basic import Mathlib.GroupTheory.Exponent import Mathlib.GroupTheory.GroupAction.CardCommute -import Mathlib.Data.Finite.Sum /-! # Dihedral Groups @@ -208,6 +208,21 @@ theorem exponent : Monoid.exponent (DihedralGroup n) = lcm n 2 := by · convert Monoid.order_dvd_exponent (sr (0 : ZMod n)) exact (orderOf_sr 0).symm +lemma not_commutative : ∀ {n : ℕ}, n ≠ 1 → n ≠ 2 → + ¬Std.Commutative fun (x y : DihedralGroup n) => x * y + | 0, _, _ => fun ⟨h'⟩ ↦ by simpa using h' (r 1) (sr 0) + | n + 3, _, _ => by + rintro ⟨h'⟩ + specialize h' (r 1) (sr 0) + rw [r_mul_sr, zero_sub, sr_mul_r, zero_add, sr.injEq, neg_eq_iff_add_eq_zero, + one_add_one_eq_two, ← ZMod.val_eq_zero, ZMod.val_two_eq_two_mod] at h' + simpa using Nat.le_of_dvd Nat.zero_lt_two <| Nat.dvd_of_mod_eq_zero h' + +lemma commutative_iff {n : ℕ} : + Std.Commutative (fun x y : DihedralGroup n ↦ x * y) ↔ n = 1 ∨ n = 2 where + mp := by contrapose!; rintro ⟨h1, h2⟩; exact not_commutative h1 h2 + mpr := by rintro (rfl | rfl) <;> exact ⟨by decide⟩ + /-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs (represented as $n + n + n + n*n$) of commuting elements. -/ @[simps] diff --git a/Mathlib/GroupTheory/SpecificGroups/KleinFour.lean b/Mathlib/GroupTheory/SpecificGroups/KleinFour.lean index 2ad3ed38cd7f4..542ab4e01b5a7 100644 --- a/Mathlib/GroupTheory/SpecificGroups/KleinFour.lean +++ b/Mathlib/GroupTheory/SpecificGroups/KleinFour.lean @@ -90,8 +90,8 @@ open Finset variable {G : Type*} [Group G] [IsKleinFour G] @[to_additive] -lemma not_isCyclic : ¬ IsCyclic G := - fun h ↦ by let _inst := Fintype.ofFinite G; simpa using h.exponent_eq_card +lemma not_isCyclic : ¬IsCyclic G := + fun h ↦ by simpa using h.exponent_eq_card @[to_additive] lemma inv_eq_self (x : G) : x⁻¹ = x := inv_eq_self_of_exponent_two (by simp) x diff --git a/Mathlib/GroupTheory/Transfer.lean b/Mathlib/GroupTheory/Transfer.lean index f33f7fc8e19a5..02bb04970dc68 100644 --- a/Mathlib/GroupTheory/Transfer.lean +++ b/Mathlib/GroupTheory/Transfer.lean @@ -325,10 +325,7 @@ theorem normalizer_le_centralizer (hP : IsCyclic P) : P.normalizer ≤ centraliz apply Nat.coprime_one_right rw [hP.card_mulAut, hk, Nat.totient_prime_pow Fact.out h0] refine (Nat.Coprime.pow_right _ ?_).mul_right ?_ - · replace key : P.IsCommutative := by - let h := hP.commGroup - exact ⟨⟨CommGroup.mul_comm⟩⟩ - apply Nat.Coprime.coprime_dvd_left (relindex_dvd_of_le_left P.normalizer P.le_centralizer) + · apply Nat.Coprime.coprime_dvd_left (relindex_dvd_of_le_left P.normalizer P.le_centralizer) apply Nat.Coprime.coprime_dvd_left (relindex_dvd_index_of_le P.le_normalizer) rw [Nat.coprime_comm, Nat.Prime.coprime_iff_not_dvd Fact.out] exact P.not_dvd_index From ec0f40db7f3ed1b4ee2f0b3dba2172f02d19f612 Mon Sep 17 00:00:00 2001 From: Kyle Miller Date: Mon, 20 Jan 2025 18:16:24 +0000 Subject: [PATCH 353/681] feat: `notation3`-defined pretty printers now make tokens that are clickable in documentation (#20861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modifies the `notation3` delaborator generator so that when `pp.tagAppFns` is true, and when the expression being delaborated is the application of a constant, all the tokens of the notation are annotated with that constant. The consequence is that in docgen documentation, the tokens will be links to that constant. This heuristic might give unexpected results. For example, in ```lean notation3 "Nat≥0" => { x : Nat // 0 ≤ x } ``` the documentation will have appearances of `Nat≥0` link to `Subtype`. In complicated notations this heuristic may have mixed results. For example, it's possible to use `notation3` to define notations that have different head constants in different expansions, and so the tokens can link to different constants in different appearances. There are no such cases of this in mathlib however. [Zulip discussion](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Filter.2EEventually.20.28.60.E2.88.80.E1.B6.A0.60.29.20notation.20is.20not.20clickable.20in.20docs/near/494590979) --- Mathlib/Util/Notation3.lean | 20 ++++++++++++++++- MathlibTest/notation3.lean | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/Mathlib/Util/Notation3.lean b/Mathlib/Util/Notation3.lean index 8021941ea2a4a..17e8a9c0118e2 100644 --- a/Mathlib/Util/Notation3.lean +++ b/Mathlib/Util/Notation3.lean @@ -442,6 +442,24 @@ def getPrettyPrintOpt (opt? : Option (TSyntax ``prettyPrintOpt)) : Bool := else true +/-- +If `pp.tagAppFns` is true and the head of the current expression is a constant, +then delaborates the head and uses it for the ref. +This causes tokens inside the syntax to refer to this constant. +A consequence is that docgen will linkify the tokens. +-/ +def withHeadRefIfTagAppFns (d : Delab) : Delab := do + let tagAppFns ← getPPOption getPPTagAppFns + if tagAppFns && (← getExpr).getAppFn.consumeMData.isConst then + -- Delaborate the head to register term info and get a syntax we can use for the ref. + -- The syntax `f` itself is thrown away. + let f ← withNaryFn <| withOptionAtCurrPos `pp.tagAppFns true delab + let stx ← withRef f d + -- Annotate to ensure that the full syntax still refers to the whole expression. + annotateTermInfo stx + else + d + /-- `notation3` declares notation using Lean-3-style syntax. @@ -584,7 +602,7 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr let delabName := name ++ `delab let matcher ← ms.foldrM (fun m t => `($(m.2) >=> $t)) (← `(pure)) trace[notation3] "matcher:{indentD matcher}" - let mut result ← `(`($pat)) + let mut result ← `(withHeadRefIfTagAppFns `($pat)) for (name, id) in boundIdents.toArray do match boundType.getD name .normal with | .normal => result ← `(MatchState.delabVar s $(quote name) (some e) >>= fun $id => $result) diff --git a/MathlibTest/notation3.lean b/MathlibTest/notation3.lean index c4473b94e10e7..9b3fc8d5f1f25 100644 --- a/MathlibTest/notation3.lean +++ b/MathlibTest/notation3.lean @@ -20,6 +20,50 @@ notation3 "∀ᶠ " (...) " in " f ", " r:(scoped p => Filter.eventually p f) => /-- info: ∀ᶠ (x : ℕ) in Filter.atTop, x < 3 : Prop -/ #guard_msgs in #check ∀ᶠ x in Filter.atTop, x < 3 +/-! +Test that `pp.tagAppFns` causes tokens to be tagged with head constant. +-/ + +open Lean in +def findWithTag (tag : Nat) (f : Format) : List Format := + match f with + | .nil => [] + | .line => [] + | .align _ => [] + | .text _ => [] + | .nest _ f' => findWithTag tag f' + | .append f' f'' => findWithTag tag f' ++ findWithTag tag f'' + | .group f' _ => findWithTag tag f' + | .tag t f' => (if t = tag then [f'] else []) ++ findWithTag tag f' + +open Lean Elab Term in +def testTagAppFns (n : Name) : TermElabM Unit := do + let stx ← `(∀ᶠ x in Filter.atTop, x < 3) + let e ← elabTermAndSynthesize stx none + let f ← Meta.ppExprWithInfos e + -- Find tags for the constant `n` + let tags : Array Nat := f.infos.fold (init := #[]) fun tags tag info => + match info with + | .ofTermInfo info | .ofDelabTermInfo info => + if info.expr.isConstOf n then + tags.push tag + else + tags + | _ => tags + let fmts := tags.map (findWithTag · f.fmt) + unless fmts.all (!·.isEmpty) do throwError "missing tag" + let fmts := fmts.toList.flatten + logInfo m!"{repr <| fmts.map (·.pretty.trim)}" + +section +/-- info: [] -/ +#guard_msgs in #eval testTagAppFns ``Filter.eventually +set_option pp.tagAppFns true +/-- info: ["∀ᶠ", "in", ","] -/ +#guard_msgs in #eval testTagAppFns ``Filter.eventually +end + + -- Testing lambda expressions: notation3 "∀ᶠ' " f ", " p => Filter.eventually (fun x => (p : _ → _) x) f /-- info: ∀ᶠ' Filter.atTop, fun x ↦ x < 3 : Prop -/ From 3c2c5041203a2782a0772001c640ecccfe364a5a Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Mon, 20 Jan 2025 19:50:48 +0000 Subject: [PATCH 354/681] feat(Data/Matroid/Basic): matroid congruence definitions (#20876) Added three definitions that produce copies of matroids with superior definitional properties, in response to [this comment](https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/Transcendence.20degree.3F/near/494675777) on zulip. --- Mathlib/Data/Matroid/Basic.lean | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Mathlib/Data/Matroid/Basic.lean b/Mathlib/Data/Matroid/Basic.lean index 81021b42ad6b0..4c8032518f51d 100644 --- a/Mathlib/Data/Matroid/Basic.lean +++ b/Mathlib/Data/Matroid/Basic.lean @@ -744,6 +744,43 @@ theorem existsMaximalSubsetProperty_indep (M : Matroid α) : end dep_indep +section copy + +/-- create a copy of `M : Matroid α` with independence and base predicates and ground set defeq +to supplied arguments that are provably equal to those of `M`. -/ +@[simps] def copy (M : Matroid α) (E : Set α) (Base Indep : Set α → Prop) + (hE : E = M.E) (hB : ∀ B, Base B ↔ M.Base B) (hI : ∀ I, Indep I ↔ M.Indep I) : Matroid α where + E := E + Base := Base + Indep := Indep + indep_iff' _ := by simp_rw [hI, hB, M.indep_iff] + exists_base := by + simp_rw [hB] + exact M.exists_base + base_exchange := by + simp_rw [show Base = M.Base from funext (by simp [hB])] + exact M.base_exchange + maximality := by + simp_rw [hE, show Indep = M.Indep from funext (by simp [hI])] + exact M.maximality + subset_ground := by + simp_rw [hE, hB] + exact M.subset_ground + +/-- create a copy of `M : Matroid α` with an independence predicate and ground set defeq +to supplied arguments that are provably equal to those of `M`. -/ +@[simps!] def copyIndep (M : Matroid α) (E : Set α) (Indep : Set α → Prop) + (hE : E = M.E) (h : ∀ I, Indep I ↔ M.Indep I) : Matroid α := + M.copy E M.Base Indep hE (fun _ ↦ Iff.rfl) h + +/-- create a copy of `M : Matroid α` with a base predicate and ground set defeq +to supplied arguments that are provably equal to those of `M`. -/ +@[simps!] def copyBase (M : Matroid α) (E : Set α) (Base : Set α → Prop) + (hE : E = M.E) (h : ∀ B, Base B ↔ M.Base B) : Matroid α := + M.copy E Base M.Indep hE h (fun _ ↦ Iff.rfl) + +end copy + section Basis /-- A Basis for a set `X ⊆ M.E` is a maximal independent subset of `X` From 0371e093656d52f4f9159d72db577ab3635f0550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 21 Jan 2025 00:20:39 +0000 Subject: [PATCH 355/681] =?UTF-8?q?feat(Logic/Basic):=20`HEq=20(cast=20h?= =?UTF-8?q?=20a)=20b=20=E2=86=94=20HEq=20a=20b`=20(#20847)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes `simp` a bit more capable when dealing with the ever-present DTT hell. --- Mathlib/Logic/Basic.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/Logic/Basic.lean b/Mathlib/Logic/Basic.lean index 56e15a7a87dc5..a9d2a671964dd 100644 --- a/Mathlib/Logic/Basic.lean +++ b/Mathlib/Logic/Basic.lean @@ -426,6 +426,14 @@ theorem rec_heq_iff_heq {α β : Sort _} {a b : α} {C : α → Sort*} {x : C a} theorem heq_rec_iff_heq {α β : Sort _} {a b : α} {C : α → Sort*} {x : β} {y : C a} {e : a = b} : HEq x (e ▸ y) ↔ HEq x y := by subst e; rfl +@[simp] +theorem cast_heq_iff_heq {α β γ : Sort _} (e : α = β) (a : α) (c : γ) : + HEq (cast e a) c ↔ HEq a c := by subst e; rfl + +@[simp] +theorem heq_cast_iff_heq {α β γ : Sort _} (e : β = γ) (a : α) (b : β) : + HEq a (cast e b) ↔ HEq a b := by subst e; rfl + universe u variable {α β : Sort u} {e : β = α} {a : α} {b : β} From 0d80c6dc78876ea2f30c8ea8eb0a5bb3bde8eacc Mon Sep 17 00:00:00 2001 From: kvanvels Date: Tue, 21 Jan 2025 01:06:00 +0000 Subject: [PATCH 356/681] chore: replace open scoped Classical with `open scoped Classical in` or `classical` (#20501) reduces some technical debt by replacing "open scoped classical" with (open scoped classical in) for theorem declarations and/or adding a "classical' tactic to a tactic proof. I followed the example in PR #20325. Co-authored-by: kvanvels <101572210+kvanvels@users.noreply.github.com> --- Archive/Imo/Imo1998Q2.lean | 14 ++++++++--- .../Wiedijk100Theorems/FriendshipGraphs.lean | 19 +++++++++++++-- Archive/Wiedijk100Theorems/Partition.lean | 6 +++-- .../IrrationalPowerOfIrrational.lean | 2 +- Mathlib/CategoryTheory/Preadditive/Mat.lean | 21 +++++++++++++---- Mathlib/Computability/TuringMachine.lean | 23 ++++++++++++------- Mathlib/Control/LawfulFix.lean | 3 +-- .../Data/Int/ConditionallyCompleteOrder.lean | 2 +- Mathlib/Data/Nat/Lattice.lean | 12 ++++++++-- Mathlib/Data/Nat/PartENat.lean | 4 ++-- Mathlib/Data/Option/Basic.lean | 2 -- .../GroupTheory/SpecificGroups/Cyclic.lean | 3 +-- Mathlib/Probability/Density.lean | 2 +- .../Probability/Distributions/Uniform.lean | 3 ++- .../ProbabilityMassFunction/Basic.lean | 9 ++++---- .../Constructions.lean | 5 +++- .../ProbabilityMassFunction/Monad.lean | 12 ++++++++-- Mathlib/Probability/Process/Adapted.lean | 2 +- Mathlib/Probability/Process/HittingTime.lean | 14 +++++++---- Mathlib/Probability/Process/Stopping.lean | 4 +++- Mathlib/RepresentationTheory/Character.lean | 3 +-- Mathlib/RepresentationTheory/FDRep.lean | 3 +-- Mathlib/RingTheory/Adjoin/FG.lean | 7 +++--- Mathlib/RingTheory/Adjoin/Tower.lean | 23 ++++++++++--------- Mathlib/RingTheory/AdjoinRoot.lean | 2 -- Mathlib/RingTheory/AlgebraTower.lean | 3 +-- .../AlgebraicIndependent/Adjoin.lean | 2 -- .../AlgebraicIndependent/Basic.lean | 2 -- .../RingTheory/AlgebraicIndependent/Defs.lean | 2 -- Mathlib/RingTheory/FiniteType.lean | 3 ++- Mathlib/RingTheory/Fintype.lean | 3 +-- Mathlib/RingTheory/FreeCommRing.lean | 2 +- Mathlib/RingTheory/LaurentSeries.lean | 3 ++- Mathlib/RingTheory/Perfection.lean | 5 ++-- Mathlib/RingTheory/PrincipalIdealDomain.lean | 3 +-- Mathlib/RingTheory/Radical.lean | 12 ++++++---- .../RingTheory/Spectrum/Maximal/Basic.lean | 2 -- Mathlib/RingTheory/Spectrum/Prime/Basic.lean | 4 +++- Mathlib/RingTheory/Valuation/Basic.lean | 4 +++- 39 files changed, 158 insertions(+), 92 deletions(-) diff --git a/Archive/Imo/Imo1998Q2.lean b/Archive/Imo/Imo1998Q2.lean index 94378d663c520..88e40d89763aa 100644 --- a/Archive/Imo/Imo1998Q2.lean +++ b/Archive/Imo/Imo1998Q2.lean @@ -39,9 +39,6 @@ the lower bound: `a(b-1)^2/2 ≤ |A|`. Rearranging gives the result. -/ - -open scoped Classical - variable {C J : Type*} (r : C → J → Prop) namespace Imo1998Q2 @@ -86,6 +83,7 @@ theorem JudgePair.agree_iff_same_rating (p : JudgePair J) (c : C) : p.Agree r c ↔ (r c p.judge₁ ↔ r c p.judge₂) := Iff.rfl +open scoped Classical in /-- The set of contestants on which two judges agree. -/ def agreedContestants [Fintype C] (p : JudgePair J) : Finset C := Finset.univ.filter fun c => p.Agree r c @@ -93,14 +91,17 @@ section variable [Fintype J] [Fintype C] +open scoped Classical in /-- All incidences of agreement. -/ def A : Finset (AgreedTriple C J) := Finset.univ.filter @fun (a : AgreedTriple C J) => (a.judgePair.Agree r a.contestant ∧ a.judgePair.Distinct) +open scoped Classical in theorem A_maps_to_offDiag_judgePair (a : AgreedTriple C J) : a ∈ A r → a.judgePair ∈ Finset.offDiag (@Finset.univ J _) := by simp [A, Finset.mem_offDiag] +open scoped Classical in theorem A_fibre_over_contestant (c : C) : (Finset.univ.filter fun p : JudgePair J => p.Agree r c ∧ p.Distinct) = ((A r).filter fun a : AgreedTriple C J => a.contestant = c).image Prod.snd := by @@ -110,6 +111,7 @@ theorem A_fibre_over_contestant (c : C) : · rintro ⟨_, h₂⟩; refine ⟨(c, p), ?_⟩; tauto · intro h; aesop +open scoped Classical in theorem A_fibre_over_contestant_card (c : C) : (Finset.univ.filter fun p : JudgePair J => p.Agree r c ∧ p.Distinct).card = ((A r).filter fun a : AgreedTriple C J => a.contestant = c).card := by @@ -119,6 +121,7 @@ theorem A_fibre_over_contestant_card (c : C) : rintro ⟨a, p⟩ h ⟨a', p'⟩ h' rfl aesop (add simp AgreedTriple.contestant) +open scoped Classical in theorem A_fibre_over_judgePair {p : JudgePair J} (h : p.Distinct) : agreedContestants r p = ((A r).filter fun a : AgreedTriple C J => a.judgePair = p).image AgreedTriple.contestant := by @@ -126,6 +129,7 @@ theorem A_fibre_over_judgePair {p : JudgePair J} (h : p.Distinct) : · rw [Finset.mem_image]; refine ⟨⟨c, p⟩, ?_⟩; aesop · aesop +open scoped Classical in theorem A_fibre_over_judgePair_card {p : JudgePair J} (h : p.Distinct) : (agreedContestants r p).card = ((A r).filter fun a : AgreedTriple C J => a.judgePair = p).card := by @@ -138,6 +142,7 @@ theorem A_card_upper_bound {k : ℕ} (hk : ∀ p : JudgePair J, p.Distinct → (agreedContestants r p).card ≤ k) : (A r).card ≤ k * (Fintype.card J * Fintype.card J - Fintype.card J) := by change _ ≤ k * (Finset.card _ * Finset.card _ - Finset.card _) + classical rw [← Finset.offDiag_card] apply Finset.card_le_mul_card_image_of_maps_to (A_maps_to_offDiag_judgePair r) intro p hp @@ -162,6 +167,7 @@ section variable [Fintype J] +open scoped Classical in theorem judge_pairs_card_lower_bound {z : ℕ} (hJ : Fintype.card J = 2 * z + 1) (c : C) : 2 * z * z + 2 * z + 1 ≤ (Finset.univ.filter fun p : JudgePair J => p.Agree r c).card := by let x := (Finset.univ.filter fun j => r c j).card @@ -173,6 +179,7 @@ theorem judge_pairs_card_lower_bound {z : ℕ} (hJ : Fintype.card J = 2 * z + 1) suffices x + y = 2 * z + 1 by simp [← Int.ofNat_add, this] rw [Finset.filter_card_add_filter_neg_card_eq_card, ← hJ]; rfl +open scoped Classical in theorem distinct_judge_pairs_card_lower_bound {z : ℕ} (hJ : Fintype.card J = 2 * z + 1) (c : C) : 2 * z * z ≤ (Finset.univ.filter fun p : JudgePair J => p.Agree r c ∧ p.Distinct).card := by let s := Finset.univ.filter fun p : JudgePair J => p.Agree r c @@ -192,6 +199,7 @@ theorem distinct_judge_pairs_card_lower_bound {z : ℕ} (hJ : Fintype.card J = 2 theorem A_card_lower_bound [Fintype C] {z : ℕ} (hJ : Fintype.card J = 2 * z + 1) : 2 * z * z * Fintype.card C ≤ (A r).card := by + classical have h : ∀ a, a ∈ A r → Prod.fst a ∈ @Finset.univ C _ := by intros; apply Finset.mem_univ apply Finset.mul_card_image_le_card_of_maps_to h intro c _ diff --git a/Archive/Wiedijk100Theorems/FriendshipGraphs.lean b/Archive/Wiedijk100Theorems/FriendshipGraphs.lean index b4e7f16d0b902..c5d0604033257 100644 --- a/Archive/Wiedijk100Theorems/FriendshipGraphs.lean +++ b/Archive/Wiedijk100Theorems/FriendshipGraphs.lean @@ -38,8 +38,6 @@ be phrased in terms of counting walks. -/ -open scoped Classical - namespace Theorems100 noncomputable section @@ -54,6 +52,7 @@ section FriendshipDef variable (G : SimpleGraph V) +open scoped Classical in /-- This property of a graph is the hypothesis of the friendship theorem: every pair of nonadjacent vertices has exactly one common friend, a vertex to which both are adjacent. @@ -74,6 +73,7 @@ namespace Friendship variable (R) +open scoped Classical in include hG in /-- One characterization of a friendship graph is that there is exactly one walk of length 2 between distinct vertices. These walks are counted in off-diagonal entries of the square of @@ -86,6 +86,7 @@ theorem adjMatrix_sq_of_ne {v w : V} (hvw : v ≠ w) : Fintype.card_ofFinset (s := filter (fun x ↦ x ∈ G.neighborSet v ∩ G.neighborSet w) univ), Set.mem_inter_iff, mem_neighborSet] +open scoped Classical in include hG in /-- This calculation amounts to counting the number of length 3 walks between nonadjacent vertices. We use it to show that nonadjacent vertices have equal degrees. -/ @@ -101,6 +102,7 @@ theorem adjMatrix_pow_three_of_not_adj {v w : V} (non_adj : ¬G.Adj v w) : variable {R} +open scoped Classical in include hG in /-- As `v` and `w` not being adjacent implies `degree G v = ((G.adjMatrix R) ^ 3) v w` and `degree G w = ((G.adjMatrix R) ^ 3) v w`, @@ -115,6 +117,7 @@ theorem degree_eq_of_not_adj {v w : V} (hvw : ¬G.Adj v w) : degree G v = degree simp only [pow_succ _ 2, sq, ← transpose_mul, transpose_apply] simp only [mul_assoc] +open scoped Classical in include hG in /-- Let `A` be the adjacency matrix of a graph `G`. If `G` is a friendship graph, then all of the off-diagonal entries of `A^2` are 1. @@ -126,6 +129,7 @@ theorem adjMatrix_sq_of_regular (hd : G.IsRegularOfDegree d) : · rw [h, sq, adjMatrix_mul_self_apply_self, hd]; simp · rw [adjMatrix_sq_of_ne R hG h, of_apply, if_neg h] +open scoped Classical in include hG in theorem adjMatrix_sq_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1) (hd : G.IsRegularOfDegree d) : G.adjMatrix (ZMod p) ^ 2 = of fun _ _ => 1 := by @@ -135,6 +139,7 @@ section Nonempty variable [Nonempty V] +open scoped Classical in include hG in /-- If `G` is a friendship graph without a politician (a vertex adjacent to all others), then it is regular. We have shown that nonadjacent vertices of a friendship graph have the same degree, @@ -168,6 +173,7 @@ theorem isRegularOf_not_existsPolitician (hG' : ¬ExistsPolitician G) : rw [key ((mem_commonNeighbors G).mpr ⟨hvx, G.symm hxw⟩), key ((mem_commonNeighbors G).mpr ⟨hvy, G.symm hcontra⟩)] +open scoped Classical in include hG in /-- Let `A` be the adjacency matrix of a `d`-regular friendship graph, and let `v` be a vector all of whose components are `1`. Then `v` is an eigenvector of `A ^ 2`, and we can compute @@ -187,6 +193,7 @@ theorem card_of_regular (hd : G.IsRegularOfDegree d) : d + (Fintype.card V - 1) card_neighborSet_eq_degree, hd v, Function.const_def, adjMatrix_mulVec_apply _ _ (mulVec _ _), mul_one, sum_const, Set.toFinset_card, Algebra.id.smul_eq_mul, Nat.cast_id] +open scoped Classical in include hG in /-- The size of a `d`-regular friendship graph is `1 mod (d-1)`, and thus `1 mod p` for a factor `p ∣ d-1`. -/ @@ -200,17 +207,20 @@ theorem card_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1) (hd : G.IsRegu end Nonempty +open scoped Classical in theorem adjMatrix_sq_mul_const_one_of_regular (hd : G.IsRegularOfDegree d) : G.adjMatrix R * of (fun _ _ => 1) = of (fun _ _ => (d : R)) := by ext x simp only [← hd x, degree, adjMatrix_mul_apply, sum_const, Nat.smul_one_eq_cast, of_apply] +open scoped Classical in theorem adjMatrix_mul_const_one_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1) (hd : G.IsRegularOfDegree d) : G.adjMatrix (ZMod p) * of (fun _ _ => 1) = of (fun _ _ => 1) := by rw [adjMatrix_sq_mul_const_one_of_regular hd, dmod] +open scoped Classical in include hG in /-- Modulo a factor of `d-1`, the square and all higher powers of the adjacency matrix of a `d`-regular friendship graph reduce to the matrix whose entries are all 1. -/ @@ -227,6 +237,7 @@ theorem adjMatrix_pow_mod_p_of_regular {p : ℕ} (dmod : (d : ZMod p) = 1) variable [Nonempty V] +open scoped Classical in include hG in /-- This is the main proof. Assuming that `3 ≤ d`, we take `p` to be a prime factor of `d-1`. Then the `p`th power of the adjacency matrix of a `d`-regular friendship graph must have trace 1 @@ -260,6 +271,7 @@ theorem false_of_three_le_degree (hd : G.IsRegularOfDegree d) (h : 3 ≤ d) : Fa Nat.dvd_one, Nat.minFac_eq_one_iff] omega +open scoped Classical in include hG in /-- If `d ≤ 1`, a `d`-regular friendship graph has at most one vertex, which is trivially a politician. -/ @@ -277,6 +289,7 @@ theorem existsPolitician_of_degree_le_one (hd : G.IsRegularOfDegree d) (hd1 : d apply h apply Fintype.card_le_one_iff.mp this +open scoped Classical in include hG in /-- If `d = 2`, a `d`-regular friendship graph has 3 vertices, so it must be complete graph, and all the vertices are politicians. -/ @@ -295,6 +308,7 @@ theorem neighborFinset_eq_of_degree_eq_two (hd : G.IsRegularOfDegree 2) (v : V) · dsimp only [IsRegularOfDegree, degree] at hd rw [hd] +open scoped Classical in include hG in theorem existsPolitician_of_degree_eq_two (hd : G.IsRegularOfDegree 2) : ExistsPolitician G := by have v := Classical.arbitrary V @@ -303,6 +317,7 @@ theorem existsPolitician_of_degree_eq_two (hd : G.IsRegularOfDegree 2) : ExistsP rw [← mem_neighborFinset, neighborFinset_eq_of_degree_eq_two hG hd v, Finset.mem_erase] exact ⟨hvw.symm, Finset.mem_univ _⟩ +open scoped Classical in include hG in theorem existsPolitician_of_degree_le_two (hd : G.IsRegularOfDegree d) (h : d ≤ 2) : ExistsPolitician G := by diff --git a/Archive/Wiedijk100Theorems/Partition.lean b/Archive/Wiedijk100Theorems/Partition.lean index 96f1877c186a5..caf136306ff69 100644 --- a/Archive/Wiedijk100Theorems/Partition.lean +++ b/Archive/Wiedijk100Theorems/Partition.lean @@ -64,8 +64,6 @@ variable {α : Type*} open Finset -open scoped Classical - /-- The partial product for the generating function for odd partitions. TODO: As `m` tends to infinity, this converges (in the `X`-adic topology). @@ -92,10 +90,12 @@ open Finset.HasAntidiagonal universe u variable {ι : Type u} +open scoped Classical in /-- A convenience constructor for the power series whose coefficients indicate a subset. -/ def indicatorSeries (α : Type*) [Semiring α] (s : Set ℕ) : PowerSeries α := PowerSeries.mk fun n => if n ∈ s then 1 else 0 +open scoped Classical in theorem coeff_indicator (s : Set ℕ) [Semiring α] (n : ℕ) : coeff α n (indicatorSeries _ s) = if n ∈ s then 1 else 0 := coeff_mk _ _ @@ -106,6 +106,7 @@ theorem coeff_indicator_pos (s : Set ℕ) [Semiring α] (n : ℕ) (h : n ∈ s) theorem coeff_indicator_neg (s : Set ℕ) [Semiring α] (n : ℕ) (h : n ∉ s) : coeff α n (indicatorSeries _ s) = 0 := by rw [coeff_indicator, if_neg h] +open scoped Classical in theorem constantCoeff_indicator (s : Set ℕ) [Semiring α] : constantCoeff α (indicatorSeries _ s) = if 0 ∈ s then 1 else 0 := rfl @@ -162,6 +163,7 @@ theorem num_series' [Field α] (i : ℕ) : def mkOdd : ℕ ↪ ℕ := ⟨fun i => 2 * i + 1, fun x y h => by linarith⟩ +open scoped Classical in -- The main workhorse of the partition theorem proof. theorem partialGF_prop (α : Type*) [CommSemiring α] (n : ℕ) (s : Finset ℕ) (hs : ∀ i ∈ s, 0 < i) (c : ℕ → Set ℕ) (hc : ∀ i, i ∉ s → 0 ∈ c i) : diff --git a/Counterexamples/IrrationalPowerOfIrrational.lean b/Counterexamples/IrrationalPowerOfIrrational.lean index 75e822d68b149..6061a15b832af 100644 --- a/Counterexamples/IrrationalPowerOfIrrational.lean +++ b/Counterexamples/IrrationalPowerOfIrrational.lean @@ -17,7 +17,7 @@ If `c` is irrational, then `c^√2 = 2` is rational, so we are done. -/ -open Classical Real +open Real namespace Counterexample diff --git a/Mathlib/CategoryTheory/Preadditive/Mat.lean b/Mathlib/CategoryTheory/Preadditive/Mat.lean index 17cee933b9716..2a27f9a373550 100644 --- a/Mathlib/CategoryTheory/Preadditive/Mat.lean +++ b/Mathlib/CategoryTheory/Preadditive/Mat.lean @@ -51,8 +51,6 @@ Ideally this would conveniently interact with both `Mat_` and `Matrix`. open CategoryTheory CategoryTheory.Preadditive -open scoped Classical - noncomputable section namespace CategoryTheory @@ -81,6 +79,7 @@ def Hom (M N : Mat_ C) : Type v₁ := namespace Hom +open scoped Classical in /-- The identity matrix consists of identity morphisms on the diagonal, and zeros elsewhere. -/ def id (M : Mat_ C) : Hom M M := fun i j => if h : i = j then eqToHom (congr_arg M.X h) else 0 @@ -98,8 +97,12 @@ instance : Category.{v₁} (Mat_ C) where Hom := Hom id := Hom.id comp f g := f.comp g - id_comp f := by simp (config := { unfoldPartialApp := true }) [dite_comp] - comp_id f := by simp (config := { unfoldPartialApp := true }) [comp_dite] + id_comp f := by + classical + simp (config := { unfoldPartialApp := true }) [dite_comp] + comp_id f := by + classical + simp (config := { unfoldPartialApp := true }) [comp_dite] assoc f g h := by apply DMatrix.ext intros @@ -110,10 +113,12 @@ instance : Category.{v₁} (Mat_ C) where theorem hom_ext {M N : Mat_ C} (f g : M ⟶ N) (H : ∀ i j, f i j = g i j) : f = g := DMatrix.ext_iff.mp H +open scoped Classical in theorem id_def (M : Mat_ C) : (𝟙 M : Hom M M) = fun i j => if h : i = j then eqToHom (congr_arg M.X h) else 0 := rfl +open scoped Classical in theorem id_apply (M : Mat_ C) (i j : M.ι) : (𝟙 M : Hom M M) i j = if h : i = j then eqToHom (congr_arg M.X h) else 0 := rfl @@ -155,6 +160,7 @@ instance : Preadditive (Mat_ C) where open CategoryTheory.Limits +open scoped Classical in /-- We now prove that `Mat_ C` has finite biproducts. Be warned, however, that `Mat_ C` is not necessarily Krull-Schmidt, @@ -249,6 +255,7 @@ def mapMat_ (F : C ⥤ D) [Functor.Additive F] : Mat_ C ⥤ Mat_ D where @[simps!] def mapMatId : (𝟭 C).mapMat_ ≅ 𝟭 (Mat_ C) := NatIso.ofComponents (fun M => eqToIso (by cases M; rfl)) fun {M N} f => by + classical ext cases M; cases N simp [comp_dite, dite_comp] @@ -259,6 +266,7 @@ def mapMatId : (𝟭 C).mapMat_ ≅ 𝟭 (Mat_ C) := def mapMatComp {E : Type*} [Category.{v₁} E] [Preadditive E] (F : C ⥤ D) [Functor.Additive F] (G : D ⥤ E) [Functor.Additive G] : (F ⋙ G).mapMat_ ≅ F.mapMat_ ⋙ G.mapMat_ := NatIso.ofComponents (fun M => eqToIso (by cases M; rfl)) fun {M N} f => by + classical ext cases M; cases N simp [comp_dite, dite_comp] @@ -294,6 +302,7 @@ open CategoryTheory.Limits variable {C} +open scoped Classical in /-- Every object in `Mat_ C` is isomorphic to the biproduct of its summands. -/ @[simps] @@ -365,6 +374,7 @@ theorem additiveObjIsoBiproduct_naturality (F : Mat_ C ⥤ D) [Functor.Additive F.map f ≫ (additiveObjIsoBiproduct F N).hom = (additiveObjIsoBiproduct F M).hom ≫ biproduct.matrix fun i j => F.map ((embedding C).map (f i j)) := by + classical ext i : 1 simp only [Category.assoc, additiveObjIsoBiproduct_hom_π, isoBiproductEmbedding_hom, embedding_obj_ι, embedding_obj_X, biproduct.lift_π, biproduct.matrix_π, @@ -492,6 +502,7 @@ instance (R : Type u) : CoeSort (Mat R) (Type u) := open Matrix +open scoped Classical in instance (R : Type u) [Semiring R] : Category (Mat R) where Hom X Y := Matrix X Y R id X := (1 : Matrix X X R) @@ -510,9 +521,11 @@ theorem hom_ext {X Y : Mat R} (f g : X ⟶ Y) (h : ∀ i j, f i j = g i j) : f = variable (R) +open scoped Classical in theorem id_def (M : Mat R) : 𝟙 M = fun i j => if i = j then 1 else 0 := rfl +open scoped Classical in theorem id_apply (M : Mat R) (i j : M) : (𝟙 M : Matrix M M R) i j = if i = j then 1 else 0 := rfl diff --git a/Mathlib/Computability/TuringMachine.lean b/Mathlib/Computability/TuringMachine.lean index 19a73e31325fb..33c511f86aaa4 100644 --- a/Mathlib/Computability/TuringMachine.lean +++ b/Mathlib/Computability/TuringMachine.lean @@ -580,8 +580,7 @@ def SupportsStmt (S : Finset Λ) : Stmt₁ → Prop | goto l => ∀ a v, l a v ∈ S | halt => True -open scoped Classical - +open scoped Classical in /-- The subterm closure of a statement. -/ noncomputable def stmts₁ : Stmt₁ → Finset Stmt₁ | Q@(move _ q) => insert Q (stmts₁ q) @@ -594,6 +593,7 @@ theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by cases q <;> simp only [stmts₁, Finset.mem_insert_self, Finset.mem_singleton_self] theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by + classical intro h₁₂ q₀ h₀₁ induction q₂ with ( simp only [stmts₁] at h₁₂ ⊢ @@ -621,6 +621,7 @@ theorem stmts₁_supportsStmt_mono {S : Finset Λ} {q₁ q₂ : Stmt₁} (h : q | halt => subst h; trivial | _ _ q IH => rcases h with (rfl | h) <;> [exact hs; exact IH h hs] +open scoped Classical in /-- The set of all statements in a Turing machine, plus one extra value `none` representing the halt state. This is used in the TM1 to TM0 reduction. -/ noncomputable def stmts (M : Λ → Stmt₁) (S : Finset Λ) : Finset (Option Stmt₁) := @@ -781,12 +782,11 @@ machine states in the target (even though the type `Λ'` is infinite). -/ noncomputable def trStmts (S : Finset Λ) : Finset Λ'₁₀ := (TM1.stmts M S) ×ˢ Finset.univ -open scoped Classical - attribute [local simp] TM1.stmts₁_self theorem tr_supports {S : Finset Λ} (ss : TM1.Supports M S) : TM0.Supports (tr M) ↑(trStmts M S) := by + classical constructor · apply Finset.mem_product.2 constructor @@ -1113,10 +1113,10 @@ theorem tr_respects : end -open scoped Classical variable [Fintype Γ] +open scoped Classical in /-- The set of accessible `Λ'.write` machine states. -/ noncomputable def writes : Stmt₁ → Finset Λ'₁ | Stmt.move _ q => writes q @@ -1126,11 +1126,13 @@ noncomputable def writes : Stmt₁ → Finset Λ'₁ | Stmt.goto _ => ∅ | Stmt.halt => ∅ +open scoped Classical in /-- The set of accessible machine states, assuming that the input machine is supported on `S`, are the normal states embedded from `S`, plus all write states accessible from these states. -/ noncomputable def trSupp (S : Finset Λ) : Finset Λ'₁ := S.biUnion fun l ↦ insert (Λ'.normal l) (writes (M l)) +open scoped Classical in theorem tr_supports [Inhabited Λ] {S : Finset Λ} (ss : Supports M S) : Supports (tr enc dec M) (trSupp M S) := ⟨Finset.mem_biUnion.2 ⟨_, ss.1, Finset.mem_insert_self _ _⟩, fun q h ↦ by @@ -1378,8 +1380,8 @@ def SupportsStmt (S : Finset Λ) : Stmt₂ → Prop | halt => True section -open scoped Classical +open scoped Classical in /-- The set of subtree statements in a statement. -/ noncomputable def stmts₁ : Stmt₂ → Finset Stmt₂ | Q@(push _ _ q) => insert Q (stmts₁ q) @@ -1394,6 +1396,7 @@ theorem stmts₁_self {q : Stmt₂} : q ∈ stmts₁ q := by cases q <;> simp only [Finset.mem_insert_self, Finset.mem_singleton_self, stmts₁] theorem stmts₁_trans {q₁ q₂ : Stmt₂} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by + classical intro h₁₂ q₀ h₀₁ induction q₂ with ( simp only [stmts₁] at h₁₂ ⊢ @@ -1422,6 +1425,7 @@ theorem stmts₁_supportsStmt_mono {S : Finset Λ} {q₁ q₂ : Stmt₂} (h : q | halt => subst h; trivial | load _ _ IH | _ _ _ _ IH => rcases h with (rfl | h) <;> [exact hs; exact IH h hs] +open scoped Classical in /-- The set of statements accessible from initial set `S` of labels. -/ noncomputable def stmts (M : Λ → Stmt₂) (S : Finset Λ) : Finset (Option Stmt₂) := Finset.insertNone (S.biUnion fun q ↦ stmts₁ (M q)) @@ -1698,8 +1702,8 @@ theorem trNormal_run {k : K} (s : StAct₂ k) (q : Stmt₂) : cases s <;> rfl section -open scoped Classical +open scoped Classical in /-- The set of machine states accessible from an initial TM2 statement. -/ noncomputable def trStmts₁ : Stmt₂ → Finset Λ'₂₁ | TM2.Stmt.push k f q => {go k (StAct.push f) q, ret q} ∪ trStmts₁ q @@ -1709,6 +1713,7 @@ noncomputable def trStmts₁ : Stmt₂ → Finset Λ'₂₁ | TM2.Stmt.branch _ q₁ q₂ => trStmts₁ q₁ ∪ trStmts₁ q₂ | _ => ∅ +open scoped Classical in theorem trStmts₁_run {k : K} {s : StAct₂ k} {q : Stmt₂} : trStmts₁ (stRun s q) = {go k s q, ret q} ∪ trStmts₁ q := by cases s <;> simp only [trStmts₁, stRun] @@ -1927,13 +1932,15 @@ theorem tr_eval (k) (L : List (Γ k)) {L₁ L₂} (H₁ : L₁ ∈ TM1.eval (tr end section -open scoped Classical + variable [Inhabited Λ] +open scoped Classical in /-- The support of a set of TM2 states in the TM2 emulator. -/ noncomputable def trSupp (S : Finset Λ) : Finset Λ'₂₁ := S.biUnion fun l ↦ insert (normal l) (trStmts₁ (M l)) +open scoped Classical in theorem tr_supports {S} (ss : TM2.Supports M S) : TM1.Supports (tr M) (trSupp M S) := ⟨Finset.mem_biUnion.2 ⟨_, ss.1, Finset.mem_insert.2 <| Or.inl rfl⟩, fun l' h ↦ by suffices ∀ (q) (_ : TM2.SupportsStmt S q) (_ : ∀ x ∈ trStmts₁ q, x ∈ trSupp M S), diff --git a/Mathlib/Control/LawfulFix.lean b/Mathlib/Control/LawfulFix.lean index f22207cffe5c1..9c9a30c5b82a3 100644 --- a/Mathlib/Control/LawfulFix.lean +++ b/Mathlib/Control/LawfulFix.lean @@ -22,8 +22,6 @@ omega complete partial orders (ωCPO). Proofs of the lawfulness of all `Fix` ins universe u v -open scoped Classical - variable {α : Type*} {β : α → Type*} open OmegaCompletePartialOrder @@ -63,6 +61,7 @@ theorem approx_mono ⦃i j : ℕ⦄ (hij : i ≤ j) : approx f i ≤ approx f j exact le_trans (ih ‹_›) (approx_mono' f) theorem mem_iff (a : α) (b : β a) : b ∈ Part.fix f a ↔ ∃ i, b ∈ approx f i a := by + classical by_cases h₀ : ∃ i : ℕ, (approx f i a).Dom · simp only [Part.fix_def f h₀] constructor <;> intro hh diff --git a/Mathlib/Data/Int/ConditionallyCompleteOrder.lean b/Mathlib/Data/Int/ConditionallyCompleteOrder.lean index 077cb7a5b47c8..03ec19f1799b6 100644 --- a/Mathlib/Data/Int/ConditionallyCompleteOrder.lean +++ b/Mathlib/Data/Int/ConditionallyCompleteOrder.lean @@ -17,8 +17,8 @@ open Int noncomputable section -open scoped Classical +open scoped Classical in instance instConditionallyCompleteLinearOrder : ConditionallyCompleteLinearOrder ℤ where __ := instLinearOrder __ := LinearOrder.toLattice diff --git a/Mathlib/Data/Nat/Lattice.lean b/Mathlib/Data/Nat/Lattice.lean index cd3c50fdd53c6..69b77b20877e1 100644 --- a/Mathlib/Data/Nat/Lattice.lean +++ b/Mathlib/Data/Nat/Lattice.lean @@ -21,17 +21,19 @@ open Set namespace Nat -open scoped Classical - +open scoped Classical in noncomputable instance : InfSet ℕ := ⟨fun s ↦ if h : ∃ n, n ∈ s then @Nat.find (fun n ↦ n ∈ s) _ h else 0⟩ +open scoped Classical in noncomputable instance : SupSet ℕ := ⟨fun s ↦ if h : ∃ n, ∀ a ∈ s, a ≤ n then @Nat.find (fun n ↦ ∀ a ∈ s, a ≤ n) _ h else 0⟩ +open scoped Classical in theorem sInf_def {s : Set ℕ} (h : s.Nonempty) : sInf s = @Nat.find (fun n ↦ n ∈ s) _ h := dif_pos _ +open scoped Classical in theorem sSup_def {s : Set ℕ} (h : ∃ n, ∀ a ∈ s, a ≤ n) : sSup s = @Nat.find (fun n ↦ ∀ a ∈ s, a ≤ n) _ h := dif_pos _ @@ -65,15 +67,18 @@ lemma iInf_const_zero {ι : Sort*} : ⨅ _ : ι, 0 = 0 := (isEmpty_or_nonempty ι).elim (fun h ↦ by simp) fun h ↦ sInf_eq_zero.2 <| by simp theorem sInf_mem {s : Set ℕ} (h : s.Nonempty) : sInf s ∈ s := by + classical rw [Nat.sInf_def h] exact Nat.find_spec h theorem not_mem_of_lt_sInf {s : Set ℕ} {m : ℕ} (hm : m < sInf s) : m ∉ s := by + classical cases eq_empty_or_nonempty s with | inl h => subst h; apply not_mem_empty | inr h => rw [Nat.sInf_def h] at hm; exact Nat.find_min h hm protected theorem sInf_le {s : Set ℕ} {m : ℕ} (hm : m ∈ s) : sInf s ≤ m := by + classical rw [Nat.sInf_def ⟨m, hm⟩] exact Nat.find_min' ⟨m, hm⟩ hm @@ -95,6 +100,7 @@ theorem eq_Ici_of_nonempty_of_upward_closed {s : Set ℕ} (hs : s.Nonempty) theorem sInf_upward_closed_eq_succ_iff {s : Set ℕ} (hs : ∀ k₁ k₂ : ℕ, k₁ ≤ k₂ → k₁ ∈ s → k₂ ∈ s) (k : ℕ) : sInf s = k + 1 ↔ k + 1 ∈ s ∧ k ∉ s := by + classical constructor · intro H rw [eq_Ici_of_nonempty_of_upward_closed (nonempty_of_sInf_eq_succ _) hs, H, mem_Ici, mem_Ici] @@ -110,6 +116,7 @@ theorem sInf_upward_closed_eq_succ_iff {s : Set ℕ} (hs : ∀ k₁ k₂ : ℕ, instance : Lattice ℕ := LinearOrder.toLattice +open scoped Classical in noncomputable instance : ConditionallyCompleteLinearOrderBot ℕ := { (inferInstance : OrderBot ℕ), (LinearOrder.toLattice : Lattice ℕ), (inferInstance : LinearOrder ℕ) with @@ -140,6 +147,7 @@ theorem sSup_mem {s : Set ℕ} (h₁ : s.Nonempty) (h₂ : BddAbove s) : sSup s theorem sInf_add {n : ℕ} {p : ℕ → Prop} (hn : n ≤ sInf { m | p m }) : sInf { m | p (m + n) } + n = sInf { m | p m } := by + classical obtain h | ⟨m, hm⟩ := { m | p (m + n) }.eq_empty_or_nonempty · rw [h, Nat.sInf_empty, zero_add] obtain hnp | hnp := hn.eq_or_lt diff --git a/Mathlib/Data/Nat/PartENat.lean b/Mathlib/Data/Nat/PartENat.lean index 5b4dd68288d83..0350d9d4b3cb9 100644 --- a/Mathlib/Data/Nat/PartENat.lean +++ b/Mathlib/Data/Nat/PartENat.lean @@ -640,8 +640,7 @@ theorem ofENat_lt {x y : ℕ∞} : ofENat x < ofENat y ↔ x < y := by section WithTopEquiv -open scoped Classical - +open scoped Classical in @[simp] theorem toWithTop_add {x y : PartENat} : toWithTop (x + y) = toWithTop x + toWithTop y := by refine PartENat.casesOn y ?_ ?_ <;> refine PartENat.casesOn x ?_ ?_ @@ -651,6 +650,7 @@ theorem toWithTop_add {x y : PartENat} : toWithTop (x + y) = toWithTop x + toWit · simp only [top_add, toWithTop_top', toWithTop_natCast', _root_.top_add, forall_const] · simp_rw [toWithTop_natCast', ← Nat.cast_add, toWithTop_natCast', forall_const] +open scoped Classical in /-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see `withTopOrderIso`). -/ @[simps] diff --git a/Mathlib/Data/Option/Basic.lean b/Mathlib/Data/Option/Basic.lean index 8a275196668f5..d6f5815d92c9e 100644 --- a/Mathlib/Data/Option/Basic.lean +++ b/Mathlib/Data/Option/Basic.lean @@ -289,8 +289,6 @@ theorem orElse_eq_none' (o o' : Option α) : o.orElse (fun _ ↦ o') = none ↔ section -open scoped Classical - theorem choice_eq_none (α : Type*) [IsEmpty α] : choice α = none := dif_neg (not_nonempty_iff_imp_false.mpr isEmptyElim) diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index faf9e2b92885d..394f2d018f935 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -288,8 +288,7 @@ open Finset Nat section Classical -open scoped Classical - +open scoped Classical in @[to_additive IsAddCyclic.card_nsmul_eq_zero_le] theorem IsCyclic.card_pow_eq_one_le [DecidableEq α] [Fintype α] [IsCyclic α] {n : ℕ} (hn0 : 0 < n) : #{a : α | a ^ n = 1} ≤ n := diff --git a/Mathlib/Probability/Density.lean b/Mathlib/Probability/Density.lean index 8100dd885dedf..a89d87c31a792 100644 --- a/Mathlib/Probability/Density.lean +++ b/Mathlib/Probability/Density.lean @@ -50,7 +50,7 @@ which we currently do not have. -/ -open scoped Classical MeasureTheory NNReal ENNReal +open scoped MeasureTheory NNReal ENNReal open TopologicalSpace MeasureTheory.Measure diff --git a/Mathlib/Probability/Distributions/Uniform.lean b/Mathlib/Probability/Distributions/Uniform.lean index 77f3a13bb4a8c..3efd4efda464d 100644 --- a/Mathlib/Probability/Distributions/Uniform.lean +++ b/Mathlib/Probability/Distributions/Uniform.lean @@ -39,7 +39,7 @@ This file defines a number of uniform `PMF` distributions from various inputs, * Refactor the `PMF` definitions to come from a `uniformMeasure` on a `Finset`/`Fintype`/`Multiset`. -/ -open scoped Classical MeasureTheory NNReal ENNReal +open scoped MeasureTheory NNReal ENNReal -- TODO: We can't `open ProbabilityTheory` without opening the `ProbabilityTheory` locale :( open TopologicalSpace MeasureTheory.Measure PMF @@ -193,6 +193,7 @@ lemma uniformPDF_eq_pdf {s : Set E} (hs : MeasurableSet s) (hu : pdf.IsUniform X unfold uniformPDF exact Filter.EventuallyEq.trans (pdf.IsUniform.pdf_eq hs hu).symm (ae_eq_refl _) +open scoped Classical in /-- Alternative way of writing the uniformPDF. -/ lemma uniformPDF_ite {s : Set E} {x : E} : uniformPDF s x μ = if x ∈ s then (μ s)⁻¹ else 0 := by diff --git a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean index f5124ea768ad5..cf45350093d48 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean @@ -34,7 +34,6 @@ noncomputable section variable {α : Type*} -open scoped Classical open NNReal ENNReal MeasureTheory /-- A probability mass function, or discrete probability measures is a function `α → ℝ≥0∞` such @@ -99,6 +98,7 @@ theorem apply_eq_one_iff (p : PMF α) (a : α) : p a = 1 ↔ p.support = {a} := fun h => _root_.trans (symm <| tsum_eq_single a fun a' ha' => (p.apply_eq_zero_iff a').2 (h.symm ▸ ha')) p.tsum_coe⟩ suffices 1 < ∑' a, p a from ne_of_lt this p.tsum_coe.symm + classical have : 0 < ∑' b, ite (b = a) 0 (p b) := lt_of_le_of_ne' zero_le' ((tsum_ne_zero_iff ENNReal.summable).2 ⟨a', ite_ne_left_iff.2 ⟨ha, Ne.symm <| (p.mem_support_iff a').2 ha'⟩⟩) @@ -114,6 +114,7 @@ theorem apply_eq_one_iff (p : PMF α) (a : α) : p a = 1 ↔ p.support = {a} := _ = ∑' b, p b := tsum_congr fun b => by split_ifs <;> simp only [zero_add, add_zero, le_rfl] theorem coe_le_one (p : PMF α) (a : α) : p a ≤ 1 := by + classical refine hasSum_le (fun b => ?_) (hasSum_ite_eq a (p a)) (hasSum_coe_one p) split_ifs with h <;> simp only [h, zero_le', le_rfl] @@ -152,8 +153,8 @@ theorem toOuterMeasure_apply_finset (s : Finset α) : p.toOuterMeasure s = ∑ x theorem toOuterMeasure_apply_singleton (a : α) : p.toOuterMeasure {a} = p a := by refine (p.toOuterMeasure_apply {a}).trans ((tsum_eq_single a fun b hb => ?_).trans ?_) - · exact ite_eq_right_iff.2 fun hb' => False.elim <| hb hb' - · exact ite_eq_left_iff.2 fun ha' => False.elim <| ha' rfl + · classical exact ite_eq_right_iff.2 fun hb' => False.elim <| hb hb' + · classical exact ite_eq_left_iff.2 fun ha' => False.elim <| ha' rfl theorem toOuterMeasure_injective : (toOuterMeasure : PMF α → OuterMeasure α).Injective := fun p q h => PMF.ext fun x => (p.toOuterMeasure_apply_singleton x).symm.trans @@ -174,7 +175,7 @@ theorem toOuterMeasure_apply_eq_one_iff : p.toOuterMeasure s = 1 ↔ p.support have hsa : s.indicator p a < p a := hs'.symm ▸ (p.apply_pos_iff a).2 hap exact ENNReal.tsum_lt_tsum (p.tsum_coe_indicator_ne_top s) (fun x => Set.indicator_apply_le fun _ => le_rfl) hsa - · suffices ∀ (x) (_ : x ∉ s), p x = 0 from + · classical suffices ∀ (x) (_ : x ∉ s), p x = 0 from _root_.trans (tsum_congr fun a => (Set.indicator_apply s p a).trans (ite_eq_left_iff.2 <| symm ∘ this a)) p.tsum_coe diff --git a/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean b/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean index 6ef283f1de7dc..95ab35f0e5b9f 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean @@ -32,7 +32,6 @@ noncomputable section variable {α β γ : Type*} -open scoped Classical open NNReal ENNReal Finset MeasureTheory section Map @@ -45,6 +44,7 @@ variable (f : α → β) (p : PMF α) (b : β) theorem monad_map_eq_map {α β : Type u} (f : α → β) (p : PMF α) : f <$> p = p.map f := rfl +open scoped Classical in @[simp] theorem map_apply : (map f p) b = ∑' a, if b = f a then p a else 0 := by simp [map] @@ -82,6 +82,7 @@ variable (s : Set β) @[simp] theorem toOuterMeasure_map_apply : (p.map f).toOuterMeasure s = p.toOuterMeasure (f ⁻¹' s) := by simp [map, Set.indicator, toOuterMeasure_apply p (f ⁻¹' s)] + rfl variable {mα : MeasurableSpace α} {mβ : MeasurableSpace β} @@ -110,6 +111,7 @@ variable (q : PMF (α → β)) (p : PMF α) (b : β) theorem monad_seq_eq_seq {α β : Type u} (q : PMF (α → β)) (p : PMF α) : q <*> p = q.seq p := rfl +open scoped Classical in @[simp] theorem seq_apply : (seq q p) b = ∑' (f : α → β) (a : α), if b = f a then q f * p a else 0 := by simp only [seq, mul_boole, bind_apply, pure_apply] @@ -207,6 +209,7 @@ theorem support_ofFintype : (ofFintype f h).support = Function.support f := rfl theorem mem_support_ofFintype_iff (a : α) : a ∈ (ofFintype f h).support ↔ f a ≠ 0 := Iff.rfl +open scoped Classical in @[simp] lemma map_ofFintype [Fintype β] (f : α → ℝ≥0∞) (h : ∑ a, f a = 1) (g : α → β) : (ofFintype f h).map g = ofFintype (fun b ↦ ∑ a with g a = b, f a) diff --git a/Mathlib/Probability/ProbabilityMassFunction/Monad.lean b/Mathlib/Probability/ProbabilityMassFunction/Monad.lean index acf07b214fb38..ee267a4c971de 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Monad.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Monad.lean @@ -23,7 +23,6 @@ noncomputable section variable {α β γ : Type*} -open scoped Classical open NNReal ENNReal open MeasureTheory @@ -32,6 +31,7 @@ namespace PMF section Pure +open scoped Classical in /-- The pure `PMF` is the `PMF` where all the mass lies in one point. The value of `pure a` is `1` at `a` and `0` elsewhere. -/ def pure (a : α) : PMF α := @@ -39,6 +39,7 @@ def pure (a : α) : PMF α := variable (a a' : α) +open scoped Classical in @[simp] theorem pure_apply : pure a a' = if a' = a then 1 else 0 := rfl @@ -61,6 +62,7 @@ section Measure variable (s : Set α) +open scoped Classical in @[simp] theorem toOuterMeasure_pure_apply : (pure a).toOuterMeasure s = if a ∈ s then 1 else 0 := by refine (toOuterMeasure_apply (pure a) s).trans ?_ @@ -74,6 +76,7 @@ theorem toOuterMeasure_pure_apply : (pure a).toOuterMeasure s = if a ∈ s then variable [MeasurableSpace α] +open scoped Classical in /-- The measure of a set under `pure a` is `1` for sets containing `a` and `0` otherwise. -/ @[simp] theorem toMeasure_pure_apply (hs : MeasurableSet s) : @@ -115,6 +118,7 @@ theorem mem_support_bind_iff (b : β) : @[simp] theorem pure_bind (a : α) (f : α → PMF β) : (pure a).bind f = f a := by + classical have : ∀ b a', ite (a' = a) (f a' b) 0 = ite (a' = a) (f a b) 0 := fun b a' => by split_ifs with h <;> simp [h] ext b @@ -148,7 +152,8 @@ variable (s : Set β) @[simp] theorem toOuterMeasure_bind_apply : - (p.bind f).toOuterMeasure s = ∑' a, p a * (f a).toOuterMeasure s := + (p.bind f).toOuterMeasure s = ∑' a, p a * (f a).toOuterMeasure s := by + classical calc (p.bind f).toOuterMeasure s = ∑' b, if b ∈ s then ∑' a, p a * f a b else 0 := by simp [toOuterMeasure_apply, Set.indicator_apply] @@ -236,6 +241,7 @@ theorem pure_bindOnSupport (a : α) (f : ∀ (a' : α) (_ : a' ∈ (pure a).supp (pure a).bindOnSupport f = f a ((mem_support_pure_iff a a).mpr rfl) := by refine PMF.ext fun b => ?_ simp only [bindOnSupport_apply, pure_apply] + classical refine _root_.trans (tsum_congr fun a' => ?_) (tsum_ite_eq a _) by_cases h : a' = a <;> simp [h] @@ -252,6 +258,7 @@ theorem bindOnSupport_bindOnSupport (p : PMF α) (f : ∀ a ∈ p.support, PMF refine PMF.ext fun a => ?_ dsimp only [bindOnSupport_apply] simp only [← tsum_dite_right, ENNReal.tsum_mul_left.symm, ENNReal.tsum_mul_right.symm] + classical simp only [ENNReal.tsum_eq_zero, dite_eq_left_iff] refine ENNReal.tsum_comm.trans (tsum_congr fun a' => tsum_congr fun b => ?_) split_ifs with h _ h_1 _ h_2 @@ -279,6 +286,7 @@ theorem toOuterMeasure_bindOnSupport_apply : (p.bindOnSupport f).toOuterMeasure s = ∑' a, p a * if h : p a = 0 then 0 else (f a h).toOuterMeasure s := by simp only [toOuterMeasure_apply, Set.indicator_apply, bindOnSupport_apply] + classical calc (∑' b, ite (b ∈ s) (∑' a, p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0) = ∑' (b) (a), ite (b ∈ s) (p a * dite (p a = 0) (fun h => 0) fun h => f a h b) 0 := diff --git a/Mathlib/Probability/Process/Adapted.lean b/Mathlib/Probability/Process/Adapted.lean index 101965bb8f539..eb30f8b442411 100644 --- a/Mathlib/Probability/Process/Adapted.lean +++ b/Mathlib/Probability/Process/Adapted.lean @@ -35,7 +35,7 @@ adapted, progressively measurable open Filter Order TopologicalSpace -open scoped Classical MeasureTheory NNReal ENNReal Topology +open scoped MeasureTheory NNReal ENNReal Topology namespace MeasureTheory diff --git a/Mathlib/Probability/Process/HittingTime.lean b/Mathlib/Probability/Process/HittingTime.lean index b5a22e608a3fe..5ac75975d6483 100644 --- a/Mathlib/Probability/Process/HittingTime.lean +++ b/Mathlib/Probability/Process/HittingTime.lean @@ -36,21 +36,25 @@ hitting times indexed by the natural numbers or the reals. By taking the bounds open Filter Order TopologicalSpace -open scoped Classical MeasureTheory NNReal ENNReal Topology +open scoped MeasureTheory NNReal ENNReal Topology namespace MeasureTheory variable {Ω β ι : Type*} {m : MeasurableSpace Ω} +open scoped Classical in /-- Hitting time: given a stochastic process `u` and a set `s`, `hitting u s n m` is the first time `u` is in `s` after time `n` and before time `m` (if `u` does not hit `s` after time `n` and before `m` then the hitting time is simply `m`). The hitting time is a stopping time if the process is adapted and discrete. -/ -noncomputable def hitting [Preorder ι] [InfSet ι] (u : ι → Ω → β) (s : Set β) (n m : ι) : Ω → ι := - fun x => if ∃ j ∈ Set.Icc n m, u j x ∈ s then sInf (Set.Icc n m ∩ {i : ι | u i x ∈ s}) else m +noncomputable def hitting [Preorder ι] [InfSet ι] (u : ι → Ω → β) + (s : Set β) (n m : ι) : Ω → ι := + fun x => if ∃ j ∈ Set.Icc n m, u j x ∈ s + then sInf (Set.Icc n m ∩ {i : ι | u i x ∈ s}) else m #adaptation_note /-- nightly-2024-03-16: added to replace simp [hitting] -/ +open scoped Classical in theorem hitting_def [Preorder ι] [InfSet ι] (u : ι → Ω → β) (s : Set β) (n m : ι) : hitting u s n m = fun x => if ∃ j ∈ Set.Icc n m, u j x ∈ s then sInf (Set.Icc n m ∩ {i : ι | u i x ∈ s}) else m := @@ -90,11 +94,13 @@ theorem not_mem_of_lt_hitting {m k : ι} (hk₁ : k < hitting u s n m ω) (hk₂ theorem hitting_eq_end_iff {m : ι} : hitting u s n m ω = m ↔ (∃ j ∈ Set.Icc n m, u j ω ∈ s) → sInf (Set.Icc n m ∩ {i : ι | u i ω ∈ s}) = m := by + classical rw [hitting, ite_eq_right_iff] theorem hitting_of_le {m : ι} (hmn : m ≤ n) : hitting u s n m ω = m := by obtain rfl | h := le_iff_eq_or_lt.1 hmn - · rw [hitting, ite_eq_right_iff, forall_exists_index] + · classical + rw [hitting, ite_eq_right_iff, forall_exists_index] conv => intro; rw [Set.mem_Icc, Set.Icc_self, and_imp, and_imp] intro i hi₁ hi₂ hi rw [Set.inter_eq_left.2, csInf_singleton] diff --git a/Mathlib/Probability/Process/Stopping.lean b/Mathlib/Probability/Process/Stopping.lean index a9b107e3d88e4..80f76791df248 100644 --- a/Mathlib/Probability/Process/Stopping.lean +++ b/Mathlib/Probability/Process/Stopping.lean @@ -33,7 +33,7 @@ stopping time, stochastic process open Filter Order TopologicalSpace -open scoped Classical MeasureTheory NNReal ENNReal Topology +open scoped MeasureTheory NNReal ENNReal Topology namespace MeasureTheory @@ -96,6 +96,7 @@ protected theorem measurableSet_eq_of_countable_range (hτ : IsStoppingTime f τ rw [this] refine (hτ.measurableSet_le i).diff ?_ refine MeasurableSet.biUnion h_countable fun j _ => ?_ + classical rw [Set.iUnion_eq_if] split_ifs with hji · exact f.mono hji.le _ (hτ.measurableSet_le j) @@ -803,6 +804,7 @@ variable {μ : Measure Ω} {τ : Ω → ι} {E : Type*} {p : ℝ≥0∞} {u : ι theorem stoppedValue_eq_of_mem_finset [AddCommMonoid E] {s : Finset ι} (hbdd : ∀ ω, τ ω ∈ s) : stoppedValue u τ = ∑ i ∈ s, Set.indicator {ω | τ ω = i} (u i) := by ext y + classical rw [stoppedValue, Finset.sum_apply, Finset.sum_indicator_eq_sum_filter] suffices Finset.filter (fun i => y ∈ {ω : Ω | τ ω = i}) s = ({τ y} : Finset ι) by rw [this, Finset.sum_singleton] diff --git a/Mathlib/RepresentationTheory/Character.lean b/Mathlib/RepresentationTheory/Character.lean index cb98ce35c607a..ada933887ae23 100644 --- a/Mathlib/RepresentationTheory/Character.lean +++ b/Mathlib/RepresentationTheory/Character.lean @@ -98,10 +98,9 @@ section Orthogonality variable {G : Grp.{u}} [IsAlgClosed k] -open scoped Classical - variable [Fintype G] [Invertible (Fintype.card G : k)] +open scoped Classical in /-- Orthogonality of characters for irreducible representations of finite group over an algebraically closed field whose characteristic doesn't divide the order of the group. -/ theorem char_orthonormal (V W : FDRep k G) [Simple V] [Simple W] : diff --git a/Mathlib/RepresentationTheory/FDRep.lean b/Mathlib/RepresentationTheory/FDRep.lean index 8eaedce3ed27a..dd5870c18de16 100644 --- a/Mathlib/RepresentationTheory/FDRep.lean +++ b/Mathlib/RepresentationTheory/FDRep.lean @@ -128,12 +128,11 @@ example : MonoidalLinear k (FDRep k G) := by infer_instance open Module -open scoped Classical - -- We need to provide this instance explicitly as otherwise `finrank_hom_simple_simple` gives a -- deterministic timeout. instance : HasKernels (FDRep k G) := by infer_instance +open scoped Classical in /-- Schur's Lemma: the dimension of the `Hom`-space between two irreducible representation is `0` if they are not isomorphic, and `1` if they are. -/ theorem finrank_hom_simple_simple [IsAlgClosed k] (V W : FDRep k G) [Simple V] [Simple W] : diff --git a/Mathlib/RingTheory/Adjoin/FG.lean b/Mathlib/RingTheory/Adjoin/FG.lean index b98e44e79d735..1ea80e3f8b9f8 100644 --- a/Mathlib/RingTheory/Adjoin/FG.lean +++ b/Mathlib/RingTheory/Adjoin/FG.lean @@ -129,11 +129,10 @@ theorem FG.prod {S : Subalgebra R A} {T : Subalgebra R B} (hS : S.FG) (hT : T.FG section -open scoped Classical - -theorem FG.map {S : Subalgebra R A} (f : A →ₐ[R] B) (hs : S.FG) : (S.map f).FG := +theorem FG.map {S : Subalgebra R A} (f : A →ₐ[R] B) (hs : S.FG) : (S.map f).FG := by let ⟨s, hs⟩ := hs - ⟨s.image f, by rw [Finset.coe_image, Algebra.adjoin_image, hs]⟩ + classical + exact ⟨s.image f, by rw [Finset.coe_image, Algebra.adjoin_image, hs]⟩ end diff --git a/Mathlib/RingTheory/Adjoin/Tower.lean b/Mathlib/RingTheory/Adjoin/Tower.lean index c916d29572648..5e0b6870afb10 100644 --- a/Mathlib/RingTheory/Adjoin/Tower.lean +++ b/Mathlib/RingTheory/Adjoin/Tower.lean @@ -58,17 +58,19 @@ end Algebra section -open scoped Classical - theorem Algebra.fg_trans' {R S A : Type*} [CommSemiring R] [CommSemiring S] [Semiring A] [Algebra R S] [Algebra S A] [Algebra R A] [IsScalarTower R S A] (hRS : (⊤ : Subalgebra R S).FG) - (hSA : (⊤ : Subalgebra S A).FG) : (⊤ : Subalgebra R A).FG := - let ⟨s, hs⟩ := hRS - let ⟨t, ht⟩ := hSA - ⟨s.image (algebraMap S A) ∪ t, by - rw [Finset.coe_union, Finset.coe_image, Algebra.adjoin_algebraMap_image_union_eq_adjoin_adjoin, - hs, Algebra.adjoin_top, ht, Subalgebra.restrictScalars_top, Subalgebra.restrictScalars_top]⟩ - + (hSA : (⊤ : Subalgebra S A).FG) : (⊤ : Subalgebra R A).FG := by + classical + rcases hRS with ⟨s, hs⟩ + rcases hSA with ⟨t, ht⟩ + exact ⟨s.image (algebraMap S A) ∪ t, by + rw [Finset.coe_union, Finset.coe_image, + Algebra.adjoin_algebraMap_image_union_eq_adjoin_adjoin, + hs, Algebra.adjoin_top, ht, Subalgebra.restrictScalars_top, + Subalgebra.restrictScalars_top + ] + ⟩ end section ArtinTate @@ -82,8 +84,6 @@ variable [Algebra A B] [Algebra B C] [Algebra A C] [IsScalarTower A B C] open Finset Submodule -open scoped Classical - theorem exists_subalgebra_of_fg (hAC : (⊤ : Subalgebra A C).FG) (hBC : (⊤ : Submodule B C).FG) : ∃ B₀ : Subalgebra A B, B₀.FG ∧ (⊤ : Submodule B₀ C).FG := by cases' hAC with x hx @@ -91,6 +91,7 @@ theorem exists_subalgebra_of_fg (hAC : (⊤ : Subalgebra A C).FG) (hBC : (⊤ : have := hy simp_rw [eq_top_iff', mem_span_finset] at this choose f hf using this + classical let s : Finset B := Finset.image₂ f (x ∪ y * y) y have hxy : ∀ xi ∈ x, xi ∈ span (Algebra.adjoin A (↑s : Set B)) (↑(insert 1 y : Finset C) : Set C) := diff --git a/Mathlib/RingTheory/AdjoinRoot.lean b/Mathlib/RingTheory/AdjoinRoot.lean index 6d04333d192e0..b861c1ecbe216 100644 --- a/Mathlib/RingTheory/AdjoinRoot.lean +++ b/Mathlib/RingTheory/AdjoinRoot.lean @@ -48,8 +48,6 @@ The main definitions are in the `AdjoinRoot` namespace. noncomputable section -open scoped Classical - open Polynomial universe u v w diff --git a/Mathlib/RingTheory/AlgebraTower.lean b/Mathlib/RingTheory/AlgebraTower.lean index cd4e432e660f0..ef70b261a1645 100644 --- a/Mathlib/RingTheory/AlgebraTower.lean +++ b/Mathlib/RingTheory/AlgebraTower.lean @@ -85,8 +85,6 @@ section Semiring open Finsupp -open scoped Classical - variable {R S A} variable [Semiring R] [Semiring S] [AddCommMonoid A] variable [Module R S] [Module S A] [Module R A] [IsScalarTower R S A] @@ -132,6 +130,7 @@ theorem Basis.smulTower_repr_mk (x i j) : (b.smulTower c).repr x (i, j) = b.repr @[simp] theorem Basis.smulTower_apply (ij) : (b.smulTower c) ij = b ij.1 • c ij.2 := by + classical obtain ⟨i, j⟩ := ij rw [Basis.apply_eq_iff] ext ⟨i', j'⟩ diff --git a/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean b/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean index 46cb51be48adf..66a7c7a829c69 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/Adjoin.lean @@ -25,8 +25,6 @@ noncomputable section open Function Set Subalgebra MvPolynomial Algebra -open scoped Classical - namespace AlgebraicIndependent variable {ι : Type*} diff --git a/Mathlib/RingTheory/AlgebraicIndependent/Basic.lean b/Mathlib/RingTheory/AlgebraicIndependent/Basic.lean index 0660623b33d9f..6f7f1983917b2 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/Basic.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/Basic.lean @@ -33,8 +33,6 @@ noncomputable section open Function Set Subalgebra MvPolynomial Algebra -open scoped Classical - variable {ι ι' R K A A' : Type*} {x : ι → A} variable [CommRing R] [CommRing A] [CommRing A'] [Algebra R A] [Algebra R A'] diff --git a/Mathlib/RingTheory/AlgebraicIndependent/Defs.lean b/Mathlib/RingTheory/AlgebraicIndependent/Defs.lean index c3d9b6df75314..83bd22ac7b31c 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent/Defs.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent/Defs.lean @@ -41,8 +41,6 @@ noncomputable section open Function Set Subalgebra MvPolynomial Algebra -open scoped Classical - variable {ι ι' : Type*} (R : Type*) {K A A' : Type*} (x : ι → A) variable [CommRing R] [CommRing A] [CommRing A'] [Algebra R A] [Algebra R A'] diff --git a/Mathlib/RingTheory/FiniteType.lean b/Mathlib/RingTheory/FiniteType.lean index 40f8bd11de976..c8b20cf8bab7c 100644 --- a/Mathlib/RingTheory/FiniteType.lean +++ b/Mathlib/RingTheory/FiniteType.lean @@ -75,10 +75,10 @@ protected theorem polynomial : FiniteType R R[X] := rw [Finset.coe_singleton] exact Polynomial.adjoin_X⟩⟩ -open scoped Classical protected theorem freeAlgebra (ι : Type*) [Finite ι] : FiniteType R (FreeAlgebra R ι) := by cases nonempty_fintype ι + classical exact ⟨⟨Finset.univ.image (FreeAlgebra.ι R), by rw [Finset.coe_image, Finset.coe_univ, Set.image_univ] @@ -86,6 +86,7 @@ protected theorem freeAlgebra (ι : Type*) [Finite ι] : FiniteType R (FreeAlgeb protected theorem mvPolynomial (ι : Type*) [Finite ι] : FiniteType R (MvPolynomial ι R) := by cases nonempty_fintype ι + classical exact ⟨⟨Finset.univ.image MvPolynomial.X, by rw [Finset.coe_image, Finset.coe_univ, Set.image_univ] diff --git a/Mathlib/RingTheory/Fintype.lean b/Mathlib/RingTheory/Fintype.lean index 9ee3bc2a315f2..e13486bc2013a 100644 --- a/Mathlib/RingTheory/Fintype.lean +++ b/Mathlib/RingTheory/Fintype.lean @@ -51,8 +51,7 @@ lemma Finset.univ_of_card_le_three (h : Fintype.card R ≤ 3) : · exact zero_ne_one h · exact zero_ne_one h.symm -open scoped Classical - +open scoped Classical in theorem card_units_lt (M₀ : Type*) [MonoidWithZero M₀] [Nontrivial M₀] [Fintype M₀] : Fintype.card M₀ˣ < Fintype.card M₀ := Fintype.card_lt_of_injective_of_not_mem Units.val Units.ext not_isUnit_zero diff --git a/Mathlib/RingTheory/FreeCommRing.lean b/Mathlib/RingTheory/FreeCommRing.lean index af33998c3ea6e..a09a60ff00f16 100644 --- a/Mathlib/RingTheory/FreeCommRing.lean +++ b/Mathlib/RingTheory/FreeCommRing.lean @@ -50,7 +50,6 @@ free commutative ring, free ring noncomputable section -open scoped Classical open Polynomial universe u v @@ -224,6 +223,7 @@ end Restriction theorem isSupported_of {p} {s : Set α} : IsSupported (of p) s ↔ p ∈ s := suffices IsSupported (of p) s → p ∈ s from ⟨this, fun hps => Subring.subset_closure ⟨p, hps, rfl⟩⟩ fun hps : IsSupported (of p) s => by + classical haveI := Classical.decPred s have : ∀ x, IsSupported x s → ∃ n : ℤ, lift (fun a => if a ∈ s then (0 : ℤ[X]) else Polynomial.X) x = n := by diff --git a/Mathlib/RingTheory/LaurentSeries.lean b/Mathlib/RingTheory/LaurentSeries.lean index dbbef917b461d..fd5d7b6a7e4a6 100644 --- a/Mathlib/RingTheory/LaurentSeries.lean +++ b/Mathlib/RingTheory/LaurentSeries.lean @@ -89,7 +89,7 @@ structure on the `X`-adic completion of `K⸨X⸩`. Once this will be available, -/ universe u -open scoped Classical PowerSeries +open scoped PowerSeries open HahnSeries Polynomial noncomputable section @@ -541,6 +541,7 @@ theorem intValuation_eq_of_coe (P : K[X]) : (Ideal.span {↑P} : Ideal K⟦X⟧) ≠ 0 ∧ ((idealX K).asIdeal : Ideal K⟦X⟧) ≠ 0 := by simp only [Ideal.zero_eq_bot, ne_eq, Ideal.span_singleton_eq_bot, coe_eq_zero_iff, hP, not_false_eq_true, true_and, (idealX K).3] + classical rw [count_associates_factors_eq (span_ne_zero).1 (Ideal.span_singleton_prime Polynomial.X_ne_zero|>.mpr prime_X) (span_ne_zero).2, count_associates_factors_eq] diff --git a/Mathlib/RingTheory/Perfection.lean b/Mathlib/RingTheory/Perfection.lean index 6dc12681fc5bd..210e3d6dbc519 100644 --- a/Mathlib/RingTheory/Perfection.lean +++ b/Mathlib/RingTheory/Perfection.lean @@ -454,10 +454,9 @@ instance : CharP (PreTilt K v O hv p) p := section Classical -open scoped Classical - open Perfection +open scoped Classical in /-- The valuation `Perfection(O/(p)) → ℝ≥0` as a function. Given `f ∈ Perfection(O/(p))`, if `f = 0` then output `0`; otherwise output `preVal(f(n))^(p^n)` for any `n` such that `f(n) ≠ 0`. -/ @@ -468,6 +467,7 @@ noncomputable def valAux (f : PreTilt K v O hv p) : ℝ≥0 := variable {K v O hv p} +open scoped Classical in theorem coeff_nat_find_add_ne_zero {f : PreTilt K v O hv p} {h : ∃ n, coeff _ _ n f ≠ 0} (k : ℕ) : coeff _ _ (Nat.find h + k) f ≠ 0 := coeff_add_ne_zero (Nat.find_spec h) k @@ -476,6 +476,7 @@ theorem valAux_eq {f : PreTilt K v O hv p} {n : ℕ} (hfn : coeff _ _ n f ≠ 0) valAux K v O hv p f = ModP.preVal K v O hv p (coeff _ _ n f) ^ p ^ n := by have h : ∃ n, coeff _ _ n f ≠ 0 := ⟨n, hfn⟩ rw [valAux, dif_pos h] + classical obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_le (Nat.find_min' h hfn) induction' k with k ih · rfl diff --git a/Mathlib/RingTheory/PrincipalIdealDomain.lean b/Mathlib/RingTheory/PrincipalIdealDomain.lean index 77a6f3b5770e5..58ef2b97976b3 100644 --- a/Mathlib/RingTheory/PrincipalIdealDomain.lean +++ b/Mathlib/RingTheory/PrincipalIdealDomain.lean @@ -307,8 +307,7 @@ variable [CommRing R] [IsDomain R] [IsPrincipalIdealRing R] section -open scoped Classical - +open scoped Classical in /-- `factors a` is a multiset of irreducible elements whose product is `a`, up to units -/ noncomputable def factors (a : R) : Multiset R := if h : a = 0 then ∅ else Classical.choose (WfDvdMonoid.exists_factors a h) diff --git a/Mathlib/RingTheory/Radical.lean b/Mathlib/RingTheory/Radical.lean index a213f7b39bfec..50e56b9aa02d5 100644 --- a/Mathlib/RingTheory/Radical.lean +++ b/Mathlib/RingTheory/Radical.lean @@ -47,14 +47,13 @@ This is different from the radical of an ideal. noncomputable section -open scoped Classical - namespace UniqueFactorizationMonoid -- `CancelCommMonoidWithZero` is required by `UniqueFactorizationMonoid` variable {M : Type*} [CancelCommMonoidWithZero M] [NormalizationMonoid M] [UniqueFactorizationMonoid M] +open scoped Classical in /-- The finite set of prime factors of an element in a unique factorization monoid. -/ def primeFactors (a : M) : Finset M := (normalizedFactors a).toFinset @@ -74,10 +73,12 @@ def radical (a : M) : M := @[simp] theorem radical_zero_eq : radical (0 : M) = 1 := by + classical rw [radical, primeFactors, normalizedFactors_zero, Multiset.toFinset_zero, Finset.prod_empty] @[simp] theorem radical_one_eq : radical (1 : M) = 1 := by + classical rw [radical, primeFactors, normalizedFactors_one, Multiset.toFinset_zero, Finset.prod_empty] theorem radical_eq_of_associated {a b : M} (h : Associated a b) : radical a = radical b := by @@ -100,6 +101,7 @@ theorem radical_pow (a : M) {n : Nat} (hn : 0 < n) : radical (a ^ n) = radical a simp_rw [radical, primeFactors_pow a hn] theorem radical_dvd_self (a : M) : radical a ∣ a := by + classical by_cases ha : a = 0 · rw [ha] apply dvd_zero @@ -147,13 +149,15 @@ theorem disjoint_normalizedFactors {a b : R} (hc : IsCoprime a b) : /-- Coprime elements have disjoint prime factors (as finsets). -/ theorem disjoint_primeFactors {a b : R} (hc : IsCoprime a b) : - Disjoint (primeFactors a) (primeFactors b) := - Multiset.disjoint_toFinset.mpr (disjoint_normalizedFactors hc) + Disjoint (primeFactors a) (primeFactors b) := by + classical + exact Multiset.disjoint_toFinset.mpr (disjoint_normalizedFactors hc) theorem mul_primeFactors_disjUnion {a b : R} (ha : a ≠ 0) (hb : b ≠ 0) (hc : IsCoprime a b) : primeFactors (a * b) = (primeFactors a).disjUnion (primeFactors b) (disjoint_primeFactors hc) := by + classical rw [Finset.disjUnion_eq_union] simp_rw [primeFactors] rw [normalizedFactors_mul ha hb, Multiset.toFinset_add] diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean index 536e6f256c14d..e13efc0c60bcb 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean @@ -14,8 +14,6 @@ Basic properties the maximal spectrum of a ring. noncomputable section -open scoped Classical - variable (R S P : Type*) [CommSemiring R] [CommSemiring S] [CommSemiring P] namespace MaximalSpectrum diff --git a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean index c789426f03c36..0f54c2ec83cac 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean @@ -42,7 +42,7 @@ assert_not_exists TopologicalSpace noncomputable section -open scoped Classical Pointwise +open scoped Pointwise universe u v @@ -560,6 +560,7 @@ and is a homeomorphism when ι is finite. -/ | ⟨i, p⟩ => (Pi.evalRingHom R i).specComap p theorem sigmaToPi_injective : (sigmaToPi R).Injective := fun ⟨i, p⟩ ⟨j, q⟩ eq ↦ by + classical obtain rfl | ne := eq_or_ne i j · congr; ext x simpa using congr_arg (Function.update (0 : ∀ i, R i) i x ∈ ·.asIdeal) eq @@ -575,6 +576,7 @@ range of `sigmaToPi`, i.e. is not of the form `πᵢ⁻¹(𝔭)` for some prime see https://math.stackexchange.com/a/1563190. -/ theorem exists_maximal_nmem_range_sigmaToPi_of_infinite : ∃ (I : Ideal (Π i, R i)) (_ : I.IsMaximal), ⟨I, inferInstance⟩ ∉ Set.range (sigmaToPi R) := by + classical let J : Ideal (Π i, R i) := -- `J := Π₀ i, R i` is an ideal in `Π i, R i` { __ := AddMonoidHom.mrange DFinsupp.coeFnAddMonoidHom smul_mem' := by diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index 5ff8726949782..d188fcced5444 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -57,7 +57,6 @@ If ever someone extends `Valuation`, we should fully comply to the `DFunLike` by boilerplate lemmas to `ValuationClass`. -/ -open scoped Classical open Function Ideal noncomputable section @@ -168,6 +167,7 @@ theorem map_add_lt {x y g} (hx : v x < g) (hy : v y < g) : v (x + y) < g := theorem map_sum_le {ι : Type*} {s : Finset ι} {f : ι → R} {g : Γ₀} (hf : ∀ i ∈ s, v (f i) ≤ g) : v (∑ i ∈ s, f i) ≤ g := by + classical refine Finset.induction_on s (fun _ => v.map_zero ▸ zero_le') (fun a s has ih hf => ?_) hf @@ -176,6 +176,7 @@ theorem map_sum_le {ι : Type*} {s : Finset ι} {f : ι → R} {g : Γ₀} (hf : theorem map_sum_lt {ι : Type*} {s : Finset ι} {f : ι → R} {g : Γ₀} (hg : g ≠ 0) (hf : ∀ i ∈ s, v (f i) < g) : v (∑ i ∈ s, f i) < g := by + classical refine Finset.induction_on s (fun _ => v.map_zero ▸ (zero_lt_iff.2 hg)) (fun a s has ih hf => ?_) hf @@ -305,6 +306,7 @@ theorem map_sub_eq_of_lt_right (h : v x < v y) : v (x - y) = v y := by rw [sub_eq_add_neg, map_add_eq_of_lt_right, map_neg] rwa [map_neg] +open scoped Classical in theorem map_sum_eq_of_lt {ι : Type*} {s : Finset ι} {f : ι → R} {j : ι} (hj : j ∈ s) (h0 : v (f j) ≠ 0) (hf : ∀ i ∈ s \ {j}, v (f i) < v (f j)) : v (∑ i ∈ s, f i) = v (f j) := by From ba4ffc06ec28cb04289d0daf1f07809e2c6f494a Mon Sep 17 00:00:00 2001 From: Christopher Hoskin Date: Tue, 21 Jan 2025 01:06:02 +0000 Subject: [PATCH 357/681] refactor(LinearAlgebra/Projection): Use IsIdempotentElem (#20665) Use `IsIdempotentElem` in a number of locations instead of `? * ? = ?`. - Algebra/Algebra/Subalgebra/Pointwise - Algebra/Ring/BooleanRing - LinearAlgebra/Projection - RingTheory/DedekindDomain/Ideal Other uses of `? * ? = ?` are not rings or have `to_additive`, which our current definition of `IsIdempotentElem` does not support. My interest in opening this PR is `LinearAlgebra/Projection`. The others are perhaps more tenuous. I have made them individual commits so any not required can easily be reverted. Co-authored-by: Christopher Hoskin --- Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean | 9 ++++++--- Mathlib/Algebra/Ring/BooleanRing.lean | 12 +++++++----- Mathlib/LinearAlgebra/Projection.lean | 11 ++++++----- Mathlib/RingTheory/DedekindDomain/Ideal.lean | 5 ++++- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean b/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean index 5003f01d48ca5..b68ffd013e5a0 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean @@ -31,8 +31,8 @@ theorem mul_toSubmodule_le (S T : Subalgebra R A) : /-- As submodules, subalgebras are idempotent. -/ @[simp] -theorem mul_self (S : Subalgebra R A) : (Subalgebra.toSubmodule S) * (Subalgebra.toSubmodule S) - = (Subalgebra.toSubmodule S) := by +theorem isIdempotentElem_toSubmodule (S : Subalgebra R A) : + IsIdempotentElem S.toSubmodule := by apply le_antisymm · refine (mul_toSubmodule_le _ _).trans_eq ?_ rw [sup_idem] @@ -40,6 +40,8 @@ theorem mul_self (S : Subalgebra R A) : (Subalgebra.toSubmodule S) * (Subalgebra rw [← mul_one x] exact Submodule.mul_mem_mul hx1 (show (1 : A) ∈ S from one_mem S) +@[deprecated (since := "2025-01-12")] alias mul_self := isIdempotentElem_toSubmodule + /-- When `A` is commutative, `Subalgebra.mul_toSubmodule_le` is strict. -/ theorem mul_toSubmodule {R : Type*} {A : Type*} [CommSemiring R] [CommSemiring A] [Algebra R A] (S T : Subalgebra R A) : (Subalgebra.toSubmodule S) * (Subalgebra.toSubmodule T) @@ -58,7 +60,8 @@ theorem mul_toSubmodule {R : Type*} {A : Type*} [CommSemiring R] [CommSemiring A exact Submodule.mul_mem_mul (show (1 : A) ∈ S from one_mem S) (algebraMap_mem T _) have := Submodule.mul_mem_mul hx hy rwa [mul_assoc, mul_comm _ (Subalgebra.toSubmodule T), ← mul_assoc _ _ (Subalgebra.toSubmodule S), - mul_self, mul_comm (Subalgebra.toSubmodule T), ← mul_assoc, mul_self] at this + isIdempotentElem_toSubmodule, mul_comm T.toSubmodule, ← mul_assoc, + isIdempotentElem_toSubmodule] at this variable {R' : Type*} [Semiring R'] [MulSemiringAction R' A] [SMulCommClass R' R A] diff --git a/Mathlib/Algebra/Ring/BooleanRing.lean b/Mathlib/Algebra/Ring/BooleanRing.lean index a40d3face51cc..bf9d1d82ec74c 100644 --- a/Mathlib/Algebra/Ring/BooleanRing.lean +++ b/Mathlib/Algebra/Ring/BooleanRing.lean @@ -8,6 +8,7 @@ import Mathlib.Tactic.Abel import Mathlib.Tactic.Ring import Mathlib.Order.Hom.Lattice import Mathlib.Algebra.Ring.Equiv +import Mathlib.Algebra.Group.Idempotent /-! # Boolean rings @@ -46,17 +47,18 @@ variable {α β γ : Type*} /-- A Boolean ring is a ring where multiplication is idempotent. -/ class BooleanRing (α) extends Ring α where /-- Multiplication in a boolean ring is idempotent. -/ - mul_self : ∀ a : α, a * a = a + isIdempotentElem (a : α) : IsIdempotentElem a namespace BooleanRing variable [BooleanRing α] (a b : α) +@[scoped simp] +lemma mul_self : a * a = a := IsIdempotentElem.eq (isIdempotentElem a) + instance : Std.IdempotentOp (α := α) (· * ·) := ⟨BooleanRing.mul_self⟩ -attribute [scoped simp] mul_self - @[scoped simp] theorem add_self : a + a = 0 := by have : a + a = a + a + (a + a) := @@ -410,7 +412,7 @@ abbrev BooleanAlgebra.toBooleanRing : BooleanRing α where one := ⊤ one_mul := top_inf_eq mul_one := inf_top_eq - mul_self := inf_idem + isIdempotentElem := inf_idem scoped[BooleanRingOfBooleanAlgebra] attribute [instance] GeneralizedBooleanAlgebra.toNonUnitalCommRing BooleanAlgebra.toBooleanRing @@ -529,7 +531,7 @@ instance : BooleanRing Bool where mul_one := Bool.and_true left_distrib := and_xor_distrib_left right_distrib := and_xor_distrib_right - mul_self := Bool.and_self + isIdempotentElem := Bool.and_self zero_mul _ := rfl mul_zero a := by cases a <;> rfl nsmul := nsmulRec diff --git a/Mathlib/LinearAlgebra/Projection.lean b/Mathlib/LinearAlgebra/Projection.lean index c025f3b525548..1a1fee69243a9 100644 --- a/Mathlib/LinearAlgebra/Projection.lean +++ b/Mathlib/LinearAlgebra/Projection.lean @@ -367,12 +367,11 @@ structure IsProj {F : Type*} [FunLike F M M] (f : F) : Prop where map_mem : ∀ x, f x ∈ m map_id : ∀ x ∈ m, f x = x -theorem isProj_iff_idempotent (f : M →ₗ[S] M) : (∃ p : Submodule S M, IsProj p f) ↔ f ∘ₗ f = f := by +theorem isProj_iff_isIdempotentElem (f : M →ₗ[S] M) : + (∃ p : Submodule S M, IsProj p f) ↔ IsIdempotentElem f := by constructor - · intro h - obtain ⟨p, hp⟩ := h + · intro ⟨p, hp⟩ ext x - rw [comp_apply] exact hp.map_id (f x) (hp.map_mem x) · intro h use range f @@ -381,7 +380,9 @@ theorem isProj_iff_idempotent (f : M →ₗ[S] M) : (∃ p : Submodule S M, IsPr exact mem_range_self f x · intro x hx obtain ⟨y, hy⟩ := mem_range.1 hx - rw [← hy, ← comp_apply, h] + rw [← hy, ← mul_apply, h] + +@[deprecated (since := "2025-01-12")] alias isProj_iff_idempotent := isProj_iff_isIdempotentElem namespace IsProj diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index d426dd8bc4573..135c80df5e677 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -255,7 +255,10 @@ theorem isDedekindDomainInv_iff [Algebra A K] [IsFractionRing A K] : theorem FractionalIdeal.adjoinIntegral_eq_one_of_isUnit [Algebra A K] [IsFractionRing A K] (x : K) (hx : IsIntegral A x) (hI : IsUnit (adjoinIntegral A⁰ x hx)) : adjoinIntegral A⁰ x hx = 1 := by set I := adjoinIntegral A⁰ x hx - have mul_self : I * I = I := by apply coeToSubmodule_injective; simp [I] + have mul_self : IsIdempotentElem I := by + apply coeToSubmodule_injective + simp only [coe_mul, adjoinIntegral_coe, I] + rw [(Algebra.adjoin A {x}).isIdempotentElem_toSubmodule] convert congr_arg (· * I⁻¹) mul_self <;> simp only [(mul_inv_cancel_iff_isUnit K).mpr hI, mul_assoc, mul_one] From cb1615844a28658e9a8d2596d402f078f9471ebf Mon Sep 17 00:00:00 2001 From: Artie Khovanov Date: Tue, 21 Jan 2025 01:06:03 +0000 Subject: [PATCH 358/681] feat: tag `csInf_insert` and `csSup_insert` `@[simp]` (#20883) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the `@[simp]` attributes for complete and conditionally complete lattices consistent, so that `sSup {a,b,c,d,...}` is simplified to to `a ⊔ b ⊔ c ⊔ d ⊔ ...` in all cases (and similarly for `sInf`). --- Mathlib/Order/CompleteLattice.lean | 2 ++ Mathlib/Order/ConditionallyCompleteLattice/Basic.lean | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Mathlib/Order/CompleteLattice.lean b/Mathlib/Order/CompleteLattice.lean index e68234ef30fbb..6dfb80d1a72f2 100644 --- a/Mathlib/Order/CompleteLattice.lean +++ b/Mathlib/Order/CompleteLattice.lean @@ -113,6 +113,7 @@ theorem sSup_le_sSup_of_forall_exists_le (h : ∀ x ∈ s, ∃ y ∈ t, x ≤ y) hac.trans (hb hct) -- We will generalize this to conditionally complete lattices in `csSup_singleton`. +@[simp] theorem sSup_singleton {a : α} : sSup {a} = a := isLUB_singleton.sSup_eq @@ -168,6 +169,7 @@ theorem sInf_le_sInf_of_forall_exists_le (h : ∀ x ∈ s, ∃ y ∈ t, y ≤ x) le_sInf fun x hx ↦ let ⟨_y, hyt, hyx⟩ := h x hx; sInf_le_of_le hyt hyx -- We will generalize this to conditionally complete lattices in `csInf_singleton`. +@[simp] theorem sInf_singleton {a : α} : sInf {a} = a := isGLB_singleton.sInf_eq diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean index 0773cfe1e11e4..af8c5cbdf3a5f 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean @@ -317,11 +317,9 @@ theorem csSup_singleton (a : α) : sSup {a} = a := theorem csInf_singleton (a : α) : sInf {a} = a := isLeast_singleton.csInf_eq -@[simp] theorem csSup_pair (a b : α) : sSup {a, b} = a ⊔ b := (@isLUB_pair _ _ a b).csSup_eq (insert_nonempty _ _) -@[simp] theorem csInf_pair (a b : α) : sInf {a, b} = a ⊓ b := (@isGLB_pair _ _ a b).csInf_eq (insert_nonempty _ _) @@ -356,11 +354,13 @@ theorem le_csInf_inter : /-- The supremum of `insert a s` is the maximum of `a` and the supremum of `s`, if `s` is nonempty and bounded above. -/ +@[simp] theorem csSup_insert (hs : BddAbove s) (sne : s.Nonempty) : sSup (insert a s) = a ⊔ sSup s := ((isLUB_csSup sne hs).insert a).csSup_eq (insert_nonempty a s) /-- The infimum of `insert a s` is the minimum of `a` and the infimum of `s`, if `s` is nonempty and bounded below. -/ +@[simp] theorem csInf_insert (hs : BddBelow s) (sne : s.Nonempty) : sInf (insert a s) = a ⊓ sInf s := csSup_insert (α := αᵒᵈ) hs sne From 94352f5731958d23a0723af049665954516e2f5a Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Tue, 21 Jan 2025 01:50:03 +0000 Subject: [PATCH 359/681] =?UTF-8?q?feat:=20show=20`IsGreatest=20(spectrum?= =?UTF-8?q?=20=E2=84=9D=E2=89=A50=20a)=20=E2=80=96a=E2=80=96=E2=82=8A`=20f?= =?UTF-8?q?or=20`IsometricContinuousFunctionalCalculus`=20(#20882)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also contains other similar results, and uses it to prove `‖cfc f a‖₊ = f ‖a‖₊` for `0 ≤ a`, and monotone `f : ℝ≥0 → ℝ≥0`. --- .../Isometric.lean | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean index 080dd2282f617..4b2e6c01ec177 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean @@ -140,6 +140,26 @@ lemma nnnorm_cfc_lt_iff (f : 𝕜 → 𝕜) (a : A) {c : ℝ≥0} (hc : 0 < c) (ha : p a := by cfc_tac) : ‖cfc f a‖₊ < c ↔ ∀ x ∈ σ 𝕜 a, ‖f x‖₊ < c := norm_cfc_lt_iff f a hc +namespace IsometricContinuousFunctionalCalculus + +lemma isGreatest_norm_spectrum [Nontrivial A] (a : A) (ha : p a := by cfc_tac) : + IsGreatest ((‖·‖) '' spectrum 𝕜 a) ‖a‖ := by + simpa only [cfc_id 𝕜 a] using IsGreatest.norm_cfc (id : 𝕜 → 𝕜) a + +lemma norm_spectrum_le (a : A) ⦃x : 𝕜⦄ (hx : x ∈ σ 𝕜 a) (ha : p a := by cfc_tac) : + ‖x‖ ≤ ‖a‖ := by + simpa only [cfc_id 𝕜 a] using norm_apply_le_norm_cfc (id : 𝕜 → 𝕜) a hx + +lemma isGreatest_nnnorm_spectrum [Nontrivial A] (a : A) (ha : p a := by cfc_tac) : + IsGreatest ((‖·‖₊) '' spectrum 𝕜 a) ‖a‖₊ := by + simpa only [cfc_id 𝕜 a] using IsGreatest.nnnorm_cfc (id : 𝕜 → 𝕜) a + +lemma nnnorm_spectrum_le (a : A) ⦃x : 𝕜⦄ (hx : x ∈ σ 𝕜 a) (ha : p a := by cfc_tac) : + ‖x‖₊ ≤ ‖a‖₊ := by + simpa only [cfc_id 𝕜 a] using nnnorm_apply_le_nnnorm_cfc (id : 𝕜 → 𝕜) a hx + +end IsometricContinuousFunctionalCalculus + end NormedRing namespace SpectrumRestricts @@ -307,6 +327,26 @@ lemma nnnorm_cfcₙ_lt_iff (f : 𝕜 → 𝕜) (a : A) (c : ℝ≥0) (ha : p a := by cfc_tac) : ‖cfcₙ f a‖₊ < c ↔ ∀ x ∈ σₙ 𝕜 a, ‖f x‖₊ < c := norm_cfcₙ_lt_iff f a c.1 hf hf₀ ha +namespace NonUnitalIsometricContinuousFunctionalCalculus + +lemma isGreatest_norm_quasispectrum (a : A) (ha : p a := by cfc_tac) : + IsGreatest ((‖·‖) '' σₙ 𝕜 a) ‖a‖ := by + simpa only [cfcₙ_id 𝕜 a] using IsGreatest.norm_cfcₙ (id : 𝕜 → 𝕜) a + +lemma norm_quasispectrum_le (a : A) ⦃x : 𝕜⦄ (hx : x ∈ σₙ 𝕜 a) (ha : p a := by cfc_tac) : + ‖x‖ ≤ ‖a‖ := by + simpa only [cfcₙ_id 𝕜 a] using norm_apply_le_norm_cfcₙ (id : 𝕜 → 𝕜) a hx + +lemma isGreatest_nnnorm_quasispectrum (a : A) (ha : p a := by cfc_tac) : + IsGreatest ((‖·‖₊) '' σₙ 𝕜 a) ‖a‖₊ := by + simpa only [cfcₙ_id 𝕜 a] using IsGreatest.nnnorm_cfcₙ (id : 𝕜 → 𝕜) a + +lemma nnnorm_quasispectrum_le (a : A) ⦃x : 𝕜⦄ (hx : x ∈ σₙ 𝕜 a) (ha : p a := by cfc_tac) : + ‖x‖₊ ≤ ‖a‖₊ := by + simpa only [cfcₙ_id 𝕜 a] using nnnorm_apply_le_nnnorm_cfcₙ (id : 𝕜 → 𝕜) a hx + +end NonUnitalIsometricContinuousFunctionalCalculus + end NormedRing namespace QuasispectrumRestricts @@ -457,6 +497,24 @@ lemma nnnorm_cfc_nnreal_lt_iff (f : ℝ≥0 → ℝ≥0) (a : A) {c : ℝ≥0} ( (ha : 0 ≤ a := by cfc_tac) : ‖cfc f a‖₊ < c ↔ ∀ x ∈ σ ℝ≥0 a, f x < c := ⟨fun h _ hx ↦ apply_le_nnnorm_cfc_nnreal f a hx hf ha |>.trans_lt h, nnnorm_cfc_nnreal_lt hc⟩ +namespace IsometricContinuousFunctionalCalculus + +lemma isGreatest_spectrum [Nontrivial A] (a : A) (ha : 0 ≤ a := by cfc_tac) : + IsGreatest (σ ℝ≥0 a) ‖a‖₊ := by + simpa [cfc_id ℝ≥0 a] using IsGreatest.nnnorm_cfc_nnreal id a + +lemma spectrum_le (a : A) ⦃x : ℝ≥0⦄ (hx : x ∈ σ ℝ≥0 a) (ha : 0 ≤ a := by cfc_tac) : + x ≤ ‖a‖₊ := by + simpa [cfc_id ℝ≥0 a] using apply_le_nnnorm_cfc_nnreal id a hx + +end IsometricContinuousFunctionalCalculus + +open IsometricContinuousFunctionalCalculus in +lemma MonotoneOn.nnnorm_cfc [Nontrivial A] (f : ℝ≥0 → ℝ≥0) (a : A) + (hf : MonotoneOn f (σ ℝ≥0 a)) (hf₂ : ContinuousOn f (σ ℝ≥0 a) := by cfc_cont_tac) + (ha : 0 ≤ a := by cfc_tac) : ‖cfc f a‖₊ = f ‖a‖₊ := + IsGreatest.nnnorm_cfc_nnreal f a |>.unique <| hf.map_isGreatest (isGreatest_spectrum a) + end Unital section NonUnital @@ -511,6 +569,25 @@ lemma nnnorm_cfcₙ_nnreal_lt_iff (f : ℝ≥0 → ℝ≥0) (a : A) (c : ℝ≥0 (ha : 0 ≤ a := by cfc_tac) : ‖cfcₙ f a‖₊ < c ↔ ∀ x ∈ σₙ ℝ≥0 a, f x < c := ⟨fun h _ hx ↦ apply_le_nnnorm_cfcₙ_nnreal f a hx hf hf₀ ha |>.trans_lt h, nnnorm_cfcₙ_nnreal_lt⟩ +namespace NonUnitalIsometricContinuousFunctionalCalculus + +lemma isGreatest_quasispectrum (a : A) (ha : 0 ≤ a := by cfc_tac) : + IsGreatest (σₙ ℝ≥0 a) ‖a‖₊ := by + simpa [cfcₙ_id ℝ≥0 a] using IsGreatest.nnnorm_cfcₙ_nnreal id a + +lemma quasispectrum_le (a : A) ⦃x : ℝ≥0⦄ (hx : x ∈ σₙ ℝ≥0 a) (ha : 0 ≤ a := by cfc_tac) : + x ≤ ‖a‖₊ := by + simpa [cfcₙ_id ℝ≥0 a] using apply_le_nnnorm_cfcₙ_nnreal id a hx + +end NonUnitalIsometricContinuousFunctionalCalculus + +open NonUnitalIsometricContinuousFunctionalCalculus in +lemma MonotoneOn.nnnorm_cfcₙ (f : ℝ≥0 → ℝ≥0) (a : A) + (hf : MonotoneOn f (σₙ ℝ≥0 a)) (hf₂ : ContinuousOn f (σₙ ℝ≥0 a) := by cfc_cont_tac) + (hf0 : f 0 = 0 := by cfc_zero_tac) (ha : 0 ≤ a := by cfc_tac) : + ‖cfcₙ f a‖₊ = f ‖a‖₊ := + IsGreatest.nnnorm_cfcₙ_nnreal f a |>.unique <| hf.map_isGreatest (isGreatest_quasispectrum a) + end NonUnital end NNReal From 0885c9378bca78e447d9b4b1a1bbcc97792f244f Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 21 Jan 2025 01:50:04 +0000 Subject: [PATCH 360/681] fix: make `NNRatCast` computable for `NNReal` and `ENNReal` (#20884) This lets us write `0.5 : NNReal` and `0.5 : ENNReal` without issue; previously the former was noncomputable, and there was no instance for the latter. This also adds some mostly-useless `Repr` instances, which are useful for testing this. --- Mathlib/Data/ENNReal/Basic.lean | 15 ++++++++++++++- Mathlib/Data/NNReal/Defs.lean | 7 +++++++ Mathlib/Data/Real/Basic.lean | 3 ++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Mathlib/Data/ENNReal/Basic.lean b/Mathlib/Data/ENNReal/Basic.lean index 9ff94a4245b6a..c09ecafc6dfa1 100644 --- a/Mathlib/Data/ENNReal/Basic.lean +++ b/Mathlib/Data/ENNReal/Basic.lean @@ -94,7 +94,7 @@ variable {α : Type*} /-- The extended nonnegative real numbers. This is usually denoted [0, ∞], and is relevant as the codomain of a measure. -/ def ENNReal := WithTop ℝ≥0 - deriving Zero, AddCommMonoidWithOne, SemilatticeSup, DistribLattice, Nontrivial + deriving Zero, Top, AddCommMonoidWithOne, SemilatticeSup, DistribLattice, Nontrivial @[inherit_doc] scoped[ENNReal] notation "ℝ≥0∞" => ENNReal @@ -105,6 +105,7 @@ scoped[ENNReal] notation "∞" => (⊤ : ENNReal) namespace ENNReal instance : OrderBot ℝ≥0∞ := inferInstanceAs (OrderBot (WithTop ℝ≥0)) +instance : OrderTop ℝ≥0∞ := inferInstanceAs (OrderTop (WithTop ℝ≥0)) instance : BoundedOrder ℝ≥0∞ := inferInstanceAs (BoundedOrder (WithTop ℝ≥0)) instance : CharZero ℝ≥0∞ := inferInstanceAs (CharZero (WithTop ℝ≥0)) instance : Min ℝ≥0∞ := SemilatticeInf.toMin @@ -185,6 +186,12 @@ lemma coe_ne_coe : (p : ℝ≥0∞) ≠ q ↔ p ≠ q := coe_inj.not theorem range_coe' : range ofNNReal = Iio ∞ := WithTop.range_coe theorem range_coe : range ofNNReal = {∞}ᶜ := (isCompl_range_some_none ℝ≥0).symm.compl_eq.symm +instance : NNRatCast ℝ≥0∞ where + nnratCast r := ofNNReal r + +@[norm_cast] +theorem coe_nnratCast (q : ℚ≥0) : ↑(q : ℝ≥0) = (q : ℝ≥0∞) := rfl + /-- `toNNReal x` returns `x` if it is real, otherwise 0. -/ protected def toNNReal : ℝ≥0∞ → ℝ≥0 := WithTop.untop' 0 @@ -686,6 +693,12 @@ end OrdConnected end Set +/-- While not very useful, this instance uses the same representation as `Real.instRepr`. -/ +unsafe instance : Repr ℝ≥0∞ where + reprPrec + | (r : ℝ≥0), p => Repr.addAppParen f!"ENNReal.ofReal ({repr r.val})" p + | ∞, _ => "∞" + namespace Mathlib.Meta.Positivity open Lean Meta Qq diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index 61436b72dc932..631407d91cc1e 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -71,6 +71,9 @@ instance : Max ℝ≥0 := SemilatticeSup.toMax instance : Sub ℝ≥0 := Nonneg.sub instance : OrderedSub ℝ≥0 := Nonneg.orderedSub +-- a computable copy of `Nonneg.instNNRatCast` +instance : NNRatCast ℝ≥0 where nnratCast r := ⟨r, r.cast_nonneg⟩ + noncomputable instance : LinearOrderedSemifield ℝ≥0 := Nonneg.linearOrderedSemifield @@ -977,6 +980,10 @@ theorem Real.exists_lt_of_strictMono [h : Nontrivial Γ₀ˣ] {f : Γ₀ →*₀ end StrictMono +/-- While not very useful, this instance uses the same representation as `Real.instRepr`. -/ +unsafe instance : Repr ℝ≥0 where + reprPrec r _ := f!"({repr r.val}).toNNReal" + namespace Mathlib.Meta.Positivity open Lean Meta Qq Function diff --git a/Mathlib/Data/Real/Basic.lean b/Mathlib/Data/Real/Basic.lean index 65b39b8a38b14..efd505490dce2 100644 --- a/Mathlib/Data/Real/Basic.lean +++ b/Mathlib/Data/Real/Basic.lean @@ -543,7 +543,8 @@ noncomputable instance decidableEq (a b : ℝ) : Decidable (a = b) := by infer_i The representative chosen is the one passed in the VM to `Quot.mk`, so two cauchy sequences converging to the same number may be printed differently. -/ -unsafe instance : Repr ℝ where reprPrec r _ := "Real.ofCauchy " ++ repr r.cauchy +unsafe instance : Repr ℝ where + reprPrec r p := Repr.addAppParen ("Real.ofCauchy " ++ repr r.cauchy) p theorem le_mk_of_forall_le {f : CauSeq ℚ abs} : (∃ i, ∀ j ≥ i, x ≤ f j) → x ≤ mk f := by intro h From 6e13e01034ba8584e8148051b4e54473d2e3cfa4 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 21 Jan 2025 14:01:58 +1100 Subject: [PATCH 361/681] feat: `casesm` tactic reuses hypothesis name if only one new hypothesis (#20763) * feat: casesm tactic reuses hypothesis name if only one new hypothesis * doc-string * refactor * only if an fvar * golf --- Mathlib/Tactic/CasesM.lean | 23 ++++++++++++++++++----- MathlibTest/casesm.lean | 30 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Mathlib/Tactic/CasesM.lean b/Mathlib/Tactic/CasesM.lean index a1b012c5b4baf..190ae12430667 100644 --- a/Mathlib/Tactic/CasesM.lean +++ b/Mathlib/Tactic/CasesM.lean @@ -40,17 +40,21 @@ partial def casesMatching (matcher : Expr → MetaM Bool) (recursive := false) ( g.cases ldecl.fvarId else let s ← saveState - let subgoals ← g.cases ldecl.fvarId + let subgoals ← g.cases ldecl.fvarId (givenNames := #[⟨true, [ldecl.userName]⟩]) if subgoals.size > 1 then s.restore continue else pure subgoals for subgoal in subgoals do + -- If only one new hypothesis is generated, rename it to the original name. + let g ← match subgoal.fields with + | #[.fvar fvarId] => subgoal.mvarId.rename fvarId ldecl.userName + | _ => pure subgoal.mvarId if recursive then - acc ← go subgoal.mvarId acc + acc ← go g acc else - acc := acc.push subgoal.mvarId + acc := acc.push g return acc return (acc.push g) @@ -77,6 +81,11 @@ def matchPatterns (pats : Array AbstractMVarsResult) (e : Expr) : MetaM Bool := let e ← instantiateMVars e pats.anyM fun p ↦ return (← Conv.matchPattern? p e) matches some (_, #[]) +/-- Common implementation of `casesm` and `casesm!`. -/ +def elabCasesM (pats : Array Term) (recursive allowSplit : Bool) : TacticM Unit := do + let pats ← elabPatterns pats + liftMetaTactic (casesMatching (matchPatterns pats) recursive allowSplit) + /-- * `casesm p` applies the `cases` tactic to a hypothesis `h : type` if `type` matches the pattern `p`. @@ -84,6 +93,7 @@ def matchPatterns (pats : Array AbstractMVarsResult) (e : Expr) : MetaM Bool := if `type` matches one of the given patterns. * `casesm* p` is a more efficient and compact version of `· repeat casesm p`. It is more efficient because the pattern is compiled once. +* `casesm! p` only applies `cases` if the number of resulting subgoals is <= 1. Example: The following tactic destructs all conjunctions and disjunctions in the current context. ``` @@ -91,8 +101,11 @@ casesm* _ ∨ _, _ ∧ _ ``` -/ elab (name := casesM) "casesm" recursive:"*"? ppSpace pats:term,+ : tactic => do - let pats ← elabPatterns pats.getElems - liftMetaTactic (casesMatching (matchPatterns pats) recursive.isSome) + elabCasesM pats recursive.isSome true + +@[inherit_doc casesM] +elab (name := casesm!) "casesm!" recursive:"*"? ppSpace pats:term,+ : tactic => do + elabCasesM pats recursive.isSome false /-- Common implementation of `cases_type` and `cases_type!`. -/ def elabCasesType (heads : Array Ident) diff --git a/MathlibTest/casesm.lean b/MathlibTest/casesm.lean index 2a765ce9e8e7b..d8d1862d4560f 100644 --- a/MathlibTest/casesm.lean +++ b/MathlibTest/casesm.lean @@ -81,6 +81,36 @@ example : True ∧ True ∧ True := by · guard_target = True; constructorm True · guard_target = True ∧ True; constructorm* True, _∧_ +example (n : Nat) : True := by + fail_if_success casesm! Nat -- two constructors, so `casesm!` doesn't fire + trivial + +example (h : Array Nat) : True := by + casesm! Array _ + trivial + +example (h : Array Nat) : True := by + casesm Array _ + -- user facing name is preserved: + guard_hyp h : List Nat + trivial + +example (n : Nat) (h : n = 0) : True := by + casesm Nat + · trivial + · -- user facing name is preserved: + guard_hyp h : n + 1 = 0 + trivial + +example (h : P ∧ Q) : True := by + casesm _ ∧ _ + -- user facing name is not used here, because there are multiple new hypotheses. + fail_if_success guard_hyp h : P + rename_i p q + guard_hyp p : P + guard_hyp q : Q + trivial + section AuxDecl variable {p q r : Prop} variable (h : p ∧ q ∨ p ∧ r) From af1c22a08783df087548b7602b99a437d393c594 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 21 Jan 2025 03:27:02 +0000 Subject: [PATCH 362/681] chore: remove porting notes about the nonempty instance linter (#20824) [Zulip thread](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/nonempty.20instance.20linter.20.235171) --- Mathlib/Algebra/Algebra/Defs.lean | 1 - Mathlib/Algebra/Algebra/Hom.lean | 1 - Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean | 1 - Mathlib/Algebra/Homology/Homotopy.lean | 1 - Mathlib/Algebra/Module/LocalizedModule/Basic.lean | 1 - Mathlib/Algebra/Star/CHSH.lean | 1 - Mathlib/AlgebraicGeometry/AffineScheme.lean | 2 -- Mathlib/AlgebraicGeometry/Gluing.lean | 1 - Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean | 1 - Mathlib/AlgebraicTopology/DoldKan/Decomposition.lean | 1 - Mathlib/AlgebraicTopology/SimplexCategory.lean | 1 - Mathlib/AlgebraicTopology/SimplicialObject/Basic.lean | 6 ------ Mathlib/AlgebraicTopology/SimplicialObject/Split.lean | 3 --- Mathlib/Analysis/Calculus/BumpFunction/Basic.lean | 1 - Mathlib/Analysis/Calculus/Implicit.lean | 1 - Mathlib/CategoryTheory/Adjunction/Basic.lean | 4 ---- Mathlib/CategoryTheory/Bicategory/Free.lean | 2 -- Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean | 2 -- Mathlib/CategoryTheory/Category/PartialFun.lean | 1 - Mathlib/CategoryTheory/CommSq.lean | 1 - Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean | 3 --- Mathlib/CategoryTheory/Core.lean | 3 --- Mathlib/CategoryTheory/DifferentialObject.lean | 3 +-- Mathlib/CategoryTheory/Enriched/Basic.lean | 2 -- Mathlib/CategoryTheory/EpiMono.lean | 2 -- Mathlib/CategoryTheory/EssentiallySmall.lean | 2 -- Mathlib/CategoryTheory/FullSubcategory.lean | 1 - Mathlib/CategoryTheory/GlueData.lean | 2 -- Mathlib/CategoryTheory/Grothendieck.lean | 2 -- Mathlib/CategoryTheory/Idempotents/Karoubi.lean | 1 - Mathlib/CategoryTheory/Limits/ExactFunctor.lean | 3 --- Mathlib/CategoryTheory/Limits/HasLimits.lean | 2 -- Mathlib/CategoryTheory/Limits/IsLimit.lean | 2 -- Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean | 6 ------ Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean | 6 ------ Mathlib/CategoryTheory/Limits/Shapes/Types.lean | 1 - Mathlib/CategoryTheory/Limits/Types.lean | 1 - Mathlib/CategoryTheory/Localization/Construction.lean | 2 -- Mathlib/CategoryTheory/Monad/Algebra.lean | 4 ---- Mathlib/CategoryTheory/Monoidal/Center.lean | 5 +---- Mathlib/CategoryTheory/Monoidal/Free/Basic.lean | 2 -- Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean | 1 - .../Monoidal/OfChosenFiniteProducts/Basic.lean | 2 -- Mathlib/CategoryTheory/Monoidal/Opposite.lean | 1 - Mathlib/CategoryTheory/MorphismProperty/IsInvertedBy.lean | 1 - Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean | 1 - Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean | 2 -- Mathlib/CategoryTheory/Preadditive/Mat.lean | 1 - Mathlib/CategoryTheory/Preadditive/Projective.lean | 1 - .../CategoryTheory/Preadditive/ProjectiveResolution.lean | 1 - Mathlib/CategoryTheory/Shift/Basic.lean | 1 - Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean | 1 - Mathlib/CategoryTheory/Sites/CoverLifting.lean | 1 - Mathlib/CategoryTheory/Sites/CoverPreserving.lean | 2 -- Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean | 1 - Mathlib/CategoryTheory/Sites/Grothendieck.lean | 4 ---- Mathlib/CategoryTheory/Widesubcategory.lean | 1 - Mathlib/CategoryTheory/WithTerminal.lean | 2 -- Mathlib/Combinatorics/Quiver/Basic.lean | 2 -- Mathlib/Combinatorics/Quiver/Subquiver.lean | 1 - Mathlib/Combinatorics/Quiver/Symmetric.lean | 1 - Mathlib/Data/PFunctor/Multivariate/W.lean | 1 - Mathlib/Data/PFunctor/Univariate/Basic.lean | 2 -- Mathlib/Data/QPF/Univariate/Basic.lean | 2 -- Mathlib/Dynamics/Ergodic/Ergodic.lean | 2 -- Mathlib/Geometry/Manifold/ChartedSpace.lean | 4 ---- Mathlib/Geometry/Manifold/Diffeomorph.lean | 1 - Mathlib/Geometry/Manifold/IsManifold.lean | 3 +-- Mathlib/Geometry/Manifold/PartitionOfUnity.lean | 1 - Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean | 6 ------ Mathlib/GroupTheory/CoprodI.lean | 1 - Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean | 1 - Mathlib/GroupTheory/GroupAction/Hom.lean | 4 ---- Mathlib/GroupTheory/MonoidLocalization/Basic.lean | 4 ---- Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean | 2 -- Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean | 2 -- Mathlib/LinearAlgebra/Dual.lean | 1 - Mathlib/LinearAlgebra/FreeModule/PID.lean | 1 - Mathlib/LinearAlgebra/Matrix/Transvection.lean | 1 - Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean | 1 - Mathlib/LinearAlgebra/Ray.lean | 2 -- Mathlib/Logic/Embedding/Basic.lean | 2 -- Mathlib/MeasureTheory/Covering/VitaliFamily.lean | 2 -- Mathlib/MeasureTheory/Measure/Typeclasses.lean | 2 -- Mathlib/ModelTheory/Basic.lean | 4 ---- Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean | 3 --- Mathlib/Order/PrimeIdeal.lean | 2 -- Mathlib/RingTheory/DedekindDomain/Ideal.lean | 1 - .../RingTheory/GradedAlgebra/HomogeneousLocalization.lean | 4 ---- Mathlib/RingTheory/IsAdjoinRoot.lean | 2 -- Mathlib/RingTheory/Perfection.lean | 5 +---- Mathlib/RingTheory/PowerBasis.lean | 2 -- Mathlib/RingTheory/Valuation/Basic.lean | 2 -- Mathlib/RingTheory/WittVector/Isocrystal.lean | 3 --- Mathlib/Topology/Algebra/Module/Equiv.lean | 1 - Mathlib/Topology/Connected/PathConnected.lean | 1 - Mathlib/Topology/FiberBundle/Basic.lean | 6 ++---- Mathlib/Topology/FiberBundle/Trivialization.lean | 1 - Mathlib/Topology/Gluing.lean | 2 -- Mathlib/Topology/MetricSpace/GromovHausdorff.lean | 1 - Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean | 1 - Mathlib/Topology/MetricSpace/Isometry.lean | 1 - Mathlib/Topology/MetricSpace/Polish.lean | 1 - Mathlib/Topology/PartialHomeomorph.lean | 1 - Mathlib/Topology/Sheaves/Presheaf.lean | 1 - Mathlib/Topology/ShrinkingLemma.lean | 1 - Mathlib/Topology/UniformSpace/Equiv.lean | 1 - Mathlib/Topology/VectorBundle/Basic.lean | 5 ++--- 108 files changed, 8 insertions(+), 208 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Defs.lean b/Mathlib/Algebra/Algebra/Defs.lean index 8f9470e1325d7..7b3f54fdd852d 100644 --- a/Mathlib/Algebra/Algebra/Defs.lean +++ b/Mathlib/Algebra/Algebra/Defs.lean @@ -95,7 +95,6 @@ section Prio See the implementation notes in this file for discussion of the details of this definition. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): unsupported @[nolint has_nonempty_instance] class Algebra (R : Type u) (A : Type v) [CommSemiring R] [Semiring A] extends SMul R A where /-- Embedding `R →+* A` given by `Algebra` structure. Use `algebraMap` from the root namespace instead.-/ diff --git a/Mathlib/Algebra/Algebra/Hom.lean b/Mathlib/Algebra/Algebra/Hom.lean index b813755c63742..31ac6c747b73f 100644 --- a/Mathlib/Algebra/Algebra/Hom.lean +++ b/Mathlib/Algebra/Algebra/Hom.lean @@ -23,7 +23,6 @@ This file defines bundled homomorphisms of `R`-algebras. universe u v w u₁ v₁ /-- Defining the homomorphism in the category R-Alg. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet structure AlgHom (R : Type u) (A : Type v) (B : Type w) [CommSemiring R] [Semiring A] [Semiring B] [Algebra R A] [Algebra R B] extends RingHom A B where commutes' : ∀ r : R, toFun (algebraMap R A r) = algebraMap R B r diff --git a/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean b/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean index dbbc854bbc197..d7640873b9f08 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Adjunctions.lean @@ -212,7 +212,6 @@ universe v u we will equip with a category structure where the morphisms are formal `R`-linear combinations of the morphisms in `C`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/pull/5171): Removed has_nonempty_instance nolint; linter not ported yet @[nolint unusedArguments] def Free (_ : Type*) (C : Type u) := C diff --git a/Mathlib/Algebra/Homology/Homotopy.lean b/Mathlib/Algebra/Homology/Homotopy.lean index 2749531ddb90a..bb13f21e29877 100644 --- a/Mathlib/Algebra/Homology/Homotopy.lean +++ b/Mathlib/Algebra/Homology/Homotopy.lean @@ -112,7 +112,6 @@ theorem prevD_nat (C D : CochainComplex V ℕ) (i : ℕ) (f : ∀ i j, C.X i ⟶ not_false_iff, comp_zero, reduceCtorEq] · congr <;> simp --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[has_nonempty_instance] /-- A homotopy `h` between chain maps `f` and `g` consists of components `h i j : C.X i ⟶ D.X j` which are zero unless `c.Rel j i`, satisfying the homotopy condition. -/ diff --git a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean index b806dbdd9c38e..4a3b1f34b2439 100644 --- a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean +++ b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean @@ -72,7 +72,6 @@ example {R} [CommSemiring R] (S : Submonoid R) : ⇑(Localization.r' S) = Locali /-- If `S` is a multiplicative subset of a ring `R` and `M` an `R`-module, then we can localize `M` by `S`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): @[nolint has_nonempty_instance] def _root_.LocalizedModule : Type max u v := Quotient (r.setoid S M) diff --git a/Mathlib/Algebra/Star/CHSH.lean b/Mathlib/Algebra/Star/CHSH.lean index 6b716f7e73fde..45bf5a0c7bc8e 100644 --- a/Mathlib/Algebra/Star/CHSH.lean +++ b/Mathlib/Algebra/Star/CHSH.lean @@ -82,7 +82,6 @@ the `Aᵢ` commute with the `Bⱼ`. The physical interpretation is that `A₀` and `A₁` are a pair of boolean observables which are spacelike separated from another pair `B₀` and `B₁` of boolean observables. -/ ---@[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet structure IsCHSHTuple {R} [Monoid R] [StarMul R] (A₀ A₁ B₀ B₁ : R) : Prop where A₀_inv : A₀ ^ 2 = 1 A₁_inv : A₁ ^ 2 = 1 diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index a2a2716bb20af..3dda7880479b0 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -46,8 +46,6 @@ namespace AlgebraicGeometry open Spec (structureSheaf) /-- The category of affine schemes -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] def AffineScheme := Scheme.Spec.EssImageSubcategory deriving Category diff --git a/Mathlib/AlgebraicGeometry/Gluing.lean b/Mathlib/AlgebraicGeometry/Gluing.lean index b97e3bf450dcf..bcdfd0adfd772 100644 --- a/Mathlib/AlgebraicGeometry/Gluing.lean +++ b/Mathlib/AlgebraicGeometry/Gluing.lean @@ -79,7 +79,6 @@ such that We can then glue the schemes `U i` together by identifying `V i j` with `V j i`, such that the `U i`'s are open subschemes of the glued space. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): @[nolint has_nonempty_instance]; linter not ported yet structure GlueData extends CategoryTheory.GlueData Scheme where f_open : ∀ i j, IsOpenImmersion (f i j) diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean index b9a5bdf4d9ecb..55c14d9043da3 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean @@ -44,7 +44,6 @@ variable {R A : Type*} variable [CommSemiring R] [CommRing A] [Algebra R A] variable (𝒜 : ℕ → Submodule R A) [GradedAlgebra 𝒜] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The projective spectrum of a graded commutative ring is the subtype of all homogeneous ideals that are prime and do not contain the irrelevant ideal. -/ @[ext] diff --git a/Mathlib/AlgebraicTopology/DoldKan/Decomposition.lean b/Mathlib/AlgebraicTopology/DoldKan/Decomposition.lean index d1b827f3f5c7c..8e789299821c5 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Decomposition.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Decomposition.lean @@ -80,7 +80,6 @@ theorem decomposition_Q (n q : ℕ) : variable (X) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The structure `MorphComponents` is an ad hoc structure that is used in the proof that `N₁ : SimplicialObject C ⥤ Karoubi (ChainComplex C ℕ))` reflects isomorphisms. The fields are the data that are needed in order to diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index fc1308dc19570..7002837fe5f37 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -82,7 +82,6 @@ theorem mk_len (n : SimplexCategory) : ([n.len] : SimplexCategory) = n := protected def rec {F : SimplexCategory → Sort*} (h : ∀ n : ℕ, F [n]) : ∀ X, F X := fun n => h n.len --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Morphisms in the `SimplexCategory`. -/ protected def Hom (a b : SimplexCategory) := Fin (a.len + 1) →o Fin (b.len + 1) diff --git a/Mathlib/AlgebraicTopology/SimplicialObject/Basic.lean b/Mathlib/AlgebraicTopology/SimplicialObject/Basic.lean index ae05211a3fe1e..4e4e34909f442 100644 --- a/Mathlib/AlgebraicTopology/SimplicialObject/Basic.lean +++ b/Mathlib/AlgebraicTopology/SimplicialObject/Basic.lean @@ -33,7 +33,6 @@ namespace CategoryTheory variable (C : Type u) [Category.{v} C] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The category of simplicial objects valued in a category `C`. This is the category of contravariant functors from `SimplexCategory` to `C`. -/ def SimplicialObject := @@ -206,7 +205,6 @@ variable (C) def whiskering (D : Type*) [Category D] : (C ⥤ D) ⥤ SimplicialObject C ⥤ SimplicialObject D := whiskeringRight _ _ _ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Truncated simplicial objects. -/ def Truncated (n : ℕ) := (SimplexCategory.Truncated n)ᵒᵖ ⥤ C @@ -360,7 +358,6 @@ variable (C) abbrev const : C ⥤ SimplicialObject C := CategoryTheory.Functor.const _ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The category of augmented simplicial objects, defined as a comma category. -/ def Augmented := Comma (𝟭 (SimplicialObject C)) (const C) @@ -472,7 +469,6 @@ theorem augment_hom_zero (X : SimplicialObject C) (X₀ : C) (f : X _[0] ⟶ X end SimplicialObject --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Cosimplicial objects. -/ def CosimplicialObject := SimplexCategory ⥤ C @@ -640,7 +636,6 @@ variable (C) def whiskering (D : Type*) [Category D] : (C ⥤ D) ⥤ CosimplicialObject C ⥤ CosimplicialObject D := whiskeringRight _ _ _ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Truncated cosimplicial objects. -/ def Truncated (n : ℕ) := SimplexCategory.Truncated n ⥤ C @@ -694,7 +689,6 @@ variable (C) abbrev const : C ⥤ CosimplicialObject C := CategoryTheory.Functor.const _ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Augmented cosimplicial objects. -/ def Augmented := Comma (const C) (𝟭 (CosimplicialObject C)) diff --git a/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean b/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean index 7e6de96ffecde..9061d57109b29 100644 --- a/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean +++ b/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean @@ -198,7 +198,6 @@ def cofan' (Δ : SimplexCategoryᵒᵖ) : Cofan (summand N Δ) := end Splitting ---Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- A splitting of a simplicial object `X` consists of the datum of a sequence of objects `N`, a sequence of morphisms `ι : N n ⟶ X _[n]` such that for all `Δ : SimplexCategoryᵒᵖ`, the canonical map `Splitting.map X ι Δ` @@ -287,7 +286,6 @@ end Splitting variable (C) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The category `SimplicialObject.Split C` is the category of simplicial objects in `C` equipped with a splitting, and morphisms are morphisms of simplicial objects which are compatible with the splittings. -/ @@ -308,7 +306,6 @@ of a simplicial object `X`. -/ def mk' {X : SimplicialObject C} (s : Splitting X) : Split C := ⟨X, s⟩ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Morphisms in `SimplicialObject.Split C` are morphisms of simplicial objects that are compatible with the splittings. -/ structure Hom (S₁ S₂ : Split C) where diff --git a/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean b/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean index 922effc6f97d8..2f7721e6ffc3c 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean @@ -74,7 +74,6 @@ add more properties if they are useful and satisfied in the examples of inner pr and finite dimensional vector spaces, notably derivative norm control in terms of `R - 1`. TODO: do we ever need `f x = 1 ↔ ‖x‖ ≤ 1`? -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not yet ported; was @[nolint has_nonempty_instance] structure ContDiffBumpBase (E : Type*) [NormedAddCommGroup E] [NormedSpace ℝ E] where /-- The function underlying this family of bump functions -/ toFun : ℝ → E → ℝ diff --git a/Mathlib/Analysis/Calculus/Implicit.lean b/Mathlib/Analysis/Calculus/Implicit.lean index d3b9846464c99..0fafd1d4cd140 100644 --- a/Mathlib/Analysis/Calculus/Implicit.lean +++ b/Mathlib/Analysis/Calculus/Implicit.lean @@ -94,7 +94,6 @@ needs to have a complete control over the choice of the implicit function. * both functions are strictly differentiable at `a`; * the derivatives are surjective; * the kernels of the derivatives are complementary subspaces of `E`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not yet ported @[nolint has_nonempty_instance] structure ImplicitFunctionData (𝕜 : Type*) [NontriviallyNormedField 𝕜] (E : Type*) [NormedAddCommGroup E] [NormedSpace 𝕜 E] [CompleteSpace E] (F : Type*) [NormedAddCommGroup F] [NormedSpace 𝕜 F] [CompleteSpace F] (G : Type*) [NormedAddCommGroup G] [NormedSpace 𝕜 G] diff --git a/Mathlib/CategoryTheory/Adjunction/Basic.lean b/Mathlib/CategoryTheory/Adjunction/Basic.lean index 6c4183721f9f5..e821bebd0ae15 100644 --- a/Mathlib/CategoryTheory/Adjunction/Basic.lean +++ b/Mathlib/CategoryTheory/Adjunction/Basic.lean @@ -328,8 +328,6 @@ structure CoreHomEquivUnitCounit (F : C ⥤ D) (G : D ⥤ C) where See `Adjunction.mkOfHomEquiv`. This structure won't typically be used anywhere else. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): `has_nonempty_instance` linter not ported yet --- @[nolint has_nonempty_instance] structure CoreHomEquiv (F : C ⥤ D) (G : D ⥤ C) where /-- The equivalence between `Hom (F X) Y` and `Hom X (G Y)` -/ homEquiv : ∀ X Y, (F.obj X ⟶ Y) ≃ (X ⟶ G.obj Y) @@ -364,8 +362,6 @@ end CoreHomEquiv See `Adjunction.mkOfUnitCounit`. This structure won't typically be used anywhere else. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): `has_nonempty_instance` linter not ported yet --- @[nolint has_nonempty_instance] structure CoreUnitCounit (F : C ⥤ D) (G : D ⥤ C) where /-- The unit of an adjunction between `F` and `G` -/ unit : 𝟭 C ⟶ F.comp G diff --git a/Mathlib/CategoryTheory/Bicategory/Free.lean b/Mathlib/CategoryTheory/Bicategory/Free.lean index 08cee6ecf1d42..4029841250cc9 100644 --- a/Mathlib/CategoryTheory/Bicategory/Free.lean +++ b/Mathlib/CategoryTheory/Bicategory/Free.lean @@ -60,8 +60,6 @@ instance categoryStruct : CategoryStruct.{max u v} (FreeBicategory B) where comp := @fun _ _ _ => Hom.comp /-- Representatives of 2-morphisms in the free bicategory. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] inductive Hom₂ : ∀ {a b : FreeBicategory B}, (a ⟶ b) → (a ⟶ b) → Type max u v | id {a b} (f : a ⟶ b) : Hom₂ f f | vcomp {a b} {f g h : a ⟶ b} (η : Hom₂ f g) (θ : Hom₂ g h) : Hom₂ f h diff --git a/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean b/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean index b80c8b92adcd7..e96f46366f895 100644 --- a/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean +++ b/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean @@ -154,8 +154,6 @@ def comp (F : OplaxFunctor B C) (G : OplaxFunctor C D) : OplaxFunctor B D where /-- A structure on an oplax functor that promotes an oplax functor to a pseudofunctor. See `Pseudofunctor.mkOfOplax`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] structure PseudoCore (F : OplaxFunctor B C) where /-- The isomorphism giving rise to the oplax unity constraint -/ mapIdIso (a : B) : F.map (𝟙 a) ≅ 𝟙 (F.obj a) diff --git a/Mathlib/CategoryTheory/Category/PartialFun.lean b/Mathlib/CategoryTheory/Category/PartialFun.lean index 6daedc19bcadb..c5d65f076306a 100644 --- a/Mathlib/CategoryTheory/Category/PartialFun.lean +++ b/Mathlib/CategoryTheory/Category/PartialFun.lean @@ -39,7 +39,6 @@ namespace PartialFun instance : CoeSort PartialFun Type* := ⟨id⟩ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]`; linter not ported yet /-- Turns a type into a `PartialFun`. -/ def of : Type* → PartialFun := id diff --git a/Mathlib/CategoryTheory/CommSq.lean b/Mathlib/CategoryTheory/CommSq.lean index 3d76ea7106835..22ac6660feea9 100644 --- a/Mathlib/CategoryTheory/CommSq.lean +++ b/Mathlib/CategoryTheory/CommSq.lean @@ -153,7 +153,6 @@ variable {A B X Y : C} {f : A ⟶ X} {i : A ⟶ B} {p : X ⟶ Y} {g : B ⟶ Y} The datum of a lift in a commutative square, i.e. an up-right-diagonal morphism which makes both triangles commute. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] @[ext] structure LiftStruct (sq : CommSq f i p g) where /-- The lift. -/ diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean index 4f4687b1fb578..b68e5a370f281 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean @@ -32,8 +32,6 @@ and morphisms `C`-morphisms `Y ⟶ Y'` making the obvious triangle commute. -/ -- We explicitly come from `PUnit.{1}` here to obtain the correct universe for morphisms of -- structured arrows. --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] def StructuredArrow (S : D) (T : C ⥤ D) := Comma (Functor.fromPUnit.{0} S) T @@ -398,7 +396,6 @@ and morphisms `C`-morphisms `Y ⟶ Y'` making the obvious triangle commute. -/ -- We explicitly come from `PUnit.{1}` here to obtain the correct universe for morphisms of -- costructured arrows. --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet def CostructuredArrow (S : C ⥤ D) (T : D) := Comma S (Functor.fromPUnit.{0} T) diff --git a/Mathlib/CategoryTheory/Core.lean b/Mathlib/CategoryTheory/Core.lean index be75572d3d4ab..5eeb69325f060 100644 --- a/Mathlib/CategoryTheory/Core.lean +++ b/Mathlib/CategoryTheory/Core.lean @@ -28,9 +28,6 @@ universe v₁ v₂ u₁ u₂ -- morphism levels before object levels. See note [CategoryTheory universes]. /-- The core of a category C is the groupoid whose morphisms are all the isomorphisms of C. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not yet ported --- @[nolint has_nonempty_instance] - def Core (C : Type u₁) := C variable {C : Type u₁} [Category.{v₁} C] diff --git a/Mathlib/CategoryTheory/DifferentialObject.lean b/Mathlib/CategoryTheory/DifferentialObject.lean index 067ddda0ea0c1..863323c9203e5 100644 --- a/Mathlib/CategoryTheory/DifferentialObject.lean +++ b/Mathlib/CategoryTheory/DifferentialObject.lean @@ -33,7 +33,6 @@ variable [HasZeroMorphisms C] [HasShift C S] /-- A differential object in a category with zero morphisms and a shift is an object `obj` equipped with a morphism `d : obj ⟶ obj⟦1⟧`, such that `d^2 = 0`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]` structure DifferentialObject where /-- The underlying object of a differential object. -/ obj : C @@ -49,7 +48,7 @@ variable {S C} namespace DifferentialObject /-- A morphism of differential objects is a morphism commuting with the differentials. -/ -@[ext] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `nolint has_nonempty_instance` +@[ext] structure Hom (X Y : DifferentialObject S C) where /-- The morphism between underlying objects of the two differentiable objects. -/ f : X.obj ⟶ Y.obj diff --git a/Mathlib/CategoryTheory/Enriched/Basic.lean b/Mathlib/CategoryTheory/Enriched/Basic.lean index 0654c73c33d3c..41a5c83cc50e2 100644 --- a/Mathlib/CategoryTheory/Enriched/Basic.lean +++ b/Mathlib/CategoryTheory/Enriched/Basic.lean @@ -169,7 +169,6 @@ section variable {W : Type v} [Category.{w} W] [MonoidalCategory W] [EnrichedCategory W C] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]` /-- A type synonym for `C`, which should come equipped with a `V`-enriched category structure. In a moment we will equip this with the (honest) category structure so that `X ⟶ Y` is `(𝟙_ W) ⟶ (X ⟶[W] Y)`. @@ -380,7 +379,6 @@ coming from the ambient braiding on `V`.) -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]` /-- The type of `A`-graded natural transformations between `V`-functors `F` and `G`. This is the type of morphisms in `V` from `A` to the `V`-object of natural transformations. -/ diff --git a/Mathlib/CategoryTheory/EpiMono.lean b/Mathlib/CategoryTheory/EpiMono.lean index a30f9c2501b46..590fa61289cdb 100644 --- a/Mathlib/CategoryTheory/EpiMono.lean +++ b/Mathlib/CategoryTheory/EpiMono.lean @@ -37,7 +37,6 @@ such that `f ≫ retraction f = 𝟙 X`. Every split monomorphism is a monomorphism. -/ -/- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] -/ @[ext, aesop apply safe (rule_sets := [CategoryTheory])] structure SplitMono {X Y : C} (f : X ⟶ Y) where /-- The map splitting `f` -/ @@ -68,7 +67,6 @@ such that `section_ f ≫ f = 𝟙 Y`. Every split epimorphism is an epimorphism. -/ -/- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] -/ @[ext, aesop apply safe (rule_sets := [CategoryTheory])] structure SplitEpi {X Y : C} (f : X ⟶ Y) where /-- The map splitting `f` -/ diff --git a/Mathlib/CategoryTheory/EssentiallySmall.lean b/Mathlib/CategoryTheory/EssentiallySmall.lean index febf03357f7fd..7e6ec94a768c1 100644 --- a/Mathlib/CategoryTheory/EssentiallySmall.lean +++ b/Mathlib/CategoryTheory/EssentiallySmall.lean @@ -44,7 +44,6 @@ theorem EssentiallySmall.mk' {C : Type u} [Category.{v} C] {S : Type w} [SmallCa /-- An arbitrarily chosen small model for an essentially small category. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171) removed @[nolint has_nonempty_instance] @[pp_with_univ] def SmallModel (C : Type u) [Category.{v} C] [EssentiallySmall.{w} C] : Type w := Classical.choose (@EssentiallySmall.equiv_smallCategory C _ _) @@ -118,7 +117,6 @@ instance (priority := 100) locallySmall_of_essentiallySmall (C : Type u) [Catego /-- We define a type alias `ShrinkHoms C` for `C`. When we have `LocallySmall.{w} C`, we'll put a `Category.{w}` instance on `ShrinkHoms C`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] @[pp_with_univ] def ShrinkHoms (C : Type u) := C diff --git a/Mathlib/CategoryTheory/FullSubcategory.lean b/Mathlib/CategoryTheory/FullSubcategory.lean index 7e3a337eddf7e..086610388e7d0 100644 --- a/Mathlib/CategoryTheory/FullSubcategory.lean +++ b/Mathlib/CategoryTheory/FullSubcategory.lean @@ -47,7 +47,6 @@ variable (F : C → D) which provides a category structure so that the morphisms `X ⟶ Y` are the morphisms in `D` from `F X` to `F Y`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] @[nolint unusedArguments] def InducedCategory (_F : C → D) : Type u₁ := C diff --git a/Mathlib/CategoryTheory/GlueData.lean b/Mathlib/CategoryTheory/GlueData.lean index fcea852442c19..7ce222e6e0218 100644 --- a/Mathlib/CategoryTheory/GlueData.lean +++ b/Mathlib/CategoryTheory/GlueData.lean @@ -43,8 +43,6 @@ such that `t' : V i j ×[U i] V i k ⟶ V j k ×[U j] V j i`. 10. `t' i j k ≫ t' j k i ≫ t' k i j = 𝟙 _`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] structure GlueData where J : Type v U : J → C diff --git a/Mathlib/CategoryTheory/Grothendieck.lean b/Mathlib/CategoryTheory/Grothendieck.lean index c987c94e3af65..799069e98d5d9 100644 --- a/Mathlib/CategoryTheory/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Grothendieck.lean @@ -54,8 +54,6 @@ gives a category whose `base : X.base ⟶ Y.base` and `f.fiber : (F.map base).obj X.fiber ⟶ Y.fiber` -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): no such linter yet --- @[nolint has_nonempty_instance] structure Grothendieck where /-- The underlying object in `C` -/ base : C diff --git a/Mathlib/CategoryTheory/Idempotents/Karoubi.lean b/Mathlib/CategoryTheory/Idempotents/Karoubi.lean index aa8ebd6d96a7d..f022f13162297 100644 --- a/Mathlib/CategoryTheory/Idempotents/Karoubi.lean +++ b/Mathlib/CategoryTheory/Idempotents/Karoubi.lean @@ -31,7 +31,6 @@ variable (C : Type*) [Category C] namespace Idempotents --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- In a preadditive category `C`, when an object `X` decomposes as `X ≅ P ⨿ Q`, one may consider `P` as a direct factor of `X` and up to unique isomorphism, it is determined by the obvious idempotent `X ⟶ P ⟶ X` which is the projection onto `P` with kernel `Q`. More generally, diff --git a/Mathlib/CategoryTheory/Limits/ExactFunctor.lean b/Mathlib/CategoryTheory/Limits/ExactFunctor.lean index 811252d88fc96..c39bc0d0cfc33 100644 --- a/Mathlib/CategoryTheory/Limits/ExactFunctor.lean +++ b/Mathlib/CategoryTheory/Limits/ExactFunctor.lean @@ -28,7 +28,6 @@ section variable (C) (D) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Bundled left-exact functors. -/ def LeftExactFunctor := FullSubcategory fun F : C ⥤ D => PreservesFiniteLimits F @@ -49,7 +48,6 @@ instance : (LeftExactFunctor.forget C D).Full := instance : (LeftExactFunctor.forget C D).Faithful := FullSubcategory.faithful _ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Bundled right-exact functors. -/ def RightExactFunctor := FullSubcategory fun F : C ⥤ D => PreservesFiniteColimits F @@ -70,7 +68,6 @@ instance : (RightExactFunctor.forget C D).Full := instance : (RightExactFunctor.forget C D).Faithful := FullSubcategory.faithful _ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Bundled exact functors. -/ def ExactFunctor := FullSubcategory fun F : C ⥤ D => diff --git a/Mathlib/CategoryTheory/Limits/HasLimits.lean b/Mathlib/CategoryTheory/Limits/HasLimits.lean index 8ebca957d879b..f5172396cb6f6 100644 --- a/Mathlib/CategoryTheory/Limits/HasLimits.lean +++ b/Mathlib/CategoryTheory/Limits/HasLimits.lean @@ -71,7 +71,6 @@ variable {F : J ⥤ C} section Limit /-- `LimitCone F` contains a cone over `F` together with the information that it is a limit. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed; linter not ported yet structure LimitCone (F : J ⥤ C) where /-- The cone itself -/ cone : Cone F @@ -583,7 +582,6 @@ section Colimit /-- `ColimitCocone F` contains a cocone over `F` together with the information that it is a colimit. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed; linter not ported yet structure ColimitCocone (F : J ⥤ C) where /-- The cocone itself -/ cocone : Cocone F diff --git a/Mathlib/CategoryTheory/Limits/IsLimit.lean b/Mathlib/CategoryTheory/Limits/IsLimit.lean index a15e2af7ecdaa..871e20809f175 100644 --- a/Mathlib/CategoryTheory/Limits/IsLimit.lean +++ b/Mathlib/CategoryTheory/Limits/IsLimit.lean @@ -50,7 +50,6 @@ cone morphism to `t`. See . -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] structure IsLimit (t : Cone F) where /-- There is a morphism from any cone point to `t.pt` -/ lift : ∀ s : Cone F, s.pt ⟶ t.pt @@ -500,7 +499,6 @@ cocone morphism from `t`. See . -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] structure IsColimit (t : Cocone F) where /-- `t.pt` maps to all other cocone covertices -/ desc : ∀ s : Cocone F, t.pt ⟶ s.pt diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean index 29d7bf37aa103..ef037726a2d00 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean @@ -67,7 +67,6 @@ open scoped Classical in * morphisms `π j : pt ⟶ F j` and `ι j : F j ⟶ pt` for each `j`, * such that `ι j ≫ π j'` is the identity when `j = j'` and zero otherwise. -/ --- @[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed structure Bicone (F : J → C) where pt : C π : ∀ j, pt ⟶ F j @@ -245,7 +244,6 @@ theorem π_of_isColimit {f : J → C} {t : Bicone f} (ht : IsColimit t.toCocone) simp [t.ι_π] /-- Structure witnessing that a bicone is both a limit cone and a colimit cocone. -/ --- @[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed structure IsBilimit {F : J → C} (B : Bicone F) where isLimit : IsLimit B.toCone isColimit : IsColimit B.toCocone @@ -313,7 +311,6 @@ end Bicone /-- A bicone over `F : J → C`, which is both a limit cone and a colimit cocone. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed; linter not ported yet structure LimitBicone (F : J → C) where bicone : Bicone F isBilimit : bicone.IsBilimit @@ -1103,7 +1100,6 @@ variable {C} maps from `X` to both `P` and `Q`, and maps from both `P` and `Q` to `X`, so that `inl ≫ fst = 𝟙 P`, `inl ≫ snd = 0`, `inr ≫ fst = 0`, and `inr ≫ snd = 𝟙 Q` -/ --- @[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed structure BinaryBicone (P Q : C) where pt : C fst : pt ⟶ P @@ -1353,7 +1349,6 @@ def toBinaryBiconeIsColimit {X Y : C} (b : Bicone (pairFunction X Y)) : end Bicone /-- Structure witnessing that a binary bicone is a limit cone and a limit cocone. -/ --- @[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed structure BinaryBicone.IsBilimit {P Q : C} (b : BinaryBicone P Q) where isLimit : IsLimit b.toCone isColimit : IsColimit b.toCocone @@ -1380,7 +1375,6 @@ def Bicone.toBinaryBiconeIsBilimit {X Y : C} (b : Bicone (pairFunction X Y)) : /-- A bicone over `P Q : C`, which is both a limit cone and a colimit cocone. -/ --- @[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed structure BinaryBiproductData (P Q : C) where bicone : BinaryBicone P Q isBilimit : bicone.IsBilimit diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean b/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean index b61c4579338d9..2741ad205d91e 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean @@ -139,7 +139,6 @@ lemma Hom.comp_eq_comp {X Y Z : WalkingMultispan fst snd} end WalkingMultispan /-- This is a structure encapsulating the data necessary to define a `Multicospan`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): has_nonempty_instance linter not ported yet @[nolint checkUnivs] structure MulticospanIndex (C : Type u) [Category.{v} C] where (L : Type w) @@ -151,7 +150,6 @@ structure MulticospanIndex (C : Type u) [Category.{v} C] where snd : ∀ b, left (sndTo b) ⟶ right b /-- This is a structure encapsulating the data necessary to define a `Multispan`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): has_nonempty_instance linter not ported yet @[nolint checkUnivs] structure MultispanIndex (C : Type u) [Category.{v} C] where (L : Type w) @@ -276,14 +274,10 @@ end MultispanIndex variable {C : Type u} [Category.{v} C] /-- A multifork is a cone over a multicospan. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] abbrev Multifork (I : MulticospanIndex.{w, w'} C) := Cone I.multicospan /-- A multicofork is a cocone over a multispan. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] abbrev Multicofork (I : MultispanIndex.{w, w'} C) := Cocone I.multispan diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean index 5706484d58e29..5d87af2751e5f 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean @@ -585,7 +585,6 @@ instance : HasPushouts.{u} (Type u) := variable {X Y Z : Type u} {X' Y' Z' : Type v} variable (f : X ⟶ Z) (g : Y ⟶ Z) (f' : X' ⟶ Z') (g' : Y' ⟶ Z') --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The usual explicit pullback in the category of types, as a subtype of the product. The full `LimitCone` data is bundled as `pullbackLimitCone f g`. -/ diff --git a/Mathlib/CategoryTheory/Limits/Types.lean b/Mathlib/CategoryTheory/Limits/Types.lean index fd38583178553..396fd6658d545 100644 --- a/Mathlib/CategoryTheory/Limits/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Types.lean @@ -321,7 +321,6 @@ See `CategoryTheory.Limits.Types.Quot`. def Quot.Rel (F : J ⥤ Type u) : (Σ j, F.obj j) → (Σ j, F.obj j) → Prop := fun p p' => ∃ f : p.1 ⟶ p'.1, p'.2 = F.map f p.2 --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- A quotient type implementing the colimit of a functor `F : J ⥤ Type u`, as pairs `⟨j, x⟩` where `x : F.obj j`, modulo the equivalence relation generated by `⟨j, x⟩ ~ ⟨j', x'⟩` whenever there is a morphism `f : j ⟶ j'` so `F.map f x = x'`. diff --git a/Mathlib/CategoryTheory/Localization/Construction.lean b/Mathlib/CategoryTheory/Localization/Construction.lean index 5bcd82a33e3e7..9cc4362686b03 100644 --- a/Mathlib/CategoryTheory/Localization/Construction.lean +++ b/Mathlib/CategoryTheory/Localization/Construction.lean @@ -50,7 +50,6 @@ namespace Localization namespace Construction --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- If `W : MorphismProperty C`, `LocQuiver W` is a quiver with the same objects as `C`, and whose morphisms are those in `C` and placeholders for formal inverses of the morphisms in `W`. -/ @@ -90,7 +89,6 @@ namespace MorphismProperty open Localization.Construction --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The localized category obtained by formally inverting the morphisms in `W : MorphismProperty C` -/ def Localization := diff --git a/Mathlib/CategoryTheory/Monad/Algebra.lean b/Mathlib/CategoryTheory/Monad/Algebra.lean index b9f87cb3658a5..9e6a0c7fb3331 100644 --- a/Mathlib/CategoryTheory/Monad/Algebra.lean +++ b/Mathlib/CategoryTheory/Monad/Algebra.lean @@ -262,8 +262,6 @@ end Monad namespace Comonad /-- An Eilenberg-Moore coalgebra for a comonad `T`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] structure Coalgebra (G : Comonad C) : Type max u₁ v₁ where /-- The underlying object associated to a coalgebra. -/ A : C @@ -288,8 +286,6 @@ namespace Coalgebra variable {G : Comonad C} /-- A morphism of Eilenberg-Moore coalgebras for the comonad `G`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet ---@[ext, nolint has_nonempty_instance] @[ext] structure Hom (A B : Coalgebra G) where /-- The underlying morphism associated to a morphism of coalgebras. -/ diff --git a/Mathlib/CategoryTheory/Monoidal/Center.lean b/Mathlib/CategoryTheory/Monoidal/Center.lean index d670e07b11bf3..d0aed0f699e35 100644 --- a/Mathlib/CategoryTheory/Monoidal/Center.lean +++ b/Mathlib/CategoryTheory/Monoidal/Center.lean @@ -47,7 +47,6 @@ Thinking of `C` as a 2-category with a single `0`-morphism, these are the same a transformations (in the pseudo- sense) of the identity 2-functor on `C`, which send the unique `0`-morphism to `X`. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): This linter does not exist yet. structure HalfBraiding (X : C) where β : ∀ U, X ⊗ U ≅ U ⊗ X monoidal : ∀ U U', (β (U ⊗ U')).hom = @@ -66,7 +65,6 @@ variable (C) /-- The Drinfeld center of a monoidal category `C` has as objects pairs `⟨X, b⟩`, where `X : C` and `b` is a half-braiding on `X`. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): This linter does not exist yet. def Center := Σ X : C, HalfBraiding X @@ -75,8 +73,7 @@ namespace Center variable {C} /-- A morphism in the Drinfeld center of `C`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet -@[ext] -- @[nolint has_nonempty_instance] +@[ext] structure Hom (X Y : Center C) where f : X.1 ⟶ Y.1 comm : ∀ U, (f ▷ U) ≫ (Y.2.β U).hom = (X.2.β U).hom ≫ (U ◁ f) := by aesop_cat diff --git a/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean index 04bf2a16a1b33..1b447182a254b 100644 --- a/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean @@ -57,8 +57,6 @@ attribute [nolint simpNF] unit.sizeOf_spec tensor.injEq tensor.sizeOf_spec /-- Formal compositions and tensor products of identities, unitors and associators. The morphisms of the free monoidal category are obtained as a quotient of these formal morphisms by the relations defining a monoidal category. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet --- @[nolint has_nonempty_instance] inductive Hom : F C → F C → Type u | id (X) : Hom X X | α_hom (X Y Z : F C) : Hom ((X.tensor Y).tensor Z) (X.tensor (Y.tensor Z)) diff --git a/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean b/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean index 910625a02dc20..3b648ca7dd9f5 100644 --- a/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean +++ b/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean @@ -50,7 +50,6 @@ variable (C) /-- We say an object in the free monoidal category is in normal form if it is of the form `(((𝟙_ C) ⊗ X₁) ⊗ X₂) ⊗ ⋯`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] inductive NormalMonoidalObject : Type u | unit : NormalMonoidalObject | tensor : NormalMonoidalObject → C → NormalMonoidalObject diff --git a/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean b/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean index ad627f3e283cf..045a1d884c4b3 100644 --- a/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/OfChosenFiniteProducts/Basic.lean @@ -311,8 +311,6 @@ a fixed choice of limit data for the empty functor, and for `pair X Y` for every This is an implementation detail for `SymmetricOfChosenFiniteProducts`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter `has_nonempty_instance` not ported yet --- @[nolint has_nonempty_instance] @[nolint unusedArguments] def MonoidalOfChosenFiniteProductsSynonym (_𝒯 : LimitCone (Functor.empty.{0} C)) (_ℬ : ∀ X Y : C, LimitCone (pair X Y)) := diff --git a/Mathlib/CategoryTheory/Monoidal/Opposite.lean b/Mathlib/CategoryTheory/Monoidal/Opposite.lean index a9d80869adb38..ed2e80caacecd 100644 --- a/Mathlib/CategoryTheory/Monoidal/Opposite.lean +++ b/Mathlib/CategoryTheory/Monoidal/Opposite.lean @@ -22,7 +22,6 @@ open CategoryTheory.MonoidalCategory /-- The type of objects of the opposite (or "reverse") monoidal category. Use the notation `Cᴹᵒᵖ`. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): This linter does not exist yet. structure MonoidalOpposite (C : Type u₁) where /-- The object of `MonoidalOpposite C` that represents `x : C`. -/ mop :: /-- The object of `C` represented by `x : MonoidalOpposite C`. -/ unmop : C diff --git a/Mathlib/CategoryTheory/MorphismProperty/IsInvertedBy.lean b/Mathlib/CategoryTheory/MorphismProperty/IsInvertedBy.lean index 16ed860f8bcb4..68929bd30839c 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/IsInvertedBy.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/IsInvertedBy.lean @@ -88,7 +88,6 @@ lemma pi {J : Type w} {C : J → Type u} {D : J → Type u'} end IsInvertedBy --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The full subcategory of `C ⥤ D` consisting of functors inverting morphisms in `W` -/ def FunctorsInverting (W : MorphismProperty C) (D : Type*) [Category D] := FullSubcategory fun F : C ⥤ D => W.IsInvertedBy F diff --git a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean index 0c7bc7c4e3cc3..28da24fb31033 100644 --- a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean +++ b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean @@ -193,7 +193,6 @@ section variable (C D : Type*) [Category C] [Category D] [Preadditive C] [Preadditive D] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- Bundled additive functors. -/ def AdditiveFunctor := FullSubcategory fun F : C ⥤ D => F.Additive diff --git a/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean b/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean index 1e95960d69dc2..0416818a8fec6 100644 --- a/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Preadditive/InjectiveResolution.lean @@ -38,8 +38,6 @@ variable {C : Type u} [Category.{v} C] [HasZeroObject C] [HasZeroMorphisms C] An `InjectiveResolution Z` consists of a bundled `ℕ`-indexed cochain complex of injective objects, along with a quasi-isomorphism from the complex consisting of just `Z` supported in degree `0`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure InjectiveResolution (Z : C) where /-- the cochain complex involved in the resolution -/ cocomplex : CochainComplex C ℕ diff --git a/Mathlib/CategoryTheory/Preadditive/Mat.lean b/Mathlib/CategoryTheory/Preadditive/Mat.lean index 2a27f9a373550..f323817080a5e 100644 --- a/Mathlib/CategoryTheory/Preadditive/Mat.lean +++ b/Mathlib/CategoryTheory/Preadditive/Mat.lean @@ -72,7 +72,6 @@ namespace Mat_ variable {C} --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- A morphism in `Mat_ C` is a dependently typed matrix of morphisms. -/ def Hom (M N : Mat_ C) : Type v₁ := DMatrix M.ι N.ι fun i j => M.X i ⟶ N.X j diff --git a/Mathlib/CategoryTheory/Preadditive/Projective.lean b/Mathlib/CategoryTheory/Preadditive/Projective.lean index b576bee9c0e8a..8568390a4fb5b 100644 --- a/Mathlib/CategoryTheory/Preadditive/Projective.lean +++ b/Mathlib/CategoryTheory/Preadditive/Projective.lean @@ -52,7 +52,6 @@ section /-- A projective presentation of an object `X` consists of an epimorphism `f : P ⟶ X` from some projective object `P`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure ProjectivePresentation (X : C) where p : C [projective : Projective p] diff --git a/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean b/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean index c743e88b1c70d..26b561b060a32 100644 --- a/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Preadditive/ProjectiveResolution.lean @@ -29,7 +29,6 @@ open Projective variable [HasZeroObject C] [HasZeroMorphisms C] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- A `ProjectiveResolution Z` consists of a bundled `ℕ`-indexed chain complex of projective objects, along with a quasi-isomorphism to the complex consisting of just `Z` supported in degree `0`. diff --git a/Mathlib/CategoryTheory/Shift/Basic.lean b/Mathlib/CategoryTheory/Shift/Basic.lean index d08d8b67edc4f..48ff0cc129d93 100644 --- a/Mathlib/CategoryTheory/Shift/Basic.lean +++ b/Mathlib/CategoryTheory/Shift/Basic.lean @@ -61,7 +61,6 @@ class HasShift (C : Type u) (A : Type*) [Category.{v} C] [AddMonoid A] where /-- `shift` is monoidal -/ shiftMonoidal : shift.Monoidal := by infer_instance --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- A helper structure to construct the shift functor `(Discrete A) ⥤ (C ⥤ C)`. -/ structure ShiftMkCore where /-- the family of shift functors -/ diff --git a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean index 2997401067b07..dad92afd416e4 100644 --- a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean @@ -34,7 +34,6 @@ variable [HasForget.{max v u} D] attribute [local instance] HasForget.hasCoeToSort HasForget.instFunLike --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- A concrete version of the multiequalizer, to be used below. -/ def Meq {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) := { x : ∀ I : S.Arrow, P.obj (op I.Y) // diff --git a/Mathlib/CategoryTheory/Sites/CoverLifting.lean b/Mathlib/CategoryTheory/Sites/CoverLifting.lean index 631707e2b37e5..b6098d47f159a 100644 --- a/Mathlib/CategoryTheory/Sites/CoverLifting.lean +++ b/Mathlib/CategoryTheory/Sites/CoverLifting.lean @@ -68,7 +68,6 @@ variable {L : GrothendieckTopology E} /-- A functor `G : (C, J) ⥤ (D, K)` between sites is called cocontinuous (SGA 4 III 2.1) if for all covering sieves `R` in `D`, `R.pullback G` is a covering sieve in `C`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]` class Functor.IsCocontinuous : Prop where cover_lift : ∀ {U : C} {S : Sieve (G.obj U)} (_ : S ∈ K (G.obj U)), S.functorPullback G ∈ J U diff --git a/Mathlib/CategoryTheory/Sites/CoverPreserving.lean b/Mathlib/CategoryTheory/Sites/CoverPreserving.lean index 08f728dd0bf0e..fce2b79404c90 100644 --- a/Mathlib/CategoryTheory/Sites/CoverPreserving.lean +++ b/Mathlib/CategoryTheory/Sites/CoverPreserving.lean @@ -51,7 +51,6 @@ variable {L : GrothendieckTopology A} /-- A functor `G : (C, J) ⥤ (D, K)` between sites is *cover-preserving* if for all covering sieves `R` in `C`, `R.functorPushforward G` is a covering sieve in `D`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]` structure CoverPreserving (G : C ⥤ D) : Prop where cover_preserve : ∀ {U : C} {S : Sieve U} (_ : S ∈ J U), S.functorPushforward G ∈ K (G.obj U) @@ -72,7 +71,6 @@ compatible family of elements at `C` and valued in `G.op ⋙ ℱ`, and each comm This is actually stronger than merely preserving compatible families because of the definition of `functorPushforward` used. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet @[nolint has_nonempty_instance] structure CompatiblePreserving (K : GrothendieckTopology D) (G : C ⥤ D) : Prop where compatible : ∀ (ℱ : Sheaf K (Type w)) {Z} {T : Presieve Z} {x : FamilyOfElements (G.op ⋙ ℱ.val) T} diff --git a/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean b/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean index e857f880260dd..4d65746a7c821 100644 --- a/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean +++ b/Mathlib/CategoryTheory/Sites/DenseSubsite/Basic.lean @@ -48,7 +48,6 @@ variable {L : GrothendieckTopology E} /-- An auxiliary structure that witnesses the fact that `f` factors through an image object of `G`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]` structure Presieve.CoverByImageStructure (G : C ⥤ D) {V U : D} (f : V ⟶ U) where obj : C lift : V ⟶ G.obj obj diff --git a/Mathlib/CategoryTheory/Sites/Grothendieck.lean b/Mathlib/CategoryTheory/Sites/Grothendieck.lean index 5570569b02e2b..cfb68cc8d4ea9 100644 --- a/Mathlib/CategoryTheory/Sites/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Sites/Grothendieck.lean @@ -413,8 +413,6 @@ instance : Inhabited (J.Cover X) := ⟨⊤⟩ /-- An auxiliary structure, used to define `S.index`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] @[ext] structure Arrow (S : J.Cover X) where /-- The source of the arrow. -/ @@ -551,8 +549,6 @@ theorem Arrow.middle_spec {X : C} {S : J.Cover X} {T : ∀ I : S.Arrow, J.Cover I.hf.choose_spec.choose_spec.choose_spec.choose_spec.2 /-- An auxiliary structure, used to define `S.index`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance, ext] @[ext] structure Relation (S : J.Cover X) where /-- The first arrow. -/ diff --git a/Mathlib/CategoryTheory/Widesubcategory.lean b/Mathlib/CategoryTheory/Widesubcategory.lean index 8c70e208ae0c9..4a9779b92eb3b 100644 --- a/Mathlib/CategoryTheory/Widesubcategory.lean +++ b/Mathlib/CategoryTheory/Widesubcategory.lean @@ -39,7 +39,6 @@ variable (F : C → D) (P : MorphismProperty D) [P.IsMultiplicative] which provides a category structure so that the morphisms `X ⟶ Y` are the morphisms in `D` from `F X` to `F Y` which satisfy a property `P : MorphismProperty D` that is multiplicative. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] @[nolint unusedArguments] def InducedWideCategory (_F : C → D) (_P : MorphismProperty D) [IsMultiplicative _P] := C diff --git a/Mathlib/CategoryTheory/WithTerminal.lean b/Mathlib/CategoryTheory/WithTerminal.lean index 3fbad067a0b3d..e8309c595d1f7 100644 --- a/Mathlib/CategoryTheory/WithTerminal.lean +++ b/Mathlib/CategoryTheory/WithTerminal.lean @@ -64,7 +64,6 @@ namespace WithTerminal variable {C} /-- Morphisms for `WithTerminal C`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `nolint has_nonempty_instance` @[simp] def Hom : WithTerminal C → WithTerminal C → Type v | of X, of Y => X ⟶ Y @@ -368,7 +367,6 @@ namespace WithInitial variable {C} /-- Morphisms for `WithInitial C`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `nolint has_nonempty_instance` @[simp] def Hom : WithInitial C → WithInitial C → Type v | of X, of Y => X ⟶ Y diff --git a/Mathlib/Combinatorics/Quiver/Basic.lean b/Mathlib/Combinatorics/Quiver/Basic.lean index ed4441ac1f8be..a9ab68044b012 100644 --- a/Mathlib/Combinatorics/Quiver/Basic.lean +++ b/Mathlib/Combinatorics/Quiver/Basic.lean @@ -69,8 +69,6 @@ def Hom.opEquiv {V} [Quiver V] {X Y : V} : right_inv _ := rfl /-- A type synonym for a quiver with no arrows. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] def Empty (V : Type u) : Type u := V instance emptyQuiver (V : Type u) : Quiver.{u} (Empty V) := ⟨fun _ _ => PEmpty⟩ diff --git a/Mathlib/Combinatorics/Quiver/Subquiver.lean b/Mathlib/Combinatorics/Quiver/Subquiver.lean index 365c0628c73d1..c200a9d3a9d2a 100644 --- a/Mathlib/Combinatorics/Quiver/Subquiver.lean +++ b/Mathlib/Combinatorics/Quiver/Subquiver.lean @@ -25,7 +25,6 @@ def WideSubquiver (V) [Quiver.{v + 1} V] := /-- A type synonym for `V`, when thought of as a quiver having only the arrows from some `WideSubquiver`. -/ --- Porting note: no hasNonemptyInstance linter yet https://github.com/leanprover-community/mathlib4/issues/5171 @[nolint unusedArguments] def WideSubquiver.toType (V) [Quiver V] (_ : WideSubquiver V) : Type u := V diff --git a/Mathlib/Combinatorics/Quiver/Symmetric.lean b/Mathlib/Combinatorics/Quiver/Symmetric.lean index dc7abe0e3f8c3..9609bd98e12aa 100644 --- a/Mathlib/Combinatorics/Quiver/Symmetric.lean +++ b/Mathlib/Combinatorics/Quiver/Symmetric.lean @@ -26,7 +26,6 @@ namespace Quiver /-- A type synonym for the symmetrized quiver (with an arrow both ways for each original arrow). NB: this does not work for `Prop`-valued quivers. It requires `[Quiver.{v+1} V]`. -/ --- Porting note: no hasNonemptyInstance linter yet https://github.com/leanprover-community/mathlib4/issues/5171 def Symmetrify (V : Type*) := V instance symmetrifyQuiver (V : Type u) [Quiver V] : Quiver (Symmetrify V) := diff --git a/Mathlib/Data/PFunctor/Multivariate/W.lean b/Mathlib/Data/PFunctor/Multivariate/W.lean index d5250ef8adc16..9fce44601bb01 100644 --- a/Mathlib/Data/PFunctor/Multivariate/W.lean +++ b/Mathlib/Data/PFunctor/Multivariate/W.lean @@ -108,7 +108,6 @@ def wp : MvPFunctor n where B := P.WPath /-- W-type of `P` -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): used to have @[nolint has_nonempty_instance] def W (α : TypeVec n) : Type _ := P.wp α diff --git a/Mathlib/Data/PFunctor/Univariate/Basic.lean b/Mathlib/Data/PFunctor/Univariate/Basic.lean index 9f6015ea64417..d9421dae365a4 100644 --- a/Mathlib/Data/PFunctor/Univariate/Basic.lean +++ b/Mathlib/Data/PFunctor/Univariate/Basic.lean @@ -85,8 +85,6 @@ def W := /- inhabitants of W types is awkward to encode as an instance assumption because there needs to be a value `a : P.A` such that `P.B a` is empty to yield a finite tree -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- attribute [nolint has_nonempty_instance] W variable {P} diff --git a/Mathlib/Data/QPF/Univariate/Basic.lean b/Mathlib/Data/QPF/Univariate/Basic.lean index ebb6886d06e51..445a0779eb6e1 100644 --- a/Mathlib/Data/QPF/Univariate/Basic.lean +++ b/Mathlib/Data/QPF/Univariate/Basic.lean @@ -218,8 +218,6 @@ def Wsetoid : Setoid q.P.W := attribute [local instance] Wsetoid /-- inductive type defined as initial algebra of a Quotient of Polynomial Functor -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] def Fix (F : Type u → Type u) [q : QPF F] := Quotient (Wsetoid : Setoid q.P.W) diff --git a/Mathlib/Dynamics/Ergodic/Ergodic.lean b/Mathlib/Dynamics/Ergodic/Ergodic.lean index cc9abb51e7198..29c03db776487 100644 --- a/Mathlib/Dynamics/Ergodic/Ergodic.lean +++ b/Mathlib/Dynamics/Ergodic/Ergodic.lean @@ -42,13 +42,11 @@ structure PreErgodic (f : α → α) (μ : Measure α := by volume_tac) : Prop w /-- A map `f : α → α` is said to be ergodic with respect to a measure `μ` if it is measure preserving and pre-ergodic. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] structure Ergodic (f : α → α) (μ : Measure α := by volume_tac) extends MeasurePreserving f μ μ, PreErgodic f μ : Prop /-- A map `f : α → α` is said to be quasi ergodic with respect to a measure `μ` if it is quasi measure preserving and pre-ergodic. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] structure QuasiErgodic (f : α → α) (μ : Measure α := by volume_tac) extends QuasiMeasurePreserving f μ μ, PreErgodic f μ : Prop diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index a862ca47f3f78..2624f27c53751 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -911,8 +911,6 @@ end ChartedSpace have a topological structure, where the topology would come from the charts. For this, one needs charts that are only partial equivalences, and continuity properties for their composition. This is formalised in `ChartedSpaceCore`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure ChartedSpaceCore (H : Type*) [TopologicalSpace H] (M : Type*) where /-- An atlas of charts, which are only `PartialEquiv`s -/ atlas : Set (PartialEquiv M H) @@ -1283,8 +1281,6 @@ lemma StructureGroupoid.restriction_in_maximalAtlas {e : PartialHomeomorph M H} /-- A `G`-diffeomorphism between two charted spaces is a homeomorphism which, when read in the charts, belongs to `G`. We avoid the word diffeomorph as it is too related to the smooth category, and use structomorph instead. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure Structomorph (G : StructureGroupoid H) (M : Type*) (M' : Type*) [TopologicalSpace M] [TopologicalSpace M'] [ChartedSpace H M] [ChartedSpace H M'] extends Homeomorph M M' where mem_groupoid : ∀ c : PartialHomeomorph M H, ∀ c' : PartialHomeomorph M' H, c ∈ atlas H M → diff --git a/Mathlib/Geometry/Manifold/Diffeomorph.lean b/Mathlib/Geometry/Manifold/Diffeomorph.lean index 39b1fb3e9f0b4..4b54d89d14d5b 100644 --- a/Mathlib/Geometry/Manifold/Diffeomorph.lean +++ b/Mathlib/Geometry/Manifold/Diffeomorph.lean @@ -65,7 +65,6 @@ variable (I I' M M' n) /-- `n`-times continuously differentiable diffeomorphism between `M` and `M'` with respect to `I` and `I'`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure Diffeomorph extends M ≃ M' where protected contMDiff_toFun : ContMDiff I I' n toEquiv protected contMDiff_invFun : ContMDiff I' I n toEquiv.symm diff --git a/Mathlib/Geometry/Manifold/IsManifold.lean b/Mathlib/Geometry/Manifold/IsManifold.lean index 29e30318e722e..e457659e18ad7 100644 --- a/Mathlib/Geometry/Manifold/IsManifold.lean +++ b/Mathlib/Geometry/Manifold/IsManifold.lean @@ -149,7 +149,7 @@ defined, the latter ensures that for `C^2` maps the second derivatives are symme on the boundary, as these are limit points of interior points where symmetry holds. If further conditions turn out to be useful, they can be added here. -/ -@[ext] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was nolint has_nonempty_instance +@[ext] structure ModelWithCorners (𝕜 : Type*) [NontriviallyNormedField 𝕜] (E : Type*) [NormedAddCommGroup E] [NormedSpace 𝕜 E] (H : Type*) [TopologicalSpace H] extends PartialEquiv H E where @@ -1662,7 +1662,6 @@ variable (M) in -- is empty if the base manifold is empty /-- The tangent bundle to a manifold, as a Sigma type. Defined in terms of `Bundle.TotalSpace` to be able to put a suitable topology on it. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was nolint has_nonempty_instance abbrev TangentBundle := Bundle.TotalSpace E (TangentSpace I : M → Type _) end TangentSpace diff --git a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean index ef5099d8835ea..9b52a1a42507b 100644 --- a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean +++ b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean @@ -95,7 +95,6 @@ subordinate to `U`, see `SmoothBumpCovering.exists_isSubordinate`. This covering can be used, e.g., to construct a partition of unity and to prove the weak Whitney embedding theorem. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure SmoothBumpCovering [FiniteDimensional ℝ E] (s : Set M := univ) where /-- The center point of each bump in the smooth covering. -/ c : ι → M diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index 867c314932f6a..99c7565362d22 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -90,8 +90,6 @@ such that We can then glue the spaces `U i` together by identifying `V i j` with `V j i`, such that the `U i`'s are open subspaces of the glued space. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure GlueData extends CategoryTheory.GlueData (PresheafedSpace.{u, v, v} C) where f_open : ∀ i j, IsOpenImmersion (f i j) @@ -552,8 +550,6 @@ such that We can then glue the spaces `U i` together by identifying `V i j` with `V j i`, such that the `U i`'s are open subspaces of the glued space. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure GlueData extends CategoryTheory.GlueData (SheafedSpace.{u, v, v} C) where f_open : ∀ i j, SheafedSpace.IsOpenImmersion (f i j) @@ -625,8 +621,6 @@ such that We can then glue the spaces `U i` together by identifying `V i j` with `V j i`, such that the `U i`'s are open subspaces of the glued space. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure GlueData extends CategoryTheory.GlueData LocallyRingedSpace where f_open : ∀ i j, LocallyRingedSpace.IsOpenImmersion (f i j) diff --git a/Mathlib/GroupTheory/CoprodI.lean b/Mathlib/GroupTheory/CoprodI.lean index 09d71fbf32674..20c498af25ecf 100644 --- a/Mathlib/GroupTheory/CoprodI.lean +++ b/Mathlib/GroupTheory/CoprodI.lean @@ -621,7 +621,6 @@ variable (M) /-- A `NeWord M i j` is a representation of a non-empty reduced words where the first letter comes from `M i` and the last letter comes from `M j`. It can be constructed from singletons and via concatenation, and thus provides a useful induction principle. -/ ---@[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): commented out inductive NeWord : ι → ι → Type _ | singleton : ∀ {i : ι} (x : M i), x ≠ 1 → NeWord i i | append : ∀ {i j k l} (_w₁ : NeWord i j) (_hne : j ≠ k) (_w₂ : NeWord k l), NeWord i l diff --git a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean index 5fc605e18a73b..2343d928c711c 100644 --- a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean +++ b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean @@ -61,7 +61,6 @@ open CategoryTheory CategoryTheory.ActionCategory CategoryTheory.SingleObj Quive /-- `IsFreeGroupoid.Generators G` is a type synonym for `G`. We think of this as the vertices of the generating quiver of `G` when `G` is free. We can't use `G` directly, since `G` already has a quiver instance from being a groupoid. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): @[nolint has_nonempty_instance] @[nolint unusedArguments] def IsFreeGroupoid.Generators (G) [Groupoid G] := G diff --git a/Mathlib/GroupTheory/GroupAction/Hom.lean b/Mathlib/GroupTheory/GroupAction/Hom.lean index f10d91924ee1c..c958a472e60c7 100644 --- a/Mathlib/GroupTheory/GroupAction/Hom.lean +++ b/Mathlib/GroupTheory/GroupAction/Hom.lean @@ -75,8 +75,6 @@ structure AddActionHom {M N : Type*} (φ: M → N) (X : Type*) [VAdd M X] (Y : T /-- Equivariant functions : When `φ : M → N` is a function, and types `X` and `Y` are endowed with actions of `M` and `N`, a function `f : X → Y` is `φ`-equivariant if `f (m • x) = (φ m) • (f x)`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] @[to_additive] structure MulActionHom where /-- The underlying function. -/ @@ -591,8 +589,6 @@ variable (T : Type*) [Semiring T] [MulSemiringAction P T] -- variable [AddMonoid N'] [DistribMulAction S N'] /-- Equivariant ring homomorphisms. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure MulSemiringActionHom extends R →ₑ+[φ] S, R →+* S /- diff --git a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean index 70d089f4ff23f..69ac2dcd67706 100644 --- a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean +++ b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean @@ -82,8 +82,6 @@ variable {M : Type*} [AddCommMonoid M] (S : AddSubmonoid M) (N : Type*) [AddComm /-- The type of AddMonoid homomorphisms satisfying the characteristic predicate: if `f : M →+ N` satisfies this predicate, then `N` is isomorphic to the localization of `M` at `S`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure LocalizationMap extends AddMonoidHom M N where map_add_units' : ∀ y : S, IsAddUnit (toFun y) surj' : ∀ z : N, ∃ x : M × S, z + toFun x.2 = toFun x.1 @@ -107,8 +105,6 @@ namespace Submonoid /-- The type of monoid homomorphisms satisfying the characteristic predicate: if `f : M →* N` satisfies this predicate, then `N` is isomorphic to the localization of `M` at `S`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure LocalizationMap extends MonoidHom M N where map_units' : ∀ y : S, IsUnit (toFun y) surj' : ∀ z : N, ∃ x : M × S, z * toFun x.2 = toFun x.1 diff --git a/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean b/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean index ac8015e1578b9..f7e0e187cbf70 100644 --- a/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean +++ b/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean @@ -53,8 +53,6 @@ theorem LocalizationMap.subsingleton (f : Submonoid.LocalizationMap S N) (h : 0 /-- The type of homomorphisms between monoids with zero satisfying the characteristic predicate: if `f : M →*₀ N` satisfies this predicate, then `N` is isomorphic to the localization of `M` at `S`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure LocalizationWithZeroMap extends LocalizationMap S N where map_zero' : toFun 0 = 0 diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean index 1ac5e28cebf7a..1f0bbd7643e0b 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean @@ -40,8 +40,6 @@ such that both forward and inverse maps are affine. We define it using an `Equiv` for the map and a `LinearEquiv` for the linear part in order to allow affine equivalences with good definitional equalities. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure AffineEquiv (k P₁ P₂ : Type*) {V₁ V₂ : Type*} [Ring k] [AddCommGroup V₁] [Module k V₁] [AddTorsor V₁ P₁] [AddCommGroup V₂] [Module k V₂] [AddTorsor V₂ P₂] extends P₁ ≃ P₂ where linear : V₁ ≃ₗ[k] V₂ diff --git a/Mathlib/LinearAlgebra/Dual.lean b/Mathlib/LinearAlgebra/Dual.lean index b8ca669106157..a6c69a3ba7efa 100644 --- a/Mathlib/LinearAlgebra/Dual.lean +++ b/Mathlib/LinearAlgebra/Dual.lean @@ -824,7 +824,6 @@ def evalUseFiniteInstance : TacticM Unit := do elab "use_finite_instance" : tactic => evalUseFiniteInstance /-- `e` and `ε` have characteristic properties of a basis and its dual -/ --- @[nolint has_nonempty_instance] Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed structure Module.DualBases (e : ι → M) (ε : ι → Dual R M) : Prop where eval_same : ∀ i, ε i (e i) = 1 eval_of_ne : Pairwise fun i j ↦ ε i (e j) = 0 diff --git a/Mathlib/LinearAlgebra/FreeModule/PID.lean b/Mathlib/LinearAlgebra/FreeModule/PID.lean index ee2c18e4201b6..85fa3318e2a59 100644 --- a/Mathlib/LinearAlgebra/FreeModule/PID.lean +++ b/Mathlib/LinearAlgebra/FreeModule/PID.lean @@ -412,7 +412,6 @@ section SmithNormal /-- A Smith normal form basis for a submodule `N` of a module `M` consists of bases for `M` and `N` such that the inclusion map `N → M` can be written as a (rectangular) matrix with `a` along the diagonal: in Smith normal form. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): @[nolint has_nonempty_instance] structure Basis.SmithNormalForm (N : Submodule R M) (ι : Type*) (n : ℕ) where /-- The basis of M. -/ bM : Basis ι R M diff --git a/Mathlib/LinearAlgebra/Matrix/Transvection.lean b/Mathlib/LinearAlgebra/Matrix/Transvection.lean index 9b9593fe097ac..8dc27fc0a5f62 100644 --- a/Mathlib/LinearAlgebra/Matrix/Transvection.lean +++ b/Mathlib/LinearAlgebra/Matrix/Transvection.lean @@ -136,7 +136,6 @@ variable (R n) /-- A structure containing all the information from which one can build a nontrivial transvection. This structure is easier to manipulate than transvections as one has a direct access to all the relevant fields. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] structure TransvectionStruct where (i j : n) hij : i ≠ j diff --git a/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean b/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean index 24854dd6d048c..da4ad9b49c356 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean @@ -34,7 +34,6 @@ variable [Module R M] [Module R M₁] [Module R M₂] [Module R M₃] [Module R /-- An isometric equivalence between two quadratic spaces `M₁, Q₁` and `M₂, Q₂` over a ring `R`, is a linear equivalence between `M₁` and `M₂` that commutes with the quadratic forms. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet @[nolint has_nonempty_instance] structure IsometryEquiv (Q₁ : QuadraticMap R M₁ N) (Q₂ : QuadraticMap R M₂ N) extends M₁ ≃ₗ[R] M₂ where map_app' : ∀ m, Q₂ (toFun m) = Q₁ m diff --git a/Mathlib/LinearAlgebra/Ray.lean b/Mathlib/LinearAlgebra/Ray.lean index c460672f898e7..b545070466409 100644 --- a/Mathlib/LinearAlgebra/Ray.lean +++ b/Mathlib/LinearAlgebra/Ray.lean @@ -180,7 +180,6 @@ theorem add_right (hy : SameRay R x y) (hz : SameRay R x z) : SameRay R x (y + z end SameRay --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed has_nonempty_instance nolint, no such linter set_option linter.unusedVariables false in /-- Nonzero vectors, as used to define rays. This type depends on an unused argument `R` so that `RayVector.Setoid` can be an instance. -/ @@ -205,7 +204,6 @@ instance RayVector.Setoid : Setoid (RayVector R M) where exact hxy.trans hyz fun hy => (y.2 hy).elim⟩ /-- A ray (equivalence class of nonzero vectors with common positive multiples) in a module. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed has_nonempty_instance nolint, no such linter def Module.Ray := Quotient (RayVector.Setoid R M) diff --git a/Mathlib/Logic/Embedding/Basic.lean b/Mathlib/Logic/Embedding/Basic.lean index a77e11e473f68..4e516587e5f5a 100644 --- a/Mathlib/Logic/Embedding/Basic.lean +++ b/Mathlib/Logic/Embedding/Basic.lean @@ -15,8 +15,6 @@ universe u v w x namespace Function --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] /-- `α ↪ β` is a bundled injective function. -/ structure Embedding (α : Sort*) (β : Sort*) where /-- An embedding as a function. Use coercion instead. -/ diff --git a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean index 7671daaa30640..6d40a1d80bc52 100644 --- a/Mathlib/MeasureTheory/Covering/VitaliFamily.lean +++ b/Mathlib/MeasureTheory/Covering/VitaliFamily.lean @@ -61,8 +61,6 @@ Vitali families are provided by covering theorems such as the Besicovitch coveri Vitali covering theorem. They make it possible to formulate general versions of theorems on differentiations of measure that apply in both contexts. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure VitaliFamily {m : MeasurableSpace X} (μ : Measure X) where /-- Sets of the family "centered" at a given point. -/ setsAt : X → Set (Set X) diff --git a/Mathlib/MeasureTheory/Measure/Typeclasses.lean b/Mathlib/MeasureTheory/Measure/Typeclasses.lean index 71c507d192908..fcd3da6faea7c 100644 --- a/Mathlib/MeasureTheory/Measure/Typeclasses.lean +++ b/Mathlib/MeasureTheory/Measure/Typeclasses.lean @@ -540,8 +540,6 @@ theorem finiteAtBot {m0 : MeasurableSpace α} (μ : Measure α) : μ.FiniteAtFil about the sets, such as that they are monotone. `SigmaFinite` is defined in terms of this: `μ` is σ-finite if there exists a sequence of finite spanning sets in the collection of all measurable sets. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure FiniteSpanningSetsIn {m0 : MeasurableSpace α} (μ : Measure α) (C : Set (Set α)) where protected set : ℕ → Set α protected set_mem : ∀ i, set i ∈ C diff --git a/Mathlib/ModelTheory/Basic.lean b/Mathlib/ModelTheory/Basic.lean index 6e23ef16e9acd..6de4fea493467 100644 --- a/Mathlib/ModelTheory/Basic.lean +++ b/Mathlib/ModelTheory/Basic.lean @@ -81,14 +81,10 @@ protected def sum (L' : Language.{u', v'}) : Language := ⟨fun n => L.Functions n ⊕ L'.Functions n, fun n => L.Relations n ⊕ L'.Relations n⟩ /-- The type of constants in a given language. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] protected abbrev Constants := L.Functions 0 /-- The type of symbols in a given language. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] abbrev Symbols := (Σ l, L.Functions l) ⊕ (Σ l, L.Relations l) diff --git a/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean b/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean index 5fd3caaed9a9c..acf857f2bf3e1 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/AddCharacter.lean @@ -92,9 +92,6 @@ lemma not_isPrimitive_mulShift [Finite R] (e : AddChar R R') {r : R} /-- Definition for a primitive additive character on a finite ring `R` into a cyclotomic extension of a field `R'`. It records which cyclotomic extension it is, the character, and the fact that the character is primitive. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- can't prove that they always exist (referring to providing an `Inhabited` instance) --- @[nolint has_nonempty_instance] structure PrimitiveAddChar (R : Type u) [CommRing R] (R' : Type v) [Field R'] where /-- The first projection from `PrimitiveAddChar`, giving the cyclotomic field. -/ n : ℕ+ diff --git a/Mathlib/Order/PrimeIdeal.lean b/Mathlib/Order/PrimeIdeal.lean index e672d2ef9634f..71262162b9097 100644 --- a/Mathlib/Order/PrimeIdeal.lean +++ b/Mathlib/Order/PrimeIdeal.lean @@ -41,8 +41,6 @@ namespace Ideal /-- A pair of an `Order.Ideal` and an `Order.PFilter` which form a partition of `P`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure PrimePair (P : Type*) [Preorder P] where I : Ideal P F : PFilter P diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index 135c80df5e677..6092f3c84aea4 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -950,7 +950,6 @@ variable [IsDedekindDomain R] /-- The height one prime spectrum of a Dedekind domain `R` is the type of nonzero prime ideals of `R`. Note that this equals the maximal spectrum if `R` has Krull dimension 1. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `has_nonempty_instance`, linter doesn't exist yet @[ext, nolint unusedArguments] structure HeightOneSpectrum where asIdeal : Ideal R diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean index d3a7fc8a87136..5db79f945e9dd 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean @@ -88,8 +88,6 @@ section /-- Let `x` be a submonoid of `A`, then `NumDenSameDeg 𝒜 x` is a structure with a numerator and a denominator with same grading such that the denominator is contained in `x`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure NumDenSameDeg where deg : ι (num den : 𝒜 deg) @@ -271,8 +269,6 @@ end HomogeneousLocalization kernel of `embedding 𝒜 x`. This is essentially the subring of `Aₓ` where the numerator and denominator share the same grading. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] def HomogeneousLocalization : Type _ := Quotient (Setoid.ker <| HomogeneousLocalization.NumDenSameDeg.embedding 𝒜 x) diff --git a/Mathlib/RingTheory/IsAdjoinRoot.lean b/Mathlib/RingTheory/IsAdjoinRoot.lean index c607d73842aef..cd89996babce3 100644 --- a/Mathlib/RingTheory/IsAdjoinRoot.lean +++ b/Mathlib/RingTheory/IsAdjoinRoot.lean @@ -80,8 +80,6 @@ and `AdjoinRoot` which constructs a new type. This is not a typeclass because the choice of root given `S` and `f` is not unique. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure IsAdjoinRoot {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S] (f : R[X]) : Type max u v where map : R[X] →+* S diff --git a/Mathlib/RingTheory/Perfection.lean b/Mathlib/RingTheory/Perfection.lean index 210e3d6dbc519..a6b3949cd74a8 100644 --- a/Mathlib/RingTheory/Perfection.lean +++ b/Mathlib/RingTheory/Perfection.lean @@ -199,7 +199,6 @@ end Perfection /-- A perfection map to a ring of characteristic `p` is a map that is isomorphic to its perfection. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): This linter does not exist yet. structure PerfectionMap (p : ℕ) [Fact p.Prime] {R : Type u₁} [CommSemiring R] [CharP R p] {P : Type u₂} [CommSemiring P] [CharP P p] [PerfectRing P p] (π : P →+* R) : Prop where injective : ∀ ⦃x y : P⦄, @@ -326,7 +325,7 @@ variable (p : ℕ) -- Porting note: Specified all arguments explicitly /-- `O/(p)` for `O`, ring of integers of `K`. -/ -@[nolint unusedArguments] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `nolint has_nonempty_instance` +@[nolint unusedArguments] def ModP (K : Type u₁) [Field K] (v : Valuation K ℝ≥0) (O : Type u₂) [CommRing O] [Algebra O K] (_ : v.Integers O) (p : ℕ) := O ⧸ (Ideal.span {(p : O)} : Ideal O) @@ -438,7 +437,6 @@ end Classical end ModP /-- Perfection of `O/(p)` where `O` is the ring of integers of `K`. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): This linter does not exist yet. def PreTilt := Ring.Perfection (ModP K v O hv p) p @@ -575,7 +573,6 @@ end PreTilt /-- The tilt of a field, as defined in Perfectoid Spaces by Peter Scholze, as in [scholze2011perfectoid]. Given a field `K` with valuation `K → ℝ≥0` and ring of integers `O`, this is implemented as the fraction field of the perfection of `O/(p)`. -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): This linter does not exist yet. def Tilt [Fact p.Prime] [Fact (v p ≠ 1)] := FractionRing (PreTilt K v O hv p) diff --git a/Mathlib/RingTheory/PowerBasis.lean b/Mathlib/RingTheory/PowerBasis.lean index fc58485528703..c256a2901825b 100644 --- a/Mathlib/RingTheory/PowerBasis.lean +++ b/Mathlib/RingTheory/PowerBasis.lean @@ -54,8 +54,6 @@ This is a structure, not a class, since the same algebra can have many power bas For the common case where `S` is defined by adjoining an integral element to `R`, the canonical power basis is given by `{Algebra,IntermediateField}.adjoin.powerBasis`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. --- @[nolint has_nonempty_instance] structure PowerBasis (R S : Type*) [CommRing R] [Ring S] [Algebra R S] where gen : S dim : ℕ diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index d188fcced5444..e89be5718406d 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -67,7 +67,6 @@ section variable (F R) (Γ₀ : Type*) [LinearOrderedCommMonoidWithZero Γ₀] [Ring R] ---Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] /-- The type of `Γ₀`-valued valuations on `R`. When you extend this structure, make sure to extend `ValuationClass`. -/ @@ -594,7 +593,6 @@ section AddMonoid variable (R) [Ring R] (Γ₀ : Type*) [LinearOrderedAddCommMonoidWithTop Γ₀] /-- The type of `Γ₀`-valued additive valuations on `R`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] def AddValuation := Valuation R (Multiplicative Γ₀ᵒᵈ) diff --git a/Mathlib/RingTheory/WittVector/Isocrystal.lean b/Mathlib/RingTheory/WittVector/Isocrystal.lean index 6686048e8f6fd..12a87d8bc7fe6 100644 --- a/Mathlib/RingTheory/WittVector/Isocrystal.lean +++ b/Mathlib/RingTheory/WittVector/Isocrystal.lean @@ -129,14 +129,12 @@ variable (V) /-- A homomorphism between isocrystals respects the Frobenius map. Notation `M →ᶠⁱ [p, k]` in the `Isocrystal` namespace. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. @[nolint has_nonempty_instance] structure IsocrystalHom extends V →ₗ[K(p, k)] V₂ where frob_equivariant : ∀ x : V, Φ(p, k) (toLinearMap x) = toLinearMap (Φ(p, k) x) /-- An isomorphism between isocrystals respects the Frobenius map. Notation `M ≃ᶠⁱ [p, k]` in the `Isocrystal` namespace. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. @[nolint has_nonempty_instance] structure IsocrystalEquiv extends V ≃ₗ[K(p, k)] V₂ where frob_equivariant : ∀ x : V, Φ(p, k) (toLinearEquiv x) = toLinearEquiv (Φ(p, k) x) @@ -156,7 +154,6 @@ open scoped Isocrystal of slope `m : ℤ`. -/ @[nolint unusedArguments] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. @[nolint has_nonempty_instance] def StandardOneDimIsocrystal (_m : ℤ) : Type _ := K(p, k) diff --git a/Mathlib/Topology/Algebra/Module/Equiv.lean b/Mathlib/Topology/Algebra/Module/Equiv.lean index 8363cb3582442..9df3e155b17c7 100644 --- a/Mathlib/Topology/Algebra/Module/Equiv.lean +++ b/Mathlib/Topology/Algebra/Module/Equiv.lean @@ -30,7 +30,6 @@ variable (R M) /-- Continuous linear equivalences between modules. We only put the type classes that are necessary for the definition, although in applications `M` and `M₂` will be topological modules over the topological semiring `R`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not ported yet; was @[nolint has_nonempty_instance] structure ContinuousLinearEquiv {R : Type*} {S : Type*} [Semiring R] [Semiring S] (σ : R →+* S) {σ' : S →+* R} [RingHomInvPair σ σ'] [RingHomInvPair σ' σ] (M : Type*) [TopologicalSpace M] [AddCommMonoid M] (M₂ : Type*) [TopologicalSpace M₂] [AddCommMonoid M₂] [Module R M] diff --git a/Mathlib/Topology/Connected/PathConnected.lean b/Mathlib/Topology/Connected/PathConnected.lean index 47f59cf4a2bd6..ca9630572492f 100644 --- a/Mathlib/Topology/Connected/PathConnected.lean +++ b/Mathlib/Topology/Connected/PathConnected.lean @@ -67,7 +67,6 @@ variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] {x y z : X} {ι /-! ### Paths -/ /-- Continuous path connecting two points `x` and `y` in a topological space -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] structure Path (x y : X) extends C(I, X) where /-- The start point of a `Path`. -/ source' : toFun 0 = x diff --git a/Mathlib/Topology/FiberBundle/Basic.lean b/Mathlib/Topology/FiberBundle/Basic.lean index 09a6da952e60f..d90ef77d7c2dd 100644 --- a/Mathlib/Topology/FiberBundle/Basic.lean +++ b/Mathlib/Topology/FiberBundle/Basic.lean @@ -391,7 +391,6 @@ Trivialization changes from `i` to `j` are given by continuous maps `coordChange `baseSet i ∩ baseSet j` to the set of homeomorphisms of `F`, but we express them as maps `B → F → F` and require continuity on `(baseSet i ∩ baseSet j) × F` to avoid the topology on the space of continuous maps on `F`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure FiberBundleCore (ι : Type*) (B : Type*) [TopologicalSpace B] (F : Type*) [TopologicalSpace F] where baseSet : ι → Set B @@ -410,7 +409,7 @@ namespace FiberBundleCore variable [TopologicalSpace B] [TopologicalSpace F] (Z : FiberBundleCore ι B F) /-- The index set of a fiber bundle core, as a convenience function for dot notation -/ -@[nolint unusedArguments] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was has_nonempty_instance +@[nolint unusedArguments] def Index (_Z : FiberBundleCore ι B F) := ι /-- The base space of a fiber bundle core, as a convenience function for dot notation -/ @@ -419,7 +418,7 @@ def Base (_Z : FiberBundleCore ι B F) := B /-- The fiber of a fiber bundle core, as a convenience function for dot notation and typeclass inference -/ -@[nolint unusedArguments] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was has_nonempty_instance +@[nolint unusedArguments] def Fiber (_ : FiberBundleCore ι B F) (_x : B) := F instance topologicalSpaceFiber (x : B) : TopologicalSpace (Z.Fiber x) := ‹_› @@ -720,7 +719,6 @@ variable (E : B → Type*) [TopologicalSpace B] [TopologicalSpace F] equivalences but there is not yet a topology on the total space. The total space is hence given a topology in such a way that there is a fiber bundle structure for which the partial equivalences are also partial homeomorphisms and hence local trivializations. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure FiberPrebundle where pretrivializationAtlas : Set (Pretrivialization F (π F E)) pretrivializationAt : B → Pretrivialization F (π F E) diff --git a/Mathlib/Topology/FiberBundle/Trivialization.lean b/Mathlib/Topology/FiberBundle/Trivialization.lean index 2652c7590a667..f15bd8790c419 100644 --- a/Mathlib/Topology/FiberBundle/Trivialization.lean +++ b/Mathlib/Topology/FiberBundle/Trivialization.lean @@ -262,7 +262,6 @@ variable [TopologicalSpace Z] [TopologicalSpace (TotalSpace F E)] `proj : Z → B` with fiber `F`, as a partial homeomorphism between `Z` and `B × F` defined between two sets of the form `proj ⁻¹' baseSet` and `baseSet × F`, acting trivially on the first coordinate. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure Trivialization (proj : Z → B) extends PartialHomeomorph Z (B × F) where baseSet : Set B open_baseSet : IsOpen baseSet diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index 681b44bc53a60..ca721bddc94f1 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -82,7 +82,6 @@ that the `U i`'s are open subspaces of the glued space. Most of the times it would be easier to use the constructor `TopCat.GlueData.mk'` where the conditions are stated in a less categorical way. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] structure GlueData extends CategoryTheory.GlueData TopCat where f_open : ∀ i j, IsOpenEmbedding (f i j) f_mono i j := (TopCat.mono_iff_injective _).mpr (f_open i j).isEmbedding.injective @@ -304,7 +303,6 @@ such that We can then glue the topological spaces `U i` together by identifying `V i j` with `V j i`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed `@[nolint has_nonempty_instance]` structure MkCore where {J : Type u} U : J → TopCat.{u} diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean index c1899369609a7..a564dcfd1a909 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean @@ -85,7 +85,6 @@ instance : Inhabited GHSpace := ⟨Quot.mk _ ⟨⟨{0}, isCompact_singleton⟩, singleton_nonempty _⟩⟩ /-- A metric space representative of any abstract point in `GHSpace` -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not yet ported; removed @[nolint has_nonempty_instance]; why? def GHSpace.Rep (p : GHSpace) : Type := (Quotient.out p : NonemptyCompacts ℓ_infty_ℝ) diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean index c7494ebd7c280..f0124bb1d3151 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean @@ -445,7 +445,6 @@ def premetricOptimalGHDist : PseudoMetricSpace (X ⊕ Y) where attribute [local instance] premetricOptimalGHDist /-- A metric space which realizes the optimal coupling between `X` and `Y` -/ --- @[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): This linter does not exist yet. def OptimalGHCoupling : Type _ := @SeparationQuotient (X ⊕ Y) (premetricOptimalGHDist X Y).toUniformSpace.toTopologicalSpace diff --git a/Mathlib/Topology/MetricSpace/Isometry.lean b/Mathlib/Topology/MetricSpace/Isometry.lean index b4b370cbcce52..8857a7993af8a 100644 --- a/Mathlib/Topology/MetricSpace/Isometry.lean +++ b/Mathlib/Topology/MetricSpace/Isometry.lean @@ -272,7 +272,6 @@ theorem MetricSpace.isometry_induced (f : α → β) (hf : f.Injective) [m : Met -- such a bijection need not exist /-- `α` and `β` are isometric if there is an isometric bijection between them. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure IsometryEquiv (α : Type u) (β : Type v) [PseudoEMetricSpace α] [PseudoEMetricSpace β] extends α ≃ β where isometry_toFun : Isometry toFun diff --git a/Mathlib/Topology/MetricSpace/Polish.lean b/Mathlib/Topology/MetricSpace/Polish.lean index 543d4da8c0d76..4762d0f29d1bb 100644 --- a/Mathlib/Topology/MetricSpace/Polish.lean +++ b/Mathlib/Topology/MetricSpace/Polish.lean @@ -235,7 +235,6 @@ variable [MetricSpace α] {s : Opens α} /-- A type synonym for a subset `s` of a metric space, on which we will construct another metric for which it will be complete. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] def CompleteCopy {α : Type*} [MetricSpace α] (s : Opens α) : Type _ := s namespace CompleteCopy diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index a6da5bc6bc39a..a6835d7101dd5 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -49,7 +49,6 @@ variable {X X' : Type*} {Y Y' : Type*} {Z Z' : Type*} [TopologicalSpace Z] [TopologicalSpace Z'] /-- Partial homeomorphisms, defined on open subsets of the space -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. @[nolint has_nonempty_instance] structure PartialHomeomorph (X : Type*) (Y : Type*) [TopologicalSpace X] [TopologicalSpace Y] extends PartialEquiv X Y where open_source : IsOpen source diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index d509f463163f3..f35935ec8b97b 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -38,7 +38,6 @@ variable (C : Type u) [Category.{v} C] namespace TopCat /-- The category of `C`-valued presheaves on a (bundled) topological space `X`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] def Presheaf (X : TopCat.{w}) : Type max u v w := (Opens X)ᵒᵖ ⥤ C diff --git a/Mathlib/Topology/ShrinkingLemma.lean b/Mathlib/Topology/ShrinkingLemma.lean index efcf49d420ddd..40c9acfeeb8ef 100644 --- a/Mathlib/Topology/ShrinkingLemma.lean +++ b/Mathlib/Topology/ShrinkingLemma.lean @@ -46,7 +46,6 @@ namespace ShrinkingLemma This type is equipped with the following partial order: `v ≤ v'` if `v.carrier ⊆ v'.carrier` and `v i = v' i` for `i ∈ v.carrier`. We will use Zorn's lemma to prove that this type has a maximal element, then show that the maximal element must have `carrier = univ`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. @[nolint has_nonempty_instance] @[ext] structure PartialRefinement (u : ι → Set X) (s : Set X) (p : Set X → Prop) where /-- A family of sets that form a partial refinement of `u`. -/ toFun : ι → Set X diff --git a/Mathlib/Topology/UniformSpace/Equiv.lean b/Mathlib/Topology/UniformSpace/Equiv.lean index 8f0d5e13b5aaf..53230fada3f82 100644 --- a/Mathlib/Topology/UniformSpace/Equiv.lean +++ b/Mathlib/Topology/UniformSpace/Equiv.lean @@ -30,7 +30,6 @@ variable {α : Type u} {β : Type*} {γ : Type*} {δ : Type*} -- not all spaces are homeomorphic to each other /-- Uniform isomorphism between `α` and `β` -/ ---@[nolint has_nonempty_instance] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): linter not yet ported structure UniformEquiv (α : Type*) (β : Type*) [UniformSpace α] [UniformSpace β] extends α ≃ β where /-- Uniform continuity of the function -/ diff --git a/Mathlib/Topology/VectorBundle/Basic.lean b/Mathlib/Topology/VectorBundle/Basic.lean index 9ba91b204f66f..6ac2a4a88260c 100644 --- a/Mathlib/Topology/VectorBundle/Basic.lean +++ b/Mathlib/Topology/VectorBundle/Basic.lean @@ -534,7 +534,7 @@ theorem coordChange_linear_comp (i j k : ι) : exact Z.coordChange_comp i j k x hx v /-- The index set of a vector bundle core, as a convenience function for dot notation -/ -@[nolint unusedArguments] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was `nolint has_nonempty_instance` +@[nolint unusedArguments] def Index := ι /-- The base space of a vector bundle core, as a convenience function for dot notation -/ @@ -543,7 +543,7 @@ def Base := B /-- The fiber of a vector bundle core, as a convenience function for dot notation and typeclass inference -/ -@[nolint unusedArguments] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was `nolint has_nonempty_instance` +@[nolint unusedArguments] def Fiber : B → Type _ := Z.toFiberBundleCore.Fiber @@ -745,7 +745,6 @@ The field `exists_coordChange` is stated as an existential statement (instead of fields), since it depends on propositional information (namely `e e' ∈ pretrivializationAtlas`). This makes it inconvenient to explicitly define a `coordChange` function when constructing a `VectorPrebundle`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): was @[nolint has_nonempty_instance] structure VectorPrebundle where pretrivializationAtlas : Set (Pretrivialization F (π F E)) pretrivialization_linear' : ∀ e, e ∈ pretrivializationAtlas → e.IsLinear R From 6e428275bcb67340667d836d8739cd0f9a23ea4b Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Tue, 21 Jan 2025 03:27:03 +0000 Subject: [PATCH 363/681] chore(Data/List/Basic): split off Map2 lemmas (#20832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR splits off a number of lemmas related maps that zip pairs of lists from `Data.List.Basic` to a new file, including: * `map₂Left'` * `map₂Right'` * `zipWith` * `zipLeft'` * `zipRight'` Doing so reduces the size of this long file by ~250 lines. Also note that the new file doesn't need to import `Basic`, so this should parallelize the compilation too. --- Mathlib.lean | 1 + Mathlib/Data/List/Basic.lean | 236 +----------------------------- Mathlib/Data/List/Map2.lean | 274 +++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+), 235 deletions(-) create mode 100644 Mathlib/Data/List/Map2.lean diff --git a/Mathlib.lean b/Mathlib.lean index f16130975e6c6..8aa9afd9c04aa 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2688,6 +2688,7 @@ import Mathlib.Data.List.Iterate import Mathlib.Data.List.Lattice import Mathlib.Data.List.Lemmas import Mathlib.Data.List.Lex +import Mathlib.Data.List.Map2 import Mathlib.Data.List.MinMax import Mathlib.Data.List.Monad import Mathlib.Data.List.NatAntidiagonal diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 8955bf6337362..72a87d4cdaa72 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -965,21 +965,6 @@ end map_bijectivity theorem eq_of_mem_map_const {b₁ b₂ : β} {l : List α} (h : b₁ ∈ map (const α b₂) l) : b₁ = b₂ := by rw [map_const] at h; exact eq_of_mem_replicate h -/-! ### zipWith -/ - -theorem nil_zipWith (f : α → β → γ) (l : List β) : zipWith f [] l = [] := by cases l <;> rfl - -theorem zipWith_nil (f : α → β → γ) (l : List α) : zipWith f l [] = [] := by cases l <;> rfl - -@[simp] -theorem zipWith_flip (f : α → β → γ) : ∀ as bs, zipWith (flip f) bs as = zipWith f as bs - | [], [] => rfl - | [], _ :: _ => rfl - | _ :: _, [] => rfl - | a :: as, b :: bs => by - simp! [zipWith_flip] - rfl - /-! ### take, drop -/ @[simp] lemma take_eq_self_iff (x : List α) {n : ℕ} : x.take n = x ↔ x.length ≤ n := @@ -1966,225 +1951,6 @@ theorem choose_property (hp : ∃ a, a ∈ l ∧ p a) : p (choose p l hp) := end Choose -/-! ### map₂Left' -/ - -section Map₂Left' - --- The definitional equalities for `map₂Left'` can already be used by the --- simplifier because `map₂Left'` is marked `@[simp]`. -@[simp] -theorem map₂Left'_nil_right (f : α → Option β → γ) (as) : - map₂Left' f as [] = (as.map fun a => f a none, []) := by cases as <;> rfl - -end Map₂Left' - -/-! ### map₂Right' -/ - -section Map₂Right' - -variable (f : Option α → β → γ) (a : α) (as : List α) (b : β) (bs : List β) - -@[simp] -theorem map₂Right'_nil_left : map₂Right' f [] bs = (bs.map (f none), []) := by cases bs <;> rfl - -@[simp] -theorem map₂Right'_nil_right : map₂Right' f as [] = ([], as) := - rfl - -@[simp] -theorem map₂Right'_nil_cons : map₂Right' f [] (b :: bs) = (f none b :: bs.map (f none), []) := - rfl - -@[simp] -theorem map₂Right'_cons_cons : - map₂Right' f (a :: as) (b :: bs) = - let r := map₂Right' f as bs - (f (some a) b :: r.fst, r.snd) := - rfl - -end Map₂Right' - -/-! ### zipLeft' -/ - -section ZipLeft' - -variable (a : α) (as : List α) (b : β) (bs : List β) - -@[simp] -theorem zipLeft'_nil_right : zipLeft' as ([] : List β) = (as.map fun a => (a, none), []) := by - cases as <;> rfl - -@[simp] -theorem zipLeft'_nil_left : zipLeft' ([] : List α) bs = ([], bs) := - rfl - -@[simp] -theorem zipLeft'_cons_nil : - zipLeft' (a :: as) ([] : List β) = ((a, none) :: as.map fun a => (a, none), []) := - rfl - -@[simp] -theorem zipLeft'_cons_cons : - zipLeft' (a :: as) (b :: bs) = - let r := zipLeft' as bs - ((a, some b) :: r.fst, r.snd) := - rfl - -end ZipLeft' - -/-! ### zipRight' -/ - -section ZipRight' - -variable (a : α) (as : List α) (b : β) (bs : List β) - -@[simp] -theorem zipRight'_nil_left : zipRight' ([] : List α) bs = (bs.map fun b => (none, b), []) := by - cases bs <;> rfl - -@[simp] -theorem zipRight'_nil_right : zipRight' as ([] : List β) = ([], as) := - rfl - -@[simp] -theorem zipRight'_nil_cons : - zipRight' ([] : List α) (b :: bs) = ((none, b) :: bs.map fun b => (none, b), []) := - rfl - -@[simp] -theorem zipRight'_cons_cons : - zipRight' (a :: as) (b :: bs) = - let r := zipRight' as bs - ((some a, b) :: r.fst, r.snd) := - rfl - -end ZipRight' - -/-! ### map₂Left -/ - -section Map₂Left - -variable (f : α → Option β → γ) (as : List α) - --- The definitional equalities for `map₂Left` can already be used by the --- simplifier because `map₂Left` is marked `@[simp]`. -@[simp] -theorem map₂Left_nil_right : map₂Left f as [] = as.map fun a => f a none := by cases as <;> rfl - -theorem map₂Left_eq_map₂Left' : ∀ as bs, map₂Left f as bs = (map₂Left' f as bs).fst - | [], _ => by simp - | a :: as, [] => by simp - | a :: as, b :: bs => by simp [map₂Left_eq_map₂Left'] - -theorem map₂Left_eq_zipWith : - ∀ as bs, length as ≤ length bs → map₂Left f as bs = zipWith (fun a b => f a (some b)) as bs - | [], [], _ => by simp - | [], _ :: _, _ => by simp - | a :: as, [], h => by - simp at h - | a :: as, b :: bs, h => by - simp only [length_cons, succ_le_succ_iff] at h - simp [h, map₂Left_eq_zipWith] - -end Map₂Left - -/-! ### map₂Right -/ - -section Map₂Right - -variable (f : Option α → β → γ) (a : α) (as : List α) (b : β) (bs : List β) - -@[simp] -theorem map₂Right_nil_left : map₂Right f [] bs = bs.map (f none) := by cases bs <;> rfl - -@[simp] -theorem map₂Right_nil_right : map₂Right f as [] = [] := - rfl - -@[simp] -theorem map₂Right_nil_cons : map₂Right f [] (b :: bs) = f none b :: bs.map (f none) := - rfl - -@[simp] -theorem map₂Right_cons_cons : - map₂Right f (a :: as) (b :: bs) = f (some a) b :: map₂Right f as bs := - rfl - -theorem map₂Right_eq_map₂Right' : map₂Right f as bs = (map₂Right' f as bs).fst := by - simp only [map₂Right, map₂Right', map₂Left_eq_map₂Left'] - -theorem map₂Right_eq_zipWith (h : length bs ≤ length as) : - map₂Right f as bs = zipWith (fun a b => f (some a) b) as bs := by - have : (fun a b => flip f a (some b)) = flip fun a b => f (some a) b := rfl - simp only [map₂Right, map₂Left_eq_zipWith, zipWith_flip, *] - -end Map₂Right - -/-! ### zipLeft -/ - -section ZipLeft - -variable (a : α) (as : List α) (b : β) (bs : List β) - -@[simp] -theorem zipLeft_nil_right : zipLeft as ([] : List β) = as.map fun a => (a, none) := by - cases as <;> rfl - -@[simp] -theorem zipLeft_nil_left : zipLeft ([] : List α) bs = [] := - rfl - -@[simp] -theorem zipLeft_cons_nil : - zipLeft (a :: as) ([] : List β) = (a, none) :: as.map fun a => (a, none) := - rfl - -@[simp] -theorem zipLeft_cons_cons : zipLeft (a :: as) (b :: bs) = (a, some b) :: zipLeft as bs := - rfl - --- Porting note: arguments explicit for recursion -theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by - rw [zipLeft, zipLeft'] - cases as with - | nil => rfl - | cons _ atl => - cases bs with - | nil => rfl - | cons _ btl => - rw [zipWithLeft, zipWithLeft', cons_inj_right] - exact @zipLeft_eq_zipLeft' atl btl - -end ZipLeft - -/-! ### zipRight -/ - -section ZipRight - -variable (a : α) (as : List α) (b : β) (bs : List β) - -@[simp] -theorem zipRight_nil_left : zipRight ([] : List α) bs = bs.map fun b => (none, b) := by - cases bs <;> rfl - -@[simp] -theorem zipRight_nil_right : zipRight as ([] : List β) = [] := - rfl - -@[simp] -theorem zipRight_nil_cons : - zipRight ([] : List α) (b :: bs) = (none, b) :: bs.map fun b => (none, b) := - rfl - -@[simp] -theorem zipRight_cons_cons : zipRight (a :: as) (b :: bs) = (some a, b) :: zipRight as bs := - rfl - -theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by - induction as generalizing bs <;> cases bs <;> simp [*] - -end ZipRight - /-! ### Forall -/ section Forall @@ -2321,4 +2087,4 @@ end lookup end List -set_option linter.style.longFile 2400 +set_option linter.style.longFile 2200 diff --git a/Mathlib/Data/List/Map2.lean b/Mathlib/Data/List/Map2.lean new file mode 100644 index 0000000000000..bea17d98be9f5 --- /dev/null +++ b/Mathlib/Data/List/Map2.lean @@ -0,0 +1,274 @@ +/- +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 +-/ +import Mathlib.Data.List.Defs +import Mathlib.Tactic.Common + +/-! +# Map₂ Lemmas + +This file contains additional lemmas about a number of list functions related to combining zipping +Lists together. In particular, we include lemmas about: + +* `map₂Left'` +* `map₂Right'` +* `zipWith` +* `zipLeft'` +* `zipRight'` + +-/ + +assert_not_exists GroupWithZero +assert_not_exists Lattice +assert_not_exists Prod.swap_eq_iff_eq_swap +assert_not_exists Ring +assert_not_exists Set.range + +open Function + +open Nat hiding one_pos + +namespace List + +universe u v w + +variable {ι : Type*} {α : Type u} {β : Type v} {γ : Type w} {l₁ l₂ : List α} + +/-! ### map₂Left' -/ + +section Map₂Left' + +-- The definitional equalities for `map₂Left'` can already be used by the +-- simplifier because `map₂Left'` is marked `@[simp]`. +@[simp] +theorem map₂Left'_nil_right (f : α → Option β → γ) (as) : + map₂Left' f as [] = (as.map fun a => f a none, []) := by cases as <;> rfl + +end Map₂Left' + +/-! ### map₂Right' -/ + +section Map₂Right' + +variable (f : Option α → β → γ) (a : α) (as : List α) (b : β) (bs : List β) + +@[simp] +theorem map₂Right'_nil_left : map₂Right' f [] bs = (bs.map (f none), []) := by cases bs <;> rfl + +@[simp] +theorem map₂Right'_nil_right : map₂Right' f as [] = ([], as) := + rfl + +@[simp] +theorem map₂Right'_nil_cons : map₂Right' f [] (b :: bs) = (f none b :: bs.map (f none), []) := + rfl + +@[simp] +theorem map₂Right'_cons_cons : + map₂Right' f (a :: as) (b :: bs) = + let r := map₂Right' f as bs + (f (some a) b :: r.fst, r.snd) := + rfl + +end Map₂Right' + +/-! ### zipWith -/ + +theorem nil_zipWith (f : α → β → γ) (l : List β) : zipWith f [] l = [] := by cases l <;> rfl + +theorem zipWith_nil (f : α → β → γ) (l : List α) : zipWith f l [] = [] := by cases l <;> rfl + +@[simp] +theorem zipWith_flip (f : α → β → γ) : ∀ as bs, zipWith (flip f) bs as = zipWith f as bs + | [], [] => rfl + | [], _ :: _ => rfl + | _ :: _, [] => rfl + | a :: as, b :: bs => by + simp! [zipWith_flip] + rfl + + +/-! ### zipLeft' -/ + +section ZipLeft' + +variable (a : α) (as : List α) (b : β) (bs : List β) + +@[simp] +theorem zipLeft'_nil_right : zipLeft' as ([] : List β) = (as.map fun a => (a, none), []) := by + cases as <;> rfl + +@[simp] +theorem zipLeft'_nil_left : zipLeft' ([] : List α) bs = ([], bs) := + rfl + +@[simp] +theorem zipLeft'_cons_nil : + zipLeft' (a :: as) ([] : List β) = ((a, none) :: as.map fun a => (a, none), []) := + rfl + +@[simp] +theorem zipLeft'_cons_cons : + zipLeft' (a :: as) (b :: bs) = + let r := zipLeft' as bs + ((a, some b) :: r.fst, r.snd) := + rfl + +end ZipLeft' + +/-! ### zipRight' -/ + +section ZipRight' + +variable (a : α) (as : List α) (b : β) (bs : List β) + +@[simp] +theorem zipRight'_nil_left : zipRight' ([] : List α) bs = (bs.map fun b => (none, b), []) := by + cases bs <;> rfl + +@[simp] +theorem zipRight'_nil_right : zipRight' as ([] : List β) = ([], as) := + rfl + +@[simp] +theorem zipRight'_nil_cons : + zipRight' ([] : List α) (b :: bs) = ((none, b) :: bs.map fun b => (none, b), []) := + rfl + +@[simp] +theorem zipRight'_cons_cons : + zipRight' (a :: as) (b :: bs) = + let r := zipRight' as bs + ((some a, b) :: r.fst, r.snd) := + rfl + +end ZipRight' + +/-! ### map₂Left -/ + +section Map₂Left + +variable (f : α → Option β → γ) (as : List α) + +-- The definitional equalities for `map₂Left` can already be used by the +-- simplifier because `map₂Left` is marked `@[simp]`. +@[simp] +theorem map₂Left_nil_right : map₂Left f as [] = as.map fun a => f a none := by cases as <;> rfl + +theorem map₂Left_eq_map₂Left' : ∀ as bs, map₂Left f as bs = (map₂Left' f as bs).fst + | [], _ => by simp + | a :: as, [] => by simp + | a :: as, b :: bs => by simp [map₂Left_eq_map₂Left'] + +theorem map₂Left_eq_zipWith : + ∀ as bs, length as ≤ length bs → map₂Left f as bs = zipWith (fun a b => f a (some b)) as bs + | [], [], _ => by simp + | [], _ :: _, _ => by simp + | a :: as, [], h => by + simp at h + | a :: as, b :: bs, h => by + simp only [length_cons, succ_le_succ_iff] at h + simp [h, map₂Left_eq_zipWith] + +end Map₂Left + +/-! ### map₂Right -/ + +section Map₂Right + +variable (f : Option α → β → γ) (a : α) (as : List α) (b : β) (bs : List β) + +@[simp] +theorem map₂Right_nil_left : map₂Right f [] bs = bs.map (f none) := by cases bs <;> rfl + +@[simp] +theorem map₂Right_nil_right : map₂Right f as [] = [] := + rfl + +@[simp] +theorem map₂Right_nil_cons : map₂Right f [] (b :: bs) = f none b :: bs.map (f none) := + rfl + +@[simp] +theorem map₂Right_cons_cons : + map₂Right f (a :: as) (b :: bs) = f (some a) b :: map₂Right f as bs := + rfl + +theorem map₂Right_eq_map₂Right' : map₂Right f as bs = (map₂Right' f as bs).fst := by + simp only [map₂Right, map₂Right', map₂Left_eq_map₂Left'] + +theorem map₂Right_eq_zipWith (h : length bs ≤ length as) : + map₂Right f as bs = zipWith (fun a b => f (some a) b) as bs := by + have : (fun a b => flip f a (some b)) = flip fun a b => f (some a) b := rfl + simp only [map₂Right, map₂Left_eq_zipWith, zipWith_flip, *] + +end Map₂Right + +/-! ### zipLeft -/ + +section ZipLeft + +variable (a : α) (as : List α) (b : β) (bs : List β) + +@[simp] +theorem zipLeft_nil_right : zipLeft as ([] : List β) = as.map fun a => (a, none) := by + cases as <;> rfl + +@[simp] +theorem zipLeft_nil_left : zipLeft ([] : List α) bs = [] := + rfl + +@[simp] +theorem zipLeft_cons_nil : + zipLeft (a :: as) ([] : List β) = (a, none) :: as.map fun a => (a, none) := + rfl + +@[simp] +theorem zipLeft_cons_cons : zipLeft (a :: as) (b :: bs) = (a, some b) :: zipLeft as bs := + rfl + +-- Porting note: arguments explicit for recursion +theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by + rw [zipLeft, zipLeft'] + cases as with + | nil => rfl + | cons _ atl => + cases bs with + | nil => rfl + | cons _ btl => + rw [zipWithLeft, zipWithLeft', cons_inj_right] + exact @zipLeft_eq_zipLeft' atl btl + +end ZipLeft + +/-! ### zipRight -/ + +section ZipRight + +variable (a : α) (as : List α) (b : β) (bs : List β) + +@[simp] +theorem zipRight_nil_left : zipRight ([] : List α) bs = bs.map fun b => (none, b) := by + cases bs <;> rfl + +@[simp] +theorem zipRight_nil_right : zipRight as ([] : List β) = [] := + rfl + +@[simp] +theorem zipRight_nil_cons : + zipRight ([] : List α) (b :: bs) = (none, b) :: bs.map fun b => (none, b) := + rfl + +@[simp] +theorem zipRight_cons_cons : zipRight (a :: as) (b :: bs) = (some a, b) :: zipRight as bs := + rfl + +theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by + induction as generalizing bs <;> cases bs <;> simp [*] + +end ZipRight + +end List From f8fdf2452d6a065d58d9552b212fc06499a8564b Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Tue, 21 Jan 2025 03:27:05 +0000 Subject: [PATCH 364/681] doc(Algebra): mention counterexamples, add links to MathOverflow (#20889) Also slightly golf two proofs. --- Mathlib/LinearAlgebra/Dimension/Basic.lean | 1 + Mathlib/RingTheory/Algebraic/Integral.lean | 13 +++++++++++++ .../IntegralClosure/IsIntegralClosure/Basic.lean | 4 ++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Mathlib/LinearAlgebra/Dimension/Basic.lean b/Mathlib/LinearAlgebra/Dimension/Basic.lean index 6d009c49a152c..403f3c596d79d 100644 --- a/Mathlib/LinearAlgebra/Dimension/Basic.lean +++ b/Mathlib/LinearAlgebra/Dimension/Basic.lean @@ -48,6 +48,7 @@ variable (R M) /-- The rank of a module, defined as a term of type `Cardinal`. We define this as the supremum of the cardinalities of linearly independent subsets. +The supremum may not be attained, see https://mathoverflow.net/a/263053. For a free module over any ring satisfying the strong rank condition (e.g. left-noetherian rings, commutative rings, and in particular division rings and fields), diff --git a/Mathlib/RingTheory/Algebraic/Integral.lean b/Mathlib/RingTheory/Algebraic/Integral.lean index 5a9c3fa6e04f6..625d736514f0f 100644 --- a/Mathlib/RingTheory/Algebraic/Integral.lean +++ b/Mathlib/RingTheory/Algebraic/Integral.lean @@ -211,6 +211,16 @@ section trans variable (R) [NoZeroDivisors S] (inj : Function.Injective (algebraMap S A)) include inj +/-! +The next theorem may fail if only `R` is assumed to be a domain but `S` is not: for example, let +`S = R[X] ⧸ (X² - X)` and let `A` be the subalgebra of `S[Y]` generated by `XY`. +`A` is algebraic over `S` because any element `∑ᵢ sᵢ(XY)ⁱ` is a root of the polynomial +`(X - 1)(Z - s₀)` in `S[Z]`, because `X(X - 1) = X² - X = 0` in `S`. +However, `XY` is a transcendental element in `A` over `R`, because `∑ᵢ rᵢ(XY)ⁱ = 0` in `S[Y]` +implies all `rᵢXⁱ = 0` (i.e., `r₀ = 0` and `rᵢX = 0` for `i > 0`) in `S`, +which implies `rᵢ = 0` in `R`. This example is inspired by the comment +https://mathoverflow.net/questions/482944/when-do-algebraic-elements-form-a-subalgebra#comment1257632_482944. -/ + theorem restrictScalars_of_isIntegral [int : Algebra.IsIntegral R S] {a : A} (h : IsAlgebraic S a) : IsAlgebraic R a := by by_cases hRS : Function.Injective (algebraMap R S) @@ -358,6 +368,9 @@ theorem Algebra.isAlgebraic_adjoin_of_nonempty [NoZeroDivisors R] {s : Set S} (h have := (isDomain_iff_noZeroDivisors_and_nontrivial _).mpr ⟨‹_›, (h x hx).nontrivial⟩ isAlgebraic_adjoin_iff.mpr h⟩ +/-- In an algebra generated by a single algebraic element over a domain `R`, every element is +algebraic. This may fail when `R` is not a domain: see https://mathoverflow.net/a/132192/ for +an example. -/ theorem Algebra.isAlgebraic_adjoin_singleton_iff [NoZeroDivisors R] {s : S} : (adjoin R {s}).IsAlgebraic ↔ IsAlgebraic R s := (isAlgebraic_adjoin_of_nonempty <| Set.singleton_nonempty s).trans forall_eq diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean index 5b810da90a937..c62e33c4ab1b2 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean @@ -56,7 +56,7 @@ theorem IsIntegral.inv_mem_adjoin (int : IsIntegral R x) : x⁻¹ ∈ adjoin R { /-- The inverse of an integral element in a subalgebra of a division ring over a field also lies in that subalgebra. -/ theorem IsIntegral.inv_mem (int : IsIntegral R x) (hx : x ∈ A) : x⁻¹ ∈ A := - adjoin_le_iff.mpr (Set.singleton_subset_iff.mpr hx) int.inv_mem_adjoin + adjoin_le (Set.singleton_subset_iff.mpr hx) int.inv_mem_adjoin /-- An integral subalgebra of a division ring over a field is closed under inverses. -/ theorem Algebra.IsIntegral.inv_mem [Algebra.IsIntegral R A] (hx : x ∈ A) : x⁻¹ ∈ A := @@ -133,7 +133,7 @@ theorem le_integralClosure_iff_isIntegral {S : Subalgebra R A} : theorem Algebra.IsIntegral.adjoin {S : Set A} (hS : ∀ x ∈ S, IsIntegral R x) : Algebra.IsIntegral R (Algebra.adjoin R S) := - le_integralClosure_iff_isIntegral.mp <| adjoin_le_iff.mpr hS + le_integralClosure_iff_isIntegral.mp <| adjoin_le hS theorem integralClosure_eq_top_iff : integralClosure R A = ⊤ ↔ Algebra.IsIntegral R A := by rw [← top_le_iff, le_integralClosure_iff_isIntegral, From 33d9a863eba6b27e0ecc388e5ba93c408f0cfcce Mon Sep 17 00:00:00 2001 From: grunweg Date: Tue, 21 Jan 2025 04:10:26 +0000 Subject: [PATCH 365/681] feat: the disjoint union of smooth manifolds (#20659) - the disjoint union of smooth manifolds is a smooth manifold - the interior and boundary are the disjoint union of the interior and boundary; the disjoint union of boundaryless manifolds is boundaryless A future PR will prove that `Sum.inl` and `Sum.inr` between `C^n` manifolds are C^n. From my bordism theory branch. --- Mathlib/Data/Set/Basic.lean | 5 + Mathlib/Data/Sum/Basic.lean | 2 + .../Geometry/Manifold/InteriorBoundary.lean | 133 +++++++++++++++++- Mathlib/Geometry/Manifold/IsManifold.lean | 55 +++++++- Mathlib/Topology/PartialHomeomorph.lean | 34 ++++- 5 files changed, 221 insertions(+), 8 deletions(-) diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 8e3156f8d4973..09da257d2220c 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -1353,6 +1353,11 @@ theorem compl_univ_iff {s : Set α} : sᶜ = univ ↔ s = ∅ := theorem compl_ne_univ : sᶜ ≠ univ ↔ s.Nonempty := compl_univ_iff.not.trans nonempty_iff_ne_empty.symm +lemma inl_compl_union_inr_compl {α β : Type*} {s : Set α} {t : Set β} : + Sum.inl '' sᶜ ∪ Sum.inr '' tᶜ = (Sum.inl '' s ∪ Sum.inr '' t)ᶜ := by + rw [compl_union] + aesop + theorem nonempty_compl : sᶜ.Nonempty ↔ s ≠ univ := (ne_univ_iff_exists_not_mem s).symm diff --git a/Mathlib/Data/Sum/Basic.lean b/Mathlib/Data/Sum/Basic.lean index 5dd68ca13d171..30d502873b139 100644 --- a/Mathlib/Data/Sum/Basic.lean +++ b/Mathlib/Data/Sum/Basic.lean @@ -17,6 +17,8 @@ universe u v w x variable {α : Type u} {α' : Type w} {β : Type v} {β' : Type x} {γ δ : Type*} +lemma not_isLeft_and_isRight {x : α ⊕ β} : ¬(x.isLeft ∧ x.isRight) := by simp + namespace Sum -- Lean has removed the `@[simp]` attribute on these. For now Mathlib adds it back. diff --git a/Mathlib/Geometry/Manifold/InteriorBoundary.lean b/Mathlib/Geometry/Manifold/InteriorBoundary.lean index d3f2825cc0551..7f6c2a06f8852 100644 --- a/Mathlib/Geometry/Manifold/InteriorBoundary.lean +++ b/Mathlib/Geometry/Manifold/InteriorBoundary.lean @@ -28,6 +28,13 @@ of `M` and `N`. - `ModelWithCorners.boundary_prod`: the boundary of `M × N` is `∂M × N ∪ (M × ∂N)`. - `ModelWithCorners.BoundarylessManifold.prod`: if `M` and `N` are boundaryless, so is `M × N` +- `ModelWithCorners.interior_disjointUnion`: the interior of a disjoint union `M ⊔ M'` + is the union of the interior of `M` and `M'` +- `ModelWithCorners.boundary_disjointUnion`: the boundary of a disjoint union `M ⊔ M'` + is the union of the boundaries of `M` and `M'` +- `ModelWithCorners.boundaryless_disjointUnion`: if `M` and `M'` are boundaryless, + so is their disjoint union `M ⊔ M'` + ## Tags manifold, interior, boundary @@ -85,7 +92,7 @@ lemma isBoundaryPoint_iff {x : M} : I.IsBoundaryPoint x ↔ extChartAt I x x ∈ lemma isInteriorPoint_or_isBoundaryPoint (x : M) : I.IsInteriorPoint x ∨ I.IsBoundaryPoint x := by rw [IsInteriorPoint, or_iff_not_imp_left, I.isBoundaryPoint_iff, ← closure_diff_interior, I.isClosed_range.closure_eq, mem_diff] - exact fun h => ⟨mem_range_self _, h⟩ + exact fun h ↦ ⟨mem_range_self _, h⟩ /-- A manifold decomposes into interior and boundary. -/ lemma interior_union_boundary_eq_univ : (I.interior M) ∪ (I.boundary M) = (univ : Set M) := @@ -97,13 +104,22 @@ lemma disjoint_interior_boundary : Disjoint (I.interior M) (I.boundary M) := by -- Choose some x in the intersection of interior and boundary. obtain ⟨x, h1, h2⟩ := not_disjoint_iff.mp h rw [← mem_empty_iff_false (extChartAt I x x), - ← disjoint_iff_inter_eq_empty.mp (disjoint_interior_frontier (s := range I)), mem_inter_iff] + ← disjoint_iff_inter_eq_empty.mp disjoint_interior_frontier, mem_inter_iff] exact ⟨h1, h2⟩ +lemma isInteriorPoint_iff_not_isBoundaryPoint (x : M) : + I.IsInteriorPoint x ↔ ¬I.IsBoundaryPoint x := by + refine ⟨?_, + by simpa only [or_iff_not_imp_right] using isInteriorPoint_or_isBoundaryPoint x (I := I)⟩ + by_contra! h + rw [← mem_empty_iff_false (extChartAt I x x), + ← disjoint_iff_inter_eq_empty.mp disjoint_interior_frontier, mem_inter_iff] + exact h + /-- The boundary is the complement of the interior. -/ lemma compl_interior : (I.interior M)ᶜ = I.boundary M:= by apply compl_unique ?_ I.interior_union_boundary_eq_univ - exact disjoint_iff_inter_eq_empty.mp (I.disjoint_interior_boundary) + exact disjoint_iff_inter_eq_empty.mp I.disjoint_interior_boundary /-- The interior is the complement of the boundary. -/ lemma compl_boundary : (I.boundary M)ᶜ = I.interior M:= by @@ -231,4 +247,115 @@ instance BoundarylessManifold.prod [BoundarylessManifold I M] [BoundarylessManif end prod +section disjointUnion + +variable {M' : Type*} [TopologicalSpace M'] [ChartedSpace H M'] {n : WithTop ℕ∞} + [hM : IsManifold I n M] [hM' : IsManifold I n M'] + [Nonempty M] [Nonempty M'] [Nonempty H] + {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] + {J : Type*} {J : ModelWithCorners 𝕜 E' H'} + {N N' : Type*} [TopologicalSpace N] [TopologicalSpace N'] [ChartedSpace H' N] [ChartedSpace H' N'] + [IsManifold J n N] [IsManifold J n N'] [Nonempty N] [Nonempty N'] [Nonempty H'] + +open Topology + +lemma interiorPoint_inl (x : M) (hx : I.IsInteriorPoint x) : + I.IsInteriorPoint (.inl x: M ⊕ M') := by + rw [I.isInteriorPoint_iff, extChartAt, ChartedSpace.sum_chartAt_inl] + dsimp only [PartialHomeomorph.extend.eq_1, PartialEquiv.trans_target, toPartialEquiv_coe_symm, + PartialHomeomorph.lift_openEmbedding_target, PartialEquiv.coe_trans, toPartialEquiv_coe, + PartialHomeomorph.toFun_eq_coe, PartialHomeomorph.lift_openEmbedding_toFun, Function.comp_apply] + rw [Sum.inl_injective.extend_apply (chartAt H x)] + simpa [I.isInteriorPoint_iff, extChartAt] using hx + +lemma boundaryPoint_inl (x : M) (hx : I.IsBoundaryPoint x) : + I.IsBoundaryPoint (.inl x: M ⊕ M') := by + rw [I.isBoundaryPoint_iff, extChartAt, ChartedSpace.sum_chartAt_inl] + dsimp + rw [Sum.inl_injective.extend_apply (chartAt H x)] + simpa [I.isBoundaryPoint_iff, extChartAt] using hx + +lemma interiorPoint_inr (x : M') (hx : I.IsInteriorPoint x) : + I.IsInteriorPoint (.inr x : M ⊕ M') := by + rw [I.isInteriorPoint_iff, extChartAt, ChartedSpace.sum_chartAt_inr] + dsimp + rw [Sum.inr_injective.extend_apply (chartAt H x)] + simpa [I.isInteriorPoint_iff, extChartAt] using hx + +lemma boundaryPoint_inr (x : M') (hx : I.IsBoundaryPoint x) : + I.IsBoundaryPoint (.inr x : M ⊕ M') := by + rw [I.isBoundaryPoint_iff, extChartAt, ChartedSpace.sum_chartAt_inr] + dsimp + rw [Sum.inr_injective.extend_apply (chartAt H x)] + simpa [I.isBoundaryPoint_iff, extChartAt] using hx + +-- Converse to the previous direction: if `x` were not an interior point, +-- it had to be a boundary point, hence `p` were a boundary point also, contradiction. +lemma isInteriorPoint_disjointUnion_left {p : M ⊕ M'} (hp : I.IsInteriorPoint p) + (hleft : Sum.isLeft p) : I.IsInteriorPoint (Sum.getLeft p hleft) := by + by_contra h + set x := Sum.getLeft p hleft + rw [isInteriorPoint_iff_not_isBoundaryPoint x, not_not] at h + rw [isInteriorPoint_iff_not_isBoundaryPoint p] at hp + have := boundaryPoint_inl (M' := M') x (by tauto) + rw [← Sum.eq_left_getLeft_of_isLeft hleft] at this + exact hp this + +lemma isInteriorPoint_disjointUnion_right {p : M ⊕ M'} (hp : I.IsInteriorPoint p) + (hright : Sum.isRight p) : I.IsInteriorPoint (Sum.getRight p hright) := by + by_contra h + set x := Sum.getRight p hright + rw [← mem_empty_iff_false p, ← (disjoint_interior_boundary (I := I)).inter_eq] + constructor + · rw [ModelWithCorners.interior, mem_setOf]; exact hp + · rw [ModelWithCorners.boundary, mem_setOf, Sum.eq_right_getRight_of_isRight hright] + have := isInteriorPoint_or_isBoundaryPoint (I := I) x + exact boundaryPoint_inr (M' := M') x (by tauto) + +lemma interior_disjointUnion : + ModelWithCorners.interior (I := I) (M ⊕ M') = + Sum.inl '' (ModelWithCorners.interior (I := I) M) + ∪ Sum.inr '' (ModelWithCorners.interior (I := I) M') := by + ext p + constructor + · intro hp + by_cases h : Sum.isLeft p + · left + exact ⟨Sum.getLeft p h, isInteriorPoint_disjointUnion_left hp h, Sum.inl_getLeft p h⟩ + · replace h := Sum.not_isLeft.mp h + right + exact ⟨Sum.getRight p h, isInteriorPoint_disjointUnion_right hp h, Sum.inr_getRight p h⟩ + · intro hp + by_cases h : Sum.isLeft p + · set x := Sum.getLeft p h with x_eq + rw [Sum.eq_left_getLeft_of_isLeft h] + apply interiorPoint_inl x + have hp : p ∈ Sum.inl '' (ModelWithCorners.interior (I := I) M) := by + obtain (good | ⟨y, hy, hxy⟩) := hp + exacts [good, (not_isLeft_and_isRight ⟨h, by rw [← hxy]; exact rfl⟩).elim] + obtain ⟨x', hx', hx'p⟩ := hp + simpa [x_eq, ← hx'p, Sum.getLeft_inl] + · set x := Sum.getRight p (Sum.not_isLeft.mp h) with x_eq + rw [Sum.eq_right_getRight_of_isRight (Sum.not_isLeft.mp h)] + apply interiorPoint_inr x + have hp : p ∈ Sum.inr '' (ModelWithCorners.interior (I := I) M') := by + obtain (⟨y, hy, hxy⟩ | good) := hp + exacts [(not_isLeft_and_isRight ⟨by rw [← hxy]; exact rfl, Sum.not_isLeft.mp h⟩).elim, good] + obtain ⟨x', hx', hx'p⟩ := hp + simpa [x_eq, ← hx'p, Sum.getRight_inr] + +lemma boundary_disjointUnion : ModelWithCorners.boundary (I := I) (M ⊕ M') = + Sum.inl '' (ModelWithCorners.boundary (I := I) M) + ∪ Sum.inr '' (ModelWithCorners.boundary (I := I) M') := by + simp only [← ModelWithCorners.compl_interior, interior_disjointUnion, inl_compl_union_inr_compl] + +/-- If `M` and `M'` are boundaryless, so is their disjoint union `M ⊔ M'`. -/ +instance boundaryless_disjointUnion + [hM: BoundarylessManifold I M] [hM': BoundarylessManifold I M'] : + BoundarylessManifold I (M ⊕ M') := by + rw [← Boundaryless.iff_boundary_eq_empty] at hM hM' ⊢ + simp [boundary_disjointUnion, hM, hM'] + +end disjointUnion + end ModelWithCorners diff --git a/Mathlib/Geometry/Manifold/IsManifold.lean b/Mathlib/Geometry/Manifold/IsManifold.lean index e457659e18ad7..b92490c31eaf0 100644 --- a/Mathlib/Geometry/Manifold/IsManifold.lean +++ b/Mathlib/Geometry/Manifold/IsManifold.lean @@ -46,6 +46,11 @@ but add these assumptions later as needed. (Quite a few results still do not req we register them as `PartialEquiv`s. `extChartAt I x` is the canonical such partial equiv around `x`. +We define a few constructions of smooth manifolds: +* every empty type is a smooth manifold +* the product of two smooth manifolds +* the disjoint union of two manifolds (over the same charted space) + As specific examples of models with corners, we define (in `Geometry.Manifold.Instances.Real`) * `modelWithCornersEuclideanHalfSpace n : ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanHalfSpace n)` for the model space used to @@ -598,6 +603,26 @@ theorem contDiffGroupoid_zero_eq : contDiffGroupoid 0 I = continuousGroupoid H : · refine I.continuous.comp_continuousOn (u.symm.continuousOn.comp I.continuousOn_symm ?_) exact (mapsTo_preimage _ _).mono_left inter_subset_left +-- FIXME: does this generalise to other groupoids? The argument is not specific +-- to C^n functions, but uses something about the groupoid's property that is not easy to abstract. +/-- Any change of coordinates with empty source belongs to `contDiffGroupoid`. -/ +lemma ContDiffGroupoid.mem_of_source_eq_empty (f : PartialHomeomorph H H) + (hf : f.source = ∅) : f ∈ contDiffGroupoid n I := by + constructor + · intro x ⟨hx, _⟩ + rw [mem_preimage] at hx + simp_all only [mem_empty_iff_false] + · intro x ⟨hx, _⟩ + have : f.target = ∅ := by simp [← f.image_source_eq_target, hf] + simp_all [hx] + +include I in +/-- Any change of coordinates with empty source belongs to `continuousGroupoid`. -/ +lemma ContinuousGroupoid.mem_of_source_eq_empty (f : PartialHomeomorph H H) + (hf : f.source = ∅) : f ∈ continuousGroupoid H := by + rw [← contDiffGroupoid_zero_eq (I := I)] + exact ContDiffGroupoid.mem_of_source_eq_empty f hf + /-- An identity partial homeomorphism belongs to the `C^n` groupoid. -/ theorem ofSet_mem_contDiffGroupoid {s : Set H} (hs : IsOpen s) : PartialHomeomorph.ofSet s hs ∈ contDiffGroupoid n I := by @@ -797,6 +822,34 @@ instance prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedA have h2 := (contDiffGroupoid n I').compatible hf2 hg2 exact contDiffGroupoid_prod h1 h2 +section DisjointUnion + +variable {M' : Type*} [TopologicalSpace M'] [ChartedSpace H M'] + [hM : IsManifold I n M] [hM' : IsManifold I n M'] + +/-- The disjoint union of two `C^n` manifolds modelled on `(E, H)` +is a `C^n` manifold modeled on `(E, H)`. -/ +instance disjointUnion [Nonempty M] [Nonempty M'] [Nonempty H] : IsManifold I n (M ⊕ M') where + compatible {e} e' he he' := by + obtain (⟨f, hf, hef⟩ | ⟨f, hf, hef⟩) := ChartedSpace.mem_atlas_sum he + · obtain (⟨f', hf', he'f'⟩ | ⟨f', hf', he'f'⟩) := ChartedSpace.mem_atlas_sum he' + · rw [hef, he'f', f.lift_openEmbedding_trans f' IsOpenEmbedding.inl] + exact hM.compatible hf hf' + · rw [hef, he'f'] + apply ContDiffGroupoid.mem_of_source_eq_empty + ext x + exact ⟨fun ⟨hx₁, hx₂⟩ ↦ by simp_all [hx₂], fun hx ↦ hx.elim⟩ + · -- Analogous argument to the first case: is there a way to deduplicate? + obtain (⟨f', hf', he'f'⟩ | ⟨f', hf', he'f'⟩) := ChartedSpace.mem_atlas_sum he' + · rw [hef, he'f'] + apply ContDiffGroupoid.mem_of_source_eq_empty + ext x + exact ⟨fun ⟨hx₁, hx₂⟩ ↦ by simp_all [hx₂], fun hx ↦ hx.elim⟩ + · rw [hef, he'f', f.lift_openEmbedding_trans f' IsOpenEmbedding.inr] + exact hM'.compatible hf hf' + +end DisjointUnion + end IsManifold theorem PartialHomeomorph.isManifold_singleton @@ -1675,4 +1728,4 @@ instance : PathConnectedSpace (TangentSpace I x) := inferInstanceAs (PathConnect end Real -set_option linter.style.longFile 1700 +set_option linter.style.longFile 1900 diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index a6835d7101dd5..cff9b2fba723d 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -1374,10 +1374,6 @@ lemma lift_openEmbedding_apply (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding simp_rw [e.lift_openEmbedding_toFun] apply hf.injective.extend_apply -@[simp] -lemma lift_openEmbedding_symm (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : - (e.lift_openEmbedding hf).symm = f ∘ e.symm := rfl - @[simp] lemma lift_openEmbedding_source (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : (e.lift_openEmbedding hf).source = f '' e.source := rfl @@ -1386,4 +1382,34 @@ lemma lift_openEmbedding_source (e : PartialHomeomorph X Z) (hf : IsOpenEmbeddin lemma lift_openEmbedding_target (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : (e.lift_openEmbedding hf).target = e.target := rfl +@[simp] +lemma lift_openEmbedding_symm (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf).symm = f ∘ e.symm := rfl + +@[simp] +lemma lift_openEmbedding_symm_source (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf).symm.source = e.target := rfl + +@[simp] +lemma lift_openEmbedding_symm_target (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf).symm.target = f '' e.source := by + rw [PartialHomeomorph.symm_target, e.lift_openEmbedding_source] + +lemma lift_openEmbedding_trans_apply + (e e' : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) (z : Z) : + (e.lift_openEmbedding hf).symm.trans (e'.lift_openEmbedding hf) z = (e.symm.trans e') z := by + simp [hf.injective.extend_apply e'] + +@[simp] +lemma lift_openEmbedding_trans (e e' : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : + (e.lift_openEmbedding hf).symm.trans (e'.lift_openEmbedding hf) = e.symm.trans e' := by + ext x + · exact e.lift_openEmbedding_trans_apply e' hf x + · simp [hf.injective.extend_apply e] + · simp_rw [PartialHomeomorph.trans_source, e.lift_openEmbedding_symm_source, e.symm_source, + e.lift_openEmbedding_symm, e'.lift_openEmbedding_source] + refine ⟨fun ⟨hx, ⟨y, hy, hxy⟩⟩ ↦ ⟨hx, ?_⟩, fun ⟨hx, hx'⟩ ↦ ⟨hx, mem_image_of_mem f hx'⟩⟩ + rw [mem_preimage]; rw [comp_apply] at hxy + exact (hf.injective hxy) ▸ hy + end PartialHomeomorph From f380e8d126dcb50c910ea4e918e96687268c536a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 21 Jan 2025 04:10:27 +0000 Subject: [PATCH 366/681] chore(ConjAct): don't import fields (#20718) `ConjAct` is imported in basic algebra files about groups, and therefore should not import `MonoidWithZero`. The latter is currently quite deeply embedded within the import graph, so we start by removing `Field`. The copyright headers come from https://github.com/leanprover-community/mathlib3/pull/8627 and https://github.com/leanprover-community/mathlib3/pull/13439. --- Mathlib.lean | 3 + Mathlib/Algebra/Field/Action/ConjAct.lean | 22 +++++++ .../Algebra/GroupWithZero/Action/ConjAct.lean | 37 +++++++++++ Mathlib/Algebra/Ring/Action/ConjAct.lean | 23 +++++++ .../Analysis/Normed/Algebra/Exponential.lean | 1 + Mathlib/GroupTheory/GroupAction/ConjAct.lean | 65 ++----------------- .../CliffordAlgebra/SpinGroup.lean | 1 + 7 files changed, 94 insertions(+), 58 deletions(-) create mode 100644 Mathlib/Algebra/Field/Action/ConjAct.lean create mode 100644 Mathlib/Algebra/GroupWithZero/Action/ConjAct.lean create mode 100644 Mathlib/Algebra/Ring/Action/ConjAct.lean diff --git a/Mathlib.lean b/Mathlib.lean index 8aa9afd9c04aa..3c1d15da1edc5 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -228,6 +228,7 @@ import Mathlib.Algebra.EuclideanDomain.Field import Mathlib.Algebra.EuclideanDomain.Int import Mathlib.Algebra.Exact import Mathlib.Algebra.Expr +import Mathlib.Algebra.Field.Action.ConjAct import Mathlib.Algebra.Field.Basic import Mathlib.Algebra.Field.Defs import Mathlib.Algebra.Field.Equiv @@ -374,6 +375,7 @@ import Mathlib.Algebra.Group.WithOne.Basic import Mathlib.Algebra.Group.WithOne.Defs import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.Algebra.GroupWithZero.Action.Basic +import Mathlib.Algebra.GroupWithZero.Action.ConjAct import Mathlib.Algebra.GroupWithZero.Action.Defs import Mathlib.Algebra.GroupWithZero.Action.End import Mathlib.Algebra.GroupWithZero.Action.Faithful @@ -892,6 +894,7 @@ import Mathlib.Algebra.Regular.Basic import Mathlib.Algebra.Regular.Pow import Mathlib.Algebra.Regular.SMul import Mathlib.Algebra.Ring.Action.Basic +import Mathlib.Algebra.Ring.Action.ConjAct import Mathlib.Algebra.Ring.Action.Field import Mathlib.Algebra.Ring.Action.Group import Mathlib.Algebra.Ring.Action.Invariant diff --git a/Mathlib/Algebra/Field/Action/ConjAct.lean b/Mathlib/Algebra/Field/Action/ConjAct.lean new file mode 100644 index 0000000000000..f55dc6893ea4d --- /dev/null +++ b/Mathlib/Algebra/Field/Action/ConjAct.lean @@ -0,0 +1,22 @@ +/- +Copyright (c) 2022 Eric Wieser. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Eric Wieser +-/ +import Mathlib.Algebra.Field.Defs +import Mathlib.Algebra.GroupWithZero.Action.ConjAct + +/-! +# Conjugation action on a field on itself +-/ + +namespace ConjAct + +variable {K : Type*} [DivisionRing K] + +instance distribMulAction₀ : DistribMulAction (ConjAct K) K := + { ConjAct.mulAction₀ with + smul_zero := by simp [smul_def] + smul_add := by simp [smul_def, mul_add, add_mul] } + +end ConjAct diff --git a/Mathlib/Algebra/GroupWithZero/Action/ConjAct.lean b/Mathlib/Algebra/GroupWithZero/Action/ConjAct.lean new file mode 100644 index 0000000000000..844e8ba3b3efc --- /dev/null +++ b/Mathlib/Algebra/GroupWithZero/Action/ConjAct.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2022 Eric Wieser. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Eric Wieser +-/ +import Mathlib.GroupTheory.GroupAction.ConjAct + +/-! +# Conjugation action of a group with zero on itself +-/ + +assert_not_exists Ring + +variable {α G₀ : Type*} + +namespace ConjAct +variable [GroupWithZero G₀] + +instance : GroupWithZero (ConjAct G₀) := ‹GroupWithZero G₀› + +@[simp] lemma ofConjAct_zero : ofConjAct 0 = (0 : G₀) := rfl +@[simp] lemma toConjAct_zero : toConjAct (0 : G₀) = 0 := rfl + +instance mulAction₀ : MulAction (ConjAct G₀) G₀ where + one_smul := by simp [smul_def] + mul_smul := by simp [smul_def, mul_assoc] + +instance smulCommClass₀ [SMul α G₀] [SMulCommClass α G₀ G₀] [IsScalarTower α G₀ G₀] : + SMulCommClass α (ConjAct G₀) G₀ where + smul_comm a ug g := by rw [smul_def, smul_def, mul_smul_comm, smul_mul_assoc] + +instance smulCommClass₀' [SMul α G₀] [SMulCommClass G₀ α G₀] [IsScalarTower α G₀ G₀] : + SMulCommClass (ConjAct G₀) α G₀ := + haveI := SMulCommClass.symm G₀ α G₀ + .symm .. + +end ConjAct diff --git a/Mathlib/Algebra/Ring/Action/ConjAct.lean b/Mathlib/Algebra/Ring/Action/ConjAct.lean new file mode 100644 index 0000000000000..f6401f3572c32 --- /dev/null +++ b/Mathlib/Algebra/Ring/Action/ConjAct.lean @@ -0,0 +1,23 @@ +/- +Copyright (c) 2022 Eric Wieser. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Eric Wieser +-/ +import Mathlib.Algebra.Ring.Action.Basic +import Mathlib.GroupTheory.GroupAction.ConjAct + +/-! +# Conjugation action of a ring on itself +-/ + +assert_not_exists Field + +namespace ConjAct +variable {R : Type*} [Semiring R] + +instance unitsMulSemiringAction : MulSemiringAction (ConjAct Rˣ) R := + { ConjAct.unitsMulDistribMulAction with + smul_zero := by simp [units_smul_def] + smul_add := by simp [units_smul_def, mul_add, add_mul] } + +end ConjAct diff --git a/Mathlib/Analysis/Normed/Algebra/Exponential.lean b/Mathlib/Analysis/Normed/Algebra/Exponential.lean index 9166797fa69d8..3d2e1d2cbdb3b 100644 --- a/Mathlib/Analysis/Normed/Algebra/Exponential.lean +++ b/Mathlib/Analysis/Normed/Algebra/Exponential.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Anatole Dedecker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker, Eric Wieser -/ +import Mathlib.Algebra.Ring.Action.ConjAct import Mathlib.Analysis.Analytic.ChangeOrigin import Mathlib.Analysis.Complex.Basic import Mathlib.Data.Nat.Choose.Cast diff --git a/Mathlib/GroupTheory/GroupAction/ConjAct.lean b/Mathlib/GroupTheory/GroupAction/ConjAct.lean index 970e9def54589..00274cf0874cf 100644 --- a/Mathlib/GroupTheory/GroupAction/ConjAct.lean +++ b/Mathlib/GroupTheory/GroupAction/ConjAct.lean @@ -1,15 +1,12 @@ /- -Copyright (c) 2021 . All rights reserved. +Copyright (c) 2021 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.Field.Defs -import Mathlib.Algebra.GroupWithZero.Action.Basic -import Mathlib.Algebra.Ring.Action.Basic +import Mathlib.Algebra.Group.Subgroup.ZPowers.Basic import Mathlib.Data.Fintype.Card import Mathlib.GroupTheory.GroupAction.Defs import Mathlib.GroupTheory.Subgroup.Centralizer -import Mathlib.Algebra.Group.Subgroup.ZPowers.Basic /-! # Conjugation action of a group on itself @@ -35,8 +32,11 @@ is that some theorems about the group actions will not apply when since this -/ +-- TODO +-- assert_not_exists GroupWithZero +assert_not_exists Ring -variable (α M G G₀ R K : Type*) +variable (α M G : Type*) /-- A type alias for a group `G`. `ConjAct G` acts on `G` by conjugation -/ def ConjAct : Type _ := @@ -46,14 +46,12 @@ namespace ConjAct open MulAction Subgroup -variable {M G G₀ R K} +variable {M G} instance [Group G] : Group (ConjAct G) := ‹Group G› instance [DivInvMonoid G] : DivInvMonoid (ConjAct G) := ‹DivInvMonoid G› -instance [GroupWithZero G] : GroupWithZero (ConjAct G) := ‹GroupWithZero G› - instance [Fintype G] : Fintype (ConjAct G) := ‹Fintype G› @[simp] @@ -167,57 +165,8 @@ instance unitsSMulCommClass' [SMul α M] [SMulCommClass M α M] [IsScalarTower end Monoid -section Semiring - -variable [Semiring R] - -instance unitsMulSemiringAction : MulSemiringAction (ConjAct Rˣ) R := - { ConjAct.unitsMulDistribMulAction with - smul_zero := by simp [units_smul_def] - smul_add := by simp [units_smul_def, mul_add, add_mul] } - -end Semiring - end Units -section GroupWithZero - -variable [GroupWithZero G₀] - --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it -theorem ofConjAct_zero : ofConjAct (0 : ConjAct G₀) = 0 := - rfl - --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it -theorem toConjAct_zero : toConjAct (0 : G₀) = 0 := - rfl - -instance mulAction₀ : MulAction (ConjAct G₀) G₀ where - one_smul := by simp [smul_def] - mul_smul := by simp [smul_def, mul_assoc] - -instance smulCommClass₀ [SMul α G₀] [SMulCommClass α G₀ G₀] [IsScalarTower α G₀ G₀] : - SMulCommClass α (ConjAct G₀) G₀ where - smul_comm a ug g := by rw [smul_def, smul_def, mul_smul_comm, smul_mul_assoc] - -instance smulCommClass₀' [SMul α G₀] [SMulCommClass G₀ α G₀] [IsScalarTower α G₀ G₀] : - SMulCommClass (ConjAct G₀) α G₀ := - haveI := SMulCommClass.symm G₀ α G₀ - SMulCommClass.symm _ _ _ - -end GroupWithZero - -section DivisionRing - -variable [DivisionRing K] - -instance distribMulAction₀ : DistribMulAction (ConjAct K) K := - { ConjAct.mulAction₀ with - smul_zero := by simp [smul_def] - smul_add := by simp [smul_def, mul_add, add_mul] } - -end DivisionRing - variable [Group G] -- todo: this file is not in good order; I will refactor this after the PR diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/SpinGroup.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/SpinGroup.lean index 06dfb81ec8f83..8bac15419c249 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/SpinGroup.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/SpinGroup.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Jiale Miao. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jiale Miao, Utensil Song, Eric Wieser -/ +import Mathlib.Algebra.Ring.Action.ConjAct import Mathlib.GroupTheory.GroupAction.ConjAct import Mathlib.Algebra.Star.Unitary import Mathlib.LinearAlgebra.CliffordAlgebra.Star From 6fdfd805685ec3ae7e9b9fbd27e25fde66238cb2 Mon Sep 17 00:00:00 2001 From: Quang Dao Date: Tue, 21 Jan 2025 04:10:28 +0000 Subject: [PATCH 367/681] feat(Data/Fin/Tuple/Basic): `snoc` & `insertNth` are injective (#20771) This PR adds injectivity lemmas for `Fin.snoc` and `Fin.insertNth`, similar to those for `Fin.cons`. This is part of #19315 that is split off. Co-authored-by: Quang Dao --- Mathlib/Algebra/Order/Antidiag/Pi.lean | 2 +- Mathlib/Data/Fin/Tuple/Basic.lean | 40 ++++++++++++++++++++- Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean | 6 ++-- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Mathlib/Algebra/Order/Antidiag/Pi.lean b/Mathlib/Algebra/Order/Antidiag/Pi.lean index a507d68457b98..672e458b039da 100644 --- a/Mathlib/Algebra/Order/Antidiag/Pi.lean +++ b/Mathlib/Algebra/Order/Antidiag/Pi.lean @@ -80,7 +80,7 @@ where simp_rw [Finset.mem_map, Embedding.coeFn_mk] at hti htj obtain ⟨ai, hai, hij'⟩ := hti obtain ⟨aj, haj, rfl⟩ := htj - rw [Fin.cons_eq_cons] at hij' + rw [Fin.cons_inj] at hij' ext · exact hij'.1 · obtain ⟨-, rfl⟩ := hij' diff --git a/Mathlib/Data/Fin/Tuple/Basic.lean b/Mathlib/Data/Fin/Tuple/Basic.lean index 3a31ba890f95d..fce4d009cd9ff 100644 --- a/Mathlib/Data/Fin/Tuple/Basic.lean +++ b/Mathlib/Data/Fin/Tuple/Basic.lean @@ -142,7 +142,7 @@ theorem cons_injective2 : Function.Injective2 (@cons n α) := fun x₀ y₀ x y ⟨congr_fun h 0, funext fun i ↦ by simpa using congr_fun h (Fin.succ i)⟩ @[simp] -theorem cons_eq_cons {x₀ y₀ : α 0} {x y : ∀ i : Fin n, α i.succ} : +theorem cons_inj {x₀ y₀ : α 0} {x y : ∀ i : Fin n, α i.succ} : cons x₀ x = cons y₀ y ↔ x₀ = y₀ ∧ x = y := cons_injective2.eq_iff @@ -586,6 +586,22 @@ theorem update_snoc_last : update (snoc p x) (last n) z = snoc p z := by · rw [eq_last_of_not_lt h] simp +/-- As a binary function, `Fin.snoc` is injective. -/ +theorem snoc_injective2 : Function.Injective2 (@snoc n α) := fun x y xₙ yₙ h ↦ + ⟨funext fun i ↦ by simpa using congr_fun h (castSucc i), by simpa using congr_fun h (last n)⟩ + +@[simp] +theorem snoc_inj {x y : ∀ i : Fin n, α i.castSucc} {xₙ yₙ : α (last n)} : + snoc x xₙ = snoc y yₙ ↔ x = y ∧ xₙ = yₙ := + snoc_injective2.eq_iff + +theorem snoc_right_injective (x : ∀ i : Fin n, α i.castSucc) : + Function.Injective (snoc x) := + snoc_injective2.right _ + +theorem snoc_left_injective (xₙ : α (last n)) : Function.Injective (snoc · xₙ) := + snoc_injective2.left _ + /-- Concatenating the first element of a tuple with its tail gives back the original tuple -/ @[simp] theorem snoc_init_self : snoc (init q) (q (last n)) = q := by @@ -791,6 +807,10 @@ lemma exists_iff_succAbove {P : Fin (n + 1) → Prop} (p : Fin (n + 1)) : · exact .inr ⟨_, hi⟩ mpr := by rintro (h | ⟨i, hi⟩) <;> exact ⟨_, ‹_›⟩ +/-- Analogue of `Fin.eq_zero_or_eq_succ` for `succAbove`. -/ +theorem eq_self_or_eq_succAbove (p i : Fin (n + 1)) : i = p ∨ ∃ j, i = p.succAbove j := + succAboveCases p (.inl rfl) (fun j => .inr ⟨j, rfl⟩) i + /-- Remove the `p`-th entry of a tuple. -/ def removeNth (p : Fin (n + 1)) (f : ∀ i, α i) : ∀ i, α (p.succAbove i) := fun i ↦ f (p.succAbove i) @@ -847,6 +867,24 @@ theorem eq_insertNth_iff {p : Fin (n + 1)} {a : α p} {f : ∀ i, α (p.succAbov g = insertNth p a f ↔ g p = a ∧ removeNth p g = f := by simpa [eq_comm] using insertNth_eq_iff +/-- As a binary function, `Fin.insertNth` is injective. -/ +theorem insertNth_injective2 {p : Fin (n + 1)} : + Function.Injective2 (@insertNth n α p) := fun xₚ yₚ x y h ↦ + ⟨by simpa using congr_fun h p, funext fun i ↦ by simpa using congr_fun h (succAbove p i)⟩ + +@[simp] +theorem insertNth_inj {p : Fin (n + 1)} {x y : ∀ i, α (succAbove p i)} {xₚ yₚ : α p} : + insertNth p xₚ x = insertNth p yₚ y ↔ xₚ = yₚ ∧ x = y := + insertNth_injective2.eq_iff + +theorem insertNth_left_injective {p : Fin (n + 1)} (x : ∀ i, α (succAbove p i)) : + Function.Injective (insertNth p · x) := + insertNth_injective2.left _ + +theorem insertNth_right_injective {p : Fin (n + 1)} (x : α p) : + Function.Injective (insertNth p x) := + insertNth_injective2.right _ + /- Porting note: Once again, Lean told me `(fun x x_1 ↦ α x)` was an invalid motive, but disabling automatic insertion and specifying that motive seems to work. -/ theorem insertNth_apply_below {i j : Fin (n + 1)} (h : j < i) (x : α i) diff --git a/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean b/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean index 51f860e725e71..c78a2338915fd 100644 --- a/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean +++ b/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean @@ -80,7 +80,7 @@ theorem mem_antidiagonalTuple {n : ℕ} {k : ℕ} {x : Fin k → ℕ} : · simp [eq_comm] | h x₀ x ih => simp_rw [Fin.sum_cons, antidiagonalTuple, List.mem_flatMap, List.mem_map, - List.Nat.mem_antidiagonal, Fin.cons_eq_cons, exists_eq_right_right, ih, + List.Nat.mem_antidiagonal, Fin.cons_inj, exists_eq_right_right, ih, @eq_comm _ _ (Prod.snd _), and_comm (a := Prod.snd _ = _), ← Prod.mk.inj_iff (a₁ := Prod.fst _), exists_eq_right] @@ -100,12 +100,12 @@ theorem nodup_antidiagonalTuple (k n : ℕ) : List.Nodup (antidiagonalTuple k n) refine List.Pairwise.cons (fun a ha x hx₁ hx₂ => ?_) (n_ih.map _ fun a b h x hx₁ hx₂ => ?_) · rw [List.mem_map] at hx₁ hx₂ ha obtain ⟨⟨a, -, rfl⟩, ⟨x₁, -, rfl⟩, ⟨x₂, -, h⟩⟩ := ha, hx₁, hx₂ - rw [Fin.cons_eq_cons] at h + rw [Fin.cons_inj] at h injection h.1 · rw [List.mem_map] at hx₁ hx₂ obtain ⟨⟨x₁, hx₁, rfl⟩, ⟨x₂, hx₂, h₁₂⟩⟩ := hx₁, hx₂ dsimp at h₁₂ - rw [Fin.cons_eq_cons, Nat.succ_inj'] at h₁₂ + rw [Fin.cons_inj, Nat.succ_inj'] at h₁₂ obtain ⟨h₁₂, rfl⟩ := h₁₂ rw [Function.onFun, h₁₂] at h exact h (List.mem_map_of_mem _ hx₁) (List.mem_map_of_mem _ hx₂) From 7c3079ec24f626892d92d62946a8581d407f4812 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 21 Jan 2025 04:10:30 +0000 Subject: [PATCH 368/681] chore: address some porting notes in Mathlib/Computability (#20822) --- Mathlib/Computability/Ackermann.lean | 1 - Mathlib/Computability/Encoding.lean | 23 ++++++++-------- Mathlib/Computability/Language.lean | 9 +------ Mathlib/Computability/Partrec.lean | 8 ++---- Mathlib/Computability/PartrecCode.lean | 3 --- Mathlib/Computability/Primrec.lean | 27 ------------------- Mathlib/Computability/RegularExpressions.lean | 25 +++++------------ Mathlib/Computability/TMComputable.lean | 7 ++--- Mathlib/Computability/TMToPartrec.lean | 4 --- Mathlib/Computability/Tape.lean | 4 +-- Mathlib/Computability/TuringMachine.lean | 3 +-- Mathlib/Data/Part.lean | 2 +- 12 files changed, 27 insertions(+), 89 deletions(-) diff --git a/Mathlib/Computability/Ackermann.lean b/Mathlib/Computability/Ackermann.lean index 92b4e6f1c3a1a..fc5ffcfc01658 100644 --- a/Mathlib/Computability/Ackermann.lean +++ b/Mathlib/Computability/Ackermann.lean @@ -83,7 +83,6 @@ theorem ack_two (n : ℕ) : ack 2 n = 2 * n + 3 := by · simp · simpa [mul_succ] --- Porting note: re-written to get rid of ack_three_aux @[simp] theorem ack_three (n : ℕ) : ack 3 n = 2 ^ (n + 3) - 3 := by induction' n with n IH diff --git a/Mathlib/Computability/Encoding.lean b/Mathlib/Computability/Encoding.lean index 67db006d7f41b..2f5c7c2632dda 100644 --- a/Mathlib/Computability/Encoding.lean +++ b/Mathlib/Computability/Encoding.lean @@ -70,11 +70,16 @@ def sectionΓ'Bool : Γ' → Bool | Γ'.bit b => b | _ => Inhabited.default +@[simp] +theorem sectionΓ'Bool_inclusionBoolΓ' {b} : sectionΓ'Bool (inclusionBoolΓ' b) = b := by + cases b <;> rfl + +@[deprecated sectionΓ'Bool_inclusionBoolΓ' (since := "2025-01-21")] theorem leftInverse_section_inclusion : Function.LeftInverse sectionΓ'Bool inclusionBoolΓ' := fun x => Bool.casesOn x rfl rfl theorem inclusionBoolΓ'_injective : Function.Injective inclusionBoolΓ' := - Function.HasLeftInverse.injective (Exists.intro sectionΓ'Bool leftInverse_section_inclusion) + Function.HasLeftInverse.injective ⟨_, (fun _ => sectionΓ'Bool_inclusionBoolΓ')⟩ /-- An encoding function of the positive binary numbers in bool. -/ def encodePosNum : PosNum → List Bool @@ -107,7 +112,7 @@ theorem encodePosNum_nonempty (n : PosNum) : encodePosNum n ≠ [] := PosNum.casesOn n (List.cons_ne_nil _ _) (fun _m => List.cons_ne_nil _ _) fun _m => List.cons_ne_nil _ _ -theorem decode_encodePosNum : ∀ n, decodePosNum (encodePosNum n) = n := by +@[simp] theorem decode_encodePosNum : ∀ n, decodePosNum (encodePosNum n) = n := by intro n induction' n with m hm m hm <;> unfold encodePosNum decodePosNum · rfl @@ -115,7 +120,7 @@ theorem decode_encodePosNum : ∀ n, decodePosNum (encodePosNum n) = n := by exact if_neg (encodePosNum_nonempty m) · exact congr_arg PosNum.bit0 hm -theorem decode_encodeNum : ∀ n, decodeNum (encodeNum n) = n := by +@[simp] theorem decode_encodeNum : ∀ n, decodeNum (encodeNum n) = n := by intro n cases' n with n <;> unfold encodeNum decodeNum · rfl @@ -123,7 +128,7 @@ theorem decode_encodeNum : ∀ n, decodeNum (encodeNum n) = n := by rw [PosNum.cast_to_num] exact if_neg (encodePosNum_nonempty n) -theorem decode_encodeNat : ∀ n, decodeNat (encodeNat n) = n := by +@[simp] theorem decode_encodeNat : ∀ n, decodeNat (encodeNat n) = n := by intro n conv_rhs => rw [← Num.to_of_nat n] exact congr_arg ((↑) : Num → ℕ) (decode_encodeNum n) @@ -144,11 +149,7 @@ def encodingNatΓ' : Encoding ℕ where Γ := Γ' encode x := List.map inclusionBoolΓ' (encodeNat x) decode x := some (decodeNat (List.map sectionΓ'Bool x)) - decode_encode x := - congr_arg _ <| by - -- Porting note: `rw` can't unify `g ∘ f` with `fun x => g (f x)`, used `LeftInverse.id` - -- instead. - rw [List.map_map, leftInverse_section_inclusion.id, List.map_id, decode_encodeNat] + decode_encode x := congr_arg _ <| by simp [Function.comp_def] /-- A binary FinEncoding of ℕ in Γ'. -/ def finEncodingNatΓ' : FinEncoding ℕ := @@ -163,7 +164,7 @@ def unaryEncodeNat : Nat → List Bool def unaryDecodeNat : List Bool → Nat := List.length -theorem unary_decode_encode_nat : ∀ n, unaryDecodeNat (unaryEncodeNat n) = n := fun n => +@[simp] theorem unary_decode_encode_nat : ∀ n, unaryDecodeNat (unaryEncodeNat n) = n := fun n => Nat.rec rfl (fun (_m : ℕ) hm => (congr_arg Nat.succ hm.symm).symm) n /-- A unary fin_encoding of ℕ. -/ @@ -182,7 +183,7 @@ def decodeBool : List Bool → Bool | b :: _ => b | _ => Inhabited.default -theorem decode_encodeBool (b : Bool) : decodeBool (encodeBool b) = b := rfl +@[simp] theorem decode_encodeBool (b : Bool) : decodeBool (encodeBool b) = b := rfl /-- A fin_encoding of bool in bool. -/ def finEncodingBoolBool : FinEncoding Bool where diff --git a/Mathlib/Computability/Language.lean b/Mathlib/Computability/Language.lean index 06251e189c2c0..a8ec5be41e453 100644 --- a/Mathlib/Computability/Language.lean +++ b/Mathlib/Computability/Language.lean @@ -41,9 +41,6 @@ instance instCompleteAtomicBooleanAlgebra : CompleteAtomicBooleanAlgebra (Langua variable {l m : Language α} {a b x : List α} --- Porting note: `reducible` attribute cannot be local. --- attribute [local reducible] Language - /-- Zero language has no elements. -/ instance : Zero (Language α) := ⟨(∅ : Set _)⟩ @@ -82,8 +79,6 @@ instance : KStar (Language α) := ⟨fun l ↦ {x | ∃ L : List (List α), x = lemma kstar_def (l : Language α) : l∗ = {x | ∃ L : List (List α), x = L.flatten ∧ ∀ y ∈ L, y ∈ l} := rfl --- Porting note: `reducible` attribute cannot be local, --- so this new theorem is required in place of `Set.ext`. @[ext] theorem ext {l m : Language α} (h : ∀ (x : List α), x ∈ l ↔ x ∈ m) : l = m := Set.ext h @@ -162,9 +157,7 @@ lemma mem_kstar_iff_exists_nonempty {x : List α} : · rintro ⟨S, rfl, h⟩ refine ⟨S.filter fun l ↦ !List.isEmpty l, by simp [List.flatten_filter_not_isEmpty], fun y hy ↦ ?_⟩ - -- Porting note: The previous code was: - -- rw [mem_filter, empty_iff_eq_nil] at hy - rw [mem_filter, Bool.not_eq_true', ← Bool.bool_iff_false, List.isEmpty_iff] at hy + simp only [mem_filter, Bool.not_eq_eq_eq_not, Bool.not_true, isEmpty_eq_false, ne_eq] at hy exact ⟨h y hy.1, hy.2⟩ · rintro ⟨S, hx, h⟩ exact ⟨S, hx, fun y hy ↦ (h y hy).1⟩ diff --git a/Mathlib/Computability/Partrec.lean b/Mathlib/Computability/Partrec.lean index 1068bd7cf6bf7..ebdc557e4cb3a 100644 --- a/Mathlib/Computability/Partrec.lean +++ b/Mathlib/Computability/Partrec.lean @@ -387,7 +387,7 @@ protected theorem bind {f : α →. β} {g : α → β →. σ} (hf : Partrec f) theorem map {f : α →. β} {g : α → β → σ} (hf : Partrec f) (hg : Computable₂ g) : Partrec fun a => (f a).map (g a) := by - simpa [bind_some_eq_map] using @Partrec.bind _ _ _ _ _ _ _ (fun a => Part.some ∘ (g a)) hf hg + simpa [bind_some_eq_map] using Partrec.bind (g := fun a x => some (g a x)) hf hg theorem to₂ {f : α × β →. σ} (hf : Partrec f) : Partrec₂ fun a b => f (a, b) := hf.of_eq fun ⟨_, _⟩ => rfl @@ -656,11 +656,7 @@ variable [Primcodable α] [Primcodable β] [Primcodable γ] [Primcodable σ] open Computable theorem option_some_iff {f : α →. σ} : (Partrec fun a => (f a).map Option.some) ↔ Partrec f := - ⟨fun h => (Nat.Partrec.ppred.comp h).of_eq fun n => by - -- Porting note: needed to help with applying bind_some_eq_map because `Function.comp` got - -- less reducible. - simp [Part.bind_assoc, ← Function.comp_apply (f := Part.some) (g := encode), bind_some_eq_map, - -Function.comp_apply], + ⟨fun h => (Nat.Partrec.ppred.comp h).of_eq fun n => by simp [Part.bind_assoc, bind_some_eq_map], fun hf => hf.map (option_some.comp snd).to₂⟩ theorem option_casesOn_right {o : α → Option β} {f : α → σ} {g : α → β →. σ} (ho : Computable o) diff --git a/Mathlib/Computability/PartrecCode.lean b/Mathlib/Computability/PartrecCode.lean index f86ef6f073202..40ff8c1cdce91 100644 --- a/Mathlib/Computability/PartrecCode.lean +++ b/Mathlib/Computability/PartrecCode.lean @@ -206,8 +206,6 @@ theorem encode_lt_rfind' (cf) : encode cf < encode (rfind' cf) := by end Nat.Partrec.Code --- Porting note: Opening `Primrec` inside `namespace Nat.Partrec.Code` causes it to resolve --- to `Nat.Partrec`. Needs `open _root_.Partrec` support section open Primrec namespace Nat.Partrec.Code @@ -557,7 +555,6 @@ theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c | prec cf cg pf pg => exact pf.prec pg | rfind' cf pf => exact pf.rfind' --- Porting note: `>>`s in `evaln` are now `>>=` because `>>`s are not elaborated well in Lean4. /-- A modified evaluation for the code which returns an `Option ℕ` instead of a `Part ℕ`. To avoid undecidability, `evaln` takes a parameter `k` and fails if it encounters a number ≥ k in the course of its execution. Other than this, the semantics are the same as in `Nat.Partrec.Code.eval`. diff --git a/Mathlib/Computability/Primrec.lean b/Mathlib/Computability/Primrec.lean index 722792093ba58..20b710c3ba844 100644 --- a/Mathlib/Computability/Primrec.lean +++ b/Mathlib/Computability/Primrec.lean @@ -32,26 +32,6 @@ open Denumerable Encodable Function namespace Nat --- Porting note: elim is no longer required because lean 4 is better --- at inferring motive types (I think this is the reason) --- and worst case, we can always explicitly write (motive := fun _ => C) --- without having to then add all the other underscores - --- /-- The non-dependent recursor on naturals. -/ --- def elim {C : Sort*} : C → (ℕ → C → C) → ℕ → C := --- @Nat.rec fun _ => C --- example {C : Sort*} (base : C) (succ : ℕ → C → C) (a : ℕ) : --- a.elim base succ = a.rec base succ := rfl - --- Porting note: cases is no longer required because lean 4 is better --- at inferring motive types (I think this is the reason) - --- /-- Cases on whether the input is 0 or a successor. -/ --- def cases {C : Sort*} (a : C) (f : ℕ → C) : ℕ → C := --- Nat.elim a fun n _ => f n --- example {C : Sort*} (a : C) (f : ℕ → C) (n : ℕ) : --- n.cases a f = n.casesOn a f := rfl - /-- Calls the given function on a pair of entries `n`, encoded via the pairing function. -/ @[simp, reducible] def unpaired {α} (f : ℕ → ℕ → α) (n : ℕ) : α := @@ -611,10 +591,6 @@ theorem _root_.PrimrecPred.or {p q : α → Prop} [DecidablePred p] [DecidablePr (hp : PrimrecPred p) (hq : PrimrecPred q) : PrimrecPred fun a => p a ∨ q a := (Primrec.or.comp hp hq).of_eq fun n => by simp --- Porting note: It is unclear whether we want to boolean versions --- of these lemmas, just the prop versions, or both --- The boolean versions are often actually easier to use --- but did not exist in Lean 3 protected theorem beq [DecidableEq α] : Primrec₂ (@BEq.beq α _) := have : PrimrecRel fun a b : ℕ => a = b := (PrimrecPred.and nat_le nat_le.swap).of_eq fun a => by simp [le_antisymm_iff] @@ -1107,9 +1083,6 @@ instance vector {n} : Primcodable (List.Vector α n) := instance finArrow {n} : Primcodable (Fin n → α) := ofEquiv _ (Equiv.vectorEquivFin _ _).symm --- Porting note: Equiv.arrayEquivFin is not ported yet --- instance array {n} : Primcodable (Array' n α) := --- ofEquiv _ (Equiv.arrayEquivFin _ _) section ULower diff --git a/Mathlib/Computability/RegularExpressions.lean b/Mathlib/Computability/RegularExpressions.lean index 8082aa2d00f52..4e10a5bf7e78c 100644 --- a/Mathlib/Computability/RegularExpressions.lean +++ b/Mathlib/Computability/RegularExpressions.lean @@ -30,6 +30,9 @@ universe u variable {α β γ : Type*} +-- Disable generation of unneeded lemmas which the simpNF linter would complain about. +set_option genSizeOfSpec false in +set_option genInjectivity false in /-- This is the definition of regular expressions. The names used here is to mirror the definition of a Kleene algebra (https://en.wikipedia.org/wiki/Kleene_algebra). * `0` (`zero`) matches nothing @@ -47,15 +50,6 @@ inductive RegularExpression (α : Type u) : Type u | comp : RegularExpression α → RegularExpression α → RegularExpression α | star : RegularExpression α → RegularExpression α - --- Porting note: `simpNF` gets grumpy about how the `foo_def`s below can simplify these.. -attribute [nolint simpNF] RegularExpression.zero.sizeOf_spec -attribute [nolint simpNF] RegularExpression.epsilon.sizeOf_spec -attribute [nolint simpNF] RegularExpression.plus.sizeOf_spec -attribute [nolint simpNF] RegularExpression.plus.injEq -attribute [nolint simpNF] RegularExpression.comp.injEq -attribute [nolint simpNF] RegularExpression.comp.sizeOf_spec - namespace RegularExpression variable {a b : α} @@ -79,7 +73,7 @@ instance : Pow (RegularExpression α) ℕ := ⟨fun n r => npowRec r n⟩ -- Porting note: declaration in an imported module ---attribute [match_pattern] Mul.mul +-- attribute [match_pattern] Mul.mul @[simp] theorem zero_def : (zero : RegularExpression α) = 0 := @@ -97,7 +91,7 @@ theorem plus_def (P Q : RegularExpression α) : plus P Q = P + Q := theorem comp_def (P Q : RegularExpression α) : comp P Q = P * Q := rfl --- Porting note: `matches` is reserved, moved to `matches'` +-- This was renamed to `matches'` during the port of Lean 4 as `matches` is a reserved word. #adaptation_note /-- around nightly-2024-02-25, we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ /-- `matches' P` provides a language which contains all strings that `P` matches -/ @@ -401,13 +395,8 @@ theorem matches'_map (f : α → β) : | char a => by rw [eq_comm] exact image_singleton - -- Porting note: the following close with last `rw` but not with `simp`? - | R + S => by simp only [matches'_map, map, matches'_add]; rw [map_add] + | R + S => by simp only [matches'_map, map, matches'_add, map_add] | comp R S => by simp [matches'_map] - | star R => by - simp_rw [map, matches', matches'_map] - rw [Language.kstar_eq_iSup_pow, Language.kstar_eq_iSup_pow] - simp_rw [← map_pow] - exact image_iUnion.symm + | star R => by simp [matches'_map] end RegularExpression diff --git a/Mathlib/Computability/TMComputable.lean b/Mathlib/Computability/TMComputable.lean index 773ba2fe6a6f2..025046b60c925 100644 --- a/Mathlib/Computability/TMComputable.lean +++ b/Mathlib/Computability/TMComputable.lean @@ -82,7 +82,6 @@ instance inhabitedσ : Inhabited tm.σ := def Stmt : Type := Turing.TM2.Stmt tm.Γ tm.Λ tm.σ --- Porting note: The `deriving Inhabited` handler couldn't derive this. instance inhabitedStmt : Inhabited (Stmt tm) := inferInstanceAs (Inhabited (Turing.TM2.Stmt tm.Γ tm.Λ tm.σ)) @@ -135,8 +134,7 @@ structure EvalsToInTime {σ : Type*} (f : σ → Option σ) (a : σ) (b : Option steps_le_m : steps ≤ m /-- Reflexivity of `EvalsTo` in 0 steps. -/ --- @[refl] -- Porting note: `@[refl]` attribute only applies to lemmas proving `x ∼ x` in Lean4. -def EvalsTo.refl {σ : Type*} (f : σ → Option σ) (a : σ) : EvalsTo f a a := +def EvalsTo.refl {σ : Type*} (f : σ → Option σ) (a : σ) : EvalsTo f a (some a) := ⟨0, rfl⟩ /-- Transitivity of `EvalsTo` in the sum of the numbers of steps. -/ @@ -146,8 +144,7 @@ def EvalsTo.trans {σ : Type*} (f : σ → Option σ) (a : σ) (b : σ) (c : Opt ⟨h₂.steps + h₁.steps, by rw [Function.iterate_add_apply, h₁.evals_in_steps, h₂.evals_in_steps]⟩ /-- Reflexivity of `EvalsToInTime` in 0 steps. -/ --- @[refl] -- Porting note: `@[refl]` attribute only applies to lemmas proving `x ∼ x` in Lean4. -def EvalsToInTime.refl {σ : Type*} (f : σ → Option σ) (a : σ) : EvalsToInTime f a a 0 := +def EvalsToInTime.refl {σ : Type*} (f : σ → Option σ) (a : σ) : EvalsToInTime f a (some a) 0 := ⟨EvalsTo.refl f a, le_refl 0⟩ /-- Transitivity of `EvalsToInTime` in the sum of the numbers of steps. -/ diff --git a/Mathlib/Computability/TMToPartrec.lean b/Mathlib/Computability/TMToPartrec.lean index e0c093182ad2c..88be54ec886b6 100644 --- a/Mathlib/Computability/TMToPartrec.lean +++ b/Mathlib/Computability/TMToPartrec.lean @@ -122,10 +122,6 @@ def Code.eval : Code → List ℕ →. List ℕ namespace Code -/- Porting note: The equation lemma of `eval` is too strong; it simplifies terms like the LHS of -`pred_eval`. Even `eqns` can't fix this. We removed `simp` attr from `eval` and prepare new simp -lemmas for `eval`. -/ - @[simp] theorem zero'_eval : zero'.eval = fun v => pure (0 :: v) := by simp [eval] diff --git a/Mathlib/Computability/Tape.lean b/Mathlib/Computability/Tape.lean index 64bf4d02f6936..cf293a33770e0 100644 --- a/Mathlib/Computability/Tape.lean +++ b/Mathlib/Computability/Tape.lean @@ -584,9 +584,7 @@ theorem Tape.map_write {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap ∀ T : Tape Γ, (T.write b).map f = (T.map f).write (f b) := by rintro ⟨⟩; rfl --- Porting note: `simpNF` complains about LHS does not simplify when using the simp lemma on --- itself, but it does indeed. -@[simp, nolint simpNF] +@[simp] theorem Tape.write_move_right_n {Γ} [Inhabited Γ] (f : Γ → Γ) (L R : ListBlank Γ) (n : ℕ) : ((Tape.move Dir.right)^[n] (Tape.mk' L R)).write (f (R.nth n)) = (Tape.move Dir.right)^[n] (Tape.mk' L (R.modifyNth f n)) := by diff --git a/Mathlib/Computability/TuringMachine.lean b/Mathlib/Computability/TuringMachine.lean index 33c511f86aaa4..423c7c3acaf78 100644 --- a/Mathlib/Computability/TuringMachine.lean +++ b/Mathlib/Computability/TuringMachine.lean @@ -147,8 +147,7 @@ def evalInduction {σ} {f : σ → Option σ} {b : σ} {C : σ → Sort*} {a : theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by refine ⟨fun h ↦ ?_, fun ⟨h₁, h₂⟩ ↦ ?_⟩ - · -- Porting note: Explicitly specify `c`. - refine @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ ?_ + · refine evalInduction h fun a h IH ↦ ?_ cases' e : f a with a' · rw [Part.mem_unique h (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e]; rfl)] diff --git a/Mathlib/Data/Part.lean b/Mathlib/Data/Part.lean index 98ebf824ed437..5a508e4709c66 100644 --- a/Mathlib/Data/Part.lean +++ b/Mathlib/Data/Part.lean @@ -436,7 +436,7 @@ theorem bind_some (a : α) (f : α → Part β) : (some a).bind f = f a := theorem bind_of_mem {o : Part α} {a : α} (h : a ∈ o) (f : α → Part β) : o.bind f = f a := by rw [eq_some_iff.2 h, bind_some] -theorem bind_some_eq_map (f : α → β) (x : Part α) : x.bind (some ∘ f) = map f x := +theorem bind_some_eq_map (f : α → β) (x : Part α) : x.bind (fun y => some (f y)) = map f x := ext <| by simp [eq_comm] theorem bind_toOption (f : α → Part β) (o : Part α) [Decidable o.Dom] [∀ a, Decidable (f a).Dom] From 70557fd6def8846eeea375ff22a6c6d42964ba94 Mon Sep 17 00:00:00 2001 From: qawbecrdtey Date: Tue, 21 Jan 2025 04:54:13 +0000 Subject: [PATCH 369/681] feat: add congruences of subtypes and sets/finsets. (#19514) A congruence about subtypes and sets/finsets. Related [zulip thread](https://leanprover.zulipchat.com/#narrow/channel/113489-new-members/topic/Mapping.20from.20subtype.20of.20finsets.20to.20finset.20of.20subtypes/near/484518824) Co-authored-by: qawbecrdtey <40463813+qawbecrdtey@users.noreply.github.com> Co-authored-by: qawbecrdtey --- Mathlib/Data/Finset/Image.lean | 22 ++++++++++++++++++++++ Mathlib/Data/Set/Basic.lean | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index c05c5afa72d5d..7491192b997e4 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -768,4 +768,26 @@ theorem finsetCongr_toEmbedding (e : α ≃ β) : e.finsetCongr.toEmbedding = (Finset.mapEmbedding e.toEmbedding).toEmbedding := rfl +/-- Given a predicate `p : α → Prop`, produces an equivalence between + `Finset {a : α // p a}` and `{s : Finset α // ∀ a ∈ s, p a}`. -/ + +@[simps] +protected def finsetSubtypeComm (p : α → Prop) : + Finset {a : α // p a} ≃ {s : Finset α // ∀ a ∈ s, p a} where + toFun s := ⟨s.map ⟨fun a ↦ a.val, Subtype.val_injective⟩, fun _ h ↦ + have ⟨v, _, h⟩ := Embedding.coeFn_mk _ _ ▸ mem_map.mp h; h ▸ v.property⟩ + invFun s := s.val.attach.map (Subtype.impEmbedding _ _ s.property) + left_inv s := by + ext a; constructor <;> intro h <;> + simp only [Finset.mem_map, Finset.mem_attach, true_and, Subtype.exists, Embedding.coeFn_mk, + exists_and_right, exists_eq_right, Subtype.impEmbedding, Subtype.mk.injEq] at * + · rcases h with ⟨_, ⟨_, h₁⟩, h₂⟩; exact h₂ ▸ h₁ + · use a, ⟨a.property, h⟩ + right_inv s := by + ext a; constructor <;> intro h <;> + simp only [Finset.mem_map, Finset.mem_attach, true_and, Subtype.exists, Embedding.coeFn_mk, + exists_and_right, exists_eq_right, Subtype.impEmbedding, Subtype.mk.injEq] at * + · rcases h with ⟨_, _, h₁, h₂⟩; exact h₂ ▸ h₁ + · use s.property _ h, a + end Equiv diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 09da257d2220c..edefcf869588c 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -2174,4 +2174,27 @@ end Disjoint @[simp] theorem Prop.compl_singleton (p : Prop) : ({p}ᶜ : Set Prop) = {¬p} := ext fun q ↦ by simpa [@Iff.comm q] using not_iff +namespace Equiv + +/-- Given a predicate `p : α → Prop`, produces an equivalence between + `Set {a : α // p a}` and `{s : Set α // ∀ a ∈ s, p a}`. -/ +protected def setSubtypeComm (p : α → Prop) : + Set {a : α // p a} ≃ {s : Set α // ∀ a ∈ s, p a} where + toFun s := ⟨{a | ∃ h : p a, s ⟨a, h⟩}, fun _ h ↦ h.1⟩ + invFun s := {a | a.val ∈ s.val} + left_inv s := by ext a; exact ⟨fun h ↦ h.2, fun h ↦ ⟨a.property, h⟩⟩ + right_inv s := by ext; exact ⟨fun h ↦ h.2, fun h ↦ ⟨s.property _ h, h⟩⟩ + +@[simp] +protected lemma setSubtypeComm_apply (p : α → Prop) (s : Set {a // p a}) : + (Equiv.setSubtypeComm p) s = ⟨{a | ∃ h : p a, ⟨a, h⟩ ∈ s}, fun _ h ↦ h.1⟩ := + rfl + +@[simp] +protected lemma setSubtypeComm_symm_apply (p : α → Prop) (s : {s // ∀ a ∈ s, p a}) : + (Equiv.setSubtypeComm p).symm s = {a | a.val ∈ s.val} := + rfl + +end Equiv + set_option linter.style.longFile 2300 From 77dfbeca100939b1368e8fadb7348eaaee99da12 Mon Sep 17 00:00:00 2001 From: Yuma Mizuno Date: Tue, 21 Jan 2025 04:54:14 +0000 Subject: [PATCH 370/681] feat(CategoryTheory/Bicategory): define mates in bicategories (#20891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A challenge from 2-category theory in [Lean Together 2025: The ∞-cosmos project: formalizing 1-, 2-, V-, and ∞-category theory](https://youtu.be/pV6BIImkToU?si=kYGLb0-C-d5olGoR&t=1266) by @emilyriehl. There is also a [Zulip thred](https://leanprover.zulipchat.com/#narrow/channel/474713-Lean-Together-2025/topic/Emily.20Riehl.3A.20The.20infty-cosmos.20project) about this talk. --- Mathlib.lean | 3 +- .../Basic.lean} | 0 .../Bicategory/Adjunction/Mate.lean | 219 ++++++++++++++++++ .../Bicategory/Kan/Adjunction.lean | 2 +- scripts/noshake.json | 2 +- 5 files changed, 223 insertions(+), 3 deletions(-) rename Mathlib/CategoryTheory/Bicategory/{Adjunction.lean => Adjunction/Basic.lean} (100%) create mode 100644 Mathlib/CategoryTheory/Bicategory/Adjunction/Mate.lean diff --git a/Mathlib.lean b/Mathlib.lean index 3c1d15da1edc5..b9cd45e7d7a0a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1670,7 +1670,8 @@ import Mathlib.CategoryTheory.Adjunction.Triple import Mathlib.CategoryTheory.Adjunction.Unique import Mathlib.CategoryTheory.Adjunction.Whiskering import Mathlib.CategoryTheory.Balanced -import Mathlib.CategoryTheory.Bicategory.Adjunction +import Mathlib.CategoryTheory.Bicategory.Adjunction.Basic +import Mathlib.CategoryTheory.Bicategory.Adjunction.Mate import Mathlib.CategoryTheory.Bicategory.Basic import Mathlib.CategoryTheory.Bicategory.Coherence import Mathlib.CategoryTheory.Bicategory.End diff --git a/Mathlib/CategoryTheory/Bicategory/Adjunction.lean b/Mathlib/CategoryTheory/Bicategory/Adjunction/Basic.lean similarity index 100% rename from Mathlib/CategoryTheory/Bicategory/Adjunction.lean rename to Mathlib/CategoryTheory/Bicategory/Adjunction/Basic.lean diff --git a/Mathlib/CategoryTheory/Bicategory/Adjunction/Mate.lean b/Mathlib/CategoryTheory/Bicategory/Adjunction/Mate.lean new file mode 100644 index 0000000000000..1e93d955a592b --- /dev/null +++ b/Mathlib/CategoryTheory/Bicategory/Adjunction/Mate.lean @@ -0,0 +1,219 @@ +/- +Copyright (c) 2025 Yuma Mizuno. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuma Mizuno +-/ +import Mathlib.CategoryTheory.Bicategory.Adjunction.Basic + +/-! +# Mates in bicategories + +This file establishes the bijection between the 2-cells + +``` + l₁ r₁ + c --→ d c ←-- d + g ↓ ↗ ↓ h g ↓ ↘ ↓ h + e --→ f e ←-- f + l₂ r₂ +``` + +where `l₁ ⊣ r₁` and `l₂ ⊣ r₂`. The corresponding natural transformations are called mates. + +For the bicategory `Cat`, the definitions in this file are provided in +`Mathlib/CategoryTheory/Adjunction/Mates.lean`, where you can find more detailed documentation +about mates. + +## Remarks + +To be precise, the definitions in `Mathlib/CategoryTheory/Adjunction/Mates.lean` are universe +polymorphic, so they are not simple specializations of the definitions in this file. + +-/ + +universe w v u + +namespace CategoryTheory + +namespace Bicategory + +open Bicategory + +variable {B : Type u} [Bicategory.{w, v} B] + +section mateEquiv + +variable {c d e f : B} {g : c ⟶ e} {h : d ⟶ f} {l₁ : c ⟶ d} {r₁ : d ⟶ c} {l₂ : e ⟶ f} {r₂ : f ⟶ e} +variable (adj₁ : l₁ ⊣ r₁) (adj₂ : l₂ ⊣ r₂) + +/-- Suppose we have a square of 1-morphisms (where the top and bottom are adjunctions `l₁ ⊣ r₁` +and `l₂ ⊣ r₂` respectively). + + c ↔ d + g ↓ ↓ h + e ↔ f + +Then we have a bijection between natural transformations `g ≫ l₂ ⟶ l₁ ≫ h` and +`r₁ ≫ g ⟶ h ≫ r₂`. This can be seen as a bijection of the 2-cells: + + l₁ r₁ + c --→ d c ←-- d + g ↓ ↗ ↓ h g ↓ ↘ ↓ h + e --→ f e ←-- f + L₂ R₂ + +Note that if one of the transformations is an iso, it does not imply the other is an iso. +-/ +@[simps] +def mateEquiv : (g ≫ l₂ ⟶ l₁ ≫ h) ≃ (r₁ ≫ g ⟶ h ≫ r₂) where + toFun α := 𝟙 _ ⊗≫ r₁ ◁ g ◁ adj₂.unit ⊗≫ r₁ ◁ α ▷ r₂ ⊗≫ adj₁.counit ▷ h ▷ r₂ ⊗≫ 𝟙 _ + invFun β := 𝟙 _ ⊗≫ adj₁.unit ▷ g ▷ l₂ ⊗≫ l₁ ◁ β ▷ l₂ ⊗≫ l₁ ◁ h ◁ adj₂.counit ⊗≫ 𝟙 _ + left_inv α := + calc + _ = 𝟙 _ ⊗≫ (adj₁.unit ▷ (g ≫ 𝟙 e) ≫ (l₁ ≫ r₁) ◁ g ◁ adj₂.unit) ▷ l₂ ⊗≫ + l₁ ◁ r₁ ◁ α ▷ r₂ ▷ l₂ ⊗≫ + l₁ ◁ (adj₁.counit ▷ h ▷ (r₂ ≫ l₂) ≫ (𝟙 d ≫ h) ◁ adj₂.counit) ⊗≫ 𝟙 _ := by + bicategory + _ = 𝟙 _ ⊗≫ g ◁ adj₂.unit ▷ l₂ ⊗≫ + (adj₁.unit ▷ (g ≫ l₂) ≫ (l₁ ≫ r₁) ◁ α) ▷ (r₂ ≫ l₂) ⊗≫ + l₁ ◁ (((r₁ ≫ l₁) ≫ h) ◁ adj₂.counit ≫ adj₁.counit ▷ h ▷ 𝟙 f) ⊗≫ 𝟙 _ := by + rw [← whisker_exchange, ← whisker_exchange] + bicategory + _ = 𝟙 _ ⊗≫ g ◁ adj₂.unit ▷ l₂ ⊗≫ α ▷ r₂ ▷ l₂ ⊗≫ + leftZigzag adj₁.unit adj₁.counit ▷ h ▷ r₂ ▷ l₂ ⊗≫ l₁ ◁ h ◁ adj₂.counit ⊗≫ 𝟙 _ := by + rw [← whisker_exchange, whisker_exchange _ adj₂.counit] + bicategory + _ = 𝟙 _ ⊗≫ g ◁ adj₂.unit ▷ l₂ ⊗≫ (α ▷ (r₂ ≫ l₂) ≫ (l₁ ≫ h) ◁ adj₂.counit) ⊗≫ 𝟙 _ := by + rw [adj₁.left_triangle] + bicategory + _ = 𝟙 _ ⊗≫ g ◁ (leftZigzag adj₂.unit adj₂.counit) ⊗≫ α ⊗≫ 𝟙 _ := by + rw [← whisker_exchange] + bicategory + _ = α := by + rw [adj₂.left_triangle] + bicategory + right_inv β := + calc + _ = 𝟙 _ ⊗≫ r₁ ◁ ((𝟙 c ≫ g) ◁ adj₂.unit ≫ adj₁.unit ▷ g ▷ (l₂ ≫ r₂)) ⊗≫ + r₁ ◁ l₁ ◁ β ▷ l₂ ▷ r₂ ⊗≫ + ((r₁ ≫ l₁) ◁ h ◁ adj₂.counit ≫ adj₁.counit ▷ (h ≫ 𝟙 f)) ▷ r₂ ⊗≫ 𝟙 _ := by + bicategory + _ = 𝟙 _ ⊗≫ r₁ ◁ (adj₁.unit ▷ g ▷ 𝟙 e ≫ ((l₁ ≫ r₁) ≫ g) ◁ adj₂.unit) ⊗≫ + ((r₁ ≫ l₁) ◁ β ≫ adj₁.counit ▷ (h ≫ r₂)) ▷ l₂ ▷ r₂ ⊗≫ + h ◁ adj₂.counit ▷ r₂ ⊗≫ 𝟙 _ := by + rw [whisker_exchange, whisker_exchange] + bicategory + _ = 𝟙 _ ⊗≫ r₁ ◁ g ◁ adj₂.unit ⊗≫ rightZigzag adj₁.unit adj₁.counit ▷ g ▷ l₂ ▷ r₂ ⊗≫ + β ▷ l₂ ▷ r₂ ⊗≫ h ◁ adj₂.counit ▷ r₂ ⊗≫ 𝟙 _ := by + rw [whisker_exchange, ← whisker_exchange _ adj₂.unit] + bicategory + _ = 𝟙 _ ⊗≫ ((r₁ ≫ g) ◁ adj₂.unit ≫ β ▷ (l₂ ≫ r₂)) ⊗≫ h ◁ adj₂.counit ▷ r₂ ⊗≫ 𝟙 _ := by + rw [adj₁.right_triangle] + bicategory + _ = 𝟙 _ ⊗≫ β ⊗≫ h ◁ rightZigzag adj₂.unit adj₂.counit ⊗≫ 𝟙 _ := by + rw [whisker_exchange] + bicategory + _ = β := by + rw [adj₂.right_triangle] + bicategory + +end mateEquiv + +section mateEquivVComp + +variable {a b c d e f : B} {g₁ : a ⟶ c} {g₂ : c ⟶ e} {h₁ : b ⟶ d} {h₂ : d ⟶ f} +variable {l₁ : a ⟶ b} {r₁ : b ⟶ a} {l₂ : c ⟶ d} {r₂ : d ⟶ c} {l₃ : e ⟶ f} {r₃ : f ⟶ e} +variable (adj₁ : l₁ ⊣ r₁) (adj₂ : l₂ ⊣ r₂) (adj₃ : l₃ ⊣ r₃) + +/-- Squares between left adjoints can be composed "vertically" by pasting. -/ +def leftAdjointSquare.vcomp (α : g₁ ≫ l₂ ⟶ l₁ ≫ h₁) (β : g₂ ≫ l₃ ⟶ l₂ ≫ h₂) : + (g₁ ≫ g₂) ≫ l₃ ⟶ l₁ ≫ (h₁ ≫ h₂) := + (α_ _ _ _).hom ≫ g₁ ◁ β ≫ (α_ _ _ _).inv ≫ α ▷ h₂ ≫ (α_ _ _ _).hom + +/-- Squares between right adjoints can be composed "vertically" by pasting. -/ +def rightAdjointSquare.vcomp (α : r₁ ≫ g₁ ⟶ h₁ ≫ r₂) (β : r₂ ≫ g₂ ⟶ h₂ ≫ r₃) : + r₁ ≫ (g₁ ≫ g₂) ⟶ (h₁ ≫ h₂) ≫ r₃ := + (α_ _ _ _).inv ≫ α ▷ g₂ ≫ (α_ _ _ _).hom ≫ h₁ ◁ β ≫ (α_ _ _ _).inv + +/-- The mates equivalence commutes with vertical composition. -/ +theorem mateEquiv_vcomp (α : g₁ ≫ l₂ ⟶ l₁ ≫ h₁) (β : g₂ ≫ l₃ ⟶ l₂ ≫ h₂) : + mateEquiv adj₁ adj₃ (leftAdjointSquare.vcomp α β) = + rightAdjointSquare.vcomp (mateEquiv adj₁ adj₂ α) (mateEquiv adj₂ adj₃ β) := by + dsimp only [leftAdjointSquare.vcomp, mateEquiv_apply, rightAdjointSquare.vcomp] + symm + calc + _ = 𝟙 _ ⊗≫ r₁ ◁ g₁ ◁ adj₂.unit ▷ g₂ ⊗≫ r₁ ◁ α ▷ r₂ ▷ g₂ ⊗≫ + ((adj₁.counit ▷ (h₁ ≫ r₂ ≫ g₂ ≫ 𝟙 e)) ≫ 𝟙 b ◁ (h₁ ◁ r₂ ◁ g₂ ◁ adj₃.unit)) ⊗≫ + h₁ ◁ r₂ ◁ β ▷ r₃ ⊗≫ h₁ ◁ adj₂.counit ▷ h₂ ▷ r₃ ⊗≫ 𝟙 _ := by + bicategory + _ = 𝟙 _ ⊗≫ r₁ ◁ g₁ ◁ adj₂.unit ▷ g₂ ⊗≫ + (r₁ ◁ (α ▷ (r₂ ≫ g₂ ≫ 𝟙 e) ≫ (l₁ ≫ h₁) ◁ r₂ ◁ g₂ ◁ adj₃.unit)) ⊗≫ + ((adj₁.counit ▷ (h₁ ≫ r₂) ▷ (g₂ ≫ l₃) ≫ (𝟙 b ≫ h₁ ≫ r₂) ◁ β) ▷ r₃) ⊗≫ + h₁ ◁ adj₂.counit ▷ h₂ ▷ r₃ ⊗≫ 𝟙 _ := by + rw [← whisker_exchange] + bicategory + _ = 𝟙 _ ⊗≫ r₁ ◁ g₁ ◁ (adj₂.unit ▷ (g₂ ≫ 𝟙 e) ≫ (l₂ ≫ r₂) ◁ g₂ ◁ adj₃.unit) ⊗≫ + (r₁ ◁ (α ▷ (r₂ ≫ g₂ ≫ l₃) ≫ (l₁ ≫ h₁) ◁ r₂ ◁ β) ▷ r₃) ⊗≫ + (adj₁.counit ▷ h₁ ▷ (r₂ ≫ l₂) ≫ (𝟙 b ≫ h₁) ◁ adj₂.counit) ▷ h₂ ▷ r₃ ⊗≫ 𝟙 _ := by + rw [← whisker_exchange, ← whisker_exchange] + bicategory + _ = 𝟙 _ ⊗≫ r₁ ◁ g₁ ◁ g₂ ◁ adj₃.unit ⊗≫ + r₁ ◁ g₁ ◁ (adj₂.unit ▷ (g₂ ≫ l₃) ≫ (l₂ ≫ r₂) ◁ β) ▷ r₃ ⊗≫ + r₁ ◁ (α ▷ (r₂ ≫ l₂) ≫ (l₁ ≫ h₁) ◁ adj₂.counit) ▷ h₂ ▷ r₃ ⊗≫ + adj₁.counit ▷ h₁ ▷ h₂ ▷ r₃ ⊗≫ 𝟙 _ := by + rw [← whisker_exchange, ← whisker_exchange, ← whisker_exchange] + bicategory + _ = 𝟙 _ ⊗≫ r₁ ◁ g₁ ◁ g₂ ◁ adj₃.unit ⊗≫ r₁ ◁ g₁ ◁ β ▷ r₃ ⊗≫ + ((r₁ ≫ g₁) ◁ leftZigzag adj₂.unit adj₂.counit ▷ (h₂ ≫ r₃)) ⊗≫ + r₁ ◁ α ▷ h₂ ▷ r₃ ⊗≫ adj₁.counit ▷ h₁ ▷ h₂ ▷ r₃ ⊗≫ 𝟙 _ := by + rw [← whisker_exchange, ← whisker_exchange] + bicategory + _ = _ := by + rw [adj₂.left_triangle] + bicategory + +end mateEquivVComp + +section mateEquivHComp + +variable {a : B} {b : B} {c : B} {d : B} {e : B} {f : B} +variable {g : a ⟶ d} {h : b ⟶ e} {k : c ⟶ f} +variable {l₁ : a ⟶ b} {r₁ : b ⟶ a} {l₂ : d ⟶ e} {r₂ : e ⟶ d} +variable {l₃ : b ⟶ c} {r₃ : c ⟶ b} {l₄ : e ⟶ f} {r₄ : f ⟶ e} +variable (adj₁ : l₁ ⊣ r₁) (adj₂ : l₂ ⊣ r₂) (adj₃ : l₃ ⊣ r₃) (adj₄ : l₄ ⊣ r₄) + +/-- Squares between left adjoints can be composed "horizontally" by pasting. -/ +def leftAdjointSquare.hcomp (α : g ≫ l₂ ⟶ l₁ ≫ h) (β : h ≫ l₄ ⟶ l₃ ≫ k) : + g ≫ (l₂ ≫ l₄) ⟶ (l₁ ≫ l₃) ≫ k := + (α_ _ _ _).inv ≫ α ▷ l₄ ≫ (α_ _ _ _).hom ≫ l₁ ◁ β ≫ (α_ _ _ _).inv + +/-- Squares between right adjoints can be composed "horizontally" by pasting. -/ +def rightAdjointSquare.hcomp (α : r₁ ≫ g ⟶ h ≫ r₂) (β : r₃ ≫ h ⟶ k ≫ r₄) : + (r₃ ≫ r₁) ≫ g ⟶ k ≫ (r₄ ≫ r₂) := + (α_ _ _ _).hom ≫ r₃ ◁ α ≫ (α_ _ _ _).inv ≫ β ▷ r₂ ≫ (α_ _ _ _).hom + +/-- The mates equivalence commutes with horizontal composition of squares. -/ +theorem mateEquiv_hcomp (α : g ≫ l₂ ⟶ l₁ ≫ h) (β : h ≫ l₄ ⟶ l₃ ≫ k) : + (mateEquiv (adj₁.comp adj₃) (adj₂.comp adj₄)) (leftAdjointSquare.hcomp α β) = + rightAdjointSquare.hcomp (mateEquiv adj₁ adj₂ α) (mateEquiv adj₃ adj₄ β) := by + dsimp [mateEquiv, leftAdjointSquare.hcomp, rightAdjointSquare.hcomp] + calc + _ = 𝟙 _ ⊗≫ r₃ ◁ r₁ ◁ g ◁ adj₂.unit ⊗≫ + r₃ ◁ r₁ ◁ ((g ≫ l₂) ◁ adj₄.unit ≫ α ▷ (l₄ ≫ r₄)) ▷ r₂ ⊗≫ + r₃ ◁ ((r₁ ≫ l₁) ◁ β ≫ adj₁.counit ▷ (l₃ ≫ k)) ▷ r₄ ▷ r₂ ⊗≫ + adj₃.counit ▷ k ▷ r₄ ▷ r₂ ⊗≫ 𝟙 _ := by + bicategory + _ = 𝟙 _ ⊗≫ r₃ ◁ r₁ ◁ g ◁ adj₂.unit ⊗≫ r₃ ◁ r₁ ◁ α ▷ r₂ ⊗≫ + r₃ ◁ ((r₁ ≫ l₁) ◁ h ◁ adj₄.unit ≫ adj₁.counit ▷ (h ≫ l₄ ≫ r₄)) ▷ r₂ ⊗≫ + r₃ ◁ β ▷ r₄ ▷ r₂ ⊗≫ adj₃.counit ▷ k ▷ r₄ ▷ r₂ ⊗≫ 𝟙 _ := by + rw [whisker_exchange, whisker_exchange] + bicategory + _ = _ := by + rw [whisker_exchange] + bicategory + +end mateEquivHComp + +end Bicategory + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean b/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean index ac3e11be6fb37..99316716f3e62 100644 --- a/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean +++ b/Mathlib/CategoryTheory/Bicategory/Kan/Adjunction.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yuma Mizuno -/ import Mathlib.CategoryTheory.Bicategory.Kan.HasKan -import Mathlib.CategoryTheory.Bicategory.Adjunction +import Mathlib.CategoryTheory.Bicategory.Adjunction.Basic import Mathlib.Tactic.TFAE /-! diff --git a/scripts/noshake.json b/scripts/noshake.json index ef5a9e86f0813..d283ad44e616b 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -430,7 +430,7 @@ ["Mathlib.Tactic.CategoryTheory.ToApp"], "Mathlib.CategoryTheory.Bicategory.Functor.Lax": ["Mathlib.Tactic.CategoryTheory.ToApp"], - "Mathlib.CategoryTheory.Bicategory.Adjunction": + "Mathlib.CategoryTheory.Bicategory.Adjunction.Basic": ["Mathlib.Tactic.CategoryTheory.Bicategory.Basic"], "Mathlib.Analysis.Normed.Operator.LinearIsometry": ["Mathlib.Algebra.Star.Basic"], From 6882ea711ba098b17868ee77021ab04fb56211a1 Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Tue, 21 Jan 2025 06:28:47 +0000 Subject: [PATCH 371/681] refactor(Data/ZMod/Quotient): Split file (#20894) This PR splits `Mathlib/Data/ZMod/Quotient.lean` into a group-theory file and a ring-theory file. This makes sure that the file on cyclic groups doesn't import ideals. --- Mathlib.lean | 3 +- Mathlib/Algebra/Module/Torsion.lean | 1 + .../{Quotient.lean => QuotientGroup.lean} | 40 ++----------- Mathlib/Data/ZMod/QuotientRing.lean | 59 +++++++++++++++++++ Mathlib/GroupTheory/FiniteAbelian/Basic.lean | 2 +- .../GroupTheory/SpecificGroups/Cyclic.lean | 3 +- .../FreeModule/IdealQuotient.lean | 2 +- Mathlib/LinearAlgebra/FreeModule/Int.lean | 2 +- .../Matrix/SpecialLinearGroup.lean | 1 + Mathlib/MeasureTheory/Group/AddCircle.lean | 2 +- .../Cyclotomic/CyclotomicCharacter.lean | 1 + .../RingTheory/AdicCompletion/Algebra.lean | 3 +- .../DedekindDomain/SelmerGroup.lean | 2 +- 13 files changed, 78 insertions(+), 43 deletions(-) rename Mathlib/Data/ZMod/{Quotient.lean => QuotientGroup.lean} (80%) create mode 100644 Mathlib/Data/ZMod/QuotientRing.lean diff --git a/Mathlib.lean b/Mathlib.lean index b9cd45e7d7a0a..27b98639892c7 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3043,7 +3043,8 @@ import Mathlib.Data.ZMod.Coprime import Mathlib.Data.ZMod.Defs import Mathlib.Data.ZMod.Factorial import Mathlib.Data.ZMod.IntUnitsPower -import Mathlib.Data.ZMod.Quotient +import Mathlib.Data.ZMod.QuotientGroup +import Mathlib.Data.ZMod.QuotientRing import Mathlib.Data.ZMod.Units import Mathlib.Deprecated.AlgebraClasses import Mathlib.Deprecated.Aliases diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index 7443d4cffa6a7..eeb6959fc276f 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.Module.ZMod import Mathlib.GroupTheory.Torsion import Mathlib.LinearAlgebra.Isomorphisms import Mathlib.RingTheory.Coprime.Ideal +import Mathlib.RingTheory.Ideal.Quotient.Defs /-! # Torsion submodules diff --git a/Mathlib/Data/ZMod/Quotient.lean b/Mathlib/Data/ZMod/QuotientGroup.lean similarity index 80% rename from Mathlib/Data/ZMod/Quotient.lean rename to Mathlib/Data/ZMod/QuotientGroup.lean index 8f05b3b2992d5..10496556935c0 100644 --- a/Mathlib/Data/ZMod/Quotient.lean +++ b/Mathlib/Data/ZMod/QuotientGroup.lean @@ -3,32 +3,28 @@ Copyright (c) 2021 Anne Baanen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ -import Mathlib.RingTheory.Ideal.Quotient.Operations +import Mathlib.Data.ZMod.Basic import Mathlib.RingTheory.Int.Basic -import Mathlib.RingTheory.ZMod /-! # `ZMod n` and quotient groups / rings -This file relates `ZMod n` to the quotient group -`ℤ / AddSubgroup.zmultiples (n : ℤ)` and to the quotient ring -`ℤ ⧸ Ideal.span {(n : ℤ)}`. +This file relates `ZMod n` to the quotient group `ℤ / AddSubgroup.zmultiples (n : ℤ)`. ## Main definitions - `ZMod.quotientZMultiplesNatEquivZMod` and `ZMod.quotientZMultiplesEquivZMod`: `ZMod n` is the group quotient of `ℤ` by `n ℤ := AddSubgroup.zmultiples (n)`, (where `n : ℕ` and `n : ℤ` respectively) - - `ZMod.quotient_span_nat_equiv_zmod` and `ZMod.quotientSpanEquivZMod `: - `ZMod n` is the ring quotient of `ℤ` by `n ℤ : Ideal.span {n}` - (where `n : ℕ` and `n : ℤ` respectively) - `ZMod.lift n f` is the map from `ZMod n` induced by `f : ℤ →+ A` that maps `n` to `0`. ## Tags -zmod, quotient group, quotient ring, ideal quotient +zmod, quotient group -/ +assert_not_exists TwoSidedIdeal + open QuotientAddGroup Set ZMod variable (n : ℕ) {A R : Type*} [AddGroup A] [Ring R] @@ -44,38 +40,12 @@ def quotientZMultiplesNatEquivZMod : ℤ ⧸ AddSubgroup.zmultiples (n : ℤ) def quotientZMultiplesEquivZMod (a : ℤ) : ℤ ⧸ AddSubgroup.zmultiples a ≃+ ZMod a.natAbs := (quotientAddEquivOfEq (zmultiples_natAbs a)).symm.trans (quotientZMultiplesNatEquivZMod a.natAbs) -/-- `ℤ` modulo the ideal generated by `n : ℕ` is `ZMod n`. -/ -def quotientSpanNatEquivZMod : ℤ ⧸ Ideal.span {(n : ℤ)} ≃+* ZMod n := - (Ideal.quotEquivOfEq (ZMod.ker_intCastRingHom _)).symm.trans <| - RingHom.quotientKerEquivOfRightInverse <| - show Function.RightInverse ZMod.cast (Int.castRingHom (ZMod n)) from intCast_zmod_cast - -/-- `ℤ` modulo the ideal generated by `a : ℤ` is `ZMod a.natAbs`. -/ -def quotientSpanEquivZMod (a : ℤ) : ℤ ⧸ Ideal.span ({a} : Set ℤ) ≃+* ZMod a.natAbs := - (Ideal.quotEquivOfEq (span_natAbs a)).symm.trans (quotientSpanNatEquivZMod a.natAbs) - @[simp] lemma index_zmultiples (a : ℤ) : (AddSubgroup.zmultiples a).index = a.natAbs := by rw [AddSubgroup.index, Nat.card_congr (quotientZMultiplesEquivZMod a).toEquiv, Nat.card_zmod] end Int -noncomputable section ChineseRemainder -open Ideal - -open scoped Function in -- required for scoped `on` notation -/-- The **Chinese remainder theorem**, elementary version for `ZMod`. See also -`Mathlib.Data.ZMod.Basic` for versions involving only two numbers. -/ -def ZMod.prodEquivPi {ι : Type*} [Fintype ι] (a : ι → ℕ) - (coprime : Pairwise (Nat.Coprime on a)) : ZMod (∏ i, a i) ≃+* Π i, ZMod (a i) := - have : Pairwise fun i j => IsCoprime (span {(a i : ℤ)}) (span {(a j : ℤ)}) := - fun _i _j h ↦ (isCoprime_span_singleton_iff _ _).mpr ((coprime h).cast (R := ℤ)) - Int.quotientSpanNatEquivZMod _ |>.symm.trans <| - quotEquivOfEq (iInf_span_singleton_natCast (R := ℤ) coprime) |>.symm.trans <| - quotientInfRingEquivPiQuotient _ this |>.trans <| - RingEquiv.piCongrRight fun i ↦ Int.quotientSpanNatEquivZMod (a i) - -end ChineseRemainder namespace AddAction diff --git a/Mathlib/Data/ZMod/QuotientRing.lean b/Mathlib/Data/ZMod/QuotientRing.lean new file mode 100644 index 0000000000000..131a259756d32 --- /dev/null +++ b/Mathlib/Data/ZMod/QuotientRing.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2021 Anne Baanen. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Anne Baanen +-/ +import Mathlib.RingTheory.Ideal.Quotient.Operations +import Mathlib.RingTheory.Int.Basic +import Mathlib.RingTheory.ZMod + +/-! +# `ZMod n` and quotient groups / rings + +This file relates `ZMod n` to the quotient ring `ℤ ⧸ Ideal.span {(n : ℤ)}`. + +## Main definitions + + - `ZMod.quotient_span_nat_equiv_zmod` and `ZMod.quotientSpanEquivZMod `: + `ZMod n` is the ring quotient of `ℤ` by `n ℤ : Ideal.span {n}` + (where `n : ℕ` and `n : ℤ` respectively) + +## Tags + +zmod, quotient ring, ideal quotient +-/ + +open QuotientAddGroup Set ZMod + +variable (n : ℕ) {A R : Type*} [AddGroup A] [Ring R] + +namespace Int + +/-- `ℤ` modulo the ideal generated by `n : ℕ` is `ZMod n`. -/ +def quotientSpanNatEquivZMod : ℤ ⧸ Ideal.span {(n : ℤ)} ≃+* ZMod n := + (Ideal.quotEquivOfEq (ZMod.ker_intCastRingHom _)).symm.trans <| + RingHom.quotientKerEquivOfRightInverse <| + show Function.RightInverse ZMod.cast (Int.castRingHom (ZMod n)) from intCast_zmod_cast + +/-- `ℤ` modulo the ideal generated by `a : ℤ` is `ZMod a.natAbs`. -/ +def quotientSpanEquivZMod (a : ℤ) : ℤ ⧸ Ideal.span ({a} : Set ℤ) ≃+* ZMod a.natAbs := + (Ideal.quotEquivOfEq (span_natAbs a)).symm.trans (quotientSpanNatEquivZMod a.natAbs) + +end Int + +noncomputable section ChineseRemainder +open Ideal + +open scoped Function in -- required for scoped `on` notation +/-- The **Chinese remainder theorem**, elementary version for `ZMod`. See also +`Mathlib.Data.ZMod.Basic` for versions involving only two numbers. -/ +def ZMod.prodEquivPi {ι : Type*} [Fintype ι] (a : ι → ℕ) + (coprime : Pairwise (Nat.Coprime on a)) : ZMod (∏ i, a i) ≃+* Π i, ZMod (a i) := + have : Pairwise fun i j => IsCoprime (span {(a i : ℤ)}) (span {(a j : ℤ)}) := + fun _i _j h ↦ (isCoprime_span_singleton_iff _ _).mpr ((coprime h).cast (R := ℤ)) + Int.quotientSpanNatEquivZMod _ |>.symm.trans <| + quotEquivOfEq (iInf_span_singleton_natCast (R := ℤ) coprime) |>.symm.trans <| + quotientInfRingEquivPiQuotient _ this |>.trans <| + RingEquiv.piCongrRight fun i ↦ Int.quotientSpanNatEquivZMod (a i) + +end ChineseRemainder diff --git a/Mathlib/GroupTheory/FiniteAbelian/Basic.lean b/Mathlib/GroupTheory/FiniteAbelian/Basic.lean index 38fa544799b25..45360f7df2277 100644 --- a/Mathlib/GroupTheory/FiniteAbelian/Basic.lean +++ b/Mathlib/GroupTheory/FiniteAbelian/Basic.lean @@ -5,7 +5,7 @@ Authors: Pierre-Alexandre Bazin -/ import Mathlib.Algebra.Module.PID import Mathlib.Algebra.Group.TypeTags.Finite -import Mathlib.Data.ZMod.Quotient +import Mathlib.Data.ZMod.QuotientRing /-! # Structure of finite(ly generated) abelian groups diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index 394f2d018f935..44e9501b1c31a 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -6,7 +6,7 @@ Authors: Johannes Hölzl import Mathlib.Algebra.Order.BigOperators.Ring.Finset import Mathlib.Data.Nat.Totient import Mathlib.Data.ZMod.Aut -import Mathlib.Data.ZMod.Quotient +import Mathlib.Data.ZMod.QuotientGroup import Mathlib.GroupTheory.OrderOfElement import Mathlib.GroupTheory.SpecificGroups.Dihedral import Mathlib.GroupTheory.Subgroup.Simple @@ -40,6 +40,7 @@ For the concrete cyclic group of order `n`, see `Data.ZMod.Basic`. cyclic group -/ +assert_not_exists TwoSidedIdeal variable {α G G' : Type*} {a : α} diff --git a/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean b/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean index 7e5fc7690e990..c083bf2d95447 100644 --- a/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean +++ b/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean @@ -9,7 +9,7 @@ import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition import Mathlib.LinearAlgebra.Quotient.Pi import Mathlib.RingTheory.Ideal.Basis import Mathlib.LinearAlgebra.Dimension.Constructions -import Mathlib.Data.ZMod.Quotient +import Mathlib.Data.ZMod.QuotientRing /-! # Ideals in free modules over PIDs diff --git a/Mathlib/LinearAlgebra/FreeModule/Int.lean b/Mathlib/LinearAlgebra/FreeModule/Int.lean index c1b47b07a0ef7..c9a94cdfd1bce 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Int.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Int.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Joseph Myers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers -/ -import Mathlib.Data.ZMod.Quotient +import Mathlib.Data.ZMod.QuotientGroup import Mathlib.GroupTheory.Index import Mathlib.LinearAlgebra.FreeModule.PID diff --git a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean index 1bc8dac9cd047..04b4156f29cde 100644 --- a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean +++ b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen, Wen Yang -/ import Mathlib.LinearAlgebra.Matrix.Adjugate +import Mathlib.LinearAlgebra.Matrix.ToLin import Mathlib.LinearAlgebra.Matrix.Transvection import Mathlib.RingTheory.RootsOfUnity.Basic diff --git a/Mathlib/MeasureTheory/Group/AddCircle.lean b/Mathlib/MeasureTheory/Group/AddCircle.lean index 3f20417353a69..1361c8e0de0cc 100644 --- a/Mathlib/MeasureTheory/Group/AddCircle.lean +++ b/Mathlib/MeasureTheory/Group/AddCircle.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.MeasureTheory.Integral.Periodic -import Mathlib.Data.ZMod.Quotient +import Mathlib.Data.ZMod.QuotientGroup import Mathlib.MeasureTheory.Group.AEStabilizer /-! diff --git a/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean b/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean index dde29ae2b1750..3ecf1367d697a 100644 --- a/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean +++ b/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean @@ -3,6 +3,7 @@ Copyright (c) 2023 Hanneke Wiersema. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Buzzard, Hanneke Wiersema -/ +import Mathlib.Algebra.Ring.Aut import Mathlib.RingTheory.RootsOfUnity.PrimitiveRoots /-! diff --git a/Mathlib/RingTheory/AdicCompletion/Algebra.lean b/Mathlib/RingTheory/AdicCompletion/Algebra.lean index 88851779d0e30..732a04c01ad0d 100644 --- a/Mathlib/RingTheory/AdicCompletion/Algebra.lean +++ b/Mathlib/RingTheory/AdicCompletion/Algebra.lean @@ -3,8 +3,9 @@ Copyright (c) 2024 Judith Ludwig, Christian Merten. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Judith Ludwig, Christian Merten -/ -import Mathlib.RingTheory.AdicCompletion.Basic import Mathlib.Algebra.Module.Torsion +import Mathlib.Algebra.Algebra.Pi +import Mathlib.RingTheory.AdicCompletion.Basic /-! # Algebra instance on adic completion diff --git a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean index 7dc77adaeda72..95dc12c2a9341 100644 --- a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean +++ b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Kurniadi Angdinata -/ import Mathlib.Algebra.Group.Equiv.TypeTags -import Mathlib.Data.ZMod.Quotient +import Mathlib.Data.ZMod.QuotientGroup import Mathlib.RingTheory.DedekindDomain.AdicValuation import Mathlib.Algebra.Group.Int.TypeTags From a52aa033a18f691fabbec4a1787cce8fee0da54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 21 Jan 2025 06:54:47 +0000 Subject: [PATCH 372/681] chore(Topology/Instances/Real): reduce imports (#20548) --- Mathlib/Analysis/Normed/Group/Quotient.lean | 1 - .../SpecialFunctions/Trigonometric/Basic.lean | 3 ++- Mathlib/Analysis/SpecificLimits/Normed.lean | 1 - Mathlib/Topology/Instances/Real/Defs.lean | 9 +++++++-- Mathlib/Topology/Instances/Real/Lemmas.lean | 11 +---------- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Mathlib/Analysis/Normed/Group/Quotient.lean b/Mathlib/Analysis/Normed/Group/Quotient.lean index d931b9c66849f..0009c2a130e4e 100644 --- a/Mathlib/Analysis/Normed/Group/Quotient.lean +++ b/Mathlib/Analysis/Normed/Group/Quotient.lean @@ -7,7 +7,6 @@ import Mathlib.Analysis.Normed.Module.Basic import Mathlib.Analysis.Normed.Group.Hom import Mathlib.RingTheory.Ideal.Quotient.Operations import Mathlib.Topology.MetricSpace.HausdorffDistance -import Mathlib.Topology.Instances.Real.Lemmas /-! # Quotients of seminormed groups diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean index 9caf00dfe93d5..ac5453bf1c463 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean @@ -3,10 +3,11 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne, Benjamin Davidson -/ +import Mathlib.Algebra.Periodic import Mathlib.Algebra.QuadraticDiscriminant +import Mathlib.Algebra.Ring.NegOnePow import Mathlib.Analysis.SpecialFunctions.Exp import Mathlib.Tactic.Positivity.Core -import Mathlib.Algebra.Ring.NegOnePow /-! # Trigonometric functions diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index ae93fb202eb70..10783716eb430 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -15,7 +15,6 @@ import Mathlib.Data.Nat.Choose.Bounds import Mathlib.Order.Filter.AtTopBot.ModEq import Mathlib.RingTheory.Polynomial.Pochhammer import Mathlib.Tactic.NoncommRing -import Mathlib.Topology.Instances.Real.Lemmas /-! # A collection of specific limit computations diff --git a/Mathlib/Topology/Instances/Real/Defs.lean b/Mathlib/Topology/Instances/Real/Defs.lean index 93400ed393606..6271ff4cf3eb8 100644 --- a/Mathlib/Topology/Instances/Real/Defs.lean +++ b/Mathlib/Topology/Instances/Real/Defs.lean @@ -6,14 +6,15 @@ Authors: Johannes Hölzl, Mario Carneiro import Mathlib.Data.Real.Star import Mathlib.Topology.Algebra.Order.Field import Mathlib.Topology.Algebra.Star +import Mathlib.Topology.Algebra.UniformGroup.Defs import Mathlib.Topology.Instances.Int import Mathlib.Topology.Order.Bornology -import Mathlib.Topology.Algebra.UniformGroup.Defs /-! # Topological properties of ℝ -/ -assert_not_exists UniformOnFun + +assert_not_exists UniformContinuousConstSMul UniformOnFun noncomputable section @@ -40,6 +41,10 @@ theorem Real.uniformContinuous_neg : UniformContinuous (@Neg.neg ℝ _) := instance : UniformAddGroup ℝ := UniformAddGroup.mk' Real.uniformContinuous_add Real.uniformContinuous_neg +theorem Real.uniformContinuous_const_mul {x : ℝ} : UniformContinuous (x * ·) := + uniformContinuous_of_continuousAt_zero (DistribMulAction.toAddMonoidHom ℝ x) + (continuous_const_smul x).continuousAt + -- short-circuit type class inference instance : TopologicalAddGroup ℝ := by infer_instance instance : TopologicalRing ℝ := inferInstance diff --git a/Mathlib/Topology/Instances/Real/Lemmas.lean b/Mathlib/Topology/Instances/Real/Lemmas.lean index a1f50ca973a4c..3ba8704780b0b 100644 --- a/Mathlib/Topology/Instances/Real/Lemmas.lean +++ b/Mathlib/Topology/Instances/Real/Lemmas.lean @@ -4,19 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Algebra.Periodic -import Mathlib.Data.Real.Star import Mathlib.Topology.Algebra.Order.Archimedean -import Mathlib.Topology.Algebra.Order.Field -import Mathlib.Topology.Algebra.Star -import Mathlib.Topology.Algebra.UniformMulAction -import Mathlib.Topology.Instances.Int -import Mathlib.Topology.Order.Bornology -import Mathlib.Topology.Algebra.UniformGroup.Defs import Mathlib.Topology.Instances.Real.Defs /-! # Topological properties of ℝ -/ + assert_not_exists UniformOnFun noncomputable section @@ -67,9 +61,6 @@ theorem Real.uniformContinuous_abs : UniformContinuous (abs : ℝ → ℝ) := theorem Real.continuous_inv : Continuous fun a : { r : ℝ // r ≠ 0 } => a.val⁻¹ := continuousOn_inv₀.restrict -theorem Real.uniformContinuous_const_mul {x : ℝ} : UniformContinuous (x * ·) := - uniformContinuous_const_smul x - theorem Real.uniformContinuous_mul (s : Set (ℝ × ℝ)) {r₁ r₂ : ℝ} (H : ∀ x ∈ s, |(x : ℝ × ℝ).1| < r₁ ∧ |x.2| < r₂) : UniformContinuous fun p : s => p.1.1 * p.1.2 := From 1264ce95ed09c73b4aadc6ec45fc7db15897e79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 21 Jan 2025 07:16:52 +0000 Subject: [PATCH 373/681] feat(CategoryTheory): the equivalence of categories induced by a bijection (#20881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `f : T → D` is a map and `D` is a category, then `InducedCategory D f` is a category with objects `T` with a fully faithful functor to `D`. In this PR, we show that in the case of a bijection `T ≃ D`, the induced category is equivalent to `D`. The code would be nicer (see #19945) if the type of morphisms in the induced category was defined as a 1-field structure. This would be a very welcomed refactor. --- Mathlib/CategoryTheory/EqToHom.lean | 22 ++++++++++++++++++++ Mathlib/CategoryTheory/EssentiallySmall.lean | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/EqToHom.lean b/Mathlib/CategoryTheory/EqToHom.lean index 1a0622b180b50..e9ede8e6dc5e4 100644 --- a/Mathlib/CategoryTheory/EqToHom.lean +++ b/Mathlib/CategoryTheory/EqToHom.lean @@ -338,4 +338,26 @@ theorem dcongr_arg {ι : Type*} {F G : ι → C} (α : ∀ i, F i ⟶ G i) {i j subst h simp +/-- If `T ≃ D` is a bijection and `D` is a category, then +`InducedCategory D e` is equivalent to `D`. -/ +@[simps] +def Equivalence.induced {T : Type*} (e : T ≃ D) : + InducedCategory D e ≌ D where + functor := inducedFunctor e + inverse := + { obj := e.symm + map {X Y} f := show e (e.symm X) ⟶ e (e.symm Y) from + eqToHom (e.apply_symm_apply X) ≫ f ≫ + eqToHom (e.apply_symm_apply Y).symm + map_comp {X Y Z} f g := by + dsimp + erw [Category.assoc, Category.assoc, Category.assoc] + rw [eqToHom_trans_assoc, eqToHom_refl, Category.id_comp] } + unitIso := NatIso.ofComponents (fun _ ↦ eqToIso (by simp)) (fun {X Y} f ↦ by + dsimp + erw [eqToHom_trans_assoc _ (by simp), eqToHom_refl, Category.id_comp] + rfl ) + counitIso := NatIso.ofComponents (fun _ ↦ eqToIso (by simp)) + functor_unitIso_comp X := eqToHom_trans (by simp) (by simp) + end CategoryTheory diff --git a/Mathlib/CategoryTheory/EssentiallySmall.lean b/Mathlib/CategoryTheory/EssentiallySmall.lean index 7e6ec94a768c1..f3ff9dccad071 100644 --- a/Mathlib/CategoryTheory/EssentiallySmall.lean +++ b/Mathlib/CategoryTheory/EssentiallySmall.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ import Mathlib.CategoryTheory.Category.ULift +import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Skeletal import Mathlib.Logic.UnivLE import Mathlib.Logic.Small.Basic @@ -187,7 +188,7 @@ noncomputable instance [Small.{w} C] : Category.{v} (Shrink.{w} C) := /-- The categorical equivalence between `C` and `Shrink C`, when `C` is small. -/ noncomputable def equivalence [Small.{w} C] : C ≌ Shrink.{w} C := - (inducedFunctor (equivShrink C).symm).asEquivalence.symm + (Equivalence.induced _).symm end Shrink From 45c7be45f5859972b869ffd8193426332e579735 Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 21 Jan 2025 11:30:30 +0000 Subject: [PATCH 374/681] fix(CI): use `gawk` instead of `awk` (#20909) This probably makes running the import diff script locally friendlier for MacOS users that have `gawk` installed. [Zulip discussion](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/import.20diff.20bot) --- scripts/import_trans_difference.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/import_trans_difference.sh b/scripts/import_trans_difference.sh index 30902e69f971e..8c72ba69ef2ed 100755 --- a/scripts/import_trans_difference.sh +++ b/scripts/import_trans_difference.sh @@ -67,7 +67,7 @@ git checkout "${currCommit}" printf '\n\n
Import changes for all files\n\n%s\n\n
\n' "$( printf "|Files|Import difference|\n|-|-|\n" - (awk -F, -v all="${all}" -v ghLimit='261752' -v newFiles="$( + (gawk -F, -v all="${all}" -v ghLimit='261752' -v newFiles="$( # we pass the "A"dded files with respect to master, converting them to module names git diff --name-only --diff-filter=A master | tr '\n' , | sed 's=\.lean,=,=g; s=/=.=g' )" ' From c499ecfa12ad67992d82c79ba0b7590bd0858550 Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Tue, 21 Jan 2025 11:45:12 +0000 Subject: [PATCH 375/681] feat(Matroid): all bases of a finitary matroid have the same cardinality (#20888) Co-authored-by: Peter Nelson Co-authored-by: Peter Nelson <71660771+apnelson1@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Data/Matroid/Rank/Cardinal.lean | 102 ++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 Mathlib/Data/Matroid/Rank/Cardinal.lean diff --git a/Mathlib.lean b/Mathlib.lean index 27b98639892c7..2c85a96c3bedd 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2756,6 +2756,7 @@ import Mathlib.Data.Matroid.Dual import Mathlib.Data.Matroid.IndepAxioms import Mathlib.Data.Matroid.Init import Mathlib.Data.Matroid.Map +import Mathlib.Data.Matroid.Rank.Cardinal import Mathlib.Data.Matroid.Restrict import Mathlib.Data.Matroid.Sum import Mathlib.Data.Multiset.Antidiagonal diff --git a/Mathlib/Data/Matroid/Rank/Cardinal.lean b/Mathlib/Data/Matroid/Rank/Cardinal.lean new file mode 100644 index 0000000000000..b12a9f56efadb --- /dev/null +++ b/Mathlib/Data/Matroid/Rank/Cardinal.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2025 Peter Nelson and Junyan Xu. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Peter Nelson, Junyan Xu +-/ +import Mathlib.Data.Matroid.Restrict +import Mathlib.SetTheory.Cardinal.Arithmetic + +/-! +# Invariance of cardinality of bases of a finitary matroid + +In a finitary matroid, all bases have the same cardinality. +In fact, something stronger holds: if `B` and `B'` are bases, then `#(B \ B') = #(B' \ B)`. +This file provides proofs of these facts, +as well as variants when each of `B` and `B'` is a `Basis` or `Basis'` of some common set `X`. + +Some extra assumption like `Finitary` is necessary for these to be true, +since the equicardinality of bases in general matroids is independent of ZFC +(see the docstring of `Data.Matroid.Basic`). +Lemmas like `Matroid.Base.cardinalMk_diff_comm_of_finitary` +become true for all matroids if they are weakened by replacing `Cardinal.mk` +with the cruder `ℕ∞`-valued `encard`; see, for example, `Matroid.Base.encard_diff_comm`. + +TODO + +* Higg's theorem that, if the generalized continuum hypothesis holds, + all bases of any matroid are equicardinal. +* API for a `Cardinal`-valued rank function. +-/ + +variable {α : Type*} {M : Matroid α} {I J B B' X : Set α} [M.Finitary] + +open Cardinal Set + +namespace Matroid + +theorem Base.cardinalMk_diff_comm_of_finitary (hB : M.Base B) (hB' : M.Base B') : + #(B \ B' : Set α) = #(B' \ B : Set α) := by + wlog hge : #(B' \ B : Set α) ≤ #(B \ B' : Set α) with aux + · exact (aux hB' hB (not_le.1 hge).le).symm + by_cases h : (B' \ B).Finite + · rw [← cast_ncard h, ← cast_ncard, hB.ncard_diff_comm hB'] + exact (diff_finite_comm hB' hB).mp h + rw [← Set.Infinite, ← infinite_coe_iff] at h + have (a : α) (ha : a ∈ B' \ B) : ∃ S : Set α, Finite S ∧ S ⊆ B ∧ ¬ M.Indep (insert a S) := by + have := (hB.insert_dep ⟨hB'.subset_ground ha.1, ha.2⟩).1 + contrapose! this + exact Finitary.indep_of_forall_finite _ fun J hJ fin ↦ (this (J \ {a}) fin.diff.to_subtype <| + diff_singleton_subset_iff.mpr hJ).subset (subset_insert_diff_singleton ..) + choose S S_fin hSB dep using this + let U := ⋃ a : ↥(B' \ B), S a a.2 + suffices B \ B' ⊆ U by + refine hge.antisymm' <| (mk_le_mk_of_subset this).trans <| (mk_iUnion_le ..).trans + <| (mul_le_max_of_aleph0_le_left (by simp)).trans ?_ + simp only [sup_le_iff, le_refl, true_and] + exact ciSup_le' fun e ↦ (lt_aleph0_of_finite _).le.trans <| by simp + rw [← diff_inter_self_eq_diff, diff_subset_iff, inter_comm] + have hUB : (B ∩ B') ∪ U ⊆ B := + union_subset inter_subset_left (iUnion_subset fun e ↦ (hSB e.1 e.2)) + by_contra hBU + have ⟨a, ha, ind⟩ := hB.exists_insert_of_ssubset ⟨hUB, hBU⟩ hB' + have : a ∈ B' \ B := ⟨ha.1, fun haB ↦ ha.2 (.inl ⟨haB, ha.1⟩)⟩ + refine dep a this (ind.subset <| insert_subset_insert <| .trans ?_ subset_union_right) + exact subset_iUnion_of_subset ⟨a, this⟩ subset_rfl + +theorem Base.cardinalMk_eq_of_finitary (hB : M.Base B) (hB' : M.Base B') : #B = #B' := by + rw [← diff_union_inter B B', + mk_union_of_disjoint (disjoint_sdiff_left.mono_right inter_subset_right), + hB.cardinalMk_diff_comm_of_finitary hB', + ← mk_union_of_disjoint (disjoint_sdiff_left.mono_right inter_subset_left), + inter_comm, diff_union_inter] + +theorem Basis'.cardinalMk_diff_comm_of_finitary (hIX : M.Basis' I X) (hJX : M.Basis' J X) : + #(I \ J : Set α) = #(J \ I : Set α) := by + rw [← base_restrict_iff'] at hIX hJX + rw [hIX.cardinalMk_diff_comm_of_finitary hJX] + +theorem Basis.cardinalMk_diff_comm_of_finitary (hIX : M.Basis I X) (hJX : M.Basis J X) : + #(I \ J : Set α) = #(J \ I : Set α) := + hIX.basis'.cardinalMk_diff_comm_of_finitary hJX.basis' + +theorem Basis'.cardinalMk_eq_of_finitary (hIX : M.Basis' I X) (hJX : M.Basis' J X) : #I = #J := by + rw [← base_restrict_iff'] at hIX hJX + rw [hIX.cardinalMk_eq_of_finitary hJX] + +theorem Basis.cardinalMk_eq_of_finitary (hIX : M.Basis I X) (hJX : M.Basis J X) : #I = #J := + hIX.basis'.cardinalMk_eq_of_finitary hJX.basis' + +theorem Indep.cardinalMk_le_base_of_finitary (hI : M.Indep I) (hB : M.Base B) : #I ≤ #B := + have ⟨_B', hB', hIB'⟩ := hI.exists_base_superset + hB'.cardinalMk_eq_of_finitary hB ▸ mk_le_mk_of_subset hIB' + +theorem Indep.cardinalMk_le_basis'_of_finitary (hI : M.Indep I) (hJ : M.Basis' J X) (hIX : I ⊆ X) : + #I ≤ #J := + have ⟨_J', hJ', hIJ'⟩ := hI.subset_basis'_of_subset hIX + hJ'.cardinalMk_eq_of_finitary hJ ▸ mk_le_mk_of_subset hIJ' + +theorem Indep.cardinalMk_le_basis_of_finitary (hI : M.Indep I) (hJ : M.Basis J X) (hIX : I ⊆ X) : + #I ≤ #J := + hI.cardinalMk_le_basis'_of_finitary hJ.basis' hIX + +end Matroid From 3a74c6cd39110ece4ae97cca7afc39c63b199ea6 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:39:44 +0000 Subject: [PATCH 376/681] chore: split Mathlib.Order.Filter.Ultrafilter (#20848) --- Mathlib.lean | 3 +- Mathlib/ModelTheory/Satisfiability.lean | 1 + Mathlib/ModelTheory/Ultraproducts.lean | 3 +- Mathlib/Order/Filter/FilterProduct.lean | 2 +- Mathlib/Order/Filter/Pointwise.lean | 3 +- Mathlib/Order/Filter/Subsingleton.lean | 4 +- Mathlib/Order/Filter/Ultrafilter/Basic.lean | 126 ++++++++++++++++++ .../Defs.lean} | 96 +------------ Mathlib/Topology/Defs/Ultrafilter.lean | 4 +- Mathlib/Topology/Ultrafilter.lean | 2 +- 10 files changed, 143 insertions(+), 101 deletions(-) create mode 100644 Mathlib/Order/Filter/Ultrafilter/Basic.lean rename Mathlib/Order/Filter/{Ultrafilter.lean => Ultrafilter/Defs.lean} (78%) diff --git a/Mathlib.lean b/Mathlib.lean index 2c85a96c3bedd..3066f2e7f50b8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4187,7 +4187,8 @@ import Mathlib.Order.Filter.Ring import Mathlib.Order.Filter.SmallSets import Mathlib.Order.Filter.Subsingleton import Mathlib.Order.Filter.Tendsto -import Mathlib.Order.Filter.Ultrafilter +import Mathlib.Order.Filter.Ultrafilter.Basic +import Mathlib.Order.Filter.Ultrafilter.Defs import Mathlib.Order.Filter.ZeroAndBoundedAtFilter import Mathlib.Order.Fin.Basic import Mathlib.Order.Fin.Tuple diff --git a/Mathlib/ModelTheory/Satisfiability.lean b/Mathlib/ModelTheory/Satisfiability.lean index 779378c10f0df..acf91d57f6bab 100644 --- a/Mathlib/ModelTheory/Satisfiability.lean +++ b/Mathlib/ModelTheory/Satisfiability.lean @@ -6,6 +6,7 @@ Authors: Aaron Anderson import Mathlib.ModelTheory.Ultraproducts import Mathlib.ModelTheory.Bundled import Mathlib.ModelTheory.Skolem +import Mathlib.Order.Filter.AtTopBot /-! # First-Order Satisfiability diff --git a/Mathlib/ModelTheory/Ultraproducts.lean b/Mathlib/ModelTheory/Ultraproducts.lean index dbe1d5d34724f..338cdcea73860 100644 --- a/Mathlib/ModelTheory/Ultraproducts.lean +++ b/Mathlib/ModelTheory/Ultraproducts.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ import Mathlib.ModelTheory.Quotients +import Mathlib.Order.Filter.Finite import Mathlib.Order.Filter.Germ.Basic -import Mathlib.Order.Filter.Ultrafilter +import Mathlib.Order.Filter.Ultrafilter.Defs /-! # Ultraproducts and Łoś's Theorem diff --git a/Mathlib/Order/Filter/FilterProduct.lean b/Mathlib/Order/Filter/FilterProduct.lean index c36a347ed094f..c7c04367c9495 100644 --- a/Mathlib/Order/Filter/FilterProduct.lean +++ b/Mathlib/Order/Filter/FilterProduct.lean @@ -6,7 +6,7 @@ Authors: Abhimanyu Pallavi Sudhir, Yury Kudryashov import Mathlib.Algebra.Order.Field.Defs import Mathlib.Algebra.Order.Group.Unbundled.Abs import Mathlib.Order.Filter.Ring -import Mathlib.Order.Filter.Ultrafilter +import Mathlib.Order.Filter.Ultrafilter.Defs /-! # Ultraproducts diff --git a/Mathlib/Order/Filter/Pointwise.lean b/Mathlib/Order/Filter/Pointwise.lean index 05f1a4c1cf4e0..fcd4bd41d71c3 100644 --- a/Mathlib/Order/Filter/Pointwise.lean +++ b/Mathlib/Order/Filter/Pointwise.lean @@ -6,8 +6,9 @@ Authors: Zhouhang Zhou, Yaël Dillies import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Group.OrderIso import Mathlib.Data.Set.Pointwise.SMul +import Mathlib.Order.Filter.AtTopBot import Mathlib.Order.Filter.NAry -import Mathlib.Order.Filter.Ultrafilter +import Mathlib.Order.Filter.Ultrafilter.Defs /-! # Pointwise operations on filters diff --git a/Mathlib/Order/Filter/Subsingleton.lean b/Mathlib/Order/Filter/Subsingleton.lean index c8d0816c3f17b..7d82c9902f6a3 100644 --- a/Mathlib/Order/Filter/Subsingleton.lean +++ b/Mathlib/Order/Filter/Subsingleton.lean @@ -3,7 +3,9 @@ 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.Order.Filter.Ultrafilter +import Mathlib.Order.Filter.CountablyGenerated +import Mathlib.Order.Filter.Prod +import Mathlib.Order.Filter.Ultrafilter.Defs /-! # Subsingleton filters diff --git a/Mathlib/Order/Filter/Ultrafilter/Basic.lean b/Mathlib/Order/Filter/Ultrafilter/Basic.lean new file mode 100644 index 0000000000000..4ba9a72dd8feb --- /dev/null +++ b/Mathlib/Order/Filter/Ultrafilter/Basic.lean @@ -0,0 +1,126 @@ +/- +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, Jeremy Avigad, Yury Kudryashov +-/ +import Mathlib.Order.Filter.Ultrafilter.Defs +import Mathlib.Order.Filter.Cofinite +import Mathlib.Order.ZornAtoms + +/-! +# Ultrafilters + +An ultrafilter is a minimal (maximal in the set order) proper filter. +In this file we define + +* `hyperfilter`: the ultrafilter extending the cofinite filter. +-/ + +universe u v + +variable {α : Type u} {β : Type v} + +open Set Filter + +namespace Ultrafilter + +variable {f : Ultrafilter α} {s : Set α} + +theorem finite_sUnion_mem_iff {s : Set (Set α)} (hs : s.Finite) : ⋃₀ s ∈ f ↔ ∃ t ∈ s, t ∈ f := + Finite.induction_on _ hs (by simp) fun _ _ his => by + simp [union_mem_iff, his, or_and_right, exists_or] + +theorem finite_biUnion_mem_iff {is : Set β} {s : β → Set α} (his : is.Finite) : + (⋃ i ∈ is, s i) ∈ f ↔ ∃ i ∈ is, s i ∈ f := by + simp only [← sUnion_image, finite_sUnion_mem_iff (his.image s), exists_mem_image] + +lemma eventually_exists_mem_iff {is : Set β} {P : β → α → Prop} (his : is.Finite) : + (∀ᶠ i in f, ∃ a ∈ is, P a i) ↔ ∃ a ∈ is, ∀ᶠ i in f, P a i := by + simp only [Filter.Eventually, Ultrafilter.mem_coe] + convert f.finite_biUnion_mem_iff his (s := P) with i + aesop + +lemma eventually_exists_iff [Finite β] {P : β → α → Prop} : + (∀ᶠ i in f, ∃ a, P a i) ↔ ∃ a, ∀ᶠ i in f, P a i := by + simpa using eventually_exists_mem_iff (f := f) (P := P) Set.finite_univ + +theorem eq_pure_of_finite_mem (h : s.Finite) (h' : s ∈ f) : ∃ x ∈ s, f = pure x := by + rw [← biUnion_of_singleton s] at h' + rcases (Ultrafilter.finite_biUnion_mem_iff h).mp h' with ⟨a, has, haf⟩ + exact ⟨a, has, eq_of_le (Filter.le_pure_iff.2 haf)⟩ + +theorem eq_pure_of_finite [Finite α] (f : Ultrafilter α) : ∃ a, f = pure a := + (eq_pure_of_finite_mem finite_univ univ_mem).imp fun _ ⟨_, ha⟩ => ha + +theorem le_cofinite_or_eq_pure (f : Ultrafilter α) : (f : Filter α) ≤ cofinite ∨ ∃ a, f = pure a := + or_iff_not_imp_left.2 fun h => + let ⟨_, hs, hfin⟩ := Filter.disjoint_cofinite_right.1 (disjoint_iff_not_le.2 h) + let ⟨a, _, hf⟩ := eq_pure_of_finite_mem hfin hs + ⟨a, hf⟩ + +theorem exists_ultrafilter_of_finite_inter_nonempty (S : Set (Set α)) + (cond : ∀ T : Finset (Set α), (↑T : Set (Set α)) ⊆ S → (⋂₀ (↑T : Set (Set α))).Nonempty) : + ∃ F : Ultrafilter α, S ⊆ F.sets := + haveI : NeBot (generate S) := + generate_neBot_iff.2 fun _ hts ht => + ht.coe_toFinset ▸ cond ht.toFinset (ht.coe_toFinset.symm ▸ hts) + ⟨of (generate S), fun _ ht => (of_le <| generate S) <| GenerateSets.basic ht⟩ + +end Ultrafilter + +namespace Filter + +open Ultrafilter + +lemma atTop_eq_pure_of_isTop [LinearOrder α] {x : α} (hx : IsTop x) : + (atTop : Filter α) = pure x := by + have : Nonempty α := ⟨x⟩ + apply atTop_neBot.eq_pure_iff.2 + convert Ici_mem_atTop x using 1 + exact (Ici_eq_singleton_iff_isTop.2 hx).symm + +lemma atBot_eq_pure_of_isBot [LinearOrder α] {x : α} (hx : IsBot x) : + (atBot : Filter α) = pure x := + @atTop_eq_pure_of_isTop αᵒᵈ _ _ hx + +/-- The `tendsto` relation can be checked on ultrafilters. -/ +theorem tendsto_iff_ultrafilter (f : α → β) (l₁ : Filter α) (l₂ : Filter β) : + Tendsto f l₁ l₂ ↔ ∀ g : Ultrafilter α, ↑g ≤ l₁ → Tendsto f g l₂ := by + simpa only [tendsto_iff_comap] using le_iff_ultrafilter + +section Hyperfilter + +variable (α) [Infinite α] + +/-- The ultrafilter extending the cofinite filter. -/ +noncomputable def hyperfilter : Ultrafilter α := + Ultrafilter.of cofinite + +variable {α} + +theorem hyperfilter_le_cofinite : ↑(hyperfilter α) ≤ @cofinite α := + Ultrafilter.of_le cofinite + +theorem _root_.Nat.hyperfilter_le_atTop : (hyperfilter ℕ).toFilter ≤ atTop := + hyperfilter_le_cofinite.trans_eq Nat.cofinite_eq_atTop + +@[simp] +theorem bot_ne_hyperfilter : (⊥ : Filter α) ≠ hyperfilter α := + (NeBot.ne inferInstance).symm + +theorem nmem_hyperfilter_of_finite {s : Set α} (hf : s.Finite) : s ∉ hyperfilter α := fun hy => + compl_not_mem hy <| hyperfilter_le_cofinite hf.compl_mem_cofinite + +alias _root_.Set.Finite.nmem_hyperfilter := nmem_hyperfilter_of_finite + +theorem compl_mem_hyperfilter_of_finite {s : Set α} (hf : Set.Finite s) : sᶜ ∈ hyperfilter α := + compl_mem_iff_not_mem.2 hf.nmem_hyperfilter + +alias _root_.Set.Finite.compl_mem_hyperfilter := compl_mem_hyperfilter_of_finite + +theorem mem_hyperfilter_of_finite_compl {s : Set α} (hf : Set.Finite sᶜ) : s ∈ hyperfilter α := + compl_compl s ▸ hf.compl_mem_hyperfilter + +end Hyperfilter + +end Filter diff --git a/Mathlib/Order/Filter/Ultrafilter.lean b/Mathlib/Order/Filter/Ultrafilter/Defs.lean similarity index 78% rename from Mathlib/Order/Filter/Ultrafilter.lean rename to Mathlib/Order/Filter/Ultrafilter/Defs.lean index 2e3a26c64e31b..4b0710720dc94 100644 --- a/Mathlib/Order/Filter/Ultrafilter.lean +++ b/Mathlib/Order/Filter/Ultrafilter/Defs.lean @@ -3,7 +3,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, Jeremy Avigad, Yury Kudryashov -/ -import Mathlib.Order.Filter.Cofinite +import Mathlib.Order.Filter.Basic import Mathlib.Order.ZornAtoms /-! @@ -16,9 +16,10 @@ In this file we define * `Ultrafilter`: subtype of ultrafilters; * `pure x : Ultrafilter α`: `pure x` as an `Ultrafilter`; * `Ultrafilter.map`, `Ultrafilter.bind`, `Ultrafilter.comap` : operations on ultrafilters; -* `hyperfilter`: the ultrafilter extending the cofinite filter. -/ +assert_not_exists Set.Finite + universe u v variable {α : Type u} {β : Type v} {γ : Type*} @@ -160,24 +161,6 @@ theorem eventually_not : (∀ᶠ x in f, ¬p x) ↔ ¬∀ᶠ x in f, p x := theorem eventually_imp : (∀ᶠ x in f, p x → q x) ↔ (∀ᶠ x in f, p x) → ∀ᶠ x in f, q x := by simp only [imp_iff_not_or, eventually_or, eventually_not] -theorem finite_sUnion_mem_iff {s : Set (Set α)} (hs : s.Finite) : ⋃₀ s ∈ f ↔ ∃ t ∈ s, t ∈ f := - Finite.induction_on _ hs (by simp) fun _ _ his => by - simp [union_mem_iff, his, or_and_right, exists_or] - -theorem finite_biUnion_mem_iff {is : Set β} {s : β → Set α} (his : is.Finite) : - (⋃ i ∈ is, s i) ∈ f ↔ ∃ i ∈ is, s i ∈ f := by - simp only [← sUnion_image, finite_sUnion_mem_iff (his.image s), exists_mem_image] - -lemma eventually_exists_mem_iff {is : Set β} {P : β → α → Prop} (his : is.Finite) : - (∀ᶠ i in f, ∃ a ∈ is, P a i) ↔ ∃ a ∈ is, ∀ᶠ i in f, P a i := by - simp only [Filter.Eventually, Ultrafilter.mem_coe] - convert f.finite_biUnion_mem_iff his (s := P) with i - aesop - -lemma eventually_exists_iff [Finite β] {P : β → α → Prop} : - (∀ᶠ i in f, ∃ a, P a i) ↔ ∃ a, ∀ᶠ i in f, P a i := by - simpa using eventually_exists_mem_iff (f := f) (P := P) Set.finite_univ - /-- Pushforward for ultrafilters. -/ nonrec def map (m : α → β) (f : Ultrafilter α) : Ultrafilter β := ofComplNotMemIff (map m f) fun s => @compl_not_mem_iff _ f (m ⁻¹' s) @@ -269,20 +252,6 @@ instance [Inhabited α] : Inhabited (Ultrafilter α) := instance [Nonempty α] : Nonempty (Ultrafilter α) := Nonempty.map pure inferInstance -theorem eq_pure_of_finite_mem (h : s.Finite) (h' : s ∈ f) : ∃ x ∈ s, f = pure x := by - rw [← biUnion_of_singleton s] at h' - rcases (Ultrafilter.finite_biUnion_mem_iff h).mp h' with ⟨a, has, haf⟩ - exact ⟨a, has, eq_of_le (Filter.le_pure_iff.2 haf)⟩ - -theorem eq_pure_of_finite [Finite α] (f : Ultrafilter α) : ∃ a, f = pure a := - (eq_pure_of_finite_mem finite_univ univ_mem).imp fun _ ⟨_, ha⟩ => ha - -theorem le_cofinite_or_eq_pure (f : Ultrafilter α) : (f : Filter α) ≤ cofinite ∨ ∃ a, f = pure a := - or_iff_not_imp_left.2 fun h => - let ⟨_, hs, hfin⟩ := Filter.disjoint_cofinite_right.1 (disjoint_iff_not_le.2 h) - let ⟨a, _, hf⟩ := eq_pure_of_finite_mem hfin hs - ⟨a, hf⟩ - /-- Monadic bind for ultrafilters, coming from the one on filters defined in terms of map and join. -/ def bind (f : Ultrafilter α) (m : α → Ultrafilter β) : Ultrafilter β := @@ -332,14 +301,6 @@ theorem of_le (f : Filter α) [NeBot f] : ↑(of f) ≤ f := theorem of_coe (f : Ultrafilter α) : of ↑f = f := coe_inj.1 <| f.unique (of_le f.toFilter) -theorem exists_ultrafilter_of_finite_inter_nonempty (S : Set (Set α)) - (cond : ∀ T : Finset (Set α), (↑T : Set (Set α)) ⊆ S → (⋂₀ (↑T : Set (Set α))).Nonempty) : - ∃ F : Ultrafilter α, S ⊆ F.sets := - haveI : NeBot (generate S) := - generate_neBot_iff.2 fun _ hts ht => - ht.coe_toFinset ▸ cond ht.toFinset (ht.coe_toFinset.symm ▸ hts) - ⟨of (generate S), fun _ ht => (of_le <| generate S) <| GenerateSets.basic ht⟩ - end Ultrafilter namespace Filter @@ -358,17 +319,6 @@ protected theorem NeBot.eq_pure_iff (hf : f.NeBot) {x : α} : f = pure x ↔ {x} ∈ f := by rw [← hf.le_pure_iff, le_pure_iff] -lemma atTop_eq_pure_of_isTop [LinearOrder α] {x : α} (hx : IsTop x) : - (atTop : Filter α) = pure x := by - have : Nonempty α := ⟨x⟩ - apply atTop_neBot.eq_pure_iff.2 - convert Ici_mem_atTop x using 1 - exact (Ici_eq_singleton_iff_isTop.2 hx).symm - -lemma atBot_eq_pure_of_isBot [LinearOrder α] {x : α} (hx : IsBot x) : - (atBot : Filter α) = pure x := - @atTop_eq_pure_of_isTop αᵒᵈ _ _ hx - @[simp] theorem lt_pure_iff : f < pure a ↔ f = ⊥ := isAtom_pure.lt_iff @@ -394,11 +344,6 @@ theorem iSup_ultrafilter_le_eq (f : Filter α) : ⨆ (g : Ultrafilter α) (_ : g ≤ f), (g : Filter α) = f := eq_of_forall_ge_iff fun f' => by simp only [iSup_le_iff, ← le_iff_ultrafilter] -/-- The `tendsto` relation can be checked on ultrafilters. -/ -theorem tendsto_iff_ultrafilter (f : α → β) (l₁ : Filter α) (l₂ : Filter β) : - Tendsto f l₁ l₂ ↔ ∀ g : Ultrafilter α, ↑g ≤ l₁ → Tendsto f g l₂ := by - simpa only [tendsto_iff_comap] using le_iff_ultrafilter - theorem exists_ultrafilter_iff {f : Filter α} : (∃ u : Ultrafilter α, ↑u ≤ f) ↔ NeBot f := ⟨fun ⟨_, uf⟩ => neBot_of_le uf, fun h => @exists_ultrafilter_le _ _ h⟩ @@ -408,41 +353,6 @@ theorem forall_neBot_le_iff {g : Filter α} {p : Filter α → Prop} (hp : Monot intro H f hf hfg exact hp (of_le f) (H _ ((of_le f).trans hfg)) -section Hyperfilter - -variable (α) [Infinite α] - -/-- The ultrafilter extending the cofinite filter. -/ -noncomputable def hyperfilter : Ultrafilter α := - Ultrafilter.of cofinite - -variable {α} - -theorem hyperfilter_le_cofinite : ↑(hyperfilter α) ≤ @cofinite α := - Ultrafilter.of_le cofinite - -theorem _root_.Nat.hyperfilter_le_atTop : (hyperfilter ℕ).toFilter ≤ atTop := - hyperfilter_le_cofinite.trans_eq Nat.cofinite_eq_atTop - -@[simp] -theorem bot_ne_hyperfilter : (⊥ : Filter α) ≠ hyperfilter α := - (NeBot.ne inferInstance).symm - -theorem nmem_hyperfilter_of_finite {s : Set α} (hf : s.Finite) : s ∉ hyperfilter α := fun hy => - compl_not_mem hy <| hyperfilter_le_cofinite hf.compl_mem_cofinite - -alias _root_.Set.Finite.nmem_hyperfilter := nmem_hyperfilter_of_finite - -theorem compl_mem_hyperfilter_of_finite {s : Set α} (hf : Set.Finite s) : sᶜ ∈ hyperfilter α := - compl_mem_iff_not_mem.2 hf.nmem_hyperfilter - -alias _root_.Set.Finite.compl_mem_hyperfilter := compl_mem_hyperfilter_of_finite - -theorem mem_hyperfilter_of_finite_compl {s : Set α} (hf : Set.Finite sᶜ) : s ∈ hyperfilter α := - compl_compl s ▸ hf.compl_mem_hyperfilter - -end Hyperfilter - end Filter namespace Ultrafilter diff --git a/Mathlib/Topology/Defs/Ultrafilter.lean b/Mathlib/Topology/Defs/Ultrafilter.lean index 894eb001af96f..312adb41a2af2 100644 --- a/Mathlib/Topology/Defs/Ultrafilter.lean +++ b/Mathlib/Topology/Defs/Ultrafilter.lean @@ -3,9 +3,9 @@ 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, Mario Carneiro, Jeremy Avigad -/ -import Mathlib.Topology.Defs.Basic -import Mathlib.Order.Filter.Ultrafilter import Mathlib.Data.Set.Lattice +import Mathlib.Order.Filter.Ultrafilter.Defs +import Mathlib.Topology.Defs.Basic import Mathlib.Topology.Defs.Filter /-! diff --git a/Mathlib/Topology/Ultrafilter.lean b/Mathlib/Topology/Ultrafilter.lean index 6329b619e4334..5927cb6d15ae8 100644 --- a/Mathlib/Topology/Ultrafilter.lean +++ b/Mathlib/Topology/Ultrafilter.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Mario Carneiro, Jeremy Avigad -/ import Mathlib.Order.Filter.Lift import Mathlib.Topology.Basic -import Mathlib.Order.Filter.Ultrafilter +import Mathlib.Order.Filter.Ultrafilter.Basic /-! # Characterization of basic topological properties in terms of ultrafilters -/ From 22d5b96853b1b27e6b23d2770ed15dcc4bf5f7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 21 Jan 2025 14:10:03 +0000 Subject: [PATCH 377/681] =?UTF-8?q?chore:=20rename=20`zero=5Fmem=E2=84=92p?= =?UTF-8?q?`=20to=20`Mem=E2=84=92p.zero`=20(#20915)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This better matches the naming convention and unlocks anonymous dot notation. Also make both lemmas simp. From my PhD (LeanCamCombi) --- .../MeasureTheory/Function/LpSeminorm/Basic.lean | 13 +++++++------ .../Function/LpSeminorm/TriangleInequality.lean | 2 +- Mathlib/MeasureTheory/Function/LpSpace.lean | 4 ++-- .../MeasureTheory/Function/SimpleFuncDenseLp.lean | 4 ++-- Mathlib/Probability/Process/Filtration.lean | 2 +- scripts/nolints_prime_decls.txt | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean index 783a4b1169548..a2019826e26f5 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean @@ -265,12 +265,13 @@ theorem eLpNorm_zero' : eLpNorm (fun _ : α => (0 : F)) p μ = 0 := by convert e @[deprecated (since := "2024-07-27")] alias snorm_zero' := eLpNorm_zero' -theorem zero_memℒp : Memℒp (0 : α → E) p μ := - ⟨aestronglyMeasurable_zero, by - rw [eLpNorm_zero] - exact ENNReal.coe_lt_top⟩ +@[simp] lemma Memℒp.zero : Memℒp (0 : α → E) p μ := + ⟨aestronglyMeasurable_zero, by rw [eLpNorm_zero]; exact ENNReal.coe_lt_top⟩ -theorem zero_mem_ℒp' : Memℒp (fun _ : α => (0 : E)) p μ := zero_memℒp (E := E) +@[simp] lemma Memℒp.zero' : Memℒp (fun _ : α => (0 : E)) p μ := Memℒp.zero + +@[deprecated (since := "2025-01-21")] alias zero_memℒp := Memℒp.zero +@[deprecated (since := "2025-01-21")] alias zero_mem_ℒp := Memℒp.zero' variable [MeasurableSpace α] @@ -886,7 +887,7 @@ lemma memℒp_indicator_const (p : ℝ≥0∞) (hs : MeasurableSet s) (c : E) (h Memℒp (s.indicator fun _ => c) p μ := by rw [memℒp_indicator_iff_restrict hs] obtain rfl | hμ := hμsc - · exact zero_memℒp + · exact Memℒp.zero · have := Fact.mk hμ.lt_top apply memℒp_const diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean index a77dc026f492f..bde7165f033fb 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean @@ -191,7 +191,7 @@ theorem memℒp_finset_sum {ι} (s : Finset ι) {f : ι → α → E} (hf : ∀ haveI : DecidableEq ι := Classical.decEq _ revert hf refine Finset.induction_on s ?_ ?_ - · simp only [zero_mem_ℒp', Finset.sum_empty, imp_true_iff] + · simp only [Memℒp.zero', Finset.sum_empty, imp_true_iff] · intro i s his ih hf simp only [his, Finset.sum_insert, not_false_iff] exact (hf i (s.mem_insert_self i)).add (ih fun j hj => hf j (Finset.mem_insert_of_mem hj)) diff --git a/Mathlib/MeasureTheory/Function/LpSpace.lean b/Mathlib/MeasureTheory/Function/LpSpace.lean index ea88132fbc69c..7ff9c55c9cd7d 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace.lean @@ -289,7 +289,7 @@ theorem edist_toLp_toLp (f g : α → E) (hf : Memℒp f p μ) (hg : Memℒp g p @[simp] theorem edist_toLp_zero (f : α → E) (hf : Memℒp f p μ) : edist (hf.toLp f) 0 = eLpNorm f p μ := by - convert edist_toLp_toLp f 0 hf zero_memℒp + convert edist_toLp_toLp f 0 hf Memℒp.zero simp @[simp] @@ -322,7 +322,7 @@ theorem norm_eq_zero_iff {f : Lp E p μ} (hp : 0 < p) : ‖f‖ = 0 ↔ f = 0 := NNReal.coe_eq_zero.trans (nnnorm_eq_zero_iff hp) theorem eq_zero_iff_ae_eq_zero {f : Lp E p μ} : f = 0 ↔ f =ᵐ[μ] 0 := by - rw [← (Lp.memℒp f).toLp_eq_toLp_iff zero_memℒp, Memℒp.toLp_zero, toLp_coeFn] + rw [← (Lp.memℒp f).toLp_eq_toLp_iff Memℒp.zero, Memℒp.toLp_zero, toLp_coeFn] @[simp] theorem nnnorm_neg (f : Lp E p μ) : ‖-f‖₊ = ‖f‖₊ := by diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index d64f4c733873a..1f5fc22267058 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -175,7 +175,7 @@ alias tendsto_approxOn_range_Lp_snorm := tendsto_approxOn_range_Lp_eLpNorm theorem memℒp_approxOn_range [BorelSpace E] {f : β → E} {μ : Measure β} (fmeas : Measurable f) [SeparableSpace (range f ∪ {0} : Set E)] (hf : Memℒp f p μ) (n : ℕ) : Memℒp (approxOn f fmeas (range f ∪ {0}) 0 (by simp) n) p μ := - memℒp_approxOn fmeas hf (y₀ := 0) (by simp) zero_memℒp n + memℒp_approxOn fmeas hf (y₀ := 0) (by simp) Memℒp.zero n theorem tendsto_approxOn_range_Lp [BorelSpace E] {f : β → E} [hp : Fact (1 ≤ p)] (hp_ne_top : p ≠ ∞) {μ : Measure β} (fmeas : Measurable f) [SeparableSpace (range f ∪ {0} : Set E)] @@ -496,7 +496,7 @@ theorem toLp_eq_mk (f : α →ₛ E) (hf : Memℒp f p μ) : (toLp f hf : α →ₘ[μ] E) = AEEqFun.mk f f.aestronglyMeasurable := rfl -theorem toLp_zero : toLp (0 : α →ₛ E) zero_memℒp = (0 : Lp.simpleFunc E p μ) := +theorem toLp_zero : toLp (0 : α →ₛ E) Memℒp.zero = (0 : Lp.simpleFunc E p μ) := rfl theorem toLp_add (f g : α →ₛ E) (hf : Memℒp f p μ) (hg : Memℒp g p μ) : diff --git a/Mathlib/Probability/Process/Filtration.lean b/Mathlib/Probability/Process/Filtration.lean index 89f83a4bcd145..3396fa6e9ab32 100644 --- a/Mathlib/Probability/Process/Filtration.lean +++ b/Mathlib/Probability/Process/Filtration.lean @@ -322,7 +322,7 @@ theorem memℒp_limitProcess_of_eLpNorm_bdd {R : ℝ≥0} {p : ℝ≥0∞} {F : (lt_of_le_of_lt ?_ (ENNReal.coe_lt_top : ↑R < ∞))⟩ simp_rw [liminf_eq, eventually_atTop] exact sSup_le fun b ⟨a, ha⟩ => (ha a le_rfl).trans (hbdd _) - · exact zero_memℒp + · exact Memℒp.zero @[deprecated (since := "2024-07-27")] alias memℒp_limitProcess_of_snorm_bdd := memℒp_limitProcess_of_eLpNorm_bdd diff --git a/scripts/nolints_prime_decls.txt b/scripts/nolints_prime_decls.txt index 6fdfdc2ba7ecd..450e3291e8c35 100644 --- a/scripts/nolints_prime_decls.txt +++ b/scripts/nolints_prime_decls.txt @@ -2993,7 +2993,7 @@ MeasureTheory.withDensityᵥ_neg' MeasureTheory.withDensityᵥ_smul' MeasureTheory.withDensityᵥ_smul_eq_withDensityᵥ_withDensity' MeasureTheory.withDensityᵥ_sub' -MeasureTheory.zero_mem_ℒp' +MeasureTheory.Memℒp.zero' mem_ball_iff_norm'' mem_ball_iff_norm''' mem_closedBall_iff_norm'' From c55e50017ba7cb74890c9b4d7672752cfd9577a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 21 Jan 2025 14:21:12 +0000 Subject: [PATCH 378/681] feat: notation for variance according to a measure (#20901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The convention of using `X ; μ` to denote that `X` is sampled with measure `μ` comes from PFR. [Zulip](https://leanprover.zulipchat.com/#narrow/channel/116395-maths/topic/.60MeasureSpace.60.20vs.20.60Measure.60.20in.20.60ProbabilityTheory.2F.60/near/476702131) From my PhD (LeanCamCombi) --- Mathlib/Probability/Variance.lean | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/Mathlib/Probability/Variance.lean b/Mathlib/Probability/Variance.lean index b5cc11cbd0014..849d2cb3bd317 100644 --- a/Mathlib/Probability/Variance.lean +++ b/Mathlib/Probability/Variance.lean @@ -56,6 +56,27 @@ to `evariance`. -/ def variance {Ω : Type*} {_ : MeasurableSpace Ω} (X : Ω → ℝ) (μ : Measure Ω) : ℝ := (evariance X μ).toReal +/-- The `ℝ≥0∞`-valued variance of the real-valued random variable `X` according to the measure `μ`. + +This is defined as the Lebesgue integral of `(X - 𝔼[X])^2`. -/ +scoped notation "eVar[" X " ; " μ "]" => ProbabilityTheory.evariance X μ + +/-- The `ℝ≥0∞`-valued variance of the real-valued random variable `X` according to the volume +measure. + +This is defined as the Lebesgue integral of `(X - 𝔼[X])^2`. -/ +scoped notation "eVar[" X "]" => eVar[X ; MeasureTheory.MeasureSpace.volume] + +/-- The `ℝ`-valued variance of the real-valued random variable `X` according to the measure `μ`. + +It is set to `0` if `X` has infinite variance. -/ +scoped notation "Var[" X " ; " μ "]" => ProbabilityTheory.variance X μ + +/-- The `ℝ`-valued variance of the real-valued random variable `X` according to the volume measure. + +It is set to `0` if `X` has infinite variance. -/ +scoped notation "Var[" X "]" => Var[X ; MeasureTheory.MeasureSpace.volume] + variable {Ω : Type*} {m : MeasurableSpace Ω} {X : Ω → ℝ} {μ : Measure Ω} theorem _root_.MeasureTheory.Memℒp.evariance_lt_top [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : @@ -151,8 +172,6 @@ theorem evariance_mul (c : ℝ) (X : Ω → ℝ) (μ : Measure Ω) : rw [mul_comm] simp_rw [← smul_eq_mul, ← integral_smul_const, smul_eq_mul, mul_comm] -scoped notation "eVar[" X "]" => ProbabilityTheory.evariance X MeasureTheory.MeasureSpace.volume - @[simp] theorem variance_zero (μ : Measure Ω) : variance 0 μ = 0 := by simp only [variance, evariance_zero, ENNReal.zero_toReal] @@ -175,8 +194,6 @@ theorem variance_smul' {A : Type*} [CommSemiring A] [Algebra A ℝ] (c : A) (X : · congr; simp only [algebraMap_smul] · simp only [Algebra.smul_def, map_pow] -scoped notation "Var[" X "]" => ProbabilityTheory.variance X MeasureTheory.MeasureSpace.volume - theorem variance_def' [IsProbabilityMeasure μ] {X : Ω → ℝ} (hX : Memℒp X 2 μ) : variance X μ = μ[X ^ 2] - μ[X] ^ 2 := by rw [hX.variance_eq, sub_sq', integral_sub', integral_add']; rotate_left From 5ffb97f4ca3c05bf9a117e9e543a358ba38cc7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Tue, 21 Jan 2025 14:47:25 +0000 Subject: [PATCH 379/681] feat: add (AE)Measurable.complex_ofReal and fun_prop attributes (#20842) --- .../Function/SpecialFunctions/Basic.lean | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean b/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean index 5cc12c4593425..ebd7459e13141 100644 --- a/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean +++ b/Mathlib/MeasureTheory/Function/SpecialFunctions/Basic.lean @@ -139,27 +139,27 @@ open Real variable {α : Type*} {m : MeasurableSpace α} {f : α → ℝ} (hf : Measurable f) include hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.exp : Measurable fun x => Real.exp (f x) := Real.measurable_exp.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.log : Measurable fun x => log (f x) := measurable_log.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.cos : Measurable fun x ↦ cos (f x) := measurable_cos.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.sin : Measurable fun x ↦ sin (f x) := measurable_sin.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.cosh : Measurable fun x ↦ cosh (f x) := measurable_cosh.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.sinh : Measurable fun x ↦ sinh (f x) := measurable_sinh.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.sqrt : Measurable fun x => √(f x) := continuous_sqrt.measurable.comp hf end RealComposition @@ -208,31 +208,31 @@ open Complex variable {α : Type*} {m : MeasurableSpace α} {f : α → ℂ} (hf : Measurable f) include hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.cexp : Measurable fun x => Complex.exp (f x) := Complex.measurable_exp.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.ccos : Measurable fun x => Complex.cos (f x) := Complex.measurable_cos.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.csin : Measurable fun x => Complex.sin (f x) := Complex.measurable_sin.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.ccosh : Measurable fun x => Complex.cosh (f x) := Complex.measurable_cosh.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.csinh : Measurable fun x => Complex.sinh (f x) := Complex.measurable_sinh.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.carg : Measurable fun x => arg (f x) := measurable_arg.comp hf -@[measurability] +@[measurability, fun_prop] protected theorem Measurable.clog : Measurable fun x => Complex.log (f x) := measurable_log.comp hf @@ -275,6 +275,18 @@ protected lemma AEMeasurable.clog : AEMeasurable (fun x ↦ log (f x)) μ := end ComplexComposition +@[measurability, fun_prop] +protected theorem Measurable.complex_ofReal {α : Type*} {m : MeasurableSpace α} {f : α → ℝ} + (hf : Measurable f) : + Measurable fun x ↦ (f x : ℂ) := + Complex.measurable_ofReal.comp hf + +@[measurability, fun_prop] +protected theorem AEMeasurable.complex_ofReal {α : Type*} {m : MeasurableSpace α} {μ : Measure α} + {f : α → ℝ} (hf : AEMeasurable f μ) : + AEMeasurable (fun x ↦ (f x : ℂ)) μ := + Complex.measurable_ofReal.comp_aemeasurable hf + section PowInstances instance Complex.hasMeasurablePow : MeasurablePow ℂ ℂ := From be0cb5462d0a41d900a692b554359fb0f19e91b6 Mon Sep 17 00:00:00 2001 From: Jon Eugster Date: Tue, 21 Jan 2025 15:01:42 +0000 Subject: [PATCH 380/681] chore(CategoryTheory/Enriched/Ordinary): create folder to allow API development (#20903) Moving `CategoryTheory/Enriched/Ordinary.lean` to `CategoryTheory/Enriched/Ordinary/Basic.lean` to allow addition of `CategoryTheory/Enriched/Ordinary/Limits.lean` in a follow-up PR. File content has not been touched. --- Mathlib.lean | 2 +- Mathlib/AlgebraicTopology/SimplicialCategory/Basic.lean | 2 +- Mathlib/CategoryTheory/Enriched/FunctorCategory.lean | 2 +- Mathlib/CategoryTheory/Enriched/HomCongr.lean | 2 +- Mathlib/CategoryTheory/Enriched/Opposite.lean | 2 +- .../Enriched/{Ordinary.lean => Ordinary/Basic.lean} | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename Mathlib/CategoryTheory/Enriched/{Ordinary.lean => Ordinary/Basic.lean} (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 3066f2e7f50b8..6c699d638a8e0 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1774,7 +1774,7 @@ import Mathlib.CategoryTheory.Enriched.Basic import Mathlib.CategoryTheory.Enriched.FunctorCategory import Mathlib.CategoryTheory.Enriched.HomCongr import Mathlib.CategoryTheory.Enriched.Opposite -import Mathlib.CategoryTheory.Enriched.Ordinary +import Mathlib.CategoryTheory.Enriched.Ordinary.Basic import Mathlib.CategoryTheory.EpiMono import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Equivalence diff --git a/Mathlib/AlgebraicTopology/SimplicialCategory/Basic.lean b/Mathlib/AlgebraicTopology/SimplicialCategory/Basic.lean index 88f5cb27d8813..3858e6c423419 100644 --- a/Mathlib/AlgebraicTopology/SimplicialCategory/Basic.lean +++ b/Mathlib/AlgebraicTopology/SimplicialCategory/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.AlgebraicTopology.SimplicialSet.Monoidal -import Mathlib.CategoryTheory.Enriched.Ordinary +import Mathlib.CategoryTheory.Enriched.Ordinary.Basic /-! # Simplicial categories diff --git a/Mathlib/CategoryTheory/Enriched/FunctorCategory.lean b/Mathlib/CategoryTheory/Enriched/FunctorCategory.lean index b798428bc9175..4636b05731fa4 100644 --- a/Mathlib/CategoryTheory/Enriched/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Enriched/FunctorCategory.lean @@ -3,7 +3,7 @@ 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.CategoryTheory.Enriched.Ordinary +import Mathlib.CategoryTheory.Enriched.Ordinary.Basic import Mathlib.CategoryTheory.Functor.Category import Mathlib.CategoryTheory.Limits.Shapes.End diff --git a/Mathlib/CategoryTheory/Enriched/HomCongr.lean b/Mathlib/CategoryTheory/Enriched/HomCongr.lean index 1d4ab2b6588ea..9536a0d158544 100644 --- a/Mathlib/CategoryTheory/Enriched/HomCongr.lean +++ b/Mathlib/CategoryTheory/Enriched/HomCongr.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Nick Ward. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Nick Ward -/ -import Mathlib.CategoryTheory.Enriched.Ordinary +import Mathlib.CategoryTheory.Enriched.Ordinary.Basic /-! # Congruence of enriched homs diff --git a/Mathlib/CategoryTheory/Enriched/Opposite.lean b/Mathlib/CategoryTheory/Enriched/Opposite.lean index d25af18fc5ba9..abb743c68e6b0 100644 --- a/Mathlib/CategoryTheory/Enriched/Opposite.lean +++ b/Mathlib/CategoryTheory/Enriched/Opposite.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Daniel Carranza. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Daniel Carranza -/ -import Mathlib.CategoryTheory.Enriched.Ordinary +import Mathlib.CategoryTheory.Enriched.Ordinary.Basic import Mathlib.CategoryTheory.Monoidal.Braided.Basic /-! diff --git a/Mathlib/CategoryTheory/Enriched/Ordinary.lean b/Mathlib/CategoryTheory/Enriched/Ordinary/Basic.lean similarity index 100% rename from Mathlib/CategoryTheory/Enriched/Ordinary.lean rename to Mathlib/CategoryTheory/Enriched/Ordinary/Basic.lean From ee78f4e232bcaca73d4b10671e595ee8111fdfc9 Mon Sep 17 00:00:00 2001 From: Jireh Loreaux Date: Tue, 21 Jan 2025 15:18:19 +0000 Subject: [PATCH 381/681] feat: an isometric continuous functional calculus gives rise to a non-unital one (#20917) --- .../Isometric.lean | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean index 4b2e6c01ec177..c32eadf334515 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Isometric.lean @@ -591,3 +591,39 @@ lemma MonotoneOn.nnnorm_cfcₙ (f : ℝ≥0 → ℝ≥0) (a : A) end NonUnital end NNReal + +/-! ### Non-unital instance for unital algebras -/ + +namespace IsometricContinuousFunctionalCalculus + +variable {𝕜 A : Type*} {p : outParam (A → Prop)} +variable [RCLike 𝕜] [NormedRing A] [StarRing A] [NormedAlgebra 𝕜 A] +variable [IsometricContinuousFunctionalCalculus 𝕜 A p] + +open scoped ContinuousFunctionalCalculus in +/-- An isometric continuous functional calculus on a unital algebra yields to a non-unital one. -/ +instance toNonUnital : NonUnitalIsometricContinuousFunctionalCalculus 𝕜 A p where + isometric a ha := by + have : CompactSpace (σₙ 𝕜 a) := by + have h_cpct : CompactSpace (spectrum 𝕜 a) := inferInstance + simp only [← isCompact_iff_compactSpace, quasispectrum_eq_spectrum_union_zero] at h_cpct ⊢ + exact h_cpct |>.union isCompact_singleton + rw [cfcₙHom_eq_cfcₙHom_of_cfcHom, cfcₙHom_of_cfcHom] + refine isometry_cfcHom a |>.comp ?_ + simp only [MulHom.coe_coe, NonUnitalStarAlgHom.coe_toNonUnitalAlgHom, + NonUnitalStarAlgHom.coe_coe] + refine AddMonoidHomClass.isometry_of_norm _ fun f ↦ ?_ + let ι : C(σ 𝕜 a, σₙ 𝕜 a) := ⟨_, continuous_inclusion <| spectrum_subset_quasispectrum 𝕜 a⟩ + show ‖(f : C(σₙ 𝕜 a, 𝕜)).comp ι‖ = ‖(f : C(σₙ 𝕜 a, 𝕜))‖ + apply le_antisymm (ContinuousMap.norm_le _ (by positivity) |>.mpr ?_) + (ContinuousMap.norm_le _ (by positivity) |>.mpr ?_) + · rintro ⟨x, hx⟩ + exact (f : C(σₙ 𝕜 a, 𝕜)).norm_coe_le_norm ⟨x, spectrum_subset_quasispectrum 𝕜 a hx⟩ + · rintro ⟨x, hx⟩ + obtain (rfl | hx') : x = 0 ∨ x ∈ σ 𝕜 a := by + simpa [quasispectrum_eq_spectrum_union_zero] using hx + · show ‖f 0‖ ≤ _ + simp + · exact (f : C(σₙ 𝕜 a, 𝕜)).comp ι |>.norm_coe_le_norm ⟨x, hx'⟩ + +end IsometricContinuousFunctionalCalculus From ed194772b55af2a1165382d325dd319ca043c7b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 21 Jan 2025 15:48:52 +0000 Subject: [PATCH 382/681] feat(IncidenceAlgebra): Euler characteristic of a partial order (#20299) From LeanCamCombi Co-authored-by: Alex J. Best --- .../Combinatorics/Enumerative/IncidenceAlgebra.lean | 12 ++++++++++++ Mathlib/Order/BoundedOrder/Basic.lean | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean b/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean index 2ba5461d3a0a6..8156e1b2c8422 100644 --- a/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean +++ b/Mathlib/Combinatorics/Enumerative/IncidenceAlgebra.lean @@ -402,6 +402,10 @@ lemma mu_apply (a b : α) : mu 𝕜 a b = if a = b then 1 else -∑ x ∈ Ico a lemma mu_eq_neg_sum_Ico_of_ne (hab : a ≠ b) : mu 𝕜 a b = -∑ x ∈ Ico a b, mu 𝕜 a x := by rw [mu_apply, if_neg hab] +variable (𝕜 α) +/-- The Euler characteristic of a finite bounded order. -/ +def eulerChar [BoundedOrder α] : 𝕜 := mu 𝕜 (⊥ : α) ⊤ + end Mu section MuSpec @@ -537,6 +541,10 @@ lemma mu_toDual (a b : α) : mu 𝕜 (toDual a) (toDual b) = mu 𝕜 b a := by @[simp] lemma mu_ofDual (a b : αᵒᵈ) : mu 𝕜 (ofDual a) (ofDual b) = mu 𝕜 b a := (mu_toDual ..).symm +@[simp] +lemma eulerChar_orderDual [BoundedOrder α] : eulerChar 𝕜 αᵒᵈ = eulerChar 𝕜 α := by + simp [eulerChar, ← mu_toDual 𝕜 (α := α)] + end OrderDual section InversionTop @@ -657,6 +665,10 @@ lemma mu_prod_mu : (mu 𝕜).prod (mu 𝕜) = (mu 𝕜 : IncidenceAlgebra 𝕜 ( rw [← zeta_prod_zeta, prod_mul_prod', mu_mul_zeta, mu_mul_zeta, one_prod_one] exact fun _ _ _ _ _ _ ↦ Commute.mul_mul_mul_comm (by simp : _ = _) _ _ +@[simp] +lemma eulerChar_prod [BoundedOrder α] [BoundedOrder β] : + eulerChar 𝕜 (α × β) = eulerChar 𝕜 α * eulerChar 𝕜 β := by simp [eulerChar, ← mu_prod_mu] + end PartialOrder end Prod end IncidenceAlgebra diff --git a/Mathlib/Order/BoundedOrder/Basic.lean b/Mathlib/Order/BoundedOrder/Basic.lean index e767d449e62e6..2ad6d7f4daaf3 100644 --- a/Mathlib/Order/BoundedOrder/Basic.lean +++ b/Mathlib/Order/BoundedOrder/Basic.lean @@ -517,10 +517,10 @@ instance instTop [Top α] [Top β] : Top (α × β) := instance instBot [Bot α] [Bot β] : Bot (α × β) := ⟨⟨⊥, ⊥⟩⟩ -theorem fst_top [Top α] [Top β] : (⊤ : α × β).fst = ⊤ := rfl -theorem snd_top [Top α] [Top β] : (⊤ : α × β).snd = ⊤ := rfl -theorem fst_bot [Bot α] [Bot β] : (⊥ : α × β).fst = ⊥ := rfl -theorem snd_bot [Bot α] [Bot β] : (⊥ : α × β).snd = ⊥ := rfl +@[simp] lemma fst_top [Top α] [Top β] : (⊤ : α × β).fst = ⊤ := rfl +@[simp] lemma snd_top [Top α] [Top β] : (⊤ : α × β).snd = ⊤ := rfl +@[simp] lemma fst_bot [Bot α] [Bot β] : (⊥ : α × β).fst = ⊥ := rfl +@[simp] lemma snd_bot [Bot α] [Bot β] : (⊥ : α × β).snd = ⊥ := rfl instance instOrderTop [LE α] [LE β] [OrderTop α] [OrderTop β] : OrderTop (α × β) where __ := inferInstanceAs (Top (α × β)) From 69e7baf10bd0d780e2abb3e596e78935bf9d78e7 Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Tue, 21 Jan 2025 17:14:37 +0000 Subject: [PATCH 383/681] feat(Integral/Pi): a version of `polarCoord` for `pi` integrals (#18400) This PR is part of the proof of the Analytic Class Number Formula. Co-authored-by: Xavier Roblot <46200072+xroblot@users.noreply.github.com> --- .../Analysis/SpecialFunctions/PolarCoord.lean | 104 ++++++++++++++++-- Mathlib/LinearAlgebra/Determinant.lean | 22 ++++ .../Topology/Algebra/Module/Determinant.lean | 6 + 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean b/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean index 016678accf824..86233fe6cde8c 100644 --- a/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean +++ b/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean @@ -89,20 +89,24 @@ def polarCoord : PartialHomeomorph (ℝ × ℝ) (ℝ × ℝ) where · exact (Complex.continuousAt_arg hz).continuousWithinAt · exact Complex.equivRealProdCLM.symm.continuous.continuousOn +/-- The derivative of `polarCoord.symm`, see `hasFDerivAt_polarCoord_symm`. -/ +def fderivPolarCoordSymm (p : ℝ × ℝ) : ℝ × ℝ →L[ℝ] ℝ × ℝ := + LinearMap.toContinuousLinearMap (Matrix.toLin (Basis.finTwoProd ℝ) + (Basis.finTwoProd ℝ) !![cos p.2, -p.1 * sin p.2; sin p.2, p.1 * cos p.2]) + theorem hasFDerivAt_polarCoord_symm (p : ℝ × ℝ) : - HasFDerivAt polarCoord.symm - (LinearMap.toContinuousLinearMap (Matrix.toLin (Basis.finTwoProd ℝ) (Basis.finTwoProd ℝ) - !![cos p.2, -p.1 * sin p.2; sin p.2, p.1 * cos p.2])) p := by + HasFDerivAt polarCoord.symm (fderivPolarCoordSymm p) p := by + unfold fderivPolarCoordSymm rw [Matrix.toLin_finTwoProd_toContinuousLinearMap] convert HasFDerivAt.prod (𝕜 := ℝ) (hasFDerivAt_fst.mul ((hasDerivAt_cos p.2).comp_hasFDerivAt p hasFDerivAt_snd)) (hasFDerivAt_fst.mul ((hasDerivAt_sin p.2).comp_hasFDerivAt p hasFDerivAt_snd)) using 2 <;> simp [smul_smul, add_comm, neg_mul, smul_neg, neg_smul _ (ContinuousLinearMap.snd ℝ ℝ ℝ)] -theorem det_fderiv_polarCoord_symm (p : ℝ × ℝ) : - (LinearMap.toContinuousLinearMap (Matrix.toLin (Basis.finTwoProd ℝ) (Basis.finTwoProd ℝ) - !![cos p.2, -p.1 * sin p.2; sin p.2, p.1 * cos p.2])).det = p.1 := by +theorem det_fderivPolarCoordSymm (p : ℝ × ℝ) : + (fderivPolarCoordSymm p).det = p.1 := by conv_rhs => rw [← one_mul p.1, ← cos_sq_add_sin_sq p.2] + unfold fderivPolarCoordSymm simp only [neg_mul, LinearMap.det_toContinuousLinearMap, LinearMap.det_toLin, Matrix.det_fin_two_of, sub_neg_eq_add] ring @@ -138,7 +142,7 @@ theorem integral_comp_polarCoord_symm {E : Type*} [NormedAddCommGroup E] [Normed _ = ∫ p in polarCoord.target, |p.1| • f (polarCoord.symm p) := by rw [← PartialHomeomorph.symm_target, integral_target_eq_integral_abs_det_fderiv_smul volume (fun p _ ↦ hasFDerivAt_polarCoord_symm p), PartialHomeomorph.symm_source] - simp_rw [det_fderiv_polarCoord_symm] + simp_rw [det_fderivPolarCoordSymm] _ = ∫ p in polarCoord.target, p.1 • f (polarCoord.symm p) := by apply setIntegral_congr_fun polarCoord.open_target.measurableSet fun x hx => ?_ rw [abs_of_pos hx.1] @@ -154,7 +158,7 @@ theorem lintegral_comp_polarCoord_symm (f : ℝ × ℝ → ℝ≥0∞) : _ = ∫⁻ (p : ℝ × ℝ) in polarCoord.target, ENNReal.ofReal |p.1| • f (polarCoord.symm p) := by rw [lintegral_image_eq_lintegral_abs_det_fderiv_mul volume _ (fun p _ ↦ (hasFDerivAt_polarCoord_symm p).hasFDerivWithinAt)] - · simp_rw [det_fderiv_polarCoord_symm]; rfl + · simp_rw [det_fderivPolarCoordSymm]; rfl exacts [polarCoord.symm.injOn, measurableSet_Ioi.prod measurableSet_Ioo] _ = ∫⁻ (p : ℝ × ℝ) in polarCoord.target, ENNReal.ofReal p.1 • f (polarCoord.symm p) := by refine setLIntegral_congr_fun polarCoord.open_target.measurableSet ?_ @@ -211,3 +215,87 @@ protected theorem lintegral_comp_polarCoord_symm (f : ℂ → ℝ≥0∞) : simp_rw [measurableEquivRealProd_symm_polarCoord_symm_apply] end Complex + +section Pi + +open ENNReal MeasureTheory MeasureTheory.Measure + +variable {ι : Type*} + +open ContinuousLinearMap in +/-- The derivative of `polarCoord.symm` on `ι → ℝ × ℝ`, see `hasFDerivAt_pi_polarCoord_symm`. -/ +noncomputable def fderivPiPolarCoordSymm (p : ι → ℝ × ℝ) : (ι → ℝ × ℝ) →L[ℝ] ι → ℝ × ℝ := + pi fun i ↦ (fderivPolarCoordSymm (p i)).comp (proj i) + +theorem injOn_pi_polarCoord_symm : + Set.InjOn (fun p (i : ι) ↦ polarCoord.symm (p i)) (Set.univ.pi fun _ ↦ polarCoord.target) := + fun _ hx _ hy h ↦ funext fun i ↦ polarCoord.symm.injOn (hx i trivial) (hy i trivial) + ((funext_iff.mp h) i) + +theorem abs_fst_of_mem_pi_polarCoord_target {p : ι → ℝ × ℝ} + (hp : p ∈ (Set.univ.pi fun _ : ι ↦ polarCoord.target)) (i : ι) : + |(p i).1| = (p i).1 := + abs_of_pos ((Set.mem_univ_pi.mp hp) i).1 + +variable [Fintype ι] + +theorem hasFDerivAt_pi_polarCoord_symm (p : ι → ℝ × ℝ) : + HasFDerivAt (fun x i ↦ polarCoord.symm (x i)) (fderivPiPolarCoordSymm p) p := by + rw [fderivPiPolarCoordSymm, hasFDerivAt_pi] + exact fun i ↦ HasFDerivAt.comp _ (hasFDerivAt_polarCoord_symm _) (hasFDerivAt_apply i _) + +theorem det_fderivPiPolarCoordSymm (p : ι → ℝ × ℝ) : + (fderivPiPolarCoordSymm p).det = ∏ i, (p i).1 := by + simp_rw [fderivPiPolarCoordSymm, ContinuousLinearMap.det_pi, det_fderivPolarCoordSymm] + +theorem pi_polarCoord_symm_target_ae_eq_univ : + (Pi.map (fun _ : ι ↦ polarCoord.symm) '' Set.univ.pi fun _ ↦ polarCoord.target) + =ᵐ[volume] Set.univ := by + rw [Set.piMap_image_univ_pi, polarCoord.symm_image_target_eq_source, volume_pi, ← Set.pi_univ] + exact ae_eq_set_pi fun _ _ ↦ polarCoord_source_ae_eq_univ + +theorem measurableSet_pi_polarCoord_target : + MeasurableSet (Set.univ.pi fun _ : ι ↦ polarCoord.target) := + MeasurableSet.univ_pi fun _ ↦ polarCoord.open_target.measurableSet + +theorem integral_comp_pi_polarCoord_symm {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + (f : (ι → ℝ × ℝ) → E) : + (∫ p in (Set.univ.pi fun _ : ι ↦ polarCoord.target), + (∏ i, (p i).1) • f (fun i ↦ polarCoord.symm (p i))) = ∫ p, f p := by + rw [← setIntegral_univ (f := f), ← setIntegral_congr_set pi_polarCoord_symm_target_ae_eq_univ] + convert (integral_image_eq_integral_abs_det_fderiv_smul volume measurableSet_pi_polarCoord_target + (fun p _ ↦ (hasFDerivAt_pi_polarCoord_symm p).hasFDerivWithinAt) + injOn_pi_polarCoord_symm f).symm using 1 + refine setIntegral_congr_fun measurableSet_pi_polarCoord_target fun x hx ↦ ?_ + simp_rw [det_fderivPiPolarCoordSymm, Finset.abs_prod, abs_fst_of_mem_pi_polarCoord_target hx] + +protected theorem Complex.integral_comp_pi_polarCoord_symm {E : Type*} [NormedAddCommGroup E] + [NormedSpace ℝ E] (f : (ι → ℂ) → E) : + (∫ p in (Set.univ.pi fun _ : ι ↦ Complex.polarCoord.target), + (∏ i, (p i).1) • f (fun i ↦ Complex.polarCoord.symm (p i))) = ∫ p, f p := by + let e := MeasurableEquiv.piCongrRight (fun _ : ι ↦ measurableEquivRealProd.symm) + have := volume_preserving_pi (fun _ : ι ↦ Complex.volume_preserving_equiv_real_prod.symm) + rw [← MeasurePreserving.integral_comp this e.measurableEmbedding f] + exact integral_comp_pi_polarCoord_symm (f ∘ e) + +theorem lintegral_comp_pi_polarCoord_symm (f : (ι → ℝ × ℝ) → ℝ≥0∞) : + ∫⁻ p in (Set.univ.pi fun _ : ι ↦ polarCoord.target), + (∏ i, .ofReal (p i).1) * f (fun i ↦ polarCoord.symm (p i)) = ∫⁻ p, f p := by + rw [← setLIntegral_univ f, ← setLIntegral_congr pi_polarCoord_symm_target_ae_eq_univ] + convert (lintegral_image_eq_lintegral_abs_det_fderiv_mul volume measurableSet_pi_polarCoord_target + (fun p _ ↦ (hasFDerivAt_pi_polarCoord_symm p).hasFDerivWithinAt) + injOn_pi_polarCoord_symm f).symm using 1 + refine setLIntegral_congr_fun measurableSet_pi_polarCoord_target ?_ + filter_upwards with x hx + simp_rw [det_fderivPiPolarCoordSymm, Finset.abs_prod, ENNReal.ofReal_prod_of_nonneg (fun _ _ ↦ + abs_nonneg _), abs_fst_of_mem_pi_polarCoord_target hx] + +protected theorem Complex.lintegral_comp_pi_polarCoord_symm (f : (ι → ℂ) → ℝ≥0∞) : + ∫⁻ p in (Set.univ.pi fun _ : ι ↦ Complex.polarCoord.target), + (∏ i, .ofReal (p i).1) * f (fun i ↦ Complex.polarCoord.symm (p i)) = ∫⁻ p, f p := by + let e := MeasurableEquiv.piCongrRight (fun _ : ι ↦ measurableEquivRealProd.symm) + have := volume_preserving_pi (fun _ : ι ↦ Complex.volume_preserving_equiv_real_prod.symm) + rw [← MeasurePreserving.lintegral_comp_emb this e.measurableEmbedding] + exact lintegral_comp_pi_polarCoord_symm (f ∘ e) + +end Pi diff --git a/Mathlib/LinearAlgebra/Determinant.lean b/Mathlib/LinearAlgebra/Determinant.lean index 6ab5b47a0e4ee..7851cb879dbf9 100644 --- a/Mathlib/LinearAlgebra/Determinant.lean +++ b/Mathlib/LinearAlgebra/Determinant.lean @@ -336,6 +336,28 @@ theorem bot_lt_ker_of_det_eq_zero {𝕜 : Type*} [Field 𝕜] [Module 𝕜 M] {f lemma det_mulLeft (a : R) : (mulLeft R a).det = a := by simp lemma det_mulRight (a : R) : (mulRight R a).det = a := by simp +omit [DecidableEq ι] in +theorem det_pi [Module.Free R M] [Module.Finite R M] (f : ι → M →ₗ[R] M) : + (LinearMap.pi (fun i ↦ (f i).comp (LinearMap.proj i))).det = ∏ i, (f i).det := by + classical + let b := Module.Free.chooseBasis R M + let B := (Pi.basis (fun _ : ι ↦ b)).reindex <| + (Equiv.sigmaEquivProd _ _).trans (Equiv.prodComm _ _) + simp_rw [← LinearMap.det_toMatrix B, ← LinearMap.det_toMatrix b] + have : ((LinearMap.toMatrix B B) (LinearMap.pi fun i ↦ f i ∘ₗ LinearMap.proj i)) = + Matrix.blockDiagonal (fun i ↦ LinearMap.toMatrix b b (f i)) := by + ext ⟨i₁, i₂⟩ ⟨j₁, j₂⟩ + unfold B + simp_rw [LinearMap.toMatrix_apply', Matrix.blockDiagonal_apply, Basis.coe_reindex, + Function.comp_apply, Basis.repr_reindex_apply, Equiv.symm_trans_apply, Equiv.prodComm_symm, + Equiv.prodComm_apply, Equiv.sigmaEquivProd_symm_apply, Prod.swap_prod_mk, Pi.basis_apply, + Pi.basis_repr, LinearMap.pi_apply, LinearMap.coe_comp, Function.comp_apply, + LinearMap.toMatrix_apply', LinearMap.coe_proj, Function.eval, Pi.single_apply] + split_ifs with h + · rw [h] + · simp only [map_zero, Finsupp.coe_zero, Pi.zero_apply] + rw [this, Matrix.det_blockDiagonal] + end LinearMap diff --git a/Mathlib/Topology/Algebra/Module/Determinant.lean b/Mathlib/Topology/Algebra/Module/Determinant.lean index cf06e39304938..7ebf8ee44e47a 100644 --- a/Mathlib/Topology/Algebra/Module/Determinant.lean +++ b/Mathlib/Topology/Algebra/Module/Determinant.lean @@ -20,6 +20,12 @@ noncomputable abbrev det {R : Type*} [CommRing R] {M : Type*} [TopologicalSpace [Module R M] (A : M →L[R] M) : R := LinearMap.det (A : M →ₗ[R] M) +theorem det_pi {ι R M : Type*} [Fintype ι] [CommRing R] [AddCommGroup M] + [TopologicalSpace M] [Module R M] [Module.Free R M] [Module.Finite R M] + (f : ι → M →L[R] M) : + (pi (fun i ↦ (f i).comp (proj i))).det = ∏ i, (f i).det := + LinearMap.det_pi _ + end ContinuousLinearMap namespace ContinuousLinearEquiv From 3a0c1d4ca1706c61158e0624497c6287d73a0a01 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Tue, 21 Jan 2025 17:30:58 +0000 Subject: [PATCH 384/681] feat(RingTheory/TensorProduct): tensor product commutes with quotients by ideals (#20715) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If `B` is an `A`-algebra and `I` an ideal of `A`, then `B ⊗[A] (A ⧸ I)` is isomorphic to `B ⧸ (I.map <| algebraMap A B)`. Co-authored by: Sihan Su Co-authored by: Yi Song --- Mathlib.lean | 1 + .../RingTheory/TensorProduct/Quotient.lean | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 Mathlib/RingTheory/TensorProduct/Quotient.lean diff --git a/Mathlib.lean b/Mathlib.lean index 6c699d638a8e0..a0f320e932cbc 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4750,6 +4750,7 @@ import Mathlib.RingTheory.TensorProduct.Free import Mathlib.RingTheory.TensorProduct.MvPolynomial import Mathlib.RingTheory.TensorProduct.Nontrivial import Mathlib.RingTheory.TensorProduct.Pi +import Mathlib.RingTheory.TensorProduct.Quotient import Mathlib.RingTheory.Trace.Basic import Mathlib.RingTheory.Trace.Defs import Mathlib.RingTheory.Trace.Quotient diff --git a/Mathlib/RingTheory/TensorProduct/Quotient.lean b/Mathlib/RingTheory/TensorProduct/Quotient.lean new file mode 100644 index 0000000000000..1995ac993264e --- /dev/null +++ b/Mathlib/RingTheory/TensorProduct/Quotient.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2025 Christian Merten, Yi Song, Sihan Su. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christian Merten, Yi Song, Sihan Su +-/ +import Mathlib.LinearAlgebra.TensorProduct.Quotient +import Mathlib.RingTheory.Ideal.Quotient.Operations +import Mathlib.RingTheory.TensorProduct.Basic + +/-! +# Interaction between quotients and tensor products for algebras + +This files proves algebra analogs of the isomorphisms in +`Mathlib.LinearAlgebra.TensorProduct.Quotient`. + +## Main results + +- `Algebra.TensorProduct.quotIdealMapEquivTensorQuot`: + `B ⧸ (I.map <| algebraMap A B) ≃ₐ[B] B ⊗[A] (A ⧸ I)` +-/ + +open TensorProduct + +namespace Algebra.TensorProduct + +variable {A : Type*} (B : Type*) [CommRing A] [CommRing B] [Algebra A B] (I : Ideal A) + +private noncomputable def quotIdealMapEquivTensorQuotAux : + (B ⧸ (I.map <| algebraMap A B)) ≃ₗ[B] B ⊗[A] (A ⧸ I) := + AddEquiv.toLinearEquiv (TensorProduct.tensorQuotEquivQuotSMul B I ≪≫ₗ + Submodule.quotEquivOfEq _ _ (Ideal.smul_top_eq_map I) ≪≫ₗ + Submodule.Quotient.restrictScalarsEquiv A (I.map <| algebraMap A B)).symm <| by + intro c x + obtain ⟨u, rfl⟩ := Ideal.Quotient.mk_surjective x + rfl + +private lemma quotIdealMapEquivTensorQuotAux_mk (b : B) : + (quotIdealMapEquivTensorQuotAux B I) b = b ⊗ₜ[A] 1 := + rfl + +/-- `B ⊗[A] (A ⧸ I)` is isomorphic as an `A`-algebra to `B ⧸ I B`. -/ +noncomputable def quotIdealMapEquivTensorQuot : + (B ⧸ (I.map <| algebraMap A B)) ≃ₐ[B] B ⊗[A] (A ⧸ I) := + AlgEquiv.ofLinearEquiv (quotIdealMapEquivTensorQuotAux B I) rfl + (fun x y ↦ by + obtain ⟨u, rfl⟩ := Ideal.Quotient.mk_surjective x + obtain ⟨v, rfl⟩ := Ideal.Quotient.mk_surjective y + simp_rw [← map_mul, quotIdealMapEquivTensorQuotAux_mk] + simp) + +@[simp] +lemma quotIdealMapEquivTensorQuot_mk (b : B) : + quotIdealMapEquivTensorQuot B I b = b ⊗ₜ[A] 1 := + rfl + +@[simp] +lemma quotIdealMapEquivTensorQuot_symm_tmul (b : B) (a : A) : + (quotIdealMapEquivTensorQuot B I).symm (b ⊗ₜ[A] a) = Submodule.Quotient.mk (a • b) := + rfl + +end Algebra.TensorProduct From 9db65959a02e233c10e019c523474c1df63f6f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 21 Jan 2025 18:15:12 +0000 Subject: [PATCH 385/681] feat(CategoryTheory): `Arrow A` is finite iff `A` is a finite category (#19945) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We obtain various results about the cardinality of `Arrow`. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/CategoryTheory/Comma/Arrow.lean | 31 +++++ .../CategoryTheory/Comma/CardinalArrow.lean | 111 ++++++++++++++++++ Mathlib/CategoryTheory/EssentiallySmall.lean | 2 +- 4 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 Mathlib/CategoryTheory/Comma/CardinalArrow.lean diff --git a/Mathlib.lean b/Mathlib.lean index a0f320e932cbc..d36d1e8adaf5d 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1733,6 +1733,7 @@ import Mathlib.CategoryTheory.CofilteredSystem import Mathlib.CategoryTheory.CommSq import Mathlib.CategoryTheory.Comma.Arrow import Mathlib.CategoryTheory.Comma.Basic +import Mathlib.CategoryTheory.Comma.CardinalArrow import Mathlib.CategoryTheory.Comma.Final import Mathlib.CategoryTheory.Comma.LocallySmall import Mathlib.CategoryTheory.Comma.Over diff --git a/Mathlib/CategoryTheory/Comma/Arrow.lean b/Mathlib/CategoryTheory/Comma/Arrow.lean index 6a161770de191..ea02bd9201175 100644 --- a/Mathlib/CategoryTheory/Comma/Arrow.lean +++ b/Mathlib/CategoryTheory/Comma/Arrow.lean @@ -277,6 +277,16 @@ def rightFunc : Arrow C ⥤ C := @[simps] def leftToRight : (leftFunc : Arrow C ⥤ C) ⟶ rightFunc where app f := f.hom +lemma ext {f g : Arrow C} + (h₁ : f.left = g.left) (h₂ : f.right = g.right) + (h₃ : f.hom = eqToHom h₁ ≫ g.hom ≫ eqToHom h₂.symm) : f = g := by + obtain ⟨X, Y, f⟩ := f + obtain ⟨X', Y', g⟩ := g + obtain rfl : X = X' := h₁ + obtain rfl : Y = Y' := h₂ + obtain rfl : f = g := by simpa using h₃ + rfl + end Arrow namespace Functor @@ -334,4 +344,25 @@ def Arrow.isoOfNatIso {C D : Type*} [Category C] [Category D] {F G : C ⥤ D} (e (f : Arrow C) : F.mapArrow.obj f ≅ G.mapArrow.obj f := Arrow.isoMk (e.app f.left) (e.app f.right) +variable (T) + +/-- `Arrow T` is equivalent to a sigma type. -/ +@[simps!] +def Arrow.equivSigma : + Arrow T ≃ Σ (X Y : T), X ⟶ Y where + toFun f := ⟨_, _, f.hom⟩ + invFun x := Arrow.mk x.2.2 + left_inv _ := rfl + right_inv _ := rfl + +/-- The equivalence `Arrow (Discrete S) ≃ S`. -/ +def Arrow.discreteEquiv (S : Type u) : Arrow (Discrete S) ≃ S where + toFun f := f.left.as + invFun s := Arrow.mk (𝟙 (Discrete.mk s)) + left_inv := by + rintro ⟨⟨_⟩, ⟨_⟩, f⟩ + obtain rfl := Discrete.eq_of_hom f + rfl + right_inv _ := rfl + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Comma/CardinalArrow.lean b/Mathlib/CategoryTheory/Comma/CardinalArrow.lean new file mode 100644 index 0000000000000..14443de419c69 --- /dev/null +++ b/Mathlib/CategoryTheory/Comma/CardinalArrow.lean @@ -0,0 +1,111 @@ +/- +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.CategoryTheory.Comma.Arrow +import Mathlib.CategoryTheory.FinCategory.Basic +import Mathlib.CategoryTheory.EssentiallySmall +import Mathlib.Data.Set.Finite.Basic +import Mathlib.SetTheory.Cardinal.HasCardinalLT + +/-! +# Cardinal of Arrow + +We obtain various results about the cardinality of `Arrow C`. For example, +If `A` is a (small) category, `Arrow C` is finite iff `FinCategory C` holds. + +-/ + +universe w w' v u + +namespace CategoryTheory + +lemma Arrow.finite_iff (C : Type u) [SmallCategory C] : + Finite (Arrow C) ↔ Nonempty (FinCategory C) := by + constructor + · intro + refine ⟨?_, fun a b ↦ ?_⟩ + · have := Finite.of_injective (fun (a : C) ↦ Arrow.mk (𝟙 a)) + (fun _ _ ↦ congr_arg Comma.left) + apply Fintype.ofFinite + · have := Finite.of_injective (fun (f : a ⟶ b) ↦ Arrow.mk f) + (fun f g h ↦ by + change (Arrow.mk f).hom = (Arrow.mk g).hom + congr) + apply Fintype.ofFinite + · rintro ⟨_⟩ + have := Fintype.ofEquiv _ (Arrow.equivSigma C).symm + infer_instance + +instance Arrow.finite {C : Type u} [SmallCategory C] [FinCategory C] : + Finite (Arrow C) := by + rw [Arrow.finite_iff] + exact ⟨inferInstance⟩ + +/-- The bijection `Arrow Cᵒᵖ ≃ Arrow C`. -/ +def Arrow.opEquiv (C : Type u) [Category.{v} C] : Arrow Cᵒᵖ ≃ Arrow C where + toFun f := Arrow.mk f.hom.unop + invFun g := Arrow.mk g.hom.op + left_inv _ := rfl + right_inv _ := rfl + +@[simp] +lemma hasCardinalLT_arrow_op_iff (C : Type u) [Category.{v} C] (κ : Cardinal.{w}) : + HasCardinalLT (Arrow Cᵒᵖ) κ ↔ HasCardinalLT (Arrow C) κ := + hasCardinalLT_iff_of_equiv (Arrow.opEquiv C) κ + +@[simp] +lemma hasCardinalLT_arrow_discrete_iff {X : Type u} (κ : Cardinal.{w}) : + HasCardinalLT (Arrow (Discrete X)) κ ↔ HasCardinalLT X κ := + hasCardinalLT_iff_of_equiv (Arrow.discreteEquiv X) κ + +lemma small_of_small_arrow (C : Type u) [Category.{v} C] [Small.{w} (Arrow C)] : + Small.{w} C := + small_of_injective (f := fun X ↦ Arrow.mk (𝟙 X)) (fun _ _ h ↦ congr_arg Comma.left h) + +lemma locallySmall_of_small_arrow (C : Type u) [Category.{v} C] [Small.{w} (Arrow C)] : + LocallySmall.{w} C where + hom_small X Y := + small_of_injective (f := fun f ↦ Arrow.mk f) (fun f g h ↦ by + change (Arrow.mk f).hom = (Arrow.mk g).hom + congr) + +/-- The bijection `Arrow.{w} (ShrinkHoms C) ≃ Arrow C`. -/ +noncomputable def Arrow.shrinkHomsEquiv (C : Type u) [Category.{v} C] [LocallySmall.{w} C] : + Arrow.{w} (ShrinkHoms C) ≃ Arrow C where + toFun := (ShrinkHoms.equivalence C).inverse.mapArrow.obj + invFun := (ShrinkHoms.equivalence C).functor.mapArrow.obj + left_inv _ := by simp [Functor.mapArrow]; rfl + right_inv _ := by simp [Functor.mapArrow]; rfl + +/-- The bijection `Arrow (Shrink C) ≃ Arrow C`. -/ +noncomputable def Arrow.shrinkEquiv (C : Type u) [Category.{v} C] [Small.{w} C] : + Arrow (Shrink.{w} C) ≃ Arrow C where + toFun := (Shrink.equivalence C).inverse.mapArrow.obj + invFun := (Shrink.equivalence C).functor.mapArrow.obj + left_inv f := by + refine Arrow.ext (Equiv.apply_symm_apply _ _) + ((Equiv.apply_symm_apply _ _)) (by simp; rfl) + right_inv _ := Arrow.ext (by simp [Shrink.equivalence]) + (by simp [Shrink.equivalence]) (by simp [Shrink.equivalence]) + +@[simp] +lemma hasCardinalLT_arrow_shrinkHoms_iff (C : Type u) [Category.{v} C] [LocallySmall.{w'} C] + (κ : Cardinal.{w}) : + HasCardinalLT (Arrow.{w'} (ShrinkHoms C)) κ ↔ HasCardinalLT (Arrow C) κ := + hasCardinalLT_iff_of_equiv (Arrow.shrinkHomsEquiv C) κ + +@[simp] +lemma hasCardinalLT_arrow_shrink_iff (C : Type u) [Category.{v} C] [Small.{w'} C] + (κ : Cardinal.{w}) : + HasCardinalLT (Arrow (Shrink.{w'} C)) κ ↔ HasCardinalLT (Arrow C) κ := + hasCardinalLT_iff_of_equiv (Arrow.shrinkEquiv C) κ + +lemma hasCardinalLT_of_hasCardinalLT_arrow + {C : Type u} [Category.{v} C] {κ : Cardinal.{w}} (h : HasCardinalLT (Arrow C) κ) : + HasCardinalLT C κ := + h.of_injective (fun X ↦ Arrow.mk (𝟙 X)) (fun _ _ h ↦ congr_arg Comma.left h) + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/EssentiallySmall.lean b/Mathlib/CategoryTheory/EssentiallySmall.lean index f3ff9dccad071..1e97be181bd34 100644 --- a/Mathlib/CategoryTheory/EssentiallySmall.lean +++ b/Mathlib/CategoryTheory/EssentiallySmall.lean @@ -23,7 +23,7 @@ the type `Skeleton C` is `w`-small, and `C` is `w`-locally small. -/ -universe w v v' u u' +universe w w' v v' u u' open CategoryTheory From 8e7550d9faf33ae32afbe86a6d9dadb1c06ad785 Mon Sep 17 00:00:00 2001 From: D-Thomine <100795491+D-Thomine@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:51:05 +0000 Subject: [PATCH 386/681] refactor(Probability.Martingale.BorelCantelli): move and simplify lemmas about indicators (#19039) Two lemmas about indicators ([limsup_eq_tendsto_sum_indicator_nat_atTop](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Topology/Algebra/Order/LiminfLimsup.html#limsup_eq_tendsto_sum_indicator_nat_atTop), [limsup_eq_tendsto_sum_indicator_atTop](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Topology/Algebra/Order/LiminfLimsup.html#limsup_eq_tendsto_sum_indicator_atTop)) are moved from `Mathlib.Topology.Algebra.Order.LiminfLimsup` to a new file `Mathlib.Topology.Algebra.IndicatorCard` . ~~`Mathlib.Probability.Martingale.BorelCantelli`. I'm not completely sure this is the right place for them, but it simplifies significantly the imports and these lemmas weren't used anywhere else, so...~~ Their proofs are also significantly simplified. There are two new lemma `Set.sum_indicator_eventually_eq_card` and `Set.infinite_iff_tendsto_sum_indicator_atTop` which seem more versatile and concentrate most of the difficulty, `limsup_eq_tendsto_sum_indicator_nat_atTop` is removed (it is less general than the last result), and `limsup_eq_tendsto_sum_indicator_atTop` is deduced very quickly from `Set.infinite_iff_tendsto_sum_indicator_atTop`. The statement of `Set.infinite_iff_tendsto_sum_indicator_atTop` is also slightly generalized. --- Mathlib.lean | 1 + .../Order/Archimedean/IndicatorCard.lean | 74 ++++++++++++++++++ .../OuterMeasure/Operations.lean | 1 + Mathlib/NumberTheory/SumPrimeReciprocals.lean | 3 +- .../Probability/Martingale/BorelCantelli.lean | 9 ++- .../Topology/Algebra/Order/LiminfLimsup.lean | 76 ------------------- .../Topology/Instances/ENNReal/Lemmas.lean | 7 +- Mathlib/Topology/UrysohnsLemma.lean | 1 + 8 files changed, 88 insertions(+), 84 deletions(-) create mode 100644 Mathlib/Algebra/Order/Archimedean/IndicatorCard.lean diff --git a/Mathlib.lean b/Mathlib.lean index d36d1e8adaf5d..a7202dbc85237 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -663,6 +663,7 @@ import Mathlib.Algebra.Order.Antidiag.Pi import Mathlib.Algebra.Order.Antidiag.Prod import Mathlib.Algebra.Order.Archimedean.Basic import Mathlib.Algebra.Order.Archimedean.Hom +import Mathlib.Algebra.Order.Archimedean.IndicatorCard import Mathlib.Algebra.Order.Archimedean.Submonoid import Mathlib.Algebra.Order.BigOperators.Expect import Mathlib.Algebra.Order.BigOperators.Group.Finset diff --git a/Mathlib/Algebra/Order/Archimedean/IndicatorCard.lean b/Mathlib/Algebra/Order/Archimedean/IndicatorCard.lean new file mode 100644 index 0000000000000..18769abc95e63 --- /dev/null +++ b/Mathlib/Algebra/Order/Archimedean/IndicatorCard.lean @@ -0,0 +1,74 @@ +/- +Copyright (c) 2024 Damien Thomine. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damien Thomine +-/ +import Mathlib.Algebra.Order.Archimedean.Basic +import Mathlib.Algebra.Order.BigOperators.Group.Finset +import Mathlib.Algebra.Order.Group.Indicator +import Mathlib.Order.LiminfLimsup +import Mathlib.SetTheory.Cardinal.Finite + +/-! +# Cardinality and limit of sum of indicators +This file contains results relating the cardinality of subsets of ℕ and limits, +limsups of sums of indicators. + +## Tags +finite, indicator, limsup, tendsto +-/ + +namespace Set + +open Filter Finset + +lemma sum_indicator_eventually_eq_card {α : Type*} [AddCommMonoid α] (a : α) {s : Set ℕ} + (hs : s.Finite) : + ∀ᶠ n in atTop, ∑ k ∈ Finset.range n, s.indicator (fun _ ↦ a) k = (Nat.card s) • a := by + have key : ∀ x ∈ hs.toFinset, s.indicator (fun _ ↦ a) x = a := by + intro x hx + rw [indicator_of_mem (hs.mem_toFinset.1 hx) (fun _ ↦ a)] + rw [Nat.card_eq_card_finite_toFinset hs, ← sum_eq_card_nsmul key, eventually_atTop] + obtain ⟨m, hm⟩ := hs.bddAbove + refine ⟨m + 1, fun n n_m ↦ (sum_subset ?_ ?_).symm⟩ <;> intro x <;> rw [hs.mem_toFinset] + · rw [Finset.mem_range] + exact fun x_s ↦ ((mem_upperBounds.1 hm) x x_s).trans_lt (Nat.lt_of_succ_le n_m) + · exact fun _ x_s ↦ indicator_of_not_mem x_s (fun _ ↦ a) + +lemma infinite_iff_tendsto_sum_indicator_atTop {R : Type*} [OrderedAddCommMonoid R] + [AddLeftStrictMono R] [Archimedean R] {r : R} (h : 0 < r) {s : Set ℕ} : + s.Infinite ↔ atTop.Tendsto (fun n ↦ ∑ k ∈ Finset.range n, s.indicator (fun _ ↦ r) k) atTop := by + constructor + · have h_mono : Monotone fun n ↦ ∑ k ∈ Finset.range n, s.indicator (fun _ ↦ r) k := by + refine (sum_mono_set_of_nonneg ?_).comp range_mono + exact (fun _ ↦ indicator_nonneg (fun _ _ ↦ h.le) _) + rw [h_mono.tendsto_atTop_atTop_iff] + intro hs n + obtain ⟨n', hn'⟩ := exists_lt_nsmul h n + obtain ⟨t, t_s, t_card⟩ := hs.exists_subset_card_eq n' + obtain ⟨m, hm⟩ := t.bddAbove + refine ⟨m + 1, hn'.le.trans ?_⟩ + apply (sum_le_sum fun i _ ↦ (indicator_le_indicator_of_subset t_s (fun _ ↦ h.le)) i).trans_eq' + have h : t ⊆ Finset.range (m + 1) := by + intro i i_t + rw [Finset.mem_range] + exact (hm i_t).trans_lt (lt_add_one m) + rw [sum_indicator_subset (fun _ ↦ r) h, sum_eq_card_nsmul (fun _ _ ↦ rfl), t_card] + · contrapose + intro hs + rw [not_infinite] at hs + rw [tendsto_congr' (sum_indicator_eventually_eq_card r hs), tendsto_atTop_atTop] + push_neg + obtain ⟨m, hm⟩ := exists_lt_nsmul h (Nat.card s • r) + exact ⟨m • r, fun n ↦ ⟨n, le_refl n, not_le_of_lt hm⟩⟩ + +lemma limsup_eq_tendsto_sum_indicator_atTop {α R : Type*} [OrderedAddCommMonoid R] + [AddLeftStrictMono R] [Archimedean R] {r : R} (h : 0 < r) (s : ℕ → Set α) : + atTop.limsup s = { ω | atTop.Tendsto + (fun n ↦ ∑ k ∈ Finset.range n, (s k).indicator (fun _ ↦ r) ω) atTop } := by + nth_rw 1 [← Nat.cofinite_eq_atTop, cofinite.limsup_set_eq] + ext ω + rw [mem_setOf_eq, mem_setOf_eq, infinite_iff_tendsto_sum_indicator_atTop h, iff_eq_eq] + congr + +end Set diff --git a/Mathlib/MeasureTheory/OuterMeasure/Operations.lean b/Mathlib/MeasureTheory/OuterMeasure/Operations.lean index 9d73c991fc3ea..ff3e6271b01bd 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Operations.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Operations.lean @@ -3,6 +3,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, Mario Carneiro -/ +import Mathlib.Algebra.Order.Group.Indicator import Mathlib.MeasureTheory.OuterMeasure.Basic /-! diff --git a/Mathlib/NumberTheory/SumPrimeReciprocals.lean b/Mathlib/NumberTheory/SumPrimeReciprocals.lean index b7c071799368c..cc8ba145bd698 100644 --- a/Mathlib/NumberTheory/SumPrimeReciprocals.lean +++ b/Mathlib/NumberTheory/SumPrimeReciprocals.lean @@ -3,8 +3,9 @@ Copyright (c) 2023 Michael Stoll. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Stoll -/ -import Mathlib.NumberTheory.SmoothNumbers +import Mathlib.Algebra.Order.Group.Indicator import Mathlib.Analysis.PSeries +import Mathlib.NumberTheory.SmoothNumbers /-! # The sum of the reciprocals of the primes diverges diff --git a/Mathlib/Probability/Martingale/BorelCantelli.lean b/Mathlib/Probability/Martingale/BorelCantelli.lean index 0f483a8596a0b..f00e58badb8f1 100644 --- a/Mathlib/Probability/Martingale/BorelCantelli.lean +++ b/Mathlib/Probability/Martingale/BorelCantelli.lean @@ -3,9 +3,10 @@ Copyright (c) 2022 Kexing Ying. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kexing Ying -/ +import Mathlib.Algebra.Order.Archimedean.IndicatorCard +import Mathlib.Probability.Martingale.Centering import Mathlib.Probability.Martingale.Convergence import Mathlib.Probability.Martingale.OptionalStopping -import Mathlib.Probability.Martingale.Centering /-! @@ -361,7 +362,9 @@ everywhere equal to the set for which `∑ k, ℙ(s (k + 1) | ℱ k) = ∞`. -/ theorem ae_mem_limsup_atTop_iff (μ : Measure Ω) [IsFiniteMeasure μ] {s : ℕ → Set Ω} (hs : ∀ n, MeasurableSet[ℱ n] (s n)) : ∀ᵐ ω ∂μ, ω ∈ limsup s atTop ↔ Tendsto (fun n => ∑ k ∈ Finset.range n, - (μ[(s (k + 1)).indicator (1 : Ω → ℝ)|ℱ k]) ω) atTop atTop := - (limsup_eq_tendsto_sum_indicator_atTop ℝ s).symm ▸ tendsto_sum_indicator_atTop_iff' hs + (μ[(s (k + 1)).indicator (1 : Ω → ℝ)|ℱ k]) ω) atTop atTop := by + rw [← limsup_nat_add s 1, + Set.limsup_eq_tendsto_sum_indicator_atTop (zero_lt_one (α := ℝ)) (fun n ↦ s (n + 1))] + exact tendsto_sum_indicator_atTop_iff' hs end MeasureTheory diff --git a/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean b/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean index 9f2b202d56789..5be53f4ed4e3c 100644 --- a/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean +++ b/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean @@ -3,12 +3,8 @@ 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, Mario Carneiro, Yury Kudryashov, Yaël Dillies -/ -import Mathlib.Algebra.BigOperators.Intervals -import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.Order.Group.DenselyOrdered -import Mathlib.Algebra.Order.Group.Indicator import Mathlib.Data.Real.Archimedean -import Mathlib.Order.Filter.AtTopBot.Archimedean import Mathlib.Order.LiminfLimsup import Mathlib.Topology.Algebra.Group.Basic import Mathlib.Topology.Order.Monotone @@ -409,78 +405,6 @@ theorem Monotone.map_liminf_of_continuousAt {f : R → S} (f_incr : Monotone f) end Monotone -section Indicator - -theorem limsup_eq_tendsto_sum_indicator_nat_atTop (s : ℕ → Set α) : - limsup s atTop = { ω | Tendsto - (fun n ↦ ∑ k ∈ Finset.range n, (s (k + 1)).indicator (1 : α → ℕ) ω) atTop atTop } := by - ext ω - simp only [limsup_eq_iInf_iSup_of_nat, Set.iSup_eq_iUnion, Set.iInf_eq_iInter, - Set.mem_iInter, Set.mem_iUnion, exists_prop] - constructor - · intro hω - refine tendsto_atTop_atTop_of_monotone' (fun n m hnm ↦ Finset.sum_mono_set_of_nonneg - (fun i ↦ Set.indicator_nonneg (fun _ _ ↦ zero_le_one) _) (Finset.range_mono hnm)) ?_ - rintro ⟨i, h⟩ - simp only [mem_upperBounds, Set.mem_range, forall_exists_index, forall_apply_eq_imp_iff] at h - induction' i with k hk - · obtain ⟨j, hj₁, hj₂⟩ := hω 1 - refine not_lt.2 (h <| j + 1) - (lt_of_le_of_lt (Finset.sum_const_zero.symm : 0 = ∑ k ∈ Finset.range (j + 1), 0).le ?_) - refine Finset.sum_lt_sum (fun m _ ↦ Set.indicator_nonneg (fun _ _ ↦ zero_le_one) _) - ⟨j - 1, Finset.mem_range.2 (lt_of_le_of_lt (Nat.sub_le _ _) j.lt_succ_self), ?_⟩ - rw [Nat.sub_add_cancel hj₁, Set.indicator_of_mem hj₂] - exact zero_lt_one - · rw [imp_false] at hk - push_neg at hk - obtain ⟨i, hi⟩ := hk - obtain ⟨j, hj₁, hj₂⟩ := hω (i + 1) - replace hi : (∑ k ∈ Finset.range i, (s (k + 1)).indicator 1 ω) = k + 1 := - le_antisymm (h i) hi - refine not_lt.2 (h <| j + 1) ?_ - rw [← Finset.sum_range_add_sum_Ico _ (i.le_succ.trans (hj₁.trans j.le_succ)), hi] - refine lt_add_of_pos_right _ ?_ - rw [(Finset.sum_const_zero.symm : 0 = ∑ k ∈ Finset.Ico i (j + 1), 0)] - refine Finset.sum_lt_sum (fun m _ ↦ Set.indicator_nonneg (fun _ _ ↦ zero_le_one) _) - ⟨j - 1, Finset.mem_Ico.2 ⟨(Nat.le_sub_iff_add_le (le_trans ((le_add_iff_nonneg_left _).2 - zero_le') hj₁)).2 hj₁, lt_of_le_of_lt (Nat.sub_le _ _) j.lt_succ_self⟩, ?_⟩ - rw [Nat.sub_add_cancel (le_trans ((le_add_iff_nonneg_left _).2 zero_le') hj₁), - Set.indicator_of_mem hj₂] - exact zero_lt_one - · rintro hω i - rw [Set.mem_setOf_eq, tendsto_atTop_atTop] at hω - by_contra! hcon - obtain ⟨j, h⟩ := hω (i + 1) - have : (∑ k ∈ Finset.range j, (s (k + 1)).indicator 1 ω) ≤ i := by - have hle : ∀ j ≤ i, (∑ k ∈ Finset.range j, (s (k + 1)).indicator 1 ω) ≤ i := by - refine fun j hij ↦ - (Finset.sum_le_card_nsmul _ _ _ ?_ : _ ≤ (Finset.range j).card • 1).trans ?_ - · exact fun m _ ↦ Set.indicator_apply_le' (fun _ ↦ le_rfl) fun _ ↦ zero_le_one - · simpa only [Finset.card_range, smul_eq_mul, mul_one] - by_cases hij : j < i - · exact hle _ hij.le - · rw [← Finset.sum_range_add_sum_Ico _ (not_lt.1 hij)] - suffices (∑ k ∈ Finset.Ico i j, (s (k + 1)).indicator 1 ω) = 0 by - rw [this, add_zero] - exact hle _ le_rfl - refine Finset.sum_eq_zero fun m hm ↦ ?_ - exact Set.indicator_of_not_mem (hcon _ <| (Finset.mem_Ico.1 hm).1.trans m.le_succ) _ - exact not_le.2 (lt_of_lt_of_le i.lt_succ_self <| h _ le_rfl) this - -theorem limsup_eq_tendsto_sum_indicator_atTop (R : Type*) [StrictOrderedSemiring R] [Archimedean R] - (s : ℕ → Set α) : limsup s atTop = { ω | Tendsto - (fun n ↦ ∑ k ∈ Finset.range n, (s (k + 1)).indicator (1 : α → R) ω) atTop atTop } := by - rw [limsup_eq_tendsto_sum_indicator_nat_atTop s] - ext ω - simp only [Set.mem_setOf_eq] - rw [(_ : (fun n ↦ ∑ k ∈ Finset.range n, (s (k + 1)).indicator (1 : α → R) ω) = fun n ↦ - ↑(∑ k ∈ Finset.range n, (s (k + 1)).indicator (1 : α → ℕ) ω))] - · exact tendsto_natCast_atTop_iff.symm - · ext n - simp only [Set.indicator, Pi.one_apply, Finset.sum_boole, Nat.cast_id] - -end Indicator - section LiminfLimsupAdd variable [AddCommGroup α] [ConditionallyCompleteLinearOrder α] [DenselyOrdered α] diff --git a/Mathlib/Topology/Instances/ENNReal/Lemmas.lean b/Mathlib/Topology/Instances/ENNReal/Lemmas.lean index 769d4aa27d05a..e6520245b62c1 100644 --- a/Mathlib/Topology/Instances/ENNReal/Lemmas.lean +++ b/Mathlib/Topology/Instances/ENNReal/Lemmas.lean @@ -3,15 +3,14 @@ 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 -/ -import Mathlib.Topology.Order.MonotoneContinuity +import Mathlib.Algebra.BigOperators.Intervals import Mathlib.Topology.Algebra.Order.LiminfLimsup import Mathlib.Topology.Instances.ENNReal.Defs import Mathlib.Topology.Instances.NNReal.Lemmas -import Mathlib.Topology.EMetricSpace.Lipschitz -import Mathlib.Topology.Metrizable.Basic -import Mathlib.Topology.Order.T5 import Mathlib.Topology.MetricSpace.Pseudo.Real import Mathlib.Topology.Metrizable.Uniformity +import Mathlib.Topology.Order.MonotoneContinuity +import Mathlib.Topology.Order.T5 /-! # Topology on extended non-negative reals diff --git a/Mathlib/Topology/UrysohnsLemma.lean b/Mathlib/Topology/UrysohnsLemma.lean index 411f0e25ccac7..89fe23dc6ebf9 100644 --- a/Mathlib/Topology/UrysohnsLemma.lean +++ b/Mathlib/Topology/UrysohnsLemma.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.Algebra.Order.Group.Indicator import Mathlib.Analysis.Normed.Affine.AddTorsor import Mathlib.Analysis.NormedSpace.FunctionSeries import Mathlib.Analysis.SpecificLimits.Basic From 590c3a6dd41193982db1a74cc3efa43e11463471 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 21 Jan 2025 18:51:06 +0000 Subject: [PATCH 387/681] chore: review of `nolint simpNF` (#20867) Closes #18942. --- Mathlib/Algebra/Category/Semigrp/Basic.lean | 4 +-- Mathlib/Algebra/Free.lean | 15 ++++---- .../Algebra/Homology/DifferentialObject.lean | 5 +-- Mathlib/Algebra/Order/CompleteField.lean | 1 - Mathlib/Algebra/Ring/Commute.lean | 1 - Mathlib/Algebra/Ring/Subring/Basic.lean | 5 --- .../GammaSpecAdjunction.lean | 4 --- .../ProjectiveSpectrum/StructureSheaf.lean | 6 +--- Mathlib/AlgebraicGeometry/Spec.lean | 4 --- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 10 ++---- .../FundamentalGroupoid/InducedMaps.lean | 2 -- Mathlib/Analysis/CStarAlgebra/Basic.lean | 3 -- Mathlib/Analysis/Normed/Group/Hom.lean | 1 - .../Group/SemiNormedGrp/Completion.lean | 4 --- Mathlib/Analysis/Normed/Group/Seminorm.lean | 3 -- Mathlib/Analysis/VonNeumannAlgebra/Basic.lean | 1 - Mathlib/CategoryTheory/Action/Monoidal.lean | 4 --- Mathlib/CategoryTheory/Closed/Cartesian.lean | 6 ---- .../Closed/FunctorCategory/Groupoid.lean | 2 -- Mathlib/CategoryTheory/Comma/Over.lean | 15 ++------ .../Comma/StructuredArrow/Basic.lean | 36 ++++--------------- .../Limits/Shapes/Equalizers.lean | 11 ++---- .../CategoryTheory/Limits/Shapes/Images.lean | 5 ++- .../Limits/Shapes/Multiequalizer.lean | 12 +++---- .../Limits/Shapes/Reflexive.lean | 6 ++-- .../Limits/Shapes/WideEqualizers.lean | 4 +-- .../Limits/Shapes/WidePullbacks.lean | 18 +++------- .../Limits/Shapes/ZeroMorphisms.lean | 4 --- .../CategoryTheory/Monoidal/Free/Basic.lean | 6 ++-- .../Preadditive/Yoneda/Basic.lean | 8 ++--- Mathlib/CategoryTheory/Sites/Sheaf.lean | 5 --- Mathlib/CategoryTheory/Subobject/Comma.lean | 5 --- Mathlib/Data/DFinsupp/BigOperators.lean | 1 - Mathlib/Data/DFinsupp/Defs.lean | 2 +- Mathlib/Data/Fin/Tuple/Basic.lean | 2 +- Mathlib/Data/Finset/Lattice/Fold.lean | 2 +- Mathlib/Data/Finset/Sups.lean | 2 -- Mathlib/Data/Finset/Sym.lean | 2 -- Mathlib/Data/Finset/Union.lean | 3 +- Mathlib/Data/Finsupp/Basic.lean | 2 +- Mathlib/Data/Finsupp/ToDFinsupp.lean | 3 -- Mathlib/Data/List/Basic.lean | 5 --- Mathlib/Data/Matrix/DMatrix.lean | 7 +--- Mathlib/Data/Matrix/Defs.lean | 7 +--- Mathlib/Data/Matrix/Diagonal.lean | 3 -- Mathlib/Data/Matrix/Mul.lean | 2 -- Mathlib/Data/NNRat/Defs.lean | 9 ++--- Mathlib/Data/Set/Function.lean | 1 - Mathlib/Data/Set/MulAntidiagonal.lean | 2 +- Mathlib/Data/SetLike/Basic.lean | 2 +- Mathlib/Data/Setoid/Partition.lean | 3 +- Mathlib/Data/Sigma/Basic.lean | 2 +- Mathlib/Data/Sign.lean | 8 ++--- Mathlib/Data/Subtype.lean | 8 ++--- .../FieldTheory/IntermediateField/Basic.lean | 6 ---- Mathlib/Geometry/Manifold/ChartedSpace.lean | 5 ++- Mathlib/GroupTheory/Complement.lean | 4 --- Mathlib/GroupTheory/OrderOfElement.lean | 6 ++-- Mathlib/GroupTheory/SemidirectProduct.lean | 8 ++--- Mathlib/LinearAlgebra/Isomorphisms.lean | 2 -- Mathlib/LinearAlgebra/Matrix/ToLin.lean | 6 ---- Mathlib/LinearAlgebra/Multilinear/Basic.lean | 5 ++- Mathlib/LinearAlgebra/QuadraticForm/Prod.lean | 2 +- Mathlib/Logic/Unique.lean | 10 ++---- .../MeasureTheory/Measure/FiniteMeasure.lean | 1 - Mathlib/NumberTheory/Divisors.lean | 8 +---- Mathlib/Order/Category/BddLat.lean | 9 ----- Mathlib/Order/Interval/Basic.lean | 11 +++--- Mathlib/Topology/Algebra/Module/Star.lean | 6 +--- .../Category/LightProfinite/Basic.lean | 6 +--- .../Topology/Category/Profinite/Basic.lean | 6 +--- Mathlib/Topology/ContinuousMap/Units.lean | 1 - 72 files changed, 86 insertions(+), 310 deletions(-) diff --git a/Mathlib/Algebra/Category/Semigrp/Basic.lean b/Mathlib/Algebra/Category/Semigrp/Basic.lean index f020632a9ccb5..7be4ed672212c 100644 --- a/Mathlib/Algebra/Category/Semigrp/Basic.lean +++ b/Mathlib/Algebra/Category/Semigrp/Basic.lean @@ -100,7 +100,7 @@ def ofHom {X Y : Type u} [Mul X] [Mul Y] (f : X →ₙ* Y) : of X ⟶ of Y := f /-- Typecheck an `AddHom` as a morphism in `AddMagmaCat`. -/ add_decl_doc AddMagmaCat.ofHom -@[to_additive] -- Porting note: simp removed, simpNF says LHS simplifies to itself +@[to_additive] theorem ofHom_apply {X Y : Type u} [Mul X] [Mul Y] (f : X →ₙ* Y) (x : X) : ofHom f x = f x := rfl @@ -180,7 +180,7 @@ def ofHom {X Y : Type u} [Semigroup X] [Semigroup Y] (f : X →ₙ* Y) : of X /-- Typecheck an `AddHom` as a morphism in `AddSemigrp`. -/ add_decl_doc AddSemigrp.ofHom -@[to_additive] -- Porting note: simp removed, simpNF says LHS simplifies to itself +@[to_additive] theorem ofHom_apply {X Y : Type u} [Semigroup X] [Semigroup Y] (f : X →ₙ* Y) (x : X) : ofHom f x = f x := rfl diff --git a/Mathlib/Algebra/Free.lean b/Mathlib/Algebra/Free.lean index 50961c7a71981..c0663264e177d 100644 --- a/Mathlib/Algebra/Free.lean +++ b/Mathlib/Algebra/Free.lean @@ -28,6 +28,10 @@ import Mathlib.Tactic.AdaptationNote universe u v l +-- Disable generation of `sizeOf_spec` and `injEq`, +-- which are not needed and the `simpNF` linter will complain about. +set_option genSizeOfSpec false in +set_option genInjectivity false in /-- Free nonabelian additive magma over a given alphabet. -/ inductive FreeAddMagma (α : Type u) : Type u | of : α → FreeAddMagma α @@ -35,6 +39,10 @@ inductive FreeAddMagma (α : Type u) : Type u deriving DecidableEq compile_inductive% FreeAddMagma +-- Disable generation of `sizeOf_spec` and `injEq`, +-- which are not needed and the `simpNF` linter will complain about. +set_option genSizeOfSpec false in +set_option genInjectivity false in /-- Free magma over a given alphabet. -/ @[to_additive] inductive FreeMagma (α : Type u) : Type u @@ -59,13 +67,6 @@ instance : Mul (FreeMagma α) := ⟨FreeMagma.mul⟩ @[to_additive (attr := simp)] theorem mul_eq (x y : FreeMagma α) : mul x y = x * y := rfl -/-! These lemmas are autogenerated by the inductive definition and due to -the existence of `mul_eq` not in simp normal form -/ -attribute [nolint simpNF] FreeAddMagma.add.sizeOf_spec -attribute [nolint simpNF] FreeMagma.mul.sizeOf_spec -attribute [nolint simpNF] FreeAddMagma.add.injEq -attribute [nolint simpNF] FreeMagma.mul.injEq - /-- Recursor for `FreeMagma` using `x * y` instead of `FreeMagma.mul x y`. -/ @[to_additive (attr := elab_as_elim, induction_eliminator) "Recursor for `FreeAddMagma` using `x + y` instead of `FreeAddMagma.add x y`."] diff --git a/Mathlib/Algebra/Homology/DifferentialObject.lean b/Mathlib/Algebra/Homology/DifferentialObject.lean index b83a6ba0c7334..c434db0589dc7 100644 --- a/Mathlib/Algebra/Homology/DifferentialObject.lean +++ b/Mathlib/Algebra/Homology/DifferentialObject.lean @@ -61,10 +61,7 @@ namespace HomologicalComplex variable {β : Type*} [AddCommGroup β] (b : β) variable (V : Type*) [Category V] [HasZeroMorphisms V] --- Porting note: this should be moved to an earlier file. --- Porting note: simpNF linter silenced, both `d_eqToHom` and its `_assoc` version --- do not simplify under themselves -@[reassoc (attr := simp, nolint simpNF)] +@[reassoc] theorem d_eqToHom (X : HomologicalComplex V (ComplexShape.up' b)) {x y z : β} (h : y = z) : X.d x y ≫ eqToHom (congr_arg X.X h) = X.d x z := by cases h; simp diff --git a/Mathlib/Algebra/Order/CompleteField.lean b/Mathlib/Algebra/Order/CompleteField.lean index 5ac0f4d4135a6..7a096783dc245 100644 --- a/Mathlib/Algebra/Order/CompleteField.lean +++ b/Mathlib/Algebra/Order/CompleteField.lean @@ -99,7 +99,6 @@ variable {β} @[simp] theorem mem_cutMap_iff : b ∈ cutMap β a ↔ ∃ q : ℚ, (q : α) < a ∧ (q : β) = b := Iff.rfl --- @[simp] -- Porting note: not in simpNF theorem coe_mem_cutMap_iff [CharZero β] : (q : β) ∈ cutMap β a ↔ (q : α) < a := Rat.cast_injective.mem_set_image diff --git a/Mathlib/Algebra/Ring/Commute.lean b/Mathlib/Algebra/Ring/Commute.lean index 381b7109ee286..794103b3e5ae2 100644 --- a/Mathlib/Algebra/Ring/Commute.lean +++ b/Mathlib/Algebra/Ring/Commute.lean @@ -133,7 +133,6 @@ lemma neg_pow' (a : R) (n : ℕ) : (-a) ^ n = a ^ n * (-1) ^ n := lemma neg_sq (a : R) : (-a) ^ 2 = a ^ 2 := by simp [sq] --- Porting note: removed the simp attribute to please the simpNF linter lemma neg_one_sq : (-1 : R) ^ 2 = 1 := by simp [neg_sq, one_pow] alias neg_pow_two := neg_sq diff --git a/Mathlib/Algebra/Ring/Subring/Basic.lean b/Mathlib/Algebra/Ring/Subring/Basic.lean index 6e38a46a7b4a4..761bf9815c924 100644 --- a/Mathlib/Algebra/Ring/Subring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subring/Basic.lean @@ -873,14 +873,9 @@ theorem ofLeftInverse_symm_apply {g : S → R} {f : R →+* S} (h : Function.Lef /-- Given an equivalence `e : R ≃+* S` of rings and a subring `s` of `R`, `subringMap e s` is the induced equivalence between `s` and `s.map e` -/ -@[simps!] def subringMap (e : R ≃+* S) : s ≃+* s.map e.toRingHom := e.subsemiringMap s.toSubsemiring --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] RingEquiv.subringMap_symm_apply_coe - RingEquiv.subringMap_apply_coe - end RingEquiv namespace Subring diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index 82314906f6c4c..b5c6c59606696 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -88,14 +88,10 @@ theorem toΓSpec_continuous : Continuous X.toΓSpecFun := by /-- The canonical (bundled) continuous map from the underlying topological space of `X` to the prime spectrum of its global sections. -/ -@[simps] def toΓSpecBase : X.toTopCat ⟶ Spec.topObj (Γ.obj (op X)) where toFun := X.toΓSpecFun continuous_toFun := X.toΓSpec_continuous --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] AlgebraicGeometry.LocallyRingedSpace.toΓSpecBase_apply - variable (r : Γ.obj (op X)) /-- The preimage in `X` of a basic open in `Spec Γ(X)` (as an open set). -/ diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean index 818f55693d133..7fc0bc4d9218a 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean @@ -174,7 +174,7 @@ instance commRingStructureSheafInTypeObj (U : (Opens (ProjectiveSpectrum.top /-- The structure presheaf, valued in `CommRing`, constructed by dressing up the `Type` valued structure presheaf. -/ -@[simps] +@[simps obj_carrier] def structurePresheafInCommRing : Presheaf CommRingCat (ProjectiveSpectrum.top 𝒜) where obj U := CommRingCat.of ((structureSheafInType 𝒜).1.obj U) map i := CommRingCat.ofHom @@ -184,10 +184,6 @@ def structurePresheafInCommRing : Presheaf CommRingCat (ProjectiveSpectrum.top map_one' := rfl map_mul' := fun _ _ => rfl } --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] - AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.structurePresheafInCommRing_map_hom_apply - /-- Some glue, verifying that the structure presheaf valued in `CommRing` agrees with the `Type` valued structure presheaf. -/ def structurePresheafCompForget : diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index 0769318a82148..fe628dda5c4cb 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -280,13 +280,9 @@ section SpecΓ open AlgebraicGeometry.LocallyRingedSpace /-- The counit morphism `R ⟶ Γ(Spec R)` given by `AlgebraicGeometry.StructureSheaf.toOpen`. -/ -@[simps!] def toSpecΓ (R : CommRingCat.{u}) : R ⟶ Γ.obj (op (Spec.toLocallyRingedSpace.obj (op R))) := StructureSheaf.toOpen R ⊤ --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] AlgebraicGeometry.toSpecΓ_hom_apply_coe - instance isIso_toSpecΓ (R : CommRingCat.{u}) : IsIso (toSpecΓ R) := by cases R; apply StructureSheaf.isIso_to_global diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index 309e345b93978..55c3b14a35165 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -223,7 +223,7 @@ open PrimeSpectrum /-- The structure presheaf, valued in `CommRingCat`, constructed by dressing up the `Type` valued structure presheaf. -/ -@[simps] +@[simps obj_carrier] def structurePresheafInCommRing : Presheaf CommRingCat (PrimeSpectrum.Top R) where obj U := CommRingCat.of ((structureSheafInType R).1.obj U) map {_ _} i := CommRingCat.ofHom @@ -233,9 +233,6 @@ def structurePresheafInCommRing : Presheaf CommRingCat (PrimeSpectrum.Top R) whe map_one' := rfl map_mul' := fun _ _ => rfl } --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] AlgebraicGeometry.structurePresheafInCommRing_map_hom_apply - /-- Some glue, verifying that the structure presheaf valued in `CommRingCat` agrees with the `Type` valued structure presheaf. -/ @@ -929,13 +926,10 @@ instance isIso_to_global : IsIso (toOpen R ⊤) := by infer_instance /-- The ring isomorphism between the ring `R` and the global sections `Γ(X, 𝒪ₓ)`. -/ -@[simps!] +@[simps! inv] def globalSectionsIso : CommRingCat.of R ≅ (structureSheaf R).1.obj (op ⊤) := asIso (toOpen R ⊤) --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] AlgebraicGeometry.StructureSheaf.globalSectionsIso_hom_hom_apply_coe - @[simp] theorem globalSectionsIso_hom (R : CommRingCat) : (globalSectionsIso R).hom = toOpen R ⊤ := rfl diff --git a/Mathlib/AlgebraicTopology/FundamentalGroupoid/InducedMaps.lean b/Mathlib/AlgebraicTopology/FundamentalGroupoid/InducedMaps.lean index 99f2a18da0783..4ba7cc3bd0912 100644 --- a/Mathlib/AlgebraicTopology/FundamentalGroupoid/InducedMaps.lean +++ b/Mathlib/AlgebraicTopology/FundamentalGroupoid/InducedMaps.lean @@ -136,8 +136,6 @@ def uliftMap : C(TopCat.of (ULift.{u} I × X), Y) := ⟨fun x => H (x.1.down, x.2), H.continuous.comp ((continuous_uLift_down.comp continuous_fst).prod_mk continuous_snd)⟩ --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[simp, nolint simpNF] theorem ulift_apply (i : ULift.{u} I) (x : X) : H.uliftMap (i, x) = H (i.down, x) := rfl diff --git a/Mathlib/Analysis/CStarAlgebra/Basic.lean b/Mathlib/Analysis/CStarAlgebra/Basic.lean index cd2cb5b8628a8..4338e91c5e23b 100644 --- a/Mathlib/Analysis/CStarAlgebra/Basic.lean +++ b/Mathlib/Analysis/CStarAlgebra/Basic.lean @@ -177,9 +177,6 @@ section Unital variable [NormedRing E] [StarRing E] [CStarRing E] --- Porting note https://github.com/leanprover-community/mathlib4/issues/10959 --- simp cannot prove this -@[simp, nolint simpNF] theorem norm_one [Nontrivial E] : ‖(1 : E)‖ = 1 := by have : 0 < ‖(1 : E)‖ := norm_pos_iff.mpr one_ne_zero rw [← mul_left_inj' this.ne', ← norm_star_mul_self, mul_one, star_one, one_mul] diff --git a/Mathlib/Analysis/Normed/Group/Hom.lean b/Mathlib/Analysis/Normed/Group/Hom.lean index 9a2101245416a..2e71c2d63fefc 100644 --- a/Mathlib/Analysis/Normed/Group/Hom.lean +++ b/Mathlib/Analysis/Normed/Group/Hom.lean @@ -110,7 +110,6 @@ variable (f g) theorem toFun_eq_coe : f.toFun = f := rfl --- Porting note: removed `simp` because `simpNF` complains the LHS doesn't simplify. theorem coe_mk (f) (h₁) (h₂) (h₃) : ⇑(⟨f, h₁, h₂, h₃⟩ : NormedAddGroupHom V₁ V₂) = f := rfl diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean index e0c929f53e5a7..15de9d58c9cde 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean @@ -51,15 +51,11 @@ instance completion_completeSpace {V : SemiNormedGrp} : CompleteSpace (completio Completion.completeSpace _ /-- The canonical morphism from a seminormed group `V` to its completion. -/ -@[simps] def completion.incl {V : SemiNormedGrp} : V ⟶ completion.obj V where toFun v := (v : Completion V) map_add' := Completion.coe_add bound' := ⟨1, fun v => by simp⟩ --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] SemiNormedGrp.completion.incl_apply - theorem completion.norm_incl_eq {V : SemiNormedGrp} {v : V} : ‖completion.incl v‖ = ‖v‖ := UniformSpace.Completion.norm_coe _ diff --git a/Mathlib/Analysis/Normed/Group/Seminorm.lean b/Mathlib/Analysis/Normed/Group/Seminorm.lean index e895bf01b8d3c..810ab65630fd8 100644 --- a/Mathlib/Analysis/Normed/Group/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Group/Seminorm.lean @@ -443,7 +443,6 @@ instance nonarchAddGroupSeminormClass : map_zero f := f.map_zero' map_neg_eq_map' f := f.neg' --- Porting note: `simpNF` said the left hand side simplified to this @[simp] theorem toZeroHom_eq_coe : ⇑p.toZeroHom = p := by rfl @@ -659,7 +658,6 @@ instance groupNormClass : GroupNormClass (GroupNorm E) E ℝ where map_inv_eq_map f := f.inv' eq_one_of_map_eq_zero f := f.eq_one_of_map_eq_zero' _ --- Porting note: `simpNF` told me the left-hand side simplified to this @[to_additive (attr := simp)] theorem toGroupSeminorm_eq_coe : ⇑p.toGroupSeminorm = p := rfl @@ -784,7 +782,6 @@ instance nonarchAddGroupNormClass : NonarchAddGroupNormClass (NonarchAddGroupNor map_neg_eq_map' f := f.neg' eq_zero_of_map_eq_zero f := f.eq_zero_of_map_eq_zero' _ --- Porting note: `simpNF` told me the left-hand side simplified to this @[simp] theorem toNonarchAddGroupSeminorm_eq_coe : ⇑p.toNonarchAddGroupSeminorm = p := rfl diff --git a/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean b/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean index 4bf4e8678ab11..ef14d27e5fae7 100644 --- a/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean +++ b/Mathlib/Analysis/VonNeumannAlgebra/Basic.lean @@ -95,7 +95,6 @@ instance instSubringClass : SubringClass (VonNeumannAlgebra H) (H →L[ℂ] H) w theorem mem_carrier {S : VonNeumannAlgebra H} {x : H →L[ℂ] H} : x ∈ S.toStarSubalgebra ↔ x ∈ (S : Set (H →L[ℂ] H)) := Iff.rfl --- Porting note: changed the declaration because `simpNF` indicated the LHS simplifies to this. @[simp] theorem coe_toStarSubalgebra (S : VonNeumannAlgebra H) : diff --git a/Mathlib/CategoryTheory/Action/Monoidal.lean b/Mathlib/CategoryTheory/Action/Monoidal.lean index cc31bc6edd902..8bb4bce035d12 100644 --- a/Mathlib/CategoryTheory/Action/Monoidal.lean +++ b/Mathlib/CategoryTheory/Action/Monoidal.lean @@ -183,13 +183,9 @@ theorem rightDual_v [RightRigidCategory V] : Xᘁ.V = X.Vᘁ := theorem leftDual_v [LeftRigidCategory V] : (ᘁX).V = ᘁX.V := rfl --- This lemma was always bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644 -@[simp, nolint simpNF] theorem rightDual_ρ [RightRigidCategory V] (h : H) : Xᘁ.ρ h = (X.ρ (h⁻¹ : H))ᘁ := by rw [← SingleObj.inv_as_inv]; rfl --- This lemma was always bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644 -@[simp, nolint simpNF] theorem leftDual_ρ [LeftRigidCategory V] (h : H) : (ᘁX).ρ h = ᘁX.ρ (h⁻¹ : H) := by rw [← SingleObj.inv_as_inv]; rfl diff --git a/Mathlib/CategoryTheory/Closed/Cartesian.lean b/Mathlib/CategoryTheory/Closed/Cartesian.lean index c79932f744135..22eb522f83727 100644 --- a/Mathlib/CategoryTheory/Closed/Cartesian.lean +++ b/Mathlib/CategoryTheory/Closed/Cartesian.lean @@ -163,13 +163,9 @@ def curry : (A ⊗ Y ⟶ X) → (Y ⟶ A ⟹ X) := def uncurry : (Y ⟶ A ⟹ X) → (A ⊗ Y ⟶ X) := ((exp.adjunction A).homEquiv _ _).symm --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[simp, nolint simpNF] theorem homEquiv_apply_eq (f : A ⊗ Y ⟶ X) : (exp.adjunction A).homEquiv _ _ f = curry f := rfl --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[simp, nolint simpNF] theorem homEquiv_symm_apply_eq (f : Y ⟶ A ⟹ X) : ((exp.adjunction A).homEquiv _ _).symm f = uncurry f := rfl @@ -375,6 +371,4 @@ def cartesianClosedOfEquiv (e : C ≌ D) [CartesianClosed C] : CartesianClosed D end Functor -attribute [nolint simpNF] CategoryTheory.CartesianClosed.homEquiv_apply_eq - CategoryTheory.CartesianClosed.homEquiv_symm_apply_eq end CategoryTheory diff --git a/Mathlib/CategoryTheory/Closed/FunctorCategory/Groupoid.lean b/Mathlib/CategoryTheory/Closed/FunctorCategory/Groupoid.lean index a304a8071b6d1..16828b2e30c69 100644 --- a/Mathlib/CategoryTheory/Closed/FunctorCategory/Groupoid.lean +++ b/Mathlib/CategoryTheory/Closed/FunctorCategory/Groupoid.lean @@ -57,8 +57,6 @@ def closedCounit (F : D ⥤ C) : closedIhom F ⋙ tensorLeft F ⟶ 𝟭 (D ⥤ C /-- If `C` is a monoidal closed category and `D` is a groupoid, then every functor `F : D ⥤ C` is closed in the functor category `F : D ⥤ C` with the pointwise monoidal structure. -/ --- Porting note: removed `@[simps]`, as some of the generated lemmas were failing the simpNF linter, --- and none of the generated lemmas was actually used in mathlib3. instance closed (F : D ⥤ C) : Closed F where rightAdj := closedIhom F adj := diff --git a/Mathlib/CategoryTheory/Comma/Over.lean b/Mathlib/CategoryTheory/Comma/Over.lean index 1ecfb385e2edb..570cbd7d2a569 100644 --- a/Mathlib/CategoryTheory/Comma/Over.lean +++ b/Mathlib/CategoryTheory/Comma/Over.lean @@ -92,24 +92,18 @@ end /-- To give a morphism in the over category, it suffices to give an arrow fitting in a commutative triangle. -/ -@[simps!] +@[simps! left] def homMk {U V : Over X} (f : U.left ⟶ V.left) (w : f ≫ V.hom = U.hom := by aesop_cat) : U ⟶ V := CostructuredArrow.homMk f w --- Porting note: simp solves this; simpNF still sees them after `-simp` (?) -attribute [-simp, nolint simpNF] homMk_right_down_down - /-- Construct an isomorphism in the over category given isomorphisms of the objects whose forward direction gives a commutative triangle. -/ -@[simps!] +@[simps! hom_left inv_left] def isoMk {f g : Over X} (hl : f.left ≅ g.left) (hw : hl.hom ≫ g.hom = f.hom := by aesop_cat) : f ≅ g := CostructuredArrow.isoMk hl hw --- Porting note: simp solves this; simpNF still sees them after `-simp` (?) -attribute [-simp, nolint simpNF] isoMk_hom_right_down_down isoMk_inv_right_down_down - @[reassoc (attr := simp)] lemma hom_left_inv_left {f g : Over X} (e : f ≅ g) : e.hom.left ≫ e.inv.left = 𝟙 f.left := by @@ -464,13 +458,10 @@ def mk {X Y : T} (f : X ⟶ Y) : Under X := /-- To give a morphism in the under category, it suffices to give a morphism fitting in a commutative triangle. -/ -@[simps!] +@[simps! right] def homMk {U V : Under X} (f : U.right ⟶ V.right) (w : U.hom ≫ f = V.hom := by aesop_cat) : U ⟶ V := StructuredArrow.homMk f w --- Porting note: simp solves this; simpNF still sees them after `-simp` (?) -attribute [-simp, nolint simpNF] homMk_left_down_down - /-- Construct an isomorphism in the over category given isomorphisms of the objects whose forward direction gives a commutative triangle. -/ diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean index b68e5a370f281..427319b4e9619 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow/Basic.lean @@ -95,7 +95,7 @@ theorem left_eq_id {X Y : StructuredArrow S T} (f : X ⟶ Y) : f.left = 𝟙 X.l we need a morphism of the objects underlying the target, and to check that the triangle commutes. -/ -@[simps] +@[simps right] def homMk {f f' : StructuredArrow S T} (g : f.right ⟶ f'.right) (w : f.hom ≫ T.map g = f'.hom := by aesop_cat) : f ⟶ f' where left := 𝟙 f.left @@ -104,10 +104,6 @@ def homMk {f f' : StructuredArrow S T} (g : f.right ⟶ f'.right) dsimp simpa using w.symm -/- Porting note: it appears the simp lemma is not getting generated but the linter -picks up on it (seems like a bug). Either way simp solves it. -/ -attribute [-simp, nolint simpNF] homMk_left - theorem homMk_surjective {f f' : StructuredArrow S T} (φ : f ⟶ f') : ∃ (ψ : f.right ⟶ f'.right) (hψ : f.hom ≫ T.map ψ = f'.hom), φ = StructuredArrow.homMk ψ hψ := @@ -151,16 +147,12 @@ lemma mkPostcomp_comp (f : S ⟶ T.obj Y) (g : Y ⟶ Y') (g' : Y' ⟶ Y'') : we need an isomorphism of the objects underlying the target, and to check that the triangle commutes. -/ -@[simps!] +@[simps! hom_right inv_right] def isoMk {f f' : StructuredArrow S T} (g : f.right ≅ f'.right) (w : f.hom ≫ T.map g.hom = f'.hom := by aesop_cat) : f ≅ f' := Comma.isoMk (eqToIso (by ext)) g (by simpa using w.symm) -/- Porting note: it appears the simp lemma is not getting generated but the linter -picks up on it. Either way simp solves these. -/ -attribute [-simp, nolint simpNF] isoMk_hom_left_down_down isoMk_inv_left_down_down - theorem ext {A B : StructuredArrow S T} (f g : A ⟶ B) : f.right = g.right → f = g := CommaMorphism.ext (Subsingleton.elim _ _) @@ -191,14 +183,10 @@ theorem eq_mk (f : StructuredArrow S T) : f = mk f.hom := rfl /-- Eta rule for structured arrows. -/ -@[simps!] +@[simps! hom_right inv_right] def eta (f : StructuredArrow S T) : f ≅ mk f.hom := isoMk (Iso.refl _) -/- Porting note: it appears the simp lemma is not getting generated but the linter -picks up on it. Either way simp solves these. -/ -attribute [-simp, nolint simpNF] eta_hom_left_down_down eta_inv_left_down_down - lemma mk_surjective (f : StructuredArrow S T) : ∃ (Y : C) (g : S ⟶ T.obj Y), f = mk g := ⟨_, _, eq_mk f⟩ @@ -458,16 +446,12 @@ theorem right_eq_id {X Y : CostructuredArrow S T} (f : X ⟶ Y) : f.right = 𝟙 we need a morphism of the objects underlying the source, and to check that the triangle commutes. -/ -@[simps!] +@[simps! left] def homMk {f f' : CostructuredArrow S T} (g : f.left ⟶ f'.left) (w : S.map g ≫ f'.hom = f.hom := by aesop_cat) : f ⟶ f' where left := g right := 𝟙 f.right -/- Porting note: it appears the simp lemma is not getting generated but the linter -picks up on it. Either way simp can prove this -/ -attribute [-simp, nolint simpNF] homMk_right_down_down - theorem homMk_surjective {f f' : CostructuredArrow S T} (φ : f ⟶ f') : ∃ (ψ : f.left ⟶ f'.left) (hψ : S.map ψ ≫ f'.hom = f.hom), φ = CostructuredArrow.homMk ψ hψ := @@ -511,15 +495,11 @@ lemma mkPrecomp_comp (f : S.obj Y ⟶ T) (g : Y' ⟶ Y) (g' : Y'' ⟶ Y') : we need an isomorphism of the objects underlying the source, and to check that the triangle commutes. -/ -@[simps!] +@[simps! hom_left inv_left] def isoMk {f f' : CostructuredArrow S T} (g : f.left ≅ f'.left) (w : S.map g.hom ≫ f'.hom = f.hom := by aesop_cat) : f ≅ f' := Comma.isoMk g (eqToIso (by ext)) (by simpa using w) -/- Porting note: it appears the simp lemma is not getting generated but the linter -picks up on it. Either way simp solves these. -/ -attribute [-simp, nolint simpNF] isoMk_hom_right_down_down isoMk_inv_right_down_down - theorem ext {A B : CostructuredArrow S T} (f g : A ⟶ B) (h : f.left = g.left) : f = g := CommaMorphism.ext h (Subsingleton.elim _ _) @@ -549,14 +529,10 @@ theorem eq_mk (f : CostructuredArrow S T) : f = mk f.hom := rfl /-- Eta rule for costructured arrows. -/ -@[simps!] +@[simps! hom_left inv_left] def eta (f : CostructuredArrow S T) : f ≅ mk f.hom := isoMk (Iso.refl _) -/- Porting note: it appears the simp lemma is not getting generated but the linter -picks up on it. Either way simp solves these. -/ -attribute [-simp, nolint simpNF] eta_hom_right_down_down eta_inv_right_down_down - lemma mk_surjective (f : CostructuredArrow S T) : ∃ (Y : C) (g : S.obj Y ⟶ T), f = mk g := ⟨_, _, eq_mk f⟩ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean index fdf4259edc924..20e34c229d380 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean @@ -63,6 +63,8 @@ inductive WalkingParallelPair : Type open WalkingParallelPair +-- Don't generate unnecessary `sizeOf_spec` lemma which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- The type family of morphisms for the diagram indexing a (co)equalizer. -/ inductive WalkingParallelPairHom : WalkingParallelPair → WalkingParallelPair → Type | left : WalkingParallelPairHom zero one @@ -70,10 +72,6 @@ inductive WalkingParallelPairHom : WalkingParallelPair → WalkingParallelPair | id (X : WalkingParallelPair) : WalkingParallelPairHom X X deriving DecidableEq -/- Porting note: this simplifies using walkingParallelPairHom_id; replacement is below; -simpNF still complains of striking this from the simp list -/ -attribute [-simp, nolint simpNF] WalkingParallelPairHom.id.sizeOf_spec - /-- Satisfying the inhabited linter -/ instance : Inhabited (WalkingParallelPairHom zero one) where default := WalkingParallelPairHom.left @@ -114,11 +112,6 @@ instance walkingParallelPairHomCategory : SmallCategory WalkingParallelPair wher theorem walkingParallelPairHom_id (X : WalkingParallelPair) : WalkingParallelPairHom.id X = 𝟙 X := rfl --- Porting note: simpNF asked me to do this because the LHS of the non-primed version reduced -@[simp] -theorem WalkingParallelPairHom.id.sizeOf_spec' (X : WalkingParallelPair) : - (WalkingParallelPairHom._sizeOf_inst X X).sizeOf (𝟙 X) = 1 + sizeOf X := by cases X <;> rfl - /-- The functor `WalkingParallelPair ⥤ WalkingParallelPairᵒᵖ` sending left to left and right to right. -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean index f11792f5eaace..ee9cbe4d2297c 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean @@ -601,6 +601,8 @@ end section HasImageMap +-- Don't generate unnecessary injectivity lemmas which the `simpNF` linter will complain about. +set_option genInjectivity false in /-- An image map is a morphism `image f → image g` fitting into a commutative square and satisfying the obvious commutativity conditions. -/ structure ImageMap {f g : Arrow C} [HasImage f.hom] [HasImage g.hom] (sq : f ⟶ g) where @@ -609,9 +611,6 @@ structure ImageMap {f g : Arrow C} [HasImage f.hom] [HasImage g.hom] (sq : f ⟶ attribute [inherit_doc ImageMap] ImageMap.map ImageMap.map_ι --- Porting note: LHS of this simplifies, simpNF still complains after blacklisting -attribute [-simp, nolint simpNF] ImageMap.mk.injEq - instance inhabitedImageMap {f : Arrow C} [HasImage f.hom] : Inhabited (ImageMap (𝟙 f)) := ⟨⟨𝟙 _, by simp⟩⟩ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean b/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean index 2741ad205d91e..f73849f24a405 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Multiequalizer.lean @@ -52,16 +52,14 @@ variable {L : Type w} {R : Type w'} {fst snd : R → L} instance [Inhabited L] : Inhabited (WalkingMulticospan fst snd) := ⟨left default⟩ +-- Don't generate unnecessary `sizeOf_spec` lemma which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- Morphisms for `WalkingMulticospan`. -/ inductive Hom : ∀ _ _ : WalkingMulticospan fst snd, Type max w w' | id (A) : Hom A A | fst (b) : Hom (left (fst b)) (right b) | snd (b) : Hom (left (snd b)) (right b) -/- Porting note: simpNF says the LHS of this internal identifier simplifies -(which it does, using Hom.id_eq_id) -/ -attribute [-simp, nolint simpNF] WalkingMulticospan.Hom.id.sizeOf_spec - instance {a : WalkingMulticospan fst snd} : Inhabited (Hom a a) := ⟨Hom.id _⟩ @@ -99,16 +97,14 @@ variable {L : Type w} {R : Type w'} {fst snd : L → R} instance [Inhabited L] : Inhabited (WalkingMultispan fst snd) := ⟨left default⟩ +-- Don't generate unnecessary `sizeOf_spec` lemma which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- Morphisms for `WalkingMultispan`. -/ inductive Hom : ∀ _ _ : WalkingMultispan fst snd, Type max w w' | id (A) : Hom A A | fst (a) : Hom (left a) (right (fst a)) | snd (a) : Hom (left a) (right (snd a)) -/- Porting note: simpNF says the LHS of this internal identifier simplifies -(which it does, using Hom.id_eq_id) -/ -attribute [-simp, nolint simpNF] WalkingMultispan.Hom.id.sizeOf_spec - instance {a : WalkingMultispan fst snd} : Inhabited (Hom a a) := ⟨Hom.id _⟩ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Reflexive.lean b/Mathlib/CategoryTheory/Limits/Shapes/Reflexive.lean index d1c5d29b44ebf..9287d4c3696b8 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Reflexive.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Reflexive.lean @@ -189,6 +189,8 @@ open WalkingReflexivePair namespace WalkingReflexivePair +-- Don't generate unnecessary `sizeOf_spec` lemma which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- The type of morphisms for the diagram indexing reflexive (co)equalizers -/ inductive Hom : (WalkingReflexivePair → WalkingReflexivePair → Type) | left : Hom one zero @@ -199,10 +201,6 @@ inductive Hom : (WalkingReflexivePair → WalkingReflexivePair → Type) | id (X : WalkingReflexivePair) : Hom X X deriving DecidableEq -attribute [-simp, nolint simpNF] Hom.id.sizeOf_spec -attribute [-simp, nolint simpNF] Hom.leftCompReflexion.sizeOf_spec -attribute [-simp, nolint simpNF] Hom.rightCompReflexion.sizeOf_spec - /-- Composition of morphisms in the diagram indexing reflexive (co)equalizers -/ def Hom.comp : ∀ { X Y Z : WalkingReflexivePair } (_ : Hom X Y) diff --git a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean index e8a53e2075d20..0e246bf283173 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean @@ -68,6 +68,8 @@ instance : DecidableEq (WalkingParallelFamily J) instance : Inhabited (WalkingParallelFamily J) := ⟨zero⟩ +-- Don't generate unnecessary `sizeOf_spec` lemma which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- The type family of morphisms for the diagram indexing a wide (co)equalizer. -/ inductive WalkingParallelFamily.Hom (J : Type w) : WalkingParallelFamily J → WalkingParallelFamily J → Type w @@ -680,5 +682,3 @@ instance (priority := 10) hasCoequalizers_of_hasWideCoequalizers [HasWideCoequal hasColimitsOfShape_of_equivalence.{w} walkingParallelFamilyEquivWalkingParallelPair end CategoryTheory.Limits - -attribute [nolint simpNF] CategoryTheory.Limits.WalkingParallelFamily.Hom.id.sizeOf_spec diff --git a/Mathlib/CategoryTheory/Limits/Shapes/WidePullbacks.lean b/Mathlib/CategoryTheory/Limits/Shapes/WidePullbacks.lean index 06d17c50c7d91..13aac3489474c 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/WidePullbacks.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/WidePullbacks.lean @@ -49,6 +49,8 @@ namespace WidePullbackShape variable {J} +-- Don't generate unnecessary `sizeOf_spec` lemma which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- The type of arrows for the shape indexing a wide pullback. -/ inductive Hom : WidePullbackShape J → WidePullbackShape J → Type w | id : ∀ X, Hom X X @@ -97,11 +99,6 @@ instance category : SmallCategory (WidePullbackShape J) := theorem hom_id (X : WidePullbackShape J) : Hom.id X = 𝟙 X := rfl -/- Porting note: we get a warning that we should change LHS to `sizeOf (𝟙 X)` but Lean cannot -find the category instance on `WidePullbackShape J` in that case. Once supplied in the proof, -the proposed proof of `simp [only WidePullbackShape.hom_id]` does not work -/ -attribute [nolint simpNF] Hom.id.sizeOf_spec - variable {C : Type u} [Category.{v} C] /-- Construct a functor out of the wide pullback shape given a J-indexed collection of arrows to a @@ -153,6 +150,8 @@ namespace WidePushoutShape variable {J} +-- Don't generate unnecessary `sizeOf_spec` lemma which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- The type of arrows for the shape indexing a wide pushout. -/ inductive Hom : WidePushoutShape J → WidePushoutShape J → Type w | id : ∀ X, Hom X X @@ -198,10 +197,6 @@ instance category : SmallCategory (WidePushoutShape J) := theorem hom_id (X : WidePushoutShape J) : Hom.id X = 𝟙 X := rfl -/- Porting note: we get a warning that we should change LHS to `sizeOf (𝟙 X)` but Lean cannot -find the category instance on `WidePushoutShape J` in that case. Once supplied in the proof, -the proposed proof of `simp [only WidePushoutShape.hom_id]` does not work -/ -attribute [nolint simpNF] Hom.id.sizeOf_spec variable {C : Type u} [Category.{v} C] /-- Construct a functor out of the wide pushout shape given a J-indexed collection of arrows from a @@ -359,13 +354,10 @@ noncomputable abbrev ι (j : J) : objs j ⟶ widePushout _ _ arrows := noncomputable abbrev head : B ⟶ widePushout B objs arrows := colimit.ι (WidePushoutShape.wideSpan _ _ _) Option.none -@[reassoc (attr := simp)] +@[reassoc, simp] theorem arrow_ι (j : J) : arrows j ≫ ι arrows j = head arrows := by apply colimit.w (WidePushoutShape.wideSpan _ _ _) (WidePushoutShape.Hom.init j) --- Porting note: this can simplify itself -attribute [nolint simpNF] WidePushout.arrow_ι WidePushout.arrow_ι_assoc - variable {arrows} /-- Descend a collection of morphisms to a morphism from the pushout. -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean index 8b225b7e7ee7d..5239662237b56 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean @@ -420,7 +420,6 @@ variable [HasZeroMorphisms C] /-- A zero morphism `0 : X ⟶ Y` is an isomorphism if and only if the identities on both `X` and `Y` are zero. -/ -@[simps] def isIsoZeroEquiv (X Y : C) : IsIso (0 : X ⟶ Y) ≃ 𝟙 X = 0 ∧ 𝟙 Y = 0 where toFun := by intro i @@ -431,9 +430,6 @@ def isIsoZeroEquiv (X Y : C) : IsIso (0 : X ⟶ Y) ≃ 𝟙 X = 0 ∧ 𝟙 Y = 0 left_inv := by aesop_cat right_inv := by aesop_cat --- Porting note: simp solves these -attribute [-simp, nolint simpNF] isIsoZeroEquiv_apply isIsoZeroEquiv_symm_apply - /-- A zero morphism `0 : X ⟶ X` is an isomorphism if and only if the identity on `X` is zero. -/ diff --git a/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean index 1b447182a254b..94bea212340b0 100644 --- a/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Free/Basic.lean @@ -35,6 +35,10 @@ section variable (C) +-- Don't generate unnecessary `sizeOf_spec` or `injEq` lemmas +-- which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in +set_option genInjectivity false in /-- Given a type `C`, the free monoidal category over `C` has as objects formal expressions built from (formal) tensor products of terms of `C` and a formal unit. Its morphisms are compositions and @@ -52,8 +56,6 @@ local notation "F" => FreeMonoidalCategory namespace FreeMonoidalCategory -attribute [nolint simpNF] unit.sizeOf_spec tensor.injEq tensor.sizeOf_spec - /-- Formal compositions and tensor products of identities, unitors and associators. The morphisms of the free monoidal category are obtained as a quotient of these formal morphisms by the relations defining a monoidal category. -/ diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean index beedbdb8d0a67..82e861ee09f3f 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean @@ -48,7 +48,7 @@ def preadditiveYonedaObj (Y : C) : Cᵒᵖ ⥤ ModuleCat.{v} (End Y) where object `X` to the group of morphisms `X ⟶ Y`. At each point, we get an additional `End Y`-module structure, see `preadditiveYonedaObj`. -/ -@[simps] +@[simps obj] def preadditiveYoneda : C ⥤ Cᵒᵖ ⥤ AddCommGrp.{v} where obj Y := preadditiveYonedaObj Y ⋙ forget₂ _ _ map f := @@ -75,7 +75,7 @@ def preadditiveCoyonedaObj (X : Cᵒᵖ) : C ⥤ ModuleCat.{v} (End X) where object `Y` to the group of morphisms `X ⟶ Y`. At each point, we get an additional `End X`-module structure, see `preadditiveCoyonedaObj`. -/ -@[simps] +@[simps obj] def preadditiveCoyoneda : Cᵒᵖ ⥤ C ⥤ AddCommGrp.{v} where obj X := preadditiveCoyonedaObj X ⋙ forget₂ _ _ map f := @@ -88,10 +88,6 @@ def preadditiveCoyoneda : Cᵒᵖ ⥤ C ⥤ AddCommGrp.{v} where map_id _ := by ext; dsimp; simp map_comp f g := by ext; dsimp; simp --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] CategoryTheory.preadditiveYoneda_map_app_apply - CategoryTheory.preadditiveCoyoneda_map_app_apply - instance additive_yonedaObj (X : C) : Functor.Additive (preadditiveYonedaObj X) where instance additive_yonedaObj' (X : C) : Functor.Additive (preadditiveYoneda.obj X) where diff --git a/Mathlib/CategoryTheory/Sites/Sheaf.lean b/Mathlib/CategoryTheory/Sites/Sheaf.lean index 6f528a0d3f6a1..9b7c318a4906a 100644 --- a/Mathlib/CategoryTheory/Sites/Sheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Sheaf.lean @@ -92,7 +92,6 @@ variable (P : Cᵒᵖ ⥤ A) {X : C} (S : Sieve X) (R : Presieve X) (E : Aᵒᵖ the cones over the natural diagram `S.arrows.diagram.op ⋙ P` associated to `S` and `P` with cone point `E` are in 1-1 correspondence with sieve_compatible family of elements for the sieve `S` and the presheaf of types `Hom (E, P -)`. -/ -@[simps] def conesEquivSieveCompatibleFamily : (S.arrows.diagram.op ⋙ P).cones.obj E ≃ { x : FamilyOfElements (P ⋙ coyoneda.obj E) (S : Presieve X) // x.SieveCompatible } where @@ -112,10 +111,6 @@ def conesEquivSieveCompatibleFamily : left_inv _ := rfl right_inv _ := rfl --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] CategoryTheory.Presheaf.conesEquivSieveCompatibleFamily_apply_coe - CategoryTheory.Presheaf.conesEquivSieveCompatibleFamily_symm_apply_app - variable {P S E} variable {x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows} (hx : SieveCompatible x) diff --git a/Mathlib/CategoryTheory/Subobject/Comma.lean b/Mathlib/CategoryTheory/Subobject/Comma.lean index 31c43bb091ef1..0c552180fb4a3 100644 --- a/Mathlib/CategoryTheory/Subobject/Comma.lean +++ b/Mathlib/CategoryTheory/Subobject/Comma.lean @@ -93,7 +93,6 @@ theorem lift_projectSubobject [HasFiniteLimits C] [PreservesFiniteLimits T] /-- If `A : S → T.obj B` is a structured arrow for `S : D` and `T : C ⥤ D`, then we can explicitly describe the subobjects of `A` as the subobjects `P` of `B` in `C` for which `A.hom` factors through the image of `P` under `T`. -/ -@[simps!] def subobjectEquiv [HasFiniteLimits C] [PreservesFiniteLimits T] (A : StructuredArrow S T) : Subobject A ≃o { P : Subobject A.right // ∃ q, q ≫ T.map P.arrow = A.hom } where toFun P := ⟨projectSubobject P, projectSubobject_factors P⟩ @@ -111,10 +110,6 @@ def subobjectEquiv [HasFiniteLimits C] [PreservesFiniteLimits T] (A : Structured · refine Subobject.mk_le_mk_of_comm (Subobject.ofMkLEMk _ _ h).right ?_ exact congr_arg CommaMorphism.right (Subobject.ofMkLEMk_comp h) --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] CategoryTheory.StructuredArrow.subobjectEquiv_symm_apply - CategoryTheory.StructuredArrow.subobjectEquiv_apply_coe - /-- If `C` is well-powered and complete and `T` preserves limits, then `StructuredArrow S T` is well-powered. -/ instance wellPowered_structuredArrow [LocallySmall.{w} C] diff --git a/Mathlib/Data/DFinsupp/BigOperators.lean b/Mathlib/Data/DFinsupp/BigOperators.lean index 20adad039c4ac..32fe109404721 100644 --- a/Mathlib/Data/DFinsupp/BigOperators.lean +++ b/Mathlib/Data/DFinsupp/BigOperators.lean @@ -307,7 +307,6 @@ def liftAddHom [∀ i, AddZeroClass (β i)] [AddCommMonoid γ] : -- This applies to roughly the remainder of the file. /-- The `DFinsupp` version of `Finsupp.liftAddHom_singleAddHom`,-/ -@[simp, nolint simpNF] -- simpNF correctly complains that the LHS simplifies already theorem liftAddHom_singleAddHom [∀ i, AddCommMonoid (β i)] : liftAddHom (β := β) (singleAddHom β) = AddMonoidHom.id (Π₀ i, β i) := (liftAddHom (β := β)).toEquiv.apply_eq_iff_eq_symm_apply.2 rfl diff --git a/Mathlib/Data/DFinsupp/Defs.lean b/Mathlib/Data/DFinsupp/Defs.lean index a8b854e30a101..1715e3d3fb437 100644 --- a/Mathlib/Data/DFinsupp/Defs.lean +++ b/Mathlib/Data/DFinsupp/Defs.lean @@ -988,7 +988,7 @@ theorem subtypeDomain_def (f : Π₀ i, β i) : f.subtypeDomain p = mk (f.support.subtype p) fun i => f i := by ext i; by_cases h2 : f i ≠ 0 <;> try simp at h2; dsimp; simp [h2] -@[simp, nolint simpNF] -- Porting note: simpNF claims that LHS does not simplify, but it does +@[simp] theorem support_subtypeDomain {f : Π₀ i, β i} : (subtypeDomain p f).support = f.support.subtype p := by ext i diff --git a/Mathlib/Data/Fin/Tuple/Basic.lean b/Mathlib/Data/Fin/Tuple/Basic.lean index fce4d009cd9ff..0d867dd8a49e8 100644 --- a/Mathlib/Data/Fin/Tuple/Basic.lean +++ b/Mathlib/Data/Fin/Tuple/Basic.lean @@ -165,7 +165,7 @@ theorem update_cons_zero : update (cons x p) 0 z = cons z p := by rw [← this, cons_succ, cons_succ] /-- Concatenating the first element of a tuple with its tail gives back the original tuple -/ -@[simp, nolint simpNF] -- Porting note: linter claims LHS doesn't simplify +@[simp] theorem cons_self_tail : cons (q 0) (tail q) = q := by ext j by_cases h : j = 0 diff --git a/Mathlib/Data/Finset/Lattice/Fold.lean b/Mathlib/Data/Finset/Lattice/Fold.lean index ff436a9d458d3..0a04809d8a4e6 100644 --- a/Mathlib/Data/Finset/Lattice/Fold.lean +++ b/Mathlib/Data/Finset/Lattice/Fold.lean @@ -143,7 +143,7 @@ protected theorem sup_comm (s : Finset β) (t : Finset γ) (f : β → γ → α (s.sup fun b => t.sup (f b)) = t.sup fun c => s.sup fun b => f b c := eq_of_forall_ge_iff fun a => by simpa using forall₂_swap -@[simp, nolint simpNF] -- Porting note: linter claims that LHS does not simplify +@[simp] theorem sup_attach (s : Finset β) (f : β → α) : (s.attach.sup fun x => f x) = s.sup f := (s.attach.sup_map (Function.Embedding.subtype _) f).symm.trans <| congr_arg _ attach_map_val diff --git a/Mathlib/Data/Finset/Sups.lean b/Mathlib/Data/Finset/Sups.lean index 04324a2636c5c..f627f7e9a839c 100644 --- a/Mathlib/Data/Finset/Sups.lean +++ b/Mathlib/Data/Finset/Sups.lean @@ -169,7 +169,6 @@ lemma biUnion_image_sup_left : s.biUnion (fun a ↦ t.image (a ⊔ ·)) = s ⊻ lemma biUnion_image_sup_right : t.biUnion (fun b ↦ s.image (· ⊔ b)) = s ⊻ t := biUnion_image_right --- Porting note: simpNF linter doesn't like @[simp] theorem image_sup_product (s t : Finset α) : (s ×ˢ t).image (uncurry (· ⊔ ·)) = s ⊻ t := image_uncurry_product _ _ _ @@ -314,7 +313,6 @@ lemma biUnion_image_inf_left : s.biUnion (fun a ↦ t.image (a ⊓ ·)) = s ⊼ lemma biUnion_image_inf_right : t.biUnion (fun b ↦ s.image (· ⊓ b)) = s ⊼ t := biUnion_image_right --- Porting note: simpNF linter doesn't like @[simp] theorem image_inf_product (s t : Finset α) : (s ×ˢ t).image (uncurry (· ⊓ ·)) = s ⊼ t := image_uncurry_product _ _ _ diff --git a/Mathlib/Data/Finset/Sym.lean b/Mathlib/Data/Finset/Sym.lean index 29ac2bd2208d5..9f35d53d8cc67 100644 --- a/Mathlib/Data/Finset/Sym.lean +++ b/Mathlib/Data/Finset/Sym.lean @@ -156,8 +156,6 @@ section Sym2 variable {m : Sym2 α} --- Porting note: add this lemma and remove simp in the next lemma since simpNF lint --- warns that its LHS is not in normal form @[simp] theorem diag_mem_sym2_mem_iff : (∀ b, b ∈ Sym2.diag a → b ∈ s) ↔ a ∈ s := by rw [← mem_sym2_iff] diff --git a/Mathlib/Data/Finset/Union.lean b/Mathlib/Data/Finset/Union.lean index 42efbe5a93ae2..c3312418518bf 100644 --- a/Mathlib/Data/Finset/Union.lean +++ b/Mathlib/Data/Finset/Union.lean @@ -87,8 +87,7 @@ private lemma pairwiseDisjoint_fibers : Set.PairwiseDisjoint ↑t fun a ↦ s.fi fun x' hx y' hy hne ↦ by simp_rw [disjoint_left, mem_filter]; rintro i ⟨_, rfl⟩ ⟨_, rfl⟩; exact hne rfl --- `simpNF` claims that the statement can't simplify itself, but it can (as of 2024-02-14) -@[simp, nolint simpNF] lemma disjiUnion_filter_eq (s : Finset α) (t : Finset β) (f : α → β) : +@[simp] lemma disjiUnion_filter_eq (s : Finset α) (t : Finset β) (f : α → β) : t.disjiUnion (fun a ↦ s.filter (f · = a)) pairwiseDisjoint_fibers = s.filter fun c ↦ f c ∈ t := ext fun b => by simpa using and_comm diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index 1ce490ed52759..6abe2e3b9c254 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -1213,7 +1213,7 @@ section variable [Zero M] [MonoidWithZero R] [MulActionWithZero R M] -@[simp, nolint simpNF] -- `simpNF` incorrectly complains the LHS doesn't simplify. +@[simp] theorem single_smul (a b : α) (f : α → M) (r : R) : single a r b • f a = single a (r • f b) b := by by_cases h : a = b <;> simp [h] diff --git a/Mathlib/Data/Finsupp/ToDFinsupp.lean b/Mathlib/Data/Finsupp/ToDFinsupp.lean index 3776ed103ea6c..5174a0b7e5313 100644 --- a/Mathlib/Data/Finsupp/ToDFinsupp.lean +++ b/Mathlib/Data/Finsupp/ToDFinsupp.lean @@ -220,8 +220,6 @@ variable (R) /-- The additive version of `Finsupp.toFinsupp`. Note that this is `noncomputable` because `Finsupp.add` is noncomputable. -/ --- Porting note: `simps` generated lemmas that did not pass `simpNF` lints, manually added below ---@[simps? (config := .asFn)] def finsuppLequivDFinsupp [DecidableEq ι] [Semiring R] [AddCommMonoid M] [∀ m : M, Decidable (m ≠ 0)] [Module R M] : (ι →₀ M) ≃ₗ[R] Π₀ _ : ι, M := { finsuppEquivDFinsupp with @@ -230,7 +228,6 @@ def finsuppLequivDFinsupp [DecidableEq ι] [Semiring R] [AddCommMonoid M] map_smul' := Finsupp.toDFinsupp_smul map_add' := Finsupp.toDFinsupp_add } --- Porting note: `simps` generated as `↑(finsuppLequivDFinsupp R).toLinearMap = Finsupp.toDFinsupp` @[simp] theorem finsuppLequivDFinsupp_apply_apply [DecidableEq ι] [Semiring R] [AddCommMonoid M] [∀ m : M, Decidable (m ≠ 0)] [Module R M] : diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 72a87d4cdaa72..27e8037124589 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -1618,12 +1618,7 @@ theorem length_eq_length_filter_add {l : List (α)} (f : α → Bool) : /-! ### filterMap -/ --- Later porting note (at time of this lemma moving to Batteries): --- removing attribute `nolint simpNF` attribute [simp 1100] filterMap_cons_none - --- Later porting note (at time of this lemma moving to Batteries): --- removing attribute `nolint simpNF` attribute [simp 1100] filterMap_cons_some theorem filterMap_eq_flatMap_toList (f : α → Option β) (l : List α) : diff --git a/Mathlib/Data/Matrix/DMatrix.lean b/Mathlib/Data/Matrix/DMatrix.lean index cf00fbd771964..94cc3254c7718 100644 --- a/Mathlib/Data/Matrix/DMatrix.lean +++ b/Mathlib/Data/Matrix/DMatrix.lean @@ -105,12 +105,7 @@ instance [∀ i j, Unique (α i j)] : Unique (DMatrix m n α) := instance [∀ i j, Subsingleton (α i j)] : Subsingleton (DMatrix m n α) := inferInstanceAs <| Subsingleton <| ∀ i j, α i j -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4481 -the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. --/ -@[simp, nolint simpNF] +@[simp] theorem zero_apply [∀ i j, Zero (α i j)] (i j) : (0 : DMatrix m n α) i j = 0 := rfl @[simp] diff --git a/Mathlib/Data/Matrix/Defs.lean b/Mathlib/Data/Matrix/Defs.lean index cee907c0593df..fb49c651c7630 100644 --- a/Mathlib/Data/Matrix/Defs.lean +++ b/Mathlib/Data/Matrix/Defs.lean @@ -212,12 +212,7 @@ instance module [Semiring R] [AddCommMonoid α] [Module R α] : Module R (Matrix section -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4481 -the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. --/ -@[simp, nolint simpNF] +@[simp] theorem zero_apply [Zero α] (i : m) (j : n) : (0 : Matrix m n α) i j = 0 := rfl @[simp] diff --git a/Mathlib/Data/Matrix/Diagonal.lean b/Mathlib/Data/Matrix/Diagonal.lean index 3f6042398a5d2..8eb3bcd89d1df 100644 --- a/Mathlib/Data/Matrix/Diagonal.lean +++ b/Mathlib/Data/Matrix/Diagonal.lean @@ -225,12 +225,9 @@ end Diagonal section Diag /-- The diagonal of a square matrix. -/ --- @[simp] -- Porting note: simpNF does not like this. def diag (A : Matrix n n α) (i : n) : α := A i i --- Porting note: new, because of removed `simp` above. --- TODO: set as an equation lemma for `diag`, see https://github.com/leanprover-community/mathlib4/pull/3024 @[simp] theorem diag_apply (A : Matrix n n α) (i) : diag A i = A i i := rfl diff --git a/Mathlib/Data/Matrix/Mul.lean b/Mathlib/Data/Matrix/Mul.lean index 4f7140b712651..92ba31f826ae7 100644 --- a/Mathlib/Data/Matrix/Mul.lean +++ b/Mathlib/Data/Matrix/Mul.lean @@ -731,14 +731,12 @@ theorem single_one_vecMul [Fintype m] [DecidableEq m] [NonAssocSemiring R] (i : m) (M : Matrix m n R) : Pi.single i 1 ᵥ* M = M i := by simp --- @[simp] -- Porting note: not in simpNF theorem diagonal_mulVec_single [Fintype n] [DecidableEq n] [NonUnitalNonAssocSemiring R] (v : n → R) (j : n) (x : R) : diagonal v *ᵥ Pi.single j x = Pi.single j (v j * x) := by ext i rw [mulVec_diagonal] exact Pi.apply_single (fun i x => v i * x) (fun i => mul_zero _) j x i --- @[simp] -- Porting note: not in simpNF theorem single_vecMul_diagonal [Fintype n] [DecidableEq n] [NonUnitalNonAssocSemiring R] (v : n → R) (j : n) (x : R) : (Pi.single j x) ᵥ* (diagonal v) = Pi.single j (x * v j) := by ext i diff --git a/Mathlib/Data/NNRat/Defs.lean b/Mathlib/Data/NNRat/Defs.lean index 19f0f15d8fa34..053a63b88459a 100644 --- a/Mathlib/Data/NNRat/Defs.lean +++ b/Mathlib/Data/NNRat/Defs.lean @@ -158,8 +158,7 @@ theorem coe_le_coe : (p : ℚ) ≤ q ↔ p ≤ q := theorem coe_lt_coe : (p : ℚ) < q ↔ p < q := Iff.rfl --- `cast_pos`, defined in a later file, makes this lemma redundant -@[simp, norm_cast, nolint simpNF] +@[norm_cast] theorem coe_pos : (0 : ℚ) < q ↔ 0 < q := Iff.rfl @@ -214,13 +213,11 @@ theorem bddAbove_coe {s : Set ℚ≥0} : BddAbove ((↑) '' s : Set ℚ) ↔ Bdd theorem bddBelow_coe (s : Set ℚ≥0) : BddBelow (((↑) : ℚ≥0 → ℚ) '' s) := ⟨0, fun _ ⟨q, _, h⟩ ↦ h ▸ q.2⟩ --- `cast_max`, defined in a later file, makes this lemma redundant -@[simp, norm_cast, nolint simpNF] +@[norm_cast] theorem coe_max (x y : ℚ≥0) : ((max x y : ℚ≥0) : ℚ) = max (x : ℚ) (y : ℚ) := coe_mono.map_max --- `cast_max`, defined in a later file, makes this lemma redundant -@[simp, norm_cast, nolint simpNF] +@[norm_cast] theorem coe_min (x y : ℚ≥0) : ((min x y : ℚ≥0) : ℚ) = min (x : ℚ) (y : ℚ) := coe_mono.map_min diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index a0711752d0b0d..138d503bcedad 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -1335,7 +1335,6 @@ theorem piecewise_univ [∀ i : α, Decidable (i ∈ (Set.univ : Set α))] : ext i simp [piecewise] ---@[simp] -- Porting note: simpNF linter complains theorem piecewise_insert_self {j : α} [∀ i, Decidable (i ∈ insert j s)] : (insert j s).piecewise f g j = f j := by simp [piecewise] diff --git a/Mathlib/Data/Set/MulAntidiagonal.lean b/Mathlib/Data/Set/MulAntidiagonal.lean index 8bddb878d7cc2..bad4cd3613dbe 100644 --- a/Mathlib/Data/Set/MulAntidiagonal.lean +++ b/Mathlib/Data/Set/MulAntidiagonal.lean @@ -38,7 +38,7 @@ theorem mulAntidiagonal_mono_right (h : t₁ ⊆ t₂) : end Mul --- Porting note: Removed simp attribute, simpnf linter can simplify lhs. Added aux version below +-- The left hand side is not in simp normal form, see variant below. @[to_additive] theorem swap_mem_mulAntidiagonal [CommSemigroup α] {s t : Set α} {a : α} {x : α × α} : x.swap ∈ Set.mulAntidiagonal s t a ↔ x ∈ Set.mulAntidiagonal t s a := by diff --git a/Mathlib/Data/SetLike/Basic.lean b/Mathlib/Data/SetLike/Basic.lean index fb74683ca034a..44719c1ca0a00 100644 --- a/Mathlib/Data/SetLike/Basic.lean +++ b/Mathlib/Data/SetLike/Basic.lean @@ -181,7 +181,7 @@ theorem coe_mem (x : p) : (x : B) ∈ p := @[aesop 5% apply (rule_sets := [SetLike])] lemma mem_of_subset {s : Set B} (hp : s ⊆ p) {x : B} (hx : x ∈ s) : x ∈ p := hp hx --- Porting note: removed `@[simp]` because `simpNF` linter complained +@[simp] protected theorem eta (x : p) (hx : (x : B) ∈ p) : (⟨x, hx⟩ : p) = x := rfl @[simp] lemma setOf_mem_eq (a : A) : {b | b ∈ a} = a := rfl diff --git a/Mathlib/Data/Setoid/Partition.lean b/Mathlib/Data/Setoid/Partition.lean index c0909554e4007..7539329317c93 100644 --- a/Mathlib/Data/Setoid/Partition.lean +++ b/Mathlib/Data/Setoid/Partition.lean @@ -336,8 +336,7 @@ instance [Unique ι] [Inhabited α] : Inhabited (IndexedPartition fun _i : ι => index := default mem_index := Set.mem_univ }⟩ --- Porting note: `simpNF` complains about `mem_index` -attribute [simp] some_mem --mem_index +attribute [simp] some_mem variable (hs : IndexedPartition s) diff --git a/Mathlib/Data/Sigma/Basic.lean b/Mathlib/Data/Sigma/Basic.lean index 888d19b2ed8d8..e9e037d20b88d 100644 --- a/Mathlib/Data/Sigma/Basic.lean +++ b/Mathlib/Data/Sigma/Basic.lean @@ -51,7 +51,7 @@ instance instDecidableEqSigma [h₁ : DecidableEq α] [h₂ : ∀ a, DecidableEq | _, _, _, _, isFalse n => isFalse fun h ↦ Sigma.noConfusion h fun e₁ _ ↦ n e₁ -- sometimes the built-in injectivity support does not work -@[simp] -- @[nolint simpNF] +@[simp] theorem mk.inj_iff {a₁ a₂ : α} {b₁ : β a₁} {b₂ : β a₂} : Sigma.mk a₁ b₁ = ⟨a₂, b₂⟩ ↔ a₁ = a₂ ∧ HEq b₁ b₂ := ⟨fun h ↦ by cases h; simp, diff --git a/Mathlib/Data/Sign.lean b/Mathlib/Data/Sign.lean index b9ca1bae2f936..4607e88ca0d3e 100644 --- a/Mathlib/Data/Sign.lean +++ b/Mathlib/Data/Sign.lean @@ -16,6 +16,8 @@ This file defines the sign function for types with zero and a decidable less-tha proves some basic theorems about it. -/ +-- Don't generate unnecessary `sizeOf_spec` lemmas which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in /-- The type of signs. -/ inductive SignType | zero @@ -23,12 +25,6 @@ inductive SignType | pos deriving DecidableEq, Inhabited, Fintype --- Porting note: these lemmas are autogenerated by the inductive definition and are not --- in simple form due to the below `x_eq_x` lemmas -attribute [nolint simpNF] SignType.zero.sizeOf_spec -attribute [nolint simpNF] SignType.neg.sizeOf_spec -attribute [nolint simpNF] SignType.pos.sizeOf_spec - namespace SignType instance : Zero SignType := diff --git a/Mathlib/Data/Subtype.lean b/Mathlib/Data/Subtype.lean index 79accfa97efb3..ea0164bca8d41 100644 --- a/Mathlib/Data/Subtype.lean +++ b/Mathlib/Data/Subtype.lean @@ -101,16 +101,12 @@ lemma coe_ne_coe {a b : Subtype p} : (a : α) ≠ b ↔ a ≠ b := coe_injective @[deprecated (since := "2024-04-04")] alias ⟨ne_of_val_ne, _⟩ := coe_ne_coe --- Porting note: it is unclear why the linter doesn't like this. --- If you understand why, please replace this comment with an explanation, or resolve. -@[simp, nolint simpNF] +@[simp] theorem _root_.exists_eq_subtype_mk_iff {a : Subtype p} {b : α} : (∃ h : p b, a = Subtype.mk b h) ↔ ↑a = b := coe_eq_iff.symm --- Porting note: it is unclear why the linter doesn't like this. --- If you understand why, please replace this comment with an explanation, or resolve. -@[simp, nolint simpNF] +@[simp] theorem _root_.exists_subtype_mk_eq_iff {a : Subtype p} {b : α} : (∃ h : p b, Subtype.mk b h = a) ↔ b = a := by simp only [@eq_comm _ b, exists_eq_subtype_mk_iff, @eq_comm _ _ a] diff --git a/Mathlib/FieldTheory/IntermediateField/Basic.lean b/Mathlib/FieldTheory/IntermediateField/Basic.lean index a80409efa5208..7f59bd51abc1d 100644 --- a/Mathlib/FieldTheory/IntermediateField/Basic.lean +++ b/Mathlib/FieldTheory/IntermediateField/Basic.lean @@ -460,16 +460,10 @@ between `E` and `E.map e` -/ def intermediateFieldMap (e : L ≃ₐ[K] L') (E : IntermediateField K L) : E ≃ₐ[K] E.map e.toAlgHom := e.subalgebraMap E.toSubalgebra -/- We manually add these two simp lemmas because `@[simps]` before `intermediate_field_map` - led to a timeout. -/ --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[simp, nolint simpNF] theorem intermediateFieldMap_apply_coe (e : L ≃ₐ[K] L') (E : IntermediateField K L) (a : E) : ↑(intermediateFieldMap e E a) = e a := rfl --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[simp, nolint simpNF] theorem intermediateFieldMap_symm_apply_coe (e : L ≃ₐ[K] L') (E : IntermediateField K L) (a : E.map e.toAlgHom) : ↑((intermediateFieldMap e E).symm a) = e.symm a := rfl diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index 2624f27c53751..12754362767ea 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -777,9 +777,8 @@ instance (H : Type*) [TopologicalSpace H] (H' : Type*) [TopologicalSpace H'] : TopologicalSpace (ModelProd H H') := instTopologicalSpaceProd --- Porting note: simpNF false positive --- Next lemma shows up often when dealing with derivatives, register it as simp. -@[simp, mfld_simps, nolint simpNF] +-- Next lemma shows up often when dealing with derivatives, so we register it as simp lemma. +@[simp, mfld_simps] theorem modelProd_range_prod_id {H : Type*} {H' : Type*} {α : Type*} (f : H → α) : (range fun p : ModelProd H H' ↦ (f p.1, p.2)) = range f ×ˢ (univ : Set H') := by rw [prod_range_univ_eq] diff --git a/Mathlib/GroupTheory/Complement.lean b/Mathlib/GroupTheory/Complement.lean index afafd4588a723..259e4a2312471 100644 --- a/Mathlib/GroupTheory/Complement.lean +++ b/Mathlib/GroupTheory/Complement.lean @@ -522,8 +522,6 @@ theorem equiv_fst_eq_one_of_mem_of_one_mem {g : G} (h1 : 1 ∈ S) (hg : g ∈ T) ext rw [equiv_fst_eq_mul_inv, equiv_snd_eq_self_of_mem_of_one_mem _ h1 hg, mul_inv_cancel] --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[simp, nolint simpNF] theorem equiv_mul_right (g : G) (k : K) : hSK.equiv (g * k) = ((hSK.equiv g).fst, (hSK.equiv g).snd * k) := by have : (hSK.equiv (g * k)).fst = (hSK.equiv g).fst := @@ -537,8 +535,6 @@ theorem equiv_mul_right_of_mem {g k : G} (h : k ∈ K) : hSK.equiv (g * k) = ((hSK.equiv g).fst, (hSK.equiv g).snd * ⟨k, h⟩) := equiv_mul_right _ g ⟨k, h⟩ --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[simp, nolint simpNF] theorem equiv_mul_left (h : H) (g : G) : hHT.equiv (h * g) = (h * (hHT.equiv g).fst, (hHT.equiv g).snd) := by have : (hHT.equiv (h * g)).2 = (hHT.equiv g).2 := hHT.equiv_snd_eq_iff_rightCosetEquivalence.2 ?_ diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index c89a47cd28aa4..a53461a680fb8 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -660,13 +660,11 @@ noncomputable def finEquivZPowers (x : G) (hx : IsOfFinOrder x) : Fin (orderOf x) ≃ (zpowers x : Set G) := (finEquivPowers x hx).trans <| Equiv.Set.ofEq hx.powers_eq_zpowers --- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[to_additive (attr := simp, nolint simpNF)] +@[to_additive] lemma finEquivZPowers_apply (hx) {n : Fin (orderOf x)} : finEquivZPowers x hx n = ⟨x ^ (n : ℕ), n, zpow_natCast x n⟩ := rfl - -- This lemma has always been bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644. -@[to_additive (attr := simp, nolint simpNF)] +@[to_additive] lemma finEquivZPowers_symm_apply (x : G) (hx) (n : ℕ) : (finEquivZPowers x hx).symm ⟨x ^ n, ⟨n, by simp⟩⟩ = ⟨n % orderOf x, Nat.mod_lt _ hx.orderOf_pos⟩ := by diff --git a/Mathlib/GroupTheory/SemidirectProduct.lean b/Mathlib/GroupTheory/SemidirectProduct.lean index a003d225cc7e2..99062dc001905 100644 --- a/Mathlib/GroupTheory/SemidirectProduct.lean +++ b/Mathlib/GroupTheory/SemidirectProduct.lean @@ -35,6 +35,9 @@ open Subgroup variable (N : Type*) (G : Type*) {H : Type*} [Group N] [Group G] [Group H] +-- Don't generate sizeOf and injectivity lemmas, which the `simpNF` linter will complain about. +set_option genSizeOfSpec false in +set_option genInjectivity false in /-- The semidirect product of groups `N` and `G`, given a map `φ` from `G` to the automorphism group of `N`. It the product of sets with the group operation `⟨n₁, g₁⟩ * ⟨n₂, g₂⟩ = ⟨n₁ * φ g₁ n₂, g₁ * g₂⟩` -/ @@ -46,11 +49,6 @@ structure SemidirectProduct (φ : G →* MulAut N) where right : G deriving DecidableEq --- Porting note: these lemmas are autogenerated by the inductive definition and are not --- in simple form due to the existence of mk_eq_inl_mul_inr -attribute [nolint simpNF] SemidirectProduct.mk.injEq -attribute [nolint simpNF] SemidirectProduct.mk.sizeOf_spec - -- Porting note: unknown attribute -- attribute [pp_using_anonymous_constructor] SemidirectProduct diff --git a/Mathlib/LinearAlgebra/Isomorphisms.lean b/Mathlib/LinearAlgebra/Isomorphisms.lean index b6bd8094f1851..b4156be52862b 100644 --- a/Mathlib/LinearAlgebra/Isomorphisms.lean +++ b/Mathlib/LinearAlgebra/Isomorphisms.lean @@ -100,8 +100,6 @@ theorem coe_quotientInfToSupQuotient (p p' : Submodule R M) : ⇑(quotientInfToSupQuotient p p') = quotientInfEquivSupQuotient p p' := rfl --- This lemma was always bad, but the linter only noticed after https://github.com/leanprover/lean4/pull/2644 -@[simp, nolint simpNF] theorem quotientInfEquivSupQuotient_apply_mk (p p' : Submodule R M) (x : p) : let map := inclusion (le_sup_left : p ≤ p ⊔ p') quotientInfEquivSupQuotient p p' (Submodule.Quotient.mk x) = diff --git a/Mathlib/LinearAlgebra/Matrix/ToLin.lean b/Mathlib/LinearAlgebra/Matrix/ToLin.lean index 942c5135c5ac8..1bce52c084cc2 100644 --- a/Mathlib/LinearAlgebra/Matrix/ToLin.lean +++ b/Mathlib/LinearAlgebra/Matrix/ToLin.lean @@ -469,9 +469,6 @@ theorem Matrix.toLinAlgEquiv'_apply (M : Matrix n n R) (v : n → R) : Matrix.toLinAlgEquiv' M v = M *ᵥ v := rfl --- Porting note: the simpNF linter rejects this, as `simp` already simplifies the lhs --- to `(1 : (n → R) →ₗ[R] n → R)`. --- @[simp] theorem Matrix.toLinAlgEquiv'_one : Matrix.toLinAlgEquiv' (1 : Matrix n n R) = LinearMap.id := Matrix.toLin'_one @@ -750,9 +747,6 @@ theorem Matrix.toLinAlgEquiv_self (M : Matrix n n R) (i : n) : theorem LinearMap.toMatrixAlgEquiv_id : LinearMap.toMatrixAlgEquiv v₁ id = 1 := by simp_rw [LinearMap.toMatrixAlgEquiv, AlgEquiv.ofLinearEquiv_apply, LinearMap.toMatrix_id] --- Porting note: the simpNF linter rejects this, as `simp` already simplifies the lhs --- to `(1 : M₁ →ₗ[R] M₁)`. --- @[simp] theorem Matrix.toLinAlgEquiv_one : Matrix.toLinAlgEquiv v₁ 1 = LinearMap.id := by rw [← LinearMap.toMatrixAlgEquiv_id v₁, Matrix.toLinAlgEquiv_toMatrixAlgEquiv] diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index a63088b6181d5..d8830d118642b 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -82,6 +82,8 @@ universe uR uS uι v v' v₁ v₂ v₃ variable {R : Type uR} {S : Type uS} {ι : Type uι} {n : ℕ} {M : Fin n.succ → Type v} {M₁ : ι → Type v₁} {M₂ : Type v₂} {M₃ : Type v₃} {M' : Type v'} +-- Don't generate injectivity lemmas, which the `simpNF` linter will time out on. +set_option genInjectivity false in /-- Multilinear maps over the ring `R`, from `∀ i, M₁ i` to `M₂` where `M₁ i` and `M₂` are modules over `R`. -/ structure MultilinearMap (R : Type uR) {ι : Type uι} (M₁ : ι → Type v₁) (M₂ : Type v₂) [Semiring R] @@ -97,9 +99,6 @@ structure MultilinearMap (R : Type uR) {ι : Type uι} (M₁ : ι → Type v₁) ∀ [DecidableEq ι] (m : ∀ i, M₁ i) (i : ι) (c : R) (x : M₁ i), toFun (update m i (c • x)) = c • toFun (update m i x) --- Porting note: added to avoid a linter timeout. -attribute [nolint simpNF] MultilinearMap.mk.injEq - namespace MultilinearMap section Semiring diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Prod.lean b/Mathlib/LinearAlgebra/QuadraticForm/Prod.lean index c9ef8e47cf38d..561f9f6950e0b 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Prod.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Prod.lean @@ -280,7 +280,7 @@ def Isometry.proj [Fintype ι] [DecidableEq ι] (i : ι) (Q : QuadraticMap R (M rw [Pi.single_eq_of_ne hij, zero_apply] /-- Note that `QuadraticMap.Isometry.id` would not be well-typed as the RHS. -/ -@[simp, nolint simpNF] -- ignore the bogus "Left-hand side does not simplify" lint error +@[simp] theorem Isometry.proj_comp_single_of_same [Fintype ι] [DecidableEq ι] (i : ι) (Q : QuadraticMap R (Mᵢ i) P) : (proj i Q).comp (single _ i) = .ofEq (Pi.single_eq_same _ _) := diff --git a/Mathlib/Logic/Unique.lean b/Mathlib/Logic/Unique.lean index e49b8327144ca..e2b92731ce5a2 100644 --- a/Mathlib/Logic/Unique.lean +++ b/Mathlib/Logic/Unique.lean @@ -41,6 +41,8 @@ for good definitional properties of the default term. universe u v w +-- Don't generate injectivity lemmas, which the `simpNF` linter will complain about. +set_option genInjectivity false in /-- `Unique α` expresses that `α` is a type with a unique term `default`. This is implemented as a type, rather than a `Prop`-valued predicate, @@ -51,8 +53,6 @@ structure Unique (α : Sort u) extends Inhabited α where uniq : ∀ a : α, a = default attribute [class] Unique --- The simplifier can already prove this using `eq_iff_true_of_subsingleton` -attribute [nolint simpNF] Unique.mk.injEq theorem unique_iff_existsUnique (α : Sort u) : Nonempty (Unique α) ↔ ∃! _ : α, True := ⟨fun ⟨u⟩ ↦ ⟨u.default, trivial, fun a _ ↦ u.uniq a⟩, @@ -84,11 +84,7 @@ instance PUnit.instUnique : Unique PUnit.{u} where default := PUnit.unit uniq x := subsingleton x _ --- Porting note: --- This should not require a nolint, --- but it is currently failing due to a problem in the linter discussed at --- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/.60simpNF.60.20error.20.22unknown.20metavariable.22 -@[simp, nolint simpNF] +@[simp] theorem PUnit.default_eq_unit : (default : PUnit) = PUnit.unit := rfl diff --git a/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean b/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean index babc5786d359e..847ad1bcd24bf 100644 --- a/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean +++ b/Mathlib/MeasureTheory/Measure/FiniteMeasure.lean @@ -209,7 +209,6 @@ instance instSMul : SMul R (FiniteMeasure Ω) where @[simp, norm_cast] theorem toMeasure_zero : ((↑) : FiniteMeasure Ω → Measure Ω) 0 = 0 := rfl --- Porting note: with `simp` here the `coeFn` lemmas below fall prey to `simpNF`: the LHS simplifies @[norm_cast] theorem toMeasure_add (μ ν : FiniteMeasure Ω) : ↑(μ + ν) = (↑μ + ↑ν : Measure Ω) := rfl diff --git a/Mathlib/NumberTheory/Divisors.lean b/Mathlib/NumberTheory/Divisors.lean index 0a26a00f55e98..4ef71ae103a18 100644 --- a/Mathlib/NumberTheory/Divisors.lean +++ b/Mathlib/NumberTheory/Divisors.lean @@ -240,17 +240,11 @@ theorem divisorsAntidiagonal_one : divisorsAntidiagonal 1 = {(1, 1)} := by ext simp [mul_eq_one, Prod.ext_iff] -/- Porting note: simpnf linter; added aux lemma below -Left-hand side simplifies from - Prod.swap x ∈ Nat.divisorsAntidiagonal n -to - x.snd * x.fst = n ∧ ¬n = 0-/ --- @[simp] +-- The left hand side is not in simp normal form, see the variant below. theorem swap_mem_divisorsAntidiagonal {x : ℕ × ℕ} : x.swap ∈ divisorsAntidiagonal n ↔ x ∈ divisorsAntidiagonal n := by rw [mem_divisorsAntidiagonal, mem_divisorsAntidiagonal, mul_comm, Prod.swap] --- Porting note: added below thm to replace the simp from the previous thm @[simp] theorem swap_mem_divisorsAntidiagonal_aux {x : ℕ × ℕ} : x.snd * x.fst = n ∧ ¬n = 0 ↔ x ∈ divisorsAntidiagonal n := by diff --git a/Mathlib/Order/Category/BddLat.lean b/Mathlib/Order/Category/BddLat.lean index 994a24252c635..531f0ef0124de 100644 --- a/Mathlib/Order/Category/BddLat.lean +++ b/Mathlib/Order/Category/BddLat.lean @@ -199,15 +199,6 @@ def latToBddLatForgetAdjunction : latToBddLat.{u} ⊣ forget₂ BddLat Lat := homEquiv_naturality_right := fun _ _ => LatticeHom.ext fun _ => rfl } /-- `latToBddLat` and `OrderDual` commute. -/ --- Porting note: the `simpNF` linter is not happy as it simplifies something that does not --- have prettyprinting effects. --- It seems like it is simplifying for example the first type --- `(↑(BddLat.dualEquiv.functor.obj (latToBddLat.obj X.op.unop)).toLat)` --- to --- `(↑(latToBddLat.obj X).toLat)ᵒᵈ` --- Interestingly, the linter is silent, if the proof is `sorry`-ed out... --- see https://github.com/leanprover-community/mathlib4/issues/5049 --- @[simps!] def latToBddLatCompDualIsoDualCompLatToBddLat : latToBddLat.{u} ⋙ BddLat.dual ≅ Lat.dual ⋙ latToBddLat := Adjunction.leftAdjointUniq (latToBddLatForgetAdjunction.comp BddLat.dualEquiv.toAdjunction) diff --git a/Mathlib/Order/Interval/Basic.lean b/Mathlib/Order/Interval/Basic.lean index 291d014cb4e11..e684d9af2792b 100644 --- a/Mathlib/Order/Interval/Basic.lean +++ b/Mathlib/Order/Interval/Basic.lean @@ -200,11 +200,11 @@ instance setLike : SetLike (NonemptyInterval α) α where coe s := Icc s.fst s.snd coe_injective' := coeHom.injective -@[norm_cast] -- @[simp, norm_cast] -- Porting note: not in simpNF +@[norm_cast] theorem coe_subset_coe : (s : Set α) ⊆ t ↔ (s : NonemptyInterval α) ≤ t := (@coeHom α _).le_iff_le -@[norm_cast] -- @[simp, norm_cast] -- Porting note: not in simpNF +@[norm_cast] theorem coe_ssubset_coe : (s : Set α) ⊂ t ↔ s < t := (@coeHom α _).lt_iff_lt @@ -292,7 +292,7 @@ def recBotCoe {C : Interval α → Sort*} (bot : C ⊥) (coe : ∀ a : NonemptyI theorem coe_injective : Injective ((↑) : NonemptyInterval α → Interval α) := WithBot.coe_injective -@[norm_cast] -- @[simp, norm_cast] -- Porting note: not in simpNF +@[norm_cast] theorem coe_inj {s t : NonemptyInterval α} : (s : Interval α) = t ↔ s = t := WithBot.coe_inj @@ -400,11 +400,11 @@ instance setLike : SetLike (Interval α) α where coe := coeHom coe_injective' := coeHom.injective -@[norm_cast] -- @[simp, norm_cast] -- Porting note: not in simpNF +@[norm_cast] theorem coe_subset_coe : (s : Set α) ⊆ t ↔ s ≤ t := (@coeHom α _).le_iff_le -@[norm_cast] -- @[simp, norm_cast] -- Porting note: not in simpNF +@[norm_cast] theorem coe_sSubset_coe : (s : Set α) ⊂ t ↔ s < t := (@coeHom α _).lt_iff_lt @@ -681,7 +681,6 @@ theorem coe_sInf [DecidableRel (α := α) (· ≤ ·)] (S : Set (Interval α)) : theorem coe_iInf [DecidableRel (α := α) (· ≤ ·)] (f : ι → Interval α) : ↑(⨅ i, f i) = ⋂ i, (f i : Set α) := by simp [iInf] --- @[simp] -- Porting note: not in simpNF @[norm_cast] theorem coe_iInf₂ [DecidableRel (α := α) (· ≤ ·)] (f : ∀ i, κ i → Interval α) : ↑(⨅ (i) (j), f i j) = ⋂ (i) (j), (f i j : Set α) := by simp_rw [coe_iInf] diff --git a/Mathlib/Topology/Algebra/Module/Star.lean b/Mathlib/Topology/Algebra/Module/Star.lean index 11d8032d76fb5..43a4ccb76dd08 100644 --- a/Mathlib/Topology/Algebra/Module/Star.lean +++ b/Mathlib/Topology/Algebra/Module/Star.lean @@ -65,16 +65,12 @@ theorem continuous_decomposeProdAdjoint_symm [TopologicalAddGroup A] : (continuous_subtype_val.comp continuous_fst).add (continuous_subtype_val.comp continuous_snd) /-- The self-adjoint part of an element of a star module, as a continuous linear map. -/ -@[simps!] +@[simps! -isSimp] def selfAdjointPartL [ContinuousAdd A] [ContinuousStar A] [ContinuousConstSMul R A] : A →L[R] selfAdjoint A where toLinearMap := selfAdjointPart R cont := continuous_selfAdjointPart _ _ --- This lemma is generated by `simps` but we don't actually want the `@[simp]` attribute. --- https://github.com/leanprover-community/mathlib4/issues/18942 -attribute [nolint simpNF] selfAdjointPartL_apply_coe - /-- The skew-adjoint part of an element of a star module, as a continuous linear map. -/ @[simps!] def skewAdjointPartL [ContinuousSub A] [ContinuousStar A] [ContinuousConstSMul R A] : diff --git a/Mathlib/Topology/Category/LightProfinite/Basic.lean b/Mathlib/Topology/Category/LightProfinite/Basic.lean index d294240517a43..7644318842d13 100644 --- a/Mathlib/Topology/Category/LightProfinite/Basic.lean +++ b/Mathlib/Topology/Category/LightProfinite/Basic.lean @@ -100,15 +100,11 @@ attribute [local instance] FintypeCat.discreteTopology /-- The natural functor from `Fintype` to `LightProfinite`, endowing a finite type with the discrete topology. -/ -@[simps! map_apply] +@[simps! -isSimp map_apply] def FintypeCat.toLightProfinite : FintypeCat ⥤ LightProfinite where obj A := LightProfinite.of A map f := ⟨f, by continuity⟩ --- This lemma is generated by `simps` but we don't actually want the `@[simp]` attribute. --- https://github.com/leanprover-community/mathlib4/issues/18942 -attribute [nolint simpNF] FintypeCat.toLightProfinite_map_apply - /-- `FintypeCat.toLightProfinite` is fully faithful. -/ def FintypeCat.toLightProfiniteFullyFaithful : toLightProfinite.FullyFaithful where preimage f := (f : _ → _) diff --git a/Mathlib/Topology/Category/Profinite/Basic.lean b/Mathlib/Topology/Category/Profinite/Basic.lean index fe5f7d2a47ee4..9bbf16eba695d 100644 --- a/Mathlib/Topology/Category/Profinite/Basic.lean +++ b/Mathlib/Topology/Category/Profinite/Basic.lean @@ -141,15 +141,11 @@ attribute [local instance] FintypeCat.discreteTopology /-- The natural functor from `Fintype` to `Profinite`, endowing a finite type with the discrete topology. -/ -@[simps map_apply] +@[simps -isSimp map_apply] def FintypeCat.toProfinite : FintypeCat ⥤ Profinite where obj A := Profinite.of A map f := ⟨f, by continuity⟩ --- This lemma is generated by `simps` but we don't actually want the `@[simp]` attribute. --- https://github.com/leanprover-community/mathlib4/issues/18942 -attribute [nolint simpNF] FintypeCat.toProfinite_map_apply - /-- `FintypeCat.toLightProfinite` is fully faithful. -/ def FintypeCat.toProfiniteFullyFaithful : toProfinite.FullyFaithful where preimage f := (f : _ → _) diff --git a/Mathlib/Topology/ContinuousMap/Units.lean b/Mathlib/Topology/ContinuousMap/Units.lean index e64dbd15575a5..d355156e8246e 100644 --- a/Mathlib/Topology/ContinuousMap/Units.lean +++ b/Mathlib/Topology/ContinuousMap/Units.lean @@ -27,7 +27,6 @@ variable [Monoid M] [TopologicalSpace M] [ContinuousMul M] and the units of the monoid of continuous maps. -/ -- `simps` generates some lemmas here with LHS not in simp normal form, -- so we write them out manually below. --- https://github.com/leanprover-community/mathlib4/issues/18942 @[to_additive (attr := simps apply_val_apply symm_apply_apply_val) "Equivalence between continuous maps into the additive units of an additive monoid with continuous addition and the additive units of the additive monoid of continuous maps."] From c01816fd5fc619562ff2f6841d4b66dcf66e2464 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 21 Jan 2025 18:51:08 +0000 Subject: [PATCH 388/681] chore: simplify some proofs with `omega` (#20919) Those simplifications were found by [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). Co-authored-by: Moritz Firsching --- Mathlib/Algebra/Polynomial/FieldDivision.lean | 6 +----- Mathlib/Algebra/Ring/Int/Parity.lean | 15 +-------------- Mathlib/AlgebraicTopology/SimplexCategory.lean | 9 +-------- Mathlib/Analysis/Complex/Polynomial/Basic.lean | 10 +--------- .../Combinatorics/Enumerative/Composition.lean | 4 +--- Mathlib/Computability/PartrecCode.lean | 6 +----- Mathlib/Data/Int/Defs.lean | 3 +-- Mathlib/Data/List/Intervals.lean | 7 +------ Mathlib/Data/Nat/Choose/Sum.lean | 6 +----- Mathlib/Data/Nat/Defs.lean | 10 ++-------- Mathlib/RingTheory/Ideal/Basic.lean | 7 +------ Mathlib/RingTheory/Polynomial/Basic.lean | 7 +------ Mathlib/RingTheory/RootsOfUnity/Complex.lean | 12 +----------- Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean | 6 +----- 14 files changed, 15 insertions(+), 93 deletions(-) diff --git a/Mathlib/Algebra/Polynomial/FieldDivision.lean b/Mathlib/Algebra/Polynomial/FieldDivision.lean index 07d250cccea6d..6c59297f72e39 100644 --- a/Mathlib/Algebra/Polynomial/FieldDivision.lean +++ b/Mathlib/Algebra/Polynomial/FieldDivision.lean @@ -187,11 +187,7 @@ theorem isRoot_of_isRoot_of_dvd_derivative_mul [CharZero R] {f g : R[X]} (hf0 : rw [rootMultiplicity_mul hdfg0, derivative_rootMultiplicity_of_root haf, rootMultiplicity_eq_zero hg, add_zero, rootMultiplicity_mul (hr ▸ hdfg0), add_comm, Nat.sub_eq_iff_eq_add (Nat.succ_le_iff.2 ((rootMultiplicity_pos hf0).2 haf))] at hr' - refine lt_irrefl (rootMultiplicity a f) ?_ - refine lt_of_lt_of_le (Nat.lt_succ_self _) - (le_trans (le_add_of_nonneg_left (Nat.zero_le (rootMultiplicity a r))) ?_) - conv_rhs => rw [hr'] - simp [add_assoc] + omega section NormalizationMonoid diff --git a/Mathlib/Algebra/Ring/Int/Parity.lean b/Mathlib/Algebra/Ring/Int/Parity.lean index 95909efda8ec2..3a8f37de3bdb1 100644 --- a/Mathlib/Algebra/Ring/Int/Parity.lean +++ b/Mathlib/Algebra/Ring/Int/Parity.lean @@ -113,20 +113,7 @@ lemma four_dvd_add_or_sub_of_odd {a b : ℤ} (ha : Odd a) (hb : Odd b) : 4 ∣ a + b ∨ 4 ∣ a - b := by obtain ⟨m, rfl⟩ := ha obtain ⟨n, rfl⟩ := hb - obtain h | h := Int.even_or_odd (m + n) - · right - rw [Int.even_add, ← Int.even_sub] at h - obtain ⟨k, hk⟩ := h - convert dvd_mul_right 4 k using 1 - rw [eq_add_of_sub_eq hk, mul_add, add_assoc, add_sub_cancel_right, ← two_mul, ← mul_assoc] - rfl - · left - obtain ⟨k, hk⟩ := h - convert dvd_mul_right 4 (k + 1) using 1 - rw [eq_sub_of_add_eq hk, add_right_comm, ← add_sub, mul_add, mul_sub, add_assoc, add_assoc, - sub_add, add_assoc, ← sub_sub (2 * n), sub_self, zero_sub, sub_neg_eq_add, ← mul_assoc, - mul_add] - rfl + omega lemma two_mul_ediv_two_add_one_of_odd : Odd n → 2 * (n / 2) + 1 = n := by rintro ⟨c, rfl⟩ diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index 7002837fe5f37..ba34f389c2b8c 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -903,14 +903,7 @@ theorem eq_σ_comp_of_not_injective' {n : ℕ} {Δ' : SimplexCategory} (θ : mk rw [Fin.succAbove_of_le_castSucc i.succ _] simp only [Fin.lt_iff_val_lt_val, Fin.le_iff_val_le_val, Fin.val_succ, Fin.coe_castSucc, Nat.lt_succ_iff, Fin.ext_iff] at h' h'' ⊢ - cases' Nat.le.dest h' with c hc - cases c - · exfalso - simp only [add_zero, len_mk, Fin.coe_pred] at hc - rw [hc] at h'' - exact h'' rfl - · rw [← hc] - simp only [add_le_add_iff_left, Nat.succ_eq_add_one, le_add_iff_nonneg_left, zero_le] + omega theorem eq_σ_comp_of_not_injective {n : ℕ} {Δ' : SimplexCategory} (θ : mk (n + 1) ⟶ Δ') (hθ : ¬Function.Injective θ.toOrderHom) : diff --git a/Mathlib/Analysis/Complex/Polynomial/Basic.lean b/Mathlib/Analysis/Complex/Polynomial/Basic.lean index 706b89c25be7f..b3296662c3ab7 100644 --- a/Mathlib/Analysis/Complex/Polynomial/Basic.lean +++ b/Mathlib/Analysis/Complex/Polynomial/Basic.lean @@ -159,15 +159,7 @@ theorem galActionHom_bijective_of_prime_degree' {p : ℚ[X]} (p_irr : Irreducibl MonoidHom.map_one, MonoidHom.map_one]) have key := card_complex_roots_eq_card_real_add_card_not_gal_inv p simp_rw [Set.toFinset_card] at key - rw [key, add_le_add_iff_left] at p_roots1 p_roots2 - rw [key, add_right_inj] - suffices ∀ m : ℕ, 2 ∣ m → 1 ≤ m → m ≤ 3 → m = 2 by exact this n hn p_roots1 p_roots2 - rintro m ⟨k, rfl⟩ h2 h3 - exact le_antisymm - (Nat.lt_succ_iff.mp - (lt_of_le_of_ne h3 (show 2 * k ≠ 2 * 1 + 1 from Nat.two_mul_ne_two_mul_add_one))) - (Nat.succ_le_iff.mpr - (lt_of_le_of_ne h2 (show 2 * 0 + 1 ≠ 2 * k from Nat.two_mul_ne_two_mul_add_one.symm))) + omega end Rationals diff --git a/Mathlib/Combinatorics/Enumerative/Composition.lean b/Mathlib/Combinatorics/Enumerative/Composition.lean index b7b6c98651639..46dc3c0b92821 100644 --- a/Mathlib/Combinatorics/Enumerative/Composition.lean +++ b/Mathlib/Combinatorics/Enumerative/Composition.lean @@ -747,9 +747,7 @@ def compositionAsSetEquiv (n : ℕ) : CompositionAsSet n ≃ Finset (Fin (n - 1) exact Nat.succ_pred_eq_of_pos (pos_iff_ne_zero.mpr i_ne_zero) refine ⟨⟨i - 1, ?_⟩, ?_, ?_⟩ · have : (i : ℕ) < n + 1 := i.2 - simp? [Nat.lt_succ_iff_lt_or_eq, i_ne_last] at this says - simp only [Nat.succ_eq_add_one, Nat.lt_succ_iff_lt_or_eq, i_ne_last, or_false] at this - exact Nat.pred_lt_pred i_ne_zero this + omega · convert i_mem simp only rwa [add_comm] diff --git a/Mathlib/Computability/PartrecCode.lean b/Mathlib/Computability/PartrecCode.lean index 40ff8c1cdce91..4a04dbd781f9d 100644 --- a/Mathlib/Computability/PartrecCode.lean +++ b/Mathlib/Computability/PartrecCode.lean @@ -198,11 +198,7 @@ theorem encode_lt_prec (cf cg) : theorem encode_lt_rfind' (cf) : encode cf < encode (rfind' cf) := by simp only [encodeCode_eq, encodeCode] - have := Nat.mul_le_mul_right cf.encodeCode (by decide : 1 ≤ 2 * 2) - rw [one_mul, mul_assoc] at this - refine lt_of_le_of_lt (le_trans this ?_) (lt_add_of_pos_right _ (by decide : 0 < 4)) - exact le_of_lt (Nat.lt_succ_of_le <| Nat.mul_le_mul_left _ <| le_of_lt <| - Nat.lt_succ_of_le <| Nat.mul_le_mul_left _ <| le_rfl) + omega end Nat.Partrec.Code diff --git a/Mathlib/Data/Int/Defs.lean b/Mathlib/Data/Int/Defs.lean index 2b92ec1456668..74a86d6296cf7 100644 --- a/Mathlib/Data/Int/Defs.lean +++ b/Mathlib/Data/Int/Defs.lean @@ -228,8 +228,7 @@ where | 0 => Hp _ Int.le_rfl H0 | n+1 => by refine cast (by rw [Int.add_sub_assoc]; rfl) (Hp _ (Int.le_of_lt ?_) (neg n)) - conv => rhs; exact b.add_zero.symm - rw [Int.add_lt_add_iff_left]; apply negSucc_lt_zero + omega variable {z b H0 Hs Hp} diff --git a/Mathlib/Data/List/Intervals.lean b/Mathlib/Data/List/Intervals.lean index c9eee93aee149..0ea92237b0822 100644 --- a/Mathlib/Data/List/Intervals.lean +++ b/Mathlib/Data/List/Intervals.lean @@ -56,12 +56,7 @@ theorem nodup (n m : ℕ) : Nodup (Ico n m) := by @[simp] theorem mem {n m l : ℕ} : l ∈ Ico n m ↔ n ≤ l ∧ l < m := by suffices n ≤ l ∧ l < n + (m - n) ↔ n ≤ l ∧ l < m by simp [Ico, this] - rcases le_total n m with hnm | hmn - · rw [Nat.add_sub_cancel' hnm] - · rw [Nat.sub_eq_zero_iff_le.mpr hmn, Nat.add_zero] - exact - and_congr_right fun hnl => - Iff.intro (fun hln => (not_le_of_gt hln hnl).elim) fun hlm => lt_of_lt_of_le hlm hmn + omega theorem eq_nil_of_le {n m : ℕ} (h : m ≤ n) : Ico n m = [] := by simp [Ico, Nat.sub_eq_zero_iff_le.mpr h] diff --git a/Mathlib/Data/Nat/Choose/Sum.lean b/Mathlib/Data/Nat/Choose/Sum.lean index c98ee34c8d002..390fb1a116da2 100644 --- a/Mathlib/Data/Nat/Choose/Sum.lean +++ b/Mathlib/Data/Nat/Choose/Sum.lean @@ -104,11 +104,7 @@ theorem sum_range_choose_halfway (m : ℕ) : (∑ i ∈ range (m + 1), (2 * m + ∑ i ∈ Ico (m + 1) (2 * m + 2), (2 * m + 1).choose i := by rw [range_eq_Ico, sum_Ico_reflect _ _ (by omega)] congr - have A : m + 1 ≤ 2 * m + 1 := by omega - rw [add_comm, add_tsub_assoc_of_le A, ← add_comm] - congr - rw [tsub_eq_iff_eq_add_of_le A] - ring + omega _ = ∑ i ∈ range (2 * m + 2), (2 * m + 1).choose i := sum_range_add_sum_Ico _ (by omega) _ = 2 ^ (2 * m + 1) := sum_range_choose (2 * m + 1) _ = 2 * 4 ^ m := by rw [pow_succ, pow_mul, mul_comm]; rfl diff --git a/Mathlib/Data/Nat/Defs.lean b/Mathlib/Data/Nat/Defs.lean index 415504a2a854d..89a1dbbbbec52 100644 --- a/Mathlib/Data/Nat/Defs.lean +++ b/Mathlib/Data/Nat/Defs.lean @@ -493,16 +493,10 @@ lemma div_mul_div_le_div (a b c : ℕ) : a / c * b / a ≤ b / c := by lemma eq_zero_of_le_half (h : n ≤ n / 2) : n = 0 := eq_zero_of_le_div (Nat.le_refl _) h lemma le_half_of_half_lt_sub (h : a / 2 < a - b) : b ≤ a / 2 := by - rw [Nat.le_div_iff_mul_le Nat.two_pos] - rw [Nat.div_lt_iff_lt_mul Nat.two_pos, Nat.sub_mul, Nat.lt_sub_iff_add_lt, - Nat.mul_two a] at h - exact Nat.le_of_lt (Nat.lt_of_add_lt_add_left h) + omega lemma half_le_of_sub_le_half (h : a - b ≤ a / 2) : a / 2 ≤ b := by - rw [Nat.le_div_iff_mul_le Nat.two_pos, Nat.sub_mul, Nat.sub_le_iff_le_add, - Nat.mul_two, Nat.add_le_add_iff_left] at h - rw [← Nat.mul_div_left b Nat.two_pos] - exact Nat.div_le_div_right h + omega protected lemma div_le_of_le_mul' (h : m ≤ k * n) : m / k ≤ n := by obtain rfl | hk := k.eq_zero_or_pos diff --git a/Mathlib/RingTheory/Ideal/Basic.lean b/Mathlib/RingTheory/Ideal/Basic.lean index 864e9f84072c4..9ce9f9e98dea1 100644 --- a/Mathlib/RingTheory/Ideal/Basic.lean +++ b/Mathlib/RingTheory/Ideal/Basic.lean @@ -77,12 +77,7 @@ theorem add_pow_mem_of_pow_mem_of_le {m n k : ℕ} by_cases h : m ≤ c · exact I.mul_mem_right _ (I.pow_mem_of_pow_mem ha h) · refine I.mul_mem_left _ (I.pow_mem_of_pow_mem hb ?_) - simp only [not_le, Nat.lt_iff_add_one_le] at h - have hck : c ≤ k := by - rw [← add_le_add_iff_right 1] - exact le_trans h (le_trans (Nat.le_add_right _ _) hk) - rw [Nat.le_sub_iff_add_le hck, ← add_le_add_iff_right 1] - exact le_trans (by rwa [add_comm _ n, add_assoc, add_le_add_iff_left]) hk + omega theorem add_pow_add_pred_mem_of_pow_mem {m n : ℕ} (ha : a ^ m ∈ I) (hb : b ^ n ∈ I) : diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index e6caeb702f390..d94f141c480d3 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -723,12 +723,7 @@ theorem isPrime_map_C_iff_isPrime (P : Ideal R) : rw [Finset.mem_erase, Finset.mem_antidiagonal] at hij simp only [Ne, Prod.mk.inj_iff, not_and_or] at hij obtain hi | hj : i < m ∨ j < n := by - rw [or_iff_not_imp_left, not_lt, le_iff_lt_or_eq] - rintro (hmi | rfl) - · rw [← not_le] - intro hnj - exact (add_lt_add_of_lt_of_le hmi hnj).ne hij.2.symm - · simp only [eq_self_iff_true, not_true, false_or, add_right_inj, not_and_self_iff] at hij + omega · rw [mul_comm] apply P.mul_mem_left exact Classical.not_not.1 (Nat.find_min hf hi) diff --git a/Mathlib/RingTheory/RootsOfUnity/Complex.lean b/Mathlib/RingTheory/RootsOfUnity/Complex.lean index d2a6eb1145140..0b20c1181f990 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Complex.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Complex.lean @@ -130,17 +130,7 @@ theorem IsPrimitiveRoot.arg {n : ℕ} {ζ : ℂ} (h : IsPrimitiveRoot ζ n) (hn · exact hin · convert hin.add_mul_left_left (-1) using 1 rw [mul_neg_one, sub_eq_add_neg] - on_goal 2 => - split_ifs with h₂ - · exact mod_cast h - suffices (i - n : ℤ).natAbs = n - i by - rw [this] - apply tsub_lt_self hn.bot_lt - contrapose! h₂ - rw [Nat.eq_zero_of_le_zero h₂, zero_mul] - exact zero_le _ - rw [← Int.natAbs_neg, neg_sub, Int.natAbs_eq_iff] - exact Or.inl (Int.ofNat_sub h.le).symm + on_goal 2 => omega split_ifs with h₂ · convert Complex.arg_cos_add_sin_mul_I _ · push_cast; rfl diff --git a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean index 662314f0bb691..83fcac52c0419 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean @@ -426,11 +426,7 @@ theorem HasProd.nat_mul_neg {f : ℤ → M} (hf : HasProd f m) : · intro x hx simp only [u1, u2, mem_inter, mem_image, exists_prop] at hx suffices x = 0 by simp only [this, eq_self_iff_true, if_true] - apply le_antisymm - · rcases hx.2 with ⟨a, _, rfl⟩ - simp only [Right.neg_nonpos_iff, Nat.cast_nonneg] - · rcases hx.1 with ⟨a, _, rfl⟩ - simp only [Nat.cast_nonneg] + omega _ = (∏ x ∈ u1, f x) * ∏ x ∈ u2, f x := prod_union_inter _ = (∏ b ∈ v', f b) * ∏ b ∈ v', f (-b) := by simp only [u1, u2, Nat.cast_inj, imp_self, implies_true, forall_const, prod_image, neg_inj] From 02f1d572ccedf7bb8af17aa8da841aca4ccf9db0 Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 21 Jan 2025 20:35:35 +0000 Subject: [PATCH 389/681] feat(CI): Zulip `:closed-pr:` emoji reaction (#20902) Add a workflow that is triggered by closing a PR. If the PR does title not start with `[Merged by Bors]`, then the script adds the `:closed-pr:` emoji reaction to messages on Zulip that link to the PR number. --- .github/workflows/zulip_emoji_closed_pr.yaml | 52 ++++++++++++++++++++ scripts/zulip_emoji_merge_delegate.py | 14 ++++++ 2 files changed, 66 insertions(+) create mode 100644 .github/workflows/zulip_emoji_closed_pr.yaml diff --git a/.github/workflows/zulip_emoji_closed_pr.yaml b/.github/workflows/zulip_emoji_closed_pr.yaml new file mode 100644 index 0000000000000..f07fe1751bb78 --- /dev/null +++ b/.github/workflows/zulip_emoji_closed_pr.yaml @@ -0,0 +1,52 @@ +name: Add "closed-pr" emoji in Zulip +# adds a reaction to Zulip messages that refer to a PR that was closed, but not merged + +# triggers the action when +on: + pull_request: + # the pull request is closed + types: [closed] + +jobs: + add_closed_pr_emoji: + # we set the `TITLE` of the PR as a variable, this shields from possible code injection + env: + TITLE: ${{ github.event.pull_request.title }} + + name: Add closed-pr emoji in Zulip + runs-on: ubuntu-latest + steps: + - name: Debugging information + run: | + # may be superfluous: GitHub may print the values of the environment variables by default + printf '%s' "${TITLE}" | hexdump -cC + printf 'PR title:"%s"\n' "${TITLE}" + printf 'issue number: "%s"\npull request number: "%s"\n' "${{ github.event.issue.number }}" "${{ github.event.pull_request.number }}" + + - name: Set up Python + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install dependencies + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + run: | + python -m pip install --upgrade pip + pip install zulip + + - name: checkout zulip_emoji_merge_delegate script + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + uses: actions/checkout@v4 + with: + sparse-checkout: | + scripts/zulip_emoji_merge_delegate.py + + - name: Run Zulip Emoji Merge Delegate Script + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + env: + ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }} + ZULIP_EMAIL: github-mathlib4-bot@leanprover.zulipchat.com + ZULIP_SITE: https://leanprover.zulipchat.com + run: | + python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "closed" "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" diff --git a/scripts/zulip_emoji_merge_delegate.py b/scripts/zulip_emoji_merge_delegate.py index de3e5d3ca70c3..13069dd7e9529 100644 --- a/scripts/zulip_emoji_merge_delegate.py +++ b/scripts/zulip_emoji_merge_delegate.py @@ -66,6 +66,7 @@ has_bors = any(reaction['emoji_name'] == 'bors' for reaction in reactions) has_merge = any(reaction['emoji_name'] == 'merge' for reaction in reactions) has_awaiting_author = any(reaction['emoji_name'] == 'writing' for reaction in reactions) + has_closed = any(reaction['emoji_name'] == 'closed-pr' for reaction in reactions) match = pr_pattern.search(content) if match: print(f"matched: '{message}'") @@ -102,6 +103,13 @@ "emoji_name": "writing" }) print(f"result: '{result}'") + if has_closed: + print('Removing closed-pr') + result = client.remove_reaction({ + "message_id": message['id'], + "emoji_name": "closed-pr" + }) + print(f"result: '{result}'") # applying appropriate emoji reaction @@ -124,6 +132,12 @@ "message_id": message['id'], "emoji_name": "writing" }) + elif LABEL == 'closed': + print('adding closed-pr') + client.add_reaction({ + "message_id": message['id'], + "emoji_name": "closed-pr" + }) elif LABEL == 'unlabeled': print('awaiting-author removed') # the reaction was already removed. From 114805c09cf2fd8d3cfe90d8bb97a08b79bfa336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 21 Jan 2025 20:43:58 +0000 Subject: [PATCH 390/681] feat: induction principle for finitely presented ring homs (#20069) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a property to hold for all finitely presented ring homs, it suffices for it to hold for `Polynomial.C : R → R[X]`, surjective ring homs with finitely generated kernels, and to be closed under composition. From GrowthInGroups (LeanCamCombi) --- Mathlib/RingTheory/FinitePresentation.lean | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/Mathlib/RingTheory/FinitePresentation.lean b/Mathlib/RingTheory/FinitePresentation.lean index 777df2c59cb87..06867a417b8d1 100644 --- a/Mathlib/RingTheory/FinitePresentation.lean +++ b/Mathlib/RingTheory/FinitePresentation.lean @@ -450,6 +450,63 @@ end FinitePresentation end RingHom +namespace RingHom.FinitePresentation +universe u v + +open Polynomial + +/-- Induction principle for finitely presented ring homomorphisms. + +For a property to hold for all finitely presented ring homs, it suffices for it to hold for +`Polynomial.C : R → R[X]`, surjective ring homs with finitely generated kernels, and to be closed +under composition. + +Note that to state this conveniently for ring homs between rings of different universes, we carry +around two predicates `P` and `Q`, which should be "the same" apart from universes: +* `P`, for ring homs `(R : Type u) → (S : Type u)`. +* `Q`, for ring homs `(R : Type u) → (S : Type v)`. +-/ +lemma polynomial_induction + (P : ∀ (R : Type u) [CommRing R] (S : Type u) [CommRing S], (R →+* S) → Prop) + (Q : ∀ (R : Type u) [CommRing R] (S : Type v) [CommRing S], (R →+* S) → Prop) + (polynomial : ∀ (R) [CommRing R], P R R[X] C) + (fg_ker : ∀ (R : Type u) [CommRing R] (S : Type v) [CommRing S] (f : R →+* S), + Surjective f → (ker f).FG → Q R S f) + (comp : ∀ (R) [CommRing R] (S) [CommRing S] (T) [CommRing T] (f : R →+* S) (g : S →+* T), + P R S f → Q S T g → Q R T (g.comp f)) + {R : Type u} {S : Type v} [CommRing R] [CommRing S] (f : R →+* S) (hf : f.FinitePresentation) : + Q R S f := by + letI := f.toAlgebra + obtain ⟨n, g, hg, hg'⟩ := hf + let g' := g.toRingHom + change Surjective g' at hg + change (ker g').FG at hg' + have : g'.comp MvPolynomial.C = f := g.comp_algebraMap + clear_value g' + subst this + clear g + induction n generalizing R S with + | zero => + refine fg_ker _ _ _ (hg.comp (MvPolynomial.C_surjective (Fin 0))) ?_ + rw [← comap_ker] + convert hg'.map (MvPolynomial.isEmptyRingEquiv R (Fin 0)).toRingHom using 1 + simp only [RingEquiv.toRingHom_eq_coe] + exact Ideal.comap_symm (MvPolynomial.isEmptyRingEquiv R (Fin 0)) + | succ n IH => + let e : MvPolynomial (Fin (n + 1)) R ≃ₐ[R] MvPolynomial (Fin n) R[X] := + (MvPolynomial.renameEquiv R (finSuccEquiv n)).trans (MvPolynomial.optionEquivRight R (Fin n)) + have he : (ker (g'.comp <| RingHomClass.toRingHom e.symm)).FG := by + rw [← RingHom.comap_ker] + convert hg'.map e.toAlgHom.toRingHom using 1 + exact Ideal.comap_symm e.toRingEquiv + have := IH (R := R[X]) (S := S) (g'.comp e.symm) (hg.comp e.symm.surjective) he + convert comp _ _ _ _ _ (polynomial _) this using 1 + rw [comp_assoc, comp_assoc] + congr 1 with r + simp [e] + +end RingHom.FinitePresentation + namespace AlgHom variable {R A B C : Type*} [CommRing R] From 1d24f3cf73e1a57e5ba5225d26ebd0f6db86b751 Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Tue, 21 Jan 2025 20:44:00 +0000 Subject: [PATCH 391/681] refactor(Order/Disjointed): allow arbitrary partial orders as domain (#20545) Co-authored-by: Johan Commelin Co-authored-by: Yury G. Kudryashov --- Mathlib.lean | 1 + Mathlib/Algebra/Order/Disjointed.lean | 69 ++++ .../OuterMeasure/Caratheodory.lean | 31 +- Mathlib/MeasureTheory/SetSemiring.lean | 27 +- Mathlib/Order/Disjointed.lean | 342 ++++++++++++------ Mathlib/Order/Interval/Finset/Box.lean | 10 +- 6 files changed, 355 insertions(+), 125 deletions(-) create mode 100644 Mathlib/Algebra/Order/Disjointed.lean diff --git a/Mathlib.lean b/Mathlib.lean index a7202dbc85237..4fe37ad19e493 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -680,6 +680,7 @@ import Mathlib.Algebra.Order.CauSeq.BigOperators import Mathlib.Algebra.Order.CauSeq.Completion import Mathlib.Algebra.Order.Chebyshev import Mathlib.Algebra.Order.CompleteField +import Mathlib.Algebra.Order.Disjointed import Mathlib.Algebra.Order.Field.Basic import Mathlib.Algebra.Order.Field.Canonical import Mathlib.Algebra.Order.Field.Defs diff --git a/Mathlib/Algebra/Order/Disjointed.lean b/Mathlib/Algebra/Order/Disjointed.lean new file mode 100644 index 0000000000000..77556150bed67 --- /dev/null +++ b/Mathlib/Algebra/Order/Disjointed.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2025 David Loeffler. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Loeffler +-/ +import Mathlib.Algebra.Order.PartialSups +import Mathlib.Data.Nat.SuccPred +import Mathlib.Order.Disjointed + +/-! +# `Disjointed` for functions on a `SuccAddOrder` + +This file contains material excised from `Mathlib.Order.Disjointed` to avoid import dependencies +from `Mathlib.Algebra.Order` into `Mathlib.Order`. + +## TODO + +Find a useful statement of `disjointedRec_succ`. +-/ + +open Order + +variable {α ι : Type*} [GeneralizedBooleanAlgebra α] + +section SuccAddOrder + +variable [LinearOrder ι] [LocallyFiniteOrderBot ι] [Add ι] [One ι] [SuccAddOrder ι] + +theorem disjointed_add_one [NoMaxOrder ι] (f : ι → α) (i : ι) : + disjointed f (i + 1) = f (i + 1) \ partialSups f i := by + simpa only [succ_eq_add_one] using disjointed_succ f (not_isMax i) + +protected lemma Monotone.disjointed_add_one_sup {f : ι → α} (hf : Monotone f) (i : ι) : + disjointed f (i + 1) ⊔ f i = f (i + 1) := by + simpa only [succ_eq_add_one i] using hf.disjointed_succ_sup i + +protected lemma Monotone.disjointed_add_one [NoMaxOrder ι] {f : ι → α} (hf : Monotone f) (i : ι) : + disjointed f (i + 1) = f (i + 1) \ f i := by + rw [← succ_eq_add_one, hf.disjointed_succ] + exact not_isMax i + +end SuccAddOrder + +section Nat + +/-- A recursion principle for `disjointed`. To construct / define something for `disjointed f i`, +it's enough to construct / define it for `f n` and to able to extend through diffs. + +Note that this version allows an arbitrary `Sort*`, but requires the domain to be `Nat`, while +the root-level `disjointedRec` allows more general domains but requires `p` to be `Prop`-valued. -/ +def Nat.disjointedRec {f : ℕ → α} {p : α → Sort*} (hdiff : ∀ ⦃t i⦄, p t → p (t \ f i)) : + ∀ ⦃n⦄, p (f n) → p (disjointed f n) + | 0 => fun h₀ ↦ disjointed_zero f ▸ h₀ + | n + 1 => fun h => by + suffices H : ∀ k, p (f (n + 1) \ partialSups f k) from disjointed_add_one f n ▸ H n + intro k + induction k with + | zero => exact hdiff h + | succ k ih => simpa only [partialSups_add_one, ← sdiff_sdiff_left] using hdiff ih + +@[simp] +theorem disjointedRec_zero {f : ℕ → α} {p : α → Sort*} + (hdiff : ∀ ⦃t i⦄, p t → p (t \ f i)) (h₀ : p (f 0)) : + Nat.disjointedRec hdiff h₀ = (disjointed_zero f ▸ h₀) := + rfl + +-- TODO: Find a useful statement of `disjointedRec_succ`. + +end Nat diff --git a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean index be505ddb8561a..36c1a59159274 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean @@ -72,6 +72,18 @@ theorem isCaratheodory_union (h₁ : IsCaratheodory m s₁) (h₂ : IsCaratheodo union_diff_left, h₂ (t ∩ s₁)] simp [diff_eq, add_assoc] +variable {m} in +lemma IsCaratheodory.biUnion_of_finite {ι : Type*} {s : ι → Set α} {t : Set ι} (ht : t.Finite) + (h : ∀ i ∈ t, m.IsCaratheodory (s i)) : + m.IsCaratheodory (⋃ i ∈ t, s i) := by + classical + lift t to Finset ι using ht + induction t using Finset.induction_on with + | empty => simp + | @insert i t hi IH => + simp only [Finset.mem_coe, Finset.mem_insert, iUnion_iUnion_eq_or_left] at h ⊢ + exact m.isCaratheodory_union (h _ <| Or.inl rfl) (IH fun _ hj ↦ h _ <| Or.inr hj) + theorem measure_inter_union (h : s₁ ∩ s₂ ⊆ ∅) (h₁ : IsCaratheodory m s₁) {t : Set α} : m (t ∩ (s₁ ∪ s₂)) = m (t ∩ s₁) + m (t ∩ s₂) := by rw [h₁, Set.inter_assoc, Set.union_inter_cancel_left, inter_diff_assoc, union_diff_cancel_left h] @@ -93,17 +105,16 @@ theorem isCaratheodory_inter (h₁ : IsCaratheodory m s₁) (h₂ : IsCaratheodo lemma isCaratheodory_diff (h₁ : IsCaratheodory m s₁) (h₂ : IsCaratheodory m s₂) : IsCaratheodory m (s₁ \ s₂) := m.isCaratheodory_inter h₁ (m.isCaratheodory_compl h₂) -lemma isCaratheodory_partialSups {s : ℕ → Set α} (h : ∀ i, m.IsCaratheodory (s i)) (i : ℕ) : +lemma isCaratheodory_partialSups {ι : Type*} [PartialOrder ι] [LocallyFiniteOrderBot ι] + {s : ι → Set α} (h : ∀ i, m.IsCaratheodory (s i)) (i : ι) : m.IsCaratheodory (partialSups s i) := by - induction i with - | zero => exact h 0 - | succ i hi => exact partialSups_add_one s i ▸ m.isCaratheodory_union hi (h (i + 1)) - -lemma isCaratheodory_disjointed {s : ℕ → Set α} (h : ∀ i, m.IsCaratheodory (s i)) (i : ℕ) : - m.IsCaratheodory (disjointed s i) := by - induction i with - | zero => exact h 0 - | succ i _ => exact m.isCaratheodory_diff (h (i + 1)) (m.isCaratheodory_partialSups h i) + simpa only [partialSups_apply, Finset.sup'_eq_sup, Finset.sup_set_eq_biUnion, ← Finset.mem_coe, + Finset.coe_Iic] using .biUnion_of_finite (finite_Iic _) (fun j _ ↦ h j) + +lemma isCaratheodory_disjointed {ι : Type*} [PartialOrder ι] [LocallyFiniteOrderBot ι] + {s : ι → Set α} (h : ∀ i, m.IsCaratheodory (s i)) (i : ι) : + m.IsCaratheodory (disjointed s i) := + disjointedRec (fun _ j ht ↦ m.isCaratheodory_diff ht <| h j) (h i) theorem isCaratheodory_sum {s : ℕ → Set α} (h : ∀ i, IsCaratheodory m (s i)) (hd : Pairwise (Disjoint on s)) {t : Set α} : diff --git a/Mathlib/MeasureTheory/SetSemiring.lean b/Mathlib/MeasureTheory/SetSemiring.lean index 9df3fa00df048..7d5c399b2bb84 100644 --- a/Mathlib/MeasureTheory/SetSemiring.lean +++ b/Mathlib/MeasureTheory/SetSemiring.lean @@ -321,16 +321,25 @@ lemma biInter_mem {ι : Type*} (hC : IsSetRing C) {s : ι → Set α} refine hC.inter_mem hs.1 ?_ exact h (fun n hnS ↦ hs.2 n hnS) -lemma partialSups_mem (hC : IsSetRing C) {s : ℕ → Set α} (hs : ∀ n, s n ∈ C) (n : ℕ) : +lemma finsetSup_mem (hC : IsSetRing C) {ι : Type*} {s : ι → Set α} {t : Finset ι} + (hs : ∀ i ∈ t, s i ∈ C) : + t.sup s ∈ C := by + classical + induction t using Finset.induction_on with + | empty => exact hC.empty_mem + | @insert m t hm ih => + simpa only [sup_insert] using + hC.union_mem (hs m <| mem_insert_self m t) (ih <| fun i hi ↦ hs _ <| mem_insert_of_mem hi) + +lemma partialSups_mem {ι : Type*} [Preorder ι] [LocallyFiniteOrderBot ι] + (hC : IsSetRing C) {s : ι → Set α} (hs : ∀ n, s n ∈ C) (n : ι) : partialSups s n ∈ C := by - rw [partialSups_eq_biUnion_range] - exact hC.biUnion_mem _ (fun n _ ↦ hs n) - -lemma disjointed_mem (hC : IsSetRing C) {s : ℕ → Set α} (hs : ∀ n, s n ∈ C) (n : ℕ) : - disjointed s n ∈ C := by - cases n with - | zero => exact hs 0 - | succ n => exact hC.diff_mem (hs n.succ) (hC.partialSups_mem hs n) + simpa only [partialSups_apply, sup'_eq_sup] using hC.finsetSup_mem (fun i hi ↦ hs i) + +lemma disjointed_mem {ι : Type*} [Preorder ι] [LocallyFiniteOrderBot ι] + (hC : IsSetRing C) {s : ι → Set α} (hs : ∀ j, s j ∈ C) (i : ι) : + disjointed s i ∈ C := + disjointedRec (fun _ j ht ↦ hC.diff_mem ht <| hs j) (hs i) end IsSetRing diff --git a/Mathlib/Order/Disjointed.lean b/Mathlib/Order/Disjointed.lean index 62ea4568a5fa6..22ee30f0339ee 100644 --- a/Mathlib/Order/Disjointed.lean +++ b/Mathlib/Order/Disjointed.lean @@ -1,42 +1,43 @@ /- 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, Yaël Dillies +Authors: Johannes Hölzl, Yaël Dillies, David Loeffler -/ -import Mathlib.Algebra.Order.PartialSups -import Mathlib.Data.Nat.SuccPred +import Mathlib.Order.PartialSups +import Mathlib.Order.Interval.Finset.Fin /-! -# Consecutive differences of sets +# Making a sequence disjoint -This file defines the way to make a sequence of elements into a sequence of disjoint elements with +This file defines the way to make a sequence of sets - or, more generally, a map from a partially +ordered type `ι` into a (generalized) Boolean algebra `α` - into a *pairwise disjoint* sequence with the same partial sups. -For a sequence `f : ℕ → α`, this new sequence will be `f 0`, `f 1 \ f 0`, `f 2 \ (f 0 ⊔ f 1)`. +For a sequence `f : ℕ → α`, this new sequence will be `f 0`, `f 1 \ f 0`, `f 2 \ (f 0 ⊔ f 1) ⋯`. It is actually unique, as `disjointed_unique` shows. ## Main declarations -* `disjointed f`: The sequence `f 0`, `f 1 \ f 0`, `f 2 \ (f 0 ⊔ f 1)`, .... +* `disjointed f`: The map sending `i` to `f i \ (⨆ j < i, f j)`. We require the index type to be a + `LocallyFiniteOrderBot` to ensure that the supremum is well defined. * `partialSups_disjointed`: `disjointed f` has the same partial sups as `f`. * `disjoint_disjointed`: The elements of `disjointed f` are pairwise disjoint. * `disjointed_unique`: `disjointed f` is the only pairwise disjoint sequence having the same partial sups as `f`. -* `iSup_disjointed`: `disjointed f` has the same supremum as `f`. Limiting case of - `partialSups_disjointed`. +* `Fintype.sup_disjointed` (for finite `ι`) or `iSup_disjointed` (for complete `α`): + `disjointed f` has the same supremum as `f`. Limiting case of `partialSups_disjointed`. +* `Fintype.exists_disjointed_le`: for any finite family `f : ι → α`, there exists a pairwise + disjoint family `g : ι → α` which is bounded above by `f` and has the same supremum. This is + an analogue of `disjointed` for arbitrary finite index types (but without any uniqueness). We also provide set notation variants of some lemmas. - -## TODO - -Find a useful statement of `disjointedRec_succ`. - -One could generalize `disjointed` to any locally finite bot preorder domain, in place of `ℕ`. -Related to the TODO in the module docstring of `Mathlib.Order.PartialSups`. -/ +assert_not_exists SuccAddOrder -variable {α : Type*} +open Finset Order + +variable {α ι : Type*} open scoped Function -- required for scoped `on` notation @@ -44,124 +45,261 @@ section GeneralizedBooleanAlgebra variable [GeneralizedBooleanAlgebra α] -/-- If `f : ℕ → α` is a sequence of elements, then `disjointed f` is the sequence formed by -subtracting each element from the nexts. This is the unique disjoint sequence whose partial sups -are the same as the original sequence. -/ -def disjointed (f : ℕ → α) : ℕ → α - | 0 => f 0 - | n + 1 => f (n + 1) \ partialSups f n +section Preorder -- the *index type* is a preorder -@[simp] -theorem disjointed_zero (f : ℕ → α) : disjointed f 0 = f 0 := - rfl +variable [Preorder ι] [LocallyFiniteOrderBot ι] -theorem disjointed_succ (f : ℕ → α) (n : ℕ) : disjointed f (n + 1) = f (n + 1) \ partialSups f n := - rfl +/-- The function mapping `i` to `f i \ (⨆ j < i, f j)`. When `ι` is a partial order, this is the +unique function `g` having the same `partialSups` as `f` and such that `g i` and `g j` are +disjoint whenever `i < j`. -/ +def disjointed (f : ι → α) (i : ι) : α := f i \ (Iio i).sup f -theorem disjointed_le_id : disjointed ≤ (id : (ℕ → α) → ℕ → α) := by - rintro f n - cases n - · rfl - · exact sdiff_le +lemma disjointed_apply (f : ι → α) (i : ι) : disjointed f i = f i \ (Iio i).sup f := rfl -theorem disjointed_le (f : ℕ → α) : disjointed f ≤ f := +lemma disjointed_of_isMin (f : ι → α) {i : ι} (hn : IsMin i) : + disjointed f i = f i := by + have : Iio i = ∅ := by rwa [← Finset.coe_eq_empty, coe_Iio, Set.Iio_eq_empty_iff] + simp only [disjointed_apply, this, sup_empty, sdiff_bot] + +@[simp] lemma disjointed_bot [OrderBot ι] (f : ι → α) : disjointed f ⊥ = f ⊥ := + disjointed_of_isMin _ isMin_bot + +theorem disjointed_le_id : disjointed ≤ (id : (ι → α) → ι → α) := + fun _ _ ↦ sdiff_le + +theorem disjointed_le (f : ι → α) : disjointed f ≤ f := disjointed_le_id f -theorem disjoint_disjointed (f : ℕ → α) : Pairwise (Disjoint on disjointed f) := by - refine (Symmetric.pairwise_on Disjoint.symm _).2 fun m n h => ?_ - cases n - · exact (Nat.not_lt_zero _ h).elim - exact - disjoint_sdiff_self_right.mono_left - ((disjointed_le f m).trans (le_partialSups_of_le f (Nat.lt_add_one_iff.1 h))) - --- Porting note: `disjointedRec` had a change in universe level. -/-- An induction principle for `disjointed`. To define/prove something on `disjointed f n`, it's -enough to define/prove it for `f n` and being able to extend through diffs. -/ -def disjointedRec {f : ℕ → α} {p : α → Sort*} (hdiff : ∀ ⦃t i⦄, p t → p (t \ f i)) : - ∀ ⦃n⦄, p (f n) → p (disjointed f n) - | 0 => id - | n + 1 => fun h => by - suffices H : ∀ k, p (f (n + 1) \ partialSups f k) from H n - rintro k - induction' k with k ih - · exact hdiff h - rw [partialSups_add_one, ← sdiff_sdiff_left] - exact hdiff ih +theorem disjoint_disjointed_of_lt (f : ι → α) {i j : ι} (h : i < j) : + Disjoint (disjointed f i) (disjointed f j) := + (disjoint_sdiff_self_right.mono_left <| le_sup (mem_Iio.mpr h)).mono_left (disjointed_le f i) + +lemma disjointed_eq_self {f : ι → α} {i : ι} (hf : ∀ j < i, Disjoint (f j) (f i)) : + disjointed f i = f i := by + rw [disjointed_apply, sdiff_eq_left, disjoint_iff, sup_inf_distrib_left, + sup_congr rfl <| fun j hj ↦ disjoint_iff.mp <| (hf _ (mem_Iio.mp hj)).symm] + exact sup_bot _ + +/- NB: The original statement for `ι = ℕ` was a `def` and worked for `p : α → Sort*`. I couldn't +prove the `Sort*` version for general `ι`, but all instances of `disjointedRec` in the library are +for Prop anyway. -/ +/-- +An induction principle for `disjointed`. To prove something about `disjointed f i`, it's +enough to prove it for `f i` and being able to extend through diffs. +-/ +lemma disjointedRec {f : ι → α} {p : α → Prop} (hdiff : ∀ ⦃t i⦄, p t → p (t \ f i)) : + ∀ ⦃i⦄, p (f i) → p (disjointed f i) := by + classical + intro i hpi + rw [disjointed] + suffices ∀ (s : Finset ι), p (f i \ s.sup f) from this _ + intro s + induction s using Finset.induction with + | empty => simpa only [sup_empty, sdiff_bot] using hpi + | insert ht IH => + rw [sup_insert, sup_comm, ← sdiff_sdiff] + exact hdiff IH -@[simp] -theorem disjointedRec_zero {f : ℕ → α} {p : α → Sort*} (hdiff : ∀ ⦃t i⦄, p t → p (t \ f i)) - (h₀ : p (f 0)) : disjointedRec hdiff h₀ = h₀ := - rfl +end Preorder --- TODO: Find a useful statement of `disjointedRec_succ`. -protected lemma Monotone.disjointed_succ {f : ℕ → α} (hf : Monotone f) (n : ℕ) : - disjointed f (n + 1) = f (n + 1) \ f n := by rw [disjointed_succ, hf.partialSups_eq] +section PartialOrder -- the index type is a partial order -protected lemma Monotone.disjointed_succ_sup {f : ℕ → α} (hf : Monotone f) (n : ℕ) : - disjointed f (n + 1) ⊔ f n = f (n + 1) := by - rw [hf.disjointed_succ, sdiff_sup_cancel]; exact hf n.le_succ +variable [PartialOrder ι] [LocallyFiniteOrderBot ι] @[simp] -theorem partialSups_disjointed (f : ℕ → α) : partialSups (disjointed f) = partialSups f := by - ext n - induction' n with k ih - · rw [partialSups_zero, partialSups_zero, disjointed_zero] - · rw [partialSups_add_one, partialSups_add_one, disjointed_succ, ih, sup_sdiff_self_right] +theorem partialSups_disjointed (f : ι → α) : + partialSups (disjointed f) = partialSups f := by + -- This seems to be much more awkward than the case of linear orders, because the supremum + -- in the definition of `disjointed` can involve multiple "paths" through the poset. + classical + -- We argue by induction on the size of `Iio i`. + suffices ∀ r i (hi : #(Iio i) ≤ r), partialSups (disjointed f) i = partialSups f i from + OrderHom.ext _ _ (funext fun i ↦ this _ i le_rfl) + intro r i hi + induction r generalizing i with + | zero => + -- Base case: `n` is minimal, so `partialSups f i = partialSups (disjointed f) n = f i`. + simp only [Nat.le_zero, card_eq_zero] at hi + simp only [partialSups_apply, Iic_eq_cons_Iio, hi, disjointed_apply, sup'_eq_sup, sup_cons, + sup_empty, sdiff_bot] + | succ n ih => + -- Induction step: first WLOG arrange that `#(Iio i) = r + 1` + rcases lt_or_eq_of_le hi with hn | hn + · exact ih _ <| Nat.le_of_lt_succ hn + simp only [partialSups_apply (disjointed f), Iic_eq_cons_Iio, sup'_eq_sup, sup_cons] + -- Key claim: we can write `Iio i` as a union of (finitely many) `Ici` intervals. + have hun : (Iio i).biUnion Iic = Iio i := by + ext r; simpa using ⟨fun ⟨a, ha⟩ ↦ ha.2.trans_lt ha.1, fun hr ↦ ⟨r, hr, le_rfl⟩⟩ + -- Use claim and `sup_biUnion` to rewrite the supremum in the definition of `disjointed f` + -- in terms of suprema over `Iic`'s. Then the RHS is a `sup` over `partialSups`, which we + -- can rewrite via the induction hypothesis. + rw [← hun, sup_biUnion, sup_congr rfl (g := partialSups f)] + · simp only [funext (partialSups_apply f), sup'_eq_sup, ← sup_biUnion, hun] + simp only [disjointed, sdiff_sup_self, Iic_eq_cons_Iio, sup_cons] + · simp only [partialSups, sup'_eq_sup, OrderHom.coe_mk] at ih ⊢ + refine fun x hx ↦ ih x ?_ + -- Remains to show `∀ x in Iio i, #(Iio x) ≤ r`. + rw [← Nat.lt_add_one_iff, ← hn] + apply lt_of_lt_of_le (b := #(Iic x)) + · simpa only [Iic_eq_cons_Iio, card_cons] using Nat.lt_succ_self _ + · refine card_le_card (fun r hr ↦ ?_) + simp only [mem_Iic, mem_Iio] at hx hr ⊢ + exact hr.trans_lt hx + +lemma Fintype.sup_disjointed [Fintype ι] (f : ι → α) : + univ.sup (disjointed f) = univ.sup f := by + classical + have hun : univ.biUnion Iic = (univ : Finset ι) := by + ext r; simpa only [mem_biUnion, mem_univ, mem_Iic, true_and, iff_true] using ⟨r, le_rfl⟩ + rw [← hun, sup_biUnion, sup_biUnion, sup_congr rfl (fun i _ ↦ ?_)] + rw [← sup'_eq_sup nonempty_Iic, ← sup'_eq_sup nonempty_Iic, + ← partialSups_apply, ← partialSups_apply, partialSups_disjointed] + +lemma disjointed_partialSups (f : ι → α) : + disjointed (partialSups f) = disjointed f := by + classical + ext i + have step1 : f i \ (Iio i).sup f = partialSups f i \ (Iio i).sup f := by + rw [sdiff_eq_symm (sdiff_le.trans (le_partialSups f i))] + simp only [funext (partialSups_apply f), sup'_eq_sup] + rw [sdiff_sdiff_eq_sdiff_sup (sup_mono Iio_subset_Iic_self), sup_eq_right] + simp only [Iic_eq_cons_Iio, sup_cons, sup_sdiff_left_self, sdiff_le_iff, le_sup_right] + simp only [disjointed_apply, step1, funext (partialSups_apply f), sup'_eq_sup, ← sup_biUnion] + congr 2 with r + simpa only [mem_biUnion, mem_Iio, mem_Iic] using + ⟨fun ⟨a, ha⟩ ↦ ha.2.trans_lt ha.1, fun hr ↦ ⟨r, hr, le_rfl⟩⟩ + +/-- `disjointed f` is the unique map `d : ι → α` such that `d` has the same partial sups as `f`, +and `d i` and `d j` are disjoint whenever `i < j`. -/ +theorem disjointed_unique {f d : ι → α} (hdisj : ∀ {i j : ι} (_ : i < j), Disjoint (d i) (d j)) + (hsups : partialSups d = partialSups f) : + d = disjointed f := by + rw [← disjointed_partialSups, ← hsups, disjointed_partialSups] + exact funext fun _ ↦ (disjointed_eq_self (fun _ hj ↦ hdisj hj)).symm + +end PartialOrder + +section LinearOrder -- the index type is a linear order + +/-! +### Linear orders +-/ + +variable [LinearOrder ι] [LocallyFiniteOrderBot ι] + +theorem disjoint_disjointed (f : ι → α) : Pairwise (Disjoint on disjointed f) := + (pairwise_disjoint_on _).mpr fun _ _ ↦ disjoint_disjointed_of_lt f /-- `disjointed f` is the unique sequence that is pairwise disjoint and has the same partial sups as `f`. -/ -theorem disjointed_unique {f d : ℕ → α} (hdisj : Pairwise (Disjoint on d)) - (hsups : partialSups d = partialSups f) : d = disjointed f := by - ext n - cases' n with n - · rw [← partialSups_zero d, hsups, partialSups_zero, disjointed_zero] - suffices h : d (n + 1) = partialSups d (n + 1) \ partialSups d n by - rw [h, hsups, partialSups_add_one, disjointed_succ, sup_sdiff, sdiff_self, bot_sup_eq] - rw [partialSups_add_one, sup_sdiff, sdiff_self, bot_sup_eq, eq_comm, sdiff_eq_self_iff_disjoint] - suffices h : ∀ m ≤ n, Disjoint (partialSups d m) (d n.succ) from h n le_rfl - rintro m hm - induction' m with m ih - · exact hdisj (Nat.succ_ne_zero _).symm - rw [partialSups_add_one, disjoint_iff, inf_sup_right, sup_eq_bot_iff, - ← disjoint_iff, ← disjoint_iff] - exact ⟨ih (Nat.le_of_succ_le hm), hdisj (Nat.lt_succ_of_le hm).ne⟩ +theorem disjointed_unique' {f d : ι → α} (hdisj : Pairwise (Disjoint on d)) + (hsups : partialSups d = partialSups f) : d = disjointed f := + disjointed_unique (fun hij ↦ hdisj hij.ne) hsups + +section SuccOrder + +variable [SuccOrder ι] + +lemma disjointed_succ (f : ι → α) {i : ι} (hi : ¬IsMax i) : + disjointed f (succ i) = f (succ i) \ partialSups f i := by + rw [disjointed_apply, partialSups_apply, sup'_eq_sup] + congr 2 with m + simpa only [mem_Iio, mem_Iic] using lt_succ_iff_of_not_isMax hi + +protected lemma Monotone.disjointed_succ {f : ι → α} (hf : Monotone f) {i : ι} (hn : ¬IsMax i) : + disjointed f (succ i) = f (succ i) \ f i := by + rwa [disjointed_succ, hf.partialSups_eq] + +/-- Note this lemma does not require `¬IsMax i`, unlike `disjointed_succ`. -/ +lemma Monotone.disjointed_succ_sup {f : ι → α} (hf : Monotone f) (i : ι) : + disjointed f (succ i) ⊔ f i = f (succ i) := by + by_cases h : IsMax i + · simpa only [succ_eq_iff_isMax.mpr h, sup_eq_right] using disjointed_le f i + · rw [disjointed_apply] + have : Iio (succ i) = Iic i := by + ext + simp only [mem_Iio, lt_succ_iff_eq_or_lt_of_not_isMax h, mem_Iic, le_iff_lt_or_eq, Or.comm] + rw [this, ← sup'_eq_sup, ← partialSups_apply, hf.partialSups_eq, + sdiff_sup_cancel <| hf <| le_succ i] + +end SuccOrder + +end LinearOrder + +/-! +### Functions on an arbitrary fintype +-/ + +/-- For any finite family of elements `f : ι → α`, we can find a pairwise-disjoint family `g` +bounded above by `f` and having the same supremum. This is non-canonical, depending on an arbitrary +choice of ordering of `ι`. -/ +lemma Fintype.exists_disjointed_le {ι : Type*} [Fintype ι] {f : ι → α} : + ∃ g, g ≤ f ∧ univ.sup g = univ.sup f ∧ Pairwise (Disjoint on g) := by + rcases isEmpty_or_nonempty ι with hι | hι + · -- do `ι = ∅` separately since `⊤ : Fin n` isn't defined for `n = 0` + exact ⟨f, le_rfl, rfl, Subsingleton.pairwise⟩ + let R : ι ≃ Fin _ := equivFin ι + let f' : Fin _ → α := f ∘ R.symm + have hf' : f = f' ∘ R := by ext; simp only [Function.comp_apply, Equiv.symm_apply_apply, f'] + refine ⟨disjointed f' ∘ R, ?_, ?_, ?_⟩ + · intro n + simpa only [hf'] using disjointed_le f' (R n) + · simpa only [← sup_image, image_univ_equiv, hf'] using sup_disjointed f' + · exact fun i j hij ↦ disjoint_disjointed f' (R.injective.ne hij) end GeneralizedBooleanAlgebra section CompleteBooleanAlgebra +/-! ### Complete Boolean algebras -/ + variable [CompleteBooleanAlgebra α] -theorem iSup_disjointed (f : ℕ → α) : ⨆ n, disjointed f n = ⨆ n, f n := +theorem iSup_disjointed [PartialOrder ι] [LocallyFiniteOrderBot ι] (f : ι → α) : + ⨆ i, disjointed f i = ⨆ i, f i := iSup_eq_iSup_of_partialSups_eq_partialSups (partialSups_disjointed f) -theorem disjointed_eq_inf_compl (f : ℕ → α) (n : ℕ) : disjointed f n = f n ⊓ ⨅ i < n, (f i)ᶜ := by - cases n - · rw [disjointed_zero, eq_comm, inf_eq_left] - simp_rw [le_iInf_iff] - exact fun i hi => (i.not_lt_zero hi).elim - simp_rw [disjointed_succ, partialSups_eq_biSup, sdiff_eq, compl_iSup] - congr - ext i - rw [Nat.lt_succ_iff] +theorem disjointed_eq_inf_compl [Preorder ι] [LocallyFiniteOrderBot ι] (f : ι → α) (i : ι) : + disjointed f i = f i ⊓ ⨅ j < i, (f j)ᶜ := by + simp only [disjointed_apply, Finset.sup_eq_iSup, mem_Iio, sdiff_eq, compl_iSup] end CompleteBooleanAlgebra -/-! ### Set notation variants of lemmas -/ +section Set +/-! ### Lemmas specific to set-valued functions -/ -theorem disjointed_subset (f : ℕ → Set α) (n : ℕ) : disjointed f n ⊆ f n := - disjointed_le f n +theorem disjointed_subset [Preorder ι] [LocallyFiniteOrderBot ι] (f : ι → Set α) (i : ι) : + disjointed f i ⊆ f i := + disjointed_le f i -theorem iUnion_disjointed {f : ℕ → Set α} : ⋃ n, disjointed f n = ⋃ n, f n := +theorem iUnion_disjointed [PartialOrder ι] [LocallyFiniteOrderBot ι] {f : ι → Set α} : + ⋃ i, disjointed f i = ⋃ i, f i := iSup_disjointed f -theorem disjointed_eq_inter_compl (f : ℕ → Set α) (n : ℕ) : - disjointed f n = f n ∩ ⋂ i < n, (f i)ᶜ := - disjointed_eq_inf_compl f n +theorem disjointed_eq_inter_compl [Preorder ι] [LocallyFiniteOrderBot ι] (f : ι → Set α) (i : ι) : + disjointed f i = f i ∩ ⋂ j < i, (f j)ᶜ := + disjointed_eq_inf_compl f i theorem preimage_find_eq_disjointed (s : ℕ → Set α) (H : ∀ x, ∃ n, x ∈ s n) [∀ x n, Decidable (x ∈ s n)] (n : ℕ) : (fun x => Nat.find (H x)) ⁻¹' {n} = disjointed s n := by ext x simp [Nat.find_eq_iff, disjointed_eq_inter_compl] + +end Set + +section Nat + +/-! +### Functions on `ℕ` + +(See also `Mathlib.Algebra.Order.Disjointed` for results with more algebra pre-requsisites.) +-/ + +variable [GeneralizedBooleanAlgebra α] + +@[simp] +theorem disjointed_zero (f : ℕ → α) : disjointed f 0 = f 0 := + disjointed_bot f + +end Nat diff --git a/Mathlib/Order/Interval/Finset/Box.lean b/Mathlib/Order/Interval/Finset/Box.lean index c84087a315416..9519e4a5286d7 100644 --- a/Mathlib/Order/Interval/Finset/Box.lean +++ b/Mathlib/Order/Interval/Finset/Box.lean @@ -3,10 +3,9 @@ Copyright (c) 2024 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Algebra.Order.Disjointed import Mathlib.Algebra.Order.Ring.Prod import Mathlib.Data.Int.Interval -import Mathlib.Order.Disjointed -import Mathlib.Tactic.AdaptationNote import Mathlib.Tactic.Ring import Mathlib.Tactic.Zify @@ -37,13 +36,16 @@ def box : ℕ → Finset α := disjointed fun n ↦ Icc (-n : α) n @[simp] lemma box_zero : (box 0 : Finset α) = {0} := by simp [box] lemma box_succ_eq_sdiff (n : ℕ) : - box (n + 1) = Icc (-n.succ : α) n.succ \ Icc (-n) n := Icc_neg_mono.disjointed_succ _ + box (n + 1) = Icc (-n.succ : α) n.succ \ Icc (-n) n := by + rw [box, Icc_neg_mono.disjointed_add_one] + simp only [Nat.cast_add_one, Nat.succ_eq_add_one] lemma disjoint_box_succ_prod (n : ℕ) : Disjoint (box (n + 1)) (Icc (-n : α) n) := by rw [box_succ_eq_sdiff]; exact disjoint_sdiff_self_left @[simp] lemma box_succ_union_prod (n : ℕ) : - box (n + 1) ∪ Icc (-n : α) n = Icc (-n.succ : α) n.succ := Icc_neg_mono.disjointed_succ_sup _ + box (n + 1) ∪ Icc (-n : α) n = Icc (-n.succ : α) n.succ := + Icc_neg_mono.disjointed_add_one_sup _ lemma box_succ_disjUnion (n : ℕ) : (box (n + 1)).disjUnion (Icc (-n : α) n) (disjoint_box_succ_prod _) = From 46d1f440f43842892c342d49913ca45cd757f39a Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Tue, 21 Jan 2025 20:44:01 +0000 Subject: [PATCH 392/681] feat(Topology/Algebra/Algebra/Equiv): continuous algebra equivs (#20609) From FLT. Written by Salvatore Mercuri. --- Mathlib.lean | 1 + Mathlib/Topology/Algebra/Algebra/Equiv.lean | 296 ++++++++++++++++++++ 2 files changed, 297 insertions(+) create mode 100644 Mathlib/Topology/Algebra/Algebra/Equiv.lean diff --git a/Mathlib.lean b/Mathlib.lean index 4fe37ad19e493..597f91cd38d8d 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5132,6 +5132,7 @@ import Mathlib.Testing.Plausible.Testable import Mathlib.Topology.AlexandrovDiscrete import Mathlib.Topology.Algebra.Affine import Mathlib.Topology.Algebra.Algebra +import Mathlib.Topology.Algebra.Algebra.Equiv import Mathlib.Topology.Algebra.Algebra.Rat import Mathlib.Topology.Algebra.Category.ProfiniteGrp.Basic import Mathlib.Topology.Algebra.Category.ProfiniteGrp.Limits diff --git a/Mathlib/Topology/Algebra/Algebra/Equiv.lean b/Mathlib/Topology/Algebra/Algebra/Equiv.lean new file mode 100644 index 0000000000000..0a5464a1c04ae --- /dev/null +++ b/Mathlib/Topology/Algebra/Algebra/Equiv.lean @@ -0,0 +1,296 @@ +/- +Copyright (c) 2024 Salvatore Mercuri. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Salvatore Mercuri +-/ +import Mathlib.Topology.Algebra.Algebra + +/-! +# Isomorphisms of topological algebras + +This file contains an API for `ContinuousAlgEquiv R A B`, the type of +continuous `R`-algebra isomorphisms with continuous inverses. Here `R` is a +commutative (semi)ring, and `A` and `B` are `R`-algebras with topologies. + +## Main definitions + +Let `R` be a commutative semiring and let `A` and `B` be `R`-algebras which +are also topological spaces. + +* `ContinuousAlgEquiv R A B`: the type of continuous `R`-algebra isomorphisms + from `A` to `B` with continuous inverses. + +## Notations + +`A ≃A[R] B` : notation for `ContinuousAlgEquiv R A B`. + +## Tags + +* continuous, isomorphism, algebra +-/ + +open scoped Topology + + +/-- +`ContinuousAlgEquiv R A B`, with notation `A ≃A[R] B`, is the type of bijections +between the topological `R`-algebras `A` and `B` which are both homeomorphisms +and `R`-algebra isomorphisms. +-/ +structure ContinuousAlgEquiv (R A B : Type*) [CommSemiring R] + [Semiring A] [TopologicalSpace A] [Semiring B] [TopologicalSpace B] [Algebra R A] + [Algebra R B] extends A ≃ₐ[R] B, A ≃ₜ B + +@[inherit_doc] +notation:50 A " ≃A[" R "]" B => ContinuousAlgEquiv R A B + +attribute [nolint docBlame] ContinuousAlgEquiv.toHomeomorph + +/-- +`ContinuousAlgEquivClass F R A B` states that `F` is a type of topological algebra + structure-preserving equivalences. You should extend this class when you + extend `ContinuousAlgEquiv`. +-/ +class ContinuousAlgEquivClass (F : Type*) (R A B : outParam Type*) [CommSemiring R] + [Semiring A] [TopologicalSpace A] [Semiring B] [TopologicalSpace B] + [Algebra R A] [Algebra R B] [EquivLike F A B] + extends AlgEquivClass F R A B, HomeomorphClass F A B : Prop + +namespace ContinuousAlgEquiv + +variable {R A B C : Type*} + [CommSemiring R] [Semiring A] [TopologicalSpace A] [Semiring B] + [TopologicalSpace B] [Semiring C] [TopologicalSpace C] [Algebra R A] [Algebra R B] + [Algebra R C] + +/-- The natural coercion from a continuous algebra isomorphism to a continuous +algebra morphism. -/ +@[coe] +def toContinuousAlgHom (e : A ≃A[R] B) : A →A[R] B where + __ := e.toAlgHom + cont := e.continuous_toFun + +instance coe : Coe (A ≃A[R] B) (A →A[R] B) := ⟨toContinuousAlgHom⟩ + +instance equivLike : EquivLike (A ≃A[R] B) A B where + coe f := f.toFun + inv f := f.invFun + coe_injective' f g h₁ h₂ := by + cases' f with f' _ + cases' g with g' _ + rcases f' with ⟨⟨_, _⟩, _⟩ + rcases g' with ⟨⟨_, _⟩, _⟩ + congr + left_inv f := f.left_inv + right_inv f := f.right_inv + +instance continuousAlgEquivClass : ContinuousAlgEquivClass (A ≃A[R] B) R A B where + map_add f := f.map_add' + map_mul f := f.map_mul' + commutes f := f.commutes' + map_continuous := continuous_toFun + inv_continuous := continuous_invFun + +theorem coe_apply (e : A ≃A[R] B) (a : A) : (e : A →A[R] B) a = e a := rfl + +@[simp] +theorem coe_coe (e : A ≃A[R] B) : ⇑(e : A →A[R] B) = e := rfl + +theorem toAlgEquiv_injective : Function.Injective (toAlgEquiv : (A ≃A[R] B) → A ≃ₐ[R] B) := by + rintro ⟨e, _, _⟩ ⟨e', _, _⟩ rfl + rfl + +@[ext] +theorem ext {f g : A ≃A[R] B} (h : ⇑f = ⇑g) : f = g := + toAlgEquiv_injective <| AlgEquiv.ext <| congr_fun h + +theorem coe_injective : Function.Injective ((↑) : (A ≃A[R] B) → A →A[R] B) := + fun _ _ h => ext <| funext <| ContinuousAlgHom.ext_iff.1 h + +@[simp] +theorem coe_inj {f g : A ≃A[R] B} : (f : A →A[R] B) = g ↔ f = g := + coe_injective.eq_iff + +@[simp] +theorem coe_toAlgEquiv (e : A ≃A[R] B) : ⇑e.toAlgEquiv = e := rfl + +theorem isOpenMap (e : A ≃A[R] B) : IsOpenMap e := + e.toHomeomorph.isOpenMap + +theorem image_closure (e : A ≃A[R] B) (S : Set A) : e '' closure S = closure (e '' S) := + e.toHomeomorph.image_closure S + +theorem preimage_closure (e : A ≃A[R] B) (S : Set B) : e ⁻¹' closure S = closure (e ⁻¹' S) := + e.toHomeomorph.preimage_closure S + +@[simp] +theorem isClosed_image (e : A ≃A[R] B) {S : Set A} : IsClosed (e '' S) ↔ IsClosed S := + e.toHomeomorph.isClosed_image + +theorem map_nhds_eq (e : A ≃A[R] B) (a : A) : Filter.map e (𝓝 a) = 𝓝 (e a) := + e.toHomeomorph.map_nhds_eq a + +theorem map_eq_zero_iff (e : A ≃A[R] B) {a : A} : e a = 0 ↔ a = 0 := + e.toAlgEquiv.toLinearEquiv.map_eq_zero_iff + +attribute [continuity] + ContinuousAlgEquiv.continuous_invFun ContinuousAlgEquiv.continuous_toFun + +@[fun_prop] +theorem continuous (e : A ≃A[R] B) : Continuous e := e.continuous_toFun + +theorem continuousOn (e : A ≃A[R] B) {S : Set A} : ContinuousOn e S := + e.continuous.continuousOn + +theorem continuousAt (e : A ≃A[R] B) {a : A} : ContinuousAt e a := + e.continuous.continuousAt + +theorem continuousWithinAt (e : A ≃A[R] B) {S : Set A} {a : A} : + ContinuousWithinAt e S a := + e.continuous.continuousWithinAt + +theorem comp_continuous_iff {α : Type*} [TopologicalSpace α] (e : A ≃A[R] B) {f : α → A} : + Continuous (e ∘ f) ↔ Continuous f := + e.toHomeomorph.comp_continuous_iff + +theorem comp_continuous_iff' {β : Type*} [TopologicalSpace β] (e : A ≃A[R] B) {g : B → β} : + Continuous (g ∘ e) ↔ Continuous g := + e.toHomeomorph.comp_continuous_iff' + +variable (R A) + +/-- The identity isomorphism as a continuous `R`-algebra equivalence. -/ +@[refl] +def refl : A ≃A[R] A where + __ := AlgEquiv.refl + continuous_toFun := continuous_id + continuous_invFun := continuous_id + +@[simp] +theorem refl_apply (a : A) : refl R A a = a := rfl + +@[simp] +theorem coe_refl : refl R A = ContinuousAlgHom.id R A := rfl + +@[simp] +theorem coe_refl' : ⇑(refl R A) = id := rfl + +variable {R A} + +/-- The inverse of a continuous algebra equivalence. -/ +@[symm] +def symm (e : A ≃A[R] B) : B ≃A[R] A where + __ := e.toAlgEquiv.symm + continuous_toFun := e.continuous_invFun + continuous_invFun := e.continuous_toFun + +@[simp] +theorem apply_symm_apply (e : A ≃A[R] B) (b : B) : e (e.symm b) = b := + e.1.right_inv b + +@[simp] +theorem symm_apply_apply (e : A ≃A[R] B) (a : A) : e.symm (e a) = a := + e.1.left_inv a + +@[simp] +theorem symm_image_image (e : A ≃A[R] B) (S : Set A) : e.symm '' (e '' S) = S := + e.toEquiv.symm_image_image S + +@[simp] +theorem image_symm_image (e : A ≃A[R] B) (S : Set B) : e '' (e.symm '' S) = S := + e.symm.symm_image_image S + +@[simp] +theorem symm_toAlgEquiv (e : A ≃A[R] B) : e.symm.toAlgEquiv = e.toAlgEquiv.symm := rfl + +@[simp] +theorem symm_toHomeomorph (e : A ≃A[R] B) : e.symm.toHomeomorph = e.toHomeomorph.symm := rfl + +theorem symm_map_nhds_eq (e : A ≃A[R] B) (a : A) : Filter.map e.symm (𝓝 (e a)) = 𝓝 a := + e.toHomeomorph.symm_map_nhds_eq a + +/-- The composition of two continuous algebra equivalences. -/ +@[trans] +def trans (e₁ : A ≃A[R] B) (e₂ : B ≃A[R] C) : A ≃A[R] C where + __ := e₁.toAlgEquiv.trans e₂.toAlgEquiv + continuous_toFun := e₂.continuous_toFun.comp e₁.continuous_toFun + continuous_invFun := e₁.continuous_invFun.comp e₂.continuous_invFun + +@[simp] +theorem trans_toAlgEquiv (e₁ : A ≃A[R] B) (e₂ : B ≃A[R] C) : + (e₁.trans e₂).toAlgEquiv = e₁.toAlgEquiv.trans e₂.toAlgEquiv := + rfl + +@[simp] +theorem trans_apply (e₁ : A ≃A[R] B) (e₂ : B ≃A[R] C) (a : A) : + (e₁.trans e₂) a = e₂ (e₁ a) := + rfl + +@[simp] +theorem symm_trans_apply (e₁ : B ≃A[R] A) (e₂ : C ≃A[R] B) (a : A) : + (e₂.trans e₁).symm a = e₂.symm (e₁.symm a) := + rfl + +theorem comp_coe (e₁ : A ≃A[R] B) (e₂ : B ≃A[R] C) : + e₂.toAlgHom.comp e₁.toAlgHom = e₁.trans e₂ := by + rfl + +@[simp high] +theorem coe_comp_coe_symm (e : A ≃A[R] B) : + e.toContinuousAlgHom.comp e.symm = ContinuousAlgHom.id R B := + ContinuousAlgHom.ext e.apply_symm_apply + +@[simp high] +theorem coe_symm_comp_coe (e : A ≃A[R] B) : + e.symm.toContinuousAlgHom.comp e = ContinuousAlgHom.id R A := + ContinuousAlgHom.ext e.symm_apply_apply + +@[simp] +theorem symm_comp_self (e : A ≃A[R] B) : (e.symm : B → A) ∘ e = id := by + exact funext <| e.symm_apply_apply + +@[simp] +theorem self_comp_symm (e : A ≃A[R] B) : (e : A → B) ∘ e.symm = id := + funext <| e.apply_symm_apply + +@[simp] +theorem symm_symm (e : A ≃A[R] B) : e.symm.symm = e := rfl + +@[simp] +theorem refl_symm : (refl R A).symm = refl R A := rfl + +theorem symm_symm_apply (e : A ≃A[R] B) (a : A) : e.symm.symm a = e a := rfl + +theorem symm_apply_eq (e : A ≃A[R] B) {a : A} {b : B} : e.symm b = a ↔ b = e a := + e.toEquiv.symm_apply_eq + +theorem eq_symm_apply (e : A ≃A[R] B) {a : A} {b : B} : a = e.symm b ↔ e a = b := + e.toEquiv.eq_symm_apply + +theorem image_eq_preimage (e : A ≃A[R] B) (S : Set A) : e '' S = e.symm ⁻¹' S := + e.toEquiv.image_eq_preimage S + +theorem image_symm_eq_preimage (e : A ≃A[R] B) (S : Set B) : e.symm '' S = e ⁻¹' S := by + rw [e.symm.image_eq_preimage, e.symm_symm] + +@[simp] +theorem symm_preimage_preimage (e : A ≃A[R] B) (S : Set B) : e.symm ⁻¹' (e ⁻¹' S) = S := + e.toEquiv.symm_preimage_preimage S + +@[simp] +theorem preimage_symm_preimage (e : A ≃A[R] B) (S : Set A) : e ⁻¹' (e.symm ⁻¹' S) = S := + e.symm.symm_preimage_preimage S + +theorem isUniformEmbedding {E₁ E₂ : Type*} [UniformSpace E₁] [UniformSpace E₂] [Ring E₁] + [UniformAddGroup E₁] [Algebra R E₁] [Ring E₂] [UniformAddGroup E₂] [Algebra R E₂] + (e : E₁ ≃A[R] E₂) : IsUniformEmbedding e := + e.toAlgEquiv.isUniformEmbedding e.toContinuousAlgHom.uniformContinuous + e.symm.toContinuousAlgHom.uniformContinuous + +theorem _root_.AlgEquiv.isUniformEmbedding {E₁ E₂ : Type*} [UniformSpace E₁] [UniformSpace E₂] + [Ring E₁] [UniformAddGroup E₁] [Algebra R E₁] [Ring E₂] [UniformAddGroup E₂] [Algebra R E₂] + (e : E₁ ≃ₐ[R] E₂) (h₁ : Continuous e) (h₂ : Continuous e.symm) : + IsUniformEmbedding e := + ContinuousAlgEquiv.isUniformEmbedding { e with continuous_toFun := h₁ } + +end ContinuousAlgEquiv From ec5d1d8e277005586c3ca983680ead5416c79888 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Tue, 21 Jan 2025 21:03:22 +0000 Subject: [PATCH 393/681] feat(CategoryTheory): Functor.prod and Functor.prod' are final (#20841) Co-authored-by: Markus Himmel --- Mathlib/CategoryTheory/Filtered/Final.lean | 18 +++++++++++++----- Mathlib/CategoryTheory/Limits/Final.lean | 13 +++++++++++++ Mathlib/CategoryTheory/Limits/Sifted.lean | 12 +++++++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Mathlib/CategoryTheory/Filtered/Final.lean b/Mathlib/CategoryTheory/Filtered/Final.lean index 69bd8fd66b993..24e561db7288e 100644 --- a/Mathlib/CategoryTheory/Filtered/Final.lean +++ b/Mathlib/CategoryTheory/Filtered/Final.lean @@ -5,7 +5,7 @@ Authors: Markus Himmel -/ import Mathlib.CategoryTheory.Filtered.Connected import Mathlib.CategoryTheory.Limits.TypesFiltered -import Mathlib.CategoryTheory.Limits.Final +import Mathlib.CategoryTheory.Limits.Sifted /-! # Final functors with filtered (co)domain @@ -298,26 +298,34 @@ theorem Functor.initial_iff_isCofiltered_costructuredArrow [IsCofilteredOrEmpty /-- If `C` is filtered, then the structured arrow category on the diagonal functor `C ⥤ C × C` is filtered as well. -/ -instance [IsFiltered C] (X : C × C) : IsFiltered (StructuredArrow X (diag C)) := by +instance [IsFilteredOrEmpty C] (X : C × C) : IsFiltered (StructuredArrow X (diag C)) := by haveI : ∀ Y, IsFiltered (StructuredArrow Y (Under.forget X.1)) := by rw [← final_iff_isFiltered_structuredArrow (Under.forget X.1)] infer_instance apply IsFiltered.of_equivalence (StructuredArrow.ofDiagEquivalence X).symm /-- The diagonal functor on any filtered category is final. -/ -instance Functor.final_diag_of_isFiltered [IsFiltered C] : Final (Functor.diag C) := +instance Functor.final_diag_of_isFiltered [IsFilteredOrEmpty C] : Final (Functor.diag C) := final_of_isFiltered_structuredArrow _ +-- Adding this instance causes performance problems elsewhere, even with low priority +theorem IsFilteredOrEmpty.isSiftedOrEmpty [IsFilteredOrEmpty C] : IsSiftedOrEmpty C := + Functor.final_diag_of_isFiltered + +-- Adding this instance causes performance problems elsewhere, even with low priority +attribute [local instance] IsFiltered.nonempty in +theorem IsFiltered.isSifted [IsFiltered C] : IsSifted C where + /-- If `C` is cofiltered, then the costructured arrow category on the diagonal functor `C ⥤ C × C` is cofiltered as well. -/ -instance [IsCofiltered C] (X : C × C) : IsCofiltered (CostructuredArrow (diag C) X) := by +instance [IsCofilteredOrEmpty C] (X : C × C) : IsCofiltered (CostructuredArrow (diag C) X) := by haveI : ∀ Y, IsCofiltered (CostructuredArrow (Over.forget X.1) Y) := by rw [← initial_iff_isCofiltered_costructuredArrow (Over.forget X.1)] infer_instance apply IsCofiltered.of_equivalence (CostructuredArrow.ofDiagEquivalence X).symm /-- The diagonal functor on any cofiltered category is initial. -/ -instance Functor.initial_diag_of_isFiltered [IsCofiltered C] : Initial (Functor.diag C) := +instance Functor.initial_diag_of_isFiltered [IsCofilteredOrEmpty C] : Initial (Functor.diag C) := initial_of_isCofiltered_costructuredArrow _ /-- If `C` is filtered, then every functor `F : C ⥤ Discrete PUnit` is final. -/ diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index 5124dc554a97f..f019212af5a48 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -1027,4 +1027,17 @@ instance Grothendieck.final_pre [hG : Final G] : (Grothendieck.pre F G).Final := end Grothendieck +section Prod + +variable {C : Type u₁} [Category.{v₁} C] +variable {D : Type u₂} [Category.{v₂} D] +variable {C' : Type u₃} [Category.{v₃} C'] +variable {D' : Type u₄} [Category.{v₄} D'] +variable (F : C ⥤ D) (G : C' ⥤ D') + +instance [F.Final] [G.Final] : (F.prod G).Final where + out := fun ⟨d, d'⟩ => isConnected_of_equivalent (StructuredArrow.prodEquivalence d d' F G).symm + +end Prod + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Sifted.lean b/Mathlib/CategoryTheory/Limits/Sifted.lean index 8f5721d4f8dae..7baf9a4e2a34b 100644 --- a/Mathlib/CategoryTheory/Limits/Sifted.lean +++ b/Mathlib/CategoryTheory/Limits/Sifted.lean @@ -20,7 +20,7 @@ preserves finite products. - [*Algebraic Theories*, Chapter 2.][Adamek_Rosicky_Vitale_2010] -/ -universe w v v₁ u u₁ +universe w v v₁ v₂ u u₁ u₂ namespace CategoryTheory @@ -101,4 +101,14 @@ end IsSifted end +section + +variable {C : Type u} [Category.{v} C] [IsSiftedOrEmpty C] {D : Type u₁} [Category.{v₁} D] + {D' : Type u₂} [Category.{v₂} D'] (F : C ⥤ D) (G : C ⥤ D') + +instance [F.Final] [G.Final] : (F.prod' G).Final := + show (diag C ⋙ F.prod G).Final from final_comp _ _ + +end + end CategoryTheory From e3ce54eedb2ab716b7f62aecc31b0308cb7719b8 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Tue, 21 Jan 2025 21:33:29 +0000 Subject: [PATCH 394/681] feat(Analysis): relate summable and multipliable sequences using log (#16546) Add some results about transforming summable sequences `f n` indexed by natural numbers , into multipliable sequeces of the form `1 + f n` using complex and real logs. Co-authored-by: Chris Birkbeck --- Mathlib.lean | 1 + .../Analysis/NormedSpace/FunctionSeries.lean | 8 ++ .../SpecialFunctions/Complex/Log.lean | 74 ++++++------------- .../SpecialFunctions/Log/Summable.lean | 68 +++++++++++++++++ 4 files changed, 100 insertions(+), 51 deletions(-) create mode 100644 Mathlib/Analysis/SpecialFunctions/Log/Summable.lean diff --git a/Mathlib.lean b/Mathlib.lean index 597f91cd38d8d..7dad5445f3f6c 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1587,6 +1587,7 @@ import Mathlib.Analysis.SpecialFunctions.Log.ENNRealLogExp import Mathlib.Analysis.SpecialFunctions.Log.ERealExp import Mathlib.Analysis.SpecialFunctions.Log.Monotone import Mathlib.Analysis.SpecialFunctions.Log.NegMulLog +import Mathlib.Analysis.SpecialFunctions.Log.Summable import Mathlib.Analysis.SpecialFunctions.NonIntegrable import Mathlib.Analysis.SpecialFunctions.OrdinaryHypergeometric import Mathlib.Analysis.SpecialFunctions.PolarCoord diff --git a/Mathlib/Analysis/NormedSpace/FunctionSeries.lean b/Mathlib/Analysis/NormedSpace/FunctionSeries.lean index 99a048f2d05da..c53248e341e13 100644 --- a/Mathlib/Analysis/NormedSpace/FunctionSeries.lean +++ b/Mathlib/Analysis/NormedSpace/FunctionSeries.lean @@ -72,6 +72,14 @@ theorem tendstoUniformlyOn_tsum_of_cofinite_eventually {ι : Type*} {f : ι → have : ¬ i ∈ hN.toFinset := fun hg ↦ hi (Finset.union_subset_left hn hg) aesop +theorem tendstoUniformlyOn_tsum_nat_eventually {α F : Type*} [NormedAddCommGroup F] + [CompleteSpace F] {f : ℕ → α → F} {u : ℕ → ℝ} (hu : Summable u) {s : Set α} + (hfu : ∀ᶠ n in atTop, ∀ x ∈ s, ‖f n x‖ ≤ u n) : + TendstoUniformlyOn (fun N x => ∑ n ∈ Finset.range N, f n x) + (fun x => ∑' n, f n x) atTop s := + fun v hv ↦ tendsto_finset_range.eventually <| + tendstoUniformlyOn_tsum_of_cofinite_eventually hu (Nat.cofinite_eq_atTop ▸ hfu) v hv + /-- An infinite sum of functions with summable sup norm is the uniform limit of its partial sums. Version with general index set. -/ theorem tendstoUniformly_tsum {f : α → β → F} (hu : Summable u) (hfu : ∀ n x, ‖f n x‖ ≤ u n) : diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean index 60934d34bd710..36a17281d89b1 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean @@ -255,62 +255,34 @@ variable {α ι: Type*} open Real -lemma Real.HasSum_rexp_HasProd (f : ι → α → ℝ) (hfn : ∀ x n, 0 < f n x) - (hf : ∀ x : α, HasSum (fun n => log (f n x)) (∑' i, log (f i x))) (a : α) : - HasProd (fun b ↦ f b a) (∏' n : ι, (f n a)) := by - have : HasProd (fun b ↦ f b a) ((rexp ∘ fun a ↦ ∑' (n : ι), log (f n a)) a) := by - apply ((hf a).rexp).congr - intro _ - congr - exact funext fun x ↦ exp_log (hfn a x) - rwa [HasProd.tprod_eq this] - - -/--The exponential of a infinite sum of real logs (which converges absolutely) is an infinite -product.-/ -lemma Real.rexp_tsum_eq_tprod (f : ι → α → ℝ) (hfn : ∀ x n, 0 < f n x) - (hf : ∀ x : α, Summable fun n => log ((f n x))) : - (rexp ∘ (fun a : α => (∑' n : ι, log (f n a)))) = (fun a : α => ∏' n : ι, (f n a)) := by - ext a - apply (HasProd.tprod_eq ?_).symm - apply ((hf a).hasSum.rexp).congr - intro _ - congr - exact funext fun x ↦ exp_log (hfn a x) - -lemma Real.summable_cexp_multipliable (f : ι → α → ℝ) (hfn : ∀ x n, 0 < f n x) - (hf : ∀ x : α, Summable fun n => log (f n x)) (a : α) : Multipliable fun b ↦ f b a := by - have := (Real.HasSum_rexp_HasProd f hfn fun a => (hf a).hasSum) a - use (∏' n : ι, (f n a)) +lemma Real.hasProd_of_hasSum_log {f : ι → ℝ} (hfn : ∀ n, 0 < f n) {a : ℝ} + (hf : HasSum (fun n => log (f n)) a) : HasProd f (rexp a) := + hf.rexp.congr (by simp [exp_log, hfn]) + +lemma Real.multipliable_of_summable_log (f : ι → ℝ) (hfn : ∀ n, 0 < f n) + (hf : Summable fun n => log (f n)) : Multipliable f := + ⟨_, Real.hasProd_of_hasSum_log hfn hf.hasSum⟩ + +/-- The exponential of a infinite sum of real logs (which converges absolutely) is an infinite +product. -/ +lemma Real.rexp_tsum_eq_tprod (f : ι → ℝ) (hfn : ∀ n, 0 < f n) + (hf : Summable fun n => log (f n)) : rexp (∑' n : ι, log (f n)) = ∏' n : ι, f n := + (Real.hasProd_of_hasSum_log hfn hf.hasSum).tprod_eq.symm open Complex -lemma Complex.HasSum_cexp_HasProd (f : ι → α → ℂ) (hfn : ∀ x n, f n x ≠ 0) - (hf : ∀ x : α, HasSum (fun n => log (f n x)) (∑' i, log (f i x))) (a : α) : - HasProd (fun b ↦ f b a) (∏' n : ι, (f n a)) := by - have : HasProd (fun b ↦ f b a) ((cexp ∘ fun a ↦ ∑' (n : ι), log (f n a)) a) := by - apply ((hf a).cexp).congr - intro _ - congr - exact funext fun x ↦ exp_log (hfn a x) - rwa [HasProd.tprod_eq this] - -lemma Complex.summable_cexp_multipliable (f : ι → α → ℂ) (hfn : ∀ x n, f n x ≠ 0) - (hf : ∀ x : α, Summable fun n => log (f n x)) (a : α) : - Multipliable fun b ↦ f b a := by - have := (Complex.HasSum_cexp_HasProd f hfn fun a => (hf a).hasSum) a - use (∏' n : ι, (f n a)) +lemma Complex.hasProd_of_hasSum_log (f : ι → ℂ) (hfn : ∀ n, f n ≠ 0) {a : ℂ} + (hf : HasSum (fun n => log (f n)) a) : HasProd (fun b ↦ f b) (cexp a) := + hf.cexp.congr (by simp [exp_log, hfn]) + +lemma Complex.multipliable_of_summable_log (f : ι → ℂ) (hfn : ∀ n, f n ≠ 0) + (hf : Summable fun n => log (f n)) : Multipliable fun b ↦ f b := + ⟨_, Complex.hasProd_of_hasSum_log _ hfn hf.hasSum⟩ /--The exponential of a infinite sum of comples logs (which converges absolutely) is an infinite product.-/ -lemma Complex.cexp_tsum_eq_tprod (f : ι → α → ℂ) (hfn : ∀ x n, f n x ≠ 0) - (hf : ∀ x : α, Summable fun n => log (f n x)) : - (cexp ∘ (fun a : α => (∑' n : ι, log (f n a)))) = fun a : α => ∏' n : ι, f n a := by - ext a - apply (HasProd.tprod_eq ?_).symm - apply ((hf a).hasSum.cexp).congr - intro _ - congr - exact funext fun x ↦ exp_log (hfn a x) +lemma Complex.cexp_tsum_eq_tprod (f : ι → ℂ) (hfn : ∀ n, f n ≠ 0) + (hf : Summable fun n => log (f n)) : (cexp ((∑' n : ι, log (f n )))) = ∏' n : ι, f n := + (Complex.hasProd_of_hasSum_log _ hfn hf.hasSum).tprod_eq.symm end tsum_tprod diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean b/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean new file mode 100644 index 0000000000000..a814fdc2d846e --- /dev/null +++ b/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean @@ -0,0 +1,68 @@ +/- +Copyright (c) 2024 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ + +import Mathlib.Analysis.SpecialFunctions.Complex.LogBounds +import Mathlib.Analysis.NormedSpace.FunctionSeries + +/-! +# Summable logs + +We give conditions under which the logarithms of a summble sequence is summable. We also give some +results about when the sums converge uniformly. + +TODO: Generalise the indexing set from ℕ to some arbitrary type, but this needs +Summable.tendsto_atTop_zero to first be done. Also remove hff from +`Complex.multipliable_one_add_of_summable` once we have vanishing/non-vanishing results for infinite +products. + +-/ + +open Filter Function Complex Real + +open scoped Interval Topology BigOperators Nat Classical Complex + +lemma Complex.summable_log_one_add_of_summable {f : ℕ → ℂ} (hf : Summable f) : + Summable (fun n : ℕ => Complex.log (1 + f n)) := by + have hff := Summable.const_smul ((3 : ℝ) / 2) (summable_norm_iff.mpr hf) + have := Metric.tendsto_atTop.mp (Summable.tendsto_atTop_zero ((summable_norm_iff.mpr hf))) + apply Summable.of_norm_bounded_eventually_nat (fun n => 3/2 * Complex.abs (f n)) hff + simp only [smul_eq_mul, gt_iff_lt, ge_iff_le, dist_zero_right, Real.norm_eq_abs, Complex.abs_abs, + Complex.norm_eq_abs, eventually_atTop] at * + obtain ⟨n, hn⟩ := this (1/2) (one_half_pos) + exact Exists.intro n fun m hm ↦ norm_log_one_add_half_le_self (LT.lt.le (hn m hm)) + +lemma Real.summable_log_one_add_of_summable {f : ℕ → ℝ} (hf : Summable f) : + Summable (fun n : ℕ => log (1 + |f n|)) := by + have : Summable (fun n ↦ Complex.ofRealCLM (log (1 + |f n|))) := by + convert Complex.summable_log_one_add_of_summable (Complex.ofRealCLM.summable hf.norm) with x + rw [ofRealCLM_apply, ofReal_log (by positivity)] + simp only [ofReal_add, ofReal_one, norm_eq_abs, ofRealCLM_apply] + convert Complex.reCLM.summable this + +lemma Complex.multipliable_one_add_of_summable (f : ℕ → ℂ) (hf : Summable f) + (hff : ∀ n : ℕ, 1 + f n ≠ 0) : Multipliable (fun n : ℕ => 1 + f n) := by + refine Complex.multipliable_of_summable_log (fun n => 1 + f n) (by simpa) ?_ + simpa only [forall_const] using Complex.summable_log_one_add_of_summable hf + +lemma Real.multipliable_one_add_of_summable (f : ℕ → ℝ) (hf : Summable f) : + Multipliable (fun n : ℕ => 1 + |f n|) := by + refine Real.multipliable_of_summable_log (fun n => 1 + |f n|) (fun _ ↦ by positivity) ?_ + simpa only [forall_const] using Real.summable_log_one_add_of_summable hf + +lemma Complex.tendstoUniformlyOn_tsum_nat_log_one_add {α : Type*} {f : ℕ → α → ℂ} (K : Set α) + {u : ℕ → ℝ} (hu : Summable u) (h : ∀ᶠ n in atTop, ∀ x ∈ K, ‖f n x‖ ≤ u n) : + TendstoUniformlyOn (fun (n : ℕ) (a : α) => ∑ i in Finset.range n, + (Complex.log (1 + f i a))) (fun a => ∑' i : ℕ, Complex.log (1 + f i a)) atTop K := by + apply tendstoUniformlyOn_tsum_nat_eventually (hu.mul_left (3/2)) + obtain ⟨N, hN⟩ := Metric.tendsto_atTop.mp (Summable.tendsto_atTop_zero hu) (1/2) (one_half_pos) + simp only [Complex.norm_eq_abs, eventually_atTop, ge_iff_le] at * + obtain ⟨N2, hN2⟩ := h + refine ⟨max N N2, fun n hn x hx => ?_⟩ + apply le_trans (Complex.norm_log_one_add_half_le_self (z := (f n x)) ?_) + · simp only [Complex.norm_eq_abs, Nat.ofNat_pos, div_pos_iff_of_pos_left, mul_le_mul_left] + exact hN2 n (le_of_max_le_right hn) x hx + · apply le_trans (le_trans (hN2 n (le_of_max_le_right hn) x hx) + (by simpa using Real.le_norm_self (u n))) (hN n (le_of_max_le_left hn)).le From efc500d4fdb34a129b809f6a9f8c1fc4c079e077 Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 22 Jan 2025 01:51:20 +0000 Subject: [PATCH 395/681] chore(CI): remove `issue_number` from `:closed-pr:` action (#20925) This cleanup was planned [here](https://github.com/leanprover-community/mathlib4/pull/20902#discussion_r1923761803). I wanted to make sure that `pull_request.number` was the correct github name for the... PR number! It is, so `issue.number` can be removed. --- .github/workflows/zulip_emoji_closed_pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/zulip_emoji_closed_pr.yaml b/.github/workflows/zulip_emoji_closed_pr.yaml index f07fe1751bb78..43076e2433e87 100644 --- a/.github/workflows/zulip_emoji_closed_pr.yaml +++ b/.github/workflows/zulip_emoji_closed_pr.yaml @@ -49,4 +49,4 @@ jobs: ZULIP_EMAIL: github-mathlib4-bot@leanprover.zulipchat.com ZULIP_SITE: https://leanprover.zulipchat.com run: | - python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "closed" "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" + python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "closed" "${{ github.event.pull_request.number }}" From 338b4da1fafc6e49fa34e45fec0af173df81f84c Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Wed, 22 Jan 2025 02:01:06 +0000 Subject: [PATCH 396/681] chore(Data/Fin/Basic): split off `rev` lemmas (#20833) This PR splits out lemmas about the `Fin.rev` function from `Data.Fin.Basic`. This addresses an instance of a long file linter trigger. --- Mathlib.lean | 1 + Mathlib/Algebra/Group/Fin/Basic.lean | 2 +- Mathlib/Data/Fin/Basic.lean | 92 ---------------------- Mathlib/Data/Fin/Rev.lean | 112 +++++++++++++++++++++++++++ Mathlib/Data/Fin/Tuple/Basic.lean | 2 +- Mathlib/Order/Fin/Basic.lean | 2 +- 6 files changed, 116 insertions(+), 95 deletions(-) create mode 100644 Mathlib/Data/Fin/Rev.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7dad5445f3f6c..2eb24f819ce99 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2515,6 +2515,7 @@ import Mathlib.Data.Fin.Basic import Mathlib.Data.Fin.Fin2 import Mathlib.Data.Fin.FlagRange import Mathlib.Data.Fin.Parity +import Mathlib.Data.Fin.Rev import Mathlib.Data.Fin.SuccPred import Mathlib.Data.Fin.Tuple.Basic import Mathlib.Data.Fin.Tuple.BubbleSortInduction diff --git a/Mathlib/Algebra/Group/Fin/Basic.lean b/Mathlib/Algebra/Group/Fin/Basic.lean index 5a34b7573582a..c7fb2d5f230d9 100644 --- a/Mathlib/Algebra/Group/Fin/Basic.lean +++ b/Mathlib/Algebra/Group/Fin/Basic.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.Group.Basic import Mathlib.Algebra.NeZero import Mathlib.Data.Nat.Cast.Defs import Mathlib.Data.Nat.Defs -import Mathlib.Data.Fin.Basic +import Mathlib.Data.Fin.Rev /-! # Fin is a group diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index c4f67ec7c5759..7dc978fddb102 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -58,10 +58,6 @@ This file expands on the development in the core library. * `Fin.divNat i` : divides `i : Fin (m * n)` by `n`; * `Fin.modNat i` : takes the mod of `i : Fin (m * n)` by `n`; -### Misc definitions - -* `Fin.revPerm : Equiv.Perm (Fin n)` : `Fin.rev` as an `Equiv.Perm`, the antitone involution given - by `i ↦ n-(i+1)` -/ @@ -267,52 +263,6 @@ theorem pos_iff_ne_zero' [NeZero n] (a : Fin n) : 0 < a ↔ a ≠ 0 := by lemma cast_injective {k l : ℕ} (h : k = l) : Injective (Fin.cast h) := fun a b hab ↦ by simpa [← val_eq_val] using hab -theorem rev_involutive : Involutive (rev : Fin n → Fin n) := rev_rev - -/-- `Fin.rev` as an `Equiv.Perm`, the antitone involution `Fin n → Fin n` given by -`i ↦ n-(i+1)`. -/ -@[simps! apply symm_apply] -def revPerm : Equiv.Perm (Fin n) := - Involutive.toPerm rev rev_involutive - -theorem rev_injective : Injective (@rev n) := - rev_involutive.injective - -theorem rev_surjective : Surjective (@rev n) := - rev_involutive.surjective - -theorem rev_bijective : Bijective (@rev n) := - rev_involutive.bijective - -@[simp] -theorem revPerm_symm : (@revPerm n).symm = revPerm := - rfl - -theorem cast_rev (i : Fin n) (h : n = m) : - i.rev.cast h = (i.cast h).rev := by - subst h; simp - -theorem rev_eq_iff {i j : Fin n} : rev i = j ↔ i = rev j := by - rw [← rev_inj, rev_rev] - -theorem rev_ne_iff {i j : Fin n} : rev i ≠ j ↔ i ≠ rev j := rev_eq_iff.not - -theorem rev_lt_iff {i j : Fin n} : rev i < j ↔ rev j < i := by - rw [← rev_lt_rev, rev_rev] - -theorem rev_le_iff {i j : Fin n} : rev i ≤ j ↔ rev j ≤ i := by - rw [← rev_le_rev, rev_rev] - -theorem lt_rev_iff {i j : Fin n} : i < rev j ↔ j < rev i := by - rw [← rev_lt_rev, rev_rev] - -theorem le_rev_iff {i j : Fin n} : i ≤ rev j ↔ j ≤ rev i := by - rw [← rev_le_rev, rev_rev] - --- Porting note: this is now syntactically equal to `val_last` - -@[simp] theorem val_rev_zero [NeZero n] : ((rev 0 : Fin n) : ℕ) = n.pred := rfl - theorem last_pos' [NeZero n] : 0 < last n := n.pos_of_neZero theorem one_lt_last [NeZero n] : 1 < last (n + 1) := by @@ -908,15 +858,6 @@ theorem castPred_one [NeZero n] (h := Fin.ext_iff.not.2 one_lt_last.ne) : · exact subsingleton_one.elim _ 1 · rfl -theorem rev_pred {i : Fin (n + 1)} (h : i ≠ 0) (h' := rev_ne_iff.mpr ((rev_last _).symm ▸ h)) : - rev (pred i h) = castPred (rev i) h' := by - rw [← castSucc_inj, castSucc_castPred, ← rev_succ, succ_pred] - -theorem rev_castPred {i : Fin (n + 1)} - (h : i ≠ last n) (h' := rev_ne_iff.mpr ((rev_zero _).symm ▸ h)) : - rev (castPred i h) = pred (rev i) h' := by - rw [← succ_inj, succ_pred, ← rev_castSucc, castSucc_castPred] - theorem succ_castPred_eq_castPred_succ {a : Fin (n + 1)} (ha : a ≠ last n) (ha' := a.succ_ne_last_iff.mpr ha) : (a.castPred ha).succ = (succ a).castPred ha' := rfl @@ -1026,17 +967,6 @@ lemma succAbove_castPred_of_le (p i : Fin (n + 1)) (h : p ≤ i) (hi : i ≠ las lemma succAbove_castPred_self (p : Fin (n + 1)) (h : p ≠ last n) : succAbove p (p.castPred h) = (p.castPred h).succ := succAbove_castPred_of_le _ _ Fin.le_rfl h -lemma succAbove_rev_left (p : Fin (n + 1)) (i : Fin n) : - p.rev.succAbove i = (p.succAbove i.rev).rev := by - obtain h | h := (rev p).succ_le_or_le_castSucc i - · rw [succAbove_of_succ_le _ _ h, - succAbove_of_le_castSucc _ _ (rev_succ _ ▸ (le_rev_iff.mpr h)), rev_succ, rev_rev] - · rw [succAbove_of_le_castSucc _ _ h, - succAbove_of_succ_le _ _ (rev_castSucc _ ▸ (rev_le_iff.mpr h)), rev_castSucc, rev_rev] - -lemma succAbove_rev_right (p : Fin (n + 1)) (i : Fin n) : - p.succAbove i.rev = (p.rev.succAbove i).rev := by rw [succAbove_rev_left, rev_rev] - /-- Embedding `i : Fin n` into `Fin (n + 1)` with a hole around `p : Fin (n + 1)` never results in `p` itself -/ lemma succAbove_ne (p : Fin (n + 1)) (i : Fin n) : p.succAbove i ≠ p := by @@ -1204,11 +1134,6 @@ lemma castPred_succAbove_castPred {a : Fin (n + 2)} {b : Fin (n + 1)} (ha : a simp_rw [← castSucc_inj (b := (a.succAbove b).castPred hk), ← castSucc_succAbove_castSucc, castSucc_castPred] -/-- `rev` commutes with `succAbove`. -/ -lemma rev_succAbove (p : Fin (n + 1)) (i : Fin n) : - rev (succAbove p i) = succAbove (rev p) (rev i) := by - rw [succAbove_rev_left, rev_rev] - --@[simp] -- Porting note: can be proved by `simp` lemma one_succAbove_zero {n : ℕ} : (1 : Fin (n + 2)).succAbove 0 = 0 := by rfl @@ -1295,17 +1220,6 @@ lemma predAbove_castPred_of_le (p i : Fin (n + 1)) (h : i ≤ p) (hp : p ≠ las lemma predAbove_castPred_self (p : Fin (n + 1)) (hp : p ≠ last n) : (castPred p hp).predAbove p = castPred p hp := predAbove_castPred_of_le _ _ Fin.le_rfl hp -lemma predAbove_rev_left (p : Fin n) (i : Fin (n + 1)) : - p.rev.predAbove i = (p.predAbove i.rev).rev := by - obtain h | h := (rev i).succ_le_or_le_castSucc p - · rw [predAbove_of_succ_le _ _ h, rev_pred, - predAbove_of_le_castSucc _ _ (rev_succ _ ▸ (le_rev_iff.mpr h)), castPred_inj, rev_rev] - · rw [predAbove_of_le_castSucc _ _ h, rev_castPred, - predAbove_of_succ_le _ _ (rev_castSucc _ ▸ (rev_le_iff.mpr h)), pred_inj, rev_rev] - -lemma predAbove_rev_right (p : Fin n) (i : Fin (n + 1)) : - p.predAbove i.rev = (p.rev.predAbove i).rev := by rw [predAbove_rev_left, rev_rev] - @[simp] lemma predAbove_right_zero [NeZero n] {i : Fin n} : predAbove (i : Fin n) 0 = 0 := by cases n · exact i.elim0 @@ -1379,10 +1293,6 @@ lemma predAbove_succAbove (p : Fin n) (i : Fin n) : p.predAbove ((castSucc p).su castSucc_pred_eq_pred_castSucc] · rw [predAbove_of_le_castSucc _ _ h, predAbove_castSucc_of_le _ _ h, castSucc_castPred] -/-- `rev` commutes with `predAbove`. -/ -lemma rev_predAbove {n : ℕ} (p : Fin n) (i : Fin (n + 1)) : - (predAbove p i).rev = predAbove p.rev i.rev := by rw [predAbove_rev_left, rev_rev] - end PredAbove section DivMod @@ -1531,5 +1441,3 @@ protected theorem zero_mul' [NeZero n] (k : Fin n) : (0 : Fin n) * k = 0 := by end Mul end Fin - -set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/Fin/Rev.lean b/Mathlib/Data/Fin/Rev.lean new file mode 100644 index 0000000000000..929b6cdbd6fde --- /dev/null +++ b/Mathlib/Data/Fin/Rev.lean @@ -0,0 +1,112 @@ +/- +Copyright (c) 2022 Eric Rodriguez. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Eric Rodriguez, Joel Riou, Yury Kudryashov +-/ +import Mathlib.Data.Fin.Basic +/-! +# Reverse on `Fin n` + +This file contains lemmas about `Fin.rev : Fin n → Fin n` which maps `i` to `n - 1 - i`. + +## Definitions + +* `Fin.revPerm : Equiv.Perm (Fin n)` : `Fin.rev` as an `Equiv.Perm`, the antitone involution given + by `i ↦ n-(i+1)` +-/ + +assert_not_exists Monoid Fintype + +open Fin Nat Function + +namespace Fin + +variable {n m : ℕ} + +theorem rev_involutive : Involutive (rev : Fin n → Fin n) := rev_rev + +/-- `Fin.rev` as an `Equiv.Perm`, the antitone involution `Fin n → Fin n` given by +`i ↦ n-(i+1)`. -/ +@[simps! apply symm_apply] +def revPerm : Equiv.Perm (Fin n) := + Involutive.toPerm rev rev_involutive + +theorem rev_injective : Injective (@rev n) := + rev_involutive.injective + +theorem rev_surjective : Surjective (@rev n) := + rev_involutive.surjective + +theorem rev_bijective : Bijective (@rev n) := + rev_involutive.bijective + +@[simp] +theorem revPerm_symm : (@revPerm n).symm = revPerm := + rfl + +theorem cast_rev (i : Fin n) (h : n = m) : + i.rev.cast h = (i.cast h).rev := by + subst h; simp + +theorem rev_eq_iff {i j : Fin n} : rev i = j ↔ i = rev j := by + rw [← rev_inj, rev_rev] + +theorem rev_ne_iff {i j : Fin n} : rev i ≠ j ↔ i ≠ rev j := rev_eq_iff.not + +theorem rev_lt_iff {i j : Fin n} : rev i < j ↔ rev j < i := by + rw [← rev_lt_rev, rev_rev] + +theorem rev_le_iff {i j : Fin n} : rev i ≤ j ↔ rev j ≤ i := by + rw [← rev_le_rev, rev_rev] + +theorem lt_rev_iff {i j : Fin n} : i < rev j ↔ j < rev i := by + rw [← rev_lt_rev, rev_rev] + +theorem le_rev_iff {i j : Fin n} : i ≤ rev j ↔ j ≤ rev i := by + rw [← rev_le_rev, rev_rev] + +-- Porting note: this is now syntactically equal to `val_last` + +@[simp] theorem val_rev_zero [NeZero n] : ((rev 0 : Fin n) : ℕ) = n.pred := rfl + +theorem rev_pred {i : Fin (n + 1)} (h : i ≠ 0) (h' := rev_ne_iff.mpr ((rev_last _).symm ▸ h)) : + rev (pred i h) = castPred (rev i) h' := by + rw [← castSucc_inj, castSucc_castPred, ← rev_succ, succ_pred] + +theorem rev_castPred {i : Fin (n + 1)} + (h : i ≠ last n) (h' := rev_ne_iff.mpr ((rev_zero _).symm ▸ h)) : + rev (castPred i h) = pred (rev i) h' := by + rw [← succ_inj, succ_pred, ← rev_castSucc, castSucc_castPred] + +lemma succAbove_rev_left (p : Fin (n + 1)) (i : Fin n) : + p.rev.succAbove i = (p.succAbove i.rev).rev := by + obtain h | h := (rev p).succ_le_or_le_castSucc i + · rw [succAbove_of_succ_le _ _ h, + succAbove_of_le_castSucc _ _ (rev_succ _ ▸ (le_rev_iff.mpr h)), rev_succ, rev_rev] + · rw [succAbove_of_le_castSucc _ _ h, + succAbove_of_succ_le _ _ (rev_castSucc _ ▸ (rev_le_iff.mpr h)), rev_castSucc, rev_rev] + +lemma succAbove_rev_right (p : Fin (n + 1)) (i : Fin n) : + p.succAbove i.rev = (p.rev.succAbove i).rev := by rw [succAbove_rev_left, rev_rev] + +/-- `rev` commutes with `succAbove`. -/ +lemma rev_succAbove (p : Fin (n + 1)) (i : Fin n) : + rev (succAbove p i) = succAbove (rev p) (rev i) := by + rw [succAbove_rev_left, rev_rev] + +lemma predAbove_rev_left (p : Fin n) (i : Fin (n + 1)) : + p.rev.predAbove i = (p.predAbove i.rev).rev := by + obtain h | h := (rev i).succ_le_or_le_castSucc p + · rw [predAbove_of_succ_le _ _ h, rev_pred, + predAbove_of_le_castSucc _ _ (rev_succ _ ▸ (le_rev_iff.mpr h)), castPred_inj, rev_rev] + · rw [predAbove_of_le_castSucc _ _ h, rev_castPred, + predAbove_of_succ_le _ _ (rev_castSucc _ ▸ (rev_le_iff.mpr h)), pred_inj, rev_rev] + +lemma predAbove_rev_right (p : Fin n) (i : Fin (n + 1)) : + p.predAbove i.rev = (p.rev.predAbove i).rev := by rw [predAbove_rev_left, rev_rev] + +/-- `rev` commutes with `predAbove`. -/ +lemma rev_predAbove {n : ℕ} (p : Fin n) (i : Fin (n + 1)) : + (predAbove p i).rev = predAbove p.rev i.rev := by rw [predAbove_rev_left, rev_rev] + +end Fin diff --git a/Mathlib/Data/Fin/Tuple/Basic.lean b/Mathlib/Data/Fin/Tuple/Basic.lean index 0d867dd8a49e8..49034b164fdbd 100644 --- a/Mathlib/Data/Fin/Tuple/Basic.lean +++ b/Mathlib/Data/Fin/Tuple/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Yury Kudryashov, Sébastien Gouëzel, Chris Hughes -/ -import Mathlib.Data.Fin.Basic +import Mathlib.Data.Fin.Rev import Mathlib.Data.Nat.Find /-! diff --git a/Mathlib/Order/Fin/Basic.lean b/Mathlib/Order/Fin/Basic.lean index 4e47785db09e5..174adbcde047a 100644 --- a/Mathlib/Order/Fin/Basic.lean +++ b/Mathlib/Order/Fin/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis, Keeley Hoek -/ -import Mathlib.Data.Fin.Basic +import Mathlib.Data.Fin.Rev import Mathlib.Order.Hom.Set /-! From 8d5e2c1a118cb5025a7596584507841290ec0de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Dupuis?= Date: Wed, 22 Jan 2025 02:43:50 +0000 Subject: [PATCH 397/681] =?UTF-8?q?feat(ContinuousFunctionalCalculus):=20`?= =?UTF-8?q?=E2=80=96sqrt=20a=E2=80=96=20=3D=20sqrt=20=E2=80=96a=E2=80=96`?= =?UTF-8?q?=20and=20`=E2=80=96a=20^=20r=E2=80=96=20=3D=20=E2=80=96a?= =?UTF-8?q?=E2=80=96^r`=20for=20an=20isometric=20CFC=20(#20819)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR shows that `‖sqrt a‖ = sqrt ‖a‖` and `‖a ^ r‖ = ‖a‖ ^ r` when `a` is an element of an algebra that admits an isometric continuous functional calculus. We also rename the file `Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow` to `Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow.Basic`, in order to put the new results in a new file with heavier imports. I think the new folder makes sense, especially since we'll need to do something like that anyway soon for the operator monotonicity and convexity/concavity results that depend on integral representations. Co-authored-by: Frédéric Dupuis <31101893+dupuisf@users.noreply.github.com> --- Mathlib.lean | 3 +- .../CStarAlgebra/ApproximateUnit.lean | 2 +- .../ContinuousFunctionalCalculus/Order.lean | 6 +- .../{Rpow.lean => Rpow/Basic.lean} | 3 + .../Rpow/Isometric.lean | 69 +++++++++++++++++++ 5 files changed, 79 insertions(+), 4 deletions(-) rename Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/{Rpow.lean => Rpow/Basic.lean} (99%) create mode 100644 Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow/Isometric.lean diff --git a/Mathlib.lean b/Mathlib.lean index 2eb24f819ce99..9c06e648c8c35 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1564,7 +1564,8 @@ import Mathlib.Analysis.SpecialFunctions.Complex.LogBounds import Mathlib.Analysis.SpecialFunctions.Complex.LogDeriv import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.ExpLog import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.PosPart -import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow +import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow.Basic +import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow.Isometric import Mathlib.Analysis.SpecialFunctions.Exp import Mathlib.Analysis.SpecialFunctions.ExpDeriv import Mathlib.Analysis.SpecialFunctions.Exponential diff --git a/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean b/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean index 0479cfb3716ed..ddb1eca0f9d22 100644 --- a/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean +++ b/Mathlib/Analysis/CStarAlgebra/ApproximateUnit.lean @@ -5,7 +5,7 @@ Authors: Jireh Loreaux -/ import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Order import Mathlib.Analysis.CStarAlgebra.SpecialFunctions.PosPart -import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow +import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow.Basic import Mathlib.Topology.ApproximateUnit /-! # Nonnegative contractions in a C⋆-algebra form an approximate unit diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean index c829c663a59c8..c093bde67133c 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean @@ -6,8 +6,9 @@ Authors: Frédéric Dupuis import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic import Mathlib.Analysis.CStarAlgebra.Unitization -import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow +import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow.Basic import Mathlib.Topology.ContinuousMap.StarOrdered +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Isometric /-! # Facts about star-ordered rings that depend on the continuous functional calculus @@ -478,7 +479,8 @@ section Pow namespace CStarAlgebra -variable {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A] +variable {A : Type*} {B : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A] + [NonUnitalCStarAlgebra B] [PartialOrder B] [StarOrderedRing B] lemma pow_nonneg {a : A} (ha : 0 ≤ a := by cfc_tac) (n : ℕ) : 0 ≤ a ^ n := by rw [← cfc_pow_id (R := ℝ≥0) a] diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow/Basic.lean similarity index 99% rename from Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow.lean rename to Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow/Basic.lean index 89d6038a11e76..4da05cf09f25a 100644 --- a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow.lean +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow/Basic.lean @@ -60,6 +60,9 @@ lemma continuous_nnrpow_const (y : ℝ≥0) : Continuous (nnrpow · y) := /- This is a "redeclaration" of the attribute to speed up the proofs in this file. -/ attribute [fun_prop] continuousOn_rpow_const +lemma monotone_nnrpow_const (y : ℝ≥0) : Monotone (nnrpow · y) := + monotone_rpow_of_nonneg zero_le_coe + end NNReal namespace CFC diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow/Isometric.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow/Isometric.lean new file mode 100644 index 0000000000000..55a50094d5046 --- /dev/null +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/Rpow/Isometric.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2025 Frédéric Dupuis. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Frédéric Dupuis +-/ + +import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow.Basic +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Isometric + +/-! # Properties of `rpow` and `sqrt` over an algebra with an isometric CFC + +This file collects results about `CFC.rpow`, `CFC.nnrpow` and `CFC.sqrt` that use facts that +rely on an isometric continuous functional calculus. + +## Main theorems + +* Various versions of `‖a ^ r‖ = ‖a‖ ^ r` and `‖CFC.sqrt a‖ = sqrt ‖a‖`. + +## Tags + +continuous functional calculus, rpow, sqrt +-/ + +open scoped NNReal + +namespace CFC + +section nonunital + +variable {A : Type*} [NonUnitalNormedRing A] [StarRing A] [NormedSpace ℝ A] [IsScalarTower ℝ A A] + [SMulCommClass ℝ A A] [PartialOrder A] [StarOrderedRing A] [NonnegSpectrumClass ℝ A] + [NonUnitalIsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] + +lemma nnnorm_nnrpow (a : A) {r : ℝ≥0} (hr : 0 < r) (ha : 0 ≤ a := by cfc_tac) : + ‖a ^ r‖₊ = ‖a‖₊ ^ (r : ℝ) := + NNReal.monotone_nnrpow_const r |>.monotoneOn _ |>.nnnorm_cfcₙ _ _ + +lemma norm_nnrpow (a : A) {r : ℝ≥0} (hr : 0 < r) (ha : 0 ≤ a := by cfc_tac) : + ‖a ^ r‖ = ‖a‖ ^ (r : ℝ) := + congr(NNReal.toReal $(nnnorm_nnrpow a hr ha)) + +lemma nnnorm_sqrt (a : A) (ha : 0 ≤ a := by cfc_tac) : ‖sqrt a‖₊ = NNReal.sqrt ‖a‖₊ := by + rw [sqrt_eq_nnrpow, NNReal.sqrt_eq_rpow] + exact nnnorm_nnrpow a (by norm_num) ha + +lemma norm_sqrt (a : A) (ha : 0 ≤ a := by cfc_tac) : ‖sqrt a‖ = Real.sqrt ‖a‖ := by + simpa using congr(NNReal.toReal $(nnnorm_sqrt a ha)) + +end nonunital + +section unital + +variable {A : Type*} [NormedRing A] [StarRing A] [NormedAlgebra ℝ A] + [PartialOrder A] [StarOrderedRing A] [NonnegSpectrumClass ℝ A] + [IsometricContinuousFunctionalCalculus ℝ A IsSelfAdjoint] + +lemma nnnorm_rpow (a : A) {r : ℝ} (hr : 0 < r) (ha : 0 ≤ a := by cfc_tac) : + ‖a ^ r‖₊ = ‖a‖₊ ^ r := by + lift r to ℝ≥0 using hr.le + rw [← nnrpow_eq_rpow, ← nnnorm_nnrpow a] + all_goals simpa + +lemma norm_rpow (a : A) {r : ℝ} (hr : 0 < r) (ha : 0 ≤ a := by cfc_tac) : + ‖a ^ r‖ = ‖a‖ ^ r := + congr(NNReal.toReal $(nnnorm_rpow a hr ha)) + +end unital + +end CFC From d57d0541d573431e5e7f87a67e25ca041d5f392d Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 22 Jan 2025 06:58:11 +0000 Subject: [PATCH 398/681] feat(CI): remove `:closed-pr:` reaction, if PR is reopened (#20926) This PR follow up on #20902: the action is now also triggered by `reopened` PRs and the bot removes the `:closed-pr:` Zulip reaction in this case. --- .github/workflows/zulip_emoji_closed_pr.yaml | 23 ++++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/zulip_emoji_closed_pr.yaml b/.github/workflows/zulip_emoji_closed_pr.yaml index 43076e2433e87..9504e7395ca0a 100644 --- a/.github/workflows/zulip_emoji_closed_pr.yaml +++ b/.github/workflows/zulip_emoji_closed_pr.yaml @@ -4,8 +4,8 @@ name: Add "closed-pr" emoji in Zulip # triggers the action when on: pull_request: - # the pull request is closed - types: [closed] + # the pull request is closed or reopened, to add or remove the emoji + types: [closed, reopened] jobs: add_closed_pr_emoji: @@ -24,29 +24,38 @@ jobs: printf 'issue number: "%s"\npull request number: "%s"\n' "${{ github.event.issue.number }}" "${{ github.event.pull_request.number }}" - name: Set up Python - if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') || + github.event_name == 'reopened' }} uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies - if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') || + github.event_name == 'reopened' }} run: | python -m pip install --upgrade pip pip install zulip - name: checkout zulip_emoji_merge_delegate script - if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') || + github.event_name == 'reopened' }} uses: actions/checkout@v4 with: sparse-checkout: | scripts/zulip_emoji_merge_delegate.py - name: Run Zulip Emoji Merge Delegate Script - if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') }} + if: ${{ ! startsWith(github.event.pull_request.title, '[Merged by Bors]') || + github.event_name == 'reopened' }} env: ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }} ZULIP_EMAIL: github-mathlib4-bot@leanprover.zulipchat.com ZULIP_SITE: https://leanprover.zulipchat.com run: | - python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "closed" "${{ github.event.pull_request.number }}" + # ${{ github.event.action }} is either "closed" or "reopened" + # however, it only matters that it is either "closed" or + # something different from "closed" + # the effect is to add the "closed-pr" emoji to the message, if it is "closed" + # and to remove it otherwise + python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "${{ github.event.action }}" "${{ github.event.pull_request.number }}" From 3197a5fe9d5c6575ce03fdee1ce1c2c9a5e6b278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Wed, 22 Jan 2025 07:21:05 +0000 Subject: [PATCH 399/681] feat(RingTheory/Trace): `trace K x` in terms of `minpoly K x` (#20906) Two facts expressing `trace K x` in terms of `(minpoly K x).nextCoeff`. --- Mathlib/RingTheory/Trace/Basic.lean | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Mathlib/RingTheory/Trace/Basic.lean b/Mathlib/RingTheory/Trace/Basic.lean index dbe13c0d621bf..5b322e66a5a7b 100644 --- a/Mathlib/RingTheory/Trace/Basic.lean +++ b/Mathlib/RingTheory/Trace/Basic.lean @@ -119,11 +119,22 @@ open IntermediateField variable (K) theorem trace_eq_trace_adjoin [FiniteDimensional K L] (x : L) : - Algebra.trace K L x = finrank K⟮x⟯ L • trace K K⟮x⟯ (AdjoinSimple.gen K x) := by + trace K L x = finrank K⟮x⟯ L • trace K K⟮x⟯ (AdjoinSimple.gen K x) := by rw [← trace_trace (S := K⟮x⟯)] - conv in x => rw [← IntermediateField.AdjoinSimple.algebraMap_gen K x] + conv in x => rw [← AdjoinSimple.algebraMap_gen K x] rw [trace_algebraMap, LinearMap.map_smul_of_tower] +variable {K} in +/-- Trace of the generator of a simple adjoin equals negative of the next coefficient of +its minimal polynomial coefficient. -/ +theorem trace_adjoinSimpleGen {x : L} (hx : IsIntegral K x) : + trace K K⟮x⟯ (AdjoinSimple.gen K x) = -(minpoly K x).nextCoeff := by + simpa [minpoly_gen K x] using PowerBasis.trace_gen_eq_nextCoeff_minpoly <| adjoin.powerBasis hx + +theorem trace_eq_finrank_mul_minpoly_nextCoeff [FiniteDimensional K L] (x : L) : + trace K L x = finrank K⟮x⟯ L * -(minpoly K x).nextCoeff := by + rw [trace_eq_trace_adjoin, trace_adjoinSimpleGen (.of_finite K x), Algebra.smul_def]; rfl + variable {K} theorem trace_eq_sum_roots [FiniteDimensional K L] {x : L} From fb39772b3eecdf7dba86cb50b77c637988821236 Mon Sep 17 00:00:00 2001 From: smorel394 Date: Wed, 22 Jan 2025 07:51:38 +0000 Subject: [PATCH 400/681] feat(Algebra/Category/Grp/Ulift): the universe lifting functor for commutative additive groups preserves colimits (#20417) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prove that the functor `AddCommGrp.ulift` preserves all colimits, hence creates small colimits. (This also finished the proof that it is an exact functor.) Method: Suppose that we have a functor `K : J ⥤ AddCommGrp.{u}` (with `J` any category), a colimit cocone `c` of `K` and a cocone `lc` of `K ⋙ uliftFunctor.{u v}`. We want to construct a morphism of cocones `uliftFunctor.mapCocone c → lc` witnessing the fact that `uliftFunctor.mapCocone c` is also a colimit cocone, but we have no direct way to do this. The idea is to use that `AddCommGrp.{max v u}` has a small cogenerator, which is just the additive (rational) circle `ℚ / ℤ`, so any abelian group of any size can be recovered from its morphisms into `ℚ / ℤ`. More precisely, the functor sending an abelian group `A` to its dual `A →+ ℚ / ℤ` is fully faithful, *if* we consider the dual as a (right) module over the endomorphism ring of `ℚ / ℤ`. So an abelian group `C` is totally determined by the restriction of the coyoneda functor `A ↦ (C →+ A)` to the category of abelian groups at a smaller universe level. We do not develop this totally here but do a direct construction. Every time we have a morphism from `lc.pt` into `ℚ / ℤ`, or more generally into any small abelian group `A`, we can construct a cocone of `K ⋙ uliftFunctor` by sticking `ULift A` at the cocone point (this is `CategoryTheory.Limits.Cocone.extensions`), and this cocone is actually made up of `u`-small abelian groups, hence gives a cocone of `K`. Using the universal property of `c`, we get a morphism `c.pt →+ A`. So we have constructed a map `(lc.pt →+ A) → (c.pt →+ A)`, and it is easy to prove that it is compatible with postcomposition of morphisms of small abelian groups. To actually get the morphism `c.pt →+ lc.pt`, we apply this to the canonical embedding of `lc.pt` into `Π (_ : lc.pt →+ ℚ / ℤ), ℚ / ℤ` (this group is not small but is a product of small groups, so our construction extends). To show that the image of `c.pt` in this product is contained in that of `lc.pt`, we use the compatibility with postcomposition and the fact that we can detect elements of the image just by applying morphisms from `Π (_ : lc.pt →+ ℚ / ℤ), ℚ / ℤ` to `ℚ / ℤ`. - [x] depends on: #20416 - [x] depends on: #20512 - [x] depends on: #20522 --- Mathlib/Algebra/Category/Grp/Colimits.lean | 83 +++++++++++++++++++++- Mathlib/Algebra/Category/Grp/Ulift.lean | 80 +++++++++++++++++++-- 2 files changed, 157 insertions(+), 6 deletions(-) diff --git a/Mathlib/Algebra/Category/Grp/Colimits.lean b/Mathlib/Algebra/Category/Grp/Colimits.lean index 80b1c46458597..f74b2fe7db828 100644 --- a/Mathlib/Algebra/Category/Grp/Colimits.lean +++ b/Mathlib/Algebra/Category/Grp/Colimits.lean @@ -17,7 +17,7 @@ quotients of finitely supported functions. -/ -universe w u v +universe u' w u v open CategoryTheory Limits @@ -94,6 +94,87 @@ lemma Quot.map_ι [DecidableEq J] {j j' : J} {f : j ⟶ j'} (x : F.obj j) : simp only [DFinsupp.singleAddHom_apply] exact AddSubgroup.subset_closure ⟨j, j', f, x, rfl⟩ +/-- +The obvious additive map from `Quot F` to `Quot (F ⋙ uliftFunctor.{u'})`. +-/ +def quotToQuotUlift [DecidableEq J] : Quot F →+ Quot (F ⋙ uliftFunctor.{u'}) := by + refine QuotientAddGroup.lift (Relations F) (DFinsupp.sumAddHom (fun j ↦ (Quot.ι _ j).comp + AddEquiv.ulift.symm.toAddMonoidHom)) ?_ + rw [AddSubgroup.closure_le] + intro _ hx + obtain ⟨j, j', u, a, rfl⟩ := hx + rw [SetLike.mem_coe, AddMonoidHom.mem_ker, map_sub, DFinsupp.sumAddHom_single, + DFinsupp.sumAddHom_single] + change Quot.ι (F ⋙ uliftFunctor) j' ((F ⋙ uliftFunctor).map u (AddEquiv.ulift.symm a)) - _ = _ + rw [Quot.map_ι] + dsimp + rw [sub_self] + +lemma quotToQuotUlift_ι [DecidableEq J] (j : J) (x : F.obj j) : + quotToQuotUlift F (Quot.ι F j x) = Quot.ι _ j (ULift.up x) := by + dsimp [quotToQuotUlift, Quot.ι] + conv_lhs => erw [AddMonoidHom.comp_apply (QuotientAddGroup.mk' (Relations F)) + (DFinsupp.singleAddHom _ j), QuotientAddGroup.lift_mk'] + simp only [DFinsupp.singleAddHom_apply, DFinsupp.sumAddHom_single, AddMonoidHom.coe_comp, + AddMonoidHom.coe_coe, Function.comp_apply] + rfl + +/-- +The obvious additive map from `Quot (F ⋙ uliftFunctor.{u'})` to `Quot F`. +-/ +def quotUliftToQuot [DecidableEq J] : Quot (F ⋙ uliftFunctor.{u'}) →+ Quot F := by + refine QuotientAddGroup.lift (Relations (F ⋙ uliftFunctor)) + (DFinsupp.sumAddHom (fun j ↦ (Quot.ι _ j).comp AddEquiv.ulift.toAddMonoidHom)) ?_ + rw [AddSubgroup.closure_le] + intro _ hx + obtain ⟨j, j', u, a, rfl⟩ := hx + rw [SetLike.mem_coe, AddMonoidHom.mem_ker, map_sub, DFinsupp.sumAddHom_single, + DFinsupp.sumAddHom_single] + change Quot.ι F j' (F.map u (AddEquiv.ulift a)) - _ = _ + rw [Quot.map_ι] + dsimp + rw [sub_self] + +lemma quotUliftToQuot_ι [DecidableEq J] (j : J) (x : (F ⋙ uliftFunctor.{u'}).obj j) : + quotUliftToQuot F (Quot.ι _ j x) = Quot.ι F j x.down := by + dsimp [quotUliftToQuot, Quot.ι] + conv_lhs => erw [AddMonoidHom.comp_apply (QuotientAddGroup.mk' (Relations (F ⋙ uliftFunctor))) + (DFinsupp.singleAddHom _ j), QuotientAddGroup.lift_mk'] + simp only [Functor.comp_obj, uliftFunctor_obj, coe_of, DFinsupp.singleAddHom_apply, + DFinsupp.sumAddHom_single, AddMonoidHom.coe_comp, AddMonoidHom.coe_coe, Function.comp_apply] + rfl + +/-- +The additive equivalence between `Quot F` and `Quot (F ⋙ uliftFunctor.{u'})`. +-/ +@[simp] +def quotQuotUliftAddEquiv [DecidableEq J] : Quot F ≃+ Quot (F ⋙ uliftFunctor.{u'}) where + toFun := quotToQuotUlift F + invFun := quotUliftToQuot F + left_inv x := by + conv_rhs => rw [← AddMonoidHom.id_apply _ x] + rw [← AddMonoidHom.comp_apply, Quot.addMonoidHom_ext F (f := (quotUliftToQuot F).comp + (quotToQuotUlift F)) (fun j a ↦ ?_)] + rw [AddMonoidHom.comp_apply, AddMonoidHom.id_apply, quotToQuotUlift_ι, quotUliftToQuot_ι] + right_inv x := by + conv_rhs => rw [← AddMonoidHom.id_apply _ x] + rw [← AddMonoidHom.comp_apply, Quot.addMonoidHom_ext _ (f := (quotToQuotUlift F).comp + (quotUliftToQuot F)) (fun j a ↦ ?_)] + rw [AddMonoidHom.comp_apply, AddMonoidHom.id_apply, quotUliftToQuot_ι, quotToQuotUlift_ι] + rfl + map_add' _ _ := by simp + +lemma Quot.desc_quotQuotUliftAddEquiv [DecidableEq J] (c : Cocone F) : + (Quot.desc (F ⋙ uliftFunctor.{u'}) (uliftFunctor.{u'}.mapCocone c)).comp + (quotQuotUliftAddEquiv F).toAddMonoidHom = + AddEquiv.ulift.symm.toAddMonoidHom.comp (Quot.desc F c) := by + refine Quot.addMonoidHom_ext _ (fun j a ↦ ?_) + dsimp + simp only [quotToQuotUlift_ι, Functor.comp_obj, uliftFunctor_obj, coe_of, ι_desc, + Functor.const_obj_obj] + erw [Quot.ι_desc] + rfl + /-- (implementation detail) A morphism of commutative additive groups `Quot F →+ A` induces a cocone on `F` as long as the universes work out. -/ diff --git a/Mathlib/Algebra/Category/Grp/Ulift.lean b/Mathlib/Algebra/Category/Grp/Ulift.lean index 4e58356a103e1..17c4fe820c0c4 100644 --- a/Mathlib/Algebra/Category/Grp/Ulift.lean +++ b/Mathlib/Algebra/Category/Grp/Ulift.lean @@ -3,9 +3,10 @@ Copyright (c) 2024 Sophie Morel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sophie Morel -/ +import Mathlib.Algebra.Category.Grp.LargeColimits import Mathlib.Algebra.Category.Grp.Limits +import Mathlib.Algebra.Module.CharacterModule import Mathlib.CategoryTheory.Limits.Preserves.Ulift -import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor /-! # Properties of the universe lift functor for groups @@ -14,8 +15,56 @@ This file shows that the functors `Grp.uliftFunctor` and `CommGrp.uliftFunctor` (as well as the additive versions) are fully faithful, preserves all limits and create small limits. -It also shows that `AddCommGrp.uliftFunctor` is an additive functor. - +Full faithfulness is pretty obvious. To prove that the functors preserves limits, +we use the fact that the forgetful functor from `Grp` or `CommGrp` into `Type` +creates all limits (because of the way limits are constructed in `Grp` and `CommGrp`), +and that the universe lift functor on `Type` preserves all limits. Once we know +that `Grp.uliftFunctor` preserves all limits and is fully faithful, it will +automatically create all limits that exist, i.e. all small ones. + +We then switch to `AddCommGrp` and show that `AddCommGrp.uliftFunctor` preserves zero morphisms +and is an additive functor, which again is pretty obvious. + +The last result is a proof that `AddCommGrp.uliftFunctor` preserves all colimits +(and hence creates small colimits). This is the only non-formal part of this file, +as we follow the same strategy as for the categories `Type`. + +Suppose that we have a functor `K : J ⥤ AddCommGrp.{u}` (with `J` any category), a +colimit cocone `c` of `K` and a cocone `lc` of `K ⋙ uliftFunctor.{u v}`. We want to +construct a morphism of cocones `uliftFunctor.mapCocone c → lc` witnessing the fact +that `uliftFunctor.mapCocone c` is also a colimit cocone, but we have no direct way +to do this. The idea is to use that `AddCommGrp.{max v u}` has a small cogenerator, +which is just the additive (rational) circle `ℚ / ℤ`, so any abelian group of +any size can be recovered from its morphisms into `ℚ / ℤ`. More precisely, the functor +sending an abelian group `A` to its dual `A →+ ℚ / ℤ` is fully faithful, *if* we consider +the dual as a (right) module over the endomorphism ring of `ℚ / ℤ`. So an abelian +group `C` is totally determined by the restriction of the coyoneda +functor `A ↦ (C →+ A)` to the category of abelian groups at a smaller universe level. +We do not develop this totally here but do a direct construction. Every time we have +a morphism from `lc.pt` into `ℚ / ℤ`, or more generally into any small abelian group +`A`, we can construct a cocone of `K ⋙ uliftFunctor` by sticking `ULift A` at the +cocone point (this is `CategoryTheory.Limits.Cocone.extensions`), and this cocone is +actually made up of `u`-small abelian groups, hence gives a cocone of `K`. Using +the universal property of `c`, we get a morphism `c.pt →+ A`. So we have constructed +a map `(lc.pt →+ A) → (c.pt →+ A)`, and it is easy to prove that it is compatible with +postcomposition of morphisms of small abelian groups. To actually get the +morphism `c.pt →+ lc.pt`, we apply this to the canonical embedding of `lc.pt` into +`Π (_ : lc.pt →+ ℚ / ℤ), ℚ / ℤ` (this group is not small but is a product of small +groups, so our construction extends). To show that the image of `c.pt` in this product +is contained in that of `lc.pt`, we use the compatibility with postcomposition and the +fact that we can detect elements of the image just by applying morphisms from +`Π (_ : lc.pt →+ ℚ / ℤ), ℚ / ℤ` to `ℚ / ℤ`. + +Note that this does *not* work for noncommutative groups, because the existence of +simple groups of arbitrary size implies that a general object `G` of `Grp` is not +determined by the restriction of `coyoneda.obj G` to the category of groups at +a smaller universe level. Indeed, the functor `Grp.uliftFunctor` does not commute +with arbitrary colimits: if we take an increasing family `K` of simple groups in +`Grp.{u}` of unbounded cardinality indexed by a linearly ordered type +(for example finitary alternating groups on a family of types in `u` of unbouded cardinality), +then the colimit of `K` in `Grp.{u}` exists and is the trivial group; meanwhile, the colimit +of `K ⋙ Grp.uliftFunctor.{u + 1}` is nontrivial (it is the "union" of all the `K j`, which is +too big to be in `Grp.{u}`). -/ universe v w w' u @@ -125,11 +174,32 @@ noncomputable instance : CreatesLimitsOfSize.{w, u} uliftFunctor.{v, u} where end CommGrp -namespace AddCommGroup +namespace AddCommGrp /-- The universe lift for commutative additive groups is additive. -/ instance uliftFunctor_additive : AddCommGrp.uliftFunctor.{u,v}.Additive where -end AddCommGroup +open Colimits in +/-- +The functor `uliftFunctor : AddCommGrp.{u} ⥤ AddCommGrp.{max u v}` preserves colimits +of arbitrary size. +-/ +noncomputable instance : PreservesColimitsOfSize.{w', w} uliftFunctor.{v, u} where + preservesColimitsOfShape {J _} := + { preservesColimit := fun {F} ↦ + { preserves := fun {c} hc ↦ by + classical + rw [isColimit_iff_bijective_desc, ← Function.Bijective.of_comp_iff _ + (quotQuotUliftAddEquiv F).bijective, ← AddEquiv.coe_toAddMonoidHom, + ← AddMonoidHom.coe_comp, Quot.desc_quotQuotUliftAddEquiv] + exact ULift.up_bijective.comp ((isColimit_iff_bijective_desc c).mp (Nonempty.intro hc)) } } + +/-- +The functor `uliftFunctor : AddCommGrp.{u} ⥤ AddCommGrp.{max u v}` creates `u`-small colimits. +-/ +noncomputable instance : CreatesColimitsOfSize.{w, u} uliftFunctor.{v, u} where + CreatesColimitsOfShape := { CreatesColimit := fun {_} ↦ createsColimitOfFullyFaithfulOfPreserves } + +end AddCommGrp From e0e8605093a7b3d6d0e9cb6c0a8caf2a6f050cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 22 Jan 2025 08:02:34 +0000 Subject: [PATCH 401/681] chore(CategoryTheory): move Functor.IsWellOrderContinuous (#20366) The definition of `Functor.IsWellOrderContinuous` is moved to a better place `Limits.Shapes.Preorder.WellOrderContinuous` (see also #20335). --- Mathlib.lean | 1 + .../Shapes/Preorder/WellOrderContinuous.lean | 82 +++++++++++++++++++ .../TransfiniteComposition.lean | 54 +----------- .../TransfiniteCompositionLifting.lean | 6 +- 4 files changed, 86 insertions(+), 57 deletions(-) create mode 100644 Mathlib/CategoryTheory/Limits/Shapes/Preorder/WellOrderContinuous.lean diff --git a/Mathlib.lean b/Mathlib.lean index 9c06e648c8c35..9eeb7460242e9 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1971,6 +1971,7 @@ import Mathlib.CategoryTheory.Limits.Shapes.Multiequalizer import Mathlib.CategoryTheory.Limits.Shapes.NormalMono.Basic import Mathlib.CategoryTheory.Limits.Shapes.NormalMono.Equalizers import Mathlib.CategoryTheory.Limits.Shapes.PiProd +import Mathlib.CategoryTheory.Limits.Shapes.Preorder.WellOrderContinuous import Mathlib.CategoryTheory.Limits.Shapes.Products import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Assoc import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Preorder/WellOrderContinuous.lean b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/WellOrderContinuous.lean new file mode 100644 index 0000000000000..d32739ec06f2a --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/WellOrderContinuous.lean @@ -0,0 +1,82 @@ +/- +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.Data.Nat.SuccPred +import Mathlib.Order.SuccPred.Limit +import Mathlib.CategoryTheory.Limits.IsLimit +import Mathlib.CategoryTheory.Category.Preorder + +/-! +# Continuity of functors from well ordered types + +Let `F : J ⥤ C` be functor from a well ordered type `J`. +We introduce the typeclass `F.IsWellOrderContinuous` +to say that if `m` is a limit element, then `F.obj m` +is the colimit of the `F.obj j` for `j < m`. + +## TODO +* use the API for initial segments in order to generalize some +definitions in this file +* given a morphism `f` in `C`, introduce a structure +`TransfiniteCompositionOfShape J f` which contains the data +of a continuous functor `F : J ⥤ C` and an identification +of `f` to the map from `F.obj ⊥` to the colimit of `F` +* redefine `MorphismProperty.transfiniteCompositionsOfShape` +in terms of this structure `TransfiniteCompositionOfShape` + +-/ + +universe w v u + +namespace CategoryTheory.Functor + +open Category Limits + +variable {C : Type u} [Category.{v} C] {J : Type w} [Preorder J] + +/-- Given a functor `F : J ⥤ C` and `m : J`, this is the induced +functor `Set.Iio j ⥤ C`. -/ +@[simps!] +def restrictionLT (F : J ⥤ C) (j : J) : Set.Iio j ⥤ C := + Monotone.functor (f := fun k ↦ k.1) (fun _ _ ↦ id) ⋙ F + +/-- Given a functor `F : J ⥤ C` and `m : J`, this is the cocone with point `F.obj m` +for the restriction of `F` to `Set.Iio m`. -/ +@[simps] +def coconeLT (F : J ⥤ C) (m : J) : + Cocone (F.restrictionLT m) where + pt := F.obj m + ι := + { app := fun ⟨i, hi⟩ ↦ F.map (homOfLE hi.le) + naturality := fun ⟨i₁, hi₁⟩ ⟨i₂, hi₂⟩ f ↦ by + dsimp + rw [← F.map_comp, comp_id] + rfl } + +/-- A functor `F : J ⥤ C` is well-order-continuous if for any limit element `m : J`, +`F.obj m` identifies to the colimit of the `F.obj j` for `j < m`. -/ +class IsWellOrderContinuous (F : J ⥤ C) : Prop where + nonempty_isColimit (m : J) (hm : Order.IsSuccLimit m) : + Nonempty (IsColimit (F.coconeLT m)) + +/-- If `F : J ⥤ C` is well-order-continuous and `m : J` is a limit element, then +the cocone `F.coconeLT m` is colimit, i.e. `F.obj m` identifies to the colimit +of the `F.obj j` for `j < m`. -/ +noncomputable def isColimitOfIsWellOrderContinuous (F : J ⥤ C) [F.IsWellOrderContinuous] + (m : J) (hm : Order.IsSuccLimit m) : + IsColimit (F.coconeLT m) := (IsWellOrderContinuous.nonempty_isColimit m hm).some + +instance (F : ℕ ⥤ C) : F.IsWellOrderContinuous where + nonempty_isColimit m hm := by simp at hm + +lemma isWellOrderContinuous_of_iso {F G : J ⥤ C} (e : F ≅ G) [F.IsWellOrderContinuous] : + G.IsWellOrderContinuous where + nonempty_isColimit (m : J) (hm : Order.IsSuccLimit m) := + ⟨(IsColimit.precomposeHomEquiv (isoWhiskerLeft _ e) _).1 + (IsColimit.ofIsoColimit (F.isColimitOfIsWellOrderContinuous m hm) + (Cocones.ext (e.app _)))⟩ + +end CategoryTheory.Functor diff --git a/Mathlib/CategoryTheory/MorphismProperty/TransfiniteComposition.lean b/Mathlib/CategoryTheory/MorphismProperty/TransfiniteComposition.lean index a795a1546a370..d6082ef5b309b 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/TransfiniteComposition.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/TransfiniteComposition.lean @@ -3,11 +3,8 @@ 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.Data.Nat.SuccPred -import Mathlib.Order.SuccPred.Limit -import Mathlib.CategoryTheory.Category.Preorder -import Mathlib.CategoryTheory.Limits.IsLimit import Mathlib.CategoryTheory.MorphismProperty.Composition +import Mathlib.CategoryTheory.Limits.Shapes.Preorder.WellOrderContinuous /-! # Classes of morphisms that are stable under transfinite composition @@ -47,59 +44,10 @@ open Category Limits variable {C : Type u} [Category.{v} C] -namespace Functor - -variable {J : Type w} [Preorder J] - -/-- Given a functor `F : J ⥤ C` and `m : J`, this is the induced -functor `Set.Iio j ⥤ C`. -/ -@[simps!] -def restrictionLT (F : J ⥤ C) (j : J) : Set.Iio j ⥤ C := - Monotone.functor (f := fun k ↦ k.1) (fun _ _ ↦ id) ⋙ F - -/-- Given a functor `F : J ⥤ C` and `m : J`, this is the cocone with point `F.obj m` -for the restriction of `F` to `Set.Iio m`. -/ -@[simps] -def coconeLT (F : J ⥤ C) (m : J) : - Cocone (F.restrictionLT m) where - pt := F.obj m - ι := - { app := fun ⟨i, hi⟩ ↦ F.map (homOfLE hi.le) - naturality := fun ⟨i₁, hi₁⟩ ⟨i₂, hi₂⟩ f ↦ by - dsimp - rw [← F.map_comp, comp_id] - rfl } - -/-- A functor `F : J ⥤ C` is well-order-continuous if for any limit element `m : J`, -`F.obj m` identifies to the colimit of the `F.obj j` for `j < m`. -/ -class IsWellOrderContinuous (F : J ⥤ C) : Prop where - nonempty_isColimit (m : J) (hm : Order.IsSuccLimit m) : - Nonempty (IsColimit (F.coconeLT m)) - -/-- If `F : J ⥤ C` is well-order-continuous and `m : J` is a limit element, then -the cocone `F.coconeLT m` is colimit, i.e. `F.obj m` identifies to the colimit -of the `F.obj j` for `j < m`. -/ -noncomputable def isColimitOfIsWellOrderContinuous (F : J ⥤ C) [F.IsWellOrderContinuous] - (m : J) (hm : Order.IsSuccLimit m) : - IsColimit (F.coconeLT m) := (IsWellOrderContinuous.nonempty_isColimit m hm).some - -instance (F : ℕ ⥤ C) : F.IsWellOrderContinuous where - nonempty_isColimit m hm := by simp at hm - -lemma isWellOrderContinuous_of_iso {F G : J ⥤ C} (e : F ≅ G) [F.IsWellOrderContinuous] : - G.IsWellOrderContinuous where - nonempty_isColimit (m : J) (hm : Order.IsSuccLimit m) := - ⟨(IsColimit.precomposeHomEquiv (isoWhiskerLeft _ e) _).1 - (IsColimit.ofIsoColimit (F.isColimitOfIsWellOrderContinuous m hm) - (Cocones.ext (e.app _)))⟩ - -end Functor - namespace MorphismProperty variable (W : MorphismProperty C) --- for Basic.lean section variable (J : Type w) [LinearOrder J] [SuccOrder J] [OrderBot J] diff --git a/Mathlib/CategoryTheory/SmallObject/TransfiniteCompositionLifting.lean b/Mathlib/CategoryTheory/SmallObject/TransfiniteCompositionLifting.lean index 7b7f5cdd144f9..715f2e390e058 100644 --- a/Mathlib/CategoryTheory/SmallObject/TransfiniteCompositionLifting.lean +++ b/Mathlib/CategoryTheory/SmallObject/TransfiniteCompositionLifting.lean @@ -4,8 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.SmallObject.WellOrderInductionData -import Mathlib.CategoryTheory.MorphismProperty.TransfiniteComposition -import Mathlib.CategoryTheory.LiftingProperties.Basic +import Mathlib.CategoryTheory.Limits.Shapes.Preorder.WellOrderContinuous /-! # The left lifting property is stable under transfinite composition @@ -56,8 +55,7 @@ variable {C : Type u} [Category.{v} C] namespace HasLiftingProperty -variable {W : MorphismProperty C} - {J : Type w} [LinearOrder J] [OrderBot J] +variable {J : Type w} [LinearOrder J] [OrderBot J] namespace transfiniteComposition From 3982e7cf7f5f566f443ad35d852a84816d8ba34d Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 22 Jan 2025 08:02:35 +0000 Subject: [PATCH 402/681] fix(Zulip reaction): add emoji_code and realm_emoji for `:closed-pr:` (#20941) I forgot that for custom emoji, the Zulip API to remove reactions requires also the code and realm_emoji, possibly not both, but certainly at least one! --- scripts/zulip_emoji_merge_delegate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/zulip_emoji_merge_delegate.py b/scripts/zulip_emoji_merge_delegate.py index 13069dd7e9529..b882ff416cf6b 100644 --- a/scripts/zulip_emoji_merge_delegate.py +++ b/scripts/zulip_emoji_merge_delegate.py @@ -107,7 +107,9 @@ print('Removing closed-pr') result = client.remove_reaction({ "message_id": message['id'], - "emoji_name": "closed-pr" + "emoji_name": "closed-pr", + "emoji_code": "61282", + "reaction_type": "realm_emoji", }) print(f"result: '{result}'") From 2c7ec21b4943ecc9c88180b443aaef2be33136b9 Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 22 Jan 2025 08:55:03 +0000 Subject: [PATCH 403/681] fix(Zulip closed pr): use emoji code for newer version of `:closed-pr:` (#20942) When the emoji changed, its `emoji_code` also changed. This PR uses the current code. --- scripts/zulip_emoji_merge_delegate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/zulip_emoji_merge_delegate.py b/scripts/zulip_emoji_merge_delegate.py index b882ff416cf6b..fbc811d1671a9 100644 --- a/scripts/zulip_emoji_merge_delegate.py +++ b/scripts/zulip_emoji_merge_delegate.py @@ -72,6 +72,7 @@ print(f"matched: '{message}'") # removing previous emoji reactions + # if the emoji is a custom emoji, add the fields `emoji_code` and `reaction_type` as well print("Removing previous reactions, if present.") if has_peace_sign: print('Removing peace_sign') @@ -108,7 +109,7 @@ result = client.remove_reaction({ "message_id": message['id'], "emoji_name": "closed-pr", - "emoji_code": "61282", + "emoji_code": "61293", # 61282 was the earlier version of the emoji "reaction_type": "realm_emoji", }) print(f"result: '{result}'") From c971e4ff5f0ee3068c1c30f9ae9c38385331e004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 22 Jan 2025 09:03:51 +0000 Subject: [PATCH 404/681] feat: a non-zero constant function is integrable iff the measure is finite (#20914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The situation here is that I want to case on `IsFiniteMeasure μ`, and in the negative branch I want to get `¬ Integrable (fun _ ↦ c) μ`. The current lemma `integrable_const_iff` is not very useful for that. From my PhD (LeanCamCombi) --- Mathlib/MeasureTheory/Function/L1Space.lean | 18 +++++++++++++----- Mathlib/MeasureTheory/Integral/Bochner.lean | 16 +++++++--------- .../MeasureTheory/Integral/IntegrableOn.lean | 11 +++++------ Mathlib/MeasureTheory/Integral/Pi.lean | 2 +- Mathlib/MeasureTheory/Measure/Typeclasses.lean | 9 +++++---- 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 31148a529c769..a14a9f3c0bea4 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -150,13 +150,17 @@ theorem hasFiniteIntegral_congr {f g : α → β} (h : f =ᵐ[μ] g) : hasFiniteIntegral_congr' <| h.fun_comp norm theorem hasFiniteIntegral_const_iff {c : β} : - HasFiniteIntegral (fun _ : α => c) μ ↔ c = 0 ∨ μ univ < ∞ := by + HasFiniteIntegral (fun _ : α => c) μ ↔ c = 0 ∨ IsFiniteMeasure μ := by simp [hasFiniteIntegral_iff_nnnorm, lintegral_const, lt_top_iff_ne_top, ENNReal.mul_eq_top, - or_iff_not_imp_left] + or_iff_not_imp_left, isFiniteMeasure_iff] + +lemma hasFiniteIntegral_const_iff_isFiniteMeasure {c : β} (hc : c ≠ 0) : + HasFiniteIntegral (fun _ ↦ c) μ ↔ IsFiniteMeasure μ := by + simp [hasFiniteIntegral_const_iff, hc, isFiniteMeasure_iff] theorem hasFiniteIntegral_const [IsFiniteMeasure μ] (c : β) : HasFiniteIntegral (fun _ : α => c) μ := - hasFiniteIntegral_const_iff.2 (Or.inr <| measure_lt_top _ _) + hasFiniteIntegral_const_iff.2 <| .inr ‹_› theorem HasFiniteIntegral.of_mem_Icc [IsFiniteMeasure μ] (a b : ℝ) {X : α → ℝ} (h : ∀ᵐ ω ∂μ, X ω ∈ Set.Icc a b) : @@ -449,10 +453,14 @@ theorem Integrable.congr {f g : α → β} (hf : Integrable f μ) (h : f =ᵐ[μ theorem integrable_congr {f g : α → β} (h : f =ᵐ[μ] g) : Integrable f μ ↔ Integrable g μ := ⟨fun hf => hf.congr h, fun hg => hg.congr h.symm⟩ -theorem integrable_const_iff {c : β} : Integrable (fun _ : α => c) μ ↔ c = 0 ∨ μ univ < ∞ := by +lemma integrable_const_iff {c : β} : Integrable (fun _ : α => c) μ ↔ c = 0 ∨ IsFiniteMeasure μ := by have : AEStronglyMeasurable (fun _ : α => c) μ := aestronglyMeasurable_const rw [Integrable, and_iff_right this, hasFiniteIntegral_const_iff] +lemma integrable_const_iff_isFiniteMeasure {c : β} (hc : c ≠ 0) : + Integrable (fun _ ↦ c) μ ↔ IsFiniteMeasure μ := by + simp [integrable_const_iff, hc, isFiniteMeasure_iff] + theorem Integrable.of_mem_Icc [IsFiniteMeasure μ] (a b : ℝ) {X : α → ℝ} (hX : AEMeasurable X μ) (h : ∀ᵐ ω ∂μ, X ω ∈ Set.Icc a b) : Integrable X μ := @@ -460,7 +468,7 @@ theorem Integrable.of_mem_Icc [IsFiniteMeasure μ] (a b : ℝ) {X : α → ℝ} @[simp] theorem integrable_const [IsFiniteMeasure μ] (c : β) : Integrable (fun _ : α => c) μ := - integrable_const_iff.2 <| Or.inr <| measure_lt_top _ _ + integrable_const_iff.2 <| .inr ‹_› @[simp] lemma Integrable.of_finite [Finite α] [MeasurableSingletonClass α] [IsFiniteMeasure μ] {f : α → β} : diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index 2720940a760a3..5153c29f675cc 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -1388,16 +1388,14 @@ theorem SimpleFunc.integral_eq_sum (f : α →ₛ E) (hfi : Integrable f μ) : @[simp] theorem integral_const (c : E) : ∫ _ : α, c ∂μ = (μ univ).toReal • c := by - cases' (@le_top _ _ _ (μ univ)).lt_or_eq with hμ hμ - · haveI : IsFiniteMeasure μ := ⟨hμ⟩ - simp only [integral, hE, L1.integral] + by_cases hμ : IsFiniteMeasure μ + · simp only [integral, hE, L1.integral] exact setToFun_const (dominatedFinMeasAdditive_weightedSMul _) _ - · by_cases hc : c = 0 - · simp [hc, integral_zero] - · have : ¬Integrable (fun _ : α => c) μ := by - simp only [integrable_const_iff, not_or] - exact ⟨hc, hμ.not_lt⟩ - simp [integral_undef, *] + by_cases hc : c = 0 + · simp [hc, integral_zero] + · simp [integral_undef, (integrable_const_iff_isFiniteMeasure hc).not.2 hμ, *] + simp only [isFiniteMeasure_iff, not_lt, top_le_iff] at hμ + simp [hμ] theorem norm_integral_le_of_norm_le_const [IsFiniteMeasure μ] {f : α → G} {C : ℝ} (h : ∀ᵐ x ∂μ, ‖f x‖ ≤ C) : ‖∫ x, f x ∂μ‖ ≤ C * (μ univ).toReal := diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index 4da7bce1104cf..c476a8473164b 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -95,7 +95,7 @@ theorem integrableOn_zero : IntegrableOn (fun _ => (0 : E)) s μ := @[simp] theorem integrableOn_const {C : E} : IntegrableOn (fun _ => C) s μ ↔ C = 0 ∨ μ s < ∞ := - integrable_const_iff.trans <| by rw [Measure.restrict_apply_univ] + integrable_const_iff.trans <| by rw [isFiniteMeasure_restrict, lt_top_iff_ne_top] theorem IntegrableOn.mono (h : IntegrableOn f t ν) (hs : s ⊆ t) (hμ : μ ≤ ν) : IntegrableOn f s μ := h.mono_measure <| Measure.restrict_mono hs hμ @@ -166,8 +166,8 @@ theorem integrableOn_singleton_iff {x : α} [MeasurableSingletonClass α] : have : f =ᵐ[μ.restrict {x}] fun _ => f x := by filter_upwards [ae_restrict_mem (measurableSet_singleton x)] with _ ha simp only [mem_singleton_iff.1 ha] - rw [IntegrableOn, integrable_congr this, integrable_const_iff] - simp + rw [IntegrableOn, integrable_congr this, integrable_const_iff, isFiniteMeasure_restrict, + lt_top_iff_ne_top] @[simp] theorem integrableOn_finite_biUnion {s : Set β} (hs : s.Finite) {t : β → Set α} : @@ -252,9 +252,8 @@ theorem integrable_indicatorConstLp {E} [NormedAddCommGroup E] {p : ℝ≥0∞} (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (c : E) : Integrable (indicatorConstLp p hs hμs c) μ := by rw [integrable_congr indicatorConstLp_coeFn, integrable_indicator_iff hs, IntegrableOn, - integrable_const_iff, lt_top_iff_ne_top] - right - simpa only [Set.univ_inter, MeasurableSet.univ, Measure.restrict_apply] using hμs + integrable_const_iff, isFiniteMeasure_restrict] + exact .inr hμs /-- If a function is integrable on a set `s` and nonzero there, then the measurable hull of `s` is well behaved: the restriction of the measure to `toMeasurable μ s` coincides with its restriction diff --git a/Mathlib/MeasureTheory/Integral/Pi.lean b/Mathlib/MeasureTheory/Integral/Pi.lean index 2bf9b9af0c309..9e6ba84a0ce90 100644 --- a/Mathlib/MeasureTheory/Integral/Pi.lean +++ b/Mathlib/MeasureTheory/Integral/Pi.lean @@ -28,7 +28,7 @@ theorem Integrable.fin_nat_prod {n : ℕ} {E : Fin n → Type*} {f : (i : Fin n) → E i → 𝕜} (hf : ∀ i, Integrable (f i)) : Integrable (fun (x : (i : Fin n) → E i) ↦ ∏ i, f i (x i)) := by induction n with - | zero => simp only [Finset.univ_eq_empty, Finset.prod_empty, volume_pi, + | zero => simp only [Finset.univ_eq_empty, Finset.prod_empty, volume_pi, isFiniteMeasure_iff, integrable_const_iff, one_ne_zero, pi_empty_univ, ENNReal.one_lt_top, or_true] | succ n n_ih => have := ((measurePreserving_piFinSuccAbove (fun i => (volume : Measure (E i))) 0).symm) diff --git a/Mathlib/MeasureTheory/Measure/Typeclasses.lean b/Mathlib/MeasureTheory/Measure/Typeclasses.lean index fcd3da6faea7c..cb4284f411de1 100644 --- a/Mathlib/MeasureTheory/Measure/Typeclasses.lean +++ b/Mathlib/MeasureTheory/Measure/Typeclasses.lean @@ -34,13 +34,14 @@ variable {m0 : MeasurableSpace α} [MeasurableSpace β] {μ ν ν₁ ν₂ : Mea section IsFiniteMeasure /-- A measure `μ` is called finite if `μ univ < ∞`. -/ +@[mk_iff] class IsFiniteMeasure (μ : Measure α) : Prop where measure_univ_lt_top : μ univ < ∞ -theorem not_isFiniteMeasure_iff : ¬IsFiniteMeasure μ ↔ μ Set.univ = ∞ := by - refine ⟨fun h => ?_, fun h => fun h' => h'.measure_univ_lt_top.ne h⟩ - by_contra h' - exact h ⟨lt_top_iff_ne_top.mpr h'⟩ +lemma not_isFiniteMeasure_iff : ¬IsFiniteMeasure μ ↔ μ univ = ∞ := by simp [isFiniteMeasure_iff] + +lemma isFiniteMeasure_restrict : IsFiniteMeasure (μ.restrict s) ↔ μ s ≠ ∞ := by + simp [isFiniteMeasure_iff, lt_top_iff_ne_top] instance Restrict.isFiniteMeasure (μ : Measure α) [hs : Fact (μ s < ∞)] : IsFiniteMeasure (μ.restrict s) := From ca7a3cdb6f97462bf2feb407a6dbe1dd3f6d96bf Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Wed, 22 Jan 2025 09:20:01 +0000 Subject: [PATCH 405/681] =?UTF-8?q?feat(Multiset/Fintype):=20`Multiset.ToT?= =?UTF-8?q?ype`=20equivalence=20between=20`v=20::=E2=82=98=20m`=20and=20`O?= =?UTF-8?q?ption=20m`=20(#19508)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also add an arbitrary equivalence `s ≃ s.map f` Co-authored-by: Daniel Weber <55664973+Command-Master@users.noreply.github.com> --- Mathlib/Data/Multiset/Fintype.lean | 147 +++++++++++++++++++++++------ 1 file changed, 119 insertions(+), 28 deletions(-) diff --git a/Mathlib/Data/Multiset/Fintype.lean b/Mathlib/Data/Multiset/Fintype.lean index ed70e899db4db..794a59feb7c3f 100644 --- a/Mathlib/Data/Multiset/Fintype.lean +++ b/Mathlib/Data/Multiset/Fintype.lean @@ -33,11 +33,13 @@ multiset enumeration -/ -variable {α : Type*} [DecidableEq α] {m : Multiset α} +variable {α β : Type*} [DecidableEq α] [DecidableEq β] {m : Multiset α} + +namespace Multiset /-- Auxiliary definition for the `CoeSort` instance. This prevents the `CoeOut m α` instance from inadvertently applying to other sigma types. -/ -def Multiset.ToType (m : Multiset α) : Type _ := (x : α) × Fin (m.count x) +def ToType (m : Multiset α) : Type _ := (x : α) × Fin (m.count x) /-- Create a type that has the same number of elements as the multiset. Terms of this type are triples `⟨x, ⟨i, h⟩⟩` where `x : α`, `i : ℕ`, and `h : i < m.count x`. @@ -51,7 +53,7 @@ example : DecidableEq m := inferInstanceAs <| DecidableEq ((x : α) × Fin (m.co /-- Constructor for terms of the coercion of `m` to a type. This helps Lean pick up the correct instances. -/ @[reducible, match_pattern] -def Multiset.mkToType (m : Multiset α) (x : α) (i : Fin (m.count x)) : m := +def mkToType (m : Multiset α) (x : α) (i : Fin (m.count x)) : m := ⟨x, i⟩ /-- As a convenience, there is a coercion from `m : Type*` to `α` by projecting onto the first @@ -64,18 +66,18 @@ instance instCoeSortMultisetType.instCoeOutToType : CoeOut m α := -- Syntactic equality -- @[simp] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/10685): dsimp can prove this -theorem Multiset.coe_mk {x : α} {i : Fin (m.count x)} : ↑(m.mkToType x i) = x := +theorem coe_mk {x : α} {i : Fin (m.count x)} : ↑(m.mkToType x i) = x := rfl -@[simp] lemma Multiset.coe_mem {x : m} : ↑x ∈ m := Multiset.count_pos.mp (by have := x.2.2; omega) +@[simp] lemma coe_mem {x : m} : ↑x ∈ m := Multiset.count_pos.mp (by have := x.2.2; omega) @[simp] -protected theorem Multiset.forall_coe (p : m → Prop) : +protected theorem forall_coe (p : m → Prop) : (∀ x : m, p x) ↔ ∀ (x : α) (i : Fin (m.count x)), p ⟨x, i⟩ := Sigma.forall @[simp] -protected theorem Multiset.exists_coe (p : m → Prop) : +protected theorem exists_coe (p : m → Prop) : (∃ x : m, p x) ↔ ∃ (x : α) (i : Fin (m.count x)), p ⟨x, i⟩ := Sigma.exists @@ -92,19 +94,17 @@ instance : Fintype { p : α × ℕ | p.2 < m.count p.1 } := /-- Construct a finset whose elements enumerate the elements of the multiset `m`. The `ℕ` component is used to differentiate between equal elements: if `x` appears `n` times then `(x, 0)`, ..., and `(x, n-1)` appear in the `Finset`. -/ -def Multiset.toEnumFinset (m : Multiset α) : Finset (α × ℕ) := +def toEnumFinset (m : Multiset α) : Finset (α × ℕ) := { p : α × ℕ | p.2 < m.count p.1 }.toFinset @[simp] -theorem Multiset.mem_toEnumFinset (m : Multiset α) (p : α × ℕ) : +theorem mem_toEnumFinset (m : Multiset α) (p : α × ℕ) : p ∈ m.toEnumFinset ↔ p.2 < m.count p.1 := Set.mem_toFinset -theorem Multiset.mem_of_mem_toEnumFinset {p : α × ℕ} (h : p ∈ m.toEnumFinset) : p.1 ∈ m := +theorem mem_of_mem_toEnumFinset {p : α × ℕ} (h : p ∈ m.toEnumFinset) : p.1 ∈ m := have := (m.mem_toEnumFinset p).mp h; Multiset.count_pos.mp (by omega) -namespace Multiset - @[simp] lemma toEnumFinset_filter_eq (m : Multiset α) (a : α) : m.toEnumFinset.filter (·.1 = a) = {a} ×ˢ Finset.range (m.count a) := by aesop @@ -132,24 +132,22 @@ namespace Multiset omega exact Nat.le_of_pred_lt (han.trans_lt <| by simpa using hsm hn) -end Multiset - @[mono] -theorem Multiset.toEnumFinset_mono {m₁ m₂ : Multiset α} (h : m₁ ≤ m₂) : +theorem toEnumFinset_mono {m₁ m₂ : Multiset α} (h : m₁ ≤ m₂) : m₁.toEnumFinset ⊆ m₂.toEnumFinset := by intro p simp only [Multiset.mem_toEnumFinset] exact gt_of_ge_of_gt (Multiset.le_iff_count.mp h p.1) @[simp] -theorem Multiset.toEnumFinset_subset_iff {m₁ m₂ : Multiset α} : +theorem toEnumFinset_subset_iff {m₁ m₂ : Multiset α} : m₁.toEnumFinset ⊆ m₂.toEnumFinset ↔ m₁ ≤ m₂ := ⟨fun h ↦ by simpa using map_fst_le_of_subset_toEnumFinset h, Multiset.toEnumFinset_mono⟩ /-- The embedding from a multiset into `α × ℕ` where the second coordinate enumerates repeats. If you are looking for the function `m → α`, that would be plain `(↑)`. -/ @[simps] -def Multiset.coeEmbedding (m : Multiset α) : m ↪ α × ℕ where +def coeEmbedding (m : Multiset α) : m ↪ α × ℕ where toFun x := (x, x.2) inj' := by intro ⟨x, i, hi⟩ ⟨y, j, hj⟩ @@ -159,7 +157,7 @@ def Multiset.coeEmbedding (m : Multiset α) : m ↪ α × ℕ where /-- Another way to coerce a `Multiset` to a type is to go through `m.toEnumFinset` and coerce that `Finset` to a type. -/ @[simps] -def Multiset.coeEquiv (m : Multiset α) : m ≃ m.toEnumFinset where +def coeEquiv (m : Multiset α) : m ≃ m.toEnumFinset where toFun x := ⟨m.coeEmbedding x, by rw [Multiset.mem_toEnumFinset] @@ -176,14 +174,14 @@ def Multiset.coeEquiv (m : Multiset α) : m ≃ m.toEnumFinset where rfl @[simp] -theorem Multiset.toEmbedding_coeEquiv_trans (m : Multiset α) : +theorem toEmbedding_coeEquiv_trans (m : Multiset α) : m.coeEquiv.toEmbedding.trans (Function.Embedding.subtype _) = m.coeEmbedding := by ext <;> rfl @[irreducible] -instance Multiset.fintypeCoe : Fintype m := +instance fintypeCoe : Fintype m := Fintype.ofEquiv m.toEnumFinset m.coeEquiv.symm -theorem Multiset.map_univ_coeEmbedding (m : Multiset α) : +theorem map_univ_coeEmbedding (m : Multiset α) : (Finset.univ : Finset m).map m.coeEmbedding = m.toEnumFinset := by ext ⟨x, i⟩ simp only [Fin.exists_iff, Finset.mem_map, Finset.mem_univ, Multiset.coeEmbedding_apply, @@ -191,7 +189,7 @@ theorem Multiset.map_univ_coeEmbedding (m : Multiset α) : exists_prop, exists_eq_right_right, exists_eq_right, Multiset.mem_toEnumFinset, true_and] @[simp] -theorem Multiset.map_univ_coe (m : Multiset α) : +theorem map_univ_coe (m : Multiset α) : (Finset.univ : Finset m).val.map (fun x : m ↦ (x : α)) = m := by have := m.map_toEnumFinset_fst rw [← m.map_univ_coeEmbedding] at this @@ -199,36 +197,129 @@ theorem Multiset.map_univ_coe (m : Multiset α) : Function.comp_apply] using this @[simp] -theorem Multiset.map_univ {β : Type*} (m : Multiset α) (f : α → β) : +theorem map_univ {β : Type*} (m : Multiset α) (f : α → β) : ((Finset.univ : Finset m).val.map fun (x : m) ↦ f (x : α)) = m.map f := by erw [← Multiset.map_map, Multiset.map_univ_coe] @[simp] -theorem Multiset.card_toEnumFinset (m : Multiset α) : m.toEnumFinset.card = Multiset.card m := by +theorem card_toEnumFinset (m : Multiset α) : m.toEnumFinset.card = Multiset.card m := by rw [Finset.card, ← Multiset.card_map Prod.fst m.toEnumFinset.val] congr exact m.map_toEnumFinset_fst @[simp] -theorem Multiset.card_coe (m : Multiset α) : Fintype.card m = Multiset.card m := by +theorem card_coe (m : Multiset α) : Fintype.card m = Multiset.card m := by rw [Fintype.card_congr m.coeEquiv] simp only [Fintype.card_coe, card_toEnumFinset] @[to_additive] -theorem Multiset.prod_eq_prod_coe [CommMonoid α] (m : Multiset α) : m.prod = ∏ x : m, (x : α) := by +theorem prod_eq_prod_coe [CommMonoid α] (m : Multiset α) : m.prod = ∏ x : m, (x : α) := by congr simp @[to_additive] -theorem Multiset.prod_eq_prod_toEnumFinset [CommMonoid α] (m : Multiset α) : +theorem prod_eq_prod_toEnumFinset [CommMonoid α] (m : Multiset α) : m.prod = ∏ x ∈ m.toEnumFinset, x.1 := by congr simp @[to_additive] -theorem Multiset.prod_toEnumFinset {β : Type*} [CommMonoid β] (m : Multiset α) (f : α → ℕ → β) : +theorem prod_toEnumFinset {β : Type*} [CommMonoid β] (m : Multiset α) (f : α → ℕ → β) : ∏ x ∈ m.toEnumFinset, f x.1 x.2 = ∏ x : m, f x x.2 := by rw [Fintype.prod_equiv m.coeEquiv (fun x ↦ f x x.2) fun x ↦ f x.1.1 x.1.2] · rw [← m.toEnumFinset.prod_coe_sort fun x ↦ f x.1 x.2] · intro x rfl + +/-- +If `s = t` then there's an equivalence between the appropriate types. +-/ +@[simps] +def cast {s t : Multiset α} (h : s = t) : s ≃ t where + toFun x := ⟨x.1, x.2.cast (by simp [h])⟩ + invFun x := ⟨x.1, x.2.cast (by simp [h])⟩ + left_inv x := rfl + right_inv x := rfl + +instance : IsEmpty (0 : Multiset α) := Fintype.card_eq_zero_iff.mp (by simp) + +instance : IsEmpty (∅ : Multiset α) := Fintype.card_eq_zero_iff.mp (by simp) + +/-- +`v ::ₘ m` is equivalent to `Option m` by mapping one `v` to `none` and everything else to `m`. +-/ +def consEquiv {v : α} : v ::ₘ m ≃ Option m where + toFun x := if h : x.1 = v ∧ x.2.val = m.count v then none else some ⟨x.1, ⟨x.2, by + by_cases hv : x.1 = v + · simp only [hv, true_and] at h ⊢ + apply lt_of_le_of_ne (Nat.le_of_lt_add_one _) h + convert x.2.2 using 1 + simp [hv] + · convert x.2.2 using 1 + exact (count_cons_of_ne hv _).symm + ⟩⟩ + invFun x := x.elim ⟨v, ⟨m.count v, by simp⟩⟩ (fun x ↦ ⟨x.1, x.2.castLE (count_le_count_cons ..)⟩) + left_inv := by + rintro ⟨x, hx⟩ + dsimp only + split + · rename_i h + obtain ⟨rfl, h2⟩ := h + simp [← h2] + · simp + right_inv := by + rintro (_ | x) + · simp + · simp only [Option.elim_some, Nat.zero_eq, Fin.coe_castLE, Fin.eta, Sigma.eta, dite_eq_ite, + ite_eq_right_iff, reduceCtorEq, imp_false, not_and] + rintro rfl + exact x.2.2.ne + +@[simp] +lemma consEquiv_symm_none {v : α} : + (consEquiv (m := m) (v := v)).symm none = + ⟨v, ⟨m.count v, (count_cons_self v m) ▸ (Nat.lt_add_one _)⟩⟩ := + rfl + +@[simp] +lemma consEquiv_symm_some {v : α} {x : m} : + (consEquiv (v := v)).symm (some x) = + ⟨x, x.2.castLE (count_le_count_cons ..)⟩ := + rfl + +lemma coe_consEquiv_of_ne {v : α} (x : v ::ₘ m) (hx : ↑x ≠ v) : + consEquiv x = some ⟨x.1, x.2.cast (by simp [hx])⟩ := by + simp [consEquiv, hx] + rfl + +lemma coe_consEquiv_of_eq_of_eq {v : α} (x : v ::ₘ m) (hx : ↑x = v) (hx2 : x.2 = m.count v) : + consEquiv x = none := by simp [consEquiv, hx, hx2] + +lemma coe_consEquiv_of_eq_of_lt {v : α} (x : v ::ₘ m) (hx : ↑x = v) (hx2 : x.2 < m.count v) : + consEquiv x = some ⟨x.1, ⟨x.2, by simpa [hx]⟩⟩ := by simp [consEquiv, hx, hx2.ne] + +/-- +There is some equivalence between `m` and `m.map f` which respects `f`. +-/ +def mapEquiv_aux (m : Multiset α) (f : α → β) : + Squash { v : m ≃ m.map f // ∀ a : m, v a = f a} := + Quotient.recOnSubsingleton m fun l ↦ .mk <| + List.recOn l + ⟨@Equiv.equivOfIsEmpty _ _ (by dsimp; infer_instance) (by dsimp; infer_instance), by simp⟩ + fun a s ⟨v, hv⟩ ↦ ⟨Multiset.consEquiv.trans v.optionCongr |>.trans + Multiset.consEquiv.symm |>.trans (Multiset.cast (map_cons f a s)).symm, fun x ↦ by + simp only [consEquiv, Equiv.trans_apply, Equiv.coe_fn_mk, Equiv.optionCongr_apply, + Equiv.coe_fn_symm_mk, cast_symm_apply_fst] + split <;> simp_all⟩ + +/-- +One of the possible equivalences from `Multiset.mapEquiv_aux`, selected using choice. +-/ +noncomputable def mapEquiv (s : Multiset α) (f : α → β) : s ≃ s.map f := + (Multiset.mapEquiv_aux s f).out.1 + +@[simp] +theorem mapEquiv_apply (s : Multiset α) (f : α → β) (v : s) : s.mapEquiv f v = f v := + (Multiset.mapEquiv_aux s f).out.2 v + +end Multiset From dc940b9d2103bbdc2af023bfc13f83296726af5d Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Wed, 22 Jan 2025 09:20:03 +0000 Subject: [PATCH 406/681] feat(CategoryTheory): Pull back filteredness along representably flat functors (#20864) --- Mathlib.lean | 1 + .../Filtered/CostructuredArrow.lean | 32 ++++++++++++--- Mathlib/CategoryTheory/Filtered/Flat.lean | 39 +++++++++++++++++++ Mathlib/CategoryTheory/Functor/Flat.lean | 7 ++++ 4 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 Mathlib/CategoryTheory/Filtered/Flat.lean diff --git a/Mathlib.lean b/Mathlib.lean index 9eeb7460242e9..289ece73daea8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1796,6 +1796,7 @@ import Mathlib.CategoryTheory.Filtered.Basic import Mathlib.CategoryTheory.Filtered.Connected import Mathlib.CategoryTheory.Filtered.CostructuredArrow import Mathlib.CategoryTheory.Filtered.Final +import Mathlib.CategoryTheory.Filtered.Flat import Mathlib.CategoryTheory.Filtered.Grothendieck import Mathlib.CategoryTheory.Filtered.OfColimitCommutesFiniteLimit import Mathlib.CategoryTheory.Filtered.Small diff --git a/Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean b/Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean index 042909b9caa30..2e51870130933 100644 --- a/Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean +++ b/Mathlib/CategoryTheory/Filtered/CostructuredArrow.lean @@ -18,19 +18,18 @@ import Mathlib.CategoryTheory.Limits.Final -/ -universe w v₁ u₁ +universe v₁ v₂ v₃ u₁ u₂ u₃ namespace CategoryTheory open Limits Functor +section Small + variable {A : Type u₁} [SmallCategory A] {B : Type u₁} [SmallCategory B] variable {T : Type u₁} [SmallCategory T] -/-- Given functors `L : A ⥤ T` and `R : B ⥤ T` with a common codomain we can conclude that `A` -is filtered given that `R` is final, `B` is filtered and each costructured arrow category -`CostructuredArrow L (R.obj b)` is filtered. -/ -theorem isFiltered_of_isFiltered_costructuredArrow (L : A ⥤ T) (R : B ⥤ T) +private lemma isFiltered_of_isFiltered_costructuredArrow_small (L : A ⥤ T) (R : B ⥤ T) [IsFiltered B] [Final R] [∀ b, IsFiltered (CostructuredArrow L (R.obj b))] : IsFiltered A := isFiltered_of_nonempty_limit_colimit_to_colimit_limit fun J {_ _} F => ⟨by let R' := Grothendieck.pre (CostructuredArrow.functor L) R @@ -46,4 +45,27 @@ theorem isFiltered_of_isFiltered_costructuredArrow (L : A ⥤ T) (R : B ⥤ T) (colimitIsoColimitGrothendieck L (limit F)).inv exact (limitCompWhiskeringLeftIsoCompLimit F (R' ⋙ CostructuredArrow.grothendieckProj L)).hom⟩ +end Small + +variable {A : Type u₁} [Category.{v₁} A] {B : Type u₂} [Category.{v₂} B] +variable {T : Type u₃} [Category.{v₃} T] + +/-- Given functors `L : A ⥤ T` and `R : B ⥤ T` with a common codomain we can conclude that `A` +is filtered given that `R` is final, `B` is filtered and each costructured arrow category +`CostructuredArrow L (R.obj b)` is filtered. -/ +theorem isFiltered_of_isFiltered_costructuredArrow (L : A ⥤ T) (R : B ⥤ T) + [IsFiltered B] [Final R] [∀ b, IsFiltered (CostructuredArrow L (R.obj b))] : IsFiltered A := by + let sA : A ≌ AsSmall.{max u₁ u₂ u₃ v₁ v₂ v₃} A := AsSmall.equiv + let sB : B ≌ AsSmall.{max u₁ u₂ u₃ v₁ v₂ v₃} B := AsSmall.equiv + let sT : T ≌ AsSmall.{max u₁ u₂ u₃ v₁ v₂ v₃} T := AsSmall.equiv + let sC : ∀ b, CostructuredArrow (sA.inverse ⋙ L ⋙ sT.functor) + ((sB.inverse ⋙ R ⋙ sT.functor).obj ⟨b⟩) ≌ CostructuredArrow L (R.obj b) := fun b => + (CostructuredArrow.pre sA.inverse (L ⋙ sT.functor) _).asEquivalence.trans + (CostructuredArrow.post L sT.functor _).asEquivalence.symm + haveI : ∀ b, IsFiltered (CostructuredArrow _ ((sB.inverse ⋙ R ⋙ sT.functor).obj b)) := + fun b => IsFiltered.of_equivalence (sC b.1).symm + haveI := isFiltered_of_isFiltered_costructuredArrow_small + (sA.inverse ⋙ L ⋙ sT.functor) (sB.inverse ⋙ R ⋙ sT.functor) + exact IsFiltered.of_equivalence sA.symm + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Filtered/Flat.lean b/Mathlib/CategoryTheory/Filtered/Flat.lean new file mode 100644 index 0000000000000..f4ca7ef2b7bb2 --- /dev/null +++ b/Mathlib/CategoryTheory/Filtered/Flat.lean @@ -0,0 +1,39 @@ +/- +Copyright (c) 2025 Jakob von Raumer. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jakob von Raumer +-/ +import Mathlib.CategoryTheory.Filtered.CostructuredArrow +import Mathlib.CategoryTheory.Functor.Flat + +/-! +# Pulling back filteredness along representably flat functors + +We show that if `F : C ⥤ D` is a representably coflat functor between two categories, +filteredness of `D` implies filteredness of `C`. Dually, if `F` is representably flat, +cofilteredness of `D` implies cofilteredness of `C`. + +Transferring (co)filteredness *along* representably (co)flat functors is given by +`IsFiltered.of_final` and its dual, since every representably flat functor is final and every +representably coflat functor is initial. +-/ + +universe v₁ v₂ u₁ u₂ + +namespace CategoryTheory + +open Limits + +variable {C : Type u₁} [Category.{v₁} C] +variable {D : Type u₂} [Category.{v₂} D] +variable (F : C ⥤ D) + +lemma isFiltered_of_representablyCoflat [IsFiltered D] [RepresentablyCoflat F] : IsFiltered C := + isFiltered_of_isFiltered_costructuredArrow F (𝟭 _) + +lemma isCofiltered_of_representablyFlat [IsCofiltered D] [RepresentablyFlat F] : + IsCofiltered C := by + have := isFiltered_of_representablyCoflat F.op + exact isCofiltered_of_isFiltered_op C + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Functor/Flat.lean b/Mathlib/CategoryTheory/Functor/Flat.lean index c828dd56ec407..b521f581f772a 100644 --- a/Mathlib/CategoryTheory/Functor/Flat.lean +++ b/Mathlib/CategoryTheory/Functor/Flat.lean @@ -3,6 +3,7 @@ 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.CategoryTheory.Filtered.Connected import Mathlib.CategoryTheory.Limits.ConeCategory import Mathlib.CategoryTheory.Limits.FilteredColimitCommutesFiniteLimit import Mathlib.CategoryTheory.Limits.Preserves.Filtered @@ -142,6 +143,12 @@ instance RepresentablyCoflat.comp (G : D ⥤ E) [RepresentablyCoflat F] [Represe RepresentablyCoflat (F ⋙ G) := (representablyFlat_op_iff _).1 <| inferInstanceAs <| RepresentablyFlat (F.op ⋙ G.op) +lemma final_of_representablyFlat [h : RepresentablyFlat F] : F.Final where + out _ := IsCofiltered.isConnected _ + +lemma initial_of_representablyCoflat [h : RepresentablyCoflat F] : F.Initial where + out _ := IsFiltered.isConnected _ + end RepresentablyFlat section HasLimit From aaf3fad0d3b04d0f239748d32ba772035b94fbf6 Mon Sep 17 00:00:00 2001 From: Alex Meiburg Date: Wed, 22 Jan 2025 09:34:09 +0000 Subject: [PATCH 407/681] feat(Logic/Equiv/Basic): sumSigmaDistrib, finSigmaFinEquiv (#19618) Upstreamed from the [EquationalTheories](https://github.com/teorth/equational_theories) project. [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/) Co-authored-by: Alex Meiburg --- Mathlib/Algebra/BigOperators/Fin.lean | 42 +++++++++++++++++++++++++++ Mathlib/Logic/Equiv/Basic.lean | 32 +++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/Mathlib/Algebra/BigOperators/Fin.lean b/Mathlib/Algebra/BigOperators/Fin.lean index 045c79a9465a3..2a445b2244dcc 100644 --- a/Mathlib/Algebra/BigOperators/Fin.lean +++ b/Mathlib/Algebra/BigOperators/Fin.lean @@ -388,6 +388,48 @@ theorem finPiFinEquiv_single {m : ℕ} {n : Fin m → ℕ} [∀ i, NeZero (n i)] rintro x hx rw [Pi.single_eq_of_ne hx, Fin.val_zero', zero_mul] +/-- Equivalence between the Sigma type `(i : Fin m) × Fin (n i)` and `Fin (∑ i : Fin m, n i)`. -/ +def finSigmaFinEquiv {m : ℕ} {n : Fin m → ℕ} : (i : Fin m) × Fin (n i) ≃ Fin (∑ i : Fin m, n i) := + match m with + | 0 => @Equiv.equivOfIsEmpty _ _ _ (by simp; exact Fin.isEmpty') + | Nat.succ m => + calc _ ≃ _ := (@finSumFinEquiv m 1).sigmaCongrLeft.symm + _ ≃ _ := Equiv.sumSigmaDistrib _ + _ ≃ _ := finSigmaFinEquiv.sumCongr (Equiv.uniqueSigma _) + _ ≃ _ := finSumFinEquiv + _ ≃ _ := finCongr (Fin.sum_univ_castSucc n).symm + +@[simp] +theorem finSigmaFinEquiv_apply {m : ℕ} {n : Fin m → ℕ} (k : (i : Fin m) × Fin (n i)) : + (finSigmaFinEquiv k : ℕ) = ∑ i : Fin k.1, n (Fin.castLE k.1.2.le i) + k.2 := by + induction m + · exact k.fst.elim0 + rename_i m ih + rcases k with ⟨⟨iv,hi⟩,j⟩ + rw [finSigmaFinEquiv] + unfold finSumFinEquiv + simp only [Equiv.coe_fn_mk, Equiv.sigmaCongrLeft, Equiv.coe_fn_symm_mk, Equiv.instTrans_trans, + Equiv.trans_apply, finCongr_apply, Fin.coe_cast] + conv => + enter [1,1,3] + apply Equiv.sumCongr_apply + by_cases him : iv < m + · conv in Sigma.mk _ _ => + equals ⟨Sum.inl ⟨iv, him⟩, j⟩ => simp [Fin.addCases, him] + simpa using ih _ + · replace him := Nat.eq_of_lt_succ_of_not_lt hi him + subst him + conv in Sigma.mk _ _ => + equals ⟨Sum.inr 0, j⟩ => simp [Fin.addCases, Fin.natAdd] + simp + rfl + +/-- `finSigmaFinEquiv` on `Fin 1 × f` is just `f`-/ +theorem finSigmaFinEquiv_one {n : Fin 1 → ℕ} (ij : (i : Fin 1) × Fin (n i)) : + (finSigmaFinEquiv ij : ℕ) = ij.2 := by + rw [finSigmaFinEquiv_apply, add_left_eq_self] + apply @Finset.sum_of_isEmpty _ _ _ _ (by simpa using Fin.isEmpty') + namespace List section CommMonoid diff --git a/Mathlib/Logic/Equiv/Basic.lean b/Mathlib/Logic/Equiv/Basic.lean index 645bea7d22304..42d71d763a324 100644 --- a/Mathlib/Logic/Equiv/Basic.lean +++ b/Mathlib/Logic/Equiv/Basic.lean @@ -215,6 +215,23 @@ theorem sigmaUnique_symm_apply {α} {β : α → Type*} [∀ a, Unique (β a)] ( (sigmaUnique α β).symm x = ⟨x, default⟩ := rfl +/-- Any `Unique` type is a left identity for type sigma up to equivalence. Compare with `uniqueProd` +which is non-dependent. -/ +def uniqueSigma {α} (β : α → Type*) [Unique α] : (i:α) × β i ≃ β default := + ⟨fun p ↦ (Unique.eq_default _).rec p.2, + fun b ↦ ⟨default, b⟩, + fun _ ↦ Sigma.ext (Unique.default_eq _) (eqRec_heq _ _), + fun _ ↦ rfl⟩ + +theorem uniqueSigma_apply {α} {β : α → Type*} [Unique α] (x : (a : α) × β a) : + uniqueSigma β x = (Unique.eq_default _).rec x.2 := + rfl + +@[simp] +theorem uniqueSigma_symm_apply {α} {β : α → Type*} [Unique α] (y : β default) : + (uniqueSigma β).symm y = ⟨default, y⟩ := + rfl + /-- `Empty` type is a right absorbing element for type product up to an equivalence. -/ def prodEmpty (α) : α × Empty ≃ Empty := equivEmpty _ @@ -919,7 +936,8 @@ theorem prodSumDistrib_symm_apply_right {α β γ} (a : α × γ) : (prodSumDistrib α β γ).symm (inr a) = (a.1, inr a.2) := rfl -/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/ +/-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. Compare +with `Equiv.sumSigmaDistrib` which is indexed by sums. -/ @[simps] def sigmaSumDistrib {ι} (α β : ι → Type*) : (Σ i, α i ⊕ β i) ≃ (Σ i, α i) ⊕ (Σ i, β i) := @@ -927,6 +945,18 @@ def sigmaSumDistrib {ι} (α β : ι → Type*) : Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by rcases p with ⟨i, a | b⟩ <;> rfl, fun p => by rcases p with (⟨i, a⟩ | ⟨i, b⟩) <;> rfl⟩ +/-- A type indexed by disjoint sums of types is equivalent to the sum of the sums. Compare with +`Equiv.sigmaSumDistrib` which has the sums as the output type. -/ +@[simps] +def sumSigmaDistrib {α β} (t : α ⊕ β → Type*) : + (Σ i, t i) ≃ (Σ i, t (.inl i)) ⊕ (Σ i, t (.inr i)) := + ⟨(match · with + | .mk (.inl x) y => .inl ⟨x, y⟩ + | .mk (.inr x) y => .inr ⟨x, y⟩), + Sum.elim (fun a ↦ ⟨.inl a.1, a.2⟩) (fun b ↦ ⟨.inr b.1, b.2⟩), + by rintro ⟨x|x,y⟩ <;> simp, + by rintro (⟨x,y⟩|⟨x,y⟩) <;> simp⟩ + /-- The product of an indexed sum of types (formally, a `Sigma`-type `Σ i, α i`) by a type `β` is equivalent to the sum of products `Σ i, (α i × β)`. -/ @[simps apply symm_apply] From 25190fa231f8fbf2903cef5e0fa03895d6dfaa22 Mon Sep 17 00:00:00 2001 From: Vasily Nesterov Date: Wed, 22 Jan 2025 10:17:56 +0000 Subject: [PATCH 408/681] refactor(Data/Seq): mark `Seq.recOn` with `cases_eliminator` (#19829) Mark `Seq.recOn` with `cases_eliminator` to enable using `cases` tactic with sequences. --- Mathlib/Data/Seq/Parallel.lean | 4 +- Mathlib/Data/Seq/Seq.lean | 126 +++++++++++++++------------------ 2 files changed, 57 insertions(+), 73 deletions(-) diff --git a/Mathlib/Data/Seq/Parallel.lean b/Mathlib/Data/Seq/Parallel.lean index ee4bdac0f33db..16ea3f436d55d 100644 --- a/Mathlib/Data/Seq/Parallel.lean +++ b/Mathlib/Data/Seq/Parallel.lean @@ -157,9 +157,7 @@ theorem terminates_parallel {S : WSeq (Computation α)} {c} (h : c ∈ S) [T : T have TT : ∀ l', Terminates (corec parallel.aux1 (l', S.tail)) := by intro apply IH _ _ _ (Or.inr _) T - rw [a] - cases' S with f al - rfl + rw [a, Seq.get?_tail] induction' e : Seq.get? S 0 with o · have D : Seq.destruct S = none := by dsimp [Seq.destruct] diff --git a/Mathlib/Data/Seq/Seq.lean b/Mathlib/Data/Seq/Seq.lean index efcc4dfa696f6..172c4fc696654 100644 --- a/Mathlib/Data/Seq/Seq.lean +++ b/Mathlib/Data/Seq/Seq.lean @@ -230,14 +230,16 @@ theorem get?_tail (s : Seq α) (n) : get? (tail s) n = get? s (n + 1) := rfl /-- Recursion principle for sequences, compare with `List.recOn`. -/ -def recOn {C : Seq α → Sort v} (s : Seq α) (h1 : C nil) (h2 : ∀ x s, C (cons x s)) : - C s := by +@[cases_eliminator] +def recOn {motive : Seq α → Sort v} (s : Seq α) (nil : motive nil) + (cons : ∀ x s, motive (cons x s)) : + motive s := by cases' H : destruct s with v · rw [destruct_eq_nil H] - apply h1 + apply nil · cases' v with a s' rw [destruct_eq_cons H] - apply h2 + apply cons theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s) (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by @@ -251,10 +253,9 @@ theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s) rw [TH] apply h1 _ _ (Or.inl rfl) -- Porting note: had to reshuffle `intro` - revert e; apply s.recOn _ fun b s' => _ - · intro e; injection e - · intro b s' e - have h_eq : (cons b s').val (Nat.succ k) = s'.val k := by cases s'; rfl + cases' s with b s' + · injection e + · have h_eq : (cons b s').val (Nat.succ k) = s'.val k := by cases s' using Subtype.recOn; rfl rw [h_eq] at e apply h1 _ _ (Or.inr (IH e)) @@ -331,20 +332,21 @@ theorem eq_of_bisim (bisim : IsBisimulation R) {s₁ s₂} (r : s₁ ~ s₂) : s match t₁, t₂, e with | _, _, ⟨s, s', rfl, rfl, r⟩ => by suffices head s = head s' ∧ R (tail s) (tail s') from - And.imp id (fun r => ⟨tail s, tail s', by cases s; rfl, by cases s'; rfl, r⟩) this + And.imp id (fun r => ⟨tail s, tail s', by cases s using Subtype.recOn; rfl, + by cases s' using Subtype.recOn; rfl, r⟩) this have := bisim r; revert r this - apply recOn s _ _ <;> apply recOn s' _ _ + cases' s with x s <;> cases' s' with x' s' · intro r _ constructor · rfl · assumption - · intro x s _ this + · intro _ this rw [destruct_nil, destruct_cons] at this exact False.elim this - · intro x s _ this + · intro _ this rw [destruct_nil, destruct_cons] at this exact False.elim this - · intro x s x' s' _ this + · intro _ this rw [destruct_cons, destruct_cons] at this rw [head_cons, head_cons, tail_cons, tail_cons] cases' this with h1 h2 @@ -568,10 +570,10 @@ def toListOrStream (s : Seq α) [Decidable s.Terminates] : List α ⊕ Stream' theorem nil_append (s : Seq α) : append nil s = s := by apply coinduction2; intro s dsimp [append]; rw [corec_eq] - dsimp [append]; apply recOn s _ _ + dsimp [append] + cases' s with x s · trivial - · intro x s - rw [destruct_cons] + · rw [destruct_cons] dsimp exact ⟨rfl, s, rfl, rfl⟩ @@ -718,10 +720,9 @@ theorem cons_append (a : α) (s t) : append (cons a s) t = cons a (append s t) : @[simp] theorem append_nil (s : Seq α) : append s nil = s := by apply coinduction2 s; intro s - apply recOn s _ _ + cases' s with x s · trivial - · intro x s - rw [cons_append, destruct_cons, destruct_cons] + · rw [cons_append, destruct_cons, destruct_cons] dsimp exact ⟨rfl, s, rfl, rfl⟩ @@ -732,15 +733,12 @@ theorem append_assoc (s t u : Seq α) : append (append s t) u = append s (append exact match s1, s2, h with | _, _, ⟨s, t, u, rfl, rfl⟩ => by - apply recOn s <;> simp - · apply recOn t <;> simp - · apply recOn u <;> simp - · intro _ u - refine ⟨nil, nil, u, ?_, ?_⟩ <;> simp - · intro _ t - refine ⟨nil, t, u, ?_, ?_⟩ <;> simp - · intro _ s - exact ⟨s, t, u, rfl, rfl⟩ + cases' s with _ s <;> simp + · cases' t with _ t <;> simp + · cases' u with _ u <;> simp + · refine ⟨nil, nil, u, ?_, ?_⟩ <;> simp + · refine ⟨nil, t, u, ?_, ?_⟩ <;> simp + · exact ⟨s, t, u, rfl, rfl⟩ · exact ⟨s, t, u, rfl, rfl⟩ @[simp] @@ -776,12 +774,10 @@ theorem map_append (f : α → β) (s t) : map f (append s t) = append (map f s) exact match s1, s2, h with | _, _, ⟨s, t, rfl, rfl⟩ => by - apply recOn s <;> simp - · apply recOn t <;> simp - · intro _ t - refine ⟨nil, t, ?_, ?_⟩ <;> simp - · intro _ s - exact ⟨s, t, rfl, rfl⟩ + cases' s with _ s <;> simp + · cases' t with _ t <;> simp + · refine ⟨nil, t, ?_, ?_⟩ <;> simp + · exact ⟨s, t, rfl, rfl⟩ @[simp] theorem map_get? (f : α → β) : ∀ s n, get? (map f s) n = (get? s n).map f @@ -835,15 +831,13 @@ theorem join_cons (a : α) (s S) : join (cons (a, s) S) = cons a (append s (join exact match s1, s2, h with | s, _, Or.inl <| Eq.refl s => by - apply recOn s; · trivial - · intro x s - rw [destruct_cons] + cases' s with x s; · trivial + · rw [destruct_cons] exact ⟨rfl, Or.inl rfl⟩ | _, _, Or.inr ⟨a, s, S, rfl, rfl⟩ => by - apply recOn s + cases' s with x s · simp [join_cons_cons, join_cons_nil] - · intro x s - simpa [join_cons_cons, join_cons_nil] using Or.inr ⟨x, s, S, rfl, rfl⟩ + · simpa [join_cons_cons, join_cons_nil] using Or.inr ⟨x, s, S, rfl, rfl⟩ @[simp] theorem join_append (S T : Seq (Seq1 α)) : join (append S T) = append (join S) (join T) := by @@ -854,18 +848,15 @@ theorem join_append (S T : Seq (Seq1 α)) : join (append S T) = append (join S) exact match s1, s2, h with | _, _, ⟨s, S, T, rfl, rfl⟩ => by - apply recOn s <;> simp - · apply recOn S <;> simp - · apply recOn T + cases' s with _ s <;> simp + · cases' S with s S <;> simp + · cases' T with s T · simp - · intro s T - cases' s with a s; simp only [join_cons, destruct_cons, true_and] + · cases' s with a s; simp only [join_cons, destruct_cons, true_and] refine ⟨s, nil, T, ?_, ?_⟩ <;> simp - · intro s S - cases' s with a s + · cases' s with a s simpa using ⟨s, S, T, rfl, rfl⟩ - · intro _ s - exact ⟨s, S, T, rfl, rfl⟩ + · exact ⟨s, S, T, rfl, rfl⟩ · refine ⟨nil, S, T, ?_, ?_⟩ <;> simp @[simp] @@ -920,11 +911,11 @@ theorem of_mem_append {s₁ s₂ : Seq α} {a : α} (h : a ∈ append s₁ s₂) generalize e : append s₁ s₂ = ss; intro h; revert s₁ apply mem_rec_on h _ intro b s' o s₁ - apply s₁.recOn _ fun c t₁ => _ + cases' s₁ with c t₁ · intro m _ apply Or.inr simpa using m - · intro c t₁ m e + · intro m e have this := congr_arg destruct e cases' show a = c ∨ a ∈ append t₁ s₂ by simpa using m with e' m · rw [e'] @@ -1002,7 +993,7 @@ def bind (s : Seq1 α) (f : α → Seq1 β) : Seq1 β := @[simp] theorem join_map_ret (s : Seq α) : Seq.join (Seq.map ret s) = s := by - apply coinduction2 s; intro s; apply recOn s <;> simp [ret] + apply coinduction2 s; intro s; cases s <;> simp [ret] @[simp] theorem bind_ret (f : α → β) : ∀ s, bind s (ret ∘ f) = map f s @@ -1016,7 +1007,7 @@ theorem bind_ret (f : α → β) : ∀ s, bind s (ret ∘ f) = map f s theorem ret_bind (a : α) (f : α → Seq1 β) : bind (ret a) f = f a := by simp only [bind, map, ret.eq_1, map_nil] cases' f a with a s - apply recOn s <;> intros <;> simp + cases s <;> simp @[simp] theorem map_join' (f : α → β) (S) : Seq.map f (Seq.join S) = Seq.join (Seq.map (map f) S) := by @@ -1028,18 +1019,16 @@ theorem map_join' (f : α → β) (S) : Seq.map f (Seq.join S) = Seq.join (Seq.m exact match s1, s2, h with | _, _, ⟨s, S, rfl, rfl⟩ => by - apply recOn s <;> simp - · apply recOn S <;> simp - · intro x S - cases' x with a s + cases' s with _ s <;> simp + · cases' S with x S <;> simp + · cases' x with a s simpa [map] using ⟨_, _, rfl, rfl⟩ - · intro _ s - exact ⟨s, S, rfl, rfl⟩ + · exact ⟨s, S, rfl, rfl⟩ · refine ⟨nil, S, ?_, ?_⟩ <;> simp @[simp] theorem map_join (f : α → β) : ∀ S, map f (join S) = join (map (map f) S) - | ((a, s), S) => by apply recOn s <;> intros <;> simp [map] + | ((a, s), S) => by cases s <;> simp [map] @[simp] theorem join_join (SS : Seq (Seq1 (Seq1 α))) : @@ -1052,17 +1041,14 @@ theorem join_join (SS : Seq (Seq1 (Seq1 α))) : exact match s1, s2, h with | _, _, ⟨s, SS, rfl, rfl⟩ => by - apply recOn s <;> simp - · apply recOn SS <;> simp - · intro S SS - cases' S with s S; cases' s with x s + cases' s with _ s <;> simp + · cases' SS with S SS <;> simp + · cases' S with s S; cases' s with x s simp only [Seq.join_cons, join_append, destruct_cons] - apply recOn s <;> simp + cases' s with x s <;> simp · exact ⟨_, _, rfl, rfl⟩ - · intro x s - refine ⟨Seq.cons x (append s (Seq.join S)), SS, ?_, ?_⟩ <;> simp - · intro _ s - exact ⟨s, SS, rfl, rfl⟩ + · refine ⟨Seq.cons x (append s (Seq.join S)), SS, ?_, ?_⟩ <;> simp + · exact ⟨s, SS, rfl, rfl⟩ · refine ⟨nil, SS, ?_, ?_⟩ <;> simp @[simp] @@ -1080,7 +1066,7 @@ theorem bind_assoc (s : Seq1 α) (f : α → Seq1 β) (g : β → Seq1 γ) : -- give names to variables. induction' s using recOn with x s_1 <;> induction' S using recOn with x_1 s_2 <;> simp · cases' x_1 with x t - apply recOn t <;> intros <;> simp + cases t <;> simp · cases' x_1 with y t; simp instance monad : Monad Seq1 where From 5bb2882fe91d3e43c1cf325ca0ced720a8a87948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 22 Jan 2025 10:17:58 +0000 Subject: [PATCH 409/681] feat: the growth of a group is at least linear (#20018) This result belongs in a folder about growth of groups, which itself belongs in a folder about geometric group theory. Such folders do not exist yet, so I am creating them (calling them `Geometry.Group.Growth` and `Geometry.Group` respectively) and documenting them as such. From GrowthInGroups (LeanCamCombi) --- Mathlib.lean | 1 + Mathlib/Data/Finset/Insert.lean | 7 ++ .../Group/Growth/LinearLowerBound.lean | 90 +++++++++++++++++++ Mathlib/Geometry/Group/Growth/README.md | 1 + 4 files changed, 99 insertions(+) create mode 100644 Mathlib/Geometry/Group/Growth/LinearLowerBound.lean diff --git a/Mathlib.lean b/Mathlib.lean index 289ece73daea8..b9fd43baf0669 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3183,6 +3183,7 @@ import Mathlib.Geometry.Euclidean.Sphere.Power import Mathlib.Geometry.Euclidean.Sphere.Ptolemy import Mathlib.Geometry.Euclidean.Sphere.SecondInter import Mathlib.Geometry.Euclidean.Triangle +import Mathlib.Geometry.Group.Growth.LinearLowerBound import Mathlib.Geometry.Group.Growth.QuotientInter import Mathlib.Geometry.Manifold.Algebra.LeftInvariantDerivation import Mathlib.Geometry.Manifold.Algebra.LieGroup diff --git a/Mathlib/Data/Finset/Insert.lean b/Mathlib/Data/Finset/Insert.lean index 3c72a9bb66c17..5c2e92723c7e6 100644 --- a/Mathlib/Data/Finset/Insert.lean +++ b/Mathlib/Data/Finset/Insert.lean @@ -197,6 +197,13 @@ theorem nontrivial_iff_ne_singleton (ha : a ∈ s) : s.Nontrivial ↔ s ≠ {a} theorem Nonempty.exists_eq_singleton_or_nontrivial : s.Nonempty → (∃ a, s = {a}) ∨ s.Nontrivial := fun ⟨a, ha⟩ => (eq_singleton_or_nontrivial ha).imp_left <| Exists.intro a +@[simp, norm_cast] lemma nontrivial_coe : (s : Set α).Nontrivial ↔ s.Nontrivial := .rfl + +alias ⟨Nontrivial.of_coe, Nontrivial.coe⟩ := nontrivial_coe + +lemma Nontrivial.not_subset_singleton (hs : s.Nontrivial) : ¬s ⊆ {a} := + mod_cast hs.coe.not_subset_singleton + instance instNontrivial [Nonempty α] : Nontrivial (Finset α) := ‹Nonempty α›.elim fun a => ⟨⟨{a}, ∅, singleton_ne_empty _⟩⟩ diff --git a/Mathlib/Geometry/Group/Growth/LinearLowerBound.lean b/Mathlib/Geometry/Group/Growth/LinearLowerBound.lean new file mode 100644 index 0000000000000..153cde694cf7f --- /dev/null +++ b/Mathlib/Geometry/Group/Growth/LinearLowerBound.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2024 Yaël Dillies, Patrick Luo, Eric Rodriguez. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Patrick Luo, Eric Rodriguez +-/ +import Mathlib.Algebra.Group.Pointwise.Finset.Basic +import Mathlib.Algebra.Group.Subgroup.Pointwise +import Mathlib.Data.Nat.SuccPred + +/-! +# Linear lower bound on the growth of a generating set + +This file proves that the growth of a set generating an infinite group is at least linear. +-/ + +open Subgroup +open scoped Pointwise + +namespace Finset +variable {G : Type*} [Group G] [DecidableEq G] {X : Finset G} {n : ℕ} + +@[to_additive] +lemma pow_ssubset_pow_succ_of_pow_ne_closure (hX₁ : (1 : G) ∈ X) (hX : X.Nontrivial) + (hXclosure : (X ^ n : Set G) ≠ closure (X : Set G)) : X ^ n ⊂ X ^ (n + 1) := by + obtain rfl | hn := eq_or_ne n 0 + · simpa [ssubset_iff_subset_not_subset, hX₁, -Finset.subset_singleton_iff] + using hX.not_subset_singleton + refine (pow_subset_pow_right hX₁ <| n.le_add_right _).ssubset_of_ne ?_ + contrapose! hXclosure with hXn + rw [← closure_pow (mod_cast hX₁) hn] + wlog hn₁ : n = 1 + · simp +contextual only [pow_one] at this + replace hXn d : X ^ (n + d) = X ^ n := by + induction' d with d hd + · rw [add_zero] + · rw [pow_add, pow_one] at hXn + rw [← add_assoc, pow_add, pow_one, hd, ← hXn] + exact mod_cast this (one_mem_pow hX₁) (hX.pow hn) one_ne_zero + (by simp [hXn, ← pow_mul, mul_two]) (by simp [hXn, ← pow_mul, mul_two]) + subst hn₁ + simp only [ne_eq, one_ne_zero, not_false_eq_true, Nat.reduceAdd, pow_one] at * + let Xgp : Subgroup G := + { carrier := X + mul_mem' := fun {x y} hx hy ↦ by + norm_cast at * + simpa [← hXn, ← sq] using mul_mem_mul hx hy + one_mem' := hX₁ + inv_mem' := fun {x} hx ↦ by + dsimp at * + norm_cast at * + have : x • X ⊆ X := by + simpa [← hXn, add_assoc, ← sq] using smul_finset_subset_mul (t := X) hx + have : x • X = X := eq_of_subset_of_card_le this (card_smul_finset ..).ge + rw [← eq_inv_smul_iff] at this + rw [this] + simpa [mem_inv_smul_finset_iff] } + exact subset_closure.antisymm <| (closure_le Xgp).2 subset_rfl + +@[to_additive] +lemma pow_right_strictMonoOn (hX₁ : 1 ∈ X) (hX : X.Nontrivial) : + StrictMonoOn (fun n ↦ X ^ n) {n | (X ^ (n - 1) : Set G) ≠ closure (X : Set G)} := by + refine strictMonoOn_of_lt_add_one ⟨?_⟩ fun n _ _ hn ↦ + pow_ssubset_pow_succ_of_pow_ne_closure hX₁ hX hn + rintro - - n hn m ⟨-, hmn⟩ hm + apply hn + obtain rfl | hm₀ := m.eq_zero_or_pos + · simp [eq_comm (a := (1 : Set _)), coe_set_eq_one, -Set.subset_singleton_iff, + hX.coe.not_subset_singleton] at hm + · calc (X : Set G) ^ (n - 1) + _ = X ^ (n - m) * X ^ (m - 1) := by rw [← pow_add]; congr 1; omega + _ = closure (X : Set G) := by rw [hm, Set.pow_mul_subgroupClosure hX.nonempty.to_set] + +@[to_additive] +lemma pow_right_strictMono (hX₁ : 1 ∈ X) (hXclosure : (closure (X : Set G) : Set G).Infinite) : + StrictMono fun n ↦ X ^ n := by + obtain rfl | hX := eq_singleton_or_nontrivial hX₁ + · simp [closure_singleton_one] at hXclosure + have h n : (X ^ (n - 1) : Set G) ≠ closure (X : Set G) := + fun h ↦ by simp [← h, ← coe_pow] at hXclosure + simpa [h] using pow_right_strictMonoOn hX₁ hX + +/-- The growth of a set generating an infinite group is at least linear. -/ +@[to_additive "The growth of a set generating an infinite group is at least linear."] +lemma add_one_le_card_pow (hX₁ : 1 ∈ X) (hXclosure : (closure (X : Set G) : Set G).Infinite) : + ∀ n, n + 1 ≤ #(X ^ n) + | 0 => by simp + | n + 1 => (add_one_le_card_pow hX₁ hXclosure _).trans_lt <| card_lt_card <| + pow_right_strictMono hX₁ (by simp [hXclosure, Set.infinite_univ]) n.lt_succ_self + +end Finset diff --git a/Mathlib/Geometry/Group/Growth/README.md b/Mathlib/Geometry/Group/Growth/README.md index 6f07dca284151..41906654ee16b 100644 --- a/Mathlib/Geometry/Group/Growth/README.md +++ b/Mathlib/Geometry/Group/Growth/README.md @@ -7,4 +7,5 @@ If $G$ is a finitely generated group, say $G = \langle S\rangle$ for some finite ## Topics The results on growth of groups currently covered are: +* The growth of a group is at least linear * The growth of a group $G$ is roughly the growth of a normal subgroup $H \le G$ times the growth of $G / H$. From b7187aa6672153b6f9eedb7ff37fd74f8de852c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Dvo=C5=99=C3=A1k?= Date: Wed, 22 Jan 2025 10:17:59 +0000 Subject: [PATCH 410/681] feat: one more pidgeonhole version (#20056) --- Mathlib/Data/Finset/Card.lean | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index 9c9758dc56612..2648f2ebda7ac 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -411,6 +411,18 @@ lemma card_le_card_of_injOn (f : α → β) (hf : ∀ a ∈ s, f a ∈ t) (f_inj _ ≤ #t := card_le_card <| image_subset_iff.2 hf @[deprecated (since := "2024-06-01")] alias card_le_card_of_inj_on := card_le_card_of_injOn +lemma card_le_card_of_injective {f : s → t} (hf : f.Injective) : #s ≤ #t := by + rcases s.eq_empty_or_nonempty with rfl | ⟨a₀, ha₀⟩ + · simp + · classical + let f' : α → β := fun a => f (if ha : a ∈ s then ⟨a, ha⟩ else ⟨a₀, ha₀⟩) + apply card_le_card_of_injOn f' + · aesop + · intro a₁ ha₁ a₂ ha₂ haa + rw [mem_coe] at ha₁ ha₂ + simp only [f', ha₁, ha₂, ← Subtype.ext_iff] at haa + exact Subtype.ext_iff.mp (hf haa) + lemma card_le_card_of_surjOn (f : α → β) (hf : Set.SurjOn f s t) : #t ≤ #s := by classical unfold Set.SurjOn at hf; exact (card_le_card (mod_cast hf)).trans card_image_le From f912b7ec20fb06975feea7ca150681d690170868 Mon Sep 17 00:00:00 2001 From: Etienne Date: Wed, 22 Jan 2025 10:18:01 +0000 Subject: [PATCH 411/681] feat: specialize `IsDenseInducing.extend` to the case of a subset (#20064) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a shortcut for `hs.isDenseInducing_val.extend f`. It is useful because if `s : Set α` is dense then the coercion `(↑) : s → α` automatically satisfies `IsUniformInducing` and `IsDenseInducing` so this gives access to the theorems satisfied by a uniform extension by simply mentioning the density hypothesis. --- Mathlib/Topology/DenseEmbedding.lean | 49 +++++++++++++++++++ .../UniformSpace/UniformEmbedding.lean | 33 +++++++++++++ 2 files changed, 82 insertions(+) diff --git a/Mathlib/Topology/DenseEmbedding.lean b/Mathlib/Topology/DenseEmbedding.lean index ac53d77bf26a1..9a65a096c076d 100644 --- a/Mathlib/Topology/DenseEmbedding.lean +++ b/Mathlib/Topology/DenseEmbedding.lean @@ -39,6 +39,10 @@ structure IsDenseInducing [TopologicalSpace α] [TopologicalSpace β] (i : α namespace IsDenseInducing variable [TopologicalSpace α] [TopologicalSpace β] + +theorem _root_.Dense.isDenseInducing_val {s : Set α} (hs : Dense s) : + IsDenseInducing (@Subtype.val α s) := ⟨IsInducing.subtypeVal, hs.denseRange_val⟩ + variable {i : α → β} lemma isInducing (di : IsDenseInducing i) : IsInducing i := di.toIsInducing @@ -205,6 +209,51 @@ theorem mk' (i : α → β) (c : Continuous i) (dense : ∀ x, x ∈ closure (ra end IsDenseInducing +namespace Dense + +variable [TopologicalSpace α] [TopologicalSpace β] {s : Set α} + +/-- This is a shortcut for `hs.isDenseInducing_val.extend f`. It is useful because if `s : Set α` +is dense then the coercion `(↑) : s → α` automatically satisfies `IsUniformInducing` and +`IsDenseInducing` so this gives access to the theorems satisfied by a uniform extension by simply +mentioning the density hypothesis. -/ +noncomputable def extend (hs : Dense s) (f : s → β) : α → β := + hs.isDenseInducing_val.extend f + +variable {f : s → β} + +theorem extend_eq_of_tendsto [T2Space β] (hs : Dense s) {a : α} {b : β} + (hf : Tendsto f (comap (↑) (𝓝 a)) (𝓝 b)) : hs.extend f a = b := + hs.isDenseInducing_val.extend_eq_of_tendsto hf + +theorem extend_eq_at [T2Space β] (hs : Dense s) {f : s → β} {x : s} + (hf : ContinuousAt f x) : hs.extend f x = f x := + hs.isDenseInducing_val.extend_eq_at hf + +theorem extend_eq [T2Space β] (hs : Dense s) (hf : Continuous f) (x : s) : + hs.extend f x = f x := + hs.extend_eq_at hf.continuousAt + +theorem extend_unique_at [T2Space β] {a : α} {g : α → β} (hs : Dense s) + (hf : ∀ᶠ x : s in comap (↑) (𝓝 a), g x = f x) (hg : ContinuousAt g a) : + hs.extend f a = g a := + hs.isDenseInducing_val.extend_unique_at hf hg + +theorem extend_unique [T2Space β] {g : α → β} (hs : Dense s) + (hf : ∀ x : s, g x = f x) (hg : Continuous g) : hs.extend f = g := + hs.isDenseInducing_val.extend_unique hf hg + +theorem continuousAt_extend [T3Space β] {a : α} (hs : Dense s) + (hf : ∀ᶠ x in 𝓝 a, ∃ b, Tendsto f (comap (↑) <| 𝓝 x) (𝓝 b)) : + ContinuousAt (hs.extend f) a := + hs.isDenseInducing_val.continuousAt_extend hf + +theorem continuous_extend [T3Space β] (hs : Dense s) + (hf : ∀ a : α, ∃ b, Tendsto f (comap (↑) (𝓝 a)) (𝓝 b)) : Continuous (hs.extend f) := + hs.isDenseInducing_val.continuous_extend hf + +end Dense + /-- A dense embedding is an embedding with dense image. -/ structure IsDenseEmbedding [TopologicalSpace α] [TopologicalSpace β] (e : α → β) extends IsDenseInducing e : Prop where diff --git a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean index 1d053c0503ab5..580dea46f38a6 100644 --- a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean +++ b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean @@ -660,3 +660,36 @@ theorem uniformly_extend_unique {g : α → γ} (hg : ∀ b, g (e b) = f b) (hc IsDenseInducing.extend_unique _ hg hc end UniformExtension + +section DenseExtension + +variable {α β : Type*} [UniformSpace α] [UniformSpace β] + +theorem isUniformInducing_val (s : Set α) : + IsUniformInducing (@Subtype.val α s) := ⟨uniformity_setCoe⟩ + +namespace Dense + +variable {s : Set α} {f : s → β} + +theorem extend_exists [CompleteSpace β] (hs : Dense s) (hf : UniformContinuous f) (a : α) : + ∃ b, Tendsto f (comap (↑) (𝓝 a)) (𝓝 b) := + uniformly_extend_exists (isUniformInducing_val s) hs.denseRange_val hf a + +theorem extend_spec [CompleteSpace β] (hs : Dense s) (hf : UniformContinuous f) (a : α) : + Tendsto f (comap (↑) (𝓝 a)) (𝓝 (hs.extend f a)) := + uniformly_extend_spec (isUniformInducing_val s) hs.denseRange_val hf a + +theorem uniformContinuous_extend [CompleteSpace β] (hs : Dense s) (hf : UniformContinuous f) : + UniformContinuous (hs.extend f) := + uniformContinuous_uniformly_extend (isUniformInducing_val s) hs.denseRange_val hf + +variable [T0Space β] + +theorem extend_of_ind (hs : Dense s) (hf : UniformContinuous f) (x : s) : + hs.extend f x = f x := + IsDenseInducing.extend_eq_at _ hf.continuous.continuousAt + +end Dense + +end DenseExtension From 95dba76c94f8e7303ea45f0823376c8c998a8c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Renison?= <85908989+IvanRenison@users.noreply.github.com> Date: Wed, 22 Jan 2025 10:18:03 +0000 Subject: [PATCH 412/681] feat(Combinatorics/SimpleGraph): chromatic number of cycle graph (#20117) --- .../Combinatorics/SimpleGraph/Circulant.lean | 29 ++++++++ .../SimpleGraph/ConcreteColorings.lean | 73 +++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/Mathlib/Combinatorics/SimpleGraph/Circulant.lean b/Mathlib/Combinatorics/SimpleGraph/Circulant.lean index 99106b3256d7b..d4c83ed115ba7 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Circulant.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Circulant.lean @@ -133,4 +133,33 @@ theorem cycleGraph_preconnected {n : ℕ} : (cycleGraph n).Preconnected := theorem cycleGraph_connected {n : ℕ} : (cycleGraph (n + 1)).Connected := (pathGraph_connected n).mono pathGraph_le_cycleGraph +private def cycleGraph_EulerianCircuit_cons (n : ℕ) : + ∀ m : Fin (n + 3), (cycleGraph (n + 3)).Walk m 0 + | ⟨0, h⟩ => Walk.nil + | ⟨m + 1, h⟩ => + have hAdj : (cycleGraph (n + 3)).Adj ⟨m + 1, h⟩ ⟨m, Nat.lt_of_succ_lt h⟩ := by + simp [cycleGraph_adj, Fin.ext_iff, Fin.sub_val_of_le] + Walk.cons hAdj (cycleGraph_EulerianCircuit_cons n ⟨m, Nat.lt_of_succ_lt h⟩) + +/-- Eulerian trail of `cycleGraph (n + 3)` -/ +def cycleGraph_EulerianCircuit (n : ℕ) : (cycleGraph (n + 3)).Walk 0 0 := + have hAdj : (cycleGraph (n + 3)).Adj 0 (Fin.last (n + 2)) := by + simp [cycleGraph_adj] + Walk.cons hAdj (cycleGraph_EulerianCircuit_cons n (Fin.last (n + 2))) + +private theorem cycleGraph_EulerianCircuit_cons_length (n : ℕ) : ∀ m : Fin (n + 3), + (cycleGraph_EulerianCircuit_cons n m).length = m.val + | ⟨0, h⟩ => by + unfold cycleGraph_EulerianCircuit_cons + rfl + | ⟨m + 1, h⟩ => by + unfold cycleGraph_EulerianCircuit_cons + simp only [Walk.length_cons] + rw [cycleGraph_EulerianCircuit_cons_length n] + +theorem cycleGraph_EulerianCircuit_length {n : ℕ} : + (cycleGraph_EulerianCircuit n).length = n + 3 := by + unfold cycleGraph_EulerianCircuit + simp [cycleGraph_EulerianCircuit_cons_length] + end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean index c3b78c334c5d1..b6c01c361ac73 100644 --- a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean +++ b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean @@ -3,8 +3,10 @@ Copyright (c) 2023 Iván Renison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Iván Renison -/ +import Mathlib.Combinatorics.SimpleGraph.Circulant import Mathlib.Combinatorics.SimpleGraph.Coloring import Mathlib.Combinatorics.SimpleGraph.Hasse +import Mathlib.Data.Fin.Parity /-! # Concrete colorings of common graphs @@ -83,4 +85,75 @@ theorem Walk.three_le_chromaticNumber_of_odd_loop {α} {G : SimpleGraph α} {u : have : ¬c' u ↔ c' u := (c'.odd_length_iff_not_congr p).mp hOdd simp_all +/-- Bicoloring of a cycle graph of even size -/ +def cycleGraph.bicoloring_of_even (n : ℕ) (h : Even n) : Coloring (cycleGraph n) Bool := + Coloring.mk (fun u ↦ u.val % 2 = 0) <| by + intro u v hAdj + match n with + | 0 => exact u.elim0 + | 1 => simp at h + | n + 2 => + simp only [ne_eq, decide_eq_decide] + simp only [cycleGraph_adj] at hAdj + cases hAdj with + | inl huv | inr huv => + rw [← add_eq_of_eq_sub' huv.symm, ← Fin.even_iff_mod_of_even h, + ← Fin.even_iff_mod_of_even h, Fin.even_add_one_iff_odd] + apply Classical.not_iff.mpr + simp [Fin.not_odd_iff_even_of_even h, Fin.not_even_iff_odd_of_even h] + +theorem chromaticNumber_cycleGraph_of_even (n : ℕ) (h : 2 ≤ n) (hEven : Even n) : + (cycleGraph n).chromaticNumber = 2 := by + have hc := (cycleGraph.bicoloring_of_even n hEven).colorable + apply le_antisymm + · apply hc.chromaticNumber_le + · have hAdj : (cycleGraph n).Adj ⟨0, Nat.zero_lt_of_lt h⟩ ⟨1, h⟩ := by + simp [cycleGraph_adj', Fin.sub_val_of_le] + exact two_le_chromaticNumber_of_adj hAdj + +/-- Tricoloring of a cycle graph -/ +def cycleGraph.tricoloring (n : ℕ) (h : 2 ≤ n) : Coloring (cycleGraph n) + (Fin 3) := Coloring.mk (fun u ↦ if u.val = n - 1 then 2 else ⟨u.val % 2, by fin_omega⟩) <| by + intro u v hAdj + match n with + | 0 => exact u.elim0 + | 1 => simp at h + | n + 2 => + simp only + simp [cycleGraph_adj] at hAdj + split_ifs with hu hv + · simp [Fin.eq_mk_iff_val_eq.mpr hu, Fin.eq_mk_iff_val_eq.mpr hv] at hAdj + · refine (Fin.ne_of_lt (Fin.mk_lt_of_lt_val (?_))).symm + exact v.val.mod_lt Nat.zero_lt_two + · refine (Fin.ne_of_lt (Fin.mk_lt_of_lt_val ?_)) + exact u.val.mod_lt Nat.zero_lt_two + · simp [Fin.ext_iff] + have hu' : u.val + (1 : Fin (n + 2)) < n + 2 := by fin_omega + have hv' : v.val + (1 : Fin (n + 2)) < n + 2 := by fin_omega + cases hAdj with + | inl huv | inr huv => + rw [← add_eq_of_eq_sub' huv.symm] + simp only [Fin.val_add_eq_of_add_lt hv', Fin.val_add_eq_of_add_lt hu', Fin.val_one] + rw [show ∀x y : ℕ, x % 2 = y % 2 ↔ (Even x ↔ Even y) by simp [Nat.even_iff]; omega, + Nat.even_add] + simp only [Nat.not_even_one, iff_false, not_iff_self, iff_not_self] + exact id + +theorem chromaticNumber_cycleGraph_of_odd (n : ℕ) (h : 2 ≤ n) (hOdd : Odd n) : + (cycleGraph n).chromaticNumber = 3 := by + have hc := (cycleGraph.tricoloring n h).colorable + apply le_antisymm + · apply hc.chromaticNumber_le + · have hn3 : n - 3 + 3 = n := by + refine Nat.sub_add_cancel (Nat.succ_le_of_lt (Nat.lt_of_le_of_ne h ?_)) + intro h2 + rw [← h2] at hOdd + exact (Nat.not_odd_iff.mpr rfl) hOdd + let w : (cycleGraph (n - 3 + 3)).Walk 0 0 := cycleGraph_EulerianCircuit (n - 3) + have hOdd' : Odd w.length := by + rw [cycleGraph_EulerianCircuit_length, hn3] + exact hOdd + rw [← hn3] + exact Walk.three_le_chromaticNumber_of_odd_loop w hOdd' + end SimpleGraph From 887629ed3fb7613d77928fec341505dc85257419 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Wed, 22 Jan 2025 10:18:04 +0000 Subject: [PATCH 413/681] chore: rename List.indexOf_lt_length to List.indexOf_lt_length_iff (#20939) --- Mathlib/Data/FinEnum.lean | 2 +- Mathlib/Data/List/Basic.lean | 11 +++++++---- Mathlib/Data/List/FinRange.lean | 2 +- Mathlib/Data/List/Nodup.lean | 2 +- Mathlib/Data/List/NodupEquivFin.lean | 4 ++-- Mathlib/GroupTheory/Perm/Cycle/Basic.lean | 2 +- Mathlib/LinearAlgebra/Multilinear/Basic.lean | 4 ++-- scripts/add_deprecations.sh | 2 +- 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Mathlib/Data/FinEnum.lean b/Mathlib/Data/FinEnum.lean index 3d499baf8ef5b..d928b5d459a79 100644 --- a/Mathlib/Data/FinEnum.lean +++ b/Mathlib/Data/FinEnum.lean @@ -46,7 +46,7 @@ def ofNodupList [DecidableEq α] (xs : List α) (h : ∀ x : α, x ∈ xs) (h' : FinEnum α where card := xs.length equiv := - ⟨fun x => ⟨xs.indexOf x, by rw [List.indexOf_lt_length]; apply h⟩, xs.get, fun x => by simp, + ⟨fun x => ⟨xs.indexOf x, by rw [List.indexOf_lt_length_iff]; apply h⟩, xs.get, fun x => by simp, fun i => by ext; simp [List.indexOf_getElem h']⟩ /-- create a `FinEnum` instance from an exhaustive list; duplicates are removed -/ diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 27e8037124589..d51295c269ce1 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -704,10 +704,12 @@ theorem indexOf_le_length {a : α} {l : List α} : indexOf a l ≤ length l := b · rw [if_pos h]; exact Nat.zero_le _ · rw [if_neg h]; exact succ_le_succ ih -theorem indexOf_lt_length {a} {l : List α} : indexOf a l < length l ↔ a ∈ l := +theorem indexOf_lt_length_iff {a} {l : List α} : indexOf a l < length l ↔ a ∈ l := ⟨fun h => Decidable.byContradiction fun al => Nat.ne_of_lt h <| indexOf_eq_length.2 al, fun al => (lt_of_le_of_ne indexOf_le_length) fun h => indexOf_eq_length.1 h al⟩ +@[deprecated (since := "2025-01-22")] alias indexOf_lt_length := indexOf_lt_length_iff + theorem indexOf_append_of_mem {a : α} (h : a ∈ l₁) : indexOf a (l₁ ++ l₂) = indexOf a l₁ := by induction' l₁ with d₁ t₁ ih · exfalso @@ -799,7 +801,8 @@ theorem indexOf_get [DecidableEq α] {a : α} {l : List α} (h) : get l ⟨index @[simp] theorem getElem?_indexOf [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) : - l[indexOf a l]? = some a := by rw [getElem?_eq_getElem, getElem_indexOf (indexOf_lt_length.2 h)] + l[indexOf a l]? = some a := by + rw [getElem?_eq_getElem, getElem_indexOf (indexOf_lt_length_iff.2 h)] -- This is incorrectly named and should be `get?_indexOf`; -- this already exists, so will require a deprecation dance. @@ -810,8 +813,8 @@ theorem indexOf_inj [DecidableEq α] {l : List α} {x y : α} (hx : x ∈ l) (hy indexOf x l = indexOf y l ↔ x = y := ⟨fun h => by have x_eq_y : - get l ⟨indexOf x l, indexOf_lt_length.2 hx⟩ = - get l ⟨indexOf y l, indexOf_lt_length.2 hy⟩ := by + get l ⟨indexOf x l, indexOf_lt_length_iff.2 hx⟩ = + get l ⟨indexOf y l, indexOf_lt_length_iff.2 hy⟩ := by simp only [h] simp only [indexOf_get] at x_eq_y; exact x_eq_y, fun h => by subst h; rfl⟩ diff --git a/Mathlib/Data/List/FinRange.lean b/Mathlib/Data/List/FinRange.lean index 8281f5ce92052..de54055232145 100644 --- a/Mathlib/Data/List/FinRange.lean +++ b/Mathlib/Data/List/FinRange.lean @@ -61,7 +61,7 @@ theorem finRange_map_get (l : List α) : (finRange l.length).map l.get = l := List.ext_get (by simp) (by simp) @[simp] theorem indexOf_finRange {k : ℕ} (i : Fin k) : (finRange k).indexOf i = i := by - have : (finRange k).indexOf i < (finRange k).length := indexOf_lt_length.mpr (by simp) + have : (finRange k).indexOf i < (finRange k).length := indexOf_lt_length_iff.mpr (by simp) have h₁ : (finRange k).get ⟨(finRange k).indexOf i, this⟩ = i := indexOf_get this have h₂ : (finRange k).get ⟨i, by simp⟩ = i := get_finRange _ simpa using (Nodup.get_inj_iff (nodup_finRange k)).mp (Eq.trans h₁ h₂.symm) diff --git a/Mathlib/Data/List/Nodup.lean b/Mathlib/Data/List/Nodup.lean index dfa426586cded..084e0e51bba63 100644 --- a/Mathlib/Data/List/Nodup.lean +++ b/Mathlib/Data/List/Nodup.lean @@ -122,7 +122,7 @@ theorem not_nodup_of_get_eq_of_ne (xs : List α) (n m : Fin xs.length) theorem indexOf_getElem [DecidableEq α] {l : List α} (H : Nodup l) (i : Nat) (h : i < l.length) : indexOf l[i] l = i := - suffices (⟨indexOf l[i] l, indexOf_lt_length.2 (getElem_mem _)⟩ : Fin l.length) = ⟨i, h⟩ + suffices (⟨indexOf l[i] l, indexOf_lt_length_iff.2 (getElem_mem _)⟩ : Fin l.length) = ⟨i, h⟩ from Fin.val_eq_of_eq this nodup_iff_injective_get.1 H (by simp) diff --git a/Mathlib/Data/List/NodupEquivFin.lean b/Mathlib/Data/List/NodupEquivFin.lean index 9b381e748861c..0edcc7b2aba6c 100644 --- a/Mathlib/Data/List/NodupEquivFin.lean +++ b/Mathlib/Data/List/NodupEquivFin.lean @@ -50,7 +50,7 @@ the set of elements of `l`. -/ @[simps] def getEquiv (l : List α) (H : Nodup l) : Fin (length l) ≃ { x // x ∈ l } where toFun i := ⟨get l i, get_mem _ _⟩ - invFun x := ⟨indexOf (↑x) l, indexOf_lt_length.2 x.2⟩ + invFun x := ⟨indexOf (↑x) l, indexOf_lt_length_iff.2 x.2⟩ left_inv i := by simp only [List.get_indexOf, eq_self_iff_true, Fin.eta, Subtype.coe_mk, H] right_inv x := by simp @@ -63,7 +63,7 @@ decidable equality. -/ def getEquivOfForallMemList (l : List α) (nd : l.Nodup) (h : ∀ x : α, x ∈ l) : Fin l.length ≃ α where toFun i := l.get i - invFun a := ⟨_, indexOf_lt_length.2 (h a)⟩ + invFun a := ⟨_, indexOf_lt_length_iff.2 (h a)⟩ left_inv i := by simp [List.indexOf_getElem, nd] right_inv a := by simp diff --git a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean index 7a9275a5282d0..27345289bc340 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean @@ -867,7 +867,7 @@ variable [DecidableEq α] {l : List α} theorem Nodup.isCycleOn_formPerm (h : l.Nodup) : l.formPerm.IsCycleOn { a | a ∈ l } := by refine ⟨l.formPerm.bijOn fun _ => List.formPerm_mem_iff_mem, fun a ha b hb => ?_⟩ - rw [Set.mem_setOf, ← List.indexOf_lt_length] at ha hb + rw [Set.mem_setOf, ← List.indexOf_lt_length_iff] at ha hb rw [← List.getElem_indexOf ha, ← List.getElem_indexOf hb] refine ⟨l.indexOf b - l.indexOf a, ?_⟩ simp only [sub_eq_neg_add, zpow_add, zpow_neg, Equiv.Perm.inv_eq_iff_eq, zpow_natCast, diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index d8830d118642b..91124505b00ab 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -1155,13 +1155,13 @@ protected def mkPiAlgebraFin : MultilinearMap R (fun _ : Fin n => A) A where map_update_add' {dec} m i x y := by rw [Subsingleton.elim dec (by infer_instance)] have : (List.finRange n).indexOf i < n := by - simpa using List.indexOf_lt_length.2 (List.mem_finRange i) + simpa using List.indexOf_lt_length_iff.2 (List.mem_finRange i) simp [List.ofFn_eq_map, (List.nodup_finRange n).map_update, List.prod_set, add_mul, this, mul_add, add_mul] map_update_smul' {dec} m i c x := by rw [Subsingleton.elim dec (by infer_instance)] have : (List.finRange n).indexOf i < n := by - simpa using List.indexOf_lt_length.2 (List.mem_finRange i) + simpa using List.indexOf_lt_length_iff.2 (List.mem_finRange i) simp [List.ofFn_eq_map, (List.nodup_finRange n).map_update, List.prod_set, this] variable {R A n} diff --git a/scripts/add_deprecations.sh b/scripts/add_deprecations.sh index ae89ebfeaf5d5..f3601dda6daed 100755 --- a/scripts/add_deprecations.sh +++ b/scripts/add_deprecations.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#! /usr/bin/env bash : <<'BASH_MODULE_DOC' From e94954481f556862bd92f6cb62d0a2af1f92f5b0 Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Wed, 22 Jan 2025 10:59:09 +0000 Subject: [PATCH 414/681] chore(AssociatedPrime): use `ker toSpanSingleton` instead of `annihilator span singleton` (#20155) Maybe better in terms of defeq, not sure if this is really an improvement. --- Mathlib/LinearAlgebra/Span/Basic.lean | 6 +++ Mathlib/RingTheory/Ideal/AssociatedPrime.lean | 41 +++++++++---------- Mathlib/RingTheory/Ideal/Maps.lean | 10 +++++ 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/Mathlib/LinearAlgebra/Span/Basic.lean b/Mathlib/LinearAlgebra/Span/Basic.lean index 145579823242b..7858b46d72293 100644 --- a/Mathlib/LinearAlgebra/Span/Basic.lean +++ b/Mathlib/LinearAlgebra/Span/Basic.lean @@ -584,11 +584,17 @@ theorem span_singleton_eq_range (x : M) : (R ∙ x) = range (toSpanSingleton R M theorem toSpanSingleton_one (x : M) : toSpanSingleton R M x 1 = x := one_smul _ _ +theorem toSpanSingleton_injective : Function.Injective (toSpanSingleton R M) := + fun _ _ eq ↦ by simpa using congr($eq 1) + @[simp] theorem toSpanSingleton_zero : toSpanSingleton R M 0 = 0 := by ext simp +theorem toSpanSingleton_eq_zero_iff {x : M} : toSpanSingleton R M x = 0 ↔ x = 0 := by + rw [← toSpanSingleton_zero, (toSpanSingleton_injective R M).eq_iff] + variable {R M} theorem toSpanSingleton_isIdempotentElem_iff {e : R} : diff --git a/Mathlib/RingTheory/Ideal/AssociatedPrime.lean b/Mathlib/RingTheory/Ideal/AssociatedPrime.lean index 0a316e3c547c5..e274dedcc24aa 100644 --- a/Mathlib/RingTheory/Ideal/AssociatedPrime.lean +++ b/Mathlib/RingTheory/Ideal/AssociatedPrime.lean @@ -34,9 +34,11 @@ Generalize this to a non-commutative setting once there are annihilator for non- variable {R : Type*} [CommRing R] (I J : Ideal R) (M : Type*) [AddCommGroup M] [Module R M] +open LinearMap + /-- `IsAssociatedPrime I M` if the prime ideal `I` is the annihilator of some `x : M`. -/ def IsAssociatedPrime : Prop := - I.IsPrime ∧ ∃ x : M, I = (R ∙ x).annihilator + I.IsPrime ∧ ∃ x : M, I = ker (toSpanSingleton R M x) variable (R) @@ -55,8 +57,7 @@ theorem IsAssociatedPrime.map_of_injective (h : IsAssociatedPrime I M) (hf : Fun obtain ⟨x, rfl⟩ := h.2 refine ⟨h.1, ⟨f x, ?_⟩⟩ ext r - rw [Submodule.mem_annihilator_span_singleton, Submodule.mem_annihilator_span_singleton, ← - map_smul, ← f.map_zero, hf.eq_iff] + simp_rw [mem_ker, toSpanSingleton_apply, ← map_smul, ← f.map_zero, hf.eq_iff] theorem LinearEquiv.isAssociatedPrime_iff (l : M ≃ₗ[R] M') : IsAssociatedPrime I M ↔ IsAssociatedPrime I M' := @@ -66,32 +67,31 @@ theorem LinearEquiv.isAssociatedPrime_iff (l : M ≃ₗ[R] M') : theorem not_isAssociatedPrime_of_subsingleton [Subsingleton M] : ¬IsAssociatedPrime I M := by rintro ⟨hI, x, hx⟩ apply hI.ne_top - rwa [Subsingleton.elim x 0, Submodule.span_singleton_eq_bot.mpr rfl, Submodule.annihilator_bot] - at hx + simpa [Subsingleton.elim x 0] using hx variable (R) theorem exists_le_isAssociatedPrime_of_isNoetherianRing [H : IsNoetherianRing R] (x : M) - (hx : x ≠ 0) : ∃ P : Ideal R, IsAssociatedPrime P M ∧ (R ∙ x).annihilator ≤ P := by - have : (R ∙ x).annihilator ≠ ⊤ := by - rwa [Ne, Ideal.eq_top_iff_one, Submodule.mem_annihilator_span_singleton, one_smul] + (hx : x ≠ 0) : ∃ P : Ideal R, IsAssociatedPrime P M ∧ ker (toSpanSingleton R M x) ≤ P := by + have : ker (toSpanSingleton R M x) ≠ ⊤ := by + rwa [Ne, Ideal.eq_top_iff_one, mem_ker, toSpanSingleton_apply, one_smul] obtain ⟨P, ⟨l, h₁, y, rfl⟩, h₃⟩ := set_has_maximal_iff_noetherian.mpr H - { P | (R ∙ x).annihilator ≤ P ∧ P ≠ ⊤ ∧ ∃ y : M, P = (R ∙ y).annihilator } - ⟨(R ∙ x).annihilator, rfl.le, this, x, rfl⟩ + { P | ker (toSpanSingleton R M x) ≤ P ∧ P ≠ ⊤ ∧ ∃ y : M, P = ker (toSpanSingleton R M y) } + ⟨_, rfl.le, this, x, rfl⟩ refine ⟨_, ⟨⟨h₁, ?_⟩, y, rfl⟩, l⟩ intro a b hab rw [or_iff_not_imp_left] intro ha - rw [Submodule.mem_annihilator_span_singleton] at ha hab - have H₁ : (R ∙ y).annihilator ≤ (R ∙ a • y).annihilator := by + rw [mem_ker, toSpanSingleton_apply] at ha hab + have H₁ : ker (toSpanSingleton R M y) ≤ ker (toSpanSingleton R M (a • y)) := by intro c hc - rw [Submodule.mem_annihilator_span_singleton] at hc ⊢ + rw [mem_ker, toSpanSingleton_apply] at hc ⊢ rw [smul_comm, hc, smul_zero] - have H₂ : (Submodule.span R {a • y}).annihilator ≠ ⊤ := by - rwa [Ne, Submodule.annihilator_eq_top_iff, Submodule.span_singleton_eq_bot] - rwa [H₁.eq_of_not_lt (h₃ (R ∙ a • y).annihilator ⟨l.trans H₁, H₂, _, rfl⟩), - Submodule.mem_annihilator_span_singleton, smul_comm, smul_smul] + have H₂ : ker (toSpanSingleton R M (a • y)) ≠ ⊤ := by + rwa [Ne, ker_eq_top, toSpanSingleton_eq_zero_iff] + rwa [H₁.eq_of_not_lt (h₃ _ ⟨l.trans H₁, H₂, _, rfl⟩), + mem_ker, toSpanSingleton_apply, smul_comm, smul_smul] variable {R} @@ -117,11 +117,9 @@ theorem associatedPrimes.nonempty [IsNoetherianRing R] [Nontrivial M] : theorem biUnion_associatedPrimes_eq_zero_divisors [IsNoetherianRing R] : ⋃ p ∈ associatedPrimes R M, p = { r : R | ∃ x : M, x ≠ 0 ∧ r • x = 0 } := by - simp_rw [← Submodule.mem_annihilator_span_singleton] refine subset_antisymm (Set.iUnion₂_subset ?_) ?_ · rintro _ ⟨h, x, ⟨⟩⟩ r h' refine ⟨x, ne_of_eq_of_ne (one_smul R x).symm ?_, h'⟩ - refine mt (Submodule.mem_annihilator_span_singleton _ _).mpr ?_ exact (Ideal.ne_top_iff_one _).mp h.ne_top · intro r ⟨x, h, h'⟩ obtain ⟨P, hP, hx⟩ := exists_le_isAssociatedPrime_of_isNoetherianRing R x h @@ -132,6 +130,7 @@ variable {R M} theorem IsAssociatedPrime.annihilator_le (h : IsAssociatedPrime I M) : (⊤ : Submodule R M).annihilator ≤ I := by obtain ⟨hI, x, rfl⟩ := h + rw [← Submodule.annihilator_span_singleton] exact Submodule.annihilator_mono le_top theorem IsAssociatedPrime.eq_radical (hI : I.IsPrimary) (h : IsAssociatedPrime J (R ⧸ I)) : @@ -140,11 +139,11 @@ theorem IsAssociatedPrime.eq_radical (hI : I.IsPrimary) (h : IsAssociatedPrime J have : x ≠ 0 := by rintro rfl apply hJ.1 - rwa [Submodule.span_singleton_eq_bot.mpr rfl, Submodule.annihilator_bot] at e + rwa [toSpanSingleton_zero, ker_zero] at e obtain ⟨x, rfl⟩ := Ideal.Quotient.mkₐ_surjective R _ x replace e : ∀ {y}, y ∈ J ↔ x * y ∈ I := by intro y - rw [e, Submodule.mem_annihilator_span_singleton, ← map_smul, smul_eq_mul, mul_comm, + rw [e, mem_ker, toSpanSingleton_apply, ← map_smul, smul_eq_mul, mul_comm, Ideal.Quotient.mkₐ_eq_mk, ← Ideal.Quotient.mk_eq_mk, Submodule.Quotient.mk_eq_zero] apply le_antisymm · intro y hy diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index 8191b555882cb..67dad3b20e060 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -807,6 +807,16 @@ theorem mem_annihilator_span (s : Set M) (r : R) : theorem mem_annihilator_span_singleton (g : M) (r : R) : r ∈ (Submodule.span R ({g} : Set M)).annihilator ↔ r • g = 0 := by simp [mem_annihilator_span] +open LinearMap in +theorem annihilator_span (s : Set M) : + (Submodule.span R s).annihilator = ⨅ g : s, ker (toSpanSingleton R M g.1) := by + ext; simp [mem_annihilator_span] + +open LinearMap in +theorem annihilator_span_singleton (g : M) : + (Submodule.span R {g}).annihilator = ker (toSpanSingleton R M g) := by + simp [annihilator_span] + @[simp] theorem mul_annihilator (I : Ideal R) : I * annihilator I = ⊥ := by rw [mul_comm, annihilator_mul] From d728fa2dabbb869ad91a95e164be081e0a8bfd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 22 Jan 2025 10:59:11 +0000 Subject: [PATCH 415/681] feat: Borel-measurable group homs from locally compact normed groups to real normed spaces are continuous (#20910) From LeanCamCombi Co-authored-by: Mantas Baksys --- Mathlib/Analysis/Normed/Module/Basic.lean | 31 +++++++++++++++++++ .../Measure/Haar/NormedSpace.lean | 10 +++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/Mathlib/Analysis/Normed/Module/Basic.lean b/Mathlib/Analysis/Normed/Module/Basic.lean index 3ca89f37a1d43..1ef16a5d78305 100644 --- a/Mathlib/Analysis/Normed/Module/Basic.lean +++ b/Mathlib/Analysis/Normed/Module/Basic.lean @@ -651,3 +651,34 @@ abbrev NormedSpace.ofCore {𝕜 : Type*} {E : Type*} [NormedField 𝕜] [Seminor norm_smul_le r x := by rw [core.norm_smul r x] end Core + +variable {G H : Type*} [SeminormedAddCommGroup G] [SeminormedAddCommGroup H] [NormedSpace ℝ H] + {s : Set G} + +/-- A group homomorphism from a normed group to a real normed space, +bounded on a neighborhood of `0`, must be continuous. -/ +lemma AddMonoidHom.continuous_of_isBounded_nhds_zero (f : G →+ H) (hs : s ∈ 𝓝 (0 : G)) + (hbounded : IsBounded (f '' s)) : Continuous f := by + obtain ⟨δ, hδ, hUε⟩ := Metric.mem_nhds_iff.mp hs + obtain ⟨C, hC⟩ := (isBounded_iff_subset_ball 0).1 (hbounded.subset <| image_subset f hUε) + refine continuous_of_continuousAt_zero _ (continuousAt_iff.2 fun ε (hε : _ < _) => ?_) + simp only [dist_zero_right, _root_.map_zero, exists_prop] + simp only [subset_def, mem_image, mem_ball, dist_zero_right, forall_exists_index, and_imp, + forall_apply_eq_imp_iff₂] at hC + have hC₀ : 0 < C := (norm_nonneg _).trans_lt <| hC 0 (by simpa) + obtain ⟨n, hn⟩ := exists_nat_gt (C / ε) + have hnpos : 0 < (n : ℝ) := (div_pos hC₀ hε).trans hn + have hn₀ : n ≠ 0 := by rintro rfl; simp at hnpos + refine ⟨δ / n, div_pos hδ hnpos, fun {x} hxδ => ?_⟩ + calc + ‖f x‖ + _ = ‖(n : ℝ)⁻¹ • f (n • x)‖ := by simp [← Nat.cast_smul_eq_nsmul ℝ, hn₀] + _ ≤ ‖(n : ℝ)⁻¹‖ * ‖f (n • x)‖ := norm_smul_le .. + _ < ‖(n : ℝ)⁻¹‖ * C := by + gcongr + · simpa [pos_iff_ne_zero] + · refine hC _ <| norm_nsmul_le.trans_lt ?_ + simpa only [norm_mul, Real.norm_natCast, lt_div_iff₀ hnpos, mul_comm] using hxδ + _ = (n : ℝ)⁻¹ * C := by simp + _ < (C / ε : ℝ)⁻¹ * C := by gcongr + _ = ε := by simp [hC₀.ne'] diff --git a/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean b/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean index c52acf767b115..1e44f801378f7 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean @@ -46,7 +46,7 @@ variable {G H : Type*} [MeasurableSpace G] [Group G] [TopologicalSpace G] [TopologicalGroup G] [BorelSpace G] [LocallyCompactSpace G] [MeasurableSpace H] [SeminormedGroup H] [OpensMeasurableSpace H] --- TODO: This could be streamlined by proving that inner regular always exist +-- TODO: This could be streamlined by proving that inner regular measures always exist open Metric Bornology in @[to_additive] lemma _root_.MonoidHom.exists_nhds_isBounded (f : G →* H) (hf : Measurable f) (x : G) : @@ -69,6 +69,14 @@ lemma _root_.MonoidHom.exists_nhds_isBounded (f : G →* H) (hf : Measurable f) end SeminormedGroup +/-- A Borel-measurable group hom from a locally compact normed group to a real normed space is +continuous. -/ +lemma AddMonoidHom.continuous_of_measurable {G H : Type*} + [SeminormedAddCommGroup G] [MeasurableSpace G] [BorelSpace G] [LocallyCompactSpace G] + [SeminormedAddCommGroup H] [MeasurableSpace H] [OpensMeasurableSpace H] [NormedSpace ℝ H] + (f : G →+ H) (hf : Measurable f) : Continuous f := + let ⟨_s, hs, hbdd⟩ := f.exists_nhds_isBounded hf 0; f.continuous_of_isBounded_nhds_zero hs hbdd + variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [MeasurableSpace E] [BorelSpace E] [FiniteDimensional ℝ E] (μ : Measure E) [IsAddHaarMeasure μ] {F : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] From 94c06bb81ae96c4a1c876dc6048cdcfc9a444471 Mon Sep 17 00:00:00 2001 From: Bergschaf Date: Wed, 22 Jan 2025 10:59:12 +0000 Subject: [PATCH 416/681] doc(Order/Hom/Lattice): warn against `toFun` (#20918) Co-authored-by: Bergschaf <86738237+Bergschaf@users.noreply.github.com> --- Mathlib/Order/Hom/Lattice.lean | 38 ++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/Mathlib/Order/Hom/Lattice.lean b/Mathlib/Order/Hom/Lattice.lean index 8d090e9e4b22a..306587a3fd1f8 100644 --- a/Mathlib/Order/Hom/Lattice.lean +++ b/Mathlib/Order/Hom/Lattice.lean @@ -44,39 +44,59 @@ variable {F ι α β γ δ : Type*} /-- The type of `⊔`-preserving functions from `α` to `β`. -/ structure SupHom (α β : Type*) [Max α] [Max β] where - /-- The underlying function of a `SupHom` -/ + /-- The underlying function of a `SupHom`. + + Do not use this function directly. Instead use the coercion coming from the `FunLike` + instance. -/ toFun : α → β - /-- A `SupHom` preserves suprema. -/ + /-- A `SupHom` preserves suprema. + + Do not use this directly. Use `map_sup` instead. -/ map_sup' (a b : α) : toFun (a ⊔ b) = toFun a ⊔ toFun b /-- The type of `⊓`-preserving functions from `α` to `β`. -/ structure InfHom (α β : Type*) [Min α] [Min β] where - /-- The underlying function of an `InfHom` -/ + /-- The underlying function of an `InfHom`. + + Do not use this function directly. Instead use the coercion coming from the `FunLike` + instance. -/ toFun : α → β - /-- An `InfHom` preserves infima. -/ + /-- An `InfHom` preserves infima. + + Do not use this directly. Use `map_inf` instead. -/ map_inf' (a b : α) : toFun (a ⊓ b) = toFun a ⊓ toFun b /-- The type of finitary supremum-preserving homomorphisms from `α` to `β`. -/ structure SupBotHom (α β : Type*) [Max α] [Max β] [Bot α] [Bot β] extends SupHom α β where - /-- A `SupBotHom` preserves the bottom element. -/ + /-- A `SupBotHom` preserves the bottom element. + + Do not use this directly. Use `map_bot` instead. -/ map_bot' : toFun ⊥ = ⊥ /-- The type of finitary infimum-preserving homomorphisms from `α` to `β`. -/ structure InfTopHom (α β : Type*) [Min α] [Min β] [Top α] [Top β] extends InfHom α β where - /-- An `InfTopHom` preserves the top element. -/ + /-- An `InfTopHom` preserves the top element. + + Do not use this directly. Use `map_top` instead. -/ map_top' : toFun ⊤ = ⊤ /-- The type of lattice homomorphisms from `α` to `β`. -/ structure LatticeHom (α β : Type*) [Lattice α] [Lattice β] extends SupHom α β where - /-- A `LatticeHom` preserves infima. -/ + /-- A `LatticeHom` preserves infima. + + Do not use this directly. Use `map_inf` instead. -/ map_inf' (a b : α) : toFun (a ⊓ b) = toFun a ⊓ toFun b /-- The type of bounded lattice homomorphisms from `α` to `β`. -/ structure BoundedLatticeHom (α β : Type*) [Lattice α] [Lattice β] [BoundedOrder α] [BoundedOrder β] extends LatticeHom α β where - /-- A `BoundedLatticeHom` preserves the top element. -/ + /-- A `BoundedLatticeHom` preserves the top element. + + Do not use this directly. Use `map_top` instead. -/ map_top' : toFun ⊤ = ⊤ - /-- A `BoundedLatticeHom` preserves the bottom element. -/ + /-- A `BoundedLatticeHom` preserves the bottom element. + + Do not use this directly. Use `map_bot` instead. -/ map_bot' : toFun ⊥ = ⊥ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11215): TODO: remove this configuration and use the default configuration. From 03251ae01fff9f997d99b3fe75cef4148a465fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 22 Jan 2025 10:59:14 +0000 Subject: [PATCH 417/681] =?UTF-8?q?feat:=20`=CE=BC[f=20*=20g=20|=20m]=20?= =?UTF-8?q?=3D=E1=B5=90[=CE=BC]=20=CE=BC[f=20|=20m]=20*=20g`=20if=20`g`=20?= =?UTF-8?q?is=20strongly=20`m`-measurable=20(#20928)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a corollary of the lemma with opposite multiplication. Also rename the existing variant to better follow the naming convention and be more discoverable. From my PhD (LeanCamCombi) --- .../Function/ConditionalExpectation/Real.lean | 26 +++++++++++++++---- Mathlib/Probability/Martingale/Basic.lean | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index ffbdbbdff17f6..8e05909283442 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -19,7 +19,7 @@ This file proves some results regarding the conditional expectation of real-valu Radon-Nikodym derivative of `fμ` restricted on `m` with respect to `μ` restricted on `m`. * `MeasureTheory.Integrable.uniformIntegrable_condexp`: the conditional expectation of a function form a uniformly integrable class. -* `MeasureTheory.condexp_stronglyMeasurable_mul`: the pull-out property of the conditional +* `MeasureTheory.condexp_mul_of_stronglyMeasurable_left`: the pull-out property of the conditional expectation. -/ @@ -219,7 +219,7 @@ theorem Integrable.uniformIntegrable_condexp {ι : Type*} [IsFiniteMeasure μ] { section PullOut -- TODO: this section could be generalized beyond multiplication, to any bounded bilinear map. -/-- Auxiliary lemma for `condexp_stronglyMeasurable_mul`. -/ +/-- Auxiliary lemma for `condexp_mul_of_stronglyMeasurable_left`. -/ theorem condexp_stronglyMeasurable_simpleFunc_mul (hm : m ≤ m0) (f : @SimpleFunc α m ℝ) {g : α → ℝ} (hg : Integrable g μ) : μ[(f * g : α → ℝ)|m] =ᵐ[μ] f * μ[g|m] := by have : ∀ (s c) (f : α → ℝ), Set.indicator s (Function.const α c) * f = s.indicator (c • f) := by @@ -304,7 +304,7 @@ theorem condexp_stronglyMeasurable_mul_of_bound₀ (hm : m ≤ m0) [IsFiniteMeas rwa [← hx_eq] /-- Pull-out property of the conditional expectation. -/ -theorem condexp_stronglyMeasurable_mul {f g : α → ℝ} (hf : StronglyMeasurable[m] f) +theorem condexp_mul_of_stronglyMeasurable_left {f g : α → ℝ} (hf : StronglyMeasurable[m] f) (hfg : Integrable (f * g) μ) (hg : Integrable g μ) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by by_cases hm : m ≤ m0; swap; · simp_rw [condexp_of_not_le hm]; rw [mul_zero] by_cases hμm : SigmaFinite (μ.trim hm) @@ -340,17 +340,33 @@ theorem condexp_stronglyMeasurable_mul {f g : α → ℝ} (hf : StronglyMeasurab · simpa only [hxs, Set.indicator_of_mem] using h_norm n x hxs · simp only [hxs, Set.indicator_of_not_mem, not_false_iff, _root_.norm_zero, Nat.cast_nonneg] +@[deprecated (since := "2025-01-22")] +alias condexp_stronglyMeasurable_mul := condexp_mul_of_stronglyMeasurable_left + +/-- Pull-out property of the conditional expectation. -/ +lemma condexp_mul_of_stronglyMeasurable_right {f g : α → ℝ} (hg : StronglyMeasurable[m] g) + (hfg : Integrable (f * g) μ) (hf : Integrable f μ) : μ[f * g | m] =ᵐ[μ] μ[f | m] * g := by + simpa [mul_comm] using condexp_mul_of_stronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf + /-- Pull-out property of the conditional expectation. -/ -theorem condexp_stronglyMeasurable_mul₀ {f g : α → ℝ} (hf : AEStronglyMeasurable' m f μ) +theorem condexp_mul_of_aestronglyMeasurable_left {f g : α → ℝ} (hf : AEStronglyMeasurable' m f μ) (hfg : Integrable (f * g) μ) (hg : Integrable g μ) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by have : μ[f * g|m] =ᵐ[μ] μ[hf.mk f * g|m] := condexp_congr_ae (hf.ae_eq_mk.mul EventuallyEq.rfl) refine this.trans ?_ have : f * μ[g|m] =ᵐ[μ] hf.mk f * μ[g|m] := hf.ae_eq_mk.mul EventuallyEq.rfl - refine (condexp_stronglyMeasurable_mul hf.stronglyMeasurable_mk ?_ hg).trans this.symm + refine (condexp_mul_of_stronglyMeasurable_left hf.stronglyMeasurable_mk ?_ hg).trans this.symm refine (integrable_congr ?_).mp hfg exact hf.ae_eq_mk.mul EventuallyEq.rfl +@[deprecated (since := "2025-01-22")] +alias condexp_stronglyMeasurable_mul₀ := condexp_mul_of_aestronglyMeasurable_left + +/-- Pull-out property of the conditional expectation. -/ +lemma condexp_mul_of_aestronglyMeasurable_right {f g : α → ℝ} (hg : AEStronglyMeasurable' m g μ) + (hfg : Integrable (f * g) μ) (hf : Integrable f μ) : μ[f * g | m] =ᵐ[μ] μ[f | m] * g := by + simpa [mul_comm] using condexp_mul_of_aestronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf + end PullOut end MeasureTheory diff --git a/Mathlib/Probability/Martingale/Basic.lean b/Mathlib/Probability/Martingale/Basic.lean index 1693e5117c3b3..809ebfe55f9ad 100644 --- a/Mathlib/Probability/Martingale/Basic.lean +++ b/Mathlib/Probability/Martingale/Basic.lean @@ -490,7 +490,7 @@ theorem Submartingale.sum_mul_sub [IsFiniteMeasure μ] {R : ℝ} {ξ f : ℕ → simp only [← Finset.sum_Ico_eq_sub _ (Nat.le_succ _), Finset.sum_apply, Pi.mul_apply, Pi.sub_apply, Nat.Ico_succ_singleton, Finset.sum_singleton] exact EventuallyLE.trans (EventuallyLE.mul_nonneg (Eventually.of_forall (hnonneg _)) - (hf.condexp_sub_nonneg (Nat.le_succ _))) (condexp_stronglyMeasurable_mul (hξ _) + (hf.condexp_sub_nonneg (Nat.le_succ _))) (condexp_mul_of_stronglyMeasurable_left (hξ _) (((hf.integrable _).sub (hf.integrable _)).bdd_mul hξ.stronglyMeasurable.aestronglyMeasurable (hξbdd _)) ((hf.integrable _).sub (hf.integrable _))).symm.le From eb96c83562ce9f3d587cb3afb6ca99f0185ad0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 22 Jan 2025 11:38:31 +0000 Subject: [PATCH 418/681] =?UTF-8?q?feat:=20definition=20of=20`<`=20on=20`?= =?UTF-8?q?=CE=B1=20=C3=97=E2=82=97=20=CE=B2`=20in=20partial=20orders=20(#?= =?UTF-8?q?20067)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From GrowthInGroups (LeanCamCombi) --- Mathlib/Algebra/Order/Monoid/Prod.lean | 8 +-- Mathlib/Algebra/Order/Rearrangement.lean | 4 +- Mathlib/Data/Fin/Tuple/Sort.lean | 4 +- .../Data/Finsupp/MonomialOrder/DegLex.lean | 2 +- Mathlib/Data/Prod/Lex.lean | 53 ++++++++++++++----- Mathlib/Order/RelClasses.lean | 3 +- Mathlib/Order/WellFoundedSet.lean | 8 ++- 7 files changed, 54 insertions(+), 28 deletions(-) diff --git a/Mathlib/Algebra/Order/Monoid/Prod.lean b/Mathlib/Algebra/Order/Monoid/Prod.lean index a245abb7cdf2b..4a35b9544902a 100644 --- a/Mathlib/Algebra/Order/Monoid/Prod.lean +++ b/Mathlib/Algebra/Order/Monoid/Prod.lean @@ -48,19 +48,19 @@ namespace Lex instance orderedCommMonoid [OrderedCommMonoid α] [MulLeftStrictMono α] [OrderedCommMonoid β] : OrderedCommMonoid (α ×ₗ β) where - mul_le_mul_left _ _ hxy z := ((le_iff _ _).1 hxy).elim + mul_le_mul_left _ _ hxy z := (le_iff.1 hxy).elim (fun hxy => left _ _ <| mul_lt_mul_left' hxy _) -- Note: the `congr_arg` used to be `rw [hxy.1]` before https://github.com/leanprover-community/mathlib4/pull/8386 -- but the definition of `Mul.mul` got unfolded differently. - (fun hxy => (le_iff _ _).2 <| Or.inr ⟨congr_arg (z.1 * ·) hxy.1, mul_le_mul_left' hxy.2 _⟩) + (fun hxy => le_iff.2 <| Or.inr ⟨congr_arg (z.1 * ·) hxy.1, mul_le_mul_left' hxy.2 _⟩) @[to_additive] instance orderedCancelCommMonoid [OrderedCancelCommMonoid α] [OrderedCancelCommMonoid β] : OrderedCancelCommMonoid (α ×ₗ β) where mul_le_mul_left _ _ := mul_le_mul_left' - le_of_mul_le_mul_left _ _ _ hxyz := ((le_iff _ _).1 hxyz).elim + le_of_mul_le_mul_left _ _ _ hxyz := (le_iff.1 hxyz).elim (fun hxy => left _ _ <| lt_of_mul_lt_mul_left' hxy) - (fun hxy => (le_iff _ _).2 <| Or.inr ⟨mul_left_cancel hxy.1, le_of_mul_le_mul_left' hxy.2⟩) + (fun hxy => le_iff.2 <| Or.inr ⟨mul_left_cancel hxy.1, le_of_mul_le_mul_left' hxy.2⟩) @[to_additive] instance linearOrderedCancelCommMonoid [LinearOrderedCancelCommMonoid α] diff --git a/Mathlib/Algebra/Order/Rearrangement.lean b/Mathlib/Algebra/Order/Rearrangement.lean index b44e25f7c4d85..d9ab756af9db1 100644 --- a/Mathlib/Algebra/Order/Rearrangement.lean +++ b/Mathlib/Algebra/Order/Rearrangement.lean @@ -99,12 +99,12 @@ theorem MonovaryOn.sum_smul_comp_perm_le_sum_smul (hfg : MonovaryOn f g s) simp only [hτ, swap_apply_left, Function.comp_apply, Equiv.coe_trans, apply_inv_self] refine add_le_add (smul_add_smul_le_smul_add_smul' ?_ ?_) (sum_congr rfl fun x hx ↦ ?_).le · specialize hamax (σ⁻¹ a) h1s - rw [Prod.Lex.le_iff] at hamax + rw [Prod.Lex.toLex_le_toLex] at hamax cases' hamax with hamax hamax · exact hfg (mem_insert_of_mem h1s) (mem_insert_self _ _) hamax · exact hamax.2 · specialize hamax (σ a) (mem_of_mem_insert_of_ne (hσ <| σ.injective.ne hσa.symm) hσa.symm) - rw [Prod.Lex.le_iff] at hamax + rw [Prod.Lex.toLex_le_toLex] at hamax cases' hamax with hamax hamax · exact hamax.le · exact hamax.1.le diff --git a/Mathlib/Data/Fin/Tuple/Sort.lean b/Mathlib/Data/Fin/Tuple/Sort.lean index b8073b76ebc30..b34388877eee2 100644 --- a/Mathlib/Data/Fin/Tuple/Sort.lean +++ b/Mathlib/Data/Fin/Tuple/Sort.lean @@ -163,8 +163,8 @@ theorem eq_sort_iff : σ = sort f ↔ Monotone (f ∘ σ) ∧ ∀ i j, i < j → f (σ i) = f (σ j) → σ i < σ j := by rw [eq_sort_iff'] refine ⟨fun h => ⟨(monotone_proj f).comp h.monotone, fun i j hij hfij => ?_⟩, fun h i j hij => ?_⟩ - · exact (((Prod.Lex.lt_iff _ _).1 <| h hij).resolve_left hfij.not_lt).2 - · obtain he | hl := (h.1 hij.le).eq_or_lt <;> apply (Prod.Lex.lt_iff _ _).2 + · exact ((Prod.Lex.toLex_lt_toLex.1 <| h hij).resolve_left hfij.not_lt).2 + · obtain he | hl := (h.1 hij.le).eq_or_lt <;> apply Prod.Lex.toLex_lt_toLex.2 exacts [Or.inr ⟨he, h.2 i j hij he⟩, Or.inl hl] /-- The permutation that sorts `f` is the identity if and only if `f` is monotone. -/ diff --git a/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean b/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean index fc03f56398bf2..d5a68b16f016c 100644 --- a/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean +++ b/Mathlib/Data/Finsupp/MonomialOrder/DegLex.lean @@ -107,7 +107,7 @@ theorem lt_def [LT α] {a b : DegLex (α →₀ ℕ)} : theorem lt_iff [LT α] {a b : DegLex (α →₀ ℕ)} : a < b ↔ (ofDegLex a).degree < (ofDegLex b).degree ∨ (((ofDegLex a).degree = (ofDegLex b).degree) ∧ toLex (ofDegLex a) < toLex (ofDegLex b)) := by - simp only [lt_def, Prod.Lex.lt_iff] + simp [lt_def, Prod.Lex.toLex_lt_toLex] variable [LinearOrder α] diff --git a/Mathlib/Data/Prod/Lex.lean b/Mathlib/Data/Prod/Lex.lean index 2aafe976d991a..10da7294c8f5b 100644 --- a/Mathlib/Data/Prod/Lex.lean +++ b/Mathlib/Data/Prod/Lex.lean @@ -6,6 +6,7 @@ Authors: Kim Morrison, Minchao Wu import Mathlib.Data.Prod.Basic import Mathlib.Order.Lattice import Mathlib.Order.BoundedOrder.Basic +import Mathlib.Tactic.Tauto /-! # Lexicographic order @@ -44,16 +45,24 @@ instance instLE (α β : Type*) [LT α] [LE β] : LE (α ×ₗ β) where le := P instance instLT (α β : Type*) [LT α] [LT β] : LT (α ×ₗ β) where lt := Prod.Lex (· < ·) (· < ·) -theorem le_iff [LT α] [LE β] (a b : α × β) : - toLex a ≤ toLex b ↔ a.1 < b.1 ∨ a.1 = b.1 ∧ a.2 ≤ b.2 := +theorem toLex_le_toLex [LT α] [LE β] {x y : α × β} : + toLex x ≤ toLex y ↔ x.1 < y.1 ∨ x.1 = y.1 ∧ x.2 ≤ y.2 := Prod.lex_def -theorem lt_iff [LT α] [LT β] (a b : α × β) : - toLex a < toLex b ↔ a.1 < b.1 ∨ a.1 = b.1 ∧ a.2 < b.2 := +theorem toLex_lt_toLex [LT α] [LT β] {x y : α × β} : + toLex x < toLex y ↔ x.1 < y.1 ∨ x.1 = y.1 ∧ x.2 < y.2 := + Prod.lex_def + +lemma le_iff [LT α] [LE β] {x y : α ×ₗ β} : + x ≤ y ↔ (ofLex x).1 < (ofLex y).1 ∨ (ofLex x).1 = (ofLex y).1 ∧ (ofLex x).2 ≤ (ofLex y).2 := + Prod.lex_def + +lemma lt_iff [LT α] [LT β] {x y : α ×ₗ β} : + x < y ↔ (ofLex x).1 < (ofLex y).1 ∨ (ofLex x).1 = (ofLex y).1 ∧ (ofLex x).2 < (ofLex y).2 := Prod.lex_def instance [LT α] [LT β] [WellFoundedLT α] [WellFoundedLT β] : WellFoundedLT (α ×ₗ β) := - ⟨WellFounded.prod_lex wellFounded_lt wellFounded_lt⟩ + instIsWellFounded instance [LT α] [LT β] [WellFoundedLT α] [WellFoundedLT β] : WellFoundedRelation (α ×ₗ β) := ⟨(· < ·), wellFounded_lt⟩ @@ -97,19 +106,37 @@ instance preorder (α β : Type*) [Preorder α] [Preorder β] : Preorder (α × theorem monotone_fst [Preorder α] [LE β] (t c : α ×ₗ β) (h : t ≤ c) : (ofLex t).1 ≤ (ofLex c).1 := by - cases (Prod.Lex.le_iff t c).mp h with + cases toLex_le_toLex.mp h with | inl h' => exact h'.le | inr h' => exact h'.1.le section Preorder -variable [PartialOrder α] [Preorder β] +variable [PartialOrder α] [Preorder β] {x y : α × β} -theorem toLex_mono : Monotone (toLex : α × β → α ×ₗ β) := by - rintro ⟨a₁, b₁⟩ ⟨a₂, b₂⟩ ⟨ha, hb⟩ - obtain rfl | ha : a₁ = a₂ ∨ _ := ha.eq_or_lt - · exact right _ hb - · exact left _ _ ha +/-- Variant of `Prod.Lex.toLex_le_toLex` for partial orders. -/ +lemma toLex_le_toLex' : toLex x ≤ toLex y ↔ x.1 ≤ y.1 ∧ (x.1 = y.1 → x.2 ≤ y.2) := by + simp only [toLex_le_toLex, lt_iff_le_not_le, le_antisymm_iff] + tauto + +/-- Variant of `Prod.Lex.toLex_lt_toLex` for partial orders. -/ +lemma toLex_lt_toLex' : toLex x < toLex y ↔ x.1 ≤ y.1 ∧ (x.1 = y.1 → x.2 < y.2) := by + rw [toLex_lt_toLex] + simp only [lt_iff_le_not_le, le_antisymm_iff] + tauto + +/-- Variant of `Prod.Lex.le_iff` for partial orders. -/ +lemma le_iff' {x y : α ×ₗ β} : + x ≤ y ↔ (ofLex x).1 ≤ (ofLex y).1 ∧ ((ofLex x).1 = (ofLex y).1 → (ofLex x).2 ≤ (ofLex y).2) := + toLex_le_toLex' + +/-- Variant of `Prod.Lex.lt_iff` for partial orders. -/ +lemma lt_iff' {x y : α ×ₗ β} : + x < y ↔ (ofLex x).1 ≤ (ofLex y).1 ∧ ((ofLex x).1 = (ofLex y).1 → (ofLex x).2 < (ofLex y).2) := + toLex_lt_toLex' + +theorem toLex_mono : Monotone (toLex : α × β → α ×ₗ β) := + fun _x _y hxy ↦ toLex_le_toLex'.2 ⟨hxy.1, fun _ ↦ hxy.2⟩ theorem toLex_strictMono : StrictMono (toLex : α × β → α ×ₗ β) := by rintro ⟨a₁, b₁⟩ ⟨a₂, b₂⟩ h @@ -153,7 +180,7 @@ instance linearOrder (α β : Type*) [LinearOrder α] [LinearOrder β] : LinearO have : BEqOrd (α ×ₗ β) := ⟨by simp [compare_def, compareLex, compareOn, Ordering.then_eq_eq, compare_eq_iff_eq]⟩ have : LTOrd (α ×ₗ β) := ⟨by - simp [compare_def, compareLex, compareOn, Ordering.then_eq_lt, lt_iff, + simp [compare_def, compareLex, compareOn, Ordering.then_eq_lt, toLex_lt_toLex, compare_lt_iff_lt, compare_eq_iff_eq]⟩ convert LTCmp.eq_compareOfLessAndEq (cmp := compare) a b } diff --git a/Mathlib/Order/RelClasses.lean b/Mathlib/Order/RelClasses.lean index 2655560ce6d55..e00316da23a17 100644 --- a/Mathlib/Order/RelClasses.lean +++ b/Mathlib/Order/RelClasses.lean @@ -446,7 +446,8 @@ instance (priority := 100) [IsEmpty α] (r : α → α → Prop) : IsWellOrder trans := isEmptyElim wf := wellFounded_of_isEmpty r -instance [IsWellFounded α r] [IsWellFounded β s] : IsWellFounded (α × β) (Prod.Lex r s) := +instance Prod.Lex.instIsWellFounded [IsWellFounded α r] [IsWellFounded β s] : + IsWellFounded (α × β) (Prod.Lex r s) := ⟨IsWellFounded.wf.prod_lex IsWellFounded.wf⟩ instance [IsWellOrder α r] [IsWellOrder β s] : IsWellOrder (α × β) (Prod.Lex r s) where diff --git a/Mathlib/Order/WellFoundedSet.lean b/Mathlib/Order/WellFoundedSet.lean index e0c2c0ea13063..49a7c70b652e2 100644 --- a/Mathlib/Order/WellFoundedSet.lean +++ b/Mathlib/Order/WellFoundedSet.lean @@ -789,7 +789,7 @@ theorem subsetProdLex [PartialOrder α] [Preorder β] {s : Set (α ×ₗ β)} constructor · by_contra hx simp_all - · exact (Prod.Lex.le_iff (f (g 0)) _).mpr <| Or.inl hn + · exact Prod.Lex.toLex_le_toLex.mpr <| .inl hn · have hhc : ∀ n, (ofLex f (g 0)).1 = (ofLex f (g n)).1 := by intro n rw [not_exists] at hc @@ -802,9 +802,7 @@ theorem subsetProdLex [PartialOrder α] [Preorder β] {s : Set (α ×ₗ β)} simpa using hf _ use (g (g' 0)), (g (g' 1)) suffices (f (g (g' 0))) ≤ (f (g (g' 1))) by simpa - · refine (Prod.Lex.le_iff (f (g (g' 0))) (f (g (g' 1)))).mpr ?_ - right - constructor + · refine Prod.Lex.toLex_le_toLex.mpr <| .inr ⟨?_, ?_⟩ · exact (hhc (g' 0)).symm.trans (hhc (g' 1)) · exact hg' (Nat.zero_le 1) @@ -823,7 +821,7 @@ theorem fiberProdLex [PartialOrder α] [Preorder β] {s : Set (α ×ₗ β)} rintro b ⟨-, hb⟩ c ⟨-, hc⟩ hbc simp only [mem_preimage, mem_singleton_iff] at hb hc have : (ofLex b).1 < (ofLex c).1 ∨ (ofLex b).1 = (ofLex c).1 ∧ f b ≤ f c := - (Prod.Lex.le_iff b c).mp hbc + Prod.Lex.toLex_le_toLex.mp hbc simp_all only [lt_self_iff_false, true_and, false_or] theorem ProdLex_iff [PartialOrder α] [Preorder β] {s : Set (α ×ₗ β)} : From 97bce08481d96a1eacfba45ffe14f4e05709c36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 22 Jan 2025 12:32:28 +0000 Subject: [PATCH 419/681] feat: action of `DomMulAct` on measures (#20204) From FLT Co-authored-by: Javier Lopez-Contreras Co-authored-by: Andrew Yang --- .../MeasureTheory/Group/MeasurableEquiv.lean | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Mathlib/MeasureTheory/Group/MeasurableEquiv.lean b/Mathlib/MeasureTheory/Group/MeasurableEquiv.lean index 95bd76b8d5572..1cc3a54fa2bda 100644 --- a/Mathlib/MeasureTheory/Group/MeasurableEquiv.lean +++ b/Mathlib/MeasureTheory/Group/MeasurableEquiv.lean @@ -34,6 +34,8 @@ We also deduce that the corresponding maps are measurable embeddings. measurable, equivalence, group action -/ +open scoped Pointwise + namespace MeasurableEquiv variable {G G₀ α : Type*} [MeasurableSpace G] [MeasurableSpace G₀] [MeasurableSpace α] [Group G] @@ -201,3 +203,30 @@ def divLeft [MeasurableMul G] [MeasurableInv G] (g : G) : G ≃ᵐ G where measurable_invFun := measurable_inv.mul_const g end MeasurableEquiv + +namespace MeasureTheory.Measure +variable {G A : Type*} [Group G] [AddCommGroup A] [DistribMulAction G A] [MeasurableSpace A] + -- We only need `MeasurableConstSMul G A` but we don't have this class. So we erroneously must + -- assume `MeasurableSpace G` + `MeasurableSMul G A` + [MeasurableSpace G] [MeasurableSMul G A] +variable {μ ν : Measure A} {g : G} + +noncomputable instance : DistribMulAction Gᵈᵐᵃ (Measure A) where + smul g μ := μ.map (DomMulAct.mk.symm g⁻¹ • ·) + one_smul μ := show μ.map _ = _ by simp + mul_smul g g' μ := show μ.map _ = ((μ.map _).map _) by + rw [map_map] + · simp [Function.comp_def, mul_smul] + · exact measurable_const_smul .. + · exact measurable_const_smul .. + smul_zero g := show (0 : Measure A).map _ = 0 by simp + smul_add g μ ν := show (μ + ν).map _ = μ.map _ + ν.map _ by + rw [Measure.map_add]; exact measurable_const_smul .. + +lemma dmaSMul_apply (μ : Measure A) (g : Gᵈᵐᵃ) (s : Set A) : + (g • μ) s = μ (DomMulAct.mk.symm g • s) := by + refine ((MeasurableEquiv.smul ((DomMulAct.mk.symm g : G)⁻¹)).map_apply _).trans ?_ + congr 1 + exact Set.preimage_smul_inv (DomMulAct.mk.symm g) s + +end MeasureTheory.Measure From 720fe962221040f13afa94b1e4a45c60fb9de7be Mon Sep 17 00:00:00 2001 From: harper-scott <114939956+harper-scott@users.noreply.github.com> Date: Wed, 22 Jan 2025 13:15:35 +0000 Subject: [PATCH 420/681] feat(GroupTheory/SemidirectProduct): add two lemmas (#20634) add lemma on cardinality of semidirect product of finite groups add def establishing an isomorphism between a semidirect product and a direct product Co-authored-by: Peiran Wu <15968905+wupr@users.noreply.github.com> --- Mathlib/GroupTheory/SemidirectProduct.lean | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Mathlib/GroupTheory/SemidirectProduct.lean b/Mathlib/GroupTheory/SemidirectProduct.lean index 99062dc001905..fb34e1cb43a1a 100644 --- a/Mathlib/GroupTheory/SemidirectProduct.lean +++ b/Mathlib/GroupTheory/SemidirectProduct.lean @@ -177,12 +177,18 @@ theorem range_inl_eq_ker_rightHom : (inl : N →* N ⋊[φ] G).range = rightHom. fun x hx ↦ ⟨x.left, by ext <;> simp_all [MonoidHom.mem_ker]⟩ /-- The bijection between the semidirect product and the product. -/ -@[simps!] -def equivProd : N ⋊[φ] G ≃ N × G := - { toFun := fun ⟨n, g⟩ ↦ ⟨n, g⟩ - invFun := fun ⟨n, g⟩ ↦ ⟨n, g⟩ - left_inv := fun _ ↦ rfl - right_inv := fun _ ↦ rfl } +@[simps] +def equivProd : N ⋊[φ] G ≃ N × G where + toFun x := ⟨x.1, x.2⟩ + invFun x := ⟨x.1, x.2⟩ + left_inv _ := rfl + right_inv _ := rfl + +/-- The group isomorphism between a semidirect product with respect to the trivial map + and the product. -/ +@[simps (config := {rhsMd := .default})] +def mulEquivProd : N ⋊[1] G ≃* N × G := + { equivProd with map_mul' _ _ := rfl } section lift @@ -303,4 +309,8 @@ def congr' : end Congr +@[simp] +lemma card : Nat.card (N ⋊[φ] G) = Nat.card N * Nat.card G := + Nat.card_prod _ _ ▸ Nat.card_congr equivProd + end SemidirectProduct From fe4e3aba400363d513386f175b82642c775038d7 Mon Sep 17 00:00:00 2001 From: Nailin Guan <150537269+Thmoas-Guan@users.noreply.github.com> Date: Wed, 22 Jan 2025 13:36:44 +0000 Subject: [PATCH 421/681] Feat(Topology/Group): add coercion toContinuousMonoidHom (#20628) Add coercion toContinuousMonoidHom when `[MonoidHomClass F A B] [ContinuousMapClass F A B]` --- .../Topology/Algebra/ContinuousMonoidHom.lean | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean index 8c4ddb97a123d..3809969b08829 100644 --- a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean +++ b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean @@ -108,6 +108,48 @@ instance instMonoidHomClass : MonoidHomClass (ContinuousMonoidHom A B) A B where instance instContinuousMapClass : ContinuousMapClass (ContinuousMonoidHom A B) A B where map_continuous f := f.continuous_toFun +@[to_additive (attr := simp)] +lemma coe_toMonoidHom (f : ContinuousMonoidHom A B) : f.toMonoidHom = f := rfl + +@[to_additive (attr := simp)] +lemma coe_toContinuousMap (f : ContinuousMonoidHom A B) : f.toContinuousMap = f := rfl + +section + +variable {A B : Type*} [Monoid A] [Monoid B] [TopologicalSpace A] [TopologicalSpace B] + {F : Type*} [FunLike F A B] + +/-- Turn an element of a type `F` satisfying `MonoidHomClass F A B` and `ContinuousMapClass F A B` +into a`ContinuousMonoidHom`. This is declared as the default coercion from `F` to +`ContinuousMonoidHom A B`. -/ +@[to_additive (attr := coe) "Turn an element of a type `F` satisfying +`AddMonoidHomClass F A B` and `ContinuousMapClass F A B` into a`ContinuousAddMonoidHom`. +This is declared as the default coercion from `F` to `ContinuousAddMonoidHom A B`."] +def toContinuousMonoidHom [MonoidHomClass F A B] [ContinuousMapClass F A B] (f : F) : + ContinuousMonoidHom A B := + { MonoidHomClass.toMonoidHom f with } + +/-- Any type satisfying `MonoidHomClass` and `ContinuousMapClass` can be cast into +`ContinuousMnoidHom` via `ContinuousMonoidHom.toContinuousMonoidHom`. -/ +@[to_additive "Any type satisfying `AddMonoidHomClass` and `ContinuousMapClass` can be cast into +`ContinuousAddMonoidHom` via `ContinuousAddMonoidHom.toContinuousAddMonoidHom`."] +instance [MonoidHomClass F A B] [ContinuousMapClass F A B] : CoeOut F (ContinuousMonoidHom A B) := + ⟨ContinuousMonoidHom.toContinuousMonoidHom⟩ + +@[to_additive (attr := simp)] +lemma coe_coe [MonoidHomClass F A B] [ContinuousMapClass F A B] (f : F) : + ⇑(f : ContinuousMonoidHom A B) = f := rfl + +@[to_additive (attr := simp, norm_cast)] +lemma toMonoidHom_toContinuousMonoidHom [MonoidHomClass F A B] [ContinuousMapClass F A B] (f : F) : + ((f : ContinuousMonoidHom A B) : A →* B) = f := rfl + +@[to_additive (attr := simp, norm_cast)] +lemma toContinuousMap_toContinuousMonoidHom [MonoidHomClass F A B] [ContinuousMapClass F A B] + (f : F) : ((f : ContinuousMonoidHom A B) : C(A, B)) = f := rfl + +end + @[to_additive (attr := ext)] theorem ext {f g : ContinuousMonoidHom A B} (h : ∀ x, f x = g x) : f = g := DFunLike.ext _ _ h From fc30cf7d2a282e7e1e29be801db327f1f52004e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Wed, 22 Jan 2025 13:49:28 +0000 Subject: [PATCH 422/681] chore: rename `condexp` to `condExp` (#20930) The current name is vestigial. From my PhD (LeanCamCombi) --- .../ConditionalExpectation/Basic.lean | 351 ++++++----- .../ConditionalExpectation/CondexpL1.lean | 571 +++++++++++------- .../ConditionalExpectation/CondexpL2.lean | 428 ++++++++----- .../ConditionalExpectation/Indicator.lean | 88 +-- .../Function/ConditionalExpectation/Real.lean | 192 +++--- Mathlib/Probability/BorelCantelli.lean | 17 +- .../Probability/ConditionalExpectation.lean | 10 +- .../Probability/Independence/Conditional.lean | 80 +-- Mathlib/Probability/Independence/Kernel.lean | 2 +- Mathlib/Probability/Independence/ZeroOne.lean | 32 +- Mathlib/Probability/Kernel/CondDistrib.lean | 52 +- Mathlib/Probability/Kernel/Condexp.lean | 204 ++++--- .../Kernel/Disintegration/Density.lean | 8 +- Mathlib/Probability/Martingale/Basic.lean | 134 ++-- .../Probability/Martingale/BorelCantelli.lean | 2 +- Mathlib/Probability/Martingale/Centering.lean | 30 +- .../Probability/Martingale/Convergence.lean | 84 ++- .../Martingale/OptionalSampling.lean | 86 ++- Mathlib/Probability/Notation.lean | 4 +- Mathlib/Probability/Process/Filtration.lean | 8 +- Mathlib/Probability/Process/Stopping.lean | 38 +- docs/overview.yaml | 2 +- scripts/nolints_prime_decls.txt | 20 +- 23 files changed, 1506 insertions(+), 937 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index 8b2d1dfe66dd5..23ea3343a5989 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -20,11 +20,11 @@ The construction is done in four steps: is integrable and define a map `Set α → (E →L[ℝ] (α →₁[μ] E))` which to a set associates a linear map. That linear map sends `x ∈ E` to the conditional expectation of the indicator of the set with value `x`. -* Extend that map to `condexpL1CLM : (α →₁[μ] E) →L[ℝ] (α →₁[μ] E)`. This is done using the same +* Extend that map to `condExpL1CLM : (α →₁[μ] E) →L[ℝ] (α →₁[μ] E)`. This is done using the same construction as the Bochner integral (see the file `MeasureTheory/Integral/SetToL1`). * Define the conditional expectation of a function `f : α → E`, which is an integrable function `α → E` equal to 0 if `f` is not integrable, and equal to an `m`-measurable representative of - `condexpL1CLM` applied to `[f]`, the equivalence class of `f` in `L¹`. + `condExpL1CLM` applied to `[f]`, the equivalence class of `f` in `L¹`. The first step is done in `MeasureTheory.Function.ConditionalExpectation.CondexpL2`, the two next steps in `MeasureTheory.Function.ConditionalExpectation.CondexpL1` and the final step is @@ -34,27 +34,27 @@ performed in this file. The conditional expectation and its properties -* `condexp (m : MeasurableSpace α) (μ : Measure α) (f : α → E)`: conditional expectation of `f` +* `condExp (m : MeasurableSpace α) (μ : Measure α) (f : α → E)`: conditional expectation of `f` with respect to `m`. -* `integrable_condexp` : `condexp` is integrable. -* `stronglyMeasurable_condexp` : `condexp` is `m`-strongly-measurable. -* `setIntegral_condexp (hf : Integrable f μ) (hs : MeasurableSet[m] s)` : if `m ≤ m0` (the +* `integrable_condExp` : `condExp` is integrable. +* `stronglyMeasurable_condExp` : `condExp` is `m`-strongly-measurable. +* `setIntegral_condExp (hf : Integrable f μ) (hs : MeasurableSet[m] s)` : if `m ≤ m0` (the σ-algebra over which the measure is defined), then the conditional expectation verifies - `∫ x in s, condexp m μ f x ∂μ = ∫ x in s, f x ∂μ` for any `m`-measurable set `s`. + `∫ x in s, condExp m μ f x ∂μ = ∫ x in s, f x ∂μ` for any `m`-measurable set `s`. -While `condexp` is function-valued, we also define `condexpL1` with value in `L1` and a continuous -linear map `condexpL1CLM` from `L1` to `L1`. `condexp` should be used in most cases. +While `condExp` is function-valued, we also define `condExpL1` with value in `L1` and a continuous +linear map `condExpL1CLM` from `L1` to `L1`. `condExp` should be used in most cases. Uniqueness of the conditional expectation -* `ae_eq_condexp_of_forall_setIntegral_eq`: an a.e. `m`-measurable function which verifies the - equality of integrals is a.e. equal to `condexp`. +* `ae_eq_condExp_of_forall_setIntegral_eq`: an a.e. `m`-measurable function which verifies the + equality of integrals is a.e. equal to `condExp`. ## Notations For a measure `μ` defined on a measurable space structure `m0`, another measurable space structure `m` with `hm : m ≤ m0` (a sub-σ-algebra) and a function `f`, we define the notation -* `μ[f|m] = condexp m μ f`. +* `μ[f|m] = condExp m μ f`. ## Tags @@ -84,284 +84,353 @@ is true: - `m` is not a sub-σ-algebra of `m0`, - `μ` is not σ-finite with respect to `m`, - `f` is not integrable. -/ -noncomputable irreducible_def condexp (m : MeasurableSpace α) {m0 : MeasurableSpace α} +noncomputable irreducible_def condExp (m : MeasurableSpace α) {m0 : MeasurableSpace α} (μ : Measure α) (f : α → F') : α → F' := if hm : m ≤ m0 then if h : SigmaFinite (μ.trim hm) ∧ Integrable f μ then if StronglyMeasurable[m] f then f - else (@aestronglyMeasurable'_condexpL1 _ _ _ _ _ m m0 μ hm h.1 _).mk - (@condexpL1 _ _ _ _ _ _ _ hm μ h.1 f) + else (@aestronglyMeasurable'_condExpL1 _ _ _ _ _ m m0 μ hm h.1 _).mk + (@condExpL1 _ _ _ _ _ _ _ hm μ h.1 f) else 0 else 0 +@[deprecated (since := "2025-01-21")] alias condexp := condExp + -- We define notation `μ[f|m]` for the conditional expectation of `f` with respect to `m`. -scoped notation μ "[" f "|" m "]" => MeasureTheory.condexp m μ f +scoped notation μ "[" f "|" m "]" => MeasureTheory.condExp m μ f + +theorem condExp_of_not_le (hm_not : ¬m ≤ m0) : μ[f|m] = 0 := by rw [condExp, dif_neg hm_not] + +@[deprecated (since := "2025-01-21")] alias condexp_of_not_le := condExp_of_not_le -theorem condexp_of_not_le (hm_not : ¬m ≤ m0) : μ[f|m] = 0 := by rw [condexp, dif_neg hm_not] +theorem condExp_of_not_sigmaFinite (hm : m ≤ m0) (hμm_not : ¬SigmaFinite (μ.trim hm)) : + μ[f|m] = 0 := by rw [condExp, dif_pos hm, dif_neg]; push_neg; exact fun h => absurd h hμm_not -theorem condexp_of_not_sigmaFinite (hm : m ≤ m0) (hμm_not : ¬SigmaFinite (μ.trim hm)) : - μ[f|m] = 0 := by rw [condexp, dif_pos hm, dif_neg]; push_neg; exact fun h => absurd h hμm_not +@[deprecated (since := "2025-01-21")] alias condexp_of_not_sigmaFinite := condExp_of_not_sigmaFinite -theorem condexp_of_sigmaFinite (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : +theorem condExp_of_sigmaFinite (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : μ[f|m] = if Integrable f μ then if StronglyMeasurable[m] f then f - else aestronglyMeasurable'_condexpL1.mk (condexpL1 hm μ f) + else aestronglyMeasurable'_condExpL1.mk (condExpL1 hm μ f) else 0 := by - rw [condexp, dif_pos hm] + rw [condExp, dif_pos hm] simp only [hμm, Ne, true_and] by_cases hf : Integrable f μ · rw [dif_pos hf, if_pos hf] · rw [dif_neg hf, if_neg hf] -theorem condexp_of_stronglyMeasurable (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] {f : α → F'} +@[deprecated (since := "2025-01-21")] alias condexp_of_sigmaFinite := condExp_of_sigmaFinite + +theorem condExp_of_stronglyMeasurable (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] {f : α → F'} (hf : StronglyMeasurable[m] f) (hfi : Integrable f μ) : μ[f|m] = f := by - rw [condexp_of_sigmaFinite hm, if_pos hfi, if_pos hf] + rw [condExp_of_sigmaFinite hm, if_pos hfi, if_pos hf] + +@[deprecated (since := "2025-01-21")] +alias condexp_of_stronglyMeasurable := condExp_of_stronglyMeasurable -theorem condexp_const (hm : m ≤ m0) (c : F') [IsFiniteMeasure μ] : +theorem condExp_const (hm : m ≤ m0) (c : F') [IsFiniteMeasure μ] : μ[fun _ : α => c|m] = fun _ => c := - condexp_of_stronglyMeasurable hm (@stronglyMeasurable_const _ _ m _ _) (integrable_const c) + condExp_of_stronglyMeasurable hm (@stronglyMeasurable_const _ _ m _ _) (integrable_const c) -theorem condexp_ae_eq_condexpL1 (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] (f : α → F') : - μ[f|m] =ᵐ[μ] condexpL1 hm μ f := by - rw [condexp_of_sigmaFinite hm] +@[deprecated (since := "2025-01-21")] alias condexp_const := condExp_const + +theorem condExp_ae_eq_condExpL1 (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] (f : α → F') : + μ[f|m] =ᵐ[μ] condExpL1 hm μ f := by + rw [condExp_of_sigmaFinite hm] by_cases hfi : Integrable f μ · rw [if_pos hfi] by_cases hfm : StronglyMeasurable[m] f · rw [if_pos hfm] - exact (condexpL1_of_aestronglyMeasurable' (StronglyMeasurable.aeStronglyMeasurable' hfm) + exact (condExpL1_of_aestronglyMeasurable' (StronglyMeasurable.aeStronglyMeasurable' hfm) hfi).symm · rw [if_neg hfm] - exact (AEStronglyMeasurable'.ae_eq_mk aestronglyMeasurable'_condexpL1).symm - rw [if_neg hfi, condexpL1_undef hfi] + exact (AEStronglyMeasurable'.ae_eq_mk aestronglyMeasurable'_condExpL1).symm + rw [if_neg hfi, condExpL1_undef hfi] exact (coeFn_zero _ _ _).symm -theorem condexp_ae_eq_condexpL1CLM (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) : - μ[f|m] =ᵐ[μ] condexpL1CLM F' hm μ (hf.toL1 f) := by - refine (condexp_ae_eq_condexpL1 hm f).trans (Eventually.of_forall fun x => ?_) - rw [condexpL1_eq hf] +@[deprecated (since := "2025-01-21")] alias condexp_ae_eq_condexpL1 := condExp_ae_eq_condExpL1 + +theorem condExp_ae_eq_condExpL1CLM (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) : + μ[f|m] =ᵐ[μ] condExpL1CLM F' hm μ (hf.toL1 f) := by + refine (condExp_ae_eq_condExpL1 hm f).trans (Eventually.of_forall fun x => ?_) + rw [condExpL1_eq hf] -theorem condexp_undef (hf : ¬Integrable f μ) : μ[f|m] = 0 := by +@[deprecated (since := "2025-01-21")] alias condexp_ae_eq_condexpL1CLM := condExp_ae_eq_condExpL1CLM + +theorem condExp_undef (hf : ¬Integrable f μ) : μ[f|m] = 0 := by by_cases hm : m ≤ m0 - swap; · rw [condexp_of_not_le hm] + swap; · rw [condExp_of_not_le hm] by_cases hμm : SigmaFinite (μ.trim hm) - swap; · rw [condexp_of_not_sigmaFinite hm hμm] + swap; · rw [condExp_of_not_sigmaFinite hm hμm] haveI : SigmaFinite (μ.trim hm) := hμm - rw [condexp_of_sigmaFinite, if_neg hf] + rw [condExp_of_sigmaFinite, if_neg hf] + +@[deprecated (since := "2025-01-21")] alias condexp_undef := condExp_undef @[simp] -theorem condexp_zero : μ[(0 : α → F')|m] = 0 := by +theorem condExp_zero : μ[(0 : α → F')|m] = 0 := by by_cases hm : m ≤ m0 - swap; · rw [condexp_of_not_le hm] + swap; · rw [condExp_of_not_le hm] by_cases hμm : SigmaFinite (μ.trim hm) - swap; · rw [condexp_of_not_sigmaFinite hm hμm] + swap; · rw [condExp_of_not_sigmaFinite hm hμm] haveI : SigmaFinite (μ.trim hm) := hμm exact - condexp_of_stronglyMeasurable hm (@stronglyMeasurable_zero _ _ m _ _) (integrable_zero _ _ _) + condExp_of_stronglyMeasurable hm (@stronglyMeasurable_zero _ _ m _ _) (integrable_zero _ _ _) -theorem stronglyMeasurable_condexp : StronglyMeasurable[m] (μ[f|m]) := by +@[deprecated (since := "2025-01-21")] alias condexp_zero := condExp_zero + +theorem stronglyMeasurable_condExp : StronglyMeasurable[m] (μ[f|m]) := by by_cases hm : m ≤ m0 - swap; · rw [condexp_of_not_le hm]; exact stronglyMeasurable_zero + swap; · rw [condExp_of_not_le hm]; exact stronglyMeasurable_zero by_cases hμm : SigmaFinite (μ.trim hm) - swap; · rw [condexp_of_not_sigmaFinite hm hμm]; exact stronglyMeasurable_zero + swap; · rw [condExp_of_not_sigmaFinite hm hμm]; exact stronglyMeasurable_zero haveI : SigmaFinite (μ.trim hm) := hμm - rw [condexp_of_sigmaFinite hm] + rw [condExp_of_sigmaFinite hm] split_ifs with hfi hfm · exact hfm · exact AEStronglyMeasurable'.stronglyMeasurable_mk _ · exact stronglyMeasurable_zero -theorem condexp_congr_ae (h : f =ᵐ[μ] g) : μ[f|m] =ᵐ[μ] μ[g|m] := by +@[deprecated (since := "2025-01-21")] alias stronglyMeasurable_condexp := stronglyMeasurable_condExp + +theorem condExp_congr_ae (h : f =ᵐ[μ] g) : μ[f|m] =ᵐ[μ] μ[g|m] := by by_cases hm : m ≤ m0 - swap; · simp_rw [condexp_of_not_le hm]; rfl + swap; · simp_rw [condExp_of_not_le hm]; rfl by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm]; rfl + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl haveI : SigmaFinite (μ.trim hm) := hμm - exact (condexp_ae_eq_condexpL1 hm f).trans - (Filter.EventuallyEq.trans (by rw [condexpL1_congr_ae hm h]) - (condexp_ae_eq_condexpL1 hm g).symm) + exact (condExp_ae_eq_condExpL1 hm f).trans + (Filter.EventuallyEq.trans (by rw [condExpL1_congr_ae hm h]) + (condExp_ae_eq_condExpL1 hm g).symm) -theorem condexp_of_aestronglyMeasurable' (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] {f : α → F'} +@[deprecated (since := "2025-01-21")] alias condexp_congr_ae := condExp_congr_ae + +theorem condExp_of_aestronglyMeasurable' (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] {f : α → F'} (hf : AEStronglyMeasurable' m f μ) (hfi : Integrable f μ) : μ[f|m] =ᵐ[μ] f := by - refine ((condexp_congr_ae hf.ae_eq_mk).trans ?_).trans hf.ae_eq_mk.symm - rw [condexp_of_stronglyMeasurable hm hf.stronglyMeasurable_mk + refine ((condExp_congr_ae hf.ae_eq_mk).trans ?_).trans hf.ae_eq_mk.symm + rw [condExp_of_stronglyMeasurable hm hf.stronglyMeasurable_mk ((integrable_congr hf.ae_eq_mk).mp hfi)] -theorem integrable_condexp : Integrable (μ[f|m]) μ := by +@[deprecated (since := "2025-01-21")] +alias condexp_of_aestronglyMeasurable' := condExp_of_aestronglyMeasurable' + +theorem integrable_condExp : Integrable (μ[f|m]) μ := by by_cases hm : m ≤ m0 - swap; · rw [condexp_of_not_le hm]; exact integrable_zero _ _ _ + swap; · rw [condExp_of_not_le hm]; exact integrable_zero _ _ _ by_cases hμm : SigmaFinite (μ.trim hm) - swap; · rw [condexp_of_not_sigmaFinite hm hμm]; exact integrable_zero _ _ _ + swap; · rw [condExp_of_not_sigmaFinite hm hμm]; exact integrable_zero _ _ _ haveI : SigmaFinite (μ.trim hm) := hμm - exact (integrable_condexpL1 f).congr (condexp_ae_eq_condexpL1 hm f).symm + exact (integrable_condExpL1 f).congr (condExp_ae_eq_condExpL1 hm f).symm + +@[deprecated (since := "2025-01-21")] alias integrable_condexp := integrable_condExp /-- The integral of the conditional expectation `μ[f|hm]` over an `m`-measurable set is equal to the integral of `f` on that set. -/ -theorem setIntegral_condexp (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) +theorem setIntegral_condExp (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) (hs : MeasurableSet[m] s) : ∫ x in s, (μ[f|m]) x ∂μ = ∫ x in s, f x ∂μ := by - rw [setIntegral_congr_ae (hm s hs) ((condexp_ae_eq_condexpL1 hm f).mono fun x hx _ => hx)] - exact setIntegral_condexpL1 hf hs + rw [setIntegral_congr_ae (hm s hs) ((condExp_ae_eq_condExpL1 hm f).mono fun x hx _ => hx)] + exact setIntegral_condExpL1 hf hs + +@[deprecated (since := "2025-01-21")] alias setIntegral_condexp := setIntegral_condExp -@[deprecated (since := "2024-04-17")] alias set_integral_condexp := setIntegral_condexp +@[deprecated (since := "2024-04-17")] alias set_integral_condexp := setIntegral_condExp -theorem integral_condexp (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : +theorem integral_condExp (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : ∫ x, (μ[f|m]) x ∂μ = ∫ x, f x ∂μ := by by_cases hf : Integrable f μ · suffices ∫ x in Set.univ, (μ[f|m]) x ∂μ = ∫ x in Set.univ, f x ∂μ by simp_rw [setIntegral_univ] at this; exact this - exact setIntegral_condexp hm hf (@MeasurableSet.univ _ m) - simp only [condexp_undef hf, Pi.zero_apply, integral_zero, integral_undef hf] + exact setIntegral_condExp hm hf (@MeasurableSet.univ _ m) + simp only [condExp_undef hf, Pi.zero_apply, integral_zero, integral_undef hf] -/-- Total probability law using `condexp` as conditional probability. -/ -theorem integral_condexp_indicator [mF : MeasurableSpace F] {Y : α → F} (hY : Measurable Y) +@[deprecated (since := "2025-01-21")] alias integral_condexp := integral_condExp + +/-- Total probability law using `condExp` as conditional probability. -/ +theorem integral_condExp_indicator [mF : MeasurableSpace F] {Y : α → F} (hY : Measurable Y) [SigmaFinite (μ.trim hY.comap_le)] {A : Set α} (hA : MeasurableSet A) : ∫ x, (μ[(A.indicator fun _ ↦ (1 : ℝ)) | mF.comap Y]) x ∂μ = (μ A).toReal := by - rw [integral_condexp, integral_indicator hA, setIntegral_const, smul_eq_mul, mul_one] + rw [integral_condExp, integral_indicator hA, setIntegral_const, smul_eq_mul, mul_one] + +@[deprecated (since := "2025-01-21")] alias integral_condexp_indicator := integral_condExp_indicator /-- **Uniqueness of the conditional expectation** If a function is a.e. `m`-measurable, verifies an integrability condition and has same integral as `f` on all `m`-measurable sets, then it is a.e. equal to `μ[f|hm]`. -/ -theorem ae_eq_condexp_of_forall_setIntegral_eq (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] +theorem ae_eq_condExp_of_forall_setIntegral_eq (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] {f g : α → F'} (hf : Integrable f μ) (hg_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn g s μ) (hg_eq : ∀ s : Set α, MeasurableSet[m] s → μ s < ∞ → ∫ x in s, g x ∂μ = ∫ x in s, f x ∂μ) (hgm : AEStronglyMeasurable' m g μ) : g =ᵐ[μ] μ[f|m] := by refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hm hg_int_finite - (fun s _ _ => integrable_condexp.integrableOn) (fun s hs hμs => ?_) hgm - (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condexp) - rw [hg_eq s hs hμs, setIntegral_condexp hm hf hs] + (fun s _ _ => integrable_condExp.integrableOn) (fun s hs hμs => ?_) hgm + (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condExp) + rw [hg_eq s hs hμs, setIntegral_condExp hm hf hs] + +@[deprecated (since := "2025-01-21")] +alias ae_eq_condexp_of_forall_setIntegral_eq := ae_eq_condExp_of_forall_setIntegral_eq @[deprecated (since := "2024-04-17")] -alias ae_eq_condexp_of_forall_set_integral_eq := ae_eq_condexp_of_forall_setIntegral_eq +alias ae_eq_condExp_of_forall_set_integral_eq := ae_eq_condExp_of_forall_setIntegral_eq + +@[deprecated (since := "2025-01-21")] +alias ae_eq_condexp_of_forall_set_integral_eq := ae_eq_condExp_of_forall_set_integral_eq -theorem condexp_bot' [hμ : NeZero μ] (f : α → F') : +theorem condExp_bot' [hμ : NeZero μ] (f : α → F') : μ[f|⊥] = fun _ => (μ Set.univ).toReal⁻¹ • ∫ x, f x ∂μ := by by_cases hμ_finite : IsFiniteMeasure μ swap · have h : ¬SigmaFinite (μ.trim bot_le) := by rwa [sigmaFinite_trim_bot_iff] rw [not_isFiniteMeasure_iff] at hμ_finite - rw [condexp_of_not_sigmaFinite bot_le h] + rw [condExp_of_not_sigmaFinite bot_le h] simp only [hμ_finite, ENNReal.top_toReal, inv_zero, zero_smul] rfl - have h_meas : StronglyMeasurable[⊥] (μ[f|⊥]) := stronglyMeasurable_condexp + have h_meas : StronglyMeasurable[⊥] (μ[f|⊥]) := stronglyMeasurable_condExp obtain ⟨c, h_eq⟩ := stronglyMeasurable_bot_iff.mp h_meas rw [h_eq] - have h_integral : ∫ x, (μ[f|⊥]) x ∂μ = ∫ x, f x ∂μ := integral_condexp bot_le + have h_integral : ∫ x, (μ[f|⊥]) x ∂μ = ∫ x, f x ∂μ := integral_condExp bot_le simp_rw [h_eq, integral_const] at h_integral rw [← h_integral, ← smul_assoc, smul_eq_mul, inv_mul_cancel₀, one_smul] rw [Ne, ENNReal.toReal_eq_zero_iff, not_or] exact ⟨NeZero.ne _, measure_ne_top μ Set.univ⟩ -theorem condexp_bot_ae_eq (f : α → F') : +@[deprecated (since := "2025-01-21")] alias condexp_bot' := condExp_bot' + +theorem condExp_bot_ae_eq (f : α → F') : μ[f|⊥] =ᵐ[μ] fun _ => (μ Set.univ).toReal⁻¹ • ∫ x, f x ∂μ := by rcases eq_zero_or_neZero μ with rfl | hμ · rw [ae_zero]; exact eventually_bot - · exact Eventually.of_forall <| congr_fun (condexp_bot' f) + · exact Eventually.of_forall <| congr_fun (condExp_bot' f) + +@[deprecated (since := "2025-01-21")] alias condexp_bot_ae_eq := condExp_bot_ae_eq -theorem condexp_bot [IsProbabilityMeasure μ] (f : α → F') : μ[f|⊥] = fun _ => ∫ x, f x ∂μ := by - refine (condexp_bot' f).trans ?_; rw [measure_univ, ENNReal.one_toReal, inv_one, one_smul] +theorem condExp_bot [IsProbabilityMeasure μ] (f : α → F') : μ[f|⊥] = fun _ => ∫ x, f x ∂μ := by + refine (condExp_bot' f).trans ?_; rw [measure_univ, ENNReal.one_toReal, inv_one, one_smul] -theorem condexp_add (hf : Integrable f μ) (hg : Integrable g μ) : +@[deprecated (since := "2025-01-21")] alias condexp_bot := condExp_bot + +theorem condExp_add (hf : Integrable f μ) (hg : Integrable g μ) : μ[f + g|m] =ᵐ[μ] μ[f|m] + μ[g|m] := by by_cases hm : m ≤ m0 - swap; · simp_rw [condexp_of_not_le hm]; simp + swap; · simp_rw [condExp_of_not_le hm]; simp by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm]; simp + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; simp haveI : SigmaFinite (μ.trim hm) := hμm - refine (condexp_ae_eq_condexpL1 hm _).trans ?_ - rw [condexpL1_add hf hg] + refine (condExp_ae_eq_condExpL1 hm _).trans ?_ + rw [condExpL1_add hf hg] exact (coeFn_add _ _).trans - ((condexp_ae_eq_condexpL1 hm _).symm.add (condexp_ae_eq_condexpL1 hm _).symm) + ((condExp_ae_eq_condExpL1 hm _).symm.add (condExp_ae_eq_condExpL1 hm _).symm) + +@[deprecated (since := "2025-01-21")] alias condexp_add := condExp_add -theorem condexp_finset_sum {ι : Type*} {s : Finset ι} {f : ι → α → F'} +theorem condExp_finset_sum {ι : Type*} {s : Finset ι} {f : ι → α → F'} (hf : ∀ i ∈ s, Integrable (f i) μ) : μ[∑ i ∈ s, f i|m] =ᵐ[μ] ∑ i ∈ s, μ[f i|m] := by induction' s using Finset.induction_on with i s his heq hf - · rw [Finset.sum_empty, Finset.sum_empty, condexp_zero] + · rw [Finset.sum_empty, Finset.sum_empty, condExp_zero] · rw [Finset.sum_insert his, Finset.sum_insert his] - exact (condexp_add (hf i <| Finset.mem_insert_self i s) <| + exact (condExp_add (hf i <| Finset.mem_insert_self i s) <| integrable_finset_sum' _ fun j hmem => hf j <| Finset.mem_insert_of_mem hmem).trans ((EventuallyEq.refl _ _).add (heq fun j hmem => hf j <| Finset.mem_insert_of_mem hmem)) -theorem condexp_smul (c : 𝕜) (f : α → F') : μ[c • f|m] =ᵐ[μ] c • μ[f|m] := by +@[deprecated (since := "2025-01-21")] alias condexp_finset_sum := condExp_finset_sum + +theorem condExp_smul (c : 𝕜) (f : α → F') : μ[c • f|m] =ᵐ[μ] c • μ[f|m] := by by_cases hm : m ≤ m0 - swap; · simp_rw [condexp_of_not_le hm]; simp + swap; · simp_rw [condExp_of_not_le hm]; simp by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm]; simp + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; simp haveI : SigmaFinite (μ.trim hm) := hμm - refine (condexp_ae_eq_condexpL1 hm _).trans ?_ - rw [condexpL1_smul c f] - refine (@condexp_ae_eq_condexpL1 _ _ _ _ _ m _ _ hm _ f).mp ?_ - refine (coeFn_smul c (condexpL1 hm μ f)).mono fun x hx1 hx2 => ?_ + refine (condExp_ae_eq_condExpL1 hm _).trans ?_ + rw [condExpL1_smul c f] + refine (@condExp_ae_eq_condExpL1 _ _ _ _ _ m _ _ hm _ f).mp ?_ + refine (coeFn_smul c (condExpL1 hm μ f)).mono fun x hx1 hx2 => ?_ simp only [hx1, hx2, Pi.smul_apply] -theorem condexp_neg (f : α → F') : μ[-f|m] =ᵐ[μ] -μ[f|m] := by +@[deprecated (since := "2025-01-21")] alias condexp_smul := condExp_smul + +theorem condExp_neg (f : α → F') : μ[-f|m] =ᵐ[μ] -μ[f|m] := by letI : Module ℝ (α → F') := @Pi.module α (fun _ => F') ℝ _ _ fun _ => inferInstance calc μ[-f|m] = μ[(-1 : ℝ) • f|m] := by rw [neg_one_smul ℝ f] - _ =ᵐ[μ] (-1 : ℝ) • μ[f|m] := condexp_smul (-1) f + _ =ᵐ[μ] (-1 : ℝ) • μ[f|m] := condExp_smul (-1) f _ = -μ[f|m] := neg_one_smul ℝ (μ[f|m]) -theorem condexp_sub (hf : Integrable f μ) (hg : Integrable g μ) : +@[deprecated (since := "2025-01-21")] alias condexp_neg := condExp_neg + +theorem condExp_sub (hf : Integrable f μ) (hg : Integrable g μ) : μ[f - g|m] =ᵐ[μ] μ[f|m] - μ[g|m] := by simp_rw [sub_eq_add_neg] - exact (condexp_add hf hg.neg).trans (EventuallyEq.rfl.add (condexp_neg g)) + exact (condExp_add hf hg.neg).trans (EventuallyEq.rfl.add (condExp_neg g)) + +@[deprecated (since := "2025-01-21")] alias condexp_sub := condExp_sub -theorem condexp_condexp_of_le {m₁ m₂ m0 : MeasurableSpace α} {μ : Measure α} (hm₁₂ : m₁ ≤ m₂) +theorem condExp_condExp_of_le {m₁ m₂ m0 : MeasurableSpace α} {μ : Measure α} (hm₁₂ : m₁ ≤ m₂) (hm₂ : m₂ ≤ m0) [SigmaFinite (μ.trim hm₂)] : μ[μ[f|m₂]|m₁] =ᵐ[μ] μ[f|m₁] := by by_cases hμm₁ : SigmaFinite (μ.trim (hm₁₂.trans hm₂)) - swap; · simp_rw [condexp_of_not_sigmaFinite (hm₁₂.trans hm₂) hμm₁]; rfl + swap; · simp_rw [condExp_of_not_sigmaFinite (hm₁₂.trans hm₂) hμm₁]; rfl haveI : SigmaFinite (μ.trim (hm₁₂.trans hm₂)) := hμm₁ by_cases hf : Integrable f μ - swap; · simp_rw [condexp_undef hf, condexp_zero]; rfl + swap; · simp_rw [condExp_undef hf, condExp_zero]; rfl refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' (hm₁₂.trans hm₂) - (fun s _ _ => integrable_condexp.integrableOn) - (fun s _ _ => integrable_condexp.integrableOn) ?_ - (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condexp) - (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condexp) + (fun s _ _ => integrable_condExp.integrableOn) + (fun s _ _ => integrable_condExp.integrableOn) ?_ + (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condExp) + (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condExp) intro s hs _ - rw [setIntegral_condexp (hm₁₂.trans hm₂) integrable_condexp hs] - rw [setIntegral_condexp (hm₁₂.trans hm₂) hf hs, setIntegral_condexp hm₂ hf (hm₁₂ s hs)] + rw [setIntegral_condExp (hm₁₂.trans hm₂) integrable_condExp hs] + rw [setIntegral_condExp (hm₁₂.trans hm₂) hf hs, setIntegral_condExp hm₂ hf (hm₁₂ s hs)] -theorem condexp_mono {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] +@[deprecated (since := "2025-01-21")] alias condexp_condexp_of_le := condExp_condExp_of_le + +theorem condExp_mono {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] [OrderedSMul ℝ E] {f g : α → E} (hf : Integrable f μ) (hg : Integrable g μ) (hfg : f ≤ᵐ[μ] g) : μ[f|m] ≤ᵐ[μ] μ[g|m] := by by_cases hm : m ≤ m0 - swap; · simp_rw [condexp_of_not_le hm]; rfl + swap; · simp_rw [condExp_of_not_le hm]; rfl by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm]; rfl + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl haveI : SigmaFinite (μ.trim hm) := hμm - exact (condexp_ae_eq_condexpL1 hm _).trans_le - ((condexpL1_mono hf hg hfg).trans_eq (condexp_ae_eq_condexpL1 hm _).symm) + exact (condExp_ae_eq_condExpL1 hm _).trans_le + ((condExpL1_mono hf hg hfg).trans_eq (condExp_ae_eq_condExpL1 hm _).symm) + +@[deprecated (since := "2025-01-21")] alias condexp_mono := condExp_mono -theorem condexp_nonneg {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] +theorem condExp_nonneg {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] [OrderedSMul ℝ E] {f : α → E} (hf : 0 ≤ᵐ[μ] f) : 0 ≤ᵐ[μ] μ[f|m] := by by_cases hfint : Integrable f μ - · rw [(condexp_zero.symm : (0 : α → E) = μ[0|m])] - exact condexp_mono (integrable_zero _ _ _) hfint hf - · rw [condexp_undef hfint] + · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] + exact condExp_mono (integrable_zero _ _ _) hfint hf + · rw [condExp_undef hfint] -theorem condexp_nonpos {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] +@[deprecated (since := "2025-01-21")] alias condexp_nonneg := condExp_nonneg + +theorem condExp_nonpos {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] [OrderedSMul ℝ E] {f : α → E} (hf : f ≤ᵐ[μ] 0) : μ[f|m] ≤ᵐ[μ] 0 := by by_cases hfint : Integrable f μ - · rw [(condexp_zero.symm : (0 : α → E) = μ[0|m])] - exact condexp_mono hfint (integrable_zero _ _ _) hf - · rw [condexp_undef hfint] + · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] + exact condExp_mono hfint (integrable_zero _ _ _) hf + · rw [condExp_undef hfint] + +@[deprecated (since := "2025-01-21")] alias condexp_nonpos := condExp_nonpos /-- **Lebesgue dominated convergence theorem**: sufficient conditions under which almost everywhere convergence of a sequence of functions implies the convergence of their image by - `condexpL1`. -/ -theorem tendsto_condexpL1_of_dominated_convergence (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] + `condExpL1`. -/ +theorem tendsto_condExpL1_of_dominated_convergence (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] {fs : ℕ → α → F'} {f : α → F'} (bound_fs : α → ℝ) (hfs_meas : ∀ n, AEStronglyMeasurable (fs n) μ) (h_int_bound_fs : Integrable bound_fs μ) (hfs_bound : ∀ n, ∀ᵐ x ∂μ, ‖fs n x‖ ≤ bound_fs x) (hfs : ∀ᵐ x ∂μ, Tendsto (fun n => fs n x) atTop (𝓝 (f x))) : - Tendsto (fun n => condexpL1 hm μ (fs n)) atTop (𝓝 (condexpL1 hm μ f)) := + Tendsto (fun n => condExpL1 hm μ (fs n)) atTop (𝓝 (condExpL1 hm μ f)) := tendsto_setToFun_of_dominated_convergence _ bound_fs hfs_meas h_int_bound_fs hfs_bound hfs +@[deprecated (since := "2025-01-21")] +alias tendsto_condexpL1_of_dominated_convergence := tendsto_condExpL1_of_dominated_convergence + /-- If two sequences of functions have a.e. equal conditional expectations at each step, converge and verify dominated convergence hypotheses, then the conditional expectations of their limits are a.e. equal. -/ -theorem tendsto_condexp_unique (fs gs : ℕ → α → F') (f g : α → F') +theorem tendsto_condExp_unique (fs gs : ℕ → α → F') (f g : α → F') (hfs_int : ∀ n, Integrable (fs n) μ) (hgs_int : ∀ n, Integrable (gs n) μ) (hfs : ∀ᵐ x ∂μ, Tendsto (fun n => fs n x) atTop (𝓝 (f x))) (hgs : ∀ᵐ x ∂μ, Tendsto (fun n => gs n x) atTop (𝓝 (g x))) (bound_fs : α → ℝ) @@ -369,22 +438,24 @@ theorem tendsto_condexp_unique (fs gs : ℕ → α → F') (f g : α → F') (h_int_bound_gs : Integrable bound_gs μ) (hfs_bound : ∀ n, ∀ᵐ x ∂μ, ‖fs n x‖ ≤ bound_fs x) (hgs_bound : ∀ n, ∀ᵐ x ∂μ, ‖gs n x‖ ≤ bound_gs x) (hfg : ∀ n, μ[fs n|m] =ᵐ[μ] μ[gs n|m]) : μ[f|m] =ᵐ[μ] μ[g|m] := by - by_cases hm : m ≤ m0; swap; · simp_rw [condexp_of_not_le hm]; rfl - by_cases hμm : SigmaFinite (μ.trim hm); swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm]; rfl + by_cases hm : m ≤ m0; swap; · simp_rw [condExp_of_not_le hm]; rfl + by_cases hμm : SigmaFinite (μ.trim hm); swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl haveI : SigmaFinite (μ.trim hm) := hμm - refine (condexp_ae_eq_condexpL1 hm f).trans ((condexp_ae_eq_condexpL1 hm g).trans ?_).symm + refine (condExp_ae_eq_condExpL1 hm f).trans ((condExp_ae_eq_condExpL1 hm g).trans ?_).symm rw [← Lp.ext_iff] - have hn_eq : ∀ n, condexpL1 hm μ (gs n) = condexpL1 hm μ (fs n) := by + have hn_eq : ∀ n, condExpL1 hm μ (gs n) = condExpL1 hm μ (fs n) := by intro n ext1 - refine (condexp_ae_eq_condexpL1 hm (gs n)).symm.trans ((hfg n).symm.trans ?_) - exact condexp_ae_eq_condexpL1 hm (fs n) - have hcond_fs : Tendsto (fun n => condexpL1 hm μ (fs n)) atTop (𝓝 (condexpL1 hm μ f)) := - tendsto_condexpL1_of_dominated_convergence hm _ (fun n => (hfs_int n).1) h_int_bound_fs + refine (condExp_ae_eq_condExpL1 hm (gs n)).symm.trans ((hfg n).symm.trans ?_) + exact condExp_ae_eq_condExpL1 hm (fs n) + have hcond_fs : Tendsto (fun n => condExpL1 hm μ (fs n)) atTop (𝓝 (condExpL1 hm μ f)) := + tendsto_condExpL1_of_dominated_convergence hm _ (fun n => (hfs_int n).1) h_int_bound_fs hfs_bound hfs - have hcond_gs : Tendsto (fun n => condexpL1 hm μ (gs n)) atTop (𝓝 (condexpL1 hm μ g)) := - tendsto_condexpL1_of_dominated_convergence hm _ (fun n => (hgs_int n).1) h_int_bound_gs + have hcond_gs : Tendsto (fun n => condExpL1 hm μ (gs n)) atTop (𝓝 (condExpL1 hm μ g)) := + tendsto_condExpL1_of_dominated_convergence hm _ (fun n => (hgs_int n).1) h_int_bound_gs hgs_bound hgs exact tendsto_nhds_unique_of_eventuallyEq hcond_gs hcond_fs (Eventually.of_forall hn_eq) +@[deprecated (since := "2025-01-21")] alias tendsto_condexp_unique := tendsto_condExp_unique + end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean index b90f7b167be62..b140355f0dcd5 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean @@ -17,12 +17,12 @@ The conditional expectation of an `L²` function is defined in is integrable and define a map `Set α → (E →L[ℝ] (α →₁[μ] E))` which to a set associates a linear map. That linear map sends `x ∈ E` to the conditional expectation of the indicator of the set with value `x`. -* Extend that map to `condexpL1CLM : (α →₁[μ] E) →L[ℝ] (α →₁[μ] E)`. This is done using the same +* Extend that map to `condExpL1CLM : (α →₁[μ] E) →L[ℝ] (α →₁[μ] E)`. This is done using the same construction as the Bochner integral (see the file `MeasureTheory/Integral/SetToL1`). ## Main definitions -* `condexpL1`: Conditional expectation of a function as a linear map from `L1` to itself. +* `condExpL1`: Conditional expectation of a function as a linear map from `L1` to itself. -/ @@ -54,7 +54,7 @@ section CondexpInd /-! ## Conditional expectation of an indicator as a continuous linear map. The goal of this section is to build -`condexpInd (hm : m ≤ m0) (μ : Measure α) (s : Set s) : G →L[ℝ] α →₁[μ] G`, which +`condExpInd (hm : m ≤ m0) (μ : Measure α) (s : Set s) : G →L[ℝ] α →₁[μ] G`, which takes `x : G` to the conditional expectation of the indicator of the set `s` with value `x`, seen as an element of `α →₁[μ] G`. -/ @@ -67,91 +67,107 @@ section CondexpIndL1Fin /-- Conditional expectation of the indicator of a measurable set with finite measure, as a function in L1. -/ -def condexpIndL1Fin (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) +def condExpIndL1Fin (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : α →₁[μ] G := - (integrable_condexpIndSMul hm hs hμs x).toL1 _ + (integrable_condExpIndSMul hm hs hμs x).toL1 _ -theorem condexpIndL1Fin_ae_eq_condexpIndSMul (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] +@[deprecated (since := "2025-01-21")] noncomputable alias condexpIndL1Fin := condExpIndL1Fin + +theorem condExpIndL1Fin_ae_eq_condExpIndSMul (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : - condexpIndL1Fin hm hs hμs x =ᵐ[μ] condexpIndSMul hm hs hμs x := - (integrable_condexpIndSMul hm hs hμs x).coeFn_toL1 + condExpIndL1Fin hm hs hμs x =ᵐ[μ] condExpIndSMul hm hs hμs x := + (integrable_condExpIndSMul hm hs hμs x).coeFn_toL1 + +@[deprecated (since := "2025-01-21")] +alias condexpIndL1Fin_ae_eq_condexpIndSMul := condExpIndL1Fin_ae_eq_condExpIndSMul variable {hm : m ≤ m0} [SigmaFinite (μ.trim hm)] -- Porting note: this lemma fills the hole in `refine' (Memℒp.coeFn_toLp _) ...` -- which is not automatically filled in Lean 4 private theorem q {hs : MeasurableSet s} {hμs : μ s ≠ ∞} {x : G} : - Memℒp (condexpIndSMul hm hs hμs x) 1 μ := by - rw [memℒp_one_iff_integrable]; apply integrable_condexpIndSMul + Memℒp (condExpIndSMul hm hs hμs x) 1 μ := by + rw [memℒp_one_iff_integrable]; apply integrable_condExpIndSMul -theorem condexpIndL1Fin_add (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x y : G) : - condexpIndL1Fin hm hs hμs (x + y) = - condexpIndL1Fin hm hs hμs x + condexpIndL1Fin hm hs hμs y := by +theorem condExpIndL1Fin_add (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x y : G) : + condExpIndL1Fin hm hs hμs (x + y) = + condExpIndL1Fin hm hs hμs x + condExpIndL1Fin hm hs hμs y := by ext1 refine (Memℒp.coeFn_toLp q).trans ?_ refine EventuallyEq.trans ?_ (Lp.coeFn_add _ _).symm refine EventuallyEq.trans ?_ (EventuallyEq.add (Memℒp.coeFn_toLp q).symm (Memℒp.coeFn_toLp q).symm) - rw [condexpIndSMul_add] + rw [condExpIndSMul_add] refine (Lp.coeFn_add _ _).trans (Eventually.of_forall fun a => ?_) rfl -theorem condexpIndL1Fin_smul (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (c : ℝ) (x : G) : - condexpIndL1Fin hm hs hμs (c • x) = c • condexpIndL1Fin hm hs hμs x := by +@[deprecated (since := "2025-01-21")] alias condexpIndL1Fin_add := condExpIndL1Fin_add + +theorem condExpIndL1Fin_smul (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (c : ℝ) (x : G) : + condExpIndL1Fin hm hs hμs (c • x) = c • condExpIndL1Fin hm hs hμs x := by ext1 refine (Memℒp.coeFn_toLp q).trans ?_ refine EventuallyEq.trans ?_ (Lp.coeFn_smul _ _).symm - rw [condexpIndSMul_smul hs hμs c x] + rw [condExpIndSMul_smul hs hμs c x] refine (Lp.coeFn_smul _ _).trans ?_ - refine (condexpIndL1Fin_ae_eq_condexpIndSMul hm hs hμs x).mono fun y hy => ?_ + refine (condExpIndL1Fin_ae_eq_condExpIndSMul hm hs hμs x).mono fun y hy => ?_ simp only [Pi.smul_apply, hy] -theorem condexpIndL1Fin_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (hs : MeasurableSet s) +@[deprecated (since := "2025-01-21")] alias condexpIndL1Fin_smul := condExpIndL1Fin_smul + +theorem condExpIndL1Fin_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (c : 𝕜) (x : F) : - condexpIndL1Fin hm hs hμs (c • x) = c • condexpIndL1Fin hm hs hμs x := by + condExpIndL1Fin hm hs hμs (c • x) = c • condExpIndL1Fin hm hs hμs x := by ext1 refine (Memℒp.coeFn_toLp q).trans ?_ refine EventuallyEq.trans ?_ (Lp.coeFn_smul _ _).symm - rw [condexpIndSMul_smul' hs hμs c x] + rw [condExpIndSMul_smul' hs hμs c x] refine (Lp.coeFn_smul _ _).trans ?_ - refine (condexpIndL1Fin_ae_eq_condexpIndSMul hm hs hμs x).mono fun y hy => ?_ + refine (condExpIndL1Fin_ae_eq_condExpIndSMul hm hs hμs x).mono fun y hy => ?_ simp only [Pi.smul_apply, hy] -theorem norm_condexpIndL1Fin_le (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : - ‖condexpIndL1Fin hm hs hμs x‖ ≤ (μ s).toReal * ‖x‖ := by +@[deprecated (since := "2025-01-21")] alias condexpIndL1Fin_smul' := condExpIndL1Fin_smul' + +theorem norm_condExpIndL1Fin_le (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : + ‖condExpIndL1Fin hm hs hμs x‖ ≤ (μ s).toReal * ‖x‖ := by rw [L1.norm_eq_integral_norm, ← ENNReal.toReal_ofReal (norm_nonneg x), ← ENNReal.toReal_mul, ← ENNReal.ofReal_le_iff_le_toReal (ENNReal.mul_ne_top hμs ENNReal.ofReal_ne_top), ofReal_integral_norm_eq_lintegral_nnnorm] swap; · rw [← memℒp_one_iff_integrable]; exact Lp.memℒp _ have h_eq : - ∫⁻ a, ‖condexpIndL1Fin hm hs hμs x a‖₊ ∂μ = ∫⁻ a, ‖condexpIndSMul hm hs hμs x a‖₊ ∂μ := by + ∫⁻ a, ‖condExpIndL1Fin hm hs hμs x a‖₊ ∂μ = ∫⁻ a, ‖condExpIndSMul hm hs hμs x a‖₊ ∂μ := by refine lintegral_congr_ae ?_ - refine (condexpIndL1Fin_ae_eq_condexpIndSMul hm hs hμs x).mono fun z hz => ?_ + refine (condExpIndL1Fin_ae_eq_condExpIndSMul hm hs hμs x).mono fun z hz => ?_ dsimp only rw [hz] rw [h_eq, ofReal_norm_eq_coe_nnnorm] - exact lintegral_nnnorm_condexpIndSMul_le hm hs hμs x + exact lintegral_nnnorm_condExpIndSMul_le hm hs hμs x + +@[deprecated (since := "2025-01-21")] alias norm_condexpIndL1Fin_le := norm_condExpIndL1Fin_le -theorem condexpIndL1Fin_disjoint_union (hs : MeasurableSet s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) +theorem condExpIndL1Fin_disjoint_union (hs : MeasurableSet s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) (hμt : μ t ≠ ∞) (hst : Disjoint s t) (x : G) : - condexpIndL1Fin hm (hs.union ht) ((measure_union_le s t).trans_lt + condExpIndL1Fin hm (hs.union ht) ((measure_union_le s t).trans_lt (lt_top_iff_ne_top.mpr (ENNReal.add_ne_top.mpr ⟨hμs, hμt⟩))).ne x = - condexpIndL1Fin hm hs hμs x + condexpIndL1Fin hm ht hμt x := by + condExpIndL1Fin hm hs hμs x + condExpIndL1Fin hm ht hμt x := by ext1 have hμst := measure_union_ne_top hμs hμt - refine (condexpIndL1Fin_ae_eq_condexpIndSMul hm (hs.union ht) hμst x).trans ?_ + refine (condExpIndL1Fin_ae_eq_condExpIndSMul hm (hs.union ht) hμst x).trans ?_ refine EventuallyEq.trans ?_ (Lp.coeFn_add _ _).symm - have hs_eq := condexpIndL1Fin_ae_eq_condexpIndSMul hm hs hμs x - have ht_eq := condexpIndL1Fin_ae_eq_condexpIndSMul hm ht hμt x + have hs_eq := condExpIndL1Fin_ae_eq_condExpIndSMul hm hs hμs x + have ht_eq := condExpIndL1Fin_ae_eq_condExpIndSMul hm ht hμt x refine EventuallyEq.trans ?_ (EventuallyEq.add hs_eq.symm ht_eq.symm) - rw [condexpIndSMul] + rw [condExpIndSMul] rw [indicatorConstLp_disjoint_union hs ht hμs hμt hst (1 : ℝ)] - rw [(condexpL2 ℝ ℝ hm).map_add] + rw [(condExpL2 ℝ ℝ hm).map_add] push_cast rw [((toSpanSingleton ℝ x).compLpL 2 μ).map_add] refine (Lp.coeFn_add _ _).trans ?_ filter_upwards with y using rfl +@[deprecated (since := "2025-01-21")] +alias condexpIndL1Fin_disjoint_union := condExpIndL1Fin_disjoint_union + end CondexpIndL1Fin open scoped Classical @@ -161,171 +177,228 @@ section CondexpIndL1 /-- Conditional expectation of the indicator of a set, as a function in L1. Its value for sets which are not both measurable and of finite measure is not used: we set it to 0. -/ -def condexpIndL1 {m m0 : MeasurableSpace α} (hm : m ≤ m0) (μ : Measure α) (s : Set α) +def condExpIndL1 {m m0 : MeasurableSpace α} (hm : m ≤ m0) (μ : Measure α) (s : Set α) [SigmaFinite (μ.trim hm)] (x : G) : α →₁[μ] G := - if hs : MeasurableSet s ∧ μ s ≠ ∞ then condexpIndL1Fin hm hs.1 hs.2 x else 0 + if hs : MeasurableSet s ∧ μ s ≠ ∞ then condExpIndL1Fin hm hs.1 hs.2 x else 0 + +@[deprecated (since := "2025-01-21")] noncomputable alias condexpIndL1 := condExpIndL1 variable {hm : m ≤ m0} [SigmaFinite (μ.trim hm)] -theorem condexpIndL1_of_measurableSet_of_measure_ne_top (hs : MeasurableSet s) (hμs : μ s ≠ ∞) - (x : G) : condexpIndL1 hm μ s x = condexpIndL1Fin hm hs hμs x := by - simp only [condexpIndL1, And.intro hs hμs, dif_pos, Ne, not_false_iff, and_self_iff] +theorem condExpIndL1_of_measurableSet_of_measure_ne_top (hs : MeasurableSet s) (hμs : μ s ≠ ∞) + (x : G) : condExpIndL1 hm μ s x = condExpIndL1Fin hm hs hμs x := by + simp only [condExpIndL1, And.intro hs hμs, dif_pos, Ne, not_false_iff, and_self_iff] -theorem condexpIndL1_of_measure_eq_top (hμs : μ s = ∞) (x : G) : condexpIndL1 hm μ s x = 0 := by - simp only [condexpIndL1, hμs, eq_self_iff_true, not_true, Ne, dif_neg, not_false_iff, +@[deprecated (since := "2025-01-21")] +alias condexpIndL1_of_measurableSet_of_measure_ne_top := + condExpIndL1_of_measurableSet_of_measure_ne_top + +theorem condExpIndL1_of_measure_eq_top (hμs : μ s = ∞) (x : G) : condExpIndL1 hm μ s x = 0 := by + simp only [condExpIndL1, hμs, eq_self_iff_true, not_true, Ne, dif_neg, not_false_iff, and_false] -theorem condexpIndL1_of_not_measurableSet (hs : ¬MeasurableSet s) (x : G) : - condexpIndL1 hm μ s x = 0 := by - simp only [condexpIndL1, hs, dif_neg, not_false_iff, false_and] +@[deprecated (since := "2025-01-21")] +alias condexpIndL1_of_measure_eq_top := condExpIndL1_of_measure_eq_top + +theorem condExpIndL1_of_not_measurableSet (hs : ¬MeasurableSet s) (x : G) : + condExpIndL1 hm μ s x = 0 := by + simp only [condExpIndL1, hs, dif_neg, not_false_iff, false_and] -theorem condexpIndL1_add (x y : G) : - condexpIndL1 hm μ s (x + y) = condexpIndL1 hm μ s x + condexpIndL1 hm μ s y := by +@[deprecated (since := "2025-01-21")] +alias condexpIndL1_of_not_measurableSet := condExpIndL1_of_not_measurableSet + +theorem condExpIndL1_add (x y : G) : + condExpIndL1 hm μ s (x + y) = condExpIndL1 hm μ s x + condExpIndL1 hm μ s y := by by_cases hs : MeasurableSet s - swap; · simp_rw [condexpIndL1_of_not_measurableSet hs]; rw [zero_add] + swap; · simp_rw [condExpIndL1_of_not_measurableSet hs]; rw [zero_add] by_cases hμs : μ s = ∞ - · simp_rw [condexpIndL1_of_measure_eq_top hμs]; rw [zero_add] - · simp_rw [condexpIndL1_of_measurableSet_of_measure_ne_top hs hμs] - exact condexpIndL1Fin_add hs hμs x y + · simp_rw [condExpIndL1_of_measure_eq_top hμs]; rw [zero_add] + · simp_rw [condExpIndL1_of_measurableSet_of_measure_ne_top hs hμs] + exact condExpIndL1Fin_add hs hμs x y + +@[deprecated (since := "2025-01-21")] alias condexpIndL1_add := condExpIndL1_add -theorem condexpIndL1_smul (c : ℝ) (x : G) : - condexpIndL1 hm μ s (c • x) = c • condexpIndL1 hm μ s x := by +theorem condExpIndL1_smul (c : ℝ) (x : G) : + condExpIndL1 hm μ s (c • x) = c • condExpIndL1 hm μ s x := by by_cases hs : MeasurableSet s - swap; · simp_rw [condexpIndL1_of_not_measurableSet hs]; rw [smul_zero] + swap; · simp_rw [condExpIndL1_of_not_measurableSet hs]; rw [smul_zero] by_cases hμs : μ s = ∞ - · simp_rw [condexpIndL1_of_measure_eq_top hμs]; rw [smul_zero] - · simp_rw [condexpIndL1_of_measurableSet_of_measure_ne_top hs hμs] - exact condexpIndL1Fin_smul hs hμs c x + · simp_rw [condExpIndL1_of_measure_eq_top hμs]; rw [smul_zero] + · simp_rw [condExpIndL1_of_measurableSet_of_measure_ne_top hs hμs] + exact condExpIndL1Fin_smul hs hμs c x -theorem condexpIndL1_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (c : 𝕜) (x : F) : - condexpIndL1 hm μ s (c • x) = c • condexpIndL1 hm μ s x := by +@[deprecated (since := "2025-01-21")] alias condexpIndL1_smul := condExpIndL1_smul + +theorem condExpIndL1_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (c : 𝕜) (x : F) : + condExpIndL1 hm μ s (c • x) = c • condExpIndL1 hm μ s x := by by_cases hs : MeasurableSet s - swap; · simp_rw [condexpIndL1_of_not_measurableSet hs]; rw [smul_zero] + swap; · simp_rw [condExpIndL1_of_not_measurableSet hs]; rw [smul_zero] by_cases hμs : μ s = ∞ - · simp_rw [condexpIndL1_of_measure_eq_top hμs]; rw [smul_zero] - · simp_rw [condexpIndL1_of_measurableSet_of_measure_ne_top hs hμs] - exact condexpIndL1Fin_smul' hs hμs c x + · simp_rw [condExpIndL1_of_measure_eq_top hμs]; rw [smul_zero] + · simp_rw [condExpIndL1_of_measurableSet_of_measure_ne_top hs hμs] + exact condExpIndL1Fin_smul' hs hμs c x + +@[deprecated (since := "2025-01-21")] alias condexpIndL1_smul' := condExpIndL1_smul' -theorem norm_condexpIndL1_le (x : G) : ‖condexpIndL1 hm μ s x‖ ≤ (μ s).toReal * ‖x‖ := by +theorem norm_condExpIndL1_le (x : G) : ‖condExpIndL1 hm μ s x‖ ≤ (μ s).toReal * ‖x‖ := by by_cases hs : MeasurableSet s swap - · simp_rw [condexpIndL1_of_not_measurableSet hs]; rw [Lp.norm_zero] + · simp_rw [condExpIndL1_of_not_measurableSet hs]; rw [Lp.norm_zero] exact mul_nonneg ENNReal.toReal_nonneg (norm_nonneg _) by_cases hμs : μ s = ∞ - · rw [condexpIndL1_of_measure_eq_top hμs x, Lp.norm_zero] + · rw [condExpIndL1_of_measure_eq_top hμs x, Lp.norm_zero] exact mul_nonneg ENNReal.toReal_nonneg (norm_nonneg _) - · rw [condexpIndL1_of_measurableSet_of_measure_ne_top hs hμs x] - exact norm_condexpIndL1Fin_le hs hμs x + · rw [condExpIndL1_of_measurableSet_of_measure_ne_top hs hμs x] + exact norm_condExpIndL1Fin_le hs hμs x + +@[deprecated (since := "2025-01-21")] alias norm_condexpIndL1_le := norm_condExpIndL1_le -theorem continuous_condexpIndL1 : Continuous fun x : G => condexpIndL1 hm μ s x := - continuous_of_linear_of_bound condexpIndL1_add condexpIndL1_smul norm_condexpIndL1_le +theorem continuous_condExpIndL1 : Continuous fun x : G => condExpIndL1 hm μ s x := + continuous_of_linear_of_bound condExpIndL1_add condExpIndL1_smul norm_condExpIndL1_le -theorem condexpIndL1_disjoint_union (hs : MeasurableSet s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) +@[deprecated (since := "2025-01-21")] alias continuous_condexpIndL1 := continuous_condExpIndL1 + +theorem condExpIndL1_disjoint_union (hs : MeasurableSet s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) (hμt : μ t ≠ ∞) (hst : Disjoint s t) (x : G) : - condexpIndL1 hm μ (s ∪ t) x = condexpIndL1 hm μ s x + condexpIndL1 hm μ t x := by + condExpIndL1 hm μ (s ∪ t) x = condExpIndL1 hm μ s x + condExpIndL1 hm μ t x := by have hμst : μ (s ∪ t) ≠ ∞ := ((measure_union_le s t).trans_lt (lt_top_iff_ne_top.mpr (ENNReal.add_ne_top.mpr ⟨hμs, hμt⟩))).ne - rw [condexpIndL1_of_measurableSet_of_measure_ne_top hs hμs x, - condexpIndL1_of_measurableSet_of_measure_ne_top ht hμt x, - condexpIndL1_of_measurableSet_of_measure_ne_top (hs.union ht) hμst x] - exact condexpIndL1Fin_disjoint_union hs ht hμs hμt hst x + rw [condExpIndL1_of_measurableSet_of_measure_ne_top hs hμs x, + condExpIndL1_of_measurableSet_of_measure_ne_top ht hμt x, + condExpIndL1_of_measurableSet_of_measure_ne_top (hs.union ht) hμst x] + exact condExpIndL1Fin_disjoint_union hs ht hμs hμt hst x + +@[deprecated (since := "2025-01-21")] +alias condexpIndL1_disjoint_union := condExpIndL1_disjoint_union end CondexpIndL1 --- Porting note: `G` is not automatically inferred in `condexpInd` in Lean 4; +-- Porting note: `G` is not automatically inferred in `condExpInd` in Lean 4; -- to avoid repeatedly typing `(G := ...)` it is made explicit. variable (G) /-- Conditional expectation of the indicator of a set, as a linear map from `G` to L1. -/ -def condexpInd {m m0 : MeasurableSpace α} (hm : m ≤ m0) (μ : Measure α) [SigmaFinite (μ.trim hm)] +def condExpInd {m m0 : MeasurableSpace α} (hm : m ≤ m0) (μ : Measure α) [SigmaFinite (μ.trim hm)] (s : Set α) : G →L[ℝ] α →₁[μ] G where - toFun := condexpIndL1 hm μ s - map_add' := condexpIndL1_add - map_smul' := condexpIndL1_smul - cont := continuous_condexpIndL1 + toFun := condExpIndL1 hm μ s + map_add' := condExpIndL1_add + map_smul' := condExpIndL1_smul + cont := continuous_condExpIndL1 + +@[deprecated (since := "2025-01-21")] noncomputable alias condexpInd := condExpInd variable {G} -theorem condexpInd_ae_eq_condexpIndSMul (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] +theorem condExpInd_ae_eq_condExpIndSMul (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : - condexpInd G hm μ s x =ᵐ[μ] condexpIndSMul hm hs hμs x := by - refine EventuallyEq.trans ?_ (condexpIndL1Fin_ae_eq_condexpIndSMul hm hs hμs x) - simp [condexpInd, condexpIndL1, hs, hμs] + condExpInd G hm μ s x =ᵐ[μ] condExpIndSMul hm hs hμs x := by + refine EventuallyEq.trans ?_ (condExpIndL1Fin_ae_eq_condExpIndSMul hm hs hμs x) + simp [condExpInd, condExpIndL1, hs, hμs] + +@[deprecated (since := "2025-01-21")] +alias condexpInd_ae_eq_condexpIndSMul := condExpInd_ae_eq_condExpIndSMul variable {hm : m ≤ m0} [SigmaFinite (μ.trim hm)] -theorem aestronglyMeasurable'_condexpInd (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : - AEStronglyMeasurable' m (condexpInd G hm μ s x) μ := - AEStronglyMeasurable'.congr (aeStronglyMeasurable'_condexpIndSMul hm hs hμs x) - (condexpInd_ae_eq_condexpIndSMul hm hs hμs x).symm +theorem aestronglyMeasurable'_condExpInd (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : + AEStronglyMeasurable' m (condExpInd G hm μ s x) μ := + AEStronglyMeasurable'.congr (aeStronglyMeasurable'_condExpIndSMul hm hs hμs x) + (condExpInd_ae_eq_condExpIndSMul hm hs hμs x).symm + +@[deprecated (since := "2025-01-21")] +alias aestronglyMeasurable'_condexpInd := aestronglyMeasurable'_condExpInd @[simp] -theorem condexpInd_empty : condexpInd G hm μ ∅ = (0 : G →L[ℝ] α →₁[μ] G) := by +theorem condExpInd_empty : condExpInd G hm μ ∅ = (0 : G →L[ℝ] α →₁[μ] G) := by ext1 x ext1 - refine (condexpInd_ae_eq_condexpIndSMul hm MeasurableSet.empty (by simp) x).trans ?_ - rw [condexpIndSMul_empty] + refine (condExpInd_ae_eq_condExpIndSMul hm MeasurableSet.empty (by simp) x).trans ?_ + rw [condExpIndSMul_empty] refine (Lp.coeFn_zero G 2 μ).trans ?_ refine EventuallyEq.trans ?_ (Lp.coeFn_zero G 1 μ).symm rfl -theorem condexpInd_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (c : 𝕜) (x : F) : - condexpInd F hm μ s (c • x) = c • condexpInd F hm μ s x := - condexpIndL1_smul' c x +@[deprecated (since := "2025-01-21")] alias condexpInd_empty := condExpInd_empty + +theorem condExpInd_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (c : 𝕜) (x : F) : + condExpInd F hm μ s (c • x) = c • condExpInd F hm μ s x := + condExpIndL1_smul' c x + +@[deprecated (since := "2025-01-21")] alias condexpInd_smul' := condExpInd_smul' -theorem norm_condexpInd_apply_le (x : G) : ‖condexpInd G hm μ s x‖ ≤ (μ s).toReal * ‖x‖ := - norm_condexpIndL1_le x +theorem norm_condExpInd_apply_le (x : G) : ‖condExpInd G hm μ s x‖ ≤ (μ s).toReal * ‖x‖ := + norm_condExpIndL1_le x -theorem norm_condexpInd_le : ‖(condexpInd G hm μ s : G →L[ℝ] α →₁[μ] G)‖ ≤ (μ s).toReal := - ContinuousLinearMap.opNorm_le_bound _ ENNReal.toReal_nonneg norm_condexpInd_apply_le +@[deprecated (since := "2025-01-21")] alias norm_condexpInd_apply_le := norm_condExpInd_apply_le -theorem condexpInd_disjoint_union_apply (hs : MeasurableSet s) (ht : MeasurableSet t) +theorem norm_condExpInd_le : ‖(condExpInd G hm μ s : G →L[ℝ] α →₁[μ] G)‖ ≤ (μ s).toReal := + ContinuousLinearMap.opNorm_le_bound _ ENNReal.toReal_nonneg norm_condExpInd_apply_le + +@[deprecated (since := "2025-01-21")] alias norm_condexpInd_le := norm_condExpInd_le + +theorem condExpInd_disjoint_union_apply (hs : MeasurableSet s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) (hμt : μ t ≠ ∞) (hst : Disjoint s t) (x : G) : - condexpInd G hm μ (s ∪ t) x = condexpInd G hm μ s x + condexpInd G hm μ t x := - condexpIndL1_disjoint_union hs ht hμs hμt hst x + condExpInd G hm μ (s ∪ t) x = condExpInd G hm μ s x + condExpInd G hm μ t x := + condExpIndL1_disjoint_union hs ht hμs hμt hst x + +@[deprecated (since := "2025-01-21")] +alias condexpInd_disjoint_union_apply := condExpInd_disjoint_union_apply + +theorem condExpInd_disjoint_union (hs : MeasurableSet s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) + (hμt : μ t ≠ ∞) (hst : Disjoint s t) : (condExpInd G hm μ (s ∪ t) : G →L[ℝ] α →₁[μ] G) = + condExpInd G hm μ s + condExpInd G hm μ t := by + ext1 x; push_cast; exact condExpInd_disjoint_union_apply hs ht hμs hμt hst x -theorem condexpInd_disjoint_union (hs : MeasurableSet s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) - (hμt : μ t ≠ ∞) (hst : Disjoint s t) : (condexpInd G hm μ (s ∪ t) : G →L[ℝ] α →₁[μ] G) = - condexpInd G hm μ s + condexpInd G hm μ t := by - ext1 x; push_cast; exact condexpInd_disjoint_union_apply hs ht hμs hμt hst x +@[deprecated (since := "2025-01-21")] alias condexpInd_disjoint_union := condExpInd_disjoint_union variable (G) -theorem dominatedFinMeasAdditive_condexpInd (hm : m ≤ m0) (μ : Measure α) +theorem dominatedFinMeasAdditive_condExpInd (hm : m ≤ m0) (μ : Measure α) [SigmaFinite (μ.trim hm)] : - DominatedFinMeasAdditive μ (condexpInd G hm μ : Set α → G →L[ℝ] α →₁[μ] G) 1 := - ⟨fun _ _ => condexpInd_disjoint_union, fun _ _ _ => norm_condexpInd_le.trans (one_mul _).symm.le⟩ + DominatedFinMeasAdditive μ (condExpInd G hm μ : Set α → G →L[ℝ] α →₁[μ] G) 1 := + ⟨fun _ _ => condExpInd_disjoint_union, fun _ _ _ => norm_condExpInd_le.trans (one_mul _).symm.le⟩ + +@[deprecated (since := "2025-01-21")] +alias dominatedFinMeasAdditive_condexpInd := dominatedFinMeasAdditive_condExpInd variable {G} -theorem setIntegral_condexpInd (hs : MeasurableSet[m] s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) - (hμt : μ t ≠ ∞) (x : G') : ∫ a in s, condexpInd G' hm μ t x a ∂μ = (μ (t ∩ s)).toReal • x := +theorem setIntegral_condExpInd (hs : MeasurableSet[m] s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) + (hμt : μ t ≠ ∞) (x : G') : ∫ a in s, condExpInd G' hm μ t x a ∂μ = (μ (t ∩ s)).toReal • x := calc - ∫ a in s, condexpInd G' hm μ t x a ∂μ = ∫ a in s, condexpIndSMul hm ht hμt x a ∂μ := + ∫ a in s, condExpInd G' hm μ t x a ∂μ = ∫ a in s, condExpIndSMul hm ht hμt x a ∂μ := setIntegral_congr_ae (hm s hs) - ((condexpInd_ae_eq_condexpIndSMul hm ht hμt x).mono fun _ hx _ => hx) - _ = (μ (t ∩ s)).toReal • x := setIntegral_condexpIndSMul hs ht hμs hμt x + ((condExpInd_ae_eq_condExpIndSMul hm ht hμt x).mono fun _ hx _ => hx) + _ = (μ (t ∩ s)).toReal • x := setIntegral_condExpIndSMul hs ht hμs hμt x + +@[deprecated (since := "2025-01-21")] alias setIntegral_condexpInd := setIntegral_condExpInd @[deprecated (since := "2024-04-17")] -alias set_integral_condexpInd := setIntegral_condexpInd +alias set_integral_condExpInd := setIntegral_condExpInd + +@[deprecated (since := "2025-01-21")] alias set_integral_condexpInd := set_integral_condExpInd -theorem condexpInd_of_measurable (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) (c : G) : - condexpInd G hm μ s c = indicatorConstLp 1 (hm s hs) hμs c := by +theorem condExpInd_of_measurable (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) (c : G) : + condExpInd G hm μ s c = indicatorConstLp 1 (hm s hs) hμs c := by ext1 refine EventuallyEq.trans ?_ indicatorConstLp_coeFn.symm - refine (condexpInd_ae_eq_condexpIndSMul hm (hm s hs) hμs c).trans ?_ - refine (condexpIndSMul_ae_eq_smul hm (hm s hs) hμs c).trans ?_ - rw [lpMeas_coe, condexpL2_indicator_of_measurable hm hs hμs (1 : ℝ)] + refine (condExpInd_ae_eq_condExpIndSMul hm (hm s hs) hμs c).trans ?_ + refine (condExpIndSMul_ae_eq_smul hm (hm s hs) hμs c).trans ?_ + rw [lpMeas_coe, condExpL2_indicator_of_measurable hm hs hμs (1 : ℝ)] refine (@indicatorConstLp_coeFn α _ _ 2 μ _ s (hm s hs) hμs (1 : ℝ)).mono fun x hx => ?_ dsimp only rw [hx] by_cases hx_mem : x ∈ s <;> simp [hx_mem] -theorem condexpInd_nonneg {E} [NormedLatticeAddCommGroup E] [NormedSpace ℝ E] [OrderedSMul ℝ E] - (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E) (hx : 0 ≤ x) : 0 ≤ condexpInd E hm μ s x := by +@[deprecated (since := "2025-01-21")] alias condexpInd_of_measurable := condExpInd_of_measurable + +theorem condExpInd_nonneg {E} [NormedLatticeAddCommGroup E] [NormedSpace ℝ E] [OrderedSMul ℝ E] + (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E) (hx : 0 ≤ x) : 0 ≤ condExpInd E hm μ s x := by rw [← coeFn_le] - refine EventuallyLE.trans_eq ?_ (condexpInd_ae_eq_condexpIndSMul hm hs hμs x).symm - exact (coeFn_zero E 1 μ).trans_le (condexpIndSMul_nonneg hs hμs x hx) + refine EventuallyLE.trans_eq ?_ (condExpInd_ae_eq_condExpIndSMul hm hs hμs x).symm + exact (coeFn_zero E 1 μ).trans_le (condExpIndSMul_nonneg hs hμs x hx) + +@[deprecated (since := "2025-01-21")] alias condexpInd_nonneg := condExpInd_nonneg end CondexpInd @@ -335,62 +408,78 @@ section CondexpL1 variable {m m0 : MeasurableSpace α} {μ : Measure α} {hm : m ≤ m0} [SigmaFinite (μ.trim hm)] {f g : α → F'} {s : Set α} --- Porting note: `F'` is not automatically inferred in `condexpL1CLM` in Lean 4; +-- Porting note: `F'` is not automatically inferred in `condExpL1CLM` in Lean 4; -- to avoid repeatedly typing `(F' := ...)` it is made explicit. variable (F') /-- Conditional expectation of a function as a linear map from `α →₁[μ] F'` to itself. -/ -def condexpL1CLM (hm : m ≤ m0) (μ : Measure α) [SigmaFinite (μ.trim hm)] : +def condExpL1CLM (hm : m ≤ m0) (μ : Measure α) [SigmaFinite (μ.trim hm)] : (α →₁[μ] F') →L[ℝ] α →₁[μ] F' := - L1.setToL1 (dominatedFinMeasAdditive_condexpInd F' hm μ) + L1.setToL1 (dominatedFinMeasAdditive_condExpInd F' hm μ) + +@[deprecated (since := "2025-01-21")] noncomputable alias condexpL1CLM := condExpL1CLM variable {F'} -theorem condexpL1CLM_smul (c : 𝕜) (f : α →₁[μ] F') : - condexpL1CLM F' hm μ (c • f) = c • condexpL1CLM F' hm μ f := by - refine L1.setToL1_smul (dominatedFinMeasAdditive_condexpInd F' hm μ) ?_ c f - exact fun c s x => condexpInd_smul' c x +theorem condExpL1CLM_smul (c : 𝕜) (f : α →₁[μ] F') : + condExpL1CLM F' hm μ (c • f) = c • condExpL1CLM F' hm μ f := by + refine L1.setToL1_smul (dominatedFinMeasAdditive_condExpInd F' hm μ) ?_ c f + exact fun c s x => condExpInd_smul' c x + +@[deprecated (since := "2025-01-21")] alias condexpL1CLM_smul := condExpL1CLM_smul -theorem condexpL1CLM_indicatorConstLp (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : F') : - (condexpL1CLM F' hm μ) (indicatorConstLp 1 hs hμs x) = condexpInd F' hm μ s x := - L1.setToL1_indicatorConstLp (dominatedFinMeasAdditive_condexpInd F' hm μ) hs hμs x +theorem condExpL1CLM_indicatorConstLp (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : F') : + (condExpL1CLM F' hm μ) (indicatorConstLp 1 hs hμs x) = condExpInd F' hm μ s x := + L1.setToL1_indicatorConstLp (dominatedFinMeasAdditive_condExpInd F' hm μ) hs hμs x -theorem condexpL1CLM_indicatorConst (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : F') : - (condexpL1CLM F' hm μ) ↑(simpleFunc.indicatorConst 1 hs hμs x) = condexpInd F' hm μ s x := by - rw [Lp.simpleFunc.coe_indicatorConst]; exact condexpL1CLM_indicatorConstLp hs hμs x +@[deprecated (since := "2025-01-21")] +alias condexpL1CLM_indicatorConstLp := condExpL1CLM_indicatorConstLp -/-- Auxiliary lemma used in the proof of `setIntegral_condexpL1CLM`. -/ -theorem setIntegral_condexpL1CLM_of_measure_ne_top (f : α →₁[μ] F') (hs : MeasurableSet[m] s) - (hμs : μ s ≠ ∞) : ∫ x in s, condexpL1CLM F' hm μ f x ∂μ = ∫ x in s, f x ∂μ := by +theorem condExpL1CLM_indicatorConst (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : F') : + (condExpL1CLM F' hm μ) ↑(simpleFunc.indicatorConst 1 hs hμs x) = condExpInd F' hm μ s x := by + rw [Lp.simpleFunc.coe_indicatorConst]; exact condExpL1CLM_indicatorConstLp hs hμs x + +@[deprecated (since := "2025-01-21")] +alias condexpL1CLM_indicatorConst := condExpL1CLM_indicatorConst + +/-- Auxiliary lemma used in the proof of `setIntegral_condExpL1CLM`. -/ +theorem setIntegral_condExpL1CLM_of_measure_ne_top (f : α →₁[μ] F') (hs : MeasurableSet[m] s) + (hμs : μ s ≠ ∞) : ∫ x in s, condExpL1CLM F' hm μ f x ∂μ = ∫ x in s, f x ∂μ := by refine @Lp.induction _ _ _ _ _ _ _ ENNReal.one_ne_top - (fun f : α →₁[μ] F' => ∫ x in s, condexpL1CLM F' hm μ f x ∂μ = ∫ x in s, f x ∂μ) ?_ ?_ + (fun f : α →₁[μ] F' => ∫ x in s, condExpL1CLM F' hm μ f x ∂μ = ∫ x in s, f x ∂μ) ?_ ?_ (isClosed_eq ?_ ?_) f · intro x t ht hμt - simp_rw [condexpL1CLM_indicatorConst ht hμt.ne x] + simp_rw [condExpL1CLM_indicatorConst ht hμt.ne x] rw [Lp.simpleFunc.coe_indicatorConst, setIntegral_indicatorConstLp (hm _ hs)] - exact setIntegral_condexpInd hs ht hμs hμt.ne x + exact setIntegral_condExpInd hs ht hμs hμt.ne x · intro f g hf_Lp hg_Lp _ hf hg - simp_rw [(condexpL1CLM F' hm μ).map_add] - rw [setIntegral_congr_ae (hm s hs) ((Lp.coeFn_add (condexpL1CLM F' hm μ (hf_Lp.toLp f)) - (condexpL1CLM F' hm μ (hg_Lp.toLp g))).mono fun x hx _ => hx)] + simp_rw [(condExpL1CLM F' hm μ).map_add] + rw [setIntegral_congr_ae (hm s hs) ((Lp.coeFn_add (condExpL1CLM F' hm μ (hf_Lp.toLp f)) + (condExpL1CLM F' hm μ (hg_Lp.toLp g))).mono fun x hx _ => hx)] rw [setIntegral_congr_ae (hm s hs) ((Lp.coeFn_add (hf_Lp.toLp f) (hg_Lp.toLp g)).mono fun x hx _ => hx)] simp_rw [Pi.add_apply] rw [integral_add (L1.integrable_coeFn _).integrableOn (L1.integrable_coeFn _).integrableOn, integral_add (L1.integrable_coeFn _).integrableOn (L1.integrable_coeFn _).integrableOn, hf, hg] - · exact (continuous_setIntegral s).comp (condexpL1CLM F' hm μ).continuous + · exact (continuous_setIntegral s).comp (condExpL1CLM F' hm μ).continuous · exact continuous_setIntegral s +@[deprecated (since := "2025-01-21")] +alias setIntegral_condexpL1CLM_of_measure_ne_top := setIntegral_condExpL1CLM_of_measure_ne_top + @[deprecated (since := "2024-04-17")] alias set_integral_condexpL1CLM_of_measure_ne_top := - setIntegral_condexpL1CLM_of_measure_ne_top + setIntegral_condExpL1CLM_of_measure_ne_top -/-- The integral of the conditional expectation `condexpL1CLM` over an `m`-measurable set is equal -to the integral of `f` on that set. See also `setIntegral_condexp`, the similar statement for -`condexp`. -/ -theorem setIntegral_condexpL1CLM (f : α →₁[μ] F') (hs : MeasurableSet[m] s) : - ∫ x in s, condexpL1CLM F' hm μ f x ∂μ = ∫ x in s, f x ∂μ := by +@[deprecated (since := "2025-01-21")] +alias setIntegral_condexpL1CLM := set_integral_condexpL1CLM_of_measure_ne_top + +/-- The integral of the conditional expectation `condExpL1CLM` over an `m`-measurable set is equal +to the integral of `f` on that set. See also `setIntegral_condExp`, the similar statement for +`condExp`. -/ +theorem setIntegral_condExpL1CLM (f : α →₁[μ] F') (hs : MeasurableSet[m] s) : + ∫ x in s, condExpL1CLM F' hm μ f x ∂μ = ∫ x in s, f x ∂μ := by let S := spanningSets (μ.trim hm) have hS_meas : ∀ i, MeasurableSet[m] (S i) := measurableSet_spanningSets (μ.trim hm) have hS_meas0 : ∀ i, MeasurableSet (S i) := fun i => hm _ (hS_meas i) @@ -406,146 +495,190 @@ theorem setIntegral_condexpL1CLM (f : α →₁[μ] F') (hs : MeasurableSet[m] s simp_rw [Set.mem_inter_iff] exact fun h => ⟨monotone_spanningSets (μ.trim hm) hij h.1, h.2⟩ have h_eq_forall : - (fun i => ∫ x in S i ∩ s, condexpL1CLM F' hm μ f x ∂μ) = fun i => ∫ x in S i ∩ s, f x ∂μ := + (fun i => ∫ x in S i ∩ s, condExpL1CLM F' hm μ f x ∂μ) = fun i => ∫ x in S i ∩ s, f x ∂μ := funext fun i => - setIntegral_condexpL1CLM_of_measure_ne_top f (@MeasurableSet.inter α m _ _ (hS_meas i) hs) + setIntegral_condExpL1CLM_of_measure_ne_top f (@MeasurableSet.inter α m _ _ (hS_meas i) hs) (hS_finite i).ne have h_right : Tendsto (fun i => ∫ x in S i ∩ s, f x ∂μ) atTop (𝓝 (∫ x in s, f x ∂μ)) := by have h := tendsto_setIntegral_of_monotone (fun i => (hS_meas0 i).inter (hm s hs)) h_mono (L1.integrable_coeFn f).integrableOn rwa [← hs_eq] at h - have h_left : Tendsto (fun i => ∫ x in S i ∩ s, condexpL1CLM F' hm μ f x ∂μ) atTop - (𝓝 (∫ x in s, condexpL1CLM F' hm μ f x ∂μ)) := by + have h_left : Tendsto (fun i => ∫ x in S i ∩ s, condExpL1CLM F' hm μ f x ∂μ) atTop + (𝓝 (∫ x in s, condExpL1CLM F' hm μ f x ∂μ)) := by have h := tendsto_setIntegral_of_monotone (fun i => (hS_meas0 i).inter (hm s hs)) h_mono - (L1.integrable_coeFn (condexpL1CLM F' hm μ f)).integrableOn + (L1.integrable_coeFn (condExpL1CLM F' hm μ f)).integrableOn rwa [← hs_eq] at h rw [h_eq_forall] at h_left exact tendsto_nhds_unique h_left h_right @[deprecated (since := "2024-04-17")] -alias set_integral_condexpL1CLM := setIntegral_condexpL1CLM +alias set_integral_condExpL1CLM := setIntegral_condExpL1CLM + +@[deprecated (since := "2025-01-21")] alias set_integral_condexpL1CLM := set_integral_condExpL1CLM -theorem aestronglyMeasurable'_condexpL1CLM (f : α →₁[μ] F') : - AEStronglyMeasurable' m (condexpL1CLM F' hm μ f) μ := by +theorem aestronglyMeasurable'_condExpL1CLM (f : α →₁[μ] F') : + AEStronglyMeasurable' m (condExpL1CLM F' hm μ f) μ := by refine @Lp.induction _ _ _ _ _ _ _ ENNReal.one_ne_top - (fun f : α →₁[μ] F' => AEStronglyMeasurable' m (condexpL1CLM F' hm μ f) μ) ?_ ?_ ?_ f + (fun f : α →₁[μ] F' => AEStronglyMeasurable' m (condExpL1CLM F' hm μ f) μ) ?_ ?_ ?_ f · intro c s hs hμs - rw [condexpL1CLM_indicatorConst hs hμs.ne c] - exact aestronglyMeasurable'_condexpInd hs hμs.ne c + rw [condExpL1CLM_indicatorConst hs hμs.ne c] + exact aestronglyMeasurable'_condExpInd hs hμs.ne c · intro f g hf hg _ hfm hgm - rw [(condexpL1CLM F' hm μ).map_add] + rw [(condExpL1CLM F' hm μ).map_add] refine AEStronglyMeasurable'.congr ?_ (coeFn_add _ _).symm exact AEStronglyMeasurable'.add hfm hgm - · have : {f : Lp F' 1 μ | AEStronglyMeasurable' m (condexpL1CLM F' hm μ f) μ} = - condexpL1CLM F' hm μ ⁻¹' {f | AEStronglyMeasurable' m f μ} := rfl + · have : {f : Lp F' 1 μ | AEStronglyMeasurable' m (condExpL1CLM F' hm μ f) μ} = + condExpL1CLM F' hm μ ⁻¹' {f | AEStronglyMeasurable' m f μ} := rfl rw [this] - refine IsClosed.preimage (condexpL1CLM F' hm μ).continuous ?_ + refine IsClosed.preimage (condExpL1CLM F' hm μ).continuous ?_ exact isClosed_aeStronglyMeasurable' hm -theorem condexpL1CLM_lpMeas (f : lpMeas F' ℝ m 1 μ) : - condexpL1CLM F' hm μ (f : α →₁[μ] F') = ↑f := by +@[deprecated (since := "2025-01-21")] +alias aestronglyMeasurable'_condexpL1CLM := aestronglyMeasurable'_condExpL1CLM + +theorem condExpL1CLM_lpMeas (f : lpMeas F' ℝ m 1 μ) : + condExpL1CLM F' hm μ (f : α →₁[μ] F') = ↑f := by let g := lpMeasToLpTrimLie F' ℝ 1 μ hm f have hfg : f = (lpMeasToLpTrimLie F' ℝ 1 μ hm).symm g := by simp only [g, LinearIsometryEquiv.symm_apply_apply] rw [hfg] refine @Lp.induction α F' m _ 1 (μ.trim hm) _ ENNReal.coe_ne_top (fun g : α →₁[μ.trim hm] F' => - condexpL1CLM F' hm μ ((lpMeasToLpTrimLie F' ℝ 1 μ hm).symm g : α →₁[μ] F') = + condExpL1CLM F' hm μ ((lpMeasToLpTrimLie F' ℝ 1 μ hm).symm g : α →₁[μ] F') = ↑((lpMeasToLpTrimLie F' ℝ 1 μ hm).symm g)) ?_ ?_ ?_ g · intro c s hs hμs rw [@Lp.simpleFunc.coe_indicatorConst _ _ m, lpMeasToLpTrimLie_symm_indicator hs hμs.ne c, - condexpL1CLM_indicatorConstLp] - exact condexpInd_of_measurable hs ((le_trim hm).trans_lt hμs).ne c + condExpL1CLM_indicatorConstLp] + exact condExpInd_of_measurable hs ((le_trim hm).trans_lt hμs).ne c · intro f g hf hg _ hf_eq hg_eq rw [LinearIsometryEquiv.map_add] push_cast rw [map_add, hf_eq, hg_eq] · refine isClosed_eq ?_ ?_ - · refine (condexpL1CLM F' hm μ).continuous.comp (continuous_induced_dom.comp ?_) + · refine (condExpL1CLM F' hm μ).continuous.comp (continuous_induced_dom.comp ?_) exact LinearIsometryEquiv.continuous _ · refine continuous_induced_dom.comp ?_ exact LinearIsometryEquiv.continuous _ -theorem condexpL1CLM_of_aestronglyMeasurable' (f : α →₁[μ] F') (hfm : AEStronglyMeasurable' m f μ) : - condexpL1CLM F' hm μ f = f := - condexpL1CLM_lpMeas (⟨f, hfm⟩ : lpMeas F' ℝ m 1 μ) +@[deprecated (since := "2025-01-21")] alias condexpL1CLM_lpMeas := condExpL1CLM_lpMeas + +theorem condExpL1CLM_of_aestronglyMeasurable' (f : α →₁[μ] F') (hfm : AEStronglyMeasurable' m f μ) : + condExpL1CLM F' hm μ f = f := + condExpL1CLM_lpMeas (⟨f, hfm⟩ : lpMeas F' ℝ m 1 μ) + +@[deprecated (since := "2025-01-21")] +alias condexpL1CLM_of_aestronglyMeasurable' := condExpL1CLM_of_aestronglyMeasurable' /-- Conditional expectation of a function, in L1. Its value is 0 if the function is not -integrable. The function-valued `condexp` should be used instead in most cases. -/ -def condexpL1 (hm : m ≤ m0) (μ : Measure α) [SigmaFinite (μ.trim hm)] (f : α → F') : α →₁[μ] F' := - setToFun μ (condexpInd F' hm μ) (dominatedFinMeasAdditive_condexpInd F' hm μ) f +integrable. The function-valued `condExp` should be used instead in most cases. -/ +def condExpL1 (hm : m ≤ m0) (μ : Measure α) [SigmaFinite (μ.trim hm)] (f : α → F') : α →₁[μ] F' := + setToFun μ (condExpInd F' hm μ) (dominatedFinMeasAdditive_condExpInd F' hm μ) f + +@[deprecated (since := "2025-01-21")] noncomputable alias condexpL1 := condExpL1 + +theorem condExpL1_undef (hf : ¬Integrable f μ) : condExpL1 hm μ f = 0 := + setToFun_undef (dominatedFinMeasAdditive_condExpInd F' hm μ) hf -theorem condexpL1_undef (hf : ¬Integrable f μ) : condexpL1 hm μ f = 0 := - setToFun_undef (dominatedFinMeasAdditive_condexpInd F' hm μ) hf +@[deprecated (since := "2025-01-21")] alias condexpL1_undef := condExpL1_undef -theorem condexpL1_eq (hf : Integrable f μ) : condexpL1 hm μ f = condexpL1CLM F' hm μ (hf.toL1 f) := - setToFun_eq (dominatedFinMeasAdditive_condexpInd F' hm μ) hf +theorem condExpL1_eq (hf : Integrable f μ) : condExpL1 hm μ f = condExpL1CLM F' hm μ (hf.toL1 f) := + setToFun_eq (dominatedFinMeasAdditive_condExpInd F' hm μ) hf + +@[deprecated (since := "2025-01-21")] alias condexpL1_eq := condExpL1_eq @[simp] -theorem condexpL1_zero : condexpL1 hm μ (0 : α → F') = 0 := +theorem condExpL1_zero : condExpL1 hm μ (0 : α → F') = 0 := setToFun_zero _ +@[deprecated (since := "2025-01-21")] alias condexpL1_zero := condExpL1_zero + @[simp] -theorem condexpL1_measure_zero (hm : m ≤ m0) : condexpL1 hm (0 : Measure α) f = 0 := +theorem condExpL1_measure_zero (hm : m ≤ m0) : condExpL1 hm (0 : Measure α) f = 0 := setToFun_measure_zero _ rfl -theorem aestronglyMeasurable'_condexpL1 {f : α → F'} : - AEStronglyMeasurable' m (condexpL1 hm μ f) μ := by +@[deprecated (since := "2025-01-21")] alias condexpL1_measure_zero := condExpL1_measure_zero + +theorem aestronglyMeasurable'_condExpL1 {f : α → F'} : + AEStronglyMeasurable' m (condExpL1 hm μ f) μ := by by_cases hf : Integrable f μ - · rw [condexpL1_eq hf] - exact aestronglyMeasurable'_condexpL1CLM _ - · rw [condexpL1_undef hf] + · rw [condExpL1_eq hf] + exact aestronglyMeasurable'_condExpL1CLM _ + · rw [condExpL1_undef hf] refine AEStronglyMeasurable'.congr ?_ (coeFn_zero _ _ _).symm exact StronglyMeasurable.aeStronglyMeasurable' (@stronglyMeasurable_zero _ _ m _ _) -theorem condexpL1_congr_ae (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (h : f =ᵐ[μ] g) : - condexpL1 hm μ f = condexpL1 hm μ g := +@[deprecated (since := "2025-01-21")] +alias aestronglyMeasurable'_condexpL1 := aestronglyMeasurable'_condExpL1 + +theorem condExpL1_congr_ae (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (h : f =ᵐ[μ] g) : + condExpL1 hm μ f = condExpL1 hm μ g := setToFun_congr_ae _ h -theorem integrable_condexpL1 (f : α → F') : Integrable (condexpL1 hm μ f) μ := +@[deprecated (since := "2025-01-21")] alias condexpL1_congr_ae := condExpL1_congr_ae + +theorem integrable_condExpL1 (f : α → F') : Integrable (condExpL1 hm μ f) μ := L1.integrable_coeFn _ -/-- The integral of the conditional expectation `condexpL1` over an `m`-measurable set is equal to -the integral of `f` on that set. See also `setIntegral_condexp`, the similar statement for -`condexp`. -/ -theorem setIntegral_condexpL1 (hf : Integrable f μ) (hs : MeasurableSet[m] s) : - ∫ x in s, condexpL1 hm μ f x ∂μ = ∫ x in s, f x ∂μ := by - simp_rw [condexpL1_eq hf] - rw [setIntegral_condexpL1CLM (hf.toL1 f) hs] +@[deprecated (since := "2025-01-21")] alias integrable_condexpL1 := integrable_condExpL1 + +/-- The integral of the conditional expectation `condExpL1` over an `m`-measurable set is equal to +the integral of `f` on that set. See also `setIntegral_condExp`, the similar statement for +`condExp`. -/ +theorem setIntegral_condExpL1 (hf : Integrable f μ) (hs : MeasurableSet[m] s) : + ∫ x in s, condExpL1 hm μ f x ∂μ = ∫ x in s, f x ∂μ := by + simp_rw [condExpL1_eq hf] + rw [setIntegral_condExpL1CLM (hf.toL1 f) hs] exact setIntegral_congr_ae (hm s hs) (hf.coeFn_toL1.mono fun x hx _ => hx) +@[deprecated (since := "2025-01-21")] alias setIntegral_condexpL1 := setIntegral_condExpL1 + @[deprecated (since := "2024-04-17")] -alias set_integral_condexpL1 := setIntegral_condexpL1 +alias set_integral_condExpL1 := setIntegral_condExpL1 -theorem condexpL1_add (hf : Integrable f μ) (hg : Integrable g μ) : - condexpL1 hm μ (f + g) = condexpL1 hm μ f + condexpL1 hm μ g := +@[deprecated (since := "2025-01-21")] alias set_integral_condexpL1 := set_integral_condExpL1 + +theorem condExpL1_add (hf : Integrable f μ) (hg : Integrable g μ) : + condExpL1 hm μ (f + g) = condExpL1 hm μ f + condExpL1 hm μ g := setToFun_add _ hf hg -theorem condexpL1_neg (f : α → F') : condexpL1 hm μ (-f) = -condexpL1 hm μ f := +@[deprecated (since := "2025-01-21")] alias condexpL1_add := condExpL1_add + +theorem condExpL1_neg (f : α → F') : condExpL1 hm μ (-f) = -condExpL1 hm μ f := setToFun_neg _ f -theorem condexpL1_smul (c : 𝕜) (f : α → F') : condexpL1 hm μ (c • f) = c • condexpL1 hm μ f := by +@[deprecated (since := "2025-01-21")] alias condexpL1_neg := condExpL1_neg + +theorem condExpL1_smul (c : 𝕜) (f : α → F') : condExpL1 hm μ (c • f) = c • condExpL1 hm μ f := by refine setToFun_smul _ ?_ c f - exact fun c _ x => condexpInd_smul' c x + exact fun c _ x => condExpInd_smul' c x + +@[deprecated (since := "2025-01-21")] alias condexpL1_smul := condExpL1_smul -theorem condexpL1_sub (hf : Integrable f μ) (hg : Integrable g μ) : - condexpL1 hm μ (f - g) = condexpL1 hm μ f - condexpL1 hm μ g := +theorem condExpL1_sub (hf : Integrable f μ) (hg : Integrable g μ) : + condExpL1 hm μ (f - g) = condExpL1 hm μ f - condExpL1 hm μ g := setToFun_sub _ hf hg -theorem condexpL1_of_aestronglyMeasurable' (hfm : AEStronglyMeasurable' m f μ) - (hfi : Integrable f μ) : condexpL1 hm μ f =ᵐ[μ] f := by - rw [condexpL1_eq hfi] +@[deprecated (since := "2025-01-21")] alias condexpL1_sub := condExpL1_sub + +theorem condExpL1_of_aestronglyMeasurable' (hfm : AEStronglyMeasurable' m f μ) + (hfi : Integrable f μ) : condExpL1 hm μ f =ᵐ[μ] f := by + rw [condExpL1_eq hfi] refine EventuallyEq.trans ?_ (Integrable.coeFn_toL1 hfi) - rw [condexpL1CLM_of_aestronglyMeasurable'] + rw [condExpL1CLM_of_aestronglyMeasurable'] exact AEStronglyMeasurable'.congr hfm (Integrable.coeFn_toL1 hfi).symm -theorem condexpL1_mono {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] +@[deprecated (since := "2025-01-21")] +alias condexpL1_of_aestronglyMeasurable' := condExpL1_of_aestronglyMeasurable' + +theorem condExpL1_mono {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] [OrderedSMul ℝ E] {f g : α → E} (hf : Integrable f μ) (hg : Integrable g μ) (hfg : f ≤ᵐ[μ] g) : - condexpL1 hm μ f ≤ᵐ[μ] condexpL1 hm μ g := by + condExpL1 hm μ f ≤ᵐ[μ] condExpL1 hm μ g := by rw [coeFn_le] - have h_nonneg : ∀ s, MeasurableSet s → μ s < ∞ → ∀ x : E, 0 ≤ x → 0 ≤ condexpInd E hm μ s x := - fun s hs hμs x hx => condexpInd_nonneg hs hμs.ne x hx - exact setToFun_mono (dominatedFinMeasAdditive_condexpInd E hm μ) h_nonneg hf hg hfg + have h_nonneg : ∀ s, MeasurableSet s → μ s < ∞ → ∀ x : E, 0 ≤ x → 0 ≤ condExpInd E hm μ s x := + fun s hs hμs x hx => condExpInd_nonneg hs hμs.ne x hx + exact setToFun_mono (dominatedFinMeasAdditive_condExpInd E hm μ) h_nonneg hf hg hfg + +@[deprecated (since := "2025-01-21")] alias condexpL1_mono := condExpL1_mono end CondexpL1 diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean index 77abe61e2911f..af886f9759cdb 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean @@ -18,14 +18,14 @@ orthogonal projection on the subspace of almost everywhere `m`-measurable functi ## Main definitions -* `condexpL2`: Conditional expectation of a function in L2 with respect to a sigma-algebra: it is +* `condExpL2`: Conditional expectation of a function in L2 with respect to a sigma-algebra: it is the orthogonal projection on the subspace `lpMeas`. ## Implementation notes Most of the results in this file are valid for a complete real normed space `F`. However, some lemmas also use `𝕜 : RCLike`: -* `condexpL2` is defined only for an `InnerProductSpace` for now, and we use `𝕜` for its field. +* `condExpL2` is defined only for an `InnerProductSpace` for now, and we use `𝕜` for its field. * results about scalar multiplication are stated not only for `ℝ` but also for `𝕜` if we happen to have `NormedSpace 𝕜 F`. @@ -61,63 +61,87 @@ local notation "⟪" x ", " y "⟫" => @inner 𝕜 E _ x y local notation "⟪" x ", " y "⟫₂" => @inner 𝕜 (α →₂[μ] E) _ x y --- Porting note: the argument `E` of `condexpL2` is not automatically filled in Lean 4. +-- Porting note: the argument `E` of `condExpL2` is not automatically filled in Lean 4. -- To avoid typing `(E := _)` every time it is made explicit. variable (E 𝕜) /-- Conditional expectation of a function in L2 with respect to a sigma-algebra -/ -noncomputable def condexpL2 (hm : m ≤ m0) : (α →₂[μ] E) →L[𝕜] lpMeas E 𝕜 m 2 μ := +noncomputable def condExpL2 (hm : m ≤ m0) : (α →₂[μ] E) →L[𝕜] lpMeas E 𝕜 m 2 μ := @orthogonalProjection 𝕜 (α →₂[μ] E) _ _ _ (lpMeas E 𝕜 m 2 μ) haveI : Fact (m ≤ m0) := ⟨hm⟩ inferInstance +@[deprecated (since := "2025-01-21")] alias condexpL2 := condExpL2 + variable {E 𝕜} -theorem aeStronglyMeasurable'_condexpL2 (hm : m ≤ m0) (f : α →₂[μ] E) : - AEStronglyMeasurable' (β := E) m (condexpL2 E 𝕜 hm f) μ := +theorem aeStronglyMeasurable'_condExpL2 (hm : m ≤ m0) (f : α →₂[μ] E) : + AEStronglyMeasurable' (β := E) m (condExpL2 E 𝕜 hm f) μ := lpMeas.aeStronglyMeasurable' _ -theorem integrableOn_condexpL2_of_measure_ne_top (hm : m ≤ m0) (hμs : μ s ≠ ∞) (f : α →₂[μ] E) : - IntegrableOn (ε := E) (condexpL2 E 𝕜 hm f) s μ := - integrableOn_Lp_of_measure_ne_top (condexpL2 E 𝕜 hm f : α →₂[μ] E) fact_one_le_two_ennreal.elim +@[deprecated (since := "2025-01-21")] +alias aeStronglyMeasurable'_condexpL2 := aeStronglyMeasurable'_condExpL2 + +theorem integrableOn_condExpL2_of_measure_ne_top (hm : m ≤ m0) (hμs : μ s ≠ ∞) (f : α →₂[μ] E) : + IntegrableOn (ε := E) (condExpL2 E 𝕜 hm f) s μ := + integrableOn_Lp_of_measure_ne_top (condExpL2 E 𝕜 hm f : α →₂[μ] E) fact_one_le_two_ennreal.elim hμs -theorem integrable_condexpL2_of_isFiniteMeasure (hm : m ≤ m0) [IsFiniteMeasure μ] {f : α →₂[μ] E} : - Integrable (ε := E) (condexpL2 E 𝕜 hm f) μ := - integrableOn_univ.mp <| integrableOn_condexpL2_of_measure_ne_top hm (measure_ne_top _ _) f +@[deprecated (since := "2025-01-21")] +alias integrableOn_condexpL2_of_measure_ne_top := integrableOn_condExpL2_of_measure_ne_top + +theorem integrable_condExpL2_of_isFiniteMeasure (hm : m ≤ m0) [IsFiniteMeasure μ] {f : α →₂[μ] E} : + Integrable (ε := E) (condExpL2 E 𝕜 hm f) μ := + integrableOn_univ.mp <| integrableOn_condExpL2_of_measure_ne_top hm (measure_ne_top _ _) f -theorem norm_condexpL2_le_one (hm : m ≤ m0) : ‖@condexpL2 α E 𝕜 _ _ _ _ _ _ μ hm‖ ≤ 1 := +@[deprecated (since := "2025-01-21")] +alias integrable_condexpL2_of_isFiniteMeasure := integrable_condExpL2_of_isFiniteMeasure + +theorem norm_condExpL2_le_one (hm : m ≤ m0) : ‖@condExpL2 α E 𝕜 _ _ _ _ _ _ μ hm‖ ≤ 1 := haveI : Fact (m ≤ m0) := ⟨hm⟩ orthogonalProjection_norm_le _ -theorem norm_condexpL2_le (hm : m ≤ m0) (f : α →₂[μ] E) : ‖condexpL2 E 𝕜 hm f‖ ≤ ‖f‖ := - ((@condexpL2 _ E 𝕜 _ _ _ _ _ _ μ hm).le_opNorm f).trans - (mul_le_of_le_one_left (norm_nonneg _) (norm_condexpL2_le_one hm)) +@[deprecated (since := "2025-01-21")] alias norm_condexpL2_le_one := norm_condExpL2_le_one + +theorem norm_condExpL2_le (hm : m ≤ m0) (f : α →₂[μ] E) : ‖condExpL2 E 𝕜 hm f‖ ≤ ‖f‖ := + ((@condExpL2 _ E 𝕜 _ _ _ _ _ _ μ hm).le_opNorm f).trans + (mul_le_of_le_one_left (norm_nonneg _) (norm_condExpL2_le_one hm)) + +@[deprecated (since := "2025-01-21")] alias norm_condexpL2_le := norm_condExpL2_le -theorem eLpNorm_condexpL2_le (hm : m ≤ m0) (f : α →₂[μ] E) : - eLpNorm (ε := E) (condexpL2 E 𝕜 hm f) 2 μ ≤ eLpNorm f 2 μ := by +theorem eLpNorm_condExpL2_le (hm : m ≤ m0) (f : α →₂[μ] E) : + eLpNorm (ε := E) (condExpL2 E 𝕜 hm f) 2 μ ≤ eLpNorm f 2 μ := by rw [lpMeas_coe, ← ENNReal.toReal_le_toReal (Lp.eLpNorm_ne_top _) (Lp.eLpNorm_ne_top _), ← Lp.norm_def, ← Lp.norm_def, Submodule.norm_coe] - exact norm_condexpL2_le hm f + exact norm_condExpL2_le hm f + +@[deprecated (since := "2025-01-21")] alias eLpNorm_condexpL2_le := eLpNorm_condExpL2_le @[deprecated (since := "2024-07-27")] -alias snorm_condexpL2_le := eLpNorm_condexpL2_le +alias snorm_condExpL2_le := eLpNorm_condExpL2_le + +@[deprecated (since := "2025-01-21")] alias snorm_condexpL2_le := snorm_condExpL2_le -theorem norm_condexpL2_coe_le (hm : m ≤ m0) (f : α →₂[μ] E) : - ‖(condexpL2 E 𝕜 hm f : α →₂[μ] E)‖ ≤ ‖f‖ := by +theorem norm_condExpL2_coe_le (hm : m ≤ m0) (f : α →₂[μ] E) : + ‖(condExpL2 E 𝕜 hm f : α →₂[μ] E)‖ ≤ ‖f‖ := by rw [Lp.norm_def, Lp.norm_def, ← lpMeas_coe] - exact ENNReal.toReal_mono (Lp.eLpNorm_ne_top _) (eLpNorm_condexpL2_le hm f) + exact ENNReal.toReal_mono (Lp.eLpNorm_ne_top _) (eLpNorm_condExpL2_le hm f) + +@[deprecated (since := "2025-01-21")] alias norm_condexpL2_coe_le := norm_condExpL2_coe_le -theorem inner_condexpL2_left_eq_right (hm : m ≤ m0) {f g : α →₂[μ] E} : - ⟪(condexpL2 E 𝕜 hm f : α →₂[μ] E), g⟫₂ = ⟪f, (condexpL2 E 𝕜 hm g : α →₂[μ] E)⟫₂ := +theorem inner_condExpL2_left_eq_right (hm : m ≤ m0) {f g : α →₂[μ] E} : + ⟪(condExpL2 E 𝕜 hm f : α →₂[μ] E), g⟫₂ = ⟪f, (condExpL2 E 𝕜 hm g : α →₂[μ] E)⟫₂ := haveI : Fact (m ≤ m0) := ⟨hm⟩ inner_orthogonalProjection_left_eq_right _ f g -theorem condexpL2_indicator_of_measurable (hm : m ≤ m0) (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) +@[deprecated (since := "2025-01-21")] +alias inner_condexpL2_left_eq_right := inner_condExpL2_left_eq_right + +theorem condExpL2_indicator_of_measurable (hm : m ≤ m0) (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) (c : E) : - (condexpL2 E 𝕜 hm (indicatorConstLp 2 (hm s hs) hμs c) : α →₂[μ] E) = + (condExpL2 E 𝕜 hm (indicatorConstLp 2 (hm s hs) hμs c) : α →₂[μ] E) = indicatorConstLp 2 (hm s hs) hμs c := by - rw [condexpL2] + rw [condExpL2] haveI : Fact (m ≤ m0) := ⟨hm⟩ have h_mem : indicatorConstLp 2 (hm s hs) hμs c ∈ lpMeas E 𝕜 m 2 μ := mem_lpMeas_indicatorConstLp hm hs hμs @@ -126,34 +150,43 @@ theorem condexpL2_indicator_of_measurable (hm : m ≤ m0) (hs : MeasurableSet[m] have h_orth_mem := orthogonalProjection_mem_subspace_eq_self ind rw [← h_coe_ind, h_orth_mem] -theorem inner_condexpL2_eq_inner_fun (hm : m ≤ m0) (f g : α →₂[μ] E) +@[deprecated (since := "2025-01-21")] +alias condexpL2_indicator_of_measurable := condExpL2_indicator_of_measurable + +theorem inner_condExpL2_eq_inner_fun (hm : m ≤ m0) (f g : α →₂[μ] E) (hg : AEStronglyMeasurable' m g μ) : - ⟪(condexpL2 E 𝕜 hm f : α →₂[μ] E), g⟫₂ = ⟪f, g⟫₂ := by + ⟪(condExpL2 E 𝕜 hm f : α →₂[μ] E), g⟫₂ = ⟪f, g⟫₂ := by symm - rw [← sub_eq_zero, ← inner_sub_left, condexpL2] + rw [← sub_eq_zero, ← inner_sub_left, condExpL2] simp only [mem_lpMeas_iff_aeStronglyMeasurable'.mpr hg, orthogonalProjection_inner_eq_zero f g] +@[deprecated (since := "2025-01-21")] +alias inner_condexpL2_eq_inner_fun := inner_condExpL2_eq_inner_fun + section Real variable {hm : m ≤ m0} -theorem integral_condexpL2_eq_of_fin_meas_real (f : Lp 𝕜 2 μ) (hs : MeasurableSet[m] s) - (hμs : μ s ≠ ∞) : ∫ x in s, (condexpL2 𝕜 𝕜 hm f : α → 𝕜) x ∂μ = ∫ x in s, f x ∂μ := by +theorem integral_condExpL2_eq_of_fin_meas_real (f : Lp 𝕜 2 μ) (hs : MeasurableSet[m] s) + (hμs : μ s ≠ ∞) : ∫ x in s, (condExpL2 𝕜 𝕜 hm f : α → 𝕜) x ∂μ = ∫ x in s, f x ∂μ := by rw [← L2.inner_indicatorConstLp_one (𝕜 := 𝕜) (hm s hs) hμs f] - have h_eq_inner : ∫ x in s, (condexpL2 𝕜 𝕜 hm f : α → 𝕜) x ∂μ = - inner (indicatorConstLp 2 (hm s hs) hμs (1 : 𝕜)) (condexpL2 𝕜 𝕜 hm f) := by + have h_eq_inner : ∫ x in s, (condExpL2 𝕜 𝕜 hm f : α → 𝕜) x ∂μ = + inner (indicatorConstLp 2 (hm s hs) hμs (1 : 𝕜)) (condExpL2 𝕜 𝕜 hm f) := by rw [L2.inner_indicatorConstLp_one (hm s hs) hμs] - rw [h_eq_inner, ← inner_condexpL2_left_eq_right, condexpL2_indicator_of_measurable hm hs hμs] + rw [h_eq_inner, ← inner_condExpL2_left_eq_right, condExpL2_indicator_of_measurable hm hs hμs] + +@[deprecated (since := "2025-01-21")] +alias integral_condexpL2_eq_of_fin_meas_real := integral_condExpL2_eq_of_fin_meas_real -theorem lintegral_nnnorm_condexpL2_le (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) (f : Lp ℝ 2 μ) : - ∫⁻ x in s, ‖(condexpL2 ℝ ℝ hm f : α → ℝ) x‖₊ ∂μ ≤ ∫⁻ x in s, ‖f x‖₊ ∂μ := by - let h_meas := lpMeas.aeStronglyMeasurable' (condexpL2 ℝ ℝ hm f) +theorem lintegral_nnnorm_condExpL2_le (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) (f : Lp ℝ 2 μ) : + ∫⁻ x in s, ‖(condExpL2 ℝ ℝ hm f : α → ℝ) x‖₊ ∂μ ≤ ∫⁻ x in s, ‖f x‖₊ ∂μ := by + let h_meas := lpMeas.aeStronglyMeasurable' (condExpL2 ℝ ℝ hm f) let g := h_meas.choose have hg_meas : StronglyMeasurable[m] g := h_meas.choose_spec.1 - have hg_eq : g =ᵐ[μ] condexpL2 ℝ ℝ hm f := h_meas.choose_spec.2.symm - have hg_eq_restrict : g =ᵐ[μ.restrict s] condexpL2 ℝ ℝ hm f := ae_restrict_of_ae hg_eq + have hg_eq : g =ᵐ[μ] condExpL2 ℝ ℝ hm f := h_meas.choose_spec.2.symm + have hg_eq_restrict : g =ᵐ[μ.restrict s] condExpL2 ℝ ℝ hm f := ae_restrict_of_ae hg_eq have hg_nnnorm_eq : (fun x => (‖g x‖₊ : ℝ≥0∞)) =ᵐ[μ.restrict s] fun x => - (‖(condexpL2 ℝ ℝ hm f : α → ℝ) x‖₊ : ℝ≥0∞) := by + (‖(condExpL2 ℝ ℝ hm f : α → ℝ) x‖₊ : ℝ≥0∞) := by refine hg_eq_restrict.mono fun x hx => ?_ dsimp only simp_rw [hx] @@ -163,14 +196,17 @@ theorem lintegral_nnnorm_condexpL2_le (hs : MeasurableSet[m] s) (hμs : μ s ≠ · exact integrableOn_Lp_of_measure_ne_top f fact_one_le_two_ennreal.elim hμs · exact hg_meas · rw [IntegrableOn, integrable_congr hg_eq_restrict] - exact integrableOn_condexpL2_of_measure_ne_top hm hμs f + exact integrableOn_condExpL2_of_measure_ne_top hm hμs f · intro t ht hμt - rw [← integral_condexpL2_eq_of_fin_meas_real f ht hμt.ne] + rw [← integral_condExpL2_eq_of_fin_meas_real f ht hμt.ne] exact setIntegral_congr_ae (hm t ht) (hg_eq.mono fun x hx _ => hx) -theorem condexpL2_ae_eq_zero_of_ae_eq_zero (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) {f : Lp ℝ 2 μ} - (hf : f =ᵐ[μ.restrict s] 0) : condexpL2 ℝ ℝ hm f =ᵐ[μ.restrict s] (0 : α → ℝ) := by - suffices h_nnnorm_eq_zero : ∫⁻ x in s, ‖(condexpL2 ℝ ℝ hm f : α → ℝ) x‖₊ ∂μ = 0 by +@[deprecated (since := "2025-01-21")] +alias lintegral_nnnorm_condexpL2_le := lintegral_nnnorm_condExpL2_le + +theorem condExpL2_ae_eq_zero_of_ae_eq_zero (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) {f : Lp ℝ 2 μ} + (hf : f =ᵐ[μ.restrict s] 0) : condExpL2 ℝ ℝ hm f =ᵐ[μ.restrict s] (0 : α → ℝ) := by + suffices h_nnnorm_eq_zero : ∫⁻ x in s, ‖(condExpL2 ℝ ℝ hm f : α → ℝ) x‖₊ ∂μ = 0 by rw [lintegral_eq_zero_iff] at h_nnnorm_eq_zero · refine h_nnnorm_eq_zero.mono fun x hx => ?_ dsimp only at hx @@ -180,7 +216,7 @@ theorem condexpL2_ae_eq_zero_of_ae_eq_zero (hs : MeasurableSet[m] s) (hμs : μ rw [lpMeas_coe] exact (Lp.stronglyMeasurable _).measurable refine le_antisymm ?_ (zero_le _) - refine (lintegral_nnnorm_condexpL2_le hs hμs f).trans (le_of_eq ?_) + refine (lintegral_nnnorm_condExpL2_le hs hμs f).trans (le_of_eq ?_) rw [lintegral_eq_zero_iff] · refine hf.mono fun x hx => ?_ dsimp only @@ -188,10 +224,13 @@ theorem condexpL2_ae_eq_zero_of_ae_eq_zero (hs : MeasurableSet[m] s) (hμs : μ simp · exact (Lp.stronglyMeasurable _).ennnorm -theorem lintegral_nnnorm_condexpL2_indicator_le_real (hs : MeasurableSet s) (hμs : μ s ≠ ∞) +@[deprecated (since := "2025-01-21")] +alias condexpL2_ae_eq_zero_of_ae_eq_zero := condExpL2_ae_eq_zero_of_ae_eq_zero + +theorem lintegral_nnnorm_condExpL2_indicator_le_real (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (ht : MeasurableSet[m] t) (hμt : μ t ≠ ∞) : - ∫⁻ a in t, ‖(condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ ≤ μ (s ∩ t) := by - refine (lintegral_nnnorm_condexpL2_le ht hμt _).trans (le_of_eq ?_) + ∫⁻ a in t, ‖(condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ ≤ μ (s ∩ t) := by + refine (lintegral_nnnorm_condExpL2_le ht hμt _).trans (le_of_eq ?_) have h_eq : ∫⁻ x in t, ‖(indicatorConstLp 2 hs hμs (1 : ℝ)) x‖₊ ∂μ = ∫⁻ x in t, s.indicator (fun _ => (1 : ℝ≥0∞)) x ∂μ := by @@ -205,30 +244,33 @@ theorem lintegral_nnnorm_condexpL2_indicator_le_real (hs : MeasurableSet s) (hμ rw [h_eq, lintegral_indicator hs, lintegral_const, Measure.restrict_restrict hs] simp only [one_mul, Set.univ_inter, MeasurableSet.univ, Measure.restrict_apply] +@[deprecated (since := "2025-01-21")] +alias lintegral_nnnorm_condexpL2_indicator_le_real := lintegral_nnnorm_condExpL2_indicator_le_real + end Real -/-- `condexpL2` commutes with taking inner products with constants. See the lemma -`condexpL2_comp_continuousLinearMap` for a more general result about commuting with continuous +/-- `condExpL2` commutes with taking inner products with constants. See the lemma +`condExpL2_comp_continuousLinearMap` for a more general result about commuting with continuous linear maps. -/ -theorem condexpL2_const_inner (hm : m ≤ m0) (f : Lp E 2 μ) (c : E) : - condexpL2 𝕜 𝕜 hm (((Lp.memℒp f).const_inner c).toLp fun a => ⟪c, f a⟫) =ᵐ[μ] - fun a => ⟪c, (condexpL2 E 𝕜 hm f : α → E) a⟫ := by +theorem condExpL2_const_inner (hm : m ≤ m0) (f : Lp E 2 μ) (c : E) : + condExpL2 𝕜 𝕜 hm (((Lp.memℒp f).const_inner c).toLp fun a => ⟪c, f a⟫) =ᵐ[μ] + fun a => ⟪c, (condExpL2 E 𝕜 hm f : α → E) a⟫ := by rw [lpMeas_coe] - have h_mem_Lp : Memℒp (fun a => ⟪c, (condexpL2 E 𝕜 hm f : α → E) a⟫) 2 μ := by + have h_mem_Lp : Memℒp (fun a => ⟪c, (condExpL2 E 𝕜 hm f : α → E) a⟫) 2 μ := by refine Memℒp.const_inner _ ?_; rw [lpMeas_coe]; exact Lp.memℒp _ - have h_eq : h_mem_Lp.toLp _ =ᵐ[μ] fun a => ⟪c, (condexpL2 E 𝕜 hm f : α → E) a⟫ := + have h_eq : h_mem_Lp.toLp _ =ᵐ[μ] fun a => ⟪c, (condExpL2 E 𝕜 hm f : α → E) a⟫ := h_mem_Lp.coeFn_toLp refine EventuallyEq.trans ?_ h_eq refine Lp.ae_eq_of_forall_setIntegral_eq' 𝕜 hm _ _ two_ne_zero ENNReal.coe_ne_top - (fun s _ hμs => integrableOn_condexpL2_of_measure_ne_top hm hμs.ne _) ?_ ?_ ?_ ?_ + (fun s _ hμs => integrableOn_condExpL2_of_measure_ne_top hm hμs.ne _) ?_ ?_ ?_ ?_ · intro s _ hμs rw [IntegrableOn, integrable_congr (ae_restrict_of_ae h_eq)] - exact (integrableOn_condexpL2_of_measure_ne_top hm hμs.ne _).const_inner _ + exact (integrableOn_condExpL2_of_measure_ne_top hm hμs.ne _).const_inner _ · intro s hs hμs - rw [← lpMeas_coe, integral_condexpL2_eq_of_fin_meas_real _ hs hμs.ne, + rw [← lpMeas_coe, integral_condExpL2_eq_of_fin_meas_real _ hs hμs.ne, integral_congr_ae (ae_restrict_of_ae h_eq), lpMeas_coe, ← - L2.inner_indicatorConstLp_eq_setIntegral_inner 𝕜 (↑(condexpL2 E 𝕜 hm f)) (hm s hs) c hμs.ne, - ← inner_condexpL2_left_eq_right, condexpL2_indicator_of_measurable _ hs, + L2.inner_indicatorConstLp_eq_setIntegral_inner 𝕜 (↑(condExpL2 E 𝕜 hm f)) (hm s hs) c hμs.ne, + ← inner_condExpL2_left_eq_right, condExpL2_indicator_of_measurable _ hs, L2.inner_indicatorConstLp_eq_setIntegral_inner 𝕜 f (hm s hs) c hμs.ne, setIntegral_congr_ae (hm s hs) ((Memℒp.coeFn_toLp ((Lp.memℒp f).const_inner c)).mono fun x hx _ => hx)] @@ -236,14 +278,16 @@ theorem condexpL2_const_inner (hm : m ≤ m0) (f : Lp E 2 μ) (c : E) : · refine AEStronglyMeasurable'.congr ?_ h_eq.symm exact (lpMeas.aeStronglyMeasurable' _).const_inner _ -/-- `condexpL2` verifies the equality of integrals defining the conditional expectation. -/ -theorem integral_condexpL2_eq (hm : m ≤ m0) (f : Lp E' 2 μ) (hs : MeasurableSet[m] s) - (hμs : μ s ≠ ∞) : ∫ x in s, (condexpL2 E' 𝕜 hm f : α → E') x ∂μ = ∫ x in s, f x ∂μ := by +@[deprecated (since := "2025-01-21")] alias condexpL2_const_inner := condExpL2_const_inner + +/-- `condExpL2` verifies the equality of integrals defining the conditional expectation. -/ +theorem integral_condExpL2_eq (hm : m ≤ m0) (f : Lp E' 2 μ) (hs : MeasurableSet[m] s) + (hμs : μ s ≠ ∞) : ∫ x in s, (condExpL2 E' 𝕜 hm f : α → E') x ∂μ = ∫ x in s, f x ∂μ := by rw [← sub_eq_zero, lpMeas_coe, ← integral_sub' (integrableOn_Lp_of_measure_ne_top _ fact_one_le_two_ennreal.elim hμs) (integrableOn_Lp_of_measure_ne_top _ fact_one_le_two_ennreal.elim hμs)] refine integral_eq_zero_of_forall_integral_inner_eq_zero 𝕜 _ ?_ ?_ - · rw [integrable_congr (ae_restrict_of_ae (Lp.coeFn_sub (↑(condexpL2 E' 𝕜 hm f)) f).symm)] + · rw [integrable_congr (ae_restrict_of_ae (Lp.coeFn_sub (↑(condExpL2 E' 𝕜 hm f)) f).symm)] exact integrableOn_Lp_of_measure_ne_top _ fact_one_le_two_ennreal.elim hμs intro c simp_rw [Pi.sub_apply, inner_sub_right] @@ -252,34 +296,39 @@ theorem integral_condexpL2_eq (hm : m ≤ m0) (f : Lp E' 2 μ) (hs : MeasurableS ((integrableOn_Lp_of_measure_ne_top _ fact_one_le_two_ennreal.elim hμs).const_inner c)] have h_ae_eq_f := Memℒp.coeFn_toLp (E := 𝕜) ((Lp.memℒp f).const_inner c) rw [← lpMeas_coe, sub_eq_zero, ← - setIntegral_congr_ae (hm s hs) ((condexpL2_const_inner hm f c).mono fun x hx _ => hx), ← + setIntegral_congr_ae (hm s hs) ((condExpL2_const_inner hm f c).mono fun x hx _ => hx), ← setIntegral_congr_ae (hm s hs) (h_ae_eq_f.mono fun x hx _ => hx)] - exact integral_condexpL2_eq_of_fin_meas_real _ hs hμs + exact integral_condExpL2_eq_of_fin_meas_real _ hs hμs + +@[deprecated (since := "2025-01-21")] alias integral_condexpL2_eq := integral_condExpL2_eq variable {E'' 𝕜' : Type*} [RCLike 𝕜'] [NormedAddCommGroup E''] [InnerProductSpace 𝕜' E''] [CompleteSpace E''] [NormedSpace ℝ E''] variable (𝕜 𝕜') -theorem condexpL2_comp_continuousLinearMap (hm : m ≤ m0) (T : E' →L[ℝ] E'') (f : α →₂[μ] E') : - (condexpL2 E'' 𝕜' hm (T.compLp f) : α →₂[μ] E'') =ᵐ[μ] - T.compLp (condexpL2 E' 𝕜 hm f : α →₂[μ] E') := by +theorem condExpL2_comp_continuousLinearMap (hm : m ≤ m0) (T : E' →L[ℝ] E'') (f : α →₂[μ] E') : + (condExpL2 E'' 𝕜' hm (T.compLp f) : α →₂[μ] E'') =ᵐ[μ] + T.compLp (condExpL2 E' 𝕜 hm f : α →₂[μ] E') := by refine Lp.ae_eq_of_forall_setIntegral_eq' 𝕜' hm _ _ two_ne_zero ENNReal.coe_ne_top - (fun s _ hμs => integrableOn_condexpL2_of_measure_ne_top hm hμs.ne _) (fun s _ hμs => + (fun s _ hμs => integrableOn_condExpL2_of_measure_ne_top hm hμs.ne _) (fun s _ hμs => integrableOn_Lp_of_measure_ne_top _ fact_one_le_two_ennreal.elim hμs.ne) ?_ ?_ ?_ · intro s hs hμs rw [T.setIntegral_compLp _ (hm s hs), T.integral_comp_comm (integrableOn_Lp_of_measure_ne_top _ fact_one_le_two_ennreal.elim hμs.ne), - ← lpMeas_coe, ← lpMeas_coe, integral_condexpL2_eq hm f hs hμs.ne, - integral_condexpL2_eq hm (T.compLp f) hs hμs.ne, T.setIntegral_compLp _ (hm s hs), + ← lpMeas_coe, ← lpMeas_coe, integral_condExpL2_eq hm f hs hμs.ne, + integral_condExpL2_eq hm (T.compLp f) hs hμs.ne, T.setIntegral_compLp _ (hm s hs), T.integral_comp_comm (integrableOn_Lp_of_measure_ne_top f fact_one_le_two_ennreal.elim hμs.ne)] · rw [← lpMeas_coe]; exact lpMeas.aeStronglyMeasurable' _ - · have h_coe := T.coeFn_compLp (condexpL2 E' 𝕜 hm f : α →₂[μ] E') + · have h_coe := T.coeFn_compLp (condExpL2 E' 𝕜 hm f : α →₂[μ] E') rw [← EventuallyEq] at h_coe refine AEStronglyMeasurable'.congr ?_ h_coe.symm - exact (lpMeas.aeStronglyMeasurable' (condexpL2 E' 𝕜 hm f)).continuous_comp T.continuous + exact (lpMeas.aeStronglyMeasurable' (condExpL2 E' 𝕜 hm f)).continuous_comp T.continuous + +@[deprecated (since := "2025-01-21")] +alias condexpL2_comp_continuousLinearMap := condExpL2_comp_continuousLinearMap variable {𝕜 𝕜'} @@ -287,72 +336,90 @@ section CondexpL2Indicator variable (𝕜) -theorem condexpL2_indicator_ae_eq_smul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) +theorem condExpL2_indicator_ae_eq_smul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E') : - condexpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) =ᵐ[μ] fun a => - (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs (1 : ℝ)) : α → ℝ) a • x := by + condExpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) =ᵐ[μ] fun a => + (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs (1 : ℝ)) : α → ℝ) a • x := by rw [indicatorConstLp_eq_toSpanSingleton_compLp hs hμs x] have h_comp := - condexpL2_comp_continuousLinearMap ℝ 𝕜 hm (toSpanSingleton ℝ x) + condExpL2_comp_continuousLinearMap ℝ 𝕜 hm (toSpanSingleton ℝ x) (indicatorConstLp 2 hs hμs (1 : ℝ)) rw [← lpMeas_coe] at h_comp refine h_comp.trans ?_ exact (toSpanSingleton ℝ x).coeFn_compLp _ -theorem condexpL2_indicator_eq_toSpanSingleton_comp (hm : m ≤ m0) (hs : MeasurableSet s) - (hμs : μ s ≠ ∞) (x : E') : (condexpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α →₂[μ] E') = - (toSpanSingleton ℝ x).compLp (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1)) := by +@[deprecated (since := "2025-01-21")] +alias condexpL2_indicator_ae_eq_smul := condExpL2_indicator_ae_eq_smul + +theorem condExpL2_indicator_eq_toSpanSingleton_comp (hm : m ≤ m0) (hs : MeasurableSet s) + (hμs : μ s ≠ ∞) (x : E') : (condExpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α →₂[μ] E') = + (toSpanSingleton ℝ x).compLp (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1)) := by ext1 rw [← lpMeas_coe] - refine (condexpL2_indicator_ae_eq_smul 𝕜 hm hs hμs x).trans ?_ + refine (condExpL2_indicator_ae_eq_smul 𝕜 hm hs hμs x).trans ?_ have h_comp := (toSpanSingleton ℝ x).coeFn_compLp - (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α →₂[μ] ℝ) + (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α →₂[μ] ℝ) rw [← EventuallyEq] at h_comp refine EventuallyEq.trans ?_ h_comp.symm filter_upwards with y using rfl +@[deprecated (since := "2025-01-21")] +alias condexpL2_indicator_eq_toSpanSingleton_comp := condExpL2_indicator_eq_toSpanSingleton_comp + variable {𝕜} -theorem setLIntegral_nnnorm_condexpL2_indicator_le (hm : m ≤ m0) (hs : MeasurableSet s) +theorem setLIntegral_nnnorm_condExpL2_indicator_le (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E') {t : Set α} (ht : MeasurableSet[m] t) (hμt : μ t ≠ ∞) : - ∫⁻ a in t, ‖(condexpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α → E') a‖₊ ∂μ ≤ + ∫⁻ a in t, ‖(condExpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α → E') a‖₊ ∂μ ≤ μ (s ∩ t) * ‖x‖₊ := calc - ∫⁻ a in t, ‖(condexpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α → E') a‖₊ ∂μ = - ∫⁻ a in t, ‖(condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a • x‖₊ ∂μ := + ∫⁻ a in t, ‖(condExpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α → E') a‖₊ ∂μ = + ∫⁻ a in t, ‖(condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a • x‖₊ ∂μ := setLIntegral_congr_fun (hm t ht) - ((condexpL2_indicator_ae_eq_smul 𝕜 hm hs hμs x).mono fun a ha _ => by rw [ha]) - _ = (∫⁻ a in t, ‖(condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ) * ‖x‖₊ := by + ((condExpL2_indicator_ae_eq_smul 𝕜 hm hs hμs x).mono fun a ha _ => by rw [ha]) + _ = (∫⁻ a in t, ‖(condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ) * ‖x‖₊ := by simp_rw [nnnorm_smul, ENNReal.coe_mul] rw [lintegral_mul_const, lpMeas_coe] exact (Lp.stronglyMeasurable _).ennnorm _ ≤ μ (s ∩ t) * ‖x‖₊ := - mul_le_mul_right' (lintegral_nnnorm_condexpL2_indicator_le_real hs hμs ht hμt) _ + mul_le_mul_right' (lintegral_nnnorm_condExpL2_indicator_le_real hs hμs ht hμt) _ + +@[deprecated (since := "2025-01-21")] +alias setLIntegral_nnnorm_condexpL2_indicator_le := setLIntegral_nnnorm_condExpL2_indicator_le @[deprecated (since := "2024-06-29")] -alias set_lintegral_nnnorm_condexpL2_indicator_le := setLIntegral_nnnorm_condexpL2_indicator_le +alias set_lintegral_nnnorm_condExpL2_indicator_le := setLIntegral_nnnorm_condExpL2_indicator_le + +@[deprecated (since := "2025-01-21")] +alias set_lintegral_nnnorm_condexpL2_indicator_le := set_lintegral_nnnorm_condExpL2_indicator_le -theorem lintegral_nnnorm_condexpL2_indicator_le (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) +theorem lintegral_nnnorm_condExpL2_indicator_le (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E') [SigmaFinite (μ.trim hm)] : - ∫⁻ a, ‖(condexpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α → E') a‖₊ ∂μ ≤ μ s * ‖x‖₊ := by + ∫⁻ a, ‖(condExpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x) : α → E') a‖₊ ∂μ ≤ μ s * ‖x‖₊ := by refine lintegral_le_of_forall_fin_meas_trim_le hm (μ s * ‖x‖₊) fun t ht hμt => ?_ - refine (setLIntegral_nnnorm_condexpL2_indicator_le hm hs hμs x ht hμt).trans ?_ + refine (setLIntegral_nnnorm_condExpL2_indicator_le hm hs hμs x ht hμt).trans ?_ gcongr apply Set.inter_subset_left +@[deprecated (since := "2025-01-21")] +alias lintegral_nnnorm_condexpL2_indicator_le := lintegral_nnnorm_condExpL2_indicator_le + /-- If the measure `μ.trim hm` is sigma-finite, then the conditional expectation of a measurable set with finite measure is integrable. -/ -theorem integrable_condexpL2_indicator (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] +theorem integrable_condExpL2_indicator (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E') : - Integrable (ε := E') (condexpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x)) μ := by + Integrable (ε := E') (condExpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x)) μ := by refine integrable_of_forall_fin_meas_le' hm (μ s * ‖x‖₊) (ENNReal.mul_lt_top hμs.lt_top ENNReal.coe_lt_top) ?_ ?_ · rw [lpMeas_coe]; exact Lp.aestronglyMeasurable _ · refine fun t ht hμt => - (setLIntegral_nnnorm_condexpL2_indicator_le hm hs hμs x ht hμt).trans ?_ + (setLIntegral_nnnorm_condExpL2_indicator_le hm hs hμs x ht hμt).trans ?_ gcongr apply Set.inter_subset_left +@[deprecated (since := "2025-01-21")] +alias integrable_condexpL2_indicator := integrable_condExpL2_indicator + end CondexpL2Indicator section CondexpIndSMul @@ -360,115 +427,152 @@ section CondexpIndSMul variable [NormedSpace ℝ G] {hm : m ≤ m0} /-- Conditional expectation of the indicator of a measurable set with finite measure, in L2. -/ -noncomputable def condexpIndSMul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : +noncomputable def condExpIndSMul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : Lp G 2 μ := - (toSpanSingleton ℝ x).compLpL 2 μ (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs (1 : ℝ))) + (toSpanSingleton ℝ x).compLpL 2 μ (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs (1 : ℝ))) + +@[deprecated (since := "2025-01-21")] alias condexpIndSMul := condExpIndSMul -theorem aeStronglyMeasurable'_condexpIndSMul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) - (x : G) : AEStronglyMeasurable' m (condexpIndSMul hm hs hμs x) μ := by - have h : AEStronglyMeasurable' m (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := - aeStronglyMeasurable'_condexpL2 _ _ - rw [condexpIndSMul] +theorem aeStronglyMeasurable'_condExpIndSMul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) + (x : G) : AEStronglyMeasurable' m (condExpIndSMul hm hs hμs x) μ := by + have h : AEStronglyMeasurable' m (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := + aeStronglyMeasurable'_condExpL2 _ _ + rw [condExpIndSMul] suffices AEStronglyMeasurable' m - (toSpanSingleton ℝ x ∘ condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1)) μ by + (toSpanSingleton ℝ x ∘ condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1)) μ by refine AEStronglyMeasurable'.congr this ?_ refine EventuallyEq.trans ?_ (coeFn_compLpL _ _).symm rfl exact AEStronglyMeasurable'.continuous_comp (toSpanSingleton ℝ x).continuous h -theorem condexpIndSMul_add (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x y : G) : - condexpIndSMul hm hs hμs (x + y) = condexpIndSMul hm hs hμs x + condexpIndSMul hm hs hμs y := by - simp_rw [condexpIndSMul]; rw [toSpanSingleton_add, add_compLpL, add_apply] +@[deprecated (since := "2025-01-21")] +alias aeStronglyMeasurable'_condexpIndSMul := aeStronglyMeasurable'_condExpIndSMul + +theorem condExpIndSMul_add (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x y : G) : + condExpIndSMul hm hs hμs (x + y) = condExpIndSMul hm hs hμs x + condExpIndSMul hm hs hμs y := by + simp_rw [condExpIndSMul]; rw [toSpanSingleton_add, add_compLpL, add_apply] -theorem condexpIndSMul_smul (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (c : ℝ) (x : G) : - condexpIndSMul hm hs hμs (c • x) = c • condexpIndSMul hm hs hμs x := by - simp_rw [condexpIndSMul]; rw [toSpanSingleton_smul, smul_compLpL, smul_apply] +@[deprecated (since := "2025-01-21")] alias condexpIndSMul_add := condExpIndSMul_add -theorem condexpIndSMul_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (hs : MeasurableSet s) +theorem condExpIndSMul_smul (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (c : ℝ) (x : G) : + condExpIndSMul hm hs hμs (c • x) = c • condExpIndSMul hm hs hμs x := by + simp_rw [condExpIndSMul]; rw [toSpanSingleton_smul, smul_compLpL, smul_apply] + +@[deprecated (since := "2025-01-21")] alias condexpIndSMul_smul := condExpIndSMul_smul + +theorem condExpIndSMul_smul' [NormedSpace ℝ F] [SMulCommClass ℝ 𝕜 F] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (c : 𝕜) (x : F) : - condexpIndSMul hm hs hμs (c • x) = c • condexpIndSMul hm hs hμs x := by - rw [condexpIndSMul, condexpIndSMul, toSpanSingleton_smul', + condExpIndSMul hm hs hμs (c • x) = c • condExpIndSMul hm hs hμs x := by + rw [condExpIndSMul, condExpIndSMul, toSpanSingleton_smul', (toSpanSingleton ℝ x).smul_compLpL c, smul_apply] -theorem condexpIndSMul_ae_eq_smul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : - condexpIndSMul hm hs hμs x =ᵐ[μ] fun a => - (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a • x := +@[deprecated (since := "2025-01-21")] alias condexpIndSMul_smul' := condExpIndSMul_smul' + +theorem condExpIndSMul_ae_eq_smul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : + condExpIndSMul hm hs hμs x =ᵐ[μ] fun a => + (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a • x := (toSpanSingleton ℝ x).coeFn_compLpL _ -theorem setLIntegral_nnnorm_condexpIndSMul_le (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) +@[deprecated (since := "2025-01-21")] alias condexpIndSMul_ae_eq_smul := condExpIndSMul_ae_eq_smul + +theorem setLIntegral_nnnorm_condExpIndSMul_le (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) {t : Set α} (ht : MeasurableSet[m] t) (hμt : μ t ≠ ∞) : - (∫⁻ a in t, ‖condexpIndSMul hm hs hμs x a‖₊ ∂μ) ≤ μ (s ∩ t) * ‖x‖₊ := + (∫⁻ a in t, ‖condExpIndSMul hm hs hμs x a‖₊ ∂μ) ≤ μ (s ∩ t) * ‖x‖₊ := calc - ∫⁻ a in t, ‖condexpIndSMul hm hs hμs x a‖₊ ∂μ = - ∫⁻ a in t, ‖(condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a • x‖₊ ∂μ := + ∫⁻ a in t, ‖condExpIndSMul hm hs hμs x a‖₊ ∂μ = + ∫⁻ a in t, ‖(condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a • x‖₊ ∂μ := setLIntegral_congr_fun (hm t ht) - ((condexpIndSMul_ae_eq_smul hm hs hμs x).mono fun a ha _ => by rw [ha]) - _ = (∫⁻ a in t, ‖(condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ) * ‖x‖₊ := by + ((condExpIndSMul_ae_eq_smul hm hs hμs x).mono fun a ha _ => by rw [ha]) + _ = (∫⁻ a in t, ‖(condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ) * ‖x‖₊ := by simp_rw [nnnorm_smul, ENNReal.coe_mul] rw [lintegral_mul_const, lpMeas_coe] exact (Lp.stronglyMeasurable _).ennnorm _ ≤ μ (s ∩ t) * ‖x‖₊ := - mul_le_mul_right' (lintegral_nnnorm_condexpL2_indicator_le_real hs hμs ht hμt) _ + mul_le_mul_right' (lintegral_nnnorm_condExpL2_indicator_le_real hs hμs ht hμt) _ + +@[deprecated (since := "2025-01-21")] +alias setLIntegral_nnnorm_condexpIndSMul_le := setLIntegral_nnnorm_condExpIndSMul_le @[deprecated (since := "2024-06-29")] -alias set_lintegral_nnnorm_condexpIndSMul_le := setLIntegral_nnnorm_condexpIndSMul_le +alias set_lintegral_nnnorm_condExpIndSMul_le := setLIntegral_nnnorm_condExpIndSMul_le -theorem lintegral_nnnorm_condexpIndSMul_le (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) - (x : G) [SigmaFinite (μ.trim hm)] : ∫⁻ a, ‖condexpIndSMul hm hs hμs x a‖₊ ∂μ ≤ μ s * ‖x‖₊ := by +@[deprecated (since := "2025-01-21")] +alias set_lintegral_nnnorm_condexpIndSMul_le := set_lintegral_nnnorm_condExpIndSMul_le + +theorem lintegral_nnnorm_condExpIndSMul_le (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) + (x : G) [SigmaFinite (μ.trim hm)] : ∫⁻ a, ‖condExpIndSMul hm hs hμs x a‖₊ ∂μ ≤ μ s * ‖x‖₊ := by refine lintegral_le_of_forall_fin_meas_trim_le hm (μ s * ‖x‖₊) fun t ht hμt => ?_ - refine (setLIntegral_nnnorm_condexpIndSMul_le hm hs hμs x ht hμt).trans ?_ + refine (setLIntegral_nnnorm_condExpIndSMul_le hm hs hμs x ht hμt).trans ?_ gcongr apply Set.inter_subset_left +@[deprecated (since := "2025-01-21")] +alias lintegral_nnnorm_condexpIndSMul_le := lintegral_nnnorm_condExpIndSMul_le + /-- If the measure `μ.trim hm` is sigma-finite, then the conditional expectation of a measurable set with finite measure is integrable. -/ -theorem integrable_condexpIndSMul (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) - (hμs : μ s ≠ ∞) (x : G) : Integrable (condexpIndSMul hm hs hμs x) μ := by +theorem integrable_condExpIndSMul (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) + (hμs : μ s ≠ ∞) (x : G) : Integrable (condExpIndSMul hm hs hμs x) μ := by refine integrable_of_forall_fin_meas_le' hm (μ s * ‖x‖₊) (ENNReal.mul_lt_top hμs.lt_top ENNReal.coe_lt_top) ?_ ?_ · exact Lp.aestronglyMeasurable _ - · refine fun t ht hμt => (setLIntegral_nnnorm_condexpIndSMul_le hm hs hμs x ht hμt).trans ?_ + · refine fun t ht hμt => (setLIntegral_nnnorm_condExpIndSMul_le hm hs hμs x ht hμt).trans ?_ gcongr apply Set.inter_subset_left -theorem condexpIndSMul_empty {x : G} : condexpIndSMul hm MeasurableSet.empty +@[deprecated (since := "2025-01-21")] alias integrable_condexpIndSMul := integrable_condExpIndSMul + +theorem condExpIndSMul_empty {x : G} : condExpIndSMul hm MeasurableSet.empty ((measure_empty (μ := μ)).le.trans_lt ENNReal.coe_lt_top).ne x = 0 := by - rw [condexpIndSMul, indicatorConstLp_empty] + rw [condExpIndSMul, indicatorConstLp_empty] simp only [Submodule.coe_zero, ContinuousLinearMap.map_zero] -theorem setIntegral_condexpL2_indicator (hs : MeasurableSet[m] s) (ht : MeasurableSet t) +@[deprecated (since := "2025-01-21")] alias condexpIndSMul_empty := condExpIndSMul_empty + +theorem setIntegral_condExpL2_indicator (hs : MeasurableSet[m] s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) (hμt : μ t ≠ ∞) : - ∫ x in s, (condexpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) x ∂μ = (μ (t ∩ s)).toReal := + ∫ x in s, (condExpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) x ∂μ = (μ (t ∩ s)).toReal := calc - ∫ x in s, (condexpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) x ∂μ = + ∫ x in s, (condExpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) x ∂μ = ∫ x in s, indicatorConstLp 2 ht hμt (1 : ℝ) x ∂μ := - @integral_condexpL2_eq α _ ℝ _ _ _ _ _ _ _ _ _ hm (indicatorConstLp 2 ht hμt (1 : ℝ)) hs hμs + @integral_condExpL2_eq α _ ℝ _ _ _ _ _ _ _ _ _ hm (indicatorConstLp 2 ht hμt (1 : ℝ)) hs hμs _ = (μ (t ∩ s)).toReal • (1 : ℝ) := setIntegral_indicatorConstLp (hm s hs) ht hμt 1 _ = (μ (t ∩ s)).toReal := by rw [smul_eq_mul, mul_one] +@[deprecated (since := "2025-01-21")] +alias setIntegral_condexpL2_indicator := setIntegral_condExpL2_indicator + @[deprecated (since := "2024-04-17")] -alias set_integral_condexpL2_indicator := setIntegral_condexpL2_indicator +alias set_integral_condExpL2_indicator := setIntegral_condExpL2_indicator -theorem setIntegral_condexpIndSMul (hs : MeasurableSet[m] s) (ht : MeasurableSet t) +@[deprecated (since := "2025-01-21")] +alias set_integral_condexpL2_indicator := set_integral_condExpL2_indicator + +theorem setIntegral_condExpIndSMul (hs : MeasurableSet[m] s) (ht : MeasurableSet t) (hμs : μ s ≠ ∞) (hμt : μ t ≠ ∞) (x : G') : - ∫ a in s, (condexpIndSMul hm ht hμt x) a ∂μ = (μ (t ∩ s)).toReal • x := + ∫ a in s, (condExpIndSMul hm ht hμt x) a ∂μ = (μ (t ∩ s)).toReal • x := calc - ∫ a in s, (condexpIndSMul hm ht hμt x) a ∂μ = - ∫ a in s, (condexpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) a • x ∂μ := + ∫ a in s, (condExpIndSMul hm ht hμt x) a ∂μ = + ∫ a in s, (condExpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) a • x ∂μ := setIntegral_congr_ae (hm s hs) - ((condexpIndSMul_ae_eq_smul hm ht hμt x).mono fun _ hx _ => hx) - _ = (∫ a in s, (condexpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) a ∂μ) • x := + ((condExpIndSMul_ae_eq_smul hm ht hμt x).mono fun _ hx _ => hx) + _ = (∫ a in s, (condExpL2 ℝ ℝ hm (indicatorConstLp 2 ht hμt 1) : α → ℝ) a ∂μ) • x := (integral_smul_const _ x) - _ = (μ (t ∩ s)).toReal • x := by rw [setIntegral_condexpL2_indicator hs ht hμs hμt] + _ = (μ (t ∩ s)).toReal • x := by rw [setIntegral_condExpL2_indicator hs ht hμs hμt] + +@[deprecated (since := "2025-01-21")] alias setIntegral_condexpIndSMul := setIntegral_condExpIndSMul @[deprecated (since := "2024-04-17")] -alias set_integral_condexpIndSMul := setIntegral_condexpIndSMul +alias set_integral_condExpIndSMul := setIntegral_condExpIndSMul + +@[deprecated (since := "2025-01-21")] +alias set_integral_condexpIndSMul := set_integral_condExpIndSMul -theorem condexpL2_indicator_nonneg (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) +theorem condExpL2_indicator_nonneg (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) [SigmaFinite (μ.trim hm)] : (0 : α → ℝ) ≤ᵐ[μ] - condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) := by - have h : AEStronglyMeasurable' m (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := - aeStronglyMeasurable'_condexpL2 _ _ + condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) := by + have h : AEStronglyMeasurable' m (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := + aeStronglyMeasurable'_condExpL2 _ _ refine EventuallyLE.trans_eq ?_ h.ae_eq_mk.symm refine @ae_le_of_ae_le_trim _ _ _ _ _ _ hm (0 : α → ℝ) _ ?_ refine ae_nonneg_of_forall_setIntegral_nonneg_of_sigmaFinite ?_ ?_ @@ -476,25 +580,29 @@ theorem condexpL2_indicator_nonneg (hm : m ≤ m0) (hs : MeasurableSet s) (hμs refine @Integrable.integrableOn _ _ m _ _ _ _ ?_ refine Integrable.trim hm ?_ ?_ · rw [integrable_congr h.ae_eq_mk.symm] - exact integrable_condexpL2_indicator hm hs hμs _ + exact integrable_condExpL2_indicator hm hs hμs _ · exact h.stronglyMeasurable_mk · intro t ht hμt rw [← setIntegral_trim hm h.stronglyMeasurable_mk ht] have h_ae : - ∀ᵐ x ∂μ, x ∈ t → h.mk _ x = (condexpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) x := by + ∀ᵐ x ∂μ, x ∈ t → h.mk _ x = (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) x := by filter_upwards [h.ae_eq_mk] with x hx exact fun _ => hx.symm rw [setIntegral_congr_ae (hm t ht) h_ae, - setIntegral_condexpL2_indicator ht hs ((le_trim hm).trans_lt hμt).ne hμs] + setIntegral_condExpL2_indicator ht hs ((le_trim hm).trans_lt hμt).ne hμs] exact ENNReal.toReal_nonneg -theorem condexpIndSMul_nonneg {E} [NormedLatticeAddCommGroup E] [NormedSpace ℝ E] [OrderedSMul ℝ E] +@[deprecated (since := "2025-01-21")] alias condexpL2_indicator_nonneg := condExpL2_indicator_nonneg + +theorem condExpIndSMul_nonneg {E} [NormedLatticeAddCommGroup E] [NormedSpace ℝ E] [OrderedSMul ℝ E] [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E) (hx : 0 ≤ x) : - (0 : α → E) ≤ᵐ[μ] condexpIndSMul hm hs hμs x := by - refine EventuallyLE.trans_eq ?_ (condexpIndSMul_ae_eq_smul hm hs hμs x).symm - filter_upwards [condexpL2_indicator_nonneg hm hs hμs] with a ha + (0 : α → E) ≤ᵐ[μ] condExpIndSMul hm hs hμs x := by + refine EventuallyLE.trans_eq ?_ (condExpIndSMul_ae_eq_smul hm hs hμs x).symm + filter_upwards [condExpL2_indicator_nonneg hm hs hμs] with a ha exact smul_nonneg ha hx +@[deprecated (since := "2025-01-21")] alias condexpIndSMul_nonneg := condExpIndSMul_nonneg + end CondexpIndSMul end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean index 260205e45cac9..32c40f221e8a5 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean @@ -15,7 +15,7 @@ a restricted measure. ## Main result -* `MeasureTheory.condexp_indicator`: If `s` is an `m`-measurable set, then the conditional +* `MeasureTheory.condExp_indicator`: If `s` is an `m`-measurable set, then the conditional expectation of the indicator function of `s` is almost everywhere equal to the indicator of `s` of the conditional expectation. Namely, `𝔼[s.indicator f | m] = s.indicator 𝔼[f | m]` a.e. @@ -33,47 +33,52 @@ namespace MeasureTheory variable {α E : Type*} {m m0 : MeasurableSpace α} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] {μ : Measure α} {f : α → E} {s : Set α} -theorem condexp_ae_eq_restrict_zero (hs : MeasurableSet[m] s) (hf : f =ᵐ[μ.restrict s] 0) : +theorem condExp_ae_eq_restrict_zero (hs : MeasurableSet[m] s) (hf : f =ᵐ[μ.restrict s] 0) : μ[f|m] =ᵐ[μ.restrict s] 0 := by by_cases hm : m ≤ m0 - swap; · simp_rw [condexp_of_not_le hm]; rfl + swap; · simp_rw [condExp_of_not_le hm]; rfl by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm]; rfl + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl haveI : SigmaFinite (μ.trim hm) := hμm have : SigmaFinite ((μ.restrict s).trim hm) := by rw [← restrict_trim hm _ hs] exact Restrict.sigmaFinite _ s by_cases hf_int : Integrable f μ - swap; · rw [condexp_undef hf_int] + swap; · rw [condExp_undef hf_int] refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hm ?_ ?_ ?_ ?_ ?_ - · exact fun t _ _ => integrable_condexp.integrableOn.integrableOn + · exact fun t _ _ => integrable_condExp.integrableOn.integrableOn · exact fun t _ _ => (integrable_zero _ _ _).integrableOn · intro t ht _ - rw [Measure.restrict_restrict (hm _ ht), setIntegral_condexp hm hf_int (ht.inter hs), ← + rw [Measure.restrict_restrict (hm _ ht), setIntegral_condExp hm hf_int (ht.inter hs), ← Measure.restrict_restrict (hm _ ht)] refine setIntegral_congr_ae (hm _ ht) ?_ filter_upwards [hf] with x hx _ using hx - · exact stronglyMeasurable_condexp.aeStronglyMeasurable' + · exact stronglyMeasurable_condExp.aeStronglyMeasurable' · exact stronglyMeasurable_zero.aeStronglyMeasurable' -/-- Auxiliary lemma for `condexp_indicator`. -/ -theorem condexp_indicator_aux (hs : MeasurableSet[m] s) (hf : f =ᵐ[μ.restrict sᶜ] 0) : +@[deprecated (since := "2025-01-21")] +alias condexp_ae_eq_restrict_zero := condExp_ae_eq_restrict_zero + +/-- Auxiliary lemma for `condExp_indicator`. -/ +theorem condExp_indicator_aux (hs : MeasurableSet[m] s) (hf : f =ᵐ[μ.restrict sᶜ] 0) : μ[s.indicator f|m] =ᵐ[μ] s.indicator (μ[f|m]) := by by_cases hm : m ≤ m0 - swap; · simp_rw [condexp_of_not_le hm, Set.indicator_zero']; rfl + swap; · simp_rw [condExp_of_not_le hm, Set.indicator_zero']; rfl have hsf_zero : ∀ g : α → E, g =ᵐ[μ.restrict sᶜ] 0 → s.indicator g =ᵐ[μ] g := fun g => indicator_ae_eq_of_restrict_compl_ae_eq_zero (hm _ hs) - refine ((hsf_zero (μ[f|m]) (condexp_ae_eq_restrict_zero hs.compl hf)).trans ?_).symm - exact condexp_congr_ae (hsf_zero f hf).symm + refine ((hsf_zero (μ[f|m]) (condExp_ae_eq_restrict_zero hs.compl hf)).trans ?_).symm + exact condExp_congr_ae (hsf_zero f hf).symm + +@[deprecated (since := "2025-01-21")] alias condexp_indicator_aux := condExp_indicator_aux /-- The conditional expectation of the indicator of a function over an `m`-measurable set with respect to the σ-algebra `m` is a.e. equal to the indicator of the conditional expectation. -/ -theorem condexp_indicator (hf_int : Integrable f μ) (hs : MeasurableSet[m] s) : +theorem condExp_indicator (hf_int : Integrable f μ) (hs : MeasurableSet[m] s) : μ[s.indicator f|m] =ᵐ[μ] s.indicator (μ[f|m]) := by by_cases hm : m ≤ m0 - swap; · simp_rw [condexp_of_not_le hm, Set.indicator_zero']; rfl + swap; · simp_rw [condExp_of_not_le hm, Set.indicator_zero']; rfl by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm, Set.indicator_zero']; rfl + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm, Set.indicator_zero']; rfl haveI : SigmaFinite (μ.trim hm) := hμm -- use `have` to perform what should be the first calc step because of an error I don't -- understand @@ -84,7 +89,7 @@ theorem condexp_indicator (hf_int : Integrable f μ) (hs : MeasurableSet[m] s) : s.indicator (μ[s.indicator f + sᶜ.indicator f|m]) =ᵐ[μ] s.indicator (μ[s.indicator f|m] + μ[sᶜ.indicator f|m]) := by have : μ[s.indicator f + sᶜ.indicator f|m] =ᵐ[μ] μ[s.indicator f|m] + μ[sᶜ.indicator f|m] := - condexp_add (hf_int.indicator (hm _ hs)) (hf_int.indicator (hm _ hs.compl)) + condExp_add (hf_int.indicator (hm _ hs)) (hf_int.indicator (hm _ hs.compl)) filter_upwards [this] with x hx classical rw [Set.indicator_apply, Set.indicator_apply, hx] _ = s.indicator (μ[s.indicator f|m]) + s.indicator (μ[sᶜ.indicator f|m]) := @@ -93,7 +98,7 @@ theorem condexp_indicator (hf_int : Integrable f μ) (hs : MeasurableSet[m] s) : s.indicator (sᶜ.indicator (μ[sᶜ.indicator f|m])) := by refine Filter.EventuallyEq.rfl.add ?_ have : sᶜ.indicator (μ[sᶜ.indicator f|m]) =ᵐ[μ] μ[sᶜ.indicator f|m] := by - refine (condexp_indicator_aux hs.compl ?_).symm.trans ?_ + refine (condExp_indicator_aux hs.compl ?_).symm.trans ?_ · exact indicator_ae_eq_restrict_compl (hm _ hs.compl) · rw [Set.indicator_indicator, Set.inter_self] filter_upwards [this] with x hx @@ -103,17 +108,19 @@ theorem condexp_indicator (hf_int : Integrable f μ) (hs : MeasurableSet[m] s) : _ =ᵐ[μ] s.indicator (μ[s.indicator f|m]) := by rw [Set.indicator_indicator, Set.inter_compl_self, Set.indicator_empty', add_zero] _ =ᵐ[μ] μ[s.indicator f|m] := by - refine (condexp_indicator_aux hs ?_).symm.trans ?_ + refine (condExp_indicator_aux hs ?_).symm.trans ?_ · exact indicator_ae_eq_restrict_compl (hm _ hs) · rw [Set.indicator_indicator, Set.inter_self] -theorem condexp_restrict_ae_eq_restrict (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] +@[deprecated (since := "2025-01-21")] alias condexp_indicator := condExp_indicator + +theorem condExp_restrict_ae_eq_restrict (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs_m : MeasurableSet[m] s) (hf_int : Integrable f μ) : (μ.restrict s)[f|m] =ᵐ[μ.restrict s] μ[f|m] := by have : SigmaFinite ((μ.restrict s).trim hm) := by rw [← restrict_trim hm _ hs_m]; infer_instance rw [ae_eq_restrict_iff_indicator_ae_eq (hm _ hs_m)] - refine EventuallyEq.trans ?_ (condexp_indicator hf_int hs_m) - refine ae_eq_condexp_of_forall_setIntegral_eq hm (hf_int.indicator (hm _ hs_m)) ?_ ?_ ?_ + refine EventuallyEq.trans ?_ (condExp_indicator hf_int hs_m) + refine ae_eq_condExp_of_forall_setIntegral_eq hm (hf_int.indicator (hm _ hs_m)) ?_ ?_ ?_ · intro t ht _ rw [← integrable_indicator_iff (hm _ ht), Set.indicator_indicator, Set.inter_comm, ← Set.indicator_indicator] @@ -121,22 +128,25 @@ theorem condexp_restrict_ae_eq_restrict (hm : m ≤ m0) [SigmaFinite (μ.trim hm rw [integrable_indicator_iff (hm _ hs_m), IntegrableOn] rw [integrable_indicator_iff (hm _ ht), IntegrableOn] at h_int_restrict ⊢ exact h_int_restrict - exact integrable_condexp.indicator (hm _ ht) + exact integrable_condExp.indicator (hm _ ht) · intro t ht _ calc ∫ x in t, s.indicator ((μ.restrict s)[f|m]) x ∂μ = ∫ x in t, ((μ.restrict s)[f|m]) x ∂μ.restrict s := by rw [integral_indicator (hm _ hs_m), Measure.restrict_restrict (hm _ hs_m), Measure.restrict_restrict (hm _ ht), Set.inter_comm] - _ = ∫ x in t, f x ∂μ.restrict s := setIntegral_condexp hm hf_int.integrableOn ht + _ = ∫ x in t, f x ∂μ.restrict s := setIntegral_condExp hm hf_int.integrableOn ht _ = ∫ x in t, s.indicator f x ∂μ := by rw [integral_indicator (hm _ hs_m), Measure.restrict_restrict (hm _ hs_m), Measure.restrict_restrict (hm _ ht), Set.inter_comm] - · exact (stronglyMeasurable_condexp.indicator hs_m).aeStronglyMeasurable' + · exact (stronglyMeasurable_condExp.indicator hs_m).aeStronglyMeasurable' + +@[deprecated (since := "2025-01-21")] +alias condexp_restrict_ae_eq_restrict := condExp_restrict_ae_eq_restrict /-- If the restriction to an `m`-measurable set `s` of a σ-algebra `m` is equal to the restriction to `s` of another σ-algebra `m₂` (hypothesis `hs`), then `μ[f | m] =ᵐ[μ.restrict s] μ[f | m₂]`. -/ -theorem condexp_ae_eq_restrict_of_measurableSpace_eq_on {m m₂ m0 : MeasurableSpace α} +theorem condExp_ae_eq_restrict_of_measurableSpace_eq_on {m m₂ m0 : MeasurableSpace α} {μ : Measure α} (hm : m ≤ m0) (hm₂ : m₂ ≤ m0) [SigmaFinite (μ.trim hm)] [SigmaFinite (μ.trim hm₂)] (hs_m : MeasurableSet[m] s) (hs : ∀ t, MeasurableSet[m] (s ∩ t) ↔ MeasurableSet[m₂] (s ∩ t)) : @@ -144,20 +154,20 @@ theorem condexp_ae_eq_restrict_of_measurableSpace_eq_on {m m₂ m0 : MeasurableS rw [ae_eq_restrict_iff_indicator_ae_eq (hm _ hs_m)] have hs_m₂ : MeasurableSet[m₂] s := by rwa [← Set.inter_univ s, ← hs Set.univ, Set.inter_univ] by_cases hf_int : Integrable f μ - swap; · simp_rw [condexp_undef hf_int]; rfl - refine ((condexp_indicator hf_int hs_m).symm.trans ?_).trans (condexp_indicator hf_int hs_m₂) + swap; · simp_rw [condExp_undef hf_int]; rfl + refine ((condExp_indicator hf_int hs_m).symm.trans ?_).trans (condExp_indicator hf_int hs_m₂) refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hm₂ - (fun s _ _ => integrable_condexp.integrableOn) - (fun s _ _ => integrable_condexp.integrableOn) ?_ ?_ - stronglyMeasurable_condexp.aeStronglyMeasurable' + (fun s _ _ => integrable_condExp.integrableOn) + (fun s _ _ => integrable_condExp.integrableOn) ?_ ?_ + stronglyMeasurable_condExp.aeStronglyMeasurable' swap - · have : StronglyMeasurable[m] (μ[s.indicator f|m]) := stronglyMeasurable_condexp + · have : StronglyMeasurable[m] (μ[s.indicator f|m]) := stronglyMeasurable_condExp refine this.aeStronglyMeasurable'.aeStronglyMeasurable'_of_measurableSpace_le_on hm hs_m (fun t => (hs t).mp) ?_ - exact condexp_ae_eq_restrict_zero hs_m.compl (indicator_ae_eq_restrict_compl (hm _ hs_m)) + exact condExp_ae_eq_restrict_zero hs_m.compl (indicator_ae_eq_restrict_compl (hm _ hs_m)) intro t ht _ have : ∫ x in t, (μ[s.indicator f|m]) x ∂μ = ∫ x in s ∩ t, (μ[s.indicator f|m]) x ∂μ := by - rw [← integral_add_compl (hm _ hs_m) integrable_condexp.integrableOn] + rw [← integral_add_compl (hm _ hs_m) integrable_condExp.integrableOn] suffices ∫ x in sᶜ, (μ[s.indicator f|m]) x ∂μ.restrict t = 0 by rw [this, add_zero, Measure.restrict_restrict (hm _ hs_m)] rw [Measure.restrict_restrict (MeasurableSet.compl (hm _ hs_m))] @@ -169,11 +179,15 @@ theorem condexp_ae_eq_restrict_of_measurableSpace_eq_on {m m₂ m0 : MeasurableS refine setIntegral_congr_ae (hm₂ _ ht) ?_ filter_upwards [this] with x hx _ using hx _ = 0 := integral_zero _ _ - refine condexp_ae_eq_restrict_zero hs_m.compl ?_ + refine condExp_ae_eq_restrict_zero hs_m.compl ?_ exact indicator_ae_eq_restrict_compl (hm _ hs_m) have hst_m : MeasurableSet[m] (s ∩ t) := (hs _).mpr (hs_m₂.inter ht) - simp_rw [this, setIntegral_condexp hm₂ (hf_int.indicator (hm _ hs_m)) ht, - setIntegral_condexp hm (hf_int.indicator (hm _ hs_m)) hst_m, integral_indicator (hm _ hs_m), + simp_rw [this, setIntegral_condExp hm₂ (hf_int.indicator (hm _ hs_m)) ht, + setIntegral_condExp hm (hf_int.indicator (hm _ hs_m)) hst_m, integral_indicator (hm _ hs_m), Measure.restrict_restrict (hm _ hs_m), ← Set.inter_assoc, Set.inter_self] +@[deprecated (since := "2025-01-21")] +alias condexp_ae_eq_restrict_of_measurableSpace_eq_on := + condExp_ae_eq_restrict_of_measurableSpace_eq_on + end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index 8e05909283442..18ca101613008 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -15,11 +15,11 @@ This file proves some results regarding the conditional expectation of real-valu ## Main results -* `MeasureTheory.rnDeriv_ae_eq_condexp`: the conditional expectation `μ[f | m]` is equal to the +* `MeasureTheory.rnDeriv_ae_eq_condExp`: the conditional expectation `μ[f | m]` is equal to the Radon-Nikodym derivative of `fμ` restricted on `m` with respect to `μ` restricted on `m`. -* `MeasureTheory.Integrable.uniformIntegrable_condexp`: the conditional expectation of a function +* `MeasureTheory.Integrable.uniformIntegrable_condExp`: the conditional expectation of a function form a uniformly integrable class. -* `MeasureTheory.condexp_mul_of_stronglyMeasurable_left`: the pull-out property of the conditional +* `MeasureTheory.condExp_mul_of_stronglyMeasurable_left`: the pull-out property of the conditional expectation. -/ @@ -35,10 +35,10 @@ namespace MeasureTheory variable {α : Type*} {m m0 : MeasurableSpace α} {μ : Measure α} -theorem rnDeriv_ae_eq_condexp {hm : m ≤ m0} [hμm : SigmaFinite (μ.trim hm)] {f : α → ℝ} +theorem rnDeriv_ae_eq_condExp {hm : m ≤ m0} [hμm : SigmaFinite (μ.trim hm)] {f : α → ℝ} (hf : Integrable f μ) : SignedMeasure.rnDeriv ((μ.withDensityᵥ f).trim hm) (μ.trim hm) =ᵐ[μ] μ[f|m] := by - refine ae_eq_condexp_of_forall_setIntegral_eq hm hf ?_ ?_ ?_ + refine ae_eq_condExp_of_forall_setIntegral_eq hm hf ?_ ?_ ?_ · exact fun _ _ _ => (integrable_of_integrable_trim hm (SignedMeasure.integrable_rnDeriv ((μ.withDensityᵥ f).trim hm) (μ.trim hm))).integrableOn · intro s hs _ @@ -51,104 +51,118 @@ theorem rnDeriv_ae_eq_condexp {hm : m ≤ m0} [hμm : SigmaFinite (μ.trim hm)] exact (SignedMeasure.measurable_rnDeriv _ _).stronglyMeasurable · exact (SignedMeasure.measurable_rnDeriv _ _).stronglyMeasurable.aeStronglyMeasurable' +@[deprecated (since := "2025-01-21")] alias rnDeriv_ae_eq_condexp := rnDeriv_ae_eq_condExp + -- TODO: the following couple of lemmas should be generalized and proved using Jensen's inequality -- for the conditional expectation (not in mathlib yet) . -theorem eLpNorm_one_condexp_le_eLpNorm (f : α → ℝ) : eLpNorm (μ[f|m]) 1 μ ≤ eLpNorm f 1 μ := by +theorem eLpNorm_one_condExp_le_eLpNorm (f : α → ℝ) : eLpNorm (μ[f|m]) 1 μ ≤ eLpNorm f 1 μ := by by_cases hf : Integrable f μ - swap; · rw [condexp_undef hf, eLpNorm_zero]; exact zero_le _ + swap; · rw [condExp_undef hf, eLpNorm_zero]; exact zero_le _ by_cases hm : m ≤ m0 - swap; · rw [condexp_of_not_le hm, eLpNorm_zero]; exact zero_le _ + swap; · rw [condExp_of_not_le hm, eLpNorm_zero]; exact zero_le _ by_cases hsig : SigmaFinite (μ.trim hm) - swap; · rw [condexp_of_not_sigmaFinite hm hsig, eLpNorm_zero]; exact zero_le _ + swap; · rw [condExp_of_not_sigmaFinite hm hsig, eLpNorm_zero]; exact zero_le _ calc eLpNorm (μ[f|m]) 1 μ ≤ eLpNorm (μ[(|f|)|m]) 1 μ := by refine eLpNorm_mono_ae ?_ - filter_upwards [condexp_mono hf hf.abs + filter_upwards [condExp_mono hf hf.abs (ae_of_all μ (fun x => le_abs_self (f x) : ∀ x, f x ≤ |f x|)), - EventuallyLE.trans (condexp_neg f).symm.le - (condexp_mono hf.neg hf.abs + EventuallyLE.trans (condExp_neg f).symm.le + (condExp_mono hf.neg hf.abs (ae_of_all μ (fun x => neg_le_abs (f x) : ∀ x, -f x ≤ |f x|)))] with x hx₁ hx₂ exact abs_le_abs hx₁ hx₂ _ = eLpNorm f 1 μ := by rw [eLpNorm_one_eq_lintegral_nnnorm, eLpNorm_one_eq_lintegral_nnnorm, - ← ENNReal.toReal_eq_toReal (hasFiniteIntegral_iff_nnnorm.mp integrable_condexp.2).ne + ← ENNReal.toReal_eq_toReal (hasFiniteIntegral_iff_nnnorm.mp integrable_condExp.2).ne (hasFiniteIntegral_iff_nnnorm.mp hf.2).ne, ← integral_norm_eq_lintegral_nnnorm - (stronglyMeasurable_condexp.mono hm).aestronglyMeasurable, + (stronglyMeasurable_condExp.mono hm).aestronglyMeasurable, ← integral_norm_eq_lintegral_nnnorm hf.1] simp_rw [Real.norm_eq_abs] - rw (config := {occs := .pos [2]}) [← integral_condexp hm] + rw (config := {occs := .pos [2]}) [← integral_condExp hm] refine integral_congr_ae ?_ have : 0 ≤ᵐ[μ] μ[(|f|)|m] := by - rw [← condexp_zero] - exact condexp_mono (integrable_zero _ _ _) hf.abs + rw [← condExp_zero] + exact condExp_mono (integrable_zero _ _ _) hf.abs (ae_of_all μ (fun x => abs_nonneg (f x) : ∀ x, 0 ≤ |f x|)) filter_upwards [this] with x hx exact abs_eq_self.2 hx +@[deprecated (since := "2025-01-21")] +alias eLpNorm_one_condexp_le_eLpNorm := eLpNorm_one_condExp_le_eLpNorm + @[deprecated (since := "2024-07-27")] -alias snorm_one_condexp_le_snorm := eLpNorm_one_condexp_le_eLpNorm +alias snorm_one_condExp_le_snorm := eLpNorm_one_condExp_le_eLpNorm + +@[deprecated (since := "2025-01-21")] alias snorm_one_condexp_le_snorm := snorm_one_condExp_le_snorm -theorem integral_abs_condexp_le (f : α → ℝ) : ∫ x, |(μ[f|m]) x| ∂μ ≤ ∫ x, |f x| ∂μ := by +theorem integral_abs_condExp_le (f : α → ℝ) : ∫ x, |(μ[f|m]) x| ∂μ ≤ ∫ x, |f x| ∂μ := by by_cases hm : m ≤ m0 swap - · simp_rw [condexp_of_not_le hm, Pi.zero_apply, abs_zero, integral_zero] + · simp_rw [condExp_of_not_le hm, Pi.zero_apply, abs_zero, integral_zero] positivity by_cases hfint : Integrable f μ swap - · simp only [condexp_undef hfint, Pi.zero_apply, abs_zero, integral_const, Algebra.id.smul_eq_mul, + · simp only [condExp_undef hfint, Pi.zero_apply, abs_zero, integral_const, Algebra.id.smul_eq_mul, mul_zero] positivity rw [integral_eq_lintegral_of_nonneg_ae, integral_eq_lintegral_of_nonneg_ae] · apply ENNReal.toReal_mono <;> simp_rw [← Real.norm_eq_abs, ofReal_norm_eq_coe_nnnorm] · exact hfint.2.ne · rw [← eLpNorm_one_eq_lintegral_nnnorm, ← eLpNorm_one_eq_lintegral_nnnorm] - exact eLpNorm_one_condexp_le_eLpNorm _ + exact eLpNorm_one_condExp_le_eLpNorm _ · filter_upwards with x using abs_nonneg _ · simp_rw [← Real.norm_eq_abs] exact hfint.1.norm · filter_upwards with x using abs_nonneg _ · simp_rw [← Real.norm_eq_abs] - exact (stronglyMeasurable_condexp.mono hm).aestronglyMeasurable.norm + exact (stronglyMeasurable_condExp.mono hm).aestronglyMeasurable.norm -theorem setIntegral_abs_condexp_le {s : Set α} (hs : MeasurableSet[m] s) (f : α → ℝ) : +@[deprecated (since := "2025-01-21")] alias integral_abs_condexp_le := integral_abs_condExp_le + +theorem setIntegral_abs_condExp_le {s : Set α} (hs : MeasurableSet[m] s) (f : α → ℝ) : ∫ x in s, |(μ[f|m]) x| ∂μ ≤ ∫ x in s, |f x| ∂μ := by by_cases hnm : m ≤ m0 swap - · simp_rw [condexp_of_not_le hnm, Pi.zero_apply, abs_zero, integral_zero] + · simp_rw [condExp_of_not_le hnm, Pi.zero_apply, abs_zero, integral_zero] positivity by_cases hfint : Integrable f μ swap - · simp only [condexp_undef hfint, Pi.zero_apply, abs_zero, integral_const, Algebra.id.smul_eq_mul, + · simp only [condExp_undef hfint, Pi.zero_apply, abs_zero, integral_const, Algebra.id.smul_eq_mul, mul_zero] positivity have : ∫ x in s, |(μ[f|m]) x| ∂μ = ∫ x, |(μ[s.indicator f|m]) x| ∂μ := by rw [← integral_indicator (hnm _ hs)] refine integral_congr_ae ?_ have : (fun x => |(μ[s.indicator f|m]) x|) =ᵐ[μ] fun x => |s.indicator (μ[f|m]) x| := - (condexp_indicator hfint hs).fun_comp abs + (condExp_indicator hfint hs).fun_comp abs refine EventuallyEq.trans (Eventually.of_forall fun x => ?_) this.symm rw [← Real.norm_eq_abs, norm_indicator_eq_indicator_norm] simp only [Real.norm_eq_abs] rw [this, ← integral_indicator (hnm _ hs)] - refine (integral_abs_condexp_le _).trans + refine (integral_abs_condExp_le _).trans (le_of_eq <| integral_congr_ae <| Eventually.of_forall fun x => ?_) simp_rw [← Real.norm_eq_abs, norm_indicator_eq_indicator_norm] +@[deprecated (since := "2025-01-21")] alias setIntegral_abs_condexp_le := setIntegral_abs_condExp_le + @[deprecated (since := "2024-04-17")] -alias set_integral_abs_condexp_le := setIntegral_abs_condexp_le +alias set_integral_abs_condExp_le := setIntegral_abs_condExp_le + +@[deprecated (since := "2025-01-21")] +alias set_integral_abs_condexp_le := set_integral_abs_condExp_le /-- If the real valued function `f` is bounded almost everywhere by `R`, then so is its conditional expectation. -/ -theorem ae_bdd_condexp_of_ae_bdd {R : ℝ≥0} {f : α → ℝ} (hbdd : ∀ᵐ x ∂μ, |f x| ≤ R) : +theorem ae_bdd_condExp_of_ae_bdd {R : ℝ≥0} {f : α → ℝ} (hbdd : ∀ᵐ x ∂μ, |f x| ≤ R) : ∀ᵐ x ∂μ, |(μ[f|m]) x| ≤ R := by by_cases hnm : m ≤ m0 swap - · simp_rw [condexp_of_not_le hnm, Pi.zero_apply, abs_zero] + · simp_rw [condExp_of_not_le hnm, Pi.zero_apply, abs_zero] exact Eventually.of_forall fun _ => R.coe_nonneg by_cases hfint : Integrable f μ swap - · simp_rw [condexp_undef hfint] + · simp_rw [condExp_undef hfint] filter_upwards [hbdd] with x hx rw [Pi.zero_apply, abs_zero] exact (abs_nonneg _).trans hx @@ -158,46 +172,48 @@ theorem ae_bdd_condexp_of_ae_bdd {R : ℝ≥0} {f : α → ℝ} (hbdd : ∀ᵐ x suffices (μ {x | ↑R < |(μ[f|m]) x|}).toReal * ↑R < (μ {x | ↑R < |(μ[f|m]) x|}).toReal * ↑R by exact this.ne rfl refine lt_of_lt_of_le (setIntegral_gt_gt R.coe_nonneg ?_ h.ne') ?_ - · exact integrable_condexp.abs.integrableOn - refine (setIntegral_abs_condexp_le ?_ _).trans ?_ + · exact integrable_condExp.abs.integrableOn + refine (setIntegral_abs_condExp_le ?_ _).trans ?_ · simp_rw [← Real.norm_eq_abs] exact @measurableSet_lt _ _ _ _ _ m _ _ _ _ _ measurable_const - stronglyMeasurable_condexp.norm.measurable + stronglyMeasurable_condExp.norm.measurable simp only [← smul_eq_mul, ← setIntegral_const, NNReal.val_eq_coe, RCLike.ofReal_real_eq_id, _root_.id] refine setIntegral_mono_ae hfint.abs.integrableOn ?_ hbdd refine ⟨aestronglyMeasurable_const, lt_of_le_of_lt ?_ - (integrable_condexp.integrableOn : IntegrableOn (μ[f|m]) {x | ↑R < |(μ[f|m]) x|} μ).2⟩ + (integrable_condExp.integrableOn : IntegrableOn (μ[f|m]) {x | ↑R < |(μ[f|m]) x|} μ).2⟩ refine setLIntegral_mono - (stronglyMeasurable_condexp.mono hnm).measurable.nnnorm.coe_nnreal_ennreal fun x hx => ?_ + (stronglyMeasurable_condExp.mono hnm).measurable.nnnorm.coe_nnreal_ennreal fun x hx => ?_ rw [enorm_eq_nnnorm, enorm_eq_nnnorm, ENNReal.coe_le_coe, Real.nnnorm_of_nonneg R.coe_nonneg] exact Subtype.mk_le_mk.2 (le_of_lt hx) +@[deprecated (since := "2025-01-21")] alias ae_bdd_condexp_of_ae_bdd := ae_bdd_condExp_of_ae_bdd + /-- Given an integrable function `g`, the conditional expectations of `g` with respect to a sequence of sub-σ-algebras is uniformly integrable. -/ -theorem Integrable.uniformIntegrable_condexp {ι : Type*} [IsFiniteMeasure μ] {g : α → ℝ} +theorem Integrable.uniformIntegrable_condExp {ι : Type*} [IsFiniteMeasure μ] {g : α → ℝ} (hint : Integrable g μ) {ℱ : ι → MeasurableSpace α} (hℱ : ∀ i, ℱ i ≤ m0) : UniformIntegrable (fun i => μ[g|ℱ i]) 1 μ := by let A : MeasurableSpace α := m0 have hmeas : ∀ n, ∀ C, MeasurableSet {x | C ≤ ‖(μ[g|ℱ n]) x‖₊} := fun n C => - measurableSet_le measurable_const (stronglyMeasurable_condexp.mono (hℱ n)).measurable.nnnorm + measurableSet_le measurable_const (stronglyMeasurable_condExp.mono (hℱ n)).measurable.nnnorm have hg : Memℒp g 1 μ := memℒp_one_iff_integrable.2 hint refine uniformIntegrable_of le_rfl ENNReal.one_ne_top - (fun n => (stronglyMeasurable_condexp.mono (hℱ n)).aestronglyMeasurable) fun ε hε => ?_ + (fun n => (stronglyMeasurable_condExp.mono (hℱ n)).aestronglyMeasurable) fun ε hε => ?_ by_cases hne : eLpNorm g 1 μ = 0 · rw [eLpNorm_eq_zero_iff hg.1 one_ne_zero] at hne refine ⟨0, fun n => (le_of_eq <| - (eLpNorm_eq_zero_iff ((stronglyMeasurable_condexp.mono (hℱ n)).aestronglyMeasurable.indicator + (eLpNorm_eq_zero_iff ((stronglyMeasurable_condExp.mono (hℱ n)).aestronglyMeasurable.indicator (hmeas n 0)) one_ne_zero).2 ?_).trans (zero_le _)⟩ - filter_upwards [condexp_congr_ae (m := ℱ n) hne] with x hx - simp only [zero_le', Set.setOf_true, Set.indicator_univ, Pi.zero_apply, hx, condexp_zero] + filter_upwards [condExp_congr_ae (m := ℱ n) hne] with x hx + simp only [zero_le', Set.setOf_true, Set.indicator_univ, Pi.zero_apply, hx, condExp_zero] obtain ⟨δ, hδ, h⟩ := hg.eLpNorm_indicator_le le_rfl ENNReal.one_ne_top hε set C : ℝ≥0 := ⟨δ, hδ.le⟩⁻¹ * (eLpNorm g 1 μ).toNNReal with hC have hCpos : 0 < C := mul_pos (inv_pos.2 hδ) (ENNReal.toNNReal_pos hne hg.eLpNorm_lt_top.ne) have : ∀ n, μ {x : α | C ≤ ‖(μ[g|ℱ n]) x‖₊} ≤ ENNReal.ofReal δ := by intro n have := mul_meas_ge_le_pow_eLpNorm' μ one_ne_zero ENNReal.one_ne_top - ((stronglyMeasurable_condexp (m := ℱ n) (μ := μ) (f := g)).mono (hℱ n)).aestronglyMeasurable C + ((stronglyMeasurable_condExp (m := ℱ n) (μ := μ) (f := g)).mono (hℱ n)).aestronglyMeasurable C rw [ENNReal.one_toReal, ENNReal.rpow_one, ENNReal.rpow_one, mul_comm, ← ENNReal.le_div_iff_mul_le (Or.inl (ENNReal.coe_ne_zero.2 hCpos.ne')) (Or.inl ENNReal.coe_lt_top.ne)] at this @@ -208,19 +224,22 @@ theorem Integrable.uniformIntegrable_condexp {ι : Type*} [IsFiniteMeasure μ] { hC, Nonneg.inv_mk, ENNReal.coe_mul, ENNReal.coe_toNNReal hg.eLpNorm_lt_top.ne, ← mul_assoc, ← ENNReal.ofReal_eq_coe_nnreal, ← ENNReal.ofReal_mul hδ.le, mul_inv_cancel₀ hδ.ne', ENNReal.ofReal_one, one_mul] - exact eLpNorm_one_condexp_le_eLpNorm _ + exact eLpNorm_one_condExp_le_eLpNorm _ refine ⟨C, fun n => le_trans ?_ (h {x : α | C ≤ ‖(μ[g|ℱ n]) x‖₊} (hmeas n C) (this n))⟩ have hmeasℱ : MeasurableSet[ℱ n] {x : α | C ≤ ‖(μ[g|ℱ n]) x‖₊} := @measurableSet_le _ _ _ _ _ (ℱ n) _ _ _ _ _ measurable_const - (@Measurable.nnnorm _ _ _ _ _ (ℱ n) _ stronglyMeasurable_condexp.measurable) - rw [← eLpNorm_congr_ae (condexp_indicator hint hmeasℱ)] - exact eLpNorm_one_condexp_le_eLpNorm _ + (@Measurable.nnnorm _ _ _ _ _ (ℱ n) _ stronglyMeasurable_condExp.measurable) + rw [← eLpNorm_congr_ae (condExp_indicator hint hmeasℱ)] + exact eLpNorm_one_condExp_le_eLpNorm _ + +@[deprecated (since := "2025-01-21")] +alias Integrable.uniformIntegrable_condexp := Integrable.uniformIntegrable_condExp section PullOut -- TODO: this section could be generalized beyond multiplication, to any bounded bilinear map. /-- Auxiliary lemma for `condexp_mul_of_stronglyMeasurable_left`. -/ -theorem condexp_stronglyMeasurable_simpleFunc_mul (hm : m ≤ m0) (f : @SimpleFunc α m ℝ) {g : α → ℝ} +theorem condExp_stronglyMeasurable_simpleFunc_mul (hm : m ≤ m0) (f : @SimpleFunc α m ℝ) {g : α → ℝ} (hg : Integrable g μ) : μ[(f * g : α → ℝ)|m] =ᵐ[μ] f * μ[g|m] := by have : ∀ (s c) (f : α → ℝ), Set.indicator s (Function.const α c) * f = s.indicator (c • f) := by intro s c f @@ -236,19 +255,22 @@ theorem condexp_stronglyMeasurable_simpleFunc_mul (hm : m ≤ m0) (f : @SimpleFu classical simp only [@SimpleFunc.const_zero _ _ m, @SimpleFunc.coe_piecewise _ _ m, @SimpleFunc.coe_const _ _ m, @SimpleFunc.coe_zero _ _ m, Set.piecewise_eq_indicator] rw [this, this] - refine (condexp_indicator (hg.smul c) hs).trans ?_ - filter_upwards [condexp_smul (m := m) (m0 := m0) c g] with x hx + refine (condExp_indicator (hg.smul c) hs).trans ?_ + filter_upwards [condExp_smul (m := m) (m0 := m0) c g] with x hx classical simp_rw [Set.indicator_apply, hx] · have h_add := @SimpleFunc.coe_add _ _ m _ g₁ g₂ calc μ[⇑(g₁ + g₂) * g|m] =ᵐ[μ] μ[(⇑g₁ + ⇑g₂) * g|m] := by - refine condexp_congr_ae (EventuallyEq.mul ?_ EventuallyEq.rfl); rw [h_add] + refine condExp_congr_ae (EventuallyEq.mul ?_ EventuallyEq.rfl); rw [h_add] _ =ᵐ[μ] μ[⇑g₁ * g|m] + μ[⇑g₂ * g|m] := by - rw [add_mul]; exact condexp_add (hg.simpleFunc_mul' hm _) (hg.simpleFunc_mul' hm _) + rw [add_mul]; exact condExp_add (hg.simpleFunc_mul' hm _) (hg.simpleFunc_mul' hm _) _ =ᵐ[μ] ⇑g₁ * μ[g|m] + ⇑g₂ * μ[g|m] := EventuallyEq.add h_eq₁ h_eq₂ _ =ᵐ[μ] ⇑(g₁ + g₂) * μ[g|m] := by rw [h_add, add_mul] -theorem condexp_stronglyMeasurable_mul_of_bound (hm : m ≤ m0) [IsFiniteMeasure μ] {f g : α → ℝ} +@[deprecated (since := "2025-01-21")] +alias condexp_stronglyMeasurable_simpleFunc_mul := condExp_stronglyMeasurable_simpleFunc_mul + +theorem condExp_stronglyMeasurable_mul_of_bound (hm : m ≤ m0) [IsFiniteMeasure μ] {f g : α → ℝ} (hf : StronglyMeasurable[m] f) (hg : Integrable g μ) (c : ℝ) (hf_bound : ∀ᵐ x ∂μ, ‖f x‖ ≤ c) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by let fs := hf.approxBounded c @@ -262,14 +284,14 @@ theorem condexp_stronglyMeasurable_mul_of_bound (hm : m ≤ m0) [IsFiniteMeasure exact (norm_nonneg _).trans hx have hfs_bound : ∀ n x, ‖fs n x‖ ≤ c := hf.norm_approxBounded_le hc have : μ[f * μ[g|m]|m] = f * μ[g|m] := by - refine condexp_of_stronglyMeasurable hm (hf.mul stronglyMeasurable_condexp) ?_ - exact integrable_condexp.bdd_mul' (hf.mono hm).aestronglyMeasurable hf_bound + refine condExp_of_stronglyMeasurable hm (hf.mul stronglyMeasurable_condExp) ?_ + exact integrable_condExp.bdd_mul' (hf.mono hm).aestronglyMeasurable hf_bound rw [← this] - refine tendsto_condexp_unique (fun n x => fs n x * g x) (fun n x => fs n x * (μ[g|m]) x) (f * g) + refine tendsto_condExp_unique (fun n x => fs n x * g x) (fun n x => fs n x * (μ[g|m]) x) (f * g) (f * μ[g|m]) ?_ ?_ ?_ ?_ (c * ‖g ·‖) ?_ (c * ‖(μ[g|m]) ·‖) ?_ ?_ ?_ ?_ · exact fun n => hg.bdd_mul' ((SimpleFunc.stronglyMeasurable (fs n)).mono hm).aestronglyMeasurable (Eventually.of_forall (hfs_bound n)) - · exact fun n => integrable_condexp.bdd_mul' + · exact fun n => integrable_condExp.bdd_mul' ((SimpleFunc.stronglyMeasurable (fs n)).mono hm).aestronglyMeasurable (Eventually.of_forall (hfs_bound n)) · filter_upwards [hfs_tendsto] with x hx @@ -277,38 +299,44 @@ theorem condexp_stronglyMeasurable_mul_of_bound (hm : m ≤ m0) [IsFiniteMeasure · filter_upwards [hfs_tendsto] with x hx exact hx.mul tendsto_const_nhds · exact hg.norm.const_mul c - · exact integrable_condexp.norm.const_mul c + · exact integrable_condExp.norm.const_mul c · refine fun n => Eventually.of_forall fun x => ?_ exact (norm_mul_le _ _).trans (mul_le_mul_of_nonneg_right (hfs_bound n x) (norm_nonneg _)) · refine fun n => Eventually.of_forall fun x => ?_ exact (norm_mul_le _ _).trans (mul_le_mul_of_nonneg_right (hfs_bound n x) (norm_nonneg _)) · intro n simp_rw [← Pi.mul_apply] - refine (condexp_stronglyMeasurable_simpleFunc_mul hm _ hg).trans ?_ - rw [condexp_of_stronglyMeasurable hm - ((SimpleFunc.stronglyMeasurable _).mul stronglyMeasurable_condexp) _] - exact integrable_condexp.bdd_mul' + refine (condExp_stronglyMeasurable_simpleFunc_mul hm _ hg).trans ?_ + rw [condExp_of_stronglyMeasurable hm + ((SimpleFunc.stronglyMeasurable _).mul stronglyMeasurable_condExp) _] + exact integrable_condExp.bdd_mul' ((SimpleFunc.stronglyMeasurable (fs n)).mono hm).aestronglyMeasurable (Eventually.of_forall (hfs_bound n)) -theorem condexp_stronglyMeasurable_mul_of_bound₀ (hm : m ≤ m0) [IsFiniteMeasure μ] {f g : α → ℝ} +@[deprecated (since := "2025-01-21")] +alias condexp_stronglyMeasurable_mul_of_bound := condExp_stronglyMeasurable_mul_of_bound + +theorem condExp_stronglyMeasurable_mul_of_bound₀ (hm : m ≤ m0) [IsFiniteMeasure μ] {f g : α → ℝ} (hf : AEStronglyMeasurable' m f μ) (hg : Integrable g μ) (c : ℝ) (hf_bound : ∀ᵐ x ∂μ, ‖f x‖ ≤ c) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by have : μ[f * g|m] =ᵐ[μ] μ[hf.mk f * g|m] := - condexp_congr_ae (EventuallyEq.mul hf.ae_eq_mk EventuallyEq.rfl) + condExp_congr_ae (EventuallyEq.mul hf.ae_eq_mk EventuallyEq.rfl) refine this.trans ?_ have : f * μ[g|m] =ᵐ[μ] hf.mk f * μ[g|m] := EventuallyEq.mul hf.ae_eq_mk EventuallyEq.rfl refine EventuallyEq.trans ?_ this.symm - refine condexp_stronglyMeasurable_mul_of_bound hm hf.stronglyMeasurable_mk hg c ?_ + refine condExp_stronglyMeasurable_mul_of_bound hm hf.stronglyMeasurable_mk hg c ?_ filter_upwards [hf_bound, hf.ae_eq_mk] with x hxc hx_eq rwa [← hx_eq] +@[deprecated (since := "2025-01-21")] +alias condexp_stronglyMeasurable_mul_of_bound₀ := condExp_stronglyMeasurable_mul_of_bound₀ + /-- Pull-out property of the conditional expectation. -/ -theorem condexp_mul_of_stronglyMeasurable_left {f g : α → ℝ} (hf : StronglyMeasurable[m] f) +theorem condExp_mul_of_stronglyMeasurable_left {f g : α → ℝ} (hf : StronglyMeasurable[m] f) (hfg : Integrable (f * g) μ) (hg : Integrable g μ) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by - by_cases hm : m ≤ m0; swap; · simp_rw [condexp_of_not_le hm]; rw [mul_zero] + by_cases hm : m ≤ m0; swap; · simp_rw [condExp_of_not_le hm]; rw [mul_zero] by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condexp_of_not_sigmaFinite hm hμm]; rw [mul_zero] + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rw [mul_zero] haveI : SigmaFinite (μ.trim hm) := hμm obtain ⟨sets, sets_prop, h_univ⟩ := hf.exists_spanning_measurableSet_norm_le hm μ simp_rw [forall_and] at sets_prop @@ -322,50 +350,50 @@ theorem condexp_mul_of_stronglyMeasurable_left {f g : α → ℝ} (hf : Strongly exact hx i hi refine fun n => ae_imp_of_ae_restrict ?_ suffices (μ.restrict (sets n))[f * g|m] =ᵐ[μ.restrict (sets n)] f * (μ.restrict (sets n))[g|m] by - refine (condexp_restrict_ae_eq_restrict hm (h_meas n) hfg).symm.trans ?_ - exact this.trans (EventuallyEq.rfl.mul (condexp_restrict_ae_eq_restrict hm (h_meas n) hg)) + refine (condExp_restrict_ae_eq_restrict hm (h_meas n) hfg).symm.trans ?_ + exact this.trans (EventuallyEq.rfl.mul (condExp_restrict_ae_eq_restrict hm (h_meas n) hg)) suffices (μ.restrict (sets n))[(sets n).indicator f * g|m] =ᵐ[μ.restrict (sets n)] (sets n).indicator f * (μ.restrict (sets n))[g|m] by refine EventuallyEq.trans ?_ (this.trans ?_) · exact - condexp_congr_ae ((indicator_ae_eq_restrict <| hm _ <| h_meas n).symm.mul EventuallyEq.rfl) + condExp_congr_ae ((indicator_ae_eq_restrict <| hm _ <| h_meas n).symm.mul EventuallyEq.rfl) · exact (indicator_ae_eq_restrict <| hm _ <| h_meas n).mul EventuallyEq.rfl have : IsFiniteMeasure (μ.restrict (sets n)) := by constructor rw [Measure.restrict_apply_univ] exact h_finite n - refine condexp_stronglyMeasurable_mul_of_bound hm (hf.indicator (h_meas n)) hg.integrableOn n ?_ + refine condExp_stronglyMeasurable_mul_of_bound hm (hf.indicator (h_meas n)) hg.integrableOn n ?_ filter_upwards with x by_cases hxs : x ∈ sets n · simpa only [hxs, Set.indicator_of_mem] using h_norm n x hxs · simp only [hxs, Set.indicator_of_not_mem, not_false_iff, _root_.norm_zero, Nat.cast_nonneg] @[deprecated (since := "2025-01-22")] -alias condexp_stronglyMeasurable_mul := condexp_mul_of_stronglyMeasurable_left +alias condexp_stronglyMeasurable_mul := condExp_mul_of_stronglyMeasurable_left /-- Pull-out property of the conditional expectation. -/ -lemma condexp_mul_of_stronglyMeasurable_right {f g : α → ℝ} (hg : StronglyMeasurable[m] g) +lemma condExp_mul_of_stronglyMeasurable_right {f g : α → ℝ} (hg : StronglyMeasurable[m] g) (hfg : Integrable (f * g) μ) (hf : Integrable f μ) : μ[f * g | m] =ᵐ[μ] μ[f | m] * g := by - simpa [mul_comm] using condexp_mul_of_stronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf + simpa [mul_comm] using condExp_mul_of_stronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf /-- Pull-out property of the conditional expectation. -/ -theorem condexp_mul_of_aestronglyMeasurable_left {f g : α → ℝ} (hf : AEStronglyMeasurable' m f μ) +theorem condExp_mul_of_aestronglyMeasurable_left {f g : α → ℝ} (hf : AEStronglyMeasurable' m f μ) (hfg : Integrable (f * g) μ) (hg : Integrable g μ) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by have : μ[f * g|m] =ᵐ[μ] μ[hf.mk f * g|m] := - condexp_congr_ae (hf.ae_eq_mk.mul EventuallyEq.rfl) + condExp_congr_ae (hf.ae_eq_mk.mul EventuallyEq.rfl) refine this.trans ?_ have : f * μ[g|m] =ᵐ[μ] hf.mk f * μ[g|m] := hf.ae_eq_mk.mul EventuallyEq.rfl - refine (condexp_mul_of_stronglyMeasurable_left hf.stronglyMeasurable_mk ?_ hg).trans this.symm + refine (condExp_mul_of_stronglyMeasurable_left hf.stronglyMeasurable_mk ?_ hg).trans this.symm refine (integrable_congr ?_).mp hfg exact hf.ae_eq_mk.mul EventuallyEq.rfl @[deprecated (since := "2025-01-22")] -alias condexp_stronglyMeasurable_mul₀ := condexp_mul_of_aestronglyMeasurable_left +alias condexp_stronglyMeasurable_mul₀ := condExp_mul_of_aestronglyMeasurable_left /-- Pull-out property of the conditional expectation. -/ -lemma condexp_mul_of_aestronglyMeasurable_right {f g : α → ℝ} (hg : AEStronglyMeasurable' m g μ) +lemma condExp_mul_of_aestronglyMeasurable_right {f g : α → ℝ} (hg : AEStronglyMeasurable' m g μ) (hfg : Integrable (f * g) μ) (hf : Integrable f μ) : μ[f * g | m] =ᵐ[μ] μ[f | m] * g := by - simpa [mul_comm] using condexp_mul_of_aestronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf + simpa [mul_comm] using condExp_mul_of_aestronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf end PullOut diff --git a/Mathlib/Probability/BorelCantelli.lean b/Mathlib/Probability/BorelCantelli.lean index c94f855abd159..68d93fc17b615 100644 --- a/Mathlib/Probability/BorelCantelli.lean +++ b/Mathlib/Probability/BorelCantelli.lean @@ -43,21 +43,28 @@ theorem iIndepFun.indep_comap_natural_of_lt (hf : ∀ i, StronglyMeasurable (f i (⨆ k ∈ {k | k ≤ i}, MeasurableSpace.comap (f k) mβ) μ by rwa [iSup_singleton] at this exact indep_iSup_of_disjoint (fun k => (hf k).measurable.comap_le) hfi (by simpa) -theorem iIndepFun.condexp_natural_ae_eq_of_lt [SecondCountableTopology β] [CompleteSpace β] +theorem iIndepFun.condExp_natural_ae_eq_of_lt [SecondCountableTopology β] [CompleteSpace β] [NormedSpace ℝ β] (hf : ∀ i, StronglyMeasurable (f i)) (hfi : iIndepFun (fun _ => mβ) f μ) (hij : i < j) : μ[f j|Filtration.natural f hf i] =ᵐ[μ] fun _ => μ[f j] := by have : IsProbabilityMeasure μ := hfi.isProbabilityMeasure - exact condexp_indep_eq (hf j).measurable.comap_le (Filtration.le _ _) + exact condExp_indep_eq (hf j).measurable.comap_le (Filtration.le _ _) (comap_measurable <| f j).stronglyMeasurable (hfi.indep_comap_natural_of_lt hf hij) -theorem iIndepSet.condexp_indicator_filtrationOfSet_ae_eq (hsm : ∀ n, MeasurableSet (s n)) +@[deprecated (since := "2025-01-21")] +alias iIndepFun.condexp_natural_ae_eq_of_lt := iIndepFun.condExp_natural_ae_eq_of_lt + +theorem iIndepSet.condExp_indicator_filtrationOfSet_ae_eq (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s μ) (hij : i < j) : μ[(s j).indicator (fun _ => 1 : Ω → ℝ)|filtrationOfSet hsm i] =ᵐ[μ] fun _ => (μ (s j)).toReal := by rw [Filtration.filtrationOfSet_eq_natural (β := ℝ) hsm] - refine (iIndepFun.condexp_natural_ae_eq_of_lt _ hs.iIndepFun_indicator hij).trans ?_ + refine (iIndepFun.condExp_natural_ae_eq_of_lt _ hs.iIndepFun_indicator hij).trans ?_ simp only [integral_indicator_const _ (hsm _), Algebra.id.smul_eq_mul, mul_one]; rfl +@[deprecated (since := "2025-01-21")] +alias iIndepSet.condexp_indicator_filtrationOfSet_ae_eq := + iIndepSet.condExp_indicator_filtrationOfSet_ae_eq + open Filter /-- **The second Borel-Cantelli lemma**: Given a sequence of independent sets `(sₙ)` such that @@ -73,7 +80,7 @@ theorem measure_limsup_eq_one {s : ℕ → Set Ω} (hsm : ∀ n, MeasurableSet ( (μ[(s (k + 1)).indicator (1 : Ω → ℝ)|filtrationOfSet hsm k]) ω) atTop atTop} =ᵐ[μ] Set.univ by rw [measure_congr this, measure_univ] have : ∀ᵐ ω ∂μ, ∀ n, (μ[(s (n + 1)).indicator (1 : Ω → ℝ)|filtrationOfSet hsm n]) ω = _ := - ae_all_iff.2 fun n => hs.condexp_indicator_filtrationOfSet_ae_eq hsm n.lt_succ_self + ae_all_iff.2 fun n => hs.condExp_indicator_filtrationOfSet_ae_eq hsm n.lt_succ_self filter_upwards [this] with ω hω refine eq_true (?_ : Tendsto _ _ _) simp_rw [hω] diff --git a/Mathlib/Probability/ConditionalExpectation.lean b/Mathlib/Probability/ConditionalExpectation.lean index 18a5ab72ec167..f8e311d0628eb 100644 --- a/Mathlib/Probability/ConditionalExpectation.lean +++ b/Mathlib/Probability/ConditionalExpectation.lean @@ -16,7 +16,7 @@ the main conditional expectation file. ## Main result -* `MeasureTheory.condexp_indep_eq`: If `m₁, m₂` are independent σ-algebras and `f` is an +* `MeasureTheory.condExp_indep_eq`: If `m₁, m₂` are independent σ-algebras and `f` is an `m₁`-measurable function, then `𝔼[f | m₂] = 𝔼[f]` almost everywhere. -/ @@ -35,11 +35,11 @@ variable {Ω E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpac /-- If `m₁, m₂` are independent σ-algebras and `f` is `m₁`-measurable, then `𝔼[f | m₂] = 𝔼[f]` almost everywhere. -/ -theorem condexp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinite (μ.trim hle₂)] +theorem condExp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinite (μ.trim hle₂)] (hf : StronglyMeasurable[m₁] f) (hindp : Indep m₁ m₂ μ) : μ[f|m₂] =ᵐ[μ] fun _ => μ[f] := by by_cases hfint : Integrable f μ - swap; · rw [condexp_undef hfint, integral_undef hfint]; rfl - refine (ae_eq_condexp_of_forall_setIntegral_eq hle₂ hfint + swap; · rw [condExp_undef hfint, integral_undef hfint]; rfl + refine (ae_eq_condExp_of_forall_setIntegral_eq hle₂ hfint (fun s _ hs => integrableOn_const.2 (Or.inr hs)) (fun s hms hs => ?_) stronglyMeasurable_const.aeStronglyMeasurable').symm rw [setIntegral_const] @@ -74,4 +74,6 @@ theorem condexp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinit (setIntegral_congr_ae (hle₂ _ hms) _ : ∫ x in s, u x ∂μ = ∫ x in s, v x ∂μ)] filter_upwards [huv] with x hx _ using hx +@[deprecated (since := "2025-01-21")] alias condexp_indep_eq := condExp_indep_eq + end MeasureTheory diff --git a/Mathlib/Probability/Independence/Conditional.lean b/Mathlib/Probability/Independence/Conditional.lean index 6456d37f340cf..c0fa7ff20f56a 100644 --- a/Mathlib/Probability/Independence/Conditional.lean +++ b/Mathlib/Probability/Independence/Conditional.lean @@ -16,8 +16,8 @@ Two σ-algebras `m₁` and `m₂` are conditionally independent given a third σ `μ⟦t₁ ∩ t₂ | m'⟧ =ᵐ[μ] μ⟦t₁ | m'⟧ * μ⟦t₂ | m'⟧`. On standard Borel spaces, the conditional expectation with respect to `m'` defines a kernel -`ProbabilityTheory.condexpKernel`, and the definition above is equivalent to -`∀ᵐ ω ∂μ, condexpKernel μ m' ω (t₁ ∩ t₂) = condexpKernel μ m' ω t₁ * condexpKernel μ m' ω t₂`. +`ProbabilityTheory.condExpKernel`, and the definition above is equivalent to +`∀ᵐ ω ∂μ, condExpKernel μ m' ω (t₁ ∩ t₂) = condExpKernel μ m' ω t₁ * condExpKernel μ m' ω t₂`. We use this property as the definition of conditional independence. ## Main definitions @@ -46,7 +46,7 @@ as for a family, but without the starting `i`, for example `CondIndepFun` is the The definitions of conditional independence in this file are a particular case of independence with respect to a kernel and a measure, as defined in the file `Probability/Independence/Kernel.lean`. -The kernel used is `ProbabilityTheory.condexpKernel`. +The kernel used is `ProbabilityTheory.condExpKernel`. -/ @@ -71,14 +71,14 @@ See `ProbabilityTheory.iCondIndepSets_iff`. It will be used for families of pi_systems. -/ def iCondIndepSets (π : ι → Set (Set Ω)) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.iIndepSets π (condexpKernel μ m') (μ.trim hm') + Kernel.iIndepSets π (condExpKernel μ m') (μ.trim hm') /-- Two sets of sets `s₁, s₂` are conditionally independent given `m'` with respect to a measure `μ` if for any sets `t₁ ∈ s₁, t₂ ∈ s₂`, then `μ⟦t₁ ∩ t₂ | m'⟧ =ᵐ[μ] μ⟦t₁ | m'⟧ * μ⟦t₂ | m'⟧`. See `ProbabilityTheory.condIndepSets_iff`. -/ def CondIndepSets (s1 s2 : Set (Set Ω)) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.IndepSets s1 s2 (condexpKernel μ m') (μ.trim hm') + Kernel.IndepSets s1 s2 (condExpKernel μ m') (μ.trim hm') /-- A family of measurable space structures (i.e. of σ-algebras) is conditionally independent given `m'` with respect to a measure `μ` (typically defined on a finer σ-algebra) if the family of sets of @@ -89,7 +89,7 @@ any sets `f i_1 ∈ m i_1, ..., f i_n ∈ m i_n`, then See `ProbabilityTheory.iCondIndep_iff`. -/ def iCondIndep (m : ι → MeasurableSpace Ω) (μ : @Measure Ω mΩ := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.iIndep m (condexpKernel (mΩ := mΩ) μ m') (μ.trim hm') + Kernel.iIndep m (condExpKernel (mΩ := mΩ) μ m') (μ.trim hm') end @@ -100,7 +100,7 @@ See `ProbabilityTheory.condIndep_iff`. -/ def CondIndep (m' m₁ m₂ : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.Indep m₁ m₂ (condexpKernel μ m') (μ.trim hm') + Kernel.Indep m₁ m₂ (condExpKernel μ m') (μ.trim hm') section @@ -112,14 +112,14 @@ generate is conditionally independent. For a set `s`, the generated measurable s sets `∅, s, sᶜ, univ`. See `ProbabilityTheory.iCondIndepSet_iff`. -/ def iCondIndepSet (s : ι → Set Ω) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.iIndepSet s (condexpKernel μ m') (μ.trim hm') + Kernel.iIndepSet s (condExpKernel μ m') (μ.trim hm') /-- Two sets are conditionally independent if the two measurable space structures they generate are conditionally independent. For a set `s`, the generated measurable space structure has measurable sets `∅, s, sᶜ, univ`. See `ProbabilityTheory.condIndepSet_iff`. -/ def CondIndepSet (s t : Set Ω) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.IndepSet s t (condexpKernel μ m') (μ.trim hm') + Kernel.IndepSet s t (condExpKernel μ m') (μ.trim hm') /-- A family of functions defined on the same space `Ω` and taking values in possibly different spaces, each with a measurable space structure, is conditionally independent if the family of @@ -129,7 +129,7 @@ with codomain having measurable space structure `m`, the generated measurable sp See `ProbabilityTheory.iCondIndepFun_iff`. -/ def iCondIndepFun {β : ι → Type*} (m : ∀ x : ι, MeasurableSpace (β x)) (f : ∀ x : ι, Ω → β x) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.iIndepFun m f (condexpKernel μ m') (μ.trim hm') + Kernel.iIndepFun m f (condExpKernel μ m') (μ.trim hm') /-- Two functions are conditionally independent if the two measurable space structures they generate are conditionally independent. For a function `f` with codomain having measurable space structure @@ -137,7 +137,7 @@ are conditionally independent. For a function `f` with codomain having measurabl See `ProbabilityTheory.condIndepFun_iff`. -/ def CondIndepFun {β γ : Type*} [MeasurableSpace β] [MeasurableSpace γ] (f : Ω → β) (g : Ω → γ) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := - Kernel.IndepFun f g (condexpKernel μ m') (μ.trim hm') + Kernel.IndepFun f g (condExpKernel μ m') (μ.trim hm') end @@ -154,18 +154,18 @@ lemma iCondIndepSets_iff (π : ι → Set (Set Ω)) (hπ : ∀ i s (_hs : s ∈ μ⟦⋂ i ∈ s, f i | m'⟧ =ᵐ[μ] ∏ i ∈ s, (μ⟦f i | m'⟧) := by simp only [iCondIndepSets, Kernel.iIndepSets] have h_eq' : ∀ (s : Finset ι) (f : ι → Set Ω) (_H : ∀ i, i ∈ s → f i ∈ π i) i (_hi : i ∈ s), - (fun ω ↦ ENNReal.toReal (condexpKernel μ m' ω (f i))) =ᵐ[μ] μ⟦f i | m'⟧ := - fun s f H i hi ↦ condexpKernel_ae_eq_condexp hm' (hπ i (f i) (H i hi)) + (fun ω ↦ ENNReal.toReal (condExpKernel μ m' ω (f i))) =ᵐ[μ] μ⟦f i | m'⟧ := + fun s f H i hi ↦ condExpKernel_ae_eq_condExp hm' (hπ i (f i) (H i hi)) have h_eq : ∀ (s : Finset ι) (f : ι → Set Ω) (_H : ∀ i, i ∈ s → f i ∈ π i), ∀ᵐ ω ∂μ, - ∀ i ∈ s, ENNReal.toReal (condexpKernel μ m' ω (f i)) = (μ⟦f i | m'⟧) ω := by + ∀ i ∈ s, ENNReal.toReal (condExpKernel μ m' ω (f i)) = (μ⟦f i | m'⟧) ω := by intros s f H simp_rw [← Finset.mem_coe] rw [ae_ball_iff (Finset.countable_toSet s)] exact h_eq' s f H have h_inter_eq : ∀ (s : Finset ι) (f : ι → Set Ω) (_H : ∀ i, i ∈ s → f i ∈ π i), - (fun ω ↦ ENNReal.toReal (condexpKernel μ m' ω (⋂ i ∈ s, f i))) + (fun ω ↦ ENNReal.toReal (condExpKernel μ m' ω (⋂ i ∈ s, f i))) =ᵐ[μ] μ⟦⋂ i ∈ s, f i | m'⟧ := by - refine fun s f H ↦ condexpKernel_ae_eq_condexp hm' ?_ + refine fun s f H ↦ condExpKernel_ae_eq_condExp hm' ?_ exact MeasurableSet.biInter (Finset.countable_toSet _) (fun i hi ↦ hπ i _ (H i hi)) refine ⟨fun h s f hf ↦ ?_, fun h s f hf ↦ ?_⟩ <;> specialize h s hf · have h' := ae_eq_of_ae_eq_trim h @@ -173,15 +173,15 @@ lemma iCondIndepSets_iff (π : ι → Set (Set Ω)) (hπ : ∀ i s (_hs : s ∈ rw [← h_inter_eq, h', ENNReal.toReal_prod, Finset.prod_apply] exact Finset.prod_congr rfl h_eq · refine (ae_eq_trim_iff hm' ?_ ?_).mpr ?_ - · refine stronglyMeasurable_condexpKernel ?_ + · refine stronglyMeasurable_condExpKernel ?_ exact MeasurableSet.biInter (Finset.countable_toSet _) (fun i hi ↦ hπ i _ (hf i hi)) · refine Measurable.stronglyMeasurable ?_ - exact Finset.measurable_prod s (fun i hi ↦ measurable_condexpKernel (hπ i _ (hf i hi))) + exact Finset.measurable_prod s (fun i hi ↦ measurable_condExpKernel (hπ i _ (hf i hi))) filter_upwards [h_eq s f hf, h_inter_eq s f hf, h] with ω h_eq h_inter_eq h - have h_ne_top : condexpKernel μ m' ω (⋂ i ∈ s, f i) ≠ ∞ := - (measure_ne_top (condexpKernel μ m' ω) _) - have : (∏ i ∈ s, condexpKernel μ m' ω (f i)) ≠ ∞ := - ENNReal.prod_ne_top fun _ _ ↦ measure_ne_top (condexpKernel μ m' ω) _ + have h_ne_top : condExpKernel μ m' ω (⋂ i ∈ s, f i) ≠ ∞ := + (measure_ne_top (condExpKernel μ m' ω) _) + have : (∏ i ∈ s, condExpKernel μ m' ω (f i)) ≠ ∞ := + ENNReal.prod_ne_top fun _ _ ↦ measure_ne_top (condExpKernel μ m' ω) _ rw [← ENNReal.ofReal_toReal h_ne_top, h_inter_eq, h, Finset.prod_apply, ← ENNReal.ofReal_toReal this, ENNReal.toReal_prod] congr 1 @@ -192,28 +192,28 @@ lemma condIndepSets_iff (s1 s2 : Set (Set Ω)) (hs1 : ∀ s ∈ s1, MeasurableSe CondIndepSets m' hm' s1 s2 μ ↔ ∀ (t1 t2 : Set Ω) (_ : t1 ∈ s1) (_ : t2 ∈ s2), (μ⟦t1 ∩ t2 | m'⟧) =ᵐ[μ] (μ⟦t1 | m'⟧) * (μ⟦t2 | m'⟧) := by simp only [CondIndepSets, Kernel.IndepSets] - have hs1_eq : ∀ s ∈ s1, (fun ω ↦ ENNReal.toReal (condexpKernel μ m' ω s)) =ᵐ[μ] μ⟦s | m'⟧ := - fun s hs ↦ condexpKernel_ae_eq_condexp hm' (hs1 s hs) - have hs2_eq : ∀ s ∈ s2, (fun ω ↦ ENNReal.toReal (condexpKernel μ m' ω s)) =ᵐ[μ] μ⟦s | m'⟧ := - fun s hs ↦ condexpKernel_ae_eq_condexp hm' (hs2 s hs) - have hs12_eq : ∀ s ∈ s1, ∀ t ∈ s2, (fun ω ↦ ENNReal.toReal (condexpKernel μ m' ω (s ∩ t))) + have hs1_eq : ∀ s ∈ s1, (fun ω ↦ ENNReal.toReal (condExpKernel μ m' ω s)) =ᵐ[μ] μ⟦s | m'⟧ := + fun s hs ↦ condExpKernel_ae_eq_condExp hm' (hs1 s hs) + have hs2_eq : ∀ s ∈ s2, (fun ω ↦ ENNReal.toReal (condExpKernel μ m' ω s)) =ᵐ[μ] μ⟦s | m'⟧ := + fun s hs ↦ condExpKernel_ae_eq_condExp hm' (hs2 s hs) + have hs12_eq : ∀ s ∈ s1, ∀ t ∈ s2, (fun ω ↦ ENNReal.toReal (condExpKernel μ m' ω (s ∩ t))) =ᵐ[μ] μ⟦s ∩ t | m'⟧ := - fun s hs t ht ↦ condexpKernel_ae_eq_condexp hm' ((hs1 s hs).inter ((hs2 t ht))) + fun s hs t ht ↦ condExpKernel_ae_eq_condExp hm' ((hs1 s hs).inter ((hs2 t ht))) refine ⟨fun h s t hs ht ↦ ?_, fun h s t hs ht ↦ ?_⟩ <;> specialize h s t hs ht · have h' := ae_eq_of_ae_eq_trim h filter_upwards [hs1_eq s hs, hs2_eq t ht, hs12_eq s hs t ht, h'] with ω hs_eq ht_eq hst_eq h' rw [← hst_eq, Pi.mul_apply, ← hs_eq, ← ht_eq, h', ENNReal.toReal_mul] · refine (ae_eq_trim_iff hm' ?_ ?_).mpr ?_ - · exact stronglyMeasurable_condexpKernel ((hs1 s hs).inter ((hs2 t ht))) + · exact stronglyMeasurable_condExpKernel ((hs1 s hs).inter ((hs2 t ht))) · refine Measurable.stronglyMeasurable (Measurable.mul ?_ ?_) - · exact measurable_condexpKernel (hs1 s hs) - · exact measurable_condexpKernel (hs2 t ht) + · exact measurable_condExpKernel (hs1 s hs) + · exact measurable_condExpKernel (hs2 t ht) filter_upwards [hs1_eq s hs, hs2_eq t ht, hs12_eq s hs t ht, h] with ω hs_eq ht_eq hst_eq h - have h_ne_top : condexpKernel μ m' ω (s ∩ t) ≠ ∞ := measure_ne_top (condexpKernel μ m' ω) _ + have h_ne_top : condExpKernel μ m' ω (s ∩ t) ≠ ∞ := measure_ne_top (condExpKernel μ m' ω) _ rw [← ENNReal.ofReal_toReal h_ne_top, hst_eq, h, Pi.mul_apply, ← hs_eq, ← ht_eq, ← ENNReal.toReal_mul, ENNReal.ofReal_toReal] - exact ENNReal.mul_ne_top (measure_ne_top (condexpKernel μ m' ω) s) - (measure_ne_top (condexpKernel μ m' ω) t) + exact ENNReal.mul_ne_top (measure_ne_top (condExpKernel μ m' ω) s) + (measure_ne_top (condExpKernel μ m' ω) t) lemma iCondIndepSets_singleton_iff (s : ι → Set Ω) (hπ : ∀ i, MeasurableSet (s i)) (μ : Measure Ω) [IsFiniteMeasure μ] : @@ -639,7 +639,7 @@ variable {β β' : Type*} {m' : MeasurableSpace Ω} {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] {f : Ω → β} {g : Ω → β'} -theorem condIndepFun_iff_condexp_inter_preimage_eq_mul {mβ : MeasurableSpace β} +theorem condIndepFun_iff_condExp_inter_preimage_eq_mul {mβ : MeasurableSpace β} {mβ' : MeasurableSpace β'} (hf : Measurable f) (hg : Measurable g) : CondIndepFun m' hm' f g μ ↔ ∀ s t, MeasurableSet s → MeasurableSet t @@ -650,7 +650,11 @@ theorem condIndepFun_iff_condexp_inter_preimage_eq_mul {mβ : MeasurableSpace β · rintro ⟨s, hs, rfl⟩ ⟨t, ht, rfl⟩ exact h s t hs ht -theorem iCondIndepFun_iff_condexp_inter_preimage_eq_mul {β : ι → Type*} +@[deprecated (since := "2025-01-21")] +alias condIndepFun_iff_condexp_inter_preimage_eq_mul := + condIndepFun_iff_condExp_inter_preimage_eq_mul + +theorem iCondIndepFun_iff_condExp_inter_preimage_eq_mul {β : ι → Type*} (m : ∀ x, MeasurableSpace (β x)) (f : ∀ i, Ω → β i) (hf : ∀ i, Measurable (f i)) : iCondIndepFun m' hm' m f μ ↔ ∀ (S : Finset ι) {sets : ∀ i : ι, Set (β i)} (_H : ∀ i, i ∈ S → MeasurableSet[m i] (sets i)), @@ -672,6 +676,10 @@ theorem iCondIndepFun_iff_condexp_inter_preimage_eq_mul {β : ι → Type*} simp only [g, dif_pos hi] convert h with i hi i hi <;> exact hg i hi +@[deprecated (since := "2025-01-21")] +alias iCondIndepFun_iff_condexp_inter_preimage_eq_mul := + iCondIndepFun_iff_condExp_inter_preimage_eq_mul + theorem condIndepFun_iff_condIndepSet_preimage {mβ : MeasurableSpace β} {mβ' : MeasurableSpace β'} (hf : Measurable f) (hg : Measurable g) : CondIndepFun m' hm' f g μ ↔ diff --git a/Mathlib/Probability/Independence/Kernel.lean b/Mathlib/Probability/Independence/Kernel.lean index 1b8fc5fb8bb20..9984c68a77708 100644 --- a/Mathlib/Probability/Independence/Kernel.lean +++ b/Mathlib/Probability/Independence/Kernel.lean @@ -17,7 +17,7 @@ for any sets `f i_1 ∈ π i_1, ..., f i_n ∈ π i_n`, then for `μ`-almost eve `κ a (⋂ i in s, f i) = ∏ i ∈ s, κ a (f i)`. This notion of independence is a generalization of both independence and conditional independence. -For conditional independence, `κ` is the conditional kernel `ProbabilityTheory.condexpKernel` and +For conditional independence, `κ` is the conditional kernel `ProbabilityTheory.condExpKernel` and `μ` is the ambient measure. For (non-conditional) independence, `κ = Kernel.const Unit μ` and the measure is the Dirac measure on `Unit`. diff --git a/Mathlib/Probability/Independence/ZeroOne.lean b/Mathlib/Probability/Independence/ZeroOne.lean index f5d9ea44f6bd9..4d8d758321b71 100644 --- a/Mathlib/Probability/Independence/ZeroOne.lean +++ b/Mathlib/Probability/Independence/ZeroOne.lean @@ -62,20 +62,23 @@ theorem measure_eq_zero_or_one_of_indepSet_self [IsFiniteMeasure μ] {t : Set Ω simpa only [ae_dirac_eq, Filter.eventually_pure] using Kernel.measure_eq_zero_or_one_of_indepSet_self h_indep -theorem condexp_eq_zero_or_one_of_condIndepSet_self +theorem condExp_eq_zero_or_one_of_condIndepSet_self [StandardBorelSpace Ω] (hm : m ≤ m0) [hμ : IsFiniteMeasure μ] {t : Set Ω} (ht : MeasurableSet t) (h_indep : CondIndepSet m hm t t μ) : ∀ᵐ ω ∂μ, (μ⟦t | m⟧) ω = 0 ∨ (μ⟦t | m⟧) ω = 1 := by -- TODO: Why is not inferred? - have (a) : IsFiniteMeasure (condexpKernel μ m a) := inferInstance + have (a) : IsFiniteMeasure (condExpKernel μ m a) := inferInstance have h := ae_of_ae_trim hm (Kernel.measure_eq_zero_or_one_of_indepSet_self h_indep) - filter_upwards [condexpKernel_ae_eq_condexp hm ht, h] with ω hω_eq hω + filter_upwards [condExpKernel_ae_eq_condExp hm ht, h] with ω hω_eq hω rw [← hω_eq, ENNReal.toReal_eq_zero_iff, ENNReal.toReal_eq_one_iff] cases hω with | inl h => exact Or.inl (Or.inl h) | inr h => exact Or.inr h +@[deprecated (since := "2025-01-21")] +alias condexp_eq_zero_or_one_of_condIndepSet_self := condExp_eq_zero_or_one_of_condIndepSet_self + open Filter theorem Kernel.indep_biSup_compl (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s κ μα) (t : Set ι) : @@ -223,7 +226,7 @@ theorem measure_zero_or_one_of_measurableSet_limsup using Kernel.measure_zero_or_one_of_measurableSet_limsup h_le h_indep hf hns hnsp hns_univ ht_tail -theorem condexp_zero_or_one_of_measurableSet_limsup [StandardBorelSpace Ω] +theorem condExp_zero_or_one_of_measurableSet_limsup [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) @@ -232,12 +235,15 @@ theorem condexp_zero_or_one_of_measurableSet_limsup [StandardBorelSpace Ω] have h := ae_of_ae_trim hm (Kernel.measure_zero_or_one_of_measurableSet_limsup h_le h_indep hf hns hnsp hns_univ ht_tail) have ht : MeasurableSet t := limsup_le_iSup.trans (iSup_le h_le) t ht_tail - filter_upwards [condexpKernel_ae_eq_condexp hm ht, h] with ω hω_eq hω + filter_upwards [condExpKernel_ae_eq_condExp hm ht, h] with ω hω_eq hω rw [← hω_eq, ENNReal.toReal_eq_zero_iff, ENNReal.toReal_eq_one_iff] cases hω with | inl h => exact Or.inl (Or.inl h) | inr h => exact Or.inr h +@[deprecated (since := "2025-01-21")] +alias condexp_zero_or_one_of_measurableSet_limsup := condExp_zero_or_one_of_measurableSet_limsup + end Abstract section AtTop @@ -285,13 +291,17 @@ theorem measure_zero_or_one_of_measurableSet_limsup_atTop simpa only [ae_dirac_eq, Filter.eventually_pure] using Kernel.measure_zero_or_one_of_measurableSet_limsup_atTop h_le h_indep ht_tail -theorem condexp_zero_or_one_of_measurableSet_limsup_atTop [StandardBorelSpace Ω] +theorem condExp_zero_or_one_of_measurableSet_limsup_atTop [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atTop] t) : ∀ᵐ ω ∂μ, (μ⟦t | m⟧) ω = 0 ∨ (μ⟦t | m⟧) ω = 1 := - condexp_eq_zero_or_one_of_condIndepSet_self hm (limsup_le_iSup.trans (iSup_le h_le) t ht_tail) + condExp_eq_zero_or_one_of_condIndepSet_self hm (limsup_le_iSup.trans (iSup_le h_le) t ht_tail) ((condIndep_limsup_atTop_self hm h_le h_indep).condIndepSet_of_measurableSet ht_tail ht_tail) +@[deprecated (since := "2025-01-21")] +alias condexp_zero_or_one_of_measurableSet_limsup_atTop := + condExp_zero_or_one_of_measurableSet_limsup_atTop + end AtTop section AtBot @@ -343,13 +353,17 @@ theorem measure_zero_or_one_of_measurableSet_limsup_atBot /-- **Kolmogorov's 0-1 law**, conditional version: any event in the tail σ-algebra of a conditionally independent sequence of sub-σ-algebras has conditional probability 0 or 1. -/ -theorem condexp_zero_or_one_of_measurableSet_limsup_atBot [StandardBorelSpace Ω] +theorem condExp_zero_or_one_of_measurableSet_limsup_atBot [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atBot] t) : ∀ᵐ ω ∂μ, (μ⟦t | m⟧) ω = 0 ∨ (μ⟦t | m⟧) ω = 1 := - condexp_eq_zero_or_one_of_condIndepSet_self hm (limsup_le_iSup.trans (iSup_le h_le) t ht_tail) + condExp_eq_zero_or_one_of_condIndepSet_self hm (limsup_le_iSup.trans (iSup_le h_le) t ht_tail) ((condIndep_limsup_atBot_self hm h_le h_indep).condIndepSet_of_measurableSet ht_tail ht_tail) +@[deprecated (since := "2025-01-21")] +alias condexp_zero_or_one_of_measurableSet_limsup_atBot := + condExp_zero_or_one_of_measurableSet_limsup_atBot + end AtBot end ProbabilityTheory diff --git a/Mathlib/Probability/Kernel/CondDistrib.lean b/Mathlib/Probability/Kernel/CondDistrib.lean index 56e7c43530b0e..f33383cd5df84 100644 --- a/Mathlib/Probability/Kernel/CondDistrib.lean +++ b/Mathlib/Probability/Kernel/CondDistrib.lean @@ -32,9 +32,9 @@ to `m`. ## Main statements -* `condDistrib_ae_eq_condexp`: for almost all `a`, `condDistrib` evaluated at `X a` and a +* `condDistrib_ae_eq_condExp`: for almost all `a`, `condDistrib` evaluated at `X a` and a measurable set `s` is equal to the conditional expectation `μ⟦Y ⁻¹' s | mβ.comap X⟧ a`. -* `condexp_prod_ae_eq_integral_condDistrib`: the conditional expectation +* `condExp_prod_ae_eq_integral_condDistrib`: the conditional expectation `μ[(fun a => f (X a, Y a)) | X; mβ]` is almost everywhere equal to the integral `∫ y, f (X a, y) ∂(condDistrib Y X μ (X a))`. @@ -202,9 +202,9 @@ alias set_lintegral_condDistrib_of_measurableSet := setLIntegral_condDistrib_of_ /-- For almost every `a : α`, the `condDistrib Y X μ` kernel applied to `X a` and a measurable set `s` is equal to the conditional expectation of the indicator of `Y ⁻¹' s`. -/ -theorem condDistrib_ae_eq_condexp (hX : Measurable X) (hY : Measurable Y) (hs : MeasurableSet s) : +theorem condDistrib_ae_eq_condExp (hX : Measurable X) (hY : Measurable Y) (hs : MeasurableSet s) : (fun a => (condDistrib Y X μ (X a) s).toReal) =ᵐ[μ] μ⟦Y ⁻¹' s|mβ.comap X⟧ := by - refine ae_eq_condexp_of_forall_setIntegral_eq hX.comap_le ?_ ?_ ?_ ?_ + refine ae_eq_condExp_of_forall_setIntegral_eq hX.comap_le ?_ ?_ ?_ ?_ · exact (integrable_const _).indicator (hY hs) · exact fun t _ _ => (integrable_toReal_condDistrib hX.aemeasurable hs).integrableOn · intro t ht _ @@ -215,15 +215,17 @@ theorem condDistrib_ae_eq_condexp (hX : Measurable X) (hY : Measurable Y) (hs : · refine (Measurable.stronglyMeasurable ?_).aeStronglyMeasurable' exact @Measurable.ennreal_toReal _ (mβ.comap X) _ (measurable_condDistrib hs) +@[deprecated (since := "2025-01-21")] alias condDistrib_ae_eq_condexp := condDistrib_ae_eq_condExp + /-- The conditional expectation of a function `f` of the product `(X, Y)` is almost everywhere equal to the integral of `y ↦ f(X, y)` against the `condDistrib` kernel. -/ -theorem condexp_prod_ae_eq_integral_condDistrib' [NormedSpace ℝ F] [CompleteSpace F] +theorem condExp_prod_ae_eq_integral_condDistrib' [NormedSpace ℝ F] [CompleteSpace F] (hX : Measurable X) (hY : AEMeasurable Y μ) (hf_int : Integrable f (μ.map fun a => (X a, Y a))) : μ[fun a => f (X a, Y a)|mβ.comap X] =ᵐ[μ] fun a => ∫ y, f (X a,y) ∂condDistrib Y X μ (X a) := by have hf_int' : Integrable (fun a => f (X a, Y a)) μ := (integrable_map_measure hf_int.1 (hX.aemeasurable.prod_mk hY)).mp hf_int - refine (ae_eq_condexp_of_forall_setIntegral_eq hX.comap_le hf_int' (fun s _ _ => ?_) ?_ ?_).symm + refine (ae_eq_condExp_of_forall_setIntegral_eq hX.comap_le hf_int' (fun s _ _ => ?_) ?_ ?_).symm · exact (hf_int.integral_condDistrib hX.aemeasurable hY).integrableOn · rintro s ⟨t, ht, rfl⟩ _ change ∫ a in X ⁻¹' t, ((fun x' => ∫ y, f (x', y) ∂(condDistrib Y X μ) x') ∘ X) a ∂μ = @@ -239,40 +241,55 @@ theorem condexp_prod_ae_eq_integral_condDistrib' [NormedSpace ℝ F] [CompleteSp mk_preimage_prod, preimage_univ, inter_univ] · exact aestronglyMeasurable'_integral_condDistrib hX.aemeasurable hY hf_int.1 +@[deprecated (since := "2025-01-21")] +alias condexp_prod_ae_eq_integral_condDistrib' := condExp_prod_ae_eq_integral_condDistrib' + /-- The conditional expectation of a function `f` of the product `(X, Y)` is almost everywhere equal to the integral of `y ↦ f(X, y)` against the `condDistrib` kernel. -/ -theorem condexp_prod_ae_eq_integral_condDistrib₀ [NormedSpace ℝ F] [CompleteSpace F] +theorem condExp_prod_ae_eq_integral_condDistrib₀ [NormedSpace ℝ F] [CompleteSpace F] (hX : Measurable X) (hY : AEMeasurable Y μ) (hf : AEStronglyMeasurable f (μ.map fun a => (X a, Y a))) (hf_int : Integrable (fun a => f (X a, Y a)) μ) : μ[fun a => f (X a, Y a)|mβ.comap X] =ᵐ[μ] fun a => ∫ y, f (X a, y) ∂condDistrib Y X μ (X a) := haveI hf_int' : Integrable f (μ.map fun a => (X a, Y a)) := by rwa [integrable_map_measure hf (hX.aemeasurable.prod_mk hY)] - condexp_prod_ae_eq_integral_condDistrib' hX hY hf_int' + condExp_prod_ae_eq_integral_condDistrib' hX hY hf_int' + +@[deprecated (since := "2025-01-21")] +alias condexp_prod_ae_eq_integral_condDistrib₀ := condExp_prod_ae_eq_integral_condDistrib₀ /-- The conditional expectation of a function `f` of the product `(X, Y)` is almost everywhere equal to the integral of `y ↦ f(X, y)` against the `condDistrib` kernel. -/ -theorem condexp_prod_ae_eq_integral_condDistrib [NormedSpace ℝ F] [CompleteSpace F] +theorem condExp_prod_ae_eq_integral_condDistrib [NormedSpace ℝ F] [CompleteSpace F] (hX : Measurable X) (hY : AEMeasurable Y μ) (hf : StronglyMeasurable f) (hf_int : Integrable (fun a => f (X a, Y a)) μ) : μ[fun a => f (X a, Y a)|mβ.comap X] =ᵐ[μ] fun a => ∫ y, f (X a, y) ∂condDistrib Y X μ (X a) := haveI hf_int' : Integrable f (μ.map fun a => (X a, Y a)) := by rwa [integrable_map_measure hf.aestronglyMeasurable (hX.aemeasurable.prod_mk hY)] - condexp_prod_ae_eq_integral_condDistrib' hX hY hf_int' + condExp_prod_ae_eq_integral_condDistrib' hX hY hf_int' + +@[deprecated (since := "2025-01-21")] +alias condexp_prod_ae_eq_integral_condDistrib := condExp_prod_ae_eq_integral_condDistrib -theorem condexp_ae_eq_integral_condDistrib [NormedSpace ℝ F] [CompleteSpace F] (hX : Measurable X) +theorem condExp_ae_eq_integral_condDistrib [NormedSpace ℝ F] [CompleteSpace F] (hX : Measurable X) (hY : AEMeasurable Y μ) {f : Ω → F} (hf : StronglyMeasurable f) (hf_int : Integrable (fun a => f (Y a)) μ) : μ[fun a => f (Y a)|mβ.comap X] =ᵐ[μ] fun a => ∫ y, f y ∂condDistrib Y X μ (X a) := - condexp_prod_ae_eq_integral_condDistrib hX hY (hf.comp_measurable measurable_snd) hf_int + condExp_prod_ae_eq_integral_condDistrib hX hY (hf.comp_measurable measurable_snd) hf_int + +@[deprecated (since := "2025-01-21")] +alias condexp_ae_eq_integral_condDistrib := condExp_ae_eq_integral_condDistrib /-- The conditional expectation of `Y` given `X` is almost everywhere equal to the integral `∫ y, y ∂(condDistrib Y X μ (X a))`. -/ -theorem condexp_ae_eq_integral_condDistrib' {Ω} [NormedAddCommGroup Ω] [NormedSpace ℝ Ω] +theorem condExp_ae_eq_integral_condDistrib' {Ω} [NormedAddCommGroup Ω] [NormedSpace ℝ Ω] [CompleteSpace Ω] [MeasurableSpace Ω] [BorelSpace Ω] [SecondCountableTopology Ω] {Y : α → Ω} (hX : Measurable X) (hY_int : Integrable Y μ) : μ[Y|mβ.comap X] =ᵐ[μ] fun a => ∫ y, y ∂condDistrib Y X μ (X a) := - condexp_ae_eq_integral_condDistrib hX hY_int.1.aemeasurable stronglyMeasurable_id hY_int + condExp_ae_eq_integral_condDistrib hX hY_int.1.aemeasurable stronglyMeasurable_id hY_int + +@[deprecated (since := "2025-01-21")] +alias condexp_ae_eq_integral_condDistrib' := condExp_ae_eq_integral_condDistrib' open MeasureTheory @@ -319,9 +336,12 @@ theorem integrable_comp_snd_map_prod_mk_iff {Ω} {_ : MeasurableSpace Ω} {X : Integrable (fun x : β × Ω => f x.2) (μ.map fun ω => (X ω, ω)) ↔ Integrable f μ := ⟨fun h => h.comp_measurable (hX.prod_mk measurable_id), fun h => h.comp_snd_map_prod_mk X⟩ -theorem condexp_ae_eq_integral_condDistrib_id [NormedSpace ℝ F] [CompleteSpace F] {X : Ω → β} +theorem condExp_ae_eq_integral_condDistrib_id [NormedSpace ℝ F] [CompleteSpace F] {X : Ω → β} {μ : Measure Ω} [IsFiniteMeasure μ] (hX : Measurable X) {f : Ω → F} (hf_int : Integrable f μ) : μ[f|mβ.comap X] =ᵐ[μ] fun a => ∫ y, f y ∂condDistrib id X μ (X a) := - condexp_prod_ae_eq_integral_condDistrib' hX aemeasurable_id (hf_int.comp_snd_map_prod_mk X) + condExp_prod_ae_eq_integral_condDistrib' hX aemeasurable_id (hf_int.comp_snd_map_prod_mk X) + +@[deprecated (since := "2025-01-21")] +alias condexp_ae_eq_integral_condDistrib_id := condExp_ae_eq_integral_condDistrib_id end ProbabilityTheory diff --git a/Mathlib/Probability/Kernel/Condexp.lean b/Mathlib/Probability/Kernel/Condexp.lean index 56675cbb11d1e..87e449f00fafe 100644 --- a/Mathlib/Probability/Kernel/Condexp.lean +++ b/Mathlib/Probability/Kernel/Condexp.lean @@ -9,8 +9,8 @@ import Mathlib.Probability.ConditionalProbability /-! # Kernel associated with a conditional expectation -We define `condexpKernel μ m`, a kernel from `Ω` to `Ω` such that for all integrable functions `f`, -`μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condexpKernel μ m ω)`. +We define `condExpKernel μ m`, a kernel from `Ω` to `Ω` such that for all integrable functions `f`, +`μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condExpKernel μ m ω)`. This kernel is defined if `Ω` is a standard Borel space. In general, `μ⟦s | m⟧` maps a measurable set `s` to a function `Ω → ℝ≥0∞`, and for all `s` that map is unique up to a `μ`-null set. For all @@ -21,11 +21,11 @@ on `Ω` allows us to do so. ## Main definitions -* `condexpKernel μ m`: kernel such that `μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condexpKernel μ m ω)`. +* `condExpKernel μ m`: kernel such that `μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condExpKernel μ m ω)`. ## Main statements -* `condexp_ae_eq_integral_condexpKernel`: `μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condexpKernel μ m ω)`. +* `condExp_ae_eq_integral_condExpKernel`: `μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condExpKernel μ m ω)`. -/ @@ -61,158 +61,211 @@ variable {Ω F : Type*} {m : MeasurableSpace Ω} [mΩ : MeasurableSpace Ω] open Classical in /-- Kernel associated with the conditional expectation with respect to a σ-algebra. It satisfies -`μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condexpKernel μ m ω)`. +`μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condExpKernel μ m ω)`. It is defined as the conditional distribution of the identity given the identity, where the second identity is understood as a map from `Ω` with the σ-algebra `mΩ` to `Ω` with σ-algebra `m ⊓ mΩ`. We use `m ⊓ mΩ` instead of `m` to ensure that it is a sub-σ-algebra of `mΩ`. We then use `Kernel.comap` to get a kernel from `m` to `mΩ` instead of from `m ⊓ mΩ` to `mΩ`. -/ -noncomputable irreducible_def condexpKernel (μ : Measure Ω) [IsFiniteMeasure μ] +noncomputable irreducible_def condExpKernel (μ : Measure Ω) [IsFiniteMeasure μ] (m : MeasurableSpace Ω) : @Kernel Ω Ω m mΩ := if _h : Nonempty Ω then Kernel.comap (@condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _) id (measurable_id'' (inf_le_left : m ⊓ mΩ ≤ m)) else 0 -lemma condexpKernel_eq (μ : Measure Ω) [IsFiniteMeasure μ] [h : Nonempty Ω] +@[deprecated (since := "2025-01-21")] alias condexpKernel := condExpKernel + +lemma condExpKernel_eq (μ : Measure Ω) [IsFiniteMeasure μ] [h : Nonempty Ω] (m : MeasurableSpace Ω) : - condexpKernel (mΩ := mΩ) μ m = Kernel.comap (@condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _) id + condExpKernel (mΩ := mΩ) μ m = Kernel.comap (@condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _) id (measurable_id'' (inf_le_left : m ⊓ mΩ ≤ m)) := by - simp [condexpKernel, h] + simp [condExpKernel, h] + +@[deprecated (since := "2025-01-21")] alias condexpKernel_eq := condExpKernel_eq + +lemma condExpKernel_apply_eq_condDistrib [Nonempty Ω] {ω : Ω} : + condExpKernel μ m ω = @condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _ (id ω) := by + simp [condExpKernel_eq, Kernel.comap_apply] -lemma condexpKernel_apply_eq_condDistrib [Nonempty Ω] {ω : Ω} : - condexpKernel μ m ω = @condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _ (id ω) := by - simp [condexpKernel_eq, Kernel.comap_apply] +@[deprecated (since := "2025-01-21")] +alias condexpKernel_apply_eq_condDistrib := condExpKernel_apply_eq_condDistrib -instance : IsMarkovKernel (condexpKernel μ m) := by +instance : IsMarkovKernel (condExpKernel μ m) := by rcases isEmpty_or_nonempty Ω with h | h · exact ⟨fun a ↦ (IsEmpty.false a).elim⟩ - · simp [condexpKernel, h]; infer_instance + · simp [condExpKernel, h]; infer_instance section Measurability variable [NormedAddCommGroup F] {f : Ω → F} -theorem measurable_condexpKernel {s : Set Ω} (hs : MeasurableSet s) : - Measurable[m] fun ω => condexpKernel μ m ω s := by +theorem measurable_condExpKernel {s : Set Ω} (hs : MeasurableSet s) : + Measurable[m] fun ω => condExpKernel μ m ω s := by nontriviality Ω - simp_rw [condexpKernel_apply_eq_condDistrib] + simp_rw [condExpKernel_apply_eq_condDistrib] refine Measurable.mono ?_ (inf_le_left : m ⊓ mΩ ≤ m) le_rfl convert measurable_condDistrib (μ := μ) hs rw [MeasurableSpace.comap_id] -theorem stronglyMeasurable_condexpKernel {s : Set Ω} (hs : MeasurableSet s) : - StronglyMeasurable[m] fun ω => condexpKernel μ m ω s := - Measurable.stronglyMeasurable (measurable_condexpKernel hs) +@[deprecated (since := "2025-01-21")] alias measurable_condexpKernel := measurable_condExpKernel + +theorem stronglyMeasurable_condExpKernel {s : Set Ω} (hs : MeasurableSet s) : + StronglyMeasurable[m] fun ω => condExpKernel μ m ω s := + Measurable.stronglyMeasurable (measurable_condExpKernel hs) + +@[deprecated (since := "2025-01-21")] +alias stronglyMeasurable_condexpKernel := stronglyMeasurable_condExpKernel -theorem _root_.MeasureTheory.AEStronglyMeasurable.integral_condexpKernel [NormedSpace ℝ F] +theorem _root_.MeasureTheory.AEStronglyMeasurable.integral_condExpKernel [NormedSpace ℝ F] (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable (fun ω => ∫ y, f y ∂condexpKernel μ m ω) μ := by + AEStronglyMeasurable (fun ω => ∫ y, f y ∂condExpKernel μ m ω) μ := by nontriviality Ω - simp_rw [condexpKernel_apply_eq_condDistrib] + simp_rw [condExpKernel_apply_eq_condDistrib] exact AEStronglyMeasurable.integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf.comp_snd_map_prod_id inf_le_right) -theorem aestronglyMeasurable'_integral_condexpKernel [NormedSpace ℝ F] +@[deprecated (since := "2025-01-21")] +alias _root_.MeasureTheory.AEStronglyMeasurable.integral_condexpKernel := + _root_.MeasureTheory.AEStronglyMeasurable.integral_condExpKernel + +theorem aestronglyMeasurable'_integral_condExpKernel [NormedSpace ℝ F] (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable' m (fun ω => ∫ y, f y ∂condexpKernel μ m ω) μ := by + AEStronglyMeasurable' m (fun ω => ∫ y, f y ∂condExpKernel μ m ω) μ := by nontriviality Ω - rw [condexpKernel_eq] + rw [condExpKernel_eq] have h := aestronglyMeasurable'_integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) rw [MeasurableSpace.comap_id] at h exact AEStronglyMeasurable'.mono h inf_le_left +@[deprecated (since := "2025-01-21")] +alias aestronglyMeasurable'_integral_condexpKernel := aestronglyMeasurable'_integral_condExpKernel + end Measurability section Integrability variable [NormedAddCommGroup F] {f : Ω → F} -theorem _root_.MeasureTheory.Integrable.condexpKernel_ae (hf_int : Integrable f μ) : - ∀ᵐ ω ∂μ, Integrable f (condexpKernel μ m ω) := by +theorem _root_.MeasureTheory.Integrable.condExpKernel_ae (hf_int : Integrable f μ) : + ∀ᵐ ω ∂μ, Integrable f (condExpKernel μ m ω) := by nontriviality Ω - rw [condexpKernel_eq] + rw [condExpKernel_eq] convert Integrable.condDistrib_ae (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 -theorem _root_.MeasureTheory.Integrable.integral_norm_condexpKernel (hf_int : Integrable f μ) : - Integrable (fun ω => ∫ y, ‖f y‖ ∂condexpKernel μ m ω) μ := by +@[deprecated (since := "2025-01-21")] +alias _root_.MeasureTheory.Integrable.condexpKernel_ae := + _root_.MeasureTheory.Integrable.condExpKernel_ae + +theorem _root_.MeasureTheory.Integrable.integral_norm_condExpKernel (hf_int : Integrable f μ) : + Integrable (fun ω => ∫ y, ‖f y‖ ∂condExpKernel μ m ω) μ := by nontriviality Ω - rw [condexpKernel_eq] + rw [condExpKernel_eq] convert Integrable.integral_norm_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 -theorem _root_.MeasureTheory.Integrable.norm_integral_condexpKernel [NormedSpace ℝ F] +@[deprecated (since := "2025-01-21")] +alias _root_.MeasureTheory.Integrable.integral_norm_condexpKernel := + _root_.MeasureTheory.Integrable.integral_norm_condExpKernel + +theorem _root_.MeasureTheory.Integrable.norm_integral_condExpKernel [NormedSpace ℝ F] (hf_int : Integrable f μ) : - Integrable (fun ω => ‖∫ y, f y ∂condexpKernel μ m ω‖) μ := by + Integrable (fun ω => ‖∫ y, f y ∂condExpKernel μ m ω‖) μ := by nontriviality Ω - rw [condexpKernel_eq] + rw [condExpKernel_eq] convert Integrable.norm_integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 -theorem _root_.MeasureTheory.Integrable.integral_condexpKernel [NormedSpace ℝ F] +@[deprecated (since := "2025-01-21")] +alias _root_.MeasureTheory.Integrable.norm_integral_condexpKernel := + _root_.MeasureTheory.Integrable.norm_integral_condExpKernel + +theorem _root_.MeasureTheory.Integrable.integral_condExpKernel [NormedSpace ℝ F] (hf_int : Integrable f μ) : - Integrable (fun ω => ∫ y, f y ∂condexpKernel μ m ω) μ := by + Integrable (fun ω => ∫ y, f y ∂condExpKernel μ m ω) μ := by nontriviality Ω - rw [condexpKernel_eq] + rw [condExpKernel_eq] convert Integrable.integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 -theorem integrable_toReal_condexpKernel {s : Set Ω} (hs : MeasurableSet s) : - Integrable (fun ω => (condexpKernel μ m ω s).toReal) μ := by +@[deprecated (since := "2025-01-21")] +alias _root_.MeasureTheory.Integrable.integral_condexpKernel := + _root_.MeasureTheory.Integrable.integral_condExpKernel + +theorem integrable_toReal_condExpKernel {s : Set Ω} (hs : MeasurableSet s) : + Integrable (fun ω => (condExpKernel μ m ω s).toReal) μ := by nontriviality Ω - rw [condexpKernel_eq] + rw [condExpKernel_eq] exact integrable_toReal_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) hs +@[deprecated (since := "2025-01-21")] +alias integrable_toReal_condexpKernel := integrable_toReal_condExpKernel + end Integrability -lemma condexpKernel_ae_eq_condexp' {s : Set Ω} (hs : MeasurableSet s) : - (fun ω ↦ (condexpKernel μ m ω s).toReal) =ᵐ[μ] μ⟦s | m ⊓ mΩ⟧ := by +lemma condExpKernel_ae_eq_condExp' {s : Set Ω} (hs : MeasurableSet s) : + (fun ω ↦ (condExpKernel μ m ω s).toReal) =ᵐ[μ] μ⟦s | m ⊓ mΩ⟧ := by rcases isEmpty_or_nonempty Ω with h | h · have : μ = 0 := Measure.eq_zero_of_isEmpty μ simpa [this] using trivial - have h := condDistrib_ae_eq_condexp (μ := μ) + have h := condDistrib_ae_eq_condExp (μ := μ) (measurable_id'' (inf_le_right : m ⊓ mΩ ≤ mΩ)) measurable_id hs simp only [id_eq, MeasurableSpace.comap_id, preimage_id_eq] at h - simp_rw [condexpKernel_apply_eq_condDistrib] + simp_rw [condExpKernel_apply_eq_condDistrib] exact h -lemma condexpKernel_ae_eq_condexp +@[deprecated (since := "2025-01-21")] +alias condexpKernel_ae_eq_condexp' := condExpKernel_ae_eq_condExp' + +lemma condExpKernel_ae_eq_condExp (hm : m ≤ mΩ) {s : Set Ω} (hs : MeasurableSet s) : - (fun ω ↦ (condexpKernel μ m ω s).toReal) =ᵐ[μ] μ⟦s | m⟧ := - (condexpKernel_ae_eq_condexp' hs).trans (by rw [inf_of_le_left hm]) + (fun ω ↦ (condExpKernel μ m ω s).toReal) =ᵐ[μ] μ⟦s | m⟧ := + (condExpKernel_ae_eq_condExp' hs).trans (by rw [inf_of_le_left hm]) -lemma condexpKernel_ae_eq_trim_condexp +@[deprecated (since := "2025-01-21")] +alias condexpKernel_ae_eq_condexp := condExpKernel_ae_eq_condExp + +lemma condExpKernel_ae_eq_trim_condExp (hm : m ≤ mΩ) {s : Set Ω} (hs : MeasurableSet s) : - (fun ω ↦ (condexpKernel μ m ω s).toReal) =ᵐ[μ.trim hm] μ⟦s | m⟧ := by - rw [ae_eq_trim_iff hm _ stronglyMeasurable_condexp] - · exact condexpKernel_ae_eq_condexp hm hs + (fun ω ↦ (condExpKernel μ m ω s).toReal) =ᵐ[μ.trim hm] μ⟦s | m⟧ := by + rw [ae_eq_trim_iff hm _ stronglyMeasurable_condExp] + · exact condExpKernel_ae_eq_condExp hm hs · refine Measurable.stronglyMeasurable ?_ - exact @Measurable.ennreal_toReal _ m _ (measurable_condexpKernel hs) + exact @Measurable.ennreal_toReal _ m _ (measurable_condExpKernel hs) + +@[deprecated (since := "2025-01-21")] +alias condexpKernel_ae_eq_trim_condexp := condExpKernel_ae_eq_trim_condExp -theorem condexp_ae_eq_integral_condexpKernel' [NormedAddCommGroup F] {f : Ω → F} +theorem condExp_ae_eq_integral_condExpKernel' [NormedAddCommGroup F] {f : Ω → F} [NormedSpace ℝ F] [CompleteSpace F] (hf_int : Integrable f μ) : - μ[f|m ⊓ mΩ] =ᵐ[μ] fun ω => ∫ y, f y ∂condexpKernel μ m ω := by + μ[f|m ⊓ mΩ] =ᵐ[μ] fun ω => ∫ y, f y ∂condExpKernel μ m ω := by rcases isEmpty_or_nonempty Ω with h | h · have : μ = 0 := Measure.eq_zero_of_isEmpty μ simpa [this] using trivial have hX : @Measurable Ω Ω mΩ (m ⊓ mΩ) id := measurable_id.mono le_rfl (inf_le_right : m ⊓ mΩ ≤ mΩ) - simp_rw [condexpKernel_apply_eq_condDistrib] - have h := condexp_ae_eq_integral_condDistrib_id hX hf_int + simp_rw [condExpKernel_apply_eq_condDistrib] + have h := condExp_ae_eq_integral_condDistrib_id hX hf_int simpa only [MeasurableSpace.comap_id, id_eq] using h +@[deprecated (since := "2025-01-21")] +alias condexp_ae_eq_integral_condexpKernel' := condExp_ae_eq_integral_condExpKernel' + /-- The conditional expectation of `f` with respect to a σ-algebra `m` is almost everywhere equal to -the integral `∫ y, f y ∂(condexpKernel μ m ω)`. -/ -theorem condexp_ae_eq_integral_condexpKernel [NormedAddCommGroup F] {f : Ω → F} +the integral `∫ y, f y ∂(condExpKernel μ m ω)`. -/ +theorem condExp_ae_eq_integral_condExpKernel [NormedAddCommGroup F] {f : Ω → F} [NormedSpace ℝ F] [CompleteSpace F] (hm : m ≤ mΩ) (hf_int : Integrable f μ) : - μ[f|m] =ᵐ[μ] fun ω => ∫ y, f y ∂condexpKernel μ m ω := - ((condexp_ae_eq_integral_condexpKernel' hf_int).symm.trans (by rw [inf_of_le_left hm])).symm + μ[f|m] =ᵐ[μ] fun ω => ∫ y, f y ∂condExpKernel μ m ω := + ((condExp_ae_eq_integral_condExpKernel' hf_int).symm.trans (by rw [inf_of_le_left hm])).symm + +@[deprecated (since := "2025-01-21")] +alias condexp_ae_eq_integral_condexpKernel := condExp_ae_eq_integral_condExpKernel section Cond @@ -224,15 +277,15 @@ variable {s t : Set Ω} [NormedAddCommGroup F] [NormedSpace ℝ F] [CompleteSpac omit [StandardBorelSpace Ω] -lemma condexp_generateFrom_singleton (hs : MeasurableSet s) {f : Ω → F} (hf : Integrable f μ) : +lemma condExp_generateFrom_singleton (hs : MeasurableSet s) {f : Ω → F} (hf : Integrable f μ) : μ[f | generateFrom {s}] =ᵐ[μ.restrict s] fun _ ↦ ∫ x, f x ∂μ[|s] := by by_cases hμs : μ s = 0 · rw [Measure.restrict_eq_zero.2 hμs] rfl - refine ae_eq_trans (condexp_restrict_ae_eq_restrict + refine ae_eq_trans (condExp_restrict_ae_eq_restrict (generateFrom_singleton_le hs) (measurableSet_generateFrom rfl) hf).symm ?_ - · refine (ae_eq_condexp_of_forall_setIntegral_eq + · refine (ae_eq_condExp_of_forall_setIntegral_eq (generateFrom_singleton_le hs) hf.restrict ?_ ?_ stronglyMeasurable_const.aeStronglyMeasurable').symm · rintro t - - @@ -252,22 +305,31 @@ lemma condexp_generateFrom_singleton (hs : MeasurableSet s) {f : Ω → F} (hf : integral_const, MeasurableSet.univ, Measure.restrict_apply, univ_inter, smul_inv_smul₀ <| ENNReal.toReal_ne_zero.2 ⟨hμs, measure_ne_top _ _⟩] -lemma condexp_set_generateFrom_singleton (hs : MeasurableSet s) (ht : MeasurableSet t) : +@[deprecated (since := "2025-01-21")] +alias condexp_generateFrom_singleton := condExp_generateFrom_singleton + +lemma condExp_set_generateFrom_singleton (hs : MeasurableSet s) (ht : MeasurableSet t) : μ⟦t | generateFrom {s}⟧ =ᵐ[μ.restrict s] fun _ ↦ (μ[t|s]).toReal := by rw [← integral_indicator_one ht] - exact condexp_generateFrom_singleton hs <| Integrable.indicator (integrable_const 1) ht + exact condExp_generateFrom_singleton hs <| Integrable.indicator (integrable_const 1) ht -lemma condexpKernel_singleton_ae_eq_cond [StandardBorelSpace Ω] (hs : MeasurableSet s) +@[deprecated (since := "2025-01-21")] +alias condexp_set_generateFrom_singleton := condExp_set_generateFrom_singleton + +lemma condExpKernel_singleton_ae_eq_cond [StandardBorelSpace Ω] (hs : MeasurableSet s) (ht : MeasurableSet t) : ∀ᵐ ω ∂μ.restrict s, - condexpKernel μ (generateFrom {s}) ω t = μ[t|s] := by - have : (fun ω ↦ (condexpKernel μ (generateFrom {s}) ω t).toReal) =ᵐ[μ.restrict s] + condExpKernel μ (generateFrom {s}) ω t = μ[t|s] := by + have : (fun ω ↦ (condExpKernel μ (generateFrom {s}) ω t).toReal) =ᵐ[μ.restrict s] μ⟦t | generateFrom {s}⟧ := - ae_restrict_le <| condexpKernel_ae_eq_condexp + ae_restrict_le <| condExpKernel_ae_eq_condExp (generateFrom_singleton_le hs) ht - filter_upwards [condexp_set_generateFrom_singleton hs ht, this] with ω hω₁ hω₂ + filter_upwards [condExp_set_generateFrom_singleton hs ht, this] with ω hω₁ hω₂ rwa [hω₁, ENNReal.toReal_eq_toReal (measure_ne_top _ t) (measure_ne_top _ t)] at hω₂ +@[deprecated (since := "2025-01-21")] +alias condexpKernel_singleton_ae_eq_cond := condExpKernel_singleton_ae_eq_cond + end Cond end ProbabilityTheory diff --git a/Mathlib/Probability/Kernel/Disintegration/Density.lean b/Mathlib/Probability/Kernel/Disintegration/Density.lean index 9dd84c89fa298..eba7c9ae48353 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Density.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Density.lean @@ -288,11 +288,11 @@ lemma setIntegral_densityProcess_of_le (hκν : fst κ ≤ ν) @[deprecated (since := "2024-04-17")] alias set_integral_densityProcess_of_le := setIntegral_densityProcess_of_le -lemma condexp_densityProcess (hκν : fst κ ≤ ν) [IsFiniteKernel ν] +lemma condExp_densityProcess (hκν : fst κ ≤ ν) [IsFiniteKernel ν] {i j : ℕ} (hij : i ≤ j) (a : α) {s : Set β} (hs : MeasurableSet s) : (ν a)[fun x ↦ densityProcess κ ν j a x s | countableFiltration γ i] =ᵐ[ν a] fun x ↦ densityProcess κ ν i a x s := by - refine (ae_eq_condexp_of_forall_setIntegral_eq ?_ ?_ ?_ ?_ ?_).symm + refine (ae_eq_condExp_of_forall_setIntegral_eq ?_ ?_ ?_ ?_ ?_).symm · exact integrable_densityProcess hκν j a hs · exact fun _ _ _ ↦ (integrable_densityProcess hκν _ _ hs).integrableOn · intro x hx _ @@ -301,10 +301,12 @@ lemma condexp_densityProcess (hκν : fst κ ≤ ν) [IsFiniteKernel ν] · exact StronglyMeasurable.aeStronglyMeasurable' (stronglyMeasurable_countableFiltration_densityProcess κ ν i a hs) +@[deprecated (since := "2025-01-21")] alias condexp_densityProcess := condExp_densityProcess + lemma martingale_densityProcess (hκν : fst κ ≤ ν) [IsFiniteKernel ν] (a : α) {s : Set β} (hs : MeasurableSet s) : Martingale (fun n x ↦ densityProcess κ ν n a x s) (countableFiltration γ) (ν a) := - ⟨adapted_densityProcess κ ν a hs, fun _ _ h ↦ condexp_densityProcess hκν h a hs⟩ + ⟨adapted_densityProcess κ ν a hs, fun _ _ h ↦ condExp_densityProcess hκν h a hs⟩ lemma densityProcess_mono_set (hκν : fst κ ≤ ν) (n : ℕ) (a : α) (x : γ) {s s' : Set β} (h : s ⊆ s') : diff --git a/Mathlib/Probability/Martingale/Basic.lean b/Mathlib/Probability/Martingale/Basic.lean index 809ebfe55f9ad..125817d26cf59 100644 --- a/Mathlib/Probability/Martingale/Basic.lean +++ b/Mathlib/Probability/Martingale/Basic.lean @@ -30,7 +30,7 @@ The definitions of filtration and adapted can be found in `Probability.Process.S ### Results -* `MeasureTheory.martingale_condexp f ℱ μ`: the sequence `fun i => μ[f | ℱ i, ℱ.le i])` is a +* `MeasureTheory.martingale_condExp f ℱ μ`: the sequence `fun i => μ[f | ℱ i, ℱ.le i])` is a martingale with respect to `ℱ` and `μ`. -/ @@ -64,18 +64,18 @@ def Submartingale [LE E] (f : ι → Ω → E) (ℱ : Filtration ι m0) (μ : Me theorem martingale_const (ℱ : Filtration ι m0) (μ : Measure Ω) [IsFiniteMeasure μ] (x : E) : Martingale (fun _ _ => x) ℱ μ := - ⟨adapted_const ℱ _, fun i j _ => by rw [condexp_const (ℱ.le _)]⟩ + ⟨adapted_const ℱ _, fun i j _ => by rw [condExp_const (ℱ.le _)]⟩ theorem martingale_const_fun [OrderBot ι] (ℱ : Filtration ι m0) (μ : Measure Ω) [IsFiniteMeasure μ] {f : Ω → E} (hf : StronglyMeasurable[ℱ ⊥] f) (hfint : Integrable f μ) : Martingale (fun _ => f) ℱ μ := by refine ⟨fun i => hf.mono <| ℱ.mono bot_le, fun i j _ => ?_⟩ - rw [condexp_of_stronglyMeasurable (ℱ.le _) (hf.mono <| ℱ.mono bot_le) hfint] + rw [condExp_of_stronglyMeasurable (ℱ.le _) (hf.mono <| ℱ.mono bot_le) hfint] variable (E) theorem martingale_zero (ℱ : Filtration ι m0) (μ : Measure Ω) : Martingale (0 : ι → Ω → E) ℱ μ := - ⟨adapted_zero E ℱ, fun i j _ => by rw [Pi.zero_apply, condexp_zero]; simp⟩ + ⟨adapted_zero E ℱ, fun i j _ => by rw [Pi.zero_apply, condExp_zero]; simp⟩ variable {E} @@ -88,15 +88,17 @@ protected theorem stronglyMeasurable (hf : Martingale f ℱ μ) (i : ι) : StronglyMeasurable[ℱ i] (f i) := hf.adapted i -theorem condexp_ae_eq (hf : Martingale f ℱ μ) {i j : ι} (hij : i ≤ j) : μ[f j|ℱ i] =ᵐ[μ] f i := +theorem condExp_ae_eq (hf : Martingale f ℱ μ) {i j : ι} (hij : i ≤ j) : μ[f j|ℱ i] =ᵐ[μ] f i := hf.2 i j hij +@[deprecated (since := "2025-01-21")] alias condexp_ae_eq := condExp_ae_eq + protected theorem integrable (hf : Martingale f ℱ μ) (i : ι) : Integrable (f i) μ := - integrable_condexp.congr (hf.condexp_ae_eq (le_refl i)) + integrable_condExp.congr (hf.condExp_ae_eq (le_refl i)) theorem setIntegral_eq [SigmaFiniteFiltration μ ℱ] (hf : Martingale f ℱ μ) {i j : ι} (hij : i ≤ j) {s : Set Ω} (hs : MeasurableSet[ℱ i] s) : ∫ ω in s, f i ω ∂μ = ∫ ω in s, f j ω ∂μ := by - rw [← @setIntegral_condexp _ _ _ _ _ (ℱ i) m0 _ _ _ (ℱ.le i) _ (hf.integrable j) hs] + rw [← @setIntegral_condExp _ _ _ _ _ (ℱ i) m0 _ _ _ (ℱ.le i) _ (hf.integrable j) hs] refine setIntegral_congr_ae (ℱ.le i s hs) ?_ filter_upwards [hf.2 i j hij] with _ heq _ using heq.symm @@ -105,17 +107,17 @@ alias set_integral_eq := setIntegral_eq theorem add (hf : Martingale f ℱ μ) (hg : Martingale g ℱ μ) : Martingale (f + g) ℱ μ := by refine ⟨hf.adapted.add hg.adapted, fun i j hij => ?_⟩ - exact (condexp_add (hf.integrable j) (hg.integrable j)).trans ((hf.2 i j hij).add (hg.2 i j hij)) + exact (condExp_add (hf.integrable j) (hg.integrable j)).trans ((hf.2 i j hij).add (hg.2 i j hij)) theorem neg (hf : Martingale f ℱ μ) : Martingale (-f) ℱ μ := - ⟨hf.adapted.neg, fun i j hij => (condexp_neg (f j)).trans (hf.2 i j hij).neg⟩ + ⟨hf.adapted.neg, fun i j hij => (condExp_neg (f j)).trans (hf.2 i j hij).neg⟩ theorem sub (hf : Martingale f ℱ μ) (hg : Martingale g ℱ μ) : Martingale (f - g) ℱ μ := by rw [sub_eq_add_neg]; exact hf.add hg.neg theorem smul (c : ℝ) (hf : Martingale f ℱ μ) : Martingale (c • f) ℱ μ := by refine ⟨hf.adapted.smul c, fun i j hij => ?_⟩ - refine (condexp_smul c (f j)).trans ((hf.2 i j hij).mono fun x hx => ?_) + refine (condExp_smul c (f j)).trans ((hf.2 i j hij).mono fun x hx => ?_) simp only [Pi.smul_apply, hx] theorem supermartingale [Preorder E] (hf : Martingale f ℱ μ) : Supermartingale f ℱ μ := @@ -131,9 +133,11 @@ theorem martingale_iff [PartialOrder E] : ⟨fun hf => ⟨hf.supermartingale, hf.submartingale⟩, fun ⟨hf₁, hf₂⟩ => ⟨hf₁.1, fun i j hij => (hf₁.2.1 i j hij).antisymm (hf₂.2.1 i j hij)⟩⟩ -theorem martingale_condexp (f : Ω → E) (ℱ : Filtration ι m0) (μ : Measure Ω) +theorem martingale_condExp (f : Ω → E) (ℱ : Filtration ι m0) (μ : Measure Ω) [SigmaFiniteFiltration μ ℱ] : Martingale (fun i => μ[f|ℱ i]) ℱ μ := - ⟨fun _ => stronglyMeasurable_condexp, fun _ j hij => condexp_condexp_of_le (ℱ.mono hij) (ℱ.le j)⟩ + ⟨fun _ => stronglyMeasurable_condExp, fun _ j hij => condExp_condExp_of_le (ℱ.mono hij) (ℱ.le j)⟩ + +@[deprecated (since := "2025-01-21")] alias martingale_condexp := martingale_condExp namespace Supermartingale @@ -147,15 +151,17 @@ protected theorem stronglyMeasurable [LE E] (hf : Supermartingale f ℱ μ) (i : protected theorem integrable [LE E] (hf : Supermartingale f ℱ μ) (i : ι) : Integrable (f i) μ := hf.2.2 i -theorem condexp_ae_le [LE E] (hf : Supermartingale f ℱ μ) {i j : ι} (hij : i ≤ j) : +theorem condExp_ae_le [LE E] (hf : Supermartingale f ℱ μ) {i j : ι} (hij : i ≤ j) : μ[f j|ℱ i] ≤ᵐ[μ] f i := hf.2.1 i j hij +@[deprecated (since := "2025-01-21")] alias condexp_ae_le := condExp_ae_le + theorem setIntegral_le [SigmaFiniteFiltration μ ℱ] {f : ι → Ω → ℝ} (hf : Supermartingale f ℱ μ) {i j : ι} (hij : i ≤ j) {s : Set Ω} (hs : MeasurableSet[ℱ i] s) : ∫ ω in s, f j ω ∂μ ≤ ∫ ω in s, f i ω ∂μ := by - rw [← setIntegral_condexp (ℱ.le i) (hf.integrable j) hs] - refine setIntegral_mono_ae integrable_condexp.integrableOn (hf.integrable i).integrableOn ?_ + rw [← setIntegral_condExp (ℱ.le i) (hf.integrable j) hs] + refine setIntegral_mono_ae integrable_condExp.integrableOn (hf.integrable i).integrableOn ?_ filter_upwards [hf.2.1 i j hij] with _ heq using heq @[deprecated (since := "2024-04-17")] @@ -164,7 +170,7 @@ alias set_integral_le := setIntegral_le theorem add [Preorder E] [AddLeftMono E] (hf : Supermartingale f ℱ μ) (hg : Supermartingale g ℱ μ) : Supermartingale (f + g) ℱ μ := by refine ⟨hf.1.add hg.1, fun i j hij => ?_, fun i => (hf.2.2 i).add (hg.2.2 i)⟩ - refine (condexp_add (hf.integrable j) (hg.integrable j)).le.trans ?_ + refine (condExp_add (hf.integrable j) (hg.integrable j)).le.trans ?_ filter_upwards [hf.2.1 i j hij, hg.2.1 i j hij] intros refine add_le_add ?_ ?_ <;> assumption @@ -176,7 +182,7 @@ theorem add_martingale [Preorder E] [AddLeftMono E] theorem neg [Preorder E] [AddLeftMono E] (hf : Supermartingale f ℱ μ) : Submartingale (-f) ℱ μ := by refine ⟨hf.1.neg, fun i j hij => ?_, fun i => (hf.2.2 i).neg⟩ - refine EventuallyLE.trans ?_ (condexp_neg (f j)).symm.le + refine EventuallyLE.trans ?_ (condExp_neg (f j)).symm.le filter_upwards [hf.2.1 i j hij] with _ _ simpa @@ -194,14 +200,16 @@ protected theorem stronglyMeasurable [LE E] (hf : Submartingale f ℱ μ) (i : protected theorem integrable [LE E] (hf : Submartingale f ℱ μ) (i : ι) : Integrable (f i) μ := hf.2.2 i -theorem ae_le_condexp [LE E] (hf : Submartingale f ℱ μ) {i j : ι} (hij : i ≤ j) : +theorem ae_le_condExp [LE E] (hf : Submartingale f ℱ μ) {i j : ι} (hij : i ≤ j) : f i ≤ᵐ[μ] μ[f j|ℱ i] := hf.2.1 i j hij +@[deprecated (since := "2025-01-21")] alias ae_le_condexp := ae_le_condExp + theorem add [Preorder E] [AddLeftMono E] (hf : Submartingale f ℱ μ) (hg : Submartingale g ℱ μ) : Submartingale (f + g) ℱ μ := by refine ⟨hf.1.add hg.1, fun i j hij => ?_, fun i => (hf.2.2 i).add (hg.2.2 i)⟩ - refine EventuallyLE.trans ?_ (condexp_add (hf.integrable j) (hg.integrable j)).symm.le + refine EventuallyLE.trans ?_ (condExp_add (hf.integrable j) (hg.integrable j)).symm.le filter_upwards [hf.2.1 i j hij, hg.2.1 i j hij] intros refine add_le_add ?_ ?_ <;> assumption @@ -212,7 +220,7 @@ theorem add_martingale [Preorder E] [AddLeftMono E] (hf : Submartingale f ℱ μ theorem neg [Preorder E] [AddLeftMono E] (hf : Submartingale f ℱ μ) : Supermartingale (-f) ℱ μ := by - refine ⟨hf.1.neg, fun i j hij => (condexp_neg (f j)).le.trans ?_, fun i => (hf.2.2 i).neg⟩ + refine ⟨hf.1.neg, fun i j hij => (condExp_neg (f j)).le.trans ?_, fun i => (hf.2.2 i).neg⟩ filter_upwards [hf.2.1 i j hij] with _ _ simpa @@ -240,10 +248,10 @@ protected theorem sup {f g : ι → Ω → ℝ} (hf : Submartingale f ℱ μ) (h fun i j hij => ?_, fun i => Integrable.sup (hf.integrable _) (hg.integrable _)⟩ refine EventuallyLE.sup_le ?_ ?_ · exact EventuallyLE.trans (hf.2.1 i j hij) - (condexp_mono (hf.integrable _) (Integrable.sup (hf.integrable j) (hg.integrable j)) + (condExp_mono (hf.integrable _) (Integrable.sup (hf.integrable j) (hg.integrable j)) (Eventually.of_forall fun x => le_max_left _ _)) · exact EventuallyLE.trans (hg.2.1 i j hij) - (condexp_mono (hg.integrable _) (Integrable.sup (hf.integrable j) (hg.integrable j)) + (condExp_mono (hg.integrable _) (Integrable.sup (hf.integrable j) (hg.integrable j)) (Eventually.of_forall fun x => le_max_right _ _)) protected theorem pos {f : ι → Ω → ℝ} (hf : Submartingale f ℱ μ) : Submartingale (f⁺) ℱ μ := @@ -263,37 +271,46 @@ theorem submartingale_of_setIntegral_le [IsFiniteMeasure μ] {f : ι → Ω → filter_upwards [this] with x hx rwa [← sub_nonneg] refine ae_nonneg_of_forall_setIntegral_nonneg - ((integrable_condexp.sub (hint i)).trim _ (stronglyMeasurable_condexp.sub <| hadp i)) + ((integrable_condExp.sub (hint i)).trim _ (stronglyMeasurable_condExp.sub <| hadp i)) fun s hs _ => ?_ specialize hf i j hij s hs - rwa [← setIntegral_trim _ (stronglyMeasurable_condexp.sub <| hadp i) hs, - integral_sub' integrable_condexp.integrableOn (hint i).integrableOn, sub_nonneg, - setIntegral_condexp (ℱ.le i) (hint j) hs] + rwa [← setIntegral_trim _ (stronglyMeasurable_condExp.sub <| hadp i) hs, + integral_sub' integrable_condExp.integrableOn (hint i).integrableOn, sub_nonneg, + setIntegral_condExp (ℱ.le i) (hint j) hs] @[deprecated (since := "2024-04-17")] alias submartingale_of_set_integral_le := submartingale_of_setIntegral_le -theorem submartingale_of_condexp_sub_nonneg [IsFiniteMeasure μ] {f : ι → Ω → ℝ} (hadp : Adapted ℱ f) +theorem submartingale_of_condExp_sub_nonneg [IsFiniteMeasure μ] {f : ι → Ω → ℝ} (hadp : Adapted ℱ f) (hint : ∀ i, Integrable (f i) μ) (hf : ∀ i j, i ≤ j → 0 ≤ᵐ[μ] μ[f j - f i|ℱ i]) : Submartingale f ℱ μ := by refine ⟨hadp, fun i j hij => ?_, hint⟩ - rw [← condexp_of_stronglyMeasurable (ℱ.le _) (hadp _) (hint _), ← eventually_sub_nonneg] - exact EventuallyLE.trans (hf i j hij) (condexp_sub (hint _) (hint _)).le + rw [← condExp_of_stronglyMeasurable (ℱ.le _) (hadp _) (hint _), ← eventually_sub_nonneg] + exact EventuallyLE.trans (hf i j hij) (condExp_sub (hint _) (hint _)).le + +@[deprecated (since := "2025-01-21")] +alias submartingale_of_condexp_sub_nonneg := submartingale_of_condExp_sub_nonneg -theorem Submartingale.condexp_sub_nonneg {f : ι → Ω → ℝ} (hf : Submartingale f ℱ μ) {i j : ι} +theorem Submartingale.condExp_sub_nonneg {f : ι → Ω → ℝ} (hf : Submartingale f ℱ μ) {i j : ι} (hij : i ≤ j) : 0 ≤ᵐ[μ] μ[f j - f i|ℱ i] := by by_cases h : SigmaFinite (μ.trim (ℱ.le i)) - swap; · rw [condexp_of_not_sigmaFinite (ℱ.le i) h] - refine EventuallyLE.trans ?_ (condexp_sub (hf.integrable _) (hf.integrable _)).symm.le + swap; · rw [condExp_of_not_sigmaFinite (ℱ.le i) h] + refine EventuallyLE.trans ?_ (condExp_sub (hf.integrable _) (hf.integrable _)).symm.le rw [eventually_sub_nonneg, - condexp_of_stronglyMeasurable (ℱ.le _) (hf.adapted _) (hf.integrable _)] + condExp_of_stronglyMeasurable (ℱ.le _) (hf.adapted _) (hf.integrable _)] exact hf.2.1 i j hij -theorem submartingale_iff_condexp_sub_nonneg [IsFiniteMeasure μ] {f : ι → Ω → ℝ} : +@[deprecated (since := "2025-01-21")] +alias Submartingale.condexp_sub_nonneg := Submartingale.condExp_sub_nonneg + +theorem submartingale_iff_condExp_sub_nonneg [IsFiniteMeasure μ] {f : ι → Ω → ℝ} : Submartingale f ℱ μ ↔ Adapted ℱ f ∧ (∀ i, Integrable (f i) μ) ∧ ∀ i j, i ≤ j → 0 ≤ᵐ[μ] μ[f j - f i|ℱ i] := - ⟨fun h => ⟨h.adapted, h.integrable, fun _ _ => h.condexp_sub_nonneg⟩, fun ⟨hadp, hint, h⟩ => - submartingale_of_condexp_sub_nonneg hadp hint h⟩ + ⟨fun h => ⟨h.adapted, h.integrable, fun _ _ => h.condExp_sub_nonneg⟩, fun ⟨hadp, hint, h⟩ => + submartingale_of_condExp_sub_nonneg hadp hint h⟩ + +@[deprecated (since := "2025-01-21")] +alias submartingale_iff_condexp_sub_nonneg := submartingale_iff_condExp_sub_nonneg end Submartingale @@ -315,7 +332,7 @@ variable {F : Type*} [NormedLatticeAddCommGroup F] [NormedSpace ℝ F] [Complete theorem smul_nonneg {f : ι → Ω → F} {c : ℝ} (hc : 0 ≤ c) (hf : Supermartingale f ℱ μ) : Supermartingale (c • f) ℱ μ := by refine ⟨hf.1.smul c, fun i j hij => ?_, fun i => (hf.2.2 i).smul c⟩ - refine (condexp_smul c (f j)).le.trans ?_ + refine (condExp_smul c (f j)).le.trans ?_ filter_upwards [hf.2.1 i j hij] with _ hle simp_rw [Pi.smul_apply] exact smul_le_smul_of_nonneg_left hle hc @@ -392,16 +409,16 @@ theorem submartingale_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Submartingale f 𝒢 μ := by refine submartingale_of_setIntegral_le_succ hadp hint fun i s hs => ?_ have : ∫ ω in s, f (i + 1) ω ∂μ = ∫ ω in s, (μ[f (i + 1)|𝒢 i]) ω ∂μ := - (setIntegral_condexp (𝒢.le i) (hint _) hs).symm + (setIntegral_condExp (𝒢.le i) (hint _) hs).symm rw [this] - exact setIntegral_mono_ae (hint i).integrableOn integrable_condexp.integrableOn (hf i) + exact setIntegral_mono_ae (hint i).integrableOn integrable_condExp.integrableOn (hf i) theorem supermartingale_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Adapted 𝒢 f) (hint : ∀ i, Integrable (f i) μ) (hf : ∀ i, μ[f (i + 1)|𝒢 i] ≤ᵐ[μ] f i) : Supermartingale f 𝒢 μ := by rw [← neg_neg f] refine (submartingale_nat hadp.neg (fun i => (hint i).neg) fun i => - EventuallyLE.trans ?_ (condexp_neg _).symm.le).neg + EventuallyLE.trans ?_ (condExp_neg _).symm.le).neg filter_upwards [hf i] with x hx using neg_le_neg hx theorem martingale_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Adapted 𝒢 f) @@ -409,30 +426,39 @@ theorem martingale_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Ada martingale_iff.2 ⟨supermartingale_nat hadp hint fun i => (hf i).symm.le, submartingale_nat hadp hint fun i => (hf i).le⟩ -theorem submartingale_of_condexp_sub_nonneg_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} +theorem submartingale_of_condExp_sub_nonneg_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Adapted 𝒢 f) (hint : ∀ i, Integrable (f i) μ) (hf : ∀ i, 0 ≤ᵐ[μ] μ[f (i + 1) - f i|𝒢 i]) : Submartingale f 𝒢 μ := by refine submartingale_nat hadp hint fun i => ?_ - rw [← condexp_of_stronglyMeasurable (𝒢.le _) (hadp _) (hint _), ← eventually_sub_nonneg] - exact EventuallyLE.trans (hf i) (condexp_sub (hint _) (hint _)).le + rw [← condExp_of_stronglyMeasurable (𝒢.le _) (hadp _) (hint _), ← eventually_sub_nonneg] + exact EventuallyLE.trans (hf i) (condExp_sub (hint _) (hint _)).le + +@[deprecated (since := "2025-01-21")] +alias submartingale_of_condexp_sub_nonneg_nat := submartingale_of_condExp_sub_nonneg_nat -theorem supermartingale_of_condexp_sub_nonneg_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} +theorem supermartingale_of_condExp_sub_nonneg_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Adapted 𝒢 f) (hint : ∀ i, Integrable (f i) μ) (hf : ∀ i, 0 ≤ᵐ[μ] μ[f i - f (i + 1)|𝒢 i]) : Supermartingale f 𝒢 μ := by rw [← neg_neg f] - refine (submartingale_of_condexp_sub_nonneg_nat hadp.neg (fun i => (hint i).neg) ?_).neg + refine (submartingale_of_condExp_sub_nonneg_nat hadp.neg (fun i => (hint i).neg) ?_).neg simpa only [Pi.zero_apply, Pi.neg_apply, neg_sub_neg] -theorem martingale_of_condexp_sub_eq_zero_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} +@[deprecated (since := "2025-01-21")] +alias supermartingale_of_condexp_sub_nonneg_nat := supermartingale_of_condExp_sub_nonneg_nat + +theorem martingale_of_condExp_sub_eq_zero_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Adapted 𝒢 f) (hint : ∀ i, Integrable (f i) μ) (hf : ∀ i, μ[f (i + 1) - f i|𝒢 i] =ᵐ[μ] 0) : Martingale f 𝒢 μ := by - refine martingale_iff.2 ⟨supermartingale_of_condexp_sub_nonneg_nat hadp hint fun i => ?_, - submartingale_of_condexp_sub_nonneg_nat hadp hint fun i => (hf i).symm.le⟩ + refine martingale_iff.2 ⟨supermartingale_of_condExp_sub_nonneg_nat hadp hint fun i => ?_, + submartingale_of_condExp_sub_nonneg_nat hadp hint fun i => (hf i).symm.le⟩ rw [← neg_sub] - refine (EventuallyEq.trans ?_ (condexp_neg _).symm).le + refine (EventuallyEq.trans ?_ (condExp_neg _).symm).le filter_upwards [hf i] with x hx simpa only [Pi.zero_apply, Pi.neg_apply, zero_eq_neg] +@[deprecated (since := "2025-01-21")] +alias martingale_of_condexp_sub_eq_zero_nat := martingale_of_condExp_sub_eq_zero_nat + -- Note that one cannot use `Submartingale.zero_le_of_predictable` to prove the other two -- corresponding lemmas without imposing more restrictions to the ordering of `E` /-- A predictable submartingale is a.e. greater equal than its initial state. -/ @@ -442,7 +468,7 @@ theorem Submartingale.zero_le_of_predictable [Preorder E] [SigmaFiniteFiltration induction' n with k ih · rfl · exact ih.trans ((hfmgle.2.1 k (k + 1) k.le_succ).trans_eq <| Germ.coe_eq.mp <| - congr_arg Germ.ofFun <| condexp_of_stronglyMeasurable (𝒢.le _) (hfadp _) <| hfmgle.integrable _) + congr_arg Germ.ofFun <| condExp_of_stronglyMeasurable (𝒢.le _) (hfadp _) <| hfmgle.integrable _) /-- A predictable supermartingale is a.e. less equal than its initial state. -/ theorem Supermartingale.le_zero_of_predictable [Preorder E] [SigmaFiniteFiltration μ 𝒢] @@ -450,7 +476,7 @@ theorem Supermartingale.le_zero_of_predictable [Preorder E] [SigmaFiniteFiltrati (n : ℕ) : f n ≤ᵐ[μ] f 0 := by induction' n with k ih · rfl - · exact ((Germ.coe_eq.mp <| congr_arg Germ.ofFun <| condexp_of_stronglyMeasurable (𝒢.le _) + · exact ((Germ.coe_eq.mp <| congr_arg Germ.ofFun <| condExp_of_stronglyMeasurable (𝒢.le _) (hfadp _) <| hfmgle.integrable _).symm.trans_le (hfmgle.2.1 k (k + 1) k.le_succ)).trans ih /-- A predictable martingale is a.e. equal to its initial state. -/ @@ -458,7 +484,7 @@ theorem Martingale.eq_zero_of_predictable [SigmaFiniteFiltration μ 𝒢] {f : (hfmgle : Martingale f 𝒢 μ) (hfadp : Adapted 𝒢 fun n => f (n + 1)) (n : ℕ) : f n =ᵐ[μ] f 0 := by induction' n with k ih · rfl - · exact ((Germ.coe_eq.mp (congr_arg Germ.ofFun <| condexp_of_stronglyMeasurable (𝒢.le _) (hfadp _) + · exact ((Germ.coe_eq.mp (congr_arg Germ.ofFun <| condExp_of_stronglyMeasurable (𝒢.le _) (hfadp _) (hfmgle.integrable _))).symm.trans (hfmgle.2 k (k + 1) k.le_succ)).trans ih namespace Submartingale @@ -486,11 +512,11 @@ theorem Submartingale.sum_mul_sub [IsFiniteMeasure μ] {R : ℝ} {ξ f : ℕ → exact (hξ.stronglyMeasurable_le hi.le).mul ((hf.adapted.stronglyMeasurable_le (Nat.succ_le_of_lt hi)).sub (hf.adapted.stronglyMeasurable_le hi.le)) - refine submartingale_of_condexp_sub_nonneg_nat hadp hint fun i => ?_ + refine submartingale_of_condExp_sub_nonneg_nat hadp hint fun i => ?_ simp only [← Finset.sum_Ico_eq_sub _ (Nat.le_succ _), Finset.sum_apply, Pi.mul_apply, Pi.sub_apply, Nat.Ico_succ_singleton, Finset.sum_singleton] exact EventuallyLE.trans (EventuallyLE.mul_nonneg (Eventually.of_forall (hnonneg _)) - (hf.condexp_sub_nonneg (Nat.le_succ _))) (condexp_mul_of_stronglyMeasurable_left (hξ _) + (hf.condExp_sub_nonneg (Nat.le_succ _))) (condExp_mul_of_stronglyMeasurable_left (hξ _) (((hf.integrable _).sub (hf.integrable _)).bdd_mul hξ.stronglyMeasurable.aestronglyMeasurable (hξbdd _)) ((hf.integrable _).sub (hf.integrable _))).symm.le diff --git a/Mathlib/Probability/Martingale/BorelCantelli.lean b/Mathlib/Probability/Martingale/BorelCantelli.lean index f00e58badb8f1..7edfbb36da6b5 100644 --- a/Mathlib/Probability/Martingale/BorelCantelli.lean +++ b/Mathlib/Probability/Martingale/BorelCantelli.lean @@ -321,7 +321,7 @@ theorem tendsto_sum_indicator_atTop_iff [IsFiniteMeasure μ] have h₂ := (martingale_martingalePart hf hint).ae_not_tendsto_atTop_atBot (martingalePart_bdd_difference ℱ hbdd) have h₃ : ∀ᵐ ω ∂μ, ∀ n, 0 ≤ (μ[f (n + 1) - f n|ℱ n]) ω := by - refine ae_all_iff.2 fun n => condexp_nonneg ?_ + refine ae_all_iff.2 fun n => condExp_nonneg ?_ filter_upwards [ae_all_iff.1 hfmono n] with ω hω using sub_nonneg.2 hω filter_upwards [h₁, h₂, h₃, hfmono] with ω hω₁ hω₂ hω₃ hω₄ constructor <;> intro ht diff --git a/Mathlib/Probability/Martingale/Centering.lean b/Mathlib/Probability/Martingale/Centering.lean index 2cfee94899d77..4b33ee59f7e98 100644 --- a/Mathlib/Probability/Martingale/Centering.lean +++ b/Mathlib/Probability/Martingale/Centering.lean @@ -49,11 +49,11 @@ theorem predictablePart_zero : predictablePart f ℱ μ 0 = 0 := by theorem adapted_predictablePart : Adapted ℱ fun n => predictablePart f ℱ μ (n + 1) := fun _ => Finset.stronglyMeasurable_sum' _ fun _ hin => - stronglyMeasurable_condexp.mono (ℱ.mono (Finset.mem_range_succ_iff.mp hin)) + stronglyMeasurable_condExp.mono (ℱ.mono (Finset.mem_range_succ_iff.mp hin)) theorem adapted_predictablePart' : Adapted ℱ fun n => predictablePart f ℱ μ n := fun _ => Finset.stronglyMeasurable_sum' _ fun _ hin => - stronglyMeasurable_condexp.mono (ℱ.mono (Finset.mem_range_le hin)) + stronglyMeasurable_condExp.mono (ℱ.mono (Finset.mem_range_le hin)) /-- Any `ℕ`-indexed stochastic process can be written as the sum of a martingale and a predictable process. This is the martingale. See `predictablePart` for the predictable process. -/ @@ -77,7 +77,7 @@ theorem integrable_martingalePart (hf_int : ∀ n, Integrable (f n) μ) (n : ℕ Integrable (martingalePart f ℱ μ n) μ := by rw [martingalePart_eq_sum] exact (hf_int 0).add - (integrable_finset_sum' _ fun i _ => ((hf_int _).sub (hf_int _)).sub integrable_condexp) + (integrable_finset_sum' _ fun i _ => ((hf_int _).sub (hf_int _)).sub integrable_condExp) theorem martingale_martingalePart (hf : Adapted ℱ f) (hf_int : ∀ n, Integrable (f n) μ) [SigmaFiniteFiltration μ ℱ] : Martingale (martingalePart f ℱ μ) ℱ μ := by @@ -86,30 +86,30 @@ theorem martingale_martingalePart (hf : Adapted ℱ f) (hf_int : ∀ n, Integrab have h_eq_sum : μ[martingalePart f ℱ μ j|ℱ i] =ᵐ[μ] f 0 + ∑ k ∈ Finset.range j, (μ[f (k + 1) - f k|ℱ i] - μ[μ[f (k + 1) - f k|ℱ k]|ℱ i]) := by rw [martingalePart_eq_sum] - refine (condexp_add (hf_int 0) ?_).trans ?_ - · exact integrable_finset_sum' _ fun i _ => ((hf_int _).sub (hf_int _)).sub integrable_condexp - refine (EventuallyEq.add EventuallyEq.rfl (condexp_finset_sum fun i _ => ?_)).trans ?_ - · exact ((hf_int _).sub (hf_int _)).sub integrable_condexp + refine (condExp_add (hf_int 0) ?_).trans ?_ + · exact integrable_finset_sum' _ fun i _ => ((hf_int _).sub (hf_int _)).sub integrable_condExp + refine (EventuallyEq.add EventuallyEq.rfl (condExp_finset_sum fun i _ => ?_)).trans ?_ + · exact ((hf_int _).sub (hf_int _)).sub integrable_condExp refine EventuallyEq.add ?_ ?_ - · rw [condexp_of_stronglyMeasurable (ℱ.le _) _ (hf_int 0)] + · rw [condExp_of_stronglyMeasurable (ℱ.le _) _ (hf_int 0)] · exact (hf 0).mono (ℱ.mono (zero_le i)) - · exact eventuallyEq_sum fun k _ => condexp_sub ((hf_int _).sub (hf_int _)) integrable_condexp + · exact eventuallyEq_sum fun k _ => condExp_sub ((hf_int _).sub (hf_int _)) integrable_condExp refine h_eq_sum.trans ?_ have h_ge : ∀ k, i ≤ k → μ[f (k + 1) - f k|ℱ i] - μ[μ[f (k + 1) - f k|ℱ k]|ℱ i] =ᵐ[μ] 0 := by intro k hk have : μ[μ[f (k + 1) - f k|ℱ k]|ℱ i] =ᵐ[μ] μ[f (k + 1) - f k|ℱ i] := - condexp_condexp_of_le (ℱ.mono hk) (ℱ.le k) + condExp_condExp_of_le (ℱ.mono hk) (ℱ.le k) filter_upwards [this] with x hx rw [Pi.sub_apply, Pi.zero_apply, hx, sub_self] have h_lt : ∀ k, k < i → μ[f (k + 1) - f k|ℱ i] - μ[μ[f (k + 1) - f k|ℱ k]|ℱ i] =ᵐ[μ] f (k + 1) - f k - μ[f (k + 1) - f k|ℱ k] := by refine fun k hk => EventuallyEq.sub ?_ ?_ - · rw [condexp_of_stronglyMeasurable] + · rw [condExp_of_stronglyMeasurable] · exact ((hf (k + 1)).mono (ℱ.mono (Nat.succ_le_of_lt hk))).sub ((hf k).mono (ℱ.mono hk.le)) · exact (hf_int _).sub (hf_int _) - · rw [condexp_of_stronglyMeasurable] - · exact stronglyMeasurable_condexp.mono (ℱ.mono hk.le) - · exact integrable_condexp + · rw [condExp_of_stronglyMeasurable] + · exact stronglyMeasurable_condExp.mono (ℱ.mono hk.le) + · exact integrable_condExp rw [martingalePart_eq_sum] refine EventuallyEq.add EventuallyEq.rfl ?_ rw [← Finset.sum_range_add_sum_Ico _ hij, ← @@ -154,7 +154,7 @@ theorem predictablePart_bdd_difference {R : ℝ≥0} {f : ℕ → Ω → ℝ} ( (hbdd : ∀ᵐ ω ∂μ, ∀ i, |f (i + 1) ω - f i ω| ≤ R) : ∀ᵐ ω ∂μ, ∀ i, |predictablePart f ℱ μ (i + 1) ω - predictablePart f ℱ μ i ω| ≤ R := by simp_rw [predictablePart, Finset.sum_apply, Finset.sum_range_succ_sub_sum] - exact ae_all_iff.2 fun i => ae_bdd_condexp_of_ae_bdd <| ae_all_iff.1 hbdd i + exact ae_all_iff.2 fun i => ae_bdd_condExp_of_ae_bdd <| ae_all_iff.1 hbdd i theorem martingalePart_bdd_difference {R : ℝ≥0} {f : ℕ → Ω → ℝ} (ℱ : Filtration ℕ m0) (hbdd : ∀ᵐ ω ∂μ, ∀ i, |f (i + 1) ω - f i ω| ≤ R) : diff --git a/Mathlib/Probability/Martingale/Convergence.lean b/Mathlib/Probability/Martingale/Convergence.lean index 11b1183ad6b5c..bc762e65c4237 100644 --- a/Mathlib/Probability/Martingale/Convergence.lean +++ b/Mathlib/Probability/Martingale/Convergence.lean @@ -29,13 +29,13 @@ theorems. convergence theorem: a uniformly integrable submartingale adapted to the filtration `ℱ` converges almost everywhere and in L¹ to an integrable function which is measurable with respect to the σ-algebra `⨆ n, ℱ n`. -* `MeasureTheory.Martingale.ae_eq_condexp_limitProcess`: part b the L¹ martingale convergence +* `MeasureTheory.Martingale.ae_eq_condExp_limitProcess`: part b the L¹ martingale convergence theorem: if `f` is a uniformly integrable martingale adapted to the filtration `ℱ`, then `f n` equals `𝔼[g | ℱ n]` almost everywhere where `g` is the limiting process of `f`. -* `MeasureTheory.Integrable.tendsto_ae_condexp`: part c the L¹ martingale convergence theorem: +* `MeasureTheory.Integrable.tendsto_ae_condExp`: part c the L¹ martingale convergence theorem: given a `⨆ n, ℱ n`-measurable function `g` where `ℱ` is a filtration, `𝔼[g | ℱ n]` converges almost everywhere to `g`. -* `MeasureTheory.Integrable.tendsto_eLpNorm_condexp`: part c the L¹ martingale convergence theorem: +* `MeasureTheory.Integrable.tendsto_eLpNorm_condExp`: part c the L¹ martingale convergence theorem: given a `⨆ n, ℱ n`-measurable function `g` where `ℱ` is a filtration, `𝔼[g | ℱ n]` converges in L¹ to `g`. @@ -325,58 +325,67 @@ theorem Submartingale.ae_tendsto_limitProcess_of_uniformIntegrable (hf : Submart /-- If a martingale `f` adapted to `ℱ` converges in L¹ to `g`, then for all `n`, `f n` is almost everywhere equal to `𝔼[g | ℱ n]`. -/ -theorem Martingale.eq_condexp_of_tendsto_eLpNorm {μ : Measure Ω} (hf : Martingale f ℱ μ) +theorem Martingale.eq_condExp_of_tendsto_eLpNorm {μ : Measure Ω} (hf : Martingale f ℱ μ) (hg : Integrable g μ) (hgtends : Tendsto (fun n => eLpNorm (f n - g) 1 μ) atTop (𝓝 0)) (n : ℕ) : f n =ᵐ[μ] μ[g|ℱ n] := by rw [← sub_ae_eq_zero, ← eLpNorm_eq_zero_iff (((hf.stronglyMeasurable n).mono (ℱ.le _)).sub - (stronglyMeasurable_condexp.mono (ℱ.le _))).aestronglyMeasurable one_ne_zero] + (stronglyMeasurable_condExp.mono (ℱ.le _))).aestronglyMeasurable one_ne_zero] have ht : Tendsto (fun m => eLpNorm (μ[f m - g|ℱ n]) 1 μ) atTop (𝓝 0) := haveI hint : ∀ m, Integrable (f m - g) μ := fun m => (hf.integrable m).sub hg tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds hgtends (fun m => zero_le _) - fun m => eLpNorm_one_condexp_le_eLpNorm _ + fun m => eLpNorm_one_condExp_le_eLpNorm _ have hev : ∀ m ≥ n, eLpNorm (μ[f m - g|ℱ n]) 1 μ = eLpNorm (f n - μ[g|ℱ n]) 1 μ := by - refine fun m hm => eLpNorm_congr_ae ((condexp_sub (hf.integrable m) hg).trans ?_) + refine fun m hm => eLpNorm_congr_ae ((condExp_sub (hf.integrable m) hg).trans ?_) filter_upwards [hf.2 n m hm] with x hx simp only [hx, Pi.sub_apply] exact tendsto_nhds_unique (tendsto_atTop_of_eventually_const hev) ht +@[deprecated (since := "2025-01-21")] +alias Martingale.eq_condexp_of_tendsto_eLpNorm := Martingale.eq_condExp_of_tendsto_eLpNorm + @[deprecated (since := "2024-07-27")] -alias Martingale.eq_condexp_of_tendsto_snorm := Martingale.eq_condexp_of_tendsto_eLpNorm +alias Martingale.eq_condExp_of_tendsto_snorm := Martingale.eq_condExp_of_tendsto_eLpNorm + +@[deprecated (since := "2025-01-21")] +alias Martingale.eq_condexp_of_tendsto_snorm := Martingale.eq_condExp_of_tendsto_snorm /-- Part b of the **L¹ martingale convergence theorem**: if `f` is a uniformly integrable martingale adapted to the filtration `ℱ`, then for all `n`, `f n` is almost everywhere equal to the conditional expectation of its limiting process wrt. `ℱ n`. -/ -theorem Martingale.ae_eq_condexp_limitProcess (hf : Martingale f ℱ μ) +theorem Martingale.ae_eq_condExp_limitProcess (hf : Martingale f ℱ μ) (hbdd : UniformIntegrable f 1 μ) (n : ℕ) : f n =ᵐ[μ] μ[ℱ.limitProcess f μ|ℱ n] := let ⟨_, hR⟩ := hbdd.2.2 - hf.eq_condexp_of_tendsto_eLpNorm ((memℒp_limitProcess_of_eLpNorm_bdd hbdd.1 hR).integrable le_rfl) + hf.eq_condExp_of_tendsto_eLpNorm ((memℒp_limitProcess_of_eLpNorm_bdd hbdd.1 hR).integrable le_rfl) (hf.submartingale.tendsto_eLpNorm_one_limitProcess hbdd) n +@[deprecated (since := "2025-01-21")] +alias Martingale.ae_eq_condexp_limitProcess := Martingale.ae_eq_condExp_limitProcess + /-- Part c of the **L¹ martingale convergence theorem**: Given an integrable function `g` which is measurable with respect to `⨆ n, ℱ n` where `ℱ` is a filtration, the martingale defined by `𝔼[g | ℱ n]` converges almost everywhere to `g`. This martingale also converges to `g` in L¹ and this result is provided by -`MeasureTheory.Integrable.tendsto_eLpNorm_condexp` -/ -theorem Integrable.tendsto_ae_condexp (hg : Integrable g μ) +`MeasureTheory.Integrable.tendsto_eLpNorm_condExp` -/ +theorem Integrable.tendsto_ae_condExp (hg : Integrable g μ) (hgmeas : StronglyMeasurable[⨆ n, ℱ n] g) : ∀ᵐ x ∂μ, Tendsto (fun n => (μ[g|ℱ n]) x) atTop (𝓝 (g x)) := by have hle : ⨆ n, ℱ n ≤ m0 := sSup_le fun m ⟨n, hn⟩ => hn ▸ ℱ.le _ have hunif : UniformIntegrable (fun n => μ[g|ℱ n]) 1 μ := - hg.uniformIntegrable_condexp_filtration + hg.uniformIntegrable_condExp_filtration obtain ⟨R, hR⟩ := hunif.2.2 have hlimint : Integrable (ℱ.limitProcess (fun n => μ[g|ℱ n]) μ) μ := (memℒp_limitProcess_of_eLpNorm_bdd hunif.1 hR).integrable le_rfl suffices g =ᵐ[μ] ℱ.limitProcess (fun n x => (μ[g|ℱ n]) x) μ by - filter_upwards [this, (martingale_condexp g ℱ μ).submartingale.ae_tendsto_limitProcess hR] with + filter_upwards [this, (martingale_condExp g ℱ μ).submartingale.ae_tendsto_limitProcess hR] with x heq ht rwa [heq] have : ∀ n s, MeasurableSet[ℱ n] s → ∫ x in s, g x ∂μ = ∫ x in s, ℱ.limitProcess (fun n x => (μ[g|ℱ n]) x) μ x ∂μ := by intro n s hs - rw [← setIntegral_condexp (ℱ.le n) hg hs, ← setIntegral_condexp (ℱ.le n) hlimint hs] + rw [← setIntegral_condExp (ℱ.le n) hg hs, ← setIntegral_condExp (ℱ.le n) hlimint hs] refine setIntegral_congr_ae (ℱ.le _ _ hs) ?_ - filter_upwards [(martingale_condexp g ℱ μ).ae_eq_condexp_limitProcess hunif n] with x hx _ + filter_upwards [(martingale_condExp g ℱ μ).ae_eq_condExp_limitProcess hunif n] with x hx _ rw [hx] refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hle (fun s _ _ => hg.integrableOn) (fun s _ _ => hlimint.integrableOn) (fun s hs _ => ?_) hgmeas.aeStronglyMeasurable' @@ -406,51 +415,66 @@ theorem Integrable.tendsto_ae_condexp (hg : Integrable g μ) integral_iUnion (fun n => hle _ (hfmeas n)) hf hlimint.integrableOn] exact tsum_congr fun n => heq _ (measure_lt_top _ _) +@[deprecated (since := "2025-01-21")] +alias Integrable.tendsto_ae_condexp := Integrable.tendsto_ae_condExp + /-- Part c of the **L¹ martingale convergence theorem**: Given an integrable function `g` which is measurable with respect to `⨆ n, ℱ n` where `ℱ` is a filtration, the martingale defined by `𝔼[g | ℱ n]` converges in L¹ to `g`. This martingale also converges to `g` almost everywhere and this result is provided by -`MeasureTheory.Integrable.tendsto_ae_condexp` -/ -theorem Integrable.tendsto_eLpNorm_condexp (hg : Integrable g μ) +`MeasureTheory.Integrable.tendsto_ae_condExp` -/ +theorem Integrable.tendsto_eLpNorm_condExp (hg : Integrable g μ) (hgmeas : StronglyMeasurable[⨆ n, ℱ n] g) : Tendsto (fun n => eLpNorm (μ[g|ℱ n] - g) 1 μ) atTop (𝓝 0) := tendsto_Lp_finite_of_tendstoInMeasure le_rfl ENNReal.one_ne_top - (fun n => (stronglyMeasurable_condexp.mono (ℱ.le n)).aestronglyMeasurable) - (memℒp_one_iff_integrable.2 hg) hg.uniformIntegrable_condexp_filtration.2.1 + (fun n => (stronglyMeasurable_condExp.mono (ℱ.le n)).aestronglyMeasurable) + (memℒp_one_iff_integrable.2 hg) hg.uniformIntegrable_condExp_filtration.2.1 (tendstoInMeasure_of_tendsto_ae - (fun n => (stronglyMeasurable_condexp.mono (ℱ.le n)).aestronglyMeasurable) - (hg.tendsto_ae_condexp hgmeas)) + (fun n => (stronglyMeasurable_condExp.mono (ℱ.le n)).aestronglyMeasurable) + (hg.tendsto_ae_condExp hgmeas)) + +@[deprecated (since := "2025-01-21")] +alias Integrable.tendsto_eLpNorm_condexp := Integrable.tendsto_eLpNorm_condExp @[deprecated (since := "2024-07-27")] -alias Integrable.tendsto_snorm_condexp := Integrable.tendsto_eLpNorm_condexp +alias Integrable.tendsto_snorm_condExp := Integrable.tendsto_eLpNorm_condExp + +@[deprecated (since := "2025-01-21")] +alias Integrable.tendsto_snorm_condexp := Integrable.tendsto_snorm_condExp /-- **Lévy's upward theorem**, almost everywhere version: given a function `g` and a filtration `ℱ`, the sequence defined by `𝔼[g | ℱ n]` converges almost everywhere to `𝔼[g | ⨆ n, ℱ n]`. -/ -theorem tendsto_ae_condexp (g : Ω → ℝ) : +theorem tendsto_ae_condExp (g : Ω → ℝ) : ∀ᵐ x ∂μ, Tendsto (fun n => (μ[g|ℱ n]) x) atTop (𝓝 ((μ[g|⨆ n, ℱ n]) x)) := by have ht : ∀ᵐ x ∂μ, Tendsto (fun n => (μ[μ[g|⨆ n, ℱ n]|ℱ n]) x) atTop (𝓝 ((μ[g|⨆ n, ℱ n]) x)) := - integrable_condexp.tendsto_ae_condexp stronglyMeasurable_condexp + integrable_condExp.tendsto_ae_condExp stronglyMeasurable_condExp have heq : ∀ n, ∀ᵐ x ∂μ, (μ[μ[g|⨆ n, ℱ n]|ℱ n]) x = (μ[g|ℱ n]) x := fun n => - condexp_condexp_of_le (le_iSup _ n) (iSup_le fun n => ℱ.le n) + condExp_condExp_of_le (le_iSup _ n) (iSup_le fun n => ℱ.le n) rw [← ae_all_iff] at heq filter_upwards [heq, ht] with x hxeq hxt exact hxt.congr hxeq +@[deprecated (since := "2025-01-21")] alias tendsto_ae_condexp := tendsto_ae_condExp + /-- **Lévy's upward theorem**, L¹ version: given a function `g` and a filtration `ℱ`, the sequence defined by `𝔼[g | ℱ n]` converges in L¹ to `𝔼[g | ⨆ n, ℱ n]`. -/ -theorem tendsto_eLpNorm_condexp (g : Ω → ℝ) : +theorem tendsto_eLpNorm_condExp (g : Ω → ℝ) : Tendsto (fun n => eLpNorm (μ[g|ℱ n] - μ[g|⨆ n, ℱ n]) 1 μ) atTop (𝓝 0) := by have ht : Tendsto (fun n => eLpNorm (μ[μ[g|⨆ n, ℱ n]|ℱ n] - μ[g|⨆ n, ℱ n]) 1 μ) atTop (𝓝 0) := - integrable_condexp.tendsto_eLpNorm_condexp stronglyMeasurable_condexp + integrable_condExp.tendsto_eLpNorm_condExp stronglyMeasurable_condExp have heq : ∀ n, ∀ᵐ x ∂μ, (μ[μ[g|⨆ n, ℱ n]|ℱ n]) x = (μ[g|ℱ n]) x := fun n => - condexp_condexp_of_le (le_iSup _ n) (iSup_le fun n => ℱ.le n) + condExp_condExp_of_le (le_iSup _ n) (iSup_le fun n => ℱ.le n) refine ht.congr fun n => eLpNorm_congr_ae ?_ filter_upwards [heq n] with x hxeq simp only [hxeq, Pi.sub_apply] +@[deprecated (since := "2025-01-21")] alias tendsto_eLpNorm_condexp := tendsto_eLpNorm_condExp + @[deprecated (since := "2024-07-27")] -alias tendsto_snorm_condexp := tendsto_eLpNorm_condexp +alias tendsto_snorm_condExp := tendsto_eLpNorm_condExp + +@[deprecated (since := "2025-01-21")] alias tendsto_snorm_condexp := tendsto_snorm_condExp end L1Convergence diff --git a/Mathlib/Probability/Martingale/OptionalSampling.lean b/Mathlib/Probability/Martingale/OptionalSampling.lean index 90b9489aaa39c..6352474b3e335 100644 --- a/Mathlib/Probability/Martingale/OptionalSampling.lean +++ b/Mathlib/Probability/Martingale/OptionalSampling.lean @@ -15,13 +15,13 @@ If `τ` is a bounded stopping time and `σ` is another stopping time, then the v ## Main results -* `stoppedValue_ae_eq_condexp_of_le_const`: the value of a martingale `f` at a stopping time `τ` +* `stoppedValue_ae_eq_condExp_of_le_const`: the value of a martingale `f` at a stopping time `τ` bounded by `n` is the conditional expectation of `f n` with respect to the σ-algebra generated by `τ`. -* `stoppedValue_ae_eq_condexp_of_le`: if `τ` and `σ` are two stopping times with `σ ≤ τ` and `τ` is +* `stoppedValue_ae_eq_condExp_of_le`: if `τ` and `σ` are two stopping times with `σ ≤ τ` and `τ` is bounded, then the value of a martingale `f` at `σ` is the conditional expectation of its value at `τ` with respect to the σ-algebra generated by `σ`. -* `stoppedValue_min_ae_eq_condexp`: the optional sampling theorem. If `τ` is a bounded stopping +* `stoppedValue_min_ae_eq_condExp`: the optional sampling theorem. If `τ` is a bounded stopping time and `σ` is another stopping time, then the value of a martingale `f` at the stopping time `min τ σ` is almost everywhere equal to the conditional expectation of `f` stopped at `τ` with respect to the σ-algebra generated by `σ`. @@ -46,22 +46,25 @@ variable {ι : Type*} [LinearOrder ι] [TopologicalSpace ι] [OrderTopology ι] [FirstCountableTopology ι] {ℱ : Filtration ι m} [SigmaFiniteFiltration μ ℱ] {τ σ : Ω → ι} {f : ι → Ω → E} {i n : ι} -theorem condexp_stopping_time_ae_eq_restrict_eq_const +theorem condExp_stopping_time_ae_eq_restrict_eq_const [(Filter.atTop : Filter ι).IsCountablyGenerated] (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) [SigmaFinite (μ.trim hτ.measurableSpace_le)] (hin : i ≤ n) : μ[f n|hτ.measurableSpace] =ᵐ[μ.restrict {x | τ x = i}] f i := by - refine Filter.EventuallyEq.trans ?_ (ae_restrict_of_ae (h.condexp_ae_eq hin)) - refine condexp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le (ℱ.le i) + refine Filter.EventuallyEq.trans ?_ (ae_restrict_of_ae (h.condExp_ae_eq hin)) + refine condExp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le (ℱ.le i) (hτ.measurableSet_eq' i) fun t => ?_ rw [Set.inter_comm _ t, IsStoppingTime.measurableSet_inter_eq_iff] -theorem condexp_stopping_time_ae_eq_restrict_eq_const_of_le_const (h : Martingale f ℱ μ) +@[deprecated (since := "2025-01-21")] +alias condexp_stopping_time_ae_eq_restrict_eq_const := condExp_stopping_time_ae_eq_restrict_eq_const + +theorem condExp_stopping_time_ae_eq_restrict_eq_const_of_le_const (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hτ_le : ∀ x, τ x ≤ n) [SigmaFinite (μ.trim (hτ.measurableSpace_le_of_le hτ_le))] (i : ι) : μ[f n|hτ.measurableSpace] =ᵐ[μ.restrict {x | τ x = i}] f i := by by_cases hin : i ≤ n - · refine Filter.EventuallyEq.trans ?_ (ae_restrict_of_ae (h.condexp_ae_eq hin)) - refine condexp_ae_eq_restrict_of_measurableSpace_eq_on (hτ.measurableSpace_le_of_le hτ_le) + · refine Filter.EventuallyEq.trans ?_ (ae_restrict_of_ae (h.condExp_ae_eq hin)) + refine condExp_ae_eq_restrict_of_measurableSpace_eq_on (hτ.measurableSpace_le_of_le hτ_le) (ℱ.le i) (hτ.measurableSet_eq' i) fun t => ?_ rw [Set.inter_comm _ t, IsStoppingTime.measurableSet_inter_eq_iff] · suffices {x : Ω | τ x = i} = ∅ by simp [this]; norm_cast @@ -70,11 +73,15 @@ theorem condexp_stopping_time_ae_eq_restrict_eq_const_of_le_const (h : Martingal rintro rfl exact hin (hτ_le x) +@[deprecated (since := "2025-01-21")] +alias condexp_stopping_time_ae_eq_restrict_eq_const_of_le_const := + condExp_stopping_time_ae_eq_restrict_eq_const_of_le_const + theorem stoppedValue_ae_eq_restrict_eq (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hτ_le : ∀ x, τ x ≤ n) [SigmaFinite (μ.trim (hτ.measurableSpace_le_of_le hτ_le))] (i : ι) : stoppedValue f τ =ᵐ[μ.restrict {x | τ x = i}] μ[f n|hτ.measurableSpace] := by refine Filter.EventuallyEq.trans ?_ - (condexp_stopping_time_ae_eq_restrict_eq_const_of_le_const h hτ hτ_le i).symm + (condExp_stopping_time_ae_eq_restrict_eq_const_of_le_const h hτ hτ_le i).symm rw [Filter.EventuallyEq, ae_restrict_iff' (ℱ.le _ _ (hτ.measurableSet_eq i))] refine Filter.Eventually.of_forall fun x hx => ?_ rw [Set.mem_setOf_eq] at hx @@ -82,7 +89,7 @@ theorem stoppedValue_ae_eq_restrict_eq (h : Martingale f ℱ μ) (hτ : IsStoppi /-- The value of a martingale `f` at a stopping time `τ` bounded by `n` is the conditional expectation of `f n` with respect to the σ-algebra generated by `τ`. -/ -theorem stoppedValue_ae_eq_condexp_of_le_const_of_countable_range (h : Martingale f ℱ μ) +theorem stoppedValue_ae_eq_condExp_of_le_const_of_countable_range (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hτ_le : ∀ x, τ x ≤ n) (h_countable_range : (Set.range τ).Countable) [SigmaFinite (μ.trim (hτ.measurableSpace_le_of_le hτ_le))] : stoppedValue f τ =ᵐ[μ] μ[f n|hτ.measurableSpace] := by @@ -94,18 +101,25 @@ theorem stoppedValue_ae_eq_condexp_of_le_const_of_countable_range (h : Martingal rw [this, ae_eq_restrict_biUnion_iff _ h_countable_range] exact fun i _ => stoppedValue_ae_eq_restrict_eq h _ hτ_le i +@[deprecated (since := "2025-01-21")] +alias stoppedValue_ae_eq_condexp_of_le_const_of_countable_range := + stoppedValue_ae_eq_condExp_of_le_const_of_countable_range + /-- The value of a martingale `f` at a stopping time `τ` bounded by `n` is the conditional expectation of `f n` with respect to the σ-algebra generated by `τ`. -/ -theorem stoppedValue_ae_eq_condexp_of_le_const [Countable ι] (h : Martingale f ℱ μ) +theorem stoppedValue_ae_eq_condExp_of_le_const [Countable ι] (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hτ_le : ∀ x, τ x ≤ n) [SigmaFinite (μ.trim (hτ.measurableSpace_le_of_le hτ_le))] : stoppedValue f τ =ᵐ[μ] μ[f n|hτ.measurableSpace] := - h.stoppedValue_ae_eq_condexp_of_le_const_of_countable_range hτ hτ_le (Set.to_countable _) + h.stoppedValue_ae_eq_condExp_of_le_const_of_countable_range hτ hτ_le (Set.to_countable _) + +@[deprecated (since := "2025-01-21")] +alias stoppedValue_ae_eq_condexp_of_le_const := stoppedValue_ae_eq_condExp_of_le_const /-- If `τ` and `σ` are two stopping times with `σ ≤ τ` and `τ` is bounded, then the value of a martingale `f` at `σ` is the conditional expectation of its value at `τ` with respect to the σ-algebra generated by `σ`. -/ -theorem stoppedValue_ae_eq_condexp_of_le_of_countable_range (h : Martingale f ℱ μ) +theorem stoppedValue_ae_eq_condExp_of_le_of_countable_range (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hσ : IsStoppingTime ℱ σ) (hσ_le_τ : σ ≤ τ) (hτ_le : ∀ x, τ x ≤ n) (hτ_countable_range : (Set.range τ).Countable) (hσ_countable_range : (Set.range σ).Countable) [SigmaFinite (μ.trim (hσ.measurableSpace_le_of_le fun x => (hσ_le_τ x).trans (hτ_le x)))] : @@ -113,24 +127,31 @@ theorem stoppedValue_ae_eq_condexp_of_le_of_countable_range (h : Martingale f have : SigmaFinite (μ.trim (hτ.measurableSpace_le_of_le hτ_le)) := sigmaFiniteTrim_mono _ (IsStoppingTime.measurableSpace_mono hσ hτ hσ_le_τ) have : μ[stoppedValue f τ|hσ.measurableSpace] =ᵐ[μ] - μ[μ[f n|hτ.measurableSpace]|hσ.measurableSpace] := condexp_congr_ae - (h.stoppedValue_ae_eq_condexp_of_le_const_of_countable_range hτ hτ_le hτ_countable_range) + μ[μ[f n|hτ.measurableSpace]|hσ.measurableSpace] := condExp_congr_ae + (h.stoppedValue_ae_eq_condExp_of_le_const_of_countable_range hτ hτ_le hτ_countable_range) refine (Filter.EventuallyEq.trans ?_ - (condexp_condexp_of_le ?_ (hτ.measurableSpace_le_of_le hτ_le)).symm).trans this.symm - · exact h.stoppedValue_ae_eq_condexp_of_le_const_of_countable_range hσ + (condExp_condExp_of_le ?_ (hτ.measurableSpace_le_of_le hτ_le)).symm).trans this.symm + · exact h.stoppedValue_ae_eq_condExp_of_le_const_of_countable_range hσ (fun x => (hσ_le_τ x).trans (hτ_le x)) hσ_countable_range · exact hσ.measurableSpace_mono hτ hσ_le_τ +@[deprecated (since := "2025-01-21")] +alias stoppedValue_ae_eq_condexp_of_le_of_countable_range := + stoppedValue_ae_eq_condExp_of_le_of_countable_range + /-- If `τ` and `σ` are two stopping times with `σ ≤ τ` and `τ` is bounded, then the value of a martingale `f` at `σ` is the conditional expectation of its value at `τ` with respect to the σ-algebra generated by `σ`. -/ -theorem stoppedValue_ae_eq_condexp_of_le [Countable ι] (h : Martingale f ℱ μ) +theorem stoppedValue_ae_eq_condExp_of_le [Countable ι] (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hσ : IsStoppingTime ℱ σ) (hσ_le_τ : σ ≤ τ) (hτ_le : ∀ x, τ x ≤ n) [SigmaFinite (μ.trim hσ.measurableSpace_le)] : stoppedValue f σ =ᵐ[μ] μ[stoppedValue f τ|hσ.measurableSpace] := - h.stoppedValue_ae_eq_condexp_of_le_of_countable_range hτ hσ hσ_le_τ hτ_le (Set.to_countable _) + h.stoppedValue_ae_eq_condExp_of_le_of_countable_range hτ hσ hσ_le_τ hτ_le (Set.to_countable _) (Set.to_countable _) +@[deprecated (since := "2025-01-21")] +alias stoppedValue_ae_eq_condexp_of_le := stoppedValue_ae_eq_condExp_of_le + end FirstCountableTopology section SubsetOfNat @@ -145,13 +166,13 @@ variable {ι : Type*} [LinearOrder ι] [LocallyFiniteOrder ι] [OrderBot ι] [To [DiscreteTopology ι] [MeasurableSpace ι] [BorelSpace ι] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] {ℱ : Filtration ι m} {τ σ : Ω → ι} {f : ι → Ω → E} {i : ι} -theorem condexp_stoppedValue_stopping_time_ae_eq_restrict_le (h : Martingale f ℱ μ) +theorem condExp_stoppedValue_stopping_time_ae_eq_restrict_le (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hσ : IsStoppingTime ℱ σ) [SigmaFinite (μ.trim hσ.measurableSpace_le)] (hτ_le : ∀ x, τ x ≤ i) : μ[stoppedValue f τ|hσ.measurableSpace] =ᵐ[μ.restrict {x : Ω | τ x ≤ σ x}] stoppedValue f τ := by rw [ae_eq_restrict_iff_indicator_ae_eq (hτ.measurableSpace_le _ (hτ.measurableSet_le_stopping_time hσ))] - refine (condexp_indicator (integrable_stoppedValue ι hτ h.integrable hτ_le) + refine (condExp_indicator (integrable_stoppedValue ι hτ h.integrable hτ_le) (hτ.measurableSet_stopping_time_le hσ)).symm.trans ?_ have h_int : Integrable ({ω : Ω | τ ω ≤ σ ω}.indicator (stoppedValue (fun n : ι => f n) τ)) μ := by @@ -171,20 +192,24 @@ theorem condexp_stoppedValue_stopping_time_ae_eq_restrict_le (h : Martingale f exact measurable_stoppedValue h.adapted.progMeasurable_of_discrete hτ · intro x hx simp only [hx, Set.indicator_of_not_mem, not_false_iff] - exact condexp_of_aestronglyMeasurable' hσ.measurableSpace_le h_meas h_int + exact condExp_of_aestronglyMeasurable' hσ.measurableSpace_le h_meas h_int + +@[deprecated (since := "2025-01-21")] +alias condexp_stoppedValue_stopping_time_ae_eq_restrict_le := + condExp_stoppedValue_stopping_time_ae_eq_restrict_le /-- **Optional Sampling theorem**. If `τ` is a bounded stopping time and `σ` is another stopping time, then the value of a martingale `f` at the stopping time `min τ σ` is almost everywhere equal to the conditional expectation of `f` stopped at `τ` with respect to the σ-algebra generated by `σ`. -/ -theorem stoppedValue_min_ae_eq_condexp [SigmaFiniteFiltration μ ℱ] (h : Martingale f ℱ μ) +theorem stoppedValue_min_ae_eq_condExp [SigmaFiniteFiltration μ ℱ] (h : Martingale f ℱ μ) (hτ : IsStoppingTime ℱ τ) (hσ : IsStoppingTime ℱ σ) {n : ι} (hτ_le : ∀ x, τ x ≤ n) [h_sf_min : SigmaFinite (μ.trim (hτ.min hσ).measurableSpace_le)] : (stoppedValue f fun x => min (σ x) (τ x)) =ᵐ[μ] μ[stoppedValue f τ|hσ.measurableSpace] := by refine - (h.stoppedValue_ae_eq_condexp_of_le hτ (hσ.min hτ) (fun x => min_le_right _ _) hτ_le).trans ?_ + (h.stoppedValue_ae_eq_condExp_of_le hτ (hσ.min hτ) (fun x => min_le_right _ _) hτ_le).trans ?_ refine ae_of_ae_restrict_of_ae_restrict_compl {x | σ x ≤ τ x} ?_ ?_ - · exact condexp_min_stopping_time_ae_eq_restrict_le hσ hτ + · exact condExp_min_stopping_time_ae_eq_restrict_le hσ hτ · suffices μ[stoppedValue f τ|(hσ.min hτ).measurableSpace] =ᵐ[μ.restrict {x | τ x ≤ σ x}] μ[stoppedValue f τ|hσ.measurableSpace] by rw [ae_restrict_iff' (hσ.measurableSpace_le _ (hσ.measurableSet_le_stopping_time hτ).compl)] @@ -193,16 +218,19 @@ theorem stoppedValue_min_ae_eq_condexp [SigmaFiniteFiltration μ ℱ] (h : Marti filter_upwards [this] with x hx hx_mem simp only [Set.mem_compl_iff, Set.mem_setOf_eq, not_le] at hx_mem exact hx hx_mem.le - apply Filter.EventuallyEq.trans _ ((condexp_min_stopping_time_ae_eq_restrict_le hτ hσ).trans _) + apply Filter.EventuallyEq.trans _ ((condExp_min_stopping_time_ae_eq_restrict_le hτ hσ).trans _) · exact stoppedValue f τ · rw [IsStoppingTime.measurableSpace_min hσ, IsStoppingTime.measurableSpace_min hτ, inf_comm] · have h1 : μ[stoppedValue f τ|hτ.measurableSpace] = stoppedValue f τ := by - apply condexp_of_stronglyMeasurable hτ.measurableSpace_le + apply condExp_of_stronglyMeasurable hτ.measurableSpace_le · exact Measurable.stronglyMeasurable <| measurable_stoppedValue h.adapted.progMeasurable_of_discrete hτ · exact integrable_stoppedValue ι hτ h.integrable hτ_le rw [h1] - exact (condexp_stoppedValue_stopping_time_ae_eq_restrict_le h hτ hσ hτ_le).symm + exact (condExp_stoppedValue_stopping_time_ae_eq_restrict_le h hτ hσ hτ_le).symm + +@[deprecated (since := "2025-01-21")] +alias stoppedValue_min_ae_eq_condexp := stoppedValue_min_ae_eq_condExp end SubsetOfNat diff --git a/Mathlib/Probability/Notation.lean b/Mathlib/Probability/Notation.lean index aaf254c1f9096..1d29018bd6cb6 100644 --- a/Mathlib/Probability/Notation.lean +++ b/Mathlib/Probability/Notation.lean @@ -36,7 +36,7 @@ open scoped MeasureTheory -- We define notations `𝔼[f|m]` for the conditional expectation of `f` with respect to `m`. scoped[ProbabilityTheory] notation "𝔼[" X "|" m "]" => - MeasureTheory.condexp m MeasureTheory.MeasureSpace.volume X + MeasureTheory.condExp m MeasureTheory.MeasureSpace.volume X -- `scoped[ProbabilityTheory]` isn't legal for `macro`s. namespace ProbabilityTheory @@ -51,7 +51,7 @@ end ProbabilityTheory scoped[ProbabilityTheory] notation "𝔼[" X "]" => ∫ a, (X : _ → _) a scoped[ProbabilityTheory] notation P "⟦" s "|" m "⟧" => - MeasureTheory.condexp m P (Set.indicator s fun ω => (1 : ℝ)) + MeasureTheory.condExp m P (Set.indicator s fun ω => (1 : ℝ)) scoped[ProbabilityTheory] notation:50 X " =ₐₛ " Y:50 => X =ᵐ[MeasureTheory.MeasureSpace.volume] Y diff --git a/Mathlib/Probability/Process/Filtration.lean b/Mathlib/Probability/Process/Filtration.lean index 3396fa6e9ab32..82b1ace233b96 100644 --- a/Mathlib/Probability/Process/Filtration.lean +++ b/Mathlib/Probability/Process/Filtration.lean @@ -212,10 +212,14 @@ instance (priority := 100) IsFiniteMeasure.sigmaFiniteFiltration [Preorder ι] ( /-- Given an integrable function `g`, the conditional expectations of `g` with respect to a filtration is uniformly integrable. -/ -theorem Integrable.uniformIntegrable_condexp_filtration [Preorder ι] {μ : Measure Ω} +theorem Integrable.uniformIntegrable_condExp_filtration [Preorder ι] {μ : Measure Ω} [IsFiniteMeasure μ] {f : Filtration ι m} {g : Ω → ℝ} (hg : Integrable g μ) : UniformIntegrable (fun i => μ[g|f i]) 1 μ := - hg.uniformIntegrable_condexp f.le + hg.uniformIntegrable_condExp f.le + +@[deprecated (since := "2025-01-21")] +alias Integrable.uniformIntegrable_condexp_filtration := + Integrable.uniformIntegrable_condExp_filtration section OfSet diff --git a/Mathlib/Probability/Process/Stopping.lean b/Mathlib/Probability/Process/Stopping.lean index 80f76791df248..f4be7f5441b4e 100644 --- a/Mathlib/Probability/Process/Stopping.lean +++ b/Mathlib/Probability/Process/Stopping.lean @@ -1048,24 +1048,32 @@ section Condexp variable [LinearOrder ι] {μ : Measure Ω} {ℱ : Filtration ι m} {τ σ : Ω → ι} {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] {f : Ω → E} -theorem condexp_stopping_time_ae_eq_restrict_eq_of_countable_range [SigmaFiniteFiltration μ ℱ] +theorem condExp_stopping_time_ae_eq_restrict_eq_of_countable_range [SigmaFiniteFiltration μ ℱ] (hτ : IsStoppingTime ℱ τ) (h_countable : (Set.range τ).Countable) [SigmaFinite (μ.trim (hτ.measurableSpace_le_of_countable_range h_countable))] (i : ι) : μ[f|hτ.measurableSpace] =ᵐ[μ.restrict {x | τ x = i}] μ[f|ℱ i] := by - refine condexp_ae_eq_restrict_of_measurableSpace_eq_on + refine condExp_ae_eq_restrict_of_measurableSpace_eq_on (hτ.measurableSpace_le_of_countable_range h_countable) (ℱ.le i) (hτ.measurableSet_eq_of_countable_range' h_countable i) fun t => ?_ rw [Set.inter_comm _ t, IsStoppingTime.measurableSet_inter_eq_iff] -theorem condexp_stopping_time_ae_eq_restrict_eq_of_countable [Countable ι] +@[deprecated (since := "2025-01-21")] +alias condexp_stopping_time_ae_eq_restrict_eq_of_countable_range := + condExp_stopping_time_ae_eq_restrict_eq_of_countable_range + +theorem condExp_stopping_time_ae_eq_restrict_eq_of_countable [Countable ι] [SigmaFiniteFiltration μ ℱ] (hτ : IsStoppingTime ℱ τ) [SigmaFinite (μ.trim hτ.measurableSpace_le_of_countable)] (i : ι) : μ[f|hτ.measurableSpace] =ᵐ[μ.restrict {x | τ x = i}] μ[f|ℱ i] := - condexp_stopping_time_ae_eq_restrict_eq_of_countable_range hτ (Set.to_countable _) i + condExp_stopping_time_ae_eq_restrict_eq_of_countable_range hτ (Set.to_countable _) i + +@[deprecated (since := "2025-01-21")] +alias condexp_stopping_time_ae_eq_restrict_eq_of_countable := + condExp_stopping_time_ae_eq_restrict_eq_of_countable variable [(Filter.atTop : Filter ι).IsCountablyGenerated] -theorem condexp_min_stopping_time_ae_eq_restrict_le_const (hτ : IsStoppingTime ℱ τ) (i : ι) +theorem condExp_min_stopping_time_ae_eq_restrict_le_const (hτ : IsStoppingTime ℱ τ) (i : ι) [SigmaFinite (μ.trim (hτ.min_const i).measurableSpace_le)] : μ[f|(hτ.min_const i).measurableSpace] =ᵐ[μ.restrict {x | τ x ≤ i}] μ[f|hτ.measurableSpace] := by have : SigmaFinite (μ.trim hτ.measurableSpace_le) := @@ -1073,21 +1081,28 @@ theorem condexp_min_stopping_time_ae_eq_restrict_le_const (hτ : IsStoppingTime rw [IsStoppingTime.measurableSpace_min_const] exact inf_le_left sigmaFiniteTrim_mono _ h_le - refine (condexp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le + refine (condExp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le (hτ.min_const i).measurableSpace_le (hτ.measurableSet_le' i) fun t => ?_).symm rw [Set.inter_comm _ t, hτ.measurableSet_inter_le_const_iff] +@[deprecated (since := "2025-01-21")] +alias condexp_min_stopping_time_ae_eq_restrict_le_const := + condExp_min_stopping_time_ae_eq_restrict_le_const + variable [TopologicalSpace ι] [OrderTopology ι] -theorem condexp_stopping_time_ae_eq_restrict_eq [FirstCountableTopology ι] +theorem condExp_stopping_time_ae_eq_restrict_eq [FirstCountableTopology ι] [SigmaFiniteFiltration μ ℱ] (hτ : IsStoppingTime ℱ τ) [SigmaFinite (μ.trim hτ.measurableSpace_le)] (i : ι) : μ[f|hτ.measurableSpace] =ᵐ[μ.restrict {x | τ x = i}] μ[f|ℱ i] := by - refine condexp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le (ℱ.le i) + refine condExp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le (ℱ.le i) (hτ.measurableSet_eq' i) fun t => ?_ rw [Set.inter_comm _ t, IsStoppingTime.measurableSet_inter_eq_iff] -theorem condexp_min_stopping_time_ae_eq_restrict_le [MeasurableSpace ι] [SecondCountableTopology ι] +@[deprecated (since := "2025-01-21")] +alias condexp_stopping_time_ae_eq_restrict_eq := condExp_stopping_time_ae_eq_restrict_eq + +theorem condExp_min_stopping_time_ae_eq_restrict_le [MeasurableSpace ι] [SecondCountableTopology ι] [BorelSpace ι] (hτ : IsStoppingTime ℱ τ) (hσ : IsStoppingTime ℱ σ) [SigmaFinite (μ.trim (hτ.min hσ).measurableSpace_le)] : μ[f|(hτ.min hσ).measurableSpace] =ᵐ[μ.restrict {x | τ x ≤ σ x}] μ[f|hτ.measurableSpace] := by @@ -1097,10 +1112,13 @@ theorem condexp_min_stopping_time_ae_eq_restrict_le [MeasurableSpace ι] [Second · exact inf_le_left · simp_all only sigmaFiniteTrim_mono _ h_le - refine (condexp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le + refine (condExp_ae_eq_restrict_of_measurableSpace_eq_on hτ.measurableSpace_le (hτ.min hσ).measurableSpace_le (hτ.measurableSet_le_stopping_time hσ) fun t => ?_).symm rw [Set.inter_comm _ t, IsStoppingTime.measurableSet_inter_le_iff]; simp_all only +@[deprecated (since := "2025-01-21")] +alias condexp_min_stopping_time_ae_eq_restrict_le := condExp_min_stopping_time_ae_eq_restrict_le + end Condexp end MeasureTheory diff --git a/docs/overview.yaml b/docs/overview.yaml index 2d11b73912178..d9df79a5cfead 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -377,7 +377,7 @@ Probability Theory: independent events: 'ProbabilityTheory.iIndepSet' independent sigma-algebras: 'ProbabilityTheory.iIndep' conditional probability: 'ProbabilityTheory.cond' - conditional expectation: 'MeasureTheory.condexp' + conditional expectation: 'MeasureTheory.condExp' Random variables and their laws: discrete law: 'PMF' probability density function: 'MeasureTheory.HasPDF' diff --git a/scripts/nolints_prime_decls.txt b/scripts/nolints_prime_decls.txt index 450e3291e8c35..31d8b5d0d0839 100644 --- a/scripts/nolints_prime_decls.txt +++ b/scripts/nolints_prime_decls.txt @@ -2695,14 +2695,14 @@ 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.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' @@ -3935,8 +3935,8 @@ ProbabilityTheory.cgf_zero' ProbabilityTheory.cond_apply' ProbabilityTheory.cond_cond_eq_cond_inter' ProbabilityTheory.uniformOn_inter' -ProbabilityTheory.condexp_ae_eq_integral_condexpKernel' -ProbabilityTheory.condexpKernel_ae_eq_condexp' +ProbabilityTheory.condExp_ae_eq_integral_condExpKernel' +ProbabilityTheory.condExpKernel_ae_eq_condExp' ProbabilityTheory.CondIndepSets.condIndep' ProbabilityTheory.cond_mul_eq_inter' ProbabilityTheory.evariance_def' From 72bf52f21e463ed123c31426cecc3ba6a5878092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 22 Jan 2025 14:26:41 +0000 Subject: [PATCH 423/681] feat(CategoryTheory): pullbacks/pushouts/limits/colimits of a class of morphisms (#20157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given `P : MorphismProperty C` and `J` a category, we introduce morphisms properties `P.pullbacks`, `P.pushouts`, `P.limitsOfShape J` and `P.colimitsOfShape J` which are obtained from `P` by taking these type of (co)limits. We obtain results like `P.isStableUnderBaseChange_iff_pullbacks_le : P.IsStableUnderBaseChange ↔ P.pullbacks ≤ P`. Co-authored-by: mckoen Co-authored-by: Jack McKoen Co-authored-by: Jack McKoen <104791831+mckoen@users.noreply.github.com> Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- .../Localization/FiniteProducts.lean | 2 +- .../MorphismProperty/Basic.lean | 20 ++ .../MorphismProperty/Limits.lean | 270 +++++++++++++++--- 3 files changed, 255 insertions(+), 37 deletions(-) diff --git a/Mathlib/CategoryTheory/Localization/FiniteProducts.lean b/Mathlib/CategoryTheory/Localization/FiniteProducts.lean index d3be845da56a6..a5fc9f3df1d9d 100644 --- a/Mathlib/CategoryTheory/Localization/FiniteProducts.lean +++ b/Mathlib/CategoryTheory/Localization/FiniteProducts.lean @@ -38,7 +38,7 @@ include hW lemma inverts : (W.functorCategory (Discrete J)).IsInvertedBy (lim ⋙ L) := - fun _ _ f hf => Localization.inverts L W _ (hW.lim_map f hf) + fun _ _ f hf => Localization.inverts L W _ (hW.limMap f hf) variable [W.ContainsIdentities] [Finite J] diff --git a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean index 0d34626b7468f..6d548e45cfabe 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean @@ -61,6 +61,26 @@ lemma ext (W W' : MorphismProperty C) (h : ∀ ⦃X Y : C⦄ (f : X ⟶ Y), W f lemma top_apply {X Y : C} (f : X ⟶ Y) : (⊤ : MorphismProperty C) f := by simp only [top_eq] +@[simp] +lemma sSup_iff (S : Set (MorphismProperty C)) {X Y : C} (f : X ⟶ Y) : + sSup S f ↔ ∃ (W : S), W.1 f := by + dsimp [sSup, iSup] + constructor + · rintro ⟨_, ⟨⟨_, ⟨⟨_, ⟨_, h⟩, rfl⟩, rfl⟩⟩, rfl⟩, hf⟩ + exact ⟨⟨_, h⟩, hf⟩ + · rintro ⟨⟨W, hW⟩, hf⟩ + exact ⟨_, ⟨⟨_, ⟨_, ⟨⟨W, hW⟩, rfl⟩⟩, rfl⟩, rfl⟩, hf⟩ + +@[simp] +lemma iSup_iff {ι : Type*} (W : ι → MorphismProperty C) {X Y : C} (f : X ⟶ Y) : + iSup W f ↔ ∃ i, W i f := by + apply (sSup_iff (Set.range W) f).trans + constructor + · rintro ⟨⟨_, i, rfl⟩, hf⟩ + exact ⟨i, hf⟩ + · rintro ⟨i, hf⟩ + exact ⟨⟨_, i, rfl⟩, hf⟩ + /-- The morphism property in `Cᵒᵖ` associated to a morphism property in `C` -/ @[simp] def op (P : MorphismProperty C) : MorphismProperty Cᵒᵖ := fun _ _ f => P f.unop diff --git a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean index d9280218e658f..48d927c184b04 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean @@ -23,35 +23,103 @@ We also introduce properties `IsStableUnderProductsOfShape`, `IsStableUnderLimit -/ -universe v u +universe w v u namespace CategoryTheory -open Limits +open Category Limits namespace MorphismProperty variable {C : Type u} [Category.{v} C] +section + +variable (P : MorphismProperty C) + +/-- Given a class of morphisms `P`, this is the class of pullbacks +of morphisms in `P`. -/ +def pullbacks : MorphismProperty C := fun A B q ↦ + ∃ (X Y : C) (p : X ⟶ Y) (f : A ⟶ X) (g : B ⟶ Y) (_ : P p), + IsPullback f q p g + +lemma pullbacks_mk {A B X Y : C} {f : A ⟶ X} {q : A ⟶ B} {p : X ⟶ Y} {g : B ⟶ Y} + (sq : IsPullback f q p g) (hp : P p) : + P.pullbacks q := + ⟨_, _, _, _, _, hp, sq⟩ + +lemma le_pullbacks : P ≤ P.pullbacks := by + intro A B q hq + exact P.pullbacks_mk IsPullback.of_id_fst hq + +/-- Given a class of morphisms `P`, this is the class of pushouts +of morphisms in `P`. -/ +def pushouts : MorphismProperty C := fun X Y q ↦ + ∃ (A B : C) (p : A ⟶ B) (f : A ⟶ X) (g : B ⟶ Y) (_ : P p), + IsPushout f p q g + +lemma pushouts_mk {A B X Y : C} {f : A ⟶ X} {q : A ⟶ B} {p : X ⟶ Y} {g : B ⟶ Y} + (sq : IsPushout f q p g) (hq : P q) : + P.pushouts p := + ⟨_, _, _, _, _, hq, sq⟩ + +lemma le_pushouts : P ≤ P.pushouts := by + intro X Y p hp + exact P.pushouts_mk IsPushout.of_id_fst hp + +instance : P.pushouts.RespectsIso := + RespectsIso.of_respects_arrow_iso _ (by + rintro q q' e ⟨A, B, p, f, g, hp, h⟩ + exact ⟨A, B, p, f ≫ e.hom.left, g ≫ e.hom.right, hp, + IsPushout.paste_horiz h (IsPushout.of_horiz_isIso ⟨e.hom.w⟩)⟩) + +instance : P.pullbacks.RespectsIso := + RespectsIso.of_respects_arrow_iso _ (by + rintro q q' e ⟨X, Y, p, f, g, hp, h⟩ + exact ⟨X, Y, p, e.inv.left ≫ f, e.inv.right ≫ g, hp, + IsPullback.paste_horiz (IsPullback.of_horiz_isIso ⟨e.inv.w⟩) h⟩) + /-- A morphism property is `IsStableUnderBaseChange` if the base change of such a morphism still falls in the class. -/ -class IsStableUnderBaseChange (P : MorphismProperty C) : Prop where +class IsStableUnderBaseChange : Prop where of_isPullback {X Y Y' S : C} {f : X ⟶ S} {g : Y ⟶ S} {f' : Y' ⟶ Y} {g' : Y' ⟶ X} (sq : IsPullback f' g' g f) (hg : P g) : P g' +instance : P.pullbacks.IsStableUnderBaseChange where + of_isPullback := by + rintro _ _ _ _ _ _ _ _ h ⟨_, _, _, _, _, hp, hq⟩ + exact P.pullbacks_mk (h.paste_horiz hq) hp + /-- A morphism property is `IsStableUnderCobaseChange` if the cobase change of such a morphism still falls in the class. -/ -class IsStableUnderCobaseChange (P : MorphismProperty C) : Prop where +class IsStableUnderCobaseChange : Prop where of_isPushout {A A' B B' : C} {f : A ⟶ A'} {g : A ⟶ B} {f' : B ⟶ B'} {g' : A' ⟶ B'} (sq : IsPushout g f f' g') (hf : P f) : P f' -lemma of_isPullback {P : MorphismProperty C} [P.IsStableUnderBaseChange] +instance : P.pushouts.IsStableUnderCobaseChange where + of_isPushout := by + rintro _ _ _ _ _ _ _ _ h ⟨_, _, _, _, _, hp, hq⟩ + exact P.pushouts_mk (hq.paste_horiz h) hp + +variable {P} in +lemma of_isPullback [P.IsStableUnderBaseChange] {X Y Y' S : C} {f : X ⟶ S} {g : Y ⟶ S} {f' : Y' ⟶ Y} {g' : Y' ⟶ X} (sq : IsPullback f' g' g f) (hg : P g) : P g' := IsStableUnderBaseChange.of_isPullback sq hg +lemma isStableUnderBaseChange_iff_pullbacks_le : + P.IsStableUnderBaseChange ↔ P.pullbacks ≤ P := by + constructor + · intro h _ _ _ ⟨_, _, _, _, _, h₁, h₂⟩ + exact of_isPullback h₂ h₁ + · intro h + constructor + intro _ _ _ _ _ _ _ _ h₁ h₂ + exact h _ ⟨_, _, _, _, _, h₂, h₁⟩ + +variable {P} in /-- Alternative constructor for `IsStableUnderBaseChange`. -/ -theorem IsStableUnderBaseChange.mk' {P : MorphismProperty C} [RespectsIso P] +theorem IsStableUnderBaseChange.mk' [RespectsIso P] (hP₂ : ∀ (X Y S : C) (f : X ⟶ S) (g : Y ⟶ S) [HasPullback f g] (_ : P g), P (pullback.fst f g)) : IsStableUnderBaseChange P where @@ -61,6 +129,8 @@ theorem IsStableUnderBaseChange.mk' {P : MorphismProperty C} [RespectsIso P] rw [← P.cancel_left_of_respectsIso e.inv, sq.flip.isoPullback_inv_fst] exact hP₂ _ _ _ f g hg +variable (C) + instance IsStableUnderBaseChange.isomorphisms : (isomorphisms C).IsStableUnderBaseChange where of_isPullback {_ _ _ _ f g _ _} h hg := @@ -68,7 +138,6 @@ instance IsStableUnderBaseChange.isomorphisms : have := hasPullback_of_left_iso g f h.isoPullback_hom_snd ▸ inferInstanceAs (IsIso _) -variable (C) in instance IsStableUnderBaseChange.monomorphisms : (monomorphisms C).IsStableUnderBaseChange where of_isPullback {X Y Y' S f g f' g'} h hg := by @@ -81,34 +150,36 @@ instance IsStableUnderBaseChange.monomorphisms : simp only [Category.assoc, h.w, reassoc_of% h₁₂] · exact h₁₂ -instance (priority := 900) IsStableUnderBaseChange.respectsIso {P : MorphismProperty C} +variable {C P} + +instance (priority := 900) IsStableUnderBaseChange.respectsIso [IsStableUnderBaseChange P] : RespectsIso P := by apply RespectsIso.of_respects_arrow_iso intro f g e exact of_isPullback (IsPullback.of_horiz_isIso (CommSq.mk e.inv.w)) -theorem pullback_fst {P : MorphismProperty C} [IsStableUnderBaseChange P] +theorem pullback_fst [IsStableUnderBaseChange P] {X Y S : C} (f : X ⟶ S) (g : Y ⟶ S) [HasPullback f g] (H : P g) : P (pullback.fst f g) := of_isPullback (IsPullback.of_hasPullback f g).flip H @[deprecated (since := "2024-11-06")] alias IsStableUnderBaseChange.fst := pullback_fst -theorem pullback_snd {P : MorphismProperty C} [IsStableUnderBaseChange P] +theorem pullback_snd [IsStableUnderBaseChange P] {X Y S : C} (f : X ⟶ S) (g : Y ⟶ S) [HasPullback f g] (H : P f) : P (pullback.snd f g) := of_isPullback (IsPullback.of_hasPullback f g) H @[deprecated (since := "2024-11-06")] alias IsStableUnderBaseChange.snd := pullback_snd -theorem baseChange_obj [HasPullbacks C] {P : MorphismProperty C} +theorem baseChange_obj [HasPullbacks C] [IsStableUnderBaseChange P] {S S' : C} (f : S' ⟶ S) (X : Over S) (H : P X.hom) : P ((Over.pullback f).obj X).hom := pullback_snd X.hom f H @[deprecated (since := "2024-11-06")] alias IsStableUnderBaseChange.baseChange_obj := baseChange_obj -theorem baseChange_map [HasPullbacks C] {P : MorphismProperty C} +theorem baseChange_map [HasPullbacks C] [IsStableUnderBaseChange P] {S S' : C} (f : S' ⟶ S) {X Y : Over S} (g : X ⟶ Y) (H : P g.left) : P ((Over.pullback f).map g).left := by let e := @@ -121,7 +192,7 @@ theorem baseChange_map [HasPullbacks C] {P : MorphismProperty C} @[deprecated (since := "2024-11-06")] alias IsStableUnderBaseChange.baseChange_map := baseChange_map -theorem pullback_map [HasPullbacks C] {P : MorphismProperty C} +theorem pullback_map [HasPullbacks C] [IsStableUnderBaseChange P] [P.IsStableUnderComposition] {S X X' Y Y' : C} {f : X ⟶ S} {g : Y ⟶ S} {f' : X' ⟶ S} {g' : Y' ⟶ S} {i₁ : X ⟶ X'} {i₂ : Y ⟶ Y'} (h₁ : P i₁) (h₂ : P i₂) (e₁ : f = i₁ ≫ f') (e₂ : g = i₂ ≫ g') : @@ -142,13 +213,23 @@ theorem pullback_map [HasPullbacks C] {P : MorphismProperty C} @[deprecated (since := "2024-11-06")] alias IsStableUnderBaseChange.pullback_map := pullback_map -lemma of_isPushout {P : MorphismProperty C} [P.IsStableUnderCobaseChange] +lemma of_isPushout [P.IsStableUnderCobaseChange] {A A' B B' : C} {f : A ⟶ A'} {g : A ⟶ B} {f' : B ⟶ B'} {g' : A' ⟶ B'} (sq : IsPushout g f f' g') (hf : P f) : P f' := IsStableUnderCobaseChange.of_isPushout sq hf +lemma isStableUnderCobaseChange_iff_pushouts_le : + P.IsStableUnderCobaseChange ↔ P.pushouts ≤ P := by + constructor + · intro h _ _ _ ⟨_, _, _, _, _, h₁, h₂⟩ + exact of_isPushout h₂ h₁ + · intro h + constructor + intro _ _ _ _ _ _ _ _ h₁ h₂ + exact h _ ⟨_, _, _, _, _, h₂, h₁⟩ + /-- An alternative constructor for `IsStableUnderCobaseChange`. -/ -theorem IsStableUnderCobaseChange.mk' {P : MorphismProperty C} [RespectsIso P] +theorem IsStableUnderCobaseChange.mk' [RespectsIso P] (hP₂ : ∀ (A B A' : C) (f : A ⟶ A') (g : A ⟶ B) [HasPushout f g] (_ : P f), P (pushout.inr f g)) : IsStableUnderCobaseChange P where @@ -177,25 +258,25 @@ instance IsStableUnderCobaseChange.epimorphisms : dsimp simp only [← reassoc_of% h.w, h₁₂] -instance IsStableUnderCobaseChange.respectsIso {P : MorphismProperty C} +instance IsStableUnderCobaseChange.respectsIso [IsStableUnderCobaseChange P] : RespectsIso P := RespectsIso.of_respects_arrow_iso _ fun _ _ e ↦ of_isPushout (IsPushout.of_horiz_isIso (CommSq.mk e.hom.w)) -theorem pushout_inl {P : MorphismProperty C} [IsStableUnderCobaseChange P] +theorem pushout_inl [IsStableUnderCobaseChange P] {A B A' : C} (f : A ⟶ A') (g : A ⟶ B) [HasPushout f g] (H : P g) : P (pushout.inl f g) := of_isPushout (IsPushout.of_hasPushout f g) H @[deprecated (since := "2024-11-06")] alias IsStableUnderBaseChange.inl := pushout_inl -theorem pushout_inr {P : MorphismProperty C} [IsStableUnderCobaseChange P] +theorem pushout_inr [IsStableUnderCobaseChange P] {A B A' : C} (f : A ⟶ A') (g : A ⟶ B) [HasPushout f g] (H : P f) : P (pushout.inr f g) := of_isPushout (IsPushout.of_hasPushout f g).flip H @[deprecated (since := "2024-11-06")] alias IsStableUnderBaseChange.inr := pushout_inr -instance IsStableUnderCobaseChange.op {P : MorphismProperty C} [IsStableUnderCobaseChange P] : +instance IsStableUnderCobaseChange.op [IsStableUnderCobaseChange P] : IsStableUnderBaseChange P.op where of_isPullback sq hg := P.of_isPushout sq.unop hg @@ -203,7 +284,7 @@ instance IsStableUnderCobaseChange.unop {P : MorphismProperty Cᵒᵖ} [IsStable IsStableUnderBaseChange P.unop where of_isPullback sq hg := P.of_isPushout sq.op hg -instance IsStableUnderBaseChange.op {P : MorphismProperty C} [IsStableUnderBaseChange P] : +instance IsStableUnderBaseChange.op [IsStableUnderBaseChange P] : IsStableUnderCobaseChange P.op where of_isPushout sq hf := P.of_isPullback sq.unop hf @@ -221,39 +302,156 @@ instance IsStableUnderCobaseChange.inf {P Q : MorphismProperty C} [IsStableUnder IsStableUnderCobaseChange (P ⊓ Q) where of_isPushout hp hg := ⟨of_isPushout hp hg.left, of_isPushout hp hg.right⟩ -section +end -variable (W : MorphismProperty C) +section LimitsOfShape + +variable (W : MorphismProperty C) (J : Type*) [Category J] + +/-- The class of morphisms in `C` that are limits of shape `J` of +natural transformations involving morphisms in `W`. -/ +inductive limitsOfShape : MorphismProperty C + | mk (X₁ X₂ : J ⥤ C) (c₁ : Cone X₁) (c₂ : Cone X₂) + (_ : IsLimit c₁) (h₂ : IsLimit c₂) (f : X₁ ⟶ X₂) (_ : W.functorCategory J f) : + limitsOfShape (h₂.lift (Cone.mk _ (c₁.π ≫ f))) + +instance : (W.limitsOfShape J).RespectsIso := + RespectsIso.of_respects_arrow_iso _ (by + rintro ⟨_, _, f⟩ ⟨Y₁, Y₂, g⟩ e ⟨X₁, X₂, c₁, c₂, h₁, h₂, f, hf⟩ + let e₁ := Arrow.leftFunc.mapIso e + let e₂ := Arrow.rightFunc.mapIso e + have fac : g ≫ e₂.inv = e₁.inv ≫ h₂.lift (Cone.mk _ (c₁.π ≫ f)) := + e.inv.w.symm + let c₁' : Cone X₁ := { pt := Y₁, π := (Functor.const _).map e₁.inv ≫ c₁.π } + let c₂' : Cone X₂ := { pt := Y₂, π := (Functor.const _).map e₂.inv ≫ c₂.π } + have h₁' : IsLimit c₁' := IsLimit.ofIsoLimit h₁ (Cones.ext e₁) + have h₂' : IsLimit c₂' := IsLimit.ofIsoLimit h₂ (Cones.ext e₂) + obtain hg : h₂'.lift (Cone.mk _ (c₁'.π ≫ f)) = g := + h₂'.hom_ext (fun j ↦ by + rw [h₂'.fac] + simp [reassoc_of% fac, c₁', c₂']) + rw [← hg] + exact ⟨_, _, _, _, h₁', _, _, hf⟩) + +variable {J} in +lemma limitsOfShape_limMap {X Y : J ⥤ C} + (f : X ⟶ Y) [HasLimit X] [HasLimit Y] (hf : W.functorCategory _ f) : + W.limitsOfShape J (limMap f) := + ⟨_, _, _, _, limit.isLimit X, _, _, hf⟩ /-- The property that a morphism property `W` is stable under limits indexed by a category `J`. -/ -def IsStableUnderLimitsOfShape (J : Type*) [Category J] : Prop := +def IsStableUnderLimitsOfShape : Prop := ∀ (X₁ X₂ : J ⥤ C) (c₁ : Cone X₁) (c₂ : Cone X₂) (_ : IsLimit c₁) (h₂ : IsLimit c₂) (f : X₁ ⟶ X₂) (_ : W.functorCategory J f), W (h₂.lift (Cone.mk _ (c₁.π ≫ f))) +lemma isStableUnderLimitsOfShape_iff_limitsOfShape_le : + W.IsStableUnderLimitsOfShape J ↔ W.limitsOfShape J ≤ W := by + constructor + · rintro h _ _ _ ⟨_, _, _, _, h₁, h₂, f, hf⟩ + exact h _ _ _ _ h₁ h₂ f hf + · intro h _ _ _ _ h₁ h₂ f hf + exact h _ ⟨_, _, _, _, h₁, _, _, hf⟩ + +variable {W J} + +lemma IsStableUnderLimitsOfShape.limitsOfShape_le + (hW : W.IsStableUnderLimitsOfShape J) : W.limitsOfShape J ≤ W := + (W.isStableUnderLimitsOfShape_iff_limitsOfShape_le J).1 hW + +lemma IsStableUnderLimitsOfShape.limMap + (hW : W.IsStableUnderLimitsOfShape J) {X Y : J ⥤ C} + (f : X ⟶ Y) [HasLimit X] [HasLimit Y] (hf : W.functorCategory _ f) : + W (limMap f) := + hW.limitsOfShape_le _ (limitsOfShape_limMap _ _ hf) + +end LimitsOfShape + +section ColimitsOfShape + +variable (W : MorphismProperty C) (J : Type*) [Category J] + +/-- The class of morphisms in `C` that are colimits of shape `J` of +natural transformations involving morphisms in `W`. -/ +inductive colimitsOfShape : MorphismProperty C + | mk (X₁ X₂ : J ⥤ C) (c₁ : Cocone X₁) (c₂ : Cocone X₂) + (h₁ : IsColimit c₁) (h₂ : IsColimit c₂) (f : X₁ ⟶ X₂) (_ : W.functorCategory J f) : + colimitsOfShape (h₁.desc (Cocone.mk _ (f ≫ c₂.ι))) + +instance : (W.colimitsOfShape J).RespectsIso := + RespectsIso.of_respects_arrow_iso _ (by + rintro ⟨_, _, f⟩ ⟨Y₁, Y₂, g⟩ e ⟨X₁, X₂, c₁, c₂, h₁, h₂, f, hf⟩ + let e₁ := Arrow.leftFunc.mapIso e + let e₂ := Arrow.rightFunc.mapIso e + have fac : e₁.hom ≫ g = h₁.desc (Cocone.mk _ (f ≫ c₂.ι)) ≫ e₂.hom := e.hom.w + let c₁' : Cocone X₁ := { pt := Y₁, ι := c₁.ι ≫ (Functor.const _).map e₁.hom} + let c₂' : Cocone X₂ := { pt := Y₂, ι := c₂.ι ≫ (Functor.const _).map e₂.hom} + have h₁' : IsColimit c₁' := IsColimit.ofIsoColimit h₁ (Cocones.ext e₁) + have h₂' : IsColimit c₂' := IsColimit.ofIsoColimit h₂ (Cocones.ext e₂) + obtain hg : h₁'.desc (Cocone.mk _ (f ≫ c₂'.ι)) = g := + h₁'.hom_ext (fun j ↦ by + rw [h₁'.fac] + simp [fac, c₁', c₂']) + rw [← hg] + exact ⟨_, _, _, _, _, h₂', _, hf⟩) + +variable {J} in +lemma colimitsOfShape_colimMap {X Y : J ⥤ C} + (f : X ⟶ Y) [HasColimit X] [HasColimit Y] (hf : W.functorCategory _ f) : + W.colimitsOfShape J (colimMap f) := + ⟨_, _, _, _, _, colimit.isColimit Y, _, hf⟩ + /-- The property that a morphism property `W` is stable under colimits indexed by a category `J`. -/ -def IsStableUnderColimitsOfShape (J : Type*) [Category J] : Prop := +def IsStableUnderColimitsOfShape : Prop := ∀ (X₁ X₂ : J ⥤ C) (c₁ : Cocone X₁) (c₂ : Cocone X₂) (h₁ : IsColimit c₁) (_ : IsColimit c₂) (f : X₁ ⟶ X₂) (_ : W.functorCategory J f), W (h₁.desc (Cocone.mk _ (f ≫ c₂.ι))) -variable {W} +lemma isStableUnderColimitsOfShape_iff_colimitsOfShape_le : + W.IsStableUnderColimitsOfShape J ↔ W.colimitsOfShape J ≤ W := by + constructor + · rintro h _ _ _ ⟨_, _, _, _, h₁, h₂, f, hf⟩ + exact h _ _ _ _ h₁ h₂ f hf + · intro h _ _ _ _ h₁ h₂ f hf + exact h _ ⟨_, _, _, _, _, h₂, _, hf⟩ -lemma IsStableUnderLimitsOfShape.lim_map {J : Type*} [Category J] - (hW : W.IsStableUnderLimitsOfShape J) {X Y : J ⥤ C} - (f : X ⟶ Y) [HasLimitsOfShape J C] (hf : W.functorCategory _ f) : - W (lim.map f) := - hW X Y _ _ (limit.isLimit X) (limit.isLimit Y) f hf +variable {W J} -lemma IsStableUnderColimitsOfShape.colim_map {J : Type*} [Category J] +lemma IsStableUnderColimitsOfShape.colimitsOfShape_le + (hW : W.IsStableUnderColimitsOfShape J) : W.colimitsOfShape J ≤ W := + (W.isStableUnderColimitsOfShape_iff_colimitsOfShape_le J).1 hW + +lemma IsStableUnderColimitsOfShape.colimMap (hW : W.IsStableUnderColimitsOfShape J) {X Y : J ⥤ C} - (f : X ⟶ Y) [HasColimitsOfShape J C] (hf : W.functorCategory _ f) : - W (colim.map f) := - hW X Y _ _ (colimit.isColimit X) (colimit.isColimit Y) f hf + (f : X ⟶ Y) [HasColimit X] [HasColimit Y] (hf : W.functorCategory _ f) : + W (colimMap f) := + hW.colimitsOfShape_le _ (colimitsOfShape_colimMap _ _ hf) + +end ColimitsOfShape + +section Coproducts + +variable (W : MorphismProperty C) + +/-- Given `W : MorphismProperty C`, this is class of morphisms that are +isomorphic to a coproduct of a family (indexed by some `J : Type w`) of maps in `W`. -/ +def coproducts : MorphismProperty C := ⨆ (J : Type w), W.colimitsOfShape (Discrete J) + +lemma colimitsOfShape_le_coproducts (J : Type w) : + W.colimitsOfShape (Discrete J) ≤ coproducts.{w} W := + le_iSup (f := fun (J : Type w) ↦ W.colimitsOfShape (Discrete J)) J + +lemma coproducts_iff {X Y : C} (f : X ⟶ Y) : + coproducts.{w} W f ↔ ∃ (J : Type w), W.colimitsOfShape (Discrete J) f := by + simp only [coproducts, iSup_iff] -variable (W) +end Coproducts + +section Products + +variable (W : MorphismProperty C) /-- The property that a morphism property `W` is stable under products indexed by a type `J`. -/ abbrev IsStableUnderProductsOfShape (J : Type*) := W.IsStableUnderLimitsOfShape (Discrete J) @@ -321,7 +519,7 @@ lemma isStableUnderCoproductsOfShape_of_isStableUnderFiniteCoproducts W.IsStableUnderCoproductsOfShape J := IsStableUnderFiniteCoproducts.isStableUnderCoproductsOfShape J -end +end Products section Diagonal From 40cb27c26b1609ac53f1251e811ea0889b68e27e Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 22 Jan 2025 15:30:40 +0000 Subject: [PATCH 424/681] chore(MeasureTheory/Function): shorten proof of instAddLeftMono (#20947) Replace 6 lines of proof with a single application of `add_le_add_left`. According to `set_option trace.profiler true`, this decreasing the elaboration time from 0.29 seconds to 0.09 seconds. Found via [`tryAtEachstep`](https://github.com/dwrensha/tryAtEachStep). --- Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index 1f5fc22267058..611b12c568fd0 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -737,12 +737,7 @@ theorem coeFn_le (f g : Lp.simpleFunc G p μ) : (f : α → G) ≤ᵐ[μ] g ↔ instance instAddLeftMono : AddLeftMono (Lp.simpleFunc G p μ) := by refine ⟨fun f g₁ g₂ hg₁₂ => ?_⟩ - rw [← Lp.simpleFunc.coeFn_le] at hg₁₂ ⊢ - have h_add_1 : ((f + g₁ : Lp.simpleFunc G p μ) : α → G) =ᵐ[μ] (f : α → G) + g₁ := Lp.coeFn_add _ _ - have h_add_2 : ((f + g₂ : Lp.simpleFunc G p μ) : α → G) =ᵐ[μ] (f : α → G) + g₂ := Lp.coeFn_add _ _ - filter_upwards [h_add_1, h_add_2, hg₁₂] with _ h1 h2 h3 - rw [h1, h2, Pi.add_apply, Pi.add_apply] - exact add_le_add le_rfl h3 + exact add_le_add_left hg₁₂ f variable (p μ G) From 6c0f299838250e5428d2e66f576d1a1babab088a Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 22 Jan 2025 15:44:32 +0000 Subject: [PATCH 425/681] chore(MeasureTheory/Function): remove unneeded rw in condexp_restrict_ae_eq_restrict (#20949) Removes an unnecessary rewrite. Found by [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). --- .../MeasureTheory/Function/ConditionalExpectation/Indicator.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean index 32c40f221e8a5..f27dbe2805802 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean @@ -126,7 +126,6 @@ theorem condExp_restrict_ae_eq_restrict (hm : m ≤ m0) [SigmaFinite (μ.trim hm Set.indicator_indicator] suffices h_int_restrict : Integrable (t.indicator ((μ.restrict s)[f|m])) (μ.restrict s) by rw [integrable_indicator_iff (hm _ hs_m), IntegrableOn] - rw [integrable_indicator_iff (hm _ ht), IntegrableOn] at h_int_restrict ⊢ exact h_int_restrict exact integrable_condExp.indicator (hm _ ht) · intro t ht _ From 184a325b076be34c348a6537489403425a9691de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Wed, 22 Jan 2025 16:20:28 +0000 Subject: [PATCH 426/681] =?UTF-8?q?feat(Algebra/GroupWithZero):=20`N?= =?UTF-8?q?=E2=81=B0.comap=20f=20=E2=89=A4=20M=E2=81=B0`=20for=20an=20inje?= =?UTF-8?q?ctive=20`f=20:=20M=20=E2=86=92*=E2=82=80=20N`=20(#20955)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proofs of two facts about non-zero-divisors. --- Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean index 66ad8bce61f90..b2bdd72d7a6b6 100644 --- a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean +++ b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean @@ -237,6 +237,16 @@ theorem nonZeroDivisors_le_comap_nonZeroDivisors_of_injective [NoZeroDivisors M' [MonoidWithZeroHomClass F M M'] (f : F) (hf : Function.Injective f) : M⁰ ≤ M'⁰.comap f := Submonoid.le_comap_of_map_le _ (map_le_nonZeroDivisors_of_injective _ hf le_rfl) +/-- If an element maps to a non-zero-divisor via injective homomorphism, +then it is non-zero-divisor. -/ +theorem mem_nonZeroDivisor_of_injective [MonoidWithZeroHomClass F M M'] {f : F} + (hf : Function.Injective f) {a : M} (ha : f a ∈ M'⁰) : a ∈ M⁰ := + fun x hx ↦ hf <| map_zero f ▸ ha (f x) (map_mul f x a ▸ map_zero f ▸ congrArg f hx) + +theorem comap_nonZeroDivisor_le_of_injective [MonoidWithZeroHomClass F M M'] {f : F} + (hf : Function.Injective f) : M'⁰.comap f ≤ M⁰ := + fun _ ha ↦ mem_nonZeroDivisor_of_injective hf (Submonoid.mem_comap.mp ha) + /-- In a finite ring, an element is a unit iff it is a non-zero-divisor. -/ lemma isUnit_iff_mem_nonZeroDivisors_of_finite [Finite R] {a : R} : IsUnit a ↔ a ∈ nonZeroDivisors R := by From 4ccc2ce04eedecb8dae58659578acb4a06f17527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Wed, 22 Jan 2025 16:34:16 +0000 Subject: [PATCH 427/681] feat: make `Integrable` provable by `fun_prop` (#20952) --- .../ConditionalExpectation/Basic.lean | 1 + .../Function/ConditionalExpectation/Real.lean | 2 +- Mathlib/MeasureTheory/Function/L1Space.lean | 38 ++++++++++++++++++- Mathlib/MeasureTheory/Function/L2Space.lean | 2 + .../Function/SimpleFuncDenseLp.lean | 2 + .../MeasureTheory/Integral/IntegrableOn.lean | 1 + .../Probability/Distributions/Gaussian.lean | 1 + Mathlib/Probability/Martingale/Centering.lean | 11 ++---- Mathlib/Probability/Moments/Basic.lean | 2 +- .../Probability/Moments/IntegrableExpMul.lean | 3 +- Mathlib/Probability/Variance.lean | 2 +- 11 files changed, 52 insertions(+), 13 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index 23ea3343a5989..7e73b119f0eaf 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -215,6 +215,7 @@ theorem condExp_of_aestronglyMeasurable' (hm : m ≤ m0) [hμm : SigmaFinite (μ @[deprecated (since := "2025-01-21")] alias condexp_of_aestronglyMeasurable' := condExp_of_aestronglyMeasurable' +@[fun_prop] theorem integrable_condExp : Integrable (μ[f|m]) μ := by by_cases hm : m ≤ m0 swap; · rw [condExp_of_not_le hm]; exact integrable_zero _ _ _ diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index 18ca101613008..dd17a8eeed254 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -299,7 +299,7 @@ theorem condExp_stronglyMeasurable_mul_of_bound (hm : m ≤ m0) [IsFiniteMeasure · filter_upwards [hfs_tendsto] with x hx exact hx.mul tendsto_const_nhds · exact hg.norm.const_mul c - · exact integrable_condExp.norm.const_mul c + · fun_prop · refine fun n => Eventually.of_forall fun x => ?_ exact (norm_mul_le _ _).trans (mul_le_mul_of_nonneg_right (hfs_bound n x) (norm_nonneg _)) · refine fun n => Eventually.of_forall fun x => ?_ diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index a14a9f3c0bea4..2261536820146 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -409,6 +409,7 @@ variable [TopologicalSpace ε] /-- `Integrable f μ` means that `f` is measurable and that the integral `∫⁻ a, ‖f a‖ ∂μ` is finite. `Integrable f` means `Integrable f volume`. -/ +@[fun_prop] def Integrable {α} {_ : MeasurableSpace α} (f : α → ε) (μ : Measure α := by volume_tac) : Prop := AEStronglyMeasurable f μ ∧ HasFiniteIntegral f μ @@ -466,7 +467,7 @@ theorem Integrable.of_mem_Icc [IsFiniteMeasure μ] (a b : ℝ) {X : α → ℝ} Integrable X μ := ⟨hX.aestronglyMeasurable, .of_mem_Icc a b h⟩ -@[simp] +@[simp, fun_prop] theorem integrable_const [IsFiniteMeasure μ] (c : β) : Integrable (fun _ : α => c) μ := integrable_const_iff.2 <| .inr ‹_› @@ -507,6 +508,7 @@ theorem Integrable.of_measure_le_smul {μ' : Measure α} (c : ℝ≥0∞) (hc : rw [← memℒp_one_iff_integrable] at hf ⊢ exact hf.of_measure_le_smul c hc hμ'_le +@[fun_prop] theorem Integrable.add_measure {f : α → β} (hμ : Integrable f μ) (hν : Integrable f ν) : Integrable f (μ + ν) := by simp_rw [← memℒp_one_iff_integrable] at hμ hν ⊢ @@ -542,6 +544,7 @@ theorem Integrable.smul_measure {f : α → β} (h : Integrable f μ) {c : ℝ rw [← memℒp_one_iff_integrable] at h ⊢ exact h.smul_measure hc +@[fun_prop] theorem Integrable.smul_measure_nnreal {f : α → β} (h : Integrable f μ) {c : ℝ≥0} : Integrable f (c • μ) := by apply h.smul_measure @@ -630,26 +633,35 @@ theorem Integrable.add' {f g : α → β} (hf : Integrable f μ) (hg : Integrabl _ = _ := lintegral_nnnorm_add_left hf.aestronglyMeasurable _ _ < ∞ := add_lt_top.2 ⟨hf.hasFiniteIntegral, hg.hasFiniteIntegral⟩ +@[fun_prop] theorem Integrable.add {f g : α → β} (hf : Integrable f μ) (hg : Integrable g μ) : Integrable (f + g) μ := ⟨hf.aestronglyMeasurable.add hg.aestronglyMeasurable, hf.add' hg⟩ +@[fun_prop] +theorem Integrable.add'' {f g : α → β} (hf : Integrable f μ) (hg : Integrable g μ) : + Integrable (fun x ↦ f x + g x) μ := hf.add hg + +@[fun_prop] theorem integrable_finset_sum' {ι} (s : Finset ι) {f : ι → α → β} (hf : ∀ i ∈ s, Integrable (f i) μ) : Integrable (∑ i ∈ s, f i) μ := Finset.sum_induction f (fun g => Integrable g μ) (fun _ _ => Integrable.add) (integrable_zero _ _ _) hf +@[fun_prop] theorem integrable_finset_sum {ι} (s : Finset ι) {f : ι → α → β} (hf : ∀ i ∈ s, Integrable (f i) μ) : Integrable (fun a => ∑ i ∈ s, f i a) μ := by simpa only [← Finset.sum_apply] using integrable_finset_sum' s hf /-- If `f` is integrable, then so is `-f`. See `Integrable.neg'` for the same statement, but formulated with `x ↦ - f x` instead of `-f`. -/ +@[fun_prop] theorem Integrable.neg {f : α → β} (hf : Integrable f μ) : Integrable (-f) μ := ⟨hf.aestronglyMeasurable.neg, hf.hasFiniteIntegral.neg⟩ /-- If `f` is integrable, then so is `fun x ↦ - f x`. See `Integrable.neg` for the same statement, but formulated with `-f` instead of `fun x ↦ - f x`. -/ +@[fun_prop] theorem Integrable.neg' {f : α → β} (hf : Integrable f μ) : Integrable (fun x ↦ - f x) μ := ⟨hf.aestronglyMeasurable.neg, hf.hasFiniteIntegral.neg⟩ @@ -725,22 +737,31 @@ lemma integrable_const_add_iff [IsFiniteMeasure μ] {f : α → β} {c : β} : Integrable (fun x ↦ c + f x) μ ↔ Integrable f μ := integrable_add_iff_integrable_right (integrable_const _) +@[fun_prop] theorem Integrable.sub {f g : α → β} (hf : Integrable f μ) (hg : Integrable g μ) : Integrable (f - g) μ := by simpa only [sub_eq_add_neg] using hf.add hg.neg +@[fun_prop] +theorem Integrable.sub' {f g : α → β} (hf : Integrable f μ) (hg : Integrable g μ) : + Integrable (fun a ↦ f a - g a) μ := by simpa only [sub_eq_add_neg] using hf.add hg.neg + +@[fun_prop] theorem Integrable.norm {f : α → β} (hf : Integrable f μ) : Integrable (fun a => ‖f a‖) μ := ⟨hf.aestronglyMeasurable.norm, hf.hasFiniteIntegral.norm⟩ +@[fun_prop] theorem Integrable.inf {β} [NormedLatticeAddCommGroup β] {f g : α → β} (hf : Integrable f μ) (hg : Integrable g μ) : Integrable (f ⊓ g) μ := by rw [← memℒp_one_iff_integrable] at hf hg ⊢ exact hf.inf hg +@[fun_prop] theorem Integrable.sup {β} [NormedLatticeAddCommGroup β] {f g : α → β} (hf : Integrable f μ) (hg : Integrable g μ) : Integrable (f ⊔ g) μ := by rw [← memℒp_one_iff_integrable] at hf hg ⊢ exact hf.sup hg +@[fun_prop] theorem Integrable.abs {β} [NormedLatticeAddCommGroup β] {f : α → β} (hf : Integrable f μ) : Integrable (fun a => |f a|) μ := by rw [← memℒp_one_iff_integrable] at hf ⊢ @@ -825,6 +846,7 @@ lemma integrable_of_le_of_le {f g₁ g₂ : α → ℝ} (hf : AEStronglyMeasurab exact max_le_add_of_nonneg (norm_nonneg _) (norm_nonneg _) exact Integrable.mono (h_int₁.norm.add h_int₂.norm) hf h_le_add +@[fun_prop] theorem Integrable.prod_mk {f : α → β} {g : α → γ} (hf : Integrable f μ) (hg : Integrable g μ) : Integrable (fun x => (f x, g x)) μ := ⟨hf.aestronglyMeasurable.prod_mk hg.aestronglyMeasurable, @@ -895,6 +917,7 @@ theorem LipschitzWith.integrable_comp_iff_of_antilipschitz {K K'} {f : α → β Integrable (g ∘ f) μ ↔ Integrable f μ := by simp [← memℒp_one_iff_integrable, hg.memℒp_comp_iff_of_antilipschitz hg' g0] +@[fun_prop] theorem Integrable.real_toNNReal {f : α → ℝ} (hf : Integrable f μ) : Integrable (fun x => ((f x).toNNReal : ℝ)) μ := by refine @@ -1113,11 +1136,13 @@ section PosPart /-! ### Lemmas used for defining the positive part of an `L¹` function -/ +@[fun_prop] theorem Integrable.pos_part {f : α → ℝ} (hf : Integrable f μ) : Integrable (fun a => max (f a) 0) μ := ⟨(hf.aestronglyMeasurable.aemeasurable.max aemeasurable_const).aestronglyMeasurable, hf.hasFiniteIntegral.max_zero⟩ +@[fun_prop] theorem Integrable.neg_part {f : α → ℝ} (hf : Integrable f μ) : Integrable (fun a => max (-f a) 0) μ := hf.neg.pos_part @@ -1128,6 +1153,7 @@ section BoundedSMul variable {𝕜 : Type*} +@[fun_prop] theorem Integrable.smul [NormedAddCommGroup 𝕜] [SMulZeroClass 𝕜 β] [BoundedSMul 𝕜 β] (c : 𝕜) {f : α → β} (hf : Integrable f μ) : Integrable (c • f) μ := ⟨hf.aestronglyMeasurable.const_smul c, hf.hasFiniteIntegral.smul c⟩ @@ -1152,6 +1178,7 @@ theorem Integrable.smul_of_top_left {f : α → β} {φ : α → 𝕜} (hφ : In rw [← memℒp_one_iff_integrable] at hφ ⊢ exact Memℒp.smul_of_top_left hf hφ +@[fun_prop] theorem Integrable.smul_const {f : α → 𝕜} (hf : Integrable f μ) (c : β) : Integrable (fun x => f x • c) μ := hf.smul_of_top_left (memℒp_top_const c) @@ -1177,6 +1204,7 @@ section NormedRing variable {𝕜 : Type*} [NormedRing 𝕜] {f : α → 𝕜} +@[fun_prop] theorem Integrable.const_mul {f : α → 𝕜} (h : Integrable f μ) (c : 𝕜) : Integrable (fun x => c * f x) μ := h.smul c @@ -1185,6 +1213,7 @@ theorem Integrable.const_mul' {f : α → 𝕜} (h : Integrable f μ) (c : 𝕜) Integrable ((fun _ : α => c) * f) μ := Integrable.const_mul h c +@[fun_prop] theorem Integrable.mul_const {f : α → 𝕜} (h : Integrable f μ) (c : 𝕜) : Integrable (fun x => f x * c) μ := h.smul (MulOpposite.op c) @@ -1223,6 +1252,7 @@ section NormedDivisionRing variable {𝕜 : Type*} [NormedDivisionRing 𝕜] {f : α → 𝕜} +@[fun_prop] theorem Integrable.div_const {f : α → 𝕜} (h : Integrable f μ) (c : 𝕜) : Integrable (fun x => f x / c) μ := by simp_rw [div_eq_mul_inv, h.mul_const] @@ -1232,6 +1262,7 @@ section RCLike variable {𝕜 : Type*} [RCLike 𝕜] {f : α → 𝕜} +@[fun_prop] theorem Integrable.ofReal {f : α → ℝ} (hf : Integrable f μ) : Integrable (fun x => (f x : 𝕜)) μ := by rw [← memℒp_one_iff_integrable] at hf ⊢ @@ -1243,10 +1274,12 @@ theorem Integrable.re_im_iff : simp_rw [← memℒp_one_iff_integrable] exact memℒp_re_im_iff +@[fun_prop] theorem Integrable.re (hf : Integrable f μ) : Integrable (fun x => RCLike.re (f x)) μ := by rw [← memℒp_one_iff_integrable] at hf ⊢ exact hf.re +@[fun_prop] theorem Integrable.im (hf : Integrable f μ) : Integrable (fun x => RCLike.im (f x)) μ := by rw [← memℒp_one_iff_integrable] at hf ⊢ exact hf.im @@ -1517,6 +1550,7 @@ open MeasureTheory variable {E : Type*} [NormedAddCommGroup E] {𝕜 : Type*} [NontriviallyNormedField 𝕜] [NormedSpace 𝕜 E] {H : Type*} [NormedAddCommGroup H] [NormedSpace 𝕜 H] +@[fun_prop] theorem ContinuousLinearMap.integrable_comp {φ : α → H} (L : H →L[𝕜] E) (φ_int : Integrable φ μ) : Integrable (fun a : α => L (φ a)) μ := ((Integrable.norm φ_int).const_mul ‖L‖).mono' @@ -1545,9 +1579,11 @@ namespace MeasureTheory variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [NormedAddCommGroup F] [NormedSpace ℝ F] +@[fun_prop] lemma Integrable.fst {f : α → E × F} (hf : Integrable f μ) : Integrable (fun x ↦ (f x).1) μ := (ContinuousLinearMap.fst ℝ E F).integrable_comp hf +@[fun_prop] lemma Integrable.snd {f : α → E × F} (hf : Integrable f μ) : Integrable (fun x ↦ (f x).2) μ := (ContinuousLinearMap.snd ℝ E F).integrable_comp hf diff --git a/Mathlib/MeasureTheory/Function/L2Space.lean b/Mathlib/MeasureTheory/Function/L2Space.lean index 6877529dd2328..3594c9e9b9d38 100644 --- a/Mathlib/MeasureTheory/Function/L2Space.lean +++ b/Mathlib/MeasureTheory/Function/L2Space.lean @@ -70,10 +70,12 @@ theorem Memℒp.inner_const {f : α → E} (hf : Memℒp f p μ) (c : E) : Mem variable {f : α → E} +@[fun_prop] theorem Integrable.const_inner (c : E) (hf : Integrable f μ) : Integrable (fun x => ⟪c, f x⟫) μ := by rw [← memℒp_one_iff_integrable] at hf ⊢; exact hf.const_inner c +@[fun_prop] theorem Integrable.inner_const (hf : Integrable f μ) (c : E) : Integrable (fun x => ⟪f x, c⟫) μ := by rw [← memℒp_one_iff_integrable] at hf ⊢; exact hf.inner_const c diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index 611b12c568fd0..7ad4405faa9c1 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -359,6 +359,7 @@ theorem memℒp_of_isFiniteMeasure (f : α →ₛ E) (p : ℝ≥0∞) (μ : Meas let ⟨C, hfC⟩ := f.exists_forall_norm_le Memℒp.of_bound f.aestronglyMeasurable C <| Eventually.of_forall hfC +@[fun_prop] theorem integrable_of_isFiniteMeasure [IsFiniteMeasure μ] (f : α →ₛ E) : Integrable f μ := memℒp_one_iff_integrable.mp (f.memℒp_of_isFiniteMeasure 1 μ) @@ -945,6 +946,7 @@ theorem L1.SimpleFunc.toLp_one_eq_toL1 (f : α →ₛ E) (hf : Integrable f μ) (Lp.simpleFunc.toLp f (memℒp_one_iff_integrable.2 hf) : α →₁[μ] E) = hf.toL1 f := rfl +@[fun_prop] protected theorem L1.SimpleFunc.integrable (f : α →₁ₛ[μ] E) : Integrable (Lp.simpleFunc.toSimpleFunc f) μ := by rw [← memℒp_one_iff_integrable]; exact Lp.simpleFunc.memℒp f diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index c476a8473164b..d92e2f0b636d3 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -240,6 +240,7 @@ theorem IntegrableOn.integrable_indicator (h : IntegrableOn f s μ) (hs : Measur Integrable (indicator s f) μ := (integrable_indicator_iff hs).2 h +@[fun_prop] theorem Integrable.indicator (h : Integrable f μ) (hs : MeasurableSet s) : Integrable (indicator s f) μ := h.integrableOn.integrable_indicator hs diff --git a/Mathlib/Probability/Distributions/Gaussian.lean b/Mathlib/Probability/Distributions/Gaussian.lean index 11c870959f6a1..8b3c99c7d763c 100644 --- a/Mathlib/Probability/Distributions/Gaussian.lean +++ b/Mathlib/Probability/Distributions/Gaussian.lean @@ -71,6 +71,7 @@ lemma stronglyMeasurable_gaussianPDFReal (μ : ℝ) (v : ℝ≥0) : StronglyMeasurable (gaussianPDFReal μ v) := (measurable_gaussianPDFReal μ v).stronglyMeasurable +@[fun_prop] lemma integrable_gaussianPDFReal (μ : ℝ) (v : ℝ≥0) : Integrable (gaussianPDFReal μ v) := by rw [gaussianPDFReal_def] diff --git a/Mathlib/Probability/Martingale/Centering.lean b/Mathlib/Probability/Martingale/Centering.lean index 4b33ee59f7e98..0802f506c451a 100644 --- a/Mathlib/Probability/Martingale/Centering.lean +++ b/Mathlib/Probability/Martingale/Centering.lean @@ -76,8 +76,7 @@ theorem adapted_martingalePart (hf : Adapted ℱ f) : Adapted ℱ (martingalePar theorem integrable_martingalePart (hf_int : ∀ n, Integrable (f n) μ) (n : ℕ) : Integrable (martingalePart f ℱ μ n) μ := by rw [martingalePart_eq_sum] - exact (hf_int 0).add - (integrable_finset_sum' _ fun i _ => ((hf_int _).sub (hf_int _)).sub integrable_condExp) + fun_prop theorem martingale_martingalePart (hf : Adapted ℱ f) (hf_int : ∀ n, Integrable (f n) μ) [SigmaFiniteFiltration μ ℱ] : Martingale (martingalePart f ℱ μ) ℱ μ := by @@ -86,14 +85,12 @@ theorem martingale_martingalePart (hf : Adapted ℱ f) (hf_int : ∀ n, Integrab have h_eq_sum : μ[martingalePart f ℱ μ j|ℱ i] =ᵐ[μ] f 0 + ∑ k ∈ Finset.range j, (μ[f (k + 1) - f k|ℱ i] - μ[μ[f (k + 1) - f k|ℱ k]|ℱ i]) := by rw [martingalePart_eq_sum] - refine (condExp_add (hf_int 0) ?_).trans ?_ - · exact integrable_finset_sum' _ fun i _ => ((hf_int _).sub (hf_int _)).sub integrable_condExp - refine (EventuallyEq.add EventuallyEq.rfl (condExp_finset_sum fun i _ => ?_)).trans ?_ - · exact ((hf_int _).sub (hf_int _)).sub integrable_condExp + refine (condExp_add (hf_int 0) (by fun_prop)).trans ?_ + refine (EventuallyEq.rfl.add (condExp_finset_sum fun i _ => by fun_prop)).trans ?_ refine EventuallyEq.add ?_ ?_ · rw [condExp_of_stronglyMeasurable (ℱ.le _) _ (hf_int 0)] · exact (hf 0).mono (ℱ.mono (zero_le i)) - · exact eventuallyEq_sum fun k _ => condExp_sub ((hf_int _).sub (hf_int _)) integrable_condExp + · exact eventuallyEq_sum fun k _ => condExp_sub (by fun_prop) integrable_condExp refine h_eq_sum.trans ?_ have h_ge : ∀ k, i ≤ k → μ[f (k + 1) - f k|ℱ i] - μ[μ[f (k + 1) - f k|ℱ k]|ℱ i] =ᵐ[μ] 0 := by intro k hk diff --git a/Mathlib/Probability/Moments/Basic.lean b/Mathlib/Probability/Moments/Basic.lean index 702f6a22f7438..ec9aaa1d55422 100644 --- a/Mathlib/Probability/Moments/Basic.lean +++ b/Mathlib/Probability/Moments/Basic.lean @@ -88,7 +88,7 @@ theorem centralMoment_one [IsZeroOrProbabilityMeasure μ] : centralMoment X 1 μ refine fun h_sub => h_int ?_ have h_add : X = (fun x => X x - integral μ X) + fun _ => integral μ X := by ext1 x; simp rw [h_add] - exact h_sub.add (integrable_const _) + fun_prop rw [integral_undef this] theorem centralMoment_two_eq_variance [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : diff --git a/Mathlib/Probability/Moments/IntegrableExpMul.lean b/Mathlib/Probability/Moments/IntegrableExpMul.lean index 27e4cb7cfa305..f2135d63a157e 100644 --- a/Mathlib/Probability/Moments/IntegrableExpMul.lean +++ b/Mathlib/Probability/Moments/IntegrableExpMul.lean @@ -266,8 +266,7 @@ lemma integrable_rpow_abs_mul_exp_add_of_integrable_exp_mul {x : ℝ} swap; · rw [← sub_ne_zero]; simp [ht] rw [← integrable_norm_iff] swap - · refine AEMeasurable.aestronglyMeasurable ?_ - exact AEMeasurable.mul (by fun_prop) (measurable_exp.comp_aemeasurable (by fun_prop)) + · exact AEMeasurable.aestronglyMeasurable <| by fun_prop simp only [norm_mul, norm_pow, norm_eq_abs, sq_abs, abs_exp] have h_le a : |X a| ^ p * exp (v * X a + x * |X a|) ≤ (p / (|t| - x)) ^ p * exp (v * X a + |t| * |X a|) := by diff --git a/Mathlib/Probability/Variance.lean b/Mathlib/Probability/Variance.lean index 849d2cb3bd317..5c3c9f6c42be4 100644 --- a/Mathlib/Probability/Variance.lean +++ b/Mathlib/Probability/Variance.lean @@ -380,7 +380,7 @@ lemma variance_le_sub_mul_sub [IsProbabilityMeasure μ] {a b : ℝ} {X : Ω → _ = ∫ ω, - X ω ^ 2 + (a + b) * X ω - a * b ∂μ := integral_congr_ae <| ae_of_all μ fun ω ↦ by ring _ = ∫ ω, - X ω ^ 2 + (a + b) * X ω ∂μ - ∫ _, a * b ∂μ := - integral_sub (hX_int₂.add hX_int₁) (integrable_const (a * b)) + integral_sub (by fun_prop) (integrable_const (a * b)) _ = ∫ ω, - X ω ^ 2 + (a + b) * X ω ∂μ - a * b := by simp _ = - μ[X ^ 2] + (a + b) * μ[X] - a * b := by simp [← integral_neg, ← integral_mul_left, integral_add hX_int₂ hX_int₁] From d9e9d6efc3aed79dc371b7d032f1f745ba095538 Mon Sep 17 00:00:00 2001 From: Kexing Ying Date: Wed, 22 Jan 2025 16:48:03 +0000 Subject: [PATCH 428/681] feat: `condExpL2` equals `condExp` for L2 functions (#20945) Co-authored-by: Kexing Ying --- .../ConditionalExpectation/Basic.lean | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index 7e73b119f0eaf..0da3f8d3a0c47 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -277,6 +277,50 @@ alias ae_eq_condExp_of_forall_set_integral_eq := ae_eq_condExp_of_forall_setInte @[deprecated (since := "2025-01-21")] alias ae_eq_condexp_of_forall_set_integral_eq := ae_eq_condExp_of_forall_set_integral_eq +section MemL2 + +lemma Memℒp.condExpL2_ae_eq_condExp' {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] + (hm : m ≤ m0) (hf1 : Integrable f μ) (hf2 : Memℒp f 2 μ) [SigmaFinite (μ.trim hm)] : + condExpL2 F' 𝕜 hm hf2.toLp =ᵐ[μ] μ[f | m] := by + refine ae_eq_condExp_of_forall_setIntegral_eq hm hf1 + (fun s hs htop ↦ integrableOn_condExpL2_of_measure_ne_top hm htop.ne _) (fun s hs htop ↦ ?_) + (aeStronglyMeasurable'_condExpL2 hm _) + rw [integral_condExpL2_eq hm (hf2.toLp _) hs htop.ne] + refine setIntegral_congr_ae (hm _ hs) ?_ + filter_upwards [hf2.coeFn_toLp] with ω hω _ using hω + +lemma Memℒp.condExpL2_ae_eq_condExp {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] + (hm : m ≤ m0) (hf : Memℒp f 2 μ) [IsFiniteMeasure μ] : + condExpL2 F' 𝕜 hm hf.toLp =ᵐ[μ] μ[f | m] := + hf.condExpL2_ae_eq_condExp' hm (memℒp_one_iff_integrable.1 <| hf.mono_exponent one_le_two) + +-- TODO: Generalize via the conditional Jensen inequality +lemma eLpNorm_condExp_le {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] : + eLpNorm (μ[f | m]) 2 μ ≤ eLpNorm f 2 μ := by + by_cases hm : m ≤ m0; swap + · simp [condExp_of_not_le hm] + by_cases hfμ : SigmaFinite (μ.trim hm); swap + · rw [condExp_of_not_sigmaFinite hm hfμ] + simp + by_cases hfi : Integrable f μ; swap + · rw [condExp_undef hfi] + simp + obtain hf | hf := eq_or_ne (eLpNorm f 2 μ) ∞ + · simp [hf] + replace hf : Memℒp f 2 μ := ⟨hfi.1, Ne.lt_top' fun a ↦ hf (id (Eq.symm a))⟩ + rw [← eLpNorm_congr_ae (hf.condExpL2_ae_eq_condExp' (𝕜 := 𝕜) hm hfi)] + refine le_trans (eLpNorm_condExpL2_le hm _) ?_ + rw [eLpNorm_congr_ae hf.coeFn_toLp] + +protected lemma Memℒp.condExp {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] + (hf : Memℒp f 2 μ) : Memℒp (μ[f | m]) 2 μ := by + by_cases hm : m ≤ m0 + · exact ⟨(stronglyMeasurable_condExp.mono hm).aestronglyMeasurable, + eLpNorm_condExp_le (𝕜 := 𝕜).trans_lt hf.eLpNorm_lt_top⟩ + · simp [condExp_of_not_le hm] + +end MemL2 + theorem condExp_bot' [hμ : NeZero μ] (f : α → F') : μ[f|⊥] = fun _ => (μ Set.univ).toReal⁻¹ • ∫ x, f x ∂μ := by by_cases hμ_finite : IsFiniteMeasure μ From bd502a40fb334f8d7007d830793db6509680c886 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 22 Jan 2025 16:48:05 +0000 Subject: [PATCH 429/681] chore(NumberTheory/FermatPsp): use gcongr to shorten proof of psp_from_prime_gt_p (#20948) Replaces 3 lines of proof (including an `nlinarith` class) with a single call to `gcongr`. According to `set_option trace.profiler true`, this speeds up elebatoration of the theorem from 1.68 seconds to 1.50 seconds. Found via [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). --- Mathlib/NumberTheory/FermatPsp.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Mathlib/NumberTheory/FermatPsp.lean b/Mathlib/NumberTheory/FermatPsp.lean index 12a27a0b7613d..5c593d0213ec5 100644 --- a/Mathlib/NumberTheory/FermatPsp.lean +++ b/Mathlib/NumberTheory/FermatPsp.lean @@ -306,10 +306,7 @@ private theorem psp_from_prime_gt_p {b : ℕ} (b_ge_two : 2 ≤ b) {p : ℕ} (p_ · exact tsub_le_tsub_left (one_le_of_lt p_gt_two) ((b ^ 2) ^ (p - 1) * b ^ 2) · have : p ≤ p * b ^ 2 := Nat.le_mul_of_pos_right _ (show 0 < b ^ 2 by positivity) exact tsub_lt_tsub_right_of_le this h - suffices h : p < (b ^ 2) ^ (p - 1) by - have : 4 ≤ b ^ 2 := by nlinarith - have : 0 < b ^ 2 := by omega - exact mul_lt_mul_of_pos_right h this + suffices h : p < (b ^ 2) ^ (p - 1) by gcongr rw [← pow_mul, Nat.mul_sub_left_distrib, mul_one] have : 2 ≤ 2 * p - 2 := le_tsub_of_add_le_left (show 4 ≤ 2 * p by omega) have : 2 + p ≤ 2 * p := by omega From 2cb1216e55b6e3706e1f7a541fc364408320ddbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Wed, 22 Jan 2025 18:42:27 +0000 Subject: [PATCH 430/681] chore(Order/WellFoundedSet): flip `isWF_iff_isPWO` (#20937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Iff lemmas are generally of the form `complicated thing ↔ simpler thing`, and being a PWO is more complicated than being a well-founded set (in the sense that PWOs are well-founded sets with extra conditions). --- Mathlib/Order/WellFoundedSet.lean | 11 +++++++++-- Mathlib/RingTheory/HahnSeries/Basic.lean | 5 ++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Mathlib/Order/WellFoundedSet.lean b/Mathlib/Order/WellFoundedSet.lean index 49a7c70b652e2..99677f208a00d 100644 --- a/Mathlib/Order/WellFoundedSet.lean +++ b/Mathlib/Order/WellFoundedSet.lean @@ -505,9 +505,13 @@ protected theorem IsWF.isPWO (hs : s.IsWF) : s.IsPWO := by simp only [forall_mem_range, not_lt] at hm exact ⟨m, m + 1, by omega, hm _⟩ -/-- In a linear order, the predicates `Set.IsWF` and `Set.IsPWO` are equivalent. -/ +/-- In a linear order, the predicates `Set.IsPWO` and `Set.IsWF` are equivalent. -/ +theorem isPWO_iff_isWF : s.IsPWO ↔ s.IsWF := + ⟨IsPWO.isWF, IsWF.isPWO⟩ + +@[deprecated isPWO_iff_isWF (since := "2025-01-21")] theorem isWF_iff_isPWO : s.IsWF ↔ s.IsPWO := - ⟨IsWF.isPWO, IsPWO.isWF⟩ + isPWO_iff_isWF.symm /-- If `α` is a linear order with well-founded `<`, then any set in it is a partially well-ordered set. @@ -668,6 +672,9 @@ theorem BddBelow.wellFoundedOn_lt : BddBelow s → s.WellFoundedOn (· < ·) := theorem BddAbove.wellFoundedOn_gt : BddAbove s → s.WellFoundedOn (· > ·) := fun h => h.dual.wellFoundedOn_lt +theorem BddBelow.isWF : BddBelow s → IsWF s := + BddBelow.wellFoundedOn_lt + end LocallyFiniteOrder namespace Set.PartiallyWellOrderedOn diff --git a/Mathlib/RingTheory/HahnSeries/Basic.lean b/Mathlib/RingTheory/HahnSeries/Basic.lean index b074a86e1aa3b..e29ff4fcd2b4d 100644 --- a/Mathlib/RingTheory/HahnSeries/Basic.lean +++ b/Mathlib/RingTheory/HahnSeries/Basic.lean @@ -476,10 +476,9 @@ theorem BddBelow_zero [Nonempty Γ] : BddBelow (Function.support (0 : Γ → R)) variable [LocallyFiniteOrder Γ] -theorem suppBddBelow_supp_PWO (f : Γ → R) - (hf : BddBelow (Function.support f)) : +theorem suppBddBelow_supp_PWO (f : Γ → R) (hf : BddBelow (Function.support f)) : (Function.support f).IsPWO := - Set.isWF_iff_isPWO.mp hf.wellFoundedOn_lt + hf.isWF.isPWO /-- Construct a Hahn series from any function whose support is bounded below. -/ @[simps] From be72b7b0797ea957925248b36f9ce76c5aecc0de Mon Sep 17 00:00:00 2001 From: Christopher Hoskin Date: Wed, 22 Jan 2025 19:43:00 +0000 Subject: [PATCH 431/681] feat(Order/Bounds/Lattice): bounds over collections of sets (#19150) Some results about upper and lower bounds over collections of sets. Inspired by #15412, but possibly of greater interest? Co-authored-by: Christopher Hoskin --- Mathlib.lean | 1 + Mathlib/Order/Bounds/Basic.lean | 6 ++++ Mathlib/Order/Bounds/Lattice.lean | 47 +++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 Mathlib/Order/Bounds/Lattice.lean diff --git a/Mathlib.lean b/Mathlib.lean index b9fd43baf0669..cef32928284c7 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4104,6 +4104,7 @@ import Mathlib.Order.BoundedOrder.Monotone import Mathlib.Order.Bounds.Basic import Mathlib.Order.Bounds.Defs import Mathlib.Order.Bounds.Image +import Mathlib.Order.Bounds.Lattice import Mathlib.Order.Bounds.OrderIso import Mathlib.Order.Category.BddDistLat import Mathlib.Order.Category.BddLat diff --git a/Mathlib/Order/Bounds/Basic.lean b/Mathlib/Order/Bounds/Basic.lean index ad2107194dde3..ff8f494fcda96 100644 --- a/Mathlib/Order/Bounds/Basic.lean +++ b/Mathlib/Order/Bounds/Basic.lean @@ -119,6 +119,12 @@ abbrev IsGreatest.orderTop (h : IsGreatest s a) : top := ⟨a, h.1⟩ le_top := Subtype.forall.2 h.2 +theorem isLUB_congr (h : upperBounds s = upperBounds t) : IsLUB s a ↔ IsLUB t a := by + rw [IsLUB, IsLUB, h] + +theorem isGLB_congr (h : lowerBounds s = lowerBounds t) : IsGLB s a ↔ IsGLB t a := by + rw [IsGLB, IsGLB, h] + /-! ### Monotonicity -/ diff --git a/Mathlib/Order/Bounds/Lattice.lean b/Mathlib/Order/Bounds/Lattice.lean new file mode 100644 index 0000000000000..4debbe2ec02e8 --- /dev/null +++ b/Mathlib/Order/Bounds/Lattice.lean @@ -0,0 +1,47 @@ +/- +Copyright (c) 2024 Christopher Hoskin. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Christopher Hoskin +-/ +import Mathlib.Data.Set.Lattice + +/-! +# Unions and intersections of bounds + +Some results about upper and lower bounds over collections of sets. + +## Implementation notes + +In a separate file as we need to import `Mathlib.Data.Set.Lattice`. + +-/ + +variable {α : Type*} [Preorder α] {ι : Sort*} {s : ι → Set α} + +open Set + +theorem gc_upperBounds_lowerBounds : GaloisConnection + (OrderDual.toDual ∘ upperBounds : Set α → (Set α)ᵒᵈ) + (lowerBounds ∘ OrderDual.ofDual : (Set α)ᵒᵈ → Set α) := by + simpa [GaloisConnection, subset_def, mem_upperBounds, mem_lowerBounds] + using fun S T ↦ forall₂_swap + +@[simp] +theorem upperBounds_iUnion : + upperBounds (⋃ i, s i) = ⋂ i, upperBounds (s i) := + gc_upperBounds_lowerBounds.l_iSup + +@[simp] +theorem lowerBounds_iUnion : + lowerBounds (⋃ i, s i) = ⋂ i, lowerBounds (s i) := + gc_upperBounds_lowerBounds.u_iInf + +theorem isLUB_iUnion_iff_of_isLUB {u : ι → α} (hs : ∀ i, IsLUB (s i) (u i)) (c : α) : + IsLUB (Set.range u) c ↔ IsLUB (⋃ i, s i) c := by + refine isLUB_congr ?_ + simp_rw [range_eq_iUnion, upperBounds_iUnion, upperBounds_singleton, (hs _).upperBounds_eq] + +theorem isGLB_iUnion_iff_of_isLUB {u : ι → α} (hs : ∀ i, IsGLB (s i) (u i)) (c : α) : + IsGLB (Set.range u) c ↔ IsGLB (⋃ i, s i) c := by + refine isGLB_congr ?_ + simp_rw [range_eq_iUnion, lowerBounds_iUnion, lowerBounds_singleton, (hs _).lowerBounds_eq] From 568cf0493039f2c7b8b80ad33ebf04fb735aaf69 Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 22 Jan 2025 20:27:51 +0000 Subject: [PATCH 432/681] feat(CI): manage `merge-conflict` label on push (#20961) Add a step to the PR summary workflow that adds or removes the `merge-conflict` label, as appropriate. We place the action in the PR summary workflow, since that workflow already checks out the whole repository, so the "cost" of the step is simply to verify whether there are merge conflicts and add/remove the label. See #19464 for a PR whose `merge-conflict` label was removed by this workflow. --- .github/workflows/PR_summary.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/PR_summary.yml b/.github/workflows/PR_summary.yml index 1c095f8a66f89..111d7058adaa3 100644 --- a/.github/workflows/PR_summary.yml +++ b/.github/workflows/PR_summary.yml @@ -14,6 +14,27 @@ jobs: with: fetch-depth: 0 + - name: Update the merge-conflict label + run: | + printf 'PR number: "%s"\n' "${{ github.event.pull_request.number }}" + if git merge origin/master --no-ff --no-commit + then + git merge --abort || true + echo "This PR does not have merge conflicts with master." + # we use curl rather than octokit/request-action so that the job won't fail + # (and send an annoying email) if the labels don't exist + curl --request DELETE \ + --url https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/merge-conflict \ + --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' + else + echo "This PR has merge conflicts with main." + # we use curl rather than octokit/request-action so that the job won't fail + # (and send an annoying email) if the labels don't exist + curl --request POST \ + --url https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/merge-conflict \ + --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' + fi + - name: Set up Python uses: actions/setup-python@v5 with: From 3226828897ffb337c36a3f486aaf2b0e6c0e9e6c Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Wed, 22 Jan 2025 21:07:05 +0000 Subject: [PATCH 433/681] feat(Data/Matrix/Mul): vecMul and mulVec are sums (#20950) We add lemmas expressing `vecMul` and `mulVec` as summations. --- Mathlib/Data/Matrix/Mul.lean | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Mathlib/Data/Matrix/Mul.lean b/Mathlib/Data/Matrix/Mul.lean index 92ba31f826ae7..4f71ea9008fa3 100644 --- a/Mathlib/Data/Matrix/Mul.lean +++ b/Mathlib/Data/Matrix/Mul.lean @@ -642,6 +642,13 @@ theorem mul_apply_eq_vecMul [Fintype n] (A : Matrix m n α) (B : Matrix n o α) (A * B) i = A i ᵥ* B := rfl +theorem vecMul_eq_sum [Fintype m] (v : m → α) (M : Matrix m n α) : v ᵥ* M = ∑ i, v i • M i := + (Finset.sum_fn ..).symm + +theorem mulVec_eq_sum [Fintype n] (v : n → α) (M : Matrix m n α) : + M *ᵥ v = ∑ i, MulOpposite.op (v i) • Mᵀ i := + (Finset.sum_fn ..).symm + theorem mulVec_diagonal [Fintype m] [DecidableEq m] (v w : m → α) (x : m) : (diagonal v *ᵥ w) x = v x * w x := diagonal_dotProduct v w x From 3e2f75fecded964cd9d2a775dbdf1ed6ba2f689c Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Wed, 22 Jan 2025 21:30:31 +0000 Subject: [PATCH 434/681] feat(Algebra/MonoidAlgebra): strengthen lemmas about coefficients of products (#20944) The degrees need only be cancellative on the support. Co-authored-by: Eric Wieser --- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 47 +++++++++++---------- Mathlib/Algebra/MonoidAlgebra/Division.lean | 6 +-- Mathlib/Algebra/MvPolynomial/Basic.lean | 4 +- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index 337f590109744..0347038157818 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -562,22 +562,22 @@ def singleHom [MulOneClass G] : k × G →* MonoidAlgebra k G where map_mul' _a _b := single_mul_single.symm theorem mul_single_apply_aux [Mul G] (f : MonoidAlgebra k G) {r : k} {x y z : G} - (H : ∀ a, a * x = z ↔ a = y) : (f * single x r) z = f y * r := by + (H : ∀ a ∈ f.support, a * x = z ↔ a = y) : (f * single x r) z = f y * r := by classical exact - have A : - ∀ a₁ b₁, - ((single x r).sum fun a₂ b₂ => ite (a₁ * a₂ = z) (b₁ * b₂) 0) = - ite (a₁ * x = z) (b₁ * r) 0 := - fun a₁ b₁ => sum_single_index <| by simp - calc - (HMul.hMul (β := MonoidAlgebra k G) f (single x r)) z = - sum f fun a b => if a = y then b * r else 0 := by simp only [mul_apply, A, H] - _ = if y ∈ f.support then f y * r else 0 := f.support.sum_ite_eq' _ _ - _ = f y * r := by split_ifs with h <;> simp at h <;> simp [h] + calc + (f * single x r) z + _ = sum f fun a b => ite (a * x = z) (b * r) 0 := + (mul_apply _ _ _).trans <| Finsupp.sum_congr fun _ _ => sum_single_index (by simp) + + _ = f.sum fun a b => ite (a = y) (b * r) 0 := Finsupp.sum_congr fun x hx => by + simp only [H _ hx] + _ = if y ∈ f.support then f y * r else 0 := f.support.sum_ite_eq' _ _ + _ = _ := by split_ifs with h <;> simp at h <;> simp [h] + theorem mul_single_one_apply [MulOneClass G] (f : MonoidAlgebra k G) (r : k) (x : G) : (HMul.hMul (β := MonoidAlgebra k G) f (single 1 r)) x = f x * r := - f.mul_single_apply_aux fun a => by rw [mul_one] + f.mul_single_apply_aux fun a ha => by rw [mul_one] theorem mul_single_apply_of_not_exists_mul [Mul G] (r : k) {g g' : G} (x : MonoidAlgebra k G) (h : ¬∃ d, g' = d * g) : (x * single g r) g' = 0 := by @@ -592,20 +592,21 @@ theorem mul_single_apply_of_not_exists_mul [Mul G] (r : k) {g g' : G} (x : Monoi exact h ⟨_, rfl⟩ theorem single_mul_apply_aux [Mul G] (f : MonoidAlgebra k G) {r : k} {x y z : G} - (H : ∀ a, x * a = y ↔ a = z) : (single x r * f) y = r * f z := by + (H : ∀ a ∈ f.support, x * a = y ↔ a = z) : (single x r * f) y = r * f z := by classical exact have : (f.sum fun a b => ite (x * a = y) (0 * b) 0) = 0 := by simp calc - (HMul.hMul (α := MonoidAlgebra k G) (single x r) f) y = - sum f fun a b => ite (x * a = y) (r * b) 0 := + (single x r * f) y + _ = sum f fun a b => ite (x * a = y) (r * b) 0 := (mul_apply _ _ _).trans <| sum_single_index this - _ = f.sum fun a b => ite (a = z) (r * b) 0 := by simp only [H] + _ = f.sum fun a b => ite (a = z) (r * b) 0 := Finsupp.sum_congr fun x hx => by + simp only [H _ hx] _ = if z ∈ f.support then r * f z else 0 := f.support.sum_ite_eq' _ _ _ = _ := by split_ifs with h <;> simp at h <;> simp [h] theorem single_one_mul_apply [MulOneClass G] (f : MonoidAlgebra k G) (r : k) (x : G) : (single (1 : G) r * f) x = r * f x := - f.single_mul_apply_aux fun a => by rw [one_mul] + f.single_mul_apply_aux fun a ha => by rw [one_mul] theorem single_mul_apply_of_not_exists_mul [Mul G] (r : k) {g g' : G} (x : MonoidAlgebra k G) (h : ¬∃ d, g' = g * d) : (single g r * x) g' = 0 := by @@ -753,12 +754,12 @@ variable [Semiring k] [Group G] @[simp] theorem mul_single_apply (f : MonoidAlgebra k G) (r : k) (x y : G) : (f * single x r) y = f (y * x⁻¹) * r := - f.mul_single_apply_aux fun _a => eq_mul_inv_iff_mul_eq.symm + f.mul_single_apply_aux fun _a _ => eq_mul_inv_iff_mul_eq.symm @[simp] theorem single_mul_apply (r : k) (x : G) (f : MonoidAlgebra k G) (y : G) : (single x r * f) y = r * f (x⁻¹ * y) := - f.single_mul_apply_aux fun _z => eq_inv_mul_iff_mul_eq.symm + f.single_mul_apply_aux fun _z _ => eq_inv_mul_iff_mul_eq.symm theorem mul_apply_left (f g : MonoidAlgebra k G) (x : G) : (f * g) x = f.sum fun a b => b * g (a⁻¹ * x) := @@ -1338,24 +1339,24 @@ theorem smul_single' (c : k) (a : G) (b : k) : c • single a b = single a (c * Finsupp.smul_single' c a b theorem mul_single_apply_aux [Add G] (f : k[G]) (r : k) (x y z : G) - (H : ∀ a, a + x = z ↔ a = y) : (f * single x r) z = f y * r := + (H : ∀ a ∈ f.support, a + x = z ↔ a = y) : (f * single x r) z = f y * r := @MonoidAlgebra.mul_single_apply_aux k (Multiplicative G) _ _ _ _ _ _ _ H theorem mul_single_zero_apply [AddZeroClass G] (f : k[G]) (r : k) (x : G) : (f * single (0 : G) r) x = f x * r := - f.mul_single_apply_aux r _ _ _ fun a => by rw [add_zero] + f.mul_single_apply_aux r _ _ _ fun a _ => by rw [add_zero] theorem mul_single_apply_of_not_exists_add [Add G] (r : k) {g g' : G} (x : k[G]) (h : ¬∃ d, g' = d + g) : (x * single g r) g' = 0 := @MonoidAlgebra.mul_single_apply_of_not_exists_mul k (Multiplicative G) _ _ _ _ _ _ h theorem single_mul_apply_aux [Add G] (f : k[G]) (r : k) (x y z : G) - (H : ∀ a, x + a = y ↔ a = z) : (single x r * f) y = r * f z := + (H : ∀ a ∈ f.support, x + a = y ↔ a = z) : (single x r * f) y = r * f z := @MonoidAlgebra.single_mul_apply_aux k (Multiplicative G) _ _ _ _ _ _ _ H theorem single_zero_mul_apply [AddZeroClass G] (f : k[G]) (r : k) (x : G) : (single (0 : G) r * f) x = r * f x := - f.single_mul_apply_aux r _ _ _ fun a => by rw [zero_add] + f.single_mul_apply_aux r _ _ _ fun a _ => by rw [zero_add] theorem single_mul_apply_of_not_exists_add [Add G] (r : k) {g g' : G} (x : k[G]) (h : ¬∃ d, g' = g + d) : (single g r * x) g' = 0 := diff --git a/Mathlib/Algebra/MonoidAlgebra/Division.lean b/Mathlib/Algebra/MonoidAlgebra/Division.lean index 7b63bd6d1bbd6..d5b413992f933 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Division.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Division.lean @@ -95,13 +95,13 @@ noncomputable def divOfHom : Multiplicative G →* AddMonoid.End k[G] where theorem of'_mul_divOf (a : G) (x : k[G]) : of' k G a * x /ᵒᶠ a = x := by refine Finsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): `ext` doesn't work rw [AddMonoidAlgebra.divOf_apply, of'_apply, single_mul_apply_aux, one_mul] - intro c + intro c hc exact add_right_inj _ theorem mul_of'_divOf (x : k[G]) (a : G) : x * of' k G a /ᵒᶠ a = x := by refine Finsupp.ext fun _ => ?_ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): `ext` doesn't work rw [AddMonoidAlgebra.divOf_apply, of'_apply, mul_single_apply_aux, mul_one] - intro c + intro c hc rw [add_comm] exact add_right_inj _ @@ -160,7 +160,7 @@ theorem divOf_add_modOf (x : k[G]) (g : G) : zero_add] · rw [modOf_apply_self_add, add_zero] rw [of'_apply, single_mul_apply_aux _ _ _, one_mul, divOf_apply] - intro a + intro a ha exact add_right_inj _ theorem modOf_add_divOf (x : k[G]) (g : G) : x %ᵒᶠ g + of' k G g * (x /ᵒᶠ g) = x := by diff --git a/Mathlib/Algebra/MvPolynomial/Basic.lean b/Mathlib/Algebra/MvPolynomial/Basic.lean index a9fe286b2e396..909b1eada5a2b 100644 --- a/Mathlib/Algebra/MvPolynomial/Basic.lean +++ b/Mathlib/Algebra/MvPolynomial/Basic.lean @@ -617,12 +617,12 @@ theorem coeff_mul [DecidableEq σ] (p q : MvPolynomial σ R) (n : σ →₀ ℕ) @[simp] theorem coeff_mul_monomial (m) (s : σ →₀ ℕ) (r : R) (p : MvPolynomial σ R) : coeff (m + s) (p * monomial s r) = coeff m p * r := - AddMonoidAlgebra.mul_single_apply_aux p _ _ _ _ fun _a => add_left_inj _ + AddMonoidAlgebra.mul_single_apply_aux p _ _ _ _ fun _a _ => add_left_inj _ @[simp] theorem coeff_monomial_mul (m) (s : σ →₀ ℕ) (r : R) (p : MvPolynomial σ R) : coeff (s + m) (monomial s r * p) = r * coeff m p := - AddMonoidAlgebra.single_mul_apply_aux p _ _ _ _ fun _a => add_right_inj _ + AddMonoidAlgebra.single_mul_apply_aux p _ _ _ _ fun _a _ => add_right_inj _ @[simp] theorem coeff_mul_X (m) (s : σ) (p : MvPolynomial σ R) : From 3dc2beffa4849b995f5bf41d58cf25a47ef9ed44 Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Wed, 22 Jan 2025 23:41:27 +0000 Subject: [PATCH 435/681] feat(Data/Nat): faster computation of Nat.log (#17325) Give an alternate definition `Nat.logC` for `Nat.log` which computes more efficiently (roughly speaking, this should have logarithmic time in the output, while `Nat.log` has linear time in its output). Prove that these two give the same output, and use `csimp` to ensure evaluation of `Nat.log` uses `Nat.logC` instead. Co-authored-by: Eric Wieser Co-authored-by: Matthew Ballard --- Mathlib/Data/Nat/Log.lean | 113 ++++++++++++++++++++++++++++++++++++++ MathlibTest/Nat/log.lean | 10 ++++ 2 files changed, 123 insertions(+) create mode 100644 MathlibTest/Nat/log.lean diff --git a/Mathlib/Data/Nat/Log.lean b/Mathlib/Data/Nat/Log.lean index b2e55d35fe599..2d4196b2fe33a 100644 --- a/Mathlib/Data/Nat/Log.lean +++ b/Mathlib/Data/Nat/Log.lean @@ -330,4 +330,117 @@ theorem log_le_clog (b n : ℕ) : log b n ≤ clog b n := by exact (Nat.pow_le_pow_iff_right hb).1 ((pow_log_le_self b n.succ_ne_zero).trans <| le_pow_clog hb _) +/-! ### Computating the logarithm efficiently -/ +section computation + +private lemma logC_aux {m b : ℕ} (hb : 1 < b) (hbm : b ≤ m) : m / (b * b) < m / b := by + have hb' : 0 < b := zero_lt_of_lt hb + rw [div_lt_iff_lt_mul (Nat.mul_pos hb' hb'), ← Nat.mul_assoc, ← div_lt_iff_lt_mul hb'] + exact (Nat.lt_mul_iff_one_lt_right (Nat.div_pos hbm hb')).2 hb + +-- This option is necessary because of lean4#2920 +set_option linter.unusedVariables false in +/-- +An alternate definition for `Nat.log` which computes more efficiently. For mathematical purposes, +use `Nat.log` instead, and see `Nat.log_eq_logC`. + +Note a tail-recursive version of `Nat.log` is also possible: +``` +def logTR (b n : ℕ) : ℕ := + let rec go : ℕ → ℕ → ℕ | n, acc => if h : b ≤ n ∧ 1 < b then go (n / b) (acc + 1) else acc + decreasing_by + have : n / b < n := Nat.div_lt_self (by omega) h.2 + decreasing_trivial + go n 0 +``` +but performs worse for large numbers than `Nat.logC`: +``` +#eval Nat.logTR 2 (2 ^ 1000000) +#eval Nat.logC 2 (2 ^ 1000000) +``` + +The definition `Nat.logC` is not tail-recursive, however, but the stack limit will only be reached +if the output size is around 2^10000, meaning the input will be around 2^(2^10000), which will +take far too long to compute in the first place. + +Adapted from https://downloads.haskell.org/~ghc/9.0.1/docs/html/libraries/ghc-bignum-1.0/GHC-Num-BigNat.html#v:bigNatLogBase-35- +-/ +@[pp_nodot] def logC (b m : ℕ) : ℕ := + if h : 1 < b then let (_, e) := step b h; e else 0 where + /-- + An auxiliary definition for `Nat.logC`, where the base of the logarithm is _squared_ in each + loop. This allows significantly faster computation of the logarithm: it takes logarithmic time + in the size of the output, rather than linear time. + -/ + step (pw : ℕ) (hpw : 1 < pw) : ℕ × ℕ := + if h : m < pw then (m, 0) + else + let (q, e) := step (pw * pw) (Nat.mul_lt_mul_of_lt_of_lt hpw hpw) + if q < pw then (q, 2 * e) else (q / pw, 2 * e + 1) + termination_by m / pw + decreasing_by + have : m / (pw * pw) < m / pw := logC_aux hpw (le_of_not_lt h) + decreasing_trivial + +private lemma logC_step {m pw q e : ℕ} (hpw : 1 < pw) (hqe : logC.step m pw hpw = (q, e)) : + pw ^ e * q ≤ m ∧ q < pw ∧ (m < pw ^ e * (q + 1)) ∧ (0 < m → 0 < q) := by + induction pw, hpw using logC.step.induct m generalizing q e with + | case1 pw hpw hmpw => + rw [logC.step, dif_pos hmpw] at hqe + cases hqe + simpa + | case2 pw hpw hmpw q' e' hqe' hqpw ih => + simp only [logC.step, dif_neg hmpw, hqe', if_pos hqpw] at hqe + cases hqe + rw [Nat.pow_mul, Nat.pow_two] + exact ⟨(ih hqe').1, hqpw, (ih hqe').2.2⟩ + | case3 pw hpw hmpw q' e' hqe' hqpw ih => + simp only [Nat.logC.step, dif_neg hmpw, hqe', if_neg hqpw] at hqe + cases hqe + rw [Nat.pow_succ, Nat.mul_assoc, Nat.pow_mul, Nat.pow_two, Nat.mul_assoc] + refine ⟨(ih hqe').1.trans' (Nat.mul_le_mul_left _ (Nat.mul_div_le _ _)), + Nat.div_lt_of_lt_mul (ih hqe').2.1, (ih hqe').2.2.1.trans_le ?_, + fun _ => Nat.div_pos (le_of_not_lt hqpw) (by omega)⟩ + exact Nat.mul_le_mul_left _ (Nat.lt_mul_div_succ _ (zero_lt_of_lt hpw)) + +private lemma logC_spec {b m : ℕ} (hb : 1 < b) (hm : 0 < m) : + b ^ logC b m ≤ m ∧ m < b ^ (logC b m + 1) := by + rw [logC, dif_pos hb] + split + next q e heq => + obtain ⟨h₁, h₂, h₃, h₄⟩ := logC_step hb heq + exact ⟨h₁.trans' (Nat.le_mul_of_pos_right _ (h₄ hm)), h₃.trans_le (Nat.mul_le_mul_left _ h₂)⟩ + +private lemma logC_of_left_le_one {b m : ℕ} (hb : b ≤ 1) : logC b m = 0 := by + rw [logC, dif_neg hb.not_lt] + +private lemma logC_zero {b : ℕ} : + logC b 0 = 0 := by + rcases le_or_lt b 1 with hb | hb + case inl => exact logC_of_left_le_one hb + case inr => + rw [logC, dif_pos hb] + split + next q e heq => + rw [logC.step, dif_pos (zero_lt_of_lt hb)] at heq + rw [(Prod.mk.inj heq).2] + +/-- +The result of `Nat.log` agrees with the result of `Nat.logC`. The latter will be computed more +efficiently, but the former is easier to prove things about and has more lemmas. +This lemma is tagged @[csimp] so that the code generated for `Nat.log` uses `Nat.logC` instead. +-/ +@[csimp] theorem log_eq_logC : log = logC := by + ext b m + rcases le_or_lt b 1 with hb | hb + case inl => rw [logC_of_left_le_one hb, Nat.log_of_left_le_one hb] + case inr => + rcases eq_or_ne m 0 with rfl | hm + case inl => rw [Nat.log_zero_right, logC_zero] + case inr => + rw [Nat.log_eq_iff (Or.inr ⟨hb, hm⟩)] + exact logC_spec hb (zero_lt_of_ne_zero hm) + +end computation + end Nat diff --git a/MathlibTest/Nat/log.lean b/MathlibTest/Nat/log.lean new file mode 100644 index 0000000000000..950bfa1034cb4 --- /dev/null +++ b/MathlibTest/Nat/log.lean @@ -0,0 +1,10 @@ +import Mathlib.Data.Nat.Log + +/-! +This used to fail (ran out of heartbeats) but with a new faster `Nat.logC` tagged `csimp`, it +succeeds. +-/ + +/-- info: 10000000 -/ +#guard_msgs in +#eval Nat.log 2 (2 ^ 10000000) From 404e2147573616efa9e1a54ce0808c2964a9312e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 23 Jan 2025 05:32:13 +0000 Subject: [PATCH 436/681] feat(Algebra/Homology/Embedding): homology of truncGE (#19572) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given an embedding `e` of complex shapes that satisfies `IsTruncGE`, we show that the morphism `K.πTruncGE e : K ⟶ K.truncGE e` induces a quasi-isomorphism in degree `e.f i` for all `i`. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- .../Homology/Embedding/ExtendHomology.lean | 9 ++ .../Homology/Embedding/TruncGEHomology.lean | 130 +++++++++++++++++- 2 files changed, 135 insertions(+), 4 deletions(-) diff --git a/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean b/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean index 5962382e8c31d..2d5d00e3d6d6f 100644 --- a/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean +++ b/Mathlib/Algebra/Homology/Embedding/ExtendHomology.lean @@ -241,6 +241,15 @@ noncomputable def rightHomologyData (h : (K.sc' i j k).RightHomologyData) : exact h.wι hι := isLimitKernelFork K e hj' hi hi' hk hk' _ h.hp _ h.hι +/-- Computation of the `g'` field of `extend.rightHomologyData`. -/ +lemma rightHomologyData_g' (h : (K.sc' i j k).RightHomologyData) (hk'' : e.f k = k') : + (rightHomologyData K e hj' hi hi' hk hk' h).g' = h.g' ≫ (K.extendXIso e hk'').inv := by + rw [← cancel_epi h.p, ← cancel_epi (extendXIso K e hj').hom] + have := (rightHomologyData K e hj' hi hi' hk hk' h).p_g' + dsimp at this + rw [assoc] at this + rw [this, K.extend_d_eq e hj' hk'', h.p_g'_assoc, shortComplexFunctor'_obj_g] + /-- The homology data of `(K.extend e).sc' i' j' k'` that is deduced from a homology data of `K.sc' i j k`. -/ @[simps] diff --git a/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean b/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean index fff53bfea4947..d39f0d57c6052 100644 --- a/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean +++ b/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean @@ -3,6 +3,7 @@ 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.Homology.Embedding.ExtendHomology import Mathlib.Algebra.Homology.Embedding.TruncGE import Mathlib.Algebra.Homology.Embedding.RestrictionHomology import Mathlib.Algebra.Homology.QuasiIso @@ -11,9 +12,11 @@ import Mathlib.Algebra.Homology.QuasiIso Given an embedding of complex shapes `e : Embedding c c'`, we shall relate the homology of `K : HomologicalComplex C c'` and of -`K.truncGE e : HomologicalComplex C c'` (TODO). +`K.truncGE e : HomologicalComplex C c'`. -So far, we only compute the homology of `K.truncGE' e : HomologicalComplex C c`. +The main result is that `K.πTruncGE e : K ⟶ K.truncGE e` induces a +quasi-isomorphism in degree `e.f i` for all `i`. (Note that the complex +`K.truncGE e` is exact in degrees that are not in the image of `e.f`.) -/ @@ -23,8 +26,8 @@ namespace HomologicalComplex variable {ι ι' : Type*} {c : ComplexShape ι} {c' : ComplexShape ι'} {C : Type*} [Category C] [HasZeroMorphisms C] - (K : HomologicalComplex C c') (e : c.Embedding c') [e.IsTruncGE] - [∀ i', K.HasHomology i'] + (K L : HomologicalComplex C c') (φ : K ⟶ L) (e : c.Embedding c') [e.IsTruncGE] + [∀ i', K.HasHomology i'] [∀ i', L.HasHomology i'] namespace truncGE' @@ -109,4 +112,123 @@ instance truncGE'_hasHomology (i : ι) : (K.truncGE' e).HasHomology i := by end truncGE' +variable [HasZeroObject C] + +namespace truncGE + +instance (i' : ι') : (K.truncGE e).HasHomology i' := by + dsimp [truncGE] + infer_instance + +/-- The right homology data which allows to show that `K.πTruncGE e` +induces an isomorphism in homology in degrees `j'` such that `e.f j = j'` for some `j`. -/ +@[simps] +noncomputable def rightHomologyMapData {i j k : ι} {j' : ι'} (hj' : e.f j = j') + (hi : c.prev j = i) (hk : c.next j = k) (hj : e.BoundaryGE j) : + ShortComplex.RightHomologyMapData ((shortComplexFunctor C c' j').map (K.πTruncGE e)) + (ShortComplex.RightHomologyData.canonical (K.sc j')) + (extend.rightHomologyData (K.truncGE' e) e hj' hi rfl hk rfl + (truncGE'.homologyData K e i j k hk hj' hj).right) where + φQ := (K.truncGE'XIsoOpcycles e hj' hj).inv + φH := 𝟙 _ + commp := by + change K.pOpcycles j' ≫ _ = _ + simp [truncGE'.homologyData, πTruncGE, e.liftExtend_f _ _ hj', + K.restrictionToTruncGE'_f_eq_iso_hom_pOpcycles_iso_inv e hj' hj] + commg' := by + have hk' : e.f k = c'.next j' := by rw [← hj', e.next_f hk] + dsimp + rw [extend.rightHomologyData_g' _ _ _ _ _ _ _ _ hk', πTruncGE, + e.liftExtend_f _ _ hk', truncGE'.homologyData_right_g'] + by_cases hjk : c.Rel j k + · simp [K.truncGE'_d_eq_fromOpcycles e hjk hj' hk' hj, + K.restrictionToTruncGE'_f_eq_iso_hom_iso_inv e hk' (e.not_boundaryGE_next hjk)] + rfl + · obtain rfl : k = j := by rw [← c.next_eq_self j (by simpa only [hk] using hjk), hk] + rw [shape _ _ _ hjk, zero_comp, comp_zero, + K.restrictionToTruncGE'_f_eq_iso_hom_pOpcycles_iso_inv e hk' hj] + simp only [restriction_X, restrictionXIso, eqToIso.inv, eqToIso.hom, assoc, + eqToHom_trans_assoc, eqToHom_refl, id_comp] + change 0 = K.fromOpcycles _ _ ≫ _ + rw [← cancel_epi (K.pOpcycles _), comp_zero, p_fromOpcycles_assoc, + d_pOpcycles_assoc, zero_comp] + +end truncGE + +lemma quasiIsoAt_πTruncGE {j : ι} {j' : ι'} (hj' : e.f j = j') : + QuasiIsoAt (K.πTruncGE e) j' := by + rw [quasiIsoAt_iff] + by_cases hj : e.BoundaryGE j + · rw [(truncGE.rightHomologyMapData K e hj' rfl rfl hj).quasiIso_iff] + dsimp + infer_instance + · let φ := (shortComplexFunctor C c' j').map (K.πTruncGE e) + have : Epi φ.τ₁ := by + by_cases hi : ∃ i, e.f i = c'.prev j' + · obtain ⟨i, hi⟩ := hi + dsimp [φ, πTruncGE] + rw [e.epi_liftExtend_f_iff _ _ hi] + infer_instance + · apply IsZero.epi (isZero_extend_X _ _ _ (by simpa using hi)) + have : IsIso φ.τ₂ := by + dsimp [φ, πTruncGE] + rw [e.isIso_liftExtend_f_iff _ _ hj'] + exact K.isIso_restrictionToTruncGE' e j hj + have : IsIso φ.τ₃ := by + dsimp [φ, πTruncGE] + have : c'.next j' = e.f (c.next j) := by simpa only [← hj'] using e.next_f rfl + rw [e.isIso_liftExtend_f_iff _ _ this.symm] + exact K.isIso_restrictionToTruncGE' e _ (e.not_boundaryGE_next' hj rfl) + exact ShortComplex.quasiIso_of_epi_of_isIso_of_mono φ + +instance (i : ι) : QuasiIsoAt (K.πTruncGE e) (e.f i) := K.quasiIsoAt_πTruncGE e rfl + +lemma quasiIso_πTruncGE_iff_isSupported : + QuasiIso (K.πTruncGE e) ↔ K.IsSupported e := by + constructor + · intro + refine ⟨fun i' hi' => ?_⟩ + rw [exactAt_iff_of_quasiIsoAt (K.πTruncGE e) i'] + exact (K.truncGE e).exactAt_of_isSupported e i' hi' + · intro + rw [quasiIso_iff] + intro i' + by_cases hi' : ∃ i, e.f i = i' + · obtain ⟨i, rfl⟩ := hi' + infer_instance + · rw [quasiIsoAt_iff_exactAt (K.πTruncGE e) i'] + all_goals exact exactAt_of_isSupported _ e i' (by simpa using hi') + +lemma acyclic_truncGE_iff_isSupportedOutside : + (K.truncGE e).Acyclic ↔ K.IsSupportedOutside e := by + constructor + · intro hK + exact ⟨fun i => + by simpa only [exactAt_iff_of_quasiIsoAt (K.πTruncGE e)] using hK (e.f i)⟩ + · intro hK i' + by_cases hi' : ∃ i, e.f i = i' + · obtain ⟨i, rfl⟩ := hi' + simpa only [← exactAt_iff_of_quasiIsoAt (K.πTruncGE e)] using hK.exactAt i + · exact exactAt_of_isSupported _ e i' (by simpa using hi') + +variable {K L} + +lemma quasiIso_truncGEMap_iff : + QuasiIso (truncGEMap φ e) ↔ ∀ (i : ι) (i' : ι') (_ : e.f i = i'), QuasiIsoAt φ i' := by + have : ∀ (i : ι) (i' : ι') (_ : e.f i = i'), + QuasiIsoAt (truncGEMap φ e) i' ↔ QuasiIsoAt φ i' := by + rintro i _ rfl + rw [← quasiIsoAt_iff_comp_left (K.πTruncGE e), πTruncGE_naturality φ e, + quasiIsoAt_iff_comp_right] + rw [quasiIso_iff] + constructor + · intro h i i' hi + simpa only [← this i i' hi] using h i' + · intro h i' + by_cases hi' : ∃ i, e.f i = i' + · obtain ⟨i, hi⟩ := hi' + simpa only [this i i' hi] using h i i' hi + · rw [quasiIsoAt_iff_exactAt] + all_goals exact exactAt_of_isSupported _ e i' (by simpa using hi') + end HomologicalComplex From ce9c3fe64e4fb0c625b03cd7b3028fab5016faa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 23 Jan 2025 05:40:12 +0000 Subject: [PATCH 437/681] feat(Algebra/Homology/Embedding): canonical truncations on `CochainComplex` (#19578) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We apply the basic `Algebra.Homology.Embedding` definitions to the particular case of cochain complexes indexed by the integers. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Algebra/Homology/Embedding/Basic.lean | 25 ++ .../Homology/Embedding/CochainComplex.lean | 224 ++++++++++++++++++ .../ShortComplex/HomologicalComplex.lean | 5 + 4 files changed, 255 insertions(+) create mode 100644 Mathlib/Algebra/Homology/Embedding/CochainComplex.lean diff --git a/Mathlib.lean b/Mathlib.lean index cef32928284c7..83f92190f7d18 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -433,6 +433,7 @@ import Mathlib.Algebra.Homology.DerivedCategory.SingleTriangle import Mathlib.Algebra.Homology.DifferentialObject import Mathlib.Algebra.Homology.Embedding.Basic import Mathlib.Algebra.Homology.Embedding.Boundary +import Mathlib.Algebra.Homology.Embedding.CochainComplex import Mathlib.Algebra.Homology.Embedding.Extend import Mathlib.Algebra.Homology.Embedding.ExtendHomology import Mathlib.Algebra.Homology.Embedding.HomEquiv diff --git a/Mathlib/Algebra/Homology/Embedding/Basic.lean b/Mathlib/Algebra/Homology/Embedding/Basic.lean index 00176a4d60d8d..828c12d3950a3 100644 --- a/Mathlib/Algebra/Homology/Embedding/Basic.lean +++ b/Mathlib/Algebra/Homology/Embedding/Basic.lean @@ -6,6 +6,7 @@ Authors: Joël Riou import Mathlib.Algebra.Homology.ComplexShape import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Algebra.Ring.Nat +import Mathlib.Tactic.ByContra /-! # Embeddings of complex shapes @@ -213,4 +214,28 @@ instance : (embeddingUpIntLE p).IsRelIff := by dsimp [embeddingUpIntLE]; infer_i instance : (embeddingUpIntLE p).IsTruncLE where mem_prev {_ k} h := ⟨k + 1, by dsimp at h ⊢; omega⟩ +lemma not_mem_range_embeddingUpIntLE_iff (n : ℤ) : + (∀ (i : ℕ), (embeddingUpIntLE p).f i ≠ n) ↔ p < n := by + constructor + · intro h + by_contra! + simp only [Int.not_lt] at this + obtain ⟨k, rfl⟩ := Int.le.dest this + exact (h k) (by simp) + · intros + dsimp + omega + +lemma not_mem_range_embeddingUpIntGE_iff (n : ℤ) : + (∀ (i : ℕ), (embeddingUpIntGE p).f i ≠ n) ↔ n < p := by + constructor + · intro h + by_contra! + simp only [Int.not_lt] at this + obtain ⟨k, rfl⟩ := Int.le.dest this + exact (h k) (by simp) + · intros + dsimp + omega + end ComplexShape diff --git a/Mathlib/Algebra/Homology/Embedding/CochainComplex.lean b/Mathlib/Algebra/Homology/Embedding/CochainComplex.lean new file mode 100644 index 0000000000000..54fe12e166c96 --- /dev/null +++ b/Mathlib/Algebra/Homology/Embedding/CochainComplex.lean @@ -0,0 +1,224 @@ +/- +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.Homology.Embedding.TruncLE + +/-! +# Truncations on cochain complexes indexed by the integers. + +In this file, we introduce abbreviations for the canonical truncations +`CochainComplex.truncLE`, `CochainComplex.truncGE` of cochain +complexes indexed by `ℤ`, as well as the conditions +`CochainComplex.IsStrictlyLE`, `CochainComplex.IsStrictlyGE`, +`CochainComplex.IsLE`, and `CochainComplex.IsGE`. + +-/ + +open CategoryTheory Category Limits ComplexShape ZeroObject + +namespace CochainComplex + +variable {C : Type*} [Category C] + +open HomologicalComplex + +section HasZeroMorphisms + +variable [HasZeroMorphisms C] (K L : CochainComplex C ℤ) (φ : K ⟶ L) (e : K ≅ L) + +section + +variable [HasZeroObject C] [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] + +/-- If `K : CochainComplex C ℤ`, this is the canonical truncation `≤ n` of `K`. -/ +noncomputable abbrev truncLE (n : ℤ) : CochainComplex C ℤ := + HomologicalComplex.truncLE K (embeddingUpIntLE n) + +/-- If `K : CochainComplex C ℤ`, this is the canonical truncation `≥ n` of `K`. -/ +noncomputable abbrev truncGE (n : ℤ) : CochainComplex C ℤ := + HomologicalComplex.truncGE K (embeddingUpIntGE n) + +/-- The canonical map `K.truncLE n ⟶ K` for `K : CochainComplex C ℤ`. -/ +noncomputable def ιTruncLE (n : ℤ) : K.truncLE n ⟶ K := + HomologicalComplex.ιTruncLE K (embeddingUpIntLE n) + +/-- The canonical map `K ⟶ K.truncGE n` for `K : CochainComplex C ℤ`. -/ +noncomputable def πTruncGE (n : ℤ) : K ⟶ K.truncGE n := + HomologicalComplex.πTruncGE K (embeddingUpIntGE n) + +section + +variable {K L} + +/-- The morphism `K.truncLE n ⟶ L.truncLE n` induced by a morphism `K ⟶ L`. -/ +noncomputable abbrev truncLEMap (n : ℤ) : K.truncLE n ⟶ L.truncLE n := + HomologicalComplex.truncLEMap φ (embeddingUpIntLE n) + +/-- The morphism `K.truncGE n ⟶ L.truncGE n` induced by a morphism `K ⟶ L`. -/ +noncomputable abbrev truncGEMap (n : ℤ) : K.truncGE n ⟶ L.truncGE n := + HomologicalComplex.truncGEMap φ (embeddingUpIntGE n) + +@[reassoc (attr := simp)] +lemma ιTruncLE_naturality (n : ℤ) : + truncLEMap φ n ≫ L.ιTruncLE n = K.ιTruncLE n ≫ φ := by + apply HomologicalComplex.ιTruncLE_naturality + +@[reassoc (attr := simp)] +lemma πTruncGE_naturality (n : ℤ) : + K.πTruncGE n ≫ truncGEMap φ n = φ ≫ L.πTruncGE n := by + apply HomologicalComplex.πTruncGE_naturality + +end + +end + +/-- The condition that a cochain complex `K` is strictly `≤ n`. -/ +abbrev IsStrictlyGE (n : ℤ) := K.IsStrictlySupported (embeddingUpIntGE n) + +/-- The condition that a cochain complex `K` is strictly `≥ n`. -/ +abbrev IsStrictlyLE (n : ℤ) := K.IsStrictlySupported (embeddingUpIntLE n) + +/-- The condition that a cochain complex `K` is (cohomologically) `≤ n`. -/ +abbrev IsGE (n : ℤ) := K.IsSupported (embeddingUpIntGE n) + +/-- The condition that a cochain complex `K` is (cohomologically) `≥ n`. -/ +abbrev IsLE (n : ℤ) := K.IsSupported (embeddingUpIntLE n) + +lemma isZero_of_isStrictlyGE (n i : ℤ) (hi : i < n) [K.IsStrictlyGE n] : + IsZero (K.X i) := + isZero_X_of_isStrictlySupported K (embeddingUpIntGE n) i + (by simpa only [not_mem_range_embeddingUpIntGE_iff] using hi) + +lemma isZero_of_isStrictlyLE (n i : ℤ) (hi : n < i) [K.IsStrictlyLE n] : + IsZero (K.X i) := + isZero_X_of_isStrictlySupported K (embeddingUpIntLE n) i + (by simpa only [not_mem_range_embeddingUpIntLE_iff] using hi) + +lemma exactAt_of_isGE (n i : ℤ) (hi : i < n) [K.IsGE n] : + K.ExactAt i := + exactAt_of_isSupported K (embeddingUpIntGE n) i + (by simpa only [not_mem_range_embeddingUpIntGE_iff] using hi) + +lemma exactAt_of_isLE (n i : ℤ) (hi : n < i) [K.IsLE n] : + K.ExactAt i := + exactAt_of_isSupported K (embeddingUpIntLE n) i + (by simpa only [not_mem_range_embeddingUpIntLE_iff] using hi) + +lemma isZero_of_isGE (n i : ℤ) (hi : i < n) [K.IsGE n] [K.HasHomology i] : + IsZero (K.homology i) := + (K.exactAt_of_isGE n i hi).isZero_homology + +lemma isZero_of_isLE (n i : ℤ) (hi : n < i) [K.IsLE n] [K.HasHomology i] : + IsZero (K.homology i) := + (K.exactAt_of_isLE n i hi).isZero_homology + +lemma isStrictlyGE_iff (n : ℤ) : + K.IsStrictlyGE n ↔ ∀ (i : ℤ) (_ : i < n), IsZero (K.X i) := by + constructor + · intro _ i hi + exact K.isZero_of_isStrictlyGE n i hi + · intro h + refine IsStrictlySupported.mk (fun i hi ↦ ?_) + rw [not_mem_range_embeddingUpIntGE_iff] at hi + exact h i hi + +lemma isStrictlyLE_iff (n : ℤ) : + K.IsStrictlyLE n ↔ ∀ (i : ℤ) (_ : n < i), IsZero (K.X i) := by + constructor + · intro _ i hi + exact K.isZero_of_isStrictlyLE n i hi + · intro h + refine IsStrictlySupported.mk (fun i hi ↦ ?_) + rw [not_mem_range_embeddingUpIntLE_iff] at hi + exact h i hi + +lemma isGE_iff (n : ℤ) : + K.IsGE n ↔ ∀ (i : ℤ) (_ : i < n), K.ExactAt i := by + constructor + · intro _ i hi + exact K.exactAt_of_isGE n i hi + · intro h + refine IsSupported.mk (fun i hi ↦ ?_) + rw [not_mem_range_embeddingUpIntGE_iff] at hi + exact h i hi + +lemma isLE_iff (n : ℤ) : + K.IsLE n ↔ ∀ (i : ℤ) (_ : n < i), K.ExactAt i := by + constructor + · intro _ i hi + exact K.exactAt_of_isLE n i hi + · intro h + refine IsSupported.mk (fun i hi ↦ ?_) + rw [not_mem_range_embeddingUpIntLE_iff] at hi + exact h i hi + +lemma isStrictlyLE_of_le (p q : ℤ) (hpq : p ≤ q) [K.IsStrictlyLE p] : + K.IsStrictlyLE q := by + rw [isStrictlyLE_iff] + intro i hi + apply K.isZero_of_isStrictlyLE p + omega + +lemma isStrictlyGE_of_ge (p q : ℤ) (hpq : p ≤ q) [K.IsStrictlyGE q] : + K.IsStrictlyGE p := by + rw [isStrictlyGE_iff] + intro i hi + apply K.isZero_of_isStrictlyGE q + omega + +lemma isLE_of_le (p q : ℤ) (hpq : p ≤ q) [K.IsLE p] : + K.IsLE q := by + rw [isLE_iff] + intro i hi + apply K.exactAt_of_isLE p + omega + +lemma isGE_of_ge (p q : ℤ) (hpq : p ≤ q) [K.IsGE q] : + K.IsGE p := by + rw [isGE_iff] + intro i hi + apply K.exactAt_of_isGE q + omega + +section + +variable {K L} + +include e + +lemma isStrictlyLE_of_iso (n : ℤ) [K.IsStrictlyLE n] : L.IsStrictlyLE n := by + apply isStrictlySupported_of_iso e + +lemma isStrictlyGE_of_iso (n : ℤ) [K.IsStrictlyGE n] : L.IsStrictlyGE n := by + apply isStrictlySupported_of_iso e + +lemma isLE_of_iso (n : ℤ) [K.IsLE n] : L.IsLE n := by + apply isSupported_of_iso e + +lemma isGE_of_iso (n : ℤ) [K.IsGE n] : L.IsGE n := by + apply isSupported_of_iso e + +end + +/-- A cochain complex that is both strictly `≤ n` and `≥ n` is isomorphic to +a complex `(single _ _ n).obj M` for some object `M`. -/ +lemma exists_iso_single [HasZeroObject C] (n : ℤ) [K.IsStrictlyGE n] [K.IsStrictlyLE n] : + ∃ (M : C), Nonempty (K ≅ (single _ _ n).obj M) := + ⟨K.X n, ⟨{ + hom := mkHomToSingle (𝟙 _) (fun i (hi : i + 1 = n) ↦ + (K.isZero_of_isStrictlyGE n i (by omega)).eq_of_src _ _) + inv := mkHomFromSingle (𝟙 _) (fun i (hi : n + 1 = i) ↦ + (K.isZero_of_isStrictlyLE n i (by omega)).eq_of_tgt _ _) + hom_inv_id := by + ext i + obtain hi | rfl | hi := lt_trichotomy i n + · apply (K.isZero_of_isStrictlyGE n i (by omega)).eq_of_src + · simp + · apply (K.isZero_of_isStrictlyLE n i (by omega)).eq_of_tgt + inv_hom_id := by aesop }⟩⟩ + +end HasZeroMorphisms + +end CochainComplex diff --git a/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean b/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean index b906d28288a6e..6f0f54b5b2b70 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/HomologicalComplex.lean @@ -614,6 +614,11 @@ lemma exactAt_iff_isZero_homology [K.HasHomology i] : dsimp [homology] rw [exactAt_iff, ShortComplex.exact_iff_isZero_homology] +variable {K i} in +lemma ExactAt.isZero_homology [K.HasHomology i] (h : K.ExactAt i) : + IsZero (K.homology i) := by + rwa [← exactAt_iff_isZero_homology] + /-- A homological complex `K` is acyclic if it is exact at `i` for any `i`. -/ def Acyclic := ∀ i, K.ExactAt i From 9c2a4e8ecb8f64916868e3d08d4800640d6f91d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 23 Jan 2025 06:28:46 +0000 Subject: [PATCH 438/681] =?UTF-8?q?feat(CategoryTheory):=20`=CE=BA`-filter?= =?UTF-8?q?ed=20categories=20(#20005)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If `κ` is a regular cardinal, we introduce the notion of `κ`-filtered category `J`: it means that any functor `A ⥤ J` from a small category such that `Arrow A` is of cardinality `< κ` admits a cocone. This generalizes the notion of filtered category. Indeed, we obtain the equivalence `IsCardinalFiltered J ℵ₀ ↔ IsFiltered J`. The API is mostly parallel to that of filtered categories. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/CategoryTheory/EssentiallySmall.lean | 4 + .../Limits/Shapes/WideEqualizers.lean | 16 ++ .../Presentable/IsCardinalFiltered.lean | 163 ++++++++++++++++++ Mathlib/SetTheory/Cardinal/Cofinality.lean | 3 + Mathlib/SetTheory/Cardinal/HasCardinalLT.lean | 14 +- 6 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean diff --git a/Mathlib.lean b/Mathlib.lean index 83f92190f7d18..53a8e9b57816a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2135,6 +2135,7 @@ import Mathlib.CategoryTheory.Preadditive.Yoneda.Basic import Mathlib.CategoryTheory.Preadditive.Yoneda.Injective import Mathlib.CategoryTheory.Preadditive.Yoneda.Limits import Mathlib.CategoryTheory.Preadditive.Yoneda.Projective +import Mathlib.CategoryTheory.Presentable.IsCardinalFiltered import Mathlib.CategoryTheory.Products.Associator import Mathlib.CategoryTheory.Products.Basic import Mathlib.CategoryTheory.Products.Bifunctor diff --git a/Mathlib/CategoryTheory/EssentiallySmall.lean b/Mathlib/CategoryTheory/EssentiallySmall.lean index 1e97be181bd34..1f2d4856e72bb 100644 --- a/Mathlib/CategoryTheory/EssentiallySmall.lean +++ b/Mathlib/CategoryTheory/EssentiallySmall.lean @@ -190,6 +190,10 @@ noncomputable instance [Small.{w} C] : Category.{v} (Shrink.{w} C) := noncomputable def equivalence [Small.{w} C] : C ≌ Shrink.{w} C := (Equivalence.induced _).symm +instance [Small.{w'} C] [LocallySmall.{w} C] : + LocallySmall.{w} (Shrink.{w'} C) := + locallySmall_of_faithful.{w} (equivalence.{w'} C).inverse + end Shrink /-- A category is essentially small if and only if diff --git a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean index 0e246bf283173..349e66c0e30f5 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean @@ -103,6 +103,22 @@ theorem WalkingParallelFamily.hom_id (X : WalkingParallelFamily J) : WalkingParallelFamily.Hom.id X = 𝟙 X := rfl +variable (J) in +/-- `Arrow (WalkingParallelFamily J)` identifies to the type obtained +by adding two elements to `T`. -/ +def WalkingParallelFamily.arrowEquiv : + Arrow (WalkingParallelFamily J) ≃ Option (Option J) where + toFun f := match f.left, f.right, f.hom with + | zero, _, .id _ => none + | one, _, .id _ => some none + | zero, one, .line t => some (some t) + invFun x := match x with + | none => Arrow.mk (𝟙 zero) + | some none => Arrow.mk (𝟙 one) + | some (some t) => Arrow.mk (.line t) + left_inv := by rintro ⟨(_ | _), _, (_ | _)⟩ <;> rfl + right_inv := by rintro (_ | (_ | _)) <;> rfl + variable {C : Type u} [Category.{v} C] variable {X Y : C} (f : J → (X ⟶ Y)) diff --git a/Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean b/Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean new file mode 100644 index 0000000000000..4898f232f020f --- /dev/null +++ b/Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean @@ -0,0 +1,163 @@ +/- +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.CategoryTheory.Filtered.Basic +import Mathlib.CategoryTheory.Limits.Shapes.WideEqualizers +import Mathlib.CategoryTheory.Comma.CardinalArrow +import Mathlib.SetTheory.Cardinal.Cofinality +import Mathlib.SetTheory.Cardinal.HasCardinalLT +import Mathlib.SetTheory.Cardinal.Arithmetic + +/-! # κ-filtered category + +If `κ` is a regular cardinal, we introduce the notion of `κ`-filtered +category `J`: it means that any functor `A ⥤ J` from a small category such +that `Arrow A` is of cardinality `< κ` admits a cocone. +This generalizes the notion of filtered category. +Indeed, we obtain the equivalence `IsCardinalFiltered J ℵ₀ ↔ IsFiltered J`. +The API is mostly parallel to that of filtered categories. + +A preordered type `J` is a `κ`-filtered category (i.e. `κ`-directed set) +if any subset of `J` of cardinality `< κ` has an upper bound. + +## References +* [Adámek, J. and Rosický, J., *Locally presentable and accessible categories*][Adamek_Rosicky_1994] + +-/ + +universe w v' v u' u + +namespace CategoryTheory + +open Limits Opposite + +/-- A category `J` is `κ`-filtered (for a regular cardinal `κ`) if +any functor `F : A ⥤ J` from a category `A` such that `HasCardinalLT (Arrow A) κ` +admits a cocone. -/ +class IsCardinalFiltered (J : Type u) [Category.{v} J] + (κ : Cardinal.{w}) [Fact κ.IsRegular] : Prop where + nonempty_cocone {A : Type w} [SmallCategory A] (F : A ⥤ J) + (hA : HasCardinalLT (Arrow A) κ) : Nonempty (Cocone F) + +lemma hasCardinalLT_arrow_walkingParallelFamily {T : Type u} + {κ : Cardinal.{w}} (hT : HasCardinalLT T κ) (hκ : Cardinal.aleph0 ≤ κ) : + HasCardinalLT (Arrow (WalkingParallelFamily T)) κ := by + simpa only [hasCardinalLT_iff_of_equiv (WalkingParallelFamily.arrowEquiv T), + hasCardinalLT_option_iff _ _ hκ] using hT + +namespace IsCardinalFiltered + +variable {J : Type u} [Category.{v} J] {κ : Cardinal.{w}} [hκ : Fact κ.IsRegular] + [IsCardinalFiltered J κ] + +/-- A choice of cocone for a functor `F : A ⥤ J` such that `HasCardinatLT (Arrow A) κ` +when `J` is a `κ`-filtered category, and `Arrow A` has cardinality `< κ`. -/ +noncomputable def cocone {A : Type v'} [Category.{u'} A] + (F : A ⥤ J) (hA : HasCardinalLT (Arrow A) κ) : + Cocone F := by + have := hA.small + have := small_of_small_arrow.{w} A + have := locallySmall_of_small_arrow.{w} A + let e := (Shrink.equivalence.{w} A).trans (ShrinkHoms.equivalence.{w} (Shrink.{w} A)) + exact (Cocones.equivalenceOfReindexing e.symm (Iso.refl _)).inverse.obj + (nonempty_cocone (κ := κ) (e.inverse ⋙ F) (by simpa)).some + +variable (J) in +lemma of_le {κ' : Cardinal.{w}} [Fact κ'.IsRegular] (h : κ' ≤ κ) : + IsCardinalFiltered J κ' where + nonempty_cocone F hA := ⟨cocone F (hA.of_le h)⟩ + +section max + +variable {K : Type u'} (S : K → J) (hS : HasCardinalLT K κ) + +/-- If `S : K → J` is a family of objects of cardinality `< κ` in a `κ`-filtered category, +this is a choice of objects in `J` which is the target of a map from any of +the objects `S k`. -/ +noncomputable def max : J := + (cocone (Discrete.functor S) (by simpa using hS)).pt + +/-- If `S : K → J` is a family of objects of cardinality `< κ` in a `κ`-filtered category, +this is a choice of map `S k ⟶ max S hS` for any `k : K`. -/ +noncomputable def toMax (k : K) : + S k ⟶ max S hS := + (cocone (Discrete.functor S) (by simpa using hS)).ι.app ⟨k⟩ + +end max + +section coeq + +variable {K : Type v'} {j j' : J} (f : K → (j ⟶ j')) (hK : HasCardinalLT K κ) + +/-- Given a family of maps `f : K → (j ⟶ j')` in a `κ`-filtered category `J`, +with `HasCardinalLT K κ`, this is an object of `J` where these morphisms +shall be equalized. -/ +noncomputable def coeq : J := + (cocone (parallelFamily f) + (hasCardinalLT_arrow_walkingParallelFamily hK hκ.out.aleph0_le)).pt + +/-- Given a family of maps `f : K → (j ⟶ j')` in a `κ`-filtered category `J`, +with `HasCardinalLT K κ`, and `k : K`, this is a choice of morphism `j' ⟶ coeq f hK`. -/ +noncomputable def coeqHom : j' ⟶ coeq f hK := + (cocone (parallelFamily f) + (hasCardinalLT_arrow_walkingParallelFamily hK hκ.out.aleph0_le)).ι.app .one + +/-- Given a family of maps `f : K → (j ⟶ j')` in a `κ`-filtered category `J`, +with `HasCardinalLT K κ`, this is a morphism `j ⟶ coeq f hK` which is equal +to all compositions `f k ≫ coeqHom f hK` for `k : K`. -/ +noncomputable def toCoeq : j ⟶ coeq f hK := + (cocone (parallelFamily f) + (hasCardinalLT_arrow_walkingParallelFamily hK hκ.out.aleph0_le)).ι.app .zero + +@[reassoc] +lemma coeq_condition (k : K) : f k ≫ coeqHom f hK = toCoeq f hK := + (cocone (parallelFamily f) + (hasCardinalLT_arrow_walkingParallelFamily hK hκ.out.aleph0_le)).w + (.line k) + +end coeq + +end IsCardinalFiltered + +open IsCardinalFiltered in +lemma isFiltered_of_isCardinalDirected (J : Type u) [Category.{v} J] + (κ : Cardinal.{w}) [hκ : Fact κ.IsRegular] [IsCardinalFiltered J κ] : + IsFiltered J := by + rw [IsFiltered.iff_cocone_nonempty.{w}] + intro A _ _ F + have hA : HasCardinalLT (Arrow A) κ := by + refine HasCardinalLT.of_le ?_ hκ.out.aleph0_le + simp only [hasCardinalLT_aleph0_iff] + infer_instance + exact ⟨cocone F hA⟩ + +attribute [local instance] Cardinal.fact_isRegular_aleph0 + +lemma isCardinalFiltered_aleph0_iff (J : Type u) [Category.{v} J] : + IsCardinalFiltered J Cardinal.aleph0.{w} ↔ IsFiltered J := by + constructor + · intro + exact isFiltered_of_isCardinalDirected J Cardinal.aleph0 + · intro + constructor + intro A _ F hA + rw [hasCardinalLT_aleph0_iff] at hA + have := ((Arrow.finite_iff A).1 hA).some + exact ⟨IsFiltered.cocone F⟩ + +lemma isCardinalFiltered_preorder (J : Type w) [Preorder J] + (κ : Cardinal.{w}) [Fact κ.IsRegular] + (h : ∀ ⦃K : Type w⦄ (s : K → J) (_ : Cardinal.mk K < κ), + ∃ (j : J), ∀ (k : K), s k ≤ j) : + IsCardinalFiltered J κ where + nonempty_cocone {A _ F hA} := by + obtain ⟨j, hj⟩ := h F.obj (by simpa only [hasCardinalLT_iff_cardinal_mk_lt] using + hasCardinalLT_of_hasCardinalLT_arrow hA) + exact ⟨Cocone.mk j + { app a := homOfLE (hj a) + naturality _ _ _ := rfl }⟩ + +end CategoryTheory diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index 7d7201ca375ba..809f5a5ecbdc4 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.lean @@ -922,6 +922,9 @@ theorem isRegular_cof {o : Ordinal} (h : o.IsLimit) : IsRegular o.cof := theorem isRegular_aleph0 : IsRegular ℵ₀ := ⟨le_rfl, by simp⟩ +lemma fact_isRegular_aleph0 : Fact Cardinal.aleph0.IsRegular where + out := Cardinal.isRegular_aleph0 + theorem isRegular_succ {c : Cardinal.{u}} (h : ℵ₀ ≤ c) : IsRegular (succ c) := ⟨h.trans (le_succ c), succ_le_of_lt diff --git a/Mathlib/SetTheory/Cardinal/HasCardinalLT.lean b/Mathlib/SetTheory/Cardinal/HasCardinalLT.lean index b14bed334c1f0..2f920d70d1b02 100644 --- a/Mathlib/SetTheory/Cardinal/HasCardinalLT.lean +++ b/Mathlib/SetTheory/Cardinal/HasCardinalLT.lean @@ -3,7 +3,7 @@ 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.SetTheory.Ordinal.Basic +import Mathlib.SetTheory.Cardinal.Arithmetic /-! # The property of being of cardinality less than a cardinal @@ -74,3 +74,15 @@ lemma hasCardinalLT_iff_of_equiv {X : Type u} {Y : Type u'} (e : X ≃ Y) (κ : lemma hasCardinalLT_aleph0_iff (X : Type u) : HasCardinalLT X Cardinal.aleph0.{v} ↔ Finite X := by simpa [HasCardinalLT] using Cardinal.mk_lt_aleph0_iff + +lemma hasCardinalLT_option_iff (X : Type u) (κ : Cardinal.{w}) + (hκ : Cardinal.aleph0 ≤ κ) : + HasCardinalLT (Option X) κ ↔ HasCardinalLT X κ := by + constructor + · intro h + exact h.of_injective _ (Option.some_injective _) + · intro h + dsimp [HasCardinalLT] at h ⊢ + simp only [Cardinal.mk_option, Cardinal.lift_add, Cardinal.lift_one] + exact Cardinal.add_lt_of_lt (by simpa using hκ) h + (lt_of_lt_of_le Cardinal.one_lt_aleph0 (by simpa using hκ)) From 866657b4bbe8cebc4de364aa59ec84a5741520d0 Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 23 Jan 2025 06:28:47 +0000 Subject: [PATCH 439/681] fix: add `#import_bumps` to set the correct options for the minImports linter (#20755) This fixes an issue [reported on Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/.60set_option.20linter.2EminImports.60.20completely.20broken.3F): asynchronous parsing of files derails completely the mechanism that the `minImports` linter uses to track import bumps. This PR introduces an `#import_bumps` command that is a simple macro to set both the `minImports` linter option to `true` and the `Elab.sync` option to `false`. As further housekeeping, simply using ```lean set_option linter.minImports true ``` triggers a message informing to use `#import_bumps` instead (but the option still gets set), and using ```lean #import_bumps ``` also emits a message, so that the `#`-command linter will not flag it, but the command will still get picked up by CI, in case it stays in final code. --- Mathlib/Tactic/Linter/MinImports.lean | 18 +++++++++++++++++- MathlibTest/MinImports.lean | 7 ++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Mathlib/Tactic/Linter/MinImports.lean b/Mathlib/Tactic/Linter/MinImports.lean index 0aad206e77cf8..9f72cfba03c25 100644 --- a/Mathlib/Tactic/Linter/MinImports.lean +++ b/Mathlib/Tactic/Linter/MinImports.lean @@ -61,6 +61,10 @@ Unlike the related `#min_imports` command, the linter takes into account notatio information. It also works incrementally, providing information that is better suited, for instance, to split files. + +Another important difference is that the `minImports` *linter* starts counting imports from +where the option is set to `true` *downwards*, whereas the `#min_imports` *command* looks at the +imports needed from the command *upwards*. -/ register_option linter.minImports : Bool := { defValue := false @@ -87,13 +91,25 @@ It returns the modules that are transitively imported by `ms`, using the data in def importsBelow (tc : NameMap NameSet) (ms : NameSet) : NameSet := ms.fold (·.append <| tc.findD · default) ms +@[inherit_doc Mathlib.Linter.linter.minImports] +macro "#import_bumps" : command => `( + -- We emit a message to prevent the `#`-command linter from flagging `#import_bumps`. + run_cmd logInfo "Counting imports from here." + set_option Elab.async false + set_option linter.minImports true) + @[inherit_doc Mathlib.Linter.linter.minImports] def minImportsLinter : Linter where run := withSetOptionIn fun stx ↦ do unless Linter.getLinterValue linter.minImports (← getOptions) do return if (← get).messages.hasErrors then return - if stx == (← `(command| set_option $(mkIdent `linter.minImports) true)) then return + if stx == (← `(command| #import_bumps)) then return + if stx == (← `(command| set_option $(mkIdent `linter.minImports) true)) then + logInfo "Try using '#import_bumps', instead of manually setting the linter option: \ + the linter works best with linear parsing of the file and '#import_bumps' \ + also sets the `Elab.async` option to `false`." + return let env ← getEnv -- the first time `minImportsRef` is read, it has `transClosure = none`; -- in this case, we set it to be the `transClosure` for the file. diff --git a/MathlibTest/MinImports.lean b/MathlibTest/MinImports.lean index 87a0a011d07ad..ad749a05da97f 100644 --- a/MathlibTest/MinImports.lean +++ b/MathlibTest/MinImports.lean @@ -77,7 +77,12 @@ lemma hi (n : ℕ) : n = n := by extract_goal; rfl section Linter.MinImports set_option linter.minImports.increases false -set_option linter.minImports true + +set_option linter.minImports false +/-- info: Counting imports from here. -/ +#guard_msgs in +#import_bumps + /-- warning: Imports increased to [Init.Guard, Mathlib.Data.Int.Notation] From f28d136dcbdaf23754d8e40f3116ef2c594bd10b Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 23 Jan 2025 07:01:35 +0000 Subject: [PATCH 440/681] feat(Archive/Imo): IMO 2024 Q3 (#19671) Add a formalization of IMO 2024 problem 3. Co-authored-by: Joseph Myers Co-authored-by: Michael Rothgang Co-authored-by: qawbecrdtey --- Archive.lean | 1 + Archive/Imo/Imo2024Q3.lean | 961 +++++++++++++++++++++++++++++++++++++ 2 files changed, 962 insertions(+) create mode 100644 Archive/Imo/Imo2024Q3.lean diff --git a/Archive.lean b/Archive.lean index fc8da3829ecc9..9b6a77f6d4afd 100644 --- a/Archive.lean +++ b/Archive.lean @@ -46,6 +46,7 @@ import Archive.Imo.Imo2020Q2 import Archive.Imo.Imo2021Q1 import Archive.Imo.Imo2024Q1 import Archive.Imo.Imo2024Q2 +import Archive.Imo.Imo2024Q3 import Archive.Imo.Imo2024Q5 import Archive.Imo.Imo2024Q6 import Archive.MiuLanguage.Basic diff --git a/Archive/Imo/Imo2024Q3.lean b/Archive/Imo/Imo2024Q3.lean new file mode 100644 index 0000000000000..abfb5b06bf769 --- /dev/null +++ b/Archive/Imo/Imo2024Q3.lean @@ -0,0 +1,961 @@ +/- +Copyright (c) 2024 Joseph Myers. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joseph Myers +-/ +import Mathlib.Data.Nat.Nth + +/-! +# IMO 2024 Q3 + +Let $a_1, a_2, a_3, \ldots$ be an infinite sequence of positive integers, and let $N$ be a +positive integer. Suppose that, for each $n > N$, $a_n$ is equal to the number of times +$a_{n-1}$ appears in the list $a_1, a_2, \ldots, a_{n-1}$. + +Prove that at least one of the sequences $a_1, a_3, a_5, \ldots$ and $a_2, a_4, a_6, \ldots$ +is eventually periodic. + +We follow Solution 1 from the +[official solutions](https://www.imo2024.uk/s/IMO2024-solutions-updated.pdf). We show that +the positive integers up to some positive integer $k$ (referred to as small numbers) all appear +infinitely often in the given sequence while all larger positive integers appear only finitely +often and then that the sequence eventually alternates between small numbers and larger integers. +A further detailed analysis of the eventual behavior of the sequence ends up showing that the +sequence of small numbers is eventually periodic with period at most $k$ (in fact exactly $k$). +-/ + + +open scoped Finset + +namespace Imo2024Q3 + +/-- The condition of the problem. Following usual Lean conventions, this is expressed with +indices starting from 0, rather than from 1 as in the informal statment (but `N` remains as the +index of the last term for which `a n` is not defined in terms of previous terms). -/ +def Condition (a : ℕ → ℕ) (N : ℕ) : Prop := + (∀ i, 0 < a i) ∧ ∀ n, N < n → a n = #{i ∈ Finset.range n | a i = a (n - 1)} + +/-- The property of a sequence being eventually periodic. -/ +def EventuallyPeriodic (b : ℕ → ℕ) : Prop := ∃ p M, 0 < p ∧ ∀ m, M ≤ m → b (m + p) = b m + +/-! ### Definitions and lemmas about the sequence that do not actually need the condition of +the problem -/ + +/-- A number greater than any of the initial terms `a 0` through `a N` (otherwise arbitrary). -/ +def M (a : ℕ → ℕ) (N : ℕ) : ℕ := (Finset.range (N + 1)).sup a + 1 + +lemma M_pos (a : ℕ → ℕ) (N : ℕ) : 0 < M a N := + Nat.add_one_pos _ + +lemma one_le_M (a : ℕ → ℕ) (N : ℕ) : 1 ≤ M a N := + Nat.lt_iff_add_one_le.1 (M_pos a N) + +lemma apply_lt_M_of_le_N (a : ℕ → ℕ) {N i : ℕ} (h : i ≤ N) : a i < M a N := + Nat.lt_add_one_iff.2 (Finset.le_sup (Finset.mem_range_succ_iff.2 h)) + +lemma N_lt_of_M_le_apply {a : ℕ → ℕ} {N i : ℕ} (h : M a N ≤ a i) : N < i := by + by_contra! hi + exact Nat.not_succ_le_self _ (h.trans (Finset.le_sup (Finset.mem_range_succ_iff.2 hi))) + +lemma ne_zero_of_M_le_apply {a : ℕ → ℕ} {N i : ℕ} (h : M a N ≤ a i) : i ≠ 0 := + Nat.not_eq_zero_of_lt (N_lt_of_M_le_apply h) + +lemma apply_lt_of_M_le_apply {a : ℕ → ℕ} {N i j : ℕ} (hi : M a N ≤ a i) (hj : j ≤ N) : + a j < a i := + (apply_lt_M_of_le_N a hj).trans_le hi + +lemma apply_ne_of_M_le_apply {a : ℕ → ℕ} {N i j : ℕ} (hi : M a N ≤ a i) (hj : j ≤ N) : + a j ≠ a i := + (apply_lt_of_M_le_apply hi hj).ne + +lemma toFinset_card_pos {a : ℕ → ℕ} {i : ℕ} (hf : {j | a j = a i}.Finite) : 0 < #hf.toFinset := + Finset.card_pos.mpr ((Set.Finite.toFinset_nonempty _).mpr ⟨i, rfl⟩) + +lemma apply_nth_zero (a : ℕ → ℕ) (i : ℕ) : a (Nat.nth (a · = a i) 0) = a i := + Nat.nth_mem (p := (a · = a i)) 0 toFinset_card_pos + +lemma map_add_one_range (p : ℕ → Prop) [DecidablePred p] (n : ℕ) (h0 : ¬ p 0) : + {x ∈ Finset.range n | p (x + 1)}.map ⟨(· + 1), add_left_injective 1⟩ = + {x ∈ Finset.range (n + 1) | p x } := by + ext x + simp only [Finset.mem_map] + constructor + · aesop + · intro hx + use x - 1 + cases x <;> simp_all + +namespace Condition + +/-! ### The basic structure of the sequence, eventually alternating small and large numbers -/ + +variable {a : ℕ → ℕ} {N : ℕ} (hc : Condition a N) +include hc + +protected lemma pos (n : ℕ) : 0 < a n := hc.1 n + +@[simp] lemma apply_ne_zero (n : ℕ) : a n ≠ 0 := + (hc.pos _).ne' + +lemma one_le_apply (n : ℕ) : 1 ≤ a n := + Nat.one_le_iff_ne_zero.2 (hc.apply_ne_zero n) + +lemma apply_eq_card {n : ℕ} (h : N < n) : a n = #{i ∈ Finset.range n | a i = a (n - 1)} := + hc.2 n h + +lemma apply_add_one_eq_card {n : ℕ} (h : N ≤ n) : + a (n + 1) = #{i ∈ Finset.range (n + 1) | a i = a n} := by + rw [hc.apply_eq_card (Nat.lt_add_one_of_le h)] + simp + +@[simp] lemma nth_apply_eq_zero (n : ℕ) : Nat.nth (a · = 0) n = 0 := by + convert Nat.nth_false _ with i + simp only [(hc.pos i).ne'] + +lemma nth_apply_add_one_eq {n : ℕ} (h : N ≤ n) : Nat.nth (a · = a n) (a (n + 1) - 1) = n := by + rw [hc.apply_add_one_eq_card h] + nth_rw 5 [← Nat.nth_count (p := (a · = a n)) rfl] + simp [Finset.range_add_one, Finset.filter_insert, Nat.count_eq_card_filter_range] + +lemma apply_nth_add_one_eq {m n : ℕ} (hfc : ∀ hf : {i | a i = m}.Finite, n < #hf.toFinset) + (hn : N ≤ Nat.nth (a · = m) n) : a (Nat.nth (a · = m) n + 1) = n + 1 := by + rw [hc.apply_eq_card (Nat.lt_add_one_of_le hn), add_tsub_cancel_right, + ← Nat.count_eq_card_filter_range, Nat.nth_mem n hfc, Nat.count_nth_succ hfc] + +lemma apply_nth_add_one_eq_of_infinite {m n : ℕ} (hi : {i | a i = m}.Infinite) + (hn : N ≤ Nat.nth (a · = m) n) : a (Nat.nth (a · = m) n + 1) = n + 1 := + hc.apply_nth_add_one_eq (fun hf ↦ absurd hf hi) hn + +lemma apply_nth_add_one_eq_of_lt {m n : ℕ} (hn : N < Nat.nth (a · = m) n) : + a (Nat.nth (a · = m) n + 1) = n + 1 := by + refine hc.apply_nth_add_one_eq ?_ hn.le + by_contra! hf + have := Nat.nth_eq_zero.2 (.inr hf) + omega + +lemma lt_toFinset_card {j : ℕ} (h : M a N ≤ a (j + 1)) (hf : {i | a i = a j}.Finite) : + M a N - 1 < #hf.toFinset := by + rw [Nat.sub_lt_iff_lt_add (M_pos _ _), Nat.lt_one_add_iff] + exact (hc.apply_eq_card (N_lt_of_M_le_apply h) ▸ h).trans (Finset.card_le_card (by simp)) + +lemma nth_ne_zero_of_M_le_of_lt {i k : ℕ} (hi : M a N ≤ a i) (hk : k < a (i + 1)) : + Nat.nth (a · = a i) k ≠ 0 := + Nat.nth_ne_zero_anti (apply_ne_of_M_le_apply hi (Nat.zero_le _)) (by omega) + (hc.nth_apply_add_one_eq (N_lt_of_M_le_apply hi).le ▸ ne_zero_of_M_le_apply hi) + +lemma apply_add_one_lt_of_apply_eq {i j : ℕ} (hi : N ≤ i) (hij : i < j) (ha : a i = a j) : + a (i + 1) < a (j + 1) := by + rw [hc.apply_add_one_eq_card hi, hc.apply_add_one_eq_card (by omega), ha] + refine Finset.card_lt_card (Finset.ssubset_def.mp ⟨Finset.filter_subset_filter _ + (by simp [hij.le]), Finset.not_subset.mpr ⟨j, ?_⟩⟩) + simp only [Finset.mem_filter, Finset.mem_range, lt_add_iff_pos_right, zero_lt_one, true_and, + and_true] + omega + +lemma apply_add_one_ne_of_apply_eq {i j : ℕ} (hi : N ≤ i) (hj : N ≤ j) (hij : i ≠ j) + (ha : a i = a j) : a (i + 1) ≠ a (j + 1) := + hij.lt_or_lt.elim (fun h ↦ (hc.apply_add_one_lt_of_apply_eq hi h ha).ne) fun h ↦ + (hc.apply_add_one_lt_of_apply_eq hj h ha.symm).ne' + +lemma exists_infinite_setOf_apply_eq : ∃ m, {i | a i = m}.Infinite := by + by_contra hi + have hr : (Set.range a).Infinite := by + contrapose! hi with hr + rw [Set.not_infinite, ← Set.finite_coe_iff] at hr + obtain ⟨n, hn⟩ := Finite.exists_infinite_fiber (Set.rangeFactorization a) + rw [Set.infinite_coe_iff, Set.preimage] at hn + simp only [Set.mem_singleton_iff, Set.rangeFactorization, Subtype.ext_iff] at hn + exact ⟨↑n, hn⟩ + simp only [not_exists, Set.not_infinite] at hi + have hinj : Set.InjOn (fun i ↦ Nat.nth (a · = i) 0 + 1) (Set.range a \ Set.Ico 0 (M a N)) := by + rintro _ ⟨⟨_, rfl⟩, hi⟩ _ ⟨⟨_, rfl⟩, hj⟩ h + simp only [Set.mem_diff, Set.mem_range, Set.mem_Ico, zero_le, true_and, not_lt] at hi hj + simp only [add_left_inj] at h + convert congr(a $h) using 1 <;> simp [apply_nth_zero] + refine Set.not_infinite.2 (hi 1) (Set.infinite_of_injOn_mapsTo hinj (fun i hi ↦ ?_) + (hr.diff (Set.finite_Ico _ _))) + simp only [Set.mem_diff, Set.mem_range, Set.mem_Ico, zero_le, true_and, not_lt] at hi + rcases hi with ⟨⟨_, rfl⟩, hi⟩ + exact hc.apply_nth_add_one_eq toFinset_card_pos + (N_lt_of_M_le_apply (a := a) (by simp only [apply_nth_zero, hi])).le + +lemma nonempty_setOf_infinite_setOf_apply_eq : {m | {i | a i = m}.Infinite}.Nonempty := + hc.exists_infinite_setOf_apply_eq + +lemma injOn_setOf_apply_add_one_eq_of_M_le {n : ℕ} (h : M a N ≤ n) : + Set.InjOn a {i | a (i + 1) = n} := by + intro i hi j hj hij + have hi' := hi ▸ hc.nth_apply_add_one_eq (Nat.lt_add_one_iff.mp (N_lt_of_M_le_apply (hi ▸ h))) + have hj' := hj ▸ hc.nth_apply_add_one_eq (Nat.lt_add_one_iff.mp (N_lt_of_M_le_apply (hj ▸ h))) + rw [← hi', ← hj', hij] + +lemma empty_consecutive_apply_ge_M : {i | M a N ≤ a i ∧ M a N ≤ a (i + 1)} = ∅ := by + rw [Set.eq_empty_iff_forall_not_mem] + intro i + induction i using Nat.strong_induction_on with | h i ih => + -- Let i be the first index where both `a i` and `a (i + 1)` are at least M. + rintro ⟨hi1, hi2⟩ + have hi : ∀ j < i, M a N ≤ a j → a (j + 1) < M a N := by simp_all + -- t is the set of indices before an appearance of the integer (a i). For each j ∈ t, (a j) + -- is the (a i)th appearance of that value, so each such value before index i appears at least + -- M times before that index; since (a i) is the (at least) Mth appearance of that value, there + -- are at least M positive integers appearing M times before (a i), a contradiction because one of + -- those must be at least M. + let t : Finset ℕ := {j ∈ Finset.range i | a (j + 1) = a i} + let t' : Finset ℕ := {j ∈ Finset.range (i + 1) | a j = a i} + have t_map_eq_t' : t.map ⟨(· + 1), add_left_injective 1⟩ = t' := by + refine map_add_one_range (a · = a i) i ?_ + intro H + rw [←H, M] at hi1 + have a0_le : a 0 ≤ (Finset.range (N + 1)).sup a := Finset.le_sup (by simp) + omega + have card_t_eq_card_t' : #t = #t' := by simp [← t_map_eq_t', t] + have htM : ∀ j ∈ t, a j < M a N := by + intro j hj + simp only [t, Finset.mem_filter, Finset.mem_range] at hj + obtain ⟨hj, hji⟩ := hj + by_contra! hjM + exact (lt_self_iff_false _).mp ((hji ▸ hi j hj hjM).trans_le hi1) + have N_le_i : N ≤ i := by + unfold M at hi1 + by_contra! HH + have i_in_range : i ∈ Finset.range (N + 1) := by rw [Finset.mem_range]; omega + have ai_le_sup : a i ≤ (Finset.range (N + 1)).sup a := Finset.le_sup i_in_range + omega + have ht' : a (i + 1) = #t' := hc.apply_add_one_eq_card N_le_i + rw [← card_t_eq_card_t'] at ht' + have ht'inj : Set.InjOn a t := by + refine (hc.injOn_setOf_apply_add_one_eq_of_M_le hi1).mono ?_ + simp_all [t, t'] + have card_image_eq_card_t : #(Finset.image a t) = #t := Finset.card_image_of_injOn ht'inj + have card_image_lt_M : #(Finset.image a t) < M a N := by + refine (Finset.card_le_card (t := Finset.Ico 1 (M a N)) ?_).trans_lt ?_ + · simp only [Finset.subset_iff, Finset.mem_image, Finset.mem_Ico, forall_exists_index, and_imp, + forall_apply_eq_imp_iff₂] + exact fun j hj ↦ ⟨hc.pos _, htM j hj⟩ + · simpa using M_pos a N + omega + +lemma card_lt_M_of_M_le {n : ℕ} (h : M a N ≤ n) : + ∃ hf : {i | a i = n}.Finite, #hf.toFinset < M a N := by + have := empty_consecutive_apply_ge_M hc + contrapose! this with hin + use Nat.nth (a · = n) (M a N - 1) + have hin' := fun hf ↦ Nat.sub_one_lt_of_le (M_pos a N) (hin hf) + have ha : M a N ≤ a (Nat.nth (a · = n) (M a N - 1)) := (Nat.nth_mem _ hin').symm ▸ h + refine ⟨ha, ?_⟩ + suffices H : a (Nat.nth (fun x ↦ a x = n) (M a N - 1) + 1) = M a N from Nat.le_of_eq H.symm + convert hc.apply_nth_add_one_eq hin' (N_lt_of_M_le_apply ha).le using 1 + +lemma bddAbove_setOf_infinite_setOf_apply_eq : BddAbove {m | {i | a i = m}.Infinite} := by + refine ⟨M a N, fun x hi ↦ ?_⟩ + by_contra hx + exact hi (hc.card_lt_M_of_M_le (not_le.mp hx).le).1 + +lemma infinite_setOf_apply_eq_anti {j k : ℕ} (hj : 0 < j) (hk : {i | a i = k}.Infinite) + (hjk : j ≤ k) : {i | a i = j}.Infinite := by + have hk' : {i | a (i + 1) = k}.Infinite := by + have hinj : Set.InjOn (· + 1) {i | a (i + 1) = k} := (add_left_injective _).injOn + rw [← Set.infinite_image_iff hinj] + have hk0 : ({i | a i = k} \ {0}).Infinite := hk.diff (Set.finite_singleton _) + convert hk0 using 1 + ext i + simp only [Set.mem_image, Set.mem_setOf_eq, Set.mem_diff, Set.mem_singleton_iff] + refine ⟨?_, ?_⟩ + · rintro ⟨j, rfl, rfl⟩ + simp + · rintro ⟨rfl, h⟩ + exact ⟨i - 1, by simp [(by omega : i - 1 + 1 = i)]⟩ + have hinj : Set.InjOn (fun x ↦ Nat.nth (a · = a x) (j - 1) + 1) + ({i | a (i + 1) = k} \ Set.Ico 0 N) := by + intro x hx y hy h + simp only [Set.mem_diff, Set.mem_setOf_eq, Set.mem_Ico, zero_le, true_and, not_lt] at hx hy + rcases hx with ⟨hxk, hNx⟩ + rcases hy with ⟨hyk, hNy⟩ + simp only [add_left_inj] at h + have hxk' : Nat.nth (a · = a x) (k - 1) = x := by rw [← hxk, hc.nth_apply_add_one_eq hNx] + have hyk' : Nat.nth (a · = a y) (k - 1) = y := by rw [← hyk, hc.nth_apply_add_one_eq hNy] + have hjk' : j - 1 ≤ k - 1 := by omega + apply_fun a at hxk' hyk' + have hyj : a (Nat.nth (a · = a y) (j - 1)) = a y := + Nat.nth_mem_anti (p := (a · = a y)) hjk' hyk' + rw [← h, Nat.nth_mem_anti (p := (a · = a x)) hjk' hxk'] at hyj + by_contra hxy + exact hc.apply_add_one_ne_of_apply_eq hNx hNy hxy hyj (hyk ▸ hxk) + have hk'' : (_ \ Set.Ico 0 (N + 2)).Infinite := + ((Set.infinite_image_iff hinj).mpr (hk'.diff (Set.finite_Ico _ _))).diff (Set.finite_Ico _ _) + refine hk''.mono fun _ hi ↦ ?_ + simp only [Set.mem_image, Set.mem_diff, Set.mem_setOf_eq, Set.mem_Ico, zero_le, true_and, + not_lt] at hi + rcases hi with ⟨⟨x, -, rfl⟩, _⟩ + rw [Set.mem_setOf_eq, hc.apply_nth_add_one_eq_of_lt (by omega), Nat.sub_add_cancel hj] + +/-! ### The definitions of small, medium and big numbers and the eventual alternation -/ + +variable (a) + +/-- The largest number to appear infinitely often. -/ +noncomputable def k : ℕ := sSup {m | {i | a i = m}.Infinite} + +/-- Small numbers are those that are at most `k` (that is, those that appear infinitely often). -/ +def Small (j : ℕ) : Prop := j ≤ k a + +variable {a} + +lemma infinite_setOf_apply_eq_k : {i | a i = k a}.Infinite := + Nat.sSup_mem hc.nonempty_setOf_infinite_setOf_apply_eq hc.bddAbove_setOf_infinite_setOf_apply_eq + +lemma infinite_setOf_apply_eq_iff_small {j : ℕ} (hj : 0 < j) : + {i | a i = j}.Infinite ↔ Small a j := + ⟨fun h ↦ le_csSup hc.bddAbove_setOf_infinite_setOf_apply_eq h, + fun h ↦ hc.infinite_setOf_apply_eq_anti hj hc.infinite_setOf_apply_eq_k h⟩ + +lemma finite_setOf_apply_eq_iff_not_small {j : ℕ} (hj : 0 < j) : + {i | a i = j}.Finite ↔ ¬Small a j := by + simpa only [Set.not_infinite] using (hc.infinite_setOf_apply_eq_iff_small hj).not + +lemma finite_setOf_apply_eq_k_add_one : {i | a i = k a + 1}.Finite := by + rw [hc.finite_setOf_apply_eq_iff_not_small (by omega), Small] + omega + +/-- There are only finitely many `m` that appear more than `k` times. -/ +lemma finite_setOf_k_lt_card : {m | ∀ hf : {i | a i = m}.Finite, k a < #hf.toFinset}.Finite := by + rw [← Set.finite_image_iff] + · refine Set.Finite.of_diff (hc.finite_setOf_apply_eq_k_add_one.subset fun i hi ↦ ?_) + (Set.finite_Iic N) + simp only [Set.mem_diff, Set.mem_image, Set.mem_setOf_eq, Set.mem_Iic, not_le] at hi + rcases hi with ⟨⟨j, hjf, rfl⟩, hNi⟩ + rw [Set.mem_setOf_eq, hc.apply_nth_add_one_eq hjf (by omega)] + · intro i hi j hj hij + simp only [add_left_inj] at hij + apply_fun a at hij + rwa [Nat.nth_mem _ hi, Nat.nth_mem _ hj] at hij + +lemma bddAbove_setOf_k_lt_card : BddAbove {m | ∀ hf : {i | a i = m}.Finite, k a < #hf.toFinset} := + hc.finite_setOf_k_lt_card.bddAbove + +lemma k_pos : 0 < k a := by + by_contra! hn + apply nonpos_iff_eq_zero.mp hn ▸ hc.infinite_setOf_apply_eq_k + convert Set.finite_empty + ext i + simp [(hc.pos i).ne'] + +lemma small_one : Small a 1 := by + by_contra hns + simp only [Small, not_le, Nat.lt_one_iff, hc.k_pos.ne'] at hns + +lemma infinite_setOf_apply_eq_one : {i | a i = 1}.Infinite := + (hc.infinite_setOf_apply_eq_iff_small (by decide)).mpr hc.small_one + +variable (a) + +/-- The largest number to appear more than `k` times. -/ +noncomputable def l : ℕ := sSup {m | ∀ hf : {i | a i = m}.Finite, k a < #hf.toFinset} + +/-- Medium numbers are those that are more than `k` but at most `l` (and include all numbers +appearing finitely often but more than `k` times). -/ +def Medium (j : ℕ) : Prop := k a < j ∧ j ≤ l a + +/-- Big numbers are those greater than `l` (thus, appear at most `k` times). -/ +def Big (j : ℕ) : Prop := l a < j + +variable {a} + +lemma k_le_l : k a ≤ l a := + le_csSup hc.bddAbove_setOf_k_lt_card (fun hf ↦ absurd hf hc.infinite_setOf_apply_eq_k) + +lemma k_lt_of_big {j : ℕ} (h : Big a j) : k a < j := + hc.k_le_l.trans_lt h + +lemma pos_of_big {j : ℕ} (h : Big a j) : 0 < j := + (Nat.zero_le _).trans_lt (hc.k_lt_of_big h) + +lemma not_small_of_big {j : ℕ} (h : Big a j) : ¬Small a j := by simp [Small, hc.k_lt_of_big h] + +lemma exists_card_le_of_big {j : ℕ} (h : Big a j) : + ∃ hf : {i | a i = j}.Finite, #hf.toFinset ≤ k a := by + have hns := hc.not_small_of_big h + rw [← hc.finite_setOf_apply_eq_iff_not_small (hc.pos_of_big h)] at hns + use hns + by_contra! hlt + exact not_mem_of_csSup_lt h hc.bddAbove_setOf_k_lt_card fun _ ↦ hlt + +variable (a N) + +/-- `N'aux` is such that, by position `N'aux`, every medium number has made all its appearances +and every small number has appeared more than max(k, N+1) times. -/ +noncomputable def N'aux : ℕ := + sSup {i | Medium a (a i)} ⊔ sSup ((fun i ↦ Nat.nth (a · = i) (k a ⊔ (N + 1))) '' Set.Iic (k a)) + +/-- `N'` is such that, by position `N'`, every medium number has made all its appearances +and every small number has appeared more than max(k, N+1) times; furthermore, `a N'` is small +(which means that every subsequent big number is preceded by a small number). -/ +noncomputable def N' : ℕ := by + classical + exact N'aux a N + (if Small a (a (N'aux a N + 1)) then 1 else 2) + +variable {a N} + +lemma not_medium_of_N'aux_lt {j : ℕ} (h : N'aux a N < j) : ¬Medium a (a j) := by + let s : Set ℕ := ⋃ i ∈ Set.Ioc (k a) (l a), {j | a j = i} + have hf : s.Finite := by + refine (Set.finite_Ioc _ _).biUnion ?_ + rintro i ⟨hk, -⟩ + rwa [hc.finite_setOf_apply_eq_iff_not_small (by omega), Small, not_le] + exact fun hm ↦ not_mem_of_csSup_lt (le_sup_left.trans_lt h) + (hf.subset fun i hi ↦ (by simpa [s] using hi)).bddAbove hm + +lemma small_or_big_of_N'aux_lt {j : ℕ} (h : N'aux a N < j) : Small a (a j) ∨ Big a (a j) := by + have _ := hc.not_medium_of_N'aux_lt h + rw [Small, Medium, Big] at * + omega + +lemma small_or_big_of_N'_le {j : ℕ} (h : N' a N ≤ j) : Small a (a j) ∨ Big a (a j) := by + refine hc.small_or_big_of_N'aux_lt ?_ + rw [N'] at h + split_ifs at h <;> omega + +omit hc + +lemma nth_sup_k_N_add_one_le_N'aux_of_small {j : ℕ} (h : Small a j) : + Nat.nth (a · = j) (k a ⊔ (N + 1)) ≤ N'aux a N := by + by_contra! hn + exact not_mem_of_csSup_lt (le_sup_right.trans_lt hn) ((Set.finite_Iic _).image _).bddAbove + ⟨j, h, rfl⟩ + +include hc + +lemma nth_sup_k_le_N'aux_of_small {j : ℕ} (h : Small a j) : + Nat.nth (a · = j) (k a) ≤ N'aux a N := + match j with + | 0 => by simp only [hc.nth_apply_eq_zero, zero_le] + | j + 1 => ((Nat.nth_le_nth ((hc.infinite_setOf_apply_eq_iff_small (Nat.zero_lt_succ j)).mpr h)).2 + le_sup_left).trans (nth_sup_k_N_add_one_le_N'aux_of_small h) + +lemma nth_sup_N_add_one_le_N'aux_of_small {j : ℕ} (h : Small a j) : + Nat.nth (a · = j) (N + 1) ≤ N'aux a N := + match j with + | 0 => by simp only [hc.nth_apply_eq_zero, zero_le] + | j + 1 => ((Nat.nth_le_nth ((hc.infinite_setOf_apply_eq_iff_small (Nat.zero_lt_succ j)).mpr h)).2 + le_sup_right).trans (nth_sup_k_N_add_one_le_N'aux_of_small h) + +lemma N_lt_N'aux : N < N'aux a N := + Nat.add_one_le_iff.mp ((Nat.le_nth fun hf ↦ absurd hf hc.infinite_setOf_apply_eq_one).trans + (hc.nth_sup_N_add_one_le_N'aux_of_small hc.small_one)) + +/-- `N` is less than `N'`. -/ +lemma N_lt_N' : N < N' a N := hc.N_lt_N'aux.trans_le (Nat.le_add_right _ _) + +lemma lt_card_filter_eq_of_small_nth_lt {i j t : ℕ} (hj0 : 0 < j) (h : Small a j) + (ht : Nat.nth (a · = j) t < i) : t < #{m ∈ Finset.range i | a m = j} := by + rw [← hc.infinite_setOf_apply_eq_iff_small hj0] at h + rw [← Nat.count_eq_card_filter_range] + exact (Nat.nth_lt_nth h).mp (ht.trans_le (Nat.le_nth_count h _)) + +lemma k_lt_card_filter_eq_of_small_of_N'aux_le {i j : ℕ} (hj0 : 0 < j) (h : Small a j) + (hN'aux : N'aux a N < i) : k a < #{m ∈ Finset.range i | a m = j} := + hc.lt_card_filter_eq_of_small_nth_lt hj0 h ((hc.nth_sup_k_le_N'aux_of_small h).trans_lt hN'aux) + +lemma N_add_one_lt_card_filter_eq_of_small_of_N'aux_le {i j : ℕ} (hj0 : 0 < j) (h : Small a j) + (hN'aux : N'aux a N < i) : N + 1 < #{m ∈ Finset.range i | a m = j} := + hc.lt_card_filter_eq_of_small_nth_lt hj0 h + ((hc.nth_sup_N_add_one_le_N'aux_of_small h).trans_lt hN'aux) + +lemma N_add_one_lt_card_filter_eq_of_small_of_N'_le {i j : ℕ} (hj0 : 0 < j) (h : Small a j) + (hN' : N' a N < i) : N + 1 < #{m ∈ Finset.range i | a m = j} := by + refine hc.N_add_one_lt_card_filter_eq_of_small_of_N'aux_le hj0 h ?_ + rw [N'] at hN' + split_ifs at hN' <;> omega + +lemma apply_add_one_big_of_apply_small_of_N'aux_le {i : ℕ} (h : Small a (a i)) + (hN'aux : N'aux a N ≤ i) : Big a (a (i + 1)) := by + have hN'' : N'aux a N < i + 1 := by omega + suffices ¬Small a (a (i + 1)) by simpa [this] using hc.small_or_big_of_N'aux_lt hN'' + rw [hc.apply_add_one_eq_card (hc.N_lt_N'aux.le.trans hN'aux), Small, not_le] + exact hc.k_lt_card_filter_eq_of_small_of_N'aux_le (hc.pos _) h hN'' + +lemma apply_add_one_big_of_apply_small_of_N'_le {i : ℕ} (h : Small a (a i)) (hN' : N' a N ≤ i) : + Big a (a (i + 1)) := + hc.apply_add_one_big_of_apply_small_of_N'aux_le h ((Nat.le_add_right _ _).trans hN') + +lemma apply_add_one_small_of_apply_big_of_N'aux_le {i : ℕ} (h : Big a (a i)) + (hN'aux : N'aux a N ≤ i) : Small a (a (i + 1)) := by + obtain ⟨hf, hfc⟩ := hc.exists_card_le_of_big h + rw [hc.apply_add_one_eq_card (hc.N_lt_N'aux.le.trans hN'aux)] + exact (Finset.card_le_card (by simp)).trans hfc + +lemma apply_add_one_small_of_apply_big_of_N'_le {i : ℕ} (h : Big a (a i)) (hN' : N' a N ≤ i) : + Small a (a (i + 1)) := + hc.apply_add_one_small_of_apply_big_of_N'aux_le h ((Nat.le_add_right _ _).trans hN') + +lemma apply_add_two_small_of_apply_small_of_N'_le {i : ℕ} (h : Small a (a i)) (hN' : N' a N ≤ i) : + Small a (a (i + 2)) := + hc.apply_add_one_small_of_apply_big_of_N'_le (hc.apply_add_one_big_of_apply_small_of_N'_le h hN') + (by omega) + +/-- `a (N' a N)` is a small number. -/ +lemma small_apply_N' : Small a (a (N' a N)) := by + rw [N'] + split_ifs with hi + · exact hi + · have hb : Big a (a (N'aux a N + 1)) := by + simpa [hi] using hc.small_or_big_of_N'aux_lt (Nat.lt_add_one (N'aux a N)) + exact hc.apply_add_one_small_of_apply_big_of_N'aux_le hb (by omega) + +lemma small_apply_N'_add_iff_even {n : ℕ} : Small a (a (N' a N + n)) ↔ Even n := by + induction n with + | zero => simpa using hc.small_apply_N' + | succ n ih => + by_cases he : Even n <;> rw [← add_assoc] <;> simp only [he, iff_true, iff_false] at ih + · have hne : ¬ Even (n + 1) := by simp [Nat.not_even_iff_odd, he] + simp only [hne, iff_false] + exact hc.not_small_of_big (hc.apply_add_one_big_of_apply_small_of_N'_le ih (by omega)) + · have hb : Big a (a (N' a N + n)) := by + simpa [ih] using hc.small_or_big_of_N'_le (j := N' a N + n) (by omega) + simp [hc.apply_add_one_small_of_apply_big_of_N'_le hb (by omega), Nat.not_even_iff_odd.mp he] + +lemma small_apply_add_two_mul_iff_small {n : ℕ} (m : ℕ) (hN' : N' a N ≤ n) : + Small a (a (n + 2 * m)) ↔ Small a (a n) := by + rw [show n = N' a N + (n - N' a N) by omega, add_assoc, hc.small_apply_N'_add_iff_even, + hc.small_apply_N'_add_iff_even] + simp [Nat.even_add] + +lemma apply_sub_one_small_of_apply_big_of_N'_le {i : ℕ} (h : Big a (a i)) (hN' : N' a N ≤ i) : + Small a (a (i - 1)) := by + have h0i : 1 ≤ i := by + have := hc.N_lt_N' + omega + have h' : N' a N ≤ i - 1 := by + by_contra hi + have hi' : i = N' a N := by omega + exact hc.not_small_of_big (hi' ▸ h) hc.small_apply_N' + exact (hc.small_or_big_of_N'_le h').elim id fun hb ↦ + False.elim (hc.not_small_of_big h (Nat.sub_add_cancel h0i ▸ + (hc.apply_add_one_small_of_apply_big_of_N'_le hb h'))) + +lemma apply_sub_one_big_of_apply_small_of_N'_lt {i : ℕ} (h : Small a (a i)) (hN' : N' a N < i) : + Big a (a (i - 1)) := by + have h0i : 1 ≤ i := by omega + have h' : N' a N ≤ i - 1 := by omega + exact (hc.small_or_big_of_N'_le h').elim (fun hs ↦ False.elim (hc.not_small_of_big + (Nat.sub_add_cancel h0i ▸ hc.apply_add_one_big_of_apply_small_of_N'_le hs h') h)) id + +lemma apply_sub_two_small_of_apply_small_of_N'_lt {i : ℕ} (h : Small a (a i)) (hN' : N' a N < i) : + Small a (a (i - 2)) := by + convert hc.apply_sub_one_small_of_apply_big_of_N'_le + (hc.apply_sub_one_big_of_apply_small_of_N'_lt h hN') (by omega) using 1 + +lemma N_add_one_lt_apply_of_apply_big_of_N'_le {i : ℕ} (h : Big a (a i)) (hN' : N' a N ≤ i) : + N + 1 < a i := by + refine hc.apply_eq_card (hc.N_lt_N'.trans_le hN') ▸ + hc.N_add_one_lt_card_filter_eq_of_small_of_N'_le (hc.pos _) + (hc.apply_sub_one_small_of_apply_big_of_N'_le h hN') ?_ + by_contra + exact hc.not_small_of_big ((by omega : i = N' a N) ▸ h) hc.small_apply_N' + +lemma setOf_apply_eq_of_apply_big_of_N'_le {i : ℕ} (h : Big a (a i)) (hN' : N' a N ≤ i) : + {j | a j = a i} = {j | N < j ∧ Small a (a (j - 1)) ∧ + a i = #{t ∈ Finset.range j | a t = a (j - 1)}} := by + have hs : {j | N < j ∧ Small a (a (j - 1)) ∧ a i = #{t ∈ Finset.range j | a t = a (j - 1)}} ⊆ + {j | a j = a i} := by + rintro _ ⟨hNj, -, hj⟩ + exact hj ▸ hc.apply_eq_card hNj + rcases hc.exists_card_le_of_big h with ⟨hf, hck⟩ + have hf' : {j | N < j ∧ Small a (a (j - 1)) ∧ + a i = #{t ∈ Finset.range j | a t = a (j - 1)}}.Finite := hf.subset hs + suffices hf.toFinset = hf'.toFinset by simpa using this + rw [← Set.Finite.toFinset_subset_toFinset (hs := hf') (ht := hf)] at hs + refine (Finset.eq_of_subset_of_card_le hs (hck.trans ?_)).symm + have hs : #((Finset.Icc 1 (k a)).image (fun t ↦ Nat.nth (a · = t) (a i - 1) + 1)) = k a := by + convert Finset.card_image_of_injOn fun t ht u hu htu ↦ ?_ + · simp only [Nat.card_Icc, add_tsub_cancel_right] + · simp only [add_left_inj] at htu + simp only [Finset.coe_Icc, Set.mem_Icc] at ht hu + rw [← Small, ← hc.infinite_setOf_apply_eq_iff_small (by omega)] at ht hu + apply_fun a at htu + rwa [Nat.nth_mem_of_infinite ht.2, Nat.nth_mem_of_infinite hu.2] at htu + refine hs ▸ Finset.card_le_card (Finset.subset_iff.2 fun j hj ↦ ?_) + simp only [Set.Finite.mem_toFinset, Set.mem_setOf_eq] + simp only [Finset.mem_image, Finset.mem_Icc] at hj + rcases hj with ⟨t, ⟨ht1, htk⟩, rfl⟩ + have hN1 : N < a i - 1 := by + have := hc.N_add_one_lt_apply_of_apply_big_of_N'_le h hN' + omega + simp only [add_tsub_cancel_right] + rw [← Small] at htk + have htki := htk + rw [← hc.infinite_setOf_apply_eq_iff_small (by omega)] at htki + rw [Nat.nth_mem_of_infinite htki] + simp only [htk, true_and] + refine ⟨Nat.lt_add_one_iff.mpr ((Nat.le_nth (fun hf ↦ absurd hf htki)).trans + ((Nat.nth_le_nth htki).2 hN1.le)), ?_⟩ + rw [← Nat.count_eq_card_filter_range, Nat.count_nth_succ_of_infinite htki] + omega + +lemma N_lt_of_apply_eq_of_apply_big_of_N'_le {i j : ℕ} (hj : a j = a i) (h : Big a (a i)) + (hN' : N' a N ≤ i) : N < j := + have hj' : j ∈ {t | a t = a i} := by simpa using hj + (hc.setOf_apply_eq_of_apply_big_of_N'_le h hN' ▸ hj').1 + +lemma small_apply_sub_one_of_apply_eq_of_apply_big_of_N'_le {i j : ℕ} (hj : a j = a i) + (h : Big a (a i)) (hN' : N' a N ≤ i) : Small a (a (j - 1)) := + have hj' : j ∈ {t | a t = a i} := by simpa using hj + (hc.setOf_apply_eq_of_apply_big_of_N'_le h hN' ▸ hj').2.1 + +/-! ### The main lemmas leading to the required result -/ + +/-- Lemma 1 from the informal solution. -/ +lemma apply_add_one_eq_card_small_le_card_eq {i : ℕ} (hi : N' a N < i) (hib : Big a (a i)) : + a (i + 1) = #{m ∈ Finset.range (k a + 1) | a i ≤ #{j ∈ Finset.range i | a j = m}} := by + rw [hc.apply_add_one_eq_card (hc.N_lt_N'.trans hi).le] + convert Finset.card_image_of_injOn (f := fun j ↦ Nat.nth (a · = j) (a i - 1) + 1) ?_ using 1 + · congr + ext j + simp only [Finset.mem_filter, Finset.mem_range, Finset.mem_image] + refine ⟨fun ⟨hj, hji⟩ ↦ ⟨a (j - 1), hji ▸ ?_⟩, fun ⟨t, ⟨hts, htr⟩, ht⟩ ↦ ?_⟩ + · have hjN : N < j := hc.N_lt_of_apply_eq_of_apply_big_of_N'_le hji hib hi.le + refine ⟨⟨Nat.lt_add_one_iff.mpr (hc.small_apply_sub_one_of_apply_eq_of_apply_big_of_N'_le + hji hib hi.le), ?_⟩, ?_⟩ + · rw [hc.apply_eq_card hjN] + have : j ≤ i := by omega + gcongr + · have hj1 : j = j - 1 + 1 := by omega + nth_rw 2 [hj1] + rw [hc.nth_apply_add_one_eq (by omega), hj1.symm] + · subst ht + rw [Nat.lt_add_one_iff, ← Small] at hts + have ht0 : 0 < t := by + by_contra! h0 + simp [nonpos_iff_eq_zero.mp h0, hc.apply_ne_zero] at htr + rw [← hc.infinite_setOf_apply_eq_iff_small ht0] at hts + rw [← Nat.count_eq_card_filter_range] at htr + constructor + · rwa [add_lt_add_iff_right, ← Nat.lt_nth_iff_count_lt hts, + Nat.sub_lt_iff_lt_add (hc.one_le_apply _), Nat.lt_one_add_iff] + · rw [hc.apply_nth_add_one_eq_of_infinite hts] + · exact Nat.sub_add_cancel (hc.one_le_apply _) + · refine (Nat.le_nth fun hf ↦ absurd hf hts).trans ((Nat.nth_le_nth hts).2 ?_) + have := hc.N_add_one_lt_apply_of_apply_big_of_N'_le hib hi.le + omega + · intro t ht u hu htu + simp only [Finset.coe_filter, Finset.mem_range, Set.mem_setOf_eq, Nat.lt_add_one_iff] at ht hu + rw [← Small] at ht hu + have ht0 : 0 < t := by + by_contra! h0 + simp only [nonpos_iff_eq_zero] at h0 + simp [h0, hc.apply_ne_zero] at ht + have hu0 : 0 < u := by + by_contra! h0 + simp only [nonpos_iff_eq_zero] at h0 + simp [h0, hc.apply_ne_zero] at hu + rw [← hc.infinite_setOf_apply_eq_iff_small ht0] at ht + rw [← hc.infinite_setOf_apply_eq_iff_small hu0] at hu + simp only [add_left_inj] at htu + apply_fun a at htu + rwa [Nat.nth_mem_of_infinite ht.1, Nat.nth_mem_of_infinite hu.1] at htu + +/-- Similar to Lemma 1 from the informal solution, but with a `Small` hypothesis instead of `Big` +and considering a range one larger (the form needed for Lemma 2). -/ +lemma apply_eq_card_small_le_card_eq_of_small {i : ℕ} (hi : N' a N + 1 < i) + (his : Small a (a i)) : + a i = #{m ∈ Finset.range (k a + 1) | a (i - 1) ≤ #{j ∈ Finset.range i | a j = m}} := by + have hib : Big a (a (i - 1)) := hc.apply_sub_one_big_of_apply_small_of_N'_lt his (by omega) + nth_rw 1 [show i = i - 1 + 1 by omega] + rw [hc.apply_add_one_eq_card_small_le_card_eq (by omega) hib] + congr 1 + ext j + simp only [Finset.mem_filter, Finset.mem_range, and_congr_right_iff] + intro hj + convert Iff.rfl using 2 + congr 1 + ext t + simp only [Finset.mem_filter, Finset.mem_range, and_congr_right_iff] + refine ⟨fun ⟨hti, rfl⟩ ↦ ⟨?_, rfl⟩, fun ⟨_, rfl⟩ ↦ ⟨by omega, rfl⟩⟩ + by_contra hti1 + have htieq : t = i - 1 := by omega + subst htieq + exact hc.not_small_of_big hib (Nat.lt_add_one_iff.mp hj) + +/-- Lemma 2 from the informal solution. -/ +lemma exists_apply_sub_two_eq_of_apply_eq {i j : ℕ} (hi : N' a N + 2 < i) (hijlt : i < j) + (his : Small a (a i)) (hijeq : a i = a j) + (hij1 : ∀ t, Small a t → #{x ∈ Finset.Ico i j | a x = t} ≤ 1) : + ∃ t, t ∈ Finset.Ico i j ∧ a (i - 2) = a t := by + let I : Finset ℕ := {t ∈ Finset.range (k a + 1) | a (i - 1) ≤ #{u ∈ Finset.range i | a u = t}} + let J : Finset ℕ := {t ∈ Finset.range (k a + 1) | a (j - 1) ≤ #{u ∈ Finset.range j | a u = t}} + have hIc : a i = #I := hc.apply_eq_card_small_le_card_eq_of_small (by omega) his + have hJc : a j = #J := hc.apply_eq_card_small_le_card_eq_of_small (by omega) (hijeq ▸ his) + have hIJc : #I = #J := hIc ▸ hJc ▸ hijeq + have := hc.N_lt_N' + have hiju : Finset.range i ∪ Finset.Ico i j = Finset.range j := by + rw [Finset.range_eq_Ico, Finset.Ico_union_Ico' (by omega) (by omega)] + simp [hijlt.le] + have hi2s : a (i - 2) < k a + 1 := + Nat.lt_add_one_iff.mpr (hc.apply_sub_two_small_of_apply_small_of_N'_lt his (by omega)) + have hiI : a (i - 2) ∈ I := by + simp only [I, Finset.mem_filter, Finset.mem_range, hi2s, true_and] + rw [hc.apply_eq_card (by omega), show i - 1 - 1 = i - 2 by omega] + exact Finset.card_le_card (Finset.filter_subset_filter _ (by simp)) + have hj2s : a (j - 2) < k a + 1 := + Nat.lt_add_one_iff.mpr (hc.apply_sub_two_small_of_apply_small_of_N'_lt (hijeq ▸ his) (by omega)) + have hjJ : a (j - 2) ∈ J := by + simp only [J, Finset.mem_filter, Finset.mem_range, hj2s, true_and] + rw [hc.apply_eq_card (by omega), show j - 1 - 1 = j - 2 by omega] + exact Finset.card_le_card (Finset.filter_subset_filter _ (by simp)) + have hjI : a (j - 2) ∈ I := by + by_contra hjI + have hjIf := hjI + simp only [Finset.mem_filter, Finset.mem_range, hj2s, true_and, not_le, I, + Nat.lt_iff_add_one_le] at hjIf + have hjI' : a (j - 1) ≤ a (i - 1) := by + calc a (j - 1) ≤ #{u ∈ Finset.range j | a u = a (j - 2)} := + (Finset.mem_filter.mp hjJ).2 + _ = #{u ∈ Finset.range i ∪ Finset.Ico i j | a u = a (j - 2)} := by rw [hiju] + _ ≤ #{u ∈ Finset.range i | a u = a (j - 2)} + #{u ∈ Finset.Ico i j | a u = a (j - 2)} := by + rw [Finset.filter_union] + exact Finset.card_union_le _ _ + _ ≤ #{u ∈ Finset.range i | a u = a (j - 2)} + 1 := by + gcongr + exact hij1 _ (by rwa [Nat.lt_add_one_iff, ← Small] at hj2s) + _ ≤ a (i - 1) := hjIf + refine hjI (Finset.eq_of_subset_of_card_le (fun x hxI ↦ ?_) hIJc.symm.le ▸ hjJ) + simp only [Finset.mem_filter, I, J] at * + refine ⟨hxI.1, ?_⟩ + calc a (j - 1) ≤ a (i - 1) := hjI' + _ ≤ #{u ∈ Finset.range i | a u = x} := hxI.2 + _ ≤ #{u ∈ Finset.range j | a u = x} := + Finset.card_le_card (Finset.filter_subset_filter _ (by simp [hijlt.le])) + have hi1j1 : a (i - 1) + 1 ≤ a (j - 1) := by + calc a (i - 1) + 1 ≤ #{u ∈ Finset.range i | a u = a (j - 2)} + 1 := by + gcongr + simp only [Finset.mem_filter, I] at hjI + exact hjI.2 + _ ≤ #{u ∈ Finset.range i | a u = a (j - 2)} + #{u ∈ Finset.Ico i j | a u = a (j - 2)} := by + gcongr + simp only [Finset.one_le_card] + refine ⟨j - 2, ?_⟩ + simp only [Finset.mem_filter, Finset.mem_Ico, and_true] + refine ⟨?_, by omega⟩ + by_contra hj + have hj' : j = i + 1 := by omega + subst hj' + exact hc.not_small_of_big (hc.apply_add_one_big_of_apply_small_of_N'_le his (by omega)) + (hijeq ▸ his) + _ = #({u ∈ Finset.range i | a u = a (j - 2)} ∪ {u ∈ Finset.Ico i j | a u = a (j - 2)}) := by + refine (Finset.card_union_of_disjoint ?_).symm + simp only [Finset.disjoint_iff_ne, Finset.mem_filter, Finset.mem_range, Finset.mem_Ico, + and_imp] + rintro t hti - u hiu - - + omega + _ = #{u ∈ Finset.range j | a u = a (j - 2)} := by + rw [← Finset.filter_union, hiju] + _ = a (j - 1) := by + rw [hc.apply_eq_card (show N < j - 1 by omega)] + congr 1 + ext t + simp only [Finset.mem_filter, Finset.mem_range] + refine ⟨fun ⟨htj, htj'⟩ ↦ ⟨?_, by convert htj' using 1⟩, + fun ⟨htj, htj'⟩ ↦ ⟨by omega, by convert htj' using 1⟩⟩ + by_contra htj'' + have ht1 : t = j - 1 := by omega + subst ht1 + exact hc.not_small_of_big (htj' ▸ hc.apply_sub_one_big_of_apply_small_of_N'_lt + (hijeq ▸ his) (by omega)) (hc.apply_sub_two_small_of_apply_small_of_N'_lt + (hijeq ▸ his) (by omega)) + have hIJ : I = J := by + refine (Finset.eq_of_subset_of_card_le (Finset.subset_iff.mp fun x hxJ ↦ ?_) hIJc.le).symm + simp only [Finset.mem_filter, Finset.mem_range, I, J, Nat.lt_add_one_iff] at * + refine ⟨hxJ.1, (add_le_add_iff_right 1).mp ?_⟩ + calc a (i - 1) + 1 ≤ a (j - 1) := hi1j1 + _ ≤ #{u ∈ Finset.range j | a u = x} := hxJ.2 + _ = #({u ∈ Finset.range i | a u = x} ∪ {u ∈ Finset.Ico i j | a u = x}) := by + rw [← Finset.filter_union, hiju] + _ ≤ #{u ∈ Finset.range i | a u = x} + #{u ∈ Finset.Ico i j | a u = x} := + Finset.card_union_le _ _ + _ ≤ #{u ∈ Finset.range i | a u = x} + 1 := by + gcongr + exact hij1 _ hxJ.1 + simp only [hIJ, J, Finset.mem_filter] at hiI + have hiI' := hi1j1.trans hiI.2 + rw [hc.apply_eq_card (by omega), show i - 1 - 1 = i - 2 by omega, Nat.add_one_le_iff, + ← not_le] at hiI' + rcases Finset.not_subset.mp (mt Finset.card_le_card hiI') with ⟨t, htj, hti⟩ + simp only [Finset.mem_filter, Finset.mem_range] at htj hti + simp only [htj.2, and_true, not_lt, tsub_le_iff_right] at hti + refine ⟨t, Finset.mem_Ico.mpr ⟨?_, htj.1⟩, htj.2.symm⟩ + by_contra + have hti' : t = i - 1 := by omega + subst hti' + exact hc.not_small_of_big (hc.apply_sub_one_big_of_apply_small_of_N'_lt his (by omega)) (htj.2 ▸ + (hc.apply_sub_two_small_of_apply_small_of_N'_lt his (by omega))) + +variable (a) + +/-- The indices, minus `n`, of small numbers appearing for the second or subsequent time at or +after `a n`. -/ +def pSet (n : ℕ) : Set ℕ := {t | ∃ i ∈ Finset.Ico n (n + t), Small a (a i) ∧ a (n + t) = a i} + +/-- The index, minus `n`, of the second appearance of the first small number to appear twice at +or after `a n`. This is only used for small `a n` with `N' a N + 2 < n`. -/ +noncomputable def p (n : ℕ) : ℕ := sInf (pSet a n) + +variable {a} + +lemma nonempty_pSet (n : ℕ) : (pSet a n).Nonempty := by + rcases hc.infinite_setOf_apply_eq_one.exists_gt n with ⟨i, hi1, hni⟩ + rcases hc.infinite_setOf_apply_eq_one.exists_gt i with ⟨j, hj1, hij⟩ + refine ⟨j - n, ?_⟩ + simp only [pSet, Finset.mem_Ico, Set.mem_setOf_eq] + exact ⟨i, ⟨hni.le, by omega⟩, hi1 ▸ ⟨hc.small_one, hj1 ▸ (by congr; omega)⟩⟩ + +lemma exists_mem_Ico_small_and_apply_add_p_eq (n : ℕ) : + ∃ i ∈ Finset.Ico n (n + p a n), Small a (a i) ∧ a (n + p a n) = a i := + csInf_mem (hc.nonempty_pSet _) + +lemma p_pos (n : ℕ) : 0 < p a n := by + by_contra! h + have hn := hc.exists_mem_Ico_small_and_apply_add_p_eq n + simp [h] at hn + +lemma card_filter_apply_eq_Ico_add_p_le_one (n : ℕ) {j : ℕ} (hjs : Small a j) : + #{i ∈ Finset.Ico n (n + p a n) | a i = j} ≤ 1 := by + have h : IsLeast (pSet a n) (p a n) := isLeast_csInf (hc.nonempty_pSet n) + simp only [IsLeast, pSet, Set.mem_setOf_eq, mem_lowerBounds, forall_exists_index, and_imp, + Finset.mem_Ico] at h + rw [Finset.card_le_one_iff] + intro x y hx hy + simp only [Finset.mem_filter, Finset.mem_Ico] at hx hy + rcases lt_trichotomy x y with hxy | rfl | hxy + · replace h := h.2 (y - n) x hx.1.1 (by omega) (hx.2 ▸ hjs) + rw [show n + (y - n) = y by omega, hx.2, hy.2] at h + omega + · rfl + · replace h := h.2 (x - n) y hy.1.1 (by omega) (hy.2 ▸ hjs) + rw [show n + (x - n) = x by omega, hx.2, hy.2] at h + omega + +lemma apply_add_p_eq {n : ℕ} (hn : N' a N + 2 < n) (hs : Small a (a n)) : a (n + p a n) = a n := by + rcases hc.exists_mem_Ico_small_and_apply_add_p_eq n with ⟨i, hiIco, his, hin⟩ + suffices i = n by rw [hin, this] + simp only [Finset.mem_Ico] at hiIco + by_contra hin' + have hf (t : ℕ) (hts : Small a t) : #{x ∈ Finset.Ico i (n + p a n) | a x = t} ≤ 1 := + calc #{x ∈ Finset.Ico i (n + p a n) | a x = t} ≤ #{x ∈ Finset.Ico n (n + p a n) | a x = t} := + Finset.card_le_card (Finset.filter_subset_filter _ (Finset.Ico_subset_Ico hiIco.1 le_rfl)) + _ ≤ 1 := hc.card_filter_apply_eq_Ico_add_p_le_one _ hts + obtain ⟨t, hti, hi2t⟩ := hc.exists_apply_sub_two_eq_of_apply_eq (j := n + p a n) (by omega) + (by omega) his hin.symm hf + have h1 := hc.card_filter_apply_eq_Ico_add_p_le_one n + (hi2t ▸ hc.apply_sub_two_small_of_apply_small_of_N'_lt his (by omega)) + revert h1 + simp only [imp_false, not_le, Finset.one_lt_card_iff, Finset.mem_filter, Finset.mem_Ico, ne_eq, + exists_and_left] + simp only [Finset.mem_Ico] at hti + refine ⟨i - 2, ⟨⟨?_, by omega⟩, hi2t⟩, t, by omega⟩ + by_contra hi2 + have hi1 : n = i - 1 := by omega + subst hi1 + exact hc.not_small_of_big (hc.apply_sub_one_big_of_apply_small_of_N'_lt his (by omega)) hs + +lemma even_p {n : ℕ} (hn : N' a N + 2 < n) (hs : Small a (a n)) : Even (p a n) := by + have hna : n = N' a N + (n - (N' a N)) := by omega + have hs' := hc.apply_add_p_eq hn hs ▸ hs + rw [hna, hc.small_apply_N'_add_iff_even] at hs + nth_rw 1 [hna] at hs' + rw [add_assoc, hc.small_apply_N'_add_iff_even] at hs' + simpa [Nat.even_add, hs] using hs' + +lemma p_le_two_mul_k {n : ℕ} (hn : N' a N + 2 < n) (hs : Small a (a n)) : p a n ≤ 2 * k a := by + by_contra hlt + obtain ⟨x, hx, y, hy, hxyne, hxy⟩ : ∃ x ∈ Finset.range (k a + 1), ∃ y ∈ Finset.range (k a + 1), + x ≠ y ∧ a (n + 2 * x) = a (n + 2 * y) := by + convert Finset.exists_ne_map_eq_of_card_lt_of_maps_to (t := Finset.Icc 1 (k a)) ?_ ?_ + · simp + · rintro i - + simp [Finset.mem_Icc, Nat.lt_add_one_iff] + rw [← Small, hc.small_apply_add_two_mul_iff_small i (by omega)] + simp [hs, hc.one_le_apply] + have hs' : Small a (a (n + 2 * x)) := by rwa [hc.small_apply_add_two_mul_iff_small x (by omega)] + have hj := hc.card_filter_apply_eq_Ico_add_p_le_one n hs' + revert hj + simp only [imp_false, not_le, Finset.one_lt_card_iff, Finset.mem_filter, Finset.mem_Ico, ne_eq, + exists_and_left] + simp only [Finset.mem_range] at hx hy + exact ⟨n + 2 * x, by omega, n + 2 * y, by omega⟩ + +lemma p_apply_sub_two_le_p_apply {n : ℕ} (hn : N' a N + 4 < n) (hs : Small a (a n)) : + p a (n - 2) ≤ p a n := by + obtain ⟨t, hti, _⟩ := hc.exists_apply_sub_two_eq_of_apply_eq (j := n + p a n) (by omega) + ((lt_add_iff_pos_right n).mpr (hc.p_pos n)) hs + (hc.apply_add_p_eq (by omega) hs).symm (fun _ ↦ hc.card_filter_apply_eq_Ico_add_p_le_one _) + by_contra + have hn2 := (hc.apply_sub_two_small_of_apply_small_of_N'_lt hs (by omega)) + have : p a n ≤ p a (n - 2) - 2 := by + obtain ⟨_, _⟩ := hc.even_p (by omega) hs + obtain ⟨_, _⟩ := hc.even_p (by omega) hn2 + omega + have h := hc.card_filter_apply_eq_Ico_add_p_le_one (n - 2) hn2 + revert h + simp only [imp_false, not_le, Finset.one_lt_card_iff, Finset.mem_filter, Finset.mem_Ico, + ne_eq, exists_and_left] + simp only [Finset.mem_Ico] at hti + exact ⟨n - 2, ⟨⟨le_rfl, by omega⟩, rfl⟩, t, by omega⟩ + +lemma p_apply_le_p_apply_add_two {n : ℕ} (hn : N' a N + 2 < n) (hs : Small a (a n)) : + p a n ≤ p a (n + 2) := + hc.p_apply_sub_two_le_p_apply (n := n + 2) (by omega) + (hc.apply_add_two_small_of_apply_small_of_N'_le hs (by omega)) + +variable (a N) + +lemma exists_p_eq : ∃ b c, ∀ n, b < n → p a (N' a N + 2 * n) = c := by + let c : ℕ := sSup (Set.range (fun i ↦ p a (N' a N + 2 * (2 + i)))) + have hk : 2 * k a ∈ upperBounds (Set.range (fun i ↦ p a (N' a N + 2 * (2 + i)))) := by + simp only [mem_upperBounds, Set.mem_range, forall_exists_index, forall_apply_eq_imp_iff] + exact fun i ↦ hc.p_le_two_mul_k (by omega) (hc.small_apply_N'_add_iff_even.mpr (by simp)) + have hlec : ∀ j ∈ Set.range (fun i ↦ p a (N' a N + 2 * (2 + i))), j ≤ c := + fun _ hj ↦ le_csSup ⟨_, hk⟩ hj + obtain ⟨t, ht⟩ := Set.Nonempty.csSup_mem (Set.range_nonempty _) (BddAbove.finite ⟨2 * k a, hk⟩) + have heqc (u : ℕ) : p a (N' a N + 2 * (2 + t + u)) = c := by + induction u with + | zero => simpa using ht + | succ u ih => + refine le_antisymm ?_ (ih ▸ ?_) + · simp only [Set.mem_range, forall_exists_index, forall_apply_eq_imp_iff] at hlec + exact add_assoc _ _ (u + 1) ▸ hlec (t + (u + 1)) + · have hs : Small a (a (N' a N + 2 * (2 + t + u))) := by + rw [hc.small_apply_N'_add_iff_even] + simp + convert hc.p_apply_le_p_apply_add_two (by omega) hs using 1 + refine ⟨1 + t, c, fun n hn ↦ ?_⟩ + rw [show n = 2 + t + (n - (2 + t)) by omega] + exact heqc _ + +lemma exists_a_apply_add_eq : ∃ b c, 0 < c ∧ ∀ n, b < n → + a (N' a N + 2 * n + 2 * c) = a (N' a N + 2 * n) := by + obtain ⟨b, c', hbc'⟩ := hc.exists_p_eq a N + have hs (n : ℕ) : Small a (a (N' a N + 2 * n)) := hc.small_apply_N'_add_iff_even.mpr (by simp) + refine ⟨b + 2, c' / 2, ?_, fun n hbn ↦ hbc' n (by omega) ▸ ?_⟩ + · have := hbc' (b + 2) (by omega) + have := hc.p_pos (N' a N + 2 * (b + 2)) + rcases hc.even_p (by omega) (hs (b + 2)) with ⟨_, _⟩ + omega + · convert hc.apply_add_p_eq (by omega) (hs n) using 3 + rcases hc.even_p (by omega) (hs n) with ⟨_, ht⟩ + simp [ht, ← two_mul] + +variable {a N} + +end Condition + +theorem result {a : ℕ → ℕ} {N : ℕ} (h : Condition a N) : + EventuallyPeriodic (fun i ↦ a (2 * i)) ∨ EventuallyPeriodic (fun i ↦ a (2 * i + 1)) := by + obtain ⟨b, c, hc, hbc⟩ := h.exists_a_apply_add_eq a N + obtain ⟨t, _⟩ | ⟨t, _⟩ := Nat.even_or_odd (Condition.N' a N) + · refine .inl ⟨c, Condition.N' a N / 2 + b + 1, hc, fun m hm ↦ ?_⟩ + convert hbc (m - t) (by omega) using 1 <;> dsimp only <;> congr <;> omega + · refine .inr ⟨c, Condition.N' a N / 2 + b + 1, hc, fun m hm ↦ ?_⟩ + convert hbc (m - t) (by omega) using 1 <;> dsimp only <;> congr 1 <;> omega + +end Imo2024Q3 From 8bec6200deecb59db5cd3c348305e53fa017e5bd Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Thu, 23 Jan 2025 07:01:36 +0000 Subject: [PATCH 441/681] feat(Order): relate chains to antichains (#20756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A set which is a chain and an antichain is subsingleton. As a result, the intersection of a chain and antichain is subsingleton. Useful from the disproof of the Aharoni–Korman conjecture, https://github.com/leanprover-community/mathlib4/pull/20082. I believe the large import here is acceptable, as `IsChain` and `IsAntichain` need to be related to each other somewhere, but there is not much to say about both (as this PR shows). As such, making a third file specifically for these seems unnecessary, and putting these in `Order.Chain` results in a larger import change. --- Mathlib/Order/Antichain.lean | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Mathlib/Order/Antichain.lean b/Mathlib/Order/Antichain.lean index df46cd2e7a882..307d08ef8455c 100644 --- a/Mathlib/Order/Antichain.lean +++ b/Mathlib/Order/Antichain.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Set.Pairwise.Basic import Mathlib.Order.Bounds.Basic import Mathlib.Order.Directed import Mathlib.Order.Hom.Set +import Mathlib.Order.Chain /-! # Antichains @@ -172,6 +173,28 @@ theorem isAntichain_singleton (a : α) (r : α → α → Prop) : IsAntichain r theorem Set.Subsingleton.isAntichain (hs : s.Subsingleton) (r : α → α → Prop) : IsAntichain r s := hs.pairwise _ +/-- A set which is simultaneously a chain and antichain is subsingleton. -/ +lemma subsingleton_of_isChain_of_isAntichain (hs : IsChain r s) (ht : IsAntichain r s) : + s.Subsingleton := by + intro x hx y hy + by_contra! hne + cases hs hx hy hne with + | inl h => exact ht hx hy hne h + | inr h => exact ht hy hx hne.symm h + +lemma isChain_and_isAntichain_iff_subsingleton : IsChain r s ∧ IsAntichain r s ↔ s.Subsingleton := + ⟨fun h ↦ subsingleton_of_isChain_of_isAntichain h.1 h.2, fun h ↦ ⟨h.isChain, h.isAntichain _⟩⟩ + +/-- The intersection of a chain and an antichain is subsingleton. -/ +lemma inter_subsingleton_of_isChain_of_isAntichain (hs : IsChain r s) (ht : IsAntichain r t) : + (s ∩ t).Subsingleton := + subsingleton_of_isChain_of_isAntichain (hs.mono (by simp)) (ht.subset (by simp)) + +/-- The intersection of an antichain and a chain is subsingleton. -/ +lemma inter_subsingleton_of_isAntichain_of_isChain (hs : IsAntichain r s) (ht : IsChain r t) : + (s ∩ t).Subsingleton := + inter_comm _ _ ▸ inter_subsingleton_of_isChain_of_isAntichain ht hs + section Preorder variable [Preorder α] From 8eba7f69470d44527dd30de0fd873aa161337401 Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 23 Jan 2025 07:42:05 +0000 Subject: [PATCH 442/681] chore(shake): shake reports an invalid config file (#20927) If the file `scripts/noshake.json` is invalid, `lake exe shake` may report various "fixes". This PR makes it report that `scripts/noshake.json` is invalid. [Reported on Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/bizarre.20lake.20shake.20errors) --- Shake/Main.lean | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Shake/Main.lean b/Shake/Main.lean index 8d5dcb0265572..6652df137ecb7 100644 --- a/Shake/Main.lean +++ b/Shake/Main.lean @@ -458,14 +458,19 @@ def main (args : List String) : IO UInt32 := do else pure none -- Read the config file - let cfg ← if let some file := cfgFile then + -- `isValidCfgFile` is `false` if and only if the config file is present and invalid. + let (cfg, isValidCfgFile) ← if let some file := cfgFile then try - IO.ofExcept (Json.parse (← IO.FS.readFile file) >>= fromJson? (α := ShakeCfg)) + pure (← IO.ofExcept (Json.parse (← IO.FS.readFile file) >>= fromJson? (α := ShakeCfg)), true) catch e => + -- The `cfgFile` is invalid, so we print the error and return `isValidCfgFile = false`. println! "{e.toString}" - pure {} - else pure {} - + pure ({}, false) + else pure ({}, true) + if !isValidCfgFile then + IO.println s!"Invalid config file '{cfgFile.get!}'" + IO.Process.exit 1 + else -- the list of root modules let mods := if args.mods.isEmpty then #[`Mathlib] else args.mods -- Only submodules of `pkg` will be edited or have info reported on them From a6e1dfdd885a3276e1184903c099d7d9ac8b4024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 23 Jan 2025 07:42:06 +0000 Subject: [PATCH 443/681] feat: more lemmas for `enorm` (#20966) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These follow the existing `norm` and `nnnorm`. The large import comes from the fact that we need to import `Topology.Instances.ENNReal` to state `continuous_enorm : Continuous (‖·‖ₑ)`. --- .../Analysis/InnerProductSpace/NormPow.lean | 6 ++ Mathlib/Analysis/Normed/Field/Basic.lean | 38 ++++---- Mathlib/Analysis/Normed/Group/Basic.lean | 96 +++++++++++++++++-- Mathlib/Analysis/Normed/Group/Completion.lean | 4 + .../Analysis/Normed/Group/Constructions.lean | 3 + Mathlib/Analysis/Normed/MulAction.lean | 8 +- .../NormedSpace/IndicatorFunction.lean | 4 + Mathlib/Analysis/NormedSpace/Int.lean | 2 + .../NormedSpace/OperatorNorm/NNNorm.lean | 4 +- .../Analysis/SpecialFunctions/Pow/NNReal.lean | 3 + 10 files changed, 137 insertions(+), 31 deletions(-) diff --git a/Mathlib/Analysis/InnerProductSpace/NormPow.lean b/Mathlib/Analysis/InnerProductSpace/NormPow.lean index 1d53811b6834c..78320b9555e7f 100644 --- a/Mathlib/Analysis/InnerProductSpace/NormPow.lean +++ b/Mathlib/Analysis/InnerProductSpace/NormPow.lean @@ -98,6 +98,12 @@ theorem nnnorm_fderiv_norm_rpow_le {f : F → E} (hf : Differentiable ℝ f) ‖fderiv ℝ (fun x ↦ ‖f x‖ ^ (p : ℝ)) x‖₊ ≤ p * ‖f x‖₊ ^ ((p : ℝ) - 1) * ‖fderiv ℝ f x‖₊ := norm_fderiv_norm_rpow_le hf hp +lemma enorm_fderiv_norm_rpow_le {f : F → E} (hf : Differentiable ℝ f) + {x : F} {p : ℝ≥0} (hp : 1 < p) : + ‖fderiv ℝ (fun x ↦ ‖f x‖ ^ (p : ℝ)) x‖ₑ ≤ p * ‖f x‖ₑ ^ ((p : ℝ) - 1) * ‖fderiv ℝ f x‖ₑ := by + simpa [enorm, ← ENNReal.coe_rpow_of_nonneg _ (sub_nonneg.2 <| NNReal.one_le_coe.2 hp.le), + ← ENNReal.coe_mul] using nnnorm_fderiv_norm_rpow_le hf hp + theorem contDiff_norm_rpow {p : ℝ} (hp : 1 < p) : ContDiff ℝ 1 (fun x : E ↦ ‖x‖ ^ p) := by rw [contDiff_one_iff_fderiv] refine ⟨fun x ↦ hasFDerivAt_norm_rpow x hp |>.differentiableAt, ?_⟩ diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index 0bc9524cf8635..97a91622891e1 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -31,7 +31,7 @@ assert_not_exists AddChar comap_norm_atTop DilationEquiv Finset.sup_mul_le_mul_s IsOfFinOrder Isometry.norm_map_of_map_one NNReal.isOpen_Ico_zero Rat.norm_cast_real RestrictScalars -variable {α : Type*} {β : Type*} {ι : Type*} +variable {G α β ι : Type*} open Filter open scoped Topology NNReal @@ -167,14 +167,17 @@ export NormOneClass (norm_one) attribute [simp] norm_one -@[simp] -theorem nnnorm_one [SeminormedAddCommGroup α] [One α] [NormOneClass α] : ‖(1 : α)‖₊ = 1 := - NNReal.eq norm_one +section SeminormedAddCommGroup +variable [SeminormedAddCommGroup G] [One G] [NormOneClass G] + +@[simp] lemma nnnorm_one : ‖(1 : G)‖₊ = 1 := NNReal.eq norm_one +@[simp] lemma enorm_one : ‖(1 : G)‖ₑ = 1 := by simp [enorm] -theorem NormOneClass.nontrivial (α : Type*) [SeminormedAddCommGroup α] [One α] [NormOneClass α] : - Nontrivial α := +theorem NormOneClass.nontrivial : Nontrivial G := nontrivial_of_ne 0 1 <| ne_of_apply_ne norm <| by simp +end SeminormedAddCommGroup + -- see Note [lower instance priority] instance (priority := 100) NonUnitalSeminormedCommRing.toNonUnitalCommRing [β : NonUnitalSeminormedCommRing α] : NonUnitalCommRing α := @@ -646,9 +649,8 @@ instance isAbsoluteValue_norm : IsAbsoluteValue (norm : α → ℝ) where abv_add' := norm_add_le abv_mul' := norm_mul -@[simp] -theorem nnnorm_mul (a b : α) : ‖a * b‖₊ = ‖a‖₊ * ‖b‖₊ := - NNReal.eq <| norm_mul a b +@[simp] lemma nnnorm_mul (a b : α) : ‖a * b‖₊ = ‖a‖₊ * ‖b‖₊ := NNReal.eq <| norm_mul a b +@[simp] lemma enorm_mul (a b : α) : ‖a * b‖ₑ = ‖a‖ₑ * ‖b‖ₑ := by simp [enorm] /-- `norm` as a `MonoidWithZeroHom`. -/ @[simps] @@ -674,6 +676,8 @@ theorem norm_pow (a : α) : ∀ n : ℕ, ‖a ^ n‖ = ‖a‖ ^ n := theorem nnnorm_pow (a : α) (n : ℕ) : ‖a ^ n‖₊ = ‖a‖₊ ^ n := (nnnormHom.toMonoidHom : α →* ℝ≥0).map_pow a n +@[simp] lemma enorm_pow (a : α) (n : ℕ) : ‖a ^ n‖ₑ = ‖a‖ₑ ^ n := by simp [enorm] + protected theorem List.norm_prod (l : List α) : ‖l.prod‖ = (l.map norm).prod := map_list_prod (normHom.toMonoidHom : α →* ℝ) _ @@ -696,6 +700,9 @@ theorem norm_inv (a : α) : ‖a⁻¹‖ = ‖a‖⁻¹ := theorem nnnorm_inv (a : α) : ‖a⁻¹‖₊ = ‖a‖₊⁻¹ := NNReal.eq <| by simp +@[simp] +lemma enorm_inv {a : α} (ha : a ≠ 0) : ‖a⁻¹‖ₑ = ‖a‖ₑ⁻¹ := by simp [enorm, ENNReal.coe_inv, ha] + @[simp] theorem norm_zpow : ∀ (a : α) (n : ℤ), ‖a ^ n‖ = ‖a‖ ^ n := map_zpow₀ (normHom : α →*₀ ℝ) @@ -923,20 +930,11 @@ open NNReal theorem norm_eq (x : ℝ≥0) : ‖(x : ℝ)‖ = x := by rw [Real.norm_eq_abs, x.abs_eq] -@[simp] -theorem nnnorm_eq (x : ℝ≥0) : ‖(x : ℝ)‖₊ = x := - NNReal.eq <| Real.norm_of_nonneg x.2 +@[simp] lemma nnnorm_eq (x : ℝ≥0) : ‖(x : ℝ)‖₊ = x := by ext; simp [nnnorm] +@[simp] lemma enorm_eq (x : ℝ≥0) : ‖(x : ℝ)‖ₑ = x := by simp [enorm] end NNReal -@[simp 1001] -- Porting note: increase priority so that the LHS doesn't simplify -theorem norm_norm [SeminormedAddCommGroup α] (x : α) : ‖‖x‖‖ = ‖x‖ := - Real.norm_of_nonneg (norm_nonneg _) - -@[simp] -theorem nnnorm_norm [SeminormedAddCommGroup α] (a : α) : ‖‖a‖‖₊ = ‖a‖₊ := by - rw [Real.nnnorm_of_nonneg (norm_nonneg a)]; rfl - /-- A restatement of `MetricSpace.tendsto_atTop` in terms of the norm. -/ theorem NormedAddCommGroup.tendsto_atTop [Nonempty α] [Preorder α] [IsDirected α (· ≤ ·)] {β : Type*} [SeminormedAddCommGroup β] {f : α → β} {b : β} : diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index 79417c8b0f215..0b033f8d12618 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -6,6 +6,7 @@ Authors: Patrick Massot, Johannes Hölzl, Yaël Dillies import Mathlib.Algebra.CharP.Defs import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.Analysis.Normed.Group.Seminorm +import Mathlib.Topology.Instances.ENNReal.Defs import Mathlib.Topology.Metrizable.Uniformity import Mathlib.Topology.Sequences @@ -77,6 +78,23 @@ export ENorm (enorm) @[inherit_doc] notation "‖" e "‖₊" => nnnorm e @[inherit_doc] notation "‖" e "‖ₑ" => enorm e +section ENorm +variable {E : Type*} [NNNorm E] {x : E} {r : ℝ≥0} + +instance NNNorm.toENorm : ENorm E where enorm := (‖·‖₊ : E → ℝ≥0∞) + +lemma enorm_eq_nnnorm (x : E) : ‖x‖ₑ = ‖x‖₊ := rfl + +@[simp, norm_cast] lemma coe_le_enorm : r ≤ ‖x‖ₑ ↔ r ≤ ‖x‖₊ := by simp [enorm] +@[simp, norm_cast] lemma enorm_le_coe : ‖x‖ₑ ≤ r ↔ ‖x‖₊ ≤ r := by simp [enorm] +@[simp, norm_cast] lemma coe_lt_enorm : r < ‖x‖ₑ ↔ r < ‖x‖₊ := by simp [enorm] +@[simp, norm_cast] lemma enorm_lt_coe : ‖x‖ₑ < r ↔ ‖x‖₊ < r := by simp [enorm] + +@[simp] lemma enorm_ne_top : ‖x‖ₑ ≠ ∞ := by simp [enorm] +@[simp] lemma enorm_lt_top : ‖x‖ₑ < ∞ := by simp [enorm] + +end ENorm + /-- A seminormed group is an additive group endowed with a norm for which `dist x y = ‖x - y‖` defines a pseudometric space structure. -/ class SeminormedAddGroup (E : Type*) extends Norm E, AddGroup E, PseudoMetricSpace E where @@ -651,6 +669,13 @@ theorem coe_comp_nnnorm' : (toReal : ℝ≥0 → ℝ) ∘ (nnnorm : E → ℝ≥ theorem norm_toNNReal' : ‖a‖.toNNReal = ‖a‖₊ := @Real.toNNReal_coe ‖a‖₊ +@[to_additive toReal_enorm] +lemma toReal_enorm' (x : E) : ‖x‖ₑ.toReal = ‖x‖ := by simp [enorm] + +@[to_additive ofReal_norm] +lemma ofReal_norm' (x : E) : .ofReal ‖x‖ = ‖x‖ₑ := by + simp [enorm, ENNReal.ofReal, Real.toNNReal, nnnorm] + @[to_additive] theorem nndist_eq_nnnorm_div (a b : E) : nndist a b = ‖a / b‖₊ := NNReal.eq <| dist_eq_norm_div _ _ @@ -677,6 +702,10 @@ theorem ne_one_of_nnnorm_ne_zero {a : E} : ‖a‖₊ ≠ 0 → a ≠ 1 := theorem nnnorm_mul_le' (a b : E) : ‖a * b‖₊ ≤ ‖a‖₊ + ‖b‖₊ := NNReal.coe_le_coe.1 <| norm_mul_le' a b +@[to_additive enorm_add_le] +lemma enorm_mul_le' (a b : E) : ‖a * b‖ₑ ≤ ‖a‖ₑ + ‖b‖ₑ := by + simpa [enorm, ← ENNReal.coe_add] using nnnorm_mul_le' a b + @[to_additive norm_nsmul_le] lemma norm_pow_le_mul_norm : ∀ {n : ℕ}, ‖a ^ n‖ ≤ n * ‖a‖ | 0 => by simp @@ -690,6 +719,9 @@ lemma nnnorm_pow_le_mul_norm {n : ℕ} : ‖a ^ n‖₊ ≤ n * ‖a‖₊ := by theorem nnnorm_inv' (a : E) : ‖a⁻¹‖₊ = ‖a‖₊ := NNReal.eq <| norm_inv' a +@[to_additive (attr := simp) enorm_neg] +lemma enorm_inv' (a : E) : ‖a⁻¹‖ₑ = ‖a‖ₑ := by simp [enorm] + @[to_additive (attr := simp) nnnorm_abs_zsmul] theorem nnnorm_zpow_abs (a : E) (n : ℤ) : ‖a ^ |n|‖₊ = ‖a ^ n‖₊ := NNReal.eq <| norm_zpow_abs a n @@ -723,6 +755,10 @@ theorem nndist_mulIndicator (s t : Set α) (f : α → E) (x : α) : theorem nnnorm_div_le (a b : E) : ‖a / b‖₊ ≤ ‖a‖₊ + ‖b‖₊ := NNReal.coe_le_coe.1 <| norm_div_le _ _ +@[to_additive] +lemma enorm_div_le : ‖a / b‖ₑ ≤ ‖a‖ₑ + ‖b‖ₑ := by + simpa [enorm, ← ENNReal.coe_add] using nnnorm_div_le a b + @[to_additive nndist_nnnorm_nnnorm_le] theorem nndist_nnnorm_nnnorm_le' (a b : E) : nndist ‖a‖₊ ‖b‖₊ ≤ ‖a / b‖₊ := NNReal.coe_le_coe.1 <| dist_norm_norm_le' a b @@ -793,19 +829,16 @@ theorem mem_emetric_ball_one_iff {r : ℝ≥0∞} : a ∈ EMetric.ball (1 : E) r end NNNorm -section ENNNorm - -instance {E : Type*} [NNNorm E] : ENorm E where - enorm := (‖·‖₊ : E → ℝ≥0∞) +section ENorm -lemma enorm_eq_nnnorm {E : Type*} [NNNorm E] {x : E} : ‖x‖ₑ = ‖x‖₊ := rfl +@[to_additive (attr := simp) enorm_zero] lemma enorm_one' : ‖(1 : E)‖ₑ = 0 := by simp [enorm] instance : ENorm ℝ≥0∞ where enorm x := x @[simp] lemma enorm_eq_self (x : ℝ≥0∞) : ‖x‖ₑ = x := rfl -end ENNNorm +end ENorm @[to_additive] theorem tendsto_iff_norm_div_tendsto_zero {f : α → E} {a : Filter α} {b : E} : @@ -870,6 +903,10 @@ theorem continuous_norm' : Continuous fun a : E => ‖a‖ := by theorem continuous_nnnorm' : Continuous fun a : E => ‖a‖₊ := continuous_norm'.subtype_mk _ +@[to_additive (attr := continuity) continuous_enorm] +lemma continuous_enorm' : Continuous fun a : E ↦ ‖a‖ₑ := + ENNReal.isOpenEmbedding_coe.continuous.comp continuous_nnnorm' + set_option linter.docPrime false in @[to_additive Inseparable.norm_eq_norm] theorem Inseparable.norm_eq_norm' {u v : E} (h : Inseparable u v) : ‖u‖ = ‖v‖ := @@ -900,11 +937,15 @@ theorem Filter.Tendsto.norm' (h : Tendsto f l (𝓝 a)) : Tendsto (fun x => ‖f theorem Filter.Tendsto.nnnorm' (h : Tendsto f l (𝓝 a)) : Tendsto (fun x => ‖f x‖₊) l (𝓝 ‖a‖₊) := Tendsto.comp continuous_nnnorm'.continuousAt h +@[to_additive Filter.Tendsto.enorm] +lemma Filter.Tendsto.enorm' (h : Tendsto f l (𝓝 a)) : Tendsto (‖f ·‖ₑ) l (𝓝 ‖a‖ₑ) := + .comp continuous_enorm'.continuousAt h + end section -variable [TopologicalSpace α] {f : α → E} +variable [TopologicalSpace α] {f : α → E} {s : Set α} {a : α} @[to_additive (attr := fun_prop) Continuous.norm] theorem Continuous.norm' : Continuous f → Continuous fun x => ‖f x‖ := @@ -914,6 +955,9 @@ theorem Continuous.norm' : Continuous f → Continuous fun x => ‖f x‖ := theorem Continuous.nnnorm' : Continuous f → Continuous fun x => ‖f x‖₊ := continuous_nnnorm'.comp +@[to_additive (attr := fun_prop) Continuous.enorm] +lemma Continuous.enorm' : Continuous f → Continuous (‖f ·‖ₑ) := continuous_enorm'.comp + @[to_additive (attr := fun_prop) ContinuousAt.norm] theorem ContinuousAt.norm' {a : α} (h : ContinuousAt f a) : ContinuousAt (fun x => ‖f x‖) a := Tendsto.norm' h @@ -922,6 +966,9 @@ theorem ContinuousAt.norm' {a : α} (h : ContinuousAt f a) : ContinuousAt (fun x theorem ContinuousAt.nnnorm' {a : α} (h : ContinuousAt f a) : ContinuousAt (fun x => ‖f x‖₊) a := Tendsto.nnnorm' h +@[to_additive (attr := fun_prop) ContinuousAt.enorm] +lemma ContinuousAt.enorm' (h : ContinuousAt f a) : ContinuousAt (‖f ·‖ₑ) a := Tendsto.enorm' h + @[to_additive ContinuousWithinAt.norm] theorem ContinuousWithinAt.norm' {s : Set α} {a : α} (h : ContinuousWithinAt f s a) : ContinuousWithinAt (fun x => ‖f x‖) s a := @@ -932,6 +979,10 @@ theorem ContinuousWithinAt.nnnorm' {s : Set α} {a : α} (h : ContinuousWithinAt ContinuousWithinAt (fun x => ‖f x‖₊) s a := Tendsto.nnnorm' h +@[to_additive ContinuousWithinAt.enorm] +lemma ContinuousWithinAt.enorm' (h : ContinuousWithinAt f s a) : ContinuousWithinAt (‖f ·‖ₑ) s a := + Tendsto.enorm' h + @[to_additive (attr := fun_prop) ContinuousOn.norm] theorem ContinuousOn.norm' {s : Set α} (h : ContinuousOn f s) : ContinuousOn (fun x => ‖f x‖) s := fun x hx => (h x hx).norm' @@ -940,6 +991,10 @@ theorem ContinuousOn.norm' {s : Set α} (h : ContinuousOn f s) : ContinuousOn (f theorem ContinuousOn.nnnorm' {s : Set α} (h : ContinuousOn f s) : ContinuousOn (fun x => ‖f x‖₊) s := fun x hx => (h x hx).nnnorm' +@[to_additive (attr := fun_prop) ContinuousOn.enorm] +lemma ContinuousOn.enorm' (h : ContinuousOn f s) : ContinuousOn (‖f ·‖ₑ) s := + fun x hx => (h x hx).enorm' + end /-- If `‖y‖ → ∞`, then we can assume `y ≠ x` for any fixed `x`. -/ @@ -1235,6 +1290,7 @@ theorem le_norm_self (r : ℝ) : r ≤ ‖r‖ := @[simp 1100] lemma norm_natCast (n : ℕ) : ‖(n : ℝ)‖ = n := abs_of_nonneg n.cast_nonneg @[simp 1100] lemma nnnorm_natCast (n : ℕ) : ‖(n : ℝ)‖₊ = n := NNReal.eq <| norm_natCast _ +@[simp 1100] lemma enorm_natCast (n : ℕ) : ‖(n : ℝ)‖ₑ = n := by simp [enorm] @[deprecated (since := "2024-04-05")] alias norm_coe_nat := norm_natCast @[deprecated (since := "2024-04-05")] alias nnnorm_coe_nat := nnnorm_natCast @@ -1257,8 +1313,11 @@ lemma nnnorm_nnratCast (q : ℚ≥0) : ‖(q : ℝ)‖₊ = q := by simp [nnnorm theorem nnnorm_of_nonneg (hr : 0 ≤ r) : ‖r‖₊ = ⟨r, hr⟩ := NNReal.eq <| norm_of_nonneg hr -@[simp] -theorem nnnorm_abs (r : ℝ) : ‖|r|‖₊ = ‖r‖₊ := by simp [nnnorm] +lemma enorm_of_nonneg (hr : 0 ≤ r) : ‖r‖ₑ = .ofReal r := by + simp [enorm, nnnorm_of_nonneg hr, ENNReal.ofReal, toNNReal, hr] + +@[simp] lemma nnnorm_abs (r : ℝ) : ‖|r|‖₊ = ‖r‖₊ := by simp [nnnorm] +@[simp] lemma enorm_abs (r : ℝ) : ‖|r|‖ₑ = ‖r‖ₑ := by simp [enorm] theorem ennnorm_eq_ofReal (hr : 0 ≤ r) : (‖r‖₊ : ℝ≥0∞) = ENNReal.ofReal r := by rw [← ofReal_norm_eq_coe_nnnorm, norm_of_nonneg hr] @@ -1290,6 +1349,16 @@ instance : NNNorm ℝ≥0 where end NNReal + -- Porting note: increase priority so that the LHS doesn't simplify +@[to_additive (attr := simp 1001) norm_norm] +lemma norm_norm' (x : E) : ‖‖x‖‖ = ‖x‖ := Real.norm_of_nonneg (norm_nonneg' _) + +@[to_additive (attr := simp) nnnorm_norm] +lemma nnnorm_norm' (x : E) : ‖‖x‖‖₊ = ‖x‖₊ := by simp [nnnorm] + +@[to_additive (attr := simp) enorm_norm] +lemma enorm_norm' (x : E) : ‖‖x‖‖ₑ = ‖x‖ₑ := by simp [enorm] + end SeminormedCommGroup section NormedGroup @@ -1342,13 +1411,22 @@ theorem eq_one_or_nnnorm_pos (a : E) : a = 1 ∨ 0 < ‖a‖₊ := theorem nnnorm_eq_zero' : ‖a‖₊ = 0 ↔ a = 1 := by rw [← NNReal.coe_eq_zero, coe_nnnorm', norm_eq_zero'] +@[to_additive (attr := simp) enorm_eq_zero] +lemma enorm_eq_zero' : ‖a‖ₑ = 0 ↔ a = 1 := by simp [enorm] + @[to_additive nnnorm_ne_zero_iff] theorem nnnorm_ne_zero_iff' : ‖a‖₊ ≠ 0 ↔ a ≠ 1 := nnnorm_eq_zero'.not +@[to_additive enorm_ne_zero] +lemma enorm_ne_zero' : ‖a‖ₑ ≠ 0 ↔ a ≠ 1 := enorm_eq_zero'.ne + @[to_additive (attr := simp) nnnorm_pos] lemma nnnorm_pos' : 0 < ‖a‖₊ ↔ a ≠ 1 := pos_iff_ne_zero.trans nnnorm_ne_zero_iff' +@[to_additive (attr := simp) enorm_pos] +lemma enorm_pos' : 0 < ‖a‖ₑ ↔ a ≠ 1 := pos_iff_ne_zero.trans enorm_ne_zero' + /-- See `tendsto_norm_one` for a version with full neighborhoods. -/ @[to_additive "See `tendsto_norm_zero` for a version with full neighborhoods."] lemma tendsto_norm_nhdsNE_one : Tendsto (norm : E → ℝ) (𝓝[≠] 1) (𝓝[>] 0) := diff --git a/Mathlib/Analysis/Normed/Group/Completion.lean b/Mathlib/Analysis/Normed/Group/Completion.lean index 1bdd796d8f4a9..20db58aa839b3 100644 --- a/Mathlib/Analysis/Normed/Group/Completion.lean +++ b/Mathlib/Analysis/Normed/Group/Completion.lean @@ -44,6 +44,10 @@ instance [SeminormedAddCommGroup E] : NormedAddCommGroup (Completion E) where theorem nnnorm_coe {E} [SeminormedAddCommGroup E] (x : E) : ‖(x : Completion E)‖₊ = ‖x‖₊ := by simp [nnnorm] +@[simp] +lemma enorm_coe {E} [SeminormedAddCommGroup E] (x : E) : ‖(x : Completion E)‖ₑ = ‖x‖ₑ := by + simp [enorm] + end Completion end UniformSpace diff --git a/Mathlib/Analysis/Normed/Group/Constructions.lean b/Mathlib/Analysis/Normed/Group/Constructions.lean index 5a2a7e261e62b..2fc6b8e143742 100644 --- a/Mathlib/Analysis/Normed/Group/Constructions.lean +++ b/Mathlib/Analysis/Normed/Group/Constructions.lean @@ -403,6 +403,9 @@ theorem Pi.nnnorm_single [DecidableEq ι] [∀ i, NormedAddCommGroup (π i)] {i simp simp [Pi.nnnorm_def, H, Pi.single_apply, Finset.sup_ite, Finset.filter_eq'] +lemma Pi.enorm_single [DecidableEq ι] [∀ i, NormedAddCommGroup (π i)] {i : ι} (y : π i) : + ‖Pi.single i y‖ₑ = ‖y‖ₑ := by simp [enorm, Pi.nnnorm_single] + theorem Pi.norm_single [DecidableEq ι] [∀ i, NormedAddCommGroup (π i)] {i : ι} (y : π i) : ‖Pi.single i y‖ = ‖y‖ := congr_arg Subtype.val <| Pi.nnnorm_single y diff --git a/Mathlib/Analysis/Normed/MulAction.lean b/Mathlib/Analysis/Normed/MulAction.lean index 2c9c706fdb6c1..48d51cde9e44f 100644 --- a/Mathlib/Analysis/Normed/MulAction.lean +++ b/Mathlib/Analysis/Normed/MulAction.lean @@ -23,7 +23,7 @@ variable {α β : Type*} section SeminormedAddGroup variable [SeminormedAddGroup α] [SeminormedAddGroup β] [SMulZeroClass α β] -variable [BoundedSMul α β] +variable [BoundedSMul α β] {r : α} {x : β} @[bound] theorem norm_smul_le (r : α) (x : β) : ‖r • x‖ ≤ ‖r‖ * ‖x‖ := by @@ -33,6 +33,10 @@ theorem norm_smul_le (r : α) (x : β) : ‖r • x‖ ≤ ‖r‖ * ‖x‖ := theorem nnnorm_smul_le (r : α) (x : β) : ‖r • x‖₊ ≤ ‖r‖₊ * ‖x‖₊ := norm_smul_le _ _ +@[bound] +lemma enorm_smul_le : ‖r • x‖ₑ ≤ ‖r‖ₑ * ‖x‖ₑ := by + simpa [enorm, ← ENNReal.coe_mul] using nnnorm_smul_le .. + theorem dist_smul_le (s : α) (x y : β) : dist (s • x) (s • y) ≤ ‖s‖ * dist x y := by simpa only [dist_eq_norm, sub_zero] using dist_smul_pair s x y @@ -91,6 +95,8 @@ theorem norm_smul (r : α) (x : β) : ‖r • x‖ = ‖r‖ * ‖x‖ := by theorem nnnorm_smul (r : α) (x : β) : ‖r • x‖₊ = ‖r‖₊ * ‖x‖₊ := NNReal.eq <| norm_smul r x +lemma enorm_smul (r : α) (x : β) : ‖r • x‖ₑ = ‖r‖ₑ * ‖x‖ₑ := by simp [enorm, nnnorm_smul] + end NormedDivisionRing section NormedDivisionRingModule diff --git a/Mathlib/Analysis/NormedSpace/IndicatorFunction.lean b/Mathlib/Analysis/NormedSpace/IndicatorFunction.lean index 2b4d9f5b4bd2d..22a5c81e03806 100644 --- a/Mathlib/Analysis/NormedSpace/IndicatorFunction.lean +++ b/Mathlib/Analysis/NormedSpace/IndicatorFunction.lean @@ -27,6 +27,10 @@ theorem nnnorm_indicator_eq_indicator_nnnorm : ‖indicator s f a‖₊ = indicator s (fun a => ‖f a‖₊) a := flip congr_fun a (indicator_comp_of_zero nnnorm_zero).symm +lemma enorm_indicator_eq_indicator_enorm : + ‖indicator s f a‖ₑ = indicator s (fun a => ‖f a‖ₑ) a := + flip congr_fun a (indicator_comp_of_zero enorm_zero).symm + theorem norm_indicator_le_of_subset (h : s ⊆ t) (f : α → E) (a : α) : ‖indicator s f a‖ ≤ ‖indicator t f a‖ := by simp only [norm_indicator_eq_indicator_norm] diff --git a/Mathlib/Analysis/NormedSpace/Int.lean b/Mathlib/Analysis/NormedSpace/Int.lean index b08f55039887a..d8a954c1320a1 100644 --- a/Mathlib/Analysis/NormedSpace/Int.lean +++ b/Mathlib/Analysis/NormedSpace/Int.lean @@ -30,6 +30,8 @@ theorem norm_coe_units (e : ℤˣ) : ‖(e : ℤ)‖ = 1 := by theorem nnnorm_natCast (n : ℕ) : ‖(n : ℤ)‖₊ = n := Real.nnnorm_natCast _ +@[simp] lemma enorm_natCast (n : ℕ) : ‖(n : ℤ)‖ₑ = n := Real.enorm_natCast _ + @[deprecated (since := "2024-04-05")] alias nnnorm_coe_nat := nnnorm_natCast @[simp] diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean index 018b01d78582b..58490a8265750 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean @@ -86,14 +86,16 @@ theorem opNNNorm_le_iff {f : E →SL[σ₁₂] F} {C : ℝ≥0} : ‖f‖₊ ≤ theorem isLeast_opNNNorm : IsLeast {C : ℝ≥0 | ∀ x, ‖f x‖₊ ≤ C * ‖x‖₊} ‖f‖₊ := by simpa only [← opNNNorm_le_iff] using isLeast_Ici - theorem opNNNorm_comp_le [RingHomIsometric σ₁₃] (f : E →SL[σ₁₂] F) : ‖h.comp f‖₊ ≤ ‖h‖₊ * ‖f‖₊ := opNorm_comp_le h f +lemma opENorm_comp_le [RingHomIsometric σ₁₃] (f : E →SL[σ₁₂] F) : ‖h.comp f‖ₑ ≤ ‖h‖ₑ * ‖f‖ₑ := by + simpa [enorm, ← ENNReal.coe_mul] using opNNNorm_comp_le h f theorem le_opNNNorm : ‖f x‖₊ ≤ ‖f‖₊ * ‖x‖₊ := f.le_opNorm x +lemma le_opENorm : ‖f x‖ₑ ≤ ‖f‖ₑ * ‖x‖ₑ := by dsimp [enorm]; exact mod_cast le_opNNNorm .. theorem nndist_le_opNNNorm (x y : E) : nndist (f x) (f y) ≤ ‖f‖₊ * nndist x y := dist_le_opNorm f x y diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean index cbe2f010c0703..3356da74c63dd 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean @@ -963,6 +963,9 @@ theorem rpow_left_surjective {x : ℝ} (hx : x ≠ 0) : Function.Surjective fun theorem rpow_left_bijective {x : ℝ} (hx : x ≠ 0) : Function.Bijective fun y : ℝ≥0∞ => y ^ x := ⟨rpow_left_injective hx, rpow_left_surjective hx⟩ +lemma _root_.Real.enorm_rpow_of_nonneg {x y : ℝ} (hx : 0 ≤ x) (hy : 0 ≤ y) : + ‖x ^ y‖ₑ = ‖x‖ₑ ^ y := by simp [enorm, nnnorm_rpow_of_nonneg hx, coe_rpow_of_nonneg _ hy] + end ENNReal -- Porting note(https://github.com/leanprover-community/mathlib4/issues/6038): restore From 3abd04bf8d3f266e93fbd9b01e9e1d6d865584b3 Mon Sep 17 00:00:00 2001 From: "Tristan F.-R." Date: Thu, 23 Jan 2025 08:42:05 +0000 Subject: [PATCH 444/681] chore(Algebra/GroupWithZero/Units/Basic): drop unnecessary porting note (#20975) rfl after simp_rw applied to the regular lean codebase in https://github.com/leanprover-community/mathlib4/pull/1096; the porting note is now outdated. Co-authored-by: Tristan F. --- Mathlib/Algebra/GroupWithZero/Units/Basic.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean index 9c876dd881321..c4108f058926d 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean @@ -196,7 +196,6 @@ figure out `p` when using `Units.exists0` from right to left. -/ theorem exists0' {p : ∀ g : G₀, g ≠ 0 → Prop} : (∃ (g : G₀) (hg : g ≠ 0), p g hg) ↔ ∃ g : G₀ˣ, p g g.ne_zero := Iff.trans (by simp_rw [val_mk0]) exists0.symm - -- Porting note: had to add the `rfl` @[simp] theorem exists_iff_ne_zero {p : G₀ → Prop} : (∃ u : G₀ˣ, p u) ↔ ∃ x ≠ 0, p x := by From 403e2d8df3749897887ba949b28aa1225d65709e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 23 Jan 2025 09:23:34 +0000 Subject: [PATCH 445/681] chore(MvPolynomial/Degrees): append `_le` in lemma names (#20294) The current names are incorrect. --- Mathlib/Algebra/MvPolynomial/CommRing.lean | 8 +-- Mathlib/Algebra/MvPolynomial/Degrees.lean | 58 +++++++++++---------- Mathlib/Algebra/MvPolynomial/Variables.lean | 7 +-- Mathlib/FieldTheory/Finite/Polynomial.lean | 11 ++-- 4 files changed, 44 insertions(+), 40 deletions(-) diff --git a/Mathlib/Algebra/MvPolynomial/CommRing.lean b/Mathlib/Algebra/MvPolynomial/CommRing.lean index 7d2f5a35c441e..8a253650778fc 100644 --- a/Mathlib/Algebra/MvPolynomial/CommRing.lean +++ b/Mathlib/Algebra/MvPolynomial/CommRing.lean @@ -87,9 +87,11 @@ section Degrees theorem degrees_neg (p : MvPolynomial σ R) : (-p).degrees = p.degrees := by rw [degrees, support_neg]; rfl -theorem degrees_sub [DecidableEq σ] (p q : MvPolynomial σ R) : - (p - q).degrees ≤ p.degrees ⊔ q.degrees := by - simpa only [sub_eq_add_neg] using le_trans (degrees_add p (-q)) (by rw [degrees_neg]) +theorem degrees_sub_le [DecidableEq σ] {p q : MvPolynomial σ R} : + (p - q).degrees ≤ p.degrees ∪ q.degrees := by + simpa [degrees_def] using AddMonoidAlgebra.supDegree_sub_le + +@[deprecated (since := "2024-12-28")] alias degrees_sub := degrees_sub_le end Degrees diff --git a/Mathlib/Algebra/MvPolynomial/Degrees.lean b/Mathlib/Algebra/MvPolynomial/Degrees.lean index 55b5f391e4aff..f6242cd8467a2 100644 --- a/Mathlib/Algebra/MvPolynomial/Degrees.lean +++ b/Mathlib/Algebra/MvPolynomial/Degrees.lean @@ -110,33 +110,38 @@ theorem degrees_zero : degrees (0 : MvPolynomial σ R) = 0 := by theorem degrees_one : degrees (1 : MvPolynomial σ R) = 0 := degrees_C 1 -theorem degrees_add [DecidableEq σ] (p q : MvPolynomial σ R) : +theorem degrees_add_le [DecidableEq σ] {p q : MvPolynomial σ R} : (p + q).degrees ≤ p.degrees ⊔ q.degrees := by simp_rw [degrees_def]; exact supDegree_add_le -theorem degrees_sum {ι : Type*} [DecidableEq σ] (s : Finset ι) (f : ι → MvPolynomial σ R) : +theorem degrees_sum_le {ι : Type*} [DecidableEq σ] (s : Finset ι) (f : ι → MvPolynomial σ R) : (∑ i ∈ s, f i).degrees ≤ s.sup fun i => (f i).degrees := by simp_rw [degrees_def]; exact supDegree_sum_le -theorem degrees_mul (p q : MvPolynomial σ R) : (p * q).degrees ≤ p.degrees + q.degrees := by +theorem degrees_mul_le {p q : MvPolynomial σ R} : (p * q).degrees ≤ p.degrees + q.degrees := by classical simp_rw [degrees_def] exact supDegree_mul_le (map_add _) -theorem degrees_prod {ι : Type*} (s : Finset ι) (f : ι → MvPolynomial σ R) : +theorem degrees_prod_le {ι : Type*} {s : Finset ι} {f : ι → MvPolynomial σ R} : (∏ i ∈ s, f i).degrees ≤ ∑ i ∈ s, (f i).degrees := by classical exact supDegree_prod_le (map_zero _) (map_add _) -theorem degrees_pow (p : MvPolynomial σ R) (n : ℕ) : (p ^ n).degrees ≤ n • p.degrees := by - simpa using degrees_prod (Finset.range n) fun _ ↦ p +theorem degrees_pow_le {p : MvPolynomial σ R} {n : ℕ} : (p ^ n).degrees ≤ n • p.degrees := by + simpa using degrees_prod_le (s := .range n) (f := fun _ ↦ p) + +@[deprecated (since := "2024-12-28")] alias degrees_add := degrees_add_le +@[deprecated (since := "2024-12-28")] alias degrees_sum := degrees_sum_le +@[deprecated (since := "2024-12-28")] alias degrees_mul := degrees_mul_le +@[deprecated (since := "2024-12-28")] alias degrees_prod := degrees_prod_le +@[deprecated (since := "2024-12-28")] alias degrees_pow := degrees_pow_le theorem mem_degrees {p : MvPolynomial σ R} {i : σ} : i ∈ p.degrees ↔ ∃ d, p.coeff d ≠ 0 ∧ i ∈ d.support := by classical simp only [degrees_def, Multiset.mem_sup, ← mem_support_iff, Finsupp.mem_toMultiset, exists_prop] -theorem le_degrees_add {p q : MvPolynomial σ R} (h : Disjoint p.degrees q.degrees) : - p.degrees ≤ (p + q).degrees := by +theorem le_degrees_add_left (h : Disjoint p.degrees q.degrees) : p.degrees ≤ (p + q).degrees := by classical apply Finset.sup_le intro d hd @@ -153,22 +158,19 @@ theorem le_degrees_add {p q : MvPolynomial σ R} (h : Disjoint p.degrees q.degre refine ⟨j, ?_, j, ?_, rfl⟩ all_goals rw [mem_degrees]; refine ⟨d, ?_, hj⟩; assumption -theorem degrees_add_of_disjoint [DecidableEq σ] {p q : MvPolynomial σ R} - (h : Disjoint p.degrees q.degrees) : (p + q).degrees = p.degrees ∪ q.degrees := by - apply le_antisymm - · apply degrees_add - · apply Multiset.union_le - · apply le_degrees_add h - · rw [add_comm] - apply le_degrees_add h.symm - -theorem degrees_map [CommSemiring S] (p : MvPolynomial σ R) (f : R →+* S) : - (map f p).degrees ⊆ p.degrees := by - classical - dsimp only [degrees] - apply Multiset.subset_of_le - apply Finset.sup_mono - apply MvPolynomial.support_map_subset +@[deprecated (since := "2024-12-28")] alias le_degrees_add := le_degrees_add_left + +lemma le_degrees_add_right (h : Disjoint p.degrees q.degrees) : q.degrees ≤ (p + q).degrees := by + simpa [add_comm] using le_degrees_add_left h.symm + +theorem degrees_add_of_disjoint [DecidableEq σ] (h : Disjoint p.degrees q.degrees) : + (p + q).degrees = p.degrees ∪ q.degrees := + degrees_add_le.antisymm <| Multiset.union_le (le_degrees_add_left h) (le_degrees_add_right h) + +lemma degrees_map_le [CommSemiring S] {f : R →+* S} : (map f p).degrees ≤ p.degrees := by + classical exact Finset.sup_mono <| support_map_subset .. + +@[deprecated (since := "2024-12-28")] alias degrees_map := degrees_map_le theorem degrees_rename (f : σ → τ) (φ : MvPolynomial σ R) : (rename f φ).degrees ⊆ φ.degrees.map f := by @@ -262,7 +264,7 @@ theorem degreeOf_mul_le (i : σ) (f g : MvPolynomial σ R) : degreeOf i (f * g) ≤ degreeOf i f + degreeOf i g := by classical simp only [degreeOf] - convert Multiset.count_le_of_le i (degrees_mul f g) + convert Multiset.count_le_of_le i degrees_mul_le rw [Multiset.count_add] theorem degreeOf_sum_le {ι : Type*} (i : σ) (s : Finset ι) (f : ι → MvPolynomial σ R) : @@ -297,7 +299,7 @@ theorem degreeOf_mul_X_self (j : σ) (f : MvPolynomial σ R) : degreeOf j (f * X j) ≤ degreeOf j f + 1 := by classical simp only [degreeOf] - apply (Multiset.count_le_of_le j (degrees_mul f (X j))).trans + apply (Multiset.count_le_of_le j degrees_mul_le).trans simp only [Multiset.count_add, add_le_add_iff_left] convert Multiset.count_le_of_le j <| degrees_X' j rw [Multiset.count_singleton_self] @@ -320,13 +322,13 @@ theorem degreeOf_mul_X_eq_degreeOf_add_one_iff (j : σ) (f : MvPolynomial σ R) theorem degreeOf_C_mul_le (p : MvPolynomial σ R) (i : σ) (c : R) : (C c * p).degreeOf i ≤ p.degreeOf i := by unfold degreeOf - convert Multiset.count_le_of_le i <| degrees_mul (C c) p + convert Multiset.count_le_of_le i degrees_mul_le simp only [degrees_C, zero_add] theorem degreeOf_mul_C_le (p : MvPolynomial σ R) (i : σ) (c : R) : (p * C c).degreeOf i ≤ p.degreeOf i := by unfold degreeOf - convert Multiset.count_le_of_le i <| degrees_mul p (C c) + convert Multiset.count_le_of_le i degrees_mul_le simp only [degrees_C, add_zero] theorem degreeOf_rename_of_injective {p : MvPolynomial σ R} {f : σ → τ} (h : Function.Injective f) diff --git a/Mathlib/Algebra/MvPolynomial/Variables.lean b/Mathlib/Algebra/MvPolynomial/Variables.lean index d135fae4e62de..c13b44ae4ffd3 100644 --- a/Mathlib/Algebra/MvPolynomial/Variables.lean +++ b/Mathlib/Algebra/MvPolynomial/Variables.lean @@ -98,7 +98,7 @@ theorem vars_add_subset [DecidableEq σ] (p q : MvPolynomial σ R) : (p + q).vars ⊆ p.vars ∪ q.vars := by intro x hx simp only [vars_def, Finset.mem_union, Multiset.mem_toFinset] at hx ⊢ - simpa using Multiset.mem_of_le (degrees_add _ _) hx + simpa using Multiset.mem_of_le degrees_add_le hx theorem vars_add_of_disjoint [DecidableEq σ] (h : Disjoint p.vars q.vars) : (p + q).vars = p.vars ∪ q.vars := by @@ -110,7 +110,7 @@ section Mul theorem vars_mul [DecidableEq σ] (φ ψ : MvPolynomial σ R) : (φ * ψ).vars ⊆ φ.vars ∪ ψ.vars := by simp_rw [vars_def, ← Multiset.toFinset_add, Multiset.toFinset_subset] - exact Multiset.subset_of_le (degrees_mul φ ψ) + exact Multiset.subset_of_le degrees_mul_le @[simp] theorem vars_one : (1 : MvPolynomial σ R).vars = ∅ := @@ -194,7 +194,8 @@ section Map variable [CommSemiring S] (f : R →+* S) variable (p) -theorem vars_map : (map f p).vars ⊆ p.vars := by classical simp [vars_def, degrees_map] +theorem vars_map : (map f p).vars ⊆ p.vars := by + classical simp [vars_def, Multiset.subset_of_le degrees_map_le] variable {f} diff --git a/Mathlib/FieldTheory/Finite/Polynomial.lean b/Mathlib/FieldTheory/Finite/Polynomial.lean index d93f2b2225060..22d9e4abf7175 100644 --- a/Mathlib/FieldTheory/Finite/Polynomial.lean +++ b/Mathlib/FieldTheory/Finite/Polynomial.lean @@ -71,13 +71,12 @@ theorem eval_indicator_apply_eq_one (a : σ → K) : eval a (indicator a) = 1 := theorem degrees_indicator (c : σ → K) : degrees (indicator c) ≤ ∑ s : σ, (Fintype.card K - 1) • {s} := by rw [indicator] - refine le_trans (degrees_prod _ _) (Finset.sum_le_sum fun s _ => ?_) classical - refine le_trans (degrees_sub _ _) ?_ - rw [degrees_one, ← bot_eq_zero, bot_sup_eq] - refine le_trans (degrees_pow _ _) (nsmul_le_nsmul_right ?_ _) - refine le_trans (degrees_sub _ _) ?_ - rw [degrees_C, ← bot_eq_zero, sup_bot_eq] + refine degrees_prod_le.trans <| Finset.sum_le_sum fun s _ ↦ degrees_sub_le.trans ?_ + rw [degrees_one, Multiset.zero_union] + refine le_trans degrees_pow_le (nsmul_le_nsmul_right ?_ _) + refine degrees_sub_le.trans ?_ + rw [degrees_C, Multiset.union_zero] exact degrees_X' _ theorem indicator_mem_restrictDegree (c : σ → K) : From 94f29269bc410cb4c0d61b2fc042fec8f00286cd Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Thu, 23 Jan 2025 09:23:35 +0000 Subject: [PATCH 446/681] chore: remove a few porting notes (#20969) Co-authored-by: Moritz Firsching --- .../ContinuedFractions/Computation/TerminatesIffRat.lean | 5 +---- Mathlib/Data/Finsupp/Fin.lean | 1 - Mathlib/Data/Nat/Factorization/Basic.lean | 5 +---- Mathlib/Geometry/Euclidean/MongePoint.lean | 3 +-- Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean | 3 +-- Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean | 8 +++----- 6 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean b/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean index 2a78678ad1a4a..b7f727a629aae 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean @@ -213,10 +213,7 @@ theorem coe_of_rat_eq (v_eq_q : v = (↑q : K)) : rcases gcf_v_eq : of v with ⟨h, s⟩; subst v -- Porting note: made coercion target explicit obtain rfl : ↑⌊(q : K)⌋ = h := by injection gcf_v_eq - -- Porting note: was - -- simp [coe_of_h_rat_eq rfl, coe_of_s_rat_eq rfl, gcf_v_eq] - simp only [gcf_v_eq, Int.cast_inj, Rat.floor_cast, of_h_eq_floor, eq_self_iff_true, - Rat.cast_intCast, and_self, coe_of_h_rat_eq rfl, coe_of_s_rat_eq rfl] + simp [coe_of_h_rat_eq rfl, coe_of_s_rat_eq rfl, gcf_v_eq] theorem of_terminates_iff_of_rat_terminates {v : K} {q : ℚ} (v_eq_q : v = (q : K)) : (of v).Terminates ↔ (of q).Terminates := by diff --git a/Mathlib/Data/Finsupp/Fin.lean b/Mathlib/Data/Finsupp/Fin.lean index 049744c5fa6a9..027350c69ca70 100644 --- a/Mathlib/Data/Finsupp/Fin.lean +++ b/Mathlib/Data/Finsupp/Fin.lean @@ -42,7 +42,6 @@ theorem cons_zero : cons y s 0 = y := @[simp] theorem cons_succ : cons y s i.succ = s i := - -- Porting note: was Fin.cons_succ _ _ _ rfl @[simp] diff --git a/Mathlib/Data/Nat/Factorization/Basic.lean b/Mathlib/Data/Nat/Factorization/Basic.lean index a56075aac773f..15357904895cd 100644 --- a/Mathlib/Data/Nat/Factorization/Basic.lean +++ b/Mathlib/Data/Nat/Factorization/Basic.lean @@ -556,10 +556,7 @@ theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) : theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) : ∏ p ∈ range m with p.Prime, p ^ padicValNat p n = n := by - -- Porting note: was `nth_rw_rhs` - conv => - rhs - rw [← factorization_prod_pow_eq_self hn] + nth_rw 2 [← factorization_prod_pow_eq_self hn] rw [eq_comm] apply Finset.prod_subset_one_on_sdiff · exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <| diff --git a/Mathlib/Geometry/Euclidean/MongePoint.lean b/Mathlib/Geometry/Euclidean/MongePoint.lean index 038fc99fd056f..90119d260be35 100644 --- a/Mathlib/Geometry/Euclidean/MongePoint.lean +++ b/Mathlib/Geometry/Euclidean/MongePoint.lean @@ -301,8 +301,7 @@ theorem eq_mongePoint_of_forall_mem_mongePlane {n : ℕ} {s : Simplex ℝ P (n + · rintro ⟨i, rfl⟩ use i, ⟨Set.mem_univ _, i.property.symm⟩ · rintro ⟨i, ⟨-, hi⟩, rfl⟩ - -- Porting note: was `use ⟨i, hi.symm⟩, rfl` - exact ⟨⟨i, hi.symm⟩, rfl⟩ + use ⟨i, hi.symm⟩ rw [hu, ← vectorSpan_image_eq_span_vsub_set_left_ne ℝ _ (Set.mem_univ _), Set.image_univ] at hi have hv : p -ᵥ s.mongePoint ∈ vectorSpan ℝ (Set.range s.points) := by let s₁ : Finset (Fin (n + 3)) := univ.erase i₁ diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index 99c7565362d22..c3fefa900b490 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -390,8 +390,7 @@ def ιInvApp {i : D.J} (U : Opens (D.U i).carrier) : rw [← (D.V (j, k)).presheaf.map_comp] erw [← (D.V (j, k)).presheaf.map_comp] repeat rw [← (D.V (j, k)).presheaf.map_comp] - -- Porting note: was just `congr` - exact congr_arg ((D.V (j, k)).presheaf.map ·) rfl } } + rfl } } /-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/ theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) : diff --git a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean index b279eda8cbc9c..4e0b53338d713 100644 --- a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean +++ b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean @@ -666,11 +666,9 @@ def invertibleOfSubmatrixEquivInvertible (A : Matrix m m α) (e₁ e₂ : n ≃ [Invertible (A.submatrix e₁ e₂)] : Invertible A := invertibleOfRightInverse _ ((⅟ (A.submatrix e₁ e₂)).submatrix e₂.symm e₁.symm) <| by have : A = (A.submatrix e₁ e₂).submatrix e₁.symm e₂.symm := by simp - -- Porting note: was - -- conv in _ * _ => - -- congr - -- rw [this] - rw [congr_arg₂ (· * ·) this rfl] + conv in _ * _ => + congr + rw [this] rw [Matrix.submatrix_mul_equiv, mul_invOf_self, submatrix_one_equiv] theorem invOf_submatrix_equiv_eq (A : Matrix m m α) (e₁ e₂ : n ≃ m) [Invertible A] From 8fac96b567d5b979e6a55c99158a99b20e968a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 23 Jan 2025 09:23:36 +0000 Subject: [PATCH 447/681] chore(CategoryTheory/Subpresheaf): split files (#20978) This PR only moves definitions and lemmas into two new files `Subpresheaf.Sieves` and `Subpresheaf.Image` in order to prepare for the development of new API. --- Mathlib.lean | 2 + Mathlib/CategoryTheory/Sites/Subsheaf.lean | 3 +- Mathlib/CategoryTheory/Subpresheaf/Basic.lean | 86 +------------------ Mathlib/CategoryTheory/Subpresheaf/Image.lean | 84 ++++++++++++++++++ .../CategoryTheory/Subpresheaf/Sieves.lean | 48 +++++++++++ 5 files changed, 137 insertions(+), 86 deletions(-) create mode 100644 Mathlib/CategoryTheory/Subpresheaf/Image.lean create mode 100644 Mathlib/CategoryTheory/Subpresheaf/Sieves.lean diff --git a/Mathlib.lean b/Mathlib.lean index 53a8e9b57816a..4a99f1e1940c6 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2249,6 +2249,8 @@ import Mathlib.CategoryTheory.Subobject.MonoOver import Mathlib.CategoryTheory.Subobject.Types import Mathlib.CategoryTheory.Subobject.WellPowered import Mathlib.CategoryTheory.Subpresheaf.Basic +import Mathlib.CategoryTheory.Subpresheaf.Image +import Mathlib.CategoryTheory.Subpresheaf.Sieves import Mathlib.CategoryTheory.Subterminal import Mathlib.CategoryTheory.Sums.Associator import Mathlib.CategoryTheory.Sums.Basic diff --git a/Mathlib/CategoryTheory/Sites/Subsheaf.lean b/Mathlib/CategoryTheory/Sites/Subsheaf.lean index 3e31f82d383ff..3be19de81341b 100644 --- a/Mathlib/CategoryTheory/Sites/Subsheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Subsheaf.lean @@ -8,7 +8,8 @@ import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono import Mathlib.Tactic.CategoryTheory.Elementwise import Mathlib.CategoryTheory.Adhesive import Mathlib.CategoryTheory.Sites.ConcreteSheafification -import Mathlib.CategoryTheory.Subpresheaf.Basic +import Mathlib.CategoryTheory.Subpresheaf.Image +import Mathlib.CategoryTheory.Subpresheaf.Sieves /-! diff --git a/Mathlib/CategoryTheory/Subpresheaf/Basic.lean b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean index e272dd86854b4..080283e8b1880 100644 --- a/Mathlib/CategoryTheory/Subpresheaf/Basic.lean +++ b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.CategoryTheory.Elementwise -import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono -import Mathlib.Tactic.CategoryTheory.Elementwise -import Mathlib.CategoryTheory.Sites.IsSheafFor +import Mathlib.Data.Set.Basic /-! @@ -115,94 +113,12 @@ theorem Subpresheaf.eq_top_iff_isIso : G = ⊤ ↔ IsIso G.ι := by rw [← IsIso.inv_hom_id_apply (G.ι.app U) x] exact ((inv (G.ι.app U)) x).2 -/-- If the image of a morphism falls in a subpresheaf, then the morphism factors through it. -/ -@[simps!] -def Subpresheaf.lift (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : F' ⟶ G.toPresheaf where - app U x := ⟨f.app U x, hf U x⟩ - naturality := by - have := elementwise_of% f.naturality - intros - refine funext fun x => Subtype.ext ?_ - simp only [toPresheaf_obj, types_comp_apply] - exact this _ _ - -@[reassoc (attr := simp)] -theorem Subpresheaf.lift_ι (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : - G.lift f hf ≫ G.ι = f := by - ext - rfl - -/-- Given a subpresheaf `G` of `F`, an `F`-section `s` on `U`, we may define a sieve of `U` -consisting of all `f : V ⟶ U` such that the restriction of `s` along `f` is in `G`. -/ -@[simps] -def Subpresheaf.sieveOfSection {U : Cᵒᵖ} (s : F.obj U) : Sieve (unop U) where - arrows V f := F.map f.op s ∈ G.obj (op V) - downward_closed := @fun V W i hi j => by - simp only [op_unop, op_comp, FunctorToTypes.map_comp_apply] - exact G.map _ hi - -/-- Given an `F`-section `s` on `U` and a subpresheaf `G`, we may define a family of elements in -`G` consisting of the restrictions of `s` -/ -def Subpresheaf.familyOfElementsOfSection {U : Cᵒᵖ} (s : F.obj U) : - (G.sieveOfSection s).1.FamilyOfElements G.toPresheaf := fun _ i hi => ⟨F.map i.op s, hi⟩ - -theorem Subpresheaf.family_of_elements_compatible {U : Cᵒᵖ} (s : F.obj U) : - (G.familyOfElementsOfSection s).Compatible := by - intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ e - refine Subtype.ext ?_ -- Porting note: `ext1` does not work here - change F.map g₁.op (F.map f₁.op s) = F.map g₂.op (F.map f₂.op s) - rw [← FunctorToTypes.map_comp_apply, ← FunctorToTypes.map_comp_apply, ← op_comp, ← op_comp, e] - theorem Subpresheaf.nat_trans_naturality (f : F' ⟶ G.toPresheaf) {U V : Cᵒᵖ} (i : U ⟶ V) (x : F'.obj U) : (f.app V (F'.map i x)).1 = F.map i (f.app U x).1 := congr_arg Subtype.val (FunctorToTypes.naturality _ _ f i x) -section Image - -/-- The image presheaf of a morphism, whose components are the set-theoretic images. -/ -@[simps] -def imagePresheaf (f : F' ⟶ F) : Subpresheaf F where - obj U := Set.range (f.app U) - map := by - rintro U V i _ ⟨x, rfl⟩ - have := elementwise_of% f.naturality - exact ⟨_, this i x⟩ - @[simp] theorem top_subpresheaf_obj (U) : (⊤ : Subpresheaf F).obj U = ⊤ := rfl -@[simp] -theorem imagePresheaf_id : imagePresheaf (𝟙 F) = ⊤ := by - ext - simp - -/-- A morphism factors through the image presheaf. -/ -@[simps!] -def toImagePresheaf (f : F' ⟶ F) : F' ⟶ (imagePresheaf f).toPresheaf := - (imagePresheaf f).lift f fun _ _ => Set.mem_range_self _ - -@[reassoc (attr := simp)] -theorem toImagePresheaf_ι (f : F' ⟶ F) : toImagePresheaf f ≫ (imagePresheaf f).ι = f := - (imagePresheaf f).lift_ι _ _ - -theorem imagePresheaf_comp_le (f₁ : F ⟶ F') (f₂ : F' ⟶ F'') : - imagePresheaf (f₁ ≫ f₂) ≤ imagePresheaf f₂ := fun U _ hx => ⟨f₁.app U hx.choose, hx.choose_spec⟩ - -instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ Type w} (f : F ⟶ F') [hf : Mono f] : - IsIso (toImagePresheaf f) := by - have : ∀ (X : Cᵒᵖ), IsIso ((toImagePresheaf f).app X) := by - intro X - rw [isIso_iff_bijective] - constructor - · intro x y e - have := (NatTrans.mono_iff_mono_app f).mp hf X - rw [mono_iff_injective] at this - exact this (congr_arg Subtype.val e :) - · rintro ⟨_, ⟨x, rfl⟩⟩ - exact ⟨x, rfl⟩ - apply NatIso.isIso_of_isIso_app - -end Image - end CategoryTheory diff --git a/Mathlib/CategoryTheory/Subpresheaf/Image.lean b/Mathlib/CategoryTheory/Subpresheaf/Image.lean new file mode 100644 index 0000000000000..367029af657f0 --- /dev/null +++ b/Mathlib/CategoryTheory/Subpresheaf/Image.lean @@ -0,0 +1,84 @@ +/- +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.CategoryTheory.Subpresheaf.Basic +import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono + +/-! +# The image of a subpresheaf + +Given a morphism of presheaves of types `f : F' ⟶ F`, we define `imagePresheaf f` +as a subpresheaf of `F`. + +## TODO (@joelriou) +* introduce `Subpresheaf.image` and `Subpresheaf.preimage` + +-/ + +universe w v u + +namespace CategoryTheory + +variable {C : Type u} [Category.{v} C] {F F' F'' : Cᵒᵖ ⥤ Type w} {G : Subpresheaf F} + +/-- If the image of a morphism falls in a subpresheaf, then the morphism factors through it. -/ +@[simps!] +def Subpresheaf.lift (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : F' ⟶ G.toPresheaf where + app U x := ⟨f.app U x, hf U x⟩ + naturality := by + have := elementwise_of% f.naturality + intros + refine funext fun x => Subtype.ext ?_ + simp only [toPresheaf_obj, types_comp_apply] + exact this _ _ + +@[reassoc (attr := simp)] +theorem Subpresheaf.lift_ι (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : + G.lift f hf ≫ G.ι = f := by + ext + rfl + +/-- The image presheaf of a morphism, whose components are the set-theoretic images. -/ +@[simps] +def imagePresheaf (f : F' ⟶ F) : Subpresheaf F where + obj U := Set.range (f.app U) + map := by + rintro U V i _ ⟨x, rfl⟩ + have := elementwise_of% f.naturality + exact ⟨_, this i x⟩ + +@[simp] +theorem imagePresheaf_id : imagePresheaf (𝟙 F) = ⊤ := by + ext + simp + +/-- A morphism factors through the image presheaf. -/ +@[simps!] +def toImagePresheaf (f : F' ⟶ F) : F' ⟶ (imagePresheaf f).toPresheaf := + (imagePresheaf f).lift f fun _ _ => Set.mem_range_self _ + +@[reassoc (attr := simp)] +theorem toImagePresheaf_ι (f : F' ⟶ F) : toImagePresheaf f ≫ (imagePresheaf f).ι = f := + (imagePresheaf f).lift_ι _ _ + +theorem imagePresheaf_comp_le (f₁ : F ⟶ F') (f₂ : F' ⟶ F'') : + imagePresheaf (f₁ ≫ f₂) ≤ imagePresheaf f₂ := fun U _ hx => ⟨f₁.app U hx.choose, hx.choose_spec⟩ + +instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ Type w} (f : F ⟶ F') [hf : Mono f] : + IsIso (toImagePresheaf f) := by + have : ∀ (X : Cᵒᵖ), IsIso ((toImagePresheaf f).app X) := by + intro X + rw [isIso_iff_bijective] + constructor + · intro x y e + have := (NatTrans.mono_iff_mono_app f).mp hf X + rw [mono_iff_injective] at this + exact this (congr_arg Subtype.val e :) + · rintro ⟨_, ⟨x, rfl⟩⟩ + exact ⟨x, rfl⟩ + apply NatIso.isIso_of_isIso_app + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Subpresheaf/Sieves.lean b/Mathlib/CategoryTheory/Subpresheaf/Sieves.lean new file mode 100644 index 0000000000000..12ffd8506ee78 --- /dev/null +++ b/Mathlib/CategoryTheory/Subpresheaf/Sieves.lean @@ -0,0 +1,48 @@ +/- +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.CategoryTheory.Subpresheaf.Basic +import Mathlib.CategoryTheory.Sites.IsSheafFor + +/-! +# Sieves attached to subpresheaves + +Given a subpresheaf `G` of a presheaf of types `F : Cᵒᵖ ⥤ Type w` and +a section `s : F.obj U`, we define a sieve `G.sieveOfSection s : Sieve (unop U)` +and the associated compatible family of elements with values in `G.toPresheaf`. + +-/ + +universe w v u + +namespace CategoryTheory.Subpresheaf + +open Opposite + +variable {C : Type u} [Category.{v} C] {F : Cᵒᵖ ⥤ Type w} (G : Subpresheaf F) + +/-- Given a subpresheaf `G` of `F`, an `F`-section `s` on `U`, we may define a sieve of `U` +consisting of all `f : V ⟶ U` such that the restriction of `s` along `f` is in `G`. -/ +@[simps] +def sieveOfSection {U : Cᵒᵖ} (s : F.obj U) : Sieve (unop U) where + arrows V f := F.map f.op s ∈ G.obj (op V) + downward_closed := @fun V W i hi j => by + simp only [op_unop, op_comp, FunctorToTypes.map_comp_apply] + exact G.map _ hi + +/-- Given an `F`-section `s` on `U` and a subpresheaf `G`, we may define a family of elements in +`G` consisting of the restrictions of `s` -/ +def familyOfElementsOfSection {U : Cᵒᵖ} (s : F.obj U) : + (G.sieveOfSection s).1.FamilyOfElements G.toPresheaf := fun _ i hi => ⟨F.map i.op s, hi⟩ + +theorem family_of_elements_compatible {U : Cᵒᵖ} (s : F.obj U) : + (G.familyOfElementsOfSection s).Compatible := by + intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ e + refine Subtype.ext ?_ -- Porting note: `ext1` does not work here + change F.map g₁.op (F.map f₁.op s) = F.map g₂.op (F.map f₂.op s) + rw [← FunctorToTypes.map_comp_apply, ← FunctorToTypes.map_comp_apply, ← op_comp, ← op_comp, e] + +end CategoryTheory.Subpresheaf From e73fda6d36b4f316abea5a9abdbf145424c6edd3 Mon Sep 17 00:00:00 2001 From: Artie Khovanov Date: Thu, 23 Jan 2025 11:42:49 +0000 Subject: [PATCH 448/681] chore(Algebra/Group/Even): Clean up file (#20558) * Rename some theorems to remove primed variants * Move `simp` attribute from `IsSquare.sq` to `Even.isSquare_pow` for consistency * Remove unhelpful alias * Golf some proofs * Make notation consistent throughout proofs Moves: `Even.nsmul` -> `Even.nsmul_right` `Even.nsmul'` -> `Even.nsmul_left` `Even.zsmul` -> `Even.zsmul_right` `Even.zsmul'` -> `Even.zsmul_left` `isSquare_zero` -> `IsSquare.zero` Deletions: `isSquare_of_exists_sq` (prefer `IsSquare.sq`) --- Mathlib/Algebra/Field/Power.lean | 2 +- Mathlib/Algebra/GeomSum.lean | 2 +- Mathlib/Algebra/Group/Even.lean | 78 +++++++++++-------- Mathlib/Algebra/Group/Nat/Even.lean | 2 +- Mathlib/Algebra/Order/Field/Power.lean | 2 +- Mathlib/Algebra/Ring/Parity.lean | 6 +- .../DivisionPolynomial/Basic.lean | 8 +- Mathlib/Data/Bool/Count.lean | 2 +- Mathlib/Data/Nat/Hyperoperation.lean | 2 +- Mathlib/GroupTheory/Coxeter/Basic.lean | 2 +- .../LegendreSymbol/QuadraticChar/Basic.lean | 2 +- .../QuadraticChar/GaussSum.lean | 2 +- .../NumberTheory/NumberField/Embeddings.lean | 4 +- Mathlib/NumberTheory/SumTwoSquares.lean | 2 +- 14 files changed, 66 insertions(+), 50 deletions(-) diff --git a/Mathlib/Algebra/Field/Power.lean b/Mathlib/Algebra/Field/Power.lean index 8340559169683..a295fde38a1ad 100644 --- a/Mathlib/Algebra/Field/Power.lean +++ b/Mathlib/Algebra/Field/Power.lean @@ -22,7 +22,7 @@ section DivisionRing variable [DivisionRing α] {n : ℤ} theorem Odd.neg_zpow (h : Odd n) (a : α) : (-a) ^ n = -a ^ n := by - have hn : n ≠ 0 := by rintro rfl; exact Int.not_even_iff_odd.2 h even_zero + have hn : n ≠ 0 := by rintro rfl; exact Int.not_even_iff_odd.2 h .zero obtain ⟨k, rfl⟩ := h simp_rw [zpow_add' (.inr (.inl hn)), zpow_one, zpow_mul, zpow_two, neg_mul_neg, neg_mul_eq_mul_neg] diff --git a/Mathlib/Algebra/GeomSum.lean b/Mathlib/Algebra/GeomSum.lean index 69be1e10b5d9d..cac128232b4fd 100644 --- a/Mathlib/Algebra/GeomSum.lean +++ b/Mathlib/Algebra/GeomSum.lean @@ -487,7 +487,7 @@ theorem geom_sum_alternating_of_le_neg_one [StrictOrderedRing α] (hx : x + 1 if Even n then (∑ i ∈ range n, x ^ i) ≤ 0 else 1 ≤ ∑ i ∈ range n, x ^ i := by have hx0 : x ≤ 0 := (le_add_of_nonneg_right zero_le_one).trans hx induction n with - | zero => simp only [range_zero, sum_empty, le_refl, ite_true, even_zero] + | zero => simp only [range_zero, sum_empty, le_refl, ite_true, Even.zero] | succ n ih => simp only [Nat.even_add_one, geom_sum_succ] split_ifs at ih with h diff --git a/Mathlib/Algebra/Group/Even.lean b/Mathlib/Algebra/Group/Even.lean index dbfa138e3cb38..6e598f103f8a3 100644 --- a/Mathlib/Algebra/Group/Even.lean +++ b/Mathlib/Algebra/Group/Even.lean @@ -16,6 +16,11 @@ This file defines square and even elements in a monoid. * `IsSquare a` means that there is some `r` such that `a = r * r` * `Even a` means that there is some `r` such that `a = r + r` +## Note + +* Many lemmas about `Even` / `IsSquare`, including important `simp` lemmas, + are in `Mathlib.Algebra.Ring.Parity`. + ## TODO * Try to generalize `IsSquare/Even` lemmas further. For example, there are still a few lemmas in @@ -26,7 +31,8 @@ This file defines square and even elements in a monoid. ## See also -`Mathlib.Algebra.Ring.Parity` for the definition of odd elements. +`Mathlib.Algebra.Ring.Parity` for the definition of odd elements as well as facts about +`Even` / `IsSquare` in rings. -/ assert_not_exists MonoidWithZero DenselyOrdered @@ -39,19 +45,19 @@ section Mul variable [Mul α] /-- An element `a` of a type `α` with multiplication satisfies `IsSquare a` if `a = r * r`, -for some `r : α`. -/ +for some root `r : α`. -/ @[to_additive "An element `a` of a type `α` with addition satisfies `Even a` if `a = r + r`, for some `r : α`."] def IsSquare (a : α) : Prop := ∃ r, a = r * r -@[to_additive (attr := simp)] lemma IsSquare.mul_self (m : α) : IsSquare (m * m) := ⟨m, rfl⟩ +@[to_additive (attr := simp)] lemma IsSquare.mul_self (r : α) : IsSquare (r * r) := ⟨r, rfl⟩ @[deprecated (since := "2024-08-27")] alias isSquare_mul_self := IsSquare.mul_self @[deprecated (since := "2024-08-27")] alias even_add_self := Even.add_self @[to_additive] lemma isSquare_op_iff {a : α} : IsSquare (op a) ↔ IsSquare a := - ⟨fun ⟨c, hc⟩ ↦ ⟨unop c, congr_arg unop hc⟩, fun ⟨c, hc⟩ ↦ ⟨op c, congr_arg op hc⟩⟩ + ⟨fun ⟨r, hr⟩ ↦ ⟨unop r, congr_arg unop hr⟩, fun ⟨r, hr⟩ ↦ ⟨op r, congr_arg op hr⟩⟩ @[to_additive] lemma isSquare_unop_iff {a : αᵐᵒᵖ} : IsSquare (unop a) ↔ IsSquare a := isSquare_op_iff.symm @@ -89,58 +95,64 @@ end Add @[to_additive (attr := simp)] lemma IsSquare.one [MulOneClass α] : IsSquare (1 : α) := ⟨1, (mul_one _).symm⟩ -@[to_additive, deprecated (since := "2024-12-27")] alias isSquare_one := IsSquare.one +@[deprecated (since := "2024-12-27")] alias isSquare_one := IsSquare.one +@[deprecated (since := "2024-12-27")] alias even_zero := Even.zero + +section MonoidHom +variable [MulOneClass α] [MulOneClass β] [FunLike F α β] [MonoidHomClass F α β] @[to_additive] -lemma IsSquare.map [MulOneClass α] [MulOneClass β] [FunLike F α β] [MonoidHomClass F α β] - {m : α} (f : F) : - IsSquare m → IsSquare (f m) := by - rintro ⟨m, rfl⟩ - exact ⟨f m, by simp⟩ +lemma IsSquare.map {a : α} (f : F) : IsSquare a → IsSquare (f a) := + fun ⟨r, _⟩ => ⟨f r, by simp_all⟩ + +end MonoidHom section Monoid variable [Monoid α] {n : ℕ} {a : α} @[to_additive even_iff_exists_two_nsmul] -lemma isSquare_iff_exists_sq (m : α) : IsSquare m ↔ ∃ c, m = c ^ 2 := by simp [IsSquare, pow_two] +lemma isSquare_iff_exists_sq (a : α) : IsSquare a ↔ ∃ r, a = r ^ 2 := by simp [IsSquare, pow_two] + +@[to_additive Even.exists_two_nsmul + "Alias of the forwards direction of `even_iff_exists_two_nsmul`."] +alias ⟨IsSquare.exists_sq, _⟩ := isSquare_iff_exists_sq -alias ⟨IsSquare.exists_sq, isSquare_of_exists_sq⟩ := isSquare_iff_exists_sq +-- provable by simp in `Algebra.Ring.Parity` +@[to_additive Even.two_nsmul] +lemma IsSquare.sq (r : α) : IsSquare (r ^ 2) := ⟨r, pow_two _⟩ -attribute [to_additive Even.exists_two_nsmul - "Alias of the forwards direction of `even_iff_exists_two_nsmul`."] IsSquare.exists_sq +@[deprecated (since := "2024-12-27")] alias IsSquare_sq := IsSquare.sq +@[deprecated (since := "2024-12-27")] alias even_two_nsmul := Even.two_nsmul -@[to_additive] lemma IsSquare.pow (n : ℕ) : IsSquare a → IsSquare (a ^ n) := by - rintro ⟨a, rfl⟩; exact ⟨a ^ n, (Commute.refl _).mul_pow _⟩ +@[to_additive Even.nsmul_right] lemma IsSquare.pow (n : ℕ) : IsSquare a → IsSquare (a ^ n) := by + rintro ⟨r, rfl⟩; exact ⟨r ^ n, (Commute.refl _).mul_pow _⟩ -@[to_additive Even.nsmul'] lemma Even.isSquare_pow : Even n → ∀ a : α, IsSquare (a ^ n) := by - rintro ⟨n, rfl⟩ a; exact ⟨a ^ n, pow_add _ _ _⟩ +@[deprecated (since := "2025-01-19")] alias Even.nsmul := Even.nsmul_right -@[to_additive Even.two_nsmul] lemma IsSquare.sq (a : α) : IsSquare (a ^ 2) := ⟨a, pow_two _⟩ +@[to_additive (attr := simp) Even.nsmul_left] +lemma Even.isSquare_pow : Even n → ∀ a : α, IsSquare (a ^ n) := by + rintro ⟨m, rfl⟩ a; exact ⟨a ^ m, pow_add _ _ _⟩ -@[deprecated (since := "2024-12-27")] alias IsSquare_sq := IsSquare.sq -@[deprecated (since := "2024-12-27")] alias even_two_nsmul := Even.two_nsmul +@[deprecated (since := "2025-01-19")] alias Even.nsmul' := Even.nsmul_left end Monoid @[to_additive] lemma IsSquare.mul [CommSemigroup α] {a b : α} : IsSquare a → IsSquare b → IsSquare (a * b) := by - rintro ⟨a, rfl⟩ ⟨b, rfl⟩; exact ⟨a * b, mul_mul_mul_comm _ _ _ _⟩ + rintro ⟨r, rfl⟩ ⟨s, rfl⟩; exact ⟨r * s, mul_mul_mul_comm _ _ _ _⟩ section DivisionMonoid variable [DivisionMonoid α] {a : α} @[to_additive (attr := simp)] lemma isSquare_inv : IsSquare a⁻¹ ↔ IsSquare a := by - constructor <;> intro h - · rw [← isSquare_op_iff, ← inv_inv a] - exact h.map (MulEquiv.inv' α) - · exact (isSquare_op_iff.mpr h).map (MulEquiv.inv' α).symm + constructor <;> intro h <;> simpa using (isSquare_op_iff.mpr h).map (MulEquiv.inv' α).symm -alias ⟨_, IsSquare.inv⟩ := isSquare_inv +@[to_additive] alias ⟨_, IsSquare.inv⟩ := isSquare_inv -attribute [to_additive] IsSquare.inv +@[to_additive Even.zsmul_right] lemma IsSquare.zpow (n : ℤ) : IsSquare a → IsSquare (a ^ n) := by + rintro ⟨r, rfl⟩; exact ⟨r ^ n, (Commute.refl _).mul_zpow _⟩ -@[to_additive] lemma IsSquare.zpow (n : ℤ) : IsSquare a → IsSquare (a ^ n) := by - rintro ⟨a, rfl⟩; exact ⟨a ^ n, (Commute.refl _).mul_zpow _⟩ +@[deprecated (since := "2024-01-19")] alias Even.zsmul := Even.zsmul_right end DivisionMonoid @@ -148,6 +160,8 @@ end DivisionMonoid lemma IsSquare.div [DivisionCommMonoid α] {a b : α} (ha : IsSquare a) (hb : IsSquare b) : IsSquare (a / b) := by rw [div_eq_mul_inv]; exact ha.mul hb.inv -@[to_additive (attr := simp) Even.zsmul'] +@[to_additive (attr := simp) Even.zsmul_left] lemma Even.isSquare_zpow [Group α] {n : ℤ} : Even n → ∀ a : α, IsSquare (a ^ n) := by - rintro ⟨n, rfl⟩ a; exact ⟨a ^ n, zpow_add _ _ _⟩ + rintro ⟨m, rfl⟩ a; exact ⟨a ^ m, zpow_add _ _ _⟩ + +@[deprecated (since := "2024-01-07")] alias Even.zsmul' := Even.zsmul_left diff --git a/Mathlib/Algebra/Group/Nat/Even.lean b/Mathlib/Algebra/Group/Nat/Even.lean index 0cedd8a212532..923b311dee4d1 100644 --- a/Mathlib/Algebra/Group/Nat/Even.lean +++ b/Mathlib/Algebra/Group/Nat/Even.lean @@ -72,7 +72,7 @@ lemma even_pow' (h : n ≠ 0) : Even (m ^ n) ↔ Even m := even_pow.trans <| and lemma even_mul_succ_self (n : ℕ) : Even (n * (n + 1)) := by rw [even_mul, even_add_one]; exact em _ lemma even_mul_pred_self : ∀ n : ℕ, Even (n * (n - 1)) - | 0 => even_zero + | 0 => .zero | (n + 1) => mul_comm (n + 1 - 1) (n + 1) ▸ even_mul_succ_self n lemma two_mul_div_two_of_even : Even n → 2 * (n / 2) = n := fun h ↦ diff --git a/Mathlib/Algebra/Order/Field/Power.lean b/Mathlib/Algebra/Order/Field/Power.lean index ac82917ae0852..f8c6e2dddb310 100644 --- a/Mathlib/Algebra/Order/Field/Power.lean +++ b/Mathlib/Algebra/Order/Field/Power.lean @@ -116,7 +116,7 @@ protected lemma Odd.zpow_nonneg_iff (hn : Odd n) : 0 ≤ a ^ n ↔ 0 ≤ a := theorem Odd.zpow_nonpos_iff (hn : Odd n) : a ^ n ≤ 0 ↔ a ≤ 0 := by rw [le_iff_lt_or_eq, le_iff_lt_or_eq, hn.zpow_neg_iff, zpow_eq_zero_iff] rintro rfl - exact Int.not_even_iff_odd.2 hn even_zero + exact Int.not_even_iff_odd.2 hn .zero lemma Odd.zpow_pos_iff (hn : Odd n) : 0 < a ^ n ↔ 0 < a := lt_iff_lt_of_le_iff_le hn.zpow_nonpos_iff diff --git a/Mathlib/Algebra/Ring/Parity.lean b/Mathlib/Algebra/Ring/Parity.lean index 0883314e27689..ed97a0457e825 100644 --- a/Mathlib/Algebra/Ring/Parity.lean +++ b/Mathlib/Algebra/Ring/Parity.lean @@ -54,7 +54,9 @@ lemma Even.neg_one_zpow (h : Even n) : (-1 : α) ^ n = 1 := by rw [h.neg_zpow, o end DivisionMonoid -@[simp] lemma isSquare_zero [MulZeroClass α] : IsSquare (0 : α) := ⟨0, (mul_zero _).symm⟩ +@[simp] lemma IsSquare.zero [MulZeroClass α] : IsSquare (0 : α) := ⟨0, (mul_zero _).symm⟩ + +@[deprecated (since := "2024-01-07")] alias isSquare_zero := IsSquare.zero section Semiring variable [Semiring α] [Semiring β] {a b : α} {m n : ℕ} @@ -255,7 +257,7 @@ lemma even_sub' (h : n ≤ m) : Even (m - n) ↔ (Odd m ↔ Odd n) := by lemma Odd.sub_odd (hm : Odd m) (hn : Odd n) : Even (m - n) := (le_total n m).elim (fun h ↦ by simp only [even_sub' h, *]) fun h ↦ by - simp only [Nat.sub_eq_zero_iff_le.2 h, even_zero] + simp only [Nat.sub_eq_zero_iff_le.2 h, Even.zero] alias _root_.Odd.tsub_odd := Nat.Odd.sub_odd diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean index d5026ebed2afd..45e995affc9dd 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean @@ -401,11 +401,11 @@ lemma Φ_ofNat (n : ℕ) : W.Φ (n + 1) = @[simp] lemma Φ_zero : W.Φ 0 = 1 := by rw [Φ, ΨSq_zero, mul_zero, zero_sub, zero_add, preΨ_one, one_mul, zero_sub, preΨ_neg, preΨ_one, - neg_one_mul, neg_neg, if_pos even_zero] + neg_one_mul, neg_neg, if_pos Even.zero] @[simp] lemma Φ_one : W.Φ 1 = X := by - rw [show 1 = ((0 : ℕ) + 1 : ℤ) by rfl, Φ_ofNat, preΨ'_one, one_pow, mul_one, if_pos even_zero, + rw [show 1 = ((0 : ℕ) + 1 : ℤ) by rfl, Φ_ofNat, preΨ'_one, one_pow, mul_one, if_pos Even.zero, mul_one, preΨ'_zero, mul_zero, zero_mul, sub_zero] @[simp] @@ -423,8 +423,8 @@ lemma Φ_three : W.Φ 3 = X * W.Ψ₃ ^ 2 - W.preΨ₄ * W.Ψ₂Sq := by @[simp] lemma Φ_four : W.Φ 4 = X * W.preΨ₄ ^ 2 * W.Ψ₂Sq - W.Ψ₃ * (W.preΨ₄ * W.Ψ₂Sq ^ 2 - W.Ψ₃ ^ 3) := by rw [show 4 = ((3 : ℕ) + 1 : ℤ) by rfl, Φ_ofNat, preΨ'_four, if_neg <| by decide, - show 3 + 2 = 2 * 2 + 1 by rfl, preΨ'_odd, preΨ'_four, preΨ'_two, if_pos even_zero, preΨ'_one, - preΨ'_three, if_pos even_zero, if_neg <| by decide] + show 3 + 2 = 2 * 2 + 1 by rfl, preΨ'_odd, preΨ'_four, preΨ'_two, if_pos Even.zero, preΨ'_one, + preΨ'_three, if_pos Even.zero, if_neg <| by decide] ring1 @[simp] diff --git a/Mathlib/Data/Bool/Count.lean b/Mathlib/Data/Bool/Count.lean index 8f71b21123ee0..a3bf1706905da 100644 --- a/Mathlib/Data/Bool/Count.lean +++ b/Mathlib/Data/Bool/Count.lean @@ -96,7 +96,7 @@ theorem two_mul_count_bool_eq_ite (hl : Chain' (· ≠ ·) l) (b : Bool) : by_cases h2 : Even (length l) · rw [if_pos h2, hl.two_mul_count_bool_of_even h2] · cases' l with x l - · exact (h2 even_zero).elim + · exact (h2 .zero).elim simp only [if_neg h2, count_cons, mul_add, head?, Option.mem_some_iff, @eq_comm _ x] rw [length_cons, Nat.even_add_one, not_not] at h2 replace hl : l.Chain' (· ≠ ·) := hl.tail diff --git a/Mathlib/Data/Nat/Hyperoperation.lean b/Mathlib/Data/Nat/Hyperoperation.lean index ea0cc84e74cc6..5fadfa52f931a 100644 --- a/Mathlib/Data/Nat/Hyperoperation.lean +++ b/Mathlib/Data/Nat/Hyperoperation.lean @@ -104,7 +104,7 @@ theorem hyperoperation_ge_four_zero (n k : ℕ) : hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by induction' k with kk kih · rw [hyperoperation_ge_three_eq_one] - simp only [even_zero, if_true] + simp only [Even.zero, if_true] · rw [hyperoperation_recursion] rw [kih] simp_rw [Nat.even_add_one] diff --git a/Mathlib/GroupTheory/Coxeter/Basic.lean b/Mathlib/GroupTheory/Coxeter/Basic.lean index c33678eadac13..f19ef6d87ef99 100644 --- a/Mathlib/GroupTheory/Coxeter/Basic.lean +++ b/Mathlib/GroupTheory/Coxeter/Basic.lean @@ -458,7 +458,7 @@ lemma listTake_alternatingWord (i j : B) (p k : ℕ) (h : k < 2 * p) : if Even k then alternatingWord i j k else alternatingWord j i k := by induction k with | zero => - simp only [take_zero, even_zero, ↓reduceIte, alternatingWord] + simp only [take_zero, Even.zero, ↓reduceIte, alternatingWord] | succ k h' => have hk : k < 2 * p := by omega apply h' at hk diff --git a/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean b/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean index 030cc20bab5bb..8368544665f34 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean @@ -160,7 +160,7 @@ theorem quadraticChar_eq_neg_one_iff_not_one {a : F} (ha : a ≠ 0) : /-- For `a : F`, `quadraticChar F a = -1 ↔ ¬ IsSquare a`. -/ theorem quadraticChar_neg_one_iff_not_isSquare {a : F} : quadraticChar F a = -1 ↔ ¬IsSquare a := by by_cases ha : a = 0 - · simp only [ha, MulChar.map_zero, zero_eq_neg, one_ne_zero, isSquare_zero, not_true] + · simp only [ha, MulChar.map_zero, zero_eq_neg, one_ne_zero, IsSquare.zero, not_true] · rw [quadraticChar_eq_neg_one_iff_not_one ha, quadraticChar_one_iff_isSquare ha] /-- If `F` has odd characteristic, then `quadraticChar F` takes the value `-1`. -/ diff --git a/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/GaussSum.lean b/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/GaussSum.lean index b10a0d651815b..29fa07a6854fe 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/GaussSum.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/GaussSum.lean @@ -102,7 +102,7 @@ theorem FiniteField.isSquare_odd_prime_iff (hF : ringChar F ≠ 2) {p : ℕ} [Fa classical by_cases hFp : ringChar F = p · rw [show (p : F) = 0 by rw [← hFp]; exact ringChar.Nat.cast_ringChar] - simp only [isSquare_zero, Ne, true_iff, map_mul] + simp only [IsSquare.zero, Ne, true_iff, map_mul] obtain ⟨n, _, hc⟩ := FiniteField.card F (ringChar F) have hchar : ringChar F = ringChar (ZMod p) := by rw [hFp]; exact (ringChar_zmod_n p).symm conv => enter [1, 1, 2]; rw [hc, Nat.cast_pow, map_pow, hchar, map_ringChar] diff --git a/Mathlib/NumberTheory/NumberField/Embeddings.lean b/Mathlib/NumberTheory/NumberField/Embeddings.lean index c057b1aa09be8..b14ba38413d3d 100644 --- a/Mathlib/NumberTheory/NumberField/Embeddings.lean +++ b/Mathlib/NumberTheory/NumberField/Embeddings.lean @@ -881,7 +881,7 @@ lemma even_nat_card_aut_of_not_isUnramified [IsGalois k K] (hw : ¬ IsUnramified · cases nonempty_fintype (K ≃ₐ[k] K) rw [even_iff_two_dvd, ← not_isUnramified_iff_card_stabilizer_eq_two.mp hw] exact Subgroup.card_subgroup_dvd_card (Stab w) - · convert even_zero + · convert Even.zero by_contra e exact H (Nat.finite_of_card_ne_zero e) @@ -894,7 +894,7 @@ lemma even_finrank_of_not_isUnramified [IsGalois k K] (hw : ¬ IsUnramified k w) : Even (finrank k K) := by by_cases FiniteDimensional k K · exact IsGalois.card_aut_eq_finrank k K ▸ even_card_aut_of_not_isUnramified hw - · exact finrank_of_not_finite ‹_› ▸ even_zero + · exact finrank_of_not_finite ‹_› ▸ Even.zero lemma isUnramified_smul_iff : IsUnramified k (σ • w) ↔ IsUnramified k w := by diff --git a/Mathlib/NumberTheory/SumTwoSquares.lean b/Mathlib/NumberTheory/SumTwoSquares.lean index ae1099ea7d72e..dcc58f8d748e3 100644 --- a/Mathlib/NumberTheory/SumTwoSquares.lean +++ b/Mathlib/NumberTheory/SumTwoSquares.lean @@ -200,7 +200,7 @@ the right hand side holds, since `padicValNat q 0 = 0` by definition.) -/ theorem Nat.eq_sq_add_sq_iff {n : ℕ} : (∃ x y : ℕ, n = x ^ 2 + y ^ 2) ↔ ∀ {q : ℕ}, q.Prime → q % 4 = 3 → Even (padicValNat q n) := by rcases n.eq_zero_or_pos with (rfl | hn₀) - · exact ⟨fun _ q _ _ => (@padicValNat.zero q).symm ▸ even_zero, fun _ => ⟨0, 0, rfl⟩⟩ + · exact ⟨fun _ q _ _ => (@padicValNat.zero q).symm ▸ Even.zero, fun _ => ⟨0, 0, rfl⟩⟩ -- now `0 < n` rw [Nat.eq_sq_add_sq_iff_eq_sq_mul] refine ⟨fun H q hq h => ?_, fun H => ?_⟩ From cae01b3009f9488c7c4544d0a4f4ec2e3088b24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 23 Jan 2025 12:19:59 +0000 Subject: [PATCH 449/681] feat(MvPolynomial): commuting the variables of mv-polynomials of mv-polynomials (#20447) From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang --- Mathlib/Algebra/MvPolynomial/Equiv.lean | 57 +++++++++++++++++++------ 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index 9f7c660990ad0..11ed4077ba4e3 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -184,21 +184,19 @@ theorem iterToSum_X (b : S₁) : iterToSum R S₁ S₂ (X b) = X (Sum.inl b) := theorem iterToSum_C_X (c : S₂) : iterToSum R S₁ S₂ (C (X c)) = X (Sum.inr c) := Eq.trans (eval₂_C _ _ (X c)) (eval₂_X _ _ _) -variable (σ) +section isEmptyRingEquiv +variable [IsEmpty σ] +variable (σ) in /-- The algebra isomorphism between multivariable polynomials in no variables and the ground ring. -/ -@[simps!] -def isEmptyAlgEquiv [he : IsEmpty σ] : MvPolynomial σ R ≃ₐ[R] R := - AlgEquiv.ofAlgHom (aeval (IsEmpty.elim he)) (Algebra.ofId _ _) - (by ext) - (by - ext i m - exact IsEmpty.elim' he i) +@[simps! apply] +def isEmptyAlgEquiv : MvPolynomial σ R ≃ₐ[R] R := + .ofAlgHom (aeval isEmptyElim) (Algebra.ofId _ _) (by ext) (by ext i m; exact isEmptyElim i) -variable {R S₁ σ} in +variable {R S₁} in @[simp] -lemma aeval_injective_iff_of_isEmpty [IsEmpty σ] [CommSemiring S₁] [Algebra R S₁] {f : σ → S₁} : +lemma aeval_injective_iff_of_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 @@ -207,13 +205,20 @@ lemma aeval_injective_iff_of_isEmpty [IsEmpty σ] [CommSemiring S₁] [Algebra R rw [this, ← Injective.of_comp_iff' _ (@isEmptyAlgEquiv R σ _ _).bijective] rfl +variable (σ) in /-- The ring isomorphism between multivariable polynomials in no variables and the ground ring. -/ -@[simps!] -def isEmptyRingEquiv [IsEmpty σ] : MvPolynomial σ R ≃+* R := - (isEmptyAlgEquiv R σ).toRingEquiv +@[simps! apply] +def isEmptyRingEquiv : MvPolynomial σ R ≃+* R := (isEmptyAlgEquiv R σ).toRingEquiv -variable {σ} +lemma isEmptyRingEquiv_symm_toRingHom : (isEmptyRingEquiv R σ).symm.toRingHom = C := rfl +@[simp] lemma isEmptyRingEquiv_symm_apply (r : R) : (isEmptyRingEquiv R σ).symm r = C r := rfl + +lemma isEmptyRingEquiv_eq_coeff_zero {σ R : Type*} [CommSemiring R] [IsEmpty σ] {x} : + isEmptyRingEquiv R σ x = x.coeff 0 := by + obtain ⟨x, rfl⟩ := (isEmptyRingEquiv R σ).symm.surjective x; simp + +end isEmptyRingEquiv /-- A helper function for `sumRingEquiv`. -/ @[simps] @@ -267,6 +272,30 @@ lemma sumAlgEquiv_comp_rename_inl : ext i simp +section commAlgEquiv +variable {R S₁ S₂ : Type*} [CommSemiring R] + +variable (R S₁ S₂) in +/-- The algebra isomorphism between multivariable polynomials in variables `S₁` of multivariable +polynomials in variables `S₂` and multivariable polynomials in variables `S₂` of multivariable +polynomials in variables `S₁`. -/ +noncomputable +def commAlgEquiv : MvPolynomial S₁ (MvPolynomial S₂ R) ≃ₐ[R] MvPolynomial S₂ (MvPolynomial S₁ R) := + (sumAlgEquiv R S₁ S₂).symm.trans <| (renameEquiv _ (.sumComm S₁ S₂)).trans (sumAlgEquiv R S₂ S₁) + +@[simp] lemma commAlgEquiv_C (p) : commAlgEquiv R S₁ S₂ (.C p) = .map C p := by + suffices (commAlgEquiv R S₁ S₂).toAlgHom.comp + (IsScalarTower.toAlgHom R (MvPolynomial S₂ R) _) = mapAlgHom (Algebra.ofId _ _) by + exact DFunLike.congr_fun this p + ext x : 1 + simp [commAlgEquiv] + +lemma commAlgEquiv_C_X (i) : commAlgEquiv R S₁ S₂ (.C (.X i)) = .X i := by simp + +@[simp] lemma commAlgEquiv_X (i) : commAlgEquiv R S₁ S₂ (.X i) = .C (.X i) := by simp [commAlgEquiv] + +end commAlgEquiv + section -- this speeds up typeclass search in the lemma below From 5eb97b6c0aff158ba8e5fef129920f2605ac341a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 23 Jan 2025 12:20:01 +0000 Subject: [PATCH 450/681] chore(CondExp): golf (#20981) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove useless `@` * Remove useless `haveI`/`letI` * Make `m` explicit in `condExp_add`, `condExp_sub`, etc... for use inside `filter_upwards`. Currently, using one of those lemmas in `filter_upwards` results in metavariables. * Reorder the file according to typeclass assumptions * Rename the base σ-algebra to `m₀` and the normed space to `E` From my PhD (LeanCamCombi) --- .../ConditionalExpectation/Basic.lean | 297 +++++++++--------- .../ConditionalExpectation/Indicator.lean | 5 +- .../Function/ConditionalExpectation/Real.lean | 7 +- Mathlib/Probability/Martingale/Basic.lean | 33 +- Mathlib/Probability/Martingale/Centering.lean | 6 +- .../Probability/Martingale/Convergence.lean | 2 +- 6 files changed, 167 insertions(+), 183 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index 0da3f8d3a0c47..8535873e0e0c7 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -8,8 +8,8 @@ import Mathlib.MeasureTheory.Function.ConditionalExpectation.CondexpL1 /-! # Conditional expectation We build the conditional expectation of an integrable function `f` with value in a Banach space -with respect to a measure `μ` (defined on a measurable space structure `m0`) and a measurable space -structure `m` with `hm : m ≤ m0` (a sub-sigma-algebra). This is an `m`-strongly measurable +with respect to a measure `μ` (defined on a measurable space structure `m₀`) and a measurable space +structure `m` with `hm : m ≤ m₀` (a sub-sigma-algebra). This is an `m`-strongly measurable function `μ[f|hm]` which is integrable and verifies `∫ x in s, μ[f|hm] x ∂μ = ∫ x in s, f x ∂μ` for all `m`-measurable sets `s`. It is unique as an element of `L¹`. @@ -38,7 +38,7 @@ The conditional expectation and its properties with respect to `m`. * `integrable_condExp` : `condExp` is integrable. * `stronglyMeasurable_condExp` : `condExp` is `m`-strongly-measurable. -* `setIntegral_condExp (hf : Integrable f μ) (hs : MeasurableSet[m] s)` : if `m ≤ m0` (the +* `setIntegral_condExp (hf : Integrable f μ) (hs : MeasurableSet[m] s)` : if `m ≤ m₀` (the σ-algebra over which the measure is defined), then the conditional expectation verifies `∫ x in s, condExp m μ f x ∂μ = ∫ x in s, f x ∂μ` for any `m`-measurable set `s`. @@ -52,8 +52,8 @@ Uniqueness of the conditional expectation ## Notations -For a measure `μ` defined on a measurable space structure `m0`, another measurable space structure -`m` with `hm : m ≤ m0` (a sub-σ-algebra) and a function `f`, we define the notation +For a measure `μ` defined on a measurable space structure `m₀`, another measurable space structure +`m` with `hm : m ≤ m₀` (a sub-σ-algebra) and a function `f`, we define the notation * `μ[f|m] = condExp m μ f`. ## Tags @@ -62,35 +62,29 @@ conditional expectation, conditional expected value -/ - open TopologicalSpace MeasureTheory.Lp Filter - -open scoped ENNReal Topology MeasureTheory +open scoped Classical ENNReal Topology MeasureTheory namespace MeasureTheory - -variable {α F F' 𝕜 : Type*} [RCLike 𝕜] -- 𝕜 for ℝ or ℂ - -- F' for integrals on a Lp submodule - [NormedAddCommGroup F'] - [NormedSpace 𝕜 F'] [NormedSpace ℝ F'] [CompleteSpace F'] - -open scoped Classical + -- E for integrals on a Lp submodule +variable {α β E 𝕜 : Type*} [RCLike 𝕜] {m m₀ : MeasurableSpace α} {μ : Measure α} {f g : α → E} + {s : Set α} -variable {m m0 : MeasurableSpace α} {μ : Measure α} {f g : α → F'} {s : Set α} +section NormedAddCommGroup +variable [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] +variable (m) in /-- Conditional expectation of a function. It is defined as 0 if any one of the following conditions is true: -- `m` is not a sub-σ-algebra of `m0`, +- `m` is not a sub-σ-algebra of `m₀`, - `μ` is not σ-finite with respect to `m`, - `f` is not integrable. -/ -noncomputable irreducible_def condExp (m : MeasurableSpace α) {m0 : MeasurableSpace α} - (μ : Measure α) (f : α → F') : α → F' := - if hm : m ≤ m0 then +noncomputable irreducible_def condExp (μ : Measure[m₀] α) (f : α → E) : α → E := + if hm : m ≤ m₀ then if h : SigmaFinite (μ.trim hm) ∧ Integrable f μ then if StronglyMeasurable[m] f then f - else (@aestronglyMeasurable'_condExpL1 _ _ _ _ _ m m0 μ hm h.1 _).mk - (@condExpL1 _ _ _ _ _ _ _ hm μ h.1 f) + else have := h.1; aestronglyMeasurable'_condExpL1.mk (condExpL1 hm μ f) else 0 else 0 @@ -99,16 +93,16 @@ noncomputable irreducible_def condExp (m : MeasurableSpace α) {m0 : MeasurableS -- We define notation `μ[f|m]` for the conditional expectation of `f` with respect to `m`. scoped notation μ "[" f "|" m "]" => MeasureTheory.condExp m μ f -theorem condExp_of_not_le (hm_not : ¬m ≤ m0) : μ[f|m] = 0 := by rw [condExp, dif_neg hm_not] +theorem condExp_of_not_le (hm_not : ¬m ≤ m₀) : μ[f|m] = 0 := by rw [condExp, dif_neg hm_not] @[deprecated (since := "2025-01-21")] alias condexp_of_not_le := condExp_of_not_le -theorem condExp_of_not_sigmaFinite (hm : m ≤ m0) (hμm_not : ¬SigmaFinite (μ.trim hm)) : +theorem condExp_of_not_sigmaFinite (hm : m ≤ m₀) (hμm_not : ¬SigmaFinite (μ.trim hm)) : μ[f|m] = 0 := by rw [condExp, dif_pos hm, dif_neg]; push_neg; exact fun h => absurd h hμm_not @[deprecated (since := "2025-01-21")] alias condexp_of_not_sigmaFinite := condExp_of_not_sigmaFinite -theorem condExp_of_sigmaFinite (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : +theorem condExp_of_sigmaFinite (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] : μ[f|m] = if Integrable f μ then if StronglyMeasurable[m] f then f @@ -122,20 +116,19 @@ theorem condExp_of_sigmaFinite (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] @[deprecated (since := "2025-01-21")] alias condexp_of_sigmaFinite := condExp_of_sigmaFinite -theorem condExp_of_stronglyMeasurable (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] {f : α → F'} +theorem condExp_of_stronglyMeasurable (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] {f : α → E} (hf : StronglyMeasurable[m] f) (hfi : Integrable f μ) : μ[f|m] = f := by rw [condExp_of_sigmaFinite hm, if_pos hfi, if_pos hf] @[deprecated (since := "2025-01-21")] alias condexp_of_stronglyMeasurable := condExp_of_stronglyMeasurable -theorem condExp_const (hm : m ≤ m0) (c : F') [IsFiniteMeasure μ] : - μ[fun _ : α => c|m] = fun _ => c := - condExp_of_stronglyMeasurable hm (@stronglyMeasurable_const _ _ m _ _) (integrable_const c) +theorem condExp_const (hm : m ≤ m₀) (c : E) [IsFiniteMeasure μ] : μ[fun _ : α ↦ c|m] = fun _ ↦ c := + condExp_of_stronglyMeasurable hm stronglyMeasurable_const (integrable_const c) @[deprecated (since := "2025-01-21")] alias condexp_const := condExp_const -theorem condExp_ae_eq_condExpL1 (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] (f : α → F') : +theorem condExp_ae_eq_condExpL1 (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] (f : α → E) : μ[f|m] =ᵐ[μ] condExpL1 hm μ f := by rw [condExp_of_sigmaFinite hm] by_cases hfi : Integrable f μ @@ -151,41 +144,37 @@ theorem condExp_ae_eq_condExpL1 (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm) @[deprecated (since := "2025-01-21")] alias condexp_ae_eq_condexpL1 := condExp_ae_eq_condExpL1 -theorem condExp_ae_eq_condExpL1CLM (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) : - μ[f|m] =ᵐ[μ] condExpL1CLM F' hm μ (hf.toL1 f) := by +theorem condExp_ae_eq_condExpL1CLM (hm : m ≤ m₀) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) : + μ[f|m] =ᵐ[μ] condExpL1CLM E hm μ (hf.toL1 f) := by refine (condExp_ae_eq_condExpL1 hm f).trans (Eventually.of_forall fun x => ?_) rw [condExpL1_eq hf] @[deprecated (since := "2025-01-21")] alias condexp_ae_eq_condexpL1CLM := condExp_ae_eq_condExpL1CLM theorem condExp_undef (hf : ¬Integrable f μ) : μ[f|m] = 0 := by - by_cases hm : m ≤ m0 + by_cases hm : m ≤ m₀ swap; · rw [condExp_of_not_le hm] by_cases hμm : SigmaFinite (μ.trim hm) swap; · rw [condExp_of_not_sigmaFinite hm hμm] - haveI : SigmaFinite (μ.trim hm) := hμm rw [condExp_of_sigmaFinite, if_neg hf] @[deprecated (since := "2025-01-21")] alias condexp_undef := condExp_undef @[simp] -theorem condExp_zero : μ[(0 : α → F')|m] = 0 := by - by_cases hm : m ≤ m0 +theorem condExp_zero : μ[(0 : α → E)|m] = 0 := by + by_cases hm : m ≤ m₀ swap; · rw [condExp_of_not_le hm] by_cases hμm : SigmaFinite (μ.trim hm) swap; · rw [condExp_of_not_sigmaFinite hm hμm] - haveI : SigmaFinite (μ.trim hm) := hμm - exact - condExp_of_stronglyMeasurable hm (@stronglyMeasurable_zero _ _ m _ _) (integrable_zero _ _ _) + exact condExp_of_stronglyMeasurable hm stronglyMeasurable_zero (integrable_zero _ _ _) @[deprecated (since := "2025-01-21")] alias condexp_zero := condExp_zero theorem stronglyMeasurable_condExp : StronglyMeasurable[m] (μ[f|m]) := by - by_cases hm : m ≤ m0 + by_cases hm : m ≤ m₀ swap; · rw [condExp_of_not_le hm]; exact stronglyMeasurable_zero by_cases hμm : SigmaFinite (μ.trim hm) swap; · rw [condExp_of_not_sigmaFinite hm hμm]; exact stronglyMeasurable_zero - haveI : SigmaFinite (μ.trim hm) := hμm rw [condExp_of_sigmaFinite hm] split_ifs with hfi hfm · exact hfm @@ -195,18 +184,17 @@ theorem stronglyMeasurable_condExp : StronglyMeasurable[m] (μ[f|m]) := by @[deprecated (since := "2025-01-21")] alias stronglyMeasurable_condexp := stronglyMeasurable_condExp theorem condExp_congr_ae (h : f =ᵐ[μ] g) : μ[f|m] =ᵐ[μ] μ[g|m] := by - by_cases hm : m ≤ m0 + by_cases hm : m ≤ m₀ swap; · simp_rw [condExp_of_not_le hm]; rfl by_cases hμm : SigmaFinite (μ.trim hm) swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl - haveI : SigmaFinite (μ.trim hm) := hμm exact (condExp_ae_eq_condExpL1 hm f).trans (Filter.EventuallyEq.trans (by rw [condExpL1_congr_ae hm h]) (condExp_ae_eq_condExpL1 hm g).symm) @[deprecated (since := "2025-01-21")] alias condexp_congr_ae := condExp_congr_ae -theorem condExp_of_aestronglyMeasurable' (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] {f : α → F'} +theorem condExp_of_aestronglyMeasurable' (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] {f : α → E} (hf : AEStronglyMeasurable' m f μ) (hfi : Integrable f μ) : μ[f|m] =ᵐ[μ] f := by refine ((condExp_congr_ae hf.ae_eq_mk).trans ?_).trans hf.ae_eq_mk.symm rw [condExp_of_stronglyMeasurable hm hf.stronglyMeasurable_mk @@ -217,18 +205,17 @@ alias condexp_of_aestronglyMeasurable' := condExp_of_aestronglyMeasurable' @[fun_prop] theorem integrable_condExp : Integrable (μ[f|m]) μ := by - by_cases hm : m ≤ m0 + by_cases hm : m ≤ m₀ swap; · rw [condExp_of_not_le hm]; exact integrable_zero _ _ _ by_cases hμm : SigmaFinite (μ.trim hm) swap; · rw [condExp_of_not_sigmaFinite hm hμm]; exact integrable_zero _ _ _ - haveI : SigmaFinite (μ.trim hm) := hμm exact (integrable_condExpL1 f).congr (condExp_ae_eq_condExpL1 hm f).symm @[deprecated (since := "2025-01-21")] alias integrable_condexp := integrable_condExp /-- The integral of the conditional expectation `μ[f|hm]` over an `m`-measurable set is equal to the integral of `f` on that set. -/ -theorem setIntegral_condExp (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) +theorem setIntegral_condExp (hm : m ≤ m₀) [SigmaFinite (μ.trim hm)] (hf : Integrable f μ) (hs : MeasurableSet[m] s) : ∫ x in s, (μ[f|m]) x ∂μ = ∫ x in s, f x ∂μ := by rw [setIntegral_congr_ae (hm s hs) ((condExp_ae_eq_condExpL1 hm f).mono fun x hx _ => hx)] exact setIntegral_condExpL1 hf hs @@ -237,20 +224,20 @@ theorem setIntegral_condExp (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hf : Int @[deprecated (since := "2024-04-17")] alias set_integral_condexp := setIntegral_condExp -theorem integral_condExp (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : +theorem integral_condExp (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] : ∫ x, (μ[f|m]) x ∂μ = ∫ x, f x ∂μ := by by_cases hf : Integrable f μ · suffices ∫ x in Set.univ, (μ[f|m]) x ∂μ = ∫ x in Set.univ, f x ∂μ by simp_rw [setIntegral_univ] at this; exact this - exact setIntegral_condExp hm hf (@MeasurableSet.univ _ m) + exact setIntegral_condExp hm hf .univ simp only [condExp_undef hf, Pi.zero_apply, integral_zero, integral_undef hf] @[deprecated (since := "2025-01-21")] alias integral_condexp := integral_condExp -/-- Total probability law using `condExp` as conditional probability. -/ -theorem integral_condExp_indicator [mF : MeasurableSpace F] {Y : α → F} (hY : Measurable Y) +/-- **Law of total probability** using `condExp` as conditional probability. -/ +theorem integral_condExp_indicator [mβ : MeasurableSpace β] {Y : α → β} (hY : Measurable Y) [SigmaFinite (μ.trim hY.comap_le)] {A : Set α} (hA : MeasurableSet A) : - ∫ x, (μ[(A.indicator fun _ ↦ (1 : ℝ)) | mF.comap Y]) x ∂μ = (μ A).toReal := by + ∫ x, (μ[(A.indicator fun _ ↦ (1 : ℝ)) | mβ.comap Y]) x ∂μ = (μ A).toReal := by rw [integral_condExp, integral_indicator hA, setIntegral_const, smul_eq_mul, mul_one] @[deprecated (since := "2025-01-21")] alias integral_condexp_indicator := integral_condExp_indicator @@ -258,8 +245,8 @@ theorem integral_condExp_indicator [mF : MeasurableSpace F] {Y : α → F} (hY : /-- **Uniqueness of the conditional expectation** If a function is a.e. `m`-measurable, verifies an integrability condition and has same integral as `f` on all `m`-measurable sets, then it is a.e. equal to `μ[f|hm]`. -/ -theorem ae_eq_condExp_of_forall_setIntegral_eq (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] - {f g : α → F'} (hf : Integrable f μ) +theorem ae_eq_condExp_of_forall_setIntegral_eq (hm : m ≤ m₀) [SigmaFinite (μ.trim hm)] + {f g : α → E} (hf : Integrable f μ) (hg_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn g s μ) (hg_eq : ∀ s : Set α, MeasurableSet[m] s → μ s < ∞ → ∫ x in s, g x ∂μ = ∫ x in s, f x ∂μ) (hgm : AEStronglyMeasurable' m g μ) : g =ᵐ[μ] μ[f|m] := by @@ -277,51 +264,7 @@ alias ae_eq_condExp_of_forall_set_integral_eq := ae_eq_condExp_of_forall_setInte @[deprecated (since := "2025-01-21")] alias ae_eq_condexp_of_forall_set_integral_eq := ae_eq_condExp_of_forall_set_integral_eq -section MemL2 - -lemma Memℒp.condExpL2_ae_eq_condExp' {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] - (hm : m ≤ m0) (hf1 : Integrable f μ) (hf2 : Memℒp f 2 μ) [SigmaFinite (μ.trim hm)] : - condExpL2 F' 𝕜 hm hf2.toLp =ᵐ[μ] μ[f | m] := by - refine ae_eq_condExp_of_forall_setIntegral_eq hm hf1 - (fun s hs htop ↦ integrableOn_condExpL2_of_measure_ne_top hm htop.ne _) (fun s hs htop ↦ ?_) - (aeStronglyMeasurable'_condExpL2 hm _) - rw [integral_condExpL2_eq hm (hf2.toLp _) hs htop.ne] - refine setIntegral_congr_ae (hm _ hs) ?_ - filter_upwards [hf2.coeFn_toLp] with ω hω _ using hω - -lemma Memℒp.condExpL2_ae_eq_condExp {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] - (hm : m ≤ m0) (hf : Memℒp f 2 μ) [IsFiniteMeasure μ] : - condExpL2 F' 𝕜 hm hf.toLp =ᵐ[μ] μ[f | m] := - hf.condExpL2_ae_eq_condExp' hm (memℒp_one_iff_integrable.1 <| hf.mono_exponent one_le_two) - --- TODO: Generalize via the conditional Jensen inequality -lemma eLpNorm_condExp_le {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] : - eLpNorm (μ[f | m]) 2 μ ≤ eLpNorm f 2 μ := by - by_cases hm : m ≤ m0; swap - · simp [condExp_of_not_le hm] - by_cases hfμ : SigmaFinite (μ.trim hm); swap - · rw [condExp_of_not_sigmaFinite hm hfμ] - simp - by_cases hfi : Integrable f μ; swap - · rw [condExp_undef hfi] - simp - obtain hf | hf := eq_or_ne (eLpNorm f 2 μ) ∞ - · simp [hf] - replace hf : Memℒp f 2 μ := ⟨hfi.1, Ne.lt_top' fun a ↦ hf (id (Eq.symm a))⟩ - rw [← eLpNorm_congr_ae (hf.condExpL2_ae_eq_condExp' (𝕜 := 𝕜) hm hfi)] - refine le_trans (eLpNorm_condExpL2_le hm _) ?_ - rw [eLpNorm_congr_ae hf.coeFn_toLp] - -protected lemma Memℒp.condExp {𝕜 : Type*} [RCLike 𝕜] [InnerProductSpace 𝕜 F'] - (hf : Memℒp f 2 μ) : Memℒp (μ[f | m]) 2 μ := by - by_cases hm : m ≤ m0 - · exact ⟨(stronglyMeasurable_condExp.mono hm).aestronglyMeasurable, - eLpNorm_condExp_le (𝕜 := 𝕜).trans_lt hf.eLpNorm_lt_top⟩ - · simp [condExp_of_not_le hm] - -end MemL2 - -theorem condExp_bot' [hμ : NeZero μ] (f : α → F') : +theorem condExp_bot' [hμ : NeZero μ] (f : α → E) : μ[f|⊥] = fun _ => (μ Set.univ).toReal⁻¹ • ∫ x, f x ∂μ := by by_cases hμ_finite : IsFiniteMeasure μ swap @@ -341,7 +284,7 @@ theorem condExp_bot' [hμ : NeZero μ] (f : α → F') : @[deprecated (since := "2025-01-21")] alias condexp_bot' := condExp_bot' -theorem condExp_bot_ae_eq (f : α → F') : +theorem condExp_bot_ae_eq (f : α → E) : μ[f|⊥] =ᵐ[μ] fun _ => (μ Set.univ).toReal⁻¹ • ∫ x, f x ∂μ := by rcases eq_zero_or_neZero μ with rfl | hμ · rw [ae_zero]; exact eventually_bot @@ -349,18 +292,17 @@ theorem condExp_bot_ae_eq (f : α → F') : @[deprecated (since := "2025-01-21")] alias condexp_bot_ae_eq := condExp_bot_ae_eq -theorem condExp_bot [IsProbabilityMeasure μ] (f : α → F') : μ[f|⊥] = fun _ => ∫ x, f x ∂μ := by +theorem condExp_bot [IsProbabilityMeasure μ] (f : α → E) : μ[f|⊥] = fun _ => ∫ x, f x ∂μ := by refine (condExp_bot' f).trans ?_; rw [measure_univ, ENNReal.one_toReal, inv_one, one_smul] @[deprecated (since := "2025-01-21")] alias condexp_bot := condExp_bot -theorem condExp_add (hf : Integrable f μ) (hg : Integrable g μ) : +theorem condExp_add (hf : Integrable f μ) (hg : Integrable g μ) (m : MeasurableSpace α) : μ[f + g|m] =ᵐ[μ] μ[f|m] + μ[g|m] := by - by_cases hm : m ≤ m0 + by_cases hm : m ≤ m₀ swap; · simp_rw [condExp_of_not_le hm]; simp by_cases hμm : SigmaFinite (μ.trim hm) swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; simp - haveI : SigmaFinite (μ.trim hm) := hμm refine (condExp_ae_eq_condExpL1 hm _).trans ?_ rw [condExpL1_add hf hg] exact (coeFn_add _ _).trans @@ -368,101 +310,119 @@ theorem condExp_add (hf : Integrable f μ) (hg : Integrable g μ) : @[deprecated (since := "2025-01-21")] alias condexp_add := condExp_add -theorem condExp_finset_sum {ι : Type*} {s : Finset ι} {f : ι → α → F'} - (hf : ∀ i ∈ s, Integrable (f i) μ) : μ[∑ i ∈ s, f i|m] =ᵐ[μ] ∑ i ∈ s, μ[f i|m] := by +theorem condExp_finset_sum {ι : Type*} {s : Finset ι} {f : ι → α → E} + (hf : ∀ i ∈ s, Integrable (f i) μ) (m : MeasurableSpace α) : + μ[∑ i ∈ s, f i|m] =ᵐ[μ] ∑ i ∈ s, μ[f i|m] := by induction' s using Finset.induction_on with i s his heq hf · rw [Finset.sum_empty, Finset.sum_empty, condExp_zero] · rw [Finset.sum_insert his, Finset.sum_insert his] - exact (condExp_add (hf i <| Finset.mem_insert_self i s) <| - integrable_finset_sum' _ fun j hmem => hf j <| Finset.mem_insert_of_mem hmem).trans - ((EventuallyEq.refl _ _).add (heq fun j hmem => hf j <| Finset.mem_insert_of_mem hmem)) + exact (condExp_add (hf i <| Finset.mem_insert_self i s) + (integrable_finset_sum' _ <| Finset.forall_of_forall_insert hf) _).trans + ((EventuallyEq.refl _ _).add <| heq <| Finset.forall_of_forall_insert hf) @[deprecated (since := "2025-01-21")] alias condexp_finset_sum := condExp_finset_sum -theorem condExp_smul (c : 𝕜) (f : α → F') : μ[c • f|m] =ᵐ[μ] c • μ[f|m] := by - by_cases hm : m ≤ m0 +theorem condExp_smul [NormedSpace 𝕜 E] (c : 𝕜) (f : α → E) (m : MeasurableSpace α) : + μ[c • f|m] =ᵐ[μ] c • μ[f|m] := by + by_cases hm : m ≤ m₀ swap; · simp_rw [condExp_of_not_le hm]; simp by_cases hμm : SigmaFinite (μ.trim hm) swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; simp - haveI : SigmaFinite (μ.trim hm) := hμm refine (condExp_ae_eq_condExpL1 hm _).trans ?_ rw [condExpL1_smul c f] - refine (@condExp_ae_eq_condExpL1 _ _ _ _ _ m _ _ hm _ f).mp ?_ + refine (condExp_ae_eq_condExpL1 hm f).mp ?_ refine (coeFn_smul c (condExpL1 hm μ f)).mono fun x hx1 hx2 => ?_ simp only [hx1, hx2, Pi.smul_apply] @[deprecated (since := "2025-01-21")] alias condexp_smul := condExp_smul -theorem condExp_neg (f : α → F') : μ[-f|m] =ᵐ[μ] -μ[f|m] := by - letI : Module ℝ (α → F') := @Pi.module α (fun _ => F') ℝ _ _ fun _ => inferInstance +theorem condExp_neg (f : α → E) (m : MeasurableSpace α) : μ[-f|m] =ᵐ[μ] -μ[f|m] := by calc μ[-f|m] = μ[(-1 : ℝ) • f|m] := by rw [neg_one_smul ℝ f] - _ =ᵐ[μ] (-1 : ℝ) • μ[f|m] := condExp_smul (-1) f + _ =ᵐ[μ] (-1 : ℝ) • μ[f|m] := condExp_smul .. _ = -μ[f|m] := neg_one_smul ℝ (μ[f|m]) @[deprecated (since := "2025-01-21")] alias condexp_neg := condExp_neg -theorem condExp_sub (hf : Integrable f μ) (hg : Integrable g μ) : +theorem condExp_sub (hf : Integrable f μ) (hg : Integrable g μ) (m : MeasurableSpace α) : μ[f - g|m] =ᵐ[μ] μ[f|m] - μ[g|m] := by simp_rw [sub_eq_add_neg] - exact (condExp_add hf hg.neg).trans (EventuallyEq.rfl.add (condExp_neg g)) + exact (condExp_add hf hg.neg _).trans (EventuallyEq.rfl.add (condExp_neg ..)) @[deprecated (since := "2025-01-21")] alias condexp_sub := condExp_sub -theorem condExp_condExp_of_le {m₁ m₂ m0 : MeasurableSpace α} {μ : Measure α} (hm₁₂ : m₁ ≤ m₂) - (hm₂ : m₂ ≤ m0) [SigmaFinite (μ.trim hm₂)] : μ[μ[f|m₂]|m₁] =ᵐ[μ] μ[f|m₁] := by +/-- **Tower property of the conditional expectation**. + +Taking the `m₂`-conditional expectation then the `m₁`-conditional expectation, where `m₁` is a +smaller σ-algebra, is the same as taking the `m₁`-conditional expectation directly. -/ +theorem condExp_condExp_of_le {m₁ m₂ m₀ : MeasurableSpace α} {μ : Measure α} (hm₁₂ : m₁ ≤ m₂) + (hm₂ : m₂ ≤ m₀) [SigmaFinite (μ.trim hm₂)] : μ[μ[f|m₂]|m₁] =ᵐ[μ] μ[f|m₁] := by by_cases hμm₁ : SigmaFinite (μ.trim (hm₁₂.trans hm₂)) swap; · simp_rw [condExp_of_not_sigmaFinite (hm₁₂.trans hm₂) hμm₁]; rfl - haveI : SigmaFinite (μ.trim (hm₁₂.trans hm₂)) := hμm₁ by_cases hf : Integrable f μ swap; · simp_rw [condExp_undef hf, condExp_zero]; rfl refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' (hm₁₂.trans hm₂) - (fun s _ _ => integrable_condExp.integrableOn) - (fun s _ _ => integrable_condExp.integrableOn) ?_ - (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condExp) - (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condExp) + (fun s _ _ => integrable_condExp.integrableOn) (fun s _ _ => integrable_condExp.integrableOn) ?_ + stronglyMeasurable_condExp.aeStronglyMeasurable' + stronglyMeasurable_condExp.aeStronglyMeasurable' intro s hs _ rw [setIntegral_condExp (hm₁₂.trans hm₂) integrable_condExp hs] rw [setIntegral_condExp (hm₁₂.trans hm₂) hf hs, setIntegral_condExp hm₂ hf (hm₁₂ s hs)] @[deprecated (since := "2025-01-21")] alias condexp_condexp_of_le := condExp_condExp_of_le -theorem condExp_mono {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] - [OrderedSMul ℝ E] {f g : α → E} (hf : Integrable f μ) (hg : Integrable g μ) (hfg : f ≤ᵐ[μ] g) : - μ[f|m] ≤ᵐ[μ] μ[g|m] := by - by_cases hm : m ≤ m0 - swap; · simp_rw [condExp_of_not_le hm]; rfl - by_cases hμm : SigmaFinite (μ.trim hm) - swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl - haveI : SigmaFinite (μ.trim hm) := hμm - exact (condExp_ae_eq_condExpL1 hm _).trans_le - ((condExpL1_mono hf hg hfg).trans_eq (condExp_ae_eq_condExpL1 hm _).symm) +section MemL2 +variable [InnerProductSpace 𝕜 E] -@[deprecated (since := "2025-01-21")] alias condexp_mono := condExp_mono +lemma Memℒp.condExpL2_ae_eq_condExp' (hm : m ≤ m₀) (hf1 : Integrable f μ) (hf2 : Memℒp f 2 μ) + [SigmaFinite (μ.trim hm)] : condExpL2 E 𝕜 hm hf2.toLp =ᵐ[μ] μ[f | m] := by + refine ae_eq_condExp_of_forall_setIntegral_eq hm hf1 + (fun s hs htop ↦ integrableOn_condExpL2_of_measure_ne_top hm htop.ne _) (fun s hs htop ↦ ?_) + (aeStronglyMeasurable'_condExpL2 hm _) + rw [integral_condExpL2_eq hm (hf2.toLp _) hs htop.ne] + refine setIntegral_congr_ae (hm _ hs) ?_ + filter_upwards [hf2.coeFn_toLp] with ω hω _ using hω -theorem condExp_nonneg {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] - [OrderedSMul ℝ E] {f : α → E} (hf : 0 ≤ᵐ[μ] f) : 0 ≤ᵐ[μ] μ[f|m] := by - by_cases hfint : Integrable f μ - · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] - exact condExp_mono (integrable_zero _ _ _) hfint hf - · rw [condExp_undef hfint] +lemma Memℒp.condExpL2_ae_eq_condExp (hm : m ≤ m₀) (hf : Memℒp f 2 μ) [IsFiniteMeasure μ] : + condExpL2 E 𝕜 hm hf.toLp =ᵐ[μ] μ[f | m] := + hf.condExpL2_ae_eq_condExp' hm (memℒp_one_iff_integrable.1 <| hf.mono_exponent one_le_two) -@[deprecated (since := "2025-01-21")] alias condexp_nonneg := condExp_nonneg +-- TODO: Generalize via the conditional Jensen inequality +include 𝕜 in +lemma eLpNorm_condExp_le : eLpNorm (μ[f | m]) 2 μ ≤ eLpNorm f 2 μ := by + by_cases hm : m ≤ m₀; swap + · simp [condExp_of_not_le hm] + by_cases hfμ : SigmaFinite (μ.trim hm); swap + · rw [condExp_of_not_sigmaFinite hm hfμ] + simp + by_cases hfi : Integrable f μ; swap + · rw [condExp_undef hfi] + simp + obtain hf | hf := eq_or_ne (eLpNorm f 2 μ) ∞ + · simp [hf] + replace hf : Memℒp f 2 μ := ⟨hfi.1, Ne.lt_top' fun a ↦ hf (id (Eq.symm a))⟩ + rw [← eLpNorm_congr_ae (hf.condExpL2_ae_eq_condExp' (𝕜 := 𝕜) hm hfi)] + refine le_trans (eLpNorm_condExpL2_le hm _) ?_ + rw [eLpNorm_congr_ae hf.coeFn_toLp] -theorem condExp_nonpos {E} [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] - [OrderedSMul ℝ E] {f : α → E} (hf : f ≤ᵐ[μ] 0) : μ[f|m] ≤ᵐ[μ] 0 := by - by_cases hfint : Integrable f μ - · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] - exact condExp_mono hfint (integrable_zero _ _ _) hf - · rw [condExp_undef hfint] +include 𝕜 in +protected lemma Memℒp.condExp (hf : Memℒp f 2 μ) : Memℒp (μ[f | m]) 2 μ := by + by_cases hm : m ≤ m₀ + · exact ⟨(stronglyMeasurable_condExp.mono hm).aestronglyMeasurable, + eLpNorm_condExp_le (𝕜 := 𝕜).trans_lt hf.eLpNorm_lt_top⟩ + · simp [condExp_of_not_le hm] -@[deprecated (since := "2025-01-21")] alias condexp_nonpos := condExp_nonpos +end MemL2 +end NormedAddCommGroup + +section NormedLatticeAddCommGroup +variable [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] /-- **Lebesgue dominated convergence theorem**: sufficient conditions under which almost everywhere convergence of a sequence of functions implies the convergence of their image by `condExpL1`. -/ -theorem tendsto_condExpL1_of_dominated_convergence (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] - {fs : ℕ → α → F'} {f : α → F'} (bound_fs : α → ℝ) +theorem tendsto_condExpL1_of_dominated_convergence (hm : m ≤ m₀) [SigmaFinite (μ.trim hm)] + {fs : ℕ → α → E} {f : α → E} (bound_fs : α → ℝ) (hfs_meas : ∀ n, AEStronglyMeasurable (fs n) μ) (h_int_bound_fs : Integrable bound_fs μ) (hfs_bound : ∀ n, ∀ᵐ x ∂μ, ‖fs n x‖ ≤ bound_fs x) (hfs : ∀ᵐ x ∂μ, Tendsto (fun n => fs n x) atTop (𝓝 (f x))) : @@ -475,7 +435,7 @@ alias tendsto_condexpL1_of_dominated_convergence := tendsto_condExpL1_of_dominat /-- If two sequences of functions have a.e. equal conditional expectations at each step, converge and verify dominated convergence hypotheses, then the conditional expectations of their limits are a.e. equal. -/ -theorem tendsto_condExp_unique (fs gs : ℕ → α → F') (f g : α → F') +theorem tendsto_condExp_unique (fs gs : ℕ → α → E) (f g : α → E) (hfs_int : ∀ n, Integrable (fs n) μ) (hgs_int : ∀ n, Integrable (gs n) μ) (hfs : ∀ᵐ x ∂μ, Tendsto (fun n => fs n x) atTop (𝓝 (f x))) (hgs : ∀ᵐ x ∂μ, Tendsto (fun n => gs n x) atTop (𝓝 (g x))) (bound_fs : α → ℝ) @@ -483,9 +443,8 @@ theorem tendsto_condExp_unique (fs gs : ℕ → α → F') (f g : α → F') (h_int_bound_gs : Integrable bound_gs μ) (hfs_bound : ∀ n, ∀ᵐ x ∂μ, ‖fs n x‖ ≤ bound_fs x) (hgs_bound : ∀ n, ∀ᵐ x ∂μ, ‖gs n x‖ ≤ bound_gs x) (hfg : ∀ n, μ[fs n|m] =ᵐ[μ] μ[gs n|m]) : μ[f|m] =ᵐ[μ] μ[g|m] := by - by_cases hm : m ≤ m0; swap; · simp_rw [condExp_of_not_le hm]; rfl + by_cases hm : m ≤ m₀; swap; · simp_rw [condExp_of_not_le hm]; rfl by_cases hμm : SigmaFinite (μ.trim hm); swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl - haveI : SigmaFinite (μ.trim hm) := hμm refine (condExp_ae_eq_condExpL1 hm f).trans ((condExp_ae_eq_condExpL1 hm g).trans ?_).symm rw [← Lp.ext_iff] have hn_eq : ∀ n, condExpL1 hm μ (gs n) = condExpL1 hm μ (fs n) := by @@ -503,4 +462,32 @@ theorem tendsto_condExp_unique (fs gs : ℕ → α → F') (f g : α → F') @[deprecated (since := "2025-01-21")] alias tendsto_condexp_unique := tendsto_condExp_unique +variable [OrderedSMul ℝ E] + +lemma condExp_mono (hf : Integrable f μ) (hg : Integrable g μ) (hfg : f ≤ᵐ[μ] g) : + μ[f|m] ≤ᵐ[μ] μ[g|m] := by + by_cases hm : m ≤ m₀ + swap; · simp_rw [condExp_of_not_le hm]; rfl + by_cases hμm : SigmaFinite (μ.trim hm) + swap; · simp_rw [condExp_of_not_sigmaFinite hm hμm]; rfl + exact (condExp_ae_eq_condExpL1 hm _).trans_le + ((condExpL1_mono hf hg hfg).trans_eq (condExp_ae_eq_condExpL1 hm _).symm) + +lemma condExp_nonneg (hf : 0 ≤ᵐ[μ] f) : 0 ≤ᵐ[μ] μ[f|m] := by + by_cases hfint : Integrable f μ + · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] + exact condExp_mono (integrable_zero _ _ _) hfint hf + · rw [condExp_undef hfint] + +lemma condExp_nonpos (hf : f ≤ᵐ[μ] 0) : μ[f|m] ≤ᵐ[μ] 0 := by + by_cases hfint : Integrable f μ + · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] + exact condExp_mono hfint (integrable_zero _ _ _) hf + · rw [condExp_undef hfint] + +@[deprecated (since := "2025-01-21")] alias condexp_mono := condExp_mono +@[deprecated (since := "2025-01-21")] alias condexp_nonneg := condExp_nonneg +@[deprecated (since := "2025-01-21")] alias condexp_nonpos := condExp_nonpos + +end NormedLatticeAddCommGroup end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean index f27dbe2805802..6501fdc7fa2bf 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean @@ -88,9 +88,8 @@ theorem condExp_indicator (hf_int : Integrable f μ) (hs : MeasurableSet[m] s) : calc s.indicator (μ[s.indicator f + sᶜ.indicator f|m]) =ᵐ[μ] s.indicator (μ[s.indicator f|m] + μ[sᶜ.indicator f|m]) := by - have : μ[s.indicator f + sᶜ.indicator f|m] =ᵐ[μ] μ[s.indicator f|m] + μ[sᶜ.indicator f|m] := - condExp_add (hf_int.indicator (hm _ hs)) (hf_int.indicator (hm _ hs.compl)) - filter_upwards [this] with x hx + filter_upwards [condExp_add (hf_int.indicator (hm _ hs)) (hf_int.indicator (hm _ hs.compl)) m] + with x hx classical rw [Set.indicator_apply, Set.indicator_apply, hx] _ = s.indicator (μ[s.indicator f|m]) + s.indicator (μ[sᶜ.indicator f|m]) := (s.indicator_add' _ _) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index dd17a8eeed254..099cc8d17c46d 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -67,8 +67,7 @@ theorem eLpNorm_one_condExp_le_eLpNorm (f : α → ℝ) : eLpNorm (μ[f|m]) 1 μ refine eLpNorm_mono_ae ?_ filter_upwards [condExp_mono hf hf.abs (ae_of_all μ (fun x => le_abs_self (f x) : ∀ x, f x ≤ |f x|)), - EventuallyLE.trans (condExp_neg f).symm.le - (condExp_mono hf.neg hf.abs + (condExp_neg ..).symm.le.trans (condExp_mono hf.neg hf.abs (ae_of_all μ (fun x => neg_le_abs (f x) : ∀ x, -f x ≤ |f x|)))] with x hx₁ hx₂ exact abs_le_abs hx₁ hx₂ _ = eLpNorm f 1 μ := by @@ -256,14 +255,14 @@ theorem condExp_stronglyMeasurable_simpleFunc_mul (hm : m ≤ m0) (f : @SimpleFu @SimpleFunc.coe_const _ _ m, @SimpleFunc.coe_zero _ _ m, Set.piecewise_eq_indicator] rw [this, this] refine (condExp_indicator (hg.smul c) hs).trans ?_ - filter_upwards [condExp_smul (m := m) (m0 := m0) c g] with x hx + filter_upwards [condExp_smul c g m] with x hx classical simp_rw [Set.indicator_apply, hx] · have h_add := @SimpleFunc.coe_add _ _ m _ g₁ g₂ calc μ[⇑(g₁ + g₂) * g|m] =ᵐ[μ] μ[(⇑g₁ + ⇑g₂) * g|m] := by refine condExp_congr_ae (EventuallyEq.mul ?_ EventuallyEq.rfl); rw [h_add] _ =ᵐ[μ] μ[⇑g₁ * g|m] + μ[⇑g₂ * g|m] := by - rw [add_mul]; exact condExp_add (hg.simpleFunc_mul' hm _) (hg.simpleFunc_mul' hm _) + rw [add_mul]; exact condExp_add (hg.simpleFunc_mul' hm _) (hg.simpleFunc_mul' hm _) _ _ =ᵐ[μ] ⇑g₁ * μ[g|m] + ⇑g₂ * μ[g|m] := EventuallyEq.add h_eq₁ h_eq₂ _ =ᵐ[μ] ⇑(g₁ + g₂) * μ[g|m] := by rw [h_add, add_mul] diff --git a/Mathlib/Probability/Martingale/Basic.lean b/Mathlib/Probability/Martingale/Basic.lean index 125817d26cf59..9b7789b528d40 100644 --- a/Mathlib/Probability/Martingale/Basic.lean +++ b/Mathlib/Probability/Martingale/Basic.lean @@ -98,7 +98,7 @@ protected theorem integrable (hf : Martingale f ℱ μ) (i : ι) : Integrable (f theorem setIntegral_eq [SigmaFiniteFiltration μ ℱ] (hf : Martingale f ℱ μ) {i j : ι} (hij : i ≤ j) {s : Set Ω} (hs : MeasurableSet[ℱ i] s) : ∫ ω in s, f i ω ∂μ = ∫ ω in s, f j ω ∂μ := by - rw [← @setIntegral_condExp _ _ _ _ _ (ℱ i) m0 _ _ _ (ℱ.le i) _ (hf.integrable j) hs] + rw [← setIntegral_condExp (ℱ.le i) (hf.integrable j) hs] refine setIntegral_congr_ae (ℱ.le i s hs) ?_ filter_upwards [hf.2 i j hij] with _ heq _ using heq.symm @@ -107,17 +107,18 @@ alias set_integral_eq := setIntegral_eq theorem add (hf : Martingale f ℱ μ) (hg : Martingale g ℱ μ) : Martingale (f + g) ℱ μ := by refine ⟨hf.adapted.add hg.adapted, fun i j hij => ?_⟩ - exact (condExp_add (hf.integrable j) (hg.integrable j)).trans ((hf.2 i j hij).add (hg.2 i j hij)) + exact (condExp_add (hf.integrable j) (hg.integrable j) _).trans + ((hf.2 i j hij).add (hg.2 i j hij)) theorem neg (hf : Martingale f ℱ μ) : Martingale (-f) ℱ μ := - ⟨hf.adapted.neg, fun i j hij => (condExp_neg (f j)).trans (hf.2 i j hij).neg⟩ + ⟨hf.adapted.neg, fun i j hij => (condExp_neg ..).trans (hf.2 i j hij).neg⟩ theorem sub (hf : Martingale f ℱ μ) (hg : Martingale g ℱ μ) : Martingale (f - g) ℱ μ := by rw [sub_eq_add_neg]; exact hf.add hg.neg theorem smul (c : ℝ) (hf : Martingale f ℱ μ) : Martingale (c • f) ℱ μ := by refine ⟨hf.adapted.smul c, fun i j hij => ?_⟩ - refine (condExp_smul c (f j)).trans ((hf.2 i j hij).mono fun x hx => ?_) + refine (condExp_smul ..).trans ((hf.2 i j hij).mono fun x hx => ?_) simp only [Pi.smul_apply, hx] theorem supermartingale [Preorder E] (hf : Martingale f ℱ μ) : Supermartingale f ℱ μ := @@ -170,7 +171,7 @@ alias set_integral_le := setIntegral_le theorem add [Preorder E] [AddLeftMono E] (hf : Supermartingale f ℱ μ) (hg : Supermartingale g ℱ μ) : Supermartingale (f + g) ℱ μ := by refine ⟨hf.1.add hg.1, fun i j hij => ?_, fun i => (hf.2.2 i).add (hg.2.2 i)⟩ - refine (condExp_add (hf.integrable j) (hg.integrable j)).le.trans ?_ + refine (condExp_add (hf.integrable j) (hg.integrable j) _).le.trans ?_ filter_upwards [hf.2.1 i j hij, hg.2.1 i j hij] intros refine add_le_add ?_ ?_ <;> assumption @@ -182,7 +183,7 @@ theorem add_martingale [Preorder E] [AddLeftMono E] theorem neg [Preorder E] [AddLeftMono E] (hf : Supermartingale f ℱ μ) : Submartingale (-f) ℱ μ := by refine ⟨hf.1.neg, fun i j hij => ?_, fun i => (hf.2.2 i).neg⟩ - refine EventuallyLE.trans ?_ (condExp_neg (f j)).symm.le + refine EventuallyLE.trans ?_ (condExp_neg ..).symm.le filter_upwards [hf.2.1 i j hij] with _ _ simpa @@ -209,7 +210,7 @@ theorem ae_le_condExp [LE E] (hf : Submartingale f ℱ μ) {i j : ι} (hij : i theorem add [Preorder E] [AddLeftMono E] (hf : Submartingale f ℱ μ) (hg : Submartingale g ℱ μ) : Submartingale (f + g) ℱ μ := by refine ⟨hf.1.add hg.1, fun i j hij => ?_, fun i => (hf.2.2 i).add (hg.2.2 i)⟩ - refine EventuallyLE.trans ?_ (condExp_add (hf.integrable j) (hg.integrable j)).symm.le + refine EventuallyLE.trans ?_ (condExp_add (hf.integrable j) (hg.integrable j) _).symm.le filter_upwards [hf.2.1 i j hij, hg.2.1 i j hij] intros refine add_le_add ?_ ?_ <;> assumption @@ -220,7 +221,7 @@ theorem add_martingale [Preorder E] [AddLeftMono E] (hf : Submartingale f ℱ μ theorem neg [Preorder E] [AddLeftMono E] (hf : Submartingale f ℱ μ) : Supermartingale (-f) ℱ μ := by - refine ⟨hf.1.neg, fun i j hij => (condExp_neg (f j)).le.trans ?_, fun i => (hf.2.2 i).neg⟩ + refine ⟨hf.1.neg, fun i j hij => (condExp_neg ..).le.trans ?_, fun i => (hf.2.2 i).neg⟩ filter_upwards [hf.2.1 i j hij] with _ _ simpa @@ -286,7 +287,7 @@ theorem submartingale_of_condExp_sub_nonneg [IsFiniteMeasure μ] {f : ι → Ω Submartingale f ℱ μ := by refine ⟨hadp, fun i j hij => ?_, hint⟩ rw [← condExp_of_stronglyMeasurable (ℱ.le _) (hadp _) (hint _), ← eventually_sub_nonneg] - exact EventuallyLE.trans (hf i j hij) (condExp_sub (hint _) (hint _)).le + exact EventuallyLE.trans (hf i j hij) (condExp_sub (hint _) (hint _) _).le @[deprecated (since := "2025-01-21")] alias submartingale_of_condexp_sub_nonneg := submartingale_of_condExp_sub_nonneg @@ -295,7 +296,7 @@ theorem Submartingale.condExp_sub_nonneg {f : ι → Ω → ℝ} (hf : Submartin (hij : i ≤ j) : 0 ≤ᵐ[μ] μ[f j - f i|ℱ i] := by by_cases h : SigmaFinite (μ.trim (ℱ.le i)) swap; · rw [condExp_of_not_sigmaFinite (ℱ.le i) h] - refine EventuallyLE.trans ?_ (condExp_sub (hf.integrable _) (hf.integrable _)).symm.le + refine EventuallyLE.trans ?_ (condExp_sub (hf.integrable _) (hf.integrable _) _).symm.le rw [eventually_sub_nonneg, condExp_of_stronglyMeasurable (ℱ.le _) (hf.adapted _) (hf.integrable _)] exact hf.2.1 i j hij @@ -332,10 +333,8 @@ variable {F : Type*} [NormedLatticeAddCommGroup F] [NormedSpace ℝ F] [Complete theorem smul_nonneg {f : ι → Ω → F} {c : ℝ} (hc : 0 ≤ c) (hf : Supermartingale f ℱ μ) : Supermartingale (c • f) ℱ μ := by refine ⟨hf.1.smul c, fun i j hij => ?_, fun i => (hf.2.2 i).smul c⟩ - refine (condExp_smul c (f j)).le.trans ?_ - filter_upwards [hf.2.1 i j hij] with _ hle - simp_rw [Pi.smul_apply] - exact smul_le_smul_of_nonneg_left hle hc + filter_upwards [condExp_smul c (f j) (ℱ i), hf.2.1 i j hij] with ω hω hle + simpa only [hω, Pi.smul_apply] using smul_le_smul_of_nonneg_left hle hc theorem smul_nonpos {f : ι → Ω → F} {c : ℝ} (hc : c ≤ 0) (hf : Supermartingale f ℱ μ) : Submartingale (c • f) ℱ μ := by @@ -418,7 +417,7 @@ theorem supermartingale_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp Supermartingale f 𝒢 μ := by rw [← neg_neg f] refine (submartingale_nat hadp.neg (fun i => (hint i).neg) fun i => - EventuallyLE.trans ?_ (condExp_neg _).symm.le).neg + EventuallyLE.trans ?_ (condExp_neg ..).symm.le).neg filter_upwards [hf i] with x hx using neg_le_neg hx theorem martingale_nat [IsFiniteMeasure μ] {f : ℕ → Ω → ℝ} (hadp : Adapted 𝒢 f) @@ -431,7 +430,7 @@ theorem submartingale_of_condExp_sub_nonneg_nat [IsFiniteMeasure μ] {f : ℕ (hf : ∀ i, 0 ≤ᵐ[μ] μ[f (i + 1) - f i|𝒢 i]) : Submartingale f 𝒢 μ := by refine submartingale_nat hadp hint fun i => ?_ rw [← condExp_of_stronglyMeasurable (𝒢.le _) (hadp _) (hint _), ← eventually_sub_nonneg] - exact EventuallyLE.trans (hf i) (condExp_sub (hint _) (hint _)).le + exact EventuallyLE.trans (hf i) (condExp_sub (hint _) (hint _) _).le @[deprecated (since := "2025-01-21")] alias submartingale_of_condexp_sub_nonneg_nat := submartingale_of_condExp_sub_nonneg_nat @@ -452,7 +451,7 @@ theorem martingale_of_condExp_sub_eq_zero_nat [IsFiniteMeasure μ] {f : ℕ → refine martingale_iff.2 ⟨supermartingale_of_condExp_sub_nonneg_nat hadp hint fun i => ?_, submartingale_of_condExp_sub_nonneg_nat hadp hint fun i => (hf i).symm.le⟩ rw [← neg_sub] - refine (EventuallyEq.trans ?_ (condExp_neg _).symm).le + refine (EventuallyEq.trans ?_ (condExp_neg ..).symm).le filter_upwards [hf i] with x hx simpa only [Pi.zero_apply, Pi.neg_apply, zero_eq_neg] diff --git a/Mathlib/Probability/Martingale/Centering.lean b/Mathlib/Probability/Martingale/Centering.lean index 0802f506c451a..002c97c9f5f23 100644 --- a/Mathlib/Probability/Martingale/Centering.lean +++ b/Mathlib/Probability/Martingale/Centering.lean @@ -85,12 +85,12 @@ theorem martingale_martingalePart (hf : Adapted ℱ f) (hf_int : ∀ n, Integrab have h_eq_sum : μ[martingalePart f ℱ μ j|ℱ i] =ᵐ[μ] f 0 + ∑ k ∈ Finset.range j, (μ[f (k + 1) - f k|ℱ i] - μ[μ[f (k + 1) - f k|ℱ k]|ℱ i]) := by rw [martingalePart_eq_sum] - refine (condExp_add (hf_int 0) (by fun_prop)).trans ?_ - refine (EventuallyEq.rfl.add (condExp_finset_sum fun i _ => by fun_prop)).trans ?_ + refine (condExp_add (hf_int 0) (by fun_prop) _).trans ?_ + refine (EventuallyEq.rfl.add (condExp_finset_sum (fun i _ => by fun_prop) _)).trans ?_ refine EventuallyEq.add ?_ ?_ · rw [condExp_of_stronglyMeasurable (ℱ.le _) _ (hf_int 0)] · exact (hf 0).mono (ℱ.mono (zero_le i)) - · exact eventuallyEq_sum fun k _ => condExp_sub (by fun_prop) integrable_condExp + · exact eventuallyEq_sum fun k _ => condExp_sub (by fun_prop) integrable_condExp _ refine h_eq_sum.trans ?_ have h_ge : ∀ k, i ≤ k → μ[f (k + 1) - f k|ℱ i] - μ[μ[f (k + 1) - f k|ℱ k]|ℱ i] =ᵐ[μ] 0 := by intro k hk diff --git a/Mathlib/Probability/Martingale/Convergence.lean b/Mathlib/Probability/Martingale/Convergence.lean index bc762e65c4237..57105ca759aaf 100644 --- a/Mathlib/Probability/Martingale/Convergence.lean +++ b/Mathlib/Probability/Martingale/Convergence.lean @@ -335,7 +335,7 @@ theorem Martingale.eq_condExp_of_tendsto_eLpNorm {μ : Measure Ω} (hf : Marting tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds hgtends (fun m => zero_le _) fun m => eLpNorm_one_condExp_le_eLpNorm _ have hev : ∀ m ≥ n, eLpNorm (μ[f m - g|ℱ n]) 1 μ = eLpNorm (f n - μ[g|ℱ n]) 1 μ := by - refine fun m hm => eLpNorm_congr_ae ((condExp_sub (hf.integrable m) hg).trans ?_) + refine fun m hm => eLpNorm_congr_ae ((condExp_sub (hf.integrable m) hg _).trans ?_) filter_upwards [hf.2 n m hm] with x hx simp only [hx, Pi.sub_apply] exact tendsto_nhds_unique (tendsto_atTop_of_eventually_const hev) ht From da8db712c239200c18ea86bc6c1726a9cfbde04e Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Thu, 23 Jan 2025 12:20:02 +0000 Subject: [PATCH 451/681] chore: fix some declarations using `coprime` (#20982) Overwhelmingly `isCoprime` is used in names when it is also used in the theorem statement. Here we fix the last instances where `coprime` was used instead. Follow up to #20976. Co-authored-by: Moritz Firsching --- Mathlib/FieldTheory/SeparableDegree.lean | 2 +- .../DiophantineApproximation/Basic.lean | 2 +- Mathlib/NumberTheory/FLT/Four.lean | 14 +++++++++----- Mathlib/NumberTheory/Zsqrtd/Basic.lean | 4 +++- Mathlib/RingTheory/EuclideanDomain.lean | 2 +- Mathlib/RingTheory/Int/Basic.lean | 8 ++++++-- Mathlib/RingTheory/Polynomial/Basic.lean | 10 ++++++++-- Mathlib/RingTheory/PrincipalIdealDomain.lean | 16 ++++++++++++---- Mathlib/RingTheory/RootsOfUnity/Minpoly.lean | 2 +- 9 files changed, 42 insertions(+), 18 deletions(-) diff --git a/Mathlib/FieldTheory/SeparableDegree.lean b/Mathlib/FieldTheory/SeparableDegree.lean index 8cc00db3d0c2b..172cb679bd8eb 100644 --- a/Mathlib/FieldTheory/SeparableDegree.lean +++ b/Mathlib/FieldTheory/SeparableDegree.lean @@ -598,7 +598,7 @@ theorem eq_X_pow_char_pow_sub_C_pow_of_natSepDegree_eq_one (q : ℕ) [ExpChar F refine ⟨_, n, y, hne, H, ?_⟩ obtain ⟨c, hf, H⟩ := hF.exists_eq_pow_mul_and_not_dvd rw [hf, natSepDegree_mul_of_isCoprime _ c <| IsCoprime.pow_left <| - (hI.coprime_or_dvd c).resolve_right H, natSepDegree_pow_of_ne_zero _ hne, hD, + (hI.isCoprime_or_dvd c).resolve_right H, natSepDegree_pow_of_ne_zero _ hne, hD, add_right_eq_self, natSepDegree_eq_zero_iff] at h simpa only [eq_one_of_monic_natDegree_zero ((hM.pow _).of_mul_monic_left (hf ▸ hm)) h, mul_one, ← hp] using hf diff --git a/Mathlib/NumberTheory/DiophantineApproximation/Basic.lean b/Mathlib/NumberTheory/DiophantineApproximation/Basic.lean index 2a02d29488dbd..66f093b9e5047 100644 --- a/Mathlib/NumberTheory/DiophantineApproximation/Basic.lean +++ b/Mathlib/NumberTheory/DiophantineApproximation/Basic.lean @@ -550,7 +550,7 @@ This version uses `Real.convergent`. -/ theorem exists_rat_eq_convergent {q : ℚ} (h : |ξ - q| < 1 / (2 * (q.den : ℝ) ^ 2)) : ∃ n, q = ξ.convergent n := by refine q.num_div_den ▸ exists_rat_eq_convergent' ⟨?_, fun hd => ?_, ?_⟩ - · exact coprime_iff_nat_coprime.mpr (natAbs_ofNat q.den ▸ q.reduced) + · exact isCoprime_iff_nat_coprime.mpr (natAbs_ofNat q.den ▸ q.reduced) · rw [← q.den_eq_one_iff.mp (Nat.cast_eq_one.mp hd)] at h simpa only [Rat.den_intCast, Nat.cast_one, one_pow, mul_one] using (abs_lt.mp h).1 · obtain ⟨hq₀, hq₁⟩ := aux₀ (Nat.cast_pos.mpr q.pos) diff --git a/Mathlib/NumberTheory/FLT/Four.lean b/Mathlib/NumberTheory/FLT/Four.lean index 5803ad9288031..38f0eb8dff081 100644 --- a/Mathlib/NumberTheory/FLT/Four.lean +++ b/Mathlib/NumberTheory/FLT/Four.lean @@ -139,14 +139,18 @@ theorem exists_pos_odd_minimal {a b c : ℤ} (h : Fermat42 a b c) : end Fermat42 -theorem Int.coprime_of_sq_sum {r s : ℤ} (h2 : IsCoprime s r) : IsCoprime (r ^ 2 + s ^ 2) r := by +theorem Int.isCoprime_of_sq_sum {r s : ℤ} (h2 : IsCoprime s r) : IsCoprime (r ^ 2 + s ^ 2) r := by rw [sq, sq] exact (IsCoprime.mul_left h2 h2).mul_add_left_left r -theorem Int.coprime_of_sq_sum' {r s : ℤ} (h : IsCoprime r s) : +@[deprecated (since := "2025-01-23")] alias Int.coprime_of_sq_sum := Int.isCoprime_of_sq_sum + +theorem Int.isCoprime_of_sq_sum' {r s : ℤ} (h : IsCoprime r s) : IsCoprime (r ^ 2 + s ^ 2) (r * s) := by - apply IsCoprime.mul_right (Int.coprime_of_sq_sum (isCoprime_comm.mp h)) - rw [add_comm]; apply Int.coprime_of_sq_sum h + apply IsCoprime.mul_right (Int.isCoprime_of_sq_sum (isCoprime_comm.mp h)) + rw [add_comm]; apply Int.isCoprime_of_sq_sum h + +@[deprecated (since := "2025-01-23")] alias Int.coprime_of_sq_sum' := Int.isCoprime_of_sq_sum' namespace Fermat42 @@ -194,7 +198,7 @@ theorem not_minimal {a b c : ℤ} (h : Minimal a b c) (ha2 : a % 2 = 1) (hc : 0 have hcp : Int.gcd m (r * s) = 1 := by rw [htt3] exact - Int.gcd_eq_one_iff_coprime.mpr (Int.coprime_of_sq_sum' (Int.gcd_eq_one_iff_coprime.mp htt4)) + Int.gcd_eq_one_iff_coprime.mpr (Int.isCoprime_of_sq_sum' (Int.gcd_eq_one_iff_coprime.mp htt4)) -- b is even because b ^ 2 = 2 * m * n. have hb2 : 2 ∣ b := by apply @Int.Prime.dvd_pow' _ 2 _ Nat.prime_two diff --git a/Mathlib/NumberTheory/Zsqrtd/Basic.lean b/Mathlib/NumberTheory/Zsqrtd/Basic.lean index 1babdaa7537b8..713d9484766ef 100644 --- a/Mathlib/NumberTheory/Zsqrtd/Basic.lean +++ b/Mathlib/NumberTheory/Zsqrtd/Basic.lean @@ -326,7 +326,7 @@ theorem gcd_eq_zero_iff (a : ℤ√d) : Int.gcd a.re a.im = 0 ↔ a = 0 := by theorem gcd_pos_iff (a : ℤ√d) : 0 < Int.gcd a.re a.im ↔ a ≠ 0 := pos_iff_ne_zero.trans <| not_congr a.gcd_eq_zero_iff -theorem coprime_of_dvd_coprime {a b : ℤ√d} (hcoprime : IsCoprime a.re a.im) (hdvd : b ∣ a) : +theorem isCoprime_of_dvd_isCoprime {a b : ℤ√d} (hcoprime : IsCoprime a.re a.im) (hdvd : b ∣ a) : IsCoprime b.re b.im := by apply isCoprime_of_dvd · rintro ⟨hre, him⟩ @@ -342,6 +342,8 @@ theorem coprime_of_dvd_coprime {a b : ℤ√d} (hcoprime : IsCoprime a.re a.im) exact ⟨hzdvdu, hzdvdv⟩ exact hcoprime.isUnit_of_dvd' ha hb +@[deprecated (since := "2025-01-23")] alias coprime_of_dvd_coprime := isCoprime_of_dvd_isCoprime + theorem exists_coprime_of_gcd_pos {a : ℤ√d} (hgcd : 0 < Int.gcd a.re a.im) : ∃ b : ℤ√d, a = ((Int.gcd a.re a.im : ℤ) : ℤ√d) * b ∧ IsCoprime b.re b.im := by obtain ⟨re, im, H1, Hre, Him⟩ := Int.exists_gcd_one hgcd diff --git a/Mathlib/RingTheory/EuclideanDomain.lean b/Mathlib/RingTheory/EuclideanDomain.lean index a0cf45fae7e77..2c36ca8f2fc47 100644 --- a/Mathlib/RingTheory/EuclideanDomain.lean +++ b/Mathlib/RingTheory/EuclideanDomain.lean @@ -96,7 +96,7 @@ theorem dvd_or_coprime (x y : α) (h : Irreducible x) : x ∣ y ∨ IsCoprime x y := letI := Classical.decEq α letI := EuclideanDomain.gcdMonoid α - _root_.dvd_or_coprime x y h + _root_.dvd_or_isCoprime x y h end EuclideanDomain diff --git a/Mathlib/RingTheory/Int/Basic.lean b/Mathlib/RingTheory/Int/Basic.lean index be4be78dc6d35..bcd2fb030e89d 100644 --- a/Mathlib/RingTheory/Int/Basic.lean +++ b/Mathlib/RingTheory/Int/Basic.lean @@ -45,9 +45,11 @@ theorem gcd_eq_one_iff_coprime {a b : ℤ} : Int.gcd a b = 1 ↔ IsCoprime a b : rw [← natCast_dvd_natCast, Int.ofNat_one, ← h] exact dvd_add ((natCast_dvd.mpr ha).mul_left _) ((natCast_dvd.mpr hb).mul_left _) -theorem coprime_iff_nat_coprime {a b : ℤ} : IsCoprime a b ↔ Nat.Coprime a.natAbs b.natAbs := by +theorem isCoprime_iff_nat_coprime {a b : ℤ} : IsCoprime a b ↔ Nat.Coprime a.natAbs b.natAbs := by rw [← gcd_eq_one_iff_coprime, Nat.coprime_iff_gcd_eq_one, gcd_eq_natAbs] +@[deprecated (since := "2025-01-23")] alias coprime_iff_nat_coprime := isCoprime_iff_nat_coprime + /-- If `gcd a (m * n) ≠ 1`, then `gcd a m ≠ 1` or `gcd a n ≠ 1`. -/ theorem gcd_ne_one_iff_gcd_mul_right_ne_one {a : ℤ} {m n : ℕ} : a.gcd (m * n) ≠ 1 ↔ a.gcd m ≠ 1 ∨ a.gcd n ≠ 1 := by @@ -65,10 +67,12 @@ theorem sq_of_gcd_eq_one {a b c : ℤ} (h : Int.gcd a b = 1) (heq : a * b = c ^ · rw [hu'] simp -theorem sq_of_coprime {a b c : ℤ} (h : IsCoprime a b) (heq : a * b = c ^ 2) : +theorem sq_of_isCoprime {a b c : ℤ} (h : IsCoprime a b) (heq : a * b = c ^ 2) : ∃ a0 : ℤ, a = a0 ^ 2 ∨ a = -a0 ^ 2 := sq_of_gcd_eq_one (gcd_eq_one_iff_coprime.mpr h) heq +@[deprecated (since := "2025-01-23")] alias sq_of_coprime := sq_of_isCoprime + theorem natAbs_euclideanDomain_gcd (a b : ℤ) : Int.natAbs (EuclideanDomain.gcd a b) = Int.gcd a b := by apply Nat.dvd_antisymm <;> rw [← Int.natCast_dvd_natCast] diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index d94f141c480d3..682fe26b642a9 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -945,7 +945,7 @@ theorem linearIndependent_powers_iff_aeval (f : M →ₗ[R] M) (v : M) : support, coeff, ofFinsupp_eq_zero] exact Iff.rfl -theorem disjoint_ker_aeval_of_coprime (f : M →ₗ[R] M) {p q : R[X]} (hpq : IsCoprime p q) : +theorem disjoint_ker_aeval_of_isCoprime (f : M →ₗ[R] M) {p q : R[X]} (hpq : IsCoprime p q) : Disjoint (LinearMap.ker (aeval f p)) (LinearMap.ker (aeval f q)) := by rw [disjoint_iff_inf_le] intro v hv @@ -954,7 +954,10 @@ theorem disjoint_ker_aeval_of_coprime (f : M →ₗ[R] M) {p q : R[X]} (hpq : Is LinearMap.mem_ker.1 (Submodule.mem_inf.1 hv).2] using congr_arg (fun p : R[X] => aeval f p v) hpq'.symm -theorem sup_aeval_range_eq_top_of_coprime (f : M →ₗ[R] M) {p q : R[X]} (hpq : IsCoprime p q) : +@[deprecated (since := "2025-01-23")] +alias disjoint_ker_aeval_of_coprime := disjoint_ker_aeval_of_isCoprime + +theorem sup_aeval_range_eq_top_of_isCoprime (f : M →ₗ[R] M) {p q : R[X]} (hpq : IsCoprime p q) : LinearMap.range (aeval f p) ⊔ LinearMap.range (aeval f q) = ⊤ := by rw [eq_top_iff] intro v _ @@ -967,6 +970,9 @@ theorem sup_aeval_range_eq_top_of_coprime (f : M →ₗ[R] M) {p q : R[X]} (hpq simpa only [mul_comm p p', mul_comm q q', aeval_one, aeval_add] using congr_arg (fun p : R[X] => aeval f p v) hpq' +@[deprecated (since := "2025-01-23")] +alias sup_aeval_range_eq_top_of_coprime := sup_aeval_range_eq_top_of_isCoprime + theorem sup_ker_aeval_le_ker_aeval_mul {f : M →ₗ[R] M} {p q : R[X]} : LinearMap.ker (aeval f p) ⊔ LinearMap.ker (aeval f q) ≤ LinearMap.ker (aeval f (p * q)) := by intro v hv diff --git a/Mathlib/RingTheory/PrincipalIdealDomain.lean b/Mathlib/RingTheory/PrincipalIdealDomain.lean index 58ef2b97976b3..f9de36718ac59 100644 --- a/Mathlib/RingTheory/PrincipalIdealDomain.lean +++ b/Mathlib/RingTheory/PrincipalIdealDomain.lean @@ -392,23 +392,31 @@ theorem isCoprime_of_dvd (x y : R) (nonzero : ¬(x = 0 ∧ y = 0)) (H : ∀ z ∈ nonunits R, z ≠ 0 → z ∣ x → ¬z ∣ y) : IsCoprime x y := (isRelPrime_of_no_nonunits_factors nonzero H).isCoprime -theorem dvd_or_coprime (x y : R) (h : Irreducible x) : x ∣ y ∨ IsCoprime x y := +theorem dvd_or_isCoprime (x y : R) (h : Irreducible x) : x ∣ y ∨ IsCoprime x y := h.dvd_or_isRelPrime.imp_right IsRelPrime.isCoprime +@[deprecated (since := "2025-01-23")] alias dvd_or_coprime := dvd_or_isCoprime + /-- See also `Irreducible.isRelPrime_iff_not_dvd`. -/ theorem Irreducible.coprime_iff_not_dvd {p n : R} (hp : Irreducible p) : IsCoprime p n ↔ ¬p ∣ n := by rw [← isRelPrime_iff_isCoprime, hp.isRelPrime_iff_not_dvd] /-- See also `Irreducible.coprime_iff_not_dvd'`. -/ -theorem Irreducible.dvd_iff_not_coprime {p n : R} (hp : Irreducible p) : p ∣ n ↔ ¬IsCoprime p n := +theorem Irreducible.dvd_iff_not_isCoprime {p n : R} (hp : Irreducible p) : p ∣ n ↔ ¬IsCoprime p n := iff_not_comm.2 hp.coprime_iff_not_dvd +@[deprecated (since := "2025-01-23")] +alias Irreducible.dvd_iff_not_coprime := Irreducible.dvd_iff_not_isCoprime + theorem Irreducible.coprime_pow_of_not_dvd {p a : R} (m : ℕ) (hp : Irreducible p) (h : ¬p ∣ a) : IsCoprime a (p ^ m) := (hp.coprime_iff_not_dvd.2 h).symm.pow_right -theorem Irreducible.coprime_or_dvd {p : R} (hp : Irreducible p) (i : R) : IsCoprime p i ∨ p ∣ i := - (_root_.em _).imp_right hp.dvd_iff_not_coprime.2 +theorem Irreducible.isCoprime_or_dvd {p : R} (hp : Irreducible p) (i : R) : IsCoprime p i ∨ p ∣ i := + (_root_.em _).imp_right hp.dvd_iff_not_isCoprime.2 + +@[deprecated (since := "2025-01-23")] +alias Irreducible.coprime_or_dvd := Irreducible.isCoprime_or_dvd variable [IsDomain R] diff --git a/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean b/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean index 2da9825d08c25..856a442cc406a 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean @@ -127,7 +127,7 @@ theorem minpoly_eq_pow {p : ℕ} [hprime : Fact p.Prime] (hdiv : ¬p ∣ n) : Polynomial.map_mul] refine IsCoprime.mul_dvd ?_ ?_ ?_ · have aux := IsPrimitive.Int.irreducible_iff_irreducible_map_cast Pmonic.isPrimitive - refine (dvd_or_coprime _ _ (aux.1 Pirr)).resolve_left ?_ + refine (dvd_or_isCoprime _ _ (aux.1 Pirr)).resolve_left ?_ rw [map_dvd_map (Int.castRingHom ℚ) Int.cast_injective Pmonic] intro hdiv refine hdiff (eq_of_monic_of_associated Pmonic Qmonic ?_) From b632e4bf07f6be125b1fc831b70c479d15860c71 Mon Sep 17 00:00:00 2001 From: blizzard_inc Date: Thu, 23 Jan 2025 13:08:27 +0000 Subject: [PATCH 452/681] chore(Algebra/FreeMonoid/Count): remove defeq abuse around `FreeMonoid.countP` (#20156) as requested on [zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Mathlib.2FAlgebra.2FFreeMonoid.2FCount.2Elean) Co-authored-by: blizzard_inc --- Mathlib/Algebra/FreeMonoid/Basic.lean | 2 +- Mathlib/Algebra/FreeMonoid/Count.lean | 101 +++++++++++++------------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/Mathlib/Algebra/FreeMonoid/Basic.lean b/Mathlib/Algebra/FreeMonoid/Basic.lean index 2c1e153eed82f..bb1c54dceedc7 100644 --- a/Mathlib/Algebra/FreeMonoid/Basic.lean +++ b/Mathlib/Algebra/FreeMonoid/Basic.lean @@ -121,7 +121,7 @@ variable {a : FreeMonoid α} /-- The length of a free monoid element: 1.length = 0 and (a * b).length = a.length + b.length -/ @[to_additive "The length of an additive free monoid element: 1.length = 0 and (a + b).length = a.length + b.length"] -def length (a : FreeMonoid α) : ℕ := List.length a +def length (a : FreeMonoid α) : ℕ := a.toList.length @[to_additive (attr := simp)] theorem length_one : length (1 : FreeMonoid α) = 0 := rfl diff --git a/Mathlib/Algebra/FreeMonoid/Count.lean b/Mathlib/Algebra/FreeMonoid/Count.lean index d9add268027ba..82e0442e18495 100644 --- a/Mathlib/Algebra/FreeMonoid/Count.lean +++ b/Mathlib/Algebra/FreeMonoid/Count.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.FreeMonoid.Basic -import Mathlib.Algebra.Group.TypeTags.Hom +import Mathlib.Algebra.Group.TypeTags.Basic /-! # `List.count` as a bundled homomorphism @@ -13,73 +13,76 @@ In this file we define `FreeMonoid.countP`, `FreeMonoid.count`, `FreeAddMonoid.c `FreeAddMonoid.count`. These are `List.countP` and `List.count` bundled as multiplicative and additive homomorphisms from `FreeMonoid` and `FreeAddMonoid`. -We do not use `to_additive` because it can't map `Multiplicative ℕ` to `ℕ`. +We do not use `to_additive` too much because it can't map `Multiplicative ℕ` to `ℕ`. +-/ -## TODO +variable {α : Type*} (p : α → Prop) [DecidablePred p] -There is lots of defeq abuse here of `FreeAddMonoid α = List α`, e.g. in statements like -``` -theorem countP_apply (l : FreeAddMonoid α) : countP p l = List.countP p l := rfl -``` -This needs cleaning up. +namespace FreeMonoid +/-- `List.countP` lifted to free monoids-/ +@[to_additive "`List.countP` lifted to free additive monoids"] +def countP' (l : FreeMonoid α) : ℕ := l.toList.countP p --/ +@[to_additive] +lemma countP'_one : (1 : FreeMonoid α).countP' p = 0 := rfl -variable {α : Type*} (p : α → Prop) [DecidablePred p] +@[to_additive] +lemma countP'_mul (l₁ l₂ : FreeMonoid α) : (l₁ * l₂).countP' p = l₁.countP' p + l₂.countP' p := by + dsimp [countP'] + simp only [List.countP_append] -namespace FreeAddMonoid +/-- `List.countP` as a bundled multiplicative monoid homomorphism. -/ +def countP : FreeMonoid α →* Multiplicative ℕ where + toFun := .ofAdd ∘ FreeMonoid.countP' p + map_one' := by + simp [countP'_one p] + map_mul' x y := by + simp [countP'_mul p] -/-- `List.countP` as a bundled additive monoid homomorphism. -/ -def countP : FreeAddMonoid α →+ ℕ where - toFun := List.countP p - map_zero' := List.countP_nil _ - map_add' := List.countP_append _ +theorem countP_apply (l : FreeMonoid α) : l.countP p = .ofAdd (l.toList.countP p) := rfl -theorem countP_of (x : α) : countP p (of x) = if p x = true then 1 else 0 := by - change List.countP p [x] = _ - simp [List.countP_cons] +lemma countP_of (x : α) : (of x).countP p = + if p x then Multiplicative.ofAdd 1 else Multiplicative.ofAdd 0 := by + rw [countP_apply, toList_of, List.countP_singleton, apply_ite (Multiplicative.ofAdd)] + simp only [decide_eq_true_eq] -theorem countP_apply (l : FreeAddMonoid α) : countP p l = List.countP p l := rfl /-- `List.count` as a bundled additive monoid homomorphism. -/ --- Porting note: was (x = ·) -def count [DecidableEq α] (x : α) : FreeAddMonoid α →+ ℕ := countP (· = x) - -theorem count_of [DecidableEq α] (x y : α) : count x (of y) = (Pi.single x 1 : α → ℕ) y := by - change List.count x [y] = _ - simp [Pi.single, Function.update, List.count_cons] +def count [DecidableEq α] (x : α) : FreeMonoid α →* Multiplicative ℕ := countP (· = x) -theorem count_apply [DecidableEq α] (x : α) (l : FreeAddMonoid α) : count x l = List.count x l := - rfl +theorem count_apply [DecidableEq α] (x : α) (l : FreeAddMonoid α) : + count x l = Multiplicative.ofAdd (l.toList.count x) := rfl -end FreeAddMonoid +theorem count_of [DecidableEq α] (x y : α) : + count x (of y) = Pi.mulSingle (f := fun _ => Multiplicative ℕ) x (Multiplicative.ofAdd 1) y := + by simp only [count, eq_comm, countP_of, ofAdd_zero, Pi.mulSingle_apply] -namespace FreeMonoid +end FreeMonoid -/-- `List.countP` as a bundled multiplicative monoid homomorphism. -/ -def countP : FreeMonoid α →* Multiplicative ℕ := - AddMonoidHom.toMultiplicative (FreeAddMonoid.countP p) +namespace FreeAddMonoid -theorem countP_of' (x : α) : - countP p (of x) = if p x then Multiplicative.ofAdd 1 else Multiplicative.ofAdd 0 := by - erw [FreeAddMonoid.countP_of] - simp only [eq_iff_iff, iff_true, ofAdd_zero]; rfl +/-- `List.countP` as a bundled additive monoid homomorphism. -/ +def countP : FreeAddMonoid α →+ ℕ where + toFun := FreeAddMonoid.countP' p + map_zero' := countP'_zero p + map_add' := countP'_add p -theorem countP_of (x : α) : countP p (of x) = if p x then Multiplicative.ofAdd 1 else 1 := by - rw [countP_of', ofAdd_zero] +theorem countP_apply (l : FreeAddMonoid α) : l.countP p = l.toList.countP p := rfl --- `rfl` is not transitive -theorem countP_apply (l : FreeAddMonoid α) : countP p l = Multiplicative.ofAdd (List.countP p l) := - rfl +theorem countP_of (x : α) : countP p (of x) = if p x then 1 else 0 := by + rw [countP_apply, toList_of, List.countP_singleton] + simp only [decide_eq_true_eq] /-- `List.count` as a bundled additive monoid homomorphism. -/ -def count [DecidableEq α] (x : α) : FreeMonoid α →* Multiplicative ℕ := countP (· = x) +-- Porting note: was (x = ·) +def count [DecidableEq α] (x : α) : FreeAddMonoid α →+ ℕ := countP (· = x) -theorem count_apply [DecidableEq α] (x : α) (l : FreeAddMonoid α) : - count x l = Multiplicative.ofAdd (List.count x l) := rfl +lemma count_of [DecidableEq α] (x y : α) : count x (of y) = (Pi.single x 1 : α → ℕ) y := by + dsimp [count] + rw [countP_of] + simp [Pi.single, Function.update] -theorem count_of [DecidableEq α] (x y : α) : - count x (of y) = @Pi.mulSingle α (fun _ => Multiplicative ℕ) _ _ x (Multiplicative.ofAdd 1) y := - by simp [count, countP_of, Pi.mulSingle_apply, eq_comm, Bool.beq_eq_decide_eq] +theorem count_apply [DecidableEq α] (x : α) (l : FreeAddMonoid α) : l.count x = l.toList.count x := + rfl -end FreeMonoid +end FreeAddMonoid From 646240905b41e3b05ad95a37d1b85c1bd9a9c18f Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Thu, 23 Jan 2025 15:00:24 +0000 Subject: [PATCH 453/681] feat(Analysis/SpecialFunctions): generalise away from nat (#20986) Generalise the first four lemmas in this file to have an arbitrary indexing type rather than nat. Despite the diff looking strange, the only user-facing change here is that the lemmas are strictly more general. --- .../SpecialFunctions/Log/Summable.lean | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean b/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean index a814fdc2d846e..3c1969101ea96 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean @@ -24,32 +24,30 @@ open Filter Function Complex Real open scoped Interval Topology BigOperators Nat Classical Complex -lemma Complex.summable_log_one_add_of_summable {f : ℕ → ℂ} (hf : Summable f) : - Summable (fun n : ℕ => Complex.log (1 + f n)) := by - have hff := Summable.const_smul ((3 : ℝ) / 2) (summable_norm_iff.mpr hf) - have := Metric.tendsto_atTop.mp (Summable.tendsto_atTop_zero ((summable_norm_iff.mpr hf))) - apply Summable.of_norm_bounded_eventually_nat (fun n => 3/2 * Complex.abs (f n)) hff - simp only [smul_eq_mul, gt_iff_lt, ge_iff_le, dist_zero_right, Real.norm_eq_abs, Complex.abs_abs, - Complex.norm_eq_abs, eventually_atTop] at * - obtain ⟨n, hn⟩ := this (1/2) (one_half_pos) - exact Exists.intro n fun m hm ↦ norm_log_one_add_half_le_self (LT.lt.le (hn m hm)) +variable {ι : Type*} -lemma Real.summable_log_one_add_of_summable {f : ℕ → ℝ} (hf : Summable f) : - Summable (fun n : ℕ => log (1 + |f n|)) := by +lemma Complex.summable_log_one_add_of_summable {f : ι → ℂ} (hf : Summable f) : + Summable (fun i : ι => Complex.log (1 + f i)) := by + apply (hf.norm.const_smul (3 / 2 : ℝ)).of_norm_bounded_eventually + filter_upwards [hf.norm.tendsto_cofinite_zero.eventually_le_const one_half_pos] with i hi + exact norm_log_one_add_half_le_self hi + +lemma Real.summable_log_one_add_of_summable {f : ι → ℝ} (hf : Summable f) : + Summable (fun i : ι => log (1 + |f i|)) := by have : Summable (fun n ↦ Complex.ofRealCLM (log (1 + |f n|))) := by - convert Complex.summable_log_one_add_of_summable (Complex.ofRealCLM.summable hf.norm) with x + convert Complex.summable_log_one_add_of_summable (Complex.ofRealCLM.summable hf.norm) with x rw [ofRealCLM_apply, ofReal_log (by positivity)] simp only [ofReal_add, ofReal_one, norm_eq_abs, ofRealCLM_apply] convert Complex.reCLM.summable this -lemma Complex.multipliable_one_add_of_summable (f : ℕ → ℂ) (hf : Summable f) - (hff : ∀ n : ℕ, 1 + f n ≠ 0) : Multipliable (fun n : ℕ => 1 + f n) := by - refine Complex.multipliable_of_summable_log (fun n => 1 + f n) (by simpa) ?_ +lemma Complex.multipliable_one_add_of_summable (f : ι → ℂ) (hf : Summable f) + (hff : ∀ n : ι, 1 + f n ≠ 0) : Multipliable (fun n : ι => 1 + f n) := by + refine Complex.multipliable_of_summable_log (fun n => 1 + f n) (by simpa) ?_ simpa only [forall_const] using Complex.summable_log_one_add_of_summable hf -lemma Real.multipliable_one_add_of_summable (f : ℕ → ℝ) (hf : Summable f) : - Multipliable (fun n : ℕ => 1 + |f n|) := by - refine Real.multipliable_of_summable_log (fun n => 1 + |f n|) (fun _ ↦ by positivity) ?_ +lemma Real.multipliable_one_add_of_summable (f : ι → ℝ) (hf : Summable f) : + Multipliable (fun n : ι => 1 + |f n|) := by + refine Real.multipliable_of_summable_log (fun n => 1 + |f n|) (fun _ ↦ by positivity) ?_ simpa only [forall_const] using Real.summable_log_one_add_of_summable hf lemma Complex.tendstoUniformlyOn_tsum_nat_log_one_add {α : Type*} {f : ℕ → α → ℂ} (K : Set α) From e36d9d7c9d629279c2c0a9a797ecf4330b711cb0 Mon Sep 17 00:00:00 2001 From: Stefan Kebekus Date: Thu, 23 Jan 2025 15:33:18 +0000 Subject: [PATCH 454/681] feat: interval integrability of periodic functions (#20938) Add a theorem showing that a periodic function is interval integrable over every interval if it is interval integrable over one period. Add docstrings with section headings to improve readability. The theorem is used in [Project VD](https://github.com/kebekus/ProjectVD), which aims to formalize Value Distribution Theory for meromorphic functions on the complex plane. --- Mathlib/MeasureTheory/Integral/Periodic.lean | 97 ++++++++++++++++---- 1 file changed, 78 insertions(+), 19 deletions(-) diff --git a/Mathlib/MeasureTheory/Integral/Periodic.lean b/Mathlib/MeasureTheory/Integral/Periodic.lean index 90abdbcb2baaf..0061e3099ce37 100644 --- a/Mathlib/MeasureTheory/Integral/Periodic.lean +++ b/Mathlib/MeasureTheory/Integral/Periodic.lean @@ -27,6 +27,10 @@ open Set Function MeasureTheory MeasureTheory.Measure TopologicalSpace AddSubgro open scoped MeasureTheory NNReal ENNReal +/-! +## Measures and integrability on ℝ and on the circle +-/ + @[measurability] protected theorem AddCircle.measurable_mk' {a : ℝ} : Measurable (β := AddCircle a) ((↑) : ℝ → AddCircle a) := @@ -221,14 +225,61 @@ protected theorem intervalIntegral_preimage (t : ℝ) (f : UnitAddCircle → E) end UnitAddCircle -variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - +/-! +## Interval integrability of periodic functions +-/ namespace Function namespace Periodic +variable {E : Type*} [NormedAddCommGroup E] + variable {f : ℝ → E} {T : ℝ} +/-- A periodic function is interval integrable over every interval if it is interval integrable +over one period. -/ +theorem intervalIntegrable {t : ℝ} (h₁f : Function.Periodic f T) (hT : 0 < T) + (h₂f : IntervalIntegrable f MeasureTheory.volume t (t + T)) (a₁ a₂ : ℝ) : + IntervalIntegrable f MeasureTheory.volume a₁ a₂ := by + -- Replace [a₁, a₂] by [t - n₁ * T, t + n₂ * T], where n₁ and n₂ are natural numbers + obtain ⟨n₁, hn₁⟩ := exists_nat_ge ((t - min a₁ a₂) / T) + obtain ⟨n₂, hn₂⟩ := exists_nat_ge ((max a₁ a₂ - t) / T) + have : Set.uIcc a₁ a₂ ⊆ Set.uIcc (t - n₁ * T) (t + n₂ * T) := by + rw [Set.uIcc_subset_uIcc_iff_le] + constructor + · calc min (t - n₁ * T) (t + n₂ * T) + _ ≤ (t - n₁ * T) := by apply min_le_left + _ ≤ min a₁ a₂ := by linarith [(div_le_iff₀ hT).1 hn₁] + · calc max a₁ a₂ + _ ≤ t + n₂ * T := by linarith [(div_le_iff₀ hT).1 hn₂] + _ ≤ max (t - n₁ * T) (t + n₂ * T) := by apply le_max_right + apply IntervalIntegrable.mono_set _ this + -- Suffices to show integrability over shifted periods + let a : ℕ → ℝ := fun n ↦ t + (n - n₁) * T + rw [(by ring : t - n₁ * T = a 0), (by simp [a] : t + n₂ * T = a (n₁ + n₂))] + apply IntervalIntegrable.trans_iterate + -- Show integrability over a shifted period + intro k hk + convert (IntervalIntegrable.comp_sub_right h₂f ((k - n₁) * T)) using 1 + · funext x + simpa using (h₁f.sub_int_mul_eq (k - n₁)).symm + · simp [a, Nat.cast_add] + ring + +/-- Special case of Function.Periodic.intervalIntegrable: A periodic function is interval integrable +over every interval if it is interval integrable over the period starting from zero. -/ +theorem intervalIntegrable₀ (h₁f : Function.Periodic f T) (hT : 0 < T) + (h₂f : IntervalIntegrable f MeasureTheory.volume 0 T) (a₁ a₂ : ℝ) : + IntervalIntegrable f MeasureTheory.volume a₁ a₂ := by + apply h₁f.intervalIntegrable hT (t := 0) + simpa + +/-! +## Interval integrals of periodic functions +-/ + +variable [NormedSpace ℝ E] + /-- An auxiliary lemma for a more general `Function.Periodic.intervalIntegral_add_eq`. -/ theorem intervalIntegral_add_eq_of_pos (hf : Periodic f T) (hT : 0 < T) (t s : ℝ) : ∫ x in t..t + T, f x = ∫ x in s..s + T, f x := by @@ -284,43 +335,48 @@ section RealValued open Filter variable {g : ℝ → ℝ} -variable (hg : Periodic g T) (h_int : ∀ t₁ t₂, IntervalIntegrable g MeasureSpace.volume t₁ t₂) -include hg h_int +variable (hg : Periodic g T) +include hg /-- If `g : ℝ → ℝ` is periodic with period `T > 0`, then for any `t : ℝ`, the function `t ↦ ∫ x in 0..t, g x` is bounded below by `t ↦ X + ⌊t/T⌋ • Y` for appropriate constants `X` and `Y`. -/ -theorem sInf_add_zsmul_le_integral_of_pos (hT : 0 < T) (t : ℝ) : +theorem sInf_add_zsmul_le_integral_of_pos (h_int : IntervalIntegrable g MeasureSpace.volume 0 T) + (hT : 0 < T) (t : ℝ) : (sInf ((fun t => ∫ x in (0)..t, g x) '' Icc 0 T) + ⌊t / T⌋ • ∫ x in (0)..T, g x) ≤ ∫ x in (0)..t, g x := by + let h'_int := hg.intervalIntegrable₀ hT h_int let ε := Int.fract (t / T) * T conv_rhs => - rw [← Int.fract_div_mul_self_add_zsmul_eq T t (by linarith), ← - integral_add_adjacent_intervals (h_int 0 ε) (h_int _ _)] - rw [hg.intervalIntegral_add_zsmul_eq ⌊t / T⌋ ε h_int, hg.intervalIntegral_add_eq ε 0, zero_add, - add_le_add_iff_right] - exact (continuous_primitive h_int 0).continuousOn.sInf_image_Icc_le <| + rw [← Int.fract_div_mul_self_add_zsmul_eq T t (by linarith), + ← integral_add_adjacent_intervals (h'_int 0 ε) (h'_int _ _)] + rw [hg.intervalIntegral_add_zsmul_eq ⌊t / T⌋ ε (hg.intervalIntegrable₀ hT h_int), + hg.intervalIntegral_add_eq ε 0, zero_add, add_le_add_iff_right] + exact (continuous_primitive h'_int 0).continuousOn.sInf_image_Icc_le <| mem_Icc_of_Ico (Int.fract_div_mul_self_mem_Ico T t hT) /-- If `g : ℝ → ℝ` is periodic with period `T > 0`, then for any `t : ℝ`, the function `t ↦ ∫ x in 0..t, g x` is bounded above by `t ↦ X + ⌊t/T⌋ • Y` for appropriate constants `X` and `Y`. -/ -theorem integral_le_sSup_add_zsmul_of_pos (hT : 0 < T) (t : ℝ) : +theorem integral_le_sSup_add_zsmul_of_pos (h_int : IntervalIntegrable g MeasureSpace.volume 0 T) + (hT : 0 < T) (t : ℝ) : (∫ x in (0)..t, g x) ≤ sSup ((fun t => ∫ x in (0)..t, g x) '' Icc 0 T) + ⌊t / T⌋ • ∫ x in (0)..T, g x := by + let h'_int := hg.intervalIntegrable₀ hT h_int let ε := Int.fract (t / T) * T conv_lhs => rw [← Int.fract_div_mul_self_add_zsmul_eq T t (by linarith), ← - integral_add_adjacent_intervals (h_int 0 ε) (h_int _ _)] - rw [hg.intervalIntegral_add_zsmul_eq ⌊t / T⌋ ε h_int, hg.intervalIntegral_add_eq ε 0, zero_add, + integral_add_adjacent_intervals (h'_int 0 ε) (h'_int _ _)] + rw [hg.intervalIntegral_add_zsmul_eq ⌊t / T⌋ ε h'_int, hg.intervalIntegral_add_eq ε 0, zero_add, add_le_add_iff_right] - exact (continuous_primitive h_int 0).continuousOn.le_sSup_image_Icc + exact (continuous_primitive h'_int 0).continuousOn.le_sSup_image_Icc (mem_Icc_of_Ico (Int.fract_div_mul_self_mem_Ico T t hT)) /-- If `g : ℝ → ℝ` is periodic with period `T > 0` and `0 < ∫ x in 0..T, g x`, then `t ↦ ∫ x in 0..t, g x` tends to `∞` as `t` tends to `∞`. -/ theorem tendsto_atTop_intervalIntegral_of_pos (h₀ : 0 < ∫ x in (0)..T, g x) (hT : 0 < T) : Tendsto (fun t => ∫ x in (0)..t, g x) atTop atTop := by + have h_int := intervalIntegrable_of_integral_ne_zero h₀.ne' apply tendsto_atTop_mono (hg.sInf_add_zsmul_le_integral_of_pos h_int hT) apply atTop.tendsto_atTop_add_const_left (sInf <| (fun t => ∫ x in (0)..t, g x) '' Icc 0 T) apply Tendsto.atTop_zsmul_const h₀ @@ -330,6 +386,7 @@ theorem tendsto_atTop_intervalIntegral_of_pos (h₀ : 0 < ∫ x in (0)..T, g x) `t ↦ ∫ x in 0..t, g x` tends to `-∞` as `t` tends to `-∞`. -/ theorem tendsto_atBot_intervalIntegral_of_pos (h₀ : 0 < ∫ x in (0)..T, g x) (hT : 0 < T) : Tendsto (fun t => ∫ x in (0)..t, g x) atBot atBot := by + have h_int := intervalIntegrable_of_integral_ne_zero h₀.ne' apply tendsto_atBot_mono (hg.integral_le_sSup_add_zsmul_of_pos h_int hT) apply atBot.tendsto_atBot_add_const_left (sSup <| (fun t => ∫ x in (0)..t, g x) '' Icc 0 T) apply Tendsto.atBot_zsmul_const h₀ @@ -337,15 +394,17 @@ theorem tendsto_atBot_intervalIntegral_of_pos (h₀ : 0 < ∫ x in (0)..T, g x) /-- If `g : ℝ → ℝ` is periodic with period `T > 0` and `∀ x, 0 < g x`, then `t ↦ ∫ x in 0..t, g x` tends to `∞` as `t` tends to `∞`. -/ -theorem tendsto_atTop_intervalIntegral_of_pos' (h₀ : ∀ x, 0 < g x) (hT : 0 < T) : +theorem tendsto_atTop_intervalIntegral_of_pos' + (h_int : IntervalIntegrable g MeasureSpace.volume 0 T) (h₀ : ∀ x, 0 < g x) (hT : 0 < T) : Tendsto (fun t => ∫ x in (0)..t, g x) atTop atTop := - hg.tendsto_atTop_intervalIntegral_of_pos h_int (intervalIntegral_pos_of_pos (h_int 0 T) h₀ hT) hT + hg.tendsto_atTop_intervalIntegral_of_pos (intervalIntegral_pos_of_pos h_int h₀ hT) hT /-- If `g : ℝ → ℝ` is periodic with period `T > 0` and `∀ x, 0 < g x`, then `t ↦ ∫ x in 0..t, g x` tends to `-∞` as `t` tends to `-∞`. -/ -theorem tendsto_atBot_intervalIntegral_of_pos' (h₀ : ∀ x, 0 < g x) (hT : 0 < T) : - Tendsto (fun t => ∫ x in (0)..t, g x) atBot atBot := - hg.tendsto_atBot_intervalIntegral_of_pos h_int (intervalIntegral_pos_of_pos (h_int 0 T) h₀ hT) hT +theorem tendsto_atBot_intervalIntegral_of_pos' + (h_int : IntervalIntegrable g MeasureSpace.volume 0 T) (h₀ : ∀ x, 0 < g x) (hT : 0 < T) : + Tendsto (fun t => ∫ x in (0)..t, g x) atBot atBot := by + exact hg.tendsto_atBot_intervalIntegral_of_pos (intervalIntegral_pos_of_pos h_int h₀ hT) hT end RealValued From 86b1020ee5b4cf232aa6c09834badf9ee9272c94 Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 23 Jan 2025 15:49:28 +0000 Subject: [PATCH 455/681] feat: inj/cancel from mono (#20973) Prove injectivity/cancellability of mul/add assuming some monotonicity. These results were rescued from #6627. Co-authored-by: Eric Wieser --- .../Algebra/Order/Monoid/Unbundled/Basic.lean | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean index a6577a705c6e3..aa2b6f7455877 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean @@ -144,13 +144,21 @@ section Preorder variable [Preorder α] @[to_additive] -lemma mul_left_mono [CovariantClass α α (· * ·) (· ≤ ·)] {a : α} : Monotone (a * ·) := +lemma mul_left_mono [MulLeftMono α] {a : α} : Monotone (a * ·) := fun _ _ h ↦ mul_le_mul_left' h _ @[to_additive] -lemma mul_right_mono [CovariantClass α α (swap (· * ·)) (· ≤ ·)] {a : α} : Monotone (· * a) := +lemma mul_right_mono [MulRightMono α] {a : α} : Monotone (· * a) := fun _ _ h ↦ mul_le_mul_right' h _ +@[to_additive] +lemma mul_left_strictMono [MulLeftStrictMono α] {a : α} : StrictMono (a * ·) := + fun _ _ h ↦ mul_lt_mul_left' h _ + +@[to_additive] +lemma mul_right_strictMono [MulRightStrictMono α] {a : α} : StrictMono (· * a) := + fun _ _ h ↦ mul_lt_mul_right' h _ + @[to_additive (attr := gcongr)] theorem mul_lt_mul_of_lt_of_lt [MulLeftStrictMono α] [MulRightStrictMono α] @@ -283,6 +291,24 @@ theorem mul_right_cancel'' [MulRightReflectLE α] {a b c : α} haveI := mulRightMono_of_mulRightStrictMono α rw [le_antisymm_iff, eq_true (mul_le_mul' hac hbd), true_and, mul_le_mul_iff_of_ge hac hbd] +@[to_additive] +lemma mul_left_inj_of_comparable [MulRightStrictMono α] {a b c : α} (h : b ≤ c ∨ c ≤ b) : + c * a = b * a ↔ c = b := by + refine ⟨fun h' => ?_, (· ▸ rfl)⟩ + contrapose h' + obtain h | h := h + · exact mul_lt_mul_right' (h.lt_of_ne' h') a |>.ne' + · exact mul_lt_mul_right' (h.lt_of_ne h') a |>.ne + +@[to_additive] +lemma mul_right_inj_of_comparable [MulLeftStrictMono α] {a b c : α} (h : b ≤ c ∨ c ≤ b) : + a * c = a * b ↔ c = b := by + refine ⟨fun h' => ?_, (· ▸ rfl)⟩ + contrapose h' + obtain h | h := h + · exact mul_lt_mul_left' (h.lt_of_ne' h') a |>.ne' + · exact mul_lt_mul_left' (h.lt_of_ne h') a |>.ne + end PartialOrder section LinearOrder @@ -325,6 +351,16 @@ lemma min_mul [CovariantClass α α (swap (· * ·)) (· ≤ ·)] (a b c : α) : haveI := mulRightMono_of_mulRightStrictMono α Left.min_le_max_of_mul_le_mul h +/-- Not an instance, to avoid loops with `IsLeftCancelMul.mulLeftStrictMono_of_mulLeftMono`. -/ +@[to_additive] +theorem MulLeftStrictMono.toIsLeftCancelMul [MulLeftStrictMono α] : IsLeftCancelMul α where + mul_left_cancel _ _ _ h := mul_left_strictMono.injective h + +/-- Not an instance, to avoid loops with `IsRightCancelMul.mulRightStrictMono_of_mulRightMono`. -/ +@[to_additive] +theorem MulRightStrictMono.toIsRightCancelMul [MulRightStrictMono α] : IsRightCancelMul α where + mul_right_cancel _ _ _ h := mul_right_strictMono.injective h + end LinearOrder section LinearOrder From fe0ee9b24874d3b129091c0e8eb7b77feb562b9d Mon Sep 17 00:00:00 2001 From: blizzard_inc Date: Thu, 23 Jan 2025 16:30:10 +0000 Subject: [PATCH 456/681] feat(Data/Control/Traversable/Instances): Add (Lawful)Traversable instance for Tree (#18818) This PR completes a TODO; this PR closes #13572. It was suggested at the issue that this could also be done with the `derive` handler for `(Lawful)Traversable`, but as mentioned there, that generates `map` and `traverse` functions that are not as universe-polymorphic. For writing the `Lawful` proof i took inspiration from the same instance for `FreeMagma` Co-authored-by: blizzard_inc Co-authored-by: Eric Wieser --- Mathlib.lean | 1 + Mathlib/Data/Tree/Basic.lean | 31 ++++++++++++-- Mathlib/Data/Tree/Traversable.lean | 69 ++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 Mathlib/Data/Tree/Traversable.lean diff --git a/Mathlib.lean b/Mathlib.lean index 4a99f1e1940c6..de108b3a42b31 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3035,6 +3035,7 @@ import Mathlib.Data.Sym.Sym2.Order import Mathlib.Data.Tree.Basic import Mathlib.Data.Tree.Get import Mathlib.Data.Tree.RBMap +import Mathlib.Data.Tree.Traversable import Mathlib.Data.TwoPointing import Mathlib.Data.TypeMax import Mathlib.Data.TypeVec diff --git a/Mathlib/Data/Tree/Basic.lean b/Mathlib/Data/Tree/Basic.lean index 75cba8e0b74ae..4c3e05fa8a410 100644 --- a/Mathlib/Data/Tree/Basic.lean +++ b/Mathlib/Data/Tree/Basic.lean @@ -18,10 +18,6 @@ We also specialize for `Tree Unit`, which is a binary tree without any additional data. We provide the notation `a △ b` for making a `Tree Unit` with children `a` and `b`. -## TODO - -Implement a `Traversable` instance for `Tree`. - ## References @@ -45,12 +41,39 @@ variable {α : Type u} instance : Inhabited (Tree α) := ⟨nil⟩ +/-- +Do an action for every node of the tree. +Actions are taken in node -> left subtree -> right subtree recursive order. +This function is the `traverse` function for the `Traversable Tree` instance. +-/ +def traverse {m : Type* → Type*} [Applicative m] {α β} (f : α → m β) : Tree α → m (Tree β) + | .nil => pure nil + | .node a l r => .node <$> f a <*> traverse f l <*> traverse f r + /-- Apply a function to each value in the tree. This is the `map` function for the `Tree` functor. -/ def map {β} (f : α → β) : Tree α → Tree β | nil => nil | node a l r => node (f a) (map f l) (map f r) +theorem id_map (t : Tree α) : t.map id = t := by + induction t with + | nil => rw [map] + | node v l r hl hr => rw [map, hl, hr, id_eq] + +theorem comp_map {β γ : Type*} (f : α → β) (g : β → γ) (t : Tree α) : + t.map (g ∘ f) = (t.map f).map g := by + induction t with + | nil => rw [map, map, map] + | node v l r hl hr => rw [map, map, map, hl, hr, Function.comp_apply] + +theorem traverse_pure (t : Tree α) {m : Type u → Type*} [Applicative m] [LawfulApplicative m] : + t.traverse (pure : α → m α) = pure t := by + induction t with + | nil => rw [traverse] + | node v l r hl hr => + rw [traverse, hl, hr, map_pure, pure_seq, seq_pure, map_pure, map_pure] + /-- The number of internal nodes (i.e. not including leaves) of a binary tree -/ @[simp] def numNodes : Tree α → ℕ diff --git a/Mathlib/Data/Tree/Traversable.lean b/Mathlib/Data/Tree/Traversable.lean new file mode 100644 index 0000000000000..9d1bd920b7724 --- /dev/null +++ b/Mathlib/Data/Tree/Traversable.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2025 Edward van de Meent. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Edward van de Meent +-/ + +import Mathlib.Data.Tree.Basic +import Mathlib.Control.Applicative +import Mathlib.Control.Traversable.Basic + +/-! +# Traversable Binary Tree + +Provides a `Traversable` instance for the `Tree` type. +-/ + +universe u v w + +namespace Tree +section Traverse +variable {α β : Type*} + +instance : Traversable Tree where + map := map + traverse := traverse + +lemma comp_traverse + {F : Type u → Type v} {G : Type v → Type w} [Applicative F] [Applicative G] + [LawfulApplicative G] {β : Type v} {γ : Type u} (f : β → F γ) (g : α → G β) + (t : Tree α) : t.traverse (Functor.Comp.mk ∘ (f <$> ·) ∘ g) = + Functor.Comp.mk ((·.traverse f) <$> (t.traverse g)) := by + induction t with + | nil => rw [traverse, traverse, map_pure, traverse]; rfl + | node v l r hl hr => + rw [traverse, hl, hr, traverse] + simp only [Function.comp_def, Function.comp_apply, Functor.Comp.map_mk, Functor.map_map, + Comp.seq_mk, seq_map_assoc, map_seq] + rfl + +lemma traverse_eq_map_id (f : α → β) (t : Tree α) : + t.traverse ((pure : β → Id β) ∘ f) = t.map f := by + rw [← Id.pure_eq (t.map f)] + induction t with + | nil => rw [traverse, map] + | node v l r hl hr => + rw [traverse, map, hl, hr, Function.comp_apply, map_pure, pure_seq, map_pure, pure_seq, + map_pure] + +lemma naturality {F G : Type u → Type*} [Applicative F] [Applicative G] [LawfulApplicative F] + [LawfulApplicative G] (η : ApplicativeTransformation F G) {β : Type u} (f : α → F β) + (t : Tree α) : η (t.traverse f) = t.traverse (η.app β ∘ f : α → G β) := by + induction t with + | nil => rw [traverse, traverse, η.preserves_pure] + | node v l r hl hr => + rw [traverse, traverse, η.preserves_seq, η.preserves_seq, η.preserves_map, hl, hr, + Function.comp_apply] + +instance : LawfulTraversable Tree where + map_const := rfl + id_map := id_map + comp_map := comp_map + id_traverse t := traverse_pure t + comp_traverse := comp_traverse + traverse_eq_map_id := traverse_eq_map_id + naturality η := naturality η + +end Traverse + +end Tree From d6544fee0d4d22bc5a485d003ded24ab34fd2423 Mon Sep 17 00:00:00 2001 From: Nick Ward <102917377+gio256@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:36:57 +0000 Subject: [PATCH 457/681] feat(AlgebraicTopology): rename standardSimplex to stdSimplex (#20974) Moves: - SSet.standardSimplex -> SSet.stdSimplex - SSet.standardSimplex.* -> SSet.stdSimplex.* --- .../AlgebraicTopology/ExtraDegeneracy.lean | 14 ++--- .../Quasicategory/StrictSegal.lean | 14 ++--- .../SimplicialSet/Basic.lean | 56 ++++++++++--------- .../AlgebraicTopology/SimplicialSet/Path.lean | 22 ++++---- 4 files changed, 54 insertions(+), 52 deletions(-) diff --git a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean index b84886418a547..d3372c2cc5cdc 100644 --- a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean +++ b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean @@ -176,10 +176,10 @@ def shift {n : ℕ} {Δ : SimplexCategory} substs hj₁ hj₂ simpa only [shiftFun_succ] using f.toOrderHom.monotone (Fin.succ_le_succ_iff.mp hi) } -open SSet.standardSimplex in +open SSet.stdSimplex in /-- The obvious extra degeneracy on the standard simplex. -/ protected noncomputable def extraDegeneracy (Δ : SimplexCategory) : - SimplicialObject.Augmented.ExtraDegeneracy (standardSimplex.obj Δ) where + SimplicialObject.Augmented.ExtraDegeneracy (stdSimplex.obj Δ) where s' _ := objMk (OrderHom.const _ 0) s _ f := (objEquiv _ _).symm (shift (objEquiv _ _ f)) @@ -198,7 +198,7 @@ protected noncomputable def extraDegeneracy (Δ : SimplexCategory) : apply (objEquiv _ _).injective apply SimplexCategory.Hom.ext ext i : 2 - dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.standardSimplex, + dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.stdSimplex, objEquiv, Equiv.ulift, uliftFunctor] simp only [shiftFun_succ] s_comp_δ n i := by @@ -206,7 +206,7 @@ protected noncomputable def extraDegeneracy (Δ : SimplexCategory) : apply (objEquiv _ _).injective apply SimplexCategory.Hom.ext ext j : 2 - dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.standardSimplex, + dsimp [SimplicialObject.δ, SimplexCategory.δ, SSet.stdSimplex, objEquiv, Equiv.ulift, uliftFunctor] by_cases h : j = 0 · subst h @@ -219,7 +219,7 @@ protected noncomputable def extraDegeneracy (Δ : SimplexCategory) : apply (objEquiv _ _).injective apply SimplexCategory.Hom.ext ext j : 2 - dsimp [SimplicialObject.σ, SimplexCategory.σ, SSet.standardSimplex, + dsimp [SimplicialObject.σ, SimplexCategory.σ, SSet.stdSimplex, objEquiv, Equiv.ulift, uliftFunctor] by_cases h : j = 0 · subst h @@ -227,8 +227,8 @@ protected noncomputable def extraDegeneracy (Δ : SimplexCategory) : · obtain ⟨_, rfl⟩ := Fin.eq_succ_of_ne_zero h simp only [Fin.succ_predAbove_succ, shiftFun_succ, Function.comp_apply] -instance nonempty_extraDegeneracy_standardSimplex (Δ : SimplexCategory) : - Nonempty (SimplicialObject.Augmented.ExtraDegeneracy (standardSimplex.obj Δ)) := +instance nonempty_extraDegeneracy_stdSimplex (Δ : SimplexCategory) : + Nonempty (SimplicialObject.Augmented.ExtraDegeneracy (stdSimplex.obj Δ)) := ⟨StandardSimplex.extraDegeneracy Δ⟩ end StandardSimplex diff --git a/Mathlib/AlgebraicTopology/Quasicategory/StrictSegal.lean b/Mathlib/AlgebraicTopology/Quasicategory/StrictSegal.lean index 2cecadb7f1d91..f083df9d4a6ab 100644 --- a/Mathlib/AlgebraicTopology/Quasicategory/StrictSegal.lean +++ b/Mathlib/AlgebraicTopology/Quasicategory/StrictSegal.lean @@ -39,18 +39,18 @@ instance quasicategory {X : SSet.{u}} [StrictSegal X] : Quasicategory X := by · rw [← spine_arrow, spine_δ_arrow_lt _ hlt] dsimp only [Path.map, spine_arrow, Fin.coe_eq_castSucc] apply congr_arg - simp only [horn, horn.spineId, standardSimplex, uliftFunctor, Functor.comp_obj, + simp only [horn, horn.spineId, stdSimplex, uliftFunctor, Functor.comp_obj, yoneda_obj_obj, whiskering_obj_obj_map, uliftFunctor_map, yoneda_obj_map, - standardSimplex.objEquiv, Equiv.ulift, Equiv.coe_fn_symm_mk, + stdSimplex.objEquiv, Equiv.ulift, Equiv.coe_fn_symm_mk, Quiver.Hom.unop_op, horn.face_coe, Subtype.mk.injEq] rw [mkOfSucc_δ_lt hlt] rfl · rw [← spine_arrow, spine_δ_arrow_gt _ hgt] dsimp only [Path.map, spine_arrow, Fin.coe_eq_castSucc] apply congr_arg - simp only [horn, horn.spineId, standardSimplex, uliftFunctor, Functor.comp_obj, + simp only [horn, horn.spineId, stdSimplex, uliftFunctor, Functor.comp_obj, yoneda_obj_obj, whiskering_obj_obj_map, uliftFunctor_map, yoneda_obj_map, - standardSimplex.objEquiv, Equiv.ulift, Equiv.coe_fn_symm_mk, + stdSimplex.objEquiv, Equiv.ulift, Equiv.coe_fn_symm_mk, Quiver.Hom.unop_op, horn.face_coe, Subtype.mk.injEq] rw [mkOfSucc_δ_gt hgt] rfl @@ -74,7 +74,7 @@ instance quasicategory {X : SSet.{u}} [StrictSegal X] : Quasicategory X := by dsimp [spine_arrow, Path.interval, Path.map] rw [← types_comp_apply (σ₀.app _) (X.map _), ← σ₀.naturality] apply congr_arg - simp only [horn, standardSimplex, uliftFunctor, Functor.comp_obj, + simp only [horn, stdSimplex, uliftFunctor, Functor.comp_obj, whiskering_obj_obj_obj, yoneda_obj_obj, uliftFunctor_obj, ne_eq, whiskering_obj_obj_map, uliftFunctor_map, yoneda_obj_map, len_mk, Nat.reduceAdd, Quiver.Hom.unop_op] @@ -85,7 +85,7 @@ instance quasicategory {X : SSet.{u}} [StrictSegal X] : Quasicategory X := by simp only [spineToDiagonal, diagonal, spineToSimplex_spine] rw [← types_comp_apply (σ₀.app _) (X.map _), ← σ₀.naturality, types_comp_apply] apply congr_arg - simp only [horn, standardSimplex, uliftFunctor, Functor.comp_obj, + simp only [horn, stdSimplex, uliftFunctor, Functor.comp_obj, whiskering_obj_obj_obj, yoneda_obj_obj, uliftFunctor_obj, uliftFunctor_map, whiskering_obj_obj_map, yoneda_obj_map, horn.face_coe, len_mk, Nat.reduceAdd, Quiver.Hom.unop_op, Subtype.mk.injEq, ULift.up_inj] @@ -94,7 +94,7 @@ instance quasicategory {X : SSet.{u}} [StrictSegal X] : Quasicategory X := by | zero => contradiction | succ _ => fin_cases z <;> - · simp only [standardSimplex.objEquiv, uliftFunctor_map, yoneda_obj_map, + · simp only [stdSimplex.objEquiv, uliftFunctor_map, yoneda_obj_map, Quiver.Hom.unop_op, Equiv.ulift_symm_down] rw [mkOfSucc_δ_eq heq] rfl diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean index bddd445599fef..26a81d25fb187 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean @@ -71,43 +71,45 @@ def uliftFunctor : SSet.{u} ⥤ SSet.{max u v} := /-- The `n`-th standard simplex `Δ[n]` associated with a nonempty finite linear order `n` is the Yoneda embedding of `n`. -/ -def standardSimplex : SimplexCategory ⥤ SSet.{u} := +def stdSimplex : SimplexCategory ⥤ SSet.{u} := yoneda ⋙ uliftFunctor -@[inherit_doc SSet.standardSimplex] -scoped[Simplicial] notation3 "Δ[" n "]" => SSet.standardSimplex.obj (SimplexCategory.mk n) +@[deprecated (since := "2025-01-23")] alias standardSimplex := stdSimplex + +@[inherit_doc SSet.stdSimplex] +scoped[Simplicial] notation3 "Δ[" n "]" => SSet.stdSimplex.obj (SimplexCategory.mk n) instance : Inhabited SSet := ⟨Δ[0]⟩ -namespace standardSimplex +namespace stdSimplex open Finset Opposite SimplexCategory @[simp] lemma map_id (n : SimplexCategory) : - (SSet.standardSimplex.map (SimplexCategory.Hom.mk OrderHom.id : n ⟶ n)) = 𝟙 _ := + (SSet.stdSimplex.map (SimplexCategory.Hom.mk OrderHom.id : n ⟶ n)) = 𝟙 _ := CategoryTheory.Functor.map_id _ _ /-- Simplices of the standard simplex identify to morphisms in `SimplexCategory`. -/ def objEquiv (n : SimplexCategory) (m : SimplexCategoryᵒᵖ) : - (standardSimplex.{u}.obj n).obj m ≃ (m.unop ⟶ n) := + (stdSimplex.{u}.obj n).obj m ≃ (m.unop ⟶ n) := Equiv.ulift.{u, 0} /-- Constructor for simplices of the standard simplex which takes a `OrderHom` as an input. -/ abbrev objMk {n : SimplexCategory} {m : SimplexCategoryᵒᵖ} (f : Fin (len m.unop + 1) →o Fin (n.len + 1)) : - (standardSimplex.{u}.obj n).obj m := + (stdSimplex.{u}.obj n).obj m := (objEquiv _ _).symm (Hom.mk f) lemma map_apply {m₁ m₂ : SimplexCategoryᵒᵖ} (f : m₁ ⟶ m₂) {n : SimplexCategory} - (x : (standardSimplex.{u}.obj n).obj m₁) : - (standardSimplex.{u}.obj n).map f x = (objEquiv _ _).symm (f.unop ≫ (objEquiv _ _) x) := by + (x : (stdSimplex.{u}.obj n).obj m₁) : + (stdSimplex.{u}.obj n).map f x = (objEquiv _ _).symm (f.unop ≫ (objEquiv _ _) x) := by rfl -/-- The canonical bijection `(standardSimplex.obj n ⟶ X) ≃ X.obj (op n)`. -/ +/-- The canonical bijection `(stdSimplex.obj n ⟶ X) ≃ X.obj (op n)`. -/ def _root_.SSet.yonedaEquiv (X : SSet.{u}) (n : SimplexCategory) : - (standardSimplex.obj n ⟶ X) ≃ X.obj (op n) := + (stdSimplex.obj n ⟶ X) ≃ X.obj (op n) := yonedaCompUliftFunctorEquiv X n /-- The unique non-degenerate `n`-simplex in `Δ[n]`. -/ @@ -149,7 +151,7 @@ lemma coe_triangle_down_toOrderHom {n : ℕ} (a b c : Fin (n+1)) (hab : a ≤ b) ↑(triangle a b c hab hbc).down.toOrderHom = ![a, b, c] := rfl -end standardSimplex +end stdSimplex section @@ -161,7 +163,7 @@ def asOrderHom {n} {m} (α : Δ[n].obj m) : OrderHom (Fin (m.unop.len + 1)) (Fin end /-- The boundary `∂Δ[n]` of the `n`-th standard simplex consists of -all `m`-simplices of `standardSimplex n` that are not surjective +all `m`-simplices of `stdSimplex n` that are not surjective (when viewed as monotone function `m → n`). -/ def boundary (n : ℕ) : SSet.{u} where obj m := { α : Δ[n].obj m // ¬Function.Surjective (asOrderHom α) } @@ -219,7 +221,7 @@ open SimplexCategory Finset Opposite /-- The (degenerate) subsimplex of `Λ[n+2, i]` concentrated in vertex `k`. -/ @[simps] def const (n : ℕ) (i k : Fin (n+3)) (m : SimplexCategoryᵒᵖ) : Λ[n+2, i].obj m := by - refine ⟨standardSimplex.const _ k _, ?_⟩ + refine ⟨stdSimplex.const _ k _, ?_⟩ suffices ¬ Finset.univ ⊆ {i, k} by simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or, Fin.forall_fin_one, subset_iff, mem_univ, @eq_comm _ _ k] @@ -233,7 +235,7 @@ def const (n : ℕ) (i k : Fin (n+3)) (m : SimplexCategoryᵒᵖ) : Λ[n+2, i].o This edge only exists if `{i, a, b}` has cardinality less than `n`. -/ @[simps] def edge (n : ℕ) (i a b : Fin (n+1)) (hab : a ≤ b) (H : #{i, a, b} ≤ n) : Λ[n, i] _[1] := by - refine ⟨standardSimplex.edge n a b hab, ?range⟩ + refine ⟨stdSimplex.edge n a b hab, ?range⟩ case range => suffices ∃ x, ¬i = x ∧ ¬a = x ∧ ¬b = x by simpa only [unop_op, len_mk, Nat.reduceAdd, asOrderHom, yoneda_obj_obj, Set.union_singleton, @@ -277,7 +279,7 @@ which is the type of horn that occurs in the horn-filling condition of quasicate def primitiveTriangle {n : ℕ} (i : Fin (n+4)) (h₀ : 0 < i) (hₙ : i < Fin.last (n+3)) (k : ℕ) (h : k < n+2) : Λ[n+3, i] _[2] := by - refine ⟨standardSimplex.triangle + refine ⟨stdSimplex.triangle (n := n+3) ⟨k, by omega⟩ ⟨k+1, by omega⟩ ⟨k+2, by omega⟩ ?_ ?_, ?_⟩ · simp only [Fin.mk_le_mk, le_add_iff_nonneg_right, zero_le] · simp only [Fin.mk_le_mk, add_le_add_iff_left, one_le_two] @@ -285,8 +287,8 @@ def primitiveTriangle {n : ℕ} (i : Fin (n+4)) OrderHom.const_coe_coe, Set.union_singleton, ne_eq, ← Set.univ_subset_iff, Set.subset_def, Set.mem_univ, Set.mem_insert_iff, Set.mem_range, Function.const_apply, exists_const, forall_true_left, not_forall, not_or, unop_op, not_exists, - standardSimplex.triangle, OrderHom.coe_mk, @eq_comm _ _ i, - standardSimplex.objMk, standardSimplex.objEquiv, Equiv.ulift] + stdSimplex.triangle, OrderHom.coe_mk, @eq_comm _ _ i, + stdSimplex.objMk, stdSimplex.objEquiv, Equiv.ulift] dsimp by_cases hk0 : k = 0 · subst hk0 @@ -302,9 +304,9 @@ def primitiveTriangle {n : ℕ} (i : Fin (n+4)) /-- The `j`th subface of the `i`-th horn. -/ @[simps] def face {n : ℕ} (i j : Fin (n+2)) (h : j ≠ i) : Λ[n+1, i] _[n] := - ⟨(standardSimplex.objEquiv _ _).symm (SimplexCategory.δ j), by + ⟨(stdSimplex.objEquiv _ _).symm (SimplexCategory.δ j), by simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, SimplexCategory.δ, not_or, - standardSimplex.objEquiv, asOrderHom, Equiv.ulift]⟩ + stdSimplex.objEquiv, asOrderHom, Equiv.ulift]⟩ /-- Two morphisms from a horn are equal if they are equal on all suitable faces. -/ protected @@ -313,14 +315,14 @@ lemma hom_ext {n : ℕ} {i : Fin (n+2)} {S : SSet} (σ₁ σ₂ : Λ[n+1, i] ⟶ σ₁ = σ₂ := by apply NatTrans.ext; apply funext; apply Opposite.rec; apply SimplexCategory.rec intro m; ext f - obtain ⟨f', hf⟩ := (standardSimplex.objEquiv _ _).symm.surjective f.1 + obtain ⟨f', hf⟩ := (stdSimplex.objEquiv _ _).symm.surjective f.1 obtain ⟨j, hji, hfj⟩ : ∃ j, ¬j = i ∧ ∀ k, f'.toOrderHom k ≠ j := by obtain ⟨f, hf'⟩ := f subst hf simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or] using hf' have H : f = (Λ[n+1, i].map (factor_δ f' j).op) (face i j hji) := by apply Subtype.ext - apply (standardSimplex.objEquiv _ _).injective + apply (stdSimplex.objEquiv _ _).injective rw [← hf] exact (factor_δ_spec f' j hfj).symm have H₁ := congrFun (σ₁.naturality (factor_δ f' j).op) (face i j hji) @@ -337,8 +339,8 @@ open Simplicial /-- The simplicial circle. -/ noncomputable def S1 : SSet := Limits.colimit <| - Limits.parallelPair (standardSimplex.map <| SimplexCategory.δ 0 : Δ[0] ⟶ Δ[1]) - (standardSimplex.map <| SimplexCategory.δ 1) + Limits.parallelPair (stdSimplex.map <| SimplexCategory.δ 0 : Δ[0] ⟶ Δ[1]) + (stdSimplex.map <| SimplexCategory.δ 1) end Examples @@ -455,13 +457,13 @@ namespace Augmented /-- The functor which sends `[n]` to the simplicial set `Δ[n]` equipped by the obvious augmentation towards the terminal object of the category of sets. -/ @[simps] -noncomputable def standardSimplex : SimplexCategory ⥤ SSet.Augmented.{u} where +noncomputable def stdSimplex : SimplexCategory ⥤ SSet.Augmented.{u} where obj Δ := - { left := SSet.standardSimplex.obj Δ + { left := SSet.stdSimplex.obj Δ right := terminal _ hom := { app := fun _ => terminal.from _ } } map θ := - { left := SSet.standardSimplex.map θ + { left := SSet.stdSimplex.map θ right := terminal.from _ } end Augmented diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean index ff920be3bfa29..b28e32a3ebf16 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean @@ -110,8 +110,8 @@ lemma map_interval {X Y : SSet.{u}} {n : ℕ} (f : X.Path n) (σ : X ⟶ Y) (f.map σ).interval j l hjl = (f.interval j l hjl).map σ := rfl /-- The spine of the unique non-degenerate `n`-simplex in `Δ[n]`.-/ -def standardSimplex.spineId (n : ℕ) : Path Δ[n] n := - spine Δ[n] n (standardSimplex.id n) +def stdSimplex.spineId (n : ℕ) : Path Δ[n] n := + spine Δ[n] n (stdSimplex.id n) /-- Any inner horn contains the spine of the unique non-degenerate `n`-simplex in `Δ[n]`.-/ @@ -119,27 +119,27 @@ in `Δ[n]`.-/ def horn.spineId {n : ℕ} (i : Fin (n + 3)) (h₀ : 0 < i) (hₙ : i < Fin.last (n + 2)) : Path Λ[n + 2, i] (n + 2) where - vertex j := ⟨standardSimplex.spineId _ |>.vertex j, (horn.const n i j _).property⟩ - arrow j := ⟨standardSimplex.spineId _ |>.arrow j, by + vertex j := ⟨stdSimplex.spineId _ |>.vertex j, (horn.const n i j _).property⟩ + arrow j := ⟨stdSimplex.spineId _ |>.arrow j, by let edge := horn.primitiveEdge h₀ hₙ j - have ha : (standardSimplex.spineId _).arrow j = edge.val := by - dsimp only [edge, standardSimplex.spineId, standardSimplex.id, spine_arrow, - mkOfSucc, horn.primitiveEdge, horn.edge, standardSimplex.edge, - standardSimplex.map_apply] + have ha : (stdSimplex.spineId _).arrow j = edge.val := by + dsimp only [edge, stdSimplex.spineId, stdSimplex.id, spine_arrow, + mkOfSucc, horn.primitiveEdge, horn.edge, stdSimplex.edge, + stdSimplex.map_apply] aesop rw [ha] exact edge.property⟩ arrow_src := by simp only [horn, SimplicialObject.δ, Subtype.mk.injEq] - exact standardSimplex.spineId _ |>.arrow_src + exact stdSimplex.spineId _ |>.arrow_src arrow_tgt := by simp only [horn, SimplicialObject.δ, Subtype.mk.injEq] - exact standardSimplex.spineId _ |>.arrow_tgt + exact stdSimplex.spineId _ |>.arrow_tgt @[simp] lemma horn.spineId_map_hornInclusion {n : ℕ} (i : Fin (n + 3)) (h₀ : 0 < i) (hₙ : i < Fin.last (n + 2)) : Path.map (horn.spineId i h₀ hₙ) (hornInclusion (n + 2) i) = - standardSimplex.spineId (n + 2) := rfl + stdSimplex.spineId (n + 2) := rfl end SSet From 6c6a89a1512208173bc28f4b39b1ee0b64a15ad5 Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Thu, 23 Jan 2025 17:46:20 +0000 Subject: [PATCH 458/681] doc(RingTheory/LaurentSeries): correct docstring (#20990) Remove a superfluous backtick and remove `.symm` in a lemma of the docstring so that it can be made clickable. --- Mathlib/RingTheory/LaurentSeries.lean | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Mathlib/RingTheory/LaurentSeries.lean b/Mathlib/RingTheory/LaurentSeries.lean index fd5d7b6a7e4a6..cf8a577647928 100644 --- a/Mathlib/RingTheory/LaurentSeries.lean +++ b/Mathlib/RingTheory/LaurentSeries.lean @@ -24,7 +24,7 @@ type with a zero. They are denoted `R⸨X⸩`. * Defines `LaurentSeries` as an abbreviation for `HahnSeries ℤ`. * Defines `hasseDeriv` of a Laurent series with coefficients in a module over a ring. -* Provides a coercion `from power series `R⟦X⟧` into `R⸨X⸩` given by `HahnSeries.ofPowerSeries`. +* Provides a coercion from power series `R⟦X⟧` into `R⸨X⸩` given by `HahnSeries.ofPowerSeries`. * Defines `LaurentSeries.powerSeriesPart` * Defines the localization map `LaurentSeries.of_powerSeries_localization` which evaluates to `HahnSeries.ofPowerSeries`. @@ -79,7 +79,8 @@ equivalence: `LaurentSeries.LaurentSeriesRingEquiv` is the *topological, ring eq `K⸨X⸩ ≃+* RatFuncAdicCompl K`. * In order to compare `K⟦X⟧` with the valuation subring in the `X`-adic completion of `RatFunc K` we consider its alias `LaurentSeries.powerSeries_as_subring` as a subring of `K⸨X⸩`, -that is itself clearly isomorphic (via `LaurentSeries.powerSeriesEquivSubring.symm`) to `K⟦X⟧`. +that is itself clearly isomorphic (via the inverse of `LaurentSeries.powerSeriesEquivSubring`) +to `K⟦X⟧`. ## To Do * The `AdicCompletion` construction is currently done for ideals in rings and does not take into From eb87fb47f61af96018faeb6fb60ac8f5207152c3 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Thu, 23 Jan 2025 17:58:07 +0000 Subject: [PATCH 459/681] =?UTF-8?q?feat:=20the=20functor=20`Ind.lim=20I=20?= =?UTF-8?q?:=20(I=20=E2=A5=A4=20C)=20=E2=A5=A4=20Ind=20C`=20(#20992)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Markus Himmel --- .../Limits/Indization/Category.lean | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Mathlib/CategoryTheory/Limits/Indization/Category.lean b/Mathlib/CategoryTheory/Limits/Indization/Category.lean index 4de4c45fb1b0f..7b2b555d9cb66 100644 --- a/Mathlib/CategoryTheory/Limits/Indization/Category.lean +++ b/Mathlib/CategoryTheory/Limits/Indization/Category.lean @@ -16,6 +16,8 @@ import Mathlib.CategoryTheory.Limits.Indization.Products We define the `v`-category of Ind-objects of a category `C`, called `Ind C`, as well as the functors `Ind.yoneda : C ⥤ Ind C` and `Ind.inclusion C : Ind C ⥤ Cᵒᵖ ⥤ Type v`. +For a small filtered category `I`, we also define `Ind.lim I : (I ⥤ C) ⥤ Ind C`. + This file will mainly collect results about ind-objects (stated in terms of `IsIndObject`) and reinterpret them in terms of `Ind C`. @@ -157,6 +159,39 @@ instance : RepresentablyCoflat (Ind.yoneda (C := C)) := by noncomputable instance : PreservesFiniteColimits (Ind.yoneda (C := C)) := preservesFiniteColimits_of_coflat _ +/-- This is the functor `(I ⥤ C) ⥤ Ind C` that sends a functor `F` to `colim (Y ∘ F)`, where `Y` +is the Yoneda embedding. It is known as "ind-lim" and denoted `“colim”` in [Kashiwara2006]. -/ +protected noncomputable def Ind.lim (I : Type v) [SmallCategory I] [IsFiltered I] : + (I ⥤ C) ⥤ Ind C := + (whiskeringRight _ _ _).obj Ind.yoneda ⋙ colim + +/-- Computing ind-lims in `Ind C` is the same as computing them in `Cᵒᵖ ⥤ Type v`. -/ +noncomputable def Ind.limCompInclusion {I : Type v} [SmallCategory I] [IsFiltered I] : + Ind.lim I ⋙ Ind.inclusion C ≅ (whiskeringRight _ _ _).obj yoneda ⋙ colim := calc + Ind.lim I ⋙ Ind.inclusion C + ≅ (whiskeringRight _ _ _).obj Ind.yoneda ⋙ colim ⋙ Ind.inclusion C := Functor.associator _ _ _ + _ ≅ (whiskeringRight _ _ _).obj Ind.yoneda ⋙ + (whiskeringRight _ _ _).obj (Ind.inclusion C) ⋙ colim := + isoWhiskerLeft _ (preservesColimitNatIso _) + _ ≅ ((whiskeringRight _ _ _).obj Ind.yoneda ⋙ + (whiskeringRight _ _ _).obj (Ind.inclusion C)) ⋙ colim := (Functor.associator _ _ _).symm + _ ≅ (whiskeringRight _ _ _).obj (Ind.yoneda ⋙ Ind.inclusion C) ⋙ colim := + isoWhiskerRight (whiskeringRightObjCompIso _ _) colim + _ ≅ (whiskeringRight _ _ _).obj yoneda ⋙ colim := + isoWhiskerRight ((whiskeringRight _ _ _).mapIso (Ind.yonedaCompInclusion)) colim + +instance {α : Type v} [SmallCategory α] [FinCategory α] [HasLimitsOfShape α C] {I : Type v} + [SmallCategory I] [IsFiltered I] : + PreservesLimitsOfShape α (Ind.lim I : (I ⥤ C) ⥤ _) := + haveI : PreservesLimitsOfShape α (Ind.lim I ⋙ Ind.inclusion C) := + preservesLimitsOfShape_of_natIso Ind.limCompInclusion.symm + preservesLimitsOfShape_of_reflects_of_preserves _ (Ind.inclusion C) + +instance {α : Type v} [SmallCategory α] [FinCategory α] [HasColimitsOfShape α C] {I : Type v} + [SmallCategory I] [IsFiltered I] : + PreservesColimitsOfShape α (Ind.lim I : (I ⥤ C) ⥤ _) := + inferInstanceAs (PreservesColimitsOfShape α (_ ⋙ colim)) + instance {α : Type v} [Finite α] [HasColimitsOfShape (Discrete α) C] : HasColimitsOfShape (Discrete α) (Ind C) := by refine ⟨fun F => ?_⟩ From 27deb2397eda5021c575c1ab20959bc782cb12fc Mon Sep 17 00:00:00 2001 From: Thomas Browning Date: Thu, 23 Jan 2025 18:20:52 +0000 Subject: [PATCH 460/681] refactor(FieldTheory/Normal): Split file (#20724) This PR splits `FieldTheory/Normal`. In particular, the proof of normal iff splitting field is now in `FieldTheory/Normal/Basic`. --- Mathlib.lean | 5 +- Mathlib/FieldTheory/AlgebraicClosure.lean | 2 +- Mathlib/FieldTheory/Fixed.lean | 3 +- Mathlib/FieldTheory/Galois/Basic.lean | 2 +- Mathlib/FieldTheory/Galois/GaloisClosure.lean | 2 +- Mathlib/FieldTheory/IsAlgClosed/Basic.lean | 3 +- Mathlib/FieldTheory/Isaacs.lean | 1 + Mathlib/FieldTheory/Minpoly/IsConjRoot.lean | 5 +- .../{Normal.lean => Normal/Basic.lean} | 197 +------------- .../Closure.lean} | 2 +- Mathlib/FieldTheory/Normal/Defs.lean | 242 ++++++++++++++++++ Mathlib/FieldTheory/PrimitiveElement.lean | 1 + Mathlib/FieldTheory/SeparableDegree.lean | 2 +- 13 files changed, 262 insertions(+), 205 deletions(-) rename Mathlib/FieldTheory/{Normal.lean => Normal/Basic.lean} (59%) rename Mathlib/FieldTheory/{NormalClosure.lean => Normal/Closure.lean} (99%) create mode 100644 Mathlib/FieldTheory/Normal/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index de108b3a42b31..5a9abcd4c4466 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3149,8 +3149,9 @@ import Mathlib.FieldTheory.Minpoly.IsConjRoot import Mathlib.FieldTheory.Minpoly.IsIntegrallyClosed import Mathlib.FieldTheory.Minpoly.MinpolyDiv import Mathlib.FieldTheory.MvRatFunc.Rank -import Mathlib.FieldTheory.Normal -import Mathlib.FieldTheory.NormalClosure +import Mathlib.FieldTheory.Normal.Basic +import Mathlib.FieldTheory.Normal.Closure +import Mathlib.FieldTheory.Normal.Defs import Mathlib.FieldTheory.Perfect import Mathlib.FieldTheory.PerfectClosure import Mathlib.FieldTheory.PolynomialGaloisGroup diff --git a/Mathlib/FieldTheory/AlgebraicClosure.lean b/Mathlib/FieldTheory/AlgebraicClosure.lean index 056881d31cde2..559bd7ea774b1 100644 --- a/Mathlib/FieldTheory/AlgebraicClosure.lean +++ b/Mathlib/FieldTheory/AlgebraicClosure.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Jiedong Jiang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Junyan Xu, Jiedong Jiang -/ -import Mathlib.FieldTheory.NormalClosure +import Mathlib.FieldTheory.Normal.Closure import Mathlib.FieldTheory.IsAlgClosed.Basic import Mathlib.FieldTheory.IntermediateField.Algebraic diff --git a/Mathlib/FieldTheory/Fixed.lean b/Mathlib/FieldTheory/Fixed.lean index 973277f311115..6c4eee03e3080 100644 --- a/Mathlib/FieldTheory/Fixed.lean +++ b/Mathlib/FieldTheory/Fixed.lean @@ -6,8 +6,9 @@ Authors: Kenny Lau import Mathlib.Algebra.Polynomial.GroupRingAction import Mathlib.Algebra.Ring.Action.Field import Mathlib.Algebra.Ring.Action.Invariant -import Mathlib.FieldTheory.Normal +import Mathlib.FieldTheory.Normal.Defs import Mathlib.FieldTheory.Separable +import Mathlib.LinearAlgebra.Dual import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix /-! diff --git a/Mathlib/FieldTheory/Galois/Basic.lean b/Mathlib/FieldTheory/Galois/Basic.lean index e5dd455a5a331..212915fa47195 100644 --- a/Mathlib/FieldTheory/Galois/Basic.lean +++ b/Mathlib/FieldTheory/Galois/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Patrick Lutz, Yongle Hu, Jingting Wang -/ import Mathlib.FieldTheory.Fixed -import Mathlib.FieldTheory.NormalClosure +import Mathlib.FieldTheory.Normal.Closure import Mathlib.FieldTheory.PrimitiveElement import Mathlib.GroupTheory.GroupAction.FixingSubgroup diff --git a/Mathlib/FieldTheory/Galois/GaloisClosure.lean b/Mathlib/FieldTheory/Galois/GaloisClosure.lean index 3a5effad525c8..bb80f0aad565f 100644 --- a/Mathlib/FieldTheory/Galois/GaloisClosure.lean +++ b/Mathlib/FieldTheory/Galois/GaloisClosure.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Nailin Guan, Yuyang Zhao -/ -import Mathlib.FieldTheory.NormalClosure +import Mathlib.FieldTheory.Normal.Closure import Mathlib.FieldTheory.SeparableClosure /-! diff --git a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean index 156df9e238ca5..6c1c121b87fb7 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean @@ -3,7 +3,8 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ -import Mathlib.FieldTheory.Normal +import Mathlib.FieldTheory.Extension +import Mathlib.FieldTheory.Normal.Defs import Mathlib.FieldTheory.Perfect import Mathlib.RingTheory.Localization.Integral diff --git a/Mathlib/FieldTheory/Isaacs.lean b/Mathlib/FieldTheory/Isaacs.lean index 2219c66b3c027..a5f3fdb5637b1 100644 --- a/Mathlib/FieldTheory/Isaacs.lean +++ b/Mathlib/FieldTheory/Isaacs.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 Junyan Xu. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Junyan Xu -/ +import Mathlib.FieldTheory.Normal.Basic import Mathlib.FieldTheory.PrimitiveElement import Mathlib.GroupTheory.CosetCover diff --git a/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean b/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean index fe5e7910abb47..e6491b2c7bb02 100644 --- a/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean +++ b/Mathlib/FieldTheory/Minpoly/IsConjRoot.lean @@ -3,9 +3,10 @@ Copyright (c) 2024 Jiedong Jiang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jiedong Jiang -/ -import Mathlib.FieldTheory.Minpoly.Basic +import Mathlib.FieldTheory.Extension import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic -import Mathlib.FieldTheory.Normal +import Mathlib.FieldTheory.Minpoly.Basic +import Mathlib.FieldTheory.Normal.Defs /-! # Conjugate roots diff --git a/Mathlib/FieldTheory/Normal.lean b/Mathlib/FieldTheory/Normal/Basic.lean similarity index 59% rename from Mathlib/FieldTheory/Normal.lean rename to Mathlib/FieldTheory/Normal/Basic.lean index c209741701297..2ce3b4b8935ec 100644 --- a/Mathlib/FieldTheory/Normal.lean +++ b/Mathlib/FieldTheory/Normal/Basic.lean @@ -4,19 +4,17 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Thomas Browning, Patrick Lutz -/ import Mathlib.FieldTheory.Extension -import Mathlib.FieldTheory.SplittingField.Construction +import Mathlib.FieldTheory.Normal.Defs import Mathlib.GroupTheory.Solvable +import Mathlib.FieldTheory.SplittingField.Construction /-! # Normal field extensions -In this file we define normal field extensions and prove that for a finite extension, being normal +In this file we prove that for a finite extension, being normal is the same as being a splitting field (`Normal.of_isSplittingField` and `Normal.exists_isSplittingField`). -## Main Definitions - -- `Normal F K` where `K` is a field extension of `F`. -/ @@ -26,34 +24,6 @@ open Polynomial IsScalarTower variable (F K : Type*) [Field F] [Field K] [Algebra F K] -/-- Typeclass for normal field extension: `K` is a normal extension of `F` iff the minimal -polynomial of every element `x` in `K` splits in `K`, i.e. every conjugate of `x` is in `K`. -/ -@[stacks 09HM] -class Normal extends Algebra.IsAlgebraic F K : Prop where - splits' (x : K) : Splits (algebraMap F K) (minpoly F x) - -variable {F K} - -theorem Normal.isIntegral (_ : Normal F K) (x : K) : IsIntegral F x := - Algebra.IsIntegral.isIntegral x - -theorem Normal.splits (_ : Normal F K) (x : K) : Splits (algebraMap F K) (minpoly F x) := - Normal.splits' x - -theorem normal_iff : Normal F K ↔ ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) := - ⟨fun h x => ⟨h.isIntegral x, h.splits x⟩, fun h => - { isAlgebraic := fun x => (h x).1.isAlgebraic - splits' := fun x => (h x).2 }⟩ - -theorem Normal.out : Normal F K → ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) := - normal_iff.1 - -variable (F K) - -instance normal_self : Normal F F where - isAlgebraic := fun _ => isIntegral_algebraMap.isAlgebraic - splits' := fun x => (minpoly.eq_X_sub_C' x).symm ▸ splits_X_sub_C _ - theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K] : ∃ p : F[X], IsSplittingField F K p := by classical @@ -76,32 +46,7 @@ section NormalTower variable (E : Type*) [Field E] [Algebra F E] [Algebra K E] [IsScalarTower F K E] -@[stacks 09HN] -theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E := - normal_iff.2 fun x => by - cases' h.out x with hx hhx - rw [algebraMap_eq F K E] at hhx - exact - ⟨hx.tower_top, - Polynomial.splits_of_splits_of_dvd (algebraMap K E) - (Polynomial.map_ne_zero (minpoly.ne_zero hx)) - ((Polynomial.splits_map_iff (algebraMap F K) (algebraMap K E)).mpr hhx) - (minpoly.dvd_map_of_isScalarTower F K x)⟩ - -theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function.Bijective ϕ := - h.toIsAlgebraic.bijective_of_isScalarTower' ϕ - variable {E F} -variable {E' : Type*} [Field E'] [Algebra F E'] - -theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' := by - rw [normal_iff] at h ⊢ - intro x; specialize h (f.symm x) - rw [← f.apply_symm_apply x, minpoly.algEquiv_eq, ← f.toAlgHom.comp_algebraMap] - exact ⟨h.1.map f, splits_comp_of_splits _ _ h.2⟩ - -theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F E' := - ⟨fun _ ↦ Normal.of_algEquiv f, fun _ ↦ Normal.of_algEquiv f.symm⟩ open IntermediateField @@ -200,14 +145,6 @@ instance normal_inf Normal F (E ⊓ E' : IntermediateField F K) := iInf_bool_eq (f := Bool.rec E' E) ▸ normal_iInf (h := by rintro (_|_) <;> infer_instance) -variable {F K} -variable {L : Type*} [Field L] [Algebra F L] [Algebra K L] [IsScalarTower F K L] - -@[simp] -theorem restrictScalars_normal {E : IntermediateField K L} : - Normal F (E.restrictScalars F) ↔ Normal F E := - Iff.rfl - end IntermediateField variable {F} {K} @@ -220,50 +157,6 @@ section Restrict variable (E : Type*) [Field E] [Algebra F E] [Algebra E K₁] [Algebra E K₂] [Algebra E K₃] [IsScalarTower F E K₁] [IsScalarTower F E K₂] [IsScalarTower F E K₃] -/-- Restrict algebra homomorphism to image of normal subfield -/ -def AlgHom.restrictNormalAux [h : Normal F E] : - (toAlgHom F E K₁).range →ₐ[F] (toAlgHom F E K₂).range where - toFun x := - ⟨ϕ x, by - suffices (toAlgHom F E K₁).range.map ϕ ≤ _ by exact this ⟨x, Subtype.mem x, rfl⟩ - rintro x ⟨y, ⟨z, hy⟩, hx⟩ - rw [← hx, ← hy] - apply minpoly.mem_range_of_degree_eq_one E - refine - Or.resolve_left (h.splits z).def (minpoly.ne_zero (h.isIntegral z)) (minpoly.irreducible ?_) - (minpoly.dvd E _ (by simp [aeval_algHom_apply])) - simp only [AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom] - suffices IsIntegral F _ by exact this.tower_top - exact ((h.isIntegral z).map <| toAlgHom F E K₁).map ϕ⟩ - map_zero' := Subtype.ext (map_zero _) - map_one' := Subtype.ext (map_one _) - map_add' x y := Subtype.ext <| by simp - map_mul' x y := Subtype.ext <| by simp - commutes' x := Subtype.ext (ϕ.commutes x) - -/-- Restrict algebra homomorphism to normal subfield. -/ -@[stacks 0BME "Part 1"] -def AlgHom.restrictNormal [Normal F E] : E →ₐ[F] E := - ((AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₂)).symm.toAlgHom.comp - (ϕ.restrictNormalAux E)).comp - (AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₁)).toAlgHom - -/-- Restrict algebra homomorphism to normal subfield (`AlgEquiv` version) -/ -def AlgHom.restrictNormal' [Normal F E] : E ≃ₐ[F] E := - AlgEquiv.ofBijective (AlgHom.restrictNormal ϕ E) (AlgHom.normal_bijective F E E _) - -@[simp] -theorem AlgHom.restrictNormal_commutes [Normal F E] (x : E) : - algebraMap E K₂ (ϕ.restrictNormal E x) = ϕ (algebraMap E K₁ x) := - Subtype.ext_iff.mp - (AlgEquiv.apply_symm_apply (AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₂)) - (ϕ.restrictNormalAux E ⟨IsScalarTower.toAlgHom F E K₁ x, x, rfl⟩)) - -theorem AlgHom.restrictNormal_comp [Normal F E] : - (ψ.restrictNormal E).comp (ϕ.restrictNormal E) = (ψ.comp ϕ).restrictNormal E := - AlgHom.ext fun _ => - (algebraMap E K₃).injective (by simp only [AlgHom.comp_apply, AlgHom.restrictNormal_commutes]) - theorem AlgHom.fieldRange_of_normal {E : IntermediateField F K} [Normal F E] (f : E →ₐ[F] K) : f.fieldRange = E := by let g := f.restrictNormal' E @@ -271,47 +164,6 @@ theorem AlgHom.fieldRange_of_normal {E : IntermediateField F K} [Normal F E] ← AlgHom.map_fieldRange, AlgEquiv.fieldRange_eq_top g, ← AlgHom.fieldRange_eq_map, IntermediateField.fieldRange_val] -/-- Restrict algebra isomorphism to a normal subfield -/ -def AlgEquiv.restrictNormal [Normal F E] : E ≃ₐ[F] E := - AlgHom.restrictNormal' χ.toAlgHom E - -@[simp] -theorem AlgEquiv.restrictNormal_commutes [Normal F E] (x : E) : - algebraMap E K₂ (χ.restrictNormal E x) = χ (algebraMap E K₁ x) := - χ.toAlgHom.restrictNormal_commutes E x - -theorem AlgEquiv.restrictNormal_trans [Normal F E] : - (χ.trans ω).restrictNormal E = (χ.restrictNormal E).trans (ω.restrictNormal E) := - AlgEquiv.ext fun _ => - (algebraMap E K₃).injective - (by simp only [AlgEquiv.trans_apply, AlgEquiv.restrictNormal_commutes]) - -/-- Restriction to a normal subfield as a group homomorphism -/ -def AlgEquiv.restrictNormalHom [Normal F E] : (K₁ ≃ₐ[F] K₁) →* E ≃ₐ[F] E := - MonoidHom.mk' (fun χ => χ.restrictNormal E) fun ω χ => χ.restrictNormal_trans ω E - -lemma AlgEquiv.restrictNormalHom_apply (L : IntermediateField F K₁) [Normal F L] - (σ : (K₁ ≃ₐ[F] K₁)) (x : L) : restrictNormalHom L σ x = σ x := - AlgEquiv.restrictNormal_commutes σ L x - -variable (F K₁) - -/-- If `K₁/E/F` is a tower of fields with `E/F` normal then `AlgHom.restrictNormal'` is an - equivalence. -/ -@[simps, stacks 0BR4] -def Normal.algHomEquivAut [Normal F E] : (E →ₐ[F] K₁) ≃ E ≃ₐ[F] E where - toFun σ := AlgHom.restrictNormal' σ E - invFun σ := (IsScalarTower.toAlgHom F E K₁).comp σ.toAlgHom - left_inv σ := by - ext - simp [AlgHom.restrictNormal'] - right_inv σ := by - ext - simp only [AlgHom.restrictNormal', AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_ofBijective] - apply NoZeroSMulDivisors.algebraMap_injective E K₁ - rw [AlgHom.restrictNormal_commutes] - simp - end Restrict section lift @@ -373,49 +225,6 @@ theorem AlgEquiv.restrictNormalHom_surjective [Normal F K₁] [Normal F E] : Function.Surjective (AlgEquiv.restrictNormalHom K₁ : (E ≃ₐ[F] E) → K₁ ≃ₐ[F] K₁) := fun χ => ⟨χ.liftNormal E, χ.restrict_liftNormal E⟩ -/-- The group homomorphism given by restricting an algebra isomorphism to itself -is the identity map. -/ -@[simp] -theorem AlgEquiv.restrictNormalHom_id (F K : Type*) - [Field F] [Field K] [Algebra F K] [Normal F K] : - AlgEquiv.restrictNormalHom K = MonoidHom.id (K ≃ₐ[F] K) := by - ext f x - dsimp only [restrictNormalHom, MonoidHom.mk'_apply, MonoidHom.id_apply] - apply (algebraMap K K).injective - rw [AlgEquiv.restrictNormal_commutes] - simp only [Algebra.id.map_eq_id, RingHom.id_apply] - -namespace IsScalarTower - -/-- In a scalar tower `K₃/K₂/K₁/F` with `K₁` and `K₂` are normal over `F`, the group homomorphism -given by the restriction of algebra isomorphisms of `K₃` to `K₁` is equal to the composition of -the group homomorphism given by the restricting an algebra isomorphism of `K₃` to `K₂` and -the group homomorphism given by the restricting an algebra isomorphism of `K₂` to `K₁` -/ -theorem AlgEquiv.restrictNormalHom_comp (F K₁ K₂ K₃ : Type*) - [Field F] [Field K₁] [Field K₂] [Field K₃] - [Algebra F K₁] [Algebra F K₂] [Algebra F K₃] [Algebra K₁ K₂] [Algebra K₁ K₃] [Algebra K₂ K₃] - [IsScalarTower F K₁ K₃] [IsScalarTower F K₁ K₂] [IsScalarTower F K₂ K₃] [IsScalarTower K₁ K₂ K₃] - [Normal F K₁] [Normal F K₂] : - AlgEquiv.restrictNormalHom K₁ = - (AlgEquiv.restrictNormalHom K₁).comp - (AlgEquiv.restrictNormalHom (F := F) (K₁ := K₃) K₂) := by - ext f x - apply (algebraMap K₁ K₃).injective - rw [IsScalarTower.algebraMap_eq K₁ K₂ K₃] - simp only [AlgEquiv.restrictNormalHom, MonoidHom.mk'_apply, RingHom.coe_comp, Function.comp_apply, - ← algebraMap_apply, AlgEquiv.restrictNormal_commutes, MonoidHom.coe_comp] - -theorem AlgEquiv.restrictNormalHom_comp_apply (K₁ K₂ : Type*) {F K₃ : Type*} - [Field F] [Field K₁] [Field K₂] [Field K₃] - [Algebra F K₁] [Algebra F K₂] [Algebra F K₃] [Algebra K₁ K₂] [Algebra K₁ K₃] [Algebra K₂ K₃] - [IsScalarTower F K₁ K₃] [IsScalarTower F K₁ K₂] [IsScalarTower F K₂ K₃] [IsScalarTower K₁ K₂ K₃] - [Normal F K₁] [Normal F K₂] (f : K₃ ≃ₐ[F] K₃) : - AlgEquiv.restrictNormalHom K₁ f = - (AlgEquiv.restrictNormalHom K₁) (AlgEquiv.restrictNormalHom K₂ f) := by - rw [IsScalarTower.AlgEquiv.restrictNormalHom_comp F K₁ K₂ K₃, MonoidHom.comp_apply] - -end IsScalarTower - open IntermediateField in theorem Normal.minpoly_eq_iff_mem_orbit [h : Normal F E] {x y : E} : minpoly F x = minpoly F y ↔ x ∈ MulAction.orbit (E ≃ₐ[F] E) y := by diff --git a/Mathlib/FieldTheory/NormalClosure.lean b/Mathlib/FieldTheory/Normal/Closure.lean similarity index 99% rename from Mathlib/FieldTheory/NormalClosure.lean rename to Mathlib/FieldTheory/Normal/Closure.lean index f71e7bfc0ab78..a2a41471b6957 100644 --- a/Mathlib/FieldTheory/NormalClosure.lean +++ b/Mathlib/FieldTheory/Normal/Closure.lean @@ -5,7 +5,7 @@ Authors: Thomas Browning -/ import Mathlib.RingTheory.SimpleRing.Basic -import Mathlib.FieldTheory.Normal +import Mathlib.FieldTheory.Normal.Basic import Mathlib.Order.Closure import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix /-! diff --git a/Mathlib/FieldTheory/Normal/Defs.lean b/Mathlib/FieldTheory/Normal/Defs.lean new file mode 100644 index 0000000000000..a8977634afdf3 --- /dev/null +++ b/Mathlib/FieldTheory/Normal/Defs.lean @@ -0,0 +1,242 @@ +/- +Copyright (c) 2020 Kenny Lau. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kenny Lau, Thomas Browning, Patrick Lutz +-/ +import Mathlib.Algebra.Polynomial.Splits +import Mathlib.FieldTheory.IntermediateField.Basic +import Mathlib.FieldTheory.Minpoly.Field + +/-! +# Normal field extensions + +In this file we define normal field extensions. + +## Main Definitions + +- `Normal F K` where `K` is a field extension of `F`. +-/ + + +noncomputable section + +open Polynomial IsScalarTower + +variable (F K : Type*) [Field F] [Field K] [Algebra F K] + +/-- Typeclass for normal field extension: `K` is a normal extension of `F` iff the minimal +polynomial of every element `x` in `K` splits in `K`, i.e. every conjugate of `x` is in `K`. -/ +@[stacks 09HM] +class Normal extends Algebra.IsAlgebraic F K : Prop where + splits' (x : K) : Splits (algebraMap F K) (minpoly F x) + +variable {F K} + +theorem Normal.isIntegral (_ : Normal F K) (x : K) : IsIntegral F x := + Algebra.IsIntegral.isIntegral x + +theorem Normal.splits (_ : Normal F K) (x : K) : Splits (algebraMap F K) (minpoly F x) := + Normal.splits' x + +theorem normal_iff : Normal F K ↔ ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) := + ⟨fun h x => ⟨h.isIntegral x, h.splits x⟩, fun h => + { isAlgebraic := fun x => (h x).1.isAlgebraic + splits' := fun x => (h x).2 }⟩ + +theorem Normal.out : Normal F K → ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) := + normal_iff.1 + +variable (F K) + +instance normal_self : Normal F F where + isAlgebraic := fun _ => isIntegral_algebraMap.isAlgebraic + splits' := fun x => (minpoly.eq_X_sub_C' x).symm ▸ splits_X_sub_C _ + +section NormalTower + +variable (E : Type*) [Field E] [Algebra F E] [Algebra K E] [IsScalarTower F K E] + +@[stacks 09HN] +theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E := + normal_iff.2 fun x => by + cases' h.out x with hx hhx + rw [algebraMap_eq F K E] at hhx + exact + ⟨hx.tower_top, + Polynomial.splits_of_splits_of_dvd (algebraMap K E) + (Polynomial.map_ne_zero (minpoly.ne_zero hx)) + ((Polynomial.splits_map_iff (algebraMap F K) (algebraMap K E)).mpr hhx) + (minpoly.dvd_map_of_isScalarTower F K x)⟩ + +theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function.Bijective ϕ := + h.toIsAlgebraic.bijective_of_isScalarTower' ϕ + +variable {E F} +variable {E' : Type*} [Field E'] [Algebra F E'] + +theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' := by + rw [normal_iff] at h ⊢ + intro x; specialize h (f.symm x) + rw [← f.apply_symm_apply x, minpoly.algEquiv_eq, ← f.toAlgHom.comp_algebraMap] + exact ⟨h.1.map f, splits_comp_of_splits _ _ h.2⟩ + +theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F E' := + ⟨fun _ ↦ Normal.of_algEquiv f, fun _ ↦ Normal.of_algEquiv f.symm⟩ + +end NormalTower + +namespace IntermediateField + +variable {F K} +variable {L : Type*} [Field L] [Algebra F L] [Algebra K L] [IsScalarTower F K L] + +@[simp] +theorem restrictScalars_normal {E : IntermediateField K L} : + Normal F (E.restrictScalars F) ↔ Normal F E := + Iff.rfl + +end IntermediateField + +variable {F} {K} +variable {K₁ K₂ K₃ : Type*} [Field K₁] [Field K₂] [Field K₃] [Algebra F K₁] + [Algebra F K₂] [Algebra F K₃] (ϕ : K₁ →ₐ[F] K₂) (χ : K₁ ≃ₐ[F] K₂) (ψ : K₂ →ₐ[F] K₃) + (ω : K₂ ≃ₐ[F] K₃) + +section Restrict + +variable (E : Type*) [Field E] [Algebra F E] [Algebra E K₁] [Algebra E K₂] [Algebra E K₃] + [IsScalarTower F E K₁] [IsScalarTower F E K₂] [IsScalarTower F E K₃] + +/-- Restrict algebra homomorphism to image of normal subfield -/ +def AlgHom.restrictNormalAux [h : Normal F E] : + (toAlgHom F E K₁).range →ₐ[F] (toAlgHom F E K₂).range where + toFun x := + ⟨ϕ x, by + suffices (toAlgHom F E K₁).range.map ϕ ≤ _ by exact this ⟨x, Subtype.mem x, rfl⟩ + rintro x ⟨y, ⟨z, hy⟩, hx⟩ + rw [← hx, ← hy] + apply minpoly.mem_range_of_degree_eq_one E + refine + Or.resolve_left (h.splits z).def (minpoly.ne_zero (h.isIntegral z)) (minpoly.irreducible ?_) + (minpoly.dvd E _ (by simp [aeval_algHom_apply])) + simp only [AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom] + suffices IsIntegral F _ by exact this.tower_top + exact ((h.isIntegral z).map <| toAlgHom F E K₁).map ϕ⟩ + map_zero' := Subtype.ext (map_zero _) + map_one' := Subtype.ext (map_one _) + map_add' x y := Subtype.ext <| by simp + map_mul' x y := Subtype.ext <| by simp + commutes' x := Subtype.ext (ϕ.commutes x) + +/-- Restrict algebra homomorphism to normal subfield. -/ +@[stacks 0BME "Part 1"] +def AlgHom.restrictNormal [Normal F E] : E →ₐ[F] E := + ((AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₂)).symm.toAlgHom.comp + (ϕ.restrictNormalAux E)).comp + (AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₁)).toAlgHom + +/-- Restrict algebra homomorphism to normal subfield (`AlgEquiv` version) -/ +def AlgHom.restrictNormal' [Normal F E] : E ≃ₐ[F] E := + AlgEquiv.ofBijective (AlgHom.restrictNormal ϕ E) (AlgHom.normal_bijective F E E _) + +@[simp] +theorem AlgHom.restrictNormal_commutes [Normal F E] (x : E) : + algebraMap E K₂ (ϕ.restrictNormal E x) = ϕ (algebraMap E K₁ x) := + Subtype.ext_iff.mp + (AlgEquiv.apply_symm_apply (AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₂)) + (ϕ.restrictNormalAux E ⟨IsScalarTower.toAlgHom F E K₁ x, x, rfl⟩)) + +theorem AlgHom.restrictNormal_comp [Normal F E] : + (ψ.restrictNormal E).comp (ϕ.restrictNormal E) = (ψ.comp ϕ).restrictNormal E := + AlgHom.ext fun _ => + (algebraMap E K₃).injective (by simp only [AlgHom.comp_apply, AlgHom.restrictNormal_commutes]) + +/-- Restrict algebra isomorphism to a normal subfield -/ +def AlgEquiv.restrictNormal [Normal F E] : E ≃ₐ[F] E := + AlgHom.restrictNormal' χ.toAlgHom E + +@[simp] +theorem AlgEquiv.restrictNormal_commutes [Normal F E] (x : E) : + algebraMap E K₂ (χ.restrictNormal E x) = χ (algebraMap E K₁ x) := + χ.toAlgHom.restrictNormal_commutes E x + +theorem AlgEquiv.restrictNormal_trans [Normal F E] : + (χ.trans ω).restrictNormal E = (χ.restrictNormal E).trans (ω.restrictNormal E) := + AlgEquiv.ext fun _ => + (algebraMap E K₃).injective + (by simp only [AlgEquiv.trans_apply, AlgEquiv.restrictNormal_commutes]) + +/-- Restriction to a normal subfield as a group homomorphism -/ +def AlgEquiv.restrictNormalHom [Normal F E] : (K₁ ≃ₐ[F] K₁) →* E ≃ₐ[F] E := + MonoidHom.mk' (fun χ => χ.restrictNormal E) fun ω χ => χ.restrictNormal_trans ω E + +lemma AlgEquiv.restrictNormalHom_apply (L : IntermediateField F K₁) [Normal F L] + (σ : (K₁ ≃ₐ[F] K₁)) (x : L) : restrictNormalHom L σ x = σ x := + AlgEquiv.restrictNormal_commutes σ L x + +variable (F K₁) + +/-- If `K₁/E/F` is a tower of fields with `E/F` normal then `AlgHom.restrictNormal'` is an + equivalence. -/ +@[simps, stacks 0BR4] +def Normal.algHomEquivAut [Normal F E] : (E →ₐ[F] K₁) ≃ E ≃ₐ[F] E where + toFun σ := AlgHom.restrictNormal' σ E + invFun σ := (IsScalarTower.toAlgHom F E K₁).comp σ.toAlgHom + left_inv σ := by + ext + simp [AlgHom.restrictNormal'] + right_inv σ := by + ext + simp only [AlgHom.restrictNormal', AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_ofBijective] + apply NoZeroSMulDivisors.algebraMap_injective E K₁ + rw [AlgHom.restrictNormal_commutes] + simp + +end Restrict + +section lift + +/-- The group homomorphism given by restricting an algebra isomorphism to itself +is the identity map. -/ +@[simp] +theorem AlgEquiv.restrictNormalHom_id (F K : Type*) + [Field F] [Field K] [Algebra F K] [Normal F K] : + AlgEquiv.restrictNormalHom K = MonoidHom.id (K ≃ₐ[F] K) := by + ext f x + dsimp only [restrictNormalHom, MonoidHom.mk'_apply, MonoidHom.id_apply] + apply (algebraMap K K).injective + rw [AlgEquiv.restrictNormal_commutes] + simp only [Algebra.id.map_eq_id, RingHom.id_apply] + +namespace IsScalarTower + +/-- In a scalar tower `K₃/K₂/K₁/F` with `K₁` and `K₂` are normal over `F`, the group homomorphism +given by the restriction of algebra isomorphisms of `K₃` to `K₁` is equal to the composition of +the group homomorphism given by the restricting an algebra isomorphism of `K₃` to `K₂` and +the group homomorphism given by the restricting an algebra isomorphism of `K₂` to `K₁` -/ +theorem AlgEquiv.restrictNormalHom_comp (F K₁ K₂ K₃ : Type*) + [Field F] [Field K₁] [Field K₂] [Field K₃] + [Algebra F K₁] [Algebra F K₂] [Algebra F K₃] [Algebra K₁ K₂] [Algebra K₁ K₃] [Algebra K₂ K₃] + [IsScalarTower F K₁ K₃] [IsScalarTower F K₁ K₂] [IsScalarTower F K₂ K₃] [IsScalarTower K₁ K₂ K₃] + [Normal F K₁] [Normal F K₂] : + AlgEquiv.restrictNormalHom K₁ = + (AlgEquiv.restrictNormalHom K₁).comp + (AlgEquiv.restrictNormalHom (F := F) (K₁ := K₃) K₂) := by + ext f x + apply (algebraMap K₁ K₃).injective + rw [IsScalarTower.algebraMap_eq K₁ K₂ K₃] + simp only [AlgEquiv.restrictNormalHom, MonoidHom.mk'_apply, RingHom.coe_comp, Function.comp_apply, + ← algebraMap_apply, AlgEquiv.restrictNormal_commutes, MonoidHom.coe_comp] + +theorem AlgEquiv.restrictNormalHom_comp_apply (K₁ K₂ : Type*) {F K₃ : Type*} + [Field F] [Field K₁] [Field K₂] [Field K₃] + [Algebra F K₁] [Algebra F K₂] [Algebra F K₃] [Algebra K₁ K₂] [Algebra K₁ K₃] [Algebra K₂ K₃] + [IsScalarTower F K₁ K₃] [IsScalarTower F K₁ K₂] [IsScalarTower F K₂ K₃] [IsScalarTower K₁ K₂ K₃] + [Normal F K₁] [Normal F K₂] (f : K₃ ≃ₐ[F] K₃) : + AlgEquiv.restrictNormalHom K₁ f = + (AlgEquiv.restrictNormalHom K₁) (AlgEquiv.restrictNormalHom K₂ f) := by + rw [IsScalarTower.AlgEquiv.restrictNormalHom_comp F K₁ K₂ K₃, MonoidHom.comp_apply] + +end IsScalarTower + +end lift diff --git a/Mathlib/FieldTheory/PrimitiveElement.lean b/Mathlib/FieldTheory/PrimitiveElement.lean index b8174c3c41d64..239f457cd3474 100644 --- a/Mathlib/FieldTheory/PrimitiveElement.lean +++ b/Mathlib/FieldTheory/PrimitiveElement.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Patrick Lutz -/ import Mathlib.FieldTheory.IsAlgClosed.Basic +import Mathlib.FieldTheory.SplittingField.Construction import Mathlib.RingTheory.IntegralDomain import Mathlib.RingTheory.Polynomial.UniqueFactorization diff --git a/Mathlib/FieldTheory/SeparableDegree.lean b/Mathlib/FieldTheory/SeparableDegree.lean index 172cb679bd8eb..2762762a786c4 100644 --- a/Mathlib/FieldTheory/SeparableDegree.lean +++ b/Mathlib/FieldTheory/SeparableDegree.lean @@ -6,7 +6,7 @@ Authors: Jz Pan import Mathlib.FieldTheory.SplittingField.Construction import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure import Mathlib.FieldTheory.Separable -import Mathlib.FieldTheory.NormalClosure +import Mathlib.FieldTheory.Normal.Closure import Mathlib.RingTheory.AlgebraicIndependent.Adjoin import Mathlib.RingTheory.AlgebraicIndependent.TranscendenceBasis import Mathlib.RingTheory.Polynomial.SeparableDegree From 3330420220e557bb94fe1aa4abaac8d1f7375a2f Mon Sep 17 00:00:00 2001 From: Hannah Fechtner Date: Thu, 23 Jan 2025 18:56:36 +0000 Subject: [PATCH 461/681] feat(Algebra/FreeMonoid): free monoids over isomorphic types are isomorphic (#18563) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free monoids over isomorphic types are isomorphic. Also, converting a relation on free monoid α to free monoids over β, when α and β are isomorphic Co-authored-by: Hannah Fechtner <123216642+hannahfechtner@users.noreply.github.com> --- Mathlib/Algebra/FreeMonoid/Basic.lean | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Mathlib/Algebra/FreeMonoid/Basic.lean b/Mathlib/Algebra/FreeMonoid/Basic.lean index bb1c54dceedc7..7340041857cfc 100644 --- a/Mathlib/Algebra/FreeMonoid/Basic.lean +++ b/Mathlib/Algebra/FreeMonoid/Basic.lean @@ -6,6 +6,7 @@ Authors: Simon Hudon, Yury Kudryashov import Mathlib.Algebra.Group.Action.Defs import Mathlib.Algebra.Group.Units.Defs import Mathlib.Algebra.BigOperators.Group.List.Basic +import Mathlib.Algebra.Group.Equiv.Defs /-! # Free monoid over a given alphabet @@ -358,6 +359,14 @@ theorem map_comp (g : β → γ) (f : α → β) : map (g ∘ f) = (map g).comp @[to_additive (attr := simp)] theorem map_id : map (@id α) = MonoidHom.id (FreeMonoid α) := hom_eq fun _ ↦ rfl +@[to_additive (attr := simp)] +theorem map_symm_apply_map_eq {x : FreeMonoid α} (e : α ≃ β) : + (map ⇑e.symm) ((map ⇑e) x) = x := by simp [map_map] + +@[to_additive (attr := simp)] +theorem map_apply_map_symm_eq {x : FreeMonoid β} (e : α ≃ β) : + (map ⇑e) ((map ⇑e.symm) x) = x := by simp [map_map] + /-- The only invertible element of the free monoid is 1; this instance enables `units_eq_one`. -/ @[to_additive] instance uniqueUnits : Unique (FreeMonoid α)ˣ where @@ -415,4 +424,27 @@ theorem length_reverse {a : FreeMonoid α} : a.reverse.length = a.length := end Reverse +section IsomorphicTypes + +variable {α β : Type*} + +/-- free monoids over isomorphic types are isomorphic -/ +@[to_additive "if two types are isomorphic, the additive free monoids over those types are +isomorphic"] +def freeMonoidCongr (e : α ≃ β) : FreeMonoid α ≃* FreeMonoid β where + toFun := FreeMonoid.map ⇑e + invFun := FreeMonoid.map ⇑e.symm + left_inv := fun _ => map_symm_apply_map_eq e + right_inv := fun _ => map_apply_map_symm_eq e + map_mul' := (by simp [map_mul]) + +@[to_additive (attr := simp)] +theorem freeMonoidCongr_of (e : α ≃ β) (a : α) : freeMonoidCongr e (of a) = of (e a) := rfl + +@[to_additive (attr := simp)] +theorem freeMonoidCongr_symm_of (e : α ≃ β) (b : β) : + freeMonoidCongr e.symm (of b) = of (e.symm b) := rfl + +end IsomorphicTypes + end FreeMonoid From f4e2c6d6e22cf7f0851bea92bc5435cd9c3d1e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 23 Jan 2025 19:32:24 +0000 Subject: [PATCH 462/681] feat(CategoryTheory/Abelian): projective dimension (#19604) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We introduce a typeclass `HasProjectiveDimensionLT X n` expressing that `Ext X Y i` all vanish when `n ≤ i`. We study how it behaves with respect to short exact sequences. When #19591 will be merged, it will possible to show `HasProjectiveDimensionLT X 1 ↔ Projective X`. --- Mathlib.lean | 1 + .../Homology/DerivedCategory/Ext/Basic.lean | 4 + .../Abelian/ProjectiveDimension.lean | 189 ++++++++++++++++++ Mathlib/CategoryTheory/Retract.lean | 23 +++ 4 files changed, 217 insertions(+) create mode 100644 Mathlib/CategoryTheory/Abelian/ProjectiveDimension.lean diff --git a/Mathlib.lean b/Mathlib.lean index 5a9abcd4c4466..4e0f1d34846c4 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1643,6 +1643,7 @@ import Mathlib.CategoryTheory.Abelian.LeftDerived import Mathlib.CategoryTheory.Abelian.NonPreadditive import Mathlib.CategoryTheory.Abelian.Opposite import Mathlib.CategoryTheory.Abelian.Projective +import Mathlib.CategoryTheory.Abelian.ProjectiveDimension import Mathlib.CategoryTheory.Abelian.ProjectiveResolution import Mathlib.CategoryTheory.Abelian.Pseudoelements import Mathlib.CategoryTheory.Abelian.Refinements diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean index 805216557b246..908ef5c957030 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean @@ -77,6 +77,10 @@ lemma hasExt_of_hasDerivedCategory [HasDerivedCategory.{w} C] : HasExt.{w} C := rw [hasExt_iff.{w}] infer_instance +lemma HasExt.standard : HasExt.{max u v} C := by + letI := HasDerivedCategory.standard + exact hasExt_of_hasDerivedCategory _ + variable {C} variable [HasExt.{w} C] diff --git a/Mathlib/CategoryTheory/Abelian/ProjectiveDimension.lean b/Mathlib/CategoryTheory/Abelian/ProjectiveDimension.lean new file mode 100644 index 0000000000000..d9a81801da948 --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/ProjectiveDimension.lean @@ -0,0 +1,189 @@ +/- +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.Homology.DerivedCategory.Ext.ExactSequences + +/-! +# Projective dimension + +In an abelian category `C`, we shall say that `X : C` has projective dimension `< n` +if all `Ext X Y i` vanish when `n ≤ i`. This defines a type class +`HasProjectiveDimensionLT X n`. We also define a type class +`HasProjectiveDimensionLE X n` as an abbreviation for +`HasProjectiveDimensionLT X (n + 1)`. +(Note that the fact that `X` is a zero object is equivalent to the condition +`HasProjectiveDimensionLT X 0`, but this cannot be expressed in terms of +`HasProjectiveDimensionLE`.) + +-/ + +universe w v u + +namespace CategoryTheory + +open Abelian Limits ZeroObject + +variable {C : Type u} [Category.{v} C] [Abelian C] + +/-- An object `X` in an abelian category has projective dimension `< n` if +all `Ext X Y i` vanish when `n ≤ i`. See also `HasProjectiveDimensionLE`. +(Do not use the `subsingleton'` field directly. Use the constructor +`HasProjectiveDimensionLT.mk`, and the lemmas `hasProjectiveDimensionLT_iff` and +`Ext.eq_zero_of_hasProjectiveDimensionLT`.) -/ +class HasProjectiveDimensionLT (X : C) (n : ℕ) : Prop where mk' :: + subsingleton' (i : ℕ) (hi : n ≤ i) ⦃Y : C⦄ : + letI := HasExt.standard C + Subsingleton (Ext.{max u v} X Y i) + +/-- An object `X` in an abelian category has projective dimension `≤ n` if +all `Ext X Y i` vanish when `n + 1 ≤ i` -/ +abbrev HasProjectiveDimensionLE (X : C) (n : ℕ) : Prop := + HasProjectiveDimensionLT X (n + 1) + +namespace HasProjectiveDimensionLT + +variable [HasExt.{w} C] (X : C) (n : ℕ) + +lemma subsingleton [hX : HasProjectiveDimensionLT X n] (i : ℕ) (hi : n ≤ i) (Y : C) : + Subsingleton (Ext.{w} X Y i) := by + letI := HasExt.standard C + have := hX.subsingleton' i hi + exact Ext.chgUniv.{w, max u v}.symm.subsingleton + +variable {X n} in +lemma mk (hX : ∀ (i : ℕ) (_ : n ≤ i) ⦃Y : C⦄, ∀ (e : Ext X Y i), e = 0) : + HasProjectiveDimensionLT X n where + subsingleton' i hi Y := by + have : Subsingleton (Ext X Y i) := ⟨fun e₁ e₂ ↦ by simp only [hX i hi]⟩ + letI := HasExt.standard C + exact Ext.chgUniv.{max u v, w}.symm.subsingleton + +end HasProjectiveDimensionLT + +lemma Abelian.Ext.eq_zero_of_hasProjectiveDimensionLT [HasExt.{w} C] + {X Y : C} {i : ℕ} (e : Ext X Y i) (n : ℕ) [HasProjectiveDimensionLT X n] + (hi : n ≤ i) : e = 0 := + (HasProjectiveDimensionLT.subsingleton X n i hi Y).elim _ _ + +section + +variable (X : C) (n : ℕ) + +lemma hasProjectiveDimensionLT_iff [HasExt.{w} C] : + HasProjectiveDimensionLT X n ↔ + ∀ (i : ℕ) (_ : n ≤ i) ⦃Y : C⦄, ∀ (e : Ext X Y i), e = 0 := + ⟨fun _ _ hi _ e ↦ e.eq_zero_of_hasProjectiveDimensionLT n hi, + HasProjectiveDimensionLT.mk⟩ + +variable {X} in +lemma Limits.IsZero.hasProjectiveDimensionLT_zero (hX : IsZero X) : + HasProjectiveDimensionLT X 0 := by + letI := HasExt.standard C + rw [hasProjectiveDimensionLT_iff] + intro i hi Y e + rw [← e.mk₀_id_comp, hX.eq_of_src (𝟙 X) 0, Ext.mk₀_zero, Ext.zero_comp] + +instance : HasProjectiveDimensionLT (0 : C) 0 := + (isZero_zero C).hasProjectiveDimensionLT_zero + +lemma hasProjectiveDimensionLT_of_ge (m : ℕ) (h : n ≤ m) + [HasProjectiveDimensionLT X n] : + HasProjectiveDimensionLT X m := by + letI := HasExt.standard C + rw [hasProjectiveDimensionLT_iff] + intro i hi Y e + exact e.eq_zero_of_hasProjectiveDimensionLT n (by omega) + +instance [HasProjectiveDimensionLT X n] (k : ℕ) : + HasProjectiveDimensionLT X (n + k) := + hasProjectiveDimensionLT_of_ge X n (n + k) (by omega) + +instance [HasProjectiveDimensionLT X n] (k : ℕ) : + HasProjectiveDimensionLT X (k + n) := + hasProjectiveDimensionLT_of_ge X n (k + n) (by omega) + +instance [HasProjectiveDimensionLT X n] : + HasProjectiveDimensionLT X n.succ := + inferInstanceAs (HasProjectiveDimensionLT X (n + 1)) + +end + +lemma Retract.hasProjectiveDimensionLT {X Y : C} (h : Retract X Y) (n : ℕ) + [HasProjectiveDimensionLT Y n] : + HasProjectiveDimensionLT X n := by + letI := HasExt.standard C + rw [hasProjectiveDimensionLT_iff] + intro i hi T x + rw [← x.mk₀_id_comp, ← h.retract, ← Ext.mk₀_comp_mk₀, + Ext.comp_assoc_of_second_deg_zero, + ((Ext.mk₀ h.r).comp x (zero_add i)).eq_zero_of_hasProjectiveDimensionLT n hi, + Ext.comp_zero] + +lemma hasProjectiveDimensionLT_of_iso {X X' : C} (e : X ≅ X') (n : ℕ) + [HasProjectiveDimensionLT X n] : + HasProjectiveDimensionLT X' n := + e.symm.retract.hasProjectiveDimensionLT n + +namespace ShortComplex + +namespace ShortExact + +variable {S : ShortComplex C} (hS : S.ShortExact) (n : ℕ) +include hS + +-- In the following lemmas, the parameters `HasProjectiveDimensionLT` are +-- explicit as it is unlikely we may infer them, unless the short complex `S` +-- was declared reducible + +lemma hasProjectiveDimensionLT_X₂ (h₁ : HasProjectiveDimensionLT S.X₁ n) + (h₃ : HasProjectiveDimensionLT S.X₃ n) : + HasProjectiveDimensionLT S.X₂ n := by + letI := HasExt.standard C + rw [hasProjectiveDimensionLT_iff] + intro i hi Y x₂ + obtain ⟨x₃, rfl⟩ := Ext.contravariant_sequence_exact₂ hS _ x₂ + (Ext.eq_zero_of_hasProjectiveDimensionLT _ n hi) + rw [x₃.eq_zero_of_hasProjectiveDimensionLT n hi, Ext.comp_zero] + +lemma hasProjectiveDimensionLT_X₃ (h₁ : HasProjectiveDimensionLT S.X₁ n) + (h₂ : HasProjectiveDimensionLT S.X₂ (n + 1)) : + HasProjectiveDimensionLT S.X₃ (n + 1) := by + letI := HasExt.standard C + rw [hasProjectiveDimensionLT_iff] + rintro (_ | i) hi Y x₃ + · simp at hi + · obtain ⟨x₁, rfl⟩ := Ext.contravariant_sequence_exact₃ hS _ x₃ + (Ext.eq_zero_of_hasProjectiveDimensionLT _ (n + 1) hi) (add_comm _ _) + rw [x₁.eq_zero_of_hasProjectiveDimensionLT n (by omega), Ext.comp_zero] + +lemma hasProjectiveDimensionLT_X₁ (h₂ : HasProjectiveDimensionLT S.X₂ n) + (h₃ : HasProjectiveDimensionLT S.X₃ (n + 1)) : + HasProjectiveDimensionLT S.X₁ n := by + letI := HasExt.standard C + rw [hasProjectiveDimensionLT_iff] + intro i hi Y x₁ + obtain ⟨x₂, rfl⟩ := Ext.contravariant_sequence_exact₁ hS _ x₁ (add_comm _ _) + (Ext.eq_zero_of_hasProjectiveDimensionLT _ (n + 1) (by omega)) + rw [x₂.eq_zero_of_hasProjectiveDimensionLT n (by omega), Ext.comp_zero] + +-- When we know `HasProjectiveDimensionLT S.X₂ 1` is equivalent to `Projective S.X₂`, +-- the assumption `h₂` can be changed to `h₂ : Projective S.X₂`. +lemma hasProjectiveDimensionLT_X₃_iff (n : ℕ) (h₂ : HasProjectiveDimensionLT S.X₂ 1) : + HasProjectiveDimensionLT S.X₃ (n + 2) ↔ HasProjectiveDimensionLT S.X₁ (n + 1) := + ⟨fun _ ↦ hS.hasProjectiveDimensionLT_X₁ (n + 1) inferInstance inferInstance, + fun _ ↦ hS.hasProjectiveDimensionLT_X₃ (n + 1) inferInstance inferInstance⟩ + +end ShortExact + +end ShortComplex + +instance (X Y : C) (n : ℕ) [HasProjectiveDimensionLT X n] + [HasProjectiveDimensionLT Y n] : + HasProjectiveDimensionLT (X ⊞ Y) n := + (ShortComplex.Splitting.ofHasBinaryBiproduct X Y).shortExact.hasProjectiveDimensionLT_X₂ n + (by assumption) (by assumption) + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Retract.lean b/Mathlib/CategoryTheory/Retract.lean index 952554b768d5a..992d4761e7632 100644 --- a/Mathlib/CategoryTheory/Retract.lean +++ b/Mathlib/CategoryTheory/Retract.lean @@ -53,6 +53,19 @@ instance : IsSplitEpi h.r := ⟨⟨h.splitEpi⟩⟩ instance : IsSplitMono h.i := ⟨⟨h.splitMono⟩⟩ +variable (X) in +/-- Any object is a retract of itself. -/ +@[simps] +def refl : Retract X X where + i := 𝟙 X + r := 𝟙 X + +/-- A retract of a retract is a retract. -/ +@[simps] +def trans {Z : C} (h' : Retract Y Z) : Retract X Z where + i := h.i ≫ h'.i + r := h'.r ≫ h.r + end Retract /-- @@ -103,4 +116,14 @@ instance : IsSplitMono h.i.right := ⟨⟨h.right.splitMono⟩⟩ end RetractArrow +namespace Iso + +/-- If `X` is isomorphic to `Y`, then `X` is a retract of `Y`. -/ +@[simps] +def retract {X Y : C} (e : X ≅ Y) : Retract X Y where + i := e.hom + r := e.inv + +end Iso + end CategoryTheory From d82bc8c0b4237c0d50b09426da25f5fe06755f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Thu, 23 Jan 2025 19:32:25 +0000 Subject: [PATCH 463/681] feat(Algebra/Homology): quasi-isomorphisms are stable under retracts and have the 2/3 property (#20221) --- Mathlib.lean | 1 + Mathlib/Algebra/Homology/QuasiIso.lean | 46 ++++++++++++++++++- .../Homology/ShortComplex/Retract.lean | 39 ++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 Mathlib/Algebra/Homology/ShortComplex/Retract.lean diff --git a/Mathlib.lean b/Mathlib.lean index 4e0f1d34846c4..99db52618fc07 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -492,6 +492,7 @@ import Mathlib.Algebra.Homology.ShortComplex.ModuleCat import Mathlib.Algebra.Homology.ShortComplex.Preadditive import Mathlib.Algebra.Homology.ShortComplex.PreservesHomology import Mathlib.Algebra.Homology.ShortComplex.QuasiIso +import Mathlib.Algebra.Homology.ShortComplex.Retract import Mathlib.Algebra.Homology.ShortComplex.RightHomology import Mathlib.Algebra.Homology.ShortComplex.ShortExact import Mathlib.Algebra.Homology.ShortComplex.SnakeLemma diff --git a/Mathlib/Algebra/Homology/QuasiIso.lean b/Mathlib/Algebra/Homology/QuasiIso.lean index 46193c305d8b1..71ef037c0f1b0 100644 --- a/Mathlib/Algebra/Homology/QuasiIso.lean +++ b/Mathlib/Algebra/Homology/QuasiIso.lean @@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison, Joël Riou -/ import Mathlib.Algebra.Homology.Homotopy +import Mathlib.Algebra.Homology.ShortComplex.Retract +import Mathlib.CategoryTheory.MorphismProperty.Composition /-! # Quasi-isomorphisms @@ -51,6 +53,15 @@ lemma quasiIsoAt_iff' (f : K ⟶ L) (i j k : ι) (hi : c.prev j = i) (hk : c.nex exact ShortComplex.quasiIso_iff_of_arrow_mk_iso _ _ (Arrow.isoOfNatIso (natIsoSc' C c i j k hi hk) (Arrow.mk f)) +lemma quasiIsoAt_of_retract {f : K ⟶ L} {f' : K' ⟶ L'} + (h : RetractArrow f f') (i : ι) [K.HasHomology i] [L.HasHomology i] + [K'.HasHomology i] [L'.HasHomology i] [hf' : QuasiIsoAt f' i] : + QuasiIsoAt f i := by + rw [quasiIsoAt_iff] at hf' ⊢ + have : RetractArrow ((shortComplexFunctor C c i).map f) + ((shortComplexFunctor C c i).map f') := h.map (shortComplexFunctor C c i).mapArrow + exact ShortComplex.quasiIso_of_retract this + lemma quasiIsoAt_iff_isIso_homologyMap (f : K ⟶ L) (i : ι) [K.HasHomology i] [L.HasHomology i] : QuasiIsoAt f i ↔ IsIso (homologyMap f i) := by @@ -223,6 +234,12 @@ lemma quasiIso_of_arrow_mk_iso (φ : K ⟶ L) (φ' : K' ⟶ L') (e : Arrow.mk φ [hφ : QuasiIso φ] : QuasiIso φ' := by simpa only [← quasiIso_iff_of_arrow_mk_iso φ φ' e] +lemma quasiIso_of_retractArrow {f : K ⟶ L} {f' : K' ⟶ L'} + (h : RetractArrow f f') [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] + [∀ i, K'.HasHomology i] [∀ i, L'.HasHomology i] [QuasiIso f'] : + QuasiIso f where + quasiIsoAt i := quasiIsoAt_of_retract h i + namespace HomologicalComplex section PreservesHomology @@ -274,10 +291,35 @@ variable (C c) def quasiIso [CategoryWithHomology C] : MorphismProperty (HomologicalComplex C c) := fun _ _ f => QuasiIso f -variable {C c} +variable {C c} [CategoryWithHomology C] @[simp] -lemma mem_quasiIso_iff [CategoryWithHomology C] (f : K ⟶ L) : quasiIso C c f ↔ QuasiIso f := by rfl +lemma mem_quasiIso_iff (f : K ⟶ L) : quasiIso C c f ↔ QuasiIso f := by rfl + +instance : (quasiIso C c).IsMultiplicative where + id_mem _ := by + rw [mem_quasiIso_iff] + infer_instance + comp_mem _ _ hf hg := by + rw [mem_quasiIso_iff] at hf hg ⊢ + infer_instance + +instance : (quasiIso C c).HasTwoOutOfThreeProperty where + of_postcomp f g hg hfg := by + rw [mem_quasiIso_iff] at hg hfg ⊢ + rwa [← quasiIso_iff_comp_right f g] + of_precomp f g hf hfg := by + rw [mem_quasiIso_iff] at hf hfg ⊢ + rwa [← quasiIso_iff_comp_left f g] + +instance : (quasiIso C c).IsStableUnderRetracts where + of_retract h hg := by + rw [mem_quasiIso_iff] at hg ⊢ + exact quasiIso_of_retractArrow h + +instance : (quasiIso C c).RespectsIso := + MorphismProperty.respectsIso_of_isStableUnderComposition + (fun _ _ _ (_ : IsIso _) ↦ by rw [mem_quasiIso_iff]; infer_instance) end HomologicalComplex diff --git a/Mathlib/Algebra/Homology/ShortComplex/Retract.lean b/Mathlib/Algebra/Homology/ShortComplex/Retract.lean new file mode 100644 index 0000000000000..6a83271823fd1 --- /dev/null +++ b/Mathlib/Algebra/Homology/ShortComplex/Retract.lean @@ -0,0 +1,39 @@ +/- +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.Homology.ShortComplex.QuasiIso +import Mathlib.CategoryTheory.MorphismProperty.Retract + +/-! +# Quasi-isomorphisms of short complexes are stable under retracts + +-/ + +namespace CategoryTheory + +open Limits + +namespace ShortComplex + +variable {C : Type*} [Category C] [HasZeroMorphisms C] + {S₁ T₁ S₂ T₂ : ShortComplex C} + [S₁.HasHomology] [T₁.HasHomology] [S₂.HasHomology] [T₂.HasHomology] + {f₁ : S₁ ⟶ T₁} {f₂ : S₂ ⟶ T₂} + +lemma quasiIso_of_retract (h : RetractArrow f₁ f₂) [hf₂ : QuasiIso f₂] : + QuasiIso f₁ := by + rw [quasiIso_iff] at hf₂ ⊢ + have h : RetractArrow (homologyMap f₁) (homologyMap f₂) := + { i := Arrow.homMk (u := homologyMap (show S₁ ⟶ S₂ from h.i.left)) + (v := homologyMap (show T₁ ⟶ T₂ from h.i.right)) (by simp [← homologyMap_comp]) + r := Arrow.homMk (u := homologyMap (show S₂ ⟶ S₁ from h.r.left)) + (v := homologyMap (show T₂ ⟶ T₁ from h.r.right)) (by simp [← homologyMap_comp]) + retract := by ext <;> simp [← homologyMap_comp] } + exact (MorphismProperty.isomorphisms C).of_retract h hf₂ + +end ShortComplex + +end CategoryTheory From ab9317ed59e4e679f93f9414206a058a7a5f1ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Thu, 23 Jan 2025 19:32:27 +0000 Subject: [PATCH 464/681] feat(RingTheory/Artinian): rewrite results using spectra types instead of sets (#20828) Rewrite results about artinian rings using `MaximalSpectrum` and `PrimeSpectrum` instead of sets `{I | I.IsMaximal}` and `{I | I.IsPrime}`. --- Mathlib/RingTheory/Artinian/Instances.lean | 2 +- Mathlib/RingTheory/Artinian/Module.lean | 57 ++++++++++++++----- Mathlib/RingTheory/Etale/Field.lean | 9 +-- .../RingTheory/Spectrum/Maximal/Basic.lean | 13 +++++ Mathlib/RingTheory/Spectrum/Prime/Basic.lean | 8 +++ .../RingTheory/Spectrum/Prime/Noetherian.lean | 4 -- 6 files changed, 68 insertions(+), 25 deletions(-) diff --git a/Mathlib/RingTheory/Artinian/Instances.lean b/Mathlib/RingTheory/Artinian/Instances.lean index a5b60aa963ede..6cd3c5974ed97 100644 --- a/Mathlib/RingTheory/Artinian/Instances.lean +++ b/Mathlib/RingTheory/Artinian/Instances.lean @@ -19,7 +19,7 @@ namespace IsArtinianRing variable (R : Type*) [CommRing R] [IsArtinianRing R] [IsReduced R] -attribute [local instance] subtype_isMaximal_finite fieldOfSubtypeIsMaximal +attribute [local instance] fieldOfSubtypeIsMaximal instance : DecompositionMonoid R := MulEquiv.decompositionMonoid (equivPi R) diff --git a/Mathlib/RingTheory/Artinian/Module.lean b/Mathlib/RingTheory/Artinian/Module.lean index 60a200a8eda6d..17341d196f991 100644 --- a/Mathlib/RingTheory/Artinian/Module.lean +++ b/Mathlib/RingTheory/Artinian/Module.lean @@ -9,6 +9,8 @@ import Mathlib.RingTheory.Ideal.Prod import Mathlib.RingTheory.Ideal.Quotient.Operations import Mathlib.RingTheory.Nilpotent.Lemmas import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Spectrum.Maximal.Basic +import Mathlib.RingTheory.Spectrum.Prime.Basic /-! # Artinian rings and modules @@ -452,7 +454,7 @@ section CommSemiring variable (R : Type*) [CommSemiring R] [IsArtinianRing R] @[stacks 00J7] -lemma maximal_ideals_finite : {I : Ideal R | I.IsMaximal}.Finite := by +lemma setOf_isMaximal_finite : {I : Ideal R | I.IsMaximal}.Finite := by set Spec := {I : Ideal R | I.IsMaximal} obtain ⟨_, ⟨s, rfl⟩, H⟩ := IsArtinian.set_has_minimal (range (Finset.inf · Subtype.val : Finset Spec → Ideal R)) ⟨⊤, ∅, by simp⟩ @@ -462,8 +464,9 @@ lemma maximal_ideals_finite : {I : Ideal R | I.IsMaximal}.Finite := by inf_le_right.eq_of_not_lt (H (p ⊓ s.inf Subtype.val) ⟨insert p s, by simp⟩) rwa [← Subtype.ext <| q.2.eq_of_le p.2.ne_top hq2] -lemma subtype_isMaximal_finite : Finite {I : Ideal R | I.IsMaximal} := - (maximal_ideals_finite R).to_subtype +instance : Finite (MaximalSpectrum R) := + haveI : Finite {I : Ideal R // I.IsMaximal} := (setOf_isMaximal_finite R).to_subtype + .of_equiv _ (MaximalSpectrum.equivSubtype _).symm end CommSemiring @@ -488,30 +491,56 @@ instance isMaximal_of_isPrime (p : Ideal R) [p.IsPrime] : p.IsMaximal := lemma isPrime_iff_isMaximal (p : Ideal R) : p.IsPrime ↔ p.IsMaximal := ⟨fun _ ↦ isMaximal_of_isPrime p, fun h ↦ h.isPrime⟩ +/-- The prime spectrum is in bijection with the maximal spectrum. -/ +@[simps] +def primeSpectrumEquivMaximalSpectrum : PrimeSpectrum R ≃ MaximalSpectrum R where + toFun I := ⟨I.asIdeal, isPrime_iff_isMaximal I.asIdeal |>.mp I.isPrime⟩ + invFun I := ⟨I.asIdeal, isPrime_iff_isMaximal I.asIdeal |>.mpr I.isMaximal⟩ + left_inv _ := rfl + right_inv _ := rfl + +lemma primeSpectrumEquivMaximalSpectrum_comp_asIdeal : + MaximalSpectrum.asIdeal ∘ primeSpectrumEquivMaximalSpectrum = + PrimeSpectrum.asIdeal (R := R) := rfl + +lemma primeSpectrumEquivMaximalSpectrum_symm_comp_asIdeal : + PrimeSpectrum.asIdeal ∘ primeSpectrumEquivMaximalSpectrum.symm = + MaximalSpectrum.asIdeal (R := R) := rfl + +lemma primeSpectrum_asIdeal_range_eq : + range PrimeSpectrum.asIdeal = (range <| MaximalSpectrum.asIdeal (R := R)) := by + simp only [PrimeSpectrum.range_asIdeal, MaximalSpectrum.range_asIdeal, + isPrime_iff_isMaximal] + variable (R) -lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by - simpa only [isPrime_iff_isMaximal] using maximal_ideals_finite R +lemma setOf_isPrime_finite : {I : Ideal R | I.IsPrime}.Finite := by + simpa only [isPrime_iff_isMaximal] using setOf_isMaximal_finite R -attribute [local instance] subtype_isMaximal_finite +instance : Finite (PrimeSpectrum R) := + haveI : Finite {I : Ideal R // I.IsPrime} := (setOf_isPrime_finite R).to_subtype + .of_equiv _ (PrimeSpectrum.equivSubtype _).symm /-- A temporary field instance on the quotients by maximal ideals. -/ @[local instance] noncomputable def fieldOfSubtypeIsMaximal - (I : {I : Ideal R | I.IsMaximal}) : Field (R ⧸ I.1) := - have := mem_setOf.mp I.2; Ideal.Quotient.field I.1 + (I : MaximalSpectrum R) : Field (R ⧸ I.asIdeal) := + Ideal.Quotient.field I.asIdeal /-- The quotient of a commutative artinian ring by its nilradical is isomorphic to a finite product of fields, namely the quotients by the maximal ideals. -/ noncomputable def quotNilradicalEquivPi : - R ⧸ nilradical R ≃+* ∀ I : {I : Ideal R | I.IsMaximal}, R ⧸ I.1 := - .trans (Ideal.quotEquivOfEq <| ext fun x ↦ by simp_rw [mem_nilradical, - nilpotent_iff_mem_prime, Submodule.mem_iInf, Subtype.forall, isPrime_iff_isMaximal, mem_setOf]) - (Ideal.quotientInfRingEquivPiQuotient _ fun I J h ↦ - Ideal.isCoprime_iff_sup_eq.mpr <| I.2.coprime_of_ne J.2 <| by rwa [Ne, Subtype.coe_inj]) + R ⧸ nilradical R ≃+* ∀ I : MaximalSpectrum R, R ⧸ I.asIdeal := + let f := MaximalSpectrum.asIdeal (R := R) + .trans + (Ideal.quotEquivOfEq <| ext fun x ↦ by + rw [PrimeSpectrum.nilradical_eq_iInf, iInf, primeSpectrum_asIdeal_range_eq]; rfl) + (Ideal.quotientInfRingEquivPiQuotient f <| fun I J h ↦ + Ideal.isCoprime_iff_sup_eq.mpr <| I.2.coprime_of_ne J.2 <| + fun hIJ ↦ h <| MaximalSpectrum.ext hIJ) /-- A reduced commutative artinian ring is isomorphic to a finite product of fields, namely the quotients by the maximal ideals. -/ -noncomputable def equivPi [IsReduced R] : R ≃+* ∀ I : {I : Ideal R | I.IsMaximal}, R ⧸ I.1 := +noncomputable def equivPi [IsReduced R] : R ≃+* ∀ I : MaximalSpectrum R, R ⧸ I.asIdeal := .trans (.symm <| .quotientBot R) <| .trans (Ideal.quotEquivOfEq (nilradical_eq_zero R).symm) (quotNilradicalEquivPi R) diff --git a/Mathlib/RingTheory/Etale/Field.lean b/Mathlib/RingTheory/Etale/Field.lean index be84c58cf9418..da08f62a5267c 100644 --- a/Mathlib/RingTheory/Etale/Field.lean +++ b/Mathlib/RingTheory/Etale/Field.lean @@ -153,8 +153,7 @@ theorem iff_isSeparable [EssFiniteType K L] : FormallyEtale K L ↔ Algebra.IsSeparable K L := ⟨fun _ ↦ FormallyUnramified.isSeparable K L, fun _ ↦ of_isSeparable K L⟩ -attribute [local instance] - IsArtinianRing.subtype_isMaximal_finite IsArtinianRing.fieldOfSubtypeIsMaximal in +attribute [local instance] IsArtinianRing.fieldOfSubtypeIsMaximal in /-- If `A` is an essentially of finite type algebra over a field `K`, then `A` is formally étale over `K` if and only if `A` is a finite product of separable field extensions. @@ -170,8 +169,8 @@ theorem iff_exists_algEquiv_prod [EssFiniteType K A] : have := FormallyUnramified.finite_of_free K A have := FormallyUnramified.isReduced_of_field K A have : IsArtinianRing A := isArtinian_of_tower K inferInstance - letI : Fintype {I : Ideal A | I.IsMaximal} := (nonempty_fintype _).some - let v (i : {I : Ideal A | I.IsMaximal}) : A := (IsArtinianRing.equivPi A).symm (Pi.single i 1) + letI : Fintype (MaximalSpectrum A) := (nonempty_fintype _).some + let v (i : MaximalSpectrum A) : A := (IsArtinianRing.equivPi A).symm (Pi.single i 1) let e : A ≃ₐ[K] _ := { __ := IsArtinianRing.equivPi A, commutes' := fun r ↦ rfl } have := (FormallyEtale.iff_of_equiv e).mp inferInstance rw [FormallyEtale.pi_iff] at this @@ -189,8 +188,6 @@ theorem iff_exists_algEquiv_prod [EssFiniteType K A] : end Algebra.FormallyEtale -attribute [local instance] - IsArtinianRing.subtype_isMaximal_finite IsArtinianRing.fieldOfSubtypeIsMaximal in /-- `A` is étale over a field `K` if and only if `A` is a finite product of finite separable field extensions. diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean index e13efc0c60bcb..dc91ef72f56f7 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Basic.lean @@ -18,6 +18,19 @@ variable (R S P : Type*) [CommSemiring R] [CommSemiring S] [CommSemiring P] namespace MaximalSpectrum +/-- The prime spectrum is in bijection with the set of prime ideals. -/ +@[simps] +def equivSubtype : MaximalSpectrum R ≃ {I : Ideal R // I.IsMaximal} where + toFun I := ⟨I.asIdeal, I.2⟩ + invFun I := ⟨I, I.2⟩ + left_inv _ := rfl + right_inv _ := rfl + +theorem range_asIdeal : Set.range MaximalSpectrum.asIdeal = {J : Ideal R | J.IsMaximal} := + Set.ext fun J ↦ + ⟨fun hJ ↦ let ⟨j, hj⟩ := Set.mem_range.mp hJ; Set.mem_setOf.mpr <| hj ▸ j.isMaximal, + fun hJ ↦ Set.mem_range.mpr ⟨⟨J, Set.mem_setOf.mp hJ⟩, rfl⟩⟩ + variable {R} instance [Nontrivial R] : Nonempty <| MaximalSpectrum R := diff --git a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean index 0f54c2ec83cac..92132833e5f2f 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Basic.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Basic.lean @@ -73,6 +73,11 @@ def equivSubtype : PrimeSpectrum R ≃ {I : Ideal R // I.IsPrime} where left_inv _ := rfl right_inv _ := rfl +theorem range_asIdeal : Set.range PrimeSpectrum.asIdeal = {J : Ideal R | J.IsPrime} := + Set.ext fun J ↦ + ⟨fun hJ ↦ let ⟨j, hj⟩ := Set.mem_range.mp hJ; Set.mem_setOf.mpr <| hj ▸ j.isPrime, + fun hJ ↦ Set.mem_range.mpr ⟨⟨J, Set.mem_setOf.mp hJ⟩, rfl⟩⟩ + /-- The map from the direct sum of prime spectra to the prime spectrum of a direct product. -/ @[simp] def primeSpectrumProdOfSum : PrimeSpectrum R ⊕ PrimeSpectrum S → PrimeSpectrum (R × S) @@ -198,6 +203,9 @@ theorem vanishingIdeal_zeroLocus_eq_radical (I : Ideal R) : rw [mem_vanishingIdeal, Ideal.radical_eq_sInf, Submodule.mem_sInf] exact ⟨fun h x hx => h ⟨x, hx.2⟩ hx.1, fun h x hx => h x.1 ⟨hx, x.2⟩⟩ +theorem nilradical_eq_iInf : nilradical R = iInf asIdeal := by + apply range_asIdeal R ▸ nilradical_eq_sInf R + @[simp] theorem zeroLocus_radical (I : Ideal R) : zeroLocus (I.radical : Set R) = zeroLocus I := vanishingIdeal_zeroLocus_eq_radical I ▸ (gc R).l_u_l_eq_l I diff --git a/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean b/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean index 4e38232fb5a13..e36ce5d245d25 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Noetherian.lean @@ -43,10 +43,6 @@ section IsArtinianRing variable (R : Type u) [CommRing R] [IsArtinianRing R] -instance : Finite (PrimeSpectrum R) := - have : Finite {I : Ideal R // I.IsPrime} := IsArtinianRing.primeSpectrum_finite R - Finite.of_injective _ (equivSubtype R).injective - instance : DiscreteTopology (PrimeSpectrum R) := discreteTopology_iff_finite_and_isPrime_imp_isMaximal.mpr ⟨inferInstance, fun _ _ ↦ inferInstance⟩ From 764d7e766c491770cc24faaeff213c2eef8a87e1 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 23 Jan 2025 21:13:41 +0000 Subject: [PATCH 465/681] feat: add `fast_instance%` elaborator (#11521) Quoting the docstring: `fast_instance% inst` takes an expression for a typeclass instance `inst`, and unfolds it into constructor applications that leverage existing instances. For instance, when used as ```lean instance instSemiring : Semiring X := sorry instance instRing : Ring X := fast_instance% Function.Injective.ring .. ``` this will define `instRing` as a nested constructor application that refers to `instSemiring`. The advantage is then that `instRing.toSemiring` unifies almost immediately with `instSemiring`, rather than having to break it down into smaller pieces. Related to #7432 Co-authored-by: Kyle Miller Co-authored-by: Matthew Robert Ballard <100034030+mattrobball@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Tactic.lean | 1 + Mathlib/Tactic/FastInstance.lean | 131 +++++++++++++++++++++++++++++ MathlibTest/fast_instance.lean | 139 +++++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+) create mode 100644 Mathlib/Tactic/FastInstance.lean create mode 100644 MathlibTest/fast_instance.lean diff --git a/Mathlib.lean b/Mathlib.lean index 99db52618fc07..a52a1a217b2d0 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4958,6 +4958,7 @@ import Mathlib.Tactic.ExtractGoal import Mathlib.Tactic.ExtractLets import Mathlib.Tactic.FBinop import Mathlib.Tactic.FailIfNoProgress +import Mathlib.Tactic.FastInstance import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.FinCases import Mathlib.Tactic.Find diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index c30277fabaaaf..fda897921c1fe 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -80,6 +80,7 @@ import Mathlib.Tactic.ExtractGoal import Mathlib.Tactic.ExtractLets import Mathlib.Tactic.FBinop import Mathlib.Tactic.FailIfNoProgress +import Mathlib.Tactic.FastInstance import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.FinCases import Mathlib.Tactic.Find diff --git a/Mathlib/Tactic/FastInstance.lean b/Mathlib/Tactic/FastInstance.lean new file mode 100644 index 0000000000000..4e2bd4871dee5 --- /dev/null +++ b/Mathlib/Tactic/FastInstance.lean @@ -0,0 +1,131 @@ +/- +Copyright (c) 2024 Eric Wieser. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Eric Wieser, Kyle Miller +-/ + +import Lean.Elab.SyntheticMVars +import Lean +import Mathlib.Init +/-! +# The `fast_instance%` term elaborator +-/ + +namespace Mathlib.Elab.FastInstance + +open Lean Meta Elab Term + +initialize registerTraceClass `Elab.fast_instance + +/-- +Throw an error for `makeFastInstance`. The trace is a list of fields. +Note: with the current implementation, this might not be accurate for multi-structure types, +since `makeFastInstance` just uses `ClassName.paramName` for the trace. +-/ +private def error {α : Type _} (trace : Array Name) (m : MessageData) : MetaM α := + throwError "\ + {m}\n\n\ + Use `set_option trace.Elab.fast_instance true` to analyze the error.\n\n\ + Trace of fields visited: {trace}" + +/-- +Core algorithm for normalizing instances. +* Ideally, the term is replaced with a synthesized instance. +* If not, it is reduced to a constructor + and each instance implicit field is given the same treatment. + If the type is a structure, the algorithm throws an error; + we're more lenient with non-structure classes. + +Many reductions for typeclasses are done with reducible transparency, so the entire body +is `withReducible` with some exceptions. +-/ +private partial def makeFastInstance (provided : Expr) (trace : Array Name := #[]) : + MetaM Expr := withReducible do + let ty ← inferType provided + withTraceNode `Elab.fast_instance (fun e => return m!"{exceptEmoji e} type: {ty}") do + let .some className ← isClass? ty + | error trace m!"Can only be used for classes, but term has type{indentExpr ty}" + trace[Elab.fast_instance] "class is {className}" + if ← withDefault <| Meta.isProp ty then + error trace m!"\ + Provided instance{indentExpr provided}\n\ + is a proof, which does not need normalization." + + -- Try to synthesize a total replacement for this term: + if let .some new ← trySynthInstance ty then + if ← withReducibleAndInstances <| isDefEq provided new then + trace[Elab.fast_instance] "replaced with synthesized instance" + return new + else + if ← withDefault <| isDefEq provided new then + error trace m!"\ + Provided instance{indentExpr provided}\n\ + is defeq only at default transparency to inferred instance{indentExpr new}" + else + error trace m!"\ + Provided instance{indentExpr provided}\n\ + is not defeq to inferred instance{indentExpr new}" + -- Otherwise, try to reduce it to a constructor. + else + -- Telescope since it might be a family of instances. + forallTelescopeReducing ty fun tyArgs _ => do + let provided' ← withReducibleAndInstances <| whnf <| mkAppN provided tyArgs + let error' (m : MessageData) : MetaM Expr := do + if isStructure (← getEnv) className then + error trace m + else + error trace m!"{m}\n\n\ + This instance is not a structure and not canonical. \ + Use a separate 'instance' command to define it." + let .const c .. := provided'.getAppFn + | error' m!"\ + Provided instance does not reduce to a constructor application{indentExpr provided}" + let some (.ctorInfo ci) := (← getEnv).find? c + | error' m!"\ + Provided instance does not reduce to a constructor application{indentExpr provided}\n\ + Reduces to an application of {c}." + let mut args := provided'.getAppArgs + let params ← withDefault <| forallTelescopeReducing ci.type fun args _ => + args.mapM fun arg => do + let recurse ← (return (← arg.fvarId!.getBinderInfo).isInstImplicit) + <&&> not <$> Meta.isProof arg + return (recurse, ← arg.fvarId!.getUserName) + unless args.size == params.size do + -- This is an invalid term. + throwError "Incorrect number of arguments for constructor application{indentExpr provided'}" + for i in [ci.numParams:args.size] do + let (recurse, binderName) := params[i]! + if recurse then + let trace' := trace.push (className ++ binderName) + args := args.set! i (← makeFastInstance args[i]! (trace := trace')) + let provided' := mkAppN provided'.getAppFn args + mkLambdaFVars tyArgs provided' + +/-- +`fast_instance% inst` takes an expression for a typeclass instance `inst`, and unfolds it into +constructor applications that leverage existing instances. + +For instance, when used as +```lean +instance instSemiring : Semiring X := sorry +instance instRing : Ring X := fast_instance% Function.Injective.ring .. +``` +this will define `instRing` as a nested constructor application that refers to `instSemiring`. +The advantage is then that `instRing.toSemiring` unifies almost immediately with `instSemiring`, +rather than having to break it down into smaller pieces. +-/ +syntax (name := fastInstance) "fast_instance%" term : term + +@[term_elab fastInstance, inherit_doc fastInstance] +def elabFastInstance : TermElab + | `(term| fast_instance%%$tk $arg), expectedType => do + let provided ← withSynthesize <| elabTerm arg expectedType + withRef tk do + try + makeFastInstance provided + catch e => + logException e + return provided + | _, _ => Elab.throwUnsupportedSyntax + +end Mathlib.Elab.FastInstance diff --git a/MathlibTest/fast_instance.lean b/MathlibTest/fast_instance.lean new file mode 100644 index 0000000000000..0e74123b6222a --- /dev/null +++ b/MathlibTest/fast_instance.lean @@ -0,0 +1,139 @@ +import Mathlib.Tactic.FastInstance +import Mathlib.Logic.Function.Defs +import Mathlib.Tactic.Spread + +namespace testing +set_option autoImplicit false + +-- For debugging: +--set_option trace.Elab.fast_instance true + +/-! +Testing a diamond: CommSemigroup +-/ + +class Mul (α : Type*) where + mul : α → α → α + +class Semigroup (α : Type*) extends Mul α where + mul_assoc (x y z : α) : mul x (mul y z) = mul (mul x y) z + +class CommMagma (α : Type*) extends Mul α where + mul_comm (x y : α) : mul x y = mul y x + +class CommSemigroup (α : Type*) extends Semigroup α, CommMagma α + +structure Wrapped (α : Type*) where + val : α + +variable {α : Type*} + +theorem val_injective : Function.Injective (Wrapped.val (α := α)) + | ⟨_⟩, ⟨_⟩, rfl => rfl + +instance [Mul α] : Mul (Wrapped α) where mul m n := ⟨Mul.mul m.1 n.1⟩ + +@[reducible] def Function.Injective.semigroup {α β : Type*} [Mul α] [Semigroup β] + (f : α → β) (hf : Function.Injective f) + (hmul : ∀ x y, f (Mul.mul x y) = Mul.mul (f x) (f y)) : + Semigroup α := + { ‹Mul α› with + mul_assoc := fun x y z => by apply hf; rw [hmul, hmul, hmul, hmul, Semigroup.mul_assoc] } + +@[reducible] def Function.Injective.commMagma {α β : Type*} [Mul α] [CommMagma β] + (f : α → β) (hf : Function.Injective f) + (hmul : ∀ x y, f (Mul.mul x y) = Mul.mul (f x) (f y)) : + CommMagma α where + mul_comm x y := by + apply hf + rw [hmul, hmul, CommMagma.mul_comm] + +@[reducible] def Function.Injective.commSemigroup {α β : Type*} [Mul α] [CommSemigroup β] + (f : α → β) (hf : Function.Injective f) + (hmul : ∀ x y, f (Mul.mul x y) = Mul.mul (f x) (f y)) : + CommSemigroup α where + toSemigroup := Function.Injective.semigroup f hf hmul + __ := Function.Injective.commMagma f hf hmul + +instance instSemigroup [Semigroup α] : Semigroup (Wrapped α) := + fast_instance% Function.Injective.semigroup _ val_injective (fun _ _ => rfl) + +instance instCommSemigroup [CommSemigroup α] : CommSemigroup (Wrapped α) := + fast_instance% Function.Injective.commSemigroup _ val_injective (fun _ _ => rfl) + +/-- +info: def testing.instSemigroup.{u_1} : {α : Type u_1} → [inst : Semigroup α] → Semigroup (Wrapped α) := +fun {α} [inst : Semigroup α] => @Semigroup.mk (Wrapped α) (@instMulWrapped α (@Semigroup.toMul α inst)) ⋯ +-/ +#guard_msgs in +set_option pp.explicit true in +#print instSemigroup +/-- +info: def testing.instCommSemigroup.{u_1} : {α : Type u_1} → [inst : CommSemigroup α] → CommSemigroup (Wrapped α) := +fun {α} [inst : CommSemigroup α] => + @CommSemigroup.mk (Wrapped α) (@instSemigroup α (@CommSemigroup.toSemigroup α inst)) ⋯ +-/ +#guard_msgs in +set_option pp.explicit true in +#print instCommSemigroup + + +/-! +Non-defeq error +-/ +instance : Mul Nat := ⟨(· * · )⟩ + +/-- +error: Provided instance + { mul := fun x y => y * x } +is not defeq to inferred instance + instMulNat + +Use `set_option trace.Elab.fast_instance true` to analyze the error. + +Trace of fields visited: [] +--- +info: { mul := fun x y => y * x } : Mul Nat +-/ +#guard_msgs in +#check fast_instance% { mul := fun x y => y * x : Mul Nat } + + +/-! +Checking handling of non-structure classes. +-/ + +class Dec (p : Prop) where + [dec : Decidable p] + +axiom It : Prop + +/-- warning: declaration uses 'sorry' -/ +#guard_msgs in +abbrev dec1 : Decidable It := isTrue sorry + +/-- warning: declaration uses 'sorry' -/ +#guard_msgs in +def dec2 : Decidable It := isTrue sorry + +/-- info: @Dec.mk It (@isTrue It dec1.proof_1) : Dec It -/ +#guard_msgs in +set_option pp.explicit true in +#check fast_instance% { dec := dec1 : Dec It } + +/-- +error: Provided instance does not reduce to a constructor application + dec2 +Reduces to an application of testing.dec2. + +This instance is not a structure and not canonical. Use a separate 'instance' command to define it. + +Use `set_option trace.Elab.fast_instance true` to analyze the error. + +Trace of fields visited: [testing.Dec.dec] +--- +info: @Dec.mk It dec2 : Dec It +-/ +#guard_msgs in +set_option pp.explicit true in +#check fast_instance% { dec := dec2 : Dec It } From 2a71f56e8867536abeae5d73fdb6666dc21ff7d4 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 23 Jan 2025 21:56:58 +0000 Subject: [PATCH 466/681] fix: add missing `MonoidAlgebra.smul_single` (#20933) This eliminates some `erw`s. Also fixes bad generated simp lemmas about `singleOneRingHom` and `singleZeroRingHom`, which previously included unwanted `toFun` terms. --- .../ZeroDivisorsInAddMonoidAlgebras.lean | 2 +- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 26 ++++++++++++------- Mathlib/Algebra/Polynomial/Basic.lean | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Counterexamples/ZeroDivisorsInAddMonoidAlgebras.lean b/Counterexamples/ZeroDivisorsInAddMonoidAlgebras.lean index b13cc110a5128..227ffb987b92f 100644 --- a/Counterexamples/ZeroDivisorsInAddMonoidAlgebras.lean +++ b/Counterexamples/ZeroDivisorsInAddMonoidAlgebras.lean @@ -235,7 +235,7 @@ example {α} [Ring α] [Nontrivial α] : ∃ f g : AddMonoidAlgebra α F, f ≠ example {α} [Zero α] : 2 • (Finsupp.single 0 1 : α →₀ F) = (Finsupp.single 0 1 : α →₀ F) ∧ (Finsupp.single 0 1 : α →₀ F) ≠ 0 := - ⟨smul_single _ _ _, by simp [Ne, Finsupp.single_eq_zero, z01.ne]⟩ + ⟨Finsupp.smul_single _ _ _, by simp [Ne, Finsupp.single_eq_zero, z01.ne]⟩ end F diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index 0347038157818..e5ef515fa4280 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -381,6 +381,11 @@ def comapDistribMulActionSelf [Group G] [Semiring k] : DistribMulAction G (Monoi end DerivedInstances +@[simp] +theorem smul_single [Semiring k] [SMulZeroClass R k] (a : G) (c : R) (b : k) : + c • single a b = single a (c • b) := + Finsupp.smul_single _ _ _ + /-! #### Copies of `ext` lemmas and bundled `single`s from `Finsupp` @@ -535,7 +540,6 @@ def of [MulOneClass G] : G →* MonoidAlgebra k G := end /-- Copy of `Finsupp.smul_single'` that avoids the `MonoidAlgebra = Finsupp` defeq abuse. -/ -@[simp] theorem smul_single' (c : k) (a : G) (b : k) : c • single a b = single a (c * b) := Finsupp.smul_single' c a b @@ -626,12 +630,8 @@ theorem liftNC_smul [MulOneClass G] {R : Type*} [Semiring R] (f : k →+* R) (g (AddMonoidHom.mulLeft (f c)).comp (liftNC (↑f) g) from DFunLike.congr_fun this φ ext - -- Porting note: `reducible` cannot be `local` so the proof gets more complex. - unfold MonoidAlgebra - simp only [AddMonoidHom.coe_comp, Function.comp_apply, singleAddHom_apply, smulAddHom_apply, - smul_single, smul_eq_mul, AddMonoidHom.coe_mulLeft, Finsupp.singleAddHom_apply] - -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [liftNC_single, liftNC_single]; rw [AddMonoidHom.coe_coe, map_mul, mul_assoc] + simp_rw [AddMonoidHom.comp_apply, singleAddHom_apply, smulAddHom_apply, + AddMonoidHom.coe_mulLeft, smul_single', liftNC_single, AddMonoidHom.coe_coe, map_mul, mul_assoc] end MiscTheorems @@ -685,7 +685,8 @@ theorem single_one_comm [CommSemiring k] [MulOneClass G] (r : k) (f : MonoidAlge /-- `Finsupp.single 1` as a `RingHom` -/ @[simps] def singleOneRingHom [Semiring k] [MulOneClass G] : k →+* MonoidAlgebra k G := - { Finsupp.singleAddHom 1 with + { singleAddHom 1 with + toFun := single 1 map_one' := rfl map_mul' := fun x y => by simp } @@ -1172,6 +1173,11 @@ because we've never discussed actions of additive groups. -/ end DerivedInstances +@[simp] +theorem smul_single [Semiring k] [SMulZeroClass R k] (a : G) (c : R) (b : k) : + c • single a b = single a (c • b) := + Finsupp.smul_single _ _ _ + /-! #### Copies of `ext` lemmas and bundled `single`s from `Finsupp` @@ -1334,7 +1340,6 @@ def singleHom [AddZeroClass G] : k × Multiplicative G →* k[G] where map_mul' _a _b := single_mul_single.symm /-- Copy of `Finsupp.smul_single'` that avoids the `AddMonoidAlgebra = Finsupp` defeq abuse. -/ -@[simp] theorem smul_single' (c : k) (a : G) (b : k) : c • single a b = single a (c * b) := Finsupp.smul_single' c a b @@ -1472,7 +1477,8 @@ section Algebra /-- `Finsupp.single 0` as a `RingHom` -/ @[simps] def singleZeroRingHom [Semiring k] [AddMonoid G] : k →+* k[G] := - { Finsupp.singleAddHom 0 with + { singleAddHom 0 with + toFun := single 0 map_one' := rfl map_mul' := fun x y => by simp only [Finsupp.singleAddHom, single_mul_single, zero_add] } diff --git a/Mathlib/Algebra/Polynomial/Basic.lean b/Mathlib/Algebra/Polynomial/Basic.lean index d88f59b1d6cca..e2e35c90fe8a0 100644 --- a/Mathlib/Algebra/Polynomial/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Basic.lean @@ -430,7 +430,7 @@ theorem monomial_pow (n : ℕ) (r : R) (k : ℕ) : monomial n r ^ k = monomial ( theorem smul_monomial {S} [SMulZeroClass S R] (a : S) (n : ℕ) (b : R) : a • monomial n b = monomial n (a • b) := - toFinsupp_injective <| by simp; rw [smul_single] + toFinsupp_injective <| AddMonoidAlgebra.smul_single _ _ _ theorem monomial_injective (n : ℕ) : Function.Injective (monomial n : R → R[X]) := (toFinsuppIso R).symm.injective.comp (single_injective n) From 75d8e210984e857656e013c87a1976cf6747e2e7 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Fri, 24 Jan 2025 00:21:23 +0000 Subject: [PATCH 467/681] feat: IsLocalHom for MonoidAlgebra (#20934) --- Mathlib/Algebra/MonoidAlgebra/Basic.lean | 20 ++++++++++++++++++++ Mathlib/Algebra/MonoidAlgebra/Defs.lean | 16 ++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index fbea78035339d..4ed491fbb056d 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -139,6 +139,17 @@ theorem single_algebraMap_eq_algebraMap_mul_of {A : Type*} [CommSemiring k] [Sem [Algebra k A] [Monoid G] (a : G) (b : k) : single a (algebraMap k A b) = algebraMap k (MonoidAlgebra A G) b * of A G a := by simp +instance isLocalHom_singleOneAlgHom + {A : Type*} [CommSemiring k] [Semiring A] [Algebra k A] [Monoid G] : + IsLocalHom (singleOneAlgHom : A →ₐ[k] MonoidAlgebra A G) where + map_nonunit := isLocalHom_singleOneRingHom.map_nonunit + +instance isLocalHom_algebraMap + {A : Type*} [CommSemiring k] [Semiring A] [Algebra k A] [Monoid G] + [IsLocalHom (algebraMap k A)] : + IsLocalHom (algebraMap k (MonoidAlgebra A G)) where + map_nonunit _ hx := .of_map _ _ <| isLocalHom_singleOneAlgHom (k := k).map_nonunit _ hx + end Algebra section lift @@ -410,6 +421,15 @@ theorem coe_algebraMap [CommSemiring R] [Semiring k] [Algebra R k] [AddMonoid G] (algebraMap R k[G] : R → k[G]) = single 0 ∘ algebraMap R k := rfl +instance isLocalHom_singleZeroAlgHom [CommSemiring R] [Semiring k] [Algebra R k] [AddMonoid G] : + IsLocalHom (singleZeroAlgHom : k →ₐ[R] k[G]) where + map_nonunit := isLocalHom_singleZeroRingHom.map_nonunit + +instance isLocalHom_algebraMap [CommSemiring R] [Semiring k] [Algebra R k] [AddMonoid G] + [IsLocalHom (algebraMap R k)] : + IsLocalHom (algebraMap R k[G]) where + map_nonunit _ hx := .of_map _ _ <| isLocalHom_singleZeroAlgHom (R := R).map_nonunit _ hx + end Algebra section lift diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index e5ef515fa4280..f85bf7c48b4fa 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -838,6 +838,18 @@ def submoduleOfSMulMem (W : Submodule k V) (h : ∀ (g : G) (v : V), v ∈ W → end Submodule +instance isLocalHom_singleOneRingHom [Semiring k] [Monoid G] : + IsLocalHom (singleOneRingHom (k := k) (G := G)) where + map_nonunit x hx := by + obtain ⟨⟨x, xi, hx, hxi⟩, rfl⟩ := hx + simp_rw [MonoidAlgebra.ext_iff, singleOneRingHom_apply] at hx hxi ⊢ + specialize hx 1 + specialize hxi 1 + classical + simp_rw [single_one_mul_apply, one_def, single_apply, if_pos] at hx + simp_rw [mul_single_one_apply, one_def, single_apply, if_pos] at hxi + exact ⟨⟨x, xi 1, hx, hxi⟩, rfl⟩ + end MonoidAlgebra /-! ### Additive monoids -/ @@ -1558,6 +1570,10 @@ theorem prod_single [CommSemiring k] [AddCommMonoid G] {s : Finset ι} {a : ι end +instance isLocalHom_singleZeroRingHom [Semiring k] [AddMonoid G] : + IsLocalHom (singleZeroRingHom (k := k) (G := G)) := + MonoidAlgebra.isLocalHom_singleOneRingHom (G := Multiplicative G) + end AddMonoidAlgebra set_option linter.style.longFile 1700 From 08dea193f686dbade77dd736cb0dbd799b1914b9 Mon Sep 17 00:00:00 2001 From: Whysoserioushah Date: Fri, 24 Jan 2025 00:30:42 +0000 Subject: [PATCH 468/681] chore(Mathlib/Algebra/Quaternion): Generalize Quaternion Algebra (#20657) Co-authored-by: Whysoserioushah <109107491+Whysoserioushah@users.noreply.github.com> Co-authored-by: Eric Wieser --- Mathlib/Algebra/Quaternion.lean | 484 ++++++++++-------- Mathlib/Algebra/QuaternionBasis.lean | 85 +-- Mathlib/Analysis/Quaternion.lean | 9 +- .../LinearAlgebra/CliffordAlgebra/Equivs.lean | 34 +- 4 files changed, 332 insertions(+), 280 deletions(-) diff --git a/Mathlib/Algebra/Quaternion.lean b/Mathlib/Algebra/Quaternion.lean index fc5bcda77af79..a183bc45667c2 100644 --- a/Mathlib/Algebra/Quaternion.lean +++ b/Mathlib/Algebra/Quaternion.lean @@ -3,12 +3,9 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Algebra.Algebra.Equiv import Mathlib.Algebra.Star.SelfAdjoint import Mathlib.LinearAlgebra.Dimension.StrongRankCondition -import Mathlib.LinearAlgebra.FreeModule.Basic import Mathlib.LinearAlgebra.FreeModule.Finite.Basic -import Mathlib.SetTheory.Cardinal.Arithmetic /-! # Quaternions @@ -18,15 +15,18 @@ algebraic structures on `ℍ[R]`. ## Main definitions -* `QuaternionAlgebra R a b`, `ℍ[R, a, b]` : - [quaternion algebra](https://en.wikipedia.org/wiki/Quaternion_algebra) with coefficients `a`, `b` -* `Quaternion R`, `ℍ[R]` : the space of quaternions, a.k.a. `QuaternionAlgebra R (-1) (-1)`; +* `QuaternionAlgebra R a b c`, `ℍ[R, a, b, c]` : + [Bourbaki, *Algebra I*][bourbaki1989] with coefficients `a`, `b`, `c` + (Many other references such as Wikipedia assume $\operatorname{char} R ≠ 2$ therefore one can + complete the square and WLOG assume $b = 0$.) +* `Quaternion R`, `ℍ[R]` : the space of quaternions, a.k.a. + `QuaternionAlgebra R (-1) (0) (-1)`; * `Quaternion.normSq` : square of the norm of a quaternion; We also define the following algebraic structures on `ℍ[R]`: -* `Ring ℍ[R, a, b]`, `StarRing ℍ[R, a, b]`, and `Algebra R ℍ[R, a, b]` : for any commutative ring - `R`; +* `Ring ℍ[R, a, b, c]`, `StarRing ℍ[R, a, b, c]`, and `Algebra R ℍ[R, a, b, c]` : + for any commutative ring `R`; * `Ring ℍ[R]`, `StarRing ℍ[R]`, and `Algebra R ℍ[R]` : for any commutative ring `R`; * `IsDomain ℍ[R]` : for a linear ordered commutative ring `R`; * `DivisionRing ℍ[R]` : for a linear ordered field `R`. @@ -35,7 +35,8 @@ We also define the following algebraic structures on `ℍ[R]`: The following notation is available with `open Quaternion` or `open scoped Quaternion`. -* `ℍ[R, c₁, c₂]` : `QuaternionAlgebra R c₁ c₂` +* `ℍ[R, c₁, c₂, c₃]` : `QuaternionAlgebra R c₁ c₂ c₃` +* `ℍ[R, c₁, c₂]` : `QuaternionAlgebra R c₁ 0 c₂` * `ℍ[R]` : quaternions over `R`. ## Implementation notes @@ -50,10 +51,10 @@ quaternion -/ -/-- Quaternion algebra over a type with fixed coefficients $a=i^2$ and $b=j^2$. +/-- Quaternion algebra over a type with fixed coefficients where $i^2 = a + bi$ and $j^2 = c$. Implemented as a structure with four fields: `re`, `imI`, `imJ`, and `imK`. -/ @[ext] -structure QuaternionAlgebra (R : Type*) (a b : R) where +structure QuaternionAlgebra (R : Type*) (a b c : R) where /-- Real part of a quaternion. -/ re : R /-- First imaginary part (i) of a quaternion. -/ @@ -64,14 +65,18 @@ structure QuaternionAlgebra (R : Type*) (a b : R) where imK : R @[inherit_doc] -scoped[Quaternion] notation "ℍ[" R "," a "," b "]" => QuaternionAlgebra R a b -open Quaternion +scoped[Quaternion] notation "ℍ[" R "," a "," b "," c "]" => + QuaternionAlgebra R a b c + +@[inherit_doc] +scoped[Quaternion] notation "ℍ[" R "," a "," b "]" => QuaternionAlgebra R a 0 b namespace QuaternionAlgebra +open Quaternion /-- The equivalence between a quaternion algebra over `R` and `R × R × R × R`. -/ @[simps] -def equivProd {R : Type*} (c₁ c₂ : R) : ℍ[R,c₁,c₂] ≃ R × R × R × R where +def equivProd {R : Type*} (c₁ c₂ c₃: R) : ℍ[R,c₁,c₂,c₃] ≃ R × R × R × R where toFun a := ⟨a.1, a.2, a.3, a.4⟩ invFun a := ⟨a.1, a.2.1, a.2.2.1, a.2.2.2⟩ left_inv _ := rfl @@ -79,30 +84,34 @@ def equivProd {R : Type*} (c₁ c₂ : R) : ℍ[R,c₁,c₂] ≃ R × R × R × /-- The equivalence between a quaternion algebra over `R` and `Fin 4 → R`. -/ @[simps symm_apply] -def equivTuple {R : Type*} (c₁ c₂ : R) : ℍ[R,c₁,c₂] ≃ (Fin 4 → R) where +def equivTuple {R : Type*} (c₁ c₂ c₃: R) : ℍ[R,c₁,c₂,c₃] ≃ (Fin 4 → R) where toFun a := ![a.1, a.2, a.3, a.4] invFun a := ⟨a 0, a 1, a 2, a 3⟩ left_inv _ := rfl right_inv f := by ext ⟨_, _ | _ | _ | _ | _ | ⟨⟩⟩ <;> rfl @[simp] -theorem equivTuple_apply {R : Type*} (c₁ c₂ : R) (x : ℍ[R,c₁,c₂]) : - equivTuple c₁ c₂ x = ![x.re, x.imI, x.imJ, x.imK] := +theorem equivTuple_apply {R : Type*} (c₁ c₂ c₃: R) (x : ℍ[R,c₁,c₂,c₃]) : + equivTuple c₁ c₂ c₃ x = ![x.re, x.imI, x.imJ, x.imK] := rfl @[simp] -theorem mk.eta {R : Type*} {c₁ c₂} (a : ℍ[R,c₁,c₂]) : mk a.1 a.2 a.3 a.4 = a := rfl +theorem mk.eta {R : Type*} {c₁ c₂ c₃} (a : ℍ[R,c₁,c₂,c₃]) : mk a.1 a.2 a.3 a.4 = a := rfl -variable {S T R : Type*} {c₁ c₂ : R} (r x y : R) (a b : ℍ[R,c₁,c₂]) +variable {S T R : Type*} {c₁ c₂ c₃ : R} (r x y : R) (a b : ℍ[R,c₁,c₂,c₃]) -instance [Subsingleton R] : Subsingleton ℍ[R, c₁, c₂] := (equivTuple c₁ c₂).subsingleton -instance [Nontrivial R] : Nontrivial ℍ[R, c₁, c₂] := (equivTuple c₁ c₂).surjective.nontrivial +instance [Subsingleton R] : Subsingleton ℍ[R, c₁, c₂, c₃] := (equivTuple c₁ c₂ c₃).subsingleton +instance [Nontrivial R] : Nontrivial ℍ[R, c₁, c₂, c₃] := (equivTuple c₁ c₂ c₃).surjective.nontrivial section Zero variable [Zero R] -/-- The imaginary part of a quaternion. -/ -def im (x : ℍ[R,c₁,c₂]) : ℍ[R,c₁,c₂] := +/-- The imaginary part of a quaternion. + +Note that unless `c₂ = 0`, this definition is not particularly well-behaved; +for instance, `QuaternionAlgebra.star_im` only says that the star of an imaginary quaternion +is imaginary under this condition. -/ +def im (x : ℍ[R,c₁,c₂,c₃]) : ℍ[R,c₁,c₂,c₃] := ⟨0, x.imI, x.imJ, x.imK⟩ @[simp] @@ -125,66 +134,66 @@ theorem im_imK : a.im.imK = a.imK := theorem im_idem : a.im.im = a.im := rfl -/-- Coercion `R → ℍ[R,c₁,c₂]`. -/ -@[coe] def coe (x : R) : ℍ[R,c₁,c₂] := ⟨x, 0, 0, 0⟩ +/-- Coercion `R → ℍ[R,c₁,c₂,c₃]`. -/ +@[coe] def coe (x : R) : ℍ[R,c₁,c₂,c₃] := ⟨x, 0, 0, 0⟩ -instance : CoeTC R ℍ[R,c₁,c₂] := ⟨coe⟩ +instance : CoeTC R ℍ[R,c₁,c₂,c₃] := ⟨coe⟩ @[simp, norm_cast] -theorem coe_re : (x : ℍ[R,c₁,c₂]).re = x := rfl +theorem coe_re : (x : ℍ[R,c₁,c₂,c₃]).re = x := rfl @[simp, norm_cast] -theorem coe_imI : (x : ℍ[R,c₁,c₂]).imI = 0 := rfl +theorem coe_imI : (x : ℍ[R,c₁,c₂,c₃]).imI = 0 := rfl @[simp, norm_cast] -theorem coe_imJ : (x : ℍ[R,c₁,c₂]).imJ = 0 := rfl +theorem coe_imJ : (x : ℍ[R,c₁,c₂,c₃]).imJ = 0 := rfl @[simp, norm_cast] -theorem coe_imK : (x : ℍ[R,c₁,c₂]).imK = 0 := rfl +theorem coe_imK : (x : ℍ[R,c₁,c₂,c₃]).imK = 0 := rfl -theorem coe_injective : Function.Injective (coe : R → ℍ[R,c₁,c₂]) := fun _ _ h => congr_arg re h +theorem coe_injective : Function.Injective (coe : R → ℍ[R,c₁,c₂,c₃]) := fun _ _ h => congr_arg re h @[simp] -theorem coe_inj {x y : R} : (x : ℍ[R,c₁,c₂]) = y ↔ x = y := +theorem coe_inj {x y : R} : (x : ℍ[R,c₁,c₂,c₃]) = y ↔ x = y := coe_injective.eq_iff -- Porting note: removed `simps`, added simp lemmas manually. -- Should adjust `simps` to name properly, i.e. as `zero_re` rather than `instZero_zero_re`. -instance : Zero ℍ[R,c₁,c₂] := ⟨⟨0, 0, 0, 0⟩⟩ +instance : Zero ℍ[R,c₁,c₂,c₃] := ⟨⟨0, 0, 0, 0⟩⟩ -@[simp] theorem zero_re : (0 : ℍ[R,c₁,c₂]).re = 0 := rfl +@[simp] theorem zero_re : (0 : ℍ[R,c₁,c₂,c₃]).re = 0 := rfl -@[simp] theorem zero_imI : (0 : ℍ[R,c₁,c₂]).imI = 0 := rfl +@[simp] theorem zero_imI : (0 : ℍ[R,c₁,c₂,c₃]).imI = 0 := rfl -@[simp] theorem zero_imJ : (0 : ℍ[R,c₁,c₂]).imJ = 0 := rfl +@[simp] theorem zero_imJ : (0 : ℍ[R,c₁,c₂,c₃]).imJ = 0 := rfl -@[simp] theorem zero_imK : (0 : ℍ[R,c₁,c₂]).imK = 0 := rfl +@[simp] theorem zero_imK : (0 : ℍ[R,c₁,c₂,c₃]).imK = 0 := rfl -@[simp] theorem zero_im : (0 : ℍ[R,c₁,c₂]).im = 0 := rfl +@[simp] theorem zero_im : (0 : ℍ[R,c₁,c₂,c₃]).im = 0 := rfl @[simp, norm_cast] -theorem coe_zero : ((0 : R) : ℍ[R,c₁,c₂]) = 0 := rfl +theorem coe_zero : ((0 : R) : ℍ[R,c₁,c₂,c₃]) = 0 := rfl -instance : Inhabited ℍ[R,c₁,c₂] := ⟨0⟩ +instance : Inhabited ℍ[R,c₁,c₂,c₃] := ⟨0⟩ section One variable [One R] -- Porting note: removed `simps`, added simp lemmas manually. Should adjust `simps` to name properly -instance : One ℍ[R,c₁,c₂] := ⟨⟨1, 0, 0, 0⟩⟩ +instance : One ℍ[R,c₁,c₂,c₃] := ⟨⟨1, 0, 0, 0⟩⟩ -@[simp] theorem one_re : (1 : ℍ[R,c₁,c₂]).re = 1 := rfl +@[simp] theorem one_re : (1 : ℍ[R,c₁,c₂,c₃]).re = 1 := rfl -@[simp] theorem one_imI : (1 : ℍ[R,c₁,c₂]).imI = 0 := rfl +@[simp] theorem one_imI : (1 : ℍ[R,c₁,c₂,c₃]).imI = 0 := rfl -@[simp] theorem one_imJ : (1 : ℍ[R,c₁,c₂]).imJ = 0 := rfl +@[simp] theorem one_imJ : (1 : ℍ[R,c₁,c₂,c₃]).imJ = 0 := rfl -@[simp] theorem one_imK : (1 : ℍ[R,c₁,c₂]).imK = 0 := rfl +@[simp] theorem one_imK : (1 : ℍ[R,c₁,c₂,c₃]).imK = 0 := rfl -@[simp] theorem one_im : (1 : ℍ[R,c₁,c₂]).im = 0 := rfl +@[simp] theorem one_im : (1 : ℍ[R,c₁,c₂,c₃]).im = 0 := rfl @[simp, norm_cast] -theorem coe_one : ((1 : R) : ℍ[R,c₁,c₂]) = 1 := rfl +theorem coe_one : ((1 : R) : ℍ[R,c₁,c₂,c₃]) = 1 := rfl end One end Zero @@ -192,7 +201,7 @@ section Add variable [Add R] -- Porting note: removed `simps`, added simp lemmas manually. Should adjust `simps` to name properly -instance : Add ℍ[R,c₁,c₂] := +instance : Add ℍ[R,c₁,c₂,c₃] := ⟨fun a b => ⟨a.1 + b.1, a.2 + b.2, a.3 + b.3, a.4 + b.4⟩⟩ @[simp] theorem add_re : (a + b).re = a.re + b.re := rfl @@ -205,7 +214,8 @@ instance : Add ℍ[R,c₁,c₂] := @[simp] theorem mk_add_mk (a₁ a₂ a₃ a₄ b₁ b₂ b₃ b₄ : R) : - (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂]) + mk b₁ b₂ b₃ b₄ = mk (a₁ + b₁) (a₂ + b₂) (a₃ + b₃) (a₄ + b₄) := + (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂,c₃]) + mk b₁ b₂ b₃ b₄ = + mk (a₁ + b₁) (a₂ + b₂) (a₃ + b₃) (a₄ + b₄) := rfl end Add @@ -217,7 +227,7 @@ variable [AddZeroClass R] QuaternionAlgebra.ext (zero_add _).symm rfl rfl rfl @[simp, norm_cast] -theorem coe_add : ((x + y : R) : ℍ[R,c₁,c₂]) = x + y := by ext <;> simp +theorem coe_add : ((x + y : R) : ℍ[R,c₁,c₂,c₃]) = x + y := by ext <;> simp end AddZeroClass @@ -225,7 +235,7 @@ section Neg variable [Neg R] -- Porting note: removed `simps`, added simp lemmas manually. Should adjust `simps` to name properly -instance : Neg ℍ[R,c₁,c₂] := ⟨fun a => ⟨-a.1, -a.2, -a.3, -a.4⟩⟩ +instance : Neg ℍ[R,c₁,c₂,c₃] := ⟨fun a => ⟨-a.1, -a.2, -a.3, -a.4⟩⟩ @[simp] theorem neg_re : (-a).re = -a.re := rfl @@ -236,7 +246,7 @@ instance : Neg ℍ[R,c₁,c₂] := ⟨fun a => ⟨-a.1, -a.2, -a.3, -a.4⟩⟩ @[simp] theorem neg_imK : (-a).imK = -a.imK := rfl @[simp] -theorem neg_mk (a₁ a₂ a₃ a₄ : R) : -(mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂]) = ⟨-a₁, -a₂, -a₃, -a₄⟩ := +theorem neg_mk (a₁ a₂ a₃ a₄ : R) : -(mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂,c₃]) = ⟨-a₁, -a₂, -a₃, -a₄⟩ := rfl end Neg @@ -248,9 +258,9 @@ variable [AddGroup R] QuaternionAlgebra.ext neg_zero.symm rfl rfl rfl @[simp, norm_cast] -theorem coe_neg : ((-x : R) : ℍ[R,c₁,c₂]) = -x := by ext <;> simp +theorem coe_neg : ((-x : R) : ℍ[R,c₁,c₂,c₃]) = -x := by ext <;> simp -instance : Sub ℍ[R,c₁,c₂] := +instance : Sub ℍ[R,c₁,c₂,c₃] := ⟨fun a b => ⟨a.1 - b.1, a.2 - b.2, a.3 - b.3, a.4 - b.4⟩⟩ @[simp] theorem sub_re : (a - b).re = a.re - b.re := rfl @@ -266,11 +276,12 @@ instance : Sub ℍ[R,c₁,c₂] := @[simp] theorem mk_sub_mk (a₁ a₂ a₃ a₄ b₁ b₂ b₃ b₄ : R) : - (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂]) - mk b₁ b₂ b₃ b₄ = mk (a₁ - b₁) (a₂ - b₂) (a₃ - b₃) (a₄ - b₄) := + (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂,c₃]) - mk b₁ b₂ b₃ b₄ = + mk (a₁ - b₁) (a₂ - b₂) (a₃ - b₃) (a₄ - b₄) := rfl @[simp, norm_cast] -theorem coe_im : (x : ℍ[R,c₁,c₂]).im = 0 := +theorem coe_im : (x : ℍ[R,c₁,c₂,c₃]).im = 0 := rfl @[simp] @@ -293,37 +304,43 @@ variable [Ring R] /-- Multiplication is given by * `1 * x = x * 1 = x`; -* `i * i = c₁`; -* `j * j = c₂`; -* `i * j = k`, `j * i = -k`; -* `k * k = -c₁ * c₂`; -* `i * k = c₁ * j`, `k * i = -c₁ * j`; -* `j * k = -c₂ * i`, `k * j = c₂ * i`. -/ -instance : Mul ℍ[R,c₁,c₂] := +* `i * i = c₁ + c₂ * i`; +* `j * j = c₃`; +* `i * j = k`, `j * i = c₂ * j - k`; +* `k * k = - c₁ * c₃`; +* `i * k = c₁ * j + c₂ * k`, `k * i = -c₁ * j`; +* `j * k = c₂ * c₃ - c₃ * i`, `k * j = c₃ * i`. -/ +instance : Mul ℍ[R,c₁,c₂,c₃] := ⟨fun a b => - ⟨a.1 * b.1 + c₁ * a.2 * b.2 + c₂ * a.3 * b.3 - c₁ * c₂ * a.4 * b.4, - a.1 * b.2 + a.2 * b.1 - c₂ * a.3 * b.4 + c₂ * a.4 * b.3, - a.1 * b.3 + c₁ * a.2 * b.4 + a.3 * b.1 - c₁ * a.4 * b.2, - a.1 * b.4 + a.2 * b.3 - a.3 * b.2 + a.4 * b.1⟩⟩ + ⟨a.1 * b.1 + c₁ * a.2 * b.2 + c₃ * a.3 * b.3 + c₂ * c₃ * a.3 * b.4 - c₁ * c₃ * a.4 * b.4, + a.1 * b.2 + a.2 * b.1 + c₂ * a.2 * b.2 - c₃ * a.3 * b.4 + c₃ * a.4 * b.3, + a.1 * b.3 + c₁ * a.2 * b.4 + a.3 * b.1 + c₂ * a.3 * b.2 - c₁ * a.4 * b.2, + a.1 * b.4 + a.2 * b.3 + c₂ * a.2 * b.4 - a.3 * b.2 + a.4 * b.1⟩⟩ @[simp] -theorem mul_re : (a * b).re = a.1 * b.1 + c₁ * a.2 * b.2 + c₂ * a.3 * b.3 - c₁ * c₂ * a.4 * b.4 := - rfl +theorem mul_re : (a * b).re = a.1 * b.1 + c₁ * a.2 * b.2 + c₃ * a.3 * b.3 + + c₂ * c₃ * a.3 * b.4 - c₁ * c₃ * a.4 * b.4 := rfl @[simp] -theorem mul_imI : (a * b).imI = a.1 * b.2 + a.2 * b.1 - c₂ * a.3 * b.4 + c₂ * a.4 * b.3 := rfl +theorem mul_imI : (a * b).imI = a.1 * b.2 + a.2 * b.1 + + c₂ * a.2 * b.2 - c₃ * a.3 * b.4 + c₃ * a.4 * b.3 := rfl @[simp] -theorem mul_imJ : (a * b).imJ = a.1 * b.3 + c₁ * a.2 * b.4 + a.3 * b.1 - c₁ * a.4 * b.2 := rfl +theorem mul_imJ : (a * b).imJ = a.1 * b.3 + c₁ * a.2 * b.4 + a.3 * b.1 + + c₂ * a.3 * b.2 - c₁ * a.4 * b.2 := rfl -@[simp] theorem mul_imK : (a * b).imK = a.1 * b.4 + a.2 * b.3 - a.3 * b.2 + a.4 * b.1 := rfl +@[simp] +theorem mul_imK : (a * b).imK = a.1 * b.4 + a.2 * b.3 + + c₂ * a.2 * b.4 - a.3 * b.2 + a.4 * b.1 := rfl @[simp] theorem mk_mul_mk (a₁ a₂ a₃ a₄ b₁ b₂ b₃ b₄ : R) : - (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂]) * mk b₁ b₂ b₃ b₄ = - ⟨a₁ * b₁ + c₁ * a₂ * b₂ + c₂ * a₃ * b₃ - c₁ * c₂ * a₄ * b₄, - a₁ * b₂ + a₂ * b₁ - c₂ * a₃ * b₄ + c₂ * a₄ * b₃, - a₁ * b₃ + c₁ * a₂ * b₄ + a₃ * b₁ - c₁ * a₄ * b₂, a₁ * b₄ + a₂ * b₃ - a₃ * b₂ + a₄ * b₁⟩ := + (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂,c₃]) * mk b₁ b₂ b₃ b₄ = + mk + (a₁ * b₁ + c₁ * a₂ * b₂ + c₃ * a₃ * b₃ + c₂ * c₃ * a₃ * b₄ - c₁ * c₃ * a₄ * b₄) + (a₁ * b₂ + a₂ * b₁ + c₂ * a₂ * b₂ - c₃ * a₃ * b₄ + c₃ * a₄ * b₃) + (a₁ * b₃ + c₁ * a₂ * b₄ + a₃ * b₁ + c₂ * a₃ * b₂ - c₁ * a₄ * b₂) + (a₁ * b₄ + a₂ * b₃ + c₂ * a₂ * b₄ - a₃ * b₂ + a₄ * b₁) := rfl end Ring @@ -331,12 +348,12 @@ section SMul variable [SMul S R] [SMul T R] (s : S) -instance : SMul S ℍ[R,c₁,c₂] where smul s a := ⟨s • a.1, s • a.2, s • a.3, s • a.4⟩ +instance : SMul S ℍ[R,c₁,c₂,c₃] where smul s a := ⟨s • a.1, s • a.2, s • a.3, s • a.4⟩ -instance [SMul S T] [IsScalarTower S T R] : IsScalarTower S T ℍ[R,c₁,c₂] where +instance [SMul S T] [IsScalarTower S T R] : IsScalarTower S T ℍ[R,c₁,c₂,c₃] where smul_assoc s t x := by ext <;> exact smul_assoc _ _ _ -instance [SMulCommClass S T R] : SMulCommClass S T ℍ[R,c₁,c₂] where +instance [SMulCommClass S T R] : SMulCommClass S T ℍ[R,c₁,c₂,c₃] where smul_comm s t x := by ext <;> exact smul_comm _ _ _ @[simp] theorem smul_re : (s • a).re = s • a.re := rfl @@ -352,112 +369,127 @@ instance [SMulCommClass S T R] : SMulCommClass S T ℍ[R,c₁,c₂] where @[simp] theorem smul_mk (re im_i im_j im_k : R) : - s • (⟨re, im_i, im_j, im_k⟩ : ℍ[R,c₁,c₂]) = ⟨s • re, s • im_i, s • im_j, s • im_k⟩ := + s • (⟨re, im_i, im_j, im_k⟩ : ℍ[R,c₁,c₂,c₃]) = ⟨s • re, s • im_i, s • im_j, s • im_k⟩ := rfl end SMul @[simp, norm_cast] theorem coe_smul [Zero R] [SMulZeroClass S R] (s : S) (r : R) : - (↑(s • r) : ℍ[R,c₁,c₂]) = s • (r : ℍ[R,c₁,c₂]) := - QuaternionAlgebra.ext rfl (smul_zero s).symm (smul_zero s).symm (smul_zero s).symm + (↑(s • r) : ℍ[R,c₁,c₂,c₃]) = s • (r : ℍ[R,c₁,c₂,c₃]) := + QuaternionAlgebra.ext rfl (smul_zero _).symm (smul_zero _).symm (smul_zero _).symm -instance [AddCommGroup R] : AddCommGroup ℍ[R,c₁,c₂] := - (equivProd c₁ c₂).injective.addCommGroup _ rfl (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) +instance [AddCommGroup R] : AddCommGroup ℍ[R,c₁,c₂,c₃] := + (equivProd c₁ c₂ c₃).injective.addCommGroup _ rfl (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) section AddCommGroupWithOne variable [AddCommGroupWithOne R] -instance : AddCommGroupWithOne ℍ[R,c₁,c₂] where - natCast n := ((n : R) : ℍ[R,c₁,c₂]) +instance : AddCommGroupWithOne ℍ[R,c₁,c₂,c₃] where + natCast n := ((n : R) : ℍ[R,c₁,c₂,c₃]) natCast_zero := by simp natCast_succ := by simp - intCast n := ((n : R) : ℍ[R,c₁,c₂]) + intCast n := ((n : R) : ℍ[R,c₁,c₂,c₃]) intCast_ofNat _ := congr_arg coe (Int.cast_natCast _) intCast_negSucc n := by change coe _ = -coe _ rw [Int.cast_negSucc, coe_neg] @[simp, norm_cast] -theorem natCast_re (n : ℕ) : (n : ℍ[R,c₁,c₂]).re = n := +theorem natCast_re (n : ℕ) : (n : ℍ[R,c₁,c₂,c₃]).re = n := rfl @[deprecated (since := "2024-04-17")] alias nat_cast_re := natCast_re @[simp, norm_cast] -theorem natCast_imI (n : ℕ) : (n : ℍ[R,c₁,c₂]).imI = 0 := +theorem natCast_imI (n : ℕ) : (n : ℍ[R,c₁,c₂,c₃]).imI = 0 := rfl @[deprecated (since := "2024-04-17")] alias nat_cast_imI := natCast_imI @[simp, norm_cast] -theorem natCast_imJ (n : ℕ) : (n : ℍ[R,c₁,c₂]).imJ = 0 := +theorem natCast_imJ (n : ℕ) : (n : ℍ[R,c₁,c₂,c₃]).imJ = 0 := rfl @[deprecated (since := "2024-04-17")] alias nat_cast_imJ := natCast_imJ @[simp, norm_cast] -theorem natCast_imK (n : ℕ) : (n : ℍ[R,c₁,c₂]).imK = 0 := +theorem natCast_imK (n : ℕ) : (n : ℍ[R,c₁,c₂,c₃]).imK = 0 := rfl @[deprecated (since := "2024-04-17")] alias nat_cast_imK := natCast_imK @[simp, norm_cast] -theorem natCast_im (n : ℕ) : (n : ℍ[R,c₁,c₂]).im = 0 := +theorem natCast_im (n : ℕ) : (n : ℍ[R,c₁,c₂,c₃]).im = 0 := rfl @[deprecated (since := "2024-04-17")] alias nat_cast_im := natCast_im @[norm_cast] -theorem coe_natCast (n : ℕ) : ↑(n : R) = (n : ℍ[R,c₁,c₂]) := +theorem coe_natCast (n : ℕ) : ↑(n : R) = (n : ℍ[R,c₁,c₂,c₃]) := rfl @[deprecated (since := "2024-04-17")] alias coe_nat_cast := coe_natCast @[simp, norm_cast] -theorem intCast_re (z : ℤ) : (z : ℍ[R,c₁,c₂]).re = z := +theorem intCast_re (z : ℤ) : (z : ℍ[R,c₁,c₂,c₃]).re = z := rfl +@[simp] +theorem ofNat_re (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : ℍ[R,c₁,c₂,c₃]).re = ofNat(n) := rfl + +@[simp] +theorem ofNat_imI (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : ℍ[R,c₁,c₂,c₃]).imI = 0 := rfl + +@[simp] +theorem ofNat_imJ (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : ℍ[R,c₁,c₂,c₃]).imJ = 0 := rfl + +@[simp] +theorem ofNat_imK (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : ℍ[R,c₁,c₂,c₃]).imK = 0 := rfl + +@[simp] +theorem ofNat_im (n : ℕ) [n.AtLeastTwo] : (ofNat(n) : ℍ[R,c₁,c₂,c₃]).im = 0 := rfl + @[deprecated (since := "2024-04-17")] alias int_cast_re := intCast_re @[simp, norm_cast] -theorem intCast_imI (z : ℤ) : (z : ℍ[R,c₁,c₂]).imI = 0 := +theorem intCast_imI (z : ℤ) : (z : ℍ[R,c₁,c₂,c₃]).imI = 0 := rfl @[deprecated (since := "2024-04-17")] alias int_cast_imI := intCast_imI @[simp, norm_cast] -theorem intCast_imJ (z : ℤ) : (z : ℍ[R,c₁,c₂]).imJ = 0 := +theorem intCast_imJ (z : ℤ) : (z : ℍ[R,c₁,c₂,c₃]).imJ = 0 := rfl @[deprecated (since := "2024-04-17")] alias int_cast_imJ := intCast_imJ @[simp, norm_cast] -theorem intCast_imK (z : ℤ) : (z : ℍ[R,c₁,c₂]).imK = 0 := +theorem intCast_imK (z : ℤ) : (z : ℍ[R,c₁,c₂,c₃]).imK = 0 := rfl @[deprecated (since := "2024-04-17")] alias int_cast_imK := intCast_imK @[simp, norm_cast] -theorem intCast_im (z : ℤ) : (z : ℍ[R,c₁,c₂]).im = 0 := +theorem intCast_im (z : ℤ) : (z : ℍ[R,c₁,c₂,c₃]).im = 0 := rfl @[deprecated (since := "2024-04-17")] alias int_cast_im := intCast_im @[norm_cast] -theorem coe_intCast (z : ℤ) : ↑(z : R) = (z : ℍ[R,c₁,c₂]) := +theorem coe_intCast (z : ℤ) : ↑(z : R) = (z : ℍ[R,c₁,c₂,c₃]) := rfl @[deprecated (since := "2024-04-17")] @@ -468,8 +500,8 @@ end AddCommGroupWithOne -- For the remainder of the file we assume `CommRing R`. variable [CommRing R] -instance instRing : Ring ℍ[R,c₁,c₂] where - __ := inferInstanceAs (AddCommGroupWithOne ℍ[R,c₁,c₂]) +instance instRing : Ring ℍ[R,c₁,c₂,c₃] where + __ := inferInstanceAs (AddCommGroupWithOne ℍ[R,c₁,c₂,c₃]) left_distrib _ _ _ := by ext <;> simp <;> ring right_distrib _ _ _ := by ext <;> simp <;> ring zero_mul _ := by ext <;> simp @@ -479,11 +511,16 @@ instance instRing : Ring ℍ[R,c₁,c₂] where mul_one _ := by ext <;> simp @[norm_cast, simp] -theorem coe_mul : ((x * y : R) : ℍ[R,c₁,c₂]) = x * y := by ext <;> simp +theorem coe_mul : ((x * y : R) : ℍ[R,c₁,c₂,c₃]) = x * y := by ext <;> simp + +@[norm_cast, simp] +lemma coe_ofNat {n : ℕ} [n.AtLeastTwo]: + ((ofNat(n) : R) : ℍ[R,c₁,c₂,c₃]) = (ofNat(n) : ℍ[R,c₁,c₂,c₃]) := by + rfl -- TODO: add weaker `MulAction`, `DistribMulAction`, and `Module` instances (and repeat them -- for `ℍ[R]`) -instance [CommSemiring S] [Algebra S R] : Algebra S ℍ[R,c₁,c₂] where +instance [CommSemiring S] [Algebra S R] : Algebra S ℍ[R,c₁,c₂,c₃] where smul := (· • ·) algebraMap := { toFun s := coe (algebraMap S R s) @@ -494,13 +531,13 @@ instance [CommSemiring S] [Algebra S R] : Algebra S ℍ[R,c₁,c₂] where smul_def' s x := by ext <;> simp [Algebra.smul_def] commutes' s x := by ext <;> simp [Algebra.commutes] -theorem algebraMap_eq (r : R) : algebraMap R ℍ[R,c₁,c₂] r = ⟨r, 0, 0, 0⟩ := +theorem algebraMap_eq (r : R) : algebraMap R ℍ[R,c₁,c₂,c₃] r = ⟨r, 0, 0, 0⟩ := rfl -theorem algebraMap_injective : (algebraMap R ℍ[R,c₁,c₂] : _ → _).Injective := +theorem algebraMap_injective : (algebraMap R ℍ[R,c₁,c₂,c₃] : _ → _).Injective := fun _ _ ↦ by simp [algebraMap_eq] -instance [NoZeroDivisors R] : NoZeroSMulDivisors R ℍ[R,c₁,c₂] := ⟨by +instance [NoZeroDivisors R] : NoZeroSMulDivisors R ℍ[R,c₁,c₂,c₃] := ⟨by rintro t ⟨a, b, c, d⟩ h rw [or_iff_not_imp_left] intro ht @@ -508,97 +545,94 @@ instance [NoZeroDivisors R] : NoZeroSMulDivisors R ℍ[R,c₁,c₂] := ⟨by section -variable (c₁ c₂) +variable (c₁ c₂ c₃) /-- `QuaternionAlgebra.re` as a `LinearMap`-/ @[simps] -def reₗ : ℍ[R,c₁,c₂] →ₗ[R] R where +def reₗ : ℍ[R,c₁,c₂,c₃] →ₗ[R] R where toFun := re map_add' _ _ := rfl map_smul' _ _ := rfl /-- `QuaternionAlgebra.imI` as a `LinearMap`-/ @[simps] -def imIₗ : ℍ[R,c₁,c₂] →ₗ[R] R where +def imIₗ : ℍ[R,c₁,c₂,c₃] →ₗ[R] R where toFun := imI map_add' _ _ := rfl map_smul' _ _ := rfl /-- `QuaternionAlgebra.imJ` as a `LinearMap`-/ @[simps] -def imJₗ : ℍ[R,c₁,c₂] →ₗ[R] R where +def imJₗ : ℍ[R,c₁,c₂,c₃] →ₗ[R] R where toFun := imJ map_add' _ _ := rfl map_smul' _ _ := rfl /-- `QuaternionAlgebra.imK` as a `LinearMap`-/ @[simps] -def imKₗ : ℍ[R,c₁,c₂] →ₗ[R] R where +def imKₗ : ℍ[R,c₁,c₂,c₃] →ₗ[R] R where toFun := imK map_add' _ _ := rfl map_smul' _ _ := rfl /-- `QuaternionAlgebra.equivTuple` as a linear equivalence. -/ -def linearEquivTuple : ℍ[R,c₁,c₂] ≃ₗ[R] Fin 4 → R := +def linearEquivTuple : ℍ[R,c₁,c₂,c₃] ≃ₗ[R] Fin 4 → R := LinearEquiv.symm -- proofs are not `rfl` in the forward direction - { (equivTuple c₁ c₂).symm with - toFun := (equivTuple c₁ c₂).symm - invFun := equivTuple c₁ c₂ + { (equivTuple c₁ c₂ c₃).symm with + toFun := (equivTuple c₁ c₂ c₃).symm + invFun := equivTuple c₁ c₂ c₃ map_add' := fun _ _ => rfl map_smul' := fun _ _ => rfl } @[simp] -theorem coe_linearEquivTuple : ⇑(linearEquivTuple c₁ c₂) = equivTuple c₁ c₂ := - rfl +theorem coe_linearEquivTuple : + ⇑(linearEquivTuple c₁ c₂ c₃) = equivTuple c₁ c₂ c₃ := rfl @[simp] -theorem coe_linearEquivTuple_symm : ⇑(linearEquivTuple c₁ c₂).symm = (equivTuple c₁ c₂).symm := - rfl +theorem coe_linearEquivTuple_symm : + ⇑(linearEquivTuple c₁ c₂ c₃).symm = (equivTuple c₁ c₂ c₃).symm := rfl -/-- `ℍ[R, c₁, c₂]` has a basis over `R` given by `1`, `i`, `j`, and `k`. -/ -noncomputable def basisOneIJK : Basis (Fin 4) R ℍ[R,c₁,c₂] := - .ofEquivFun <| linearEquivTuple c₁ c₂ +/-- `ℍ[R, c₁, c₂, c₃]` has a basis over `R` given by `1`, `i`, `j`, and `k`. -/ +noncomputable def basisOneIJK : Basis (Fin 4) R ℍ[R,c₁,c₂,c₃] := + .ofEquivFun <| linearEquivTuple c₁ c₂ c₃ @[simp] -theorem coe_basisOneIJK_repr (q : ℍ[R,c₁,c₂]) : - ⇑((basisOneIJK c₁ c₂).repr q) = ![q.re, q.imI, q.imJ, q.imK] := +theorem coe_basisOneIJK_repr (q : ℍ[R,c₁,c₂,c₃]) : + ((basisOneIJK c₁ c₂ c₃).repr q) = ![q.re, q.imI, q.imJ, q.imK] := rfl -instance : Module.Finite R ℍ[R,c₁,c₂] := .of_basis (basisOneIJK c₁ c₂) +instance : Module.Finite R ℍ[R,c₁,c₂,c₃] := .of_basis (basisOneIJK c₁ c₂ c₃) -instance : Module.Free R ℍ[R,c₁,c₂] := .of_basis (basisOneIJK c₁ c₂) +instance : Module.Free R ℍ[R,c₁,c₂,c₃] := .of_basis (basisOneIJK c₁ c₂ c₃) -theorem rank_eq_four [StrongRankCondition R] : Module.rank R ℍ[R,c₁,c₂] = 4 := by - rw [rank_eq_card_basis (basisOneIJK c₁ c₂), Fintype.card_fin] +theorem rank_eq_four [StrongRankCondition R] : Module.rank R ℍ[R,c₁,c₂,c₃] = 4 := by + rw [rank_eq_card_basis (basisOneIJK c₁ c₂ c₃), Fintype.card_fin] norm_num -theorem finrank_eq_four [StrongRankCondition R] : Module.finrank R ℍ[R,c₁,c₂] = 4 := by +theorem finrank_eq_four [StrongRankCondition R] : Module.finrank R ℍ[R,c₁,c₂,c₃] = 4 := by rw [Module.finrank, rank_eq_four, Cardinal.toNat_ofNat] -/-- There is a natural equivalence when swapping the coefficients of a quaternion algebra. -/ +/-- There is a natural equivalence when swapping the first and third coefficients of a + quaternion algebra if `c₂` is 0. -/ @[simps] -def swapEquiv : ℍ[R,c₁,c₂] ≃ₐ[R] ℍ[R, c₂, c₁] where +def swapEquiv : ℍ[R,c₁,0,c₃] ≃ₐ[R] ℍ[R,c₃,0,c₁] where toFun t := ⟨t.1, t.3, t.2, -t.4⟩ invFun t := ⟨t.1, t.3, t.2, -t.4⟩ left_inv _ := by simp right_inv _ := by simp - map_mul' _ _ := by - ext - <;> simp only [mul_re, mul_imJ, mul_imI, add_left_inj, mul_imK, neg_mul, neg_add_rev, - neg_sub, mk_mul_mk, mul_neg, neg_neg, sub_neg_eq_add] - <;> ring + map_mul' _ _ := by ext <;> simp <;> ring map_add' _ _ := by ext <;> simp [add_comm] commutes' _ := by simp [algebraMap_eq] end @[norm_cast, simp] -theorem coe_sub : ((x - y : R) : ℍ[R,c₁,c₂]) = x - y := - (algebraMap R ℍ[R,c₁,c₂]).map_sub x y +theorem coe_sub : ((x - y : R) : ℍ[R,c₁,c₂,c₃]) = x - y := + (algebraMap R ℍ[R,c₁,c₂,c₃]).map_sub x y @[norm_cast, simp] -theorem coe_pow (n : ℕ) : (↑(x ^ n) : ℍ[R,c₁,c₂]) = (x : ℍ[R,c₁,c₂]) ^ n := - (algebraMap R ℍ[R,c₁,c₂]).map_pow x n +theorem coe_pow (n : ℕ) : (↑(x ^ n) : ℍ[R,c₁,c₂,c₃]) = (x : ℍ[R,c₁,c₂,c₃]) ^ n := + (algebraMap R ℍ[R,c₁,c₂,c₃]).map_pow x n theorem coe_commutes : ↑r * a = a * r := Algebra.commutes r a @@ -612,15 +646,16 @@ theorem coe_mul_eq_smul : ↑r * a = r • a := theorem mul_coe_eq_smul : a * r = r • a := by rw [← coe_commutes, coe_mul_eq_smul] @[norm_cast, simp] -theorem coe_algebraMap : ⇑(algebraMap R ℍ[R,c₁,c₂]) = coe := +theorem coe_algebraMap : ⇑(algebraMap R ℍ[R,c₁,c₂,c₃]) = coe := rfl -theorem smul_coe : x • (y : ℍ[R,c₁,c₂]) = ↑(x * y) := by rw [coe_mul, coe_mul_eq_smul] +theorem smul_coe : x • (y : ℍ[R,c₁,c₂,c₃]) = ↑(x * y) := by rw [coe_mul, coe_mul_eq_smul] /-- Quaternion conjugate. -/ -instance instStarQuaternionAlgebra : Star ℍ[R,c₁,c₂] where star a := ⟨a.1, -a.2, -a.3, -a.4⟩ +instance instStarQuaternionAlgebra : Star ℍ[R,c₁,c₂,c₃] where star a := + ⟨a.1 + c₂ * a.2, -a.2, -a.3, -a.4⟩ -@[simp] theorem re_star : (star a).re = a.re := rfl +@[simp] theorem re_star : (star a).re = a.re + c₂ * a.imI := rfl @[simp] theorem imI_star : (star a).imI = -a.imI := @@ -639,44 +674,54 @@ theorem im_star : (star a).im = -a.im := QuaternionAlgebra.ext neg_zero.symm rfl rfl rfl @[simp] -theorem star_mk (a₁ a₂ a₃ a₄ : R) : star (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂]) = ⟨a₁, -a₂, -a₃, -a₄⟩ := - rfl +theorem star_mk (a₁ a₂ a₃ a₄ : R) : star (mk a₁ a₂ a₃ a₄ : ℍ[R,c₁,c₂,c₃]) = + ⟨a₁ + c₂ * a₂, -a₂, -a₃, -a₄⟩ := rfl -instance instStarRing : StarRing ℍ[R,c₁,c₂] where +instance instStarRing : StarRing ℍ[R,c₁,c₂,c₃] where star_involutive x := by simp [Star.star] - star_add a b := by ext <;> simp [add_comm] + star_add a b := by ext <;> simp [add_comm] ; ring star_mul a b := by ext <;> simp <;> ring -theorem self_add_star' : a + star a = ↑(2 * a.re) := by ext <;> simp [two_mul] +theorem self_add_star' : a + star a = ↑(2 * a.re + c₂ * a.imI) := by ext <;> simp [two_mul]; ring -theorem self_add_star : a + star a = 2 * a.re := by simp only [self_add_star', two_mul, coe_add] +theorem self_add_star : a + star a = 2 * a.re + c₂ * a.imI := by simp [self_add_star'] -theorem star_add_self' : star a + a = ↑(2 * a.re) := by rw [add_comm, self_add_star'] +theorem star_add_self' : star a + a = ↑(2 * a.re + c₂ * a.imI) := by rw [add_comm, self_add_star'] -theorem star_add_self : star a + a = 2 * a.re := by rw [add_comm, self_add_star] +theorem star_add_self : star a + a = 2 * a.re + c₂ * a.imI := by rw [add_comm, self_add_star] -theorem star_eq_two_re_sub : star a = ↑(2 * a.re) - a := +theorem star_eq_two_re_sub : star a = ↑(2 * a.re + c₂ * a.imI) - a := eq_sub_iff_add_eq.2 a.star_add_self' +lemma comm (r : R) (x : ℍ[R, c₁, c₂, c₃]) : r * x = x * r := by + ext <;> simp [mul_comm] + instance : IsStarNormal a := ⟨by - rw [a.star_eq_two_re_sub] - exact (coe_commute (2 * a.re) a).sub_left (Commute.refl a)⟩ + rw [commute_iff_eq, a.star_eq_two_re_sub]; + ext <;> simp <;> ring⟩ @[simp, norm_cast] -theorem star_coe : star (x : ℍ[R,c₁,c₂]) = x := by ext <;> simp +theorem star_coe : star (x : ℍ[R,c₁,c₂,c₃]) = x := by ext <;> simp -@[simp] theorem star_im : star a.im = -a.im := im_star _ +@[simp] theorem star_im : star a.im = -a.im + c₂ * a.imI := by ext <;> simp @[simp] -theorem star_smul [Monoid S] [DistribMulAction S R] (s : S) (a : ℍ[R,c₁,c₂]) : +theorem star_smul [Monoid S] [DistribMulAction S R] [SMulCommClass S R R] + (s : S) (a : ℍ[R,c₁,c₂,c₃]) : + star (s • a) = s • star a := + QuaternionAlgebra.ext + (by simp [mul_smul_comm]) (smul_neg _ _).symm (smul_neg _ _).symm (smul_neg _ _).symm + +/-- A version of `star_smul` for the special case when `c₂ = 0`, without `SMulCommClass S R R`. -/ +theorem star_smul' [Monoid S] [DistribMulAction S R] (s : S) (a : ℍ[R,c₁,0,c₃]) : star (s • a) = s • star a := - QuaternionAlgebra.ext rfl (smul_neg _ _).symm (smul_neg _ _).symm (smul_neg _ _).symm + QuaternionAlgebra.ext (by simp) (smul_neg _ _).symm (smul_neg _ _).symm (smul_neg _ _).symm -theorem eq_re_of_eq_coe {a : ℍ[R,c₁,c₂]} {x : R} (h : a = x) : a = a.re := by rw [h, coe_re] +theorem eq_re_of_eq_coe {a : ℍ[R,c₁,c₂,c₃]} {x : R} (h : a = x) : a = a.re := by rw [h, coe_re] -theorem eq_re_iff_mem_range_coe {a : ℍ[R,c₁,c₂]} : - a = a.re ↔ a ∈ Set.range (coe : R → ℍ[R,c₁,c₂]) := +theorem eq_re_iff_mem_range_coe {a : ℍ[R,c₁,c₂,c₃]} : + a = a.re ↔ a ∈ Set.range (coe : R → ℍ[R,c₁,c₂,c₃]) := ⟨fun h => ⟨a.re, h.symm⟩, fun ⟨_, h⟩ => eq_re_of_eq_coe h.symm⟩ section CharZero @@ -684,10 +729,10 @@ section CharZero variable [NoZeroDivisors R] [CharZero R] @[simp] -theorem star_eq_self {c₁ c₂ : R} {a : ℍ[R,c₁,c₂]} : star a = a ↔ a = a.re := by - simp [QuaternionAlgebra.ext_iff, neg_eq_iff_add_eq_zero, add_self_eq_zero] +theorem star_eq_self {c₁ c₂ : R} {a : ℍ[R,c₁,c₂,c₃]} : star a = a ↔ a = a.re := by + simp_all [QuaternionAlgebra.ext_iff, neg_eq_iff_add_eq_zero, add_self_eq_zero] -theorem star_eq_neg {c₁ c₂ : R} {a : ℍ[R,c₁,c₂]} : star a = -a ↔ a.re = 0 := by +theorem star_eq_neg {c₁ : R} {a : ℍ[R,c₁,0,c₃]} : star a = -a ↔ a.re = 0 := by simp [QuaternionAlgebra.ext_iff, eq_neg_iff_add_eq_zero] end CharZero @@ -702,7 +747,7 @@ theorem mul_star_eq_coe : a * star a = (a * star a).re := by open MulOpposite /-- Quaternion conjugate as an `AlgEquiv` to the opposite ring. -/ -def starAe : ℍ[R,c₁,c₂] ≃ₐ[R] ℍ[R,c₁,c₂]ᵐᵒᵖ := +def starAe : ℍ[R,c₁,c₂,c₃] ≃ₐ[R] ℍ[R,c₁,c₂,c₃]ᵐᵒᵖ := { starAddEquiv.trans opAddEquiv with toFun := op ∘ star invFun := star ∘ unop @@ -710,38 +755,40 @@ def starAe : ℍ[R,c₁,c₂] ≃ₐ[R] ℍ[R,c₁,c₂]ᵐᵒᵖ := commutes' := fun r => by simp } @[simp] -theorem coe_starAe : ⇑(starAe : ℍ[R,c₁,c₂] ≃ₐ[R] _) = op ∘ star := +theorem coe_starAe : ⇑(starAe : ℍ[R,c₁,c₂,c₃] ≃ₐ[R] _) = op ∘ star := rfl end QuaternionAlgebra /-- Space of quaternions over a type. Implemented as a structure with four fields: `re`, `im_i`, `im_j`, and `im_k`. -/ -def Quaternion (R : Type*) [One R] [Neg R] := - QuaternionAlgebra R (-1) (-1) +def Quaternion (R : Type*) [Zero R] [One R] [Neg R] := + QuaternionAlgebra R (-1) (0) (-1) @[inherit_doc] scoped[Quaternion] notation "ℍ[" R "]" => Quaternion R +open Quaternion + /-- The equivalence between the quaternions over `R` and `R × R × R × R`. -/ @[simps!] -def Quaternion.equivProd (R : Type*) [One R] [Neg R] : ℍ[R] ≃ R × R × R × R := - QuaternionAlgebra.equivProd _ _ +def Quaternion.equivProd (R : Type*) [Zero R] [One R] [Neg R] : ℍ[R] ≃ R × R × R × R := + QuaternionAlgebra.equivProd _ _ _ /-- The equivalence between the quaternions over `R` and `Fin 4 → R`. -/ @[simps! symm_apply] -def Quaternion.equivTuple (R : Type*) [One R] [Neg R] : ℍ[R] ≃ (Fin 4 → R) := - QuaternionAlgebra.equivTuple _ _ +def Quaternion.equivTuple (R : Type*) [Zero R] [One R] [Neg R] : ℍ[R] ≃ (Fin 4 → R) := + QuaternionAlgebra.equivTuple _ _ _ @[simp] -theorem Quaternion.equivTuple_apply (R : Type*) [One R] [Neg R] (x : ℍ[R]) : +theorem Quaternion.equivTuple_apply (R : Type*) [Zero R] [One R] [Neg R] (x : ℍ[R]) : Quaternion.equivTuple R x = ![x.re, x.imI, x.imJ, x.imK] := rfl -instance {R : Type*} [One R] [Neg R] [Subsingleton R] : Subsingleton ℍ[R] := - inferInstanceAs (Subsingleton <| ℍ[R, -1, -1]) -instance {R : Type*} [One R] [Neg R] [Nontrivial R] : Nontrivial ℍ[R] := - inferInstanceAs (Nontrivial <| ℍ[R, -1, -1]) +instance {R : Type*} [Zero R] [One R] [Neg R] [Subsingleton R] : Subsingleton ℍ[R] := + inferInstanceAs (Subsingleton <| ℍ[R, -1, 0, -1]) +instance {R : Type*} [Zero R] [One R] [Neg R] [Nontrivial R] : Nontrivial ℍ[R] := + inferInstanceAs (Nontrivial <| ℍ[R, -1, 0, -1]) namespace Quaternion @@ -754,23 +801,23 @@ instance : CoeTC R ℍ[R] := ⟨coe⟩ instance instRing : Ring ℍ[R] := QuaternionAlgebra.instRing -instance : Inhabited ℍ[R] := inferInstanceAs <| Inhabited ℍ[R,-1,-1] +instance : Inhabited ℍ[R] := inferInstanceAs <| Inhabited ℍ[R,-1, 0, -1] -instance [SMul S R] : SMul S ℍ[R] := inferInstanceAs <| SMul S ℍ[R,-1,-1] +instance [SMul S R] : SMul S ℍ[R] := inferInstanceAs <| SMul S ℍ[R,-1, 0, -1] instance [SMul S T] [SMul S R] [SMul T R] [IsScalarTower S T R] : IsScalarTower S T ℍ[R] := - inferInstanceAs <| IsScalarTower S T ℍ[R,-1,-1] + inferInstanceAs <| IsScalarTower S T ℍ[R,-1,0,-1] instance [SMul S R] [SMul T R] [SMulCommClass S T R] : SMulCommClass S T ℍ[R] := - inferInstanceAs <| SMulCommClass S T ℍ[R,-1,-1] + inferInstanceAs <| SMulCommClass S T ℍ[R,-1,0,-1] protected instance algebra [CommSemiring S] [Algebra S R] : Algebra S ℍ[R] := - inferInstanceAs <| Algebra S ℍ[R,-1,-1] + inferInstanceAs <| Algebra S ℍ[R,-1,0,-1] -- Porting note: added shortcut instance : Star ℍ[R] := QuaternionAlgebra.instStarQuaternionAlgebra instance : StarRing ℍ[R] := QuaternionAlgebra.instStarRing -instance : IsStarNormal a := inferInstanceAs <| IsStarNormal (R := ℍ[R,-1,-1]) a +instance : IsStarNormal a := inferInstanceAs <| IsStarNormal (R := ℍ[R,-1,0,-1]) a @[ext] theorem ext : a.re = b.re → a.imI = b.imI → a.imJ = b.imJ → a.imK = b.imK → a = b := @@ -880,19 +927,19 @@ theorem coe_sub : ((x - y : R) : ℍ[R]) = x - y := @[simp] theorem mul_re : (a * b).re = a.re * b.re - a.imI * b.imI - a.imJ * b.imJ - a.imK * b.imK := - (QuaternionAlgebra.mul_re a b).trans <| by simp only [one_mul, neg_mul, sub_eq_add_neg, neg_neg] + (QuaternionAlgebra.mul_re a b).trans <| by simp [one_mul, neg_mul, sub_eq_add_neg, neg_neg] @[simp] theorem mul_imI : (a * b).imI = a.re * b.imI + a.imI * b.re + a.imJ * b.imK - a.imK * b.imJ := - (QuaternionAlgebra.mul_imI a b).trans <| by simp only [one_mul, neg_mul, sub_eq_add_neg, neg_neg] + (QuaternionAlgebra.mul_imI a b).trans <| by ring @[simp] theorem mul_imJ : (a * b).imJ = a.re * b.imJ - a.imI * b.imK + a.imJ * b.re + a.imK * b.imI := - (QuaternionAlgebra.mul_imJ a b).trans <| by simp only [one_mul, neg_mul, sub_eq_add_neg, neg_neg] + (QuaternionAlgebra.mul_imJ a b).trans <| by ring @[simp] theorem mul_imK : (a * b).imK = a.re * b.imK + a.imI * b.imJ - a.imJ * b.imI + a.imK * b.re := - (QuaternionAlgebra.mul_imK a b).trans <| by simp only [one_mul, neg_mul, sub_eq_add_neg, neg_neg] + (QuaternionAlgebra.mul_imK a b).trans <| by ring @[simp, norm_cast] theorem coe_mul : ((x * y : R) : ℍ[R]) = x * y := QuaternionAlgebra.coe_mul x y @@ -1020,16 +1067,17 @@ theorem algebraMap_injective : (algebraMap R ℍ[R] : _ → _).Injective := theorem smul_coe : x • (y : ℍ[R]) = ↑(x * y) := QuaternionAlgebra.smul_coe x y -instance : Module.Finite R ℍ[R] := inferInstanceAs <| Module.Finite R ℍ[R,-1,-1] -instance : Module.Free R ℍ[R] := inferInstanceAs <| Module.Free R ℍ[R,-1,-1] +instance : Module.Finite R ℍ[R] := inferInstanceAs <| Module.Finite R ℍ[R,-1,0,-1] +instance : Module.Free R ℍ[R] := inferInstanceAs <| Module.Free R ℍ[R,-1,0,-1] theorem rank_eq_four [StrongRankCondition R] : Module.rank R ℍ[R] = 4 := - QuaternionAlgebra.rank_eq_four _ _ + QuaternionAlgebra.rank_eq_four _ _ _ theorem finrank_eq_four [StrongRankCondition R] : Module.finrank R ℍ[R] = 4 := - QuaternionAlgebra.finrank_eq_four _ _ + QuaternionAlgebra.finrank_eq_four _ _ _ -@[simp] theorem star_re : (star a).re = a.re := rfl +@[simp] theorem star_re : (star a).re = a.re := by + rw [QuaternionAlgebra.re_star, zero_mul, add_zero] @[simp] theorem star_imI : (star a).imI = -a.imI := rfl @@ -1039,33 +1087,31 @@ theorem finrank_eq_four [StrongRankCondition R] : Module.finrank R ℍ[R] = 4 := @[simp] theorem star_im : (star a).im = -a.im := a.im_star -nonrec theorem self_add_star' : a + star a = ↑(2 * a.re) := - a.self_add_star' +nonrec theorem self_add_star' : a + star a = ↑(2 * a.re) := by + simp [a.self_add_star', Quaternion.coe] -nonrec theorem self_add_star : a + star a = 2 * a.re := - a.self_add_star +nonrec theorem self_add_star : a + star a = 2 * a.re := by + simp [a.self_add_star, Quaternion.coe] -nonrec theorem star_add_self' : star a + a = ↑(2 * a.re) := - a.star_add_self' +nonrec theorem star_add_self' : star a + a = ↑(2 * a.re) := by + simp [a.star_add_self', Quaternion.coe] -nonrec theorem star_add_self : star a + a = 2 * a.re := - a.star_add_self +nonrec theorem star_add_self : star a + a = 2 * a.re := by + simp [a.star_add_self, Quaternion.coe] -nonrec theorem star_eq_two_re_sub : star a = ↑(2 * a.re) - a := - a.star_eq_two_re_sub +nonrec theorem star_eq_two_re_sub : star a = ↑(2 * a.re) - a := by + simp [a.star_eq_two_re_sub, Quaternion.coe] @[simp, norm_cast] theorem star_coe : star (x : ℍ[R]) = x := QuaternionAlgebra.star_coe x @[simp] -theorem im_star : star a.im = -a.im := - QuaternionAlgebra.im_star _ +theorem im_star : star a.im = -a.im := by ext <;> simp @[simp] theorem star_smul [Monoid S] [DistribMulAction S R] (s : S) (a : ℍ[R]) : - star (s • a) = s • star a := - QuaternionAlgebra.star_smul _ _ + star (s • a) = s • star a := QuaternionAlgebra.star_smul' s a theorem eq_re_of_eq_coe {a : ℍ[R]} {x : R} (h : a = x) : a = a.re := QuaternionAlgebra.eq_re_of_eq_coe h @@ -1308,34 +1354,34 @@ open Quaternion section QuaternionAlgebra -variable {R : Type*} (c₁ c₂ : R) +variable {R : Type*} (c₁ c₂ c₃ : R) private theorem pow_four [Infinite R] : #R ^ 4 = #R := power_nat_eq (aleph0_le_mk R) <| by decide /-- The cardinality of a quaternion algebra, as a type. -/ -theorem mk_quaternionAlgebra : #(ℍ[R,c₁,c₂]) = #R ^ 4 := by - rw [mk_congr (QuaternionAlgebra.equivProd c₁ c₂)] +theorem mk_quaternionAlgebra : #(ℍ[R,c₁,c₂,c₃]) = #R ^ 4 := by + rw [mk_congr (QuaternionAlgebra.equivProd c₁ c₂ c₃)] simp only [mk_prod, lift_id] ring @[simp] -theorem mk_quaternionAlgebra_of_infinite [Infinite R] : #(ℍ[R,c₁,c₂]) = #R := by +theorem mk_quaternionAlgebra_of_infinite [Infinite R] : #(ℍ[R,c₁,c₂,c₃]) = #R := by rw [mk_quaternionAlgebra, pow_four] /-- The cardinality of a quaternion algebra, as a set. -/ -theorem mk_univ_quaternionAlgebra : #(Set.univ : Set ℍ[R,c₁,c₂]) = #R ^ 4 := by +theorem mk_univ_quaternionAlgebra : #(Set.univ : Set ℍ[R,c₁,c₂,c₃]) = #R ^ 4 := by rw [mk_univ, mk_quaternionAlgebra] theorem mk_univ_quaternionAlgebra_of_infinite [Infinite R] : - #(Set.univ : Set ℍ[R,c₁,c₂]) = #R := by rw [mk_univ_quaternionAlgebra, pow_four] + #(Set.univ : Set ℍ[R,c₁,c₂,c₃]) = #R := by rw [mk_univ_quaternionAlgebra, pow_four] /-- Show the quaternion ⟨w, x, y, z⟩ as a string "{ re := w, imI := x, imJ := y, imK := z }". For the typical case of quaternions over ℝ, each component will show as a Cauchy sequence due to the way Real numbers are represented. -/ -instance [Repr R] {a b : R} : Repr ℍ[R, a, b] where +instance [Repr R] {a b c : R} : Repr ℍ[R, a, b, c] where reprPrec q _ := s!"\{ re := {repr q.re}, imI := {repr q.imI}, imJ := {repr q.imJ}, imK := {repr q.imK} }" @@ -1343,22 +1389,22 @@ end QuaternionAlgebra section Quaternion -variable (R : Type*) [One R] [Neg R] +variable (R : Type*) [Zero R] [One R] [Neg R] /-- The cardinality of the quaternions, as a type. -/ @[simp] theorem mk_quaternion : #(ℍ[R]) = #R ^ 4 := - mk_quaternionAlgebra _ _ + mk_quaternionAlgebra _ _ _ theorem mk_quaternion_of_infinite [Infinite R] : #(ℍ[R]) = #R := - mk_quaternionAlgebra_of_infinite _ _ + mk_quaternionAlgebra_of_infinite _ _ _ /-- The cardinality of the quaternions, as a set. -/ theorem mk_univ_quaternion : #(Set.univ : Set ℍ[R]) = #R ^ 4 := - mk_univ_quaternionAlgebra _ _ + mk_univ_quaternionAlgebra _ _ _ theorem mk_univ_quaternion_of_infinite [Infinite R] : #(Set.univ : Set ℍ[R]) = #R := - mk_univ_quaternionAlgebra_of_infinite _ _ + mk_univ_quaternionAlgebra_of_infinite _ _ _ end Quaternion diff --git a/Mathlib/Algebra/QuaternionBasis.lean b/Mathlib/Algebra/QuaternionBasis.lean index 0bbcb83c8be73..9fcaf7da1c225 100644 --- a/Mathlib/Algebra/QuaternionBasis.lean +++ b/Mathlib/Algebra/QuaternionBasis.lean @@ -11,11 +11,11 @@ import Mathlib.Tactic.Ring ## Main definitions -* `QuaternionAlgebra.Basis A c₁ c₂`: a basis for a subspace of an `R`-algebra `A` that has the - same algebra structure as `ℍ[R,c₁,c₂]`. -* `QuaternionAlgebra.Basis.self R`: the canonical basis for `ℍ[R,c₁,c₂]`. +* `QuaternionAlgebra.Basis A c₁ c₂ c₃`: a basis for a subspace of an `R`-algebra `A` that has the + same algebra structure as `ℍ[R,c₁,c₂,c₃]`. +* `QuaternionAlgebra.Basis.self R`: the canonical basis for `ℍ[R,c₁,c₂,c₃]`. * `QuaternionAlgebra.Basis.compHom b f`: transform a basis `b` by an AlgHom `f`. -* `QuaternionAlgebra.lift`: Define an `AlgHom` out of `ℍ[R,c₁,c₂]` by its action on the basis +* `QuaternionAlgebra.lift`: Define an `AlgHom` out of `ℍ[R,c₁,c₂,c₃]` by its action on the basis elements `i`, `j`, and `k`. In essence, this is a universal property. Analogous to `Complex.lift`, but takes a bundled `QuaternionAlgebra.Basis` instead of just a `Subtype` as the amount of data / proves is non-negligible. @@ -27,26 +27,27 @@ open Quaternion namespace QuaternionAlgebra /-- A quaternion basis contains the information both sufficient and necessary to construct an -`R`-algebra homomorphism from `ℍ[R,c₁,c₂]` to `A`; or equivalently, a surjective -`R`-algebra homomorphism from `ℍ[R,c₁,c₂]` to an `R`-subalgebra of `A`. +`R`-algebra homomorphism from `ℍ[R,c₁,c₂,c₃]` to `A`; or equivalently, a surjective +`R`-algebra homomorphism from `ℍ[R,c₁,c₂,c₃]` to an `R`-subalgebra of `A`. Note that for definitional convenience, `k` is provided as a field even though `i_mul_j` fully determines it. -/ -structure Basis {R : Type*} (A : Type*) [CommRing R] [Ring A] [Algebra R A] (c₁ c₂ : R) where +structure Basis {R : Type*} (A : Type*) [CommRing R] [Ring A] [Algebra R A] (c₁ c₂ c₃ : R) where (i j k : A) - i_mul_i : i * i = c₁ • (1 : A) - j_mul_j : j * j = c₂ • (1 : A) + i_mul_i : i * i = c₁ • (1 : A) + c₂ • i + j_mul_j : j * j = c₃ • (1 : A) i_mul_j : i * j = k - j_mul_i : j * i = -k + j_mul_i : j * i = c₂ • j - k variable {R : Type*} {A B : Type*} [CommRing R] [Ring A] [Ring B] [Algebra R A] [Algebra R B] -variable {c₁ c₂ : R} +variable {c₁ c₂ c₃: R} namespace Basis /-- Since `k` is redundant, it is not necessary to show `q₁.k = q₂.k` when showing `q₁ = q₂`. -/ @[ext] -protected theorem ext ⦃q₁ q₂ : Basis A c₁ c₂⦄ (hi : q₁.i = q₂.i) (hj : q₁.j = q₂.j) : q₁ = q₂ := by +protected theorem ext ⦃q₁ q₂ : Basis A c₁ c₂ c₃⦄ (hi : q₁.i = q₂.i) + (hj : q₁.j = q₂.j) : q₁ = q₂ := by cases q₁; rename_i q₁_i_mul_j _ cases q₂; rename_i q₂_i_mul_j _ congr @@ -57,7 +58,7 @@ variable (R) /-- There is a natural quaternionic basis for the `QuaternionAlgebra`. -/ @[simps i j k] -protected def self : Basis ℍ[R,c₁,c₂] c₁ c₂ where +protected def self : Basis ℍ[R,c₁,c₂,c₃] c₁ c₂ c₃ where i := ⟨0, 1, 0, 0⟩ i_mul_i := by ext <;> simp j := ⟨0, 0, 1, 0⟩ @@ -68,64 +69,70 @@ protected def self : Basis ℍ[R,c₁,c₂] c₁ c₂ where variable {R} -instance : Inhabited (Basis ℍ[R,c₁,c₂] c₁ c₂) := +instance : Inhabited (Basis ℍ[R,c₁,c₂,c₃] c₁ c₂ c₃) := ⟨Basis.self R⟩ -variable (q : Basis A c₁ c₂) +variable (q : Basis A c₁ c₂ c₃) attribute [simp] i_mul_i j_mul_j i_mul_j j_mul_i @[simp] -theorem i_mul_k : q.i * q.k = c₁ • q.j := by - rw [← i_mul_j, ← mul_assoc, i_mul_i, smul_mul_assoc, one_mul] +theorem i_mul_k : q.i * q.k = c₁ • q.j + c₂ • q.k := by + rw [← i_mul_j, ← mul_assoc, i_mul_i, add_mul, smul_mul_assoc, one_mul, smul_mul_assoc] @[simp] theorem k_mul_i : q.k * q.i = -c₁ • q.j := by - rw [← i_mul_j, mul_assoc, j_mul_i, mul_neg, i_mul_k, neg_smul] + rw [← i_mul_j, mul_assoc, j_mul_i, mul_sub, i_mul_k, neg_smul, mul_smul_comm, i_mul_j] + linear_combination (norm := module) @[simp] -theorem k_mul_j : q.k * q.j = c₂ • q.i := by +theorem k_mul_j : q.k * q.j = c₃ • q.i := by rw [← i_mul_j, mul_assoc, j_mul_j, mul_smul_comm, mul_one] @[simp] -theorem j_mul_k : q.j * q.k = -c₂ • q.i := by - rw [← i_mul_j, ← mul_assoc, j_mul_i, neg_mul, k_mul_j, neg_smul] +theorem j_mul_k : q.j * q.k = (c₂ * c₃) • 1 - c₃ • q.i := by + rw [← i_mul_j, ← mul_assoc, j_mul_i, sub_mul, smul_mul_assoc, j_mul_j, ← smul_assoc, k_mul_j] + rfl @[simp] -theorem k_mul_k : q.k * q.k = -((c₁ * c₂) • (1 : A)) := by - rw [← i_mul_j, mul_assoc, ← mul_assoc q.j _ _, j_mul_i, ← i_mul_j, ← mul_assoc, mul_neg, ← - mul_assoc, i_mul_i, smul_mul_assoc, one_mul, neg_mul, smul_mul_assoc, j_mul_j, smul_smul] +theorem k_mul_k : q.k * q.k = -((c₁ * c₃) • (1 : A)) := by + rw [← i_mul_j, mul_assoc, ← mul_assoc q.j _ _, j_mul_i, ← i_mul_j, ← mul_assoc, mul_sub, ← + mul_assoc, i_mul_i, add_mul, smul_mul_assoc, one_mul, sub_mul, smul_mul_assoc, mul_smul_comm, + smul_mul_assoc, mul_assoc, j_mul_j, add_mul, smul_mul_assoc, j_mul_j, smul_smul, + smul_mul_assoc, mul_assoc, j_mul_j] + linear_combination (norm := module) + /-- Intermediate result used to define `QuaternionAlgebra.Basis.liftHom`. -/ -def lift (x : ℍ[R,c₁,c₂]) : A := +def lift (x : ℍ[R,c₁,c₂,c₃]) : A := algebraMap R _ x.re + x.imI • q.i + x.imJ • q.j + x.imK • q.k -theorem lift_zero : q.lift (0 : ℍ[R,c₁,c₂]) = 0 := by simp [lift] +theorem lift_zero : q.lift (0 : ℍ[R,c₁,c₂,c₃]) = 0 := by simp [lift] -theorem lift_one : q.lift (1 : ℍ[R,c₁,c₂]) = 1 := by simp [lift] +theorem lift_one : q.lift (1 : ℍ[R,c₁,c₂,c₃]) = 1 := by simp [lift] -theorem lift_add (x y : ℍ[R,c₁,c₂]) : q.lift (x + y) = q.lift x + q.lift y := by +theorem lift_add (x y : ℍ[R,c₁,c₂,c₃]) : q.lift (x + y) = q.lift x + q.lift y := by simp only [lift, add_re, map_add, add_imI, add_smul, add_imJ, add_imK] abel -theorem lift_mul (x y : ℍ[R,c₁,c₂]) : q.lift (x * y) = q.lift x * q.lift y := by +theorem lift_mul (x y : ℍ[R,c₁,c₂,c₃]) : q.lift (x * y) = q.lift x * q.lift y := by simp only [lift, Algebra.algebraMap_eq_smul_one] simp_rw [add_mul, mul_add, smul_mul_assoc, mul_smul_comm, one_mul, mul_one, smul_smul] simp only [i_mul_i, j_mul_j, i_mul_j, j_mul_i, i_mul_k, k_mul_i, k_mul_j, j_mul_k, k_mul_k] simp only [smul_smul, smul_neg, sub_eq_add_neg, add_smul, ← add_assoc, mul_neg, neg_smul] - simp only [mul_right_comm _ _ (c₁ * c₂), mul_comm _ (c₁ * c₂)] + simp only [mul_right_comm _ _ (c₁ * c₃), mul_comm _ (c₁ * c₃)] simp only [mul_comm _ c₁, mul_right_comm _ _ c₁] - simp only [mul_comm _ c₂, mul_right_comm _ _ c₂] + simp only [mul_comm _ c₂, mul_right_comm _ _ c₃] simp only [← mul_comm c₁ c₂, ← mul_assoc] simp only [mul_re, sub_eq_add_neg, add_smul, neg_smul, mul_imI, ← add_assoc, mul_imJ, mul_imK] - abel + linear_combination (norm := module) -theorem lift_smul (r : R) (x : ℍ[R,c₁,c₂]) : q.lift (r • x) = r • q.lift x := by +theorem lift_smul (r : R) (x : ℍ[R,c₁,c₂,c₃]) : q.lift (r • x) = r • q.lift x := by simp [lift, mul_smul, ← Algebra.smul_def] /-- A `QuaternionAlgebra.Basis` implies an `AlgHom` from the quaternions. -/ @[simps!] -def liftHom : ℍ[R,c₁,c₂] →ₐ[R] A := +def liftHom : ℍ[R,c₁,c₂,c₃] →ₐ[R] A := AlgHom.mk' { toFun := q.lift map_zero' := q.lift_zero @@ -135,20 +142,20 @@ def liftHom : ℍ[R,c₁,c₂] →ₐ[R] A := /-- Transform a `QuaternionAlgebra.Basis` through an `AlgHom`. -/ @[simps i j k] -def compHom (F : A →ₐ[R] B) : Basis B c₁ c₂ where +def compHom (F : A →ₐ[R] B) : Basis B c₁ c₂ c₃ where i := F q.i - i_mul_i := by rw [← map_mul, q.i_mul_i, map_smul, map_one] + i_mul_i := by rw [← map_mul, q.i_mul_i, map_add, map_smul, map_smul, map_one] j := F q.j j_mul_j := by rw [← map_mul, q.j_mul_j, map_smul, map_one] k := F q.k i_mul_j := by rw [← map_mul, q.i_mul_j] - j_mul_i := by rw [← map_mul, q.j_mul_i, map_neg] + j_mul_i := by rw [← map_mul, q.j_mul_i, map_sub, map_smul] end Basis /-- A quaternionic basis on `A` is equivalent to a map from the quaternion algebra to `A`. -/ @[simps] -def lift : Basis A c₁ c₂ ≃ (ℍ[R,c₁,c₂] →ₐ[R] A) where +def lift : Basis A c₁ c₂ c₃ ≃ (ℍ[R,c₁,c₂,c₃] →ₐ[R] A) where toFun := Basis.liftHom invFun := (Basis.self R).compHom left_inv q := by ext <;> simp [Basis.lift] @@ -162,7 +169,7 @@ def lift : Basis A c₁ c₂ ≃ (ℍ[R,c₁,c₂] →ₐ[R] A) where /-- Two `R`-algebra morphisms from a quaternion algebra are equal if they agree on `i` and `j`. -/ @[ext] -theorem hom_ext ⦃f g : ℍ[R,c₁,c₂] →ₐ[R] A⦄ +theorem hom_ext ⦃f g : ℍ[R,c₁,c₂,c₃] →ₐ[R] A⦄ (hi : f (Basis.self R).i = g (Basis.self R).i) (hj : f (Basis.self R).j = g (Basis.self R).j) : f = g := lift.symm.injective <| Basis.ext hi hj diff --git a/Mathlib/Analysis/Quaternion.lean b/Mathlib/Analysis/Quaternion.lean index 9f75be8137503..6c28375ee66a8 100644 --- a/Mathlib/Analysis/Quaternion.lean +++ b/Mathlib/Analysis/Quaternion.lean @@ -163,7 +163,7 @@ theorem norm_piLp_equiv_symm_equivTuple (x : ℍ) : /-- `QuaternionAlgebra.linearEquivTuple` as a `LinearIsometryEquiv`. -/ @[simps apply symm_apply] noncomputable def linearIsometryEquivTuple : ℍ ≃ₗᵢ[ℝ] EuclideanSpace ℝ (Fin 4) := - { (QuaternionAlgebra.linearEquivTuple (-1 : ℝ) (-1 : ℝ)).trans + { (QuaternionAlgebra.linearEquivTuple (-1 : ℝ) (0 : ℝ) (-1 : ℝ)).trans (WithLp.linearEquiv 2 ℝ (Fin 4 → ℝ)).symm with toFun := fun a => !₂[a.1, a.2, a.3, a.4] invFun := fun a => ⟨a 0, a 1, a 2, a 3⟩ @@ -209,13 +209,16 @@ variable {α : Type*} @[simp, norm_cast] theorem hasSum_coe {f : α → ℝ} {r : ℝ} : HasSum (fun a => (f a : ℍ)) (↑r : ℍ) ↔ HasSum f r := - ⟨fun h => by simpa only using h.map (show ℍ →ₗ[ℝ] ℝ from QuaternionAlgebra.reₗ _ _) continuous_re, + ⟨fun h => by + simpa only using + h.map (show ℍ →ₗ[ℝ] ℝ from QuaternionAlgebra.reₗ _ _ _) continuous_re, fun h => by simpa only using h.map (algebraMap ℝ ℍ) (continuous_algebraMap _ _)⟩ @[simp, norm_cast] theorem summable_coe {f : α → ℝ} : (Summable fun a => (f a : ℍ)) ↔ Summable f := by simpa only using - Summable.map_iff_of_leftInverse (algebraMap ℝ ℍ) (show ℍ →ₗ[ℝ] ℝ from QuaternionAlgebra.reₗ _ _) + Summable.map_iff_of_leftInverse (algebraMap ℝ ℍ) (show ℍ →ₗ[ℝ] ℝ from + QuaternionAlgebra.reₗ _ _ _) (continuous_algebraMap _ _) continuous_re coe_re @[norm_cast] diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean index 9abbbe4782efb..22f87694b197f 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean @@ -242,7 +242,7 @@ theorem Q_apply (v : R × R) : Q c₁ c₂ v = c₁ * (v.1 * v.1) + c₂ * (v.2 /-- The quaternion basis vectors within the algebra. -/ @[simps i j k] -def quaternionBasis : QuaternionAlgebra.Basis (CliffordAlgebra (Q c₁ c₂)) c₁ c₂ where +def quaternionBasis : QuaternionAlgebra.Basis (CliffordAlgebra (Q c₁ c₂)) c₁ 0 c₂ where i := ι (Q c₁ c₂) (1, 0) j := ι (Q c₁ c₂) (0, 1) k := ι (Q c₁ c₂) (1, 0) * ι (Q c₁ c₂) (0, 1) @@ -254,16 +254,16 @@ def quaternionBasis : QuaternionAlgebra.Basis (CliffordAlgebra (Q c₁ c₂)) c simp i_mul_j := rfl j_mul_i := by - rw [eq_neg_iff_add_eq_zero, ι_mul_ι_add_swap, QuadraticMap.polar] + rw [zero_smul, zero_sub, eq_neg_iff_add_eq_zero, ι_mul_ι_add_swap, QuadraticMap.polar] simp variable {c₁ c₂} /-- Intermediate result of `CliffordAlgebraQuaternion.equiv`: clifford algebras over `CliffordAlgebraQuaternion.Q` can be converted to `ℍ[R,c₁,c₂]`. -/ -def toQuaternion : CliffordAlgebra (Q c₁ c₂) →ₐ[R] ℍ[R,c₁,c₂] := +def toQuaternion : CliffordAlgebra (Q c₁ c₂) →ₐ[R] ℍ[R,c₁,0,c₂] := CliffordAlgebra.lift (Q c₁ c₂) - ⟨{ toFun := fun v => (⟨0, v.1, v.2, 0⟩ : ℍ[R,c₁,c₂]) + ⟨{ toFun := fun v => (⟨0, v.1, v.2, 0⟩ : ℍ[R,c₁,0,c₂]) map_add' := fun v₁ v₂ => by simp map_smul' := fun r v => by dsimp; rw [mul_zero] }, fun v => by dsimp @@ -272,7 +272,7 @@ def toQuaternion : CliffordAlgebra (Q c₁ c₂) →ₐ[R] ℍ[R,c₁,c₂] := @[simp] theorem toQuaternion_ι (v : R × R) : - toQuaternion (ι (Q c₁ c₂) v) = (⟨0, v.1, v.2, 0⟩ : ℍ[R,c₁,c₂]) := + toQuaternion (ι (Q c₁ c₂) v) = (⟨0, v.1, v.2, 0⟩ : ℍ[R,c₁,0,c₂]) := CliffordAlgebra.lift_ι_apply _ _ v /-- The "clifford conjugate" maps to the quaternion conjugate. -/ @@ -280,22 +280,18 @@ theorem toQuaternion_star (c : CliffordAlgebra (Q c₁ c₂)) : toQuaternion (star c) = star (toQuaternion c) := by simp only [CliffordAlgebra.star_def'] induction c using CliffordAlgebra.induction with - | algebraMap r => - simp only [reverse.commutes, AlgHom.commutes, QuaternionAlgebra.coe_algebraMap, - QuaternionAlgebra.star_coe] - | ι x => - rw [reverse_ι, involute_ι, toQuaternion_ι, map_neg, toQuaternion_ι, - QuaternionAlgebra.neg_mk, star_mk, neg_zero] - | mul x₁ x₂ hx₁ hx₂ => simp only [reverse.map_mul, map_mul, hx₁, hx₂, star_mul] - | add x₁ x₂ hx₁ hx₂ => simp only [reverse.map_add, map_add, hx₁, hx₂, star_add] + | algebraMap r => simp + | ι x => simp + | mul x₁ x₂ hx₁ hx₂ => simp [hx₁, hx₂] + | add x₁ x₂ hx₁ hx₂ => simp [hx₁, hx₂] /-- Map a quaternion into the clifford algebra. -/ -def ofQuaternion : ℍ[R,c₁,c₂] →ₐ[R] CliffordAlgebra (Q c₁ c₂) := +def ofQuaternion : ℍ[R,c₁,0,c₂] →ₐ[R] CliffordAlgebra (Q c₁ c₂) := (quaternionBasis c₁ c₂).liftHom @[simp] theorem ofQuaternion_mk (a₁ a₂ a₃ a₄ : R) : - ofQuaternion (⟨a₁, a₂, a₃, a₄⟩ : ℍ[R,c₁,c₂]) = + ofQuaternion (⟨a₁, a₂, a₃, a₄⟩ : ℍ[R,c₁,0,c₂]) = algebraMap R _ a₁ + a₂ • ι (Q c₁ c₂) (1, 0) + a₃ • ι (Q c₁ c₂) (0, 1) + a₄ • (ι (Q c₁ c₂) (1, 0) * ι (Q c₁ c₂) (0, 1)) := rfl @@ -319,23 +315,23 @@ theorem ofQuaternion_toQuaternion (c : CliffordAlgebra (Q c₁ c₂)) : @[simp] theorem toQuaternion_comp_ofQuaternion : - toQuaternion.comp ofQuaternion = AlgHom.id R ℍ[R,c₁,c₂] := by + toQuaternion.comp ofQuaternion = AlgHom.id R ℍ[R,c₁,0,c₂] := by ext : 1 <;> simp @[simp] -theorem toQuaternion_ofQuaternion (q : ℍ[R,c₁,c₂]) : toQuaternion (ofQuaternion q) = q := +theorem toQuaternion_ofQuaternion (q : ℍ[R,c₁,0,c₂]) : toQuaternion (ofQuaternion q) = q := AlgHom.congr_fun toQuaternion_comp_ofQuaternion q /-- The clifford algebra over `CliffordAlgebraQuaternion.Q c₁ c₂` is isomorphic as an `R`-algebra to `ℍ[R,c₁,c₂]`. -/ @[simps!] -protected def equiv : CliffordAlgebra (Q c₁ c₂) ≃ₐ[R] ℍ[R,c₁,c₂] := +protected def equiv : CliffordAlgebra (Q c₁ c₂) ≃ₐ[R] ℍ[R,c₁,0,c₂] := AlgEquiv.ofAlgHom toQuaternion ofQuaternion toQuaternion_comp_ofQuaternion ofQuaternion_comp_toQuaternion /-- The quaternion conjugate maps to the "clifford conjugate" (aka `star`). -/ @[simp] -theorem ofQuaternion_star (q : ℍ[R,c₁,c₂]) : ofQuaternion (star q) = star (ofQuaternion q) := +theorem ofQuaternion_star (q : ℍ[R,c₁,0,c₂]) : ofQuaternion (star q) = star (ofQuaternion q) := CliffordAlgebraQuaternion.equiv.injective <| by rw [equiv_apply, equiv_apply, toQuaternion_star, toQuaternion_ofQuaternion, toQuaternion_ofQuaternion] From 130893c2a72a4d7fc195ecbde519de2e0f99c69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 24 Jan 2025 05:43:16 +0000 Subject: [PATCH 469/681] feat: split a set in the prime spectrum of `R[X]` into its localization away from `c : R` and quotient by `c` parts (#20303) From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang --- Mathlib/Data/Set/Image.lean | 7 +++++ .../RingTheory/Spectrum/Prime/Topology.lean | 28 +++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Mathlib/Data/Set/Image.lean b/Mathlib/Data/Set/Image.lean index a36c4d6171444..ac85ff8a86b20 100644 --- a/Mathlib/Data/Set/Image.lean +++ b/Mathlib/Data/Set/Image.lean @@ -974,6 +974,13 @@ theorem range_some_union_none (α : Type*) : range (some : α → Option α) ∪ theorem insert_none_range_some (α : Type*) : insert none (range (some : α → Option α)) = univ := (isCompl_range_some_none α).symm.sup_eq_top +lemma image_of_range_union_range_eq_univ {α β γ γ' δ δ' : Type*} + {h : β → α} {f : γ → β} {f₁ : γ' → α} {f₂ : γ → γ'} {g : δ → β} {g₁ : δ' → α} {g₂ : δ → δ'} + (hf : h ∘ f = f₁ ∘ f₂) (hg : h ∘ g = g₁ ∘ g₂) (hfg : range f ∪ range g = univ) (s : Set β) : + h '' s = f₁ '' (f₂ '' (f ⁻¹' s)) ∪ g₁ '' (g₂ '' (g ⁻¹' s)) := by + rw [← image_comp, ← image_comp, ← hf, ← hg, image_comp, image_comp, image_preimage_eq_inter_range, + image_preimage_eq_inter_range, ← image_union, ← inter_union_distrib_left, hfg, inter_univ] + end Range section Subsingleton diff --git a/Mathlib/RingTheory/Spectrum/Prime/Topology.lean b/Mathlib/RingTheory/Spectrum/Prime/Topology.lean index 818c5fbc7a98f..52f45bb237367 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Topology.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Topology.lean @@ -9,6 +9,7 @@ import Mathlib.RingTheory.Ideal.Over import Mathlib.RingTheory.KrullDimension.Basic import Mathlib.RingTheory.LocalRing.ResidueField.Defs import Mathlib.RingTheory.LocalRing.RingHom.Basic +import Mathlib.RingTheory.Localization.Algebra import Mathlib.RingTheory.Localization.Away.Basic import Mathlib.RingTheory.Localization.Ideal import Mathlib.RingTheory.Spectrum.Maximal.Localization @@ -41,7 +42,7 @@ variable (R : Type u) (S : Type v) namespace PrimeSpectrum -section CommSemiRing +section CommSemiring variable [CommSemiring R] [CommSemiring S] variable {R S} @@ -258,6 +259,10 @@ def comap (f : R →+* S) : C(PrimeSpectrum S, PrimeSpectrum R) where rintro _ ⟨s, rfl⟩ exact ⟨_, preimage_specComap_zeroLocus_aux f s⟩ +lemma coe_comap (f : R →+* S) : comap f = f.specComap := rfl + +lemma comap_apply (f : R →+* S) (x) : comap f x = f.specComap x := rfl + variable (f : R →+* S) @[simp] @@ -354,9 +359,8 @@ theorem comap_isInducing_of_surjective (hf : Surjective f) : IsInducing (comap f @[deprecated (since := "2024-10-28")] alias comap_inducing_of_surjective := comap_isInducing_of_surjective - end Comap -end CommSemiRing +end CommSemiring section SpecOfSurjective @@ -432,7 +436,7 @@ def primeSpectrumProdHomeo : end SpecProd -section CommSemiRing +section CommSemiring variable [CommSemiring R] [CommSemiring S] variable {R S} @@ -571,6 +575,20 @@ theorem isLocalization_away_iff_atPrime_of_basicOpen_eq_singleton [Algebra R S] exact not_not.mpr (q.span_singleton_le_iff_mem.mp le) IsLocalization.isLocalization_iff_of_isLocalization _ _ (Localization.Away f) +open Localization Polynomial Set in +lemma range_comap_algebraMap_localization_compl_eq_range_comap_quotientMk + {R : Type*} [CommRing R] (c : R) : + letI := (mapRingHom (algebraMap R (Away c))).toAlgebra + (range (comap (algebraMap R[X] (Away c)[X])))ᶜ + = range (comap (mapRingHom (Ideal.Quotient.mk (.span {c})))) := by + letI := (mapRingHom (algebraMap R (Away c))).toAlgebra + have := Polynomial.isLocalization (.powers c) (Away c) + rw [Submonoid.map_powers] at this + have surj : Function.Surjective (mapRingHom (Ideal.Quotient.mk (.span {c}))) := + Polynomial.map_surjective _ Ideal.Quotient.mk_surjective + rw [range_comap_of_surjective _ _ surj, localization_away_comap_range _ (C c)] + simp [Polynomial.ker_mapRingHom, Ideal.map_span] + end BasicOpen section DiscreteTopology @@ -950,7 +968,7 @@ def primeSpectrum_unique_of_localization_at_minimal (h : I ∈ minimalPrimes R) end LocalizationAtMinimal -end CommSemiRing +end CommSemiring end PrimeSpectrum From 5fb85e0f4821f65b24314b64c00db24605b30438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 24 Jan 2025 06:06:32 +0000 Subject: [PATCH 470/681] feat: constructible sets in the prime spectrum (#20274) Provide tooling for manipulating constructible sets in the prime spectrum of a ring. From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang --- Mathlib.lean | 1 + .../Spectrum/Prime/ConstructibleSet.lean | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 Mathlib/RingTheory/Spectrum/Prime/ConstructibleSet.lean diff --git a/Mathlib.lean b/Mathlib.lean index a52a1a217b2d0..44d7671ebde7d 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4751,6 +4751,7 @@ import Mathlib.RingTheory.Spectrum.Maximal.Defs import Mathlib.RingTheory.Spectrum.Maximal.Localization import Mathlib.RingTheory.Spectrum.Maximal.Topology import Mathlib.RingTheory.Spectrum.Prime.Basic +import Mathlib.RingTheory.Spectrum.Prime.ConstructibleSet import Mathlib.RingTheory.Spectrum.Prime.Defs import Mathlib.RingTheory.Spectrum.Prime.FreeLocus import Mathlib.RingTheory.Spectrum.Prime.IsOpenComapC diff --git a/Mathlib/RingTheory/Spectrum/Prime/ConstructibleSet.lean b/Mathlib/RingTheory/Spectrum/Prime/ConstructibleSet.lean new file mode 100644 index 0000000000000..47a1ca362df0a --- /dev/null +++ b/Mathlib/RingTheory/Spectrum/Prime/ConstructibleSet.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2024 Yaël Dillies, Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Andrew Yang +-/ +import Mathlib.Order.SuccPred.WithBot +import Mathlib.RingTheory.Spectrum.Prime.Topology + +/-! +# Constructible sets in the prime spectrum + +This file provides tooling for manipulating constructible sets in the prime spectrum of a ring. + +## TODO + +Link to constructible sets in a topological space. +-/ + +open Finset +open scoped Polynomial + +namespace PrimeSpectrum +variable {R S T : Type*} [CommSemiring R] [CommSemiring S] [CommSemiring T] + +variable (R) in +/-- The data of a constructible set `s` is finitely many tuples `(f, g₁, ..., gₙ)` such that +`s = ⋃ (f, g₁, ..., gₙ), V(g₁, ..., gₙ) \ V(f)`. + +To obtain `s` from its data, use `PrimeSpectrum.ConstructibleSetData.toSet`. -/ +abbrev ConstructibleSetData := Finset (R × Σ n, Fin n → R) + +namespace ConstructibleSetData + +/-- Given the data of the constructible set `s`, build the data of the constructible set +`{I | {x | f x ∈ I} ∈ s}`. -/ +def map [DecidableEq S] (f : R →+* S) (s : ConstructibleSetData R) : ConstructibleSetData S := + s.image fun ⟨r, n, g⟩ ↦ ⟨f r, n, f ∘ g⟩ + +@[simp] +lemma map_id [DecidableEq R] (s : ConstructibleSetData R) : s.map (.id _) = s := by simp [map] + +lemma map_comp [DecidableEq S] [DecidableEq T] (f : S →+* T) (g : R →+* S) + (s : ConstructibleSetData R) : s.map (f.comp g) = (s.map g).map f := by + simp [map, image_image, Function.comp_def] + +/-- Given the data of a constructible set `s`, namely finitely many tuples `(f, g₁, ..., gₙ)` such +that `s = ⋃ (f, g₁, ..., gₙ), V(g₁, ..., gₙ) \ V(f)`, return `s`. -/ +def toSet (S : ConstructibleSetData R) : Set (PrimeSpectrum R) := + ⋃ x ∈ S, zeroLocus (Set.range x.2.2) \ zeroLocus {x.1} + +@[simp] +lemma toSet_map [DecidableEq S] (f : R →+* S) (s : ConstructibleSetData R) : + (s.map f).toSet = comap f ⁻¹' s.toSet := by + unfold toSet map + rw [set_biUnion_finset_image] + simp [← Set.range_comp] + +/-- The degree bound on a constructible set for Chevalley's theorem for the inclusion `R ↪ R[X]`. -/ +def degBound (S : ConstructibleSetData R[X]) : ℕ := S.sup fun e ↦ ∑ i, (e.2.2 i).degree.succ + +end PrimeSpectrum.ConstructibleSetData From 8a9bd0608c1c0dc4fd8a938b858ac9e5528a02c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Fri, 24 Jan 2025 07:58:30 +0000 Subject: [PATCH 471/681] feat(MeasureTheory): additive contents on rings of sets (#20977) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two main results: - a function on a ring of sets which is additive on pairs of disjoint sets defines an additive content - if an additive content is continuous at `∅`, then its value on a countable disjoint union is the sum of the values Co-authored-by: Peter Pfaffelhuber Co-authored-by: Sébastien Gouëzel Part of the formalization of Kolmogorov's extension theorem. Co-authored-by: Remy Degenne --- Mathlib/Data/Nat/Lattice.lean | 4 + Mathlib/Data/Set/Accumulate.lean | 12 +++ Mathlib/MeasureTheory/Measure/AddContent.lean | 95 +++++++++++++++++-- Mathlib/MeasureTheory/SetSemiring.lean | 27 +++++- .../Topology/Instances/ENNReal/Lemmas.lean | 14 +++ 5 files changed, 142 insertions(+), 10 deletions(-) diff --git a/Mathlib/Data/Nat/Lattice.lean b/Mathlib/Data/Nat/Lattice.lean index 69b77b20877e1..1ede706e2e0fb 100644 --- a/Mathlib/Data/Nat/Lattice.lean +++ b/Mathlib/Data/Nat/Lattice.lean @@ -3,6 +3,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, Floris van Doorn, Gabriel Ebner, Yury Kudryashov -/ +import Mathlib.Data.Set.Accumulate import Mathlib.Order.ConditionallyCompleteLattice.Finset import Mathlib.Order.Interval.Finset.Nat @@ -235,4 +236,7 @@ theorem biInter_le_succ (u : ℕ → Set α) (n : ℕ) : ⋂ k ≤ n + 1, u k = theorem biInter_le_succ' (u : ℕ → Set α) (n : ℕ) : ⋂ k ≤ n + 1, u k = u 0 ∩ ⋂ k ≤ n, u (k + 1) := Nat.iInf_le_succ' u n +theorem accumulate_succ (u : ℕ → Set α) (n : ℕ) : + Accumulate u (n + 1) = Accumulate u n ∪ u (n + 1) := biUnion_le_succ u n + end Set diff --git a/Mathlib/Data/Set/Accumulate.lean b/Mathlib/Data/Set/Accumulate.lean index ffa9845a9ad40..72726156c5014 100644 --- a/Mathlib/Data/Set/Accumulate.lean +++ b/Mathlib/Data/Set/Accumulate.lean @@ -52,4 +52,16 @@ theorem iUnion_accumulate [Preorder α] : ⋃ x, Accumulate s x = ⋃ x, s x := exact ⟨x', hz⟩ · exact iUnion_mono fun i => subset_accumulate +@[simp] +lemma accumulate_zero_nat (s : ℕ → Set β) : Accumulate s 0 = s 0 := by + simp [accumulate_def] + +open Function in +theorem disjoint_accumulate [Preorder α] (hs : Pairwise (Disjoint on s)) {i j : α} (hij : i < j) : + Disjoint (Accumulate s i) (s j) := by + apply disjoint_left.2 (fun x hx ↦ ?_) + simp only [Accumulate, mem_iUnion, exists_prop] at hx + rcases hx with ⟨k, hk, hx⟩ + exact disjoint_left.1 (hs (hk.trans_lt hij).ne) hx + end Set diff --git a/Mathlib/MeasureTheory/Measure/AddContent.lean b/Mathlib/MeasureTheory/Measure/AddContent.lean index 40d6422e75b95..2332cc948c41d 100644 --- a/Mathlib/MeasureTheory/Measure/AddContent.lean +++ b/Mathlib/MeasureTheory/Measure/AddContent.lean @@ -3,9 +3,9 @@ Copyright (c) 2024 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne, Peter Pfaffelhuber -/ -import Mathlib.Algebra.BigOperators.Group.Finset.Basic -import Mathlib.Data.ENNReal.Basic import Mathlib.MeasureTheory.SetSemiring +import Mathlib.Topology.Algebra.InfiniteSum.Defs +import Mathlib.Topology.Instances.ENNReal.Lemmas /-! # Additive Contents @@ -37,12 +37,16 @@ If `C` is a set ring (`MeasureTheory.IsSetRing C`), we have, for `s, t ∈ C`, * `MeasureTheory.addContent_union_le`: `m (s ∪ t) ≤ m s + m t` * `MeasureTheory.addContent_le_diff`: `m s - m t ≤ m (s \ t)` +* `IsSetRing.addContent_of_union`: a function on a ring of sets which is additive on pairs of +disjoint sets defines an additive content +* `addContent_iUnion_eq_sum_of_tendsto_zero`: if an additive content is continuous at `∅`, then +its value on a countable disjoint union is the sum of the values -/ -open Set Finset +open Set Finset Function Filter -open scoped ENNReal +open scoped ENNReal Topology namespace MeasureTheory @@ -157,9 +161,10 @@ lemma addContent_biUnion_le {ι : Type*} (hC : IsSetRing C) {s : ι → Set α} {S : Finset ι} (hs : ∀ n ∈ S, s n ∈ C) : m (⋃ i ∈ S, s i) ≤ ∑ i ∈ S, m (s i) := by classical - induction' S using Finset.induction with i S hiS h hs - · simp - · rw [Finset.sum_insert hiS] + induction S using Finset.induction with + | empty => simp + | @insert i S hiS h => + rw [Finset.sum_insert hiS] simp_rw [← Finset.mem_coe, Finset.coe_insert, Set.biUnion_insert] simp only [Finset.mem_insert, forall_eq_or_imp] at hs refine (addContent_union_le hC hs.1 (hC.biUnion_mem S hs.2)).trans ?_ @@ -173,6 +178,82 @@ lemma le_addContent_diff (m : AddContent C) (hC : IsSetRing C) (hs : s ∈ C) (h rw [tsub_eq_zero_of_le (addContent_mono hC.isSetSemiring (hC.inter_mem hs ht) ht inter_subset_right), add_zero] +lemma addContent_diff_of_ne_top (m : AddContent C) (hC : IsSetRing C) + (hm_ne_top : ∀ s ∈ C, m s ≠ ∞) + {s t : Set α} (hs : s ∈ C) (ht : t ∈ C) (hts : t ⊆ s) : + m (s \ t) = m s - m t := by + have h_union : m (t ∪ s \ t) = m t + m (s \ t) := + addContent_union hC ht (hC.diff_mem hs ht) disjoint_sdiff_self_right + simp_rw [Set.union_diff_self, Set.union_eq_right.mpr hts] at h_union + rw [h_union, ENNReal.add_sub_cancel_left (hm_ne_top _ ht)] + +lemma addContent_accumulate (m : AddContent C) (hC : IsSetRing C) + {s : ℕ → Set α} (hs_disj : Pairwise (Disjoint on s)) (hsC : ∀ i, s i ∈ C) (n : ℕ) : + m (Set.Accumulate s n) = ∑ i in Finset.range (n + 1), m (s i) := by + induction n with + | zero => simp + | succ n hn => + rw [Finset.sum_range_succ, ← hn, Set.accumulate_succ, addContent_union hC _ (hsC _)] + · exact Set.disjoint_accumulate hs_disj (Nat.lt_succ_self n) + · exact hC.accumulate_mem hsC n + +/-- A function which is additive on disjoint elements in a ring of sets `C` defines an +additive content on `C`. -/ +def IsSetRing.addContent_of_union (m : Set α → ℝ≥0∞) (hC : IsSetRing C) (m_empty : m ∅ = 0) + (m_add : ∀ {s t : Set α} (_hs : s ∈ C) (_ht : t ∈ C), Disjoint s t → m (s ∪ t) = m s + m t) : + AddContent C where + toFun := m + empty' := m_empty + sUnion' I h_ss h_dis h_mem := by + classical + induction I using Finset.induction with + | empty => simp only [Finset.coe_empty, Set.sUnion_empty, Finset.sum_empty, m_empty] + | @insert s I hsI h => + rw [Finset.coe_insert] at * + rw [Set.insert_subset_iff] at h_ss + rw [Set.pairwiseDisjoint_insert_of_not_mem] at h_dis + swap; · exact hsI + have h_sUnion_mem : ⋃₀ ↑I ∈ C := by + rw [Set.sUnion_eq_biUnion] + apply hC.biUnion_mem + intro n hn + exact h_ss.2 hn + rw [Set.sUnion_insert, m_add h_ss.1 h_sUnion_mem (Set.disjoint_sUnion_right.mpr h_dis.2), + Finset.sum_insert hsI, h h_ss.2 h_dis.1] + rwa [Set.sUnion_insert] at h_mem + +/-- In a ring of sets, continuity of an additive content at `∅` implies σ-additivity. +This is not true in general in semirings, or without the hypothesis that `m` is finite. See the +examples 7 and 8 in Halmos' book Measure Theory (1974), page 40. -/ +theorem addContent_iUnion_eq_sum_of_tendsto_zero (hC : IsSetRing C) (m : AddContent C) + (hm_ne_top : ∀ s ∈ C, m s ≠ ∞) + (hm_tendsto : ∀ ⦃s : ℕ → Set α⦄ (_ : ∀ n, s n ∈ C), + Antitone s → (⋂ n, s n) = ∅ → Tendsto (fun n ↦ m (s n)) atTop (𝓝 0)) + ⦃f : ℕ → Set α⦄ (hf : ∀ i, f i ∈ C) (hUf : (⋃ i, f i) ∈ C) + (h_disj : Pairwise (Disjoint on f)) : + m (⋃ i, f i) = ∑' i, m (f i) := by + -- We use the continuity of `m` at `∅` on the sequence `n ↦ (⋃ i, f i) \ (set.accumulate f n)` + let s : ℕ → Set α := fun n ↦ (⋃ i, f i) \ Set.Accumulate f n + have hCs n : s n ∈ C := hC.diff_mem hUf (hC.accumulate_mem hf n) + have h_tendsto : Tendsto (fun n ↦ m (s n)) atTop (𝓝 0) := by + refine hm_tendsto hCs ?_ ?_ + · intro i j hij x hxj + rw [Set.mem_diff] at hxj ⊢ + exact ⟨hxj.1, fun hxi ↦ hxj.2 (Set.monotone_accumulate hij hxi)⟩ + · simp_rw [s, Set.diff_eq] + rw [Set.iInter_inter_distrib, Set.iInter_const, ← Set.compl_iUnion, Set.iUnion_accumulate] + exact Set.inter_compl_self _ + have hmsn n : m (s n) = m (⋃ i, f i) - ∑ i in Finset.range (n + 1), m (f i) := by + rw [addContent_diff_of_ne_top m hC hm_ne_top hUf (hC.accumulate_mem hf n) + (Set.accumulate_subset_iUnion _), addContent_accumulate m hC h_disj hf n] + simp_rw [hmsn] at h_tendsto + refine tendsto_nhds_unique ?_ (ENNReal.tendsto_nat_tsum fun i ↦ m (f i)) + refine (Filter.tendsto_add_atTop_iff_nat 1).mp ?_ + rwa [ENNReal.tendsto_const_sub_nhds_zero_iff (hm_ne_top _ hUf) (fun n ↦ ?_)] at h_tendsto + rw [← addContent_accumulate m hC h_disj hf] + exact addContent_mono hC.isSetSemiring (hC.accumulate_mem hf n) hUf + (Set.accumulate_subset_iUnion _) + end IsSetRing end MeasureTheory diff --git a/Mathlib/MeasureTheory/SetSemiring.lean b/Mathlib/MeasureTheory/SetSemiring.lean index 7d5c399b2bb84..503f9ca6b3e8d 100644 --- a/Mathlib/MeasureTheory/SetSemiring.lean +++ b/Mathlib/MeasureTheory/SetSemiring.lean @@ -3,6 +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, Peter Pfaffelhuber -/ +import Mathlib.Data.Nat.Lattice +import Mathlib.Data.Set.Accumulate import Mathlib.Data.Set.Pairwise.Lattice import Mathlib.MeasureTheory.PiSystem @@ -303,9 +305,10 @@ lemma biUnion_mem {ι : Type*} (hC : IsSetRing C) {s : ι → Set α} (S : Finset ι) (hs : ∀ n ∈ S, s n ∈ C) : ⋃ i ∈ S, s i ∈ C := by classical - induction' S using Finset.induction with i S _ h hs - · simp [hC.empty_mem] - · simp_rw [← Finset.mem_coe, Finset.coe_insert, Set.biUnion_insert] + induction S using Finset.induction with + | empty => simp [hC.empty_mem] + | @insert i S _ h => + simp_rw [← Finset.mem_coe, Finset.coe_insert, Set.biUnion_insert] refine hC.union_mem (hs i (mem_insert_self i S)) ?_ exact h (fun n hnS ↦ hs n (mem_insert_of_mem hnS)) @@ -341,6 +344,24 @@ lemma disjointed_mem {ι : Type*} [Preorder ι] [LocallyFiniteOrderBot ι] disjointed s i ∈ C := disjointedRec (fun _ j ht ↦ hC.diff_mem ht <| hs j) (hs i) +theorem iUnion_le_mem (hC : IsSetRing C) {s : ℕ → Set α} (hs : ∀ n, s n ∈ C) (n : ℕ) : + (⋃ i ≤ n, s i) ∈ C := by + induction n with + | zero => simp [hs 0] + | succ n hn => rw [biUnion_le_succ]; exact hC.union_mem hn (hs _) + +theorem iInter_le_mem (hC : IsSetRing C) {s : ℕ → Set α} (hs : ∀ n, s n ∈ C) (n : ℕ) : + (⋂ i ≤ n, s i) ∈ C := by + induction n with + | zero => simp [hs 0] + | succ n hn => rw [biInter_le_succ]; exact hC.inter_mem hn (hs _) + +theorem accumulate_mem (hC : IsSetRing C) {s : ℕ → Set α} (hs : ∀ i, s i ∈ C) (n : ℕ) : + Accumulate s n ∈ C := by + induction n with + | zero => simp [hs 0] + | succ n hn => rw [accumulate_succ]; exact hC.union_mem hn (hs _) + end IsSetRing end MeasureTheory diff --git a/Mathlib/Topology/Instances/ENNReal/Lemmas.lean b/Mathlib/Topology/Instances/ENNReal/Lemmas.lean index e6520245b62c1..4cb57c22494fc 100644 --- a/Mathlib/Topology/Instances/ENNReal/Lemmas.lean +++ b/Mathlib/Topology/Instances/ENNReal/Lemmas.lean @@ -237,6 +237,20 @@ protected theorem tendsto_nhds_zero {f : Filter α} {u : α → ℝ≥0∞} : Tendsto u f (𝓝 0) ↔ ∀ ε > 0, ∀ᶠ x in f, u x ≤ ε := nhds_zero_basis_Iic.tendsto_right_iff +theorem tendsto_const_sub_nhds_zero_iff {l : Filter α} {f : α → ℝ≥0∞} {a : ℝ≥0∞} (ha : a ≠ ∞) + (hfa : ∀ n, f n ≤ a) : + Tendsto (fun n ↦ a - f n) l (𝓝 0) ↔ Tendsto (fun n ↦ f n) l (𝓝 a) := by + rw [ENNReal.tendsto_nhds_zero, ENNReal.tendsto_nhds ha] + refine ⟨fun h ε hε ↦ ?_, fun h ε hε ↦ ?_⟩ + · filter_upwards [h ε hε] with n hn + refine ⟨?_, (hfa n).trans (le_add_right le_rfl)⟩ + rw [tsub_le_iff_right] at hn ⊢ + rwa [add_comm] + · filter_upwards [h ε hε] with n hn + have hN_left := hn.1 + rw [tsub_le_iff_right] at hN_left ⊢ + rwa [add_comm] + protected theorem tendsto_atTop [Nonempty β] [SemilatticeSup β] {f : β → ℝ≥0∞} {a : ℝ≥0∞} (ha : a ≠ ∞) : Tendsto f atTop (𝓝 a) ↔ ∀ ε > 0, ∃ N, ∀ n ≥ N, f n ∈ Icc (a - ε) (a + ε) := .trans (atTop_basis.tendsto_iff (hasBasis_nhds_of_ne_top ha)) (by simp only [true_and]; rfl) From 21e96d4e6c2bcb675526c2366949bea1e7156f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Fri, 24 Jan 2025 08:30:28 +0000 Subject: [PATCH 472/681] feat(CategoryTheory): (co)limits indexed by preorders (#20335) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this PR, we show very basic results about (co)limits indexed by a preordered type J. `OrderBot J` implies the existence of all limits indexed by `J` (and similarly when `J` has a greatest element). We also introduce the typeclass `HasIterationOfShape C J` which contains the assumptions in order to do constructions by transfinite induction (see #20245 for the application to the small object argument). Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 2 + .../Limits/Shapes/Preorder/Basic.lean | 54 +++++++++++++++++++ .../Shapes/Preorder/HasIterationOfShape.lean | 54 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean create mode 100644 Mathlib/CategoryTheory/Limits/Shapes/Preorder/HasIterationOfShape.lean diff --git a/Mathlib.lean b/Mathlib.lean index 44d7671ebde7d..75e8603fc02bb 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1975,6 +1975,8 @@ import Mathlib.CategoryTheory.Limits.Shapes.Multiequalizer import Mathlib.CategoryTheory.Limits.Shapes.NormalMono.Basic import Mathlib.CategoryTheory.Limits.Shapes.NormalMono.Equalizers import Mathlib.CategoryTheory.Limits.Shapes.PiProd +import Mathlib.CategoryTheory.Limits.Shapes.Preorder.Basic +import Mathlib.CategoryTheory.Limits.Shapes.Preorder.HasIterationOfShape import Mathlib.CategoryTheory.Limits.Shapes.Preorder.WellOrderContinuous import Mathlib.CategoryTheory.Limits.Shapes.Products import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Assoc diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean new file mode 100644 index 0000000000000..fd2ca7692b49c --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean @@ -0,0 +1,54 @@ +/- +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.CategoryTheory.Limits.Shapes.Terminal + +/-! +# Limits and colimits indexed by preorders + +In this file, we obtain the following very basic results +about limits and colimits indexed by a preordered type `J`: +* a least element in `J` implies the existence of all limits indexed by `J` +* a greatest element in `J` implies the existence of all colimits indexed by `J` + +-/ + +universe v v' u u' w + +open CategoryTheory Limits + +variable (J : Type w) [Preorder J] (C : Type u) [Category.{v} C] + +namespace Preorder + +section OrderBot + +variable [OrderBot J] + +/-- The least element in a preordered type is initial in the category +associated to this preorder. -/ +def isInitialBot : IsInitial (⊥ : J) := IsInitial.ofUnique _ + +instance : HasInitial J := hasInitial_of_unique ⊥ + +instance : HasLimitsOfShape J C := ⟨fun _ ↦ by infer_instance⟩ + +end OrderBot + +section OrderTop + +variable [OrderTop J] + +/-- The greatest element of a preordered type is terminal in the category +associated to this preorder. -/ +def isTerminalBot : IsTerminal (⊤ : J) := IsTerminal.ofUnique _ + +instance : HasTerminal J := hasTerminal_of_unique ⊤ + +instance : HasColimitsOfShape J C := ⟨fun _ ↦ by infer_instance⟩ + +end OrderTop + +end Preorder diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Preorder/HasIterationOfShape.lean b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/HasIterationOfShape.lean new file mode 100644 index 0000000000000..b255543b53a02 --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/HasIterationOfShape.lean @@ -0,0 +1,54 @@ +/- +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.CategoryTheory.Limits.FunctorCategory.Basic +import Mathlib.CategoryTheory.Limits.Comma +import Mathlib.Order.SuccPred.Limit + +/-! +# An assumption for constructions by transfinite induction + +In this file, we introduce the typeclass `HasIterationOfShape J C` which is +an assumption in order to do constructions by transfinite induction indexed by +a well-ordered type `J` in a category `C` (see `CategoryTheory.SmallObject`). + +-/ + +universe w v v' u u' + +namespace CategoryTheory.Limits + +variable (J : Type w) [Preorder J] (C : Type u) [Category.{v} C] + (K : Type u') [Category.{v'} K] + +/-- A category `C` has iterations of shape a preordered type `J` +when certain specific shapes of colimits exists: colimits indexed by `J`, +and by `Set.Iio j` for `j : J`. -/ +class HasIterationOfShape : Prop where + hasColimitsOfShape_of_isSuccLimit (j : J) (hj : Order.IsSuccLimit j) : + HasColimitsOfShape (Set.Iio j) C := by infer_instance + hasColimitsOfShape : HasColimitsOfShape J C := by infer_instance + +attribute [instance] HasIterationOfShape.hasColimitsOfShape + +variable [HasIterationOfShape J C] + +variable {J} in +lemma hasColimitsOfShape_of_isSuccLimit (j : J) + (hj : Order.IsSuccLimit j) : + HasColimitsOfShape (Set.Iio j) C := + HasIterationOfShape.hasColimitsOfShape_of_isSuccLimit j hj + +instance : HasIterationOfShape J (Arrow C) where + hasColimitsOfShape_of_isSuccLimit j hj := by + have := hasColimitsOfShape_of_isSuccLimit C j hj + infer_instance + +instance : HasIterationOfShape J (K ⥤ C) where + hasColimitsOfShape_of_isSuccLimit j hj := by + have := hasColimitsOfShape_of_isSuccLimit C j hj + infer_instance + +end CategoryTheory.Limits From 175a60f66fa50c88d6d4c7e3e7c51152dbd63add Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Fri, 24 Jan 2025 08:30:29 +0000 Subject: [PATCH 473/681] chore: Golf de Moivre's formula (#21012) Golfs the proof of de Moivre's formula to a single line of rewrites, using a preexisting theorem. --- Mathlib/Data/Complex/Exponential.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index af666d90bb9c4..8972434892eb7 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -667,10 +667,7 @@ theorem exp_ofReal_mul_I_im (x : ℝ) : (exp (x * I)).im = Real.sin x := by /-- **De Moivre's formula** -/ theorem cos_add_sin_mul_I_pow (n : ℕ) (z : ℂ) : (cos z + sin z * I) ^ n = cos (↑n * z) + sin (↑n * z) * I := by - rw [← exp_mul_I, ← exp_mul_I] - induction' n with n ih - · rw [pow_zero, Nat.cast_zero, zero_mul, zero_mul, exp_zero] - · rw [pow_succ, ih, Nat.cast_succ, add_mul, add_mul, one_mul, exp_add] + rw [← exp_mul_I, ← exp_mul_I, ← exp_nat_mul, mul_assoc] end Complex From ffaf9758753e7e58dfb0b5d60d531a72d6fe6413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= Date: Fri, 24 Jan 2025 08:47:59 +0000 Subject: [PATCH 474/681] =?UTF-8?q?perf:=20improves=20the=20performance=20?= =?UTF-8?q?of=20the=20`Repr=20(Equiv.Perm=20=CE=B1)`=20instance=20(2/4)=20?= =?UTF-8?q?(#20538)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The instance of `Repr (Equiv.Perm α)` uses the following `truncCycleFactors` function: ```lean def cycleFactorsAux [DecidableEq α] [Fintype α] (l : List α) (f : Perm α) (h : ∀ {x}, f x ≠ x → x ∈ l) : { l : List (Perm α) // l.prod = f ∧ (∀ g ∈ l, IsCycle g) ∧ l.Pairwise Disjoint } := match l with | [] => ⟨[], ⋯⟩ | x :: l => if hx : f x = x then cycleFactorsAux l f ⋯ else let ⟨m, hm⟩ := cycleFactorsAux l ((cycleOf f x)⁻¹ * f) ⋯ ⟨cycleOf f x :: m, ⋯⟩ def truncCycleFactors [DecidableEq α] [Fintype α] (f : Perm α) : Trunc { l : List (Perm α) // l.prod = f ∧ (∀ g ∈ l, IsCycle g) ∧ l.Pairwise Disjoint } := Quotient.recOnSubsingleton (motive := fun m => (∀ x, f x ≠ x → x ∈ m) → Trunc { l // l.prod = f ∧ (∀ g ∈ l, g.IsCycle) ∧ List.Pairwise Disjoint l }) (Finset.univ : Finset α).val (fun l h => Trunc.mk (cycleFactorsAux l f ⋯)) ⋯ ``` However, for a permutation consisted of many disjoint cycles, like `(c[0, 1] * c[2, 3] * c[4, 5] * c[6, 7] : Equiv.Perm (Fin 10))`, evaluating returned permutations takes too long. This is because the argument `f` in `cycleFactorsAux` gets more complex per step; `f` to `(cycleOf f x)⁻¹ * f`. To solve this problem, we memorize the first permutation: ```lean def cycleFactorsAux [DecidableEq α] [Fintype α] (l : List α) (f : Perm α) (h : ∀ {x}, f x ≠ x → x ∈ l) : { pl : List (Perm α) // pl.prod = f ∧ (∀ g ∈ pl, IsCycle g) ∧ pl.Pairwise Disjoint } := go l f ⋯ ⋯ where go (l : List α) (g : Perm α) (hg : ∀ {x}, g x ≠ x → x ∈ l) (hfg : ∀ {x}, g x ≠ x → cycleOf f x = cycleOf g x) : { pl : List (Perm α) // pl.prod = g ∧ (∀ g' ∈ pl, IsCycle g') ∧ pl.Pairwise Disjoint } := match l with | [] => ⟨[], ⋯⟩ | x :: l => if hx : g x = x then go l g ⋯ ⋯ else let ⟨m, hm₁, hm₂, hm₃⟩ := go l ((cycleOf f x)⁻¹ * g) ⋯ ⋯ ⟨cycleOf f x :: m, ⋯⟩ ``` --- Mathlib/GroupTheory/Perm/Cycle/Factors.lean | 99 +++++++++++++-------- 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean index a3fe94c15f780..542a4d867174a 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean @@ -307,50 +307,75 @@ section cycleFactors open scoped List in /-- Given a list `l : List α` and a permutation `f : Perm α` whose nonfixed points are all in `l`, recursively factors `f` into cycles. -/ -def cycleFactorsAux [DecidableEq α] [Fintype α] (l : List α) (f : Perm α) - (h : ∀ {x}, f x ≠ x → x ∈ l) : - { l : List (Perm α) // l.prod = f ∧ (∀ g ∈ l, IsCycle g) ∧ l.Pairwise Disjoint } := +def cycleFactorsAux [DecidableEq α] [Fintype α] + (l : List α) (f : Perm α) (h : ∀ {x}, f x ≠ x → x ∈ l) : + { pl : List (Perm α) // pl.prod = f ∧ (∀ g ∈ pl, IsCycle g) ∧ pl.Pairwise Disjoint } := + go l f h (fun _ => rfl) +where + /-- The auxiliary of `cycleFactorsAux`. This functions separates cycles from `f` instead of `g` + to prevent the process of a cycle gets complex. -/ + go (l : List α) (g : Perm α) (hg : ∀ {x}, g x ≠ x → x ∈ l) + (hfg : ∀ {x}, g x ≠ x → cycleOf f x = cycleOf g x) : + { pl : List (Perm α) // pl.prod = g ∧ (∀ g' ∈ pl, IsCycle g') ∧ pl.Pairwise Disjoint } := match l with | [] => ⟨[], by { simp only [imp_false, List.Pairwise.nil, List.not_mem_nil, forall_const, and_true, forall_prop_of_false, Classical.not_not, not_false_iff, List.prod_nil] at * ext simp [*]}⟩ - | x::l => - if hx : f x = x then cycleFactorsAux l f (by - intro y hy; exact List.mem_of_ne_of_mem (fun h => hy (by rwa [h])) (h hy)) + | x :: l => + if hx : g x = x then go l g (by + intro y hy; exact List.mem_of_ne_of_mem (fun h => hy (by rwa [h])) (hg hy)) hfg else - let ⟨m, hm⟩ := - cycleFactorsAux l ((cycleOf f x)⁻¹ * f) (by - intro y hy - exact List.mem_of_ne_of_mem - (fun h : y = x => by - rw [h, mul_apply, Ne, inv_eq_iff_eq, cycleOf_apply_self] at hy - exact hy rfl) - (h fun h : f y = y => by - rw [mul_apply, h, Ne, inv_eq_iff_eq, cycleOf_apply] at hy - split_ifs at hy <;> tauto)) - ⟨cycleOf f x :: m, by simp [List.prod_cons, hm.1], - fun g hg ↦ ((List.mem_cons).1 hg).elim (fun hg => hg ▸ isCycle_cycleOf _ hx) (hm.2.1 g), - List.pairwise_cons.2 - ⟨fun g hg y => - or_iff_not_imp_left.2 fun hfy => - have hxy : SameCycle f x y := - Classical.not_not.1 (mt cycleOf_apply_of_not_sameCycle hfy) - have hgm : (g::m.erase g) ~ m := - List.cons_perm_iff_perm_erase.2 ⟨hg, List.Perm.refl _⟩ - have : ∀ h ∈ m.erase g, Disjoint g h := - (List.pairwise_cons.1 ((hgm.pairwise_iff Disjoint.symm).2 hm.2.2)).1 - by_cases id fun hgy : g y ≠ y => - (disjoint_prod_right _ this y).resolve_right <| by - have hsc : SameCycle f⁻¹ x (f y) := by - rwa [sameCycle_inv, sameCycle_apply_right] - have hm₁ := hm.1 - rw [disjoint_prod_perm hm.2.2 hgm.symm, List.prod_cons, - ← eq_inv_mul_iff_mul_eq] at hm₁ - rwa [hm₁, mul_apply, mul_apply, cycleOf_inv, hsc.cycleOf_apply, inv_apply_self, - inv_eq_iff_eq, eq_comm], - hm.2.2⟩⟩ + let ⟨m, hm₁, hm₂, hm₃⟩ := + go l ((cycleOf f x)⁻¹ * g) (by + rw [hfg hx] + intro y hy + exact List.mem_of_ne_of_mem + (fun h : y = x => by + rw [h, mul_apply, Ne, inv_eq_iff_eq, cycleOf_apply_self] at hy + exact hy rfl) + (hg fun h : g y = y => by + rw [mul_apply, h, Ne, inv_eq_iff_eq, cycleOf_apply] at hy + split_ifs at hy <;> tauto)) + (by + rw [hfg hx] + intro y hy + simp [inv_eq_iff_eq, cycleOf_apply, eq_comm (a := g y)] at hy + rw [hfg (Ne.symm hy.right), ← mul_inv_eq_one (a := g.cycleOf y), cycleOf_inv] + simp_rw [mul_inv_rev] + rw [inv_inv, cycleOf_mul_of_apply_right_eq_self, ← cycleOf_inv, mul_inv_eq_one] + · rw [Commute.inv_left_iff, commute_iff_eq] + ext z; by_cases hz : SameCycle g x z + · simp [cycleOf_apply, hz] + · simp [cycleOf_apply_of_not_sameCycle, hz] + · exact cycleOf_apply_of_not_sameCycle hy.left) + ⟨cycleOf f x :: m, by + rw [hfg hx] at hm₁ ⊢ + constructor + · rw [List.prod_cons, hm₁] + simp + · exact + ⟨fun g' hg' => + ((List.mem_cons).1 hg').elim (fun hg' => hg'.symm ▸ isCycle_cycleOf _ hx) (hm₂ g'), + List.pairwise_cons.2 + ⟨fun g' hg' y => + or_iff_not_imp_left.2 fun hgy => + have hxy : SameCycle g x y := + Classical.not_not.1 (mt cycleOf_apply_of_not_sameCycle hgy) + have hg'm : (g' :: m.erase g') ~ m := + List.cons_perm_iff_perm_erase.2 ⟨hg', List.Perm.refl _⟩ + have : ∀ h ∈ m.erase g', Disjoint g' h := + (List.pairwise_cons.1 ((hg'm.pairwise_iff Disjoint.symm).2 hm₃)).1 + by_cases id fun hg'y : g' y ≠ y => + (disjoint_prod_right _ this y).resolve_right <| by + have hsc : SameCycle g⁻¹ x (g y) := by + rwa [sameCycle_inv, sameCycle_apply_right] + rw [disjoint_prod_perm hm₃ hg'm.symm, List.prod_cons, + ← eq_inv_mul_iff_mul_eq] at hm₁ + rwa [hm₁, mul_apply, mul_apply, cycleOf_inv, hsc.cycleOf_apply, + inv_apply_self, inv_eq_iff_eq, eq_comm], + hm₃⟩⟩⟩ theorem mem_list_cycles_iff {α : Type*} [Finite α] {l : List (Perm α)} (h1 : ∀ σ : Perm α, σ ∈ l → σ.IsCycle) (h2 : l.Pairwise Disjoint) {σ : Perm α} : From a5519b0bc4f8c9323f15ec88866be938eb601955 Mon Sep 17 00:00:00 2001 From: Matej Penciak Date: Fri, 24 Jan 2025 09:23:27 +0000 Subject: [PATCH 475/681] doc(Algebra/Category/Ring/Basic): Fix some docstrings (#21014) Fix a few docstrings for `RingCat`, `CommSemiRingCat`, and `CommRingCat` that were incorrectly copied from `SemiRingCat`. --- Mathlib/Algebra/Category/Ring/Basic.lean | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index 6c70b9d5fdd78..eb6977db75632 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -166,7 +166,7 @@ instance forgetReflectIsos : (forget SemiRingCat).ReflectsIsomorphisms where end SemiRingCat -/-- The category of semirings. -/ +/-- The category of rings. -/ structure RingCat where private mk :: /-- The underlying type. -/ @@ -314,7 +314,7 @@ instance forgetReflectIsos : (forget RingCat).ReflectsIsomorphisms where end RingCat -/-- The category of semirings. -/ +/-- The category of commutative semirings. -/ structure CommSemiRingCat where private mk :: /-- The underlying type. -/ @@ -461,7 +461,7 @@ instance forgetReflectIsos : (forget CommSemiRingCat).ReflectsIsomorphisms where end CommSemiRingCat -/-- The category of semirings. -/ +/-- The category of commutative rings. -/ structure CommRingCat where private mk :: /-- The underlying type. -/ From 1cbfe61c57846329c6daec86f44706ce589f9477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 24 Jan 2025 09:44:51 +0000 Subject: [PATCH 476/681] feat: constructible sets (#20054) Define constructible sets, which are morally sets in a topological space which we can make out of finite unions and intersections of open and closed sets. From GrowthInGroups (LeanCamCombi) --- Mathlib.lean | 1 + Mathlib/Topology/Constructible.lean | 433 ++++++++++++++++++++++++++++ Mathlib/Topology/Constructions.lean | 15 +- 3 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 Mathlib/Topology/Constructible.lean diff --git a/Mathlib.lean b/Mathlib.lean index 75e8603fc02bb..a93503d6b2071 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5337,6 +5337,7 @@ import Mathlib.Topology.Connected.LocallyConnected import Mathlib.Topology.Connected.PathConnected import Mathlib.Topology.Connected.Separation import Mathlib.Topology.Connected.TotallyDisconnected +import Mathlib.Topology.Constructible import Mathlib.Topology.Constructions import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.Topology.ContinuousMap.Basic diff --git a/Mathlib/Topology/Constructible.lean b/Mathlib/Topology/Constructible.lean new file mode 100644 index 0000000000000..4ad63357cdd71 --- /dev/null +++ b/Mathlib/Topology/Constructible.lean @@ -0,0 +1,433 @@ +/- +Copyright (c) 2024 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies +-/ +import Mathlib.Order.BooleanSubalgebra +import Mathlib.Topology.Spectral.Hom + +/-! +# Constructible sets + +This file defines constructible sets, which are morally sets in a topological space which we can +make out of finite unions and intersections of open and closed sets. + +Precisely, constructible sets are the boolean subalgebra generated by open retrocompact sets, +where a set is retrocompact if its intersection with every compact open set is compact. +In a locally noetherian space, all sets are retrocompact, in which case this boolean subalgebra is +simply the one generated by the open sets. + +Constructible sets are useful because the image of a constructible set under a finitely presented +morphism of schemes is a constructible set (and this is *not* true at the level of varieties). + +## Main declarations + +* `IsRetrocompact`: Predicate for a set to be retrocompact, namely to have its intersection with + every compact open be compact. +* `IsConstructible`: Predicate for a set to be constructible, namely to belong to the boolean + subalgebra generated by open retrocompact sets. +* `IsLocallyConstructible`: Predicate for a set to be locally constructible, namely to be + partitionable along an open cover such that each of its parts is constructible in the + respective open subspace. +-/ + +open Set TopologicalSpace Topology +open scoped Set.Notation + +variable {ι : Sort*} {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] {f : X → Y} + {s t U : Set X} {a : X} + +/-! ### retrocompact sets -/ + +/-- A retrocompact set is a set whose intersection with every compact open is compact. -/ +@[stacks 005A] +def IsRetrocompact (s : Set X) : Prop := ∀ ⦃U⦄, IsCompact U → IsOpen U → IsCompact (s ∩ U) + +@[simp] lemma IsRetrocompact.empty : IsRetrocompact (∅ : Set X) := by simp [IsRetrocompact] +@[simp] lemma IsRetrocompact.univ : IsRetrocompact (univ : Set X) := by + simp +contextual [IsRetrocompact] + +@[simp] lemma IsRetrocompact.singleton : IsRetrocompact {a} := + fun _ _ _ ↦ Subsingleton.singleton_inter.isCompact + +lemma IsRetrocompact.union (hs : IsRetrocompact s) (ht : IsRetrocompact t) : + IsRetrocompact (s ∪ t : Set X) := + fun _U hUcomp hUopen ↦ union_inter_distrib_right .. ▸ (hs hUcomp hUopen).union (ht hUcomp hUopen) + +private lemma supClosed_isRetrocompact : SupClosed {s : Set X | IsRetrocompact s} := + fun _s hs _t ht ↦ hs.union ht + +lemma IsRetrocompact.finsetSup {ι : Type*} {s : Finset ι} {t : ι → Set X} + (ht : ∀ i ∈ s, IsRetrocompact (t i)) : IsRetrocompact (s.sup t) := by + induction' s using Finset.cons_induction with i s ih hi + · simp + · rw [Finset.sup_cons] + exact (ht _ <| by simp).union <| hi <| Finset.forall_of_forall_cons ht + +set_option linter.docPrime false in +lemma IsRetrocompact.finsetSup' {ι : Type*} {s : Finset ι} {hs} {t : ι → Set X} + (ht : ∀ i ∈ s, IsRetrocompact (t i)) : IsRetrocompact (s.sup' hs t) := by + rw [Finset.sup'_eq_sup]; exact .finsetSup ht + +lemma IsRetrocompact.iUnion [Finite ι] {f : ι → Set X} (hf : ∀ i, IsRetrocompact (f i)) : + IsRetrocompact (⋃ i, f i) := supClosed_isRetrocompact.iSup_mem .empty hf + +lemma IsRetrocompact.sUnion {S : Set (Set X)} (hS : S.Finite) (hS' : ∀ s ∈ S, IsRetrocompact s) : + IsRetrocompact (⋃₀ S) := supClosed_isRetrocompact.sSup_mem hS .empty hS' + +lemma IsRetrocompact.biUnion {ι : Type*} {f : ι → Set X} {t : Set ι} (ht : t.Finite) + (hf : ∀ i ∈ t, IsRetrocompact (f i)) : IsRetrocompact (⋃ i ∈ t, f i) := + supClosed_isRetrocompact.biSup_mem ht .empty hf + +section T2Space +variable [T2Space X] + +lemma IsRetrocompact.inter (hs : IsRetrocompact s) (ht : IsRetrocompact t) : + IsRetrocompact (s ∩ t : Set X) := + fun _U hUcomp hUopen ↦ inter_inter_distrib_right .. ▸ (hs hUcomp hUopen).inter (ht hUcomp hUopen) + +private lemma infClosed_isRetrocompact : InfClosed {s : Set X | IsRetrocompact s} := + fun _s hs _t ht ↦ hs.inter ht + +lemma IsRetrocompact.finsetInf {ι : Type*} {s : Finset ι} {t : ι → Set X} + (ht : ∀ i ∈ s, IsRetrocompact (t i)) : IsRetrocompact (s.inf t) := by + induction' s using Finset.cons_induction with i s ih hi + · simp + · rw [Finset.inf_cons] + exact (ht _ <| by simp).inter <| hi <| Finset.forall_of_forall_cons ht + +set_option linter.docPrime false in +lemma IsRetrocompact.finsetInf' {ι : Type*} {s : Finset ι} {hs} {t : ι → Set X} + (ht : ∀ i ∈ s, IsRetrocompact (t i)) : IsRetrocompact (s.inf' hs t) := by + rw [Finset.inf'_eq_inf]; exact .finsetInf ht + +lemma IsRetrocompact.iInter [Finite ι] {f : ι → Set X} (hf : ∀ i, IsRetrocompact (f i)) : + IsRetrocompact (⋂ i, f i) := infClosed_isRetrocompact.iInf_mem .univ hf + +lemma IsRetrocompact.sInter {S : Set (Set X)} (hS : S.Finite) (hS' : ∀ s ∈ S, IsRetrocompact s) : + IsRetrocompact (⋂₀ S) := infClosed_isRetrocompact.sInf_mem hS .univ hS' + +lemma IsRetrocompact.biInter {ι : Type*} {f : ι → Set X} {t : Set ι} (ht : t.Finite) + (hf : ∀ i ∈ t, IsRetrocompact (f i)) : IsRetrocompact (⋂ i ∈ t, f i) := + infClosed_isRetrocompact.biInf_mem ht .univ hf + +end T2Space + +lemma IsRetrocompact.inter_isOpen (hs : IsRetrocompact s) (ht : IsRetrocompact t) + (htopen : IsOpen t) : IsRetrocompact (s ∩ t : Set X) := + fun _U hUcomp hUopen ↦ inter_assoc .. ▸ hs (ht hUcomp hUopen) (htopen.inter hUopen) + +lemma IsRetrocompact.isOpen_inter (hs : IsRetrocompact s) (ht : IsRetrocompact t) + (hsopen : IsOpen s) : IsRetrocompact (s ∩ t : Set X) := + inter_comm .. ▸ ht.inter_isOpen hs hsopen + +lemma IsRetrocompact_iff_isSpectralMap_subtypeVal : + IsRetrocompact s ↔ IsSpectralMap (Subtype.val : s → X) := by + refine ⟨fun hs ↦ ⟨continuous_subtype_val, fun t htopen htcomp ↦ ?_⟩, fun hs t htcomp htopen ↦ ?_⟩ + · rw [IsEmbedding.subtypeVal.isCompact_iff, image_preimage_eq_inter_range, + Subtype.range_coe_subtype, setOf_mem_eq, inter_comm] + exact hs htcomp htopen + · simpa using (hs.isCompact_preimage_of_isOpen htopen htcomp).image continuous_subtype_val + +@[stacks 005B] +lemma IsRetrocompact.image_of_isEmbedding (hs : IsRetrocompact s) (hfemb : IsEmbedding f) + (hfcomp : IsRetrocompact (range f)) : IsRetrocompact (f '' s) := by + rintro U hUcomp hUopen + rw [← image_inter_preimage, ← hfemb.isCompact_iff] + refine hs ?_ <| hUopen.preimage hfemb.continuous + rw [hfemb.isCompact_iff, image_preimage_eq_inter_range, inter_comm] + exact hfcomp hUcomp hUopen + +@[stacks 005J "Extracted from the proof"] +lemma IsRetrocompact.preimage_of_isOpenEmbedding {s : Set Y} (hf : IsOpenEmbedding f) + (hs : IsRetrocompact s) : IsRetrocompact (f ⁻¹' s) := by + rintro U hUcomp hUopen + rw [hf.isCompact_iff, image_preimage_inter] + exact hs (hUcomp.image hf.continuous) <| hf.isOpenMap _ hUopen + +@[stacks 09YE "Extracted from the proof"] +lemma IsRetrocompact.preimage_of_isClosedEmbedding {s : Set Y} (hf : IsClosedEmbedding f) + (hf' : IsCompact (range f)ᶜ) (hs : IsRetrocompact s) : IsRetrocompact (f ⁻¹' s) := by + rintro U hUcomp hUopen + have hfUopen : IsOpen (f '' U ∪ (range f)ᶜ) := by + simpa [← range_diff_image hf.injective, sdiff_eq, compl_inter, union_comm] + using (hf.isClosedMap _ hUopen.isClosed_compl).isOpen_compl + have hfUcomp : IsCompact (f '' U ∪ (range f)ᶜ) := (hUcomp.image hf.continuous).union hf' + simpa [inter_union_distrib_left, inter_left_comm, inter_eq_right.2 (image_subset_range ..), + hf.isCompact_iff, image_preimage_inter] using (hs hfUcomp hfUopen).inter_left hf.isClosed_range + +/-! ### Constructible sets -/ + +namespace Topology + +/-- A constructible set is a set that can be written as the +finite union/finite intersection/complement of open retrocompact sets. + +In other words, constructible sets form the boolean subalgebra generated by open retrocompact sets. +-/ +def IsConstructible (s : Set X) : Prop := + s ∈ BooleanSubalgebra.closure {U | IsOpen U ∧ IsRetrocompact U} + +@[simp] +protected lemma IsConstructible.empty : IsConstructible (∅ : Set X) := BooleanSubalgebra.bot_mem + +@[simp] +protected lemma IsConstructible.univ : IsConstructible (univ : Set X) := BooleanSubalgebra.top_mem + +lemma IsConstructible.union : IsConstructible s → IsConstructible t → IsConstructible (s ∪ t) := + BooleanSubalgebra.sup_mem + +lemma IsConstructible.inter : IsConstructible s → IsConstructible t → IsConstructible (s ∩ t) := + BooleanSubalgebra.inf_mem + +lemma IsConstructible.sdiff : IsConstructible s → IsConstructible t → IsConstructible (s \ t) := + BooleanSubalgebra.sdiff_mem + +lemma IsConstructible.himp : IsConstructible s → IsConstructible t → IsConstructible (s ⇨ t) := + BooleanSubalgebra.himp_mem + +@[simp] lemma isConstructible_compl : IsConstructible sᶜ ↔ IsConstructible s := + BooleanSubalgebra.compl_mem_iff + +alias ⟨IsConstructible.of_compl, IsConstructible.compl⟩ := isConstructible_compl + +lemma IsConstructible.iUnion [Finite ι] {f : ι → Set X} (hf : ∀ i, IsConstructible (f i)) : + IsConstructible (⋃ i, f i) := BooleanSubalgebra.iSup_mem hf + +lemma IsConstructible.iInter [Finite ι] {f : ι → Set X} (hf : ∀ i, IsConstructible (f i)) : + IsConstructible (⋂ i, f i) := BooleanSubalgebra.iInf_mem hf + +lemma IsConstructible.sUnion {S : Set (Set X)} (hS : S.Finite) (hS' : ∀ s ∈ S, IsConstructible s) : + IsConstructible (⋃₀ S) := BooleanSubalgebra.sSup_mem hS hS' + +lemma IsConstructible.sInter {S : Set (Set X)} (hS : S.Finite) (hS' : ∀ s ∈ S, IsConstructible s) : + IsConstructible (⋂₀ S) := BooleanSubalgebra.sInf_mem hS hS' + +lemma IsConstructible.biUnion {ι : Type*} {f : ι → Set X} {t : Set ι} (ht : t.Finite) + (hf : ∀ i ∈ t, IsConstructible (f i)) : IsConstructible (⋃ i ∈ t, f i) := + BooleanSubalgebra.biSup_mem ht hf + +lemma IsConstructible.biInter {ι : Type*} {f : ι → Set X} {t : Set ι} (ht : t.Finite) + (hf : ∀ i ∈ t, IsConstructible (f i)) : IsConstructible (⋂ i ∈ t, f i) := + BooleanSubalgebra.biInf_mem ht hf + +lemma _root_.IsRetrocompact.isConstructible (hUopen : IsOpen U) (hUcomp : IsRetrocompact U) : + IsConstructible U := BooleanSubalgebra.subset_closure ⟨hUopen, hUcomp⟩ + +/-- An induction principle for constructible sets. If `p` holds for all open retrocompact +sets, and is preserved under union and complement, then `p` holds for all constructible sets. -/ +@[elab_as_elim] +lemma IsConstructible.empty_union_induction {p : ∀ s : Set X, IsConstructible s → Prop} + (open_retrocompact : ∀ U (hUopen : IsOpen U) (hUcomp : IsRetrocompact U), + p U (BooleanSubalgebra.subset_closure ⟨hUopen, hUcomp⟩)) + (union : ∀ s hs t ht, p s hs → p t ht → p (s ∪ t) (hs.union ht)) + (compl : ∀ s hs, p s hs → p sᶜ hs.compl) {s} (hs : IsConstructible s) : p s hs := by + induction hs using BooleanSubalgebra.closure_bot_sup_induction with + | mem U hU => exact open_retrocompact _ hU.1 hU.2 + | bot => exact open_retrocompact _ isOpen_empty .empty + | sup s hs t ht hs' ht' => exact union _ _ _ _ hs' ht' + | compl s hs hs' => exact compl _ _ hs' + +/-- If `f` is continuous and is such that preimages of retrocompact sets are retrocompact, then +preimages of constructible sets are constructible. -/ +@[stacks 005I] +lemma IsConstructible.preimage {s : Set Y} (hfcont : Continuous f) + (hf : ∀ s, IsRetrocompact s → IsRetrocompact (f ⁻¹' s)) (hs : IsConstructible s) : + IsConstructible (f ⁻¹' s) := by + induction hs using IsConstructible.empty_union_induction with + | open_retrocompact U hUopen hUcomp => + exact (hf _ hUcomp).isConstructible <| hUopen.preimage hfcont + | union s hs t ht hs' ht' => rw [preimage_union]; exact hs'.union ht' + | compl s hs hs' => rw [preimage_compl]; exact hs'.compl + +@[stacks 005J] +lemma IsConstructible.preimage_of_isOpenEmbedding {s : Set Y} (hf : IsOpenEmbedding f) + (hs : IsConstructible s) : IsConstructible (f ⁻¹' s) := + hs.preimage hf.continuous fun _t ht ↦ ht.preimage_of_isOpenEmbedding hf + +@[stacks 09YE] +lemma IsConstructible.preimage_of_isClosedEmbedding {s : Set Y} (hf : IsClosedEmbedding f) + (hf' : IsCompact (range f)ᶜ) (hs : IsConstructible s) : IsConstructible (f ⁻¹' s) := + hs.preimage hf.continuous fun _t ht ↦ ht.preimage_of_isClosedEmbedding hf hf' + +@[stacks 09YD] +lemma IsConstructible.image_of_isOpenEmbedding (hfopen : IsOpenEmbedding f) + (hfcomp : IsRetrocompact (range f)) (hs : IsConstructible s) : IsConstructible (f '' s) := by + induction hs using IsConstructible.empty_union_induction with + | open_retrocompact U hUopen hUcomp => + exact (hUcomp.image_of_isEmbedding hfopen.isEmbedding hfcomp).isConstructible <| + hfopen.isOpenMap _ hUopen + | union s hs t ht hs' ht' => rw [image_union]; exact hs'.union ht' + | compl s hs hs' => + rw [← range_diff_image hfopen.injective] + exact (hfcomp.isConstructible hfopen.isOpen_range).sdiff hs' + +@[stacks 09YG] +lemma IsConstructible.image_of_isClosedEmbedding (hf : IsClosedEmbedding f) + (hfcomp : IsRetrocompact (range f)ᶜ) (hs : IsConstructible s) : IsConstructible (f '' s) := by + induction hs using IsConstructible.empty_union_induction with + | open_retrocompact U hUopen hUcomp => + have hfU : IsOpen (f '' U ∪ (range f)ᶜ) := by + simpa [← range_diff_image hf.injective, sdiff_eq, compl_inter, union_comm] + using (hf.isClosedMap _ hUopen.isClosed_compl).isOpen_compl + suffices h : IsRetrocompact (f '' U ∪ (range f)ᶜ) by + simpa [union_inter_distrib_right, inter_eq_left.2 (image_subset_range ..)] + using (h.isConstructible hfU).sdiff (hfcomp.isConstructible hf.isClosed_range.isOpen_compl) + rintro V hVcomp hVopen + rw [union_inter_distrib_right, ← image_inter_preimage] + exact ((hUcomp (hf.isCompact_preimage hVcomp) (hVopen.preimage hf.continuous)).image + hf.continuous).union <| hfcomp hVcomp hVopen + | union s hs t ht hs' ht' => rw [image_union]; exact hs'.union ht' + | compl s hs hs' => + rw [← range_diff_image hf.injective] + exact (hfcomp.isConstructible hf.isClosed_range.isOpen_compl).of_compl.sdiff hs' + +lemma isConstructible_preimage_iff_of_isOpenEmbedding {s : Set Y} (hf : IsOpenEmbedding f) + (hfcomp : IsRetrocompact (range f)) (hsf : s ⊆ range f) : + IsConstructible (f ⁻¹' s) ↔ IsConstructible s where + mp hs := by simpa [image_preimage_eq_range_inter, inter_eq_right.2 hsf] + using hs.image_of_isOpenEmbedding hf hfcomp + mpr := .preimage_of_isOpenEmbedding hf + +section CompactSpace +variable [CompactSpace X] {P : ∀ s : Set X, IsConstructible s → Prop} {B : Set (Set X)} + {b : ι → Set X} + +lemma _root_.IsRetrocompact.isCompact (hs : IsRetrocompact s) : IsCompact s := by + simpa using hs CompactSpace.isCompact_univ + +/-- Variant of `TopologicalSpace.IsTopologicalBasis.isRetrocompact_iff_isCompact` for a +non-indexed topological basis. -/ +lemma _root_.TopologicalSpace.IsTopologicalBasis.isRetrocompact_iff_isCompact' + (basis : IsTopologicalBasis B) (compact_inter : ∀ U ∈ B, ∀ V ∈ B, IsCompact (U ∩ V)) + (hU : IsOpen U) : IsRetrocompact U ↔ IsCompact U := by + refine ⟨IsRetrocompact.isCompact, fun hU' {V} hV' hV ↦ ?_⟩ + obtain ⟨s, rfl⟩ := eq_sUnion_finset_of_isTopologicalBasis_of_isCompact_open _ basis _ hU' hU + obtain ⟨t, rfl⟩ := eq_sUnion_finset_of_isTopologicalBasis_of_isCompact_open _ basis _ hV' hV + rw [Set.sUnion_inter_sUnion] + refine ((s.finite_toSet.image _).prod (t.finite_toSet.image _)).isCompact_biUnion ?_ + simp only [mem_prod, mem_image, Finset.mem_coe, Subtype.exists, exists_and_right, exists_eq_right, + and_imp, forall_exists_index, Prod.forall] + exact fun u v hu _ hv _ ↦ compact_inter _ hu _ hv + +lemma _root_.TopologicalSpace.IsTopologicalBasis.isRetrocompact_iff_isCompact + (basis : IsTopologicalBasis (range b)) (compact_inter : ∀ i j, IsCompact (b i ∩ b j)) + (hU : IsOpen U) : IsRetrocompact U ↔ IsCompact U := + basis.isRetrocompact_iff_isCompact' (by simpa using compact_inter) hU + +/-- Variant of `TopologicalSpace.IsTopologicalBasis.isRetrocompact` for a non-indexed topological +basis. -/ +lemma _root_.TopologicalSpace.IsTopologicalBasis.isRetrocompact' (basis : IsTopologicalBasis B) + (compact_inter : ∀ U ∈ B, ∀ V ∈ B, IsCompact (U ∩ V)) (hU : U ∈ B) : IsRetrocompact U := + (basis.isRetrocompact_iff_isCompact' compact_inter <| basis.isOpen hU).2 <| by + simpa using compact_inter _ hU _ hU + +lemma _root_.TopologicalSpace.IsTopologicalBasis.isRetrocompact + (basis : IsTopologicalBasis (range b)) (compact_inter : ∀ i j, IsCompact (b i ∩ b j)) (i : ι) : + IsRetrocompact (b i) := + (basis.isRetrocompact_iff_isCompact compact_inter <| basis.isOpen <| mem_range_self _).2 <| by + simpa using compact_inter i i + +/-- Variant of `TopologicalSpace.IsTopologicalBasis.isConstructible` for a non-indexed topological +basis. -/ +lemma _root_.TopologicalSpace.IsTopologicalBasis.isConstructible' (basis : IsTopologicalBasis B) + (compact_inter : ∀ U ∈ B, ∀ V ∈ B, IsCompact (U ∩ V)) (hU : U ∈ B) : IsConstructible U := + (basis.isRetrocompact' compact_inter hU).isConstructible <| basis.isOpen hU + +lemma _root_.TopologicalSpace.IsTopologicalBasis.isConstructible + (basis : IsTopologicalBasis (range b)) (compact_inter : ∀ i j, IsCompact (b i ∩ b j)) (i : ι) : + IsConstructible (b i) := + (basis.isRetrocompact compact_inter _).isConstructible <| basis.isOpen <| mem_range_self _ + +@[elab_as_elim] +lemma IsConstructible.induction_of_isTopologicalBasis {ι : Type*} [Nonempty ι] (b : ι → Set X) + (basis : IsTopologicalBasis (range b)) (compact_inter : ∀ i j, IsCompact (b i ∩ b j)) + (sdiff : ∀ i s (hs : Set.Finite s), P (b i \ ⋃ j ∈ s, b j) + ((basis.isConstructible compact_inter _).sdiff <| .biUnion hs fun _ _ ↦ + basis.isConstructible compact_inter _)) + (union : ∀ s hs t ht, P s hs → P t ht → P (s ∪ t) (hs.union ht)) + (s : Set X) (hs : IsConstructible s) : P s hs := by + induction s, hs using BooleanSubalgebra.closure_sdiff_sup_induction with + | isSublattice => + exact ⟨fun s hs t ht ↦ ⟨hs.1.union ht.1, hs.2.union ht.2⟩, + fun s hs t ht ↦ ⟨hs.1.inter ht.1, hs.2.inter_isOpen ht.2 ht.1⟩⟩ + | bot_mem => exact ⟨isOpen_empty, .empty⟩ + | top_mem => exact ⟨isOpen_univ, .univ⟩ + | sdiff U hU V hV => + have := isCompact_open_iff_eq_finite_iUnion_of_isTopologicalBasis _ basis + fun i ↦ by simpa using compact_inter i i + obtain ⟨s, hs, rfl⟩ := (this _).1 ⟨hU.2.isCompact, hU.1⟩ + obtain ⟨t, ht, rfl⟩ := (this _).1 ⟨hV.2.isCompact, hV.1⟩ + simp_rw [iUnion_diff] + induction s, hs using Set.Finite.induction_on with + | empty => simpa using sdiff (Classical.arbitrary _) {Classical.arbitrary _} + | @insert i s hi hs ih => + simp_rw [biUnion_insert] + exact union _ _ _ + (.biUnion hs fun i _ ↦ (basis.isConstructible compact_inter _).sdiff <| + .biUnion ht fun j _ ↦ basis.isConstructible compact_inter _) + (sdiff _ _ ht) + (ih ⟨isOpen_biUnion fun _ _ ↦ basis.isOpen ⟨_, rfl⟩, .biUnion hs + fun i _ ↦ basis.isRetrocompact compact_inter _⟩) + | sup s _ t _ hs' ht' => exact union _ _ _ _ hs' ht' + +end CompactSpace + +/-! ### Locally constructible sets -/ + +/-- A set in a topological space is locally constructible, if every point has a neighborhood on +which the set is constructible. -/ +@[stacks 005G] +def IsLocallyConstructible (s : Set X) : Prop := ∀ x, ∃ U ∈ 𝓝 x, IsOpen U ∧ IsConstructible (U ↓∩ s) + +lemma IsConstructible.isLocallyConstructible (hs : IsConstructible s) : IsLocallyConstructible s := + fun _ ↦ ⟨univ, by simp, by simp, + (isConstructible_preimage_iff_of_isOpenEmbedding isOpen_univ.isOpenEmbedding_subtypeVal + (by simp) (by simp)).2 hs⟩ + +lemma _root_.IsRetrocompact.isLocallyConstructible (hUopen : IsOpen U) (hUcomp : IsRetrocompact U) : + IsLocallyConstructible U := (hUcomp.isConstructible hUopen).isLocallyConstructible + +@[simp] protected lemma IsLocallyConstructible.empty : IsLocallyConstructible (∅ : Set X) := + IsConstructible.empty.isLocallyConstructible + +@[simp] protected lemma IsLocallyConstructible.univ : IsLocallyConstructible (univ : Set X) := + IsConstructible.univ.isLocallyConstructible + +lemma IsLocallyConstructible.inter (hs : IsLocallyConstructible s) (ht : IsLocallyConstructible t) : + IsLocallyConstructible (s ∩ t) := by + rintro x + obtain ⟨U, hxU, hU, hsU⟩ := hs x + obtain ⟨V, hxV, hV, htV⟩ := ht x + refine ⟨U ∩ V, Filter.inter_mem hxU hxV, hU.inter hV, ?_⟩ + change IsConstructible + (inclusion inter_subset_left ⁻¹' (U ↓∩ s) ∩ inclusion inter_subset_right ⁻¹' (V ↓∩ t)) + exact .inter (hsU.preimage_of_isOpenEmbedding <| .inclusion _ <| + .preimage continuous_subtype_val <| hU.inter hV) + (htV.preimage_of_isOpenEmbedding <| .inclusion _ <| + .preimage continuous_subtype_val <| hU.inter hV ) + +lemma IsLocallyConstructible.finsetInf {ι : Type*} {s : Finset ι} {t : ι → Set X} + (ht : ∀ i ∈ s, IsLocallyConstructible (t i)) : IsLocallyConstructible (s.inf t) := by + induction' s using Finset.cons_induction with i s ih hi + · simp + · rw [Finset.inf_cons] + exact (ht _ <| by simp).inter <| hi <| Finset.forall_of_forall_cons ht + +set_option linter.docPrime false in +lemma IsLocallyConstructible.finsetInf' {ι : Type*} {s : Finset ι} {hs} {t : ι → Set X} + (ht : ∀ i ∈ s, IsLocallyConstructible (t i)) : IsLocallyConstructible (s.inf' hs t) := by + rw [Finset.inf'_eq_inf]; exact .finsetInf ht + +private lemma infClosed_isLocallyConstructible : InfClosed {s : Set X | IsLocallyConstructible s} := + fun _s hs _t ht ↦ hs.inter ht + +lemma IsLocallyConstructible.iInter [Finite ι] {f : ι → Set X} + (hf : ∀ i, IsLocallyConstructible (f i)) : IsLocallyConstructible (⋂ i, f i) := + infClosed_isLocallyConstructible.iInf_mem .univ hf + +lemma IsLocallyConstructible.sInter {S : Set (Set X)} (hS : S.Finite) + (hS' : ∀ s ∈ S, IsLocallyConstructible s) : IsLocallyConstructible (⋂₀ S) := + infClosed_isLocallyConstructible.sInf_mem hS .univ hS' + +end Topology diff --git a/Mathlib/Topology/Constructions.lean b/Mathlib/Topology/Constructions.lean index 3eac03c81156e..468b25f3f1616 100644 --- a/Mathlib/Topology/Constructions.lean +++ b/Mathlib/Topology/Constructions.lean @@ -37,6 +37,7 @@ product, sum, disjoint union, subspace, quotient space noncomputable section open Topology TopologicalSpace Set Filter Function +open scoped Set.Notation universe u v @@ -1153,9 +1154,21 @@ protected lemma Topology.IsEmbedding.codRestrict {e : X → Y} (he : IsEmbedding @[deprecated (since := "2024-10-26")] alias Embedding.codRestrict := IsEmbedding.codRestrict -protected lemma Topology.IsEmbedding.inclusion {s t : Set X} (h : s ⊆ t) : +variable {s t : Set X} + +protected lemma Topology.IsEmbedding.inclusion (h : s ⊆ t) : IsEmbedding (inclusion h) := IsEmbedding.subtypeVal.codRestrict _ _ +protected lemma Topology.IsOpenEmbedding.inclusion (hst : s ⊆ t) (hs : IsOpen (t ↓∩ s)) : + IsOpenEmbedding (inclusion hst) where + toIsEmbedding := .inclusion _ + isOpen_range := by rwa [range_inclusion] + +protected lemma Topology.IsClosedEmbedding.inclusion (hst : s ⊆ t) (hs : IsClosed (t ↓∩ s)) : + IsClosedEmbedding (inclusion hst) where + toIsEmbedding := .inclusion _ + isClosed_range := by rwa [range_inclusion] + @[deprecated (since := "2024-10-26")] alias embedding_inclusion := IsEmbedding.inclusion From f088ec9d4a2a560ae7904961913390dd06c5d044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Fri, 24 Jan 2025 10:30:32 +0000 Subject: [PATCH 477/681] chore(AlgebraicTopology): make stdSimplex a cosimplicial object (#20954) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functor `stdSimplex : SimplexCategory ⥤ SSet.{u}` is redefined to the defeq type of cosimplicial objects in `SSet`. This allows the use of the notation `stdSimplex.δ i` instead of `stdSimplex.map (SimplexCategory.δ i)`. Co-authored-by: gio256 <102917377+gio256@users.noreply.github.com> --- Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean index 26a81d25fb187..998e24cce1c55 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean @@ -69,9 +69,10 @@ lemma comp_app {X Y Z : SSet} (f : X ⟶ Y) (g : Y ⟶ Z) (n : SimplexCategory def uliftFunctor : SSet.{u} ⥤ SSet.{max u v} := (SimplicialObject.whiskering _ _).obj CategoryTheory.uliftFunctor.{v, u} -/-- The `n`-th standard simplex `Δ[n]` associated with a nonempty finite linear order `n` -is the Yoneda embedding of `n`. -/ -def stdSimplex : SimplexCategory ⥤ SSet.{u} := +/-- The functor `SimplexCategory ⥤ SSet` which sends `SimplexCategory.mk n` to +the standard simplex `Δ[n]` is a cosimplicial object in the category of simplicial sets. +(This functor is essentially given by the Yoneda embedding). -/ +def stdSimplex : CosimplicialObject SSet.{u} := yoneda ⋙ uliftFunctor @[deprecated (since := "2025-01-23")] alias standardSimplex := stdSimplex @@ -339,8 +340,7 @@ open Simplicial /-- The simplicial circle. -/ noncomputable def S1 : SSet := Limits.colimit <| - Limits.parallelPair (stdSimplex.map <| SimplexCategory.δ 0 : Δ[0] ⟶ Δ[1]) - (stdSimplex.map <| SimplexCategory.δ 1) + Limits.parallelPair (stdSimplex.δ 0 : Δ[0] ⟶ Δ[1]) (stdSimplex.δ 1) end Examples From 0b8fbb6182760e5cd62bdcbfb1b732308b7e6c5b Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Fri, 24 Jan 2025 10:30:33 +0000 Subject: [PATCH 478/681] feat(Analysis/Analytic/IsolatedZeros): vanishing of products (#20996) If a product of analytic functions (on a preconnected set) is zero, then one of the factors is zero. --- Mathlib/Analysis/Analytic/IsolatedZeros.lean | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index de1d205483fbb..94a872b1f4840 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -7,6 +7,7 @@ import Mathlib.Analysis.Analytic.Constructions import Mathlib.Analysis.Calculus.DSlope import Mathlib.Analysis.Calculus.FDeriv.Analytic import Mathlib.Analysis.Analytic.Uniqueness +import Mathlib.Topology.Perfect /-! # Principle of isolated zeros @@ -306,4 +307,46 @@ theorem eq_of_frequently_eq [ConnectedSpace 𝕜] (hf : AnalyticOnNhd 𝕜 f uni @[deprecated (since := "2024-09-26")] alias _root_.AnalyticOn.eq_of_frequently_eq := eq_of_frequently_eq +section Mul +/-! +### Vanishing of products of analytic functions +-/ + +variable {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] + {B : Type*} [NormedAddCommGroup B] [NormedSpace 𝕜 B] [Module A B] + +/-- If `f, g` are analytic on a neighbourhood of the preconnected open set `U`, and `f • g = 0` +on `U`, then either `f = 0` on `U` or `g = 0` on `U`. -/ +lemma eq_zero_or_eq_zero_of_smul_eq_zero [NoZeroSMulDivisors A B] + {f : 𝕜 → A} {g : 𝕜 → B} (hf : AnalyticOnNhd 𝕜 f U) (hg : AnalyticOnNhd 𝕜 g U) + (hfg : ∀ z ∈ U, f z • g z = 0) (hU : IsPreconnected U) : + (∀ z ∈ U, f z = 0) ∨ (∀ z ∈ U, g z = 0) := by + -- We want to apply `IsPreconnected.preperfect_of_nontrivial` which requires `U` to have at least + -- two elements. So we need to dispose of the cases `#U = 0` and `#U = 1` first. + by_cases hU' : U = ∅ + · simp [hU'] + obtain ⟨z, hz⟩ : ∃ z, z ∈ U := nonempty_iff_ne_empty.mpr hU' + by_cases hU'' : U = {z} + · simpa [hU''] using hfg z hz + apply (nontrivial_iff_ne_singleton hz).mpr at hU'' + -- Now connectedness implies that `z` is an accumulation point of `U`, so at least one of + -- `f` and `g` must vanish frequently in a neighbourhood of `z`. + have : ∃ᶠ w in 𝓝[≠] z, w ∈ U := + frequently_mem_iff_neBot.mpr <| hU.preperfect_of_nontrivial hU'' z hz + have : ∃ᶠ w in 𝓝[≠] z, f w = 0 ∨ g w = 0 := + this.mp <| by filter_upwards with w hw using smul_eq_zero.mp (hfg w hw) + cases frequently_or_distrib.mp this with + | inl h => exact Or.inl <| hf.eqOn_zero_of_preconnected_of_frequently_eq_zero hU hz h + | inr h => exact Or.inr <| hg.eqOn_zero_of_preconnected_of_frequently_eq_zero hU hz h + +/-- If `f, g` are analytic on a neighbourhood of the preconnected open set `U`, and `f * g = 0` +on `U`, then either `f = 0` on `U` or `g = 0` on `U`. -/ +lemma eq_zero_or_eq_zero_of_mul_eq_zero [NoZeroDivisors A] + {f g : 𝕜 → A} (hf : AnalyticOnNhd 𝕜 f U) (hg : AnalyticOnNhd 𝕜 g U) + (hfg : ∀ z ∈ U, f z * g z = 0) (hU : IsPreconnected U) : + (∀ z ∈ U, f z = 0) ∨ (∀ z ∈ U, g z = 0) := + eq_zero_or_eq_zero_of_smul_eq_zero hf hg hfg hU + +end Mul + end AnalyticOnNhd From 57182707e9672ad6206aef8a729e9b989f66b195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Dvo=C5=99=C3=A1k?= Date: Fri, 24 Jan 2025 10:39:58 +0000 Subject: [PATCH 479/681] =?UTF-8?q?style(Computability/ContextFreeGrammar/?= =?UTF-8?q?reverse):=20injective=20and=20surjec=E2=80=A6=20(#19325)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …tive from bijective --- Mathlib/Computability/ContextFreeGrammar.lean | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mathlib/Computability/ContextFreeGrammar.lean b/Mathlib/Computability/ContextFreeGrammar.lean index 62502385e7d1f..aae94be8a4dc5 100644 --- a/Mathlib/Computability/ContextFreeGrammar.lean +++ b/Mathlib/Computability/ContextFreeGrammar.lean @@ -223,10 +223,10 @@ lemma reverse_bijective : Bijective (reverse : ContextFreeRule T N → ContextFr reverse_involutive.bijective lemma reverse_injective : Injective (reverse : ContextFreeRule T N → ContextFreeRule T N) := - reverse_involutive.injective + reverse_bijective.injective lemma reverse_surjective : Surjective (reverse : ContextFreeRule T N → ContextFreeRule T N) := - reverse_involutive.surjective + reverse_bijective.surjective protected lemma Rewrites.reverse : ∀ {u v}, r.Rewrites u v → r.reverse.Rewrites u.reverse v.reverse | _, _, head s => by simpa using .append_left .input_output _ @@ -257,10 +257,10 @@ lemma reverse_bijective : Bijective (reverse : ContextFreeGrammar T → ContextF reverse_involutive.bijective lemma reverse_injective : Injective (reverse : ContextFreeGrammar T → ContextFreeGrammar T) := - reverse_involutive.injective + reverse_bijective.injective lemma reverse_surjective : Surjective (reverse : ContextFreeGrammar T → ContextFreeGrammar T) := - reverse_involutive.surjective + reverse_bijective.surjective lemma produces_reverse : g.reverse.Produces u.reverse v.reverse ↔ g.Produces u v := (Equiv.ofBijective _ ContextFreeRule.reverse_bijective).exists_congr From e1f9f040625dc9473eade841874dfea86c33dd60 Mon Sep 17 00:00:00 2001 From: Whysoserioushah <109107491+Whysoserioushah@users.noreply.github.com> Date: Fri, 24 Jan 2025 11:21:05 +0000 Subject: [PATCH 480/681] feat(Algebra/Azumaya/Defs): Define Azumaya algebras (#20489) Co-authored-by: Whysoserioushah Co-authored-by: Jujian Zhang --- Mathlib.lean | 1 + Mathlib/Algebra/Azumaya/Defs.lean | 58 +++++++++++++++++++++++++++++++ docs/references.bib | 11 ++++++ 3 files changed, 70 insertions(+) create mode 100644 Mathlib/Algebra/Azumaya/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index a93503d6b2071..283e0ddac24f2 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -35,6 +35,7 @@ import Mathlib.Algebra.Algebra.Tower import Mathlib.Algebra.Algebra.Unitization import Mathlib.Algebra.Algebra.ZMod import Mathlib.Algebra.AlgebraicCard +import Mathlib.Algebra.Azumaya.Defs import Mathlib.Algebra.BigOperators.Associated import Mathlib.Algebra.BigOperators.Balance import Mathlib.Algebra.BigOperators.Expect diff --git a/Mathlib/Algebra/Azumaya/Defs.lean b/Mathlib/Algebra/Azumaya/Defs.lean new file mode 100644 index 0000000000000..08c3a24d68833 --- /dev/null +++ b/Mathlib/Algebra/Azumaya/Defs.lean @@ -0,0 +1,58 @@ +/- +Copyright (c) 2025 Yunzhou Xie. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yunzhou Xie, Jujian Zhang +-/ +import Mathlib.Algebra.Module.Projective +import Mathlib.RingTheory.Finiteness.Defs +import Mathlib.RingTheory.TensorProduct.Basic + +/-! +# Azumaya Algebras + +An Azumaya algebra over a commutative ring `R` is a finitely generated, projective +and faithful R-algebra where the tensor product `A ⊗[R] Aᵐᵒᵖ` is isomorphic to the +`R`-endomorphisms of A via the map `f : a ⊗ b ↦ (x ↦ a * x * b.unop)`. +TODO : Add the three more definitions and prove they are equivalent: +· There exists an `R`-algebra `B` such that `B ⊗[R] A` is Morita equivalent to `R`; +· `Aᵐᵒᵖ ⊗[R] A` is Morita equivalent to `R`; +· The center of `A` is `R` and `A` is a separable algebra. + +## Reference + +* [Benson Farb , R. Keith Dennis, *Noncommutative Algebra*][bensonfarb1993] + +## Tags + +Azumaya algebra, central simple algebra, noncommutative algebra +-/ + +variable (R A : Type*) [CommSemiring R] [Semiring A] [Algebra R A] + +open TensorProduct MulOpposite + +/-- `A` as a `A ⊗[R] Aᵐᵒᵖ`-module (or equivalently, an `A`-`A` bimodule). -/ +noncomputable abbrev instModuleTensorProductMop : + Module (A ⊗[R] Aᵐᵒᵖ) A := TensorProduct.Algebra.module + +/-- The canonical map from `A ⊗[R] Aᵐᵒᵖ` to `Module.End R A` where + `a ⊗ b` maps to `f : x ↦ a * x * b`. -/ +noncomputable def AlgHom.mulLeftRight : (A ⊗[R] Aᵐᵒᵖ) →ₐ[R] Module.End R A := + letI : Module (A ⊗[R] Aᵐᵒᵖ) A := TensorProduct.Algebra.module + letI : IsScalarTower R (A ⊗[R] Aᵐᵒᵖ) A := { + smul_assoc := fun r ab a ↦ by + change TensorProduct.Algebra.moduleAux _ _ = _ • TensorProduct.Algebra.moduleAux _ _ + simp } + Algebra.lsmul R (A := A ⊗[R] Aᵐᵒᵖ) R A + +@[simp] +lemma AlgHom.mulLeftRight_apply (a : A) (b : Aᵐᵒᵖ) (x : A) : + AlgHom.mulLeftRight R A (a ⊗ₜ b) x = a * x * b.unop := by + simp only [AlgHom.mulLeftRight, Algebra.lsmul_coe] + change TensorProduct.Algebra.moduleAux _ _ = _ + simp [TensorProduct.Algebra.moduleAux, ← mul_assoc] + +/-- An Azumaya algebra is a finitely generated, projective and faithful R-algebra where + `AlgHom.mulLeftRight R A : (A ⊗[R] Aᵐᵒᵖ) →ₐ[R] Module.End R A` is an isomorphism. -/ +class IsAzumaya extends Module.Projective R A, FaithfulSMul R A, Module.Finite R A : Prop where + bij : Function.Bijective <| AlgHom.mulLeftRight R A diff --git a/docs/references.bib b/docs/references.bib index 9136aacea3cb3..50eba91c9488f 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -276,6 +276,17 @@ @Book{ behrends1979 zbl = {0436.46013} } +@Book{ bensonfarb1993, + author = {Benson Farb, R. Keith Dennis}, + series = {Graduate Texts in Mathematics}, + title = {Noncommutative Algebra}, + year = {1993}, + publisher = {Springer}, + language = {English}, + volume = {144}, + url = {https://link.springer.com/book/10.1007/978-1-4612-0889-1} +} + @Article{ bergelson1985, author = {Bergelson, Vitaly}, title = {Sets of Recurrence of Zm-Actions and Properties of Sets of From 33cc4f3c0df43887bbd33ba56eedf811fbcba173 Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Fri, 24 Jan 2025 14:15:59 +0000 Subject: [PATCH 481/681] feat(Topology/Algebra/TopologicallyNilpotent): top nilpotent in linear topologies (#20971) In a monoid with zero and a topology, an element is topologically nilpotent if its powers converge to zero. In a ring with a linear topology, sum and product of (commuting) topologically nilpotent elements are topologically nilpotent. --- Mathlib.lean | 1 + Mathlib/RingTheory/Ideal/Basic.lean | 38 +++-- Mathlib/RingTheory/Ideal/Defs.lean | 16 +-- .../Algebra/TopologicallyNilpotent.lean | 130 ++++++++++++++++++ 4 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 Mathlib/Topology/Algebra/TopologicallyNilpotent.lean diff --git a/Mathlib.lean b/Mathlib.lean index 283e0ddac24f2..e5ac44298f4a6 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5243,6 +5243,7 @@ import Mathlib.Topology.Algebra.SeparationQuotient.Section import Mathlib.Topology.Algebra.Star import Mathlib.Topology.Algebra.StarSubalgebra import Mathlib.Topology.Algebra.Support +import Mathlib.Topology.Algebra.TopologicallyNilpotent import Mathlib.Topology.Algebra.UniformConvergence import Mathlib.Topology.Algebra.UniformField import Mathlib.Topology.Algebra.UniformFilterBasis diff --git a/Mathlib/RingTheory/Ideal/Basic.lean b/Mathlib/RingTheory/Ideal/Basic.lean index 9ce9f9e98dea1..bb6c5745b3faf 100644 --- a/Mathlib/RingTheory/Ideal/Basic.lean +++ b/Mathlib/RingTheory/Ideal/Basic.lean @@ -53,6 +53,31 @@ theorem mem_pi (x : Π i, α i) : x ∈ pi I ↔ ∀ i, x i ∈ I i := end Pi +section Commute + +variable {α : Type*} [Semiring α] (I : Ideal α) {a b : α} + +theorem add_pow_mem_of_pow_mem_of_le_of_commute {m n k : ℕ} + (ha : a ^ m ∈ I) (hb : b ^ n ∈ I) (hk : m + n ≤ k + 1) + (hab : Commute a b) : + (a + b) ^ k ∈ I := by + simp_rw [hab.add_pow, ← Nat.cast_comm] + apply I.sum_mem + intro c _ + apply mul_mem_left + by_cases h : m ≤ c + · rw [hab.pow_pow] + exact I.mul_mem_left _ (I.pow_mem_of_pow_mem ha h) + · refine I.mul_mem_left _ (I.pow_mem_of_pow_mem hb ?_) + omega + +theorem add_pow_add_pred_mem_of_pow_mem_of_commute {m n : ℕ} + (ha : a ^ m ∈ I) (hb : b ^ n ∈ I) (hab : Commute a b) : + (a + b) ^ (m + n - 1) ∈ I := + I.add_pow_mem_of_pow_mem_of_le_of_commute ha hb (by rw [← Nat.sub_le_iff_le_add]) hab + +end Commute + end Ideal end Semiring @@ -69,20 +94,13 @@ variable [CommSemiring α] (I : Ideal α) theorem add_pow_mem_of_pow_mem_of_le {m n k : ℕ} (ha : a ^ m ∈ I) (hb : b ^ n ∈ I) (hk : m + n ≤ k + 1) : - (a + b) ^ k ∈ I := by - rw [add_pow] - apply I.sum_mem - intro c _ - apply mul_mem_right - by_cases h : m ≤ c - · exact I.mul_mem_right _ (I.pow_mem_of_pow_mem ha h) - · refine I.mul_mem_left _ (I.pow_mem_of_pow_mem hb ?_) - omega + (a + b) ^ k ∈ I := + I.add_pow_mem_of_pow_mem_of_le_of_commute ha hb hk (Commute.all ..) theorem add_pow_add_pred_mem_of_pow_mem {m n : ℕ} (ha : a ^ m ∈ I) (hb : b ^ n ∈ I) : (a + b) ^ (m + n - 1) ∈ I := - I.add_pow_mem_of_pow_mem_of_le ha hb <| by rw [← Nat.sub_le_iff_le_add] + I.add_pow_add_pred_mem_of_pow_mem_of_commute ha hb (Commute.all ..) theorem pow_multiset_sum_mem_span_pow [DecidableEq α] (s : Multiset α) (n : ℕ) : s.sum ^ (Multiset.card s * n + 1) ∈ diff --git a/Mathlib/RingTheory/Ideal/Defs.lean b/Mathlib/RingTheory/Ideal/Defs.lean index ba78f8a4b205b..ca2e6072c593a 100644 --- a/Mathlib/RingTheory/Ideal/Defs.lean +++ b/Mathlib/RingTheory/Ideal/Defs.lean @@ -66,6 +66,14 @@ theorem unit_mul_mem_iff_mem {x y : α} (hy : IsUnit y) : y * x ∈ I ↔ x ∈ have := I.mul_mem_left y' h rwa [← mul_assoc, hy', one_mul] at this +theorem pow_mem_of_mem (ha : a ∈ I) (n : ℕ) (hn : 0 < n) : a ^ n ∈ I := + Nat.casesOn n (Not.elim (by decide)) + (fun m _hm => (pow_succ a m).symm ▸ I.mul_mem_left (a ^ m) ha) hn + +theorem pow_mem_of_pow_mem {m n : ℕ} (ha : a ^ m ∈ I) (h : m ≤ n) : a ^ n ∈ I := by + rw [← Nat.add_sub_of_le h, add_comm, pow_add] + exact I.mul_mem_left _ ha + end Ideal /-- For two elements `m` and `m'` in an `R`-module `M`, the set of elements `r : R` with @@ -103,14 +111,6 @@ variable {b} lemma mem_of_dvd (hab : a ∣ b) (ha : a ∈ I) : b ∈ I := by obtain ⟨c, rfl⟩ := hab; exact I.mul_mem_right _ ha -theorem pow_mem_of_mem (ha : a ∈ I) (n : ℕ) (hn : 0 < n) : a ^ n ∈ I := - Nat.casesOn n (Not.elim (by decide)) - (fun m _hm => (pow_succ a m).symm ▸ I.mul_mem_left (a ^ m) ha) hn - -theorem pow_mem_of_pow_mem {m n : ℕ} (ha : a ^ m ∈ I) (h : m ≤ n) : a ^ n ∈ I := by - rw [← Nat.add_sub_of_le h, pow_add] - exact I.mul_mem_right _ ha - end Ideal end CommSemiring diff --git a/Mathlib/Topology/Algebra/TopologicallyNilpotent.lean b/Mathlib/Topology/Algebra/TopologicallyNilpotent.lean new file mode 100644 index 0000000000000..e9a9dea659cfa --- /dev/null +++ b/Mathlib/Topology/Algebra/TopologicallyNilpotent.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2024 Antoine Chambert-Loir, María Inés de Frutos-Fernández. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Antoine Chambert-Loir, María Inés de Frutos-Fernández +-/ +import Mathlib.Topology.Algebra.LinearTopology +import Mathlib.RingTheory.Ideal.Basic + +/-! # Topologically nilpotent elements + +Let `M` be a monoid with zero `M`, endowed with a topology. + +* `IsTopologicallyNilpotent a` says that `a : M` is *topologically nilpotent*, +ie, its powers converge to zero. + +* `IsTopologicallyNilpotent.map`: +The image of a topologically nilpotent element under a continuous morphism of +monoids with zero endowed with a topology is topologically nilpotent. + +* `IsTopologicallyNilpotent.zero`: `0` is topologically nilpotent. + +Let `R` be a commutative ring with a linear topology. + +* `IsTopologicallyNilpotent.mul_left`: if `a : R` is topologically nilpotent, +then `a*b` is topologically nilpotent. + +* `IsTopologicallyNilpotent.mul_right`: if `a : R` is topologically nilpotent, +then `a * b` is topologically nilpotent. + +* `IsTopologicallyNilpotent.add`: if `a b : R` are topologically nilpotent, +then `a + b` is topologically nilpotent. + +These lemmas are actually deduced from their analogues for commuting elements of rings. + +-/ + +open Filter + +open scoped Topology + +/-- An element is topologically nilpotent if its powers converge to `0`. -/ +def IsTopologicallyNilpotent + {R : Type*} [MonoidWithZero R] [TopologicalSpace R] (a : R) : Prop := + Tendsto (a ^ ·) atTop (𝓝 0) + +namespace IsTopologicallyNilpotent + +section MonoidWithZero + +variable {R S : Type*} [TopologicalSpace R] [MonoidWithZero R] + [MonoidWithZero S] [TopologicalSpace S] + +/-- The image of a topologically nilpotent element under a continuous morphism + is topologically nilpotent -/ +theorem map {F : Type*} [FunLike F R S] [MonoidWithZeroHomClass F R S] + {φ : F} (hφ : Continuous φ) {a : R} (ha : IsTopologicallyNilpotent a) : + IsTopologicallyNilpotent (φ a) := by + unfold IsTopologicallyNilpotent at ha ⊢ + simp_rw [← map_pow] + exact (map_zero φ ▸ hφ.tendsto 0).comp ha + +/-- `0` is topologically nilpotent -/ +theorem zero : IsTopologicallyNilpotent (0 : R) := + tendsto_atTop_of_eventually_const (i₀ := 1) + (fun _ hi => by rw [zero_pow (Nat.ne_zero_iff_zero_lt.mpr hi)]) + +theorem exists_pow_mem_of_mem_nhds {a : R} (ha : IsTopologicallyNilpotent a) + {v : Set R} (hv : v ∈ 𝓝 0) : + ∃ n, a ^ n ∈ v := + (ha.eventually_mem hv).exists + +end MonoidWithZero + +section Ring + +variable {R : Type*} [TopologicalSpace R] [Ring R] + +/-- If `a` and `b` commute and `a` is topologically nilpotent, + then `a * b` is topologically nilpotent. -/ +theorem mul_right_of_commute [IsLinearTopology Rᵐᵒᵖ R] + {a b : R} (ha : IsTopologicallyNilpotent a) (hab : Commute a b) : + IsTopologicallyNilpotent (a * b) := by + simp_rw [IsTopologicallyNilpotent, hab.mul_pow] + exact IsLinearTopology.tendsto_mul_zero_of_left _ _ ha + +/-- If `a` and `b` commute and `b` is topologically nilpotent, + then `a * b` is topologically nilpotent. -/ + theorem mul_left_of_commute [IsLinearTopology R R] {a b : R} + (hb : IsTopologicallyNilpotent b) (hab : Commute a b) : + IsTopologicallyNilpotent (a * b) := by + simp_rw [IsTopologicallyNilpotent, hab.mul_pow] + exact IsLinearTopology.tendsto_mul_zero_of_right _ _ hb + +/-- If `a` and `b` are topologically nilpotent and commute, + then `a + b` is topologically nilpotent. -/ +theorem add_of_commute [IsLinearTopology R R] {a b : R} + (ha : IsTopologicallyNilpotent a) (hb : IsTopologicallyNilpotent b) (h : Commute a b) : + IsTopologicallyNilpotent (a + b) := by + simp only [IsTopologicallyNilpotent, atTop_basis.tendsto_iff IsLinearTopology.hasBasis_ideal, + true_and] + intro I I_mem_nhds + obtain ⟨na, ha⟩ := ha.exists_pow_mem_of_mem_nhds I_mem_nhds + obtain ⟨nb, hb⟩ := hb.exists_pow_mem_of_mem_nhds I_mem_nhds + exact ⟨na + nb, fun m hm ↦ + I.add_pow_mem_of_pow_mem_of_le_of_commute ha hb (le_trans hm (Nat.le_add_right _ _)) h⟩ + +end Ring + +section CommRing + +variable {R : Type*} [TopologicalSpace R] [CommRing R] [IsLinearTopology R R] + +/-- If `a` is topologically nilpotent, then `a * b` is topologically nilpotent. -/ +theorem mul_right {a : R} (ha : IsTopologicallyNilpotent a) (b : R) : + IsTopologicallyNilpotent (a * b) := + ha.mul_right_of_commute (Commute.all ..) + +/-- If `b` is topologically nilpotent, then `a * b` is topologically nilpotent. -/ + theorem mul_left (a : R) {b : R} (hb : IsTopologicallyNilpotent b) : + IsTopologicallyNilpotent (a * b) := + hb.mul_left_of_commute (Commute.all ..) + +/-- If `a` and `b` are topologically nilpotent, then `a + b` is topologically nilpotent. -/ +theorem add {a b : R} (ha : IsTopologicallyNilpotent a) (hb : IsTopologicallyNilpotent b) : + IsTopologicallyNilpotent (a + b) := + ha.add_of_commute hb (Commute.all ..) + +end CommRing + +end IsTopologicallyNilpotent From 8527b66544c539fd7656f9eb724e062db66f5d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Fri, 24 Jan 2025 14:39:43 +0000 Subject: [PATCH 482/681] feat(Order/RelIso): missing `Subrel` instances (#21011) --- Mathlib/Order/RelIso/Set.lean | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Mathlib/Order/RelIso/Set.lean b/Mathlib/Order/RelIso/Set.lean index 73c00fb2a9a04..d52b7837ed95b 100644 --- a/Mathlib/Order/RelIso/Set.lean +++ b/Mathlib/Order/RelIso/Set.lean @@ -78,9 +78,6 @@ theorem coe_inclusionEmbedding (r : α → α → Prop) {s t : Set α} (h : s (Subrel.inclusionEmbedding r h : s → t) = Set.inclusion h := rfl -instance (r : α → α → Prop) [IsWellOrder α r] (p : α → Prop) : IsWellOrder _ (Subrel r p) := - RelEmbedding.isWellOrder (Subrel.relEmbedding r p) - instance (r : α → α → Prop) [IsRefl α r] (p : α → Prop) : IsRefl _ (Subrel r p) := ⟨fun x => @IsRefl.refl α r _ x⟩ @@ -96,6 +93,16 @@ instance (r : α → α → Prop) [IsTrans α r] (p : α → Prop) : IsTrans _ ( instance (r : α → α → Prop) [IsIrrefl α r] (p : α → Prop) : IsIrrefl _ (Subrel r p) := ⟨fun x => @IsIrrefl.irrefl α r _ x⟩ +instance (r : α → α → Prop) [IsTrichotomous α r] (p : α → Prop) : IsTrichotomous _ (Subrel r p) := + ⟨fun x y => by rw [Subtype.eq_iff]; exact @IsTrichotomous.trichotomous α r _ x y⟩ + +instance (r : α → α → Prop) [IsWellFounded α r] (p : α → Prop) : IsWellFounded _ (Subrel r p) := + (Subrel.relEmbedding r p).isWellFounded + +instance (r : α → α → Prop) [IsPreorder α r] (p : α → Prop) : IsPreorder _ (Subrel r p) where +instance (r : α → α → Prop) [IsStrictOrder α r] (p : α → Prop) : IsStrictOrder _ (Subrel r p) where +instance (r : α → α → Prop) [IsWellOrder α r] (p : α → Prop) : IsWellOrder _ (Subrel r p) where + end Subrel /-- Restrict the codomain of a relation embedding. -/ From 4c0603b2f300236c325f1a796f1d9ebffb24f124 Mon Sep 17 00:00:00 2001 From: FMLJohn <417963616@qq.com> Date: Fri, 24 Jan 2025 15:20:08 +0000 Subject: [PATCH 483/681] chore(Data/Nat/Choose/Sum): refined the statement of `Finset.sum_antidiagonal_choose_add`. (#21022) --- Mathlib/Data/Nat/Choose/Sum.lean | 4 ++-- Mathlib/RingTheory/PowerSeries/WellKnown.lean | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Mathlib/Data/Nat/Choose/Sum.lean b/Mathlib/Data/Nat/Choose/Sum.lean index 390fb1a116da2..b75fe2b7a54fa 100644 --- a/Mathlib/Data/Nat/Choose/Sum.lean +++ b/Mathlib/Data/Nat/Choose/Sum.lean @@ -230,9 +230,9 @@ theorem sum_antidiagonal_choose_succ_mul (f : ℕ → ℕ → R) (n : ℕ) : simpa only [nsmul_eq_mul] using sum_antidiagonal_choose_succ_nsmul f n theorem sum_antidiagonal_choose_add (d n : ℕ) : - (∑ ij ∈ antidiagonal n, (d + ij.2).choose d) = (d + n).choose d + (d + n).choose (d + 1) := by + (∑ ij ∈ antidiagonal n, (d + ij.2).choose d) = (d + n + 1).choose (d + 1) := by induction n with | zero => simp - | succ n hn => simpa [Nat.sum_antidiagonal_succ] using hn + | succ n hn => rw [Nat.sum_antidiagonal_succ, hn, Nat.choose_succ_succ (d + (n + 1)), ← add_assoc] end Finset diff --git a/Mathlib/RingTheory/PowerSeries/WellKnown.lean b/Mathlib/RingTheory/PowerSeries/WellKnown.lean index 783e6348c6aa9..0b795197df1f1 100644 --- a/Mathlib/RingTheory/PowerSeries/WellKnown.lean +++ b/Mathlib/RingTheory/PowerSeries/WellKnown.lean @@ -93,8 +93,7 @@ theorem mk_one_pow_eq_mk_choose_add : rw [pow_add, hd, pow_one, mul_comm, coeff_mul] simp_rw [coeff_mk, Pi.one_apply, one_mul] norm_cast - rw [Finset.sum_antidiagonal_choose_add, ← Nat.choose_succ_succ, Nat.succ_eq_add_one, - add_right_comm] + rw [Finset.sum_antidiagonal_choose_add, add_right_comm] /-- Given a natural number `d : ℕ` and a commutative ring `S`, `PowerSeries.invOneSubPow S d` is the From 725eddcb98acf9b505220b6945a3b4a673a8a564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 24 Jan 2025 16:46:28 +0000 Subject: [PATCH 484/681] feat: submodule of mv polynomials whose coeffs lie in a fixed submodule (#20989) From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang --- Mathlib/Algebra/MvPolynomial/Basic.lean | 98 +++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/Mathlib/Algebra/MvPolynomial/Basic.lean b/Mathlib/Algebra/MvPolynomial/Basic.lean index 909b1eada5a2b..61c751a168619 100644 --- a/Mathlib/Algebra/MvPolynomial/Basic.lean +++ b/Mathlib/Algebra/MvPolynomial/Basic.lean @@ -869,6 +869,104 @@ theorem as_sum (p : MvPolynomial σ R) : p = ∑ v ∈ p.support, monomial v (co end AsSum +section coeffsIn +variable {R S σ : Type*} [CommSemiring R] [CommSemiring S] + +section Module +variable [Module R S] {M N : Submodule R S} {p : MvPolynomial σ S} {s : σ} {i : σ →₀ ℕ} {x : S} + {n : ℕ} + +variable (σ M) in +/-- The `R`-submodule of multivariate polynomials whose coefficients lie in a `R`-submodule `M`. -/ +@[simps] +def coeffsIn : Submodule R (MvPolynomial σ S) where + carrier := {p | ∀ i, p.coeff i ∈ M} + add_mem' := by simp+contextual [add_mem] + zero_mem' := by simp + smul_mem' := by simp+contextual [Submodule.smul_mem] + +lemma mem_coeffsIn : p ∈ coeffsIn σ M ↔ ∀ i, p.coeff i ∈ M := .rfl + +@[simp] +lemma monomial_mem_coeffsIn : monomial i x ∈ coeffsIn σ M ↔ x ∈ M := by + classical + simp only [mem_coeffsIn, coeff_monomial] + exact ⟨fun h ↦ by simpa using h i, fun hs j ↦ by split <;> simp [hs]⟩ + +@[simp] +lemma C_mem_coeffsIn : C x ∈ coeffsIn σ M ↔ x ∈ M := by simpa using monomial_mem_coeffsIn (i := 0) + +@[simp] +lemma one_coeffsIn : 1 ∈ coeffsIn σ M ↔ 1 ∈ M := by simpa using C_mem_coeffsIn (x := (1 : S)) + +@[simp] +lemma mul_monomial_mem_coeffsIn : p * monomial i 1 ∈ coeffsIn σ M ↔ p ∈ coeffsIn σ M := by + classical + simp only [mem_coeffsIn, coeff_mul_monomial', Finsupp.mem_support_iff] + constructor + · rintro hp j + simpa using hp (j + i) + · rintro hp i + split <;> simp [hp] + +@[simp] +lemma monomial_mul_mem_coeffsIn : monomial i 1 * p ∈ coeffsIn σ M ↔ p ∈ coeffsIn σ M := by + simp [mul_comm] + +@[simp] +lemma mul_X_mem_coeffsIn : p * X s ∈ coeffsIn σ M ↔ p ∈ coeffsIn σ M := by + simpa [-mul_monomial_mem_coeffsIn] using mul_monomial_mem_coeffsIn (i := .single s 1) + +@[simp] +lemma X_mul_mem_coeffsIn : X s * p ∈ coeffsIn σ M ↔ p ∈ coeffsIn σ M := by simp [mul_comm] + +variable (M) in +lemma coeffsIn_eq_span_monomial : coeffsIn σ M = .span R {monomial i m | (m ∈ M) (i : σ →₀ ℕ)} := by + classical + refine le_antisymm ?_ <| Submodule.span_le.2 ?_ + · rintro p hp + rw [p.as_sum] + exact sum_mem fun i hi ↦ Submodule.subset_span ⟨_, hp i, _, rfl⟩ + · rintro _ ⟨m, hm, s, n, rfl⟩ i + simp [coeff_X_pow] + split <;> simp [hm] + +lemma coeffsIn_le {N : Submodule R (MvPolynomial σ S)} : + coeffsIn σ M ≤ N ↔ ∀ m ∈ M, ∀ i, monomial i m ∈ N := by + simp [coeffsIn_eq_span_monomial, Submodule.span_le, Set.subset_def, + forall_swap (α := MvPolynomial σ S)] + +end Module + +section Algebra +variable [Algebra R S] {M : Submodule R S} + +lemma coeffsIn_mul (M N : Submodule R S) : coeffsIn σ (M * N) = coeffsIn σ M * coeffsIn σ N := by + classical + refine le_antisymm (coeffsIn_le.2 ?_) ?_ + · intros r hr s + induction hr using Submodule.mul_induction_on' with + | mem_mul_mem m hm n hn => + rw [← add_zero s, ← monomial_mul] + apply Submodule.mul_mem_mul <;> simpa + | add x _ y _ hx hy => + simpa [map_add] using add_mem hx hy + · rw [Submodule.mul_le] + intros x hx y hy k + rw [MvPolynomial.coeff_mul] + exact sum_mem fun c hc ↦ Submodule.mul_mem_mul (hx _) (hy _) + +lemma coeffsIn_pow : ∀ {n}, n ≠ 0 → ∀ M : Submodule R S, coeffsIn σ (M ^ n) = coeffsIn σ M ^ n + | 1, _, M => by simp + | n + 2, _, M => by rw [pow_succ, coeffsIn_mul, coeffsIn_pow, ← pow_succ]; exact n.succ_ne_zero + +lemma le_coeffsIn_pow : ∀ {n}, coeffsIn σ M ^ n ≤ coeffsIn σ (M ^ n) + | 0 => by simpa using ⟨1, map_one _⟩ + | n + 1 => (coeffsIn_pow n.succ_ne_zero _).ge + +end Algebra +end coeffsIn + end CommSemiring end MvPolynomial From 59eed68fe429e3b530ee79ce6109d7efbd9d8d98 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Fri, 24 Jan 2025 18:38:07 +0000 Subject: [PATCH 485/681] chore: fix docstring (#21027) --- Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean index fb149455f547a..d43a840accbf1 100644 --- a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean +++ b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean @@ -198,8 +198,8 @@ theorem ae_eq_of_integral_contDiff_smul_eq (fun g g_diff g_supp ↦ h g g_diff.contDiff g_supp) /-- If a function `f` locally integrable on an open subset `U` of a finite-dimensional real - manifold has zero integral when multiplied by any smooth function compactly supported - in an open set `U`, then `f` vanishes almost everywhere in `U`. -/ + vector space has zero integral when multiplied by any smooth function compactly supported + in `U`, then `f` vanishes almost everywhere in `U`. -/ theorem IsOpen.ae_eq_zero_of_integral_contDiff_smul_eq_zero {U : Set E} (hU : IsOpen U) (hf : LocallyIntegrableOn f U μ) (h : ∀ (g : E → ℝ), ContDiff ℝ ∞ g → HasCompactSupport g → tsupport g ⊆ U → From 395adf2401cc7247738280245313c33803ea7eec Mon Sep 17 00:00:00 2001 From: Oliver Nash Date: Fri, 24 Jan 2025 19:43:18 +0000 Subject: [PATCH 486/681] feat: define the Cartan matrix of a root pairing relative to a base (#20999) Also adding `RootPairing.IsValuedIn` (together with some API) since this enables us to define an integer-valued Cartan matrix for crystallographic pairings. More importantly, `RootPairing.IsValuedIn` is also the missing piece to generalise (and unify) some results which currently require ordered scalars such as [RootPairing.coxeterWeight_mem_set_of_isCrystallographic](https://leanprover-community.github.io/mathlib4_docs/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.html#RootPairing.coxeterWeight_mem_set_of_isCrystallographic) but this work is left for a future PR (mostly to simplify review). Co-authored-by: Oliver Nash <7734364+ocfnash@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Algebra/Lie/Weights/RootSystem.lean | 2 +- .../LinearAlgebra/RootSystem/BaseChange.lean | 2 +- .../RootSystem/CartanMatrix.lean | 53 ++++++++++++ Mathlib/LinearAlgebra/RootSystem/Defs.lean | 82 ++++++++++++++----- .../RootSystem/Finite/CanonicalBilinear.lean | 8 +- .../RootSystem/Finite/Nondegenerate.lean | 3 +- 7 files changed, 122 insertions(+), 29 deletions(-) create mode 100644 Mathlib/LinearAlgebra/RootSystem/CartanMatrix.lean diff --git a/Mathlib.lean b/Mathlib.lean index e5ac44298f4a6..afb17fd169f07 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3620,6 +3620,7 @@ import Mathlib.LinearAlgebra.Reflection import Mathlib.LinearAlgebra.RootSystem.Base import Mathlib.LinearAlgebra.RootSystem.BaseChange import Mathlib.LinearAlgebra.RootSystem.Basic +import Mathlib.LinearAlgebra.RootSystem.CartanMatrix import Mathlib.LinearAlgebra.RootSystem.Defs import Mathlib.LinearAlgebra.RootSystem.Finite.CanonicalBilinear import Mathlib.LinearAlgebra.RootSystem.Finite.Nondegenerate diff --git a/Mathlib/Algebra/Lie/Weights/RootSystem.lean b/Mathlib/Algebra/Lie/Weights/RootSystem.lean index 73c1e4f1312b4..2c4915771269b 100644 --- a/Mathlib/Algebra/Lie/Weights/RootSystem.lean +++ b/Mathlib/Algebra/Lie/Weights/RootSystem.lean @@ -410,7 +410,7 @@ alias rootSystem_toLin_apply := rootSystem_toPerfectPairing_apply @[simp] lemma rootSystem_coroot_apply (α) : (rootSystem H).coroot α = coroot α := rfl instance : (rootSystem H).IsCrystallographic where - exists_int α β := + exists_value α β := ⟨chainBotCoeff β.1 α.1 - chainTopCoeff β.1 α.1, by simp [apply_coroot_eq_cast β.1 α.1]⟩ theorem isReduced_rootSystem : (rootSystem H).IsReduced := by diff --git a/Mathlib/LinearAlgebra/RootSystem/BaseChange.lean b/Mathlib/LinearAlgebra/RootSystem/BaseChange.lean index 5b095cfca25a4..60e98abdd2d75 100644 --- a/Mathlib/LinearAlgebra/RootSystem/BaseChange.lean +++ b/Mathlib/LinearAlgebra/RootSystem/BaseChange.lean @@ -115,7 +115,7 @@ end SubfieldValued /-- Restriction of scalars for a crystallographic root pairing. -/ abbrev restrictScalars [P.IsCrystallographic] : RootSystem ι K (span K (range P.root)) (span K (range P.coroot)) := - P.restrictScalars' K <| IsCrystallographic.mem_range_algebraMap P K + P.restrictScalars' K (IsValuedIn.trans P K ℤ).exists_value /-- Restriction of scalars to `ℚ` for a crystallographic root pairing in characteristic zero. -/ abbrev restrictScalarsRat [CharZero L] [P.IsCrystallographic] := diff --git a/Mathlib/LinearAlgebra/RootSystem/CartanMatrix.lean b/Mathlib/LinearAlgebra/RootSystem/CartanMatrix.lean new file mode 100644 index 0000000000000..3c23104e4e2bb --- /dev/null +++ b/Mathlib/LinearAlgebra/RootSystem/CartanMatrix.lean @@ -0,0 +1,53 @@ +/- +Copyright (c) 2025 Oliver Nash. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Oliver Nash +-/ +import Mathlib.LinearAlgebra.RootSystem.Base + +/-! +# Cartan matrices for root systems + +This file contains definitions and basic results about Cartan matrices of root pairings / systems. + +## Main definitions: + * `RootPairing.cartanMatrix`: the Cartan matrix of a crystallographic root pairing, with respect to + a base `b`. + +-/ + +noncomputable section + +open Function Set + +variable {ι R M N : Type*} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] + +namespace RootPairing.Base + +variable (S : Type*) [CommRing S] [Algebra S R] + {P : RootPairing ι R M N} [P.IsValuedIn S] (b : P.Base) + +/-- The Cartan matrix of a root pairing, taking values in `S`, with respect to a base `b`. + +See also `RootPairing.Base.cartanMatrix`. -/ +def cartanMatrixIn : + Matrix b.support b.support S := + .of fun i j ↦ P.pairingIn S i j + +/-- The Cartan matrix of a crystallographic root pairing, with respect to a base `b`. -/ +abbrev cartanMatrix [P.IsCrystallographic] : + Matrix b.support b.support ℤ := + b.cartanMatrixIn ℤ + +lemma cartanMatrixIn_def (i j : b.support) : + b.cartanMatrixIn S i j = P.pairingIn S i j := + rfl + +variable [Nontrivial R] [NoZeroSMulDivisors S R] + +@[simp] +lemma cartanMatrixIn_apply_same (i : b.support) : + b.cartanMatrixIn S i i = 2 := + NoZeroSMulDivisors.algebraMap_injective S R <| by simp [cartanMatrixIn_def, map_ofNat] + +end RootPairing.Base diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index 8216ae6e996a4..7ca876bc7654e 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -380,29 +380,60 @@ lemma pairing_reflection_perm_self_right (i j : ι) : sub_add_cancel_left, ← toLin_toPerfectPairing, map_neg, toLin_toPerfectPairing, root_coroot_eq_pairing] +/-- If `R` is an `S`-algebra, a root pairing over `R` is said to be valued in `S` if the pairing +between a root and coroot always belongs to `S`. + +Of particular interest is the case `S = ℤ`. See `RootPairing.IsCrystallographic`. -/ +@[mk_iff] +class IsValuedIn (S : Type*) [CommRing S] [Algebra S R] : Prop where + exists_value : ∀ i j, ∃ s, algebraMap S R s = P.pairing i j + +protected alias exists_value := IsValuedIn.exists_value + /-- A root pairing is said to be crystallographic if the pairing between a root and coroot is always an integer. -/ -class IsCrystallographic : Prop where - exists_int : ∀ i j, ∃ z : ℤ, z = P.pairing i j +abbrev IsCrystallographic := P.IsValuedIn ℤ + +section IsValuedIn + +instance : P.IsValuedIn R where + exists_value i j := by simp + +variable (S : Type*) [CommRing S] [Algebra S R] + +variable {S} in +lemma isValuedIn_iff_mem_range : + P.IsValuedIn S ↔ ∀ i j, P.pairing i j ∈ range (algebraMap S R) := by + simp only [isValuedIn_iff, mem_range] -protected lemma exists_int [P.IsCrystallographic] (i j : ι) : - ∃ z : ℤ, z = P.pairing i j := - IsCrystallographic.exists_int i j +instance : P.IsValuedIn R where + exists_value := by simp -lemma isCrystallographic_iff : - P.IsCrystallographic ↔ ∀ i j, ∃ z : ℤ, z = P.pairing i j := - ⟨fun ⟨h⟩ ↦ h, fun h ↦ ⟨h⟩⟩ +instance [P.IsValuedIn S] : P.flip.IsValuedIn S := by + rw [isValuedIn_iff, forall_comm] + exact P.exists_value -instance [P.IsCrystallographic] : P.flip.IsCrystallographic := by - rw [isCrystallographic_iff, forall_comm] - exact P.exists_int +/-- A variant of `RootPairing.pairing` for root pairings which are valued in a smaller set of +coefficients. -lemma IsCrystallographic.mem_range_algebraMap [P.IsCrystallographic] - (S : Type*) [CommRing S] [Algebra S R] (i j : ι) : - P.pairing i j ∈ (algebraMap S R).range := by - obtain ⟨k, hk⟩ := P.exists_int i j - simp only [RingHom.mem_range] - exact ⟨k, by simpa⟩ +Note that it is uniquely-defined only when the map `S → R` is injective, i.e., when we have +`[NoZeroSMulDivisors S R]`. -/ +def pairingIn [P.IsValuedIn S] (i j : ι) : S := + (P.exists_value i j).choose + +@[simp] +lemma algebraMap_pairingIn [P.IsValuedIn S] (i j : ι) : + algebraMap S R (P.pairingIn S i j) = P.pairing i j := + (P.exists_value i j).choose_spec + +lemma IsValuedIn.trans (T : Type*) [CommRing T] [Algebra T S] [Algebra T R] [IsScalarTower T S R] + [P.IsValuedIn T] : + P.IsValuedIn S where + exists_value i j := by + use algebraMap T S (P.pairingIn T i j) + simp [← RingHom.comp_apply, ← IsScalarTower.algebraMap_eq T S R] + +end IsValuedIn /-- A root pairing is said to be reduced if any linearly dependent pair of roots is related by a sign. -/ @@ -547,11 +578,18 @@ def coxeterWeight : R := pairing P i j * pairing P j i lemma coxeterWeight_swap : coxeterWeight P i j = coxeterWeight P j i := by simp only [coxeterWeight, mul_comm] -lemma exists_int_eq_coxeterWeight [P.IsCrystallographic] (i j : ι) : - ∃ z : ℤ, P.coxeterWeight i j = z := by - obtain ⟨a, ha⟩ := P.exists_int i j - obtain ⟨b, hb⟩ := P.exists_int j i - exact ⟨a * b, by simp [coxeterWeight, ha, hb]⟩ +/-- A variant of `RootPairing.coxeterWeight` for root pairings which are valued in a smaller set of +coefficients. + +Note that it is uniquely-defined only when the map `S → R` is injective, i.e., when we have +`[NoZeroSMulDivisors S R]`. -/ +def coxeterWeightIn (S : Type*) [CommRing S] [Algebra S R] [P.IsValuedIn S] (i j : ι) : S := + P.pairingIn S i j * P.pairingIn S j i + +@[simp] lemma algebraMap_coxeterWeightIn (S : Type*) [CommRing S] [Algebra S R] [P.IsValuedIn S] + (i j : ι) : + algebraMap S R (P.coxeterWeightIn S i j) = P.coxeterWeight i j := by + simp [coxeterWeightIn, coxeterWeight] /-- Two roots are orthogonal when they are fixed by each others' reflections. -/ def IsOrthogonal : Prop := pairing P i j = 0 ∧ pairing P j i = 0 diff --git a/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.lean b/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.lean index 39b0b06f3214c..e2e30db0f2b7c 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.lean @@ -268,10 +268,10 @@ instance instIsRootPositiveRootForm : IsRootPositive P P.RootForm where lemma coxeterWeight_mem_set_of_isCrystallographic (i j : ι) [P.IsCrystallographic] : P.coxeterWeight i j ∈ ({0, 1, 2, 3, 4} : Set R) := by obtain ⟨n, hcn⟩ : ∃ n : ℕ, P.coxeterWeight i j = n := by - obtain ⟨z, hz⟩ := P.exists_int_eq_coxeterWeight i j - have hz₀ : 0 ≤ z := by simpa [hz] using P.coxeterWeight_non_neg P.RootForm i j - obtain ⟨n, rfl⟩ := Int.eq_ofNat_of_zero_le hz₀ - exact ⟨n, by simp [hz]⟩ + have : 0 ≤ P.coxeterWeightIn ℤ i j := by + simpa [← P.algebraMap_coxeterWeightIn ℤ] using P.coxeterWeight_non_neg P.RootForm i j + obtain ⟨n, hn⟩ := Int.eq_ofNat_of_zero_le this + exact ⟨n, by simp [← P.algebraMap_coxeterWeightIn ℤ, hn]⟩ have : P.coxeterWeight i j ≤ 4 := P.coxeterWeight_le_four i j simp only [hcn, mem_insert_iff, mem_singleton_iff] at this ⊢ norm_cast at this ⊢ diff --git a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean index 60b73071e6aae..aa86853fa0777 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean @@ -77,7 +77,8 @@ instance [P.IsAnisotropic] : P.flip.IsAnisotropic where /-- An auxiliary lemma en route to `RootPairing.instIsAnisotropicOfIsCrystallographic`. -/ private lemma rootForm_root_ne_zero_aux [CharZero R] [P.IsCrystallographic] (i : ι) : P.RootForm (P.root i) (P.root i) ≠ 0 := by - choose z hz using P.exists_int i + choose z hz using P.exists_value (S := ℤ) i + simp_rw [algebraMap_int_eq, Int.coe_castRingHom] at hz simp only [rootForm_apply_apply, PerfectPairing.flip_apply_apply, root_coroot_eq_pairing, ← hz] suffices 0 < ∑ i, z i * z i by norm_cast; exact this.ne' refine Finset.sum_pos' (fun i _ ↦ mul_self_nonneg (z i)) ⟨i, Finset.mem_univ i, ?_⟩ From f8b7f16aeb0df5c1e6a42b8f4d674f558caee86b Mon Sep 17 00:00:00 2001 From: Matthew Robert Ballard Date: Fri, 24 Jan 2025 19:52:34 +0000 Subject: [PATCH 487/681] perf: use `fast_instance%` for instances constructed via non-canonical constructors (#20993) Most the applications have `Function.Injective/Surjective.class` at the head of their expressions except for `Submodule.addCommMonoid/addCommGroup/module'/module`. The latter probably have the former deeper inside. Co-authored-by: Eric Wieser Co-authored-by: Kyle Miller Co-authored-by: Matthew Robert Ballard <100034030+mattrobball@users.noreply.github.com> Co-authored-by: Anne C.A. Baanen --- Mathlib/Algebra/Field/Subfield/Defs.lean | 8 +-- Mathlib/Algebra/Group/Subgroup/Defs.lean | 9 +-- Mathlib/Algebra/Group/Submonoid/Defs.lean | 16 ++--- Mathlib/Algebra/Group/Subsemigroup/Defs.lean | 5 +- Mathlib/Algebra/Module/Submodule/Defs.lean | 9 +-- Mathlib/Algebra/Module/Submodule/Order.lean | 12 ++-- Mathlib/Algebra/Order/CauSeq/Completion.lean | 5 +- Mathlib/Algebra/Order/Field/Subfield.lean | 5 +- .../Algebra/Order/Interval/Set/Instances.lean | 28 +++++---- Mathlib/Algebra/Order/Monoid/Submonoid.lean | 18 +++--- Mathlib/Algebra/Order/Nonneg/Field.lean | 2 +- Mathlib/Algebra/Order/Nonneg/Ring.lean | 19 +++--- Mathlib/Algebra/Order/Positive/Ring.lean | 17 +++--- Mathlib/Algebra/Polynomial/Basic.lean | 42 +++++--------- Mathlib/Algebra/Ring/Subring/Defs.lean | 4 +- Mathlib/Algebra/Ring/Subring/Order.lean | 8 +-- Mathlib/Algebra/Ring/Subsemiring/Defs.lean | 6 +- Mathlib/Algebra/Ring/Subsemiring/Order.lean | 26 +++++---- Mathlib/AlgebraicGeometry/Modules/Tilde.lean | 2 +- Mathlib/Data/Finsupp/Defs.lean | 22 +++---- Mathlib/GroupTheory/Congruence/Defs.lean | 58 +++++-------------- .../AffineSpace/AffineSubspace.lean | 9 +-- Mathlib/LinearAlgebra/Quotient/Defs.lean | 34 ++++------- Mathlib/RingTheory/Congruence/Defs.lean | 23 ++++---- Mathlib/RingTheory/NonUnitalSubring/Defs.lean | 11 ++-- .../RingTheory/NonUnitalSubsemiring/Defs.lean | 8 ++- Mathlib/Tactic/FastInstance.lean | 3 +- scripts/noshake.json | 18 +++++- 28 files changed, 203 insertions(+), 224 deletions(-) diff --git a/Mathlib/Algebra/Field/Subfield/Defs.lean b/Mathlib/Algebra/Field/Subfield/Defs.lean index 9af131cc79a95..f7955cd9e0f5e 100644 --- a/Mathlib/Algebra/Field/Subfield/Defs.lean +++ b/Mathlib/Algebra/Field/Subfield/Defs.lean @@ -107,7 +107,7 @@ instance instSMulRat (s : S) : SMul ℚ s where smul q x := ⟨q • x, qsmul_me variable (S) /-- A subfield inherits a division ring structure -/ -instance (priority := 75) toDivisionRing (s : S) : DivisionRing s := +instance (priority := 75) toDivisionRing (s : S) : DivisionRing s := fast_instance% Subtype.coe_injective.divisionRing ((↑) : s → K) rfl rfl (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) @@ -117,7 +117,7 @@ instance (priority := 75) toDivisionRing (s : S) : DivisionRing s := -- Prefer subclasses of `Field` over subclasses of `SubfieldClass`. /-- A subfield of a field inherits a field structure -/ instance (priority := 75) toField {K} [Field K] [SetLike S K] [SubfieldClass S K] (s : S) : - Field s := + Field s := fast_instance% Subtype.coe_injective.field ((↑) : s → K) rfl rfl (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) @@ -276,14 +276,14 @@ instance : Pow s ℤ := ⟨fun x z => ⟨x ^ z, s.zpow_mem x.2 z⟩⟩ -- TODO: Those are just special cases of `SubfieldClass.toDivisionRing`/`SubfieldClass.toField` -instance toDivisionRing (s : Subfield K) : DivisionRing s := +instance toDivisionRing (s : Subfield K) : DivisionRing s := fast_instance% Subtype.coe_injective.divisionRing ((↑) : s → K) rfl rfl (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) fun _ ↦ rfl /-- A subfield inherits a field structure -/ -instance toField {K} [Field K] (s : Subfield K) : Field s := +instance toField {K} [Field K] (s : Subfield K) : Field s := fast_instance% Subtype.coe_injective.field ((↑) : s → K) rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ ↦ rfl) (fun _ => rfl) diff --git a/Mathlib/Algebra/Group/Subgroup/Defs.lean b/Mathlib/Algebra/Group/Subgroup/Defs.lean index eea53f4a65caf..a97477f0b4657 100644 --- a/Mathlib/Algebra/Group/Subgroup/Defs.lean +++ b/Mathlib/Algebra/Group/Subgroup/Defs.lean @@ -5,6 +5,7 @@ Authors: Kexing Ying -/ import Mathlib.Algebra.Group.Submonoid.Defs import Mathlib.Tactic.Common +import Mathlib.Tactic.FastInstance /-! # Subgroups @@ -175,7 +176,7 @@ variable (H) -- Prefer subclasses of `Group` over subclasses of `SubgroupClass`. /-- A subgroup of a group inherits a group structure. -/ @[to_additive "An additive subgroup of an `AddGroup` inherits an `AddGroup` structure."] -instance (priority := 75) toGroup : Group H := +instance (priority := 75) toGroup : Group H := fast_instance% Subtype.coe_injective.group _ rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -183,7 +184,7 @@ instance (priority := 75) toGroup : Group H := /-- A subgroup of a `CommGroup` is a `CommGroup`. -/ @[to_additive "An additive subgroup of an `AddCommGroup` is an `AddCommGroup`."] instance (priority := 75) toCommGroup {G : Type*} [CommGroup G] [SetLike S G] [SubgroupClass S G] : - CommGroup H := + CommGroup H := fast_instance% Subtype.coe_injective.commGroup _ rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -504,13 +505,13 @@ theorem mk_eq_one {g : G} {h} : (⟨g, h⟩ : H) = 1 ↔ g = 1 := Submonoid.mk_e /-- A subgroup of a group inherits a group structure. -/ @[to_additive "An `AddSubgroup` of an `AddGroup` inherits an `AddGroup` structure."] -instance toGroup {G : Type*} [Group G] (H : Subgroup G) : Group H := +instance toGroup {G : Type*} [Group G] (H : Subgroup G) : Group H := fast_instance% Subtype.coe_injective.group _ rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl /-- A subgroup of a `CommGroup` is a `CommGroup`. -/ @[to_additive "An `AddSubgroup` of an `AddCommGroup` is an `AddCommGroup`."] -instance toCommGroup {G : Type*} [CommGroup G] (H : Subgroup G) : CommGroup H := +instance toCommGroup {G : Type*} [CommGroup G] (H : Subgroup G) : CommGroup H := fast_instance% Subtype.coe_injective.commGroup _ rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/Algebra/Group/Submonoid/Defs.lean b/Mathlib/Algebra/Group/Submonoid/Defs.lean index 4f7ad4ad1b945..e4735cec1b93f 100644 --- a/Mathlib/Algebra/Group/Submonoid/Defs.lean +++ b/Mathlib/Algebra/Group/Submonoid/Defs.lean @@ -6,6 +6,7 @@ Amelia Livingston, Yury Kudryashov -/ import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Group.Subsemigroup.Defs +import Mathlib.Tactic.FastInstance /-! # Submonoids: definition @@ -351,21 +352,21 @@ theorem mk_pow {M} [Monoid M] {A : Type*} [SetLike A M] [SubmonoidClass A M] {S @[to_additive "An `AddSubmonoid` of a unital additive magma inherits a unital additive magma structure."] instance (priority := 75) toMulOneClass {M : Type*} [MulOneClass M] {A : Type*} [SetLike A M] - [SubmonoidClass A M] (S : A) : MulOneClass S := - Subtype.coe_injective.mulOneClass Subtype.val rfl (fun _ _ => rfl) + [SubmonoidClass A M] (S : A) : MulOneClass S := fast_instance% + Subtype.coe_injective.mulOneClass Subtype.val rfl (fun _ _ => rfl) -- Prefer subclasses of `Monoid` over subclasses of `SubmonoidClass`. /-- A submonoid of a monoid inherits a monoid structure. -/ @[to_additive "An `AddSubmonoid` of an `AddMonoid` inherits an `AddMonoid` structure."] instance (priority := 75) toMonoid {M : Type*} [Monoid M] {A : Type*} [SetLike A M] - [SubmonoidClass A M] (S : A) : Monoid S := + [SubmonoidClass A M] (S : A) : Monoid S := fast_instance% Subtype.coe_injective.monoid Subtype.val rfl (fun _ _ => rfl) (fun _ _ => rfl) -- Prefer subclasses of `Monoid` over subclasses of `SubmonoidClass`. /-- A submonoid of a `CommMonoid` is a `CommMonoid`. -/ @[to_additive "An `AddSubmonoid` of an `AddCommMonoid` is an `AddCommMonoid`."] instance (priority := 75) toCommMonoid {M} [CommMonoid M] {A : Type*} [SetLike A M] - [SubmonoidClass A M] (S : A) : CommMonoid S := + [SubmonoidClass A M] (S : A) : CommMonoid S := fast_instance% Subtype.coe_injective.commMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl /-- The natural monoid hom from a submonoid of monoid `M` to `M`. -/ @@ -420,7 +421,8 @@ theorem one_def : (1 : S) = ⟨1, S.one_mem⟩ := /-- A submonoid of a unital magma inherits a unital magma structure. -/ @[to_additive "An `AddSubmonoid` of a unital additive magma inherits a unital additive magma structure."] -instance toMulOneClass {M : Type*} [MulOneClass M] (S : Submonoid M) : MulOneClass S := +instance toMulOneClass {M : Type*} [MulOneClass M] (S : Submonoid M) : + MulOneClass S := fast_instance% Subtype.coe_injective.mulOneClass Subtype.val rfl fun _ _ => rfl @[to_additive] @@ -430,12 +432,12 @@ protected theorem pow_mem {M : Type*} [Monoid M] (S : Submonoid M) {x : M} (hx : /-- A submonoid of a monoid inherits a monoid structure. -/ @[to_additive "An `AddSubmonoid` of an `AddMonoid` inherits an `AddMonoid` structure."] -instance toMonoid {M : Type*} [Monoid M] (S : Submonoid M) : Monoid S := +instance toMonoid {M : Type*} [Monoid M] (S : Submonoid M) : Monoid S := fast_instance% Subtype.coe_injective.monoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl /-- A submonoid of a `CommMonoid` is a `CommMonoid`. -/ @[to_additive "An `AddSubmonoid` of an `AddCommMonoid` is an `AddCommMonoid`."] -instance toCommMonoid {M} [CommMonoid M] (S : Submonoid M) : CommMonoid S := +instance toCommMonoid {M} [CommMonoid M] (S : Submonoid M) : CommMonoid S := fast_instance% Subtype.coe_injective.commMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl /-- The natural monoid hom from a submonoid of monoid `M` to `M`. -/ diff --git a/Mathlib/Algebra/Group/Subsemigroup/Defs.lean b/Mathlib/Algebra/Group/Subsemigroup/Defs.lean index 24404d2fb09fc..1523e0b5c57c6 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Defs.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Defs.lean @@ -7,6 +7,7 @@ Amelia Livingston, Yury Kudryashov, Yakov Pechersky import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Group.InjSurj import Mathlib.Data.SetLike.Basic +import Mathlib.Tactic.FastInstance /-! # Subsemigroups: definition @@ -254,13 +255,13 @@ theorem mul_def (x y : S') : x * y = ⟨x * y, mul_mem x.2 y.2⟩ := /-- A subsemigroup of a semigroup inherits a semigroup structure. -/ @[to_additive "An `AddSubsemigroup` of an `AddSemigroup` inherits an `AddSemigroup` structure."] instance toSemigroup {M : Type*} [Semigroup M] {A : Type*} [SetLike A M] [MulMemClass A M] - (S : A) : Semigroup S := + (S : A) : Semigroup S := fast_instance% Subtype.coe_injective.semigroup Subtype.val fun _ _ => rfl /-- A subsemigroup of a `CommSemigroup` is a `CommSemigroup`. -/ @[to_additive "An `AddSubsemigroup` of an `AddCommSemigroup` is an `AddCommSemigroup`."] instance toCommSemigroup {M} [CommSemigroup M] {A : Type*} [SetLike A M] [MulMemClass A M] - (S : A) : CommSemigroup S := + (S : A) : CommSemigroup S := fast_instance% Subtype.coe_injective.commSemigroup Subtype.val fun _ _ => rfl /-- The natural semigroup hom from a subsemigroup of semigroup `M` to `M`. -/ diff --git a/Mathlib/Algebra/Module/Submodule/Defs.lean b/Mathlib/Algebra/Module/Submodule/Defs.lean index 6430f82524dff..55faba7453264 100644 --- a/Mathlib/Algebra/Module/Submodule/Defs.lean +++ b/Mathlib/Algebra/Module/Submodule/Defs.lean @@ -137,7 +137,7 @@ variable [Semiring R] [AddCommMonoid M] [Module R M] {A : Type*} [SetLike A M] -- Prefer subclasses of `Module` over `SMulMemClass`. /-- A submodule of a `Module` is a `Module`. -/ -instance (priority := 75) toModule : Module R S' := +instance (priority := 75) toModule : Module R S' := fast_instance% Subtype.coe_injective.module R (AddSubmonoidClass.subtype S') (SetLike.val_smul S') /-- This can't be an instance because Lean wouldn't know how to find `R`, but we can still use @@ -246,10 +246,11 @@ theorem coe_mem (x : p) : (x : M) ∈ p := variable (p) -instance addCommMonoid : AddCommMonoid p := +instance addCommMonoid : AddCommMonoid p := fast_instance% { p.toAddSubmonoid.toAddCommMonoid with } -instance module' [Semiring S] [SMul S R] [Module S M] [IsScalarTower S R M] : Module S p := +instance module' [Semiring S] [SMul S R] [Module S M] [IsScalarTower S R M] : + Module S p := fast_instance% { (show MulAction S p from p.toSubMulAction.mulAction') with smul_zero := fun a => by ext; simp zero_smul := fun a => by ext; simp @@ -319,7 +320,7 @@ theorem sub_mem_iff_left (hy : y ∈ p) : x - y ∈ p ↔ x ∈ p := by theorem sub_mem_iff_right (hx : x ∈ p) : x - y ∈ p ↔ y ∈ p := by rw [sub_eq_add_neg, p.add_mem_iff_right hx, p.neg_mem_iff] -instance addCommGroup : AddCommGroup p := +instance addCommGroup : AddCommGroup p := fast_instance% { p.toAddSubgroup.toAddCommGroup with } end AddCommGroup diff --git a/Mathlib/Algebra/Module/Submodule/Order.lean b/Mathlib/Algebra/Module/Submodule/Order.lean index 25d64e4e3fe8e..25cb72fc29c8d 100644 --- a/Mathlib/Algebra/Module/Submodule/Order.lean +++ b/Mathlib/Algebra/Module/Submodule/Order.lean @@ -18,24 +18,24 @@ variable [Semiring R] /-- A submodule of an `OrderedAddCommMonoid` is an `OrderedAddCommMonoid`. -/ instance toOrderedAddCommMonoid [OrderedAddCommMonoid M] [Module R M] (S : Submodule R M) : - OrderedAddCommMonoid S := + OrderedAddCommMonoid S := fast_instance% Subtype.coe_injective.orderedAddCommMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl /-- A submodule of a `LinearOrderedAddCommMonoid` is a `LinearOrderedAddCommMonoid`. -/ instance toLinearOrderedAddCommMonoid [LinearOrderedAddCommMonoid M] [Module R M] - (S : Submodule R M) : LinearOrderedAddCommMonoid S := + (S : Submodule R M) : LinearOrderedAddCommMonoid S := fast_instance% Subtype.coe_injective.linearOrderedAddCommMonoid Subtype.val rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl /-- A submodule of an `OrderedCancelAddCommMonoid` is an `OrderedCancelAddCommMonoid`. -/ instance toOrderedCancelAddCommMonoid [OrderedCancelAddCommMonoid M] [Module R M] - (S : Submodule R M) : OrderedCancelAddCommMonoid S := + (S : Submodule R M) : OrderedCancelAddCommMonoid S := fast_instance% Subtype.coe_injective.orderedCancelAddCommMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl /-- A submodule of a `LinearOrderedCancelAddCommMonoid` is a `LinearOrderedCancelAddCommMonoid`. -/ instance toLinearOrderedCancelAddCommMonoid [LinearOrderedCancelAddCommMonoid M] [Module R M] - (S : Submodule R M) : LinearOrderedCancelAddCommMonoid S := + (S : Submodule R M) : LinearOrderedCancelAddCommMonoid S := fast_instance% Subtype.coe_injective.linearOrderedCancelAddCommMonoid Subtype.val rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -46,14 +46,14 @@ variable [Ring R] /-- A submodule of an `OrderedAddCommGroup` is an `OrderedAddCommGroup`. -/ instance toOrderedAddCommGroup [OrderedAddCommGroup M] [Module R M] (S : Submodule R M) : - OrderedAddCommGroup S := + OrderedAddCommGroup S := fast_instance% Subtype.coe_injective.orderedAddCommGroup Subtype.val rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl /-- A submodule of a `LinearOrderedAddCommGroup` is a `LinearOrderedAddCommGroup`. -/ instance toLinearOrderedAddCommGroup [LinearOrderedAddCommGroup M] [Module R M] - (S : Submodule R M) : LinearOrderedAddCommGroup S := + (S : Submodule R M) : LinearOrderedAddCommGroup S := fast_instance% Subtype.coe_injective.linearOrderedAddCommGroup Subtype.val rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/Algebra/Order/CauSeq/Completion.lean b/Mathlib/Algebra/Order/CauSeq/Completion.lean index 283cb6611892c..2272380559614 100644 --- a/Mathlib/Algebra/Order/CauSeq/Completion.lean +++ b/Mathlib/Algebra/Order/CauSeq/Completion.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro, Robert Y. Lewis -/ import Mathlib.Algebra.Order.CauSeq.Basic import Mathlib.Data.Rat.Cast.Defs +import Mathlib.Tactic.FastInstance /-! # Cauchy completion @@ -139,7 +140,7 @@ private theorem zero_def : 0 = mk (abv := abv) 0 := private theorem one_def : 1 = mk (abv := abv) 1 := rfl -instance Cauchy.ring : Ring (Cauchy abv) := +instance Cauchy.ring : Ring (Cauchy abv) := fast_instance% Function.Surjective.ring mk Quotient.mk'_surjective zero_def.symm one_def.symm (fun _ _ => (mk_add _ _).symm) (fun _ _ => (mk_mul _ _).symm) (fun _ => (mk_neg _).symm) (fun _ _ => (mk_sub _ _).symm) (fun _ _ => (mk_smul _ _).symm) (fun _ _ => (mk_smul _ _).symm) @@ -164,7 +165,7 @@ section variable {α : Type*} [LinearOrderedField α] variable {β : Type*} [CommRing β] {abv : β → α} [IsAbsoluteValue abv] -instance Cauchy.commRing : CommRing (Cauchy abv) := +instance Cauchy.commRing : CommRing (Cauchy abv) := fast_instance% Function.Surjective.commRing mk Quotient.mk'_surjective zero_def.symm one_def.symm (fun _ _ => (mk_add _ _).symm) (fun _ _ => (mk_mul _ _).symm) (fun _ => (mk_neg _).symm) (fun _ _ => (mk_sub _ _).symm) (fun _ _ => (mk_smul _ _).symm) (fun _ _ => (mk_smul _ _).symm) diff --git a/Mathlib/Algebra/Order/Field/Subfield.lean b/Mathlib/Algebra/Order/Field/Subfield.lean index 6556c94ad7517..6b0ef75e83012 100644 --- a/Mathlib/Algebra/Order/Field/Subfield.lean +++ b/Mathlib/Algebra/Order/Field/Subfield.lean @@ -17,7 +17,7 @@ variable {K S : Type*} [SetLike S K] -- Prefer subclasses of `Field` over subclasses of `SubfieldClass`. /-- A subfield of a `LinearOrderedField` is a `LinearOrderedField`. -/ instance (priority := 75) toLinearOrderedField [LinearOrderedField K] - [SubfieldClass S K] (s : S) : LinearOrderedField s := + [SubfieldClass S K] (s : S) : LinearOrderedField s := fast_instance% Subtype.coe_injective.linearOrderedField Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) @@ -30,7 +30,8 @@ namespace Subfield variable {K : Type*} /-- A subfield of a `LinearOrderedField` is a `LinearOrderedField`. -/ -instance toLinearOrderedField [LinearOrderedField K] (s : Subfield K) : LinearOrderedField s := +instance toLinearOrderedField [LinearOrderedField K] (s : Subfield K) : + LinearOrderedField s := fast_instance% Subtype.coe_injective.linearOrderedField Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (by intros; rfl) diff --git a/Mathlib/Algebra/Order/Interval/Set/Instances.lean b/Mathlib/Algebra/Order/Interval/Set/Instances.lean index 06d73380d901f..9a3eed9085dfd 100644 --- a/Mathlib/Algebra/Order/Interval/Set/Instances.lean +++ b/Mathlib/Algebra/Order/Interval/Set/Instances.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.GroupWithZero.InjSurj import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Ring.Regular import Mathlib.Order.Interval.Set.Basic +import Mathlib.Tactic.FastInstance /-! # Algebraic instances for unit intervals @@ -118,20 +119,20 @@ theorem mul_le_left {x y : Icc (0 : α) 1} : x * y ≤ x := theorem mul_le_right {x y : Icc (0 : α) 1} : x * y ≤ y := (mul_le_mul_of_nonneg_right x.2.2 y.2.1).trans_eq (one_mul _) -instance monoidWithZero : MonoidWithZero (Icc (0 : α) 1) := +instance monoidWithZero : MonoidWithZero (Icc (0 : α) 1) := fast_instance% Subtype.coe_injective.monoidWithZero _ coe_zero coe_one coe_mul coe_pow instance commMonoidWithZero {α : Type*} [OrderedCommSemiring α] : - CommMonoidWithZero (Icc (0 : α) 1) := + CommMonoidWithZero (Icc (0 : α) 1) := fast_instance% Subtype.coe_injective.commMonoidWithZero _ coe_zero coe_one coe_mul coe_pow instance cancelMonoidWithZero {α : Type*} [OrderedRing α] [NoZeroDivisors α] : - CancelMonoidWithZero (Icc (0 : α) 1) := + CancelMonoidWithZero (Icc (0 : α) 1) := fast_instance% @Function.Injective.cancelMonoidWithZero α _ NoZeroDivisors.toCancelMonoidWithZero _ _ _ _ (fun v => v.val) Subtype.coe_injective coe_zero coe_one coe_mul coe_pow instance cancelCommMonoidWithZero {α : Type*} [OrderedCommRing α] [NoZeroDivisors α] : - CancelCommMonoidWithZero (Icc (0 : α) 1) := + CancelCommMonoidWithZero (Icc (0 : α) 1) := fast_instance% @Function.Injective.cancelCommMonoidWithZero α _ NoZeroDivisors.toCancelCommMonoidWithZero _ _ _ _ (fun v => v.val) Subtype.coe_injective coe_zero coe_one coe_mul coe_pow @@ -191,10 +192,11 @@ instance mul : Mul (Ico (0 : α) 1) where theorem coe_mul (x y : Ico (0 : α) 1) : ↑(x * y) = (x * y : α) := rfl -instance semigroup : Semigroup (Ico (0 : α) 1) := +instance semigroup : Semigroup (Ico (0 : α) 1) := fast_instance% Subtype.coe_injective.semigroup _ coe_mul -instance commSemigroup {α : Type*} [OrderedCommSemiring α] : CommSemigroup (Ico (0 : α) 1) := +instance commSemigroup {α : Type*} [OrderedCommSemiring α] : + CommSemigroup (Ico (0 : α) 1) := fast_instance% Subtype.coe_injective.commSemigroup _ coe_mul end Set.Ico @@ -250,17 +252,18 @@ theorem coe_mul (x y : Ioc (0 : α) 1) : ↑(x * y) = (x * y : α) := theorem coe_pow (x : Ioc (0 : α) 1) (n : ℕ) : ↑(x ^ n) = ((x : α) ^ n) := rfl -instance semigroup : Semigroup (Ioc (0 : α) 1) := +instance semigroup : Semigroup (Ioc (0 : α) 1) := fast_instance% Subtype.coe_injective.semigroup _ coe_mul -instance monoid : Monoid (Ioc (0 : α) 1) := +instance monoid : Monoid (Ioc (0 : α) 1) := fast_instance% Subtype.coe_injective.monoid _ coe_one coe_mul coe_pow -instance commSemigroup {α : Type*} [StrictOrderedCommSemiring α] : CommSemigroup (Ioc (0 : α) 1) := +instance commSemigroup {α : Type*} [StrictOrderedCommSemiring α] : + CommSemigroup (Ioc (0 : α) 1) := fast_instance% Subtype.coe_injective.commSemigroup _ coe_mul instance commMonoid {α : Type*} [StrictOrderedCommSemiring α] : - CommMonoid (Ioc (0 : α) 1) := + CommMonoid (Ioc (0 : α) 1) := fast_instance% Subtype.coe_injective.commMonoid _ coe_one coe_mul coe_pow instance cancelMonoid {α : Type*} [StrictOrderedRing α] [IsDomain α] : @@ -296,10 +299,11 @@ instance mul : Mul (Ioo (0 : α) 1) where theorem coe_mul (x y : Ioo (0 : α) 1) : ↑(x * y) = (x * y : α) := rfl -instance semigroup : Semigroup (Ioo (0 : α) 1) := +instance semigroup : Semigroup (Ioo (0 : α) 1) := fast_instance% Subtype.coe_injective.semigroup _ coe_mul -instance commSemigroup {α : Type*} [StrictOrderedCommSemiring α] : CommSemigroup (Ioo (0 : α) 1) := +instance commSemigroup {α : Type*} [StrictOrderedCommSemiring α] : + CommSemigroup (Ioo (0 : α) 1) := fast_instance% Subtype.coe_injective.commSemigroup _ coe_mul variable {β : Type*} [OrderedRing β] diff --git a/Mathlib/Algebra/Order/Monoid/Submonoid.lean b/Mathlib/Algebra/Order/Monoid/Submonoid.lean index f12cf9b2fc99b..ed546cdce5154 100644 --- a/Mathlib/Algebra/Order/Monoid/Submonoid.lean +++ b/Mathlib/Algebra/Order/Monoid/Submonoid.lean @@ -6,6 +6,7 @@ Authors: Damiano Testa import Mathlib.Algebra.Order.Monoid.Basic import Mathlib.Algebra.Group.Submonoid.Defs import Mathlib.Order.Interval.Set.Defs +import Mathlib.Tactic.FastInstance /-! # Ordered instances on submonoids @@ -20,7 +21,7 @@ variable {M S : Type*} [SetLike S M] /-- A submonoid of an `OrderedCommMonoid` is an `OrderedCommMonoid`. -/ @[to_additive "An `AddSubmonoid` of an `OrderedAddCommMonoid` is an `OrderedAddCommMonoid`."] instance (priority := 75) toOrderedCommMonoid [OrderedCommMonoid M] - [SubmonoidClass S M] (s : S) : OrderedCommMonoid s := + [SubmonoidClass S M] (s : S) : OrderedCommMonoid s := fast_instance% Subtype.coe_injective.orderedCommMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl -- Prefer subclasses of `Monoid` over subclasses of `SubmonoidClass`. @@ -28,7 +29,7 @@ instance (priority := 75) toOrderedCommMonoid [OrderedCommMonoid M] @[to_additive "An `AddSubmonoid` of a `LinearOrderedAddCommMonoid` is a `LinearOrderedAddCommMonoid`."] instance (priority := 75) toLinearOrderedCommMonoid [LinearOrderedCommMonoid M] - [SubmonoidClass S M] (s : S) : LinearOrderedCommMonoid s := + [SubmonoidClass S M] (s : S) : LinearOrderedCommMonoid s := fast_instance% Subtype.coe_injective.linearOrderedCommMonoid Subtype.val rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -37,7 +38,7 @@ instance (priority := 75) toLinearOrderedCommMonoid [LinearOrderedCommMonoid M] @[to_additive AddSubmonoidClass.toOrderedCancelAddCommMonoid "An `AddSubmonoid` of an `OrderedCancelAddCommMonoid` is an `OrderedCancelAddCommMonoid`."] instance (priority := 75) toOrderedCancelCommMonoid [OrderedCancelCommMonoid M] - [SubmonoidClass S M] (s : S) : OrderedCancelCommMonoid s := + [SubmonoidClass S M] (s : S) : OrderedCancelCommMonoid s := fast_instance% Subtype.coe_injective.orderedCancelCommMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl -- Prefer subclasses of `Monoid` over subclasses of `SubmonoidClass`. @@ -47,7 +48,7 @@ instance (priority := 75) toOrderedCancelCommMonoid [OrderedCancelCommMonoid M] "An `AddSubmonoid` of a `LinearOrderedCancelAddCommMonoid` is a `LinearOrderedCancelAddCommMonoid`."] instance (priority := 75) toLinearOrderedCancelCommMonoid [LinearOrderedCancelCommMonoid M] - [SubmonoidClass S M] (s : S) : LinearOrderedCancelCommMonoid s := + [SubmonoidClass S M] (s : S) : LinearOrderedCancelCommMonoid s := fast_instance% Subtype.coe_injective.linearOrderedCancelCommMonoid Subtype.val rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -59,14 +60,15 @@ variable {M : Type*} /-- A submonoid of an `OrderedCommMonoid` is an `OrderedCommMonoid`. -/ @[to_additive "An `AddSubmonoid` of an `OrderedAddCommMonoid` is an `OrderedAddCommMonoid`."] -instance toOrderedCommMonoid [OrderedCommMonoid M] (S : Submonoid M) : OrderedCommMonoid S := +instance toOrderedCommMonoid [OrderedCommMonoid M] (S : Submonoid M) : + OrderedCommMonoid S := fast_instance% Subtype.coe_injective.orderedCommMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl /-- A submonoid of a `LinearOrderedCommMonoid` is a `LinearOrderedCommMonoid`. -/ @[to_additive "An `AddSubmonoid` of a `LinearOrderedAddCommMonoid` is a `LinearOrderedAddCommMonoid`."] instance toLinearOrderedCommMonoid [LinearOrderedCommMonoid M] (S : Submonoid M) : - LinearOrderedCommMonoid S := + LinearOrderedCommMonoid S := fast_instance% Subtype.coe_injective.linearOrderedCommMonoid Subtype.val rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -74,7 +76,7 @@ instance toLinearOrderedCommMonoid [LinearOrderedCommMonoid M] (S : Submonoid M) @[to_additive AddSubmonoid.toOrderedCancelAddCommMonoid "An `AddSubmonoid` of an `OrderedCancelAddCommMonoid` is an `OrderedCancelAddCommMonoid`."] instance toOrderedCancelCommMonoid [OrderedCancelCommMonoid M] (S : Submonoid M) : - OrderedCancelCommMonoid S := + OrderedCancelCommMonoid S := fast_instance% Subtype.coe_injective.orderedCancelCommMonoid Subtype.val rfl (fun _ _ => rfl) fun _ _ => rfl /-- A submonoid of a `LinearOrderedCancelCommMonoid` is a `LinearOrderedCancelCommMonoid`. @@ -83,7 +85,7 @@ instance toOrderedCancelCommMonoid [OrderedCancelCommMonoid M] (S : Submonoid M) "An `AddSubmonoid` of a `LinearOrderedCancelAddCommMonoid` is a `LinearOrderedCancelAddCommMonoid`."] instance toLinearOrderedCancelCommMonoid [LinearOrderedCancelCommMonoid M] (S : Submonoid M) : - LinearOrderedCancelCommMonoid S := + LinearOrderedCancelCommMonoid S := fast_instance% Subtype.coe_injective.linearOrderedCancelCommMonoid Subtype.val rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/Algebra/Order/Nonneg/Field.lean b/Mathlib/Algebra/Order/Nonneg/Field.lean index 49c06d2e70cdd..1ffb11a94f50a 100644 --- a/Mathlib/Algebra/Order/Nonneg/Field.lean +++ b/Mathlib/Algebra/Order/Nonneg/Field.lean @@ -94,7 +94,7 @@ instance instNNRatSMul : SMul ℚ≥0 {x : α // 0 ≤ x} where (⟨q • a, by rw [NNRat.smul_def]; exact mul_nonneg q.cast_nonneg ha⟩ : {x : α // 0 ≤ x}) = q • a := rfl -instance linearOrderedSemifield : LinearOrderedSemifield { x : α // 0 ≤ x } := +instance linearOrderedSemifield : LinearOrderedSemifield { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.linearOrderedSemifield _ Nonneg.coe_zero Nonneg.coe_one Nonneg.coe_add Nonneg.coe_mul Nonneg.coe_inv Nonneg.coe_div (fun _ _ => rfl) coe_nnqsmul Nonneg.coe_pow Nonneg.coe_zpow Nonneg.coe_natCast coe_nnratCast (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/Algebra/Order/Nonneg/Ring.lean b/Mathlib/Algebra/Order/Nonneg/Ring.lean index 6c20dd04819c4..742ffb82c8154 100644 --- a/Mathlib/Algebra/Order/Nonneg/Ring.lean +++ b/Mathlib/Algebra/Order/Nonneg/Ring.lean @@ -11,6 +11,7 @@ import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.Ring.InjSurj import Mathlib.Order.CompleteLatticeIntervals import Mathlib.Order.LatticeIntervals +import Mathlib.Tactic.FastInstance /-! # Bundled ordered algebra instance on the type of nonnegative elements @@ -43,37 +44,39 @@ variable {α : Type*} namespace Nonneg -instance orderedAddCommMonoid [OrderedAddCommMonoid α] : OrderedAddCommMonoid { x : α // 0 ≤ x } := +instance orderedAddCommMonoid [OrderedAddCommMonoid α] : + OrderedAddCommMonoid { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.orderedAddCommMonoid _ Nonneg.coe_zero (fun _ _ => rfl) fun _ _ => rfl instance linearOrderedAddCommMonoid [LinearOrderedAddCommMonoid α] : - LinearOrderedAddCommMonoid { x : α // 0 ≤ x } := + LinearOrderedAddCommMonoid { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.linearOrderedAddCommMonoid _ Nonneg.coe_zero (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl instance orderedCancelAddCommMonoid [OrderedCancelAddCommMonoid α] : - OrderedCancelAddCommMonoid { x : α // 0 ≤ x } := + OrderedCancelAddCommMonoid { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.orderedCancelAddCommMonoid _ Nonneg.coe_zero (fun _ _ => rfl) fun _ _ => rfl instance linearOrderedCancelAddCommMonoid [LinearOrderedCancelAddCommMonoid α] : - LinearOrderedCancelAddCommMonoid { x : α // 0 ≤ x } := + LinearOrderedCancelAddCommMonoid { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.linearOrderedCancelAddCommMonoid _ Nonneg.coe_zero (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -instance orderedSemiring [OrderedSemiring α] : OrderedSemiring { x : α // 0 ≤ x } := +instance orderedSemiring [OrderedSemiring α] : OrderedSemiring { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.orderedSemiring _ Nonneg.coe_zero Nonneg.coe_one (fun _ _ => rfl) (fun _ _=> rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl instance strictOrderedSemiring [StrictOrderedSemiring α] : - StrictOrderedSemiring { x : α // 0 ≤ x } := + StrictOrderedSemiring { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.strictOrderedSemiring _ Nonneg.coe_zero Nonneg.coe_one (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl -instance orderedCommSemiring [OrderedCommSemiring α] : OrderedCommSemiring { x : α // 0 ≤ x } := +instance orderedCommSemiring [OrderedCommSemiring α] : + OrderedCommSemiring { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.orderedCommSemiring _ Nonneg.coe_zero Nonneg.coe_one (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl @@ -82,7 +85,7 @@ instance orderedCommMonoid [OrderedCommSemiring α] : OrderedCommMonoid { x : α mul_le_mul_left a _ h c := mul_le_mul le_rfl h a.prop c.prop instance strictOrderedCommSemiring [StrictOrderedCommSemiring α] : - StrictOrderedCommSemiring { x : α // 0 ≤ x } := + StrictOrderedCommSemiring { x : α // 0 ≤ x } := fast_instance% Subtype.coe_injective.strictOrderedCommSemiring _ Nonneg.coe_zero Nonneg.coe_one (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl diff --git a/Mathlib/Algebra/Order/Positive/Ring.lean b/Mathlib/Algebra/Order/Positive/Ring.lean index ff395b0df05ef..73dd89bc15ab3 100644 --- a/Mathlib/Algebra/Order/Positive/Ring.lean +++ b/Mathlib/Algebra/Order/Positive/Ring.lean @@ -5,6 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Ring.InjSurj +import Mathlib.Tactic.FastInstance /-! # Algebraic structures on the set of positive numbers @@ -32,19 +33,19 @@ instance : Add { x : M // 0 < x } := theorem coe_add (x y : { x : M // 0 < x }) : ↑(x + y) = (x + y : M) := rfl -instance addSemigroup : AddSemigroup { x : M // 0 < x } := +instance addSemigroup : AddSemigroup { x : M // 0 < x } := fast_instance% Subtype.coe_injective.addSemigroup _ coe_add instance addCommSemigroup {M : Type*} [AddCommMonoid M] [Preorder M] - [AddLeftStrictMono M] : AddCommSemigroup { x : M // 0 < x } := + [AddLeftStrictMono M] : AddCommSemigroup { x : M // 0 < x } := fast_instance% Subtype.coe_injective.addCommSemigroup _ coe_add instance addLeftCancelSemigroup {M : Type*} [AddLeftCancelMonoid M] [Preorder M] - [AddLeftStrictMono M] : AddLeftCancelSemigroup { x : M // 0 < x } := + [AddLeftStrictMono M] : AddLeftCancelSemigroup { x : M // 0 < x } := fast_instance% Subtype.coe_injective.addLeftCancelSemigroup _ coe_add instance addRightCancelSemigroup {M : Type*} [AddRightCancelMonoid M] [Preorder M] - [AddLeftStrictMono M] : AddRightCancelSemigroup { x : M // 0 < x } := + [AddLeftStrictMono M] : AddRightCancelSemigroup { x : M // 0 < x } := fast_instance% Subtype.coe_injective.addRightCancelSemigroup _ coe_add instance addLeftStrictMono : AddLeftStrictMono { x : M // 0 < x } := @@ -90,10 +91,10 @@ theorem val_pow (x : { x : R // 0 < x }) (n : ℕ) : ↑(x ^ n) = (x : R) ^ n := rfl -instance : Semigroup { x : R // 0 < x } := +instance : Semigroup { x : R // 0 < x } := fast_instance% Subtype.coe_injective.semigroup Subtype.val val_mul -instance : Distrib { x : R // 0 < x } := +instance : Distrib { x : R // 0 < x } := fast_instance% Subtype.coe_injective.distrib _ coe_add val_mul instance : One { x : R // 0 < x } := @@ -103,7 +104,7 @@ instance : One { x : R // 0 < x } := theorem val_one : ((1 : { x : R // 0 < x }) : R) = 1 := rfl -instance : Monoid { x : R // 0 < x } := +instance : Monoid { x : R // 0 < x } := fast_instance% Subtype.coe_injective.monoid _ val_one val_mul val_pow end Mul @@ -111,7 +112,7 @@ end Mul section mul_comm instance orderedCommMonoid [StrictOrderedCommSemiring R] : - OrderedCommMonoid { x : R // 0 < x } := + OrderedCommMonoid { x : R // 0 < x } := fast_instance% { Subtype.partialOrder _, Subtype.coe_injective.commMonoid (M₂ := R) (Subtype.val) val_one val_mul val_pow with mul_le_mul_left := fun _ _ hxy c => diff --git a/Mathlib/Algebra/Polynomial/Basic.lean b/Mathlib/Algebra/Polynomial/Basic.lean index e2e35c90fe8a0..a93b0c652a92e 100644 --- a/Mathlib/Algebra/Polynomial/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.MonoidAlgebra.Defs import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop import Mathlib.Data.Finset.Sort +import Mathlib.Tactic.FastInstance /-! # Theory of univariate polynomials @@ -266,37 +267,25 @@ instance inhabited : Inhabited R[X] := instance instNatCast : NatCast R[X] where natCast n := ofFinsupp n instance semiring : Semiring R[X] := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { Function.Injective.semiring toFinsupp toFinsupp_injective toFinsupp_zero toFinsupp_one - toFinsupp_add toFinsupp_mul (fun _ _ => toFinsupp_nsmul _ _) toFinsupp_pow fun _ => rfl with - toAdd := Polynomial.add' - toMul := Polynomial.mul' - toZero := Polynomial.zero - toOne := Polynomial.one - nsmul := (· • ·) - npow := fun n x => (x ^ n) } + fast_instance% Function.Injective.semiring toFinsupp toFinsupp_injective toFinsupp_zero + toFinsupp_one toFinsupp_add toFinsupp_mul (fun _ _ => toFinsupp_nsmul _ _) toFinsupp_pow + fun _ => rfl instance distribSMul {S} [DistribSMul S R] : DistribSMul S R[X] := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { Function.Injective.distribSMul ⟨⟨toFinsupp, toFinsupp_zero⟩, toFinsupp_add⟩ toFinsupp_injective - toFinsupp_smul with - toSMulZeroClass := Polynomial.smulZeroClass } + fast_instance% Function.Injective.distribSMul ⟨⟨toFinsupp, toFinsupp_zero⟩, toFinsupp_add⟩ + toFinsupp_injective toFinsupp_smul instance distribMulAction {S} [Monoid S] [DistribMulAction S R] : DistribMulAction S R[X] := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { Function.Injective.distribMulAction ⟨⟨toFinsupp, toFinsupp_zero (R := R)⟩, toFinsupp_add⟩ - toFinsupp_injective toFinsupp_smul with - toSMul := Polynomial.smulZeroClass.toSMul } + fast_instance% Function.Injective.distribMulAction + ⟨⟨toFinsupp, toFinsupp_zero (R := R)⟩, toFinsupp_add⟩ toFinsupp_injective toFinsupp_smul instance faithfulSMul {S} [SMulZeroClass S R] [FaithfulSMul S R] : FaithfulSMul S R[X] where eq_of_smul_eq_smul {_s₁ _s₂} h := eq_of_smul_eq_smul fun a : ℕ →₀ R => congr_arg toFinsupp (h ⟨a⟩) instance module {S} [Semiring S] [Module S R] : Module S R[X] := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { Function.Injective.module _ ⟨⟨toFinsupp, toFinsupp_zero⟩, toFinsupp_add⟩ toFinsupp_injective - toFinsupp_smul with - toDistribMulAction := Polynomial.distribMulAction } + fast_instance% Function.Injective.module _ ⟨⟨toFinsupp, toFinsupp_zero⟩, toFinsupp_add⟩ + toFinsupp_injective toFinsupp_smul instance smulCommClass {S₁ S₂} [SMulZeroClass S₁ R] [SMulZeroClass S₂ R] [SMulCommClass S₁ S₂ R] : SMulCommClass S₁ S₂ R[X] := @@ -1051,7 +1040,7 @@ section CommSemiring variable [CommSemiring R] instance commSemiring : CommSemiring R[X] := - { Function.Injective.commSemigroup toFinsupp toFinsupp_injective toFinsupp_mul with + fast_instance% { Function.Injective.commSemigroup toFinsupp toFinsupp_injective toFinsupp_mul with toSemiring := Polynomial.semiring } end CommSemiring @@ -1076,15 +1065,10 @@ theorem toFinsupp_zsmul (a : ℤ) (b : R[X]) : instance instIntCast : IntCast R[X] where intCast n := ofFinsupp n instance ring : Ring R[X] := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { Function.Injective.ring toFinsupp toFinsupp_injective (toFinsupp_zero (R := R)) + fast_instance% Function.Injective.ring toFinsupp toFinsupp_injective (toFinsupp_zero (R := R)) toFinsupp_one toFinsupp_add toFinsupp_mul toFinsupp_neg toFinsupp_sub (fun _ _ => toFinsupp_nsmul _ _) - (fun _ _ => toFinsupp_zsmul _ _) toFinsupp_pow (fun _ => rfl) fun _ => rfl with - toSemiring := Polynomial.semiring, - toNeg := Polynomial.neg' - toSub := Polynomial.sub - zsmul := ((· • ·) : ℤ → R[X] → R[X]) } + (fun _ _ => toFinsupp_zsmul _ _) toFinsupp_pow (fun _ => rfl) fun _ => rfl @[simp] theorem coeff_neg (p : R[X]) (n : ℕ) : coeff (-p) n = -coeff p n := by diff --git a/Mathlib/Algebra/Ring/Subring/Defs.lean b/Mathlib/Algebra/Ring/Subring/Defs.lean index 4ac441db39d99..69b8b9aab8fb8 100644 --- a/Mathlib/Algebra/Ring/Subring/Defs.lean +++ b/Mathlib/Algebra/Ring/Subring/Defs.lean @@ -97,14 +97,14 @@ instance (priority := 75) toHasIntCast : IntCast s := -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. /-- A subring of a ring inherits a ring structure -/ -instance (priority := 75) toRing : Ring s := +instance (priority := 75) toRing : Ring s := fast_instance% Subtype.coe_injective.ring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. /-- A subring of a `CommRing` is a `CommRing`. -/ instance (priority := 75) toCommRing {R} [CommRing R] [SetLike S R] [SubringClass S R] : - CommRing s := + CommRing s := fast_instance% Subtype.coe_injective.commRing Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl diff --git a/Mathlib/Algebra/Ring/Subring/Order.lean b/Mathlib/Algebra/Ring/Subring/Order.lean index e5e5fe0305d5a..ff7a1d9af142d 100644 --- a/Mathlib/Algebra/Ring/Subring/Order.lean +++ b/Mathlib/Algebra/Ring/Subring/Order.lean @@ -26,7 +26,7 @@ variable {R S : Type*} [SetLike S R] (s : S) -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. /-- A subring of an `OrderedRing` is an `OrderedRing`. -/ instance (priority := 75) toOrderedRing [OrderedRing R] [SubringClass S R] : - OrderedRing s := + OrderedRing s := fast_instance% Subtype.coe_injective.orderedRing Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl @@ -34,7 +34,7 @@ instance (priority := 75) toOrderedRing [OrderedRing R] [SubringClass S R] : -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. /-- A subring of an `OrderedCommRing` is an `OrderedCommRing`. -/ instance (priority := 75) toOrderedCommRing [OrderedCommRing R] [SubringClass S R] : - OrderedCommRing s := + OrderedCommRing s := fast_instance% Subtype.coe_injective.orderedCommRing Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl @@ -42,7 +42,7 @@ instance (priority := 75) toOrderedCommRing [OrderedCommRing R] [SubringClass S -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. /-- A subring of a `LinearOrderedRing` is a `LinearOrderedRing`. -/ instance (priority := 75) toLinearOrderedRing [LinearOrderedRing R] [SubringClass S R] : - LinearOrderedRing s := + LinearOrderedRing s := fast_instance% Subtype.coe_injective.linearOrderedRing Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -50,7 +50,7 @@ instance (priority := 75) toLinearOrderedRing [LinearOrderedRing R] [SubringClas -- Prefer subclasses of `Ring` over subclasses of `SubringClass`. /-- A subring of a `LinearOrderedCommRing` is a `LinearOrderedCommRing`. -/ instance (priority := 75) toLinearOrderedCommRing [LinearOrderedCommRing R] [SubringClass S R] : - LinearOrderedCommRing s := + LinearOrderedCommRing s := fast_instance% Subtype.coe_injective.linearOrderedCommRing Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ => rfl) (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean index 3d0186346b217..f409e13f8b5bc 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Defs.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Defs.lean @@ -71,7 +71,7 @@ namespace SubsemiringClass -- Prefer subclasses of `NonAssocSemiring` over subclasses of `SubsemiringClass`. /-- A subsemiring of a `NonAssocSemiring` inherits a `NonAssocSemiring` structure -/ -instance (priority := 75) toNonAssocSemiring : NonAssocSemiring s := +instance (priority := 75) toNonAssocSemiring : NonAssocSemiring s := fast_instance% Subtype.coe_injective.nonAssocSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl @@ -92,7 +92,7 @@ theorem coe_subtype : (subtype s : s → R) = ((↑) : s → R) := -- Prefer subclasses of `Semiring` over subclasses of `SubsemiringClass`. /-- A subsemiring of a `Semiring` is a `Semiring`. -/ instance (priority := 75) toSemiring {R} [Semiring R] [SetLike S R] [SubsemiringClass S R] : - Semiring s := + Semiring s := fast_instance% Subtype.coe_injective.semiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl @@ -105,7 +105,7 @@ theorem coe_pow {R} [Semiring R] [SetLike S R] [SubsemiringClass S R] (x : s) (n /-- A subsemiring of a `CommSemiring` is a `CommSemiring`. -/ instance toCommSemiring {R} [CommSemiring R] [SetLike S R] [SubsemiringClass S R] : - CommSemiring s := + CommSemiring s := fast_instance% Subtype.coe_injective.commSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl diff --git a/Mathlib/Algebra/Ring/Subsemiring/Order.lean b/Mathlib/Algebra/Ring/Subsemiring/Order.lean index cfe828f062d3f..3b042de898b4b 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Order.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Order.lean @@ -6,6 +6,7 @@ Authors: Damiano Testa import Mathlib.Algebra.Order.Ring.InjSurj import Mathlib.Algebra.Ring.Subsemiring.Defs import Mathlib.Order.Interval.Set.Defs +import Mathlib.Tactic.FastInstance /-! # `Order`ed instances for `SubsemiringClass` and `Subsemiring`. @@ -16,37 +17,37 @@ variable {R S : Type*} [SetLike S R] (s : S) /-- A subsemiring of an `OrderedSemiring` is an `OrderedSemiring`. -/ instance toOrderedSemiring [OrderedSemiring R] [SubsemiringClass S R] : - OrderedSemiring s := + OrderedSemiring s := fast_instance% Subtype.coe_injective.orderedSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of a `StrictOrderedSemiring` is a `StrictOrderedSemiring`. -/ instance toStrictOrderedSemiring [StrictOrderedSemiring R] - [SubsemiringClass S R] : StrictOrderedSemiring s := + [SubsemiringClass S R] : StrictOrderedSemiring s := fast_instance% Subtype.coe_injective.strictOrderedSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of an `OrderedCommSemiring` is an `OrderedCommSemiring`. -/ instance toOrderedCommSemiring [OrderedCommSemiring R] [SubsemiringClass S R] : - OrderedCommSemiring s := + OrderedCommSemiring s := fast_instance% Subtype.coe_injective.orderedCommSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of a `StrictOrderedCommSemiring` is a `StrictOrderedCommSemiring`. -/ instance toStrictOrderedCommSemiring [StrictOrderedCommSemiring R] - [SubsemiringClass S R] : StrictOrderedCommSemiring s := + [SubsemiringClass S R] : StrictOrderedCommSemiring s := fast_instance% Subtype.coe_injective.strictOrderedCommSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of a `LinearOrderedSemiring` is a `LinearOrderedSemiring`. -/ instance toLinearOrderedSemiring [LinearOrderedSemiring R] - [SubsemiringClass S R] : LinearOrderedSemiring s := + [SubsemiringClass S R] : LinearOrderedSemiring s := fast_instance% Subtype.coe_injective.linearOrderedSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) fun _ _ => rfl /-- A subsemiring of a `LinearOrderedCommSemiring` is a `LinearOrderedCommSemiring`. -/ instance toLinearOrderedCommSemiring [LinearOrderedCommSemiring R] - [SubsemiringClass S R] : LinearOrderedCommSemiring s := + [SubsemiringClass S R] : LinearOrderedCommSemiring s := fast_instance% Subtype.coe_injective.linearOrderedCommSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -58,37 +59,38 @@ namespace Subsemiring variable {R : Type*} /-- A subsemiring of an `OrderedSemiring` is an `OrderedSemiring`. -/ -instance toOrderedSemiring [OrderedSemiring R] (s : Subsemiring R) : OrderedSemiring s := +instance toOrderedSemiring [OrderedSemiring R] (s : Subsemiring R) : + OrderedSemiring s := fast_instance% Subtype.coe_injective.orderedSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of a `StrictOrderedSemiring` is a `StrictOrderedSemiring`. -/ instance toStrictOrderedSemiring [StrictOrderedSemiring R] (s : Subsemiring R) : - StrictOrderedSemiring s := + StrictOrderedSemiring s := fast_instance% Subtype.coe_injective.strictOrderedSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of an `OrderedCommSemiring` is an `OrderedCommSemiring`. -/ instance toOrderedCommSemiring [OrderedCommSemiring R] (s : Subsemiring R) : - OrderedCommSemiring s := + OrderedCommSemiring s := fast_instance% Subtype.coe_injective.orderedCommSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of a `StrictOrderedCommSemiring` is a `StrictOrderedCommSemiring`. -/ instance toStrictOrderedCommSemiring [StrictOrderedCommSemiring R] (s : Subsemiring R) : - StrictOrderedCommSemiring s := + StrictOrderedCommSemiring s := fast_instance% Subtype.coe_injective.strictOrderedCommSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl /-- A subsemiring of a `LinearOrderedSemiring` is a `LinearOrderedSemiring`. -/ instance toLinearOrderedSemiring [LinearOrderedSemiring R] (s : Subsemiring R) : - LinearOrderedSemiring s := + LinearOrderedSemiring s := fast_instance% Subtype.coe_injective.linearOrderedSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) fun _ _ => rfl /-- A subsemiring of a `LinearOrderedCommSemiring` is a `LinearOrderedCommSemiring`. -/ instance toLinearOrderedCommSemiring [LinearOrderedCommSemiring R] (s : Subsemiring R) : - LinearOrderedCommSemiring s := + LinearOrderedCommSemiring s := fast_instance% Subtype.coe_injective.linearOrderedCommSemiring Subtype.val rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/AlgebraicGeometry/Modules/Tilde.lean b/Mathlib/AlgebraicGeometry/Modules/Tilde.lean index aa13874400ecd..a8e8fd231a3dd 100644 --- a/Mathlib/AlgebraicGeometry/Modules/Tilde.lean +++ b/Mathlib/AlgebraicGeometry/Modules/Tilde.lean @@ -143,7 +143,7 @@ See also `Tilde.isLocallyFraction`. def tildeInType : Sheaf (Type u) (PrimeSpectrum.Top R) := subsheafToTypes (Tilde.isLocallyFraction M) -instance (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : +noncomputable instance (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : AddCommGroup (M.tildeInType.1.obj U) := inferInstanceAs <| AddCommGroup (Tilde.sectionsSubmodule M U) diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index 56eb68dc8f217..8b53485f90f37 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.Group.Indicator import Mathlib.Data.Set.Finite.Basic +import Mathlib.Tactic.FastInstance /-! # Type of functions with finite support @@ -487,7 +488,7 @@ theorem support_add_eq [DecidableEq α] {g₁ g₂ : α →₀ M} (h : Disjoint simp only [mem_support_iff, not_not] at *; simpa only [add_apply, this, zero_add] instance instAddZeroClass : AddZeroClass (α →₀ M) := - DFunLike.coe_injective.addZeroClass _ coe_zero coe_add + fast_instance% DFunLike.coe_injective.addZeroClass _ coe_zero coe_add instance instIsLeftCancelAdd [IsLeftCancelAdd M] : IsLeftCancelAdd (α →₀ M) where add_left_cancel _ _ _ h := ext fun x => add_left_cancel <| DFunLike.congr_fun h x @@ -566,14 +567,13 @@ instance instNatSMul : SMul ℕ (α →₀ M) := ⟨fun n v => v.mapRange (n • ·) (nsmul_zero _)⟩ instance instAddMonoid : AddMonoid (α →₀ M) := - DFunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => rfl + fast_instance% DFunLike.coe_injective.addMonoid _ coe_zero coe_add fun _ _ => rfl end AddMonoid instance instAddCommMonoid [AddCommMonoid M] : AddCommMonoid (α →₀ M) := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { DFunLike.coe_injective.addCommMonoid DFunLike.coe coe_zero coe_add (fun _ _ => rfl) with - toAddMonoid := Finsupp.instAddMonoid } + fast_instance% DFunLike.coe_injective.addCommMonoid + DFunLike.coe coe_zero coe_add (fun _ _ => rfl) instance instNeg [NegZeroClass G] : Neg (α →₀ G) := ⟨mapRange Neg.neg neg_zero⟩ @@ -616,16 +616,12 @@ instance instIntSMul [AddGroup G] : SMul ℤ (α →₀ G) := ⟨fun n v => v.mapRange (n • ·) (zsmul_zero _)⟩ instance instAddGroup [AddGroup G] : AddGroup (α →₀ G) := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { DFunLike.coe_injective.addGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub (fun _ _ => rfl) - fun _ _ => rfl with - toAddMonoid := Finsupp.instAddMonoid } + fast_instance% DFunLike.coe_injective.addGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub + (fun _ _ => rfl) fun _ _ => rfl instance instAddCommGroup [AddCommGroup G] : AddCommGroup (α →₀ G) := - --TODO: add reference to library note in PR https://github.com/leanprover-community/mathlib4/pull/7432 - { DFunLike.coe_injective.addCommGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub - (fun _ _ => rfl) fun _ _ => rfl with - toAddGroup := Finsupp.instAddGroup } + fast_instance% DFunLike.coe_injective.addCommGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub + (fun _ _ => rfl) fun _ _ => rfl @[simp] theorem support_neg [AddGroup G] (f : α →₀ G) : support (-f) = support f := diff --git a/Mathlib/GroupTheory/Congruence/Defs.lean b/Mathlib/GroupTheory/Congruence/Defs.lean index f3b58fe980782..43eb71a59dbeb 100644 --- a/Mathlib/GroupTheory/Congruence/Defs.lean +++ b/Mathlib/GroupTheory/Congruence/Defs.lean @@ -6,6 +6,7 @@ Authors: Amelia Livingston import Mathlib.Algebra.Group.InjSurj import Mathlib.Algebra.Group.Units.Defs import Mathlib.Data.Setoid.Basic +import Mathlib.Tactic.FastInstance /-! # Congruence relations @@ -638,48 +639,27 @@ instance {M : Type*} [Monoid M] (c : Con M) : Pow c.Quotient ℕ where /-- The quotient of a semigroup by a congruence relation is a semigroup. -/ @[to_additive "The quotient of an `AddSemigroup` by an additive congruence relation is an `AddSemigroup`."] -instance semigroup {M : Type*} [Semigroup M] (c : Con M) : Semigroup c.Quotient := - { (Function.Surjective.semigroup _ - Quotient.mk''_surjective fun _ _ => rfl : - Semigroup c.Quotient) with - /- The `toMul` field is given explicitly for performance reasons. - This avoids any need to unfold `Function.Surjective.semigroup` when the type checker is checking - that instance diagrams commute -/ - toMul := Con.hasMul _ } +instance semigroup {M : Type*} [Semigroup M] (c : Con M) : Semigroup c.Quotient := fast_instance% + Function.Surjective.semigroup _ Quotient.mk''_surjective fun _ _ => rfl /-- The quotient of a commutative semigroup by a congruence relation is a semigroup. -/ @[to_additive "The quotient of an `AddCommSemigroup` by an additive congruence relation is an `AddCommSemigroup`."] instance commSemigroup {M : Type*} [CommSemigroup M] (c : Con M) : CommSemigroup c.Quotient := - { (Function.Surjective.commSemigroup _ Quotient.mk''_surjective fun _ _ => rfl : - CommSemigroup c.Quotient) with - /- The `toSemigroup` field is given explicitly for performance reasons. - This avoids any need to unfold `Function.Surjective.commSemigroup` when the type checker is - checking that instance diagrams commute -/ - toSemigroup := Con.semigroup _ } + Function.Surjective.commSemigroup _ Quotient.mk''_surjective fun _ _ => rfl /-- The quotient of a monoid by a congruence relation is a monoid. -/ @[to_additive "The quotient of an `AddMonoid` by an additive congruence relation is an `AddMonoid`."] -instance monoid {M : Type*} [Monoid M] (c : Con M) : Monoid c.Quotient := - { (Function.Surjective.monoid _ Quotient.mk''_surjective rfl - (fun _ _ => rfl) fun _ _ => rfl : Monoid c.Quotient) with - /- The `toSemigroup` and `toOne` fields are given explicitly for performance reasons. - This avoids any need to unfold `Function.Surjective.monoid` when the type checker is - checking that instance diagrams commute -/ - toSemigroup := Con.semigroup _ - toOne := Con.one _ } +instance monoid {M : Type*} [Monoid M] (c : Con M) : Monoid c.Quotient := fast_instance% + Function.Surjective.monoid _ Quotient.mk''_surjective rfl (fun _ _ => rfl) fun _ _ => rfl /-- The quotient of a `CommMonoid` by a congruence relation is a `CommMonoid`. -/ @[to_additive "The quotient of an `AddCommMonoid` by an additive congruence relation is an `AddCommMonoid`."] -instance commMonoid {M : Type*} [CommMonoid M] (c : Con M) : CommMonoid c.Quotient := - { (Function.Surjective.commMonoid _ Quotient.mk''_surjective rfl - (fun _ _ => rfl) fun _ _ => rfl : CommMonoid c.Quotient) with - /- The `toMonoid` field is given explicitly for performance reasons. - This avoids any need to unfold `Function.Surjective.commMonoid` when the type checker is - checking that instance diagrams commute -/ - toMonoid := Con.monoid _ } +instance commMonoid {M : Type*} [CommMonoid M] (c : Con M) : CommMonoid c.Quotient := fast_instance% + fast_instance% Function.Surjective.commMonoid _ Quotient.mk''_surjective rfl + (fun _ _ => rfl) fun _ _ => rfl /-- Sometimes, a group is defined as a quotient of a monoid by a congruence relation. Usually, the inverse operation is defined as `Setoid.map f _` for some `f`. @@ -754,24 +734,16 @@ instance zpowinst : Pow c.Quotient ℤ := /-- The quotient of a group by a congruence relation is a group. -/ @[to_additive "The quotient of an `AddGroup` by an additive congruence relation is an `AddGroup`."] -instance group : Group c.Quotient := - { (Function.Surjective.group Quotient.mk'' - Quotient.mk''_surjective rfl (fun _ _ => rfl) (fun _ => rfl) - (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl : Group c.Quotient) with - toMonoid := Con.monoid _ - toInv := Con.hasInv _ - toDiv := Con.hasDiv _ } +instance group : Group c.Quotient := fast_instance% + Function.Surjective.group Quotient.mk'' Quotient.mk''_surjective + rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl /-- The quotient of a `CommGroup` by a congruence relation is a `CommGroup`. -/ @[to_additive "The quotient of an `AddCommGroup` by an additive congruence relation is an `AddCommGroup`."] -instance commGroup {M : Type*} [CommGroup M] (c : Con M) : CommGroup c.Quotient := - { (Function.Surjective.commGroup _ Quotient.mk''_surjective rfl (fun _ _ => rfl) (fun _ => rfl) - (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) : CommGroup c.Quotient) with - /- The `toGroup` field is given explicitly for performance reasons. - This avoids any need to unfold `Function.Surjective.commGroup` when the type checker is - checking that instance diagrams commute -/ - toGroup := Con.group _ } +instance commGroup {M : Type*} [CommGroup M] (c : Con M) : CommGroup c.Quotient := fast_instance% + Function.Surjective.commGroup _ Quotient.mk''_surjective rfl (fun _ _ => rfl) (fun _ => rfl) + (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) end Groups diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean index 74dd02ec163ae..f3eee53f08930 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean @@ -748,7 +748,7 @@ This is the affine version of `Submodule.topEquiv`. -/ def topEquiv : (⊤ : AffineSubspace k P) ≃ᵃ[k] P where toEquiv := Equiv.Set.univ P linear := .ofEq _ _ (direction_top _ _ _) ≪≫ₗ Submodule.topEquiv - map_vadd' _p _v := rfl + map_vadd' _ _ := rfl variable {P} @@ -1471,7 +1471,7 @@ This is the affine version of `Submodule.inclusion`. -/ def inclusion (h : S₁ ≤ S₂) : S₁ →ᵃ[k] S₂ where toFun := Set.inclusion h linear := Submodule.inclusion <| AffineSubspace.direction_le h - map_vadd' _ _ := rfl + map_vadd' := fun ⟨_,_⟩ ⟨_,_⟩ => rfl @[simp] theorem coe_inclusion_apply (h : S₁ ≤ S₂) (x : S₁) : (inclusion h x : P₁) = x := @@ -1511,14 +1511,15 @@ This is the affine version of `LinearEquiv.ofEq`. -/ def ofEq (h : S₁ = S₂) : S₁ ≃ᵃ[k] S₂ where toEquiv := Equiv.Set.ofEq <| congr_arg _ h linear := .ofEq _ _ <| congr_arg _ h - map_vadd' _ _ := rfl + map_vadd' := fun ⟨_,_⟩ ⟨_,_⟩ => rfl @[simp] theorem coe_ofEq_apply (h : S₁ = S₂) (x : S₁) : (ofEq S₁ S₂ h x : P₁) = x := rfl @[simp] -theorem ofEq_symm (h : S₁ = S₂) : (ofEq S₁ S₂ h).symm = ofEq S₂ S₁ h.symm := +theorem ofEq_symm (h : S₁ = S₂) : (ofEq S₁ S₂ h).symm = ofEq S₂ S₁ h.symm := by + ext rfl @[simp] diff --git a/Mathlib/LinearAlgebra/Quotient/Defs.lean b/Mathlib/LinearAlgebra/Quotient/Defs.lean index 810d76fdc6985..fc58414515648 100644 --- a/Mathlib/LinearAlgebra/Quotient/Defs.lean +++ b/Mathlib/LinearAlgebra/Quotient/Defs.lean @@ -143,12 +143,9 @@ section Module variable {S : Type*} --- Performance of `Function.Surjective.mulAction` is worse since it has to unify data to apply --- TODO: https://github.com/leanprover-community/mathlib4/pull/7432 instance mulAction' [Monoid S] [SMul S R] [MulAction S M] [IsScalarTower S R M] - (P : Submodule R M) : MulAction S (M ⧸ P) := - { Function.Surjective.mulAction mk Quot.mk_surjective <| Submodule.Quotient.mk_smul P with - toSMul := instSMul' _ } + (P : Submodule R M) : MulAction S (M ⧸ P) := fast_instance% + Function.Surjective.mulAction mk Quot.mk_surjective <| Submodule.Quotient.mk_smul P -- Porting note: should this be marked as a `@[default_instance]`? instance mulAction (P : Submodule R M) : MulAction R (M ⧸ P) := @@ -162,37 +159,28 @@ instance smulZeroClass' [SMul S R] [SMulZeroClass S M] [IsScalarTower S R M] (P instance smulZeroClass (P : Submodule R M) : SMulZeroClass R (M ⧸ P) := Quotient.smulZeroClass' P --- Performance of `Function.Surjective.distribSMul` is worse since it has to unify data to apply --- TODO: https://github.com/leanprover-community/mathlib4/pull/7432 instance distribSMul' [SMul S R] [DistribSMul S M] [IsScalarTower S R M] (P : Submodule R M) : - DistribSMul S (M ⧸ P) := - { Function.Surjective.distribSMul {toFun := mk, map_zero' := rfl, map_add' := fun _ _ => rfl} - Quot.mk_surjective (Submodule.Quotient.mk_smul P) with - toSMulZeroClass := smulZeroClass' _ } + DistribSMul S (M ⧸ P) := fast_instance% + Function.Surjective.distribSMul {toFun := mk, map_zero' := rfl, map_add' := fun _ _ => rfl} + Quot.mk_surjective (Submodule.Quotient.mk_smul P) -- Porting note: should this be marked as a `@[default_instance]`? instance distribSMul (P : Submodule R M) : DistribSMul R (M ⧸ P) := Quotient.distribSMul' P --- Performance of `Function.Surjective.distribMulAction` is worse since it has to unify data --- TODO: https://github.com/leanprover-community/mathlib4/pull/7432 instance distribMulAction' [Monoid S] [SMul S R] [DistribMulAction S M] [IsScalarTower S R M] - (P : Submodule R M) : DistribMulAction S (M ⧸ P) := - { Function.Surjective.distribMulAction {toFun := mk, map_zero' := rfl, map_add' := fun _ _ => rfl} - Quot.mk_surjective (Submodule.Quotient.mk_smul P) with - toMulAction := mulAction' _ } + (P : Submodule R M) : DistribMulAction S (M ⧸ P) := fast_instance% + Function.Surjective.distribMulAction {toFun := mk, map_zero' := rfl, map_add' := fun _ _ => rfl} + Quot.mk_surjective (Submodule.Quotient.mk_smul P) -- Porting note: should this be marked as a `@[default_instance]`? instance distribMulAction (P : Submodule R M) : DistribMulAction R (M ⧸ P) := Quotient.distribMulAction' P --- Performance of `Function.Surjective.module` is worse since it has to unify data to apply --- TODO: https://github.com/leanprover-community/mathlib4/pull/7432 instance module' [Semiring S] [SMul S R] [Module S M] [IsScalarTower S R M] (P : Submodule R M) : - Module S (M ⧸ P) := - { Function.Surjective.module _ {toFun := mk, map_zero' := by rfl, map_add' := fun _ _ => by rfl} - Quot.mk_surjective (Submodule.Quotient.mk_smul P) with - toDistribMulAction := distribMulAction' _ } + Module S (M ⧸ P) := fast_instance% + Function.Surjective.module _ {toFun := mk, map_zero' := by rfl, map_add' := fun _ _ => by rfl} + Quot.mk_surjective (Submodule.Quotient.mk_smul P) -- Porting note: should this be marked as a `@[default_instance]`? instance module (P : Submodule R M) : Module R (M ⧸ P) := diff --git a/Mathlib/RingTheory/Congruence/Defs.lean b/Mathlib/RingTheory/Congruence/Defs.lean index 106c5bf38657e..79d50bcfd7bb2 100644 --- a/Mathlib/RingTheory/Congruence/Defs.lean +++ b/Mathlib/RingTheory/Congruence/Defs.lean @@ -6,6 +6,7 @@ Authors: Eric Wieser import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Algebra.Ring.InjSurj import Mathlib.GroupTheory.Congruence.Defs +import Mathlib.Tactic.FastInstance /-! # Congruence relations on rings @@ -320,45 +321,47 @@ The operations above on the quotient by `c : RingCon R` preserve the algebraic s section Algebraic -instance [NonUnitalNonAssocSemiring R] (c : RingCon R) : NonUnitalNonAssocSemiring c.Quotient := +instance [NonUnitalNonAssocSemiring R] (c : RingCon R) : + NonUnitalNonAssocSemiring c.Quotient := fast_instance% Function.Surjective.nonUnitalNonAssocSemiring _ Quotient.mk''_surjective rfl (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -instance [NonAssocSemiring R] (c : RingCon R) : NonAssocSemiring c.Quotient := +instance [NonAssocSemiring R] (c : RingCon R) : NonAssocSemiring c.Quotient := fast_instance% Function.Surjective.nonAssocSemiring _ Quotient.mk''_surjective rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl -instance [NonUnitalSemiring R] (c : RingCon R) : NonUnitalSemiring c.Quotient := +instance [NonUnitalSemiring R] (c : RingCon R) : NonUnitalSemiring c.Quotient := fast_instance% Function.Surjective.nonUnitalSemiring _ Quotient.mk''_surjective rfl (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -instance [Semiring R] (c : RingCon R) : Semiring c.Quotient := +instance [Semiring R] (c : RingCon R) : Semiring c.Quotient := fast_instance% Function.Surjective.semiring _ Quotient.mk''_surjective rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl -instance [CommSemiring R] (c : RingCon R) : CommSemiring c.Quotient := +instance [CommSemiring R] (c : RingCon R) : CommSemiring c.Quotient := fast_instance% Function.Surjective.commSemiring _ Quotient.mk''_surjective rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl -instance [NonUnitalNonAssocRing R] (c : RingCon R) : NonUnitalNonAssocRing c.Quotient := +instance [NonUnitalNonAssocRing R] (c : RingCon R) : + NonUnitalNonAssocRing c.Quotient := fast_instance% Function.Surjective.nonUnitalNonAssocRing _ Quotient.mk''_surjective rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -instance [NonAssocRing R] (c : RingCon R) : NonAssocRing c.Quotient := +instance [NonAssocRing R] (c : RingCon R) : NonAssocRing c.Quotient := fast_instance% Function.Surjective.nonAssocRing _ Quotient.mk''_surjective rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl -instance [NonUnitalRing R] (c : RingCon R) : NonUnitalRing c.Quotient := +instance [NonUnitalRing R] (c : RingCon R) : NonUnitalRing c.Quotient := fast_instance% Function.Surjective.nonUnitalRing _ Quotient.mk''_surjective rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -instance [Ring R] (c : RingCon R) : Ring c.Quotient := +instance [Ring R] (c : RingCon R) : Ring c.Quotient := fast_instance% Function.Surjective.ring _ Quotient.mk''_surjective rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl -instance [CommRing R] (c : RingCon R) : CommRing c.Quotient := +instance [CommRing R] (c : RingCon R) : CommRing c.Quotient := fast_instance% Function.Surjective.commRing _ Quotient.mk''_surjective rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) fun _ => rfl diff --git a/Mathlib/RingTheory/NonUnitalSubring/Defs.lean b/Mathlib/RingTheory/NonUnitalSubring/Defs.lean index b0d51fc219306..b408644c2fc0e 100644 --- a/Mathlib/RingTheory/NonUnitalSubring/Defs.lean +++ b/Mathlib/RingTheory/NonUnitalSubring/Defs.lean @@ -5,6 +5,7 @@ Authors: Jireh Loreaux -/ import Mathlib.Algebra.Group.Subgroup.Defs import Mathlib.RingTheory.NonUnitalSubsemiring.Defs +import Mathlib.Tactic.FastInstance /-! # `NonUnitalSubring`s @@ -60,21 +61,21 @@ namespace NonUnitalSubringClass -- Prefer subclasses of `NonUnitalRing` over subclasses of `NonUnitalSubringClass`. /-- A non-unital subring of a non-unital ring inherits a non-unital ring structure -/ -instance (priority := 75) toNonUnitalNonAssocRing : NonUnitalNonAssocRing s := +instance (priority := 75) toNonUnitalNonAssocRing : NonUnitalNonAssocRing s := fast_instance% Subtype.val_injective.nonUnitalNonAssocRing _ rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -- Prefer subclasses of `NonUnitalRing` over subclasses of `NonUnitalSubringClass`. /-- A non-unital subring of a non-unital ring inherits a non-unital ring structure -/ instance (priority := 75) toNonUnitalRing {R : Type*} [NonUnitalRing R] [SetLike S R] - [NonUnitalSubringClass S R] (s : S) : NonUnitalRing s := + [NonUnitalSubringClass S R] (s : S) : NonUnitalRing s := fast_instance% Subtype.val_injective.nonUnitalRing _ rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -- Prefer subclasses of `NonUnitalRing` over subclasses of `NonUnitalSubringClass`. /-- A non-unital subring of a `NonUnitalCommRing` is a `NonUnitalCommRing`. -/ instance (priority := 75) toNonUnitalCommRing {R} [NonUnitalCommRing R] [SetLike S R] - [NonUnitalSubringClass S R] : NonUnitalCommRing s := + [NonUnitalSubringClass S R] : NonUnitalCommRing s := fast_instance% Subtype.val_injective.nonUnitalCommRing _ rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -249,7 +250,7 @@ protected theorem sub_mem {x y : R} (hx : x ∈ s) (hy : y ∈ s) : x - y ∈ s /-- A non-unital subring of a non-unital ring inherits a non-unital ring structure -/ instance toNonUnitalRing {R : Type*} [NonUnitalRing R] (s : NonUnitalSubring R) : - NonUnitalRing s := + NonUnitalRing s := fast_instance% Subtype.coe_injective.nonUnitalRing _ rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl @@ -277,7 +278,7 @@ theorem coe_eq_zero_iff {x : s} : (x : R) = 0 ↔ x = 0 := by /-- A non-unital subring of a `NonUnitalCommRing` is a `NonUnitalCommRing`. -/ instance toNonUnitalCommRing {R} [NonUnitalCommRing R] (s : NonUnitalSubring R) : - NonUnitalCommRing s := + NonUnitalCommRing s := fast_instance% Subtype.coe_injective.nonUnitalCommRing _ rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean b/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean index 366fb8a79c8b3..7104d467ac071 100644 --- a/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean +++ b/Mathlib/RingTheory/NonUnitalSubsemiring/Defs.lean @@ -6,6 +6,7 @@ Authors: Jireh Loreaux import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Algebra.Ring.InjSurj import Mathlib.Algebra.Group.Submonoid.Defs +import Mathlib.Tactic.FastInstance /-! # Bundled non-unital subsemirings @@ -41,7 +42,8 @@ open AddSubmonoidClass `NonUnitalSubsemiringClass`. -/ /-- A non-unital subsemiring of a `NonUnitalNonAssocSemiring` inherits a `NonUnitalNonAssocSemiring` structure -/ -instance (priority := 75) toNonUnitalNonAssocSemiring : NonUnitalNonAssocSemiring s := +instance (priority := 75) toNonUnitalNonAssocSemiring : + NonUnitalNonAssocSemiring s := fast_instance% Subtype.coe_injective.nonUnitalNonAssocSemiring Subtype.val rfl (by simp) (fun _ _ => rfl) fun _ _ => rfl @@ -59,12 +61,12 @@ theorem coeSubtype : (subtype s : s → R) = ((↑) : s → R) := /-- A non-unital subsemiring of a `NonUnitalSemiring` is a `NonUnitalSemiring`. -/ instance toNonUnitalSemiring {R} [NonUnitalSemiring R] [SetLike S R] - [NonUnitalSubsemiringClass S R] : NonUnitalSemiring s := + [NonUnitalSubsemiringClass S R] : NonUnitalSemiring s := fast_instance% Subtype.coe_injective.nonUnitalSemiring Subtype.val rfl (by simp) (fun _ _ => rfl) fun _ _ => rfl /-- A non-unital subsemiring of a `NonUnitalCommSemiring` is a `NonUnitalCommSemiring`. -/ instance toNonUnitalCommSemiring {R} [NonUnitalCommSemiring R] [SetLike S R] - [NonUnitalSubsemiringClass S R] : NonUnitalCommSemiring s := + [NonUnitalSubsemiringClass S R] : NonUnitalCommSemiring s := fast_instance% Subtype.coe_injective.nonUnitalCommSemiring Subtype.val rfl (by simp) (fun _ _ => rfl) fun _ _ => rfl diff --git a/Mathlib/Tactic/FastInstance.lean b/Mathlib/Tactic/FastInstance.lean index 4e2bd4871dee5..45ae5c3925ff1 100644 --- a/Mathlib/Tactic/FastInstance.lean +++ b/Mathlib/Tactic/FastInstance.lean @@ -110,7 +110,8 @@ For instance, when used as instance instSemiring : Semiring X := sorry instance instRing : Ring X := fast_instance% Function.Injective.ring .. ``` -this will define `instRing` as a nested constructor application that refers to `instSemiring`. +this will define `instRing` as a nested constructor application that refers to `instSemiring` +rather than applications of `Function.Injective.ring` or other non-canonical constructors. The advantage is then that `instRing.toSemiring` unifies almost immediately with `instSemiring`, rather than having to break it down into smaller pieces. -/ diff --git a/scripts/noshake.json b/scripts/noshake.json index d283ad44e616b..aa972bb4b8568 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -367,6 +367,7 @@ "Mathlib.Lean.Expr.ExtraRecognizers": ["Mathlib.Data.Set.Operations"], "Mathlib.Lean.Expr.Basic": ["Batteries.Logic"], "Mathlib.GroupTheory.MonoidLocalization.Basic": ["Mathlib.Init.Data.Prod"], + "Mathlib.GroupTheory.Congruence.Defs": ["Mathlib.Tactic.FastInstance"], "Mathlib.Geometry.Manifold.Sheaf.Smooth": ["Mathlib.CategoryTheory.Sites.Whiskering"], "Mathlib.Geometry.Manifold.PoincareConjecture": @@ -401,6 +402,7 @@ ["Mathlib.Order.ConditionallyCompleteLattice.Basic"], "Mathlib.Data.FunLike.Basic": ["Mathlib.Logic.Function.Basic"], "Mathlib.Data.Finsupp.Notation": ["Mathlib.Data.Finsupp.Single"], + "Mathlib.Data.Finsupp.Defs": ["Mathlib.Tactic.FastInstance"], "Mathlib.Data.Finset.Insert": ["Mathlib.Data.Finset.Attr"], "Mathlib.Data.ENat.Lattice": ["Mathlib.Algebra.Group.Action.Defs"], "Mathlib.Data.ByteArray": ["Batteries.Data.ByteSubarray"], @@ -447,11 +449,22 @@ "Mathlib.Algebra.ZeroOne.Lemmas": ["Batteries.Tactic.Init"], "Mathlib.Algebra.Star.Module": ["Mathlib.Algebra.Module.LinearMap.Star"], "Mathlib.Algebra.Ring.CentroidHom": ["Mathlib.Algebra.Algebra.Defs"], + "Mathlib.Algebra.Order.Ring.Nat": ["Mathlib.Algebra.Order.Group.Nat"], "Mathlib.Algebra.Order.Quantale": ["Mathlib.Tactic.Variable"], + "Mathlib.Algebra.Order.Positive.Ring": ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Order.Pi": ["Mathlib.Algebra.ZeroOne.Lemmas"], + "Mathlib.Algebra.Order.Nonneg.Ring": ["Mathlib.Tactic.FastInstance"], + "Mathlib.Algebra.Order.Nonneg.Field": ["Mathlib.Algebra.Order.Field.InjSurj"], + "Mathlib.Algebra.Order.Interval.Set.Instances": + ["Mathlib.Tactic.FastInstance"], + "Mathlib.Algebra.Order.Field.Subfield": + ["Mathlib.Algebra.Order.Field.InjSurj"], + "Mathlib.Algebra.Order.CauSeq.Completion": ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Order.CauSeq.Basic": ["Mathlib.Data.Setoid.Basic"], "Mathlib.Algebra.MonoidAlgebra.Basic": ["Mathlib.LinearAlgebra.Finsupp.SumProd"], + "Mathlib.Algebra.Module.Submodule.Order": + ["Mathlib.Algebra.Order.Group.InjSurj"], "Mathlib.Algebra.Module.LinearMap.Star": ["Mathlib.Algebra.Module.Equiv", "Mathlib.Algebra.Module.Equiv.Defs", @@ -459,10 +472,11 @@ "Mathlib.Algebra.Module.LinearMap.Basic": ["Mathlib.Algebra.Star.Basic"], "Mathlib.Algebra.Module.Equiv": ["Mathlib.Algebra.Star.Basic"], "Mathlib.Algebra.Homology.ModuleCat": ["Mathlib.Algebra.Homology.Homotopy"], - "Mathlib.Algebra.Group.Idempotent": ["Mathlib.Data.Subtype"], "Mathlib.Algebra.Group.Units.Basic": ["Mathlib.Tactic.Subsingleton"], "Mathlib.Algebra.Group.Units": ["Mathlib.Tactic.Subsingleton"], + "Mathlib.Algebra.Group.Subsemigroup.Defs": ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Group.Pi.Basic": ["Batteries.Tactic.Classical"], + "Mathlib.Algebra.Group.Idempotent": ["Mathlib.Data.Subtype"], "Mathlib.Algebra.Group.Defs": ["Mathlib.Tactic.OfNat"], "Mathlib.Algebra.GeomSum": ["Mathlib.Algebra.Order.BigOperators.Ring.Finset"], "Mathlib.Algebra.Category.Ring.Basic": @@ -474,8 +488,6 @@ "Mathlib.Algebra.BigOperators.Group.List": ["Mathlib.Data.List.ProdSigma"], "Mathlib.Algebra.Algebra.Subalgebra.Order": ["Mathlib.Algebra.Module.Submodule.Order"], - "Mathlib.Algebra.Order.Ring.Nat": - ["Mathlib.Algebra.Order.Group.Nat"], "Batteries.Tactic.OpenPrivate": ["Lean.Parser.Module"], "Batteries.Tactic.Omega.OmegaM": ["Batteries.Tactic.Omega.Int"], "Batteries.Tactic.Omega.Frontend": ["Batteries.Tactic.Omega.Logic"], From a7e69b0a2ff3179b8e6364f7b4955a67700218cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Fri, 24 Jan 2025 19:52:35 +0000 Subject: [PATCH 488/681] chore(AlgebraicTopology): split SimplicialSet.Basic (#21025) This PR only splits the file `AlgebraicTopology.SimplicialSet.Basic` by creating three new files `StdSimplex`, `Boundary`, `Horn`. This prepares for a refactor and future developments of API for these simplicial sets. For example, the boundary and the horn should be redefined (keeping the defeq) as subcomplexes of the standard simplex using the `Subpresheaf` API, see #20840. --- Mathlib.lean | 3 + .../AlgebraicTopology/ExtraDegeneracy.lean | 2 +- .../SimplicialSet/Basic.lean | 309 ------------------ .../SimplicialSet/Boundary.lean | 54 +++ .../AlgebraicTopology/SimplicialSet/Horn.lean | 167 ++++++++++ .../SimplicialSet/KanComplex.lean | 2 +- .../AlgebraicTopology/SimplicialSet/Path.lean | 2 +- .../SimplicialSet/StdSimplex.lean | 152 +++++++++ 8 files changed, 379 insertions(+), 312 deletions(-) create mode 100644 Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean create mode 100644 Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean create mode 100644 Mathlib/AlgebraicTopology/SimplicialSet/StdSimplex.lean diff --git a/Mathlib.lean b/Mathlib.lean index afb17fd169f07..b5d5e1fd3dbfc 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1112,12 +1112,15 @@ import Mathlib.AlgebraicTopology.SimplicialObject.Basic import Mathlib.AlgebraicTopology.SimplicialObject.Coskeletal import Mathlib.AlgebraicTopology.SimplicialObject.Split import Mathlib.AlgebraicTopology.SimplicialSet.Basic +import Mathlib.AlgebraicTopology.SimplicialSet.Boundary import Mathlib.AlgebraicTopology.SimplicialSet.Coskeletal import Mathlib.AlgebraicTopology.SimplicialSet.HomotopyCat +import Mathlib.AlgebraicTopology.SimplicialSet.Horn import Mathlib.AlgebraicTopology.SimplicialSet.KanComplex import Mathlib.AlgebraicTopology.SimplicialSet.Monoidal import Mathlib.AlgebraicTopology.SimplicialSet.Nerve import Mathlib.AlgebraicTopology.SimplicialSet.Path +import Mathlib.AlgebraicTopology.SimplicialSet.StdSimplex import Mathlib.AlgebraicTopology.SimplicialSet.StrictSegal import Mathlib.AlgebraicTopology.SingularSet import Mathlib.AlgebraicTopology.TopologicalSimplex diff --git a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean index d3372c2cc5cdc..e75d6e00a68dc 100644 --- a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean +++ b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.AlgebraicTopology.AlternatingFaceMapComplex -import Mathlib.AlgebraicTopology.SimplicialSet.Basic +import Mathlib.AlgebraicTopology.SimplicialSet.StdSimplex import Mathlib.AlgebraicTopology.CechNerve import Mathlib.Algebra.Homology.Homotopy import Mathlib.Tactic.FinCases diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean index 998e24cce1c55..628c8c85b00e8 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplicialObject.Basic -import Mathlib.CategoryTheory.Limits.Shapes.Types import Mathlib.CategoryTheory.Yoneda -import Mathlib.Data.Fin.VecNotation import Mathlib.Tactic.FinCases /-! @@ -19,16 +17,6 @@ i.e. a `Type`-valued presheaf on the simplex category. but this would be unnecessarily confusing given the existing notion of a simplicial type in homotopy type theory.) -We define the standard simplices `Δ[n]` as simplicial sets, -and their boundaries `∂Δ[n]` and horns `Λ[n, i]`. -(The notations are available via `Open Simplicial`.) - -## Future work - -There isn't yet a complete API for simplices, boundaries, and horns. -As an example, we should have a function that constructs -from a non-surjective order preserving function `Fin n → Fin n` -a morphism `Δ[n] ⟶ ∂Δ[n]`. -/ universe v u @@ -69,281 +57,6 @@ lemma comp_app {X Y Z : SSet} (f : X ⟶ Y) (g : Y ⟶ Z) (n : SimplexCategory def uliftFunctor : SSet.{u} ⥤ SSet.{max u v} := (SimplicialObject.whiskering _ _).obj CategoryTheory.uliftFunctor.{v, u} -/-- The functor `SimplexCategory ⥤ SSet` which sends `SimplexCategory.mk n` to -the standard simplex `Δ[n]` is a cosimplicial object in the category of simplicial sets. -(This functor is essentially given by the Yoneda embedding). -/ -def stdSimplex : CosimplicialObject SSet.{u} := - yoneda ⋙ uliftFunctor - -@[deprecated (since := "2025-01-23")] alias standardSimplex := stdSimplex - -@[inherit_doc SSet.stdSimplex] -scoped[Simplicial] notation3 "Δ[" n "]" => SSet.stdSimplex.obj (SimplexCategory.mk n) - -instance : Inhabited SSet := - ⟨Δ[0]⟩ - -namespace stdSimplex - -open Finset Opposite SimplexCategory - -@[simp] -lemma map_id (n : SimplexCategory) : - (SSet.stdSimplex.map (SimplexCategory.Hom.mk OrderHom.id : n ⟶ n)) = 𝟙 _ := - CategoryTheory.Functor.map_id _ _ - -/-- Simplices of the standard simplex identify to morphisms in `SimplexCategory`. -/ -def objEquiv (n : SimplexCategory) (m : SimplexCategoryᵒᵖ) : - (stdSimplex.{u}.obj n).obj m ≃ (m.unop ⟶ n) := - Equiv.ulift.{u, 0} - -/-- Constructor for simplices of the standard simplex which takes a `OrderHom` as an input. -/ -abbrev objMk {n : SimplexCategory} {m : SimplexCategoryᵒᵖ} - (f : Fin (len m.unop + 1) →o Fin (n.len + 1)) : - (stdSimplex.{u}.obj n).obj m := - (objEquiv _ _).symm (Hom.mk f) - -lemma map_apply {m₁ m₂ : SimplexCategoryᵒᵖ} (f : m₁ ⟶ m₂) {n : SimplexCategory} - (x : (stdSimplex.{u}.obj n).obj m₁) : - (stdSimplex.{u}.obj n).map f x = (objEquiv _ _).symm (f.unop ≫ (objEquiv _ _) x) := by - rfl - -/-- The canonical bijection `(stdSimplex.obj n ⟶ X) ≃ X.obj (op n)`. -/ -def _root_.SSet.yonedaEquiv (X : SSet.{u}) (n : SimplexCategory) : - (stdSimplex.obj n ⟶ X) ≃ X.obj (op n) := - yonedaCompUliftFunctorEquiv X n - -/-- The unique non-degenerate `n`-simplex in `Δ[n]`. -/ -def id (n : ℕ) : Δ[n] _[n] := yonedaEquiv Δ[n] [n] (𝟙 Δ[n]) - -lemma id_eq_objEquiv_symm (n : ℕ) : id n = (objEquiv _ _).symm (𝟙 _) := rfl - -lemma objEquiv_id (n : ℕ) : objEquiv _ _ (id n) = 𝟙 _ := rfl - -/-- The (degenerate) `m`-simplex in the standard simplex concentrated in vertex `k`. -/ -def const (n : ℕ) (k : Fin (n+1)) (m : SimplexCategoryᵒᵖ) : Δ[n].obj m := - objMk (OrderHom.const _ k ) - -@[simp] -lemma const_down_toOrderHom (n : ℕ) (k : Fin (n+1)) (m : SimplexCategoryᵒᵖ) : - (const n k m).down.toOrderHom = OrderHom.const _ k := - rfl - -/-- The edge of the standard simplex with endpoints `a` and `b`. -/ -def edge (n : ℕ) (a b : Fin (n+1)) (hab : a ≤ b) : Δ[n] _[1] := by - refine objMk ⟨![a, b], ?_⟩ - rw [Fin.monotone_iff_le_succ] - simp only [unop_op, len_mk, Fin.forall_fin_one] - apply Fin.mk_le_mk.mpr hab - -lemma coe_edge_down_toOrderHom (n : ℕ) (a b : Fin (n+1)) (hab : a ≤ b) : - ↑(edge n a b hab).down.toOrderHom = ![a, b] := - rfl - -/-- The triangle in the standard simplex with vertices `a`, `b`, and `c`. -/ -def triangle {n : ℕ} (a b c : Fin (n+1)) (hab : a ≤ b) (hbc : b ≤ c) : Δ[n] _[2] := by - refine objMk ⟨![a, b, c], ?_⟩ - rw [Fin.monotone_iff_le_succ] - simp only [unop_op, len_mk, Fin.forall_fin_two] - dsimp - simp only [*, Matrix.tail_cons, Matrix.head_cons, true_and] - -lemma coe_triangle_down_toOrderHom {n : ℕ} (a b c : Fin (n+1)) (hab : a ≤ b) (hbc : b ≤ c) : - ↑(triangle a b c hab hbc).down.toOrderHom = ![a, b, c] := - rfl - -end stdSimplex - -section - -/-- The `m`-simplices of the `n`-th standard simplex are -the monotone maps from `Fin (m+1)` to `Fin (n+1)`. -/ -def asOrderHom {n} {m} (α : Δ[n].obj m) : OrderHom (Fin (m.unop.len + 1)) (Fin (n + 1)) := - α.down.toOrderHom - -end - -/-- The boundary `∂Δ[n]` of the `n`-th standard simplex consists of -all `m`-simplices of `stdSimplex n` that are not surjective -(when viewed as monotone function `m → n`). -/ -def boundary (n : ℕ) : SSet.{u} where - obj m := { α : Δ[n].obj m // ¬Function.Surjective (asOrderHom α) } - map {m₁ m₂} f α := - ⟨Δ[n].map f α.1, by - intro h - apply α.property - exact Function.Surjective.of_comp h⟩ - -/-- The boundary `∂Δ[n]` of the `n`-th standard simplex -/ -scoped[Simplicial] notation3 "∂Δ[" n "]" => SSet.boundary n - -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{ α : Δ[n].obj m // _ }`. --/ -set_option linter.unusedVariables false in -/-- The inclusion of the boundary of the `n`-th standard simplex into that standard simplex. -/ -def boundaryInclusion (n : ℕ) : ∂Δ[n] ⟶ Δ[n] where app m (α : { α : Δ[n].obj m // _ }) := α - -/-- `horn n i` (or `Λ[n, i]`) is the `i`-th horn of the `n`-th standard simplex, where `i : n`. -It consists of all `m`-simplices `α` of `Δ[n]` -for which the union of `{i}` and the range of `α` is not all of `n` -(when viewing `α` as monotone function `m → n`). -/ -def horn (n : ℕ) (i : Fin (n + 1)) : SSet where - obj m := { α : Δ[n].obj m // Set.range (asOrderHom α) ∪ {i} ≠ Set.univ } - map {m₁ m₂} f α := - ⟨Δ[n].map f α.1, by - intro h; apply α.property - rw [Set.eq_univ_iff_forall] at h ⊢; intro j - apply Or.imp _ id (h j) - intro hj - exact Set.range_comp_subset_range _ _ hj⟩ - -/-- The `i`-th horn `Λ[n, i]` of the standard `n`-simplex -/ -scoped[Simplicial] notation3 "Λ[" n ", " i "]" => SSet.horn (n : ℕ) i - -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{ α : Δ[n].obj m // _ }`. --/ -set_option linter.unusedVariables false in -/-- The inclusion of the `i`-th horn of the `n`-th standard simplex into that standard simplex. -/ -def hornInclusion (n : ℕ) (i : Fin (n + 1)) : Λ[n, i] ⟶ Δ[n] where - app m (α : { α : Δ[n].obj m // _ }) := α - -namespace horn - -open SimplexCategory Finset Opposite - -/-- The (degenerate) subsimplex of `Λ[n+2, i]` concentrated in vertex `k`. -/ -@[simps] -def const (n : ℕ) (i k : Fin (n+3)) (m : SimplexCategoryᵒᵖ) : Λ[n+2, i].obj m := by - refine ⟨stdSimplex.const _ k _, ?_⟩ - suffices ¬ Finset.univ ⊆ {i, k} by - simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or, Fin.forall_fin_one, - subset_iff, mem_univ, @eq_comm _ _ k] - intro h - have := (card_le_card h).trans card_le_two - rw [card_fin] at this - omega - -/-- The edge of `Λ[n, i]` with endpoints `a` and `b`. - -This edge only exists if `{i, a, b}` has cardinality less than `n`. -/ -@[simps] -def edge (n : ℕ) (i a b : Fin (n+1)) (hab : a ≤ b) (H : #{i, a, b} ≤ n) : Λ[n, i] _[1] := by - refine ⟨stdSimplex.edge n a b hab, ?range⟩ - case range => - suffices ∃ x, ¬i = x ∧ ¬a = x ∧ ¬b = x by - simpa only [unop_op, len_mk, Nat.reduceAdd, asOrderHom, yoneda_obj_obj, Set.union_singleton, - ne_eq, ← Set.univ_subset_iff, Set.subset_def, Set.mem_univ, Set.mem_insert_iff, - @eq_comm _ _ i, Set.mem_range, forall_const, not_forall, not_or, not_exists, - Fin.forall_fin_two, Fin.isValue] - contrapose! H - replace H : univ ⊆ {i, a, b} := - fun x _ ↦ by simpa [or_iff_not_imp_left, eq_comm] using H x - replace H := card_le_card H - rwa [card_fin] at H - -/-- Alternative constructor for the edge of `Λ[n, i]` with endpoints `a` and `b`, -assuming `3 ≤ n`. -/ -@[simps!] -def edge₃ (n : ℕ) (i a b : Fin (n+1)) (hab : a ≤ b) (H : 3 ≤ n) : - Λ[n, i] _[1] := - horn.edge n i a b hab <| Finset.card_le_three.trans H - -/-- The edge of `Λ[n, i]` with endpoints `j` and `j+1`. - -This constructor assumes `0 < i < n`, -which is the type of horn that occurs in the horn-filling condition of quasicategories. -/ -@[simps!] -def primitiveEdge {n : ℕ} {i : Fin (n+1)} - (h₀ : 0 < i) (hₙ : i < Fin.last n) (j : Fin n) : - Λ[n, i] _[1] := by - refine horn.edge n i j.castSucc j.succ ?_ ?_ - · simp only [← Fin.val_fin_le, Fin.coe_castSucc, Fin.val_succ, le_add_iff_nonneg_right, zero_le] - simp only [← Fin.val_fin_lt, Fin.val_zero, Fin.val_last] at h₀ hₙ - obtain rfl|hn : n = 2 ∨ 2 < n := by - rw [eq_comm, or_comm, ← le_iff_lt_or_eq]; omega - · revert i j; decide - · exact Finset.card_le_three.trans hn - -/-- The triangle in the standard simplex with vertices `k`, `k+1`, and `k+2`. - -This constructor assumes `0 < i < n`, -which is the type of horn that occurs in the horn-filling condition of quasicategories. -/ -@[simps] -def primitiveTriangle {n : ℕ} (i : Fin (n+4)) - (h₀ : 0 < i) (hₙ : i < Fin.last (n+3)) - (k : ℕ) (h : k < n+2) : Λ[n+3, i] _[2] := by - refine ⟨stdSimplex.triangle - (n := n+3) ⟨k, by omega⟩ ⟨k+1, by omega⟩ ⟨k+2, by omega⟩ ?_ ?_, ?_⟩ - · simp only [Fin.mk_le_mk, le_add_iff_nonneg_right, zero_le] - · simp only [Fin.mk_le_mk, add_le_add_iff_left, one_le_two] - simp only [unop_op, SimplexCategory.len_mk, asOrderHom, SimplexCategory.Hom.toOrderHom_mk, - OrderHom.const_coe_coe, Set.union_singleton, ne_eq, ← Set.univ_subset_iff, Set.subset_def, - Set.mem_univ, Set.mem_insert_iff, Set.mem_range, Function.const_apply, exists_const, - forall_true_left, not_forall, not_or, unop_op, not_exists, - stdSimplex.triangle, OrderHom.coe_mk, @eq_comm _ _ i, - stdSimplex.objMk, stdSimplex.objEquiv, Equiv.ulift] - dsimp - by_cases hk0 : k = 0 - · subst hk0 - use Fin.last (n+3) - simp only [hₙ.ne, not_false_eq_true, Fin.zero_eta, zero_add, true_and] - intro j - fin_cases j <;> simp [Fin.ext_iff] - · use 0 - simp only [h₀.ne', not_false_eq_true, true_and] - intro j - fin_cases j <;> simp [Fin.ext_iff, hk0] - -/-- The `j`th subface of the `i`-th horn. -/ -@[simps] -def face {n : ℕ} (i j : Fin (n+2)) (h : j ≠ i) : Λ[n+1, i] _[n] := - ⟨(stdSimplex.objEquiv _ _).symm (SimplexCategory.δ j), by - simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, SimplexCategory.δ, not_or, - stdSimplex.objEquiv, asOrderHom, Equiv.ulift]⟩ - -/-- Two morphisms from a horn are equal if they are equal on all suitable faces. -/ -protected -lemma hom_ext {n : ℕ} {i : Fin (n+2)} {S : SSet} (σ₁ σ₂ : Λ[n+1, i] ⟶ S) - (h : ∀ (j) (h : j ≠ i), σ₁.app _ (face i j h) = σ₂.app _ (face i j h)) : - σ₁ = σ₂ := by - apply NatTrans.ext; apply funext; apply Opposite.rec; apply SimplexCategory.rec - intro m; ext f - obtain ⟨f', hf⟩ := (stdSimplex.objEquiv _ _).symm.surjective f.1 - obtain ⟨j, hji, hfj⟩ : ∃ j, ¬j = i ∧ ∀ k, f'.toOrderHom k ≠ j := by - obtain ⟨f, hf'⟩ := f - subst hf - simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or] using hf' - have H : f = (Λ[n+1, i].map (factor_δ f' j).op) (face i j hji) := by - apply Subtype.ext - apply (stdSimplex.objEquiv _ _).injective - rw [← hf] - exact (factor_δ_spec f' j hfj).symm - have H₁ := congrFun (σ₁.naturality (factor_δ f' j).op) (face i j hji) - have H₂ := congrFun (σ₂.naturality (factor_δ f' j).op) (face i j hji) - dsimp at H₁ H₂ - rw [H, H₁, H₂, h _ hji] - -end horn - -section Examples - -open Simplicial - -/-- The simplicial circle. -/ -noncomputable def S1 : SSet := - Limits.colimit <| - Limits.parallelPair (stdSimplex.δ 0 : Δ[0] ⟶ Δ[1]) (stdSimplex.δ 1) - -end Examples - /-- Truncated simplicial sets. -/ def Truncated (n : ℕ) := SimplicialObject.Truncated (Type u) n @@ -373,10 +86,6 @@ lemma Truncated.hom_ext {n : ℕ} {X Y : Truncated n} {f g : X ⟶ Y} (w : ∀ n /-- The truncation functor on simplicial sets. -/ abbrev truncation (n : ℕ) : SSet ⥤ SSet.Truncated n := SimplicialObject.truncation n -instance {n} : Inhabited (SSet.Truncated n) := - ⟨(truncation n).obj <| Δ[0]⟩ - - open SimplexCategory noncomputable section @@ -450,24 +159,6 @@ augmented simplicial objects. -/ abbrev Augmented := SimplicialObject.Augmented (Type u) -namespace Augmented - --- Porting note: an instance of `Subsingleton (⊤_ (Type u))` was added in --- `CategoryTheory.Limits.Types` to ease the automation in this definition -/-- The functor which sends `[n]` to the simplicial set `Δ[n]` equipped by -the obvious augmentation towards the terminal object of the category of sets. -/ -@[simps] -noncomputable def stdSimplex : SimplexCategory ⥤ SSet.Augmented.{u} where - obj Δ := - { left := SSet.stdSimplex.obj Δ - right := terminal _ - hom := { app := fun _ => terminal.from _ } } - map θ := - { left := SSet.stdSimplex.map θ - right := terminal.from _ } - -end Augmented - section applications variable {S : SSet} diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean new file mode 100644 index 0000000000000..58805409d1ceb --- /dev/null +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2021 Kim Morrison. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johan Commelin, Kim Morrison, Adam Topaz +-/ +import Mathlib.AlgebraicTopology.SimplicialSet.StdSimplex + +/-! +# The boundary of the standard simplex + +We introduce the boundary `∂Δ[n]` of the standard simplex `Δ[n]`. +(These notations become available by doing `open Simplicial`.) + +## Future work + +There isn't yet a complete API for simplices, boundaries, and horns. +As an example, we should have a function that constructs +from a non-surjective order preserving function `Fin n → Fin n` +a morphism `Δ[n] ⟶ ∂Δ[n]`. + + +-/ + +universe u + +open Simplicial + +namespace SSet + +/-- The boundary `∂Δ[n]` of the `n`-th standard simplex consists of +all `m`-simplices of `stdSimplex n` that are not surjective +(when viewed as monotone function `m → n`). -/ +def boundary (n : ℕ) : SSet.{u} where + obj m := { α : Δ[n].obj m // ¬Function.Surjective (asOrderHom α) } + map {m₁ m₂} f α := + ⟨Δ[n].map f α.1, by + intro h + apply α.property + exact Function.Surjective.of_comp h⟩ + +/-- The boundary `∂Δ[n]` of the `n`-th standard simplex -/ +scoped[Simplicial] notation3 "∂Δ[" n "]" => SSet.boundary n + +#adaptation_note +/-- +The new unused variable linter in +https://github.com/leanprover/lean4/pull/5338 +flags `{ α : Δ[n].obj m // _ }`. +-/ +set_option linter.unusedVariables false in +/-- The inclusion of the boundary of the `n`-th standard simplex into that standard simplex. -/ +def boundaryInclusion (n : ℕ) : ∂Δ[n] ⟶ Δ[n] where app m (α : { α : Δ[n].obj m // _ }) := α + +end SSet diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean new file mode 100644 index 0000000000000..ef8c001fd1d79 --- /dev/null +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean @@ -0,0 +1,167 @@ +/- +Copyright (c) 2021 Kim Morrison. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johan Commelin, Kim Morrison, Adam Topaz +-/ +import Mathlib.AlgebraicTopology.SimplicialSet.StdSimplex + +/-! +# Horns + +This file introduce horns `Λ[n, i]`. + +-/ + +universe u + +open CategoryTheory Simplicial + +namespace SSet + +/-- `horn n i` (or `Λ[n, i]`) is the `i`-th horn of the `n`-th standard simplex, where `i : n`. +It consists of all `m`-simplices `α` of `Δ[n]` +for which the union of `{i}` and the range of `α` is not all of `n` +(when viewing `α` as monotone function `m → n`). -/ +def horn (n : ℕ) (i : Fin (n + 1)) : SSet where + obj m := { α : Δ[n].obj m // Set.range (asOrderHom α) ∪ {i} ≠ Set.univ } + map {m₁ m₂} f α := + ⟨Δ[n].map f α.1, by + intro h; apply α.property + rw [Set.eq_univ_iff_forall] at h ⊢; intro j + apply Or.imp _ id (h j) + intro hj + exact Set.range_comp_subset_range _ _ hj⟩ + +/-- The `i`-th horn `Λ[n, i]` of the standard `n`-simplex -/ +scoped[Simplicial] notation3 "Λ[" n ", " i "]" => SSet.horn (n : ℕ) i + +#adaptation_note +/-- +The new unused variable linter in +https://github.com/leanprover/lean4/pull/5338 +flags `{ α : Δ[n].obj m // _ }`. +-/ +set_option linter.unusedVariables false in +/-- The inclusion of the `i`-th horn of the `n`-th standard simplex into that standard simplex. -/ +def hornInclusion (n : ℕ) (i : Fin (n + 1)) : Λ[n, i] ⟶ Δ[n] where + app m (α : { α : Δ[n].obj m // _ }) := α + +namespace horn + +open SimplexCategory Finset Opposite + +/-- The (degenerate) subsimplex of `Λ[n+2, i]` concentrated in vertex `k`. -/ +@[simps] +def const (n : ℕ) (i k : Fin (n+3)) (m : SimplexCategoryᵒᵖ) : Λ[n+2, i].obj m := by + refine ⟨stdSimplex.const _ k _, ?_⟩ + suffices ¬ Finset.univ ⊆ {i, k} by + simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or, Fin.forall_fin_one, + subset_iff, mem_univ, @eq_comm _ _ k] + intro h + have := (card_le_card h).trans card_le_two + rw [card_fin] at this + omega + +/-- The edge of `Λ[n, i]` with endpoints `a` and `b`. + +This edge only exists if `{i, a, b}` has cardinality less than `n`. -/ +@[simps] +def edge (n : ℕ) (i a b : Fin (n+1)) (hab : a ≤ b) (H : #{i, a, b} ≤ n) : Λ[n, i] _[1] := by + refine ⟨stdSimplex.edge n a b hab, ?range⟩ + case range => + suffices ∃ x, ¬i = x ∧ ¬a = x ∧ ¬b = x by + simpa only [unop_op, len_mk, Nat.reduceAdd, asOrderHom, yoneda_obj_obj, Set.union_singleton, + ne_eq, ← Set.univ_subset_iff, Set.subset_def, Set.mem_univ, Set.mem_insert_iff, + @eq_comm _ _ i, Set.mem_range, forall_const, not_forall, not_or, not_exists, + Fin.forall_fin_two, Fin.isValue] + contrapose! H + replace H : univ ⊆ {i, a, b} := + fun x _ ↦ by simpa [or_iff_not_imp_left, eq_comm] using H x + replace H := card_le_card H + rwa [card_fin] at H + +/-- Alternative constructor for the edge of `Λ[n, i]` with endpoints `a` and `b`, +assuming `3 ≤ n`. -/ +@[simps!] +def edge₃ (n : ℕ) (i a b : Fin (n+1)) (hab : a ≤ b) (H : 3 ≤ n) : + Λ[n, i] _[1] := + horn.edge n i a b hab <| Finset.card_le_three.trans H + +/-- The edge of `Λ[n, i]` with endpoints `j` and `j+1`. + +This constructor assumes `0 < i < n`, +which is the type of horn that occurs in the horn-filling condition of quasicategories. -/ +@[simps!] +def primitiveEdge {n : ℕ} {i : Fin (n+1)} + (h₀ : 0 < i) (hₙ : i < Fin.last n) (j : Fin n) : + Λ[n, i] _[1] := by + refine horn.edge n i j.castSucc j.succ ?_ ?_ + · simp only [← Fin.val_fin_le, Fin.coe_castSucc, Fin.val_succ, le_add_iff_nonneg_right, zero_le] + simp only [← Fin.val_fin_lt, Fin.val_zero, Fin.val_last] at h₀ hₙ + obtain rfl|hn : n = 2 ∨ 2 < n := by + rw [eq_comm, or_comm, ← le_iff_lt_or_eq]; omega + · revert i j; decide + · exact Finset.card_le_three.trans hn + +/-- The triangle in the standard simplex with vertices `k`, `k+1`, and `k+2`. + +This constructor assumes `0 < i < n`, +which is the type of horn that occurs in the horn-filling condition of quasicategories. -/ +@[simps] +def primitiveTriangle {n : ℕ} (i : Fin (n+4)) + (h₀ : 0 < i) (hₙ : i < Fin.last (n+3)) + (k : ℕ) (h : k < n+2) : Λ[n+3, i] _[2] := by + refine ⟨stdSimplex.triangle + (n := n+3) ⟨k, by omega⟩ ⟨k+1, by omega⟩ ⟨k+2, by omega⟩ ?_ ?_, ?_⟩ + · simp only [Fin.mk_le_mk, le_add_iff_nonneg_right, zero_le] + · simp only [Fin.mk_le_mk, add_le_add_iff_left, one_le_two] + simp only [unop_op, SimplexCategory.len_mk, asOrderHom, SimplexCategory.Hom.toOrderHom_mk, + OrderHom.const_coe_coe, Set.union_singleton, ne_eq, ← Set.univ_subset_iff, Set.subset_def, + Set.mem_univ, Set.mem_insert_iff, Set.mem_range, Function.const_apply, exists_const, + forall_true_left, not_forall, not_or, unop_op, not_exists, + stdSimplex.triangle, OrderHom.coe_mk, @eq_comm _ _ i, + stdSimplex.objMk, stdSimplex.objEquiv, Equiv.ulift] + dsimp + by_cases hk0 : k = 0 + · subst hk0 + use Fin.last (n+3) + simp only [hₙ.ne, not_false_eq_true, Fin.zero_eta, zero_add, true_and] + intro j + fin_cases j <;> simp [Fin.ext_iff] + · use 0 + simp only [h₀.ne', not_false_eq_true, true_and] + intro j + fin_cases j <;> simp [Fin.ext_iff, hk0] + +/-- The `j`th subface of the `i`-th horn. -/ +@[simps] +def face {n : ℕ} (i j : Fin (n+2)) (h : j ≠ i) : Λ[n+1, i] _[n] := + ⟨(stdSimplex.objEquiv _ _).symm (SimplexCategory.δ j), by + simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, SimplexCategory.δ, not_or, + stdSimplex.objEquiv, asOrderHom, Equiv.ulift]⟩ + +/-- Two morphisms from a horn are equal if they are equal on all suitable faces. -/ +protected +lemma hom_ext {n : ℕ} {i : Fin (n+2)} {S : SSet} (σ₁ σ₂ : Λ[n+1, i] ⟶ S) + (h : ∀ (j) (h : j ≠ i), σ₁.app _ (face i j h) = σ₂.app _ (face i j h)) : + σ₁ = σ₂ := by + apply NatTrans.ext; apply funext; apply Opposite.rec; apply SimplexCategory.rec + intro m; ext f + obtain ⟨f', hf⟩ := (stdSimplex.objEquiv _ _).symm.surjective f.1 + obtain ⟨j, hji, hfj⟩ : ∃ j, ¬j = i ∧ ∀ k, f'.toOrderHom k ≠ j := by + obtain ⟨f, hf'⟩ := f + subst hf + simpa [← Set.univ_subset_iff, Set.subset_def, asOrderHom, not_or] using hf' + have H : f = (Λ[n+1, i].map (factor_δ f' j).op) (face i j hji) := by + apply Subtype.ext + apply (stdSimplex.objEquiv _ _).injective + rw [← hf] + exact (factor_δ_spec f' j hfj).symm + have H₁ := congrFun (σ₁.naturality (factor_δ f' j).op) (face i j hji) + have H₂ := congrFun (σ₂.naturality (factor_δ f' j).op) (face i j hji) + dsimp at H₁ H₂ + rw [H, H₁, H₂, h _ hji] + +end horn + +end SSet diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean index 982bd19ff062b..47ca5bae4df0c 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.AlgebraicTopology.SimplicialSet.Basic +import Mathlib.AlgebraicTopology.SimplicialSet.Horn /-! # Kan complexes diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean index b28e32a3ebf16..3969919746617 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Emily Riehl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Emily Riehl, Joël Riou -/ -import Mathlib.AlgebraicTopology.SimplicialSet.Basic +import Mathlib.AlgebraicTopology.SimplicialSet.Horn /-! # Paths in simplicial sets diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/StdSimplex.lean b/Mathlib/AlgebraicTopology/SimplicialSet/StdSimplex.lean new file mode 100644 index 0000000000000..60fefd38146d0 --- /dev/null +++ b/Mathlib/AlgebraicTopology/SimplicialSet/StdSimplex.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2021 Kim Morrison. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johan Commelin, Kim Morrison, Adam Topaz +-/ +import Mathlib.AlgebraicTopology.SimplicialSet.Basic +import Mathlib.CategoryTheory.Limits.Shapes.Types +import Mathlib.Data.Fin.VecNotation + +/-! +# The standard simplex + +We define the standard simplices `Δ[n]` as simplicial sets. +See files `SimplicialSet.Boundary` and `SimplicialSet.Horn` +for their boundaries`∂Δ[n]` and horns `Λ[n, i]`. +(The notations are available via `open Simplicial`.) + +-/ + +universe u + +open CategoryTheory Limits Simplicial + +namespace SSet + +/-- The functor `SimplexCategory ⥤ SSet` which sends `SimplexCategory.mk n` to +the standard simplex `Δ[n]` is a cosimplicial object in the category of simplicial sets. +(This functor is essentially given by the Yoneda embedding). -/ +def stdSimplex : CosimplicialObject SSet.{u} := + yoneda ⋙ uliftFunctor + +@[deprecated (since := "2025-01-23")] alias standardSimplex := stdSimplex + +@[inherit_doc SSet.stdSimplex] +scoped[Simplicial] notation3 "Δ[" n "]" => SSet.stdSimplex.obj (SimplexCategory.mk n) + +instance : Inhabited SSet := + ⟨Δ[0]⟩ + +instance {n} : Inhabited (SSet.Truncated n) := + ⟨(truncation n).obj <| Δ[0]⟩ + +namespace stdSimplex + +open Finset Opposite SimplexCategory + +@[simp] +lemma map_id (n : SimplexCategory) : + (SSet.stdSimplex.map (SimplexCategory.Hom.mk OrderHom.id : n ⟶ n)) = 𝟙 _ := + CategoryTheory.Functor.map_id _ _ + +/-- Simplices of the standard simplex identify to morphisms in `SimplexCategory`. -/ +def objEquiv (n : SimplexCategory) (m : SimplexCategoryᵒᵖ) : + (stdSimplex.{u}.obj n).obj m ≃ (m.unop ⟶ n) := + Equiv.ulift.{u, 0} + +/-- Constructor for simplices of the standard simplex which takes a `OrderHom` as an input. -/ +abbrev objMk {n : SimplexCategory} {m : SimplexCategoryᵒᵖ} + (f : Fin (len m.unop + 1) →o Fin (n.len + 1)) : + (stdSimplex.{u}.obj n).obj m := + (objEquiv _ _).symm (Hom.mk f) + +lemma map_apply {m₁ m₂ : SimplexCategoryᵒᵖ} (f : m₁ ⟶ m₂) {n : SimplexCategory} + (x : (stdSimplex.{u}.obj n).obj m₁) : + (stdSimplex.{u}.obj n).map f x = (objEquiv _ _).symm (f.unop ≫ (objEquiv _ _) x) := by + rfl + +/-- The canonical bijection `(stdSimplex.obj n ⟶ X) ≃ X.obj (op n)`. -/ +def _root_.SSet.yonedaEquiv (X : SSet.{u}) (n : SimplexCategory) : + (stdSimplex.obj n ⟶ X) ≃ X.obj (op n) := + yonedaCompUliftFunctorEquiv X n + +/-- The unique non-degenerate `n`-simplex in `Δ[n]`. -/ +def id (n : ℕ) : Δ[n] _[n] := yonedaEquiv Δ[n] [n] (𝟙 Δ[n]) + +lemma id_eq_objEquiv_symm (n : ℕ) : id n = (objEquiv _ _).symm (𝟙 _) := rfl + +lemma objEquiv_id (n : ℕ) : objEquiv _ _ (id n) = 𝟙 _ := rfl + +/-- The (degenerate) `m`-simplex in the standard simplex concentrated in vertex `k`. -/ +def const (n : ℕ) (k : Fin (n+1)) (m : SimplexCategoryᵒᵖ) : Δ[n].obj m := + objMk (OrderHom.const _ k ) + +@[simp] +lemma const_down_toOrderHom (n : ℕ) (k : Fin (n+1)) (m : SimplexCategoryᵒᵖ) : + (const n k m).down.toOrderHom = OrderHom.const _ k := + rfl + +/-- The edge of the standard simplex with endpoints `a` and `b`. -/ +def edge (n : ℕ) (a b : Fin (n+1)) (hab : a ≤ b) : Δ[n] _[1] := by + refine objMk ⟨![a, b], ?_⟩ + rw [Fin.monotone_iff_le_succ] + simp only [unop_op, len_mk, Fin.forall_fin_one] + apply Fin.mk_le_mk.mpr hab + +lemma coe_edge_down_toOrderHom (n : ℕ) (a b : Fin (n+1)) (hab : a ≤ b) : + ↑(edge n a b hab).down.toOrderHom = ![a, b] := + rfl + +/-- The triangle in the standard simplex with vertices `a`, `b`, and `c`. -/ +def triangle {n : ℕ} (a b c : Fin (n+1)) (hab : a ≤ b) (hbc : b ≤ c) : Δ[n] _[2] := by + refine objMk ⟨![a, b, c], ?_⟩ + rw [Fin.monotone_iff_le_succ] + simp only [unop_op, len_mk, Fin.forall_fin_two] + dsimp + simp only [*, Matrix.tail_cons, Matrix.head_cons, true_and] + +lemma coe_triangle_down_toOrderHom {n : ℕ} (a b c : Fin (n+1)) (hab : a ≤ b) (hbc : b ≤ c) : + ↑(triangle a b c hab hbc).down.toOrderHom = ![a, b, c] := + rfl + +end stdSimplex + +section + +/-- The `m`-simplices of the `n`-th standard simplex are +the monotone maps from `Fin (m+1)` to `Fin (n+1)`. -/ +def asOrderHom {n} {m} (α : Δ[n].obj m) : OrderHom (Fin (m.unop.len + 1)) (Fin (n + 1)) := + α.down.toOrderHom + +end + +section Examples + +open Simplicial + +/-- The simplicial circle. -/ +noncomputable def S1 : SSet := + Limits.colimit <| + Limits.parallelPair (stdSimplex.δ 0 : Δ[0] ⟶ Δ[1]) (stdSimplex.δ 1) + +end Examples + +namespace Augmented + +-- Porting note: an instance of `Subsingleton (⊤_ (Type u))` was added in +-- `CategoryTheory.Limits.Types` to ease the automation in this definition +/-- The functor which sends `[n]` to the simplicial set `Δ[n]` equipped by +the obvious augmentation towards the terminal object of the category of sets. -/ +@[simps] +noncomputable def stdSimplex : SimplexCategory ⥤ SSet.Augmented.{u} where + obj Δ := + { left := SSet.stdSimplex.obj Δ + right := terminal _ + hom := { app := fun _ => terminal.from _ } } + map θ := + { left := SSet.stdSimplex.map θ + right := terminal.from _ } + +end Augmented + +end SSet From a02db214424cc2f035f0bcc2fdff0c74662d89ae Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Fri, 24 Jan 2025 20:24:56 +0000 Subject: [PATCH 489/681] chore: simplify some proofs with `rfl` and `tauto` (#20985) Those simplifications were found by [`tryAtEachStep`](https://github.com/dwrensha/tryAtEachStep). Co-authored-by: Moritz Firsching --- Mathlib/Algebra/Algebra/Quasispectrum.lean | 9 +-------- .../PiTensorProduct/ProjectiveSeminorm.lean | 9 +-------- .../CategoryTheory/Triangulated/Opposite/Basic.lean | 3 --- Mathlib/Combinatorics/SimpleGraph/Walk.lean | 9 ++------- Mathlib/LinearAlgebra/SesquilinearForm.lean | 6 +----- .../ModularForms/CongruenceSubgroups.lean | 12 +----------- Mathlib/Topology/Gluing.lean | 6 +----- 7 files changed, 7 insertions(+), 47 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Quasispectrum.lean b/Mathlib/Algebra/Algebra/Quasispectrum.lean index 5dce203059f77..fa1469c46f1a2 100644 --- a/Mathlib/Algebra/Algebra/Quasispectrum.lean +++ b/Mathlib/Algebra/Algebra/Quasispectrum.lean @@ -586,11 +586,4 @@ lemma quasispectrumRestricts_iff_spectrumRestricts_inr' theorem quasispectrumRestricts_iff_spectrumRestricts {R S A : Type*} [Semifield R] [Semifield S] [Ring A] [Algebra R S] [Algebra R A] [Algebra S A] {a : A} {f : S → R} : - QuasispectrumRestricts a f ↔ SpectrumRestricts a f := by - rw [quasispectrumRestricts_iff, spectrumRestricts_iff, quasispectrum_eq_spectrum_union_zero] - refine and_congr_left fun h ↦ ?_ - refine ⟨(Set.RightInvOn.mono · Set.subset_union_left), fun h' x hx ↦ ?_⟩ - simp only [Set.union_singleton, Set.mem_insert_iff] at hx - obtain (rfl | hx) := hx - · simpa using h 0 - · exact h' hx + QuasispectrumRestricts a f ↔ SpectrumRestricts a f := by rfl diff --git a/Mathlib/Analysis/NormedSpace/PiTensorProduct/ProjectiveSeminorm.lean b/Mathlib/Analysis/NormedSpace/PiTensorProduct/ProjectiveSeminorm.lean index edb1a33efca0f..2f9a18162eca1 100644 --- a/Mathlib/Analysis/NormedSpace/PiTensorProduct/ProjectiveSeminorm.lean +++ b/Mathlib/Analysis/NormedSpace/PiTensorProduct/ProjectiveSeminorm.lean @@ -98,14 +98,7 @@ noncomputable def projectiveSeminorm : Seminorm 𝕜 (⨂[𝕜] i, E i) := by refine Seminorm.ofSMulLE (fun x ↦ iInf (fun (p : lifts x) ↦ projectiveSeminormAux p.1)) ?_ ?_ ?_ · refine le_antisymm ?_ ?_ · refine ciInf_le_of_le (bddBelow_projectiveSemiNormAux (0 : ⨂[𝕜] i, E i)) ⟨0, lifts_zero⟩ ?_ - simp only [projectiveSeminormAux, Function.comp_apply] - rw [List.sum_eq_zero] - intro _ - simp only [List.mem_map, Prod.exists, forall_exists_index, and_imp] - intro _ _ hxm - rw [← FreeAddMonoid.ofList_nil] at hxm - exfalso - exact List.not_mem_nil _ hxm + rfl · letI : Nonempty (lifts 0) := ⟨0, lifts_zero (R := 𝕜) (s := E)⟩ exact le_ciInf (fun p ↦ projectiveSeminormAux_nonneg p.1) · intro x y diff --git a/Mathlib/CategoryTheory/Triangulated/Opposite/Basic.lean b/Mathlib/CategoryTheory/Triangulated/Opposite/Basic.lean index 94ae9013b1c47..f336e41e98c31 100644 --- a/Mathlib/CategoryTheory/Triangulated/Opposite/Basic.lean +++ b/Mathlib/CategoryTheory/Triangulated/Opposite/Basic.lean @@ -99,9 +99,6 @@ lemma shiftFunctorAdd'_op_hom_app (X : Cᵒᵖ) (a₁ a₂ a₃ : ℤ) (h : a₁ erw [@pullbackShiftFunctorAdd'_hom_app (OppositeShift C ℤ) _ _ _ _ _ _ _ X a₁ a₂ a₃ h b₁ b₂ b₃ (by dsimp; omega) (by dsimp; omega) (by dsimp; omega)] rw [oppositeShiftFunctorAdd'_hom_app] - obtain rfl : b₁ = -a₁ := by omega - obtain rfl : b₂ = -a₂ := by omega - obtain rfl : b₃ = -a₃ := by omega rfl lemma shiftFunctorAdd'_op_inv_app (X : Cᵒᵖ) (a₁ a₂ a₃ : ℤ) (h : a₁ + a₂ = a₃) diff --git a/Mathlib/Combinatorics/SimpleGraph/Walk.lean b/Mathlib/Combinatorics/SimpleGraph/Walk.lean index 06aaabee0f997..86e1e71cf4a52 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Walk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Walk.lean @@ -1120,15 +1120,10 @@ theorem exists_boundary_dart {u v : V} (p : G.Walk u v) (S : Set V) (uS : u ∈ exact ⟨d, List.Mem.tail _ hd, hcd⟩ · exact ⟨⟨(x, y), a⟩, List.Mem.head _, uS, h⟩ -@[simp] lemma getVert_copy {u v w x : V} (p : G.Walk u v) (i : ℕ) (h : u = w) (h' : v = x) : +@[simp] lemma getVert_copy {u v w x : V} (p : G.Walk u v) (i : ℕ) (h : u = w) (h' : v = x) : (p.copy h h').getVert i = p.getVert i := by subst_vars - match p, i with - | .nil, _ => - rw [getVert_of_length_le _ (by simp only [length_nil, Nat.zero_le] : nil.length ≤ _)] - rw [getVert_of_length_le _ (by simp only [length_copy, length_nil, Nat.zero_le])] - | .cons hadj q, 0 => simp only [copy_rfl_rfl, getVert_zero] - | .cons hadj q, (n + 1) => simp only [copy_cons, getVert_cons_succ]; rfl + rfl @[simp] lemma getVert_tail {u v n} (p : G.Walk u v) : p.tail.getVert n = p.getVert (n + 1) := by diff --git a/Mathlib/LinearAlgebra/SesquilinearForm.lean b/Mathlib/LinearAlgebra/SesquilinearForm.lean index 504d2acfe7e8e..a3423723021fe 100644 --- a/Mathlib/LinearAlgebra/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/SesquilinearForm.lean @@ -79,11 +79,7 @@ theorem isOrthoᵢ_def {B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] M} {v : n theorem isOrthoᵢ_flip (B : M₁ →ₛₗ[I₁] M₁ →ₛₗ[I₁'] M) {v : n → M₁} : B.IsOrthoᵢ v ↔ B.flip.IsOrthoᵢ v := by simp_rw [isOrthoᵢ_def] - constructor <;> intro h i j hij - · rw [flip_apply] - exact h j i (Ne.symm hij) - simp_rw [flip_apply] at h - exact h j i (Ne.symm hij) + constructor <;> exact fun h i j hij ↦ h j i hij.symm end CommRing diff --git a/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean b/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean index ee91db811cdfa..cf81fe88e9ba2 100644 --- a/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean +++ b/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean @@ -67,17 +67,7 @@ theorem Gamma_one_top : Gamma 1 = ⊤ := by lemma mem_Gamma_one (γ : SL(2, ℤ)) : γ ∈ Γ(1) := by simp only [Gamma_one_top, Subgroup.mem_top] -theorem Gamma_zero_bot : Gamma 0 = ⊥ := by - ext - simp only [Gamma_mem, coe_matrix_coe, Int.coe_castRingHom, map_apply, Int.cast_id, - Subgroup.mem_bot] - constructor - · intro h - ext i j - fin_cases i <;> fin_cases j <;> simp only [h] - exacts [h.1, h.2.1, h.2.2.1, h.2.2.2] - · intro h - simp [h] +theorem Gamma_zero_bot : Gamma 0 = ⊥ := rfl lemma ModularGroup_T_pow_mem_Gamma (N M : ℤ) (hNM : N ∣ M) : (ModularGroup.T ^ M) ∈ Gamma (Int.natAbs N) := by diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index ca721bddc94f1..bf2384b9dc371 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -100,11 +100,7 @@ theorem isOpen_iff (U : Set 𝖣.glued) : IsOpen U ↔ ∀ i, IsOpen (𝖣.ι i simp_rw [← Multicoequalizer.ι_sigmaπ 𝖣.diagram] rw [← (homeoOfIso (Multicoequalizer.isoCoequalizer 𝖣.diagram).symm).isOpen_preimage] rw [coequalizer_isOpen_iff, colimit_isOpen_iff.{u}] - dsimp only [GlueData.diagram_l, GlueData.diagram_left, GlueData.diagram_r, GlueData.diagram_right, - parallelPair_obj_one] - constructor - · intro h j; exact h ⟨j⟩ - · intro h j; cases j; apply h + tauto theorem ι_jointly_surjective (x : 𝖣.glued) : ∃ (i : _) (y : D.U i), 𝖣.ι i y = x := 𝖣.ι_jointly_surjective (forget TopCat) x From 6d3806f20df5903e938b25be0a3dc0a1ffb393fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Fri, 24 Jan 2025 20:24:57 +0000 Subject: [PATCH 490/681] feat(Order/WellFounded): a relation is well-founded iff there's no infinite decreasing sequence (#21010) --- Mathlib/Order/OrderIsoNat.lean | 4 +++- Mathlib/Order/WellFounded.lean | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Mathlib/Order/OrderIsoNat.lean b/Mathlib/Order/OrderIsoNat.lean index 0c00be9047fa7..891efab009d6f 100644 --- a/Mathlib/Order/OrderIsoNat.lean +++ b/Mathlib/Order/OrderIsoNat.lean @@ -77,7 +77,9 @@ theorem not_acc_of_decreasing_seq (f : ((· > ·) : ℕ → ℕ → Prop) ↪r r rw [acc_iff_no_decreasing_seq, not_isEmpty_iff] exact ⟨⟨f, k, rfl⟩⟩ -/-- A relation is well-founded iff it doesn't have any infinite decreasing sequence. -/ +/-- A strict order relation is well-founded iff it doesn't have any infinite decreasing sequence. + +See `wellFounded_iff_no_descending_seq` for a version which works on any relation. -/ theorem wellFounded_iff_no_descending_seq : WellFounded r ↔ IsEmpty (((· > ·) : ℕ → ℕ → Prop) ↪r r) := by constructor diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index 5aa9a2eaa166b..e9675df3ac387 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -78,6 +78,26 @@ theorem wellFounded_iff_has_min {r : α → α → Prop} : by_contra hy' exact hm' y hy' hy +/-- A relation is well-founded iff it doesn't have any infinite decreasing sequence. + +See `RelEmbedding.wellFounded_iff_no_descending_seq` for a version on strict orders. -/ +theorem wellFounded_iff_no_descending_seq : + WellFounded r ↔ IsEmpty { f : ℕ → α // ∀ n, r (f (n + 1)) (f n) } := by + rw [WellFounded.wellFounded_iff_has_min] + refine ⟨fun hr ↦ ⟨fun ⟨f, hf⟩ ↦ ?_⟩, ?_⟩ + · obtain ⟨_, ⟨n, rfl⟩, hn⟩ := hr _ (Set.range_nonempty f) + exact hn _ (Set.mem_range_self (n + 1)) (hf n) + · contrapose! + rw [not_isEmpty_iff] + rintro ⟨s, hs, hs'⟩ + let f : ℕ → s := Nat.rec (Classical.indefiniteDescription _ hs) fun n IH ↦ + ⟨(hs' _ IH.2).choose, (hs' _ IH.2).choose_spec.1⟩ + exact ⟨⟨Subtype.val ∘ f, fun n ↦ (hs' _ (f n).2).choose_spec.2⟩⟩ + +theorem not_rel_apply_succ [h : IsWellFounded α r] (f : ℕ → α) : ∃ n, ¬ r (f (n + 1)) (f n) := by + by_contra! hf + exact (wellFounded_iff_no_descending_seq.1 h.wf).elim ⟨f, hf⟩ + open Set /-- The supremum of a bounded, well-founded order -/ From 2b9299ee24f7ec68d2efc27a64d9105386af633d Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Fri, 24 Jan 2025 21:41:24 +0000 Subject: [PATCH 491/681] feat(AlgebraicGeometry): API for zero locus (#20812) Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib/AlgebraicGeometry/AffineScheme.lean | 149 ++++++++++++++++-- .../GammaSpecAdjunction.lean | 2 +- Mathlib/AlgebraicGeometry/OpenImmersion.lean | 22 ++- Mathlib/AlgebraicGeometry/Scheme.lean | 70 ++++++++ Mathlib/Order/BooleanAlgebra.lean | 6 + Mathlib/Topology/Sets/Opens.lean | 6 + 6 files changed, 239 insertions(+), 16 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index 3dda7880479b0..a7a71a986a8ca 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -74,6 +74,16 @@ theorem Scheme.isoSpec_inv_naturality {X Y : Scheme} [IsAffine X] [IsAffine Y] ( rw [Iso.eq_inv_comp, isoSpec, asIso_hom, ← Scheme.toSpecΓ_naturality_assoc, isoSpec, asIso_inv, IsIso.hom_inv_id, Category.comp_id] +@[reassoc (attr := simp)] +lemma Scheme.toSpecΓ_isoSpec_inv (X : Scheme.{u}) [IsAffine X] : + X.toSpecΓ ≫ X.isoSpec.inv = 𝟙 _ := + X.isoSpec.hom_inv_id + +@[reassoc (attr := simp)] +lemma Scheme.isoSpec_inv_toSpecΓ (X : Scheme.{u}) [IsAffine X] : + X.isoSpec.inv ≫ X.toSpecΓ = 𝟙 _ := + X.isoSpec.inv_hom_id + /-- Construct an affine scheme from a scheme and the information that it is affine. Also see `AffineScheme.of` for a typeclass version. -/ @[simps] @@ -281,12 +291,17 @@ def Scheme.Opens.toSpecΓ {X : Scheme.{u}} (U : X.Opens) : lemma Scheme.Opens.toSpecΓ_SpecMap_map {X : Scheme} (U V : X.Opens) (h : U ≤ V) : U.toSpecΓ ≫ Spec.map (X.presheaf.map (homOfLE h).op) = X.homOfLE h ≫ V.toSpecΓ := by delta Scheme.Opens.toSpecΓ - simp [← Spec.map_comp, ← X.presheaf.map_comp] + simp [← Spec.map_comp, ← X.presheaf.map_comp, toSpecΓ_naturality_assoc] @[simp] lemma Scheme.Opens.toSpecΓ_top {X : Scheme} : (⊤ : X.Opens).toSpecΓ = (⊤ : X.Opens).ι ≫ X.toSpecΓ := by - simp [Scheme.Opens.toSpecΓ]; rfl + simp [Scheme.Opens.toSpecΓ, toSpecΓ_naturality]; rfl + +@[reassoc] +lemma Scheme.Opens.toSpecΓ_appTop {X : Scheme.{u}} (U : X.Opens) : + U.toSpecΓ.appTop = (Scheme.ΓSpecIso Γ(X, U)).hom ≫ U.topIso.inv := by + simp [Scheme.Opens.toSpecΓ] namespace IsAffineOpen @@ -300,8 +315,13 @@ def isoSpec : haveI : IsAffine U := hU U.toScheme.isoSpec ≪≫ Scheme.Spec.mapIso U.topIso.symm.op -lemma isoSpec_hom {X : Scheme.{u}} {U : X.Opens} (hU : IsAffineOpen U) : - hU.isoSpec.hom = U.toSpecΓ := rfl +lemma isoSpec_hom : hU.isoSpec.hom = U.toSpecΓ := rfl + +@[reassoc (attr := simp)] +lemma toSpecΓ_isoSpec_inv : U.toSpecΓ ≫ hU.isoSpec.inv = 𝟙 _ := hU.isoSpec.hom_inv_id + +@[reassoc (attr := simp)] +lemma isoSpec_inv_toSpecΓ : hU.isoSpec.inv ≫ U.toSpecΓ = 𝟙 _ := hU.isoSpec.inv_hom_id open IsLocalRing in lemma isoSpec_hom_base_apply (x : U) : @@ -345,6 +365,9 @@ instance isOpenImmersion_fromSpec : @[reassoc (attr := simp)] lemma isoSpec_inv_ι : hU.isoSpec.inv ≫ U.ι = hU.fromSpec := rfl +@[reassoc (attr := simp)] +lemma toSpecΓ_fromSpec : U.toSpecΓ ≫ hU.fromSpec = U.ι := toSpecΓ_isoSpec_inv_assoc _ _ + @[simp] theorem range_fromSpec : Set.range hU.fromSpec.base = (U : Set X) := by @@ -893,36 +916,136 @@ theorem of_affine_open_cover {X : Scheme} {P : X.affineOpens → Prop} section ZeroLocus -/-- On a locally ringed space `X`, the preimage of the zero locus of the prime spectrum -of `Γ(X, ⊤)` under `toΓSpecFun` agrees with the associated zero locus on `X`. -/ -lemma Scheme.toΓSpec_preimage_zeroLocus_eq {X : Scheme.{u}} (s : Set Γ(X, ⊤)) : +namespace Scheme + +open ConcreteCategory + +variable (X : Scheme.{u}) + +/-- On a scheme `X`, the preimage of the zero locus of the prime spectrum +of `Γ(X, ⊤)` under `X.toSpecΓ : X ⟶ Spec Γ(X, ⊤)` agrees with the associated zero locus on `X`. -/ +lemma toSpecΓ_preimage_zeroLocus (s : Set Γ(X, ⊤)) : X.toSpecΓ.base ⁻¹' PrimeSpectrum.zeroLocus s = X.zeroLocus s := LocallyRingedSpace.toΓSpec_preimage_zeroLocus_eq s -open ConcreteCategory +@[deprecated (since := "2025-01-17")] alias toΓSpec_preimage_zeroLocus_eq := + toSpecΓ_preimage_zeroLocus -/-- If `X` is affine, the image of the zero locus of global sections of `X` under `toΓSpecFun` +/-- If `X` is affine, the image of the zero locus of global sections of `X` under `X.isoSpec` is the zero locus in terms of the prime spectrum of `Γ(X, ⊤)`. -/ -lemma Scheme.toΓSpec_image_zeroLocus_eq_of_isAffine {X : Scheme.{u}} [IsAffine X] +lemma isoSpec_image_zeroLocus [IsAffine X] (s : Set Γ(X, ⊤)) : X.isoSpec.hom.base '' X.zeroLocus s = PrimeSpectrum.zeroLocus s := by - erw [← X.toΓSpec_preimage_zeroLocus_eq, Set.image_preimage_eq] + erw [← X.toSpecΓ_preimage_zeroLocus, Set.image_preimage_eq] exact (bijective_of_isIso X.isoSpec.hom.base).surjective +lemma toSpecΓ_image_zeroLocus [IsAffine X] (s : Set Γ(X, ⊤)) : + X.toSpecΓ.base '' X.zeroLocus s = PrimeSpectrum.zeroLocus s := + X.isoSpec_image_zeroLocus _ + +lemma isoSpec_inv_preimage_zeroLocus [IsAffine X] (s : Set Γ(X, ⊤)) : + X.isoSpec.inv.base ⁻¹' X.zeroLocus s = PrimeSpectrum.zeroLocus s := by + rw [← toSpecΓ_preimage_zeroLocus, ← Set.preimage_comp, ← TopCat.coe_comp, ← Scheme.comp_base, + X.isoSpec_inv_toSpecΓ] + rfl + +lemma isoSpec_inv_image_zeroLocus [IsAffine X] (s : Set Γ(X, ⊤)) : + X.isoSpec.inv.base '' PrimeSpectrum.zeroLocus s = X.zeroLocus s := by + rw [← isoSpec_inv_preimage_zeroLocus, Set.image_preimage_eq] + exact (bijective_of_isIso X.isoSpec.inv.base).surjective + +@[deprecated (since := "2025-01-17")] alias toΓSpec_image_zeroLocus_eq_of_isAffine := + Scheme.isoSpec_image_zeroLocus + /-- If `X` is an affine scheme, every closed set of `X` is the zero locus of a set of global sections. -/ -lemma Scheme.eq_zeroLocus_of_isClosed_of_isAffine (X : Scheme.{u}) [IsAffine X] (s : Set X) : +lemma eq_zeroLocus_of_isClosed_of_isAffine [IsAffine X] (s : Set X) : IsClosed s ↔ ∃ I : Ideal (Γ(X, ⊤)), s = X.zeroLocus (I : Set Γ(X, ⊤)) := by refine ⟨fun hs ↦ ?_, ?_⟩ · let Z : Set (Spec <| Γ(X, ⊤)) := X.toΓSpecFun '' s have hZ : IsClosed Z := (X.isoSpec.hom.homeomorph).isClosedMap _ hs obtain ⟨I, (hI : Z = _)⟩ := (PrimeSpectrum.isClosed_iff_zeroLocus_ideal _).mp hZ use I - simp only [← Scheme.toΓSpec_preimage_zeroLocus_eq, ← hI, Z] + simp only [← Scheme.toSpecΓ_preimage_zeroLocus, ← hI, Z] erw [Set.preimage_image_eq _ (bijective_of_isIso X.isoSpec.hom.base).injective] · rintro ⟨I, rfl⟩ exact zeroLocus_isClosed X I.carrier +open Set.Notation in +lemma Opens.toSpecΓ_preimage_zeroLocus {X : Scheme.{u}} (U : X.Opens) + (s : Set Γ(X, U)) : + U.toSpecΓ.base ⁻¹' PrimeSpectrum.zeroLocus s = U.1 ↓∩ X.zeroLocus s := by + rw [toSpecΓ, Scheme.comp_base, TopCat.coe_comp, Set.preimage_comp, Spec.map_base] + erw [PrimeSpectrum.preimage_comap_zeroLocus] + rw [Scheme.toSpecΓ_preimage_zeroLocus] + show _ = U.ι.base ⁻¹' (X.zeroLocus s) + rw [Scheme.preimage_zeroLocus, U.ι_app_self, ← zeroLocus_map_of_eq _ U.ι_preimage_self, + ← Set.image_comp, ← RingHom.coe_comp, ← CommRingCat.hom_comp] + congr! + simp [← Functor.map_comp] + rfl + +end Scheme + +lemma IsAffineOpen.fromSpec_preimage_zeroLocus {X : Scheme.{u}} {U : X.Opens} + (hU : IsAffineOpen U) (s : Set Γ(X, U)) : + hU.fromSpec.base ⁻¹' X.zeroLocus s = PrimeSpectrum.zeroLocus s := by + ext x + suffices (∀ f ∈ s, ¬¬ f ∈ x.asIdeal) ↔ s ⊆ x.asIdeal by + simpa [← hU.fromSpec_image_basicOpen, -not_not] using this + simp_rw [not_not] + rfl + +lemma IsAffineOpen.fromSpec_image_zeroLocus {X : Scheme.{u}} {U : X.Opens} + (hU : IsAffineOpen U) (s : Set Γ(X, U)) : + hU.fromSpec.base '' PrimeSpectrum.zeroLocus s = X.zeroLocus s ∩ U := by + rw [← hU.fromSpec_preimage_zeroLocus, Set.image_preimage_eq_inter_range, range_fromSpec] + +open Set.Notation in +lemma Scheme.zeroLocus_inf (X : Scheme.{u}) {U : X.Opens} (I J : Ideal Γ(X, U)) : + X.zeroLocus (U := U) ↑(I ⊓ J) = X.zeroLocus (U := U) I ∪ X.zeroLocus (U := U) J := by + suffices U.1 ↓∩ (X.zeroLocus (U := U) ↑(I ⊓ J)) = + U.1 ↓∩ (X.zeroLocus (U := U) I ∪ X.zeroLocus (U := U) J) by + ext x + by_cases hxU : x ∈ U + · simpa [hxU] using congr(⟨x, hxU⟩ ∈ $this) + · simp only [Submodule.inf_coe, Set.mem_union, + codisjoint_iff_compl_le_left.mp (X.codisjoint_zeroLocus (U := U) (I ∩ J)) hxU, + codisjoint_iff_compl_le_left.mp (X.codisjoint_zeroLocus (U := U) I) hxU, true_or] + simp only [← U.toSpecΓ_preimage_zeroLocus, PrimeSpectrum.zeroLocus_inf I J, + Set.preimage_union] + +lemma Scheme.zeroLocus_biInf + {X : Scheme.{u}} {U : X.Opens} {ι : Type*} + (I : ι → Ideal Γ(X, U)) {t : Set ι} (ht : t.Finite) : + X.zeroLocus (U := U) ↑(⨅ i ∈ t, I i) = (⋃ i ∈ t, X.zeroLocus (U := U) (I i)) ∪ (↑U)ᶜ := by + refine ht.induction_on _ (by simp) fun {i t} hit ht IH ↦ ?_ + simp only [Set.mem_insert_iff, Set.iUnion_iUnion_eq_or_left, ← IH, ← zeroLocus_inf, + Submodule.inf_coe, Set.union_assoc] + congr! + simp + +lemma Scheme.zeroLocus_biInf_of_nonempty + {X : Scheme.{u}} {U : X.Opens} {ι : Type*} + (I : ι → Ideal Γ(X, U)) {t : Set ι} (ht : t.Finite) (ht' : t.Nonempty) : + X.zeroLocus (U := U) ↑(⨅ i ∈ t, I i) = ⋃ i ∈ t, X.zeroLocus (U := U) (I i) := by + rw [zeroLocus_biInf I ht, Set.union_eq_left] + obtain ⟨i, hi⟩ := ht' + exact fun x hx ↦ Set.mem_iUnion₂_of_mem hi + (codisjoint_iff_compl_le_left.mp (X.codisjoint_zeroLocus (U := U) (I i)) hx) + +lemma Scheme.zeroLocus_iInf + {X : Scheme.{u}} {U : X.Opens} {ι : Type*} + (I : ι → Ideal Γ(X, U)) [Finite ι] : + X.zeroLocus (U := U) ↑(⨅ i, I i) = (⋃ i, X.zeroLocus (U := U) (I i)) ∪ (↑U)ᶜ := by + simpa using zeroLocus_biInf I Set.finite_univ + +lemma Scheme.zeroLocus_iInf_of_nonempty + {X : Scheme.{u}} {U : X.Opens} {ι : Type*} + (I : ι → Ideal Γ(X, U)) [Finite ι] [Nonempty ι] : + X.zeroLocus (U := U) ↑(⨅ i, I i) = ⋃ i, X.zeroLocus (U := U) (I i) := by + simpa using zeroLocus_biInf_of_nonempty I Set.finite_univ + end ZeroLocus section Factorization diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index b5c6c59606696..f7d458c2b79a6 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -420,7 +420,7 @@ theorem Scheme.toSpecΓ_base (X : Scheme.{u}) (x) : (Scheme.toSpecΓ X).base x = (Spec.map (X.presheaf.germ ⊤ x trivial)).base (IsLocalRing.closedPoint _) := rfl -@[reassoc (attr := simp)] +@[reassoc] theorem Scheme.toSpecΓ_naturality {X Y : Scheme.{u}} (f : X ⟶ Y) : f ≫ Y.toSpecΓ = X.toSpecΓ ≫ Spec.map (f.appTop) := ΓSpec.adjunction.unit.naturality f diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index 990eb295b3aa0..f78bd0243cceb 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -142,6 +142,11 @@ lemma image_iSup₂ {ι : Sort*} {κ : ι → Sort*} (s : (i : ι) → κ i → ext : 1 simp [Set.image_iUnion₂] +@[simp] +lemma map_mem_image_iff {X Y : Scheme} (f : X ⟶ Y) [IsOpenImmersion f] + {U : X.Opens} {x : X} : f.base x ∈ f ''ᵁ U ↔ x ∈ U := + f.isOpenEmbedding.injective.mem_set_image + /-- The isomorphism `Γ(Y, f(U)) ≅ Γ(X, U)` induced by an open immersion `f : X ⟶ Y`. -/ def appIso (U) : Γ(Y, f ''ᵁ U) ≅ Γ(X, U) := (asIso <| LocallyRingedSpace.IsOpenImmersion.invApp f.toLRSHom U).symm @@ -677,8 +682,9 @@ end MorphismProperty namespace Scheme -theorem image_basicOpen {X Y : Scheme.{u}} (f : X ⟶ Y) [H : IsOpenImmersion f] {U : X.Opens} - (r : Γ(X, U)) : +variable {X Y : Scheme.{u}} (f : X ⟶ Y) [H : IsOpenImmersion f] + +theorem image_basicOpen {U : X.Opens} (r : Γ(X, U)) : f ''ᵁ X.basicOpen r = Y.basicOpen ((f.appIso U).inv r) := by have e := Scheme.preimage_basicOpen f ((f.appIso U).inv r) rw [Scheme.Hom.appIso_inv_app_apply', Scheme.basicOpen_res, inf_eq_right.mpr _] at e @@ -686,6 +692,18 @@ theorem image_basicOpen {X Y : Scheme.{u}} (f : X ⟶ Y) [H : IsOpenImmersion f] refine Set.Subset.trans (Scheme.basicOpen_le _ _) (Set.image_subset_range _ _) · exact (X.basicOpen_le r).trans (f.preimage_image_eq _).ge +lemma image_zeroLocus {U : X.Opens} (s : Set Γ(X, U)) : + f.base '' X.zeroLocus s = + Y.zeroLocus (U := f ''ᵁ U) ((f.appIso U).inv.hom '' s) ∩ Set.range f.base := by + ext x + by_cases hx : x ∈ Set.range f.base + · obtain ⟨x, rfl⟩ := hx + simp only [f.isOpenEmbedding.injective.mem_set_image, Scheme.mem_zeroLocus_iff, + ← SetLike.mem_coe, Set.mem_inter_iff, Set.forall_mem_image, ← Scheme.image_basicOpen, + IsOpenMap.coe_functor_obj, Set.mem_range, exists_apply_eq_apply, and_true] + · simp only [Set.mem_inter_iff, hx, and_false, iff_false] + exact fun H ↦ hx (Set.image_subset_range _ _ H) + end Scheme end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index d0f1ae12a2b67..fdd3809d8e81f 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -577,9 +577,21 @@ theorem basicOpen_mul : X.basicOpen (f * g) = X.basicOpen f ⊓ X.basicOpen g := lemma basicOpen_pow {n : ℕ} (h : 0 < n) : X.basicOpen (f ^ n) = X.basicOpen f := RingedSpace.basicOpen_pow _ _ _ h +lemma basicOpen_add_le : + X.basicOpen (f + g) ≤ X.basicOpen f ⊔ X.basicOpen g := by + intro x hx + have hxU : x ∈ U := X.basicOpen_le _ hx + simp only [SetLike.mem_coe, Scheme.mem_basicOpen _ _ _ hxU, map_add, Opens.coe_sup, + Set.mem_union] at hx ⊢ + exact IsLocalRing.isUnit_or_isUnit_of_isUnit_add hx + theorem basicOpen_of_isUnit {f : Γ(X, U)} (hf : IsUnit f) : X.basicOpen f = U := RingedSpace.basicOpen_of_isUnit _ hf +@[simp] +theorem basicOpen_one : X.basicOpen (1 : Γ(X, U)) = U := + X.basicOpen_of_isUnit isUnit_one + instance algebra_section_section_basicOpen {X : Scheme} {U : X.Opens} (f : Γ(X, U)) : Algebra Γ(X, U) Γ(X, X.basicOpen f) := (X.presheaf.map (homOfLE <| X.basicOpen_le f : _ ⟶ U).op).hom.toAlgebra @@ -618,6 +630,51 @@ lemma mem_zeroLocus_iff {U : X.Opens} (s : Set Γ(X, U)) (x : X) : x ∈ X.zeroLocus s ↔ ∀ f ∈ s, x ∉ X.basicOpen f := X.toRingedSpace.mem_zeroLocus_iff s x +lemma codisjoint_zeroLocus {U : X.Opens} + (s : Set Γ(X, U)) : Codisjoint (X.zeroLocus s) U := by + have (x : X) : ∀ f ∈ s, x ∈ X.basicOpen f → x ∈ U := fun _ _ h ↦ X.basicOpen_le _ h + simpa [codisjoint_iff_le_sup, Set.ext_iff, or_iff_not_imp_left] + +lemma zeroLocus_span {U : X.Opens} (s : Set Γ(X, U)) : + X.zeroLocus (U := U) (Ideal.span s) = X.zeroLocus s := by + ext x + simp only [Scheme.mem_zeroLocus_iff, SetLike.mem_coe] + refine ⟨fun H f hfs ↦ H f (Ideal.subset_span hfs), fun H f ↦ Submodule.span_induction H ?_ ?_ ?_⟩ + · simp only [Scheme.basicOpen_zero]; exact not_false + · exact fun a b _ _ ha hb H ↦ (X.basicOpen_add_le a b H).elim ha hb + · simp +contextual + +lemma zeroLocus_map {U V : X.Opens} (i : U ≤ V) (s : Set Γ(X, V)) : + X.zeroLocus ((X.presheaf.map (homOfLE i).op).hom '' s) = X.zeroLocus s ∪ Uᶜ := by + ext x + suffices (∀ f ∈ s, x ∈ U → x ∉ X.basicOpen f) ↔ x ∈ U → (∀ f ∈ s, x ∉ X.basicOpen f) by + simpa [or_iff_not_imp_right] + conv_lhs => enter [i]; rw [forall_comm (β := x ∈ U)] -- why doesn't simp fire on this + rw [forall_comm (β := x ∈ U)] + +lemma zeroLocus_map_of_eq {U V : X.Opens} (i : U = V) (s : Set Γ(X, V)) : + X.zeroLocus ((X.presheaf.map (eqToHom i).op).hom '' s) = X.zeroLocus s := by + ext; simp + +lemma zeroLocus_mono {U : X.Opens} {s t : Set Γ(X, U)} (h : s ⊆ t) : + X.zeroLocus t ⊆ X.zeroLocus s := by + simp only [Set.subset_def, Scheme.mem_zeroLocus_iff] + exact fun x H f hf hxf ↦ H f (h hf) hxf + +lemma preimage_zeroLocus {X Y : Scheme.{u}} (f : X ⟶ Y) {U : Y.Opens} (s : Set Γ(Y, U)) : + f.base ⁻¹' Y.zeroLocus s = X.zeroLocus ((f.app U).hom '' s) := by + ext + simp [← Scheme.preimage_basicOpen] + rfl + +@[simp] +lemma zeroLocus_univ {U : X.Opens} : + X.zeroLocus (U := U) Set.univ = (↑U)ᶜ := by + ext x + simp only [Scheme.mem_zeroLocus_iff, Set.mem_univ, forall_const, Set.mem_compl_iff, + SetLike.mem_coe, ← not_exists, not_iff_not] + exact ⟨fun ⟨f, hf⟩ ↦ X.basicOpen_le f hf, fun _ ↦ ⟨1, by rwa [X.basicOpen_of_isUnit isUnit_one]⟩⟩ + end ZeroLocus end Scheme @@ -678,6 +735,19 @@ lemma Scheme.iso_inv_base_hom_base_apply {X Y : Scheme.{u}} (e : X ≅ Y) (y : Y show (e.inv.base ≫ e.hom.base) y = 𝟙 Y.toPresheafedSpace y simp +theorem Spec_zeroLocus_eq_zeroLocus {R : CommRingCat} (s : Set R) : + (Spec R).zeroLocus ((Scheme.ΓSpecIso R).inv '' s) = PrimeSpectrum.zeroLocus s := by + ext x + suffices (∀ a ∈ s, x ∉ PrimeSpectrum.basicOpen a) ↔ x ∈ PrimeSpectrum.zeroLocus s by simpa + simp [Spec_carrier, PrimeSpectrum.mem_zeroLocus, Set.subset_def, + PrimeSpectrum.mem_basicOpen _ x] + +@[simp] +theorem Spec_zeroLocus {R : CommRingCat} (s : Set Γ(Spec R, ⊤)) : + (Spec R).zeroLocus s = PrimeSpectrum.zeroLocus ((Scheme.ΓSpecIso R).inv ⁻¹' s) := by + convert Spec_zeroLocus_eq_zeroLocus ((Scheme.ΓSpecIso R).inv ⁻¹' s) + rw [Set.image_preimage_eq] + exact (ConcreteCategory.bijective_of_isIso (C := CommRingCat) _).2 section Stalks namespace Scheme diff --git a/Mathlib/Order/BooleanAlgebra.lean b/Mathlib/Order/BooleanAlgebra.lean index ea8924624d601..e46f2bb3b9b91 100644 --- a/Mathlib/Order/BooleanAlgebra.lean +++ b/Mathlib/Order/BooleanAlgebra.lean @@ -697,6 +697,12 @@ theorem himp_le : x ⇨ y ≤ z ↔ y ≤ z ∧ Codisjoint x z := lemma himp_ne_right : x ⇨ y ≠ x ↔ x ≠ ⊤ ∨ y ≠ ⊤ := himp_eq_left.not.trans not_and_or +lemma codisjoint_iff_compl_le_left : Codisjoint x y ↔ yᶜ ≤ x := + hnot_le_iff_codisjoint_left.symm + +lemma codisjoint_iff_compl_le_right : Codisjoint x y ↔ xᶜ ≤ y := + hnot_le_iff_codisjoint_right.symm + end BooleanAlgebra instance Prop.instBooleanAlgebra : BooleanAlgebra Prop where diff --git a/Mathlib/Topology/Sets/Opens.lean b/Mathlib/Topology/Sets/Opens.lean index bac92aeaffc4e..47ad1534b482b 100644 --- a/Mathlib/Topology/Sets/Opens.lean +++ b/Mathlib/Topology/Sets/Opens.lean @@ -164,6 +164,9 @@ theorem mk_inf_mk {U V : Set α} {hU : IsOpen U} {hV : IsOpen V} : theorem coe_inf (s t : Opens α) : (↑(s ⊓ t) : Set α) = ↑s ∩ ↑t := rfl +@[simp] +lemma mem_inf {s t : Opens α} {x : α} : x ∈ s ⊓ t ↔ x ∈ s ∧ x ∈ t := Iff.rfl + @[simp, norm_cast] theorem coe_sup (s t : Opens α) : (↑(s ⊔ t) : Set α) = ↑s ∪ ↑t := rfl @@ -172,6 +175,9 @@ theorem coe_sup (s t : Opens α) : (↑(s ⊔ t) : Set α) = ↑s ∪ ↑t := theorem coe_bot : ((⊥ : Opens α) : Set α) = ∅ := rfl +@[simp] +lemma mem_bot {x : α} : x ∈ (⊥ : Opens α) ↔ False := Iff.rfl + @[simp] theorem mk_empty : (⟨∅, isOpen_empty⟩ : Opens α) = ⊥ := rfl @[simp, norm_cast] From a7b7802cac360f430a14cb9aaa99d98f1e06cc8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 24 Jan 2025 22:23:20 +0000 Subject: [PATCH 492/681] chore(Pointwise): rename `Set.set_smul_subset_set_smul_iff` to `Set.smul_set_subset_smul_set_iff` (#20300) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves: * `set_smul_subset_set_smul_iff` → `smul_set_subset_smul_set_iff` * `set_smul_subset_iff` → `smul_set_subset_iff_subset_inv_smul_set` * `subset_set_smul_iff` → `subset_smul_set_iff` * `set_smul_subset_set_smul_iff₀` → `smul_set_subset_smul_set_iff₀` * `set_smul_subset_iff₀` → `smul_set_subset_iff₀` * `subset_set_smul_iff₀` → `subset_smul_set_iff₀` From LeanCamCombi --- .../Algebra/Group/Pointwise/Finset/Basic.lean | 4 +-- Mathlib/Algebra/Group/Subgroup/Pointwise.lean | 24 +++++++------- .../Algebra/Group/Submonoid/Pointwise.lean | 24 +++++++------- Mathlib/Algebra/Ring/Subring/Pointwise.lean | 12 +++---- .../Algebra/Ring/Subsemiring/Pointwise.lean | 12 +++---- Mathlib/Analysis/Convex/Normed.lean | 4 +-- .../LocallyConvex/BalancedCoreHull.lean | 2 +- Mathlib/Analysis/Normed/Operator/Compact.lean | 2 +- .../Additive/ApproximateSubgroup.lean | 2 +- Mathlib/Data/Set/Pointwise/Iterate.lean | 2 +- Mathlib/Data/Set/Pointwise/SMul.lean | 33 ++++++++++++++----- Mathlib/GroupTheory/CoprodI.lean | 2 +- Mathlib/GroupTheory/GroupAction/Blocks.lean | 2 +- .../GroupTheory/GroupAction/FixedPoints.lean | 2 +- .../Valuation/ValuationSubring.lean | 6 ++-- 15 files changed, 74 insertions(+), 59 deletions(-) diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean index af7620fdb7069..e1433b9eac116 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean @@ -1689,13 +1689,13 @@ theorem smul_finset_subset_smul_finset_iff : a • s ⊆ a • t ↔ s ⊆ t := theorem smul_finset_subset_iff : a • s ⊆ t ↔ s ⊆ a⁻¹ • t := by simp_rw [← coe_subset] push_cast - exact Set.set_smul_subset_iff + exact Set.smul_set_subset_iff_subset_inv_smul_set @[to_additive] theorem subset_smul_finset_iff : s ⊆ a • t ↔ a⁻¹ • s ⊆ t := by simp_rw [← coe_subset] push_cast - exact Set.subset_set_smul_iff + exact Set.subset_smul_set_iff @[to_additive] theorem smul_finset_inter : a • (s ∩ t) = a • s ∩ a • t := diff --git a/Mathlib/Algebra/Group/Subgroup/Pointwise.lean b/Mathlib/Algebra/Group/Subgroup/Pointwise.lean index 9d32674ef1a3b..b2d5af26623ba 100644 --- a/Mathlib/Algebra/Group/Subgroup/Pointwise.lean +++ b/Mathlib/Algebra/Group/Subgroup/Pointwise.lean @@ -403,13 +403,13 @@ theorem mem_inv_pointwise_smul_iff {a : α} {S : Subgroup G} {x : G} : x ∈ a @[simp] theorem pointwise_smul_le_pointwise_smul_iff {a : α} {S T : Subgroup G} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff + smul_set_subset_smul_set_iff theorem pointwise_smul_subset_iff {a : α} {S T : Subgroup G} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff + smul_set_subset_iff_subset_inv_smul_set theorem subset_pointwise_smul_iff {a : α} {S T : Subgroup G} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff + subset_smul_set_iff @[simp] theorem smul_inf (a : α) (S T : Subgroup G) : a • (S ⊓ T) = a • S ⊓ a • T := by @@ -473,13 +473,13 @@ theorem mem_inv_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) (S : Subgroup G) ( @[simp] theorem pointwise_smul_le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : Subgroup G} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff₀ ha + smul_set_subset_smul_set_iff₀ ha theorem pointwise_smul_le_iff₀ {a : α} (ha : a ≠ 0) {S T : Subgroup G} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff₀ ha + smul_set_subset_iff₀ ha theorem le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : Subgroup G} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff₀ ha + subset_smul_set_iff₀ ha end GroupWithZero @@ -551,13 +551,13 @@ theorem mem_inv_pointwise_smul_iff {a : α} {S : AddSubgroup A} {x : A} : x ∈ @[simp] theorem pointwise_smul_le_pointwise_smul_iff {a : α} {S T : AddSubgroup A} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff + smul_set_subset_smul_set_iff theorem pointwise_smul_le_iff {a : α} {S T : AddSubgroup A} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff + smul_set_subset_iff_subset_inv_smul_set theorem le_pointwise_smul_iff {a : α} {S T : AddSubgroup A} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff + subset_smul_set_iff end Group @@ -583,15 +583,15 @@ theorem mem_inv_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) (S : AddSubgroup A @[simp] theorem pointwise_smul_le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : AddSubgroup A} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff₀ ha + smul_set_subset_smul_set_iff₀ ha theorem pointwise_smul_le_iff₀ {a : α} (ha : a ≠ 0) {S T : AddSubgroup A} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff₀ ha + smul_set_subset_iff₀ ha theorem le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : AddSubgroup A} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff₀ ha + subset_smul_set_iff₀ ha end GroupWithZero diff --git a/Mathlib/Algebra/Group/Submonoid/Pointwise.lean b/Mathlib/Algebra/Group/Submonoid/Pointwise.lean index 567936d4f37ef..f698bdf137947 100644 --- a/Mathlib/Algebra/Group/Submonoid/Pointwise.lean +++ b/Mathlib/Algebra/Group/Submonoid/Pointwise.lean @@ -275,13 +275,13 @@ theorem mem_inv_pointwise_smul_iff {a : α} {S : Submonoid M} {x : M} : x ∈ a @[simp] theorem pointwise_smul_le_pointwise_smul_iff {a : α} {S T : Submonoid M} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff + smul_set_subset_smul_set_iff theorem pointwise_smul_subset_iff {a : α} {S T : Submonoid M} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff + smul_set_subset_iff_subset_inv_smul_set theorem subset_pointwise_smul_iff {a : α} {S T : Submonoid M} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff + subset_smul_set_iff end Group @@ -305,13 +305,13 @@ theorem mem_inv_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) (S : Submonoid M) @[simp] theorem pointwise_smul_le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : Submonoid M} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff₀ ha + smul_set_subset_smul_set_iff₀ ha theorem pointwise_smul_le_iff₀ {a : α} (ha : a ≠ 0) {S T : Submonoid M} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff₀ ha + smul_set_subset_iff₀ ha theorem le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : Submonoid M} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff₀ ha + subset_smul_set_iff₀ ha end GroupWithZero @@ -389,13 +389,13 @@ theorem mem_inv_pointwise_smul_iff {a : α} {S : AddSubmonoid A} {x : A} : x ∈ @[simp] theorem pointwise_smul_le_pointwise_smul_iff {a : α} {S T : AddSubmonoid A} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff + smul_set_subset_smul_set_iff theorem pointwise_smul_le_iff {a : α} {S T : AddSubmonoid A} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff + smul_set_subset_iff_subset_inv_smul_set theorem le_pointwise_smul_iff {a : α} {S T : AddSubmonoid A} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff + subset_smul_set_iff end Group @@ -419,15 +419,15 @@ theorem mem_inv_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) (S : AddSubmonoid @[simp] theorem pointwise_smul_le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : AddSubmonoid A} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff₀ ha + smul_set_subset_smul_set_iff₀ ha theorem pointwise_smul_le_iff₀ {a : α} (ha : a ≠ 0) {S T : AddSubmonoid A} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff₀ ha + smul_set_subset_iff₀ ha theorem le_pointwise_smul_iff₀ {a : α} (ha : a ≠ 0) {S T : AddSubmonoid A} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff₀ ha + subset_smul_set_iff₀ ha end GroupWithZero diff --git a/Mathlib/Algebra/Ring/Subring/Pointwise.lean b/Mathlib/Algebra/Ring/Subring/Pointwise.lean index b472910f34900..da145f5a27b74 100644 --- a/Mathlib/Algebra/Ring/Subring/Pointwise.lean +++ b/Mathlib/Algebra/Ring/Subring/Pointwise.lean @@ -108,13 +108,13 @@ theorem mem_inv_pointwise_smul_iff {a : M} {S : Subring R} {x : R} : x ∈ a⁻ @[simp] theorem pointwise_smul_le_pointwise_smul_iff {a : M} {S T : Subring R} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff + smul_set_subset_smul_set_iff theorem pointwise_smul_subset_iff {a : M} {S T : Subring R} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff + smul_set_subset_iff_subset_inv_smul_set theorem subset_pointwise_smul_iff {a : M} {S T : Subring R} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff + subset_smul_set_iff /-! TODO: add `equivSMul` like we have for subgroup. -/ @@ -143,13 +143,13 @@ theorem mem_inv_pointwise_smul_iff₀ {a : M} (ha : a ≠ 0) (S : Subring R) (x @[simp] theorem pointwise_smul_le_pointwise_smul_iff₀ {a : M} (ha : a ≠ 0) {S T : Subring R} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff₀ ha + smul_set_subset_smul_set_iff₀ ha theorem pointwise_smul_le_iff₀ {a : M} (ha : a ≠ 0) {S T : Subring R} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff₀ ha + smul_set_subset_iff₀ ha theorem le_pointwise_smul_iff₀ {a : M} (ha : a ≠ 0) {S T : Subring R} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff₀ ha + subset_smul_set_iff₀ ha end GroupWithZero diff --git a/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean b/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean index 250d388ca8b0a..4e24ba3121d75 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean @@ -103,13 +103,13 @@ theorem mem_inv_pointwise_smul_iff {a : M} {S : Subsemiring R} {x : R} : x ∈ a @[simp] theorem pointwise_smul_le_pointwise_smul_iff {a : M} {S T : Subsemiring R} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff + smul_set_subset_smul_set_iff theorem pointwise_smul_subset_iff {a : M} {S T : Subsemiring R} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff + smul_set_subset_iff_subset_inv_smul_set theorem subset_pointwise_smul_iff {a : M} {S T : Subsemiring R} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff + subset_smul_set_iff /-! TODO: add `equiv_smul` like we have for subgroup. -/ @@ -138,15 +138,15 @@ theorem mem_inv_pointwise_smul_iff₀ {a : M} (ha : a ≠ 0) (S : Subsemiring R) @[simp] theorem pointwise_smul_le_pointwise_smul_iff₀ {a : M} (ha : a ≠ 0) {S T : Subsemiring R} : a • S ≤ a • T ↔ S ≤ T := - set_smul_subset_set_smul_iff₀ ha + smul_set_subset_smul_set_iff₀ ha theorem pointwise_smul_le_iff₀ {a : M} (ha : a ≠ 0) {S T : Subsemiring R} : a • S ≤ T ↔ S ≤ a⁻¹ • T := - set_smul_subset_iff₀ ha + smul_set_subset_iff₀ ha theorem le_pointwise_smul_iff₀ {a : M} (ha : a ≠ 0) {S T : Subsemiring R} : S ≤ a • T ↔ a⁻¹ • S ≤ T := - subset_set_smul_iff₀ ha + subset_smul_set_iff₀ ha end GroupWithZero diff --git a/Mathlib/Analysis/Convex/Normed.lean b/Mathlib/Analysis/Convex/Normed.lean index 2277ac898fcf3..ee456daba0041 100644 --- a/Mathlib/Analysis/Convex/Normed.lean +++ b/Mathlib/Analysis/Convex/Normed.lean @@ -146,7 +146,7 @@ lemma exists_mem_interior_convexHull_affineBasis (hs : s ∈ 𝓝 x) : wlog hx : x = 0 · obtain ⟨b, hb⟩ := this (s := -x +ᵥ s) (by simpa using vadd_mem_nhds_vadd (-x) hs) rfl use x +ᵥ b - simpa [subset_set_vadd_iff, mem_vadd_set_iff_neg_vadd_mem, convexHull_vadd, interior_vadd, + simpa [subset_vadd_set_iff, mem_vadd_set_iff_neg_vadd_mem, convexHull_vadd, interior_vadd, Pi.vadd_def, -vadd_eq_add, vadd_eq_add (a := -x), ← Set.vadd_set_range] using hb subst hx -- The strategy is now to find an arbitrary maximal spanning simplex (aka an affine basis)... @@ -171,7 +171,7 @@ lemma exists_mem_interior_convexHull_affineBasis (hs : s ∈ 𝓝 x) : set d : AffineBasis (Fin (finrank ℝ E + 1)) ℝ E := Units.mk0 ε' hε'.ne' • c have hε₀ : 0 < ε / 2 := by positivity have hdnorm : (range d : Set E) ⊆ closedBall 0 (ε / 2) := by - simp [d, Set.set_smul_subset_iff₀ hε'.ne', hε₀.le, _root_.smul_closedBall, abs_of_nonneg hε'.le, + simp [d, Set.smul_set_subset_iff₀ hε'.ne', hε₀.le, _root_.smul_closedBall, abs_of_nonneg hε'.le, range_subset_iff, norm_smul] simpa [ε', hε₀.ne', range_subset_iff, ← mul_div_right_comm (ε / 2), div_le_iff₀ hc', mul_le_mul_left hε₀] using hcnorm diff --git a/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean b/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean index bf2b65c776bf0..f1d9d6b5a0bcf 100644 --- a/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean +++ b/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean @@ -196,7 +196,7 @@ theorem subset_balancedCore (ht : (0 : E) ∈ t) (hst : ∀ a : 𝕜, ‖a‖ s ⊆ balancedCore 𝕜 t := by rw [balancedCore_eq_iInter ht] refine subset_iInter₂ fun a ha ↦ ?_ - rw [subset_set_smul_iff₀ (norm_pos_iff.mp <| zero_lt_one.trans_le ha)] + rw [subset_smul_set_iff₀ (norm_pos_iff.mp <| zero_lt_one.trans_le ha)] apply hst rw [norm_inv] exact inv_le_one_of_one_le₀ ha diff --git a/Mathlib/Analysis/Normed/Operator/Compact.lean b/Mathlib/Analysis/Normed/Operator/Compact.lean index da69e15c03410..972e8b93105c1 100644 --- a/Mathlib/Analysis/Normed/Operator/Compact.lean +++ b/Mathlib/Analysis/Normed/Operator/Compact.lean @@ -326,7 +326,7 @@ theorem IsCompactOperator.continuous {f : M₁ →ₛₗ[σ₁₂] M₂} (hf : I have : IsUnit c⁻¹ := hcnz.isUnit.inv rwa [mem_map, preimage_smul_setₛₗ _ _ _ f this, set_smul_mem_nhds_zero_iff (inv_ne_zero hcnz)] -- Since `σ₁₂ c⁻¹` = `(σ₁₂ c)⁻¹`, we have to prove that `K ⊆ σ₁₂ c • U`. - rw [map_inv₀, ← subset_set_smul_iff₀ ((map_ne_zero σ₁₂).mpr hcnz)] + rw [map_inv₀, ← subset_smul_set_iff₀ ((map_ne_zero σ₁₂).mpr hcnz)] -- But `σ₁₂` is isometric, so `‖σ₁₂ c‖ = ‖c‖ > r`, which concludes the argument since -- `∀ a : 𝕜₂, r ≤ ‖a‖ → K ⊆ a • U`. refine hrU (σ₁₂ c) ?_ diff --git a/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean b/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean index 208904c043257..286e7296091b2 100644 --- a/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean +++ b/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean @@ -197,7 +197,7 @@ lemma isApproximateSubgroup_one {A : Set G} : · simp [hA.nonempty.ne_empty] at hKA · rw [Finset.coe_singleton, singleton_smul, sq] at hKA use x - have hx' : x ⁻¹ • (A * A) ⊆ A := by rwa [← subset_set_smul_iff] + have hx' : x ⁻¹ • (A * A) ⊆ A := by rwa [← subset_smul_set_iff] have hx_inv : x⁻¹ ∈ A := by simpa using hx' (smul_mem_smul_set (mul_mem_mul hA.one_mem hA.one_mem)) have hx_sq : x * x ∈ A := by diff --git a/Mathlib/Data/Set/Pointwise/Iterate.lean b/Mathlib/Data/Set/Pointwise/Iterate.lean index 3aa53135e8e06..acffc678dbd7e 100644 --- a/Mathlib/Data/Set/Pointwise/Iterate.lean +++ b/Mathlib/Data/Set/Pointwise/Iterate.lean @@ -32,7 +32,7 @@ theorem smul_eq_self_of_preimage_zpow_eq_self {G : Type*} [CommGroup G] {n : ℤ refine le_antisymm (this hg) ?_ conv_lhs => rw [← smul_inv_smul g s] replace hg : g⁻¹ ^ n ^ j = 1 := by rw [inv_zpow, hg, inv_one] - simpa only [le_eq_subset, set_smul_subset_set_smul_iff] using this hg + simpa only [le_eq_subset, smul_set_subset_smul_set_iff] using this hg rw [(IsFixedPt.preimage_iterate hs j : (zpowGroupHom n)^[j] ⁻¹' s = s).symm] rintro g' hg' - ⟨y, hy, rfl⟩ change (zpowGroupHom n)^[j] (g' * y) ∈ s diff --git a/Mathlib/Data/Set/Pointwise/SMul.lean b/Mathlib/Data/Set/Pointwise/SMul.lean index 84372884b6f19..343a74fb58eb3 100644 --- a/Mathlib/Data/Set/Pointwise/SMul.lean +++ b/Mathlib/Data/Set/Pointwise/SMul.lean @@ -330,20 +330,28 @@ theorem preimage_smul_inv (a : α) (t : Set β) : (fun x ↦ a⁻¹ • x) ⁻¹ preimage_smul (toUnits a)⁻¹ t @[to_additive (attr := simp)] -theorem set_smul_subset_set_smul_iff : a • A ⊆ a • B ↔ A ⊆ B := +theorem smul_set_subset_smul_set_iff : a • A ⊆ a • B ↔ A ⊆ B := image_subset_image_iff <| MulAction.injective _ +@[deprecated (since := "2024-12-28")] +alias set_smul_subset_set_smul_iff := smul_set_subset_smul_set_iff + @[to_additive] -theorem set_smul_subset_iff : a • A ⊆ B ↔ A ⊆ a⁻¹ • B := +theorem smul_set_subset_iff_subset_inv_smul_set : a • A ⊆ B ↔ A ⊆ a⁻¹ • B := image_subset_iff.trans <| iff_of_eq <| congr_arg _ <| preimage_equiv_eq_image_symm _ <| MulAction.toPerm _ +@[deprecated (since := "2024-12-28")] +alias set_smul_subset_iff := smul_set_subset_iff_subset_inv_smul_set + @[to_additive] -theorem subset_set_smul_iff : A ⊆ a • B ↔ a⁻¹ • A ⊆ B := +theorem subset_smul_set_iff : A ⊆ a • B ↔ a⁻¹ • A ⊆ B := Iff.symm <| image_subset_iff.trans <| Iff.symm <| iff_of_eq <| congr_arg _ <| image_equiv_eq_preimage_symm _ <| MulAction.toPerm _ +@[deprecated (since := "2024-12-28")] alias subset_set_smul_iff := subset_smul_set_iff + @[to_additive] theorem smul_set_inter : a • (s ∩ t) = a • s ∩ a • t := image_inter <| MulAction.injective a @@ -515,14 +523,21 @@ theorem preimage_smul_inv₀ (ha : a ≠ 0) (t : Set β) : (fun x ↦ a⁻¹ • preimage_smul (Units.mk0 a ha)⁻¹ t @[simp] -theorem set_smul_subset_set_smul_iff₀ (ha : a ≠ 0) {A B : Set β} : a • A ⊆ a • B ↔ A ⊆ B := - show Units.mk0 a ha • _ ⊆ _ ↔ _ from set_smul_subset_set_smul_iff +theorem smul_set_subset_smul_set_iff₀ (ha : a ≠ 0) {A B : Set β} : a • A ⊆ a • B ↔ A ⊆ B := + show Units.mk0 a ha • _ ⊆ _ ↔ _ from smul_set_subset_smul_set_iff + +@[deprecated (since := "2024-12-28")] +alias set_smul_subset_set_smul_iff₀ := smul_set_subset_smul_set_iff₀ + +theorem smul_set_subset_iff₀ (ha : a ≠ 0) {A B : Set β} : a • A ⊆ B ↔ A ⊆ a⁻¹ • B := + show Units.mk0 a ha • _ ⊆ _ ↔ _ from smul_set_subset_iff_subset_inv_smul_set + +@[deprecated (since := "2024-12-28")] alias set_smul_subset_iff₀ := smul_set_subset_iff₀ -theorem set_smul_subset_iff₀ (ha : a ≠ 0) {A B : Set β} : a • A ⊆ B ↔ A ⊆ a⁻¹ • B := - show Units.mk0 a ha • _ ⊆ _ ↔ _ from set_smul_subset_iff +theorem subset_smul_set_iff₀ (ha : a ≠ 0) {A B : Set β} : A ⊆ a • B ↔ a⁻¹ • A ⊆ B := + show _ ⊆ Units.mk0 a ha • _ ↔ _ from subset_smul_set_iff -theorem subset_set_smul_iff₀ (ha : a ≠ 0) {A B : Set β} : A ⊆ a • B ↔ a⁻¹ • A ⊆ B := - show _ ⊆ Units.mk0 a ha • _ ↔ _ from subset_set_smul_iff +@[deprecated (since := "2024-12-28")] alias subset_set_smul_iff₀ := subset_smul_set_iff₀ theorem smul_set_inter₀ (ha : a ≠ 0) : a • (s ∩ t) = a • s ∩ a • t := show Units.mk0 a ha • _ = _ from smul_set_inter diff --git a/Mathlib/GroupTheory/CoprodI.lean b/Mathlib/GroupTheory/CoprodI.lean index 20c498af25ecf..a67918662b655 100644 --- a/Mathlib/GroupTheory/CoprodI.lean +++ b/Mathlib/GroupTheory/CoprodI.lean @@ -835,7 +835,7 @@ theorem lift_word_ping_pong {i j k} (w : NeWord H i j) (hk : j ≠ k) : · calc lift f (NeWord.append w₁ hne w₂).prod • X k = lift f w₁.prod • lift f w₂.prod • X k := by simp [MulAction.mul_smul] - _ ⊆ lift f w₁.prod • X _ := set_smul_subset_set_smul_iff.mpr (hIw₂ hk) + _ ⊆ lift f w₁.prod • X _ := smul_set_subset_smul_set_iff.mpr (hIw₂ hk) _ ⊆ X i := hIw₁ hne include hXnonempty hXdisj diff --git a/Mathlib/GroupTheory/GroupAction/Blocks.lean b/Mathlib/GroupTheory/GroupAction/Blocks.lean index 5655e4bb9cc96..7bc87f229f0a2 100644 --- a/Mathlib/GroupTheory/GroupAction/Blocks.lean +++ b/Mathlib/GroupTheory/GroupAction/Blocks.lean @@ -229,7 +229,7 @@ lemma IsBlock.subgroup {H : Subgroup G} (hB : IsBlock G B) : IsBlock H B := fun /-- A block of a group action is invariant iff it is fixed. -/ @[to_additive "A block of a group action is invariant iff it is fixed."] lemma isInvariantBlock_iff_isFixedBlock : IsInvariantBlock G B ↔ IsFixedBlock G B := - ⟨fun hB g ↦ (hB g).antisymm <| subset_set_smul_iff.2 <| hB _, IsFixedBlock.isInvariantBlock⟩ + ⟨fun hB g ↦ (hB g).antisymm <| subset_smul_set_iff.2 <| hB _, IsFixedBlock.isInvariantBlock⟩ /-- An invariant block of a group action is a fixed block. -/ @[to_additive "An invariant block of a group action is a fixed block."] diff --git a/Mathlib/GroupTheory/GroupAction/FixedPoints.lean b/Mathlib/GroupTheory/GroupAction/FixedPoints.lean index ec44881e43a15..2a40a937b2799 100644 --- a/Mathlib/GroupTheory/GroupAction/FixedPoints.lean +++ b/Mathlib/GroupTheory/GroupAction/FixedPoints.lean @@ -149,7 +149,7 @@ theorem set_mem_fixedBy_of_subset_fixedBy {s : Set α} {g : G} (s_ss_fixedBy : s theorem smul_subset_of_set_mem_fixedBy {s t : Set α} {g : G} (t_ss_s : t ⊆ s) (s_in_fixedBy : s ∈ fixedBy (Set α) g) : g • t ⊆ s := - (Set.set_smul_subset_set_smul_iff.mpr t_ss_s).trans s_in_fixedBy.subset + (Set.smul_set_subset_smul_set_iff.mpr t_ss_s).trans s_in_fixedBy.subset /-! If a set `s : Set α` is a superset of `(MulAction.fixedBy α g)ᶜ` (resp. `(AddAction.fixedBy α g)ᶜ`), diff --git a/Mathlib/RingTheory/Valuation/ValuationSubring.lean b/Mathlib/RingTheory/Valuation/ValuationSubring.lean index d1f3ec7693c78..bf3b19d8bb5aa 100644 --- a/Mathlib/RingTheory/Valuation/ValuationSubring.lean +++ b/Mathlib/RingTheory/Valuation/ValuationSubring.lean @@ -754,13 +754,13 @@ theorem mem_inv_pointwise_smul_iff {g : G} {S : ValuationSubring K} {x : K} : @[simp] theorem pointwise_smul_le_pointwise_smul_iff {g : G} {S T : ValuationSubring K} : - g • S ≤ g • T ↔ S ≤ T := Set.set_smul_subset_set_smul_iff + g • S ≤ g • T ↔ S ≤ T := Set.smul_set_subset_smul_set_iff theorem pointwise_smul_subset_iff {g : G} {S T : ValuationSubring K} : g • S ≤ T ↔ S ≤ g⁻¹ • T := - Set.set_smul_subset_iff + Set.smul_set_subset_iff_subset_inv_smul_set theorem subset_pointwise_smul_iff {g : G} {S T : ValuationSubring K} : S ≤ g • T ↔ g⁻¹ • S ≤ T := - Set.subset_set_smul_iff + Set.subset_smul_set_iff end PointwiseActions From fb8b7ee74e32f1ece9601ed397153089bcadb2c1 Mon Sep 17 00:00:00 2001 From: damiano Date: Fri, 24 Jan 2025 22:23:21 +0000 Subject: [PATCH 493/681] chore(noshake): ignoreImport `FastInstance` (#21034) This should be a way to get `shake` to ignore `FastInstance` imports programmatically. --- scripts/noshake.json | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/noshake.json b/scripts/noshake.json index aa972bb4b8568..5a6590b022253 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -96,6 +96,7 @@ "Mathlib.Tactic.ExtractGoal", "Mathlib.Tactic.FBinop", "Mathlib.Tactic.FailIfNoProgress", + "Mathlib.Tactic.FastInstance", "Mathlib.Tactic.FieldSimp", "Mathlib.Tactic.FinCases", "Mathlib.Tactic.Find", @@ -367,7 +368,6 @@ "Mathlib.Lean.Expr.ExtraRecognizers": ["Mathlib.Data.Set.Operations"], "Mathlib.Lean.Expr.Basic": ["Batteries.Logic"], "Mathlib.GroupTheory.MonoidLocalization.Basic": ["Mathlib.Init.Data.Prod"], - "Mathlib.GroupTheory.Congruence.Defs": ["Mathlib.Tactic.FastInstance"], "Mathlib.Geometry.Manifold.Sheaf.Smooth": ["Mathlib.CategoryTheory.Sites.Whiskering"], "Mathlib.Geometry.Manifold.PoincareConjecture": @@ -402,7 +402,6 @@ ["Mathlib.Order.ConditionallyCompleteLattice.Basic"], "Mathlib.Data.FunLike.Basic": ["Mathlib.Logic.Function.Basic"], "Mathlib.Data.Finsupp.Notation": ["Mathlib.Data.Finsupp.Single"], - "Mathlib.Data.Finsupp.Defs": ["Mathlib.Tactic.FastInstance"], "Mathlib.Data.Finset.Insert": ["Mathlib.Data.Finset.Attr"], "Mathlib.Data.ENat.Lattice": ["Mathlib.Algebra.Group.Action.Defs"], "Mathlib.Data.ByteArray": ["Batteries.Data.ByteSubarray"], @@ -451,15 +450,10 @@ "Mathlib.Algebra.Ring.CentroidHom": ["Mathlib.Algebra.Algebra.Defs"], "Mathlib.Algebra.Order.Ring.Nat": ["Mathlib.Algebra.Order.Group.Nat"], "Mathlib.Algebra.Order.Quantale": ["Mathlib.Tactic.Variable"], - "Mathlib.Algebra.Order.Positive.Ring": ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Order.Pi": ["Mathlib.Algebra.ZeroOne.Lemmas"], - "Mathlib.Algebra.Order.Nonneg.Ring": ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Order.Nonneg.Field": ["Mathlib.Algebra.Order.Field.InjSurj"], - "Mathlib.Algebra.Order.Interval.Set.Instances": - ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Order.Field.Subfield": ["Mathlib.Algebra.Order.Field.InjSurj"], - "Mathlib.Algebra.Order.CauSeq.Completion": ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Order.CauSeq.Basic": ["Mathlib.Data.Setoid.Basic"], "Mathlib.Algebra.MonoidAlgebra.Basic": ["Mathlib.LinearAlgebra.Finsupp.SumProd"], @@ -474,7 +468,6 @@ "Mathlib.Algebra.Homology.ModuleCat": ["Mathlib.Algebra.Homology.Homotopy"], "Mathlib.Algebra.Group.Units.Basic": ["Mathlib.Tactic.Subsingleton"], "Mathlib.Algebra.Group.Units": ["Mathlib.Tactic.Subsingleton"], - "Mathlib.Algebra.Group.Subsemigroup.Defs": ["Mathlib.Tactic.FastInstance"], "Mathlib.Algebra.Group.Pi.Basic": ["Batteries.Tactic.Classical"], "Mathlib.Algebra.Group.Idempotent": ["Mathlib.Data.Subtype"], "Mathlib.Algebra.Group.Defs": ["Mathlib.Tactic.OfNat"], From afdba6f87c03a95d38ff76014b073d15ee62f1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Fri, 24 Jan 2025 22:55:38 +0000 Subject: [PATCH 494/681] refactor: make `LinearOrderedCommMonoidWithZero` extend `OrderBot` (#19193) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the following fails: ```lean import Mathlib variable {α : Type*} [LinearOrderedCommGroupWithZero α] #synth OrderBot α /- failed to synthesize OrderBot α Additional diagnostic information may be available using the `set_option diagnostics true` command. -/ ``` --- .../LinearOrderWithPosMulPosEqZero.lean | 17 +++--- Mathlib/Algebra/Order/Field/Canonical.lean | 8 ++- .../Order/GroupWithZero/Canonical.lean | 32 +++++----- Mathlib/RingTheory/Valuation/Archimedean.lean | 2 + Mathlib/RingTheory/Valuation/Basic.lean | 25 +++++++- .../RingTheory/Valuation/ValuationRing.lean | 58 ++++++++++--------- 6 files changed, 88 insertions(+), 54 deletions(-) diff --git a/Counterexamples/LinearOrderWithPosMulPosEqZero.lean b/Counterexamples/LinearOrderWithPosMulPosEqZero.lean index 3967fef0982e9..a20b56bb93669 100644 --- a/Counterexamples/LinearOrderWithPosMulPosEqZero.lean +++ b/Counterexamples/LinearOrderWithPosMulPosEqZero.lean @@ -68,13 +68,16 @@ instance commMonoid : CommMonoid Foo where mul_comm := by boom mul_assoc := by boom -instance : LinearOrderedCommMonoidWithZero Foo := - { Foo.linearOrder, Foo.commMonoid with - zero := 0 - zero_mul := by boom - mul_zero := by boom - mul_le_mul_left := by rintro ⟨⟩ ⟨⟩ h ⟨⟩ <;> revert h <;> decide - zero_le_one := by decide } +instance : LinearOrderedCommMonoidWithZero Foo where + __ := linearOrder + __ := commMonoid + zero := 0 + zero_mul := by boom + mul_zero := by boom + mul_le_mul_left := by rintro ⟨⟩ ⟨⟩ h ⟨⟩ <;> revert h <;> decide + zero_le_one := by decide + bot := 0 + bot_le := by boom theorem not_mul_pos : ¬∀ {M : Type} [LinearOrderedCommMonoidWithZero M], ∀ a b : M, 0 < a → 0 < b → 0 < a * b := by diff --git a/Mathlib/Algebra/Order/Field/Canonical.lean b/Mathlib/Algebra/Order/Field/Canonical.lean index 512b93cdd1c40..1435a769ed076 100644 --- a/Mathlib/Algebra/Order/Field/Canonical.lean +++ b/Mathlib/Algebra/Order/Field/Canonical.lean @@ -27,9 +27,11 @@ variable {α : Type*} [LinearOrderedSemifield α] [CanonicallyOrderedAdd α] /-- Construct a `LinearOrderedCommGroupWithZero` from a canonically ordered `LinearOrderedSemifield`. -/ abbrev LinearOrderedSemifield.toLinearOrderedCommGroupWithZero : - LinearOrderedCommGroupWithZero α := - { ‹LinearOrderedSemifield α› with - mul_le_mul_left := fun _ _ h _ ↦ mul_le_mul_of_nonneg_left h <| zero_le _ } + LinearOrderedCommGroupWithZero α where + __ := ‹LinearOrderedSemifield α› + bot := 0 + bot_le := zero_le + mul_le_mul_left _ _ h _:= mul_le_mul_of_nonneg_left h <| zero_le _ variable [Sub α] [OrderedSub α] diff --git a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean index 2b1886a061185..5262c6b338451 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean @@ -7,7 +7,6 @@ import Mathlib.Algebra.GroupWithZero.InjSurj import Mathlib.Algebra.GroupWithZero.Units.Equiv import Mathlib.Algebra.GroupWithZero.WithZero import Mathlib.Algebra.Order.AddGroupWithTop -import Mathlib.Algebra.Order.GroupWithZero.Synonym import Mathlib.Algebra.Order.GroupWithZero.Unbundled.Lemmas import Mathlib.Algebra.Order.Monoid.Basic import Mathlib.Algebra.Order.Monoid.OrderDual @@ -31,7 +30,7 @@ variable {α : Type*} /-- A linearly ordered commutative monoid with a zero element. -/ class LinearOrderedCommMonoidWithZero (α : Type*) extends LinearOrderedCommMonoid α, - CommMonoidWithZero α where + CommMonoidWithZero α, OrderBot α where /-- `0 ≤ 1` in any linearly ordered commutative monoid. -/ zero_le_one : (0 : α) ≤ 1 @@ -55,15 +54,17 @@ The following facts are true more generally in a (linearly) ordered commutative -/ /-- Pullback a `LinearOrderedCommMonoidWithZero` under an injective map. See note [reducible non-instances]. -/ -abbrev Function.Injective.linearOrderedCommMonoidWithZero {β : Type*} [Zero β] [One β] [Mul β] - [Pow β ℕ] [Max β] [Min β] (f : β → α) (hf : Function.Injective f) (zero : f 0 = 0) +abbrev Function.Injective.linearOrderedCommMonoidWithZero {β : Type*} [Zero β] [Bot β] [One β] + [Mul β] [Pow β ℕ] [Max β] [Min β] (f : β → α) (hf : Function.Injective f) (zero : f 0 = 0) (one : f 1 = 1) (mul : ∀ x y, f (x * y) = f x * f y) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) - (hsup : ∀ x y, f (x ⊔ y) = max (f x) (f y)) (hinf : ∀ x y, f (x ⊓ y) = min (f x) (f y)) : - LinearOrderedCommMonoidWithZero β := - { LinearOrder.lift f hf hsup hinf, hf.orderedCommMonoid f one mul npow, - hf.commMonoidWithZero f zero one mul npow with - zero_le_one := - show f 0 ≤ f 1 by simp only [zero, one, LinearOrderedCommMonoidWithZero.zero_le_one] } + (hsup : ∀ x y, f (x ⊔ y) = max (f x) (f y)) (hinf : ∀ x y, f (x ⊓ y) = min (f x) (f y)) + (bot : f ⊥ = ⊥) : LinearOrderedCommMonoidWithZero β where + __ := LinearOrder.lift f hf hsup hinf + __ := hf.orderedCommMonoid f one mul npow + __ := hf.commMonoidWithZero f zero one mul npow + zero_le_one := + show f 0 ≤ f 1 by simp only [zero, one, LinearOrderedCommMonoidWithZero.zero_le_one] + bot_le a := show f ⊥ ≤ f a from bot ▸ bot_le @[simp] lemma zero_le' : 0 ≤ a := by simpa only [mul_zero, mul_one] using mul_le_mul_left' (zero_le_one' α) a @@ -81,15 +82,18 @@ theorem zero_lt_iff : 0 < a ↔ a ≠ 0 := theorem ne_zero_of_lt (h : b < a) : a ≠ 0 := fun h1 ↦ not_lt_zero' <| show b < 0 from h1 ▸ h +/-- See also `bot_eq_zero` and `bot_eq_zero'` for canonically ordered monoids. -/ +lemma bot_eq_zero'' : (⊥ : α) = 0 := eq_of_forall_ge_iff fun _ ↦ by simp + instance instLinearOrderedAddCommMonoidWithTopAdditiveOrderDual : LinearOrderedAddCommMonoidWithTop (Additive αᵒᵈ) where - top := (0 : α) - top_add' := fun a ↦ zero_mul a.toMul - le_top := fun _ ↦ zero_le' + top := .ofMul <| .toDual 0 + top_add' a := zero_mul a.toMul.ofDual + le_top _ := zero_le' instance instLinearOrderedAddCommMonoidWithTopOrderDualAdditive : LinearOrderedAddCommMonoidWithTop (Additive α)ᵒᵈ where - top := OrderDual.toDual (Additive.ofMul 0) + top := .toDual <| .ofMul _ top_add' := fun a ↦ zero_mul (Additive.toMul (OrderDual.ofDual a)) le_top := fun a ↦ @zero_le' _ _ (Additive.toMul (OrderDual.ofDual a)) diff --git a/Mathlib/RingTheory/Valuation/Archimedean.lean b/Mathlib/RingTheory/Valuation/Archimedean.lean index 2f6d1e71bf789..42b7d56d295ea 100644 --- a/Mathlib/RingTheory/Valuation/Archimedean.lean +++ b/Mathlib/RingTheory/Valuation/Archimedean.lean @@ -24,6 +24,8 @@ variable {F Γ₀ O : Type*} [Field F] [LinearOrderedCommGroupWithZero Γ₀] instance : LinearOrderedCommGroupWithZero (MonoidHom.mrange v) where __ : CommGroupWithZero (MonoidHom.mrange v) := inferInstance __ : LinearOrder (MonoidHom.mrange v) := inferInstance + bot := 0 + bot_le a := show (0 : Γ₀) ≤ _ from zero_le' zero_le_one := Subtype.coe_le_coe.mp zero_le_one mul_le_mul_left := by simp only [Subtype.forall, MonoidHom.mem_mrange, forall_exists_index, Submonoid.mk_mul_mk, diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index e89be5718406d..2d1fe63a3a6d8 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Buzzard, Johan Commelin, Patrick Massot -/ +import Mathlib.Algebra.Order.Hom.Monoid import Mathlib.Algebra.Order.Ring.Basic import Mathlib.RingTheory.Ideal.Maps import Mathlib.Tactic.TFAE @@ -252,6 +253,14 @@ lemma map_apply (f : Γ₀ →*₀ Γ'₀) (hf : Monotone f) (v : Valuation R Γ def IsEquiv (v₁ : Valuation R Γ₀) (v₂ : Valuation R Γ'₀) : Prop := ∀ r s, v₁ r ≤ v₁ s ↔ v₂ r ≤ v₂ s +/-- An ordered monoid isomorphism `Γ₀ ≃ Γ'₀` induces an equivalence +`Valuation R Γ₀ ≃ Valuation R Γ'₀`. -/ +def congr (f : Γ₀ ≃*o Γ'₀) : Valuation R Γ₀ ≃ Valuation R Γ'₀ where + toFun := map f f.toOrderIso.monotone + invFun := map f.symm f.toOrderIso.symm.monotone + left_inv ν := by ext; simp + right_inv ν := by ext; simp + end Monoid section Group @@ -896,12 +905,24 @@ variable {K Γ₀ : Type*} [Ring R] [LinearOrderedCommMonoidWithZero Γ₀] /-- The `AddValuation` associated to a `Valuation`. -/ def toAddValuation : Valuation R Γ₀ ≃ AddValuation R (Additive Γ₀)ᵒᵈ := - AddValuation.ofValuation (R := R) (Γ₀ := (Additive Γ₀)ᵒᵈ) + .trans (congr + { toFun := fun x ↦ .ofAdd <| .toDual <| .toDual <| .ofMul x + invFun := fun x ↦ x.toAdd.ofDual.ofDual.toMul + left_inv := fun _x ↦ rfl + right_inv := fun _x ↦ rfl + map_mul' := fun _x _y ↦ rfl + map_le_map_iff' := .rfl }) (AddValuation.ofValuation (R := R) (Γ₀ := (Additive Γ₀)ᵒᵈ)) /-- The `Valuation` associated to a `AddValuation`. -/ def ofAddValuation : AddValuation R (Additive Γ₀)ᵒᵈ ≃ Valuation R Γ₀ := - AddValuation.toValuation + AddValuation.toValuation.trans <| congr <| + { toFun := fun x ↦ x.toAdd.ofDual.ofDual.toMul + invFun := fun x ↦ .ofAdd <| .toDual <| .toDual <| .ofMul x + left_inv := fun _x ↦ rfl + right_inv := fun _x ↦ rfl + map_mul' := fun _x _y ↦ rfl + map_le_map_iff' := .rfl } @[simp] lemma ofAddValuation_symm_eq : ofAddValuation.symm = toAddValuation (R := R) (Γ₀ := Γ₀) := rfl diff --git a/Mathlib/RingTheory/Valuation/ValuationRing.lean b/Mathlib/RingTheory/Valuation/ValuationRing.lean index d0ff48e43af4d..65e0b27c7dd14 100644 --- a/Mathlib/RingTheory/Valuation/ValuationRing.lean +++ b/Mathlib/RingTheory/Valuation/ValuationRing.lean @@ -155,34 +155,36 @@ noncomputable instance linearOrder : LinearOrder (ValueGroup A K) where decidableLE := by classical infer_instance noncomputable instance linearOrderedCommGroupWithZero : - LinearOrderedCommGroupWithZero (ValueGroup A K) := - { linearOrder .. with - mul_assoc := by rintro ⟨a⟩ ⟨b⟩ ⟨c⟩; apply Quotient.sound'; rw [mul_assoc] - one_mul := by rintro ⟨a⟩; apply Quotient.sound'; rw [one_mul] - mul_one := by rintro ⟨a⟩; apply Quotient.sound'; rw [mul_one] - mul_comm := by rintro ⟨a⟩ ⟨b⟩; apply Quotient.sound'; rw [mul_comm] - mul_le_mul_left := by - rintro ⟨a⟩ ⟨b⟩ ⟨c, rfl⟩ ⟨d⟩ - use c; simp only [Algebra.smul_def]; ring - zero_mul := by rintro ⟨a⟩; apply Quotient.sound'; rw [zero_mul] - mul_zero := by rintro ⟨a⟩; apply Quotient.sound'; rw [mul_zero] - zero_le_one := ⟨0, by rw [zero_smul]⟩ - exists_pair_ne := by - use 0, 1 - intro c; obtain ⟨d, hd⟩ := Quotient.exact' c - apply_fun fun t => d⁻¹ • t at hd - simp only [inv_smul_smul, smul_zero, one_ne_zero] at hd - inv_zero := by apply Quotient.sound'; rw [inv_zero] - mul_inv_cancel := by - rintro ⟨a⟩ ha - apply Quotient.sound' - use 1 - simp only [one_smul, ne_eq] - apply (mul_inv_cancel₀ _).symm - contrapose ha - simp only [Classical.not_not] at ha ⊢ - rw [ha] - rfl } + LinearOrderedCommGroupWithZero (ValueGroup A K) where + __ := linearOrder .. + mul_assoc := by rintro ⟨a⟩ ⟨b⟩ ⟨c⟩; apply Quotient.sound'; rw [mul_assoc] + one_mul := by rintro ⟨a⟩; apply Quotient.sound'; rw [one_mul] + mul_one := by rintro ⟨a⟩; apply Quotient.sound'; rw [mul_one] + mul_comm := by rintro ⟨a⟩ ⟨b⟩; apply Quotient.sound'; rw [mul_comm] + mul_le_mul_left := by + rintro ⟨a⟩ ⟨b⟩ ⟨c, rfl⟩ ⟨d⟩ + use c; simp only [Algebra.smul_def]; ring + zero_mul := by rintro ⟨a⟩; apply Quotient.sound'; rw [zero_mul] + mul_zero := by rintro ⟨a⟩; apply Quotient.sound'; rw [mul_zero] + zero_le_one := ⟨0, by rw [zero_smul]⟩ + exists_pair_ne := by + use 0, 1 + intro c; obtain ⟨d, hd⟩ := Quotient.exact' c + apply_fun fun t => d⁻¹ • t at hd + simp only [inv_smul_smul, smul_zero, one_ne_zero] at hd + inv_zero := by apply Quotient.sound'; rw [inv_zero] + mul_inv_cancel := by + rintro ⟨a⟩ ha + apply Quotient.sound' + use 1 + simp only [one_smul, ne_eq] + apply (mul_inv_cancel₀ _).symm + contrapose ha + simp only [Classical.not_not] at ha ⊢ + rw [ha] + rfl + bot := 0 + bot_le := by rintro ⟨a⟩; exact ⟨0, zero_smul ..⟩ /-- Any valuation ring induces a valuation on its fraction field. -/ def valuation : Valuation K (ValueGroup A K) where From 8f355f5e88923a65fc6ea15daa7f110406ed00ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Fri, 24 Jan 2025 22:55:39 +0000 Subject: [PATCH 495/681] chore(SetTheory/Cardinal/Arithmetic): remove unneeded import (#21013) --- Mathlib/Order/Filter/CardinalInter.lean | 2 +- Mathlib/SetTheory/Cardinal/Arithmetic.lean | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Mathlib/Order/Filter/CardinalInter.lean b/Mathlib/Order/Filter/CardinalInter.lean index 9a1e5bb744169..50c3f20937b94 100644 --- a/Mathlib/Order/Filter/CardinalInter.lean +++ b/Mathlib/Order/Filter/CardinalInter.lean @@ -6,8 +6,8 @@ Authors: Josha Dekker import Mathlib.Order.Filter.Tendsto import Mathlib.Order.Filter.Finite import Mathlib.Order.Filter.CountableInter -import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.SetTheory.Cardinal.Cofinality +import Mathlib.Tactic.Linarith /-! # Filters with a cardinal intersection property diff --git a/Mathlib/SetTheory/Cardinal/Arithmetic.lean b/Mathlib/SetTheory/Cardinal/Arithmetic.lean index b3bf57c0f1e5a..089e73efbad75 100644 --- a/Mathlib/SetTheory/Cardinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Cardinal/Arithmetic.lean @@ -5,7 +5,6 @@ Authors: Johannes Hölzl, Mario Carneiro, Floris van Doorn -/ import Mathlib.SetTheory.Cardinal.Aleph import Mathlib.SetTheory.Ordinal.Principal -import Mathlib.Tactic.Linarith /-! # Cardinal arithmetic @@ -220,7 +219,7 @@ theorem mul_eq_left_iff {a b : Cardinal} : a * b = a ↔ max ℵ₀ b ≤ a ∧ rw [← not_lt] apply fun h2b => ne_of_gt _ h conv_rhs => left; rw [← mul_one n] - rw [mul_lt_mul_left] + rw [Nat.mul_lt_mul_left] · exact id apply Nat.lt_of_succ_le h2a · rintro (⟨⟨ha, hab⟩, hb⟩ | rfl | rfl) From 3726d94334efd87237a3a24673f6fbfac4a303a4 Mon Sep 17 00:00:00 2001 From: grunweg Date: Sat, 25 Jan 2025 00:59:55 +0000 Subject: [PATCH 496/681] chore: ensure `inherit_doc`-ed notation is mentioned in the underlying doc-string (#20684) This is not exhaustive. Add some `inherit_doc` when appropriate. Co-authored-by: grunweg --- Counterexamples/SorgenfreyLine.lean | 3 ++- Mathlib/Algebra/AddConstMap/Basic.lean | 3 ++- Mathlib/Algebra/AddConstMap/Equiv.lean | 3 ++- Mathlib/Algebra/Algebra/Equiv.lean | 3 ++- Mathlib/Algebra/Algebra/Hom.lean | 2 +- Mathlib/Algebra/Algebra/NonUnitalHom.lean | 6 ++++-- Mathlib/Algebra/Group/Operations.lean | 2 +- Mathlib/Algebra/Group/Units/Defs.lean | 2 +- Mathlib/Algebra/Lie/Basic.lean | 18 ++++++++++-------- Mathlib/Algebra/Module/Equiv/Defs.lean | 6 +++--- Mathlib/Algebra/Module/Torsion.lean | 2 +- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 2 +- Mathlib/Algebra/Order/Floor.lean | 2 +- Mathlib/Algebra/Order/Group/Unbundled/Abs.lean | 5 +++-- Mathlib/Algebra/Order/Hom/Ring.lean | 6 ++++-- Mathlib/Algebra/Polynomial/Basic.lean | 3 ++- Mathlib/Algebra/Polynomial/Div.lean | 4 ++-- Mathlib/Algebra/Quaternion.lean | 7 ++++--- Mathlib/Algebra/Quotient.lean | 2 +- Mathlib/Algebra/Symmetrized.lean | 4 ++-- .../Asymptotics/AsymptoticEquivalent.lean | 5 +++-- .../Analysis/CStarAlgebra/Module/Synonym.lean | 4 ++-- Mathlib/Analysis/Calculus/Gradient/Basic.lean | 1 + Mathlib/Analysis/Complex/UnitDisc/Basic.lean | 2 +- .../Analysis/Complex/UpperHalfPlane/Basic.lean | 2 +- Mathlib/Analysis/Convex/Segment.lean | 3 ++- Mathlib/Analysis/Fourier/FourierTransform.lean | 9 ++++++--- Mathlib/Analysis/Fourier/ZMod.lean | 2 +- .../Analysis/InnerProductSpace/Adjoint.lean | 4 +++- Mathlib/Analysis/InnerProductSpace/Defs.lean | 5 +++++ .../Analysis/InnerProductSpace/LinearPMap.lean | 3 ++- .../Analysis/InnerProductSpace/Orthogonal.lean | 6 +++--- Mathlib/Analysis/Normed/Affine/Isometry.lean | 5 +++-- Mathlib/Analysis/Normed/Lp/lpSpace.lean | 3 ++- .../Normed/Operator/LinearIsometry.lean | 6 ++++-- Mathlib/Analysis/RCLike/Inner.lean | 2 +- .../OrdinaryHypergeometric.lean | 4 ++-- .../SpecialFunctions/Trigonometric/Basic.lean | 4 +++- Mathlib/Data/Matrix/Hadamard.lean | 4 ++-- Mathlib/Data/Matrix/Kronecker.lean | 10 ++++++---- Mathlib/Data/NNReal/Defs.lean | 4 ++-- Mathlib/Geometry/Manifold/ChartedSpace.lean | 4 ++-- Mathlib/Geometry/Manifold/ContMDiffMap.lean | 4 +++- .../Geometry/Manifold/DerivationBundle.lean | 12 +++++++----- Mathlib/Geometry/Manifold/Diffeomorph.lean | 2 +- Mathlib/Geometry/Manifold/IsManifold.lean | 2 +- .../Manifold/VectorBundle/SmoothSection.lean | 3 ++- .../LinearAlgebra/Matrix/SchurComplement.lean | 1 + Mathlib/Logic/Equiv/PartialEquiv.lean | 4 +++- .../MeasureTheory/Integral/CircleIntegral.lean | 3 ++- .../Integral/IntervalAverage.lean | 1 + Mathlib/Topology/Homotopy/HomotopyGroup.lean | 11 +++++++---- Mathlib/Topology/PartialHomeomorph.lean | 3 ++- scripts/nolints.json | 17 ----------------- 54 files changed, 136 insertions(+), 104 deletions(-) diff --git a/Counterexamples/SorgenfreyLine.lean b/Counterexamples/SorgenfreyLine.lean index da5f2a78f9496..496df14aaa0b7 100644 --- a/Counterexamples/SorgenfreyLine.lean +++ b/Counterexamples/SorgenfreyLine.lean @@ -42,7 +42,8 @@ namespace Counterexample noncomputable section -/-- The Sorgenfrey line. It is the real line with the topology space structure generated by +/-- The Sorgenfrey line (denoted as `ℝₗ` within the `SorgenfreyLine` namespace). +It is the real line with the topology space structure generated by half-open intervals `Set.Ico a b`. -/ def SorgenfreyLine : Type := ℝ -- Porting note: was deriving ConditionallyCompleteLinearOrder, LinearOrderedField, Archimedean diff --git a/Mathlib/Algebra/AddConstMap/Basic.lean b/Mathlib/Algebra/AddConstMap/Basic.lean index dc5674fb8f1ef..1f7087d7e049d 100644 --- a/Mathlib/Algebra/AddConstMap/Basic.lean +++ b/Mathlib/Algebra/AddConstMap/Basic.lean @@ -32,7 +32,8 @@ assert_not_exists Finset open Function Set -/-- A bundled map `f : G → H` such that `f (x + a) = f x + b` for all `x`. +/-- A bundled map `f : G → H` such that `f (x + a) = f x + b` for all `x`, +denoted as `f: G →+c[a, b] H`. One can think about `f` as a lift to `G` of a map between two `AddCircle`s. -/ structure AddConstMap (G H : Type*) [Add G] [Add H] (a : G) (b : H) where diff --git a/Mathlib/Algebra/AddConstMap/Equiv.lean b/Mathlib/Algebra/AddConstMap/Equiv.lean index 28779a4f482cc..7c5fbbb2766d2 100644 --- a/Mathlib/Algebra/AddConstMap/Equiv.lean +++ b/Mathlib/Algebra/AddConstMap/Equiv.lean @@ -20,7 +20,8 @@ assert_not_exists Finset open Function open scoped AddConstMap -/-- An equivalence between `G` and `H` conjugating `(· + a)` to `(· + b)`. -/ +/-- An equivalence between `G` and `H` conjugating `(· + a)` to `(· + b)`, +denoted as `G ≃+c[a, b] H`. -/ structure AddConstEquiv (G H : Type*) [Add G] [Add H] (a : G) (b : H) extends G ≃ H, G →+c[a, b] H diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index cd52e4afdabda..9a0fa07bd87e7 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -22,7 +22,8 @@ This file defines bundled isomorphisms of `R`-algebras. universe u v w u₁ v₁ -/-- An equivalence of algebras is an equivalence of rings commuting with the actions of scalars. -/ +/-- An equivalence of algebras (denoted as `A ≃ₐ[R] B`) +is an equivalence of rings commuting with the actions of scalars. -/ structure AlgEquiv (R : Type u) (A : Type v) (B : Type w) [CommSemiring R] [Semiring A] [Semiring B] [Algebra R A] [Algebra R B] extends A ≃ B, A ≃* B, A ≃+ B, A ≃+* B where /-- An equivalence of algebras commutes with the action of scalars. -/ diff --git a/Mathlib/Algebra/Algebra/Hom.lean b/Mathlib/Algebra/Algebra/Hom.lean index 31ac6c747b73f..92862f9a814cd 100644 --- a/Mathlib/Algebra/Algebra/Hom.lean +++ b/Mathlib/Algebra/Algebra/Hom.lean @@ -22,7 +22,7 @@ This file defines bundled homomorphisms of `R`-algebras. universe u v w u₁ v₁ -/-- Defining the homomorphism in the category R-Alg. -/ +/-- Defining the homomorphism in the category R-Alg, denoted `A →ₐ[R] B`. -/ structure AlgHom (R : Type u) (A : Type v) (B : Type w) [CommSemiring R] [Semiring A] [Semiring B] [Algebra R A] [Algebra R B] extends RingHom A B where commutes' : ∀ r : R, toFun (algebraMap R A r) = algebraMap R B r diff --git a/Mathlib/Algebra/Algebra/NonUnitalHom.lean b/Mathlib/Algebra/Algebra/NonUnitalHom.lean index d4e25752e01d4..0563a75d8d15b 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalHom.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalHom.lean @@ -46,8 +46,10 @@ universe u u₁ v w w₁ w₂ w₃ variable {R : Type u} {S : Type u₁} -/-- A morphism respecting addition, multiplication, and scalar multiplication. When these arise from -algebra structures, this is the same as a not-necessarily-unital morphism of algebras. -/ +/-- A morphism respecting addition, multiplication, and scalar multiplication +(denoted as `A →ₛₙₐ[φ] B`, or `A →ₙₐ[R] B` when `φ` is the identity on `R`). +When these arise from algebra structures, this is the same +as a not-necessarily-unital morphism of algebras. -/ structure NonUnitalAlgHom [Monoid R] [Monoid S] (φ : R →* S) (A : Type v) (B : Type w) [NonUnitalNonAssocSemiring A] [DistribMulAction R A] [NonUnitalNonAssocSemiring B] [DistribMulAction S B] extends A →ₑ+[φ] B, A →ₙ* B diff --git a/Mathlib/Algebra/Group/Operations.lean b/Mathlib/Algebra/Group/Operations.lean index 72ef50266f6c9..596f447f86c0e 100644 --- a/Mathlib/Algebra/Group/Operations.lean +++ b/Mathlib/Algebra/Group/Operations.lean @@ -140,7 +140,7 @@ variable {G : Type*} /-- Class of types that have an inversion operation. -/ @[to_additive, notation_class] class Inv (α : Type u) where - /-- Invert an element of α. -/ + /-- Invert an element of α, denoted by `a⁻¹`. -/ inv : α → α @[inherit_doc] diff --git a/Mathlib/Algebra/Group/Units/Defs.lean b/Mathlib/Algebra/Group/Units/Defs.lean index 62cfa10d66c99..4a0c7e074d41d 100644 --- a/Mathlib/Algebra/Group/Units/Defs.lean +++ b/Mathlib/Algebra/Group/Units/Defs.lean @@ -296,7 +296,7 @@ section Monoid variable [Monoid α] {a : α} -/-- Partial division. It is defined when the +/-- Partial division, denoted `a /ₚ u`. It is defined when the second argument is invertible, and unlike the division operator in `DivisionRing` it is not totalized at zero. -/ def divp (a : α) (u : Units α) : α := diff --git a/Mathlib/Algebra/Lie/Basic.lean b/Mathlib/Algebra/Lie/Basic.lean index 9d53a393cf7e3..49a2a97527997 100644 --- a/Mathlib/Algebra/Lie/Basic.lean +++ b/Mathlib/Algebra/Lie/Basic.lean @@ -277,7 +277,8 @@ instance Module.Dual.instLieModule : LieModule R L (M →ₗ[R] R) where end BasicProperties -/-- A morphism of Lie algebras is a linear map respecting the bracket operations. -/ +/-- A morphism of Lie algebras (denoted as `L₁ →ₗ⁅R⁆ L₂`) +is a linear map respecting the bracket operations. -/ structure LieHom (R L L' : Type*) [CommRing R] [LieRing L] [LieAlgebra R L] [LieRing L'] [LieAlgebra R L'] extends L →ₗ[R] L' where /-- A morphism of Lie algebras is compatible with brackets. -/ @@ -470,9 +471,10 @@ theorem LieModule.compLieHom [Module R M] [LieModule R L₂ M] : end ModulePullBack -/-- An equivalence of Lie algebras is a morphism which is also a linear equivalence. We could -instead define an equivalence to be a morphism which is also a (plain) equivalence. However it is -more convenient to define via linear equivalence to get `.toLinearEquiv` for free. -/ +/-- An equivalence of Lie algebras (denoted as `L₁ ≃ₗ⁅R⁆ L₂`) is a morphism +which is also a linear equivalence. +We could instead define an equivalence to be a morphism which is also a (plain) equivalence. +However, it is more convenient to define via linear equivalence to get `.toLinearEquiv` for free. -/ structure LieEquiv (R : Type u) (L : Type v) (L' : Type w) [CommRing R] [LieRing L] [LieAlgebra R L] [LieRing L'] [LieAlgebra R L'] extends L →ₗ⁅R⁆ L' where /-- The inverse function of an equivalence of Lie algebras -/ @@ -642,8 +644,8 @@ variable [AddCommGroup M] [AddCommGroup N] [AddCommGroup P] variable [Module R M] [Module R N] [Module R P] variable [LieRingModule L M] [LieRingModule L N] [LieRingModule L P] -/-- A morphism of Lie algebra modules is a linear map which commutes with the action of the Lie -algebra. -/ +/-- A morphism of Lie algebra modules (denoted as `M →ₗ⁅R,L⁆ N`) is a linear map +which commutes with the action of the Lie algebra. -/ structure LieModuleHom extends M →ₗ[R] N where /-- A module of Lie algebra modules is compatible with the action of the Lie algebra on the modules. -/ @@ -857,8 +859,8 @@ instance : Module R (M →ₗ⁅R,L⁆ N) := end LieModuleHom -/-- An equivalence of Lie algebra modules is a linear equivalence which is also a morphism of -Lie algebra modules. -/ +/-- An equivalence of Lie algebra modules (denoted as `M ≃ₗ⁅R,L⁆ N`) is a linear equivalence +which is also a morphism of Lie algebra modules. -/ structure LieModuleEquiv extends M →ₗ⁅R,L⁆ N where /-- The inverse function of an equivalence of Lie modules -/ invFun : N → M diff --git a/Mathlib/Algebra/Module/Equiv/Defs.lean b/Mathlib/Algebra/Module/Equiv/Defs.lean index 678ac96dd6526..e2acc6cc59c16 100644 --- a/Mathlib/Algebra/Module/Equiv/Defs.lean +++ b/Mathlib/Algebra/Module/Equiv/Defs.lean @@ -66,11 +66,11 @@ add_decl_doc LinearEquiv.right_inv /-- `LinearEquiv.invFun` is a left inverse to the linear equivalence's underlying function. -/ add_decl_doc LinearEquiv.left_inv -/-- The notation `M ≃ₛₗ[σ] M₂` denotes the type of linear equivalences between `M` and `M₂` over a +/-- `M ≃ₛₗ[σ] M₂` denotes the type of linear equivalences between `M` and `M₂` over a ring homomorphism `σ`. -/ notation:50 M " ≃ₛₗ[" σ "] " M₂ => LinearEquiv σ M M₂ -/-- The notation `M ≃ₗ [R] M₂` denotes the type of linear equivalences between `M` and `M₂` over +/-- `M ≃ₗ [R] M₂` denotes the type of linear equivalences between `M` and `M₂` over a plain linear map `M →ₗ M₂`. -/ notation:50 M " ≃ₗ[" R "] " M₂ => LinearEquiv (RingHom.id R) M M₂ @@ -297,7 +297,7 @@ def trans (e₁₂ : M₁ ≃ₛₗ[σ₁₂] M₂) (e₂₃ : M₂ ≃ₛₗ[σ₂₃] M₃) : M₁ ≃ₛₗ[σ₁₃] M₃ := { e₂₃.toLinearMap.comp e₁₂.toLinearMap, e₁₂.toEquiv.trans e₂₃.toEquiv with } -/-- The notation `e₁ ≪≫ₗ e₂` denotes the composition of the linear equivalences `e₁` and `e₂`. -/ +/-- `e₁ ≪≫ₗ e₂` denotes the composition of the linear equivalences `e₁` and `e₂`. -/ notation3:80 (name := transNotation) e₁:80 " ≪≫ₗ " e₂:81 => @LinearEquiv.trans _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ (RingHom.id _) (RingHom.id _) (RingHom.id _) (RingHom.id _) (RingHom.id _) (RingHom.id _) RingHomCompTriple.ids RingHomCompTriple.ids diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index eeb6959fc276f..099a6f0601239 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -866,7 +866,7 @@ namespace AddSubgroup variable (A : Type*) [AddCommGroup A] (n : ℤ) -/-- The additive `n`-torsion subgroup for an integer `n`. -/ +/-- The additive `n`-torsion subgroup for an integer `n`, denoted as `A[n]`. -/ @[reducible] def torsionBy : AddSubgroup A := (Submodule.torsionBy ℤ A n).toAddSubgroup diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index f85bf7c48b4fa..9876076f4945c 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -859,7 +859,7 @@ section variable [Semiring k] -/-- The monoid algebra over a semiring `k` generated by the additive monoid `G`. +/-- The monoid algebra over a semiring `k` generated by the additive monoid `G`, denoted by `G[k]`. It is the type of finite formal `k`-linear combinations of terms of `G`, endowed with the convolution product. -/ diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index f42a9e7c4cfb8..94a5729037a50 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -602,7 +602,7 @@ def floor : α → ℤ := def ceil : α → ℤ := FloorRing.ceil -/-- `Int.fract a`, the fractional part of `a`, is `a` minus its floor. -/ +/-- `Int.fract a` the fractional part of `a`, is `a` minus its floor. -/ def fract (a : α) : α := a - floor a diff --git a/Mathlib/Algebra/Order/Group/Unbundled/Abs.lean b/Mathlib/Algebra/Order/Group/Unbundled/Abs.lean index 56042ed6f46bf..c356f6487f6a8 100644 --- a/Mathlib/Algebra/Order/Group/Unbundled/Abs.lean +++ b/Mathlib/Algebra/Order/Group/Unbundled/Abs.lean @@ -28,8 +28,9 @@ variable [Lattice α] section Group variable [Group α] {a b : α} -/-- `mabs a` is the absolute value of `a`. -/ -@[to_additive "`abs a` is the absolute value of `a`"] def mabs (a : α) : α := a ⊔ a⁻¹ +/-- `mabs a`, denoted `|a|ₘ`, is the absolute value of `a`. -/ +@[to_additive "`abs a`, denoted `|a|`, is the absolute value of `a`"] +def mabs (a : α) : α := a ⊔ a⁻¹ @[inherit_doc mabs] macro:max atomic("|" noWs) a:term noWs "|ₘ" : term => `(mabs $a) diff --git a/Mathlib/Algebra/Order/Hom/Ring.lean b/Mathlib/Algebra/Order/Hom/Ring.lean index f0d4f29ca26ed..d3bd1d7c4c040 100644 --- a/Mathlib/Algebra/Order/Hom/Ring.lean +++ b/Mathlib/Algebra/Order/Hom/Ring.lean @@ -39,7 +39,8 @@ open Function variable {F α β γ δ : Type*} -/-- `OrderRingHom α β` is the type of monotone semiring homomorphisms from `α` to `β`. +/-- `OrderRingHom α β`, denoted `α →+*o β`, +is the type of monotone semiring homomorphisms from `α` to `β`. When possible, instead of parametrizing results over `(f : OrderRingHom α β)`, you should parametrize over `(F : Type*) [OrderRingHomClass F α β] (f : F)`. @@ -63,7 +64,8 @@ to otherwise the [refl] attribute on `OrderRingIso.refl` complains. TODO: change back when `refl` attribute is fixed, github issue https://github.com/leanprover-community/mathlib4/issues/2505 -/ -/-- `OrderRingHom α β` is the type of order-preserving semiring isomorphisms between `α` and `β`. +/-- `OrderRingIso α β`, denoted as `α ≃+*o β`, +is the type of order-preserving semiring isomorphisms between `α` and `β`. When possible, instead of parametrizing results over `(f : OrderRingIso α β)`, you should parametrize over `(F : Type*) [OrderRingIsoClass F α β] (f : F)`. diff --git a/Mathlib/Algebra/Polynomial/Basic.lean b/Mathlib/Algebra/Polynomial/Basic.lean index a93b0c652a92e..4a0d9b37f9a1d 100644 --- a/Mathlib/Algebra/Polynomial/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Basic.lean @@ -53,7 +53,8 @@ in general not be used once the basic API for polynomials is constructed. noncomputable section -/-- `Polynomial R` is the type of univariate polynomials over `R`. +/-- `Polynomial R` is the type of univariate polynomials over `R`, +denoted as `R[X]` within the `Polynomial` namespace. Polynomials should be seen as (semi-)rings with the additional constructor `X`. The embedding from `R` is called `C`. -/ diff --git a/Mathlib/Algebra/Polynomial/Div.lean b/Mathlib/Algebra/Polynomial/Div.lean index 48d16d1d4a6f2..6d1a1c3d96070 100644 --- a/Mathlib/Algebra/Polynomial/Div.lean +++ b/Mathlib/Algebra/Polynomial/Div.lean @@ -111,12 +111,12 @@ noncomputable def divModByMonicAux : ∀ (_p : R[X]) {q : R[X]}, Monic q → R[X else ⟨0, p⟩ termination_by p => p -/-- `divByMonic` gives the quotient of `p` by a monic polynomial `q`. -/ +/-- `divByMonic`, denoted as `p /ₘ q`, gives the quotient of `p` by a monic polynomial `q`. -/ def divByMonic (p q : R[X]) : R[X] := letI := Classical.decEq R if hq : Monic q then (divModByMonicAux p hq).1 else 0 -/-- `modByMonic` gives the remainder of `p` by a monic polynomial `q`. -/ +/-- `modByMonic`, denoted as `p %ₘ q`, gives the remainder of `p` by a monic polynomial `q`. -/ def modByMonic (p q : R[X]) : R[X] := letI := Classical.decEq R if hq : Monic q then (divModByMonicAux p hq).2 else p diff --git a/Mathlib/Algebra/Quaternion.lean b/Mathlib/Algebra/Quaternion.lean index a183bc45667c2..bfc6a75772dcc 100644 --- a/Mathlib/Algebra/Quaternion.lean +++ b/Mathlib/Algebra/Quaternion.lean @@ -51,7 +51,8 @@ quaternion -/ -/-- Quaternion algebra over a type with fixed coefficients where $i^2 = a + bi$ and $j^2 = c$. +/-- Quaternion algebra over a type with fixed coefficients where $i^2 = a + bi$ and $j^2 = c$, +denoted as `ℍ[R,a,b]`. Implemented as a structure with four fields: `re`, `imI`, `imJ`, and `imK`. -/ @[ext] structure QuaternionAlgebra (R : Type*) (a b c : R) where @@ -760,8 +761,8 @@ theorem coe_starAe : ⇑(starAe : ℍ[R,c₁,c₂,c₃] ≃ₐ[R] _) = op ∘ st end QuaternionAlgebra -/-- Space of quaternions over a type. Implemented as a structure with four fields: -`re`, `im_i`, `im_j`, and `im_k`. -/ +/-- Space of quaternions over a type, denoted as `ℍ[R]`. +Implemented as a structure with four fields: `re`, `im_i`, `im_j`, and `im_k`. -/ def Quaternion (R : Type*) [Zero R] [One R] [Neg R] := QuaternionAlgebra R (-1) (0) (-1) diff --git a/Mathlib/Algebra/Quotient.lean b/Mathlib/Algebra/Quotient.lean index ea7436110634b..608df82c9e2de 100644 --- a/Mathlib/Algebra/Quotient.lean +++ b/Mathlib/Algebra/Quotient.lean @@ -46,7 +46,7 @@ class HasQuotient (A : outParam <| Type u) (B : Type v) where quotient' : B → Type max u v -- Will be provided by e.g. `Ideal.Quotient.inhabited` -/-- `HasQuotient.Quotient A b` (with notation `A ⧸ b`) is the quotient +/-- `HasQuotient.Quotient A b` (denoted as `A ⧸ b`) is the quotient of the type `A` by `b`. This differs from `HasQuotient.quotient'` in that the `A` argument is diff --git a/Mathlib/Algebra/Symmetrized.lean b/Mathlib/Algebra/Symmetrized.lean index 5d4e197bf27e2..8a465c5325c76 100644 --- a/Mathlib/Algebra/Symmetrized.lean +++ b/Mathlib/Algebra/Symmetrized.lean @@ -30,8 +30,8 @@ The approach taken here is inspired by `Mathlib/Algebra/Opposites.lean`. We use open Function -/-- The symmetrized algebra has the same underlying space as the original algebra. --/ +/-- The symmetrized algebra (denoted as `αˢʸᵐ`) +has the same underlying space as the original algebra `α`. -/ def SymAlg (α : Type*) : Type _ := α diff --git a/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean b/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean index aca2bbc1fa356..e444c0049889b 100644 --- a/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean +++ b/Mathlib/Analysis/Asymptotics/AsymptoticEquivalent.lean @@ -66,8 +66,9 @@ section NormedAddCommGroup variable {α β : Type*} [NormedAddCommGroup β] -/-- Two functions `u` and `v` are said to be asymptotically equivalent along a filter `l` when - `u x - v x = o(v x)` as `x` converges along `l`. -/ +/-- Two functions `u` and `v` are said to be asymptotically equivalent along a filter `l` + (denoted as `u ~[l] v` in the `Asymptotics` namespace) + when `u x - v x = o(v x)` as `x` converges along `l`. -/ def IsEquivalent (l : Filter α) (u v : α → β) := (u - v) =o[l] v diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean index 4dae3f6a8222d..95c7421f62a16 100644 --- a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean +++ b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean @@ -47,8 +47,8 @@ The pattern here is the same one as is used by `Lex` for order structures; it av separate synonym for each type, and allows all the structure-copying code to be shared. -/ -/-- A type synonym for endowing a given type with a `CStarModule` structure. This has the scoped -notation `C⋆ᵐᵒᵈ`. +/-- A type synonym for endowing a given type with a `CStarModule` structure. +This has the scoped notation `C⋆ᵐᵒᵈ` in the WithCStarModule namespace. Note: because the C⋆-algebra `A` over which `E` is a `CStarModule` is listed as an `outParam` in that class, we don't pass it as an unused argument to `WithCStarModule`, unlike the `p` parameter diff --git a/Mathlib/Analysis/Calculus/Gradient/Basic.lean b/Mathlib/Analysis/Calculus/Gradient/Basic.lean index 5c6489419a6d0..e67253e3e2ec7 100644 --- a/Mathlib/Analysis/Calculus/Gradient/Basic.lean +++ b/Mathlib/Analysis/Calculus/Gradient/Basic.lean @@ -68,6 +68,7 @@ def gradientWithin (f : F → 𝕜) (s : Set F) (x : F) : F := (toDual 𝕜 F).symm (fderivWithin 𝕜 f s x) /-- Gradient of `f` at the point `x`, if it exists. Zero otherwise. +Denoted as `∇` within the Gradient namespace. If the derivative exists (i.e., `∃ f', HasGradientAt f f' x`), then `f x' = f x + ⟨f', x' - x⟩ + o (x' - x)` where `x'` converges to `x`. -/ diff --git a/Mathlib/Analysis/Complex/UnitDisc/Basic.lean b/Mathlib/Analysis/Complex/UnitDisc/Basic.lean index adaa04bfb5b12..d5d3b8b0e4d30 100644 --- a/Mathlib/Analysis/Complex/UnitDisc/Basic.lean +++ b/Mathlib/Analysis/Complex/UnitDisc/Basic.lean @@ -22,7 +22,7 @@ local notation "conj'" => starRingEnd ℂ namespace Complex -/-- Complex unit disc. -/ +/-- The complex unit disc, denoted as `𝔻` withinin the Complex namespace -/ def UnitDisc : Type := ball (0 : ℂ) 1 deriving TopologicalSpace diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean index 3a538cfd9d8ac..f2a07cb6618ce 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean @@ -24,7 +24,7 @@ noncomputable section open Matrix Matrix.SpecialLinearGroup open scoped MatrixGroups -/-- The open upper half plane -/ +/-- The open upper half plane, denoted as `ℍ` within the `UpperHalfPlane` namespace -/ def UpperHalfPlane := { point : ℂ // 0 < point.im } diff --git a/Mathlib/Analysis/Convex/Segment.lean b/Mathlib/Analysis/Convex/Segment.lean index 1c4e577df9e16..13d7ab381b215 100644 --- a/Mathlib/Analysis/Convex/Segment.lean +++ b/Mathlib/Analysis/Convex/Segment.lean @@ -48,7 +48,8 @@ def segment (x y : E) : Set E := { z : E | ∃ a b : 𝕜, 0 ≤ a ∧ 0 ≤ b ∧ a + b = 1 ∧ a • x + b • y = z } /-- Open segment in a vector space. Note that `openSegment 𝕜 x x = {x}` instead of being `∅` when -the base semiring has some element between `0` and `1`. -/ +the base semiring has some element between `0` and `1`. +Denoted as `[x -[𝕜] y]` within the `Convex` namespace. -/ def openSegment (x y : E) : Set E := { z : E | ∃ a b : 𝕜, 0 < a ∧ 0 < b ∧ a + b = 1 ∧ a • x + b • y = z } diff --git a/Mathlib/Analysis/Fourier/FourierTransform.lean b/Mathlib/Analysis/Fourier/FourierTransform.lean index c75680f9ddcd1..dcde87aa5b436 100644 --- a/Mathlib/Analysis/Fourier/FourierTransform.lean +++ b/Mathlib/Analysis/Fourier/FourierTransform.lean @@ -298,7 +298,8 @@ open scoped Real namespace Real -/-- The standard additive character of `ℝ`, given by `fun x ↦ exp (2 * π * x * I)`. -/ +/-- The standard additive character of `ℝ`, given by `fun x ↦ exp (2 * π * x * I)`. +Denoted as `𝐞` within the `Real.FourierTransform` namespace. -/ def fourierChar : AddChar ℝ 𝕊 where toFun z := .exp (2 * π * z) map_zero_eq_one' := by simp only; rw [mul_zero, Circle.exp_zero] @@ -372,12 +373,14 @@ open scoped RealInnerProductSpace variable [FiniteDimensional ℝ V] /-- The Fourier transform of a function on an inner product space, with respect to the standard -additive character `ω ↦ exp (2 i π ω)`. -/ +additive character `ω ↦ exp (2 i π ω)`. +Denoted as `𝓕` within the `Real.FourierTransform` namespace. -/ def fourierIntegral (f : V → E) (w : V) : E := VectorFourier.fourierIntegral 𝐞 volume (innerₗ V) f w /-- The inverse Fourier transform of a function on an inner product space, defined as the Fourier -transform but with opposite sign in the exponential. -/ +transform but with opposite sign in the exponential. +Denoted as `𝓕⁻¹` within the `Real.FourierTransform` namespace. -/ def fourierIntegralInv (f : V → E) (w : V) : E := VectorFourier.fourierIntegral 𝐞 volume (-innerₗ V) f w diff --git a/Mathlib/Analysis/Fourier/ZMod.lean b/Mathlib/Analysis/Fourier/ZMod.lean index ae3c4f996bbcc..22825977656de 100644 --- a/Mathlib/Analysis/Fourier/ZMod.lean +++ b/Mathlib/Analysis/Fourier/ZMod.lean @@ -76,7 +76,7 @@ section defs /-- The discrete Fourier transform on `ℤ / N ℤ` (with the counting measure), bundled as a linear -equivalence. +equivalence. Denoted as `𝓕` within the `ZMod` namespace. -/ noncomputable def dft : (ZMod N → E) ≃ₗ[ℂ] (ZMod N → E) where toFun := auxDFT diff --git a/Mathlib/Analysis/InnerProductSpace/Adjoint.lean b/Mathlib/Analysis/InnerProductSpace/Adjoint.lean index 83a790f784a3c..ad17c521ac625 100644 --- a/Mathlib/Analysis/InnerProductSpace/Adjoint.lean +++ b/Mathlib/Analysis/InnerProductSpace/Adjoint.lean @@ -99,11 +99,13 @@ theorem adjointAux_norm (A : E →L[𝕜] F) : ‖adjointAux A‖ = ‖A‖ := b rw [adjointAux_apply, LinearIsometryEquiv.norm_map] exact toSesqForm_apply_norm_le -/-- The adjoint of a bounded operator from Hilbert space `E` to Hilbert space `F`. -/ +/-- The adjoint of a bounded operator `A` from a Hilbert space `E` to another Hilbert space `F`, + denoted as `A†`. -/ def adjoint : (E →L[𝕜] F) ≃ₗᵢ⋆[𝕜] F →L[𝕜] E := LinearIsometryEquiv.ofSurjective { adjointAux with norm_map' := adjointAux_norm } fun A => ⟨adjointAux A, adjointAux_adjointAux A⟩ +@[inherit_doc] scoped[InnerProduct] postfix:1000 "†" => ContinuousLinearMap.adjoint open InnerProduct diff --git a/Mathlib/Analysis/InnerProductSpace/Defs.lean b/Mathlib/Analysis/InnerProductSpace/Defs.lean index c89fcb0886d38..8b3140b2eae8a 100644 --- a/Mathlib/Analysis/InnerProductSpace/Defs.lean +++ b/Mathlib/Analysis/InnerProductSpace/Defs.lean @@ -193,12 +193,16 @@ variable [AddCommGroup F] [Module 𝕜 F] [c : PreInnerProductSpace.Core 𝕜 F] local notation "⟪" x ", " y "⟫" => @inner 𝕜 F _ x y +/-- Local notation for `RCLike.normSq 𝕜` -/ local notation "normSqK" => @RCLike.normSq 𝕜 _ +/-- Local notation for `RCLike.re 𝕜` -/ local notation "reK" => @RCLike.re 𝕜 _ +/-- Local notation for `RCLike.ext_iff 𝕜` -/ local notation "ext_iff" => @RCLike.ext_iff 𝕜 _ +/-- Local notation for `starRingEnd _` -/ local postfix:90 "†" => starRingEnd _ /-- Inner product defined by the `PreInnerProductSpace.Core` structure. We can't reuse @@ -213,6 +217,7 @@ attribute [local instance] toPreInner' def normSq (x : F) := reK ⟪x, x⟫ +/-- The norm squared function for `PreInnerProductSpace.Core` structure. -/ local notation "normSqF" => @normSq 𝕜 F _ _ _ _ theorem inner_conj_symm (x y : F) : ⟪y, x⟫† = ⟪x, y⟫ := diff --git a/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean b/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean index e80e7b0443eb7..8c535957fea7e 100644 --- a/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean +++ b/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean @@ -143,11 +143,12 @@ theorem adjointAux_unique (y : T.adjointDomain) {x₀ : E} variable (T) open scoped Classical in -/-- The adjoint operator as a partially defined linear operator. -/ +/-- The adjoint operator as a partially defined linear operator, denoted as `T†`. -/ def adjoint : F →ₗ.[𝕜] E where domain := T.adjointDomain toFun := if hT : Dense (T.domain : Set E) then adjointAux hT else 0 +@[inherit_doc] scoped postfix:1024 "†" => LinearPMap.adjoint theorem mem_adjoint_domain_iff (y : F) : y ∈ T†.domain ↔ Continuous ((innerₛₗ 𝕜 y).comp T.toFun) := diff --git a/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean b/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean index 876666070250b..d0bbc998a808f 100644 --- a/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean +++ b/Mathlib/Analysis/InnerProductSpace/Orthogonal.lean @@ -33,7 +33,7 @@ namespace Submodule variable (K : Submodule 𝕜 E) -/-- The subspace of vectors orthogonal to a given subspace. -/ +/-- The subspace of vectors orthogonal to a given subspace, denoted `Kᗮ`. -/ def orthogonal : Submodule 𝕜 E where carrier := { v | ∀ u ∈ K, ⟪u, v⟫ = 0 } zero_mem' _ _ := inner_zero_right _ @@ -199,7 +199,7 @@ theorem bilinFormOfRealInner_orthogonal {E} [NormedAddCommGroup E] [InnerProduct /-! ### Orthogonality of submodules -In this section we define `Submodule.IsOrtho U V`, with notation `U ⟂ V`. +In this section we define `Submodule.IsOrtho U V`, denoted as `U ⟂ V`. The API roughly matches that of `Disjoint`. -/ @@ -207,7 +207,7 @@ The API roughly matches that of `Disjoint`. namespace Submodule -/-- The proposition that two submodules are orthogonal. Has notation `U ⟂ V`. -/ +/-- The proposition that two submodules are orthogonal, denoted as `U ⟂ V`. -/ def IsOrtho (U V : Submodule 𝕜 E) : Prop := U ≤ Vᗮ diff --git a/Mathlib/Analysis/Normed/Affine/Isometry.lean b/Mathlib/Analysis/Normed/Affine/Isometry.lean index b4f0354b00717..d7caa79c94031 100644 --- a/Mathlib/Analysis/Normed/Affine/Isometry.lean +++ b/Mathlib/Analysis/Normed/Affine/Isometry.lean @@ -46,7 +46,7 @@ variable (𝕜 : Type*) {V V₁ V₁' V₂ V₃ V₄ : Type*} {P₁ P₁' : Type [SeminormedAddCommGroup V₄] [NormedSpace 𝕜 V₄] [PseudoMetricSpace P₄] [NormedAddTorsor V₄ P₄] /-- A `𝕜`-affine isometric embedding of one normed add-torsor over a normed `𝕜`-space into -another. -/ +another, denoted as `f : P →ᵃⁱ[𝕜] P₂`. -/ structure AffineIsometry extends P →ᵃ[𝕜] P₂ where norm_map : ∀ x : V, ‖linear x‖ = ‖x‖ @@ -260,7 +260,8 @@ end AffineSubspace variable (𝕜 P P₂) -/-- An affine isometric equivalence between two normed vector spaces. -/ +/-- An affine isometric equivalence between two normed vector spaces, +denoted `f : P ≃ᵃⁱ[𝕜] P₂`. -/ structure AffineIsometryEquiv extends P ≃ᵃ[𝕜] P₂ where norm_map : ∀ x, ‖linear x‖ = ‖x‖ diff --git a/Mathlib/Analysis/Normed/Lp/lpSpace.lean b/Mathlib/Analysis/Normed/Lp/lpSpace.lean index b2a36ecac89b5..356ca2b7ac0dc 100644 --- a/Mathlib/Analysis/Normed/Lp/lpSpace.lean +++ b/Mathlib/Analysis/Normed/Lp/lpSpace.lean @@ -288,7 +288,8 @@ instance : AddCommGroup (PreLp E) := by unfold PreLp; infer_instance instance PreLp.unique [IsEmpty α] : Unique (PreLp E) := Pi.uniqueOfIsEmpty E -/-- lp space -/ +/-- lp space +The `p=∞` case has notation `ℓ^∞(ι, E)` resp. `ℓ^∞(ι)` (for `E = ℝ`) in the `lp` namespace. -/ def lp (E : α → Type*) [∀ i, NormedAddCommGroup (E i)] (p : ℝ≥0∞) : AddSubgroup (PreLp E) where carrier := { f | Memℓp f p } zero_mem' := zero_memℓp diff --git a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean index 03481455bb86d..a59154a0c16c3 100644 --- a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean +++ b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean @@ -42,7 +42,8 @@ variable {R R₂ R₃ R₄ E E₂ E₃ E₄ F 𝓕 : Type*} [Semiring R] [Semiri [SeminormedAddCommGroup E₄] [Module R E] [Module R₂ E₂] [Module R₃ E₃] [Module R₄ E₄] [NormedAddCommGroup F] [Module R F] -/-- A `σ₁₂`-semilinear isometric embedding of a normed `R`-module into an `R₂`-module. -/ +/-- A `σ₁₂`-semilinear isometric embedding of a normed `R`-module into an `R₂`-module, +denoted as `f : E →ₛₗᵢ[σ₁₂] E₂`. -/ structure LinearIsometry (σ₁₂ : R →+* R₂) (E E₂ : Type*) [SeminormedAddCommGroup E] [SeminormedAddCommGroup E₂] [Module R E] [Module R₂ E₂] extends E →ₛₗ[σ₁₂] E₂ where norm_map' : ∀ x, ‖toLinearMap x‖ = ‖x‖ @@ -402,7 +403,8 @@ theorem subtypeₗᵢ_toContinuousLinearMap : p.subtypeₗᵢ.toContinuousLinear end Submodule -/-- A semilinear isometric equivalence between two normed vector spaces. -/ +/-- A semilinear isometric equivalence between two normed vector spaces, +denoted as `f : E ≃ₛₗᵢ[σ₁₂] E₂`. -/ structure LinearIsometryEquiv (σ₁₂ : R →+* R₂) {σ₂₁ : R₂ →+* R} [RingHomInvPair σ₁₂ σ₂₁] [RingHomInvPair σ₂₁ σ₁₂] (E E₂ : Type*) [SeminormedAddCommGroup E] [SeminormedAddCommGroup E₂] [Module R E] [Module R₂ E₂] extends E ≃ₛₗ[σ₁₂] E₂ where diff --git a/Mathlib/Analysis/RCLike/Inner.lean b/Mathlib/Analysis/RCLike/Inner.lean index 4136cd8069e82..31f4ce68c9de2 100644 --- a/Mathlib/Analysis/RCLike/Inner.lean +++ b/Mathlib/Analysis/RCLike/Inner.lean @@ -32,7 +32,7 @@ variable [RCLike 𝕜] section Pi variable [∀ i, SeminormedAddCommGroup (E i)] [∀ i, InnerProductSpace 𝕜 (E i)] {w : ι → ℝ} -/-- Weighted inner product giving rise to the L2 norm. -/ +/-- Weighted inner product giving rise to the L2 norm, denoted as `⟪g, f⟫_[𝕜, w]`. -/ def wInner (w : ι → ℝ) (f g : ∀ i, E i) : 𝕜 := ∑ i, w i • inner (f i) (g i) /-- The weight function making `wInner` into the compact inner product. -/ diff --git a/Mathlib/Analysis/SpecialFunctions/OrdinaryHypergeometric.lean b/Mathlib/Analysis/SpecialFunctions/OrdinaryHypergeometric.lean index bbbd460e9abe3..557084bf800d2 100644 --- a/Mathlib/Analysis/SpecialFunctions/OrdinaryHypergeometric.lean +++ b/Mathlib/Analysis/SpecialFunctions/OrdinaryHypergeometric.lean @@ -67,8 +67,8 @@ noncomputable def ordinaryHypergeometricSeries (a b c : 𝕂) : FormalMultilinea variable {𝔸} (a b c : 𝕂) -/-- `ordinaryHypergeometric (a b c : 𝕂) : 𝔸 → 𝔸` is the ordinary hypergeometric map, defined as the -sum of the `FormalMultilinearSeries` `ordinaryHypergeometricSeries 𝔸 a b c`. +/-- `ordinaryHypergeometric (a b c : 𝕂) : 𝔸 → 𝔸`, denoted `₂F₁`, is the ordinary hypergeometric map, +defined as the sum of the `FormalMultilinearSeries` `ordinaryHypergeometricSeries 𝔸 a b c`. Note that this takes the junk value `0` outside the radius of convergence. -/ diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean index ac5453bf1c463..e2816cc24eaff 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean @@ -116,7 +116,9 @@ theorem exists_cos_eq_zero : 0 ∈ cos '' Icc (1 : ℝ) 2 := ⟨le_of_lt cos_two_neg, le_of_lt cos_one_pos⟩ /-- The number π = 3.14159265... Defined here using choice as twice a zero of cos in [1,2], from -which one can derive all its properties. For explicit bounds on π, see `Data.Real.Pi.Bounds`. -/ +which one can derive all its properties. For explicit bounds on π, see `Data.Real.Pi.Bounds`. + +Denoted `π`, once the `Real` namespace is opened. -/ protected noncomputable def pi : ℝ := 2 * Classical.choose exists_cos_eq_zero diff --git a/Mathlib/Data/Matrix/Hadamard.lean b/Mathlib/Data/Matrix/Hadamard.lean index cdaa2360b95c5..4b8efd38c185e 100644 --- a/Mathlib/Data/Matrix/Hadamard.lean +++ b/Mathlib/Data/Matrix/Hadamard.lean @@ -34,7 +34,7 @@ variable {α m n R : Type*} namespace Matrix -/-- `Matrix.hadamard` defines the Hadamard product, +/-- `Matrix.hadamard` (denoted as `⊙` within the Matrix namespace) defines the Hadamard product, which is the pointwise product of two matrices of the same size. -/ def hadamard [Mul α] (A : Matrix m n α) (B : Matrix m n α) : Matrix m n α := of fun i j => A i j * B i j @@ -45,7 +45,7 @@ theorem hadamard_apply [Mul α] (A : Matrix m n α) (B : Matrix m n α) (i j) : hadamard A B i j = A i j * B i j := rfl -scoped infixl:100 " ⊙ " => Matrix.hadamard +@[inherit_doc] scoped infixl:100 " ⊙ " => Matrix.hadamard section BasicProperties diff --git a/Mathlib/Data/Matrix/Kronecker.lean b/Mathlib/Data/Matrix/Kronecker.lean index 525e8243ba190..31a238dac9c94 100644 --- a/Mathlib/Data/Matrix/Kronecker.lean +++ b/Mathlib/Data/Matrix/Kronecker.lean @@ -36,8 +36,8 @@ This defines the [Kronecker product](https://en.wikipedia.org/wiki/Kronecker_pro These require `open Kronecker`: * `A ⊗ₖ B` for `kroneckerMap (*) A B`. Lemmas about this notation use the token `kronecker`. -* `A ⊗ₖₜ B` and `A ⊗ₖₜ[R] B` for `kroneckerMap (⊗ₜ) A B`. Lemmas about this notation use the token - `kroneckerTMul`. +* `A ⊗ₖₜ B` and `A ⊗ₖₜ[R] B` for `kroneckerMap (⊗ₜ) A B`. + Lemmas about this notation use the token `kroneckerTMul`. -/ @@ -239,6 +239,7 @@ open Matrix def kronecker [Mul α] : Matrix l m α → Matrix n p α → Matrix (l × n) (m × p) α := kroneckerMap (· * ·) +@[inherit_doc Matrix.kroneckerMap] scoped[Kronecker] infixl:100 " ⊗ₖ " => Matrix.kroneckerMap (· * ·) open Kronecker @@ -417,10 +418,11 @@ Prefer the notation `⊗ₖₜ` rather than this definition. -/ def kroneckerTMul : Matrix l m α → Matrix n p β → Matrix (l × n) (m × p) (α ⊗[R] β) := kroneckerMap (· ⊗ₜ ·) +@[inherit_doc kroneckerTMul] scoped[Kronecker] infixl:100 " ⊗ₖₜ " => Matrix.kroneckerMap (· ⊗ₜ ·) -scoped[Kronecker] - notation:100 x " ⊗ₖₜ[" R "] " y:100 => Matrix.kroneckerMap (TensorProduct.tmul R) x y +@[inherit_doc kroneckerTMul] scoped[Kronecker] notation:100 x " ⊗ₖₜ[" R "] " y:100 => + Matrix.kroneckerMap (TensorProduct.tmul R) x y open Kronecker diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index 631407d91cc1e..95519a608d383 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -50,7 +50,7 @@ assert_not_exists Star open Function -- to ensure these instances are computable -/-- Nonnegative real numbers. -/ +/-- Nonnegative real numbers, denoted as `ℝ≥0` withinin the NNReal namespace -/ def NNReal := { r : ℝ // 0 ≤ r } deriving Zero, One, Semiring, StrictOrderedSemiring, CommMonoidWithZero, CommSemiring, PartialOrder, SemilatticeInf, SemilatticeSup, DistribLattice, OrderedCommSemiring, @@ -58,7 +58,7 @@ def NNReal := { r : ℝ // 0 ≤ r } deriving namespace NNReal -scoped notation "ℝ≥0" => NNReal +@[inherit_doc] scoped notation "ℝ≥0" => NNReal instance : CanonicallyOrderedAdd ℝ≥0 := Nonneg.canonicallyOrderedAdd instance : NoZeroDivisors ℝ≥0 := Nonneg.noZeroDivisors diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index 12754362767ea..7bcb7a3778950 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -120,9 +120,9 @@ variable {H : Type u} {H' : Type*} {M : Type*} {M' : Type*} {M'' : Type*} `PartialHomeomorph.trans` and `PartialEquiv.trans`. Note that, as is usual for equivs, the composition is from left to right, hence the direction of the arrow. -/ -scoped[Manifold] infixr:100 " ≫ₕ " => PartialHomeomorph.trans +@[inherit_doc] scoped[Manifold] infixr:100 " ≫ₕ " => PartialHomeomorph.trans -scoped[Manifold] infixr:100 " ≫ " => PartialEquiv.trans +@[inherit_doc] scoped[Manifold] infixr:100 " ≫ " => PartialEquiv.trans open Set PartialHomeomorph Manifold -- Porting note: Added `Manifold` diff --git a/Mathlib/Geometry/Manifold/ContMDiffMap.lean b/Mathlib/Geometry/Manifold/ContMDiffMap.lean index c4d2dbbb08733..07becbcbb3db7 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMap.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMap.lean @@ -25,7 +25,9 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom {J : ModelWithCorners 𝕜 F G} {N : Type*} [TopologicalSpace N] [ChartedSpace G N] (n : WithTop ℕ∞) variable (I I') in -/-- Bundled `n` times continuously differentiable maps. -/ +/-- Bundled `n` times continuously differentiable maps, +denoted as `C^n(I, M; I', M')` and `C^n(I, M; k)` (when the target is a normed space `k` with +the trivial model) in the `Manifold` namespace. -/ def ContMDiffMap := { f : M → M' // ContMDiff I I' n f } diff --git a/Mathlib/Geometry/Manifold/DerivationBundle.lean b/Mathlib/Geometry/Manifold/DerivationBundle.lean index 0cbb33ee8efac..4cca168870307 100644 --- a/Mathlib/Geometry/Manifold/DerivationBundle.lean +++ b/Mathlib/Geometry/Manifold/DerivationBundle.lean @@ -32,7 +32,8 @@ instance smoothFunctionsAlgebra : Algebra 𝕜 C^∞⟮I, M; 𝕜⟯ := by infer instance smooth_functions_tower : IsScalarTower 𝕜 C^∞⟮I, M; 𝕜⟯ C^∞⟮I, M; 𝕜⟯ := by infer_instance /-- Type synonym, introduced to put a different `SMul` action on `C^n⟮I, M; 𝕜⟯` -which is defined as `f • r = f(x) * r`. -/ +which is defined as `f • r = f(x) * r`. +Denoted as `C^n⟮I, M; 𝕜⟯⟨x⟩` within the `Derivation` namespace. -/ @[nolint unusedArguments] def PointedContMDiffMap (_ : M) := C^n⟮I, M; 𝕜⟯ @@ -123,7 +124,8 @@ variable {I} {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Ty [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] -/-- The heterogeneous differential as a linear map. Instead of taking a function as an argument this +/-- The heterogeneous differential as a linear map, denoted as `𝒅ₕ` within the `Manifold` namespace. +Instead of taking a function as an argument this differential takes `h : f x = y`. It is particularly handy to deal with situations where the points on where it has to be evaluated are equal but not definitionally equal. -/ def hfdifferential {f : C^∞⟮I, M; I', M'⟯} {x : M} {y : M'} (h : f x = y) : @@ -143,16 +145,16 @@ def hfdifferential {f : C^∞⟮I, M; I', M'⟯} {x : M} {y : M'} (h : f x = y) map_smul' _ _ := rfl map_add' _ _ := rfl -/-- The homogeneous differential as a linear map. -/ +/-- The homogeneous differential as a linear map, denoted as `𝒅` within the `Manifold` namespace. -/ def fdifferential (f : C^∞⟮I, M; I', M'⟯) (x : M) : PointDerivation I x →ₗ[𝕜] PointDerivation I' (f x) := hfdifferential (rfl : f x = f x) -- Standard notation for the differential. The abbreviation is `MId`. -scoped[Manifold] notation "𝒅" => fdifferential +@[inherit_doc] scoped[Manifold] notation "𝒅" => fdifferential -- Standard notation for the differential. The abbreviation is `MId`. -scoped[Manifold] notation "𝒅ₕ" => hfdifferential +@[inherit_doc] scoped[Manifold] notation "𝒅ₕ" => hfdifferential @[simp] theorem fdifferential_apply (f : C^∞⟮I, M; I', M'⟯) {x : M} (v : PointDerivation I x) diff --git a/Mathlib/Geometry/Manifold/Diffeomorph.lean b/Mathlib/Geometry/Manifold/Diffeomorph.lean index 4b54d89d14d5b..8c50a4f7055ec 100644 --- a/Mathlib/Geometry/Manifold/Diffeomorph.lean +++ b/Mathlib/Geometry/Manifold/Diffeomorph.lean @@ -64,7 +64,7 @@ section Defs variable (I I' M M' n) /-- `n`-times continuously differentiable diffeomorphism between `M` and `M'` with respect to `I` -and `I'`. -/ +and `I'`, denoted as `M ≃ₘ^n⟮I, I'⟯ M'` (in the `Manifold` namespace). -/ structure Diffeomorph extends M ≃ M' where protected contMDiff_toFun : ContMDiff I I' n toEquiv protected contMDiff_invFun : ContMDiff I' I n toEquiv.symm diff --git a/Mathlib/Geometry/Manifold/IsManifold.lean b/Mathlib/Geometry/Manifold/IsManifold.lean index b92490c31eaf0..69d14ee8012e6 100644 --- a/Mathlib/Geometry/Manifold/IsManifold.lean +++ b/Mathlib/Geometry/Manifold/IsManifold.lean @@ -166,7 +166,7 @@ structure ModelWithCorners (𝕜 : Type*) [NontriviallyNormedField 𝕜] (E : Ty attribute [simp, mfld_simps] ModelWithCorners.source_eq -/-- A vector space is a model with corners. -/ +/-- A vector space is a model with corners, denoted as `𝓘(𝕜, E)` within the `Manifold` namespace. -/ def modelWithCornersSelf (𝕜 : Type*) [NontriviallyNormedField 𝕜] (E : Type*) [NormedAddCommGroup E] [NormedSpace 𝕜 E] : ModelWithCorners 𝕜 E E where toPartialEquiv := PartialEquiv.refl E diff --git a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean index fa5a1a2036d04..fc9c216accc73 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean @@ -31,7 +31,8 @@ variable (F : Type*) [NormedAddCommGroup F] [NormedSpace 𝕜 F] -- `V` vector bundle [∀ x : M, TopologicalSpace (V x)] [FiberBundle F V] -/-- Bundled `n` times continuously differentiable sections of a vector bundle. -/ +/-- Bundled `n` times continuously differentiable sections of a vector bundle. +Denoted as `Cₛ^n⟮I; F, V⟯` within the `Manifold` namespace. -/ structure ContMDiffSection where /-- the underlying function of this section -/ protected toFun : ∀ x, V x diff --git a/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean b/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean index 5bd189f1e2b73..eb134172c1ac3 100644 --- a/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean +++ b/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean @@ -445,6 +445,7 @@ section StarOrderedRing variable {𝕜 : Type*} [CommRing 𝕜] [StarRing 𝕜] +/-- Notation for `Sum.elim`, scoped within the `Matrix` namespace. -/ scoped infixl:65 " ⊕ᵥ " => Sum.elim theorem schur_complement_eq₁₁ [Fintype m] [DecidableEq m] [Fintype n] {A : Matrix m m 𝕜} diff --git a/Mathlib/Logic/Equiv/PartialEquiv.lean b/Mathlib/Logic/Equiv/PartialEquiv.lean index ff661bd6d8b3e..ca658fa24c549 100644 --- a/Mathlib/Logic/Equiv/PartialEquiv.lean +++ b/Mathlib/Logic/Equiv/PartialEquiv.lean @@ -574,7 +574,9 @@ protected def trans' (e' : PartialEquiv β γ) (h : e.target = e'.source) : Part right_inv' y hy := by simp [hy, h] /-- Composing two partial equivs, by restricting to the maximal domain where their composition -is well defined. -/ +is well defined. +Within the `Manifold` namespace, there is the notation `e ≫ f` for this. +-/ @[trans] protected def trans : PartialEquiv α γ := PartialEquiv.trans' (e.symm.restr e'.source).symm (e'.restr e.target) (inter_comm _ _) diff --git a/Mathlib/MeasureTheory/Integral/CircleIntegral.lean b/Mathlib/MeasureTheory/Integral/CircleIntegral.lean index 4fd2b90860e81..346ad13c7ca91 100644 --- a/Mathlib/MeasureTheory/Integral/CircleIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/CircleIntegral.lean @@ -300,10 +300,11 @@ theorem circleIntegrable_sub_inv_iff {c w : ℂ} {R : ℝ} : variable [NormedSpace ℂ E] -/-- Definition for $\oint_{|z-c|=R} f(z)\,dz$. -/ +/-- Definition for $\oint_{|z-c|=R} f(z)\,dz$ -/ def circleIntegral (f : ℂ → E) (c : ℂ) (R : ℝ) : E := ∫ θ : ℝ in (0)..2 * π, deriv (circleMap c R) θ • f (circleMap c R θ) +/-- `∮ z in C(c, R), f z` is the circle integral $\oint_{|z-c|=R} f(z)\,dz$. -/ notation3 "∮ "(...)" in ""C("c", "R")"", "r:(scoped f => circleIntegral f c R) => r theorem circleIntegral_def_Icc (f : ℂ → E) (c : ℂ) (R : ℝ) : diff --git a/Mathlib/MeasureTheory/Integral/IntervalAverage.lean b/Mathlib/MeasureTheory/Integral/IntervalAverage.lean index 0ecbef306508c..0f592cd4f7158 100644 --- a/Mathlib/MeasureTheory/Integral/IntervalAverage.lean +++ b/Mathlib/MeasureTheory/Integral/IntervalAverage.lean @@ -31,6 +31,7 @@ open scoped Interval variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +/-- `⨍ x in a..b, f x` is the average of `f` over the interval `Ι a w.r.t. the Lebesgue measure. -/ notation3 "⨍ "(...)" in "a".."b", "r:60:(scoped f => average (Measure.restrict volume (uIoc a b)) f) => r diff --git a/Mathlib/Topology/Homotopy/HomotopyGroup.lean b/Mathlib/Topology/Homotopy/HomotopyGroup.lean index 4f7eabdf8af64..5b89b085f0379 100644 --- a/Mathlib/Topology/Homotopy/HomotopyGroup.lean +++ b/Mathlib/Topology/Homotopy/HomotopyGroup.lean @@ -46,6 +46,8 @@ open Homeomorph noncomputable section +/-- `I^N` is notation (in the Topology namespace) for `N → I`, +i.e. the unit cube indexed by a type `N`. -/ scoped[Topology] notation "I^" N => N → I namespace Cube @@ -76,11 +78,12 @@ end Cube variable (N X : Type*) [TopologicalSpace X] (x : X) -/-- The space of paths with both endpoints equal to a specified point `x : X`. -/ +/-- The space of paths with both endpoints equal to a specified point `x : X`. +Denoted as `Ω`, within the `Topology.Homotopy` namespace. -/ abbrev LoopSpace := Path x x -scoped[Topology.Homotopy] notation "Ω" => LoopSpace +@[inherit_doc] scoped[Topology.Homotopy] notation "Ω" => LoopSpace instance LoopSpace.inhabited : Inhabited (Path x x) := ⟨Path.refl x⟩ @@ -364,11 +367,11 @@ def homotopyGroupEquivFundamentalGroup (i : N) : apply Quotient.congr (loopHomeo i).toEquiv exact fun p q => ⟨homotopicTo i, homotopicFrom i⟩ -/-- Homotopy group of finite index. -/ +/-- Homotopy group of finite index, denoted as `π_n` within the Topology namespace. -/ abbrev HomotopyGroup.Pi (n) (X : Type*) [TopologicalSpace X] (x : X) := HomotopyGroup (Fin n) _ x -scoped[Topology] notation "π_" => HomotopyGroup.Pi +@[inherit_doc] scoped[Topology] notation "π_" => HomotopyGroup.Pi /-- The 0-dimensional generalized loops based at `x` are in bijection with `X`. -/ def genLoopHomeoOfIsEmpty (N x) [IsEmpty N] : Ω^ N X x ≃ₜ X where diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index cff9b2fba723d..a178c181fd1cd 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -690,7 +690,8 @@ protected def trans' (h : e.target = e'.source) : PartialHomeomorph X Z where continuousOn_invFun := e.continuousOn_symm.comp e'.continuousOn_symm <| h.symm ▸ e'.symm_mapsTo /-- Composing two partial homeomorphisms, by restricting to the maximal domain where their -composition is well defined. -/ +composition is well defined. +Within the `Manifold` namespace, there is the notation `e ≫ₕ f` for this. -/ @[trans] protected def trans : PartialHomeomorph X Z := PartialHomeomorph.trans' (e.symm.restrOpen e'.source e'.open_source).symm diff --git a/scripts/nolints.json b/scripts/nolints.json index d2824c5a15099..208e5531b4cd5 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -35,8 +35,6 @@ ["docBlame", "measurability!?"], ["docBlame", "tacticCancel_denoms_"], ["docBlame", "tacticUse_finite_instance"], - ["docBlame", "«term∮_InC(_,_),_»"], - ["docBlame", "«term⨍_In_.._,_»"], ["docBlame", "when"], ["docBlame", "whenM"], ["docBlame", "Action.V"], @@ -154,30 +152,19 @@ ["docBlame", "ImplicitFunctionData.pt"], ["docBlame", "ImplicitFunctionData.rightDeriv"], ["docBlame", "ImplicitFunctionData.rightFun"], - ["docBlame", "InnerProduct.«term_†»"], ["docBlame", "Int.decNonneg"], ["docBlame", "IntermediateField.delabAdjoinNotation"], ["docBlame", "IsAdjoinRoot.map"], ["docBlame", "JordanHolderLattice.IsMaximal"], ["docBlame", "JordanHolderLattice.Iso"], - ["docBlame", "Kronecker.«term_⊗ₖ_»"], - ["docBlame", "Kronecker.«term_⊗ₖₜ[_]_»"], - ["docBlame", "Kronecker.«term_⊗ₖₜ_»"], ["docBlame", "Lean.ExportM"], ["docBlame", "LinearPMap.domain"], ["docBlame", "LinearPMap.sSup"], - ["docBlame", "LinearPMap.«term_†»"], ["docBlame", "LinearPMap.toFun"], ["docBlame", "LinearPMap.toFun'"], ["docBlame", "LinearRecurrence.coeffs"], ["docBlame", "LinearRecurrence.order"], ["docBlame", "MagmaCat.forget_obj_eq_coe"], - ["docBlame", "Manifold.«term_≫_»"], - ["docBlame", "Manifold.«term_≫ₕ_»"], - ["docBlame", "Manifold.«term𝒅»"], - ["docBlame", "Manifold.«term𝒅ₕ»"], - ["docBlame", "Matrix.«term_⊕ᵥ_»"], - ["docBlame", "Matrix.«term_⊙_»"], ["docBlame", "MaximalSpectrum.asIdeal"], ["docBlame", "MeasureTheory.«term_[_|_]»"], ["docBlame", "MeasureTheory.«term_→₁[_]_»"], @@ -221,7 +208,6 @@ ["docBlame", "NFA.start"], ["docBlame", "NFA.step"], ["docBlame", "NNDist.nndist"], - ["docBlame", "NNReal.«termℝ≥0»"], ["docBlame", "Nat.discriminate"], ["docBlame", "Nat.findX"], ["docBlame", "Nat.ltByCases"], @@ -293,8 +279,6 @@ ["docBlame", "Stream'.unfolds"], ["docBlame", "StrictWeakOrder.Equiv"], ["docBlame", "Submodule.«term_∙_»"], - ["docBlame", "Topology.«termI^_»"], - ["docBlame", "Topology.termπ_"], ["docBlame", "Traversable.foldMap"], ["docBlame", "Traversable.foldl"], ["docBlame", "Traversable.foldlm"], @@ -504,7 +488,6 @@ ["docBlame", "Tactic.Elementwise.tacticElementwise___"], ["docBlame", "Tactic.NormNum.evalNatGCD"], ["docBlame", "ToAdditive.additiveTestUnsafe.visit"], - ["docBlame", "Topology.Homotopy.termΩ"], ["docBlame", "WittVector.Isocrystal.frob"], ["docBlame", "AlgebraicGeometry.PresheafedSpace.Hom.base"], ["docBlame", "AlgebraicGeometry.PresheafedSpace.Hom.c"], From 1409d1f1d981457369ed73c5c756673e1e7c1ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= Date: Sat, 25 Jan 2025 05:06:19 +0000 Subject: [PATCH 497/681] =?UTF-8?q?perf:=20improves=20the=20performance=20?= =?UTF-8?q?of=20the=20`Repr=20(Equiv.Perm=20=CE=B1)`=20instance=20(3/4)=20?= =?UTF-8?q?(#12610)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `instance [Fintype α] [Repr α] : Repr (Equiv.Perm α)` uses functions depends on `[DecidableRel (SameCycle (f : Equiv.Perm α))]`. If `α` is `Fintype` where `Fintype.card α = n`, it is sufficient for deciding `SameCycle f x y` to apply `f` to `x` for `n` times and check if `y` appears in them. However, currently, `f` is applied for `Fintype.card (Equiv.Perm α) = n!` times! 😃 < You know, factorial is written as "!" 🥶 😰 🫥 🙉 This is because, some of lemmas required to prove that it is sufficient for deciding `SameCycle f x y` to apply `f` to `x` for `n` times, uses the formula `(cycleOf (f : Equiv.Perm α) x).support : Finset α`. `(g : Equiv.Perm α).support` depends on `[Fintype α] [DecidableEq α]`, and `cycleOf (f : Equiv.Perm α) x` depends on `[DecidableRel (SameCycle (f : Equiv.Perm α))]`, so these lemmas depends on `[Fintype α] [DecidableEq α] [DecidableRel (SameCycle (f : Equiv.Perm α))]`. If we could prove that fact without these lemmas and define before these lemmas, the imstance argument `[DecidableRel (SameCycle (f : Equiv.Perm α))]` in these lemmas are not required anymore. And, if we use `n!` instead of `n`, these lemmas are not required anymore! 😃 < You know, factorial is written as "!" 👹 👹 👹 👹 So the current Mathlib apply `f` to `x` for `n!` times, but this is clearly a performance problem. To solve this problem, we copy these lemmas as private lemmas before `instance [Fintype α] [DecidableEq α] : DecidableRel (SameCycle (f : Equiv.Perm α))`. These lemmas depends on `[Fintype α] [DecidableEq α] [DecidableRel (SameCycle (f : Equiv.Perm α))]`. In `instance [Fintype α] [DecidableEq α] : DecidableRel (SameCycle (f : Equiv.Perm α))`, we prove that it is sufficient for deciding `SameCycle f x y` to apply `f` to `x` for `n` times, using these lemmas with `classical`. We're proving a lemma so the computable instance is not necessary. After define the instance, we restate the previous private lemma as global lemmas, these lemmas doesn't depend on `[DecidableRel (SameCycle (f : Equiv.Perm α))]` anymore. And we don't have to apply `f` for `n!` times anymore! 🕳 < You know, factorial is written a- 🔘👈😉 😄 😇 🤣 Co-authored-by: Pol'tta / Miyahara Kō <52843868+Komyyy@users.noreply.github.com> --- Mathlib/GroupTheory/Perm/Cycle/Basic.lean | 17 --- Mathlib/GroupTheory/Perm/Cycle/Factors.lean | 153 +++++++++++++------- 2 files changed, 97 insertions(+), 73 deletions(-) diff --git a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean index 27345289bc340..dd80ddc889ffc 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Basic.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Basic.lean @@ -5,7 +5,6 @@ Authors: Chris Hughes, Yaël Dillies -/ import Mathlib.Algebra.Module.BigOperators -import Mathlib.Data.List.Iterate import Mathlib.GroupTheory.Perm.Finite import Mathlib.GroupTheory.Perm.List @@ -193,10 +192,6 @@ theorem SameCycle.exists_pow_eq'' [Finite α] (h : SameCycle f x y) : rw [pow_orderOf_eq_one, pow_zero] · exact ⟨i.succ, i.zero_lt_succ, hi.le, by rfl⟩ -instance (f : Perm α) [DecidableRel (SameCycle f⁻¹)] : - DecidableRel (SameCycle f) := fun x y => - decidable_of_iff (f⁻¹.SameCycle x y) (sameCycle_inv) - instance (f : Perm α) [DecidableRel (SameCycle f)] : DecidableRel (SameCycle f⁻¹) := fun x y => decidable_of_iff (f.SameCycle x y) (sameCycle_inv).symm @@ -204,18 +199,6 @@ instance (f : Perm α) [DecidableRel (SameCycle f)] : instance (priority := 100) [DecidableEq α] : DecidableRel (SameCycle (1 : Perm α)) := fun x y => decidable_of_iff (x = y) sameCycle_one.symm -instance [Fintype α] [DecidableEq α] (f : Perm α) : DecidableRel (SameCycle f) := fun x y => - decidable_of_iff (y ∈ List.iterate f x (Fintype.card (Perm α))) <| by - simp only [List.mem_iterate, iterate_eq_pow, eq_comm (a := y)] - exact ⟨fun ⟨n, _, hn⟩ => ⟨n, hn⟩, fun ⟨i, hi⟩ => ⟨(i % orderOf f).natAbs, - Int.ofNat_lt.1 <| by - rw [Int.natAbs_of_nonneg (Int.emod_nonneg _ <| Int.natCast_ne_zero.2 (orderOf_pos _).ne')] - refine (Int.emod_lt _ <| Int.natCast_ne_zero_iff_pos.2 <| orderOf_pos _).trans_le ?_ - simp [orderOf_le_card_univ], - by - rw [← zpow_natCast, Int.natAbs_of_nonneg (Int.emod_nonneg _ <| - Int.natCast_ne_zero_iff_pos.2 <| orderOf_pos _), zpow_mod_orderOf, hi]⟩⟩ - end SameCycle /-! diff --git a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean index 542a4d867174a..516cc85380d9d 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Yaël Dillies -/ +import Mathlib.Data.List.Iterate import Mathlib.GroupTheory.Perm.Cycle.Basic /-! @@ -156,24 +157,6 @@ theorem isCycle_cycleOf (f : Perm α) [DecidableRel f.SameCycle] (hx : f x ≠ x rw [cycleOf_apply_of_not_sameCycle hxy] at h exact (h rfl).elim⟩ -@[simp] -theorem two_le_card_support_cycleOf_iff [DecidableEq α] [Fintype α] : - 2 ≤ #(cycleOf f x).support ↔ f x ≠ x := by - refine ⟨fun h => ?_, fun h => by simpa using (isCycle_cycleOf _ h).two_le_card_support⟩ - contrapose! h - rw [← cycleOf_eq_one_iff] at h - simp [h] - -@[simp] lemma support_cycleOf_nonempty [DecidableEq α] [Fintype α] : - (cycleOf f x).support.Nonempty ↔ f x ≠ x := by - rw [← two_le_card_support_cycleOf_iff, ← card_pos, ← Nat.succ_le_iff] - exact ⟨fun h => Or.resolve_left h.eq_or_lt (card_support_ne_one _).symm, zero_lt_two.trans_le⟩ - -@[deprecated support_cycleOf_nonempty (since := "2024-06-16")] -theorem card_support_cycleOf_pos_iff [DecidableEq α] [Fintype α] : - 0 < #(cycleOf f x).support ↔ f x ≠ x := by - rw [card_pos, support_cycleOf_nonempty] - theorem pow_mod_orderOf_cycleOf_apply (f : Perm α) [DecidableRel f.SameCycle] (n : ℕ) (x : α) : (f ^ (n % orderOf (cycleOf f x))) x = (f ^ n) x := by rw [← cycleOf_pow_apply_self f, ← cycleOf_pow_apply_self f, pow_mod_orderOf] @@ -199,18 +182,7 @@ theorem Disjoint.cycleOf_mul_distrib [DecidableRel f.SameCycle] [DecidableRel g. · simp [h.commute.eq, cycleOf_mul_of_apply_right_eq_self h.symm.commute, hfx] · simp [cycleOf_mul_of_apply_right_eq_self h.commute, hgx] -theorem support_cycleOf_eq_nil_iff [DecidableEq α] [Fintype α] : - (f.cycleOf x).support = ∅ ↔ x ∉ f.support := by simp - -theorem support_cycleOf_le [DecidableEq α] [Fintype α] (f : Perm α) (x : α) : - support (f.cycleOf x) ≤ support f := by - intro y hy - rw [mem_support, cycleOf_apply] at hy - split_ifs at hy - · exact mem_support.mpr hy - · exact absurd rfl hy - -theorem mem_support_cycleOf_iff [DecidableEq α] [Fintype α] : +private theorem mem_support_cycleOf_iff_aux [DecidableRel f.SameCycle] [DecidableEq α] [Fintype α] : y ∈ support (f.cycleOf x) ↔ SameCycle f x y ∧ x ∈ support f := by by_cases hx : f x = x · rw [(cycleOf_eq_one_iff _).mpr hx] @@ -223,21 +195,10 @@ theorem mem_support_cycleOf_iff [DecidableEq α] [Fintype α] : simpa using hx · simpa [hx] using hy -theorem mem_support_cycleOf_iff' (hx : f x ≠ x) [DecidableEq α] [Fintype α] : +private theorem mem_support_cycleOf_iff'_aux (hx : f x ≠ x) + [DecidableRel f.SameCycle] [DecidableEq α] [Fintype α] : y ∈ support (f.cycleOf x) ↔ SameCycle f x y := by - rw [mem_support_cycleOf_iff, and_iff_left (mem_support.2 hx)] - -theorem SameCycle.mem_support_iff {f} [DecidableEq α] [Fintype α] (h : SameCycle f x y) : - x ∈ support f ↔ y ∈ support f := - ⟨fun hx => support_cycleOf_le f x (mem_support_cycleOf_iff.mpr ⟨h, hx⟩), fun hy => - support_cycleOf_le f y (mem_support_cycleOf_iff.mpr ⟨h.symm, hy⟩)⟩ - -theorem pow_mod_card_support_cycleOf_self_apply [DecidableEq α] [Fintype α] - (f : Perm α) (n : ℕ) (x : α) : (f ^ (n % #(f.cycleOf x).support)) x = (f ^ n) x := by - by_cases hx : f x = x - · rw [pow_apply_eq_self_of_apply_eq_self hx, pow_apply_eq_self_of_apply_eq_self hx] - · rw [← cycleOf_pow_apply_self, ← cycleOf_pow_apply_self f, ← (isCycle_cycleOf f hx).orderOf, - pow_mod_orderOf] + rw [mem_support_cycleOf_iff_aux, and_iff_left (mem_support.2 hx)] /-- `x` is in the support of `f` iff `Equiv.Perm.cycle_of f x` is a cycle. -/ theorem isCycle_cycleOf_iff (f : Perm α) [DecidableRel f.SameCycle] : @@ -246,24 +207,104 @@ theorem isCycle_cycleOf_iff (f : Perm α) [DecidableRel f.SameCycle] : rw [Ne, ← cycleOf_eq_one_iff f] exact hx.ne_one -theorem isCycleOn_support_cycleOf [DecidableEq α] [Fintype α] (f : Perm α) (x : α) : - f.IsCycleOn (f.cycleOf x).support := +private theorem isCycleOn_support_cycleOf_aux [DecidableEq α] [Fintype α] (f : Perm α) + [DecidableRel f.SameCycle] (x : α) : f.IsCycleOn (f.cycleOf x).support := ⟨f.bijOn <| by - refine fun _ ↦ ⟨fun h ↦ mem_support_cycleOf_iff.2 ?_, fun h ↦ mem_support_cycleOf_iff.2 ?_⟩ - · exact ⟨sameCycle_apply_right.1 (mem_support_cycleOf_iff.1 h).1, - (mem_support_cycleOf_iff.1 h).2⟩ - · exact ⟨sameCycle_apply_right.2 (mem_support_cycleOf_iff.1 h).1, - (mem_support_cycleOf_iff.1 h).2⟩ + refine fun _ ↦ + ⟨fun h ↦ mem_support_cycleOf_iff_aux.2 ?_, fun h ↦ mem_support_cycleOf_iff_aux.2 ?_⟩ + · exact ⟨sameCycle_apply_right.1 (mem_support_cycleOf_iff_aux.1 h).1, + (mem_support_cycleOf_iff_aux.1 h).2⟩ + · exact ⟨sameCycle_apply_right.2 (mem_support_cycleOf_iff_aux.1 h).1, + (mem_support_cycleOf_iff_aux.1 h).2⟩ , fun a ha b hb => by - rw [mem_coe, mem_support_cycleOf_iff] at ha hb + rw [mem_coe, mem_support_cycleOf_iff_aux] at ha hb exact ha.1.symm.trans hb.1⟩ -theorem SameCycle.exists_pow_eq_of_mem_support {f} [DecidableEq α] [Fintype α] (h : SameCycle f x y) - (hx : x ∈ f.support) : ∃ i < #(f.cycleOf x).support, (f ^ i) x = y := by +private theorem SameCycle.exists_pow_eq_of_mem_support_aux {f} [DecidableEq α] [Fintype α] + [DecidableRel f.SameCycle] (h : SameCycle f x y) (hx : x ∈ f.support) : + ∃ i < #(f.cycleOf x).support, (f ^ i) x = y := by rw [mem_support] at hx - exact Equiv.Perm.IsCycleOn.exists_pow_eq (b := y) (f.isCycleOn_support_cycleOf x) - (by rw [mem_support_cycleOf_iff' hx]) (by rwa [mem_support_cycleOf_iff' hx]) + exact Equiv.Perm.IsCycleOn.exists_pow_eq (b := y) (f.isCycleOn_support_cycleOf_aux x) + (by rw [mem_support_cycleOf_iff'_aux hx]) (by rwa [mem_support_cycleOf_iff'_aux hx]) + +instance instDecidableRelSameCycle [DecidableEq α] [Fintype α] (f : Perm α) : + DecidableRel (SameCycle f) := fun x y => + decidable_of_iff (y ∈ List.iterate f x (Fintype.card α)) <| by + simp only [List.mem_iterate, iterate_eq_pow, eq_comm (a := y)] + constructor + · rintro ⟨n, _, hn⟩ + exact ⟨n, hn⟩ + · intro hxy + by_cases hx : x ∈ f.support + case pos => + -- we can't invoke the aux lemmas above without obtaining the decidable instance we are + -- already building; but now we've left the data, so we can do this non-constructively + -- without sacrificing computability. + let _inst (f : Perm α) : DecidableRel (SameCycle f) := Classical.decRel _ + rcases hxy.exists_pow_eq_of_mem_support_aux hx with ⟨i, hixy, hi⟩ + refine ⟨i, lt_of_lt_of_le hixy (card_le_univ _), hi⟩ + case neg => + haveI : Nonempty α := ⟨x⟩ + rw [not_mem_support] at hx + exact ⟨0, Fintype.card_pos, hxy.eq_of_left hx⟩ + +@[simp] +theorem two_le_card_support_cycleOf_iff [DecidableEq α] [Fintype α] : + 2 ≤ #(cycleOf f x).support ↔ f x ≠ x := by + refine ⟨fun h => ?_, fun h => by simpa using (isCycle_cycleOf _ h).two_le_card_support⟩ + contrapose! h + rw [← cycleOf_eq_one_iff] at h + simp [h] + +@[simp] lemma support_cycleOf_nonempty [DecidableEq α] [Fintype α] : + (cycleOf f x).support.Nonempty ↔ f x ≠ x := by + rw [← two_le_card_support_cycleOf_iff, ← card_pos, ← Nat.succ_le_iff] + exact ⟨fun h => Or.resolve_left h.eq_or_lt (card_support_ne_one _).symm, zero_lt_two.trans_le⟩ + +@[deprecated support_cycleOf_nonempty (since := "2024-06-16")] +theorem card_support_cycleOf_pos_iff [DecidableEq α] [Fintype α] : + 0 < #(cycleOf f x).support ↔ f x ≠ x := by + rw [card_pos, support_cycleOf_nonempty] + +theorem mem_support_cycleOf_iff [DecidableEq α] [Fintype α] : + y ∈ support (f.cycleOf x) ↔ SameCycle f x y ∧ x ∈ support f := + mem_support_cycleOf_iff_aux + +theorem mem_support_cycleOf_iff' (hx : f x ≠ x) [DecidableEq α] [Fintype α] : + y ∈ support (f.cycleOf x) ↔ SameCycle f x y := + mem_support_cycleOf_iff'_aux hx + +theorem support_cycleOf_eq_nil_iff [DecidableEq α] [Fintype α] : + (f.cycleOf x).support = ∅ ↔ x ∉ f.support := by simp + +theorem isCycleOn_support_cycleOf [DecidableEq α] [Fintype α] (f : Perm α) (x : α) : + f.IsCycleOn (f.cycleOf x).support := + isCycleOn_support_cycleOf_aux f x + +theorem SameCycle.exists_pow_eq_of_mem_support {f} [DecidableEq α] [Fintype α] (h : SameCycle f x y) + (hx : x ∈ f.support) : ∃ i < #(f.cycleOf x).support, (f ^ i) x = y := + h.exists_pow_eq_of_mem_support_aux hx + +theorem support_cycleOf_le [DecidableEq α] [Fintype α] (f : Perm α) (x : α) : + support (f.cycleOf x) ≤ support f := by + intro y hy + rw [mem_support, cycleOf_apply] at hy + split_ifs at hy + · exact mem_support.mpr hy + · exact absurd rfl hy + +theorem SameCycle.mem_support_iff {f} [DecidableEq α] [Fintype α] (h : SameCycle f x y) : + x ∈ support f ↔ y ∈ support f := + ⟨fun hx => support_cycleOf_le f x (mem_support_cycleOf_iff.mpr ⟨h, hx⟩), fun hy => + support_cycleOf_le f y (mem_support_cycleOf_iff.mpr ⟨h.symm, hy⟩)⟩ + +theorem pow_mod_card_support_cycleOf_self_apply [DecidableEq α] [Fintype α] + (f : Perm α) (n : ℕ) (x : α) : (f ^ (n % #(f.cycleOf x).support)) x = (f ^ n) x := by + by_cases hx : f x = x + · rw [pow_apply_eq_self_of_apply_eq_self hx, pow_apply_eq_self_of_apply_eq_self hx] + · rw [← cycleOf_pow_apply_self, ← cycleOf_pow_apply_self f, ← (isCycle_cycleOf f hx).orderOf, + pow_mod_orderOf] theorem SameCycle.exists_pow_eq [DecidableEq α] [Fintype α] (f : Perm α) (h : SameCycle f x y) : ∃ i : ℕ, 0 < i ∧ i ≤ #(f.cycleOf x).support + 1 ∧ (f ^ i) x = y := by From 3b7a6cf6913b32f057ab13361da0624ad77e0690 Mon Sep 17 00:00:00 2001 From: Jiang Jiedong Date: Sat, 25 Jan 2025 05:26:10 +0000 Subject: [PATCH 498/681] feat(Topology/Algebra/Field): `ContinuousSMul` for intermediate fields (#18142) If `M` is an intermediate field between field extension `L/K`, then `M` acts continuously on `L` and bot act continuously on `M`. The `M` acts continuously on `L` part is proved in a more general setup. --- Mathlib.lean | 1 + Mathlib/Topology/Algebra/Algebra.lean | 4 +++ Mathlib/Topology/Algebra/Field.lean | 10 +++++++ .../Topology/Algebra/IntermediateField.lean | 29 +++++++++++++++++++ Mathlib/Topology/Algebra/Ring/Basic.lean | 8 +++++ 5 files changed, 52 insertions(+) create mode 100644 Mathlib/Topology/Algebra/IntermediateField.lean diff --git a/Mathlib.lean b/Mathlib.lean index b5d5e1fd3dbfc..0cee4b9954dac 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5192,6 +5192,7 @@ import Mathlib.Topology.Algebra.InfiniteSum.Nonarchimedean import Mathlib.Topology.Algebra.InfiniteSum.Order import Mathlib.Topology.Algebra.InfiniteSum.Real import Mathlib.Topology.Algebra.InfiniteSum.Ring +import Mathlib.Topology.Algebra.IntermediateField import Mathlib.Topology.Algebra.LinearTopology import Mathlib.Topology.Algebra.Localization import Mathlib.Topology.Algebra.Module.Alternating.Basic diff --git a/Mathlib/Topology/Algebra/Algebra.lean b/Mathlib/Topology/Algebra/Algebra.lean index c014fccd8e079..0fbeb2410e869 100644 --- a/Mathlib/Topology/Algebra/Algebra.lean +++ b/Mathlib/Topology/Algebra/Algebra.lean @@ -52,6 +52,10 @@ theorem continuousSMul_of_algebraMap [TopologicalSemiring A] (h : Continuous (al ContinuousSMul R A := ⟨(continuous_algebraMap_iff_smul R A).1 h⟩ +instance Subalgebra.continuousSMul (S : Subalgebra R A) (X) [TopologicalSpace X] [MulAction A X] + [ContinuousSMul A X] : ContinuousSMul S X := + Subsemiring.continuousSMul S.toSubsemiring X + section variable [ContinuousSMul R A] diff --git a/Mathlib/Topology/Algebra/Field.lean b/Mathlib/Topology/Algebra/Field.lean index cce773d29a6f3..0181efb391afb 100644 --- a/Mathlib/Topology/Algebra/Field.lean +++ b/Mathlib/Topology/Algebra/Field.lean @@ -178,3 +178,13 @@ theorem IsPreconnected.eq_of_sq_eq [Field 𝕜] [HasContinuousInv₀ 𝕜] [Cont (iff_of_eq (iff_false _)).2 (hg_ne _)] at hy' ⊢ <;> assumption end Preconnected + +section ContinuousSMul + +variable {F : Type*} [DivisionRing F] [TopologicalSpace F] [TopologicalRing F] + (X : Type*) [TopologicalSpace X] [MulAction F X] [ContinuousSMul F X] + +instance Subfield.continuousSMul (M : Subfield F) : ContinuousSMul M X := + Subring.continuousSMul M.toSubring X + +end ContinuousSMul diff --git a/Mathlib/Topology/Algebra/IntermediateField.lean b/Mathlib/Topology/Algebra/IntermediateField.lean new file mode 100644 index 0000000000000..17651f34142f9 --- /dev/null +++ b/Mathlib/Topology/Algebra/IntermediateField.lean @@ -0,0 +1,29 @@ +/- +Copyright (c) 2024 Jiedong Jiang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jiedong Jiang +-/ +import Mathlib.FieldTheory.IntermediateField.Adjoin.Defs +import Mathlib.Topology.Algebra.Field + +/-! +# Continuous actions related to intermediate fields + +In this file we define the instances related to continuous actions of +intermediate fields. The topology on intermediate fields is already defined +in earlier file `Mathlib.Topology.Algebra.Field` as the subspace topology. +-/ + +variable {K L : Type*} [Field K] [Field L] [Algebra K L] + [TopologicalSpace L] [TopologicalRing L] + +variable (X : Type*) [TopologicalSpace X] [MulAction L X] [ContinuousSMul L X] +variable (M : IntermediateField K L) + +instance IntermediateField.continuousSMul (M : IntermediateField K L) : ContinuousSMul M X := + M.toSubfield.continuousSMul X + +instance IntermediateField.botContinuousSMul (M : IntermediateField K L) : + ContinuousSMul (⊥ : IntermediateField K L) M := + Topology.IsInducing.continuousSMul (X := L) (N := (⊥ : IntermediateField K L)) (Y := M) + (M := (⊥ : IntermediateField K L)) Topology.IsInducing.subtypeVal continuous_id rfl diff --git a/Mathlib/Topology/Algebra/Ring/Basic.lean b/Mathlib/Topology/Algebra/Ring/Basic.lean index f565a4012f388..613f1181d73b9 100644 --- a/Mathlib/Topology/Algebra/Ring/Basic.lean +++ b/Mathlib/Topology/Algebra/Ring/Basic.lean @@ -130,6 +130,10 @@ namespace Subsemiring instance topologicalSemiring (S : Subsemiring α) : TopologicalSemiring S := { S.toSubmonoid.continuousMul, S.toAddSubmonoid.continuousAdd with } +instance continuousSMul (s : Subsemiring α) (X) [TopologicalSpace X] [MulAction α X] + [ContinuousSMul α X] : ContinuousSMul s X := + Submonoid.continuousSMul + end Subsemiring /-- The (topological-space) closure of a subsemiring of a topological semiring is @@ -308,6 +312,10 @@ variable [Ring α] [TopologicalRing α] instance Subring.instTopologicalRing (S : Subring α) : TopologicalRing S := { S.toSubmonoid.continuousMul, inferInstanceAs (TopologicalAddGroup S.toAddSubgroup) with } +instance Subring.continuousSMul (s : Subring α) (X) [TopologicalSpace X] [MulAction α X] + [ContinuousSMul α X] : ContinuousSMul s X := + Subsemiring.continuousSMul s.toSubsemiring X + /-- The (topological-space) closure of a subring of a topological ring is itself a subring. -/ def Subring.topologicalClosure (S : Subring α) : Subring α := From 3a62ce8338d097fae0ca5d017687cc7d74645397 Mon Sep 17 00:00:00 2001 From: D-Thomine <100795491+D-Thomine@users.noreply.github.com> Date: Sat, 25 Jan 2025 05:58:09 +0000 Subject: [PATCH 499/681] feat(Data.Real.EReal): add lemmas about division (#20293) A few more lemmas about division and order/distributivity in EReal. --- Mathlib/Data/Real/EReal.lean | 52 +++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/Mathlib/Data/Real/EReal.lean b/Mathlib/Data/Real/EReal.lean index eb40ab8dbcdd0..17c70dbd11726 100644 --- a/Mathlib/Data/Real/EReal.lean +++ b/Mathlib/Data/Real/EReal.lean @@ -1863,24 +1863,36 @@ lemma sign_mul_inv_abs' (a : EReal) : (sign a) * ((a.abs⁻¹ : ℝ≥0∞) : ER /-! #### Inversion and Positivity -/ +lemma bot_lt_inv (x : EReal) : ⊥ < x⁻¹ := by + cases x with + | h_bot => exact inv_bot ▸ bot_lt_zero + | h_top => exact EReal.inv_top ▸ bot_lt_zero + | h_real x => exact (coe_inv x).symm ▸ bot_lt_coe (x⁻¹) + +lemma inv_lt_top (x : EReal) : x⁻¹ < ⊤ := by + cases x with + | h_bot => exact inv_bot ▸ zero_lt_top + | h_top => exact EReal.inv_top ▸ zero_lt_top + | h_real x => exact (coe_inv x).symm ▸ coe_lt_top (x⁻¹) + lemma inv_nonneg_of_nonneg {a : EReal} (h : 0 ≤ a) : 0 ≤ a⁻¹ := by - induction a with + cases a with | h_bot | h_top => simp | h_real a => rw [← coe_inv a, EReal.coe_nonneg, inv_nonneg]; exact EReal.coe_nonneg.1 h lemma inv_nonpos_of_nonpos {a : EReal} (h : a ≤ 0) : a⁻¹ ≤ 0 := by - induction a with + cases a with | h_bot | h_top => simp | h_real a => rw [← coe_inv a, EReal.coe_nonpos, inv_nonpos]; exact EReal.coe_nonpos.1 h lemma inv_pos_of_pos_ne_top {a : EReal} (h : 0 < a) (h' : a ≠ ⊤) : 0 < a⁻¹ := by - induction a with + cases a with | h_bot => exact (not_lt_bot h).rec | h_real a => rw [← coe_inv a]; norm_cast at *; exact inv_pos_of_pos h | h_top => exact (h' (Eq.refl ⊤)).rec lemma inv_neg_of_neg_ne_bot {a : EReal} (h : a < 0) (h' : a ≠ ⊥) : a⁻¹ < 0 := by - induction a with + cases a with | h_bot => exact (h' (Eq.refl ⊥)).rec | h_real a => rw [← coe_inv a]; norm_cast at *; exact inv_lt_zero.2 h | h_top => exact (not_top_lt h).rec @@ -1956,11 +1968,11 @@ lemma mul_div_mul_cancel {a b c : EReal} (h₁ : c ≠ ⊥) (h₂ : c ≠ ⊤) ( congr exact mul_div_cancel h₁ h₂ h₃ -/-! #### Division Distributivity -/ - -lemma div_right_distrib_of_nonneg {a b c : EReal} (h : 0 ≤ a) (h' : 0 ≤ b) : - (a + b) / c = (a / c) + (b / c) := - EReal.right_distrib_of_nonneg h h' +lemma div_eq_iff {a b c : EReal} (hbot : b ≠ ⊥) (htop : b ≠ ⊤) (hzero : b ≠ 0) : + c / b = a ↔ c = a * b := by + refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ + · rw [← @mul_div_cancel c b hbot htop hzero, h, mul_comm a b] + · rw [h, mul_comm a b, ← mul_div b a b, @mul_div_cancel a b hbot htop hzero] /-! #### Division and Order -/ @@ -2022,6 +2034,18 @@ lemma div_le_iff_le_mul {a b c : EReal} (h : 0 < b) (h' : b ≠ ⊤) : rw [mul_div b c b, mul_comm b] exact StrictMono.le_iff_le (strictMono_div_right_of_pos h h') +lemma lt_div_iff {a b c : EReal} (h : 0 < b) (h' : b ≠ ⊤) : + a < c / b ↔ a * b < c := by + nth_rw 1 [← @mul_div_cancel a b (ne_bot_of_gt h) h' (ne_of_gt h)] + rw [EReal.mul_div b a b, mul_comm a b] + exact (strictMono_div_right_of_pos h h').lt_iff_lt + +lemma div_lt_iff {a b c : EReal} (h : 0 < b) (h' : b ≠ ⊤) : + c / b < a ↔ c < a * b := by + nth_rw 1 [← @mul_div_cancel a b (ne_bot_of_gt h) h' (ne_of_gt h)] + rw [EReal.mul_div b a b, mul_comm a b] + exact (strictMono_div_right_of_pos h h').lt_iff_lt + lemma div_nonneg {a b : EReal} (h : 0 ≤ a) (h' : 0 ≤ b) : 0 ≤ a / b := mul_nonneg h (inv_nonneg_of_nonneg h') @@ -2034,6 +2058,16 @@ lemma div_nonpos_of_nonneg_of_nonpos {a b : EReal} (h : 0 ≤ a) (h' : b ≤ 0) lemma div_nonneg_of_nonpos_of_nonpos {a b : EReal} (h : a ≤ 0) (h' : b ≤ 0) : 0 ≤ a / b := le_of_eq_of_le (Eq.symm zero_div) (div_le_div_right_of_nonpos h' h) +/-! #### Division Distributivity -/ + +lemma div_right_distrib_of_nonneg {a b c : EReal} (h : 0 ≤ a) (h' : 0 ≤ b) : + (a + b) / c = (a / c) + (b / c) := + EReal.right_distrib_of_nonneg h h' + +lemma add_div_of_nonneg_right {a b c : EReal} (h : 0 ≤ c) : + (a + b) / c = a / c + b / c := by + apply right_distrib_of_nonneg_of_ne_top (inv_nonneg_of_nonneg h) (inv_lt_top c).ne + end EReal -- Porting note(https://github.com/leanprover-community/mathlib4/issues/6038): restore From 62560ab2e5a9f5c6f65ad32083c84cf2027c6b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Sat, 25 Jan 2025 06:17:41 +0000 Subject: [PATCH 500/681] feat: two Finset lemmas (#15294) Add `prod_image_of_disjoint` (and the `to_additive` version `sum_image_of_disjoint`) and `sUnion_disjiUnion` Co-authored-by: pfaffelh Co-authored-by: Eric Wieser Co-authored-by: Remy Degenne Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> --- .../BigOperators/Group/Finset/Basic.lean | 44 +++++++++++++++++++ Mathlib/Data/Finset/Union.lean | 7 +++ 2 files changed, 51 insertions(+) diff --git a/Mathlib/Algebra/BigOperators/Group/Finset/Basic.lean b/Mathlib/Algebra/BigOperators/Group/Finset/Basic.lean index a83b1bce754f2..795c3077f3dde 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset/Basic.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset/Basic.lean @@ -1434,6 +1434,50 @@ theorem prod_unique_nonempty {α β : Type*} [CommMonoid β] [Unique α] (s : Fi (h : s.Nonempty) : ∏ x ∈ s, f x = f default := by rw [h.eq_singleton_default, Finset.prod_singleton] +section Image_Overlap + +variable {α β ι : Type*} [DecidableEq ι] [DecidableEq α] + +@[to_additive] +lemma prod_filter_of_pairwise_eq_one [CommMonoid β] {f : ι → α} {g : α → β} {n : ι} {I : Finset ι} + (hn : n ∈ I) (hf : (I : Set ι).Pairwise fun i j ↦ f i = f j → g (f i) = 1) : + ∏ j ∈ filter (fun j ↦ f j = f n) I, g (f j) = g (f n) := by + have h j (hj : j ∈ (filter (fun i ↦ f i = f n) I).erase n) : g (f j) = 1 := by + simp only [mem_erase, mem_filter] at hj + exact hf hj.2.1 hn hj.1 hj.2.2 + rw [← mul_one (g (f n)), ← prod_eq_one h, + ← mul_prod_erase (filter (f · = f n) I) (fun i ↦ g (f i)) <| mem_filter.mpr ⟨hn, by rfl⟩] + +/-- A version of `Finset.prod_map` and `Finset.prod_image`, but we do not assume that `f` is +injective. Rather, we assume that the image of `f` on `I` only overlaps where `g (f i) = 1`. +The conclusion is the same as in `prod_image`.-/ +@[to_additive (attr := simp) +"A version of `Finset.sum_map` and `Finset.sum_image`, but we do not assume that `f` is +injective. Rather, we assume that the image of `f` on `I` only overlaps where `g (f i) = 0`. +The conclusion is the same as in `sum_image`."] +lemma prod_image_of_pairwise_eq_one [CommMonoid β] {f : ι → α} {g : α → β} {I : Finset ι} + (hf : (I : Set ι).Pairwise fun i j ↦ f i = f j → g (f i) = 1) : + ∏ s in I.image f, g s = ∏ i in I, g (f i) := by + rw [prod_image'] + exact fun n hnI => (prod_filter_of_pairwise_eq_one hnI hf).symm + +/-- A version of `Finset.prod_map` and `Finset.prod_image`, but we do not assume that `f` is +injective. Rather, we assume that the images of `f` are disjoint on `I`, and `g ⊥ = 1`. The +conclusion is the same as in `prod_image`.-/ +@[to_additive (attr := simp) +"A version of `Finset.sum_map` and `Finset.sum_image`, but we do not assume that `f` is +injective. Rather, we assume that the images of `f` are disjoint on `I`, and `g ⊥ = 0`. The +conclusion is the same as in `sum_image`." +] +lemma prod_image_of_disjoint [CommMonoid β] [PartialOrder α] [OrderBot α] {f : ι → α} {g : α → β} + (hg_bot : g ⊥ = 1) {I : Finset ι} (hf_disj : (I : Set ι).PairwiseDisjoint f) : + ∏ s in I.image f, g s = ∏ i in I, g (f i) := by + refine prod_image_of_pairwise_eq_one <| hf_disj.imp fun i j (hdisj : Disjoint _ _) hfij ↦ ?_ + rw [← hfij, disjoint_self] at hdisj + rw [hdisj, hg_bot] + +end Image_Overlap + end Finset namespace Fintype diff --git a/Mathlib/Data/Finset/Union.lean b/Mathlib/Data/Finset/Union.lean index c3312418518bf..e457938f87ae0 100644 --- a/Mathlib/Data/Finset/Union.lean +++ b/Mathlib/Data/Finset/Union.lean @@ -81,6 +81,13 @@ lemma disjiUnion_disjiUnion (s : Finset α) (f : α → Finset β) (g : β → F exact disjoint_left.mp (h1 a.prop b.prop <| Subtype.coe_injective.ne hab) hfa hfb := eq_of_veq <| Multiset.bind_assoc.trans (Multiset.attach_bind_coe _ _).symm +lemma sUnion_disjiUnion {f : α → Finset (Set β)} (I : Finset α) + (hf : (I : Set α).PairwiseDisjoint f) : + ⋃₀ (I.disjiUnion f hf : Set (Set β)) = ⋃ a ∈ I, ⋃₀ ↑(f a) := by + ext + simp only [coe_disjiUnion, Set.mem_sUnion, Set.mem_iUnion, mem_coe, exists_prop] + tauto + variable [DecidableEq β] {s : Finset α} {t : Finset β} {f : α → β} private lemma pairwiseDisjoint_fibers : Set.PairwiseDisjoint ↑t fun a ↦ s.filter (f · = a) := From 7e84e12889da8039230f568319b165ac8692a518 Mon Sep 17 00:00:00 2001 From: Jujian Zhang Date: Sat, 25 Jan 2025 06:17:42 +0000 Subject: [PATCH 501/681] feat(Algebra/Subalgebra): some lemmas about centralizers (#18764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let `R` be a commutative ring and `A` and `B` two `R`-algebras. - `Subalgebra.centralizer_sup`: if `S` and `T` are subalgebras of `A`, then the centralizer of `S ⊔ T` is the intersection of the centralizer of `S` and the centralizer of `T`. - `Subalgebra.centralizer_range_includeLeft_eq_center_tensorProduct`: if `B` is free as a module, then the centralizer of `A` in `A ⊗ B` is `C(A) ⊗ B` where `C(A)` is the center of `A`. - `Subalgebra.centralizer_range_includeRight_eq_center_tensorProduct`: if `A` is free as a module, then the centralizer of `B` in `A ⊗ B` is `A ⊗ C(B)` where `C(B)` is the center of `B`. Co-authored-by: zjj Co-authored-by: Junyan Xu --- Mathlib.lean | 1 + Mathlib/Algebra/Algebra/Hom.lean | 7 +- Mathlib/Algebra/Algebra/Subalgebra/Basic.lean | 40 ++++ .../Algebra/Subalgebra/Centralizer.lean | 197 ++++++++++++++++++ Mathlib/RingTheory/TensorProduct/Basic.lean | 18 ++ 5 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 Mathlib/Algebra/Algebra/Subalgebra/Centralizer.lean diff --git a/Mathlib.lean b/Mathlib.lean index 0cee4b9954dac..35a8f159abfea 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -20,6 +20,7 @@ import Mathlib.Algebra.Algebra.Rat import Mathlib.Algebra.Algebra.RestrictScalars import Mathlib.Algebra.Algebra.Spectrum import Mathlib.Algebra.Algebra.Subalgebra.Basic +import Mathlib.Algebra.Algebra.Subalgebra.Centralizer import Mathlib.Algebra.Algebra.Subalgebra.Directed import Mathlib.Algebra.Algebra.Subalgebra.IsSimpleOrder import Mathlib.Algebra.Algebra.Subalgebra.MulOpposite diff --git a/Mathlib/Algebra/Algebra/Hom.lean b/Mathlib/Algebra/Algebra/Hom.lean index 92862f9a814cd..355643e02267e 100644 --- a/Mathlib/Algebra/Algebra/Hom.lean +++ b/Mathlib/Algebra/Algebra/Hom.lean @@ -413,8 +413,8 @@ end RingHom namespace Algebra -variable (R : Type u) (A : Type v) -variable [CommSemiring R] [Semiring A] [Algebra R A] +variable (R : Type u) (A : Type v) (B : Type w) +variable [CommSemiring R] [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] /-- `AlgebraMap` as an `AlgHom`. -/ def ofId : R →ₐ[R] A := @@ -433,6 +433,9 @@ instance subsingleton_id : Subsingleton (R →ₐ[R] A) := @[ext high] theorem ext_id (f g : R →ₐ[R] A) : f = g := Subsingleton.elim _ _ +@[simp] +theorem comp_ofId (φ : A →ₐ[R] B) : φ.comp (Algebra.ofId R A) = Algebra.ofId R B := by ext + section MulDistribMulAction instance : MulDistribMulAction (A →ₐ[R] A) Aˣ where diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index 15b381c605224..64279f792eac2 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -766,6 +766,43 @@ theorem iSup_toSubsemiring {ι : Sort*} [Nonempty ι] (S : ι → Subalgebra R A (iSup S).toSubsemiring = ⨆ i, (S i).toSubsemiring := by simp only [iSup, Set.range_nonempty, sSup_toSubsemiring, ← Set.range_comp, Function.comp_def] +lemma mem_iSup_of_mem {ι : Sort*} {S : ι → Subalgebra R A} (i : ι) {x : A} (hx : x ∈ S i) : + x ∈ iSup S := + le_iSup S i hx + +@[elab_as_elim] +lemma iSup_induction {ι : Sort*} (S : ι → Subalgebra R A) {motive : A → Prop} + {x : A} (mem : x ∈ ⨆ i, S i) + (basic : ∀ i, ∀ a ∈ S i, motive a) + (zero : motive 0) (one : motive 1) + (add : ∀ a b, motive a → motive b → motive (a + b)) + (mul : ∀ a b, motive a → motive b → motive (a * b)) + (algebraMap : ∀ r, motive (algebraMap R A r)) : motive x := by + let T : Subalgebra R A := + { carrier := {x | motive x} + mul_mem' {a b} := mul a b + one_mem' := one + add_mem' {a b} := add a b + zero_mem' := zero + algebraMap_mem' := algebraMap } + suffices iSup S ≤ T from this mem + rwa [iSup_le_iff] + +/-- A dependent version of `Subalgebra.iSup_induction`. -/ +@[elab_as_elim] +theorem iSup_induction' {ι : Sort*} (S : ι → Subalgebra R A) {motive : ∀ x, (x ∈ ⨆ i, S i) → Prop} + {x : A} (mem : x ∈ ⨆ i, S i) + (basic : ∀ (i) (x) (hx : x ∈ S i), motive x (mem_iSup_of_mem i hx)) + (zero : motive 0 (zero_mem _)) (one : motive 1 (one_mem _)) + (add : ∀ x y hx hy, motive x hx → motive y hy → motive (x + y) (add_mem ‹_› ‹_›)) + (mul : ∀ x y hx hy, motive x hx → motive y hy → motive (x * y) (mul_mem ‹_› ‹_›)) + (algebraMap : ∀ r, motive (algebraMap R A r) (Subalgebra.algebraMap_mem _ ‹_›)) : + motive x mem := by + refine Exists.elim ?_ fun (hx : x ∈ ⨆ i, S i) (hc : motive x hx) ↦ hc + exact iSup_induction S (motive := fun x' ↦ ∃ h, motive x' h) mem + (fun _ _ h ↦ ⟨_, basic _ _ h⟩) ⟨_, zero⟩ ⟨_, one⟩ (fun _ _ h h' ↦ ⟨_, add _ _ _ _ h.2 h'.2⟩) + (fun _ _ h h' ↦ ⟨_, mul _ _ _ _ h.2 h'.2⟩) fun _ ↦ ⟨_, algebraMap _⟩ + instance : Inhabited (Subalgebra R A) := ⟨⊥⟩ theorem mem_bot {x : A} : x ∈ (⊥ : Subalgebra R A) ↔ x ∈ Set.range (algebraMap R A) := Iff.rfl @@ -787,6 +824,9 @@ theorem _root_.AlgHom.range_eq_top (f : A →ₐ[R] B) : @[deprecated (since := "2024-11-11")] alias range_top_iff_surjective := AlgHom.range_eq_top +@[simp] +theorem range_ofId : (Algebra.ofId R A).range = ⊥ := rfl + @[simp] theorem range_id : (AlgHom.id R A).range = ⊤ := SetLike.coe_injective Set.range_id diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Centralizer.lean b/Mathlib/Algebra/Algebra/Subalgebra/Centralizer.lean new file mode 100644 index 0000000000000..500bc456f934d --- /dev/null +++ b/Mathlib/Algebra/Algebra/Subalgebra/Centralizer.lean @@ -0,0 +1,197 @@ +/- +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.Algebra.Algebra.Subalgebra.Basic +import Mathlib.RingTheory.TensorProduct.Basic +import Mathlib.RingTheory.Adjoin.Basic +import Mathlib.LinearAlgebra.TensorProduct.Basis +import Mathlib.LinearAlgebra.FreeModule.Basic + +/-! +# Properties of centers and centralizers + +This file contains theorems about the center and centralizer of a subalgebra. + +## Main results + +Let `R` be a commutative ring and `A` and `B` two `R`-algebras. +- `Subalgebra.centralizer_sup`: if `S` and `T` are subalgebras of `A`, then the centralizer of + `S ⊔ T` is the intersection of the centralizer of `S` and the centralizer of `T`. +- `Subalgebra.centralizer_range_includeLeft_eq_center_tensorProduct`: if `B` is free as a module, + then the centralizer of `A ⊗ 1` in `A ⊗ B` is `C(A) ⊗ B` where `C(A)` is the center of `A`. +- `Subalgebra.centralizer_range_includeRight_eq_center_tensorProduct`: if `A` is free as a module, + then the centralizer of `1 ⊗ B` in `A ⊗ B` is `A ⊗ C(B)` where `C(B)` is the center of `B`. +-/ + +namespace Subalgebra + +open Algebra.TensorProduct + +section CommSemiring + +variable {R : Type*} [CommSemiring R] +variable {A : Type*} [Semiring A] [Algebra R A] + +lemma le_centralizer_iff (S T : Subalgebra R A) : S ≤ centralizer R T ↔ T ≤ centralizer R S := + ⟨fun h t ht _ hs ↦ (h hs t ht).symm, fun h s hs _ ht ↦ (h ht s hs).symm⟩ + +lemma centralizer_coe_sup (S T : Subalgebra R A) : + centralizer R ((S ⊔ T : Subalgebra R A) : Set A) = centralizer R S ⊓ centralizer R T := + eq_of_forall_le_iff fun K ↦ by + simp_rw [le_centralizer_iff, sup_le_iff, le_inf_iff, K.le_centralizer_iff] + +lemma centralizer_coe_iSup {ι : Sort*} (S : ι → Subalgebra R A) : + centralizer R ((⨆ i, S i : Subalgebra R A) : Set A) = ⨅ i, centralizer R (S i) := + eq_of_forall_le_iff fun K ↦ by + simp_rw [le_centralizer_iff, iSup_le_iff, le_iInf_iff, K.le_centralizer_iff] + +end CommSemiring + +section Free + +variable (R : Type*) [CommSemiring R] +variable (A : Type*) [Semiring A] [Algebra R A] +variable (B : Type*) [Semiring B] [Algebra R B] + +open Finsupp TensorProduct + +/-- +Let `R` be a commutative ring and `A, B` be `R`-algebras where `B` is free as `R`-module. +For any subset `S ⊆ A`, the centralizer of `S ⊗ 1 ⊆ A ⊗ B` is `C_A(S) ⊗ B` where `C_A(S)` is the +centralizer of `S` in `A`. +-/ +lemma centralizer_coe_image_includeLeft_eq_center_tensorProduct + (S : Set A) [Module.Free R B] : + Subalgebra.centralizer R + (Algebra.TensorProduct.includeLeft (S := R) '' S) = + (Algebra.TensorProduct.map (Subalgebra.centralizer R (S : Set A)).val + (AlgHom.id R B)).range := by + classical + ext w + constructor + · intro hw + rw [mem_centralizer_iff] at hw + let ℬ := Module.Free.chooseBasis R B + obtain ⟨b, rfl⟩ := TensorProduct.eq_repr_basis_right ℬ w + refine Subalgebra.sum_mem _ fun j hj => ⟨⟨b j, ?_⟩ ⊗ₜ[R] ℬ j, by simp⟩ + rw [Subalgebra.mem_centralizer_iff] + intro x hx + suffices x • b = b.mapRange (· * x) (by simp) from Finsupp.ext_iff.1 this j + specialize hw (x ⊗ₜ[R] 1) ⟨x, hx, rfl⟩ + simp only [Finsupp.sum, Finset.mul_sum, Algebra.TensorProduct.tmul_mul_tmul, one_mul, + Finset.sum_mul, mul_one] at hw + refine TensorProduct.sum_tmul_basis_right_injective ℬ ?_ + simp only [Finsupp.coe_lsum] + rw [sum_of_support_subset (s := b.support) (hs := Finsupp.support_smul) (h := by aesop), + sum_of_support_subset (s := b.support) (hs := support_mapRange) (h := by aesop)] + simpa only [Finsupp.coe_smul, Pi.smul_apply, smul_eq_mul, LinearMap.flip_apply, + TensorProduct.mk_apply, Finsupp.mapRange_apply] using hw + + · rintro ⟨w, rfl⟩ + rw [Subalgebra.mem_centralizer_iff] + rintro _ ⟨x, hx, rfl⟩ + induction w using TensorProduct.induction_on with + | zero => simp + | tmul b c => + simp [Subalgebra.mem_centralizer_iff _ |>.1 b.2 x hx] + | add y z hy hz => rw [map_add, mul_add, hy, hz, add_mul] + +/-- +Let `R` be a commutative ring and `A, B` be `R`-algebras where `B` is free as `R`-module. +For any subset `S ⊆ B`, the centralizer of `1 ⊗ S ⊆ A ⊗ B` is `A ⊗ C_B(S)` where `C_B(S)` is the +centralizer of `S` in `B`. +-/ +lemma centralizer_coe_image_includeRight_eq_center_tensorProduct + (S : Set B) [Module.Free R A] : + Subalgebra.centralizer R + (Algebra.TensorProduct.includeRight '' S) = + (Algebra.TensorProduct.map (AlgHom.id R A) + (Subalgebra.centralizer R (S : Set B)).val).range := by + have eq1 := centralizer_coe_image_includeLeft_eq_center_tensorProduct R B A S + apply_fun Subalgebra.comap (Algebra.TensorProduct.comm R A B).toAlgHom at eq1 + convert eq1 + · ext x + simpa [mem_centralizer_iff] using + ⟨fun h b hb ↦ (Algebra.TensorProduct.comm R A B).symm.injective <| by aesop, fun h b hb ↦ + (Algebra.TensorProduct.comm R A B).injective <| by aesop⟩ + · ext x + simp only [AlgHom.mem_range, AlgEquiv.toAlgHom_eq_coe, mem_comap, AlgHom.coe_coe] + constructor + · rintro ⟨x, rfl⟩ + exact ⟨(Algebra.TensorProduct.comm R _ _) x, + by rw [Algebra.TensorProduct.comm_comp_map_apply]⟩ + · rintro ⟨y, hy⟩ + refine ⟨(Algebra.TensorProduct.comm R _ _) y, (Algebra.TensorProduct.comm R A B).injective ?_⟩ + rw [← hy, comm_comp_map_apply, ← comm_symm, AlgEquiv.symm_apply_apply] + +/-- +Let `R` be a commutative ring and `A, B` be `R`-algebras where `B` is free as `R`-module. +For any subalgebra `S` of `A`, the centralizer of `S ⊗ 1 ⊆ A ⊗ B` is `C_A(S) ⊗ B` where `C_A(S)` is +the centralizer of `S` in `A`. +-/ +lemma centralizer_coe_map_includeLeft_eq_center_tensorProduct + (S : Subalgebra R A) [Module.Free R B] : + Subalgebra.centralizer R + (S.map (Algebra.TensorProduct.includeLeft (R := R) (B := B))) = + (Algebra.TensorProduct.map (Subalgebra.centralizer R (S : Set A)).val + (AlgHom.id R B)).range := + centralizer_coe_image_includeLeft_eq_center_tensorProduct R A B S + +/-- +Let `R` be a commutative ring and `A, B` be `R`-algebras where `A` is free as `R`-module. +For any subalgebra `S` of `B`, the centralizer of `1 ⊗ S ⊆ A ⊗ B` is `A ⊗ C_B(S)` where `C_B(S)` is +the centralizer of `S` in `B`. +-/ +lemma centralizer_coe_map_includeRight_eq_center_tensorProduct + (S : Subalgebra R B) [Module.Free R A] : + Subalgebra.centralizer R + (S.map (Algebra.TensorProduct.includeRight (R := R) (A := A))) = + (Algebra.TensorProduct.map (AlgHom.id R A) + (Subalgebra.centralizer R (S : Set B)).val).range := + centralizer_coe_image_includeRight_eq_center_tensorProduct R A B S + +/-- +Let `R` be a commutative ring and `A, B` be `R`-algebras where `B` is free as `R`-module. +Then the centralizer of `A ⊗ 1 ⊆ A ⊗ B` is `C(A) ⊗ B` where `C(A)` is the center of `A`. +-/ +lemma centralizer_coe_range_includeLeft_eq_center_tensorProduct [Module.Free R B] : + Subalgebra.centralizer R + (Algebra.TensorProduct.includeLeft : A →ₐ[R] A ⊗[R] B).range = + (Algebra.TensorProduct.map (Subalgebra.center R A).val (AlgHom.id R B)).range := by + rw [← centralizer_univ, ← Algebra.coe_top (R := R) (A := A), + ← centralizer_coe_map_includeLeft_eq_center_tensorProduct R A B ⊤] + ext + simp [includeLeft, includeLeftRingHom, Set.range_comp] + +/-- +Let `R` be a commutative ring and `A, B` be `R`-algebras where `A` is free as `R`-module. +Then the centralizer of `1 ⊗ B ⊆ A ⊗ B` is `A ⊗ C(B)` where `C(B)` is the center of `B`. +-/ +lemma centralizer_range_includeRight_eq_center_tensorProduct [Module.Free R A] : + Subalgebra.centralizer R + (Algebra.TensorProduct.includeRight : B →ₐ[R] A ⊗[R] B).range = + (Algebra.TensorProduct.map (AlgHom.id R A) (center R B).val).range := by + rw [← centralizer_univ, ← Algebra.coe_top (R := R) (A := B), + ← centralizer_coe_map_includeRight_eq_center_tensorProduct R A B ⊤] + ext + simp [includeRight, includeLeftRingHom, Set.range_comp] + +lemma centralizer_tensorProduct_eq_center_tensorProduct_left [Module.Free R B] : + Subalgebra.centralizer R + (Algebra.TensorProduct.map (AlgHom.id R A) (Algebra.ofId R B)).range = + (Algebra.TensorProduct.map (Subalgebra.center R A).val (AlgHom.id R B)).range := by + rw [← centralizer_coe_range_includeLeft_eq_center_tensorProduct] + simp [Algebra.TensorProduct.map_range] + +lemma centralizer_tensorProduct_eq_center_tensorProduct_right [Module.Free R A] : + Subalgebra.centralizer R + (Algebra.TensorProduct.map (Algebra.ofId R A) (AlgHom.id R B)).range = + (Algebra.TensorProduct.map (AlgHom.id R A) (center R B).val).range := by + rw [← centralizer_range_includeRight_eq_center_tensorProduct] + simp [Algebra.TensorProduct.map_range] + +end Free + +end Subalgebra diff --git a/Mathlib/RingTheory/TensorProduct/Basic.lean b/Mathlib/RingTheory/TensorProduct/Basic.lean index 06ad42f8fd9ac..23244caec6a64 100644 --- a/Mathlib/RingTheory/TensorProduct/Basic.lean +++ b/Mathlib/RingTheory/TensorProduct/Basic.lean @@ -883,6 +883,14 @@ theorem comm_symm : (TensorProduct.comm R A B).symm = TensorProduct.comm R B A := by ext; rfl +@[simp] +lemma comm_comp_includeLeft : + (TensorProduct.comm R A B : A ⊗[R] B →ₐ[R] B ⊗[R] A).comp includeLeft = includeRight := rfl + +@[simp] +lemma comm_comp_includeRight : + (TensorProduct.comm R A B : A ⊗[R] B →ₐ[R] B ⊗[R] A).comp includeRight = includeLeft := rfl + theorem adjoin_tmul_eq_top : adjoin R { t : A ⊗[R] B | ∃ a b, a ⊗ₜ[R] b = t } = ⊤ := top_le_iff.mp <| (top_le_iff.mpr <| span_tmul_eq_top R A B).trans (span_le_adjoin R _) @@ -983,6 +991,16 @@ theorem map_range (f : A →ₐ[R] B) (g : C →ₐ[R] D) : · rw [← map_comp_includeLeft f g, ← map_comp_includeRight f g] exact sup_le (AlgHom.range_comp_le_range _ _) (AlgHom.range_comp_le_range _ _) +lemma comm_comp_map (f : A →ₐ[R] C) (g : B →ₐ[R] D) : + (TensorProduct.comm R C D : C ⊗[R] D →ₐ[R] D ⊗[R] C).comp (Algebra.TensorProduct.map f g) = + (Algebra.TensorProduct.map g f).comp (TensorProduct.comm R A B).toAlgHom := by + ext <;> rfl + +lemma comm_comp_map_apply (f : A →ₐ[R] C) (g : B →ₐ[R] D) (x) : + TensorProduct.comm R C D (Algebra.TensorProduct.map f g x) = + (Algebra.TensorProduct.map g f) (TensorProduct.comm R A B x) := + congr($(comm_comp_map f g) x) + /-- Construct an isomorphism between tensor products of an S-algebra with an R-algebra from S- and R- isomorphisms between the tensor factors. -/ From 9d2da635c49b39ffdd1b61674b054cfde15a2c1a Mon Sep 17 00:00:00 2001 From: Bergschaf Date: Sat, 25 Jan 2025 06:17:44 +0000 Subject: [PATCH 502/681] feat(Order/Nucleus): Nucleus (#19440) Co-authored-by: Bergschaf <86738237+Bergschaf@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Order/Nucleus.lean | 113 +++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 Mathlib/Order/Nucleus.lean diff --git a/Mathlib.lean b/Mathlib.lean index 35a8f159abfea..c5107ec812dd7 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4279,6 +4279,7 @@ import Mathlib.Order.Monotone.Odd import Mathlib.Order.Monotone.Union import Mathlib.Order.Nat import Mathlib.Order.Notation +import Mathlib.Order.Nucleus import Mathlib.Order.OmegaCompletePartialOrder import Mathlib.Order.OrdContinuous import Mathlib.Order.OrderIsoNat diff --git a/Mathlib/Order/Nucleus.lean b/Mathlib/Order/Nucleus.lean new file mode 100644 index 0000000000000..e867d9f21930b --- /dev/null +++ b/Mathlib/Order/Nucleus.lean @@ -0,0 +1,113 @@ +/- +Copyright (c) 2024 Christian Krause. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chriara Cimino, Christian Krause +-/ +import Mathlib.Order.Closure +import Mathlib.Order.CompleteLattice +import Mathlib.Order.Hom.Lattice + +/-! +# Nucleus + +Locales are the dual concept to frames. Locale theory is a branch of point-free topology, where +intuitively locales are like topological spaces which may or may not have enough points. +Sublocales of a locale generalize the concept of subspaces in topology to the point-free setting. + +A nucleus is an endomorphism of a frame which corresponds to a sublocale. + +## References +https://ncatlab.org/nlab/show/sublocale +https://ncatlab.org/nlab/show/nucleus +-/ + +open Order InfHom + +variable {X : Type*} [CompleteLattice X] + +/-- A nucleus is an inflationary idempotent `inf`-preserving endomorphism of a semilattice. +In a frame, nuclei correspond to sublocales. -/ -- TODO: Formalise that claim +structure Nucleus (X : Type*) [SemilatticeInf X] extends InfHom X X where + /-- A `Nucleus` is idempotent. + + Do not use this directly. Instead use `NucleusClass.idempotent`. -/ + idempotent' (x : X) : toFun (toFun x) ≤ toFun x + /-- A `Nucleus` is increasing. + + Do not use this directly. Instead use `NucleusClass.le_apply`. -/ + le_apply' (x : X) : x ≤ toFun x + +/-- `NucleusClass F X` states that F is a type of nuclei. -/ +class NucleusClass (F X : Type*) [SemilatticeInf X] [FunLike F X X] extends InfHomClass F X X : + Prop where + /-- A nucleus is idempotent. -/ + idempotent (x : X) (f : F) : f (f x) ≤ f x + /-- A nucleus is increasing. -/ + le_apply (x : X) (f : F) : x ≤ f x + +namespace Nucleus + +variable {n m : Nucleus X} {x y : X} + +instance : FunLike (Nucleus X) X X where + coe x := x.toFun + coe_injective' f g h := by obtain ⟨⟨_, _⟩, _⟩ := f; congr! + +lemma toFun_eq_coe (n : Nucleus X) : n.toFun = n := rfl +@[simp] lemma coe_toInfHom (n : Nucleus X) : ⇑n.toInfHom = n := rfl + +instance : NucleusClass (Nucleus X) X where + idempotent _ _ := idempotent' .. + le_apply _ _ := le_apply' .. + map_inf _ _ _ := map_inf' .. + +/-- Every `Nucleus` is a `ClosureOperator`. -/ +def toClosureOperator (n : Nucleus X) : ClosureOperator X := + ClosureOperator.mk' n (OrderHomClass.mono n) n.le_apply' n.idempotent' + +lemma idempotent : n (n x) = n x := + n.toClosureOperator.idempotent x + +lemma le_apply : x ≤ n x := + n.toClosureOperator.le_closure x + +lemma map_inf : n (x ⊓ y) = n x ⊓ n y := + InfHomClass.map_inf n x y + +@[ext] lemma ext {m n : Nucleus X} (h : ∀ a, m a = n a) : m = n := + DFunLike.ext m n h + +/-- A `Nucleus` preserves ⊤. -/ +instance : TopHomClass (Nucleus X) X X where + map_top _ := eq_top_iff.mpr le_apply + +instance : PartialOrder (Nucleus X) := .lift (⇑) DFunLike.coe_injective + +@[simp, norm_cast] lemma coe_le_coe : ⇑m ≤ n ↔ m ≤ n := .rfl +@[simp, norm_cast] lemma coe_lt_coe : ⇑m < n ↔ m < n := .rfl + +/-- The smallest `Nucleus` is the identity. -/ +instance instBot : Bot (Nucleus X) where + bot.toFun x := x + bot.idempotent' := by simp + bot.le_apply' := by simp + bot.map_inf' := by simp + +/-- The biggest `Nucleus` sends everything to `⊤`. -/ +instance instTop : Top (Nucleus X) where + top.toFun := ⊤ + top.idempotent' := by simp + top.le_apply' := by simp + top.map_inf' := by simp + +@[simp, norm_cast] lemma coe_bot : ⇑(⊥ : Nucleus X) = id := rfl +@[simp, norm_cast] lemma coe_top : ⇑(⊤ : Nucleus X) = ⊤ := rfl + +@[simp] lemma bot_apply (x : X) : (⊥ : Nucleus X) x = x := rfl +@[simp] lemma top_apply (x : X) : (⊤ : Nucleus X) x = ⊤ := rfl + +instance : BoundedOrder (Nucleus X) where + bot_le _ _ := le_apply + le_top _ _ := by simp + +end Nucleus From 25224336253ab92857a4ba6abf4ab57893cb4ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 25 Jan 2025 06:17:45 +0000 Subject: [PATCH 503/681] chore(Data/Nat/Cast): don't import `MonoidWithZero` for results about `MonoidHom` (#20745) For this, move the results from `Data.Nat.Cast.Basic` not mentioning `Nat.cast` (!) to a new file `Algebra.Group.Nat.Hom`. See https://github.com/leanprover-community/mathlib3/pull/2957 for the copyright attribution. --- Mathlib.lean | 1 + .../MonCat/ForgetCorepresentable.lean | 2 +- Mathlib/Algebra/Group/Nat/Hom.lean | 125 ++++++++++++++++++ .../Algebra/Group/Submonoid/Membership.lean | 1 + Mathlib/Algebra/Polynomial/Eval/Defs.lean | 1 + Mathlib/Algebra/Polynomial/Monomial.lean | 3 +- Mathlib/Data/Int/Cast/Lemmas.lean | 1 + Mathlib/Data/Nat/Cast/Basic.lean | 90 +------------ 8 files changed, 133 insertions(+), 91 deletions(-) create mode 100644 Mathlib/Algebra/Group/Nat/Hom.lean diff --git a/Mathlib.lean b/Mathlib.lean index c5107ec812dd7..a2b1ae1bd0ba9 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -311,6 +311,7 @@ import Mathlib.Algebra.Group.Invertible.Defs import Mathlib.Algebra.Group.MinimalAxioms import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Group.Nat.Even +import Mathlib.Algebra.Group.Nat.Hom import Mathlib.Algebra.Group.Nat.TypeTags import Mathlib.Algebra.Group.Nat.Units import Mathlib.Algebra.Group.NatPowAssoc diff --git a/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean b/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean index ce3e674738fab..28ed84e06487d 100644 --- a/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean +++ b/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sophie Morel -/ import Mathlib.Algebra.Category.MonCat.Basic -import Mathlib.Data.Nat.Cast.Basic +import Mathlib.Algebra.Group.Nat.Hom /-! # The forget functor is corepresentable diff --git a/Mathlib/Algebra/Group/Nat/Hom.lean b/Mathlib/Algebra/Group/Nat/Hom.lean new file mode 100644 index 0000000000000..d54b5ae8d598a --- /dev/null +++ b/Mathlib/Algebra/Group/Nat/Hom.lean @@ -0,0 +1,125 @@ +/- +Copyright (c) 2020 Yury Kudryashov. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yury Kudryashov +-/ +import Mathlib.Algebra.Group.Equiv.Defs +import Mathlib.Algebra.Group.Hom.Basic +import Mathlib.Algebra.Group.Nat.Defs +import Mathlib.Algebra.Group.TypeTags.Hom +import Mathlib.Tactic.MinImports + +/-! +# Extensionality of monoid homs from `ℕ` +-/ + +assert_not_exists OrderedCommMonoid MonoidWithZero + +open Additive Multiplicative + +variable {M M : Type*} + +section AddMonoidHomClass + +variable {A B F : Type*} [FunLike F ℕ A] + +lemma ext_nat' [AddMonoid A] [AddMonoidHomClass F ℕ A] (f g : F) (h : f 1 = g 1) : f = g := + DFunLike.ext f g <| by + intro n + induction n with + | zero => simp_rw [map_zero f, map_zero g] + | succ n ihn => + simp [h, ihn] + +@[ext] +lemma AddMonoidHom.ext_nat [AddMonoid A] {f g : ℕ →+ A} : f 1 = g 1 → f = g := + ext_nat' f g + +end AddMonoidHomClass + +section AddMonoid +variable [AddMonoid M] + +variable (M) in +/-- Additive homomorphisms from `ℕ` are defined by the image of `1`. -/ +def multiplesHom : M ≃ (ℕ →+ M) where + toFun x := + { toFun := fun n ↦ n • x + map_zero' := zero_nsmul x + map_add' := fun _ _ ↦ add_nsmul _ _ _ } + invFun f := f 1 + left_inv := one_nsmul + right_inv f := AddMonoidHom.ext_nat <| one_nsmul (f 1) + +@[simp] lemma multiplesHom_apply (x : M) (n : ℕ) : multiplesHom M x n = n • x := rfl + +lemma multiplesHom_symm_apply (f : ℕ →+ M) : (multiplesHom M).symm f = f 1 := rfl + +lemma AddMonoidHom.apply_nat (f : ℕ →+ M) (n : ℕ) : f n = n • f 1 := by + rw [← multiplesHom_symm_apply, ← multiplesHom_apply, Equiv.apply_symm_apply] + +end AddMonoid + +section Monoid +variable [Monoid M] + +variable (M) in +/-- Monoid homomorphisms from `Multiplicative ℕ` are defined by the image +of `Multiplicative.ofAdd 1`. -/ +@[to_additive existing] +def powersHom : M ≃ (Multiplicative ℕ →* M) := + Additive.ofMul.trans <| (multiplesHom _).trans <| AddMonoidHom.toMultiplicative'' + +@[to_additive existing (attr := simp)] +lemma powersHom_apply (x : M) (n : Multiplicative ℕ) : + powersHom M x n = x ^ n.toAdd := rfl + +@[to_additive existing (attr := simp)] +lemma powersHom_symm_apply (f : Multiplicative ℕ →* M) : + (powersHom M).symm f = f (Multiplicative.ofAdd 1) := rfl + +@[to_additive existing AddMonoidHom.apply_nat] +lemma MonoidHom.apply_mnat (f : Multiplicative ℕ →* M) (n : Multiplicative ℕ) : + f n = f (Multiplicative.ofAdd 1) ^ n.toAdd := by + rw [← powersHom_symm_apply, ← powersHom_apply, Equiv.apply_symm_apply] + +@[to_additive existing (attr := ext) AddMonoidHom.ext_nat] +lemma MonoidHom.ext_mnat ⦃f g : Multiplicative ℕ →* M⦄ + (h : f (Multiplicative.ofAdd 1) = g (Multiplicative.ofAdd 1)) : f = g := + MonoidHom.ext fun n ↦ by rw [f.apply_mnat, g.apply_mnat, h] + +end Monoid + +section AddCommMonoid +variable [AddCommMonoid M] + +variable (M) in +/-- If `M` is commutative, `multiplesHom` is an additive equivalence. -/ +def multiplesAddHom : M ≃+ (ℕ →+ M) where + __ := multiplesHom M + map_add' a b := AddMonoidHom.ext fun n ↦ by simp [nsmul_add] + +@[simp] lemma multiplesAddHom_apply (x : M) (n : ℕ) : multiplesAddHom M x n = n • x := rfl + +@[simp] lemma multiplesAddHom_symm_apply (f : ℕ →+ M) : (multiplesAddHom M).symm f = f 1 := rfl + +end AddCommMonoid + +section CommMonoid +variable [CommMonoid M] + +variable (M) in +/-- If `M` is commutative, `powersHom` is a multiplicative equivalence. -/ +@[to_additive existing] +def powersMulHom : M ≃* (Multiplicative ℕ →* M) where + __ := powersHom M + map_mul' a b := MonoidHom.ext fun n ↦ by simp [mul_pow] + +@[to_additive existing (attr := simp)] +lemma powersMulHom_apply (x : M) (n : Multiplicative ℕ) : powersMulHom M x n = x ^ n.toAdd := rfl + +@[to_additive existing (attr := simp)] +lemma powersMulHom_symm_apply (f : Multiplicative ℕ →* M) : (powersMulHom M).symm f = f (ofAdd 1) := + rfl + +end CommMonoid diff --git a/Mathlib/Algebra/Group/Submonoid/Membership.lean b/Mathlib/Algebra/Group/Submonoid/Membership.lean index 8121874d5e833..5c401ebbaecf0 100644 --- a/Mathlib/Algebra/Group/Submonoid/Membership.lean +++ b/Mathlib/Algebra/Group/Submonoid/Membership.lean @@ -6,6 +6,7 @@ Amelia Livingston, Yury Kudryashov -/ import Mathlib.Algebra.FreeMonoid.Basic import Mathlib.Algebra.Group.Idempotent +import Mathlib.Algebra.Group.Nat.Hom import Mathlib.Algebra.Group.Submonoid.MulOpposite import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.GroupWithZero.Divisibility diff --git a/Mathlib/Algebra/Polynomial/Eval/Defs.lean b/Mathlib/Algebra/Polynomial/Eval/Defs.lean index 088010ca51334..1cb42ee480336 100644 --- a/Mathlib/Algebra/Polynomial/Eval/Defs.lean +++ b/Mathlib/Algebra/Polynomial/Eval/Defs.lean @@ -3,6 +3,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, Kim Morrison, Jens Wagemaker -/ +import Mathlib.Algebra.Group.Nat.Hom import Mathlib.Algebra.Polynomial.Basic /-! diff --git a/Mathlib/Algebra/Polynomial/Monomial.lean b/Mathlib/Algebra/Polynomial/Monomial.lean index f994bf2057858..c22c4afba88b1 100644 --- a/Mathlib/Algebra/Polynomial/Monomial.lean +++ b/Mathlib/Algebra/Polynomial/Monomial.lean @@ -3,12 +3,11 @@ 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, Kim Morrison, Jens Wagemaker -/ +import Mathlib.Algebra.Group.Nat.Hom import Mathlib.Algebra.Polynomial.Basic /-! # Univariate monomials - -Preparatory lemmas for degree_basic. -/ diff --git a/Mathlib/Data/Int/Cast/Lemmas.lean b/Mathlib/Data/Int/Cast/Lemmas.lean index a9229d8aa827b..628317d302d5e 100644 --- a/Mathlib/Data/Int/Cast/Lemmas.lean +++ b/Mathlib/Data/Int/Cast/Lemmas.lean @@ -3,6 +3,7 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Mathlib.Algebra.Group.TypeTags.Hom import Mathlib.Algebra.Ring.Hom.Basic import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Algebra.Ring.Parity diff --git a/Mathlib/Data/Nat/Cast/Basic.lean b/Mathlib/Data/Nat/Cast/Basic.lean index 6ad91dd172cc3..617f4537a4023 100644 --- a/Mathlib/Data/Nat/Cast/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Basic.lean @@ -5,7 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Algebra.Divisibility.Hom import Mathlib.Algebra.Group.Even -import Mathlib.Algebra.Group.TypeTags.Hom +import Mathlib.Algebra.Group.Nat.Hom import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Algebra.Ring.Nat @@ -92,21 +92,7 @@ end Nat section AddMonoidHomClass -variable {A B F : Type*} [AddMonoidWithOne B] [FunLike F ℕ A] - -theorem ext_nat' [AddMonoid A] [AddMonoidHomClass F ℕ A] (f g : F) (h : f 1 = g 1) : f = g := - DFunLike.ext f g <| by - intro n - induction n with - | zero => simp_rw [map_zero f, map_zero g] - | succ n ihn => - simp [h, ihn] - -@[ext] -theorem AddMonoidHom.ext_nat [AddMonoid A] {f g : ℕ →+ A} : f 1 = g 1 → f = g := - ext_nat' f g - -variable [AddMonoidWithOne A] +variable {A B F : Type*} [AddMonoidWithOne B] [FunLike F ℕ A] [AddMonoidWithOne A] -- these versions are primed so that the `RingHomClass` versions aren't theorem eq_natCast' [AddMonoidHomClass F ℕ A] (f : F) (h1 : f 1 = 1) : ∀ n : ℕ, f n = n @@ -195,78 +181,6 @@ instance Nat.uniqueRingHom {R : Type*} [NonAssocSemiring R] : Unique (ℕ →+* default := Nat.castRingHom R uniq := RingHom.eq_natCast' -section Monoid -variable (α) [Monoid α] (β) [AddMonoid β] - -/-- Additive homomorphisms from `ℕ` are defined by the image of `1`. -/ -def multiplesHom : β ≃ (ℕ →+ β) where - toFun x := - { toFun := fun n ↦ n • x - map_zero' := zero_nsmul x - map_add' := fun _ _ ↦ add_nsmul _ _ _ } - invFun f := f 1 - left_inv := one_nsmul - right_inv f := AddMonoidHom.ext_nat <| one_nsmul (f 1) - -/-- Monoid homomorphisms from `Multiplicative ℕ` are defined by the image -of `Multiplicative.ofAdd 1`. -/ -@[to_additive existing] -def powersHom : α ≃ (Multiplicative ℕ →* α) := - Additive.ofMul.trans <| (multiplesHom _).trans <| AddMonoidHom.toMultiplicative'' - -variable {α} - --- TODO: can `to_additive` generate the following lemmas automatically? - -lemma multiplesHom_apply (x : β) (n : ℕ) : multiplesHom β x n = n • x := rfl - -@[to_additive existing (attr := simp)] -lemma powersHom_apply (x : α) (n : Multiplicative ℕ) : - powersHom α x n = x ^ n.toAdd := rfl - -lemma multiplesHom_symm_apply (f : ℕ →+ β) : (multiplesHom β).symm f = f 1 := rfl - -@[to_additive existing (attr := simp)] -lemma powersHom_symm_apply (f : Multiplicative ℕ →* α) : - (powersHom α).symm f = f (Multiplicative.ofAdd 1) := rfl - -lemma MonoidHom.apply_mnat (f : Multiplicative ℕ →* α) (n : Multiplicative ℕ) : - f n = f (Multiplicative.ofAdd 1) ^ n.toAdd := by - rw [← powersHom_symm_apply, ← powersHom_apply, Equiv.apply_symm_apply] - -@[ext] -lemma MonoidHom.ext_mnat ⦃f g : Multiplicative ℕ →* α⦄ - (h : f (Multiplicative.ofAdd 1) = g (Multiplicative.ofAdd 1)) : f = g := - MonoidHom.ext fun n ↦ by rw [f.apply_mnat, g.apply_mnat, h] - -lemma AddMonoidHom.apply_nat (f : ℕ →+ β) (n : ℕ) : f n = n • f 1 := by - rw [← multiplesHom_symm_apply, ← multiplesHom_apply, Equiv.apply_symm_apply] - -end Monoid - -section CommMonoid -variable (α) [CommMonoid α] (β) [AddCommMonoid β] - -/-- If `α` is commutative, `multiplesHom` is an additive equivalence. -/ -def multiplesAddHom : β ≃+ (ℕ →+ β) := - { multiplesHom β with map_add' := fun a b ↦ AddMonoidHom.ext fun n ↦ by simp [nsmul_add] } - -/-- If `α` is commutative, `powersHom` is a multiplicative equivalence. -/ -def powersMulHom : α ≃* (Multiplicative ℕ →* α) := - { powersHom α with map_mul' := fun a b ↦ MonoidHom.ext fun n ↦ by simp [mul_pow] } - -@[simp] lemma multiplesAddHom_apply (x : β) (n : ℕ) : multiplesAddHom β x n = n • x := rfl - -@[simp] -lemma powersMulHom_apply (x : α) (n : Multiplicative ℕ) : powersMulHom α x n = x ^ n.toAdd := rfl - -@[simp] lemma multiplesAddHom_symm_apply (f : ℕ →+ β) : (multiplesAddHom β).symm f = f 1 := rfl - -@[simp] lemma powersMulHom_symm_apply (f : Multiplicative ℕ →* α) : - (powersMulHom α).symm f = f (ofAdd 1) := rfl - -end CommMonoid - namespace Pi variable {π : α → Type*} [∀ a, NatCast (π a)] From 698c109b77120370782850b691a286e1906fe3ae Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Sat, 25 Jan 2025 06:17:46 +0000 Subject: [PATCH 504/681] chore: deprecate `gcd_eq_one_iff_coprime` (#20976) https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/.60gcd_eq_one_iff_coprime.60.20and.20.60isCoprime_iff_gcd_eq_one.60 Co-authored-by: Moritz Firsching --- Mathlib/Data/ZMod/Coprime.lean | 5 ++-- Mathlib/NumberTheory/FLT/Four.lean | 15 ++++++------ Mathlib/NumberTheory/PellMatiyasevic.lean | 3 +-- Mathlib/NumberTheory/Zsqrtd/Basic.lean | 4 ++-- Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean | 4 ++-- Mathlib/RingTheory/Coprime/Lemmas.lean | 4 ++-- Mathlib/RingTheory/Int/Basic.lean | 24 ++++++-------------- 7 files changed, 25 insertions(+), 34 deletions(-) diff --git a/Mathlib/Data/ZMod/Coprime.lean b/Mathlib/Data/ZMod/Coprime.lean index 91030c12cfdc1..2923900a3f990 100644 --- a/Mathlib/Data/ZMod/Coprime.lean +++ b/Mathlib/Data/ZMod/Coprime.lean @@ -3,8 +3,9 @@ Copyright (c) 2022 Michael Stoll. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Stoll -/ +import Mathlib.Algebra.EuclideanDomain.Int +import Mathlib.Data.Nat.Prime.Int import Mathlib.Data.ZMod.Basic -import Mathlib.RingTheory.Int.Basic import Mathlib.RingTheory.PrincipalIdealDomain /-! @@ -22,7 +23,7 @@ namespace ZMod `gcd a p ≠ 1`. -/ theorem eq_zero_iff_gcd_ne_one {a : ℤ} {p : ℕ} [pp : Fact p.Prime] : (a : ZMod p) = 0 ↔ a.gcd p ≠ 1 := by - rw [Ne, Int.gcd_comm, Int.gcd_eq_one_iff_coprime, + rw [Ne, Int.gcd_comm, ← Int.isCoprime_iff_gcd_eq_one, (Nat.prime_iff_prime_int.1 pp.1).coprime_iff_not_dvd, Classical.not_not, intCast_zmod_eq_zero_iff_dvd] diff --git a/Mathlib/NumberTheory/FLT/Four.lean b/Mathlib/NumberTheory/FLT/Four.lean index 38f0eb8dff081..2ce906d75b4c6 100644 --- a/Mathlib/NumberTheory/FLT/Four.lean +++ b/Mathlib/NumberTheory/FLT/Four.lean @@ -80,7 +80,7 @@ theorem exists_minimal {a b c : ℤ} (h : Fermat42 a b c) : ∃ a0 b0 c0, Minima /-- a minimal solution to `a ^ 4 + b ^ 4 = c ^ 2` must have `a` and `b` coprime. -/ theorem coprime_of_minimal {a b c : ℤ} (h : Minimal a b c) : IsCoprime a b := by - apply Int.gcd_eq_one_iff_coprime.mp + apply Int.isCoprime_iff_gcd_eq_one.mpr by_contra hab obtain ⟨p, hp, hpa, hpb⟩ := Nat.Prime.not_coprime_iff_dvd.mp hab obtain ⟨a1, rfl⟩ := Int.natCast_dvd.mpr hpa @@ -119,7 +119,7 @@ theorem exists_odd_minimal {a b c : ℤ} (h : Fermat42 a b c) : · exfalso have h1 : 2 ∣ (Int.gcd a0 b0 : ℤ) := Int.dvd_gcd (Int.dvd_of_emod_eq_zero hap) (Int.dvd_of_emod_eq_zero hbp) - rw [Int.gcd_eq_one_iff_coprime.mpr (coprime_of_minimal hf)] at h1 + rw [Int.isCoprime_iff_gcd_eq_one.mp (coprime_of_minimal hf)] at h1 revert h1 decide · exact ⟨b0, ⟨a0, ⟨c0, minimal_comm hf, hbp⟩⟩⟩ @@ -164,7 +164,8 @@ theorem not_minimal {a b c : ℤ} (h : Minimal a b c) (ha2 : a % 2 = 1) (hc : 0 delta PythagoreanTriple linear_combination h.1.2.2 -- coprime requirement: - have h2 : Int.gcd (a ^ 2) (b ^ 2) = 1 := Int.gcd_eq_one_iff_coprime.mpr (coprime_of_minimal h).pow + have h2 : Int.gcd (a ^ 2) (b ^ 2) = 1 := + Int.isCoprime_iff_gcd_eq_one.mp (coprime_of_minimal h).pow -- in order to reduce the possibilities we get from the classification of pythagorean triples -- it helps if we know the parity of a ^ 2 (and the sign of c): have ha22 : a ^ 2 % 2 = 1 := by @@ -179,10 +180,10 @@ theorem not_minimal {a b c : ℤ} (h : Minimal a b c) (ha2 : a % 2 = 1) (hc : 0 linear_combination ht1 -- a and n are coprime, because a ^ 2 = m ^ 2 - n ^ 2 and m and n are coprime. have h3 : Int.gcd a n = 1 := by - apply Int.gcd_eq_one_iff_coprime.mpr + apply Int.isCoprime_iff_gcd_eq_one.mp apply @IsCoprime.of_mul_left_left _ _ _ a rw [← sq, ht1, (by ring : m ^ 2 - n ^ 2 = m ^ 2 + -n * n)] - exact (Int.gcd_eq_one_iff_coprime.mp ht4).pow_left.add_mul_right_left (-n) + exact (Int.isCoprime_iff_gcd_eq_one.mpr ht4).pow_left.add_mul_right_left (-n) -- m is positive because b is non-zero and b ^ 2 = 2 * m * n and we already have 0 ≤ m. have hb20 : b ^ 2 ≠ 0 := mt pow_eq_zero h.1.2.1 have h4 : 0 < m := by @@ -197,8 +198,8 @@ theorem not_minimal {a b c : ℤ} (h : Minimal a b c) (ha2 : a % 2 = 1) (hc : 0 -- m and r * s are coprime because m = r ^ 2 + s ^ 2 and r and s are coprime. have hcp : Int.gcd m (r * s) = 1 := by rw [htt3] - exact - Int.gcd_eq_one_iff_coprime.mpr (Int.isCoprime_of_sq_sum' (Int.gcd_eq_one_iff_coprime.mp htt4)) + exact Int.isCoprime_iff_gcd_eq_one.mp + (Int.isCoprime_of_sq_sum' (Int.isCoprime_iff_gcd_eq_one.mpr htt4)) -- b is even because b ^ 2 = 2 * m * n. have hb2 : 2 ∣ b := by apply @Int.Prime.dvd_pow' _ 2 _ Nat.prime_two diff --git a/Mathlib/NumberTheory/PellMatiyasevic.lean b/Mathlib/NumberTheory/PellMatiyasevic.lean index b3c0223113d11..11aa143aeb098 100644 --- a/Mathlib/NumberTheory/PellMatiyasevic.lean +++ b/Mathlib/NumberTheory/PellMatiyasevic.lean @@ -3,8 +3,7 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Order.Ring.Basic -import Mathlib.Data.Nat.ModEq +import Mathlib.Data.Nat.Prime.Basic import Mathlib.NumberTheory.Zsqrtd.Basic /-! diff --git a/Mathlib/NumberTheory/Zsqrtd/Basic.lean b/Mathlib/NumberTheory/Zsqrtd/Basic.lean index 713d9484766ef..00bc9cbbccdaa 100644 --- a/Mathlib/NumberTheory/Zsqrtd/Basic.lean +++ b/Mathlib/NumberTheory/Zsqrtd/Basic.lean @@ -5,9 +5,9 @@ Authors: Mario Carneiro -/ import Mathlib.Algebra.Ring.Associated import Mathlib.Algebra.Star.Unitary -import Mathlib.RingTheory.Int.Basic import Mathlib.RingTheory.PrincipalIdealDomain import Mathlib.Tactic.Ring +import Mathlib.Algebra.EuclideanDomain.Int /-! # ℤ[√d] @@ -350,7 +350,7 @@ theorem exists_coprime_of_gcd_pos {a : ℤ√d} (hgcd : 0 < Int.gcd a.re a.im) : rw [mul_comm] at Hre Him refine ⟨⟨re, im⟩, ?_, ?_⟩ · rw [smul_val, ← Hre, ← Him] - · rw [← Int.gcd_eq_one_iff_coprime, H1] + · rw [Int.isCoprime_iff_gcd_eq_one, H1] end Gcd diff --git a/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean b/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean index a2da9ffabe073..b3ef1877a2913 100644 --- a/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean +++ b/Mathlib/NumberTheory/Zsqrtd/GaussianInt.lean @@ -3,10 +3,10 @@ Copyright (c) 2019 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.NumberTheory.Zsqrtd.Basic -import Mathlib.RingTheory.PrincipalIdealDomain import Mathlib.Data.Complex.Basic +import Mathlib.Data.Nat.Prime.Basic import Mathlib.Data.Real.Archimedean +import Mathlib.NumberTheory.Zsqrtd.Basic /-! # Gaussian integers diff --git a/Mathlib/RingTheory/Coprime/Lemmas.lean b/Mathlib/RingTheory/Coprime/Lemmas.lean index 4ccc44de66126..b4e4211ac4ea8 100644 --- a/Mathlib/RingTheory/Coprime/Lemmas.lean +++ b/Mathlib/RingTheory/Coprime/Lemmas.lean @@ -33,8 +33,8 @@ section theorem Int.isCoprime_iff_gcd_eq_one {m n : ℤ} : IsCoprime m n ↔ Int.gcd m n = 1 := by constructor · rintro ⟨a, b, h⟩ - have : 1 = m * a + n * b := by rwa [mul_comm m, mul_comm n, eq_comm] - exact Nat.dvd_one.mp (Int.gcd_dvd_iff.mpr ⟨a, b, this⟩) + refine Nat.dvd_one.mp (Int.gcd_dvd_iff.mpr ⟨a, b, ?_⟩) + rwa [mul_comm m, mul_comm n, eq_comm] · rw [← Int.ofNat_inj, IsCoprime, Int.gcd_eq_gcd_ab, mul_comm m, mul_comm n, Nat.cast_one] intro h exact ⟨_, _, h⟩ diff --git a/Mathlib/RingTheory/Int/Basic.lean b/Mathlib/RingTheory/Int/Basic.lean index bcd2fb030e89d..6222efbb76ead 100644 --- a/Mathlib/RingTheory/Int/Basic.lean +++ b/Mathlib/RingTheory/Int/Basic.lean @@ -30,30 +30,20 @@ unique factors namespace Int -theorem gcd_eq_one_iff_coprime {a b : ℤ} : Int.gcd a b = 1 ↔ IsCoprime a b := by - constructor - · intro hg - obtain ⟨ua, -, ha⟩ := exists_unit_of_abs a - obtain ⟨ub, -, hb⟩ := exists_unit_of_abs b - use Nat.gcdA (Int.natAbs a) (Int.natAbs b) * ua, Nat.gcdB (Int.natAbs a) (Int.natAbs b) * ub - rw [mul_assoc, ← ha, mul_assoc, ← hb, mul_comm, mul_comm _ (Int.natAbs b : ℤ), ← - Nat.gcd_eq_gcd_ab, ← gcd_eq_natAbs, hg, Int.ofNat_one] - · rintro ⟨r, s, h⟩ - by_contra hg - obtain ⟨p, ⟨hp, ha, hb⟩⟩ := Nat.Prime.not_coprime_iff_dvd.mp hg - apply Nat.Prime.not_dvd_one hp - rw [← natCast_dvd_natCast, Int.ofNat_one, ← h] - exact dvd_add ((natCast_dvd.mpr ha).mul_left _) ((natCast_dvd.mpr hb).mul_left _) +@[deprecated "use `isCoprime_iff_gcd_eq_one.symm` instead" (since := "2025-01-23")] +theorem gcd_eq_one_iff_coprime {a b : ℤ} : Int.gcd a b = 1 ↔ IsCoprime a b := + isCoprime_iff_gcd_eq_one.symm + theorem isCoprime_iff_nat_coprime {a b : ℤ} : IsCoprime a b ↔ Nat.Coprime a.natAbs b.natAbs := by - rw [← gcd_eq_one_iff_coprime, Nat.coprime_iff_gcd_eq_one, gcd_eq_natAbs] + rw [isCoprime_iff_gcd_eq_one, Nat.coprime_iff_gcd_eq_one, gcd_eq_natAbs] @[deprecated (since := "2025-01-23")] alias coprime_iff_nat_coprime := isCoprime_iff_nat_coprime /-- If `gcd a (m * n) ≠ 1`, then `gcd a m ≠ 1` or `gcd a n ≠ 1`. -/ theorem gcd_ne_one_iff_gcd_mul_right_ne_one {a : ℤ} {m n : ℕ} : a.gcd (m * n) ≠ 1 ↔ a.gcd m ≠ 1 ∨ a.gcd n ≠ 1 := by - simp only [gcd_eq_one_iff_coprime, ← not_and_or, not_iff_not, IsCoprime.mul_right_iff] + simp only [← isCoprime_iff_gcd_eq_one, ← not_and_or, not_iff_not, IsCoprime.mul_right_iff] theorem sq_of_gcd_eq_one {a b c : ℤ} (h : Int.gcd a b = 1) (heq : a * b = c ^ 2) : ∃ a0 : ℤ, a = a0 ^ 2 ∨ a = -a0 ^ 2 := by @@ -69,7 +59,7 @@ theorem sq_of_gcd_eq_one {a b c : ℤ} (h : Int.gcd a b = 1) (heq : a * b = c ^ theorem sq_of_isCoprime {a b c : ℤ} (h : IsCoprime a b) (heq : a * b = c ^ 2) : ∃ a0 : ℤ, a = a0 ^ 2 ∨ a = -a0 ^ 2 := - sq_of_gcd_eq_one (gcd_eq_one_iff_coprime.mpr h) heq + sq_of_gcd_eq_one (isCoprime_iff_gcd_eq_one.mp h) heq @[deprecated (since := "2025-01-23")] alias sq_of_coprime := sq_of_isCoprime From a9be65ea7de0589e8c9fd4655af6aca0e8f2b8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 25 Jan 2025 06:17:48 +0000 Subject: [PATCH 505/681] feat: submodule of multivariate polynomials of bounded degrees (#20984) From GrowthInGroups (LeanCamCombi) Co-authored-by: Andrew Yang --- Mathlib/Algebra/MvPolynomial/Degrees.lean | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Mathlib/Algebra/MvPolynomial/Degrees.lean b/Mathlib/Algebra/MvPolynomial/Degrees.lean index f6242cd8467a2..cbfaf3b83f88c 100644 --- a/Mathlib/Algebra/MvPolynomial/Degrees.lean +++ b/Mathlib/Algebra/MvPolynomial/Degrees.lean @@ -524,6 +524,51 @@ theorem totalDegree_rename_le (f : σ → τ) (p : MvPolynomial σ R) : end TotalDegree +section degreesLE +variable {s t : Multiset σ} + +variable (R σ s) in +/-- The submodule of multivariate polynomials of degrees bounded by a monomial `s`. -/ +def degreesLE : Submodule R (MvPolynomial σ R) where + carrier := {p | p.degrees ≤ s} + add_mem' {a b} ha hb := by classical exact degrees_add_le.trans (sup_le ha hb) + zero_mem' := by simp + smul_mem' c {x} hx := by + dsimp + rw [Algebra.smul_def] + refine degrees_mul_le.trans ?_ + simpa [degrees_C] using hx + +@[simp] lemma mem_degreesLE : p ∈ degreesLE R σ s ↔ p.degrees ≤ s := Iff.rfl + +variable (s t) in +lemma degreesLE_add : degreesLE R σ (s + t) = degreesLE R σ s * degreesLE R σ t := by + classical + rw [le_antisymm_iff, Submodule.mul_le] + refine ⟨fun x hx ↦ x.as_sum ▸ sum_mem fun i hi ↦ ?_, + fun x hx y hy ↦ degrees_mul_le.trans (add_le_add hx hy)⟩ + replace hi : i.toMultiset ≤ s + t := (Finset.le_sup hi).trans hx + let a := (i.toMultiset - t).toFinsupp + let b := (i.toMultiset ⊓ t).toFinsupp + have : a + b = i := Multiset.toFinsupp.symm.injective (by simp [a, b, Multiset.sub_add_inter]) + have ha : a.toMultiset ≤ s := by simpa [a, add_comm (a := t)] using hi + have hb : b.toMultiset ≤ t := by simp [b, Multiset.inter_le_right] + rw [show monomial i (x.coeff i) = monomial a (x.coeff i) * monomial b 1 by simp [this]] + exact Submodule.mul_mem_mul ((degrees_monomial _ _).trans ha) ((degrees_monomial _ _).trans hb) + +@[simp] lemma degreesLE_zero : degreesLE R σ 0 = 1 := by + refine le_antisymm (fun x hx ↦ ?_) (by simp) + simp only [mem_degreesLE, nonpos_iff_eq_zero] at hx + have := (totalDegree_eq_zero_iff_eq_C (p := x)).mp + (Nat.eq_zero_of_le_zero (x.totalDegree_le_degrees_card.trans (by simp [hx]))) + exact ⟨x.coeff 0, by simp [Algebra.smul_def, ← this]⟩ + +variable (s) in +lemma degreesLE_nsmul : ∀ n, degreesLE R σ (n • s) = degreesLE R σ s ^ n + | 0 => by simp + | k + 1 => by simp only [pow_succ, degreesLE_nsmul, degreesLE_add, add_smul, one_smul] + +end degreesLE end CommSemiring end MvPolynomial From d394d2f55404758ad55037c75e330b2a2f2b6e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Sat, 25 Jan 2025 06:17:49 +0000 Subject: [PATCH 506/681] feat(RingTheory/Artinian): an artinian local reduced ring is a field (#21019) Prove that an artinian local reduced ring is a field. --- Mathlib/RingTheory/Artinian/Ring.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/RingTheory/Artinian/Ring.lean b/Mathlib/RingTheory/Artinian/Ring.lean index a508c61431e11..4889c2cb83fb2 100644 --- a/Mathlib/RingTheory/Artinian/Ring.lean +++ b/Mathlib/RingTheory/Artinian/Ring.lean @@ -3,8 +3,10 @@ Copyright (c) 2021 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Junyan Xu, Jujian Zhang -/ +import Mathlib.Algebra.Field.Equiv import Mathlib.RingTheory.Artinian.Module import Mathlib.RingTheory.Localization.Defs +import Mathlib.RingTheory.LocalRing.MaximalIdeal.Basic import Mathlib.RingTheory.Nakayama /-! @@ -83,6 +85,12 @@ theorem isNilpotent_jacobson_bot : IsNilpotent (Ideal.jacobson (⊥ : Ideal R)) refine this (mul_mem_mul (mem_span_singleton_self x) ?_) rwa [← hn (n + 1) (Nat.le_succ _)] +variable (R) in +/-- Commutative artinian reduced local ring is a field. -/ +theorem isField_of_isReduced_of_isLocalRing [IsReduced R] [IsLocalRing R] : IsField R := + (IsArtinianRing.equivPi R).trans (RingEquiv.piUnique _) |>.toMulEquiv.isField + _ (Ideal.Quotient.field _).toIsField + section Localization variable (S : Submonoid R) (L : Type*) [CommSemiring L] [Algebra R L] [IsLocalization S L] From 98e595522642bddbd8d8d1c1b0071630e1407d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Sat, 25 Jan 2025 06:17:50 +0000 Subject: [PATCH 507/681] feat(Algebra/Algebra/Prod): simple theorems about `fst`, `snd` and `prod` (#21020) Very basic theorems about `AlgHom.fst`, `AlgHom.snd` and `AlgHom.prod`. Counterparts for `LinearMap` already exist. --- Mathlib/Algebra/Algebra/Prod.lean | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Mathlib/Algebra/Algebra/Prod.lean b/Mathlib/Algebra/Algebra/Prod.lean index 0c726579527a5..bee86dbf00c8b 100644 --- a/Mathlib/Algebra/Algebra/Prod.lean +++ b/Mathlib/Algebra/Algebra/Prod.lean @@ -61,7 +61,15 @@ def fst : A × B →ₐ[R] A := def snd : A × B →ₐ[R] B := { RingHom.snd A B with commutes' := fun _r => rfl } -variable {R A B} +variable {A B} + +@[simp] +theorem fst_apply (a) : fst R A B a = a.1 := rfl + +@[simp] +theorem snd_apply (a) : snd R A B a = a.2 := rfl + +variable {R} /-- The `Pi.prod` of two morphisms is a morphism. -/ @[simps!] @@ -81,8 +89,11 @@ theorem fst_prod (f : A →ₐ[R] B) (g : A →ₐ[R] C) : (fst R B C).comp (pro theorem snd_prod (f : A →ₐ[R] B) (g : A →ₐ[R] C) : (snd R B C).comp (prod f g) = g := by ext; rfl @[simp] -theorem prod_fst_snd : prod (fst R A B) (snd R A B) = 1 := - DFunLike.coe_injective Pi.prod_fst_snd +theorem prod_fst_snd : prod (fst R A B) (snd R A B) = AlgHom.id R _ := rfl + +theorem prod_comp {C' : Type*} [Semiring C'] [Algebra R C'] + (f : A →ₐ[R] B) (g : B →ₐ[R] C) (g' : B →ₐ[R] C') : + (g.prod g').comp f = (g.comp f).prod (g'.comp f) := rfl /-- Taking the product of two maps with the same domain is equivalent to taking the product of their codomains. -/ From b8b62d355efa8bfab395cacea6cde9df93fae55e Mon Sep 17 00:00:00 2001 From: Whysoserioushah Date: Sat, 25 Jan 2025 07:03:47 +0000 Subject: [PATCH 508/681] feat(Mathlib/Algebra/BrauerGroup/Defs): define Brauer Equivalence and Brauer Group (#20968) co-authored by: @jjaassoonn Co-authored-by: Whysoserioushah <109107491+Whysoserioushah@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/Algebra/BrauerGroup/Defs.lean | 93 +++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 Mathlib/Algebra/BrauerGroup/Defs.lean diff --git a/Mathlib.lean b/Mathlib.lean index a2b1ae1bd0ba9..9346f01dec3ad 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -64,6 +64,7 @@ import Mathlib.Algebra.BigOperators.Ring.Nat import Mathlib.Algebra.BigOperators.RingEquiv import Mathlib.Algebra.BigOperators.Sym import Mathlib.Algebra.BigOperators.WithTop +import Mathlib.Algebra.BrauerGroup.Defs import Mathlib.Algebra.Category.AlgebraCat.Basic import Mathlib.Algebra.Category.AlgebraCat.Limits import Mathlib.Algebra.Category.AlgebraCat.Monoidal diff --git a/Mathlib/Algebra/BrauerGroup/Defs.lean b/Mathlib/Algebra/BrauerGroup/Defs.lean new file mode 100644 index 0000000000000..02c990d52f2ac --- /dev/null +++ b/Mathlib/Algebra/BrauerGroup/Defs.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2025 Yunzhou Xie. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yunzhou Xie, Jujian Zhang +-/ +import Mathlib.Algebra.Central.Defs +import Mathlib.LinearAlgebra.FiniteDimensional.Defs +import Mathlib.LinearAlgebra.Matrix.Reindex +import Mathlib.Algebra.Category.AlgebraCat.Basic + +/-! +# Definition of Brauer group of a field K + +We introduce the definition of Brauer group of a field K, which is the quotient of the set of +all finite-dimensional central simple algebras over K modulo the Brauer Equivalence where two +central simple algebras `A` and `B` are Brauer Equivalent if there exist `n, m ∈ ℕ+` such +that `Mₙ(A) ≃ₐ[K] Mₙ(B)`. + +# TODOs +1. Prove that the Brauer group is an abelian group where multiplication is defined as tensorproduct. +2. Prove that the Brauer group is a functor from the category of fields to the category of groups. +3. Prove that over a field, being Brauer equivalent is the same as being Morita equivalent. + +# References +* [Algebraic Number Theory, *J.W.S Cassels*][cassels1967algebraic] + +## Tags +Brauer group, Central simple algebra, Galois Cohomology +-/ + +universe u v + +/-- `CSA` is the set of all finite dimensional central simple algebras over field `K`, for its + generalisation over a `CommRing` please find `IsAzumaya` in `Mathlib.Algebra.Azumaya.Defs`. -/ +structure CSA (K : Type u) [Field K] extends AlgebraCat.{v} K where + /-- Any member of `CSA` is central. -/ + [isCentral : Algebra.IsCentral K carrier] + /-- Any member of `CSA` is simple. -/ + [isSimple : IsSimpleRing carrier] + /-- Any member of `CSA` is finite-dimensional. -/ + [fin_dim : FiniteDimensional K carrier] + +variable {K : Type u} [Field K] + +instance : CoeSort (CSA.{u, v} K) (Type v) := ⟨(·.carrier)⟩ + +attribute [instance] CSA.isCentral CSA.isSimple CSA.fin_dim + +/-- Two finite dimensional central simple algebras `A` and `B` are Brauer Equivalent + if there exist `n, m ∈ ℕ+` such that the `Mₙ(A) ≃ₐ[K] Mₙ(B)`. -/ +abbrev IsBrauerEquivalent (A B : CSA K) : Prop := + ∃n m : ℕ, n ≠ 0 ∧ m ≠ 0 ∧ (Nonempty <| Matrix (Fin n) (Fin n) A ≃ₐ[K] Matrix (Fin m) (Fin m) B) + +namespace IsBrauerEquivalent + +@[refl] +lemma refl (A : CSA K) : IsBrauerEquivalent A A := + ⟨1, 1, one_ne_zero, one_ne_zero, ⟨AlgEquiv.refl⟩⟩ + +@[symm] +lemma symm {A B : CSA K} (h : IsBrauerEquivalent A B) : IsBrauerEquivalent B A := + let ⟨n, m, hn, hm, ⟨iso⟩⟩ := h + ⟨m, n, hm, hn, ⟨iso.symm⟩⟩ + +open Matrix in +@[trans] +lemma trans {A B C : CSA K} (hAB : IsBrauerEquivalent A B) (hBC : IsBrauerEquivalent B C) : + IsBrauerEquivalent A C := by + obtain ⟨n, m, hn, hm, ⟨iso1⟩⟩ := hAB + obtain ⟨p, q, hp, hq, ⟨iso2⟩⟩ := hBC + exact ⟨p * n, m * q, by simp_all, by simp_all, + ⟨reindexAlgEquiv _ _ finProdFinEquiv |>.symm.trans <| compAlgEquiv _ _ _ _|>.symm.trans <| + iso1.mapMatrix (m := Fin p)|>.trans <| compAlgEquiv _ _ _ _|>.trans <| + reindexAlgEquiv K B (.prodComm (Fin p) (Fin m))|>.trans <| compAlgEquiv _ _ _ _|>.symm.trans <| + iso2.mapMatrix.trans <| compAlgEquiv _ _ _ _|>.trans <| reindexAlgEquiv _ _ finProdFinEquiv⟩⟩ + +lemma is_eqv : Equivalence (IsBrauerEquivalent (K := K)) where + refl := refl + symm := symm + trans := trans + +end IsBrauerEquivalent + +variable (K) + +/-- `CSA` equipped with Brauer Equivalence is indeed a setoid. -/ +def Brauer.CSA_Setoid: Setoid (CSA K) where + r := IsBrauerEquivalent + iseqv := IsBrauerEquivalent.is_eqv + +/-- `BrauerGroup` is the set of all finite-dimensional central simple algebras quotient + by Brauer Equivalence. -/ +abbrev BrauerGroup := Quotient (Brauer.CSA_Setoid K) From f7d835ab34f2a214021059196e8bbd8ba208f359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 25 Jan 2025 07:03:48 +0000 Subject: [PATCH 509/681] feat: the product of L^p functions is L^p' (#21033) Co-authored-by: Kexing Ying --- .../Function/LpSeminorm/CompareExp.lean | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean index 9661035b3d111..649bc7c74f6ed 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean @@ -411,4 +411,26 @@ theorem Memℒp.mul_of_top_left' (hf : Memℒp f ∞ μ) (hφ : Memℒp φ p μ) end Mul +section Prod +variable {ι α 𝕜 : Type*} {_ : MeasurableSpace α} [NormedCommRing 𝕜] {μ : Measure α} {f : ι → α → 𝕜} + {p : ι → ℝ≥0∞} {s : Finset ι} + +open Finset in +/-- See `Memℒp.prod'` for the applied version. -/ +protected lemma Memℒp.prod (hf : ∀ i ∈ s, Memℒp (f i) (p i) μ) : + Memℒp (∏ i ∈ s, f i) (∑ i ∈ s, (p i)⁻¹)⁻¹ μ := by + induction s using cons_induction with + | empty => + by_cases hμ : μ = 0 <;> + simp [Memℒp, eLpNormEssSup_const, hμ, aestronglyMeasurable_const, Pi.one_def] + | cons i s hi ih => + rw [prod_cons] + exact (ih <| forall_of_forall_cons hf).mul (hf i <| mem_cons_self ..) (by simp) + +/-- See `Memℒp.prod` for the unapplied version. -/ +protected lemma Memℒp.prod' (hf : ∀ i ∈ s, Memℒp (f i) (p i) μ) : + Memℒp (fun ω ↦ ∏ i ∈ s, f i ω) (∑ i ∈ s, (p i)⁻¹)⁻¹ μ := by + simpa [Finset.prod_fn] using Memℒp.prod hf + +end Prod end MeasureTheory From a1c3eb58f5c4a53545775eb3e54f94714f5a24bd Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Sat, 25 Jan 2025 08:15:06 +0000 Subject: [PATCH 510/681] feat: functoriality of coimage-image comparison (#21044) Co-authored-by: Markus Himmel --- Mathlib/CategoryTheory/Abelian/Images.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/CategoryTheory/Abelian/Images.lean b/Mathlib/CategoryTheory/Abelian/Images.lean index 1bed70213ca90..1d4f4e9e92564 100644 --- a/Mathlib/CategoryTheory/Abelian/Images.lean +++ b/Mathlib/CategoryTheory/Abelian/Images.lean @@ -106,4 +106,12 @@ theorem coimageImageComparison_eq_coimageImageComparison' : theorem coimage_image_factorisation : coimage.π f ≫ coimageImageComparison f ≫ image.ι f = f := by simp [coimageImageComparison] +/-- The coimage-image comparison morphism is functorial. -/ +@[simps!] +def coimageImageComparisonFunctor : Arrow C ⥤ Arrow C where + obj f := Arrow.mk (coimageImageComparison f.hom) + map {f g} η := Arrow.homMk + (cokernel.map _ _ (kernel.map _ _ η.left η.right (by simp)) η.left (by simp)) + (kernel.map _ _ η.right (cokernel.map _ _ η.left η.right (by simp)) (by simp)) (by aesop_cat) + end CategoryTheory.Abelian From 070b12d842dfb0856aebb83a5b49c71aa3e252a3 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Sat, 25 Jan 2025 08:30:45 +0000 Subject: [PATCH 511/681] fix: remove a nonsensical to_additive (#21040) There's nothing to additivize here. --- Mathlib/Algebra/Equiv/TransferInstance.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/Algebra/Equiv/TransferInstance.lean b/Mathlib/Algebra/Equiv/TransferInstance.lean index 4555c2270dd82..13b89b97205f4 100644 --- a/Mathlib/Algebra/Equiv/TransferInstance.lean +++ b/Mathlib/Algebra/Equiv/TransferInstance.lean @@ -205,7 +205,6 @@ protected abbrev semigroupWithZero [SemigroupWithZero β] : SemigroupWithZero α let zero := e.zero apply e.injective.semigroupWithZero _ <;> intros <;> exact e.apply_symm_apply _ -@[to_additive] noncomputable instance [Small.{v} α] [SemigroupWithZero α] : SemigroupWithZero (Shrink.{v} α) := (equivShrink α).symm.semigroupWithZero From 319694c02ee0e84e316396bb7d4f11241eb07e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 25 Jan 2025 09:32:19 +0000 Subject: [PATCH 512/681] refactor: merge `AEStronglyMeasurable` and `AEStronglyMeasurable'` (#20932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `AEStronglyMeasurable` is a convenient special case of `AEStronglyMeasurable'`, but we can tweak the argument implicitness so that `AEStronglyMeasurable f μ` means the same thing as before while `AEStronglyMeasurable[m] f μ` means the same thing as the current `AEStronglyMeasurable' m f μ`. --- .../Fourier/FourierTransformDeriv.lean | 4 +- .../ConditionalExpectation/AEMeasurable.lean | 238 ++++++++-------- .../ConditionalExpectation/Basic.lean | 23 +- .../ConditionalExpectation/CondexpL1.lean | 57 ++-- .../ConditionalExpectation/CondexpL2.lean | 56 ++-- .../ConditionalExpectation/Indicator.lean | 11 +- .../Function/ConditionalExpectation/Real.lean | 8 +- .../ConditionalExpectation/Unique.lean | 13 +- Mathlib/MeasureTheory/Function/L1Space.lean | 2 +- .../Function/LpSeminorm/Trim.lean | 2 +- .../Function/StronglyMeasurable/Basic.lean | 256 +++++++++++------- .../Function/StronglyMeasurable/Inner.lean | 28 +- Mathlib/MeasureTheory/Integral/Bochner.lean | 25 +- .../Probability/ConditionalExpectation.lean | 2 +- .../Probability/Independence/Conditional.lean | 13 +- Mathlib/Probability/Kernel/CondDistrib.lean | 12 +- Mathlib/Probability/Kernel/Condexp.lean | 28 +- .../Kernel/Disintegration/Density.lean | 2 +- .../Probability/Martingale/Convergence.lean | 6 +- .../Martingale/OptionalSampling.lean | 4 +- scripts/nolints_prime_decls.txt | 5 +- 21 files changed, 413 insertions(+), 382 deletions(-) diff --git a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean index fe95597e697b1..da429e36827e9 100644 --- a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean +++ b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean @@ -806,9 +806,7 @@ theorem iteratedDeriv_fourierIntegral {f : ℝ → E} {N : ℕ∞} {n : ℕ} have A (n : ℕ) (hn : n ≤ N) : Integrable (fun v ↦ ‖v‖^n * ‖f v‖) := by convert (hf n hn).norm with x simp [norm_smul] - have B : AEStronglyMeasurable f := by - convert (hf 0 (zero_le _)).1 with x - simp + have B : AEStronglyMeasurable f := by simpa using (hf 0 (zero_le _)).1 rw [iteratedDeriv, iteratedFDeriv_fourierIntegral A B hn, fourierIntegral_continuousMultilinearMap_apply (integrable_fourierPowSMulRight _ (A n hn) B), fourierIntegral_eq, fourierIntegral_eq] diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean index 95319082eb996..164391648cfb7 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean @@ -3,21 +3,19 @@ Copyright (c) 2021 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.Function.StronglyMeasurable.Lp -import Mathlib.MeasureTheory.Integral.Bochner -import Mathlib.Order.Filter.IndicatorFunction -import Mathlib.MeasureTheory.Function.StronglyMeasurable.Inner import Mathlib.MeasureTheory.Function.LpSeminorm.Trim +import Mathlib.MeasureTheory.Function.StronglyMeasurable.Inner +import Mathlib.MeasureTheory.Function.StronglyMeasurable.Lp /-! # Functions a.e. measurable with respect to a sub-σ-algebra -A function `f` verifies `AEStronglyMeasurable' m f μ` if it is `μ`-a.e. equal to +A function `f` verifies `AEStronglyMeasurable[m] f μ` if it is `μ`-a.e. equal to an `m`-strongly measurable function. This is similar to `AEStronglyMeasurable`, but the `MeasurableSpace` structures used for the measurability statement and for the measure are different. We define `lpMeas F 𝕜 m p μ`, the subspace of `Lp F p μ` containing functions `f` verifying -`AEStronglyMeasurable' m f μ`, i.e. functions which are `μ`-a.e. equal to an `m`-strongly +`AEStronglyMeasurable[m] f μ`, i.e. functions which are `μ`-a.e. equal to an `m`-strongly measurable function. ## Main statements @@ -42,104 +40,97 @@ open scoped ENNReal MeasureTheory namespace MeasureTheory -/-- A function `f` verifies `AEStronglyMeasurable' m f μ` if it is `μ`-a.e. equal to +/-- A function `f` verifies `AEStronglyMeasurable[m] f μ` if it is `μ`-a.e. equal to an `m`-strongly measurable function. This is similar to `AEStronglyMeasurable`, but the `MeasurableSpace` structures used for the measurability statement and for the measure are different. -/ +@[deprecated AEStronglyMeasurable (since := "2025-01-23")] def AEStronglyMeasurable' {α β} [TopologicalSpace β] (m : MeasurableSpace α) - {_ : MeasurableSpace α} (f : α → β) (μ : Measure α) : Prop := - ∃ g : α → β, StronglyMeasurable[m] g ∧ f =ᵐ[μ] g + {_ : MeasurableSpace α} (f : α → β) (μ : Measure α) : Prop := AEStronglyMeasurable[m] f μ + +set_option linter.deprecated false namespace AEStronglyMeasurable' variable {α β 𝕜 : Type*} {m m0 : MeasurableSpace α} {μ : Measure α} [TopologicalSpace β] {f g : α → β} -theorem congr (hf : AEStronglyMeasurable' m f μ) (hfg : f =ᵐ[μ] g) : - AEStronglyMeasurable' m g μ := by - obtain ⟨f', hf'_meas, hff'⟩ := hf; exact ⟨f', hf'_meas, hfg.symm.trans hff'⟩ - -theorem mono {m'} (hf : AEStronglyMeasurable' m f μ) (hm : m ≤ m') : - AEStronglyMeasurable' m' f μ := - let ⟨f', hf'_meas, hff'⟩ := hf; ⟨f', hf'_meas.mono hm, hff'⟩ - -theorem add [Add β] [ContinuousAdd β] (hf : AEStronglyMeasurable' m f μ) - (hg : AEStronglyMeasurable' m g μ) : AEStronglyMeasurable' m (f + g) μ := by - rcases hf with ⟨f', h_f'_meas, hff'⟩ - rcases hg with ⟨g', h_g'_meas, hgg'⟩ - exact ⟨f' + g', h_f'_meas.add h_g'_meas, hff'.add hgg'⟩ - -theorem neg [AddGroup β] [TopologicalAddGroup β] {f : α → β} (hfm : AEStronglyMeasurable' m f μ) : - AEStronglyMeasurable' m (-f) μ := by - rcases hfm with ⟨f', hf'_meas, hf_ae⟩ - refine ⟨-f', hf'_meas.neg, hf_ae.mono fun x hx => ?_⟩ - simp_rw [Pi.neg_apply] - rw [hx] - -theorem sub [AddGroup β] [TopologicalAddGroup β] {f g : α → β} (hfm : AEStronglyMeasurable' m f μ) - (hgm : AEStronglyMeasurable' m g μ) : AEStronglyMeasurable' m (f - g) μ := by - rcases hfm with ⟨f', hf'_meas, hf_ae⟩ - rcases hgm with ⟨g', hg'_meas, hg_ae⟩ - refine ⟨f' - g', hf'_meas.sub hg'_meas, hf_ae.mp (hg_ae.mono fun x hx1 hx2 => ?_)⟩ - simp_rw [Pi.sub_apply] - rw [hx1, hx2] - -theorem const_smul [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] (c : 𝕜) (hf : AEStronglyMeasurable' m f μ) : - AEStronglyMeasurable' m (c • f) μ := by - rcases hf with ⟨f', h_f'_meas, hff'⟩ - refine ⟨c • f', h_f'_meas.const_smul c, ?_⟩ - exact EventuallyEq.fun_comp hff' fun x => c • x +@[deprecated AEStronglyMeasurable.congr (since := "2025-01-23")] +theorem congr (hf : AEStronglyMeasurable[m] f μ) (hfg : f =ᵐ[μ] g) : + AEStronglyMeasurable[m] g μ := AEStronglyMeasurable.congr hf hfg + +@[deprecated AEStronglyMeasurable.mono (since := "2025-01-23")] +theorem mono {m'} (hf : AEStronglyMeasurable[m] f μ) (hm : m ≤ m') : + AEStronglyMeasurable' m' f μ := AEStronglyMeasurable.mono hm hf + +@[deprecated AEStronglyMeasurable.add (since := "2025-01-23")] +theorem add [Add β] [ContinuousAdd β] (hf : AEStronglyMeasurable[m] f μ) + (hg : AEStronglyMeasurable[m] g μ) : AEStronglyMeasurable[m] (f + g) μ := + AEStronglyMeasurable.add hf hg + +@[deprecated AEStronglyMeasurable.neg (since := "2025-01-23")] +theorem neg [AddGroup β] [TopologicalAddGroup β] {f : α → β} (hfm : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] (-f) μ := + AEStronglyMeasurable.neg hfm +@[deprecated AEStronglyMeasurable.sub (since := "2025-01-23")] +theorem sub [AddGroup β] [TopologicalAddGroup β] {f g : α → β} (hfm : AEStronglyMeasurable[m] f μ) + (hgm : AEStronglyMeasurable[m] g μ) : AEStronglyMeasurable[m] (f - g) μ := + AEStronglyMeasurable.sub hfm hgm + +@[deprecated AEStronglyMeasurable.const_smul (since := "2025-01-23")] +theorem const_smul [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] (c : 𝕜) (hf : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] (c • f) μ := + AEStronglyMeasurable.const_smul hf _ + +@[deprecated AEStronglyMeasurable.const_inner (since := "2025-01-23")] theorem const_inner {𝕜 β} [RCLike 𝕜] [NormedAddCommGroup β] [InnerProductSpace 𝕜 β] {f : α → β} - (hfm : AEStronglyMeasurable' m f μ) (c : β) : - AEStronglyMeasurable' m (fun x => (inner c (f x) : 𝕜)) μ := by - rcases hfm with ⟨f', hf'_meas, hf_ae⟩ - refine - ⟨fun x => (inner c (f' x) : 𝕜), (@stronglyMeasurable_const _ _ m _ c).inner hf'_meas, - hf_ae.mono fun x hx => ?_⟩ - dsimp only - rw [hx] + (hfm : AEStronglyMeasurable[m] f μ) (c : β) : + AEStronglyMeasurable[m] (fun x => (inner c (f x) : 𝕜)) μ := + AEStronglyMeasurable.const_inner hfm -@[simp] theorem of_subsingleton [Subsingleton β] : AEStronglyMeasurable' m f μ := - ⟨f, by simp, by simp⟩ +@[deprecated AEStronglyMeasurable.of_subsingleton_cod (since := "2025-01-23")] +theorem of_subsingleton [Subsingleton β] : AEStronglyMeasurable[m] f μ := .of_subsingleton_cod -@[simp] theorem of_subsingleton' [Subsingleton α] : AEStronglyMeasurable' m f μ := - ⟨f, by simp, by simp⟩ +@[deprecated AEStronglyMeasurable.of_subsingleton_dom (since := "2025-01-23")] +theorem of_subsingleton' [Subsingleton α] : AEStronglyMeasurable[m] f μ := .of_subsingleton_dom /-- An `m`-strongly measurable function almost everywhere equal to `f`. -/ -noncomputable def mk (f : α → β) (hfm : AEStronglyMeasurable' m f μ) : α → β := - hfm.choose +@[deprecated AEStronglyMeasurable.mk (since := "2025-01-23")] +noncomputable def mk (f : α → β) (hfm : AEStronglyMeasurable[m] f μ) : α → β := + AEStronglyMeasurable.mk f hfm -theorem stronglyMeasurable_mk {f : α → β} (hfm : AEStronglyMeasurable' m f μ) : +@[deprecated AEStronglyMeasurable.stronglyMeasurable_mk (since := "2025-01-23")] +theorem stronglyMeasurable_mk {f : α → β} (hfm : AEStronglyMeasurable[m] f μ) : StronglyMeasurable[m] (hfm.mk f) := - hfm.choose_spec.1 + AEStronglyMeasurable.stronglyMeasurable_mk hfm -theorem ae_eq_mk {f : α → β} (hfm : AEStronglyMeasurable' m f μ) : f =ᵐ[μ] hfm.mk f := - hfm.choose_spec.2 +@[deprecated AEStronglyMeasurable.ae_eq_mk (since := "2025-01-23")] +theorem ae_eq_mk {f : α → β} (hfm : AEStronglyMeasurable[m] f μ) : f =ᵐ[μ] hfm.mk f := + AEStronglyMeasurable.ae_eq_mk hfm +@[deprecated Continuous.comp_aestronglyMeasurable (since := "2025-01-23")] theorem continuous_comp {γ} [TopologicalSpace γ] {f : α → β} {g : β → γ} (hg : Continuous g) - (hf : AEStronglyMeasurable' m f μ) : AEStronglyMeasurable' m (g ∘ f) μ := - ⟨fun x => g (hf.mk _ x), - @Continuous.comp_stronglyMeasurable _ _ _ m _ _ _ _ hg hf.stronglyMeasurable_mk, - hf.ae_eq_mk.mono fun x hx => by rw [Function.comp_apply, hx]⟩ + (hf : AEStronglyMeasurable[m] f μ) : AEStronglyMeasurable[m] (g ∘ f) μ := + hg.comp_aestronglyMeasurable hf end AEStronglyMeasurable' +@[deprecated AEStronglyMeasurable.of_trim (since := "2025-01-23")] theorem aeStronglyMeasurable'_of_aeStronglyMeasurable'_trim {α β} {m m0 m0' : MeasurableSpace α} [TopologicalSpace β] (hm0 : m0 ≤ m0') {μ : Measure α} {f : α → β} - (hf : AEStronglyMeasurable' m f (μ.trim hm0)) : AEStronglyMeasurable' m f μ := by - obtain ⟨g, hg_meas, hfg⟩ := hf; exact ⟨g, hg_meas, ae_eq_of_ae_eq_trim hfg⟩ + (hf : AEStronglyMeasurable[m] f (μ.trim hm0)) : AEStronglyMeasurable[m] f μ := .of_trim hm0 hf +@[deprecated StronglyMeasurable.aestronglyMeasurable (since := "2025-01-23")] theorem StronglyMeasurable.aeStronglyMeasurable' {α β} {m _ : MeasurableSpace α} [TopologicalSpace β] {μ : Measure α} {f : α → β} (hf : StronglyMeasurable[m] f) : - AEStronglyMeasurable' m f μ := - ⟨f, hf, ae_eq_refl _⟩ + AEStronglyMeasurable[m] f μ := hf.aestronglyMeasurable theorem ae_eq_trim_iff_of_aeStronglyMeasurable' {α β} [TopologicalSpace β] [MetrizableSpace β] {m m0 : MeasurableSpace α} {μ : Measure α} {f g : α → β} (hm : m ≤ m0) - (hfm : AEStronglyMeasurable' m f μ) (hgm : AEStronglyMeasurable' m g μ) : + (hfm : AEStronglyMeasurable[m] f μ) (hgm : AEStronglyMeasurable[m] g μ) : hfm.mk f =ᵐ[μ.trim hm] hgm.mk g ↔ f =ᵐ[μ] g := - (ae_eq_trim_iff hm hfm.stronglyMeasurable_mk hgm.stronglyMeasurable_mk).trans + (hfm.stronglyMeasurable_mk.ae_eq_trim_iff hm hgm.stronglyMeasurable_mk).trans ⟨fun h => hfm.ae_eq_mk.trans (h.trans hgm.ae_eq_mk.symm), fun h => hfm.ae_eq_mk.symm.trans (h.trans hgm.ae_eq_mk)⟩ @@ -154,26 +145,14 @@ theorem AEStronglyMeasurable.comp_ae_measurable' {α β γ : Type*} [Topological another σ-algebra `m₂` (hypothesis `hs`), the set `s` is `m` measurable and a function `f` almost everywhere supported on `s` is `m`-ae-strongly-measurable, then `f` is also `m₂`-ae-strongly-measurable. -/ +@[deprecated AEStronglyMeasurable.of_measurableSpace_le_on (since := "2025-01-23")] theorem AEStronglyMeasurable'.aeStronglyMeasurable'_of_measurableSpace_le_on {α E} {m m₂ m0 : MeasurableSpace α} {μ : Measure α} [TopologicalSpace E] [Zero E] (hm : m ≤ m0) {s : Set α} {f : α → E} (hs_m : MeasurableSet[m] s) (hs : ∀ t, MeasurableSet[m] (s ∩ t) → MeasurableSet[m₂] (s ∩ t)) - (hf : AEStronglyMeasurable' m f μ) (hf_zero : f =ᵐ[μ.restrict sᶜ] 0) : - AEStronglyMeasurable' m₂ f μ := by - have h_ind_eq : s.indicator (hf.mk f) =ᵐ[μ] f := by - refine Filter.EventuallyEq.trans ?_ <| - indicator_ae_eq_of_restrict_compl_ae_eq_zero (hm _ hs_m) hf_zero - filter_upwards [hf.ae_eq_mk] with x hx - by_cases hxs : x ∈ s - · simp [hxs, hx] - · simp [hxs] - suffices StronglyMeasurable[m₂] (s.indicator (hf.mk f)) from - AEStronglyMeasurable'.congr this.aeStronglyMeasurable' h_ind_eq - have hf_ind : StronglyMeasurable[m] (s.indicator (hf.mk f)) := - hf.stronglyMeasurable_mk.indicator hs_m - exact - hf_ind.stronglyMeasurable_of_measurableSpace_le_on hs_m hs fun x hxs => - Set.indicator_of_not_mem hxs _ + (hf : AEStronglyMeasurable[m] f μ) (hf_zero : f =ᵐ[μ.restrict sᶜ] 0) : + AEStronglyMeasurable' m₂ f μ := + .of_measurableSpace_le_on hm hs_m hs hf hf_zero variable {α F 𝕜 : Type*} {p : ℝ≥0∞} [RCLike 𝕜] -- 𝕜 for ℝ or ℂ @@ -188,44 +167,53 @@ section LpMeas variable (F) /-- `lpMeasSubgroup F m p μ` is the subspace of `Lp F p μ` containing functions `f` verifying -`AEStronglyMeasurable' m f μ`, i.e. functions which are `μ`-a.e. equal to +`AEStronglyMeasurable[m] f μ`, i.e. functions which are `μ`-a.e. equal to an `m`-strongly measurable function. -/ def lpMeasSubgroup (m : MeasurableSpace α) [MeasurableSpace α] (p : ℝ≥0∞) (μ : Measure α) : AddSubgroup (Lp F p μ) where - carrier := {f : Lp F p μ | AEStronglyMeasurable' m f μ} + carrier := {f : Lp F p μ | AEStronglyMeasurable[m] f μ} zero_mem' := ⟨(0 : α → F), @stronglyMeasurable_zero _ _ m _ _, Lp.coeFn_zero _ _ _⟩ add_mem' {f g} hf hg := (hf.add hg).congr (Lp.coeFn_add f g).symm - neg_mem' {f} hf := AEStronglyMeasurable'.congr hf.neg (Lp.coeFn_neg f).symm + neg_mem' {f} hf := AEStronglyMeasurable.congr hf.neg (Lp.coeFn_neg f).symm variable (𝕜) /-- `lpMeas F 𝕜 m p μ` is the subspace of `Lp F p μ` containing functions `f` verifying -`AEStronglyMeasurable' m f μ`, i.e. functions which are `μ`-a.e. equal to +`AEStronglyMeasurable[m] f μ`, i.e. functions which are `μ`-a.e. equal to an `m`-strongly measurable function. -/ def lpMeas (m : MeasurableSpace α) [MeasurableSpace α] (p : ℝ≥0∞) (μ : Measure α) : Submodule 𝕜 (Lp F p μ) where - carrier := {f : Lp F p μ | AEStronglyMeasurable' m f μ} + carrier := {f : Lp F p μ | AEStronglyMeasurable[m] f μ} zero_mem' := ⟨(0 : α → F), @stronglyMeasurable_zero _ _ m _ _, Lp.coeFn_zero _ _ _⟩ add_mem' {f g} hf hg := (hf.add hg).congr (Lp.coeFn_add f g).symm smul_mem' c f hf := (hf.const_smul c).congr (Lp.coeFn_smul c f).symm variable {F 𝕜} -theorem mem_lpMeasSubgroup_iff_aeStronglyMeasurable' {m m0 : MeasurableSpace α} {μ : Measure α} - {f : Lp F p μ} : f ∈ lpMeasSubgroup F m p μ ↔ AEStronglyMeasurable' m f μ := by +theorem mem_lpMeasSubgroup_iff_aeStronglyMeasurable {m m0 : MeasurableSpace α} {μ : Measure α} + {f : Lp F p μ} : f ∈ lpMeasSubgroup F m p μ ↔ AEStronglyMeasurable[m] f μ := by rw [← AddSubgroup.mem_carrier, lpMeasSubgroup, Set.mem_setOf_eq] -theorem mem_lpMeas_iff_aeStronglyMeasurable' {m m0 : MeasurableSpace α} {μ : Measure α} - {f : Lp F p μ} : f ∈ lpMeas F 𝕜 m p μ ↔ AEStronglyMeasurable' m f μ := by +@[deprecated (since := "2025-01-24")] +alias mem_lpMeasSubgroup_iff_aeStronglyMeasurable' := mem_lpMeasSubgroup_iff_aeStronglyMeasurable + +theorem mem_lpMeas_iff_aeStronglyMeasurable {m m0 : MeasurableSpace α} {μ : Measure α} + {f : Lp F p μ} : f ∈ lpMeas F 𝕜 m p μ ↔ AEStronglyMeasurable[m] f μ := by rw [← SetLike.mem_coe, ← Submodule.mem_carrier, lpMeas, Set.mem_setOf_eq] -theorem lpMeas.aeStronglyMeasurable' {m _ : MeasurableSpace α} {μ : Measure α} - (f : lpMeas F 𝕜 m p μ) : AEStronglyMeasurable' (β := F) m f μ := - mem_lpMeas_iff_aeStronglyMeasurable'.mp f.mem +@[deprecated (since := "2025-01-24")] +alias mem_lpMeas_iff_aeStronglyMeasurable' := mem_lpMeas_iff_aeStronglyMeasurable + +theorem lpMeas.aeStronglyMeasurable {m _ : MeasurableSpace α} {μ : Measure α} + (f : lpMeas F 𝕜 m p μ) : AEStronglyMeasurable[m] (f : α → F) μ := + mem_lpMeas_iff_aeStronglyMeasurable.mp f.mem + +@[deprecated (since := "2025-01-24")] +alias lpMeas.aeStronglyMeasurable' := lpMeas.aeStronglyMeasurable theorem mem_lpMeas_self {m0 : MeasurableSpace α} (μ : Measure α) (f : Lp F p μ) : f ∈ lpMeas F 𝕜 m0 p μ := - mem_lpMeas_iff_aeStronglyMeasurable'.mpr (Lp.aestronglyMeasurable f) + mem_lpMeas_iff_aeStronglyMeasurable.mpr (Lp.aestronglyMeasurable f) theorem lpMeasSubgroup_coe {m _ : MeasurableSpace α} {μ : Measure α} {f : lpMeasSubgroup F m p μ} : (f : _ → _) = (f : Lp F p μ) := @@ -256,9 +244,9 @@ variable {m m0 : MeasurableSpace α} {μ : Measure α} everywhere equal to (given by `AEMeasurable.mk`) belongs to `ℒp` for the measure `μ.trim hm`. -/ theorem memℒp_trim_of_mem_lpMeasSubgroup (hm : m ≤ m0) (f : Lp F p μ) (hf_meas : f ∈ lpMeasSubgroup F m p μ) : - Memℒp (mem_lpMeasSubgroup_iff_aeStronglyMeasurable'.mp hf_meas).choose p (μ.trim hm) := by - have hf : AEStronglyMeasurable' m f μ := - mem_lpMeasSubgroup_iff_aeStronglyMeasurable'.mp hf_meas + Memℒp (mem_lpMeasSubgroup_iff_aeStronglyMeasurable.mp hf_meas).choose p (μ.trim hm) := by + have hf : AEStronglyMeasurable[m] f μ := + mem_lpMeasSubgroup_iff_aeStronglyMeasurable.mp hf_meas let g := hf.choose obtain ⟨hg, hfg⟩ := hf.choose_spec change Memℒp g p (μ.trim hm) @@ -274,7 +262,7 @@ theorem memℒp_trim_of_mem_lpMeasSubgroup (hm : m ≤ m0) (f : Lp F p μ) theorem mem_lpMeasSubgroup_toLp_of_trim (hm : m ≤ m0) (f : Lp F p (μ.trim hm)) : (memℒp_of_memℒp_trim hm (Lp.memℒp f)).toLp f ∈ lpMeasSubgroup F m p μ := by let hf_mem_ℒp := memℒp_of_memℒp_trim hm (Lp.memℒp f) - rw [mem_lpMeasSubgroup_iff_aeStronglyMeasurable'] + rw [mem_lpMeasSubgroup_iff_aeStronglyMeasurable] refine AEStronglyMeasurable'.congr ?_ (Memℒp.coeFn_toLp hf_mem_ℒp).symm refine aeStronglyMeasurable'_of_aeStronglyMeasurable'_trim hm ?_ exact Lp.aestronglyMeasurable f @@ -284,7 +272,7 @@ variable (F p μ) /-- Map from `lpMeasSubgroup` to `Lp F p (μ.trim hm)`. -/ noncomputable def lpMeasSubgroupToLpTrim (hm : m ≤ m0) (f : lpMeasSubgroup F m p μ) : Lp F p (μ.trim hm) := - Memℒp.toLp (mem_lpMeasSubgroup_iff_aeStronglyMeasurable'.mp f.mem).choose + Memℒp.toLp (mem_lpMeasSubgroup_iff_aeStronglyMeasurable.mp f.mem).choose -- Porting note: had to replace `f` with `f.1` here. (memℒp_trim_of_mem_lpMeasSubgroup hm f.1 f.mem) @@ -292,7 +280,7 @@ variable (𝕜) /-- Map from `lpMeas` to `Lp F p (μ.trim hm)`. -/ noncomputable def lpMeasToLpTrim (hm : m ≤ m0) (f : lpMeas F 𝕜 m p μ) : Lp F p (μ.trim hm) := - Memℒp.toLp (mem_lpMeas_iff_aeStronglyMeasurable'.mp f.mem).choose + Memℒp.toLp (mem_lpMeas_iff_aeStronglyMeasurable.mp f.mem).choose -- Porting note: had to replace `f` with `f.1` here. (memℒp_trim_of_mem_lpMeasSubgroup hm f.1 f.mem) @@ -316,7 +304,7 @@ theorem lpMeasSubgroupToLpTrim_ae_eq (hm : m ≤ m0) (f : lpMeasSubgroup F m p lpMeasSubgroupToLpTrim F p μ hm f =ᵐ[μ] f := -- Porting note: replaced `(↑f)` with `f.1` here. (ae_eq_of_ae_eq_trim (Memℒp.coeFn_toLp (memℒp_trim_of_mem_lpMeasSubgroup hm f.1 f.mem))).trans - (mem_lpMeasSubgroup_iff_aeStronglyMeasurable'.mp f.mem).choose_spec.2.symm + (mem_lpMeasSubgroup_iff_aeStronglyMeasurable.mp f.mem).choose_spec.2.symm theorem lpTrimToLpMeasSubgroup_ae_eq (hm : m ≤ m0) (f : Lp F p (μ.trim hm)) : lpTrimToLpMeasSubgroup F p μ hm f =ᵐ[μ] f := @@ -327,7 +315,7 @@ theorem lpMeasToLpTrim_ae_eq (hm : m ≤ m0) (f : lpMeas F 𝕜 m p μ) : lpMeasToLpTrim F 𝕜 p μ hm f =ᵐ[μ] f := -- Porting note: replaced `(↑f)` with `f.1` here. (ae_eq_of_ae_eq_trim (Memℒp.coeFn_toLp (memℒp_trim_of_mem_lpMeasSubgroup hm f.1 f.mem))).trans - (mem_lpMeasSubgroup_iff_aeStronglyMeasurable'.mp f.mem).choose_spec.2.symm + (mem_lpMeasSubgroup_iff_aeStronglyMeasurable.mp f.mem).choose_spec.2.symm theorem lpTrimToLpMeas_ae_eq (hm : m ≤ m0) (f : Lp F p (μ.trim hm)) : lpTrimToLpMeas F 𝕜 p μ hm f =ᵐ[μ] f := @@ -340,7 +328,7 @@ theorem lpMeasSubgroupToLpTrim_right_inv (hm : m ≤ m0) : intro f ext1 refine - ae_eq_trim_of_stronglyMeasurable hm (Lp.stronglyMeasurable _) (Lp.stronglyMeasurable _) ?_ + (Lp.stronglyMeasurable _).ae_eq_trim_of_stronglyMeasurable hm (Lp.stronglyMeasurable _) ?_ exact (lpMeasSubgroupToLpTrim_ae_eq hm _).trans (lpTrimToLpMeasSubgroup_ae_eq hm _) /-- `lpTrimToLpMeasSubgroup` is a left inverse of `lpMeasSubgroupToLpTrim`. -/ @@ -357,7 +345,7 @@ theorem lpMeasSubgroupToLpTrim_add (hm : m ≤ m0) (f g : lpMeasSubgroup F m p lpMeasSubgroupToLpTrim F p μ hm f + lpMeasSubgroupToLpTrim F p μ hm g := by ext1 refine EventuallyEq.trans ?_ (Lp.coeFn_add _ _).symm - refine ae_eq_trim_of_stronglyMeasurable hm (Lp.stronglyMeasurable _) ?_ ?_ + refine (Lp.stronglyMeasurable _).ae_eq_trim_of_stronglyMeasurable hm ?_ ?_ · exact (Lp.stronglyMeasurable _).add (Lp.stronglyMeasurable _) refine (lpMeasSubgroupToLpTrim_ae_eq hm _).trans ?_ refine @@ -372,11 +360,9 @@ theorem lpMeasSubgroupToLpTrim_neg (hm : m ≤ m0) (f : lpMeasSubgroup F m p μ) lpMeasSubgroupToLpTrim F p μ hm (-f) = -lpMeasSubgroupToLpTrim F p μ hm f := by ext1 refine EventuallyEq.trans ?_ (Lp.coeFn_neg _).symm - refine ae_eq_trim_of_stronglyMeasurable hm (Lp.stronglyMeasurable _) ?_ ?_ - · exact @StronglyMeasurable.neg _ _ _ m _ _ _ (Lp.stronglyMeasurable _) - refine (lpMeasSubgroupToLpTrim_ae_eq hm _).trans ?_ - refine EventuallyEq.trans ?_ (EventuallyEq.neg (lpMeasSubgroupToLpTrim_ae_eq hm f).symm) - refine (Lp.coeFn_neg _).trans ?_ + refine (Lp.stronglyMeasurable _).ae_eq_trim_of_stronglyMeasurable hm (Lp.stronglyMeasurable _).neg + <| (lpMeasSubgroupToLpTrim_ae_eq hm _).trans <| + ((Lp.coeFn_neg _).trans ?_).trans (lpMeasSubgroupToLpTrim_ae_eq hm f).symm.neg simp_rw [lpMeasSubgroup_coe] exact Eventually.of_forall fun x => by rfl @@ -390,7 +376,7 @@ theorem lpMeasToLpTrim_smul (hm : m ≤ m0) (c : 𝕜) (f : lpMeas F 𝕜 m p μ lpMeasToLpTrim F 𝕜 p μ hm (c • f) = c • lpMeasToLpTrim F 𝕜 p μ hm f := by ext1 refine EventuallyEq.trans ?_ (Lp.coeFn_smul _ _).symm - refine ae_eq_trim_of_stronglyMeasurable hm (Lp.stronglyMeasurable _) ?_ ?_ + refine (Lp.stronglyMeasurable _).ae_eq_trim_of_stronglyMeasurable hm ?_ ?_ · exact (Lp.stronglyMeasurable _).const_smul c refine (lpMeasToLpTrim_ae_eq hm _).trans ?_ refine (Lp.coeFn_smul _ _).trans ?_ @@ -454,14 +440,14 @@ instance [hm : Fact (m ≤ m0)] [CompleteSpace F] [hp : Fact (1 ≤ p)] : rw [(lpMeasSubgroupToLpMeasIso F 𝕜 p μ).symm.completeSpace_iff]; infer_instance theorem isComplete_aeStronglyMeasurable' [hp : Fact (1 ≤ p)] [CompleteSpace F] (hm : m ≤ m0) : - IsComplete {f : Lp F p μ | AEStronglyMeasurable' m f μ} := by + IsComplete {f : Lp F p μ | AEStronglyMeasurable[m] f μ} := by rw [← completeSpace_coe_iff_isComplete] haveI : Fact (m ≤ m0) := ⟨hm⟩ change CompleteSpace (lpMeasSubgroup F m p μ) infer_instance theorem isClosed_aeStronglyMeasurable' [Fact (1 ≤ p)] [CompleteSpace F] (hm : m ≤ m0) : - IsClosed {f : Lp F p μ | AEStronglyMeasurable' m f μ} := + IsClosed {f : Lp F p μ | AEStronglyMeasurable[m] f μ} := IsComplete.isClosed (isComplete_aeStronglyMeasurable' hm) end CompleteSubspace @@ -517,11 +503,11 @@ variable {m m0 : MeasurableSpace α} {μ : Measure α} [Fact (1 ≤ p)] [NormedS theorem Lp.induction_stronglyMeasurable_aux (hm : m ≤ m0) (hp_ne_top : p ≠ ∞) (P : Lp F p μ → Prop) (h_ind : ∀ (c : F) {s : Set α} (hs : MeasurableSet[m] s) (hμs : μ s < ∞), P (Lp.simpleFunc.indicatorConst p (hm s hs) hμs.ne c)) - (h_add : ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, AEStronglyMeasurable' m f μ → - AEStronglyMeasurable' m g μ → Disjoint (Function.support f) (Function.support g) → + (h_add : ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, AEStronglyMeasurable[m] f μ → + AEStronglyMeasurable[m] g μ → Disjoint (Function.support f) (Function.support g) → P (hf.toLp f) → P (hg.toLp g) → P (hf.toLp f + hg.toLp g)) (h_closed : IsClosed {f : lpMeas F ℝ m p μ | P f}) : - ∀ f : Lp F p μ, AEStronglyMeasurable' m f μ → P f := by + ∀ f : Lp F p μ, AEStronglyMeasurable[m] f μ → P f := by intro f hf let f' := (⟨f, hf⟩ : lpMeas F ℝ m p μ) let g := lpMeasToLpTrimLie F ℝ p μ hm f' @@ -573,11 +559,11 @@ theorem Lp.induction_stronglyMeasurable (hm : m ≤ m0) (hp_ne_top : p ≠ ∞) StronglyMeasurable[m] g → Disjoint (Function.support f) (Function.support g) → P (hf.toLp f) → P (hg.toLp g) → P (hf.toLp f + hg.toLp g)) (h_closed : IsClosed {f : lpMeas F ℝ m p μ | P f}) : - ∀ f : Lp F p μ, AEStronglyMeasurable' m f μ → P f := by + ∀ f : Lp F p μ, AEStronglyMeasurable[m] f μ → P f := by intro f hf suffices h_add_ae : - ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, AEStronglyMeasurable' m f μ → - AEStronglyMeasurable' m g μ → Disjoint (Function.support f) (Function.support g) → + ∀ ⦃f g⦄, ∀ hf : Memℒp f p μ, ∀ hg : Memℒp g p μ, AEStronglyMeasurable[m] f μ → + AEStronglyMeasurable[m] g μ → Disjoint (Function.support f) (Function.support g) → P (hf.toLp f) → P (hg.toLp g) → P (hf.toLp f + hg.toLp g) from Lp.induction_stronglyMeasurable_aux hm hp_ne_top _ h_ind h_add_ae h_closed f hf intro f g hf hg hfm hgm h_disj hPf hPg @@ -636,10 +622,10 @@ theorem Memℒp.induction_stronglyMeasurable (hm : m ≤ m0) (hp_ne_top : p ≠ P f → P g → P (f + g)) (h_closed : IsClosed {f : lpMeas F ℝ m p μ | P f}) (h_ae : ∀ ⦃f g⦄, f =ᵐ[μ] g → Memℒp f p μ → P f → P g) : - ∀ ⦃f : α → F⦄, Memℒp f p μ → AEStronglyMeasurable' m f μ → P f := by + ∀ ⦃f : α → F⦄, Memℒp f p μ → AEStronglyMeasurable[m] f μ → P f := by intro f hf hfm let f_Lp := hf.toLp f - have hfm_Lp : AEStronglyMeasurable' m f_Lp μ := hfm.congr hf.coeFn_toLp.symm + have hfm_Lp : AEStronglyMeasurable[m] f_Lp μ := hfm.congr hf.coeFn_toLp.symm refine h_ae hf.coeFn_toLp (Lp.memℒp _) ?_ change P f_Lp refine Lp.induction_stronglyMeasurable hm hp_ne_top (fun f => P f) ?_ ?_ h_closed f_Lp hfm_Lp diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index 8535873e0e0c7..3ab7e033caf91 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -84,7 +84,7 @@ noncomputable irreducible_def condExp (μ : Measure[m₀] α) (f : α → E) : if hm : m ≤ m₀ then if h : SigmaFinite (μ.trim hm) ∧ Integrable f μ then if StronglyMeasurable[m] f then f - else have := h.1; aestronglyMeasurable'_condExpL1.mk (condExpL1 hm μ f) + else have := h.1; aestronglyMeasurable_condExpL1.mk (condExpL1 hm μ f) else 0 else 0 @@ -106,7 +106,7 @@ theorem condExp_of_sigmaFinite (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm μ[f|m] = if Integrable f μ then if StronglyMeasurable[m] f then f - else aestronglyMeasurable'_condExpL1.mk (condExpL1 hm μ f) + else aestronglyMeasurable_condExpL1.mk (condExpL1 hm μ f) else 0 := by rw [condExp, dif_pos hm] simp only [hμm, Ne, true_and] @@ -135,10 +135,9 @@ theorem condExp_ae_eq_condExpL1 (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim h · rw [if_pos hfi] by_cases hfm : StronglyMeasurable[m] f · rw [if_pos hfm] - exact (condExpL1_of_aestronglyMeasurable' (StronglyMeasurable.aeStronglyMeasurable' hfm) - hfi).symm + exact (condExpL1_of_aestronglyMeasurable' hfm.aestronglyMeasurable hfi).symm · rw [if_neg hfm] - exact (AEStronglyMeasurable'.ae_eq_mk aestronglyMeasurable'_condExpL1).symm + exact aestronglyMeasurable_condExpL1.ae_eq_mk.symm rw [if_neg hfi, condExpL1_undef hfi] exact (coeFn_zero _ _ _).symm @@ -178,7 +177,7 @@ theorem stronglyMeasurable_condExp : StronglyMeasurable[m] (μ[f|m]) := by rw [condExp_of_sigmaFinite hm] split_ifs with hfi hfm · exact hfm - · exact AEStronglyMeasurable'.stronglyMeasurable_mk _ + · exact aestronglyMeasurable_condExpL1.stronglyMeasurable_mk · exact stronglyMeasurable_zero @[deprecated (since := "2025-01-21")] alias stronglyMeasurable_condexp := stronglyMeasurable_condExp @@ -195,7 +194,7 @@ theorem condExp_congr_ae (h : f =ᵐ[μ] g) : μ[f|m] =ᵐ[μ] μ[g|m] := by @[deprecated (since := "2025-01-21")] alias condexp_congr_ae := condExp_congr_ae theorem condExp_of_aestronglyMeasurable' (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] {f : α → E} - (hf : AEStronglyMeasurable' m f μ) (hfi : Integrable f μ) : μ[f|m] =ᵐ[μ] f := by + (hf : AEStronglyMeasurable[m] f μ) (hfi : Integrable f μ) : μ[f|m] =ᵐ[μ] f := by refine ((condExp_congr_ae hf.ae_eq_mk).trans ?_).trans hf.ae_eq_mk.symm rw [condExp_of_stronglyMeasurable hm hf.stronglyMeasurable_mk ((integrable_congr hf.ae_eq_mk).mp hfi)] @@ -249,10 +248,10 @@ theorem ae_eq_condExp_of_forall_setIntegral_eq (hm : m ≤ m₀) [SigmaFinite ( {f g : α → E} (hf : Integrable f μ) (hg_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn g s μ) (hg_eq : ∀ s : Set α, MeasurableSet[m] s → μ s < ∞ → ∫ x in s, g x ∂μ = ∫ x in s, f x ∂μ) - (hgm : AEStronglyMeasurable' m g μ) : g =ᵐ[μ] μ[f|m] := by + (hgm : AEStronglyMeasurable[m] g μ) : g =ᵐ[μ] μ[f|m] := by refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hm hg_int_finite (fun s _ _ => integrable_condExp.integrableOn) (fun s hs hμs => ?_) hgm - (StronglyMeasurable.aeStronglyMeasurable' stronglyMeasurable_condExp) + (StronglyMeasurable.aestronglyMeasurable stronglyMeasurable_condExp) rw [hg_eq s hs hμs, setIntegral_condExp hm hf hs] @[deprecated (since := "2025-01-21")] @@ -363,8 +362,8 @@ theorem condExp_condExp_of_le {m₁ m₂ m₀ : MeasurableSpace α} {μ : Measur swap; · simp_rw [condExp_undef hf, condExp_zero]; rfl refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' (hm₁₂.trans hm₂) (fun s _ _ => integrable_condExp.integrableOn) (fun s _ _ => integrable_condExp.integrableOn) ?_ - stronglyMeasurable_condExp.aeStronglyMeasurable' - stronglyMeasurable_condExp.aeStronglyMeasurable' + stronglyMeasurable_condExp.aestronglyMeasurable + stronglyMeasurable_condExp.aestronglyMeasurable intro s hs _ rw [setIntegral_condExp (hm₁₂.trans hm₂) integrable_condExp hs] rw [setIntegral_condExp (hm₁₂.trans hm₂) hf hs, setIntegral_condExp hm₂ hf (hm₁₂ s hs)] @@ -378,7 +377,7 @@ lemma Memℒp.condExpL2_ae_eq_condExp' (hm : m ≤ m₀) (hf1 : Integrable f μ) [SigmaFinite (μ.trim hm)] : condExpL2 E 𝕜 hm hf2.toLp =ᵐ[μ] μ[f | m] := by refine ae_eq_condExp_of_forall_setIntegral_eq hm hf1 (fun s hs htop ↦ integrableOn_condExpL2_of_measure_ne_top hm htop.ne _) (fun s hs htop ↦ ?_) - (aeStronglyMeasurable'_condExpL2 hm _) + (aestronglyMeasurable_condExpL2 hm _) rw [integral_condExpL2_eq hm (hf2.toLp _) hs htop.ne] refine setIntegral_congr_ae (hm _ hs) ?_ filter_upwards [hf2.coeFn_toLp] with ω hω _ using hω diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean index b140355f0dcd5..1871e8db5807f 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean @@ -300,13 +300,16 @@ alias condexpInd_ae_eq_condexpIndSMul := condExpInd_ae_eq_condExpIndSMul variable {hm : m ≤ m0} [SigmaFinite (μ.trim hm)] -theorem aestronglyMeasurable'_condExpInd (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : - AEStronglyMeasurable' m (condExpInd G hm μ s x) μ := - AEStronglyMeasurable'.congr (aeStronglyMeasurable'_condExpIndSMul hm hs hμs x) +theorem aestronglyMeasurable_condExpInd (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : + AEStronglyMeasurable[m] (condExpInd G hm μ s x) μ := + (aestronglyMeasurable_condExpIndSMul hm hs hμs x).congr (condExpInd_ae_eq_condExpIndSMul hm hs hμs x).symm +@[deprecated (since := "2025-01-24")] +alias aestronglyMeasurable'_condExpInd := aestronglyMeasurable_condExpInd + @[deprecated (since := "2025-01-21")] -alias aestronglyMeasurable'_condexpInd := aestronglyMeasurable'_condExpInd +alias aestronglyMeasurable'_condexpInd := aestronglyMeasurable_condExpInd @[simp] theorem condExpInd_empty : condExpInd G hm μ ∅ = (0 : G →L[ℝ] α →₁[μ] G) := by @@ -517,25 +520,30 @@ alias set_integral_condExpL1CLM := setIntegral_condExpL1CLM @[deprecated (since := "2025-01-21")] alias set_integral_condexpL1CLM := set_integral_condExpL1CLM -theorem aestronglyMeasurable'_condExpL1CLM (f : α →₁[μ] F') : - AEStronglyMeasurable' m (condExpL1CLM F' hm μ f) μ := by +theorem aestronglyMeasurable_condExpL1CLM (f : α →₁[μ] F') : + AEStronglyMeasurable[m] (condExpL1CLM F' hm μ f) μ := by refine @Lp.induction _ _ _ _ _ _ _ ENNReal.one_ne_top - (fun f : α →₁[μ] F' => AEStronglyMeasurable' m (condExpL1CLM F' hm μ f) μ) ?_ ?_ ?_ f + (fun f : α →₁[μ] F' => AEStronglyMeasurable[m] (condExpL1CLM F' hm μ f) μ) ?_ ?_ ?_ f · intro c s hs hμs rw [condExpL1CLM_indicatorConst hs hμs.ne c] - exact aestronglyMeasurable'_condExpInd hs hμs.ne c + exact aestronglyMeasurable_condExpInd hs hμs.ne c · intro f g hf hg _ hfm hgm rw [(condExpL1CLM F' hm μ).map_add] - refine AEStronglyMeasurable'.congr ?_ (coeFn_add _ _).symm - exact AEStronglyMeasurable'.add hfm hgm - · have : {f : Lp F' 1 μ | AEStronglyMeasurable' m (condExpL1CLM F' hm μ f) μ} = - condExpL1CLM F' hm μ ⁻¹' {f | AEStronglyMeasurable' m f μ} := rfl + exact (hfm.add hgm).congr (coeFn_add ..).symm + · have : {f : Lp F' 1 μ | AEStronglyMeasurable[m] (condExpL1CLM F' hm μ f) μ} = + condExpL1CLM F' hm μ ⁻¹' {f | AEStronglyMeasurable[m] f μ} := rfl rw [this] refine IsClosed.preimage (condExpL1CLM F' hm μ).continuous ?_ exact isClosed_aeStronglyMeasurable' hm +@[deprecated (since := "2025-01-24")] +alias aestronglyMeasurable'_condExpL1CLM := aestronglyMeasurable_condExpL1CLM + @[deprecated (since := "2025-01-21")] -alias aestronglyMeasurable'_condexpL1CLM := aestronglyMeasurable'_condExpL1CLM +alias aestronglyMeasurable_condexpL1CLM := aestronglyMeasurable_condExpL1CLM + +@[deprecated (since := "2025-01-24")] +alias aestronglyMeasurable'_condexpL1CLM := aestronglyMeasurable_condexpL1CLM theorem condExpL1CLM_lpMeas (f : lpMeas F' ℝ m 1 μ) : condExpL1CLM F' hm μ (f : α →₁[μ] F') = ↑f := by @@ -562,7 +570,7 @@ theorem condExpL1CLM_lpMeas (f : lpMeas F' ℝ m 1 μ) : @[deprecated (since := "2025-01-21")] alias condexpL1CLM_lpMeas := condExpL1CLM_lpMeas -theorem condExpL1CLM_of_aestronglyMeasurable' (f : α →₁[μ] F') (hfm : AEStronglyMeasurable' m f μ) : +theorem condExpL1CLM_of_aestronglyMeasurable' (f : α →₁[μ] F') (hfm : AEStronglyMeasurable[m] f μ) : condExpL1CLM F' hm μ f = f := condExpL1CLM_lpMeas (⟨f, hfm⟩ : lpMeas F' ℝ m 1 μ) @@ -598,17 +606,22 @@ theorem condExpL1_measure_zero (hm : m ≤ m0) : condExpL1 hm (0 : Measure α) f @[deprecated (since := "2025-01-21")] alias condexpL1_measure_zero := condExpL1_measure_zero -theorem aestronglyMeasurable'_condExpL1 {f : α → F'} : - AEStronglyMeasurable' m (condExpL1 hm μ f) μ := by +theorem aestronglyMeasurable_condExpL1 {f : α → F'} : + AEStronglyMeasurable[m] (condExpL1 hm μ f) μ := by by_cases hf : Integrable f μ · rw [condExpL1_eq hf] - exact aestronglyMeasurable'_condExpL1CLM _ + exact aestronglyMeasurable_condExpL1CLM _ · rw [condExpL1_undef hf] - refine AEStronglyMeasurable'.congr ?_ (coeFn_zero _ _ _).symm - exact StronglyMeasurable.aeStronglyMeasurable' (@stronglyMeasurable_zero _ _ m _ _) + exact stronglyMeasurable_zero.aestronglyMeasurable.congr (coeFn_zero ..).symm + +@[deprecated (since := "2025-01-24")] +alias aestronglyMeasurable'_condExpL1 := aestronglyMeasurable_condExpL1 @[deprecated (since := "2025-01-21")] -alias aestronglyMeasurable'_condexpL1 := aestronglyMeasurable'_condExpL1 +alias aestronglyMeasurable_condexpL1 := aestronglyMeasurable_condExpL1 + +@[deprecated (since := "2025-01-24")] +alias aestronglyMeasurable'_condexpL1 := aestronglyMeasurable_condexpL1 theorem condExpL1_congr_ae (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (h : f =ᵐ[μ] g) : condExpL1 hm μ f = condExpL1 hm μ g := @@ -660,12 +673,12 @@ theorem condExpL1_sub (hf : Integrable f μ) (hg : Integrable g μ) : @[deprecated (since := "2025-01-21")] alias condexpL1_sub := condExpL1_sub -theorem condExpL1_of_aestronglyMeasurable' (hfm : AEStronglyMeasurable' m f μ) +theorem condExpL1_of_aestronglyMeasurable' (hfm : AEStronglyMeasurable[m] f μ) (hfi : Integrable f μ) : condExpL1 hm μ f =ᵐ[μ] f := by rw [condExpL1_eq hfi] refine EventuallyEq.trans ?_ (Integrable.coeFn_toL1 hfi) rw [condExpL1CLM_of_aestronglyMeasurable'] - exact AEStronglyMeasurable'.congr hfm (Integrable.coeFn_toL1 hfi).symm + exact hfm.congr hfi.coeFn_toL1.symm @[deprecated (since := "2025-01-21")] alias condexpL1_of_aestronglyMeasurable' := condExpL1_of_aestronglyMeasurable' diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean index af886f9759cdb..b6524435ba77e 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean @@ -75,12 +75,15 @@ noncomputable def condExpL2 (hm : m ≤ m0) : (α →₂[μ] E) →L[𝕜] lpMea variable {E 𝕜} -theorem aeStronglyMeasurable'_condExpL2 (hm : m ≤ m0) (f : α →₂[μ] E) : - AEStronglyMeasurable' (β := E) m (condExpL2 E 𝕜 hm f) μ := - lpMeas.aeStronglyMeasurable' _ +theorem aestronglyMeasurable_condExpL2 (hm : m ≤ m0) (f : α →₂[μ] E) : + AEStronglyMeasurable[m] (condExpL2 E 𝕜 hm f : α → E) μ := + lpMeas.aeStronglyMeasurable _ -@[deprecated (since := "2025-01-21")] -alias aeStronglyMeasurable'_condexpL2 := aeStronglyMeasurable'_condExpL2 +@[deprecated (since := "2025-01-24")] +alias aeStronglyMeasurable'_condExpL2 := aestronglyMeasurable_condExpL2 + +@[deprecated (since := "2025-01-24")] +alias aeStronglyMeasurable'_condexpL2 := aestronglyMeasurable_condExpL2 theorem integrableOn_condExpL2_of_measure_ne_top (hm : m ≤ m0) (hμs : μ s ≠ ∞) (f : α →₂[μ] E) : IntegrableOn (ε := E) (condExpL2 E 𝕜 hm f) s μ := @@ -154,11 +157,11 @@ theorem condExpL2_indicator_of_measurable (hm : m ≤ m0) (hs : MeasurableSet[m] alias condexpL2_indicator_of_measurable := condExpL2_indicator_of_measurable theorem inner_condExpL2_eq_inner_fun (hm : m ≤ m0) (f g : α →₂[μ] E) - (hg : AEStronglyMeasurable' m g μ) : + (hg : AEStronglyMeasurable[m] g μ) : ⟪(condExpL2 E 𝕜 hm f : α →₂[μ] E), g⟫₂ = ⟪f, g⟫₂ := by symm rw [← sub_eq_zero, ← inner_sub_left, condExpL2] - simp only [mem_lpMeas_iff_aeStronglyMeasurable'.mpr hg, orthogonalProjection_inner_eq_zero f g] + simp only [mem_lpMeas_iff_aeStronglyMeasurable.mpr hg, orthogonalProjection_inner_eq_zero f g] @[deprecated (since := "2025-01-21")] alias inner_condexpL2_eq_inner_fun := inner_condExpL2_eq_inner_fun @@ -180,7 +183,7 @@ alias integral_condexpL2_eq_of_fin_meas_real := integral_condExpL2_eq_of_fin_mea theorem lintegral_nnnorm_condExpL2_le (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) (f : Lp ℝ 2 μ) : ∫⁻ x in s, ‖(condExpL2 ℝ ℝ hm f : α → ℝ) x‖₊ ∂μ ≤ ∫⁻ x in s, ‖f x‖₊ ∂μ := by - let h_meas := lpMeas.aeStronglyMeasurable' (condExpL2 ℝ ℝ hm f) + let h_meas := lpMeas.aeStronglyMeasurable (condExpL2 ℝ ℝ hm f) let g := h_meas.choose have hg_meas : StronglyMeasurable[m] g := h_meas.choose_spec.1 have hg_eq : g =ᵐ[μ] condExpL2 ℝ ℝ hm f := h_meas.choose_spec.2.symm @@ -274,9 +277,9 @@ theorem condExpL2_const_inner (hm : m ≤ m0) (f : Lp E 2 μ) (c : E) : L2.inner_indicatorConstLp_eq_setIntegral_inner 𝕜 f (hm s hs) c hμs.ne, setIntegral_congr_ae (hm s hs) ((Memℒp.coeFn_toLp ((Lp.memℒp f).const_inner c)).mono fun x hx _ => hx)] - · rw [← lpMeas_coe]; exact lpMeas.aeStronglyMeasurable' _ - · refine AEStronglyMeasurable'.congr ?_ h_eq.symm - exact (lpMeas.aeStronglyMeasurable' _).const_inner _ + · rw [← lpMeas_coe]; exact lpMeas.aeStronglyMeasurable _ + · refine AEStronglyMeasurable.congr ?_ h_eq.symm + exact (lpMeas.aeStronglyMeasurable _).const_inner @[deprecated (since := "2025-01-21")] alias condexpL2_const_inner := condExpL2_const_inner @@ -321,11 +324,11 @@ theorem condExpL2_comp_continuousLinearMap (hm : m ≤ m0) (T : E' →L[ℝ] E'' integral_condExpL2_eq hm (T.compLp f) hs hμs.ne, T.setIntegral_compLp _ (hm s hs), T.integral_comp_comm (integrableOn_Lp_of_measure_ne_top f fact_one_le_two_ennreal.elim hμs.ne)] - · rw [← lpMeas_coe]; exact lpMeas.aeStronglyMeasurable' _ + · rw [← lpMeas_coe]; exact lpMeas.aeStronglyMeasurable _ · have h_coe := T.coeFn_compLp (condExpL2 E' 𝕜 hm f : α →₂[μ] E') rw [← EventuallyEq] at h_coe - refine AEStronglyMeasurable'.congr ?_ h_coe.symm - exact (lpMeas.aeStronglyMeasurable' (condExpL2 E' 𝕜 hm f)).continuous_comp T.continuous + refine AEStronglyMeasurable.congr ?_ h_coe.symm + exact T.continuous.comp_aestronglyMeasurable (lpMeas.aeStronglyMeasurable (condExpL2 E' 𝕜 hm f)) @[deprecated (since := "2025-01-21")] alias condexpL2_comp_continuousLinearMap := condExpL2_comp_continuousLinearMap @@ -433,20 +436,19 @@ noncomputable def condExpIndSMul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : @[deprecated (since := "2025-01-21")] alias condexpIndSMul := condExpIndSMul -theorem aeStronglyMeasurable'_condExpIndSMul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) - (x : G) : AEStronglyMeasurable' m (condExpIndSMul hm hs hμs x) μ := by - have h : AEStronglyMeasurable' m (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := - aeStronglyMeasurable'_condExpL2 _ _ +theorem aestronglyMeasurable_condExpIndSMul (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) + (x : G) : AEStronglyMeasurable[m] (condExpIndSMul hm hs hμs x) μ := by + have h : AEStronglyMeasurable[m] (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := + aestronglyMeasurable_condExpL2 _ _ rw [condExpIndSMul] - suffices AEStronglyMeasurable' m - (toSpanSingleton ℝ x ∘ condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1)) μ by - refine AEStronglyMeasurable'.congr this ?_ - refine EventuallyEq.trans ?_ (coeFn_compLpL _ _).symm - rfl - exact AEStronglyMeasurable'.continuous_comp (toSpanSingleton ℝ x).continuous h + exact ((toSpanSingleton ℝ x).continuous.comp_aestronglyMeasurable h).congr + (coeFn_compLpL _ _).symm + +@[deprecated (since := "2025-01-24")] +alias aeStronglyMeasurable'_condExpIndSMul := aestronglyMeasurable_condExpIndSMul @[deprecated (since := "2025-01-21")] -alias aeStronglyMeasurable'_condexpIndSMul := aeStronglyMeasurable'_condExpIndSMul +alias aestronglyMeasurable'_condexpIndSMul := aestronglyMeasurable_condExpIndSMul theorem condExpIndSMul_add (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x y : G) : condExpIndSMul hm hs hμs (x + y) = condExpIndSMul hm hs hμs x + condExpIndSMul hm hs hμs y := by @@ -571,8 +573,8 @@ alias set_integral_condexpIndSMul := set_integral_condExpIndSMul theorem condExpL2_indicator_nonneg (hm : m ≤ m0) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) [SigmaFinite (μ.trim hm)] : (0 : α → ℝ) ≤ᵐ[μ] condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) := by - have h : AEStronglyMeasurable' m (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := - aeStronglyMeasurable'_condExpL2 _ _ + have h : AEStronglyMeasurable[m] (condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) μ := + aestronglyMeasurable_condExpL2 _ _ refine EventuallyLE.trans_eq ?_ h.ae_eq_mk.symm refine @ae_le_of_ae_le_trim _ _ _ _ _ _ hm (0 : α → ℝ) _ ?_ refine ae_nonneg_of_forall_setIntegral_nonneg_of_sigmaFinite ?_ ?_ diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean index 6501fdc7fa2bf..ec9544a287a01 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean @@ -53,8 +53,8 @@ theorem condExp_ae_eq_restrict_zero (hs : MeasurableSet[m] s) (hf : f =ᵐ[μ.re Measure.restrict_restrict (hm _ ht)] refine setIntegral_congr_ae (hm _ ht) ?_ filter_upwards [hf] with x hx _ using hx - · exact stronglyMeasurable_condExp.aeStronglyMeasurable' - · exact stronglyMeasurable_zero.aeStronglyMeasurable' + · exact stronglyMeasurable_condExp.aestronglyMeasurable + · exact stronglyMeasurable_zero.aestronglyMeasurable @[deprecated (since := "2025-01-21")] alias condexp_ae_eq_restrict_zero := condExp_ae_eq_restrict_zero @@ -137,7 +137,7 @@ theorem condExp_restrict_ae_eq_restrict (hm : m ≤ m0) [SigmaFinite (μ.trim hm _ = ∫ x in t, s.indicator f x ∂μ := by rw [integral_indicator (hm _ hs_m), Measure.restrict_restrict (hm _ hs_m), Measure.restrict_restrict (hm _ ht), Set.inter_comm] - · exact (stronglyMeasurable_condExp.indicator hs_m).aeStronglyMeasurable' + · exact (stronglyMeasurable_condExp.indicator hs_m).aestronglyMeasurable @[deprecated (since := "2025-01-21")] alias condexp_restrict_ae_eq_restrict := condExp_restrict_ae_eq_restrict @@ -157,11 +157,10 @@ theorem condExp_ae_eq_restrict_of_measurableSpace_eq_on {m m₂ m0 : MeasurableS refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hm₂ (fun s _ _ => integrable_condExp.integrableOn) (fun s _ _ => integrable_condExp.integrableOn) ?_ ?_ - stronglyMeasurable_condExp.aeStronglyMeasurable' + stronglyMeasurable_condExp.aestronglyMeasurable swap · have : StronglyMeasurable[m] (μ[s.indicator f|m]) := stronglyMeasurable_condExp - refine this.aeStronglyMeasurable'.aeStronglyMeasurable'_of_measurableSpace_le_on hm hs_m - (fun t => (hs t).mp) ?_ + refine this.aestronglyMeasurable.of_measurableSpace_le_on hm hs_m (fun t => (hs t).mp) ?_ exact condExp_ae_eq_restrict_zero hs_m.compl (indicator_ae_eq_restrict_compl (hm _ hs_m)) intro t ht _ have : ∫ x in t, (μ[s.indicator f|m]) x ∂μ = ∫ x in s ∩ t, (μ[s.indicator f|m]) x ∂μ := by diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index 099cc8d17c46d..8eac500e658bf 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -49,7 +49,7 @@ theorem rnDeriv_ae_eq_condExp {hm : m ≤ m0} [hμm : SigmaFinite (μ.trim hm)] (SignedMeasure.integrable_rnDeriv ((μ.withDensityᵥ f).trim hm) (μ.trim hm)) hs, ← setIntegral_trim hm _ hs] exact (SignedMeasure.measurable_rnDeriv _ _).stronglyMeasurable - · exact (SignedMeasure.measurable_rnDeriv _ _).stronglyMeasurable.aeStronglyMeasurable' + · exact (SignedMeasure.measurable_rnDeriv _ _).stronglyMeasurable.aestronglyMeasurable @[deprecated (since := "2025-01-21")] alias rnDeriv_ae_eq_condexp := rnDeriv_ae_eq_condExp @@ -316,7 +316,7 @@ theorem condExp_stronglyMeasurable_mul_of_bound (hm : m ≤ m0) [IsFiniteMeasure alias condexp_stronglyMeasurable_mul_of_bound := condExp_stronglyMeasurable_mul_of_bound theorem condExp_stronglyMeasurable_mul_of_bound₀ (hm : m ≤ m0) [IsFiniteMeasure μ] {f g : α → ℝ} - (hf : AEStronglyMeasurable' m f μ) (hg : Integrable g μ) (c : ℝ) + (hf : AEStronglyMeasurable[m] f μ) (hg : Integrable g μ) (c : ℝ) (hf_bound : ∀ᵐ x ∂μ, ‖f x‖ ≤ c) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by have : μ[f * g|m] =ᵐ[μ] μ[hf.mk f * g|m] := condExp_congr_ae (EventuallyEq.mul hf.ae_eq_mk EventuallyEq.rfl) @@ -376,7 +376,7 @@ lemma condExp_mul_of_stronglyMeasurable_right {f g : α → ℝ} (hg : StronglyM simpa [mul_comm] using condExp_mul_of_stronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf /-- Pull-out property of the conditional expectation. -/ -theorem condExp_mul_of_aestronglyMeasurable_left {f g : α → ℝ} (hf : AEStronglyMeasurable' m f μ) +theorem condExp_mul_of_aestronglyMeasurable_left {f g : α → ℝ} (hf : AEStronglyMeasurable[m] f μ) (hfg : Integrable (f * g) μ) (hg : Integrable g μ) : μ[f * g|m] =ᵐ[μ] f * μ[g|m] := by have : μ[f * g|m] =ᵐ[μ] μ[hf.mk f * g|m] := condExp_congr_ae (hf.ae_eq_mk.mul EventuallyEq.rfl) @@ -390,7 +390,7 @@ theorem condExp_mul_of_aestronglyMeasurable_left {f g : α → ℝ} (hf : AEStro alias condexp_stronglyMeasurable_mul₀ := condExp_mul_of_aestronglyMeasurable_left /-- Pull-out property of the conditional expectation. -/ -lemma condExp_mul_of_aestronglyMeasurable_right {f g : α → ℝ} (hg : AEStronglyMeasurable' m g μ) +lemma condExp_mul_of_aestronglyMeasurable_right {f g : α → ℝ} (hg : AEStronglyMeasurable[m] g μ) (hfg : Integrable (f * g) μ) (hf : Integrable f μ) : μ[f * g | m] =ᵐ[μ] μ[f | m] * g := by simpa [mul_comm] using condExp_mul_of_aestronglyMeasurable_left hg (mul_comm f g ▸ hfg) hf diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean index 99a5b211c1158..033ce021ee4be 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean @@ -74,7 +74,7 @@ theorem Lp.ae_eq_zero_of_forall_setIntegral_eq_zero' (hm : m ≤ m0) (f : Lp E' (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) (hf_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn f s μ) (hf_zero : ∀ s : Set α, MeasurableSet[m] s → μ s < ∞ → ∫ x in s, f x ∂μ = 0) - (hf_meas : AEStronglyMeasurable' m f μ) : f =ᵐ[μ] 0 := by + (hf_meas : AEStronglyMeasurable[m] f μ) : f =ᵐ[μ] 0 := by let f_meas : lpMeas E' 𝕜 m p μ := ⟨f, hf_meas⟩ -- Porting note: `simp only` does not call `rfl` to try to close the goal. See https://github.com/leanprover-community/mathlib4/issues/5025 have hf_f_meas : f =ᵐ[μ] f_meas := by simp only [f_meas, Subtype.coe_mk]; rfl @@ -99,7 +99,7 @@ theorem Lp.ae_eq_of_forall_setIntegral_eq' (hm : m ≤ m0) (f g : Lp E' p μ) (h (hp_ne_top : p ≠ ∞) (hf_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn f s μ) (hg_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn g s μ) (hfg : ∀ s : Set α, MeasurableSet[m] s → μ s < ∞ → ∫ x in s, f x ∂μ = ∫ x in s, g x ∂μ) - (hf_meas : AEStronglyMeasurable' m f μ) (hg_meas : AEStronglyMeasurable' m g μ) : + (hf_meas : AEStronglyMeasurable[m] f μ) (hg_meas : AEStronglyMeasurable[m] g μ) : f =ᵐ[μ] g := by suffices h_sub : ⇑(f - g) =ᵐ[μ] 0 by rw [← sub_ae_eq_zero]; exact (Lp.coeFn_sub f g).symm.trans h_sub @@ -112,11 +112,8 @@ theorem Lp.ae_eq_of_forall_setIntegral_eq' (hm : m ≤ m0) (f g : Lp E' p μ) (h intro s hs hμs rw [IntegrableOn, integrable_congr (ae_restrict_of_ae (Lp.coeFn_sub f g))] exact (hf_int_finite s hs hμs).sub (hg_int_finite s hs hμs) - have hfg_meas : AEStronglyMeasurable' m (⇑(f - g)) μ := - AEStronglyMeasurable'.congr (hf_meas.sub hg_meas) (Lp.coeFn_sub f g).symm - exact - Lp.ae_eq_zero_of_forall_setIntegral_eq_zero' 𝕜 hm (f - g) hp_ne_zero hp_ne_top hfg_int hfg' - hfg_meas + exact Lp.ae_eq_zero_of_forall_setIntegral_eq_zero' 𝕜 hm (f - g) hp_ne_zero hp_ne_top hfg_int hfg' + <| (hf_meas.sub hg_meas).congr (Lp.coeFn_sub f g).symm @[deprecated (since := "2024-04-17")] alias Lp.ae_eq_of_forall_set_integral_eq' := Lp.ae_eq_of_forall_setIntegral_eq' @@ -127,7 +124,7 @@ theorem ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' (hm : m ≤ m0) [SigmaFin {f g : α → F'} (hf_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn f s μ) (hg_int_finite : ∀ s, MeasurableSet[m] s → μ s < ∞ → IntegrableOn g s μ) (hfg_eq : ∀ s : Set α, MeasurableSet[m] s → μ s < ∞ → ∫ x in s, f x ∂μ = ∫ x in s, g x ∂μ) - (hfm : AEStronglyMeasurable' m f μ) (hgm : AEStronglyMeasurable' m g μ) : f =ᵐ[μ] g := by + (hfm : AEStronglyMeasurable[m] f μ) (hgm : AEStronglyMeasurable[m] g μ) : f =ᵐ[μ] g := by rw [← ae_eq_trim_iff_of_aeStronglyMeasurable' hm hfm hgm] have hf_mk_int_finite (s) : MeasurableSet[m] s → μ.trim hm s < ∞ → @IntegrableOn _ _ m _ _ (hfm.mk f) s (μ.trim hm) := by diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 2261536820146..2624f72f454f2 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -1317,7 +1317,7 @@ theorem integrable_of_forall_fin_meas_le' {μ : Measure α} (hm : m ≤ m0) [Sig ⟨hf_meas, (lintegral_le_of_forall_fin_meas_trim_le hm C hf).trans_lt hC⟩ theorem integrable_of_forall_fin_meas_le [SigmaFinite μ] (C : ℝ≥0∞) (hC : C < ∞) {f : α → E} - (hf_meas : AEStronglyMeasurable f μ) + (hf_meas : AEStronglyMeasurable[m] f μ) (hf : ∀ s : Set α, MeasurableSet[m] s → μ s ≠ ∞ → (∫⁻ x in s, ‖f x‖₊ ∂μ) ≤ C) : Integrable f μ := have : SigmaFinite (μ.trim le_rfl) := by rwa [@trim_eq_self _ m] diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean index 3136274c2a507..b6776ff95e87a 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean @@ -67,7 +67,7 @@ theorem eLpNorm_trim (hm : m ≤ m0) {f : α → E} (hf : StronglyMeasurable[m] @[deprecated (since := "2024-07-27")] alias snorm_trim := eLpNorm_trim -theorem eLpNorm_trim_ae (hm : m ≤ m0) {f : α → E} (hf : AEStronglyMeasurable f (μ.trim hm)) : +theorem eLpNorm_trim_ae (hm : m ≤ m0) {f : α → E} (hf : AEStronglyMeasurable[m] f (μ.trim hm)) : eLpNorm f p (μ.trim hm) = eLpNorm f p μ := by rw [eLpNorm_congr_ae hf.ae_eq_mk, eLpNorm_congr_ae (ae_eq_of_ae_eq_trim hf.ae_eq_mk)] exact eLpNorm_trim hm hf.stronglyMeasurable_mk diff --git a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean index 3fcd3f10b57d4..3b54bf1d8f7db 100644 --- a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean +++ b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean @@ -85,11 +85,18 @@ def FinStronglyMeasurable [Zero β] ∃ fs : ℕ → α →ₛ β, (∀ n, μ (support (fs n)) < ∞) ∧ ∀ x, Tendsto (fun n => fs n x) atTop (𝓝 (f x)) /-- A function is `AEStronglyMeasurable` with respect to a measure `μ` if it is almost everywhere -equal to the limit of a sequence of simple functions. -/ +equal to the limit of a sequence of simple functions. + +One can specify the sigma-algebra according to which simple functions are taken using the +`AEStronglyMeasurable[m]` notation in the `MeasureTheory` scope. -/ @[fun_prop] -def AEStronglyMeasurable - {_ : MeasurableSpace α} (f : α → β) (μ : Measure α := by volume_tac) : Prop := - ∃ g, StronglyMeasurable g ∧ f =ᵐ[μ] g +def AEStronglyMeasurable [m : MeasurableSpace α] {m₀ : MeasurableSpace α} (f : α → β) + (μ : Measure[m₀] α := by volume_tac) : Prop := + ∃ g : α → β, StronglyMeasurable[m] g ∧ f =ᵐ[μ] g + +/-- A function is `m`-`AEStronglyMeasurable` with respect to a measure `μ` if it is almost +everywhere equal to the limit of a sequence of `m`-simple functions. -/ +scoped notation "AEStronglyMeasurable[" m "]" => @MeasureTheory.AEStronglyMeasurable _ _ _ m /-- A function is `AEFinStronglyMeasurable` with respect to a measure if it is almost everywhere equal to the limit of a sequence of simple functions with support with finite measure. -/ @@ -103,15 +110,11 @@ open MeasureTheory /-! ## Strongly measurable functions -/ -@[aesop 30% apply (rule_sets := [Measurable])] -protected theorem StronglyMeasurable.aestronglyMeasurable {α β} {_ : MeasurableSpace α} - [TopologicalSpace β] {f : α → β} {μ : Measure α} (hf : StronglyMeasurable f) : - AEStronglyMeasurable f μ := - ⟨f, hf, EventuallyEq.refl _ _⟩ +section StronglyMeasurable +variable {_ : MeasurableSpace α} [TopologicalSpace β] {f : α → β} {μ : Measure α} @[simp] -theorem Subsingleton.stronglyMeasurable {α β} [MeasurableSpace α] [TopologicalSpace β] - [Subsingleton β] (f : α → β) : StronglyMeasurable f := by +theorem Subsingleton.stronglyMeasurable [Subsingleton β] (f : α → β) : StronglyMeasurable f := by let f_sf : α →ₛ β := ⟨f, fun x => ?_, Set.Subsingleton.finite Set.subsingleton_of_subsingleton⟩ · exact ⟨fun _ => f_sf, fun x => tendsto_const_nhds⟩ · have h_univ : f ⁻¹' {x} = Set.univ := by @@ -120,29 +123,23 @@ theorem Subsingleton.stronglyMeasurable {α β} [MeasurableSpace α] [Topologica rw [h_univ] exact MeasurableSet.univ -theorem SimpleFunc.stronglyMeasurable {α β} {_ : MeasurableSpace α} [TopologicalSpace β] - (f : α →ₛ β) : StronglyMeasurable f := +theorem SimpleFunc.stronglyMeasurable (f : α →ₛ β) : StronglyMeasurable f := ⟨fun _ => f, fun _ => tendsto_const_nhds⟩ @[nontriviality] -theorem StronglyMeasurable.of_finite [Finite α] {_ : MeasurableSpace α} - [MeasurableSingletonClass α] [TopologicalSpace β] +theorem StronglyMeasurable.of_finite [Finite α] [MeasurableSingletonClass α] {f : α → β} : StronglyMeasurable f := ⟨fun _ => SimpleFunc.ofFinite f, fun _ => tendsto_const_nhds⟩ -theorem stronglyMeasurable_const {α β} {_ : MeasurableSpace α} [TopologicalSpace β] {b : β} : - StronglyMeasurable fun _ : α => b := +theorem stronglyMeasurable_const {b : β} : StronglyMeasurable fun _ : α => b := ⟨fun _ => SimpleFunc.const α b, fun _ => tendsto_const_nhds⟩ @[to_additive] -theorem stronglyMeasurable_one {α β} {_ : MeasurableSpace α} [TopologicalSpace β] [One β] : - StronglyMeasurable (1 : α → β) := - stronglyMeasurable_const +theorem stronglyMeasurable_one [One β] : StronglyMeasurable (1 : α → β) := stronglyMeasurable_const /-- A version of `stronglyMeasurable_const` that assumes `f x = f y` for all `x, y`. This version works for functions between empty types. -/ -theorem stronglyMeasurable_const' {α β} {m : MeasurableSpace α} [TopologicalSpace β] {f : α → β} - (hf : ∀ x y, f x = f y) : StronglyMeasurable f := by +theorem stronglyMeasurable_const' (hf : ∀ x y, f x = f y) : StronglyMeasurable f := by nontriviality α inhabit α convert stronglyMeasurable_const (β := β) using 1 @@ -150,10 +147,11 @@ theorem stronglyMeasurable_const' {α β} {m : MeasurableSpace α} [TopologicalS -- Porting note: changed binding type of `MeasurableSpace α`. @[simp] -theorem Subsingleton.stronglyMeasurable' {α β} [MeasurableSpace α] [TopologicalSpace β] - [Subsingleton α] (f : α → β) : StronglyMeasurable f := +theorem Subsingleton.stronglyMeasurable' [Subsingleton α] (f : α → β) : StronglyMeasurable f := stronglyMeasurable_const' fun x y => by rw [Subsingleton.elim x y] +end StronglyMeasurable + namespace StronglyMeasurable variable {f g : α → β} @@ -823,23 +821,49 @@ protected theorem real_toNNReal {_ : MeasurableSpace α} {f : α → ℝ} (hf : StronglyMeasurable fun x => (f x).toNNReal := continuous_real_toNNReal.comp_stronglyMeasurable hf -theorem measurableSet_eq_fun {m : MeasurableSpace α} {E} [TopologicalSpace E] [MetrizableSpace E] - {f g : α → E} (hf : StronglyMeasurable f) (hg : StronglyMeasurable g) : - MeasurableSet { x | f x = g x } := by +section PseudoMetrizableSpace +variable {E : Type*} {m m₀ : MeasurableSpace α} {μ : Measure[m₀] α} {f g : α → E} + [TopologicalSpace E] [Preorder E] [OrderClosedTopology E] [PseudoMetrizableSpace E] + +lemma measurableSet_le (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) : + MeasurableSet[m] {a | f a ≤ g a} := by + borelize (E × E) + exact (hf.prod_mk hg).measurable isClosed_le_prod.measurableSet + +lemma measurableSet_lt (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) : + MeasurableSet[m] {a | f a < g a} := by + simpa only [lt_iff_le_not_le] using (hf.measurableSet_le hg).inter (hg.measurableSet_le hf).compl + +lemma ae_le_trim_of_stronglyMeasurable (hm : m ≤ m₀) (hf : StronglyMeasurable[m] f) + (hg : StronglyMeasurable[m] g) (hfg : f ≤ᵐ[μ] g) : f ≤ᵐ[μ.trim hm] g := by + rwa [EventuallyLE, ae_iff, trim_measurableSet_eq hm] + exact (hf.measurableSet_le hg).compl + +lemma ae_le_trim_iff (hm : m ≤ m₀) (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) : + f ≤ᵐ[μ.trim hm] g ↔ f ≤ᵐ[μ] g := + ⟨ae_le_of_ae_le_trim, ae_le_trim_of_stronglyMeasurable hm hf hg⟩ + +end PseudoMetrizableSpace + +section MetrizableSpace +variable {E : Type*} {m m₀ : MeasurableSpace α} {μ : Measure[m₀] α} {f g : α → E} + [TopologicalSpace E] [MetrizableSpace E] + +lemma measurableSet_eq_fun (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) : + MeasurableSet[m] {a | f a = g a} := by borelize (E × E) exact (hf.prod_mk hg).measurable isClosed_diagonal.measurableSet -theorem measurableSet_lt {m : MeasurableSpace α} [TopologicalSpace β] [LinearOrder β] - [OrderClosedTopology β] [PseudoMetrizableSpace β] {f g : α → β} (hf : StronglyMeasurable f) - (hg : StronglyMeasurable g) : MeasurableSet { a | f a < g a } := by - borelize (β × β) - exact (hf.prod_mk hg).measurable isOpen_lt_prod.measurableSet +lemma ae_eq_trim_of_stronglyMeasurable (hm : m ≤ m₀) (hf : StronglyMeasurable[m] f) + (hg : StronglyMeasurable[m] g) (hfg : f =ᵐ[μ] g) : f =ᵐ[μ.trim hm] g := by + rwa [EventuallyEq, ae_iff, trim_measurableSet_eq hm] + exact (hf.measurableSet_eq_fun hg).compl -theorem measurableSet_le {m : MeasurableSpace α} [TopologicalSpace β] [Preorder β] - [OrderClosedTopology β] [PseudoMetrizableSpace β] {f g : α → β} (hf : StronglyMeasurable f) - (hg : StronglyMeasurable g) : MeasurableSet { a | f a ≤ g a } := by - borelize (β × β) - exact (hf.prod_mk hg).measurable isClosed_le_prod.measurableSet +lemma ae_eq_trim_iff (hm : m ≤ m₀) (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) : + f =ᵐ[μ.trim hm] g ↔ f =ᵐ[μ] g := + ⟨ae_eq_of_ae_eq_trim, ae_eq_trim_of_stronglyMeasurable hm hf hg⟩ + +end MetrizableSpace theorem stronglyMeasurable_in_set {m : MeasurableSpace α} [TopologicalSpace β] [Zero β] {s : Set α} {f : α → β} (hs : MeasurableSet s) (hf : StronglyMeasurable f) @@ -1075,43 +1099,49 @@ theorem aefinStronglyMeasurable_zero {α β} {_ : MeasurableSpace α} (μ : Meas /-! ## Almost everywhere strongly measurable functions -/ +section AEStronglyMeasurable +variable [TopologicalSpace β] [TopologicalSpace γ] {m m₀ : MeasurableSpace α} {μ ν : Measure[m₀] α} + {f g : α → β} + +@[aesop 30% apply (rule_sets := [Measurable])] +protected theorem StronglyMeasurable.aestronglyMeasurable (hf : StronglyMeasurable[m] f) : + AEStronglyMeasurable[m] f μ := ⟨f, hf, EventuallyEq.refl _ _⟩ + @[measurability] -theorem aestronglyMeasurable_const {α β} {_ : MeasurableSpace α} {μ : Measure α} - [TopologicalSpace β] {b : β} : AEStronglyMeasurable (fun _ : α => b) μ := +theorem aestronglyMeasurable_const {b : β} : AEStronglyMeasurable[m] (fun _ : α => b) μ := stronglyMeasurable_const.aestronglyMeasurable @[to_additive (attr := measurability)] -theorem aestronglyMeasurable_one {α β} {_ : MeasurableSpace α} {μ : Measure α} [TopologicalSpace β] - [One β] : AEStronglyMeasurable (1 : α → β) μ := +theorem aestronglyMeasurable_one [One β] : AEStronglyMeasurable[m] (1 : α → β) μ := stronglyMeasurable_one.aestronglyMeasurable @[simp] -theorem Subsingleton.aestronglyMeasurable {_ : MeasurableSpace α} [TopologicalSpace β] - [Subsingleton β] {μ : Measure α} (f : α → β) : AEStronglyMeasurable f μ := - (Subsingleton.stronglyMeasurable f).aestronglyMeasurable +lemma AEStronglyMeasurable.of_subsingleton_dom [Subsingleton α] : AEStronglyMeasurable[m] f μ := + (Subsingleton.stronglyMeasurable' f).aestronglyMeasurable @[simp] -theorem Subsingleton.aestronglyMeasurable' {_ : MeasurableSpace α} [TopologicalSpace β] - [Subsingleton α] {μ : Measure α} (f : α → β) : AEStronglyMeasurable f μ := - (Subsingleton.stronglyMeasurable' f).aestronglyMeasurable +lemma AEStronglyMeasurable.of_subsingleton_cod [Subsingleton β] : AEStronglyMeasurable[m] f μ := + (Subsingleton.stronglyMeasurable f).aestronglyMeasurable + +theorem Subsingleton.aestronglyMeasurable [Subsingleton β] (f : α → β) : AEStronglyMeasurable f μ := + .of_subsingleton_cod + +lemma Subsingleton.aestronglyMeasurable' [Subsingleton α] (f : α → β) : AEStronglyMeasurable f μ := + .of_subsingleton_dom @[simp] -theorem aestronglyMeasurable_zero_measure [MeasurableSpace α] [TopologicalSpace β] (f : α → β) : - AEStronglyMeasurable f (0 : Measure α) := by +theorem aestronglyMeasurable_zero_measure (f : α → β) : + AEStronglyMeasurable[m] f (0 : Measure[m₀] α) := by nontriviality α inhabit α exact ⟨fun _ => f default, stronglyMeasurable_const, rfl⟩ @[measurability] -theorem SimpleFunc.aestronglyMeasurable {_ : MeasurableSpace α} {μ : Measure α} [TopologicalSpace β] - (f : α →ₛ β) : AEStronglyMeasurable f μ := +theorem SimpleFunc.aestronglyMeasurable (f : α →ₛ β) : AEStronglyMeasurable f μ := f.stronglyMeasurable.aestronglyMeasurable namespace AEStronglyMeasurable -variable {m : MeasurableSpace α} {μ ν : Measure α} [TopologicalSpace β] [TopologicalSpace γ] - {f g : α → β} - lemma of_finite [DiscreteMeasurableSpace α] [Finite α] : AEStronglyMeasurable f μ := ⟨_, .of_finite, ae_eq_rfl⟩ @@ -1119,17 +1149,17 @@ section Mk /-- A `StronglyMeasurable` function such that `f =ᵐ[μ] hf.mk f`. See lemmas `stronglyMeasurable_mk` and `ae_eq_mk`. -/ -protected noncomputable def mk (f : α → β) (hf : AEStronglyMeasurable f μ) : α → β := +protected noncomputable def mk (f : α → β) (hf : AEStronglyMeasurable[m] f μ) : α → β := hf.choose -theorem stronglyMeasurable_mk (hf : AEStronglyMeasurable f μ) : StronglyMeasurable (hf.mk f) := +lemma stronglyMeasurable_mk (hf : AEStronglyMeasurable[m] f μ) : StronglyMeasurable[m] (hf.mk f) := hf.choose_spec.1 theorem measurable_mk [PseudoMetrizableSpace β] [MeasurableSpace β] [BorelSpace β] - (hf : AEStronglyMeasurable f μ) : Measurable (hf.mk f) := + (hf : AEStronglyMeasurable[m] f μ) : Measurable[m] (hf.mk f) := hf.stronglyMeasurable_mk.measurable -theorem ae_eq_mk (hf : AEStronglyMeasurable f μ) : f =ᵐ[μ] hf.mk f := +theorem ae_eq_mk (hf : AEStronglyMeasurable[m] f μ) : f =ᵐ[μ] hf.mk f := hf.choose_spec.2 @[aesop 5% apply (rule_sets := [Measurable])] @@ -1140,37 +1170,43 @@ protected theorem aemeasurable {β} [MeasurableSpace β] [TopologicalSpace β] end Mk -theorem congr (hf : AEStronglyMeasurable f μ) (h : f =ᵐ[μ] g) : AEStronglyMeasurable g μ := +theorem congr (hf : AEStronglyMeasurable[m] f μ) (h : f =ᵐ[μ] g) : AEStronglyMeasurable[m] g μ := ⟨hf.mk f, hf.stronglyMeasurable_mk, h.symm.trans hf.ae_eq_mk⟩ theorem _root_.aestronglyMeasurable_congr (h : f =ᵐ[μ] g) : - AEStronglyMeasurable f μ ↔ AEStronglyMeasurable g μ := + AEStronglyMeasurable[m] f μ ↔ AEStronglyMeasurable[m] g μ := ⟨fun hf => hf.congr h, fun hg => hg.congr h.symm⟩ -theorem mono_measure {ν : Measure α} (hf : AEStronglyMeasurable f μ) (h : ν ≤ μ) : - AEStronglyMeasurable f ν := +theorem mono_measure {ν : Measure α} (hf : AEStronglyMeasurable[m] f μ) (h : ν ≤ μ) : + AEStronglyMeasurable[m] f ν := ⟨hf.mk f, hf.stronglyMeasurable_mk, Eventually.filter_mono (ae_mono h) hf.ae_eq_mk⟩ -protected lemma mono_ac (h : ν ≪ μ) (hμ : AEStronglyMeasurable f μ) : AEStronglyMeasurable f ν := - let ⟨g, hg, hg'⟩ := hμ; ⟨g, hg, h.ae_eq hg'⟩ +protected lemma mono_ac (h : ν ≪ μ) (hμ : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] f ν := let ⟨g, hg, hg'⟩ := hμ; ⟨g, hg, h.ae_eq hg'⟩ - -theorem mono_set {s t} (h : s ⊆ t) (ht : AEStronglyMeasurable f (μ.restrict t)) : - AEStronglyMeasurable f (μ.restrict s) := +theorem mono_set {s t} (h : s ⊆ t) (ht : AEStronglyMeasurable[m] f (μ.restrict t)) : + AEStronglyMeasurable[m] f (μ.restrict s) := ht.mono_measure (restrict_mono h le_rfl) -protected theorem restrict (hfm : AEStronglyMeasurable f μ) {s} : - AEStronglyMeasurable f (μ.restrict s) := +lemma mono {m'} (hm : m ≤ m') (hf : AEStronglyMeasurable[m] f μ) : AEStronglyMeasurable[m'] f μ := + let ⟨f', hf'_meas, hff'⟩ := hf; ⟨f', hf'_meas.mono hm, hff'⟩ + +lemma of_trim {m₀' : MeasurableSpace α} (hm₀ : m₀' ≤ m₀) + (hf : AEStronglyMeasurable[m] f (μ.trim hm₀)) : AEStronglyMeasurable[m] f μ := by + obtain ⟨g, hg_meas, hfg⟩ := hf; exact ⟨g, hg_meas, ae_eq_of_ae_eq_trim hfg⟩ + +protected theorem restrict (hfm : AEStronglyMeasurable[m] f μ) {s} : + AEStronglyMeasurable[m] f (μ.restrict s) := hfm.mono_measure Measure.restrict_le_self -theorem ae_mem_imp_eq_mk {s} (h : AEStronglyMeasurable f (μ.restrict s)) : +theorem ae_mem_imp_eq_mk {s} (h : AEStronglyMeasurable[m] f (μ.restrict s)) : ∀ᵐ x ∂μ, x ∈ s → f x = h.mk f x := ae_imp_of_ae_restrict h.ae_eq_mk /-- The composition of a continuous function and an ae strongly measurable function is ae strongly measurable. -/ theorem _root_.Continuous.comp_aestronglyMeasurable {g : β → γ} {f : α → β} (hg : Continuous g) - (hf : AEStronglyMeasurable f μ) : AEStronglyMeasurable (fun x => g (f x)) μ := + (hf : AEStronglyMeasurable[m] f μ) : AEStronglyMeasurable[m] (fun x => g (f x)) μ := ⟨_, hg.comp_stronglyMeasurable hf.stronglyMeasurable_mk, EventuallyEq.fun_comp hf.ae_eq_mk g⟩ /-- A continuous function from `α` to `β` is ae strongly measurable when one of the two spaces is @@ -1180,8 +1216,8 @@ theorem _root_.Continuous.aestronglyMeasurable [TopologicalSpace α] [OpensMeasu AEStronglyMeasurable f μ := hf.stronglyMeasurable.aestronglyMeasurable -protected theorem prod_mk {f : α → β} {g : α → γ} (hf : AEStronglyMeasurable f μ) - (hg : AEStronglyMeasurable g μ) : AEStronglyMeasurable (fun x => (f x, g x)) μ := +protected theorem prod_mk {f : α → β} {g : α → γ} (hf : AEStronglyMeasurable[m] f μ) + (hg : AEStronglyMeasurable[m] g μ) : AEStronglyMeasurable[m] (fun x => (f x, g x)) μ := ⟨fun x => (hf.mk f x, hg.mk g x), hf.stronglyMeasurable_mk.prod_mk hg.stronglyMeasurable_mk, hf.ae_eq_mk.prod_mk hg.ae_eq_mk⟩ @@ -1190,81 +1226,102 @@ functions is ae strongly measurable. -/ theorem _root_.Continuous.comp_aestronglyMeasurable₂ {β' : Type*} [TopologicalSpace β'] {g : β → β' → γ} {f : α → β} {f' : α → β'} (hg : Continuous g.uncurry) - (hf : AEStronglyMeasurable f μ) (h'f : AEStronglyMeasurable f' μ) : - AEStronglyMeasurable (fun x => g (f x) (f' x)) μ := + (hf : AEStronglyMeasurable[m] f μ) (h'f : AEStronglyMeasurable[m] f' μ) : + AEStronglyMeasurable[m] (fun x => g (f x) (f' x)) μ := hg.comp_aestronglyMeasurable (hf.prod_mk h'f) /-- In a space with second countable topology, measurable implies ae strongly measurable. -/ @[fun_prop, aesop unsafe 30% apply (rule_sets := [Measurable])] -theorem _root_.Measurable.aestronglyMeasurable {_ : MeasurableSpace α} {μ : Measure α} +theorem _root_.Measurable.aestronglyMeasurable [MeasurableSpace β] [PseudoMetrizableSpace β] [SecondCountableTopology β] - [OpensMeasurableSpace β] (hf : Measurable f) : AEStronglyMeasurable f μ := + [OpensMeasurableSpace β] (hf : Measurable[m] f) : AEStronglyMeasurable[m] f μ := hf.stronglyMeasurable.aestronglyMeasurable +/-- If the restriction to a set `s` of a σ-algebra `m` is included in the restriction to `s` of +another σ-algebra `m₂` (hypothesis `hs`), the set `s` is `m` measurable and a function `f` almost +everywhere supported on `s` is `m`-ae-strongly-measurable, then `f` is also +`m₂`-ae-strongly-measurable. -/ +lemma of_measurableSpace_le_on {m' m₀ : MeasurableSpace α} {μ : Measure[m₀] α} [Zero β] + (hm : m ≤ m₀) {s : Set α} (hs_m : MeasurableSet[m] s) + (hs : ∀ t, MeasurableSet[m] (s ∩ t) → MeasurableSet[m'] (s ∩ t)) + (hf : AEStronglyMeasurable[m] f μ) (hf_zero : f =ᵐ[μ.restrict sᶜ] 0) : + AEStronglyMeasurable[m'] f μ := by + have h_ind_eq : s.indicator (hf.mk f) =ᵐ[μ] f := by + refine Filter.EventuallyEq.trans ?_ <| + indicator_ae_eq_of_restrict_compl_ae_eq_zero (hm _ hs_m) hf_zero + filter_upwards [hf.ae_eq_mk] with x hx + by_cases hxs : x ∈ s + · simp [hxs, hx] + · simp [hxs] + suffices StronglyMeasurable[m'] (s.indicator (hf.mk f)) from + this.aestronglyMeasurable.congr h_ind_eq + exact (hf.stronglyMeasurable_mk.indicator hs_m).stronglyMeasurable_of_measurableSpace_le_on hs_m + hs fun x hxs => Set.indicator_of_not_mem hxs _ + section Arithmetic @[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable]))] -protected theorem mul [Mul β] [ContinuousMul β] (hf : AEStronglyMeasurable f μ) - (hg : AEStronglyMeasurable g μ) : AEStronglyMeasurable (f * g) μ := +protected theorem mul [Mul β] [ContinuousMul β] (hf : AEStronglyMeasurable[m] f μ) + (hg : AEStronglyMeasurable[m] g μ) : AEStronglyMeasurable[m] (f * g) μ := ⟨hf.mk f * hg.mk g, hf.stronglyMeasurable_mk.mul hg.stronglyMeasurable_mk, hf.ae_eq_mk.mul hg.ae_eq_mk⟩ @[to_additive (attr := measurability)] -protected theorem mul_const [Mul β] [ContinuousMul β] (hf : AEStronglyMeasurable f μ) (c : β) : - AEStronglyMeasurable (fun x => f x * c) μ := +protected theorem mul_const [Mul β] [ContinuousMul β] (hf : AEStronglyMeasurable[m] f μ) (c : β) : + AEStronglyMeasurable[m] (fun x => f x * c) μ := hf.mul aestronglyMeasurable_const @[to_additive (attr := measurability)] -protected theorem const_mul [Mul β] [ContinuousMul β] (hf : AEStronglyMeasurable f μ) (c : β) : - AEStronglyMeasurable (fun x => c * f x) μ := +protected theorem const_mul [Mul β] [ContinuousMul β] (hf : AEStronglyMeasurable[m] f μ) (c : β) : + AEStronglyMeasurable[m] (fun x => c * f x) μ := aestronglyMeasurable_const.mul hf @[to_additive (attr := measurability)] -protected theorem inv [Inv β] [ContinuousInv β] (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable f⁻¹ μ := +protected theorem inv [Inv β] [ContinuousInv β] (hf : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] f⁻¹ μ := ⟨(hf.mk f)⁻¹, hf.stronglyMeasurable_mk.inv, hf.ae_eq_mk.inv⟩ @[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable]))] -protected theorem div [Group β] [TopologicalGroup β] (hf : AEStronglyMeasurable f μ) - (hg : AEStronglyMeasurable g μ) : AEStronglyMeasurable (f / g) μ := +protected theorem div [Group β] [TopologicalGroup β] (hf : AEStronglyMeasurable[m] f μ) + (hg : AEStronglyMeasurable[m] g μ) : AEStronglyMeasurable[m] (f / g) μ := ⟨hf.mk f / hg.mk g, hf.stronglyMeasurable_mk.div hg.stronglyMeasurable_mk, hf.ae_eq_mk.div hg.ae_eq_mk⟩ @[to_additive] -theorem mul_iff_right [CommGroup β] [TopologicalGroup β] (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable (f * g) μ ↔ AEStronglyMeasurable g μ := +theorem mul_iff_right [CommGroup β] [TopologicalGroup β] (hf : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] (f * g) μ ↔ AEStronglyMeasurable[m] g μ := ⟨fun h ↦ show g = f * g * f⁻¹ by simp only [mul_inv_cancel_comm] ▸ h.mul hf.inv, fun h ↦ hf.mul h⟩ @[to_additive] -theorem mul_iff_left [CommGroup β] [TopologicalGroup β] (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable (g * f) μ ↔ AEStronglyMeasurable g μ := +theorem mul_iff_left [CommGroup β] [TopologicalGroup β] (hf : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] (g * f) μ ↔ AEStronglyMeasurable[m] g μ := mul_comm g f ▸ AEStronglyMeasurable.mul_iff_right hf @[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable]))] protected theorem smul {𝕜} [TopologicalSpace 𝕜] [SMul 𝕜 β] [ContinuousSMul 𝕜 β] {f : α → 𝕜} - {g : α → β} (hf : AEStronglyMeasurable f μ) (hg : AEStronglyMeasurable g μ) : - AEStronglyMeasurable (fun x => f x • g x) μ := + {g : α → β} (hf : AEStronglyMeasurable[m] f μ) (hg : AEStronglyMeasurable[m] g μ) : + AEStronglyMeasurable[m] (fun x => f x • g x) μ := continuous_smul.comp_aestronglyMeasurable (hf.prod_mk hg) @[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable])) const_nsmul] -protected theorem pow [Monoid β] [ContinuousMul β] (hf : AEStronglyMeasurable f μ) (n : ℕ) : - AEStronglyMeasurable (f ^ n) μ := +protected theorem pow [Monoid β] [ContinuousMul β] (hf : AEStronglyMeasurable[m] f μ) (n : ℕ) : + AEStronglyMeasurable[m] (f ^ n) μ := ⟨hf.mk f ^ n, hf.stronglyMeasurable_mk.pow _, hf.ae_eq_mk.pow_const _⟩ @[to_additive (attr := measurability)] protected theorem const_smul {𝕜} [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] - (hf : AEStronglyMeasurable f μ) (c : 𝕜) : AEStronglyMeasurable (c • f) μ := + (hf : AEStronglyMeasurable[m] f μ) (c : 𝕜) : AEStronglyMeasurable[m] (c • f) μ := ⟨c • hf.mk f, hf.stronglyMeasurable_mk.const_smul c, hf.ae_eq_mk.const_smul c⟩ @[to_additive (attr := measurability)] protected theorem const_smul' {𝕜} [SMul 𝕜 β] [ContinuousConstSMul 𝕜 β] - (hf : AEStronglyMeasurable f μ) (c : 𝕜) : AEStronglyMeasurable (fun x => c • f x) μ := + (hf : AEStronglyMeasurable[m] f μ) (c : 𝕜) : AEStronglyMeasurable[m] (fun x => c • f x) μ := hf.const_smul c @[to_additive (attr := measurability)] protected theorem smul_const {𝕜} [TopologicalSpace 𝕜] [SMul 𝕜 β] [ContinuousSMul 𝕜 β] {f : α → 𝕜} - (hf : AEStronglyMeasurable f μ) (c : β) : AEStronglyMeasurable (fun x => f x • c) μ := + (hf : AEStronglyMeasurable[m] f μ) (c : β) : AEStronglyMeasurable[m] (fun x => f x • c) μ := continuous_smul.comp_aestronglyMeasurable (hf.prod_mk aestronglyMeasurable_const) end Arithmetic @@ -1448,7 +1505,7 @@ theorem nullMeasurableSet_le [Preorder β] [OrderClosedTopology β] [PseudoMetri simp only [hfx, hgx] theorem _root_.aestronglyMeasurable_of_aestronglyMeasurable_trim {α} {m m0 : MeasurableSpace α} - {μ : Measure α} (hm : m ≤ m0) {f : α → β} (hf : AEStronglyMeasurable f (μ.trim hm)) : + {μ : Measure α} (hm : m ≤ m0) {f : α → β} (hf : AEStronglyMeasurable[m] f (μ.trim hm)) : AEStronglyMeasurable f μ := ⟨hf.mk f, StronglyMeasurable.mono hf.stronglyMeasurable_mk hm, ae_eq_of_ae_eq_trim hf.ae_eq_mk⟩ @@ -1669,6 +1726,7 @@ theorem _root_.aestronglyMeasurable_const_smul_iff₀ {c : G₀} (hc : c ≠ 0) end MulAction +end AEStronglyMeasurable end AEStronglyMeasurable /-! ## Almost everywhere finitely strongly measurable functions -/ diff --git a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Inner.lean b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Inner.lean index 3cebf19542574..eecceb92a2a2d 100644 --- a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Inner.lean +++ b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Inner.lean @@ -11,8 +11,7 @@ import Mathlib.Analysis.InnerProductSpace.Basic -/ - -variable {α : Type*} +variable {α 𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] namespace MeasureTheory @@ -21,33 +20,36 @@ namespace MeasureTheory namespace StronglyMeasurable -protected theorem inner {𝕜 : Type*} {E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] - [InnerProductSpace 𝕜 E] {_ : MeasurableSpace α} {f g : α → E} (hf : StronglyMeasurable f) +protected theorem inner {_ : MeasurableSpace α} {f g : α → E} (hf : StronglyMeasurable f) (hg : StronglyMeasurable g) : StronglyMeasurable fun t => @inner 𝕜 _ _ (f t) (g t) := Continuous.comp_stronglyMeasurable continuous_inner (hf.prod_mk hg) end StronglyMeasurable namespace AEStronglyMeasurable - -variable {m : MeasurableSpace α} {μ : Measure α} {𝕜 : Type*} {E : Type*} [RCLike 𝕜] - [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable {m m₀ : MeasurableSpace α} {μ : Measure[m₀] α} {f g : α → E} {c : E} local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y -protected theorem re {f : α → 𝕜} (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable (fun x => RCLike.re (f x)) μ := +protected theorem re {f : α → 𝕜} (hf : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] (fun x => RCLike.re (f x)) μ := RCLike.continuous_re.comp_aestronglyMeasurable hf -protected theorem im {f : α → 𝕜} (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable (fun x => RCLike.im (f x)) μ := +protected theorem im {f : α → 𝕜} (hf : AEStronglyMeasurable[m] f μ) : + AEStronglyMeasurable[m] (fun x => RCLike.im (f x)) μ := RCLike.continuous_im.comp_aestronglyMeasurable hf protected theorem inner {_ : MeasurableSpace α} {μ : Measure α} {f g : α → E} - (hf : AEStronglyMeasurable f μ) (hg : AEStronglyMeasurable g μ) : - AEStronglyMeasurable (fun x => ⟪f x, g x⟫) μ := + (hf : AEStronglyMeasurable[m] f μ) (hg : AEStronglyMeasurable[m] g μ) : + AEStronglyMeasurable[m] (fun x => ⟪f x, g x⟫) μ := continuous_inner.comp_aestronglyMeasurable (hf.prod_mk hg) +lemma inner_const (hf : AEStronglyMeasurable[m] f μ) : AEStronglyMeasurable[m] (⟪f ·, c⟫) μ := + hf.inner aestronglyMeasurable_const + +lemma const_inner (hg : AEStronglyMeasurable[m] g μ) : AEStronglyMeasurable[m] (⟪c, g ·⟫) μ := + aestronglyMeasurable_const.inner hg + end AEStronglyMeasurable end MeasureTheory diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index 5153c29f675cc..51627a057494c 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -1847,34 +1847,11 @@ theorem integral_trim (hm : m ≤ m0) {f : β → G} (hf : StronglyMeasurable[m] (hf_int.trim hm hf) exact tendsto_nhds_unique h_lim_1 h_lim_2 -theorem integral_trim_ae (hm : m ≤ m0) {f : β → G} (hf : AEStronglyMeasurable f (μ.trim hm)) : +theorem integral_trim_ae (hm : m ≤ m0) {f : β → G} (hf : AEStronglyMeasurable[m] f (μ.trim hm)) : ∫ x, f x ∂μ = ∫ x, f x ∂μ.trim hm := by rw [integral_congr_ae (ae_eq_of_ae_eq_trim hf.ae_eq_mk), integral_congr_ae hf.ae_eq_mk] exact integral_trim hm hf.stronglyMeasurable_mk -theorem ae_eq_trim_of_stronglyMeasurable [TopologicalSpace γ] [MetrizableSpace γ] (hm : m ≤ m0) - {f g : β → γ} (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) - (hfg : f =ᵐ[μ] g) : f =ᵐ[μ.trim hm] g := by - rwa [EventuallyEq, ae_iff, trim_measurableSet_eq hm] - exact (hf.measurableSet_eq_fun hg).compl - -theorem ae_eq_trim_iff [TopologicalSpace γ] [MetrizableSpace γ] (hm : m ≤ m0) {f g : β → γ} - (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) : - f =ᵐ[μ.trim hm] g ↔ f =ᵐ[μ] g := - ⟨ae_eq_of_ae_eq_trim, ae_eq_trim_of_stronglyMeasurable hm hf hg⟩ - -theorem ae_le_trim_of_stronglyMeasurable [LinearOrder γ] [TopologicalSpace γ] - [OrderClosedTopology γ] [PseudoMetrizableSpace γ] (hm : m ≤ m0) {f g : β → γ} - (hf : StronglyMeasurable[m] f) (hg : StronglyMeasurable[m] g) (hfg : f ≤ᵐ[μ] g) : - f ≤ᵐ[μ.trim hm] g := by - rwa [EventuallyLE, ae_iff, trim_measurableSet_eq hm] - exact (hf.measurableSet_le hg).compl - -theorem ae_le_trim_iff [LinearOrder γ] [TopologicalSpace γ] [OrderClosedTopology γ] - [PseudoMetrizableSpace γ] (hm : m ≤ m0) {f g : β → γ} (hf : StronglyMeasurable[m] f) - (hg : StronglyMeasurable[m] g) : f ≤ᵐ[μ.trim hm] g ↔ f ≤ᵐ[μ] g := - ⟨ae_le_of_ae_le_trim, ae_le_trim_of_stronglyMeasurable hm hf hg⟩ - end IntegralTrim section SnormBound diff --git a/Mathlib/Probability/ConditionalExpectation.lean b/Mathlib/Probability/ConditionalExpectation.lean index f8e311d0628eb..04a9b261c32a8 100644 --- a/Mathlib/Probability/ConditionalExpectation.lean +++ b/Mathlib/Probability/ConditionalExpectation.lean @@ -41,7 +41,7 @@ theorem condExp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinit swap; · rw [condExp_undef hfint, integral_undef hfint]; rfl refine (ae_eq_condExp_of_forall_setIntegral_eq hle₂ hfint (fun s _ hs => integrableOn_const.2 (Or.inr hs)) (fun s hms hs => ?_) - stronglyMeasurable_const.aeStronglyMeasurable').symm + stronglyMeasurable_const.aestronglyMeasurable).symm rw [setIntegral_const] rw [← memℒp_one_iff_integrable] at hfint refine Memℒp.induction_stronglyMeasurable hle₁ ENNReal.one_ne_top _ ?_ ?_ ?_ ?_ hfint ?_ diff --git a/Mathlib/Probability/Independence/Conditional.lean b/Mathlib/Probability/Independence/Conditional.lean index c0fa7ff20f56a..9fa9a790247a1 100644 --- a/Mathlib/Probability/Independence/Conditional.lean +++ b/Mathlib/Probability/Independence/Conditional.lean @@ -172,9 +172,8 @@ lemma iCondIndepSets_iff (π : ι → Set (Set Ω)) (hπ : ∀ i s (_hs : s ∈ filter_upwards [h_eq s f hf, h_inter_eq s f hf, h'] with ω h_eq h_inter_eq h' rw [← h_inter_eq, h', ENNReal.toReal_prod, Finset.prod_apply] exact Finset.prod_congr rfl h_eq - · refine (ae_eq_trim_iff hm' ?_ ?_).mpr ?_ - · refine stronglyMeasurable_condExpKernel ?_ - exact MeasurableSet.biInter (Finset.countable_toSet _) (fun i hi ↦ hπ i _ (hf i hi)) + · refine ((stronglyMeasurable_condExpKernel ?_).ae_eq_trim_iff hm' ?_).mpr ?_ + · exact .biInter (Finset.countable_toSet _) (fun i hi ↦ hπ i _ (hf i hi)) · refine Measurable.stronglyMeasurable ?_ exact Finset.measurable_prod s (fun i hi ↦ measurable_condExpKernel (hπ i _ (hf i hi))) filter_upwards [h_eq s f hf, h_inter_eq s f hf, h] with ω h_eq h_inter_eq h @@ -203,11 +202,9 @@ lemma condIndepSets_iff (s1 s2 : Set (Set Ω)) (hs1 : ∀ s ∈ s1, MeasurableSe · have h' := ae_eq_of_ae_eq_trim h filter_upwards [hs1_eq s hs, hs2_eq t ht, hs12_eq s hs t ht, h'] with ω hs_eq ht_eq hst_eq h' rw [← hst_eq, Pi.mul_apply, ← hs_eq, ← ht_eq, h', ENNReal.toReal_mul] - · refine (ae_eq_trim_iff hm' ?_ ?_).mpr ?_ - · exact stronglyMeasurable_condExpKernel ((hs1 s hs).inter ((hs2 t ht))) - · refine Measurable.stronglyMeasurable (Measurable.mul ?_ ?_) - · exact measurable_condExpKernel (hs1 s hs) - · exact measurable_condExpKernel (hs2 t ht) + · refine ((stronglyMeasurable_condExpKernel ((hs1 s hs).inter (hs2 t ht))).ae_eq_trim_iff hm' + ((measurable_condExpKernel (hs1 s hs)).mul + (measurable_condExpKernel (hs2 t ht))).stronglyMeasurable).mpr ?_ filter_upwards [hs1_eq s hs, hs2_eq t ht, hs12_eq s hs t ht, h] with ω hs_eq ht_eq hst_eq h have h_ne_top : condExpKernel μ m' ω (s ∩ t) ≠ ∞ := measure_ne_top (condExpKernel μ m' ω) _ rw [← ENNReal.ofReal_toReal h_ne_top, hst_eq, h, Pi.mul_apply, ← hs_eq, ← ht_eq, diff --git a/Mathlib/Probability/Kernel/CondDistrib.lean b/Mathlib/Probability/Kernel/CondDistrib.lean index f33383cd5df84..8868754b1be92 100644 --- a/Mathlib/Probability/Kernel/CondDistrib.lean +++ b/Mathlib/Probability/Kernel/CondDistrib.lean @@ -100,11 +100,14 @@ theorem _root_.MeasureTheory.AEStronglyMeasurable.integral_condDistrib (hX : AEM AEStronglyMeasurable (fun a => ∫ y, f (X a, y) ∂condDistrib Y X μ (X a)) μ := (hf.integral_condDistrib_map hY).comp_aemeasurable hX -theorem aestronglyMeasurable'_integral_condDistrib (hX : AEMeasurable X μ) (hY : AEMeasurable Y μ) +theorem aestronglyMeasurable_integral_condDistrib (hX : AEMeasurable X μ) (hY : AEMeasurable Y μ) (hf : AEStronglyMeasurable f (μ.map fun a => (X a, Y a))) : - AEStronglyMeasurable' (mβ.comap X) (fun a => ∫ y, f (X a, y) ∂condDistrib Y X μ (X a)) μ := + AEStronglyMeasurable[mβ.comap X] (fun a => ∫ y, f (X a, y) ∂condDistrib Y X μ (X a)) μ := (hf.integral_condDistrib_map hY).comp_ae_measurable' hX +@[deprecated (since := "2025-01-24")] +alias aestronglyMeasurable'_integral_condDistrib := aestronglyMeasurable_integral_condDistrib + end Measurability /-- `condDistrib` is a.e. uniquely defined as the kernel satisfying the defining property of @@ -212,8 +215,7 @@ theorem condDistrib_ae_eq_condExp (hX : Measurable X) (hY : Measurable Y) (hs : (Eventually.of_forall fun ω => measure_lt_top (condDistrib Y X μ (X ω)) _), integral_indicator_const _ (hY hs), Measure.restrict_apply (hY hs), smul_eq_mul, mul_one, inter_comm, setLIntegral_condDistrib_of_measurableSet hX hY.aemeasurable hs ht] - · refine (Measurable.stronglyMeasurable ?_).aeStronglyMeasurable' - exact @Measurable.ennreal_toReal _ (mβ.comap X) _ (measurable_condDistrib hs) + · exact (measurable_condDistrib hs).ennreal_toReal.aestronglyMeasurable @[deprecated (since := "2025-01-21")] alias condDistrib_ae_eq_condexp := condDistrib_ae_eq_condExp @@ -239,7 +241,7 @@ theorem condExp_prod_ae_eq_integral_condDistrib' [NormedSpace ℝ F] [CompleteSp Measure.setIntegral_condKernel_univ_right ht hf_int.integrableOn, setIntegral_map (ht.prod MeasurableSet.univ) hf_int.1 (hX.aemeasurable.prod_mk hY), mk_preimage_prod, preimage_univ, inter_univ] - · exact aestronglyMeasurable'_integral_condDistrib hX.aemeasurable hY hf_int.1 + · exact aestronglyMeasurable_integral_condDistrib hX.aemeasurable hY hf_int.1 @[deprecated (since := "2025-01-21")] alias condexp_prod_ae_eq_integral_condDistrib' := condExp_prod_ae_eq_integral_condDistrib' diff --git a/Mathlib/Probability/Kernel/Condexp.lean b/Mathlib/Probability/Kernel/Condexp.lean index 87e449f00fafe..d12727bf44629 100644 --- a/Mathlib/Probability/Kernel/Condexp.lean +++ b/Mathlib/Probability/Kernel/Condexp.lean @@ -41,7 +41,8 @@ section AuxLemmas variable {Ω F : Type*} {m mΩ : MeasurableSpace Ω} {μ : Measure Ω} {f : Ω → F} theorem _root_.MeasureTheory.AEStronglyMeasurable.comp_snd_map_prod_id [TopologicalSpace F] - (hm : m ≤ mΩ) (hf : AEStronglyMeasurable f μ) : AEStronglyMeasurable (fun x : Ω × Ω => f x.2) + (hm : m ≤ mΩ) (hf : AEStronglyMeasurable f μ) : + AEStronglyMeasurable[m.prod mΩ] (fun x : Ω × Ω => f x.2) (@Measure.map Ω (Ω × Ω) mΩ (m.prod mΩ) (fun ω => (id ω, id ω)) μ) := by rw [← aestronglyMeasurable_comp_snd_map_prod_mk_iff (measurable_id'' hm)] at hf simp_rw [id] at hf ⊢ @@ -129,19 +130,22 @@ theorem _root_.MeasureTheory.AEStronglyMeasurable.integral_condExpKernel [Normed alias _root_.MeasureTheory.AEStronglyMeasurable.integral_condexpKernel := _root_.MeasureTheory.AEStronglyMeasurable.integral_condExpKernel -theorem aestronglyMeasurable'_integral_condExpKernel [NormedSpace ℝ F] +theorem aestronglyMeasurable_integral_condExpKernel [NormedSpace ℝ F] (hf : AEStronglyMeasurable f μ) : - AEStronglyMeasurable' m (fun ω => ∫ y, f y ∂condExpKernel μ m ω) μ := by + AEStronglyMeasurable[m] (fun ω => ∫ y, f y ∂condExpKernel μ m ω) μ := by nontriviality Ω rw [condExpKernel_eq] - have h := aestronglyMeasurable'_integral_condDistrib + have h := aestronglyMeasurable_integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) rw [MeasurableSpace.comap_id] at h - exact AEStronglyMeasurable'.mono h inf_le_left + exact h.mono inf_le_left + +@[deprecated (since := "2025-01-24")] +alias aestronglyMeasurable'_integral_condExpKernel := aestronglyMeasurable_integral_condExpKernel @[deprecated (since := "2025-01-21")] -alias aestronglyMeasurable'_integral_condexpKernel := aestronglyMeasurable'_integral_condExpKernel +alias aestronglyMeasurable'_integral_condexpKernel := aestronglyMeasurable_integral_condExpKernel end Measurability @@ -235,10 +239,9 @@ alias condexpKernel_ae_eq_condexp := condExpKernel_ae_eq_condExp lemma condExpKernel_ae_eq_trim_condExp (hm : m ≤ mΩ) {s : Set Ω} (hs : MeasurableSet s) : (fun ω ↦ (condExpKernel μ m ω s).toReal) =ᵐ[μ.trim hm] μ⟦s | m⟧ := by - rw [ae_eq_trim_iff hm _ stronglyMeasurable_condExp] - · exact condExpKernel_ae_eq_condExp hm hs - · refine Measurable.stronglyMeasurable ?_ - exact @Measurable.ennreal_toReal _ m _ (measurable_condExpKernel hs) + rw [(measurable_condExpKernel hs).ennreal_toReal.stronglyMeasurable.ae_eq_trim_iff hm + stronglyMeasurable_condExp] + exact condExpKernel_ae_eq_condExp hm hs @[deprecated (since := "2025-01-21")] alias condexpKernel_ae_eq_trim_condexp := condExpKernel_ae_eq_trim_condExp @@ -285,9 +288,8 @@ lemma condExp_generateFrom_singleton (hs : MeasurableSet s) {f : Ω → F} (hf : refine ae_eq_trans (condExp_restrict_ae_eq_restrict (generateFrom_singleton_le hs) (measurableSet_generateFrom rfl) hf).symm ?_ - · refine (ae_eq_condExp_of_forall_setIntegral_eq - (generateFrom_singleton_le hs) hf.restrict ?_ ?_ - stronglyMeasurable_const.aeStronglyMeasurable').symm + · refine (ae_eq_condExp_of_forall_setIntegral_eq (generateFrom_singleton_le hs) hf.restrict ?_ ?_ + stronglyMeasurable_const.aestronglyMeasurable).symm · rintro t - - rw [integrableOn_const] exact Or.inr <| measure_lt_top (μ.restrict s) t diff --git a/Mathlib/Probability/Kernel/Disintegration/Density.lean b/Mathlib/Probability/Kernel/Disintegration/Density.lean index eba7c9ae48353..1ac6c0d62bdfe 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Density.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Density.lean @@ -298,7 +298,7 @@ lemma condExp_densityProcess (hκν : fst κ ≤ ν) [IsFiniteKernel ν] · intro x hx _ rw [setIntegral_densityProcess hκν i a hs hx, setIntegral_densityProcess_of_le hκν hij a hs hx] - · exact StronglyMeasurable.aeStronglyMeasurable' + · exact StronglyMeasurable.aestronglyMeasurable (stronglyMeasurable_countableFiltration_densityProcess κ ν i a hs) @[deprecated (since := "2025-01-21")] alias condexp_densityProcess := condExp_densityProcess diff --git a/Mathlib/Probability/Martingale/Convergence.lean b/Mathlib/Probability/Martingale/Convergence.lean index 57105ca759aaf..78e152f66e770 100644 --- a/Mathlib/Probability/Martingale/Convergence.lean +++ b/Mathlib/Probability/Martingale/Convergence.lean @@ -215,7 +215,7 @@ theorem Submartingale.ae_tendsto_limitProcess [IsFiniteMeasure μ] (hf : Submart filter_upwards [hf.exists_ae_trim_tendsto_of_bdd hbdd] with ω hω simp_rw [g', dif_pos hω] exact hω.choose_spec - have hg'm : @AEStronglyMeasurable _ _ _ (⨆ n, ℱ n) g' (μ.trim hle) := + have hg'm : AEStronglyMeasurable[⨆ n, ℱ n] g' (μ.trim hle) := (@aemeasurable_of_tendsto_metrizable_ae' _ _ (⨆ n, ℱ n) _ _ _ _ _ _ _ (fun n => ((hf.stronglyMeasurable n).measurable.mono (le_sSup ⟨n, rfl⟩ : ℱ n ≤ ⨆ n, ℱ n) le_rfl).aemeasurable) hg').aestronglyMeasurable @@ -388,8 +388,8 @@ theorem Integrable.tendsto_ae_condExp (hg : Integrable g μ) filter_upwards [(martingale_condExp g ℱ μ).ae_eq_condExp_limitProcess hunif n] with x hx _ rw [hx] refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hle (fun s _ _ => hg.integrableOn) - (fun s _ _ => hlimint.integrableOn) (fun s hs _ => ?_) hgmeas.aeStronglyMeasurable' - stronglyMeasurable_limitProcess.aeStronglyMeasurable' + (fun s _ _ => hlimint.integrableOn) (fun s hs _ => ?_) hgmeas.aestronglyMeasurable + stronglyMeasurable_limitProcess.aestronglyMeasurable have hpi : IsPiSystem {s | ∃ n, MeasurableSet[ℱ n] s} := by rw [Set.setOf_exists] exact isPiSystem_iUnion_of_monotone _ (fun n ↦ (ℱ n).isPiSystem_measurableSet) fun _ _ ↦ ℱ.mono diff --git a/Mathlib/Probability/Martingale/OptionalSampling.lean b/Mathlib/Probability/Martingale/OptionalSampling.lean index 6352474b3e335..bf95b0773b2a2 100644 --- a/Mathlib/Probability/Martingale/OptionalSampling.lean +++ b/Mathlib/Probability/Martingale/OptionalSampling.lean @@ -178,9 +178,9 @@ theorem condExp_stoppedValue_stopping_time_ae_eq_restrict_le (h : Martingale f Integrable ({ω : Ω | τ ω ≤ σ ω}.indicator (stoppedValue (fun n : ι => f n) τ)) μ := by refine (integrable_stoppedValue ι hτ h.integrable hτ_le).indicator ?_ exact hτ.measurableSpace_le _ (hτ.measurableSet_le_stopping_time hσ) - have h_meas : AEStronglyMeasurable' hσ.measurableSpace + have h_meas : AEStronglyMeasurable[hσ.measurableSpace] ({ω : Ω | τ ω ≤ σ ω}.indicator (stoppedValue (fun n : ι => f n) τ)) μ := by - refine StronglyMeasurable.aeStronglyMeasurable' ?_ + refine StronglyMeasurable.aestronglyMeasurable ?_ refine StronglyMeasurable.stronglyMeasurable_of_measurableSpace_le_on (hτ.measurableSet_le_stopping_time hσ) ?_ ?_ ?_ · intro t ht diff --git a/scripts/nolints_prime_decls.txt b/scripts/nolints_prime_decls.txt index 31d8b5d0d0839..be856e67cdf24 100644 --- a/scripts/nolints_prime_decls.txt +++ b/scripts/nolints_prime_decls.txt @@ -2833,7 +2833,7 @@ 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.lpMeas.aestronglyMeasurable MeasureTheory.Lp.norm_const' MeasureTheory.Lp.simpleFunc.eq' MeasureTheory.Lp.tendsto_Lp_iff_tendsto_ℒp' @@ -2895,7 +2895,6 @@ 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' @@ -2962,7 +2961,7 @@ MeasureTheory.stoppedProcess_eq'' MeasureTheory.stoppedValue_eq' MeasureTheory.stoppedValue_piecewise_const' MeasureTheory.stoppedValue_sub_eq_sum' -MeasureTheory.StronglyMeasurable.aeStronglyMeasurable' +MeasureTheory.StronglyMeasurable.aestronglyMeasurable MeasureTheory.StronglyMeasurable.const_smul' MeasureTheory.StronglyMeasurable.integral_kernel_prod_left' MeasureTheory.StronglyMeasurable.integral_kernel_prod_left'' From 974ebe9d972639d4379e96da7e62a125a7e77b27 Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Sat, 25 Jan 2025 09:47:37 +0000 Subject: [PATCH 513/681] feat(MeasureTheory/IntegrableOn): add `integrableAtFilter_atBot_iff` (#21016) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the following statement ```lean theorem integrableAtFilter_atBot_iff : IntegrableAtFilter f atBot μ ↔ ∃ a, IntegrableOn f (Iic a) μ ``` and a similar statement for `atTop`. Co-authored-by: Xavier Roblot <46200072+xroblot@users.noreply.github.com> --- Mathlib/MeasureTheory/Integral/IntegrableOn.lean | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index d92e2f0b636d3..9093ea80babe2 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -376,6 +376,18 @@ protected theorem IntegrableAtFilter.eventually (h : IntegrableAtFilter f l μ) ∀ᶠ s in l.smallSets, IntegrableOn f s μ := Iff.mpr (eventually_smallSets' fun _s _t hst ht => ht.mono_set hst) h +theorem integrableAtFilter_atBot_iff [Preorder α] [IsDirected α fun (x1 x2 : α) => x1 ≥ x2] + [Nonempty α] : + IntegrableAtFilter f atBot μ ↔ ∃ a, IntegrableOn f (Iic a) μ := by + refine ⟨fun ⟨s, hs, hi⟩ ↦ ?_, fun ⟨a, ha⟩ ↦ ⟨Iic a, Iic_mem_atBot a, ha⟩⟩ + obtain ⟨t, ht⟩ := mem_atBot_sets.mp hs + exact ⟨t, hi.mono_set fun _ hx ↦ ht _ hx⟩ + +theorem integrableAtFilter_atTop_iff [Preorder α] [IsDirected α fun (x1 x2 : α) => x1 ≤ x2] + [Nonempty α] : + IntegrableAtFilter f atTop μ ↔ ∃ a, IntegrableOn f (Ici a) μ := + integrableAtFilter_atBot_iff (α := αᵒᵈ) + protected theorem IntegrableAtFilter.add {f g : α → E} (hf : IntegrableAtFilter f l μ) (hg : IntegrableAtFilter g l μ) : IntegrableAtFilter (f + g) l μ := by From b23a78ef44c332aef4db22a4183d658554e4e343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 25 Jan 2025 09:47:38 +0000 Subject: [PATCH 514/681] doc: turn links to Stacks into `stacks` attributes (#21046) I did not touch the links that are in module docs. --- Mathlib/CategoryTheory/Abelian/Basic.lean | 8 ++-- Mathlib/CategoryTheory/Abelian/Images.lean | 6 +-- Mathlib/CategoryTheory/Abelian/Transfer.lean | 6 +-- Mathlib/CategoryTheory/Adjunction/Basic.lean | 13 ++---- Mathlib/CategoryTheory/Adjunction/Limits.lean | 12 ++---- Mathlib/CategoryTheory/Category/Basic.lean | 19 +++------ Mathlib/CategoryTheory/Category/Preorder.lean | 6 +-- Mathlib/CategoryTheory/Comma/Over.lean | 18 +++------ Mathlib/CategoryTheory/DiscreteCategory.lean | 6 +-- Mathlib/CategoryTheory/Equivalence.lean | 31 +++++--------- Mathlib/CategoryTheory/EssentialImage.lean | 6 +-- .../FiberedCategory/Cartesian.lean | 5 +-- .../FiberedCategory/Cocartesian.lean | 5 +-- Mathlib/CategoryTheory/Filtered/Basic.lean | 12 ++---- Mathlib/CategoryTheory/FullSubcategory.lean | 7 +--- Mathlib/CategoryTheory/Functor/Basic.lean | 6 +-- .../CategoryTheory/Functor/FullyFaithful.lean | 12 ++---- Mathlib/CategoryTheory/IsConnected.lean | 6 +-- Mathlib/CategoryTheory/Iso.lean | 6 +-- .../LimitsOfProductsAndEqualizers.lean | 24 ++++------- Mathlib/CategoryTheory/Limits/Final.lean | 6 +-- Mathlib/CategoryTheory/Limits/IsLimit.lean | 12 ++---- .../Limits/Shapes/BinaryProducts.lean | 12 ++---- .../Limits/Shapes/Pullback/HasPullback.lean | 6 +-- Mathlib/CategoryTheory/Limits/Types.lean | 12 ++---- .../Monoidal/Braided/Basic.lean | 6 +-- Mathlib/CategoryTheory/Monoidal/Category.lean | 6 +-- Mathlib/CategoryTheory/Noetherian.lean | 12 ++---- Mathlib/CategoryTheory/Opposites.lean | 6 +-- Mathlib/CategoryTheory/Products/Basic.lean | 7 +--- Mathlib/CategoryTheory/SingleObj.lean | 14 ++----- Mathlib/CategoryTheory/Sites/Canonical.lean | 6 +-- .../Sites/EqualizerSheafCondition.lean | 11 ++--- .../CategoryTheory/Sites/Grothendieck.lean | 23 +++++------ Mathlib/CategoryTheory/Sites/Pretopology.lean | 9 ++--- .../CategoryTheory/Triangulated/Basic.lean | 8 ++-- .../Triangulated/Pretriangulated.lean | 21 ++++------ .../Triangulated/Triangulated.lean | 7 ++-- Mathlib/CategoryTheory/Types.lean | 12 ++---- Mathlib/CategoryTheory/Yoneda.lean | 40 ++++++------------- Mathlib/RingTheory/Etale/Basic.lean | 6 +-- Mathlib/RingTheory/Smooth/Basic.lean | 7 +--- Mathlib/RingTheory/Unramified/Basic.lean | 6 +-- .../Topology/Category/Profinite/Basic.lean | 5 +-- Mathlib/Topology/Sheaves/Forget.lean | 7 +--- 45 files changed, 164 insertions(+), 317 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/Basic.lean b/Mathlib/CategoryTheory/Abelian/Basic.lean index 34d8b479eb65e..7071943140dbb 100644 --- a/Mathlib/CategoryTheory/Abelian/Basic.lean +++ b/Mathlib/CategoryTheory/Abelian/Basic.lean @@ -242,11 +242,9 @@ attribute [local instance] OfCoimageImageComparisonIsIso.isNormalEpiCategory /-- A preadditive category with kernels, cokernels, and finite products, in which the coimage-image comparison morphism is always an isomorphism, -is an abelian category. - -The Stacks project uses this characterisation at the definition of an abelian category. -See . --/ +is an abelian category. -/ +@[stacks 0109 +"The Stacks project uses this characterisation at the definition of an abelian category."] def ofCoimageImageComparisonIsIso : Abelian C where end CategoryTheory.Abelian diff --git a/Mathlib/CategoryTheory/Abelian/Images.lean b/Mathlib/CategoryTheory/Abelian/Images.lean index 1d4f4e9e92564..8c3bf7213ffe1 100644 --- a/Mathlib/CategoryTheory/Abelian/Images.lean +++ b/Mathlib/CategoryTheory/Abelian/Images.lean @@ -85,10 +85,8 @@ end Coimage In any abelian category this is an isomorphism. Conversely, any additive category with kernels and cokernels and -in which this is always an isomorphism, is abelian. - -See --/ +in which this is always an isomorphism, is abelian. -/ +@[stacks 0107] def coimageImageComparison : Abelian.coimage f ⟶ Abelian.image f := cokernel.desc (kernel.ι f) (kernel.lift (cokernel.π f) f (by simp)) (by ext; simp) diff --git a/Mathlib/CategoryTheory/Abelian/Transfer.lean b/Mathlib/CategoryTheory/Abelian/Transfer.lean index 61b48e84e435b..20ca075bae757 100644 --- a/Mathlib/CategoryTheory/Abelian/Transfer.lean +++ b/Mathlib/CategoryTheory/Abelian/Transfer.lean @@ -154,10 +154,8 @@ open AbelianOfAdjunction we have `F : C ⥤ D` `G : D ⥤ C` (both preserving zero morphisms), `G` is left exact (that is, preserves finite limits), and further we have `adj : G ⊣ F` and `i : F ⋙ G ≅ 𝟭 C`, -then `C` is also abelian. - -See --/ +then `C` is also abelian. -/ +@[stacks 03A3] def abelianOfAdjunction {C : Type u₁} [Category.{v₁} C] [Preadditive C] [HasFiniteProducts C] {D : Type u₂} [Category.{v₂} D] [Abelian D] (F : C ⥤ D) [Functor.PreservesZeroMorphisms F] (G : D ⥤ C) [Functor.PreservesZeroMorphisms G] [PreservesFiniteLimits G] (i : F ⋙ G ≅ 𝟭 C) diff --git a/Mathlib/CategoryTheory/Adjunction/Basic.lean b/Mathlib/CategoryTheory/Adjunction/Basic.lean index e821bebd0ae15..edb9845c4258c 100644 --- a/Mathlib/CategoryTheory/Adjunction/Basic.lean +++ b/Mathlib/CategoryTheory/Adjunction/Basic.lean @@ -97,10 +97,8 @@ There is also a constructor `Adjunction.mkOfHomEquiv` which constructs an adjunc hom set equivalence. To construct adjoints to a given functor, there are constructors `leftAdjointOfEquiv` and -`adjunctionOfEquivLeft` (as well as their duals). - -See . --/ +`adjunctionOfEquivLeft` (as well as their duals). -/ +@[stacks 0037] structure Adjunction (F : C ⥤ D) (G : D ⥤ C) where /-- The unit of an adjunction -/ unit : 𝟭 C ⟶ F.comp G @@ -508,11 +506,8 @@ section variable {E : Type u₃} [ℰ : Category.{v₃} E] {H : D ⥤ E} {I : E ⥤ D} (adj₁ : F ⊣ G) (adj₂ : H ⊣ I) -/-- Composition of adjunctions. - -See . --/ -@[simps! (config := .lemmasOnly) unit counit] +/-- Composition of adjunctions. -/ +@[simps! (config := .lemmasOnly) unit counit, stacks 0DV0] def comp : F ⋙ H ⊣ I ⋙ G := mk' { homEquiv := fun _ _ ↦ Equiv.trans (adj₂.homEquiv _ _) (adj₁.homEquiv _ _) diff --git a/Mathlib/CategoryTheory/Adjunction/Limits.lean b/Mathlib/CategoryTheory/Adjunction/Limits.lean index 2db2c795ef2c2..2706ad1af5434 100644 --- a/Mathlib/CategoryTheory/Adjunction/Limits.lean +++ b/Mathlib/CategoryTheory/Adjunction/Limits.lean @@ -79,10 +79,8 @@ def functorialityAdjunction : Cocones.functoriality K F ⊣ functorialityRightAd counit := functorialityCounit adj K include adj in -/-- A left adjoint preserves colimits. - -See . --/ +/-- A left adjoint preserves colimits. -/ +@[stacks 0038] lemma leftAdjoint_preservesColimits : PreservesColimitsOfSize.{v, u} F where preservesColimitsOfShape := { preservesColimit := @@ -203,10 +201,8 @@ def functorialityAdjunction' : functorialityLeftAdjoint adj K ⊣ Cones.functori counit := functorialityCounit' adj K include adj in -/-- A right adjoint preserves limits. - -See . --/ +/-- A right adjoint preserves limits. -/ +@[stacks 0038] lemma rightAdjoint_preservesLimits : PreservesLimitsOfSize.{v, u} G where preservesLimitsOfShape := { preservesLimit := diff --git a/Mathlib/CategoryTheory/Category/Basic.lean b/Mathlib/CategoryTheory/Category/Basic.lean index d314808670795..e47e8bcebd744 100644 --- a/Mathlib/CategoryTheory/Category/Basic.lean +++ b/Mathlib/CategoryTheory/Category/Basic.lean @@ -142,11 +142,8 @@ attribute [aesop safe (rule_sets := [CategoryTheory])] Subsingleton.elim /-- The typeclass `Category C` describes morphisms associated to objects of type `C`. The universe levels of the objects and morphisms are unconstrained, and will often need to be -specified explicitly, as `Category.{v} C`. (See also `LargeCategory` and `SmallCategory`.) - -See . --/ -@[pp_with_univ] +specified explicitly, as `Category.{v} C`. (See also `LargeCategory` and `SmallCategory`.) -/ +@[pp_with_univ, stacks 0014] class Category (obj : Type u) extends CategoryStruct.{v} obj : Type max u (v + 1) where /-- Identity morphisms are left identities for composition. -/ id_comp : ∀ {X Y : obj} (f : X ⟶ Y), 𝟙 X ≫ f = f := by aesop_cat @@ -235,19 +232,15 @@ theorem dite_comp {P : Prop} [Decidable P] (if h : P then f h else f' h) ≫ g = if h : P then f h ≫ g else f' h ≫ g := by aesop /-- A morphism `f` is an epimorphism if it can be cancelled when precomposed: -`f ≫ g = f ≫ h` implies `g = h`. - -See . --/ +`f ≫ g = f ≫ h` implies `g = h`. -/ +@[stacks 003B] class Epi (f : X ⟶ Y) : Prop where /-- A morphism `f` is an epimorphism if it can be cancelled when precomposed. -/ left_cancellation : ∀ {Z : C} (g h : Y ⟶ Z), f ≫ g = f ≫ h → g = h /-- A morphism `f` is a monomorphism if it can be cancelled when postcomposed: -`g ≫ f = h ≫ f` implies `g = h`. - -See . --/ +`g ≫ f = h ≫ f` implies `g = h`. -/ +@[stacks 003B] class Mono (f : X ⟶ Y) : Prop where /-- A morphism `f` is a monomorphism if it can be cancelled when postcomposed. -/ right_cancellation : ∀ {Z : C} (g h : Z ⟶ X), g ≫ f = h ≫ f → g = h diff --git a/Mathlib/CategoryTheory/Category/Preorder.lean b/Mathlib/CategoryTheory/Category/Preorder.lean index f2935460a2529..fee0af705c592 100644 --- a/Mathlib/CategoryTheory/Category/Preorder.lean +++ b/Mathlib/CategoryTheory/Category/Preorder.lean @@ -39,10 +39,8 @@ The category structure coming from a preorder. There is a morphism `X ⟶ Y` if Because we don't allow morphisms to live in `Prop`, we have to define `X ⟶ Y` as `ULift (PLift (X ≤ Y))`. -See `CategoryTheory.homOfLE` and `CategoryTheory.leOfHom`. - -See . --/ +See `CategoryTheory.homOfLE` and `CategoryTheory.leOfHom`. -/ +@[stacks 00D3] instance (priority := 100) smallCategory (α : Type u) [Preorder α] : SmallCategory α where Hom U V := ULift (PLift (U ≤ V)) id X := ⟨⟨le_refl X⟩⟩ diff --git a/Mathlib/CategoryTheory/Comma/Over.lean b/Mathlib/CategoryTheory/Comma/Over.lean index 570cbd7d2a569..2a293365b9ad6 100644 --- a/Mathlib/CategoryTheory/Comma/Over.lean +++ b/Mathlib/CategoryTheory/Comma/Over.lean @@ -30,10 +30,8 @@ variable {T : Type u₁} [Category.{v₁} T] variable {D : Type u₂} [Category.{v₂} D] /-- The over category has as objects arrows in `T` with codomain `X` and as morphisms commutative -triangles. - -See . --/ +triangles. -/ +@[stacks 001G] def Over (X : T) := CostructuredArrow (𝟭 T) X @@ -118,10 +116,8 @@ section variable (X) -/-- The forgetful functor mapping an arrow to its domain. - -See . --/ +/-- The forgetful functor mapping an arrow to its domain. -/ +@[stacks 001G] def forget : Over X ⥤ T := Comma.fst _ _ @@ -141,10 +137,8 @@ def forgetCocone (X : T) : Limits.Cocone (forget X) := { pt := X ι := { app := Comma.hom } } -/-- A morphism `f : X ⟶ Y` induces a functor `Over X ⥤ Over Y` in the obvious way. - -See . --/ +/-- A morphism `f : X ⟶ Y` induces a functor `Over X ⥤ Over Y` in the obvious way. -/ +@[stacks 001G] def map {Y : T} (f : X ⟶ Y) : Over X ⥤ Over Y := Comma.mapRight _ <| Discrete.natTrans fun _ => f diff --git a/Mathlib/CategoryTheory/DiscreteCategory.lean b/Mathlib/CategoryTheory/DiscreteCategory.lean index 4505a8e1b9584..f97365afa177a 100644 --- a/Mathlib/CategoryTheory/DiscreteCategory.lean +++ b/Mathlib/CategoryTheory/DiscreteCategory.lean @@ -67,10 +67,8 @@ instance {α : Type u₁} [DecidableEq α] : DecidableEq (Discrete α) := /-- The "Discrete" category on a type, whose morphisms are equalities. Because we do not allow morphisms in `Prop` (only in `Type`), -somewhat annoyingly we have to define `X ⟶ Y` as `ULift (PLift (X = Y))`. - -See --/ +somewhat annoyingly we have to define `X ⟶ Y` as `ULift (PLift (X = Y))`. -/ +@[stacks 001A] instance discreteCategory (α : Type u₁) : SmallCategory (Discrete α) where Hom X Y := ULift (PLift (X.as = Y.as)) id _ := ULift.up (PLift.up rfl) diff --git a/Mathlib/CategoryTheory/Equivalence.lean b/Mathlib/CategoryTheory/Equivalence.lean index 85a5fc5503a8c..073a622465f51 100644 --- a/Mathlib/CategoryTheory/Equivalence.lean +++ b/Mathlib/CategoryTheory/Equivalence.lean @@ -71,11 +71,8 @@ universe v₁ v₂ v₃ u₁ u₂ u₃ The triangle equation is written as a family of equalities between morphisms, it is more complicated if we write it as an equality of natural transformations, because then we would have - to insert natural transformations like `F ⟶ F1`. - -See --/ -@[ext] + to insert natural transformations like `F ⟶ F1`. -/ +@[ext, stacks 001J] structure Equivalence (C : Type u₁) (D : Type u₂) [Category.{v₁} C] [Category.{v₂} D] where mk' :: /-- A functor in one direction -/ functor : C ⥤ D @@ -425,10 +422,8 @@ theorem pow_neg_one (e : C ≌ C) : e ^ (-1 : ℤ) = e.symm := -- Note: the better formulation of this would involve `HasShift`. end -/-- The functor of an equivalence of categories is essentially surjective. - -See . --/ +/-- The functor of an equivalence of categories is essentially surjective. -/ +@[stacks 02C3] instance essSurj_functor (e : C ≌ E) : e.functor.EssSurj := ⟨fun Y => ⟨e.inverse.obj Y, ⟨e.counitIso.app Y⟩⟩⟩ @@ -443,20 +438,16 @@ def fullyFaithfulFunctor (e : C ≌ E) : e.functor.FullyFaithful where def fullyFaithfulInverse (e : C ≌ E) : e.inverse.FullyFaithful where preimage {X Y} f := e.counitIso.inv.app X ≫ e.functor.map f ≫ e.counitIso.hom.app Y -/-- The functor of an equivalence of categories is faithful. - -See . --/ +/-- The functor of an equivalence of categories is faithful. -/ +@[stacks 02C3] instance faithful_functor (e : C ≌ E) : e.functor.Faithful := e.fullyFaithfulFunctor.faithful instance faithful_inverse (e : C ≌ E) : e.inverse.Faithful := e.fullyFaithfulInverse.faithful -/-- The functor of an equivalence of categories is full. - -See . --/ +/-- The functor of an equivalence of categories is full. -/ +@[stacks 02C3] instance full_functor (e : C ≌ E) : e.functor.Full := e.fullyFaithfulFunctor.full @@ -527,10 +518,8 @@ noncomputable def inv (F : C ⥤ D) [F.IsEquivalence] : D ⥤ C where map_id X := by apply F.map_injective; simp map_comp {X Y Z} f g := by apply F.map_injective; simp -/-- Interpret a functor that is an equivalence as an equivalence. - -See . -/ -@[simps functor] +/-- Interpret a functor that is an equivalence as an equivalence. -/ +@[simps functor, stacks 02C3] noncomputable def asEquivalence (F : C ⥤ D) [F.IsEquivalence] : C ≌ D where functor := F inverse := F.inv diff --git a/Mathlib/CategoryTheory/EssentialImage.lean b/Mathlib/CategoryTheory/EssentialImage.lean index a9a14f0935a2b..f7fd17a62ab59 100644 --- a/Mathlib/CategoryTheory/EssentialImage.lean +++ b/Mathlib/CategoryTheory/EssentialImage.lean @@ -109,10 +109,8 @@ def toEssImageCompEssentialImageInclusion (F : C ⥤ D) : F.toEssImage ⋙ F.ess FullSubcategory.lift_comp_inclusion _ _ _ /-- A functor `F : C ⥤ D` is essentially surjective if every object of `D` is in the essential -image of `F`. In other words, for every `Y : D`, there is some `X : C` with `F.obj X ≅ Y`. - -See . --/ +image of `F`. In other words, for every `Y : D`, there is some `X : C` with `F.obj X ≅ Y`. -/ +@[stacks 001C] class EssSurj (F : C ⥤ D) : Prop where /-- All the objects of the target category are in the essential image. -/ mem_essImage (Y : D) : Y ∈ F.essImage diff --git a/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean b/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean index b6f222bcedcbc..08a933d5053c9 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean @@ -65,9 +65,8 @@ a' a --φ--> b v v v R' --g--> R --f--> S ``` -such that `φ'` lifts `g ≫ f`, there exists a lift `χ` of `g` such that `φ' = χ ≫ φ`. - -See . -/ +such that `φ'` lifts `g ≫ f`, there exists a lift `χ` of `g` such that `φ' = χ ≫ φ`. -/ +@[stacks 02XK] class IsStronglyCartesian extends IsHomLift p f φ : Prop where universal_property' {a' : 𝒳} (g : p.obj a' ⟶ R) (φ' : a' ⟶ b) [IsHomLift p (g ≫ f) φ'] : ∃! χ : a' ⟶ a, IsHomLift p g χ ∧ χ ≫ φ = φ' diff --git a/Mathlib/CategoryTheory/FiberedCategory/Cocartesian.lean b/Mathlib/CategoryTheory/FiberedCategory/Cocartesian.lean index d2e2b408959c9..48278cc831bc2 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/Cocartesian.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/Cocartesian.lean @@ -60,9 +60,8 @@ a --φ--> b b' v v v R --f--> S --g--> S' ``` -such that `φ'` lifts `f ≫ g`, there exists a lift `χ` of `g` such that `φ' = χ ≫ φ`. - -See . -/ +such that `φ'` lifts `f ≫ g`, there exists a lift `χ` of `g` such that `φ' = χ ≫ φ`. -/ +@[stacks 02XK] class IsStronglyCocartesian extends IsHomLift p f φ : Prop where universal_property' {b' : 𝒳} (g : S ⟶ p.obj b') (φ' : a ⟶ b') [IsHomLift p (f ≫ g) φ'] : ∃! χ : b ⟶ b', IsHomLift p g χ ∧ φ ≫ χ = φ' diff --git a/Mathlib/CategoryTheory/Filtered/Basic.lean b/Mathlib/CategoryTheory/Filtered/Basic.lean index e356e98a41ca6..3e22decd81bac 100644 --- a/Mathlib/CategoryTheory/Filtered/Basic.lean +++ b/Mathlib/CategoryTheory/Filtered/Basic.lean @@ -76,10 +76,8 @@ class IsFilteredOrEmpty : Prop where 1. for every pair of objects there exists another object "to the right", 2. for every pair of parallel morphisms there exists a morphism to the right so the compositions are equal, and -3. there exists some object. - -See . (They also define a diagram being filtered.) --/ +3. there exists some object. -/ +@[stacks 002V "They also define a diagram being filtered."] class IsFiltered extends IsFilteredOrEmpty C : Prop where /-- a filtered category must be non empty -/ [nonempty : Nonempty C] @@ -504,10 +502,8 @@ class IsCofilteredOrEmpty : Prop where 1. for every pair of objects there exists another object "to the left", 2. for every pair of parallel morphisms there exists a morphism to the left so the compositions are equal, and -3. there exists some object. - -See . --/ +3. there exists some object. -/ +@[stacks 04AZ] class IsCofiltered extends IsCofilteredOrEmpty C : Prop where /-- a cofiltered category must be non empty -/ [nonempty : Nonempty C] diff --git a/Mathlib/CategoryTheory/FullSubcategory.lean b/Mathlib/CategoryTheory/FullSubcategory.lean index 086610388e7d0..3e85d68da2273 100644 --- a/Mathlib/CategoryTheory/FullSubcategory.lean +++ b/Mathlib/CategoryTheory/FullSubcategory.lean @@ -99,11 +99,8 @@ variable (Z : C → Prop) /-- A subtype-like structure for full subcategories. Morphisms just ignore the property. We don't use actual subtypes since the simp-normal form `↑X` of `X.val` does not work well for full -subcategories. - -See . We do not define 'strictly full' subcategories. --/ -@[ext] +subcategories. -/ +@[ext, stacks 001D "We do not define 'strictly full' subcategories."] structure FullSubcategory where /-- The category of which this is a full subcategory -/ obj : C diff --git a/Mathlib/CategoryTheory/Functor/Basic.lean b/Mathlib/CategoryTheory/Functor/Basic.lean index 8219f68054377..13a3440fd5fb9 100644 --- a/Mathlib/CategoryTheory/Functor/Basic.lean +++ b/Mathlib/CategoryTheory/Functor/Basic.lean @@ -30,10 +30,8 @@ section To apply a functor `F` to an object use `F.obj X`, and to a morphism use `F.map f`. The axiom `map_id` expresses preservation of identities, and -`map_comp` expresses functoriality. - -See . --/ +`map_comp` expresses functoriality. -/ +@[stacks 001B] structure Functor (C : Type u₁) [Category.{v₁} C] (D : Type u₂) [Category.{v₂} D] extends Prefunctor C D : Type max v₁ v₂ u₁ u₂ where /-- A functor preserves identity morphisms. -/ diff --git a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean index c550e1890088a..98607af7c86c4 100644 --- a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean +++ b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean @@ -36,17 +36,13 @@ variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] namespace Functor -/-- A functor `F : C ⥤ D` is full if for each `X Y : C`, `F.map` is surjective. - -See . --/ +/-- A functor `F : C ⥤ D` is full if for each `X Y : C`, `F.map` is surjective. -/ +@[stacks 001C] class Full (F : C ⥤ D) : Prop where map_surjective {X Y : C} : Function.Surjective (F.map (X := X) (Y := Y)) -/-- A functor `F : C ⥤ D` is faithful if for each `X Y : C`, `F.map` is injective. - -See . --/ +/-- A functor `F : C ⥤ D` is faithful if for each `X Y : C`, `F.map` is injective. -/ +@[stacks 001C] class Faithful (F : C ⥤ D) : Prop where /-- `F.map` is injective for each `X Y : C`. -/ map_injective : ∀ {X Y : C}, Function.Injective (F.map : (X ⟶ Y) → (F.obj X ⟶ F.obj Y)) := by diff --git a/Mathlib/CategoryTheory/IsConnected.lean b/Mathlib/CategoryTheory/IsConnected.lean index a2467f07e290a..e1ff3d18f906e 100644 --- a/Mathlib/CategoryTheory/IsConnected.lean +++ b/Mathlib/CategoryTheory/IsConnected.lean @@ -67,10 +67,8 @@ NB. Some authors include the empty category as connected, we do not. We instead are interested in categories with exactly one 'connected component'. -This allows us to show that the functor X ⨯ - preserves connected limits. - -See --/ +This allows us to show that the functor X ⨯ - preserves connected limits. -/ +@[stacks 002S] class IsConnected (J : Type u₁) [Category.{v₁} J] extends IsPreconnected J : Prop where [is_nonempty : Nonempty J] diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean index 6e0dd598bc818..781198c903a31 100644 --- a/Mathlib/CategoryTheory/Iso.lean +++ b/Mathlib/CategoryTheory/Iso.lean @@ -42,10 +42,8 @@ open Category The inverse morphism is bundled. See also `CategoryTheory.Core` for the category with the same objects and isomorphisms playing -the role of morphisms. - -See . --/ +the role of morphisms. -/ +@[stacks 0017] structure Iso {C : Type u} [Category.{v} C] (X Y : C) where /-- The forward direction of an isomorphism. -/ hom : X ⟶ Y diff --git a/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean b/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean index 84ff0c9c14b61..43c2773df6cc1 100644 --- a/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean +++ b/Mathlib/CategoryTheory/Limits/Constructions/LimitsOfProductsAndEqualizers.lean @@ -123,19 +123,15 @@ instance limitSubobjectProduct_mono [HasLimitsOfSize.{w, w} C] (F : J ⥤ C) : Mono (limitSubobjectProduct F) := mono_comp _ _ -/-- Any category with products and equalizers has all limits. - -See . --/ +/-- Any category with products and equalizers has all limits. -/ +@[stacks 002N] theorem has_limits_of_hasEqualizers_and_products [HasProducts.{w} C] [HasEqualizers C] : HasLimitsOfSize.{w, w} C := { has_limits_of_shape := fun _ _ => { has_limit := fun F => hasLimit_of_equalizer_and_product F } } -/-- Any category with finite products and equalizers has all finite limits. - -See . --/ +/-- Any category with finite products and equalizers has all finite limits. -/ +@[stacks 002O] theorem hasFiniteLimits_of_hasEqualizers_and_finite_products [HasFiniteProducts C] [HasEqualizers C] : HasFiniteLimits C where out _ := { has_limit := fun F => hasLimit_of_equalizer_and_product F } @@ -343,19 +339,15 @@ instance colimitQuotientCoproduct_epi [HasColimitsOfSize.{w, w} C] (F : J ⥤ C) Epi (colimitQuotientCoproduct F) := epi_comp _ _ -/-- Any category with coproducts and coequalizers has all colimits. - -See . --/ +/-- Any category with coproducts and coequalizers has all colimits. -/ +@[stacks 002P] theorem has_colimits_of_hasCoequalizers_and_coproducts [HasCoproducts.{w} C] [HasCoequalizers C] : HasColimitsOfSize.{w, w} C where has_colimits_of_shape := fun _ _ => { has_colimit := fun F => hasColimit_of_coequalizer_and_coproduct F } -/-- Any category with finite coproducts and coequalizers has all finite colimits. - -See . --/ +/-- Any category with finite coproducts and coequalizers has all finite colimits. -/ +@[stacks 002Q] theorem hasFiniteColimits_of_hasCoequalizers_and_finite_coproducts [HasFiniteCoproducts C] [HasCoequalizers C] : HasFiniteColimits C where out _ := { has_colimit := fun F => hasColimit_of_coequalizer_and_coproduct F } diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index f019212af5a48..93331eeffeb40 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -82,10 +82,8 @@ variable {D : Type u₂} [Category.{v₂} D] /-- A functor `F : C ⥤ D` is final if for every `d : D`, the comma category of morphisms `d ⟶ F.obj c` -is connected. - -See --/ +is connected. -/ +@[stacks 04E6] class Final (F : C ⥤ D) : Prop where out (d : D) : IsConnected (StructuredArrow d F) diff --git a/Mathlib/CategoryTheory/Limits/IsLimit.lean b/Mathlib/CategoryTheory/Limits/IsLimit.lean index 871e20809f175..aead84cff4f8a 100644 --- a/Mathlib/CategoryTheory/Limits/IsLimit.lean +++ b/Mathlib/CategoryTheory/Limits/IsLimit.lean @@ -46,10 +46,8 @@ variable {C : Type u₃} [Category.{v₃} C] variable {F : J ⥤ C} /-- A cone `t` on `F` is a limit cone if each cone on `F` admits a unique -cone morphism to `t`. - -See . - -/ +cone morphism to `t`. -/ +@[stacks 002E] structure IsLimit (t : Cone F) where /-- There is a morphism from any cone point to `t.pt` -/ lift : ∀ s : Cone F, s.pt ⟶ t.pt @@ -495,10 +493,8 @@ end end IsLimit /-- A cocone `t` on `F` is a colimit cocone if each cocone on `F` admits a unique -cocone morphism from `t`. - -See . --/ +cocone morphism from `t`. -/ +@[stacks 002F] structure IsColimit (t : Cocone F) where /-- `t.pt` maps to all other cocone covertices -/ desc : ∀ s : Cocone F, t.pt ⟶ s.pt diff --git a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean index 02ed48104a196..3ee93b6a24866 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean @@ -837,17 +837,13 @@ end CoprodLemmas variable (C) -/-- `HasBinaryProducts` represents a choice of product for every pair of objects. - -See . --/ +/-- `HasBinaryProducts` represents a choice of product for every pair of objects. -/ +@[stacks 001T] abbrev HasBinaryProducts := HasLimitsOfShape (Discrete WalkingPair) C -/-- `HasBinaryCoproducts` represents a choice of coproduct for every pair of objects. - -See . --/ +/-- `HasBinaryCoproducts` represents a choice of coproduct for every pair of objects. -/ +@[stacks 04AP] abbrev HasBinaryCoproducts := HasColimitsOfShape (Discrete WalkingPair) C diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean index 7a97bde56f6a0..4283ca314dade 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean @@ -502,10 +502,8 @@ end PushoutSymmetry variable (C) -/-- `HasPullbacks` represents a choice of pullback for every pair of morphisms - -See --/ +/-- `HasPullbacks` represents a choice of pullback for every pair of morphisms. -/ +@[stacks 001W] abbrev HasPullbacks := HasLimitsOfShape WalkingCospan C diff --git a/Mathlib/CategoryTheory/Limits/Types.lean b/Mathlib/CategoryTheory/Limits/Types.lean index 396fd6658d545..462571b6714a7 100644 --- a/Mathlib/CategoryTheory/Limits/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Types.lean @@ -192,10 +192,8 @@ instance hasLimitsOfShape [Small.{u} J] : HasLimitsOfShape J (Type u) where /-- The category of types has all limits. -More specifically, when `UnivLE.{v, u}`, the category `Type u` has all `v`-small limits. - -See . --/ +More specifically, when `UnivLE.{v, u}`, the category `Type u` has all `v`-small limits. -/ +@[stacks 002U] instance (priority := 1300) hasLimitsOfSize [UnivLE.{v, u}] : HasLimitsOfSize.{w, v} (Type u) where has_limits_of_shape _ := { } @@ -484,10 +482,8 @@ instance hasColimit [Small.{u} J] (F : J ⥤ Type u) : HasColimit F := instance hasColimitsOfShape [Small.{u} J] : HasColimitsOfShape J (Type u) where -/-- The category of types has all colimits. - -See . --/ +/-- The category of types has all colimits. -/ +@[stacks 002U] instance (priority := 1300) hasColimitsOfSize [UnivLE.{v, u}] : HasColimitsOfSize.{w, v} (Type u) where diff --git a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean index 4f1f7e9e08cb8..77c4c2e4eb1e1 100644 --- a/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Braided/Basic.lean @@ -342,10 +342,8 @@ theorem braiding_inv_tensorUnit_right (X : C) : (β_ X (𝟙_ C)).inv = (λ_ X). end /-- -A symmetric monoidal category is a braided monoidal category for which the braiding is symmetric. - -See . --/ +A symmetric monoidal category is a braided monoidal category for which the braiding is symmetric. -/ +@[stacks 0FFW] class SymmetricCategory (C : Type u) [Category.{v} C] [MonoidalCategory.{v} C] extends BraidedCategory.{v} C where -- braiding symmetric: diff --git a/Mathlib/CategoryTheory/Monoidal/Category.lean b/Mathlib/CategoryTheory/Monoidal/Category.lean index f91baa59cfa43..2451bdd366d10 100644 --- a/Mathlib/CategoryTheory/Monoidal/Category.lean +++ b/Mathlib/CategoryTheory/Monoidal/Category.lean @@ -149,10 +149,8 @@ In a monoidal category, we can take the tensor product of objects, `X ⊗ Y` and Tensor product does not need to be strictly associative on objects, but there is a specified associator, `α_ X Y Z : (X ⊗ Y) ⊗ Z ≅ X ⊗ (Y ⊗ Z)`. There is a tensor unit `𝟙_ C`, with specified left and right unitor isomorphisms `λ_ X : 𝟙_ C ⊗ X ≅ X` and `ρ_ X : X ⊗ 𝟙_ C ≅ X`. -These associators and unitors satisfy the pentagon and triangle equations. - -See . --/ +These associators and unitors satisfy the pentagon and triangle equations. -/ +@[stacks 0FFK] -- Porting note: The Mathport did not translate the temporary notation class MonoidalCategory (C : Type u) [𝒞 : Category.{v} C] extends MonoidalCategoryStruct C where tensorHom_def {X₁ Y₁ X₂ Y₂ : C} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) : diff --git a/Mathlib/CategoryTheory/Noetherian.lean b/Mathlib/CategoryTheory/Noetherian.lean index 6b7a78e563ca6..8c80a261f546d 100644 --- a/Mathlib/CategoryTheory/Noetherian.lean +++ b/Mathlib/CategoryTheory/Noetherian.lean @@ -30,10 +30,8 @@ open CategoryTheory.Limits variable {C : Type*} [Category C] /-- A noetherian object is an object -which does not have infinite increasing sequences of subobjects. - -See https://stacks.math.columbia.edu/tag/0FCG --/ +which does not have infinite increasing sequences of subobjects. -/ +@[stacks 0FCG] class NoetherianObject (X : C) : Prop where subobject_gt_wellFounded' : WellFounded ((· > ·) : Subobject X → Subobject X → Prop) @@ -42,10 +40,8 @@ lemma NoetherianObject.subobject_gt_wellFounded (X : C) [NoetherianObject X] : NoetherianObject.subobject_gt_wellFounded' /-- An artinian object is an object -which does not have infinite decreasing sequences of subobjects. - -See https://stacks.math.columbia.edu/tag/0FCF --/ +which does not have infinite decreasing sequences of subobjects. -/ +@[stacks 0FCF] class ArtinianObject (X : C) : Prop where subobject_lt_wellFounded' : WellFounded ((· < ·) : Subobject X → Subobject X → Prop) diff --git a/Mathlib/CategoryTheory/Opposites.lean b/Mathlib/CategoryTheory/Opposites.lean index 914d995a8d4cd..8a6a9972931b0 100644 --- a/Mathlib/CategoryTheory/Opposites.lean +++ b/Mathlib/CategoryTheory/Opposites.lean @@ -60,10 +60,8 @@ namespace CategoryTheory variable [Category.{v₁} C] -/-- The opposite category. - -See . --/ +/-- The opposite category. -/ +@[stacks 001M] instance Category.opposite : Category.{v₁} Cᵒᵖ where comp f g := (g.unop ≫ f.unop).op id X := (𝟙 (unop X)).op diff --git a/Mathlib/CategoryTheory/Products/Basic.lean b/Mathlib/CategoryTheory/Products/Basic.lean index 0894a2421f869..c32a60a69ef2c 100644 --- a/Mathlib/CategoryTheory/Products/Basic.lean +++ b/Mathlib/CategoryTheory/Products/Basic.lean @@ -35,11 +35,8 @@ section variable (C : Type u₁) [Category.{v₁} C] (D : Type u₂) [Category.{v₂} D] -- the generates simp lemmas like `id_fst` and `comp_snd` -/-- `prod C D` gives the cartesian product of two categories. - -See . --/ -@[simps (config := { notRecursive := [] }) Hom id_fst id_snd comp_fst comp_snd] +/-- `prod C D` gives the cartesian product of two categories. -/ +@[simps (config := { notRecursive := [] }) Hom id_fst id_snd comp_fst comp_snd, stacks 001K] instance prod : Category.{max v₁ v₂} (C × D) where Hom X Y := (X.1 ⟶ Y.1) × (X.2 ⟶ Y.2) id X := ⟨𝟙 X.1, 𝟙 X.2⟩ diff --git a/Mathlib/CategoryTheory/SingleObj.lean b/Mathlib/CategoryTheory/SingleObj.lean index 48fed64ab7d7d..b4844a38d181a 100644 --- a/Mathlib/CategoryTheory/SingleObj.lean +++ b/Mathlib/CategoryTheory/SingleObj.lean @@ -74,10 +74,8 @@ theorem comp_as_mul {x y z : SingleObj M} (f : x ⟶ y) (g : y ⟶ z) : f ≫ g /-- If `M` is finite and in universe zero, then `SingleObj M` is a `FinCategory`. -/ instance finCategoryOfFintype (M : Type) [Fintype M] [Monoid M] : FinCategory (SingleObj M) where -/-- Groupoid structure on `SingleObj M`. - -See . --/ +/-- Groupoid structure on `SingleObj M`. -/ +@[stacks 0019] instance groupoid : Groupoid (SingleObj G) where inv x := x⁻¹ inv_comp := mul_inv_cancel @@ -104,12 +102,8 @@ theorem toEnd_def (x : M) : toEnd M x = x := variable (N : Type v) [Monoid N] /-- There is a 1-1 correspondence between monoid homomorphisms `M → N` and functors between the - corresponding single-object categories. It means that `SingleObj` is a fully faithful - functor. - -See -- -although we do not characterize when the functor is full or faithful. --/ +corresponding single-object categories. It means that `SingleObj` is a fully faithful functor. -/ +@[stacks 001F "We do not characterize when the functor is full or faithful."] def mapHom : (M →* N) ≃ SingleObj M ⥤ SingleObj N where toFun f := { obj := id diff --git a/Mathlib/CategoryTheory/Sites/Canonical.lean b/Mathlib/CategoryTheory/Sites/Canonical.lean index 1c9d6de317649..8dd61b381382a 100644 --- a/Mathlib/CategoryTheory/Sites/Canonical.lean +++ b/Mathlib/CategoryTheory/Sites/Canonical.lean @@ -188,10 +188,8 @@ theorem le_finestTopology (Ps : Set (Cᵒᵖ ⥤ Type v)) (J : GrothendieckTopol exact hJ P hP (S.pullback f) (J.pullback_stable f hS) /-- The `canonicalTopology` on a category is the finest (largest) topology for which every -representable presheaf is a sheaf. - -See --/ +representable presheaf is a sheaf. -/ +@[stacks 00ZA] def canonicalTopology (C : Type u) [Category.{v} C] : GrothendieckTopology C := finestTopology (Set.range yoneda.obj) diff --git a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean index 29b141d4386aa..406251e3f3f1b 100644 --- a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean +++ b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean @@ -224,9 +224,8 @@ theorem compatible_iff (x : FirstObj P R) : rw [Types.limit_ext_iff'] at t simpa [firstMap, secondMap] using t ⟨⟨⟨Y, f, hf⟩, Z, g, hg⟩⟩ -/-- `P` is a sheaf for `R`, iff the fork given by `w` is an equalizer. -See . --/ +/-- `P` is a sheaf for `R`, iff the fork given by `w` is an equalizer. -/ +@[stacks 00VM] theorem sheaf_condition : R.IsSheafFor P ↔ Nonempty (IsLimit (Fork.ofι _ (w P R))) := by rw [Types.type_equalizer_iff_unique, ← Equiv.forall_congr_right (firstObjEqFamily P R).toEquiv.symm] @@ -322,10 +321,8 @@ theorem compatible_iff (x : FirstObj P X) : (Arrows.Compatible P π ((Types.prod apply_fun Pi.π (fun (ij : I × I) ↦ P.obj (op (pullback (π ij.1) (π ij.2)))) ⟨i, j⟩ at t simpa [firstMap, secondMap] using t -/-- -`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer. -See . --/ +/-- `P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer. -/ +@[stacks 00VM] theorem sheaf_condition : (Presieve.ofArrows X π).IsSheafFor P ↔ Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff] diff --git a/Mathlib/CategoryTheory/Sites/Grothendieck.lean b/Mathlib/CategoryTheory/Sites/Grothendieck.lean index cfb68cc8d4ea9..816a9f82f51ce 100644 --- a/Mathlib/CategoryTheory/Sites/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Sites/Grothendieck.lean @@ -66,9 +66,8 @@ three axioms: A sieve `S` on `X` is referred to as `J`-covering, (or just covering), if `S ∈ J X`. -See , or [nlab], or [MM92][] Chapter III, Section 2, -Definition 1. --/ +See also [nlab] or [MM92] Chapter III, Section 2, Definition 1. -/ +@[stacks 00Z4] structure GrothendieckTopology where /-- A Grothendieck topology on `C` consists of a set of sieves for each object `X`, which satisfy some axioms. -/ @@ -132,9 +131,8 @@ theorem covering_of_eq_top : S = ⊤ → S ∈ J X := fun h => h.symm ▸ J.top_ /-- If `S` is a subset of `R`, and `S` is covering, then `R` is covering as well. -See (2), or discussion after [MM92] Chapter III, -Section 2, Definition 1. --/ +See also discussion after [MM92] Chapter III, Section 2, Definition 1. -/ +@[stacks 00Z5 "(2)"] theorem superset_covering (Hss : S ≤ R) (sjx : S ∈ J X) : R ∈ J X := by apply J.transitive sjx R fun Y f hf => _ intros Y f hf @@ -144,9 +142,8 @@ theorem superset_covering (Hss : S ≤ R) (sjx : S ∈ J X) : R ∈ J X := by /-- The intersection of two covering sieves is covering. -See (1), or [MM92] Chapter III, -Section 2, Definition 1 (iv). --/ +See also [MM92] Chapter III, Section 2, Definition 1 (iv). -/ +@[stacks 00Z5 "(1)"] theorem intersection_covering (rj : R ∈ J X) (sj : S ∈ J X) : R ⊓ S ∈ J X := by apply J.transitive rj _ fun Y f Hf => _ intros Y f hf @@ -231,21 +228,21 @@ variable {C} theorem trivial_covering : S ∈ trivial C X ↔ S = ⊤ := Set.mem_singleton_iff -/-- See -/ +@[stacks 00Z6] instance instLEGrothendieckTopology : LE (GrothendieckTopology C) where le J₁ J₂ := (J₁ : ∀ X : C, Set (Sieve X)) ≤ (J₂ : ∀ X : C, Set (Sieve X)) theorem le_def {J₁ J₂ : GrothendieckTopology C} : J₁ ≤ J₂ ↔ (J₁ : ∀ X : C, Set (Sieve X)) ≤ J₂ := Iff.rfl -/-- See -/ +@[stacks 00Z6] instance : PartialOrder (GrothendieckTopology C) := { instLEGrothendieckTopology with le_refl := fun _ => le_def.mpr le_rfl le_trans := fun _ _ _ h₁₂ h₂₃ => le_def.mpr (le_trans h₁₂ h₂₃) le_antisymm := fun _ _ h₁₂ h₂₁ => GrothendieckTopology.ext (le_antisymm h₁₂ h₂₁) } -/-- See -/ +@[stacks 00Z7] instance : InfSet (GrothendieckTopology C) where sInf T := { sieves := sInf (sieves '' T) @@ -265,7 +262,7 @@ lemma mem_sInf (s : Set (GrothendieckTopology C)) {X : C} (S : Sieve X) : show S ∈ sInf (sieves '' s) X ↔ _ simp -/-- See -/ +@[stacks 00Z7] theorem isGLB_sInf (s : Set (GrothendieckTopology C)) : IsGLB s (sInf s) := by refine @IsGLB.of_image _ _ _ _ sieves ?_ _ _ ?_ · #adaptation_note diff --git a/Mathlib/CategoryTheory/Sites/Pretopology.lean b/Mathlib/CategoryTheory/Sites/Pretopology.lean index bde2d0fb7bd77..6285e9b9a6bde 100644 --- a/Mathlib/CategoryTheory/Sites/Pretopology.lean +++ b/Mathlib/CategoryTheory/Sites/Pretopology.lean @@ -101,8 +101,9 @@ instance : Inhabited (Pretopology C) := /-- A pretopology `K` can be completed to a Grothendieck topology `J` by declaring a sieve to be `J`-covering if it contains a family in `K`. -See , or [MM92] Chapter III, Section 2, Equation (2). +See also [MM92] Chapter III, Section 2, Equation (2). -/ +@[stacks 00ZC] def toGrothendieck (K : Pretopology C) : GrothendieckTopology C where sieves X S := ∃ R ∈ K X, R ≤ (S : Presieve _) top_mem' _ := ⟨Presieve.singleton (𝟙 _), K.has_isos _, fun _ _ _ => ⟨⟩⟩ @@ -162,10 +163,8 @@ lemma mem_ofGrothendieck (t : GrothendieckTopology C) {X : C} (S : Presieve X) : /-- The trivial pretopology, in which the coverings are exactly singleton isomorphisms. This topology is -also known as the indiscrete, coarse, or chaotic topology. - -See --/ +also known as the indiscrete, coarse, or chaotic topology. -/ +@[stacks 07GE] def trivial : Pretopology C where coverings X S := ∃ (Y : _) (f : Y ⟶ X) (_ : IsIso f), S = Presieve.singleton f has_isos _ _ _ i := ⟨_, _, i, rfl⟩ diff --git a/Mathlib/CategoryTheory/Triangulated/Basic.lean b/Mathlib/CategoryTheory/Triangulated/Basic.lean index b8e3b05949917..588667615973e 100644 --- a/Mathlib/CategoryTheory/Triangulated/Basic.lean +++ b/Mathlib/CategoryTheory/Triangulated/Basic.lean @@ -34,9 +34,8 @@ We work in a category `C` equipped with a shift. variable (C : Type u) [Category.{v} C] [HasShift C ℤ] /-- A triangle in `C` is a sextuple `(X,Y,Z,f,g,h)` where `X,Y,Z` are objects of `C`, -and `f : X ⟶ Y`, `g : Y ⟶ Z`, `h : Z ⟶ X⟦1⟧` are morphisms in `C`. -See . --/ +and `f : X ⟶ Y`, `g : Y ⟶ Z`, `h : Z ⟶ X⟦1⟧` are morphisms in `C`. -/ +@[stacks 0144] structure Triangle where mk' :: /-- the first object of a triangle -/ obj₁ : C @@ -95,9 +94,8 @@ In other words, we have a commutative diagram: X' ───> Y' ───> Z' ───> X'⟦1⟧ f' g' h' ``` -See . -/ -@[ext] +@[ext, stacks 0144] structure TriangleMorphism (T₁ : Triangle C) (T₂ : Triangle C) where /-- the first morphism in a triangle morphism -/ hom₁ : T₁.obj₁ ⟶ T₂.obj₁ diff --git a/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean b/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean index bdaf65cf13c90..553fd66efc6ca 100644 --- a/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean +++ b/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean @@ -56,9 +56,8 @@ relative to that shift is called pretriangulated if the following hold: ``` where the left square commutes, and whose rows are distinguished triangles, there exists a morphism `c : Z ⟶ Z'` such that `(a,b,c)` is a triangle morphism. - -See -/ +@[stacks 0145] class Pretriangulated [∀ n : ℤ, Functor.Additive (shiftFunctor C n)] where /-- a class of triangle which are called `distinguished` -/ distinguishedTriangles : Set (Triangle C) @@ -115,10 +114,8 @@ theorem inv_rot_of_distTriang (T : Triangle C) (H : T ∈ distTriang C) : f g h X ───> Y ───> Z ───> X⟦1⟧ ``` -the composition `f ≫ g = 0`. -See --/ -@[reassoc] +the composition `f ≫ g = 0`. -/ +@[reassoc, stacks 0146] theorem comp_distTriang_mor_zero₁₂ (T) (H : T ∈ (distTriang C)) : T.mor₁ ≫ T.mor₂ = 0 := by obtain ⟨c, hc⟩ := complete_distinguished_triangle_morphism _ _ (contractible_distinguished T.obj₁) H (𝟙 T.obj₁) @@ -130,10 +127,8 @@ theorem comp_distTriang_mor_zero₁₂ (T) (H : T ∈ (distTriang C)) : T.mor₁ f g h X ───> Y ───> Z ───> X⟦1⟧ ``` -the composition `g ≫ h = 0`. -See --/ -@[reassoc] +the composition `g ≫ h = 0`. -/ +@[reassoc, stacks 0146] theorem comp_distTriang_mor_zero₂₃ (T : Triangle C) (H : T ∈ distTriang C) : T.mor₂ ≫ T.mor₃ = 0 := comp_distTriang_mor_zero₁₂ T.rotate (rot_of_distTriang T H) @@ -143,10 +138,8 @@ theorem comp_distTriang_mor_zero₂₃ (T : Triangle C) (H : T ∈ distTriang C) f g h X ───> Y ───> Z ───> X⟦1⟧ ``` -the composition `h ≫ f⟦1⟧ = 0`. -See --/ -@[reassoc] +the composition `h ≫ f⟦1⟧ = 0`. -/ +@[reassoc, stacks 0146] theorem comp_distTriang_mor_zero₃₁ (T : Triangle C) (H : T ∈ distTriang C) : T.mor₃ ≫ T.mor₁⟦1⟧' = 0 := by have H₂ := rot_of_distTriang T.rotate (rot_of_distTriang T H) diff --git a/Mathlib/CategoryTheory/Triangulated/Triangulated.lean b/Mathlib/CategoryTheory/Triangulated/Triangulated.lean index d626b0eb72e4d..bb65bf364d393 100644 --- a/Mathlib/CategoryTheory/Triangulated/Triangulated.lean +++ b/Mathlib/CategoryTheory/Triangulated/Triangulated.lean @@ -32,8 +32,8 @@ variable {C} -- Porting note: see https://github.com/leanprover/lean4/issues/2188 set_option genInjectivity false in -/-- An octahedron is a type of datum whose existence is asserted by -the octahedron axiom (TR 4), see https://stacks.math.columbia.edu/tag/05QK -/ +/-- An octahedron is a type of datum whose existence is asserted by the octahedron axiom (TR 4). -/ +@[stacks 05QK] structure Octahedron {X₁ X₂ X₃ Z₁₂ Z₂₃ Z₁₃ : C} {u₁₂ : X₁ ⟶ X₂} {u₂₃ : X₂ ⟶ X₃} {u₁₃ : X₁ ⟶ X₃} (comm : u₁₂ ≫ u₂₃ = u₁₃) @@ -160,7 +160,8 @@ end Triangulated open Triangulated /-- A triangulated category is a pretriangulated category which satisfies -the octahedron axiom (TR 4), see https://stacks.math.columbia.edu/tag/05QK -/ +the octahedron axiom (TR 4). -/ +@[stacks 05QK] class IsTriangulated : Prop where /-- the octahedron axiom (TR 4) -/ octahedron_axiom : diff --git a/Mathlib/CategoryTheory/Types.lean b/Mathlib/CategoryTheory/Types.lean index 12a318305da27..9eeb5f3d051ae 100644 --- a/Mathlib/CategoryTheory/Types.lean +++ b/Mathlib/CategoryTheory/Types.lean @@ -224,10 +224,8 @@ def homOfElement {X : Type u} (x : X) : PUnit ⟶ X := fun _ => x theorem homOfElement_eq_iff {X : Type u} (x y : X) : homOfElement x = homOfElement y ↔ x = y := ⟨fun H => congr_fun H PUnit.unit, by aesop⟩ -/-- A morphism in `Type` is a monomorphism if and only if it is injective. - -See . --/ +/-- A morphism in `Type` is a monomorphism if and only if it is injective. -/ +@[stacks 003C] theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by constructor · intro H x x' h @@ -238,10 +236,8 @@ theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.In theorem injective_of_mono {X Y : Type u} (f : X ⟶ Y) [hf : Mono f] : Function.Injective f := (mono_iff_injective f).1 hf -/-- A morphism in `Type` is an epimorphism if and only if it is surjective. - -See . --/ +/-- A morphism in `Type` is an epimorphism if and only if it is surjective. -/ +@[stacks 003C] theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by constructor · rintro ⟨H⟩ diff --git a/Mathlib/CategoryTheory/Yoneda.lean b/Mathlib/CategoryTheory/Yoneda.lean index e362440ade3cf..70282b07cb005 100644 --- a/Mathlib/CategoryTheory/Yoneda.lean +++ b/Mathlib/CategoryTheory/Yoneda.lean @@ -29,11 +29,8 @@ universe v v₁ v₂ u₁ u₂ -- morphism levels before object levels. See note [CategoryTheory universes]. variable {C : Type u₁} [Category.{v₁} C] -/-- The Yoneda embedding, as a functor from `C` into presheaves on `C`. - -See . --/ -@[simps] +/-- The Yoneda embedding, as a functor from `C` into presheaves on `C`. -/ +@[simps, stacks 001O] def yoneda : C ⥤ Cᵒᵖ ⥤ Type v₁ where obj X := { obj := fun Y => unop Y ⟶ X @@ -70,17 +67,13 @@ def fullyFaithful : (yoneda (C := C)).FullyFaithful where lemma fullyFaithful_preimage {X Y : C} (f : yoneda.obj X ⟶ yoneda.obj Y) : fullyFaithful.preimage f = f.app (op X) (𝟙 X) := rfl -/-- The Yoneda embedding is full. - -See . --/ +/-- The Yoneda embedding is full. -/ +@[stacks 001P] instance yoneda_full : (yoneda : C ⥤ Cᵒᵖ ⥤ Type v₁).Full := fullyFaithful.full -/-- The Yoneda embedding is faithful. - -See . --/ +/-- The Yoneda embedding is faithful. -/ +@[stacks 001P] instance yoneda_faithful : (yoneda : C ⥤ Cᵒᵖ ⥤ Type v₁).Faithful := fullyFaithful.faithful @@ -254,10 +247,8 @@ def CorepresentableBy.toIso {F : C ⥤ Type v₁} {X : C} (e : F.Corepresentable /-- A functor `F : Cᵒᵖ ⥤ Type v` is representable if there is an object `Y` with a structure `F.RepresentableBy Y`, i.e. there is a natural bijection `(X ⟶ Y) ≃ F.obj (op X)`, -which may also be rephrased as a natural isomorphism `yoneda.obj X ≅ F` when `Category.{v} C`. - -See . --/ +which may also be rephrased as a natural isomorphism `yoneda.obj X ≅ F` when `Category.{v} C`. -/ +@[stacks 001Q] class IsRepresentable (F : Cᵒᵖ ⥤ Type v) : Prop where has_representation : ∃ (Y : C), Nonempty (F.RepresentableBy Y) @@ -277,9 +268,8 @@ instance {X : C} : IsRepresentable (yoneda.obj X) := IsRepresentable.mk' (Iso.refl _) /-- A functor `F : C ⥤ Type v₁` is corepresentable if there is object `X` so `F ≅ coyoneda.obj X`. - -See . -/ +@[stacks 001Q] class IsCorepresentable (F : C ⥤ Type v) : Prop where has_corepresentation : ∃ (X : C), Nonempty (F.CorepresentableBy X) @@ -527,10 +517,8 @@ def yonedaCompUliftFunctorEquiv (F : Cᵒᵖ ⥤ Type max v₁ w) (X : C) : /-- The Yoneda lemma asserts that the Yoneda pairing `(X : Cᵒᵖ, F : Cᵒᵖ ⥤ Type) ↦ (yoneda.obj (unop X) ⟶ F)` -is naturally isomorphic to the evaluation `(X, F) ↦ F.obj X`. - -See . --/ +is naturally isomorphic to the evaluation `(X, F) ↦ F.obj X`. -/ +@[stacks 001P] def yonedaLemma : yonedaPairing C ≅ yonedaEvaluation C := NatIso.ofComponents (fun _ ↦ Equiv.toIso (yonedaEquiv.trans Equiv.ulift.symm)) @@ -709,10 +697,8 @@ def coyonedaCompUliftFunctorEquiv (F : C ⥤ Type max v₁ w) (X : Cᵒᵖ) : /-- The Coyoneda lemma asserts that the Coyoneda pairing `(X : C, F : C ⥤ Type) ↦ (coyoneda.obj X ⟶ F)` -is naturally isomorphic to the evaluation `(X, F) ↦ F.obj X`. - -See . --/ +is naturally isomorphic to the evaluation `(X, F) ↦ F.obj X`. -/ +@[stacks 001P] def coyonedaLemma : coyonedaPairing C ≅ coyonedaEvaluation C := NatIso.ofComponents (fun _ ↦ Equiv.toIso (coyonedaEquiv.trans Equiv.ulift.symm)) diff --git a/Mathlib/RingTheory/Etale/Basic.lean b/Mathlib/RingTheory/Etale/Basic.lean index 127e6a5b37aeb..1f11834fdfbaa 100644 --- a/Mathlib/RingTheory/Etale/Basic.lean +++ b/Mathlib/RingTheory/Etale/Basic.lean @@ -38,10 +38,8 @@ variable (R : Type u) [CommRing R] variable (A : Type u) [CommRing A] [Algebra R A] /-- An `R` algebra `A` is formally étale if for every `R`-algebra, every square-zero ideal -`I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists exactly one lift `A →ₐ[R] B`. - -See -/ -@[mk_iff] +`I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists exactly one lift `A →ₐ[R] B`. -/ +@[mk_iff, stacks 00UQ] class FormallyEtale : Prop where comp_bijective : ∀ ⦃B : Type u⦄ [CommRing B], diff --git a/Mathlib/RingTheory/Smooth/Basic.lean b/Mathlib/RingTheory/Smooth/Basic.lean index 0d42a4a3c9af6..76b6df39845a5 100644 --- a/Mathlib/RingTheory/Smooth/Basic.lean +++ b/Mathlib/RingTheory/Smooth/Basic.lean @@ -41,11 +41,8 @@ variable (R : Type u) [CommSemiring R] variable (A : Type u) [Semiring A] [Algebra R A] /-- An `R` algebra `A` is formally smooth if for every `R`-algebra, every square-zero ideal -`I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists at least one lift `A →ₐ[R] B`. - -See . --/ -@[mk_iff] +`I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists at least one lift `A →ₐ[R] B`. -/ +@[mk_iff, stacks 00TI] class FormallySmooth : Prop where comp_surjective : ∀ ⦃B : Type u⦄ [CommRing B], diff --git a/Mathlib/RingTheory/Unramified/Basic.lean b/Mathlib/RingTheory/Unramified/Basic.lean index 9e91002b6692d..f24642133de7f 100644 --- a/Mathlib/RingTheory/Unramified/Basic.lean +++ b/Mathlib/RingTheory/Unramified/Basic.lean @@ -46,10 +46,8 @@ An `R`-algebra `A` is formally unramified if `Ω[A⁄R]` is trivial. This is equivalent to "for every `R`-algebra, every square-zero ideal `I : Ideal B` and `f : A →ₐ[R] B ⧸ I`, there exists at most one lift `A →ₐ[R] B`". -See `Algebra.FormallyUnramified.iff_comp_injective`. - -See . -/ -@[mk_iff] +See `Algebra.FormallyUnramified.iff_comp_injective`. -/ +@[mk_iff, stacks 00UM] class FormallyUnramified : Prop where subsingleton_kaehlerDifferential : Subsingleton (Ω[A⁄R]) diff --git a/Mathlib/Topology/Category/Profinite/Basic.lean b/Mathlib/Topology/Category/Profinite/Basic.lean index 9bbf16eba695d..e0da94050bcc9 100644 --- a/Mathlib/Topology/Category/Profinite/Basic.lean +++ b/Mathlib/Topology/Category/Profinite/Basic.lean @@ -96,9 +96,8 @@ section Profinite -- unhelpfully defines a function `CompHaus.{max u₁ u₂} → Profinite.{max u₁ u₂}`. /-- (Implementation) The object part of the connected_components functor from compact Hausdorff spaces -to Profinite spaces, given by quotienting a space by its connected components. -See: https://stacks.math.columbia.edu/tag/0900 --/ +to Profinite spaces, given by quotienting a space by its connected components. -/ +@[stacks 0900] def CompHaus.toProfiniteObj (X : CompHaus.{u}) : Profinite.{u} where toTop := TopCat.of (ConnectedComponents X) is_compact := Quotient.compactSpace diff --git a/Mathlib/Topology/Sheaves/Forget.lean b/Mathlib/Topology/Sheaves/Forget.lean index f32fb2bb507d4..458a5633cd652 100644 --- a/Mathlib/Topology/Sheaves/Forget.lean +++ b/Mathlib/Topology/Sheaves/Forget.lean @@ -41,11 +41,8 @@ The important special case is when that preserves limits and reflects isomorphisms. Then to check the sheaf condition it suffices to check it on the underlying sheaf of types. -Another useful example is the forgetful functor `TopCommRingCat ⥤ TopCat`. - -See . -In fact we prove a stronger version with arbitrary target category. --/ +Another useful example is the forgetful functor `TopCommRingCat ⥤ TopCat`. -/ +@[stacks 0073 "In fact we prove a stronger version with arbitrary target category."] theorem isSheaf_iff_isSheaf_comp' {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] (G : C ⥤ D) [G.ReflectsIsomorphisms] [HasLimitsOfSize.{v, v} C] [PreservesLimitsOfSize.{v, v} G] {X : TopCat.{v}} (F : Presheaf C X) : Presheaf.IsSheaf F ↔ Presheaf.IsSheaf (F ⋙ G) := From 5ef6d7dc4c667778f7d75a4e9b04f08f8834559b Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Sat, 25 Jan 2025 11:16:19 +0000 Subject: [PATCH 515/681] chore: fix typo (#21043) Co-authored-by: Markus Himmel --- Mathlib/CategoryTheory/Limits/Shapes/Images.lean | 4 ++-- Mathlib/CategoryTheory/Monoidal/Functor.lean | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean index ee9cbe4d2297c..3db2bd31165a7 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean @@ -24,7 +24,7 @@ so that `m` factors through the `m'` in any other such factorisation. morphism `e`. * `HasImages C` means that every morphism in `C` has an image. * Let `f : X ⟶ Y` and `g : P ⟶ Q` be morphisms in `C`, which we will represent as objects of the - arrow category `arrow C`. Then `sq : f ⟶ g` is a commutative square in `C`. If `f` and `g` have + arrow category `Arrow C`. Then `sq : f ⟶ g` is a commutative square in `C`. If `f` and `g` have images, then `HasImageMap sq` represents the fact that there is a morphism `i : image f ⟶ image g` making the diagram @@ -241,7 +241,7 @@ def ofArrowIso {f g : Arrow C} (F : ImageFactorisation f.hom) (sq : f ⟶ g) [Is end ImageFactorisation -/-- `has_image f` means that there exists an image factorisation of `f`. -/ +/-- `HasImage f` means that there exists an image factorisation of `f`. -/ class HasImage (f : X ⟶ Y) : Prop where mk' :: exists_image : Nonempty (ImageFactorisation f) diff --git a/Mathlib/CategoryTheory/Monoidal/Functor.lean b/Mathlib/CategoryTheory/Monoidal/Functor.lean index 75e6de20c0015..1f421e496a054 100644 --- a/Mathlib/CategoryTheory/Monoidal/Functor.lean +++ b/Mathlib/CategoryTheory/Monoidal/Functor.lean @@ -55,7 +55,7 @@ namespace Functor -- "weigh more" than structural maps. -- (However by this argument `associativity` is currently stated backwards!) /-- A functor `F : C ⥤ D` between monoidal categories is lax monoidal if it is -equipped with morphisms `ε : 𝟙 _D ⟶ F.obj (𝟙_ C)` and `μ X Y : F.obj X ⊗ F.obj Y ⟶ F.obj (X ⊗ Y)`, +equipped with morphisms `ε : 𝟙_ D ⟶ F.obj (𝟙_ C)` and `μ X Y : F.obj X ⊗ F.obj Y ⟶ F.obj (X ⊗ Y)`, satisfying the appropriate coherences. -/ class LaxMonoidal where /-- unit morphism -/ From efeadfb18697dff701318aa598fc7cd36099920a Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:53:55 +0000 Subject: [PATCH 516/681] feat(Data/Matroid/Constructions): Instances for basic matroids (#20886) We add some instances for the matroids in `Data/Matroid/Constructions`, and also a `RkPos -> Nonempty` instance in `Matroid.Basic`. --- Mathlib/Data/Matroid/Basic.lean | 6 ++++++ Mathlib/Data/Matroid/Constructions.lean | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Mathlib/Data/Matroid/Basic.lean b/Mathlib/Data/Matroid/Basic.lean index 4c8032518f51d..60a143ac60a47 100644 --- a/Mathlib/Data/Matroid/Basic.lean +++ b/Mathlib/Data/Matroid/Basic.lean @@ -263,6 +263,12 @@ instance finiteRk_of_finite (M : Matroid α) [M.Finite] : FiniteRk M := /-- The empty set isn't a base -/ empty_not_base : ¬M.Base ∅ +instance rkPos_nonempty {M : Matroid α} [M.RkPos] : M.Nonempty := by + obtain ⟨B, hB⟩ := M.exists_base + obtain rfl | ⟨e, heB⟩ := B.eq_empty_or_nonempty + · exact False.elim <| RkPos.empty_not_base hB + exact ⟨e, M.subset_ground B hB heB ⟩ + @[deprecated (since := "2025-01-20")] alias rkPos_iff_empty_not_base := rkPos_iff section exchange diff --git a/Mathlib/Data/Matroid/Constructions.lean b/Mathlib/Data/Matroid/Constructions.lean index e886f458dbe70..a6e15c479d63c 100644 --- a/Mathlib/Data/Matroid/Constructions.lean +++ b/Mathlib/Data/Matroid/Constructions.lean @@ -128,6 +128,9 @@ theorem eq_loopyOn_or_rkPos (M : Matroid α) : M = loopyOn M.E ∨ RkPos M := by theorem not_rkPos_iff : ¬RkPos M ↔ M = loopyOn M.E := by rw [rkPos_iff, not_iff_comm, empty_base_iff] +instance loopyOn_finiteRk : FiniteRk (loopyOn E) := + ⟨∅, by simp⟩ + end LoopyOn section FreeOn @@ -183,6 +186,13 @@ theorem restrict_eq_freeOn_iff : M ↾ I = freeOn I ↔ M.Indep I := by theorem Indep.restrict_eq_freeOn (hI : M.Indep I) : M ↾ I = freeOn I := by rwa [restrict_eq_freeOn_iff] +instance freeOn_finitary : Finitary (freeOn E) := by + simp only [finitary_iff, freeOn_indep_iff] + exact fun I h e heI ↦ by simpa using h {e} (by simpa) + +lemma freeOn_rkPos (hE : E.Nonempty) : RkPos (freeOn E) := by + simp [rkPos_iff, hE.ne_empty.symm] + end FreeOn section uniqueBaseOn @@ -243,6 +253,20 @@ theorem uniqueBaseOn_restrict (h : I ⊆ E) (R : Set α) : (uniqueBaseOn I E) ↾ R = uniqueBaseOn (I ∩ R) R := by rw [uniqueBaseOn_restrict', inter_right_comm, inter_eq_self_of_subset_left h] +lemma uniqueBaseOn_finiteRk (hI : I.Finite) : FiniteRk (uniqueBaseOn I E) := by + rw [← uniqueBaseOn_inter_ground_eq] + refine ⟨I ∩ E, ?_⟩ + rw [uniqueBaseOn_base_iff inter_subset_right, and_iff_right rfl] + exact hI.subset inter_subset_left + +instance uniqueBaseOn_finitary : Finitary (uniqueBaseOn I E) := by + refine ⟨fun K hK ↦ ?_⟩ + simp only [uniqueBaseOn_indep_iff'] at hK ⊢ + exact fun e heK ↦ singleton_subset_iff.1 <| hK _ (by simpa) (by simp) + +lemma uniqueBaseOn_rkPos (hIE : I ⊆ E) (hI : I.Nonempty) : RkPos (uniqueBaseOn I E) where + empty_not_base := by simpa [uniqueBaseOn_base_iff hIE] using Ne.symm <| hI.ne_empty + end uniqueBaseOn end Matroid From b3dcc0fd69ca27fbcaeadb166d37f8467b4e05d8 Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Sat, 25 Jan 2025 15:53:00 +0000 Subject: [PATCH 517/681] feat(LinearAlgebra): add `Submodule.span_eq_top_of_restrictScalars` (#21054) --- Mathlib/LinearAlgebra/Span/Basic.lean | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mathlib/LinearAlgebra/Span/Basic.lean b/Mathlib/LinearAlgebra/Span/Basic.lean index 7858b46d72293..ea92a62c9cc47 100644 --- a/Mathlib/LinearAlgebra/Span/Basic.lean +++ b/Mathlib/LinearAlgebra/Span/Basic.lean @@ -191,6 +191,9 @@ theorem span_span_of_tower : span S (span R s : Set M) = span S s := le_antisymm (span_le.2 <| span_subset_span R S s) (span_mono subset_span) +theorem span_eq_top_of_span_eq_top (s : Set M) (hs : span R s = ⊤) : span S s = ⊤ := + le_top.antisymm (hs.ge.trans (span_le_restrictScalars R S s)) + variable {R S} in lemma span_range_inclusion_eq_top (p : Submodule R M) (q : Submodule S M) (h₁ : p ≤ q.restrictScalars R) (h₂ : q ≤ span S p) : From b89b720811b1335dff393d883277608b6206a7db Mon Sep 17 00:00:00 2001 From: grunweg Date: Sat, 25 Jan 2025 16:00:51 +0000 Subject: [PATCH 518/681] feat: the real manifold [x,y] has boundary {x,y} (#15892) Also rename one lemma added in #15891, which I forgot to rename there. Co-authored-by: Michael Rothgang --- Mathlib/Geometry/Manifold/Instances/Real.lean | 64 ++++++++++++++++--- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index 55635af781f7f..28cd5cdbe8912 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 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.Geometry.Manifold.InteriorBoundary import Mathlib.Geometry.Manifold.IsManifold import Mathlib.Analysis.InnerProductSpace.PiL2 @@ -11,7 +12,8 @@ import Mathlib.Analysis.InnerProductSpace.PiL2 We introduce the necessary bits to be able to define manifolds modelled over `ℝ^n`, boundaryless or with boundary or with corners. As a concrete example, we construct explicitly the manifold with -boundary structure on the real interval `[x, y]`. +boundary structure on the real interval `[x, y]`, and prove that its boundary is indeed `{x,y}` +whenever `x < y`. More specifically, we introduce * `modelWithCornersEuclideanHalfSpace n : @@ -77,11 +79,9 @@ instance [NeZero n] : Inhabited (EuclideanHalfSpace n) := instance : Inhabited (EuclideanQuadrant n) := ⟨⟨0, fun _ => le_rfl⟩⟩ -instance {n : ℕ} [NeZero n] : Zero (EuclideanHalfSpace n) where - zero := ⟨fun _ ↦ 0, by norm_num⟩ +instance {n : ℕ} [NeZero n] : Zero (EuclideanHalfSpace n) := ⟨⟨fun _ ↦ 0, by norm_num⟩⟩ -instance {n : ℕ} : Zero (EuclideanQuadrant n) where - zero := ⟨fun _ ↦ 0, by norm_num⟩ +instance {n : ℕ} : Zero (EuclideanQuadrant n) := ⟨⟨fun _ ↦ 0, by norm_num⟩⟩ @[ext] theorem EuclideanQuadrant.ext (x y : EuclideanQuadrant n) (h : x.1 = y.1) : x = y := @@ -382,15 +382,18 @@ lemma IccRightChart_extend_top : norm_num [IccRightChart, modelWithCornersEuclideanHalfSpace_zero] congr -lemma IccRightChart_extend_right_mem_frontier : +lemma IccRightChart_extend_top_mem_frontier : (IccRightChart x y).extend (𝓡∂ 1) ⊤ ∈ frontier (range (𝓡∂ 1)) := by rw [IccRightChart_extend_top, frontier_range_modelWithCornersEuclideanHalfSpace, mem_setOf, PiLp.zero_apply] +@[deprecated (since := "2025-01-25")] +alias IccRightChart_extend_right_mem_frontier := IccRightChart_extend_top_mem_frontier + /-- Charted space structure on `[x, y]`, using only two charts taking values in `EuclideanHalfSpace 1`. -/ -instance IccChartedSpace (x y : ℝ) [h : Fact (x < y)] : +instance instIccChartedSpace (x y : ℝ) [h : Fact (x < y)] : ChartedSpace (EuclideanHalfSpace 1) (Icc x y) where atlas := {IccLeftChart x y, IccRightChart x y} chartAt z := if z.val < y then IccLeftChart x y else IccRightChart x y @@ -403,6 +406,51 @@ instance IccChartedSpace (x y : ℝ) [h : Fact (x < y)] : simpa only [not_lt] using h' chart_mem_atlas z := by by_cases h' : (z : ℝ) < y <;> simp [h'] +@[simp] +lemma Icc_chartedSpaceChartAt {z : Set.Icc x y} : + chartAt _ z = if z.val < y then IccLeftChart x y else IccRightChart x y := rfl + +lemma Icc_chartedSpaceChartAt_of_le_top {z : Set.Icc x y} (h : z.val < y) : + chartAt _ z = IccLeftChart x y := by + simp [Icc_chartedSpaceChartAt, h] + +lemma Icc_chartedSpaceChartAt_of_top_le {z : Set.Icc x y} (h : y ≤ z.val) : + chartAt _ z = IccRightChart x y := by + simp [Icc_chartedSpaceChartAt, reduceIte, not_lt.mpr h] + +lemma Icc_isBoundaryPoint_bot : (𝓡∂ 1).IsBoundaryPoint (⊥ : Set.Icc x y) := by + rw [ModelWithCorners.isBoundaryPoint_iff, extChartAt, + Icc_chartedSpaceChartAt_of_le_top (by norm_num [hxy.out])] + exact IccLeftChart_extend_bot_mem_frontier + +lemma Icc_isBoundaryPoint_top : (𝓡∂ 1).IsBoundaryPoint (⊤ : Set.Icc x y) := by + rw [ModelWithCorners.isBoundaryPoint_iff, extChartAt, + Icc_chartedSpaceChartAt_of_top_le (by norm_num)] + exact IccRightChart_extend_top_mem_frontier + +lemma Icc_isInteriorPoint_interior {p : Set.Icc x y} (hp : x < p.val ∧ p.val < y) : + (𝓡∂ 1).IsInteriorPoint p := by + rw [ModelWithCorners.IsInteriorPoint, extChartAt, Icc_chartedSpaceChartAt_of_le_top hp.2, + interior_range_modelWithCornersEuclideanHalfSpace] + exact IccLeftChart_extend_interior_pos hp + +lemma boundary_Icc : (𝓡∂ 1).boundary (Icc x y) = {⊥, ⊤} := by + ext p + rcases Set.eq_endpoints_or_mem_Ioo_of_mem_Icc p.2 with (hp | hp | hp) + · have : p = ⊥ := SetCoe.ext hp + rw [this] + apply iff_of_true Icc_isBoundaryPoint_bot (mem_insert ⊥ {⊤}) + · have : p = ⊤ := SetCoe.ext hp + rw [this] + apply iff_of_true Icc_isBoundaryPoint_top (mem_insert_of_mem ⊥ rfl) + · apply iff_of_false + · simpa [← mem_compl_iff, ModelWithCorners.compl_boundary] using + Icc_isInteriorPoint_interior hp + · rw [mem_insert_iff, mem_singleton_iff] + push_neg + constructor <;> by_contra h <;> rw [congrArg Subtype.val h] at hp + exacts [left_mem_Ioo.mp hp, right_mem_Ioo.mp hp] + /-- The manifold structure on `[x, y]` is smooth. -/ instance instIsManifoldIcc (x y : ℝ) [Fact (x < y)] {n : WithTop ℕ∞} : @@ -444,7 +492,7 @@ instance instIsManifoldIcc (x y : ℝ) [Fact (x < y)] {n : WithTop ℕ∞} : exact (mem_groupoid_of_pregroupoid.mpr (symm_trans_mem_contDiffGroupoid _)).1 /-! Register the manifold structure on `Icc 0 1`. These are merely special cases of -`IccChartedSpace` and `instIsManifoldIcc`. -/ +`instIccChartedSpace` and `instIsManifoldIcc`. -/ section From 01b13023c8f46a28bd8e6c17861a857b36cddd44 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Sat, 25 Jan 2025 16:29:28 +0000 Subject: [PATCH 519/681] feat(Data/Matroid/Circuit): Matroid circuits (#20995) We define and give basis API for circuits (minimal dependent sets) in matroids. --- Mathlib.lean | 1 + Mathlib/Data/Matroid/Circuit.lean | 169 ++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 Mathlib/Data/Matroid/Circuit.lean diff --git a/Mathlib.lean b/Mathlib.lean index 9346f01dec3ad..dcc63f4a4ea88 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2773,6 +2773,7 @@ import Mathlib.Data.Matrix.Rank import Mathlib.Data.Matrix.Reflection import Mathlib.Data.Matrix.RowCol import Mathlib.Data.Matroid.Basic +import Mathlib.Data.Matroid.Circuit import Mathlib.Data.Matroid.Closure import Mathlib.Data.Matroid.Constructions import Mathlib.Data.Matroid.Dual diff --git a/Mathlib/Data/Matroid/Circuit.lean b/Mathlib/Data/Matroid/Circuit.lean new file mode 100644 index 0000000000000..d8f568c93c09e --- /dev/null +++ b/Mathlib/Data/Matroid/Circuit.lean @@ -0,0 +1,169 @@ +/- +Copyright (c) 2025 Peter Nelson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Peter Nelson +-/ +import Mathlib.Data.Matroid.Closure + +/-! +# Matroid Circuits + +A `Circuit` of a matroid `M` is a minimal set `C` that is dependent in `M`. +A matroid is determined by its set of circuits, and often the circuits +offer a more compact description of a matroid than the collection of independent sets or bases. +In matroids arising from graphs, circuits correspond to graphical cycles. + +# Main Declarations + +* `Matroid.Circuit M C` means that `C` is minimally dependent in `M`. +-/ + +variable {α : Type*} {M : Matroid α} {C C' I X Y R : Set α} {e f x y : α} + +open Set + +namespace Matroid + +/-- A `Circuit` of `M` is a minimal dependent set in `M` -/ +def Circuit (M : Matroid α) := Minimal M.Dep + +lemma circuit_def : M.Circuit C ↔ Minimal M.Dep C := Iff.rfl + +lemma Circuit.dep (hC : M.Circuit C) : M.Dep C := + hC.prop + +lemma Circuit.not_indep (hC : M.Circuit C) : ¬ M.Indep C := + hC.dep.not_indep + +lemma Circuit.minimal (hC : M.Circuit C) : Minimal M.Dep C := + hC + +@[aesop unsafe 20% (rule_sets := [Matroid])] +lemma Circuit.subset_ground (hC : M.Circuit C) : C ⊆ M.E := + hC.dep.subset_ground + +lemma Circuit.nonempty (hC : M.Circuit C) : C.Nonempty := + hC.dep.nonempty + +lemma empty_not_circuit (M : Matroid α) : ¬M.Circuit ∅ := + fun h ↦ by simpa using h.nonempty + +lemma circuit_iff : M.Circuit C ↔ M.Dep C ∧ ∀ ⦃D⦄, M.Dep D → D ⊆ C → D = C := by + simp_rw [circuit_def, minimal_subset_iff, eq_comm (a := C)] + +lemma Circuit.ssubset_indep (hC : M.Circuit C) (hXC : X ⊂ C) : M.Indep X := by + rw [← not_dep_iff (hXC.subset.trans hC.subset_ground)] + exact fun h ↦ hXC.ne ((circuit_iff.1 hC).2 h hXC.subset) + +lemma Circuit.minimal_not_indep (hC : M.Circuit C) : Minimal (¬ M.Indep ·) C := by + simp_rw [minimal_iff_forall_ssubset, and_iff_right hC.not_indep, not_not] + exact fun ⦃t⦄ a ↦ ssubset_indep hC a + +lemma circuit_iff_minimal_not_indep (hCE : C ⊆ M.E) : M.Circuit C ↔ Minimal (¬ M.Indep ·) C := + ⟨Circuit.minimal_not_indep, fun h ↦ ⟨(not_indep_iff hCE).1 h.prop, + fun _ hJ hJC ↦ (h.eq_of_superset hJ.not_indep hJC).le⟩⟩ + +lemma Circuit.diff_singleton_indep (hC : M.Circuit C) (he : e ∈ C) : M.Indep (C \ {e}) := + hC.ssubset_indep (diff_singleton_sSubset.2 he) + +lemma circuit_iff_forall_ssubset : M.Circuit C ↔ M.Dep C ∧ ∀ ⦃I⦄, I ⊂ C → M.Indep I := by + rw [Circuit, minimal_iff_forall_ssubset, and_congr_right_iff] + exact fun h ↦ ⟨fun h' I hIC ↦ ((not_dep_iff (hIC.subset.trans h.subset_ground)).1 (h' hIC)), + fun h I hIC ↦ (h hIC).not_dep⟩ + +lemma circuit_antichain : IsAntichain (· ⊆ ·) (setOf M.Circuit) := + fun _ hC _ hC' hne hss ↦ hne <| (Circuit.minimal hC').eq_of_subset hC.dep hss + +lemma Circuit.eq_of_not_indep_subset (hC : M.Circuit C) (hX : ¬ M.Indep X) (hXC : X ⊆ C) : + X = C := + eq_of_le_of_not_lt hXC (hX ∘ hC.ssubset_indep) + +lemma Circuit.eq_of_dep_subset (hC : M.Circuit C) (hX : M.Dep X) (hXC : X ⊆ C) : X = C := + hC.eq_of_not_indep_subset hX.not_indep hXC + +lemma Circuit.not_ssubset (hC : M.Circuit C) (hC' : M.Circuit C') : ¬C' ⊂ C := + fun h' ↦ h'.ne (hC.eq_of_dep_subset hC'.dep h'.subset) + +lemma Circuit.eq_of_subset_circuit (hC : M.Circuit C) (hC' : M.Circuit C') (h : C ⊆ C') : C = C' := + hC'.eq_of_dep_subset hC.dep h + +lemma circuit_iff_dep_forall_diff_singleton_indep : + M.Circuit C ↔ M.Dep C ∧ ∀ e ∈ C, M.Indep (C \ {e}) := by + wlog hCE : C ⊆ M.E + · exact iff_of_false (hCE ∘ Circuit.subset_ground) (fun h ↦ hCE h.1.subset_ground) + simp [circuit_iff_minimal_not_indep hCE, ← not_indep_iff hCE, + minimal_iff_forall_diff_singleton (P := (¬ M.Indep ·)) + (fun _ _ hY hYX hX ↦ hY <| hX.subset hYX)] + +/-! ### Independence and bases -/ + +lemma Indep.insert_circuit_of_forall (hI : M.Indep I) (heI : e ∉ I) (he : e ∈ M.closure I) + (h : ∀ f ∈ I, e ∉ M.closure (I \ {f})) : M.Circuit (insert e I) := by + rw [circuit_iff_dep_forall_diff_singleton_indep, hI.insert_dep_iff, and_iff_right ⟨he, heI⟩] + rintro f (rfl | hfI) + · simpa [heI] + rw [← insert_diff_singleton_comm (by rintro rfl; contradiction), + (hI.diff _).insert_indep_iff_of_not_mem (by simp [heI])] + exact ⟨mem_ground_of_mem_closure he, h f hfI⟩ + +lemma Indep.insert_circuit_of_forall_of_nontrivial (hI : M.Indep I) (hInt : I.Nontrivial) + (he : e ∈ M.closure I) (h : ∀ f ∈ I, e ∉ M.closure (I \ {f})) : M.Circuit (insert e I) := by + refine hI.insert_circuit_of_forall (fun heI ↦ ?_) he h + obtain ⟨f, hf, hne⟩ := hInt.exists_ne e + exact h f hf (mem_closure_of_mem' _ (by simp [heI, hne.symm])) + +lemma Circuit.diff_singleton_basis (hC : M.Circuit C) (he : e ∈ C) : M.Basis (C \ {e}) C := by + nth_rw 2 [← insert_eq_of_mem he] + rw [← insert_diff_singleton, (hC.diff_singleton_indep he).basis_insert_iff, + insert_diff_singleton, insert_eq_of_mem he] + exact Or.inl hC.dep + +lemma Circuit.basis_iff_eq_diff_singleton (hC : M.Circuit C) : + M.Basis I C ↔ ∃ e ∈ C, I = C \ {e} := by + refine ⟨fun h ↦ ?_, ?_⟩ + · obtain ⟨e, he⟩ := exists_of_ssubset + (h.subset.ssubset_of_ne (by rintro rfl; exact hC.dep.not_indep h.indep)) + exact ⟨e, he.1, h.eq_of_subset_indep (hC.diff_singleton_indep he.1) + (subset_diff_singleton h.subset he.2) diff_subset⟩ + rintro ⟨e, he, rfl⟩ + exact hC.diff_singleton_basis he + +lemma Circuit.basis_iff_insert_eq (hC : M.Circuit C) : + M.Basis I C ↔ ∃ e ∈ C \ I, C = insert e I := by + rw [hC.basis_iff_eq_diff_singleton] + refine ⟨fun ⟨e, he, hI⟩ ↦ ⟨e, ⟨he, fun heI ↦ (hI.subset heI).2 rfl⟩, ?_⟩, + fun ⟨e, he, hC⟩ ↦ ⟨e, he.1, ?_⟩⟩ + · rw [hI, insert_diff_singleton, insert_eq_of_mem he] + rw [hC, insert_diff_self_of_not_mem he.2] + +/-! ### Closure -/ + +lemma Circuit.closure_diff_singleton_eq (hC : M.Circuit C) (e : α) : + M.closure (C \ {e}) = M.closure C := + (em (e ∈ C)).elim + (fun he ↦ by rw [(hC.diff_singleton_basis he).closure_eq_closure]) + (fun he ↦ by rw [diff_singleton_eq_self he]) + +lemma Circuit.subset_closure_diff_singleton (hC : M.Circuit C) (e : α) : + C ⊆ M.closure (C \ {e}) := by + rw [hC.closure_diff_singleton_eq] + exact M.subset_closure _ hC.subset_ground + +lemma Circuit.mem_closure_diff_singleton_of_mem (hC : M.Circuit C) (heC : e ∈ C) : + e ∈ M.closure (C \ {e}) := + (hC.subset_closure_diff_singleton e) heC + +/-! ### Restriction -/ + +lemma Circuit.circuit_restrict_of_subset (hC : M.Circuit C) (hCR : C ⊆ R) : + (M ↾ R).Circuit C := by + simp_rw [circuit_iff, restrict_dep_iff, dep_iff, and_imp] at * + exact ⟨⟨hC.1.1, hCR⟩, fun I hI _ hIC ↦ hC.2 hI (hIC.trans hC.1.2) hIC⟩ + +lemma restrict_circuit_iff (hR : R ⊆ M.E := by aesop_mat) : + (M ↾ R).Circuit C ↔ M.Circuit C ∧ C ⊆ R := by + refine ⟨?_, fun h ↦ h.1.circuit_restrict_of_subset h.2⟩ + simp_rw [circuit_iff, restrict_dep_iff, and_imp, dep_iff] + exact fun hC hCR h ↦ ⟨⟨⟨hC,hCR.trans hR⟩,fun I hI hIC ↦ h hI.1 (hIC.trans hCR) hIC⟩,hCR⟩ + +end Matroid From 38f76ef80253f383a338a7b769c4722a9514bbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 25 Jan 2025 16:37:23 +0000 Subject: [PATCH 520/681] doc(overview): combinatorics overview (#18884) Expand the graph theory section and write new sections for enumerative, set family and additive combinatorics as well Ramsey theory Co-authored-by: adomani --- .../Additive/ApproximateSubgroup.lean | 2 +- .../Combinatorics/Additive/SmallTripling.lean | 4 +- docs/overview.yaml | 56 +++++++++++++++++-- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean b/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean index 286e7296091b2..9fdc80e1a7677 100644 --- a/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean +++ b/Mathlib/Combinatorics/Additive/ApproximateSubgroup.lean @@ -126,7 +126,7 @@ lemma of_small_tripling [DecidableEq G] {A : Finset G} (hA₁ : 1 ∈ A) (hAsymm sq_covBySMul := by replace hA := calc (#(A ^ 4 * A) : ℝ) _ = #(A ^ 5) := by rw [← pow_succ] - _ ≤ K ^ 3 * #A := small_pow_of_small_tripling' (by omega) hA hAsymm + _ ≤ K ^ 3 * #A := small_pow_of_small_tripling (by omega) hA hAsymm have hA₀ : A.Nonempty := ⟨1, hA₁⟩ obtain ⟨F, -, hF, hAF⟩ := ruzsa_covering_mul hA₀ hA exact ⟨F, hF, by norm_cast; simpa [div_eq_mul_inv, pow_succ, mul_assoc, hAsymm] using hAF⟩ diff --git a/Mathlib/Combinatorics/Additive/SmallTripling.lean b/Mathlib/Combinatorics/Additive/SmallTripling.lean index 783cfbe6ceb6f..997ee229b26f0 100644 --- a/Mathlib/Combinatorics/Additive/SmallTripling.lean +++ b/Mathlib/Combinatorics/Additive/SmallTripling.lean @@ -130,7 +130,7 @@ terms in the product. When `A` is symmetric (`-A = A`), the base of the exponential can be lowered from `K ^ 3` to `K`, where `K` is the tripling constant. See `Finset.small_nsmul_of_small_tripling`."] -lemma small_alternating_pow_of_small_tripling' (hm : 3 ≤ m) (hA : #(A ^ 3) ≤ K * #A) (ε : Fin m → ℤ) +lemma small_alternating_pow_of_small_tripling (hm : 3 ≤ m) (hA : #(A ^ 3) ≤ K * #A) (ε : Fin m → ℤ) (hε : ∀ i, |ε i| = 1) : #((finRange m).map fun i ↦ A ^ ε i).prod ≤ K ^ (3 * (m - 2)) * #A := by have hm₀ : m ≠ 0 := by positivity @@ -174,7 +174,7 @@ in the sense that `|m • A|` is at most `|A|` times a constant exponential in ` See also `Finset.small_alternating_nsmul_of_small_tripling` for a version with a weaker constant but which encompasses non-symmetric sets."] -lemma small_pow_of_small_tripling' (hm : 3 ≤ m) (hA : #(A ^ 3) ≤ K * #A) (hAsymm : A⁻¹ = A) : +lemma small_pow_of_small_tripling (hm : 3 ≤ m) (hA : #(A ^ 3) ≤ K * #A) (hAsymm : A⁻¹ = A) : #(A ^ m) ≤ K ^ (m - 2) * #A := by have (ε : ℤ) (hε : |ε| = 1) : A ^ ε = A := by obtain rfl | rfl := eq_or_eq_neg_of_abs_eq hε <;> simp [hAsymm] diff --git a/docs/overview.yaml b/docs/overview.yaml index d9df79a5cfead..8a37e088447d8 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -427,17 +427,63 @@ Geometry: Nullstellensatz : 'MvPolynomial.vanishingIdeal_zeroLocus_eq_radical' Combinatorics: - Graph theory: - simple graph: 'SimpleGraph' - degree-sum formula: 'SimpleGraph.sum_degrees_eq_twice_card_edges' - matching: 'SimpleGraph.Subgraph.IsMatching' - adjacency matrix: 'SimpleGraph.adjMatrix' Pigeonhole principles: finite: 'Fintype.exists_ne_map_eq_of_card_lt' infinite: 'Finite.exists_infinite_fiber' strong pigeonhole principle: 'Fintype.exists_lt_card_fiber_of_mul_lt_card' Transversals: Hall's marriage theorem: 'Finset.all_card_le_biUnion_card_iff_exists_injective' + Enumerative combinatorics: + Catalan numbers: 'catalan' + Bell numbers: 'Multiset.bell' + Dyck words: 'DyckWord' + Set families: + # Correlation inequalities: + Four functions theorem: 'four_functions_theorem' + Harris-Kleitman inequality: 'IsLowerSet.le_card_inter_finset' + # Antichains: + Ahlswede-Zhang identity: 'AhlswedeZhang.infSum_eq_one' + LYM inequality: 'Finset.sum_card_slice_div_choose_le_one' + Sperner's theorem: 'IsAntichain.sperner' + # Intersecting families: + Maximum size of an intersecting family: 'Set.Intersecting.is_max_iff_card_eq' + Kleitman's theorem: 'Finset.card_biUnion_le_of_intersecting' + # VC dimension: + VC dimension: 'Finset.vcDim' + Sauer-Shelah lemma: 'Finset.card_shatterer_le_sum_vcDim' + Kruskal-Katona theorem: 'Finset.kruskal_katona' + Graph theory: + simple graph: 'SimpleGraph' + degree-sum formula: 'SimpleGraph.sum_degrees_eq_twice_card_edges' + matching: 'SimpleGraph.Subgraph.IsMatching' + adjacency matrix: 'SimpleGraph.adjMatrix' + Strongly regular graphs: 'SimpleGraph.IsSRGWith' + # Extremal graph theory: + Turán's theorem: 'SimpleGraph.isTuranMaximal_iff_nonempty_iso_turanGraph' + Regularity lemma: 'szemeredi_regularity' + Triangle counting lemma: 'SimpleGraph.triangle_counting' + Triangle removal lemma: 'SimpleGraph.triangle_removal' + Ramsey theory: + van der Waerden theorem: 'Combinatorics.exists_mono_homothetic_copy' + Hales-Jewett theorem: 'Combinatorics.Line.exists_mono_in_high_dimension' + Hindman's theorem: 'Hindman.FS_partition_regular' + Additive combinatorics: + # Avoiding patterns: + sets without arithmetic progressions: 'ThreeAPFree' + Roth's theorem: 'roth_3ap_theorem_nat' + Corners theorem: corners_theorem_nat + Behrend's construction: 'Behrend.roth_lower_bound' + # Growth: + doubling constant: 'Finset.addConst' + Ruzsa covering lemma: 'Finset.exists_subset_add_sub' + Ruzsa triangle inequality: 'Finset.ruzsa_triangle_inequality_sub_sub_sub' + Plünnecke-Petridis inequality: 'Finset.pluennecke_petridis_inequality_add' + Small tripling implies small powers: 'Finset.small_pow_of_small_tripling' + Dyson transform: 'Finset.addDysonETransform' + Cauchy-Davenport theorem: 'ZMod.cauchy_davenport' + Erdős–Ginzburg–Ziv theorem: 'ZMod.erdos_ginzburg_ziv' + Additive energy: 'Finset.addEnergy' + Freiman homomorphisms: 'IsAddFreimanHom' Dynamics: Circle dynamics: From 773fd70b277de7128e27499a4b76e7f8cef6cd1f Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Sat, 25 Jan 2025 16:37:25 +0000 Subject: [PATCH 521/681] feat(RingTheory): the smooth locus of an algebra (#20953) Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com> --- Mathlib.lean | 1 + .../Algebra/Module/FinitePresentation.lean | 29 ++++ Mathlib/RingTheory/Extension.lean | 7 + .../RingTheory/Kaehler/CotangentComplex.lean | 55 ++++++- Mathlib/RingTheory/Presentation.lean | 22 +++ Mathlib/RingTheory/Smooth/Locus.lean | 142 ++++++++++++++++++ 6 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 Mathlib/RingTheory/Smooth/Locus.lean diff --git a/Mathlib.lean b/Mathlib.lean index dcc63f4a4ea88..8759b1dc6f015 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4756,6 +4756,7 @@ import Mathlib.RingTheory.SimpleRing.Matrix import Mathlib.RingTheory.Smooth.Basic import Mathlib.RingTheory.Smooth.Kaehler import Mathlib.RingTheory.Smooth.Local +import Mathlib.RingTheory.Smooth.Locus import Mathlib.RingTheory.Smooth.Pi import Mathlib.RingTheory.Smooth.StandardSmooth import Mathlib.RingTheory.Spectrum.Maximal.Basic diff --git a/Mathlib/Algebra/Module/FinitePresentation.lean b/Mathlib/Algebra/Module/FinitePresentation.lean index 4c43da972ed6a..51af8af5b2d8b 100644 --- a/Mathlib/Algebra/Module/FinitePresentation.lean +++ b/Mathlib/Algebra/Module/FinitePresentation.lean @@ -241,6 +241,35 @@ lemma Module.finitePresentation_of_ker [Module.FinitePresentation R N] LinearMap.ker_eq_bot.mpr (Submodule.injective_subtype (LinearMap.ker l)), Submodule.comap_bot] exact (Module.FinitePresentation.fg_ker f hf).map (Submodule.subtype _) +/-- Given a split exact sequence `0 → M → N → P → 0` with `N` finitely presented, +then `M` is also finitely presented. -/ +lemma Module.finitePresentation_of_split_exact + {P : Type*} [AddCommGroup P] [Module R P] + [Module.FinitePresentation R N] + (f : M →ₗ[R] N) (g : N →ₗ[R] P) (l : P →ₗ[R] N) (hl : g ∘ₗ l = .id) + (hf : Function.Injective f) (H : Function.Exact f g) : + Module.FinitePresentation R M := by + have hg : Function.Surjective g := Function.LeftInverse.surjective (DFunLike.congr_fun hl) + have := Module.Finite.of_surjective g hg + obtain ⟨e, rfl, rfl⟩ := ((Function.Exact.split_tfae' H).out 0 2 rfl rfl).mp + ⟨hf, l, hl⟩ + refine Module.finitePresentation_of_surjective (LinearMap.fst _ _ _ ∘ₗ e.toLinearMap) + (Prod.fst_surjective.comp e.surjective) ?_ + rw [LinearMap.ker_comp, Submodule.comap_equiv_eq_map_symm, + LinearMap.exact_iff.mp Function.Exact.inr_fst, ← Submodule.map_top] + exact .map _ (.map _ (Module.Finite.fg_top)) + +/-- Given an exact sequence `0 → M → N → P → 0` +with `N` finitely presented and `P` projective, then `M` is also finitely presented. -/ +lemma Module.finitePresentation_of_projective_of_exact + {P : Type*} [AddCommGroup P] [Module R P] + [Module.FinitePresentation R N] [Module.Projective R P] + (f : M →ₗ[R] N) (g : N →ₗ[R] P) + (hf : Function.Injective f) (hg : Function.Surjective g) (H : Function.Exact f g) : + Module.FinitePresentation R M := + have ⟨l, hl⟩ := Module.projective_lifting_property g .id hg + Module.finitePresentation_of_split_exact f g l hl hf H + end Ring section CommRing diff --git a/Mathlib/RingTheory/Extension.lean b/Mathlib/RingTheory/Extension.lean index 019a131967157..1de194d71dedc 100644 --- a/Mathlib/RingTheory/Extension.lean +++ b/Mathlib/RingTheory/Extension.lean @@ -416,6 +416,13 @@ lemma Cotangent.map_comp (f : Hom P P') (g : Hom P' P'') : simp only [map_mk, Hom.toAlgHom_apply, Hom.comp_toRingHom, RingHom.coe_comp, Function.comp_apply, val_mk, LinearMap.coe_comp, LinearMap.coe_restrictScalars] +lemma Cotangent.finite (hP : P.ker.FG) : + Module.Finite S P.Cotangent := by + refine ⟨.of_restrictScalars (R := P.Ring) _ ?_⟩ + rw [Submodule.restrictScalars_top, ← LinearMap.range_eq_top.mpr Extension.Cotangent.mk_surjective, + ← Submodule.map_top] + exact (P.ker.fg_top.mpr hP).map _ + end Cotangent end Algebra.Extension diff --git a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean index 2ca02e4c274e9..3c8dd440d4251 100644 --- a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean +++ b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.RingTheory.Kaehler.Polynomial -import Mathlib.RingTheory.Generators +import Mathlib.Algebra.Module.FinitePresentation +import Mathlib.RingTheory.Presentation /-! @@ -394,6 +395,9 @@ lemma cotangentSpaceBasis_apply (i) : P.cotangentSpaceBasis i = ((1 : S) ⊗ₜ[P.Ring] D R P.Ring (.X i) :) := by simp [cotangentSpaceBasis, toExtension] +instance (P : Generators R S) : Module.Free S P.toExtension.CotangentSpace := + .of_basis P.cotangentSpaceBasis + universe w' u' v' variable {R' : Type u'} {S' : Type v'} [CommRing R'] [CommRing S'] [Algebra R' S'] @@ -433,6 +437,16 @@ lemma toKaehler_cotangentSpaceBasis (i) : end Generators +-- TODO: generalize to essentially of finite presentation algebras +open KaehlerDifferential in +attribute [local instance] Module.finitePresentation_of_projective in +instance [Algebra.FinitePresentation R S] : Module.FinitePresentation S (Ω[S⁄R]) := by + let P := Algebra.Presentation.ofFinitePresentation R S + have : Algebra.FiniteType R P.toExtension.Ring := .mvPolynomial _ _ + refine Module.finitePresentation_of_surjective _ P.toExtension.toKaehler_surjective ?_ + rw [LinearMap.exact_iff.mp P.toExtension.exact_cotangentComplex_toKaehler, ← Submodule.map_top] + exact (Extension.Cotangent.finite P.ideal_fg_of_isFinite).1.map P.toExtension.cotangentComplex + variable {P : Generators R S} open Extension.H1Cotangent in @@ -458,6 +472,28 @@ noncomputable def H1Cotangent.map : H1Cotangent R S' →ₗ[S'] H1Cotangent S T := Extension.H1Cotangent.map (Generators.defaultHom _ _).toExtensionHom +/-- Isomorphic algebras induce isomorphic `H¹(L_{S/R})`. -/ +noncomputable +def H1Cotangent.mapEquiv (e : S ≃ₐ[R] S') : + H1Cotangent R S ≃ₗ[R] H1Cotangent R S' := + -- we are constructing data, so we do not use `algebraize` + letI := e.toRingHom.toAlgebra + letI := e.symm.toRingHom.toAlgebra + have : IsScalarTower R S S' := .of_algebraMap_eq' e.toAlgHom.comp_algebraMap.symm + have : IsScalarTower R S' S := .of_algebraMap_eq' e.symm.toAlgHom.comp_algebraMap.symm + have : IsScalarTower S S' S := .of_algebraMap_eq fun _ ↦ (e.symm_apply_apply _).symm + have : IsScalarTower S' S S' := .of_algebraMap_eq fun _ ↦ (e.apply_symm_apply _).symm + { __ := map R R S S' + invFun := map R R S' S + left_inv x := by + show ((map R R S' S).restrictScalars S ∘ₗ map R R S S') x = x + rw [map, map, ← Extension.H1Cotangent.map_comp, Extension.H1Cotangent.map_eq, + Extension.H1Cotangent.map_id, LinearMap.id_apply] + right_inv x := by + show ((map R R S S').restrictScalars S' ∘ₗ map R R S' S) x = x + rw [map, map, ← Extension.H1Cotangent.map_comp, Extension.H1Cotangent.map_eq, + Extension.H1Cotangent.map_id, LinearMap.id_apply] } + variable {R S S' T} /-- `H¹(L_{S/R})` is independent of the presentation chosen. -/ @@ -466,4 +502,21 @@ abbrev Generators.equivH1Cotangent (P : Generators.{w} R S) : P.toExtension.H1Cotangent ≃ₗ[S] H1Cotangent R S := Generators.H1Cotangent.equiv _ _ +attribute [local instance] Module.finitePresentation_of_projective in +instance [FinitePresentation R S] [Module.Projective S (Ω[S⁄R])] : + Module.Finite S (H1Cotangent R S) := by + let P := Algebra.Presentation.ofFinitePresentation R S + have : Algebra.FiniteType R P.toExtension.Ring := FiniteType.mvPolynomial R P.vars + suffices Module.Finite S P.toExtension.H1Cotangent from + .of_surjective P.equivH1Cotangent.toLinearMap P.equivH1Cotangent.surjective + rw [Module.finite_def, Submodule.fg_top, ← LinearMap.ker_rangeRestrict] + have := Extension.Cotangent.finite P.ideal_fg_of_isFinite + have : Module.FinitePresentation S (LinearMap.range P.toExtension.cotangentComplex) := by + rw [← LinearMap.exact_iff.mp P.toExtension.exact_cotangentComplex_toKaehler] + exact Module.finitePresentation_of_projective_of_exact + _ _ (Subtype.val_injective) P.toExtension.toKaehler_surjective + (LinearMap.exact_subtype_ker_map _) + exact Module.FinitePresentation.fg_ker (N := LinearMap.range P.toExtension.cotangentComplex) + _ P.toExtension.cotangentComplex.surjective_rangeRestrict + end Algebra diff --git a/Mathlib/RingTheory/Presentation.lean b/Mathlib/RingTheory/Presentation.lean index 398f0c3b2efbc..598bfa0dbf673 100644 --- a/Mathlib/RingTheory/Presentation.lean +++ b/Mathlib/RingTheory/Presentation.lean @@ -126,6 +126,28 @@ lemma finitePresentation_of_isFinite [P.IsFinite] : FinitePresentation R S := FinitePresentation.equiv (P.quotientEquiv.restrictScalars R) +variable (R S) in +/-- An arbitrary choice of a finite presentation of a finitely presented algebra. -/ +noncomputable +def ofFinitePresentation [FinitePresentation R S] : Presentation.{0, 0} R S := + letI H := FinitePresentation.out (R := R) (A := S) + letI n : ℕ := H.choose + letI f : MvPolynomial (Fin n) R →ₐ[R] S := H.choose_spec.choose + haveI hf : Function.Surjective f := H.choose_spec.choose_spec.1 + haveI hf' : (RingHom.ker f).FG := H.choose_spec.choose_spec.2 + letI H' := Submodule.fg_iff_exists_fin_generating_family.mp hf' + let m : ℕ := H'.choose + let v : Fin m → MvPolynomial (Fin n) R := H'.choose_spec.choose + let hv : Ideal.span (Set.range v) = RingHom.ker f := H'.choose_spec.choose_spec + { __ := Generators.ofSurjective (fun x ↦ f (.X x)) (by convert hf; ext; simp) + rels := Fin m + relation := v + span_range_relation_eq_ker := hv.trans (by congr; ext; simp) } + +instance [FinitePresentation R S] : (ofFinitePresentation R S).IsFinite where + finite_vars := Finite.of_fintype (Fin _) + finite_rels := Finite.of_fintype (Fin _) + section Construction /-- If `algebraMap R S` is bijective, the empty generators are a presentation with no relations. -/ diff --git a/Mathlib/RingTheory/Smooth/Locus.lean b/Mathlib/RingTheory/Smooth/Locus.lean new file mode 100644 index 0000000000000..7e4b969ef0b7e --- /dev/null +++ b/Mathlib/RingTheory/Smooth/Locus.lean @@ -0,0 +1,142 @@ +/- +Copyright (c) 2025 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.RingTheory.Etale.Kaehler +import Mathlib.RingTheory.Spectrum.Prime.FreeLocus +import Mathlib.RingTheory.Support + +/-! +# Smooth locus of an algebra + +Most results in this file are proved for algebras of finite presentations. +Some of them are true for arbitrary algebras but the proof is substantially harder. + +## Main results +- `Algebra.smoothLocus` : The set of primes that are smooth over the base. +- `Algebra.basicOpen_subset_smoothLocus_iff` : + `D(f)` is contained in the smooth locus if and only if `A_f` is smooth over `R`. +- `Algebra.smoothLocus_eq_univ_iff` : + The smooth locus is the whole spectrum if and only if `A` is smooth over `R`. +- `Algebra.isOpen_smoothLocus` : The smooth locus is open. +-/ + +universe u + +variable (R A : Type u) [CommRing R] [CommRing A] [Algebra R A] + +namespace Algebra + +variable {A} in +/-- +An `R`-algebra `A` is smooth at a prime `p` of `A` if `Aₚ` is formally smooth over `R`. + +This does not imply `Aₚ` is smooth over `R` under the mathlib definition +even if `A` is finitely presented, +but it can be shown that this is equivalent to the stacks project definition that `A` is smooth +at `p` if and only if there exists `f ∉ p` such that `A_f` is smooth over `R`. +See `Algebra.basicOpen_subset_smoothLocus_iff_smooth` and `Algebra.isOpen_smoothLocus`. +-/ +@[stacks 00TB] +abbrev IsSmoothAt (p : Ideal A) [p.IsPrime] : Prop := + Algebra.FormallySmooth R (Localization.AtPrime p) + +/-- `Algebra.smoothLocus R A` is the set of primes `p` of `A` +such that `Aₚ` is formally smooth over `R`. -/ +def smoothLocus : Set (PrimeSpectrum A) := { p | IsSmoothAt R p.asIdeal } + +variable {R A} + +attribute [local instance] Module.finitePresentation_of_projective in +lemma smoothLocus_eq_compl_support_inter [EssFiniteType R A] : + smoothLocus R A = (Module.support A (H1Cotangent R A))ᶜ ∩ Module.freeLocus A (Ω[A⁄R]) := by + ext p + simp only [Set.mem_inter_iff, Set.mem_compl_iff, Module.not_mem_support_iff, + Module.mem_freeLocus] + refine Algebra.FormallySmooth.iff_subsingleton_and_projective.trans ?_ + congr! 1 + · have := IsLocalizedModule.iso p.asIdeal.primeCompl + (H1Cotangent.map R R A (Localization.AtPrime p.asIdeal)) + exact this.subsingleton_congr.symm + · trans Module.Free (Localization.AtPrime p.asIdeal) (Ω[Localization.AtPrime p.asIdeal⁄R]) + · have : EssFiniteType A (Localization.AtPrime p.asIdeal) := + .of_isLocalization _ p.asIdeal.primeCompl + have : EssFiniteType R (Localization.AtPrime p.asIdeal) := .comp _ A _ + exact ⟨fun _ ↦ Module.free_of_flat_of_isLocalRing, fun _ ↦ inferInstance⟩ + · have := IsLocalizedModule.iso p.asIdeal.primeCompl + (KaehlerDifferential.map R R A (Localization.AtPrime p.asIdeal)) + have := LinearEquiv.ofBijective (this.extendScalarsOfIsLocalization + p.asIdeal.primeCompl (Localization.AtPrime p.asIdeal)) this.bijective + exact ⟨fun H ↦ H.of_equiv' this.symm, fun H ↦ H.of_equiv' this⟩ + +lemma basicOpen_subset_smoothLocus_iff [FinitePresentation R A] {f : A} : + ↑(PrimeSpectrum.basicOpen f) ⊆ smoothLocus R A ↔ + Algebra.FormallySmooth R (Localization.Away f) := by + rw [smoothLocus_eq_compl_support_inter, Set.subset_inter_iff, Set.subset_compl_comm, + PrimeSpectrum.basicOpen_eq_zeroLocus_compl, compl_compl, + ← LocalizedModule.subsingleton_iff_support_subset, + Algebra.FormallySmooth.iff_subsingleton_and_projective] + congr! 1 + · have := IsLocalizedModule.iso (.powers f) (H1Cotangent.map R R A (Localization.Away f)) + rw [this.subsingleton_congr] + · rw [← PrimeSpectrum.basicOpen_eq_zeroLocus_compl, Module.basicOpen_subset_freeLocus_iff] + have := IsLocalizedModule.iso (.powers f) + (KaehlerDifferential.map R R A (Localization.Away f)) + have := LinearEquiv.ofBijective (this.extendScalarsOfIsLocalization + (.powers f) (Localization.Away f)) this.bijective + exact ⟨fun _ ↦ .of_equiv this, fun _ ↦ .of_equiv this.symm⟩ + +lemma basicOpen_subset_smoothLocus_iff_smooth [FinitePresentation R A] {f : A} : + ↑(PrimeSpectrum.basicOpen f) ⊆ smoothLocus R A ↔ + Algebra.Smooth R (Localization.Away f) := by + have : FinitePresentation A (Localization.Away f) := IsLocalization.Away.finitePresentation f + rw [basicOpen_subset_smoothLocus_iff] + exact ⟨fun H ↦ ⟨H, .trans _ A _⟩, fun H ↦ H.1⟩ + +lemma smoothLocus_eq_univ_iff [FinitePresentation R A] : + smoothLocus R A = Set.univ ↔ Algebra.FormallySmooth R A := by + have := IsLocalization.atUnits A (.powers 1) (S := Localization.Away (1 : A)) (by simp) + rw [Algebra.FormallySmooth.iff_of_equiv (this.restrictScalars R), + ← basicOpen_subset_smoothLocus_iff] + simp + +lemma smoothLocus_comap_of_isLocalization {Af : Type u} [CommRing Af] [Algebra A Af] [Algebra R Af] + [IsScalarTower R A Af] (f : A) [IsLocalization.Away f Af] : + PrimeSpectrum.comap (algebraMap A Af) ⁻¹' smoothLocus R A = smoothLocus R Af := by + ext p + let q := PrimeSpectrum.comap (algebraMap A Af) p + have : IsLocalization.AtPrime (Localization.AtPrime p.asIdeal) q.asIdeal := + IsLocalization.isLocalization_isLocalization_atPrime_isLocalization (.powers f) _ p.asIdeal + refine Algebra.FormallySmooth.iff_of_equiv ?_ + exact (IsLocalization.algEquiv q.asIdeal.primeCompl _ _).restrictScalars R + +-- Note that this does not follow directly from `smoothLocus_eq_compl_support_inter` because +-- `H¹(L_{S/R})` is not necessarily finitely generated. +open PrimeSpectrum in +lemma isOpen_smoothLocus [FinitePresentation R A] : IsOpen (smoothLocus R A) := by + rw [isOpen_iff_forall_mem_open] + intro x hx + obtain ⟨_, ⟨_, ⟨f, rfl⟩, rfl⟩, hxf, hf⟩ := + isBasis_basic_opens.exists_subset_of_mem_open + (smoothLocus_eq_compl_support_inter.le hx).2 Module.isOpen_freeLocus + rw [Module.basicOpen_subset_freeLocus_iff] at hf + let Af := Localization.Away f + have : Algebra.FinitePresentation A (Localization.Away f) := + IsLocalization.Away.finitePresentation f + have : Algebra.FinitePresentation R (Localization.Away f) := + .trans _ A _ + have : IsOpen (smoothLocus R Af) := by + have := IsLocalizedModule.iso (.powers f) + (KaehlerDifferential.map R R A (Localization.Away f)) + have := LinearEquiv.ofBijective (this.extendScalarsOfIsLocalization + (.powers f) (Localization.Away f)) this.bijective + have := Module.Projective.of_equiv this + rw [smoothLocus_eq_compl_support_inter, Module.support_eq_zeroLocus] + exact (isClosed_zeroLocus _).isOpen_compl.inter Module.isOpen_freeLocus + rw [← smoothLocus_comap_of_isLocalization f] at this + replace this := (PrimeSpectrum.localization_away_isOpenEmbedding Af f).isOpenMap _ this + rw [Set.image_preimage_eq_inter_range, localization_away_comap_range Af f] at this + exact ⟨_, Set.inter_subset_left, this, hx, hxf⟩ + +end Algebra From ae9766f5362404a60adcb3353eb085795801c03a Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Sat, 25 Jan 2025 17:33:45 +0000 Subject: [PATCH 522/681] feat(Data/Matroid/Closure): matroid closure lemmas (#20885) This PR adds a few lemmas about matroid closure, and its interaction with restrictions, independence and bases. --- Mathlib/Data/Matroid/Closure.lean | 191 +++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 1 deletion(-) diff --git a/Mathlib/Data/Matroid/Closure.lean b/Mathlib/Data/Matroid/Closure.lean index 4dec4fadae6e9..f00a1faa7dc23 100644 --- a/Mathlib/Data/Matroid/Closure.lean +++ b/Mathlib/Data/Matroid/Closure.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Peter Nelson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Peter Nelson -/ -import Mathlib.Data.Matroid.Restrict +import Mathlib.Data.Matroid.Map import Mathlib.Order.Closure import Mathlib.Order.CompleteLatticeIntervals @@ -270,6 +270,18 @@ lemma closure_closure_union_closure_eq_closure_union (M : Matroid α) (X Y : Set M.closure (insert e (M.closure X)) = M.closure (insert e X) := by simp_rw [← singleton_union, closure_union_closure_right_eq] +lemma closure_union_congr_left {X' : Set α} (h : M.closure X = M.closure X') : + M.closure (X ∪ Y) = M.closure (X' ∪ Y) := by + rw [← M.closure_union_closure_left_eq, h, M.closure_union_closure_left_eq] + +lemma closure_union_congr_right {Y' : Set α} (h : M.closure Y = M.closure Y') : + M.closure (X ∪ Y) = M.closure (X ∪ Y') := by + rw [← M.closure_union_closure_right_eq, h, M.closure_union_closure_right_eq] + +lemma closure_insert_congr_right (h : M.closure X = M.closure Y) : + M.closure (insert e X) = M.closure (insert e Y) := by + simp [← union_singleton, closure_union_congr_left h] + @[simp] lemma closure_union_closure_empty_eq (M : Matroid α) (X : Set α) : M.closure X ∪ M.closure ∅ = M.closure X := union_eq_self_of_subset_right (M.closure_subset_closure (empty_subset _)) @@ -485,6 +497,27 @@ lemma Indep.closure_inter_eq_inter_closure (h : M.Indep (I ∪ J)) : · exact iInter_congr (by simp) rwa [← union_eq_iUnion] +lemma Indep.inter_Basis_biInter {ι : Type*} (hI : M.Indep I) {X : ι → Set α} {A : Set ι} + (hA : A.Nonempty) (h : ∀ i ∈ A, M.Basis ((X i) ∩ I) (X i)) : + M.Basis ((⋂ i ∈ A, X i) ∩ I) (⋂ i ∈ A, X i) := by + refine (hI.inter_left _).basis_of_subset_of_subset_closure inter_subset_left ?_ + simp_rw [← biInter_inter hA, + closure_biInter_eq_biInter_closure_of_biUnion_indep hA (I := fun i ↦ (X i) ∩ I) + (hI.subset (by simp)), subset_iInter_iff] + exact fun i hiA ↦ (biInter_subset_of_mem hiA).trans (h i hiA).subset_closure + +lemma Indep.inter_Basis_iInter [Nonempty ι] {X : ι → Set α} (hI : M.Indep I) + (h : ∀ i, M.Basis ((X i) ∩ I) (X i)) : M.Basis ((⋂ i, X i) ∩ I) (⋂ i, X i) := by + convert hI.inter_Basis_biInter (ι := PLift ι) univ_nonempty (X := fun i ↦ X i.down) + (by simpa using fun (i : PLift ι) ↦ h i.down) <;> + · simp only [mem_univ, iInter_true] + exact (iInter_plift_down X).symm + +lemma Indep.inter_Basis_sInter {Xs : Set (Set α)} (hI : M.Indep I) (hXs : Xs.Nonempty) + (h : ∀ X ∈ Xs, M.Basis (X ∩ I) X) : M.Basis (⋂₀ Xs ∩ I) (⋂₀ Xs) := by + rw [sInter_eq_biInter] + exact hI.inter_Basis_biInter hXs h + lemma basis_iff_basis_closure_of_subset (hIX : I ⊆ X) (hX : X ⊆ M.E := by aesop_mat) : M.Basis I X ↔ M.Basis I (M.closure X) := ⟨fun h ↦ h.basis_closure_right, fun h ↦ h.basis_subset hIX (M.subset_closure X hX)⟩ @@ -519,11 +552,25 @@ lemma basis_iff_indep_closure : M.Basis I X ↔ M.Indep I ∧ X ⊆ M.closure I ⟨fun h ↦ ⟨h.indep, h.subset_closure, h.subset⟩, fun h ↦ (basis_union_iff_indep_closure.mpr ⟨h.1, h.2.1⟩).basis_subset h.2.2 subset_union_right⟩ +lemma Indep.inter_basis_closure_iff_subset_closure_inter {X : Set α} (hI : M.Indep I) : + M.Basis (X ∩ I) X ↔ X ⊆ M.closure (X ∩ I) := + ⟨Basis.subset_closure, (hI.inter_left X).basis_of_subset_of_subset_closure inter_subset_left⟩ + +lemma Basis.closure_inter_basis_closure (h : M.Basis (X ∩ I) X) (hI : M.Indep I) : + M.Basis (M.closure X ∩ I) (M.closure X) := by + rw [hI.inter_basis_closure_iff_subset_closure_inter] at h ⊢ + exact (M.closure_subset_closure_of_subset_closure h).trans (M.closure_subset_closure + (inter_subset_inter_left _ (h.trans (M.closure_subset_closure inter_subset_left)))) + lemma Basis.eq_of_closure_subset (hI : M.Basis I X) (hJI : J ⊆ I) (hJ : X ⊆ M.closure J) : J = I := by rw [← hI.indep.closure_inter_eq_self_of_subset hJI, inter_eq_self_of_subset_right] exact hI.subset.trans hJ +lemma Basis.insert_basis_insert_of_not_mem_closure (hIX : M.Basis I X) (heI : e ∉ M.closure I) + (heE : e ∈ M.E := by aesop_mat) : M.Basis (insert e I) (insert e X) := + hIX.insert_basis_insert <| hIX.indep.insert_indep_iff.2 <| .inl ⟨heE, heI⟩ + @[simp] lemma empty_basis_iff : M.Basis ∅ X ↔ X ⊆ M.closure ∅ := by rw [basis_iff_indep_closure, and_iff_right M.empty_indep, and_iff_left (empty_subset _)] @@ -557,6 +604,26 @@ lemma indep_iff_forall_closure_diff_ne : nth_rw 2 [show I = insert e (I \ {e}) by simp [heI]] rw [← closure_insert_closure_eq_closure_insert, insert_eq_of_mem hin, closure_closure] +lemma Indep.union_indep_iff_forall_not_mem_closure_right (hI : M.Indep I) (hJ : M.Indep J) : + M.Indep (I ∪ J) ↔ ∀ e ∈ J \ I, e ∉ M.closure (I ∪ (J \ {e})) := by + refine ⟨fun h e heJ hecl ↦ h.not_mem_closure_diff_of_mem (.inr heJ.1) ?_, fun h ↦ ?_⟩ + · rwa [union_diff_distrib, diff_singleton_eq_self heJ.2] + obtain ⟨K, hKIJ, hK⟩ := hI.subset_basis_of_subset (show I ⊆ I ∪ J from subset_union_left) + obtain rfl | hssu := hKIJ.subset.eq_or_ssubset + · exact hKIJ.indep + exfalso + obtain ⟨e, heI, heK⟩ := exists_of_ssubset hssu + have heJI : e ∈ J \ I := by + rw [← union_diff_right, union_comm] + exact ⟨heI, not_mem_subset hK heK⟩ + refine h _ heJI ?_ + rw [← diff_singleton_eq_self heJI.2, ← union_diff_distrib] + exact M.closure_subset_closure (subset_diff_singleton hKIJ.subset heK) <| hKIJ.subset_closure heI + +lemma Indep.union_indep_iff_forall_not_mem_closure_left (hI : M.Indep I) (hJ : M.Indep J) : + M.Indep (I ∪ J) ↔ ∀ e ∈ I \ J, e ∉ M.closure ((I \ {e}) ∪ J) := by + simp_rw [union_comm I J, hJ.union_indep_iff_forall_not_mem_closure_right hI, union_comm] + lemma Indep.closure_ssubset_closure (hI : M.Indep I) (hJI : J ⊂ I) : M.closure J ⊂ M.closure I := by obtain ⟨e, heI, heJ⟩ := exists_of_ssubset hJI exact (M.closure_subset_closure hJI.subset).ssubset_of_not_subset fun hss ↦ heJ <| @@ -740,6 +807,35 @@ lemma Indep.base_of_spanning (hI : M.Indep I) (hIs : M.Spanning I) : M.Base I := lemma Spanning.base_of_indep (hIs : M.Spanning I) (hI : M.Indep I) : M.Base I := hI.base_of_spanning hIs +lemma Indep.eq_of_spanning_subset (hI : M.Indep I) (hS : M.Spanning S) (hSI : S ⊆ I) : S = I := + ((hI.subset hSI).base_of_spanning hS).eq_of_subset_indep hI hSI + +lemma Basis.spanning_iff_spanning (hIX : M.Basis I X) : M.Spanning I ↔ M.Spanning X := by + rw [spanning_iff_closure_eq, spanning_iff_closure_eq, hIX.closure_eq_closure] + +lemma Spanning.base_restrict_iff (hS : M.Spanning S) : (M ↾ S).Base B ↔ M.Base B ∧ B ⊆ S := by + rw [base_restrict_iff', basis'_iff_basis] + refine ⟨fun h ↦ ⟨?_, h.subset⟩, fun h ↦ h.1.indep.basis_of_subset_of_subset_closure h.2 ?_⟩ + · exact h.indep.base_of_spanning <| by rwa [h.spanning_iff_spanning] + rw [h.1.closure_eq] + exact hS.subset_ground + +lemma Spanning.compl_coindep (hS : M.Spanning S) : M.Coindep (M.E \ S) := by + rwa [← spanning_iff_compl_coindep] + +lemma Basis.base_of_spanning (hIX : M.Basis I X) (hX : M.Spanning X) : M.Base I := + hIX.indep.base_of_spanning <| by rwa [hIX.spanning_iff_spanning] + +lemma Indep.exists_base_subset_spanning (hI : M.Indep I) (hS : M.Spanning S) (hIS : I ⊆ S) : + ∃ B, M.Base B ∧ I ⊆ B ∧ B ⊆ S := by + obtain ⟨B, hB⟩ := hI.subset_basis_of_subset hIS + exact ⟨B, hB.1.base_of_spanning hS, hB.2, hB.1.subset⟩ + +lemma Restriction.base_iff_of_spanning {N : Matroid α} (hR : N ≤r M) (hN : M.Spanning N.E) : + N.Base B ↔ (M.Base B ∧ B ⊆ N.E) := by + obtain ⟨R, hR : R ⊆ M.E, rfl⟩ := hR + rw [Spanning.base_restrict_iff (show M.Spanning R from hN), restrict_ground_eq] + lemma ext_spanning {M M' : Matroid α} (h : M.E = M'.E) (hsp : ∀ S, S ⊆ M.E → (M.Spanning S ↔ M'.Spanning S )) : M = M' := by have hsp' : M.Spanning = M'.Spanning := by @@ -753,5 +849,98 @@ lemma ext_spanning {M M' : Matroid α} (h : M.E = M'.E) end Spanning +section Constructions + +variable {R S : Set α} + +@[simp] lemma restrict_closure_eq' (M : Matroid α) (X R : Set α) : + (M ↾ R).closure X = (M.closure (X ∩ R) ∩ R) ∪ (R \ M.E) := by + obtain ⟨I, hI⟩ := (M ↾ R).exists_basis' X + obtain ⟨hI', hIR⟩ := basis'_restrict_iff.1 hI + ext e + rw [← hI.closure_eq_closure, ← hI'.closure_eq_closure, hI.indep.mem_closure_iff', mem_union, + mem_inter_iff, hI'.indep.mem_closure_iff', restrict_ground_eq, restrict_indep_iff, mem_diff] + by_cases he : M.Indep (insert e I) + · simp [he, and_comm, insert_subset_iff, hIR, (he.subset_ground (mem_insert ..)), imp_or] + tauto + +lemma restrict_closure_eq (M : Matroid α) (hXR : X ⊆ R) (hR : R ⊆ M.E := by aesop_mat) : + (M ↾ R).closure X = M.closure X ∩ R := by + rw [restrict_closure_eq', diff_eq_empty.mpr hR, union_empty, inter_eq_self_of_subset_left hXR] + +@[simp] lemma emptyOn_closure_eq (X : Set α) : (emptyOn α).closure X = ∅ := + (closure_subset_ground ..).antisymm <| empty_subset _ + +@[simp] lemma loopyOn_closure_eq (E X : Set α) : (loopyOn E).closure X = E := by + simp [loopyOn, restrict_closure_eq'] + +@[simp] lemma loopyOn_spanning_iff {E : Set α} : (loopyOn E).Spanning X ↔ X ⊆ E := by + rw [spanning_iff, loopyOn_closure_eq, loopyOn_ground, and_iff_right rfl] + +@[simp] lemma freeOn_closure_eq (E X : Set α) : (freeOn E).closure X = X ∩ E := by + simp (config := {contextual := true}) [← closure_inter_ground _ X, Set.ext_iff, and_comm, + insert_subset_iff, freeOn_indep_iff, (freeOn_indep inter_subset_right).mem_closure_iff'] + +@[simp] lemma uniqueBaseOn_closure_eq (I E X : Set α) : + (uniqueBaseOn I E).closure X = (X ∩ I ∩ E) ∪ (E \ I) := by + rw [uniqueBaseOn, restrict_closure_eq', freeOn_closure_eq, inter_right_comm, + inter_assoc (c := E), inter_self, inter_right_comm, freeOn_ground] + +lemma closure_empty_eq_ground_iff : M.closure ∅ = M.E ↔ M = loopyOn M.E := by + refine ⟨fun h ↦ ext_closure ?_, fun h ↦ by rw [h, loopyOn_closure_eq, loopyOn_ground]⟩ + refine fun X ↦ subset_antisymm (by simp [closure_subset_ground]) ?_ + rw [loopyOn_closure_eq, ← h] + exact M.closure_mono (empty_subset _) + +@[simp] lemma comap_closure_eq {β : Type*} (M : Matroid β) (f : α → β) (X : Set α) : + (M.comap f).closure X = f ⁻¹' M.closure (f '' X) := by + -- Use a choice of basis and extensionality to change the goal to a statement about independence. + obtain ⟨I, hI⟩ := (M.comap f).exists_basis' X + obtain ⟨hI', hIinj, -⟩ := comap_basis'_iff.1 hI + simp_rw [← hI.closure_eq_closure, ← hI'.closure_eq_closure, Set.ext_iff, + hI.indep.mem_closure_iff', comap_ground_eq, mem_preimage, hI'.indep.mem_closure_iff', + comap_indep_iff, and_imp, mem_image, and_congr_right_iff, ← image_insert_eq] + -- the lemma now easily follows by considering elements/non-elements of `I` separately. + intro x hxE + by_cases hxI : x ∈ I + · simp [hxI, show ∃ y ∈ I, f y = f x from ⟨x, hxI, rfl⟩] + simp [hxI, injOn_insert hxI, hIinj] + +@[simp] lemma map_closure_eq {β : Type*} (M : Matroid α) (f : α → β) (hf) (X : Set β) : + (M.map f hf).closure X = f '' M.closure (f ⁻¹' X) := by + -- It is enough to prove that `map` and `closure` commute for `M`-independent sets. + suffices aux : ∀ ⦃I⦄, M.Indep I → (M.map f hf).closure (f '' I) = f '' (M.closure I) by + obtain ⟨I, hI⟩ := M.exists_basis (f ⁻¹' X ∩ M.E) + rw [← closure_inter_ground, map_ground, ← M.closure_inter_ground, ← hI.closure_eq_closure, + ← aux hI.indep, ← image_preimage_inter, ← (hI.map hf).closure_eq_closure] + -- Let `I` be independent, and transform the goal using closure/independence lemmas + refine fun I hI ↦ Set.ext fun e ↦ ?_ + simp only [(hI.map f hf).mem_closure_iff', map_ground, mem_image, map_indep_iff, + forall_exists_index, and_imp, hI.mem_closure_iff'] + -- The goal now easily follows from the invariance of independence under maps. + constructor + · rintro ⟨⟨x, hxE, rfl⟩, h2⟩ + refine ⟨x, ⟨hxE, fun hI' ↦ ?_⟩, rfl⟩ + obtain ⟨y, hyI, hfy⟩ := h2 _ hI' image_insert_eq.symm + rw [hf.eq_iff (hI.subset_ground hyI) hxE] at hfy + rwa [← hfy] + rintro ⟨x, ⟨hxE, hxi⟩, rfl⟩ + refine ⟨⟨x, hxE, rfl⟩, fun J hJ hJI ↦ ⟨x, hxi ?_, rfl⟩⟩ + replace hJ := hJ.map f hf + have hrw := image_insert_eq ▸ hJI + rwa [← hrw, map_image_indep_iff (insert_subset hxE hI.subset_ground)] at hJ + +lemma restrict_spanning_iff (hSR : S ⊆ R) (hR : R ⊆ M.E := by aesop_mat) : + (M ↾ R).Spanning S ↔ R ⊆ M.closure S := by + rw [spanning_iff, restrict_ground_eq, and_iff_left hSR, restrict_closure_eq _ hSR, inter_eq_right] + +lemma restrict_spanning_iff' : (M ↾ R).Spanning S ↔ R ∩ M.E ⊆ M.closure S ∧ S ⊆ R := by + rw [spanning_iff, restrict_closure_eq', restrict_ground_eq, and_congr_left_iff, + diff_eq_compl_inter, ← union_inter_distrib_right, inter_eq_right, union_comm, + ← diff_subset_iff, diff_compl] + intro hSR + rw [inter_eq_self_of_subset_left hSR] + +end Constructions end Matroid From 3f9f891a7ac31707956966ceb7dfa4c64c9ec0ce Mon Sep 17 00:00:00 2001 From: damiano Date: Sat, 25 Jan 2025 18:15:47 +0000 Subject: [PATCH 523/681] chore: add Kerodon tags (#21048) --- Mathlib/AlgebraicTopology/Quasicategory/Basic.lean | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Mathlib/AlgebraicTopology/Quasicategory/Basic.lean b/Mathlib/AlgebraicTopology/Quasicategory/Basic.lean index c322b54925ac3..fcfb94843d7c4 100644 --- a/Mathlib/AlgebraicTopology/Quasicategory/Basic.lean +++ b/Mathlib/AlgebraicTopology/Quasicategory/Basic.lean @@ -31,8 +31,8 @@ open CategoryTheory Simplicial /-- A simplicial set `S` is a *quasicategory* if it satisfies the following horn-filling condition: for every `n : ℕ` and `0 < i < n`, every map of simplicial sets `σ₀ : Λ[n, i] → S` can be extended to a map `σ : Δ[n] → S`. - -[Kerodon, 003A] -/ +-/ +@[kerodon 003A] class Quasicategory (S : SSet) : Prop where hornFilling' : ∀ ⦃n : ℕ⦄ ⦃i : Fin (n+3)⦄ (σ₀ : Λ[n+2, i] ⟶ S) (_h0 : 0 < i) (_hn : i < Fin.last (n+2)), @@ -50,9 +50,8 @@ lemma Quasicategory.hornFilling {S : SSet} [Quasicategory S] ⦃n : ℕ⦄ ⦃i simp [hn] at h0 | succ n => exact Quasicategory.hornFilling' σ₀ h0 hn -/-- Every Kan complex is a quasicategory. - -[Kerodon, 003C] -/ +/-- Every Kan complex is a quasicategory. -/ +@[kerodon 003C] instance (S : SSet) [KanComplex S] : Quasicategory S where hornFilling' _ _ σ₀ _ _ := KanComplex.hornFilling σ₀ From 4591fe148a16f331e6c61956634f9f9210c5b4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sat, 25 Jan 2025 18:48:35 +0000 Subject: [PATCH 524/681] chore: namespace `comap_swap` (#21061) From PFR --- Mathlib/MeasureTheory/Measure/Comap.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/MeasureTheory/Measure/Comap.lean b/Mathlib/MeasureTheory/Measure/Comap.lean index 457a53c721731..e9f8da9f066b3 100644 --- a/Mathlib/MeasureTheory/Measure/Comap.lean +++ b/Mathlib/MeasureTheory/Measure/Comap.lean @@ -173,5 +173,5 @@ lemma map_symm {μ : Measure α} (e : β ≃ᵐ α) : μ.map e.symm = μ.comap e end MeasurableEquiv -lemma comap_swap (μ : Measure (α × β)) : μ.comap Prod.swap = μ.map Prod.swap := +lemma MeasureTheory.Measure.comap_swap (μ : Measure (α × β)) : μ.comap .swap = μ.map .swap := (MeasurableEquiv.prodComm ..).comap_symm From 4b33aedfed17acf4c72c34b3112f9da2dad0d7b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 25 Jan 2025 21:57:52 +0000 Subject: [PATCH 525/681] feat(CategoryTheory): accessible functors and presentable objects (#19937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR introduces the notions of accessible functors and of presentable objects. An object `X` in a category is `κ`-presentable (for `κ` a regular cardinal) if the functor `Hom(X, -)` commutes with colimits indexed by `κ`-filtered categories. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + Mathlib/CategoryTheory/Presentable/Basic.lean | 126 ++++++++++++++++++ .../Presentable/IsCardinalFiltered.lean | 5 + docs/references.bib | 15 +++ 4 files changed, 147 insertions(+) create mode 100644 Mathlib/CategoryTheory/Presentable/Basic.lean diff --git a/Mathlib.lean b/Mathlib.lean index 8759b1dc6f015..a8987b6f88349 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2146,6 +2146,7 @@ import Mathlib.CategoryTheory.Preadditive.Yoneda.Basic import Mathlib.CategoryTheory.Preadditive.Yoneda.Injective import Mathlib.CategoryTheory.Preadditive.Yoneda.Limits import Mathlib.CategoryTheory.Preadditive.Yoneda.Projective +import Mathlib.CategoryTheory.Presentable.Basic import Mathlib.CategoryTheory.Presentable.IsCardinalFiltered import Mathlib.CategoryTheory.Products.Associator import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Presentable/Basic.lean b/Mathlib/CategoryTheory/Presentable/Basic.lean new file mode 100644 index 0000000000000..0ffacc86a36fc --- /dev/null +++ b/Mathlib/CategoryTheory/Presentable/Basic.lean @@ -0,0 +1,126 @@ +/- +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.CategoryTheory.Filtered.Basic +import Mathlib.CategoryTheory.Limits.Preserves.Basic +import Mathlib.CategoryTheory.Presentable.IsCardinalFiltered +import Mathlib.SetTheory.Cardinal.Cofinality +import Mathlib.SetTheory.Cardinal.HasCardinalLT + +/-! # Presentable objects + +A functor `F : C ⥤ D` is `κ`-accessible (`Functor.IsCardinalAccessible`) +if it commutes with colimits of shape `J` where `J` is any `κ`-filtered category +(that is essentially small relative to the universe `w` such that `κ : Cardinal.{w}`.). +We also introduce another typeclass `Functor.IsAccessible` saying that there exists +a regular cardinal `κ` such that `Functor.IsCardinalAccessible`. + +An object `X` of a category is `κ`-presentable (`IsCardinalPresentable`) +if the functor `Hom(X, _)` (i.e. `coyoneda.obj (op X)`) is `κ`-accessible. +Similar as for accessible functors, we define a type class `IsAccessible`. + +## References +* [Adámek, J. and Rosický, J., *Locally presentable and accessible categories*][Adamek_Rosicky_1994] + +-/ + +universe w w' v'' v' v u'' u' u + +namespace CategoryTheory + +open Limits Opposite + +variable {C : Type u} [Category.{v} C] {D : Type u'} [Category.{v'} D] + +namespace Functor + +variable (F G : C ⥤ D) (e : F ≅ G) (κ : Cardinal.{w}) [Fact κ.IsRegular] + +/-- A functor `F : C ⥤ D` is `κ`-accessible (with `κ` a regular cardinal) +if it preserves colimits of shape `J` where `J` is any `κ`-filtered category. +In the mathematical literature, some assumptions are often made on the +categories `C` or `D` (e.g. the existence of `κ`-filtered colimits, +see `HasCardinalFilteredColimits` below), but here we do not +make such assumptions. -/ +class IsCardinalAccessible : Prop where + preservesColimitOfShape (J : Type w) [SmallCategory J] [IsCardinalFiltered J κ] : + PreservesColimitsOfShape J F + +lemma preservesColimitsOfShape_of_isCardinalAccessible [F.IsCardinalAccessible κ] + (J : Type w) [SmallCategory J] [IsCardinalFiltered J κ] : + PreservesColimitsOfShape J F := + IsCardinalAccessible.preservesColimitOfShape κ _ + +lemma preservesColimitsOfShape_of_isCardinalAccessible_of_essentiallySmall + [F.IsCardinalAccessible κ] + (J : Type u'') [Category.{v''} J] [EssentiallySmall.{w} J] [IsCardinalFiltered J κ] : + PreservesColimitsOfShape J F := by + have := IsCardinalFiltered.of_equivalence κ (equivSmallModel.{w} J) + have := F.preservesColimitsOfShape_of_isCardinalAccessible κ (SmallModel.{w} J) + exact preservesColimitsOfShape_of_equiv (equivSmallModel.{w} J).symm F + +variable {κ} in +lemma isCardinalAccessible_of_le + [F.IsCardinalAccessible κ] {κ' : Cardinal.{w}} [Fact κ'.IsRegular] (h : κ ≤ κ') : + F.IsCardinalAccessible κ' where + preservesColimitOfShape {J _ _} := by + have := IsCardinalFiltered.of_le J h + exact F.preservesColimitsOfShape_of_isCardinalAccessible κ J + +include e in +variable {F G} in +lemma isCardinalAccessible_of_natIso [F.IsCardinalAccessible κ] : G.IsCardinalAccessible κ where + preservesColimitOfShape J _ hκ := by + have := F.preservesColimitsOfShape_of_isCardinalAccessible κ J + exact preservesColimitsOfShape_of_natIso e + +end Functor + +variable (X : C) (Y : C) (e : X ≅ Y) (κ : Cardinal.{w}) [Fact κ.IsRegular] + +/-- An object `X` in a category is `κ`-presentable (for `κ` a regular cardinal) +when the functor `Hom(X, _)` preserves colimits indexed by +`κ`-filtered categories. -/ +abbrev IsCardinalPresentable : Prop := (coyoneda.obj (op X)).IsCardinalAccessible κ + +lemma preservesColimitsOfShape_of_isCardinalPresentable [IsCardinalPresentable X κ] + (J : Type w) [SmallCategory.{w} J] [IsCardinalFiltered J κ] : + PreservesColimitsOfShape J (coyoneda.obj (op X)) := + (coyoneda.obj (op X)).preservesColimitsOfShape_of_isCardinalAccessible κ J + +lemma preservesColimitsOfShape_of_isCardinalPresentable_of_essentiallySmall + [IsCardinalPresentable X κ] + (J : Type u'') [Category.{v''} J] [EssentiallySmall.{w} J] [IsCardinalFiltered J κ] : + PreservesColimitsOfShape J (coyoneda.obj (op X)) := + (coyoneda.obj (op X)).preservesColimitsOfShape_of_isCardinalAccessible_of_essentiallySmall κ J + +variable {κ} in +lemma isCardinalPresentable_of_le [IsCardinalPresentable X κ] + {κ' : Cardinal.{w}} [Fact κ'.IsRegular] (h : κ ≤ κ') : + IsCardinalPresentable X κ' := + (coyoneda.obj (op X)).isCardinalAccessible_of_le h + +include e in +variable {X Y} in +lemma isCardinalPresentable_of_iso [IsCardinalPresentable X κ] : IsCardinalPresentable Y κ := + Functor.isCardinalAccessible_of_natIso (coyoneda.mapIso e.symm.op) κ + +section + +variable (C) (κ : Cardinal.{w}) [Fact κ.IsRegular] + +/-- A category has `κ`-filtered colimits if it has colimits of shape `J` +for any `κ`-filtered category `J`. -/ +class HasCardinalFilteredColimits : Prop where + hasColimitsOfShape (J : Type w) [SmallCategory J] [IsCardinalFiltered J κ] : + HasColimitsOfShape J C := by intros; infer_instance + +attribute [instance] HasCardinalFilteredColimits.hasColimitsOfShape + +instance [HasColimitsOfSize.{w, w} C] : HasCardinalFilteredColimits.{w} C κ where + +end + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean b/Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean index 4898f232f020f..ae10f8303d505 100644 --- a/Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean +++ b/Mathlib/CategoryTheory/Presentable/IsCardinalFiltered.lean @@ -70,6 +70,11 @@ lemma of_le {κ' : Cardinal.{w}} [Fact κ'.IsRegular] (h : κ' ≤ κ) : IsCardinalFiltered J κ' where nonempty_cocone F hA := ⟨cocone F (hA.of_le h)⟩ +variable (κ) in +lemma of_equivalence {J' : Type u'} [Category.{v'} J'] (e : J ≌ J') : + IsCardinalFiltered J' κ where + nonempty_cocone F hA := ⟨e.inverse.mapCoconeInv (cocone (F ⋙ e.inverse) hA)⟩ + section max variable {K : Type u'} (S : K → J) (hS : HasCardinalLT K κ) diff --git a/docs/references.bib b/docs/references.bib index 50eba91c9488f..817246b9e23f7 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -21,6 +21,21 @@ @Book{ abramsky_gabbay_maibaum_1994 zbl = {0829.68111} } +@Book{ Adamek_Rosicky_1994, + author = {Adámek, Jiří and Rosický, Jiří}, + title = {Locally presentable and accessible categories}, + series = {London Mathematical Society Lecture Note Series}, + volume = {189}, + publisher = {Cambridge University Press, Cambridge}, + year = {1994}, + pages = {xiv+316}, + isbn = {0-521-42261-2}, + mrclass = {18Axx (18-02)}, + mrnumber = {1294136}, + doi = {10.1017/CBO9780511600579}, + url = {https://doi.org/10.1017/CBO9780511600579} +} + @Book{ Adamek_Rosicky_Vitale_2010, place = {Cambridge}, series = {Cambridge Tracts in Mathematics}, From e137b58ed6ad560e505447661f014af4d047077e Mon Sep 17 00:00:00 2001 From: Christopher Hoskin Date: Sat, 25 Jan 2025 23:10:10 +0000 Subject: [PATCH 526/681] feat: add `QuadraticMap.associated_tmul` and thus golf `QuadraticForm.associated_tmul` (#20177) Co-authored-by: Oliver Nash Co-authored-by: Oliver Nash <7734364+ocfnash@users.noreply.github.com> --- .../BilinearForm/TensorProduct.lean | 14 ++++++++ .../LinearAlgebra/QuadraticForm/Basic.lean | 19 ++++++----- .../QuadraticForm/TensorProduct.lean | 33 ++++++++----------- Mathlib/LinearAlgebra/SesquilinearForm.lean | 13 ++++---- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean b/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean index 6d38ee83cd9d5..ebb2c333b7633 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean @@ -70,6 +70,16 @@ protected abbrev tmul (B₁ : BilinMap A M₁ N₁) (B₂ : BilinMap R M₂ N₂ BilinMap A (M₁ ⊗[R] M₂) (N₁ ⊗[R] N₂) := tensorDistrib R A (B₁ ⊗ₜ[R] B₂) +attribute [local ext] TensorProduct.ext in +/-- A tensor product of symmetric bilinear maps is symmetric. -/ +lemma tmul_isSymm {B₁ : BilinMap A M₁ N₁} {B₂ : BilinMap R M₂ N₂} + (hB₁ : ∀ x y, B₁ x y = B₁ y x) (hB₂ : ∀ x y, B₂ x y = B₂ y x) + (x y : M₁ ⊗[R] M₂) : + B₁.tmul B₂ x y = B₁.tmul B₂ y x := by + revert x y + rw [isSymm_iff_eq_flip] + aesop + variable (A) in /-- The base change of a bilinear map (also known as "extension of scalars"). -/ protected def baseChange (B : BilinMap R M₂ N₂) : BilinMap A (A ⊗[R] M₂) (A ⊗[R] N₂) := @@ -81,6 +91,10 @@ theorem baseChange_tmul (B₂ : BilinMap R M₂ N₂) (a : A) (m₂ : M₂) B₂.baseChange A (a ⊗ₜ m₂) (a' ⊗ₜ m₂') = (a * a') ⊗ₜ (B₂ m₂ m₂') := rfl +lemma baseChange_isSymm {B₂ : BilinMap R M₂ N₂} (hB₂ : ∀ x y, B₂ x y = B₂ y x) (x y : A ⊗[R] M₂) : + B₂.baseChange A x y = B₂.baseChange A y x := + tmul_isSymm mul_comm hB₂ x y + end BilinMap namespace BilinForm diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean index 9778e86170c13..893c99b52d4fa 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean @@ -896,9 +896,13 @@ theorem associated_apply (x y : M) : rw [← LinearMap.smul_apply, nsmul_eq_mul, Nat.cast_ofNat, mul_invOf_self', LinearMap.one_apply, polar] -theorem associated_isSymm (Q : QuadraticForm R M) [Invertible (2 : R)] : - (associatedHom S Q).IsSymm := fun x y ↦ by - simp only [associated_apply, sub_eq_add_neg, add_assoc, RingHom.id_apply, add_comm, add_left_comm] +theorem associated_isSymm (Q : QuadraticMap R M N) (x y : M) : + associatedHom S Q x y = associatedHom S Q y x := by + simp only [associated_apply, sub_eq_add_neg, add_assoc, add_comm, add_left_comm] + +theorem _root_.QuadraticForm.associated_isSymm (Q : QuadraticForm R M) [Invertible (2 : R)] : + (associatedHom S Q).IsSymm := + QuadraticMap.associated_isSymm S Q /-- A version of `QuadraticMap.associated_isSymm` for general targets (using `flip` because `IsSymm` does not apply here). -/ @@ -919,11 +923,10 @@ theorem associated_toQuadraticMap (B : BilinMap R M N) (x y : M) : LinearMap.smul_def, _root_.map_sub] abel_nf -theorem associated_left_inverse [Invertible (2 : R)] {B₁ : BilinMap R M R} (h : B₁.IsSymm) : +theorem associated_left_inverse {B₁ : BilinMap R M N} (h : ∀ x y, B₁ x y = B₁ y x) : associatedHom S B₁.toQuadraticMap = B₁ := LinearMap.ext₂ fun x y ↦ by - rw [associated_toQuadraticMap, ← h.eq x y, RingHom.id_apply, ← two_mul, ← smul_eq_mul, - invOf_smul_eq_iff, two_smul, two_smul] + rw [associated_toQuadraticMap, ← h x y, ← two_smul R, invOf_smul_eq_iff, two_smul, two_smul] /-- A version of `QuadraticMap.associated_left_inverse` for general targets. -/ lemma associated_left_inverse' {B₁ : BilinMap R M N} (hB₁ : B₁.flip = B₁) : @@ -1190,10 +1193,10 @@ theorem QuadraticMap.toMatrix'_smul (a : R) (Q : QuadraticMap R (n → R) R) : (a • Q).toMatrix' = a • Q.toMatrix' := by simp only [toMatrix', LinearEquiv.map_smul, LinearMap.map_smul] -theorem QuadraticMap.isSymm_toMatrix' (Q : QuadraticMap R (n → R) R) : Q.toMatrix'.IsSymm := by +theorem QuadraticMap.isSymm_toMatrix' (Q : QuadraticForm R (n → R)) : Q.toMatrix'.IsSymm := by ext i j rw [toMatrix', Matrix.transpose_apply, LinearMap.toMatrix₂'_apply, LinearMap.toMatrix₂'_apply, - ← associated_isSymm, RingHom.id_apply, associated_apply] + ← associated_isSymm] end diff --git a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean index d873b9641653c..7a26465a9f79c 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean @@ -66,6 +66,15 @@ protected noncomputable abbrev tmul (Q₁ : QuadraticMap A M₁ N₁) (Q₂ : QuadraticMap R M₂ N₂) : QuadraticMap A (M₁ ⊗[R] M₂) (N₁ ⊗[R] N₂) := tensorDistrib R A (Q₁ ⊗ₜ[R] Q₂) +theorem associated_tmul [Invertible (2 : A)] + (Q₁ : QuadraticMap A M₁ N₁) (Q₂ : QuadraticMap R M₂ N₂) : + (Q₁.tmul Q₂).associated = Q₁.associated.tmul Q₂.associated := by + letI : Invertible (2 : A) := (Invertible.map (algebraMap R A) 2).copy 2 (map_ofNat _ _).symm + rw [QuadraticMap.tmul, BilinMap.tmul] + have : Subsingleton (Invertible (2 : A)) := inferInstance + convert associated_left_inverse A (LinearMap.BilinMap.tmul_isSymm + (QuadraticMap.associated_isSymm A Q₁) (QuadraticMap.associated_isSymm R Q₂)) + end QuadraticMap namespace QuadraticForm @@ -96,26 +105,10 @@ protected noncomputable abbrev tmul (Q₁ : QuadraticForm A M₁) (Q₂ : Quadra tensorDistrib R A (Q₁ ⊗ₜ[R] Q₂) theorem associated_tmul [Invertible (2 : A)] (Q₁ : QuadraticForm A M₁) (Q₂ : QuadraticForm R M₂) : - associated (R := A) (Q₁.tmul Q₂) - = BilinForm.tmul ((associated (R := A) Q₁)) (associated (R := R) Q₂) := by - letI : Invertible (2 : A) := (Invertible.map (algebraMap R A) 2).copy 2 (map_ofNat _ _).symm - /- Previously `QuadraticForm.tensorDistrib` was defined in a similar way to - `QuadraticMap.tensorDistrib`. We now obtain the definition of `QuadraticForm.tensorDistrib` - from `QuadraticMap.tensorDistrib` using `A ⊗[R] R ≃ₗ[A] A`. Hypothesis `e1` below shows that the - new definition is equal to the old, and allows us to reuse the old proof. - - TODO: Define `IsSymm` for bilinear maps and generalise this result to Quadratic Maps. - -/ - have e1: (BilinMap.toQuadraticMapLinearMap A A (M₁ ⊗[R] M₂) ∘ - BilinForm.tensorDistrib R A (M₁ := M₁) (M₂ := M₂) ∘ - AlgebraTensorModule.map - (QuadraticMap.associated : QuadraticForm A M₁ →ₗ[A] BilinForm A M₁) - (QuadraticMap.associated : QuadraticForm R M₂ →ₗ[R] BilinForm R M₂)) = - tensorDistrib R A := rfl - rw [QuadraticForm.tmul, ← e1, BilinForm.tmul] - dsimp - have : Subsingleton (Invertible (2 : A)) := inferInstance - convert associated_left_inverse A ((associated_isSymm A Q₁).tmul (associated_isSymm R Q₂)) + (Q₁.tmul Q₂).associated = BilinForm.tmul Q₁.associated Q₂.associated := by + rw [BilinForm.tmul, BilinForm.tensorDistrib, LinearMap.comp_apply, ← BilinMap.tmul, + ← QuadraticMap.associated_tmul Q₁ Q₂] + aesop theorem polarBilin_tmul [Invertible (2 : A)] (Q₁ : QuadraticForm A M₁) (Q₂ : QuadraticForm R M₂) : polarBilin (Q₁.tmul Q₂) = ⅟(2 : A) • BilinForm.tmul (polarBilin Q₁) (polarBilin Q₂) := by diff --git a/Mathlib/LinearAlgebra/SesquilinearForm.lean b/Mathlib/LinearAlgebra/SesquilinearForm.lean index a3423723021fe..8657bbed12d1d 100644 --- a/Mathlib/LinearAlgebra/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/SesquilinearForm.lean @@ -213,13 +213,12 @@ end IsSymm @[simp] theorem isSymm_zero : (0 : M →ₛₗ[I] M →ₗ[R] R).IsSymm := fun _ _ => map_zero _ -theorem isSymm_iff_eq_flip {B : LinearMap.BilinForm R M} : B.IsSymm ↔ B = B.flip := by - constructor <;> intro h - · ext - rw [← h, flip_apply, RingHom.id_apply] - intro x y - conv_lhs => rw [h] - rfl +theorem BilinMap.isSymm_iff_eq_flip {N : Type*} [AddCommMonoid N] [Module R N] + {B : LinearMap.BilinMap R M N} : (∀ x y, B x y = B y x) ↔ B = B.flip := by + simp [LinearMap.ext_iff₂] + +theorem isSymm_iff_eq_flip {B : LinearMap.BilinForm R M} : B.IsSymm ↔ B = B.flip := + BilinMap.isSymm_iff_eq_flip end Symmetric From dd4bdae78bef2da5ab879ffc6def75f1ae62634c Mon Sep 17 00:00:00 2001 From: leanprover-community-bot-assistant Date: Sun, 26 Jan 2025 00:16:15 +0000 Subject: [PATCH 527/681] chore(scripts): update nolints.json (#21070) I am happy to remove some nolints for you! --- scripts/nolints.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/nolints.json b/scripts/nolints.json index 208e5531b4cd5..d52df230c4996 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -235,8 +235,6 @@ ["docBlame", "PowerBasis.gen"], ["docBlame", "Pretrivialization.baseSet"], ["docBlame", "PrimeSpectrum.asIdeal"], - ["docBlame", "ProbabilityTheory.«termEVar[_]»"], - ["docBlame", "ProbabilityTheory.«termVar[_]»"], ["docBlame", "ProbabilityTheory.«term_=ₐₛ_»"], ["docBlame", "ProbabilityTheory.«term_≤ₐₛ_»"], ["docBlame", "ProbabilityTheory.«term_⟦_|_⟧»"], From e1a3d4c7b6d3d3110719a674111f9e137a6b82be Mon Sep 17 00:00:00 2001 From: Gabriel Ebner Date: Sun, 26 Jan 2025 00:57:35 +0000 Subject: [PATCH 528/681] feat: do not allocate heap cells for Erased (#21068) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The memory representation of `Erased` used to be a heap cell, because `Erased` is defined in terms of `PSigma`. If we define `Erased` as a subtype of a predicate instead, then the compiler will erase values of type `Erased`. Unfortunately, this does not work for ghost fields in structures (yet). The structure will still contain a field for the ghost value, but at least it will be the scalar zero now. But I suspect it would be fairly small diff to fix this in core. ```lean structure Demo where a : Erased Nat b : Erased Nat set_option trace.compiler.ir.result true in def foo : Demo where a := .mk 42; b := .mk 8 ``` Before: ``` [result] def foo._closed_1 : obj := let x_1 : obj := ctor_0[PSigma.mk] ◾ ◾; inc x_1; let x_2 : obj := ctor_0[Demo.mk] x_1 x_1; ret x_2 def foo : obj := let x_1 : obj := foo._closed_1; ret x_1 ``` After: ``` [result] def foo : obj := let x_1 : obj := ctor_0[Demo.mk] ◾ ◾; ret x_1 ``` @digama0 This is what I was suggesting earlier this week. --- Mathlib/Data/Erased.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Data/Erased.lean b/Mathlib/Data/Erased.lean index 6460d80645efa..b1b6a212314a3 100644 --- a/Mathlib/Data/Erased.lean +++ b/Mathlib/Data/Erased.lean @@ -21,7 +21,7 @@ universe u and proofs. This can be used to track data without storing it literally. -/ def Erased (α : Sort u) : Sort max 1 u := - Σ's : α → Prop, ∃ a, (fun b => a = b) = s + { s : α → Prop // ∃ a, (a = ·) = s } namespace Erased From 1844f029a2fd418595badb7be8d8967e20f65570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 26 Jan 2025 04:42:47 +0000 Subject: [PATCH 529/681] =?UTF-8?q?feat:=20`a=20^=20b=20=E2=89=A4=20?= =?UTF-8?q?=E2=84=B5=E2=82=80`=20if=20`a=20=E2=89=A4=20=E2=84=B5=E2=82=80`?= =?UTF-8?q?=20and=20`b=20<=20=E2=84=B5=E2=82=80`=20(#21060)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From PFR The corresponding `Cardinal.power_lt_aleph0` already exists. Co-authored-by: Sébastien Gouëzel --- Mathlib/SetTheory/Cardinal/Arithmetic.lean | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mathlib/SetTheory/Cardinal/Arithmetic.lean b/Mathlib/SetTheory/Cardinal/Arithmetic.lean index 089e73efbad75..be256f0f972f9 100644 --- a/Mathlib/SetTheory/Cardinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Cardinal/Arithmetic.lean @@ -527,6 +527,9 @@ theorem power_nat_le_max {c : Cardinal.{u}} {n : ℕ} : c ^ (n : Cardinal.{u}) · exact le_max_of_le_left (power_nat_le hc) · exact le_max_of_le_right (power_lt_aleph0 hc (nat_lt_aleph0 _)).le +lemma power_le_aleph0 {a b : Cardinal.{u}} (ha : a ≤ ℵ₀) (hb : b < ℵ₀) : a ^ b ≤ ℵ₀ := by + lift b to ℕ using hb; simpa [ha] using power_nat_le_max (c := a) + theorem powerlt_aleph0 {c : Cardinal} (h : ℵ₀ ≤ c) : c ^< ℵ₀ = c := by apply le_antisymm · rw [powerlt_le] From 771b149b16b1e19b8833b746961be8107de599bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 26 Jan 2025 04:59:02 +0000 Subject: [PATCH 530/681] feat: `log (x / x) = 0` (#21056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From PFR Co-authored-by: Sébastien Gouëzel --- Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean | 7 +++++-- Mathlib/Analysis/SpecialFunctions/Complex/Log.lean | 3 +++ Mathlib/Analysis/SpecialFunctions/Log/Basic.lean | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean index 1b221e58e8826..e2af86fcb1b81 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean @@ -176,8 +176,11 @@ theorem arg_eq_arg_iff {x y : ℂ} (hx : x ≠ 0) (hy : y ≠ 0) : rw [← ofReal_div, arg_real_mul] exact div_pos (abs.pos hy) (abs.pos hx) -@[simp] -theorem arg_one : arg 1 = 0 := by simp [arg, zero_le_one] +@[simp] lemma arg_one : arg 1 = 0 := by simp [arg, zero_le_one] + +/-- This holds true for all `x : ℂ` because of the junk values `0 / 0 = 0` and `arg 0 = 0`. -/ +@[simp] lemma arg_div_self (x : ℂ) : arg (x / x) = 0 := by + obtain rfl | hx := eq_or_ne x 0 <;> simp [*] @[simp] theorem arg_neg_one : arg (-1) = π := by simp [arg, le_refl, not_le.2 (zero_lt_one' ℝ)] diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean index 36a17281d89b1..34903e135a74d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean @@ -93,6 +93,9 @@ theorem log_zero : log 0 = 0 := by simp [log] @[simp] theorem log_one : log 1 = 0 := by simp [log] +/-- This holds true for all `x : ℂ` because of the junk values `0 / 0 = 0` and `log 0 = 0`. -/ +@[simp] lemma log_div_self (x : ℂ) : log (x / x) = 0 := by simp [log] + theorem log_neg_one : log (-1) = π * I := by simp [log] theorem log_I : log I = π / 2 * I := by simp [log] diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean index 3091ec96f13d0..3944edf91c60c 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean @@ -86,6 +86,10 @@ theorem log_zero : log 0 = 0 := theorem log_one : log 1 = 0 := exp_injective <| by rw [exp_log zero_lt_one, exp_zero] +/-- This holds true for all `x : \` because of the junk values `0 / 0 = 0` and `arg 0 = 0`. -/ +@[simp] lemma log_div_self (x : ℝ) : log (x / x) = 0 := by + obtain rfl | hx := eq_or_ne x 0 <;> simp [*] + @[simp] theorem log_abs (x : ℝ) : log |x| = log x := by by_cases h : x = 0 From c774a9c24d10356bcdf7d4bb6285c8bd5ad68c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Sun, 26 Jan 2025 06:03:10 +0000 Subject: [PATCH 531/681] feat(SetTheory/Cardinal/Arithmetic): omega ordinals are additively/multiplicatively principal (#18778) --- Mathlib/SetTheory/Cardinal/Arithmetic.lean | 42 +++++++++++++++++----- Mathlib/SetTheory/Ordinal/Principal.lean | 6 ---- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Mathlib/SetTheory/Cardinal/Arithmetic.lean b/Mathlib/SetTheory/Cardinal/Arithmetic.lean index be256f0f972f9..ab0045568dde8 100644 --- a/Mathlib/SetTheory/Cardinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Cardinal/Arithmetic.lean @@ -431,14 +431,6 @@ section aleph theorem aleph_add_aleph (o₁ o₂ : Ordinal) : ℵ_ o₁ + ℵ_ o₂ = ℵ_ (max o₁ o₂) := by rw [Cardinal.add_eq_max (aleph0_le_aleph o₁), aleph_max] -theorem principal_add_ord {c : Cardinal} (hc : ℵ₀ ≤ c) : Ordinal.Principal (· + ·) c.ord := - fun a b ha hb => by - rw [lt_ord, Ordinal.card_add] at * - exact add_lt_of_lt hc ha hb - -theorem principal_add_aleph (o : Ordinal) : Ordinal.Principal (· + ·) (ℵ_ o).ord := - principal_add_ord <| aleph0_le_aleph o - theorem add_right_inj_of_lt_aleph0 {α β γ : Cardinal} (γ₀ : γ < aleph0) : α + γ = β + γ ↔ α = β := ⟨fun h => Cardinal.eq_of_add_eq_add_right h γ₀, fun h => congr_arg (· + γ) h⟩ @@ -957,4 +949,38 @@ theorem principal_opow_ord {c : Cardinal} (hc : ℵ₀ ≤ c) : Principal (· ^ apply (isInitial_ord c).principal_opow rwa [omega0_le_ord] +/-! ### Initial ordinals are principal -/ + +theorem principal_add_ord {c : Cardinal} (hc : ℵ₀ ≤ c) : Principal (· + ·) c.ord := by + intro a b ha hb + rw [lt_ord, card_add] at * + exact add_lt_of_lt hc ha hb + +theorem IsInitial.principal_add {o : Ordinal} (h : IsInitial o) (ho : ω ≤ o) : + Principal (· + ·) o := by + rw [← h.ord_card] + apply principal_add_ord + rwa [aleph0_le_card] + +theorem principal_add_omega (o : Ordinal) : Principal (· + ·) (ω_ o) := + (isInitial_omega o).principal_add (omega0_le_omega o) + +theorem principal_mul_ord {c : Cardinal} (hc : ℵ₀ ≤ c) : Principal (· * ·) c.ord := by + intro a b ha hb + rw [lt_ord, card_mul] at * + exact mul_lt_of_lt hc ha hb + +theorem IsInitial.principal_mul {o : Ordinal} (h : IsInitial o) (ho : ω ≤ o) : + Principal (· * ·) o := by + rw [← h.ord_card] + apply principal_mul_ord + rwa [aleph0_le_card] + +theorem principal_mul_omega (o : Ordinal) : Principal (· * ·) (ω_ o) := + (isInitial_omega o).principal_mul (omega0_le_omega o) + +@[deprecated principal_add_omega (since := "2024-11-08")] +theorem _root_.Cardinal.principal_add_aleph (o : Ordinal) : Principal (· + ·) (ℵ_ o).ord := + principal_add_ord <| aleph0_le_aleph o + end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/Principal.lean b/Mathlib/SetTheory/Ordinal/Principal.lean index 1500096b7b3a1..f09bda8e413e2 100644 --- a/Mathlib/SetTheory/Ordinal/Principal.lean +++ b/Mathlib/SetTheory/Ordinal/Principal.lean @@ -198,9 +198,6 @@ theorem principal_add_iff_add_lt_ne_self : Principal (· + ·) a ↔ ∀ b < a, theorem principal_add_omega0 : Principal (· + ·) ω := principal_add_iff_add_left_eq_self.2 fun _ => add_omega0 -@[deprecated (since := "2024-09-30")] -alias principal_add_omega := principal_add_omega0 - theorem add_omega0_opow (h : a < ω ^ b) : a + ω ^ b = ω ^ b := by refine le_antisymm ?_ (le_add_left _ a) induction' b using limitRecOn with b _ b l IH @@ -352,9 +349,6 @@ theorem principal_mul_omega0 : Principal (· * ·) ω := fun a b ha hb => dsimp only; rw [← natCast_mul] apply nat_lt_omega0 -@[deprecated (since := "2024-09-30")] -alias principal_mul_omega := principal_mul_omega0 - theorem mul_omega0 (a0 : 0 < a) (ha : a < ω) : a * ω = ω := principal_mul_iff_mul_left_eq.1 principal_mul_omega0 a a0 ha From 24e055ffab661c2c82b4fe71b191fe8ae02def9b Mon Sep 17 00:00:00 2001 From: Stefan Kebekus Date: Sun, 26 Jan 2025 07:04:56 +0000 Subject: [PATCH 532/681] feat: mark AnalyticAt / MeromorphicAt for use with fun_prop (#21057) Mark theorems pertaining to `AnalyticAt` / `MeromorphicAt` for use with `fun_prop`. As discussed yesterday in the FLUG meeting with @TwoFX and others, I duplicated a several theorems because tactics such as `fun_prop` and `rw` cannot see that `f + g` and `fun x => f x + g x` are the same thing. I made the formulations a little more consistent, in that there is now always one theorem `AnalyticAt.add` that speaks about `f + g` and one version `AnalyticAt.add'` that speaks about `fun x => f x + g x`. This new functionality is used in [Project VD](https://github.com/kebekus/ProjectVD), which aims to formalize Value Distribution Theory for meromorphic functions on the complex plane. --- Mathlib/Analysis/Analytic/Basic.lean | 2 + Mathlib/Analysis/Analytic/Composition.lean | 13 ++++ Mathlib/Analysis/Analytic/Constructions.lean | 68 +++++++++++++++++-- Mathlib/Analysis/Analytic/IsolatedZeros.lean | 38 +++++++++++ Mathlib/Analysis/Analytic/Linear.lean | 1 + Mathlib/Analysis/Analytic/Meromorphic.lean | 61 ++++++++++++++++- .../Analysis/Calculus/FDeriv/Analytic.lean | 2 + .../SpecialFunctions/Complex/Analytic.lean | 3 + .../Analysis/SpecialFunctions/ExpDeriv.lean | 18 ++++- 9 files changed, 197 insertions(+), 9 deletions(-) diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index d770f727726f8..f607e676809c6 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -442,6 +442,7 @@ variable (𝕜) /-- Given a function `f : E → F`, we say that `f` is analytic at `x` if it admits a convergent power series expansion around `x`. -/ +@[fun_prop] def AnalyticAt (f : E → F) (x : E) := ∃ p : FormalMultilinearSeries 𝕜 E F, HasFPowerSeriesAt f p x @@ -1343,6 +1344,7 @@ protected theorem AnalyticWithinAt.continuousWithinAt (hf : AnalyticWithinAt ContinuousWithinAt f s x := hf.continuousWithinAt_insert.mono (subset_insert x s) +@[fun_prop] protected theorem AnalyticAt.continuousAt (hf : AnalyticAt 𝕜 f x) : ContinuousAt f x := let ⟨_, hp⟩ := hf hp.continuousAt diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index f7188918787a3..ae4386b4831c7 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -860,17 +860,30 @@ 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`. -/ +@[fun_prop] theorem AnalyticAt.comp {g : F → G} {f : E → F} {x : E} (hg : AnalyticAt 𝕜 g (f x)) (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (g ∘ f) x := by rw [← analyticWithinAt_univ] at hg hf ⊢ apply hg.comp hf (by simp) +/-- If two functions `g` and `f` are analytic respectively at `f x` and `x`, then `g ∘ f` is +analytic at `x`. -/ +@[fun_prop] +theorem AnalyticAt.comp' {g : F → G} {f : E → F} {x : E} (hg : AnalyticAt 𝕜 g (f x)) + (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (fun z ↦ g (f z)) x := + hg.comp hf + /-- Version of `AnalyticAt.comp` where point equality is a separate hypothesis. -/ theorem AnalyticAt.comp_of_eq {g : F → G} {f : E → F} {y : F} {x : E} (hg : AnalyticAt 𝕜 g y) (hf : AnalyticAt 𝕜 f x) (hy : f x = y) : AnalyticAt 𝕜 (g ∘ f) x := by rw [← hy] at hg exact hg.comp hf +/-- Version of `AnalyticAt.comp` where point equality is a separate hypothesis. -/ +theorem AnalyticAt.comp_of_eq' {g : F → G} {f : E → F} {y : F} {x : E} (hg : AnalyticAt 𝕜 g y) + (hf : AnalyticAt 𝕜 f x) (hy : f x = y) : AnalyticAt 𝕜 (fun z ↦ g (f z)) x := by + apply hg.comp_of_eq hf hy + theorem AnalyticAt.comp_analyticWithinAt {g : F → G} {f : E → F} {x : E} {s : Set E} (hg : AnalyticAt 𝕜 g (f x)) (hf : AnalyticWithinAt 𝕜 f s x) : AnalyticWithinAt 𝕜 (g ∘ f) s x := by diff --git a/Mathlib/Analysis/Analytic/Constructions.lean b/Mathlib/Analysis/Analytic/Constructions.lean index f56a2644814f0..a835539121144 100644 --- a/Mathlib/Analysis/Analytic/Constructions.lean +++ b/Mathlib/Analysis/Analytic/Constructions.lean @@ -46,6 +46,7 @@ theorem hasFPowerSeriesAt_const {c : F} {e : E} : HasFPowerSeriesAt (fun _ => c) (constFormalMultilinearSeries 𝕜 E c) e := ⟨⊤, hasFPowerSeriesOnBall_const⟩ +@[fun_prop] theorem analyticAt_const {v : F} {x : E} : AnalyticAt 𝕜 (fun _ => v) x := ⟨constFormalMultilinearSeries 𝕜 E v, hasFPowerSeriesAt_const⟩ @@ -100,11 +101,17 @@ theorem AnalyticWithinAt.add (hf : AnalyticWithinAt 𝕜 f s x) (hg : AnalyticWi let ⟨_, hqf⟩ := hg (hpf.add hqf).analyticWithinAt +@[fun_prop] 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 +@[fun_prop] +theorem AnalyticAt.add' (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : + AnalyticAt 𝕜 (fun z ↦ f z + g z) x := + hf.add hg + theorem HasFPowerSeriesWithinOnBall.neg (hf : HasFPowerSeriesWithinOnBall f pf s x r) : HasFPowerSeriesWithinOnBall (-f) (-pf) s x r := { r_le := by @@ -134,10 +141,15 @@ theorem AnalyticWithinAt.neg (hf : AnalyticWithinAt 𝕜 f s x) : AnalyticWithin let ⟨_, hpf⟩ := hf hpf.neg.analyticWithinAt +@[fun_prop] theorem AnalyticAt.neg (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (-f) x := let ⟨_, hpf⟩ := hf hpf.neg.analyticAt +@[fun_prop] +theorem AnalyticAt.neg' (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (fun z ↦ -f z) x := + hf.neg + 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 @@ -160,10 +172,16 @@ theorem AnalyticWithinAt.sub (hf : AnalyticWithinAt 𝕜 f s x) (hg : AnalyticWi AnalyticWithinAt 𝕜 (f - g) s x := by simpa only [sub_eq_add_neg] using hf.add hg.neg +@[fun_prop] 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 +@[fun_prop] +theorem AnalyticAt.sub' (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : + AnalyticAt 𝕜 (fun z ↦ f z - g z) x := + hf.sub hg + theorem HasFPowerSeriesWithinOnBall.const_smul (hf : HasFPowerSeriesWithinOnBall f pf s x r) : HasFPowerSeriesWithinOnBall (c • f) (c • pf) s x r where r_le := le_trans hf.r_le pf.radius_le_smul @@ -191,10 +209,15 @@ theorem AnalyticWithinAt.const_smul (hf : AnalyticWithinAt 𝕜 f s x) : let ⟨_, hpf⟩ := hf hpf.const_smul.analyticWithinAt +@[fun_prop] theorem AnalyticAt.const_smul (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (c • f) x := let ⟨_, hpf⟩ := hf hpf.const_smul.analyticAt +@[fun_prop] +theorem AnalyticAt.const_smul' (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (fun z ↦ c • f z) x := + hf.const_smul + 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) @@ -307,6 +330,7 @@ lemma AnalyticWithinAt.prod {e : E} {f : E → F} {g : E → G} {s : Set E} exact ⟨_, hf.prod hg⟩ /-- The Cartesian product of analytic functions is analytic. -/ +@[fun_prop] lemma AnalyticAt.prod {e : E} {f : E → F} {g : E → G} (hf : AnalyticAt 𝕜 f e) (hg : AnalyticAt 𝕜 g e) : AnalyticAt 𝕜 (fun x ↦ (f x, g x)) e := by @@ -590,11 +614,13 @@ pedantic to allow towers of field extensions. TODO: can we replace `𝕜'` with a "normed module" in such a way that `analyticAt_mul` is a special case of this? -/ +@[fun_prop] lemma analyticAt_smul [NormedSpace 𝕝 E] [IsScalarTower 𝕜 𝕝 E] (z : 𝕝 × E) : AnalyticAt 𝕜 (fun x : 𝕝 × E ↦ x.1 • x.2) z := (ContinuousLinearMap.lsmul 𝕜 𝕝).analyticAt_bilinear z /-- Multiplication in a normed algebra over `𝕜` is analytic. -/ +@[fun_prop] lemma analyticAt_mul (z : A × A) : AnalyticAt 𝕜 (fun x : A × A ↦ x.1 * x.2) z := (ContinuousLinearMap.mul 𝕜 A).analyticAt_bilinear z @@ -606,11 +632,19 @@ lemma AnalyticWithinAt.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] (analyticAt_smul _).comp₂_analyticWithinAt hf hg /-- Scalar multiplication of one analytic function by another. -/ +@[fun_prop] lemma AnalyticAt.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {z : E} (hf : AnalyticAt 𝕜 f z) (hg : AnalyticAt 𝕜 g z) : - AnalyticAt 𝕜 (fun x ↦ f x • g x) z := + AnalyticAt 𝕜 (f • g) z := (analyticAt_smul _).comp₂ hf hg +/-- Scalar multiplication of one analytic function by another. -/ +@[fun_prop] +lemma AnalyticAt.smul' [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {z : E} + (hf : AnalyticAt 𝕜 f z) (hg : AnalyticAt 𝕜 g z) : + AnalyticAt 𝕜 (fun x ↦ f x • g x) z := + hf.smul hg + /-- Scalar multiplication of one analytic function by another. -/ lemma AnalyticOn.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {s : Set E} @@ -634,10 +668,16 @@ lemma AnalyticWithinAt.mul {f g : E → A} {s : Set E} {z : E} (analyticAt_mul _).comp₂_analyticWithinAt hf hg /-- Multiplication of analytic functions (valued in a normed `𝕜`-algebra) is analytic. -/ +@[fun_prop] lemma AnalyticAt.mul {f g : E → A} {z : E} (hf : AnalyticAt 𝕜 f z) (hg : AnalyticAt 𝕜 g z) : - AnalyticAt 𝕜 (fun x ↦ f x * g x) z := + AnalyticAt 𝕜 (f * g) z := (analyticAt_mul _).comp₂ hf hg +@[fun_prop] +lemma AnalyticAt.mul' {f g : E → A} {z : E} (hf : AnalyticAt 𝕜 f z) (hg : AnalyticAt 𝕜 g z) : + AnalyticAt 𝕜 (fun x ↦ f x * g x) z := + hf.mul hg + /-- 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) : @@ -665,6 +705,7 @@ lemma AnalyticWithinAt.pow {f : E → A} {z : E} {s : Set E} (hf : AnalyticWithi exact hm.mul hf /-- Powers of analytic functions (into a normed `𝕜`-algebra) are analytic. -/ +@[fun_prop] lemma AnalyticAt.pow {f : E → A} {z : E} (hf : AnalyticAt 𝕜 f z) (n : ℕ) : AnalyticAt 𝕜 (fun x ↦ f x ^ n) z := by rw [← analyticWithinAt_univ] at hf ⊢ @@ -791,6 +832,7 @@ lemma hasFPowerSeriesOnBall_inverse_one_sub List.ofFn_const, List.prod_replicate] exact (summable_geometric_of_norm_lt_one hy).hasSum +@[fun_prop] lemma analyticAt_inverse_one_sub (𝕜 : Type*) [NontriviallyNormedField 𝕜] (A : Type*) [NormedRing A] [NormedAlgebra 𝕜 A] [HasSummableGeomSeries A] : AnalyticAt 𝕜 (fun x : A ↦ Ring.inverse (1 - x)) 0 := @@ -798,6 +840,7 @@ lemma analyticAt_inverse_one_sub (𝕜 : Type*) [NontriviallyNormedField 𝕜] /-- If `A` is a normed algebra over `𝕜` with summable geometric series, then inversion on `A` is analytic at any unit. -/ +@[fun_prop] lemma analyticAt_inverse {𝕜 : Type*} [NontriviallyNormedField 𝕜] {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] [HasSummableGeomSeries A] (z : Aˣ) : AnalyticAt 𝕜 Ring.inverse (z : A) := by @@ -837,12 +880,14 @@ lemma hasFPowerSeriesOnBall_inv_one_sub convert hasFPowerSeriesOnBall_inverse_one_sub 𝕜 𝕝 exact Ring.inverse_eq_inv'.symm +@[fun_prop] lemma analyticAt_inv_one_sub (𝕝 : Type*) [NontriviallyNormedField 𝕝] [NormedAlgebra 𝕜 𝕝] : AnalyticAt 𝕜 (fun x : 𝕝 ↦ (1 - x)⁻¹) 0 := ⟨_, ⟨_, hasFPowerSeriesOnBall_inv_one_sub 𝕜 𝕝⟩⟩ /-- If `𝕝` is a normed field extension of `𝕜`, then the inverse map `𝕝 → 𝕝` is `𝕜`-analytic away from 0. -/ +@[fun_prop] lemma analyticAt_inv {z : 𝕝} (hz : z ≠ 0) : AnalyticAt 𝕜 Inv.inv z := by convert analyticAt_inverse (𝕜 := 𝕜) (Units.mk0 _ hz) exact Ring.inverse_eq_inv'.symm @@ -861,10 +906,16 @@ theorem AnalyticWithinAt.inv {f : E → 𝕝} {x : E} {s : Set E} (analyticAt_inv f0).comp_analyticWithinAt fa /-- `(f x)⁻¹` is analytic away from `f x = 0` -/ +@[fun_prop] theorem AnalyticAt.inv {f : E → 𝕝} {x : E} (fa : AnalyticAt 𝕜 f x) (f0 : f x ≠ 0) : - AnalyticAt 𝕜 (fun x ↦ (f x)⁻¹) x := + AnalyticAt 𝕜 f⁻¹ x := (analyticAt_inv f0).comp fa +@[fun_prop] +theorem AnalyticAt.inv' {f : E → 𝕝} {x : E} (fa : AnalyticAt 𝕜 f x) (f0 : f x ≠ 0) : + AnalyticAt 𝕜 (fun x ↦ (f x)⁻¹) x := + fa.inv f0 + /-- `(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) : @@ -887,11 +938,18 @@ theorem AnalyticWithinAt.div {f g : E → 𝕝} {s : Set E} {x : E} simp_rw [div_eq_mul_inv]; exact fa.mul (ga.inv g0) /-- `f x / g x` is analytic away from `g x = 0` -/ +@[fun_prop] theorem AnalyticAt.div {f g : E → 𝕝} {x : E} (fa : AnalyticAt 𝕜 f x) (ga : AnalyticAt 𝕜 g x) (g0 : g x ≠ 0) : - AnalyticAt 𝕜 (fun x ↦ f x / g x) x := by + AnalyticAt 𝕜 (f / g) x := by simp_rw [div_eq_mul_inv]; exact fa.mul (ga.inv g0) +@[fun_prop] +theorem AnalyticAt.div' {f g : E → 𝕝} {x : E} + (fa : AnalyticAt 𝕜 f x) (ga : AnalyticAt 𝕜 g x) (g0 : g x ≠ 0) : + AnalyticAt 𝕜 (fun x ↦ f x / g x) x := + fa.div ga g0 + /-- `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) : @@ -924,6 +982,7 @@ theorem Finset.analyticWithinAt_sum {f : α → E → F} {c : E} {s : Set E} exact (h a (Or.inl rfl)).add (hB fun b m ↦ h b (Or.inr m)) /-- Finite sums of analytic functions are analytic -/ +@[fun_prop] theorem Finset.analyticAt_sum {f : α → E → F} {c : E} (N : Finset α) (h : ∀ n ∈ N, AnalyticAt 𝕜 (f n) c) : AnalyticAt 𝕜 (fun z ↦ ∑ n ∈ N, f n z) c := by @@ -958,6 +1017,7 @@ theorem Finset.analyticWithinAt_prod {A : Type*} [NormedCommRing A] [NormedAlgeb exact (h a (Or.inl rfl)).mul (hB fun b m ↦ h b (Or.inr m)) /-- Finite products of analytic functions are analytic -/ +@[fun_prop] theorem Finset.analyticAt_prod {A : Type*} [NormedCommRing A] [NormedAlgebra 𝕜 A] {f : α → E → A} {c : E} (N : Finset α) (h : ∀ n ∈ N, AnalyticAt 𝕜 (f n) c) : AnalyticAt 𝕜 (fun z ↦ ∏ n ∈ N, f n z) c := by diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index 94a872b1f4840..0c12a9fea2373 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -241,6 +241,44 @@ lemma apply_eq_zero_of_order_toNat_ne_zero (hf : AnalyticAt 𝕜 f z₀) : simp [hf.order_eq_zero_iff] tauto +/- Helper lemma for `AnalyticAt.order_mul` -/ +lemma order_mul_of_order_eq_top {f g : 𝕜 → 𝕜} (hf : AnalyticAt 𝕜 f z₀) + (hg : AnalyticAt 𝕜 g z₀) (h'f : hf.order = ⊤) : + (hf.mul hg).order = ⊤ := by + rw [AnalyticAt.order_eq_top_iff, eventually_nhds_iff] at * + obtain ⟨t, h₁t, h₂t, h₃t⟩ := h'f + exact ⟨t, fun y hy ↦ (by simp [h₁t y hy]), h₂t, h₃t⟩ + +/-- The order is additive when multiplying analytic functions. -/ +theorem order_mul {f g : 𝕜 → 𝕜} (hf : AnalyticAt 𝕜 f z₀) (hg : AnalyticAt 𝕜 g z₀) : + (hf.mul hg).order = hf.order + hg.order := by + -- Trivial cases: one of the functions vanishes around z₀ + by_cases h₂f : hf.order = ⊤ + · simp [hf.order_mul_of_order_eq_top hg h₂f, h₂f] + by_cases h₂g : hg.order = ⊤ + · simp [mul_comm f g, hg.order_mul_of_order_eq_top hf h₂g, h₂g] + -- Non-trivial case: both functions do not vanish around z₀ + obtain ⟨g₁, h₁g₁, h₂g₁, h₃g₁⟩ := hf.order_neq_top_iff.1 h₂f + obtain ⟨g₂, h₁g₂, h₂g₂, h₃g₂⟩ := hg.order_neq_top_iff.1 h₂g + rw [← ENat.coe_toNat h₂f, ← ENat.coe_toNat h₂g, ← ENat.coe_add, (hf.mul hg).order_eq_nat_iff] + use g₁ * g₂, by exact h₁g₁.mul h₁g₂ + constructor + · simp + tauto + · obtain ⟨t, h₁t, h₂t, h₃t⟩ := eventually_nhds_iff.1 h₃g₁ + obtain ⟨s, h₁s, h₂s, h₃s⟩ := eventually_nhds_iff.1 h₃g₂ + exact eventually_nhds_iff.2 + ⟨t ∩ s, fun y hy ↦ (by simp [h₁t y hy.1, h₁s y hy.2]; ring), h₂t.inter h₂s, h₃t, h₃s⟩ + +/-- The order multiplies by `n` when taking an analytic function to its `n`th power. -/ +theorem order_pow {f : 𝕜 → 𝕜} (hf : AnalyticAt 𝕜 f z₀) {n : ℕ} : + (hf.pow n).order = n • hf.order := by + induction n + case zero => + simp [AnalyticAt.order_eq_zero_iff] + case succ n hn => + simp [add_mul, pow_add, (hf.pow n).order_mul hf, hn] + end AnalyticAt namespace AnalyticOnNhd diff --git a/Mathlib/Analysis/Analytic/Linear.lean b/Mathlib/Analysis/Analytic/Linear.lean index bd405daef5895..5b7595bccbaa9 100644 --- a/Mathlib/Analysis/Analytic/Linear.lean +++ b/Mathlib/Analysis/Analytic/Linear.lean @@ -136,6 +136,7 @@ end ContinuousLinearMap variable {s : Set E} {z : E} {t : Set (E × F)} {p : E × F} +@[fun_prop] lemma analyticAt_id : AnalyticAt 𝕜 (id : E → E) z := (ContinuousLinearMap.id 𝕜 E).analyticAt z diff --git a/Mathlib/Analysis/Analytic/Meromorphic.lean b/Mathlib/Analysis/Analytic/Meromorphic.lean index 3ed9fadaa6e5c..86a7ea98ddcc0 100644 --- a/Mathlib/Analysis/Analytic/Meromorphic.lean +++ b/Mathlib/Analysis/Analytic/Meromorphic.lean @@ -26,9 +26,11 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] /-- Meromorphy of `f` at `x` (more precisely, on a punctured neighbourhood of `x`; the value at `x` itself is irrelevant). -/ +@[fun_prop] def MeromorphicAt (f : 𝕜 → E) (x : 𝕜) := ∃ (n : ℕ), AnalyticAt 𝕜 (fun z ↦ (z - x) ^ n • f z) x +@[fun_prop] lemma AnalyticAt.meromorphicAt {f : 𝕜 → E} {x : 𝕜} (hf : AnalyticAt 𝕜 f x) : MeromorphicAt f x := ⟨0, by simpa only [pow_zero, one_smul]⟩ @@ -37,9 +39,11 @@ namespace MeromorphicAt lemma id (x : 𝕜) : MeromorphicAt id x := analyticAt_id.meromorphicAt +@[fun_prop] lemma const (e : E) (x : 𝕜) : MeromorphicAt (fun _ ↦ e) x := analyticAt_const.meromorphicAt +@[fun_prop] lemma add {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : MeromorphicAt (f + g) x := by rcases hf with ⟨m, hf⟩ @@ -53,35 +57,63 @@ lemma add {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : Meromorph exact (((analyticAt_id.sub analyticAt_const).pow _).smul hf).add (((analyticAt_id.sub analyticAt_const).pow _).smul hg) +@[fun_prop] +lemma add' {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (fun z ↦ f z + g z) x := + hf.add hg + +@[fun_prop] lemma smul {f : 𝕜 → 𝕜} {g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : MeromorphicAt (f • g) x := by rcases hf with ⟨m, hf⟩ rcases hg with ⟨n, hg⟩ refine ⟨m + n, ?_⟩ - convert hf.smul hg using 2 with z + convert hf.smul' hg using 2 with z rw [Pi.smul_apply', smul_eq_mul] module +@[fun_prop] +lemma smul' {f : 𝕜 → 𝕜} {g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (fun z ↦ f z • g z) x := + hf.smul hg + +@[fun_prop] lemma mul {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : MeromorphicAt (f * g) x := hf.smul hg +@[fun_prop] +lemma mul' {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (fun z ↦ f z * g z) x := + hf.smul hg + +@[fun_prop] lemma neg {f : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicAt (-f) x := by convert (MeromorphicAt.const (-1 : 𝕜) x).smul hf using 1 ext1 z simp only [Pi.neg_apply, Pi.smul_apply', neg_smul, one_smul] +@[fun_prop] +lemma neg' {f : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicAt (fun z ↦ -f z) x := + hf.neg + @[simp] lemma neg_iff {f : 𝕜 → E} {x : 𝕜} : MeromorphicAt (-f) x ↔ MeromorphicAt f x := ⟨fun h ↦ by simpa only [neg_neg] using h.neg, MeromorphicAt.neg⟩ +@[fun_prop] lemma sub {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : MeromorphicAt (f - g) x := by convert hf.add hg.neg using 1 ext1 z simp_rw [Pi.sub_apply, Pi.add_apply, Pi.neg_apply, sub_eq_add_neg] +@[fun_prop] +lemma sub' {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (fun z ↦ f z - g z) x := + hf.sub hg + /-- With our definitions, `MeromorphicAt f x` depends only on the values of `f` on a punctured neighbourhood of `x` (not on `f x`) -/ lemma congr {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hfg : f =ᶠ[𝓝[≠] x] g) : @@ -89,13 +121,14 @@ lemma congr {f g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) (hfg : f =ᶠ rcases hf with ⟨m, hf⟩ refine ⟨m + 1, ?_⟩ have : AnalyticAt 𝕜 (fun z ↦ z - x) x := analyticAt_id.sub analyticAt_const - refine (this.smul hf).congr ?_ + refine (this.smul' hf).congr ?_ rw [eventuallyEq_nhdsWithin_iff] at hfg filter_upwards [hfg] with z hz rcases eq_or_ne z x with rfl | hn · simp · rw [hz (Set.mem_compl_singleton_iff.mp hn), pow_succ', mul_smul] +@[fun_prop] lemma inv {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicAt f⁻¹ x := by rcases hf with ⟨m, hf⟩ by_cases h_eq : (fun z ↦ (z - x) ^ m • f z) =ᶠ[𝓝 x] 0 @@ -110,7 +143,7 @@ lemma inv {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicA have : AnalyticAt 𝕜 (fun z ↦ (z - x) ^ (m + 1)) x := (analyticAt_id.sub analyticAt_const).pow _ -- use `m + 1` rather than `m` to damp out any silly issues with the value at `z = x` - refine ⟨n + 1, (this.smul <| hg_an.inv hg_ne).congr ?_⟩ + refine ⟨n + 1, (this.smul' <| hg_an.inv hg_ne).congr ?_⟩ filter_upwards [hg_eq, hg_an.continuousAt.eventually_ne hg_ne] with z hfg hg_ne' rcases eq_or_ne z x with rfl | hz_ne · simp only [sub_self, pow_succ, mul_zero, zero_smul] @@ -123,25 +156,47 @@ lemma inv {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicA rw [pow_succ', mul_assoc, hfg] ring +@[fun_prop] +lemma inv' {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) : MeromorphicAt (fun z ↦ (f z)⁻¹) x := + hf.inv + @[simp] lemma inv_iff {f : 𝕜 → 𝕜} {x : 𝕜} : MeromorphicAt f⁻¹ x ↔ MeromorphicAt f x := ⟨fun h ↦ by simpa only [inv_inv] using h.inv, MeromorphicAt.inv⟩ +@[fun_prop] lemma div {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : MeromorphicAt (f / g) x := (div_eq_mul_inv f g).symm ▸ (hf.mul hg.inv) +@[fun_prop] +lemma div' {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + MeromorphicAt (fun z ↦ f z / g z) x := + hf.div hg + +@[fun_prop] lemma pow {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (n : ℕ) : MeromorphicAt (f ^ n) x := by induction n with | zero => simpa only [pow_zero] using MeromorphicAt.const 1 x | succ m hm => simpa only [pow_succ] using hm.mul hf +@[fun_prop] +lemma pow' {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (n : ℕ) : + MeromorphicAt (fun z ↦ (f z) ^ n) x := + hf.pow n + +@[fun_prop] lemma zpow {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (n : ℤ) : MeromorphicAt (f ^ n) x := by induction n with | ofNat m => simpa only [Int.ofNat_eq_coe, zpow_natCast] using hf.pow m | negSucc m => simpa only [zpow_negSucc, inv_iff] using hf.pow (m + 1) +@[fun_prop] +lemma zpow' {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (n : ℤ) : + MeromorphicAt (fun z ↦ (f z) ^ n) x := + hf.zpow n + theorem eventually_analyticAt [CompleteSpace E] {f : 𝕜 → E} {x : 𝕜} (h : MeromorphicAt f x) : ∀ᶠ y in 𝓝[≠] x, AnalyticAt 𝕜 f y := by rw [MeromorphicAt] at h diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index 59fd0722065d8..09a1501984d89 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -118,6 +118,7 @@ theorem AnalyticWithinAt.differentiableWithinAt (h : AnalyticWithinAt 𝕜 f s x obtain ⟨p, hp⟩ := h exact hp.differentiableWithinAt +@[fun_prop] theorem AnalyticAt.differentiableAt : AnalyticAt 𝕜 f x → DifferentiableAt 𝕜 f x | ⟨_, hp⟩ => hp.differentiableAt @@ -234,6 +235,7 @@ protected theorem HasFPowerSeriesWithinOnBall.fderivWithin_of_mem [CompleteSpace exact this.symm /-- If a function is analytic on a set `s`, so is its Fréchet derivative. -/ +@[fun_prop] protected theorem AnalyticAt.fderiv [CompleteSpace F] (h : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (fderiv 𝕜 f) x := by rcases h with ⟨p, r, hp⟩ diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean index ef1748b715e87..45424cd36fd7d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean @@ -21,6 +21,7 @@ variable {E : Type} [NormedAddCommGroup E] [NormedSpace ℂ E] variable {f g : E → ℂ} {z : ℂ} {x : E} {s : Set E} /-- `log` is analytic away from nonpositive reals -/ +@[fun_prop] theorem analyticAt_clog (m : z ∈ slitPlane) : AnalyticAt ℂ log z := by rw [analyticAt_iff_eventually_differentiableAt] filter_upwards [isOpen_slitPlane.eventually_mem m] @@ -28,6 +29,7 @@ theorem analyticAt_clog (m : z ∈ slitPlane) : AnalyticAt ℂ log z := by exact differentiableAt_id.clog m /-- `log` is analytic away from nonpositive reals -/ +@[fun_prop] theorem AnalyticAt.clog (fa : AnalyticAt ℂ f x) (m : f x ∈ slitPlane) : AnalyticAt ℂ (fun z ↦ log (f z)) x := (analyticAt_clog m).comp fa @@ -56,6 +58,7 @@ theorem AnalyticWithinAt.cpow (fa : AnalyticWithinAt ℂ f s x) (ga : AnalyticWi exact ((fa.clog m).mul ga).cexp /-- `f z ^ g z` is analytic if `f z` is not a nonpositive real -/ +@[fun_prop] 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 ⊢ diff --git a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean index d13b1341c8a8d..63ef6f5d143ab 100644 --- a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean @@ -43,13 +43,20 @@ theorem analyticOnNhd_cexp : AnalyticOnNhd ℂ exp univ := by theorem analyticOn_cexp : AnalyticOn ℂ exp univ := analyticOnNhd_cexp.analyticOn /-- `exp` is analytic at any point -/ +@[fun_prop] theorem analyticAt_cexp : AnalyticAt ℂ exp z := analyticOnNhd_cexp z (mem_univ _) /-- `exp ∘ f` is analytic -/ -theorem AnalyticAt.cexp (fa : AnalyticAt ℂ f x) : AnalyticAt ℂ (fun z ↦ exp (f z)) x := +@[fun_prop] +theorem AnalyticAt.cexp (fa : AnalyticAt ℂ f x) : AnalyticAt ℂ (exp ∘ f) x := analyticAt_cexp.comp fa +/-- `exp ∘ f` is analytic -/ +@[fun_prop] +theorem AnalyticAt.cexp' (fa : AnalyticAt ℂ f x) : AnalyticAt ℂ (fun z ↦ exp (f z)) x := + fa.cexp + theorem AnalyticWithinAt.cexp (fa : AnalyticWithinAt ℂ f s x) : AnalyticWithinAt ℂ (fun z ↦ exp (f z)) s x := analyticAt_cexp.comp_analyticWithinAt fa @@ -204,13 +211,20 @@ theorem analyticOnNhd_rexp : AnalyticOnNhd ℝ exp univ := by theorem analyticOn_rexp : AnalyticOn ℝ exp univ := analyticOnNhd_rexp.analyticOn /-- `exp` is analytic at any point -/ +@[fun_prop] theorem analyticAt_rexp : AnalyticAt ℝ exp x := analyticOnNhd_rexp x (mem_univ _) /-- `exp ∘ f` is analytic -/ -theorem AnalyticAt.rexp {x : E} (fa : AnalyticAt ℝ f x) : AnalyticAt ℝ (fun z ↦ exp (f z)) x := +@[fun_prop] +theorem AnalyticAt.rexp {x : E} (fa : AnalyticAt ℝ f x) : AnalyticAt ℝ (exp ∘ f) x := analyticAt_rexp.comp fa +/-- `exp ∘ f` is analytic -/ +@[fun_prop] +theorem AnalyticAt.rexp' {x : E} (fa : AnalyticAt ℝ f x) : AnalyticAt ℝ (fun z ↦ exp (f z)) x := + fa.rexp + theorem AnalyticWithinAt.rexp {x : E} (fa : AnalyticWithinAt ℝ f s x) : AnalyticWithinAt ℝ (fun z ↦ exp (f z)) s x := analyticAt_rexp.comp_analyticWithinAt fa From af8c17b2c995e84c8d44e1c7592136845c590307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 26 Jan 2025 07:36:53 +0000 Subject: [PATCH 533/681] =?UTF-8?q?feat:=20`=E2=88=80=E1=B5=90=20x=20?= =?UTF-8?q?=E2=88=82=CE=BC[|s],=20x=20=E2=88=88=20s`=20(#21059)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From PFR --- Mathlib/Probability/ConditionalProbability.lean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mathlib/Probability/ConditionalProbability.lean b/Mathlib/Probability/ConditionalProbability.lean index 4e4d89fc5ac91..2bc58c9893945 100644 --- a/Mathlib/Probability/ConditionalProbability.lean +++ b/Mathlib/Probability/ConditionalProbability.lean @@ -138,6 +138,12 @@ lemma absolutelyContinuous_cond_univ [IsFiniteMeasure μ] : μ ≪ μ[|univ] := refine absolutelyContinuous_smul ?_ simp [measure_ne_top] +lemma ae_cond_mem₀ (hs : NullMeasurableSet s μ) : ∀ᵐ x ∂μ[|s], x ∈ s := + ae_smul_measure (ae_restrict_mem₀ hs) _ + +lemma ae_cond_mem (hs : MeasurableSet s) : ∀ᵐ x ∂μ[|s], x ∈ s := + ae_smul_measure (ae_restrict_mem hs) _ + section Bayes variable (μ) in From feb6a5dd8f4a8f2d804e0a0fc6c5c197628c1d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Sun, 26 Jan 2025 10:01:07 +0000 Subject: [PATCH 534/681] chore: replace `right_deriv` by `rightDeriv` in lemma names (#21076) And similarly for `left_deriv`. There is no `leftDeriv` or `rightDeriv` definition (they refer to a `derivWithin` in an interval) but they have a similar role in lemma names so should be written in the same way as definitions. --- Mathlib/Analysis/Convex/Deriv.lean | 40 ++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/Mathlib/Analysis/Convex/Deriv.lean b/Mathlib/Analysis/Convex/Deriv.lean index 65dbae3b210de..40ff12e20d1fe 100644 --- a/Mathlib/Analysis/Convex/Deriv.lean +++ b/Mathlib/Analysis/Convex/Deriv.lean @@ -395,11 +395,14 @@ lemma le_slope_of_hasDerivWithinAt_Ioi (hfc : ConvexOn ℝ S f) exact hfc.1.ordConnected.out hx hy ⟨ht'.le, ht.le⟩ /-- Reformulation of `ConvexOn.le_slope_of_hasDerivWithinAt_Ioi` using `derivWithin`. -/ -lemma right_deriv_le_slope (hfc : ConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma rightDeriv_le_slope (hfc : ConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Ioi x) x) : derivWithin f (Ioi x) x ≤ slope f x y := le_slope_of_hasDerivWithinAt_Ioi hfc hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias right_deriv_le_slope := rightDeriv_le_slope + /-- If `f : ℝ → ℝ` is convex on `S` and differentiable within `S` at `x`, then the slope of any secant line with left endpoint at `x` is bounded below by the derivative of `f` within `S` at `x`. @@ -449,11 +452,14 @@ lemma slope_le_of_hasDerivWithinAt_Iio (hfc : ConvexOn ℝ S f) exact hfc.1.ordConnected.out hx hy ⟨ht.le, ht'.le⟩ /-- Reformulation of `ConvexOn.slope_le_of_hasDerivWithinAt_Iio` using `derivWithin`. -/ -lemma slope_le_left_deriv (hfc : ConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma slope_le_leftDeriv (hfc : ConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Iio y) y) : slope f x y ≤ derivWithin f (Iio y) y := hfc.slope_le_of_hasDerivWithinAt_Iio hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias slope_le_left_deriv := slope_le_leftDeriv + /-- If `f : ℝ → ℝ` is convex on `S` and differentiable within `S` at `y`, then the slope of any secant line with right endpoint at `y` is bounded above by the derivative of `f` within `S` at `y`. @@ -531,11 +537,14 @@ lemma lt_slope_of_hasDerivWithinAt_Ioi (hfc : StrictConvexOn ℝ S f) simp only [← slope_def_field] at this exact (hfc.convexOn.le_slope_of_hasDerivWithinAt_Ioi hx hu hxu hf').trans_lt this -lemma right_deriv_lt_slope (hfc : StrictConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma rightDeriv_lt_slope (hfc : StrictConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Ioi x) x) : derivWithin f (Ioi x) x < slope f x y := hfc.lt_slope_of_hasDerivWithinAt_Ioi hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias right_deriv_lt_slope := rightDeriv_lt_slope + /-- If `f : ℝ → ℝ` is strictly convex on `S` and differentiable within `S` at `x ∈ S`, then the slope of any secant line with left endpoint at `x` is strictly greater than the derivative of `f` within `S` at `x`. @@ -583,11 +592,14 @@ lemma slope_lt_of_hasDerivWithinAt_Iio (hfc : StrictConvexOn ℝ S f) simp_rw [← slope_def_field, slope_comm _ y] at this exact this.trans_le <| hfc.convexOn.slope_le_of_hasDerivWithinAt_Iio hu hy huy hf' -lemma slope_lt_left_deriv (hfc : StrictConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma slope_lt_leftDeriv (hfc : StrictConvexOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Iio y) y) : slope f x y < derivWithin f (Iio y) y := hfc.slope_lt_of_hasDerivWithinAt_Iio hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias slope_lt_left_deriv := slope_lt_leftDeriv + /-- If `f : ℝ → ℝ` is strictly convex on `S` and differentiable within `S` at `y ∈ S`, then the slope of any secant line with right endpoint at `y` is strictly less than the derivative of `f` within `S` at `y`. @@ -657,11 +669,14 @@ lemma slope_le_of_hasDerivWithinAt_Ioi (hfc : ConcaveOn ℝ S f) simpa only [Pi.neg_def, slope_neg, neg_neg] using neg_le_neg (hfc.neg.le_slope_of_hasDerivWithinAt_Ioi hx hy hxy hf'.neg) -lemma slope_le_right_deriv (hfc : ConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma slope_le_rightDeriv (hfc : ConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Ioi x) x) : slope f x y ≤ derivWithin f (Ioi x) x := hfc.slope_le_of_hasDerivWithinAt_Ioi hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias slope_le_right_deriv := slope_le_rightDeriv + lemma slope_le_of_hasDerivWithinAt (hfc : ConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : HasDerivWithinAt f f' S x) : slope f x y ≤ f' := @@ -696,11 +711,14 @@ lemma le_slope_of_hasDerivWithinAt_Iio (hfc : ConcaveOn ℝ S f) simpa only [neg_neg, Pi.neg_def, slope_neg] using neg_le_neg (hfc.neg.slope_le_of_hasDerivWithinAt_Iio hx hy hxy hf'.neg) -lemma left_deriv_le_slope (hfc : ConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma leftDeriv_le_slope (hfc : ConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Iio y) y) : derivWithin f (Iio y) y ≤ slope f x y := hfc.le_slope_of_hasDerivWithinAt_Iio hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias left_deriv_le_slope := leftDeriv_le_slope + lemma le_slope_of_hasDerivWithinAt (hfc : ConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hf' : HasDerivWithinAt f f' S y) : f' ≤ slope f x y := @@ -757,11 +775,14 @@ lemma slope_lt_of_hasDerivWithinAt_Ioi (hfc : StrictConcaveOn ℝ S f) simpa only [Pi.neg_def, slope_neg, neg_neg] using neg_lt_neg (hfc.neg.lt_slope_of_hasDerivWithinAt_Ioi hx hy hxy hf'.neg) -lemma slope_lt_right_deriv (hfc : StrictConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma slope_lt_rightDeriv (hfc : StrictConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Ioi x) x) : slope f x y < derivWithin f (Ioi x) x := hfc.slope_lt_of_hasDerivWithinAt_Ioi hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias slope_lt_right_deriv := slope_lt_rightDeriv + lemma slope_lt_of_hasDerivWithinAt (hfc : StrictConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : HasDerivWithinAt f f' S x) : slope f x y < f' := by @@ -797,11 +818,14 @@ lemma lt_slope_of_hasDerivWithinAt_Iio (hfc : StrictConcaveOn ℝ S f) simpa only [Pi.neg_def, slope_neg, neg_neg] using neg_lt_neg (hfc.neg.slope_lt_of_hasDerivWithinAt_Iio hx hy hxy hf'.neg) -lemma left_deriv_lt_slope (hfc : StrictConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) +lemma leftDeriv_lt_slope (hfc : StrictConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hfd : DifferentiableWithinAt ℝ f (Iio y) y) : derivWithin f (Iio y) y < slope f x y := hfc.lt_slope_of_hasDerivWithinAt_Iio hx hy hxy hfd.hasDerivWithinAt +@[deprecated (since := "2025-01-26")] +alias left_deriv_lt_slope := leftDeriv_lt_slope + lemma lt_slope_of_hasDerivWithinAt (hfc : StrictConcaveOn ℝ S f) (hx : x ∈ S) (hy : y ∈ S) (hxy : x < y) (hf' : HasDerivWithinAt f f' S y) : f' < slope f x y := by From 150682c445684955c51e5ebad6866a2cb7177993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Sun, 26 Jan 2025 10:39:59 +0000 Subject: [PATCH 535/681] refactor(Order/WellFounded): use `WellFoundedLT` for `argmin` (#20777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of taking an explicit `WellFounded (· < ·)` argument, we can take a typeclass `WellFoundedLT` argument instead. --- Mathlib/Analysis/Convex/Caratheodory.lean | 8 +++--- Mathlib/CategoryTheory/CofilteredSystem.lean | 2 +- .../ConditionallyCompleteLattice/Basic.lean | 6 ++--- Mathlib/Order/WellFounded.lean | 26 +++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Mathlib/Analysis/Convex/Caratheodory.lean b/Mathlib/Analysis/Convex/Caratheodory.lean index 59b4f09c6a3ec..1bdb62e308505 100644 --- a/Mathlib/Analysis/Convex/Caratheodory.lean +++ b/Mathlib/Analysis/Convex/Caratheodory.lean @@ -100,17 +100,17 @@ variable {s : Set E} {x : E} /-- Given a point `x` in the convex hull of a set `s`, this is a finite subset of `s` of minimum cardinality, whose convex hull contains `x`. -/ noncomputable def minCardFinsetOfMemConvexHull (hx : x ∈ convexHull 𝕜 s) : Finset E := - Function.argminOn Finset.card Nat.lt_wfRel.2 { t | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } <| by + Function.argminOn Finset.card { t | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } <| by simpa only [convexHull_eq_union_convexHull_finite_subsets s, exists_prop, mem_iUnion] using hx variable (hx : x ∈ convexHull 𝕜 s) theorem minCardFinsetOfMemConvexHull_subseteq : ↑(minCardFinsetOfMemConvexHull hx) ⊆ s := - (Function.argminOn_mem _ _ { t : Finset E | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } _).1 + (Function.argminOn_mem _ { t : Finset E | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } _).1 theorem mem_minCardFinsetOfMemConvexHull : x ∈ convexHull 𝕜 (minCardFinsetOfMemConvexHull hx : Set E) := - (Function.argminOn_mem _ _ { t : Finset E | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } _).2 + (Function.argminOn_mem _ { t : Finset E | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } _).2 theorem minCardFinsetOfMemConvexHull_nonempty : (minCardFinsetOfMemConvexHull hx).Nonempty := by rw [← Finset.coe_nonempty, ← @convexHull_nonempty_iff 𝕜] @@ -118,7 +118,7 @@ theorem minCardFinsetOfMemConvexHull_nonempty : (minCardFinsetOfMemConvexHull hx theorem minCardFinsetOfMemConvexHull_card_le_card {t : Finset E} (ht₁ : ↑t ⊆ s) (ht₂ : x ∈ convexHull 𝕜 (t : Set E)) : #(minCardFinsetOfMemConvexHull hx) ≤ #t := - Function.argminOn_le _ _ _ (by exact ⟨ht₁, ht₂⟩) + Function.argminOn_le _ _ (by exact ⟨ht₁, ht₂⟩) theorem affineIndependent_minCardFinsetOfMemConvexHull : AffineIndependent 𝕜 ((↑) : minCardFinsetOfMemConvexHull hx → E) := by diff --git a/Mathlib/CategoryTheory/CofilteredSystem.lean b/Mathlib/CategoryTheory/CofilteredSystem.lean index fba99256f7078..a3088857c8cf8 100644 --- a/Mathlib/CategoryTheory/CofilteredSystem.lean +++ b/Mathlib/CategoryTheory/CofilteredSystem.lean @@ -344,7 +344,7 @@ theorem eventually_injective [Nonempty J] [Finite F.sections] : have card_le : ∀ j, Fintype.card (F.obj j) ≤ Fintype.card F.sections := fun j => Fintype.card_le_of_surjective _ (F.eval_section_surjective_of_surjective Fsur j) let fn j := Fintype.card F.sections - Fintype.card (F.obj j) - refine ⟨fn.argmin Nat.lt_wfRel.wf, + refine ⟨fn.argmin, fun i f => ((Fintype.bijective_iff_surjective_and_card _).2 ⟨Fsur f, le_antisymm ?_ (Fintype.card_le_of_surjective _ <| Fsur f)⟩).1⟩ rw [← Nat.sub_le_sub_iff_left (card_le i)] diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean index af8c5cbdf3a5f..84fa0aae1c71a 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean @@ -538,12 +538,12 @@ open Function variable [WellFoundedLT α] -theorem sInf_eq_argmin_on (hs : s.Nonempty) : sInf s = argminOn id wellFounded_lt s hs := - IsLeast.csInf_eq ⟨argminOn_mem _ _ _ _, fun _ ha => argminOn_le id _ _ ha⟩ +theorem sInf_eq_argmin_on (hs : s.Nonempty) : sInf s = argminOn id s hs := + IsLeast.csInf_eq ⟨argminOn_mem _ _ _, fun _ ha => argminOn_le id _ ha⟩ theorem isLeast_csInf (hs : s.Nonempty) : IsLeast s (sInf s) := by rw [sInf_eq_argmin_on hs] - exact ⟨argminOn_mem _ _ _ _, fun a ha => argminOn_le id _ _ ha⟩ + exact ⟨argminOn_mem _ _ _, fun a ha => argminOn_le id _ ha⟩ theorem le_csInf_iff' (hs : s.Nonempty) : b ≤ sInf s ↔ b ∈ lowerBounds s := le_isGLB_iff (isLeast_csInf hs).isGLB diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index e9675df3ac387..4123fe4543d71 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -235,45 +235,45 @@ variable (f : α → β) section LT -variable [LT β] (h : WellFounded ((· < ·) : β → β → Prop)) +variable [LT β] [h : WellFoundedLT β] /-- Given a function `f : α → β` where `β` carries a well-founded `<`, this is an element of `α` whose image under `f` is minimal in the sense of `Function.not_lt_argmin`. -/ noncomputable def argmin [Nonempty α] : α := - WellFounded.min (InvImage.wf f h) Set.univ Set.univ_nonempty + WellFounded.min (InvImage.wf f h.wf) Set.univ Set.univ_nonempty -theorem not_lt_argmin [Nonempty α] (a : α) : ¬f a < f (argmin f h) := - WellFounded.not_lt_min (InvImage.wf f h) _ _ (Set.mem_univ a) +theorem not_lt_argmin [Nonempty α] (a : α) : ¬f a < f (argmin f) := + WellFounded.not_lt_min (InvImage.wf f h.wf) _ _ (Set.mem_univ a) /-- Given a function `f : α → β` where `β` carries a well-founded `<`, and a non-empty subset `s` of `α`, this is an element of `s` whose image under `f` is minimal in the sense of `Function.not_lt_argminOn`. -/ noncomputable def argminOn (s : Set α) (hs : s.Nonempty) : α := - WellFounded.min (InvImage.wf f h) s hs + WellFounded.min (InvImage.wf f h.wf) s hs @[simp] -theorem argminOn_mem (s : Set α) (hs : s.Nonempty) : argminOn f h s hs ∈ s := +theorem argminOn_mem (s : Set α) (hs : s.Nonempty) : argminOn f s hs ∈ s := WellFounded.min_mem _ _ _ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): @[simp] removed as it will never apply theorem not_lt_argminOn (s : Set α) {a : α} (ha : a ∈ s) - (hs : s.Nonempty := Set.nonempty_of_mem ha) : ¬f a < f (argminOn f h s hs) := - WellFounded.not_lt_min (InvImage.wf f h) s hs ha + (hs : s.Nonempty := Set.nonempty_of_mem ha) : ¬f a < f (argminOn f s hs) := + WellFounded.not_lt_min (InvImage.wf f h.wf) s hs ha end LT section LinearOrder -variable [LinearOrder β] (h : WellFounded ((· < ·) : β → β → Prop)) +variable [LinearOrder β] [WellFoundedLT β] -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): @[simp] removed as it will never apply -theorem argmin_le (a : α) [Nonempty α] : f (argmin f h) ≤ f a := - not_lt.mp <| not_lt_argmin f h a +theorem argmin_le (a : α) [Nonempty α] : f (argmin f) ≤ f a := + not_lt.mp <| not_lt_argmin f a -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): @[simp] removed as it will never apply theorem argminOn_le (s : Set α) {a : α} (ha : a ∈ s) (hs : s.Nonempty := Set.nonempty_of_mem ha) : - f (argminOn f h s hs) ≤ f a := - not_lt.mp <| not_lt_argminOn f h s ha hs + f (argminOn f s hs) ≤ f a := + not_lt.mp <| not_lt_argminOn f s ha hs end LinearOrder From bc0287e58c6a04db6dec0ba650680d9e08f4b385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Sun, 26 Jan 2025 13:15:56 +0000 Subject: [PATCH 536/681] feat(Order/Antisymmetrization): `AntisymmRel` lemmas (#19571) These are mostly ported from [`SetTheory.PGame.Equiv`](https://leanprover-community.github.io/mathlib4_docs/Mathlib/SetTheory/Game/PGame.html#SetTheory.PGame.Equiv). --- Mathlib/Order/Antisymmetrization.lean | 115 +++++++++++++++++++++++--- Mathlib/Order/RelClasses.lean | 10 +++ 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/Mathlib/Order/Antisymmetrization.lean b/Mathlib/Order/Antisymmetrization.lean index 2a5cced208b85..a64b7b3da17a8 100644 --- a/Mathlib/Order/Antisymmetrization.lean +++ b/Mathlib/Order/Antisymmetrization.lean @@ -3,8 +3,9 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Order.Hom.Basic import Mathlib.Logic.Relation +import Mathlib.Order.Hom.Basic +import Mathlib.Tactic.Tauto /-! # Turning a preorder into a partial order @@ -27,13 +28,14 @@ such that `a ≤ b` and `b ≤ a`. open Function OrderDual -variable {α β : Type*} +variable {α β : Type*} {a b c d : α} section Relation variable (r : α → α → Prop) -/-- The antisymmetrization relation. -/ +/-- The antisymmetrization relation `AntisymmRel r` is defined so that +`AntisymmRel r a b ↔ r a b ∧ r b a`. -/ def AntisymmRel (a b : α) : Prop := r a b ∧ r b a @@ -44,26 +46,44 @@ theorem antisymmRel_swap : AntisymmRel (swap r) = AntisymmRel r := theorem antisymmRel_refl [IsRefl α r] (a : α) : AntisymmRel r a a := ⟨refl _, refl _⟩ +variable {r} in +lemma AntisymmRel.rfl [IsRefl α r] (a : α) : AntisymmRel r a a := antisymmRel_refl .. + +instance [IsRefl α r] : IsRefl α (AntisymmRel r) where + refl := antisymmRel_refl r + variable {r} @[symm] -theorem AntisymmRel.symm {a b : α} : AntisymmRel r a b → AntisymmRel r b a := +theorem AntisymmRel.symm : AntisymmRel r a b → AntisymmRel r b a := And.symm +instance : IsSymm α (AntisymmRel r) where + symm _ _ := AntisymmRel.symm + +theorem antisymmRel_comm : AntisymmRel r a b ↔ AntisymmRel r b a := + And.comm + @[trans] -theorem AntisymmRel.trans [IsTrans α r] {a b c : α} (hab : AntisymmRel r a b) - (hbc : AntisymmRel r b c) : AntisymmRel r a c := +theorem AntisymmRel.trans [IsTrans α r] (hab : AntisymmRel r a b) (hbc : AntisymmRel r b c) : + AntisymmRel r a c := ⟨_root_.trans hab.1 hbc.1, _root_.trans hbc.2 hab.2⟩ -instance AntisymmRel.decidableRel [DecidableRel r] : DecidableRel (AntisymmRel r) := fun _ _ => - instDecidableAnd +instance [IsTrans α r] : IsTrans α (AntisymmRel r) where + trans _ _ _ := .trans + +instance AntisymmRel.decidableRel [DecidableRel r] : DecidableRel (AntisymmRel r) := + fun _ _ ↦ instDecidableAnd @[simp] -theorem antisymmRel_iff_eq [IsRefl α r] [IsAntisymm α r] {a b : α} : AntisymmRel r a b ↔ a = b := +theorem antisymmRel_iff_eq [IsRefl α r] [IsAntisymm α r] : AntisymmRel r a b ↔ a = b := antisymm_iff alias ⟨AntisymmRel.eq, _⟩ := antisymmRel_iff_eq +theorem AntisymmRel.le [LE α] (h : AntisymmRel (· ≤ ·) a b) : a ≤ b := h.1 +theorem AntisymmRel.ge [LE α] (h : AntisymmRel (· ≤ ·) a b) : b ≤ a := h.2 + end Relation section IsPreorder @@ -112,9 +132,82 @@ end IsPreorder section Preorder -variable [Preorder α] [Preorder β] {a b : α} +variable [Preorder α] [Preorder β] + +theorem le_iff_lt_or_antisymmRel : a ≤ b ↔ a < b ∨ AntisymmRel (· ≤ ·) a b := by + rw [lt_iff_le_not_le, AntisymmRel] + tauto + +@[trans] +theorem le_of_le_of_antisymmRel (h₁ : a ≤ b) (h₂ : AntisymmRel (· ≤ ·) b c) : a ≤ c := + h₁.trans h₂.le + +@[trans] +theorem le_of_antisymmRel_of_le (h₁ : AntisymmRel (· ≤ ·) a b) (h₂ : b ≤ c) : a ≤ c := + h₁.le.trans h₂ + +@[trans] +theorem lt_of_lt_of_antisymmRel (h₁ : a < b) (h₂ : AntisymmRel (· ≤ ·) b c) : a < c := + h₁.trans_le h₂.le + +@[trans] +theorem lt_of_antisymmRel_of_lt (h₁ : AntisymmRel (· ≤ ·) a b) (h₂ : b < c) : a < c := + h₁.le.trans_lt h₂ + +alias ⟨LE.le.lt_or_antisymmRel, _⟩ := le_iff_lt_or_antisymmRel +alias LE.le.trans_antisymmRel := le_of_le_of_antisymmRel +alias AntisymmRel.trans_le := le_of_antisymmRel_of_le +alias LT.lt.trans_antisymmRel := lt_of_lt_of_antisymmRel +alias AntisymmRel.trans_lt := lt_of_antisymmRel_of_lt + +instance : @Trans α α α (· ≤ ·) (AntisymmRel (· ≤ ·)) (· ≤ ·) where + trans := le_of_le_of_antisymmRel + +instance : @Trans α α α (AntisymmRel (· ≤ ·)) (· ≤ ·) (· ≤ ·) where + trans := le_of_antisymmRel_of_le + +instance : @Trans α α α (· < ·) (AntisymmRel (· ≤ ·)) (· < ·) where + trans := lt_of_lt_of_antisymmRel + +instance : @Trans α α α (AntisymmRel (· ≤ ·)) (· < ·) (· < ·) where + trans := lt_of_antisymmRel_of_lt + +theorem AntisymmRel.le_congr (h₁ : AntisymmRel (· ≤ ·) a b) (h₂ : AntisymmRel (· ≤ ·) c d) : + a ≤ c ↔ b ≤ d where + mp h := (h₁.symm.trans_le h).trans_antisymmRel h₂ + mpr h := (h₁.trans_le h).trans_antisymmRel h₂.symm + +theorem AntisymmRel.le_congr_left (h : AntisymmRel (· ≤ ·) a b) : a ≤ c ↔ b ≤ c := + h.le_congr (antisymmRel_refl _ c) + +theorem AntisymmRel.le_congr_right (h : AntisymmRel (· ≤ ·) b c) : a ≤ b ↔ a ≤ c := + (antisymmRel_refl _ a).le_congr h + +theorem AntisymmRel.lt_congr (h₁ : AntisymmRel (· ≤ ·) a b) (h₂ : AntisymmRel (· ≤ ·) c d) : + a < c ↔ b < d where + mp h := (h₁.symm.trans_lt h).trans_antisymmRel h₂ + mpr h := (h₁.trans_lt h).trans_antisymmRel h₂.symm + +theorem AntisymmRel.lt_congr_left (h : AntisymmRel (· ≤ ·) a b) : a < c ↔ b < c := + h.lt_congr (antisymmRel_refl _ c) + +theorem AntisymmRel.lt_congr_right (h : AntisymmRel (· ≤ ·) b c) : a < b ↔ a < c := + (antisymmRel_refl _ a).lt_congr h + +theorem AntisymmRel.antisymmRel_congr + (h₁ : AntisymmRel (· ≤ ·) a b) (h₂ : AntisymmRel (· ≤ ·) c d) : + AntisymmRel (· ≤ ·) a c ↔ AntisymmRel (· ≤ ·) b d := + rel_congr h₁ h₂ + +theorem AntisymmRel.antisymmRel_congr_left (h : AntisymmRel (· ≤ ·) a b) : + AntisymmRel (· ≤ ·) a c ↔ AntisymmRel (· ≤ ·) b c := + rel_congr_left h + +theorem AntisymmRel.antisymmRel_congr_right (h : AntisymmRel (· ≤ ·) b c) : + AntisymmRel (· ≤ ·) a b ↔ AntisymmRel (· ≤ ·) a c := + rel_congr_right h -theorem AntisymmRel.image {a b : α} (h : AntisymmRel (· ≤ ·) a b) {f : α → β} (hf : Monotone f) : +theorem AntisymmRel.image (h : AntisymmRel (· ≤ ·) a b) {f : α → β} (hf : Monotone f) : AntisymmRel (· ≤ ·) (f a) (f b) := ⟨hf h.1, hf h.2⟩ diff --git a/Mathlib/Order/RelClasses.lean b/Mathlib/Order/RelClasses.lean index e00316da23a17..3ca9b0f2679b2 100644 --- a/Mathlib/Order/RelClasses.lean +++ b/Mathlib/Order/RelClasses.lean @@ -137,6 +137,16 @@ theorem trans_trichotomous_right [IsTrans α r] [IsTrichotomous α r] {a b c : theorem transitive_of_trans (r : α → α → Prop) [IsTrans α r] : Transitive r := IsTrans.trans +theorem rel_congr_left [IsSymm α r] [IsTrans α r] {a b c : α} (h : r a b) : r a c ↔ r b c := + ⟨trans_of r (symm_of r h), trans_of r h⟩ + +theorem rel_congr_right [IsSymm α r] [IsTrans α r] {a b c : α} (h : r b c) : r a b ↔ r a c := + ⟨(trans_of r · h), (trans_of r · (symm_of r h))⟩ + +theorem rel_congr [IsSymm α r] [IsTrans α r] {a b c d : α} (h₁ : r a b) (h₂ : r c d) : + r a c ↔ r b d := by + rw [rel_congr_left h₁, rel_congr_right h₂] + /-- In a trichotomous irreflexive order, every element is determined by the set of predecessors. -/ theorem extensional_of_trichotomous_of_irrefl (r : α → α → Prop) [IsTrichotomous α r] [IsIrrefl α r] {a b : α} (H : ∀ x, r x a ↔ r x b) : a = b := From 0d39cc610eef811c1ba8f83c11ed37c26894a8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 26 Jan 2025 15:45:28 +0000 Subject: [PATCH 537/681] feat(LinearAlgebra/ExteriorPower): the exterior powers, as functors (#18596) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We define the `n`th exterior power functor, from `ModuleCat R` to itself. Co-authored-by: sophie.morel@ens-lyon.fr Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + .../Category/ModuleCat/ExteriorPower.lean | 106 ++++++++++++++++++ .../LinearAlgebra/ExteriorPower/Basic.lean | 40 ++++++- 3 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 Mathlib/Algebra/Category/ModuleCat/ExteriorPower.lean diff --git a/Mathlib.lean b/Mathlib.lean index a8987b6f88349..e5041a5fd5c1b 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -112,6 +112,7 @@ import Mathlib.Algebra.Category.ModuleCat.Differentials.Basic import Mathlib.Algebra.Category.ModuleCat.Differentials.Presheaf import Mathlib.Algebra.Category.ModuleCat.EnoughInjectives import Mathlib.Algebra.Category.ModuleCat.EpiMono +import Mathlib.Algebra.Category.ModuleCat.ExteriorPower import Mathlib.Algebra.Category.ModuleCat.FilteredColimits import Mathlib.Algebra.Category.ModuleCat.Free import Mathlib.Algebra.Category.ModuleCat.Images diff --git a/Mathlib/Algebra/Category/ModuleCat/ExteriorPower.lean b/Mathlib/Algebra/Category/ModuleCat/ExteriorPower.lean new file mode 100644 index 0000000000000..d3152f601c9e4 --- /dev/null +++ b/Mathlib/Algebra/Category/ModuleCat/ExteriorPower.lean @@ -0,0 +1,106 @@ +/- +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.LinearAlgebra.ExteriorPower.Basic +import Mathlib.Algebra.Category.ModuleCat.Basic + +/-! +# The exterior powers as functors on the category of modules + +In this file, given `M : ModuleCat R` and `n : ℕ`, we define `M.exteriorPower n : ModuleCat R`, +and this extends to a functor `ModuleCat.exteriorPower.functor : ModuleCat R ⥤ ModuleCat R`. + +-/ + +universe v u + +open CategoryTheory + +namespace ModuleCat + +variable {R : Type u} [CommRing R] + +/-- The exterior power of an object in `ModuleCat R`. -/ +def exteriorPower (M : ModuleCat.{v} R) (n : ℕ) : ModuleCat.{max u v} R := + ModuleCat.of R (⋀[R]^n M) + +-- this could be an abbrev, but using a def eases automation +/-- The type of `n`-alternating maps on `M : ModuleCat R` to `N : ModuleCat R`. -/ +def AlternatingMap (M : ModuleCat.{v} R) (N : ModuleCat.{max u v} R) (n : ℕ) := + _root_.AlternatingMap R M N (Fin n) + +instance (M : ModuleCat.{v} R) (N : ModuleCat.{max u v} R) (n : ℕ) : + FunLike (M.AlternatingMap N n) (Fin n → M) N := + inferInstanceAs (FunLike (M [⋀^(Fin n)]→ₗ[R] N) (Fin n → M) N) + +namespace AlternatingMap + +variable {M : ModuleCat.{v} R} {N : ModuleCat.{max u v} R} {n : ℕ} + +@[ext] +lemma ext {φ φ' : M.AlternatingMap N n} (h : ∀ (x : Fin n → M), φ x = φ' x ) : + φ = φ' := + _root_.AlternatingMap.ext h + +variable (φ : M.AlternatingMap N n) {N' : ModuleCat.{max u v} R} (g : N ⟶ N') + +/-- The postcomposition of an alternating map by a linear map. -/ +def postcomp : M.AlternatingMap N' n := + g.hom.compAlternatingMap φ + +@[simp] +lemma postcomp_apply (x : Fin n → M) : + φ.postcomp g x = g (φ x) := rfl + +end AlternatingMap + +namespace exteriorPower + +/-- Constructor for elements in `M.exteriorPower n` when `M` is an object of `ModuleCat R` +and `n : ℕ`. -/ +def mk {M : ModuleCat.{v} R} {n : ℕ} : + M.AlternatingMap (M.exteriorPower n) n := + exteriorPower.ιMulti _ _ + +@[ext] +lemma hom_ext {M : ModuleCat.{v} R} {N : ModuleCat.{max u v} R} {n : ℕ} + {f g : M.exteriorPower n ⟶ N} + (h : mk.postcomp f = mk.postcomp g) : f = g := by + ext : 1 + exact exteriorPower.linearMap_ext h + +/-- The morphism `M.exteriorPower n ⟶ N` induced by an alternating map. -/ +noncomputable def desc {M : ModuleCat.{v} R} {n : ℕ} {N : ModuleCat.{max u v} R} + (φ : M.AlternatingMap N n) : M.exteriorPower n ⟶ N := + ofHom (exteriorPower.alternatingMapLinearEquiv φ) + +@[simp] +lemma desc_mk {M : ModuleCat.{v} R} {n : ℕ} {N : ModuleCat.{max u v} R} + (φ : M.AlternatingMap N n) (x : Fin n → M) : + desc φ (mk x) = φ x := by + apply exteriorPower.alternatingMapLinearEquiv_apply_ιMulti + +/-- The morphism `M.exteriorPower n ⟶ N.exteriorPower n` induced by a morphism `M ⟶ N` +in `ModuleCat R`. -/ +noncomputable def map {M N : ModuleCat.{v} R} (f : M ⟶ N) (n : ℕ) : + M.exteriorPower n ⟶ N.exteriorPower n := + ofHom (_root_.exteriorPower.map n f.hom) + +@[simp] +lemma map_mk {M N : ModuleCat.{v} R} (f : M ⟶ N) {n : ℕ} (x : Fin n → M) : + map f n (mk x) = mk (f ∘ x) := by + apply exteriorPower.map_apply_ιMulti + +variable (R) + +/-- The functor `ModuleCat R ⥤ ModuleCat R` which sends a module to its +`n`th exterior power. -/ +noncomputable def functor (n : ℕ) : ModuleCat.{v} R ⥤ ModuleCat.{max u v} R where + obj M := M.exteriorPower n + map f := map f n + +end exteriorPower + +end ModuleCat diff --git a/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean b/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean index 1eeeb2f33aea4..fce6e1013a043 100644 --- a/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean +++ b/Mathlib/LinearAlgebra/ExteriorPower/Basic.lean @@ -17,8 +17,12 @@ We study the exterior powers of a module `M` over a commutative ring `R`. * `exteriorPower.presentation R n M` is the standard presentation of the `R`-module `⋀[R]^n M`. +* `exteriorPower.map n f : ⋀[R]^n M →ₗ[R] ⋀[R]^n N` is the linear map on `nth` exterior powers +induced by a linear map `f : M →ₗ[R] N`. (See the file `Algebra.Category.ModuleCat.ExteriorPower` +for the corresponding functor `ModuleCat R ⥤ ModuleCat R`.) + ## Theorems -* `ιMulti_span`: The image of `exteriorPower.ιMulti` spans `⋀[R]^n M`. +* `exteriorPower.ιMulti_span`: The image of `exteriorPower.ιMulti` spans `⋀[R]^n M`. * We construct `exteriorPower.alternatingMapLinearEquiv` which expresses the universal property of the exterior power as a @@ -29,7 +33,7 @@ alternating maps and linear maps from the exterior power. open scoped TensorProduct -universe u v uM uN uN' uN'' uE uF +universe u variable (R : Type u) [CommRing R] (n : ℕ) {M N N' : Type*} [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] @@ -198,4 +202,36 @@ lemma alternatingMapLinearEquiv_comp (g : N →ₗ[R] N') (f : M [⋀^Fin n]→ simp only [alternatingMapLinearEquiv_comp_ιMulti, LinearMap.compAlternatingMap_apply, LinearMap.coe_comp, comp_apply, alternatingMapLinearEquiv_apply_ιMulti] +/-! Functoriality of the exterior powers. -/ + +variable (n) in +/-- The linear map between `n`th exterior powers induced by a linear map between the modules. -/ +noncomputable def map (f : M →ₗ[R] N) : ⋀[R]^n M →ₗ[R] ⋀[R]^n N := + alternatingMapLinearEquiv ((ιMulti R n).compLinearMap f) + +@[simp] lemma alternatingMapLinearEquiv_symm_map (f : M →ₗ[R] N) : + alternatingMapLinearEquiv.symm (map n f) = (ιMulti R n).compLinearMap f := by + simp only [map, LinearEquiv.symm_apply_apply] + +@[simp] +theorem map_comp_ιMulti (f : M →ₗ[R] N) : + (map n f).compAlternatingMap (ιMulti R n) = (ιMulti R n).compLinearMap f := by + simp only [map, alternatingMapLinearEquiv_comp_ιMulti] + +@[simp] +theorem map_apply_ιMulti (f : M →ₗ[R] N) (m : Fin n → M) : + map n f (ιMulti R n m) = ιMulti R n (f ∘ m) := by + simp only [map, alternatingMapLinearEquiv_apply_ιMulti, AlternatingMap.compLinearMap_apply] + rfl + +@[simp] +theorem map_id : + map n (LinearMap.id (R := R) (M := M)) = LinearMap.id := by + aesop + +@[simp] +theorem map_comp (f : M →ₗ[R] N) (g : N →ₗ[R] N') : + map n (g ∘ₗ f) = map n g ∘ₗ map n f := by + aesop + end exteriorPower From bf91ae4f8033a22927db4a04a7be16ca7e8b43f5 Mon Sep 17 00:00:00 2001 From: grunweg Date: Sun, 26 Jan 2025 15:57:42 +0000 Subject: [PATCH 538/681] feat: boundary of a product `M \times [x,y]` (#15893) - [x] depends on: #14972 - [x] depends on: #15892 Co-authored-by: Michael Rothgang --- Mathlib/Geometry/Manifold/Instances/Real.lean | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index 28cd5cdbe8912..78db01d88e9e2 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -13,7 +13,8 @@ import Mathlib.Analysis.InnerProductSpace.PiL2 We introduce the necessary bits to be able to define manifolds modelled over `ℝ^n`, boundaryless or with boundary or with corners. As a concrete example, we construct explicitly the manifold with boundary structure on the real interval `[x, y]`, and prove that its boundary is indeed `{x,y}` -whenever `x < y`. +whenever `x < y`. As a corollary, a product `M × [x, y]` with a manifold `M` without boundary +has boundary `M × {x, y}`. More specifically, we introduce * `modelWithCornersEuclideanHalfSpace n : @@ -451,8 +452,16 @@ lemma boundary_Icc : (𝓡∂ 1).boundary (Icc x y) = {⊥, ⊤} := by constructor <;> by_contra h <;> rw [congrArg Subtype.val h] at hp exacts [left_mem_Ioo.mp hp, right_mem_Ioo.mp hp] -/-- The manifold structure on `[x, y]` is smooth. --/ +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + +/-- A product `M × [x,y]` for `M` boundaryless has boundary `M × {x, y}`. -/ +lemma boundary_product [I.Boundaryless] : + (I.prod (𝓡∂ 1)).boundary (M × Icc x y) = Set.prod univ {⊥, ⊤} := by + rw [I.boundary_of_boundaryless_left, boundary_Icc] + +/-- The manifold structure on `[x, y]` is smooth. -/ instance instIsManifoldIcc (x y : ℝ) [Fact (x < y)] {n : WithTop ℕ∞} : IsManifold (𝓡∂ 1) n (Icc x y) := by have M : ContDiff ℝ n (show EuclideanSpace ℝ (Fin 1) → EuclideanSpace ℝ (Fin 1) From a1037826c282716733ec9a54c9dc4599677ac3bc Mon Sep 17 00:00:00 2001 From: Thomas Zhu Date: Sun, 26 Jan 2025 16:12:40 +0000 Subject: [PATCH 539/681] chore(Tactic/Polyrith): remove polyrith dependency on Python (#17626) * Removed dependency on Python to make requests to SageMath, using curl instead * Moved API calling logic from `scripts/polyrith_sage.py` to `Tactic/Polyrith.lean` * Moved `scripts/polyrith_sage_helper.py` inline Co-authored-by: Thomas Zhu <29544653+hanwenzhu@users.noreply.github.com> --- Mathlib/Tactic/Polyrith.lean | 162 ++++++++++++++++++++++---------- MathlibTest/polyrith.lean | 2 +- scripts/polyrith_sage.py | 115 ----------------------- scripts/polyrith_sage_helper.py | 49 ++++++++-- 4 files changed, 152 insertions(+), 176 deletions(-) delete mode 100644 scripts/polyrith_sage.py diff --git a/Mathlib/Tactic/Polyrith.lean b/Mathlib/Tactic/Polyrith.lean index 91b368722375e..dd9c5a039957b 100644 --- a/Mathlib/Tactic/Polyrith.lean +++ b/Mathlib/Tactic/Polyrith.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2022 Dhruv Bhatia. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Dhruv Bhatia, Eric Wieser, Mario Carneiro +Authors: Dhruv Bhatia, Eric Wieser, Mario Carneiro, Thomas Zhu -/ import Mathlib.Tactic.LinearCombination @@ -15,8 +15,8 @@ field by using multivariable polynomial hypotheses/proof terms over the same fie Used as is, the tactic makes use of those hypotheses in the local context that are over the same field as the target. However, the user can also specify which hypotheses from the local context to use, along with proof terms that might not already be in the -local context. Note: since this tactic uses SageMath via an API call done in Python, -it can only be used with a working internet connection, and with a local installation of Python. +local context. Note: since this tactic uses SageMath via an API call, +it can only be used with a working internet connection. ## Implementation Notes @@ -27,21 +27,16 @@ tactic succeeds. In other words, `linear_combination` is a certificate checker, to the user to find a collection of good coefficients. The `polyrith` tactic automates this process using the theory of Groebner bases. -Polyrith does this by first parsing the relevant hypotheses into a form that Python can understand. -It then calls a Python file that uses the SageMath API to compute the coefficients. These -coefficients are then sent back to Lean, which parses them into pexprs. The information is then -given to the `linear_combination` tactic, which completes the process by checking the certificate. +Polyrith does this by first parsing the relevant hypotheses into a form that SageMath can +understand. It then calls the SageMath API to compute the coefficients. These coefficients are +then sent back to Lean, which parses them into pexprs. The information is then given to the +`linear_combination` tactic, which completes the process by checking the certificate. In fact, `polyrith` uses Sage to test for membership in the *radical* of the ideal. This means it searches for a linear combination of hypotheses that add up to a *power* of the goal. When this power is not 1, it uses the `(exp := n)` feature of `linear_combination` to report the certificate. -`polyrith` calls an external python script `scripts/polyrith_sage.py`. Because this is not a Lean -file, changes to this script may not be noticed during Lean compilation if you have already -generated olean files. If you are modifying this python script, you likely know what you're doing; -remember to force recompilation of any files that call `polyrith`. - ## TODO * Give Sage more information about the specific ring being used for the coefficients. For now, @@ -86,12 +81,12 @@ inductive Poly This converts a poly object into a string representing it. The string maintains the semantic structure of the poly object. -The output of this function must be valid Python syntax, and it assumes the variables `varN` from -`scripts/polyrith.py.` +The output of this function must be valid Python syntax, and it assumes the variables `vars` +(see `sageCreateQuery`). -/ def Poly.format : Poly → Lean.Format | .const z => toString z - | .var n => s!"var{n}" + | .var n => s!"vars[{n}]" -- this references variable `vars`, which need to be bounded (below) | .hyp e => s!"hyp{e}" -- this one can't be used by python | .add p q => s!"({p.format} + {q.format})" | .sub p q => s!"({p.format} - {q.format})" @@ -165,17 +160,17 @@ inductive Source where | fvar : FVarId → Source /-- The first half of `polyrith` produces a list of arguments to be sent to Sage. -/ -def parseContext (only : Bool) (hyps : Array Expr) (tgt : Expr) : +def parseContext (only : Bool) (hyps : Array Expr) (target : Expr) : AtomM (Expr × Array (Source × Poly) × Poly) := do let fail {α} : AtomM α := throwError "polyrith failed: target is not an equality in semirings" - let some (α, e₁, e₂) := (← whnfR <|← instantiateMVars tgt).eq? | fail + let some (α, e₁, e₂) := (← whnfR <|← instantiateMVars target).eq? | fail let .sort u ← instantiateMVars (← whnf (← inferType α)) | unreachable! let some v := u.dec | throwError "not a type{indentExpr α}" have α : Q(Type v) := α have e₁ : Q($α) := e₁; have e₂ : Q($α) := e₂ let sα ← synthInstanceQ (q(CommSemiring $α) : Q(Type v)) let c ← mkCache sα - let tgt := (← parse sα c e₁).sub (← parse sα c e₂) + let target := (← parse sα c e₁).sub (← parse sα c e₂) let rec /-- Parses a hypothesis and adds it to the `out` list. -/ processHyp src ty out := do @@ -189,15 +184,9 @@ def parseContext (only : Bool) (hyps : Array Expr) (tgt : Expr) : out ← processHyp (.fvar ldecl.fvarId) ldecl.type out for hyp in hyps, i in [:hyps.size] do out ← processHyp (.input i) (← inferType hyp) out - pure (α, out, tgt) - -/-- Constructs the list of arguments to pass to the external sage script `polyrith_sage.py`. -/ -def createSageArgs (trace : Bool) (α : Expr) (atoms : Nat) - (hyps : Array (Source × Poly)) (tgt : Poly) : Array String := - let hyps := hyps.map (toString ·.2) |>.toList.toString - #[toString trace, toString α, toString atoms, hyps, toString tgt] + pure (α, out, target) -/-- A JSON parser for `ℚ` specific to the return value of `polyrith_sage.py`. -/ +/-- A JSON parser for `ℚ` specific to the return value of Sage. -/ local instance : FromJson ℚ where fromJson? | .arr #[a, b] => return (← fromJson? a : ℤ) / (← fromJson? b : ℕ) | _ => .error "expected array with two elements" @@ -284,28 +273,100 @@ structure SageError where /-- The result of a sage call. -/ def SageResult := Except SageError SageSuccess + +section SageMathApi + +/-! # Interaction with SageMath -/ + +/-- +These are Sage functions that test membership in the radical and format the output. See +https://github.com/sagemath/sage/blob/f8df80820dc7321dc9b18c9644c3b8315999670b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx#L4472-L4518 +for a description of `MPolynomial_libsingular.lift`. +-/ +def sageHelperFunctions : String := + include_str ".."/".."/"scripts"/"polyrith_sage_helper.py" + +/-- +The Sage type to use, given a base type of the target. Currently always rational numbers (`QQ`). +Future extensions may change behavior depending on the base type. +-/ +@[nolint unusedArguments] +def sageTypeStr (_ : Expr) : String := "QQ" + +/-- +Create a Sage script to send to SageMath API. +-/ +def sageCreateQuery (α : Expr) (atoms : Nat) (hyps : Array (Source × Poly)) (target : Poly) : + IO String := do + -- since `hyps` and `target` reference the variable list `vars` (see `Poly.format`), + -- `hyps` and `target` are wrapped as functions where `vars` is bounded using `lambda` + let hypsListPython := "[" ++ ",".intercalate (hyps.map (toString ·.2) |>.toList) ++ "]" + let mkHypsListPython := s!"lambda vars: {hypsListPython}" + let mkTargetPython := s!"lambda vars: {target}" + let command := + s!"main({sageTypeStr α}, {atoms}, {mkHypsListPython}, {mkTargetPython})" + return sageHelperFunctions ++ "\n" ++ command + +/-- Parse a `SageResult` from the raw SageMath API output. -/ instance : FromJson SageResult where fromJson? j := do - if let .ok true := fromJson? <| j.getObjValD "success" then - return .ok (← fromJson? j) + -- we expect the output has either "success": true and contains "stdout", + -- or has "success": false and error information under "execute_reply" + if let .ok true := j.getObjValAs? Bool "success" then + -- parse SageSuccess from stdout, which is formatted as SageCoeffAndPower + -- (see sageCreateQuery for the format of stdout) + let stdout ← j.getObjValAs? String "stdout" + let coeffAndPower ← Json.parse stdout >>= fromJson? + let sageSuccess := { data := some coeffAndPower } + return .ok sageSuccess else - return .error (← fromJson? j) + -- parse SageError from execute_reply + let executeReply ← j.getObjVal? "execute_reply" + let errorName ← executeReply.getObjValAs? String "ename" + let errorValue ← executeReply.getObjValAs? String "evalue" + return .error { name := errorName, value := errorValue } + +/-- The User-Agent header value for HTTP calls to SageMath API -/ +register_option polyrith.sageUserAgent : String := + { defValue := "LeanProver (https://leanprover-community.github.io/)" + group := "polyrith" + descr := "The User-Agent header value for HTTP calls to SageMath API" } /-- -This tactic calls python from the command line with the args in `arg_list`. -The output printed to the console is parsed as a `Json`. -It assumes that `python3` is available on the path. +This function calls the Sage API at . +The output is parsed as `SageResult`. -/ -def sageOutput (args : Array String) : IO SageResult := do - let path := (← getMathlibDir) / "scripts" / "polyrith_sage.py" - unless ← path.pathExists do - throw <| IO.userError "could not find python script scripts/polyrith_sage.py" - let out ← IO.Process.output { cmd := "python3", args := #[path.toString] ++ args } +def runSage (trace : Bool) (α : Expr) (atoms : Nat) (hyps : Array (Source × Poly)) (target : Poly) : + CoreM SageResult := do + let query ← sageCreateQuery α atoms hyps target + if trace then + -- dry run enabled + return .ok { trace := query } + + -- send query to SageMath API + let apiUrl := "https://sagecell.sagemath.org/service" + let data := s!"code={System.Uri.escapeUri query}" + let curlArgs := #[ + "-X", "POST", + "--user-agent", polyrith.sageUserAgent.get (← getOptions), + "--data-raw", data, + apiUrl + ] + let out ← IO.Process.output { cmd := "curl", args := curlArgs } if out.exitCode != 0 then - throw <| IO.userError <| - s!"scripts/polyrith_sage.py exited with code {out.exitCode}:\n\n{out.stderr}" + IO.throwServerError <| + "Could not send API request to SageMath. " ++ + s!"curl exited with code {out.exitCode}:\n{out.stderr}" + + -- parse results match Json.parse out.stdout >>= fromJson? with - | .ok v => return v - | .error e => throw <| .userError e + | .ok result => return result + | .error e => IO.throwServerError <| + s!"Could not parse SageMath output (error: {e})\nSageMath output:\n{out.stdout}" + +end SageMathApi + + +/-! # Main function -/ /-- This is the main body of the `polyrith` tactic. It takes in the following inputs: @@ -319,11 +380,11 @@ collects all the relevant hypotheses/proof terms from the context, and from thos selected by the user, taking into account whether `only` is true. (The list of atoms is updated accordingly as well). -This information is used to create a list of args that get used in a call to -the appropriate python file that executes a grobner basis computation. The -output of this computation is a `String` representing the certificate. This -string is parsed into a list of `Poly` objects that are then converted into -`Expr`s (using the updated list of atoms). +This information is used to create an appropriate SageMath script that executes a +Groebner basis computation, which is sent to SageMath's API server. +The output of this computation is a JSON representing the certificate. +This JSON is parsed into the power of the goal and a list of `Poly` objects +that are then converted into `Expr`s (using the updated list of atoms). the names of the hypotheses, along with the corresponding coefficients are given to `linear_combination`. If that tactic succeeds, the user is prompted @@ -336,7 +397,7 @@ def polyrith (g : MVarId) (only : Bool) (hyps : Array Expr) (traceOnly := false) : MetaM (Except MVarId (TSyntax `tactic)) := do IO.sleep 10 -- otherwise can lead to weird errors when actively editing code with polyrith calls g.withContext <| AtomM.run .reducible do - let (α, hyps', tgt) ← parseContext only hyps (← g.getType) + let (α, hyps', target) ← parseContext only hyps (← g.getType) let rec /-- Try to prove the goal by `ring` and fail with the given message otherwise. -/ byRing msg := do @@ -348,7 +409,7 @@ def polyrith (g : MVarId) (only : Bool) (hyps : Array Expr) if hyps'.isEmpty then return ← byRing "polyrith did not find any relevant hypotheses" let vars := (← get).atoms.size - match ← sageOutput (createSageArgs traceOnly α vars hyps' tgt) with + match ← runSage traceOnly α vars hyps' target with | .ok { trace, data } => if let some trace := trace then logInfo trace if let some {coeffs := polys, power := pow} := data then @@ -390,8 +451,7 @@ Notes: * This tactic only works with a working internet connection, since it calls Sage using the SageCell web API at . Many thanks to the Sage team and organization for allowing this use. -* This tactic assumes that the user has `python3` installed and available on the path. - (Test by opening a terminal and executing `python3 --version`.) +* This tactic assumes that the user has `curl` available on path. Examples: @@ -405,7 +465,7 @@ example (x y z w : ℚ) (hzw : z = w) : x*z + 2*y*z = x*w + 2*y*w := by polyrith -- Try this: linear_combination (2 * y + x) * hzw -constant scary : ∀ a b : ℚ, a + b = 0 +axiom scary : ∀ a b : ℚ, a + b = 0 example (a b c d : ℚ) (h : a + b = 0) (h2: b + c = 0) : a + b + c + d = 0 := by polyrith only [scary c d, h] diff --git a/MathlibTest/polyrith.lean b/MathlibTest/polyrith.lean index 58c192b53bdc6..1e95db80d41cc 100644 --- a/MathlibTest/polyrith.lean +++ b/MathlibTest/polyrith.lean @@ -504,7 +504,7 @@ example (a b c : ℤ) (h1 : a = b) (h2 : b = 1) : polyrith example (x y : ℚ) (h1 : x + y = 3) (h2 : 3*x = 7) : - x*x*y + y*x*y + 6*x = 3*x*y + 14 := + x*x*y + y*x*y + 6*x = 3*x*y + 14 := by polyrith example (x y z w : ℚ) (hzw : z = w) : x*z + 2*y*z = x*w + 2*y*w := by diff --git a/scripts/polyrith_sage.py b/scripts/polyrith_sage.py deleted file mode 100644 index 9833e5923864e..0000000000000 --- a/scripts/polyrith_sage.py +++ /dev/null @@ -1,115 +0,0 @@ -# This file is part of the `polyrith` tactic in `src/tactic/polyrith.lean`. -# It interfaces between Lean and the Sage web interface. - -import json -from os.path import join, dirname -import sys -from typing import Dict, Any -import urllib.error -import urllib.parse -import urllib.request - -# These functions are used to format the output of Sage for parsing in Lean. -# They are stored here as a string since they are passed to Sage via the web API. -with open(join(dirname(__file__), "polyrith_sage_helper.py"), encoding='utf8') as f: - polynomial_formatting_functions = f.read() - -# future extensions may change behavior depending on the base type -def type_str(type): - return "QQ" - -def create_query(type: str, n_vars: int, eq_list, target): - """ Create a query to invoke Sage's `MPolynomial_libsingular.lift`. See - https://github.com/sagemath/sage/blob/f8df80820dc7321dc9b18c9644c3b8315999670b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx#L4472-L4518 - for a description of this method. """ - var_list = [f"var{i}" for i in range(n_vars)] + ['aux'] - query = f''' -if {n_vars!r} != 0: - P = PolynomialRing({type_str(type)}, {var_list}) - [{", ".join(var_list)}] = P.gens() - p = P({target}) - if p==0: - # The "radicalization trick" implemented below does not work if the target polynomial p is 0 - # since it requires substituting 1/p. - print('1;'+serialize_polynomials(len({eq_list})*[P(0)])) - else: - # Implements the trick described in 2.2 of arxiv.org/pdf/1007.3615.pdf - # for testing membership in the radical. - gens = {eq_list} + [1 - p*aux] - I = P.ideal(gens) - coeffs = P(1).lift(I) - power = max(cf.degree(aux) for cf in coeffs) - coeffs = [P(cf.subs(aux = 1/p)*p^power) for cf in coeffs[:int(-1)]] - print(str(power)+';'+serialize_polynomials(coeffs)) -else: - # workaround for a Sage shortcoming with `n_vars = 0`, - # `TypeError: no conversion of this ring to a Singular ring defined` - # In this case, there is no need to look for membership in the *radical*; - # we just check for membership in the ideal, and return exponent 1 - # if coefficients are found. - P = PolynomialRing({type_str(type)}, 'var', 1) - p = P({target}) - I = P.ideal({eq_list}) - coeffs = p.lift(I) - print('1;'+serialize_polynomials(coeffs)) -''' - return query - -class EvaluationError(Exception): - def __init__(self, ename, evalue, message='Error in Sage communication'): - self.ename = ename - self.evalue = evalue - self.message = message - super().__init__(self.message) - -def parse_response(resp: str) -> Dict[str, Any]: - exp, data = resp.split(';', 1) - return dict(power=int(exp), coeffs=json.loads(data)) - - -def evaluate_in_sage(query: str) -> Dict[str, Any]: - data = urllib.parse.urlencode({'code': query}).encode('utf-8') - headers = {'Content-Type': 'application/x-www-form-urlencoded', - 'User-Agent': 'LeanProver (https://leanprover-community.github.io/)'} - req = urllib.request.Request('https://sagecell.sagemath.org/service', data=data, headers=headers) - with urllib.request.urlopen(req) as response: - response_data = response.read().decode() - response = json.loads(response_data) - if response['success']: - return parse_response(response.get('stdout')) - elif 'execute_reply' in response and 'ename' in response['execute_reply'] and 'evalue' in response['execute_reply']: - raise EvaluationError(response['execute_reply']['ename'], response['execute_reply']['evalue']) - else: - raise Exception(response) - -def main(): - '''The system args contain the following: - 0 - the path to this python file - 1 - a string containing "true" or "false" depending on whether polyrith was called with trace enabled - 2 - a string representing the base type of the target - 3 - the number of variables used - 4 - a list of the polynomial hypotheses/proof terms in terms of the variables - 5 - a single polynomial representing the target - - This returns a json object with format: - ``` - { success: bool, - data: Optional[list[str]], - trace: Optional[str], - name: Optional[str], - value: Optional[str] } - ``` - ''' - command = create_query(sys.argv[2], int(sys.argv[3]), sys.argv[4], sys.argv[5]) - final_query = polynomial_formatting_functions + "\n" + command - if sys.argv[1] == 'true': # trace dry run enabled - output = dict(success=True, trace=command) - else: - try: - output = dict(success=True, data=evaluate_in_sage(final_query)) - except EvaluationError as e: - output = dict(success=False, name=e.ename, value=e.evalue) - print(json.dumps(output)) - -if __name__ == "__main__": - main() diff --git a/scripts/polyrith_sage_helper.py b/scripts/polyrith_sage_helper.py index 44f05122530fb..78355df4754dc 100644 --- a/scripts/polyrith_sage_helper.py +++ b/scripts/polyrith_sage_helper.py @@ -1,13 +1,44 @@ # this file will be run by the remote sage server, so should not import local files. -from typing import Iterable +import json -def q_arr(coeff: QQ) -> str: - return "[" + str(coeff.numerator()) + "," + str(coeff.denominator()) + "]" +def q_arr(coeff: QQ) -> list[int]: + return [int(coeff.numerator()), int(coeff.denominator())] -def arr(args: Iterable[str]) -> str: - return "[" + ",".join(args) + "]" +def serialize_polynomials(power, coeffs) -> str: + return json.dumps({'power': int(power), 'coeffs': [ + [[[[int(t[0]), int(t[1])] for t in etuple.sparse_iter()], q_arr(coeff)] + for etuple, coeff in c.dict().items()] for c in coeffs + ]}) -def serialize_polynomials(coeffs) -> str: - return arr( - arr(arr([arr(arr([str(t[0]), str(t[1])]) for t in etuple.sparse_iter()), q_arr(coeff)]) - for etuple, coeff in c.dict().items()) for c in coeffs) +def main(base_ring, atoms: int, make_hyps, make_target): + if atoms != 0: + vars_str = ['var' + str(i) for i in range(atoms)] + ['aux'] + P = PolynomialRing(base_ring, vars_str) + *vars, aux = P.gens() + hyps = make_hyps(vars) + p = P(make_target(vars)) + if p == 0: + # The 'radicalization trick' implemented below does not work if + # the target polynomial p is 0 since it requires substituting 1/p. + print(serialize_polynomials(1, len(hyps)*[P(0)])) + else: + # Implements the trick described in 2.2 of arxiv.org/pdf/1007.3615.pdf + # for testing membership in the radical. + gens = hyps + [1 - p*aux] + I = P.ideal(gens) + coeffs = P(1).lift(I) + power = max(cf.degree(aux) for cf in coeffs) + coeffs = [P(cf.subs(aux = 1/p)*p^power) for cf in coeffs[:int(-1)]] + print(serialize_polynomials(power, coeffs)) + else: + # workaround for a Sage shortcoming with `atoms = 0`, + # `TypeError: no conversion of this ring to a Singular ring defined` + # In this case, there is no need to look for membership in the *radical*; + # we just check for membership in the ideal, and return exponent 1 + # if coefficients are found. + P = PolynomialRing(base_ring, 'var', 1) + hyps = make_hyps([]) + p = P(make_target([])) + I = P.ideal(hyps) + coeffs = p.lift(I) + print(serialize_polynomials(1, coeffs)) From 4e9e3115d964c4f49bcb414a7956bce121a01b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Sun, 26 Jan 2025 17:26:17 +0000 Subject: [PATCH 540/681] =?UTF-8?q?feat:=20`=CE=BC[ofNat=20n=20*=20f|m]=20?= =?UTF-8?q?=3D=E1=B5=90[=CE=BC]=20ofNat=20n=20*=20=CE=BC[f|m]`=20(#21001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also: * make `condExp_const` a simp lemma * rename `condExp_undef` to `condExp_of_not_integrable` (there are many ways in which `condExp` is undefined other than the function not being integrable) * specialise `eLpNorm_condExp_le` and `Memℒp.condExp` to real inner product spaces as otherwise `𝕜` is unconstrained by the return type * add a TODO From my PhD (LeanCamCombi) --- .../ConditionalExpectation/Basic.lean | 47 ++++++++++++++----- .../ConditionalExpectation/Indicator.lean | 4 +- .../Function/ConditionalExpectation/Real.lean | 12 ++--- .../Probability/ConditionalExpectation.lean | 2 +- 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index 3ab7e033caf91..e5fb77b18b62e 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -56,6 +56,12 @@ For a measure `μ` defined on a measurable space structure `m₀`, another measu `m` with `hm : m ≤ m₀` (a sub-σ-algebra) and a function `f`, we define the notation * `μ[f|m] = condExp m μ f`. +## TODO + +See https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/Conditional.20expectation.20of.20product +for how to prove that we can pull `m`-measurable continuous linear maps out of the `m`-conditional +expectation. This would generalise `MeasureTheory.condExp_mul_of_stronglyMeasurable_left`. + ## Tags conditional expectation, conditional expected value @@ -123,6 +129,7 @@ theorem condExp_of_stronglyMeasurable (hm : m ≤ m₀) [hμm : SigmaFinite (μ. @[deprecated (since := "2025-01-21")] alias condexp_of_stronglyMeasurable := condExp_of_stronglyMeasurable +@[simp] theorem condExp_const (hm : m ≤ m₀) (c : E) [IsFiniteMeasure μ] : μ[fun _ : α ↦ c|m] = fun _ ↦ c := condExp_of_stronglyMeasurable hm stronglyMeasurable_const (integrable_const c) @@ -150,14 +157,15 @@ theorem condExp_ae_eq_condExpL1CLM (hm : m ≤ m₀) [SigmaFinite (μ.trim hm)] @[deprecated (since := "2025-01-21")] alias condexp_ae_eq_condexpL1CLM := condExp_ae_eq_condExpL1CLM -theorem condExp_undef (hf : ¬Integrable f μ) : μ[f|m] = 0 := by +theorem condExp_of_not_integrable (hf : ¬Integrable f μ) : μ[f|m] = 0 := by by_cases hm : m ≤ m₀ swap; · rw [condExp_of_not_le hm] by_cases hμm : SigmaFinite (μ.trim hm) swap; · rw [condExp_of_not_sigmaFinite hm hμm] rw [condExp_of_sigmaFinite, if_neg hf] -@[deprecated (since := "2025-01-21")] alias condexp_undef := condExp_undef +@[deprecated (since := "2025-01-21")] alias condexp_undef := condExp_of_not_integrable +@[deprecated (since := "2025-01-21")] alias condExp_undef := condExp_of_not_integrable @[simp] theorem condExp_zero : μ[(0 : α → E)|m] = 0 := by @@ -229,7 +237,7 @@ theorem integral_condExp (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] : · suffices ∫ x in Set.univ, (μ[f|m]) x ∂μ = ∫ x in Set.univ, f x ∂μ by simp_rw [setIntegral_univ] at this; exact this exact setIntegral_condExp hm hf .univ - simp only [condExp_undef hf, Pi.zero_apply, integral_zero, integral_undef hf] + simp only [condExp_of_not_integrable hf, Pi.zero_apply, integral_zero, integral_undef hf] @[deprecated (since := "2025-01-21")] alias integral_condexp := integral_condExp @@ -359,7 +367,7 @@ theorem condExp_condExp_of_le {m₁ m₂ m₀ : MeasurableSpace α} {μ : Measur by_cases hμm₁ : SigmaFinite (μ.trim (hm₁₂.trans hm₂)) swap; · simp_rw [condExp_of_not_sigmaFinite (hm₁₂.trans hm₂) hμm₁]; rfl by_cases hf : Integrable f μ - swap; · simp_rw [condExp_undef hf, condExp_zero]; rfl + swap; · simp_rw [condExp_of_not_integrable hf, condExp_zero]; rfl refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' (hm₁₂.trans hm₂) (fun s _ _ => integrable_condExp.integrableOn) (fun s _ _ => integrable_condExp.integrableOn) ?_ stronglyMeasurable_condExp.aestronglyMeasurable @@ -370,7 +378,7 @@ theorem condExp_condExp_of_le {m₁ m₂ m₀ : MeasurableSpace α} {μ : Measur @[deprecated (since := "2025-01-21")] alias condexp_condexp_of_le := condExp_condExp_of_le -section MemL2 +section RCLike variable [InnerProductSpace 𝕜 E] lemma Memℒp.condExpL2_ae_eq_condExp' (hm : m ≤ m₀) (hf1 : Integrable f μ) (hf2 : Memℒp f 2 μ) @@ -386,8 +394,12 @@ lemma Memℒp.condExpL2_ae_eq_condExp (hm : m ≤ m₀) (hf : Memℒp f 2 μ) [I condExpL2 E 𝕜 hm hf.toLp =ᵐ[μ] μ[f | m] := hf.condExpL2_ae_eq_condExp' hm (memℒp_one_iff_integrable.1 <| hf.mono_exponent one_le_two) +end RCLike + +section Real +variable [InnerProductSpace ℝ E] + -- TODO: Generalize via the conditional Jensen inequality -include 𝕜 in lemma eLpNorm_condExp_le : eLpNorm (μ[f | m]) 2 μ ≤ eLpNorm f 2 μ := by by_cases hm : m ≤ m₀; swap · simp [condExp_of_not_le hm] @@ -395,25 +407,34 @@ lemma eLpNorm_condExp_le : eLpNorm (μ[f | m]) 2 μ ≤ eLpNorm f 2 μ := by · rw [condExp_of_not_sigmaFinite hm hfμ] simp by_cases hfi : Integrable f μ; swap - · rw [condExp_undef hfi] + · rw [condExp_of_not_integrable hfi] simp obtain hf | hf := eq_or_ne (eLpNorm f 2 μ) ∞ · simp [hf] replace hf : Memℒp f 2 μ := ⟨hfi.1, Ne.lt_top' fun a ↦ hf (id (Eq.symm a))⟩ - rw [← eLpNorm_congr_ae (hf.condExpL2_ae_eq_condExp' (𝕜 := 𝕜) hm hfi)] + rw [← eLpNorm_congr_ae (hf.condExpL2_ae_eq_condExp' (𝕜 := ℝ) hm hfi)] refine le_trans (eLpNorm_condExpL2_le hm _) ?_ rw [eLpNorm_congr_ae hf.coeFn_toLp] -include 𝕜 in protected lemma Memℒp.condExp (hf : Memℒp f 2 μ) : Memℒp (μ[f | m]) 2 μ := by by_cases hm : m ≤ m₀ · exact ⟨(stronglyMeasurable_condExp.mono hm).aestronglyMeasurable, - eLpNorm_condExp_le (𝕜 := 𝕜).trans_lt hf.eLpNorm_lt_top⟩ + eLpNorm_condExp_le.trans_lt hf.eLpNorm_lt_top⟩ · simp [condExp_of_not_le hm] -end MemL2 +end Real end NormedAddCommGroup +section NormedRing +variable {R : Type*} [NormedRing R] [NormedSpace ℝ R] [CompleteSpace R] + +@[simp] +lemma condExp_ofNat (n : ℕ) [n.AtLeastTwo] (f : α → R) : + μ[ofNat(n) * f|m] =ᵐ[μ] ofNat(n) * μ[f|m] := by + simpa [Nat.cast_smul_eq_nsmul] using condExp_smul (μ := μ) (m := m) (n : ℝ) f + +end NormedRing + section NormedLatticeAddCommGroup variable [NormedLatticeAddCommGroup E] [CompleteSpace E] [NormedSpace ℝ E] @@ -476,13 +497,13 @@ lemma condExp_nonneg (hf : 0 ≤ᵐ[μ] f) : 0 ≤ᵐ[μ] μ[f|m] := by by_cases hfint : Integrable f μ · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] exact condExp_mono (integrable_zero _ _ _) hfint hf - · rw [condExp_undef hfint] + · rw [condExp_of_not_integrable hfint] lemma condExp_nonpos (hf : f ≤ᵐ[μ] 0) : μ[f|m] ≤ᵐ[μ] 0 := by by_cases hfint : Integrable f μ · rw [(condExp_zero.symm : (0 : α → E) = μ[0|m])] exact condExp_mono hfint (integrable_zero _ _ _) hf - · rw [condExp_undef hfint] + · rw [condExp_of_not_integrable hfint] @[deprecated (since := "2025-01-21")] alias condexp_mono := condExp_mono @[deprecated (since := "2025-01-21")] alias condexp_nonneg := condExp_nonneg diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean index ec9544a287a01..8610e0a9cbe52 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Indicator.lean @@ -44,7 +44,7 @@ theorem condExp_ae_eq_restrict_zero (hs : MeasurableSet[m] s) (hf : f =ᵐ[μ.re rw [← restrict_trim hm _ hs] exact Restrict.sigmaFinite _ s by_cases hf_int : Integrable f μ - swap; · rw [condExp_undef hf_int] + swap; · rw [condExp_of_not_integrable hf_int] refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hm ?_ ?_ ?_ ?_ ?_ · exact fun t _ _ => integrable_condExp.integrableOn.integrableOn · exact fun t _ _ => (integrable_zero _ _ _).integrableOn @@ -152,7 +152,7 @@ theorem condExp_ae_eq_restrict_of_measurableSpace_eq_on {m m₂ m0 : MeasurableS rw [ae_eq_restrict_iff_indicator_ae_eq (hm _ hs_m)] have hs_m₂ : MeasurableSet[m₂] s := by rwa [← Set.inter_univ s, ← hs Set.univ, Set.inter_univ] by_cases hf_int : Integrable f μ - swap; · simp_rw [condExp_undef hf_int]; rfl + swap; · simp_rw [condExp_of_not_integrable hf_int]; rfl refine ((condExp_indicator hf_int hs_m).symm.trans ?_).trans (condExp_indicator hf_int hs_m₂) refine ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' hm₂ (fun s _ _ => integrable_condExp.integrableOn) diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index 8eac500e658bf..41c370cc5b4b6 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -57,7 +57,7 @@ theorem rnDeriv_ae_eq_condExp {hm : m ≤ m0} [hμm : SigmaFinite (μ.trim hm)] -- for the conditional expectation (not in mathlib yet) . theorem eLpNorm_one_condExp_le_eLpNorm (f : α → ℝ) : eLpNorm (μ[f|m]) 1 μ ≤ eLpNorm f 1 μ := by by_cases hf : Integrable f μ - swap; · rw [condExp_undef hf, eLpNorm_zero]; exact zero_le _ + swap; · rw [condExp_of_not_integrable hf, eLpNorm_zero]; exact zero_le _ by_cases hm : m ≤ m0 swap; · rw [condExp_of_not_le hm, eLpNorm_zero]; exact zero_le _ by_cases hsig : SigmaFinite (μ.trim hm) @@ -102,8 +102,8 @@ theorem integral_abs_condExp_le (f : α → ℝ) : ∫ x, |(μ[f|m]) x| ∂μ positivity by_cases hfint : Integrable f μ swap - · simp only [condExp_undef hfint, Pi.zero_apply, abs_zero, integral_const, Algebra.id.smul_eq_mul, - mul_zero] + · simp only [condExp_of_not_integrable hfint, Pi.zero_apply, abs_zero, integral_const, + Algebra.id.smul_eq_mul, mul_zero] positivity rw [integral_eq_lintegral_of_nonneg_ae, integral_eq_lintegral_of_nonneg_ae] · apply ENNReal.toReal_mono <;> simp_rw [← Real.norm_eq_abs, ofReal_norm_eq_coe_nnnorm] @@ -127,8 +127,8 @@ theorem setIntegral_abs_condExp_le {s : Set α} (hs : MeasurableSet[m] s) (f : positivity by_cases hfint : Integrable f μ swap - · simp only [condExp_undef hfint, Pi.zero_apply, abs_zero, integral_const, Algebra.id.smul_eq_mul, - mul_zero] + · simp only [condExp_of_not_integrable hfint, Pi.zero_apply, abs_zero, integral_const, + Algebra.id.smul_eq_mul, mul_zero] positivity have : ∫ x in s, |(μ[f|m]) x| ∂μ = ∫ x, |(μ[s.indicator f|m]) x| ∂μ := by rw [← integral_indicator (hnm _ hs)] @@ -161,7 +161,7 @@ theorem ae_bdd_condExp_of_ae_bdd {R : ℝ≥0} {f : α → ℝ} (hbdd : ∀ᵐ x exact Eventually.of_forall fun _ => R.coe_nonneg by_cases hfint : Integrable f μ swap - · simp_rw [condExp_undef hfint] + · simp_rw [condExp_of_not_integrable hfint] filter_upwards [hbdd] with x hx rw [Pi.zero_apply, abs_zero] exact (abs_nonneg _).trans hx diff --git a/Mathlib/Probability/ConditionalExpectation.lean b/Mathlib/Probability/ConditionalExpectation.lean index 04a9b261c32a8..2cb4e7ad41acd 100644 --- a/Mathlib/Probability/ConditionalExpectation.lean +++ b/Mathlib/Probability/ConditionalExpectation.lean @@ -38,7 +38,7 @@ almost everywhere. -/ theorem condExp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinite (μ.trim hle₂)] (hf : StronglyMeasurable[m₁] f) (hindp : Indep m₁ m₂ μ) : μ[f|m₂] =ᵐ[μ] fun _ => μ[f] := by by_cases hfint : Integrable f μ - swap; · rw [condExp_undef hfint, integral_undef hfint]; rfl + swap; · rw [condExp_of_not_integrable hfint, integral_undef hfint]; rfl refine (ae_eq_condExp_of_forall_setIntegral_eq hle₂ hfint (fun s _ hs => integrableOn_const.2 (Or.inr hs)) (fun s hms hs => ?_) stronglyMeasurable_const.aestronglyMeasurable).symm From e76789944f69a2650053a9ab0f688f94e8849f7c Mon Sep 17 00:00:00 2001 From: Junyan Xu Date: Sun, 26 Jan 2025 18:07:00 +0000 Subject: [PATCH 541/681] feat(Algebra): `Mul/RingEquiv`s between `center` and `Module.End` (#20721) --- Mathlib/Algebra/Category/ModuleCat/Basic.lean | 9 ++- Mathlib/Algebra/Module/Equiv/Basic.lean | 68 +++++++++++++------ Mathlib/Algebra/Ring/Subring/Basic.lean | 9 +++ Mathlib/Algebra/Ring/Subsemiring/Basic.lean | 12 +++- Mathlib/GroupTheory/Subgroup/Center.lean | 10 +++ Mathlib/GroupTheory/Submonoid/Center.lean | 58 ++++++++++++++++ Mathlib/RepresentationTheory/Character.lean | 2 +- Mathlib/RepresentationTheory/FDRep.lean | 13 ++-- Mathlib/RepresentationTheory/Rep.lean | 6 +- .../RingTheory/NonUnitalSubring/Basic.lean | 11 +++ .../NonUnitalSubsemiring/Basic.lean | 15 ++++ 11 files changed, 178 insertions(+), 35 deletions(-) diff --git a/Mathlib/Algebra/Category/ModuleCat/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Basic.lean index 4c63c2f7e9aea..3b5c357c23475 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Basic.lean @@ -444,14 +444,17 @@ end variable (M N : ModuleCat.{v} R) -/-- `ModuleCat.Hom.hom` as an isomorphism of monoids. -/ -@[simps] -def endMulEquiv : End M ≃* (M →ₗ[R] M) where +/-- `ModuleCat.Hom.hom` as an isomorphism of rings. -/ +@[simps!] def endRingEquiv : End M ≃+* (M →ₗ[R] M) where toFun := ModuleCat.Hom.hom invFun := ModuleCat.ofHom map_mul' _ _ := rfl left_inv _ := rfl right_inv _ := rfl + map_add' _ _ := rfl + +/-- `ModuleCat.Hom.hom` as an isomorphism of monoids. -/ +@[deprecated (since := "2025-01-23")] alias endMulEquiv := endRingEquiv /-- The scalar multiplication on an object of `ModuleCat R` considered as a morphism of rings from `R` to the endomorphisms of the underlying abelian group. -/ diff --git a/Mathlib/Algebra/Module/Equiv/Basic.lean b/Mathlib/Algebra/Module/Equiv/Basic.lean index b0228d7304c79..ddbbd94475a75 100644 --- a/Mathlib/Algebra/Module/Equiv/Basic.lean +++ b/Mathlib/Algebra/Module/Equiv/Basic.lean @@ -482,6 +482,41 @@ theorem symm_neg : (neg R : M ≃ₗ[R] M).symm = neg R := end Neg +section Semiring + +open LinearMap + +variable {M₂₁ M₂₂ : Type*} [Semiring R] [AddCommMonoid M₁] [AddCommMonoid M₂] + [AddCommMonoid M₂₁] [AddCommMonoid M₂₂] [Module R M₁] [Module R M₂] [Module R M₂₁] [Module R M₂₂] + +/-- A linear isomorphism between the domains and codomains of two spaces of linear maps gives a +additive isomorphism between the two function spaces. + +See also `LinearEquiv.arrowCongr` for the linear version of this isomorphism. -/ +def arrowCongrAddEquiv (e₁ : M₁ ≃ₗ[R] M₂) (e₂ : M₂₁ ≃ₗ[R] M₂₂) : + (M₁ →ₗ[R] M₂₁) ≃+ (M₂ →ₗ[R] M₂₂) where + toFun f := e₂.comp (f.comp e₁.symm.toLinearMap) + invFun f := e₂.symm.comp (f.comp e₁.toLinearMap) + left_inv f := by + ext x + simp only [symm_apply_apply, Function.comp_apply, coe_comp, coe_coe] + right_inv f := by + ext x + simp only [Function.comp_apply, apply_symm_apply, coe_comp, coe_coe] + map_add' f g := by + ext x + simp only [map_add, add_apply, Function.comp_apply, coe_comp, coe_coe] + +/-- If `M` and `M₂` are linearly isomorphic then the endomorphism rings of `M` and `M₂` +are isomorphic. + +See `LinearEquiv.conj` for the linear version of this isomorphism. -/ +def conjRingEquiv (e : M₁ ≃ₗ[R] M₂) : Module.End R M₁ ≃+* Module.End R M₂ where + __ := arrowCongrAddEquiv e e + map_mul' _ _ := by ext; simp [arrowCongrAddEquiv] + +end Semiring + section CommSemiring variable [CommSemiring R] [AddCommMonoid M] [AddCommMonoid M₂] [AddCommMonoid M₃] @@ -494,24 +529,15 @@ def smulOfUnit (a : Rˣ) : M ≃ₗ[R] M := DistribMulAction.toLinearEquiv R M a /-- A linear isomorphism between the domains and codomains of two spaces of linear maps gives a -linear isomorphism between the two function spaces. -/ +linear isomorphism between the two function spaces. + +See `LinearEquiv.arrowCongrAddEquiv` for the additive version of this isomorphism that works +over a not necessarily commutative semiring. -/ def arrowCongr {R M₁ M₂ M₂₁ M₂₂ : Sort _} [CommSemiring R] [AddCommMonoid M₁] [AddCommMonoid M₂] [AddCommMonoid M₂₁] [AddCommMonoid M₂₂] [Module R M₁] [Module R M₂] [Module R M₂₁] [Module R M₂₂] (e₁ : M₁ ≃ₗ[R] M₂) (e₂ : M₂₁ ≃ₗ[R] M₂₂) : (M₁ →ₗ[R] M₂₁) ≃ₗ[R] M₂ →ₗ[R] M₂₂ where - toFun := fun f : M₁ →ₗ[R] M₂₁ ↦ (e₂ : M₂₁ →ₗ[R] M₂₂).comp <| f.comp (e₁.symm : M₂ →ₗ[R] M₁) - invFun f := (e₂.symm : M₂₂ →ₗ[R] M₂₁).comp <| f.comp (e₁ : M₁ →ₗ[R] M₂) - left_inv f := by - ext x - simp only [symm_apply_apply, Function.comp_apply, coe_comp, coe_coe] - right_inv f := by - ext x - simp only [Function.comp_apply, apply_symm_apply, coe_comp, coe_coe] - map_add' f g := by - ext x - simp only [map_add, add_apply, Function.comp_apply, coe_comp, coe_coe] - map_smul' c f := by - ext x - simp only [smul_apply, Function.comp_apply, coe_comp, map_smulₛₗ e₂, coe_coe] + __ := arrowCongrAddEquiv e₁ e₂ + map_smul' c f := by ext; simp [arrowCongrAddEquiv] @[simp] theorem arrowCongr_apply {R M₁ M₂ M₂₁ M₂₂ : Sort _} [CommSemiring R] [AddCommMonoid M₁] @@ -547,7 +573,11 @@ def congrRight (f : M₂ ≃ₗ[R] M₃) : (M →ₗ[R] M₂) ≃ₗ[R] M →ₗ arrowCongr (LinearEquiv.refl R M) f /-- If `M` and `M₂` are linearly isomorphic then the two spaces of linear maps from `M` and `M₂` to -themselves are linearly isomorphic. -/ +themselves are linearly isomorphic. + +See `LinearEquiv.conjRingEquiv` for the isomorphism between endomorphism rings, +which works over a not necessarily commutative semiring. -/ +-- TODO: upgrade to AlgEquiv (but this file currently cannot import AlgEquiv) def conj (e : M ≃ₗ[R] M₂) : Module.End R M ≃ₗ[R] Module.End R M₂ := arrowCongr e e @@ -582,12 +612,8 @@ isomorphism between `M₂ →ₗ[R] M` and `M₃ →ₗ[R] M`, if `M` is both an `S`-module and their actions commute. -/ def congrLeft {R} (S) [Semiring R] [Semiring S] [Module R M₂] [Module R M₃] [Module R M] [Module S M] [SMulCommClass R S M] (e : M₂ ≃ₗ[R] M₃) : (M₂ →ₗ[R] M) ≃ₗ[S] (M₃ →ₗ[R] M) where - toFun f := f.comp e.symm.toLinearMap - invFun f := f.comp e.toLinearMap - map_add' _ _ := rfl + __ := e.arrowCongrAddEquiv (.refl ..) map_smul' _ _ := rfl - left_inv f := by dsimp only; apply DFunLike.ext; exact (congr_arg f <| e.left_inv ·) - right_inv f := by dsimp only; apply DFunLike.ext; exact (congr_arg f <| e.right_inv ·) end CommSemiring diff --git a/Mathlib/Algebra/Ring/Subring/Basic.lean b/Mathlib/Algebra/Ring/Subring/Basic.lean index 761bf9815c924..8c113ce263a89 100644 --- a/Mathlib/Algebra/Ring/Subring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subring/Basic.lean @@ -384,6 +384,15 @@ theorem center_eq_top (R) [CommRing R] : center R = ⊤ := instance : CommRing (center R) := { inferInstanceAs (CommSemiring (Subsemiring.center R)), (center R).toRing with } +/-- The center of isomorphic (not necessarily associative) rings are isomorphic. -/ +@[simps!] def centerCongr (e : R ≃+* S) : center R ≃+* center S := + NonUnitalSubsemiring.centerCongr e + +/-- The center of a (not necessarily associative) ring +is isomorphic to the center of its opposite. -/ +@[simps!] def centerToMulOpposite : center R ≃+* center Rᵐᵒᵖ := + NonUnitalSubsemiring.centerToMulOpposite + end section DivisionRing diff --git a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean index e38a8720a241a..65b72af50f1f4 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean @@ -262,6 +262,17 @@ This is not an instance as it forms a non-defeq diamond with abbrev center.commSemiring' : CommSemiring (center R) := { Submonoid.center.commMonoid', (center R).toNonAssocSemiring with } +variable {R} + +/-- The center of isomorphic (not necessarily associative) semirings are isomorphic. -/ +@[simps!] def centerCongr [NonAssocSemiring S] (e : R ≃+* S) : center R ≃+* center S := + NonUnitalSubsemiring.centerCongr e + +/-- The center of a (not necessarily associative) semiring +is isomorphic to the center of its opposite. -/ +@[simps!] def centerToMulOpposite : center R ≃+* center Rᵐᵒᵖ := + NonUnitalSubsemiring.centerToMulOpposite + end NonAssocSemiring section Semiring @@ -285,7 +296,6 @@ instance decidableMemCenter {R} [Semiring R] [DecidableEq R] [Fintype R] : theorem center_eq_top (R) [CommSemiring R] : center R = ⊤ := SetLike.coe_injective (Set.center_eq_univ R) - end Semiring section Centralizer diff --git a/Mathlib/GroupTheory/Subgroup/Center.lean b/Mathlib/GroupTheory/Subgroup/Center.lean index 6dd4dbfa41447..b8dc94177cf81 100644 --- a/Mathlib/GroupTheory/Subgroup/Center.lean +++ b/Mathlib/GroupTheory/Subgroup/Center.lean @@ -40,6 +40,16 @@ theorem center_toSubmonoid : (center G).toSubmonoid = Submonoid.center G := instance center.isCommutative : (center G).IsCommutative := ⟨⟨fun a b => Subtype.ext (b.2.comm a).symm⟩⟩ +variable {G} in +/-- The center of isomorphic groups are isomorphic. -/ +@[to_additive (attr := simps!) "The center of isomorphic additive groups are isomorphic."] +def centerCongr {H} [Group H] (e : G ≃* H) : center G ≃* center H := Submonoid.centerCongr e + +/-- The center of a group is isomorphic to the center of its opposite. -/ +@[to_additive (attr := simps!) +"The center of an additive group is isomorphic to the center of its opposite."] +def centerToMulOpposite : center G ≃* center Gᵐᵒᵖ := Submonoid.centerToMulOpposite + /-- For a group with zero, the center of the units is the same as the units of the center. -/ @[simps! apply_val_coe symm_apply_coe_val] def centerUnitsEquivUnitsCenter (G₀ : Type*) [GroupWithZero G₀] : diff --git a/Mathlib/GroupTheory/Submonoid/Center.lean b/Mathlib/GroupTheory/Submonoid/Center.lean index 44028df37b868..addceff424890 100644 --- a/Mathlib/GroupTheory/Submonoid/Center.lean +++ b/Mathlib/GroupTheory/Submonoid/Center.lean @@ -126,3 +126,61 @@ def unitsCenterToCenterUnits [Monoid M] : (Submonoid.center M)ˣ →* Submonoid. theorem unitsCenterToCenterUnits_injective [Monoid M] : Function.Injective (unitsCenterToCenterUnits M) := fun _a _b h => Units.ext <| Subtype.ext <| congr_arg (Units.val ∘ Subtype.val) h + +section congr + +variable {M} {N : Type*} + +@[to_additive] theorem _root_.MulEquivClass.apply_mem_center {F} [EquivLike F M N] [Mul M] [Mul N] + [MulEquivClass F M N] (e : F) {x : M} (hx : x ∈ Set.center M) : e x ∈ Set.center N := by + let e := MulEquivClass.toMulEquiv e + show e x ∈ Set.center N + constructor <;> + (intros; apply e.symm.injective; + simp only [map_mul, e.symm_apply_apply, (isMulCentral_iff _).mp hx]) + +@[to_additive] theorem _root_.MulEquivClass.apply_mem_center_iff {F} [EquivLike F M N] + [Mul M] [Mul N] [MulEquivClass F M N] (e : F) {x : M} : + e x ∈ Set.center N ↔ x ∈ Set.center M := + ⟨(by simpa using MulEquivClass.apply_mem_center (MulEquivClass.toMulEquiv e).symm ·), + MulEquivClass.apply_mem_center e⟩ + +/-- The center of isomorphic magmas are isomorphic. -/ +@[to_additive (attr := simps) "The center of isomorphic additive magmas are isomorphic."] +def Subsemigroup.centerCongr [Mul M] [Mul N] (e : M ≃* N) : center M ≃* center N where + toFun r := ⟨e r, MulEquivClass.apply_mem_center e r.2⟩ + invFun s := ⟨e.symm s, MulEquivClass.apply_mem_center e.symm s.2⟩ + left_inv _ := Subtype.ext (e.left_inv _) + right_inv _ := Subtype.ext (e.right_inv _) + map_mul' _ _ := Subtype.ext (map_mul ..) + +/-- The center of isomorphic monoids are isomorphic. -/ +@[to_additive (attr := simps!) "The center of isomorphic additive monoids are isomorphic."] +def Submonoid.centerCongr [MulOneClass M] [MulOneClass N] (e : M ≃* N) : center M ≃* center N := + Subsemigroup.centerCongr e + +@[to_additive] theorem MulOpposite.op_mem_center_iff [Mul M] {x : M} : + op x ∈ Set.center Mᵐᵒᵖ ↔ x ∈ Set.center M := by + simp_rw [Set.mem_center_iff, isMulCentral_iff, MulOpposite.forall, ← op_mul, op_inj]; aesop + +@[to_additive] theorem MulOpposite.unop_mem_center_iff [Mul M] {x : Mᵐᵒᵖ} : + unop x ∈ Set.center M ↔ x ∈ Set.center Mᵐᵒᵖ := + op_mem_center_iff.symm + +/-- The center of a magma is isomorphic to the center of its opposite. -/ +@[to_additive (attr := simps) +"The center of an additive magma is isomorphic to the center of its opposite."] +def Subsemigroup.centerToMulOpposite [Mul M] : center M ≃* center Mᵐᵒᵖ where + toFun r := ⟨_, MulOpposite.op_mem_center_iff.mpr r.2⟩ + invFun r := ⟨_, MulOpposite.unop_mem_center_iff.mpr r.2⟩ + left_inv _ := rfl + right_inv _ := rfl + map_mul' r _ := Subtype.ext (congr_arg MulOpposite.op <| r.2.1 _) + +/-- The center of a monoid is isomorphic to the center of its opposite. -/ +@[to_additive (attr := simps!) +"The center of an additive monoid is isomorphic to the center of its opposite. "] +def Submonoid.centerToMulOpposite [MulOneClass M] : center M ≃* center Mᵐᵒᵖ := + Subsemigroup.centerToMulOpposite + +end congr diff --git a/Mathlib/RepresentationTheory/Character.lean b/Mathlib/RepresentationTheory/Character.lean index ada933887ae23..6dc6591865ab8 100644 --- a/Mathlib/RepresentationTheory/Character.lean +++ b/Mathlib/RepresentationTheory/Character.lean @@ -115,7 +115,7 @@ theorem char_orthonormal (V W : FDRep k G) [Simple V] [Simple W] : rw [char_iso (FDRep.dualTensorIsoLinHom W.ρ V)] -- The average over the group of the character of a representation equals the dimension of the -- space of invariants. - rw [average_char_eq_finrank_invariants, ← FDRep.endMulEquiv_comp_ρ (of _), + rw [average_char_eq_finrank_invariants, ← FDRep.endRingEquiv_comp_ρ (of _), FDRep.of_ρ (linHom W.ρ V.ρ)] -- The space of invariants of `Hom(W, V)` is the subspace of `G`-equivariant linear maps, -- `Hom_G(W, V)`. diff --git a/Mathlib/RepresentationTheory/FDRep.lean b/Mathlib/RepresentationTheory/FDRep.lean index dd5870c18de16..dae66e0f2aa47 100644 --- a/Mathlib/RepresentationTheory/FDRep.lean +++ b/Mathlib/RepresentationTheory/FDRep.lean @@ -82,15 +82,16 @@ instance (V W : FDRep k G) : FiniteDimensional k (V ⟶ W) := /-- The monoid homomorphism corresponding to the action of `G` onto `V : FDRep k G`. -/ def ρ (V : FDRep k G) : G →* V →ₗ[k] V := - (ModuleCat.endMulEquiv _).toMonoidHom.comp (Action.ρ V) + (ModuleCat.endRingEquiv _).toMonoidHom.comp (Action.ρ V) @[simp] -lemma endMulEquiv_symm_comp_ρ (V : FDRep k G) : - (MonoidHomClass.toMonoidHom (ModuleCat.endMulEquiv V.V.obj).symm).comp (ρ V) = Action.ρ V := rfl +lemma endRingEquiv_symm_comp_ρ (V : FDRep k G) : + (MonoidHomClass.toMonoidHom (ModuleCat.endRingEquiv V.V.obj).symm).comp (ρ V) = Action.ρ V := + rfl @[simp] -lemma endMulEquiv_comp_ρ (V : FDRep k G) : - (MonoidHomClass.toMonoidHom (ModuleCat.endMulEquiv V.V.obj)).comp (Action.ρ V) = ρ V := rfl +lemma endRingEquiv_comp_ρ (V : FDRep k G) : + (MonoidHomClass.toMonoidHom (ModuleCat.endRingEquiv V.V.obj)).comp (Action.ρ V) = ρ V := rfl @[simp] lemma hom_action_ρ (V : FDRep k G) (g : G) : (Action.ρ V g).hom = ρ V g := rfl @@ -111,7 +112,7 @@ theorem Iso.conj_ρ {V W : FDRep k G} (i : V ≅ W) (g : G) : @[simps ρ] def of {V : Type u} [AddCommGroup V] [Module k V] [FiniteDimensional k V] (ρ : Representation k G V) : FDRep k G := - ⟨FGModuleCat.of k V, ρ ≫ MonCat.ofHom (ModuleCat.endMulEquiv _).symm.toMonoidHom⟩ + ⟨FGModuleCat.of k V, ρ ≫ MonCat.ofHom (ModuleCat.endRingEquiv _).symm.toMonoidHom⟩ instance : HasForget₂ (FDRep k G) (Rep k G) where forget₂ := (forget₂ (FGModuleCat k) (ModuleCat k)).mapAction (MonCat.of G) diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index 68e82a8670b12..b5bf54039d5d6 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -61,11 +61,11 @@ instance (V : Rep k G) : Module k V := by -/ def ρ (V : Rep k G) : Representation k G V := -- Porting note: was `V.ρ` - (ModuleCat.endMulEquiv V.V).toMonoidHom.comp (Action.ρ V) + (ModuleCat.endRingEquiv V.V).toMonoidHom.comp (Action.ρ V) /-- Lift an unbundled representation to `Rep`. -/ def of {V : Type u} [AddCommGroup V] [Module k V] (ρ : G →* V →ₗ[k] V) : Rep k G := - ⟨ModuleCat.of k V, MonCat.ofHom ((ModuleCat.endMulEquiv _).symm.toMonoidHom.comp ρ) ⟩ + ⟨ModuleCat.of k V, MonCat.ofHom ((ModuleCat.endRingEquiv _).symm.toMonoidHom.comp ρ) ⟩ @[simp] theorem coe_of {V : Type u} [AddCommGroup V] [Module k V] (ρ : G →* V →ₗ[k] V) : @@ -77,7 +77,7 @@ theorem of_ρ {V : Type u} [AddCommGroup V] [Module k V] (ρ : G →* V →ₗ[k rfl theorem Action_ρ_eq_ρ {A : Rep k G} : - Action.ρ A = (ModuleCat.endMulEquiv _).symm.toMonoidHom.comp A.ρ := + Action.ρ A = (ModuleCat.endRingEquiv _).symm.toMonoidHom.comp A.ρ := rfl @[simp] diff --git a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean index 35474da03eabb..ecf3da187d103 100644 --- a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean @@ -342,6 +342,17 @@ instance center.instNonUnitalCommRing : NonUnitalCommRing (center R) := { NonUnitalSubsemiring.center.instNonUnitalCommSemiring R, inferInstanceAs <| NonUnitalNonAssocRing (center R) with } +variable {R} + +/-- The center of isomorphic (not necessarily unital or associative) rings are isomorphic. -/ +@[simps!] def centerCongr {S} [NonUnitalNonAssocRing S] (e : R ≃+* S) : center R ≃+* center S := + NonUnitalSubsemiring.centerCongr e + +/-- The center of a (not necessarily uintal or associative) ring +is isomorphic to the center of its opposite. -/ +@[simps!] def centerToMulOpposite : center R ≃+* center Rᵐᵒᵖ := + NonUnitalSubsemiring.centerToMulOpposite + end NonUnitalNonAssocRing section NonUnitalRing diff --git a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean index 61c5c358fc66c..76b1cd54c6879 100644 --- a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean @@ -10,8 +10,10 @@ import Mathlib.Algebra.Group.Subsemigroup.Operations import Mathlib.Algebra.GroupWithZero.Center import Mathlib.Algebra.Ring.Center import Mathlib.Algebra.Ring.Centralizer +import Mathlib.Algebra.Ring.Opposite import Mathlib.Algebra.Ring.Prod import Mathlib.Data.Set.Finite.Range +import Mathlib.GroupTheory.Submonoid.Center import Mathlib.GroupTheory.Subsemigroup.Centralizer import Mathlib.RingTheory.NonUnitalSubsemiring.Defs @@ -245,6 +247,19 @@ lemma _root_.Set.mem_center_iff_addMonoidHom (a : R) : rw [Set.mem_center_iff, isMulCentral_iff] simp [DFunLike.ext_iff] +variable {R} + +/-- The center of isomorphic (not necessarily unital or associative) semirings are isomorphic. -/ +@[simps!] def centerCongr [NonUnitalNonAssocSemiring S] (e : R ≃+* S) : center R ≃+* center S where + __ := Subsemigroup.centerCongr e + map_add' _ _ := Subtype.ext <| by exact map_add e .. + +/-- The center of a (not necessarily unital or associative) semiring +is isomorphic to the center of its opposite. -/ +@[simps!] def centerToMulOpposite : center R ≃+* center Rᵐᵒᵖ where + __ := Subsemigroup.centerToMulOpposite + map_add' _ _ := rfl + end NonUnitalNonAssocSemiring section NonUnitalSemiring From fdcb7c69f674333c7541c0f62d365115a9f748a7 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Sun, 26 Jan 2025 18:41:40 +0000 Subject: [PATCH 542/681] feat: state `PEquiv.equiv_toPEquiv_toMatrix` in terms of `submatrix` (#21089) This matches the prose more closely, and also means lemmas about `submatrix` can be used. --- Mathlib/Data/Matrix/PEquiv.lean | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mathlib/Data/Matrix/PEquiv.lean b/Mathlib/Data/Matrix/PEquiv.lean index eb70fede2430c..17259b93851a3 100644 --- a/Mathlib/Data/Matrix/PEquiv.lean +++ b/Mathlib/Data/Matrix/PEquiv.lean @@ -152,8 +152,8 @@ theorem single_mul_single_right [Fintype n] [Fintype k] [DecidableEq n] [Decidab rw [← Matrix.mul_assoc, single_mul_single] /-- We can also define permutation matrices by permuting the rows of the identity matrix. -/ -theorem equiv_toPEquiv_toMatrix [DecidableEq n] [Zero α] [One α] (σ : Equiv n n) (i j : n) : - σ.toPEquiv.toMatrix i j = (1 : Matrix n n α) (σ i) j := - if_congr Option.some_inj rfl rfl +theorem equiv_toPEquiv_toMatrix [DecidableEq n] [Zero α] [One α] (σ : Equiv n n) : + σ.toPEquiv.toMatrix = (1 : Matrix n n α).submatrix σ id := + Matrix.ext fun _ _ => if_congr Option.some_inj rfl rfl end PEquiv From d45ceb432b8e804b989aba92eeda7895f2f58f8a Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Sun, 26 Jan 2025 18:51:20 +0000 Subject: [PATCH 543/681] chore: update Mathlib dependencies 2025-01-26 (#21100) 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 7cc60c94958f9..7373536114b5d 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "5b23a1297aba9683f231c4b1a7ab4076af4ad53d", + "rev": "383137545783429af1317226778fd44869a711e2", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 0b484e169f7f49dc0708e35505da829a9e1699b0 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Sun, 26 Jan 2025 20:04:56 +0000 Subject: [PATCH 544/681] chore: deduplicate proof that coproduct of separating set is separator (#21081) Co-authored-by: Markus Himmel --- Mathlib.lean | 1 - Mathlib/CategoryTheory/Generator/Basic.lean | 20 ++++++--- .../CategoryTheory/Generator/Coproduct.lean | 43 ------------------- .../CategoryTheory/Generator/Presheaf.lean | 2 +- 4 files changed, 14 insertions(+), 52 deletions(-) delete mode 100644 Mathlib/CategoryTheory/Generator/Coproduct.lean diff --git a/Mathlib.lean b/Mathlib.lean index e5041a5fd5c1b..5d48b98ae5aef 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1845,7 +1845,6 @@ import Mathlib.CategoryTheory.Galois.Prorepresentability import Mathlib.CategoryTheory.Galois.Topology import Mathlib.CategoryTheory.Generator.Abelian import Mathlib.CategoryTheory.Generator.Basic -import Mathlib.CategoryTheory.Generator.Coproduct import Mathlib.CategoryTheory.Generator.Preadditive import Mathlib.CategoryTheory.Generator.Presheaf import Mathlib.CategoryTheory.Generator.Sheaf diff --git a/Mathlib/CategoryTheory/Generator/Basic.lean b/Mathlib/CategoryTheory/Generator/Basic.lean index 049514c52cef9..70168c6d7626d 100644 --- a/Mathlib/CategoryTheory/Generator/Basic.lean +++ b/Mathlib/CategoryTheory/Generator/Basic.lean @@ -527,15 +527,21 @@ theorem isSeparator_coprod_of_isSeparator_right (G H : C) [HasBinaryCoproduct G (hH : IsSeparator H) : IsSeparator (G ⨿ H) := (isSeparator_coprod _ _).2 <| IsSeparating.mono hH <| by simp +lemma isSeparator_of_isColimit_cofan {β : Type w} {f : β → C} + (hf : IsSeparating (Set.range f)) {c : Cofan f} (hc : IsColimit c) : IsSeparator c.pt := by + refine (isSeparator_def _).2 fun X Y u v huv => hf _ _ fun Z hZ g => ?_ + obtain ⟨b, rfl⟩ := Set.mem_range.1 hZ + classical simpa using c.ι.app ⟨b⟩ ≫= huv (hc.desc (Cofan.mk _ (Pi.single b g))) + theorem isSeparator_sigma {β : Type w} (f : β → C) [HasCoproduct f] : IsSeparator (∐ f) ↔ IsSeparating (Set.range f) := by - refine - ⟨fun h X Y u v huv => ?_, fun h => - (isSeparator_def _).2 fun X Y u v huv => h _ _ fun Z hZ g => ?_⟩ - · refine h.def _ _ fun g => colimit.hom_ext fun b => ?_ - simpa using huv (f b.as) (by simp) (colimit.ι (Discrete.functor f) _ ≫ g) - · obtain ⟨b, rfl⟩ := Set.mem_range.1 hZ - classical simpa using Sigma.ι f b ≫= huv (Sigma.desc (Pi.single b g)) + refine ⟨fun h X Y u v huv => ?_, fun h => isSeparator_of_isColimit_cofan h (colimit.isColimit _)⟩ + refine h.def _ _ fun g => colimit.hom_ext fun b => ?_ + simpa using huv (f b.as) (by simp) (colimit.ι (Discrete.functor f) _ ≫ g) + +theorem IsSeparating.isSeparator_coproduct {β : Type w} {f : β → C} [HasCoproduct f] + (hS : IsSeparating (Set.range f)) : IsSeparator (∐ f) := + (isSeparator_sigma _).2 hS theorem isSeparator_sigma_of_isSeparator {β : Type w} (f : β → C) [HasCoproduct f] (b : β) (hb : IsSeparator (f b)) : IsSeparator (∐ f) := diff --git a/Mathlib/CategoryTheory/Generator/Coproduct.lean b/Mathlib/CategoryTheory/Generator/Coproduct.lean deleted file mode 100644 index 0e948301d4819..0000000000000 --- a/Mathlib/CategoryTheory/Generator/Coproduct.lean +++ /dev/null @@ -1,43 +0,0 @@ -/- -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.CategoryTheory.Generator.Basic -import Mathlib.CategoryTheory.Limits.Shapes.Products - -/-! -# The coproduct of a separating family of objects is separating - -If a family of objects `S : ι → C` in a category with zero morphisms -is separating, then the coproduct of `S` is a separator in `C`. - --/ - -universe w v u - -namespace CategoryTheory.IsSeparating - -open Limits - -variable {C : Type u} [Category.{v} C] [HasZeroMorphisms C] - {ι : Type w} {S : ι → C} - -open Classical in -lemma isSeparator_of_isColimit_cofan - (hS : IsSeparating (Set.range S)) {c : Cofan S} (hc : IsColimit c) : - IsSeparator c.pt := by - intro X Y f g h - apply hS - rintro _ ⟨i, rfl⟩ α - let β : c.pt ⟶ X := Cofan.IsColimit.desc hc - (fun j ↦ if hij : i = j then eqToHom (by rw [hij]) ≫ α else 0) - have hβ : c.inj i ≫ β = α := by simp [β] - simp only [← hβ, Category.assoc, h c.pt (by simp) β] - -lemma isSeparator_coproduct (hS : IsSeparating (Set.range S)) [HasCoproduct S] : - IsSeparator (∐ S) := - isSeparator_of_isColimit_cofan hS (colimit.isColimit _) - -end CategoryTheory.IsSeparating diff --git a/Mathlib/CategoryTheory/Generator/Presheaf.lean b/Mathlib/CategoryTheory/Generator/Presheaf.lean index d12ab50d4882a..61042589d44a2 100644 --- a/Mathlib/CategoryTheory/Generator/Presheaf.lean +++ b/Mathlib/CategoryTheory/Generator/Presheaf.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.Generator.Coproduct +import Mathlib.CategoryTheory.Generator.Basic import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic /-! From 1a2855bcafb0b3a2ff91f7cd89d20cab1db77460 Mon Sep 17 00:00:00 2001 From: Chris Hughes Date: Sun, 26 Jan 2025 21:04:08 +0000 Subject: [PATCH 545/681] chore(GroupTheory/OrderOfElement): Use Nat.divisors (#21077) --- Mathlib/GroupTheory/OrderOfElement.lean | 27 +++++-------------- .../GroupTheory/SpecificGroups/Cyclic.lean | 6 ++--- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index a53461a680fb8..4a207ce12d1ef 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -10,6 +10,7 @@ import Mathlib.Algebra.Order.Group.Action import Mathlib.Algebra.Order.Ring.Abs import Mathlib.Dynamics.PeriodicPts.Lemmas import Mathlib.GroupTheory.Index +import Mathlib.NumberTheory.Divisors import Mathlib.Order.Interval.Set.Infinite import Mathlib.Tactic.Positivity @@ -689,28 +690,12 @@ variable [Monoid G] {x : G} {n : ℕ} @[to_additive] theorem sum_card_orderOf_eq_card_pow_eq_one [Fintype G] [DecidableEq G] (hn : n ≠ 0) : - (∑ m ∈ (Finset.range n.succ).filter (· ∣ n), + (∑ m ∈ divisors n, (Finset.univ.filter fun x : G => orderOf x = m).card) = - (Finset.univ.filter fun x : G => x ^ n = 1).card := - calc - (∑ m ∈ (Finset.range n.succ).filter (· ∣ n), - (Finset.univ.filter fun x : G => orderOf x = m).card) = _ := - (Finset.card_biUnion - (by - intros - apply Finset.disjoint_filter.2 - rintro _ _ rfl; assumption)).symm - _ = _ := - congr_arg Finset.card - (Finset.ext - (by - intro x - suffices orderOf x ≤ n ∧ orderOf x ∣ n ↔ x ^ n = 1 by simpa [Nat.lt_succ_iff] - exact - ⟨fun h => by - let ⟨m, hm⟩ := h.2 - rw [hm, pow_mul, pow_orderOf_eq_one, one_pow], fun h => - ⟨orderOf_le_of_pow_eq_one hn.bot_lt h, orderOf_dvd_of_pow_eq_one h⟩⟩)) + (Finset.univ.filter fun x : G => x ^ n = 1).card := by + refine (Finset.card_biUnion ?_).symm.trans ?_ + · simp +contextual [disjoint_iff, Finset.ext_iff] + · congr; ext; simp [hn, orderOf_dvd_iff_pow_eq_one] @[to_additive] theorem orderOf_le_card_univ [Fintype G] : orderOf x ≤ Fintype.card G := diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index 44e9501b1c31a..d000af6ee0f64 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -456,8 +456,8 @@ private theorem card_orderOf_eq_totient_aux₁ {d : ℕ} (hd : d ∣ Fintype.car have h2 : (∑ m ∈ d.divisors, #{a : α | orderOf a = m}) = ∑ m ∈ d.divisors, φ m := by - rw [← filter_dvd_eq_divisors hd0, sum_card_orderOf_eq_card_pow_eq_one hd0, - filter_dvd_eq_divisors hd0, sum_totient, ← ha, card_pow_eq_one_eq_orderOf_aux hn a] + rw [sum_card_orderOf_eq_card_pow_eq_one hd0, sum_totient, + ← ha, card_pow_eq_one_eq_orderOf_aux hn a] simpa [← cons_self_properDivisors hd0, ← h1] using h2 @[to_additive] @@ -472,7 +472,7 @@ theorem card_orderOf_eq_totient_aux₂ {d : ℕ} (hd : d ∣ Fintype.card α) : apply lt_irrefl c calc c = ∑ m ∈ c.divisors, #{a : α | orderOf a = m} := by - simp only [← filter_dvd_eq_divisors hc0.ne', sum_card_orderOf_eq_card_pow_eq_one hc0.ne'] + simp only [sum_card_orderOf_eq_card_pow_eq_one hc0.ne'] apply congr_arg card simp [c] _ = ∑ m ∈ c.divisors.erase d, #{a : α | orderOf a = m} := by From 75641346318b534cf439fb119368029b122a0199 Mon Sep 17 00:00:00 2001 From: damiano Date: Sun, 26 Jan 2025 23:20:12 +0000 Subject: [PATCH 546/681] doc(ComputeDegree): typos (#21095) --- Mathlib/Tactic/ComputeDegree.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/Tactic/ComputeDegree.lean b/Mathlib/Tactic/ComputeDegree.lean index f94993bf7de95..f82b8e0189765 100644 --- a/Mathlib/Tactic/ComputeDegree.lean +++ b/Mathlib/Tactic/ComputeDegree.lean @@ -440,14 +440,14 @@ def miscomputedDegree? (deg : Expr) : List Expr → List MessageData * `degree f ≤ d`, * `coeff f d = r`, if `d` is the degree of `f`. -The tactic may leave goals of the form `d' = d` `d' ≤ d`, or `r ≠ 0`, where `d'` in `ℕ` or +The tactic may leave goals of the form `d' = d`, `d' ≤ d`, or `r ≠ 0`, where `d'` in `ℕ` or `WithBot ℕ` is the tactic's guess of the degree, and `r` is the coefficient's guess of the leading coefficient of `f`. `compute_degree` applies `norm_num` to the left-hand side of all side goals, trying to close them. The variant `compute_degree!` first applies `compute_degree`. -Then it uses `norm_num` on all the whole remaining goals and tries `assumption`. +Then it uses `norm_num` on all the remaining goals and tries `assumption`. -/ syntax (name := computeDegree) "compute_degree" "!"? : tactic From eec31174e373348bbf22a745311357bd8e1d1045 Mon Sep 17 00:00:00 2001 From: Laurance Lau Date: Sun, 26 Jan 2025 23:58:51 +0000 Subject: [PATCH 547/681] doc(Algebra/BigOperators/Fin): change 'product' to 'sum' in doc-string of additivised declarations (#21101) The additivised declarations speak about sums: probably, this was a copy-paste error. --- Mathlib/Algebra/BigOperators/Fin.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/BigOperators/Fin.lean b/Mathlib/Algebra/BigOperators/Fin.lean index 2a445b2244dcc..5e74ef85d66a6 100644 --- a/Mathlib/Algebra/BigOperators/Fin.lean +++ b/Mathlib/Algebra/BigOperators/Fin.lean @@ -55,7 +55,7 @@ theorem prod_univ_zero [CommMonoid β] (f : Fin 0 → β) : ∏ i, f i = 1 := /-- A product of a function `f : Fin (n + 1) → β` over all `Fin (n + 1)` is the product of `f x`, for some `x : Fin (n + 1)` times the remaining product -/ @[to_additive "A sum of a function `f : Fin (n + 1) → β` over all `Fin (n + 1)` is the sum of -`f x`, for some `x : Fin (n + 1)` plus the remaining product"] +`f x`, for some `x : Fin (n + 1)` plus the remaining sum"] theorem prod_univ_succAbove [CommMonoid β] {n : ℕ} (f : Fin (n + 1) → β) (x : Fin (n + 1)) : ∏ i, f i = f x * ∏ i : Fin n, f (x.succAbove i) := by rw [univ_succAbove, prod_cons, Finset.prod_map _ x.succAboveEmb] @@ -64,7 +64,7 @@ theorem prod_univ_succAbove [CommMonoid β] {n : ℕ} (f : Fin (n + 1) → β) ( /-- A product of a function `f : Fin (n + 1) → β` over all `Fin (n + 1)` is the product of `f 0` plus the remaining product -/ @[to_additive "A sum of a function `f : Fin (n + 1) → β` over all `Fin (n + 1)` is the sum of -`f 0` plus the remaining product"] +`f 0` plus the remaining sum"] theorem prod_univ_succ [CommMonoid β] {n : ℕ} (f : Fin (n + 1) → β) : ∏ i, f i = f 0 * ∏ i : Fin n, f i.succ := prod_univ_succAbove f 0 From 77d9317db1da3abe4a844826b99df497683e4c91 Mon Sep 17 00:00:00 2001 From: Kevin Buzzard Date: Mon, 27 Jan 2025 01:57:05 +0000 Subject: [PATCH 548/681] chore(Algebra/Group/Submonoid/Operations): move instances to new file (#21067) Move declarations such as `Submonoid.smul` and `Submonoid.mulAction` into a new file, and shake some imports. --- Mathlib.lean | 1 + .../Algebra/Group/Submonoid/MulAction.lean | 69 ++++++++++++++++++ .../Algebra/Group/Submonoid/Operations.lean | 70 +------------------ Mathlib/Algebra/Module/Submodule/Defs.lean | 1 + Mathlib/Algebra/Polynomial/Basic.lean | 1 + Mathlib/GroupTheory/GroupAction/Defs.lean | 2 +- .../GroupTheory/MonoidLocalization/Basic.lean | 1 + .../GroupTheory/OreLocalization/Basic.lean | 3 +- Mathlib/Topology/Algebra/Monoid.lean | 1 + 9 files changed, 80 insertions(+), 69 deletions(-) create mode 100644 Mathlib/Algebra/Group/Submonoid/MulAction.lean diff --git a/Mathlib.lean b/Mathlib.lean index 5d48b98ae5aef..c7575c572829a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -355,6 +355,7 @@ import Mathlib.Algebra.Group.Submonoid.Defs import Mathlib.Algebra.Group.Submonoid.DistribMulAction import Mathlib.Algebra.Group.Submonoid.Finsupp import Mathlib.Algebra.Group.Submonoid.Membership +import Mathlib.Algebra.Group.Submonoid.MulAction import Mathlib.Algebra.Group.Submonoid.MulOpposite import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.Group.Submonoid.Pointwise diff --git a/Mathlib/Algebra/Group/Submonoid/MulAction.lean b/Mathlib/Algebra/Group/Submonoid/MulAction.lean new file mode 100644 index 0000000000000..7c37bc72c9f08 --- /dev/null +++ b/Mathlib/Algebra/Group/Submonoid/MulAction.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2021 Eric Wieser. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Eric Wieser +-/ +import Mathlib.Algebra.Group.Submonoid.Defs +import Mathlib.Algebra.Group.Action.Defs + +/-! +# Actions by `Submonoid`s + +These instances transfer the action by an element `m : M` of a monoid `M` written as `m • a` onto +the action by an element `s : S` of a submonoid `S : Submonoid M` such that `s • a = (s : M) • a`. + +These instances work particularly well in conjunction with `Monoid.toMulAction`, enabling +`s • m` as an alias for `↑s * m`. +-/ + +namespace Submonoid + +variable {M' : Type*} {α β : Type*} + +section MulOneClass + +variable [MulOneClass M'] + +@[to_additive] +instance smul [SMul M' α] (S : Submonoid M') : SMul S α := + SMul.comp _ S.subtype + +@[to_additive] +instance smulCommClass_left [SMul M' β] [SMul α β] [SMulCommClass M' α β] + (S : Submonoid M') : SMulCommClass S α β := + ⟨fun a _ _ => smul_comm (a : M') _ _⟩ + +@[to_additive] +instance smulCommClass_right [SMul α β] [SMul M' β] [SMulCommClass α M' β] + (S : Submonoid M') : SMulCommClass α S β := + ⟨fun a s => smul_comm a (s : M')⟩ + +/-- Note that this provides `IsScalarTower S M' M'` which is needed by `SMulMulAssoc`. -/ +instance isScalarTower [SMul α β] [SMul M' α] [SMul M' β] [IsScalarTower M' α β] + (S : Submonoid M') : + IsScalarTower S α β := + ⟨fun a => smul_assoc (a : M')⟩ + +section SMul +variable [SMul M' α] {S : Submonoid M'} + +@[to_additive] lemma smul_def (g : S) (a : α) : g • a = (g : M') • a := rfl + +@[to_additive (attr := simp)] +lemma mk_smul (g : M') (hg : g ∈ S) (a : α) : (⟨g, hg⟩ : S) • a = g • a := rfl + +end SMul +end MulOneClass + +variable [Monoid M'] + +/-- The action by a submonoid is the action by the underlying monoid. -/ +@[to_additive + "The additive action by an `AddSubmonoid` is the action by the underlying `AddMonoid`. "] +instance mulAction [MulAction M' α] (S : Submonoid M') : MulAction S α where + one_smul := one_smul M' + mul_smul m₁ m₂ := mul_smul (m₁ : M') m₂ + +example {S : Submonoid M'} : IsScalarTower S M' M' := by infer_instance + +end Submonoid diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index 9037ade39062b..a997c5650f854 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.Group.Action.Faithful import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Submonoid.Basic +import Mathlib.Algebra.Group.Submonoid.MulAction import Mathlib.Algebra.Group.TypeTags.Basic /-! @@ -973,75 +974,10 @@ theorem Submonoid.equivMapOfInjective_coe_mulEquiv (e : M ≃* N) : ext rfl -section Actions - -/-! ### Actions by `Submonoid`s - -These instances transfer the action by an element `m : M` of a monoid `M` written as `m • a` onto -the action by an element `s : S` of a submonoid `S : Submonoid M` such that `s • a = (s : M) • a`. - -These instances work particularly well in conjunction with `Monoid.toMulAction`, enabling -`s • m` as an alias for `↑s * m`. --/ - - -namespace Submonoid - -variable {M' : Type*} {α β : Type*} - -section MulOneClass - -variable [MulOneClass M'] - -@[to_additive] -instance smul [SMul M' α] (S : Submonoid M') : SMul S α := - SMul.comp _ S.subtype - -@[to_additive] -instance smulCommClass_left [SMul M' β] [SMul α β] [SMulCommClass M' α β] - (S : Submonoid M') : SMulCommClass S α β := - ⟨fun a _ _ => smul_comm (a : M') _ _⟩ - -@[to_additive] -instance smulCommClass_right [SMul α β] [SMul M' β] [SMulCommClass α M' β] - (S : Submonoid M') : SMulCommClass α S β := - ⟨fun a s => smul_comm a (s : M')⟩ - -/-- Note that this provides `IsScalarTower S M' M'` which is needed by `SMulMulAssoc`. -/ -instance isScalarTower [SMul α β] [SMul M' α] [SMul M' β] [IsScalarTower M' α β] - (S : Submonoid M') : - IsScalarTower S α β := - ⟨fun a => smul_assoc (a : M')⟩ - -section SMul -variable [SMul M' α] {S : Submonoid M'} - -@[to_additive] lemma smul_def (g : S) (a : α) : g • a = (g : M') • a := rfl - -@[to_additive (attr := simp)] -lemma mk_smul (g : M') (hg : g ∈ S) (a : α) : (⟨g, hg⟩ : S) • a = g • a := rfl - -instance faithfulSMul [FaithfulSMul M' α] : FaithfulSMul S α := +instance Submonoid.faithfulSMul {M' α : Type*} [MulOneClass M'] [SMul M' α] {S : Submonoid M'} + [FaithfulSMul M' α] : FaithfulSMul S α := ⟨fun h => Subtype.ext <| eq_of_smul_eq_smul h⟩ -end SMul -end MulOneClass - -variable [Monoid M'] - -/-- The action by a submonoid is the action by the underlying monoid. -/ -@[to_additive - "The additive action by an `AddSubmonoid` is the action by the underlying `AddMonoid`. "] -instance mulAction [MulAction M' α] (S : Submonoid M') : MulAction S α := - MulAction.compHom _ S.subtype - -example {S : Submonoid M'} : IsScalarTower S M' M' := by infer_instance - - -end Submonoid - -end Actions - section Units namespace Submonoid diff --git a/Mathlib/Algebra/Module/Submodule/Defs.lean b/Mathlib/Algebra/Module/Submodule/Defs.lean index 55faba7453264..50ffade02ba27 100644 --- a/Mathlib/Algebra/Module/Submodule/Defs.lean +++ b/Mathlib/Algebra/Module/Submodule/Defs.lean @@ -5,6 +5,7 @@ Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro -/ import Mathlib.Algebra.Group.Subgroup.Defs import Mathlib.GroupTheory.GroupAction.SubMulAction +import Mathlib.Algebra.Group.Submonoid.Basic /-! diff --git a/Mathlib/Algebra/Polynomial/Basic.lean b/Mathlib/Algebra/Polynomial/Basic.lean index 4a0d9b37f9a1d..880597eb13c1f 100644 --- a/Mathlib/Algebra/Polynomial/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Basic.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.MonoidAlgebra.Defs import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop import Mathlib.Data.Finset.Sort import Mathlib.Tactic.FastInstance +import Mathlib.Algebra.Group.Submonoid.Operations /-! # Theory of univariate polynomials diff --git a/Mathlib/GroupTheory/GroupAction/Defs.lean b/Mathlib/GroupTheory/GroupAction/Defs.lean index d2cba75e644f6..fe04a1f0932df 100644 --- a/Mathlib/GroupTheory/GroupAction/Defs.lean +++ b/Mathlib/GroupTheory/GroupAction/Defs.lean @@ -5,8 +5,8 @@ Authors: Chris Hughes -/ import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Group.Subgroup.Defs -import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.GroupWithZero.Action.Defs +import Mathlib.Algebra.Group.Submonoid.MulAction /-! # Definition of `orbit`, `fixedPoints` and `stabilizer` diff --git a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean index 69ac2dcd67706..c1d5b153c65e4 100644 --- a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean +++ b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean @@ -6,6 +6,7 @@ Authors: Amelia Livingston import Mathlib.Algebra.Group.Submonoid.Defs import Mathlib.GroupTheory.Congruence.Hom import Mathlib.GroupTheory.OreLocalization.Basic +import Mathlib.Algebra.Group.Submonoid.Operations /-! # Localizations of commutative monoids diff --git a/Mathlib/GroupTheory/OreLocalization/Basic.lean b/Mathlib/GroupTheory/OreLocalization/Basic.lean index 24b43521f550b..356e809eb79d9 100644 --- a/Mathlib/GroupTheory/OreLocalization/Basic.lean +++ b/Mathlib/GroupTheory/OreLocalization/Basic.lean @@ -3,9 +3,10 @@ Copyright (c) 2022 Jakob von Raumer. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jakob von Raumer, Kevin Klinge, Andrew Yang -/ -import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.GroupTheory.OreLocalization.OreSet import Mathlib.Tactic.Common +import Mathlib.Algebra.Group.Submonoid.MulAction +import Mathlib.Algebra.Group.Units.Defs /-! diff --git a/Mathlib/Topology/Algebra/Monoid.lean b/Mathlib/Topology/Algebra/Monoid.lean index f136b5fd39568..2cfc9ff7764f6 100644 --- a/Mathlib/Topology/Algebra/Monoid.lean +++ b/Mathlib/Topology/Algebra/Monoid.lean @@ -9,6 +9,7 @@ import Mathlib.Topology.Algebra.MulAction import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.Group.ULift import Mathlib.Topology.ContinuousMap.Defs +import Mathlib.Algebra.Group.Submonoid.Basic /-! # Theory of topological monoids From a02b5327b943254e9f640deaccb4179429b0109f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Mon, 27 Jan 2025 02:33:03 +0000 Subject: [PATCH 549/681] =?UTF-8?q?chore:=20golf=20using=20`funext?= =?UTF-8?q?=E2=82=82`=20(#21106)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/Order/Antisymmetrization.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Order/Antisymmetrization.lean b/Mathlib/Order/Antisymmetrization.lean index a64b7b3da17a8..1ec2f0a774711 100644 --- a/Mathlib/Order/Antisymmetrization.lean +++ b/Mathlib/Order/Antisymmetrization.lean @@ -40,7 +40,7 @@ def AntisymmRel (a b : α) : Prop := r a b ∧ r b a theorem antisymmRel_swap : AntisymmRel (swap r) = AntisymmRel r := - funext fun _ => funext fun _ => propext and_comm + funext₂ fun _ _ ↦ propext and_comm @[refl] theorem antisymmRel_refl [IsRefl α r] (a : α) : AntisymmRel r a a := From ff6124cf633a03b75f7025ca3b7060280d4d2d92 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Mon, 27 Jan 2025 04:24:54 +0000 Subject: [PATCH 550/681] chore(Fintype): golf a proof (#21113) ... by reusing an existing lemma. --- Mathlib/Data/Fintype/Basic.lean | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index ff4691dc54789..3207bf60506dd 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -1060,11 +1060,7 @@ variable [Fintype α] [DecidableEq β] {f : α → β} /-- `bijInv f` is the unique inverse to a bijection `f`. This acts as a computable alternative to `Function.invFun`. -/ def bijInv (f_bij : Bijective f) (b : β) : α := - Fintype.choose (fun a => f a = b) - (by - rcases f_bij.right b with ⟨a', fa_eq_b⟩ - rw [← fa_eq_b] - exact ⟨a', ⟨rfl, fun a h => f_bij.left h⟩⟩) + Fintype.choose (fun a => f a = b) (f_bij.existsUnique b) theorem leftInverse_bijInv (f_bij : Bijective f) : LeftInverse (bijInv f_bij) f := fun a => f_bij.left (choose_spec (fun a' => f a' = f a) _) From 55b933aaa1ceff33ed74f6bb477a6877ab0238cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Mon, 27 Jan 2025 05:02:08 +0000 Subject: [PATCH 551/681] feat: derivWithin lemmas (#21092) New lemmas: `derivWithin_zero`, `derivWithin_mul_const_field`, `derivWithin_const_mul_field`. --- Mathlib/Analysis/Calculus/Deriv/Basic.lean | 3 +++ Mathlib/Analysis/Calculus/Deriv/Mul.lean | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Mathlib/Analysis/Calculus/Deriv/Basic.lean b/Mathlib/Analysis/Calculus/Deriv/Basic.lean index 64f66f524e715..9f7a163866129 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Basic.lean @@ -658,6 +658,9 @@ theorem deriv_const' : (deriv fun _ : 𝕜 => c) = fun _ => 0 := theorem derivWithin_const : derivWithin (fun _ => c) s = 0 := by ext; simp [derivWithin] +@[simp] +theorem derivWithin_zero : derivWithin (0 : 𝕜 → F) s = 0 := derivWithin_const _ _ + end Const section Continuous diff --git a/Mathlib/Analysis/Calculus/Deriv/Mul.lean b/Mathlib/Analysis/Calculus/Deriv/Mul.lean index b97172a75dda6..3da9a8ed34991 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Mul.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Mul.lean @@ -246,6 +246,17 @@ theorem derivWithin_mul_const (hc : DifferentiableWithinAt 𝕜 c s x) (d : 𝔸 · exact (hc.hasDerivWithinAt.mul_const d).derivWithin hxs · simp [derivWithin_zero_of_isolated hxs] +lemma derivWithin_mul_const_field (u : 𝕜') : + derivWithin (fun y => v y * u) s x = derivWithin v s x * u := by + by_cases hv : DifferentiableWithinAt 𝕜 v s x + · rw [derivWithin_mul_const hv u] + by_cases hu : u = 0 + · simp [hu] + rw [derivWithin_zero_of_not_differentiableWithinAt hv, zero_mul, + derivWithin_zero_of_not_differentiableWithinAt] + have : v = fun x ↦ (v x * u) * u⁻¹ := by ext; simp [hu] + exact fun h_diff ↦ hv <| this ▸ h_diff.mul_const _ + theorem deriv_mul_const (hc : DifferentiableAt 𝕜 c x) (d : 𝔸) : deriv (fun y => c y * d) x = deriv c x * d := (hc.hasDerivAt.mul_const d).deriv @@ -284,6 +295,11 @@ theorem derivWithin_const_mul (c : 𝔸) (hd : DifferentiableWithinAt 𝕜 d s x · exact (hd.hasDerivWithinAt.const_mul c).derivWithin hxs · simp [derivWithin_zero_of_isolated hxs] +lemma derivWithin_const_mul_field (u : 𝕜') : + derivWithin (fun y => u * v y) s x = u * derivWithin v s x := by + simp_rw [mul_comm u] + exact derivWithin_mul_const_field u + theorem deriv_const_mul (c : 𝔸) (hd : DifferentiableAt 𝕜 d x) : deriv (fun y => c * d y) x = c * deriv d x := (hd.hasDerivAt.const_mul c).deriv From 3f5ccd4552086a62e5b19ab9bef1130cac957de4 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Mon, 27 Jan 2025 06:10:28 +0000 Subject: [PATCH 552/681] feat: separating set in the category of ind-objects (#21082) Under sufficient conditions (for example if `C` is small, preadditive and has finite coproducts) we will be able to assemble this into a separating object. Co-authored-by: Markus Himmel --- Mathlib.lean | 1 + .../CategoryTheory/Generator/Indization.lean | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 Mathlib/CategoryTheory/Generator/Indization.lean diff --git a/Mathlib.lean b/Mathlib.lean index c7575c572829a..601df39d4cf67 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1846,6 +1846,7 @@ import Mathlib.CategoryTheory.Galois.Prorepresentability import Mathlib.CategoryTheory.Galois.Topology import Mathlib.CategoryTheory.Generator.Abelian import Mathlib.CategoryTheory.Generator.Basic +import Mathlib.CategoryTheory.Generator.Indization import Mathlib.CategoryTheory.Generator.Preadditive import Mathlib.CategoryTheory.Generator.Presheaf import Mathlib.CategoryTheory.Generator.Sheaf diff --git a/Mathlib/CategoryTheory/Generator/Indization.lean b/Mathlib/CategoryTheory/Generator/Indization.lean new file mode 100644 index 0000000000000..4c79e7d781802 --- /dev/null +++ b/Mathlib/CategoryTheory/Generator/Indization.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2025 Markus Himmel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Markus Himmel +-/ +import Mathlib.CategoryTheory.Generator.Basic +import Mathlib.CategoryTheory.Limits.Indization.Category + +/-! +# Separating set in the category of ind-objects + +We construct a separating set in the category of ind-objects. + +## Future work + +Once we have constructed zero morphisms in the category of ind-objects, we will be able to show +that under sufficient conditions, the category of ind-objects has a separating object. + +-/ + +universe v u + +namespace CategoryTheory + +open Limits + +section + +variable {C : Type u} [Category.{v} C] + +theorem Ind.isSeparating_range_yoneda : IsSeparating (Set.range (Ind.yoneda : C ⥤ _).obj) := by + refine fun X Y f g h => (cancel_epi (Ind.colimitPresentationCompYoneda X).hom).1 ?_ + exact colimit.hom_ext (fun i => by simp [← Category.assoc, h]) + +end + +end CategoryTheory From 413249c638b4c9453166d2b94c9a7f13f6238b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Mon, 27 Jan 2025 06:18:48 +0000 Subject: [PATCH 553/681] =?UTF-8?q?feat(RingTheory/Artinian):=20`IsUnit=20?= =?UTF-8?q?a`=20iff=20`a=20=E2=88=88=20R=E2=81=B0`=20for=20an=20artinian?= =?UTF-8?q?=20ring=20`R`=20(#21084)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib/RingTheory/Artinian/Ring.lean | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Mathlib/RingTheory/Artinian/Ring.lean b/Mathlib/RingTheory/Artinian/Ring.lean index 4889c2cb83fb2..455b601e23f61 100644 --- a/Mathlib/RingTheory/Artinian/Ring.lean +++ b/Mathlib/RingTheory/Artinian/Ring.lean @@ -91,6 +91,26 @@ theorem isField_of_isReduced_of_isLocalRing [IsReduced R] [IsLocalRing R] : IsFi (IsArtinianRing.equivPi R).trans (RingEquiv.piUnique _) |>.toMulEquiv.isField _ (Ideal.Quotient.field _).toIsField +section IsUnit + +open nonZeroDivisors + +/-- If an element of an artinian ring is not a zero divisor then it is a unit. -/ +theorem isUnit_of_mem_nonZeroDivisors {a : R} (ha : a ∈ R⁰) : IsUnit a := + IsUnit.isUnit_iff_mulLeft_bijective.mpr <| + IsArtinian.bijective_of_injective_endomorphism (LinearMap.mulLeft R a) + fun _ _ ↦ (mul_cancel_left_mem_nonZeroDivisors ha).mp + +/-- In an artinian ring, an element is a unit iff it is a non-zero-divisor. +See also `isUnit_iff_mem_nonZeroDivisors_of_finite`.-/ +theorem isUnit_iff_mem_nonZeroDivisors {a : R} : IsUnit a ↔ a ∈ R⁰ := + ⟨IsUnit.mem_nonZeroDivisors, isUnit_of_mem_nonZeroDivisors⟩ + +theorem isUnit_submonoid_eq : IsUnit.submonoid R = R⁰ := by + ext; simp [IsUnit.mem_submonoid_iff, isUnit_iff_mem_nonZeroDivisors] + +end IsUnit + section Localization variable (S : Submonoid R) (L : Type*) [CommSemiring L] [Algebra R L] [IsLocalization S L] From 36e9a271ec64d6d64e57afe080796cbb14e787fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Mon, 27 Jan 2025 09:35:20 +0000 Subject: [PATCH 554/681] feat(RingTheory/IntegralClosure): prove `Module.Finite R (adjoin R S)` for finite set `S` of integral elements (#20970) Prove that `Algebra.adjoin R S` has finite rank over `R` when `S` is finite with elements that are all integral over `R`. Special case for singleton included. --- Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean | 8 ++++++++ .../IntegralClosure/IsIntegralClosure/Basic.lean | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean index 361784bfb1bc2..c40c5bce9c177 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean @@ -201,6 +201,14 @@ theorem fg_adjoin_of_finite {s : Set A} (hfs : s.Finite) (his : ∀ x ∈ s, IsI (his a <| Set.mem_insert a s).fg_adjoin_singleton) his +theorem Algebra.finite_adjoin_of_finite_of_isIntegral {s : Set A} (hf : s.Finite) + (hi : ∀ x ∈ s, IsIntegral R x) : Module.Finite R (adjoin R s) := + Module.Finite.iff_fg.mpr <| fg_adjoin_of_finite hf hi + +theorem Algebra.finite_adjoin_simple_of_isIntegral {x : A} (hi : IsIntegral R x) : + Module.Finite R (adjoin R {x}) := + Module.Finite.iff_fg.mpr hi.fg_adjoin_singleton + theorem isNoetherian_adjoin_finset [IsNoetherianRing R] (s : Finset A) (hs : ∀ x ∈ s, IsIntegral R x) : IsNoetherian R (Algebra.adjoin R (s : Set A)) := isNoetherian_of_fg_of_noetherian _ (fg_adjoin_of_finite s.finite_toSet hs) diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean index c62e33c4ab1b2..ff4bf59739f94 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean @@ -132,7 +132,7 @@ theorem le_integralClosure_iff_isIntegral {S : Subalgebra R A} : Algebra.isIntegral_def.symm theorem Algebra.IsIntegral.adjoin {S : Set A} (hS : ∀ x ∈ S, IsIntegral R x) : - Algebra.IsIntegral R (Algebra.adjoin R S) := + Algebra.IsIntegral R (adjoin R S) := le_integralClosure_iff_isIntegral.mp <| adjoin_le hS theorem integralClosure_eq_top_iff : integralClosure R A = ⊤ ↔ Algebra.IsIntegral R A := by From 0d0f87bbd9c5926b09472e9cce18c14bfa5194fb Mon Sep 17 00:00:00 2001 From: Wrenna Robson Date: Mon, 27 Jan 2025 09:49:14 +0000 Subject: [PATCH 555/681] feat(`InformationTheory/Hamming`): Add AddGroup instances (#20994) Add missing AddGroup and NormedAddGroup instances to Hamming. --- Mathlib/InformationTheory/Hamming.lean | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Mathlib/InformationTheory/Hamming.lean b/Mathlib/InformationTheory/Hamming.lean index 8ad9b91993a9b..47a11f3d84615 100644 --- a/Mathlib/InformationTheory/Hamming.lean +++ b/Mathlib/InformationTheory/Hamming.lean @@ -244,6 +244,8 @@ instance [Zero α] [∀ i, Zero (β i)] [∀ i, SMulWithZero α (β i)] : SMulWi instance [∀ i, AddMonoid (β i)] : AddMonoid (Hamming β) := Pi.addMonoid +instance [∀ i, AddGroup (β i)] : AddGroup (Hamming β) := Pi.addGroup + instance [∀ i, AddCommMonoid (β i)] : AddCommMonoid (Hamming β) := Pi.addCommMonoid @@ -396,15 +398,15 @@ instance [∀ i, Zero (β i)] : Norm (Hamming β) := theorem norm_eq_hammingNorm [∀ i, Zero (β i)] (x : Hamming β) : ‖x‖ = hammingNorm (ofHamming x) := rfl --- Porting note: merged `SeminormedAddCommGroup` and `NormedAddCommGroup` instances +instance [∀ i, AddGroup (β i)] : NormedAddGroup (Hamming β) where + dist_eq := by push_cast; exact mod_cast hammingDist_eq_hammingNorm instance [∀ i, AddCommGroup (β i)] : NormedAddCommGroup (Hamming β) where dist_eq := by push_cast; exact mod_cast hammingDist_eq_hammingNorm @[simp, push_cast] -theorem nnnorm_eq_hammingNorm [∀ i, AddCommGroup (β i)] (x : Hamming β) : - ‖x‖₊ = hammingNorm (ofHamming x) := - rfl +theorem nnnorm_eq_hammingNorm [∀ i, AddGroup (β i)] (x : Hamming β) : + ‖x‖₊ = hammingNorm (ofHamming x) := rfl end From f24bf08ffc13236fabe7dee9a1488c64b37a7ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Mon, 27 Jan 2025 09:49:15 +0000 Subject: [PATCH 556/681] feat(RingTheory/IntegralClosure): `Algebra.IsIntegral` transfers via surjective homomorphisms (#21023) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a surjective `f : A →ₐ[R] B`, if `Algebra.IsIntegral R A` then `Algebra.IsIntegral R B`. --- Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean index 0f9874f3e5ae8..69833b5a71fed 100644 --- a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean @@ -41,6 +41,11 @@ theorem Algebra.IsIntegral.of_injective (f : A →ₐ[R] B) (hf : Function.Injec [Algebra.IsIntegral R B] : Algebra.IsIntegral R A := ⟨fun _ ↦ (isIntegral_algHom_iff f hf).mp (isIntegral _)⟩ +/-- Homomorphic image of an integral algebra is an integral algebra. -/ +theorem Algebra.IsIntegral.of_surjective [Algebra.IsIntegral R A] + (f : A →ₐ[R] B) (hf : Function.Surjective f) : Algebra.IsIntegral R B := + isIntegral_def.mpr fun b ↦ let ⟨a, ha⟩ := hf b; ha ▸ (isIntegral_def.mp ‹_› a).map f + theorem AlgEquiv.isIntegral_iff (e : A ≃ₐ[R] B) : Algebra.IsIntegral R A ↔ Algebra.IsIntegral R B := ⟨fun h ↦ h.of_injective e.symm e.symm.injective, fun h ↦ h.of_injective e e.injective⟩ From d17e5f6e4d5658fd5388ea83d6e1b2aab4e8e538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 27 Jan 2025 09:49:16 +0000 Subject: [PATCH 557/681] feat(CategoryTheory/Subpresheaf): preimage/image/range of subpresheaves (#21047) --- .../Sites/LocallyInjective.lean | 4 +- .../Sites/LocallySurjective.lean | 28 +-- Mathlib/CategoryTheory/Sites/Subsheaf.lean | 52 +++-- Mathlib/CategoryTheory/Subpresheaf/Basic.lean | 3 +- Mathlib/CategoryTheory/Subpresheaf/Image.lean | 212 +++++++++++++----- .../CategoryTheory/Subpresheaf/Sieves.lean | 1 - 6 files changed, 207 insertions(+), 93 deletions(-) diff --git a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean index 64b1d4140a669..9f60ac73c6f1a 100644 --- a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean @@ -243,8 +243,8 @@ lemma mono_of_isLocallyInjective [IsLocallyInjective φ] : Mono φ := by infer_instance instance {F G : Sheaf J (Type w)} (f : F ⟶ G) : - IsLocallyInjective (imageSheafι f) := by - dsimp [imageSheafι] + IsLocallyInjective (Sheaf.imageι f) := by + dsimp [Sheaf.imageι] infer_instance end Sheaf diff --git a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean index e3c5a1393050f..a4fe2b6272f33 100644 --- a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean @@ -50,7 +50,7 @@ def imageSieve {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) {U : C} (s : G.obj (op U)) : rw [op_comp, G.map_comp, comp_apply, ← ht, elementwise_of% f.naturality] theorem imageSieve_eq_sieveOfSection {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) {U : C} (s : G.obj (op U)) : - imageSieve f s = (imagePresheaf (whiskerRight f (forget A))).sieveOfSection s := + imageSieve f s = (Subpresheaf.range (whiskerRight f (forget A))).sieveOfSection s := rfl theorem imageSieve_whisker_forget {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) {U : C} (s : G.obj (op U)) : @@ -92,13 +92,13 @@ instance {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) [IsLocallySurjective J f] : imageSieve_mem s := imageSieve_mem J f s theorem isLocallySurjective_iff_imagePresheaf_sheafify_eq_top {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) : - IsLocallySurjective J f ↔ (imagePresheaf (whiskerRight f (forget A))).sheafify J = ⊤ := by + IsLocallySurjective J f ↔ (Subpresheaf.range (whiskerRight f (forget A))).sheafify J = ⊤ := by simp only [Subpresheaf.ext_iff, funext_iff, Set.ext_iff, top_subpresheaf_obj, Set.top_eq_univ, Set.mem_univ, iff_true] exact ⟨fun H _ => H.imageSieve_mem, fun H => ⟨H _⟩⟩ theorem isLocallySurjective_iff_imagePresheaf_sheafify_eq_top' {F G : Cᵒᵖ ⥤ Type w} (f : F ⟶ G) : - IsLocallySurjective J f ↔ (imagePresheaf f).sheafify J = ⊤ := by + IsLocallySurjective J f ↔ (Subpresheaf.range f).sheafify J = ⊤ := by apply isLocallySurjective_iff_imagePresheaf_sheafify_eq_top theorem isLocallySurjective_iff_whisker_forget {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) : @@ -248,7 +248,7 @@ lemma isLocallySurjective_comp_iff infer_instance instance {F₁ F₂ : Cᵒᵖ ⥤ Type w} (f : F₁ ⟶ F₂) : - IsLocallySurjective J (toImagePresheafSheafify J f) where + IsLocallySurjective J (Subpresheaf.toRangeSheafify J f) where imageSieve_mem {X} := by rintro ⟨s, hs⟩ refine J.superset_covering ?_ hs @@ -257,20 +257,20 @@ instance {F₁ F₂ : Cᵒᵖ ⥤ Type w} (f : F₁ ⟶ F₂) : /-- The image of `F` in `J.sheafify F` is isomorphic to the sheafification. -/ noncomputable def sheafificationIsoImagePresheaf (F : Cᵒᵖ ⥤ Type max u v) : - J.sheafify F ≅ ((imagePresheaf (J.toSheafify F)).sheafify J).toPresheaf where + J.sheafify F ≅ ((Subpresheaf.range (J.toSheafify F)).sheafify J).toPresheaf where hom := - J.sheafifyLift (toImagePresheafSheafify J _) + J.sheafifyLift (Subpresheaf.toRangeSheafify J _) ((isSheaf_iff_isSheaf_of_type J _).mpr <| Subpresheaf.sheafify_isSheaf _ <| (isSheaf_iff_isSheaf_of_type J _).mp <| GrothendieckTopology.sheafify_isSheaf J _) inv := Subpresheaf.ι _ hom_inv_id := - J.sheafify_hom_ext _ _ (J.sheafify_isSheaf _) (by simp [toImagePresheafSheafify]) + J.sheafify_hom_ext _ _ (J.sheafify_isSheaf _) (by simp [Subpresheaf.toRangeSheafify]) inv_hom_id := by rw [← cancel_mono (Subpresheaf.ι _), Category.id_comp, Category.assoc] refine Eq.trans ?_ (Category.comp_id _) congr 1 - exact J.sheafify_hom_ext _ _ (J.sheafify_isSheaf _) (by simp [toImagePresheafSheafify]) + exact J.sheafify_hom_ext _ _ (J.sheafify_isSheaf _) (by simp [Subpresheaf.toRangeSheafify]) section @@ -328,8 +328,8 @@ instance isLocallySurjective_of_iso [IsIso φ] : IsLocallySurjective φ := by infer_instance instance {F G : Sheaf J (Type w)} (f : F ⟶ G) : - IsLocallySurjective (toImageSheaf f) := by - dsimp [toImageSheaf] + IsLocallySurjective (Sheaf.toImage f) := by + dsimp [Sheaf.toImage] infer_instance variable [J.HasSheafCompose (forget A)] @@ -339,11 +339,11 @@ instance [IsLocallySurjective φ] : (Presheaf.isLocallySurjective_iff_whisker_forget J φ.val).1 inferInstance theorem isLocallySurjective_iff_isIso {F G : Sheaf J (Type w)} (f : F ⟶ G) : - IsLocallySurjective f ↔ IsIso (imageSheafι f) := by + IsLocallySurjective f ↔ IsIso (Sheaf.imageι f) := by dsimp only [IsLocallySurjective] - rw [imageSheafι, Presheaf.isLocallySurjective_iff_imagePresheaf_sheafify_eq_top', + rw [Sheaf.imageι, Presheaf.isLocallySurjective_iff_imagePresheaf_sheafify_eq_top', Subpresheaf.eq_top_iff_isIso] - exact isIso_iff_of_reflects_iso (f := imageSheafι f) (F := sheafToPresheaf J (Type w)) + exact isIso_iff_of_reflects_iso (f := Sheaf.imageι f) (F := sheafToPresheaf J (Type w)) instance epi_of_isLocallySurjective' {F₁ F₂ : Sheaf J (Type w)} (φ : F₁ ⟶ F₂) [IsLocallySurjective φ] : Epi φ where @@ -369,7 +369,7 @@ lemma isLocallySurjective_iff_epi {F G : Sheaf J (Type w)} (φ : F ⟶ G) · intro infer_instance · intro - have := epi_of_epi_fac (toImageSheaf_ι φ) + have := epi_of_epi_fac (Sheaf.toImage_ι φ) rw [isLocallySurjective_iff_isIso φ] apply isIso_of_mono_of_epi diff --git a/Mathlib/CategoryTheory/Sites/Subsheaf.lean b/Mathlib/CategoryTheory/Sites/Subsheaf.lean index 3be19de81341b..03d5262b3fe05 100644 --- a/Mathlib/CategoryTheory/Sites/Subsheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Subsheaf.lean @@ -194,16 +194,17 @@ variable (J) /-- A morphism factors through the sheafification of the image presheaf. -/ @[simps!] -def toImagePresheafSheafify (f : F' ⟶ F) : F' ⟶ ((imagePresheaf f).sheafify J).toPresheaf := - toImagePresheaf f ≫ Subpresheaf.homOfLe ((imagePresheaf f).le_sheafify J) +def Subpresheaf.toRangeSheafify (f : F' ⟶ F) : F' ⟶ ((Subpresheaf.range f).sheafify J).toPresheaf := + toRange f ≫ Subpresheaf.homOfLe ((range f).le_sheafify J) + variable {J} /-- The image sheaf of a morphism between sheaves, defined to be the sheafification of `image_presheaf`. -/ @[simps] -def imageSheaf {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Sheaf J (Type w) := - ⟨((imagePresheaf f.1).sheafify J).toPresheaf, by +def Sheaf.image {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Sheaf J (Type w) := + ⟨((Subpresheaf.range f.1).sheafify J).toPresheaf, by rw [isSheaf_iff_isSheaf_of_type] apply Subpresheaf.sheafify_isSheaf rw [← isSheaf_iff_isSheaf_of_type] @@ -211,34 +212,35 @@ def imageSheaf {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Sheaf J (Type w) := /-- A morphism factors through the image sheaf. -/ @[simps] -def toImageSheaf {F F' : Sheaf J (Type w)} (f : F ⟶ F') : F ⟶ imageSheaf f := - ⟨toImagePresheafSheafify J f.1⟩ +def Sheaf.toImage {F F' : Sheaf J (Type w)} (f : F ⟶ F') : F ⟶ Sheaf.image f := + ⟨Subpresheaf.toRangeSheafify J f.1⟩ /-- The inclusion of the image sheaf to the target. -/ @[simps] -def imageSheafι {F F' : Sheaf J (Type w)} (f : F ⟶ F') : imageSheaf f ⟶ F' := +def Sheaf.imageι {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Sheaf.image f ⟶ F' := ⟨Subpresheaf.ι _⟩ + @[reassoc (attr := simp)] -theorem toImageSheaf_ι {F F' : Sheaf J (Type w)} (f : F ⟶ F') : - toImageSheaf f ≫ imageSheafι f = f := by +theorem Sheaf.toImage_ι {F F' : Sheaf J (Type w)} (f : F ⟶ F') : + toImage f ≫ imageι f = f := by ext1 - simp [toImagePresheafSheafify] + simp [Subpresheaf.toRangeSheafify] -instance {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Mono (imageSheafι f) := +instance {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Mono (Sheaf.imageι f) := (sheafToPresheaf J _).mono_of_mono_map (by dsimp infer_instance) -instance {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Epi (toImageSheaf f) := by +instance {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Epi (Sheaf.toImage f) := by refine ⟨@fun G' g₁ g₂ e => ?_⟩ ext U ⟨s, hx⟩ apply ((isSheaf_iff_isSheaf_of_type J _).mp G'.2 _ hx).isSeparatedFor.ext rintro V i ⟨y, e'⟩ change (g₁.val.app _ ≫ G'.val.map _) _ = (g₂.val.app _ ≫ G'.val.map _) _ rw [← NatTrans.naturality, ← NatTrans.naturality] - have E : (toImageSheaf f).val.app (op V) y = (imageSheaf f).val.map i.op ⟨s, hx⟩ := + have E : (Sheaf.toImage f).val.app (op V) y = (Sheaf.image f).val.map i.op ⟨s, hx⟩ := Subtype.ext e' have := congr_arg (fun f : F ⟶ G' => (Sheaf.Hom.val f).app _ y) e dsimp at this ⊢ @@ -246,9 +248,9 @@ instance {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Epi (toImageSheaf f) := by /-- The mono factorization given by `image_sheaf` for a morphism. -/ def imageMonoFactorization {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Limits.MonoFactorisation f where - I := imageSheaf f - m := imageSheafι f - e := toImageSheaf f + I := Sheaf.image f + m := Sheaf.imageι f + e := Sheaf.toImage f /-- The mono factorization given by `image_sheaf` for a morphism is an image. -/ noncomputable def imageFactorization {F F' : Sheaf J (Type (max v u))} (f : F ⟶ F') : @@ -257,14 +259,13 @@ noncomputable def imageFactorization {F F' : Sheaf J (Type (max v u))} (f : F isImage := { lift := fun I => by haveI M := (Sheaf.Hom.mono_iff_presheaf_mono J (Type (max v u)) _).mp I.m_mono - haveI := isIso_toImagePresheaf I.m.1 - refine ⟨Subpresheaf.homOfLe ?_ ≫ inv (toImagePresheaf I.m.1)⟩ + refine ⟨Subpresheaf.homOfLe ?_ ≫ inv (Subpresheaf.toRange I.m.1)⟩ apply Subpresheaf.sheafify_le · conv_lhs => rw [← I.fac] - apply imagePresheaf_comp_le + apply Subpresheaf.range_comp_le · rw [← isSheaf_iff_isSheaf_of_type] exact F'.2 - · apply Presieve.isSheaf_iso J (asIso <| toImagePresheaf I.m.1) + · apply Presieve.isSheaf_iso J (asIso <| Subpresheaf.toRange I.m.1) rw [← isSheaf_iff_isSheaf_of_type] exact I.I.2 lift_fac := fun I => by @@ -273,10 +274,17 @@ noncomputable def imageFactorization {F F' : Sheaf J (Type (max v u))} (f : F generalize_proofs h rw [← Subpresheaf.homOfLe_ι h, Category.assoc] congr 1 - rw [IsIso.inv_comp_eq, toImagePresheaf_ι] } + rw [IsIso.inv_comp_eq, Subpresheaf.toRange_ι] } instance : Limits.HasImages (Sheaf J (Type max v u)) := - ⟨@fun _ _ f => ⟨⟨imageFactorization f⟩⟩⟩ + ⟨fun f => ⟨⟨imageFactorization f⟩⟩⟩ + +@[deprecated (since := "2025-01-25")] alias toImagePresheafSheafify := + Subpresheaf.toRangeSheafify +@[deprecated (since := "2025-01-25")] alias imageSheaf := Sheaf.image +@[deprecated (since := "2025-01-25")] alias toImageSheaf := Sheaf.toImage +@[deprecated (since := "2025-01-25")] alias imageSheafι := Sheaf.imageι +@[deprecated (since := "2025-01-25")] alias toImageSheaf_ι := Sheaf.toImage_ι end Image diff --git a/Mathlib/CategoryTheory/Subpresheaf/Basic.lean b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean index 080283e8b1880..2a751fadcfb62 100644 --- a/Mathlib/CategoryTheory/Subpresheaf/Basic.lean +++ b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean @@ -6,7 +6,6 @@ Authors: Andrew Yang import Mathlib.CategoryTheory.Elementwise import Mathlib.Data.Set.Basic - /-! # Subpresheaf of types @@ -47,6 +46,8 @@ variable {F F' F'' : Cᵒᵖ ⥤ Type w} (G G' : Subpresheaf F) instance : PartialOrder (Subpresheaf F) := PartialOrder.lift Subpresheaf.obj (fun _ _ => Subpresheaf.ext) +lemma Subpresheaf.le_def (S T : Subpresheaf F) : S ≤ T ↔ ∀ U, S.obj U ≤ T.obj U := Iff.rfl + instance : Top (Subpresheaf F) := ⟨⟨fun _ => ⊤, @fun U _ _ x _ => by simp⟩⟩ diff --git a/Mathlib/CategoryTheory/Subpresheaf/Image.lean b/Mathlib/CategoryTheory/Subpresheaf/Image.lean index 367029af657f0..4247b888fb3af 100644 --- a/Mathlib/CategoryTheory/Subpresheaf/Image.lean +++ b/Mathlib/CategoryTheory/Subpresheaf/Image.lean @@ -1,20 +1,18 @@ /- Copyright (c) 2022 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Andrew Yang +Authors: Andrew Yang, Joël Riou -/ - import Mathlib.CategoryTheory.Subpresheaf.Basic import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono /-! # The image of a subpresheaf -Given a morphism of presheaves of types `f : F' ⟶ F`, we define `imagePresheaf f` -as a subpresheaf of `F`. - -## TODO (@joelriou) -* introduce `Subpresheaf.image` and `Subpresheaf.preimage` +Given a morphism of presheaves of types `p : F' ⟶ F`, we define its range +`Subpresheaf.range p`. More generally, if `G' : Subpresheaf F'`, we +define `G'.image p : Subpresheaf F` as the image of `G'` by `f`, and +if `G : Subpresheaf F`, we define its preimage `G.preimage f : Subpresheaf F'`. -/ @@ -22,63 +20,171 @@ universe w v u namespace CategoryTheory -variable {C : Type u} [Category.{v} C] {F F' F'' : Cᵒᵖ ⥤ Type w} {G : Subpresheaf F} +variable {C : Type u} [Category.{v} C] {F F' F'' : Cᵒᵖ ⥤ Type w} -/-- If the image of a morphism falls in a subpresheaf, then the morphism factors through it. -/ -@[simps!] -def Subpresheaf.lift (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : F' ⟶ G.toPresheaf where - app U x := ⟨f.app U x, hf U x⟩ - naturality := by - have := elementwise_of% f.naturality - intros - refine funext fun x => Subtype.ext ?_ - simp only [toPresheaf_obj, types_comp_apply] - exact this _ _ +namespace Subpresheaf -@[reassoc (attr := simp)] -theorem Subpresheaf.lift_ι (f : F' ⟶ F) (hf : ∀ U x, f.app U x ∈ G.obj U) : - G.lift f hf ≫ G.ι = f := by - ext - rfl +section range -/-- The image presheaf of a morphism, whose components are the set-theoretic images. -/ +/-- The range of a morphism of presheaves of types, as a subpresheaf of the target. -/ @[simps] -def imagePresheaf (f : F' ⟶ F) : Subpresheaf F where - obj U := Set.range (f.app U) +def range (p : F' ⟶ F) : Subpresheaf F where + obj U := Set.range (p.app U) map := by rintro U V i _ ⟨x, rfl⟩ - have := elementwise_of% f.naturality - exact ⟨_, this i x⟩ + exact ⟨_, FunctorToTypes.naturality _ _ p i x⟩ + +variable (F) in +lemma range_id : range (𝟙 F) = ⊤ := by aesop @[simp] -theorem imagePresheaf_id : imagePresheaf (𝟙 F) = ⊤ := by - ext - simp +lemma range_ι (G : Subpresheaf F) : range G.ι = G := by aesop + +end range + +section lift -/-- A morphism factors through the image presheaf. -/ +variable (f : F' ⟶ F) {G : Subpresheaf F} (hf : range f ≤ G) + +/-- If the image of a morphism falls in a subpresheaf, then the morphism factors through it. -/ @[simps!] -def toImagePresheaf (f : F' ⟶ F) : F' ⟶ (imagePresheaf f).toPresheaf := - (imagePresheaf f).lift f fun _ _ => Set.mem_range_self _ +def lift : F' ⟶ G.toPresheaf where + app U x := ⟨f.app U x, hf U (by simp)⟩ + naturality _ _ g := by + ext x + simpa [Subtype.ext_iff] using FunctorToTypes.naturality _ _ f g x @[reassoc (attr := simp)] -theorem toImagePresheaf_ι (f : F' ⟶ F) : toImagePresheaf f ≫ (imagePresheaf f).ι = f := - (imagePresheaf f).lift_ι _ _ - -theorem imagePresheaf_comp_le (f₁ : F ⟶ F') (f₂ : F' ⟶ F'') : - imagePresheaf (f₁ ≫ f₂) ≤ imagePresheaf f₂ := fun U _ hx => ⟨f₁.app U hx.choose, hx.choose_spec⟩ - -instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ Type w} (f : F ⟶ F') [hf : Mono f] : - IsIso (toImagePresheaf f) := by - have : ∀ (X : Cᵒᵖ), IsIso ((toImagePresheaf f).app X) := by - intro X - rw [isIso_iff_bijective] - constructor - · intro x y e - have := (NatTrans.mono_iff_mono_app f).mp hf X - rw [mono_iff_injective] at this - exact this (congr_arg Subtype.val e :) - · rintro ⟨_, ⟨x, rfl⟩⟩ - exact ⟨x, rfl⟩ - apply NatIso.isIso_of_isIso_app +theorem lift_ι : lift f hf ≫ G.ι = f := rfl + +end lift + +section range + +variable (p : F' ⟶ F) + +/-- Given a morphism `p : F' ⟶ F` of presheaves of types, this is the morphism +from `F'` to its range. -/ +def toRange : + F' ⟶ (range p).toPresheaf := + lift p (by rfl) + +@[reassoc (attr := simp)] +lemma toRange_ι : toRange p ≫ (range p).ι = p := rfl + +lemma toRange_app_val {i : Cᵒᵖ} (x : F'.obj i) : + ((toRange p).app i x).val = p.app i x := by + simp [toRange] + +@[simp] +lemma range_toRange : range (toRange p) = ⊤ := by + ext i ⟨x, hx⟩ + dsimp at hx ⊢ + simp only [Set.mem_range, Set.mem_univ, iff_true] + simp only [Set.mem_range] at hx + obtain ⟨y, rfl⟩ := hx + exact ⟨y, rfl⟩ + +lemma epi_iff_range_eq_top : + Epi p ↔ range p = ⊤ := by + simp [NatTrans.epi_iff_epi_app, epi_iff_surjective, Subpresheaf.ext_iff, funext_iff, + Set.range_eq_univ] + +instance : Epi (toRange p) := by simp [epi_iff_range_eq_top] + +instance [Mono p] : IsIso (toRange p) := by + have := mono_of_mono_fac (toRange_ι p) + rw [NatTrans.isIso_iff_isIso_app] + intro i + rw [isIso_iff_bijective] + constructor + · rw [← mono_iff_injective] + infer_instance + · rw [← epi_iff_surjective] + infer_instance + +lemma range_comp_le (f : F ⟶ F') (g : F' ⟶ F'') : + range (f ≫ g) ≤ range g := fun _ _ _ ↦ by aesop + +end range + +section image + +variable (G : Subpresheaf F) (f : F ⟶ F') + +/-- The image of a subpresheaf by a morphism of presheaves of types. -/ +@[simps] +def image : Subpresheaf F' where + obj i := (f.app i) '' (G.obj i) + map := by + rintro Δ Δ' φ _ ⟨x, hx, rfl⟩ + exact ⟨F.map φ x, G.map φ hx, by apply FunctorToTypes.naturality⟩ + +lemma image_top : (⊤ : Subpresheaf F).image f = range f := by aesop + +lemma image_comp (g : F' ⟶ F'') : + G.image (f ≫ g) = (G.image f).image g := by aesop + +lemma range_comp (g : F' ⟶ F'') : + range (f ≫ g) = (range f).image g := by aesop + +end image + +section preimage + +/-- The preimage of a subpresheaf by a morphism of presheaves of types. -/ +@[simps] +def preimage (G : Subpresheaf F) (p : F' ⟶ F) : Subpresheaf F' where + obj n := p.app n ⁻¹' (G.obj n) + map f := (Set.preimage_mono (G.map f)).trans (by + simp only [Set.preimage_preimage, FunctorToTypes.naturality _ _ p f] + rfl) + +@[simp] +lemma preimage_id (G : Subpresheaf F) : + G.preimage (𝟙 F) = G := by aesop + +lemma preimage_comp (G : Subpresheaf F) (f : F'' ⟶ F') (g : F' ⟶ F) : + G.preimage (f ≫ g) = (G.preimage g).preimage f := by aesop + +lemma image_le_iff (G : Subpresheaf F) (f : F ⟶ F') (G' : Subpresheaf F') : + G.image f ≤ G' ↔ G ≤ G'.preimage f := by + simp [Subpresheaf.le_def] + +/-- Given a morphism `p : F' ⟶ F` of presheaves of types and `G : Subpresheaf F`, +this is the morphism from the preimage of `G` by `p` to `G`. -/ +def fromPreimage (G : Subpresheaf F) (p : F' ⟶ F) : + (G.preimage p).toPresheaf ⟶ G.toPresheaf := + lift ((G.preimage p).ι ≫ p) (by + rw [range_comp, range_ι, image_le_iff]) + +@[reassoc] +lemma fromPreimage_ι (G : Subpresheaf F) (p : F' ⟶ F) : + G.fromPreimage p ≫ G.ι = (G.preimage p).ι ≫ p := rfl + +lemma preimage_eq_top_iff (G : Subpresheaf F) (p : F' ⟶ F) : + G.preimage p = ⊤ ↔ range p ≤ G := by + rw [← image_top, image_le_iff] + aesop + +@[simp] +lemma preimage_image_of_epi (G : Subpresheaf F) (p : F' ⟶ F) [hp : Epi p] : + (G.preimage p).image p = G := by + apply le_antisymm + · rw [image_le_iff] + · intro i x hx + simp only [NatTrans.epi_iff_epi_app, epi_iff_surjective] at hp + obtain ⟨y, rfl⟩ := hp _ x + exact ⟨y, hx, rfl⟩ + +end preimage + +end Subpresheaf + +@[deprecated (since := "2025-01-25")] alias imagePresheaf := Subpresheaf.range +@[deprecated (since := "2025-01-25")] alias imagePresheaf_id := Subpresheaf.range_id +@[deprecated (since := "2025-01-25")] alias toImagePresheaf := Subpresheaf.toRange +@[deprecated (since := "2025-01-25")] alias toImagePresheaf_ι := Subpresheaf.toRange_ι +@[deprecated (since := "2025-01-25")] alias imagePresheaf_comp_le := Subpresheaf.range_comp_le end CategoryTheory diff --git a/Mathlib/CategoryTheory/Subpresheaf/Sieves.lean b/Mathlib/CategoryTheory/Subpresheaf/Sieves.lean index 12ffd8506ee78..7c84f551edcd1 100644 --- a/Mathlib/CategoryTheory/Subpresheaf/Sieves.lean +++ b/Mathlib/CategoryTheory/Subpresheaf/Sieves.lean @@ -3,7 +3,6 @@ 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.CategoryTheory.Subpresheaf.Basic import Mathlib.CategoryTheory.Sites.IsSheafFor From d93a176e58bef9991884f129003e6f64b4f5af79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Mon, 27 Jan 2025 09:49:18 +0000 Subject: [PATCH 558/681] chore(SetTheory/Game/Impartial): golf two proofs (#21074) --- Mathlib/SetTheory/Game/Impartial.lean | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Mathlib/SetTheory/Game/Impartial.lean b/Mathlib/SetTheory/Game/Impartial.lean index e06e5beb85b35..2d6cde0fec9aa 100644 --- a/Mathlib/SetTheory/Game/Impartial.lean +++ b/Mathlib/SetTheory/Game/Impartial.lean @@ -103,16 +103,11 @@ termination_by G variable (G : PGame) [Impartial G] theorem nonpos : ¬0 < G := by - intro h - have h' := neg_lt_neg_iff.2 h - rw [neg_zero, lt_congr_left (Equiv.symm (neg_equiv_self G))] at h' - exact (h.trans h').false + apply (lt_asymm · ?_) + rwa [← neg_lt_neg_iff, neg_zero, ← lt_congr_right (neg_equiv_self G)] theorem nonneg : ¬G < 0 := by - intro h - have h' := neg_lt_neg_iff.2 h - rw [neg_zero, lt_congr_right (Equiv.symm (neg_equiv_self G))] at h' - exact (h.trans h').false + simpa using nonpos (-G) /-- In an impartial game, either the first player always wins, or the second player always wins. -/ theorem equiv_or_fuzzy_zero : (G ≈ 0) ∨ G ‖ 0 := by From 2bce15bb8aa6d5d4af1c9ef1151e81e22353b65b Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Mon, 27 Jan 2025 10:06:23 +0000 Subject: [PATCH 559/681] feat(RingTheory/LaurentSeries): add algebraEquiv (#21004) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define an `Algebra K RatFuncAdicCompl K` instance on `RatFuncAdicCompl K` and promote the already defined ring equivalences to algebra equivalences `LaurentSeriesAlgEquiv : K⸨X⸩ ≃ₐ[K] RatFuncAdicCompl K` and `K⟦X⟧ ≃ₐ[K] (idealX K).adicCompletionIntegers (RatFunc K)`. TODO : update docstring (on top of file) --- .../DedekindDomain/AdicValuation.lean | 3 + Mathlib/RingTheory/LaurentSeries.lean | 93 +++++++++++++++---- 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean index 110ec9cd323fb..d7d5139cc0b3e 100644 --- a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean +++ b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean @@ -403,6 +403,9 @@ def adicCompletion := instance : Field (v.adicCompletion K) := inferInstanceAs <| Field (@UniformSpace.Completion K v.adicValued.toUniformSpace) +instance : Algebra K (v.adicCompletion K) := + RingHom.toAlgebra (@UniformSpace.Completion.coeRingHom K _ v.adicValued.toUniformSpace _ _) + instance : Inhabited (v.adicCompletion K) := ⟨0⟩ diff --git a/Mathlib/RingTheory/LaurentSeries.lean b/Mathlib/RingTheory/LaurentSeries.lean index cf8a577647928..27e5f145a98c1 100644 --- a/Mathlib/RingTheory/LaurentSeries.lean +++ b/Mathlib/RingTheory/LaurentSeries.lean @@ -14,6 +14,7 @@ import Mathlib.RingTheory.Localization.FractionRing import Mathlib.Topology.UniformSpace.Cauchy import Mathlib.Algebra.Group.Int.TypeTags + /-! # Laurent Series @@ -60,8 +61,8 @@ such that the `X`-adic valuation `v` satisfies `v (f - Q) < γ`. `LaurentSeries.exists_powerSeries_of_memIntegers` show that an element in the completion of `RatFunc K` is in the unit ball if and only if it comes from a power series through the isomorphism `LaurentSeriesRingEquiv`. -* `LaurentSeries.powerSeriesRingEquiv` is the ring isomorphism between `K⟦X⟧` and the unit ball -inside the `X`-adic completion of `RatFunc K`. +* `LaurentSeries.powerSeriesAlgEquiv` is the `K`-algebra isomorphism between `K⟦X⟧` +and the unit ball inside the `X`-adic completion of `RatFunc K`. ## Implementation details @@ -75,18 +76,13 @@ that it is complete and contains `RatFunc K` as a dense subspace. The isomorphis equivalence, expressing the mathematical idea that the completion "is unique". It is `LaurentSeries.comparePkg`. * For applications to `K⟦X⟧` it is actually more handy to use the *inverse* of the above -equivalence: `LaurentSeries.LaurentSeriesRingEquiv` is the *topological, ring equivalence* -`K⸨X⸩ ≃+* RatFuncAdicCompl K`. +equivalence: `LaurentSeries.LaurentSeriesAlgEquiv` is the *topological, algebra equivalence* +`K⸨X⸩ ≃ₐ[K] RatFuncAdicCompl K`. * In order to compare `K⟦X⟧` with the valuation subring in the `X`-adic completion of `RatFunc K` we consider its alias `LaurentSeries.powerSeries_as_subring` as a subring of `K⸨X⸩`, that is itself clearly isomorphic (via the inverse of `LaurentSeries.powerSeriesEquivSubring`) to `K⟦X⟧`. -## To Do -* The `AdicCompletion` construction is currently done for ideals in rings and does not take into -account the relation with algebra structures on the ring, hence it does not yield a `K`-algebra -structure on the `X`-adic completion of `K⸨X⸩`. Once this will be available, we should update -`LaurentSeries.LaurentSeriesRingEquiv` to an algebra equivalence. -/ universe u @@ -1061,6 +1057,11 @@ equivalence: it goes from `K⸨X⸩` to `RatFuncAdicCompl K` -/ abbrev LaurentSeriesRingEquiv : K⸨X⸩ ≃+* RatFuncAdicCompl K := (ratfuncAdicComplRingEquiv K).symm +@[simp] +lemma LaurentSeriesRingEquiv_def (f : K⟦X⟧) : + (LaurentSeriesRingEquiv K) f = (LaurentSeriesPkg K).compare ratfuncAdicComplPkg (f : K⸨X⸩) := + rfl + @[simp] theorem ratfuncAdicComplRingEquiv_apply (x : RatFuncAdicCompl K) : ratfuncAdicComplRingEquiv K x = ratfuncAdicComplPkg.compare (LaurentSeriesPkg K) x := rfl @@ -1071,6 +1072,17 @@ theorem coe_X_compare : rw [PowerSeries.coe_X, ← RatFunc.coe_X, ← LaurentSeries_coe, ← compare_coe] rfl +theorem algebraMap_apply (a : K) : algebraMap K K⸨X⸩ a = HahnSeries.C a := by + simp [RingHom.algebraMap_toAlgebra] + +instance : Algebra K (RatFuncAdicCompl K) := + RingHom.toAlgebra ((LaurentSeriesRingEquiv K).toRingHom.comp HahnSeries.C) + +/-- The algebra equivalence between `K⸨X⸩` and the `X`-adic completion of `RatFunc X` -/ +def LaurentSeriesAlgEquiv : K⸨X⸩ ≃ₐ[K] RatFuncAdicCompl K := + AlgEquiv.ofRingEquiv (f := LaurentSeriesRingEquiv K) + (fun a ↦ by simp [RingHom.algebraMap_toAlgebra]) + open Filter WithZero open scoped WithZeroTopology Topology Multiplicative @@ -1132,22 +1144,30 @@ section PowerSeries /-- In order to compare `K⟦X⟧` with the valuation subring in the `X`-adic completion of `RatFunc K` we consider its alias as a subring of `K⸨X⸩`. -/ abbrev powerSeries_as_subring : Subring K⸨X⸩ := - RingHom.range (HahnSeries.ofPowerSeries ℤ K) +-- RingHom.range (HahnSeries.ofPowerSeries ℤ K) + Subring.map (HahnSeries.ofPowerSeries ℤ K) ⊤ /-- The ring `K⟦X⟧` is isomorphic to the subring `powerSeries_as_subring K` -/ -abbrev powerSeriesEquivSubring : K⟦X⟧ ≃+* powerSeries_as_subring K := by - rw [powerSeries_as_subring, RingHom.range_eq_map] - exact ((Subring.topEquiv).symm).trans (Subring.equivMapOfInjective ⊤ (ofPowerSeries ℤ K) +abbrev powerSeriesEquivSubring : K⟦X⟧ ≃+* powerSeries_as_subring K := + ((Subring.topEquiv).symm).trans (Subring.equivMapOfInjective ⊤ (ofPowerSeries ℤ K) ofPowerSeries_injective) +lemma powerSeriesEquivSubring_apply (f : K⟦X⟧) : + powerSeriesEquivSubring K f = + ⟨HahnSeries.ofPowerSeries ℤ K f, Subring.mem_map.mpr ⟨f, trivial, rfl⟩⟩ := + rfl + +lemma powerSeriesEquivSubring_coe_apply (f : K⟦X⟧) : + (powerSeriesEquivSubring K f : K⸨X⸩) = ofPowerSeries ℤ K f := + rfl + /- Through the isomorphism `LaurentSeriesRingEquiv`, power series land in the unit ball inside the completion of `RatFunc K`. -/ theorem mem_integers_of_powerSeries (F : K⟦X⟧) : (LaurentSeriesRingEquiv K) F ∈ (idealX K).adicCompletionIntegers (RatFunc K) := by - have : (LaurentSeriesRingEquiv K) F = - (LaurentSeriesPkg K).compare ratfuncAdicComplPkg (F : K⸨X⸩) := rfl simp only [Subring.mem_map, exists_prop, ValuationSubring.mem_toSubring, - mem_adicCompletionIntegers, this, valuation_compare, val_le_one_iff_eq_coe] + mem_adicCompletionIntegers, LaurentSeriesRingEquiv_def, + valuation_compare, val_le_one_iff_eq_coe] exact ⟨F, rfl⟩ /- Conversely, all elements in the unit ball inside the completion of `RatFunc K` come from a power @@ -1166,13 +1186,13 @@ theorem powerSeries_ext_subring : Subring.map (LaurentSeriesRingEquiv K).toRingHom (powerSeries_as_subring K) = ((idealX K).adicCompletionIntegers (RatFunc K)).toSubring := by ext x - refine ⟨fun ⟨f, ⟨F, coe_F⟩, hF⟩ ↦ ?_, fun H ↦ ?_⟩ + refine ⟨fun ⟨f, ⟨F, _, coe_F⟩, hF⟩ ↦ ?_, fun H ↦ ?_⟩ · simp only [ValuationSubring.mem_toSubring, ← hF, ← coe_F] apply mem_integers_of_powerSeries · obtain ⟨F, hF⟩ := exists_powerSeries_of_memIntegers K H simp only [Equiv.toFun_as_coe, UniformEquiv.coe_toEquiv, exists_exists_eq_and, UniformEquiv.coe_symm_toEquiv, Subring.mem_map, Equiv.invFun_as_coe] - exact ⟨F, ⟨F, rfl⟩, hF⟩ + exact ⟨F, ⟨F, trivial, rfl⟩, hF⟩ /-- The ring isomorphism between `K⟦X⟧` and the unit ball inside the `X`-adic completion of `RatFunc K`. -/ @@ -1180,6 +1200,43 @@ abbrev powerSeriesRingEquiv : K⟦X⟧ ≃+* (idealX K).adicCompletionIntegers ( ((powerSeriesEquivSubring K).trans (LaurentSeriesRingEquiv K).subringMap).trans <| RingEquiv.subringCongr (powerSeries_ext_subring K) +lemma powerSeriesRingEquiv_coe_apply (f : K⟦X⟧) : + powerSeriesRingEquiv K f = LaurentSeriesRingEquiv K (f : K⸨X⸩) := + rfl + +lemma LaurentSeriesRingEquiv_mem_valuationSubring (f : K⟦X⟧) : + LaurentSeriesRingEquiv K f ∈ Valued.v.valuationSubring := by + simp only [Valuation.mem_valuationSubring_iff] + rw [LaurentSeriesRingEquiv_def, valuation_compare, val_le_one_iff_eq_coe] + use f + +lemma algebraMap_C_mem_adicCompletionIntegers (x : K) : + ((LaurentSeriesRingEquiv K).toRingHom.comp HahnSeries.C) x ∈ + adicCompletionIntegers (RatFunc K) (idealX K) := by + have : HahnSeries.C x = ofPowerSeries ℤ K (PowerSeries.C K x) := by + simp [C_apply, ofPowerSeries_C] + simp only [RingHom.comp_apply, RingEquiv.toRingHom_eq_coe, RingHom.coe_coe, this] + apply LaurentSeriesRingEquiv_mem_valuationSubring + +instance : Algebra K ((idealX K).adicCompletionIntegers (RatFunc K)) := + RingHom.toAlgebra <| + ((LaurentSeriesRingEquiv K).toRingHom.comp HahnSeries.C).codRestrict _ + (algebraMap_C_mem_adicCompletionIntegers K) + +instance : IsScalarTower K ((idealX K).adicCompletionIntegers (RatFunc K)) + ((idealX K).adicCompletion (RatFunc K)) := + IsScalarTower.of_algebraMap_eq (fun _ ↦ by rfl) + +/-- The algebra isomorphism between `K⟦X⟧` and the unit ball inside the `X`-adic completion of +`RatFunc K`. -/ +def powerSeriesAlgEquiv : K⟦X⟧ ≃ₐ[K] (idealX K).adicCompletionIntegers (RatFunc K) := by + apply AlgEquiv.ofRingEquiv (f := powerSeriesRingEquiv K) + intro a + rw [PowerSeries.algebraMap_eq, RingHom.algebraMap_toAlgebra, ← Subtype.coe_inj, + powerSeriesRingEquiv_coe_apply, + RingHom.codRestrict_apply _ _ (algebraMap_C_mem_adicCompletionIntegers K)] + simp + end PowerSeries end Comparison From c33fe046f64d7570c10713af5fb4ffd95d1d0613 Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Mon, 27 Jan 2025 10:18:21 +0000 Subject: [PATCH 560/681] feat(NumberTheory/LSeries): results involving partial sums of coefficients (part 1) (#20661) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We prove several results involving partial sums of coefficients (or norm of coefficients) of L-series. The two main results of this PR are: - `LSeriesSummable_of_sum_norm_bigO`: for `f : ℕ → ℂ`, if the partial sums `∑ k ∈ Icc 1 n, ‖f k‖` are `O(n ^ r)` for some real `0 ≤ r`, then the L-series `Lseries f` converges at `s : ℂ` for all `s` such that `r < s.re`. - `LSeries_eq_mul_integral` : for `f : ℕ → ℂ`, if the partial sums `∑ k ∈ Icc 1 n, f k` are `O(n ^ r)` for some real `0 ≤ r` and the L-series `LSeries f` converges at `s : ℂ` with `r < s.re`, then `LSeries f s = s * ∫ t in Set.Ioi 1, (∑ k ∈ Icc 1 ⌊t⌋₊, f k) * t ^ (- (s + 1))`. More results will be proved in #20660 --- Mathlib.lean | 1 + .../Asymptotics/SpecificAsymptotics.lean | 21 ++- .../SpecialFunctions/ImproperIntegrals.lean | 26 +++ .../SpecialFunctions/Pow/Complex.lean | 7 + .../Analysis/SpecialFunctions/Pow/Deriv.lean | 7 + .../Analysis/SpecialFunctions/Pow/Real.lean | 35 ++++ Mathlib/Data/Complex/Abs.lean | 10 +- Mathlib/NumberTheory/AbelSummation.lean | 43 ++--- Mathlib/NumberTheory/LSeries/Basic.lean | 6 + Mathlib/NumberTheory/LSeries/SumCoeff.lean | 154 ++++++++++++++++++ Mathlib/Order/Interval/Finset/Nat.lean | 3 + 11 files changed, 289 insertions(+), 24 deletions(-) create mode 100644 Mathlib/NumberTheory/LSeries/SumCoeff.lean diff --git a/Mathlib.lean b/Mathlib.lean index 601df39d4cf67..7222c8e7e64fc 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4020,6 +4020,7 @@ import Mathlib.NumberTheory.LSeries.Nonvanishing import Mathlib.NumberTheory.LSeries.Positivity import Mathlib.NumberTheory.LSeries.PrimesInAP import Mathlib.NumberTheory.LSeries.RiemannZeta +import Mathlib.NumberTheory.LSeries.SumCoeff import Mathlib.NumberTheory.LSeries.ZMod import Mathlib.NumberTheory.LegendreSymbol.AddCharacter import Mathlib.NumberTheory.LegendreSymbol.Basic diff --git a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean index e1c0e57e890c5..00668c051caf3 100644 --- a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean @@ -3,9 +3,8 @@ Copyright (c) 2021 Anatole Dedecker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker -/ -import Mathlib.Analysis.Normed.Order.Basic -import Mathlib.Analysis.Asymptotics.Lemmas -import Mathlib.Analysis.Normed.Module.Basic +import Mathlib.Analysis.Asymptotics.AsymptoticEquivalent +import Mathlib.Analysis.SpecificLimits.Basic /-! # A collection of specific asymptotic results @@ -143,3 +142,19 @@ theorem Filter.Tendsto.cesaro {u : ℕ → ℝ} {l : ℝ} (h : Tendsto u atTop ( h.cesaro_smul end Real + +section NormedLinearOrderedField + +variable {R : Type*} [NormedLinearOrderedField R] [OrderTopology R] [FloorRing R] + +theorem Asymptotics.isEquivalent_nat_floor : + (fun (x : R) ↦ ↑⌊x⌋₊) ~[atTop] (fun x ↦ x) := by + refine isEquivalent_of_tendsto_one ?_ tendsto_nat_floor_div_atTop + filter_upwards with x hx using by rw [hx, Nat.floor_zero, Nat.cast_eq_zero] + +theorem Asymptotics.isEquivalent_nat_ceil : + (fun (x : R) ↦ ↑⌈x⌉₊) ~[atTop] (fun x ↦ x) := by + refine isEquivalent_of_tendsto_one ?_ tendsto_nat_ceil_div_atTop + filter_upwards with x hx using by rw [hx, Nat.ceil_zero, Nat.cast_eq_zero] + +end NormedLinearOrderedField diff --git a/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean b/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean index 3ef729e02e9f1..4e8ea696d800a 100644 --- a/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean +++ b/Mathlib/Analysis/SpecialFunctions/ImproperIntegrals.lean @@ -81,6 +81,14 @@ theorem integrableOn_Ioi_rpow_iff {s t : ℝ} (ht : 0 < t) : exact Real.rpow_le_rpow_of_exponent_le x_one h exact not_IntegrableOn_Ioi_inv this +theorem integrableAtFilter_rpow_atTop_iff {s : ℝ} : + IntegrableAtFilter (fun x : ℝ ↦ x ^ s) atTop ↔ s < -1 := by + refine ⟨fun ⟨t, ht, hint⟩ ↦ ?_, fun h ↦ + ⟨Set.Ioi 1, Ioi_mem_atTop 1, (integrableOn_Ioi_rpow_iff zero_lt_one).mpr h⟩⟩ + obtain ⟨a, ha⟩ := mem_atTop_sets.mp ht + refine (integrableOn_Ioi_rpow_iff (zero_lt_one.trans_le (le_max_right a 1))).mp ?_ + exact hint.mono_set <| fun x hx ↦ ha _ <| (le_max_left a 1).trans hx.le + /-- The real power function with any exponent is not integrable on `(0, +∞)`. -/ theorem not_integrableOn_Ioi_rpow (s : ℝ) : ¬ IntegrableOn (fun x ↦ x ^ s) (Ioi (0 : ℝ)) := by intro h @@ -127,6 +135,24 @@ theorem integrableOn_Ioi_cpow_iff {s : ℂ} {t : ℝ} (ht : 0 < t) : simp [Complex.abs_cpow_eq_rpow_re_of_pos this] rwa [integrableOn_Ioi_rpow_iff ht] at B +theorem integrableOn_Ioi_deriv_ofReal_cpow {s : ℂ} {t : ℝ} (ht : 0 < t) (hs : s.re < 0) : + IntegrableOn (deriv fun x : ℝ ↦ (x : ℂ) ^ s) (Set.Ioi t) := by + have h : IntegrableOn (fun x : ℝ ↦ s * x ^ (s - 1)) (Set.Ioi t) := by + refine (integrableOn_Ioi_cpow_of_lt ?_ ht).const_mul _ + rwa [Complex.sub_re, Complex.one_re, sub_lt_iff_lt_add, neg_add_cancel] + refine h.congr_fun (fun x hx ↦ ?_) measurableSet_Ioi + rw [Complex.deriv_ofReal_cpow_const (ht.trans hx).ne' (fun h ↦ (Complex.zero_re ▸ h ▸ hs).false)] + +theorem integrableOn_Ioi_deriv_norm_ofReal_cpow {s : ℂ} {t : ℝ} (ht : 0 < t) (hs : s.re ≤ 0): + IntegrableOn (deriv fun x : ℝ ↦ ‖(x : ℂ) ^ s‖) (Set.Ioi t) := by + rw [integrableOn_congr_fun (fun x hx ↦ by + rw [deriv_norm_ofReal_cpow _ (ht.trans hx)]) measurableSet_Ioi] + obtain hs | hs := eq_or_lt_of_le hs + · simp_rw [hs, zero_mul] + exact integrableOn_zero + · replace hs : s.re - 1 < - 1 := by rwa [sub_lt_iff_lt_add, neg_add_cancel] + exact (integrableOn_Ioi_rpow_of_lt hs ht).const_mul s.re + /-- The complex power function with any exponent is not integrable on `(0, +∞)`. -/ theorem not_integrableOn_Ioi_cpow (s : ℂ) : ¬ IntegrableOn (fun x : ℝ ↦ (x : ℂ) ^ s) (Ioi (0 : ℝ)) := by diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean index 0407d95d6e2cc..30cb5251b049e 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean @@ -42,6 +42,13 @@ theorem cpow_eq_zero_iff (x y : ℂ) : x ^ y = 0 ↔ x = 0 ∧ y ≠ 0 := by simp only [cpow_def] split_ifs <;> simp [*, exp_ne_zero] +theorem cpow_ne_zero_iff {x y : ℂ} : + x ^ y ≠ 0 ↔ x ≠ 0 ∨ y = 0 := by + rw [ne_eq, cpow_eq_zero_iff, not_and_or, ne_eq, not_not] + +theorem cpow_ne_zero_iff_of_exponent_ne_zero {x y : ℂ} (hy : y ≠ 0) : + x ^ y ≠ 0 ↔ x ≠ 0 := by simp [hy] + @[simp] theorem zero_cpow {x : ℂ} (h : x ≠ 0) : (0 : ℂ) ^ x = 0 := by simp [cpow_def, *] diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean index 901b5b2038c02..88657855528d1 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean @@ -623,6 +623,13 @@ theorem deriv_rpow_const (hf : DifferentiableAt ℝ f x) (hx : f x ≠ 0 ∨ 1 deriv (fun x => f x ^ p) x = deriv f x * p * f x ^ (p - 1) := (hf.hasDerivAt.rpow_const hx).deriv +theorem deriv_norm_ofReal_cpow (c : ℂ) {t : ℝ} (ht : 0 < t) : + (deriv fun x : ℝ ↦ ‖(x : ℂ) ^ c‖) t = c.re * t ^ (c.re - 1) := by + rw [EventuallyEq.deriv_eq (f := fun x ↦ x ^ c.re)] + · rw [Real.deriv_rpow_const (Or.inl ht.ne')] + · filter_upwards [eventually_gt_nhds ht] with x hx + rw [Complex.norm_eq_abs, Complex.abs_cpow_eq_rpow_re_of_pos hx] + lemma isTheta_deriv_rpow_const_atTop {p : ℝ} (hp : p ≠ 0) : deriv (fun (x : ℝ) => x ^ p) =Θ[atTop] fun x => x ^ (p-1) := by calc deriv (fun (x : ℝ) => x ^ p) =ᶠ[atTop] fun x => p * x ^ (p - 1) := by diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index a49168a3cabb8..fabc68692ced8 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -318,6 +318,12 @@ theorem abs_cpow_eq_rpow_re_of_nonneg {x : ℝ} (hx : 0 ≤ x) {y : ℂ} (hy : r abs (x ^ y) = x ^ re y := by rw [abs_cpow_of_imp] <;> simp [*, arg_ofReal_of_nonneg, _root_.abs_of_nonneg] +open Filter in +lemma norm_ofReal_cpow_eventually_eq_atTop (c : ℂ) : + (fun t : ℝ ↦ ‖(t : ℂ) ^ c‖) =ᶠ[atTop] fun t ↦ t ^ c.re := by + filter_upwards [eventually_gt_atTop 0] with t ht + rw [Complex.norm_eq_abs, abs_cpow_eq_rpow_re_of_pos ht] + lemma norm_natCast_cpow_of_re_ne_zero (n : ℕ) {s : ℂ} (hs : s.re ≠ 0) : ‖(n : ℂ) ^ s‖ = (n : ℝ) ^ (s.re) := by rw [norm_eq_abs, ← ofReal_natCast, abs_cpow_eq_rpow_re_of_nonneg n.cast_nonneg hs] @@ -962,6 +968,35 @@ lemma norm_log_natCast_le_rpow_div (n : ℕ) {ε : ℝ} (hε : 0 < ε) : ‖log end Complex +namespace Asymptotics + +open Filter + +variable {E : Type*} [SeminormedRing E] (a b c : ℝ) + +theorem IsBigO.mul_atTop_rpow_of_isBigO_rpow {f g : ℝ → E} + (hf : f =O[atTop] fun t ↦ (t : ℝ) ^ a) (hg : g =O[atTop] fun t ↦ (t : ℝ) ^ b) + (h : a + b ≤ c) : + (f * g) =O[atTop] fun t ↦ (t : ℝ) ^ c := by + refine (hf.mul hg).trans (Eventually.isBigO ?_) + filter_upwards [eventually_ge_atTop 1] with t ht + rw [← Real.rpow_add (zero_lt_one.trans_le ht), Real.norm_of_nonneg (Real.rpow_nonneg + (zero_le_one.trans ht) (a + b))] + exact Real.rpow_le_rpow_of_exponent_le ht h + +theorem IsBigO.mul_atTop_rpow_natCast_of_isBigO_rpow {f g : ℕ → E} + (hf : f =O[atTop] fun n ↦ (n : ℝ) ^ a) (hg : g =O[atTop] fun n ↦ (n : ℝ) ^ b) + (h : a + b ≤ c) : + (f * g) =O[atTop] fun n ↦ (n : ℝ) ^ c := by + refine (hf.mul hg).trans (Eventually.isBigO ?_) + filter_upwards [eventually_ge_atTop 1] with t ht + replace ht : 1 ≤ (t : ℝ) := Nat.one_le_cast.mpr ht + rw [← Real.rpow_add (zero_lt_one.trans_le ht), Real.norm_of_nonneg (Real.rpow_nonneg + (zero_le_one.trans ht) (a + b))] + exact Real.rpow_le_rpow_of_exponent_le ht h + +end Asymptotics + /-! ## Square roots of reals -/ diff --git a/Mathlib/Data/Complex/Abs.lean b/Mathlib/Data/Complex/Abs.lean index 7531c38a54ff3..92b673fb0b86a 100644 --- a/Mathlib/Data/Complex/Abs.lean +++ b/Mathlib/Data/Complex/Abs.lean @@ -291,10 +291,16 @@ theorem lim_abs (f : CauSeq ℂ Complex.abs) : lim (cauSeqAbs f) = Complex.abs ( let ⟨i, hi⟩ := equiv_lim f ε ε0 ⟨i, fun j hj => lt_of_le_of_lt (Complex.abs.abs_abv_sub_le_abv_sub _ _) (hi j hj)⟩ +lemma ne_zero_of_re_pos {s : ℂ} (hs : 0 < s.re) : s ≠ 0 := + fun h ↦ (zero_re ▸ h ▸ hs).false + lemma ne_zero_of_one_lt_re {s : ℂ} (hs : 1 < s.re) : s ≠ 0 := - fun h ↦ ((zero_re ▸ h ▸ hs).trans zero_lt_one).false + ne_zero_of_re_pos <| zero_lt_one.trans hs + +lemma re_neg_ne_zero_of_re_pos {s : ℂ} (hs : 0 < s.re) : (-s).re ≠ 0 := + ne_iff_lt_or_gt.mpr <| Or.inl <| neg_re s ▸ (neg_lt_zero.mpr hs) lemma re_neg_ne_zero_of_one_lt_re {s : ℂ} (hs : 1 < s.re) : (-s).re ≠ 0 := - ne_iff_lt_or_gt.mpr <| Or.inl <| neg_re s ▸ by linarith + re_neg_ne_zero_of_re_pos <| zero_lt_one.trans hs end Complex diff --git a/Mathlib/NumberTheory/AbelSummation.lean b/Mathlib/NumberTheory/AbelSummation.lean index 202136f5c40ad..e31f094ec8fa5 100644 --- a/Mathlib/NumberTheory/AbelSummation.lean +++ b/Mathlib/NumberTheory/AbelSummation.lean @@ -51,8 +51,8 @@ namespace abelSummationProof open intervalIntegral IntervalIntegrable -private theorem sumlocc (n : ℕ) : - ∀ᵐ t, t ∈ Set.Icc (n : ℝ) (n + 1) → ∑ k ∈ Icc 0 ⌊t⌋₊, c k = ∑ k ∈ Icc 0 n, c k := by +private theorem sumlocc {m : ℕ} (n : ℕ) : + ∀ᵐ t, t ∈ Set.Icc (n : ℝ) (n + 1) → ∑ k ∈ Icc m ⌊t⌋₊, c k = ∑ k ∈ Icc m n, c k := by filter_upwards [Ico_ae_eq_Icc] with t h ht rw [Nat.floor_eq_on_Ico _ _ (h.mpr ht)] @@ -83,11 +83,12 @@ private theorem ineqofmemIco' {k : ℕ} (hk : k ∈ Ico (⌊a⌋₊ + 1) ⌊b⌋ a ≤ k ∧ k + 1 ≤ b := ineqofmemIco (by rwa [← Finset.coe_Ico]) -private theorem integrablemulsum (ha : 0 ≤ a) {g : ℝ → 𝕜} (hg_int : IntegrableOn g (Set.Icc a b)) : - IntegrableOn (fun t ↦ g t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) (Set.Icc a b) := by +theorem _root_.integrableOn_mul_sum_Icc {m : ℕ} (ha : 0 ≤ a) {g : ℝ → 𝕜} + (hg_int : IntegrableOn g (Set.Icc a b)) : + IntegrableOn (fun t ↦ g t * ∑ k ∈ Icc m ⌊t⌋₊, c k) (Set.Icc a b) := by obtain hab | hab := le_or_gt a b · obtain hb | hb := eq_or_lt_of_le (Nat.floor_le_floor hab) - · have : ∀ᵐ t, t ∈ Set.Icc a b → ∑ k ∈ Icc 0 ⌊a⌋₊, c k = ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by + · have : ∀ᵐ t, t ∈ Set.Icc a b → ∑ k ∈ Icc m ⌊a⌋₊, c k = ∑ k ∈ Icc m ⌊t⌋₊, c k := by filter_upwards [sumlocc c ⌊a⌋₊] with t ht₁ ht₂ rw [ht₁ ⟨(Nat.floor_le ha).trans ht₂.1, hb ▸ ht₂.2.trans (Nat.lt_floor_add_one b).le⟩] rw [← ae_restrict_iff' measurableSet_Icc] at this @@ -95,7 +96,7 @@ private theorem integrablemulsum (ha : 0 ≤ a) {g : ℝ → 𝕜} (hg_int : Int (hg_int.mul_const _) ((Filter.EventuallyEq.refl _ g).mul this) · have h_locint {t₁ t₂ : ℝ} {n : ℕ} (h : t₁ ≤ t₂) (h₁ : n ≤ t₁) (h₂ : t₂ ≤ n + 1) (h₃ : a ≤ t₁) (h₄ : t₂ ≤ b) : - IntervalIntegrable (fun t ↦ g t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) volume t₁ t₂ := by + IntervalIntegrable (fun t ↦ g t * ∑ k ∈ Icc m ⌊t⌋₊, c k) volume t₁ t₂ := by rw [intervalIntegrable_iff_integrableOn_Icc_of_le h] exact (IntegrableOn.mono_set (hg_int.mul_const _) (Set.Icc_subset_Icc h₃ h₄)).congr <| ae_restrict_of_ae_restrict_of_subset (Set.Icc_subset_Icc h₁ h₂) @@ -154,15 +155,15 @@ theorem _root_.sum_mul_eq_sub_sub_integral_mul (ha : 0 ≤ a) (hab : a ≤ b) -- (Note we have 5 goals, but the 1st and 3rd are identical. TODO: find a non-hacky way of dealing -- with both at once.) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux6] - exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux5) + exact (integrableOn_mul_sum_Icc c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux5) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux5] - exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_left aux6) + exact (integrableOn_mul_sum_Icc c ha hf_int).mono_set (Set.Icc_subset_Icc_left aux6) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux6] - exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux5) + exact (integrableOn_mul_sum_Icc c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux5) · rw [intervalIntegrable_iff_integrableOn_Icc_of_le aux3] - exact (integrablemulsum c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux4) + exact (integrableOn_mul_sum_Icc c ha hf_int).mono_set (Set.Icc_subset_Icc_right aux4) · exact fun k hk ↦ (intervalIntegrable_iff_integrableOn_Icc_of_le (mod_cast k.le_succ)).mpr - <| (integrablemulsum c ha hf_int).mono_set + <| (integrableOn_mul_sum_Icc c ha hf_int).mono_set <| (Set.Icc_subset_Icc_iff (mod_cast k.le_succ)).mpr <| mod_cast (ineqofmemIco hk) /-- A version of `sum_mul_eq_sub_sub_integral_mul` where the endpoints are `Nat`. -/ @@ -209,7 +210,7 @@ theorem sum_mul_eq_sub_integral_mul₀ (hc : c 0 = 0) (b : ℝ) f b * (∑ k ∈ Icc 0 ⌊b⌋₊, c k) - ∫ t in Set.Ioc 1 b, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k := by obtain hb | hb := le_or_gt 1 b · have : 1 ≤ ⌊b⌋₊ := (Nat.one_le_floor_iff _).mpr hb - nth_rewrite 1 [Icc_eq_cons_Ioc (by omega), sum_cons, ← Nat.Icc_succ_left, + nth_rewrite 1 [Icc_eq_cons_Ioc (Nat.zero_le _), sum_cons, ← Nat.Icc_succ_left, Icc_eq_cons_Ioc (by omega), sum_cons] rw [Nat.succ_eq_add_one, zero_add, ← Nat.floor_one (α := ℝ), sum_mul_eq_sub_sub_integral_mul c zero_le_one hb hf_diff hf_int, Nat.floor_one, Nat.cast_one, @@ -235,13 +236,14 @@ section limit open Filter Topology abelSummationProof intervalIntegral -private theorem locallyintegrablemulsum (ha : 0 ≤ a) {g : ℝ → 𝕜} (hg : IntegrableOn g (Set.Ici a)) : - LocallyIntegrableOn (fun t ↦ g t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) (Set.Ici a) := by +theorem locallyIntegrableOn_mul_sum_Icc {m : ℕ} (ha : 0 ≤ a) {g : ℝ → 𝕜} + (hg : IntegrableOn g (Set.Ici a)) : + LocallyIntegrableOn (fun t ↦ g t * ∑ k ∈ Icc m ⌊t⌋₊, c k) (Set.Ici a) := by refine (locallyIntegrableOn_iff isLocallyClosed_Ici).mpr fun K hK₁ hK₂ ↦ ?_ by_cases hK₃ : K.Nonempty · have h_inf : a ≤ sInf K := (hK₁ (hK₂.sInf_mem hK₃)) refine IntegrableOn.mono_set ?_ (Bornology.IsBounded.subset_Icc_sInf_sSup hK₂.isBounded) - refine integrablemulsum _ (ha.trans h_inf) (hg.mono_set ?_) + refine integrableOn_mul_sum_Icc _ (ha.trans h_inf) (hg.mono_set ?_) exact (Set.Icc_subset_Ici_iff (Real.sInf_le_sSup _ hK₂.bddBelow hK₂.bddAbove)).mpr h_inf · rw [Set.not_nonempty_iff_eq_empty.mp hK₃] exact integrableOn_empty @@ -259,7 +261,8 @@ theorem tendsto_sum_mul_atTop_nhds_one_sub_integral refine Tendsto.congr (fun _ ↦ by rw [← integral_of_le (Nat.cast_nonneg _)]) ?_ refine intervalIntegral_tendsto_integral_Ioi _ ?_ tendsto_natCast_atTop_atTop exact integrableOn_Ici_iff_integrableOn_Ioi.mp - <| (locallyintegrablemulsum c le_rfl hf_int).integrableOn_of_isBigO_atTop hg_dom hg_int + <| (locallyIntegrableOn_mul_sum_Icc c le_rfl hf_int).integrableOn_of_isBigO_atTop + hg_dom hg_int refine (h_lim.sub h_lim').congr (fun _ ↦ ?_) rw [sum_mul_eq_sub_integral_mul' _ _ (fun t ht ↦ hf_diff _ ht.1) (hf_int.mono_set Set.Icc_subset_Ici_self)] @@ -280,7 +283,8 @@ theorem tendsto_sum_mul_atTop_nhds_one_sub_integral₀ (hc : c 0 = 0) atTop (𝓝 (∫ t in Set.Ioi 1, deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k)) := by refine Tendsto.congr' h (intervalIntegral_tendsto_integral_Ioi _ ?_ tendsto_natCast_atTop_atTop) exact integrableOn_Ici_iff_integrableOn_Ioi.mp - <| (locallyintegrablemulsum c zero_le_one hf_int).integrableOn_of_isBigO_atTop hg_dom hg_int + <| (locallyIntegrableOn_mul_sum_Icc c zero_le_one hf_int).integrableOn_of_isBigO_atTop + hg_dom hg_int refine (h_lim.sub h_lim').congr (fun _ ↦ ?_) rw [sum_mul_eq_sub_integral_mul₀' _ hc _ (fun t ht ↦ hf_diff _ ht.1) (hf_int.mono_set Set.Icc_subset_Ici_self)] @@ -325,9 +329,10 @@ private theorem summable_mul_of_bigO_atTop_aux (m : ℕ) · exact add_le_add_left (le_trans (neg_le_abs _) (Real.norm_eq_abs _ ▸ norm_integral_le_integral_norm _)) _ · refine add_le_add_left (setIntegral_mono_set ?_ ?_ Set.Ioc_subset_Ioi_self.eventuallyLE) C₁ - · refine integrableOn_Ici_iff_integrableOn_Ioi.mp <| + · exact integrableOn_Ici_iff_integrableOn_Ioi.mp <| (integrable_norm_iff h_mes.aestronglyMeasurable).mpr <| - (locallyintegrablemulsum _ m.cast_nonneg hf_int).integrableOn_of_isBigO_atTop hg₁ hg₂ + (locallyIntegrableOn_mul_sum_Icc _ m.cast_nonneg hf_int).integrableOn_of_isBigO_atTop + hg₁ hg₂ · filter_upwards with t using norm_nonneg _ theorem summable_mul_of_bigO_atTop diff --git a/Mathlib/NumberTheory/LSeries/Basic.lean b/Mathlib/NumberTheory/LSeries/Basic.lean index 3faf700efb403..3f0a95887411d 100644 --- a/Mathlib/NumberTheory/LSeries/Basic.lean +++ b/Mathlib/NumberTheory/LSeries/Basic.lean @@ -68,6 +68,12 @@ lemma term_def (f : ℕ → ℂ) (s : ℂ) (n : ℕ) : term f s n = if n = 0 then 0 else f n / n ^ s := rfl +/-- An alternate spelling of `term_def` for the case `f 0 = 0`. -/ +lemma term_def₀ {f : ℕ → ℂ} (hf : f 0 = 0) (s : ℂ) (n : ℕ) : + LSeries.term f s n = f n * (n : ℂ) ^ (- s) := by + rw [LSeries.term] + split_ifs with h <;> simp [h, hf, cpow_neg, div_eq_inv_mul, mul_comm] + @[simp] lemma term_zero (f : ℕ → ℂ) (s : ℂ) : term f s 0 = 0 := rfl diff --git a/Mathlib/NumberTheory/LSeries/SumCoeff.lean b/Mathlib/NumberTheory/LSeries/SumCoeff.lean new file mode 100644 index 0000000000000..35a11908fb0fe --- /dev/null +++ b/Mathlib/NumberTheory/LSeries/SumCoeff.lean @@ -0,0 +1,154 @@ +/- +Copyright (c) 2025 Xavier Roblot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Xavier Roblot +-/ +import Mathlib.Analysis.Asymptotics.SpecificAsymptotics +import Mathlib.Analysis.InnerProductSpace.Calculus +import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals +import Mathlib.NumberTheory.AbelSummation +import Mathlib.NumberTheory.LSeries.Basic + +/-! +# Partial sums of coefficients of L-series + +We prove several results involving partial sums of coefficients (or norm of coefficients) of +L-series. + +## Main results + +* `LSeriesSummable_of_sum_norm_bigO`: for `f : ℕ → ℂ`, if the partial sums + `∑ k ∈ Icc 1 n, ‖f k‖` are `O(n ^ r)` for some real `0 ≤ r`, then the L-series `LSeries f` + converges at `s : ℂ` for all `s` such that `r < s.re`. + +* `LSeries_eq_mul_integral` : for `f : ℕ → ℂ`, if the partial sums `∑ k ∈ Icc 1 n, f k` are + `O(n ^ r)` for some real `0 ≤ r` and the L-series `LSeries f` converges at `s : ℂ` with + `r < s.re`, then `LSeries f s = s * ∫ t in Set.Ioi 1, (∑ k ∈ Icc 1 ⌊t⌋₊, f k) * t ^ (-(s + 1))`. + +-/ + +open Finset Filter MeasureTheory Topology Complex Asymptotics + +section summable + +variable {f : ℕ → ℂ} {r : ℝ} {s : ℂ} + +private theorem LSeriesSummable_of_sum_norm_bigO_aux (hf : f 0 = 0) + (hO : (fun n ↦ ∑ k ∈ Icc 1 n, ‖f k‖) =O[atTop] fun n ↦ (n : ℝ) ^ r) + (hr : 0 ≤ r) (hs : r < s.re) : + LSeriesSummable f s := by + have h₁ : -s ≠ 0 := neg_ne_zero.mpr <| ne_zero_of_re_pos (hr.trans_lt hs) + have h₂ : (-s).re + r ≤ 0 := by + rw [neg_re, neg_add_nonpos_iff] + exact hs.le + have h₃ (t : ℝ) (ht : t ∈ Set.Ici 1) : DifferentiableAt ℝ (fun x : ℝ ↦ ‖(x : ℂ) ^ (-s)‖) t := + have ht' : t ≠ 0 := (zero_lt_one.trans_le ht).ne' + (differentiableAt_id.ofReal_cpow_const ht' h₁).norm ℝ <| + (cpow_ne_zero_iff_of_exponent_ne_zero h₁).mpr <| ofReal_ne_zero.mpr ht' + have h₄ : (deriv fun t : ℝ ↦ ‖(t : ℂ) ^ (-s)‖) =ᶠ[atTop] fun t ↦ -s.re * t ^ (-(s.re +1)) := by + filter_upwards [eventually_gt_atTop 0] with t ht + rw [deriv_norm_ofReal_cpow _ ht, neg_re, neg_add'] + simp_rw [LSeriesSummable, funext (LSeries.term_def₀ hf s), mul_comm (f _)] + refine summable_mul_of_bigO_atTop' (f := fun t ↦ (t : ℂ) ^ (-s)) + (g := fun t ↦ t ^ (-(s.re + 1) + r)) _ h₃ ?_ ?_ ?_ ?_ + · refine integrableOn_Ici_iff_integrableOn_Ioi.mpr + (integrableOn_Ioi_deriv_norm_ofReal_cpow zero_lt_one ?_) + exact neg_re _ ▸ neg_nonpos.mpr <| hr.trans hs.le + · refine (IsBigO.mul_atTop_rpow_natCast_of_isBigO_rpow _ _ _ ?_ hO h₂).congr_right (by simp) + exact (norm_ofReal_cpow_eventually_eq_atTop _).isBigO.natCast_atTop + · refine h₄.isBigO.of_const_mul_right.mul_atTop_rpow_of_isBigO_rpow _ r _ ?_ le_rfl + exact (hO.comp_tendsto tendsto_nat_floor_atTop).trans <| + isEquivalent_nat_floor.isBigO.rpow hr (eventually_ge_atTop 0) + · rwa [integrableAtFilter_rpow_atTop_iff, neg_add_lt_iff_lt_add, add_neg_cancel_right] + +/-- If the partial sums `∑ k ∈ Icc 1 n, ‖f k‖` are `O(n ^ r)` for some real `0 ≤ r`, then the +L-series `LSeries f` converges at `s : ℂ` for all `s` such that `r < s.re`. -/ +theorem LSeriesSummable_of_sum_norm_bigO + (hO : (fun n ↦ ∑ k ∈ Icc 1 n, ‖f k‖) =O[atTop] fun n ↦ (n : ℝ) ^ r) + (hr : 0 ≤ r) (hs : r < s.re) : + LSeriesSummable f s := by + have h₁ : (fun n ↦ if n = 0 then 0 else f n) =ᶠ[atTop] f := by + filter_upwards [eventually_ne_atTop 0] with n hn using by simp_rw [if_neg hn] + refine (LSeriesSummable_of_sum_norm_bigO_aux (if_pos rfl) ?_ hr hs).congr' _ h₁ + refine hO.congr' (Eventually.of_forall fun _ ↦ Finset.sum_congr rfl fun _ h ↦ ?_) EventuallyEq.rfl + rw [if_neg (zero_lt_one.trans_le (mem_Icc.mp h).1).ne'] + +/-- If `f` takes nonnegative real values and the partial sums `∑ k ∈ Icc 1 n, f k` are `O(n ^ r)` +for some real `0 ≤ r`, then the L-series `LSeries f` converges at `s : ℂ` for all `s` +such that `r < s.re`. -/ +theorem LSeriesSummable_of_sum_norm_bigO_and_nonneg + {f : ℕ → ℝ} (hO : (fun n ↦ ∑ k ∈ Icc 1 n, f k) =O[atTop] fun n ↦ (n : ℝ) ^ r) + (hf : ∀ n, 0 ≤ f n) (hr : 0 ≤ r) (hs : r < s.re) : + LSeriesSummable (fun n ↦ f n) s := + LSeriesSummable_of_sum_norm_bigO (by simpa [_root_.abs_of_nonneg (hf _)]) hr hs + +end summable + +section integralrepresentation + +private theorem LSeries_eq_mul_integral_aux {f : ℕ → ℂ} (hf : f 0 = 0) {r : ℝ} (hr : 0 ≤ r) {s : ℂ} + (hs : r < s.re) (hS : LSeriesSummable f s) + (hO : (fun n ↦ ∑ k ∈ Icc 1 n, f k) =O[atTop] fun n ↦ (n : ℝ) ^ r) : + LSeries f s = s * ∫ t in Set.Ioi (1 : ℝ), (∑ k ∈ Icc 1 ⌊t⌋₊, f k) * t ^ (- (s + 1)) := by + have h₁ : (-s - 1).re + r < -1 := by + rwa [sub_re, one_re, neg_re, neg_sub_left, neg_add_lt_iff_lt_add, add_neg_cancel_comm] + have h₂ : s ≠ 0 := ne_zero_of_re_pos (hr.trans_lt hs) + have h₃ (t : ℝ) (ht : t ∈ Set.Ici 1) : DifferentiableAt ℝ (fun x : ℝ ↦ (x : ℂ) ^ (-s)) t := + differentiableAt_id.ofReal_cpow_const (zero_lt_one.trans_le ht).ne' (neg_ne_zero.mpr h₂) + have h₄ : ∀ n, ∑ k ∈ Icc 0 n, f k = ∑ k ∈ Icc 1 n, f k := fun n ↦ by + rw [← Nat.Icc_insert_succ_left n.zero_le, sum_insert (by aesop), hf, zero_add, zero_add] + simp_rw [← h₄] at hO + rw [← integral_mul_left] + refine tendsto_nhds_unique ((tendsto_add_atTop_iff_nat 1).mpr hS.hasSum.tendsto_sum_nat) ?_ + simp_rw [Nat.range_succ_eq_Icc_zero, LSeries.term_def₀ hf, mul_comm (f _)] + convert tendsto_sum_mul_atTop_nhds_one_sub_integral₀ (f := fun x ↦ (x : ℂ) ^ (-s)) (l := 0) + ?_ hf h₃ ?_ ?_ ?_ (integrableAtFilter_rpow_atTop_iff.mpr h₁) + · rw [zero_sub, ← integral_neg] + refine setIntegral_congr_fun measurableSet_Ioi fun t ht ↦ ?_ + rw [deriv_ofReal_cpow_const (zero_lt_one.trans ht).ne', h₄] + · ring_nf + · exact neg_ne_zero.mpr <| ne_zero_of_re_pos (hr.trans_lt hs) + · refine integrableOn_Ici_iff_integrableOn_Ioi.mpr <| + integrableOn_Ioi_deriv_ofReal_cpow zero_lt_one (by simpa using hr.trans_lt hs) + · have hlim : Tendsto (fun n : ℕ ↦ (n : ℝ) ^ (-(s.re - r))) atTop (𝓝 0) := + (tendsto_rpow_neg_atTop (by rwa [sub_pos])).comp tendsto_natCast_atTop_atTop + refine (IsBigO.mul_atTop_rpow_natCast_of_isBigO_rpow (-s.re) _ _ ?_ hO ?_).trans_tendsto hlim + · exact isBigO_norm_left.mp <| (norm_ofReal_cpow_eventually_eq_atTop _).isBigO.natCast_atTop + · linarith + · refine .mul_atTop_rpow_of_isBigO_rpow (-(s + 1).re) r _ ?_ ?_ (by rw [← neg_re, neg_add']) + · simpa [- neg_add_rev, neg_add'] using isBigO_deriv_ofReal_cpow_const_atTop _ + · exact (hO.comp_tendsto tendsto_nat_floor_atTop).trans <| + isEquivalent_nat_floor.isBigO.rpow hr (eventually_ge_atTop 0) + +/-- If the partial sums `∑ k ∈ Icc 1 n, f k` are `O(n ^ r)` for some real `0 ≤ r` and the +L-series `LSeries f` converges at `s : ℂ` with `r < s.re`, then +`LSeries f s = s * ∫ t in Set.Ioi 1, (∑ k ∈ Icc 1 ⌊t⌋₊, f k) * t ^ (-(s + 1))`. -/ +theorem LSeries_eq_mul_integral (f : ℕ → ℂ) {r : ℝ} (hr : 0 ≤ r) {s : ℂ} (hs : r < s.re) + (hS : LSeriesSummable f s) + (hO : (fun n ↦ ∑ k ∈ Icc 1 n, f k) =O[atTop] fun n ↦ (n : ℝ) ^ r) : + LSeries f s = s * ∫ t in Set.Ioi (1 : ℝ), (∑ k ∈ Icc 1 ⌊t⌋₊, f k) * t ^ (-(s + 1)) := by + rw [← LSeriesSummable_congr' s (f := fun n ↦ if n = 0 then 0 else f n) + (by filter_upwards [eventually_ne_atTop 0] with n h using if_neg h)] at hS + have (n) : ∑ k ∈ Icc 1 n, (if k = 0 then 0 else f k) = ∑ k ∈ Icc 1 n, f k := + Finset.sum_congr rfl fun k hk ↦ by rw [if_neg (zero_lt_one.trans_le (mem_Icc.mp hk).1).ne'] + rw [← LSeries_congr _ (fun _ ↦ if_neg _), LSeries_eq_mul_integral_aux (if_pos rfl) hr hs hS] <;> + simp_all + +/-- A version of `LSeries_eq_mul_integral` where we use the stronger condition that the partial sums +`∑ k ∈ Icc 1 n, ‖f k‖` are `O(n ^ r)` to deduce the integral representation. -/ +theorem LSeries_eq_mul_integral' (f : ℕ → ℂ) {r : ℝ} (hr : 0 ≤ r) {s : ℂ} (hs : r < s.re) + (hO : (fun n ↦ ∑ k ∈ Icc 1 n, ‖f k‖) =O[atTop] fun n ↦ (n : ℝ) ^ r) : + LSeries f s = s * ∫ t in Set.Ioi (1 : ℝ), (∑ k ∈ Icc 1 ⌊t⌋₊, f k) * t ^ (-(s + 1)) := + LSeries_eq_mul_integral _ hr hs (LSeriesSummable_of_sum_norm_bigO hO hr hs) <| + (isBigO_of_le _ fun _ ↦ (norm_sum_le _ _).trans <| Real.le_norm_self _).trans hO + +/-- If `f` takes nonnegative real values and the partial sums `∑ k ∈ Icc 1 n, f k` are `O(n ^ r)` +for some real `0 ≤ r`, then for `s : ℂ` with `r < s.re`, we have +`LSeries f s = s * ∫ t in Set.Ioi 1, (∑ k ∈ Icc 1 ⌊t⌋₊, f k) * t ^ (-(s + 1))`. -/ +theorem LSeries_eq_mul_integral_of_nonneg (f : ℕ → ℝ) {r : ℝ} (hr : 0 ≤ r) {s : ℂ} (hs : r < s.re) + (hO : (fun n ↦ ∑ k ∈ Icc 1 n, f k) =O[atTop] fun n ↦ (n : ℝ) ^ r) (hf : ∀ n, 0 ≤ f n) : + LSeries (fun n ↦ f n) s = + s * ∫ t in Set.Ioi (1 : ℝ), (∑ k ∈ Icc 1 ⌊t⌋₊, (f k : ℂ)) * t ^ (-(s + 1)) := + LSeries_eq_mul_integral' _ hr hs <| hO.congr_left fun _ ↦ by simp [_root_.abs_of_nonneg (hf _)] + +end integralrepresentation diff --git a/Mathlib/Order/Interval/Finset/Nat.lean b/Mathlib/Order/Interval/Finset/Nat.lean index d446eb5f35743..56f30d50f8236 100644 --- a/Mathlib/Order/Interval/Finset/Nat.lean +++ b/Mathlib/Order/Interval/Finset/Nat.lean @@ -65,6 +65,9 @@ lemma range_eq_Icc_zero_sub_one (n : ℕ) (hn : n ≠ 0) : range n = Icc 0 (n - theorem _root_.Finset.range_eq_Ico : range = Ico 0 := Ico_zero_eq_range.symm +theorem range_succ_eq_Icc_zero (n : ℕ) : range (n + 1) = Icc 0 n := by + rw [range_eq_Icc_zero_sub_one _ (Nat.add_one_ne_zero _), Nat.add_sub_cancel_right] + @[simp] lemma card_Icc : #(Icc a b) = b + 1 - a := List.length_range' .. @[simp] lemma card_Ico : #(Ico a b) = b - a := List.length_range' .. @[simp] lemma card_Ioc : #(Ioc a b) = b - a := List.length_range' .. From 41fd6951f93a0d743fa88588acad8327d72c4fec Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 27 Jan 2025 12:48:50 +0000 Subject: [PATCH 561/681] feat(Algebra/Category): `ConcreteCategory` instance for `AlgebraCat` (#21121) This is a step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This PR adds a `ConcreteCategory` instance for `AlgebraCat`. It also replaces the `Hom.hom` structure projection with an alias for `ConcreteCategory.hom`. Apparently this went perfectly well and everything stays working nicely. :) I have not tried to look for code that can be cleaned up now, only at what broke. I want to get started on cleanup when the other concrete category instances are in. --- .../Algebra/Category/AlgebraCat/Basic.lean | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean index 87dd242280419..808f200d06da4 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean @@ -61,15 +61,38 @@ variable {R} in structure Hom (A B : AlgebraCat.{v} R) where private mk :: /-- The underlying algebra map. -/ - hom : A →ₐ[R] B + hom' : A →ₐ[R] B instance : Category (AlgebraCat.{v} R) where Hom A B := Hom A B id A := ⟨AlgHom.id R A⟩ - comp f g := ⟨g.hom.comp f.hom⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ -instance {M N : AlgebraCat.{v} R} : CoeFun (M ⟶ N) (fun _ ↦ M → N) where - coe f := f.hom +instance : ConcreteCategory (AlgebraCat.{v} R) (· →ₐ[R] ·) where + hom := Hom.hom' + ofHom := Hom.mk + +variable {R} in +/-- Turn a morphism in `AlgebraCat` back into an `AlgHom`. -/ +abbrev Hom.hom {A B : AlgebraCat.{v} R} (f : Hom A B) := + ConcreteCategory.hom (C := AlgebraCat R) f + +variable {R} in +/-- Typecheck an `AlgHom` as a morphism in `AlgebraCat`. -/ +abbrev ofHom {A B : Type v} [Ring A] [Ring B] [Algebra R A] [Algebra R B] (f : A →ₐ[R] B) : + of R A ⟶ of R B := + ConcreteCategory.ofHom (C := AlgebraCat R) f + +variable {R} in +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (A B : AlgebraCat.{v} R) (f : Hom A B) := + f.hom + +initialize_simps_projections Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[simp] lemma hom_id {A : AlgebraCat.{v} R} : (𝟙 A : A ⟶ A).hom = AlgHom.id R A := rfl @@ -90,11 +113,7 @@ lemma comp_apply {A B C : AlgebraCat.{v} R} (f : A ⟶ B) (g : B ⟶ C) (a : A) lemma hom_ext {A B : AlgebraCat.{v} R} {f g : A ⟶ B} (hf : f.hom = g.hom) : f = g := Hom.ext hf -/-- Typecheck an `AlgHom` as a morphism in `AlgebraCat R`. -/ -abbrev ofHom {R : Type u} [CommRing R] {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] - (f : X →ₐ[R] Y) : of R X ⟶ of R Y := - ⟨f⟩ - +@[simp] lemma hom_ofHom {R : Type u} [CommRing R] {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] (f : X →ₐ[R] Y) : (ofHom f).hom = f := rfl @@ -127,12 +146,6 @@ lemma hom_inv_apply {A B : AlgebraCat.{v} R} (e : A ≅ B) (x : B) : e.hom (e.in instance : Inhabited (AlgebraCat R) := ⟨of R R⟩ -instance : HasForget.{v} (AlgebraCat.{v} R) where - forget := - { obj := fun R => R - map := fun f => f.hom } - forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ - lemma forget_obj {A : AlgebraCat.{v} R} : (forget (AlgebraCat.{v} R)).obj A = A := rfl lemma forget_map {A B : AlgebraCat.{v} R} (f : A ⟶ B) : From de461966ae0fa71c09b66072e72a81153208f405 Mon Sep 17 00:00:00 2001 From: "Tristan F.-R." Date: Mon, 27 Jan 2025 13:29:47 +0000 Subject: [PATCH 562/681] feat(Logic/IsEmpty/Relator): empty on sides (#20319) various proofs of Left/Right/BiTotal guaranteeing emptiness when certain types are empty. Co-authored-by: Tristan F. Co-authored-by: Tristan F.-R. --- Mathlib/Logic/IsEmpty.lean | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Mathlib/Logic/IsEmpty.lean b/Mathlib/Logic/IsEmpty.lean index fa48bd9fc85c3..d6c0c75306607 100644 --- a/Mathlib/Logic/IsEmpty.lean +++ b/Mathlib/Logic/IsEmpty.lean @@ -213,10 +213,22 @@ variable {α β : Type*} (R : α → β → Prop) theorem leftTotal_empty [IsEmpty α] : LeftTotal R := by simp only [LeftTotal, IsEmpty.forall_iff] +theorem leftTotal_iff_isEmpty_left [IsEmpty β] : LeftTotal R ↔ IsEmpty α := by + simp only [LeftTotal, IsEmpty.exists_iff, isEmpty_iff] + @[simp] theorem rightTotal_empty [IsEmpty β] : RightTotal R := by simp only [RightTotal, IsEmpty.forall_iff] +theorem rightTotal_iff_isEmpty_right [IsEmpty α] : RightTotal R ↔ IsEmpty β := by + simp only [RightTotal, IsEmpty.exists_iff, isEmpty_iff, imp_self] + @[simp] theorem biTotal_empty [IsEmpty α] [IsEmpty β] : BiTotal R := ⟨leftTotal_empty R, rightTotal_empty R⟩ + +theorem biTotal_iff_isEmpty_right [IsEmpty α] : BiTotal R ↔ IsEmpty β := by + simp only [BiTotal, leftTotal_empty, rightTotal_iff_isEmpty_right, true_and] + +theorem biTotal_iff_isEmpty_left [IsEmpty β] : BiTotal R ↔ IsEmpty α := by + simp only [BiTotal, leftTotal_iff_isEmpty_left, rightTotal_empty, and_true] From e779c77ec098b1f964424caa60a864eda84fd501 Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Mon, 27 Jan 2025 13:29:48 +0000 Subject: [PATCH 563/681] chore(Data/Complex/Exponential): split trig functions to new file (#21075) This PR splits Data/Complex/Exponential.lean into a new Trigonometric.lean file, addressing an instance of a long file linter trigger. --- Mathlib.lean | 1 + Mathlib/Analysis/Complex/Basic.lean | 2 +- .../Trigonometric/Chebyshev.lean | 2 +- Mathlib/Data/Complex/Exponential.lean | 884 +--------------- Mathlib/Data/Complex/Trigonometric.lean | 951 ++++++++++++++++++ Mathlib/Tactic/FunProp.lean | 2 +- MathlibTest/Recall.lean | 2 +- MathlibTest/positivity.lean | 2 +- 8 files changed, 959 insertions(+), 887 deletions(-) create mode 100644 Mathlib/Data/Complex/Trigonometric.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7222c8e7e64fc..636adb7f3c36c 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2501,6 +2501,7 @@ import Mathlib.Data.Complex.FiniteDimensional import Mathlib.Data.Complex.Module import Mathlib.Data.Complex.Order import Mathlib.Data.Complex.Orientation +import Mathlib.Data.Complex.Trigonometric import Mathlib.Data.Countable.Basic import Mathlib.Data.Countable.Defs import Mathlib.Data.Countable.Small diff --git a/Mathlib/Analysis/Complex/Basic.lean b/Mathlib/Analysis/Complex/Basic.lean index 73c4f7ae5cdfa..af99bc7e8dd7f 100644 --- a/Mathlib/Analysis/Complex/Basic.lean +++ b/Mathlib/Analysis/Complex/Basic.lean @@ -5,7 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Data.Complex.Module import Mathlib.Data.Complex.Order -import Mathlib.Data.Complex.Exponential +import Mathlib.Data.Complex.Trigonometric import Mathlib.Analysis.RCLike.Basic import Mathlib.Topology.Algebra.InfiniteSum.Field import Mathlib.Topology.Algebra.InfiniteSum.Module diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Chebyshev.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Chebyshev.lean index 049879b836902..e56f20010f8cf 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Chebyshev.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Chebyshev.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.Data.Complex.Exponential +import Mathlib.Data.Complex.Trigonometric import Mathlib.Data.Complex.Module import Mathlib.RingTheory.Polynomial.Chebyshev diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index 8972434892eb7..fd4dfde3db5b6 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -12,10 +12,9 @@ import Mathlib.Tactic.Bound.Attribute import Mathlib.Algebra.CharP.Defs /-! -# Exponential, trigonometric and hyperbolic trigonometric functions +# Exponential Function -This file contains the definitions of the real and complex exponential, sine, cosine, tangent, -hyperbolic sine, hyperbolic cosine, and hyperbolic tangent functions. +This file contains the definitions of the real and complex exponential function. -/ @@ -51,40 +50,6 @@ def exp' (z : ℂ) : CauSeq ℂ Complex.abs := def exp (z : ℂ) : ℂ := CauSeq.lim (exp' z) -/-- The complex sine function, defined via `exp` -/ -@[pp_nodot] -def sin (z : ℂ) : ℂ := - (exp (-z * I) - exp (z * I)) * I / 2 - -/-- The complex cosine function, defined via `exp` -/ -@[pp_nodot] -def cos (z : ℂ) : ℂ := - (exp (z * I) + exp (-z * I)) / 2 - -/-- The complex tangent function, defined as `sin z / cos z` -/ -@[pp_nodot] -def tan (z : ℂ) : ℂ := - sin z / cos z - -/-- The complex cotangent function, defined as `cos z / sin z` -/ -def cot (z : ℂ) : ℂ := - cos z / sin z - -/-- The complex hyperbolic sine function, defined via `exp` -/ -@[pp_nodot] -def sinh (z : ℂ) : ℂ := - (exp z - exp (-z)) / 2 - -/-- The complex hyperbolic cosine function, defined via `exp` -/ -@[pp_nodot] -def cosh (z : ℂ) : ℂ := - (exp z + exp (-z)) / 2 - -/-- The complex hyperbolic tangent function, defined as `sinh z / cosh z` -/ -@[pp_nodot] -def tanh (z : ℂ) : ℂ := - sinh z / cosh z - /-- scoped notation for the complex exponential function -/ scoped notation "cexp" => Complex.exp @@ -103,41 +68,6 @@ noncomputable section nonrec def exp (x : ℝ) : ℝ := (exp x).re -/-- The real sine function, defined as the real part of the complex sine -/ -@[pp_nodot] -nonrec def sin (x : ℝ) : ℝ := - (sin x).re - -/-- The real cosine function, defined as the real part of the complex cosine -/ -@[pp_nodot] -nonrec def cos (x : ℝ) : ℝ := - (cos x).re - -/-- The real tangent function, defined as the real part of the complex tangent -/ -@[pp_nodot] -nonrec def tan (x : ℝ) : ℝ := - (tan x).re - -/-- The real cotangent function, defined as the real part of the complex cotangent -/ -nonrec def cot (x : ℝ) : ℝ := - (cot x).re - -/-- The real hypebolic sine function, defined as the real part of the complex hyperbolic sine -/ -@[pp_nodot] -nonrec def sinh (x : ℝ) : ℝ := - (sinh x).re - -/-- The real hypebolic cosine function, defined as the real part of the complex hyperbolic cosine -/ -@[pp_nodot] -nonrec def cosh (x : ℝ) : ℝ := - (cosh x).re - -/-- The real hypebolic tangent function, defined as the real part of -the complex hyperbolic tangent -/ -@[pp_nodot] -nonrec def tanh (x : ℝ) : ℝ := - (tanh x).re - /-- scoped notation for the real exponential function -/ scoped notation "rexp" => Real.exp @@ -248,427 +178,6 @@ theorem exp_ofReal_im (x : ℝ) : (exp x).im = 0 := by rw [← ofReal_exp_ofReal theorem exp_ofReal_re (x : ℝ) : (exp x).re = Real.exp x := rfl -theorem two_sinh : 2 * sinh x = exp x - exp (-x) := - mul_div_cancel₀ _ two_ne_zero - -theorem two_cosh : 2 * cosh x = exp x + exp (-x) := - mul_div_cancel₀ _ two_ne_zero - -@[simp] -theorem sinh_zero : sinh 0 = 0 := by simp [sinh] - -@[simp] -theorem sinh_neg : sinh (-x) = -sinh x := by simp [sinh, exp_neg, (neg_div _ _).symm, add_mul] - -private theorem sinh_add_aux {a b c d : ℂ} : - (a - b) * (c + d) + (a + b) * (c - d) = 2 * (a * c - b * d) := by ring - -theorem sinh_add : sinh (x + y) = sinh x * cosh y + cosh x * sinh y := by - rw [← mul_right_inj' (two_ne_zero' ℂ), two_sinh, exp_add, neg_add, exp_add, eq_comm, mul_add, ← - mul_assoc, two_sinh, mul_left_comm, two_sinh, ← mul_right_inj' (two_ne_zero' ℂ), mul_add, - mul_left_comm, two_cosh, ← mul_assoc, two_cosh] - exact sinh_add_aux - -@[simp] -theorem cosh_zero : cosh 0 = 1 := by simp [cosh] - -@[simp] -theorem cosh_neg : cosh (-x) = cosh x := by simp [add_comm, cosh, exp_neg] - -private theorem cosh_add_aux {a b c d : ℂ} : - (a + b) * (c + d) + (a - b) * (c - d) = 2 * (a * c + b * d) := by ring - -theorem cosh_add : cosh (x + y) = cosh x * cosh y + sinh x * sinh y := by - rw [← mul_right_inj' (two_ne_zero' ℂ), two_cosh, exp_add, neg_add, exp_add, eq_comm, mul_add, ← - mul_assoc, two_cosh, ← mul_assoc, two_sinh, ← mul_right_inj' (two_ne_zero' ℂ), mul_add, - mul_left_comm, two_cosh, mul_left_comm, two_sinh] - exact cosh_add_aux - -theorem sinh_sub : sinh (x - y) = sinh x * cosh y - cosh x * sinh y := by - simp [sub_eq_add_neg, sinh_add, sinh_neg, cosh_neg] - -theorem cosh_sub : cosh (x - y) = cosh x * cosh y - sinh x * sinh y := by - simp [sub_eq_add_neg, cosh_add, sinh_neg, cosh_neg] - -theorem sinh_conj : sinh (conj x) = conj (sinh x) := by - rw [sinh, ← RingHom.map_neg, exp_conj, exp_conj, ← RingHom.map_sub, sinh, map_div₀] - -- Porting note: not nice - simp [← one_add_one_eq_two] - -@[simp] -theorem ofReal_sinh_ofReal_re (x : ℝ) : ((sinh x).re : ℂ) = sinh x := - conj_eq_iff_re.1 <| by rw [← sinh_conj, conj_ofReal] - -@[simp, norm_cast] -theorem ofReal_sinh (x : ℝ) : (Real.sinh x : ℂ) = sinh x := - ofReal_sinh_ofReal_re _ - -@[simp] -theorem sinh_ofReal_im (x : ℝ) : (sinh x).im = 0 := by rw [← ofReal_sinh_ofReal_re, ofReal_im] - -theorem sinh_ofReal_re (x : ℝ) : (sinh x).re = Real.sinh x := - rfl - -theorem cosh_conj : cosh (conj x) = conj (cosh x) := by - rw [cosh, ← RingHom.map_neg, exp_conj, exp_conj, ← RingHom.map_add, cosh, map_div₀] - -- Porting note: not nice - simp [← one_add_one_eq_two] - -theorem ofReal_cosh_ofReal_re (x : ℝ) : ((cosh x).re : ℂ) = cosh x := - conj_eq_iff_re.1 <| by rw [← cosh_conj, conj_ofReal] - -@[simp, norm_cast] -theorem ofReal_cosh (x : ℝ) : (Real.cosh x : ℂ) = cosh x := - ofReal_cosh_ofReal_re _ - -@[simp] -theorem cosh_ofReal_im (x : ℝ) : (cosh x).im = 0 := by rw [← ofReal_cosh_ofReal_re, ofReal_im] - -@[simp] -theorem cosh_ofReal_re (x : ℝ) : (cosh x).re = Real.cosh x := - rfl - -theorem tanh_eq_sinh_div_cosh : tanh x = sinh x / cosh x := - rfl - -@[simp] -theorem tanh_zero : tanh 0 = 0 := by simp [tanh] - -@[simp] -theorem tanh_neg : tanh (-x) = -tanh x := by simp [tanh, neg_div] - -theorem tanh_conj : tanh (conj x) = conj (tanh x) := by - rw [tanh, sinh_conj, cosh_conj, ← map_div₀, tanh] - -@[simp] -theorem ofReal_tanh_ofReal_re (x : ℝ) : ((tanh x).re : ℂ) = tanh x := - conj_eq_iff_re.1 <| by rw [← tanh_conj, conj_ofReal] - -@[simp, norm_cast] -theorem ofReal_tanh (x : ℝ) : (Real.tanh x : ℂ) = tanh x := - ofReal_tanh_ofReal_re _ - -@[simp] -theorem tanh_ofReal_im (x : ℝ) : (tanh x).im = 0 := by rw [← ofReal_tanh_ofReal_re, ofReal_im] - -theorem tanh_ofReal_re (x : ℝ) : (tanh x).re = Real.tanh x := - rfl - -@[simp] -theorem cosh_add_sinh : cosh x + sinh x = exp x := by - rw [← mul_right_inj' (two_ne_zero' ℂ), mul_add, two_cosh, two_sinh, add_add_sub_cancel, two_mul] - -@[simp] -theorem sinh_add_cosh : sinh x + cosh x = exp x := by rw [add_comm, cosh_add_sinh] - -@[simp] -theorem exp_sub_cosh : exp x - cosh x = sinh x := - sub_eq_iff_eq_add.2 (sinh_add_cosh x).symm - -@[simp] -theorem exp_sub_sinh : exp x - sinh x = cosh x := - sub_eq_iff_eq_add.2 (cosh_add_sinh x).symm - -@[simp] -theorem cosh_sub_sinh : cosh x - sinh x = exp (-x) := by - rw [← mul_right_inj' (two_ne_zero' ℂ), mul_sub, two_cosh, two_sinh, add_sub_sub_cancel, two_mul] - -@[simp] -theorem sinh_sub_cosh : sinh x - cosh x = -exp (-x) := by rw [← neg_sub, cosh_sub_sinh] - -@[simp] -theorem cosh_sq_sub_sinh_sq : cosh x ^ 2 - sinh x ^ 2 = 1 := by - rw [sq_sub_sq, cosh_add_sinh, cosh_sub_sinh, ← exp_add, add_neg_cancel, exp_zero] - -theorem cosh_sq : cosh x ^ 2 = sinh x ^ 2 + 1 := by - rw [← cosh_sq_sub_sinh_sq x] - ring - -theorem sinh_sq : sinh x ^ 2 = cosh x ^ 2 - 1 := by - rw [← cosh_sq_sub_sinh_sq x] - ring - -theorem cosh_two_mul : cosh (2 * x) = cosh x ^ 2 + sinh x ^ 2 := by rw [two_mul, cosh_add, sq, sq] - -theorem sinh_two_mul : sinh (2 * x) = 2 * sinh x * cosh x := by - rw [two_mul, sinh_add] - ring - -theorem cosh_three_mul : cosh (3 * x) = 4 * cosh x ^ 3 - 3 * cosh x := by - have h1 : x + 2 * x = 3 * x := by ring - rw [← h1, cosh_add x (2 * x)] - simp only [cosh_two_mul, sinh_two_mul] - have h2 : sinh x * (2 * sinh x * cosh x) = 2 * cosh x * sinh x ^ 2 := by ring - rw [h2, sinh_sq] - ring - -theorem sinh_three_mul : sinh (3 * x) = 4 * sinh x ^ 3 + 3 * sinh x := by - have h1 : x + 2 * x = 3 * x := by ring - rw [← h1, sinh_add x (2 * x)] - simp only [cosh_two_mul, sinh_two_mul] - have h2 : cosh x * (2 * sinh x * cosh x) = 2 * sinh x * cosh x ^ 2 := by ring - rw [h2, cosh_sq] - ring - -@[simp] -theorem sin_zero : sin 0 = 0 := by simp [sin] - -@[simp] -theorem sin_neg : sin (-x) = -sin x := by - simp [sin, sub_eq_add_neg, exp_neg, (neg_div _ _).symm, add_mul] - -theorem two_sin : 2 * sin x = (exp (-x * I) - exp (x * I)) * I := - mul_div_cancel₀ _ two_ne_zero - -theorem two_cos : 2 * cos x = exp (x * I) + exp (-x * I) := - mul_div_cancel₀ _ two_ne_zero - -theorem sinh_mul_I : sinh (x * I) = sin x * I := by - rw [← mul_right_inj' (two_ne_zero' ℂ), two_sinh, ← mul_assoc, two_sin, mul_assoc, I_mul_I, - mul_neg_one, neg_sub, neg_mul_eq_neg_mul] - -theorem cosh_mul_I : cosh (x * I) = cos x := by - rw [← mul_right_inj' (two_ne_zero' ℂ), two_cosh, two_cos, neg_mul_eq_neg_mul] - -theorem tanh_mul_I : tanh (x * I) = tan x * I := by - rw [tanh_eq_sinh_div_cosh, cosh_mul_I, sinh_mul_I, mul_div_right_comm, tan] - -theorem cos_mul_I : cos (x * I) = cosh x := by rw [← cosh_mul_I]; ring_nf; simp - -theorem sin_mul_I : sin (x * I) = sinh x * I := by - have h : I * sin (x * I) = -sinh x := by - rw [mul_comm, ← sinh_mul_I] - ring_nf - simp - rw [← neg_neg (sinh x), ← h] - apply Complex.ext <;> simp - -theorem tan_mul_I : tan (x * I) = tanh x * I := by - rw [tan, sin_mul_I, cos_mul_I, mul_div_right_comm, tanh_eq_sinh_div_cosh] - -theorem sin_add : sin (x + y) = sin x * cos y + cos x * sin y := by - rw [← mul_left_inj' I_ne_zero, ← sinh_mul_I, add_mul, add_mul, mul_right_comm, ← sinh_mul_I, - mul_assoc, ← sinh_mul_I, ← cosh_mul_I, ← cosh_mul_I, sinh_add] - -@[simp] -theorem cos_zero : cos 0 = 1 := by simp [cos] - -@[simp] -theorem cos_neg : cos (-x) = cos x := by simp [cos, sub_eq_add_neg, exp_neg, add_comm] - -theorem cos_add : cos (x + y) = cos x * cos y - sin x * sin y := by - rw [← cosh_mul_I, add_mul, cosh_add, cosh_mul_I, cosh_mul_I, sinh_mul_I, sinh_mul_I, - mul_mul_mul_comm, I_mul_I, mul_neg_one, sub_eq_add_neg] - -theorem sin_sub : sin (x - y) = sin x * cos y - cos x * sin y := by - simp [sub_eq_add_neg, sin_add, sin_neg, cos_neg] - -theorem cos_sub : cos (x - y) = cos x * cos y + sin x * sin y := by - simp [sub_eq_add_neg, cos_add, sin_neg, cos_neg] - -theorem sin_add_mul_I (x y : ℂ) : sin (x + y * I) = sin x * cosh y + cos x * sinh y * I := by - rw [sin_add, cos_mul_I, sin_mul_I, mul_assoc] - -theorem sin_eq (z : ℂ) : sin z = sin z.re * cosh z.im + cos z.re * sinh z.im * I := by - convert sin_add_mul_I z.re z.im; exact (re_add_im z).symm - -theorem cos_add_mul_I (x y : ℂ) : cos (x + y * I) = cos x * cosh y - sin x * sinh y * I := by - rw [cos_add, cos_mul_I, sin_mul_I, mul_assoc] - -theorem cos_eq (z : ℂ) : cos z = cos z.re * cosh z.im - sin z.re * sinh z.im * I := by - convert cos_add_mul_I z.re z.im; exact (re_add_im z).symm - -theorem sin_sub_sin : sin x - sin y = 2 * sin ((x - y) / 2) * cos ((x + y) / 2) := by - have s1 := sin_add ((x + y) / 2) ((x - y) / 2) - have s2 := sin_sub ((x + y) / 2) ((x - y) / 2) - rw [div_add_div_same, add_sub, add_right_comm, add_sub_cancel_right, add_self_div_two] at s1 - rw [div_sub_div_same, ← sub_add, add_sub_cancel_left, add_self_div_two] at s2 - rw [s1, s2] - ring - -theorem cos_sub_cos : cos x - cos y = -2 * sin ((x + y) / 2) * sin ((x - y) / 2) := by - have s1 := cos_add ((x + y) / 2) ((x - y) / 2) - have s2 := cos_sub ((x + y) / 2) ((x - y) / 2) - rw [div_add_div_same, add_sub, add_right_comm, add_sub_cancel_right, add_self_div_two] at s1 - rw [div_sub_div_same, ← sub_add, add_sub_cancel_left, add_self_div_two] at s2 - rw [s1, s2] - ring - -theorem sin_add_sin : sin x + sin y = 2 * sin ((x + y) / 2) * cos ((x - y) / 2) := by - simpa using sin_sub_sin x (-y) - -theorem cos_add_cos : cos x + cos y = 2 * cos ((x + y) / 2) * cos ((x - y) / 2) := by - calc - cos x + cos y = cos ((x + y) / 2 + (x - y) / 2) + cos ((x + y) / 2 - (x - y) / 2) := ?_ - _ = - cos ((x + y) / 2) * cos ((x - y) / 2) - sin ((x + y) / 2) * sin ((x - y) / 2) + - (cos ((x + y) / 2) * cos ((x - y) / 2) + sin ((x + y) / 2) * sin ((x - y) / 2)) := - ?_ - _ = 2 * cos ((x + y) / 2) * cos ((x - y) / 2) := ?_ - - · congr <;> field_simp - · rw [cos_add, cos_sub] - ring - -theorem sin_conj : sin (conj x) = conj (sin x) := by - rw [← mul_left_inj' I_ne_zero, ← sinh_mul_I, ← conj_neg_I, ← RingHom.map_mul, ← RingHom.map_mul, - sinh_conj, mul_neg, sinh_neg, sinh_mul_I, mul_neg] - -@[simp] -theorem ofReal_sin_ofReal_re (x : ℝ) : ((sin x).re : ℂ) = sin x := - conj_eq_iff_re.1 <| by rw [← sin_conj, conj_ofReal] - -@[simp, norm_cast] -theorem ofReal_sin (x : ℝ) : (Real.sin x : ℂ) = sin x := - ofReal_sin_ofReal_re _ - -@[simp] -theorem sin_ofReal_im (x : ℝ) : (sin x).im = 0 := by rw [← ofReal_sin_ofReal_re, ofReal_im] - -theorem sin_ofReal_re (x : ℝ) : (sin x).re = Real.sin x := - rfl - -theorem cos_conj : cos (conj x) = conj (cos x) := by - rw [← cosh_mul_I, ← conj_neg_I, ← RingHom.map_mul, ← cosh_mul_I, cosh_conj, mul_neg, cosh_neg] - -@[simp] -theorem ofReal_cos_ofReal_re (x : ℝ) : ((cos x).re : ℂ) = cos x := - conj_eq_iff_re.1 <| by rw [← cos_conj, conj_ofReal] - -@[simp, norm_cast] -theorem ofReal_cos (x : ℝ) : (Real.cos x : ℂ) = cos x := - ofReal_cos_ofReal_re _ - -@[simp] -theorem cos_ofReal_im (x : ℝ) : (cos x).im = 0 := by rw [← ofReal_cos_ofReal_re, ofReal_im] - -theorem cos_ofReal_re (x : ℝ) : (cos x).re = Real.cos x := - rfl - -@[simp] -theorem tan_zero : tan 0 = 0 := by simp [tan] - -theorem tan_eq_sin_div_cos : tan x = sin x / cos x := - rfl - -theorem cot_eq_cos_div_sin : cot x = cos x / sin x := - rfl - -theorem tan_mul_cos {x : ℂ} (hx : cos x ≠ 0) : tan x * cos x = sin x := by - rw [tan_eq_sin_div_cos, div_mul_cancel₀ _ hx] - -@[simp] -theorem tan_neg : tan (-x) = -tan x := by simp [tan, neg_div] - -theorem tan_conj : tan (conj x) = conj (tan x) := by rw [tan, sin_conj, cos_conj, ← map_div₀, tan] - -theorem cot_conj : cot (conj x) = conj (cot x) := by rw [cot, sin_conj, cos_conj, ← map_div₀, cot] - -@[simp] -theorem ofReal_tan_ofReal_re (x : ℝ) : ((tan x).re : ℂ) = tan x := - conj_eq_iff_re.1 <| by rw [← tan_conj, conj_ofReal] - -@[simp] -theorem ofReal_cot_ofReal_re (x : ℝ) : ((cot x).re : ℂ) = cot x := - conj_eq_iff_re.1 <| by rw [← cot_conj, conj_ofReal] - -@[simp, norm_cast] -theorem ofReal_tan (x : ℝ) : (Real.tan x : ℂ) = tan x := - ofReal_tan_ofReal_re _ - -@[simp, norm_cast] -theorem ofReal_cot (x : ℝ) : (Real.cot x : ℂ) = cot x := - ofReal_cot_ofReal_re _ - -@[simp] -theorem tan_ofReal_im (x : ℝ) : (tan x).im = 0 := by rw [← ofReal_tan_ofReal_re, ofReal_im] - -theorem tan_ofReal_re (x : ℝ) : (tan x).re = Real.tan x := - rfl - -theorem cos_add_sin_I : cos x + sin x * I = exp (x * I) := by - rw [← cosh_add_sinh, sinh_mul_I, cosh_mul_I] - -theorem cos_sub_sin_I : cos x - sin x * I = exp (-x * I) := by - rw [neg_mul, ← cosh_sub_sinh, sinh_mul_I, cosh_mul_I] - -@[simp] -theorem sin_sq_add_cos_sq : sin x ^ 2 + cos x ^ 2 = 1 := - Eq.trans (by rw [cosh_mul_I, sinh_mul_I, mul_pow, I_sq, mul_neg_one, sub_neg_eq_add, add_comm]) - (cosh_sq_sub_sinh_sq (x * I)) - -@[simp] -theorem cos_sq_add_sin_sq : cos x ^ 2 + sin x ^ 2 = 1 := by rw [add_comm, sin_sq_add_cos_sq] - -theorem cos_two_mul' : cos (2 * x) = cos x ^ 2 - sin x ^ 2 := by rw [two_mul, cos_add, ← sq, ← sq] - -theorem cos_two_mul : cos (2 * x) = 2 * cos x ^ 2 - 1 := by - rw [cos_two_mul', eq_sub_iff_add_eq.2 (sin_sq_add_cos_sq x), ← sub_add, sub_add_eq_add_sub, - two_mul] - -theorem sin_two_mul : sin (2 * x) = 2 * sin x * cos x := by - rw [two_mul, sin_add, two_mul, add_mul, mul_comm] - -theorem cos_sq : cos x ^ 2 = 1 / 2 + cos (2 * x) / 2 := by - simp [cos_two_mul, div_add_div_same, mul_div_cancel_left₀, two_ne_zero, -one_div] - -theorem cos_sq' : cos x ^ 2 = 1 - sin x ^ 2 := by rw [← sin_sq_add_cos_sq x, add_sub_cancel_left] - -theorem sin_sq : sin x ^ 2 = 1 - cos x ^ 2 := by rw [← sin_sq_add_cos_sq x, add_sub_cancel_right] - -theorem inv_one_add_tan_sq {x : ℂ} (hx : cos x ≠ 0) : (1 + tan x ^ 2)⁻¹ = cos x ^ 2 := by - rw [tan_eq_sin_div_cos, div_pow] - field_simp - -theorem tan_sq_div_one_add_tan_sq {x : ℂ} (hx : cos x ≠ 0) : - tan x ^ 2 / (1 + tan x ^ 2) = sin x ^ 2 := by - simp only [← tan_mul_cos hx, mul_pow, ← inv_one_add_tan_sq hx, div_eq_mul_inv, one_mul] - -theorem cos_three_mul : cos (3 * x) = 4 * cos x ^ 3 - 3 * cos x := by - have h1 : x + 2 * x = 3 * x := by ring - rw [← h1, cos_add x (2 * x)] - simp only [cos_two_mul, sin_two_mul, mul_add, mul_sub, mul_one, sq] - have h2 : 4 * cos x ^ 3 = 2 * cos x * cos x * cos x + 2 * cos x * cos x ^ 2 := by ring - rw [h2, cos_sq'] - ring - -theorem sin_three_mul : sin (3 * x) = 3 * sin x - 4 * sin x ^ 3 := by - have h1 : x + 2 * x = 3 * x := by ring - rw [← h1, sin_add x (2 * x)] - simp only [cos_two_mul, sin_two_mul, cos_sq'] - have h2 : cos x * (2 * sin x * cos x) = 2 * sin x * cos x ^ 2 := by ring - rw [h2, cos_sq'] - ring - -theorem exp_mul_I : exp (x * I) = cos x + sin x * I := - (cos_add_sin_I _).symm - -theorem exp_add_mul_I : exp (x + y * I) = exp x * (cos y + sin y * I) := by rw [exp_add, exp_mul_I] - -theorem exp_eq_exp_re_mul_sin_add_cos : exp x = exp x.re * (cos x.im + sin x.im * I) := by - rw [← exp_add_mul_I, re_add_im] - -theorem exp_re : (exp x).re = Real.exp x.re * Real.cos x.im := by - rw [exp_eq_exp_re_mul_sin_add_cos] - simp [exp_ofReal_re, cos_ofReal_re] - -theorem exp_im : (exp x).im = Real.exp x.re * Real.sin x.im := by - rw [exp_eq_exp_re_mul_sin_add_cos] - simp [exp_ofReal_re, sin_ofReal_re] - -@[simp] -theorem exp_ofReal_mul_I_re (x : ℝ) : (exp (x * I)).re = Real.cos x := by - simp [exp_mul_I, cos_ofReal_re] - -@[simp] -theorem exp_ofReal_mul_I_im (x : ℝ) : (exp (x * I)).im = Real.sin x := by - simp [exp_mul_I, sin_ofReal_re] - -/-- **De Moivre's formula** -/ -theorem cos_add_sin_mul_I_pow (n : ℕ) (z : ℂ) : - (cos z + sin z * I) ^ n = cos (↑n * z) + sin (↑n * z) * I := by - rw [← exp_mul_I, ← exp_mul_I, ← exp_nat_mul, mul_assoc] - end Complex namespace Real @@ -716,241 +225,6 @@ nonrec theorem exp_neg : exp (-x) = (exp x)⁻¹ := theorem exp_sub : exp (x - y) = exp x / exp y := by simp [sub_eq_add_neg, exp_add, exp_neg, div_eq_mul_inv] -@[simp] -theorem sin_zero : sin 0 = 0 := by simp [sin] - -@[simp] -theorem sin_neg : sin (-x) = -sin x := by simp [sin, exp_neg, (neg_div _ _).symm, add_mul] - -nonrec theorem sin_add : sin (x + y) = sin x * cos y + cos x * sin y := - ofReal_injective <| by simp [sin_add] - -@[simp] -theorem cos_zero : cos 0 = 1 := by simp [cos] - -@[simp] -theorem cos_neg : cos (-x) = cos x := by simp [cos, exp_neg] - -@[simp] -theorem cos_abs : cos |x| = cos x := by - cases le_total x 0 <;> simp only [*, _root_.abs_of_nonneg, abs_of_nonpos, cos_neg] - -nonrec theorem cos_add : cos (x + y) = cos x * cos y - sin x * sin y := - ofReal_injective <| by simp [cos_add] - -theorem sin_sub : sin (x - y) = sin x * cos y - cos x * sin y := by - simp [sub_eq_add_neg, sin_add, sin_neg, cos_neg] - -theorem cos_sub : cos (x - y) = cos x * cos y + sin x * sin y := by - simp [sub_eq_add_neg, cos_add, sin_neg, cos_neg] - -nonrec theorem sin_sub_sin : sin x - sin y = 2 * sin ((x - y) / 2) * cos ((x + y) / 2) := - ofReal_injective <| by simp [sin_sub_sin] - -nonrec theorem cos_sub_cos : cos x - cos y = -2 * sin ((x + y) / 2) * sin ((x - y) / 2) := - ofReal_injective <| by simp [cos_sub_cos] - -nonrec theorem cos_add_cos : cos x + cos y = 2 * cos ((x + y) / 2) * cos ((x - y) / 2) := - ofReal_injective <| by simp [cos_add_cos] - -theorem two_mul_sin_mul_sin (x y : ℝ) : 2 * sin x * sin y = cos (x - y) - cos (x + y) := by - simp [cos_add, cos_sub] - ring - -theorem two_mul_cos_mul_cos (x y : ℝ) : 2 * cos x * cos y = cos (x - y) + cos (x + y) := by - simp [cos_add, cos_sub] - ring - -theorem two_mul_sin_mul_cos (x y : ℝ) : 2 * sin x * cos y = sin (x - y) + sin (x + y) := by - simp [sin_add, sin_sub] - ring - -nonrec theorem tan_eq_sin_div_cos : tan x = sin x / cos x := - ofReal_injective <| by simp only [ofReal_tan, tan_eq_sin_div_cos, ofReal_div, ofReal_sin, - ofReal_cos] - -nonrec theorem cot_eq_cos_div_sin : cot x = cos x / sin x := - ofReal_injective <| by simp [cot_eq_cos_div_sin] - -theorem tan_mul_cos {x : ℝ} (hx : cos x ≠ 0) : tan x * cos x = sin x := by - rw [tan_eq_sin_div_cos, div_mul_cancel₀ _ hx] - -@[simp] -theorem tan_zero : tan 0 = 0 := by simp [tan] - -@[simp] -theorem tan_neg : tan (-x) = -tan x := by simp [tan, neg_div] - -@[simp] -nonrec theorem sin_sq_add_cos_sq : sin x ^ 2 + cos x ^ 2 = 1 := - ofReal_injective (by simp [sin_sq_add_cos_sq]) - -@[simp] -theorem cos_sq_add_sin_sq : cos x ^ 2 + sin x ^ 2 = 1 := by rw [add_comm, sin_sq_add_cos_sq] - -theorem sin_sq_le_one : sin x ^ 2 ≤ 1 := by - rw [← sin_sq_add_cos_sq x]; exact le_add_of_nonneg_right (sq_nonneg _) - -theorem cos_sq_le_one : cos x ^ 2 ≤ 1 := by - rw [← sin_sq_add_cos_sq x]; exact le_add_of_nonneg_left (sq_nonneg _) - -theorem abs_sin_le_one : |sin x| ≤ 1 := - abs_le_one_iff_mul_self_le_one.2 <| by simp only [← sq, sin_sq_le_one] - -theorem abs_cos_le_one : |cos x| ≤ 1 := - abs_le_one_iff_mul_self_le_one.2 <| by simp only [← sq, cos_sq_le_one] - -theorem sin_le_one : sin x ≤ 1 := - (abs_le.1 (abs_sin_le_one _)).2 - -theorem cos_le_one : cos x ≤ 1 := - (abs_le.1 (abs_cos_le_one _)).2 - -theorem neg_one_le_sin : -1 ≤ sin x := - (abs_le.1 (abs_sin_le_one _)).1 - -theorem neg_one_le_cos : -1 ≤ cos x := - (abs_le.1 (abs_cos_le_one _)).1 - -nonrec theorem cos_two_mul : cos (2 * x) = 2 * cos x ^ 2 - 1 := - ofReal_injective <| by simp [cos_two_mul] - -nonrec theorem cos_two_mul' : cos (2 * x) = cos x ^ 2 - sin x ^ 2 := - ofReal_injective <| by simp [cos_two_mul'] - -nonrec theorem sin_two_mul : sin (2 * x) = 2 * sin x * cos x := - ofReal_injective <| by simp [sin_two_mul] - -nonrec theorem cos_sq : cos x ^ 2 = 1 / 2 + cos (2 * x) / 2 := - ofReal_injective <| by simp [cos_sq] - -theorem cos_sq' : cos x ^ 2 = 1 - sin x ^ 2 := by rw [← sin_sq_add_cos_sq x, add_sub_cancel_left] - -theorem sin_sq : sin x ^ 2 = 1 - cos x ^ 2 := - eq_sub_iff_add_eq.2 <| sin_sq_add_cos_sq _ - -lemma sin_sq_eq_half_sub : sin x ^ 2 = 1 / 2 - cos (2 * x) / 2 := by - rw [sin_sq, cos_sq, ← sub_sub, sub_half] - -theorem abs_sin_eq_sqrt_one_sub_cos_sq (x : ℝ) : |sin x| = √(1 - cos x ^ 2) := by - rw [← sin_sq, sqrt_sq_eq_abs] - -theorem abs_cos_eq_sqrt_one_sub_sin_sq (x : ℝ) : |cos x| = √(1 - sin x ^ 2) := by - rw [← cos_sq', sqrt_sq_eq_abs] - -theorem inv_one_add_tan_sq {x : ℝ} (hx : cos x ≠ 0) : (1 + tan x ^ 2)⁻¹ = cos x ^ 2 := - have : Complex.cos x ≠ 0 := mt (congr_arg re) hx - ofReal_inj.1 <| by simpa using Complex.inv_one_add_tan_sq this - -theorem tan_sq_div_one_add_tan_sq {x : ℝ} (hx : cos x ≠ 0) : - tan x ^ 2 / (1 + tan x ^ 2) = sin x ^ 2 := by - simp only [← tan_mul_cos hx, mul_pow, ← inv_one_add_tan_sq hx, div_eq_mul_inv, one_mul] - -theorem inv_sqrt_one_add_tan_sq {x : ℝ} (hx : 0 < cos x) : (√(1 + tan x ^ 2))⁻¹ = cos x := by - rw [← sqrt_sq hx.le, ← sqrt_inv, inv_one_add_tan_sq hx.ne'] - -theorem tan_div_sqrt_one_add_tan_sq {x : ℝ} (hx : 0 < cos x) : - tan x / √(1 + tan x ^ 2) = sin x := by - rw [← tan_mul_cos hx.ne', ← inv_sqrt_one_add_tan_sq hx, div_eq_mul_inv] - -nonrec theorem cos_three_mul : cos (3 * x) = 4 * cos x ^ 3 - 3 * cos x := by - rw [← ofReal_inj]; simp [cos_three_mul] - -nonrec theorem sin_three_mul : sin (3 * x) = 3 * sin x - 4 * sin x ^ 3 := by - rw [← ofReal_inj]; simp [sin_three_mul] - -/-- The definition of `sinh` in terms of `exp`. -/ -nonrec theorem sinh_eq (x : ℝ) : sinh x = (exp x - exp (-x)) / 2 := - ofReal_injective <| by simp [Complex.sinh] - -@[simp] -theorem sinh_zero : sinh 0 = 0 := by simp [sinh] - -@[simp] -theorem sinh_neg : sinh (-x) = -sinh x := by simp [sinh, exp_neg, (neg_div _ _).symm, add_mul] - -nonrec theorem sinh_add : sinh (x + y) = sinh x * cosh y + cosh x * sinh y := by - rw [← ofReal_inj]; simp [sinh_add] - -/-- The definition of `cosh` in terms of `exp`. -/ -theorem cosh_eq (x : ℝ) : cosh x = (exp x + exp (-x)) / 2 := - eq_div_of_mul_eq two_ne_zero <| by - rw [cosh, exp, exp, Complex.ofReal_neg, Complex.cosh, mul_two, ← Complex.add_re, ← mul_two, - div_mul_cancel₀ _ (two_ne_zero' ℂ), Complex.add_re] - -@[simp] -theorem cosh_zero : cosh 0 = 1 := by simp [cosh] - -@[simp] -theorem cosh_neg : cosh (-x) = cosh x := - ofReal_inj.1 <| by simp - -@[simp] -theorem cosh_abs : cosh |x| = cosh x := by - cases le_total x 0 <;> simp [*, _root_.abs_of_nonneg, abs_of_nonpos] - -nonrec theorem cosh_add : cosh (x + y) = cosh x * cosh y + sinh x * sinh y := by - rw [← ofReal_inj]; simp [cosh_add] - -theorem sinh_sub : sinh (x - y) = sinh x * cosh y - cosh x * sinh y := by - simp [sub_eq_add_neg, sinh_add, sinh_neg, cosh_neg] - -theorem cosh_sub : cosh (x - y) = cosh x * cosh y - sinh x * sinh y := by - simp [sub_eq_add_neg, cosh_add, sinh_neg, cosh_neg] - -nonrec theorem tanh_eq_sinh_div_cosh : tanh x = sinh x / cosh x := - ofReal_inj.1 <| by simp [tanh_eq_sinh_div_cosh] - -@[simp] -theorem tanh_zero : tanh 0 = 0 := by simp [tanh] - -@[simp] -theorem tanh_neg : tanh (-x) = -tanh x := by simp [tanh, neg_div] - -@[simp] -theorem cosh_add_sinh : cosh x + sinh x = exp x := by rw [← ofReal_inj]; simp - -@[simp] -theorem sinh_add_cosh : sinh x + cosh x = exp x := by rw [add_comm, cosh_add_sinh] - -@[simp] -theorem exp_sub_cosh : exp x - cosh x = sinh x := - sub_eq_iff_eq_add.2 (sinh_add_cosh x).symm - -@[simp] -theorem exp_sub_sinh : exp x - sinh x = cosh x := - sub_eq_iff_eq_add.2 (cosh_add_sinh x).symm - -@[simp] -theorem cosh_sub_sinh : cosh x - sinh x = exp (-x) := by - rw [← ofReal_inj] - simp - -@[simp] -theorem sinh_sub_cosh : sinh x - cosh x = -exp (-x) := by rw [← neg_sub, cosh_sub_sinh] - -@[simp] -theorem cosh_sq_sub_sinh_sq (x : ℝ) : cosh x ^ 2 - sinh x ^ 2 = 1 := by rw [← ofReal_inj]; simp - -nonrec theorem cosh_sq : cosh x ^ 2 = sinh x ^ 2 + 1 := by rw [← ofReal_inj]; simp [cosh_sq] - -theorem cosh_sq' : cosh x ^ 2 = 1 + sinh x ^ 2 := - (cosh_sq x).trans (add_comm _ _) - -nonrec theorem sinh_sq : sinh x ^ 2 = cosh x ^ 2 - 1 := by rw [← ofReal_inj]; simp [sinh_sq] - -nonrec theorem cosh_two_mul : cosh (2 * x) = cosh x ^ 2 + sinh x ^ 2 := by - rw [← ofReal_inj]; simp [cosh_two_mul] - -nonrec theorem sinh_two_mul : sinh (2 * x) = 2 * sinh x * cosh x := by - rw [← ofReal_inj]; simp [sinh_two_mul] - -nonrec theorem cosh_three_mul : cosh (3 * x) = 4 * cosh x ^ 3 - 3 * cosh x := by - rw [← ofReal_inj]; simp [cosh_three_mul] - -nonrec theorem sinh_three_mul : sinh (3 * x) = 4 * sinh x ^ 3 + 3 * sinh x := by - rw [← ofReal_inj]; simp [sinh_three_mul] - open IsAbsoluteValue Nat theorem sum_le_exp_of_nonneg {x : ℝ} (hx : 0 ≤ x) (n : ℕ) : ∑ i ∈ range n, x ^ i / i ! ≤ exp x := @@ -1055,13 +329,6 @@ theorem exp_le_one_iff {x : ℝ} : exp x ≤ 1 ↔ x ≤ 0 := theorem one_le_exp_iff {x : ℝ} : 1 ≤ exp x ↔ 0 ≤ x := exp_zero ▸ exp_le_exp -/-- `Real.cosh` is always positive -/ -theorem cosh_pos (x : ℝ) : 0 < Real.cosh x := - (cosh_eq x).symm ▸ half_pos (add_pos (exp_pos x) (exp_pos (-x))) - -theorem sinh_lt_cosh : sinh x < cosh x := - lt_of_pow_lt_pow_left₀ 2 (cosh_pos _).le <| (cosh_sq x).symm ▸ lt_add_one _ - end Real namespace Complex @@ -1334,125 +601,6 @@ theorem exp_1_approx_succ_eq {n} {a₁ b₁ : ℝ} {m : ℕ} (en : n + 1 = m) {r theorem exp_approx_start (x a b : ℝ) (h : |exp x - expNear 0 x a| ≤ |x| ^ 0 / Nat.factorial 0 * b) : |exp x - a| ≤ b := by simpa using h -theorem cos_bound {x : ℝ} (hx : |x| ≤ 1) : |cos x - (1 - x ^ 2 / 2)| ≤ |x| ^ 4 * (5 / 96) := - calc - |cos x - (1 - x ^ 2 / 2)| = Complex.abs (Complex.cos x - (1 - (x : ℂ) ^ 2 / 2)) := by - rw [← abs_ofReal]; simp - _ = Complex.abs ((Complex.exp (x * I) + Complex.exp (-x * I) - (2 - (x : ℂ) ^ 2)) / 2) := by - simp [Complex.cos, sub_div, add_div, neg_div, div_self (two_ne_zero' ℂ)] - _ = abs - (((Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) + - (Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial)) / 2) := - (congr_arg Complex.abs - (congr_arg (fun x : ℂ => x / 2) - (by - simp only [sum_range_succ, neg_mul, pow_succ, pow_zero, mul_one, range_zero, sum_empty, - Nat.factorial, Nat.cast_one, ne_eq, one_ne_zero, not_false_eq_true, div_self, - zero_add, div_one, Nat.mul_one, Nat.cast_succ, Nat.cast_mul, Nat.cast_ofNat, mul_neg, - neg_neg] - apply Complex.ext <;> simp [div_eq_mul_inv, normSq] <;> ring_nf - ))) - _ ≤ abs ((Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) / 2) + - abs ((Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) / 2) := by - rw [add_div]; exact Complex.abs.add_le _ _ - _ = abs (Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) / 2 + - abs (Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) / 2 := by - simp [map_div₀] - _ ≤ Complex.abs (x * I) ^ 4 * (Nat.succ 4 * ((Nat.factorial 4) * (4 : ℕ) : ℝ)⁻¹) / 2 + - Complex.abs (-x * I) ^ 4 * (Nat.succ 4 * ((Nat.factorial 4) * (4 : ℕ) : ℝ)⁻¹) / 2 := by - gcongr - · exact Complex.exp_bound (by simpa) (by decide) - · exact Complex.exp_bound (by simpa) (by decide) - _ ≤ |x| ^ 4 * (5 / 96) := by norm_num [Nat.factorial] - -theorem sin_bound {x : ℝ} (hx : |x| ≤ 1) : |sin x - (x - x ^ 3 / 6)| ≤ |x| ^ 4 * (5 / 96) := - calc - |sin x - (x - x ^ 3 / 6)| = Complex.abs (Complex.sin x - (x - x ^ 3 / 6 : ℝ)) := by - rw [← abs_ofReal]; simp - _ = Complex.abs (((Complex.exp (-x * I) - Complex.exp (x * I)) * I - - (2 * x - x ^ 3 / 3 : ℝ)) / 2) := by - simp [Complex.sin, sub_div, add_div, neg_div, mul_div_cancel_left₀ _ (two_ne_zero' ℂ), - div_div, show (3 : ℂ) * 2 = 6 by norm_num] - _ = Complex.abs (((Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) - - (Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial)) * I / 2) := - (congr_arg Complex.abs - (congr_arg (fun x : ℂ => x / 2) - (by - simp only [sum_range_succ, neg_mul, pow_succ, pow_zero, mul_one, ofReal_sub, ofReal_mul, - ofReal_ofNat, ofReal_div, range_zero, sum_empty, Nat.factorial, Nat.cast_one, ne_eq, - one_ne_zero, not_false_eq_true, div_self, zero_add, div_one, mul_neg, neg_neg, - Nat.mul_one, Nat.cast_succ, Nat.cast_mul, Nat.cast_ofNat] - apply Complex.ext <;> simp [div_eq_mul_inv, normSq]; ring))) - _ ≤ abs ((Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) * I / 2) + - abs (-((Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) * I) / 2) := by - rw [sub_mul, sub_eq_add_neg, add_div]; exact Complex.abs.add_le _ _ - _ = abs (Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) / 2 + - abs (Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) / 2 := by - simp [add_comm, map_div₀] - _ ≤ Complex.abs (x * I) ^ 4 * (Nat.succ 4 * (Nat.factorial 4 * (4 : ℕ) : ℝ)⁻¹) / 2 + - Complex.abs (-x * I) ^ 4 * (Nat.succ 4 * (Nat.factorial 4 * (4 : ℕ) : ℝ)⁻¹) / 2 := by - gcongr - · exact Complex.exp_bound (by simpa) (by decide) - · exact Complex.exp_bound (by simpa) (by decide) - _ ≤ |x| ^ 4 * (5 / 96) := by norm_num [Nat.factorial] - -theorem cos_pos_of_le_one {x : ℝ} (hx : |x| ≤ 1) : 0 < cos x := - calc 0 < 1 - x ^ 2 / 2 - |x| ^ 4 * (5 / 96) := - sub_pos.2 <| - lt_sub_iff_add_lt.2 - (calc - |x| ^ 4 * (5 / 96) + x ^ 2 / 2 ≤ 1 * (5 / 96) + 1 / 2 := by - gcongr - · exact pow_le_one₀ (abs_nonneg _) hx - · rw [sq, ← abs_mul_self, abs_mul] - exact mul_le_one₀ hx (abs_nonneg _) hx - _ < 1 := by norm_num) - _ ≤ cos x := sub_le_comm.1 (abs_sub_le_iff.1 (cos_bound hx)).2 - -theorem sin_pos_of_pos_of_le_one {x : ℝ} (hx0 : 0 < x) (hx : x ≤ 1) : 0 < sin x := - calc 0 < x - x ^ 3 / 6 - |x| ^ 4 * (5 / 96) := - sub_pos.2 <| lt_sub_iff_add_lt.2 - (calc - |x| ^ 4 * (5 / 96) + x ^ 3 / 6 ≤ x * (5 / 96) + x / 6 := by - gcongr - · calc - |x| ^ 4 ≤ |x| ^ 1 := - pow_le_pow_of_le_one (abs_nonneg _) - (by rwa [_root_.abs_of_nonneg (le_of_lt hx0)]) (by decide) - _ = x := by simp [_root_.abs_of_nonneg (le_of_lt hx0)] - · calc - x ^ 3 ≤ x ^ 1 := pow_le_pow_of_le_one (le_of_lt hx0) hx (by decide) - _ = x := pow_one _ - _ < x := by linarith) - _ ≤ sin x := - sub_le_comm.1 (abs_sub_le_iff.1 (sin_bound (by rwa [_root_.abs_of_nonneg (le_of_lt hx0)]))).2 - -theorem sin_pos_of_pos_of_le_two {x : ℝ} (hx0 : 0 < x) (hx : x ≤ 2) : 0 < sin x := - have : x / 2 ≤ 1 := (div_le_iff₀ (by norm_num)).mpr (by simpa) - calc - 0 < 2 * sin (x / 2) * cos (x / 2) := - mul_pos (mul_pos (by norm_num) (sin_pos_of_pos_of_le_one (half_pos hx0) this)) - (cos_pos_of_le_one (by rwa [_root_.abs_of_nonneg (le_of_lt (half_pos hx0))])) - _ = sin x := by rw [← sin_two_mul, two_mul, add_halves] - -theorem cos_one_le : cos 1 ≤ 2 / 3 := - calc - cos 1 ≤ |(1 : ℝ)| ^ 4 * (5 / 96) + (1 - 1 ^ 2 / 2) := - sub_le_iff_le_add.1 (abs_sub_le_iff.1 (cos_bound (by simp))).1 - _ ≤ 2 / 3 := by norm_num - -theorem cos_one_pos : 0 < cos 1 := - cos_pos_of_le_one (le_of_eq abs_one) - -theorem cos_two_neg : cos 2 < 0 := - calc cos 2 = cos (2 * 1) := congr_arg cos (mul_one _).symm - _ = _ := Real.cos_two_mul 1 - _ ≤ 2 * (2 / 3) ^ 2 - 1 := by - gcongr - · exact cos_one_pos.le - · apply cos_one_le - _ < 0 := by norm_num - theorem exp_bound_div_one_sub_of_interval' {x : ℝ} (h1 : 0 < x) (h2 : x < 1) : Real.exp x < 1 / (1 - x) := by have H : 0 < 1 - (1 + x + x ^ 2) * (1 - x) := calc @@ -1527,41 +675,13 @@ def evalExp : PositivityExt where eval {u α} _ _ e := do pure (.positive q(Real.exp_pos $a)) | _, _, _ => throwError "not Real.exp" -/-- Extension for the `positivity` tactic: `Real.cosh` is always positive. -/ -@[positivity Real.cosh _] -def evalCosh : PositivityExt where eval {u α} _ _ e := do - match u, α, e with - | 0, ~q(ℝ), ~q(Real.cosh $a) => - assertInstancesCommute - return .positive q(Real.cosh_pos $a) - | _, _, _ => throwError "not Real.cosh" - -example (x : ℝ) : 0 < x.cosh := by positivity - end Mathlib.Meta.Positivity namespace Complex -@[simp] -theorem abs_cos_add_sin_mul_I (x : ℝ) : abs (cos x + sin x * I) = 1 := by - have := Real.sin_sq_add_cos_sq x - simp_all [add_comm, abs, normSq, sq, sin_ofReal_re, cos_ofReal_re, mul_re] - @[simp] theorem abs_exp_ofReal (x : ℝ) : abs (exp x) = Real.exp x := by rw [← ofReal_exp] exact abs_of_nonneg (le_of_lt (Real.exp_pos _)) -@[simp] -theorem abs_exp_ofReal_mul_I (x : ℝ) : abs (exp (x * I)) = 1 := by - rw [exp_mul_I, abs_cos_add_sin_mul_I] - -theorem abs_exp (z : ℂ) : abs (exp z) = Real.exp z.re := by - rw [exp_eq_exp_re_mul_sin_add_cos, map_mul, abs_exp_ofReal, abs_cos_add_sin_mul_I, mul_one] - -theorem abs_exp_eq_iff_re_eq {x y : ℂ} : abs (exp x) = abs (exp y) ↔ x.re = y.re := by - rw [abs_exp, abs_exp, Real.exp_eq_exp] - end Complex - -set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/Complex/Trigonometric.lean b/Mathlib/Data/Complex/Trigonometric.lean new file mode 100644 index 0000000000000..ea6b53a511038 --- /dev/null +++ b/Mathlib/Data/Complex/Trigonometric.lean @@ -0,0 +1,951 @@ +/- +Copyright (c) 2018 Chris Hughes. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Hughes, Abhimanyu Pallavi Sudhir +-/ +import Mathlib.Data.Complex.Exponential + +/-! +# Trigonometric and hyperbolic trigonometric functions + +This file contains the definitions of the sine, cosine, tangent, +hyperbolic sine, hyperbolic cosine, and hyperbolic tangent functions. + +-/ + +open CauSeq Finset IsAbsoluteValue +open scoped ComplexConjugate + +namespace Complex + +noncomputable section + +/-- The complex sine function, defined via `exp` -/ +@[pp_nodot] +def sin (z : ℂ) : ℂ := + (exp (-z * I) - exp (z * I)) * I / 2 + +/-- The complex cosine function, defined via `exp` -/ +@[pp_nodot] +def cos (z : ℂ) : ℂ := + (exp (z * I) + exp (-z * I)) / 2 + +/-- The complex tangent function, defined as `sin z / cos z` -/ +@[pp_nodot] +def tan (z : ℂ) : ℂ := + sin z / cos z + +/-- The complex cotangent function, defined as `cos z / sin z` -/ +def cot (z : ℂ) : ℂ := + cos z / sin z + +/-- The complex hyperbolic sine function, defined via `exp` -/ +@[pp_nodot] +def sinh (z : ℂ) : ℂ := + (exp z - exp (-z)) / 2 + +/-- The complex hyperbolic cosine function, defined via `exp` -/ +@[pp_nodot] +def cosh (z : ℂ) : ℂ := + (exp z + exp (-z)) / 2 + +/-- The complex hyperbolic tangent function, defined as `sinh z / cosh z` -/ +@[pp_nodot] +def tanh (z : ℂ) : ℂ := + sinh z / cosh z + +end + +end Complex + +namespace Real + +open Complex + +noncomputable section + +/-- The real sine function, defined as the real part of the complex sine -/ +@[pp_nodot] +nonrec def sin (x : ℝ) : ℝ := + (sin x).re + +/-- The real cosine function, defined as the real part of the complex cosine -/ +@[pp_nodot] +nonrec def cos (x : ℝ) : ℝ := + (cos x).re + +/-- The real tangent function, defined as the real part of the complex tangent -/ +@[pp_nodot] +nonrec def tan (x : ℝ) : ℝ := + (tan x).re + +/-- The real cotangent function, defined as the real part of the complex cotangent -/ +nonrec def cot (x : ℝ) : ℝ := + (cot x).re + +/-- The real hypebolic sine function, defined as the real part of the complex hyperbolic sine -/ +@[pp_nodot] +nonrec def sinh (x : ℝ) : ℝ := + (sinh x).re + +/-- The real hypebolic cosine function, defined as the real part of the complex hyperbolic cosine -/ +@[pp_nodot] +nonrec def cosh (x : ℝ) : ℝ := + (cosh x).re + +/-- The real hypebolic tangent function, defined as the real part of +the complex hyperbolic tangent -/ +@[pp_nodot] +nonrec def tanh (x : ℝ) : ℝ := + (tanh x).re + +end + +end Real + +namespace Complex + +variable (x y : ℂ) + +theorem two_sinh : 2 * sinh x = exp x - exp (-x) := + mul_div_cancel₀ _ two_ne_zero + +theorem two_cosh : 2 * cosh x = exp x + exp (-x) := + mul_div_cancel₀ _ two_ne_zero + +@[simp] +theorem sinh_zero : sinh 0 = 0 := by simp [sinh] + +@[simp] +theorem sinh_neg : sinh (-x) = -sinh x := by simp [sinh, exp_neg, (neg_div _ _).symm, add_mul] + +private theorem sinh_add_aux {a b c d : ℂ} : + (a - b) * (c + d) + (a + b) * (c - d) = 2 * (a * c - b * d) := by ring + +theorem sinh_add : sinh (x + y) = sinh x * cosh y + cosh x * sinh y := by + rw [← mul_right_inj' (two_ne_zero' ℂ), two_sinh, exp_add, neg_add, exp_add, eq_comm, mul_add, ← + mul_assoc, two_sinh, mul_left_comm, two_sinh, ← mul_right_inj' (two_ne_zero' ℂ), mul_add, + mul_left_comm, two_cosh, ← mul_assoc, two_cosh] + exact sinh_add_aux + +@[simp] +theorem cosh_zero : cosh 0 = 1 := by simp [cosh] + +@[simp] +theorem cosh_neg : cosh (-x) = cosh x := by simp [add_comm, cosh, exp_neg] + +private theorem cosh_add_aux {a b c d : ℂ} : + (a + b) * (c + d) + (a - b) * (c - d) = 2 * (a * c + b * d) := by ring + +theorem cosh_add : cosh (x + y) = cosh x * cosh y + sinh x * sinh y := by + rw [← mul_right_inj' (two_ne_zero' ℂ), two_cosh, exp_add, neg_add, exp_add, eq_comm, mul_add, ← + mul_assoc, two_cosh, ← mul_assoc, two_sinh, ← mul_right_inj' (two_ne_zero' ℂ), mul_add, + mul_left_comm, two_cosh, mul_left_comm, two_sinh] + exact cosh_add_aux + +theorem sinh_sub : sinh (x - y) = sinh x * cosh y - cosh x * sinh y := by + simp [sub_eq_add_neg, sinh_add, sinh_neg, cosh_neg] + +theorem cosh_sub : cosh (x - y) = cosh x * cosh y - sinh x * sinh y := by + simp [sub_eq_add_neg, cosh_add, sinh_neg, cosh_neg] + +theorem sinh_conj : sinh (conj x) = conj (sinh x) := by + rw [sinh, ← RingHom.map_neg, exp_conj, exp_conj, ← RingHom.map_sub, sinh, map_div₀] + -- Porting note: not nice + simp [← one_add_one_eq_two] + +@[simp] +theorem ofReal_sinh_ofReal_re (x : ℝ) : ((sinh x).re : ℂ) = sinh x := + conj_eq_iff_re.1 <| by rw [← sinh_conj, conj_ofReal] + +@[simp, norm_cast] +theorem ofReal_sinh (x : ℝ) : (Real.sinh x : ℂ) = sinh x := + ofReal_sinh_ofReal_re _ + +@[simp] +theorem sinh_ofReal_im (x : ℝ) : (sinh x).im = 0 := by rw [← ofReal_sinh_ofReal_re, ofReal_im] + +theorem sinh_ofReal_re (x : ℝ) : (sinh x).re = Real.sinh x := + rfl + +theorem cosh_conj : cosh (conj x) = conj (cosh x) := by + rw [cosh, ← RingHom.map_neg, exp_conj, exp_conj, ← RingHom.map_add, cosh, map_div₀] + -- Porting note: not nice + simp [← one_add_one_eq_two] + +theorem ofReal_cosh_ofReal_re (x : ℝ) : ((cosh x).re : ℂ) = cosh x := + conj_eq_iff_re.1 <| by rw [← cosh_conj, conj_ofReal] + +@[simp, norm_cast] +theorem ofReal_cosh (x : ℝ) : (Real.cosh x : ℂ) = cosh x := + ofReal_cosh_ofReal_re _ + +@[simp] +theorem cosh_ofReal_im (x : ℝ) : (cosh x).im = 0 := by rw [← ofReal_cosh_ofReal_re, ofReal_im] + +@[simp] +theorem cosh_ofReal_re (x : ℝ) : (cosh x).re = Real.cosh x := + rfl + +theorem tanh_eq_sinh_div_cosh : tanh x = sinh x / cosh x := + rfl + +@[simp] +theorem tanh_zero : tanh 0 = 0 := by simp [tanh] + +@[simp] +theorem tanh_neg : tanh (-x) = -tanh x := by simp [tanh, neg_div] + +theorem tanh_conj : tanh (conj x) = conj (tanh x) := by + rw [tanh, sinh_conj, cosh_conj, ← map_div₀, tanh] + +@[simp] +theorem ofReal_tanh_ofReal_re (x : ℝ) : ((tanh x).re : ℂ) = tanh x := + conj_eq_iff_re.1 <| by rw [← tanh_conj, conj_ofReal] + +@[simp, norm_cast] +theorem ofReal_tanh (x : ℝ) : (Real.tanh x : ℂ) = tanh x := + ofReal_tanh_ofReal_re _ + +@[simp] +theorem tanh_ofReal_im (x : ℝ) : (tanh x).im = 0 := by rw [← ofReal_tanh_ofReal_re, ofReal_im] + +theorem tanh_ofReal_re (x : ℝ) : (tanh x).re = Real.tanh x := + rfl + +@[simp] +theorem cosh_add_sinh : cosh x + sinh x = exp x := by + rw [← mul_right_inj' (two_ne_zero' ℂ), mul_add, two_cosh, two_sinh, add_add_sub_cancel, two_mul] + +@[simp] +theorem sinh_add_cosh : sinh x + cosh x = exp x := by rw [add_comm, cosh_add_sinh] + +@[simp] +theorem exp_sub_cosh : exp x - cosh x = sinh x := + sub_eq_iff_eq_add.2 (sinh_add_cosh x).symm + +@[simp] +theorem exp_sub_sinh : exp x - sinh x = cosh x := + sub_eq_iff_eq_add.2 (cosh_add_sinh x).symm + +@[simp] +theorem cosh_sub_sinh : cosh x - sinh x = exp (-x) := by + rw [← mul_right_inj' (two_ne_zero' ℂ), mul_sub, two_cosh, two_sinh, add_sub_sub_cancel, two_mul] + +@[simp] +theorem sinh_sub_cosh : sinh x - cosh x = -exp (-x) := by rw [← neg_sub, cosh_sub_sinh] + +@[simp] +theorem cosh_sq_sub_sinh_sq : cosh x ^ 2 - sinh x ^ 2 = 1 := by + rw [sq_sub_sq, cosh_add_sinh, cosh_sub_sinh, ← exp_add, add_neg_cancel, exp_zero] + +theorem cosh_sq : cosh x ^ 2 = sinh x ^ 2 + 1 := by + rw [← cosh_sq_sub_sinh_sq x] + ring + +theorem sinh_sq : sinh x ^ 2 = cosh x ^ 2 - 1 := by + rw [← cosh_sq_sub_sinh_sq x] + ring + +theorem cosh_two_mul : cosh (2 * x) = cosh x ^ 2 + sinh x ^ 2 := by rw [two_mul, cosh_add, sq, sq] + +theorem sinh_two_mul : sinh (2 * x) = 2 * sinh x * cosh x := by + rw [two_mul, sinh_add] + ring + +theorem cosh_three_mul : cosh (3 * x) = 4 * cosh x ^ 3 - 3 * cosh x := by + have h1 : x + 2 * x = 3 * x := by ring + rw [← h1, cosh_add x (2 * x)] + simp only [cosh_two_mul, sinh_two_mul] + have h2 : sinh x * (2 * sinh x * cosh x) = 2 * cosh x * sinh x ^ 2 := by ring + rw [h2, sinh_sq] + ring + +theorem sinh_three_mul : sinh (3 * x) = 4 * sinh x ^ 3 + 3 * sinh x := by + have h1 : x + 2 * x = 3 * x := by ring + rw [← h1, sinh_add x (2 * x)] + simp only [cosh_two_mul, sinh_two_mul] + have h2 : cosh x * (2 * sinh x * cosh x) = 2 * sinh x * cosh x ^ 2 := by ring + rw [h2, cosh_sq] + ring + +@[simp] +theorem sin_zero : sin 0 = 0 := by simp [sin] + +@[simp] +theorem sin_neg : sin (-x) = -sin x := by + simp [sin, sub_eq_add_neg, exp_neg, (neg_div _ _).symm, add_mul] + +theorem two_sin : 2 * sin x = (exp (-x * I) - exp (x * I)) * I := + mul_div_cancel₀ _ two_ne_zero + +theorem two_cos : 2 * cos x = exp (x * I) + exp (-x * I) := + mul_div_cancel₀ _ two_ne_zero + +theorem sinh_mul_I : sinh (x * I) = sin x * I := by + rw [← mul_right_inj' (two_ne_zero' ℂ), two_sinh, ← mul_assoc, two_sin, mul_assoc, I_mul_I, + mul_neg_one, neg_sub, neg_mul_eq_neg_mul] + +theorem cosh_mul_I : cosh (x * I) = cos x := by + rw [← mul_right_inj' (two_ne_zero' ℂ), two_cosh, two_cos, neg_mul_eq_neg_mul] + +theorem tanh_mul_I : tanh (x * I) = tan x * I := by + rw [tanh_eq_sinh_div_cosh, cosh_mul_I, sinh_mul_I, mul_div_right_comm, tan] + +theorem cos_mul_I : cos (x * I) = cosh x := by rw [← cosh_mul_I]; ring_nf; simp + +theorem sin_mul_I : sin (x * I) = sinh x * I := by + have h : I * sin (x * I) = -sinh x := by + rw [mul_comm, ← sinh_mul_I] + ring_nf + simp + rw [← neg_neg (sinh x), ← h] + apply Complex.ext <;> simp + +theorem tan_mul_I : tan (x * I) = tanh x * I := by + rw [tan, sin_mul_I, cos_mul_I, mul_div_right_comm, tanh_eq_sinh_div_cosh] + +theorem sin_add : sin (x + y) = sin x * cos y + cos x * sin y := by + rw [← mul_left_inj' I_ne_zero, ← sinh_mul_I, add_mul, add_mul, mul_right_comm, ← sinh_mul_I, + mul_assoc, ← sinh_mul_I, ← cosh_mul_I, ← cosh_mul_I, sinh_add] + +@[simp] +theorem cos_zero : cos 0 = 1 := by simp [cos] + +@[simp] +theorem cos_neg : cos (-x) = cos x := by simp [cos, sub_eq_add_neg, exp_neg, add_comm] + +theorem cos_add : cos (x + y) = cos x * cos y - sin x * sin y := by + rw [← cosh_mul_I, add_mul, cosh_add, cosh_mul_I, cosh_mul_I, sinh_mul_I, sinh_mul_I, + mul_mul_mul_comm, I_mul_I, mul_neg_one, sub_eq_add_neg] + +theorem sin_sub : sin (x - y) = sin x * cos y - cos x * sin y := by + simp [sub_eq_add_neg, sin_add, sin_neg, cos_neg] + +theorem cos_sub : cos (x - y) = cos x * cos y + sin x * sin y := by + simp [sub_eq_add_neg, cos_add, sin_neg, cos_neg] + +theorem sin_add_mul_I (x y : ℂ) : sin (x + y * I) = sin x * cosh y + cos x * sinh y * I := by + rw [sin_add, cos_mul_I, sin_mul_I, mul_assoc] + +theorem sin_eq (z : ℂ) : sin z = sin z.re * cosh z.im + cos z.re * sinh z.im * I := by + convert sin_add_mul_I z.re z.im; exact (re_add_im z).symm + +theorem cos_add_mul_I (x y : ℂ) : cos (x + y * I) = cos x * cosh y - sin x * sinh y * I := by + rw [cos_add, cos_mul_I, sin_mul_I, mul_assoc] + +theorem cos_eq (z : ℂ) : cos z = cos z.re * cosh z.im - sin z.re * sinh z.im * I := by + convert cos_add_mul_I z.re z.im; exact (re_add_im z).symm + +theorem sin_sub_sin : sin x - sin y = 2 * sin ((x - y) / 2) * cos ((x + y) / 2) := by + have s1 := sin_add ((x + y) / 2) ((x - y) / 2) + have s2 := sin_sub ((x + y) / 2) ((x - y) / 2) + rw [div_add_div_same, add_sub, add_right_comm, add_sub_cancel_right, add_self_div_two] at s1 + rw [div_sub_div_same, ← sub_add, add_sub_cancel_left, add_self_div_two] at s2 + rw [s1, s2] + ring + +theorem cos_sub_cos : cos x - cos y = -2 * sin ((x + y) / 2) * sin ((x - y) / 2) := by + have s1 := cos_add ((x + y) / 2) ((x - y) / 2) + have s2 := cos_sub ((x + y) / 2) ((x - y) / 2) + rw [div_add_div_same, add_sub, add_right_comm, add_sub_cancel_right, add_self_div_two] at s1 + rw [div_sub_div_same, ← sub_add, add_sub_cancel_left, add_self_div_two] at s2 + rw [s1, s2] + ring + +theorem sin_add_sin : sin x + sin y = 2 * sin ((x + y) / 2) * cos ((x - y) / 2) := by + simpa using sin_sub_sin x (-y) + +theorem cos_add_cos : cos x + cos y = 2 * cos ((x + y) / 2) * cos ((x - y) / 2) := by + calc + cos x + cos y = cos ((x + y) / 2 + (x - y) / 2) + cos ((x + y) / 2 - (x - y) / 2) := ?_ + _ = + cos ((x + y) / 2) * cos ((x - y) / 2) - sin ((x + y) / 2) * sin ((x - y) / 2) + + (cos ((x + y) / 2) * cos ((x - y) / 2) + sin ((x + y) / 2) * sin ((x - y) / 2)) := + ?_ + _ = 2 * cos ((x + y) / 2) * cos ((x - y) / 2) := ?_ + + · congr <;> field_simp + · rw [cos_add, cos_sub] + ring + +theorem sin_conj : sin (conj x) = conj (sin x) := by + rw [← mul_left_inj' I_ne_zero, ← sinh_mul_I, ← conj_neg_I, ← RingHom.map_mul, ← RingHom.map_mul, + sinh_conj, mul_neg, sinh_neg, sinh_mul_I, mul_neg] + +@[simp] +theorem ofReal_sin_ofReal_re (x : ℝ) : ((sin x).re : ℂ) = sin x := + conj_eq_iff_re.1 <| by rw [← sin_conj, conj_ofReal] + +@[simp, norm_cast] +theorem ofReal_sin (x : ℝ) : (Real.sin x : ℂ) = sin x := + ofReal_sin_ofReal_re _ + +@[simp] +theorem sin_ofReal_im (x : ℝ) : (sin x).im = 0 := by rw [← ofReal_sin_ofReal_re, ofReal_im] + +theorem sin_ofReal_re (x : ℝ) : (sin x).re = Real.sin x := + rfl + +theorem cos_conj : cos (conj x) = conj (cos x) := by + rw [← cosh_mul_I, ← conj_neg_I, ← RingHom.map_mul, ← cosh_mul_I, cosh_conj, mul_neg, cosh_neg] + +@[simp] +theorem ofReal_cos_ofReal_re (x : ℝ) : ((cos x).re : ℂ) = cos x := + conj_eq_iff_re.1 <| by rw [← cos_conj, conj_ofReal] + +@[simp, norm_cast] +theorem ofReal_cos (x : ℝ) : (Real.cos x : ℂ) = cos x := + ofReal_cos_ofReal_re _ + +@[simp] +theorem cos_ofReal_im (x : ℝ) : (cos x).im = 0 := by rw [← ofReal_cos_ofReal_re, ofReal_im] + +theorem cos_ofReal_re (x : ℝ) : (cos x).re = Real.cos x := + rfl + +@[simp] +theorem tan_zero : tan 0 = 0 := by simp [tan] + +theorem tan_eq_sin_div_cos : tan x = sin x / cos x := + rfl + +theorem cot_eq_cos_div_sin : cot x = cos x / sin x := + rfl + +theorem tan_mul_cos {x : ℂ} (hx : cos x ≠ 0) : tan x * cos x = sin x := by + rw [tan_eq_sin_div_cos, div_mul_cancel₀ _ hx] + +@[simp] +theorem tan_neg : tan (-x) = -tan x := by simp [tan, neg_div] + +theorem tan_conj : tan (conj x) = conj (tan x) := by rw [tan, sin_conj, cos_conj, ← map_div₀, tan] + +theorem cot_conj : cot (conj x) = conj (cot x) := by rw [cot, sin_conj, cos_conj, ← map_div₀, cot] + +@[simp] +theorem ofReal_tan_ofReal_re (x : ℝ) : ((tan x).re : ℂ) = tan x := + conj_eq_iff_re.1 <| by rw [← tan_conj, conj_ofReal] + +@[simp] +theorem ofReal_cot_ofReal_re (x : ℝ) : ((cot x).re : ℂ) = cot x := + conj_eq_iff_re.1 <| by rw [← cot_conj, conj_ofReal] + +@[simp, norm_cast] +theorem ofReal_tan (x : ℝ) : (Real.tan x : ℂ) = tan x := + ofReal_tan_ofReal_re _ + +@[simp, norm_cast] +theorem ofReal_cot (x : ℝ) : (Real.cot x : ℂ) = cot x := + ofReal_cot_ofReal_re _ + +@[simp] +theorem tan_ofReal_im (x : ℝ) : (tan x).im = 0 := by rw [← ofReal_tan_ofReal_re, ofReal_im] + +theorem tan_ofReal_re (x : ℝ) : (tan x).re = Real.tan x := + rfl + +theorem cos_add_sin_I : cos x + sin x * I = exp (x * I) := by + rw [← cosh_add_sinh, sinh_mul_I, cosh_mul_I] + +theorem cos_sub_sin_I : cos x - sin x * I = exp (-x * I) := by + rw [neg_mul, ← cosh_sub_sinh, sinh_mul_I, cosh_mul_I] + +@[simp] +theorem sin_sq_add_cos_sq : sin x ^ 2 + cos x ^ 2 = 1 := + Eq.trans (by rw [cosh_mul_I, sinh_mul_I, mul_pow, I_sq, mul_neg_one, sub_neg_eq_add, add_comm]) + (cosh_sq_sub_sinh_sq (x * I)) + +@[simp] +theorem cos_sq_add_sin_sq : cos x ^ 2 + sin x ^ 2 = 1 := by rw [add_comm, sin_sq_add_cos_sq] + +theorem cos_two_mul' : cos (2 * x) = cos x ^ 2 - sin x ^ 2 := by rw [two_mul, cos_add, ← sq, ← sq] + +theorem cos_two_mul : cos (2 * x) = 2 * cos x ^ 2 - 1 := by + rw [cos_two_mul', eq_sub_iff_add_eq.2 (sin_sq_add_cos_sq x), ← sub_add, sub_add_eq_add_sub, + two_mul] + +theorem sin_two_mul : sin (2 * x) = 2 * sin x * cos x := by + rw [two_mul, sin_add, two_mul, add_mul, mul_comm] + +theorem cos_sq : cos x ^ 2 = 1 / 2 + cos (2 * x) / 2 := by + simp [cos_two_mul, div_add_div_same, mul_div_cancel_left₀, two_ne_zero, -one_div] + +theorem cos_sq' : cos x ^ 2 = 1 - sin x ^ 2 := by rw [← sin_sq_add_cos_sq x, add_sub_cancel_left] + +theorem sin_sq : sin x ^ 2 = 1 - cos x ^ 2 := by rw [← sin_sq_add_cos_sq x, add_sub_cancel_right] + +theorem inv_one_add_tan_sq {x : ℂ} (hx : cos x ≠ 0) : (1 + tan x ^ 2)⁻¹ = cos x ^ 2 := by + rw [tan_eq_sin_div_cos, div_pow] + field_simp + +theorem tan_sq_div_one_add_tan_sq {x : ℂ} (hx : cos x ≠ 0) : + tan x ^ 2 / (1 + tan x ^ 2) = sin x ^ 2 := by + simp only [← tan_mul_cos hx, mul_pow, ← inv_one_add_tan_sq hx, div_eq_mul_inv, one_mul] + +theorem cos_three_mul : cos (3 * x) = 4 * cos x ^ 3 - 3 * cos x := by + have h1 : x + 2 * x = 3 * x := by ring + rw [← h1, cos_add x (2 * x)] + simp only [cos_two_mul, sin_two_mul, mul_add, mul_sub, mul_one, sq] + have h2 : 4 * cos x ^ 3 = 2 * cos x * cos x * cos x + 2 * cos x * cos x ^ 2 := by ring + rw [h2, cos_sq'] + ring + +theorem sin_three_mul : sin (3 * x) = 3 * sin x - 4 * sin x ^ 3 := by + have h1 : x + 2 * x = 3 * x := by ring + rw [← h1, sin_add x (2 * x)] + simp only [cos_two_mul, sin_two_mul, cos_sq'] + have h2 : cos x * (2 * sin x * cos x) = 2 * sin x * cos x ^ 2 := by ring + rw [h2, cos_sq'] + ring + +theorem exp_mul_I : exp (x * I) = cos x + sin x * I := + (cos_add_sin_I _).symm + +theorem exp_add_mul_I : exp (x + y * I) = exp x * (cos y + sin y * I) := by rw [exp_add, exp_mul_I] + +theorem exp_eq_exp_re_mul_sin_add_cos : exp x = exp x.re * (cos x.im + sin x.im * I) := by + rw [← exp_add_mul_I, re_add_im] + +theorem exp_re : (exp x).re = Real.exp x.re * Real.cos x.im := by + rw [exp_eq_exp_re_mul_sin_add_cos] + simp [exp_ofReal_re, cos_ofReal_re] + +theorem exp_im : (exp x).im = Real.exp x.re * Real.sin x.im := by + rw [exp_eq_exp_re_mul_sin_add_cos] + simp [exp_ofReal_re, sin_ofReal_re] + +@[simp] +theorem exp_ofReal_mul_I_re (x : ℝ) : (exp (x * I)).re = Real.cos x := by + simp [exp_mul_I, cos_ofReal_re] + +@[simp] +theorem exp_ofReal_mul_I_im (x : ℝ) : (exp (x * I)).im = Real.sin x := by + simp [exp_mul_I, sin_ofReal_re] + +/-- **De Moivre's formula** -/ +theorem cos_add_sin_mul_I_pow (n : ℕ) (z : ℂ) : + (cos z + sin z * I) ^ n = cos (↑n * z) + sin (↑n * z) * I := by + rw [← exp_mul_I, ← exp_mul_I, ← exp_nat_mul, mul_assoc] + +end Complex + +namespace Real + +open Complex + +variable (x y : ℝ) + +@[simp] +theorem sin_zero : sin 0 = 0 := by simp [sin] + +@[simp] +theorem sin_neg : sin (-x) = -sin x := by simp [sin, exp_neg, (neg_div _ _).symm, add_mul] + +nonrec theorem sin_add : sin (x + y) = sin x * cos y + cos x * sin y := + ofReal_injective <| by simp [sin_add] + +@[simp] +theorem cos_zero : cos 0 = 1 := by simp [cos] + +@[simp] +theorem cos_neg : cos (-x) = cos x := by simp [cos, exp_neg] + +@[simp] +theorem cos_abs : cos |x| = cos x := by + cases le_total x 0 <;> simp only [*, _root_.abs_of_nonneg, abs_of_nonpos, cos_neg] + +nonrec theorem cos_add : cos (x + y) = cos x * cos y - sin x * sin y := + ofReal_injective <| by simp [cos_add] + +theorem sin_sub : sin (x - y) = sin x * cos y - cos x * sin y := by + simp [sub_eq_add_neg, sin_add, sin_neg, cos_neg] + +theorem cos_sub : cos (x - y) = cos x * cos y + sin x * sin y := by + simp [sub_eq_add_neg, cos_add, sin_neg, cos_neg] + +nonrec theorem sin_sub_sin : sin x - sin y = 2 * sin ((x - y) / 2) * cos ((x + y) / 2) := + ofReal_injective <| by simp [sin_sub_sin] + +nonrec theorem cos_sub_cos : cos x - cos y = -2 * sin ((x + y) / 2) * sin ((x - y) / 2) := + ofReal_injective <| by simp [cos_sub_cos] + +nonrec theorem cos_add_cos : cos x + cos y = 2 * cos ((x + y) / 2) * cos ((x - y) / 2) := + ofReal_injective <| by simp [cos_add_cos] + +theorem two_mul_sin_mul_sin (x y : ℝ) : 2 * sin x * sin y = cos (x - y) - cos (x + y) := by + simp [cos_add, cos_sub] + ring + +theorem two_mul_cos_mul_cos (x y : ℝ) : 2 * cos x * cos y = cos (x - y) + cos (x + y) := by + simp [cos_add, cos_sub] + ring + +theorem two_mul_sin_mul_cos (x y : ℝ) : 2 * sin x * cos y = sin (x - y) + sin (x + y) := by + simp [sin_add, sin_sub] + ring + +nonrec theorem tan_eq_sin_div_cos : tan x = sin x / cos x := + ofReal_injective <| by simp only [ofReal_tan, tan_eq_sin_div_cos, ofReal_div, ofReal_sin, + ofReal_cos] + +nonrec theorem cot_eq_cos_div_sin : cot x = cos x / sin x := + ofReal_injective <| by simp [cot_eq_cos_div_sin] + +theorem tan_mul_cos {x : ℝ} (hx : cos x ≠ 0) : tan x * cos x = sin x := by + rw [tan_eq_sin_div_cos, div_mul_cancel₀ _ hx] + +@[simp] +theorem tan_zero : tan 0 = 0 := by simp [tan] + +@[simp] +theorem tan_neg : tan (-x) = -tan x := by simp [tan, neg_div] + +@[simp] +nonrec theorem sin_sq_add_cos_sq : sin x ^ 2 + cos x ^ 2 = 1 := + ofReal_injective (by simp [sin_sq_add_cos_sq]) + +@[simp] +theorem cos_sq_add_sin_sq : cos x ^ 2 + sin x ^ 2 = 1 := by rw [add_comm, sin_sq_add_cos_sq] + +theorem sin_sq_le_one : sin x ^ 2 ≤ 1 := by + rw [← sin_sq_add_cos_sq x]; exact le_add_of_nonneg_right (sq_nonneg _) + +theorem cos_sq_le_one : cos x ^ 2 ≤ 1 := by + rw [← sin_sq_add_cos_sq x]; exact le_add_of_nonneg_left (sq_nonneg _) + +theorem abs_sin_le_one : |sin x| ≤ 1 := + abs_le_one_iff_mul_self_le_one.2 <| by simp only [← sq, sin_sq_le_one] + +theorem abs_cos_le_one : |cos x| ≤ 1 := + abs_le_one_iff_mul_self_le_one.2 <| by simp only [← sq, cos_sq_le_one] + +theorem sin_le_one : sin x ≤ 1 := + (abs_le.1 (abs_sin_le_one _)).2 + +theorem cos_le_one : cos x ≤ 1 := + (abs_le.1 (abs_cos_le_one _)).2 + +theorem neg_one_le_sin : -1 ≤ sin x := + (abs_le.1 (abs_sin_le_one _)).1 + +theorem neg_one_le_cos : -1 ≤ cos x := + (abs_le.1 (abs_cos_le_one _)).1 + +nonrec theorem cos_two_mul : cos (2 * x) = 2 * cos x ^ 2 - 1 := + ofReal_injective <| by simp [cos_two_mul] + +nonrec theorem cos_two_mul' : cos (2 * x) = cos x ^ 2 - sin x ^ 2 := + ofReal_injective <| by simp [cos_two_mul'] + +nonrec theorem sin_two_mul : sin (2 * x) = 2 * sin x * cos x := + ofReal_injective <| by simp [sin_two_mul] + +nonrec theorem cos_sq : cos x ^ 2 = 1 / 2 + cos (2 * x) / 2 := + ofReal_injective <| by simp [cos_sq] + +theorem cos_sq' : cos x ^ 2 = 1 - sin x ^ 2 := by rw [← sin_sq_add_cos_sq x, add_sub_cancel_left] + +theorem sin_sq : sin x ^ 2 = 1 - cos x ^ 2 := + eq_sub_iff_add_eq.2 <| sin_sq_add_cos_sq _ + +lemma sin_sq_eq_half_sub : sin x ^ 2 = 1 / 2 - cos (2 * x) / 2 := by + rw [sin_sq, cos_sq, ← sub_sub, sub_half] + +theorem abs_sin_eq_sqrt_one_sub_cos_sq (x : ℝ) : |sin x| = √(1 - cos x ^ 2) := by + rw [← sin_sq, sqrt_sq_eq_abs] + +theorem abs_cos_eq_sqrt_one_sub_sin_sq (x : ℝ) : |cos x| = √(1 - sin x ^ 2) := by + rw [← cos_sq', sqrt_sq_eq_abs] + +theorem inv_one_add_tan_sq {x : ℝ} (hx : cos x ≠ 0) : (1 + tan x ^ 2)⁻¹ = cos x ^ 2 := + have : Complex.cos x ≠ 0 := mt (congr_arg re) hx + ofReal_inj.1 <| by simpa using Complex.inv_one_add_tan_sq this + +theorem tan_sq_div_one_add_tan_sq {x : ℝ} (hx : cos x ≠ 0) : + tan x ^ 2 / (1 + tan x ^ 2) = sin x ^ 2 := by + simp only [← tan_mul_cos hx, mul_pow, ← inv_one_add_tan_sq hx, div_eq_mul_inv, one_mul] + +theorem inv_sqrt_one_add_tan_sq {x : ℝ} (hx : 0 < cos x) : (√(1 + tan x ^ 2))⁻¹ = cos x := by + rw [← sqrt_sq hx.le, ← sqrt_inv, inv_one_add_tan_sq hx.ne'] + +theorem tan_div_sqrt_one_add_tan_sq {x : ℝ} (hx : 0 < cos x) : + tan x / √(1 + tan x ^ 2) = sin x := by + rw [← tan_mul_cos hx.ne', ← inv_sqrt_one_add_tan_sq hx, div_eq_mul_inv] + +nonrec theorem cos_three_mul : cos (3 * x) = 4 * cos x ^ 3 - 3 * cos x := by + rw [← ofReal_inj]; simp [cos_three_mul] + +nonrec theorem sin_three_mul : sin (3 * x) = 3 * sin x - 4 * sin x ^ 3 := by + rw [← ofReal_inj]; simp [sin_three_mul] + +/-- The definition of `sinh` in terms of `exp`. -/ +nonrec theorem sinh_eq (x : ℝ) : sinh x = (exp x - exp (-x)) / 2 := + ofReal_injective <| by simp [Complex.sinh] + +@[simp] +theorem sinh_zero : sinh 0 = 0 := by simp [sinh] + +@[simp] +theorem sinh_neg : sinh (-x) = -sinh x := by simp [sinh, exp_neg, (neg_div _ _).symm, add_mul] + +nonrec theorem sinh_add : sinh (x + y) = sinh x * cosh y + cosh x * sinh y := by + rw [← ofReal_inj]; simp [sinh_add] + +/-- The definition of `cosh` in terms of `exp`. -/ +theorem cosh_eq (x : ℝ) : cosh x = (exp x + exp (-x)) / 2 := + eq_div_of_mul_eq two_ne_zero <| by + rw [cosh, exp, exp, Complex.ofReal_neg, Complex.cosh, mul_two, ← Complex.add_re, ← mul_two, + div_mul_cancel₀ _ (two_ne_zero' ℂ), Complex.add_re] + +@[simp] +theorem cosh_zero : cosh 0 = 1 := by simp [cosh] + +@[simp] +theorem cosh_neg : cosh (-x) = cosh x := + ofReal_inj.1 <| by simp + +@[simp] +theorem cosh_abs : cosh |x| = cosh x := by + cases le_total x 0 <;> simp [*, _root_.abs_of_nonneg, abs_of_nonpos] + +nonrec theorem cosh_add : cosh (x + y) = cosh x * cosh y + sinh x * sinh y := by + rw [← ofReal_inj]; simp [cosh_add] + +theorem sinh_sub : sinh (x - y) = sinh x * cosh y - cosh x * sinh y := by + simp [sub_eq_add_neg, sinh_add, sinh_neg, cosh_neg] + +theorem cosh_sub : cosh (x - y) = cosh x * cosh y - sinh x * sinh y := by + simp [sub_eq_add_neg, cosh_add, sinh_neg, cosh_neg] + +nonrec theorem tanh_eq_sinh_div_cosh : tanh x = sinh x / cosh x := + ofReal_inj.1 <| by simp [tanh_eq_sinh_div_cosh] + +@[simp] +theorem tanh_zero : tanh 0 = 0 := by simp [tanh] + +@[simp] +theorem tanh_neg : tanh (-x) = -tanh x := by simp [tanh, neg_div] + +@[simp] +theorem cosh_add_sinh : cosh x + sinh x = exp x := by rw [← ofReal_inj]; simp + +@[simp] +theorem sinh_add_cosh : sinh x + cosh x = exp x := by rw [add_comm, cosh_add_sinh] + +@[simp] +theorem exp_sub_cosh : exp x - cosh x = sinh x := + sub_eq_iff_eq_add.2 (sinh_add_cosh x).symm + +@[simp] +theorem exp_sub_sinh : exp x - sinh x = cosh x := + sub_eq_iff_eq_add.2 (cosh_add_sinh x).symm + +@[simp] +theorem cosh_sub_sinh : cosh x - sinh x = exp (-x) := by + rw [← ofReal_inj] + simp + +@[simp] +theorem sinh_sub_cosh : sinh x - cosh x = -exp (-x) := by rw [← neg_sub, cosh_sub_sinh] + +@[simp] +theorem cosh_sq_sub_sinh_sq (x : ℝ) : cosh x ^ 2 - sinh x ^ 2 = 1 := by rw [← ofReal_inj]; simp + +nonrec theorem cosh_sq : cosh x ^ 2 = sinh x ^ 2 + 1 := by rw [← ofReal_inj]; simp [cosh_sq] + +theorem cosh_sq' : cosh x ^ 2 = 1 + sinh x ^ 2 := + (cosh_sq x).trans (add_comm _ _) + +nonrec theorem sinh_sq : sinh x ^ 2 = cosh x ^ 2 - 1 := by rw [← ofReal_inj]; simp [sinh_sq] + +nonrec theorem cosh_two_mul : cosh (2 * x) = cosh x ^ 2 + sinh x ^ 2 := by + rw [← ofReal_inj]; simp [cosh_two_mul] + +nonrec theorem sinh_two_mul : sinh (2 * x) = 2 * sinh x * cosh x := by + rw [← ofReal_inj]; simp [sinh_two_mul] + +nonrec theorem cosh_three_mul : cosh (3 * x) = 4 * cosh x ^ 3 - 3 * cosh x := by + rw [← ofReal_inj]; simp [cosh_three_mul] + +nonrec theorem sinh_three_mul : sinh (3 * x) = 4 * sinh x ^ 3 + 3 * sinh x := by + rw [← ofReal_inj]; simp [sinh_three_mul] + +open IsAbsoluteValue Nat + +private theorem add_one_lt_exp_of_pos {x : ℝ} (hx : 0 < x) : x + 1 < exp x := + (by nlinarith : x + 1 < 1 + x + x ^ 2 / 2).trans_le (quadratic_le_exp_of_nonneg hx.le) + +private theorem add_one_le_exp_of_nonneg {x : ℝ} (hx : 0 ≤ x) : x + 1 ≤ exp x := by + rcases eq_or_lt_of_le hx with (rfl | h) + · simp + exact (add_one_lt_exp_of_pos h).le + +/-- `Real.cosh` is always positive -/ +theorem cosh_pos (x : ℝ) : 0 < Real.cosh x := + (cosh_eq x).symm ▸ half_pos (add_pos (exp_pos x) (exp_pos (-x))) + +theorem sinh_lt_cosh : sinh x < cosh x := + lt_of_pow_lt_pow_left₀ 2 (cosh_pos _).le <| (cosh_sq x).symm ▸ lt_add_one _ + +end Real + +namespace Real + +open Complex Finset + +theorem cos_bound {x : ℝ} (hx : |x| ≤ 1) : |cos x - (1 - x ^ 2 / 2)| ≤ |x| ^ 4 * (5 / 96) := + calc + |cos x - (1 - x ^ 2 / 2)| = Complex.abs (Complex.cos x - (1 - (x : ℂ) ^ 2 / 2)) := by + rw [← abs_ofReal]; simp + _ = Complex.abs ((Complex.exp (x * I) + Complex.exp (-x * I) - (2 - (x : ℂ) ^ 2)) / 2) := by + simp [Complex.cos, sub_div, add_div, neg_div, div_self (two_ne_zero' ℂ)] + _ = abs + (((Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) + + (Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial)) / 2) := + (congr_arg Complex.abs + (congr_arg (fun x : ℂ => x / 2) + (by + simp only [sum_range_succ, neg_mul, pow_succ, pow_zero, mul_one, range_zero, sum_empty, + Nat.factorial, Nat.cast_one, ne_eq, one_ne_zero, not_false_eq_true, div_self, + zero_add, div_one, Nat.mul_one, Nat.cast_succ, Nat.cast_mul, Nat.cast_ofNat, mul_neg, + neg_neg] + apply Complex.ext <;> simp [div_eq_mul_inv, normSq] <;> ring_nf + ))) + _ ≤ abs ((Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) / 2) + + abs ((Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) / 2) := by + rw [add_div]; exact Complex.abs.add_le _ _ + _ = abs (Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) / 2 + + abs (Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) / 2 := by + simp [map_div₀] + _ ≤ Complex.abs (x * I) ^ 4 * (Nat.succ 4 * ((Nat.factorial 4) * (4 : ℕ) : ℝ)⁻¹) / 2 + + Complex.abs (-x * I) ^ 4 * (Nat.succ 4 * ((Nat.factorial 4) * (4 : ℕ) : ℝ)⁻¹) / 2 := by + gcongr + · exact Complex.exp_bound (by simpa) (by decide) + · exact Complex.exp_bound (by simpa) (by decide) + _ ≤ |x| ^ 4 * (5 / 96) := by norm_num [Nat.factorial] + +theorem sin_bound {x : ℝ} (hx : |x| ≤ 1) : |sin x - (x - x ^ 3 / 6)| ≤ |x| ^ 4 * (5 / 96) := + calc + |sin x - (x - x ^ 3 / 6)| = Complex.abs (Complex.sin x - (x - x ^ 3 / 6 : ℝ)) := by + rw [← abs_ofReal]; simp + _ = Complex.abs (((Complex.exp (-x * I) - Complex.exp (x * I)) * I - + (2 * x - x ^ 3 / 3 : ℝ)) / 2) := by + simp [Complex.sin, sub_div, add_div, neg_div, mul_div_cancel_left₀ _ (two_ne_zero' ℂ), + div_div, show (3 : ℂ) * 2 = 6 by norm_num] + _ = Complex.abs (((Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) - + (Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial)) * I / 2) := + (congr_arg Complex.abs + (congr_arg (fun x : ℂ => x / 2) + (by + simp only [sum_range_succ, neg_mul, pow_succ, pow_zero, mul_one, ofReal_sub, ofReal_mul, + ofReal_ofNat, ofReal_div, range_zero, sum_empty, Nat.factorial, Nat.cast_one, ne_eq, + one_ne_zero, not_false_eq_true, div_self, zero_add, div_one, mul_neg, neg_neg, + Nat.mul_one, Nat.cast_succ, Nat.cast_mul, Nat.cast_ofNat] + apply Complex.ext <;> simp [div_eq_mul_inv, normSq]; ring))) + _ ≤ abs ((Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) * I / 2) + + abs (-((Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) * I) / 2) := by + rw [sub_mul, sub_eq_add_neg, add_div]; exact Complex.abs.add_le _ _ + _ = abs (Complex.exp (x * I) - ∑ m ∈ range 4, (x * I) ^ m / m.factorial) / 2 + + abs (Complex.exp (-x * I) - ∑ m ∈ range 4, (-x * I) ^ m / m.factorial) / 2 := by + simp [add_comm, map_div₀] + _ ≤ Complex.abs (x * I) ^ 4 * (Nat.succ 4 * (Nat.factorial 4 * (4 : ℕ) : ℝ)⁻¹) / 2 + + Complex.abs (-x * I) ^ 4 * (Nat.succ 4 * (Nat.factorial 4 * (4 : ℕ) : ℝ)⁻¹) / 2 := by + gcongr + · exact Complex.exp_bound (by simpa) (by decide) + · exact Complex.exp_bound (by simpa) (by decide) + _ ≤ |x| ^ 4 * (5 / 96) := by norm_num [Nat.factorial] + +theorem cos_pos_of_le_one {x : ℝ} (hx : |x| ≤ 1) : 0 < cos x := + calc 0 < 1 - x ^ 2 / 2 - |x| ^ 4 * (5 / 96) := + sub_pos.2 <| + lt_sub_iff_add_lt.2 + (calc + |x| ^ 4 * (5 / 96) + x ^ 2 / 2 ≤ 1 * (5 / 96) + 1 / 2 := by + gcongr + · exact pow_le_one₀ (abs_nonneg _) hx + · rw [sq, ← abs_mul_self, abs_mul] + exact mul_le_one₀ hx (abs_nonneg _) hx + _ < 1 := by norm_num) + _ ≤ cos x := sub_le_comm.1 (abs_sub_le_iff.1 (cos_bound hx)).2 + +theorem sin_pos_of_pos_of_le_one {x : ℝ} (hx0 : 0 < x) (hx : x ≤ 1) : 0 < sin x := + calc 0 < x - x ^ 3 / 6 - |x| ^ 4 * (5 / 96) := + sub_pos.2 <| lt_sub_iff_add_lt.2 + (calc + |x| ^ 4 * (5 / 96) + x ^ 3 / 6 ≤ x * (5 / 96) + x / 6 := by + gcongr + · calc + |x| ^ 4 ≤ |x| ^ 1 := + pow_le_pow_of_le_one (abs_nonneg _) + (by rwa [_root_.abs_of_nonneg (le_of_lt hx0)]) (by decide) + _ = x := by simp [_root_.abs_of_nonneg (le_of_lt hx0)] + · calc + x ^ 3 ≤ x ^ 1 := pow_le_pow_of_le_one (le_of_lt hx0) hx (by decide) + _ = x := pow_one _ + _ < x := by linarith) + _ ≤ sin x := + sub_le_comm.1 (abs_sub_le_iff.1 (sin_bound (by rwa [_root_.abs_of_nonneg (le_of_lt hx0)]))).2 + +theorem sin_pos_of_pos_of_le_two {x : ℝ} (hx0 : 0 < x) (hx : x ≤ 2) : 0 < sin x := + have : x / 2 ≤ 1 := (div_le_iff₀ (by norm_num)).mpr (by simpa) + calc + 0 < 2 * sin (x / 2) * cos (x / 2) := + mul_pos (mul_pos (by norm_num) (sin_pos_of_pos_of_le_one (half_pos hx0) this)) + (cos_pos_of_le_one (by rwa [_root_.abs_of_nonneg (le_of_lt (half_pos hx0))])) + _ = sin x := by rw [← sin_two_mul, two_mul, add_halves] + +theorem cos_one_le : cos 1 ≤ 2 / 3 := + calc + cos 1 ≤ |(1 : ℝ)| ^ 4 * (5 / 96) + (1 - 1 ^ 2 / 2) := + sub_le_iff_le_add.1 (abs_sub_le_iff.1 (cos_bound (by simp))).1 + _ ≤ 2 / 3 := by norm_num + +theorem cos_one_pos : 0 < cos 1 := + cos_pos_of_le_one (le_of_eq abs_one) + +theorem cos_two_neg : cos 2 < 0 := + calc cos 2 = cos (2 * 1) := congr_arg cos (mul_one _).symm + _ = _ := Real.cos_two_mul 1 + _ ≤ 2 * (2 / 3) ^ 2 - 1 := by + gcongr + · exact cos_one_pos.le + · apply cos_one_le + _ < 0 := by norm_num + +end Real + +namespace Mathlib.Meta.Positivity +open Lean.Meta Qq + +/-- Extension for the `positivity` tactic: `Real.cosh` is always positive. -/ +@[positivity Real.cosh _] +def evalCosh : PositivityExt where eval {u α} _ _ e := do + match u, α, e with + | 0, ~q(ℝ), ~q(Real.cosh $a) => + assertInstancesCommute + return .positive q(Real.cosh_pos $a) + | _, _, _ => throwError "not Real.cosh" + +example (x : ℝ) : 0 < x.cosh := by positivity + +end Mathlib.Meta.Positivity + +namespace Complex + +@[simp] +theorem abs_cos_add_sin_mul_I (x : ℝ) : abs (cos x + sin x * I) = 1 := by + have := Real.sin_sq_add_cos_sq x + simp_all [add_comm, abs, normSq, sq, sin_ofReal_re, cos_ofReal_re, mul_re] + +@[simp] +theorem abs_exp_ofReal_mul_I (x : ℝ) : abs (exp (x * I)) = 1 := by + rw [exp_mul_I, abs_cos_add_sin_mul_I] + +theorem abs_exp (z : ℂ) : abs (exp z) = Real.exp z.re := by + rw [exp_eq_exp_re_mul_sin_add_cos, map_mul, abs_exp_ofReal, abs_cos_add_sin_mul_I, mul_one] + +theorem abs_exp_eq_iff_re_eq {x y : ℂ} : abs (exp x) = abs (exp y) ↔ x.re = y.re := by + rw [abs_exp, abs_exp, Real.exp_eq_exp] + +end Complex diff --git a/Mathlib/Tactic/FunProp.lean b/Mathlib/Tactic/FunProp.lean index 1e9f65989489a..a52e272d5b956 100644 --- a/Mathlib/Tactic/FunProp.lean +++ b/Mathlib/Tactic/FunProp.lean @@ -37,7 +37,7 @@ example (y : ℝ) (hy : y ≠ 0) : ContinuousAt (fun x : ℝ => 1/x) y := by fun **Basic debugging:** The most common issue is that a function is missing the appropriate theorem. For example: ```lean -import Mathlib.Data.Complex.Exponential +import Mathlib.Data.Complex.Trigonometric example : Continuous (fun x : ℝ => x * Real.sin x) := by fun_prop ``` Fails with the error: diff --git a/MathlibTest/Recall.lean b/MathlibTest/Recall.lean index a665edc1a8f34..01092a624dc92 100644 --- a/MathlibTest/Recall.lean +++ b/MathlibTest/Recall.lean @@ -1,7 +1,7 @@ import Mathlib.Tactic.Recall import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.SpecialFunctions.Trigonometric.Basic -import Mathlib.Data.Complex.Exponential +import Mathlib.Data.Complex.Trigonometric set_option linter.style.setOption false -- Remark: When the test is run by make/CI, this option is not set, so we set it here. diff --git a/MathlibTest/positivity.lean b/MathlibTest/positivity.lean index 80b80dab4bb9e..a9b0c4816cbd6 100644 --- a/MathlibTest/positivity.lean +++ b/MathlibTest/positivity.lean @@ -1,5 +1,5 @@ import Mathlib.Tactic.Positivity -import Mathlib.Data.Complex.Exponential +import Mathlib.Data.Complex.Trigonometric import Mathlib.Data.Real.Sqrt import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Analysis.SpecialFunctions.Pow.Real From b849359fabbb75a1539b12e221b64acf9b104415 Mon Sep 17 00:00:00 2001 From: sven-manthe Date: Mon, 27 Jan 2025 14:13:35 +0000 Subject: [PATCH 564/681] feat: define Descriptive.Tree (#18763) Define trees in the sense of descriptive set theory. Deduce SetLike from a more general instance about complete sublattices of power set lattices. Taken from https://github.com/sven-manthe/A-formalization-of-Borel-determinacy-in-Lean Co-authored-by: sven-manthe <147848313+sven-manthe@users.noreply.github.com> Co-authored-by: sven-manthe --- Mathlib.lean | 2 + Mathlib/Data/SetLike/Basic.lean | 10 ++++ Mathlib/Order/CompleteLattice/SetLike.lean | 56 ++++++++++++++++++++++ Mathlib/SetTheory/Descriptive/Tree.lean | 46 ++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 Mathlib/Order/CompleteLattice/SetLike.lean create mode 100644 Mathlib/SetTheory/Descriptive/Tree.lean diff --git a/Mathlib.lean b/Mathlib.lean index 636adb7f3c36c..a9e8682e0b928 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4158,6 +4158,7 @@ import Mathlib.Order.Compare import Mathlib.Order.CompleteBooleanAlgebra import Mathlib.Order.CompleteLattice import Mathlib.Order.CompleteLattice.Finset +import Mathlib.Order.CompleteLattice.SetLike import Mathlib.Order.CompleteLatticeIntervals import Mathlib.Order.CompletePartialOrder import Mathlib.Order.CompleteSublattice @@ -4863,6 +4864,7 @@ import Mathlib.SetTheory.Cardinal.SchroederBernstein import Mathlib.SetTheory.Cardinal.Subfield import Mathlib.SetTheory.Cardinal.ToNat import Mathlib.SetTheory.Cardinal.UnivLE +import Mathlib.SetTheory.Descriptive.Tree import Mathlib.SetTheory.Game.Basic import Mathlib.SetTheory.Game.Birthday import Mathlib.SetTheory.Game.Domineering diff --git a/Mathlib/Data/SetLike/Basic.lean b/Mathlib/Data/SetLike/Basic.lean index 44719c1ca0a00..9f99e745a2ce2 100644 --- a/Mathlib/Data/SetLike/Basic.lean +++ b/Mathlib/Data/SetLike/Basic.lean @@ -214,4 +214,14 @@ theorem exists_of_lt : p < q → ∃ x ∈ q, x ∉ p := theorem lt_iff_le_and_exists : p < q ↔ p ≤ q ∧ ∃ x ∈ q, x ∉ p := by rw [lt_iff_le_not_le, not_le_iff_exists] +/-- membership is inherited from `Set X` -/ +abbrev instSubtypeSet {X} {p : Set X → Prop} : SetLike {s // p s} X where + coe := (↑) + coe_injective' := Subtype.val_injective + +/-- membership is inherited from `S` -/ +abbrev instSubtype {X S} [SetLike S X] {p : S → Prop} : SetLike {s // p s} X where + coe := (↑) + coe_injective' := SetLike.coe_injective.comp Subtype.val_injective + end SetLike diff --git a/Mathlib/Order/CompleteLattice/SetLike.lean b/Mathlib/Order/CompleteLattice/SetLike.lean new file mode 100644 index 0000000000000..2e5426d136ae5 --- /dev/null +++ b/Mathlib/Order/CompleteLattice/SetLike.lean @@ -0,0 +1,56 @@ +/- +Copyright (c) 2024 Sven Manthe. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sven Manthe +-/ +import Mathlib.Order.CompleteSublattice + +/-! +# `SetLike` instance for elements of `CompleteSublattice (Set X)` + +This file provides lemmas for the `SetLike` instance for elements of `CompleteSublattice (Set X)` +-/ + +attribute [local instance] SetLike.instSubtypeSet + +namespace Sublattice + +variable {X : Type*} {L : Sublattice (Set X)} + +variable {S T : L} {x : X} + +@[ext] lemma ext_mem (h : ∀ x, x ∈ S ↔ x ∈ T) : S = T := SetLike.ext h + +lemma mem_subtype : x ∈ L.subtype T ↔ x ∈ T := Iff.rfl + +@[simp] lemma setLike_mem_inf : x ∈ S ⊓ T ↔ x ∈ S ∧ x ∈ T := by simp [← mem_subtype] +@[simp] lemma setLike_mem_sup : x ∈ S ⊔ T ↔ x ∈ S ∨ x ∈ T := by simp [← mem_subtype] + +@[simp] lemma setLike_mem_coe : x ∈ T.val ↔ x ∈ T := Iff.rfl +@[simp] lemma setLike_mem_mk (U : Set X) (h : U ∈ L) : x ∈ (⟨U, h⟩ : L) ↔ x ∈ U := Iff.rfl + +end Sublattice + +namespace CompleteSublattice + +variable {X : Type*} {L : CompleteSublattice (Set X)} + +variable {S T : L} {𝒮 : Set L} {I : Sort*} {f : I → L} {x : X} + +@[ext] lemma ext (h : ∀ x, x ∈ S ↔ x ∈ T) : S = T := SetLike.ext h + +lemma mem_subtype : x ∈ L.subtype T ↔ x ∈ T := Iff.rfl + +@[simp] lemma mem_inf : x ∈ S ⊓ T ↔ x ∈ S ∧ x ∈ T := by simp [← mem_subtype] +@[simp] lemma mem_sInf : x ∈ sInf 𝒮 ↔ ∀ T ∈ 𝒮, x ∈ T := by simp [← mem_subtype] +@[simp] lemma mem_iInf : x ∈ ⨅ i : I, f i ↔ ∀ i : I, x ∈ f i := by simp [← mem_subtype] +@[simp] lemma mem_top : x ∈ (⊤ : L) := by simp [← mem_subtype] + +@[simp] lemma mem_sup : x ∈ S ⊔ T ↔ x ∈ S ∨ x ∈ T := by simp [← mem_subtype] +@[simp] lemma mem_sSup : x ∈ sSup 𝒮 ↔ ∃ T ∈ 𝒮, x ∈ T := by simp [← mem_subtype] +@[simp] lemma mem_iSup : x ∈ ⨆ i : I, f i ↔ ∃ i : I, x ∈ f i := by simp [← mem_subtype] +@[simp] lemma not_mem_bot : ¬ x ∈ (⊥ : L) := by simp [← mem_subtype] + +@[simp] lemma mem_mk (U : Set X) (h : U ∈ L) : x ∈ (⟨U, h⟩ : L) ↔ x ∈ U := Iff.rfl + +end CompleteSublattice diff --git a/Mathlib/SetTheory/Descriptive/Tree.lean b/Mathlib/SetTheory/Descriptive/Tree.lean new file mode 100644 index 0000000000000..43a7f2f810ce2 --- /dev/null +++ b/Mathlib/SetTheory/Descriptive/Tree.lean @@ -0,0 +1,46 @@ +/- +Copyright (c) 2024 Sven Manthe. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sven Manthe +-/ +import Mathlib.Order.CompleteLattice.SetLike + +/-! +# Trees in the sense of descriptive set theory + +This file defines trees of depth `ω` in the sense of descriptive set theory as sets of finite +sequences that are stable under taking prefixes. + +## Main declarations + +* `tree A`: a (possibly infinite) tree of depth at most `ω` with nodes in `A` +-/ + +namespace Descriptive + +/-- A tree is a set of finite sequences, implemented as `List A`, that is stable under + taking prefixes. For the definition we use the equivalent property `x ++ [a] ∈ T → x ∈ T`, + which is more convenient to check. We define `tree A` as a complete sublattice of + `Set (List A)`, which coerces to the type of trees on `A`. -/ +def tree (A : Type*) : CompleteSublattice (Set (List A)) := + CompleteSublattice.mk' {T | ∀ ⦃x : List A⦄ ⦃a : A⦄, x ++ [a] ∈ T → x ∈ T} + (by rintro S hS x a ⟨t, ht, hx⟩; use t, ht, hS ht hx) + (by rintro S hS x a h T hT; exact hS hT <| h T hT) + +instance (A : Type*) : SetLike (tree A) (List A) := SetLike.instSubtypeSet + +variable {A : Type*} {T : tree A} + +lemma mem_of_append {x y : List A} (h : x ++ y ∈ T) : x ∈ T := by + induction' y with y ys ih generalizing x + · simpa using h + · exact T.prop (ih (by simpa)) + +lemma mem_of_prefix {x y : List A} (h' : x <+: y) (h : y ∈ T) : x ∈ T := by + obtain ⟨_, rfl⟩ := h'; exact mem_of_append h + +@[simp] lemma tree_eq_bot : T = ⊥ ↔ [] ∉ T where + mp := by rintro rfl; simp + mpr h := by ext x; simpa using fun h' ↦ h <| mem_of_prefix x.nil_prefix h' + +end Descriptive From ed60c9dda28949866558c8535af385e336ed2fd7 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 27 Jan 2025 14:13:36 +0000 Subject: [PATCH 565/681] feat(Algebra/Category): `ConcreteCategory` instances for rings (#20815) This is a step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This PR adds a `ConcreteCategory` instance for the categories of rings: `SemiRingCat`, `RingCat`, `CommSemiRingCat` and `CommRingCat`. It also replaces the `Hom.hom` structure projection with an alias for `ConcreteCategory.hom`. The latter requires a few fixes downstream where things get mistakenly unfolded (especially involving `ModuleCat.restrictScalars`) or where `rw` doesn't see through the definitional equality `ConcreteCategory.hom (ConcreteCategory.ofHom f) = f`. Finally, a few places where the proof works around the old `forget` <-> `FunLike` mismatch, and needs updating. I have not tried to look for code that can be cleaned up now, only at what broke. I want to get started on cleanup when the other concrete category instances are in. Co-authored-by: Anne Baanen --- .../ModuleCat/Differentials/Presheaf.lean | 3 +- .../Algebra/Category/ModuleCat/Presheaf.lean | 6 +- .../Category/ModuleCat/Presheaf/Sheafify.lean | 8 +- Mathlib/Algebra/Category/Ring/Basic.lean | 180 +++++++++++------- Mathlib/AlgebraicGeometry/AffineScheme.lean | 44 +++-- Mathlib/AlgebraicGeometry/AffineSpace.lean | 8 +- .../Cover/MorphismProperty.lean | 2 +- .../GammaSpecAdjunction.lean | 2 +- Mathlib/AlgebraicGeometry/Gluing.lean | 6 +- .../Morphisms/RingHomProperties.lean | 4 +- .../ProjectiveSpectrum/Basic.lean | 2 +- Mathlib/AlgebraicGeometry/Spec.lean | 2 +- Mathlib/AlgebraicGeometry/StructureSheaf.lean | 5 +- .../LocallyRingedSpace/HasColimits.lean | 7 +- .../LocallyRingedSpace/ResidueField.lean | 2 +- .../RingedSpace/PresheafedSpace/Gluing.lean | 8 +- Mathlib/RingTheory/RingHomProperties.lean | 5 +- 17 files changed, 170 insertions(+), 124 deletions(-) diff --git a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean index da141704256b2..c25122a364ea7 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean @@ -181,7 +181,8 @@ commutative rings. -/ noncomputable def relativeDifferentials' : PresheafOfModules.{u} (R ⋙ forget₂ _ _) where obj X := CommRingCat.KaehlerDifferential (φ'.app X) - map f := CommRingCat.KaehlerDifferential.map (φ'.naturality f) + -- Have to hint `g' := R.map f` below, or it gets unfolded weirdly. + map f := CommRingCat.KaehlerDifferential.map (g' := R.map f) (φ'.naturality f) -- Without `dsimp`, `ext` doesn't pick up the right lemmas. map_id _ := by dsimp; ext; simp map_comp _ _ := by dsimp; ext; simp diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean index a619b7e79f880..3fd18ca3d8336 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean @@ -42,12 +42,12 @@ structure PresheafOfModules where /-- the restriction maps of a presheaf of modules -/ map {X Y : Cᵒᵖ} (f : X ⟶ Y) : obj X ⟶ (ModuleCat.restrictScalars (R.map f).hom).obj (obj Y) map_id (X : Cᵒᵖ) : - map (𝟙 X) = - (ModuleCat.restrictScalarsId' _ (congrArg RingCat.Hom.hom (R.map_id X))).inv.app _ := by + map (𝟙 X) = (ModuleCat.restrictScalarsId' (R.map (𝟙 X)).hom + (congrArg RingCat.Hom.hom (R.map_id X))).inv.app _ := by aesop_cat map_comp {X Y Z : Cᵒᵖ} (f : X ⟶ Y) (g : Y ⟶ Z) : map (f ≫ g) = map f ≫ (ModuleCat.restrictScalars _).map (map g) ≫ - (ModuleCat.restrictScalarsComp' _ _ _ + (ModuleCat.restrictScalarsComp' (R.map f).hom (R.map g).hom (R.map (f ≫ g)).hom (congrArg RingCat.Hom.hom <| R.map_comp f g)).inv.app _ := by aesop_cat namespace PresheafOfModules diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean index 4a8d0a5b70086..a1d35a63c69ed 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean @@ -106,7 +106,7 @@ lemma isCompatible_map_smul : ((r₀.smul m₀).map (whiskerRight φ (forget _)) RingCat.comp_apply] have hb₀ : (φ.app (Opposite.op Z)) b₀ = (A.map (f₁.op ≫ g₁.op)) m := by dsimp [b₀] - erw [NatTrans.naturality_apply, hb₁, Functor.map_comp, comp_apply] + erw [NatTrans.naturality_apply, hb₁, Functor.map_comp, CategoryTheory.comp_apply] have ha₀' : (α.app (Opposite.op Z)) a₀ = (R.map (f₂.op ≫ g₂.op)) r := by rw [ha₀, ← op_comp, fac, op_comp] have hb₀' : (φ.app (Opposite.op Z)) b₀ = (A.map (f₂.op ≫ g₂.op)) m := by @@ -161,7 +161,7 @@ def SMulCandidate.mk' (S : Sieve X.unop) (hS : S ∈ J X.unop) apply A.isSeparated _ _ (J.pullback_stable f.unop hS) rintro Z g hg dsimp at hg - erw [← comp_apply, ← A.val.map_comp, ← NatTrans.naturality_apply, M₀.map_smul] + erw [← CategoryTheory.comp_apply, ← A.val.map_comp, ← NatTrans.naturality_apply, M₀.map_smul] refine (ha _ hg).trans (app_eq_of_isLocallyInjective α φ A.isSeparated _ _ _ _ ?_ ?_) · rw [← RingCat.comp_apply, NatTrans.naturality, RingCat.comp_apply, ha₀] apply (hr₀ _ hg).symm.trans @@ -298,9 +298,9 @@ lemma map_smul : apply A.isSeparated _ _ hS rintro Y f ⟨⟨r₀, (hr₀ : (α.app (Opposite.op Y)).hom r₀ = (R.val.map f.op).hom ((R.val.map π).hom r))⟩, ⟨m₀, hm₀⟩⟩ - rw [← comp_apply, ← Functor.map_comp, + rw [← CategoryTheory.comp_apply, ← Functor.map_comp, map_smul_eq α φ r m (π ≫ f.op) r₀ (by rw [hr₀, Functor.map_comp, RingCat.comp_apply]) m₀ - (by rw [hm₀, Functor.map_comp, comp_apply]), + (by rw [hm₀, Functor.map_comp, CategoryTheory.comp_apply]), map_smul_eq α φ (R.val.map π r) (A.val.map π m) f.op r₀ hr₀ m₀ hm₀] end Sheafify diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index eb6977db75632..8dd6aac24e41d 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -53,18 +53,37 @@ lemma of_carrier (R : SemiRingCat.{u}) : of R = R := rfl variable {R} in /-- The type of morphisms in `SemiRingCat`. -/ @[ext] -structure Hom (R S : SemiRingCat) where +structure Hom (R S : SemiRingCat.{u}) where private mk :: /-- The underlying ring hom. -/ - hom : R →+* S + hom' : R →+* S instance : Category SemiRingCat where Hom R S := Hom R S id R := ⟨RingHom.id R⟩ - comp f g := ⟨g.hom.comp f.hom⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ -instance {R S : SemiRingCat.{u}} : CoeFun (R ⟶ S) (fun _ ↦ R → S) where - coe f := f.hom +instance : ConcreteCategory.{u} SemiRingCat (fun R S => R →+* S) where + hom := Hom.hom' + ofHom f := ⟨f⟩ + +/-- Turn a morphism in `SemiRingCat` back into a `RingHom`. -/ +abbrev Hom.hom {R S : SemiRingCat.{u}} (f : Hom R S) := + ConcreteCategory.hom (C := SemiRingCat) f + +/-- Typecheck a `RingHom` as a morphism in `SemiRingCat`. -/ +abbrev ofHom {R S : Type u} [Semiring R] [Semiring S] (f : R →+* S) : of R ⟶ of S := + ConcreteCategory.ofHom (C := SemiRingCat) f + +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (R S : SemiRingCat) (f : Hom R S) := + f.hom + +initialize_simps_projections Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[simp] lemma hom_id {R : SemiRingCat} : (𝟙 R : R ⟶ R).hom = RingHom.id R := rfl @@ -85,10 +104,7 @@ lemma comp_apply {R S T : SemiRingCat} (f : R ⟶ S) (g : S ⟶ T) (r : R) : lemma hom_ext {R S : SemiRingCat} {f g : R ⟶ S} (hf : f.hom = g.hom) : f = g := Hom.ext hf -/-- Typecheck a `RingHom` as a morphism in `SemiRingCat`. -/ -abbrev ofHom {R S : Type u} [Semiring R] [Semiring S] (f : R →+* S) : of R ⟶ of S := - ⟨f⟩ - +@[simp] lemma hom_ofHom {R S : Type u} [Semiring R] [Semiring S] (f : R →+* S) : (ofHom f).hom = f := rfl @[simp] @@ -120,12 +136,6 @@ lemma hom_inv_apply {R S : SemiRingCat} (e : R ≅ S) (s : S) : e.hom (e.inv s) instance : Inhabited SemiRingCat := ⟨of PUnit⟩ -instance : HasForget.{u} SemiRingCat where - forget := - { obj := fun R => R - map := fun f => f.hom } - forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ - /-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. -/ unif_hint forget_obj_eq_coe (R R' : SemiRingCat) where R ≟ R' ⊢ @@ -154,8 +164,8 @@ instance hasForgetToAddCommMonCat : HasForget₂ SemiRingCat AddCommMonCat where @[simps] def _root_.RingEquiv.toSemiRingCatIso {R S : Type u} [Semiring R] [Semiring S] (e : R ≃+* S) : of R ≅ of S where - hom := ⟨e⟩ - inv := ⟨e.symm⟩ + hom := ofHom e + inv := ofHom e.symm instance forgetReflectIsos : (forget SemiRingCat).ReflectsIsomorphisms where reflects {X Y} f _ := by @@ -197,18 +207,37 @@ lemma of_carrier (R : RingCat.{u}) : of R = R := rfl variable {R} in /-- The type of morphisms in `RingCat`. -/ @[ext] -structure Hom (R S : RingCat) where +structure Hom (R S : RingCat.{u}) where private mk :: /-- The underlying ring hom. -/ - hom : R →+* S + hom' : R →+* S instance : Category RingCat where Hom R S := Hom R S id R := ⟨RingHom.id R⟩ - comp f g := ⟨g.hom.comp f.hom⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ -instance {R S : RingCat.{u}} : CoeFun (R ⟶ S) (fun _ ↦ R → S) where - coe f := f.hom +instance : ConcreteCategory.{u} RingCat (fun R S => R →+* S) where + hom := Hom.hom' + ofHom f := ⟨f⟩ + +/-- Turn a morphism in `RingCat` back into a `RingHom`. -/ +abbrev Hom.hom {R S : RingCat.{u}} (f : Hom R S) := + ConcreteCategory.hom (C := RingCat) f + +/-- Typecheck a `RingHom` as a morphism in `RingCat`. -/ +abbrev ofHom {R S : Type u} [Ring R] [Ring S] (f : R →+* S) : of R ⟶ of S := + ConcreteCategory.ofHom (C := RingCat) f + +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (R S : RingCat) (f : Hom R S) := + f.hom + +initialize_simps_projections Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[simp] lemma hom_id {R : RingCat} : (𝟙 R : R ⟶ R).hom = RingHom.id R := rfl @@ -229,10 +258,7 @@ lemma comp_apply {R S T : RingCat} (f : R ⟶ S) (g : S ⟶ T) (r : R) : lemma hom_ext {R S : RingCat} {f g : R ⟶ S} (hf : f.hom = g.hom) : f = g := Hom.ext hf -/-- Typecheck a `RingHom` as a morphism in `RingCat`. -/ -abbrev ofHom {R S : Type u} [Ring R] [Ring S] (f : R →+* S) : of R ⟶ of S := - ⟨f⟩ - +@[simp] lemma hom_ofHom {R S : Type u} [Ring R] [Ring S] (f : R →+* S) : (ofHom f).hom = f := rfl @[simp] @@ -264,12 +290,6 @@ lemma hom_inv_apply {R S : RingCat} (e : R ≅ S) (s : S) : e.hom (e.inv s) = s instance : Inhabited RingCat := ⟨of PUnit⟩ -instance : HasForget.{u} RingCat where - forget := - { obj := fun R => R - map := fun f => f.hom } - forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ - /-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. An example where this is needed is in applying @@ -302,8 +322,8 @@ instance hasForgetToAddCommGrp : HasForget₂ RingCat AddCommGrp where @[simps] def _root_.RingEquiv.toRingCatIso {R S : Type u} [Ring R] [Ring S] (e : R ≃+* S) : of R ≅ of S where - hom := ⟨e⟩ - inv := ⟨e.symm⟩ + hom := ofHom e + inv := ofHom e.symm instance forgetReflectIsos : (forget RingCat).ReflectsIsomorphisms where reflects {X Y} f _ := by @@ -345,18 +365,37 @@ lemma of_carrier (R : CommSemiRingCat.{u}) : of R = R := rfl variable {R} in /-- The type of morphisms in `CommSemiRingCat`. -/ @[ext] -structure Hom (R S : CommSemiRingCat) where +structure Hom (R S : CommSemiRingCat.{u}) where private mk :: /-- The underlying ring hom. -/ - hom : R →+* S + hom' : R →+* S instance : Category CommSemiRingCat where Hom R S := Hom R S id R := ⟨RingHom.id R⟩ - comp f g := ⟨g.hom.comp f.hom⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ -instance {R S : CommSemiRingCat.{u}} : CoeFun (R ⟶ S) (fun _ ↦ R → S) where - coe f := f.hom +instance : ConcreteCategory.{u} CommSemiRingCat (fun R S => R →+* S) where + hom := Hom.hom' + ofHom f := ⟨f⟩ + +/-- Turn a morphism in `CommSemiRingCat` back into a `RingHom`. -/ +abbrev Hom.hom {R S : CommSemiRingCat.{u}} (f : Hom R S) := + ConcreteCategory.hom (C := CommSemiRingCat) f + +/-- Typecheck a `RingHom` as a morphism in `CommSemiRingCat`. -/ +abbrev ofHom {R S : Type u} [CommSemiring R] [CommSemiring S] (f : R →+* S) : of R ⟶ of S := + ConcreteCategory.ofHom (C := CommSemiRingCat) f + +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (R S : CommSemiRingCat) (f : Hom R S) := + f.hom + +initialize_simps_projections Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[simp] lemma hom_id {R : CommSemiRingCat} : (𝟙 R : R ⟶ R).hom = RingHom.id R := rfl @@ -377,10 +416,7 @@ lemma comp_apply {R S T : CommSemiRingCat} (f : R ⟶ S) (g : S ⟶ T) (r : R) : lemma hom_ext {R S : CommSemiRingCat} {f g : R ⟶ S} (hf : f.hom = g.hom) : f = g := Hom.ext hf -/-- Typecheck a `RingHom` as a morphism in `CommSemiRingCat`. -/ -abbrev ofHom {R S : Type u} [CommSemiring R] [CommSemiring S] (f : R →+* S) : of R ⟶ of S := - ⟨f⟩ - +@[simp] lemma hom_ofHom {R S : Type u} [CommSemiring R] [CommSemiring S] (f : R →+* S) : (ofHom f).hom = f := rfl @@ -413,12 +449,6 @@ lemma hom_inv_apply {R S : CommSemiRingCat} (e : R ≅ S) (s : S) : e.hom (e.inv instance : Inhabited CommSemiRingCat := ⟨of PUnit⟩ -instance : HasForget.{u} CommSemiRingCat where - forget := - { obj := fun R => R - map := fun f => f.hom } - forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ - /-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. -/ unif_hint forget_obj_eq_coe (R R' : CommSemiRingCat) where R ≟ R' ⊢ @@ -449,8 +479,8 @@ instance hasForgetToCommMonCat : HasForget₂ CommSemiRingCat CommMonCat where def _root_.RingEquiv.toCommSemiRingCatIso {R S : Type u} [CommSemiring R] [CommSemiring S] (e : R ≃+* S) : of R ≅ of S where - hom := ⟨e⟩ - inv := ⟨e.symm⟩ + hom := ofHom e + inv := ofHom e.symm instance forgetReflectIsos : (forget CommSemiRingCat).ReflectsIsomorphisms where reflects {X Y} f _ := by @@ -492,18 +522,37 @@ lemma of_carrier (R : CommRingCat.{u}) : of R = R := rfl variable {R} in /-- The type of morphisms in `CommRingCat`. -/ @[ext] -structure Hom (R S : CommRingCat) where +structure Hom (R S : CommRingCat.{u}) where private mk :: /-- The underlying ring hom. -/ - hom : R →+* S + hom' : R →+* S instance : Category CommRingCat where Hom R S := Hom R S id R := ⟨RingHom.id R⟩ - comp f g := ⟨g.hom.comp f.hom⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ -instance {R S : CommRingCat.{u}} : CoeFun (R ⟶ S) (fun _ ↦ R → S) where - coe f := f.hom +instance : ConcreteCategory.{u} CommRingCat (fun R S => R →+* S) where + hom := Hom.hom' + ofHom f := ⟨f⟩ + +/-- The underlying ring hom. -/ +abbrev Hom.hom {R S : CommRingCat.{u}} (f : Hom R S) := + ConcreteCategory.hom (C := CommRingCat) f + +/-- Typecheck a `RingHom` as a morphism in `CommRingCat`. -/ +abbrev ofHom {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) : of R ⟶ of S := + ConcreteCategory.ofHom (C := CommRingCat) f + +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (R S : CommRingCat) (f : Hom R S) := + f.hom + +initialize_simps_projections Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[simp] lemma hom_id {R : CommRingCat} : (𝟙 R : R ⟶ R).hom = RingHom.id R := rfl @@ -524,10 +573,7 @@ lemma comp_apply {R S T : CommRingCat} (f : R ⟶ S) (g : S ⟶ T) (r : R) : lemma hom_ext {R S : CommRingCat} {f g : R ⟶ S} (hf : f.hom = g.hom) : f = g := Hom.ext hf -/-- Typecheck a `RingHom` as a morphism in `CommRingCat`. -/ -abbrev ofHom {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) : of R ⟶ of S := - ⟨f⟩ - +@[simp] lemma hom_ofHom {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) : (ofHom f).hom = f := rfl @@ -560,12 +606,6 @@ lemma hom_inv_apply {R S : CommRingCat} (e : R ≅ S) (s : S) : e.hom (e.inv s) instance : Inhabited CommRingCat := ⟨of PUnit⟩ -instance : HasForget.{u} CommRingCat where - forget := - { obj := fun R => R - map := fun f => f.hom } - forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ - lemma forget_obj {R : CommRingCat} : (forget CommRingCat).obj R = R := rfl /-- This unification hint helps with problems of the form `(forget ?C).obj R =?= carrier R'`. @@ -606,8 +646,8 @@ instance hasForgetToAddCommMonCat : HasForget₂ CommRingCat CommSemiRingCat whe def _root_.RingEquiv.toCommRingCatIso {R S : Type u} [CommRing R] [CommRing S] (e : R ≃+* S) : of R ≅ of S where - hom := ⟨e⟩ - inv := ⟨e.symm⟩ + hom := ofHom e + inv := ofHom e.symm instance forgetReflectIsos : (forget CommRingCat).ReflectsIsomorphisms where reflects {X Y} f _ := by @@ -669,10 +709,10 @@ abbrev CommRingCatMax.{u1, u2} := CommRingCat.{max u1 u2} lemma RingCat.forget_map_apply {R S : RingCat} (f : R ⟶ S) (x : (CategoryTheory.forget RingCat).obj R) : - @DFunLike.coe _ _ _ HasForget.instFunLike f x = f x := + (forget _).map f x = f x := rfl lemma CommRingCat.forget_map_apply {R S : CommRingCat} (f : R ⟶ S) (x : (CategoryTheory.forget CommRingCat).obj R) : - @DFunLike.coe _ _ _ HasForget.instFunLike f x = f x := + (forget _).map f x = f x := rfl diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index a7a71a986a8ca..4772bc08cc2a9 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -630,7 +630,7 @@ lemma appLE_eq_away_map {X Y : Scheme.{u}} (f : X ⟶ Y) {U : Y.Opens} (hU : IsA letI := hV.isLocalization_basicOpen (f.appLE U V e r) ext : 1 apply IsLocalization.ringHom_ext (.powers r) - rw [IsLocalization.Away.map, IsLocalization.map_comp, + rw [IsLocalization.Away.map, CommRingCat.hom_ofHom, IsLocalization.map_comp, RingHom.algebraMap_toAlgebra, RingHom.algebraMap_toAlgebra, ← CommRingCat.hom_comp, ← CommRingCat.hom_comp, Scheme.Hom.appLE_map, Scheme.Hom.map_appLE] @@ -646,7 +646,7 @@ lemma app_basicOpen_eq_away_map {X Y : Scheme.{u}} (f : X ⟶ Y) {U : Y.Opens} haveI := h.isLocalization_basicOpen (f.app U r) ext : 1 apply IsLocalization.ringHom_ext (.powers r) - rw [IsLocalization.Away.map, CommRingCat.hom_comp, RingHom.comp_assoc, + rw [IsLocalization.Away.map, CommRingCat.hom_comp, RingHom.comp_assoc, CommRingCat.hom_ofHom, IsLocalization.map_comp, RingHom.algebraMap_toAlgebra, RingHom.algebraMap_toAlgebra, ← RingHom.comp_assoc, ← CommRingCat.hom_comp, ← CommRingCat.hom_comp, ← X.presheaf.map_comp] @@ -817,31 +817,35 @@ def SpecMapRestrictBasicOpenIso {R S : CommRingCat} (f : R ⟶ S) (r : R) : Arrow.mk (Spec.map <| CommRingCat.ofHom (Localization.awayMap f.hom r)) := by letI e₁ : Localization.Away r ≃ₐ[R] Γ(Spec R, basicOpen r) := IsLocalization.algEquiv (Submonoid.powers r) _ _ - letI e₂ : Localization.Away (f r) ≃ₐ[S] Γ(Spec S, basicOpen (f r)) := - IsLocalization.algEquiv (Submonoid.powers (f r)) _ _ + letI e₂ : Localization.Away (f.hom r) ≃ₐ[S] Γ(Spec S, basicOpen (f.hom r)) := + IsLocalization.algEquiv (Submonoid.powers (f.hom r)) _ _ refine Arrow.isoMk ?_ ?_ ?_ · exact (Spec (.of S)).isoOfEq (comap_basicOpen _ _) ≪≫ - (IsAffineOpen.Spec_basicOpen (f r)).isoSpec ≪≫ Scheme.Spec.mapIso e₂.toCommRingCatIso.op + (IsAffineOpen.Spec_basicOpen (f.hom r)).isoSpec ≪≫ Scheme.Spec.mapIso e₂.toCommRingCatIso.op · exact (IsAffineOpen.Spec_basicOpen r).isoSpec ≪≫ Scheme.Spec.mapIso e₁.toCommRingCatIso.op · have := AlgebraicGeometry.IsOpenImmersion.of_isLocalization (S := (Localization.Away r)) r rw [← cancel_mono (Spec.map (CommRingCat.ofHom (algebraMap R (Localization.Away r))))] simp only [Arrow.mk_left, Arrow.mk_right, Functor.id_obj, Scheme.isoOfEq_rfl, Iso.refl_trans, - Iso.trans_hom, Functor.mapIso_hom, Iso.op_hom, Iso.symm_hom, - Scheme.Spec_map, Quiver.Hom.unop_op, Arrow.mk_hom, Category.assoc, - ← Spec.map_comp] - show _ ≫ Spec.map (CommRingCat.ofHom - ((e₂.toRingHom.comp (Localization.awayMap f.hom r)).comp (algebraMap R _))) - = _ ≫ _ ≫ Spec.map (CommRingCat.ofHom (e₁.toRingHom.comp (algebraMap R _))) - rw [RingHom.comp_assoc] - conv => enter [1,2,1,1,2]; tactic => exact IsLocalization.map_comp _ - rw [← RingHom.comp_assoc] - conv => enter [1,2,1,1,1]; tactic => exact e₂.toAlgHom.comp_algebraMap - conv => enter [2,2,2,1,1]; tactic => exact e₁.toAlgHom.comp_algebraMap - show _ ≫ Spec.map (f ≫ (Scheme.ΓSpecIso S).inv ≫ - (Spec S).presheaf.map (homOfLE le_top).op) = - Spec.map f ∣_ basicOpen r ≫ _ ≫ Spec.map ((Scheme.ΓSpecIso R).inv ≫ - (Spec R).presheaf.map (homOfLE le_top).op) + Iso.trans_hom, Functor.mapIso_hom, Iso.op_hom, Scheme.Spec_map, Quiver.Hom.unop_op, + Arrow.mk_hom, Category.assoc, ← Spec.map_comp] + conv => + congr + · enter [2, 1]; tactic => + show _ = + (f ≫ (Scheme.ΓSpecIso S).inv ≫ (Spec S).presheaf.map (homOfLE le_top).op) + ext + simp only [Localization.awayMap, IsLocalization.Away.map, AlgEquiv.toRingEquiv_eq_coe, + RingEquiv.toCommRingCatIso_hom, AlgEquiv.toRingEquiv_toRingHom, CommRingCat.hom_comp, + CommRingCat.hom_ofHom, RingHom.comp_apply, IsLocalization.map_eq, RingHom.coe_coe, + AlgEquiv.commutes, IsAffineOpen.algebraMap_Spec_obj] + · enter [2, 2, 1]; tactic => + show _ = (Scheme.ΓSpecIso R).inv ≫ (Spec R).presheaf.map (homOfLE le_top).op + ext + simp only [AlgEquiv.toRingEquiv_eq_coe, RingEquiv.toCommRingCatIso_hom, + AlgEquiv.toRingEquiv_toRingHom, CommRingCat.hom_comp, CommRingCat.hom_ofHom, + RingHom.coe_comp, RingHom.coe_coe, Function.comp_apply, AlgEquiv.commutes, + IsAffineOpen.algebraMap_Spec_obj, homOfLE_leOfHom] simp only [IsAffineOpen.isoSpec_hom, homOfLE_leOfHom, Spec.map_comp, Category.assoc, Scheme.Opens.toSpecΓ_SpecMap_map_assoc, Scheme.Opens.toSpecΓ_top, Scheme.homOfLE_ι_assoc, morphismRestrict_ι_assoc] diff --git a/Mathlib/AlgebraicGeometry/AffineSpace.lean b/Mathlib/AlgebraicGeometry/AffineSpace.lean index e845edc496140..b8779620b2064 100644 --- a/Mathlib/AlgebraicGeometry/AffineSpace.lean +++ b/Mathlib/AlgebraicGeometry/AffineSpace.lean @@ -89,7 +89,7 @@ def toSpecMvPolyIntEquiv : (X ⟶ Spec ℤ[n]) ≃ (n → Γ(X, ⊤)) where Iso.cancel_iso_inv_left, ← Iso.eq_inv_comp] apply of_mvPolynomial_int_ext intro i - rw [coe_eval₂Hom, eval₂_X] + rw [ConcreteCategory.hom_ofHom, coe_eval₂Hom, eval₂_X] rfl right_inv v := by ext i @@ -203,7 +203,7 @@ def isoOfIsAffine [IsAffine S] : ext : 1 apply ringHom_ext' · show _ = (CommRingCat.ofHom C ≫ _).hom - rw [CommRingCat.hom_comp, RingHom.comp_assoc, eval₂Hom_comp_C, + rw [CommRingCat.hom_comp, RingHom.comp_assoc, CommRingCat.hom_ofHom, eval₂Hom_comp_C, ← CommRingCat.hom_comp, ← CommRingCat.hom_ext_iff, ← cancel_mono (Scheme.ΓSpecIso _).hom] rw [← Scheme.comp_appTop, homOfVector_over, Scheme.comp_appTop] @@ -212,7 +212,7 @@ def isoOfIsAffine [IsAffine S] : rw [← Scheme.comp_appTop_assoc, Scheme.isoSpec, asIso_inv, IsIso.hom_inv_id] simp · intro i - rw [CommRingCat.comp_apply, coe_eval₂Hom] + rw [CommRingCat.comp_apply, ConcreteCategory.hom_ofHom, coe_eval₂Hom] simp only [eval₂_X] exact homOfVector_appTop_coord _ _ _ @@ -328,7 +328,7 @@ lemma map_Spec_map {R S : CommRingCat.{max u v}} (φ : R ⟶ S) : conv_lhs => enter[2]; tactic => exact map_appTop_coord _ _ conv_rhs => enter[2]; tactic => exact SpecIso_inv_appTop_coord _ _ rw [SpecIso_inv_appTop_coord, ← CommRingCat.comp_apply, ← Scheme.ΓSpecIso_inv_naturality, - CommRingCat.comp_apply, map_X] + CommRingCat.comp_apply, ConcreteCategory.hom_ofHom, map_X] /-- The map between affine spaces over affine bases is isomorphic to the natural map between polynomial rings. -/ diff --git a/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean b/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean index 87849e46136ca..042468ac880d9 100644 --- a/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean +++ b/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean @@ -113,7 +113,7 @@ def Cover.bind [P.IsStableUnderComposition] (f : ∀ x : 𝒰.J, (𝒰.obj x).Co rcases (f (𝒰.f x)).covers y with ⟨z, hz⟩ change x ∈ Set.range ((f (𝒰.f x)).map ((f (𝒰.f x)).f y) ≫ 𝒰.map (𝒰.f x)).base use z - erw [comp_apply] + erw [CategoryTheory.comp_apply] rw [hz, hy] map_prop _ := P.comp_mem _ _ ((f _).map_prop _) (𝒰.map_prop _) diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index f7d458c2b79a6..2506ebe79df0c 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -139,7 +139,7 @@ theorem toΓSpecCApp_iff -- Porting Note: Type class problem got stuck in `IsLocalization.Away.AwayMap.lift_comp` -- created instance manually. This replaces the `pick_goal` tactics have loc_inst := IsLocalization.to_basicOpen (Γ.obj (op X)) r - refine CommRingCat.hom_ext_iff.trans ?_ + refine ConcreteCategory.ext_iff.trans ?_ rw [← @IsLocalization.Away.lift_comp _ _ _ _ _ _ _ r loc_inst _ (X.isUnit_res_toΓSpecMapBasicOpen r)] --pick_goal 5; exact is_localization.to_basic_open _ r diff --git a/Mathlib/AlgebraicGeometry/Gluing.lean b/Mathlib/AlgebraicGeometry/Gluing.lean index bcdfd0adfd772..2d70705beae89 100644 --- a/Mathlib/AlgebraicGeometry/Gluing.lean +++ b/Mathlib/AlgebraicGeometry/Gluing.lean @@ -227,7 +227,7 @@ theorem ι_eq_iff (i j : D.J) (x : (D.U i).carrier) (y : (D.U j).carrier) : (TopCat.GlueData.ι_eq_iff_rel D.toLocallyRingedSpaceGlueData.toSheafedSpaceGlueData.toPresheafedSpaceGlueData.toTopGlueData i j x y) - rw [← ((TopCat.mono_iff_injective D.isoCarrier.inv).mp _).eq_iff, ← comp_apply] + rw [← ((TopCat.mono_iff_injective D.isoCarrier.inv).mp _).eq_iff, ← CategoryTheory.comp_apply] · simp_rw [← D.ι_isoCarrier_inv] rfl -- `rfl` was not needed before https://github.com/leanprover-community/mathlib4/pull/13170 · infer_instance @@ -339,7 +339,7 @@ theorem fromGlued_injective : Function.Injective 𝒰.fromGlued.base := by intro x y h obtain ⟨i, x, rfl⟩ := 𝒰.gluedCover.ι_jointly_surjective x obtain ⟨j, y, rfl⟩ := 𝒰.gluedCover.ι_jointly_surjective y - rw [← comp_apply, ← comp_apply] at h + rw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply] at h simp_rw [← Scheme.comp_base] at h rw [ι_fromGlued, ι_fromGlued] at h let e := @@ -389,7 +389,7 @@ instance : Epi 𝒰.fromGlued.base := by intro x obtain ⟨y, h⟩ := 𝒰.covers x use (𝒰.gluedCover.ι (𝒰.f x)).base y - rw [← comp_apply] + rw [← CategoryTheory.comp_apply] rw [← 𝒰.ι_fromGlued (𝒰.f x)] at h exact h diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index 9f07373d33dce..625901a76887e 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -158,7 +158,7 @@ theorem sourceAffineLocally_isLocal (h₁ : RingHom.RespectsIso P) simpa using hU rw [← f.appLE_congr _ rfl this (fun f => P f.hom), IsAffineOpen.appLE_eq_away_map f (isAffineOpen_top Y) U.2 _ r] - simp only + simp only [CommRingCat.hom_ofHom] apply (config := { allowSynthFailures := true }) h₂ exact H U · introv hs hs' U @@ -167,7 +167,7 @@ theorem sourceAffineLocally_isLocal (h₁ : RingHom.RespectsIso P) simp_rw [sourceAffineLocally_morphismRestrict] at hs' have := hs' r ⟨X.basicOpen (f.appLE ⊤ U le_top r.1), U.2.basicOpen (f.appLE ⊤ U le_top r.1)⟩ (by simp [Scheme.Hom.appLE]) - rwa [IsAffineOpen.appLE_eq_away_map f (isAffineOpen_top Y) U.2, + rwa [IsAffineOpen.appLE_eq_away_map f (isAffineOpen_top Y) U.2, CommRingCat.hom_ofHom, ← h₁.is_localization_away_iff] at this variable {P} diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Basic.lean index 16327672ba49a..8a215ab44a022 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Basic.lean @@ -179,7 +179,7 @@ lemma awayMap_awayToSection : obtain ⟨⟨n, a, ⟨b, hb'⟩, i, rfl : _ = b⟩, rfl⟩ := mk_surjective a simp only [homOfLE_leOfHom, CommRingCat.hom_comp, RingHom.coe_comp, Function.comp_apply] erw [ProjectiveSpectrum.Proj.awayToSection_apply] - rw [val_awayMap_mk, Localization.mk_eq_mk', IsLocalization.map_mk', + rw [CommRingCat.hom_ofHom, val_awayMap_mk, Localization.mk_eq_mk', IsLocalization.map_mk', ← Localization.mk_eq_mk'] refine Localization.mk_eq_mk_iff.mpr ?_ rw [Localization.r_iff_exists] diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index fe628dda5c4cb..26b9f817d1bf5 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -420,7 +420,7 @@ instance isLocalizedModule_toPushforwardStalkAlgHom : change PrimeSpectrum.basicOpen r ≤ U at hrU apply_fun (Spec.topMap (CommRingCat.ofHom (algebraMap R S)) _* (structureSheaf S).1).map (homOfLE hrU).op at e - simp only [Functor.op_map, map_zero, ← comp_apply, toOpen_res] at e + simp only [Functor.op_map, map_zero, ← CategoryTheory.comp_apply, toOpen_res] at e have : toOpen S (PrimeSpectrum.basicOpen <| algebraMap R S r) x = 0 := by refine Eq.trans ?_ e; rfl have := diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index 55c3b14a35165..9e79bc6c7f8b9 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -947,9 +947,8 @@ theorem localizationToStalk_stalkSpecializes {R : Type*} [CommRing R] {x y : Pri StructureSheaf.localizationToStalk R x := by ext : 1 apply IsLocalization.ringHom_ext (S := Localization.AtPrime y.asIdeal) y.asIdeal.primeCompl - erw [RingHom.comp_assoc] - conv_rhs => erw [RingHom.comp_assoc] - dsimp [CommRingCat.ofHom, localizationToStalk, PrimeSpectrum.localizationMapOfSpecializes] + rw [CommRingCat.hom_comp, RingHom.comp_assoc, CommRingCat.hom_comp, RingHom.comp_assoc] + dsimp [localizationToStalk, PrimeSpectrum.localizationMapOfSpecializes] rw [IsLocalization.lift_comp, IsLocalization.lift_comp, IsLocalization.lift_comp] exact CommRingCat.hom_ext_iff.mp (toStalk_stalkSpecializes h) diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean index e05dffc7df37d..a4c26869dcdfe 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean @@ -227,9 +227,10 @@ theorem coequalizer_π_stalk_isLocalHom (x : Y) : constructor rintro a ha rcases TopCat.Presheaf.germ_exist _ _ a with ⟨U, hU, s, rfl⟩ - rw [← CommRingCat.forget_map_apply, PresheafedSpace.stalkMap_germ_apply - (coequalizer.π (C := SheafedSpace _) f.toShHom g.toShHom) U _ hU] at ha - rw [CommRingCat.forget_map_apply] + rw [← CommRingCat.forget_map_apply, forget_map_eq_coe, + PresheafedSpace.stalkMap_germ_apply + (coequalizer.π (C := SheafedSpace _) f.toShHom g.toShHom) U _ hU] at ha + rw [coe_toHasForget_instFunLike] let V := imageBasicOpen f g U s have hV : (coequalizer.π f.toShHom g.toShHom).base ⁻¹' ((coequalizer.π f.toShHom g.toShHom).base '' V.1) = V.1 := diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean index e96b86ffdeceb..5120aff056674 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean @@ -113,7 +113,7 @@ lemma residueFieldMap_comp {Z : LocallyRingedSpace.{u}} (g : Y ⟶ Z) (x : X) : simp only [comp_toShHom, SheafedSpace.comp_base, Function.comp_apply, residueFieldMap, CommRingCat.hom_comp, TopCat.comp_app] simp_rw [stalkMap_comp] - apply IsLocalRing.ResidueField.map_comp + apply IsLocalRing.ResidueField.map_comp (Hom.stalkMap g (f.base x)).hom (Hom.stalkMap f x).hom @[reassoc] lemma evaluation_naturality {V : Opens Y} (x : (Opens.map f.base).obj V) : diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index c3fefa900b490..912cb224dd41a 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -192,14 +192,16 @@ theorem snd_invApp_t_app' (i j k : D.J) (U : Opens (pullback (D.f i j) (D.f i k) rw [this, Set.image_comp, Set.image_comp, Set.preimage_image_eq] swap · refine Function.HasLeftInverse.injective ⟨(D.t i k).base, fun x => ?_⟩ - rw [← comp_apply, ← comp_base, D.t_inv, id_base, id_apply] + rw [← CategoryTheory.comp_apply, ← comp_base, D.t_inv, id_base, CategoryTheory.id_apply] refine congr_arg (_ '' ·) ?_ refine congr_fun ?_ _ refine Set.image_eq_preimage_of_inverse ?_ ?_ · intro x - rw [← comp_apply, ← comp_base, IsIso.inv_hom_id, id_base, id_apply] + rw [← CategoryTheory.comp_apply, ← comp_base, IsIso.inv_hom_id, id_base, + CategoryTheory.id_apply] · intro x - rw [← comp_apply, ← comp_base, IsIso.hom_inv_id, id_base, id_apply] + rw [← CategoryTheory.comp_apply, ← comp_base, IsIso.hom_inv_id, id_base, + CategoryTheory.id_apply] · rw [← IsIso.eq_inv_comp, IsOpenImmersion.inv_invApp, Category.assoc, (D.t' k i j).c.naturality_assoc] simp_rw [← Category.assoc] diff --git a/Mathlib/RingTheory/RingHomProperties.lean b/Mathlib/RingTheory/RingHomProperties.lean index c2ac311deb389..ae523c83039b3 100644 --- a/Mathlib/RingTheory/RingHomProperties.lean +++ b/Mathlib/RingTheory/RingHomProperties.lean @@ -48,14 +48,13 @@ theorem RespectsIso.cancel_left_isIso (hP : RespectsIso @P) {R S T : CommRingCat (g : S ⟶ T) [IsIso f] : P (g.hom.comp f.hom) ↔ P g.hom := ⟨fun H => by convert hP.2 (f ≫ g).hom (asIso f).symm.commRingCatIsoToRingEquiv H - exact (IsIso.inv_hom_id_assoc _ _).symm, hP.2 g.hom (asIso f).commRingCatIsoToRingEquiv⟩ + simp [← CommRingCat.hom_comp], hP.2 g.hom (asIso f).commRingCatIsoToRingEquiv⟩ theorem RespectsIso.cancel_right_isIso (hP : RespectsIso @P) {R S T : CommRingCat} (f : R ⟶ S) (g : S ⟶ T) [IsIso g] : P (g.hom.comp f.hom) ↔ P f.hom := ⟨fun H => by convert hP.1 (f ≫ g).hom (asIso g).symm.commRingCatIsoToRingEquiv H - change f = f ≫ g ≫ inv g - simp, hP.1 f.hom (asIso g).commRingCatIsoToRingEquiv⟩ + simp [← CommRingCat.hom_comp], hP.1 f.hom (asIso g).commRingCatIsoToRingEquiv⟩ theorem RespectsIso.is_localization_away_iff (hP : RingHom.RespectsIso @P) {R S : Type u} (R' S' : Type u) [CommRing R] [CommRing S] [CommRing R'] [CommRing S'] [Algebra R R'] From 12422efb2dba88b50549bcc26bf9fd547626feca Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 27 Jan 2025 14:13:37 +0000 Subject: [PATCH 566/681] chore(Data/Matrix/PEquiv): clean up names (#21108) This renames and deprecates: * `PEquiv.mul_matrix_apply` -> `PEquiv.toMatrix_mul_apply` * `PEquiv.matrix_mul_apply` -> `PEquiv.mul_toMatrix_apply` * `PEquiv.toPEquiv_mul_matrix` -> `PEquiv.toMatrix_toPEquiv_mul` * `PEquiv.mul_toPEquiv_toMatrix` -> `PEquiv.mul_toMatrix_toPEquiv` * `PEquiv.equiv_toPEquiv_toMatrix` -> `PEquiv.toMatrix_toPEquiv_eq` Also adds two more convenience lemmas, and removes an unused `classical` tactic. --- Mathlib/Data/Matrix/PEquiv.lean | 82 ++++++++++++------- Mathlib/Data/PEquiv.lean | 1 + Mathlib/LinearAlgebra/Matrix/Permutation.lean | 2 +- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/Mathlib/Data/Matrix/PEquiv.lean b/Mathlib/Data/Matrix/PEquiv.lean index 17259b93851a3..632eaa239a6fa 100644 --- a/Mathlib/Data/Matrix/PEquiv.lean +++ b/Mathlib/Data/Matrix/PEquiv.lean @@ -55,13 +55,28 @@ theorem toMatrix_apply [DecidableEq n] [Zero α] [One α] (f : m ≃. n) (i j) : toMatrix f i j = if j ∈ f i then (1 : α) else 0 := rfl -theorem mul_matrix_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α) +theorem toMatrix_mul_apply [Fintype m] [DecidableEq m] [Semiring α] (f : l ≃. m) (M : Matrix m n α) (i j) : (f.toMatrix * M :) i j = Option.casesOn (f i) 0 fun fi => M fi j := by dsimp [toMatrix, Matrix.mul_apply] cases' h : f i with fi · simp [h] · rw [Finset.sum_eq_single fi] <;> simp +contextual [h, eq_comm] +@[deprecated (since := "2025-01-27")] alias mul_matrix_apply := toMatrix_mul_apply + +theorem mul_toMatrix_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n) + (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 (M i) := by + dsimp [Matrix.mul_apply, toMatrix_apply] + cases' h : f.symm j with fj + · simp [h, ← f.eq_some_iff] + · rw [Finset.sum_eq_single fj] + · simp [h, ← f.eq_some_iff] + · rintro b - n + simp [h, ← f.eq_some_iff, n.symm] + · simp + +@[deprecated (since := "2025-01-27")] alias matrix_mul_apply := mul_toMatrix_apply + theorem toMatrix_symm [DecidableEq m] [DecidableEq n] [Zero α] [One α] (f : m ≃. n) : (f.symm.toMatrix : Matrix n m α) = f.toMatrixᵀ := by ext @@ -74,32 +89,38 @@ theorem toMatrix_refl [DecidableEq n] [Zero α] [One α] : ext simp [toMatrix_apply, one_apply] -theorem matrix_mul_apply [Fintype m] [Semiring α] [DecidableEq n] (M : Matrix l m α) (f : m ≃. n) - (i j) : (M * f.toMatrix :) i j = Option.casesOn (f.symm j) 0 fun fj => M i fj := by - dsimp [toMatrix, Matrix.mul_apply] - cases' h : f.symm j with fj - · simp [h, ← f.eq_some_iff] - · rw [Finset.sum_eq_single fj] - · simp [h, ← f.eq_some_iff] - · rintro b - n - simp [h, ← f.eq_some_iff, n.symm] - · simp +@[simp] +theorem toMatrix_toPEquiv_apply [DecidableEq n] [Zero α] [One α] (f : m ≃ n) (i) : + f.toPEquiv.toMatrix i = Pi.single (f i) (1 : α) := by + ext + simp [toMatrix_apply, Pi.single_apply, eq_comm] -theorem toPEquiv_mul_matrix [Fintype m] [DecidableEq m] [Semiring α] (f : m ≃ m) +@[simp] +theorem transpose_toMatrix_toPEquiv_apply + [DecidableEq m] [DecidableEq n] [Zero α] [One α] (f : m ≃ n) (j) : + f.toPEquiv.toMatrixᵀ j = Pi.single (f.symm j) (1 : α) := by + ext + simp [toMatrix_apply, Pi.single_apply, eq_comm, ← Equiv.apply_eq_iff_eq_symm_apply] + +theorem toMatrix_toPEquiv_mul [Fintype m] [DecidableEq m] [Semiring α] (f : m ≃ m) (M : Matrix m n α) : f.toPEquiv.toMatrix * M = M.submatrix f id := by ext i j - rw [mul_matrix_apply, Equiv.toPEquiv_apply, submatrix_apply, id] + rw [toMatrix_mul_apply, Equiv.toPEquiv_apply, submatrix_apply, id] -theorem mul_toPEquiv_toMatrix {m n α : Type*} [Fintype n] [DecidableEq n] [Semiring α] (f : n ≃ n) +@[deprecated (since := "2025-01-27")] alias toPEquiv_mul_matrix := toMatrix_toPEquiv_mul + +theorem mul_toMatrix_toPEquiv {m n α : Type*} [Fintype n] [DecidableEq n] [Semiring α] (f : n ≃ n) (M : Matrix m n α) : M * f.toPEquiv.toMatrix = M.submatrix id f.symm := Matrix.ext fun i j => by - rw [PEquiv.matrix_mul_apply, ← Equiv.toPEquiv_symm, Equiv.toPEquiv_apply, + rw [PEquiv.mul_toMatrix_apply, ← Equiv.toPEquiv_symm, Equiv.toPEquiv_apply, Matrix.submatrix_apply, id] +@[deprecated (since := "2025-01-27")] alias mul_toPEquiv_toMatrix := mul_toMatrix_toPEquiv + theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m) (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by ext i j - rw [mul_matrix_apply] + rw [toMatrix_mul_apply] dsimp [toMatrix, PEquiv.trans] cases f i <;> simp @@ -110,19 +131,18 @@ theorem toMatrix_bot [DecidableEq n] [Zero α] [One α] : theorem toMatrix_injective [DecidableEq n] [MonoidWithZero α] [Nontrivial α] : Function.Injective (@toMatrix m n α _ _ _) := by - classical - intro f g - refine not_imp_not.1 ?_ - simp only [Matrix.ext_iff.symm, toMatrix_apply, PEquiv.ext_iff, not_forall, exists_imp] - intro i hi - use i - cases' hf : f i with fi - · cases' hg : g i with gi - · rw [hf, hg] at hi; exact (hi rfl).elim - · use gi - simp - · use fi - simp [hf.symm, Ne.symm hi] + intro f g + refine not_imp_not.1 ?_ + simp only [Matrix.ext_iff.symm, toMatrix_apply, PEquiv.ext_iff, not_forall, exists_imp] + intro i hi + use i + cases' hf : f i with fi + · cases' hg : g i with gi + · rw [hf, hg] at hi; exact (hi rfl).elim + · use gi + simp + · use fi + simp [hf.symm, Ne.symm hi] theorem toMatrix_swap [DecidableEq n] [Ring α] (i j : n) : (Equiv.swap i j).toPEquiv.toMatrix = @@ -152,8 +172,10 @@ theorem single_mul_single_right [Fintype n] [Fintype k] [DecidableEq n] [Decidab rw [← Matrix.mul_assoc, single_mul_single] /-- We can also define permutation matrices by permuting the rows of the identity matrix. -/ -theorem equiv_toPEquiv_toMatrix [DecidableEq n] [Zero α] [One α] (σ : Equiv n n) : +theorem toMatrix_toPEquiv_eq [DecidableEq n] [Zero α] [One α] (σ : Equiv.Perm n) : σ.toPEquiv.toMatrix = (1 : Matrix n n α).submatrix σ id := Matrix.ext fun _ _ => if_congr Option.some_inj rfl rfl +@[deprecated (since := "2025-01-27")] alias equiv_toPEquiv_toMatrix := toMatrix_toPEquiv_eq + end PEquiv diff --git a/Mathlib/Data/PEquiv.lean b/Mathlib/Data/PEquiv.lean index 007830364ceb2..fa6cbb13d14d7 100644 --- a/Mathlib/Data/PEquiv.lean +++ b/Mathlib/Data/PEquiv.lean @@ -432,6 +432,7 @@ theorem toPEquiv_trans (f : α ≃ β) (g : β ≃ γ) : theorem toPEquiv_symm (f : α ≃ β) : f.symm.toPEquiv = f.toPEquiv.symm := rfl +@[simp] theorem toPEquiv_apply (f : α ≃ β) (x : α) : f.toPEquiv x = some (f x) := rfl diff --git a/Mathlib/LinearAlgebra/Matrix/Permutation.lean b/Mathlib/LinearAlgebra/Matrix/Permutation.lean index 96c0d8f5fc771..990b92bc1ee05 100644 --- a/Mathlib/LinearAlgebra/Matrix/Permutation.lean +++ b/Mathlib/LinearAlgebra/Matrix/Permutation.lean @@ -39,7 +39,7 @@ namespace Matrix /-- The determinant of a permutation matrix equals its sign. -/ @[simp] theorem det_permutation [CommRing R] : det (σ.permMatrix R) = Perm.sign σ := by - rw [← Matrix.mul_one (σ.permMatrix R), PEquiv.toPEquiv_mul_matrix, + rw [← Matrix.mul_one (σ.permMatrix R), PEquiv.toMatrix_toPEquiv_mul, det_permute, det_one, mul_one] /-- The trace of a permutation matrix equals the number of fixed points. -/ From da67df32cd51987bbc2b7db52f0c9ace84f5e13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Renison?= <85908989+IvanRenison@users.noreply.github.com> Date: Mon, 27 Jan 2025 14:51:16 +0000 Subject: [PATCH 567/681] feat(Combinatorics/SimpleGraph): add definitions and theorems about the coloring of sum graphs (#18677) --- Mathlib/Combinatorics/SimpleGraph/Sum.lean | 78 +++++++++++++++++++--- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Sum.lean b/Mathlib/Combinatorics/SimpleGraph/Sum.lean index 25de075d43605..aaf460a2f7c93 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Sum.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Sum.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Iván Renison -/ import Mathlib.Combinatorics.SimpleGraph.Basic +import Mathlib.Combinatorics.SimpleGraph.Coloring import Mathlib.Combinatorics.SimpleGraph.Maps /-! @@ -46,18 +47,12 @@ variable {G : SimpleGraph α} {H : SimpleGraph β} /-- The disjoint sum is commutative up to isomorphism. `Iso.sumComm` as a graph isomorphism. -/ @[simps!] def Iso.sumComm : G ⊕g H ≃g H ⊕g G := ⟨Equiv.sumComm α β, by - intro u v - cases u <;> cases v <;> simp⟩ + rintro (u | u) (v | v) <;> simp⟩ /-- The disjoint sum is associative up to isomorphism. `Iso.sumAssoc` as a graph isomorphism. -/ @[simps!] def Iso.sumAssoc {I : SimpleGraph γ} : (G ⊕g H) ⊕g I ≃g G ⊕g (H ⊕g I) := ⟨Equiv.sumAssoc α β γ, by - intro u v - cases u <;> cases v <;> rename_i u v - · cases u <;> cases v <;> simp - · cases u <;> simp - · cases v <;> simp - · simp⟩ + rintro ((u | u) | u) ((v | v) | v) <;> simp⟩ /-- The embedding of `G` into `G ⊕g H`. -/ @[simps] @@ -73,4 +68,71 @@ def Embedding.sumInr : H ↪g G ⊕g H where inj' u v := by simp map_rel_iff' := by simp +/-- Color `G ⊕g H` with colorings of `G` and `H` -/ +def Coloring.sum (cG : G.Coloring γ) (cH : H.Coloring γ) : (G ⊕g H).Coloring γ where + toFun := Sum.elim cG cH + map_rel' {u v} huv := by cases u <;> cases v <;> simp_all [cG.valid, cH.valid] + +/-- Get coloring of `G` from coloring of `G ⊕g H` -/ +def Coloring.sumLeft (c : (G ⊕g H).Coloring γ) : G.Coloring γ := c.comp Embedding.sumInl.toHom + +/-- Get coloring of `H` from coloring of `G ⊕g H` -/ +def Coloring.sumRight (c : (G ⊕g H).Coloring γ) : H.Coloring γ := c.comp Embedding.sumInr.toHom + +@[simp] +theorem Coloring.sumLeft_sum (cG : G.Coloring γ) (cH : H.Coloring γ) : (cG.sum cH).sumLeft = cG := + rfl + +@[simp] +theorem Coloring.sumRight_sum (cG : G.Coloring γ) (cH : H.Coloring γ) : (cG.sum cH).sumRight = cH := + rfl + +@[simp] +theorem Coloring.sum_sumLeft_sumRight (c : (G ⊕g H).Coloring γ) : c.sumLeft.sum c.sumRight = c := by + ext (u | u) <;> rfl + +/-- Bijection between `(G ⊕g H).Coloring γ` and `G.Coloring γ × H.Coloring γ` -/ +def Coloring.sumEquiv : (G ⊕g H).Coloring γ ≃ G.Coloring γ × H.Coloring γ where + toFun c := ⟨c.sumLeft, c.sumRight⟩ + invFun p := p.1.sum p.2 + left_inv c := by simp [sum_sumLeft_sumRight c] + right_inv p := rfl + +/-- Color `G ⊕g H` with `Fin (n + m)` given a coloring of `G` with `Fin n` and a coloring of `H` +with `Fin m` -/ +def Coloring.sumFin {n m : ℕ} (cG : G.Coloring (Fin n)) (cH : H.Coloring (Fin m)) : + (G ⊕g H).Coloring (Fin (max n m)) := sum + (G.recolorOfEmbedding (Fin.castLEEmb (n.le_max_left m)) cG) + (H.recolorOfEmbedding (Fin.castLEEmb (n.le_max_right m)) cH) + +theorem Colorable.sum_max {n m : ℕ} (hG : G.Colorable n) (hH : H.Colorable m) : + (G ⊕g H).Colorable (max n m) := Nonempty.intro (hG.some.sumFin hH.some) + +theorem Colorable.of_sum_left {n : ℕ} (h : (G ⊕g H).Colorable n) : G.Colorable n := + Nonempty.intro (h.some.sumLeft) + +theorem Colorable.of_sum_right {n : ℕ} (h : (G ⊕g H).Colorable n) : H.Colorable n := + Nonempty.intro (h.some.sumRight) + +@[simp] +theorem colorable_sum {n : ℕ} : (G ⊕g H).Colorable n ↔ G.Colorable n ∧ H.Colorable n := + ⟨fun cGH => ⟨cGH.of_sum_left, cGH.of_sum_right⟩, + fun ⟨cG, cH⟩ => by rw [← n.max_self]; exact cG.sum_max cH⟩ + +theorem chromaticNumber_le_sum_left : G.chromaticNumber ≤ (G ⊕g H).chromaticNumber := + chromaticNumber_le_of_forall_imp (fun _ h ↦ h.of_sum_left) + +theorem chromaticNumber_le_sum_right : H.chromaticNumber ≤ (G ⊕g H).chromaticNumber := + chromaticNumber_le_of_forall_imp (fun _ h ↦ h.of_sum_right) + +@[simp] +theorem chromaticNumber_sum : + (G ⊕g H).chromaticNumber = max G.chromaticNumber H.chromaticNumber := by + refine eq_max chromaticNumber_le_sum_left chromaticNumber_le_sum_right ?_ + rintro (n | n) hG hH + · simp [show (none : ℕ∞) = (⊤ : ℕ∞) from rfl] + · let cG : G.Coloring (Fin n) := (chromaticNumber_le_iff_colorable.mp hG).some + let cH : H.Coloring (Fin n) := (chromaticNumber_le_iff_colorable.mp hH).some + exact chromaticNumber_le_iff_colorable.mpr (Nonempty.intro (cG.sum cH)) + end SimpleGraph From 6fd88b131fe2627ed11731cd06e96fdab2d599b2 Mon Sep 17 00:00:00 2001 From: Etienne Date: Mon, 27 Jan 2025 14:51:17 +0000 Subject: [PATCH 568/681] feat: a `RelHom` preserves directedness (#20080) If $a : \iota \to \alpha$ is directed with respect to $r$, and $f$ is a `RelHom r s` then $f \circ a$ is directed with respect to $s$. Add a `DirectedOn` version. --- Mathlib/Order/RelIso/Set.lean | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Mathlib/Order/RelIso/Set.lean b/Mathlib/Order/RelIso/Set.lean index d52b7837ed95b..90cb227e3edb9 100644 --- a/Mathlib/Order/RelIso/Set.lean +++ b/Mathlib/Order/RelIso/Set.lean @@ -3,6 +3,7 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Mathlib.Order.Directed import Mathlib.Order.RelIso.Basic import Mathlib.Logic.Embedding.Set import Mathlib.Logic.Equiv.Set @@ -35,6 +36,14 @@ theorem map_sup [SemilatticeSup α] [LinearOrder β] [FunLike F β α] a (m ⊔ n) = a m ⊔ a n := map_inf (α := αᵒᵈ) (β := βᵒᵈ) _ _ _ +theorem directed [FunLike F α β] [RelHomClass F r s] {ι : Sort*} {a : ι → α} {f : F} + (ha : Directed r a) : Directed s (f ∘ a) := + ha.mono_comp _ fun _ _ h ↦ map_rel f h + +theorem directedOn [FunLike F α β] [RelHomClass F r s] {f : F} + {t : Set α} (hs : DirectedOn r t) : DirectedOn s (f '' t) := + hs.mono_comp fun _ _ h ↦ map_rel f h + end RelHomClass namespace RelIso From ace1a0644d805a464a61f8eba1812574789d7425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 27 Jan 2025 14:51:19 +0000 Subject: [PATCH 569/681] =?UTF-8?q?chore:=20rename=20the=20fact=20that=20`?= =?UTF-8?q?(=E2=88=80=20a=20<=20a=E2=82=81,=20a=20=E2=89=A4=20a=E2=82=82)?= =?UTF-8?q?=20=E2=86=94=20a=E2=82=81=20=E2=89=A4=20a=E2=82=82`=20in=20a=20?= =?UTF-8?q?dense=20order=20(#20317)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I found those lemma names hard to find, especially because they didn't contain `_of_dense` or didn't contain `lt`. Moves: * `le_of_forall_le_of_dense` → `le_of_forall_gt_imp_ge_of_dense` * `le_of_forall_ge_of_dense` → `le_of_forall_lt_imp_le_of_dense` * `forall_lt_le_iff` → `forall_lt_imp_le_iff_le_of_dense` * `forall_gt_ge_iff` → `forall_gt_imp_ge_iff_le_of_dense` * `eq_of_le_of_forall_le_of_dense` → `eq_of_le_of_forall_lt_imp_le_of_dense` * `eq_of_le_of_forall_ge_of_dense` → `eq_of_le_of_forall_gt_imp_ge_of_dense` --- Mathlib/Algebra/Order/CauSeq/Basic.lean | 2 +- Mathlib/Algebra/Order/Field/Basic.lean | 6 +-- .../Algebra/Order/Group/DenselyOrdered.lean | 4 +- .../Order/Monoid/Unbundled/ExistsOfLE.lean | 2 +- Mathlib/Analysis/Complex/CauchyIntegral.lean | 2 +- Mathlib/Analysis/Complex/Liouville.lean | 2 +- .../Analysis/Complex/PhragmenLindelof.lean | 2 +- Mathlib/Analysis/LocallyConvex/Polar.lean | 2 +- Mathlib/Analysis/Normed/Field/Ultra.lean | 2 +- Mathlib/Analysis/Normed/Module/Dual.lean | 2 +- Mathlib/Data/ENNReal/Inv.lean | 7 +-- Mathlib/Data/NNReal/Defs.lean | 2 +- Mathlib/Data/Real/Archimedean.lean | 4 +- Mathlib/Data/Real/EReal.lean | 2 +- Mathlib/MeasureTheory/Covering/Vitali.lean | 2 +- Mathlib/MeasureTheory/Measure/Hausdorff.lean | 2 +- .../NumberTheory/ModularForms/QExpansion.lean | 2 +- Mathlib/Order/Basic.lean | 45 ++++++++++++------- Mathlib/Order/Bounds/Basic.lean | 2 +- Mathlib/Order/WithBot.lean | 4 +- Mathlib/Topology/EMetricSpace/Defs.lean | 2 +- Mathlib/Topology/MetricSpace/Defs.lean | 2 +- .../Topology/MetricSpace/GromovHausdorff.lean | 2 +- .../MetricSpace/GromovHausdorffRealized.lean | 2 +- .../MetricSpace/HausdorffDimension.lean | 2 +- .../Topology/MetricSpace/Pseudo/Lemmas.lean | 4 +- 26 files changed, 64 insertions(+), 48 deletions(-) diff --git a/Mathlib/Algebra/Order/CauSeq/Basic.lean b/Mathlib/Algebra/Order/CauSeq/Basic.lean index fb76b07c2edb2..b7366261beeea 100644 --- a/Mathlib/Algebra/Order/CauSeq/Basic.lean +++ b/Mathlib/Algebra/Order/CauSeq/Basic.lean @@ -404,7 +404,7 @@ theorem zero_limZero : LimZero (0 : CauSeq β abv) theorem const_limZero {x : β} : LimZero (const x) ↔ x = 0 := ⟨fun H => (abv_eq_zero abv).1 <| - (eq_of_le_of_forall_le_of_dense (abv_nonneg abv _)) fun _ ε0 => + (eq_of_le_of_forall_lt_imp_le_of_dense (abv_nonneg abv _)) fun _ ε0 => let ⟨_, hi⟩ := H _ ε0 le_of_lt <| hi _ le_rfl, fun e => e.symm ▸ zero_limZero⟩ diff --git a/Mathlib/Algebra/Order/Field/Basic.lean b/Mathlib/Algebra/Order/Field/Basic.lean index d2b9446b43e01..5d80dad8dfcfd 100644 --- a/Mathlib/Algebra/Order/Field/Basic.lean +++ b/Mathlib/Algebra/Order/Field/Basic.lean @@ -414,7 +414,7 @@ theorem le_iff_forall_one_lt_le_mul₀ {α : Type*} [LinearOrderedSemifield α] obtain rfl|hb := hb.eq_or_lt · simp_rw [zero_mul] at h exact h 2 one_lt_two - refine le_of_forall_le_of_dense fun x hbx => ?_ + refine le_of_forall_gt_imp_ge_of_dense fun x hbx => ?_ convert h (x / b) ((one_lt_div hb).mpr hbx) rw [mul_div_cancel₀ _ hb.ne'] @@ -755,14 +755,14 @@ private lemma exists_mul_right_lt₀ {a b c : α} (hc : a * b < c) : ∃ b' > b, simp_rw [mul_comm a] at hc ⊢; exact exists_mul_left_lt₀ hc lemma le_mul_of_forall_lt₀ {a b c : α} (h : ∀ a' > a, ∀ b' > b, c ≤ a' * b') : c ≤ a * b := by - refine le_of_forall_le_of_dense fun d hd ↦ ?_ + refine le_of_forall_gt_imp_ge_of_dense fun d hd ↦ ?_ obtain ⟨a', ha', hd⟩ := exists_mul_left_lt₀ hd obtain ⟨b', hb', hd⟩ := exists_mul_right_lt₀ hd exact (h a' ha' b' hb').trans hd.le lemma mul_le_of_forall_lt_of_nonneg {a b c : α} (ha : 0 ≤ a) (hc : 0 ≤ c) (h : ∀ a' ≥ 0, a' < a → ∀ b' ≥ 0, b' < b → a' * b' ≤ c) : a * b ≤ c := by - refine le_of_forall_ge_of_dense fun d d_ab ↦ ?_ + refine le_of_forall_lt_imp_le_of_dense fun d d_ab ↦ ?_ rcases lt_or_le d 0 with hd | hd · exact hd.le.trans hc obtain ⟨a', ha', d_ab⟩ := exists_lt_mul_left_of_nonneg ha hd d_ab diff --git a/Mathlib/Algebra/Order/Group/DenselyOrdered.lean b/Mathlib/Algebra/Order/Group/DenselyOrdered.lean index a019c1739800a..a1bd1983375e5 100644 --- a/Mathlib/Algebra/Order/Group/DenselyOrdered.lean +++ b/Mathlib/Algebra/Order/Group/DenselyOrdered.lean @@ -68,7 +68,7 @@ private lemma exists_mul_right_lt [CommGroup α] [LT α] [DenselyOrdered α] lemma le_mul_of_forall_lt [CommGroup α] [LinearOrder α] [CovariantClass α α (· * ·) (· ≤ ·)] [DenselyOrdered α] {a b c : α} (h : ∀ a' > a, ∀ b' > b, c ≤ a' * b') : c ≤ a * b := by - refine le_of_forall_le_of_dense fun d hd ↦ ?_ + refine le_of_forall_gt_imp_ge_of_dense fun d hd ↦ ?_ obtain ⟨a', ha', hd⟩ := exists_mul_left_lt hd obtain ⟨b', hb', hd⟩ := exists_mul_right_lt hd exact (h a' ha' b' hb').trans hd.le @@ -77,7 +77,7 @@ lemma le_mul_of_forall_lt [CommGroup α] [LinearOrder α] [CovariantClass α α lemma mul_le_of_forall_lt [CommGroup α] [LinearOrder α] [CovariantClass α α (· * ·) (· ≤ ·)] [DenselyOrdered α] {a b c : α} (h : ∀ a' < a, ∀ b' < b, a' * b' ≤ c) : a * b ≤ c := by - refine le_of_forall_ge_of_dense fun d hd ↦ ?_ + refine le_of_forall_lt_imp_le_of_dense fun d hd ↦ ?_ obtain ⟨a', ha', hd⟩ := exists_lt_mul_left hd obtain ⟨b', hb', hd⟩ := exists_lt_mul_right hd exact hd.le.trans (h a' ha' b' hb') diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean index 1bd716addf327..c2e25592e58cd 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean @@ -69,7 +69,7 @@ variable [LinearOrder α] [DenselyOrdered α] [Monoid α] [ExistsMulOfLE α] @[to_additive] theorem le_of_forall_one_lt_le_mul (h : ∀ ε : α, 1 < ε → a ≤ b * ε) : a ≤ b := - le_of_forall_le_of_dense fun x hxb => by + le_of_forall_gt_imp_ge_of_dense fun x hxb => by obtain ⟨ε, rfl⟩ := exists_mul_of_le hxb.le exact h _ (one_lt_of_lt_mul_right hxb) diff --git a/Mathlib/Analysis/Complex/CauchyIntegral.lean b/Mathlib/Analysis/Complex/CauchyIntegral.lean index 99b3e0d3c22dc..68eaaa612c9ce 100644 --- a/Mathlib/Analysis/Complex/CauchyIntegral.lean +++ b/Mathlib/Analysis/Complex/CauchyIntegral.lean @@ -343,7 +343,7 @@ theorem circleIntegral_sub_center_inv_smul_of_differentiable_on_off_countable_of (hd : ∀ z ∈ (ball c R \ {c}) \ s, DifferentiableAt ℂ f z) (hy : Tendsto f (𝓝[{c}ᶜ] c) (𝓝 y)) : (∮ z in C(c, R), (z - c)⁻¹ • f z) = (2 * π * I : ℂ) • y := by rw [← sub_eq_zero, ← norm_le_zero_iff] - refine le_of_forall_le_of_dense fun ε ε0 => ?_ + refine le_of_forall_gt_imp_ge_of_dense fun ε ε0 => ?_ obtain ⟨δ, δ0, hδ⟩ : ∃ δ > (0 : ℝ), ∀ z ∈ closedBall c δ \ {c}, dist (f z) y < ε / (2 * π) := ((nhdsWithin_hasBasis nhds_basis_closedBall _).tendsto_iff nhds_basis_ball).1 hy _ (div_pos ε0 Real.two_pi_pos) diff --git a/Mathlib/Analysis/Complex/Liouville.lean b/Mathlib/Analysis/Complex/Liouville.lean index aee36657dab9e..75d46597fd3d1 100644 --- a/Mathlib/Analysis/Complex/Liouville.lean +++ b/Mathlib/Analysis/Complex/Liouville.lean @@ -89,7 +89,7 @@ theorem liouville_theorem_aux {f : ℂ → F} (hf : Differentiable ℂ f) (hb : exact ⟨max C 1, lt_max_iff.2 (Or.inr zero_lt_one), fun z => (hC (f z) (mem_range_self _)).trans (le_max_left _ _)⟩ - refine norm_le_zero_iff.1 (le_of_forall_le_of_dense fun ε ε₀ => ?_) + refine norm_le_zero_iff.1 (le_of_forall_gt_imp_ge_of_dense fun ε ε₀ => ?_) calc ‖deriv f c‖ ≤ C / (C / ε) := norm_deriv_le_of_forall_mem_sphere_norm_le (div_pos C₀ ε₀) hf.diffContOnCl fun z _ => hC z diff --git a/Mathlib/Analysis/Complex/PhragmenLindelof.lean b/Mathlib/Analysis/Complex/PhragmenLindelof.lean index ee37b9bc62b36..1d6cb0068727f 100644 --- a/Mathlib/Analysis/Complex/PhragmenLindelof.lean +++ b/Mathlib/Analysis/Complex/PhragmenLindelof.lean @@ -116,7 +116,7 @@ theorem horizontal_strip (hfd : DiffContOnCl ℂ f (im ⁻¹' Ioo a b)) cases' hza with hza hza; · exact hle_a _ hza.symm cases' hzb with hzb hzb; · exact hle_b _ hzb wlog hC₀ : 0 < C generalizing C - · refine le_of_forall_le_of_dense fun C' hC' => this (fun w hw => ?_) (fun w hw => ?_) ?_ + · refine le_of_forall_gt_imp_ge_of_dense fun C' hC' => this (fun w hw => ?_) (fun w hw => ?_) ?_ · exact (hle_a _ hw).trans hC'.le · exact (hle_b _ hw).trans hC'.le · refine ((norm_nonneg (f (a * I))).trans (hle_a _ ?_)).trans_lt hC' diff --git a/Mathlib/Analysis/LocallyConvex/Polar.lean b/Mathlib/Analysis/LocallyConvex/Polar.lean index af5dc28df843c..d49aedb9e4449 100644 --- a/Mathlib/Analysis/LocallyConvex/Polar.lean +++ b/Mathlib/Analysis/LocallyConvex/Polar.lean @@ -139,7 +139,7 @@ variable (B : E →ₗ[𝕜] F →ₗ[𝕜] 𝕜) theorem polar_univ (h : SeparatingRight B) : B.polar Set.univ = {(0 : F)} := by rw [Set.eq_singleton_iff_unique_mem] refine ⟨by simp only [zero_mem_polar], fun y hy => h _ fun x => ?_⟩ - refine norm_le_zero_iff.mp (le_of_forall_le_of_dense fun ε hε => ?_) + refine norm_le_zero_iff.mp (le_of_forall_gt_imp_ge_of_dense fun ε hε => ?_) rcases NormedField.exists_norm_lt 𝕜 hε with ⟨c, hc, hcε⟩ calc ‖B x y‖ = ‖c‖ * ‖B (c⁻¹ • x) y‖ := by diff --git a/Mathlib/Analysis/Normed/Field/Ultra.lean b/Mathlib/Analysis/Normed/Field/Ultra.lean index 8ef392b9b1afd..79e9e92787437 100644 --- a/Mathlib/Analysis/Normed/Field/Ultra.lean +++ b/Mathlib/Analysis/Normed/Field/Ultra.lean @@ -76,7 +76,7 @@ lemma isUltrametricDist_of_forall_pow_norm_le_nsmul_pow_max_one_norm -- that avoids explicitly mentioning `m`-th roots. -- First note it suffices to show that `‖x + 1‖ ≤ a` for all `a : ℝ` with `max ‖x‖ 1 < a`. rw [max_comm] - refine le_of_forall_le_of_dense fun a ha ↦ ?_ + refine le_of_forall_gt_imp_ge_of_dense fun a ha ↦ ?_ have ha' : 1 < a := (max_lt_iff.mp ha).left -- `max 1 ‖x‖ < a`, so there must be some `m : ℕ` such that `m + 1 < (a / max 1 ‖x‖) ^ m` -- by the virtue of exponential growth being faster than linear growth diff --git a/Mathlib/Analysis/Normed/Module/Dual.lean b/Mathlib/Analysis/Normed/Module/Dual.lean index 8a947e649a0b2..279e098d12e2c 100644 --- a/Mathlib/Analysis/Normed/Module/Dual.lean +++ b/Mathlib/Analysis/Normed/Module/Dual.lean @@ -240,7 +240,7 @@ theorem polar_ball {𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [Normed apply le_antisymm · intro x hx rw [mem_closedBall_zero_iff] - apply le_of_forall_le_of_dense + apply le_of_forall_gt_imp_ge_of_dense intro a ha rw [← mem_closedBall_zero_iff, ← (mul_div_cancel_left₀ a (Ne.symm (ne_of_lt hr)))] rw [← RCLike.norm_of_nonneg (K := 𝕜) (le_trans zero_le_one diff --git a/Mathlib/Data/ENNReal/Inv.lean b/Mathlib/Data/ENNReal/Inv.lean index 9b9e842c4e348..63249a8693464 100644 --- a/Mathlib/Data/ENNReal/Inv.lean +++ b/Mathlib/Data/ENNReal/Inv.lean @@ -44,7 +44,8 @@ protected theorem div_eq_inv_mul : a / b = b⁻¹ * a := by rw [div_eq_mul_inv, show sInf { b : ℝ≥0∞ | 1 ≤ 0 * b } = ∞ by simp @[simp] theorem inv_top : ∞⁻¹ = 0 := - bot_unique <| le_of_forall_le_of_dense fun a (h : 0 < a) => sInf_le <| by simp [*, h.ne', top_mul] + bot_unique <| le_of_forall_gt_imp_ge_of_dense fun a (h : 0 < a) => sInf_le <| by + simp [*, h.ne', top_mul] theorem coe_inv_le : (↑r⁻¹ : ℝ≥0∞) ≤ (↑r)⁻¹ := le_sInf fun b (hb : 1 ≤ ↑r * b) => @@ -444,7 +445,7 @@ instance : SMulPosMono ℝ≥0 ℝ≥0∞ where elim _r _ _a _b hab := mul_le_mul_right' (coe_le_coe.2 hab) _ theorem le_of_forall_nnreal_lt {x y : ℝ≥0∞} (h : ∀ r : ℝ≥0, ↑r < x → ↑r ≤ y) : x ≤ y := by - refine le_of_forall_ge_of_dense fun r hr => ?_ + refine le_of_forall_lt_imp_le_of_dense fun r hr => ?_ lift r to ℝ≥0 using ne_top_of_lt hr exact h r hr @@ -533,7 +534,7 @@ private lemma exists_lt_mul_right {a b c : ℝ≥0∞} (hc : c < a * b) : ∃ b' simp_rw [mul_comm a] at hc ⊢; exact exists_lt_mul_left hc lemma mul_le_of_forall_lt {a b c : ℝ≥0∞} (h : ∀ a' < a, ∀ b' < b, a' * b' ≤ c) : a * b ≤ c := by - refine le_of_forall_ge_of_dense fun d hd ↦ ?_ + refine le_of_forall_lt_imp_le_of_dense fun d hd ↦ ?_ obtain ⟨a', ha', hd⟩ := exists_lt_mul_left hd obtain ⟨b', hb', hd⟩ := exists_lt_mul_right hd exact le_trans hd.le <| h _ ha' _ hb' diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index 95519a608d383..be4890f48ea14 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -800,7 +800,7 @@ nonrec theorem div_le_div_left {a b c : ℝ≥0} (a0 : 0 < a) (b0 : 0 < b) (c0 : div_le_div_iff_of_pos_left a0 b0 c0 theorem le_of_forall_lt_one_mul_le {x y : ℝ≥0} (h : ∀ a < 1, a * x ≤ y) : x ≤ y := - le_of_forall_ge_of_dense fun a ha => by + le_of_forall_lt_imp_le_of_dense fun a ha => by have hx : x ≠ 0 := pos_iff_ne_zero.1 (lt_of_le_of_lt (zero_le _) ha) have hx' : x⁻¹ ≠ 0 := by rwa [Ne, inv_eq_zero] have : a * x⁻¹ < 1 := by rwa [← lt_inv_iff_mul_lt hx', inv_inv] diff --git a/Mathlib/Data/Real/Archimedean.lean b/Mathlib/Data/Real/Archimedean.lean index 039acaddf3405..3e9bf433eb681 100644 --- a/Mathlib/Data/Real/Archimedean.lean +++ b/Mathlib/Data/Real/Archimedean.lean @@ -42,7 +42,7 @@ theorem of_near (f : ℕ → ℚ) (x : ℝ) (h : ∀ ε > 0, ∃ i, ∀ j ≥ i, ⟨isCauSeq_iff_lift.2 (CauSeq.of_near _ (const abs x) h), sub_eq_zero.1 <| abs_eq_zero.1 <| - (eq_of_le_of_forall_le_of_dense (abs_nonneg _)) fun _ε ε0 => + (eq_of_le_of_forall_lt_imp_le_of_dense (abs_nonneg _)) fun _ε ε0 => mk_near_of_forall_near <| (h _ ε0).imp fun _i h j ij => le_of_lt (h j ij)⟩ theorem exists_floor (x : ℝ) : ∃ ub : ℤ, (ub : ℝ) ≤ x ∧ ∀ z : ℤ, (z : ℝ) ≤ x → z ≤ ub := @@ -88,7 +88,7 @@ theorem exists_isLUB (hne : s.Nonempty) (hbdd : BddAbove s) : ∃ x, IsLUB s x : simpa using sub_lt_iff_lt_add'.2 (lt_of_le_of_lt hy <| sub_lt_iff_lt_add.1 <| hf₂ _ k0 _ yS) let g : CauSeq ℚ abs := ⟨fun n => f n / n, hg⟩ refine ⟨mk g, ⟨fun x xS => ?_, fun y h => ?_⟩⟩ - · refine le_of_forall_ge_of_dense fun z xz => ?_ + · refine le_of_forall_lt_imp_le_of_dense fun z xz => ?_ cases' exists_nat_gt (x - z)⁻¹ with K hK refine le_mk_of_forall_le ⟨K, fun n nK => ?_⟩ replace xz := sub_pos.2 xz diff --git a/Mathlib/Data/Real/EReal.lean b/Mathlib/Data/Real/EReal.lean index 17c70dbd11726..8e308ba21e9aa 100644 --- a/Mathlib/Data/Real/EReal.lean +++ b/Mathlib/Data/Real/EReal.lean @@ -1291,7 +1291,7 @@ private lemma exists_lt_add_right {a b c : EReal} (hc : c < a + b) : ∃ b' < b, simp_rw [add_comm a] at hc ⊢; exact exists_lt_add_left hc lemma add_le_of_forall_lt {a b c : EReal} (h : ∀ a' < a, ∀ b' < b, a' + b' ≤ c) : a + b ≤ c := by - refine le_of_forall_ge_of_dense fun d hd ↦ ?_ + refine le_of_forall_lt_imp_le_of_dense fun d hd ↦ ?_ obtain ⟨a', ha', hd⟩ := exists_lt_add_left hd obtain ⟨b', hb', hd⟩ := exists_lt_add_right hd exact hd.le.trans (h _ ha' _ hb') diff --git a/Mathlib/MeasureTheory/Covering/Vitali.lean b/Mathlib/MeasureTheory/Covering/Vitali.lean index 5b2934b6db6d8..61f42f43718a6 100644 --- a/Mathlib/MeasureTheory/Covering/Vitali.lean +++ b/Mathlib/MeasureTheory/Covering/Vitali.lean @@ -310,7 +310,7 @@ theorem exists_disjoint_covering_ae linarith [Idist_v b ⟨bu, hbx⟩] -- we will show that, in `ball x (R x)`, almost all `s` is covered by the family `u`. refine ⟨_ ∩ ball x (R x), inter_mem_nhdsWithin _ (ball_mem_nhds _ (hR0 _)), - nonpos_iff_eq_zero.mp (le_of_forall_le_of_dense fun ε εpos => ?_)⟩ + nonpos_iff_eq_zero.mp (le_of_forall_gt_imp_ge_of_dense fun ε εpos => ?_)⟩ -- the elements of `v` are disjoint and all contained in a finite volume ball, hence the sum -- of their measures is finite. have I : (∑' a : v, μ (B a)) < ∞ := by diff --git a/Mathlib/MeasureTheory/Measure/Hausdorff.lean b/Mathlib/MeasureTheory/Measure/Hausdorff.lean index 2f8b288b9314b..5bd12b8bc5683 100644 --- a/Mathlib/MeasureTheory/Measure/Hausdorff.lean +++ b/Mathlib/MeasureTheory/Measure/Hausdorff.lean @@ -501,7 +501,7 @@ theorem mkMetric_le_liminf_tsum {β : Type*} {ι : β → Type*} [∀ n, Countab haveI : ∀ n, Encodable (ι n) := fun n => Encodable.ofCountable _ simp only [mkMetric_apply] refine iSup₂_le fun ε hε => ?_ - refine le_of_forall_le_of_dense fun c hc => ?_ + refine le_of_forall_gt_imp_ge_of_dense fun c hc => ?_ rcases ((frequently_lt_of_liminf_lt (by isBoundedDefault) hc).and_eventually ((hr.eventually (gt_mem_nhds hε)).and (ht.and hst))).exists with ⟨n, hn, hrn, htn, hstn⟩ diff --git a/Mathlib/NumberTheory/ModularForms/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/QExpansion.lean index 27d4e3389e4bb..43be8d61e52f2 100644 --- a/Mathlib/NumberTheory/ModularForms/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/QExpansion.lean @@ -149,7 +149,7 @@ lemma qExpansionFormalMultilinearSeries_apply_norm (m : ℕ) : lemma qExpansionFormalMultilinearSeries_radius [NeZero n] [ModularFormClass F Γ(n) k] : 1 ≤ (qExpansionFormalMultilinearSeries n f).radius := by - refine le_of_forall_ge_of_dense fun r hr ↦ ?_ + refine le_of_forall_lt_imp_le_of_dense fun r hr ↦ ?_ lift r to NNReal using hr.ne_top apply FormalMultilinearSeries.le_radius_of_summable simp only [qExpansionFormalMultilinearSeries_apply_norm] diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index 6b4dfb2191463..11f4a94f61cf1 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -1263,32 +1263,47 @@ instance [∀ i, Preorder (π i)] [∀ i, DenselyOrdered (π i)] : ⟨le_update_iff.2 ⟨ha.le, fun _ _ ↦ le_rfl⟩, i, by rwa [update_self]⟩, update_le_iff.2 ⟨hb.le, fun _ _ ↦ hab _⟩, i, by rwa [update_self]⟩⟩ -theorem le_of_forall_le_of_dense [LinearOrder α] [DenselyOrdered α] {a₁ a₂ : α} - (h : ∀ a, a₂ < a → a₁ ≤ a) : a₁ ≤ a₂ := +section LinearOrder +variable [LinearOrder α] [DenselyOrdered α] {a₁ a₂ : α} + +theorem le_of_forall_gt_imp_ge_of_dense (h : ∀ a, a₂ < a → a₁ ≤ a) : a₁ ≤ a₂ := le_of_not_gt fun ha ↦ let ⟨a, ha₁, ha₂⟩ := exists_between ha lt_irrefl a <| lt_of_lt_of_le ‹a < a₁› (h _ ‹a₂ < a›) -theorem eq_of_le_of_forall_le_of_dense [LinearOrder α] [DenselyOrdered α] {a₁ a₂ : α} (h₁ : a₂ ≤ a₁) - (h₂ : ∀ a, a₂ < a → a₁ ≤ a) : a₁ = a₂ := - le_antisymm (le_of_forall_le_of_dense h₂) h₁ +lemma forall_gt_imp_ge_iff_le_of_dense : (∀ a, a₂ < a → a₁ ≤ a) ↔ a₁ ≤ a₂ := + ⟨le_of_forall_gt_imp_ge_of_dense, fun ha _a ha₂ ↦ ha.trans ha₂.le⟩ + +lemma eq_of_le_of_forall_lt_imp_le_of_dense (h₁ : a₂ ≤ a₁) (h₂ : ∀ a, a₂ < a → a₁ ≤ a) : a₁ = a₂ := + le_antisymm (le_of_forall_gt_imp_ge_of_dense h₂) h₁ -theorem le_of_forall_ge_of_dense [LinearOrder α] [DenselyOrdered α] {a₁ a₂ : α} - (h : ∀ a₃ < a₁, a₃ ≤ a₂) : a₁ ≤ a₂ := +theorem le_of_forall_lt_imp_le_of_dense (h : ∀ a < a₁, a ≤ a₂) : a₁ ≤ a₂ := le_of_not_gt fun ha ↦ let ⟨a, ha₁, ha₂⟩ := exists_between ha lt_irrefl a <| lt_of_le_of_lt (h _ ‹a < a₁›) ‹a₂ < a› -theorem eq_of_le_of_forall_ge_of_dense [LinearOrder α] [DenselyOrdered α] {a₁ a₂ : α} (h₁ : a₂ ≤ a₁) - (h₂ : ∀ a₃ < a₁, a₃ ≤ a₂) : a₁ = a₂ := - (le_of_forall_ge_of_dense h₂).antisymm h₁ +lemma forall_lt_imp_le_iff_le_of_dense : (∀ a < a₁, a ≤ a₂) ↔ a₁ ≤ a₂ := + ⟨le_of_forall_lt_imp_le_of_dense, fun ha _a ha₁ ↦ ha₁.le.trans ha⟩ + +theorem eq_of_le_of_forall_gt_imp_ge_of_dense (h₁ : a₂ ≤ a₁) (h₂ : ∀ a < a₁, a ≤ a₂) : a₁ = a₂ := + (le_of_forall_lt_imp_le_of_dense h₂).antisymm h₁ + +@[deprecated (since := "2025-01-21")] +alias le_of_forall_le_of_dense := le_of_forall_gt_imp_ge_of_dense + +@[deprecated (since := "2025-01-21")] +alias le_of_forall_ge_of_dense := le_of_forall_lt_imp_le_of_dense + +@[deprecated (since := "2025-01-21")] alias forall_lt_le_iff := forall_lt_imp_le_iff_le_of_dense +@[deprecated (since := "2025-01-21")] alias forall_gt_ge_iff := forall_gt_imp_ge_iff_le_of_dense + +@[deprecated (since := "2025-01-21")] +alias eq_of_le_of_forall_le_of_dense := eq_of_le_of_forall_lt_imp_le_of_dense -theorem forall_lt_le_iff [LinearOrder α] [DenselyOrdered α] {a b : α} : (∀ c < a, c ≤ b) ↔ a ≤ b := - ⟨le_of_forall_ge_of_dense, fun hab _c hca ↦ hca.le.trans hab⟩ +@[deprecated (since := "2025-01-21")] +alias eq_of_le_of_forall_ge_of_dense := eq_of_le_of_forall_gt_imp_ge_of_dense -theorem forall_gt_ge_iff [LinearOrder α] [DenselyOrdered α] {a b : α} : - (∀ c, a < c → b ≤ c) ↔ b ≤ a := - forall_lt_le_iff (α := αᵒᵈ) +end LinearOrder theorem dense_or_discrete [LinearOrder α] (a₁ a₂ : α) : (∃ a, a₁ < a ∧ a < a₂) ∨ (∀ a, a₁ < a → a₂ ≤ a) ∧ ∀ a < a₂, a ≤ a₁ := diff --git a/Mathlib/Order/Bounds/Basic.lean b/Mathlib/Order/Bounds/Basic.lean index ff8f494fcda96..a161ef7fab20c 100644 --- a/Mathlib/Order/Bounds/Basic.lean +++ b/Mathlib/Order/Bounds/Basic.lean @@ -458,7 +458,7 @@ theorem exists_glb_Ioi (i : γ) : ∃ j, IsGLB (Ioi i) j := variable [DenselyOrdered γ] theorem isLUB_Iio {a : γ} : IsLUB (Iio a) a := - ⟨fun _ hx => le_of_lt hx, fun _ hy => le_of_forall_ge_of_dense hy⟩ + ⟨fun _ hx => le_of_lt hx, fun _ hy => le_of_forall_lt_imp_le_of_dense hy⟩ theorem isGLB_Ioi {a : γ} : IsGLB (Ioi a) a := @isLUB_Iio γᵒᵈ _ _ a diff --git a/Mathlib/Order/WithBot.lean b/Mathlib/Order/WithBot.lean index 63a1594ad82a0..8cbe3710d0429 100644 --- a/Mathlib/Order/WithBot.lean +++ b/Mathlib/Order/WithBot.lean @@ -956,7 +956,7 @@ lemma le_of_forall_lt_iff_le [LinearOrder α] [DenselyOrdered α] [NoMinOrder α | coe x => rw [le_coe_iff] rintro y rfl - exact le_of_forall_le_of_dense (by exact_mod_cast h) + exact le_of_forall_gt_imp_ge_of_dense (by exact_mod_cast h) lemma ge_of_forall_gt_iff_ge [LinearOrder α] [DenselyOrdered α] [NoMinOrder α] {x y : WithBot α} : (∀ z : α, z < x → z ≤ y) ↔ x ≤ y := by @@ -966,7 +966,7 @@ lemma ge_of_forall_gt_iff_ge [LinearOrder α] [DenselyOrdered α] [NoMinOrder α | coe y => rw [le_coe_iff] rintro h x rfl - exact le_of_forall_ge_of_dense (by exact_mod_cast h) + exact le_of_forall_lt_imp_le_of_dense (by exact_mod_cast h) section LE diff --git a/Mathlib/Topology/EMetricSpace/Defs.lean b/Mathlib/Topology/EMetricSpace/Defs.lean index e3582222d3610..0c9f840cb9455 100644 --- a/Mathlib/Topology/EMetricSpace/Defs.lean +++ b/Mathlib/Topology/EMetricSpace/Defs.lean @@ -596,7 +596,7 @@ theorem edist_pos {x y : γ} : 0 < edist x y ↔ x ≠ y := by simp [← not_le] /-- Two points coincide if their distance is `< ε` for all positive ε -/ theorem eq_of_forall_edist_le {x y : γ} (h : ∀ ε > 0, edist x y ≤ ε) : x = y := - eq_of_edist_eq_zero (eq_of_le_of_forall_le_of_dense bot_le h) + eq_of_edist_eq_zero (eq_of_le_of_forall_lt_imp_le_of_dense bot_le h) /-- Auxiliary function to replace the uniformity on an emetric space with a uniformity which is equal to the original one, but maybe not defeq. diff --git a/Mathlib/Topology/MetricSpace/Defs.lean b/Mathlib/Topology/MetricSpace/Defs.lean index e678bdcfedb6b..0ada8be44573b 100644 --- a/Mathlib/Topology/MetricSpace/Defs.lean +++ b/Mathlib/Topology/MetricSpace/Defs.lean @@ -78,7 +78,7 @@ theorem dist_pos {x y : γ} : 0 < dist x y ↔ x ≠ y := by simpa only [not_le] using not_congr dist_le_zero theorem eq_of_forall_dist_le {x y : γ} (h : ∀ ε > 0, dist x y ≤ ε) : x = y := - eq_of_dist_eq_zero (eq_of_le_of_forall_le_of_dense dist_nonneg h) + eq_of_dist_eq_zero (eq_of_le_of_forall_lt_imp_le_of_dense dist_nonneg h) /-- Deduce the equality of points from the vanishing of the nonnegative distance -/ theorem eq_of_nndist_eq_zero {x y : γ} : nndist x y = 0 → x = y := by diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean index a564dcfd1a909..caf9feed00c8f 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean @@ -311,7 +311,7 @@ theorem hausdorffDist_optimal {X : Type u} [MetricSpace X] [CompactSpace X] [Non let Fb := candidatesBOfCandidates F Fgood have : hausdorffDist (range (optimalGHInjl X Y)) (range (optimalGHInjr X Y)) ≤ HD Fb := hausdorffDist_optimal_le_HD _ _ (candidatesBOfCandidates_mem F Fgood) - refine le_trans this (le_of_forall_le_of_dense fun r hr => ?_) + refine le_trans this (le_of_forall_gt_imp_ge_of_dense fun r hr => ?_) have I1 : ∀ x : X, (⨅ y, Fb (inl x, inr y)) ≤ r := by intro x have : f (inl x) ∈ (p : Set _) := Φrange ▸ (mem_range_self _) diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean index f0124bb1d3151..5eedc8d457f84 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean @@ -480,7 +480,7 @@ the Hausdorff distance in the optimal coupling, although we only prove here the we need. -/ theorem hausdorffDist_optimal_le_HD {f} (h : f ∈ candidatesB X Y) : hausdorffDist (range (optimalGHInjl X Y)) (range (optimalGHInjr X Y)) ≤ HD f := by - refine le_trans (le_of_forall_le_of_dense fun r hr => ?_) (HD_optimalGHDist_le X Y f h) + refine le_trans (le_of_forall_gt_imp_ge_of_dense fun r hr => ?_) (HD_optimalGHDist_le X Y f h) have A : ∀ x ∈ range (optimalGHInjl X Y), ∃ y ∈ range (optimalGHInjr X Y), dist x y ≤ r := by rintro _ ⟨z, rfl⟩ have I1 : (⨆ x, ⨅ y, optimalGHDist X Y (inl x, inr y)) < r := diff --git a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean index ec335783eba45..0235fc0d81322 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean @@ -232,7 +232,7 @@ theorem bsupr_limsup_dimH (s : Set X) : ⨆ x ∈ s, limsup dimH (𝓝[s] x).sma refine le_antisymm (iSup₂_le fun x _ => ?_) ?_ · refine limsup_le_of_le isCobounded_le_of_bot ?_ exact eventually_smallSets.2 ⟨s, self_mem_nhdsWithin, fun t => dimH_mono⟩ - · refine le_of_forall_ge_of_dense fun r hr => ?_ + · refine le_of_forall_lt_imp_le_of_dense fun r hr => ?_ rcases exists_mem_nhdsWithin_lt_dimH_of_lt_dimH hr with ⟨x, hxs, hxr⟩ refine le_iSup₂_of_le x hxs ?_; rw [limsup_eq]; refine le_sInf fun b hb => ?_ rcases eventually_smallSets.1 hb with ⟨t, htx, ht⟩ diff --git a/Mathlib/Topology/MetricSpace/Pseudo/Lemmas.lean b/Mathlib/Topology/MetricSpace/Pseudo/Lemmas.lean index 6b6cd86da53a2..9f284fb00b881 100644 --- a/Mathlib/Topology/MetricSpace/Pseudo/Lemmas.lean +++ b/Mathlib/Topology/MetricSpace/Pseudo/Lemmas.lean @@ -91,7 +91,7 @@ lemma exists_isCompact_closedBall [WeaklyLocallyCompactSpace α] (x : α) : theorem biInter_gt_closedBall (x : α) (r : ℝ) : ⋂ r' > r, closedBall x r' = closedBall x r := by ext - simp [forall_gt_ge_iff] + simp [forall_gt_imp_ge_iff_le_of_dense] theorem biInter_gt_ball (x : α) (r : ℝ) : ⋂ r' > r, ball x r' = closedBall x r := by ext @@ -100,7 +100,7 @@ theorem biInter_gt_ball (x : α) (r : ℝ) : ⋂ r' > r, ball x r' = closedBall theorem biUnion_lt_ball (x : α) (r : ℝ) : ⋃ r' < r, ball x r' = ball x r := by ext rw [← not_iff_not] - simp [forall_lt_le_iff] + simp [forall_lt_imp_le_iff_le_of_dense] theorem biUnion_lt_closedBall (x : α) (r : ℝ) : ⋃ r' < r, closedBall x r' = ball x r := by ext From cb7d162fbd6940499f385cf716ed1b92aefd971c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Mon, 27 Jan 2025 14:51:20 +0000 Subject: [PATCH 570/681] =?UTF-8?q?feat:=20`(v=20+=E1=B5=A5=20s)=20-?= =?UTF-8?q?=E1=B5=A5=20(v=20+=E1=B5=A5=20t)=20=3D=20s=20-=E1=B5=A5=20t`=20?= =?UTF-8?q?(#21058)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From PFR --- Mathlib/Algebra/AddTorsor.lean | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Mathlib/Algebra/AddTorsor.lean b/Mathlib/Algebra/AddTorsor.lean index c853185785a74..7977a04a58c14 100644 --- a/Mathlib/Algebra/AddTorsor.lean +++ b/Mathlib/Algebra/AddTorsor.lean @@ -38,6 +38,8 @@ multiplicative group actions). -/ +open scoped Pointwise + /-- An `AddTorsor G P` gives a structure to the nonempty type `P`, acted on by an `AddGroup G` with a transitive and free action given by the `+ᵥ` operation and a corresponding subtraction given by the @@ -162,8 +164,6 @@ theorem vadd_eq_vadd_iff_neg_add_eq_vsub {v₁ v₂ : G} {p₁ p₂ : P} : namespace Set -open Pointwise - theorem singleton_vsub_self (p : P) : ({p} : Set P) -ᵥ {p} = {(0 : G)} := by rw [Set.singleton_vsub_singleton, vsub_self] @@ -231,6 +231,13 @@ theorem vadd_eq_vadd_iff_sub_eq_vsub {v₁ v₂ : G} {p₁ p₂ : P} : theorem vsub_sub_vsub_comm (p₁ p₂ p₃ p₄ : P) : p₁ -ᵥ p₂ - (p₃ -ᵥ p₄) = p₁ -ᵥ p₃ - (p₂ -ᵥ p₄) := by rw [← vsub_vadd_eq_vsub_sub, vsub_vadd_comm, vsub_vadd_eq_vsub_sub] +namespace Set + +@[simp] lemma vadd_set_vsub_vadd_set (v : G) (s t : Set P) : (v +ᵥ s) -ᵥ (v +ᵥ t) = s -ᵥ t := by + ext; simp [mem_vsub, mem_vadd_set] + +end Set + end comm namespace Prod From c190220d2c66cc535a45a528a569ce827ebfd00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Mon, 27 Jan 2025 14:51:21 +0000 Subject: [PATCH 571/681] feat: inequality on the integral of a convex function of a RN derivative (#21093) --- Mathlib.lean | 1 + .../Decomposition/IntegralRNDeriv.lean | 99 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 Mathlib/MeasureTheory/Decomposition/IntegralRNDeriv.lean diff --git a/Mathlib.lean b/Mathlib.lean index a9e8682e0b928..612bcdad18894 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3744,6 +3744,7 @@ import Mathlib.MeasureTheory.Covering.OneDim import Mathlib.MeasureTheory.Covering.Vitali import Mathlib.MeasureTheory.Covering.VitaliFamily import Mathlib.MeasureTheory.Decomposition.Exhaustion +import Mathlib.MeasureTheory.Decomposition.IntegralRNDeriv import Mathlib.MeasureTheory.Decomposition.Jordan import Mathlib.MeasureTheory.Decomposition.Lebesgue import Mathlib.MeasureTheory.Decomposition.RadonNikodym diff --git a/Mathlib/MeasureTheory/Decomposition/IntegralRNDeriv.lean b/Mathlib/MeasureTheory/Decomposition/IntegralRNDeriv.lean new file mode 100644 index 0000000000000..e2ddf8630cf97 --- /dev/null +++ b/Mathlib/MeasureTheory/Decomposition/IntegralRNDeriv.lean @@ -0,0 +1,99 @@ +/- +Copyright (c) 2025 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne, Lorenzo Luccioli +-/ +import Mathlib.Analysis.Convex.Continuous +import Mathlib.Analysis.Convex.Integral +import Mathlib.MeasureTheory.Decomposition.RadonNikodym + +/-! +# Integrals of functions of Radon-Nikodym derivatives + +## Main statements + +* `mul_le_integral_rnDeriv_of_ac`: for a convex continuous function `f` on `[0, ∞)`, if `μ` + is absolutely continuous with respect to `ν`, then + `(ν univ).toReal * f ((μ univ).toReal / (ν univ).toReal) ≤ ∫ x, f (μ.rnDeriv ν x).toReal ∂ν`. + +-/ + + +open Set + +namespace MeasureTheory + +variable {α : Type*} {mα : MeasurableSpace α} {μ ν : Measure α} {f : ℝ → ℝ} + +/-- For a convex continuous function `f` on `[0, ∞)`, if `μ` is absolutely continuous +with respect to a probability measure `ν`, then +`f (μ univ).toReal ≤ ∫ x, f (μ.rnDeriv ν x).toReal ∂ν`. -/ +lemma le_integral_rnDeriv_of_ac [IsFiniteMeasure μ] [IsProbabilityMeasure ν] + (hf_cvx : ConvexOn ℝ (Ici 0) f) (hf_cont : ContinuousWithinAt f (Ici 0) 0) + (hf_int : Integrable (fun x ↦ f (μ.rnDeriv ν x).toReal) ν) (hμν : μ ≪ ν) : + f (μ univ).toReal ≤ ∫ x, f (μ.rnDeriv ν x).toReal ∂ν := by + have hf_cont' : ContinuousOn f (Ici 0) := by + intro x hx + rcases eq_or_lt_of_le (α := ℝ) (hx : 0 ≤ x) with rfl | hx_pos + · exact hf_cont + · have h := hf_cvx.continuousOn_interior x + simp only [nonempty_Iio, interior_Ici', mem_Ioi] at h + rw [continuousWithinAt_iff_continuousAt (Ioi_mem_nhds hx_pos)] at h + exact (h hx_pos).continuousWithinAt + calc f (μ univ).toReal + = f (∫ x, (μ.rnDeriv ν x).toReal ∂ν) := by rw [Measure.integral_toReal_rnDeriv hμν] + _ ≤ ∫ x, f (μ.rnDeriv ν x).toReal ∂ν := by + rw [← average_eq_integral, ← average_eq_integral] + exact ConvexOn.map_average_le hf_cvx hf_cont' isClosed_Ici (by simp) + Measure.integrable_toReal_rnDeriv hf_int + +/-- For a convex continuous function `f` on `[0, ∞)`, if `μ` is absolutely continuous +with respect to `ν`, then +`(ν univ).toReal * f ((μ univ).toReal / (ν univ).toReal) ≤ ∫ x, f (μ.rnDeriv ν x).toReal ∂ν`. -/ +lemma mul_le_integral_rnDeriv_of_ac [IsFiniteMeasure μ] [IsFiniteMeasure ν] + (hf_cvx : ConvexOn ℝ (Ici 0) f) (hf_cont : ContinuousWithinAt f (Ici 0) 0) + (hf_int : Integrable (fun x ↦ f (μ.rnDeriv ν x).toReal) ν) (hμν : μ ≪ ν) : + (ν univ).toReal * f ((μ univ).toReal / (ν univ).toReal) + ≤ ∫ x, f (μ.rnDeriv ν x).toReal ∂ν := by + by_cases hν : ν = 0 + · simp [hν] + have : NeZero ν := ⟨hν⟩ + let μ' := (ν univ)⁻¹ • μ + let ν' := (ν univ)⁻¹ • ν + have : IsFiniteMeasure μ' := μ.smul_finite (by simp [hν]) + have hμν' : μ' ≪ ν' := hμν.smul _ + have h_rnDeriv_eq : μ'.rnDeriv ν' =ᵐ[ν] μ.rnDeriv ν := by + have h1' : μ'.rnDeriv ν' =ᵐ[ν'] (ν univ)⁻¹ • μ.rnDeriv ν' := + Measure.rnDeriv_smul_left_of_ne_top' (μ := ν') (ν := μ) (by simp [hν]) + have h1 : μ'.rnDeriv ν' =ᵐ[ν] (ν univ)⁻¹ • μ.rnDeriv ν' := by + rwa [Measure.ae_smul_measure_eq] at h1' + simp + have h2 : μ.rnDeriv ν' =ᵐ[ν] (ν univ)⁻¹⁻¹ • μ.rnDeriv ν := + Measure.rnDeriv_smul_right_of_ne_top' (μ := ν) (ν := μ) (by simp) (by simp [hν]) + filter_upwards [h1, h2] with x h1 h2 + rw [h1, Pi.smul_apply, smul_eq_mul, h2] + simp only [inv_inv, Pi.smul_apply, smul_eq_mul] + rw [← mul_assoc, ENNReal.inv_mul_cancel, one_mul] + · simp [hν] + · simp + have h_eq : ∫ x, f (μ'.rnDeriv ν' x).toReal ∂ν' + = (ν univ).toReal⁻¹ * ∫ x, f ((μ.rnDeriv ν x).toReal) ∂ν := by + rw [integral_smul_measure, smul_eq_mul, ENNReal.toReal_inv] + congr 1 + refine integral_congr_ae ?_ + filter_upwards [h_rnDeriv_eq] with x hx + rw [hx] + have h : f (μ' univ).toReal ≤ ∫ x, f (μ'.rnDeriv ν' x).toReal ∂ν' := + le_integral_rnDeriv_of_ac hf_cvx hf_cont ?_ hμν' + swap + · refine Integrable.smul_measure ?_ (by simp [hν]) + refine (integrable_congr ?_).mpr hf_int + filter_upwards [h_rnDeriv_eq] with x hx + rw [hx] + rw [h_eq, mul_comm, ← div_le_iff₀, div_eq_inv_mul, inv_inv] at h + · convert h + · simp only [div_eq_inv_mul, Measure.smul_apply, smul_eq_mul, ENNReal.toReal_mul, + ENNReal.toReal_inv, μ'] + · simp [ENNReal.toReal_pos_iff, hν] + +end MeasureTheory From 02a6cbce220609dc6a9e5a686afa01a463643d9d Mon Sep 17 00:00:00 2001 From: Hannah Scholz Date: Mon, 27 Jan 2025 15:35:51 +0000 Subject: [PATCH 572/681] feat: PSum of finite sorts is finite (#20285) --- Mathlib/Data/Finite/Sum.lean | 9 +++++++++ Mathlib/Data/Sum/Basic.lean | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/Mathlib/Data/Finite/Sum.lean b/Mathlib/Data/Finite/Sum.lean index 177f8e038134a..4c3ecc2999ef5 100644 --- a/Mathlib/Data/Finite/Sum.lean +++ b/Mathlib/Data/Finite/Sum.lean @@ -24,4 +24,13 @@ theorem sum_left (β) [Finite (α ⊕ β)] : Finite α := theorem sum_right (α) [Finite (α ⊕ β)] : Finite β := of_injective (Sum.inr : β → α ⊕ β) Sum.inr_injective +instance {α β : Sort*} [Finite α] [Finite β] : Finite (α ⊕' β) := + of_equiv _ ((Equiv.psumEquivSum _ _).symm.trans (Equiv.plift.psumCongr Equiv.plift)) + +theorem psum_left {α β : Sort*} [Finite (α ⊕' β)] : Finite α := + of_injective (PSum.inl : α → α ⊕' β) PSum.inl_injective + +theorem psum_right {α β : Sort*} [Finite (α ⊕' β)] : Finite β := + of_injective (PSum.inr : β → α ⊕' β) PSum.inr_injective + end Finite diff --git a/Mathlib/Data/Sum/Basic.lean b/Mathlib/Data/Sum/Basic.lean index 30d502873b139..cf572757b919f 100644 --- a/Mathlib/Data/Sum/Basic.lean +++ b/Mathlib/Data/Sum/Basic.lean @@ -269,3 +269,17 @@ def in₂ (c : γ) : α ⊕ (β ⊕ γ) := inr <| inr c end Sum3 + +/-! +### PSum +-/ + +namespace PSum + +variable {α β : Sort*} + +theorem inl_injective : Function.Injective (PSum.inl : α → α ⊕' β) := fun _ _ ↦ inl.inj + +theorem inr_injective : Function.Injective (PSum.inr : β → α ⊕' β) := fun _ _ ↦ inr.inj + +end PSum From c6ea3e1ef836bbc65587b0e37293efec910d05ed Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 27 Jan 2025 16:24:04 +0000 Subject: [PATCH 573/681] feat(Algebra/Category): `ConcreteCategory` instance for `ModuleCat` (#21125) This is a step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This PR adds a `ConcreteCategory` instance for `ModuleCat`. It also replaces the `Hom.hom` structure projection with an alias for `ConcreteCategory.hom`. Sadly `ModuleCat.restrictScalars` and `PresheafOfModules` do not appreciate subtle changes in elaboration/defeq, and quite a few declarations need subtle fixes. Maybe a more structural fix exists? I have not tried to look for code that can be cleaned up now, only at what broke. I want to get started on cleanup when the other concrete category instances are in. --- Mathlib/Algebra/Category/Grp/AB.lean | 7 +-- .../Algebra/Category/Grp/LargeColimits.lean | 2 +- Mathlib/Algebra/Category/ModuleCat/Basic.lean | 44 ++++++++++++------- .../Category/ModuleCat/Biproducts.lean | 2 +- .../Category/ModuleCat/ChangeOfRings.lean | 10 ++--- .../ModuleCat/Differentials/Presheaf.lean | 3 +- .../Algebra/Category/ModuleCat/Limits.lean | 3 +- .../Category/ModuleCat/Monoidal/Basic.lean | 2 +- .../Category/ModuleCat/Presheaf/Monoidal.lean | 13 ++++-- .../ModuleCat/Presheaf/Pushforward.lean | 9 ++-- .../Algebra/Category/ModuleCat/Products.lean | 2 +- .../Algebra/Category/ModuleCat/Subobject.lean | 2 +- .../Algebra/Homology/ConcreteCategory.lean | 2 +- Mathlib/Algebra/Homology/ShortComplex/Ab.lean | 6 +-- .../ShortComplex/ConcreteCategory.lean | 10 ++--- .../WithAlgebraicStructures.lean | 2 +- .../GroupCohomology/Basic.lean | 18 ++++---- .../GroupCohomology/LowDegree.lean | 2 +- .../GroupCohomology/Resolution.lean | 5 ++- Mathlib/RepresentationTheory/Rep.lean | 9 ++-- .../RingTheory/Coalgebra/TensorProduct.lean | 2 +- 21 files changed, 89 insertions(+), 66 deletions(-) diff --git a/Mathlib/Algebra/Category/Grp/AB.lean b/Mathlib/Algebra/Category/Grp/AB.lean index dde16f6cf9ea2..3038d2cedbcac 100644 --- a/Mathlib/Algebra/Category/Grp/AB.lean +++ b/Mathlib/Algebra/Category/Grp/AB.lean @@ -32,14 +32,15 @@ noncomputable instance : intro x (hx : _ = _) dsimp at hx rcases Concrete.colimit_exists_rep S.X₂ x with ⟨j, y, rfl⟩ - rw [← comp_apply, colimMap_eq, colimit.ι_map, comp_apply, + rw [← CategoryTheory.comp_apply, colimMap_eq, colimit.ι_map, CategoryTheory.comp_apply, ← map_zero (by exact colimit.ι S.X₃ j : (S.X₃).obj j →+ ↑(colimit S.X₃))] at hx rcases Concrete.colimit_exists_of_rep_eq.{u, u, u} S.X₃ _ _ hx with ⟨k, e₁, e₂, hk : _ = S.X₃.map e₂ 0⟩ - rw [map_zero, ← comp_apply, ← NatTrans.naturality, comp_apply] at hk + rw [map_zero, ← CategoryTheory.comp_apply, ← NatTrans.naturality, CategoryTheory.comp_apply] + at hk rcases hS k hk with ⟨t, ht⟩ use colimit.ι S.X₁ k t - erw [← comp_apply, colimit.ι_map, comp_apply, ht] + erw [← CategoryTheory.comp_apply, colimit.ι_map, CategoryTheory.comp_apply, ht] exact colimit.w_apply S.X₂ e₁ y) noncomputable instance : diff --git a/Mathlib/Algebra/Category/Grp/LargeColimits.lean b/Mathlib/Algebra/Category/Grp/LargeColimits.lean index 9f9628925dad5..9d0a40892ca36 100644 --- a/Mathlib/Algebra/Category/Grp/LargeColimits.lean +++ b/Mathlib/Algebra/Category/Grp/LargeColimits.lean @@ -40,7 +40,7 @@ lemma isColimit_iff_bijective_desc [DecidableEq J] : apply ofHom_injective refine hc.hom_ext (fun j ↦ ?_) ext x - rw [comp_apply, comp_apply, ← Quot.ι_desc _ c j x] + rw [CategoryTheory.comp_apply, CategoryTheory.comp_apply, ← Quot.ι_desc _ c j x] exact ULift.down_injective (DFunLike.congr_fun eq (Quot.ι F j x)) · set c' : Cocone F := { pt := AddCommGrp.of (ULift (AddCircle (1 : ℚ))) diff --git a/Mathlib/Algebra/Category/ModuleCat/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Basic.lean index 3b5c357c23475..1692cf8873858 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Basic.lean @@ -89,20 +89,40 @@ variable {R} in structure Hom (M N : ModuleCat.{v} R) where private mk :: /-- The underlying linear map. -/ - hom : M →ₗ[R] N + hom' : M →ₗ[R] N instance moduleCategory : Category.{v, max (v+1) u} (ModuleCat.{v} R) where Hom M N := Hom M N id _ := ⟨LinearMap.id⟩ - comp f g := ⟨g.hom.comp f.hom⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ -instance {M N : ModuleCat.{v} R} : CoeFun (M ⟶ N) (fun _ ↦ M → N) where - coe f := f.hom +instance : ConcreteCategory (ModuleCat.{v} R) (· →ₗ[R] ·) where + hom := Hom.hom' + ofHom := Hom.mk section variable {R} +/-- Turn a morphism in `ModuleCat` back into a `LinearMap`. -/ +abbrev Hom.hom {A B : ModuleCat.{v} R} (f : Hom A B) := + ConcreteCategory.hom (C := ModuleCat R) f + +/-- Typecheck a `LinearMap` as a morphism in `ModuleCat`. -/ +abbrev ofHom {X Y : Type v} [AddCommGroup X] [Module R X] [AddCommGroup Y] [Module R Y] + (f : X →ₗ[R] Y) : of R X ⟶ of R Y := + ConcreteCategory.ofHom (C := ModuleCat R) f + +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (A B : ModuleCat.{v} R) (f : Hom A B) := + f.hom + +initialize_simps_projections Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ + @[simp] lemma hom_id {M : ModuleCat.{v} R} : (𝟙 M : M ⟶ M).hom = LinearMap.id := rfl @@ -137,15 +157,9 @@ lemma hom_surjective {M N : ModuleCat.{v} R} : Function.Surjective (Hom.hom : (M ⟶ N) → (M →ₗ[R] N)) := hom_bijective.surjective -/-- Typecheck a `LinearMap` as a morphism in `ModuleCat R`. -/ -abbrev ofHom {X Y : Type v} [AddCommGroup X] [Module R X] [AddCommGroup Y] [Module R Y] - (f : X →ₗ[R] Y) : of R X ⟶ of R Y := - ⟨f⟩ - @[deprecated (since := "2024-10-06")] alias asHom := ModuleCat.ofHom -/- Doesn't need to be `@[simp]` since the `simp` tactic applies this rewrite automatically: -`ofHom` and `hom` are reducibly equal to the constructor and projection respectively. -/ +@[simp] lemma hom_ofHom {X Y : Type v} [AddCommGroup X] [Module R X] [AddCommGroup Y] [Module R Y] (f : X →ₗ[R] Y) : (ofHom f).hom = f := rfl @@ -540,9 +554,9 @@ a morphism between the underlying objects in `AddCommGrp` and the compatibility with the scalar multiplication. -/ @[simps] def homMk : M ⟶ N where - hom.toFun := φ - hom.map_add' _ _ := φ.map_add _ _ - hom.map_smul' r x := (congr_hom (hφ r) x).symm + hom'.toFun := φ + hom'.map_add' _ _ := φ.map_add _ _ + hom'.map_smul' r x := (congr_hom (hφ r) x).symm lemma forget₂_map_homMk : (forget₂ (ModuleCat R) AddCommGrp).map (homMk φ hφ) = φ := rfl @@ -571,7 +585,7 @@ variable {R : Type*} [CommRing R] namespace ModuleCat /-- Turn a bilinear map into a homomorphism. -/ -@[simps] +@[simps!] def ofHom₂ {M N P : ModuleCat.{u} R} (f : M →ₗ[R] N →ₗ[R] P) : M ⟶ of R (N ⟶ P) := ofHom <| homLinearEquiv.symm.toLinearMap ∘ₗ f diff --git a/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean b/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean index 4387064834c7e..cb8a2f9ed669a 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean @@ -86,7 +86,7 @@ variable {J : Type w} (f : J → ModuleCat.{max w v} R) /-- The map from an arbitrary cone over an indexed family of abelian groups to the cartesian product of those groups. -/ -@[simps] +@[simps!] def lift (s : Fan f) : s.pt ⟶ ModuleCat.of R (∀ j, f j) := ofHom { toFun := fun x j => s.π.app ⟨j⟩ x diff --git a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean index b922ed2155138..d2665b9f8258f 100644 --- a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean @@ -298,7 +298,7 @@ def map' {M1 M2 : ModuleCat.{v} R} (l : M1 ⟶ M2) : obj' f M1 ⟶ obj' f M2 := theorem map'_id {M : ModuleCat.{v} R} : map' f (𝟙 M) = 𝟙 _ := by ext x - simp [map'] + simp [map', obj'] theorem map'_comp {M₁ M₂ M₃ : ModuleCat.{v} R} (l₁₂ : M₁ ⟶ M₂) (l₂₃ : M₂ ⟶ M₃) : map' f (l₁₂ ≫ l₂₃) = map' f l₁₂ ≫ map' f l₂₃ := by @@ -415,7 +415,7 @@ instance : CoeFun (obj' f M) fun _ => S → M := /-- If `M, M'` are `R`-modules, then any `R`-linear map `g : M ⟶ M'` induces an `S`-linear map `(S →ₗ[R] M) ⟶ (S →ₗ[R] M')` defined by `h ↦ g ∘ h`-/ -@[simps] +@[simps!] def map' {M M' : ModuleCat R} (g : M ⟶ M') : obj' f M ⟶ obj' f M' := ofHom { toFun := fun h => g.hom.comp h @@ -610,7 +610,7 @@ Given `R`-module X and `S`-module Y and a map `g : (extendScalars f).obj X ⟶ Y map `S ⨂ X → Y`, there is a `X ⟶ (restrictScalars f).obj Y`, i.e. `R`-linear map `X ⟶ Y` by `x ↦ g (1 ⊗ x)`. -/ -@[simps hom_apply] +@[simps! hom_apply] def HomEquiv.toRestrictScalars {X Y} (g : (extendScalars f).obj X ⟶ Y) : X ⟶ (restrictScalars f).obj Y := -- TODO: after https://github.com/leanprover-community/mathlib4/pull/19511 we need to hint `(Y := ...)`. @@ -649,7 +649,7 @@ Given `R`-module X and `S`-module Y and a map `X ⟶ (restrictScalars f).obj Y`, `X ⟶ Y`, there is a map `(extend_scalars f).obj X ⟶ Y`, i.e `S`-linear map `S ⨂ X → Y` by `s ⊗ x ↦ s • g x`. -/ -@[simps hom_apply] +@[simps! hom_apply] def HomEquiv.fromExtendScalars {X Y} (g : X ⟶ (restrictScalars f).obj Y) : (extendScalars f).obj X ⟶ Y := by letI m1 : Module R S := Module.compHom S f; letI m2 : Module R Y := Module.compHom Y f @@ -734,7 +734,7 @@ def unit : 𝟭 (ModuleCat R) ⟶ extendScalars f ⋙ restrictScalars.{max v u /-- For any `S`-module Y, there is a natural `R`-linear map from `S ⨂ Y` to `Y` by `s ⊗ y ↦ s • y` -/ -@[simps hom_apply] +@[simps! hom_apply] def Counit.map {Y} : (restrictScalars f ⋙ extendScalars f).obj Y ⟶ Y := ofHom { toFun := diff --git a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean index c25122a364ea7..33b8dc3cb3281 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean @@ -193,7 +193,8 @@ attribute [simp] relativeDifferentials'_obj lemma relativeDifferentials'_map_d {X Y : Dᵒᵖ} (f : X ⟶ Y) (x : R.obj X) : DFunLike.coe (α := CommRingCat.KaehlerDifferential (φ'.app X)) (β := fun _ ↦ CommRingCat.KaehlerDifferential (φ'.app Y)) - ((relativeDifferentials' φ').map f).hom (CommRingCat.KaehlerDifferential.d x) = + (ModuleCat.Hom.hom (R := ↑(R.obj X)) ((relativeDifferentials' φ').map f)) + (CommRingCat.KaehlerDifferential.d x) = CommRingCat.KaehlerDifferential.d (R.map f x) := CommRingCat.KaehlerDifferential.map_d (φ'.naturality f) _ diff --git a/Mathlib/Algebra/Category/ModuleCat/Limits.lean b/Mathlib/Algebra/Category/ModuleCat/Limits.lean index 431ac7e1734a3..81944fb1cb648 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Limits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Limits.lean @@ -249,8 +249,7 @@ def directLimitIsColimit : IsColimit (directLimitCocone G f) where rfl fac s i := by ext - dsimp only [directLimitCocone, CategoryStruct.comp] - rw [LinearMap.comp_apply] + dsimp only [hom_comp, directLimitCocone, hom_ofHom, LinearMap.comp_apply] apply DirectLimit.lift_of uniq s m h := by have : diff --git a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean index 89bdba339ff9f..1f38171bfc7b0 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean @@ -244,7 +244,7 @@ lemma tensorLift_tmul (m : M₁) (n : M₂) : end -lemma tensor_ext {f g : M₁ ⊗ M₂ ⟶ M₃} (h : ∀ m n, f (m ⊗ₜ n) = g (m ⊗ₜ n)) : +lemma tensor_ext {f g : M₁ ⊗ M₂ ⟶ M₃} (h : ∀ m n, f.hom (m ⊗ₜ n) = g.hom (m ⊗ₜ n)) : f = g := hom_ext <| TensorProduct.ext (by ext; apply h) diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean index cd94fb824ae02..869be578d46d6 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Monoidal.lean @@ -53,7 +53,8 @@ noncomputable def tensorObj : PresheafOfModules (R ⋙ forget₂ _ _) where map_id X := ModuleCat.MonoidalCategory.tensor_ext (by intro m₁ m₂ dsimp [tensorObjMap] - simp) + simp + rfl) -- `ModuleCat.restrictScalarsId'App_inv_apply` doesn't get picked up due to type mismatch map_comp f g := ModuleCat.MonoidalCategory.tensor_ext (by intro m₁ m₂ dsimp [tensorObjMap] @@ -65,7 +66,8 @@ variable {M₁ M₂ M₃ M₄} lemma tensorObj_map_tmul {X Y : Cᵒᵖ} (f : X ⟶ Y) (m₁ : M₁.obj X) (m₂ : M₂.obj X) : DFunLike.coe (α := (M₁.obj X ⊗ M₂.obj X :)) (β := fun _ ↦ (ModuleCat.restrictScalars (R.map f).hom).obj (M₁.obj Y ⊗ M₂.obj Y)) - ((tensorObj M₁ M₂).map f).hom (m₁ ⊗ₜ[R.obj X] m₂) = M₁.map f m₁ ⊗ₜ[R.obj Y] M₂.map f m₂ := rfl + (ModuleCat.Hom.hom (R := ↑(R.obj X)) ((tensorObj M₁ M₂).map f)) (m₁ ⊗ₜ[R.obj X] m₂) = + M₁.map f m₁ ⊗ₜ[R.obj Y] M₂.map f m₂ := rfl /-- The tensor product of two morphisms of presheaves of modules. -/ @[simps] @@ -73,8 +75,11 @@ noncomputable def tensorHom (f : M₁ ⟶ M₂) (g : M₃ ⟶ M₄) : tensorObj app X := f.app X ⊗ g.app X naturality {X Y} φ := ModuleCat.MonoidalCategory.tensor_ext (fun m₁ m₃ ↦ by dsimp - rw [tensorObj_map_tmul, ModuleCat.MonoidalCategory.tensorHom_tmul, tensorObj_map_tmul, - naturality_apply, naturality_apply]) + rw [tensorObj_map_tmul] + -- Need `erw` because of the type mismatch in `map` and the tensor product. + erw [ModuleCat.MonoidalCategory.tensorHom_tmul, tensorObj_map_tmul] + rw [naturality_apply, naturality_apply] + simp) end Monoidal diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean index 62c75c356bf58..80d229fe13f6c 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean @@ -28,15 +28,16 @@ namespace PresheafOfModules variable (F : C ⥤ D) +set_option maxHeartbeats 400000 in -- Seems to be a timeout in type checking the definition /-- The pushforward functor on presheaves of modules for a functor `F : C ⥤ D` and `R : Dᵒᵖ ⥤ RingCat`. On the underlying presheaves of abelian groups, it is induced by the precomposition with `F.op`. -/ def pushforward₀ (R : Dᵒᵖ ⥤ RingCat.{u}) : PresheafOfModules.{v} R ⥤ PresheafOfModules.{v} (F.op ⋙ R) where obj M := - { obj := fun X ↦ ModuleCat.of _ (M.obj (F.op.obj X)) - map := fun {X Y} f ↦ M.map (F.op.map f) - map_id := fun X ↦ by + { obj X := ModuleCat.of _ (M.obj (F.op.obj X)) + map {X Y} f := M.map (F.op.map f) + map_id X := by refine ModuleCat.hom_ext -- Work around an instance diamond for `restrictScalarsId'` (@LinearMap.ext _ _ _ _ _ _ _ _ (_) (_) _ _ _ (fun x => ?_)) @@ -46,7 +47,7 @@ def pushforward₀ (R : Dᵒᵖ ⥤ RingCat.{u}) : -- Work around an instance diamond for `restrictScalarsId'` (@LinearMap.ext _ _ _ _ _ _ _ _ (_) (_) _ _ _ (fun x => ?_)) exact (M.congr_map_apply (F.op.map_comp f g) x).trans (by simp) } - map {M₁ M₂} φ := { app := fun X ↦ φ.app _ } + map {M₁ M₂} φ := { app X := φ.app _ } /-- The pushforward of presheaves of modules commutes with the forgetful functor to presheaves of abelian groups. -/ diff --git a/Mathlib/Algebra/Category/ModuleCat/Products.lean b/Mathlib/Algebra/Category/ModuleCat/Products.lean index 937317e6ea0a5..d4a7f6a1b8fcb 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Products.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Products.lean @@ -86,7 +86,7 @@ def coproductCoconeIsColimit : IsColimit (coproductCocone Z) where ext : 1 refine DirectSum.linearMap_ext _ fun i ↦ ?_ ext x - simpa only [LinearMap.coe_comp, Function.comp_apply, toModule_lof] using + simpa only [LinearMap.coe_comp, Function.comp_apply, hom_ofHom, toModule_lof] using congr($(h ⟨i⟩) x) variable [HasCoproduct Z] diff --git a/Mathlib/Algebra/Category/ModuleCat/Subobject.lean b/Mathlib/Algebra/Category/ModuleCat/Subobject.lean index 5fb8394a9c465..29c919d23199d 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Subobject.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Subobject.lean @@ -59,7 +59,7 @@ noncomputable def subobjectModule : Subobject M ≃o Submodule R M := ofHom (underlyingIso (ofHom N.subtype)).symm.toLinearEquiv.toLinearMap := by ext x rfl - rw [this, hom_comp, LinearEquiv.range_comp] + rw [this, hom_comp, hom_ofHom, LinearEquiv.range_comp] · exact (Submodule.range_subtype _).symm map_rel_iff' := fun {S T} => by refine ⟨fun h => ?_, fun h => mk_le_mk_of_comm (↟(Submodule.inclusion h)) rfl⟩ diff --git a/Mathlib/Algebra/Homology/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ConcreteCategory.lean index f510e2876a6f3..9c7f9f7bae473 100644 --- a/Mathlib/Algebra/Homology/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ConcreteCategory.lean @@ -80,7 +80,7 @@ lemma δ_apply (x₃ : (forget₂ C Ab).obj (S.X₃.X i)) AddMonoidHom.zero_apply])) := by refine hS.δ_apply' i j hij _ ((forget₂ C Ab).map (S.X₂.pOpcycles i) x₂) _ ?_ ?_ · rw [← forget₂_comp_apply, ← forget₂_comp_apply, - HomologicalComplex.p_opcyclesMap, Functor.map_comp, comp_apply, + HomologicalComplex.p_opcyclesMap, Functor.map_comp, CategoryTheory.comp_apply, HomologicalComplex.homology_π_ι, forget₂_comp_apply, hx₂, HomologicalComplex.i_cyclesMk] · apply (Preadditive.mono_iff_injective (S.X₂.iCycles j)).1 inferInstance conv_lhs => diff --git a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean index 393b22f24e512..f1b0f96f3b7a0 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean @@ -37,7 +37,7 @@ variable (S : ShortComplex Ab.{u}) @[simp] lemma ab_zero_apply (x : S.X₁) : S.g (S.f x) = 0 := by - rw [← comp_apply, S.zero] + rw [← CategoryTheory.comp_apply, S.zero] rfl /-- The canonical additive morphism `S.X₁ →+ AddMonoidHom.ker S.g` induced by `S.f`. -/ @@ -81,7 +81,7 @@ noncomputable def abCyclesIso : S.cycles ≅ AddCommGrp.of (AddMonoidHom.ker S.g lemma abCyclesIso_inv_apply_iCycles (x : AddMonoidHom.ker S.g) : S.iCycles (S.abCyclesIso.inv x) = x := by dsimp only [abCyclesIso] - rw [← comp_apply, S.abLeftHomologyData.cyclesIso_inv_comp_iCycles] + rw [← CategoryTheory.comp_apply, S.abLeftHomologyData.cyclesIso_inv_comp_iCycles] rfl /-- Given a short complex `S` of abelian groups, this is the isomorphism between @@ -129,7 +129,7 @@ lemma ab_exact_iff_range_eq_ker : S.Exact ↔ S.f.range = S.g.ker := by · intro h refine le_antisymm ?_ h rintro _ ⟨x₁, rfl⟩ - rw [AddMonoidHom.mem_ker, ← comp_apply, S.zero] + rw [AddMonoidHom.mem_ker, ← CategoryTheory.comp_apply, S.zero] rfl · intro h rw [h] diff --git a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean index 92d14ea2564f5..610dbd89fe414 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean @@ -32,7 +32,7 @@ lemma ShortComplex.zero_apply [Limits.HasZeroMorphisms C] [(forget₂ C Ab).PreservesZeroMorphisms] (S : ShortComplex C) (x : (forget₂ C Ab).obj S.X₁) : ((forget₂ C Ab).map S.g) (((forget₂ C Ab).map S.f) x) = 0 := by - rw [← comp_apply, ← Functor.map_comp, S.zero, Functor.map_zero] + rw [← CategoryTheory.comp_apply, ← Functor.map_comp, S.zero, Functor.map_zero] rfl section preadditive @@ -112,8 +112,8 @@ lemma i_cyclesMk [S.HasHomology] (x₂ : (forget₂ C Ab).obj S.X₂) (hx₂ : ((forget₂ C Ab).map S.g) x₂ = 0) : (forget₂ C Ab).map S.iCycles (S.cyclesMk x₂ hx₂) = x₂ := by dsimp [cyclesMk] - erw [← comp_apply, S.mapCyclesIso_hom_iCycles (forget₂ C Ab), - ← comp_apply, abCyclesIso_inv_apply_iCycles ] + erw [← CategoryTheory.comp_apply, S.mapCyclesIso_hom_iCycles (forget₂ C Ab), + ← CategoryTheory.comp_apply, abCyclesIso_inv_apply_iCycles ] end ShortComplex @@ -172,13 +172,13 @@ lemma δ_apply' (x₃ : (forget₂ C Ab).obj D.L₀.X₃) · refine ((congr_hom (e.hom.naturality D.L₁.g) x₂).symm.trans ?_).trans (congr_hom (e.hom.naturality D.v₀₁.τ₃) x₃) dsimp - rw [comp_apply, comp_apply] + rw [CategoryTheory.comp_apply, CategoryTheory.comp_apply] erw [h₂] rfl · refine ((congr_hom (e.hom.naturality D.L₂.f) x₁).symm.trans ?_).trans (congr_hom (e.hom.naturality D.v₁₂.τ₂) x₂) dsimp - rw [comp_apply, comp_apply] + rw [CategoryTheory.comp_apply, CategoryTheory.comp_apply] erw [h₁] rfl diff --git a/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean b/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean index d5e68a50703d7..1b1231d4bd3c3 100644 --- a/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean +++ b/Mathlib/CategoryTheory/Limits/ConcreteCategory/WithAlgebraicStructures.lean @@ -74,7 +74,7 @@ lemma colimit_no_zero_smul_divisor rw [← this, ← map_smul (colimit.ι F j).hom] at hx obtain ⟨j', i, h⟩ := Concrete.colimit_rep_eq_zero (hx := hx) obtain ⟨j'', H⟩ := H - simpa [elementwise_of% (colimit.w F), this, map_zero] using congr(colimit.ι F _ + simpa [elementwise_of% (colimit.w F), ← this, map_zero] using congr(colimit.ι F _ $(H (IsFiltered.sup {j, j', j''} { ⟨j, j', by simp, by simp, i⟩ }) (IsFiltered.toSup _ _ <| by simp) (F.map (IsFiltered.toSup _ _ <| by simp) x) diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean b/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean index 756771dc9da34..c620c7d2c03c8 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean @@ -146,8 +146,7 @@ and the homogeneous `linearYonedaObjResolution`. -/ -- https://github.com/leanprover-community/mathlib4/issues/5164 change d n A f g = diagonalHomEquiv (n + 1) A ((resolution k G).d (n + 1) n ≫ (diagonalHomEquiv n A).symm f) g - rw [diagonalHomEquiv_apply, Action.comp_hom, ModuleCat.hom_comp, LinearMap.comp_apply, - resolution.d_eq] + rw [diagonalHomEquiv_apply, Action.comp_hom, ConcreteCategory.comp_apply, resolution.d_eq] erw [resolution.d_of (Fin.partialProd g)] simp only [map_sum, ← Finsupp.smul_single_one _ ((-1 : k) ^ _)] -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 @@ -188,8 +187,9 @@ noncomputable abbrev inhomogeneousCochains : CochainComplex (ModuleCat k) ℕ := ((linearYonedaObjResolution A).d_comp_d n (n + 1) (n + 2))) simp only [ModuleCat.hom_comp, LinearMap.comp_apply] at this dsimp only - simp only [d_eq, LinearEquiv.toModuleIso_inv_hom, LinearEquiv.toModuleIso_hom_hom, - ModuleCat.hom_comp, LinearMap.comp_apply, LinearEquiv.coe_coe, ModuleCat.hom_zero] + simp only [d_eq, LinearEquiv.toModuleIso_inv, LinearEquiv.toModuleIso_hom, + ModuleCat.hom_comp, LinearMap.comp_apply, LinearEquiv.coe_coe, ModuleCat.hom_zero, + ModuleCat.ofHom_comp] /- Porting note: I can see I need to rewrite `LinearEquiv.coe_coe` twice to at least reduce the need for `symm_apply_apply` to be an `erw`. However, even `erw` refuses to rewrite the second `coe_coe`... -/ @@ -213,11 +213,11 @@ def inhomogeneousCochainsIso : inhomogeneousCochains A ≅ linearYonedaObjResolu ext simp only [ChainComplex.linearYonedaObj_X, linearYoneda_obj_obj_carrier, CochainComplex.of_x, linearYoneda_obj_obj_isAddCommGroup, linearYoneda_obj_obj_isModule, Iso.symm_hom, - ChainComplex.linearYonedaObj_d, ModuleCat.hom_comp, linearYoneda_obj_map_hom, - Quiver.Hom.unop_op, LinearEquiv.toModuleIso_inv_hom, LinearMap.coe_comp, Function.comp_apply, - Linear.leftComp_apply, inhomogeneousCochains.d_def, d_eq, LinearEquiv.toModuleIso_hom_hom, - ModuleCat.ofHom_comp, Category.assoc, LinearEquiv.comp_coe, LinearEquiv.self_trans_symm, - LinearEquiv.refl_toLinearMap, LinearMap.id_comp, LinearEquiv.coe_coe] + LinearEquiv.toModuleIso_inv, ChainComplex.linearYonedaObj_d, ModuleCat.hom_comp, + ModuleCat.hom_ofHom, LinearMap.coe_comp, Function.comp_apply, Linear.leftComp_apply, + inhomogeneousCochains.d_def, d_eq, LinearEquiv.toModuleIso_hom, ModuleCat.ofHom_comp, + Category.assoc, LinearEquiv.comp_coe, LinearEquiv.self_trans_symm, LinearEquiv.refl_toLinearMap, + LinearMap.id_comp, LinearEquiv.coe_coe] rfl /-- The `n`-cocycles `Zⁿ(G, A)` of a `k`-linear `G`-representation `A`, i.e. the kernel of the diff --git a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean index 1c8844cd09b48..ccb8715cbcaa6 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean @@ -205,7 +205,7 @@ theorem dTwo_comp_dOne : dTwo A ∘ₗ dOne A = 0 := by show (ModuleCat.ofHom (dOne A) ≫ ModuleCat.ofHom (dTwo A)).hom = _ have h1 := congr_arg ModuleCat.ofHom (dOne_comp_eq A) have h2 := congr_arg ModuleCat.ofHom (dTwo_comp_eq A) - simp only [ModuleCat.ofHom_comp, ModuleCat.ofHom_comp, ← LinearEquiv.toModuleIso_hom_hom] at h1 h2 + simp only [ModuleCat.ofHom_comp, ModuleCat.ofHom_comp, ← LinearEquiv.toModuleIso_hom] at h1 h2 simp only [(Iso.eq_inv_comp _).2 h2, (Iso.eq_inv_comp _).2 h1, ModuleCat.ofHom_hom, ModuleCat.hom_ofHom, Category.assoc, Iso.hom_inv_id_assoc, HomologicalComplex.d_comp_d_assoc, zero_comp, comp_zero, ModuleCat.hom_zero] diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean index b53ab4e4d4058..ad038c15186b4 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean @@ -494,7 +494,7 @@ theorem d_eq (n : ℕ) : ((groupCohomology.resolution k G).d (n + 1) n).hom = /- Porting note: want to rewrite `LinearMap.smul_apply` but simp/simp_rw won't do it; I need erw, so using Finset.sum_congr to get rid of the binder -/ refine Finset.sum_congr rfl fun _ _ => ?_ - simp only [ModuleCat.hom_smul, SimplexCategory.len_mk] + simp only [ModuleCat.hom_smul, SimplexCategory.len_mk, ModuleCat.hom_ofHom] erw [LinearMap.smul_apply] rw [Finsupp.lmapDomain_apply, Finsupp.mapDomain_single, Finsupp.smul_single', mul_one] rfl @@ -560,7 +560,8 @@ theorem forget₂ToModuleCatHomotopyEquiv_f_0_eq : LinearMap.id fun i => rfl, LinearMap.id_comp] rfl - · congr + · rw [ModuleCat.hom_comp] + congr · ext x dsimp (config := { unfoldPartialApp := true }) [HomotopyEquiv.ofIso, Finsupp.LinearEquiv.finsuppUnique] diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index b5bf54039d5d6..5e1201f82dfad 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -296,7 +296,7 @@ noncomputable def leftRegularHom (A : Rep k G) (x : A) : Rep.ofMulAction k G G theorem leftRegularHom_apply {A : Rep k G} (x : A) : (leftRegularHom A x).hom (Finsupp.single 1 1) = x := by -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [leftRegularHom_hom_hom, Finsupp.lift_apply, Finsupp.sum_single_index, one_smul, + erw [leftRegularHom_hom, Finsupp.lift_apply, Finsupp.sum_single_index, one_smul, A.ρ.map_one, LinearMap.one_apply] rw [zero_smul] @@ -314,9 +314,10 @@ noncomputable def leftRegularHomEquiv (A : Rep k G) : (Rep.ofMulAction k G G ⟶ f.hom ((ofMulAction k G G).ρ x (Finsupp.single (1 : G) (1 : k))) = A.ρ x (f.hom (Finsupp.single (1 : G) (1 : k))) := LinearMap.ext_iff.1 (ModuleCat.hom_ext_iff.mp (f.comm x)) (Finsupp.single 1 1) - simp only [leftRegularHom_hom_hom, LinearMap.comp_apply, Finsupp.lsingle_apply, + simp only [leftRegularHom_hom, LinearMap.comp_apply, Finsupp.lsingle_apply, Finsupp.lift_apply, ← this, coe_of, of_ρ, Representation.ofMulAction_single x (1 : G) (1 : k), - smul_eq_mul, mul_one, zero_smul, Finsupp.sum_single_index, one_smul] + smul_eq_mul, mul_one, zero_smul, Finsupp.sum_single_index, one_smul, + ConcreteCategory.hom_ofHom] -- Mismatched `Zero k` instances rfl right_inv x := leftRegularHom_apply x @@ -324,7 +325,7 @@ noncomputable def leftRegularHomEquiv (A : Rep k G) : (Rep.ofMulAction k G G ⟶ theorem leftRegularHomEquiv_symm_single {A : Rep k G} (x : A) (g : G) : ((leftRegularHomEquiv A).symm x).hom (Finsupp.single g 1) = A.ρ g x := by -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [leftRegularHomEquiv_symm_apply, leftRegularHom_hom_hom, Finsupp.lift_apply, + erw [leftRegularHomEquiv_symm_apply, leftRegularHom_hom, Finsupp.lift_apply, Finsupp.sum_single_index, one_smul] rw [zero_smul] diff --git a/Mathlib/RingTheory/Coalgebra/TensorProduct.lean b/Mathlib/RingTheory/Coalgebra/TensorProduct.lean index dafc8270e1007..e8efc2bbe44ae 100644 --- a/Mathlib/RingTheory/Coalgebra/TensorProduct.lean +++ b/Mathlib/RingTheory/Coalgebra/TensorProduct.lean @@ -57,7 +57,7 @@ noncomputable instance TensorProduct.instCoalgebra : Coalgebra R (M ⊗[R] N) := map_comp_comul := by rw [CoalgebraCat.ofComonObjCoalgebraStruct_comul] simp [-Mon_.monMonoidalStruct_tensorObj_X, - ModuleCat.MonoidalCategory.instMonoidalCategoryStruct_tensorHom_hom, + ModuleCat.MonoidalCategory.instMonoidalCategoryStruct_tensorHom, ModuleCat.hom_comp, ModuleCat.of, ModuleCat.ofHom, ModuleCat.MonoidalCategory.tensorμ_eq_tensorTensorTensorComm] } From 02552f946ec2d20f2f0f57c9b09ad785bb7a14b1 Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Mon, 27 Jan 2025 16:24:05 +0000 Subject: [PATCH 574/681] feat(CategoryTheory): filteredness of Comma catgories given finality of one of the functors (#21128) --- Mathlib/CategoryTheory/Comma/Final.lean | 41 +++++++++++++++++-- .../Comma/StructuredArrow/CommaMap.lean | 2 +- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/Mathlib/CategoryTheory/Comma/Final.lean b/Mathlib/CategoryTheory/Comma/Final.lean index 6c77ce36c3afb..75a9a5c7cd59b 100644 --- a/Mathlib/CategoryTheory/Comma/Final.lean +++ b/Mathlib/CategoryTheory/Comma/Final.lean @@ -6,6 +6,7 @@ Authors: Jakob von Raumer import Mathlib.CategoryTheory.Functor.KanExtension.Adjunction import Mathlib.CategoryTheory.Limits.IsConnected import Mathlib.CategoryTheory.Filtered.Final +import Mathlib.CategoryTheory.Filtered.Flat import Mathlib.CategoryTheory.Grothendieck import Mathlib.CategoryTheory.Comma.StructuredArrow.CommaMap @@ -19,9 +20,12 @@ final and `A` is connected. We then use this in a proof that derives finality of `map` between two comma categories on a quasi-commutative diagram of functors, some of which need to be final. +Finally we prove filteredness of a `Comma L R` given that `R` is final and `A` and `B` are +filtered. + ## References -* [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Lemma 3.4.3 & 3.4.4 +* [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Lemma 3.4.3 -- 3.4.5 -/ universe v₁ v₂ v₃ v₄ v₅ v₆ u₁ u₂ u₃ u₄ u₅ u₆ @@ -109,9 +113,9 @@ end NonSmall Let `F`, `G`, `R` and `R'` be final and `B` be filtered. Then, the induced functor between the comma categories of the first and second row of the diagram is final. -/ -lemma map_final {A : Type u₁} [Category.{v₁} A] {B : Type u₂} [Category.{u₂} B] {T : Type u₃} +lemma map_final {A : Type u₁} [Category.{v₁} A] {B : Type u₂} [Category.{v₂} B] {T : Type u₃} [Category.{v₃} T] {L : A ⥤ T} {R : B ⥤ T} {A' : Type u₄} [Category.{v₄} A'] {B' : Type u₅} - [Category.{v₅} B'] {T' : Type u₂} [Category.{u₂} T'] {L' : A' ⥤ T'} {R' : B' ⥤ T'} {F : A ⥤ A'} + [Category.{v₅} B'] {T' : Type u₆} [Category.{v₆} T'] {L' : A' ⥤ T'} {R' : B' ⥤ T'} {F : A ⥤ A'} {G : B ⥤ B'} {H : T ⥤ T'} (iL : F ⋙ L' ≅ L ⋙ H) (iR : G ⋙ R' ≅ R ⋙ H) [IsFiltered B] [R.Final] [R'.Final] [F.Final] [G.Final] : (Comma.map iL.hom iR.inv).Final := ⟨fun ⟨i₂, j₂, u₂⟩ => by @@ -132,6 +136,37 @@ lemma map_final {A : Type u₁} [Category.{v₁} A] {B : Type u₂} [Category.{u rw [IsIso.Iso.inv_inv] infer_instance⟩ +section Filtered + +variable {A : Type u₁} [Category.{v₁} A] +variable {B : Type u₂} [Category.{v₂} B] +variable {T : Type u₃} [Category.{v₃} T] +variable (L : A ⥤ T) (R : B ⥤ T) + +attribute [local instance] map_final in +/-- Let `A` and `B` be filtered categories, `R : B ⥤ T` be final and `L : A ⥤ T`. Then, the +comma category `Comma L R` is filtered. -/ +lemma isFiltered_of_final [IsFiltered A] [IsFiltered B] [R.Final] : IsFiltered (Comma L R) := by + haveI (a : A) : IsFiltered (Comma (fromPUnit (L.obj a)) R) := + R.final_iff_isFiltered_structuredArrow.mp inferInstance (L.obj a) + have (a : A) : (fromPUnit (Over.mk (𝟙 a))).Final := final_const_of_isTerminal Over.mkIdTerminal + let η (a : A) : fromPUnit (Over.mk (𝟙 a)) ⋙ Over.forget a ⋙ L ≅ fromPUnit (L.obj a) := + NatIso.ofComponents (fun _ => Iso.refl _) + have (a : A) := IsFiltered.of_final (map (L := fromPUnit (L.obj a)) (F := 𝟭 T) (η a).hom + ((Iso.refl (𝟭 B ⋙ R)).inv)) + have : RepresentablyCoflat (fst L R) := + ⟨fun a => IsFiltered.of_equivalence (CostructuredArrow.ofCommaFstEquivalence L R a).symm⟩ + apply isFiltered_of_representablyCoflat (fst L R) + +attribute [local instance] isFiltered_of_final in +/-- Let `A` and `B` be cofiltered categories, `L : A ⥤ T` be initial and `R : B ⥤ T`. Then, the +comma category `Comma L R` is cofiltered. -/ +lemma isCofiltered_of_initial [IsCofiltered A] [IsCofiltered B] [L.Initial] : + IsCofiltered (Comma L R) := + IsCofiltered.of_equivalence (Comma.opEquiv _ _).symm + +end Filtered + end Comma end CategoryTheory diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean index 5a2d0d2c79798..9a0d5b34cc35b 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.lean @@ -23,7 +23,7 @@ noncomputable section variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] {T : Type u₃} [Category.{v₃} T] {L : C ⥤ T} {R : D ⥤ T} {C' : Type u₄} [Category.{v₄} C'] {D' : Type u₅} [Category.{v₅} D'] {T' : Type u₆} - [Category.{u₆} T'] {L' : C' ⥤ T'} {R' : D' ⥤ T'} {F₁ : C ⥤ C'} {F₂ : D ⥤ D'} {F : T ⥤ T'} + [Category.{v₆} T'] {L' : C' ⥤ T'} {R' : D' ⥤ T'} {F₁ : C ⥤ C'} {F₂ : D ⥤ D'} {F : T ⥤ T'} (α : F₁ ⋙ L' ⟶ L ⋙ F) (β : R ⋙ F ⟶ F₂ ⋙ R') /-- The functor establishing the equivalence `StructuredArrow.commaMapEquivalence`. -/ From d7b266a0ed0c00133d416cecc98cc8e6db76a6e8 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Mon, 27 Jan 2025 16:24:07 +0000 Subject: [PATCH 575/681] chore(Algebra/Category): `erw` -> `rw` (#21130) My script found one `erw` call that could become a `rw`. (This can remain `rw` on #21125 too.) --- Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean index d2665b9f8258f..fa3ae76a99db8 100644 --- a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean @@ -873,8 +873,7 @@ lemma homEquiv_extendScalarsId (M : ModuleCat R) : (extendRestrictScalarsAdj (RingHom.id R)).homEquiv _ _ ((extendScalarsId R).hom.app M) = (restrictScalarsId R).inv.app M := by ext m - rw [extendRestrictScalarsAdj_homEquiv_apply, ← extendScalarsId_inv_app_apply] - erw [← comp_apply] + rw [extendRestrictScalarsAdj_homEquiv_apply, ← extendScalarsId_inv_app_apply, ← comp_apply] simp lemma extendScalarsId_hom_app_one_tmul (M : ModuleCat R) (m : M) : From 0a8db061453381ea9485fc4d6db6f05a7c702e0f Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 27 Jan 2025 17:00:00 +0000 Subject: [PATCH 576/681] refactor: unapply matrix lemmas (#21091) These are slightly more convenient expressed in terms of vector operations. `ext; simp` can always be used to restore them to the applied versions. --- Mathlib/Data/Matrix/Mul.lean | 12 +++++++----- Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean | 2 +- Mathlib/LinearAlgebra/Matrix/Hermitian.lean | 2 +- Mathlib/LinearAlgebra/Matrix/PosDef.lean | 4 ++-- Mathlib/LinearAlgebra/Matrix/Spectrum.lean | 7 ++++++- Mathlib/LinearAlgebra/Matrix/ToLin.lean | 2 +- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Mathlib/Data/Matrix/Mul.lean b/Mathlib/Data/Matrix/Mul.lean index 4f71ea9008fa3..e73dffb37c049 100644 --- a/Mathlib/Data/Matrix/Mul.lean +++ b/Mathlib/Data/Matrix/Mul.lean @@ -722,12 +722,12 @@ theorem mulVec_smul [Fintype n] [Monoid R] [NonUnitalNonAssocSemiring S] [Distri @[simp] theorem mulVec_single [Fintype n] [DecidableEq n] [NonUnitalNonAssocSemiring R] (M : Matrix m n R) - (j : n) (x : R) : M *ᵥ Pi.single j x = fun i => M i j * x := + (j : n) (x : R) : M *ᵥ Pi.single j x = MulOpposite.op x • Mᵀ j := funext fun _ => dotProduct_single _ _ _ @[simp] theorem single_vecMul [Fintype m] [DecidableEq m] [NonUnitalNonAssocSemiring R] (M : Matrix m n R) - (i : m) (x : R) : Pi.single i x ᵥ* M = fun j => x * M i j := + (i : m) (x : R) : Pi.single i x ᵥ* M = x • M i := funext fun _ => single_dotProduct _ _ _ theorem mulVec_single_one [Fintype n] [DecidableEq n] [NonAssocSemiring R] @@ -736,7 +736,7 @@ theorem mulVec_single_one [Fintype n] [DecidableEq n] [NonAssocSemiring R] theorem single_one_vecMul [Fintype m] [DecidableEq m] [NonAssocSemiring R] (i : m) (M : Matrix m n R) : - Pi.single i 1 ᵥ* M = M i := by simp + Pi.single i 1 ᵥ* M = M i := by ext; simp theorem diagonal_mulVec_single [Fintype n] [DecidableEq n] [NonUnitalNonAssocSemiring R] (v : n → R) (j : n) (x : R) : diagonal v *ᵥ Pi.single j x = Pi.single j (v j * x) := by @@ -781,12 +781,14 @@ section NonAssocSemiring variable [NonAssocSemiring α] -theorem mulVec_one [Fintype n] (A : Matrix m n α) : A *ᵥ 1 = fun i => ∑ j, A i j := by +theorem mulVec_one [Fintype n] (A : Matrix m n α) : A *ᵥ 1 = ∑ j, Aᵀ j := by ext; simp [mulVec, dotProduct] -theorem vec_one_mul [Fintype m] (A : Matrix m n α) : 1 ᵥ* A = fun j => ∑ i, A i j := by +theorem one_vecMul [Fintype m] (A : Matrix m n α) : 1 ᵥ* A = ∑ i, A i := by ext; simp [vecMul, dotProduct] +@[deprecated (since := "2025-01-26")] alias vec_one_mul := one_vecMul + variable [Fintype m] [Fintype n] [DecidableEq m] @[simp] diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean index 8befb3f75b370..8ae8358bfca55 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean @@ -39,7 +39,7 @@ theorem PiToModule.fromMatrix_apply [DecidableEq ι] (A : Matrix ι ι R) (w : theorem PiToModule.fromMatrix_apply_single_one [DecidableEq ι] (A : Matrix ι ι R) (j : ι) : PiToModule.fromMatrix R b A (Pi.single j 1) = ∑ i : ι, A i j • b i := by rw [PiToModule.fromMatrix_apply, Fintype.linearCombination_apply, Matrix.mulVec_single] - simp_rw [mul_one] + simp_rw [MulOpposite.op_one, one_smul, transpose_apply] /-- The endomorphisms of `M` acts on `(ι → R) →ₗ[R] M`, and takes the projection to a `(ι → R) →ₗ[R] M`. -/ diff --git a/Mathlib/LinearAlgebra/Matrix/Hermitian.lean b/Mathlib/LinearAlgebra/Matrix/Hermitian.lean index 89a34b681a4a6..c7e39b7cc0e1d 100644 --- a/Mathlib/LinearAlgebra/Matrix/Hermitian.lean +++ b/Mathlib/LinearAlgebra/Matrix/Hermitian.lean @@ -279,7 +279,7 @@ theorem isHermitian_iff_isSymmetric [Fintype n] [DecidableEq n] {A : Matrix n n · intro h ext i j simpa only [(Pi.single_star i 1).symm, ← star_mulVec, mul_one, dotProduct_single, - single_vecMul, star_one, one_mul] using h (Pi.single i 1) (Pi.single j 1) + single_one_vecMul, star_one] using h (Pi.single i 1) (Pi.single j 1) end RCLike diff --git a/Mathlib/LinearAlgebra/Matrix/PosDef.lean b/Mathlib/LinearAlgebra/Matrix/PosDef.lean index 5e46c1956c392..7776201ccffd1 100644 --- a/Mathlib/LinearAlgebra/Matrix/PosDef.lean +++ b/Mathlib/LinearAlgebra/Matrix/PosDef.lean @@ -363,8 +363,8 @@ theorem _root_.Matrix.posDef_diagonal_iff PosDef (diagonal d) ↔ ∀ i, 0 < d i := by refine ⟨fun h i => ?_, .diagonal⟩ have := h.2 (Pi.single i 1) - simp only [mulVec_single, mul_one, dotProduct_diagonal', Pi.star_apply, Pi.single_eq_same, - star_one, one_mul, Function.ne_iff, Pi.zero_apply] at this + simp_rw [mulVec_single_one, ← Pi.single_star, star_one, single_dotProduct, one_mul, + transpose_apply, diagonal_apply_eq, Function.ne_iff] at this exact this ⟨i, by simp⟩ protected theorem one [StarOrderedRing R] [DecidableEq n] [NoZeroDivisors R] : diff --git a/Mathlib/LinearAlgebra/Matrix/Spectrum.lean b/Mathlib/LinearAlgebra/Matrix/Spectrum.lean index 3367f16ef2d73..ef6287892c69e 100644 --- a/Mathlib/LinearAlgebra/Matrix/Spectrum.lean +++ b/Mathlib/LinearAlgebra/Matrix/Spectrum.lean @@ -74,6 +74,11 @@ lemma eigenvectorUnitary_coe {𝕜 : Type*} [RCLike 𝕜] {n : Type*} [Fintype n (EuclideanSpace.basisFun n 𝕜).toBasis.toMatrix (hA.eigenvectorBasis).toBasis := rfl +@[simp] +theorem eigenvectorUnitary_transpose_apply (j : n) : + (eigenvectorUnitary hA)ᵀ j = ⇑(hA.eigenvectorBasis j) := + rfl + @[simp] theorem eigenvectorUnitary_apply (i j : n) : eigenvectorUnitary hA i j = ⇑(hA.eigenvectorBasis j) i := @@ -81,7 +86,7 @@ theorem eigenvectorUnitary_apply (i j : n) : theorem eigenvectorUnitary_mulVec (j : n) : eigenvectorUnitary hA *ᵥ Pi.single j 1 = ⇑(hA.eigenvectorBasis j) := by - simp only [mulVec_single, eigenvectorUnitary_apply, mul_one] + simp_rw [mulVec_single_one, eigenvectorUnitary_transpose_apply] theorem star_eigenvectorUnitary_mulVec (j : n) : (star (eigenvectorUnitary hA : Matrix n n 𝕜)) *ᵥ ⇑(hA.eigenvectorBasis j) = Pi.single j 1 := by diff --git a/Mathlib/LinearAlgebra/Matrix/ToLin.lean b/Mathlib/LinearAlgebra/Matrix/ToLin.lean index 1bce52c084cc2..506f38bc302e3 100644 --- a/Mathlib/LinearAlgebra/Matrix/ToLin.lean +++ b/Mathlib/LinearAlgebra/Matrix/ToLin.lean @@ -249,7 +249,7 @@ variable [Fintype n] @[simp] theorem Matrix.mulVecLin_one [DecidableEq n] : Matrix.mulVecLin (1 : Matrix n n R) = LinearMap.id := by - ext; simp [Matrix.one_apply, Pi.single_apply] + ext; simp [Matrix.one_apply, Pi.single_apply, eq_comm] @[simp] theorem Matrix.mulVecLin_mul [Fintype m] (M : Matrix l m R) (N : Matrix m n R) : From b4e8a667d4dfc38cab023a7aedf2b884756e26ec Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Mon, 27 Jan 2025 18:22:27 +0000 Subject: [PATCH 577/681] feat(CategoryTheory): `Comma.snd L R` is final if `R` is final and domains are filtered (#21136) --- Mathlib/CategoryTheory/Comma/Final.lean | 31 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/Mathlib/CategoryTheory/Comma/Final.lean b/Mathlib/CategoryTheory/Comma/Final.lean index 75a9a5c7cd59b..23e5a76639305 100644 --- a/Mathlib/CategoryTheory/Comma/Final.lean +++ b/Mathlib/CategoryTheory/Comma/Final.lean @@ -5,6 +5,7 @@ Authors: Jakob von Raumer -/ import Mathlib.CategoryTheory.Functor.KanExtension.Adjunction import Mathlib.CategoryTheory.Limits.IsConnected +import Mathlib.CategoryTheory.Limits.Sifted import Mathlib.CategoryTheory.Filtered.Final import Mathlib.CategoryTheory.Filtered.Flat import Mathlib.CategoryTheory.Grothendieck @@ -20,8 +21,8 @@ final and `A` is connected. We then use this in a proof that derives finality of `map` between two comma categories on a quasi-commutative diagram of functors, some of which need to be final. -Finally we prove filteredness of a `Comma L R` given that `R` is final and `A` and `B` are -filtered. +Finally we prove filteredness of a `Comma L R` and finality of `snd L R`, given that `R` is final +and `A` and `B` are filtered. ## References @@ -84,9 +85,9 @@ instance final_fst [R.Final] : (fst L R).Final := by exact (Functor.associator _ _ _).symm.trans (Iso.compInverseIso (mapFst _ _)) instance initial_snd [L.Initial] : (snd L R).Initial := by - haveI : ((opFunctor L R).leftOp ⋙ fst R.op L.op).Final := + have : ((opFunctor L R).leftOp ⋙ fst R.op L.op).Final := final_equivalence_comp (opEquiv L R).functor.leftOp (fst R.op L.op) - haveI : (snd L R).op.Final := final_of_natIso (opFunctorCompFst _ _) + have : (snd L R).op.Final := final_of_natIso (opFunctorCompFst _ _) apply initial_of_final_op /-- `Comma L R` with `L : A ⥤ T` and `R : B ⥤ T` is connected if `R` is final and `A` is @@ -146,7 +147,7 @@ variable (L : A ⥤ T) (R : B ⥤ T) attribute [local instance] map_final in /-- Let `A` and `B` be filtered categories, `R : B ⥤ T` be final and `L : A ⥤ T`. Then, the comma category `Comma L R` is filtered. -/ -lemma isFiltered_of_final [IsFiltered A] [IsFiltered B] [R.Final] : IsFiltered (Comma L R) := by +instance isFiltered_of_final [IsFiltered A] [IsFiltered B] [R.Final] : IsFiltered (Comma L R) := by haveI (a : A) : IsFiltered (Comma (fromPUnit (L.obj a)) R) := R.final_iff_isFiltered_structuredArrow.mp inferInstance (L.obj a) have (a : A) : (fromPUnit (Over.mk (𝟙 a))).Final := final_const_of_isTerminal Over.mkIdTerminal @@ -165,6 +166,26 @@ lemma isCofiltered_of_initial [IsCofiltered A] [IsCofiltered B] [L.Initial] : IsCofiltered (Comma L R) := IsCofiltered.of_equivalence (Comma.opEquiv _ _).symm +attribute [local instance] final_of_isFiltered_of_pUnit in +/-- Let `A` and `B` be filtered categories, `R : B ⥤ T` be final and `R : A ⥤ T`. Then, the +projection `snd L R : Comma L R ⥤ B` is final. -/ +instance final_snd [IsFiltered A] [IsFiltered B] [R.Final] : (snd L R).Final := by + let iL : star.{1} A ⋙ 𝟭 _ ≅ L ⋙ star _ := Iso.refl _ + let iR : 𝟭 B ⋙ star.{1} B ≅ R ⋙ star _ := Iso.refl _ + have := map_final iL iR + let s := (equivProd (𝟭 _) (star B)).trans <| prod.leftUnitorEquivalence B + let iS : map iL.hom iR.inv ⋙ s.functor ≅ snd L R := + NatIso.ofComponents (fun _ => Iso.refl _) (fun f => by simp [iL, iR, s]) + apply final_of_natIso iS + +/-- Let `A` and `B` be cofiltered categories, `L : A ⥤ T` be initial and `R : B ⥤ T`. Then, the +projection `fst L R : Comma L R ⥤ A` is initial. -/ +instance initial_fst [IsCofiltered A] [IsCofiltered B] [L.Initial] : (fst L R).Initial := by + have : ((opFunctor L R).leftOp ⋙ snd R.op L.op).Final := + final_equivalence_comp (opEquiv L R).functor.leftOp _ + have : (fst L R).op.Final := final_of_natIso <| opFunctorCompSnd _ _ + apply initial_of_final_op + end Filtered end Comma From 8a5a88ebe43a362aa6fc688857ebb6bfcc31e08e Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 27 Jan 2025 19:34:51 +0000 Subject: [PATCH 578/681] feat: generalize tangent cone lemmas to TVS (#20859) Without any changes to the proofs, these lemmas do not need a normed space. --- Mathlib/Analysis/Calculus/TangentCone.lean | 41 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/Mathlib/Analysis/Calculus/TangentCone.lean b/Mathlib/Analysis/Calculus/TangentCone.lean index 68f5491fa0644..e3061bb13fff2 100644 --- a/Mathlib/Analysis/Calculus/TangentCone.lean +++ b/Mathlib/Analysis/Calculus/TangentCone.lean @@ -70,15 +70,17 @@ def UniqueDiffOn (s : Set E) : Prop := end TangentCone -variable {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] -variable {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] -variable {G : Type*} [NormedAddCommGroup G] [NormedSpace ℝ G] -variable {𝕜} {x y : E} {s t : Set E} +variable {𝕜} +variable {E F G : Type*} section TangentCone -- This section is devoted to the properties of the tangent cone. + open NormedField +section TVS +variable [AddCommGroup E] [Module 𝕜 E] [TopologicalSpace E] +variable {x y : E} {s t : Set E} theorem mem_tangentConeAt_of_pow_smul {r : 𝕜} (hr₀ : r ≠ 0) (hr : ‖r‖ < 1) (hs : ∀ᶠ n : ℕ in atTop, x + r ^ n • y ∈ s) : y ∈ tangentConeAt 𝕜 s x := by @@ -96,6 +98,14 @@ theorem tangentCone_mono (h : s ⊆ t) : tangentConeAt 𝕜 s x ⊆ tangentConeA rintro y ⟨c, d, ds, ctop, clim⟩ exact ⟨c, d, mem_of_superset ds fun n hn => h hn, ctop, clim⟩ +end TVS + +section Normed +variable [NormedAddCommGroup E] [NormedSpace 𝕜 E] +variable [NormedAddCommGroup F] [NormedSpace 𝕜 F] +variable [NormedAddCommGroup G] [NormedSpace ℝ G] +variable {x y : E} {s t : Set E} + /-- Auxiliary lemma ensuring that, under the assumptions defining the tangent cone, the sequence `d` tends to 0 at infinity. -/ theorem tangentConeAt.lim_zero {α : Type*} (l : Filter α) {c : α → 𝕜} {d : α → E} @@ -337,6 +347,8 @@ theorem tangentCone_eq_univ {s : Set 𝕜} {x : 𝕜} (hx : (𝓝[s \ {x}] x).Ne · convert tendsto_const_nhds (α := ℕ) (x := y) with n simp [mul_assoc, inv_mul_cancel₀ (d_ne n)] +end Normed + end TangentCone section UniqueDiff @@ -346,6 +358,9 @@ section UniqueDiff This section is devoted to properties of the predicates `UniqueDiffWithinAt` and `UniqueDiffOn`. -/ +section TVS +variable [AddCommGroup E] [Module 𝕜 E] [TopologicalSpace E] +variable {x y : E} {s t : Set E} theorem UniqueDiffOn.uniqueDiffWithinAt {s : Set E} {x} (hs : UniqueDiffOn 𝕜 s) (h : x ∈ s) : UniqueDiffWithinAt 𝕜 s x := @@ -364,6 +379,13 @@ theorem uniqueDiffOn_empty : UniqueDiffOn 𝕜 (∅ : Set E) := theorem UniqueDiffWithinAt.congr_pt (h : UniqueDiffWithinAt 𝕜 s x) (hy : x = y) : UniqueDiffWithinAt 𝕜 s y := hy ▸ h +end TVS + +section Normed +variable [NormedAddCommGroup E] [NormedSpace 𝕜 E] +variable [NormedAddCommGroup F] [NormedSpace 𝕜 F] +variable {x y : E} {s t : Set E} + theorem UniqueDiffWithinAt.mono_nhds (h : UniqueDiffWithinAt 𝕜 s x) (st : 𝓝[s] x ≤ 𝓝[t] x) : UniqueDiffWithinAt 𝕜 t x := by simp only [uniqueDiffWithinAt_iff] at * @@ -457,6 +479,11 @@ theorem UniqueDiffOn.univ_pi (ι : Type*) [Finite ι] (E : ι → Type*) (h : ∀ i, UniqueDiffOn 𝕜 (s i)) : UniqueDiffOn 𝕜 (Set.pi univ s) := UniqueDiffOn.pi _ _ _ _ fun i _ => h i +end Normed + +section RealNormed +variable [NormedAddCommGroup G] [NormedSpace ℝ G] + /-- In a real vector space, a convex set with nonempty interior is a set of unique differentiability at every point of its closure. -/ theorem uniqueDiffWithinAt_convex {s : Set G} (conv : Convex ℝ s) (hs : (interior s).Nonempty) @@ -479,6 +506,10 @@ theorem uniqueDiffOn_convex {s : Set G} (conv : Convex ℝ s) (hs : (interior s) UniqueDiffOn ℝ s := fun _ xs => uniqueDiffWithinAt_convex conv hs (subset_closure xs) +end RealNormed + +section Real + theorem uniqueDiffOn_Ici (a : ℝ) : UniqueDiffOn ℝ (Ici a) := uniqueDiffOn_convex (convex_Ici a) <| by simp only [interior_Ici, nonempty_Ioi] @@ -532,4 +563,6 @@ theorem uniqueDiffWithinAt_or_nhdsWithin_eq_bot (s : Set 𝕜) (x : 𝕜) : apply neBot_of_le (hf := h) exact nhdsWithin_mono _ diff_subset +end Real + end UniqueDiff From 994a62cac301d73313dcc990c03eea78ad6f97b9 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Mon, 27 Jan 2025 20:28:11 +0000 Subject: [PATCH 579/681] chore(BigOperators/Fin): golf a proof (#21131) Cherry-picked from #21112 --- Mathlib/Algebra/BigOperators/Fin.lean | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Mathlib/Algebra/BigOperators/Fin.lean b/Mathlib/Algebra/BigOperators/Fin.lean index 5e74ef85d66a6..4d62dc8fa144a 100644 --- a/Mathlib/Algebra/BigOperators/Fin.lean +++ b/Mathlib/Algebra/BigOperators/Fin.lean @@ -215,17 +215,7 @@ theorem partialProd_left_inv {G : Type*} [Group G] (f : Fin (n + 1) → G) : @[to_additive] theorem partialProd_right_inv {G : Type*} [Group G] (f : Fin n → G) (i : Fin n) : (partialProd f (Fin.castSucc i))⁻¹ * partialProd f i.succ = f i := by - obtain ⟨i, hn⟩ := i - induction i with - | zero => simp [-Fin.succ_mk, partialProd_succ] - | succ i hi => - specialize hi (lt_trans (Nat.lt_succ_self i) hn) - simp only [Fin.coe_eq_castSucc, Fin.succ_mk, Fin.castSucc_mk] at hi ⊢ - rw [← Fin.succ_mk _ _ (lt_trans (Nat.lt_succ_self _) hn), ← Fin.succ_mk _ _ hn] - simp only [partialProd_succ, mul_inv_rev, Fin.castSucc_mk] - -- Porting note: was - -- assoc_rw [hi, inv_mul_cancel_left] - rw [← mul_assoc, mul_left_eq_self, mul_assoc, hi, inv_mul_cancel] + rw [partialProd_succ, inv_mul_cancel_left] /-- Let `(g₀, g₁, ..., gₙ)` be a tuple of elements in `Gⁿ⁺¹`. Then if `k < j`, this says `(g₀g₁...gₖ₋₁)⁻¹ * g₀g₁...gₖ = gₖ`. From 31612cb1080e72b13cc4edcfbf25ea3f20b5183b Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Mon, 27 Jan 2025 22:45:27 +0000 Subject: [PATCH 580/681] feat(Algebra): `Pi.single_induction` (#21141) From "Formalizing the Bruhat-Tits tree" Co-authored-by: Judith Ludwig Co-authored-by: Christian Merten <136261474+chrisflav@users.noreply.github.com> --- Mathlib/Algebra/BigOperators/Pi.lean | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Mathlib/Algebra/BigOperators/Pi.lean b/Mathlib/Algebra/BigOperators/Pi.lean index 88511371f4a9e..0db9fbd374673 100644 --- a/Mathlib/Algebra/BigOperators/Pi.lean +++ b/Mathlib/Algebra/BigOperators/Pi.lean @@ -181,3 +181,22 @@ def Pi.monoidHomMulEquiv {ι : Type*} [Fintype ι] [DecidableEq ι] (M : ι → MonoidHom.mul_apply, mul_apply] end MulEquiv + +variable [Finite ι] [DecidableEq ι] {M : Type*} + +-- manually additivized to fix variable names +-- See https://github.com/leanprover-community/mathlib4/issues/11462 +lemma Pi.single_induction [AddCommMonoid M] (p : (ι → M) → Prop) (f : ι → M) + (zero : p 0) (add : ∀ f g, p f → p g → p (f + g)) + (single : ∀ i m, p (Pi.single i m)) : p f := by + cases nonempty_fintype ι + rw [← Finset.univ_sum_single f] + exact Finset.sum_induction _ _ add zero (by simp [single]) + +@[to_additive (attr := elab_as_elim) existing] +lemma Pi.mulSingle_induction [CommMonoid M] (p : (ι → M) → Prop) (f : ι → M) + (one : p 1) (mul : ∀ f g, p f → p g → p (f * g)) + (mulSingle : ∀ i m, p (Pi.mulSingle i m)) : p f := by + cases nonempty_fintype ι + rw [← Finset.univ_prod_mulSingle f] + exact Finset.prod_induction _ _ mul one (by simp [mulSingle]) From d66fa49e3527f7b76a2bf37f444667481429ae00 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Mon, 27 Jan 2025 23:15:21 +0000 Subject: [PATCH 581/681] feat(Data/Matroid/Rank/Cardinal): Cardinality-valued rank function (#20921) We abstract out the matroid property of 'having a well-defined `Cardinality`-valued rank function' as a typeclass `Matroid.CardinalRank`, and use it to define a rank function `Matroid.cardRk` and prove basic properties. The fact that `Finitary` matroids have such a rank function is now provided as an instance. --- Mathlib/Data/Matroid/Basic.lean | 3 + Mathlib/Data/Matroid/Rank/Cardinal.lean | 353 ++++++++++++++++++++---- 2 files changed, 301 insertions(+), 55 deletions(-) diff --git a/Mathlib/Data/Matroid/Basic.lean b/Mathlib/Data/Matroid/Basic.lean index 60a143ac60a47..4bef987a38c32 100644 --- a/Mathlib/Data/Matroid/Basic.lean +++ b/Mathlib/Data/Matroid/Basic.lean @@ -217,6 +217,9 @@ namespace Matroid variable {α : Type*} {M : Matroid α} +instance (M : Matroid α) : Nonempty {B // M.Base B} := + nonempty_subtype.2 M.exists_base + /-- Typeclass for a matroid having finite ground set. Just a wrapper for `M.E.Finite`-/ @[mk_iff] protected class Finite (M : Matroid α) : Prop where /-- The ground set is finite -/ diff --git a/Mathlib/Data/Matroid/Rank/Cardinal.lean b/Mathlib/Data/Matroid/Rank/Cardinal.lean index b12a9f56efadb..0d10845213b06 100644 --- a/Mathlib/Data/Matroid/Rank/Cardinal.lean +++ b/Mathlib/Data/Matroid/Rank/Cardinal.lean @@ -3,46 +3,294 @@ Copyright (c) 2025 Peter Nelson and Junyan Xu. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Peter Nelson, Junyan Xu -/ -import Mathlib.Data.Matroid.Restrict +import Mathlib.Data.Matroid.Closure +import Mathlib.Data.Matroid.Map import Mathlib.SetTheory.Cardinal.Arithmetic /-! -# Invariance of cardinality of bases of a finitary matroid +# Cardinal-valued rank In a finitary matroid, all bases have the same cardinality. -In fact, something stronger holds: if `B` and `B'` are bases, then `#(B \ B') = #(B' \ B)`. -This file provides proofs of these facts, -as well as variants when each of `B` and `B'` is a `Basis` or `Basis'` of some common set `X`. +In fact, something stronger holds: if `I` and `J` are both bases for a set `X`, +then `#(I \ J) = #(J \ I)` and (consequently) `#I = #J`. +This file introduces a typeclass `InvariantCardinalRank` that applies to any matroid +such that this property holds for all `I`, `J` and `X`. -Some extra assumption like `Finitary` is necessary for these to be true, +A matroid satisfying this condition has a well-defined cardinality-valued rank function, +both for itself and all its minors. + +# Main Declarations + +* `Matroid.InvariantCardinalRank` : a typeclass capturing the idea that a matroid and all its minors + have a well-behaved cardinal-valued rank function. +* `Matroid.cRank M` is the supremum of the cardinalities of the bases of matroid `M`. +* `Matroid.cRk M X` is the supremum of the cardinalities of the bases of a set `X` in a matroid `M`. +* `invariantCardinalRank_of_finitary` is the instance + showing that `Finitary` matroids are `InvariantCardinalRank`. +* `cRk_inter_add_cRk_union_le` states that cardinal rank is submodular. + +# Notes + +It is not the case that all matroids are `InvariantCardinalRank`, since the equicardinality of bases in general matroids is independent of ZFC -(see the docstring of `Data.Matroid.Basic`). -Lemmas like `Matroid.Base.cardinalMk_diff_comm_of_finitary` -become true for all matroids if they are weakened by replacing `Cardinal.mk` -with the cruder `ℕ∞`-valued `encard`; see, for example, `Matroid.Base.encard_diff_comm`. +(see the module docstring of `Mathlib.Data.Matroid.Basic`). +Lemmas like `Matroid.Base.cardinalMk_diff_comm` become true for all matroids +only if they are weakened by replacing `Cardinal.mk` +with the cruder `ℕ∞`-valued `Set.encard`; see, for example, `Matroid.Base.encard_diff_comm`. + +# Implementation Details + +Since the functions `cRank` and `cRk` are defined as suprema, +independently of the `Matroid.InvariantCardinalRank` typeclass, +they are well-defined for all matroids. +However, for matroids that do not satisfy `InvariantCardinalRank`, they are badly behaved. +For instance, in general `cRk` is not submodular, +and its value may differ on a set `X` and the closure of `X`. +We state and prove theorems without `InvariantCardinalRank` whenever possible, +which sometime makes their proofs longer than they would be with the instance. -TODO +# TODO + +* Higgs' theorem : if the generalized continuum hypothesis holds, + then every matroid is `InvariantCardinalRank`. -* Higg's theorem that, if the generalized continuum hypothesis holds, - all bases of any matroid are equicardinal. -* API for a `Cardinal`-valued rank function. -/ -variable {α : Type*} {M : Matroid α} {I J B B' X : Set α} [M.Finitary] +universe u v + +variable {α : Type u} {β : Type v} {f : α → β} {M : Matroid α} {I J B B' X Y : Set α} open Cardinal Set namespace Matroid -theorem Base.cardinalMk_diff_comm_of_finitary (hB : M.Base B) (hB' : M.Base B') : - #(B \ B' : Set α) = #(B' \ B : Set α) := by - wlog hge : #(B' \ B : Set α) ≤ #(B \ B' : Set α) with aux - · exact (aux hB' hB (not_le.1 hge).le).symm +section Rank + +variable {κ : Cardinal} + +/-- The rank (supremum of the cardinalities of bases) of a matroid `M` as a `Cardinal`. -/ +noncomputable def cRank (M : Matroid α) := ⨆ (B : {B // M.Base B}), #B + +/-- The rank (supremum of the cardinalities of bases) of a set `X` in a matroid `M`, +as a `Cardinal`. -/ +noncomputable def cRk (M : Matroid α) (X : Set α) := (M ↾ X).cRank + +theorem Base.cardinalMk_le_cRank (hB : M.Base B) : #B ≤ M.cRank := + le_ciSup (f := fun (B : {B // M.Base B}) ↦ #(B.1)) (bddAbove_range _) ⟨B, hB⟩ + +theorem Basis'.cardinalMk_le_cRk (hIX : M.Basis' I X) : #I ≤ M.cRk X := + (base_restrict_iff'.2 hIX).cardinalMk_le_cRank + +theorem Basis.cardinalMk_le_cRk (hIX : M.Basis I X) : #I ≤ M.cRk X := + hIX.basis'.cardinalMk_le_cRk + +theorem cRank_le_iff : M.cRank ≤ κ ↔ ∀ ⦃B⦄, M.Base B → #B ≤ κ := + ⟨fun h _ hB ↦ (hB.cardinalMk_le_cRank.trans h), fun h ↦ ciSup_le fun ⟨_, hB⟩ ↦ h hB⟩ + +theorem cRk_le_iff : M.cRk X ≤ κ ↔ ∀ ⦃I⦄, M.Basis' I X → #I ≤ κ := by + simp_rw [cRk, cRank_le_iff, base_restrict_iff'] + +theorem Indep.cardinalMk_le_cRk_of_subset (hI : M.Indep I) (hIX : I ⊆ X) : #I ≤ M.cRk X := + let ⟨_, hJ, hIJ⟩ := hI.subset_basis'_of_subset hIX + (mk_le_mk_of_subset hIJ).trans hJ.cardinalMk_le_cRk + +theorem cRk_le_cardinalMk (M : Matroid α) (X : Set α) : M.cRk X ≤ #X := + ciSup_le fun ⟨_, hI⟩ ↦ mk_le_mk_of_subset hI.subset_ground + +@[simp] theorem cRk_ground (M : Matroid α) : M.cRk M.E = M.cRank := by + rw [cRk, restrict_ground_eq_self] + +@[simp] theorem cRank_restrict (M : Matroid α) (X : Set α) : (M ↾ X).cRank = M.cRk X := rfl + +theorem cRk_mono (M : Matroid α) : Monotone M.cRk := by + simp only [Monotone, le_eq_subset, cRk_le_iff] + intro X Y hXY I hIX + obtain ⟨J, hJ, hIJ⟩ := hIX.indep.subset_basis'_of_subset (hIX.subset.trans hXY) + exact (mk_le_mk_of_subset hIJ).trans hJ.cardinalMk_le_cRk + +theorem cRk_le_of_subset (M : Matroid α) (hXY : X ⊆ Y) : M.cRk X ≤ M.cRk Y := + M.cRk_mono hXY + +@[simp] theorem cRk_inter_ground (M : Matroid α) (X : Set α) : M.cRk (X ∩ M.E) = M.cRk X := + (M.cRk_le_of_subset inter_subset_left).antisymm <| cRk_le_iff.2 + fun _ h ↦ h.basis_inter_ground.cardinalMk_le_cRk + +theorem cRk_restrict_subset (M : Matroid α) (hYX : Y ⊆ X) : (M ↾ X).cRk Y = M.cRk Y := by + have aux : ∀ ⦃I⦄, M.Basis' I Y ↔ (M ↾ X).Basis' I Y := by + simp_rw [basis'_restrict_iff, inter_eq_self_of_subset_left hYX, iff_self_and] + exact fun I h ↦ h.subset.trans hYX + simp_rw [le_antisymm_iff, cRk_le_iff] + exact ⟨fun I hI ↦ (aux.2 hI).cardinalMk_le_cRk, fun I hI ↦ (aux.1 hI).cardinalMk_le_cRk⟩ + +theorem cRk_restrict (M : Matroid α) (X Y : Set α) : (M ↾ X).cRk Y = M.cRk (X ∩ Y) := by + rw [← cRk_inter_ground, restrict_ground_eq, cRk_restrict_subset _ inter_subset_right, + inter_comm] + +theorem Indep.cRk_eq_cardinalMk (hI : M.Indep I) : #I = M.cRk I := + (M.cRk_le_cardinalMk I).antisymm' (hI.basis_self.cardinalMk_le_cRk) + +@[simp] theorem cRk_map_image_lift (M : Matroid α) (hf : InjOn f M.E) (X : Set α) + (hX : X ⊆ M.E := by aesop_mat) : lift.{u,v} ((M.map f hf).cRk (f '' X)) = lift (M.cRk X) := by + nth_rw 1 [cRk, cRank, le_antisymm_iff, lift_iSup (bddAbove_range _), cRk, cRank, cRk, cRank] + nth_rw 2 [lift_iSup (bddAbove_range _)] + simp only [ciSup_le_iff (bddAbove_range _), ge_iff_le, Subtype.forall, base_restrict_iff', + basis'_iff_basis hX, basis'_iff_basis (show f '' X ⊆ (M.map f hf).E from image_mono hX)] + refine ⟨fun I hI ↦ ?_, fun I hI ↦ ?_⟩ + · obtain ⟨I, X', hIX, rfl, hXX'⟩ := map_basis_iff'.1 hI + rw [mk_image_eq_of_injOn_lift _ _ (hf.mono hIX.indep.subset_ground), lift_le] + obtain rfl : X = X' := by rwa [hf.image_eq_image_iff hX hIX.subset_ground] at hXX' + exact hIX.cardinalMk_le_cRk + rw [← mk_image_eq_of_injOn_lift _ _ (hf.mono hI.indep.subset_ground), lift_le] + exact (hI.map hf).cardinalMk_le_cRk + +@[simp] theorem cRk_map_image {β : Type u} {f : α → β} (M : Matroid α) (hf : InjOn f M.E) + (X : Set α) (hX : X ⊆ M.E := by aesop_mat) : (M.map f hf).cRk (f '' X) = M.cRk X := + lift_inj.1 <| M.cRk_map_image_lift .. + +theorem cRk_map_eq {β : Type u} {f : α → β} {X : Set β} (M : Matroid α) (hf : InjOn f M.E) : + (M.map f hf).cRk X = M.cRk (f ⁻¹' X) := by + rw [← M.cRk_inter_ground, ← M.cRk_map_image hf _, image_preimage_inter, ← map_ground _ _ hf, + cRk_inter_ground] + +@[simp] theorem cRk_comap_lift (M : Matroid β) (f : α → β) (X : Set α) : + lift.{v,u} ((M.comap f).cRk X) = lift (M.cRk (f '' X)) := by + nth_rw 1 [cRk, cRank, le_antisymm_iff, lift_iSup (bddAbove_range _), cRk, cRank, cRk, cRank] + nth_rw 2 [lift_iSup (bddAbove_range _)] + simp only [ciSup_le_iff (bddAbove_range _), ge_iff_le, Subtype.forall, base_restrict_iff', + comap_basis'_iff, and_imp] + refine ⟨fun I hI hfI hIX ↦ ?_, fun I hIX ↦ ?_⟩ + · rw [← mk_image_eq_of_injOn_lift _ _ hfI, lift_le] + exact hI.cardinalMk_le_cRk + obtain ⟨I₀, hI₀X, rfl, hfI₀⟩ := show ∃ I₀ ⊆ X, f '' I₀ = I ∧ InjOn f I₀ by + obtain ⟨I₀, hI₀ss, hbij⟩ := exists_subset_bijOn (f ⁻¹' I ∩ X) f + refine ⟨I₀, hI₀ss.trans inter_subset_right, ?_, hbij.injOn⟩ + rw [hbij.image_eq, image_preimage_inter, inter_eq_self_of_subset_left hIX.subset] + rw [mk_image_eq_of_injOn_lift _ _ hfI₀, lift_le] + exact Basis'.cardinalMk_le_cRk <| comap_basis'_iff.2 ⟨hIX, hfI₀, hI₀X⟩ + +@[simp] theorem cRk_comap {β : Type u} (M : Matroid β) (f : α → β) (X : Set α) : + (M.comap f).cRk X = M.cRk (f '' X) := + lift_inj.1 <| M.cRk_comap_lift .. + +end Rank + +section Invariant + +/-- A class stating that cardinality-valued rank is well-defined +(i.e. all bases are equicardinal) for a matroid `M` and its minors. +Notably, this holds for `Finitary` matroids; see `Matroid.invarCardinalRank_of_finitary`. -/ +@[mk_iff] +class InvariantCardinalRank (M : Matroid α) : Prop where + forall_card_basis_diff : + ∀ ⦃I J X⦄, M.Basis I X → M.Basis J X → #(I \ J : Set α) = #(J \ I : Set α) + +variable [InvariantCardinalRank M] + +theorem Basis.cardinalMk_diff_comm (hIX : M.Basis I X) (hJX : M.Basis J X) : + #(I \ J : Set α) = #(J \ I : Set α) := + InvariantCardinalRank.forall_card_basis_diff hIX hJX + +theorem Basis'.cardinalMk_diff_comm (hIX : M.Basis' I X) (hJX : M.Basis' J X) : + #(I \ J : Set α) = #(J \ I : Set α) := + hIX.basis_inter_ground.cardinalMk_diff_comm hJX.basis_inter_ground + +theorem Base.cardinalMk_diff_comm (hB : M.Base B) (hB' : M.Base B') : + #(B \ B' : Set α) = #(B' \ B : Set α) := + hB.basis_ground.cardinalMk_diff_comm hB'.basis_ground + +theorem Basis.cardinalMk_eq (hIX : M.Basis I X) (hJX : M.Basis J X) : #I = #J := by + rw [← diff_union_inter I J, + mk_union_of_disjoint (disjoint_sdiff_left.mono_right inter_subset_right), + hIX.cardinalMk_diff_comm hJX, + ← mk_union_of_disjoint (disjoint_sdiff_left.mono_right inter_subset_left), + inter_comm, diff_union_inter] + +theorem Basis'.cardinalMk_eq (hIX : M.Basis' I X) (hJX : M.Basis' J X) : #I = #J := + hIX.basis_inter_ground.cardinalMk_eq hJX.basis_inter_ground + +theorem Base.cardinalMk_eq (hB : M.Base B) (hB' : M.Base B') : #B = #B' := + hB.basis_ground.cardinalMk_eq hB'.basis_ground + +theorem Indep.cardinalMk_le_base (hI : M.Indep I) (hB : M.Base B) : #I ≤ #B := + have ⟨_B', hB', hIB'⟩ := hI.exists_base_superset + hB'.cardinalMk_eq hB ▸ mk_le_mk_of_subset hIB' + +theorem Indep.cardinalMk_le_basis' (hI : M.Indep I) (hJ : M.Basis' J X) (hIX : I ⊆ X) : + #I ≤ #J := + have ⟨_J', hJ', hIJ'⟩ := hI.subset_basis'_of_subset hIX + hJ'.cardinalMk_eq hJ ▸ mk_le_mk_of_subset hIJ' + +theorem Indep.cardinalMk_le_basis (hI : M.Indep I) (hJ : M.Basis J X) (hIX : I ⊆ X) : + #I ≤ #J := + hI.cardinalMk_le_basis' hJ.basis' hIX + +theorem Base.cardinalMk_eq_cRank (hB : M.Base B) : #B = M.cRank := by + have hrw : ∀ B' : {B : Set α // M.Base B}, #B' = #B := fun B' ↦ B'.2.cardinalMk_eq hB + simp [cRank, hrw] + +/-- Restrictions of matroids with cardinal rank functions have cardinal rank functions- -/ +instance invariantCardinalRank_restrict [InvariantCardinalRank M] : + InvariantCardinalRank (M ↾ X) := by + refine ⟨fun I J Y hI hJ ↦ ?_⟩ + rw [basis_restrict_iff'] at hI hJ + exact hI.1.cardinalMk_diff_comm hJ.1 + +theorem Basis'.cardinalMk_eq_cRk (hIX : M.Basis' I X) : #I = M.cRk X := by + rw [cRk, (base_restrict_iff'.2 hIX).cardinalMk_eq_cRank] + +theorem Basis.cardinalMk_eq_cRk (hIX : M.Basis I X) : #I = M.cRk X := + hIX.basis'.cardinalMk_eq_cRk + +@[simp] theorem cRk_closure (M : Matroid α) [InvariantCardinalRank M] (X : Set α) : + M.cRk (M.closure X) = M.cRk X := by + obtain ⟨I, hI⟩ := M.exists_basis' X + rw [← hI.basis_closure_right.cardinalMk_eq_cRk, ← hI.cardinalMk_eq_cRk] + +theorem cRk_closure_congr (hXY : M.closure X = M.closure Y) : M.cRk X = M.cRk Y := by + rw [← cRk_closure, hXY, cRk_closure] + +variable (M : Matroid α) [InvariantCardinalRank M] (e : α) (X Y : Set α) + +@[simp] theorem cRk_union_closure_right_eq : M.cRk (X ∪ M.closure Y) = M.cRk (X ∪ Y) := + M.cRk_closure_congr (M.closure_union_closure_right_eq _ _) + +@[simp] theorem cRk_union_closure_left_eq : M.cRk (M.closure X ∪ Y) = M.cRk (X ∪ Y) := + M.cRk_closure_congr (M.closure_union_closure_left_eq _ _) + +@[simp] theorem cRk_insert_closure_eq : M.cRk (insert e (M.closure X)) = M.cRk (insert e X) := by + rw [← union_singleton, cRk_union_closure_left_eq, union_singleton] + +theorem cRk_union_closure_eq : M.cRk (M.closure X ∪ M.closure Y) = M.cRk (X ∪ Y) := by + simp + +/-- The `Cardinal` rank function is submodular. -/ +theorem cRk_inter_add_cRk_union_le : M.cRk (X ∩ Y) + M.cRk (X ∪ Y) ≤ M.cRk X + M.cRk Y := by + obtain ⟨Ii, hIi⟩ := M.exists_basis' (X ∩ Y) + obtain ⟨IX, hIX, hIX'⟩ := + hIi.indep.subset_basis'_of_subset (hIi.subset.trans inter_subset_left) + obtain ⟨IY, hIY, hIY'⟩ := + hIi.indep.subset_basis'_of_subset (hIi.subset.trans inter_subset_right) + rw [← cRk_union_closure_eq, ← hIX.closure_eq_closure, ← hIY.closure_eq_closure, + cRk_union_closure_eq, ← hIi.cardinalMk_eq_cRk, ← hIX.cardinalMk_eq_cRk, + ← hIY.cardinalMk_eq_cRk, ← mk_union_add_mk_inter, add_comm] + exact add_le_add (M.cRk_le_cardinalMk _) (mk_le_mk_of_subset (subset_inter hIX' hIY')) + +end Invariant + +section Instances + +/-- `Finitary` matroids have a cardinality-valued rank function. -/ +instance invariantCardinalRank_of_finitary [Finitary M] : InvariantCardinalRank M := by + suffices aux : ∀ ⦃B B'⦄ ⦃N : Matroid α⦄, Finitary N → N.Base B → N.Base B' → + #(B \ B' : Set α) ≤ #(B' \ B : Set α) from + ⟨fun I J X hI hJ ↦ (aux (restrict_finitary X) hI.base_restrict hJ.base_restrict).antisymm + (aux (restrict_finitary X) hJ.base_restrict hI.base_restrict)⟩ + intro B B' N hfin hB hB' by_cases h : (B' \ B).Finite · rw [← cast_ncard h, ← cast_ncard, hB.ncard_diff_comm hB'] - exact (diff_finite_comm hB' hB).mp h + exact (hB'.diff_finite_comm hB).mp h rw [← Set.Infinite, ← infinite_coe_iff] at h - have (a : α) (ha : a ∈ B' \ B) : ∃ S : Set α, Finite S ∧ S ⊆ B ∧ ¬ M.Indep (insert a S) := by + have (a : α) (ha : a ∈ B' \ B) : ∃ S : Set α, Finite S ∧ S ⊆ B ∧ ¬ N.Indep (insert a S) := by have := (hB.insert_dep ⟨hB'.subset_ground ha.1, ha.2⟩).1 contrapose! this exact Finitary.indep_of_forall_finite _ fun J hJ fin ↦ (this (J \ {a}) fin.diff.to_subtype <| @@ -50,7 +298,7 @@ theorem Base.cardinalMk_diff_comm_of_finitary (hB : M.Base B) (hB' : M.Base B') choose S S_fin hSB dep using this let U := ⋃ a : ↥(B' \ B), S a a.2 suffices B \ B' ⊆ U by - refine hge.antisymm' <| (mk_le_mk_of_subset this).trans <| (mk_iUnion_le ..).trans + refine (mk_le_mk_of_subset this).trans <| (mk_iUnion_le ..).trans <| (mul_le_max_of_aleph0_le_left (by simp)).trans ?_ simp only [sup_le_iff, le_refl, true_and] exact ciSup_le' fun e ↦ (lt_aleph0_of_finite _).le.trans <| by simp @@ -63,40 +311,35 @@ theorem Base.cardinalMk_diff_comm_of_finitary (hB : M.Base B) (hB' : M.Base B') refine dep a this (ind.subset <| insert_subset_insert <| .trans ?_ subset_union_right) exact subset_iUnion_of_subset ⟨a, this⟩ subset_rfl -theorem Base.cardinalMk_eq_of_finitary (hB : M.Base B) (hB' : M.Base B') : #B = #B' := by - rw [← diff_union_inter B B', - mk_union_of_disjoint (disjoint_sdiff_left.mono_right inter_subset_right), - hB.cardinalMk_diff_comm_of_finitary hB', - ← mk_union_of_disjoint (disjoint_sdiff_left.mono_right inter_subset_left), - inter_comm, diff_union_inter] - -theorem Basis'.cardinalMk_diff_comm_of_finitary (hIX : M.Basis' I X) (hJX : M.Basis' J X) : - #(I \ J : Set α) = #(J \ I : Set α) := by - rw [← base_restrict_iff'] at hIX hJX - rw [hIX.cardinalMk_diff_comm_of_finitary hJX] - -theorem Basis.cardinalMk_diff_comm_of_finitary (hIX : M.Basis I X) (hJX : M.Basis J X) : - #(I \ J : Set α) = #(J \ I : Set α) := - hIX.basis'.cardinalMk_diff_comm_of_finitary hJX.basis' - -theorem Basis'.cardinalMk_eq_of_finitary (hIX : M.Basis' I X) (hJX : M.Basis' J X) : #I = #J := by - rw [← base_restrict_iff'] at hIX hJX - rw [hIX.cardinalMk_eq_of_finitary hJX] - -theorem Basis.cardinalMk_eq_of_finitary (hIX : M.Basis I X) (hJX : M.Basis J X) : #I = #J := - hIX.basis'.cardinalMk_eq_of_finitary hJX.basis' +instance invariantCardinalRank_map (M : Matroid α) [InvariantCardinalRank M] (hf : InjOn f M.E) : + InvariantCardinalRank (M.map f hf) := by + refine ⟨fun I J X hI hJ ↦ ?_⟩ + obtain ⟨I, X, hIX, rfl, rfl⟩ := map_basis_iff'.1 hI + obtain ⟨J, X', hJX, rfl, h'⟩ := map_basis_iff'.1 hJ + obtain rfl : X = X' := by + rwa [InjOn.image_eq_image_iff hf hIX.subset_ground hJX.subset_ground] at h' + have hcard := hIX.cardinalMk_diff_comm hJX + rwa [← lift_inj.{u,v}, + ← mk_image_eq_of_injOn_lift _ _ (hf.mono ((hIX.indep.diff _).subset_ground)), + ← mk_image_eq_of_injOn_lift _ _ (hf.mono ((hJX.indep.diff _).subset_ground)), + lift_inj, (hf.mono hIX.indep.subset_ground).image_diff, + (hf.mono hJX.indep.subset_ground).image_diff, inter_comm, + hf.image_inter hJX.indep.subset_ground hIX.indep.subset_ground, + diff_inter_self_eq_diff, diff_self_inter] at hcard -theorem Indep.cardinalMk_le_base_of_finitary (hI : M.Indep I) (hB : M.Base B) : #I ≤ #B := - have ⟨_B', hB', hIB'⟩ := hI.exists_base_superset - hB'.cardinalMk_eq_of_finitary hB ▸ mk_le_mk_of_subset hIB' +instance invariantCardinalRank_comap (M : Matroid β) [InvariantCardinalRank M] (f : α → β) : + InvariantCardinalRank (M.comap f) := by + refine ⟨fun I J X hI hJ ↦ ?_⟩ + obtain ⟨hI, hfI, hIX⟩ := comap_basis_iff.1 hI + obtain ⟨hJ, hfJ, hJX⟩ := comap_basis_iff.1 hJ + rw [← lift_inj.{u,v}, ← mk_image_eq_of_injOn_lift _ _ (hfI.mono diff_subset), + ← mk_image_eq_of_injOn_lift _ _ (hfJ.mono diff_subset), lift_inj, hfI.image_diff, + hfJ.image_diff, ← diff_union_diff_cancel inter_subset_left (image_inter_subset f I J), + inter_comm, diff_inter_self_eq_diff, mk_union_of_disjoint, hI.cardinalMk_diff_comm hJ, + ← diff_union_diff_cancel inter_subset_left (image_inter_subset f J I), inter_comm, + diff_inter_self_eq_diff, mk_union_of_disjoint, inter_comm J I] <;> + exact disjoint_sdiff_left.mono_right (diff_subset.trans inter_subset_left) -theorem Indep.cardinalMk_le_basis'_of_finitary (hI : M.Indep I) (hJ : M.Basis' J X) (hIX : I ⊆ X) : - #I ≤ #J := - have ⟨_J', hJ', hIJ'⟩ := hI.subset_basis'_of_subset hIX - hJ'.cardinalMk_eq_of_finitary hJ ▸ mk_le_mk_of_subset hIJ' - -theorem Indep.cardinalMk_le_basis_of_finitary (hI : M.Indep I) (hJ : M.Basis J X) (hIX : I ⊆ X) : - #I ≤ #J := - hI.cardinalMk_le_basis'_of_finitary hJ.basis' hIX +end Instances end Matroid From 59594e2d95f5e4dae0e564f8088a9d99d558b699 Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Mon, 27 Jan 2025 23:24:32 +0000 Subject: [PATCH 582/681] feat(Topology/Algebra/Indicator): indicator of a clopen is continuous (#20687) Indicator functions of clopen subsets are continuous. --- Mathlib/Topology/Algebra/Indicator.lean | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mathlib/Topology/Algebra/Indicator.lean b/Mathlib/Topology/Algebra/Indicator.lean index 189c9d6f29038..87a704835566a 100644 --- a/Mathlib/Topology/Algebra/Indicator.lean +++ b/Mathlib/Topology/Algebra/Indicator.lean @@ -5,6 +5,7 @@ Authors: PFR contributors -/ import Mathlib.Algebra.Group.Indicator import Mathlib.Topology.ContinuousOn +import Mathlib.Topology.Clopen /-! # Continuity of indicator functions @@ -36,3 +37,8 @@ theorem ContinuousOn.continuousAt_mulIndicator (hf : ContinuousOn f (interior s) ⟨interior s, hs, Set.eqOn_mulIndicator.symm.mono interior_subset⟩ · exact ContinuousAt.congr continuousAt_const <| Filter.eventuallyEq_iff_exists_mem.mpr ⟨sᶜ, mem_interior_iff_mem_nhds.mp h, Set.eqOn_mulIndicator'.symm⟩ + +@[to_additive] +lemma IsClopen.continuous_mulIndicator (hs : IsClopen s) (hf : Continuous f) : + Continuous (s.mulIndicator f) := + hf.mulIndicator (by simp [isClopen_iff_frontier_eq_empty.mp hs]) From ffa9869ea0460f7f85318a96cec21f0ef8430ecc Mon Sep 17 00:00:00 2001 From: damiano Date: Mon, 27 Jan 2025 23:55:31 +0000 Subject: [PATCH 583/681] fix(CI): use `Elab.async=false` for late importers workflow (#21147) Spotted in [this Zulip message](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Late.20importers.20report/near/496179935). --- .github/workflows/latest_import.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/latest_import.yml b/.github/workflows/latest_import.yml index aa7a52cd7f981..6e9b5b0cf2cfd 100644 --- a/.github/workflows/latest_import.yml +++ b/.github/workflows/latest_import.yml @@ -48,8 +48,10 @@ jobs: - name: add minImports linter option run: | - # set `linter.minImports option` to true in `lakefile` - sed -i -- '/^ -- '\`'latest_import.yml'\`' uses this comment/{s=^= ⟨`linter.minImports, true⟩,\n=}' lakefile.lean + # we disable checking for backticks inside single quotes with the next line + # shellcheck disable=SC2016 + # set `linter.minImports option` to true and `Elab.async` to false in `lakefile` + sed -i -- '/^ -- '\`'latest_import.yml'\`' uses this comment/{s=^= ⟨`linter.minImports, true⟩,\n ⟨`Elab.async, false⟩,\n=}' lakefile.lean # import the `minImports` linter in `Mathlib.Init` sed -i -z 's=^=import Mathlib.Tactic.Linter.MinImports\n=' Mathlib/Init.lean From 9c435f84e5559c1cf8d4ae4882b5a75970200b21 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 28 Jan 2025 00:03:54 +0000 Subject: [PATCH 584/681] chore(SupIndep): speedup the `Decidable` instance (#21114) The new instance runs in polynomial time instead of exponential. --- Mathlib/Order/SupIndep.lean | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Mathlib/Order/SupIndep.lean b/Mathlib/Order/SupIndep.lean index 68a3a6a1f2487..3642adc8ce776 100644 --- a/Mathlib/Order/SupIndep.lean +++ b/Mathlib/Order/SupIndep.lean @@ -5,7 +5,6 @@ Authors: Aaron Anderson, Kevin Buzzard, Yaël Dillies, Eric Wieser -/ import Mathlib.Data.Finset.Sigma import Mathlib.Data.Finset.Pairwise -import Mathlib.Data.Finset.Powerset import Mathlib.Data.Fintype.Basic import Mathlib.Order.CompleteLatticeIntervals @@ -58,13 +57,27 @@ def SupIndep (s : Finset ι) (f : ι → α) : Prop := variable {s t : Finset ι} {f : ι → α} {i : ι} -instance [DecidableEq ι] [DecidableEq α] : Decidable (SupIndep s f) := by - refine @Finset.decidableForallOfDecidableSubsets _ _ _ (?_) - rintro t - - refine @Finset.decidableDforallFinset _ _ _ (?_) - rintro i - - have : Decidable (Disjoint (f i) (sup t f)) := decidable_of_iff' (_ = ⊥) disjoint_iff - infer_instance +/-- The RHS looks like the definition of `iSupIndep`. -/ +theorem supIndep_iff_disjoint_erase [DecidableEq ι] : + s.SupIndep f ↔ ∀ i ∈ s, Disjoint (f i) ((s.erase i).sup f) := + ⟨fun hs _ hi => hs (erase_subset _ _) hi (not_mem_erase _ _), fun hs _ ht i hi hit => + (hs i hi).mono_right (sup_mono fun _ hj => mem_erase.2 ⟨ne_of_mem_of_not_mem hj hit, ht hj⟩)⟩ + +/-- If both the index type and the lattice have decidable equality, +then the `SupIndep` predicate is decidable. + +TODO: speedup the definition and drop the `[DecidableEq ι]` assumption +by iterating over the pairs `(a, t)` such that `s = Finset.cons a t _` +using something like `List.eraseIdx` +or by generating both `f i` and `(s.erase i).sup f` in one loop over `s`. +Yet another possible optimization is to precompute partial suprema of `f` +over the inits and tails of the list representing `s`, +store them in 2 `Array`s, +then compute each `sup` in 1 operation. -/ +instance [DecidableEq ι] [DecidableEq α] : Decidable (SupIndep s f) := + have : ∀ i, Decidable (Disjoint (f i) ((s.erase i).sup f)) := fun _ ↦ + decidable_of_iff _ disjoint_iff.symm + decidable_of_iff _ supIndep_iff_disjoint_erase.symm theorem SupIndep.subset (ht : t.SupIndep f) (h : s ⊆ t) : s.SupIndep f := fun _ hu _ hi => ht (hu.trans h) (h hi) @@ -88,12 +101,6 @@ theorem SupIndep.le_sup_iff (hs : s.SupIndep f) (hts : t ⊆ s) (hi : i ∈ s) ( by_contra hit exact hf i (disjoint_self.1 <| (hs hts hi hit).mono_right h) -/-- The RHS looks like the definition of `iSupIndep`. -/ -theorem supIndep_iff_disjoint_erase [DecidableEq ι] : - s.SupIndep f ↔ ∀ i ∈ s, Disjoint (f i) ((s.erase i).sup f) := - ⟨fun hs _ hi => hs (erase_subset _ _) hi (not_mem_erase _ _), fun hs _ ht i hi hit => - (hs i hi).mono_right (sup_mono fun _ hj => mem_erase.2 ⟨ne_of_mem_of_not_mem hj hit, ht hj⟩)⟩ - theorem supIndep_antimono_fun {g : ι → α} (h : ∀ x ∈ s, f x ≤ g x) (h : s.SupIndep g) : s.SupIndep f := by classical From 8959d57303deecbecaa12b1d7f25808c0f534561 Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Tue, 28 Jan 2025 00:34:40 +0000 Subject: [PATCH 585/681] feat(Matrix): more lemmas for `PEquiv.toMatrix` (#21143) Also - add `Matrix.transpose_stdBasisMatrix` and `conjTranspose` version - add `Matrix.ext_ofMulVec` - tag `Matrix.GeneralLinearGroup.map` with `@[simps]` From "Formalizing the Bruhat-Tits tree" Co-authored by: Judith Ludwig Co-authored-by: Eric Wieser --- Mathlib/Data/Matrix/Basis.lean | 11 +++++++ Mathlib/Data/Matrix/ConjTranspose.lean | 8 +++++ Mathlib/Data/Matrix/Mul.lean | 14 +++++++++ Mathlib/Data/Matrix/PEquiv.lean | 31 ++++++++++++++++--- .../Matrix/GeneralLinearGroup/Defs.lean | 1 + 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/Mathlib/Data/Matrix/Basis.lean b/Mathlib/Data/Matrix/Basis.lean index 69638ec2666c4..d7eeeed30a977 100644 --- a/Mathlib/Data/Matrix/Basis.lean +++ b/Mathlib/Data/Matrix/Basis.lean @@ -49,6 +49,17 @@ theorem stdBasisMatrix_zero (i : m) (j : n) : stdBasisMatrix i j (0 : α) = 0 := ext simp +@[simp] +lemma transpose_stdBasisMatrix (i : m) (j : n) (a : α) : + (stdBasisMatrix i j a)ᵀ = stdBasisMatrix j i a := by + aesop (add unsafe unfold stdBasisMatrix) + +@[simp] +lemma map_stdBasisMatrix (i : m) (j : n) (a : α) {β : Type*} [Zero β] + {F : Type*} [FunLike F α β] [ZeroHomClass F α β] (f : F) : + (stdBasisMatrix i j a).map f = stdBasisMatrix i j (f a) := by + aesop (add unsafe unfold stdBasisMatrix) + end Zero theorem stdBasisMatrix_add [AddZeroClass α] (i : m) (j : n) (a b : α) : diff --git a/Mathlib/Data/Matrix/ConjTranspose.lean b/Mathlib/Data/Matrix/ConjTranspose.lean index 4b856340799ca..f43539add8aae 100644 --- a/Mathlib/Data/Matrix/ConjTranspose.lean +++ b/Mathlib/Data/Matrix/ConjTranspose.lean @@ -11,6 +11,7 @@ import Mathlib.Algebra.Star.BigOperators import Mathlib.Algebra.Star.Module import Mathlib.Algebra.Star.Pi import Mathlib.Data.Fintype.BigOperators +import Mathlib.Data.Matrix.Basis import Mathlib.Data.Matrix.Mul /-! @@ -40,6 +41,13 @@ def conjTranspose [Star α] (M : Matrix m n α) : Matrix n m α := @[inherit_doc] scoped postfix:1024 "ᴴ" => Matrix.conjTranspose +@[simp] +lemma conjTranspose_stdBasisMatrix [DecidableEq n] [DecidableEq m] [AddMonoid α] + [StarAddMonoid α] (i : m) (j : n) (a : α) : + (stdBasisMatrix i j a)ᴴ = stdBasisMatrix j i (star a) := by + show (stdBasisMatrix i j a).transpose.map starAddEquiv = stdBasisMatrix j i (star a) + simp + section Diagonal variable [DecidableEq n] diff --git a/Mathlib/Data/Matrix/Mul.lean b/Mathlib/Data/Matrix/Mul.lean index e73dffb37c049..c074c0ef47fff 100644 --- a/Mathlib/Data/Matrix/Mul.lean +++ b/Mathlib/Data/Matrix/Mul.lean @@ -789,6 +789,20 @@ theorem one_vecMul [Fintype m] (A : Matrix m n α) : 1 ᵥ* A = ∑ i, A i := by @[deprecated (since := "2025-01-26")] alias vec_one_mul := one_vecMul +lemma ext_of_mulVec_single [DecidableEq n] [Fintype n] {M N : Matrix m n α} + (h : ∀ i, M *ᵥ Pi.single i 1 = N *ᵥ Pi.single i 1) : + M = N := by + ext i j + simp_rw [mulVec_single_one] at h + exact congrFun (h j) i + +lemma ext_of_single_vecMul [DecidableEq m] [Fintype m] {M N : Matrix m n α} + (h : ∀ i, Pi.single i 1 ᵥ* M = Pi.single i 1 ᵥ* N) : + M = N := by + ext i j + simp_rw [single_one_vecMul] at h + exact congrFun (h i) j + variable [Fintype m] [Fintype n] [DecidableEq m] @[simp] diff --git a/Mathlib/Data/Matrix/PEquiv.lean b/Mathlib/Data/Matrix/PEquiv.lean index 632eaa239a6fa..98cb355cc674a 100644 --- a/Mathlib/Data/Matrix/PEquiv.lean +++ b/Mathlib/Data/Matrix/PEquiv.lean @@ -40,7 +40,7 @@ open Matrix universe u v variable {k l m n : Type*} -variable {α : Type v} +variable {α β : Type*} open Matrix @@ -102,21 +102,36 @@ theorem transpose_toMatrix_toPEquiv_apply ext simp [toMatrix_apply, Pi.single_apply, eq_comm, ← Equiv.apply_eq_iff_eq_symm_apply] -theorem toMatrix_toPEquiv_mul [Fintype m] [DecidableEq m] [Semiring α] (f : m ≃ m) - (M : Matrix m n α) : f.toPEquiv.toMatrix * M = M.submatrix f id := by +theorem toMatrix_toPEquiv_mul [Fintype m] [DecidableEq m] + [Semiring α] (f : l ≃ m) (M : Matrix m n α) : + f.toPEquiv.toMatrix * M = M.submatrix f id := by ext i j rw [toMatrix_mul_apply, Equiv.toPEquiv_apply, submatrix_apply, id] @[deprecated (since := "2025-01-27")] alias toPEquiv_mul_matrix := toMatrix_toPEquiv_mul -theorem mul_toMatrix_toPEquiv {m n α : Type*} [Fintype n] [DecidableEq n] [Semiring α] (f : n ≃ n) - (M : Matrix m n α) : M * f.toPEquiv.toMatrix = M.submatrix id f.symm := +theorem mul_toMatrix_toPEquiv [Fintype m] [DecidableEq n] + [Semiring α] (M : Matrix l m α) (f : m ≃ n) : + (M * f.toPEquiv.toMatrix) = M.submatrix id f.symm := Matrix.ext fun i j => by rw [PEquiv.mul_toMatrix_apply, ← Equiv.toPEquiv_symm, Equiv.toPEquiv_apply, Matrix.submatrix_apply, id] @[deprecated (since := "2025-01-27")] alias mul_toPEquiv_toMatrix := mul_toMatrix_toPEquiv +lemma toMatrix_toPEquiv_mulVec [DecidableEq n] [Fintype n] + [NonAssocSemiring α] (σ : m ≃ n) (a : n → α) : + σ.toPEquiv.toMatrix *ᵥ a = a ∘ σ := by + ext j + simp [toMatrix, mulVec, dotProduct] + +lemma vecMul_toMatrix_toPEquiv [DecidableEq n] [Fintype m] + [NonAssocSemiring α] (σ : m ≃ n) (a : m → α) : + a ᵥ* σ.toPEquiv.toMatrix = a ∘ σ.symm := by + classical + ext j + simp [toMatrix, σ.apply_eq_iff_eq_symm_apply, vecMul, dotProduct] + theorem toMatrix_trans [Fintype m] [DecidableEq m] [DecidableEq n] [Semiring α] (f : l ≃. m) (g : m ≃. n) : ((f.trans g).toMatrix : Matrix l n α) = f.toMatrix * g.toMatrix := by ext i j @@ -178,4 +193,10 @@ theorem toMatrix_toPEquiv_eq [DecidableEq n] [Zero α] [One α] (σ : Equiv.Perm @[deprecated (since := "2025-01-27")] alias equiv_toPEquiv_toMatrix := toMatrix_toPEquiv_eq +@[simp] +lemma map_toMatrix [DecidableEq n] [NonAssocSemiring α] [NonAssocSemiring β] + (f : α →+* β) (σ : m ≃. n) : σ.toMatrix.map f = σ.toMatrix := by + ext i j + simp + end PEquiv diff --git a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean index 6a59c9e32abf2..e61efb9e17587 100644 --- a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean +++ b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean @@ -130,6 +130,7 @@ end CoeLemmas variable {S T : Type*} [CommRing S] [CommRing T] /-- A ring homomorphism ``f : R →+* S`` induces a homomorphism ``GLₙ(f) : GLₙ(R) →* GLₙ(S)``. -/ +@[simps! apply_val] def map (f : R →+* S) : GL n R →* GL n S := Units.map <| (RingHom.mapMatrix f).toMonoidHom @[simp] From 2d4a40714ede518ac0e07965d3145ad9209b2537 Mon Sep 17 00:00:00 2001 From: Yunkai Zhang Date: Tue, 28 Jan 2025 01:12:04 +0000 Subject: [PATCH 586/681] doc: fixed notation error in customizing category composition (#21132) Fixed the notation error on defining customised composition following conventions, which is incorrectly ported from Lean 3. --- Mathlib/CategoryTheory/Category/Basic.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Category/Basic.lean b/Mathlib/CategoryTheory/Category/Basic.lean index e47e8bcebd744..247f3da889691 100644 --- a/Mathlib/CategoryTheory/Category/Basic.lean +++ b/Mathlib/CategoryTheory/Category/Basic.lean @@ -23,7 +23,7 @@ Introduces notations in the `CategoryTheory` scope Users may like to add `g ⊚ f` for composition in the standard convention, using ```lean -local notation g ` ⊚ `:80 f:80 := category.comp f g -- type as \oo +local notation:80 g " ⊚ " f:80 => CategoryTheory.CategoryStruct.comp f g -- type as \oo ``` ## Porting note From ddd2cd27004c9dce41e8cd7bcda7604ecb895cb1 Mon Sep 17 00:00:00 2001 From: maddycrim <58754954+maddycrim@users.noreply.github.com> Date: Tue, 28 Jan 2025 01:27:09 +0000 Subject: [PATCH 587/681] feat(RingTheory/Localization/Pi): localization of a finite direct product is a product of localizations (#19042) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For lemma ` isUnit_piRingHom_algebraMap_comp_piEvalRingHom` : Let `M` be a submonoid of a direct product of commutative rings `R i`, and let `M' i` denote the projection of `M` onto each corresponding factor. Given a ring homomorphism from the direct product `Π i, R i` to the product of the localizations of each `R i` at `M' i`, every `y : M` maps to a unit under this homomorphism. For theorem `bijective_lift_piRingHom_algebraMap_comp_piEvalRingHom` : Let `M` be a submonoid of a direct product of commutative rings `R i`, and let `M' i` denote the projection of `M` onto each factor. Then the canonical map from the localization of the direct product `Π i, R i` at `M` to the direct product of the localizations of each `R i` at `M' i` is bijective. Co-authored-by: maddycrim Co-authored-by: Junyan Xu Co-authored-by: Madison Crim --- Mathlib.lean | 1 + Mathlib/Algebra/Algebra/Pi.lean | 9 +++ Mathlib/RingTheory/Localization/Basic.lean | 5 ++ Mathlib/RingTheory/Localization/Pi.lean | 79 ++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 Mathlib/RingTheory/Localization/Pi.lean diff --git a/Mathlib.lean b/Mathlib.lean index 612bcdad18894..770fd7dd35750 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4637,6 +4637,7 @@ import Mathlib.RingTheory.Localization.LocalizationLocalization import Mathlib.RingTheory.Localization.Module import Mathlib.RingTheory.Localization.NormTrace import Mathlib.RingTheory.Localization.NumDen +import Mathlib.RingTheory.Localization.Pi import Mathlib.RingTheory.Localization.Submodule import Mathlib.RingTheory.MatrixAlgebra import Mathlib.RingTheory.Multiplicity diff --git a/Mathlib/Algebra/Algebra/Pi.lean b/Mathlib/Algebra/Algebra/Pi.lean index 188a138794019..f6a57e3d71a44 100644 --- a/Mathlib/Algebra/Algebra/Pi.lean +++ b/Mathlib/Algebra/Algebra/Pi.lean @@ -48,6 +48,15 @@ theorem algebraMap_apply {_ : CommSemiring R} [_s : ∀ i, Semiring (f i)] [∀ (a : R) (i : I) : algebraMap R (∀ i, f i) a i = algebraMap R (f i) a := rfl +variable {I} in +instance (g : I → Type*) [∀ i, CommSemiring (f i)] [∀ i, Semiring (g i)] + [∀ i, Algebra (f i) (g i)] : Algebra (∀ i, f i) (∀ i, g i) where + algebraMap := Pi.ringHom fun _ ↦ (algebraMap _ _).comp (Pi.evalRingHom f _) + commutes' _ _ := funext fun _ ↦ Algebra.commutes _ _ + smul_def' _ _ := funext fun _ ↦ Algebra.smul_def _ _ + +example [∀ i, CommSemiring (f i)] : Pi.instAlgebraForall f f = Algebra.id _ := rfl + -- One could also build a `∀ i, R i`-algebra structure on `∀ i, A i`, -- when each `A i` is an `R i`-algebra, although I'm not sure that it's useful. variable {I} (R) diff --git a/Mathlib/RingTheory/Localization/Basic.lean b/Mathlib/RingTheory/Localization/Basic.lean index 22ac6c09fc61e..8b0b1e1417be3 100644 --- a/Mathlib/RingTheory/Localization/Basic.lean +++ b/Mathlib/RingTheory/Localization/Basic.lean @@ -296,6 +296,11 @@ theorem isLocalization_iff_of_isLocalization [IsLocalization M S] [IsLocalizatio ⟨fun _ ↦ isLocalization_of_algEquiv N (algEquiv M S P), fun _ ↦ isLocalization_of_algEquiv M (algEquiv N S P)⟩ +theorem iff_of_le_of_exists_dvd (N : Submonoid R) (h₁ : M ≤ N) (h₂ : ∀ n ∈ N, ∃ m ∈ M, n ∣ m) : + IsLocalization M S ↔ IsLocalization N S := + have : IsLocalization N (Localization M) := of_le_of_exists_dvd _ _ h₁ h₂ + isLocalization_iff_of_isLocalization _ _ (Localization M) + end variable (M) diff --git a/Mathlib/RingTheory/Localization/Pi.lean b/Mathlib/RingTheory/Localization/Pi.lean new file mode 100644 index 0000000000000..28a3911c43cd7 --- /dev/null +++ b/Mathlib/RingTheory/Localization/Pi.lean @@ -0,0 +1,79 @@ +/- +Copyright (c) 2024 Madison Crim. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Madison Crim +-/ +import Mathlib.Algebra.Algebra.Pi +import Mathlib.Algebra.BigOperators.Pi +import Mathlib.Algebra.Divisibility.Prod +import Mathlib.Algebra.Group.Submonoid.BigOperators +import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.RingTheory.Localization.Basic +import Mathlib.Algebra.Group.Pi.Units + +/-! +# Localizing a product of commutative rings + +## Main Result + + * `bijective_lift_piRingHom_algebraMap_comp_piEvalRingHom`: the canonical map from a + localization of a finite product of rings `R i `at a monoid `M` to the direct product of + localizations `R i` at the projection of `M` onto each corresponding factor is bijective. + +## Implementation notes + +See `Mathlib/RingTheory/Localization/Defs.lean` for a design overview. + +## Tags +localization, commutative ring +-/ + +namespace IsLocalization + +variable {ι : Type*} (R S : ι → Type*) + [Π i, CommSemiring (R i)] [Π i, CommSemiring (S i)] [Π i, Algebra (R i) (S i)] + +/-- If `S i` is a localization of `R i` at the submonoid `M i` for each `i`, +then `Π i, S i` is a localization of `Π i, R i` at the product submonoid. -/ +instance (M : Π i, Submonoid (R i)) [∀ i, IsLocalization (M i) (S i)] : + IsLocalization (.pi .univ M) (Π i, S i) where + map_units' m := Pi.isUnit_iff.mpr fun i ↦ map_units _ ⟨m.1 i, m.2 i ⟨⟩⟩ + surj' z := by + choose rm h using fun i ↦ surj (M := M i) (z i) + exact ⟨(fun i ↦ (rm i).1, ⟨_, fun i _ ↦ (rm i).2.2⟩), funext h⟩ + exists_of_eq {x y} eq := by + choose c hc using fun i ↦ exists_of_eq (M := M i) (congr_fun eq i) + exact ⟨⟨_, fun i _ ↦ (c i).2⟩, funext hc⟩ + +variable (S' : Type*) [CommSemiring S'] [Algebra (Π i, R i) S'] (M : Submonoid (Π i, R i)) + +theorem iff_map_piEvalRingHom [Finite ι] : + IsLocalization M S' ↔ IsLocalization (.pi .univ fun i ↦ M.map (Pi.evalRingHom R i)) S' := + iff_of_le_of_exists_dvd M _ (fun m hm i _ ↦ ⟨m, hm, rfl⟩) fun n hn ↦ by + choose m mem eq using hn + have := Fintype.ofFinite ι + refine ⟨∏ i, m i ⟨⟩, prod_mem fun i _ ↦ mem i _, pi_dvd_iff.mpr fun i ↦ ?_⟩ + rw [Fintype.prod_apply] + exact (eq i ⟨⟩).symm.dvd.trans (Finset.dvd_prod_of_mem _ <| Finset.mem_univ _) + +variable [∀ i, IsLocalization (M.map (Pi.evalRingHom R i)) (S i)] + +/-- Let `M` be a submonoid of a direct product of commutative rings `R i`, and let `M' i` denote +the projection of `M` onto each corresponding factor. Given a ring homomorphism from the direct +product `Π i, R i` to the product of the localizations of each `R i` at `M' i`, every `y : M` +maps to a unit under this homomorphism. -/ +lemma isUnit_piRingHom_algebraMap_comp_piEvalRingHom (y : M) : + IsUnit ((Pi.ringHom fun i ↦ (algebraMap (R i) (S i)).comp (Pi.evalRingHom R i)) y) := + Pi.isUnit_iff.mpr fun i ↦ map_units _ (⟨y.1 i, y, y.2, rfl⟩ : M.map (Pi.evalRingHom R i)) + +/-- Let `M` be a submonoid of a direct product of commutative rings `R i`, and let `M' i` denote +the projection of `M` onto each factor. Then the canonical map from the localization of the direct +product `Π i, R i` at `M` to the direct product of the localizations of each `R i` at `M' i` +is bijective. -/ +theorem bijective_lift_piRingHom_algebraMap_comp_piEvalRingHom [IsLocalization M S'] [Finite ι] : + Function.Bijective (lift (S := S') (isUnit_piRingHom_algebraMap_comp_piEvalRingHom R S M)) := + have := (iff_map_piEvalRingHom R (Π i, S i) M).mpr inferInstance + (ringEquivOfRingEquiv (M := M) (T := M) _ _ (.refl _) <| + Submonoid.map_equiv_eq_comap_symm _ _).bijective + +end IsLocalization From 022b2bf37f267274f9d7dfcf6735ca9d6bf7f47f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 28 Jan 2025 02:20:58 +0000 Subject: [PATCH 588/681] feat(SetTheory/Game/PGame): rewrite left moves of `-x` as right moves of `x` under binders (#21109) These lemmas strengthen our simp set considerably, and allow us to now prove various other theorems by `simp` on the negative game. See [Zulip](https://leanprover.zulipchat.com/#narrow/channel/116395-maths/topic/Poset.20games/near/496019881) for some discussion on this. --- Mathlib/SetTheory/Game/PGame.lean | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 8186fa7fea3eb..ac6caee7a3166 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -1363,6 +1363,26 @@ theorem moveRight_neg_symm {x : PGame} (i) : theorem moveRight_neg_symm' {x : PGame} (i) : x.moveRight i = -(-x).moveLeft (toLeftMovesNeg i) := by simp +@[simp] +theorem forall_leftMoves_neg {x : PGame} {p : (-x).LeftMoves → Prop} : + (∀ i : (-x).LeftMoves, p i) ↔ (∀ i : x.RightMoves, p (toLeftMovesNeg i)) := + toLeftMovesNeg.forall_congr_right.symm + +@[simp] +theorem exists_leftMoves_neg {x : PGame} {p : (-x).LeftMoves → Prop} : + (∃ i : (-x).LeftMoves, p i) ↔ (∃ i : x.RightMoves, p (toLeftMovesNeg i)) := + toLeftMovesNeg.exists_congr_right.symm + +@[simp] +theorem forall_rightMoves_neg {x : PGame} {p : (-x).RightMoves → Prop} : + (∀ i : (-x).RightMoves, p i) ↔ (∀ i : x.LeftMoves, p (toRightMovesNeg i)) := + toRightMovesNeg.forall_congr_right.symm + +@[simp] +theorem exists_rightMoves_neg {x : PGame} {p : (-x).RightMoves → Prop} : + (∃ i : (-x).RightMoves, p i) ↔ (∃ i : x.LeftMoves, p (toRightMovesNeg i)) := + toRightMovesNeg.exists_congr_right.symm + theorem leftMoves_neg_cases {x : PGame} (k) {P : (-x).LeftMoves → Prop} (h : ∀ i, P <| toLeftMovesNeg i) : P k := by From 7bf93b83ed499ab6331c882f890e1cb4ad0dfac7 Mon Sep 17 00:00:00 2001 From: Yunkai Zhang Date: Tue, 28 Jan 2025 02:20:59 +0000 Subject: [PATCH 589/681] feat(CategoryTheory/Endofunctor): prove the dual form of Lambek's Lemma on terminal coalgebra (#21140) Implement the proof of the coalgebra form of Lambek's lemma, stating that if the category of coalgebra on endofunctors has a terminal coalgebra T, then the structure map of the terminal coalgebra is an isomorphism. --- .../CategoryTheory/Endofunctor/Algebra.lean | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Endofunctor/Algebra.lean b/Mathlib/CategoryTheory/Endofunctor/Algebra.lean index fe740cc36ff77..aaf7e3bd09385 100644 --- a/Mathlib/CategoryTheory/Endofunctor/Algebra.lean +++ b/Mathlib/CategoryTheory/Endofunctor/Algebra.lean @@ -17,7 +17,6 @@ coalgebras over `G`. ## TODO -* Prove the dual result about the structure map of the terminal coalgebra of an endofunctor. * Prove that if the countable infinite product over the powers of the endofunctor exists, then algebras over the endofunctor coincide with algebras over the free monad on the endofunctor. -/ @@ -382,6 +381,35 @@ def equivOfNatIso {F G : C ⥤ C} (α : F ≅ G) : Coalgebra F ≌ Coalgebra G w counitIso := (functorOfNatTransComp _ _).symm ≪≫ functorOfNatTransEq (by simp) ≪≫ functorOfNatTransId +namespace Terminal + +variable {A} (h : @Limits.IsTerminal (Coalgebra F) _ A) + +/-- The inverse of the structure map of an terminal coalgebra -/ +@[simp] +def strInv : F.obj A.1 ⟶ A.1 := + (h.from ⟨F.obj A.V, F.map A.str⟩).f + +theorem right_inv' : + ⟨A.str ≫ strInv h, by rw [Category.assoc, F.map_comp, strInv, ← Hom.h] ⟩ = 𝟙 A := + Limits.IsTerminal.hom_ext h _ (𝟙 A) + +theorem right_inv : A.str ≫ strInv h = 𝟙 _ := + congr_arg Hom.f (right_inv' h) + +theorem left_inv : strInv h ≫ A.str = 𝟙 _ := by + rw [strInv, ← (h.from ⟨F.obj A.V, F.map A.str⟩).h, ← F.map_id, ← F.map_comp] + congr + exact right_inv h + +/-- The structure map of the terminal coalgebra is an isomorphism, +hence endofunctors preserve their terminal coalgebras +-/ +theorem str_isIso (h : Limits.IsTerminal A) : IsIso A.str := + { out := ⟨strInv h, right_inv _, left_inv _⟩ } + +end Terminal + end Coalgebra namespace Adjunction From 6ac68693d219f89dcb242e9565245f1fbe108953 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Tue, 28 Jan 2025 03:55:35 +0000 Subject: [PATCH 590/681] feat(Data/Matroid/Circuit): fundamental circuits and extensionality (#21145) We define the fundamental circuit in a matroid for a set `I` and an element `e`, then use it to show that dependent sets all contain circuits, and a circuit-based extensionality lemma. --- Mathlib/Data/Matroid/Circuit.lean | 157 +++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 2 deletions(-) diff --git a/Mathlib/Data/Matroid/Circuit.lean b/Mathlib/Data/Matroid/Circuit.lean index d8f568c93c09e..cd068114bce61 100644 --- a/Mathlib/Data/Matroid/Circuit.lean +++ b/Mathlib/Data/Matroid/Circuit.lean @@ -16,6 +16,24 @@ In matroids arising from graphs, circuits correspond to graphical cycles. # Main Declarations * `Matroid.Circuit M C` means that `C` is minimally dependent in `M`. +* For an `Indep`endent set `I` whose closure contains an element `e ∉ I`, + `Matroid.fundCircuit M e I` is the unique circuit contained in `insert e I`. +* `Matroid.Indep.fundCircuit_circuit` states that `Matroid.fundCircuit M e I` is indeed a circuit. +* `Circuit.eq_fundCircuit_of_subset` states that `Matroid.fundCircuit M e I` is the + unique circuit contained in `insert e I`. +* `Matroid.dep_iff_superset_circuit` states that the dependent subsets of the ground set + are precisely those that contain a circuit. +* `Matroid.ext_circuit` : a matroid is determined by its collection of circuits. + +# Implementation Details + +Since `Matroid.fundCircuit M e I` is only sensible if `I` is independent and `e ∈ M.closure I \ I`, +to avoid hypotheses being explicitly included in the definition, +junk values need to be chosen if either hypothesis fails. +The definition is chosen so that the junk values satisfy +`M.fundCircuit e I = {e}` for `e ∈ I` and +`M.fundCircuit e I = insert e I` if `e ∉ M.closure I`. +These make the useful statement `e ∈ M.fundCircuit e I ⊆ insert e I` true unconditionally. -/ variable {α : Type*} {M : Matroid α} {C C' I X Y R : Set α} {e f x y : α} @@ -87,6 +105,10 @@ lemma Circuit.not_ssubset (hC : M.Circuit C) (hC' : M.Circuit C') : ¬C' ⊂ C : lemma Circuit.eq_of_subset_circuit (hC : M.Circuit C) (hC' : M.Circuit C') (h : C ⊆ C') : C = C' := hC'.eq_of_dep_subset hC.dep h +lemma Circuit.eq_of_superset_circuit (hC : M.Circuit C) (hC' : M.Circuit C') (h : C' ⊆ C) : + C = C' := + (hC'.eq_of_subset_circuit hC h).symm + lemma circuit_iff_dep_forall_diff_singleton_indep : M.Circuit C ↔ M.Dep C ∧ ∀ e ∈ C, M.Indep (C \ {e}) := by wlog hCE : C ⊆ M.E @@ -155,8 +177,7 @@ lemma Circuit.mem_closure_diff_singleton_of_mem (hC : M.Circuit C) (heC : e ∈ /-! ### Restriction -/ -lemma Circuit.circuit_restrict_of_subset (hC : M.Circuit C) (hCR : C ⊆ R) : - (M ↾ R).Circuit C := by +lemma Circuit.circuit_restrict_of_subset (hC : M.Circuit C) (hCR : C ⊆ R) : (M ↾ R).Circuit C := by simp_rw [circuit_iff, restrict_dep_iff, dep_iff, and_imp] at * exact ⟨⟨hC.1.1, hCR⟩, fun I hI _ hIC ↦ hC.2 hI (hIC.trans hC.1.2) hIC⟩ @@ -166,4 +187,136 @@ lemma restrict_circuit_iff (hR : R ⊆ M.E := by aesop_mat) : simp_rw [circuit_iff, restrict_dep_iff, and_imp, dep_iff] exact fun hC hCR h ↦ ⟨⟨⟨hC,hCR.trans hR⟩,fun I hI hIC ↦ h hI.1 (hIC.trans hCR) hIC⟩,hCR⟩ +/-! ### Fundamental Circuits -/ + +/-- For an independent set `I` and some `e ∈ M.closure I \ I`, +`M.fundCircuit e I` is the unique circuit contained in `insert e I`. +For the fact that this is a circuit, see `Matroid.Indep.fundCircuit_circuit`, +and the fact that it is unique, see `Matroid.Circuit.eq_fundCircuit_of_subset`. +Has the junk value `{e}` if `e ∈ I` and `insert e I` if `e ∉ M.closure I`. -/ +def fundCircuit (M : Matroid α) (e : α) (I : Set α) : Set α := + insert e (I ∩ (⋂₀ {J | J ⊆ I ∧ e ∈ M.closure J})) + +lemma fundCircuit_eq_sInter (he : e ∈ M.closure I) : + M.fundCircuit e I = insert e (⋂₀ {J | J ⊆ I ∧ e ∈ M.closure J}) := by + rw [fundCircuit, inter_eq_self_of_subset_right] + exact sInter_subset_of_mem ⟨Subset.rfl, he⟩ + +lemma fundCircuit_subset_insert (M : Matroid α) (e : α) (I : Set α) : + M.fundCircuit e I ⊆ insert e I := + insert_subset_insert inter_subset_left + +lemma fundCircuit_subset_ground (he : e ∈ M.E) (hI : I ⊆ M.E := by aesop_mat) : + M.fundCircuit e I ⊆ M.E := + (M.fundCircuit_subset_insert e I).trans (insert_subset he hI) + +lemma mem_fundCircuit (M : Matroid α) (e : α) (I : Set α) : e ∈ fundCircuit M e I := + mem_insert .. + +/-- The fundamental circuit of `e` and `X` has the junk value `{e}` if `e ∈ X` -/ +lemma fundCircuit_eq_of_mem (heX : e ∈ X) (heE : e ∈ M.E := by aesop_mat) : + M.fundCircuit e X = {e} := by + suffices h : ∀ a ∈ X, (∀ I ⊆ X, e ∈ M.closure I → a ∈ I) → a = e by + simpa [subset_antisymm_iff, fundCircuit] + exact fun f hfX h ↦ h {e} (by simpa) (mem_closure_of_mem' _ rfl) + +/-- A version of `Matroid.fundCircuit_eq_of_mem` that applies when `X ⊆ M.E` instead of `e ∈ X`.-/ +lemma fundCircuit_eq_of_mem' (heX : e ∈ X) (hX : X ⊆ M.E := by aesop_mat) : + M.fundCircuit e X = {e} := by + rwa [fundCircuit_eq_of_mem] + +lemma Indep.fundCircuit_circuit (hI : M.Indep I) (hecl : e ∈ M.closure I) (heI : e ∉ I) : + M.Circuit (M.fundCircuit e I) := by + apply (hI.inter_right _).insert_circuit_of_forall (by simp [heI]) + · rw [(hI.subset _).closure_inter_eq_inter_closure, mem_inter_iff, and_iff_right hecl, + hI.closure_sInter_eq_biInter_closure_of_forall_subset _ (by simp +contextual)] + · simp + · exact ⟨I, rfl.subset, hecl⟩ + exact union_subset rfl.subset (sInter_subset_of_mem ⟨rfl.subset, hecl⟩) + simp only [mem_inter_iff, mem_sInter, mem_setOf_eq, and_imp] + exact fun f hfI hf hecl ↦ (hf _ (diff_subset.trans inter_subset_left) hecl).2 rfl + +lemma Indep.mem_fundCircuit_iff (hI : M.Indep I) (hecl : e ∈ M.closure I) (heI : e ∉ I) : + x ∈ M.fundCircuit e I ↔ M.Indep (insert e I \ {x}) := by + obtain rfl | hne := eq_or_ne x e + · simp [hI.diff, mem_fundCircuit] + suffices (∀ t ⊆ I, e ∈ M.closure t → x ∈ t) ↔ e ∉ M.closure (I \ {x}) by + simpa [fundCircuit_eq_sInter hecl, hne, ← insert_diff_singleton_comm hne.symm, + (hI.diff _).insert_indep_iff, mem_ground_of_mem_closure hecl, heI] + refine ⟨fun h hecl ↦ (h _ diff_subset hecl).2 rfl, fun h J hJ heJ ↦ by_contra fun hxJ ↦ h ?_⟩ + exact M.closure_subset_closure (subset_diff_singleton hJ hxJ) heJ + +lemma Base.fundCircuit_circuit {B : Set α} (hB : M.Base B) (hxE : x ∈ M.E) (hxB : x ∉ B) : + M.Circuit (M.fundCircuit x B) := + hB.indep.fundCircuit_circuit (by rwa [hB.closure_eq]) hxB + +/-- For `I` independent, `M.fundCircuit e I` is the only circuit contained in `insert e I`. -/ +lemma Circuit.eq_fundCircuit_of_subset (hC : M.Circuit C) (hI : M.Indep I) (hCss : C ⊆ insert e I) : + C = M.fundCircuit e I := by + obtain hCI | ⟨heC, hCeI⟩ := subset_insert_iff.1 hCss + · exact (hC.not_indep (hI.subset hCI)).elim + suffices hss : M.fundCircuit e I ⊆ C by + refine hC.eq_of_superset_circuit (hI.fundCircuit_circuit ?_ fun heI ↦ ?_) hss + · rw [hI.mem_closure_iff] + exact .inl (hC.dep.superset hCss (insert_subset (hC.subset_ground heC) hI.subset_ground)) + exact hC.not_indep (hI.subset (hCss.trans (by simp [heI]))) + refine insert_subset heC (inter_subset_right.trans ?_) + refine (sInter_subset_of_mem (t := C \ {e}) ?_).trans diff_subset + simp [hCss, hC.mem_closure_diff_singleton_of_mem heC] + +/-! ### Dependence -/ + +lemma Dep.exists_circuit_subset (hX : M.Dep X) : ∃ C, C ⊆ X ∧ M.Circuit C := by + obtain ⟨I, hI⟩ := M.exists_basis X + obtain ⟨e, heX, heI⟩ := exists_of_ssubset + (hI.subset.ssubset_of_ne (by rintro rfl; exact hI.indep.not_dep hX)) + exact ⟨M.fundCircuit e I, (M.fundCircuit_subset_insert e I).trans (insert_subset heX hI.subset), + hI.indep.fundCircuit_circuit (hI.subset_closure heX) heI⟩ + +lemma dep_iff_superset_circuit (hX : X ⊆ M.E := by aesop_mat) : + M.Dep X ↔ ∃ C, C ⊆ X ∧ M.Circuit C := + ⟨Dep.exists_circuit_subset, fun ⟨C, hCX, hC⟩ ↦ hC.dep.superset hCX⟩ + +/-- A version of `Matroid.dep_iff_superset_circuit` that has the supportedness hypothesis +as part of the equivalence, rather than a hypothesis. -/ +lemma dep_iff_superset_circuit' : M.Dep X ↔ (∃ C, C ⊆ X ∧ M.Circuit C) ∧ X ⊆ M.E := + ⟨fun h ↦ ⟨h.exists_circuit_subset, h.subset_ground⟩, fun ⟨⟨C, hCX, hC⟩, h⟩ ↦ hC.dep.superset hCX⟩ + +/-- A version of `Matroid.indep_iff_forall_subset_not_circuit` that has the supportedness hypothesis +as part of the equivalence, rather than a hypothesis. -/ +lemma indep_iff_forall_subset_not_circuit' : + M.Indep I ↔ (∀ C, C ⊆ I → ¬M.Circuit C) ∧ I ⊆ M.E := by + simp_rw [indep_iff_not_dep, dep_iff_superset_circuit'] + aesop + +lemma indep_iff_forall_subset_not_circuit (hI : I ⊆ M.E := by aesop_mat) : + M.Indep I ↔ ∀ C, C ⊆ I → ¬M.Circuit C := by + rw [indep_iff_forall_subset_not_circuit', and_iff_left hI] + +/-! ### Extensionality -/ + +lemma ext_circuit {M₁ M₂ : Matroid α} (hE : M₁.E = M₂.E) + (h : ∀ ⦃C⦄, C ⊆ M₁.E → (M₁.Circuit C ↔ M₂.Circuit C)) : M₁ = M₂ := by + have h' {C} : M₁.Circuit C ↔ M₂.Circuit C := + (em (C ⊆ M₁.E)).elim (h (C := C)) (fun hC ↦ iff_of_false (mt Circuit.subset_ground hC) + (mt Circuit.subset_ground fun hss ↦ hC (hss.trans_eq hE.symm))) + refine ext_indep hE fun I hI ↦ ?_ + simp_rw [indep_iff_forall_subset_not_circuit hI, h', + indep_iff_forall_subset_not_circuit (hI.trans_eq hE)] + +/-- A stronger version of `Matroid.ext_circuit`: +two matroids on the same ground set are equal if no circuit of one is independent in the other. -/ +lemma ext_circuit_not_indep {M₁ M₂ : Matroid α} (hE : M₁.E = M₂.E) + (h₁ : ∀ C, M₁.Circuit C → ¬ M₂.Indep C) (h₂ : ∀ C, M₂.Circuit C → ¬ M₁.Indep C) : + M₁ = M₂ := by + refine ext_circuit hE fun C hCE ↦ ⟨fun hC ↦ ?_, fun hC ↦ ?_⟩ + · obtain ⟨C', hC'C, hC'⟩ := ((not_indep_iff (by rwa [← hE])).1 (h₁ C hC)).exists_circuit_subset + rwa [← hC.eq_of_not_indep_subset (h₂ C' hC') hC'C] + obtain ⟨C', hC'C, hC'⟩ := ((not_indep_iff hCE).1 (h₂ C hC)).exists_circuit_subset + rwa [← hC.eq_of_not_indep_subset (h₁ C' hC') hC'C] + +lemma ext_iff_circuit {M₁ M₂ : Matroid α} : + M₁ = M₂ ↔ M₁.E = M₂.E ∧ ∀ C, M₁.Circuit C ↔ M₂.Circuit C := + ⟨fun h ↦ by simp [h], fun h ↦ ext_circuit h.1 fun C hC ↦ h.2 (C := C)⟩ + end Matroid From d86d6c30e6e0018fd8844af59f2cc21b1b4b2af2 Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Tue, 28 Jan 2025 06:01:13 +0000 Subject: [PATCH 591/681] chore: import Std in Mathlib.lean (#21126) This will allow Loogle to find pieces of the standard library which mathlib currently does not use, like the date and time API. Co-authored-by: Markus Himmel --- Mathlib.lean | 1 + scripts/lint-style.lean | 13 ++++++++++--- scripts/mk_all.lean | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Mathlib.lean b/Mathlib.lean index 770fd7dd35750..7957aa53874e1 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1,3 +1,4 @@ +import Std import Batteries import Mathlib.Algebra.AddConstMap.Basic import Mathlib.Algebra.AddConstMap.Equiv diff --git a/scripts/lint-style.lean b/scripts/lint-style.lean index b4b7d93b9f283..7f1b2cdd34467 100644 --- a/scripts/lint-style.lean +++ b/scripts/lint-style.lean @@ -29,6 +29,12 @@ def findImports (path : System.FilePath) : IO (Array Lean.Name) := do return (← Lean.parseImports' (← IO.FS.readFile path) path.toString) |>.map (fun imp ↦ imp.module) |>.erase `Init +/-- Additional imports generated by `mk_all`. -/ +def explicitImports : Array Lean.Name := #[`Batteries, `Std] + +/-- Remove the additional imports generated by `mk_all` so that only mathlib modules remain. -/ +def eraseExplicitImports (names : Array Lean.Name) : Array Lean.Name := + explicitImports.foldl Array.erase names /-- Check that `Mathlib.Init` is transitively imported in all of Mathlib. @@ -39,7 +45,7 @@ Return `true` iff there was an error. def checkInitImports : IO Bool := do -- Find any file in the Mathlib directory which does not contain any Mathlib import. -- We simply parse `Mathlib.lean`, as CI ensures this file is up to date. - let allModuleNames := (← findImports "Mathlib.lean").erase `Batteries + let allModuleNames := eraseExplicitImports (← findImports "Mathlib.lean") let mut modulesWithoutMathlibImports := #[] let mut importsHeaderLinter := #[] for module in allModuleNames do @@ -107,8 +113,9 @@ def lintStyleCli (args : Cli.Parsed) : IO UInt32 := do let mut allModuleNames := #[] for s in ["Archive.lean", "Counterexamples.lean", "Mathlib.lean"] do allModuleNames := allModuleNames.append (← findImports s) - -- Note: since "Batteries" is added explicitly to "Mathlib.lean", we remove it here manually. - allModuleNames := allModuleNames.erase `Batteries + -- Note: since "Batteries" and "Std" are added explicitly to "Mathlib.lean", we remove them here + -- manually. + allModuleNames := eraseExplicitImports allModuleNames -- Read the `nolints` file, with manual exceptions for the linter. -- NB. We pass these lints to `lintModules` explicitly to prevent cache invalidation bugs: diff --git a/scripts/mk_all.lean b/scripts/mk_all.lean index 00bacbc8eaefb..ae79948610542 100644 --- a/scripts/mk_all.lean +++ b/scripts/mk_all.lean @@ -55,9 +55,9 @@ def mkAllCLI (args : Parsed) : IO UInt32 := do for d in libs.reverse do -- reverse to create `Mathlib/Tactic.lean` before `Mathlib.lean` let fileName := addExtension d "lean" let mut allFiles ← getAllModulesSorted git d - -- mathlib exception: manually import Batteries in `Mathlib.lean` + -- mathlib exception: manually import Std and Batteries in `Mathlib.lean` if d == "Mathlib" then - allFiles := #["Batteries"] ++ allFiles + allFiles := #["Std", "Batteries"] ++ allFiles let fileContent := ("\n".intercalate (allFiles.map ("import " ++ ·)).toList).push '\n' if !(← pathExists fileName) then if check then From 8be3c37339db9dcce0e1d03f19e975e8fd7d795d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Tue, 28 Jan 2025 07:05:13 +0000 Subject: [PATCH 592/681] feat(Algebra/Polynomial): `Polynomial.aeval` for product algebras (#21062) Results about evaluating polynomials on elements from (generalized) product algebras. Add necessary (and basic) facts for `Pi` algebras. --- Mathlib/Algebra/Algebra/Pi.lean | 10 +++++++ Mathlib/Algebra/Polynomial/AlgebraMap.lean | 33 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/Mathlib/Algebra/Algebra/Pi.lean b/Mathlib/Algebra/Algebra/Pi.lean index f6a57e3d71a44..d04b77f4ffb48 100644 --- a/Mathlib/Algebra/Algebra/Pi.lean +++ b/Mathlib/Algebra/Algebra/Pi.lean @@ -79,6 +79,16 @@ def evalAlgHom {_ : CommSemiring R} [∀ i, Semiring (f i)] [∀ i, Algebra R (f toFun := fun f => f i commutes' := fun _ => rfl } +@[simp] +theorem algHom_evalAlgHom [CommSemiring R] [s : ∀ i, Semiring (f i)] [∀ i, Algebra R (f i)] : + algHom R f (evalAlgHom R f) = AlgHom.id R (Π i, f i) := rfl + +/-- `Pi.algHom` commutes with composition. -/ +theorem algHom_comp [CommSemiring R] [∀ i, Semiring (f i)] [∀ i, Algebra R (f i)] + {A B : Type*} [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] + (g : ∀ i, B →ₐ[R] f i) (h : A →ₐ[R] B) : + (algHom R f g).comp h = algHom R f (fun i ↦ (g i).comp h) := rfl + variable (A B : Type*) [CommSemiring R] [Semiring B] [Algebra R B] /-- `Function.const` as an `AlgHom`. The name matches `Pi.constRingHom`, `Pi.constMonoidHom`, diff --git a/Mathlib/Algebra/Polynomial/AlgebraMap.lean b/Mathlib/Algebra/Polynomial/AlgebraMap.lean index 40e975a43fbfe..2129497e1006c 100644 --- a/Mathlib/Algebra/Polynomial/AlgebraMap.lean +++ b/Mathlib/Algebra/Polynomial/AlgebraMap.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.Algebra.Pi +import Mathlib.Algebra.Algebra.Prod import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.Algebra.Tower import Mathlib.Algebra.MonoidAlgebra.Basic @@ -368,6 +369,38 @@ theorem aeval_algebraMap_apply_eq_algebraMap_eval (x : R) (p : R[X]) : aeval (algebraMap R A x) p = algebraMap R A (p.eval x) := aeval_algHom_apply (Algebra.ofId R A) x p +/-- Polynomial evaluation on a pair is a product of the evaluations on the components. -/ +theorem aeval_prod (x : A × B) : aeval (R := R) x = (aeval x.1).prod (aeval x.2) := + aeval_algHom (.fst R A B) x ▸ aeval_algHom (.snd R A B) x ▸ + (aeval x).prod_comp (.fst R A B) (.snd R A B) + +/-- Polynomial evaluation on a pair is a pair of evaluations. -/ +theorem aeval_prod_apply (x : A × B) (p : Polynomial R) : + p.aeval x = (p.aeval x.1, p.aeval x.2) := by simp [aeval_prod] + +section Pi + +variable {I : Type*} {A : I → Type*} [∀ i, Semiring (A i)] [∀ i, Algebra R (A i)] +variable (x : Π i, A i) (p : R[X]) + +/-- Polynomial evaluation on an indexed tuple is the indexed product of the evaluations +on the components. +Generalizes `Polynomial.aeval_prod` to indexed products. -/ +theorem aeval_pi (x : Π i, A i) : aeval (R := R) x = Pi.algHom R A (fun i ↦ aeval (x i)) := + (funext fun i ↦ aeval_algHom (Pi.evalAlgHom R A i) x) ▸ + (Pi.algHom_comp R A (Pi.evalAlgHom R A) (aeval x)) + +theorem aeval_pi_apply₂ (j : I) : p.aeval x j = p.aeval (x j) := + aeval_pi (R := R) x ▸ Pi.algHom_apply R A (fun i ↦ aeval (x i)) p j + +/-- Polynomial evaluation on an indexed tuple is the indexed tuple of the evaluations +on the components. +Generalizes `Polynomial.aeval_prod_apply` to indexed products. -/ +theorem aeval_pi_apply : p.aeval x = fun j ↦ p.aeval (x j) := + funext fun j ↦ aeval_pi_apply₂ x p j + +end Pi + @[simp] theorem coe_aeval_eq_eval (r : R) : (aeval r : R[X] → R) = eval r := rfl From eff2ae8d16dc6d0c3892edca07aa6b6652ac24a8 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 28 Jan 2025 07:32:00 +0000 Subject: [PATCH 593/681] feat(Asymptotics): prove `IsLittleOTVS.add` (#20578) Co-authored-by: Eric Wieser --- Mathlib/Analysis/Asymptotics/TVS.lean | 11 +++++++++++ Mathlib/Analysis/Convex/EGauge.lean | 19 ++++++++++++++++++- Mathlib/Order/Filter/SmallSets.lean | 15 +++++++++++++++ Mathlib/Topology/Algebra/Monoid.lean | 6 ++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Mathlib/Analysis/Asymptotics/TVS.lean b/Mathlib/Analysis/Asymptotics/TVS.lean index 5d0db2d9253a3..59720fc3eebdd 100644 --- a/Mathlib/Analysis/Asymptotics/TVS.lean +++ b/Mathlib/Analysis/Asymptotics/TVS.lean @@ -193,6 +193,17 @@ lemma IsLittleOTVS.insert [TopologicalSpace α] {x : α} {s : Set α} lemma IsLittleOTVS.bot : f =o[𝕜;⊥] g := fun u hU => ⟨univ, by simp⟩ +theorem IsLittleOTVS.add [TopologicalAddGroup E] [ContinuousSMul 𝕜 E] + {f₁ f₂ : α → E} {g : α → F} {l : Filter α} + (h₁ : f₁ =o[𝕜; l] g) (h₂ : f₂ =o[𝕜; l] g) : (f₁ + f₂) =o[𝕜; l] g := by + rw [(nhds_basis_balanced 𝕜 E).add_self.isLittleOTVS_iff (basis_sets _)] + rintro U ⟨hU, hUb⟩ + rcases ((h₁.eventually_smallSets U hU).and (h₂.eventually_smallSets U hU)).exists_mem_of_smallSets + with ⟨V, hV, hVf₁, hVf₂⟩ + refine ⟨V, hV, fun ε hε ↦ ?_⟩ + filter_upwards [hVf₁ ε hε, hVf₂ ε hε] with x hx₁ hx₂ + exact (egauge_add_add_le hUb hUb _ _).trans (max_le hx₁ hx₂) + protected lemma IsLittleOTVS.smul_left (h : f =o[𝕜;l] g) (c : α → 𝕜) : (fun x ↦ c x • f x) =o[𝕜;l] (fun x ↦ c x • g x) := by unfold IsLittleOTVS at * diff --git a/Mathlib/Analysis/Convex/EGauge.lean b/Mathlib/Analysis/Convex/EGauge.lean index 5083bf5351560..3680e97a36527 100644 --- a/Mathlib/Analysis/Convex/EGauge.lean +++ b/Mathlib/Analysis/Convex/EGauge.lean @@ -67,7 +67,7 @@ lemma egauge_union (s t : Set E) (x : E) : egauge 𝕜 (s ∪ t) x = egauge 𝕜 lemma le_egauge_inter (s t : Set E) (x : E) : egauge 𝕜 s x ⊔ egauge 𝕜 t x ≤ egauge 𝕜 (s ∩ t) x := - max_le_iff.2 ⟨egauge_anti _ inter_subset_left _, egauge_anti _ inter_subset_right _⟩ + max_le (egauge_anti _ inter_subset_left _) (egauge_anti _ inter_subset_right _) end SMul @@ -168,6 +168,23 @@ lemma egauge_smul_right (h : c = 0 → s.Nonempty) (x : E) : end Module +section VectorSpace + +variable {𝕜 : Type*} [NormedField 𝕜] {E : Type*} [AddCommGroup E] [Module 𝕜 E] + +theorem egauge_add_add_le {U V : Set E} (hU : Balanced 𝕜 U) (hV : Balanced 𝕜 V) (a b : E) : + egauge 𝕜 (U + V) (a + b) ≤ max (egauge 𝕜 U a) (egauge 𝕜 V b) := by + refine le_of_forall_lt' fun c hc ↦ ?_ + simp only [max_lt_iff, egauge_lt_iff] at hc ⊢ + rcases hc with ⟨⟨x, hx, hxc⟩, ⟨y, hy, hyc⟩⟩ + wlog hxy : ‖x‖ ≤ ‖y‖ generalizing a b x y U V + · simpa only [add_comm] using this hV hU b a y hy hyc x hx hxc (le_of_not_le hxy) + refine ⟨y, ?_, hyc⟩ + rw [smul_add] + exact add_mem_add (hU.smul_mono hxy hx) hy + +end VectorSpace + section SeminormedAddCommGroup variable (𝕜 : Type*) [NormedField 𝕜] {E : Type*} [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] diff --git a/Mathlib/Order/Filter/SmallSets.lean b/Mathlib/Order/Filter/SmallSets.lean index 1e40a2da092eb..28c02d2e8dc15 100644 --- a/Mathlib/Order/Filter/SmallSets.lean +++ b/Mathlib/Order/Filter/SmallSets.lean @@ -54,6 +54,21 @@ theorem hasBasis_smallSets (l : Filter α) : HasBasis l.smallSets (fun t : Set α => t ∈ l) powerset := l.basis_sets.smallSets +theorem Eventually.exists_mem_basis_of_smallSets {p : ι → Prop} {s : ι → Set α} {P : Set α → Prop} + (h₁ : ∀ᶠ t in l.smallSets, P t) (h₂ : HasBasis l p s) : ∃ i, p i ∧ P (s i) := + (h₂.smallSets.eventually_iff.mp h₁).imp fun _i ⟨hpi, hi⟩ ↦ ⟨hpi, hi Subset.rfl⟩ + +theorem Frequently.smallSets_of_forall_mem_basis {p : ι → Prop} {s : ι → Set α} {P : Set α → Prop} + (h₁ : ∀ i, p i → P (s i)) (h₂ : HasBasis l p s) : ∃ᶠ t in l.smallSets, P t := + h₂.smallSets.frequently_iff.mpr fun _ hi => ⟨_, Subset.rfl, h₁ _ hi⟩ + +theorem Eventually.exists_mem_of_smallSets {p : Set α → Prop} + (h : ∀ᶠ t in l.smallSets, p t) : ∃ s ∈ l, p s := + h.exists_mem_basis_of_smallSets l.basis_sets + +/-! No `Frequently.smallSets_of_forall_mem (h : ∀ s ∈ l, p s) : ∃ᶠ t in l.smallSets, p t` as +`Filter.frequently_smallSets_mem : ∃ᶠ t in l.smallSets, t ∈ l` is preferred. -/ + /-- `g` converges to `f.smallSets` if for all `s ∈ f`, eventually we have `g x ⊆ s`. -/ theorem tendsto_smallSets_iff {f : α → Set β} : Tendsto f la lb.smallSets ↔ ∀ t ∈ lb, ∀ᶠ x in la, f x ⊆ t := diff --git a/Mathlib/Topology/Algebra/Monoid.lean b/Mathlib/Topology/Algebra/Monoid.lean index 2cfc9ff7764f6..025c3e373cc41 100644 --- a/Mathlib/Topology/Algebra/Monoid.lean +++ b/Mathlib/Topology/Algebra/Monoid.lean @@ -568,6 +568,12 @@ theorem exists_open_nhds_one_mul_subset {U : Set M} (hU : U ∈ 𝓝 (1 : M)) : ∃ V : Set M, IsOpen V ∧ (1 : M) ∈ V ∧ V * V ⊆ U := by simpa only [mul_subset_iff] using exists_open_nhds_one_split hU +@[to_additive] +theorem Filter.HasBasis.mul_self {p : ι → Prop} {s : ι → Set M} (h : (𝓝 1).HasBasis p s) : + (𝓝 1).HasBasis p fun i => s i * s i := by + rw [← nhds_mul_nhds_one, ← map₂_mul, ← map_uncurry_prod] + simpa only [← image_mul_prod] using h.prod_self.map _ + end MulOneClass section ContinuousMul From abcae08fdcad503ad41f1f30c52c5440b147955e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 28 Jan 2025 08:00:52 +0000 Subject: [PATCH 594/681] doc: turn more links to Stacks into `@[stacks]` tags (#21135) This was made quite manually. Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> --- Mathlib/AlgebraicGeometry/Noetherian.lean | 25 +++++++--------- Mathlib/CategoryTheory/Galois/Topology.lean | 2 +- Mathlib/CategoryTheory/Limits/Final.lean | 14 +++------ .../Limits/Shapes/Countable.lean | 4 +-- Mathlib/CategoryTheory/Sites/Canonical.lean | 16 ++++------ .../CategoryTheory/Sites/CoverLifting.lean | 8 ++--- .../CategoryTheory/Sites/CoverPreserving.lean | 7 ++--- .../Sites/EqualizerSheafCondition.lean | 23 ++++++++++----- Mathlib/CategoryTheory/Sites/IsSheafFor.lean | 7 +++-- Mathlib/CategoryTheory/Sites/Pretopology.lean | 10 +++---- Mathlib/CategoryTheory/Sites/Sheaf.lean | 29 +++++++++---------- Mathlib/RingTheory/Adjoin/Tower.lean | 3 +- Mathlib/RingTheory/Etale/Basic.lean | 8 ++--- Mathlib/RingTheory/FinitePresentation.lean | 2 +- Mathlib/RingTheory/Finiteness/Nakayama.lean | 4 +-- Mathlib/RingTheory/Ideal/Operations.lean | 3 +- .../RingTheory/LocalRing/RingHom/Basic.lean | 4 +-- Mathlib/RingTheory/Smooth/Basic.lean | 9 ++---- .../Spectrum/Prime/IsOpenComapC.lean | 7 ++--- .../RingTheory/Spectrum/Prime/Topology.lean | 8 ++--- Mathlib/RingTheory/Unramified/Basic.lean | 9 ++---- Mathlib/Topology/NoetherianSpace.lean | 6 ++-- Mathlib/Topology/Separation/Regular.lean | 5 ++-- 23 files changed, 93 insertions(+), 120 deletions(-) diff --git a/Mathlib/AlgebraicGeometry/Noetherian.lean b/Mathlib/AlgebraicGeometry/Noetherian.lean index 7d1c4fff13747..73a384e72fb39 100644 --- a/Mathlib/AlgebraicGeometry/Noetherian.lean +++ b/Mathlib/AlgebraicGeometry/Noetherian.lean @@ -191,9 +191,8 @@ lemma noetherianSpace_of_isAffineOpen (U : X.Opens) (hU : IsAffineOpen U) (Scheme.restrictFunctorΓ.app (op U)).symm.commRingCatIsoToRingEquiv exact @noetherianSpace_of_isAffine _ hU _ -/-- Any open immersion `Z ⟶ X` with `X` locally Noetherian is quasi-compact. - -[Stacks: Lemma 01OX](https://stacks.math.columbia.edu/tag/01OX) -/ +/-- Any open immersion `Z ⟶ X` with `X` locally Noetherian is quasi-compact. -/ +@[stacks 01OX] instance (priority := 100) {Z : Scheme} [IsLocallyNoetherian X] {f : Z ⟶ X} [IsOpenImmersion f] : QuasiCompact f := by apply (quasiCompact_iff_forall_affine f).mpr @@ -206,9 +205,8 @@ instance (priority := 100) {Z : Scheme} [IsLocallyNoetherian X] · exact Set.inter_subset_left · exact Set.inter_subset_right -/-- A locally Noetherian scheme is quasi-separated. - -[Stacks: Lemma 01OY](https://stacks.math.columbia.edu/tag/01OY) -/ +/-- A locally Noetherian scheme is quasi-separated. -/ +@[stacks 01OY] instance (priority := 100) IsLocallyNoetherian.quasiSeparatedSpace [IsLocallyNoetherian X] : QuasiSeparatedSpace X := by apply (quasiSeparatedSpace_iff_affine X).mpr @@ -266,9 +264,8 @@ theorem isNoetherian_iff_of_finite_affine_openCover {𝒰 : Scheme.OpenCover.{v, · exact Scheme.OpenCover.compactSpace 𝒰 open CategoryTheory in -/-- A Noetherian scheme has a Noetherian underlying topological space. - -[Stacks, Lemma 01OZ](https://stacks.math.columbia.edu/tag/01OZ) -/ +/-- A Noetherian scheme has a Noetherian underlying topological space. -/ +@[stacks 01OZ] instance (priority := 100) IsNoetherian.noetherianSpace [IsNoetherian X] : NoetherianSpace X := by apply TopologicalSpace.noetherian_univ_iff.mp @@ -284,9 +281,8 @@ instance (priority := 100) IsNoetherian.noetherianSpace [IsNoetherian X] : convert noetherianSpace_of_isAffineOpen U.1 U.2 apply IsLocallyNoetherian.component_noetherian -/-- Any morphism of schemes `f : X ⟶ Y` with `X` Noetherian is quasi-compact. - -[Stacks, Lemma 01P0](https://stacks.math.columbia.edu/tag/01P0) -/ +/-- Any morphism of schemes `f : X ⟶ Y` with `X` Noetherian is quasi-compact. -/ +@[stacks 01P0] instance (priority := 100) quasiCompact_of_noetherianSpace_source {X Y : Scheme} [NoetherianSpace X] (f : X ⟶ Y) : QuasiCompact f := ⟨fun _ _ _ => NoetherianSpace.isCompact _⟩ @@ -325,9 +321,8 @@ theorem isNoetherian_Spec {R : CommRingCat} : ⟨fun _ => inferInstance, fun _ => inferInstance⟩ -/-- A Noetherian scheme has a finite number of irreducible components. - -[Stacks, Lemma 0BA8](https://stacks.math.columbia.edu/tag/0BA8) -/ +/-- A Noetherian scheme has a finite number of irreducible components. -/ +@[stacks 0BA8] theorem finite_irreducibleComponents_of_isNoetherian [IsNoetherian X] : (irreducibleComponents X).Finite := NoetherianSpace.finite_irreducibleComponents diff --git a/Mathlib/CategoryTheory/Galois/Topology.lean b/Mathlib/CategoryTheory/Galois/Topology.lean index 17d6329fb58cd..7020a117b13ee 100644 --- a/Mathlib/CategoryTheory/Galois/Topology.lean +++ b/Mathlib/CategoryTheory/Galois/Topology.lean @@ -17,7 +17,7 @@ embedding of `Aut F` into `∀ X, Aut (F.obj X)` where ## References -- Stacks Project: Tag 0BMQ +- [Stacks 0BMQ](https://stacks.math.columbia.edu/tag/0BMQ) -/ diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index 93331eeffeb40..3431f905c7954 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -335,11 +335,8 @@ section variable (G) /-- When `F : C ⥤ D` is final, and `G : D ⥤ E` has a colimit, then `F ⋙ G` has a colimit also and -`colimit (F ⋙ G) ≅ colimit G` - -https://stacks.math.columbia.edu/tag/04E7 --/ -@[simps! (config := .lemmasOnly)] +`colimit (F ⋙ G) ≅ colimit G`. -/ +@[simps! (config := .lemmasOnly), stacks 04E7] def colimitIso [HasColimit G] : colimit (F ⋙ G) ≅ colimit G := asIso (colimit.pre G F) @@ -684,11 +681,8 @@ section variable (G) /-- When `F : C ⥤ D` is initial, and `G : D ⥤ E` has a limit, then `F ⋙ G` has a limit also and -`limit (F ⋙ G) ≅ limit G` - -https://stacks.math.columbia.edu/tag/04E7 --/ -@[simps! (config := .lemmasOnly)] +`limit (F ⋙ G) ≅ limit G`. -/ +@[simps! (config := .lemmasOnly), stacks 04E7] def limitIso [HasLimit G] : limit (F ⋙ G) ≅ limit G := (asIso (limit.pre G F)).symm diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean index 6f0db0a360ddb..9064ae11e1cb9 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean @@ -219,9 +219,7 @@ instance sequentialFunctor_initial : (sequentialFunctor J).Initial where · right exact ⟨CostructuredArrow.homMk (homOfLE h).op rfl⟩ -/-- -This is proved in https://stacks.math.columbia.edu/tag/0032 --/ +@[stacks 0032] proof_wanted preorder_of_cofiltered (J : Type*) [Category J] [IsCofiltered J] : ∃ (I : Type*) (_ : Preorder I) (_ : IsCofiltered I) (F : I ⥤ J), F.Initial diff --git a/Mathlib/CategoryTheory/Sites/Canonical.lean b/Mathlib/CategoryTheory/Sites/Canonical.lean index 8dd61b381382a..be99c646d4406 100644 --- a/Mathlib/CategoryTheory/Sites/Canonical.lean +++ b/Mathlib/CategoryTheory/Sites/Canonical.lean @@ -139,11 +139,9 @@ theorem isSheafFor_trans (P : Cᵒᵖ ⥤ Type v) (R S : Sieve X) rw [this] apply hR' hf -/-- Construct the finest (largest) Grothendieck topology for which the given presheaf is a sheaf. - -This is a special case of https://stacks.math.columbia.edu/tag/00Z9, but following a different -proof (see the comments there). --/ +/-- Construct the finest (largest) Grothendieck topology for which the given presheaf is a sheaf. -/ +@[stacks 00Z9 "This is a special case of the Stacks entry, but following a different +proof (see the Stacks comments)."] def finestTopologySingle (P : Cᵒᵖ ⥤ Type v) : GrothendieckTopology C where sieves X S := ∀ (Y) (f : Y ⟶ X), Presieve.IsSheafFor P (S.pullback f : Presieve Y) top_mem' X Y f := by @@ -164,11 +162,9 @@ def finestTopologySingle (P : Cᵒᵖ ⥤ Type v) : GrothendieckTopology C where rw [pullback_id, pullback_comp] at this apply this -/-- -Construct the finest (largest) Grothendieck topology for which all the given presheaves are sheaves. - -This is equal to the construction of . --/ +/-- Construct the finest (largest) Grothendieck topology for which all the given presheaves are +sheaves. -/ +@[stacks 00Z9 "Equal to that Stacks construction"] def finestTopology (Ps : Set (Cᵒᵖ ⥤ Type v)) : GrothendieckTopology C := sInf (finestTopologySingle '' Ps) diff --git a/Mathlib/CategoryTheory/Sites/CoverLifting.lean b/Mathlib/CategoryTheory/Sites/CoverLifting.lean index b6098d47f159a..db34551ea0323 100644 --- a/Mathlib/CategoryTheory/Sites/CoverLifting.lean +++ b/Mathlib/CategoryTheory/Sites/CoverLifting.lean @@ -211,11 +211,9 @@ variable [∀ (F : Cᵒᵖ ⥤ A), G.op.HasPointwiseRightKanExtension F] /-- If `G` is cocontinuous, then `G.op.ran` pushes sheaves to sheaves. -This is SGA 4 III 2.2. An alternative reference is -https://stacks.math.columbia.edu/tag/00XK (where results -are obtained under the additional assumption that -`C` and `D` have pullbacks). --/ +This is SGA 4 III 2.2. -/ +@[stacks 00XK "Alternative reference. There, results are obtained under the additional assumption +that `C` and `D` have pullbacks."] theorem ran_isSheaf_of_isCocontinuous (ℱ : Sheaf J A) : Presheaf.IsSheaf K (G.op.ran.obj ℱ.val) := by rw [Presheaf.isSheaf_iff_multifork] diff --git a/Mathlib/CategoryTheory/Sites/CoverPreserving.lean b/Mathlib/CategoryTheory/Sites/CoverPreserving.lean index fce2b79404c90..f7d3acf8d8072 100644 --- a/Mathlib/CategoryTheory/Sites/CoverPreserving.lean +++ b/Mathlib/CategoryTheory/Sites/CoverPreserving.lean @@ -154,11 +154,8 @@ theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [F.Full] [F.Faithful variable {F J K} -/-- If `F` is cover-preserving and compatible-preserving, -then `F` is a continuous functor. - -This result is basically . --/ +/-- If `F` is cover-preserving and compatible-preserving, then `F` is a continuous functor. -/ +@[stacks 00WW "This is basically this Stacks entry."] lemma Functor.isContinuous_of_coverPreserving (hF₁ : CompatiblePreserving.{w} K F) (hF₂ : CoverPreserving J K F) : Functor.IsContinuous.{w} F J K where op_comp_isSheaf_of_types G X S hS x hx := by diff --git a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean index 406251e3f3f1b..c52235dba062f 100644 --- a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean +++ b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean @@ -45,8 +45,9 @@ noncomputable section /-- The middle object of the fork diagram given in Equation (3) of [MM92], as well as the fork diagram -of . +of the Stacks entry. -/ +@[stacks 00VM "This is the middle object of the fork diagram there."] def FirstObj : Type max v u := ∏ᶜ fun f : ΣY, { f : Y ⟶ X // R f } => P.obj (op f.1) @@ -78,8 +79,9 @@ instance : Inhabited (FirstObj P ((⊥ : Sieve X) : Presieve X)) := /-- The left morphism of the fork diagram given in Equation (3) of [MM92], as well as the fork diagram -of . +of the Stacks entry. -/ +@[stacks 00VM "This is the left morphism of the fork diagram there."] def forkMap : P.obj (op X) ⟶ FirstObj P R := Pi.lift fun f => P.map f.2.1.op @@ -176,15 +178,17 @@ namespace Presieve variable [R.hasPullbacks] /-- -The rightmost object of the fork diagram of https://stacks.math.columbia.edu/tag/00VM, which +The rightmost object of the fork diagram of the Stacks entry, which contains the data used to check a family of elements for a presieve is compatible. -/ -@[simp] def SecondObj : Type max v u := +@[simp, stacks 00VM "This is the rightmost object of the fork diagram there."] +def SecondObj : Type max v u := ∏ᶜ fun fg : (ΣY, { f : Y ⟶ X // R f }) × ΣZ, { g : Z ⟶ X // R g } => haveI := Presieve.hasPullbacks.has_pullbacks fg.1.2.2 fg.2.2.2 P.obj (op (pullback fg.1.2.1 fg.2.2.1)) -/-- The map `pr₀*` of . -/ +/-- The map `pr₀*` of the Stacks entry. -/ +@[stacks 00VM "This is the map `pr₀*` there."] def firstMap : FirstObj P R ⟶ SecondObj P R := Pi.lift fun fg => haveI := Presieve.hasPullbacks.has_pullbacks fg.1.2.2 fg.2.2.2 @@ -193,7 +197,8 @@ def firstMap : FirstObj P R ⟶ SecondObj P R := instance [HasPullbacks C] : Inhabited (SecondObj P (⊥ : Presieve X)) := ⟨firstMap _ _ default⟩ -/-- The map `pr₁*` of . -/ +/-- The map `pr₁*` of the Stacks entry. -/ +@[stacks 00VM "This is the map `pr₁*` there."] def secondMap : FirstObj P R ⟶ SecondObj P R := Pi.lift fun fg => haveI := Presieve.hasPullbacks.has_pullbacks fg.1.2.2 fg.2.2.2 @@ -254,10 +259,11 @@ variable {B : C} {I : Type} (X : I → C) (π : (i : I) → X i ⟶ B) -- TODO: allow `I : Type w` /-- -The middle object of the fork diagram of . +The middle object of the fork diagram of the Stacks entry. The difference between this and `Equalizer.FirstObj P (ofArrows X π)` arises if the family of arrows `π` contains duplicates. The `Presieve.ofArrows` doesn't see those. -/ +@[stacks 00VM "The middle object of the fork diagram there."] def FirstObj : Type w := ∏ᶜ (fun i ↦ P.obj (op (X i))) @[ext] @@ -268,10 +274,11 @@ lemma FirstObj.ext (z₁ z₂ : FirstObj P X) (h : ∀ i, (Pi.π _ i : FirstObj exact h i /-- -The rightmost object of the fork diagram of https://stacks.math.columbia.edu/tag/00VM. +The rightmost object of the fork diagram of the Stacks entry. The difference between this and `Equalizer.Presieve.SecondObj P (ofArrows X π)` arises if the family of arrows `π` contains duplicates. The `Presieve.ofArrows` doesn't see those. -/ +@[stacks 00VM "The rightmost object of the fork diagram there."] def SecondObj : Type w := ∏ᶜ (fun (ij : I × I) ↦ P.obj (op (pullback (π ij.1) (π ij.2)))) diff --git a/Mathlib/CategoryTheory/Sites/IsSheafFor.lean b/Mathlib/CategoryTheory/Sites/IsSheafFor.lean index 0d7effb4b905f..e229cdcd97a5f 100644 --- a/Mathlib/CategoryTheory/Sites/IsSheafFor.lean +++ b/Mathlib/CategoryTheory/Sites/IsSheafFor.lean @@ -83,9 +83,10 @@ A presheaf is a sheaf (resp, separated) if every *compatible* family of elements (resp, at most one) amalgamation. This data is referred to as a `family` in [MM92], Chapter III, Section 4. It is also a concrete -version of the elements of the middle object in https://stacks.math.columbia.edu/tag/00VM which is +version of the elements of the middle object in the Stacks entry which is more useful for direct calculations. It is also used implicitly in Definition C2.1.2 in [Elephant]. -/ +@[stacks 00VM "This is a concrete version of the elements of the middle object there."] def FamilyOfElements (P : Cᵒᵖ ⥤ Type w) (R : Presieve X) := ∀ ⦃Y : C⦄ (f : Y ⟶ X), R f → P.obj (op Y) @@ -416,8 +417,8 @@ This version is also useful to establish that being a sheaf is preserved under i presheaves. See the discussion before Equation (3) of [MM92], Chapter III, Section 4. See also C2.1.4 of -[Elephant]. This is also a direct reformulation of . --/ +[Elephant]. -/ +@[stacks 00Z8 "Direct reformulation"] def YonedaSheafCondition (P : Cᵒᵖ ⥤ Type v₁) (S : Sieve X) : Prop := ∀ f : S.functor ⟶ P, ∃! g, S.functorInclusion ≫ g = f diff --git a/Mathlib/CategoryTheory/Sites/Pretopology.lean b/Mathlib/CategoryTheory/Sites/Pretopology.lean index 6285e9b9a6bde..1732a166ae6f3 100644 --- a/Mathlib/CategoryTheory/Sites/Pretopology.lean +++ b/Mathlib/CategoryTheory/Sites/Pretopology.lean @@ -52,12 +52,10 @@ three axioms: In some sense, a pretopology can be seen as Grothendieck topology with weaker saturation conditions, in that each covering is not necessarily downward closed. -See: https://ncatlab.org/nlab/show/Grothendieck+pretopology, or -https://stacks.math.columbia.edu/tag/00VH, or [MM92] Chapter III, Section 2, Definition 2. -Note that Stacks calls a category together with a pretopology a site, and [MM92] calls this -a basis for a topology. --/ -@[ext] +See: https://ncatlab.org/nlab/show/Grothendieck+pretopology or [MM92] Chapter III, +Section 2, Definition 2. -/ +@[ext, stacks 00VH "Note that Stacks calls a category together with a pretopology a site, +and [MM92] calls this a basis for a topology."] structure Pretopology where coverings : ∀ X : C, Set (Presieve X) has_isos : ∀ ⦃X Y⦄ (f : Y ⟶ X) [IsIso f], Presieve.singleton f ∈ coverings X diff --git a/Mathlib/CategoryTheory/Sites/Sheaf.lean b/Mathlib/CategoryTheory/Sites/Sheaf.lean index 9b7c318a4906a..b213f408e9c07 100644 --- a/Mathlib/CategoryTheory/Sites/Sheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Sheaf.lean @@ -68,10 +68,8 @@ variable (J : GrothendieckTopology C) -- We follow https://stacks.math.columbia.edu/tag/00VL definition 00VR /-- A sheaf of A is a presheaf P : Cᵒᵖ => A such that for every E : A, the -presheaf of types given by sending U : C to Hom_{A}(E, P U) is a sheaf of types. - -https://stacks.math.columbia.edu/tag/00VR --/ +presheaf of types given by sending U : C to Hom_{A}(E, P U) is a sheaf of types. -/ +@[stacks 00VR] def IsSheaf (P : Cᵒᵖ ⥤ A) : Prop := ∀ E : A, Presieve.IsSheaf J (P ⋙ coyoneda.obj (op E)) @@ -586,34 +584,35 @@ section variable [HasProducts.{max u₁ v₁} A] variable [HasProducts.{max u₁ v₁} A'] -/-- -The middle object of the fork diagram given in Equation (3) of [MM92], as well as the fork diagram -of . --/ +/-- The middle object of the fork diagram given in Equation (3) of [MM92], as well as the fork +diagram of the Stacks entry. -/ +@[stacks 00VM "The middle object of the fork diagram there."] def firstObj : A := ∏ᶜ fun f : ΣV, { f : V ⟶ U // R f } => P.obj (op f.1) -/-- -The left morphism of the fork diagram given in Equation (3) of [MM92], as well as the fork diagram -of . --/ +/-- The left morphism of the fork diagram given in Equation (3) of [MM92], as well as the fork +diagram of the Stacks entry. -/ +@[stacks 00VM "The left morphism the fork diagram there."] def forkMap : P.obj (op U) ⟶ firstObj R P := Pi.lift fun f => P.map f.2.1.op variable [HasPullbacks C] -/-- The rightmost object of the fork diagram of https://stacks.math.columbia.edu/tag/00VM, which +/-- The rightmost object of the fork diagram of the Stacks entry, which contains the data used to check a family of elements for a presieve is compatible. -/ +@[stacks 00VM "The rightmost object of the fork diagram there."] def secondObj : A := ∏ᶜ fun fg : (ΣV, { f : V ⟶ U // R f }) × ΣW, { g : W ⟶ U // R g } => P.obj (op (pullback fg.1.2.1 fg.2.2.1)) -/-- The map `pr₀*` of . -/ +/-- The map `pr₀*` of the Stacks entry. -/ +@[stacks 00VM "The map `pr₀*` there."] def firstMap : firstObj R P ⟶ secondObj R P := Pi.lift fun _ => Pi.π _ _ ≫ P.map (pullback.fst _ _).op -/-- The map `pr₁*` of . -/ +/-- The map `pr₁*` of the Stacks entry. -/ +@[stacks 00VM "The map `pr₁*` there."] def secondMap : firstObj R P ⟶ secondObj R P := Pi.lift fun _ => Pi.π _ _ ≫ P.map (pullback.snd _ _).op diff --git a/Mathlib/RingTheory/Adjoin/Tower.lean b/Mathlib/RingTheory/Adjoin/Tower.lean index 5e0b6870afb10..f0bec2c20ba93 100644 --- a/Mathlib/RingTheory/Adjoin/Tower.lean +++ b/Mathlib/RingTheory/Adjoin/Tower.lean @@ -141,7 +141,8 @@ variable [Algebra A B] [Algebra B C] [Algebra A C] [IsScalarTower A B C] A is noetherian, and C is algebra-finite over A, and C is module-finite over B, then B is algebra-finite over A. -References: Atiyah--Macdonald Proposition 7.8; Stacks 00IS; Altman--Kleiman 16.17. -/ +References: Atiyah--Macdonald Proposition 7.8; Altman--Kleiman 16.17. -/ +@[stacks 00IS] theorem fg_of_fg_of_fg [IsNoetherianRing A] (hAC : (⊤ : Subalgebra A C).FG) (hBC : (⊤ : Submodule B C).FG) (hBCi : Function.Injective (algebraMap B C)) : (⊤ : Subalgebra A B).FG := diff --git a/Mathlib/RingTheory/Etale/Basic.lean b/Mathlib/RingTheory/Etale/Basic.lean index 1f11834fdfbaa..1b85886b995e0 100644 --- a/Mathlib/RingTheory/Etale/Basic.lean +++ b/Mathlib/RingTheory/Etale/Basic.lean @@ -167,11 +167,9 @@ section variable (R : Type u) [CommRing R] variable (A : Type u) [CommRing A] [Algebra R A] -/-- An `R`-algebra `A` is étale if it is formally étale and of finite presentation. - -Note that the definition in the stacks project is -different, but shows that it is equivalent -to the definition here. -/ +/-- An `R`-algebra `A` is étale if it is formally étale and of finite presentation. -/ +@[stacks 00U1 "Note that this is a different definition from this Stacks entry, but + shows that it is equivalent to the definition here."] class Etale : Prop where formallyEtale : FormallyEtale R A := by infer_instance finitePresentation : FinitePresentation R A := by infer_instance diff --git a/Mathlib/RingTheory/FinitePresentation.lean b/Mathlib/RingTheory/FinitePresentation.lean index 06867a417b8d1..dbc3a551101b0 100644 --- a/Mathlib/RingTheory/FinitePresentation.lean +++ b/Mathlib/RingTheory/FinitePresentation.lean @@ -212,8 +212,8 @@ theorem trans [Algebra A B] [IsScalarTower R A B] [FinitePresentation R A] open MvPolynomial --- We follow the proof of https://stacks.math.columbia.edu/tag/0561 -- TODO: extract out helper lemmas and tidy proof. +@[stacks 0561] theorem of_restrict_scalars_finitePresentation [Algebra A B] [IsScalarTower R A B] [FinitePresentation.{w₁, w₃} R B] [FiniteType R A] : FinitePresentation.{w₂, w₃} A B := by diff --git a/Mathlib/RingTheory/Finiteness/Nakayama.lean b/Mathlib/RingTheory/Finiteness/Nakayama.lean index a5ae263188b4d..d17b83e9cc888 100644 --- a/Mathlib/RingTheory/Finiteness/Nakayama.lean +++ b/Mathlib/RingTheory/Finiteness/Nakayama.lean @@ -26,8 +26,8 @@ variable {R : Type*} {M : Type*} [Semiring R] [AddCommMonoid M] [Module R M] open Set -/-- **Nakayama's Lemma**. Atiyah-Macdonald 2.5, Eisenbud 4.7, Matsumura 2.2, -[Stacks 00DV](https://stacks.math.columbia.edu/tag/00DV) -/ +/-- **Nakayama's Lemma**. Atiyah-Macdonald 2.5, Eisenbud 4.7, Matsumura 2.2. -/ +@[stacks 00DV] theorem exists_sub_one_mem_and_smul_eq_zero_of_fg_of_le_smul {R : Type*} [CommRing R] {M : Type*} [AddCommGroup M] [Module R M] (I : Ideal R) (N : Submodule R M) (hn : N.FG) (hin : N ≤ I • N) : ∃ r : R, r - 1 ∈ I ∧ ∀ n ∈ N, r • n = (0 : M) := by diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index ee0467668b791..1c18bee75de0d 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -1035,7 +1035,8 @@ theorem subset_union_prime' {R : Type u} [CommRing R] {s : Finset ι} {f : ι exact hs <| Or.inr <| Set.mem_biUnion hjt <| add_sub_cancel_left r s ▸ (f j).sub_mem hj <| hr j hjt -/-- Prime avoidance. Atiyah-Macdonald 1.11, Eisenbud 3.3, Stacks 00DS, Matsumura Ex.1.6. -/ +/-- Prime avoidance. Atiyah-Macdonald 1.11, Eisenbud 3.3, Matsumura Ex.1.6. -/ +@[stacks 00DS] theorem subset_union_prime {R : Type u} [CommRing R] {s : Finset ι} {f : ι → Ideal R} (a b : ι) (hp : ∀ i ∈ s, i ≠ a → i ≠ b → IsPrime (f i)) {I : Ideal R} : ((I : Set R) ⊆ ⋃ i ∈ (↑s : Set ι), f i) ↔ ∃ i ∈ s, I ≤ f i := diff --git a/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean b/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean index 2c5a8113251ff..e2b6096cd016d 100644 --- a/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean +++ b/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean @@ -86,8 +86,8 @@ section variable [CommSemiring R] [IsLocalRing R] [CommSemiring S] [IsLocalRing S] /-- A ring homomorphism between local rings is a local ring hom iff it reflects units, -i.e. any preimage of a unit is still a unit. https://stacks.math.columbia.edu/tag/07BJ --/ +i.e. any preimage of a unit is still a unit. -/ +@[stacks 07BJ] theorem local_hom_TFAE (f : R →+* S) : List.TFAE [IsLocalHom f, f '' (maximalIdeal R).1 ⊆ maximalIdeal S, diff --git a/Mathlib/RingTheory/Smooth/Basic.lean b/Mathlib/RingTheory/Smooth/Basic.lean index 76b6df39845a5..9ccb330ef6a71 100644 --- a/Mathlib/RingTheory/Smooth/Basic.lean +++ b/Mathlib/RingTheory/Smooth/Basic.lean @@ -340,12 +340,9 @@ section variable (R : Type u) [CommSemiring R] variable (A : Type u) [Semiring A] [Algebra R A] -/-- An `R` algebra `A` is smooth if it is formally smooth and of finite presentation. - -In the stacks project, the definition of smooth is completely different, and tag - proves that their definition is equivalent -to this. --/ +/-- An `R` algebra `A` is smooth if it is formally smooth and of finite presentation. -/ +@[stacks 00T2 "In the stacks project, the definition of smooth is completely different, and tag + proves that their definition is equivalent to this."] class Smooth [CommSemiring R] (A : Type u) [Semiring A] [Algebra R A] : Prop where formallySmooth : FormallySmooth R A := by infer_instance finitePresentation : FinitePresentation R A := by infer_instance diff --git a/Mathlib/RingTheory/Spectrum/Prime/IsOpenComapC.lean b/Mathlib/RingTheory/Spectrum/Prime/IsOpenComapC.lean index 4a6c542cd5693..2117b0ff26773 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/IsOpenComapC.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/IsOpenComapC.lean @@ -59,11 +59,8 @@ theorem imageOfDf_eq_comap_C_compl_zeroLocus : · rintro ⟨xli, complement, rfl⟩ exact comap_C_mem_imageOfDf complement -/-- The morphism `C⁺ : Spec R[x] → Spec R` is open. -Stacks Project "Lemma 00FB", first part. - -https://stacks.math.columbia.edu/tag/00FB --/ +/-- The morphism `C⁺ : Spec R[x] → Spec R` is open. -/ +@[stacks 00FB "First part"] theorem isOpenMap_comap_C : IsOpenMap (PrimeSpectrum.comap (C : R →+* R[X])) := by rintro U ⟨s, z⟩ rw [← compl_compl U, ← z, ← iUnion_of_singleton_coe s, zeroLocus_iUnion, compl_iInter, diff --git a/Mathlib/RingTheory/Spectrum/Prime/Topology.lean b/Mathlib/RingTheory/Spectrum/Prime/Topology.lean index 52f45bb237367..c846ca364238f 100644 --- a/Mathlib/RingTheory/Spectrum/Prime/Topology.lean +++ b/Mathlib/RingTheory/Spectrum/Prime/Topology.lean @@ -976,11 +976,9 @@ section CommSemiring variable [CommSemiring R] open PrimeSpectrum in -/-- -[Stacks: Lemma 00ES (3)](https://stacks.math.columbia.edu/tag/00ES) -Zero loci of minimal prime ideals of `R` are irreducible components in `Spec R` and any -irreducible component is a zero locus of some minimal prime ideal. --/ +/-- Zero loci of minimal prime ideals of `R` are irreducible components in `Spec R` and any +irreducible component is a zero locus of some minimal prime ideal. -/ +@[stacks 00ES] protected def minimalPrimes.equivIrreducibleComponents : minimalPrimes R ≃o (irreducibleComponents <| PrimeSpectrum R)ᵒᵈ := by let e : {p : Ideal R | p.IsPrime ∧ ⊥ ≤ p} ≃o PrimeSpectrum R := diff --git a/Mathlib/RingTheory/Unramified/Basic.lean b/Mathlib/RingTheory/Unramified/Basic.lean index f24642133de7f..8d6c532010819 100644 --- a/Mathlib/RingTheory/Unramified/Basic.lean +++ b/Mathlib/RingTheory/Unramified/Basic.lean @@ -282,12 +282,9 @@ section variable (R : Type*) [CommRing R] variable (A : Type*) [CommRing A] [Algebra R A] -/-- An `R`-algebra `A` is unramified if it is formally unramified and of finite type. - -Note that the Stacks project has a different definition of unramified, and tag - shows that their definition is the -same as this one. --/ +/-- An `R`-algebra `A` is unramified if it is formally unramified and of finite type. -/ +@[stacks 00UT "Note that the Stacks project has a different definition of unramified, and tag + shows that their definition is the same as this one."] class Unramified : Prop where formallyUnramified : FormallyUnramified R A := by infer_instance finiteType : FiniteType R A := by infer_instance diff --git a/Mathlib/Topology/NoetherianSpace.lean b/Mathlib/Topology/NoetherianSpace.lean index 931e8748cbfce..e26ec3b5c4b6d 100644 --- a/Mathlib/Topology/NoetherianSpace.lean +++ b/Mathlib/Topology/NoetherianSpace.lean @@ -70,7 +70,7 @@ protected theorem _root_.Topology.IsInducing.noetherianSpace [NoetherianSpace α @[deprecated (since := "2024-10-28")] alias _root_.Inducing.noetherianSpace := IsInducing.noetherianSpace -/-- [Stacks: Lemma 0052 (1)](https://stacks.math.columbia.edu/tag/0052)-/ +@[stacks 0052 "(1)"] instance NoetherianSpace.set [NoetherianSpace α] (s : Set α) : NoetherianSpace s := IsInducing.subtypeVal.noetherianSpace @@ -191,7 +191,7 @@ theorem NoetherianSpace.exists_finset_irreducible [NoetherianSpace α] (s : Clos simpa [Set.exists_finite_iff_finset, Finset.sup_id_eq_sSup] using NoetherianSpace.exists_finite_set_closeds_irreducible s -/-- [Stacks: Lemma 0052 (2)](https://stacks.math.columbia.edu/tag/0052) -/ +@[stacks 0052 "(2)"] theorem NoetherianSpace.finite_irreducibleComponents [NoetherianSpace α] : (irreducibleComponents α).Finite := by obtain ⟨S : Set (Set α), hSf, hSc, hSi, hSU⟩ := @@ -201,7 +201,7 @@ theorem NoetherianSpace.finite_irreducibleComponents [NoetherianSpace α] : rcases isIrreducible_iff_sUnion_isClosed.1 hs.1 S hSc (hSU ▸ Set.subset_univ _) with ⟨t, htS, ht⟩ rwa [ht.antisymm (hs.2 (hSi _ htS) ht)] -/-- [Stacks: Lemma 0052 (3)](https://stacks.math.columbia.edu/tag/0052) -/ +@[stacks 0052 "(3)"] theorem NoetherianSpace.exists_open_ne_empty_le_irreducibleComponent [NoetherianSpace α] (Z : Set α) (H : Z ∈ irreducibleComponents α) : ∃ o : Set α, IsOpen o ∧ o ≠ ∅ ∧ o ≤ Z := by diff --git a/Mathlib/Topology/Separation/Regular.lean b/Mathlib/Topology/Separation/Regular.lean index 3be8602edb54b..ae49d2084217e 100644 --- a/Mathlib/Topology/Separation/Regular.lean +++ b/Mathlib/Topology/Separation/Regular.lean @@ -3,8 +3,9 @@ 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, Mario Carneiro -/ -import Mathlib.Topology.Separation.Hausdorff +import Mathlib.Tactic.StacksAttribute import Mathlib.Topology.Compactness.Lindelof +import Mathlib.Topology.Separation.Hausdorff /-! # Regular, normal, T₃, T₄ and T₅ spaces @@ -637,8 +638,8 @@ theorem connectedComponent_eq_iInter_isClopen [T2Space X] [CompactSpace X] (x : ⟨s ∩ v, H2, mem_inter H.2.1 h1⟩ /-- `ConnectedComponents X` is Hausdorff when `X` is Hausdorff and compact -/ +@[stacks 0900 "The Stacks entry proves profiniteness."] instance ConnectedComponents.t2 [T2Space X] [CompactSpace X] : T2Space (ConnectedComponents X) := by - -- Proof follows that of: https://stacks.math.columbia.edu/tag/0900 -- Fix 2 distinct connected components, with points a and b refine ⟨ConnectedComponents.surjective_coe.forall₂.2 fun a b ne => ?_⟩ rw [ConnectedComponents.coe_ne_coe] at ne From afd713f864ea3f20d3ede2b3227805cfd8f7595a Mon Sep 17 00:00:00 2001 From: Markus Himmel Date: Tue, 28 Jan 2025 09:37:27 +0000 Subject: [PATCH 595/681] feat: equalizers and coequalizers in the category of ind-objects (#21139) We study parallel pairs of morphisms in `Ind C`, discover that they are always induced by natural transformations in a suitable indexing category, and deduce that ind-objects are closed under equalizers and the category of ind-objects has coequalizers. Huge thanks to @javra and @datokrat. If they had not spent countless hours tirelessly PRing properties of comma categories and the Grothendieck construction to mathlib this PR would not have been possible, even though you can't see any of their results used in the PR (since they are applied by instance synthesis). Co-authored-by: Markus Himmel --- Mathlib.lean | 1 + .../Limits/Indization/Category.lean | 44 ++++- .../Limits/Indization/Equalizers.lean | 26 ++- .../Limits/Indization/ParallelPair.lean | 171 ++++++++++++++++++ 4 files changed, 232 insertions(+), 10 deletions(-) create mode 100644 Mathlib/CategoryTheory/Limits/Indization/ParallelPair.lean diff --git a/Mathlib.lean b/Mathlib.lean index 7957aa53874e1..e36e8aed8c257 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1932,6 +1932,7 @@ import Mathlib.CategoryTheory.Limits.Indization.Equalizers import Mathlib.CategoryTheory.Limits.Indization.FilteredColimits import Mathlib.CategoryTheory.Limits.Indization.IndObject import Mathlib.CategoryTheory.Limits.Indization.LocallySmall +import Mathlib.CategoryTheory.Limits.Indization.ParallelPair import Mathlib.CategoryTheory.Limits.Indization.Products import Mathlib.CategoryTheory.Limits.IsConnected import Mathlib.CategoryTheory.Limits.IsLimit diff --git a/Mathlib/CategoryTheory/Limits/Indization/Category.lean b/Mathlib/CategoryTheory/Limits/Indization/Category.lean index 7b2b555d9cb66..c1cf76d2a04fe 100644 --- a/Mathlib/CategoryTheory/Limits/Indization/Category.lean +++ b/Mathlib/CategoryTheory/Limits/Indization/Category.lean @@ -7,6 +7,7 @@ import Mathlib.CategoryTheory.Functor.Flat import Mathlib.CategoryTheory.Limits.Constructions.Filtered import Mathlib.CategoryTheory.Limits.FullSubcategory import Mathlib.CategoryTheory.Limits.Indization.LocallySmall +import Mathlib.CategoryTheory.Limits.Indization.ParallelPair import Mathlib.CategoryTheory.Limits.Indization.FilteredColimits import Mathlib.CategoryTheory.Limits.Indization.Products @@ -30,7 +31,8 @@ Adopting the theorem numbering of [Kashiwara2006], we show that * if `C` has finite coproducts, then `Ind C` has small coproducts (6.1.18(ii)), * if `C` has products indexed by `α`, then `Ind C` has products indexed by `α`, and the functor `Ind C ⥤ Cᵒᵖ ⥤ Type v` creates such products (6.1.17) -* the functor `C ⥤ Ind C` preserves small limits. +* the functor `C ⥤ Ind C` preserves small limits, +* if `C` has coequalizers, then `Ind C` has coequalizers (6.1.18(i)). More limit-colimit properties will follow. @@ -43,7 +45,7 @@ Note that: * [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Chapter 6 -/ -universe v u +universe w v u namespace CategoryTheory @@ -180,14 +182,14 @@ noncomputable def Ind.limCompInclusion {I : Type v} [SmallCategory I] [IsFiltere _ ≅ (whiskeringRight _ _ _).obj yoneda ⋙ colim := isoWhiskerRight ((whiskeringRight _ _ _).mapIso (Ind.yonedaCompInclusion)) colim -instance {α : Type v} [SmallCategory α] [FinCategory α] [HasLimitsOfShape α C] {I : Type v} +instance {α : Type w} [SmallCategory α] [FinCategory α] [HasLimitsOfShape α C] {I : Type v} [SmallCategory I] [IsFiltered I] : PreservesLimitsOfShape α (Ind.lim I : (I ⥤ C) ⥤ _) := haveI : PreservesLimitsOfShape α (Ind.lim I ⋙ Ind.inclusion C) := preservesLimitsOfShape_of_natIso Ind.limCompInclusion.symm preservesLimitsOfShape_of_reflects_of_preserves _ (Ind.inclusion C) -instance {α : Type v} [SmallCategory α] [FinCategory α] [HasColimitsOfShape α C] {I : Type v} +instance {α : Type w} [SmallCategory α] [FinCategory α] [HasColimitsOfShape α C] {I : Type v} [SmallCategory I] [IsFiltered I] : PreservesColimitsOfShape α (Ind.lim I : (I ⥤ C) ⥤ _) := inferInstanceAs (PreservesColimitsOfShape α (_ ⋙ colim)) @@ -209,11 +211,43 @@ instance {α : Type v} [Finite α] [HasColimitsOfShape (Discrete α) C] : -- ``` -- from the fact that finite limits commute with filtered colimits and from the fact that -- `Ind.yoneda` preserves finite colimits. - apply hasColimitOfIso iso.symm + exact hasColimitOfIso iso.symm instance [HasFiniteCoproducts C] : HasCoproducts.{v} (Ind C) := have : HasFiniteCoproducts (Ind C) := ⟨fun _ => hasColimitsOfShape_of_equivalence (Discrete.equivalence Equiv.ulift)⟩ hasCoproducts_of_finite_and_filtered +/-- Given an `IndParallelPairPresentation f g`, we can understand the parallel pair `(f, g)` as +the colimit of `(P.φ, P.ψ)` in `Ind C`. -/ +noncomputable def IndParallelPairPresentation.parallelPairIsoParallelPairCompIndYoneda + {A B : Ind C} {f g : A ⟶ B} + (P : IndParallelPairPresentation ((Ind.inclusion _).map f) ((Ind.inclusion _).map g)) : + parallelPair f g ≅ parallelPair P.φ P.ψ ⋙ Ind.lim P.I := + ((whiskeringRight WalkingParallelPair _ _).obj (Ind.inclusion C)).preimageIso <| + diagramIsoParallelPair _ ≪≫ + P.parallelPairIsoParallelPairCompYoneda ≪≫ + isoWhiskerLeft (parallelPair _ _) Ind.limCompInclusion.symm + +instance [HasColimitsOfShape WalkingParallelPair C] : + HasColimitsOfShape WalkingParallelPair (Ind C) := by + refine ⟨fun F => ?_⟩ + obtain ⟨P⟩ := nonempty_indParallelPairPresentation (F.obj WalkingParallelPair.zero).2 + (F.obj WalkingParallelPair.one).2 (Ind.inclusion _ |>.map <| F.map WalkingParallelPairHom.left) + (Ind.inclusion _ |>.map <| F.map WalkingParallelPairHom.right) + exact hasColimitOfIso (diagramIsoParallelPair _ ≪≫ P.parallelPairIsoParallelPairCompIndYoneda) + +/-- A way to understand morphisms in `Ind C`: every morphism is induced by a natural transformation +of diagrams. -/ +theorem Ind.exists_nonempty_arrow_mk_iso_ind_lim {A B : Ind C} {f : A ⟶ B} : + ∃ (I : Type v) (_ : SmallCategory I) (_ : IsFiltered I) (F G : I ⥤ C) (φ : F ⟶ G), + Nonempty (Arrow.mk f ≅ Arrow.mk ((Ind.lim _).map φ)) := by + obtain ⟨P⟩ := nonempty_indParallelPairPresentation A.2 B.2 + (Ind.inclusion _ |>.map f) (Ind.inclusion _ |>.map f) + refine ⟨P.I, inferInstance, inferInstance, P.F₁, P.F₂, P.φ, ⟨Arrow.isoMk ?_ ?_ ?_⟩⟩ + · exact P.parallelPairIsoParallelPairCompIndYoneda.app WalkingParallelPair.zero + · exact P.parallelPairIsoParallelPairCompIndYoneda.app WalkingParallelPair.one + · simpa using + (P.parallelPairIsoParallelPairCompIndYoneda.hom.naturality WalkingParallelPairHom.left).symm + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Indization/Equalizers.lean b/Mathlib/CategoryTheory/Limits/Indization/Equalizers.lean index ef9fd1afa688d..880fad0485062 100644 --- a/Mathlib/CategoryTheory/Limits/Indization/Equalizers.lean +++ b/Mathlib/CategoryTheory/Limits/Indization/Equalizers.lean @@ -4,16 +4,15 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel -/ import Mathlib.CategoryTheory.Limits.Indization.FilteredColimits +import Mathlib.CategoryTheory.Limits.FullSubcategory +import Mathlib.CategoryTheory.Limits.Indization.ParallelPair /-! # Equalizers of ind-objects -The eventual goal of this file is to show that if a category `C` has equalizers, then ind-objects -are closed under equalizers. For now, it contains one of the main prerequisites, namely we show -that under sufficient conditions the limit of a diagram in `I ⥤ C` taken in `Cᵒᵖ ⥤ Type v` is an -ind-object. +We show that if a category `C` has equalizers, then ind-objects are closed under equalizers. -## References +# References * [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Section 6.1 -/ @@ -60,4 +59,21 @@ theorem isIndObject_limit_comp_yoneda_comp_colim end +/-- If `C` has equalizers. then ind-objects are closed under equalizers. + +This is Proposition 6.1.17(i) in [Kashiwara2006]. +-/ +theorem closedUnderLimitsOfShape_walkingParallelPair_isIndObject [HasEqualizers C] : + ClosedUnderLimitsOfShape WalkingParallelPair (IsIndObject (C := C)) := by + apply closedUnderLimitsOfShape_of_limit + intro F hF h + obtain ⟨P⟩ := nonempty_indParallelPairPresentation (h WalkingParallelPair.zero) + (h WalkingParallelPair.one) (F.map WalkingParallelPairHom.left) + (F.map WalkingParallelPairHom.right) + exact IsIndObject.map + (HasLimit.isoOfNatIso (P.parallelPairIsoParallelPairCompYoneda.symm ≪≫ + (diagramIsoParallelPair _).symm)).hom + (isIndObject_limit_comp_yoneda_comp_colim (parallelPair P.φ P.ψ) + (fun i => isIndObject_limit_comp_yoneda _)) + end CategoryTheory.Limits diff --git a/Mathlib/CategoryTheory/Limits/Indization/ParallelPair.lean b/Mathlib/CategoryTheory/Limits/Indization/ParallelPair.lean new file mode 100644 index 0000000000000..68c898bc32634 --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Indization/ParallelPair.lean @@ -0,0 +1,171 @@ +/- +Copyright (c) 2025 Markus Himmel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Markus Himmel +-/ +import Mathlib.CategoryTheory.Comma.Final +import Mathlib.CategoryTheory.Limits.Indization.IndObject + +/-! +# Parallel pairs of natural transformations between ind-objects + +We show that if `A` and `B` are ind-objects and `f` and `g` are natural transformations between +`A` and `B`, then there is a small filtered category `I` such that `A`, `B`, `f` and `g` are +commonly presented by diagrams and natural transformations in `I ⥤ C`. + + +## References +* [M. Kashiwara, P. Schapira, *Categories and Sheaves*][Kashiwara2006], Proposition 6.1.15 (though + our proof is more direct). +-/ + +universe v₁ v₂ v₃ u₁ u₂ u₃ + +namespace CategoryTheory + +open Limits + +variable {C : Type u₁} [Category.{v₁} C] + +/-- Structure containing data exhibiting two parallel natural transformations `f` and `g` between +presheaves `A` and `B` as induced by a natural transformation in a functor category exhibiting +`A` and `B` as ind-objects. -/ +structure IndParallelPairPresentation {A B : Cᵒᵖ ⥤ Type v₁} (f g : A ⟶ B) where + /-- The indexing category. -/ + I : Type v₁ + /-- Category instance on the indexing category. -/ + [ℐ : SmallCategory I] + [hI : IsFiltered I] + /-- The diagram presenting `A`. -/ + F₁ : I ⥤ C + /-- The diagram presenting `B`. -/ + F₂ : I ⥤ C + /-- The cocone on `F₁` with apex `A`. -/ + ι₁ : F₁ ⋙ yoneda ⟶ (Functor.const I).obj A + /-- The cocone on `F₁` with apex `A` is a colimit cocone. -/ + isColimit₁ : IsColimit (Cocone.mk A ι₁) + /-- The cocone on `F₂` with apex `B`. -/ + ι₂ : F₂ ⋙ yoneda ⟶ (Functor.const I).obj B + /-- The cocone on `F₂` with apex `B` is a colimit cocone. -/ + isColimit₂ : IsColimit (Cocone.mk B ι₂) + /-- The natural transformation presenting `f`. -/ + φ : F₁ ⟶ F₂ + /-- The natural transformation presenting `g`. -/ + ψ : F₁ ⟶ F₂ + /-- `f` is in fact presented by `φ`. -/ + hf : f = IsColimit.map isColimit₁ (Cocone.mk B ι₂) (whiskerRight φ yoneda) + /-- `g` is in fact presented by `ψ`. -/ + hg : g = IsColimit.map isColimit₁ (Cocone.mk B ι₂) (whiskerRight ψ yoneda) + +instance {A B : Cᵒᵖ ⥤ Type v₁} {f g : A ⟶ B} (P : IndParallelPairPresentation f g) : + SmallCategory P.I := P.ℐ +instance {A B : Cᵒᵖ ⥤ Type v₁} {f g : A ⟶ B} (P : IndParallelPairPresentation f g) : + IsFiltered P.I := P.hI + +namespace NonemptyParallelPairPresentationAux + +variable {A B : Cᵒᵖ ⥤ Type v₁} (f g : A ⟶ B) (P₁ : IndObjectPresentation A) + (P₂ : IndObjectPresentation B) + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +abbrev K : Type v₁ := + Comma ((P₁.toCostructuredArrow ⋙ CostructuredArrow.map f).prod' + (P₁.toCostructuredArrow ⋙ CostructuredArrow.map g)) + (P₂.toCostructuredArrow.prod' P₂.toCostructuredArrow) + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +abbrev F₁ : K f g P₁ P₂ ⥤ C := Comma.fst _ _ ⋙ P₁.F +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +abbrev F₂ : K f g P₁ P₂ ⥤ C := Comma.snd _ _ ⋙ P₂.F + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +abbrev ι₁ : F₁ f g P₁ P₂ ⋙ yoneda ⟶ (Functor.const (K f g P₁ P₂)).obj A := + whiskerLeft (Comma.fst _ _) P₁.ι + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +noncomputable abbrev isColimit₁ : IsColimit (Cocone.mk A (ι₁ f g P₁ P₂)) := + (Functor.Final.isColimitWhiskerEquiv _ _).symm P₁.isColimit + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +abbrev ι₂ : F₂ f g P₁ P₂ ⋙ yoneda ⟶ (Functor.const (K f g P₁ P₂)).obj B := + whiskerLeft (Comma.snd _ _) P₂.ι + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +noncomputable abbrev isColimit₂ : IsColimit (Cocone.mk B (ι₂ f g P₁ P₂)) := + (Functor.Final.isColimitWhiskerEquiv _ _).symm P₂.isColimit + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +def ϕ : F₁ f g P₁ P₂ ⟶ F₂ f g P₁ P₂ where + app h := h.hom.1.left + naturality _ _ h := by + have := h.w + simp only [Functor.prod'_obj, Functor.comp_obj, prod_Hom, Functor.prod'_map, Functor.comp_map, + prod_comp, Prod.mk.injEq, CostructuredArrow.hom_eq_iff, CostructuredArrow.map_obj_left, + IndObjectPresentation.toCostructuredArrow_obj_left, CostructuredArrow.comp_left, + CostructuredArrow.map_map_left, IndObjectPresentation.toCostructuredArrow_map_left] at this + exact this.1 + +theorem hf : f = IsColimit.map (isColimit₁ f g P₁ P₂) + (Cocone.mk B (ι₂ f g P₁ P₂)) (whiskerRight (ϕ f g P₁ P₂) yoneda) := by + refine (isColimit₁ f g P₁ P₂).hom_ext (fun i => ?_) + rw [IsColimit.ι_map] + simpa using i.hom.1.w.symm + +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +def ψ : F₁ f g P₁ P₂ ⟶ F₂ f g P₁ P₂ where + app h := h.hom.2.left + naturality _ _ h := by + have := h.w + simp only [Functor.prod'_obj, Functor.comp_obj, prod_Hom, Functor.prod'_map, Functor.comp_map, + prod_comp, Prod.mk.injEq, CostructuredArrow.hom_eq_iff, CostructuredArrow.map_obj_left, + IndObjectPresentation.toCostructuredArrow_obj_left, CostructuredArrow.comp_left, + CostructuredArrow.map_map_left, IndObjectPresentation.toCostructuredArrow_map_left] at this + exact this.2 + +theorem hg : g = IsColimit.map (isColimit₁ f g P₁ P₂) + (Cocone.mk B (ι₂ f g P₁ P₂)) (whiskerRight (ψ f g P₁ P₂) yoneda) := by + refine (isColimit₁ f g P₁ P₂).hom_ext (fun i => ?_) + rw [IsColimit.ι_map] + simpa using i.hom.2.w.symm + +attribute [local instance] Comma.isFiltered_of_final in +/-- Implementation; see `nonempty_indParallelPairPresentation`. -/ +noncomputable def presentation : IndParallelPairPresentation f g where + I := K f g P₁ P₂ + F₁ := F₁ f g P₁ P₂ + F₂ := F₂ f g P₁ P₂ + ι₁ := ι₁ f g P₁ P₂ + isColimit₁ := isColimit₁ f g P₁ P₂ + ι₂ := ι₂ f g P₁ P₂ + isColimit₂ := isColimit₂ f g P₁ P₂ + φ := ϕ f g P₁ P₂ + ψ := ψ f g P₁ P₂ + hf := hf f g P₁ P₂ + hg := hg f g P₁ P₂ + +end NonemptyParallelPairPresentationAux + +theorem nonempty_indParallelPairPresentation {A B : Cᵒᵖ ⥤ Type v₁} (hA : IsIndObject A) + (hB : IsIndObject B) (f g : A ⟶ B) : Nonempty (IndParallelPairPresentation f g) := + ⟨NonemptyParallelPairPresentationAux.presentation f g hA.presentation hB.presentation⟩ + +namespace IndParallelPairPresentation + +/-- Given an `IndParallelPairPresentation f g`, we can understand the parallel pair `(f, g)` +as the colimit of `(P.φ, P.ψ)` in `Cᵒᵖ ⥤ Type v`. -/ +noncomputable def parallelPairIsoParallelPairCompYoneda {A B : Cᵒᵖ ⥤ Type v₁} {f g : A ⟶ B} + (P : IndParallelPairPresentation f g) : + parallelPair f g ≅ parallelPair P.φ P.ψ ⋙ (whiskeringRight _ _ _).obj yoneda ⋙ colim := + parallelPair.ext + (P.isColimit₁.coconePointUniqueUpToIso (colimit.isColimit _)) + (P.isColimit₂.coconePointUniqueUpToIso (colimit.isColimit _)) + (P.isColimit₁.hom_ext (fun j => by + simp [P.hf, P.isColimit₁.ι_map_assoc, P.isColimit₁.comp_coconePointUniqueUpToIso_hom_assoc, + P.isColimit₂.comp_coconePointUniqueUpToIso_hom])) + (P.isColimit₁.hom_ext (fun j => by + simp [P.hg, P.isColimit₁.ι_map_assoc, P.isColimit₁.comp_coconePointUniqueUpToIso_hom_assoc, + P.isColimit₂.comp_coconePointUniqueUpToIso_hom])) + +end IndParallelPairPresentation + +end CategoryTheory From 20c785e90a6474743c8f4bc446a175dce562443f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Tue, 28 Jan 2025 10:27:21 +0000 Subject: [PATCH 596/681] =?UTF-8?q?chore:=20use=20`=E2=80=96x=E2=80=96?= =?UTF-8?q?=E2=82=91`=20instead=20of=20`=E2=86=91=E2=80=96x=E2=80=96?= =?UTF-8?q?=E2=82=8A`=20(#20806)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename lemmas from `_nnnorm_`/`_ennnorm_` to `_enorm_` where applicable. Rewrite/golf proofs where necessary. --- Mathlib/Analysis/Analytic/Basic.lean | 20 +- Mathlib/Analysis/Analytic/CPolynomial.lean | 11 +- Mathlib/Analysis/Analytic/ChangeOrigin.lean | 9 +- Mathlib/Analysis/Analytic/Composition.lean | 8 +- Mathlib/Analysis/Analytic/Inverse.lean | 6 +- Mathlib/Analysis/Analytic/Uniqueness.lean | 2 +- Mathlib/Analysis/Analytic/Within.lean | 8 +- .../Analysis/BoxIntegral/Integrability.lean | 2 +- .../Analysis/Calculus/FDeriv/Analytic.lean | 10 +- Mathlib/Analysis/Complex/CauchyIntegral.lean | 2 +- Mathlib/Analysis/Convex/EGauge.lean | 64 ++-- .../FunctionalSpaces/SobolevInequality.lean | 91 +++-- Mathlib/Analysis/Normed/Algebra/Spectrum.lean | 6 +- Mathlib/Analysis/Normed/Group/Basic.lean | 64 ++-- .../SpecialFunctions/JapaneseBracket.lean | 6 +- .../Constructions/BorelSpace/Metric.lean | 19 +- .../Covering/Differentiation.lean | 70 ++-- .../ConditionalExpectation/CondexpL1.lean | 6 +- .../ConditionalExpectation/CondexpL2.lean | 8 +- .../Function/ConditionalExpectation/Real.lean | 16 +- .../ConditionalExpectation/Unique.lean | 14 +- .../Function/ContinuousMapDense.lean | 19 +- .../Function/ConvergenceInMeasure.lean | 2 +- Mathlib/MeasureTheory/Function/L1Space.lean | 191 +++++----- Mathlib/MeasureTheory/Function/L2Space.lean | 4 +- .../Function/LpSeminorm/Basic.lean | 337 +++++++++--------- .../Function/LpSeminorm/ChebyshevMarkov.lean | 4 +- .../Function/LpSeminorm/CompareExp.lean | 12 +- .../LpSeminorm/TriangleInequality.lean | 4 +- .../Function/LpSeminorm/Trim.lean | 2 +- Mathlib/MeasureTheory/Function/LpSpace.lean | 193 +++++----- .../Function/SimpleFuncDenseLp.lean | 63 ++-- .../Function/StronglyMeasurable/Basic.lean | 12 +- .../Function/UniformIntegrable.lean | 58 ++- Mathlib/MeasureTheory/Integral/Bochner.lean | 94 ++--- .../Integral/BoundedContinuousFunction.lean | 2 +- .../Integral/DominatedConvergence.lean | 15 +- .../Integral/FundThmCalculus.lean | 2 +- .../MeasureTheory/Integral/IntegrableOn.lean | 6 +- .../Integral/IntegralEqImproper.lean | 58 ++- Mathlib/MeasureTheory/Integral/Lebesgue.lean | 27 +- Mathlib/MeasureTheory/Integral/Prod.lean | 24 +- .../MeasureTheory/Integral/SetIntegral.lean | 14 +- Mathlib/MeasureTheory/Integral/SetToL1.lean | 14 +- .../MeasureTheory/Measure/Haar/Quotient.lean | 12 +- .../Measure/Lebesgue/EqHaar.lean | 2 +- .../NumberTheory/ModularForms/QExpansion.lean | 4 +- Mathlib/Probability/Density.lean | 15 +- .../Probability/Distributions/Uniform.lean | 4 +- Mathlib/Probability/Integration.lean | 49 ++- .../Kernel/Composition/IntegralCompProd.lean | 29 +- Mathlib/Probability/Kernel/CondDistrib.lean | 2 +- .../Kernel/Disintegration/CondCDF.lean | 2 +- .../Kernel/MeasurableIntegral.lean | 2 +- .../Probability/Martingale/Convergence.lean | 2 +- Mathlib/Probability/Variance.lean | 47 +-- scripts/nolints_prime_decls.txt | 6 +- 57 files changed, 869 insertions(+), 906 deletions(-) diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index f607e676809c6..095e60deae80a 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -503,13 +503,13 @@ theorem HasFPowerSeriesOnBall.comp_sub (hf : HasFPowerSeriesOnBall f p x r) (y : theorem HasFPowerSeriesWithinOnBall.hasSum_sub (hf : HasFPowerSeriesWithinOnBall f p s x r) {y : E} (hy : y ∈ (insert x s) ∩ EMetric.ball x r) : HasSum (fun n : ℕ => p n fun _ => y - x) (f y) := by - have : y - x ∈ EMetric.ball (0 : E) r := by simpa [edist_eq_coe_nnnorm_sub] using hy.2 + have : y - x ∈ EMetric.ball (0 : E) r := by simpa [edist_eq_enorm_sub] using hy.2 have := hf.hasSum (by simpa only [add_sub_cancel] using hy.1) this simpa only [add_sub_cancel] theorem HasFPowerSeriesOnBall.hasSum_sub (hf : HasFPowerSeriesOnBall f p x r) {y : E} (hy : y ∈ EMetric.ball x r) : HasSum (fun n : ℕ => p n fun _ => y - x) (f y) := by - have : y - x ∈ EMetric.ball (0 : E) r := by simpa [edist_eq_coe_nnnorm_sub] using hy + have : y - x ∈ EMetric.ball (0 : E) r := by simpa [edist_eq_enorm_sub] using hy simpa only [add_sub_cancel] using hf.hasSum this theorem HasFPowerSeriesOnBall.radius_pos (hf : HasFPowerSeriesOnBall f p x r) : 0 < p.radius := @@ -544,7 +544,7 @@ lemma HasFPowerSeriesWithinOnBall.congr {f g : E → F} {p : FormalMultilinearSe · simpa using h'' · apply h' refine ⟨hy, ?_⟩ - simpa [edist_eq_coe_nnnorm_sub] using h'y + simpa [edist_eq_enorm_sub] using h'y /-- Variant of `HasFPowerSeriesWithinOnBall.congr` in which one requests equality on `insert x s` instead of separating `x` and `s`. -/ @@ -554,7 +554,7 @@ lemma HasFPowerSeriesWithinOnBall.congr' {f g : E → F} {p : FormalMultilinearS HasFPowerSeriesWithinOnBall g p s x r := by refine ⟨h.r_le, h.r_pos, fun {y} hy h'y ↦ ?_⟩ convert h.hasSum hy h'y using 1 - exact h' ⟨hy, by simpa [edist_eq_coe_nnnorm_sub] using h'y⟩ + exact h' ⟨hy, by simpa [edist_eq_enorm_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) : @@ -576,7 +576,7 @@ theorem HasFPowerSeriesOnBall.congr (hf : HasFPowerSeriesOnBall f p x r) hasSum := fun {y} hy => by convert hf.hasSum hy using 1 apply hg.symm - simpa [edist_eq_coe_nnnorm_sub] using hy } + simpa [edist_eq_enorm_sub] using hy } theorem HasFPowerSeriesAt.congr (hf : HasFPowerSeriesAt f p x) (hg : f =ᶠ[𝓝 x] g) : HasFPowerSeriesAt g p x := by @@ -679,7 +679,7 @@ theorem HasFPowerSeriesWithinAt.mono_of_mem_nhdsWithin rcases hy with rfl | hy · simp apply mem_insert_of_mem _ (hr' ?_) - simp only [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, sub_zero, lt_min_iff, mem_inter_iff, + simp only [EMetric.mem_ball, edist_eq_enorm_sub, sub_zero, lt_min_iff, mem_inter_iff, add_sub_cancel_left, hy, and_true] at h'y ⊢ exact h'y.2 @@ -912,7 +912,7 @@ theorem HasFPowerSeriesWithinOnBall.tendsto_partialSum_prod {y : E} (atTop ×ˢ 𝓝 y) (𝓝 0) by simpa using A.add this apply Metric.tendsto_nhds.2 (fun ε εpos ↦ ?_) obtain ⟨r', yr', r'r⟩ : ∃ (r' : ℝ≥0), ‖y‖₊ < r' ∧ r' < r := by - simp [edist_eq_coe_nnnorm] at hy + simp [edist_zero_eq_enorm] at hy simpa using ENNReal.lt_iff_exists_nnreal_btwn.1 hy have yr'_2 : ‖y‖ < r' := by simpa [← coe_nnnorm] using yr' have S : Summable fun n ↦ ‖p n‖ * ↑r' ^ n := p.summable_norm_mul_pow (r'r.trans_le hf.r_le) @@ -991,7 +991,7 @@ theorem HasFPowerSeriesWithinOnBall.uniform_geometric_approx' {r' : ℝ≥0} have hr'0 : 0 < (r' : ℝ) := (norm_nonneg _).trans_lt yr' have : y ∈ EMetric.ball (0 : E) r := by refine mem_emetric_ball_zero_iff.2 (lt_trans ?_ h) - exact mod_cast yr' + simpa [enorm] using yr' rw [norm_sub_rev, ← mul_div_right_comm] have ya : a * (‖y‖ / ↑r') ≤ a := mul_le_of_le_one_right ha.1.le (div_le_one_of_le₀ yr'.le r'.coe_nonneg) @@ -1102,7 +1102,7 @@ theorem HasFPowerSeriesWithinOnBall.isBigO_image_sub_image_sub_deriv_principal zero_add, ← Subsingleton.pi_single_eq (0 : Fin 1) (y.1 - x), Pi.single, ← Subsingleton.pi_single_eq (0 : Fin 1) (y.2 - x), Pi.single, ← (p 1).map_update_sub, ← Pi.single, Subsingleton.pi_single_eq, sub_sub_sub_cancel_right] - rw [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, ENNReal.coe_lt_coe] at hy' + rw [EMetric.mem_ball, edist_eq_enorm_sub, enorm_lt_coe] at hy' set B : ℕ → ℝ := fun n => C * (a / r') ^ 2 * (‖y - (x, x)‖ * ‖y.1 - y.2‖) * ((n + 2) * a ^ n) have hAB : ∀ n, ‖A (n + 2)‖ ≤ B n := fun n => calc @@ -1282,7 +1282,7 @@ theorem HasFPowerSeriesWithinOnBall.tendstoLocallyUniformlyOn' · ext z simp · intro z - simp [edist_eq_coe_nnnorm, edist_eq_coe_nnnorm_sub] + simp [edist_zero_eq_enorm, edist_eq_enorm_sub] /-- If a function admits a power series expansion at `x`, then it is the locally uniform limit of the partial sums of this power series on the disk of convergence, i.e., `f y` diff --git a/Mathlib/Analysis/Analytic/CPolynomial.lean b/Mathlib/Analysis/Analytic/CPolynomial.lean index 8c2c58d2957d5..d41f5fdabed38 100644 --- a/Mathlib/Analysis/Analytic/CPolynomial.lean +++ b/Mathlib/Analysis/Analytic/CPolynomial.lean @@ -278,7 +278,7 @@ theorem HasFiniteFPowerSeriesOnBall.eq_partialSum' ∀ y ∈ EMetric.ball x r, ∀ m, n ≤ m → f y = p.partialSum m (y - x) := by intro y hy m hm - rw [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, ← mem_emetric_ball_zero_iff] at hy + rw [EMetric.mem_ball, edist_eq_enorm_sub, ← mem_emetric_ball_zero_iff] at hy rw [← (HasFiniteFPowerSeriesOnBall.eq_partialSum hf _ hy m hm), add_sub_cancel] /-! The particular cases where `f` has a finite power series bounded by `0` or `1`. -/ @@ -300,8 +300,8 @@ theorem HasFiniteFPowerSeriesOnBall.bound_zero_of_eq_zero (hf : ∀ y ∈ EMetri rw [hf (x + y)] · convert hasSum_zero rw [hp, ContinuousMultilinearMap.zero_apply] - · rwa [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, add_comm, add_sub_cancel_right, - ← edist_eq_coe_nnnorm, ← EMetric.mem_ball] + · rwa [EMetric.mem_ball, edist_eq_enorm_sub, add_comm, add_sub_cancel_right, + ← edist_zero_eq_enorm, ← EMetric.mem_ball] /-- If `f` has a formal power series at `x` bounded by `0`, then `f` is equal to `0` in a neighborhood of `x`. -/ @@ -504,8 +504,7 @@ theorem HasFiniteFPowerSeriesOnBall.changeOrigin (hf : HasFiniteFPowerSeriesOnBa FormalMultilinearSeries.sum (FormalMultilinearSeries.changeOrigin p y) z := by rw [mem_emetric_ball_zero_iff, lt_tsub_iff_right, add_comm] at hz rw [p.changeOrigin_eval_of_finite hf.finite, add_assoc, hf.sum] - refine mem_emetric_ball_zero_iff.2 (lt_of_le_of_lt ?_ hz) - exact mod_cast nnnorm_add_le y z + exact mem_emetric_ball_zero_iff.2 ((enorm_add_le _ _).trans_lt hz) rw [this] apply (p.changeOrigin y).hasSum_of_finite fun _ => p.changeOrigin_finite_of_finite hf.finite @@ -514,7 +513,7 @@ it is continuously polynomial at every point of this ball. -/ theorem HasFiniteFPowerSeriesOnBall.cPolynomialAt_of_mem (hf : HasFiniteFPowerSeriesOnBall f p x n r) (h : y ∈ EMetric.ball x r) : CPolynomialAt 𝕜 f y := by - have : (‖y - x‖₊ : ℝ≥0∞) < r := by simpa [edist_eq_coe_nnnorm_sub] using h + have : (‖y - x‖₊ : ℝ≥0∞) < r := by simpa [edist_eq_enorm_sub] using h have := hf.changeOrigin this rw [add_sub_cancel] at this exact this.cPolynomialAt diff --git a/Mathlib/Analysis/Analytic/ChangeOrigin.lean b/Mathlib/Analysis/Analytic/ChangeOrigin.lean index 0e2e48a529be8..a9dd1bdf95994 100644 --- a/Mathlib/Analysis/Analytic/ChangeOrigin.lean +++ b/Mathlib/Analysis/Analytic/ChangeOrigin.lean @@ -306,8 +306,8 @@ variable [CompleteSpace F] {f : E → F} {p : FormalMultilinearSeries 𝕜 E F} it also admits a power series on any subball of this ball (even with a different center provided it belongs to `s`), given by `p.changeOrigin`. -/ theorem HasFPowerSeriesWithinOnBall.changeOrigin (hf : HasFPowerSeriesWithinOnBall f p s x r) - (h : (‖y‖₊ : ℝ≥0∞) < r) (hy : x + y ∈ insert x s) : - HasFPowerSeriesWithinOnBall f (p.changeOrigin y) s (x + y) (r - ‖y‖₊) where + (h : ‖y‖ₑ < r) (hy : x + y ∈ insert x s) : + HasFPowerSeriesWithinOnBall f (p.changeOrigin y) s (x + y) (r - ‖y‖ₑ) where r_le := by apply le_trans _ p.changeOrigin_radius exact tsub_le_tsub hf.r_le le_rfl @@ -322,8 +322,7 @@ theorem HasFPowerSeriesWithinOnBall.changeOrigin (hf : HasFPowerSeriesWithinOnBa rw [insert_eq_of_mem hy] at this apply this simpa [add_assoc] using h'z - refine mem_emetric_ball_zero_iff.2 (lt_of_le_of_lt ?_ hz) - exact mod_cast nnnorm_add_le y z + exact mem_emetric_ball_zero_iff.2 (lt_of_le_of_lt (enorm_add_le _ _) hz) rw [this] apply (p.changeOrigin y).hasSum refine EMetric.ball_subset_ball (le_trans ?_ p.changeOrigin_radius) hz @@ -342,7 +341,7 @@ it is analytic at every point of this ball. -/ theorem HasFPowerSeriesWithinOnBall.analyticWithinAt_of_mem (hf : HasFPowerSeriesWithinOnBall f p s x r) (h : y ∈ insert x s ∩ EMetric.ball x r) : AnalyticWithinAt 𝕜 f s y := by - have : (‖y - x‖₊ : ℝ≥0∞) < r := by simpa [edist_eq_coe_nnnorm_sub] using h.2 + have : (‖y - x‖₊ : ℝ≥0∞) < r := by simpa [edist_eq_enorm_sub] using h.2 have := hf.changeOrigin this (by simpa using h.1) rw [add_sub_cancel] at this exact this.analyticWithinAt diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index ae4386b4831c7..6844e170f22e9 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -742,7 +742,7 @@ theorem HasFPowerSeriesWithinAt.comp {g : F → G} {f : E → F} {q : FormalMult apply hδ have : y ∈ EMetric.ball (0 : E) δ := (EMetric.ball_subset_ball (le_trans (min_le_left _ _) (min_le_right _ _))) hy - simpa [-Set.mem_insert_iff, edist_eq_coe_nnnorm_sub, h'y] + simpa [-Set.mem_insert_iff, edist_eq_enorm_sub, h'y] /- Now the proof starts. To show that the sum of `q.comp p` at `y` is `g (f (x + y))`, we will write `q.comp p` applied to `y` as a big sum over all compositions. Since the sum is summable, to get its convergence it suffices to get @@ -775,7 +775,7 @@ theorem HasFPowerSeriesWithinAt.comp {g : F → G} {f : E → F} {q : FormalMult have : Tendsto (fun (z : ℕ × F) ↦ q.partialSum z.1 z.2) (atTop ×ˢ 𝓝 (f (x + y) - f x)) (𝓝 (g (f x + (f (x + y) - f x)))) := by apply Hg.tendsto_partialSum_prod (y := f (x + y) - f x) - · simpa [edist_eq_coe_nnnorm_sub] using fy_mem.2 + · simpa [edist_eq_enorm_sub] using fy_mem.2 · simpa using fy_mem.1 simpa using this.comp A -- Third step: the sum over all compositions in `compPartialSumTarget 0 n n` converges to @@ -806,9 +806,9 @@ theorem HasFPowerSeriesWithinAt.comp {g : F → G} {f : E → F} {q : FormalMult apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) rw [Finset.prod_const, Finset.card_fin] gcongr - rw [EMetric.mem_ball, edist_eq_coe_nnnorm] at hy + rw [EMetric.mem_ball, edist_zero_eq_enorm] at hy have := le_trans (le_of_lt hy) (min_le_right _ _) - rwa [ENNReal.coe_le_coe, ← NNReal.coe_le_coe, coe_nnnorm] at this + rwa [enorm_le_coe, ← NNReal.coe_le_coe, coe_nnnorm] at this tendsto_nhds_of_cauchySeq_of_subseq cau compPartialSumTarget_tendsto_atTop C -- Fifth step: the sum over `n` of `q.comp p n` can be expressed as a particular resummation of -- the sum over all compositions, by grouping together the compositions of the same diff --git a/Mathlib/Analysis/Analytic/Inverse.lean b/Mathlib/Analysis/Analytic/Inverse.lean index 6ef7fff93cce3..bb9bba9211dc6 100644 --- a/Mathlib/Analysis/Analytic/Inverse.lean +++ b/Mathlib/Analysis/Analytic/Inverse.lean @@ -592,9 +592,9 @@ lemma HasFPowerSeriesAt.tendsto_partialSum_prod_of_comp apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) rw [Finset.prod_const, Finset.card_fin] gcongr - rw [EMetric.mem_ball, edist_eq_coe_nnnorm] at hy + rw [EMetric.mem_ball, edist_zero_eq_enorm] at hy have := le_trans (le_of_lt hy) (min_le_right _ _) - rwa [ENNReal.coe_le_coe, ← NNReal.coe_le_coe, coe_nnnorm] at this + rwa [enorm_le_coe, ← NNReal.coe_le_coe, coe_nnnorm] at this apply HasSum.of_sigma (fun b ↦ hasSum_fintype _) ?_ cau simpa [FormalMultilinearSeries.comp] using h0.hasSum hy0 have B : Tendsto (fun (n : ℕ × ℕ) => ∑ i ∈ compPartialSumTarget 0 n.1 n.2, @@ -686,7 +686,7 @@ theorem PartialHomeomorph.hasFPowerSeriesAt_symm (f : PartialHomeomorph E F) {a refine ⟨min r (p.leftInv i a).radius, min_le_right _ _, lt_min r_pos (radius_leftInv_pos_of_radius_pos h.radius_pos hp), fun {y} hy ↦ ?_⟩ have : y + f a ∈ EMetric.ball (f a) r := by - simp only [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, sub_zero, lt_min_iff, + simp only [EMetric.mem_ball, edist_eq_enorm_sub, sub_zero, lt_min_iff, add_sub_cancel_right] at hy ⊢ exact hy.1 simpa [add_comm] using hr this diff --git a/Mathlib/Analysis/Analytic/Uniqueness.lean b/Mathlib/Analysis/Analytic/Uniqueness.lean index 6c836c8afcab6..7bd05ac5c6aea 100644 --- a/Mathlib/Analysis/Analytic/Uniqueness.lean +++ b/Mathlib/Analysis/Analytic/Uniqueness.lean @@ -183,7 +183,7 @@ theorem eqOn_zero_of_preconnected_of_eventuallyEq_zero_aux [CompleteSpace F] {f EMetric.mem_closure_iff.1 xu (r / 2) (ENNReal.half_pos hp.r_pos.ne') let q := p.changeOrigin (y - x) have has_series : HasFPowerSeriesOnBall f q y (r / 2) := by - have A : (‖y - x‖₊ : ℝ≥0∞) < r / 2 := by rwa [edist_comm, edist_eq_coe_nnnorm_sub] at hxy + have A : (‖y - x‖₊ : ℝ≥0∞) < r / 2 := by rwa [edist_comm, edist_eq_enorm_sub] at hxy have := hp.changeOrigin (A.trans_le ENNReal.half_le_self) simp only [add_sub_cancel] at this apply this.mono (ENNReal.half_pos hp.r_pos.ne') diff --git a/Mathlib/Analysis/Analytic/Within.lean b/Mathlib/Analysis/Analytic/Within.lean index fd9bd854f032d..9ffa3528476c8 100644 --- a/Mathlib/Analysis/Analytic/Within.lean +++ b/Mathlib/Analysis/Analytic/Within.lean @@ -124,14 +124,14 @@ lemma hasFPowerSeriesWithinOnBall_iff_exists_hasFPowerSeriesOnBall [CompleteSpac · intro h refine ⟨fun y ↦ p.sum (y - x), ?_, ?_⟩ · intro y ⟨ys,yb⟩ - simp only [EMetric.mem_ball, edist_eq_coe_nnnorm_sub] at yb + simp only [EMetric.mem_ball, edist_eq_enorm_sub] at yb have e0 := p.hasSum (x := y - x) ?_ have e1 := (h.hasSum (y := y - x) ?_ ?_) · simp only [add_sub_cancel] at e1 exact e1.unique e0 · simpa only [add_sub_cancel] - · simpa only [EMetric.mem_ball, edist_eq_coe_nnnorm] - · simp only [EMetric.mem_ball, edist_eq_coe_nnnorm] + · simpa only [EMetric.mem_ball, edist_zero_eq_enorm] + · simp only [EMetric.mem_ball, edist_zero_eq_enorm] exact lt_of_lt_of_le yb h.r_le · refine ⟨h.r_le, h.r_pos, ?_⟩ intro y lt @@ -145,7 +145,7 @@ lemma hasFPowerSeriesWithinOnBall_iff_exists_hasFPowerSeriesOnBall [CompleteSpac rw [hfg] · exact hg.hasSum lt · refine ⟨ys, ?_⟩ - simpa only [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, add_sub_cancel_left, sub_zero] using lt + simpa only [EMetric.mem_ball, edist_eq_enorm_sub, add_sub_cancel_left, sub_zero] using lt /-- `f` has power series `p` at `x` iff some local extension of `f` has that series -/ lemma hasFPowerSeriesWithinAt_iff_exists_hasFPowerSeriesAt [CompleteSpace F] {f : E → F} diff --git a/Mathlib/Analysis/BoxIntegral/Integrability.lean b/Mathlib/Analysis/BoxIntegral/Integrability.lean index a8a89c7794886..695710a0bc222 100644 --- a/Mathlib/Analysis/BoxIntegral/Integrability.lean +++ b/Mathlib/Analysis/BoxIntegral/Integrability.lean @@ -223,7 +223,7 @@ theorem IntegrableOn.hasBoxIntegral [CompleteSpace E] {f : (ι → ℝ) → E} { -- Choose `N` such that the integral of `‖f N x - g x‖` is less than or equal to `ε`. obtain ⟨N₀, hN₀⟩ : ∃ N : ℕ, ∫ x in I, ‖f N x - g x‖ ∂μ ≤ ε := by have : Tendsto (fun n => ∫⁻ x in I, ‖f n x - g x‖₊ ∂μ) atTop (𝓝 0) := - SimpleFunc.tendsto_approxOn_range_L1_nnnorm hg.measurable hgi + SimpleFunc.tendsto_approxOn_range_L1_enorm hg.measurable hgi refine (this.eventually (ge_mem_nhds ε0')).exists.imp fun N hN => ?_ exact integral_coe_le_of_lintegral_coe_le hN -- For each `x`, we choose `Nx x ≥ N₀` such that `dist (f Nx x) (g x) ≤ ε`. diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index 09a1501984d89..00cea385a3f4a 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -205,7 +205,7 @@ protected theorem HasFPowerSeriesOnBall.fderiv [CompleteSpace F] (h.r_pos.trans_le h.r_le)).mono h.r_pos h.r_le).comp_sub x dsimp only rw [← h.fderiv_eq, add_sub_cancel] - simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz + simpa only [edist_eq_enorm_sub, EMetric.mem_ball] using hz /-- If a function has a power series within a set on a ball, then so does its derivative. -/ protected theorem HasFPowerSeriesWithinOnBall.fderivWithin [CompleteSpace F] @@ -220,7 +220,7 @@ protected theorem HasFPowerSeriesWithinOnBall.fderivWithin [CompleteSpace F] (h.r_pos.trans_le h.r_le)).mono h.r_pos h.r_le).comp_sub x · dsimp only rw [← h.fderivWithin_eq _ _ hu, add_sub_cancel] - · simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz.2 + · simpa only [edist_eq_enorm_sub, EMetric.mem_ball] using hz.2 · simpa using hz.1 /-- If a function has a power series within a set on a ball, then so does its derivative. For a @@ -315,7 +315,7 @@ theorem HasFPowerSeriesWithinOnBall.hasSum_derivSeries_of_hasFDerivWithinAt rw [← b.isEmbedding.hasSum_iff] have : HasFPowerSeriesWithinOnBall (a ∘ f) (a.compFormalMultilinearSeries p) s x r := a.comp_hasFPowerSeriesWithinOnBall h - have Z := (this.fderivWithin hu).hasSum h'y (by simpa [edist_eq_coe_nnnorm] using hy) + have Z := (this.fderivWithin hu).hasSum h'y (by simpa [edist_zero_eq_enorm] using hy) have : fderivWithin 𝕜 (a ∘ f) (insert x s) (x + y) = a ∘L f' := by apply HasFDerivWithinAt.fderivWithin _ (hu _ h'y) exact a.hasFDerivAt.comp_hasFDerivWithinAt (x + y) hf' @@ -339,7 +339,7 @@ protected theorem HasFPowerSeriesWithinOnBall.fderivWithin_of_mem_of_analyticOn (h : AnalyticOn 𝕜 f s) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) : HasFPowerSeriesWithinOnBall (fderivWithin 𝕜 f s) p.derivSeries s x r := by refine ⟨hr.r_le.trans p.radius_le_radius_derivSeries, hr.r_pos, fun {y} hy h'y ↦ ?_⟩ - apply hr.hasSum_derivSeries_of_hasFDerivWithinAt (by simpa [edist_eq_coe_nnnorm] using h'y) hy + apply hr.hasSum_derivSeries_of_hasFDerivWithinAt (by simpa [edist_zero_eq_enorm] using h'y) hy · rw [insert_eq_of_mem hx] at hy ⊢ apply DifferentiableWithinAt.hasFDerivWithinAt exact h.differentiableOn _ hy @@ -489,7 +489,7 @@ protected theorem HasFiniteFPowerSeriesOnBall.fderiv ((p.hasFiniteFPowerSeriesOnBall_changeOrigin 1 h.finite).mono h.r_pos le_top).comp_sub x dsimp only rw [← h.fderiv_eq, add_sub_cancel] - simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz + simpa only [edist_eq_enorm_sub, EMetric.mem_ball] using hz /-- If a function has a finite power series on a ball, then so does its derivative. This is a variant of `HasFiniteFPowerSeriesOnBall.fderiv` where the degree of `f` is `< n` diff --git a/Mathlib/Analysis/Complex/CauchyIntegral.lean b/Mathlib/Analysis/Complex/CauchyIntegral.lean index 68eaaa612c9ce..41557430b9bf3 100644 --- a/Mathlib/Analysis/Complex/CauchyIntegral.lean +++ b/Mathlib/Analysis/Complex/CauchyIntegral.lean @@ -536,7 +536,7 @@ theorem hasFPowerSeriesOnBall_of_differentiable_off_countable {R : ℝ≥0} {c : hasSum := fun {w} hw => by have hw' : c + w ∈ ball c R := by simpa only [add_mem_ball_iff_norm, ← coe_nnnorm, mem_emetric_ball_zero_iff, - NNReal.coe_lt_coe, ENNReal.coe_lt_coe] using hw + NNReal.coe_lt_coe, enorm_lt_coe] using hw rw [← two_pi_I_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable hs hw' hc hd] exact (hasFPowerSeriesOn_cauchy_integral diff --git a/Mathlib/Analysis/Convex/EGauge.lean b/Mathlib/Analysis/Convex/EGauge.lean index 3680e97a36527..6e85fb9180274 100644 --- a/Mathlib/Analysis/Convex/EGauge.lean +++ b/Mathlib/Analysis/Convex/EGauge.lean @@ -32,15 +32,15 @@ section SMul /-- The Minkowski functional for vector spaces over normed fields. Given a set `s` in a vector space over a normed field `𝕜`, `egauge s` is the functional which sends `x : E` -to the infimum of `‖c‖₊` over `c` such that `x` belongs to `s` scaled by `c`. +to the infimum of `‖c‖ₑ` over `c` such that `x` belongs to `s` scaled by `c`. -The definition only requires `𝕜` to have a `NNNorm` instance +The definition only requires `𝕜` to have a `ENorm` instance and `(· • ·) : 𝕜 → E → E` to be defined. This way the definition applies, e.g., to `𝕜 = ℝ≥0`. For `𝕜 = ℝ≥0`, the function is equal (up to conversion to `ℝ`) to the usual Minkowski functional defined in `gauge`. -/ -noncomputable def egauge (𝕜 : Type*) [NNNorm 𝕜] {E : Type*} [SMul 𝕜 E] (s : Set E) (x : E) : ℝ≥0∞ := - ⨅ (c : 𝕜) (_ : x ∈ c • s), ‖c‖₊ +noncomputable def egauge (𝕜 : Type*) [ENorm 𝕜] {E : Type*} [SMul 𝕜 E] (s : Set E) (x : E) : ℝ≥0∞ := + ⨅ (c : 𝕜) (_ : x ∈ c • s), ‖c‖ₑ variable (𝕜 : Type*) [NNNorm 𝕜] {E : Type*} [SMul 𝕜 E] {c : 𝕜} {s t : Set E} {x : E} {r : ℝ≥0∞} @@ -52,13 +52,13 @@ lemma egauge_anti (h : s ⊆ t) (x : E) : egauge 𝕜 t x ≤ egauge 𝕜 s x := variable {𝕜} -lemma egauge_le_of_mem_smul (h : x ∈ c • s) : egauge 𝕜 s x ≤ ‖c‖₊ := iInf₂_le c h +lemma egauge_le_of_mem_smul (h : x ∈ c • s) : egauge 𝕜 s x ≤ ‖c‖ₑ := iInf₂_le c h -lemma le_egauge_iff : r ≤ egauge 𝕜 s x ↔ ∀ c : 𝕜, x ∈ c • s → r ≤ ‖c‖₊ := le_iInf₂_iff +lemma le_egauge_iff : r ≤ egauge 𝕜 s x ↔ ∀ c : 𝕜, x ∈ c • s → r ≤ ‖c‖ₑ := le_iInf₂_iff lemma egauge_eq_top : egauge 𝕜 s x = ∞ ↔ ∀ c : 𝕜, x ∉ c • s := by simp [egauge] -lemma egauge_lt_iff : egauge 𝕜 s x < r ↔ ∃ c : 𝕜, x ∈ c • s ∧ ‖c‖₊ < r := by +lemma egauge_lt_iff : egauge 𝕜 s x < r ↔ ∃ c : 𝕜, x ∈ c • s ∧ ‖c‖ₑ < r := by simp [egauge, iInf_lt_iff] lemma egauge_union (s t : Set E) (x : E) : egauge 𝕜 (s ∪ t) x = egauge 𝕜 s x ⊓ egauge 𝕜 t x := by @@ -87,25 +87,24 @@ section Module variable {𝕜 : Type*} [NormedDivisionRing 𝕜] {E : Type*} [AddCommGroup E] [Module 𝕜 E] {c : 𝕜} {s : Set E} {x : E} -/-- If `c • x ∈ s` and `c ≠ 0`, then `egauge 𝕜 s x` is at most `((‖c‖₊⁻¹ : ℝ≥0) : ℝ≥0∞). +/-- If `c • x ∈ s` and `c ≠ 0`, then `egauge 𝕜 s x` is at most `(‖c‖₊⁻¹ : ℝ≥0)`. See also `egauge_le_of_smul_mem`. -/ -lemma egauge_le_of_smul_mem_of_ne (h : c • x ∈ s) (hc : c ≠ 0) : - egauge 𝕜 s x ≤ ↑(‖c‖₊⁻¹ : ℝ≥0) := by +lemma egauge_le_of_smul_mem_of_ne (h : c • x ∈ s) (hc : c ≠ 0) : egauge 𝕜 s x ≤ (‖c‖₊⁻¹ : ℝ≥0) := by rw [← nnnorm_inv] exact egauge_le_of_mem_smul <| (mem_inv_smul_set_iff₀ hc _ _).2 h -/-- If `c • x ∈ s`, then `egauge 𝕜 s x` is at most `(‖c‖₊ : ℝ≥0∞)⁻¹. +/-- If `c • x ∈ s`, then `egauge 𝕜 s x` is at most `‖c‖ₑ⁻¹`. See also `egauge_le_of_smul_mem_of_ne`. -/ -lemma egauge_le_of_smul_mem (h : c • x ∈ s) : egauge 𝕜 s x ≤ (‖c‖₊ : ℝ≥0∞)⁻¹ := by +lemma egauge_le_of_smul_mem (h : c • x ∈ s) : egauge 𝕜 s x ≤ ‖c‖ₑ⁻¹ := by rcases eq_or_ne c 0 with rfl | hc · simp · exact (egauge_le_of_smul_mem_of_ne h hc).trans ENNReal.coe_inv_le lemma mem_of_egauge_lt_one (hs : Balanced 𝕜 s) (hx : egauge 𝕜 s x < 1) : x ∈ s := let ⟨c, hxc, hc⟩ := egauge_lt_iff.1 hx - hs c (mod_cast hc.le) hxc + hs c (by simpa [enorm] using hc.le) hxc lemma egauge_eq_zero_iff : egauge 𝕜 s x = 0 ↔ ∃ᶠ c : 𝕜 in 𝓝 0, x ∈ c • s := by refine (iInf₂_eq_bot _).trans ?_ @@ -128,25 +127,25 @@ lemma egauge_le_one (h : x ∈ s) : egauge 𝕜 s x ≤ 1 := by variable {𝕜} lemma le_egauge_smul_left (c : 𝕜) (s : Set E) (x : E) : - egauge 𝕜 s x / ‖c‖₊ ≤ egauge 𝕜 (c • s) x := by + egauge 𝕜 s x / ‖c‖ₑ ≤ egauge 𝕜 (c • s) x := by simp_rw [le_egauge_iff, smul_smul] rintro a ⟨x, hx, rfl⟩ apply ENNReal.div_le_of_le_mul - rw [← ENNReal.coe_mul, ← nnnorm_mul] + rw [← enorm_mul] exact egauge_le_of_mem_smul <| smul_mem_smul_set hx lemma egauge_smul_left (hc : c ≠ 0) (s : Set E) (x : E) : - egauge 𝕜 (c • s) x = egauge 𝕜 s x / ‖c‖₊ := by + egauge 𝕜 (c • s) x = egauge 𝕜 s x / ‖c‖ₑ := by refine le_antisymm ?_ (le_egauge_smul_left _ _ _) rw [ENNReal.le_div_iff_mul_le (by simp [*]) (by simp)] calc - egauge 𝕜 (c • s) x * ‖c‖₊ = egauge 𝕜 (c • s) x / ‖c⁻¹‖₊ := by - rw [nnnorm_inv, ENNReal.coe_inv (by simpa), div_eq_mul_inv, inv_inv] + egauge 𝕜 (c • s) x * ‖c‖ₑ = egauge 𝕜 (c • s) x / ‖c⁻¹‖ₑ := by + rw [enorm_inv (by simpa), div_eq_mul_inv, inv_inv] _ ≤ egauge 𝕜 (c⁻¹ • c • s) x := le_egauge_smul_left _ _ _ _ = egauge 𝕜 s x := by rw [inv_smul_smul₀ hc] lemma le_egauge_smul_right (c : 𝕜) (s : Set E) (x : E) : - ‖c‖₊ * egauge 𝕜 s x ≤ egauge 𝕜 s (c • x) := by + ‖c‖ₑ * egauge 𝕜 s x ≤ egauge 𝕜 s (c • x) := by rw [le_egauge_iff] rintro a ⟨y, hy, hxy⟩ rcases eq_or_ne c 0 with rfl | hc @@ -157,12 +156,12 @@ lemma le_egauge_smul_right (c : 𝕜) (s : Set E) (x : E) : simp only [mul_smul, hxy, inv_smul_smul₀ hc] lemma egauge_smul_right (h : c = 0 → s.Nonempty) (x : E) : - egauge 𝕜 s (c • x) = ‖c‖₊ * egauge 𝕜 s x := by + egauge 𝕜 s (c • x) = ‖c‖ₑ * egauge 𝕜 s x := by refine le_antisymm ?_ (le_egauge_smul_right c s x) rcases eq_or_ne c 0 with rfl | hc · simp [egauge_zero_right _ (h rfl)] - · rw [mul_comm, ← ENNReal.div_le_iff_le_mul (.inl <| by simpa) (.inl ENNReal.coe_ne_top), - ENNReal.div_eq_inv_mul, ← ENNReal.coe_inv (by simpa), ← nnnorm_inv] + · rw [mul_comm, ← ENNReal.div_le_iff_le_mul (.inl <| by simpa) (.inl enorm_ne_top), + ENNReal.div_eq_inv_mul, ← enorm_inv (by simpa)] refine (le_egauge_smul_right _ _ _).trans_eq ?_ rw [inv_smul_smul₀ hc] @@ -189,36 +188,37 @@ section SeminormedAddCommGroup variable (𝕜 : Type*) [NormedField 𝕜] {E : Type*} [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] -lemma div_le_egauge_closedBall (r : ℝ≥0) (x : E) : ‖x‖₊ / r ≤ egauge 𝕜 (closedBall 0 r) x := by +lemma div_le_egauge_closedBall (r : ℝ≥0) (x : E) : ‖x‖ₑ / r ≤ egauge 𝕜 (closedBall 0 r) x := by rw [le_egauge_iff] rintro c ⟨y, hy, rfl⟩ rw [mem_closedBall_zero_iff, ← coe_nnnorm, NNReal.coe_le_coe] at hy - simp only [nnnorm_smul, ENNReal.coe_mul] + rw [enorm_smul] apply ENNReal.div_le_of_le_mul gcongr + rwa [enorm_le_coe] -lemma le_egauge_closedBall_one (x : E) : ‖x‖₊ ≤ egauge 𝕜 (closedBall 0 1) x := by +lemma le_egauge_closedBall_one (x : E) : ‖x‖ₑ ≤ egauge 𝕜 (closedBall 0 1) x := by simpa using div_le_egauge_closedBall 𝕜 1 x -lemma div_le_egauge_ball (r : ℝ≥0) (x : E) : ‖x‖₊ / r ≤ egauge 𝕜 (ball 0 r) x := +lemma div_le_egauge_ball (r : ℝ≥0) (x : E) : ‖x‖ₑ / r ≤ egauge 𝕜 (ball 0 r) x := (div_le_egauge_closedBall 𝕜 r x).trans <| egauge_anti _ ball_subset_closedBall _ -lemma le_egauge_ball_one (x : E) : ‖x‖₊ ≤ egauge 𝕜 (ball 0 1) x := by +lemma le_egauge_ball_one (x : E) : ‖x‖ₑ ≤ egauge 𝕜 (ball 0 1) x := by simpa using div_le_egauge_ball 𝕜 1 x variable {𝕜} variable {c : 𝕜} {x : E} {r : ℝ≥0} lemma egauge_ball_le_of_one_lt_norm (hc : 1 < ‖c‖) (h₀ : r ≠ 0 ∨ ‖x‖ ≠ 0) : - egauge 𝕜 (ball 0 r) x ≤ ‖c‖₊ * ‖x‖₊ / r := by + egauge 𝕜 (ball 0 r) x ≤ ‖c‖ₑ * ‖x‖ₑ / r := by letI : NontriviallyNormedField 𝕜 := ⟨c, hc⟩ rcases (zero_le r).eq_or_lt with rfl | hr · rw [ENNReal.coe_zero, ENNReal.div_zero (mul_ne_zero _ _)] · apply le_top · simpa using one_pos.trans hc - · simpa [← NNReal.coe_eq_zero] using h₀ + · simpa [enorm, ← NNReal.coe_eq_zero] using h₀ · rcases eq_or_ne ‖x‖ 0 with hx | hx - · have hx' : ‖x‖₊ = 0 := by rwa [← coe_nnnorm, NNReal.coe_eq_zero] at hx + · have hx' : ‖x‖ₑ = 0 := by simpa [enorm, ← coe_nnnorm, NNReal.coe_eq_zero] using hx simp [egauge_eq_zero_iff, hx'] refine (frequently_iff_neBot.2 (inferInstance : NeBot (𝓝[≠] (0 : 𝕜)))).mono fun c hc ↦ ?_ simp [mem_smul_set_iff_inv_smul_mem₀ hc, norm_smul, hx, hr] @@ -227,10 +227,10 @@ lemma egauge_ball_le_of_one_lt_norm (hc : 1 < ‖c‖) (h₀ : r ≠ 0 ∨ ‖x egauge 𝕜 (ball 0 r) x ≤ ↑(‖a‖₊⁻¹) := egauge_le_of_smul_mem_of_ne (mem_ball_zero_iff.2 har) ha₀ _ ≤ ↑(‖c‖₊ * ‖x‖₊ / r) := by rwa [ENNReal.coe_le_coe, div_eq_inv_mul, ← mul_assoc] - _ ≤ ‖c‖₊ * ‖x‖₊ / r := ENNReal.coe_div_le.trans <| by rw [ENNReal.coe_mul] + _ ≤ ‖c‖ₑ * ‖x‖ₑ / r := ENNReal.coe_div_le.trans <| by simp [ENNReal.coe_mul, enorm] lemma egauge_ball_one_le_of_one_lt_norm (hc : 1 < ‖c‖) (x : E) : - egauge 𝕜 (ball 0 1) x ≤ ‖c‖₊ * ‖x‖₊ := by + egauge 𝕜 (ball 0 1) x ≤ ‖c‖ₑ * ‖x‖ₑ := by simpa using egauge_ball_le_of_one_lt_norm hc (.inl one_ne_zero) end SeminormedAddCommGroup diff --git a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean index 616027a97b9a7..df47835cf9bfe 100644 --- a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean +++ b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean @@ -300,7 +300,7 @@ theorem lintegral_pow_le_pow_lintegral_fderiv_aux [Fintype ι] {p : ℝ} (hp : Real.IsConjExponent #ι p) {u : (ι → ℝ) → F} (hu : ContDiff ℝ 1 u) (h2u : HasCompactSupport u) : - ∫⁻ x, (‖u x‖₊ : ℝ≥0∞) ^ p ≤ (∫⁻ x, ‖fderiv ℝ u x‖₊) ^ p := by + ∫⁻ x, ‖u x‖ₑ ^ p ≤ (∫⁻ x, ‖fderiv ℝ u x‖ₑ) ^ p := by classical /- For a function `f` in one variable and `t ∈ ℝ` we have `|f(t)| = `|∫_{-∞}^t Df(s)∂s| ≤ ∫_ℝ |Df(s)| ∂s` where we use the fundamental theorem of calculus. @@ -311,43 +311,41 @@ theorem lintegral_pow_le_pow_lintegral_fderiv_aux [Fintype ι] have : (1 : ℝ) ≤ ↑#ι - 1 := by have hι : (2 : ℝ) ≤ #ι := by exact_mod_cast hp.one_lt linarith - calc ∫⁻ x, (‖u x‖₊ : ℝ≥0∞) ^ p - = ∫⁻ x, ((‖u x‖₊ : ℝ≥0∞) ^ (1 / (#ι - 1 : ℝ))) ^ (#ι : ℝ) := by + calc ∫⁻ x, ‖u x‖ₑ ^ p + = ∫⁻ x, (‖u x‖ₑ ^ (1 / (#ι - 1 : ℝ))) ^ (#ι : ℝ) := by -- a little algebraic manipulation of the exponent congr! 2 with x rw [← ENNReal.rpow_mul, hp.conj_eq] field_simp - _ = ∫⁻ x, ∏ _i : ι, (‖u x‖₊ : ℝ≥0∞) ^ (1 / (#ι - 1 : ℝ)) := by + _ = ∫⁻ x, ∏ _i : ι, ‖u x‖ₑ ^ (1 / (#ι - 1 : ℝ)) := by -- express the left-hand integrand as a product of identical factors congr! 2 with x simp_rw [prod_const, card_univ] norm_cast - _ ≤ ∫⁻ x, ∏ i, (∫⁻ xᵢ, ‖fderiv ℝ u (update x i xᵢ)‖₊) ^ ((1 : ℝ) / (#ι - 1 : ℝ)) := ?_ - _ ≤ (∫⁻ x, ‖fderiv ℝ u x‖₊) ^ p := by + _ ≤ ∫⁻ x, ∏ i, (∫⁻ xᵢ, ‖fderiv ℝ u (update x i xᵢ)‖ₑ) ^ ((1 : ℝ) / (#ι - 1 : ℝ)) := ?_ + _ ≤ (∫⁻ x, ‖fderiv ℝ u x‖ₑ) ^ p := by -- apply the grid-lines lemma apply lintegral_prod_lintegral_pow_le _ hp have : Continuous (fderiv ℝ u) := hu.continuous_fderiv le_rfl fun_prop -- we estimate |u x| using the fundamental theorem of calculus. gcongr with x i - calc (‖u x‖₊ : ℝ≥0∞) - _ ≤ ∫⁻ xᵢ in Iic (x i), ‖deriv (u ∘ update x i) xᵢ‖₊ := by - apply le_trans (by simp) (HasCompactSupport.ennnorm_le_lintegral_Ici_deriv _ _ _) + calc ‖u x‖ₑ + _ ≤ ∫⁻ xᵢ in Iic (x i), ‖deriv (u ∘ update x i) xᵢ‖ₑ := by + apply le_trans (by simp) (HasCompactSupport.enorm_le_lintegral_Ici_deriv _ _ _) · exact hu.comp (by convert contDiff_update 1 x i) · exact h2u.comp_isClosedEmbedding (isClosedEmbedding_update x i) - _ ≤ ∫⁻ xᵢ, (‖fderiv ℝ u (update x i xᵢ)‖₊ : ℝ≥0∞) := ?_ + _ ≤ ∫⁻ xᵢ, ‖fderiv ℝ u (update x i xᵢ)‖ₑ := ?_ gcongr · exact Measure.restrict_le_self intro y dsimp - gcongr -- bound the derivative which appears - calc ‖deriv (u ∘ update x i) y‖₊ = ‖fderiv ℝ u (update x i y) (deriv (update x i) y)‖₊ := by + calc ‖deriv (u ∘ update x i) y‖ₑ = ‖fderiv ℝ u (update x i y) (deriv (update x i) y)‖ₑ := by rw [fderiv_comp_deriv _ (hu.differentiable le_rfl).differentiableAt (hasDerivAt_update x i y).differentiableAt] - _ ≤ ‖fderiv ℝ u (update x i y)‖₊ * ‖deriv (update x i) y‖₊ := - ContinuousLinearMap.le_opNNNorm .. - _ ≤ ‖fderiv ℝ u (update x i y)‖₊ := by simp [deriv_update, Pi.nnnorm_single] + _ ≤ ‖fderiv ℝ u (update x i y)‖ₑ * ‖deriv (update x i) y‖ₑ := ContinuousLinearMap.le_opENorm _ _ + _ ≤ ‖fderiv ℝ u (update x i y)‖ₑ := by simp [deriv_update, Pi.enorm_single] variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [MeasurableSpace E] [BorelSpace E] [FiniteDimensional ℝ E] (μ : Measure E) [IsAddHaarMeasure μ] @@ -374,8 +372,8 @@ Lebesgue integral of the Fréchet derivative of `u`. -/ theorem lintegral_pow_le_pow_lintegral_fderiv {u : E → F} (hu : ContDiff ℝ 1 u) (h2u : HasCompactSupport u) {p : ℝ} (hp : Real.IsConjExponent (finrank ℝ E) p) : - ∫⁻ x, (‖u x‖₊ : ℝ≥0∞) ^ p ∂μ ≤ - lintegralPowLePowLIntegralFDerivConst μ p * (∫⁻ x, ‖fderiv ℝ u x‖₊ ∂μ) ^ p := by + ∫⁻ x, ‖u x‖ₑ ^ p ∂μ ≤ + lintegralPowLePowLIntegralFDerivConst μ p * (∫⁻ x, ‖fderiv ℝ u x‖ₑ ∂μ) ^ p := by /- We reduce to the case where `E` is `ℝⁿ`, for which we have already proved the result using an explicit basis in `MeasureTheory.lintegral_pow_le_pow_lintegral_fderiv_aux`. This proof is not too hard, but takes quite some steps, reasoning about the equivalence @@ -403,30 +401,28 @@ theorem lintegral_pow_le_pow_lintegral_fderiv {u : E → F} have hv : ContDiff ℝ 1 v := hu.comp e.symm.contDiff have h2v : HasCompactSupport v := h2u.comp_homeomorph e.symm.toHomeomorph have := - calc ∫⁻ x, (‖u x‖₊ : ℝ≥0∞) ^ p ∂(volume : Measure (ι → ℝ)).map e.symm - = ∫⁻ y, (‖v y‖₊ : ℝ≥0∞) ^ p := by + calc ∫⁻ x, ‖u x‖ₑ ^ p ∂(volume : Measure (ι → ℝ)).map e.symm + = ∫⁻ y, ‖v y‖ₑ ^ p := by refine lintegral_map ?_ e.symm.continuous.measurable borelize F exact hu.continuous.measurable.nnnorm.coe_nnreal_ennreal.pow_const _ - _ ≤ (∫⁻ y, ‖fderiv ℝ v y‖₊) ^ p := - lintegral_pow_le_pow_lintegral_fderiv_aux hp hv h2v - _ = (∫⁻ y, ‖(fderiv ℝ u (e.symm y)).comp (fderiv ℝ e.symm y)‖₊) ^ p := by + _ ≤ (∫⁻ y, ‖fderiv ℝ v y‖ₑ) ^ p := lintegral_pow_le_pow_lintegral_fderiv_aux hp hv h2v + _ = (∫⁻ y, ‖(fderiv ℝ u (e.symm y)).comp (fderiv ℝ e.symm y)‖ₑ) ^ p := by congr! with y apply fderiv_comp _ (hu.differentiable le_rfl _) exact e.symm.differentiableAt - _ ≤ (∫⁻ y, ‖fderiv ℝ u (e.symm y)‖₊ * ‖(e.symm : (ι → ℝ) →L[ℝ] E)‖₊) ^ p := by + _ ≤ (∫⁻ y, ‖fderiv ℝ u (e.symm y)‖ₑ * ‖(e.symm : (ι → ℝ) →L[ℝ] E)‖ₑ) ^ p := by gcongr with y - norm_cast rw [e.symm.fderiv] - apply ContinuousLinearMap.opNNNorm_comp_le - _ = (‖(e.symm : (ι → ℝ) →L[ℝ] E)‖₊ * ∫⁻ y, ‖fderiv ℝ u (e.symm y)‖₊) ^ p := by + apply ContinuousLinearMap.opENorm_comp_le + _ = (‖(e.symm : (ι → ℝ) →L[ℝ] E)‖ₑ * ∫⁻ y, ‖fderiv ℝ u (e.symm y)‖ₑ) ^ p := by rw [lintegral_mul_const, mul_comm] refine (Continuous.nnnorm ?_).measurable.coe_nnreal_ennreal exact (hu.continuous_fderiv le_rfl).comp e.symm.continuous - _ = (‖(e.symm : (ι → ℝ) →L[ℝ] E)‖₊ ^ p : ℝ≥0) * (∫⁻ y, ‖fderiv ℝ u (e.symm y)‖₊) ^ p := by - rw [ENNReal.mul_rpow_of_nonneg _ _ h0p, ← ENNReal.coe_rpow_of_nonneg _ h0p] + _ = (‖(e.symm : (ι → ℝ) →L[ℝ] E)‖₊ ^ p : ℝ≥0) * (∫⁻ y, ‖fderiv ℝ u (e.symm y)‖ₑ) ^ p := by + rw [ENNReal.mul_rpow_of_nonneg _ _ h0p, enorm_eq_nnnorm, ← ENNReal.coe_rpow_of_nonneg _ h0p] _ = (‖(e.symm : (ι → ℝ) →L[ℝ] E)‖₊ ^ p : ℝ≥0) - * (∫⁻ x, ‖fderiv ℝ u x‖₊ ∂(volume : Measure (ι → ℝ)).map e.symm) ^ p := by + * (∫⁻ x, ‖fderiv ℝ u x‖ₑ ∂(volume : Measure (ι → ℝ)).map e.symm) ^ p := by congr rw [lintegral_map _ e.symm.continuous.measurable] have : Continuous (fderiv ℝ u) := hu.continuous_fderiv le_rfl @@ -449,7 +445,7 @@ theorem eLpNorm_le_eLpNorm_fderiv_one {u : E → F} (hu : ContDiff ℝ 1 u) (h2 {p : ℝ≥0} (hp : NNReal.IsConjExponent (finrank ℝ E) p) : eLpNorm u p μ ≤ eLpNormLESNormFDerivOneConst μ p * eLpNorm (fderiv ℝ u) 1 μ := by have h0p : 0 < (p : ℝ) := hp.coe.symm.pos - rw [eLpNorm_one_eq_lintegral_nnnorm, + rw [eLpNorm_one_eq_lintegral_enorm, ← ENNReal.rpow_le_rpow_iff h0p, ENNReal.mul_rpow_of_nonneg _ _ h0p.le, ← ENNReal.coe_rpow_of_nonneg _ h0p.le, eLpNormLESNormFDerivOneConst, ← NNReal.rpow_mul, eLpNorm_nnreal_pow_eq_lintegral hp.symm.pos.ne', @@ -535,16 +531,16 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_eq_inner {u : E → F'} have : (p : ℝ) * (n - 1) - (n - p) = n * (p - 1) := by ring field_simp [this]; ring have h4γ : (γ : ℝ) ≠ 0 := (zero_lt_one.trans h1γ).ne' - by_cases h3u : ∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ = 0 + by_cases h3u : ∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ = 0 · rw [eLpNorm_nnreal_eq_lintegral h0p', h3u, ENNReal.zero_rpow_of_pos] <;> positivity - have h4u : ∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ ≠ ∞ := by - refine lintegral_rpow_nnnorm_lt_top_of_eLpNorm'_lt_top + have h4u : ∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ ≠ ∞ := by + refine lintegral_rpow_enorm_lt_top_of_eLpNorm'_lt_top ((NNReal.coe_pos.trans pos_iff_ne_zero).mpr h0p') ?_ |>.ne rw [← eLpNorm_nnreal_eq_eLpNorm' h0p'] exact hu.continuous.memℒp_of_hasCompactSupport (μ := μ) h2u |>.eLpNorm_lt_top - have h5u : (∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ) ^ (1 / q) ≠ 0 := + have h5u : (∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ) ^ (1 / q) ≠ 0 := ENNReal.rpow_pos (pos_iff_ne_zero.mpr h3u) h4u |>.ne' - have h6u : (∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ) ^ (1 / q) ≠ ∞ := + have h6u : (∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ) ^ (1 / q) ≠ ∞ := ENNReal.rpow_ne_top_of_nonneg (div_nonneg zero_le_one hq.symm.nonneg) h4u have h7u := hu.continuous -- for fun_prop have h8u := (hu.fderiv_right (m := 0) le_rfl).continuous -- for fun_prop @@ -553,20 +549,21 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_eq_inner {u : E → F'} have h2v : HasCompactSupport v := h2u.norm.rpow_const h4γ set C := eLpNormLESNormFDerivOneConst μ n' have := - calc (∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ) ^ (1 / (n' : ℝ)) = eLpNorm v n' μ := by + calc (∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ) ^ (1 / (n' : ℝ)) = eLpNorm v n' μ := by rw [← h2γ, eLpNorm_nnreal_eq_lintegral hn.symm.pos.ne'] - simp (discharger := positivity) [v, Real.nnnorm_rpow_of_nonneg, ENNReal.rpow_mul, + simp (discharger := positivity) [v, Real.enorm_rpow_of_nonneg, ENNReal.rpow_mul, ← ENNReal.coe_rpow_of_nonneg] _ ≤ C * eLpNorm (fderiv ℝ v) 1 μ := eLpNorm_le_eLpNorm_fderiv_one μ hv h2v hn - _ = C * ∫⁻ x, ‖fderiv ℝ v x‖₊ ∂μ := by rw [eLpNorm_one_eq_lintegral_nnnorm] - _ ≤ C * γ * ∫⁻ x, ‖u x‖₊ ^ ((γ : ℝ) - 1) * ‖fderiv ℝ u x‖₊ ∂μ := by + _ = C * ∫⁻ x, ‖fderiv ℝ v x‖ₑ ∂μ := by rw [eLpNorm_one_eq_lintegral_enorm] + _ ≤ C * γ * ∫⁻ x, ‖u x‖ₑ ^ ((γ : ℝ) - 1) * ‖fderiv ℝ u x‖ₑ ∂μ := by rw [mul_assoc, ← lintegral_const_mul γ] gcongr - simp_rw [← mul_assoc, ← ENNReal.coe_rpow_of_nonneg _ (sub_nonneg.mpr h1γ.le)] - exact ENNReal.coe_le_coe.mpr <| nnnorm_fderiv_norm_rpow_le (hu.differentiable le_rfl) h1γ + simp_rw [← mul_assoc] + exact enorm_fderiv_norm_rpow_le (hu.differentiable le_rfl) h1γ + dsimp [enorm] fun_prop - _ ≤ C * γ * ((∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ) ^ (1 / q) * - (∫⁻ x, ‖fderiv ℝ u x‖₊ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ))) := by + _ ≤ C * γ * ((∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ) ^ (1 / q) * + (∫⁻ x, ‖fderiv ℝ u x‖ₑ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ))) := by gcongr convert ENNReal.lintegral_mul_le_Lp_mul_Lq μ (.symm <| .conjExponent <| show 1 < (p : ℝ) from hp) ?_ ?_ using 5 @@ -574,12 +571,12 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_eq_inner {u : E → F'} · borelize F' fun_prop · fun_prop - _ = C * γ * (∫⁻ x, ‖fderiv ℝ u x‖₊ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ)) * - (∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ) ^ (1 / q) := by ring + _ = C * γ * (∫⁻ x, ‖fderiv ℝ u x‖ₑ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ)) * + (∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ) ^ (1 / q) := by ring calc eLpNorm u p' μ - = (∫⁻ x, ‖u x‖₊ ^ (p' : ℝ) ∂μ) ^ (1 / (p' : ℝ)) := eLpNorm_nnreal_eq_lintegral h0p' - _ ≤ C * γ * (∫⁻ x, ‖fderiv ℝ u x‖₊ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ)) := by + = (∫⁻ x, ‖u x‖ₑ ^ (p' : ℝ) ∂μ) ^ (1 / (p' : ℝ)) := eLpNorm_nnreal_eq_lintegral h0p' + _ ≤ C * γ * (∫⁻ x, ‖fderiv ℝ u x‖ₑ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ)) := by rwa [← h2q, ENNReal.rpow_sub _ _ h3u h4u, ENNReal.div_le_iff h5u h6u] _ = eLpNormLESNormFDerivOfEqInnerConst μ p * eLpNorm (fderiv ℝ u) (↑p) μ := by suffices (C : ℝ) * γ = eLpNormLESNormFDerivOfEqInnerConst μ p by diff --git a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean index 4f081227992a4..649fa425cabf5 100644 --- a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean +++ b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean @@ -184,10 +184,8 @@ theorem exists_nnnorm_eq_spectralRadius_of_nonempty [ProperSpace 𝕜] {a : A} ( theorem spectralRadius_lt_of_forall_lt_of_nonempty [ProperSpace 𝕜] {a : A} (ha : (σ a).Nonempty) {r : ℝ≥0} (hr : ∀ k ∈ σ a, ‖k‖₊ < r) : spectralRadius 𝕜 a < r := - sSup_image.symm.trans_lt <| - ((spectrum.isCompact a).sSup_lt_iff_of_continuous ha - (ENNReal.continuous_coe.comp continuous_nnnorm).continuousOn (r : ℝ≥0∞)).mpr - (by dsimp only [(· ∘ ·)]; exact mod_cast hr) + sSup_image.symm.trans_lt <| ((spectrum.isCompact a).sSup_lt_iff_of_continuous ha + continuous_enorm.continuousOn (r : ℝ≥0∞)).mpr (by simpa using hr) open ENNReal Polynomial diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index 0b033f8d12618..d773e1f72c4f5 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -686,8 +686,7 @@ alias nndist_eq_nnnorm := nndist_eq_nnnorm_sub theorem nndist_one_right (a : E) : nndist a 1 = ‖a‖₊ := by simp [nndist_eq_nnnorm_div] @[to_additive (attr := simp)] -theorem edist_one_right (a : E) : edist a 1 = ‖a‖₊ := by - rw [edist_nndist, nndist_one_right] +lemma edist_one_right (a : E) : edist a 1 = ‖a‖ₑ := by simp [edist_nndist, nndist_one_right, enorm] @[to_additive (attr := simp) nnnorm_zero] theorem nnnorm_one' : ‖(1 : E)‖₊ = 0 := NNReal.eq norm_one' @@ -800,44 +799,51 @@ lemma nnnorm_div_eq_nnnorm_right {x : E} (y : E) (h : ‖x‖₊ = 0) : ‖x / y lemma nnnorm_div_eq_nnnorm_left (x : E) {y : E} (h : ‖y‖₊ = 0) : ‖x / y‖₊ = ‖x‖₊ := NNReal.eq <| norm_div_eq_norm_left _ <| congr_arg NNReal.toReal h -@[to_additive ofReal_norm_eq_coe_nnnorm] -theorem ofReal_norm_eq_coe_nnnorm' (a : E) : ENNReal.ofReal ‖a‖ = ‖a‖₊ := - ENNReal.ofReal_eq_coe_nnreal _ - /-- The non negative norm seen as an `ENNReal` and then as a `Real` is equal to the norm. -/ @[to_additive toReal_coe_nnnorm "The non negative norm seen as an `ENNReal` and then as a `Real` is equal to the norm."] theorem toReal_coe_nnnorm' (a : E) : (‖a‖₊ : ℝ≥0∞).toReal = ‖a‖ := rfl -@[to_additive] -theorem edist_eq_coe_nnnorm_div (a b : E) : edist a b = ‖a / b‖₊ := by - rw [edist_dist, dist_eq_norm_div, ofReal_norm_eq_coe_nnnorm'] - -@[to_additive edist_eq_coe_nnnorm] -theorem edist_eq_coe_nnnorm' (x : E) : edist x 1 = (‖x‖₊ : ℝ≥0∞) := by - rw [edist_eq_coe_nnnorm_div, div_one] - open scoped symmDiff in @[to_additive] theorem edist_mulIndicator (s t : Set α) (f : α → E) (x : α) : edist (s.mulIndicator f x) (t.mulIndicator f x) = ‖(s ∆ t).mulIndicator f x‖₊ := by rw [edist_nndist, nndist_mulIndicator] -@[to_additive] -theorem mem_emetric_ball_one_iff {r : ℝ≥0∞} : a ∈ EMetric.ball (1 : E) r ↔ ↑‖a‖₊ < r := by - rw [EMetric.mem_ball, edist_eq_coe_nnnorm'] - end NNNorm section ENorm @[to_additive (attr := simp) enorm_zero] lemma enorm_one' : ‖(1 : E)‖ₑ = 0 := by simp [enorm] +@[to_additive ofReal_norm_eq_enorm] +lemma ofReal_norm_eq_enorm' (a : E) : .ofReal ‖a‖ = ‖a‖ₑ := ENNReal.ofReal_eq_coe_nnreal _ + +@[deprecated (since := "2025-01-17")] alias ofReal_norm_eq_coe_nnnorm := ofReal_norm_eq_enorm +@[deprecated (since := "2025-01-17")] alias ofReal_norm_eq_coe_nnnorm' := ofReal_norm_eq_enorm' + instance : ENorm ℝ≥0∞ where enorm x := x @[simp] lemma enorm_eq_self (x : ℝ≥0∞) : ‖x‖ₑ = x := rfl +@[to_additive] +theorem edist_eq_enorm_div (a b : E) : edist a b = ‖a / b‖ₑ := by + rw [edist_dist, dist_eq_norm_div, ofReal_norm_eq_enorm'] + +@[deprecated (since := "2025-01-17")] alias edist_eq_coe_nnnorm_sub := edist_eq_enorm_sub +@[deprecated (since := "2025-01-17")] alias edist_eq_coe_nnnorm_div := edist_eq_enorm_div + +@[to_additive] +theorem edist_one_eq_enorm (x : E) : edist x 1 = ‖x‖ₑ := by rw [edist_eq_enorm_div, div_one] + +@[deprecated (since := "2025-01-17")] alias edist_eq_coe_nnnorm := edist_zero_eq_enorm +@[deprecated (since := "2025-01-17")] alias edist_eq_coe_nnnorm' := edist_one_eq_enorm + +@[to_additive] +theorem mem_emetric_ball_one_iff {r : ℝ≥0∞} : a ∈ EMetric.ball 1 r ↔ ‖a‖ₑ < r := by + rw [EMetric.mem_ball, edist_one_eq_enorm] + end ENorm @[to_additive] @@ -1319,11 +1325,15 @@ lemma enorm_of_nonneg (hr : 0 ≤ r) : ‖r‖ₑ = .ofReal r := by @[simp] lemma nnnorm_abs (r : ℝ) : ‖|r|‖₊ = ‖r‖₊ := by simp [nnnorm] @[simp] lemma enorm_abs (r : ℝ) : ‖|r|‖ₑ = ‖r‖ₑ := by simp [enorm] -theorem ennnorm_eq_ofReal (hr : 0 ≤ r) : (‖r‖₊ : ℝ≥0∞) = ENNReal.ofReal r := by - rw [← ofReal_norm_eq_coe_nnnorm, norm_of_nonneg hr] +theorem enorm_eq_ofReal (hr : 0 ≤ r) : ‖r‖ₑ = .ofReal r := by + rw [← ofReal_norm_eq_enorm, norm_of_nonneg hr] + +@[deprecated (since := "2025-01-17")] alias ennnorm_eq_ofReal := enorm_eq_ofReal -theorem ennnorm_eq_ofReal_abs (r : ℝ) : (‖r‖₊ : ℝ≥0∞) = ENNReal.ofReal |r| := by - rw [← Real.nnnorm_abs r, Real.ennnorm_eq_ofReal (abs_nonneg _)] +theorem enorm_eq_ofReal_abs (r : ℝ) : ‖r‖ₑ = ENNReal.ofReal |r| := by + rw [← enorm_eq_ofReal (abs_nonneg _), enorm_abs] + +@[deprecated (since := "2025-01-17")] alias ennnorm_eq_ofReal_abs := enorm_eq_ofReal_abs theorem toNNReal_eq_nnnorm_of_nonneg (hr : 0 ≤ r) : r.toNNReal = ‖r‖₊ := by rw [Real.toNNReal_of_nonneg hr] @@ -1331,12 +1341,10 @@ theorem toNNReal_eq_nnnorm_of_nonneg (hr : 0 ≤ r) : r.toNNReal = ‖r‖₊ := rw [coe_mk, coe_nnnorm r, Real.norm_eq_abs r, abs_of_nonneg hr] -- Porting note: this is due to the change from `Subtype.val` to `NNReal.toReal` for the coercion -theorem ofReal_le_ennnorm (r : ℝ) : ENNReal.ofReal r ≤ ‖r‖₊ := by - obtain hr | hr := le_total 0 r - · exact (Real.ennnorm_eq_ofReal hr).ge - · rw [ENNReal.ofReal_eq_zero.2 hr] - exact bot_le --- Porting note: should this be renamed to `Real.ofReal_le_nnnorm`? +theorem ofReal_le_enorm (r : ℝ) : ENNReal.ofReal r ≤ ‖r‖ₑ := by + rw [enorm_eq_ofReal_abs]; gcongr; exact le_abs_self _ + +@[deprecated (since := "2025-01-17")] alias ofReal_le_ennnorm := ofReal_le_enorm end Real diff --git a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean index 595b8aa9b7f34..a773a828ece6a 100644 --- a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean +++ b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean @@ -132,9 +132,9 @@ theorem integrable_one_add_norm {r : ℝ} (hnr : (finrank ℝ E : ℝ) < r) : constructor · apply Measurable.aestronglyMeasurable (by fun_prop) -- Lower Lebesgue integral - have : (∫⁻ a : E, ‖(1 + ‖a‖) ^ (-r)‖₊ ∂μ) = ∫⁻ a : E, ENNReal.ofReal ((1 + ‖a‖) ^ (-r)) ∂μ := - lintegral_nnnorm_eq_of_nonneg fun _ => rpow_nonneg (by positivity) _ - rw [hasFiniteIntegral_iff_nnnorm, this] + have : (∫⁻ a : E, ‖(1 + ‖a‖) ^ (-r)‖ₑ ∂μ) = ∫⁻ a : E, ENNReal.ofReal ((1 + ‖a‖) ^ (-r)) ∂μ := + lintegral_enorm_of_nonneg fun _ => rpow_nonneg (by positivity) _ + rw [hasFiniteIntegral_iff_enorm, this] exact finite_integral_one_add_norm hnr theorem integrable_rpow_neg_one_add_norm_sq {r : ℝ} (hnr : (finrank ℝ E : ℝ) < r) : diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean index 07c0bcd00e44e..c3611c1f706ca 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean @@ -232,25 +232,28 @@ theorem measurable_nnnorm : Measurable (nnnorm : α → ℝ≥0) := continuous_nnnorm.measurable @[measurability, fun_prop] -theorem Measurable.nnnorm {f : β → α} (hf : Measurable f) : Measurable fun a => ‖f a‖₊ := +protected theorem Measurable.nnnorm {f : β → α} (hf : Measurable f) : Measurable fun a => ‖f a‖₊ := measurable_nnnorm.comp hf @[measurability, fun_prop] -theorem AEMeasurable.nnnorm {f : β → α} {μ : Measure β} (hf : AEMeasurable f μ) : +protected lemma AEMeasurable.nnnorm {f : β → α} {μ : Measure β} (hf : AEMeasurable f μ) : AEMeasurable (fun a => ‖f a‖₊) μ := measurable_nnnorm.comp_aemeasurable hf @[measurability] -theorem measurable_ennnorm : Measurable fun x : α => (‖x‖₊ : ℝ≥0∞) := - measurable_nnnorm.coe_nnreal_ennreal +lemma measurable_enorm : Measurable (enorm : α → ℝ≥0∞) := continuous_enorm.measurable @[measurability, fun_prop] -theorem Measurable.ennnorm {f : β → α} (hf : Measurable f) : Measurable fun a => (‖f a‖₊ : ℝ≥0∞) := +protected lemma Measurable.enorm {f : β → α} (hf : Measurable f) : Measurable (‖f ·‖ₑ) := hf.nnnorm.coe_nnreal_ennreal @[measurability, fun_prop] -theorem AEMeasurable.ennnorm {f : β → α} {μ : Measure β} (hf : AEMeasurable f μ) : - AEMeasurable (fun a => (‖f a‖₊ : ℝ≥0∞)) μ := - measurable_ennnorm.comp_aemeasurable hf +protected lemma AEMeasurable.enorm {f : β → α} {μ : Measure β} (hf : AEMeasurable f μ) : + AEMeasurable (‖f ·‖ₑ) μ := + measurable_enorm.comp_aemeasurable hf + +@[deprecated (since := "2025-01-21")] alias measurable_ennnorm := measurable_enorm +@[deprecated (since := "2025-01-21")] alias Measurable.ennnorm := Measurable.enorm +@[deprecated (since := "2025-01-21")] alias AEMeasurable.ennnorm := AEMeasurable.enorm end NormedAddCommGroup diff --git a/Mathlib/MeasureTheory/Covering/Differentiation.lean b/Mathlib/MeasureTheory/Covering/Differentiation.lean index 672bfe1a4f090..f54de11ae1ded 100644 --- a/Mathlib/MeasureTheory/Covering/Differentiation.lean +++ b/Mathlib/MeasureTheory/Covering/Differentiation.lean @@ -770,10 +770,10 @@ theorem ae_tendsto_lintegral_div {f : α → ℝ≥0∞} (hf : AEMeasurable f μ apply lintegral_congr_ae exact ae_restrict_of_ae hf.ae_eq_mk -theorem ae_tendsto_lintegral_nnnorm_sub_div'_of_integrable {f : α → E} (hf : Integrable f μ) +theorem ae_tendsto_lintegral_enorm_sub_div'_of_integrable {f : α → E} (hf : Integrable f μ) (h'f : StronglyMeasurable f) : - ∀ᵐ x ∂μ, Tendsto (fun a => (∫⁻ y in a, ‖f y - f x‖₊ ∂μ) / μ a) (v.filterAt x) (𝓝 0) := by - /- For every `c`, then `(∫⁻ y in a, ‖f y - c‖₊ ∂μ) / μ a` tends almost everywhere to `‖f x - c‖`. + ∀ᵐ x ∂μ, Tendsto (fun a => (∫⁻ y in a, ‖f y - f x‖ₑ ∂μ) / μ a) (v.filterAt x) (𝓝 0) := by + /- For every `c`, then `(∫⁻ y in a, ‖f y - c‖ₑ ∂μ) / μ a` tends almost everywhere to `‖f x - c‖`. We apply this to a countable set of `c` which is dense in the range of `f`, to deduce the desired convergence. A minor technical inconvenience is that constants are not integrable, so to apply previous @@ -784,37 +784,31 @@ theorem ae_tendsto_lintegral_nnnorm_sub_div'_of_integrable {f : α → E} (hf : have main : ∀ᵐ x ∂μ, ∀ᵉ (n : ℕ) (c ∈ t), - Tendsto (fun a => (∫⁻ y in a, ‖f y - (A.set n).indicator (fun _ => c) y‖₊ ∂μ) / μ a) - (v.filterAt x) (𝓝 ‖f x - (A.set n).indicator (fun _ => c) x‖₊) := by + Tendsto (fun a => (∫⁻ y in a, ‖f y - (A.set n).indicator (fun _ => c) y‖ₑ ∂μ) / μ a) + (v.filterAt x) (𝓝 ‖f x - (A.set n).indicator (fun _ => c) x‖ₑ) := by #adaptation_note /-- 2024-04-23 The next two lines were previously just `simp_rw [ae_all_iff, ae_ball_iff t_count]`. -/ simp_rw [ae_all_iff] intro x; rw [ae_ball_iff t_count]; revert x intro n c _ apply ae_tendsto_lintegral_div' - · refine (h'f.sub ?_).ennnorm + · refine (h'f.sub ?_).enorm exact stronglyMeasurable_const.indicator (IsOpen.measurableSet (A.set_mem n)) · apply ne_of_lt calc - (∫⁻ y, ↑‖f y - (A.set n).indicator (fun _ : α => c) y‖₊ ∂μ) ≤ - ∫⁻ y, ‖f y‖₊ + ‖(A.set n).indicator (fun _ : α => c) y‖₊ ∂μ := by - apply lintegral_mono - intro x - dsimp - rw [← ENNReal.coe_add] - exact ENNReal.coe_le_coe.2 (nnnorm_sub_le _ _) - _ = (∫⁻ y, ‖f y‖₊ ∂μ) + ∫⁻ y, ‖(A.set n).indicator (fun _ : α => c) y‖₊ ∂μ := - (lintegral_add_left h'f.ennnorm _) + ∫⁻ y, ‖f y - (A.set n).indicator (fun _ : α => c) y‖ₑ ∂μ + ≤ ∫⁻ y, ‖f y‖ₑ + ‖(A.set n).indicator (fun _ : α => c) y‖ₑ ∂μ := + lintegral_mono fun x ↦ enorm_sub_le + _ = ∫⁻ y, ‖f y‖ₑ ∂μ + ∫⁻ y, ‖(A.set n).indicator (fun _ : α => c) y‖ₑ ∂μ := + lintegral_add_left h'f.enorm _ _ < ∞ + ∞ := haveI I : Integrable ((A.set n).indicator fun _ : α => c) μ := by simp only [integrable_indicator_iff (IsOpen.measurableSet (A.set_mem n)), integrableOn_const, A.finite n, or_true] ENNReal.add_lt_add hf.2 I.2 filter_upwards [main, v.ae_eventually_measure_pos] with x hx h'x - have M : - ∀ c ∈ t, Tendsto (fun a => (∫⁻ y in a, ‖f y - c‖₊ ∂μ) / μ a) - (v.filterAt x) (𝓝 ‖f x - c‖₊) := by - intro c hc + have M c (hc : c ∈ t) : + Tendsto (fun a => (∫⁻ y in a, ‖f y - c‖ₑ ∂μ) / μ a) (v.filterAt x) (𝓝 ‖f x - c‖ₑ) := by obtain ⟨n, xn⟩ : ∃ n, x ∈ A.set n := by simpa [← A.spanning] using mem_univ x specialize hx n c hc simp only [xn, indicator_of_mem] at hx @@ -825,18 +819,18 @@ theorem ae_tendsto_lintegral_nnnorm_sub_div'_of_integrable {f : α → E} (hf : apply setLIntegral_congr_fun h'a filter_upwards with y hy using (by simp only [ha hy, indicator_of_mem]) apply ENNReal.tendsto_nhds_zero.2 fun ε εpos => ?_ - obtain ⟨c, ct, xc⟩ : ∃ c ∈ t, (‖f x - c‖₊ : ℝ≥0∞) < ε / 2 := by - simp_rw [← edist_eq_coe_nnnorm_sub] + obtain ⟨c, ct, xc⟩ : ∃ c ∈ t, ‖f x - c‖ₑ < ε / 2 := by + simp_rw [← edist_eq_enorm_sub] have : f x ∈ closure t := ht (mem_range_self _) exact EMetric.mem_closure_iff.1 this (ε / 2) (ENNReal.half_pos (ne_of_gt εpos)) filter_upwards [(tendsto_order.1 (M c ct)).2 (ε / 2) xc, h'x, v.eventually_measure_lt_top x] with a ha h'a h''a apply ENNReal.div_le_of_le_mul calc - (∫⁻ y in a, ‖f y - f x‖₊ ∂μ) ≤ ∫⁻ y in a, ‖f y - c‖₊ + ‖f x - c‖₊ ∂μ := by + (∫⁻ y in a, ‖f y - f x‖ₑ ∂μ) ≤ ∫⁻ y in a, ‖f y - c‖ₑ + ‖f x - c‖ₑ ∂μ := by apply lintegral_mono fun x => ?_ - simpa only [← edist_eq_coe_nnnorm_sub] using edist_triangle_right _ _ _ - _ = (∫⁻ y in a, ‖f y - c‖₊ ∂μ) + ∫⁻ _ in a, ‖f x - c‖₊ ∂μ := + simpa only [← edist_eq_enorm_sub] using edist_triangle_right _ _ _ + _ = (∫⁻ y in a, ‖f y - c‖ₑ ∂μ) + ∫⁻ _ in a, ‖f x - c‖ₑ ∂μ := (lintegral_add_right _ measurable_const) _ ≤ ε / 2 * μ a + ε / 2 * μ a := by gcongr @@ -846,10 +840,14 @@ theorem ae_tendsto_lintegral_nnnorm_sub_div'_of_integrable {f : α → E} (hf : gcongr _ = ε * μ a := by rw [← add_mul, ENNReal.add_halves] -theorem ae_tendsto_lintegral_nnnorm_sub_div_of_integrable {f : α → E} (hf : Integrable f μ) : - ∀ᵐ x ∂μ, Tendsto (fun a => (∫⁻ y in a, ‖f y - f x‖₊ ∂μ) / μ a) (v.filterAt x) (𝓝 0) := by +@[deprecated (since := "2025-01-22")] +alias ae_tendsto_lintegral_nnnorm_sub_div'_of_integrable := + ae_tendsto_lintegral_enorm_sub_div'_of_integrable + +theorem ae_tendsto_lintegral_enorm_sub_div_of_integrable {f : α → E} (hf : Integrable f μ) : + ∀ᵐ x ∂μ, Tendsto (fun a => (∫⁻ y in a, ‖f y - f x‖ₑ ∂μ) / μ a) (v.filterAt x) (𝓝 0) := by have I : Integrable (hf.1.mk f) μ := hf.congr hf.1.ae_eq_mk - filter_upwards [v.ae_tendsto_lintegral_nnnorm_sub_div'_of_integrable I hf.1.stronglyMeasurable_mk, + filter_upwards [v.ae_tendsto_lintegral_enorm_sub_div'_of_integrable I hf.1.stronglyMeasurable_mk, hf.1.ae_eq_mk] with x hx h'x apply hx.congr _ intro a @@ -859,14 +857,18 @@ theorem ae_tendsto_lintegral_nnnorm_sub_div_of_integrable {f : α → E} (hf : I filter_upwards [hf.1.ae_eq_mk] with y hy rw [hy, h'x] -theorem ae_tendsto_lintegral_nnnorm_sub_div {f : α → E} (hf : LocallyIntegrable f μ) : - ∀ᵐ x ∂μ, Tendsto (fun a => (∫⁻ y in a, ‖f y - f x‖₊ ∂μ) / μ a) (v.filterAt x) (𝓝 0) := by +@[deprecated (since := "2025-01-22")] +alias ae_tendsto_lintegral_nnnorm_sub_div_of_integrable := + ae_tendsto_lintegral_enorm_sub_div_of_integrable + +theorem ae_tendsto_lintegral_enorm_sub_div {f : α → E} (hf : LocallyIntegrable f μ) : + ∀ᵐ x ∂μ, Tendsto (fun a => (∫⁻ y in a, ‖f y - f x‖ₑ ∂μ) / μ a) (v.filterAt x) (𝓝 0) := by rcases hf.exists_nat_integrableOn with ⟨u, u_open, u_univ, hu⟩ have : ∀ n, ∀ᵐ x ∂μ, - Tendsto (fun a => (∫⁻ y in a, ‖(u n).indicator f y - (u n).indicator f x‖₊ ∂μ) / μ a) + Tendsto (fun a => (∫⁻ y in a, ‖(u n).indicator f y - (u n).indicator f x‖ₑ ∂μ) / μ a) (v.filterAt x) (𝓝 0) := by intro n - apply ae_tendsto_lintegral_nnnorm_sub_div_of_integrable + apply ae_tendsto_lintegral_enorm_sub_div_of_integrable exact (integrable_indicator_iff (u_open n).measurableSet).2 (hu n) filter_upwards [ae_all_iff.2 this] with x hx obtain ⟨n, hn⟩ : ∃ n, x ∈ u n := by simpa only [← u_univ, mem_iUnion] using mem_univ x @@ -877,11 +879,14 @@ theorem ae_tendsto_lintegral_nnnorm_sub_div {f : α → E} (hf : LocallyIntegrab refine setLIntegral_congr_fun h'a (Eventually.of_forall (fun y hy ↦ ?_)) rw [indicator_of_mem (ha hy) f, indicator_of_mem hn f] +@[deprecated (since := "2025-01-22")] +alias ae_tendsto_lintegral_nnnorm_sub_div := ae_tendsto_lintegral_enorm_sub_div + /-- *Lebesgue differentiation theorem*: for almost every point `x`, the average of `‖f y - f x‖` on `a` tends to `0` as `a` shrinks to `x` along a Vitali family. -/ theorem ae_tendsto_average_norm_sub {f : α → E} (hf : LocallyIntegrable f μ) : ∀ᵐ x ∂μ, Tendsto (fun a => ⨍ y in a, ‖f y - f x‖ ∂μ) (v.filterAt x) (𝓝 0) := by - filter_upwards [v.ae_tendsto_lintegral_nnnorm_sub_div hf] with x hx + filter_upwards [v.ae_tendsto_lintegral_enorm_sub_div hf] with x hx have := (ENNReal.tendsto_toReal ENNReal.zero_ne_top).comp hx simp only [ENNReal.zero_toReal] at this apply Tendsto.congr' _ this @@ -891,6 +896,7 @@ theorem ae_tendsto_average_norm_sub {f : α → E} (hf : LocallyIntegrable f μ) have A : IntegrableOn (fun y => (‖f y - f x‖₊ : ℝ)) a μ := by simp_rw [coe_nnnorm] exact (h''a.sub (integrableOn_const.2 (Or.inr h'a))).norm + dsimp [enorm] rw [lintegral_coe_eq_integral _ A, ENNReal.toReal_ofReal (by positivity)] simp only [coe_nnnorm, smul_eq_mul] diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean index 1871e8db5807f..59eff72389d34 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean @@ -132,15 +132,15 @@ theorem norm_condExpIndL1Fin_le (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x ‖condExpIndL1Fin hm hs hμs x‖ ≤ (μ s).toReal * ‖x‖ := by rw [L1.norm_eq_integral_norm, ← ENNReal.toReal_ofReal (norm_nonneg x), ← ENNReal.toReal_mul, ← ENNReal.ofReal_le_iff_le_toReal (ENNReal.mul_ne_top hμs ENNReal.ofReal_ne_top), - ofReal_integral_norm_eq_lintegral_nnnorm] + ofReal_integral_norm_eq_lintegral_enorm] swap; · rw [← memℒp_one_iff_integrable]; exact Lp.memℒp _ have h_eq : - ∫⁻ a, ‖condExpIndL1Fin hm hs hμs x a‖₊ ∂μ = ∫⁻ a, ‖condExpIndSMul hm hs hμs x a‖₊ ∂μ := by + ∫⁻ a, ‖condExpIndL1Fin hm hs hμs x a‖ₑ ∂μ = ∫⁻ a, ‖condExpIndSMul hm hs hμs x a‖ₑ ∂μ := by refine lintegral_congr_ae ?_ refine (condExpIndL1Fin_ae_eq_condExpIndSMul hm hs hμs x).mono fun z hz => ?_ dsimp only rw [hz] - rw [h_eq, ofReal_norm_eq_coe_nnnorm] + rw [h_eq, ofReal_norm_eq_enorm] exact lintegral_nnnorm_condExpIndSMul_le hm hs hμs x @[deprecated (since := "2025-01-21")] alias norm_condexpIndL1Fin_le := norm_condExpIndL1Fin_le diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean index b6524435ba77e..c51e17e623243 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean @@ -194,7 +194,7 @@ theorem lintegral_nnnorm_condExpL2_le (hs : MeasurableSet[m] s) (hμs : μ s ≠ dsimp only simp_rw [hx] rw [lintegral_congr_ae hg_nnnorm_eq.symm] - refine lintegral_nnnorm_le_of_forall_fin_meas_integral_eq + refine lintegral_enorm_le_of_forall_fin_meas_integral_eq hm (Lp.stronglyMeasurable f) ?_ ?_ ?_ ?_ hs hμs · exact integrableOn_Lp_of_measure_ne_top f fact_one_le_two_ennreal.elim hμs · exact hg_meas @@ -225,7 +225,7 @@ theorem condExpL2_ae_eq_zero_of_ae_eq_zero (hs : MeasurableSet[m] s) (hμs : μ dsimp only rw [hx] simp - · exact (Lp.stronglyMeasurable _).ennnorm + · exact (Lp.stronglyMeasurable _).enorm @[deprecated (since := "2025-01-21")] alias condexpL2_ae_eq_zero_of_ae_eq_zero := condExpL2_ae_eq_zero_of_ae_eq_zero @@ -383,7 +383,7 @@ theorem setLIntegral_nnnorm_condExpL2_indicator_le (hm : m ≤ m0) (hs : Measura _ = (∫⁻ a in t, ‖(condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ) * ‖x‖₊ := by simp_rw [nnnorm_smul, ENNReal.coe_mul] rw [lintegral_mul_const, lpMeas_coe] - exact (Lp.stronglyMeasurable _).ennnorm + exact (Lp.stronglyMeasurable _).enorm _ ≤ μ (s ∩ t) * ‖x‖₊ := mul_le_mul_right' (lintegral_nnnorm_condExpL2_indicator_le_real hs hμs ht hμt) _ @@ -488,7 +488,7 @@ theorem setLIntegral_nnnorm_condExpIndSMul_le (hm : m ≤ m0) (hs : MeasurableSe _ = (∫⁻ a in t, ‖(condExpL2 ℝ ℝ hm (indicatorConstLp 2 hs hμs 1) : α → ℝ) a‖₊ ∂μ) * ‖x‖₊ := by simp_rw [nnnorm_smul, ENNReal.coe_mul] rw [lintegral_mul_const, lpMeas_coe] - exact (Lp.stronglyMeasurable _).ennnorm + exact (Lp.stronglyMeasurable _).enorm _ ≤ μ (s ∩ t) * ‖x‖₊ := mul_le_mul_right' (lintegral_nnnorm_condExpL2_indicator_le_real hs hμs ht hμt) _ diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean index 41c370cc5b4b6..3f4e72c29f95a 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Real.lean @@ -71,12 +71,12 @@ theorem eLpNorm_one_condExp_le_eLpNorm (f : α → ℝ) : eLpNorm (μ[f|m]) 1 μ (ae_of_all μ (fun x => neg_le_abs (f x) : ∀ x, -f x ≤ |f x|)))] with x hx₁ hx₂ exact abs_le_abs hx₁ hx₂ _ = eLpNorm f 1 μ := by - rw [eLpNorm_one_eq_lintegral_nnnorm, eLpNorm_one_eq_lintegral_nnnorm, - ← ENNReal.toReal_eq_toReal (hasFiniteIntegral_iff_nnnorm.mp integrable_condExp.2).ne - (hasFiniteIntegral_iff_nnnorm.mp hf.2).ne, - ← integral_norm_eq_lintegral_nnnorm + rw [eLpNorm_one_eq_lintegral_enorm, eLpNorm_one_eq_lintegral_enorm, + ← ENNReal.toReal_eq_toReal (hasFiniteIntegral_iff_enorm.mp integrable_condExp.2).ne + (hasFiniteIntegral_iff_enorm.mp hf.2).ne, + ← integral_norm_eq_lintegral_enorm (stronglyMeasurable_condExp.mono hm).aestronglyMeasurable, - ← integral_norm_eq_lintegral_nnnorm hf.1] + ← integral_norm_eq_lintegral_enorm hf.1] simp_rw [Real.norm_eq_abs] rw (config := {occs := .pos [2]}) [← integral_condExp hm] refine integral_congr_ae ?_ @@ -106,9 +106,9 @@ theorem integral_abs_condExp_le (f : α → ℝ) : ∫ x, |(μ[f|m]) x| ∂μ Algebra.id.smul_eq_mul, mul_zero] positivity rw [integral_eq_lintegral_of_nonneg_ae, integral_eq_lintegral_of_nonneg_ae] - · apply ENNReal.toReal_mono <;> simp_rw [← Real.norm_eq_abs, ofReal_norm_eq_coe_nnnorm] + · apply ENNReal.toReal_mono <;> simp_rw [← Real.norm_eq_abs, ofReal_norm_eq_enorm] · exact hfint.2.ne - · rw [← eLpNorm_one_eq_lintegral_nnnorm, ← eLpNorm_one_eq_lintegral_nnnorm] + · rw [← eLpNorm_one_eq_lintegral_enorm, ← eLpNorm_one_eq_lintegral_enorm] exact eLpNorm_one_condExp_le_eLpNorm _ · filter_upwards with x using abs_nonneg _ · simp_rw [← Real.norm_eq_abs] @@ -237,7 +237,7 @@ alias Integrable.uniformIntegrable_condexp := Integrable.uniformIntegrable_condE section PullOut -- TODO: this section could be generalized beyond multiplication, to any bounded bilinear map. -/-- Auxiliary lemma for `condexp_mul_of_stronglyMeasurable_left`. -/ +/-- Auxiliary lemma for `condExp_mul_of_stronglyMeasurable_left`. -/ theorem condExp_stronglyMeasurable_simpleFunc_mul (hm : m ≤ m0) (f : @SimpleFunc α m ℝ) {g : α → ℝ} (hg : Integrable g μ) : μ[(f * g : α → ℝ)|m] =ᵐ[μ] f * μ[g|m] := by have : ∀ (s c) (f : α → ℝ), Set.indicator s (Function.const α c) * f = s.indicator (c • f) := by diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean index 033ce021ee4be..490cbe24cc817 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Unique.lean @@ -204,18 +204,22 @@ theorem integral_norm_le_of_forall_fin_meas_integral_eq (hm : m ≤ m0) {f g : /-- Let `m` be a sub-σ-algebra of `m0`, `f` an `m0`-measurable function and `g` an `m`-measurable function, such that their integrals coincide on `m`-measurable sets with finite measure. -Then `∫⁻ x in s, ‖g x‖₊ ∂μ ≤ ∫⁻ x in s, ‖f x‖₊ ∂μ` on all `m`-measurable sets with finite +Then `∫⁻ x in s, ‖g x‖ₑ ∂μ ≤ ∫⁻ x in s, ‖f x‖ₑ ∂μ` on all `m`-measurable sets with finite measure. -/ -theorem lintegral_nnnorm_le_of_forall_fin_meas_integral_eq (hm : m ≤ m0) {f g : α → ℝ} +theorem lintegral_enorm_le_of_forall_fin_meas_integral_eq (hm : m ≤ m0) {f g : α → ℝ} (hf : StronglyMeasurable f) (hfi : IntegrableOn f s μ) (hg : StronglyMeasurable[m] g) (hgi : IntegrableOn g s μ) (hgf : ∀ t, MeasurableSet[m] t → μ t < ∞ → ∫ x in t, g x ∂μ = ∫ x in t, f x ∂μ) - (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) : (∫⁻ x in s, ‖g x‖₊ ∂μ) ≤ ∫⁻ x in s, ‖f x‖₊ ∂μ := by - rw [← ofReal_integral_norm_eq_lintegral_nnnorm hfi, ← - ofReal_integral_norm_eq_lintegral_nnnorm hgi, ENNReal.ofReal_le_ofReal_iff] + (hs : MeasurableSet[m] s) (hμs : μ s ≠ ∞) : (∫⁻ x in s, ‖g x‖ₑ ∂μ) ≤ ∫⁻ x in s, ‖f x‖ₑ ∂μ := by + rw [← ofReal_integral_norm_eq_lintegral_enorm hfi, ← + ofReal_integral_norm_eq_lintegral_enorm hgi, ENNReal.ofReal_le_ofReal_iff] · exact integral_norm_le_of_forall_fin_meas_integral_eq hm hf hfi hg hgi hgf hs hμs · positivity +@[deprecated (since := "2025-01-21")] +alias lintegral_nnnorm_le_of_forall_fin_meas_integral_eq := + lintegral_enorm_le_of_forall_fin_meas_integral_eq + end IntegralNormLE end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean b/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean index 633e66b2ab991..8110b019c55bb 100644 --- a/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean +++ b/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean @@ -117,11 +117,8 @@ theorem exists_continuous_eLpNorm_sub_le_of_closed [μ.OuterRegular] (hp : p ≠ have gc_mem : Memℒp (fun x => g x • c) p μ := by refine Memℒp.smul_of_top_left (memℒp_top_const _) ?_ refine ⟨g.continuous.aestronglyMeasurable, ?_⟩ - have : eLpNorm (v.indicator fun _x => (1 : ℝ)) p μ < ⊤ := by - refine (eLpNorm_indicator_const_le _ _).trans_lt ?_ - simp only [lt_top_iff_ne_top, hμv.ne, nnnorm_one, ENNReal.coe_one, one_div, one_mul, Ne, - ENNReal.rpow_eq_top_iff, inv_lt_zero, false_and, or_false, not_and, not_lt, - ENNReal.toReal_nonneg, imp_true_iff] + have : eLpNorm (v.indicator fun _x => (1 : ℝ)) p μ < ⊤ := + (eLpNorm_indicator_const_le _ _).trans_lt <| by simp [lt_top_iff_ne_top, hμv.ne] refine (eLpNorm_mono fun x => ?_).trans_lt this by_cases hx : x ∈ v · simp only [hx, abs_of_nonneg (hg_range x).1, (hg_range x).2, Real.norm_eq_abs, @@ -219,8 +216,8 @@ theorem Integrable.exists_hasCompactSupport_lintegral_sub_le [R1Space α] [WeaklyLocallyCompactSpace α] [μ.Regular] {f : α → E} (hf : Integrable f μ) {ε : ℝ≥0∞} (hε : ε ≠ 0) : ∃ g : α → E, - HasCompactSupport g ∧ (∫⁻ x, ‖f x - g x‖₊ ∂μ) ≤ ε ∧ Continuous g ∧ Integrable g μ := by - simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_nnnorm] at hf ⊢ + HasCompactSupport g ∧ ∫⁻ x, ‖f x - g x‖ₑ ∂μ ≤ ε ∧ Continuous g ∧ Integrable g μ := by + simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_enorm] at hf ⊢ exact hf.exists_hasCompactSupport_eLpNorm_sub_le ENNReal.one_ne_top hε /-- In a locally compact space, any integrable function can be approximated by compactly supported @@ -230,7 +227,7 @@ theorem Integrable.exists_hasCompactSupport_integral_sub_le {f : α → E} (hf : Integrable f μ) {ε : ℝ} (hε : 0 < ε) : ∃ g : α → E, HasCompactSupport g ∧ (∫ x, ‖f x - g x‖ ∂μ) ≤ ε ∧ Continuous g ∧ Integrable g μ := by - simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_nnnorm, ← ENNReal.ofReal_one] + simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_enorm, ← ENNReal.ofReal_one] at hf ⊢ simpa using hf.exists_hasCompactSupport_integral_rpow_sub_le zero_lt_one hε @@ -309,8 +306,8 @@ theorem Memℒp.exists_boundedContinuous_integral_rpow_sub_le [μ.WeaklyRegular] version in terms of `∫⁻`. -/ theorem Integrable.exists_boundedContinuous_lintegral_sub_le [μ.WeaklyRegular] {f : α → E} (hf : Integrable f μ) {ε : ℝ≥0∞} (hε : ε ≠ 0) : - ∃ g : α →ᵇ E, (∫⁻ x, ‖f x - g x‖₊ ∂μ) ≤ ε ∧ Integrable g μ := by - simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_nnnorm] at hf ⊢ + ∃ g : α →ᵇ E, ∫⁻ x, ‖f x - g x‖ₑ ∂μ ≤ ε ∧ Integrable g μ := by + simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_enorm] at hf ⊢ exact hf.exists_boundedContinuous_eLpNorm_sub_le ENNReal.one_ne_top hε /-- Any integrable function can be approximated by bounded continuous functions, @@ -318,7 +315,7 @@ version in terms of `∫`. -/ theorem Integrable.exists_boundedContinuous_integral_sub_le [μ.WeaklyRegular] {f : α → E} (hf : Integrable f μ) {ε : ℝ} (hε : 0 < ε) : ∃ g : α →ᵇ E, (∫ x, ‖f x - g x‖ ∂μ) ≤ ε ∧ Integrable g μ := by - simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_nnnorm, ← ENNReal.ofReal_one] + simp only [← memℒp_one_iff_integrable, ← eLpNorm_one_eq_lintegral_enorm, ← ENNReal.ofReal_one] at hf ⊢ simpa using hf.exists_boundedContinuous_integral_rpow_sub_le zero_lt_one hε diff --git a/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean b/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean index f9a7daf12fa48..e8eaafe2a7ed0 100644 --- a/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean +++ b/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean @@ -270,7 +270,7 @@ theorem tendstoInMeasure_of_tendsto_eLpNorm_of_stronglyMeasurable (hp_ne_zero : · rw [← ENNReal.ofReal_rpow_of_pos hε] convert mul_meas_ge_le_pow_eLpNorm' μ hp_ne_zero hp_ne_top ((hf n).sub hg).aestronglyMeasurable (ENNReal.ofReal ε) - rw [dist_eq_norm, ← ENNReal.ofReal_le_ofReal_iff (norm_nonneg _), ofReal_norm_eq_coe_nnnorm] + rw [dist_eq_norm, ← ENNReal.ofReal_le_ofReal_iff (norm_nonneg _), ofReal_norm_eq_enorm] exact Iff.rfl · rw [Ne, ENNReal.ofReal_eq_zero, not_le] exact Or.inl (Real.rpow_pos_of_pos hε _) diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 2624f72f454f2..11feddd7f0440 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -29,7 +29,7 @@ classes of integrable functions, already defined as a special case of `L^p` spac ## Main definitions * Let `f : α → β` be a function, where `α` is a `MeasureSpace` and `β` a `NormedAddCommGroup`. - Then `HasFiniteIntegral f` means `(∫⁻ a, ‖f a‖₊) < ∞`. + Then `HasFiniteIntegral f` means `∫⁻ a, ‖f a‖ₑ < ∞`. * If `β` is moreover a `MeasurableSpace` then `f` is called `Integrable` if `f` is `Measurable` and `HasFiniteIntegral f` holds. @@ -60,13 +60,15 @@ namespace MeasureTheory /-! ### Some results about the Lebesgue integral involving a normed group -/ +lemma lintegral_enorm_eq_lintegral_edist (f : α → β) : + ∫⁻ a, ‖f a‖ₑ ∂μ = ∫⁻ a, edist (f a) 0 ∂μ := by simp only [edist_zero_eq_enorm] -theorem lintegral_nnnorm_eq_lintegral_edist (f : α → β) : - ∫⁻ a, ‖f a‖₊ ∂μ = ∫⁻ a, edist (f a) 0 ∂μ := by simp only [edist_eq_coe_nnnorm] +@[deprecated (since := "2025-01-20")] +alias lintegral_nnnorm_eq_lintegral_edist := lintegral_enorm_eq_lintegral_edist theorem lintegral_norm_eq_lintegral_edist (f : α → β) : ∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ = ∫⁻ a, edist (f a) 0 ∂μ := by - simp only [ofReal_norm_eq_coe_nnnorm, edist_eq_coe_nnnorm] + simp only [ofReal_norm_eq_enorm, edist_zero_eq_enorm] theorem lintegral_edist_triangle {f g h : α → β} (hf : AEStronglyMeasurable f μ) (hh : AEStronglyMeasurable h μ) : @@ -75,18 +77,23 @@ theorem lintegral_edist_triangle {f g h : α → β} (hf : AEStronglyMeasurable refine lintegral_mono fun a => ?_ apply edist_triangle_right -theorem lintegral_nnnorm_zero : (∫⁻ _ : α, ‖(0 : β)‖₊ ∂μ) = 0 := by simp +-- Yaël: Why do the following four lemmas even exist? +theorem lintegral_enorm_zero : ∫⁻ _ : α, ‖(0 : β)‖ₑ ∂μ = 0 := by simp -theorem lintegral_nnnorm_add_left {f : α → β} (hf : AEStronglyMeasurable f μ) (g : α → γ) : - ∫⁻ a, ‖f a‖₊ + ‖g a‖₊ ∂μ = (∫⁻ a, ‖f a‖₊ ∂μ) + ∫⁻ a, ‖g a‖₊ ∂μ := - lintegral_add_left' hf.ennnorm _ +theorem lintegral_enorm_add_left {f : α → β} (hf : AEStronglyMeasurable f μ) (g : α → γ) : + ∫⁻ a, ‖f a‖ₑ + ‖g a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ + ∫⁻ a, ‖g a‖ₑ ∂μ := + lintegral_add_left' hf.enorm _ -theorem lintegral_nnnorm_add_right (f : α → β) {g : α → γ} (hg : AEStronglyMeasurable g μ) : - ∫⁻ a, ‖f a‖₊ + ‖g a‖₊ ∂μ = (∫⁻ a, ‖f a‖₊ ∂μ) + ∫⁻ a, ‖g a‖₊ ∂μ := - lintegral_add_right' _ hg.ennnorm +theorem lintegral_enorm_add_right (f : α → β) {g : α → γ} (hg : AEStronglyMeasurable g μ) : + ∫⁻ a, ‖f a‖ₑ + ‖g a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ + ∫⁻ a, ‖g a‖ₑ ∂μ := + lintegral_add_right' _ hg.enorm -theorem lintegral_nnnorm_neg {f : α → β} : (∫⁻ a, ‖(-f) a‖₊ ∂μ) = ∫⁻ a, ‖f a‖₊ ∂μ := by - simp only [Pi.neg_apply, nnnorm_neg] +theorem lintegral_enorm_neg {f : α → β} : ∫⁻ a, ‖(-f) a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ := by simp + +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_zero := lintegral_enorm_zero +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_add_left := lintegral_enorm_add_left +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_add_right := lintegral_enorm_add_right +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_neg := lintegral_enorm_neg /-! ### The predicate `HasFiniteIntegral` -/ @@ -95,19 +102,21 @@ theorem lintegral_nnnorm_neg {f : α → β} : (∫⁻ a, ‖(-f) a‖₊ ∂μ) `HasFiniteIntegral f` means `HasFiniteIntegral f volume`. -/ def HasFiniteIntegral {_ : MeasurableSpace α} (f : α → ε) (μ : Measure α := by volume_tac) : Prop := - (∫⁻ a, ‖f a‖ₑ ∂μ) < ∞ + ∫⁻ a, ‖f a‖ₑ ∂μ < ∞ theorem hasFiniteIntegral_def {_ : MeasurableSpace α} (f : α → ε) (μ : Measure α) : - HasFiniteIntegral f μ ↔ ((∫⁻ a, ‖f a‖ₑ ∂μ) < ∞) := + HasFiniteIntegral f μ ↔ (∫⁻ a, ‖f a‖ₑ ∂μ < ∞) := Iff.rfl -theorem hasFiniteIntegral_iff_nnnorm {f : α → β} : - HasFiniteIntegral f μ ↔ (∫⁻ a, ‖f a‖₊ ∂μ) < ∞ := by - simp only [HasFiniteIntegral, ofReal_norm_eq_coe_nnnorm, enorm_eq_nnnorm] +theorem hasFiniteIntegral_iff_enorm {f : α → β} : HasFiniteIntegral f μ ↔ ∫⁻ a, ‖f a‖ₑ ∂μ < ∞ := by + simp only [HasFiniteIntegral, ofReal_norm_eq_enorm, enorm_eq_nnnorm] + +@[deprecated (since := "2025-01-20")] +alias hasFiniteIntegral_iff_nnnorm := hasFiniteIntegral_iff_enorm theorem hasFiniteIntegral_iff_norm (f : α → β) : HasFiniteIntegral f μ ↔ (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) < ∞ := by - simp only [hasFiniteIntegral_iff_nnnorm, ofReal_norm_eq_coe_nnnorm] + simp only [hasFiniteIntegral_iff_enorm, ofReal_norm_eq_enorm] theorem hasFiniteIntegral_iff_edist (f : α → β) : HasFiniteIntegral f μ ↔ (∫⁻ a, edist (f a) 0 ∂μ) < ∞ := by @@ -115,7 +124,7 @@ theorem hasFiniteIntegral_iff_edist (f : α → β) : theorem hasFiniteIntegral_iff_ofReal {f : α → ℝ} (h : 0 ≤ᵐ[μ] f) : HasFiniteIntegral f μ ↔ (∫⁻ a, ENNReal.ofReal (f a) ∂μ) < ∞ := by - rw [hasFiniteIntegral_iff_nnnorm, lintegral_nnnorm_eq_of_ae_nonneg h] + rw [hasFiniteIntegral_iff_enorm, lintegral_enorm_of_ae_nonneg h] theorem hasFiniteIntegral_iff_ofNNReal {f : α → ℝ≥0} : HasFiniteIntegral (fun x => (f x : ℝ)) μ ↔ (∫⁻ a, f a ∂μ) < ∞ := by @@ -151,7 +160,7 @@ theorem hasFiniteIntegral_congr {f g : α → β} (h : f =ᵐ[μ] g) : theorem hasFiniteIntegral_const_iff {c : β} : HasFiniteIntegral (fun _ : α => c) μ ↔ c = 0 ∨ IsFiniteMeasure μ := by - simp [hasFiniteIntegral_iff_nnnorm, lintegral_const, lt_top_iff_ne_top, ENNReal.mul_eq_top, + simp [hasFiniteIntegral_iff_enorm, lintegral_const, lt_top_iff_ne_top, ENNReal.mul_eq_top, or_iff_not_imp_left, isFiniteMeasure_iff] lemma hasFiniteIntegral_const_iff_isFiniteMeasure {c : β} (hc : c ≠ 0) : @@ -213,23 +222,19 @@ variable (α β μ) @[simp] theorem hasFiniteIntegral_zero : HasFiniteIntegral (fun _ : α => (0 : β)) μ := by - simp [hasFiniteIntegral_iff_nnnorm] + simp [hasFiniteIntegral_iff_enorm] variable {α β μ} theorem HasFiniteIntegral.neg {f : α → β} (hfi : HasFiniteIntegral f μ) : - HasFiniteIntegral (-f) μ := by simpa [hasFiniteIntegral_iff_nnnorm] using hfi + HasFiniteIntegral (-f) μ := by simpa [hasFiniteIntegral_iff_enorm] using hfi @[simp] theorem hasFiniteIntegral_neg_iff {f : α → β} : HasFiniteIntegral (-f) μ ↔ HasFiniteIntegral f μ := ⟨fun h => neg_neg f ▸ h.neg, HasFiniteIntegral.neg⟩ theorem HasFiniteIntegral.norm {f : α → β} (hfi : HasFiniteIntegral f μ) : - HasFiniteIntegral (fun a => ‖f a‖) μ := by - have eq : (fun a => (nnnorm ‖f a‖ : ℝ≥0∞)) = fun a => (‖f a‖₊ : ℝ≥0∞) := by - funext - rw [nnnorm_norm] - rwa [hasFiniteIntegral_iff_nnnorm, eq] + HasFiniteIntegral (fun a => ‖f a‖) μ := by simpa [hasFiniteIntegral_iff_enorm] using hfi theorem hasFiniteIntegral_norm_iff (f : α → β) : HasFiniteIntegral (fun a => ‖f a‖) μ ↔ HasFiniteIntegral f μ := @@ -237,32 +242,25 @@ theorem hasFiniteIntegral_norm_iff (f : α → β) : theorem hasFiniteIntegral_toReal_of_lintegral_ne_top {f : α → ℝ≥0∞} (hf : ∫⁻ x, f x ∂μ ≠ ∞) : HasFiniteIntegral (fun x ↦ (f x).toReal) μ := by - have h x : (‖(f x).toReal‖₊ : ℝ≥0∞) = ENNReal.ofNNReal ⟨(f x).toReal, ENNReal.toReal_nonneg⟩ := by - rw [Real.nnnorm_of_nonneg] - simp_rw [hasFiniteIntegral_iff_nnnorm, h] + have h x : ‖(f x).toReal‖ₑ = .ofReal (f x).toReal := by + rw [Real.enorm_of_nonneg ENNReal.toReal_nonneg] + simp_rw [hasFiniteIntegral_iff_enorm, h] refine lt_of_le_of_lt (lintegral_mono fun x => ?_) (lt_top_iff_ne_top.2 hf) by_cases hfx : f x = ∞ · simp [hfx] · lift f x to ℝ≥0 using hfx with fx h simp [← h, ← NNReal.coe_le_coe] -lemma hasFiniteIntegral_toReal_iff {f : α → ℝ≥0∞} (hf_ne_top : ∀ᵐ x ∂μ, f x ≠ ∞) : +lemma hasFiniteIntegral_toReal_iff {f : α → ℝ≥0∞} (hf : ∀ᵐ x ∂μ, f x ≠ ∞) : HasFiniteIntegral (fun x ↦ (f x).toReal) μ ↔ ∫⁻ x, f x ∂μ ≠ ∞ := by - have h_eq x : (‖(f x).toReal‖₊ : ℝ≥0∞) - = ENNReal.ofNNReal ⟨(f x).toReal, ENNReal.toReal_nonneg⟩ := by - rw [Real.nnnorm_of_nonneg] - simp_rw [hasFiniteIntegral_iff_nnnorm, h_eq, lt_top_iff_ne_top] - convert Iff.rfl using 2 - refine lintegral_congr_ae ?_ - filter_upwards [hf_ne_top] with x hfx - lift f x to ℝ≥0 using hfx with fx h - simp only [coe_toReal, ENNReal.coe_inj] - rfl + have : ∀ᵐ x ∂μ, .ofReal (f x).toReal = f x := by filter_upwards [hf] with x hx; simp [hx] + simp [hasFiniteIntegral_iff_enorm, Real.enorm_of_nonneg ENNReal.toReal_nonneg, + lintegral_congr_ae this, lt_top_iff_ne_top] theorem isFiniteMeasure_withDensity_ofReal {f : α → ℝ} (hfi : HasFiniteIntegral f μ) : IsFiniteMeasure (μ.withDensity fun x => ENNReal.ofReal <| f x) := by refine isFiniteMeasure_withDensity ((lintegral_mono fun x => ?_).trans_lt hfi).ne - exact Real.ofReal_le_ennnorm (f x) + exact Real.ofReal_le_enorm (f x) section DominatedConvergence @@ -374,12 +372,7 @@ theorem HasFiniteIntegral.smul [NormedAddCommGroup 𝕜] [SMulZeroClass 𝕜 β] {f : α → β} : HasFiniteIntegral f μ → HasFiniteIntegral (c • f) μ := by simp only [HasFiniteIntegral]; intro hfi calc - (∫⁻ a : α, ‖c • f a‖₊ ∂μ) ≤ ∫⁻ a : α, ‖c‖₊ * ‖f a‖₊ ∂μ := by - refine lintegral_mono ?_ - intro i - -- After https://github.com/leanprover/lean4/pull/2734, we need to do beta reduction `exact mod_cast` - beta_reduce - exact mod_cast (nnnorm_smul_le c (f i)) + ∫⁻ a : α, ‖c • f a‖ₑ ∂μ ≤ ∫⁻ a : α, ‖c‖ₑ * ‖f a‖ₑ ∂μ := lintegral_mono fun i ↦ enorm_smul_le _ < ∞ := by rw [lintegral_const_mul'] exacts [mul_lt_top coe_lt_top hfi, coe_ne_top] @@ -418,7 +411,7 @@ def Integrable {α} {_ : MeasurableSpace α} (f : α → ε) scoped notation "Integrable[" mα "]" => @Integrable _ _ _ _ mα theorem memℒp_one_iff_integrable {f : α → β} : Memℒp f 1 μ ↔ Integrable f μ := by - simp_rw [Integrable, hasFiniteIntegral_iff_nnnorm, Memℒp, eLpNorm_one_eq_lintegral_nnnorm] + simp_rw [Integrable, hasFiniteIntegral_iff_enorm, Memℒp, eLpNorm_one_eq_lintegral_enorm] theorem Integrable.aestronglyMeasurable {f : α → β} (hf : Integrable f μ) : AEStronglyMeasurable f μ := @@ -480,7 +473,6 @@ lemma Integrable.of_finite [Finite α] [MeasurableSingletonClass α] [IsFiniteMe @[deprecated Integrable.of_finite (since := "2024-10-05"), nolint deprecatedNoSince] lemma Integrable.of_isEmpty [IsEmpty α] {f : α → β} : Integrable f μ := .of_finite - theorem Memℒp.integrable_norm_rpow {f : α → β} {p : ℝ≥0∞} (hf : Memℒp f p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) : Integrable (fun x : α => ‖f x‖ ^ p.toReal) μ := by rw [← memℒp_one_iff_integrable] @@ -625,12 +617,8 @@ variable {α β μ} theorem Integrable.add' {f g : α → β} (hf : Integrable f μ) (hg : Integrable g μ) : HasFiniteIntegral (f + g) μ := calc - (∫⁻ a, ‖f a + g a‖₊ ∂μ) ≤ ∫⁻ a, ‖f a‖₊ + ‖g a‖₊ ∂μ := - lintegral_mono fun a => by - -- After https://github.com/leanprover/lean4/pull/2734, we need to do beta reduction before `exact mod_cast` - beta_reduce - exact mod_cast nnnorm_add_le _ _ - _ = _ := lintegral_nnnorm_add_left hf.aestronglyMeasurable _ + ∫⁻ a, ‖f a + g a‖ₑ ∂μ ≤ ∫⁻ a, ‖f a‖ₑ + ‖g a‖ₑ ∂μ := lintegral_mono fun _ ↦ enorm_add_le _ _ + _ = _ := lintegral_enorm_add_left hf.aestronglyMeasurable _ _ < ∞ := add_lt_top.2 ⟨hf.hasFiniteIntegral, hg.hasFiniteIntegral⟩ @[fun_prop] @@ -789,7 +777,7 @@ theorem Integrable.bdd_mul {F : Type*} [NormedDivisionRing F] {f g : α → F} ( vector-valued function by a scalar function with finite essential supremum is integrable. -/ theorem Integrable.essSup_smul {𝕜 : Type*} [NormedField 𝕜] [NormedSpace 𝕜 β] {f : α → β} (hf : Integrable f μ) {g : α → 𝕜} (g_aestronglyMeasurable : AEStronglyMeasurable g μ) - (ess_sup_g : essSup (fun x => (‖g x‖₊ : ℝ≥0∞)) μ ≠ ∞) : + (ess_sup_g : essSup (‖g ·‖ₑ) μ ≠ ∞) : Integrable (fun x : α => g x • f x) μ := by rw [← memℒp_one_iff_integrable] at * refine ⟨g_aestronglyMeasurable.smul hf.1, ?_⟩ @@ -804,8 +792,7 @@ theorem Integrable.essSup_smul {𝕜 : Type*} [NormedField 𝕜] [NormedSpace scalar-valued function by a vector-value function with finite essential supremum is integrable. -/ theorem Integrable.smul_essSup {𝕜 : Type*} [NormedRing 𝕜] [Module 𝕜 β] [BoundedSMul 𝕜 β] {f : α → 𝕜} (hf : Integrable f μ) {g : α → β} - (g_aestronglyMeasurable : AEStronglyMeasurable g μ) - (ess_sup_g : essSup (fun x => (‖g x‖₊ : ℝ≥0∞)) μ ≠ ∞) : + (g_aestronglyMeasurable : AEStronglyMeasurable g μ) (ess_sup_g : essSup (‖g ·‖ₑ) μ ≠ ∞) : Integrable (fun x : α => f x • g x) μ := by rw [← memℒp_one_iff_integrable] at * refine ⟨hf.1.smul g_aestronglyMeasurable, ?_⟩ @@ -864,8 +851,8 @@ theorem Memℒp.integrable {q : ℝ≥0∞} (hq1 : 1 ≤ q) {f : α → β} [IsF where `‖f x‖ ≥ ε` is finite for all positive `ε`. -/ theorem Integrable.measure_norm_ge_lt_top {f : α → β} (hf : Integrable f μ) {ε : ℝ} (hε : 0 < ε) : μ { x | ε ≤ ‖f x‖ } < ∞ := by - rw [show { x | ε ≤ ‖f x‖ } = { x | ENNReal.ofReal ε ≤ ‖f x‖₊ } by - simp only [ENNReal.ofReal, Real.toNNReal_le_iff_le_coe, ENNReal.coe_le_coe, coe_nnnorm]] + rw [show { x | ε ≤ ‖f x‖ } = { x | .ofReal ε ≤ ‖f x‖ₑ } by + simp [ENNReal.ofReal, Real.toNNReal_le_iff_le_coe]] refine (meas_ge_le_mul_pow_eLpNorm μ one_ne_zero ENNReal.one_ne_top hf.1 ?_).trans_lt ?_ · simpa only [Ne, ENNReal.ofReal_eq_zero, not_le] using hε apply ENNReal.mul_lt_top @@ -947,8 +934,8 @@ variable [MeasurableSingletonClass α] {f : α → β} /-- A function has finite integral for the counting measure iff its norm is summable. -/ lemma hasFiniteIntegral_count_iff : HasFiniteIntegral f Measure.count ↔ Summable (‖f ·‖) := by - simp only [hasFiniteIntegral_iff_nnnorm, lintegral_count, lt_top_iff_ne_top, - ENNReal.tsum_coe_ne_top_iff_summable, ← NNReal.summable_coe, coe_nnnorm] + simp only [hasFiniteIntegral_iff_enorm, enorm, lintegral_count, lt_top_iff_ne_top, + tsum_coe_ne_top_iff_summable, ← summable_coe, coe_nnnorm] /-- A function is integrable for the counting measure iff its norm is summable. -/ lemma integrable_count_iff : @@ -985,16 +972,11 @@ theorem integrable_withDensity_iff_integrable_coe_smul {f : α → ℝ≥0} (hf {g : α → E} : Integrable g (μ.withDensity fun x => f x) ↔ Integrable (fun x => (f x : ℝ) • g x) μ := by by_cases H : AEStronglyMeasurable (fun x : α => (f x : ℝ) • g x) μ - · simp only [Integrable, aestronglyMeasurable_withDensity_iff hf, hasFiniteIntegral_iff_nnnorm, H] + · simp only [Integrable, aestronglyMeasurable_withDensity_iff hf, hasFiniteIntegral_iff_enorm, H, + true_and] rw [lintegral_withDensity_eq_lintegral_mul₀' hf.coe_nnreal_ennreal.aemeasurable] - · rw [iff_iff_eq] - congr - ext1 x - simp only [nnnorm_smul, NNReal.nnnorm_eq, coe_mul, Pi.mul_apply] - · rw [aemeasurable_withDensity_ennreal_iff hf] - convert H.ennnorm using 1 - ext1 x - simp only [nnnorm_smul, NNReal.nnnorm_eq, coe_mul] + · simp [enorm_smul] + · simpa [aemeasurable_withDensity_ennreal_iff hf, enorm_smul] using H.enorm · simp only [Integrable, aestronglyMeasurable_withDensity_iff hf, H, false_and] theorem integrable_withDensity_iff_integrable_smul {f : α → ℝ≥0} (hf : Measurable f) {g : α → E} : @@ -1093,9 +1075,8 @@ noncomputable def withDensitySMulLI {f : α → ℝ≥0} (f_meas : Measurable f) congr 1 apply lintegral_congr_ae filter_upwards [(memℒ1_smul_of_L1_withDensity f_meas u).coeFn_toLp] with x hx - rw [hx, Pi.mul_apply] - change (‖(f x : ℝ) • u x‖₊ : ℝ≥0∞) = (f x : ℝ≥0∞) * (‖u x‖₊ : ℝ≥0∞) - simp only [nnnorm_smul, NNReal.nnnorm_eq, ENNReal.coe_mul] + rw [hx] + simp [NNReal.smul_def, enorm_smul] @[simp] theorem withDensitySMulLI_apply {f : α → ℝ≥0} (f_meas : Measurable f) @@ -1110,7 +1091,7 @@ section ENNReal theorem mem_ℒ1_toReal_of_lintegral_ne_top {f : α → ℝ≥0∞} (hfm : AEMeasurable f μ) (hfi : ∫⁻ x, f x ∂μ ≠ ∞) : Memℒp (fun x ↦ (f x).toReal) 1 μ := by - rw [Memℒp, eLpNorm_one_eq_lintegral_nnnorm] + rw [Memℒp, eLpNorm_one_eq_lintegral_enorm] exact ⟨(AEMeasurable.ennreal_toReal hfm).aestronglyMeasurable, hasFiniteIntegral_toReal_of_lintegral_ne_top hfi⟩ @@ -1193,8 +1174,8 @@ variable {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] theorem integrable_smul_const {f : α → 𝕜} {c : E} (hc : c ≠ 0) : Integrable (fun x => f x • c) μ ↔ Integrable f μ := by simp_rw [Integrable, aestronglyMeasurable_smul_const_iff (f := f) hc, and_congr_right_iff, - hasFiniteIntegral_iff_nnnorm, nnnorm_smul, ENNReal.coe_mul] - intro _; rw [lintegral_mul_const' _ _ ENNReal.coe_ne_top, ENNReal.mul_lt_top_iff] + hasFiniteIntegral_iff_enorm, enorm_smul] + intro _; rw [lintegral_mul_const' _ _ enorm_ne_top, ENNReal.mul_lt_top_iff] have : ∀ x : ℝ≥0∞, x = 0 → x < ∞ := by simp simp [hc, or_iff_left_of_imp (this _)] @@ -1295,15 +1276,13 @@ theorem Integrable.trim (hm : m ≤ m0) (hf_int : Integrable f μ') (hf : Strong refine ⟨hf.aestronglyMeasurable, ?_⟩ rw [HasFiniteIntegral, lintegral_trim hm _] · exact hf_int.2 - · exact @StronglyMeasurable.ennnorm _ m _ _ f hf + · exact @StronglyMeasurable.enorm _ m _ _ f hf theorem integrable_of_integrable_trim (hm : m ≤ m0) (hf_int : Integrable f (μ'.trim hm)) : Integrable f μ' := by obtain ⟨hf_meas_ae, hf⟩ := hf_int refine ⟨aestronglyMeasurable_of_aestronglyMeasurable_trim hm hf_meas_ae, ?_⟩ - rw [HasFiniteIntegral] at hf ⊢ - rwa [lintegral_trim_ae hm _] at hf - exact AEStronglyMeasurable.ennnorm hf_meas_ae + simpa [HasFiniteIntegral, lintegral_trim_ae hm hf_meas_ae.enorm] using hf end Trim @@ -1313,12 +1292,12 @@ variable {E : Type*} {m0 : MeasurableSpace α} [NormedAddCommGroup E] theorem integrable_of_forall_fin_meas_le' {μ : Measure α} (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (C : ℝ≥0∞) (hC : C < ∞) {f : α → E} (hf_meas : AEStronglyMeasurable f μ) - (hf : ∀ s, MeasurableSet[m] s → μ s ≠ ∞ → (∫⁻ x in s, ‖f x‖₊ ∂μ) ≤ C) : Integrable f μ := + (hf : ∀ s, MeasurableSet[m] s → μ s ≠ ∞ → ∫⁻ x in s, ‖f x‖ₑ ∂μ ≤ C) : Integrable f μ := ⟨hf_meas, (lintegral_le_of_forall_fin_meas_trim_le hm C hf).trans_lt hC⟩ theorem integrable_of_forall_fin_meas_le [SigmaFinite μ] (C : ℝ≥0∞) (hC : C < ∞) {f : α → E} (hf_meas : AEStronglyMeasurable[m] f μ) - (hf : ∀ s : Set α, MeasurableSet[m] s → μ s ≠ ∞ → (∫⁻ x in s, ‖f x‖₊ ∂μ) ≤ C) : + (hf : ∀ s : Set α, MeasurableSet[m] s → μ s ≠ ∞ → ∫⁻ x in s, ‖f x‖ₑ ∂μ ≤ C) : Integrable f μ := have : SigmaFinite (μ.trim le_rfl) := by rwa [@trim_eq_self _ m] integrable_of_forall_fin_meas_le' le_rfl C hC hf_meas hf @@ -1409,29 +1388,27 @@ theorem aemeasurable_coeFn [MeasurableSpace β] [BorelSpace β] (f : α →₁[ (Lp.stronglyMeasurable f).measurable.aemeasurable theorem edist_def (f g : α →₁[μ] β) : edist f g = ∫⁻ a, edist (f a) (g a) ∂μ := by - simp only [Lp.edist_def, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_nnnorm, Pi.sub_apply, + simp only [Lp.edist_def, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_enorm, Pi.sub_apply, one_toReal, ENNReal.rpow_one, ne_eq, not_false_eq_true, div_self, ite_false] - simp [edist_eq_coe_nnnorm_sub] + simp [edist_eq_enorm_sub] theorem dist_def (f g : α →₁[μ] β) : dist f g = (∫⁻ a, edist (f a) (g a) ∂μ).toReal := by simp_rw [dist_edist, edist_def] -theorem norm_def (f : α →₁[μ] β) : ‖f‖ = (∫⁻ a, ‖f a‖₊ ∂μ).toReal := by - simp [Lp.norm_def, eLpNorm, eLpNorm'_eq_lintegral_nnnorm] +theorem norm_def (f : α →₁[μ] β) : ‖f‖ = (∫⁻ a, ‖f a‖ₑ ∂μ).toReal := by + simp [Lp.norm_def, eLpNorm, eLpNorm'_eq_lintegral_enorm] /-- Computing the norm of a difference between two L¹-functions. Note that this is not a special case of `norm_def` since `(f - g) x` and `f x - g x` are not equal (but only a.e.-equal). -/ -theorem norm_sub_eq_lintegral (f g : α →₁[μ] β) : - ‖f - g‖ = (∫⁻ x, (‖f x - g x‖₊ : ℝ≥0∞) ∂μ).toReal := by +theorem norm_sub_eq_lintegral (f g : α →₁[μ] β) : ‖f - g‖ = (∫⁻ x, ‖f x - g x‖ₑ ∂μ).toReal := by rw [norm_def] congr 1 rw [lintegral_congr_ae] filter_upwards [Lp.coeFn_sub f g] with _ ha simp only [ha, Pi.sub_apply] -theorem ofReal_norm_eq_lintegral (f : α →₁[μ] β) : - ENNReal.ofReal ‖f‖ = ∫⁻ x, (‖f x‖₊ : ℝ≥0∞) ∂μ := by +theorem ofReal_norm_eq_lintegral (f : α →₁[μ] β) : ENNReal.ofReal ‖f‖ = ∫⁻ x, ‖f x‖ₑ ∂μ := by rw [norm_def, ENNReal.ofReal_toReal] exact ne_of_lt (hasFiniteIntegral_coeFn f) @@ -1439,8 +1416,8 @@ theorem ofReal_norm_eq_lintegral (f : α →₁[μ] β) : special case of `ofReal_norm_eq_lintegral` since `(f - g) x` and `f x - g x` are not equal (but only a.e.-equal). -/ theorem ofReal_norm_sub_eq_lintegral (f g : α →₁[μ] β) : - ENNReal.ofReal ‖f - g‖ = ∫⁻ x, (‖f x - g x‖₊ : ℝ≥0∞) ∂μ := by - simp_rw [ofReal_norm_eq_lintegral, ← edist_eq_coe_nnnorm] + ENNReal.ofReal ‖f - g‖ = ∫⁻ x, ‖f x - g x‖ₑ ∂μ := by + simp_rw [ofReal_norm_eq_lintegral, ← edist_zero_eq_enorm] apply lintegral_congr_ae filter_upwards [Lp.coeFn_sub f g] with _ ha simp only [ha, Pi.sub_apply] @@ -1488,14 +1465,13 @@ theorem toL1_sub (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) rfl theorem norm_toL1 (f : α → β) (hf : Integrable f μ) : - ‖hf.toL1 f‖ = ENNReal.toReal (∫⁻ a, edist (f a) 0 ∂μ) := by - simp only [toL1, Lp.norm_toLp, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_nnnorm, one_toReal, - ENNReal.rpow_one, ne_eq, not_false_eq_true, div_self, ite_false] - simp [edist_eq_coe_nnnorm] + ‖hf.toL1 f‖ = (∫⁻ a, edist (f a) 0 ∂μ).toReal := by + simp [toL1, Lp.norm_toLp, eLpNorm, eLpNorm'_eq_lintegral_enorm] + +theorem enorm_toL1 {f : α → β} (hf : Integrable f μ) : ‖hf.toL1 f‖ₑ = ∫⁻ a, ‖f a‖ₑ ∂μ := by + simpa [Integrable.toL1, eLpNorm, eLpNorm', enorm] using ENNReal.coe_toNNReal hf.2.ne -theorem nnnorm_toL1 {f : α → β} (hf : Integrable f μ) : - (‖hf.toL1 f‖₊ : ℝ≥0∞) = ∫⁻ a, ‖f a‖₊ ∂μ := by - simpa [Integrable.toL1, eLpNorm, eLpNorm'] using ENNReal.coe_toNNReal hf.2.ne +@[deprecated (since := "2025-01-20")] alias nnnorm_toL1 := enorm_toL1 theorem norm_toL1_eq_lintegral_norm (f : α → β) (hf : Integrable f μ) : ‖hf.toL1 f‖ = ENNReal.toReal (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) := by @@ -1504,14 +1480,14 @@ theorem norm_toL1_eq_lintegral_norm (f : α → β) (hf : Integrable f μ) : @[simp] theorem edist_toL1_toL1 (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : edist (hf.toL1 f) (hg.toL1 g) = ∫⁻ a, edist (f a) (g a) ∂μ := by - simp only [toL1, Lp.edist_toLp_toLp, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_nnnorm, + simp only [toL1, Lp.edist_toLp_toLp, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_enorm, Pi.sub_apply, one_toReal, ENNReal.rpow_one, ne_eq, not_false_eq_true, div_self, ite_false] - simp [edist_eq_coe_nnnorm_sub] + simp [edist_eq_enorm_sub] theorem edist_toL1_zero (f : α → β) (hf : Integrable f μ) : edist (hf.toL1 f) 0 = ∫⁻ a, edist (f a) 0 ∂μ := by - simp only [edist_zero_right, Lp.nnnorm_coe_ennreal, toL1_eq_mk, eLpNorm_aeeqFun] - apply eLpNorm_one_eq_lintegral_nnnorm + simp only [edist_zero_right, Lp.enorm_def, toL1_eq_mk, eLpNorm_aeeqFun] + apply eLpNorm_one_eq_lintegral_enorm variable {𝕜 : Type*} [NormedRing 𝕜] [Module 𝕜 β] [BoundedSMul 𝕜 β] @@ -1532,8 +1508,7 @@ variable {E : Type*} [NormedAddCommGroup E] {f : α → E} lemma HasFiniteIntegral.restrict (h : HasFiniteIntegral f μ) {s : Set α} : HasFiniteIntegral f (μ.restrict s) := by refine lt_of_le_of_lt ?_ h - convert lintegral_mono_set (μ := μ) (s := s) (t := univ) (f := fun x ↦ ↑‖f x‖₊) (subset_univ s) - exact Measure.restrict_univ.symm + simpa [Measure.restrict_univ] using lintegral_mono_set (subset_univ s) /-- One should usually use `MeasureTheory.Integrable.IntegrableOn` instead. -/ lemma Integrable.restrict (hf : Integrable f μ) {s : Set α} : Integrable f (μ.restrict s) := diff --git a/Mathlib/MeasureTheory/Function/L2Space.lean b/Mathlib/MeasureTheory/Function/L2Space.lean index 3594c9e9b9d38..878c21c3d7fa3 100644 --- a/Mathlib/MeasureTheory/Function/L2Space.lean +++ b/Mathlib/MeasureTheory/Function/L2Space.lean @@ -156,7 +156,7 @@ theorem integral_inner_eq_sq_eLpNorm (f : α →₂[μ] E) : ext1 x have h_two : (2 : ℝ) = ((2 : ℕ) : ℝ) := by simp rw [← Real.rpow_natCast _ 2, ← h_two, ← - ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) zero_le_two, ofReal_norm_eq_coe_nnnorm] + ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) zero_le_two, ofReal_norm_eq_enorm] norm_cast @[deprecated (since := "2024-07-27")] @@ -169,7 +169,7 @@ private theorem norm_sq_eq_inner' (f : α →₂[μ] E) : ‖f‖ ^ 2 = RCLike.r · rw [← ENNReal.rpow_natCast, eLpNorm_eq_eLpNorm' two_ne_zero ENNReal.two_ne_top, eLpNorm', ← ENNReal.rpow_mul, one_div, h_two] simp [enorm_eq_nnnorm] - · refine (lintegral_rpow_nnnorm_lt_top_of_eLpNorm'_lt_top zero_lt_two ?_).ne + · refine (lintegral_rpow_enorm_lt_top_of_eLpNorm'_lt_top zero_lt_two ?_).ne rw [← h_two, ← eLpNorm_eq_eLpNorm' two_ne_zero ENNReal.two_ne_top] exact Lp.eLpNorm_lt_top f diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean index a2019826e26f5..34188e7455aaa 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean @@ -70,18 +70,22 @@ this quantity is finite -/ def eLpNorm' {_ : MeasurableSpace α} (f : α → ε) (q : ℝ) (μ : Measure α) : ℝ≥0∞ := (∫⁻ a, ‖f a‖ₑ ^ q ∂μ) ^ (1 / q) -lemma eLpNorm'_eq_lintegral_nnnorm {_ : MeasurableSpace α} (f : α → F) (q : ℝ) (μ : Measure α) : - eLpNorm' f q μ = (∫⁻ a, ‖f a‖₊ ^ q ∂μ) ^ (1 / q) := +lemma eLpNorm'_eq_lintegral_enorm {_ : MeasurableSpace α} (f : α → F) (q : ℝ) (μ : Measure α) : + eLpNorm' f q μ = (∫⁻ a, ‖f a‖ₑ ^ q ∂μ) ^ (1 / q) := rfl +@[deprecated (since := "2025-01-17")] +alias eLpNorm'_eq_lintegral_nnnorm := eLpNorm'_eq_lintegral_enorm + /-- seminorm for `ℒ∞`, equal to the essential supremum of `‖f‖`. -/ def eLpNormEssSup {_ : MeasurableSpace α} (f : α → ε) (μ : Measure α) := essSup (fun x => ‖f x‖ₑ) μ -lemma eLpNormEssSup_eq_essSup_nnnorm {_ : MeasurableSpace α} (f : α → F) (μ : Measure α) : - eLpNormEssSup f μ = essSup (fun x => (‖f x‖₊ : ℝ≥0∞)) μ := - rfl +lemma eLpNormEssSup_eq_essSup_enorm {_ : MeasurableSpace α} (f : α → F) (μ : Measure α) : + eLpNormEssSup f μ = essSup (‖f ·‖ₑ) μ := rfl +@[deprecated (since := "2025-01-17")] +alias eLpNormEssSup_eq_essSup_nnnorm := eLpNormEssSup_eq_essSup_enorm /-- `ℒp` seminorm, equal to `0` for `p=0`, to `(∫ ‖f a‖^p ∂μ) ^ (1/p)` for `0 < p < ∞` and to `essSup ‖f‖ μ` for `p = ∞`. -/ @@ -102,25 +106,31 @@ lemma eLpNorm_nnreal_eq_eLpNorm' {f : α → F} {p : ℝ≥0} (hp : p ≠ 0) : @[deprecated (since := "2024-07-27")] alias snorm_nnreal_eq_snorm' := eLpNorm_nnreal_eq_eLpNorm' -theorem eLpNorm_eq_lintegral_rpow_nnnorm (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) {f : α → F} : - eLpNorm f p μ = (∫⁻ x, (‖f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) ^ (1 / p.toReal) := by - rw [eLpNorm_eq_eLpNorm' hp_ne_zero hp_ne_top, eLpNorm'_eq_lintegral_nnnorm] +theorem eLpNorm_eq_lintegral_rpow_enorm (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) {f : α → F} : + eLpNorm f p μ = (∫⁻ x, ‖f x‖ₑ ^ p.toReal ∂μ) ^ (1 / p.toReal) := by + rw [eLpNorm_eq_eLpNorm' hp_ne_zero hp_ne_top, eLpNorm'_eq_lintegral_enorm] @[deprecated (since := "2024-07-27")] -alias snorm_eq_lintegral_rpow_nnnorm := eLpNorm_eq_lintegral_rpow_nnnorm +alias snorm_eq_lintegral_rpow_nnnorm := eLpNorm_eq_lintegral_rpow_enorm + +@[deprecated (since := "2025-01-17")] +alias eLpNorm_eq_lintegral_rpow_nnnorm := eLpNorm_eq_lintegral_rpow_enorm lemma eLpNorm_nnreal_eq_lintegral {f : α → F} {p : ℝ≥0} (hp : p ≠ 0) : - eLpNorm f p μ = (∫⁻ x, ‖f x‖₊ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ)) := + eLpNorm f p μ = (∫⁻ x, ‖f x‖ₑ ^ (p : ℝ) ∂μ) ^ (1 / (p : ℝ)) := eLpNorm_nnreal_eq_eLpNorm' hp @[deprecated (since := "2024-07-27")] alias snorm_nnreal_eq_lintegral := eLpNorm_nnreal_eq_lintegral -theorem eLpNorm_one_eq_lintegral_nnnorm {f : α → F} : eLpNorm f 1 μ = ∫⁻ x, ‖f x‖₊ ∂μ := by - simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm one_ne_zero ENNReal.coe_ne_top, ENNReal.one_toReal, +theorem eLpNorm_one_eq_lintegral_enorm {f : α → F} : eLpNorm f 1 μ = ∫⁻ x, ‖f x‖ₑ ∂μ := by + simp_rw [eLpNorm_eq_lintegral_rpow_enorm one_ne_zero ENNReal.coe_ne_top, ENNReal.one_toReal, one_div_one, ENNReal.rpow_one] +@[deprecated (since := "2025-01-17")] +alias eLpNorm_one_eq_lintegral_nnnorm := eLpNorm_one_eq_lintegral_enorm + @[deprecated (since := "2024-07-27")] -alias snorm_one_eq_lintegral_nnnorm := eLpNorm_one_eq_lintegral_nnnorm +alias snorm_one_eq_lintegral_nnnorm := eLpNorm_one_eq_lintegral_enorm @[simp] theorem eLpNorm_exponent_top {f : α → F} : eLpNorm f ∞ μ = eLpNormEssSup f μ := by simp [eLpNorm] @@ -138,18 +148,21 @@ theorem Memℒp.aestronglyMeasurable {f : α → E} {p : ℝ≥0∞} (h : Memℒ AEStronglyMeasurable f μ := h.1 -theorem lintegral_rpow_nnnorm_eq_rpow_eLpNorm' {f : α → F} (hq0_lt : 0 < q) : - ∫⁻ a, (‖f a‖₊ : ℝ≥0∞) ^ q ∂μ = eLpNorm' f q μ ^ q := by - rw [eLpNorm'_eq_lintegral_nnnorm, ← ENNReal.rpow_mul, one_div, inv_mul_cancel₀, ENNReal.rpow_one] - exact (ne_of_lt hq0_lt).symm +theorem lintegral_rpow_enorm_eq_rpow_eLpNorm' {f : α → F} (hq0_lt : 0 < q) : + ∫⁻ a, ‖f a‖ₑ ^ q ∂μ = eLpNorm' f q μ ^ q := by + rw [eLpNorm'_eq_lintegral_enorm, ← ENNReal.rpow_mul, one_div, inv_mul_cancel₀, ENNReal.rpow_one] + exact hq0_lt.ne' + +@[deprecated (since := "2025-01-17")] +alias lintegral_rpow_nnnorm_eq_rpow_eLpNorm' := lintegral_rpow_enorm_eq_rpow_eLpNorm' @[deprecated (since := "2024-07-27")] -alias lintegral_rpow_nnnorm_eq_rpow_snorm' := lintegral_rpow_nnnorm_eq_rpow_eLpNorm' +alias lintegral_rpow_nnnorm_eq_rpow_snorm' := lintegral_rpow_enorm_eq_rpow_eLpNorm' lemma eLpNorm_nnreal_pow_eq_lintegral {f : α → F} {p : ℝ≥0} (hp : p ≠ 0) : - eLpNorm f p μ ^ (p : ℝ) = ∫⁻ x, ‖f x‖₊ ^ (p : ℝ) ∂μ := by + eLpNorm f p μ ^ (p : ℝ) = ∫⁻ x, ‖f x‖ₑ ^ (p : ℝ) ∂μ := by simp [eLpNorm_eq_eLpNorm' (by exact_mod_cast hp) ENNReal.coe_ne_top, - lintegral_rpow_nnnorm_eq_rpow_eLpNorm' ((NNReal.coe_pos.trans pos_iff_ne_zero).mpr hp)] + lintegral_rpow_enorm_eq_rpow_eLpNorm' ((NNReal.coe_pos.trans pos_iff_ne_zero).mpr hp)] @[deprecated (since := "2024-07-27")] alias snorm_nnreal_pow_eq_lintegral := eLpNorm_nnreal_pow_eq_lintegral @@ -170,31 +183,39 @@ theorem Memℒp.eLpNorm_ne_top {f : α → E} (hfp : Memℒp f p μ) : eLpNorm f @[deprecated (since := "2024-07-27")] alias Memℒp.snorm_ne_top := Memℒp.eLpNorm_ne_top -theorem lintegral_rpow_nnnorm_lt_top_of_eLpNorm'_lt_top {f : α → F} (hq0_lt : 0 < q) - (hfq : eLpNorm' f q μ < ∞) : (∫⁻ a, (‖f a‖₊ : ℝ≥0∞) ^ q ∂μ) < ∞ := by - rw [lintegral_rpow_nnnorm_eq_rpow_eLpNorm' hq0_lt] +theorem lintegral_rpow_enorm_lt_top_of_eLpNorm'_lt_top {f : α → F} (hq0_lt : 0 < q) + (hfq : eLpNorm' f q μ < ∞) : ∫⁻ a, ‖f a‖ₑ ^ q ∂μ < ∞ := by + rw [lintegral_rpow_enorm_eq_rpow_eLpNorm' hq0_lt] exact ENNReal.rpow_lt_top_of_nonneg (le_of_lt hq0_lt) (ne_of_lt hfq) @[deprecated (since := "2024-07-27")] alias lintegral_rpow_nnnorm_lt_top_of_snorm'_lt_top := - lintegral_rpow_nnnorm_lt_top_of_eLpNorm'_lt_top + lintegral_rpow_enorm_lt_top_of_eLpNorm'_lt_top + +@[deprecated (since := "2025-01-17")] +alias lintegral_rpow_nnnorm_lt_top_of_eLpNorm'_lt_top' := + lintegral_rpow_enorm_lt_top_of_eLpNorm'_lt_top -theorem lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top {f : α → F} (hp_ne_zero : p ≠ 0) - (hp_ne_top : p ≠ ∞) (hfp : eLpNorm f p μ < ∞) : (∫⁻ a, (‖f a‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) < ∞ := by - apply lintegral_rpow_nnnorm_lt_top_of_eLpNorm'_lt_top +theorem lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top {f : α → F} (hp_ne_zero : p ≠ 0) + (hp_ne_top : p ≠ ∞) (hfp : eLpNorm f p μ < ∞) : ∫⁻ a, ‖f a‖ₑ ^ p.toReal ∂μ < ∞ := by + apply lintegral_rpow_enorm_lt_top_of_eLpNorm'_lt_top · exact ENNReal.toReal_pos hp_ne_zero hp_ne_top · simpa [eLpNorm_eq_eLpNorm' hp_ne_zero hp_ne_top] using hfp @[deprecated (since := "2024-07-27")] -alias lintegral_rpow_nnnorm_lt_top_of_snorm_lt_top := lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top +alias lintegral_rpow_nnnorm_lt_top_of_snorm_lt_top := lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top + +@[deprecated (since := "2025-01-17")] +alias lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top := + lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top theorem eLpNorm_lt_top_iff_lintegral_rpow_nnnorm_lt_top {f : α → F} (hp_ne_zero : p ≠ 0) - (hp_ne_top : p ≠ ∞) : eLpNorm f p μ < ∞ ↔ (∫⁻ a, (‖f a‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) < ∞ := - ⟨lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_ne_zero hp_ne_top, by + (hp_ne_top : p ≠ ∞) : eLpNorm f p μ < ∞ ↔ ∫⁻ a, (‖f a‖ₑ) ^ p.toReal ∂μ < ∞ := + ⟨lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top hp_ne_zero hp_ne_top, by intro h have hp' := ENNReal.toReal_pos hp_ne_zero hp_ne_top have : 0 < 1 / p.toReal := div_pos zero_lt_one hp' - simpa [eLpNorm_eq_lintegral_rpow_nnnorm hp_ne_zero hp_ne_top] using + simpa [eLpNorm_eq_lintegral_rpow_enorm hp_ne_zero hp_ne_top] using ENNReal.rpow_lt_top_of_nonneg (le_of_lt this) (ne_of_lt h)⟩ @[deprecated (since := "2024-07-27")] @@ -224,7 +245,7 @@ theorem memℒp_zero_iff_aestronglyMeasurable {f : α → E} : @[simp] theorem eLpNorm'_zero (hp0_lt : 0 < q) : eLpNorm' (0 : α → F) q μ = 0 := by - simp [eLpNorm'_eq_lintegral_nnnorm, hp0_lt] + simp [eLpNorm'_eq_lintegral_enorm, hp0_lt] @[deprecated (since := "2024-07-27")] alias snorm'_zero := eLpNorm'_zero @@ -233,16 +254,14 @@ alias snorm'_zero := eLpNorm'_zero theorem eLpNorm'_zero' (hq0_ne : q ≠ 0) (hμ : μ ≠ 0) : eLpNorm' (0 : α → F) q μ = 0 := by rcases le_or_lt 0 q with hq0 | hq_neg · exact eLpNorm'_zero (lt_of_le_of_ne hq0 hq0_ne.symm) - · simp [eLpNorm'_eq_lintegral_nnnorm, ENNReal.rpow_eq_zero_iff, hμ, hq_neg] + · simp [eLpNorm'_eq_lintegral_enorm, ENNReal.rpow_eq_zero_iff, hμ, hq_neg] @[deprecated (since := "2024-07-27")] alias snorm'_zero' := eLpNorm'_zero' @[simp] theorem eLpNormEssSup_zero : eLpNormEssSup (0 : α → F) μ = 0 := by - simp_rw [eLpNormEssSup_eq_essSup_nnnorm, Pi.zero_apply, nnnorm_zero, ENNReal.coe_zero, - ← ENNReal.bot_eq_zero] - exact essSup_const_bot + simp [eLpNormEssSup, ← bot_eq_zero', essSup_const_bot] @[deprecated (since := "2024-07-27")] alias snormEssSup_zero := eLpNormEssSup_zero @@ -320,7 +339,7 @@ section Neg @[simp] theorem eLpNorm'_neg (f : α → F) (q : ℝ) (μ : Measure α) : eLpNorm' (-f) q μ = eLpNorm' f q μ := by - simp [eLpNorm'_eq_lintegral_nnnorm] + simp [eLpNorm'_eq_lintegral_enorm] @[deprecated (since := "2024-07-27")] alias snorm'_neg := eLpNorm'_neg @@ -330,7 +349,7 @@ theorem eLpNorm_neg (f : α → F) (p : ℝ≥0∞) (μ : Measure α) : eLpNorm by_cases h0 : p = 0 · simp [h0] by_cases h_top : p = ∞ - · simp [h_top, eLpNormEssSup_eq_essSup_nnnorm] + · simp [h_top, eLpNormEssSup_eq_essSup_enorm] simp [eLpNorm_eq_eLpNorm' h0 h_top] lemma eLpNorm_sub_comm (f g : α → E) (p : ℝ≥0∞) (μ : Measure α) : @@ -350,8 +369,8 @@ end Neg section Const theorem eLpNorm'_const (c : F) (hq_pos : 0 < q) : - eLpNorm' (fun _ : α => c) q μ = (‖c‖₊ : ℝ≥0∞) * μ Set.univ ^ (1 / q) := by - rw [eLpNorm'_eq_lintegral_nnnorm, lintegral_const, + eLpNorm' (fun _ : α => c) q μ = ‖c‖ₑ * μ Set.univ ^ (1 / q) := by + rw [eLpNorm'_eq_lintegral_enorm, lintegral_const, ENNReal.mul_rpow_of_nonneg _ _ (by simp [hq_pos.le] : 0 ≤ 1 / q)] congr rw [← ENNReal.rpow_mul] @@ -362,37 +381,33 @@ theorem eLpNorm'_const (c : F) (hq_pos : 0 < q) : alias snorm'_const := eLpNorm'_const theorem eLpNorm'_const' [IsFiniteMeasure μ] (c : F) (hc_ne_zero : c ≠ 0) (hq_ne_zero : q ≠ 0) : - eLpNorm' (fun _ : α => c) q μ = (‖c‖₊ : ℝ≥0∞) * μ Set.univ ^ (1 / q) := by - rw [eLpNorm'_eq_lintegral_nnnorm, lintegral_const, + eLpNorm' (fun _ : α => c) q μ = ‖c‖ₑ * μ Set.univ ^ (1 / q) := by + rw [eLpNorm'_eq_lintegral_enorm, lintegral_const, ENNReal.mul_rpow_of_ne_top _ (measure_ne_top μ Set.univ)] · congr rw [← ENNReal.rpow_mul] suffices hp_cancel : q * (1 / q) = 1 by rw [hp_cancel, ENNReal.rpow_one] rw [one_div, mul_inv_cancel₀ hq_ne_zero] · rw [Ne, ENNReal.rpow_eq_top_iff, not_or, not_and_or, not_and_or] - constructor - · left - rwa [ENNReal.coe_eq_zero, nnnorm_eq_zero] - · exact Or.inl ENNReal.coe_ne_top + simp [hc_ne_zero] @[deprecated (since := "2024-07-27")] alias snorm'_const' := eLpNorm'_const' -theorem eLpNormEssSup_const (c : F) (hμ : μ ≠ 0) : - eLpNormEssSup (fun _ : α => c) μ = (‖c‖₊ : ℝ≥0∞) := by - rw [eLpNormEssSup_eq_essSup_nnnorm, essSup_const _ hμ] +theorem eLpNormEssSup_const (c : F) (hμ : μ ≠ 0) : eLpNormEssSup (fun _ : α => c) μ = ‖c‖ₑ := by + rw [eLpNormEssSup_eq_essSup_enorm, essSup_const _ hμ] @[deprecated (since := "2024-07-27")] alias snormEssSup_const := eLpNormEssSup_const theorem eLpNorm'_const_of_isProbabilityMeasure (c : F) (hq_pos : 0 < q) [IsProbabilityMeasure μ] : - eLpNorm' (fun _ : α => c) q μ = (‖c‖₊ : ℝ≥0∞) := by simp [eLpNorm'_const c hq_pos, measure_univ] + eLpNorm' (fun _ : α => c) q μ = ‖c‖ₑ := by simp [eLpNorm'_const c hq_pos, measure_univ] @[deprecated (since := "2024-07-27")] alias snorm'_const_of_isProbabilityMeasure := eLpNorm'_const_of_isProbabilityMeasure theorem eLpNorm_const (c : F) (h0 : p ≠ 0) (hμ : μ ≠ 0) : - eLpNorm (fun _ : α => c) p μ = (‖c‖₊ : ℝ≥0∞) * μ Set.univ ^ (1 / ENNReal.toReal p) := by + eLpNorm (fun _ : α => c) p μ = ‖c‖ₑ * μ Set.univ ^ (1 / ENNReal.toReal p) := by by_cases h_top : p = ∞ · simp [h_top, eLpNormEssSup_const c hμ] simp [eLpNorm_eq_eLpNorm' h0 h_top, eLpNorm'_const, ENNReal.toReal_pos h0 h_top] @@ -401,7 +416,7 @@ theorem eLpNorm_const (c : F) (h0 : p ≠ 0) (hμ : μ ≠ 0) : alias snorm_const := eLpNorm_const theorem eLpNorm_const' (c : F) (h0 : p ≠ 0) (h_top : p ≠ ∞) : - eLpNorm (fun _ : α => c) p μ = (‖c‖₊ : ℝ≥0∞) * μ Set.univ ^ (1 / ENNReal.toReal p) := by + eLpNorm (fun _ : α => c) p μ = ‖c‖ₑ * μ Set.univ ^ (1 / ENNReal.toReal p) := by simp [eLpNorm_eq_eLpNorm' h0 h_top, eLpNorm'_const, ENNReal.toReal_pos h0 h_top] @[deprecated (since := "2024-07-27")] @@ -416,14 +431,11 @@ theorem eLpNorm_const_lt_top_iff {p : ℝ≥0∞} {c : F} (hp_ne_zero : p ≠ 0) by_cases hc : c = 0 · simp only [hc, true_or, eq_self_iff_true, ENNReal.zero_lt_top, eLpNorm_zero'] rw [eLpNorm_const' c hp_ne_zero hp_ne_top] - by_cases hμ_top : μ Set.univ = ∞ + obtain hμ_top | hμ_top := eq_or_ne (μ .univ) ∞ · simp [hc, hμ_top, hp] rw [ENNReal.mul_lt_top_iff] - simp only [true_and, one_div, ENNReal.rpow_eq_zero_iff, hμ, false_or, or_false, - ENNReal.coe_lt_top, nnnorm_eq_zero, ENNReal.coe_eq_zero, - MeasureTheory.Measure.measure_univ_eq_zero, hp, inv_lt_zero, hc, false_and, - inv_pos, or_self_iff, hμ_top, Ne.lt_top hμ_top, iff_true] - exact ENNReal.rpow_lt_top_of_nonneg (inv_nonneg.mpr hp.le) hμ_top + simpa [hμ, hc, hμ_top, hμ_top.lt_top] using + ENNReal.rpow_lt_top_of_nonneg (inv_nonneg.mpr hp.le) hμ_top @[deprecated (since := "2024-07-27")] alias snorm_const_lt_top_iff := eLpNorm_const_lt_top_iff @@ -439,12 +451,8 @@ theorem memℒp_const (c : E) [IsFiniteMeasure μ] : Memℒp (fun _ : α => c) p refine ENNReal.rpow_lt_top_of_nonneg ?_ (measure_ne_top μ Set.univ) simp -theorem memℒp_top_const (c : E) : Memℒp (fun _ : α => c) ∞ μ := by - refine ⟨aestronglyMeasurable_const, ?_⟩ - by_cases h : μ = 0 - · simp only [h, eLpNorm_measure_zero, ENNReal.zero_lt_top] - · rw [eLpNorm_const _ ENNReal.top_ne_zero h] - simp only [ENNReal.top_toReal, div_zero, ENNReal.rpow_zero, mul_one, ENNReal.coe_lt_top] +theorem memℒp_top_const (c : E) : Memℒp (fun _ : α => c) ∞ μ := + ⟨aestronglyMeasurable_const, by by_cases h : μ = 0 <;> simp [eLpNorm_const _, h]⟩ theorem memℒp_const_iff {p : ℝ≥0∞} {c : E} (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) : Memℒp (fun _ : α => c) p μ ↔ c = 0 ∨ μ Set.univ < ∞ := by @@ -457,9 +465,10 @@ variable {f : α → F} lemma eLpNorm'_mono_nnnorm_ae {f : α → F} {g : α → G} (hq : 0 ≤ q) (h : ∀ᵐ x ∂μ, ‖f x‖₊ ≤ ‖g x‖₊) : eLpNorm' f q μ ≤ eLpNorm' g q μ := by - simp only [eLpNorm'_eq_lintegral_nnnorm] + simp only [eLpNorm'_eq_lintegral_enorm] gcongr ?_ ^ (1/q) refine lintegral_mono_ae (h.mono fun x hx => ?_) + dsimp [enorm] gcongr @[deprecated (since := "2024-07-27")] @@ -474,9 +483,8 @@ alias snorm'_mono_ae := eLpNorm'_mono_ae theorem eLpNorm'_congr_nnnorm_ae {f g : α → F} (hfg : ∀ᵐ x ∂μ, ‖f x‖₊ = ‖g x‖₊) : eLpNorm' f q μ = eLpNorm' g q μ := by - have : (fun x => (‖f x‖₊ : ℝ≥0∞) ^ q) =ᵐ[μ] fun x => (‖g x‖₊ : ℝ≥0∞) ^ q := - hfg.mono fun x hx => by simp_rw [hx] - simp only [eLpNorm'_eq_lintegral_nnnorm, lintegral_congr_ae this] + have : (‖f ·‖ₑ ^ q) =ᵐ[μ] (‖g ·‖ₑ ^ q) := hfg.mono fun x hx ↦ by simp [enorm, hx] + simp only [eLpNorm'_eq_lintegral_enorm, lintegral_congr_ae this] @[deprecated (since := "2024-07-27")] alias snorm'_congr_nnnorm_ae := eLpNorm'_congr_nnnorm_ae @@ -591,7 +599,7 @@ theorem eLpNorm_le_of_ae_nnnorm_bound {f : α → F} {C : ℝ≥0} (hfC : ∀ᵐ · simp [hp] have : ∀ᵐ x ∂μ, ‖f x‖₊ ≤ ‖(C : ℝ)‖₊ := hfC.mono fun x hx => hx.trans_eq C.nnnorm_eq.symm refine (eLpNorm_mono_ae this).trans_eq ?_ - rw [eLpNorm_const _ hp (NeZero.ne μ), C.nnnorm_eq, one_div, ENNReal.smul_def, smul_eq_mul] + rw [eLpNorm_const _ hp (NeZero.ne μ), C.enorm_eq, one_div, ENNReal.smul_def, smul_eq_mul] @[deprecated (since := "2024-07-27")] alias snorm_le_of_ae_nnnorm_bound := eLpNorm_le_of_ae_nnnorm_bound @@ -630,7 +638,7 @@ alias snorm_indicator_sub_indicator := eLpNorm_indicator_sub_indicator @[simp] theorem eLpNorm'_norm {f : α → F} : - eLpNorm' (fun a => ‖f a‖) q μ = eLpNorm' f q μ := by simp [eLpNorm'_eq_lintegral_nnnorm] + eLpNorm' (fun a => ‖f a‖) q μ = eLpNorm' f q μ := by simp [eLpNorm'_eq_lintegral_enorm] @[deprecated (since := "2024-07-27")] alias snorm'_norm := eLpNorm'_norm @@ -644,8 +652,8 @@ alias snorm_norm := eLpNorm_norm theorem eLpNorm'_norm_rpow (f : α → F) (p q : ℝ) (hq_pos : 0 < q) : eLpNorm' (fun x => ‖f x‖ ^ q) p μ = eLpNorm' f (p * q) μ ^ q := by - simp_rw [eLpNorm'_eq_lintegral_nnnorm, ← ENNReal.rpow_mul, ← one_div_mul_one_div, one_div, - mul_assoc, inv_mul_cancel₀ hq_pos.ne.symm, mul_one, ← ofReal_norm_eq_coe_nnnorm, + simp_rw [eLpNorm', ← ENNReal.rpow_mul, ← one_div_mul_one_div, one_div, + mul_assoc, inv_mul_cancel₀ hq_pos.ne.symm, mul_one, ← ofReal_norm_eq_enorm, Real.norm_eq_abs, abs_eq_self.mpr (Real.rpow_nonneg (norm_nonneg _) _), mul_comm p, ← ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) hq_pos.le, ENNReal.rpow_mul] @@ -658,22 +666,17 @@ theorem eLpNorm_norm_rpow (f : α → F) (hq_pos : 0 < q) : · simp [h0, ENNReal.zero_rpow_of_pos hq_pos] by_cases hp_top : p = ∞ · simp only [hp_top, eLpNorm_exponent_top, ENNReal.top_mul', hq_pos.not_le, - ENNReal.ofReal_eq_zero, if_false, eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_nnnorm] - have h_rpow : - essSup (fun x : α => (‖‖f x‖ ^ q‖₊ : ℝ≥0∞)) μ = - essSup (fun x : α => (‖f x‖₊ : ℝ≥0∞) ^ q) μ := by + ENNReal.ofReal_eq_zero, if_false, eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_enorm] + have h_rpow : essSup (‖‖f ·‖ ^ q‖ₑ) μ = essSup (‖f ·‖ₑ ^ q) μ := by congr ext1 x - conv_rhs => rw [← nnnorm_norm] - rw [← ENNReal.coe_rpow_of_nonneg _ hq_pos.le, ENNReal.coe_inj] - ext - push_cast - rw [Real.norm_rpow_of_nonneg (norm_nonneg _)] + conv_rhs => rw [← enorm_norm] + rw [← Real.enorm_rpow_of_nonneg (norm_nonneg _) hq_pos.le] rw [h_rpow] have h_rpow_mono := ENNReal.strictMono_rpow_of_pos hq_pos have h_rpow_surj := (ENNReal.rpow_left_bijective hq_pos.ne.symm).2 let iso := h_rpow_mono.orderIsoOfSurjective _ h_rpow_surj - exact (iso.essSup_apply (fun x => (‖f x‖₊ : ℝ≥0∞)) μ).symm + exact (iso.essSup_apply (fun x => ‖f x‖ₑ) μ).symm rw [eLpNorm_eq_eLpNorm' h0 hp_top, eLpNorm_eq_eLpNorm' _ _] swap · refine mul_ne_zero h0 ?_ @@ -774,15 +777,14 @@ lemma eLpNorm_indicator_eq_eLpNorm_restrict (hs : MeasurableSet s) : by_cases hp_zero : p = 0 · simp only [hp_zero, eLpNorm_exponent_zero] by_cases hp_top : p = ∞ - · simp_rw [hp_top, eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_nnnorm, - nnnorm_indicator_eq_indicator_nnnorm, ENNReal.coe_indicator, - ENNReal.essSup_indicator_eq_essSup_restrict hs] - simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_zero hp_top] - suffices (∫⁻ x, (‖s.indicator f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) = - ∫⁻ x in s, (‖f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ by rw [this] + · simp_rw [hp_top, eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_enorm, + enorm_indicator_eq_indicator_enorm, ENNReal.essSup_indicator_eq_essSup_restrict hs] + simp_rw [eLpNorm_eq_lintegral_rpow_enorm hp_zero hp_top] + suffices (∫⁻ x, (‖s.indicator f x‖ₑ) ^ p.toReal ∂μ) = + ∫⁻ x in s, ‖f x‖ₑ ^ p.toReal ∂μ by rw [this] rw [← lintegral_indicator hs] congr - simp_rw [nnnorm_indicator_eq_indicator_nnnorm, ENNReal.coe_indicator] + simp_rw [enorm_indicator_eq_indicator_enorm] have h_zero : (fun x => x ^ p.toReal) (0 : ℝ≥0∞) = 0 := by simp [ENNReal.toReal_pos hp_zero hp_top] -- Porting note: The implicit argument should be specified because the elaborator can't deal with @@ -819,14 +821,14 @@ lemma eLpNormEssSup_indicator_le (s : Set α) (f : α → G) : exact Set.indicator_le_self s _ x lemma eLpNormEssSup_indicator_const_le (s : Set α) (c : G) : - eLpNormEssSup (s.indicator fun _ : α => c) μ ≤ ‖c‖₊ := by + eLpNormEssSup (s.indicator fun _ : α => c) μ ≤ ‖c‖ₑ := by by_cases hμ0 : μ = 0 · rw [hμ0, eLpNormEssSup_measure_zero] exact zero_le _ · exact (eLpNormEssSup_indicator_le s fun _ => c).trans (eLpNormEssSup_const c hμ0).le lemma eLpNormEssSup_indicator_const_eq (s : Set α) (c : G) (hμs : μ s ≠ 0) : - eLpNormEssSup (s.indicator fun _ : α => c) μ = ‖c‖₊ := by + eLpNormEssSup (s.indicator fun _ : α => c) μ = ‖c‖ₑ := by refine le_antisymm (eLpNormEssSup_indicator_const_le s c) ?_ by_contra! h have h' := ae_iff.mp (ae_lt_of_essSup_lt h) @@ -835,33 +837,33 @@ lemma eLpNormEssSup_indicator_const_eq (s : Set α) (c : G) (hμs : μ s ≠ 0) rw [Set.mem_setOf_eq, Set.indicator_of_mem hx_mem, enorm_eq_nnnorm] lemma eLpNorm_indicator_const₀ (hs : NullMeasurableSet s μ) (hp : p ≠ 0) (hp_top : p ≠ ∞) : - eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := + eLpNorm (s.indicator fun _ => c) p μ = ‖c‖ₑ * μ s ^ (1 / p.toReal) := have hp_pos : 0 < p.toReal := ENNReal.toReal_pos hp hp_top calc eLpNorm (s.indicator fun _ => c) p μ - = (∫⁻ x, ((‖(s.indicator fun _ ↦ c) x‖₊ : ℝ≥0∞) ^ p.toReal) ∂μ) ^ (1 / p.toReal) := - eLpNorm_eq_lintegral_rpow_nnnorm hp hp_top - _ = (∫⁻ x, (s.indicator fun _ ↦ (‖c‖₊ : ℝ≥0∞) ^ p.toReal) x ∂μ) ^ (1 / p.toReal) := by + = (∫⁻ x, (‖(s.indicator fun _ ↦ c) x‖ₑ ^ p.toReal) ∂μ) ^ (1 / p.toReal) := + eLpNorm_eq_lintegral_rpow_enorm hp hp_top + _ = (∫⁻ x, (s.indicator fun _ ↦ ‖c‖ₑ ^ p.toReal) x ∂μ) ^ (1 / p.toReal) := by congr 2 - refine (Set.comp_indicator_const c (fun x ↦ (‖x‖₊ : ℝ≥0∞) ^ p.toReal) ?_) + refine (Set.comp_indicator_const c (fun x ↦ (‖x‖ₑ) ^ p.toReal) ?_) simp [hp_pos] - _ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by + _ = ‖c‖ₑ * μ s ^ (1 / p.toReal) := by rw [lintegral_indicator_const₀ hs, ENNReal.mul_rpow_of_nonneg, ← ENNReal.rpow_mul, mul_one_div_cancel hp_pos.ne', ENNReal.rpow_one] positivity lemma eLpNorm_indicator_const (hs : MeasurableSet s) (hp : p ≠ 0) (hp_top : p ≠ ∞) : - eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := + eLpNorm (s.indicator fun _ => c) p μ = ‖c‖ₑ * μ s ^ (1 / p.toReal) := eLpNorm_indicator_const₀ hs.nullMeasurableSet hp hp_top lemma eLpNorm_indicator_const' (hs : MeasurableSet s) (hμs : μ s ≠ 0) (hp : p ≠ 0) : - eLpNorm (s.indicator fun _ => c) p μ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by + eLpNorm (s.indicator fun _ => c) p μ = ‖c‖ₑ * μ s ^ (1 / p.toReal) := by by_cases hp_top : p = ∞ · simp [hp_top, eLpNormEssSup_indicator_const_eq s c hμs] · exact eLpNorm_indicator_const hs hp hp_top lemma eLpNorm_indicator_const_le (c : G) (p : ℝ≥0∞) : - eLpNorm (s.indicator fun _ => c) p μ ≤ ‖c‖₊ * μ s ^ (1 / p.toReal) := by + eLpNorm (s.indicator fun _ => c) p μ ≤ ‖c‖ₑ * μ s ^ (1 / p.toReal) := by obtain rfl | hp := eq_or_ne p 0 · simp only [eLpNorm_exponent_zero, zero_le'] obtain rfl | h'p := eq_or_ne p ∞ @@ -872,9 +874,9 @@ lemma eLpNorm_indicator_const_le (c : G) (p : ℝ≥0∞) : calc eLpNorm (s.indicator fun _ => c) p μ ≤ eLpNorm (t.indicator fun _ => c) p μ := eLpNorm_mono (norm_indicator_le_of_subset (subset_toMeasurable _ _) _) - _ = ‖c‖₊ * μ t ^ (1 / p.toReal) := + _ = ‖c‖ₑ * μ t ^ (1 / p.toReal) := eLpNorm_indicator_const (measurableSet_toMeasurable ..) hp h'p - _ = ‖c‖₊ * μ s ^ (1 / p.toReal) := by rw [measure_toMeasurable] + _ = ‖c‖ₑ * μ s ^ (1 / p.toReal) := by rw [measure_toMeasurable] lemma Memℒp.indicator (hs : MeasurableSet s) (hf : Memℒp f p μ) : Memℒp (s.indicator f) p μ := ⟨hf.aestronglyMeasurable.indicator hs, lt_of_le_of_lt (eLpNorm_indicator_le f) hf.eLpNorm_lt_top⟩ @@ -916,18 +918,16 @@ protected lemma Memℒp.piecewise [DecidablePred (· ∈ s)] {g} (hs : Measurabl rw [eLpNorm_lt_top_iff_lintegral_rpow_nnnorm_lt_top hp_zero hp_top, ← lintegral_add_compl _ hs, ENNReal.add_lt_top] constructor - · have h : ∀ᵐ x ∂μ, x ∈ s → - (‖Set.piecewise s f g x‖₊ : ℝ≥0∞) ^ p.toReal = (‖f x‖₊ : ℝ≥0∞) ^ p.toReal := by + · have h : ∀ᵐ x ∂μ, x ∈ s → ‖Set.piecewise s f g x‖ₑ ^ p.toReal = ‖f x‖ₑ ^ p.toReal := by filter_upwards with a ha using by simp [ha] rw [setLIntegral_congr_fun hs h] - exact lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hf.2 - · have h : ∀ᵐ x ∂μ, x ∈ sᶜ → - (‖Set.piecewise s f g x‖₊ : ℝ≥0∞) ^ p.toReal = (‖g x‖₊ : ℝ≥0∞) ^ p.toReal := by + exact lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hf.2 + · have h : ∀ᵐ x ∂μ, x ∈ sᶜ → ‖Set.piecewise s f g x‖ₑ ^ p.toReal = ‖g x‖ₑ ^ p.toReal := by filter_upwards with a ha have ha' : a ∉ s := ha simp [ha'] rw [setLIntegral_congr_fun hs.compl h] - exact lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hg.2 + exact lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top hp_zero hp_top hg.2 end Indicator @@ -938,12 +938,9 @@ theorem eLpNorm_restrict_eq_of_support_subset {s : Set α} {f : α → F} (hsf : by_cases hp0 : p = 0 · simp [hp0] by_cases hp_top : p = ∞ - · simp only [hp_top, eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_nnnorm] - apply ENNReal.essSup_restrict_eq_of_support_subset - apply Function.support_subset_iff.2 (fun x hx ↦ ?_) - simp only [ne_eq, ENNReal.coe_eq_zero, nnnorm_eq_zero] at hx - exact Function.support_subset_iff.1 hsf x hx - · simp_rw [eLpNorm_eq_eLpNorm' hp0 hp_top, eLpNorm'_eq_lintegral_nnnorm] + · simp only [hp_top, eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_enorm] + exact ENNReal.essSup_restrict_eq_of_support_subset fun x hx ↦ hsf <| enorm_ne_zero.1 hx + · simp_rw [eLpNorm_eq_eLpNorm' hp0 hp_top, eLpNorm'_eq_lintegral_enorm] congr 1 apply setLIntegral_eq_of_support_subset have : ¬(p.toReal ≤ 0) := by simpa only [not_le] using ENNReal.toReal_pos hp0 hp_top @@ -1047,7 +1044,7 @@ theorem Memℒp.smul_measure {f : α → E} {c : ℝ≥0∞} (hf : Memℒp f p theorem eLpNorm_one_add_measure (f : α → F) (μ ν : Measure α) : eLpNorm f 1 (μ + ν) = eLpNorm f 1 μ + eLpNorm f 1 ν := by - simp_rw [eLpNorm_one_eq_lintegral_nnnorm] + simp_rw [eLpNorm_one_eq_lintegral_enorm] rw [lintegral_add_measure _ μ ν] @[deprecated (since := "2024-07-27")] @@ -1067,11 +1064,11 @@ theorem eLpNorm_le_add_measure_left (f : α → F) (μ ν : Measure α) {p : ℝ @[deprecated (since := "2024-07-27")] alias snorm_le_add_measure_left := eLpNorm_le_add_measure_left -lemma eLpNormEssSup_eq_iSup (hμ : ∀ a, μ {a} ≠ 0) (f : α → E) : eLpNormEssSup f μ = ⨆ a, ↑‖f a‖₊ := +lemma eLpNormEssSup_eq_iSup (hμ : ∀ a, μ {a} ≠ 0) (f : α → E) : eLpNormEssSup f μ = ⨆ a, ‖f a‖ₑ := essSup_eq_iSup hμ _ @[simp] lemma eLpNormEssSup_count [MeasurableSingletonClass α] (f : α → E) : - eLpNormEssSup f .count = ⨆ a, ↑‖f a‖₊ := essSup_count _ + eLpNormEssSup f .count = ⨆ a, ‖f a‖ₑ := essSup_count _ theorem Memℒp.left_of_add_measure {f : α → E} (h : Memℒp f p (μ + ν)) : Memℒp f p μ := h.mono_measure <| Measure.le_add_right <| le_refl _ @@ -1101,22 +1098,12 @@ alias snorm'_eq_zero_of_ae_zero' := eLpNorm'_eq_zero_of_ae_zero' theorem ae_eq_zero_of_eLpNorm'_eq_zero {f : α → E} (hq0 : 0 ≤ q) (hf : AEStronglyMeasurable f μ) (h : eLpNorm' f q μ = 0) : f =ᵐ[μ] 0 := by - rw [eLpNorm'_eq_lintegral_nnnorm, ENNReal.rpow_eq_zero_iff] at h - cases h with - | inl h => - rw [lintegral_eq_zero_iff' (hf.ennnorm.pow_const q)] at h - refine h.left.mono fun x hx => ?_ - rw [Pi.zero_apply, ENNReal.rpow_eq_zero_iff] at hx - cases hx with - | inl hx => - cases' hx with hx _ - rwa [← ENNReal.coe_zero, ENNReal.coe_inj, nnnorm_eq_zero] at hx - | inr hx => - exact absurd hx.left ENNReal.coe_ne_top - | inr h => - exfalso - rw [one_div, inv_lt_zero] at h - exact hq0.not_lt h.right + simp only [eLpNorm'_eq_lintegral_enorm, lintegral_eq_zero_iff' (hf.enorm.pow_const q), one_div, + ENNReal.rpow_eq_zero_iff, inv_pos, inv_neg'', hq0.not_lt, and_false, or_false] at h + refine h.left.mono fun x hx ↦ ?_ + simp only [Pi.zero_apply, ENNReal.rpow_eq_zero_iff, enorm_eq_zero, enorm_ne_top, false_and, + or_false] at hx + exact hx.1 @[deprecated (since := "2024-07-27")] alias ae_eq_zero_of_snorm'_eq_zero := ae_eq_zero_of_eLpNorm'_eq_zero @@ -1129,15 +1116,15 @@ theorem eLpNorm'_eq_zero_iff (hq0_lt : 0 < q) {f : α → E} (hf : AEStronglyMea alias snorm'_eq_zero_iff := eLpNorm'_eq_zero_iff theorem coe_nnnorm_ae_le_eLpNormEssSup {_ : MeasurableSpace α} (f : α → F) (μ : Measure α) : - ∀ᵐ x ∂μ, (‖f x‖₊ : ℝ≥0∞) ≤ eLpNormEssSup f μ := - ENNReal.ae_le_essSup fun x => (‖f x‖₊ : ℝ≥0∞) + ∀ᵐ x ∂μ, ‖f x‖ₑ ≤ eLpNormEssSup f μ := + ENNReal.ae_le_essSup fun x => ‖f x‖ₑ @[deprecated (since := "2024-07-27")] alias coe_nnnorm_ae_le_snormEssSup := coe_nnnorm_ae_le_eLpNormEssSup @[simp] theorem eLpNormEssSup_eq_zero_iff {f : α → F} : eLpNormEssSup f μ = 0 ↔ f =ᵐ[μ] 0 := by - simp [EventuallyEq, eLpNormEssSup_eq_essSup_nnnorm] + simp [EventuallyEq, eLpNormEssSup_eq_essSup_enorm] @[deprecated (since := "2024-07-27")] alias snormEssSup_eq_zero_iff := eLpNormEssSup_eq_zero_iff @@ -1156,7 +1143,7 @@ theorem eLpNorm_eq_zero_of_ae_zero {f : α → E} (hf : f =ᵐ[μ] 0) : eLpNorm rw [← eLpNorm_zero (p := p) (μ := μ) (α := α) (F := E)] exact eLpNorm_congr_ae hf -theorem ae_le_eLpNormEssSup {f : α → F} : ∀ᵐ y ∂μ, ‖f y‖₊ ≤ eLpNormEssSup f μ := +theorem ae_le_eLpNormEssSup {f : α → F} : ∀ᵐ y ∂μ, ‖f y‖ₑ ≤ eLpNormEssSup f μ := ae_le_essSup @[deprecated (since := "2024-07-27")] @@ -1168,7 +1155,7 @@ lemma eLpNormEssSup_lt_top_iff_isBoundedUnder : simp_rw [← ENNReal.coe_le_coe, ENNReal.coe_toNNReal h.ne]; exact ae_le_eLpNormEssSup⟩ mpr := by rintro ⟨C, hC⟩; exact eLpNormEssSup_lt_top_of_ae_nnnorm_bound (C := C) hC -theorem meas_eLpNormEssSup_lt {f : α → F} : μ { y | eLpNormEssSup f μ < ‖f y‖₊ } = 0 := +theorem meas_eLpNormEssSup_lt {f : α → F} : μ { y | eLpNormEssSup f μ < ‖f y‖ₑ } = 0 := meas_essSup_lt @[deprecated (since := "2024-07-27")] @@ -1182,7 +1169,7 @@ lemma eLpNorm_lt_top_of_finite [Finite α] [IsFiniteMeasure μ] : eLpNorm f p μ exact .le_of_finite rw [eLpNorm_lt_top_iff_lintegral_rpow_nnnorm_lt_top hp₀ hp] refine IsFiniteMeasure.lintegral_lt_top_of_bounded_to_ennreal μ ?_ - simp_rw [← ENNReal.coe_rpow_of_nonneg _ ENNReal.toReal_nonneg] + simp_rw [enorm, ← ENNReal.coe_rpow_of_nonneg _ ENNReal.toReal_nonneg] norm_cast exact Finite.exists_le _ @@ -1205,7 +1192,7 @@ variable {β : Type*} {mβ : MeasurableSpace β} {f : α → β} {g : β → E} theorem eLpNormEssSup_map_measure (hg : AEStronglyMeasurable g (Measure.map f μ)) (hf : AEMeasurable f μ) : eLpNormEssSup g (Measure.map f μ) = eLpNormEssSup (g ∘ f) μ := - essSup_map_measure hg.ennnorm hf + essSup_map_measure hg.enorm hf @[deprecated (since := "2024-07-27")] alias snormEssSup_map_measure := eLpNormEssSup_map_measure @@ -1217,8 +1204,8 @@ theorem eLpNorm_map_measure (hg : AEStronglyMeasurable g (Measure.map f μ)) by_cases hp_top : p = ∞ · simp_rw [hp_top, eLpNorm_exponent_top] exact eLpNormEssSup_map_measure hg hf - simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_zero hp_top] - rw [lintegral_map' (hg.ennnorm.pow_const p.toReal) hf] + simp_rw [eLpNorm_eq_lintegral_rpow_enorm hp_zero hp_top] + rw [lintegral_map' (hg.enorm.pow_const p.toReal) hf] rfl @[deprecated (since := "2024-07-27")] @@ -1267,7 +1254,7 @@ theorem _root_.MeasurableEmbedding.eLpNorm_map_measure {g : β → F} (hf : Meas by_cases hp : p = ∞ · simp_rw [hp, eLpNorm_exponent_top] exact hf.essSup_map_measure - · simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_zero hp] + · simp_rw [eLpNorm_eq_lintegral_rpow_enorm hp_zero hp] rw [hf.lintegral_map] rfl @@ -1289,10 +1276,10 @@ section Monotonicity theorem eLpNorm'_le_nnreal_smul_eLpNorm'_of_ae_le_mul {f : α → F} {g : α → G} {c : ℝ≥0} (h : ∀ᵐ x ∂μ, ‖f x‖₊ ≤ c * ‖g x‖₊) {p : ℝ} (hp : 0 < p) : eLpNorm' f p μ ≤ c • eLpNorm' g p μ := by - simp_rw [eLpNorm'_eq_lintegral_nnnorm] + simp_rw [eLpNorm'_eq_lintegral_enorm] rw [← ENNReal.rpow_le_rpow_iff hp, ENNReal.smul_def, smul_eq_mul, ENNReal.mul_rpow_of_nonneg _ _ hp.le] - simp_rw [← ENNReal.rpow_mul, one_div, inv_mul_cancel₀ hp.ne.symm, ENNReal.rpow_one, + simp_rw [← ENNReal.rpow_mul, one_div, inv_mul_cancel₀ hp.ne.symm, ENNReal.rpow_one, enorm, ← ENNReal.coe_rpow_of_nonneg _ hp.le, ← lintegral_const_mul' _ _ ENNReal.coe_ne_top, ← ENNReal.coe_mul] apply lintegral_mono_ae @@ -1305,10 +1292,10 @@ alias snorm'_le_nnreal_smul_snorm'_of_ae_le_mul := eLpNorm'_le_nnreal_smul_eLpNo theorem eLpNormEssSup_le_nnreal_smul_eLpNormEssSup_of_ae_le_mul {f : α → F} {g : α → G} {c : ℝ≥0} (h : ∀ᵐ x ∂μ, ‖f x‖₊ ≤ c * ‖g x‖₊) : eLpNormEssSup f μ ≤ c • eLpNormEssSup g μ := calc - essSup (fun x => (‖f x‖₊ : ℝ≥0∞)) μ ≤ essSup (fun x => (↑(c * ‖g x‖₊) : ℝ≥0∞)) μ := + essSup (‖f ·‖ₑ) μ ≤ essSup (fun x => (↑(c * ‖g x‖₊) : ℝ≥0∞)) μ := essSup_mono_ae <| h.mono fun _ hx => ENNReal.coe_le_coe.mpr hx - _ = essSup (fun x => (c * ‖g x‖₊ : ℝ≥0∞)) μ := by simp_rw [ENNReal.coe_mul] - _ = c • essSup (fun x => (‖g x‖₊ : ℝ≥0∞)) μ := ENNReal.essSup_const_mul + _ = essSup (c * ‖g ·‖ₑ) μ := by simp_rw [ENNReal.coe_mul, enorm] + _ = c • essSup (‖g ·‖ₑ) μ := ENNReal.essSup_const_mul @[deprecated (since := "2024-07-27")] alias snormEssSup_le_nnreal_smul_snormEssSup_of_ae_le_mul := @@ -1384,20 +1371,20 @@ section BoundedSMul variable {𝕜 : Type*} [NormedRing 𝕜] [MulActionWithZero 𝕜 E] [MulActionWithZero 𝕜 F] variable [BoundedSMul 𝕜 E] [BoundedSMul 𝕜 F] {c : 𝕜} {f : α → F} -theorem eLpNorm'_const_smul_le (hq : 0 < q) : eLpNorm' (c • f) q μ ≤ ‖c‖₊ • eLpNorm' f q μ := +theorem eLpNorm'_const_smul_le (hq : 0 < q) : eLpNorm' (c • f) q μ ≤ ‖c‖ₑ * eLpNorm' f q μ := eLpNorm'_le_nnreal_smul_eLpNorm'_of_ae_le_mul (Eventually.of_forall fun _ => nnnorm_smul_le ..) hq @[deprecated (since := "2024-07-27")] alias snorm'_const_smul_le := eLpNorm'_const_smul_le -theorem eLpNormEssSup_const_smul_le : eLpNormEssSup (c • f) μ ≤ ‖c‖₊ • eLpNormEssSup f μ := +theorem eLpNormEssSup_const_smul_le : eLpNormEssSup (c • f) μ ≤ ‖c‖ₑ * eLpNormEssSup f μ := eLpNormEssSup_le_nnreal_smul_eLpNormEssSup_of_ae_le_mul (Eventually.of_forall fun _ => by simp [nnnorm_smul_le]) @[deprecated (since := "2024-07-27")] alias snormEssSup_const_smul_le := eLpNormEssSup_const_smul_le -theorem eLpNorm_const_smul_le : eLpNorm (c • f) p μ ≤ ‖c‖₊ • eLpNorm f p μ := +theorem eLpNorm_const_smul_le : eLpNorm (c • f) p μ ≤ ‖c‖ₑ * eLpNorm f p μ := eLpNorm_le_nnreal_smul_eLpNorm_of_ae_le_mul (Eventually.of_forall fun _ => by simp [nnnorm_smul_le]) _ @@ -1425,29 +1412,31 @@ variable {𝕜 : Type*} [NormedDivisionRing 𝕜] [MulActionWithZero 𝕜 E] [Mo variable [BoundedSMul 𝕜 E] [BoundedSMul 𝕜 F] theorem eLpNorm'_const_smul {f : α → F} (c : 𝕜) (hq_pos : 0 < q) : - eLpNorm' (c • f) q μ = ‖c‖₊ • eLpNorm' f q μ := by + eLpNorm' (c • f) q μ = ‖c‖ₑ * eLpNorm' f q μ := by obtain rfl | hc := eq_or_ne c 0 - · simp [eLpNorm'_eq_lintegral_nnnorm, hq_pos] - refine le_antisymm (eLpNorm'_const_smul_le hq_pos) ?_ - simpa [hc, le_inv_smul_iff_of_pos] using eLpNorm'_const_smul_le (c := c⁻¹) (f := c • f) hq_pos + · simp [eLpNorm'_eq_lintegral_enorm, hq_pos] + refine le_antisymm (eLpNorm'_const_smul_le hq_pos) <| ENNReal.mul_le_of_le_div' ?_ + simpa [enorm_inv, hc, ENNReal.div_eq_inv_mul] + using eLpNorm'_const_smul_le (c := c⁻¹) (f := c • f) hq_pos @[deprecated (since := "2024-07-27")] alias snorm'_const_smul := eLpNorm'_const_smul theorem eLpNormEssSup_const_smul (c : 𝕜) (f : α → F) : - eLpNormEssSup (c • f) μ = (‖c‖₊ : ℝ≥0∞) * eLpNormEssSup f μ := by - simp_rw [eLpNormEssSup_eq_essSup_nnnorm, Pi.smul_apply, nnnorm_smul, ENNReal.coe_mul, + eLpNormEssSup (c • f) μ = ‖c‖ₑ * eLpNormEssSup f μ := by + simp_rw [eLpNormEssSup_eq_essSup_enorm, Pi.smul_apply, enorm_smul, ENNReal.essSup_const_mul] @[deprecated (since := "2024-07-27")] alias snormEssSup_const_smul := eLpNormEssSup_const_smul theorem eLpNorm_const_smul (c : 𝕜) (f : α → F) (p : ℝ≥0∞) (μ : Measure α): - eLpNorm (c • f) p μ = (‖c‖₊ : ℝ≥0∞) * eLpNorm f p μ := by + eLpNorm (c • f) p μ = ‖c‖ₑ * eLpNorm f p μ := by obtain rfl | hc := eq_or_ne c 0 · simp - refine le_antisymm eLpNorm_const_smul_le ?_ - simpa [hc, le_inv_smul_iff_of_pos] using eLpNorm_const_smul_le (c := c⁻¹) (f := c • f) + refine le_antisymm eLpNorm_const_smul_le <| ENNReal.mul_le_of_le_div' ?_ + simpa [enorm_inv, hc, ENNReal.div_eq_inv_mul] + using eLpNorm_const_smul_le (c := c⁻¹) (f := c • f) @[deprecated (since := "2024-07-27")] alias snorm_const_smul := eLpNorm_const_smul @@ -1461,7 +1450,7 @@ end NormedSpace theorem le_eLpNorm_of_bddBelow (hp : p ≠ 0) (hp' : p ≠ ∞) {f : α → F} (C : ℝ≥0) {s : Set α} (hs : MeasurableSet s) (hf : ∀ᵐ x ∂μ, x ∈ s → C ≤ ‖f x‖₊) : C • μ s ^ (1 / p.toReal) ≤ eLpNorm f p μ := by - rw [ENNReal.smul_def, smul_eq_mul, eLpNorm_eq_lintegral_rpow_nnnorm hp hp', + rw [ENNReal.smul_def, smul_eq_mul, eLpNorm_eq_lintegral_rpow_enorm hp hp', one_div, ENNReal.le_rpow_inv_iff (ENNReal.toReal_pos hp hp'), ENNReal.mul_rpow_of_nonneg _ _ ENNReal.toReal_nonneg, ← ENNReal.rpow_mul, inv_mul_cancel₀ (ENNReal.toReal_pos hp hp').ne.symm, ENNReal.rpow_one, ← setLIntegral_const, @@ -1469,9 +1458,9 @@ theorem le_eLpNorm_of_bddBelow (hp : p ≠ 0) (hp' : p ≠ ∞) {f : α → F} ( refine lintegral_mono_ae ?_ filter_upwards [hf] with x hx by_cases hxs : x ∈ s - · simp only [Set.indicator_of_mem hxs] at hx ⊢ + · simp only [Set.indicator_of_mem, hxs, true_implies] at hx ⊢ gcongr - exact hx hxs + rwa [coe_le_enorm] · simp [Set.indicator_of_not_mem hxs] @[deprecated (since := "2024-07-27")] @@ -1511,7 +1500,7 @@ variable [MeasurableSpace E] [OpensMeasurableSpace E] {R : ℝ≥0} theorem ae_bdd_liminf_atTop_rpow_of_eLpNorm_bdd {p : ℝ≥0∞} {f : ℕ → α → E} (hfmeas : ∀ n, Measurable (f n)) (hbdd : ∀ n, eLpNorm (f n) p μ ≤ R) : - ∀ᵐ x ∂μ, liminf (fun n => ((‖f n x‖₊ : ℝ≥0∞) ^ p.toReal : ℝ≥0∞)) atTop < ∞ := by + ∀ᵐ x ∂μ, liminf (fun n => ((‖f n x‖ₑ) ^ p.toReal : ℝ≥0∞)) atTop < ∞ := by by_cases hp0 : p.toReal = 0 · simp only [hp0, ENNReal.rpow_zero] filter_upwards with _ @@ -1526,7 +1515,7 @@ theorem ae_bdd_liminf_atTop_rpow_of_eLpNorm_bdd {p : ℝ≥0∞} {f : ℕ → α (lt_of_le_of_lt ?_ (ENNReal.rpow_lt_top_of_nonneg ENNReal.toReal_nonneg ENNReal.coe_ne_top : (R : ℝ≥0∞) ^ p.toReal < ∞))).ne - simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm hp hp', one_div] at hbdd + simp_rw [eLpNorm_eq_lintegral_rpow_enorm hp hp', one_div] at hbdd simp_rw [liminf_eq, eventually_atTop] exact sSup_le fun b ⟨a, ha⟩ => @@ -1537,11 +1526,11 @@ alias ae_bdd_liminf_atTop_rpow_of_snorm_bdd := ae_bdd_liminf_atTop_rpow_of_eLpNo theorem ae_bdd_liminf_atTop_of_eLpNorm_bdd {p : ℝ≥0∞} (hp : p ≠ 0) {f : ℕ → α → E} (hfmeas : ∀ n, Measurable (f n)) (hbdd : ∀ n, eLpNorm (f n) p μ ≤ R) : - ∀ᵐ x ∂μ, liminf (fun n => (‖f n x‖₊ : ℝ≥0∞)) atTop < ∞ := by + ∀ᵐ x ∂μ, liminf (fun n => (‖f n x‖ₑ)) atTop < ∞ := by by_cases hp' : p = ∞ · subst hp' simp_rw [eLpNorm_exponent_top] at hbdd - have : ∀ n, ∀ᵐ x ∂μ, (‖f n x‖₊ : ℝ≥0∞) < R + 1 := fun n => + have : ∀ n, ∀ᵐ x ∂μ, (‖f n x‖ₑ) < R + 1 := fun n => ae_lt_of_essSup_lt (lt_of_le_of_lt (hbdd n) <| ENNReal.lt_add_right ENNReal.coe_ne_top one_ne_zero) rw [← ae_all_iff] at this @@ -1551,15 +1540,15 @@ theorem ae_bdd_liminf_atTop_of_eLpNorm_bdd {p : ℝ≥0∞} (hp : p ≠ 0) {f : filter_upwards [ae_bdd_liminf_atTop_rpow_of_eLpNorm_bdd hfmeas hbdd] with x hx have hppos : 0 < p.toReal := ENNReal.toReal_pos hp hp' have : - liminf (fun n => (‖f n x‖₊ : ℝ≥0∞) ^ p.toReal) atTop = - liminf (fun n => (‖f n x‖₊ : ℝ≥0∞)) atTop ^ p.toReal := by + liminf (fun n => (‖f n x‖ₑ) ^ p.toReal) atTop = + liminf (fun n => (‖f n x‖ₑ)) atTop ^ p.toReal := by change - liminf (fun n => ENNReal.orderIsoRpow p.toReal hppos (‖f n x‖₊ : ℝ≥0∞)) atTop = - ENNReal.orderIsoRpow p.toReal hppos (liminf (fun n => (‖f n x‖₊ : ℝ≥0∞)) atTop) + liminf (fun n => ENNReal.orderIsoRpow p.toReal hppos (‖f n x‖ₑ)) atTop = + ENNReal.orderIsoRpow p.toReal hppos (liminf (fun n => (‖f n x‖ₑ)) atTop) refine (OrderIso.liminf_apply (ENNReal.orderIsoRpow p.toReal _) ?_ ?_ ?_ ?_).symm <;> isBoundedDefault rw [this] at hx - rw [← ENNReal.rpow_one (liminf (fun n => ‖f n x‖₊) atTop), ← mul_inv_cancel₀ hppos.ne.symm, + rw [← ENNReal.rpow_one (liminf (‖f · x‖ₑ) atTop), ← mul_inv_cancel₀ hppos.ne.symm, ENNReal.rpow_mul] exact ENNReal.rpow_lt_top_of_nonneg (inv_nonneg.2 hppos.le) hx.ne @@ -1587,13 +1576,13 @@ theorem Memℒp.exists_eLpNorm_indicator_compl_lt {β : Type*} [NormedAddCommGro rcases eq_or_ne p 0 with rfl | hp₀ · use ∅; simp [pos_iff_ne_zero.2 hε] -- first take care of `p = 0` · obtain ⟨s, hsm, hs, hε⟩ : - ∃ s, MeasurableSet s ∧ μ s < ∞ ∧ ∫⁻ a in sᶜ, (‖f a‖₊) ^ p.toReal ∂μ < ε ^ p.toReal := by + ∃ s, MeasurableSet s ∧ μ s < ∞ ∧ ∫⁻ a in sᶜ, (‖f a‖ₑ) ^ p.toReal ∂μ < ε ^ p.toReal := by apply exists_setLintegral_compl_lt · exact ((eLpNorm_lt_top_iff_lintegral_rpow_nnnorm_lt_top hp₀ hp_top).1 hf.2).ne · simp [*] refine ⟨s, hsm, hs, ?_⟩ rwa [eLpNorm_indicator_eq_eLpNorm_restrict hsm.compl, - eLpNorm_eq_lintegral_rpow_nnnorm hp₀ hp_top, one_div, ENNReal.rpow_inv_lt_iff] + eLpNorm_eq_lintegral_rpow_enorm hp₀ hp_top, one_div, ENNReal.rpow_inv_lt_iff] simp [ENNReal.toReal_pos, *] @[deprecated (since := "2024-07-27")] diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean index 6248e4a2c5925..968d77d53489e 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean @@ -21,9 +21,9 @@ variable {α E : Type*} {m0 : MeasurableSpace α} [NormedAddCommGroup E] theorem pow_mul_meas_ge_le_eLpNorm (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) (hf : AEStronglyMeasurable f μ) (ε : ℝ≥0∞) : (ε * μ { x | ε ≤ (‖f x‖₊ : ℝ≥0∞) ^ p.toReal }) ^ (1 / p.toReal) ≤ eLpNorm f p μ := by - rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_ne_zero hp_ne_top] + rw [eLpNorm_eq_lintegral_rpow_enorm hp_ne_zero hp_ne_top] gcongr - exact mul_meas_ge_le_lintegral₀ (hf.ennnorm.pow_const _) ε + exact mul_meas_ge_le_lintegral₀ (hf.enorm.pow_const _) ε @[deprecated (since := "2024-07-27")] alias pow_mul_meas_ge_le_snorm := pow_mul_meas_ge_le_eLpNorm diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean index 649bc7c74f6ed..e56b6c50caf6d 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean @@ -30,16 +30,16 @@ theorem eLpNorm'_le_eLpNorm'_mul_rpow_measure_univ {p q : ℝ} (hp0_lt : 0 < p) · rw [hpq_eq, sub_self, ENNReal.rpow_zero, mul_one] have hpq : p < q := lt_of_le_of_ne hpq hpq_eq let g := fun _ : α => (1 : ℝ≥0∞) - have h_rw : (∫⁻ a, (‖f a‖₊ : ℝ≥0∞) ^ p ∂μ) = ∫⁻ a, ((‖f a‖₊ : ℝ≥0∞) * g a) ^ p ∂μ := + have h_rw : (∫⁻ a, ‖f a‖ₑ ^ p ∂μ) = ∫⁻ a, (‖f a‖ₑ * g a) ^ p ∂μ := lintegral_congr fun a => by simp [g] - repeat' rw [eLpNorm'_eq_lintegral_nnnorm] + repeat' rw [eLpNorm'_eq_lintegral_enorm] rw [h_rw] let r := p * q / (q - p) have hpqr : 1 / p = 1 / q + 1 / r := by field_simp [r, hp0_lt.ne', hq0_lt.ne'] calc (∫⁻ a : α, (↑‖f a‖₊ * g a) ^ p ∂μ) ^ (1 / p) ≤ (∫⁻ a : α, ↑‖f a‖₊ ^ q ∂μ) ^ (1 / q) * (∫⁻ a : α, g a ^ r ∂μ) ^ (1 / r) := - ENNReal.lintegral_Lp_mul_le_Lq_mul_Lr hp0_lt hpq hpqr μ hf.ennnorm aemeasurable_const + ENNReal.lintegral_Lp_mul_le_Lq_mul_Lr hp0_lt hpq hpqr μ hf.enorm aemeasurable_const _ = (∫⁻ a : α, ↑‖f a‖₊ ^ q ∂μ) ^ (1 / q) * μ Set.univ ^ (1 / p - 1 / q) := by rw [hpqr]; simp [r, g] @@ -48,7 +48,7 @@ alias snorm'_le_snorm'_mul_rpow_measure_univ := eLpNorm'_le_eLpNorm'_mul_rpow_me theorem eLpNorm'_le_eLpNormEssSup_mul_rpow_measure_univ {q : ℝ} (hq_pos : 0 < q) : eLpNorm' f q μ ≤ eLpNormEssSup f μ * μ Set.univ ^ (1 / q) := by - have h_le : (∫⁻ a : α, (‖f a‖₊ : ℝ≥0∞) ^ q ∂μ) ≤ ∫⁻ _ : α, eLpNormEssSup f μ ^ q ∂μ := by + have h_le : (∫⁻ a : α, ‖f a‖ₑ ^ q ∂μ) ≤ ∫⁻ _ : α, eLpNormEssSup f μ ^ q ∂μ := by refine lintegral_mono_ae ?_ have h_nnnorm_le_eLpNorm_ess_sup := coe_nnnorm_ae_le_eLpNormEssSup f μ exact h_nnnorm_le_eLpNorm_ess_sup.mono fun x hx => by gcongr @@ -198,7 +198,7 @@ theorem eLpNorm_le_eLpNorm_top_mul_eLpNorm (p : ℝ≥0∞) (f : α → E) {g : exact ha by_cases hp_zero : p = 0 · simp only [hp_zero, eLpNorm_exponent_zero, mul_zero, le_zero_iff] - simp_rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_zero hp_top, eLpNorm_exponent_top, eLpNormEssSup] + simp_rw [eLpNorm_eq_lintegral_rpow_enorm hp_zero hp_top, eLpNorm_exponent_top, eLpNormEssSup] calc (∫⁻ x, (‖b (f x) (g x)‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) ^ (1 / p.toReal) ≤ (∫⁻ x, (‖f x‖₊ : ℝ≥0∞) ^ p.toReal * (‖g x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) ^ (1 / p.toReal) := by @@ -255,7 +255,7 @@ theorem eLpNorm'_le_eLpNorm'_mul_eLpNorm' {p q r : ℝ} (hf : AEStronglyMeasurab h.mono fun a ha => (ENNReal.rpow_le_rpow_iff hp0_lt).mpr <| ENNReal.coe_le_coe.mpr <| ha _ ≤ _ := ?_ simp_rw [eLpNorm', ENNReal.coe_mul] - exact ENNReal.lintegral_Lp_mul_le_Lq_mul_Lr hp0_lt hpq hpqr μ hf.ennnorm hg.ennnorm + exact ENNReal.lintegral_Lp_mul_le_Lq_mul_Lr hp0_lt hpq hpqr μ hf.enorm hg.enorm @[deprecated (since := "2024-07-27")] alias snorm'_le_snorm'_mul_snorm' := eLpNorm'_le_eLpNorm'_mul_eLpNorm' diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean index bde7165f033fb..74b789bb4680a 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean @@ -28,7 +28,7 @@ theorem eLpNorm'_add_le (hf : AEStronglyMeasurable f μ) (hg : AEStronglyMeasura (∫⁻ a, ((fun a => (‖f a‖₊ : ℝ≥0∞)) + fun a => (‖g a‖₊ : ℝ≥0∞)) a ^ q ∂μ) ^ (1 / q) := by gcongr with a simp only [Pi.add_apply, ← ENNReal.coe_add, ENNReal.coe_le_coe, nnnorm_add_le] - _ ≤ eLpNorm' f q μ + eLpNorm' g q μ := ENNReal.lintegral_Lp_add_le hf.ennnorm hg.ennnorm hq1 + _ ≤ eLpNorm' f q μ + eLpNorm' g q μ := ENNReal.lintegral_Lp_add_le hf.enorm hg.enorm hq1 @[deprecated (since := "2024-07-27")] alias snorm'_add_le := eLpNorm'_add_le @@ -41,7 +41,7 @@ theorem eLpNorm'_add_le_of_le_one (hf : AEStronglyMeasurable f μ) (hq0 : 0 ≤ gcongr with a simp only [Pi.add_apply, ← ENNReal.coe_add, ENNReal.coe_le_coe, nnnorm_add_le] _ ≤ (2 : ℝ≥0∞) ^ (1 / q - 1) * (eLpNorm' f q μ + eLpNorm' g q μ) := - ENNReal.lintegral_Lp_add_le_of_le_one hf.ennnorm hq0 hq1 + ENNReal.lintegral_Lp_add_le_of_le_one hf.enorm hq0 hq1 @[deprecated (since := "2024-07-27")] alias snorm'_add_le_of_le_one := eLpNorm'_add_le_of_le_one diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean index b6776ff95e87a..0cb5cd60fe951 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/Trim.lean @@ -51,7 +51,7 @@ theorem essSup_trim (hm : m ≤ m0) {f : α → ℝ≥0∞} (hf : Measurable[m] theorem eLpNormEssSup_trim (hm : m ≤ m0) {f : α → E} (hf : StronglyMeasurable[m] f) : eLpNormEssSup f (μ.trim hm) = eLpNormEssSup f μ := - essSup_trim _ (@StronglyMeasurable.ennnorm _ m _ _ _ hf) + essSup_trim _ (@StronglyMeasurable.enorm _ m _ _ _ hf) @[deprecated (since := "2024-07-27")] alias snormEssSup_trim := eLpNormEssSup_trim diff --git a/Mathlib/MeasureTheory/Function/LpSpace.lean b/Mathlib/MeasureTheory/Function/LpSpace.lean index 7ff9c55c9cd7d..64caa8bea97f1 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace.lean @@ -248,10 +248,12 @@ theorem nnnorm_def (f : Lp E p μ) : ‖f‖₊ = ENNReal.toNNReal (eLpNorm f p protected theorem coe_nnnorm (f : Lp E p μ) : (‖f‖₊ : ℝ) = ‖f‖ := rfl -@[simp, norm_cast] -theorem nnnorm_coe_ennreal (f : Lp E p μ) : (‖f‖₊ : ℝ≥0∞) = eLpNorm f p μ := +@[simp] +theorem enorm_def (f : Lp E p μ) : ‖f‖ₑ = eLpNorm f p μ := ENNReal.coe_toNNReal <| Lp.eLpNorm_ne_top f +@[deprecated (since := "2025-01-20")] alias nnnorm_coe_ennreal := enorm_def + @[simp] lemma norm_toLp (f : α → E) (hf : Memℒp f p μ) : ‖hf.toLp f‖ = ENNReal.toReal (eLpNorm f p μ) := by rw [norm_def, eLpNorm_congr_ae (Memℒp.coeFn_toLp hf)] @@ -261,8 +263,10 @@ theorem nnnorm_toLp (f : α → E) (hf : Memℒp f p μ) : ‖hf.toLp f‖₊ = ENNReal.toNNReal (eLpNorm f p μ) := NNReal.eq <| norm_toLp f hf -theorem coe_nnnorm_toLp {f : α → E} (hf : Memℒp f p μ) : (‖hf.toLp f‖₊ : ℝ≥0∞) = eLpNorm f p μ := by - rw [nnnorm_toLp f hf, ENNReal.coe_toNNReal hf.2.ne] +lemma enorm_toLp {f : α → E} (hf : Memℒp f p μ) : ‖hf.toLp f‖ₑ = eLpNorm f p μ := by + simp [enorm, nnnorm_toLp f hf, ENNReal.coe_toNNReal hf.2.ne] + +@[deprecated (since := "2025-01-20")] alias coe_nnnorm_toLp := enorm_toLp theorem dist_def (f g : Lp E p μ) : dist f g = (eLpNorm (⇑f - ⇑g) p μ).toReal := by simp_rw [dist, norm_def] @@ -402,8 +406,8 @@ instance instNormedAddCommGroup [hp : Fact (1 ≤ p)] : NormedAddCommGroup (Lp E map_zero' := norm_zero neg' := by simp add_le' := fun f g => by - suffices (‖f + g‖₊ : ℝ≥0∞) ≤ ‖f‖₊ + ‖g‖₊ from mod_cast this - simp only [Lp.nnnorm_coe_ennreal] + suffices ‖f + g‖ₑ ≤ ‖f‖ₑ + ‖g‖ₑ by simpa [← ENNReal.coe_add, enorm] using this + simp only [Lp.enorm_def] exact (eLpNorm_congr_ae (AEEqFun.coeFn_add _ _)).trans_le (eLpNorm_add_le (Lp.aestronglyMeasurable _) (Lp.aestronglyMeasurable _) hp.out) eq_zero_of_map_eq_zero' := fun _ => @@ -426,9 +430,7 @@ variable [BoundedSMul 𝕜 E] [BoundedSMul 𝕜' E] theorem const_smul_mem_Lp (c : 𝕜) (f : Lp E p μ) : c • (f : α →ₘ[μ] E) ∈ Lp E p μ := by rw [mem_Lp_iff_eLpNorm_lt_top, eLpNorm_congr_ae (AEEqFun.coeFn_smul _ _)] - refine eLpNorm_const_smul_le.trans_lt ?_ - rw [ENNReal.smul_def, smul_eq_mul, ENNReal.mul_lt_top_iff] - exact Or.inl ⟨ENNReal.coe_lt_top, f.prop⟩ + exact eLpNorm_const_smul_le.trans_lt <| ENNReal.mul_lt_top ENNReal.coe_lt_top f.prop variable (E p μ 𝕜) @@ -461,10 +463,9 @@ instance instIsScalarTower [SMul 𝕜 𝕜'] [IsScalarTower 𝕜 𝕜' E] : IsSc instance instBoundedSMul [Fact (1 ≤ p)] : BoundedSMul 𝕜 (Lp E p μ) := -- TODO: add `BoundedSMul.of_nnnorm_smul_le` BoundedSMul.of_norm_smul_le fun r f => by - suffices (‖r • f‖₊ : ℝ≥0∞) ≤ ‖r‖₊ * ‖f‖₊ from mod_cast this - rw [nnnorm_def, nnnorm_def, ENNReal.coe_toNNReal (Lp.eLpNorm_ne_top _), - eLpNorm_congr_ae (coeFn_smul _ _), ENNReal.coe_toNNReal (Lp.eLpNorm_ne_top _)] - exact eLpNorm_const_smul_le + suffices ‖r • f‖ₑ ≤ ‖r‖ₑ * ‖f‖ₑ by simpa [← ENNReal.coe_mul, enorm] using this + simpa only [eLpNorm_congr_ae (coeFn_smul _ _), enorm_def] + using eLpNorm_const_smul_le (c := r) (f := f) (p := p) end BoundedSMul @@ -536,8 +537,7 @@ theorem exists_eLpNorm_indicator_le (hp : p ≠ ∞) (c : E) {ε : ℝ≥0∞} ( have hp₀ : 0 < p := bot_lt_iff_ne_bot.2 h'p have hp₀' : 0 ≤ 1 / p.toReal := div_nonneg zero_le_one ENNReal.toReal_nonneg have hp₀'' : 0 < p.toReal := ENNReal.toReal_pos hp₀.ne' hp - obtain ⟨η, hη_pos, hη_le⟩ : - ∃ η : ℝ≥0, 0 < η ∧ (‖c‖₊ : ℝ≥0∞) * (η : ℝ≥0∞) ^ (1 / p.toReal) ≤ ε := by + obtain ⟨η, hη_pos, hη_le⟩ : ∃ η : ℝ≥0, 0 < η ∧ ‖c‖ₑ * (η : ℝ≥0∞) ^ (1 / p.toReal) ≤ ε := by have : Filter.Tendsto (fun x : ℝ≥0 => ((‖c‖₊ * x ^ (1 / p.toReal) : ℝ≥0) : ℝ≥0∞)) (𝓝 0) (𝓝 (0 : ℝ≥0)) := by @@ -548,8 +548,7 @@ theorem exists_eLpNorm_indicator_le (hp : p ≠ ∞) (c : E) {ε : ℝ≥0∞} ( obtain ⟨δ, hδ, hδε'⟩ := NNReal.nhds_zero_basis.eventually_iff.mp (this.eventually_le_const hε') obtain ⟨η, hη, hηδ⟩ := exists_between hδ refine ⟨η, hη, ?_⟩ - rw [← ENNReal.coe_rpow_of_nonneg _ hp₀', ← ENNReal.coe_mul] - exact hδε' hηδ + simpa only [← ENNReal.coe_rpow_of_nonneg _ hp₀', enorm, ← ENNReal.coe_mul] using hδε' hηδ refine ⟨η, hη_pos, fun s hs => ?_⟩ refine (eLpNorm_indicator_const_le _ _).trans (le_trans ?_ hη_le) exact mul_le_mul_left' (ENNReal.rpow_le_rpow hs hp₀') _ @@ -614,13 +613,13 @@ theorem norm_indicatorConstLp (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) : ‖indicatorConstLp p hs hμs c‖ = ‖c‖ * (μ s).toReal ^ (1 / p.toReal) := by rw [Lp.norm_def, eLpNorm_congr_ae indicatorConstLp_coeFn, eLpNorm_indicator_const hs hp_ne_zero hp_ne_top, ENNReal.toReal_mul, ENNReal.toReal_rpow, - ENNReal.coe_toReal, coe_nnnorm] + toReal_enorm] theorem norm_indicatorConstLp_top (hμs_ne_zero : μ s ≠ 0) : ‖indicatorConstLp ∞ hs hμs c‖ = ‖c‖ := by rw [Lp.norm_def, eLpNorm_congr_ae indicatorConstLp_coeFn, eLpNorm_indicator_const' hs hμs_ne_zero ENNReal.top_ne_zero, ENNReal.top_toReal, - _root_.div_zero, ENNReal.rpow_zero, mul_one, ENNReal.coe_toReal, coe_nnnorm] + _root_.div_zero, ENNReal.rpow_zero, mul_one, toReal_enorm] theorem norm_indicatorConstLp' (hp_pos : p ≠ 0) (hμs_pos : μ s ≠ 0) : ‖indicatorConstLp p hs hμs c‖ = ‖c‖ * (μ s).toReal ^ (1 / p.toReal) := by @@ -634,29 +633,33 @@ theorem norm_indicatorConstLp_le : rw [indicatorConstLp, Lp.norm_toLp] refine ENNReal.toReal_le_of_le_ofReal (by positivity) ?_ refine (eLpNorm_indicator_const_le _ _).trans_eq ?_ - rw [← coe_nnnorm, ENNReal.ofReal_mul (NNReal.coe_nonneg _), ENNReal.ofReal_coe_nnreal, - ENNReal.toReal_rpow, ENNReal.ofReal_toReal] + rw [ENNReal.ofReal_mul (norm_nonneg _), ofReal_norm, ENNReal.toReal_rpow, ENNReal.ofReal_toReal] exact ENNReal.rpow_ne_top_of_nonneg (by positivity) hμs theorem nnnorm_indicatorConstLp_le : ‖indicatorConstLp p hs hμs c‖₊ ≤ ‖c‖₊ * (μ s).toNNReal ^ (1 / p.toReal) := norm_indicatorConstLp_le -theorem ennnorm_indicatorConstLp_le : - (‖indicatorConstLp p hs hμs c‖₊ : ℝ≥0∞) ≤ ‖c‖₊ * (μ s) ^ (1 / p.toReal) := by - refine (ENNReal.coe_le_coe.mpr nnnorm_indicatorConstLp_le).trans_eq ?_ - simp [ENNReal.coe_rpow_of_nonneg, ENNReal.coe_toNNReal hμs] +theorem enorm_indicatorConstLp_le : + ‖indicatorConstLp p hs hμs c‖ₑ ≤ ‖c‖ₑ * μ s ^ (1 / p.toReal) := by + simpa [ENNReal.coe_rpow_of_nonneg, ENNReal.coe_toNNReal hμs, Lp.enorm_def, ← enorm_eq_nnnorm] + using ENNReal.coe_le_coe.2 <| nnnorm_indicatorConstLp_le (c := c) (hμs := hμs) + +@[deprecated (since := "2025-01-20")] alias ennnorm_indicatorConstLp_le := enorm_indicatorConstLp_le -theorem edist_indicatorConstLp_eq_nnnorm {t : Set α} {ht : MeasurableSet t} {hμt : μ t ≠ ∞} : +theorem edist_indicatorConstLp_eq_enorm {t : Set α} {ht : MeasurableSet t} {hμt : μ t ≠ ∞} : edist (indicatorConstLp p hs hμs c) (indicatorConstLp p ht hμt c) = - ‖indicatorConstLp p (hs.symmDiff ht) (measure_symmDiff_ne_top hμs hμt) c‖₊ := by + ‖indicatorConstLp p (hs.symmDiff ht) (measure_symmDiff_ne_top hμs hμt) c‖ₑ := by unfold indicatorConstLp - rw [Lp.edist_toLp_toLp, eLpNorm_indicator_sub_indicator, Lp.coe_nnnorm_toLp] + rw [Lp.edist_toLp_toLp, eLpNorm_indicator_sub_indicator, Lp.enorm_toLp] + +@[deprecated (since := "2025-01-20")] +alias edist_indicatorConstLp_eq_nnnorm := edist_indicatorConstLp_eq_enorm theorem dist_indicatorConstLp_eq_norm {t : Set α} {ht : MeasurableSet t} {hμt : μ t ≠ ∞} : dist (indicatorConstLp p hs hμs c) (indicatorConstLp p ht hμt c) = ‖indicatorConstLp p (hs.symmDiff ht) (measure_symmDiff_ne_top hμs hμt) c‖ := by - rw [Lp.dist_edist, edist_indicatorConstLp_eq_nnnorm, ENNReal.coe_toReal, Lp.coe_nnnorm] + simp [Lp.dist_edist, edist_indicatorConstLp_eq_enorm, enorm, ENNReal.coe_toReal, Lp.coe_nnnorm] /-- A family of `indicatorConstLp` functions tends to an `indicatorConstLp`, if the underlying sets tend to the set in the sense of the measure of the symmetric difference. -/ @@ -741,12 +744,12 @@ theorem Lp.norm_const [NeZero μ] (hp_zero : p ≠ 0) : ‖Lp.const p μ c‖ = ‖c‖ * (μ Set.univ).toReal ^ (1 / p.toReal) := by have := NeZero.ne μ rw [← Memℒp.toLp_const, Lp.norm_toLp, eLpNorm_const] <;> try assumption - rw [ENNReal.toReal_mul, ENNReal.coe_toReal, ← ENNReal.toReal_rpow, coe_nnnorm] + rw [ENNReal.toReal_mul, toReal_enorm, ← ENNReal.toReal_rpow] theorem Lp.norm_const' (hp_zero : p ≠ 0) (hp_top : p ≠ ∞) : ‖Lp.const p μ c‖ = ‖c‖ * (μ Set.univ).toReal ^ (1 / p.toReal) := by rw [← Memℒp.toLp_const, Lp.norm_toLp, eLpNorm_const'] <;> try assumption - rw [ENNReal.toReal_mul, ENNReal.coe_toReal, ← ENNReal.toReal_rpow, coe_nnnorm] + rw [ENNReal.toReal_mul, toReal_enorm, ← ENNReal.toReal_rpow] theorem Lp.norm_const_le : ‖Lp.const p μ c‖ ≤ ‖c‖ * (μ Set.univ).toReal ^ (1 / p.toReal) := by rw [← indicatorConstLp_univ] @@ -1150,18 +1153,15 @@ namespace MeasureTheory namespace Lp theorem eLpNorm'_lim_eq_lintegral_liminf {ι} [Nonempty ι] [LinearOrder ι] {f : ι → α → G} {p : ℝ} - (hp_nonneg : 0 ≤ p) {f_lim : α → G} - (h_lim : ∀ᵐ x : α ∂μ, Tendsto (fun n => f n x) atTop (𝓝 (f_lim x))) : - eLpNorm' f_lim p μ = (∫⁻ a, atTop.liminf fun m => (‖f m a‖₊ : ℝ≥0∞) ^ p ∂μ) ^ (1 / p) := by - suffices h_no_pow : - (∫⁻ a, (‖f_lim a‖₊ : ℝ≥0∞) ^ p ∂μ) = ∫⁻ a, atTop.liminf fun m => (‖f m a‖₊ : ℝ≥0∞) ^ p ∂μ by - rw [eLpNorm'_eq_lintegral_nnnorm, h_no_pow] + {f_lim : α → G} (h_lim : ∀ᵐ x : α ∂μ, Tendsto (fun n => f n x) atTop (𝓝 (f_lim x))) : + eLpNorm' f_lim p μ = (∫⁻ a, atTop.liminf (‖f · a‖ₑ ^ p) ∂μ) ^ (1 / p) := by + suffices h_no_pow : (∫⁻ a, ‖f_lim a‖ₑ ^ p ∂μ) = ∫⁻ a, atTop.liminf fun m => ‖f m a‖ₑ ^ p ∂μ by + rw [eLpNorm'_eq_lintegral_enorm, h_no_pow] refine lintegral_congr_ae (h_lim.mono fun a ha => ?_) dsimp only rw [Tendsto.liminf_eq] - simp_rw [← ENNReal.coe_rpow_of_nonneg _ hp_nonneg, ENNReal.tendsto_coe] - refine ((NNReal.continuous_rpow_const hp_nonneg).tendsto ‖f_lim a‖₊).comp ?_ - exact (continuous_nnnorm.tendsto (f_lim a)).comp ha + refine (ENNReal.continuous_rpow_const.tendsto ‖f_lim a‖₊).comp ?_ + exact (continuous_enorm.tendsto (f_lim a)).comp ha @[deprecated (since := "2024-07-27")] alias snorm'_lim_eq_lintegral_liminf := eLpNorm'_lim_eq_lintegral_liminf @@ -1170,9 +1170,9 @@ theorem eLpNorm'_lim_le_liminf_eLpNorm' {E} [NormedAddCommGroup E] {f : ℕ → (hp_pos : 0 < p) (hf : ∀ n, AEStronglyMeasurable (f n) μ) {f_lim : α → E} (h_lim : ∀ᵐ x : α ∂μ, Tendsto (fun n => f n x) atTop (𝓝 (f_lim x))) : eLpNorm' f_lim p μ ≤ atTop.liminf fun n => eLpNorm' (f n) p μ := by - rw [eLpNorm'_lim_eq_lintegral_liminf hp_pos.le h_lim] + rw [eLpNorm'_lim_eq_lintegral_liminf h_lim] rw [one_div, ← ENNReal.le_rpow_inv_iff (by simp [hp_pos] : 0 < p⁻¹), inv_inv] - refine (lintegral_liminf_le' fun m => (hf m).ennnorm.pow_const _).trans_eq ?_ + refine (lintegral_liminf_le' fun m => (hf m).enorm.pow_const _).trans_eq ?_ have h_pow_liminf : atTop.liminf (fun n ↦ eLpNorm' (f n) p μ) ^ p = atTop.liminf fun n ↦ eLpNorm' (f n) p μ ^ p := by @@ -1181,7 +1181,7 @@ theorem eLpNorm'_lim_le_liminf_eLpNorm' {E} [NormedAddCommGroup E] {f : ℕ → refine (h_rpow_mono.orderIsoOfSurjective _ h_rpow_surj).liminf_apply ?_ ?_ ?_ ?_ all_goals isBoundedDefault rw [h_pow_liminf] - simp_rw [eLpNorm'_eq_lintegral_nnnorm, ← ENNReal.rpow_mul, one_div, + simp_rw [eLpNorm'_eq_lintegral_enorm, ← ENNReal.rpow_mul, one_div, inv_mul_cancel₀ hp_pos.ne.symm, ENNReal.rpow_one] @[deprecated (since := "2024-07-27")] @@ -1189,13 +1189,12 @@ alias snorm'_lim_le_liminf_snorm' := eLpNorm'_lim_le_liminf_eLpNorm' theorem eLpNorm_exponent_top_lim_eq_essSup_liminf {ι} [Nonempty ι] [LinearOrder ι] {f : ι → α → G} {f_lim : α → G} (h_lim : ∀ᵐ x : α ∂μ, Tendsto (fun n => f n x) atTop (𝓝 (f_lim x))) : - eLpNorm f_lim ∞ μ = essSup (fun x => atTop.liminf fun m => (‖f m x‖₊ : ℝ≥0∞)) μ := by - rw [eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_nnnorm] + eLpNorm f_lim ∞ μ = essSup (fun x => atTop.liminf fun m => ‖f m x‖ₑ) μ := by + rw [eLpNorm_exponent_top, eLpNormEssSup_eq_essSup_enorm] refine essSup_congr_ae (h_lim.mono fun x hx => ?_) dsimp only apply (Tendsto.liminf_eq ..).symm - rw [ENNReal.tendsto_coe] - exact (continuous_nnnorm.tendsto (f_lim x)).comp hx + exact (continuous_enorm.tendsto (f_lim x)).comp hx @[deprecated (since := "2024-07-27")] alias snorm_exponent_top_lim_eq_essSup_liminf := eLpNorm_exponent_top_lim_eq_essSup_liminf @@ -1206,7 +1205,7 @@ theorem eLpNorm_exponent_top_lim_le_liminf_eLpNorm_exponent_top {ι} [Nonempty eLpNorm f_lim ∞ μ ≤ atTop.liminf fun n => eLpNorm (f n) ∞ μ := by rw [eLpNorm_exponent_top_lim_eq_essSup_liminf h_lim] simp_rw [eLpNorm_exponent_top, eLpNormEssSup] - exact ENNReal.essSup_liminf_le fun n => fun x => (‖f n x‖₊ : ℝ≥0∞) + exact ENNReal.essSup_liminf_le _ @[deprecated (since := "2024-07-27")] alias snorm_exponent_top_lim_le_liminf_snorm_exponent_top := @@ -1335,35 +1334,31 @@ private theorem eLpNorm'_sum_norm_sub_le_tsum_of_cauchy_eLpNorm' {f : ℕ → α alias snorm'_sum_norm_sub_le_tsum_of_cauchy_snorm' := eLpNorm'_sum_norm_sub_le_tsum_of_cauchy_eLpNorm' -private theorem lintegral_rpow_sum_coe_nnnorm_sub_le_rpow_tsum +private theorem lintegral_rpow_sum_enorm_sub_le_rpow_tsum {f : ℕ → α → E} {p : ℝ} (hp1 : 1 ≤ p) {B : ℕ → ℝ≥0∞} (n : ℕ) (hn : eLpNorm' (fun x => ∑ i ∈ Finset.range (n + 1), ‖f (i + 1) x - f i x‖) p μ ≤ ∑' i, B i) : - (∫⁻ a, (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) ≤ - (∑' i, B i) ^ p := by + (∫⁻ a, (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ) ≤ (∑' i, B i) ^ p := by have hp_pos : 0 < p := zero_lt_one.trans_le hp1 rw [← inv_inv p, @ENNReal.le_rpow_inv_iff _ _ p⁻¹ (by simp [hp_pos]), inv_inv p] - simp_rw [eLpNorm'_eq_lintegral_nnnorm, one_div] at hn + simp_rw [eLpNorm'_eq_lintegral_enorm, one_div] at hn have h_nnnorm_nonneg : - (fun a => (‖∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖‖₊ : ℝ≥0∞) ^ p) = fun a => - (∑ i ∈ Finset.range (n + 1), (‖f (i + 1) a - f i a‖₊ : ℝ≥0∞)) ^ p := by + (fun a => ‖∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖‖ₑ ^ p) = fun a => + (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖ₑ) ^ p := by ext1 a congr - simp_rw [← ofReal_norm_eq_coe_nnnorm] + simp_rw [← ofReal_norm_eq_enorm] rw [← ENNReal.ofReal_sum_of_nonneg] · rw [Real.norm_of_nonneg _] exact Finset.sum_nonneg fun x _ => norm_nonneg _ · exact fun x _ => norm_nonneg _ rwa [h_nnnorm_nonneg] at hn -private theorem lintegral_rpow_tsum_coe_nnnorm_sub_le_tsum {f : ℕ → α → E} +private theorem lintegral_rpow_tsum_coe_enorm_sub_le_tsum {f : ℕ → α → E} (hf : ∀ n, AEStronglyMeasurable (f n) μ) {p : ℝ} (hp1 : 1 ≤ p) {B : ℕ → ℝ≥0∞} - (h : - ∀ n, - (∫⁻ a, (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) ≤ - (∑' i, B i) ^ p) : - (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) ^ (1 / p) ≤ ∑' i, B i := by + (h : ∀ n, ∫⁻ a, (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ ≤ (∑' i, B i) ^ p) : + (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ) ^ (1 / p) ≤ ∑' i, B i := by have hp_pos : 0 < p := zero_lt_one.trans_le hp1 - suffices h_pow : (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) ≤ (∑' i, B i) ^ p by + suffices h_pow : (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ) ≤ (∑' i, B i) ^ p by rwa [one_div, ← ENNReal.le_rpow_inv_iff (by simp [hp_pos] : 0 < p⁻¹), inv_inv] have h_tsum_1 : ∀ g : ℕ → ℝ≥0∞, ∑' i, g i = atTop.liminf fun n => ∑ i ∈ Finset.range (n + 1), g i := by @@ -1372,35 +1367,29 @@ private theorem lintegral_rpow_tsum_coe_nnnorm_sub_le_tsum {f : ℕ → α → E simp_rw [h_tsum_1 _] rw [← h_tsum_1] have h_liminf_pow : - (∫⁻ a, (atTop.liminf - fun n => ∑ i ∈ Finset.range (n + 1), (‖f (i + 1) a - f i a‖₊ : ℝ≥0∞)) ^ p ∂μ) = - ∫⁻ a, atTop.liminf - fun n => (∑ i ∈ Finset.range (n + 1), (‖f (i + 1) a - f i a‖₊ : ℝ≥0∞)) ^ p ∂μ := by + ∫⁻ a, (atTop.liminf fun n => ∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ = + ∫⁻ a, atTop.liminf fun n => (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ := by refine lintegral_congr fun x => ?_ have h_rpow_mono := ENNReal.strictMono_rpow_of_pos (zero_lt_one.trans_le hp1) have h_rpow_surj := (ENNReal.rpow_left_bijective hp_pos.ne.symm).2 refine (h_rpow_mono.orderIsoOfSurjective _ h_rpow_surj).liminf_apply ?_ ?_ ?_ ?_ all_goals isBoundedDefault rw [h_liminf_pow] - refine (lintegral_liminf_le' ?_).trans ?_ - · exact fun n => - (Finset.aemeasurable_sum (Finset.range (n + 1)) fun i _ => - ((hf (i + 1)).sub (hf i)).ennnorm).pow_const - _ - · exact liminf_le_of_frequently_le' (Frequently.of_forall h) - -private theorem tsum_nnnorm_sub_ae_lt_top {f : ℕ → α → E} (hf : ∀ n, AEStronglyMeasurable (f n) μ) + refine (lintegral_liminf_le' fun n ↦ ?_).trans <| liminf_le_of_frequently_le' <| .of_forall h + exact ((Finset.range _).aemeasurable_sum fun i _ ↦ ((hf _).sub (hf i)).enorm).pow_const _ + +private theorem tsum_enorm_sub_ae_lt_top {f : ℕ → α → E} (hf : ∀ n, AEStronglyMeasurable (f n) μ) {p : ℝ} (hp1 : 1 ≤ p) {B : ℕ → ℝ≥0∞} (hB : ∑' i, B i ≠ ∞) - (h : (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) ^ (1 / p) ≤ ∑' i, B i) : - ∀ᵐ x ∂μ, (∑' i, ‖f (i + 1) x - f i x‖₊ : ℝ≥0∞) < ∞ := by + (h : (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ) ^ (1 / p) ≤ ∑' i, B i) : + ∀ᵐ x ∂μ, ∑' i, ‖f (i + 1) x - f i x‖ₑ < ∞ := by have hp_pos : 0 < p := zero_lt_one.trans_le hp1 - have h_integral : (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) < ∞ := by + have h_integral : ∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ < ∞ := by have h_tsum_lt_top : (∑' i, B i) ^ p < ∞ := ENNReal.rpow_lt_top_of_nonneg hp_pos.le hB refine lt_of_le_of_lt ?_ h_tsum_lt_top rwa [one_div, ← ENNReal.le_rpow_inv_iff (by simp [hp_pos] : 0 < p⁻¹), inv_inv] at h - have rpow_ae_lt_top : ∀ᵐ x ∂μ, (∑' i, ‖f (i + 1) x - f i x‖₊ : ℝ≥0∞) ^ p < ∞ := by + have rpow_ae_lt_top : ∀ᵐ x ∂μ, (∑' i, ‖f (i + 1) x - f i x‖ₑ) ^ p < ∞ := by refine ae_lt_top' (AEMeasurable.pow_const ?_ _) h_integral.ne - exact AEMeasurable.ennreal_tsum fun n => ((hf (n + 1)).sub (hf n)).ennnorm + exact AEMeasurable.ennreal_tsum fun n => ((hf (n + 1)).sub (hf n)).enorm refine rpow_ae_lt_top.mono fun x hx => ?_ rwa [← ENNReal.lt_rpow_inv_iff hp_pos, ENNReal.top_rpow_of_pos (by simp [hp_pos] : 0 < p⁻¹)] at hx @@ -1413,15 +1402,13 @@ theorem ae_tendsto_of_cauchy_eLpNorm' [CompleteSpace E] {f : ℕ → α → E} { have h1 : ∀ n, eLpNorm' (fun x => ∑ i ∈ Finset.range (n + 1), ‖f (i + 1) x - f i x‖) p μ ≤ ∑' i, B i := eLpNorm'_sum_norm_sub_le_tsum_of_cauchy_eLpNorm' hf hp1 h_cau - have h2 : - ∀ n, - (∫⁻ a, (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) ≤ - (∑' i, B i) ^ p := - fun n => lintegral_rpow_sum_coe_nnnorm_sub_le_rpow_tsum hp1 n (h1 n) - have h3 : (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖₊ : ℝ≥0∞) ^ p ∂μ) ^ (1 / p) ≤ ∑' i, B i := - lintegral_rpow_tsum_coe_nnnorm_sub_le_tsum hf hp1 h2 - have h4 : ∀ᵐ x ∂μ, (∑' i, ‖f (i + 1) x - f i x‖₊ : ℝ≥0∞) < ∞ := - tsum_nnnorm_sub_ae_lt_top hf hp1 hB h3 + have h2 n : + ∫⁻ a, (∑ i ∈ Finset.range (n + 1), ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ ≤ (∑' i, B i) ^ p := + lintegral_rpow_sum_enorm_sub_le_rpow_tsum hp1 n (h1 n) + have h3 : (∫⁻ a, (∑' i, ‖f (i + 1) a - f i a‖ₑ) ^ p ∂μ) ^ (1 / p) ≤ ∑' i, B i := + lintegral_rpow_tsum_coe_enorm_sub_le_tsum hf hp1 h2 + have h4 : ∀ᵐ x ∂μ, ∑' i, ‖f (i + 1) x - f i x‖ₑ < ∞ := + tsum_enorm_sub_ae_lt_top hf hp1 hB h3 exact h4.mono fun x hx => .of_nnnorm <| ENNReal.tsum_coe_ne_top_iff_summable.mp hx.ne have h : ∀ᵐ x ∂μ, ∃ l : E, @@ -1453,7 +1440,7 @@ theorem ae_tendsto_of_cauchy_eLpNorm [CompleteSpace E] {f : ℕ → α → E} ∀ᵐ x ∂μ, ∃ l : E, atTop.Tendsto (fun n => f n x) (𝓝 l) := by by_cases hp_top : p = ∞ · simp_rw [hp_top] at * - have h_cau_ae : ∀ᵐ x ∂μ, ∀ N n m, N ≤ n → N ≤ m → (‖(f n - f m) x‖₊ : ℝ≥0∞) < B N := by + have h_cau_ae : ∀ᵐ x ∂μ, ∀ N n m, N ≤ n → N ≤ m → ‖(f n - f m) x‖ₑ < B N := by simp_rw [ae_all_iff] exact fun N n m hnN hmN => ae_lt_of_essSup_lt (h_cau N n m hnN hmN) simp_rw [eLpNorm_exponent_top, eLpNormEssSup] at h_cau @@ -1463,7 +1450,7 @@ theorem ae_tendsto_of_cauchy_eLpNorm [CompleteSpace E] {f : ℕ → α → E} specialize hx N n m hnN hmN rw [_root_.dist_eq_norm, ← ENNReal.ofReal_le_iff_le_toReal (ENNReal.ne_top_of_tsum_ne_top hB N), - ofReal_norm_eq_coe_nnnorm] + ofReal_norm_eq_enorm] exact hx.le · rw [← ENNReal.zero_toReal] exact @@ -1745,27 +1732,35 @@ namespace MeasureTheory namespace Lp -theorem pow_mul_meas_ge_le_norm (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) (ε : ℝ≥0∞) : - (ε * μ { x | ε ≤ (‖f x‖₊ : ℝ≥0∞) ^ p.toReal }) ^ (1 / p.toReal) ≤ ENNReal.ofReal ‖f‖ := +/-- A version of **Markov's inequality** with elements of Lp. -/ +lemma pow_mul_meas_ge_le_enorm (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) (ε : ℝ≥0∞) : + (ε * μ {x | ε ≤ ‖f x‖ₑ ^ p.toReal}) ^ (1 / p.toReal) ≤ ENNReal.ofReal ‖f‖ := (ENNReal.ofReal_toReal (eLpNorm_ne_top f)).symm ▸ pow_mul_meas_ge_le_eLpNorm μ hp_ne_zero hp_ne_top (Lp.aestronglyMeasurable f) ε -theorem mul_meas_ge_le_pow_norm (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) (ε : ℝ≥0∞) : - ε * μ { x | ε ≤ (‖f x‖₊ : ℝ≥0∞) ^ p.toReal } ≤ ENNReal.ofReal ‖f‖ ^ p.toReal := +/-- A version of **Markov's inequality** with elements of Lp. -/ +lemma mul_meas_ge_le_pow_enorm (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) (ε : ℝ≥0∞) : + ε * μ {x | ε ≤ ‖f x‖ₑ ^ p.toReal} ≤ ENNReal.ofReal ‖f‖ ^ p.toReal := (ENNReal.ofReal_toReal (eLpNorm_ne_top f)).symm ▸ mul_meas_ge_le_pow_eLpNorm μ hp_ne_zero hp_ne_top (Lp.aestronglyMeasurable f) ε -/-- A version of Markov's inequality with elements of Lp. -/ -theorem mul_meas_ge_le_pow_norm' (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) - (ε : ℝ≥0∞) : ε ^ p.toReal * μ { x | ε ≤ ‖f x‖₊ } ≤ ENNReal.ofReal ‖f‖ ^ p.toReal := +/-- A version of **Markov's inequality** with elements of Lp. -/ +theorem mul_meas_ge_le_pow_enorm' (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) + (ε : ℝ≥0∞) : ε ^ p.toReal * μ {x | ε ≤ ‖f x‖₊ } ≤ ENNReal.ofReal ‖f‖ ^ p.toReal := (ENNReal.ofReal_toReal (eLpNorm_ne_top f)).symm ▸ mul_meas_ge_le_pow_eLpNorm' μ hp_ne_zero hp_ne_top (Lp.aestronglyMeasurable f) ε -theorem meas_ge_le_mul_pow_norm (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) {ε : ℝ≥0∞} - (hε : ε ≠ 0) : μ { x | ε ≤ ‖f x‖₊ } ≤ ε⁻¹ ^ p.toReal * ENNReal.ofReal ‖f‖ ^ p.toReal := +/-- A version of **Markov's inequality** with elements of Lp. -/ +theorem meas_ge_le_mul_pow_enorm (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞) {ε : ℝ≥0∞} + (hε : ε ≠ 0) : μ {x | ε ≤ ‖f x‖₊} ≤ ε⁻¹ ^ p.toReal * ENNReal.ofReal ‖f‖ ^ p.toReal := (ENNReal.ofReal_toReal (eLpNorm_ne_top f)).symm ▸ meas_ge_le_mul_pow_eLpNorm μ hp_ne_zero hp_ne_top (Lp.aestronglyMeasurable f) hε +@[deprecated (since := "2025-01-20")] alias pow_mul_meas_ge_le_norm := pow_mul_meas_ge_le_enorm +@[deprecated (since := "2025-01-20")] alias mul_meas_ge_le_pow_norm := mul_meas_ge_le_pow_enorm +@[deprecated (since := "2025-01-20")] alias mul_meas_ge_le_pow_norm' := mul_meas_ge_le_pow_enorm' +@[deprecated (since := "2025-01-20")] alias meas_ge_le_mul_pow_norm := meas_ge_le_mul_pow_enorm + end Lp end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index 7ad4405faa9c1..69360af72aed9 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -73,16 +73,14 @@ theorem nnnorm_approxOn_le [OpensMeasurableSpace E] {f : β → E} (hf : Measura theorem norm_approxOn_y₀_le [OpensMeasurableSpace E] {f : β → E} (hf : Measurable f) {s : Set E} {y₀ : E} (h₀ : y₀ ∈ s) [SeparableSpace s] (x : β) (n : ℕ) : ‖approxOn f hf s y₀ h₀ n x - y₀‖ ≤ ‖f x - y₀‖ + ‖f x - y₀‖ := by - have := edist_approxOn_y0_le hf h₀ x n - repeat rw [edist_comm y₀, edist_eq_coe_nnnorm_sub] at this - exact mod_cast this + simpa [enorm, edist_eq_enorm_sub, ← ENNReal.coe_add, norm_sub_rev] + using edist_approxOn_y0_le hf h₀ x n theorem norm_approxOn_zero_le [OpensMeasurableSpace E] {f : β → E} (hf : Measurable f) {s : Set E} (h₀ : (0 : E) ∈ s) [SeparableSpace s] (x : β) (n : ℕ) : ‖approxOn f hf s 0 h₀ n x‖ ≤ ‖f x‖ + ‖f x‖ := by - have := edist_approxOn_y0_le hf h₀ x n - simp only [edist_comm (0 : E), edist_eq_coe_nnnorm] at this - exact mod_cast this + simpa [enorm, edist_eq_enorm_sub, ← ENNReal.coe_add, norm_sub_rev] + using edist_approxOn_y0_le hf h₀ x n theorem tendsto_approxOn_Lp_eLpNorm [OpensMeasurableSpace E] {f : β → E} (hf : Measurable f) {s : Set E} {y₀ : E} (h₀ : y₀ ∈ s) [SeparableSpace s] (hp_ne_top : p ≠ ∞) {μ : Measure β} @@ -91,35 +89,28 @@ theorem tendsto_approxOn_Lp_eLpNorm [OpensMeasurableSpace E] {f : β → E} (hf by_cases hp_zero : p = 0 · simpa only [hp_zero, eLpNorm_exponent_zero] using tendsto_const_nhds have hp : 0 < p.toReal := toReal_pos hp_zero hp_ne_top - suffices - Tendsto (fun n => ∫⁻ x, (‖approxOn f hf s y₀ h₀ n x - f x‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) atTop - (𝓝 0) by - simp only [eLpNorm_eq_lintegral_rpow_nnnorm hp_zero hp_ne_top] + suffices Tendsto (fun n => ∫⁻ x, ‖approxOn f hf s y₀ h₀ n x - f x‖ₑ ^ p.toReal ∂μ) atTop (𝓝 0) by + simp only [eLpNorm_eq_lintegral_rpow_enorm hp_zero hp_ne_top] convert continuous_rpow_const.continuousAt.tendsto.comp this simp [zero_rpow_of_pos (_root_.inv_pos.mpr hp)] -- We simply check the conditions of the Dominated Convergence Theorem: -- (1) The function "`p`-th power of distance between `f` and the approximation" is measurable - have hF_meas : - ∀ n, Measurable fun x => (‖approxOn f hf s y₀ h₀ n x - f x‖₊ : ℝ≥0∞) ^ p.toReal := by - simpa only [← edist_eq_coe_nnnorm_sub] using fun n => + have hF_meas n : Measurable fun x => ‖approxOn f hf s y₀ h₀ n x - f x‖ₑ ^ p.toReal := by + simpa only [← edist_eq_enorm_sub] using (approxOn f hf s y₀ h₀ n).measurable_bind (fun y x => edist y (f x) ^ p.toReal) fun y => (measurable_edist_right.comp hf).pow_const p.toReal -- (2) The functions "`p`-th power of distance between `f` and the approximation" are uniformly -- bounded, at any given point, by `fun x => ‖f x - y₀‖ ^ p.toReal` - have h_bound : - ∀ n, (fun x => (‖approxOn f hf s y₀ h₀ n x - f x‖₊ : ℝ≥0∞) ^ p.toReal) ≤ᵐ[μ] fun x => - (‖f x - y₀‖₊ : ℝ≥0∞) ^ p.toReal := - fun n => - Eventually.of_forall fun x => - rpow_le_rpow (coe_mono (nnnorm_approxOn_le hf h₀ x n)) toReal_nonneg + have h_bound n : + (fun x ↦ ‖approxOn f hf s y₀ h₀ n x - f x‖ₑ ^ p.toReal) ≤ᵐ[μ] (‖f · - y₀‖ₑ ^ p.toReal) := + .of_forall fun x => rpow_le_rpow (coe_mono (nnnorm_approxOn_le hf h₀ x n)) toReal_nonneg -- (3) The bounding function `fun x => ‖f x - y₀‖ ^ p.toReal` has finite integral - have h_fin : (∫⁻ a : β, (‖f a - y₀‖₊ : ℝ≥0∞) ^ p.toReal ∂μ) ≠ ⊤ := - (lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp_zero hp_ne_top hi).ne + have h_fin : (∫⁻ a : β, ‖f a - y₀‖ₑ ^ p.toReal ∂μ) ≠ ⊤ := + (lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top hp_zero hp_ne_top hi).ne -- (4) The functions "`p`-th power of distance between `f` and the approximation" tend pointwise -- to zero have h_lim : - ∀ᵐ a : β ∂μ, - Tendsto (fun n => (‖approxOn f hf s y₀ h₀ n a - f a‖₊ : ℝ≥0∞) ^ p.toReal) atTop (𝓝 0) := by + ∀ᵐ a : β ∂μ, Tendsto (‖approxOn f hf s y₀ h₀ · a - f a‖ₑ ^ p.toReal) atTop (𝓝 0) := by filter_upwards [hμ] with a ha have : Tendsto (fun n => (approxOn f hf s y₀ h₀ n) a - f a) atTop (𝓝 (f a - f a)) := (tendsto_approxOn hf h₀ ha).sub tendsto_const_nhds @@ -222,13 +213,15 @@ section Integrable variable [MeasurableSpace β] variable [MeasurableSpace E] [NormedAddCommGroup E] -theorem tendsto_approxOn_L1_nnnorm [OpensMeasurableSpace E] {f : β → E} (hf : Measurable f) +theorem tendsto_approxOn_L1_enorm [OpensMeasurableSpace E] {f : β → E} (hf : Measurable f) {s : Set E} {y₀ : E} (h₀ : y₀ ∈ s) [SeparableSpace s] {μ : Measure β} (hμ : ∀ᵐ x ∂μ, f x ∈ closure s) (hi : HasFiniteIntegral (fun x => f x - y₀) μ) : - Tendsto (fun n => ∫⁻ x, ‖approxOn f hf s y₀ h₀ n x - f x‖₊ ∂μ) atTop (𝓝 0) := by - simpa [eLpNorm_one_eq_lintegral_nnnorm] using + Tendsto (fun n => ∫⁻ x, ‖approxOn f hf s y₀ h₀ n x - f x‖ₑ ∂μ) atTop (𝓝 0) := by + simpa [eLpNorm_one_eq_lintegral_enorm] using tendsto_approxOn_Lp_eLpNorm hf h₀ one_ne_top hμ - (by simpa [eLpNorm_one_eq_lintegral_nnnorm] using hi) + (by simpa [eLpNorm_one_eq_lintegral_enorm] using hi) + +@[deprecated (since := "2025-01-21")] alias tendsto_approxOn_L1_nnnorm := tendsto_approxOn_L1_enorm theorem integrable_approxOn [BorelSpace E] {f : β → E} {μ : Measure β} (fmeas : Measurable f) (hf : Integrable f μ) {s : Set E} {y₀ : E} (h₀ : y₀ ∈ s) [SeparableSpace s] @@ -236,14 +229,17 @@ theorem integrable_approxOn [BorelSpace E] {f : β → E} {μ : Measure β} (fme rw [← memℒp_one_iff_integrable] at hf hi₀ ⊢ exact memℒp_approxOn fmeas hf h₀ hi₀ n -theorem tendsto_approxOn_range_L1_nnnorm [OpensMeasurableSpace E] {f : β → E} {μ : Measure β} +theorem tendsto_approxOn_range_L1_enorm [OpensMeasurableSpace E] {f : β → E} {μ : Measure β} [SeparableSpace (range f ∪ {0} : Set E)] (fmeas : Measurable f) (hf : Integrable f μ) : - Tendsto (fun n => ∫⁻ x, ‖approxOn f fmeas (range f ∪ {0}) 0 (by simp) n x - f x‖₊ ∂μ) atTop + Tendsto (fun n => ∫⁻ x, ‖approxOn f fmeas (range f ∪ {0}) 0 (by simp) n x - f x‖ₑ ∂μ) atTop (𝓝 0) := by - apply tendsto_approxOn_L1_nnnorm fmeas + apply tendsto_approxOn_L1_enorm fmeas · filter_upwards with x using subset_closure (by simp) · simpa using hf.2 +@[deprecated (since := "2025-01-21")] +alias tendsto_approxOn_range_L1_nnnorm := tendsto_approxOn_range_L1_enorm + theorem integrable_approxOn_range [BorelSpace E] {f : β → E} {μ : Measure β} (fmeas : Measurable f) [SeparableSpace (range f ∪ {0} : Set E)] (hf : Integrable f μ) (n : ℕ) : Integrable (approxOn f fmeas (range f ∪ {0}) 0 (by simp) n) μ := @@ -278,10 +274,9 @@ theorem memℒp_top (f : α →ₛ E) (μ : Measure α) : Memℒp f ∞ μ := memℒp_top_of_bound f.aestronglyMeasurable C <| Eventually.of_forall hfC protected theorem eLpNorm'_eq {p : ℝ} (f : α →ₛ F) (μ : Measure α) : - eLpNorm' f p μ = (∑ y ∈ f.range, (‖y‖₊ : ℝ≥0∞) ^ p * μ (f ⁻¹' {y})) ^ (1 / p) := by - have h_map : (fun a => (‖f a‖₊ : ℝ≥0∞) ^ p) = f.map fun a : F => (‖a‖₊ : ℝ≥0∞) ^ p := by - simp; rfl - rw [eLpNorm'_eq_lintegral_nnnorm, h_map, lintegral_eq_lintegral, map_lintegral] + eLpNorm' f p μ = (∑ y ∈ f.range, ‖y‖ₑ ^ p * μ (f ⁻¹' {y})) ^ (1 / p) := by + have h_map : (‖f ·‖ₑ ^ p) = f.map (‖·‖ₑ ^ p) := by simp; rfl + rw [eLpNorm'_eq_lintegral_enorm, h_map, lintegral_eq_lintegral, map_lintegral] @[deprecated (since := "2024-07-27")] protected alias snorm'_eq := SimpleFunc.eLpNorm'_eq diff --git a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean index 3b54bf1d8f7db..3ea95e6147099 100644 --- a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean +++ b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean @@ -812,10 +812,12 @@ protected theorem nnnorm {_ : MeasurableSpace α} {β : Type*} [SeminormedAddCom continuous_nnnorm.comp_stronglyMeasurable hf @[measurability] -protected theorem ennnorm {_ : MeasurableSpace α} {β : Type*} [SeminormedAddCommGroup β] - {f : α → β} (hf : StronglyMeasurable f) : Measurable fun a => (‖f a‖₊ : ℝ≥0∞) := +protected theorem enorm {_ : MeasurableSpace α} {β : Type*} [SeminormedAddCommGroup β] + {f : α → β} (hf : StronglyMeasurable f) : Measurable (‖f ·‖ₑ) := (ENNReal.continuous_coe.comp_stronglyMeasurable hf.nnnorm).measurable +@[deprecated (since := "2025-01-21")] alias ennnorm := StronglyMeasurable.enorm + @[measurability] protected theorem real_toNNReal {_ : MeasurableSpace α} {f : α → ℝ} (hf : StronglyMeasurable f) : StronglyMeasurable fun x => (f x).toNNReal := @@ -1438,10 +1440,12 @@ protected theorem nnnorm {β : Type*} [SeminormedAddCommGroup β] {f : α → β continuous_nnnorm.comp_aestronglyMeasurable hf @[measurability] -protected theorem ennnorm {β : Type*} [SeminormedAddCommGroup β] {f : α → β} - (hf : AEStronglyMeasurable f μ) : AEMeasurable (fun a => (‖f a‖₊ : ℝ≥0∞)) μ := +protected theorem enorm {β : Type*} [SeminormedAddCommGroup β] {f : α → β} + (hf : AEStronglyMeasurable f μ) : AEMeasurable (‖f ·‖ₑ) μ := (ENNReal.continuous_coe.comp_aestronglyMeasurable hf.nnnorm).aemeasurable +@[deprecated (since := "2025-01-20")] alias ennnorm := AEStronglyMeasurable.enorm + @[aesop safe 20 apply (rule_sets := [Measurable])] protected theorem edist {β : Type*} [SeminormedAddCommGroup β] {f g : α → β} (hf : AEStronglyMeasurable f μ) (hg : AEStronglyMeasurable g μ) : diff --git a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean index 172756a4d9dbd..58d1ce643a517 100644 --- a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean @@ -224,12 +224,12 @@ theorem Memℒp.integral_indicator_norm_ge_le (hf : Memℒp f 1 μ) (hmeas : Str which does not require measurability. -/ theorem Memℒp.integral_indicator_norm_ge_nonneg_le_of_meas (hf : Memℒp f 1 μ) (hmeas : StronglyMeasurable f) {ε : ℝ} (hε : 0 < ε) : - ∃ M : ℝ, 0 ≤ M ∧ (∫⁻ x, ‖{ x | M ≤ ‖f x‖₊ }.indicator f x‖₊ ∂μ) ≤ ENNReal.ofReal ε := + ∃ M : ℝ, 0 ≤ M ∧ (∫⁻ x, ‖{ x | M ≤ ‖f x‖₊ }.indicator f x‖ₑ ∂μ) ≤ ENNReal.ofReal ε := let ⟨M, hM⟩ := hf.integral_indicator_norm_ge_le hmeas hε ⟨max M 0, le_max_right _ _, by simpa⟩ theorem Memℒp.integral_indicator_norm_ge_nonneg_le (hf : Memℒp f 1 μ) {ε : ℝ} (hε : 0 < ε) : - ∃ M : ℝ, 0 ≤ M ∧ (∫⁻ x, ‖{ x | M ≤ ‖f x‖₊ }.indicator f x‖₊ ∂μ) ≤ ENNReal.ofReal ε := by + ∃ M : ℝ, 0 ≤ M ∧ (∫⁻ x, ‖{ x | M ≤ ‖f x‖₊ }.indicator f x‖ₑ ∂μ) ≤ ENNReal.ofReal ε := by have hf_mk : Memℒp (hf.1.mk f) 1 μ := (memℒp_congr_ae hf.1.ae_eq_mk).mp hf obtain ⟨M, hM_pos, hfM⟩ := hf_mk.integral_indicator_norm_ge_nonneg_le_of_meas hf.1.stronglyMeasurable_mk hε @@ -281,27 +281,25 @@ theorem Memℒp.eLpNorm_indicator_norm_ge_le (hf : Memℒp f p μ) (hmeas : Stro obtain ⟨M, hM', hM⟩ := Memℒp.integral_indicator_norm_ge_nonneg_le (μ := μ) (hf.norm_rpow hp_ne_zero hp_ne_top) (Real.rpow_pos_of_pos hε p.toReal) refine ⟨M ^ (1 / p.toReal), ?_⟩ - rw [eLpNorm_eq_lintegral_rpow_nnnorm hp_ne_zero hp_ne_top, ← ENNReal.rpow_one (ENNReal.ofReal ε)] + rw [eLpNorm_eq_lintegral_rpow_enorm hp_ne_zero hp_ne_top, ← ENNReal.rpow_one (ENNReal.ofReal ε)] conv_rhs => rw [← mul_one_div_cancel (ENNReal.toReal_pos hp_ne_zero hp_ne_top).ne.symm] rw [ENNReal.rpow_mul, ENNReal.rpow_le_rpow_iff (one_div_pos.2 <| ENNReal.toReal_pos hp_ne_zero hp_ne_top), ENNReal.ofReal_rpow_of_pos hε] - convert hM - rename_i x - rw [← ENNReal.coe_rpow_of_nonneg _ ENNReal.toReal_nonneg, nnnorm_indicator_eq_indicator_nnnorm, - nnnorm_indicator_eq_indicator_nnnorm] + convert hM using 3 with x + rw [enorm_indicator_eq_indicator_enorm, enorm_indicator_eq_indicator_enorm] have hiff : M ^ (1 / p.toReal) ≤ ‖f x‖₊ ↔ M ≤ ‖‖f x‖ ^ p.toReal‖₊ := by rw [coe_nnnorm, coe_nnnorm, Real.norm_rpow_of_nonneg (norm_nonneg _), norm_norm, ← Real.rpow_le_rpow_iff hM' (Real.rpow_nonneg (norm_nonneg _) _) (one_div_pos.2 <| ENNReal.toReal_pos hp_ne_zero hp_ne_top), ← Real.rpow_mul (norm_nonneg _), mul_one_div_cancel (ENNReal.toReal_pos hp_ne_zero hp_ne_top).ne.symm, Real.rpow_one] by_cases hx : x ∈ { x : α | M ^ (1 / p.toReal) ≤ ‖f x‖₊ } - · rw [Set.indicator_of_mem hx, Set.indicator_of_mem, Real.nnnorm_of_nonneg] - · rfl + · rw [Set.indicator_of_mem hx, Set.indicator_of_mem, Real.enorm_of_nonneg (by positivity), + ← ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) ENNReal.toReal_nonneg, ofReal_norm] rw [Set.mem_setOf_eq] rwa [← hiff] · rw [Set.indicator_of_not_mem hx, Set.indicator_of_not_mem] - · simp [(ENNReal.toReal_pos hp_ne_zero hp_ne_top).ne.symm] + · simp [ENNReal.toReal_pos hp_ne_zero hp_ne_top] · rw [Set.mem_setOf_eq] rwa [← hiff] @@ -499,7 +497,7 @@ theorem eLpNorm_sub_le_of_dist_bdd (μ : Measure α) refine le_trans (eLpNorm_mono this) ?_ rw [eLpNorm_indicator_const hs hp hp'] refine mul_le_mul_right' (le_of_eq ?_) _ - rw [← ofReal_norm_eq_coe_nnnorm, Real.norm_eq_abs, abs_of_nonneg hc] + rw [← ofReal_norm_eq_enorm, Real.norm_eq_abs, abs_of_nonneg hc] @[deprecated (since := "2024-07-27")] alias snorm_sub_le_of_dist_bdd := eLpNorm_sub_le_of_dist_bdd @@ -920,33 +918,23 @@ theorem uniformIntegrable_average refine ⟨δ, hδ₁, fun n s hs hle => ?_⟩ simp_rw [Finset.smul_sum, Finset.indicator_sum] refine le_trans (eLpNorm_sum_le (fun i _ => ((hf₁ i).const_smul _).indicator hs) hp) ?_ - have : ∀ i, s.indicator ((n : ℝ) ⁻¹ • f i) = (↑n : ℝ)⁻¹ • s.indicator (f i) := - fun i ↦ indicator_const_smul _ _ _ - simp_rw [this, eLpNorm_const_smul, ← Finset.mul_sum, nnnorm_inv, Real.nnnorm_natCast] - by_cases hn : (↑(↑n : ℝ≥0)⁻¹ : ℝ≥0∞) = 0 - · simp only [hn, zero_mul, zero_le] - refine le_trans ?_ (?_ : ↑(↑n : ℝ≥0)⁻¹ * n • ENNReal.ofReal ε ≤ ENNReal.ofReal ε) - · refine (ENNReal.mul_le_mul_left hn ENNReal.coe_ne_top).2 ?_ - conv_rhs => rw [← Finset.card_range n] - exact Finset.sum_le_card_nsmul _ _ _ fun i _ => hδ₂ _ _ hs hle - · simp only [ENNReal.coe_eq_zero, inv_eq_zero, Nat.cast_eq_zero] at hn - rw [nsmul_eq_mul, ← mul_assoc, ENNReal.coe_inv, ENNReal.coe_natCast, - ENNReal.inv_mul_cancel _ (ENNReal.natCast_ne_top _), one_mul] - all_goals simpa only [Ne, Nat.cast_eq_zero] + have this i : s.indicator ((n : ℝ) ⁻¹ • f i) = (↑n : ℝ)⁻¹ • s.indicator (f i) := + indicator_const_smul _ _ _ + obtain rfl | hn := eq_or_ne n 0 + · simp + simp_rw [this, eLpNorm_const_smul, ← Finset.mul_sum] + rw [enorm_inv (by positivity), Real.enorm_natCast, ← ENNReal.div_eq_inv_mul] + refine ENNReal.div_le_of_le_mul' ?_ + simpa using Finset.sum_le_card_nsmul (.range n) _ _ fun i _ => hδ₂ _ _ hs hle · obtain ⟨C, hC⟩ := hf₃ simp_rw [Finset.smul_sum] refine ⟨C, fun n => (eLpNorm_sum_le (fun i _ => (hf₁ i).const_smul _) hp).trans ?_⟩ - simp_rw [eLpNorm_const_smul, ← Finset.mul_sum, nnnorm_inv, Real.nnnorm_natCast] - by_cases hn : (↑(↑n : ℝ≥0)⁻¹ : ℝ≥0∞) = 0 - · simp only [hn, zero_mul, zero_le] - refine le_trans ?_ (?_ : ↑(↑n : ℝ≥0)⁻¹ * (n • C : ℝ≥0∞) ≤ C) - · refine (ENNReal.mul_le_mul_left hn ENNReal.coe_ne_top).2 ?_ - conv_rhs => rw [← Finset.card_range n] - exact Finset.sum_le_card_nsmul _ _ _ fun i _ => hC i - · simp only [ENNReal.coe_eq_zero, inv_eq_zero, Nat.cast_eq_zero] at hn - rw [nsmul_eq_mul, ← mul_assoc, ENNReal.coe_inv, ENNReal.coe_natCast, - ENNReal.inv_mul_cancel _ (ENNReal.natCast_ne_top _), one_mul] - all_goals simpa only [Ne, Nat.cast_eq_zero] + obtain rfl | hn := eq_or_ne n 0 + · simp + simp_rw [eLpNorm_const_smul, ← Finset.mul_sum] + rw [enorm_inv (by positivity), Real.enorm_natCast, ← ENNReal.div_eq_inv_mul] + refine ENNReal.div_le_of_le_mul' ?_ + simpa using Finset.sum_le_card_nsmul (.range n) _ _ fun i _ => hC i /-- The averaging of a uniformly integrable real-valued sequence is also uniformly integrable. -/ theorem uniformIntegrable_average_real (hp : 1 ≤ p) {f : ℕ → α → ℝ} (hf : UniformIntegrable f p μ) : diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index 51627a057494c..a9ff72df2468e 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -868,12 +868,14 @@ theorem norm_integral_le_lintegral_norm (f : α → G) : · rw [integral_undef hf, norm_zero]; exact toReal_nonneg · simp [integral, hG] -theorem ennnorm_integral_le_lintegral_ennnorm (f : α → G) : - (‖∫ a, f a ∂μ‖₊ : ℝ≥0∞) ≤ ∫⁻ a, ‖f a‖₊ ∂μ := by - simp_rw [← ofReal_norm_eq_coe_nnnorm] +theorem enorm_integral_le_lintegral_enorm (f : α → G) : ‖∫ a, f a ∂μ‖ₑ ≤ ∫⁻ a, ‖f a‖ₑ ∂μ := by + simp_rw [← ofReal_norm_eq_enorm] apply ENNReal.ofReal_le_of_le_toReal exact norm_integral_le_lintegral_norm f +@[deprecated (since := "2025-01-21")] +alias ennnorm_integral_le_lintegral_ennnorm := enorm_integral_le_lintegral_enorm + theorem integral_eq_zero_of_ae {f : α → G} (hf : f =ᵐ[μ] 0) : ∫ a, f a ∂μ = 0 := by simp [integral_congr_ae hf, integral_zero] @@ -887,7 +889,7 @@ theorem HasFiniteIntegral.tendsto_setIntegral_nhds_zero {ι} {f : α → G} ENNReal.coe_zero] exact tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds (tendsto_setLIntegral_zero (ne_of_lt hf) hs) (fun i => zero_le _) - fun i => ennnorm_integral_le_lintegral_ennnorm _ + fun i => enorm_integral_le_lintegral_enorm _ @[deprecated (since := "2024-04-17")] alias HasFiniteIntegral.tendsto_set_integral_nhds_zero := @@ -907,7 +909,7 @@ alias Integrable.tendsto_set_integral_nhds_zero := /-- If `F i → f` in `L1`, then `∫ x, F i x ∂μ → ∫ x, f x ∂μ`. -/ theorem tendsto_integral_of_L1 {ι} (f : α → G) (hfi : Integrable f μ) {F : ι → α → G} {l : Filter ι} (hFi : ∀ᶠ i in l, Integrable (F i) μ) - (hF : Tendsto (fun i => ∫⁻ x, ‖F i x - f x‖₊ ∂μ) l (𝓝 0)) : + (hF : Tendsto (fun i => ∫⁻ x, ‖F i x - f x‖ₑ ∂μ) l (𝓝 0)) : Tendsto (fun i => ∫ x, F i x ∂μ) l (𝓝 <| ∫ x, f x ∂μ) := by by_cases hG : CompleteSpace G · simp only [integral, hG, L1.integral] @@ -919,18 +921,18 @@ lemma tendsto_integral_of_L1' {ι} (f : α → G) (hfi : Integrable f μ) {F : (hFi : ∀ᶠ i in l, Integrable (F i) μ) (hF : Tendsto (fun i ↦ eLpNorm (F i - f) 1 μ) l (𝓝 0)) : Tendsto (fun i ↦ ∫ x, F i x ∂μ) l (𝓝 (∫ x, f x ∂μ)) := by refine tendsto_integral_of_L1 f hfi hFi ?_ - simp_rw [eLpNorm_one_eq_lintegral_nnnorm, Pi.sub_apply] at hF + simp_rw [eLpNorm_one_eq_lintegral_enorm, Pi.sub_apply] at hF exact hF /-- If `F i → f` in `L1`, then `∫ x in s, F i x ∂μ → ∫ x in s, f x ∂μ`. -/ lemma tendsto_setIntegral_of_L1 {ι} (f : α → G) (hfi : Integrable f μ) {F : ι → α → G} {l : Filter ι} - (hFi : ∀ᶠ i in l, Integrable (F i) μ) (hF : Tendsto (fun i ↦ ∫⁻ x, ‖F i x - f x‖₊ ∂μ) l (𝓝 0)) + (hFi : ∀ᶠ i in l, Integrable (F i) μ) (hF : Tendsto (fun i ↦ ∫⁻ x, ‖F i x - f x‖ₑ ∂μ) l (𝓝 0)) (s : Set α) : Tendsto (fun i ↦ ∫ x in s, F i x ∂μ) l (𝓝 (∫ x in s, f x ∂μ)) := by refine tendsto_integral_of_L1 f hfi.restrict ?_ ?_ · filter_upwards [hFi] with i hi using hi.restrict - · simp_rw [← eLpNorm_one_eq_lintegral_nnnorm] at hF ⊢ + · simp_rw [← eLpNorm_one_eq_lintegral_enorm] at hF ⊢ exact tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds hF (fun _ ↦ zero_le') (fun _ ↦ eLpNorm_mono_measure _ Measure.restrict_le_self) @@ -944,7 +946,7 @@ lemma tendsto_setIntegral_of_L1' {ι} (f : α → G) (hfi : Integrable f μ) {F (s : Set α) : Tendsto (fun i ↦ ∫ x in s, F i x ∂μ) l (𝓝 (∫ x in s, f x ∂μ)) := by refine tendsto_setIntegral_of_L1 f hfi hFi ?_ s - simp_rw [eLpNorm_one_eq_lintegral_nnnorm, Pi.sub_apply] at hF + simp_rw [eLpNorm_one_eq_lintegral_enorm, Pi.sub_apply] at hF exact hF @[deprecated (since := "2024-04-17")] @@ -1048,16 +1050,22 @@ theorem integral_eq_lintegral_of_nonneg_ae {f : α → ℝ} (hf : 0 ≤ᵐ[μ] f rw [Real.norm_eq_abs, abs_of_nonneg h] rw [this, hfi]; rfl -theorem integral_norm_eq_lintegral_nnnorm {P : Type*} [NormedAddCommGroup P] {f : α → P} - (hf : AEStronglyMeasurable f μ) : ∫ x, ‖f x‖ ∂μ = ENNReal.toReal (∫⁻ x, ‖f x‖₊ ∂μ) := by +theorem integral_norm_eq_lintegral_enorm {P : Type*} [NormedAddCommGroup P] {f : α → P} + (hf : AEStronglyMeasurable f μ) : ∫ x, ‖f x‖ ∂μ = (∫⁻ x, ‖f x‖ₑ ∂μ).toReal := by rw [integral_eq_lintegral_of_nonneg_ae _ hf.norm] - · simp_rw [ofReal_norm_eq_coe_nnnorm] + · simp_rw [ofReal_norm_eq_enorm] · filter_upwards; simp_rw [Pi.zero_apply, norm_nonneg, imp_true_iff] -theorem ofReal_integral_norm_eq_lintegral_nnnorm {P : Type*} [NormedAddCommGroup P] {f : α → P} - (hf : Integrable f μ) : ENNReal.ofReal (∫ x, ‖f x‖ ∂μ) = ∫⁻ x, ‖f x‖₊ ∂μ := by - rw [integral_norm_eq_lintegral_nnnorm hf.aestronglyMeasurable, ENNReal.ofReal_toReal] - exact lt_top_iff_ne_top.mp (hasFiniteIntegral_iff_nnnorm.mpr hf.2) +@[deprecated (since := "2025-01-21")] +alias integral_norm_eq_lintegral_nnnorm := integral_norm_eq_lintegral_enorm + +theorem ofReal_integral_norm_eq_lintegral_enorm {P : Type*} [NormedAddCommGroup P] {f : α → P} + (hf : Integrable f μ) : ENNReal.ofReal (∫ x, ‖f x‖ ∂μ) = ∫⁻ x, ‖f x‖ₑ ∂μ := by + rw [integral_norm_eq_lintegral_enorm hf.aestronglyMeasurable, ENNReal.ofReal_toReal] + exact lt_top_iff_ne_top.mp (hasFiniteIntegral_iff_enorm.mpr hf.2) + +@[deprecated (since := "2025-01-21")] +alias ofReal_integral_norm_eq_lintegral_nnnorm := ofReal_integral_norm_eq_lintegral_enorm theorem integral_eq_integral_pos_part_sub_integral_neg_part {f : α → ℝ} (hf : Integrable f μ) : ∫ a, f a ∂μ = ∫ a, (Real.toNNReal (f a) : ℝ) ∂μ - ∫ a, (Real.toNNReal (-f a) : ℝ) ∂μ := by @@ -1079,13 +1087,13 @@ theorem lintegral_coe_eq_integral (f : α → ℝ≥0) (hfi : Integrable (fun x rw [← lt_top_iff_ne_top] convert hfi.hasFiniteIntegral -- Porting note: `convert` no longer unfolds `HasFiniteIntegral` - simp_rw [hasFiniteIntegral_iff_nnnorm, NNReal.nnnorm_eq] + simp_rw [hasFiniteIntegral_iff_enorm, NNReal.enorm_eq] theorem ofReal_integral_eq_lintegral_ofReal {f : α → ℝ} (hfi : Integrable f μ) (f_nn : 0 ≤ᵐ[μ] f) : ENNReal.ofReal (∫ x, f x ∂μ) = ∫⁻ x, ENNReal.ofReal (f x) ∂μ := by have : f =ᵐ[μ] (‖f ·‖) := f_nn.mono fun _x hx ↦ (abs_of_nonneg hx).symm - simp_rw [integral_congr_ae this, ofReal_integral_norm_eq_lintegral_nnnorm hfi, - ← ofReal_norm_eq_coe_nnnorm] + simp_rw [integral_congr_ae this, ofReal_integral_norm_eq_lintegral_enorm hfi, + ← ofReal_norm_eq_enorm] exact lintegral_congr_ae (this.symm.fun_comp ENNReal.ofReal) theorem integral_toReal {f : α → ℝ≥0∞} (hfm : AEMeasurable f μ) (hf : ∀ᵐ x ∂μ, f x < ∞) : @@ -1249,7 +1257,7 @@ lemma tendsto_of_integral_tendsto_of_monotone {μ : Measure α} {f : ℕ → α have h := tendsto_of_lintegral_tendsto_of_monotone ?_ h_tendsto h_mono h_bound ?_ rotate_left · exact (hF_int.1.aemeasurable.sub (hf_int 0).1.aemeasurable).ennreal_ofReal - · exact ((lintegral_ofReal_le_lintegral_nnnorm _).trans_lt (hF_int.sub (hf_int 0)).2).ne + · exact ((lintegral_ofReal_le_lintegral_enorm _).trans_lt (hF_int.sub (hf_int 0)).2).ne filter_upwards [h, hf_mono, hf_bound] with a ha ha_mono ha_bound have h1 : (fun i ↦ f i a) = fun i ↦ (f' i a).toReal + f 0 a := by unfold f' @@ -1296,11 +1304,11 @@ section NormedAddCommGroup variable {H : Type*} [NormedAddCommGroup H] theorem L1.norm_eq_integral_norm (f : α →₁[μ] H) : ‖f‖ = ∫ a, ‖f a‖ ∂μ := by - simp only [eLpNorm, eLpNorm'_eq_lintegral_nnnorm, ENNReal.one_toReal, ENNReal.rpow_one, + simp only [eLpNorm, eLpNorm'_eq_lintegral_enorm, ENNReal.one_toReal, ENNReal.rpow_one, Lp.norm_def, if_false, ENNReal.one_ne_top, one_ne_zero, _root_.div_one] rw [integral_eq_lintegral_of_nonneg_ae (Eventually.of_forall (by simp [norm_nonneg])) (Lp.aestronglyMeasurable f).norm] - simp [ofReal_norm_eq_coe_nnnorm] + simp [ofReal_norm_eq_enorm] theorem L1.dist_eq_integral_dist (f g : α →₁[μ] H) : dist f g = ∫ a, dist (f a) (g a) ∂μ := by simp only [dist_eq_norm, L1.norm_eq_integral_norm] @@ -1314,14 +1322,14 @@ theorem L1.norm_of_fun_eq_integral_norm {f : α → H} (hf : Integrable f μ) : theorem Memℒp.eLpNorm_eq_integral_rpow_norm {f : α → H} {p : ℝ≥0∞} (hp1 : p ≠ 0) (hp2 : p ≠ ∞) (hf : Memℒp f p μ) : eLpNorm f p μ = ENNReal.ofReal ((∫ a, ‖f a‖ ^ p.toReal ∂μ) ^ p.toReal⁻¹) := by - have A : ∫⁻ a : α, ENNReal.ofReal (‖f a‖ ^ p.toReal) ∂μ = ∫⁻ a : α, ‖f a‖₊ ^ p.toReal ∂μ := by - simp_rw [← ofReal_rpow_of_nonneg (norm_nonneg _) toReal_nonneg, ofReal_norm_eq_coe_nnnorm] - simp only [eLpNorm_eq_lintegral_rpow_nnnorm hp1 hp2, one_div] + have A : ∫⁻ a : α, ENNReal.ofReal (‖f a‖ ^ p.toReal) ∂μ = ∫⁻ a : α, ‖f a‖ₑ ^ p.toReal ∂μ := by + simp_rw [← ofReal_rpow_of_nonneg (norm_nonneg _) toReal_nonneg, ofReal_norm_eq_enorm] + simp only [eLpNorm_eq_lintegral_rpow_enorm hp1 hp2, one_div] rw [integral_eq_lintegral_of_nonneg_ae]; rotate_left · exact ae_of_all _ fun x => by positivity · exact (hf.aestronglyMeasurable.norm.aemeasurable.pow_const _).aestronglyMeasurable rw [A, ← ofReal_rpow_of_nonneg toReal_nonneg (inv_nonneg.2 toReal_nonneg), ofReal_toReal] - exact (lintegral_rpow_nnnorm_lt_top_of_eLpNorm_lt_top hp1 hp2 hf.2).ne + exact (lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top hp1 hp2 hf.2).ne @[deprecated (since := "2024-07-27")] alias Memℒp.snorm_eq_integral_rpow_norm := Memℒp.eLpNorm_eq_integral_rpow_norm @@ -1428,8 +1436,8 @@ theorem tendsto_integral_norm_approxOn_sub (fmeas : Measurable f) (hf : Integrable f μ) [SeparableSpace (range f ∪ {0} : Set E)] : Tendsto (fun n ↦ ∫ x, ‖SimpleFunc.approxOn f fmeas (range f ∪ {0}) 0 (by simp) n x - f x‖ ∂μ) atTop (𝓝 0) := by - convert (tendsto_toReal zero_ne_top).comp (tendsto_approxOn_range_L1_nnnorm fmeas hf) with n - rw [integral_norm_eq_lintegral_nnnorm] + convert (tendsto_toReal zero_ne_top).comp (tendsto_approxOn_range_L1_enorm fmeas hf) with n + rw [integral_norm_eq_lintegral_enorm] · simp · apply (SimpleFunc.aestronglyMeasurable _).sub apply (stronglyMeasurable_iff_measurable_separable.2 ⟨fmeas, ?_⟩ ).aestronglyMeasurable @@ -1484,9 +1492,9 @@ theorem integral_finset_sum_measure {ι} {m : MeasurableSpace α} {f : α → G} theorem nndist_integral_add_measure_le_lintegral {f : α → G} (h₁ : Integrable f μ) (h₂ : Integrable f ν) : - (nndist (∫ x, f x ∂μ) (∫ x, f x ∂(μ + ν)) : ℝ≥0∞) ≤ ∫⁻ x, ‖f x‖₊ ∂ν := by + (nndist (∫ x, f x ∂μ) (∫ x, f x ∂(μ + ν)) : ℝ≥0∞) ≤ ∫⁻ x, ‖f x‖ₑ ∂ν := by rw [integral_add_measure h₁ h₂, nndist_comm, nndist_eq_nnnorm, add_sub_cancel_left] - exact ennnorm_integral_le_lintegral_ennnorm _ + exact enorm_integral_le_lintegral_enorm _ theorem hasSum_integral_measure {ι} {m : MeasurableSpace α} {f : α → G} {μ : ι → Measure α} (hf : Integrable f (Measure.sum μ)) : @@ -1495,11 +1503,11 @@ theorem hasSum_integral_measure {ι} {m : MeasurableSpace α} {f : α → G} {μ simp only [HasSum, ← integral_finset_sum_measure fun i _ => hfi i] refine Metric.nhds_basis_ball.tendsto_right_iff.mpr fun ε ε0 => ?_ lift ε to ℝ≥0 using ε0.le - have hf_lt : (∫⁻ x, ‖f x‖₊ ∂Measure.sum μ) < ∞ := hf.2 - have hmem : ∀ᶠ y in 𝓝 (∫⁻ x, ‖f x‖₊ ∂Measure.sum μ), (∫⁻ x, ‖f x‖₊ ∂Measure.sum μ) < y + ε := by + have hf_lt : (∫⁻ x, ‖f x‖ₑ ∂Measure.sum μ) < ∞ := hf.2 + have hmem : ∀ᶠ y in 𝓝 (∫⁻ x, ‖f x‖ₑ ∂Measure.sum μ), (∫⁻ x, ‖f x‖ₑ ∂Measure.sum μ) < y + ε := by refine tendsto_id.add tendsto_const_nhds (lt_mem_nhds (α := ℝ≥0∞) <| ENNReal.lt_add_right ?_ ?_) exacts [hf_lt.ne, ENNReal.coe_ne_zero.2 (NNReal.coe_ne_zero.1 ε0.ne')] - refine ((hasSum_lintegral_measure (fun x => ‖f x‖₊) μ).eventually hmem).mono fun s hs => ?_ + refine ((hasSum_lintegral_measure (fun x => ‖f x‖ₑ) μ).eventually hmem).mono fun s hs => ?_ obtain ⟨ν, hν⟩ : ∃ ν, (∑ i ∈ s, μ i) + ν = Measure.sum μ := by refine ⟨Measure.sum fun i : ↥(sᶜ : Set ι) => μ i, ?_⟩ simpa only [← Measure.sum_coe_finset] using Measure.sum_add_sum_compl (s : Set ι) μ @@ -1677,26 +1685,26 @@ theorem integral_mul_norm_le_Lp_mul_Lq {E} [NormedAddCommGroup E] {f g : α → rw [ENNReal.toReal_rpow, ENNReal.toReal_rpow, ← ENNReal.toReal_mul] -- replace norms by nnnorm have h_left : ∫⁻ a, ENNReal.ofReal (‖f a‖ * ‖g a‖) ∂μ = - ∫⁻ a, ((fun x => (‖f x‖₊ : ℝ≥0∞)) * fun x => (‖g x‖₊ : ℝ≥0∞)) a ∂μ := by - simp_rw [Pi.mul_apply, ← ofReal_norm_eq_coe_nnnorm, ENNReal.ofReal_mul (norm_nonneg _)] - have h_right_f : ∫⁻ a, ENNReal.ofReal (‖f a‖ ^ p) ∂μ = ∫⁻ a, (‖f a‖₊ : ℝ≥0∞) ^ p ∂μ := by + ∫⁻ a, ((‖f ·‖ₑ) * (‖g ·‖ₑ)) a ∂μ := by + simp_rw [Pi.mul_apply, ← ofReal_norm_eq_enorm, ENNReal.ofReal_mul (norm_nonneg _)] + have h_right_f : ∫⁻ a, .ofReal (‖f a‖ ^ p) ∂μ = ∫⁻ a, ‖f a‖ₑ ^ p ∂μ := by refine lintegral_congr fun x => ?_ - rw [← ofReal_norm_eq_coe_nnnorm, ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) hpq.nonneg] - have h_right_g : ∫⁻ a, ENNReal.ofReal (‖g a‖ ^ q) ∂μ = ∫⁻ a, (‖g a‖₊ : ℝ≥0∞) ^ q ∂μ := by + rw [← ofReal_norm_eq_enorm, ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) hpq.nonneg] + have h_right_g : ∫⁻ a, .ofReal (‖g a‖ ^ q) ∂μ = ∫⁻ a, ‖g a‖ₑ ^ q ∂μ := by refine lintegral_congr fun x => ?_ - rw [← ofReal_norm_eq_coe_nnnorm, ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) hpq.symm.nonneg] + rw [← ofReal_norm_eq_enorm, ENNReal.ofReal_rpow_of_nonneg (norm_nonneg _) hpq.symm.nonneg] rw [h_left, h_right_f, h_right_g] -- we can now apply `ENNReal.lintegral_mul_le_Lp_mul_Lq` (up to the `toReal` application) refine ENNReal.toReal_mono ?_ ?_ · refine ENNReal.mul_ne_top ?_ ?_ · convert hf.eLpNorm_ne_top - rw [eLpNorm_eq_lintegral_rpow_nnnorm] + rw [eLpNorm_eq_lintegral_rpow_enorm] · rw [ENNReal.toReal_ofReal hpq.nonneg] · rw [Ne, ENNReal.ofReal_eq_zero, not_le] exact hpq.pos · exact ENNReal.coe_ne_top · convert hg.eLpNorm_ne_top - rw [eLpNorm_eq_lintegral_rpow_nnnorm] + rw [eLpNorm_eq_lintegral_rpow_enorm] · rw [ENNReal.toReal_ofReal hpq.symm.nonneg] · rw [Ne, ENNReal.ofReal_eq_zero, not_le] exact hpq.symm.pos @@ -1838,12 +1846,12 @@ theorem integral_trim (hm : m ≤ m0) {f : β → G} (hf : StronglyMeasurable[m] integral_trim_simpleFunc hm (f_seq n) (hf_seq_int n) have h_lim_1 : atTop.Tendsto (fun n => ∫ x, f_seq n x ∂μ) (𝓝 (∫ x, f x ∂μ)) := by refine tendsto_integral_of_L1 f hf_int (Eventually.of_forall hf_seq_int) ?_ - exact SimpleFunc.tendsto_approxOn_range_L1_nnnorm (hf.mono hm).measurable hf_int + exact SimpleFunc.tendsto_approxOn_range_L1_enorm (hf.mono hm).measurable hf_int have h_lim_2 : atTop.Tendsto (fun n => ∫ x, f_seq n x ∂μ) (𝓝 (∫ x, f x ∂μ.trim hm)) := by simp_rw [hf_seq_eq] refine @tendsto_integral_of_L1 β G _ _ m (μ.trim hm) _ f (hf_int.trim hm hf) _ _ (Eventually.of_forall hf_seq_int_m) ?_ - exact @SimpleFunc.tendsto_approxOn_range_L1_nnnorm β G m _ _ _ f _ _ hf.measurable + exact @SimpleFunc.tendsto_approxOn_range_L1_enorm β G m _ _ _ f _ _ hf.measurable (hf_int.trim hm hf) exact tendsto_nhds_unique h_lim_1 h_lim_2 diff --git a/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean b/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean index d76ba1fe92b5b..6eb67e7491eb7 100644 --- a/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean +++ b/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean @@ -47,7 +47,7 @@ theorem lintegral_lt_top_of_nnreal (f : X →ᵇ ℝ≥0) : ∫⁻ x, f x ∂μ theorem integrable_of_nnreal [OpensMeasurableSpace X] (f : X →ᵇ ℝ≥0) : Integrable (((↑) : ℝ≥0 → ℝ) ∘ ⇑f) μ := by refine ⟨(NNReal.continuous_coe.comp f.continuous).measurable.aestronglyMeasurable, ?_⟩ - simp only [hasFiniteIntegral_iff_nnnorm, Function.comp_apply, NNReal.nnnorm_eq] + simp only [hasFiniteIntegral_iff_enorm, Function.comp_apply, NNReal.enorm_eq] exact lintegral_lt_top_of_nnreal _ f theorem integral_eq_integral_nnrealPart_sub [OpensMeasurableSpace X] (f : X →ᵇ ℝ) : diff --git a/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean b/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean index 3a7713df35dda..063908dfd80a5 100644 --- a/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean +++ b/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean @@ -102,11 +102,11 @@ theorem hasSum_integral_of_dominated_convergence {ι} [Countable ι] {F : ι → _ ≤ ∑' n, bound n a := sum_le_tsum _ (fun n _ => ha0 n) has theorem integral_tsum {ι} [Countable ι] {f : ι → α → G} (hf : ∀ i, AEStronglyMeasurable (f i) μ) - (hf' : ∑' i, ∫⁻ a : α, ‖f i a‖₊ ∂μ ≠ ∞) : + (hf' : ∑' i, ∫⁻ a : α, ‖f i a‖ₑ ∂μ ≠ ∞) : ∫ a : α, ∑' i, f i a ∂μ = ∑' i, ∫ a : α, f i a ∂μ := by by_cases hG : CompleteSpace G; swap · simp [integral, hG] - have hf'' : ∀ i, AEMeasurable (fun x => (‖f i x‖₊ : ℝ≥0∞)) μ := fun i => (hf i).ennnorm + have hf'' i : AEMeasurable (‖f i ·‖ₑ) μ := (hf i).enorm have hhh : ∀ᵐ a : α ∂μ, Summable fun n => (‖f n a‖₊ : ℝ) := by rw [← lintegral_tsum hf''] at hf' refine (ae_lt_top' (AEMeasurable.ennreal_tsum hf'') hf').mono ?_ @@ -124,7 +124,7 @@ theorem integral_tsum {ι} [Countable ι] {f : ι → α → G} (hf : ∀ i, AES apply AEMeasurable.nnreal_tsum exact fun i => (hf i).nnnorm.aemeasurable · dsimp [HasFiniteIntegral] - have : ∫⁻ a, ∑' n, ‖f n a‖₊ ∂μ < ⊤ := by rwa [lintegral_tsum hf'', lt_top_iff_ne_top] + have : ∫⁻ a, ∑' n, ‖f n a‖ₑ ∂μ < ⊤ := by rwa [lintegral_tsum hf'', lt_top_iff_ne_top] convert this using 1 apply lintegral_congr_ae simp_rw [← coe_nnnorm, ← NNReal.coe_tsum, enorm_eq_nnnorm, NNReal.nnnorm_eq] @@ -140,14 +140,13 @@ lemma hasSum_integral_of_summable_integral_norm {ι} [Countable ι] {F : ι → · simp [integral, hE, hasSum_zero] rw [integral_tsum (fun i ↦ (hF_int i).1)] · exact (hF_sum.of_norm_bounded _ fun i ↦ norm_integral_le_integral_norm _).hasSum - have (i : ι) : ∫⁻ (a : α), ‖F i a‖₊ ∂μ = ‖(∫ a : α, ‖F i a‖ ∂μ)‖₊ := by + have (i : ι) : ∫⁻ a, ‖F i a‖ₑ ∂μ = ‖∫ a, ‖F i a‖ ∂μ‖ₑ := by + dsimp [enorm] rw [lintegral_coe_eq_integral _ (hF_int i).norm, coe_nnreal_eq, coe_nnnorm, Real.norm_of_nonneg (integral_nonneg (fun a ↦ norm_nonneg (F i a)))] simp only [coe_nnnorm] - rw [funext this, ← ENNReal.coe_tsum] - · apply coe_ne_top - · simp_rw [← NNReal.summable_coe, coe_nnnorm] - exact hF_sum.abs + rw [funext this] + exact ENNReal.tsum_coe_ne_top_iff_summable.2 <| NNReal.summable_coe.1 hF_sum.abs lemma integral_tsum_of_summable_integral_norm {ι} [Countable ι] {F : ι → α → E} (hF_int : ∀ i : ι, Integrable (F i) μ) (hF_sum : Summable fun i ↦ ∫ a, ‖F i a‖ ∂μ) : diff --git a/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean b/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean index a88490002c8be..9eec63db434d4 100644 --- a/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean +++ b/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean @@ -1223,7 +1223,7 @@ theorem integrableOn_deriv_right_of_nonneg (hcont : ContinuousOn g (Icc a b)) let F : ℝ → ℝ := (↑) ∘ f have intF : IntegrableOn F (Ioo a b) := by refine ⟨f.measurable.coe_nnreal_real.aestronglyMeasurable, ?_⟩ - simpa only [F, hasFiniteIntegral_iff_nnnorm, comp_apply, NNReal.nnnorm_eq] using fint + simpa only [F, hasFiniteIntegral_iff_enorm, comp_apply, NNReal.enorm_eq] using fint have A : ∫⁻ x : ℝ in Ioo a b, f x = ENNReal.ofReal (∫ x in Ioo a b, F x) := lintegral_coe_eq_integral _ intF rw [A] at hf diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index 9093ea80babe2..e46bfe3e48acd 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -232,8 +232,8 @@ theorem MeasurePreserving.integrableOn_image [MeasurableSpace β] {e : α → β theorem integrable_indicator_iff (hs : MeasurableSet s) : Integrable (indicator s f) μ ↔ IntegrableOn f s μ := by - simp_rw [IntegrableOn, Integrable, hasFiniteIntegral_iff_nnnorm, - nnnorm_indicator_eq_indicator_nnnorm, ENNReal.coe_indicator, lintegral_indicator hs, + simp_rw [IntegrableOn, Integrable, hasFiniteIntegral_iff_enorm, + enorm_indicator_eq_indicator_enorm, lintegral_indicator hs, aestronglyMeasurable_indicator_iff hs] theorem IntegrableOn.integrable_indicator (h : IntegrableOn f s μ) (hs : MeasurableSet s) : @@ -335,7 +335,7 @@ theorem integrableOn_Lp_of_measure_ne_top {E} [NormedAddCommGroup E] {p : ℝ≥ theorem Integrable.lintegral_lt_top {f : α → ℝ} (hf : Integrable f μ) : (∫⁻ x, ENNReal.ofReal (f x) ∂μ) < ∞ := calc - (∫⁻ x, ENNReal.ofReal (f x) ∂μ) ≤ ∫⁻ x, ↑‖f x‖₊ ∂μ := lintegral_ofReal_le_lintegral_nnnorm f + (∫⁻ x, ENNReal.ofReal (f x) ∂μ) ≤ ∫⁻ x, ↑‖f x‖₊ ∂μ := lintegral_ofReal_le_lintegral_enorm f _ < ∞ := hf.2 theorem IntegrableOn.setLIntegral_lt_top {f : α → ℝ} {s : Set α} (hf : IntegrableOn f s μ) : diff --git a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean index 99c22b52d22c3..e0363619f99bb 100644 --- a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean +++ b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean @@ -396,46 +396,62 @@ section Integrable variable {α ι E : Type*} [MeasurableSpace α] {μ : Measure α} {l : Filter ι} [NormedAddCommGroup E] -theorem AECover.integrable_of_lintegral_nnnorm_bounded [l.NeBot] [l.IsCountablyGenerated] +theorem AECover.integrable_of_lintegral_enorm_bounded [l.NeBot] [l.IsCountablyGenerated] {φ : ι → Set α} (hφ : AECover μ l φ) {f : α → E} (I : ℝ) (hfm : AEStronglyMeasurable f μ) - (hbounded : ∀ᶠ i in l, (∫⁻ x in φ i, ‖f x‖₊ ∂μ) ≤ ENNReal.ofReal I) : Integrable f μ := by + (hbounded : ∀ᶠ i in l, ∫⁻ x in φ i, ‖f x‖ₑ ∂μ ≤ ENNReal.ofReal I) : Integrable f μ := by refine ⟨hfm, (le_of_tendsto ?_ hbounded).trans_lt ENNReal.ofReal_lt_top⟩ - exact hφ.lintegral_tendsto_of_countably_generated hfm.ennnorm + exact hφ.lintegral_tendsto_of_countably_generated hfm.enorm -theorem AECover.integrable_of_lintegral_nnnorm_tendsto [l.NeBot] [l.IsCountablyGenerated] +@[deprecated (since := "2025-01-22")] +alias AECover.integrable_of_lintegral_nnnorm_bounded := + AECover.integrable_of_lintegral_enorm_bounded + +theorem AECover.integrable_of_lintegral_enorm_tendsto [l.NeBot] [l.IsCountablyGenerated] {φ : ι → Set α} (hφ : AECover μ l φ) {f : α → E} (I : ℝ) (hfm : AEStronglyMeasurable f μ) - (htendsto : Tendsto (fun i => ∫⁻ x in φ i, ‖f x‖₊ ∂μ) l (𝓝 <| ENNReal.ofReal I)) : + (htendsto : Tendsto (fun i => ∫⁻ x in φ i, ‖f x‖ₑ ∂μ) l (𝓝 <| .ofReal I)) : Integrable f μ := by - refine hφ.integrable_of_lintegral_nnnorm_bounded (max 1 (I + 1)) hfm ?_ + refine hφ.integrable_of_lintegral_enorm_bounded (max 1 (I + 1)) hfm ?_ refine htendsto.eventually (ge_mem_nhds ?_) refine (ENNReal.ofReal_lt_ofReal_iff (lt_max_of_lt_left zero_lt_one)).2 ?_ exact lt_max_of_lt_right (lt_add_one I) -theorem AECover.integrable_of_lintegral_nnnorm_bounded' [l.NeBot] [l.IsCountablyGenerated] +@[deprecated (since := "2025-01-22")] +alias AECover.integrable_of_lintegral_nnnorm_tendsto := + AECover.integrable_of_lintegral_enorm_tendsto + +theorem AECover.integrable_of_lintegral_enorm_bounded' [l.NeBot] [l.IsCountablyGenerated] {φ : ι → Set α} (hφ : AECover μ l φ) {f : α → E} (I : ℝ≥0) (hfm : AEStronglyMeasurable f μ) - (hbounded : ∀ᶠ i in l, (∫⁻ x in φ i, ‖f x‖₊ ∂μ) ≤ I) : Integrable f μ := - hφ.integrable_of_lintegral_nnnorm_bounded I hfm + (hbounded : ∀ᶠ i in l, ∫⁻ x in φ i, ‖f x‖ₑ ∂μ ≤ I) : Integrable f μ := + hφ.integrable_of_lintegral_enorm_bounded I hfm (by simpa only [ENNReal.ofReal_coe_nnreal] using hbounded) -theorem AECover.integrable_of_lintegral_nnnorm_tendsto' [l.NeBot] [l.IsCountablyGenerated] +@[deprecated (since := "2025-01-22")] +alias AECover.integrable_of_lintegral_nnnorm_bounded' := + AECover.integrable_of_lintegral_enorm_bounded' + +theorem AECover.integrable_of_lintegral_enorm_tendsto' [l.NeBot] [l.IsCountablyGenerated] {φ : ι → Set α} (hφ : AECover μ l φ) {f : α → E} (I : ℝ≥0) (hfm : AEStronglyMeasurable f μ) - (htendsto : Tendsto (fun i => ∫⁻ x in φ i, ‖f x‖₊ ∂μ) l (𝓝 I)) : Integrable f μ := - hφ.integrable_of_lintegral_nnnorm_tendsto I hfm + (htendsto : Tendsto (fun i => ∫⁻ x in φ i, ‖f x‖ₑ ∂μ) l (𝓝 I)) : Integrable f μ := + hφ.integrable_of_lintegral_enorm_tendsto I hfm (by simpa only [ENNReal.ofReal_coe_nnreal] using htendsto) +@[deprecated (since := "2025-01-22")] +alias AECover.integrable_of_lintegral_nnnorm_tendsto' := + AECover.integrable_of_lintegral_enorm_tendsto' + theorem AECover.integrable_of_integral_norm_bounded [l.NeBot] [l.IsCountablyGenerated] {φ : ι → Set α} (hφ : AECover μ l φ) {f : α → E} (I : ℝ) (hfi : ∀ i, IntegrableOn f (φ i) μ) (hbounded : ∀ᶠ i in l, (∫ x in φ i, ‖f x‖ ∂μ) ≤ I) : Integrable f μ := by have hfm : AEStronglyMeasurable f μ := hφ.aestronglyMeasurable fun i => (hfi i).aestronglyMeasurable - refine hφ.integrable_of_lintegral_nnnorm_bounded I hfm ?_ + refine hφ.integrable_of_lintegral_enorm_bounded I hfm ?_ conv at hbounded in integral _ _ => rw [integral_eq_lintegral_of_nonneg_ae (ae_of_all _ fun x => @norm_nonneg E _ (f x)) hfm.norm.restrict] conv at hbounded in ENNReal.ofReal _ => rw [← coe_nnnorm, ENNReal.ofReal_coe_nnreal] refine hbounded.mono fun i hi => ?_ - rw [← ENNReal.ofReal_toReal <| ne_top_of_lt <| hasFiniteIntegral_iff_nnnorm.mp (hfi i).2] + rw [← ENNReal.ofReal_toReal <| ne_top_of_lt <| hasFiniteIntegral_iff_enorm.mp (hfi i).2] apply ENNReal.ofReal_le_ofReal hi theorem AECover.integrable_of_integral_norm_tendsto [l.NeBot] [l.IsCountablyGenerated] @@ -958,23 +974,27 @@ theorem _root_.HasCompactSupport.integral_Iic_deriv_eq (hf : ContDiff ℝ 1 f) exact h2f.filter_mono _root_.atBot_le_cocompact |>.tendsto open UniformSpace in -lemma _root_.HasCompactSupport.ennnorm_le_lintegral_Ici_deriv +lemma _root_.HasCompactSupport.enorm_le_lintegral_Ici_deriv {F : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] {f : ℝ → F} (hf : ContDiff ℝ 1 f) (h'f : HasCompactSupport f) (x : ℝ) : - (‖f x‖₊ : ℝ≥0∞) ≤ ∫⁻ y in Iic x, ‖deriv f y‖₊ := by + ‖f x‖ₑ ≤ ∫⁻ y in Iic x, ‖deriv f y‖ₑ := by let I : F →L[ℝ] Completion F := Completion.toComplL let f' : ℝ → Completion F := I ∘ f have hf' : ContDiff ℝ 1 f' := hf.continuousLinearMap_comp I have h'f' : HasCompactSupport f' := h'f.comp_left rfl - have : (‖f' x‖₊ : ℝ≥0∞) ≤ ∫⁻ y in Iic x, ‖deriv f' y‖₊ := by + have : ‖f' x‖ₑ ≤ ∫⁻ y in Iic x, ‖deriv f' y‖ₑ := by rw [← HasCompactSupport.integral_Iic_deriv_eq hf' h'f' x] - exact ennnorm_integral_le_lintegral_ennnorm _ + exact enorm_integral_le_lintegral_enorm _ convert this with y - · simp [f', I, Completion.nnnorm_coe] + · simp [f', I, Completion.enorm_coe] · rw [fderiv_comp_deriv _ I.differentiableAt (hf.differentiable le_rfl _)] simp only [ContinuousLinearMap.fderiv] simp [I] +@[deprecated (since := "2025-01-22")] +alias _root_.HasCompactSupport.ennnorm_le_lintegral_Ici_deriv := + HasCompactSupport.enorm_le_lintegral_Ici_deriv + end IicFTC section UnivFTC diff --git a/Mathlib/MeasureTheory/Integral/Lebesgue.lean b/Mathlib/MeasureTheory/Integral/Lebesgue.lean index b0cbd7bec0648..171fca1f4b81a 100644 --- a/Mathlib/MeasureTheory/Integral/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Integral/Lebesgue.lean @@ -323,22 +323,31 @@ theorem setLIntegral_congr_fun {f g : α → ℝ≥0∞} {s : Set α} (hs : Meas @[deprecated (since := "2024-06-29")] alias set_lintegral_congr_fun := setLIntegral_congr_fun -theorem lintegral_ofReal_le_lintegral_nnnorm (f : α → ℝ) : - ∫⁻ x, ENNReal.ofReal (f x) ∂μ ≤ ∫⁻ x, ‖f x‖₊ ∂μ := by - simp_rw [← ofReal_norm_eq_coe_nnnorm] +theorem lintegral_ofReal_le_lintegral_enorm (f : α → ℝ) : + ∫⁻ x, ENNReal.ofReal (f x) ∂μ ≤ ∫⁻ x, ‖f x‖ₑ ∂μ := by + simp_rw [← ofReal_norm_eq_enorm] refine lintegral_mono fun x => ENNReal.ofReal_le_ofReal ?_ rw [Real.norm_eq_abs] exact le_abs_self (f x) -theorem lintegral_nnnorm_eq_of_ae_nonneg {f : α → ℝ} (h_nonneg : 0 ≤ᵐ[μ] f) : - ∫⁻ x, ‖f x‖₊ ∂μ = ∫⁻ x, ENNReal.ofReal (f x) ∂μ := by +@[deprecated (since := "2025-01-17")] +alias lintegral_ofReal_le_lintegral_nnnorm := lintegral_ofReal_le_lintegral_enorm + +theorem lintegral_enorm_of_ae_nonneg {f : α → ℝ} (h_nonneg : 0 ≤ᵐ[μ] f) : + ∫⁻ x, ‖f x‖ₑ ∂μ = ∫⁻ x, .ofReal (f x) ∂μ := by apply lintegral_congr_ae filter_upwards [h_nonneg] with x hx - rw [Real.nnnorm_of_nonneg hx, ENNReal.ofReal_eq_coe_nnreal hx] + rw [Real.enorm_eq_ofReal hx] + +@[deprecated (since := "2025-01-17")] +alias lintegral_nnnorm_eq_of_ae_nonneg := lintegral_enorm_of_ae_nonneg + +theorem lintegral_enorm_of_nonneg {f : α → ℝ} (h_nonneg : 0 ≤ f) : + ∫⁻ x, ‖f x‖ₑ ∂μ = ∫⁻ x, .ofReal (f x) ∂μ := + lintegral_enorm_of_ae_nonneg <| .of_forall h_nonneg -theorem lintegral_nnnorm_eq_of_nonneg {f : α → ℝ} (h_nonneg : 0 ≤ f) : - ∫⁻ x, ‖f x‖₊ ∂μ = ∫⁻ x, ENNReal.ofReal (f x) ∂μ := - lintegral_nnnorm_eq_of_ae_nonneg (Filter.Eventually.of_forall h_nonneg) +@[deprecated (since := "2025-01-17")] +alias lintegral_nnnorm_eq_of_nonneg := lintegral_enorm_of_nonneg /-- **Monotone convergence theorem** -- sometimes called **Beppo-Levi convergence**. See `lintegral_iSup_directed` for a more general form. -/ diff --git a/Mathlib/MeasureTheory/Integral/Prod.lean b/Mathlib/MeasureTheory/Integral/Prod.lean index 886d5b00bc910..ac9f5a09023f9 100644 --- a/Mathlib/MeasureTheory/Integral/Prod.lean +++ b/Mathlib/MeasureTheory/Integral/Prod.lean @@ -59,7 +59,7 @@ along one of the variables (using either the Lebesgue or Bochner integral) is me theorem measurableSet_integrable [SFinite ν] ⦃f : α → β → E⦄ (hf : StronglyMeasurable (uncurry f)) : MeasurableSet {x | Integrable (f x) ν} := by simp_rw [Integrable, hf.of_uncurry_left.aestronglyMeasurable, true_and] - exact measurableSet_lt (Measurable.lintegral_prod_right hf.ennnorm) measurable_const + exact measurableSet_lt (Measurable.lintegral_prod_right hf.enorm) measurable_const section @@ -148,7 +148,7 @@ variable [SFinite ν] theorem integrable_measure_prod_mk_left {s : Set (α × β)} (hs : MeasurableSet s) (h2s : (μ.prod ν) s ≠ ∞) : Integrable (fun x => (ν (Prod.mk x ⁻¹' s)).toReal) μ := by refine ⟨(measurable_measure_prod_mk_left hs).ennreal_toReal.aemeasurable.aestronglyMeasurable, ?_⟩ - simp_rw [hasFiniteIntegral_iff_nnnorm, ennnorm_eq_ofReal toReal_nonneg] + simp_rw [hasFiniteIntegral_iff_enorm, enorm_eq_ofReal toReal_nonneg] convert h2s.lt_top using 1 rw [prod_apply hs] apply lintegral_congr_ae @@ -216,11 +216,11 @@ theorem hasFiniteIntegral_prod_iff ⦃f : α × β → E⦄ (h1f : StronglyMeasu HasFiniteIntegral f (μ.prod ν) ↔ (∀ᵐ x ∂μ, HasFiniteIntegral (fun y => f (x, y)) ν) ∧ HasFiniteIntegral (fun x => ∫ y, ‖f (x, y)‖ ∂ν) μ := by - simp only [hasFiniteIntegral_iff_nnnorm, lintegral_prod_of_measurable _ h1f.ennnorm] + simp only [hasFiniteIntegral_iff_enorm, lintegral_prod_of_measurable _ h1f.enorm] have (x) : ∀ᵐ y ∂ν, 0 ≤ ‖f (x, y)‖ := by filter_upwards with y using norm_nonneg _ simp_rw [integral_eq_lintegral_of_nonneg_ae (this _) (h1f.norm.comp_measurable measurable_prod_mk_left).aestronglyMeasurable, - ennnorm_eq_ofReal toReal_nonneg, ofReal_norm_eq_coe_nnnorm] + enorm_eq_ofReal toReal_nonneg, ofReal_norm_eq_enorm] -- this fact is probably too specialized to be its own lemma have : ∀ {p q r : Prop} (_ : r → p), (r ↔ p ∧ q) ↔ p → (r ↔ q) := fun {p q r} h1 => by rw [← and_congr_right_iff, and_iff_right_of_imp h1] @@ -228,7 +228,7 @@ theorem hasFiniteIntegral_prod_iff ⦃f : α × β → E⦄ (h1f : StronglyMeasu · intro h2f; rw [lintegral_congr_ae] filter_upwards [h2f] with x hx rw [ofReal_toReal]; rw [← lt_top_iff_ne_top]; exact hx - · intro h2f; refine ae_lt_top ?_ h2f.ne; exact h1f.ennnorm.lintegral_prod_right' + · intro h2f; refine ae_lt_top ?_ h2f.ne; exact h1f.enorm.lintegral_prod_right' theorem hasFiniteIntegral_prod_iff' ⦃f : α × β → E⦄ (h1f : AEStronglyMeasurable f (μ.prod ν)) : HasFiniteIntegral f (μ.prod ν) ↔ @@ -385,17 +385,15 @@ theorem continuous_integral_integral : refine tendsto_integral_of_L1 _ (L1.integrable_coeFn g).integral_prod_left (Eventually.of_forall fun h => (L1.integrable_coeFn h).integral_prod_left) ?_ - simp_rw [← - lintegral_fn_integral_sub (fun x => (‖x‖₊ : ℝ≥0∞)) (L1.integrable_coeFn _) - (L1.integrable_coeFn g)] + simp_rw [← lintegral_fn_integral_sub _ (L1.integrable_coeFn _) (L1.integrable_coeFn g)] apply tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds _ (fun i => zero_le _) _ - · exact fun i => ∫⁻ x, ∫⁻ y, ‖i (x, y) - g (x, y)‖₊ ∂ν ∂μ - swap; · exact fun i => lintegral_mono fun x => ennnorm_integral_le_lintegral_ennnorm _ + · exact fun i => ∫⁻ x, ∫⁻ y, ‖i (x, y) - g (x, y)‖ₑ ∂ν ∂μ + swap; · exact fun i => lintegral_mono fun x => enorm_integral_le_lintegral_enorm _ show - Tendsto (fun i : α × β →₁[μ.prod ν] E => ∫⁻ x, ∫⁻ y : β, ‖i (x, y) - g (x, y)‖₊ ∂ν ∂μ) (𝓝 g) + Tendsto (fun i : α × β →₁[μ.prod ν] E => ∫⁻ x, ∫⁻ y : β, ‖i (x, y) - g (x, y)‖ₑ ∂ν ∂μ) (𝓝 g) (𝓝 0) - have : ∀ i : α × β →₁[μ.prod ν] E, Measurable fun z => (‖i z - g z‖₊ : ℝ≥0∞) := fun i => - ((Lp.stronglyMeasurable i).sub (Lp.stronglyMeasurable g)).ennnorm + have this (i : α × β →₁[μ.prod ν] E) : Measurable fun z => ‖i z - g z‖ₑ := + ((Lp.stronglyMeasurable i).sub (Lp.stronglyMeasurable g)).enorm -- Porting note: was -- simp_rw [← lintegral_prod_of_measurable _ (this _), ← L1.ofReal_norm_sub_eq_lintegral, ← -- ofReal_zero] diff --git a/Mathlib/MeasureTheory/Integral/SetIntegral.lean b/Mathlib/MeasureTheory/Integral/SetIntegral.lean index f97aa2469f9e8..0a85688f8e170 100644 --- a/Mathlib/MeasureTheory/Integral/SetIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/SetIntegral.lean @@ -211,8 +211,7 @@ theorem ofReal_setIntegral_one_of_measure_ne_top {X : Type*} {m : MeasurableSpac ENNReal.ofReal (∫ _ in s, (1 : ℝ) ∂μ) = ENNReal.ofReal (∫ _ in s, ‖(1 : ℝ)‖ ∂μ) := by simp only [norm_one] _ = ∫⁻ _ in s, 1 ∂μ := by - rw [ofReal_integral_norm_eq_lintegral_nnnorm (integrableOn_const.2 (Or.inr hs.lt_top))] - simp only [nnnorm_one, ENNReal.coe_one] + simpa [ofReal_integral_norm_eq_lintegral_enorm (integrableOn_const.2 (.inr hs.lt_top))] _ = μ s := setLIntegral_one _ @[deprecated (since := "2024-04-17")] @@ -244,7 +243,7 @@ theorem tendsto_setIntegral_of_monotone have hSm : MeasurableSet S := MeasurableSet.iUnion_of_monotone h_mono hsm have hsub {i} : s i ⊆ S := subset_iUnion s i rw [← withDensity_apply _ hSm] at hfi' - set ν := μ.withDensity fun x => ‖f x‖₊ with hν + set ν := μ.withDensity (‖f ·‖ₑ) with hν 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 + ε) := @@ -252,7 +251,7 @@ theorem tendsto_setIntegral_of_monotone 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] - refine (ennnorm_integral_le_lintegral_ennnorm _).trans ?_ + refine (enorm_integral_le_lintegral_enorm _).trans ?_ rw [← withDensity_apply _ (hSm.diff (hsm _)), ← hν, measure_diff hsub (hsm _).nullMeasurableSet] exacts [tsub_le_iff_tsub_le.mp hi.1, (hi.2.trans_lt <| ENNReal.add_lt_top.2 ⟨hfi', ENNReal.coe_lt_top⟩).ne] @@ -661,7 +660,7 @@ theorem setIntegral_gt_gt {R : ℝ} {f : X → ℝ} (hR : 0 ≤ R) (μ {x | ↑R < f x}).toReal * R < ∫ x in {x | ↑R < f x}, f x ∂μ := by have : IntegrableOn (fun _ => R) {x | ↑R < f x} μ := by refine ⟨aestronglyMeasurable_const, lt_of_le_of_lt ?_ hfint.2⟩ - refine setLIntegral_mono_ae hfint.1.ennnorm <| ae_of_all _ fun x hx => ?_ + refine setLIntegral_mono_ae hfint.1.enorm <| ae_of_all _ fun x hx => ?_ simp only [ENNReal.coe_le_coe, Real.nnnorm_of_nonneg hR, enorm_eq_nnnorm, Real.nnnorm_of_nonneg (hR.trans <| le_of_lt hx), Subtype.mk_le_mk] exact le_of_lt hx @@ -1416,10 +1415,7 @@ theorem integral_withDensity_eq_integral_smul {f : X → ℝ≥0} (f_meas : Meas · rfl · exact integral_nonneg fun x => NNReal.coe_nonneg _ · refine ⟨f_meas.coe_nnreal_real.aemeasurable.aestronglyMeasurable, ?_⟩ - rw [withDensity_apply _ s_meas] at hs - rw [hasFiniteIntegral_iff_nnnorm] - convert hs with x - simp only [NNReal.nnnorm_eq] + simpa [withDensity_apply _ s_meas, hasFiniteIntegral_iff_enorm] using hs · intro u u' _ u_int u'_int h h' change (∫ x : X, u x + u' x ∂μ.withDensity fun x : X => ↑(f x)) = ∫ x : X, f x • (u x + u' x) ∂μ diff --git a/Mathlib/MeasureTheory/Integral/SetToL1.lean b/Mathlib/MeasureTheory/Integral/SetToL1.lean index 9c3a4587da7c6..2fdacefa4379d 100644 --- a/Mathlib/MeasureTheory/Integral/SetToL1.lean +++ b/Mathlib/MeasureTheory/Integral/SetToL1.lean @@ -607,13 +607,13 @@ namespace SimpleFunc theorem norm_eq_sum_mul (f : α →₁ₛ[μ] G) : ‖f‖ = ∑ x ∈ (toSimpleFunc f).range, (μ (toSimpleFunc f ⁻¹' {x})).toReal * ‖x‖ := by - rw [norm_toSimpleFunc, eLpNorm_one_eq_lintegral_nnnorm] - have h_eq := SimpleFunc.map_apply (fun x => (‖x‖₊ : ℝ≥0∞)) (toSimpleFunc f) + rw [norm_toSimpleFunc, eLpNorm_one_eq_lintegral_enorm] + have h_eq := SimpleFunc.map_apply (‖·‖ₑ) (toSimpleFunc f) simp_rw [← h_eq] rw [SimpleFunc.lintegral_eq_lintegral, SimpleFunc.map_lintegral, ENNReal.toReal_sum] · congr ext1 x - rw [ENNReal.toReal_mul, mul_comm, ← ofReal_norm_eq_coe_nnnorm, + rw [ENNReal.toReal_mul, mul_comm, ← ofReal_norm_eq_enorm, ENNReal.toReal_ofReal (norm_nonneg _)] · intro x _ by_cases hx0 : x = 0 @@ -1350,14 +1350,14 @@ theorem continuous_setToFun (hT : DominatedFinMeasAdditive μ T C) : /-- If `F i → f` in `L1`, then `setToFun μ T hT (F i) → setToFun μ T hT f`. -/ theorem tendsto_setToFun_of_L1 (hT : DominatedFinMeasAdditive μ T C) {ι} (f : α → E) (hfi : Integrable f μ) {fs : ι → α → E} {l : Filter ι} (hfsi : ∀ᶠ i in l, Integrable (fs i) μ) - (hfs : Tendsto (fun i => ∫⁻ x, ‖fs i x - f x‖₊ ∂μ) l (𝓝 0)) : + (hfs : Tendsto (fun i => ∫⁻ x, ‖fs i x - f x‖ₑ ∂μ) l (𝓝 0)) : Tendsto (fun i => setToFun μ T hT (fs i)) l (𝓝 <| setToFun μ T hT f) := by classical let f_lp := hfi.toL1 f let F_lp i := if hFi : Integrable (fs i) μ then hFi.toL1 (fs i) else 0 have tendsto_L1 : Tendsto F_lp l (𝓝 f_lp) := by rw [Lp.tendsto_Lp_iff_tendsto_ℒp'] - simp_rw [eLpNorm_one_eq_lintegral_nnnorm, Pi.sub_apply] + simp_rw [eLpNorm_one_eq_lintegral_enorm, Pi.sub_apply] refine (tendsto_congr' ?_).mp hfs filter_upwards [hfsi] with i hi refine lintegral_congr_ae ?_ @@ -1380,7 +1380,7 @@ theorem tendsto_setToFun_approxOn_of_measurable (hT : DominatedFinMeasAdditive (𝓝 <| setToFun μ T hT f) := tendsto_setToFun_of_L1 hT _ hfi (Eventually.of_forall (SimpleFunc.integrable_approxOn hfm hfi h₀ h₀i)) - (SimpleFunc.tendsto_approxOn_L1_nnnorm hfm _ hs (hfi.sub h₀i).2) + (SimpleFunc.tendsto_approxOn_L1_enorm hfm _ hs (hfi.sub h₀i).2) theorem tendsto_setToFun_approxOn_of_measurable_of_range_subset (hT : DominatedFinMeasAdditive μ T C) [MeasurableSpace E] [BorelSpace E] {f : α → E} @@ -1569,7 +1569,7 @@ theorem tendsto_setToFun_of_dominated_convergence (hT : DominatedFinMeasAdditive rw [← Integrable.toL1_sub] refine ((fs_int n).sub f_int).coeFn_toL1.mono fun x hx => ?_ dsimp only - rw [hx, ofReal_norm_eq_coe_nnnorm, Pi.sub_apply] + rw [hx, ofReal_norm_eq_enorm, Pi.sub_apply] /-- Lebesgue dominated convergence theorem for filters with a countable basis -/ theorem tendsto_setToFun_filter_of_dominated_convergence (hT : DominatedFinMeasAdditive μ T C) {ι} diff --git a/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean b/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean index a782f7e429aeb..7915e996c9a65 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean @@ -393,7 +393,7 @@ lemma QuotientGroup.integral_eq_integral_automorphize {E : Type*} [NormedAddComm rw [integral_tsum] · exact fun i ↦ (hf₁.1.comp_quasiMeasurePreserving (measurePreserving_smul i μ).quasiMeasurePreserving).restrict - · rw [← h𝓕.lintegral_eq_tsum'' (fun x ↦ ‖f x‖₊)] + · rw [← h𝓕.lintegral_eq_tsum'' (‖f ·‖ₑ)] exact ne_of_lt hf₁.2 /-- This is the **Unfolding Trick**: Given a subgroup `Γ` of a group `G`, the integral of a @@ -403,7 +403,7 @@ lemma QuotientGroup.integral_eq_integral_automorphize {E : Type*} [NormedAddComm lemma QuotientGroup.integral_mul_eq_integral_automorphize_mul {K : Type*} [NormedField K] [NormedSpace ℝ K] [μ.IsMulRightInvariant] {f : G → K} (f_ℒ_1 : Integrable f μ) {g : G ⧸ Γ → K} (hg : AEStronglyMeasurable g μ_𝓕) - (g_ℒ_infinity : essSup (fun x ↦ ↑‖g x‖₊) μ_𝓕 ≠ ∞) + (g_ℒ_infinity : essSup (fun x ↦ ↑‖g x‖ₑ) μ_𝓕 ≠ ∞) (F_ae_measurable : AEStronglyMeasurable (QuotientGroup.automorphize f) μ_𝓕) : ∫ x : G, g (x : G ⧸ Γ) * (f x) ∂μ = ∫ x : G ⧸ Γ, g x * (QuotientGroup.automorphize f x) ∂μ_𝓕 := by @@ -418,8 +418,7 @@ lemma QuotientGroup.integral_mul_eq_integral_automorphize_mul {K : Type*} [Norme have : AEStronglyMeasurable (fun (x : G) ↦ g (x : (G ⧸ Γ))) μ := (hg.mono_ac h𝓕.absolutelyContinuous_map).comp_measurable meas_π refine Integrable.essSup_smul f_ℒ_1 this ?_ - have hg' : AEStronglyMeasurable (fun x ↦ (‖g x‖₊ : ℝ≥0∞)) μ_𝓕 := - (ENNReal.continuous_coe.comp continuous_nnnorm).comp_aestronglyMeasurable hg + have hg' : AEStronglyMeasurable (‖g ·‖ₑ) μ_𝓕 := continuous_enorm.comp_aestronglyMeasurable hg rw [← essSup_comp_quotientGroup_mk h𝓕 hg'.aemeasurable] exact g_ℒ_infinity have H₂ : AEStronglyMeasurable (QuotientGroup.automorphize ((g ∘ π) * f)) μ_𝓕 := by @@ -447,7 +446,7 @@ local notation "μ_𝓕" => Measure.map (@QuotientAddGroup.mk G' _ Γ') (μ'.res lemma QuotientAddGroup.integral_mul_eq_integral_automorphize_mul {K : Type*} [NormedField K] [NormedSpace ℝ K] [μ'.IsAddRightInvariant] {f : G' → K} (f_ℒ_1 : Integrable f μ') {g : G' ⧸ Γ' → K} (hg : AEStronglyMeasurable g μ_𝓕) - (g_ℒ_infinity : essSup (fun x ↦ (‖g x‖₊ : ℝ≥0∞)) μ_𝓕 ≠ ∞) + (g_ℒ_infinity : essSup (‖g ·‖ₑ) μ_𝓕 ≠ ∞) (F_ae_measurable : AEStronglyMeasurable (QuotientAddGroup.automorphize f) μ_𝓕) (h𝓕 : IsAddFundamentalDomain Γ'.op 𝓕' μ') : ∫ x : G', g (x : G' ⧸ Γ') * (f x) ∂μ' @@ -463,8 +462,7 @@ lemma QuotientAddGroup.integral_mul_eq_integral_automorphize_mul {K : Type*} [No have : AEStronglyMeasurable (fun (x : G') ↦ g (x : (G' ⧸ Γ'))) μ' := (hg.mono_ac h𝓕.absolutelyContinuous_map).comp_measurable meas_π refine Integrable.essSup_smul f_ℒ_1 this ?_ - have hg' : AEStronglyMeasurable (fun x ↦ (‖g x‖₊ : ℝ≥0∞)) μ_𝓕 := - (ENNReal.continuous_coe.comp continuous_nnnorm).comp_aestronglyMeasurable hg + have hg' : AEStronglyMeasurable (‖g ·‖ₑ) μ_𝓕 := continuous_enorm.comp_aestronglyMeasurable hg rw [← essSup_comp_quotientAddGroup_mk h𝓕 hg'.aemeasurable] exact g_ℒ_infinity have H₂ : AEStronglyMeasurable (QuotientAddGroup.automorphize ((g ∘ π) * f)) μ_𝓕 := by diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean index aa7a1f5093442..2027a22e7dfeb 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean @@ -563,7 +563,7 @@ theorem _root_.AlternatingMap.measure_parallelepiped (ω : G [⋀^Fin n]→ₗ[ conv_rhs => rw [ω.eq_smul_basis_det (finBasisOfFinrankEq ℝ G _i.out)] simp only [addHaar_parallelepiped, AlternatingMap.measure, coe_nnreal_smul_apply, AlternatingMap.smul_apply, Algebra.id.smul_eq_mul, abs_mul, ENNReal.ofReal_mul (abs_nonneg _), - Real.ennnorm_eq_ofReal_abs] + ← Real.enorm_eq_ofReal_abs, enorm] instance (ω : G [⋀^Fin n]→ₗ[ℝ] ℝ) : IsAddLeftInvariant ω.measure := by rw [AlternatingMap.measure]; infer_instance diff --git a/Mathlib/NumberTheory/ModularForms/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/QExpansion.lean index 43be8d61e52f2..beb1790478637 100644 --- a/Mathlib/NumberTheory/ModularForms/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/QExpansion.lean @@ -161,8 +161,8 @@ lemma qExpansionFormalMultilinearSeries_radius [NeZero n] [ModularFormClass F Γ lemma hasFPowerSeries_cuspFunction [NeZero n] [ModularFormClass F Γ(n) k] : HasFPowerSeriesOnBall (cuspFunction n f) (qExpansionFormalMultilinearSeries n f) 0 1 := by refine ⟨qExpansionFormalMultilinearSeries_radius n f, zero_lt_one, fun hy ↦ ?_⟩ - rw [EMetric.mem_ball, edist_zero_right, ENNReal.coe_lt_one_iff, ← NNReal.coe_lt_one, - coe_nnnorm, norm_eq_abs] at hy + rw [EMetric.mem_ball, edist_zero_right, enorm_eq_nnnorm, ENNReal.coe_lt_one_iff, + ← NNReal.coe_lt_one, coe_nnnorm, norm_eq_abs] at hy simpa [qExpansionFormalMultilinearSeries] using hasSum_qExpansion_of_abs_lt n f hy end ModularFormClass diff --git a/Mathlib/Probability/Density.lean b/Mathlib/Probability/Density.lean index a89d87c31a792..3a90248fdc473 100644 --- a/Mathlib/Probability/Density.lean +++ b/Mathlib/Probability/Density.lean @@ -289,15 +289,14 @@ theorem integral_mul_eq_integral [HasPDF X ℙ] : ∫ x, x * (pdf X ℙ volume x _ = _ := integral_pdf_smul measurable_id.aestronglyMeasurable theorem hasFiniteIntegral_mul {f : ℝ → ℝ} {g : ℝ → ℝ≥0∞} (hg : pdf X ℙ =ᵐ[volume] g) - (hgi : ∫⁻ x, ‖f x‖₊ * g x ≠ ∞) : + (hgi : ∫⁻ x, ‖f x‖ₑ * g x ≠ ∞) : HasFiniteIntegral fun x => f x * (pdf X ℙ volume x).toReal := by - rw [hasFiniteIntegral_iff_nnnorm] - have : (fun x => ↑‖f x‖₊ * g x) =ᵐ[volume] fun x => ‖f x * (pdf X ℙ volume x).toReal‖₊ := by - refine ae_eq_trans (Filter.EventuallyEq.mul (ae_eq_refl fun x => (‖f x‖₊ : ℝ≥0∞)) - (ae_eq_trans hg.symm ofReal_toReal_ae_eq.symm)) ?_ - simp_rw [← smul_eq_mul, nnnorm_smul, ENNReal.coe_mul, smul_eq_mul] - refine Filter.EventuallyEq.mul (ae_eq_refl _) ?_ - simp only [Real.ennnorm_eq_ofReal ENNReal.toReal_nonneg, ae_eq_refl] + rw [hasFiniteIntegral_iff_enorm] + have : (fun x => ‖f x‖ₑ * g x) =ᵐ[volume] fun x => ‖f x * (pdf X ℙ volume x).toReal‖ₑ := by + refine ae_eq_trans ((ae_eq_refl _).mul (ae_eq_trans hg.symm ofReal_toReal_ae_eq.symm)) ?_ + simp_rw [← smul_eq_mul, enorm_smul, smul_eq_mul] + refine .mul (ae_eq_refl _) ?_ + simp only [Real.enorm_eq_ofReal ENNReal.toReal_nonneg, ae_eq_refl] rwa [lt_top_iff_ne_top, ← lintegral_congr_ae this] end Real diff --git a/Mathlib/Probability/Distributions/Uniform.lean b/Mathlib/Probability/Distributions/Uniform.lean index 3efd4efda464d..2e4daec4ac77e 100644 --- a/Mathlib/Probability/Distributions/Uniform.lean +++ b/Mathlib/Probability/Distributions/Uniform.lean @@ -153,11 +153,11 @@ theorem mul_pdf_integrable (hcs : IsCompact s) (huX : IsUniform X s ℙ) : (measurable_pdf X ℙ).aemeasurable.ennreal_toReal.aestronglyMeasurable refine hasFiniteIntegral_mul (pdf_eq hcs.measurableSet huX) ?_ set ind := (volume s)⁻¹ • (1 : ℝ → ℝ≥0∞) - have : ∀ x, ↑‖x‖₊ * s.indicator ind x = s.indicator (fun x => ‖x‖₊ * ind x) x := fun x => + have : ∀ x, ‖x‖ₑ * s.indicator ind x = s.indicator (fun x => ‖x‖ₑ * ind x) x := fun x => (s.indicator_mul_right (fun x => ↑‖x‖₊) ind).symm simp only [ind, this, lintegral_indicator hcs.measurableSet, mul_one, Algebra.id.smul_eq_mul, Pi.one_apply, Pi.smul_apply] - rw [lintegral_mul_const _ measurable_nnnorm.coe_nnreal_ennreal] + rw [lintegral_mul_const _ measurable_enorm] exact ENNReal.mul_ne_top (setLIntegral_lt_top_of_isCompact hnt.2 hcs continuous_nnnorm).ne (ENNReal.inv_lt_top.2 (pos_iff_ne_zero.mpr hnt.1)).ne diff --git a/Mathlib/Probability/Integration.lean b/Mathlib/Probability/Integration.lean index 77a6aa46b89e1..7d987ea9c0935 100644 --- a/Mathlib/Probability/Integration.lean +++ b/Mathlib/Probability/Integration.lean @@ -153,19 +153,16 @@ theorem lintegral_prod_eq_prod_lintegral_of_indepFun {ι : Type*} [DecidableEq theorem IndepFun.integrable_mul {β : Type*} [MeasurableSpace β] {X Y : Ω → β} [NormedDivisionRing β] [BorelSpace β] (hXY : IndepFun X Y μ) (hX : Integrable X μ) (hY : Integrable Y μ) : Integrable (X * Y) μ := by - let nX : Ω → ENNReal := fun a => ‖X a‖₊ - let nY : Ω → ENNReal := fun a => ‖Y a‖₊ - have hXY' : IndepFun (fun a => ‖X a‖₊) (fun a => ‖Y a‖₊) μ := - hXY.comp measurable_nnnorm measurable_nnnorm - have hXY'' : IndepFun nX nY μ := - hXY'.comp measurable_coe_nnreal_ennreal measurable_coe_nnreal_ennreal - have hnX : AEMeasurable nX μ := hX.1.aemeasurable.nnnorm.coe_nnreal_ennreal - have hnY : AEMeasurable nY μ := hY.1.aemeasurable.nnnorm.coe_nnreal_ennreal + let nX : Ω → ℝ≥0∞ := fun a => ‖X a‖ₑ + let nY : Ω → ℝ≥0∞ := fun a => ‖Y a‖ₑ + have hXY' : IndepFun nX nY μ := hXY.comp measurable_enorm measurable_enorm + have hnX : AEMeasurable nX μ := hX.1.aemeasurable.enorm + have hnY : AEMeasurable nY μ := hY.1.aemeasurable.enorm have hmul : ∫⁻ a, nX a * nY a ∂μ = (∫⁻ a, nX a ∂μ) * ∫⁻ a, nY a ∂μ := - lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun' hnX hnY hXY'' + lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun' hnX hnY hXY' refine ⟨hX.1.mul hY.1, ?_⟩ simp only [nX, nY] at hmul - simp_rw [hasFiniteIntegral_iff_nnnorm, Pi.mul_apply, nnnorm_mul, ENNReal.coe_mul, hmul] + simp_rw [hasFiniteIntegral_iff_enorm, Pi.mul_apply, enorm_mul, hmul] exact ENNReal.mul_lt_top hX.2 hY.2 /-- If the product of two independent real-valued random variables is integrable and @@ -175,18 +172,16 @@ theorem IndepFun.integrable_left_of_integrable_mul {β : Type*} [MeasurableSpace (hX : AEStronglyMeasurable X μ) (hY : AEStronglyMeasurable Y μ) (h'Y : ¬Y =ᵐ[μ] 0) : Integrable X μ := by refine ⟨hX, ?_⟩ - have I : (∫⁻ ω, ‖Y ω‖₊ ∂μ) ≠ 0 := fun H ↦ by - have I : (fun ω => ‖Y ω‖₊ : Ω → ℝ≥0∞) =ᵐ[μ] 0 := (lintegral_eq_zero_iff' hY.ennnorm).1 H + have I : (∫⁻ ω, ‖Y ω‖ₑ ∂μ) ≠ 0 := fun H ↦ by + have I : (fun ω => ‖Y ω‖ₑ : Ω → ℝ≥0∞) =ᵐ[μ] 0 := (lintegral_eq_zero_iff' hY.enorm).1 H apply h'Y filter_upwards [I] with ω hω simpa using hω - refine hasFiniteIntegral_iff_nnnorm.mpr <| lt_top_iff_ne_top.2 fun H => ?_ - have J : IndepFun (fun ω => ‖X ω‖₊ : Ω → ℝ≥0∞) (fun ω => ‖Y ω‖₊ : Ω → ℝ≥0∞) μ := by - have M : Measurable fun x : β => (‖x‖₊ : ℝ≥0∞) := measurable_nnnorm.coe_nnreal_ennreal - apply IndepFun.comp hXY M M - have A : (∫⁻ ω, ‖X ω * Y ω‖₊ ∂μ) < ∞ := h'XY.2 - simp only [nnnorm_mul, ENNReal.coe_mul] at A - rw [lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun'' hX.ennnorm hY.ennnorm J, H] at A + refine hasFiniteIntegral_iff_enorm.mpr <| lt_top_iff_ne_top.2 fun H => ?_ + have J : IndepFun (‖X ·‖ₑ) (‖Y ·‖ₑ) μ := hXY.comp measurable_enorm measurable_enorm + have A : ∫⁻ ω, ‖X ω * Y ω‖ₑ ∂μ < ∞ := h'XY.2 + simp only [enorm_mul, ENNReal.coe_mul] at A + rw [lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun'' hX.enorm hY.enorm J, H] at A simp only [ENNReal.top_mul I, lt_self_iff_false] at A /-- If the product of two independent real-valued random variables is integrable and the @@ -196,19 +191,17 @@ theorem IndepFun.integrable_right_of_integrable_mul {β : Type*} [MeasurableSpac (hX : AEStronglyMeasurable X μ) (hY : AEStronglyMeasurable Y μ) (h'X : ¬X =ᵐ[μ] 0) : Integrable Y μ := by refine ⟨hY, ?_⟩ - have I : (∫⁻ ω, ‖X ω‖₊ ∂μ) ≠ 0 := fun H ↦ by - have I : (fun ω => ‖X ω‖₊ : Ω → ℝ≥0∞) =ᵐ[μ] 0 := (lintegral_eq_zero_iff' hX.ennnorm).1 H + have I : ∫⁻ ω, ‖X ω‖ₑ ∂μ ≠ 0 := fun H ↦ by + have I : ((‖X ·‖ₑ) : Ω → ℝ≥0∞) =ᵐ[μ] 0 := (lintegral_eq_zero_iff' hX.enorm).1 H apply h'X filter_upwards [I] with ω hω simpa using hω refine lt_top_iff_ne_top.2 fun H => ?_ - have J : IndepFun (fun ω => ‖X ω‖₊ : Ω → ℝ≥0∞) (fun ω => ‖Y ω‖₊ : Ω → ℝ≥0∞) μ := by - have M : Measurable fun x : β => (‖x‖₊ : ℝ≥0∞) := measurable_nnnorm.coe_nnreal_ennreal - apply IndepFun.comp hXY M M - have A : (∫⁻ ω, ‖X ω * Y ω‖₊ ∂μ) < ∞ := h'XY.2 - simp only [nnnorm_mul, ENNReal.coe_mul] at A - simp_rw [enorm_eq_nnnorm] at H - rw [lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun'' hX.ennnorm hY.ennnorm J, H] at A + have J : IndepFun (fun ω => ‖X ω‖ₑ : Ω → ℝ≥0∞) (fun ω => ‖Y ω‖ₑ : Ω → ℝ≥0∞) μ := + IndepFun.comp hXY measurable_enorm measurable_enorm + have A : ∫⁻ ω, ‖X ω * Y ω‖ₑ ∂μ < ∞ := h'XY.2 + simp only [enorm_mul, ENNReal.coe_mul] at A + rw [lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun'' hX.enorm hY.enorm J, H] at A simp only [ENNReal.mul_top I, lt_self_iff_false] at A /-- The (Bochner) integral of the product of two independent, nonnegative random diff --git a/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean b/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean index a9ab89e8cf8f4..3b0cddf917b80 100644 --- a/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean +++ b/Mathlib/Probability/Kernel/Composition/IntegralCompProd.lean @@ -45,7 +45,7 @@ namespace ProbabilityTheory theorem hasFiniteIntegral_prod_mk_left (a : α) {s : Set (β × γ)} (h2s : (κ ⊗ₖ η) a s ≠ ∞) : HasFiniteIntegral (fun b => (η (a, b) (Prod.mk b ⁻¹' s)).toReal) (κ a) := by let t := toMeasurable ((κ ⊗ₖ η) a) s - simp_rw [hasFiniteIntegral_iff_nnnorm, ennnorm_eq_ofReal toReal_nonneg] + simp_rw [hasFiniteIntegral_iff_enorm, enorm_eq_ofReal toReal_nonneg] calc ∫⁻ b, ENNReal.ofReal (η (a, b) (Prod.mk b ⁻¹' s)).toReal ∂κ a _ ≤ ∫⁻ b, η (a, b) (Prod.mk b ⁻¹' t) ∂κ a := by @@ -82,19 +82,19 @@ theorem hasFiniteIntegral_compProd_iff ⦃f : β × γ → E⦄ (h1f : StronglyM HasFiniteIntegral f ((κ ⊗ₖ η) a) ↔ (∀ᵐ x ∂κ a, HasFiniteIntegral (fun y => f (x, y)) (η (a, x))) ∧ HasFiniteIntegral (fun x => ∫ y, ‖f (x, y)‖ ∂η (a, x)) (κ a) := by - simp only [hasFiniteIntegral_iff_nnnorm] - rw [Kernel.lintegral_compProd _ _ _ h1f.ennnorm] + simp only [hasFiniteIntegral_iff_enorm] + rw [lintegral_compProd _ _ _ h1f.enorm] have : ∀ x, ∀ᵐ y ∂η (a, x), 0 ≤ ‖f (x, y)‖ := fun x => Eventually.of_forall fun y => norm_nonneg _ simp_rw [integral_eq_lintegral_of_nonneg_ae (this _) (h1f.norm.comp_measurable measurable_prod_mk_left).aestronglyMeasurable, - ennnorm_eq_ofReal toReal_nonneg, ofReal_norm_eq_coe_nnnorm] + enorm_eq_ofReal toReal_nonneg, ofReal_norm_eq_enorm] have : ∀ {p q r : Prop} (_ : r → p), (r ↔ p ∧ q) ↔ p → (r ↔ q) := fun {p q r} h1 => by rw [← and_congr_right_iff, and_iff_right_of_imp h1] rw [this] · intro h2f; rw [lintegral_congr_ae] filter_upwards [h2f] with x hx rw [ofReal_toReal]; rw [← lt_top_iff_ne_top]; exact hx - · intro h2f; refine ae_lt_top ?_ h2f.ne; exact h1f.ennnorm.lintegral_kernel_prod_right'' + · intro h2f; refine ae_lt_top ?_ h2f.ne; exact h1f.enorm.lintegral_kernel_prod_right'' theorem hasFiniteIntegral_compProd_iff' ⦃f : β × γ → E⦄ (h1f : AEStronglyMeasurable f ((κ ⊗ₖ η) a)) : @@ -200,21 +200,18 @@ theorem Kernel.continuous_integral_integral : refine tendsto_integral_of_L1 _ (L1.integrable_coeFn g).integral_compProd (Eventually.of_forall fun h => (L1.integrable_coeFn h).integral_compProd) ?_ - simp_rw [← - Kernel.lintegral_fn_integral_sub (fun x => (‖x‖₊ : ℝ≥0∞)) (L1.integrable_coeFn _) - (L1.integrable_coeFn g)] + simp_rw [← lintegral_fn_integral_sub (‖·‖ₑ) (L1.integrable_coeFn _) (L1.integrable_coeFn g)] apply tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds _ (fun i => zero_le _) _ - · exact fun i => ∫⁻ x, ∫⁻ y, ‖i (x, y) - g (x, y)‖₊ ∂η (a, x) ∂κ a - swap; · exact fun i => lintegral_mono fun x => ennnorm_integral_le_lintegral_ennnorm _ + · exact fun i => ∫⁻ x, ∫⁻ y, ‖i (x, y) - g (x, y)‖ₑ ∂η (a, x) ∂κ a + swap; · exact fun i => lintegral_mono fun x => enorm_integral_le_lintegral_enorm _ show Tendsto - (fun i : β × γ →₁[(κ ⊗ₖ η) a] E => ∫⁻ x, ∫⁻ y : γ, ‖i (x, y) - g (x, y)‖₊ ∂η (a, x) ∂κ a) + (fun i : β × γ →₁[(κ ⊗ₖ η) a] E => ∫⁻ x, ∫⁻ y : γ, ‖i (x, y) - g (x, y)‖ₑ ∂η (a, x) ∂κ a) (𝓝 g) (𝓝 0) - have : ∀ i : (MeasureTheory.Lp (α := β × γ) E 1 (((κ ⊗ₖ η) a) : Measure (β × γ))), - Measurable fun z => (‖i z - g z‖₊ : ℝ≥0∞) := fun i => - ((Lp.stronglyMeasurable i).sub (Lp.stronglyMeasurable g)).ennnorm - simp_rw [← Kernel.lintegral_compProd _ _ _ (this _), ← L1.ofReal_norm_sub_eq_lintegral, ← - ofReal_zero] + have this (i : Lp (α := β × γ) E 1 (((κ ⊗ₖ η) a) : Measure (β × γ))) : + Measurable fun z => ‖i z - g z‖ₑ := + ((Lp.stronglyMeasurable i).sub (Lp.stronglyMeasurable g)).enorm + simp_rw [← lintegral_compProd _ _ _ (this _), ← L1.ofReal_norm_sub_eq_lintegral, ← ofReal_zero] refine (continuous_ofReal.tendsto 0).comp ?_ rw [← tendsto_iff_norm_sub_tendsto_zero] exact tendsto_id diff --git a/Mathlib/Probability/Kernel/CondDistrib.lean b/Mathlib/Probability/Kernel/CondDistrib.lean index 8868754b1be92..a0933088f0f3d 100644 --- a/Mathlib/Probability/Kernel/CondDistrib.lean +++ b/Mathlib/Probability/Kernel/CondDistrib.lean @@ -321,7 +321,7 @@ theorem _root_.MeasureTheory.Integrable.comp_snd_map_prod_mk by_cases hX : AEMeasurable X μ · have hf := hf_int.1.comp_snd_map_prod_mk X (mΩ := mΩ) (mβ := mβ) refine ⟨hf, ?_⟩ - rw [hasFiniteIntegral_iff_nnnorm, lintegral_map' hf.ennnorm (hX.prod_mk aemeasurable_id)] + rw [hasFiniteIntegral_iff_enorm, lintegral_map' hf.enorm (hX.prod_mk aemeasurable_id)] exact hf_int.2 · rw [Measure.map_of_not_aemeasurable] · simp diff --git a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean index 7a63f0c847a34..25bf36467a984 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean @@ -198,7 +198,7 @@ lemma integrable_preCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℚ Integrable (fun a ↦ (preCDF ρ x a).toReal) ρ.fst := by refine integrable_of_forall_fin_meas_le _ (measure_lt_top ρ.fst univ) ?_ fun t _ _ ↦ ?_ · exact measurable_preCDF.ennreal_toReal.aestronglyMeasurable - · simp_rw [← ofReal_norm_eq_coe_nnnorm, Real.norm_of_nonneg ENNReal.toReal_nonneg] + · simp_rw [← ofReal_norm_eq_enorm, Real.norm_of_nonneg ENNReal.toReal_nonneg] rw [← lintegral_one] refine (setLIntegral_le_lintegral _ _).trans (lintegral_mono_ae ?_) filter_upwards [preCDF_le_one ρ] with a ha using ENNReal.ofReal_toReal_le.trans (ha _) diff --git a/Mathlib/Probability/Kernel/MeasurableIntegral.lean b/Mathlib/Probability/Kernel/MeasurableIntegral.lean index d3eb71066d3ed..f226af6adbb25 100644 --- a/Mathlib/Probability/Kernel/MeasurableIntegral.lean +++ b/Mathlib/Probability/Kernel/MeasurableIntegral.lean @@ -32,7 +32,7 @@ theorem ProbabilityTheory.measurableSet_kernel_integrable ⦃f : α → β → E (hf : StronglyMeasurable (uncurry f)) : MeasurableSet {x | Integrable (f x) (κ x)} := by simp_rw [Integrable, hf.of_uncurry_left.aestronglyMeasurable, true_and] - exact measurableSet_lt (Measurable.lintegral_kernel_prod_right hf.ennnorm) measurable_const + exact measurableSet_lt (Measurable.lintegral_kernel_prod_right hf.enorm) measurable_const open ProbabilityTheory.Kernel diff --git a/Mathlib/Probability/Martingale/Convergence.lean b/Mathlib/Probability/Martingale/Convergence.lean index 78e152f66e770..00ffa32b2454b 100644 --- a/Mathlib/Probability/Martingale/Convergence.lean +++ b/Mathlib/Probability/Martingale/Convergence.lean @@ -154,7 +154,7 @@ theorem Submartingale.upcrossings_ae_lt_top' [IsFiniteMeasure μ] (hf : Submarti rw [mul_comm, ← ENNReal.le_div_iff_mul_le] at this · refine (lt_of_le_of_lt this (ENNReal.div_lt_top ?_ ?_)).ne · have hR' : ∀ n, ∫⁻ ω, ‖f n ω - a‖₊ ∂μ ≤ R + ‖a‖₊ * μ Set.univ := by - simp_rw [eLpNorm_one_eq_lintegral_nnnorm] at hbdd + simp_rw [eLpNorm_one_eq_lintegral_enorm] at hbdd intro n refine (lintegral_mono ?_ : ∫⁻ ω, ‖f n ω - a‖₊ ∂μ ≤ ∫⁻ ω, ‖f n ω‖₊ + ‖a‖₊ ∂μ).trans ?_ · intro ω diff --git a/Mathlib/Probability/Variance.lean b/Mathlib/Probability/Variance.lean index 5c3c9f6c42be4..886ceef0e7ebe 100644 --- a/Mathlib/Probability/Variance.lean +++ b/Mathlib/Probability/Variance.lean @@ -49,7 +49,7 @@ namespace ProbabilityTheory /-- The `ℝ≥0∞`-valued variance of a real-valued random variable defined as the Lebesgue integral of `(X - 𝔼[X])^2`. -/ def evariance {Ω : Type*} {_ : MeasurableSpace Ω} (X : Ω → ℝ) (μ : Measure Ω) : ℝ≥0∞ := - ∫⁻ ω, (‖X ω - μ[X]‖₊ : ℝ≥0∞) ^ 2 ∂μ + ∫⁻ ω, ‖X ω - μ[X]‖ₑ ^ 2 ∂μ /-- The `ℝ`-valued variance of a real-valued random variable defined by applying `ENNReal.toReal` to `evariance`. -/ @@ -82,7 +82,7 @@ variable {Ω : Type*} {m : MeasurableSpace Ω} {X : Ω → ℝ} {μ : Measure Ω theorem _root_.MeasureTheory.Memℒp.evariance_lt_top [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : evariance X μ < ∞ := by have := ENNReal.pow_lt_top (hX.sub <| memℒp_const <| μ[X]).2 2 - rw [eLpNorm_eq_lintegral_rpow_nnnorm two_ne_zero ENNReal.two_ne_top, ← ENNReal.rpow_two] at this + rw [eLpNorm_eq_lintegral_rpow_enorm two_ne_zero ENNReal.two_ne_top, ← ENNReal.rpow_two] at this simp only [ENNReal.toReal_ofNat, Pi.sub_apply, ENNReal.one_toReal, one_div] at this rw [← ENNReal.rpow_mul, inv_mul_cancel₀ (two_ne_zero : (2 : ℝ) ≠ 0), ENNReal.rpow_one] at this simp_rw [ENNReal.rpow_two] at this @@ -94,7 +94,7 @@ theorem evariance_eq_top [IsFiniteMeasure μ] (hXm : AEStronglyMeasurable X μ) rw [← Ne, ← lt_top_iff_ne_top] at h have : Memℒp (fun ω => X ω - μ[X]) 2 μ := by refine ⟨hXm.sub aestronglyMeasurable_const, ?_⟩ - rw [eLpNorm_eq_lintegral_rpow_nnnorm two_ne_zero ENNReal.two_ne_top] + rw [eLpNorm_eq_lintegral_rpow_enorm two_ne_zero ENNReal.two_ne_top] simp only [ENNReal.toReal_ofNat, ENNReal.one_toReal, ENNReal.rpow_two, Ne] exact ENNReal.rpow_lt_top_of_nonneg (by linarith) h.ne refine hX ?_ @@ -117,11 +117,8 @@ theorem _root_.MeasureTheory.Memℒp.ofReal_variance_eq [IsFiniteMeasure μ] (hX theorem evariance_eq_lintegral_ofReal (X : Ω → ℝ) (μ : Measure Ω) : evariance X μ = ∫⁻ ω, ENNReal.ofReal ((X ω - μ[X]) ^ 2) ∂μ := by rw [evariance] - congr - ext1 ω - rw [pow_two, ← ENNReal.coe_mul, ← nnnorm_mul, ← pow_two] - congr - exact (Real.toNNReal_eq_nnnorm_of_nonneg <| sq_nonneg _).symm + congr with ω + rw [pow_two, ← enorm_mul, ← pow_two, Real.enorm_of_nonneg (sq_nonneg _)] theorem _root_.MeasureTheory.Memℒp.variance_eq_of_integral_eq_zero (hX : Memℒp X 2 μ) (hXint : μ[X] = 0) : variance X μ = μ[X ^ (2 : Nat)] := by @@ -152,25 +149,16 @@ theorem evariance_eq_zero_iff (hX : AEMeasurable X μ) : evariance X μ = 0 ↔ X =ᵐ[μ] fun _ => μ[X] := by rw [evariance, lintegral_eq_zero_iff'] constructor <;> intro hX <;> filter_upwards [hX] with ω hω - · simpa only [Pi.zero_apply, sq_eq_zero_iff, ENNReal.coe_eq_zero, nnnorm_eq_zero, sub_eq_zero] - using hω - · rw [hω] - simp - · exact (hX.sub_const _).ennnorm.pow_const _ -- TODO `measurability` and `fun_prop` fail + · simpa [sub_eq_zero] using hω + · simp [hω] + · exact (hX.sub_const _).enorm.pow_const _ -- TODO `measurability` and `fun_prop` fail theorem evariance_mul (c : ℝ) (X : Ω → ℝ) (μ : Measure Ω) : evariance (fun ω => c * X ω) μ = ENNReal.ofReal (c ^ 2) * evariance X μ := by rw [evariance, evariance, ← lintegral_const_mul' _ _ ENNReal.ofReal_lt_top.ne] - congr - ext1 ω - rw [ENNReal.ofReal, ← ENNReal.coe_pow, ← ENNReal.coe_pow, ← ENNReal.coe_mul] - congr - rw [← sq_abs, ← Real.rpow_two, Real.toNNReal_rpow_of_nonneg (abs_nonneg _), NNReal.rpow_two, - ← mul_pow, Real.toNNReal_mul_nnnorm _ (abs_nonneg _)] - conv_rhs => rw [← nnnorm_norm, norm_mul, norm_abs_eq_norm, ← norm_mul, nnnorm_norm, mul_sub] - congr - rw [mul_comm] - simp_rw [← smul_eq_mul, ← integral_smul_const, smul_eq_mul, mul_comm] + congr with ω + rw [integral_mul_left, ← mul_sub, enorm_mul, mul_pow, ← enorm_pow, + Real.enorm_of_nonneg (sq_nonneg _)] @[simp] theorem variance_zero (μ : Measure Ω) : variance 0 μ = 0 := by @@ -228,20 +216,20 @@ theorem variance_le_expectation_sq [IsProbabilityMeasure μ] {X : Ω → ℝ} · exact (AEMeasurable.pow_const (hm.aemeasurable.sub_const _) _).aestronglyMeasurable theorem evariance_def' [IsProbabilityMeasure μ] {X : Ω → ℝ} (hX : AEStronglyMeasurable X μ) : - evariance X μ = (∫⁻ ω, (‖X ω‖₊ ^ 2 :) ∂μ) - ENNReal.ofReal (μ[X] ^ 2) := by + evariance X μ = (∫⁻ ω, ‖X ω‖ₑ ^ 2 ∂μ) - ENNReal.ofReal (μ[X] ^ 2) := by by_cases hℒ : Memℒp X 2 μ · rw [← hℒ.ofReal_variance_eq, variance_def' hℒ, ENNReal.ofReal_sub _ (sq_nonneg _)] congr + simp_rw [← enorm_pow, enorm] rw [lintegral_coe_eq_integral] - · congr 2 with ω - simp only [Pi.pow_apply, NNReal.coe_pow, coe_nnnorm, Real.norm_eq_abs, Even.pow_abs even_two] - · exact hℒ.abs.integrable_sq + · simp + · simpa using hℒ.abs.integrable_sq · symm rw [evariance_eq_top hX hℒ, ENNReal.sub_eq_top_iff] refine ⟨?_, ENNReal.ofReal_ne_top⟩ rw [Memℒp, not_and] at hℒ specialize hℒ hX - simp only [eLpNorm_eq_lintegral_rpow_nnnorm two_ne_zero ENNReal.two_ne_top, not_lt, top_le_iff, + simp only [eLpNorm_eq_lintegral_rpow_enorm two_ne_zero ENNReal.two_ne_top, not_lt, top_le_iff, ENNReal.toReal_ofNat, one_div, ENNReal.rpow_eq_top_iff, inv_lt_zero, inv_pos, and_true, or_iff_not_imp_left, not_and_or, zero_lt_two] at hℒ exact mod_cast hℒ fun _ => zero_le_two @@ -255,7 +243,7 @@ theorem meas_ge_le_evariance_div_sq {X : Ω → ℝ} (hX : AEStronglyMeasurable · congr simp only [Pi.sub_apply, ENNReal.coe_le_coe, ← Real.norm_eq_abs, ← coe_nnnorm, NNReal.coe_le_coe, ENNReal.ofReal_coe_nnreal] - · rw [eLpNorm_eq_lintegral_rpow_nnnorm two_ne_zero ENNReal.two_ne_top] + · rw [eLpNorm_eq_lintegral_rpow_enorm two_ne_zero ENNReal.two_ne_top] simp only [show ENNReal.ofNNReal (c ^ 2) = (ENNReal.ofNNReal c) ^ 2 by norm_cast, ENNReal.toReal_ofNat, one_div, Pi.sub_apply] rw [div_eq_mul_inv, ENNReal.inv_pow, mul_comm, ENNReal.rpow_two] @@ -263,6 +251,7 @@ theorem meas_ge_le_evariance_div_sq {X : Ω → ℝ} (hX : AEStronglyMeasurable simp_rw [← ENNReal.rpow_mul, inv_mul_cancel₀ (two_ne_zero : (2 : ℝ) ≠ 0), ENNReal.rpow_two, ENNReal.rpow_one, evariance] + /-- **Chebyshev's inequality**: one can control the deviation probability of a real random variable from its expectation in terms of the variance. -/ theorem meas_ge_le_variance_div_sq [IsFiniteMeasure μ] {X : Ω → ℝ} (hX : Memℒp X 2 μ) {c : ℝ} diff --git a/scripts/nolints_prime_decls.txt b/scripts/nolints_prime_decls.txt index be856e67cdf24..fd259826572ac 100644 --- a/scripts/nolints_prime_decls.txt +++ b/scripts/nolints_prime_decls.txt @@ -1117,7 +1117,7 @@ DoubleCentralizer.nnnorm_def' DoubleCentralizer.norm_def' dvd_antisymm' dvd_geom_sum₂_iff_of_dvd_sub' -edist_eq_coe_nnnorm' +edist_zero_eq_enorm' EllipticCurve.coe_inv_map_Δ' EllipticCurve.coe_inv_variableChange_Δ' EllipticCurve.coe_map_Δ' @@ -2823,7 +2823,7 @@ 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_rpow_enorm_eq_rpow_eLpNorm' MeasureTheory.lintegral_singleton' MeasureTheory.lintegral_sub' MeasureTheory.lintegral_sub_le' @@ -3494,7 +3494,7 @@ Num.of_to_nat' Num.succ_ofInt' odd_add_one_self' odd_add_self_one' -ofReal_norm_eq_coe_nnnorm' +ofReal_norm_eq_enorm' OmegaCompletePartialOrder.const_continuous' OmegaCompletePartialOrder.ContinuousHom.bind_continuous' OmegaCompletePartialOrder.ContinuousHom.forall_forall_merge' From b26f2742893c49e7bc59ab508bb5694f149d65bc Mon Sep 17 00:00:00 2001 From: damiano Date: Tue, 28 Jan 2025 10:57:16 +0000 Subject: [PATCH 597/681] doc: punctuation typos (#21161) --- Mathlib/RingTheory/Nakayama.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/RingTheory/Nakayama.lean b/Mathlib/RingTheory/Nakayama.lean index ad4d01141b8f1..55c8610c70b93 100644 --- a/Mathlib/RingTheory/Nakayama.lean +++ b/Mathlib/RingTheory/Nakayama.lean @@ -16,13 +16,13 @@ This file contains some alternative statements of Nakayama's Lemma as found in ## Main statements * `Submodule.eq_smul_of_le_smul_of_le_jacobson` - A version of (2) in - [Stacks: Nakayama's Lemma](https://stacks.math.columbia.edu/tag/00DV)., + [Stacks: Nakayama's Lemma](https://stacks.math.columbia.edu/tag/00DV), generalising to the Jacobson of any ideal. * `Submodule.eq_bot_of_le_smul_of_le_jacobson_bot` - Statement (2) in [Stacks: Nakayama's Lemma](https://stacks.math.columbia.edu/tag/00DV). * `Submodule.sup_smul_eq_sup_smul_of_le_smul_of_le_jacobson` - A version of (4) in - [Stacks: Nakayama's Lemma](https://stacks.math.columbia.edu/tag/00DV)., + [Stacks: Nakayama's Lemma](https://stacks.math.columbia.edu/tag/00DV), generalising to the Jacobson of any ideal. * `Submodule.smul_le_of_le_smul_of_le_jacobson_bot` - Statement (4) in [Stacks: Nakayama's Lemma](https://stacks.math.columbia.edu/tag/00DV). From f7efa03639af91b7116b20b011f32abf6b4fabaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= Date: Tue, 28 Jan 2025 11:07:41 +0000 Subject: [PATCH 598/681] =?UTF-8?q?perf:=20improve=20the=20performance=20o?= =?UTF-8?q?f=20the=20`Repr=20(Equiv.Perm=20=CE=B1)`=20instance=20(4/4)=20(?= =?UTF-8?q?#12611)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, `#eval` for `Equiv.Perm α` outputs their disjoint cycles in the format of `Multiset` like: ```lean #eval (1 : Perm (Fin 4)) -- 0 #eval (c[0, 1] : Perm (Fin 4)) -- {c[0, 1]} #eval (c[0, 1] * c[2, 3] : Perm (Fin 4)) -- {c[0, 1], c[2, 3]} ``` However, outputting the original format is preferred: ```lean #eval (1 : Perm (Fin 4)) -- 1 #eval (c[0, 1] : Perm (Fin 4)) -- c[0, 1] #eval (c[0, 1] * c[2, 3] : Perm (Fin 4)) -- c[0, 1] * c[2, 3] ``` This PR change the format and add tests for this. Co-authored-by: Miyahara Kō <52843868+Komyyy@users.noreply.github.com> Co-authored-by: Pol'tta / Miyahara Kō <52843868+Komyyy@users.noreply.github.com> --- Mathlib/GroupTheory/Perm/Cycle/Concrete.lean | 36 ++++++++++++++++---- MathlibTest/Perm.lean | 14 ++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 MathlibTest/Perm.lean diff --git a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean index 4f238742343a8..233d79ecb80e8 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean @@ -39,8 +39,6 @@ The forward direction of `Equiv.Perm.isoCycle'` uses `Fintype.choose` of the uni result, relying on the `Fintype` instance of a `Cycle.nodup` subtype. It is unclear if this works faster than the `Equiv.Perm.toCycle`, which relies on recursion over `Finset.univ`. -Running `#eval` on even a simple noncyclic permutation `c[(1 : Fin 7), 2, 3] * c[0, 5]` -to show it takes a long time. TODO: is this because computing the cycle factors is slow? -/ @@ -469,9 +467,35 @@ set_option linter.unusedTactic false in notation3 (prettyPrint := false) "c["(l", "* => foldr (h t => List.cons h t) List.nil)"]" => Cycle.formPerm (Cycle.ofList l) (Iff.mpr Cycle.nodup_coe_iff (by decide)) -unsafe instance repr_perm [Repr α] : Repr (Perm α) := - ⟨fun f _ => repr (Multiset.pmap (fun (g : Perm α) (hg : g.IsCycle) => isoCycle ⟨g, hg⟩) - (Perm.cycleFactorsFinset f).val -- toCycle is faster? - fun _ hg => (mem_cycleFactorsFinset_iff.mp (Finset.mem_def.mpr hg)).left)⟩ +/-- Represents a permutation as product of disjoint cycles: +``` +#eval (c[0, 1, 2, 3] : Perm (Fin 4)) +-- c[0, 1, 2, 3] + +#eval (c[3, 1] * c[0, 2] : Perm (Fin 4)) +-- c[0, 2] * c[1, 3] + +#eval (c[1, 2, 3] * c[0, 1, 2] : Perm (Fin 4)) +-- c[0, 2] * c[1, 3] + +#eval (c[1, 2, 3] * c[0, 1, 2] * c[3, 1] * c[0, 2] : Perm (Fin 4)) +-- 1 +``` +-/ +unsafe instance instRepr [Repr α] : Repr (Perm α) where + reprPrec f prec := + -- Obtain a list of formats which represents disjoint cycles. + letI l := Quot.unquot <| Multiset.map repr <| Multiset.pmap toCycle + (Perm.cycleFactorsFinset f).val + fun _ hg => (mem_cycleFactorsFinset_iff.mp (Finset.mem_def.mpr hg)).left + -- And intercalate `*`s. + match l with + | [] => "1" + | [f] => f + | l => + -- multiple terms, use `*` precedence + (if prec ≥ 70 then Lean.Format.paren else id) + (Lean.Format.fill + (Lean.Format.joinSep l (" *" ++ Lean.Format.line))) end Equiv.Perm diff --git a/MathlibTest/Perm.lean b/MathlibTest/Perm.lean new file mode 100644 index 0000000000000..72aaf2dee0de9 --- /dev/null +++ b/MathlibTest/Perm.lean @@ -0,0 +1,14 @@ + +import Mathlib.GroupTheory.Perm.Cycle.Concrete +import Mathlib.Tactic.DeriveFintype + +open Equiv + +#guard with_decl_name% ex₁ unsafe (reprStr (1 : Perm (Fin 4))) == "1" +#guard with_decl_name% ex₂ unsafe (reprStr (c[0, 1] : Perm (Fin 4))) == "c[0, 1]" +#guard with_decl_name% ex₃ + unsafe (reprStr (c[0, 1] * c[2, 3] : Perm (Fin 4))) == "c[0, 1] * c[2, 3]" +#guard with_decl_name% ex₄ + unsafe (reprPrec (c[0, 1] * c[2, 3] : Perm (Fin 4)) 70).pretty == "(c[0, 1] * c[2, 3])" +#guard with_decl_name% ex₅ + unsafe (reprPrec (c[0, 1] * c[1, 2] : Perm (Fin 4)) 70).pretty == "c[0, 1, 2]" From fb4aed528fc5708338cebe3653408d86a21684cd Mon Sep 17 00:00:00 2001 From: Jeremy Tan Jie Rui Date: Tue, 28 Jan 2025 11:07:42 +0000 Subject: [PATCH 599/681] chore: delete deprecated algebraic structure files (#16836) Based on a comparison with 32de3f675e28bc8b32de22cba2660940d0a5fc10 these six files have not been substantially changed for over a year. Co-authored-by: Kim Morrison --- Mathlib.lean | 6 - Mathlib/Deprecated/Group.lean | 391 ------------------- Mathlib/Deprecated/Ring.lean | 150 ------- Mathlib/Deprecated/Subfield.lean | 150 ------- Mathlib/Deprecated/Subgroup.lean | 627 ------------------------------ Mathlib/Deprecated/Submonoid.lean | 363 ----------------- Mathlib/Deprecated/Subring.lean | 205 ---------- MathlibTest/Header.lean | 2 +- 8 files changed, 1 insertion(+), 1893 deletions(-) delete mode 100644 Mathlib/Deprecated/Group.lean delete mode 100644 Mathlib/Deprecated/Ring.lean delete mode 100644 Mathlib/Deprecated/Subfield.lean delete mode 100644 Mathlib/Deprecated/Subgroup.lean delete mode 100644 Mathlib/Deprecated/Submonoid.lean delete mode 100644 Mathlib/Deprecated/Subring.lean diff --git a/Mathlib.lean b/Mathlib.lean index e36e8aed8c257..6a48a4ad40e51 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3086,7 +3086,6 @@ import Mathlib.Deprecated.Cardinal.Finite import Mathlib.Deprecated.Cardinal.PartENat import Mathlib.Deprecated.Combinator import Mathlib.Deprecated.Equiv -import Mathlib.Deprecated.Group import Mathlib.Deprecated.HashMap import Mathlib.Deprecated.LazyList import Mathlib.Deprecated.Logic @@ -3094,11 +3093,6 @@ import Mathlib.Deprecated.MinMax import Mathlib.Deprecated.NatLemmas import Mathlib.Deprecated.Order import Mathlib.Deprecated.RelClasses -import Mathlib.Deprecated.Ring -import Mathlib.Deprecated.Subfield -import Mathlib.Deprecated.Subgroup -import Mathlib.Deprecated.Submonoid -import Mathlib.Deprecated.Subring import Mathlib.Dynamics.BirkhoffSum.Average import Mathlib.Dynamics.BirkhoffSum.Basic import Mathlib.Dynamics.BirkhoffSum.NormedSpace diff --git a/Mathlib/Deprecated/Group.lean b/Mathlib/Deprecated/Group.lean deleted file mode 100644 index dd913b42c9bec..0000000000000 --- a/Mathlib/Deprecated/Group.lean +++ /dev/null @@ -1,391 +0,0 @@ -/- -Copyright (c) 2019 Yury Kudryashov. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Yury Kudryashov --/ -import Mathlib.Algebra.Group.Units.Hom -import Mathlib.Algebra.Ring.Hom.Defs -import Mathlib.Algebra.Group.TypeTags.Basic - -/-! -# Unbundled monoid and group homomorphisms - -This file is deprecated, and is no longer imported by anything in mathlib other than other -deprecated files, and test files. You should not need to import it. - -This file defines predicates for unbundled monoid and group homomorphisms. Instead of using -this file, please use `MonoidHom`, defined in `Algebra.Hom.Group`, with notation `→*`, for -morphisms between monoids or groups. For example use `φ : G →* H` to represent a group -homomorphism between multiplicative groups, and `ψ : A →+ B` to represent a group homomorphism -between additive groups. - -## Main Definitions - -`IsMonoidHom` (deprecated), `IsGroupHom` (deprecated) - -## Tags - -IsGroupHom, IsMonoidHom - --/ - - -universe u v - -variable {α : Type u} {β : Type v} - -/-- Predicate for maps which preserve an addition. -/ -structure IsAddHom {α β : Type*} [Add α] [Add β] (f : α → β) : Prop where - /-- The proposition that `f` preserves addition. -/ - map_add : ∀ x y, f (x + y) = f x + f y - -/-- Predicate for maps which preserve a multiplication. -/ -@[to_additive] -structure IsMulHom {α β : Type*} [Mul α] [Mul β] (f : α → β) : Prop where - /-- The proposition that `f` preserves multiplication. -/ - map_mul : ∀ x y, f (x * y) = f x * f y - -namespace IsMulHom - -variable [Mul α] [Mul β] {γ : Type*} [Mul γ] - -/-- The identity map preserves multiplication. -/ -@[to_additive "The identity map preserves addition"] -theorem id : IsMulHom (id : α → α) := - { map_mul := fun _ _ => rfl } - -/-- The composition of maps which preserve multiplication, also preserves multiplication. -/ -@[to_additive "The composition of addition preserving maps also preserves addition"] -theorem comp {f : α → β} {g : β → γ} (hf : IsMulHom f) (hg : IsMulHom g) : IsMulHom (g ∘ f) := - { map_mul := fun x y => by simp only [Function.comp, hf.map_mul, hg.map_mul] } - -/-- A product of maps which preserve multiplication, -preserves multiplication when the target is commutative. -/ -@[to_additive - "A sum of maps which preserves addition, preserves addition when the target - is commutative."] -theorem mul {α β} [Semigroup α] [CommSemigroup β] {f g : α → β} (hf : IsMulHom f) - (hg : IsMulHom g) : IsMulHom fun a => f a * g a := - { map_mul := fun a b => by - simp only [hf.map_mul, hg.map_mul, mul_comm, mul_assoc, mul_left_comm] } - -/-- The inverse of a map which preserves multiplication, -preserves multiplication when the target is commutative. -/ -@[to_additive - "The negation of a map which preserves addition, preserves addition when - the target is commutative."] -theorem inv {α β} [Mul α] [CommGroup β] {f : α → β} (hf : IsMulHom f) : IsMulHom fun a => (f a)⁻¹ := - { map_mul := fun a b => (hf.map_mul a b).symm ▸ mul_inv _ _ } - -end IsMulHom - -/-- Predicate for additive monoid homomorphisms -(deprecated -- use the bundled `MonoidHom` version). -/ -structure IsAddMonoidHom [AddZeroClass α] [AddZeroClass β] (f : α → β) extends IsAddHom f : - Prop where - /-- The proposition that `f` preserves the additive identity. -/ - map_zero : f 0 = 0 - -/-- Predicate for monoid homomorphisms (deprecated -- use the bundled `MonoidHom` version). -/ -@[to_additive] -structure IsMonoidHom [MulOneClass α] [MulOneClass β] (f : α → β) extends IsMulHom f : Prop where - /-- The proposition that `f` preserves the multiplicative identity. -/ - map_one : f 1 = 1 - -namespace MonoidHom - -variable {M : Type*} {N : Type*} {mM : MulOneClass M} {mN : MulOneClass N} - -/-- Interpret a map `f : M → N` as a homomorphism `M →* N`. -/ -@[to_additive "Interpret a map `f : M → N` as a homomorphism `M →+ N`."] -def of {f : M → N} (h : IsMonoidHom f) : M →* N where - toFun := f - map_one' := h.2 - map_mul' := h.1.1 - -@[to_additive (attr := simp)] -theorem coe_of {f : M → N} (hf : IsMonoidHom f) : ⇑(MonoidHom.of hf) = f := - rfl - -@[to_additive] -theorem isMonoidHom_coe (f : M →* N) : IsMonoidHom (f : M → N) := - { map_mul := f.map_mul - map_one := f.map_one } - -end MonoidHom - -namespace MulEquiv - -variable {M : Type*} {N : Type*} [MulOneClass M] [MulOneClass N] - -/-- A multiplicative isomorphism preserves multiplication (deprecated). -/ -@[to_additive "An additive isomorphism preserves addition (deprecated)."] -theorem isMulHom (h : M ≃* N) : IsMulHom h := - ⟨map_mul h⟩ - -/-- A multiplicative bijection between two monoids is a monoid hom - (deprecated -- use `MulEquiv.toMonoidHom`). -/ -@[to_additive - "An additive bijection between two additive monoids is an additive - monoid hom (deprecated). "] -theorem isMonoidHom (h : M ≃* N) : IsMonoidHom h := - { map_mul := map_mul h - map_one := h.map_one } - -end MulEquiv - -namespace IsMonoidHom - -/-- A monoid homomorphism preserves multiplication. -/ -@[to_additive "An additive monoid homomorphism preserves addition."] -theorem map_mul' [MulOneClass α] [MulOneClass β] {f : α → β} (hf : IsMonoidHom f) (x y) : - f (x * y) = f x * f y := - hf.map_mul x y - -/-- The inverse of a map which preserves multiplication, -preserves multiplication when the target is commutative. -/ -@[to_additive - "The negation of a map which preserves addition, preserves addition - when the target is commutative."] -theorem inv {α β} [MulOneClass α] [CommGroup β] {f : α → β} (hf : IsMonoidHom f) : - IsMonoidHom fun a => (f a)⁻¹ := - { map_one := hf.map_one.symm ▸ inv_one - map_mul := fun a b => (hf.map_mul a b).symm ▸ mul_inv _ _ } - -end IsMonoidHom - -/-- A map to a group preserving multiplication is a monoid homomorphism. -/ -@[to_additive "A map to an additive group preserving addition is an additive monoid -homomorphism."] -theorem IsMulHom.to_isMonoidHom [MulOneClass α] [Group β] {f : α → β} (hf : IsMulHom f) : - IsMonoidHom f := - { map_one := (mul_right_eq_self (a := f 1)).1 <| by rw [← hf.map_mul, one_mul] - map_mul := hf.map_mul } - -namespace IsMonoidHom - -variable [MulOneClass α] [MulOneClass β] {f : α → β} - -/-- The identity map is a monoid homomorphism. -/ -@[to_additive "The identity map is an additive monoid homomorphism."] -theorem id : IsMonoidHom (@id α) := - { map_one := rfl - map_mul := fun _ _ => rfl } - -/-- The composite of two monoid homomorphisms is a monoid homomorphism. -/ -@[to_additive - "The composite of two additive monoid homomorphisms is an additive monoid - homomorphism."] -theorem comp (hf : IsMonoidHom f) {γ} [MulOneClass γ] {g : β → γ} (hg : IsMonoidHom g) : - IsMonoidHom (g ∘ f) := - { IsMulHom.comp hf.toIsMulHom hg.toIsMulHom with - map_one := show g _ = 1 by rw [hf.map_one, hg.map_one] } - -end IsMonoidHom - -namespace IsAddMonoidHom - -/-- Left multiplication in a ring is an additive monoid morphism. -/ -theorem isAddMonoidHom_mul_left {γ : Type*} [NonUnitalNonAssocSemiring γ] (x : γ) : - IsAddMonoidHom fun y : γ => x * y := - { map_zero := mul_zero x - map_add := fun y z => mul_add x y z } - -/-- Right multiplication in a ring is an additive monoid morphism. -/ -theorem isAddMonoidHom_mul_right {γ : Type*} [NonUnitalNonAssocSemiring γ] (x : γ) : - IsAddMonoidHom fun y : γ => y * x := - { map_zero := zero_mul x - map_add := fun y z => add_mul y z x } - -end IsAddMonoidHom - -/-- Predicate for additive group homomorphism (deprecated -- use bundled `MonoidHom`). -/ -structure IsAddGroupHom [AddGroup α] [AddGroup β] (f : α → β) extends IsAddHom f : Prop - -/-- Predicate for group homomorphisms (deprecated -- use bundled `MonoidHom`). -/ -@[to_additive] -structure IsGroupHom [Group α] [Group β] (f : α → β) extends IsMulHom f : Prop - -@[to_additive] -theorem MonoidHom.isGroupHom {G H : Type*} {_ : Group G} {_ : Group H} (f : G →* H) : - IsGroupHom (f : G → H) := - { map_mul := f.map_mul } - -@[to_additive] -theorem MulEquiv.isGroupHom {G H : Type*} {_ : Group G} {_ : Group H} (h : G ≃* H) : - IsGroupHom h := - { map_mul := map_mul h } - -/-- Construct `IsGroupHom` from its only hypothesis. -/ -@[to_additive "Construct `IsAddGroupHom` from its only hypothesis."] -theorem IsGroupHom.mk' [Group α] [Group β] {f : α → β} (hf : ∀ x y, f (x * y) = f x * f y) : - IsGroupHom f := - { map_mul := hf } - -namespace IsGroupHom - -variable [Group α] [Group β] {f : α → β} (hf : IsGroupHom f) - -/-- The identity is a group homomorphism. -/ -@[to_additive "The identity is an additive group homomorphism."] -theorem id : IsGroupHom (@id α) := - { map_mul := fun _ _ => rfl } - -section -include hf - -open IsMulHom (map_mul) - -theorem map_mul' : ∀ x y, f (x * y) = f x * f y := - hf.toIsMulHom.map_mul - -/-- A group homomorphism is a monoid homomorphism. -/ -@[to_additive "An additive group homomorphism is an additive monoid homomorphism."] -theorem to_isMonoidHom : IsMonoidHom f := - hf.toIsMulHom.to_isMonoidHom - -/-- A group homomorphism sends 1 to 1. -/ -@[to_additive "An additive group homomorphism sends 0 to 0."] -theorem map_one : f 1 = 1 := - hf.to_isMonoidHom.map_one - -/-- A group homomorphism sends inverses to inverses. -/ -@[to_additive "An additive group homomorphism sends negations to negations."] -theorem map_inv (a : α) : f a⁻¹ = (f a)⁻¹ := - eq_inv_of_mul_eq_one_left <| by rw [← hf.map_mul, inv_mul_cancel, hf.map_one] - -@[to_additive] -theorem map_div (a b : α) : f (a / b) = f a / f b := by - simp_rw [div_eq_mul_inv, hf.map_mul, hf.map_inv] - -/-- The composition of two group homomorphisms is a group homomorphism. -/ -@[to_additive - "The composition of two additive group homomorphisms is an additive - group homomorphism."] -theorem comp {γ} [Group γ] {g : β → γ} (hg : IsGroupHom g) : - IsGroupHom (g ∘ f) := - { IsMulHom.comp hf.toIsMulHom hg.toIsMulHom with } - -/-- A group homomorphism is injective iff its kernel is trivial. -/ -@[to_additive "An additive group homomorphism is injective if its kernel is trivial."] -theorem injective_iff : Function.Injective f ↔ ∀ a, f a = 1 → a = 1 := - ⟨fun h _ => by rw [← hf.map_one]; exact @h _ _, fun h x y hxy => - eq_of_div_eq_one <| h _ <| by rwa [hf.map_div, div_eq_one]⟩ - -end - -/-- The product of group homomorphisms is a group homomorphism if the target is commutative. -/ -@[to_additive - "The sum of two additive group homomorphisms is an additive group homomorphism - if the target is commutative."] -theorem mul {α β} [Group α] [CommGroup β] {f g : α → β} (hf : IsGroupHom f) (hg : IsGroupHom g) : - IsGroupHom fun a => f a * g a := - { map_mul := (hf.toIsMulHom.mul hg.toIsMulHom).map_mul } - -/-- The inverse of a group homomorphism is a group homomorphism if the target is commutative. -/ -@[to_additive - "The negation of an additive group homomorphism is an additive group homomorphism - if the target is commutative."] -theorem inv {α β} [Group α] [CommGroup β] {f : α → β} (hf : IsGroupHom f) : - IsGroupHom fun a => (f a)⁻¹ := - { map_mul := hf.toIsMulHom.inv.map_mul } - -end IsGroupHom - -namespace RingHom - -/-! -These instances look redundant, because `Deprecated.Ring` provides `IsRingHom` for a `→+*`. -Nevertheless these are harmless, and helpful for stripping out dependencies on `Deprecated.Ring`. --/ - - -variable {R : Type*} {S : Type*} - -section - -variable [NonAssocSemiring R] [NonAssocSemiring S] - -theorem to_isMonoidHom (f : R →+* S) : IsMonoidHom f := - { map_one := f.map_one - map_mul := f.map_mul } - -theorem to_isAddMonoidHom (f : R →+* S) : IsAddMonoidHom f := - { map_zero := f.map_zero - map_add := f.map_add } - -end - -section - -variable [Ring R] [Ring S] - -theorem to_isAddGroupHom (f : R →+* S) : IsAddGroupHom f := - { map_add := f.map_add } - -end - -end RingHom - -/-- Inversion is a group homomorphism if the group is commutative. -/ -@[to_additive - "Negation is an `AddGroup` homomorphism if the `AddGroup` is commutative."] -theorem Inv.isGroupHom [CommGroup α] : IsGroupHom (Inv.inv : α → α) := - { map_mul := mul_inv } - -/-- The difference of two additive group homomorphisms is an additive group -homomorphism if the target is commutative. -/ -theorem IsAddGroupHom.sub {α β} [AddGroup α] [AddCommGroup β] {f g : α → β} (hf : IsAddGroupHom f) - (hg : IsAddGroupHom g) : IsAddGroupHom fun a => f a - g a := by - simpa only [sub_eq_add_neg] using hf.add hg.neg - -namespace Units - -variable {M : Type*} {N : Type*} [Monoid M] [Monoid N] - -/-- The group homomorphism on units induced by a multiplicative morphism. -/ -abbrev map' {f : M → N} (hf : IsMonoidHom f) : Mˣ →* Nˣ := - map (MonoidHom.of hf) - -@[simp] -theorem coe_map' {f : M → N} (hf : IsMonoidHom f) (x : Mˣ) : ↑((map' hf : Mˣ → Nˣ) x) = f x := - rfl - -theorem coe_isMonoidHom : IsMonoidHom (↑· : Mˣ → M) := - (coeHom M).isMonoidHom_coe - -end Units - -namespace IsUnit - -variable {M : Type*} {N : Type*} [Monoid M] [Monoid N] - -theorem map' {f : M → N} (hf : IsMonoidHom f) {x : M} (h : IsUnit x) : IsUnit (f x) := - h.map (MonoidHom.of hf) - -end IsUnit - -theorem Additive.isAddHom [Mul α] [Mul β] {f : α → β} (hf : IsMulHom f) : - @IsAddHom (Additive α) (Additive β) _ _ f := - { map_add := hf.map_mul } - -theorem Multiplicative.isMulHom [Add α] [Add β] {f : α → β} (hf : IsAddHom f) : - @IsMulHom (Multiplicative α) (Multiplicative β) _ _ f := - { map_mul := hf.map_add } - --- defeq abuse -theorem Additive.isAddMonoidHom [MulOneClass α] [MulOneClass β] {f : α → β} - (hf : IsMonoidHom f) : @IsAddMonoidHom (Additive α) (Additive β) _ _ f := - { Additive.isAddHom hf.toIsMulHom with map_zero := hf.map_one } - -theorem Multiplicative.isMonoidHom [AddZeroClass α] [AddZeroClass β] {f : α → β} - (hf : IsAddMonoidHom f) : @IsMonoidHom (Multiplicative α) (Multiplicative β) _ _ f := - { Multiplicative.isMulHom hf.toIsAddHom with map_one := hf.map_zero } - -theorem Additive.isAddGroupHom [Group α] [Group β] {f : α → β} (hf : IsGroupHom f) : - @IsAddGroupHom (Additive α) (Additive β) _ _ f := - { map_add := hf.toIsMulHom.map_mul } - -theorem Multiplicative.isGroupHom [AddGroup α] [AddGroup β] {f : α → β} (hf : IsAddGroupHom f) : - @IsGroupHom (Multiplicative α) (Multiplicative β) _ _ f := - { map_mul := hf.toIsAddHom.map_add } diff --git a/Mathlib/Deprecated/Ring.lean b/Mathlib/Deprecated/Ring.lean deleted file mode 100644 index fc34ab12c07ee..0000000000000 --- a/Mathlib/Deprecated/Ring.lean +++ /dev/null @@ -1,150 +0,0 @@ -/- -Copyright (c) 2020 Mario Carneiro. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro --/ -import Mathlib.Deprecated.Group - -/-! -# Unbundled semiring and ring homomorphisms (deprecated) - -This file is deprecated, and is no longer imported by anything in mathlib other than other -deprecated files, and test files. You should not need to import it. - -This file defines predicates for unbundled semiring and ring homomorphisms. Instead of using -this file, please use `RingHom`, defined in `Algebra.Hom.Ring`, with notation `→+*`, for -morphisms between semirings or rings. For example use `φ : A →+* B` to represent a -ring homomorphism. - -## Main Definitions - -`IsSemiringHom` (deprecated), `IsRingHom` (deprecated) - -## Tags - -IsSemiringHom, IsRingHom - --/ - - -universe u v - -variable {α : Type u} - -/-- Predicate for semiring homomorphisms (deprecated -- use the bundled `RingHom` version). -/ -structure IsSemiringHom {α : Type u} {β : Type v} [Semiring α] [Semiring β] (f : α → β) : Prop where - /-- The proposition that `f` preserves the additive identity. -/ - map_zero : f 0 = 0 - /-- The proposition that `f` preserves the multiplicative identity. -/ - map_one : f 1 = 1 - /-- The proposition that `f` preserves addition. -/ - map_add : ∀ x y, f (x + y) = f x + f y - /-- The proposition that `f` preserves multiplication. -/ - map_mul : ∀ x y, f (x * y) = f x * f y - -namespace IsSemiringHom - -variable {β : Type v} [Semiring α] [Semiring β] -variable {f : α → β} - -/-- The identity map is a semiring homomorphism. -/ -theorem id : IsSemiringHom (@id α) := by constructor <;> intros <;> rfl - -/-- The composition of two semiring homomorphisms is a semiring homomorphism. -/ -theorem comp (hf : IsSemiringHom f) {γ} [Semiring γ] {g : β → γ} (hg : IsSemiringHom g) : - IsSemiringHom (g ∘ f) := - { map_zero := by simpa [map_zero hf] using map_zero hg - map_one := by simpa [map_one hf] using map_one hg - map_add := fun {x y} => by simp [map_add hf, map_add hg] - map_mul := fun {x y} => by simp [map_mul hf, map_mul hg] } - -/-- A semiring homomorphism is an additive monoid homomorphism. -/ -theorem to_isAddMonoidHom (hf : IsSemiringHom f) : IsAddMonoidHom f := - { ‹IsSemiringHom f› with map_add := by apply @‹IsSemiringHom f›.map_add } - -/-- A semiring homomorphism is a monoid homomorphism. -/ -theorem to_isMonoidHom (hf : IsSemiringHom f) : IsMonoidHom f := - { ‹IsSemiringHom f› with } - -end IsSemiringHom - -/-- Predicate for ring homomorphisms (deprecated -- use the bundled `RingHom` version). -/ -structure IsRingHom {α : Type u} {β : Type v} [Ring α] [Ring β] (f : α → β) : Prop where - /-- The proposition that `f` preserves the multiplicative identity. -/ - map_one : f 1 = 1 - /-- The proposition that `f` preserves multiplication. -/ - map_mul : ∀ x y, f (x * y) = f x * f y - /-- The proposition that `f` preserves addition. -/ - map_add : ∀ x y, f (x + y) = f x + f y - -namespace IsRingHom - -variable {β : Type v} [Ring α] [Ring β] - -/-- A map of rings that is a semiring homomorphism is also a ring homomorphism. -/ -theorem of_semiring {f : α → β} (H : IsSemiringHom f) : IsRingHom f := - { H with } - -variable {f : α → β} {x y : α} - -/-- Ring homomorphisms map zero to zero. -/ -theorem map_zero (hf : IsRingHom f) : f 0 = 0 := - calc - f 0 = f (0 + 0) - f 0 := by rw [hf.map_add]; simp - _ = 0 := by simp - -/-- Ring homomorphisms preserve additive inverses. -/ -theorem map_neg (hf : IsRingHom f) : f (-x) = -f x := - calc - f (-x) = f (-x + x) - f x := by rw [hf.map_add]; simp - _ = -f x := by simp [hf.map_zero] - -/-- Ring homomorphisms preserve subtraction. -/ -theorem map_sub (hf : IsRingHom f) : f (x - y) = f x - f y := by - simp [sub_eq_add_neg, hf.map_add, hf.map_neg] - -/-- The identity map is a ring homomorphism. -/ -theorem id : IsRingHom (@id α) := by constructor <;> intros <;> rfl - --- see Note [no instance on morphisms] -/-- The composition of two ring homomorphisms is a ring homomorphism. -/ -theorem comp (hf : IsRingHom f) {γ} [Ring γ] {g : β → γ} (hg : IsRingHom g) : IsRingHom (g ∘ f) := - { map_add := fun x y => by simp only [Function.comp_apply, map_add hf, map_add hg] - map_mul := fun x y => by simp only [Function.comp_apply, map_mul hf, map_mul hg] - map_one := by simp only [Function.comp_apply, map_one hf, map_one hg] } - -/-- A ring homomorphism is also a semiring homomorphism. -/ -theorem to_isSemiringHom (hf : IsRingHom f) : IsSemiringHom f := - { ‹IsRingHom f› with map_zero := map_zero hf } - -theorem to_isAddGroupHom (hf : IsRingHom f) : IsAddGroupHom f := - { map_add := hf.map_add } - -end IsRingHom - -variable {β : Type v} {rα : Semiring α} {rβ : Semiring β} - -namespace RingHom - -section - -/-- Interpret `f : α → β` with `IsSemiringHom f` as a ring homomorphism. -/ -def of {f : α → β} (hf : IsSemiringHom f) : α →+* β := - { MonoidHom.of hf.to_isMonoidHom, AddMonoidHom.of hf.to_isAddMonoidHom with toFun := f } - -@[simp] -theorem coe_of {f : α → β} (hf : IsSemiringHom f) : ⇑(of hf) = f := - rfl - -theorem to_isSemiringHom (f : α →+* β) : IsSemiringHom f := - { map_zero := f.map_zero - map_one := f.map_one - map_add := f.map_add - map_mul := f.map_mul } - -end - -theorem to_isRingHom {α γ} [Ring α] [Ring γ] (g : α →+* γ) : IsRingHom g := - IsRingHom.of_semiring g.to_isSemiringHom - -end RingHom diff --git a/Mathlib/Deprecated/Subfield.lean b/Mathlib/Deprecated/Subfield.lean deleted file mode 100644 index 3ce93a3a26acc..0000000000000 --- a/Mathlib/Deprecated/Subfield.lean +++ /dev/null @@ -1,150 +0,0 @@ -/- -Copyright (c) 2018 Andreas Swerdlow. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Andreas Swerdlow --/ -import Mathlib.Algebra.Field.Basic -import Mathlib.Deprecated.Subring -import Mathlib.Algebra.GroupWithZero.Units.Lemmas - -/-! -# Unbundled subfields (deprecated) - -This file is deprecated, and is no longer imported by anything in mathlib other than other -deprecated files, and test files. You should not need to import it. - -This file defines predicates for unbundled subfields. Instead of using this file, please use -`Subfield`, defined in `FieldTheory.Subfield`, for subfields of fields. - -## Main definitions - -`IsSubfield (S : Set F) : Prop` : the predicate that `S` is the underlying set of a subfield -of the field `F`. The bundled variant `Subfield F` should be used in preference to this. - -## Tags - -IsSubfield, subfield --/ - - -variable {F : Type*} [Field F] (S : Set F) - -/-- `IsSubfield (S : Set F)` is the predicate saying that a given subset of a field is -the set underlying a subfield. This structure is deprecated; use the bundled variant -`Subfield F` to model subfields of a field. -/ -structure IsSubfield extends IsSubring S : Prop where - inv_mem : ∀ {x : F}, x ∈ S → x⁻¹ ∈ S - -theorem IsSubfield.div_mem {S : Set F} (hS : IsSubfield S) {x y : F} (hx : x ∈ S) (hy : y ∈ S) : - x / y ∈ S := by - rw [div_eq_mul_inv] - exact hS.toIsSubring.toIsSubmonoid.mul_mem hx (hS.inv_mem hy) - -theorem IsSubfield.pow_mem {a : F} {n : ℤ} {s : Set F} (hs : IsSubfield s) (h : a ∈ s) : - a ^ n ∈ s := by - cases' n with n n - · suffices a ^ (n : ℤ) ∈ s by exact this - rw [zpow_natCast] - exact hs.toIsSubring.toIsSubmonoid.pow_mem h - · rw [zpow_negSucc] - exact hs.inv_mem (hs.toIsSubring.toIsSubmonoid.pow_mem h) - -theorem Univ.isSubfield : IsSubfield (@Set.univ F) := - { Univ.isSubmonoid, IsAddSubgroup.univ_addSubgroup with - inv_mem := fun _ ↦ trivial } - -theorem Preimage.isSubfield {K : Type*} [Field K] (f : F →+* K) {s : Set K} (hs : IsSubfield s) : - IsSubfield (f ⁻¹' s) := - { f.isSubring_preimage hs.toIsSubring with - inv_mem := fun {a} (ha : f a ∈ s) ↦ show f a⁻¹ ∈ s by - rw [map_inv₀] - exact hs.inv_mem ha } - -theorem Image.isSubfield {K : Type*} [Field K] (f : F →+* K) {s : Set F} (hs : IsSubfield s) : - IsSubfield (f '' s) := - { f.isSubring_image hs.toIsSubring with - inv_mem := fun ⟨x, xmem, ha⟩ ↦ ⟨x⁻¹, hs.inv_mem xmem, ha ▸ map_inv₀ f x⟩ } - -theorem Range.isSubfield {K : Type*} [Field K] (f : F →+* K) : IsSubfield (Set.range f) := by - rw [← Set.image_univ] - apply Image.isSubfield _ Univ.isSubfield - -namespace Field - -/-- `Field.closure s` is the minimal subfield that includes `s`. -/ -def closure : Set F := - { x | ∃ y ∈ Ring.closure S, ∃ z ∈ Ring.closure S, y / z = x } - -variable {S} - -theorem ring_closure_subset : Ring.closure S ⊆ closure S := - fun x hx ↦ ⟨x, hx, 1, Ring.closure.isSubring.toIsSubmonoid.one_mem, div_one x⟩ - -theorem closure.isSubmonoid : IsSubmonoid (closure S) := - { mul_mem := by - rintro _ _ ⟨p, hp, q, hq, hq0, rfl⟩ ⟨r, hr, s, hs, hs0, rfl⟩ - exact ⟨p * r, IsSubmonoid.mul_mem Ring.closure.isSubring.toIsSubmonoid hp hr, q * s, - IsSubmonoid.mul_mem Ring.closure.isSubring.toIsSubmonoid hq hs, - (div_mul_div_comm _ _ _ _).symm⟩ - one_mem := ring_closure_subset <| IsSubmonoid.one_mem Ring.closure.isSubring.toIsSubmonoid } - -theorem closure.isSubfield : IsSubfield (closure S) := - { closure.isSubmonoid with - add_mem := by - intro a b ha hb - rcases id ha with ⟨p, hp, q, hq, rfl⟩ - rcases id hb with ⟨r, hr, s, hs, rfl⟩ - by_cases hq0 : q = 0 - · rwa [hq0, div_zero, zero_add] - by_cases hs0 : s = 0 - · rwa [hs0, div_zero, add_zero] - exact ⟨p * s + q * r, - IsAddSubmonoid.add_mem Ring.closure.isSubring.toIsAddSubgroup.toIsAddSubmonoid - (Ring.closure.isSubring.toIsSubmonoid.mul_mem hp hs) - (Ring.closure.isSubring.toIsSubmonoid.mul_mem hq hr), - q * s, Ring.closure.isSubring.toIsSubmonoid.mul_mem hq hs, (div_add_div p r hq0 hs0).symm⟩ - zero_mem := ring_closure_subset Ring.closure.isSubring.toIsAddSubgroup.toIsAddSubmonoid.zero_mem - neg_mem := by - rintro _ ⟨p, hp, q, hq, rfl⟩ - exact ⟨-p, Ring.closure.isSubring.toIsAddSubgroup.neg_mem hp, q, hq, neg_div q p⟩ - inv_mem := by - rintro _ ⟨p, hp, q, hq, rfl⟩ - exact ⟨q, hq, p, hp, (inv_div _ _).symm⟩ } - -theorem mem_closure {a : F} (ha : a ∈ S) : a ∈ closure S := - ring_closure_subset <| Ring.mem_closure ha - -theorem subset_closure : S ⊆ closure S := - fun _ ↦ mem_closure - -theorem closure_subset {T : Set F} (hT : IsSubfield T) (H : S ⊆ T) : closure S ⊆ T := by - rintro _ ⟨p, hp, q, hq, hq0, rfl⟩ - exact hT.div_mem (Ring.closure_subset hT.toIsSubring H hp) - (Ring.closure_subset hT.toIsSubring H hq) - -theorem closure_subset_iff {s t : Set F} (ht : IsSubfield t) : closure s ⊆ t ↔ s ⊆ t := - ⟨Set.Subset.trans subset_closure, closure_subset ht⟩ - -@[gcongr] -theorem closure_mono {s t : Set F} (H : s ⊆ t) : closure s ⊆ closure t := - closure_subset closure.isSubfield <| Set.Subset.trans H subset_closure - -end Field - -theorem isSubfield_iUnion_of_directed {ι : Type*} [Nonempty ι] {s : ι → Set F} - (hs : ∀ i, IsSubfield (s i)) (directed : ∀ i j, ∃ k, s i ⊆ s k ∧ s j ⊆ s k) : - IsSubfield (⋃ i, s i) := - { inv_mem := fun hx ↦ - let ⟨i, hi⟩ := Set.mem_iUnion.1 hx - Set.mem_iUnion.2 ⟨i, (hs i).inv_mem hi⟩ - toIsSubring := isSubring_iUnion_of_directed (fun i ↦ (hs i).toIsSubring) directed } - -theorem IsSubfield.inter {S₁ S₂ : Set F} (hS₁ : IsSubfield S₁) (hS₂ : IsSubfield S₂) : - IsSubfield (S₁ ∩ S₂) := - { IsSubring.inter hS₁.toIsSubring hS₂.toIsSubring with - inv_mem := fun hx ↦ ⟨hS₁.inv_mem hx.1, hS₂.inv_mem hx.2⟩ } - -theorem IsSubfield.iInter {ι : Sort*} {S : ι → Set F} (h : ∀ y : ι, IsSubfield (S y)) : - IsSubfield (Set.iInter S) := - { IsSubring.iInter fun y ↦ (h y).toIsSubring with - inv_mem := fun hx ↦ Set.mem_iInter.2 fun y ↦ (h y).inv_mem <| Set.mem_iInter.1 hx y } diff --git a/Mathlib/Deprecated/Subgroup.lean b/Mathlib/Deprecated/Subgroup.lean deleted file mode 100644 index 3842d160c48ac..0000000000000 --- a/Mathlib/Deprecated/Subgroup.lean +++ /dev/null @@ -1,627 +0,0 @@ -/- -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, Kim Morrison, Johan Commelin, Mario Carneiro, - Michael Howes --/ -import Mathlib.Algebra.Group.Subgroup.Basic -import Mathlib.Deprecated.Submonoid - -/-! -# Unbundled subgroups (deprecated) - -This file is deprecated, and is no longer imported by anything in mathlib other than other -deprecated files, and test files. You should not need to import it. - -This file defines unbundled multiplicative and additive subgroups. Instead of using this file, -please use `Subgroup G` and `AddSubgroup A`, defined in `Mathlib.Algebra.Group.Subgroup.Basic`. - -## Main definitions - -`IsAddSubgroup (S : Set A)` : the predicate that `S` is the underlying subset of an additive -subgroup of `A`. The bundled variant `AddSubgroup A` should be used in preference to this. - -`IsSubgroup (S : Set G)` : the predicate that `S` is the underlying subset of a subgroup -of `G`. The bundled variant `Subgroup G` should be used in preference to this. - -## Tags - -subgroup, subgroups, IsSubgroup --/ - - -open Set Function - -variable {G : Type*} {H : Type*} {A : Type*} {a b : G} - -section Group - -variable [Group G] [AddGroup A] - -/-- `s` is an additive subgroup: a set containing 0 and closed under addition and negation. -/ -structure IsAddSubgroup (s : Set A) extends IsAddSubmonoid s : Prop where - /-- The proposition that `s` is closed under negation. -/ - neg_mem {a} : a ∈ s → -a ∈ s - -/-- `s` is a subgroup: a set containing 1 and closed under multiplication and inverse. -/ -@[to_additive] -structure IsSubgroup (s : Set G) extends IsSubmonoid s : Prop where - /-- The proposition that `s` is closed under inverse. -/ - inv_mem {a} : a ∈ s → a⁻¹ ∈ s - -@[to_additive] -theorem IsSubgroup.div_mem {s : Set G} (hs : IsSubgroup s) {x y : G} (hx : x ∈ s) (hy : y ∈ s) : - x / y ∈ s := by simpa only [div_eq_mul_inv] using hs.mul_mem hx (hs.inv_mem hy) - -theorem Additive.isAddSubgroup {s : Set G} (hs : IsSubgroup s) : @IsAddSubgroup (Additive G) _ s := - @IsAddSubgroup.mk (Additive G) _ _ (Additive.isAddSubmonoid hs.toIsSubmonoid) hs.inv_mem - -theorem Additive.isAddSubgroup_iff {s : Set G} : @IsAddSubgroup (Additive G) _ s ↔ IsSubgroup s := - ⟨by rintro ⟨⟨h₁, h₂⟩, h₃⟩; exact @IsSubgroup.mk G _ _ ⟨h₁, @h₂⟩ @h₃, fun h => - Additive.isAddSubgroup h⟩ - -theorem Multiplicative.isSubgroup {s : Set A} (hs : IsAddSubgroup s) : - @IsSubgroup (Multiplicative A) _ s := - @IsSubgroup.mk (Multiplicative A) _ _ (Multiplicative.isSubmonoid hs.toIsAddSubmonoid) hs.neg_mem - -theorem Multiplicative.isSubgroup_iff {s : Set A} : - @IsSubgroup (Multiplicative A) _ s ↔ IsAddSubgroup s := - ⟨by rintro ⟨⟨h₁, h₂⟩, h₃⟩; exact @IsAddSubgroup.mk A _ _ ⟨h₁, @h₂⟩ @h₃, fun h => - Multiplicative.isSubgroup h⟩ - -@[to_additive of_add_neg] -theorem IsSubgroup.of_div (s : Set G) (one_mem : (1 : G) ∈ s) - (div_mem : ∀ {a b : G}, a ∈ s → b ∈ s → a * b⁻¹ ∈ s) : IsSubgroup s := - have inv_mem : ∀ a, a ∈ s → a⁻¹ ∈ s := fun a ha => by - have : 1 * a⁻¹ ∈ s := div_mem one_mem ha - convert this using 1 - rw [one_mul] - { inv_mem := inv_mem _ - mul_mem := fun {a b} ha hb => by - have : a * b⁻¹⁻¹ ∈ s := div_mem ha (inv_mem b hb) - convert this - rw [inv_inv] - one_mem } - -theorem IsAddSubgroup.of_sub (s : Set A) (zero_mem : (0 : A) ∈ s) - (sub_mem : ∀ {a b : A}, a ∈ s → b ∈ s → a - b ∈ s) : IsAddSubgroup s := - IsAddSubgroup.of_add_neg s zero_mem fun {x y} hx hy => by - simpa only [sub_eq_add_neg] using sub_mem hx hy - -@[to_additive] -theorem IsSubgroup.inter {s₁ s₂ : Set G} (hs₁ : IsSubgroup s₁) (hs₂ : IsSubgroup s₂) : - IsSubgroup (s₁ ∩ s₂) := - { IsSubmonoid.inter hs₁.toIsSubmonoid hs₂.toIsSubmonoid with - inv_mem := fun hx => ⟨hs₁.inv_mem hx.1, hs₂.inv_mem hx.2⟩ } - -@[to_additive] -theorem IsSubgroup.iInter {ι : Sort*} {s : ι → Set G} (hs : ∀ y : ι, IsSubgroup (s y)) : - IsSubgroup (Set.iInter s) := - { IsSubmonoid.iInter fun y => (hs y).toIsSubmonoid with - inv_mem := fun h => - Set.mem_iInter.2 fun y => IsSubgroup.inv_mem (hs _) (Set.mem_iInter.1 h y) } - -@[to_additive] -theorem isSubgroup_iUnion_of_directed {ι : Type*} [Nonempty ι] {s : ι → Set G} - (hs : ∀ i, IsSubgroup (s i)) (directed : ∀ i j, ∃ k, s i ⊆ s k ∧ s j ⊆ s k) : - IsSubgroup (⋃ i, s i) := - { inv_mem := fun ha => - let ⟨i, hi⟩ := Set.mem_iUnion.1 ha - Set.mem_iUnion.2 ⟨i, (hs i).inv_mem hi⟩ - toIsSubmonoid := isSubmonoid_iUnion_of_directed (fun i => (hs i).toIsSubmonoid) directed } - -end Group - -namespace IsSubgroup - -open IsSubmonoid - -variable [Group G] {s : Set G} (hs : IsSubgroup s) -include hs - -@[to_additive] -theorem inv_mem_iff : a⁻¹ ∈ s ↔ a ∈ s := - ⟨fun h => by simpa using hs.inv_mem h, inv_mem hs⟩ - -@[to_additive] -theorem mul_mem_cancel_right (h : a ∈ s) : b * a ∈ s ↔ b ∈ s := - ⟨fun hba => by simpa using hs.mul_mem hba (hs.inv_mem h), fun hb => hs.mul_mem hb h⟩ - -@[to_additive] -theorem mul_mem_cancel_left (h : a ∈ s) : a * b ∈ s ↔ b ∈ s := - ⟨fun hab => by simpa using hs.mul_mem (hs.inv_mem h) hab, hs.mul_mem h⟩ - -end IsSubgroup - -/-- `IsNormalAddSubgroup (s : Set A)` expresses the fact that `s` is a normal additive subgroup -of the additive group `A`. Important: the preferred way to say this in Lean is via bundled -subgroups `S : AddSubgroup A` and `hs : S.normal`, and not via this structure. -/ -structure IsNormalAddSubgroup [AddGroup A] (s : Set A) extends IsAddSubgroup s : Prop where - /-- The proposition that `s` is closed under (additive) conjugation. -/ - normal : ∀ n ∈ s, ∀ g : A, g + n + -g ∈ s - -/-- `IsNormalSubgroup (s : Set G)` expresses the fact that `s` is a normal subgroup -of the group `G`. Important: the preferred way to say this in Lean is via bundled -subgroups `S : Subgroup G` and not via this structure. -/ -@[to_additive] -structure IsNormalSubgroup [Group G] (s : Set G) extends IsSubgroup s : Prop where - /-- The proposition that `s` is closed under conjugation. -/ - normal : ∀ n ∈ s, ∀ g : G, g * n * g⁻¹ ∈ s - -@[to_additive] -theorem isNormalSubgroup_of_commGroup [CommGroup G] {s : Set G} (hs : IsSubgroup s) : - IsNormalSubgroup s := - { hs with normal := fun n hn g => by rwa [mul_right_comm, mul_inv_cancel, one_mul] } - -theorem Additive.isNormalAddSubgroup [Group G] {s : Set G} (hs : IsNormalSubgroup s) : - @IsNormalAddSubgroup (Additive G) _ s := - @IsNormalAddSubgroup.mk (Additive G) _ _ (Additive.isAddSubgroup hs.toIsSubgroup) - (@IsNormalSubgroup.normal _ ‹Group (Additive G)› _ hs) - -- Porting note: Lean needs help synthesising - -theorem Additive.isNormalAddSubgroup_iff [Group G] {s : Set G} : - @IsNormalAddSubgroup (Additive G) _ s ↔ IsNormalSubgroup s := - ⟨by rintro ⟨h₁, h₂⟩; exact @IsNormalSubgroup.mk G _ _ (Additive.isAddSubgroup_iff.1 h₁) @h₂, - fun h => Additive.isNormalAddSubgroup h⟩ - -theorem Multiplicative.isNormalSubgroup [AddGroup A] {s : Set A} (hs : IsNormalAddSubgroup s) : - @IsNormalSubgroup (Multiplicative A) _ s := - @IsNormalSubgroup.mk (Multiplicative A) _ _ (Multiplicative.isSubgroup hs.toIsAddSubgroup) - (@IsNormalAddSubgroup.normal _ ‹AddGroup (Multiplicative A)› _ hs) - -theorem Multiplicative.isNormalSubgroup_iff [AddGroup A] {s : Set A} : - @IsNormalSubgroup (Multiplicative A) _ s ↔ IsNormalAddSubgroup s := - ⟨by - rintro ⟨h₁, h₂⟩ - exact @IsNormalAddSubgroup.mk A _ _ (Multiplicative.isSubgroup_iff.1 h₁) @h₂, - fun h => Multiplicative.isNormalSubgroup h⟩ - -namespace IsSubgroup - -variable [Group G] - --- Normal subgroup properties -@[to_additive] -theorem mem_norm_comm {s : Set G} (hs : IsNormalSubgroup s) {a b : G} (hab : a * b ∈ s) : - b * a ∈ s := by - simpa using (hs.normal (a * b) hab a⁻¹) - -@[to_additive] -theorem mem_norm_comm_iff {s : Set G} (hs : IsNormalSubgroup s) {a b : G} : a * b ∈ s ↔ b * a ∈ s := - ⟨mem_norm_comm hs, mem_norm_comm hs⟩ - -/-- The trivial subgroup -/ -@[to_additive "the trivial additive subgroup"] -def trivial (G : Type*) [Group G] : Set G := - {1} - -@[to_additive (attr := simp)] -theorem mem_trivial {g : G} : g ∈ trivial G ↔ g = 1 := - mem_singleton_iff - -@[to_additive] -theorem trivial_normal : IsNormalSubgroup (trivial G) := by refine ⟨⟨⟨?_, ?_⟩, ?_⟩, ?_⟩ <;> simp - -@[to_additive] -theorem eq_trivial_iff {s : Set G} (hs : IsSubgroup s) : s = trivial G ↔ ∀ x ∈ s, x = (1 : G) := by - simp only [Set.ext_iff, IsSubgroup.mem_trivial] - exact ⟨fun h x => (h x).1, fun h x => ⟨h x, fun hx => hx.symm ▸ hs.toIsSubmonoid.one_mem⟩⟩ - -@[to_additive] -theorem univ_subgroup : IsNormalSubgroup (@univ G) := by refine ⟨⟨⟨?_, ?_⟩, ?_⟩, ?_⟩ <;> simp - -/-- The underlying set of the center of a group. -/ -@[to_additive addCenter "The underlying set of the center of an additive group."] -def center (G : Type*) [Group G] : Set G := - { z | ∀ g, g * z = z * g } - -@[to_additive mem_add_center] -theorem mem_center {a : G} : a ∈ center G ↔ ∀ g, g * a = a * g := - Iff.rfl - -@[to_additive add_center_normal] -theorem center_normal : IsNormalSubgroup (center G) := - { one_mem := by simp [center] - mul_mem := fun ha hb g => by - rw [← mul_assoc, mem_center.2 ha g, mul_assoc, mem_center.2 hb g, ← mul_assoc] - inv_mem := fun {a} ha g => - calc - g * a⁻¹ = a⁻¹ * (g * a) * a⁻¹ := by simp [ha g] - _ = a⁻¹ * g := by rw [← mul_assoc, mul_assoc]; simp - normal := fun n ha g h => - calc - h * (g * n * g⁻¹) = h * n := by simp [ha g, mul_assoc] - _ = g * g⁻¹ * n * h := by rw [ha h]; simp - _ = g * n * g⁻¹ * h := by rw [mul_assoc g, ha g⁻¹, ← mul_assoc] - } - -/-- The underlying set of the normalizer of a subset `S : Set G` of a group `G`. That is, - the elements `g : G` such that `g * S * g⁻¹ = S`. -/ -@[to_additive addNormalizer - "The underlying set of the normalizer of a subset `S : Set A` of an - additive group `A`. That is, the elements `a : A` such that `a + S - a = S`."] -def normalizer (s : Set G) : Set G := - { g : G | ∀ n, n ∈ s ↔ g * n * g⁻¹ ∈ s } - -@[to_additive] -theorem normalizer_isSubgroup (s : Set G) : IsSubgroup (normalizer s) := - { one_mem := by simp [normalizer] - mul_mem := fun {a b} - (ha : ∀ n, n ∈ s ↔ a * n * a⁻¹ ∈ s) (hb : ∀ n, n ∈ s ↔ b * n * b⁻¹ ∈ s) n => - by rw [mul_inv_rev, ← mul_assoc, mul_assoc a, mul_assoc a, ← ha, ← hb] - inv_mem := fun {a} (ha : ∀ n, n ∈ s ↔ a * n * a⁻¹ ∈ s) n => by - rw [ha (a⁻¹ * n * a⁻¹⁻¹)]; simp [mul_assoc] } - -@[to_additive subset_add_normalizer] -theorem subset_normalizer {s : Set G} (hs : IsSubgroup s) : s ⊆ normalizer s := fun g hg n => by - rw [IsSubgroup.mul_mem_cancel_right hs ((IsSubgroup.inv_mem_iff hs).2 hg), - IsSubgroup.mul_mem_cancel_left hs hg] - -end IsSubgroup - --- Homomorphism subgroups -namespace IsGroupHom - -open IsSubmonoid IsSubgroup - -/-- `ker f : Set G` is the underlying subset of the kernel of a map `G → H`. -/ -@[to_additive "`ker f : Set A` is the underlying subset of the kernel of a map `A → B`"] -def ker [Group H] (f : G → H) : Set G := - preimage f (trivial H) - -@[to_additive] -theorem mem_ker [Group H] (f : G → H) {x : G} : x ∈ ker f ↔ f x = 1 := - mem_trivial - -variable [Group G] [Group H] - -@[to_additive] -theorem one_ker_inv {f : G → H} (hf : IsGroupHom f) {a b : G} (h : f (a * b⁻¹) = 1) : - f a = f b := by - rw [hf.map_mul, hf.map_inv] at h - rw [← inv_inv (f b), eq_inv_of_mul_eq_one_left h] - -@[to_additive] -theorem one_ker_inv' {f : G → H} (hf : IsGroupHom f) {a b : G} (h : f (a⁻¹ * b) = 1) : - f a = f b := by - rw [hf.map_mul, hf.map_inv] at h - apply inv_injective - rw [eq_inv_of_mul_eq_one_left h] - -@[to_additive] -theorem inv_ker_one {f : G → H} (hf : IsGroupHom f) {a b : G} (h : f a = f b) : - f (a * b⁻¹) = 1 := by - have : f a * (f b)⁻¹ = 1 := by rw [h, mul_inv_cancel] - rwa [← hf.map_inv, ← hf.map_mul] at this - -@[to_additive] -theorem inv_ker_one' {f : G → H} (hf : IsGroupHom f) {a b : G} (h : f a = f b) : - f (a⁻¹ * b) = 1 := by - have : (f a)⁻¹ * f b = 1 := by rw [h, inv_mul_cancel] - rwa [← hf.map_inv, ← hf.map_mul] at this - -@[to_additive] -theorem one_iff_ker_inv {f : G → H} (hf : IsGroupHom f) (a b : G) : f a = f b ↔ f (a * b⁻¹) = 1 := - ⟨hf.inv_ker_one, hf.one_ker_inv⟩ - -@[to_additive] -theorem one_iff_ker_inv' {f : G → H} (hf : IsGroupHom f) (a b : G) : f a = f b ↔ f (a⁻¹ * b) = 1 := - ⟨hf.inv_ker_one', hf.one_ker_inv'⟩ - -@[to_additive] -theorem inv_iff_ker {f : G → H} (hf : IsGroupHom f) (a b : G) : f a = f b ↔ a * b⁻¹ ∈ ker f := by - rw [mem_ker]; exact one_iff_ker_inv hf _ _ - -@[to_additive] -theorem inv_iff_ker' {f : G → H} (hf : IsGroupHom f) (a b : G) : f a = f b ↔ a⁻¹ * b ∈ ker f := by - rw [mem_ker]; exact one_iff_ker_inv' hf _ _ - -@[to_additive] -theorem image_subgroup {f : G → H} (hf : IsGroupHom f) {s : Set G} (hs : IsSubgroup s) : - IsSubgroup (f '' s) := - { mul_mem := fun {a₁ a₂} ⟨b₁, hb₁, eq₁⟩ ⟨b₂, hb₂, eq₂⟩ => - ⟨b₁ * b₂, hs.mul_mem hb₁ hb₂, by simp [eq₁, eq₂, hf.map_mul]⟩ - one_mem := ⟨1, hs.toIsSubmonoid.one_mem, hf.map_one⟩ - inv_mem := fun {a} ⟨b, hb, Eq⟩ => - ⟨b⁻¹, hs.inv_mem hb, by - rw [hf.map_inv] - simp [*]⟩ } - -@[to_additive] -theorem range_subgroup {f : G → H} (hf : IsGroupHom f) : IsSubgroup (Set.range f) := - @Set.image_univ _ _ f ▸ hf.image_subgroup univ_subgroup.toIsSubgroup - -attribute [local simp] IsSubmonoid.one_mem IsSubgroup.inv_mem - IsSubmonoid.mul_mem IsNormalSubgroup.normal - -@[to_additive] -theorem preimage {f : G → H} (hf : IsGroupHom f) {s : Set H} (hs : IsSubgroup s) : - IsSubgroup (f ⁻¹' s) where - one_mem := by simp [hf.map_one, hs.one_mem] - mul_mem := by simp_all [hf.map_mul, hs.mul_mem] - inv_mem := by simp_all [hf.map_inv] - -@[to_additive] -theorem preimage_normal {f : G → H} (hf : IsGroupHom f) {s : Set H} (hs : IsNormalSubgroup s) : - IsNormalSubgroup (f ⁻¹' s) := - { one_mem := by simp [hf.map_one, hs.toIsSubgroup.one_mem] - mul_mem := by simp +contextual [hf.map_mul, hs.toIsSubgroup.mul_mem] - inv_mem := by simp +contextual [hf.map_inv, hs.toIsSubgroup.inv_mem] - normal := by simp +contextual [hs.normal, hf.map_mul, hf.map_inv] } - -@[to_additive] -theorem isNormalSubgroup_ker {f : G → H} (hf : IsGroupHom f) : IsNormalSubgroup (ker f) := - hf.preimage_normal trivial_normal - -@[to_additive] -theorem injective_of_trivial_ker {f : G → H} (hf : IsGroupHom f) (h : ker f = trivial G) : - Function.Injective f := by - intro a₁ a₂ hfa - simp [Set.ext_iff, ker, IsSubgroup.trivial] at h - have ha : a₁ * a₂⁻¹ = 1 := by rw [← h]; exact hf.inv_ker_one hfa - rw [eq_inv_of_mul_eq_one_left ha, inv_inv a₂] - -@[to_additive] -theorem trivial_ker_of_injective {f : G → H} (hf : IsGroupHom f) (h : Function.Injective f) : - ker f = trivial G := - Set.ext fun x => - Iff.intro - (fun hx => by - suffices f x = f 1 by simpa using h this - simp [hf.map_one]; rwa [mem_ker] at hx) - (by simp +contextual [mem_ker, hf.map_one]) - -@[to_additive] -theorem injective_iff_trivial_ker {f : G → H} (hf : IsGroupHom f) : - Function.Injective f ↔ ker f = trivial G := - ⟨hf.trivial_ker_of_injective, hf.injective_of_trivial_ker⟩ - -@[to_additive] -theorem trivial_ker_iff_eq_one {f : G → H} (hf : IsGroupHom f) : - ker f = trivial G ↔ ∀ x, f x = 1 → x = 1 := by - rw [Set.ext_iff] - simpa [ker] using ⟨fun h x hx => (h x).1 hx, fun h x => ⟨h x, fun hx => by rw [hx, hf.map_one]⟩⟩ - -end IsGroupHom - -namespace AddGroup - -variable [AddGroup A] - -/-- If `A` is an additive group and `s : Set A`, then `InClosure s : Set A` is the underlying -subset of the subgroup generated by `s`. -/ -inductive InClosure (s : Set A) : A → Prop - | basic {a : A} : a ∈ s → InClosure s a - | zero : InClosure s 0 - | neg {a : A} : InClosure s a → InClosure s (-a) - | add {a b : A} : InClosure s a → InClosure s b → InClosure s (a + b) - -end AddGroup - -namespace Group - -open IsSubmonoid IsSubgroup - -variable [Group G] {s : Set G} - -/-- If `G` is a group and `s : Set G`, then `InClosure s : Set G` is the underlying -subset of the subgroup generated by `s`. -/ -@[to_additive] -inductive InClosure (s : Set G) : G → Prop - | basic {a : G} : a ∈ s → InClosure s a - | one : InClosure s 1 - | inv {a : G} : InClosure s a → InClosure s a⁻¹ - | mul {a b : G} : InClosure s a → InClosure s b → InClosure s (a * b) - -/-- `Group.closure s` is the subgroup generated by `s`, i.e. the smallest subgroup containing `s`. --/ -@[to_additive - "`AddGroup.closure s` is the additive subgroup generated by `s`, i.e., the - smallest additive subgroup containing `s`."] -def closure (s : Set G) : Set G := - { a | InClosure s a } - -@[to_additive] -theorem mem_closure {a : G} : a ∈ s → a ∈ closure s := - InClosure.basic - -@[to_additive] -theorem closure.isSubgroup (s : Set G) : IsSubgroup (closure s) := - { one_mem := InClosure.one - mul_mem := InClosure.mul - inv_mem := InClosure.inv } - -@[to_additive] -theorem subset_closure {s : Set G} : s ⊆ closure s := fun _ => mem_closure - -@[to_additive] -theorem closure_subset {s t : Set G} (ht : IsSubgroup t) (h : s ⊆ t) : closure s ⊆ t := fun a ha => - by induction ha <;> simp [h _, *, ht.one_mem, ht.mul_mem, IsSubgroup.inv_mem_iff] - -@[to_additive] -theorem closure_subset_iff {s t : Set G} (ht : IsSubgroup t) : closure s ⊆ t ↔ s ⊆ t := - ⟨fun h _ ha => h (mem_closure ha), fun h _ ha => closure_subset ht h ha⟩ - -@[to_additive (attr := gcongr)] -theorem closure_mono {s t : Set G} (h : s ⊆ t) : closure s ⊆ closure t := - closure_subset (closure.isSubgroup _) <| Set.Subset.trans h subset_closure - -@[to_additive (attr := simp)] -theorem closure_subgroup {s : Set G} (hs : IsSubgroup s) : closure s = s := - Set.Subset.antisymm (closure_subset hs <| Set.Subset.refl s) subset_closure - -@[to_additive] -theorem exists_list_of_mem_closure {s : Set G} {a : G} (h : a ∈ closure s) : - ∃ l : List G, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ l.prod = a := - InClosure.recOn h - (fun {x} hxs => ⟨[x], List.forall_mem_singleton.2 <| Or.inl hxs, List.prod_singleton⟩) - ⟨[], List.forall_mem_nil _, rfl⟩ - (fun {_} _ ⟨L, HL1, HL2⟩ => - ⟨L.reverse.map Inv.inv, fun _ hx => - let ⟨y, hy1, hy2⟩ := List.exists_of_mem_map hx - hy2 ▸ Or.imp id (by rw [inv_inv]; exact id) (HL1 _ <| List.mem_reverse.1 hy1).symm, - HL2 ▸ - List.recOn L inv_one.symm fun hd tl ih => by - rw [List.reverse_cons, List.map_append, List.prod_append, ih, List.map_singleton, - List.prod_cons, List.prod_nil, mul_one, List.prod_cons, mul_inv_rev]⟩) - fun {x y} _ _ ⟨L1, HL1, HL2⟩ ⟨L2, HL3, HL4⟩ => - ⟨L1 ++ L2, List.forall_mem_append.2 ⟨HL1, HL3⟩, by rw [List.prod_append, HL2, HL4]⟩ - -@[to_additive] -theorem image_closure [Group H] {f : G → H} (hf : IsGroupHom f) (s : Set G) : - f '' closure s = closure (f '' s) := - le_antisymm - (by - rintro _ ⟨x, hx, rfl⟩ - exact InClosure.recOn hx - (by intros _ ha; exact subset_closure (mem_image_of_mem f ha)) - (by - rw [hf.map_one] - apply IsSubmonoid.one_mem (closure.isSubgroup _).toIsSubmonoid) - (by - intros _ _ - rw [hf.map_inv] - apply IsSubgroup.inv_mem (closure.isSubgroup _)) - (by - intros _ _ _ _ ha hb - rw [hf.map_mul] - exact (closure.isSubgroup (f '' s)).toIsSubmonoid.mul_mem ha hb)) - (closure_subset (hf.image_subgroup <| closure.isSubgroup _) <| - Set.image_subset _ subset_closure) - -@[to_additive] -theorem mclosure_subset {s : Set G} : Monoid.Closure s ⊆ closure s := - Monoid.closure_subset (closure.isSubgroup _).toIsSubmonoid <| subset_closure - -@[to_additive] -theorem mclosure_inv_subset {s : Set G} : Monoid.Closure (Inv.inv ⁻¹' s) ⊆ closure s := - Monoid.closure_subset (closure.isSubgroup _).toIsSubmonoid fun x hx => - inv_inv x ▸ ((closure.isSubgroup _).inv_mem <| subset_closure hx) - -@[to_additive] -theorem closure_eq_mclosure {s : Set G} : closure s = Monoid.Closure (s ∪ Inv.inv ⁻¹' s) := - Set.Subset.antisymm - (@closure_subset _ _ _ (Monoid.Closure (s ∪ Inv.inv ⁻¹' s)) - { one_mem := (Monoid.closure.isSubmonoid _).one_mem - mul_mem := (Monoid.closure.isSubmonoid _).mul_mem - inv_mem := fun hx => - Monoid.InClosure.recOn hx - (fun {x} hx => - Or.casesOn hx - (fun hx => - Monoid.subset_closure <| Or.inr <| show x⁻¹⁻¹ ∈ s from (inv_inv x).symm ▸ hx) - fun hx => Monoid.subset_closure <| Or.inl hx) - ((@inv_one G _).symm ▸ IsSubmonoid.one_mem (Monoid.closure.isSubmonoid _)) - fun {x y} _ _ ihx ihy => - (mul_inv_rev x y).symm ▸ IsSubmonoid.mul_mem (Monoid.closure.isSubmonoid _) ihy ihx } - (Set.Subset.trans Set.subset_union_left Monoid.subset_closure)) - (Monoid.closure_subset (closure.isSubgroup _).toIsSubmonoid <| - Set.union_subset subset_closure fun x hx => - inv_inv x ▸ (IsSubgroup.inv_mem (closure.isSubgroup _) <| subset_closure hx)) - -@[to_additive] -theorem mem_closure_union_iff {G : Type*} [CommGroup G] {s t : Set G} {x : G} : - x ∈ closure (s ∪ t) ↔ ∃ y ∈ closure s, ∃ z ∈ closure t, y * z = x := by - simp only [closure_eq_mclosure, Monoid.mem_closure_union_iff, exists_prop, preimage_union] - constructor - · rintro ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, rfl⟩ - refine ⟨_, ⟨_, hys, _, hzs, rfl⟩, _, ⟨_, hyt, _, hzt, rfl⟩, ?_⟩ - rw [mul_assoc, mul_assoc, mul_left_comm zs] - · rintro ⟨_, ⟨ys, hys, zs, hzs, rfl⟩, _, ⟨yt, hyt, zt, hzt, rfl⟩, rfl⟩ - refine ⟨_, ⟨ys, hys, yt, hyt, rfl⟩, _, ⟨zs, hzs, zt, hzt, rfl⟩, ?_⟩ - rw [mul_assoc, mul_assoc, mul_left_comm yt] - -end Group - -namespace IsSubgroup - -variable [Group G] - -@[to_additive] -theorem trivial_eq_closure : trivial G = Group.closure ∅ := - Subset.antisymm (by simp [Set.subset_def, (Group.closure.isSubgroup _).one_mem]) - (Group.closure_subset trivial_normal.toIsSubgroup <| by simp) - -end IsSubgroup - -/- The normal closure of a set s is the subgroup closure of all the conjugates of -elements of s. It is the smallest normal subgroup containing s. -/ -namespace Group - -variable {s : Set G} [Group G] - -theorem conjugatesOf_subset {t : Set G} (ht : IsNormalSubgroup t) {a : G} (h : a ∈ t) : - conjugatesOf a ⊆ t := fun x hc => by - obtain ⟨c, w⟩ := isConj_iff.1 hc - have H := IsNormalSubgroup.normal ht a h c - rwa [← w] - -theorem conjugatesOfSet_subset' {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) : - conjugatesOfSet s ⊆ t := - Set.iUnion₂_subset fun _ H => conjugatesOf_subset ht (h H) - -/-- The normal closure of a set s is the subgroup closure of all the conjugates of -elements of s. It is the smallest normal subgroup containing s. -/ -def normalClosure (s : Set G) : Set G := - closure (conjugatesOfSet s) - -theorem conjugatesOfSet_subset_normalClosure : conjugatesOfSet s ⊆ normalClosure s := - subset_closure - -theorem subset_normalClosure : s ⊆ normalClosure s := - Set.Subset.trans subset_conjugatesOfSet conjugatesOfSet_subset_normalClosure - -/-- The normal closure of a set is a subgroup. -/ -theorem normalClosure.isSubgroup (s : Set G) : IsSubgroup (normalClosure s) := - closure.isSubgroup (conjugatesOfSet s) - -/-- The normal closure of s is a normal subgroup. -/ -theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) := - { normalClosure.isSubgroup _ with - normal := fun n h g => by - induction' h with x hx x hx ihx x y hx hy ihx ihy - · exact conjugatesOfSet_subset_normalClosure (conj_mem_conjugatesOfSet hx) - · simpa using (normalClosure.isSubgroup s).one_mem - · rw [← conj_inv] - exact (normalClosure.isSubgroup _).inv_mem ihx - · rw [← conj_mul] - exact (normalClosure.isSubgroup _).toIsSubmonoid.mul_mem ihx ihy } - -/-- The normal closure of s is the smallest normal subgroup containing s. -/ -theorem normalClosure_subset {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) : - normalClosure s ⊆ t := fun a w => by - induction w with - | basic hx => exact conjugatesOfSet_subset' ht h <| hx - | one => exact ht.toIsSubgroup.toIsSubmonoid.one_mem - | inv _ ihx => exact ht.toIsSubgroup.inv_mem ihx - | mul _ _ ihx ihy => exact ht.toIsSubgroup.toIsSubmonoid.mul_mem ihx ihy - -theorem normalClosure_subset_iff {s t : Set G} (ht : IsNormalSubgroup t) : - s ⊆ t ↔ normalClosure s ⊆ t := - ⟨normalClosure_subset ht, Set.Subset.trans subset_normalClosure⟩ - -@[gcongr] -theorem normalClosure_mono {s t : Set G} : s ⊆ t → normalClosure s ⊆ normalClosure t := fun h => - normalClosure_subset normalClosure.is_normal (Set.Subset.trans h subset_normalClosure) - -end Group - -/-- Create a bundled subgroup from a set `s` and `[IsSubgroup s]`. -/ -@[to_additive "Create a bundled additive subgroup from a set `s` and `[IsAddSubgroup s]`."] -def Subgroup.of [Group G] {s : Set G} (h : IsSubgroup s) : Subgroup G where - carrier := s - one_mem' := h.1.1 - mul_mem' := h.1.2 - inv_mem' := h.2 - -@[to_additive] -theorem Subgroup.isSubgroup [Group G] (K : Subgroup G) : IsSubgroup (K : Set G) := - { one_mem := K.one_mem' - mul_mem := K.mul_mem' - inv_mem := K.inv_mem' } - --- this will never fire if it's an instance -@[to_additive] -theorem Subgroup.of_normal [Group G] (s : Set G) (h : IsSubgroup s) (n : IsNormalSubgroup s) : - Subgroup.Normal (Subgroup.of h) := - { conj_mem := n.normal } diff --git a/Mathlib/Deprecated/Submonoid.lean b/Mathlib/Deprecated/Submonoid.lean deleted file mode 100644 index 25e8af4f8368f..0000000000000 --- a/Mathlib/Deprecated/Submonoid.lean +++ /dev/null @@ -1,363 +0,0 @@ -/- -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, Kenny Lau, Johan Commelin, Mario Carneiro, Kevin Buzzard --/ -import Mathlib.Algebra.Group.Submonoid.Defs -import Mathlib.Deprecated.Group -import Mathlib.Data.Set.Lattice -import Mathlib.Algebra.BigOperators.Group.Finset.Defs - -/-! -# Unbundled submonoids (deprecated) - -This file is deprecated, and is no longer imported by anything in mathlib other than other -deprecated files, and test files. You should not need to import it. - -This file defines unbundled multiplicative and additive submonoids. Instead of using this file, -please use `Submonoid G` and `AddSubmonoid A`, defined in `GroupTheory.Submonoid.Basic`. - -## Main definitions - -`IsAddSubmonoid (S : Set M)` : the predicate that `S` is the underlying subset of an additive -submonoid of `M`. The bundled variant `AddSubmonoid M` should be used in preference to this. - -`IsSubmonoid (S : Set M)` : the predicate that `S` is the underlying subset of a submonoid -of `M`. The bundled variant `Submonoid M` should be used in preference to this. - -## Tags -Submonoid, Submonoids, IsSubmonoid --/ - - -variable {M : Type*} [Monoid M] {s : Set M} {A : Type*} [AddMonoid A] - -/-- `s` is an additive submonoid: a set containing 0 and closed under addition. -Note that this structure is deprecated, and the bundled variant `AddSubmonoid A` should be -preferred. -/ -structure IsAddSubmonoid (s : Set A) : Prop where - /-- The proposition that s contains 0. -/ - zero_mem : (0 : A) ∈ s - /-- The proposition that s is closed under addition. -/ - add_mem {a b} : a ∈ s → b ∈ s → a + b ∈ s - -/-- `s` is a submonoid: a set containing 1 and closed under multiplication. -Note that this structure is deprecated, and the bundled variant `Submonoid M` should be -preferred. -/ -@[to_additive] -structure IsSubmonoid (s : Set M) : Prop where - /-- The proposition that s contains 1. -/ - one_mem : (1 : M) ∈ s - /-- The proposition that s is closed under multiplication. -/ - mul_mem {a b} : a ∈ s → b ∈ s → a * b ∈ s - -theorem Additive.isAddSubmonoid {s : Set M} : - IsSubmonoid s → @IsAddSubmonoid (Additive M) _ s - | ⟨h₁, h₂⟩ => ⟨h₁, @h₂⟩ - -theorem Additive.isAddSubmonoid_iff {s : Set M} : - @IsAddSubmonoid (Additive M) _ s ↔ IsSubmonoid s := - ⟨fun ⟨h₁, h₂⟩ => ⟨h₁, @h₂⟩, Additive.isAddSubmonoid⟩ - -theorem Multiplicative.isSubmonoid {s : Set A} : - IsAddSubmonoid s → @IsSubmonoid (Multiplicative A) _ s - | ⟨h₁, h₂⟩ => ⟨h₁, @h₂⟩ - -theorem Multiplicative.isSubmonoid_iff {s : Set A} : - @IsSubmonoid (Multiplicative A) _ s ↔ IsAddSubmonoid s := - ⟨fun ⟨h₁, h₂⟩ => ⟨h₁, @h₂⟩, Multiplicative.isSubmonoid⟩ - -/-- The intersection of two submonoids of a monoid `M` is a submonoid of `M`. -/ -@[to_additive - "The intersection of two `AddSubmonoid`s of an `AddMonoid` `M` is an `AddSubmonoid` of M."] -theorem IsSubmonoid.inter {s₁ s₂ : Set M} (is₁ : IsSubmonoid s₁) (is₂ : IsSubmonoid s₂) : - IsSubmonoid (s₁ ∩ s₂) := - { one_mem := ⟨is₁.one_mem, is₂.one_mem⟩ - mul_mem := @fun _ _ hx hy => ⟨is₁.mul_mem hx.1 hy.1, is₂.mul_mem hx.2 hy.2⟩ } - -/-- The intersection of an indexed set of submonoids of a monoid `M` is a submonoid of `M`. -/ -@[to_additive - "The intersection of an indexed set of `AddSubmonoid`s of an `AddMonoid` `M` is - an `AddSubmonoid` of `M`."] -theorem IsSubmonoid.iInter {ι : Sort*} {s : ι → Set M} (h : ∀ y : ι, IsSubmonoid (s y)) : - IsSubmonoid (Set.iInter s) := - { one_mem := Set.mem_iInter.2 fun y => (h y).one_mem - mul_mem := fun h₁ h₂ => - Set.mem_iInter.2 fun y => (h y).mul_mem (Set.mem_iInter.1 h₁ y) (Set.mem_iInter.1 h₂ y) } - -/-- The union of an indexed, directed, nonempty set of submonoids of a monoid `M` is a submonoid - of `M`. -/ -@[to_additive - "The union of an indexed, directed, nonempty set of `AddSubmonoid`s of an `AddMonoid` `M` - is an `AddSubmonoid` of `M`. "] -theorem isSubmonoid_iUnion_of_directed {ι : Type*} [hι : Nonempty ι] {s : ι → Set M} - (hs : ∀ i, IsSubmonoid (s i)) (Directed : ∀ i j, ∃ k, s i ⊆ s k ∧ s j ⊆ s k) : - IsSubmonoid (⋃ i, s i) := - { one_mem := - let ⟨i⟩ := hι - Set.mem_iUnion.2 ⟨i, (hs i).one_mem⟩ - mul_mem := fun ha hb => - let ⟨i, hi⟩ := Set.mem_iUnion.1 ha - let ⟨j, hj⟩ := Set.mem_iUnion.1 hb - let ⟨k, hk⟩ := Directed i j - Set.mem_iUnion.2 ⟨k, (hs k).mul_mem (hk.1 hi) (hk.2 hj)⟩ } - -section powers - -/-- The set of natural number powers `1, x, x², ...` of an element `x` of a monoid. -/ -@[to_additive - "The set of natural number multiples `0, x, 2x, ...` of an element `x` of an `AddMonoid`."] -def powers (x : M) : Set M := - { y | ∃ n : ℕ, x ^ n = y } - -/-- 1 is in the set of natural number powers of an element of a monoid. -/ -@[to_additive "0 is in the set of natural number multiples of an element of an `AddMonoid`."] -theorem powers.one_mem {x : M} : (1 : M) ∈ powers x := - ⟨0, pow_zero _⟩ - -/-- An element of a monoid is in the set of that element's natural number powers. -/ -@[to_additive - "An element of an `AddMonoid` is in the set of that element's natural number multiples."] -theorem powers.self_mem {x : M} : x ∈ powers x := - ⟨1, pow_one _⟩ - -/-- The set of natural number powers of an element of a monoid is closed under multiplication. -/ -@[to_additive - "The set of natural number multiples of an element of an `AddMonoid` is closed under - addition."] -theorem powers.mul_mem {x y z : M} : y ∈ powers x → z ∈ powers x → y * z ∈ powers x := - fun ⟨n₁, h₁⟩ ⟨n₂, h₂⟩ => ⟨n₁ + n₂, by simp only [pow_add, *]⟩ - -/-- The set of natural number powers of an element of a monoid `M` is a submonoid of `M`. -/ -@[to_additive - "The set of natural number multiples of an element of an `AddMonoid` `M` is - an `AddSubmonoid` of `M`."] -theorem powers.isSubmonoid (x : M) : IsSubmonoid (powers x) := - { one_mem := powers.one_mem - mul_mem := powers.mul_mem } - -/-- A monoid is a submonoid of itself. -/ -@[to_additive "An `AddMonoid` is an `AddSubmonoid` of itself."] -theorem Univ.isSubmonoid : IsSubmonoid (@Set.univ M) := by constructor <;> simp - -/-- The preimage of a submonoid under a monoid hom is a submonoid of the domain. -/ -@[to_additive - "The preimage of an `AddSubmonoid` under an `AddMonoid` hom is - an `AddSubmonoid` of the domain."] -theorem IsSubmonoid.preimage {N : Type*} [Monoid N] {f : M → N} (hf : IsMonoidHom f) {s : Set N} - (hs : IsSubmonoid s) : IsSubmonoid (f ⁻¹' s) := - { one_mem := show f 1 ∈ s by (rw [IsMonoidHom.map_one hf]; exact hs.one_mem) - mul_mem := fun {a b} (ha : f a ∈ s) (hb : f b ∈ s) => - show f (a * b) ∈ s by (rw [IsMonoidHom.map_mul' hf]; exact hs.mul_mem ha hb) } - -/-- The image of a submonoid under a monoid hom is a submonoid of the codomain. -/ -@[to_additive - "The image of an `AddSubmonoid` under an `AddMonoid` hom is an `AddSubmonoid` of the - codomain."] -theorem IsSubmonoid.image {γ : Type*} [Monoid γ] {f : M → γ} (hf : IsMonoidHom f) {s : Set M} - (hs : IsSubmonoid s) : IsSubmonoid (f '' s) := - { one_mem := ⟨1, hs.one_mem, hf.map_one⟩ - mul_mem := @fun a b ⟨x, hx⟩ ⟨y, hy⟩ => - ⟨x * y, hs.mul_mem hx.1 hy.1, by rw [hf.map_mul, hx.2, hy.2]⟩ } - -/-- The image of a monoid hom is a submonoid of the codomain. -/ -@[to_additive "The image of an `AddMonoid` hom is an `AddSubmonoid` of the codomain."] -theorem Range.isSubmonoid {γ : Type*} [Monoid γ] {f : M → γ} (hf : IsMonoidHom f) : - IsSubmonoid (Set.range f) := by - rw [← Set.image_univ] - exact Univ.isSubmonoid.image hf - -/-- Submonoids are closed under natural powers. -/ -@[to_additive - "An `AddSubmonoid` is closed under multiplication by naturals."] -theorem IsSubmonoid.pow_mem {a : M} (hs : IsSubmonoid s) (h : a ∈ s) : ∀ {n : ℕ}, a ^ n ∈ s - | 0 => by - rw [pow_zero] - exact hs.one_mem - | n + 1 => by - rw [pow_succ] - exact hs.mul_mem (IsSubmonoid.pow_mem hs h) h - -/-- The set of natural number powers of an element of a `Submonoid` is a subset of the -`Submonoid`. -/ -@[to_additive - "The set of natural number multiples of an element of an `AddSubmonoid` is a subset of - the `AddSubmonoid`."] -theorem IsSubmonoid.powers_subset {a : M} (hs : IsSubmonoid s) (h : a ∈ s) : powers a ⊆ s := - fun _ ⟨_, hx⟩ => hx ▸ hs.pow_mem h - -end powers - -namespace IsSubmonoid - -/-- The product of a list of elements of a submonoid is an element of the submonoid. -/ -@[to_additive - "The sum of a list of elements of an `AddSubmonoid` is an element of the `AddSubmonoid`."] -theorem list_prod_mem (hs : IsSubmonoid s) : ∀ {l : List M}, (∀ x ∈ l, x ∈ s) → l.prod ∈ s - | [], _ => hs.one_mem - | a :: l, h => - suffices a * l.prod ∈ s by simpa - have : a ∈ s ∧ ∀ x ∈ l, x ∈ s := by simpa using h - hs.mul_mem this.1 (list_prod_mem hs this.2) - -/-- The product of a multiset of elements of a submonoid of a `CommMonoid` is an element of -the submonoid. -/ -@[to_additive - "The sum of a multiset of elements of an `AddSubmonoid` of an `AddCommMonoid` - is an element of the `AddSubmonoid`. "] -theorem multiset_prod_mem {M} [CommMonoid M] {s : Set M} (hs : IsSubmonoid s) (m : Multiset M) : - (∀ a ∈ m, a ∈ s) → m.prod ∈ s := by - refine Quotient.inductionOn m fun l hl => ?_ - rw [Multiset.quot_mk_to_coe, Multiset.prod_coe] - exact list_prod_mem hs hl - -/-- The product of elements of a submonoid of a `CommMonoid` indexed by a `Finset` is an element -of the submonoid. -/ -@[to_additive - "The sum of elements of an `AddSubmonoid` of an `AddCommMonoid` indexed by - a `Finset` is an element of the `AddSubmonoid`."] -theorem finset_prod_mem {M A} [CommMonoid M] {s : Set M} (hs : IsSubmonoid s) (f : A → M) : - ∀ t : Finset A, (∀ b ∈ t, f b ∈ s) → (∏ b ∈ t, f b) ∈ s - | ⟨m, hm⟩, _ => multiset_prod_mem hs _ (by simpa) - -end IsSubmonoid - -namespace AddMonoid - -/-- The inductively defined membership predicate for the submonoid generated by a subset of a - monoid. -/ -inductive InClosure (s : Set A) : A → Prop - | basic {a : A} : a ∈ s → InClosure _ a - | zero : InClosure _ 0 - | add {a b : A} : InClosure _ a → InClosure _ b → InClosure _ (a + b) - -end AddMonoid - -namespace Monoid - -/-- The inductively defined membership predicate for the `Submonoid` generated by a subset of an - monoid. -/ -@[to_additive] -inductive InClosure (s : Set M) : M → Prop - | basic {a : M} : a ∈ s → InClosure _ a - | one : InClosure _ 1 - | mul {a b : M} : InClosure _ a → InClosure _ b → InClosure _ (a * b) - -/-- The inductively defined submonoid generated by a subset of a monoid. -/ -@[to_additive - "The inductively defined `AddSubmonoid` generated by a subset of an `AddMonoid`."] -def Closure (s : Set M) : Set M := - { a | InClosure s a } - -@[to_additive] -theorem closure.isSubmonoid (s : Set M) : IsSubmonoid (Closure s) := - { one_mem := InClosure.one - mul_mem := InClosure.mul } - -/-- A subset of a monoid is contained in the submonoid it generates. -/ -@[to_additive - "A subset of an `AddMonoid` is contained in the `AddSubmonoid` it generates."] -theorem subset_closure {s : Set M} : s ⊆ Closure s := fun _ => InClosure.basic - -/-- The submonoid generated by a set is contained in any submonoid that contains the set. -/ -@[to_additive - "The `AddSubmonoid` generated by a set is contained in any `AddSubmonoid` that - contains the set."] -theorem closure_subset {s t : Set M} (ht : IsSubmonoid t) (h : s ⊆ t) : Closure s ⊆ t := fun a ha => - by induction ha <;> simp [h _, *, IsSubmonoid.one_mem, IsSubmonoid.mul_mem] - -/-- Given subsets `t` and `s` of a monoid `M`, if `s ⊆ t`, the submonoid of `M` generated by `s` is - contained in the submonoid generated by `t`. -/ -@[to_additive (attr := gcongr) - "Given subsets `t` and `s` of an `AddMonoid M`, if `s ⊆ t`, the `AddSubmonoid` - of `M` generated by `s` is contained in the `AddSubmonoid` generated by `t`."] -theorem closure_mono {s t : Set M} (h : s ⊆ t) : Closure s ⊆ Closure t := - closure_subset (closure.isSubmonoid t) <| Set.Subset.trans h subset_closure - -/-- The submonoid generated by an element of a monoid equals the set of natural number powers of - the element. -/ -@[to_additive - "The `AddSubmonoid` generated by an element of an `AddMonoid` equals the set of - natural number multiples of the element."] -theorem closure_singleton {x : M} : Closure ({x} : Set M) = powers x := - Set.eq_of_subset_of_subset - (closure_subset (powers.isSubmonoid x) <| Set.singleton_subset_iff.2 <| powers.self_mem) <| - IsSubmonoid.powers_subset (closure.isSubmonoid _) <| - Set.singleton_subset_iff.1 <| subset_closure - -/-- The image under a monoid hom of the submonoid generated by a set equals the submonoid generated - by the image of the set under the monoid hom. -/ -@[to_additive - "The image under an `AddMonoid` hom of the `AddSubmonoid` generated by a set equals - the `AddSubmonoid` generated by the image of the set under the `AddMonoid` hom."] -theorem image_closure {A : Type*} [Monoid A] {f : M → A} (hf : IsMonoidHom f) (s : Set M) : - f '' Closure s = Closure (f '' s) := - le_antisymm - (by - rintro _ ⟨x, hx, rfl⟩ - induction' hx with z hz - · solve_by_elim [subset_closure, Set.mem_image_of_mem] - · rw [hf.map_one] - apply IsSubmonoid.one_mem (closure.isSubmonoid (f '' s)) - · rw [hf.map_mul] - solve_by_elim [(closure.isSubmonoid _).mul_mem] ) - (closure_subset (IsSubmonoid.image hf (closure.isSubmonoid _)) <| - Set.image_subset _ subset_closure) - -/-- Given an element `a` of the submonoid of a monoid `M` generated by a set `s`, there exists -a list of elements of `s` whose product is `a`. -/ -@[to_additive - "Given an element `a` of the `AddSubmonoid` of an `AddMonoid M` generated by - a set `s`, there exists a list of elements of `s` whose sum is `a`."] -theorem exists_list_of_mem_closure {s : Set M} {a : M} (h : a ∈ Closure s) : - ∃ l : List M, (∀ x ∈ l, x ∈ s) ∧ l.prod = a := by - induction h with - | @basic a ha => exists [a]; simp [ha] - | one => exists []; simp - | mul _ _ ha hb => - rcases ha with ⟨la, ha, eqa⟩ - rcases hb with ⟨lb, hb, eqb⟩ - exists la ++ lb - simp only [List.mem_append, or_imp, List.prod_append, eqa.symm, eqb.symm, and_true] - exact fun a => ⟨ha a, hb a⟩ - -/-- Given sets `s, t` of a commutative monoid `M`, `x ∈ M` is in the submonoid of `M` generated by - `s ∪ t` iff there exists an element of the submonoid generated by `s` and an element of the - submonoid generated by `t` whose product is `x`. -/ -@[to_additive - "Given sets `s, t` of a commutative `AddMonoid M`, `x ∈ M` is in the `AddSubmonoid` - of `M` generated by `s ∪ t` iff there exists an element of the `AddSubmonoid` generated by `s` - and an element of the `AddSubmonoid` generated by `t` whose sum is `x`."] -theorem mem_closure_union_iff {M : Type*} [CommMonoid M] {s t : Set M} {x : M} : - x ∈ Closure (s ∪ t) ↔ ∃ y ∈ Closure s, ∃ z ∈ Closure t, y * z = x := - ⟨fun hx => - let ⟨L, HL1, HL2⟩ := exists_list_of_mem_closure hx - HL2 ▸ - List.recOn L - (fun _ => - ⟨1, (closure.isSubmonoid _).one_mem, 1, (closure.isSubmonoid _).one_mem, mul_one _⟩) - (fun hd tl ih HL1 => - let ⟨y, hy, z, hz, hyzx⟩ := ih (List.forall_mem_of_forall_mem_cons HL1) - Or.casesOn (HL1 hd <| List.mem_cons_self _ _) - (fun hs => - ⟨hd * y, (closure.isSubmonoid _).mul_mem (subset_closure hs) hy, z, hz, by - rw [mul_assoc, List.prod_cons, ← hyzx]⟩) - fun ht => - ⟨y, hy, z * hd, (closure.isSubmonoid _).mul_mem hz (subset_closure ht), by - rw [← mul_assoc, List.prod_cons, ← hyzx, mul_comm hd]⟩) - HL1, - fun ⟨_, hy, _, hz, hyzx⟩ => - hyzx ▸ - (closure.isSubmonoid _).mul_mem (closure_mono Set.subset_union_left hy) - (closure_mono Set.subset_union_right hz)⟩ - -end Monoid - -/-- Create a bundled submonoid from a set `s` and `[IsSubmonoid s]`. -/ -@[to_additive "Create a bundled additive submonoid from a set `s` and `[IsAddSubmonoid s]`."] -def Submonoid.of {s : Set M} (h : IsSubmonoid s) : Submonoid M := - ⟨⟨s, @fun _ _ => h.2⟩, h.1⟩ - -@[to_additive] -theorem Submonoid.isSubmonoid (S : Submonoid M) : IsSubmonoid (S : Set M) := by - exact ⟨S.2, S.1.2⟩ diff --git a/Mathlib/Deprecated/Subring.lean b/Mathlib/Deprecated/Subring.lean deleted file mode 100644 index 05bea1fc07bb0..0000000000000 --- a/Mathlib/Deprecated/Subring.lean +++ /dev/null @@ -1,205 +0,0 @@ -/- -Copyright (c) 2018 Johan Commelin. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin --/ -import Mathlib.Algebra.Ring.Subring.Defs -import Mathlib.Deprecated.Group -import Mathlib.Deprecated.Subgroup - -/-! -# Unbundled subrings (deprecated) - -This file is deprecated, and is no longer imported by anything in mathlib other than other -deprecated files, and test files. You should not need to import it. - -This file defines predicates for unbundled subrings. Instead of using this file, please use -`Subring`, defined in `Mathlib.Algebra.Ring.Subring.Basic`, for subrings of rings. - -## Main definitions - -`IsSubring (S : Set R) : Prop` : the predicate that `S` is the underlying set of a subring -of the ring `R`. The bundled variant `Subring R` should be used in preference to this. - -## Tags - -IsSubring --/ - - -universe u v - -open Group - -variable {R : Type u} [Ring R] - -/-- `S` is a subring: a set containing 1 and closed under multiplication, addition and additive -inverse. -/ -structure IsSubring (S : Set R) extends IsAddSubgroup S, IsSubmonoid S : Prop - -/-- Construct a `Subring` from a set satisfying `IsSubring`. -/ -def IsSubring.subring {S : Set R} (hs : IsSubring S) : Subring R where - carrier := S - one_mem' := hs.one_mem - mul_mem' := hs.mul_mem - zero_mem' := hs.zero_mem - add_mem' := hs.add_mem - neg_mem' := hs.neg_mem - -namespace RingHom - -theorem isSubring_preimage {R : Type u} {S : Type v} [Ring R] [Ring S] (f : R →+* S) {s : Set S} - (hs : IsSubring s) : IsSubring (f ⁻¹' s) := - { IsAddGroupHom.preimage f.to_isAddGroupHom hs.toIsAddSubgroup, - IsSubmonoid.preimage f.to_isMonoidHom hs.toIsSubmonoid with } - -theorem isSubring_image {R : Type u} {S : Type v} [Ring R] [Ring S] (f : R →+* S) {s : Set R} - (hs : IsSubring s) : IsSubring (f '' s) := - { IsAddGroupHom.image_addSubgroup f.to_isAddGroupHom hs.toIsAddSubgroup, - IsSubmonoid.image f.to_isMonoidHom hs.toIsSubmonoid with } - -theorem isSubring_set_range {R : Type u} {S : Type v} [Ring R] [Ring S] (f : R →+* S) : - IsSubring (Set.range f) := - { IsAddGroupHom.range_addSubgroup f.to_isAddGroupHom, Range.isSubmonoid f.to_isMonoidHom with } - -end RingHom - -theorem IsSubring.inter {S₁ S₂ : Set R} (hS₁ : IsSubring S₁) (hS₂ : IsSubring S₂) : - IsSubring (S₁ ∩ S₂) := - { IsAddSubgroup.inter hS₁.toIsAddSubgroup hS₂.toIsAddSubgroup, - IsSubmonoid.inter hS₁.toIsSubmonoid hS₂.toIsSubmonoid with } - -theorem IsSubring.iInter {ι : Sort*} {S : ι → Set R} (h : ∀ y : ι, IsSubring (S y)) : - IsSubring (Set.iInter S) := - { IsAddSubgroup.iInter fun i ↦ (h i).toIsAddSubgroup, - IsSubmonoid.iInter fun i ↦ (h i).toIsSubmonoid with } - -theorem isSubring_iUnion_of_directed {ι : Type*} [Nonempty ι] {s : ι → Set R} - (h : ∀ i, IsSubring (s i)) (directed : ∀ i j, ∃ k, s i ⊆ s k ∧ s j ⊆ s k) : - IsSubring (⋃ i, s i) := - { toIsAddSubgroup := isAddSubgroup_iUnion_of_directed (fun i ↦ (h i).toIsAddSubgroup) directed - toIsSubmonoid := isSubmonoid_iUnion_of_directed (fun i ↦ (h i).toIsSubmonoid) directed } - -namespace Ring - -/-- The smallest subring containing a given subset of a ring, considered as a set. This function -is deprecated; use `Subring.closure`. -/ -def closure (s : Set R) := - AddGroup.closure (Monoid.Closure s) - -variable {s : Set R} - --- attribute [local reducible] closure -- Porting note: not available in Lean4 - -theorem exists_list_of_mem_closure {a : R} (h : a ∈ closure s) : - ∃ L : List (List R), (∀ l ∈ L, ∀ x ∈ l, x ∈ s ∨ x = (-1 : R)) ∧ (L.map List.prod).sum = a := - AddGroup.InClosure.recOn h - fun {x} hx ↦ match x, Monoid.exists_list_of_mem_closure hx with - | _, ⟨L, h1, rfl⟩ => - ⟨[L], List.forall_mem_singleton.2 fun r hr ↦ Or.inl (h1 r hr), List.sum_singleton⟩ - ⟨[], List.forall_mem_nil _, rfl⟩ - fun {b} _ ih ↦ match b, ih with - | _, ⟨L1, h1, rfl⟩ => - ⟨L1.map (List.cons (-1)), - fun L2 h2 ↦ match L2, List.mem_map.1 h2 with - | _, ⟨L3, h3, rfl⟩ => List.forall_mem_cons.2 ⟨Or.inr rfl, h1 L3 h3⟩, by - simp only [List.map_map, Function.comp_def, List.prod_cons, neg_one_mul] - refine List.recOn L1 neg_zero.symm fun hd tl ih ↦ ?_ - rw [List.map_cons, List.sum_cons, ih, List.map_cons, List.sum_cons, neg_add]⟩ - fun {r1 r2} _ _ ih1 ih2 ↦ match r1, r2, ih1, ih2 with - | _, _, ⟨L1, h1, rfl⟩, ⟨L2, h2, rfl⟩ => - ⟨L1 ++ L2, List.forall_mem_append.2 ⟨h1, h2⟩, by rw [List.map_append, List.sum_append]⟩ - -@[elab_as_elim] -protected theorem InClosure.recOn {C : R → Prop} {x : R} (hx : x ∈ closure s) (h1 : C 1) - (hneg1 : C (-1)) (hs : ∀ z ∈ s, ∀ n, C n → C (z * n)) (ha : ∀ {x y}, C x → C y → C (x + y)) : - C x := by - have h0 : C 0 := add_neg_cancel (1 : R) ▸ ha h1 hneg1 - rcases exists_list_of_mem_closure hx with ⟨L, HL, rfl⟩ - clear hx - induction' L with hd tl ih - · exact h0 - rw [List.forall_mem_cons] at HL - suffices C (List.prod hd) by - rw [List.map_cons, List.sum_cons] - exact ha this (ih HL.2) - replace HL := HL.1 - clear ih tl - -- Porting note: Expanded `rsuffices` - suffices ∃ L, (∀ x ∈ L, x ∈ s) ∧ (List.prod hd = List.prod L ∨ List.prod hd = -List.prod L) by - rcases this with ⟨L, HL', HP | HP⟩ <;> rw [HP] <;> clear HP HL - · induction' L with hd tl ih - · exact h1 - rw [List.forall_mem_cons] at HL' - rw [List.prod_cons] - exact hs _ HL'.1 _ (ih HL'.2) - · induction' L with hd tl ih - · exact hneg1 - rw [List.prod_cons, neg_mul_eq_mul_neg] - rw [List.forall_mem_cons] at HL' - exact hs _ HL'.1 _ (ih HL'.2) - induction' hd with hd tl ih - · exact ⟨[], List.forall_mem_nil _, Or.inl rfl⟩ - rw [List.forall_mem_cons] at HL - rcases ih HL.2 with ⟨L, HL', HP | HP⟩ <;> cases' HL.1 with hhd hhd - · exact - ⟨hd::L, List.forall_mem_cons.2 ⟨hhd, HL'⟩, - Or.inl <| by rw [List.prod_cons, List.prod_cons, HP]⟩ - · exact ⟨L, HL', Or.inr <| by rw [List.prod_cons, hhd, neg_one_mul, HP]⟩ - · exact - ⟨hd::L, List.forall_mem_cons.2 ⟨hhd, HL'⟩, - Or.inr <| by rw [List.prod_cons, List.prod_cons, HP, neg_mul_eq_mul_neg]⟩ - · exact ⟨L, HL', Or.inl <| by rw [List.prod_cons, hhd, HP, neg_one_mul, neg_neg]⟩ - -theorem closure.isSubring : IsSubring (closure s) := - { AddGroup.closure.isAddSubgroup _ with - one_mem := AddGroup.mem_closure <| IsSubmonoid.one_mem <| Monoid.closure.isSubmonoid _ - mul_mem := fun {a _} ha hb ↦ AddGroup.InClosure.recOn hb - (fun {c} hc ↦ AddGroup.InClosure.recOn ha - (fun hd ↦ AddGroup.subset_closure ((Monoid.closure.isSubmonoid _).mul_mem hd hc)) - ((zero_mul c).symm ▸ (AddGroup.closure.isAddSubgroup _).zero_mem) - (fun {d} _ hdc ↦ neg_mul_eq_neg_mul d c ▸ (AddGroup.closure.isAddSubgroup _).neg_mem hdc) - fun {d e} _ _ hdc hec ↦ - (add_mul d e c).symm ▸ (AddGroup.closure.isAddSubgroup _).add_mem hdc hec) - ((mul_zero a).symm ▸ (AddGroup.closure.isAddSubgroup _).zero_mem) - (fun {c} _ hac ↦ neg_mul_eq_mul_neg a c ▸ (AddGroup.closure.isAddSubgroup _).neg_mem hac) - fun {c d} _ _ hac had ↦ - (mul_add a c d).symm ▸ (AddGroup.closure.isAddSubgroup _).add_mem hac had } - -theorem mem_closure {a : R} : a ∈ s → a ∈ closure s := - AddGroup.mem_closure ∘ @Monoid.subset_closure _ _ _ _ - -theorem subset_closure : s ⊆ closure s := - fun _ ↦ mem_closure - -theorem closure_subset {t : Set R} (ht : IsSubring t) : s ⊆ t → closure s ⊆ t := - AddGroup.closure_subset ht.toIsAddSubgroup ∘ Monoid.closure_subset ht.toIsSubmonoid - -theorem closure_subset_iff {s t : Set R} (ht : IsSubring t) : closure s ⊆ t ↔ s ⊆ t := - (AddGroup.closure_subset_iff ht.toIsAddSubgroup).trans - ⟨Set.Subset.trans Monoid.subset_closure, Monoid.closure_subset ht.toIsSubmonoid⟩ - -@[gcongr] -theorem closure_mono {s t : Set R} (H : s ⊆ t) : closure s ⊆ closure t := - closure_subset closure.isSubring <| Set.Subset.trans H subset_closure - -theorem image_closure {S : Type*} [Ring S] (f : R →+* S) (s : Set R) : - f '' closure s = closure (f '' s) := by - refine le_antisymm ?_ (closure_subset (RingHom.isSubring_image _ closure.isSubring) <| - Set.image_subset _ subset_closure) - rintro _ ⟨x, hx, rfl⟩ - apply AddGroup.InClosure.recOn (motive := fun {x} _ ↦ f x ∈ closure (f '' s)) hx _ <;> intros - · rw [f.map_zero] - apply closure.isSubring.zero_mem - · rw [f.map_neg] - apply closure.isSubring.neg_mem - assumption - · rw [f.map_add] - apply closure.isSubring.add_mem - assumption' - · apply AddGroup.mem_closure - rw [← Monoid.image_closure f.to_isMonoidHom] - apply Set.mem_image_of_mem - assumption - -end Ring diff --git a/MathlibTest/Header.lean b/MathlibTest/Header.lean index dcfe5788d4f31..6553027d5e3fc 100644 --- a/MathlibTest/Header.lean +++ b/MathlibTest/Header.lean @@ -9,7 +9,7 @@ import Lake import Mathlib.Tactic.Linter.Header import /- -/ Mathlib.Tactic -- the `TextBased` linter does not flag this `broadImport` import Mathlib.Tactic.Have -import Mathlib.Deprecated.Subfield +import Mathlib.Deprecated.MinMax /-- warning: In the past, importing 'Lake' in mathlib has led to dramatic slow-downs of the linter (see e.g. https://github.com/leanprover-community/mathlib4/pull/13779). Please consider carefully if this import is useful and make sure to benchmark it. If this is fine, feel free to silence this linter. From 2f62308d384bc6e2e7b0fb9140a08d7029abc109 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Tue, 28 Jan 2025 11:07:43 +0000 Subject: [PATCH 600/681] chore(Data/Matroid/Rank/Cardinal): docstring typo (#21149) Fixes a wrong lemma reference in a docstring. --- Mathlib/Data/Matroid/Rank/Cardinal.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Data/Matroid/Rank/Cardinal.lean b/Mathlib/Data/Matroid/Rank/Cardinal.lean index 0d10845213b06..b08d04f620122 100644 --- a/Mathlib/Data/Matroid/Rank/Cardinal.lean +++ b/Mathlib/Data/Matroid/Rank/Cardinal.lean @@ -178,7 +178,7 @@ section Invariant /-- A class stating that cardinality-valued rank is well-defined (i.e. all bases are equicardinal) for a matroid `M` and its minors. -Notably, this holds for `Finitary` matroids; see `Matroid.invarCardinalRank_of_finitary`. -/ +Notably, this holds for `Finitary` matroids; see `Matroid.invariantCardinalRank_of_finitary`. -/ @[mk_iff] class InvariantCardinalRank (M : Matroid α) : Prop where forall_card_basis_diff : From b0565aecf6b227354e4f408228e3440ba94a7887 Mon Sep 17 00:00:00 2001 From: Salvatore Mercuri Date: Tue, 28 Jan 2025 11:39:12 +0000 Subject: [PATCH 601/681] feat: generalise `TopologicalGroup.isInducing_if_nhds_one` to `MonoidHomClass` (#21159) This allows direct application of `TopologicalAddGroup.isInducing_iff_nhds_zero` to `TopologicalRing` and ring homs. --- Mathlib/Topology/Algebra/Group/Basic.lean | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Mathlib/Topology/Algebra/Group/Basic.lean b/Mathlib/Topology/Algebra/Group/Basic.lean index 28b8320d761a6..649dc2de97a8b 100644 --- a/Mathlib/Topology/Algebra/Group/Basic.lean +++ b/Mathlib/Topology/Algebra/Group/Basic.lean @@ -813,10 +813,11 @@ theorem continuous_of_continuousAt_one₂ {H M : Type*} [CommMonoid M] [Topologi @[to_additive] lemma TopologicalGroup.isInducing_iff_nhds_one - {H : Type*} [Group H] [TopologicalSpace H] [TopologicalGroup H] {f : G →* H} : + {H : Type*} [Group H] [TopologicalSpace H] [TopologicalGroup H] {F : Type*} + [FunLike F G H] [MonoidHomClass F G H] {f : F} : Topology.IsInducing f ↔ 𝓝 (1 : G) = (𝓝 (1 : H)).comap f := by rw [Topology.isInducing_iff_nhds] - refine ⟨(f.map_one ▸ · 1), fun hf x ↦ ?_⟩ + refine ⟨(map_one f ▸ · 1), fun hf x ↦ ?_⟩ rw [← nhds_translation_mul_inv, ← nhds_translation_mul_inv (f x), Filter.comap_comap, hf, Filter.comap_comap] congr 1 From 2705ba700688c5d245baed71faab5c3bfc69ca18 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:17:49 +0000 Subject: [PATCH 602/681] chore: deprecate list_reverse_induction (#21166) --- Mathlib/Computability/DFA.lean | 13 ++++++------- Mathlib/Computability/MyhillNerode.lean | 6 +++--- Mathlib/Data/List/Indexes.lean | 13 +++---------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/Mathlib/Computability/DFA.lean b/Mathlib/Computability/DFA.lean index e55cb83d9c17c..dd5c1c6b0348b 100644 --- a/Mathlib/Computability/DFA.lean +++ b/Mathlib/Computability/DFA.lean @@ -6,7 +6,6 @@ Authors: Fox Thomson, Chris Wong import Mathlib.Computability.Language import Mathlib.Data.Countable.Small import Mathlib.Data.Fintype.Card -import Mathlib.Data.List.Indexes import Mathlib.Tactic.NormNum /-! @@ -185,9 +184,9 @@ theorem comap_id : M.comap id = M := rfl @[simp] theorem evalFrom_comap (f : α' → α) (s : σ) (x : List α') : (M.comap f).evalFrom s x = M.evalFrom s (x.map f) := by - induction x using List.list_reverse_induction with - | base => simp - | ind x a ih => simp [ih] + induction x using List.reverseRecOn with + | nil => simp + | append_singleton x a ih => simp [ih] @[simp] theorem eval_comap (f : α' → α) (x : List α') : (M.comap f).eval x = M.eval (x.map f) := by @@ -226,9 +225,9 @@ theorem symm_reindex (g : σ ≃ σ') : (reindex (α := α) g).symm = reindex g. @[simp] theorem evalFrom_reindex (g : σ ≃ σ') (s : σ') (x : List α) : (reindex g M).evalFrom s x = g (M.evalFrom (g.symm s) x) := by - induction x using List.list_reverse_induction with - | base => simp - | ind x a ih => simp [ih] + induction x using List.reverseRecOn with + | nil => simp + | append_singleton x a ih => simp [ih] @[simp] theorem eval_reindex (g : σ ≃ σ') (x : List α) : (reindex g M).eval x = g (M.eval x) := by diff --git a/Mathlib/Computability/MyhillNerode.lean b/Mathlib/Computability/MyhillNerode.lean index 0ab520eb65238..9a9fc6bd140ee 100644 --- a/Mathlib/Computability/MyhillNerode.lean +++ b/Mathlib/Computability/MyhillNerode.lean @@ -85,9 +85,9 @@ theorem accepts_toDFA : L.toDFA.accepts = L := by ext x rw [DFA.mem_accepts] suffices L.toDFA.eval x = L.leftQuotient x by simp [this] - induction x using List.list_reverse_induction with - | base => simp - | ind x a ih => simp [ih, leftQuotient_append] + induction x using List.reverseRecOn with + | nil => simp + | append_singleton x a ih => simp [ih, leftQuotient_append] theorem IsRegular.of_finite_range_leftQuotient (h : Set.Finite (Set.range L.leftQuotient)) : L.IsRegular := diff --git a/Mathlib/Data/List/Indexes.lean b/Mathlib/Data/List/Indexes.lean index e9680556a8109..6d8b49e231af6 100644 --- a/Mathlib/Data/List/Indexes.lean +++ b/Mathlib/Data/List/Indexes.lean @@ -23,17 +23,10 @@ variable {α : Type u} {β : Type v} section MapIdx +@[deprecated reverseRecOn (since := "2025-01-28")] theorem list_reverse_induction (p : List α → Prop) (base : p []) - (ind : ∀ (l : List α) (e : α), p l → p (l ++ [e])) : (∀ (l : List α), p l) := by - let q := fun l ↦ p (reverse l) - have pq : ∀ l, p (reverse l) → q l := by simp only [q, reverse_reverse]; intro; exact id - have qp : ∀ l, q (reverse l) → p l := by simp only [q, reverse_reverse]; intro; exact id - intro l - apply qp - generalize (reverse l) = l - induction' l with head tail ih - · apply pq; simp only [reverse_nil, base] - · apply pq; simp only [reverse_cons]; apply ind; apply qp; rw [reverse_reverse]; exact ih + (ind : ∀ (l : List α) (e : α), p l → p (l ++ [e])) : (∀ (l : List α), p l) := + fun l => l.reverseRecOn base ind @[deprecated (since := "2024-10-15")] alias mapIdxGo_length := mapIdx_go_length From d6bfd18b789f8d5da8ed4aff0897250ad2d8b0ea Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Tue, 28 Jan 2025 12:51:18 +0000 Subject: [PATCH 603/681] chore: cleanup simp priorities in Algebra/GCDMonoid (#21156) --- Mathlib/Algebra/GCDMonoid/Finset.lean | 6 ++---- Mathlib/Algebra/GCDMonoid/Multiset.lean | 10 ++-------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Mathlib/Algebra/GCDMonoid/Finset.lean b/Mathlib/Algebra/GCDMonoid/Finset.lean index 89d7b6ca4f3ef..245b1c3f9ec1b 100644 --- a/Mathlib/Algebra/GCDMonoid/Finset.lean +++ b/Mathlib/Algebra/GCDMonoid/Finset.lean @@ -76,8 +76,7 @@ theorem lcm_insert [DecidableEq β] {b : β} : theorem lcm_singleton {b : β} : ({b} : Finset β).lcm f = normalize (f b) := Multiset.lcm_singleton --- Porting note: Priority changed for `simpNF` -@[simp 1100] +@[local simp] -- This will later be provable by other `simp` lemmas. theorem normalize_lcm : normalize (s.lcm f) = s.lcm f := by simp [lcm_def] theorem lcm_union [DecidableEq β] : (s₁ ∪ s₂).lcm f = GCDMonoid.lcm (s₁.lcm f) (s₂.lcm f) := @@ -149,8 +148,7 @@ theorem gcd_insert [DecidableEq β] {b : β} : theorem gcd_singleton {b : β} : ({b} : Finset β).gcd f = normalize (f b) := Multiset.gcd_singleton --- Porting note: Priority changed for `simpNF` -@[simp 1100] +@[local simp] -- This will later be provable by other `simp` lemmas. theorem normalize_gcd : normalize (s.gcd f) = s.gcd f := by simp [gcd_def] theorem gcd_union [DecidableEq β] : (s₁ ∪ s₂).gcd f = GCDMonoid.gcd (s₁.gcd f) (s₂.gcd f) := diff --git a/Mathlib/Algebra/GCDMonoid/Multiset.lean b/Mathlib/Algebra/GCDMonoid/Multiset.lean index a50a163331755..cbe9338671d3a 100644 --- a/Mathlib/Algebra/GCDMonoid/Multiset.lean +++ b/Mathlib/Algebra/GCDMonoid/Multiset.lean @@ -63,11 +63,7 @@ theorem dvd_lcm {s : Multiset α} {a : α} (h : a ∈ s) : a ∣ s.lcm := theorem lcm_mono {s₁ s₂ : Multiset α} (h : s₁ ⊆ s₂) : s₁.lcm ∣ s₂.lcm := lcm_dvd.2 fun _ hb ↦ dvd_lcm (h hb) -/- Porting note: Following `Algebra.GCDMonoid.Basic`'s version of `normalize_gcd`, I'm giving -this lower priority to avoid linter complaints about simp-normal form -/ -/- Porting note: Mathport seems to be replacing `Multiset.induction_on s $` with -`(Multiset.induction_on s)`, when it should be `Multiset.induction_on s <|`. -/ -@[simp 1100] +@[simp] theorem normalize_lcm (s : Multiset α) : normalize s.lcm = s.lcm := Multiset.induction_on s (by simp) fun a s _ ↦ by simp @@ -139,9 +135,7 @@ theorem gcd_dvd {s : Multiset α} {a : α} (h : a ∈ s) : s.gcd ∣ a := theorem gcd_mono {s₁ s₂ : Multiset α} (h : s₁ ⊆ s₂) : s₂.gcd ∣ s₁.gcd := dvd_gcd.2 fun _ hb ↦ gcd_dvd (h hb) -/- Porting note: Following `Algebra.GCDMonoid.Basic`'s version of `normalize_gcd`, I'm giving -this lower priority to avoid linter complaints about simp-normal form -/ -@[simp 1100] +@[simp] theorem normalize_gcd (s : Multiset α) : normalize s.gcd = s.gcd := Multiset.induction_on s (by simp) fun a s _ ↦ by simp From 3228d1d68564e0aa9de5a446cf85d9b6bf51eb1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= Date: Tue, 28 Jan 2025 13:12:41 +0000 Subject: [PATCH 604/681] doc(docs/1000.yaml): add eight theorems (#21152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Beck's monadicity theorem * Basel problem * Banach open mapping theorem * Dini's theorem * Hilbert's basis theorem * Kleene's recursion theorem * Smn theorem * Well-ordering theorem Co-authored-by: Michael Rothgang Co-authored-by: Miyahara Kō <52843868+Komyyy@users.noreply.github.com> --- Mathlib/CategoryTheory/Monad/Monadicity.lean | 6 ++-- Mathlib/Computability/PartrecCode.lean | 8 ++++-- Mathlib/RingTheory/Polynomial/Basic.lean | 2 +- Mathlib/Topology/UniformSpace/Dini.lean | 20 ++++++------- docs/1000.yaml | 30 ++++++++++++++++++-- 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/Mathlib/CategoryTheory/Monad/Monadicity.lean b/Mathlib/CategoryTheory/Monad/Monadicity.lean index 591201fa31725..8947ae28924ea 100644 --- a/Mathlib/CategoryTheory/Monad/Monadicity.lean +++ b/Mathlib/CategoryTheory/Monad/Monadicity.lean @@ -337,8 +337,8 @@ instance [CreatesColimitOfIsSplitPair G] : ∀ (A : Algebra adj.toMonad), fun _ => CreatesColimitOfIsSplitPair.out _ _ /-- -Beck's monadicity theorem. If `G` has a left adjoint and creates coequalizers of `G`-split pairs, -then it is monadic. +**Beck's monadicity theorem**: if `G` has a left adjoint and creates coequalizers of `G`-split +pairs, then it is monadic. This is the converse of `createsGSplitCoequalizersOfMonadic`. -/ def monadicOfCreatesGSplitCoequalizers [CreatesColimitOfIsSplitPair G] : @@ -351,7 +351,7 @@ def monadicOfCreatesGSplitCoequalizers [CreatesColimitOfIsSplitPair G] : have : ReflectsColimitOfIsSplitPair G := ⟨by intros; infer_instance⟩ exact monadicOfHasPreservesReflectsGSplitCoequalizers adj -/-- An alternate version of Beck's monadicity theorem. If `G` reflects isomorphisms, preserves +/-- An alternate version of **Beck's monadicity theorem**: if `G` reflects isomorphisms, preserves coequalizers of `G`-split pairs and `C` has coequalizers of `G`-split pairs, then it is monadic. -/ def monadicOfHasPreservesGSplitCoequalizersOfReflectsIsomorphisms [G.ReflectsIsomorphisms] diff --git a/Mathlib/Computability/PartrecCode.lean b/Mathlib/Computability/PartrecCode.lean index 4a04dbd781f9d..fc3cd1f404901 100644 --- a/Mathlib/Computability/PartrecCode.lean +++ b/Mathlib/Computability/PartrecCode.lean @@ -32,6 +32,7 @@ of some code. * `Nat.Partrec.Code.exists_code`: Partial recursiveness is equivalent to being the eval of a code. * `Nat.Partrec.Code.evaln_prim`: `evaln` is primitive recursive. * `Nat.Partrec.Code.fixed_point`: Roger's fixed point theorem. +* `Nat.Partrec.Code.fixed_point₂`: Kleene's second recursion theorem. ## References @@ -979,9 +980,9 @@ theorem eval_part : Partrec₂ eval := (evaln_prim.to_comp.comp ((Computable.snd.pair (fst.comp fst)).pair (snd.comp fst))).to₂).of_eq fun a => by simp [eval_eq_rfindOpt] -/-- Roger's fixed-point theorem: Any total, computable `f` has a fixed point: That is, under the -interpretation given by `Nat.Partrec.Code.eval`, there is a code `c` such that `c` and `f c` have -the same evaluation. +/-- **Roger's fixed-point theorem**: any total, computable `f` has a fixed point. +That is, under the interpretation given by `Nat.Partrec.Code.eval`, there is a code `c` +such that `c` and `f c` have the same evaluation. -/ theorem fixed_point {f : Code → Code} (hf : Computable f) : ∃ c : Code, eval (f c) = eval c := let g (x y : ℕ) : Part ℕ := eval (ofNat Code x) x >>= fun b => eval (ofNat Code b) y @@ -1000,6 +1001,7 @@ theorem fixed_point {f : Code → Code} (hf : Computable f) : ∃ c : Code, eval show eval (f (curry cg (encode cF))) n = eval (curry cg (encode cF)) n by simp [F, g, eg', eF', Part.map_id']⟩ +/-- **Kleene's second recursion theorem** -/ theorem fixed_point₂ {f : Code → ℕ →. ℕ} (hf : Partrec₂ f) : ∃ c : Code, eval c = f c := let ⟨cf, ef⟩ := exists_code.1 hf (fixed_point (curry_prim.comp (_root_.Primrec.const cf) Primrec.encode).to_comp).imp fun c e => diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index 682fe26b642a9..27ce39be124cc 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -860,7 +860,7 @@ end MvPolynomial end Prime -/-- Hilbert basis theorem: a polynomial ring over a noetherian ring is a noetherian ring. -/ +/-- **Hilbert basis theorem**: a polynomial ring over a Noetherian ring is a Noetherian ring. -/ protected theorem Polynomial.isNoetherianRing [inst : IsNoetherianRing R] : IsNoetherianRing R[X] := isNoetherianRing_iff.2 ⟨fun I : Ideal R[X] => diff --git a/Mathlib/Topology/UniformSpace/Dini.lean b/Mathlib/Topology/UniformSpace/Dini.lean index aff1384ce1d4f..97b9a70caecb8 100644 --- a/Mathlib/Topology/UniformSpace/Dini.lean +++ b/Mathlib/Topology/UniformSpace/Dini.lean @@ -42,7 +42,7 @@ variable {F : ι → α → G} {f : α → G} namespace Monotone -/-- **Dini's theorem** If `F n` is a monotone increasing collection of continuous functions +/-- **Dini's theorem**: if `F n` is a monotone increasing collection of continuous functions converging pointwise to a continuous function `f`, then `F n` converges locally uniformly to `f`. -/ lemma tendstoLocallyUniformly_of_forall_tendsto (hF_cont : ∀ i, Continuous (F i)) (hF_mono : Monotone F) (hf : Continuous f) @@ -64,7 +64,7 @@ lemma tendstoLocallyUniformly_of_forall_tendsto simp only [abs_of_nonpos (sub_nonpos_of_le (F_le_f _ _)), neg_sub, sub_le_sub_iff_left] exact hF_mono hnm z -/-- **Dini's theorem** If `F n` is a monotone increasing collection of continuous functions on a +/-- **Dini's theorem**: if `F n` is a monotone increasing collection of continuous functions on a set `s` converging pointwise to a continuous function `f`, then `F n` converges locally uniformly to `f`. -/ lemma tendstoLocallyUniformlyOn_of_forall_tendsto {s : Set α} @@ -75,7 +75,7 @@ lemma tendstoLocallyUniformlyOn_of_forall_tendsto {s : Set α} exact tendstoLocallyUniformly_of_forall_tendsto (hF_cont · |>.restrict) (fun _ _ h x ↦ hF_mono _ x.2 h) hf.restrict (fun x ↦ h_tendsto x x.2) -/-- **Dini's theorem** If `F n` is a monotone increasing collection of continuous functions on a +/-- **Dini's theorem**: if `F n` is a monotone increasing collection of continuous functions on a compact space converging pointwise to a continuous function `f`, then `F n` converges uniformly to `f`. -/ lemma tendstoUniformly_of_forall_tendsto [CompactSpace α] (hF_cont : ∀ i, Continuous (F i)) @@ -84,7 +84,7 @@ lemma tendstoUniformly_of_forall_tendsto [CompactSpace α] (hF_cont : ∀ i, Con tendstoLocallyUniformly_iff_tendstoUniformly_of_compactSpace.mp <| tendstoLocallyUniformly_of_forall_tendsto hF_cont hF_mono hf h_tendsto -/-- **Dini's theorem** If `F n` is a monotone increasing collection of continuous functions on a +/-- **Dini's theorem**: if `F n` is a monotone increasing collection of continuous functions on a compact set `s` converging pointwise to a continuous function `f`, then `F n` converges uniformly to `f`. -/ lemma tendstoUniformlyOn_of_forall_tendsto {s : Set α} (hs : IsCompact s) @@ -98,7 +98,7 @@ end Monotone namespace Antitone -/-- **Dini's theorem** If `F n` is a monotone decreasing collection of continuous functions on a +/-- **Dini's theorem**: if `F n` is a monotone decreasing collection of continuous functions on a converging pointwise to a continuous function `f`, then `F n` converges locally uniformly to `f`. -/ lemma tendstoLocallyUniformly_of_forall_tendsto (hF_cont : ∀ i, Continuous (F i)) (hF_anti : Antitone F) (hf : Continuous f) @@ -106,7 +106,7 @@ lemma tendstoLocallyUniformly_of_forall_tendsto TendstoLocallyUniformly F f atTop := Monotone.tendstoLocallyUniformly_of_forall_tendsto (G := Gᵒᵈ) hF_cont hF_anti hf h_tendsto -/-- **Dini's theorem** If `F n` is a monotone decreasing collection of continuous functions on a +/-- **Dini's theorem**: if `F n` is a monotone decreasing collection of continuous functions on a set `s` converging pointwise to a continuous function `f`, then `F n` converges locally uniformly to `f`. -/ lemma tendstoLocallyUniformlyOn_of_forall_tendsto {s : Set α} @@ -115,7 +115,7 @@ lemma tendstoLocallyUniformlyOn_of_forall_tendsto {s : Set α} TendstoLocallyUniformlyOn F f atTop s := Monotone.tendstoLocallyUniformlyOn_of_forall_tendsto (G := Gᵒᵈ) hF_cont hF_anti hf h_tendsto -/-- **Dini's theorem** If `F n` is a monotone decreasing collection of continuous functions on a +/-- **Dini's theorem**: if `F n` is a monotone decreasing collection of continuous functions on a compact space converging pointwise to a continuous function `f`, then `F n` converges uniformly to `f`. -/ lemma tendstoUniformly_of_forall_tendsto [CompactSpace α] (hF_cont : ∀ i, Continuous (F i)) @@ -123,7 +123,7 @@ lemma tendstoUniformly_of_forall_tendsto [CompactSpace α] (hF_cont : ∀ i, Con TendstoUniformly F f atTop := Monotone.tendstoUniformly_of_forall_tendsto (G := Gᵒᵈ) hF_cont hF_anti hf h_tendsto -/-- **Dini's theorem** If `F n` is a monotone decreasing collection of continuous functions on a +/-- **Dini's theorem**: if `F n` is a monotone decreasing collection of continuous functions on a compact set `s` converging pointwise to a continuous `f`, then `F n` converges uniformly to `f`. -/ lemma tendstoUniformlyOn_of_forall_tendsto {s : Set α} (hs : IsCompact s) (hF_cont : ∀ i, ContinuousOn (F i) s) (hF_anti : ∀ x ∈ s, Antitone (F · x)) @@ -139,7 +139,7 @@ namespace ContinuousMap variable {F : ι → C(α, G)} {f : C(α, G)} -/-- **Dini's theorem** If `F n` is a monotone increasing collection of continuous functions +/-- **Dini's theorem**: if `F n` is a monotone increasing collection of continuous functions converging pointwise to a continuous function `f`, then `F n` converges to `f` in the compact-open topology. -/ lemma tendsto_of_monotone_of_pointwise (hF_mono : Monotone F) @@ -148,7 +148,7 @@ lemma tendsto_of_monotone_of_pointwise (hF_mono : Monotone F) tendsto_of_tendstoLocallyUniformly <| hF_mono.tendstoLocallyUniformly_of_forall_tendsto (F · |>.continuous) f.continuous h_tendsto -/-- **Dini's theorem** If `F n` is a monotone decreasing collection of continuous functions +/-- **Dini's theorem**: if `F n` is a monotone decreasing collection of continuous functions converging pointwise to a continuous function `f`, then `F n` converges to `f` in the compact-open topology. -/ lemma tendsto_of_antitone_of_pointwise (hF_anti : Antitone F) diff --git a/docs/1000.yaml b/docs/1000.yaml index fc2fe3e686f5e..3fcbd78a71c5f 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -554,6 +554,9 @@ Q594571: Q595466: title: Dini's theorem + decl: Monotone.tendstoLocallyUniformly_of_forall_tendsto + authors: Jireh Loreaux + date: 2024 Q599876: title: Cochran's theorem @@ -634,7 +637,9 @@ Q656198: Q656645: title: Hilbert's basis theorem - # search mathlib or zulip; mathlib is close to this! + decl: Polynomial.isNoetherianRing + authors: Kenny Lau + date: 2019 Q656772: title: Cayley–Hamilton theorem @@ -818,6 +823,9 @@ Q794269: Q810431: title: Basel problem + decl: hasSum_zeta_two + authors: David Loeffler + date: 2022 Q828284: title: Parallel axis theorem @@ -1025,8 +1033,9 @@ Q943246: Q944297: title: Open mapping theorem - # TODO: this entry points to Wikipedia's disambiguation page => wikipedia should be fixed - # Banach open mapping theorem/Banach-Schauder theorem in functional analysis is in mathlib (ContinuousLinearMap.isOpenMap) + decl: ContinuousLinearMap.isOpenMap + authors: Sébastien Gouëzel + date: 2019 Q948664: title: Kneser's addition theorem @@ -1564,6 +1573,9 @@ Q1455794: Q1457052: title: Well-ordering theorem + decl: exists_wellOrder + authors: Mario Carneiro, Chris Hughes, Violeta Hernández + date: 2017 Q1471282: title: Radon's theorem @@ -1729,6 +1741,12 @@ Q1765521: Q1766814: title: Smn theorem + decls: + - Nat.Partrec.Code.smn + - Nat.Partrec'.part_iff + authors: Mario Carneiro + date: 2018 + comment: "This theorem is trivial when using Mathlib's computability definition, but this definition is equivalent to the usual one, as shown in `Nat.Partrec'.part_iff`." Q1785610: title: Poncelet's closure theorem @@ -1781,6 +1799,9 @@ Q1930577: Q1933521: title: Kleene's recursion theorem + decl: Nat.Partrec.Code.fixed_point₂ + authors: Mario Carneiro + date: 2018 Q1938251: title: Hasse–Minkowski theorem @@ -2664,6 +2685,9 @@ Q4877965: Q4878586: title: Beck's monadicity theorem + decl: CategoryTheory.Monad.monadicOfCreatesGSplitCoequalizers + authors: Bhavik Mehta + date: 2020 Q4880958: title: Behnke–Stein theorem From 46e8915d7c7f614a7c27e8cb81496cb496045405 Mon Sep 17 00:00:00 2001 From: Salvatore Mercuri Date: Tue, 28 Jan 2025 14:00:41 +0000 Subject: [PATCH 605/681] feat: add `WithZero.units_val_eq_coe_unitsWithZeroEquiv` (#21160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Taking `Units.val` of a unit in `WithZero α` corresponds to coercing `unitsWithZeroEquiv` from `α` to `WithZero α` --- Mathlib/Algebra/GroupWithZero/WithZero.lean | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mathlib/Algebra/GroupWithZero/WithZero.lean b/Mathlib/Algebra/GroupWithZero/WithZero.lean index 43ea0028206c0..9ad955134228e 100644 --- a/Mathlib/Algebra/GroupWithZero/WithZero.lean +++ b/Mathlib/Algebra/GroupWithZero/WithZero.lean @@ -266,6 +266,10 @@ def unitsWithZeroEquiv : (WithZero α)ˣ ≃* α where right_inv _ := rfl map_mul' _ _ := coe_inj.mp <| by simp only [Units.val_mul, coe_unzero, coe_mul] +theorem coe_unitsWithZeroEquiv_eq_units_val (γ : (WithZero α)ˣ) : + ↑(unitsWithZeroEquiv γ) = γ.val := by + simp only [WithZero.unitsWithZeroEquiv, MulEquiv.coe_mk, Equiv.coe_fn_mk, WithZero.coe_unzero] + /-- Any group with zero is isomorphic to adjoining `0` to the units of itself. -/ def withZeroUnitsEquiv {G : Type*} [GroupWithZero G] [DecidablePred (fun a : G ↦ a = 0)] : From 7fb23e3f477961ed83cc90dc70339929f3d9544b Mon Sep 17 00:00:00 2001 From: Yakov Pechersky Date: Tue, 28 Jan 2025 15:49:59 +0000 Subject: [PATCH 606/681] chore(RingTheory/Valuation): `map_neg` etc over Monoid (#21151) makes it and friends like `map_add_of_distinct_val` work in ENat --- Mathlib/RingTheory/Valuation/Basic.lean | 72 +++++++++++++------------ 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index 2d1fe63a3a6d8..6a320028e373a 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -253,20 +253,6 @@ lemma map_apply (f : Γ₀ →*₀ Γ'₀) (hf : Monotone f) (v : Valuation R Γ def IsEquiv (v₁ : Valuation R Γ₀) (v₂ : Valuation R Γ'₀) : Prop := ∀ r s, v₁ r ≤ v₁ s ↔ v₂ r ≤ v₂ s -/-- An ordered monoid isomorphism `Γ₀ ≃ Γ'₀` induces an equivalence -`Valuation R Γ₀ ≃ Valuation R Γ'₀`. -/ -def congr (f : Γ₀ ≃*o Γ'₀) : Valuation R Γ₀ ≃ Valuation R Γ'₀ where - toFun := map f f.toOrderIso.monotone - invFun := map f.symm f.toOrderIso.symm.monotone - left_inv ν := by ext; simp - right_inv ν := by ext; simp - -end Monoid - -section Group - -variable [LinearOrderedCommGroupWithZero Γ₀] (v : Valuation R Γ₀) {x y : R} - @[simp] theorem map_neg (x : R) : v (-x) = v x := v.toMonoidWithZeroHom.toMonoidHom.map_neg x @@ -274,12 +260,6 @@ theorem map_neg (x : R) : v (-x) = v x := theorem map_sub_swap (x y : R) : v (x - y) = v (y - x) := v.toMonoidWithZeroHom.toMonoidHom.map_sub_swap x y -theorem map_inv {R : Type*} [DivisionRing R] (v : Valuation R Γ₀) : ∀ x, v x⁻¹ = (v x)⁻¹ := - map_inv₀ _ - -theorem map_div {R : Type*} [DivisionRing R] (v : Valuation R Γ₀) : ∀ x y, v (x / y) = v x / v y := - map_div₀ _ - theorem map_sub (x y : R) : v (x - y) ≤ max (v x) (v y) := calc v (x - y) = v (x + -y) := by rw [sub_eq_add_neg] @@ -290,6 +270,8 @@ theorem map_sub_le {x y g} (hx : v x ≤ g) (hy : v y ≤ g) : v (x - y) ≤ g : rw [sub_eq_add_neg] exact v.map_add_le hx (le_trans (le_of_eq (v.map_neg y)) hy) +variable {x y : R} + theorem map_add_of_distinct_val (h : v x ≠ v y) : v (x + y) = max (v x) (v y) := by suffices ¬v (x + y) < max (v x) (v y) from or_iff_not_imp_right.1 (le_iff_eq_or_lt.1 (v.map_add x y)) this @@ -339,6 +321,26 @@ theorem map_one_sub_of_lt (h : v x < 1) : v (1 - x) = 1 := by rw [sub_eq_add_neg 1 x] simpa only [v.map_one, v.map_neg] using v.map_add_eq_of_lt_left h +/-- An ordered monoid isomorphism `Γ₀ ≃ Γ'₀` induces an equivalence +`Valuation R Γ₀ ≃ Valuation R Γ'₀`. -/ +def congr (f : Γ₀ ≃*o Γ'₀) : Valuation R Γ₀ ≃ Valuation R Γ'₀ where + toFun := map f f.toOrderIso.monotone + invFun := map f.symm f.toOrderIso.symm.monotone + left_inv ν := by ext; simp + right_inv ν := by ext; simp + +end Monoid + +section Group + +variable [LinearOrderedCommGroupWithZero Γ₀] (v : Valuation R Γ₀) {x y : R} + +theorem map_inv {R : Type*} [DivisionRing R] (v : Valuation R Γ₀) : ∀ x, v x⁻¹ = (v x)⁻¹ := + map_inv₀ _ + +theorem map_div {R : Type*} [DivisionRing R] (v : Valuation R Γ₀) : ∀ x y, v (x / y) = v x / v y := + map_div₀ _ + theorem one_lt_val_iff (v : Valuation K Γ₀) {x : K} (h : x ≠ 0) : 1 < v x ↔ v x⁻¹ < 1 := by simp [inv_lt_one₀ (v.pos_iff.2 h)] @@ -782,20 +784,6 @@ lemma map_apply (f : Γ₀ →+ Γ'₀) (ht : f ⊤ = ⊤) (hf : Monotone f) (v def IsEquiv (v₁ : AddValuation R Γ₀) (v₂ : AddValuation R Γ'₀) : Prop := Valuation.IsEquiv v₁ v₂ -end Monoid - -section Group - -variable [LinearOrderedAddCommGroupWithTop Γ₀] [Ring R] (v : AddValuation R Γ₀) {x y : R} - -@[simp] -theorem map_inv (v : AddValuation K Γ₀) {x : K} : v x⁻¹ = - (v x) := - map_inv₀ (toValuation v) x - -@[simp] -theorem map_div (v : AddValuation K Γ₀) {x y : K} : v (x / y) = v x - v y := - map_div₀ (toValuation v) x y - @[simp] theorem map_neg (x : R) : v (-x) = v x := Valuation.map_neg v x @@ -809,6 +797,8 @@ theorem map_sub (x y : R) : min (v x) (v y) ≤ v (x - y) := theorem map_le_sub {x y : R} {g : Γ₀} (hx : g ≤ v x) (hy : g ≤ v y) : g ≤ v (x - y) := Valuation.map_sub_le v hx hy +variable {x y : R} + theorem map_add_of_distinct_val (h : v x ≠ v y) : v (x + y) = @Min.min Γ₀ _ (v x) (v y) := Valuation.map_add_of_distinct_val v h @@ -831,6 +821,20 @@ theorem map_sub_eq_of_lt_right {x y : R} (hx : v y < v x) : theorem map_eq_of_lt_sub (h : v x < v (y - x)) : v y = v x := Valuation.map_eq_of_sub_lt v h +end Monoid + +section Group + +variable [LinearOrderedAddCommGroupWithTop Γ₀] [Ring R] (v : AddValuation R Γ₀) {x y : R} + +@[simp] +theorem map_inv (v : AddValuation K Γ₀) {x : K} : v x⁻¹ = - (v x) := + map_inv₀ (toValuation v) x + +@[simp] +theorem map_div (v : AddValuation K Γ₀) {x y : K} : v (x / y) = v x - v y := + map_div₀ (toValuation v) x y + end Group end Basic From cefd4055db9d1ae4eb5c8213df52e2bd5dbb9902 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Tue, 28 Jan 2025 16:01:10 +0000 Subject: [PATCH 607/681] feat(Combinatorics/SimpleGraph/Matching): Interactions between `spanningCoe`, `IsAlternating` and `IsCycles` (#20800) Add basic results in preparation for Tutte's theorem. Co-authored-by: Pim Otte --- .../Combinatorics/SimpleGraph/Matching.lean | 50 ++++++++++++++----- Mathlib/Combinatorics/SimpleGraph/Path.lean | 16 ++++++ 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/Mathlib/Combinatorics/SimpleGraph/Matching.lean b/Mathlib/Combinatorics/SimpleGraph/Matching.lean index e98fe155b060b..9f069cf54b51b 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Matching.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Matching.lean @@ -243,7 +243,7 @@ lemma IsPerfectMatching.induce_connectedComponent_isMatching (h : M.IsPerfectMat simpa [h.2.verts_eq_univ] using h.1.induce_connectedComponent c @[simp] -lemma IsPerfectMatching.toSubgraph_spanningCoe_iff (h : M.spanningCoe ≤ G') : +lemma IsPerfectMatching.toSubgraph_iff (h : M.spanningCoe ≤ G') : (G'.toSubgraph M.spanningCoe h).IsPerfectMatching ↔ M.IsPerfectMatching := by simp only [isPerfectMatching_iff, toSubgraph_adj, spanningCoe_adj] @@ -339,9 +339,18 @@ lemma IsCycles.other_adj_of_adj (h : G.IsCycles) (hadj : G.Adj v w) : obtain ⟨w', hww'⟩ := (G.neighborSet v).exists_ne_of_one_lt_ncard (by omega) w exact ⟨w', ⟨hww'.2.symm, hww'.1⟩⟩ +lemma IsCycles.induce_supp (c : G.ConnectedComponent) (h : G.IsCycles) : + (G.induce c.supp).spanningCoe.IsCycles := by + intro v ⟨w, hw⟩ + rw [mem_neighborSet, c.adj_spanningCoe_induce_supp] at hw + rw [← h ⟨w, hw.2⟩] + congr + ext w' + simp only [mem_neighborSet, c.adj_spanningCoe_induce_supp, hw, true_and] + open scoped symmDiff -lemma Subgraph.IsPerfectMatching.symmDiff_spanningCoe_IsCycles +lemma Subgraph.IsPerfectMatching.symmDiff_isCycles {M : Subgraph G} {M' : Subgraph G'} (hM : M.IsPerfectMatching) (hM' : M'.IsPerfectMatching) : (M.spanningCoe ∆ M'.spanningCoe).IsCycles := by intro v @@ -368,10 +377,12 @@ for `SimpleGraph` rather than `SimpleGraph.Subgraph`. def IsAlternating (G G' : SimpleGraph V) := ∀ ⦃v w w': V⦄, w ≠ w' → G.Adj v w → G.Adj v w' → (G'.Adj v w ↔ ¬ G'.Adj v w') -lemma IsPerfectMatching.symmDiff_spanningCoe_of_isAlternating {M : Subgraph G} - (hM : M.IsPerfectMatching) (hG' : G'.IsAlternating M.spanningCoe) (hG'cyc : G'.IsCycles) : - (SimpleGraph.toSubgraph (M.spanningCoe ∆ G') - (by rfl)).IsPerfectMatching := by +lemma IsAlternating.mono {G'' : SimpleGraph V} (halt : G.IsAlternating G') (h : G'' ≤ G) : + G''.IsAlternating G' := fun _ _ _ hww' hvw hvw' ↦ halt hww' (h hvw) (h hvw') + +lemma IsPerfectMatching.symmDiff_of_isAlternating (hM : M.IsPerfectMatching) + (hG' : G'.IsAlternating M.spanningCoe) (hG'cyc : G'.IsCycles) : + (⊤ : Subgraph (M.spanningCoe ∆ G')).IsPerfectMatching := by rw [Subgraph.isPerfectMatching_iff] intro v simp only [toSubgraph_adj, symmDiff_def, sup_adj, sdiff_adj, Subgraph.spanningCoe_adj] @@ -380,20 +391,33 @@ lemma IsPerfectMatching.symmDiff_spanningCoe_of_isAlternating {M : Subgraph G} · obtain ⟨w', hw'⟩ := hG'cyc.other_adj_of_adj h have hmadj : M.Adj v w ↔ ¬M.Adj v w' := by simpa using hG' hw'.1 h hw'.2 use w' - simp only [hmadj.mp hw.1, hw'.2, not_true_eq_false, and_self, not_false_eq_true, or_true, - true_and] + simp only [Subgraph.top_adj, sup_adj, sdiff_adj, Subgraph.spanningCoe_adj, hmadj.mp hw.1, hw'.2, + not_true_eq_false, and_self, not_false_eq_true, or_true, true_and] rintro y (hl | hr) · aesop · obtain ⟨w'', hw''⟩ := hG'cyc.other_adj_of_adj hr.1 by_contra! hc - simp_all only [show M.Adj v y ↔ ¬M.Adj v w' from by simpa using hG' hc hr.1 hw'.2, - not_false_eq_true, ne_eq, iff_true, not_true_eq_false, and_false] + simp_all [show M.Adj v y ↔ ¬M.Adj v w' from by simpa using hG' hc hr.1 hw'.2] · use w - simp only [hw.1, h, not_false_eq_true, and_self, not_true_eq_false, or_false, true_and] + simp only [Subgraph.top_adj, sup_adj, sdiff_adj, Subgraph.spanningCoe_adj, hw.1, h, + not_false_eq_true, and_self, not_true_eq_false, or_false, true_and] rintro y (hl | hr) · exact hw.2 _ hl.1 · have ⟨w', hw'⟩ := hG'cyc.other_adj_of_adj hr.1 - simp_all only [show M.Adj v y ↔ ¬M.Adj v w' from by simpa using hG' hw'.1 hr.1 hw'.2, not_not, - ne_eq, and_false] + simp_all [show M.Adj v y ↔ ¬M.Adj v w' from by simpa using hG' hw'.1 hr.1 hw'.2] + +lemma IsPerfectMatching.isAlternating_symmDiff_left {M' : Subgraph G'} + (hM : M.IsPerfectMatching) (hM' : M'.IsPerfectMatching) : + (M.spanningCoe ∆ M'.spanningCoe).IsAlternating M.spanningCoe := by + intro v w w' hww' hvw hvw' + obtain ⟨v1, hm1, hv1⟩ := hM.1 (hM.2 v) + obtain ⟨v2, hm2, hv2⟩ := hM'.1 (hM'.2 v) + simp only [symmDiff_def] at * + aesop + +lemma IsPerfectMatching.isAlternating_symmDiff_right + {M' : Subgraph G'} (hM : M.IsPerfectMatching) (hM' : M'.IsPerfectMatching) : + (M.spanningCoe ∆ M'.spanningCoe).IsAlternating M'.spanningCoe := by + simpa [symmDiff_comm] using isAlternating_symmDiff_left hM' hM end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Path.lean b/Mathlib/Combinatorics/SimpleGraph/Path.lean index 3211d0a9774fe..d016e6d94ad99 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Path.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Path.lean @@ -1071,6 +1071,22 @@ theorem mem_supp_iff (C : G.ConnectedComponent) (v : V) : v ∈ C.supp ↔ G.connectedComponentMk v = C := Iff.rfl +lemma mem_supp_congr_adj {v w : V} (c : G.ConnectedComponent) (hadj : G.Adj v w) : + v ∈ c.supp ↔ w ∈ c.supp := by + simp only [ConnectedComponent.mem_supp_iff] at * + constructor <;> intro h <;> simp only [← h] <;> apply connectedComponentMk_eq_of_adj + · exact hadj.symm + · exact hadj + +lemma adj_spanningCoe_induce_supp {v w : V} (c : G.ConnectedComponent) : + (G.induce c.supp).spanningCoe.Adj v w ↔ v ∈ c.supp ∧ G.Adj v w := by + by_cases h : v ∈ c.supp + · refine ⟨by aesop, ?_⟩ + intro h' + have : w ∈ c.supp := by rwa [c.mem_supp_congr_adj h'.2] at h + aesop + · aesop + theorem connectedComponentMk_mem {v : V} : v ∈ G.connectedComponentMk v := rfl From 3d93b8de288966be8a00fd865583f1cfca86a1d8 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Tue, 28 Jan 2025 16:01:11 +0000 Subject: [PATCH 608/681] feat(*/Fin/*): add lemmas (#21175) Cherry-picked parts of #21112 that don't rely on a decision about inline `haveI : NeZero n := _` --- Mathlib/Data/Fin/Basic.lean | 6 ++++++ Mathlib/Order/Fin/Basic.lean | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 7dc978fddb102..6cfce6b1e1b72 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -565,9 +565,15 @@ theorem leftInverse_cast (eq : n = m) : LeftInverse (Fin.cast eq.symm) (Fin.cast theorem rightInverse_cast (eq : n = m) : RightInverse (Fin.cast eq.symm) (Fin.cast eq) := fun _ => rfl +@[simp] +theorem cast_inj (eq : n = m) {a b : Fin n} : a.cast eq = b.cast eq ↔ a = b := by + simp [← val_inj] + +@[simp] theorem cast_lt_cast (eq : n = m) {a b : Fin n} : a.cast eq < b.cast eq ↔ a < b := Iff.rfl +@[simp] theorem cast_le_cast (eq : n = m) {a b : Fin n} : a.cast eq ≤ b.cast eq ↔ a ≤ b := Iff.rfl diff --git a/Mathlib/Order/Fin/Basic.lean b/Mathlib/Order/Fin/Basic.lean index 174adbcde047a..b96bc794c18a1 100644 --- a/Mathlib/Order/Fin/Basic.lean +++ b/Mathlib/Order/Fin/Basic.lean @@ -71,7 +71,7 @@ instance instLattice : Lattice (Fin n) := inferInstance lemma top_eq_last (n : ℕ) : ⊤ = Fin.last n := rfl -lemma bot_eq_zero (n : ℕ) : ⊥ = (0 : Fin (n + 1)) := rfl +lemma bot_eq_zero (n : ℕ) [NeZero n] : ⊥ = (0 : Fin n) := rfl @[simp] theorem rev_bot [NeZero n] : rev (⊥ : Fin n) = ⊤ := rfl @[simp] theorem rev_top [NeZero n] : rev (⊤ : Fin n) = ⊥ := rev_rev _ @@ -79,6 +79,22 @@ lemma bot_eq_zero (n : ℕ) : ⊥ = (0 : Fin (n + 1)) := rfl theorem rev_zero_eq_top (n : ℕ) [NeZero n] : rev (0 : Fin n) = ⊤ := rfl theorem rev_last_eq_bot (n : ℕ) : rev (last n) = ⊥ := by rw [rev_last, bot_eq_zero] +@[simp] +theorem succ_top (n : ℕ) [NeZero n] : (⊤ : Fin n).succ = ⊤ := by + rw [← rev_zero_eq_top, ← rev_zero_eq_top, ← rev_castSucc, castSucc_zero'] + +@[simp] +theorem val_top (n : ℕ) [NeZero n] : ((⊤ : Fin n) : ℕ) = n - 1 := rfl + +@[simp] +theorem zero_eq_top {n : ℕ} [NeZero n] : (0 : Fin n) = ⊤ ↔ n = 1 := by + rw [← bot_eq_zero, subsingleton_iff_bot_eq_top, subsingleton_iff_le_one, LE.le.le_iff_eq] + exact pos_of_neZero n + +@[simp] +theorem top_eq_zero {n : ℕ} [NeZero n] : (⊤ : Fin n) = 0 ↔ n = 1 := + eq_comm.trans zero_eq_top + section ToFin variable {α : Type*} [Preorder α] {f : α → Fin (n + 1)} @@ -225,6 +241,8 @@ def succOrderEmb (n : ℕ) : Fin n ↪o Fin (n + 1) := .ofStrictMono succ strict @[simp, norm_cast] lemma coe_succOrderEmb : ⇑(succOrderEmb n) = Fin.succ := rfl +@[simp] lemma succOrderEmb_toEmbedding : (succOrderEmb n).toEmbedding = succEmb n := rfl + /-- `Fin.castLE` as an `OrderEmbedding`. `castLEEmb h i` embeds `i` into a larger `Fin` type. -/ From 22d2235f9cd82310504ac1570169282f1968ca39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Tue, 28 Jan 2025 16:40:42 +0000 Subject: [PATCH 609/681] feat(Probability): notation and lemmas for the composition of a measure and a kernel (Measure.bind) (#19639) From the TestingLowerBounds project. Co-authored-by: Lorenzo Luccioli Co-authored-by: Remy Degenne --- Mathlib.lean | 3 + Mathlib/MeasureTheory/Measure/Prod.lean | 14 +++ .../Kernel/Composition/CompNotation.lean | 56 +++++++++ .../Kernel/Composition/Lemmas.lean | 103 ++++++++++++++++ .../Kernel/Composition/MeasureComp.lean | 112 ++++++++++++++++++ .../Kernel/Composition/MeasureCompProd.lean | 22 ++++ Mathlib/Probability/Kernel/Proper.lean | 9 +- scripts/noshake.json | 2 + 8 files changed, 318 insertions(+), 3 deletions(-) create mode 100644 Mathlib/Probability/Kernel/Composition/CompNotation.lean create mode 100644 Mathlib/Probability/Kernel/Composition/Lemmas.lean create mode 100644 Mathlib/Probability/Kernel/Composition/MeasureComp.lean diff --git a/Mathlib.lean b/Mathlib.lean index 6a48a4ad40e51..38b9f5aa9552a 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4356,7 +4356,10 @@ import Mathlib.Probability.Independence.ZeroOne import Mathlib.Probability.Integration import Mathlib.Probability.Kernel.Basic import Mathlib.Probability.Kernel.Composition.Basic +import Mathlib.Probability.Kernel.Composition.CompNotation import Mathlib.Probability.Kernel.Composition.IntegralCompProd +import Mathlib.Probability.Kernel.Composition.Lemmas +import Mathlib.Probability.Kernel.Composition.MeasureComp import Mathlib.Probability.Kernel.Composition.MeasureCompProd import Mathlib.Probability.Kernel.Composition.ParallelComp import Mathlib.Probability.Kernel.CondDistrib diff --git a/Mathlib/MeasureTheory/Measure/Prod.lean b/Mathlib/MeasureTheory/Measure/Prod.lean index 6248de656ceb8..e20bbe27b66ac 100644 --- a/Mathlib/MeasureTheory/Measure/Prod.lean +++ b/Mathlib/MeasureTheory/Measure/Prod.lean @@ -851,6 +851,13 @@ instance fst.instIsProbabilityMeasure [IsProbabilityMeasure ρ] : IsProbabilityM rw [fst_univ] exact measure_univ +instance fst.instIsZeroOrProbabilityMeasure [IsZeroOrProbabilityMeasure ρ] : + IsZeroOrProbabilityMeasure ρ.fst := by + rcases eq_zero_or_isProbabilityMeasure ρ with h | h + · simp only [h, fst_zero] + infer_instance + · infer_instance + @[simp] lemma fst_prod [IsProbabilityMeasure ν] : (μ.prod ν).fst = μ := by ext1 s hs @@ -909,6 +916,13 @@ instance snd.instIsProbabilityMeasure [IsProbabilityMeasure ρ] : IsProbabilityM rw [snd_univ] exact measure_univ +instance snd.instIsZeroOrProbabilityMeasure [IsZeroOrProbabilityMeasure ρ] : + IsZeroOrProbabilityMeasure ρ.snd := by + rcases eq_zero_or_isProbabilityMeasure ρ with h | h + · simp only [h, snd_zero] + infer_instance + · infer_instance + @[simp] lemma snd_prod [IsProbabilityMeasure μ] : (μ.prod ν).snd = ν := by ext1 s hs diff --git a/Mathlib/Probability/Kernel/Composition/CompNotation.lean b/Mathlib/Probability/Kernel/Composition/CompNotation.lean new file mode 100644 index 0000000000000..a206f6de86282 --- /dev/null +++ b/Mathlib/Probability/Kernel/Composition/CompNotation.lean @@ -0,0 +1,56 @@ +/- +Copyright (c) 2025 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne, Lorenzo Luccioli +-/ +import Mathlib.Probability.Kernel.Basic + +/-! +# Notation for the compostition of a measure and a kernel + +This operation, for which we introduce the notation `∘ₘ`, takes `μ : Measure α` and +`κ : Kernel α β` and creates `κ ∘ₘ μ : Measure β`. The integral of a function against `κ ∘ₘ μ` is +`∫⁻ x, f x ∂(κ ∘ₘ μ) = ∫⁻ a, ∫⁻ b, f b ∂(κ a) ∂μ`. + +This file does not define composition but only introduces notation for +`MeasureTheory.Measure.bind μ κ`. + +## Notations + +* `κ ∘ₘ μ = MeasureTheory.Measure.bind μ κ`, for `κ` a kernel. +-/ + +/- This file is only for lemmas that are direct specializations of `Measure.bind` to kernels, +anything more involved shoud go elsewhere (for example the `MeasureComp` file). -/ +assert_not_exists ProbabilityTheory.Kernel.compProd + +open ProbabilityTheory + +namespace MeasureTheory.Measure + +variable {α β : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} + {μ : Measure α} {κ : Kernel α β} + +/-- Composition of a measure and a kernel. + +Notation for `MeasureTheory.Measure.bind` -/ +scoped[ProbabilityTheory] notation3 κ " ∘ₘ " μ:100 => MeasureTheory.Measure.bind μ κ + +@[simp] +lemma comp_apply_univ [IsMarkovKernel κ] : (κ ∘ₘ μ) Set.univ = μ Set.univ := by + simp [bind_apply .univ κ.measurable] + +lemma deterministic_comp_eq_map {f : α → β} (hf : Measurable f) : + Kernel.deterministic f hf ∘ₘ μ = μ.map f := + Measure.bind_dirac_eq_map μ hf + +@[simp] +lemma id_comp : Kernel.id ∘ₘ μ = μ := by rw [Kernel.id, deterministic_comp_eq_map, Measure.map_id] + +lemma swap_comp {μ : Measure (α × β)} : (Kernel.swap α β) ∘ₘ μ = μ.map Prod.swap := + deterministic_comp_eq_map measurable_swap + +@[simp] +lemma const_comp {ν : Measure β} : (Kernel.const α ν) ∘ₘ μ = μ Set.univ • ν := μ.bind_const + +end MeasureTheory.Measure diff --git a/Mathlib/Probability/Kernel/Composition/Lemmas.lean b/Mathlib/Probability/Kernel/Composition/Lemmas.lean new file mode 100644 index 0000000000000..f4afde5959480 --- /dev/null +++ b/Mathlib/Probability/Kernel/Composition/Lemmas.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2025 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne, Lorenzo Luccioli +-/ +import Mathlib.Probability.Kernel.Composition.MeasureComp +import Mathlib.Probability.Kernel.Composition.ParallelComp + +/-! +# Lemmas relating different ways to compose measures and kernels + +This file contains lemmas about the composition of measures and kernels that do not fit in any of +the other files in this directory, because they involve several types of compositions/products. + +## Main statements + +* `parallelComp_comp_parallelComp`: `(η ∥ₖ η') ∘ₖ (κ ∥ₖ κ') = (η ∘ₖ κ) ∥ₖ (η' ∘ₖ κ')` + +-/ + +open MeasureTheory ProbabilityTheory + +variable {α β γ δ : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} + {mγ : MeasurableSpace γ} {mδ : MeasurableSpace δ} + {μ : Measure α} {ν : Measure β} {κ : Kernel α β} + +namespace MeasureTheory.Measure + +lemma compProd_eq_parallelComp_comp_copy_comp [SFinite μ] [IsSFiniteKernel κ] : + μ ⊗ₘ κ = (Kernel.id ∥ₖ κ) ∘ₘ Kernel.copy α ∘ₘ μ := by + rw [compProd_eq_comp_prod, ← Kernel.parallelComp_comp_copy, Measure.comp_assoc] + +lemma prod_comp_right [SFinite ν] {κ : Kernel β γ} [IsSFiniteKernel κ] : + μ.prod (κ ∘ₘ ν) = (Kernel.id ∥ₖ κ) ∘ₘ (μ.prod ν) := by + ext s hs + rw [Measure.prod_apply hs, Measure.bind_apply hs (Kernel.measurable _)] + simp_rw [Measure.bind_apply (measurable_prod_mk_left hs) (Kernel.measurable _)] + rw [MeasureTheory.lintegral_prod] + swap; · exact (Kernel.measurable_coe _ hs).aemeasurable + congr with a + congr with b + rw [Kernel.parallelComp_apply, Kernel.id_apply, Measure.prod_apply hs, lintegral_dirac'] + exact measurable_measure_prod_mk_left hs + +lemma prod_comp_left [SFinite μ] [SFinite ν] {κ : Kernel α γ} [IsSFiniteKernel κ] : + (κ ∘ₘ μ).prod ν = (κ ∥ₖ Kernel.id) ∘ₘ (μ.prod ν) := by + have h1 : (κ ∘ₘ μ).prod ν = (ν.prod (κ ∘ₘ μ)).map Prod.swap := by rw [Measure.prod_swap] + have h2 : (κ ∥ₖ Kernel.id) ∘ₘ (μ.prod ν) = ((Kernel.id ∥ₖ κ) ∘ₘ (ν.prod μ)).map Prod.swap := by + calc (κ ∥ₖ Kernel.id) ∘ₘ (μ.prod ν) + _ = (κ ∥ₖ Kernel.id) ∘ₘ ((ν.prod μ).map Prod.swap) := by rw [Measure.prod_swap] + _ = (κ ∥ₖ Kernel.id) ∘ₘ ((Kernel.swap _ _) ∘ₘ (ν.prod μ)) := by + rw [Kernel.swap, Measure.deterministic_comp_eq_map] + _ = (Kernel.swap _ _) ∘ₘ ((Kernel.id ∥ₖ κ) ∘ₘ (ν.prod μ)) := by + rw [Measure.comp_assoc, Measure.comp_assoc, Kernel.swap_parallelComp] + _ = ((Kernel.id ∥ₖ κ) ∘ₘ (ν.prod μ)).map Prod.swap := by + rw [Kernel.swap, Measure.deterministic_comp_eq_map] + rw [← Measure.prod_comp_right, ← h1] at h2 + exact h2.symm + +end MeasureTheory.Measure + +namespace ProbabilityTheory.Kernel + +variable {α' β' γ' : Type*} {mα' : MeasurableSpace α'} {mβ' : MeasurableSpace β'} + {mγ' : MeasurableSpace γ'} + [IsSFiniteKernel κ] + +lemma parallelComp_id_left_comp_parallelComp + {η : Kernel α' γ} [IsSFiniteKernel η] {ξ : Kernel γ δ} [IsSFiniteKernel ξ] : + (Kernel.id ∥ₖ ξ) ∘ₖ (κ ∥ₖ η) = κ ∥ₖ (ξ ∘ₖ η) := by + ext a + rw [parallelComp_apply, comp_apply, comp_apply, parallelComp_apply, Measure.prod_comp_right] + +lemma parallelComp_id_right_comp_parallelComp {η : Kernel α' γ} [IsSFiniteKernel η] + {ξ : Kernel γ δ} [IsSFiniteKernel ξ] : + (ξ ∥ₖ Kernel.id) ∘ₖ (η ∥ₖ κ) = (ξ ∘ₖ η) ∥ₖ κ := by + ext a + rw [parallelComp_apply, comp_apply, comp_apply, parallelComp_apply, Measure.prod_comp_left] + +lemma parallelComp_comp_parallelComp {η : Kernel β γ} [IsSFiniteKernel η] + {κ' : Kernel α' β'} [IsSFiniteKernel κ'] {η' : Kernel β' γ'} [IsSFiniteKernel η'] : + (η ∥ₖ η') ∘ₖ (κ ∥ₖ κ') = (η ∘ₖ κ) ∥ₖ (η' ∘ₖ κ') := by + rw [← parallelComp_id_left_comp_parallelComp, ← parallelComp_id_right_comp_parallelComp, + ← comp_assoc, parallelComp_id_left_comp_parallelComp, comp_id] + +lemma parallelComp_comp_prod {η : Kernel β γ} [IsSFiniteKernel η] + {κ' : Kernel α β'} [IsSFiniteKernel κ'] {η' : Kernel β' γ'} [IsSFiniteKernel η'] : + (η ∥ₖ η') ∘ₖ (κ ×ₖ κ') = (η ∘ₖ κ) ×ₖ (η' ∘ₖ κ') := by + rw [← parallelComp_comp_copy, ← comp_assoc, parallelComp_comp_parallelComp, + ← parallelComp_comp_copy] + +lemma parallelComp_comm {η : Kernel γ δ} [IsSFiniteKernel η] : + (Kernel.id ∥ₖ κ) ∘ₖ (η ∥ₖ Kernel.id) = (η ∥ₖ Kernel.id) ∘ₖ (Kernel.id ∥ₖ κ) := by + rw [parallelComp_id_left_comp_parallelComp, parallelComp_id_right_comp_parallelComp, + comp_id, comp_id] + +end ProbabilityTheory.Kernel + +lemma MeasureTheory.Measure.parallelComp_comp_compProd [SFinite μ] + [IsSFiniteKernel κ] {η : Kernel β γ} [IsSFiniteKernel η] : + (Kernel.id ∥ₖ η) ∘ₘ (μ ⊗ₘ κ) = μ ⊗ₘ (η ∘ₖ κ) := by + rw [Measure.compProd_eq_comp_prod, Measure.compProd_eq_comp_prod, Measure.comp_assoc, + Kernel.parallelComp_comp_prod, Kernel.id_comp] diff --git a/Mathlib/Probability/Kernel/Composition/MeasureComp.lean b/Mathlib/Probability/Kernel/Composition/MeasureComp.lean new file mode 100644 index 0000000000000..80b35782496b3 --- /dev/null +++ b/Mathlib/Probability/Kernel/Composition/MeasureComp.lean @@ -0,0 +1,112 @@ +/- +Copyright (c) 2025 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne, Lorenzo Luccioli +-/ +import Mathlib.Probability.Kernel.Composition.CompNotation +import Mathlib.Probability.Kernel.Composition.MeasureCompProd + +/-! +# Lemmas about the composition of a measure and a kernel + +Basic lemmas about the composition `κ ∘ₘ μ` of a kernel `κ` and a measure `μ`. + +-/ + +open scoped ENNReal + +open ProbabilityTheory MeasureTheory + +namespace MeasureTheory.Measure + +variable {α β γ : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} {mγ : MeasurableSpace γ} + {μ ν : Measure α} {κ η : Kernel α β} + +lemma comp_assoc {η : Kernel β γ} : η ∘ₘ (κ ∘ₘ μ) = (η ∘ₖ κ) ∘ₘ μ := + Measure.bind_bind κ.measurable η.measurable + +@[simp] +lemma snd_compProd (μ : Measure α) [SFinite μ] (κ : Kernel α β) [IsSFiniteKernel κ] : + (μ ⊗ₘ κ).snd = κ ∘ₘ μ := by + ext s hs + rw [bind_apply hs κ.measurable, snd_apply hs, compProd_apply] + · rfl + · exact measurable_snd hs + +instance [SFinite μ] [IsSFiniteKernel κ] : SFinite (κ ∘ₘ μ) := by + rw [← snd_compProd]; infer_instance + +instance [IsFiniteMeasure μ] [IsFiniteKernel κ] : IsFiniteMeasure (κ ∘ₘ μ) := by + rw [← snd_compProd]; infer_instance + +instance [IsProbabilityMeasure μ] [IsMarkovKernel κ] : IsProbabilityMeasure (κ ∘ₘ μ) := by + rw [← snd_compProd]; infer_instance + +instance [IsZeroOrProbabilityMeasure μ] [IsZeroOrMarkovKernel κ] : + IsZeroOrProbabilityMeasure (κ ∘ₘ μ) := by + rw [← snd_compProd]; infer_instance + +lemma map_comp (μ : Measure α) (κ : Kernel α β) {f : β → γ} (hf : Measurable f) : + (κ ∘ₘ μ).map f = (κ.map f) ∘ₘ μ := by + ext s hs + rw [Measure.map_apply hf hs, Measure.bind_apply (hf hs) κ.measurable, + Measure.bind_apply hs (Kernel.measurable _)] + simp_rw [Kernel.map_apply' _ hf _ hs] + +section CompProd + +lemma compProd_eq_comp_prod (μ : Measure α) [SFinite μ] (κ : Kernel α β) [IsSFiniteKernel κ] : + μ ⊗ₘ κ = (Kernel.id ×ₖ κ) ∘ₘ μ := by + rw [compProd, Kernel.compProd_prodMkLeft_eq_comp] + rfl + +lemma compProd_id_eq_copy_comp [SFinite μ] : μ ⊗ₘ Kernel.id = Kernel.copy α ∘ₘ μ := by + rw [compProd_id, Kernel.copy, deterministic_comp_eq_map] + +end CompProd + +section AddSMul + +@[simp] +lemma comp_add [SFinite μ] [SFinite ν] [IsSFiniteKernel κ] : + κ ∘ₘ (μ + ν) = κ ∘ₘ μ + κ ∘ₘ ν := by + simp_rw [← snd_compProd, compProd_add_left] + simp + +lemma add_comp [SFinite μ] [IsSFiniteKernel κ] [IsSFiniteKernel η] : + (κ + η) ∘ₘ μ = κ ∘ₘ μ + η ∘ₘ μ := by + simp_rw [← snd_compProd, compProd_add_right] + simp + +/-- Same as `add_comp` except that it uses `⇑κ + ⇑η` instead of `⇑(κ + η)` in order to have +a simp-normal form on the left of the equality. -/ +@[simp] +lemma add_comp' [SFinite μ] [IsSFiniteKernel κ] [IsSFiniteKernel η] : + (⇑κ + ⇑η) ∘ₘ μ = κ ∘ₘ μ + η ∘ₘ μ := by rw [← Kernel.coe_add, add_comp] + +lemma comp_smul (a : ℝ≥0∞) : κ ∘ₘ (a • μ) = a • (κ ∘ₘ μ) := by + ext s hs + simp only [bind_apply hs κ.measurable, lintegral_smul_measure, smul_apply, smul_eq_mul] + +end AddSMul + +section AbsolutelyContinuous + +variable [SFinite μ] [SFinite ν] [IsSFiniteKernel κ] [IsSFiniteKernel η] + +lemma AbsolutelyContinuous.comp (hμν : μ ≪ ν) (hκη : ∀ᵐ a ∂μ, κ a ≪ η a) : + κ ∘ₘ μ ≪ η ∘ₘ ν := by + simp_rw [← snd_compProd, Measure.snd] + exact (hμν.compProd hκη).map measurable_snd + +lemma AbsolutelyContinuous.comp_right (hμν : μ ≪ ν) (κ : Kernel α γ) [IsSFiniteKernel κ] : + κ ∘ₘ μ ≪ κ ∘ₘ ν := + hμν.comp (ae_of_all μ fun _ _ a ↦ a) + +lemma AbsolutelyContinuous.comp_left (μ : Measure α) [SFinite μ] (hκη : ∀ᵐ a ∂μ, κ a ≪ η a) : + κ ∘ₘ μ ≪ η ∘ₘ μ := + μ.absolutelyContinuous_refl.comp hκη + +end AbsolutelyContinuous + +end MeasureTheory.Measure diff --git a/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean b/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean index 64933b8111dc2..d39c73a222f5c 100644 --- a/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean +++ b/Mathlib/Probability/Kernel/Composition/MeasureCompProd.lean @@ -81,6 +81,17 @@ lemma _root_.ProbabilityTheory.Kernel.compProd_apply_eq_compProd_sectR {γ : Typ simp_rw [Kernel.compProd_apply hs, compProd_apply hs, Kernel.sectR_apply] rfl +lemma compProd_id [SFinite μ] : μ ⊗ₘ Kernel.id = μ.map (fun x ↦ (x, x)) := by + ext s hs + rw [compProd_apply hs, map_apply (measurable_id.prod measurable_id) hs] + have h_meas a : MeasurableSet (Prod.mk a ⁻¹' s) := measurable_prod_mk_left hs + simp_rw [Kernel.id_apply, dirac_apply' _ (h_meas _)] + calc ∫⁻ a, (Prod.mk a ⁻¹' s).indicator 1 a ∂μ + _ = ∫⁻ a, ((fun x ↦ (x, x)) ⁻¹' s).indicator 1 a ∂μ := rfl + _ = μ ((fun x ↦ (x, x)) ⁻¹' s) := by + rw [lintegral_indicator_one] + exact (measurable_id.prod measurable_id) hs + lemma compProd_congr [IsSFiniteKernel κ] [IsSFiniteKernel η] (h : κ =ᵐ[μ] η) : μ ⊗ₘ κ = μ ⊗ₘ η := by by_cases hμ : SFinite μ @@ -207,6 +218,17 @@ instance [IsFiniteMeasure μ] [IsFiniteKernel κ] : IsFiniteMeasure (μ ⊗ₘ instance [IsProbabilityMeasure μ] [IsMarkovKernel κ] : IsProbabilityMeasure (μ ⊗ₘ κ) := by rw [compProd]; infer_instance +instance [IsZeroOrProbabilityMeasure μ] [IsZeroOrMarkovKernel κ] : + IsZeroOrProbabilityMeasure (μ ⊗ₘ κ) := by + rw [compProd] + rcases eq_zero_or_isProbabilityMeasure μ with rfl | h + · simp only [Kernel.const_zero, Kernel.compProd_zero_left, Kernel.zero_apply] + infer_instance + rcases eq_zero_or_isMarkovKernel κ with rfl | hκ + · simp only [Kernel.prodMkLeft_zero, Kernel.compProd_zero_right, Kernel.zero_apply] + infer_instance + · infer_instance + section AbsolutelyContinuous lemma AbsolutelyContinuous.compProd_left [SFinite ν] (hμν : μ ≪ ν) (κ : Kernel α β) : diff --git a/Mathlib/Probability/Kernel/Proper.lean b/Mathlib/Probability/Kernel/Proper.lean index b7cb185ae7528..724d6cff74ea3 100644 --- a/Mathlib/Probability/Kernel/Proper.lean +++ b/Mathlib/Probability/Kernel/Proper.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Yaël Dillies, Kalle Kytölä, Kin Yau James Wong. All rights Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Kalle Kytölä, Kin Yau James Wong -/ -import Mathlib.Probability.Kernel.Basic +import Mathlib.Probability.Kernel.Composition.CompNotation /-! # Proper kernels @@ -66,14 +66,17 @@ alias ⟨IsProper.restrict_eq_indicator_smul, IsProper.of_restrict_eq_indicator_ alias ⟨IsProper.inter_eq_indicator_mul, IsProper.of_inter_eq_indicator_mul⟩ := isProper_iff_inter_eq_indicator_mul -lemma IsProper.setLIntegral_eq_bind (hπ : IsProper π) (h𝓑𝓧 : 𝓑 ≤ 𝓧) {μ : Measure[𝓧] X} +lemma IsProper.setLIntegral_eq_comp (hπ : IsProper π) (h𝓑𝓧 : 𝓑 ≤ 𝓧) {μ : Measure[𝓧] X} (hA : MeasurableSet[𝓧] A) (hB : MeasurableSet[𝓑] B) : - ∫⁻ a in B, π a A ∂μ = μ.bind π (A ∩ B) := by + ∫⁻ a in B, π a A ∂μ = (π ∘ₘ μ) (A ∩ B) := by rw [Measure.bind_apply (by measurability) (π.measurable.mono h𝓑𝓧 le_rfl)] simp only [hπ.inter_eq_indicator_mul h𝓑𝓧 hA hB, ← indicator_mul_const, Pi.one_apply, one_mul] rw [← lintegral_indicator (h𝓑𝓧 _ hB)] rfl +@[deprecated (since := "2025-01-24")] +alias IsProper.setLIntegral_eq_bind := IsProper.setLIntegral_eq_comp + /-- Auxiliary lemma for `IsProper.lintegral_mul` and `IsProper.setLIntegral_eq_indicator_mul_lintegral`. -/ private lemma IsProper.lintegral_indicator_mul_indicator (hπ : IsProper π) (h𝓑𝓧 : 𝓑 ≤ 𝓧) diff --git a/scripts/noshake.json b/scripts/noshake.json index 5a6590b022253..1eaa58abc994d 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -340,6 +340,8 @@ "Mathlib.Probability.Notation": ["Mathlib.MeasureTheory.Decomposition.Lebesgue", "Mathlib.MeasureTheory.Function.ConditionalExpectation.Basic"], + "Mathlib.Probability.Kernel.Proper": + ["Mathlib.Probability.Kernel.Composition.CompNotation"], "Mathlib.Order.RelClasses": ["Batteries.WF"], "Mathlib.Order.Filter.ListTraverse": ["Mathlib.Control.Traversable.Instances"], From c0caeecc5b1c930d0f0f6bb481231f2158e0e959 Mon Sep 17 00:00:00 2001 From: grunweg Date: Tue, 28 Jan 2025 16:40:43 +0000 Subject: [PATCH 610/681] chore(1000.yaml): less ambiguous titles (#21177) Re-generate the theorem titles from upstream, using a slightly better algorithm. This fixes a TODO (also remarked by Michael Stoll), and makes editing the file easier since it is clearer which result is meant. This catches one declaration name which did not refer to the right theorem (it referred to a different version of Tonelli's theorem). While at it, remove one further outdated TODO, and mention the PNT+ repository in a comment. Co-authored-by: grunweg --- docs/1000.yaml | 104 ++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/docs/1000.yaml b/docs/1000.yaml index 3fcbd78a71c5f..ca2e502ee182b 100644 --- a/docs/1000.yaml +++ b/docs/1000.yaml @@ -9,10 +9,7 @@ # and by `make_site.py` in the leanprover-community.github.io repo. # # Current TODOs/unresolved questions: -# - add infrastructure for updating the information upstream when formalisations are added # - perhaps add a wikidata version of the stacks attribute, and generate this file automatically -# -# TODO: display a less ambiguous title for e.g. "Liouville's theorem" Q11518: title: Pythagorean theorem @@ -272,7 +269,7 @@ Q257387: comment: "mathlib4 pull request at https://github.com/leanprover-community/mathlib4/pull/20722" Q258374: - title: Carathéodory's theorem + title: Carathéodory's theorem (measure theory) decl: MeasureTheory.OuterMeasure.caratheodory comment: Hard to say what exactly is meant. @@ -280,7 +277,7 @@ Q260928: title: Jordan curve theorem Q266291: - title: Bloch's theorem + title: Bloch's theorem (complex variables) Q268031: title: Abel's binomial theorem @@ -383,6 +380,7 @@ Q384142: Q386292: title: Prime number theorem + comment: "Ongoing formalisation of various versions in https://github.com/AlexKontorovich/PrimeNumberTheoremAnd" # also in 100.yaml Q388525: @@ -464,8 +462,8 @@ Q504843: title: Mycielski's theorem Q505798: - title: Lagrange's theorem - # group theorem result; exist additive and multiplicative version + title: Lagrange's theorem (group theory) + # exist additive and multiplicative version decl: Subgroup.card_subgroup_dvd_card Q510197: @@ -526,7 +524,7 @@ Q574902: title: Tarski's indefinability theorem Q576478: - title: Liouville's theorem + title: Liouville's theorem (complex analysis) decl: Differentiable.apply_eq_apply_of_bounded Q578555: @@ -623,7 +621,7 @@ Q649977: title: Shirshov–Cohn theorem Q650738: - title: Folk theorem + title: Folk theorem (game theory) Q651593: title: Norton's theorem @@ -661,7 +659,7 @@ Q657903: title: Hilbert–Waring theorem Q660799: - title: Darboux's theorem + title: Darboux's theorem (analysis) # "all derivatives have the intermediate value property" # TODO should exist in mathlib, add decl! @@ -852,7 +850,7 @@ Q837506: comment: "will enter mathlib in 2024" Q837551: - title: Frobenius theorem + title: Frobenius theorem (differential topology) Q841893: title: Desargues's theorem @@ -919,7 +917,7 @@ Q859122: title: Cauchy–Hadamard theorem Q865665: - title: Birkhoff's theorem + title: Birkhoff's theorem (relativity) Q866116: title: Hahn–Banach theorem @@ -944,7 +942,7 @@ Q890875: title: Bohr–van Leeuwen theorem Q897769: - title: König's theorem + title: Kőnig's theorem (graph theory) Q899002: title: Pascal's theorem @@ -1032,13 +1030,13 @@ Q943246: decl: littleWedderburn Q944297: - title: Open mapping theorem + title: Open mapping theorem (functional analysis) decl: ContinuousLinearMap.isOpenMap authors: Sébastien Gouëzel date: 2019 Q948664: - title: Kneser's addition theorem + title: Kneser's addition theorem (combinatorics) authors: Mantas Bakšys, Yaël Dillies url: https://github.com/YaelDillies/LeanCamCombi/blob/master/LeanCamCombi/Kneser/Kneser.lean date: 2022 @@ -1059,11 +1057,11 @@ Q966837: title: Cramér–Wold theorem Q967972: - title: Open mapping theorem + title: Open mapping theorem (complex analysis) decl: AnalyticOnNhd.is_constant_or_isOpen Q973359: - title: Rado's theorem + title: Radó's theorem (harmonic functions) Q974405: title: Hille–Yosida theorem @@ -1170,7 +1168,7 @@ Q1057919: Q1058662: title: Darboux's theorem - # symplectic geometry result + # symplectic geometry Q1059151: title: FWL theorem @@ -1222,7 +1220,7 @@ Q1076274: title: Choquet–Bishop–de Leeuw theorem Q1077462: - title: König's theorem + title: König's theorem (set theory) Q1077741: title: Hairy ball theorem @@ -1277,7 +1275,7 @@ Q1135706: title: Harnack's theorem Q1136043: - title: Hurwitz's theorem + title: Hurwitz's theorem (complex analysis) Q1136262: title: Optical theorem @@ -1294,12 +1292,11 @@ Q1137206: authors: Moritz Doll Q1139041: - title: Cauchy's theorem - # for finite groups + title: Cauchy's theorem (group theory) decl: exists_prime_orderOf_dvd_card Q1139430: - title: Hurwitz's theorem + title: Hurwitz's theorem (normed division algebras) Q1139524: title: Rationality theorem @@ -1311,7 +1308,7 @@ Q1140200: title: PCP theorem Q1141747: - title: Carnot's theorem + title: Carnot's theorem (inradius, circumradius) Q1143540: title: Heckscher–Ohlin theorem @@ -1430,7 +1427,7 @@ Q1217677: authors: Yury G. Kudryashov (first) and Benjamin Davidson (second) Q1227061: - title: Khinchin's theorem + title: Khinchin's theorem on Diophantine approximations Q1227702: title: Dirichlet's unit theorem @@ -1484,7 +1481,7 @@ Q1317367: title: Japanese theorem for concyclic polygons Q1322892: - title: Dirac's theorems + title: Dirac's theorem on chordal graphs Q1330788: title: Weierstrass factorization theorem @@ -1509,7 +1506,7 @@ Q1357684: title: Riesz representation theorem Q1361031: - title: Frobenius theorem + title: Frobenius theorem (real division algebras) Q1361393: title: Luzin's theorem @@ -1658,7 +1655,7 @@ Q1621180: title: Orlicz–Pettis theorem Q1630588: - title: Hurwitz's theorem + title: Hurwitz's theorem (number theory) Q1631749: title: Lester's theorem @@ -1832,7 +1829,7 @@ Q2000090: title: Art gallery theorem Q2008549: - title: Hilbert's theorem + title: Hilbert's theorem (differential geometry) Q2013213: title: Reuschle's theorem @@ -2012,7 +2009,7 @@ Q2345282: title: Shannon's theorem Q2347139: - title: Carnot's theorem + title: Carnot's theorem (thermodynamics) Q2360531: title: Jordan–Schur theorem @@ -2049,7 +2046,7 @@ Q2449984X: title: Pivot theorem Q2471737: - title: Carathéodory's theorem + title: Carathéodory's theorem (convex hull) decl: convexHull_eq_union Q2473965: @@ -2075,7 +2072,7 @@ Q2518048: title: Kodaira vanishing theorem Q2524990: - title: Jackson's theorem + title: Jackson's theorem (queueing theory) Q2525646: title: Jordan–Hölder theorem @@ -2130,7 +2127,7 @@ Q2800071: title: Perfect graph theorem Q2862403: - title: Bombieri's theorem + title: Schneider–Lang theorem Q2893695: title: Unmixedness theorem @@ -2196,7 +2193,11 @@ Q3345678: title: Moore–Aronszajn theorem Q3424029: - title: Chasles's theorems + # TODO: refer to the individual entries instead + # The list in wikipedia has already been changed. This will will change automatically + # when the 1000+ theorem project synchronises its data with wikipedia and this file is + # synchronised with the 1000+ theorem's data. + title: Chasles's theorem (disambiguation) Q3443426: title: Bondy's theorem @@ -2244,10 +2245,10 @@ Q3527009: title: Baker's theorem Q3527011: - title: Beck's theorem + title: Beck's theorem (geometry) Q3527015: - title: Bernstein's theorem + title: Bernstein's theorem on monotone functions Q3527017: title: Beurling–Lax theorem @@ -2256,7 +2257,7 @@ Q3527019: title: Birch's theorem Q3527034: - title: Cauchy's theorem + title: Cauchy's theorem (geometry) Q3527040: title: Chomsky–Schützenberger representation theorem @@ -2494,7 +2495,7 @@ Q4378868: date: 2022 Q4378889: - title: Carathéodory's theorem + title: Carathéodory's theorem (conformal mapping) Q4408070: title: De Finetti's theorem @@ -2518,8 +2519,7 @@ Q4454973: title: Lindelöf's theorem Q4454976: - title: Liouville's theorem - # theorem in conformal mappings + title: Liouville's theorem (conformal mappings) Q4454989: title: Meusnier's theorem @@ -2606,7 +2606,7 @@ Q4734844: title: Alperin–Brauer–Gorenstein theorem Q4736422: - title: Denjoy theorem + title: Denjoy–Luzin theorem Q4746948: title: Amitsur–Levitzki theorem @@ -2702,7 +2702,7 @@ Q4891633: title: Berger–Kazdan comparison theorem Q4894565: - title: Bernstein's theorem + title: Bernstein's theorem (approximation theory) Q4914101: title: Bing's recognition theorem @@ -3010,7 +3010,7 @@ Q5494134: title: Fraňková–Helly selection theorem Q5498822: - title: Birkhoff's theorem + title: Birkhoff's ergodic theorem Q5499906: title: Shirshov–Witt theorem @@ -3081,10 +3081,10 @@ Q5609384: title: Grinberg's theorem Q5610188: - title: Gromov's compactness theorem + title: Gromov's compactness theorem (geometry) Q5610190: - title: Gromov's compactness theorem + title: Gromov's compactness theorem (topology) Q5610718: title: Grothendieck's connectedness theorem @@ -3198,8 +3198,7 @@ Q6402928: title: Lagrange reversion theorem Q6403282: - title: Lagrange's theorem - # number theory + title: Lagrange's theorem (number theory) Q6407842: title: Killing–Hopf theorem @@ -3677,8 +3676,7 @@ Q7818977: title: Tomita's theorem Q7820874: - title: Tonelli's theorem - decl: MeasureTheory.lintegral_prod + title: Tonelli's theorem (functional analysis) Q7824894: title: Topkis's theorem @@ -3742,7 +3740,7 @@ Q7966545: title: Walter theorem Q7978735: - title: Weber's theorem + title: Weber's theorem (Algebraic curves) Q7980241: title: Weinberg–Witten theorem @@ -3929,7 +3927,7 @@ Q18205730: title: Byers–Yang theorem Q18206032: - title: Cartan's theorem + title: Closed subgroup theorem Q18206266: title: Euclid–Euler theorem @@ -3970,7 +3968,7 @@ Q25304301: title: Bregman–Minc inequality Q25345219: - title: BBD decomposition theorem + title: Decomposition theorem of Beilinson, Bernstein and Deligne Q25378690: title: Ionescu-Tulcea theorem @@ -3982,7 +3980,7 @@ Q28194853: title: Lovelock's theorem Q28458131: - title: Glivenko's theorem + title: Glivenko's theorem (probability theory) Q31838822: title: Kirchberger's theorem From e710222cf34d8d79f5adfc82bcc6c0dd9104eaba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= Date: Tue, 28 Jan 2025 16:54:06 +0000 Subject: [PATCH 611/681] perf(Mathlib/Tactic/CC/*): faster `cc` by using `FastSubsingleton` (#20723) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cc` spends much times on synthesizing `Subsingleton` instances. This PR makes `cc` faster by using `FastSubsingleton` instead of `Subsingleton`. [Zulip thread](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/cc.20performance.20issue.20and.20mysterious.20Subsingleton) Co-authored-by: Patrick Massot Co-authored-by: Miyahara Kō <52843868+Komyyy@users.noreply.github.com> --- Mathlib/Lean/Meta/CongrTheorems.lean | 5 +++++ Mathlib/Tactic/CC/Addition.lean | 10 +++------- Mathlib/Tactic/CC/Datatypes.lean | 5 +++-- Mathlib/Tactic/CC/MkProof.lean | 1 - Mathlib/Tactic/CongrExclamation.lean | 5 ----- MathlibTest/cc.lean | 2 +- scripts/noshake.json | 4 +++- 7 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Mathlib/Lean/Meta/CongrTheorems.lean b/Mathlib/Lean/Meta/CongrTheorems.lean index a8dafe249c20f..fa7daf4c35b9d 100644 --- a/Mathlib/Lean/Meta/CongrTheorems.lean +++ b/Mathlib/Lean/Meta/CongrTheorems.lean @@ -105,6 +105,11 @@ class FastIsEmpty (α : Sort u) : Prop where protected theorem FastSubsingleton.elim {α : Sort u} [h : FastSubsingleton α] : (a b : α) → a = b := h.inst.allEq +protected theorem FastSubsingleton.helim {α β : Sort u} [FastSubsingleton α] + (h₂ : α = β) (a : α) (b : β) : HEq a b := by + have : Subsingleton α := FastSubsingleton.inst + exact Subsingleton.helim h₂ a b + instance (priority := 100) {α : Type u} [inst : FastIsEmpty α] : FastSubsingleton α where inst := have := inst.inst; inferInstance diff --git a/Mathlib/Tactic/CC/Addition.lean b/Mathlib/Tactic/CC/Addition.lean index 4ad4dc22d38f0..2fb9ddbc68213 100644 --- a/Mathlib/Tactic/CC/Addition.lean +++ b/Mathlib/Tactic/CC/Addition.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Miyahara Kō -/ import Mathlib.Data.Option.Defs -import Mathlib.Lean.Expr.Basic import Mathlib.Tactic.CC.MkProof /-! @@ -199,12 +198,11 @@ def pushSubsingletonEq (a b : Expr) : CCM Unit := do let B ← normalize (← inferType b) -- TODO(Leo): check if the following test is a performance bottleneck if ← pureIsDefEq A B then - -- TODO(Leo): to improve performance we can create the following proof lazily - let proof ← mkAppM ``Subsingleton.elim #[a, b] + let proof ← mkAppM ``FastSubsingleton.elim #[a, b] pushEq a b proof else let some AEqB ← getEqProof A B | failure - let proof ← mkAppM ``Subsingleton.helim #[AEqB, a, b] + let proof ← mkAppM ``FastSubsingleton.helim #[AEqB, a, b] pushHEq a b proof /-- Given the equivalent expressions `oldRoot` and `newRoot` the root of `oldRoot` is @@ -940,9 +938,7 @@ partial def applySimpleEqvs (e : Expr) : CCM Unit := do to the todo list or register `e` as the canonical form of itself. -/ partial def processSubsingletonElem (e : Expr) : CCM Unit := do let type ← inferType e - -- TODO: this is likely to become a bottleneck. See e.g. - -- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/convert.20is.20often.20slow/near/433830798 - let ss ← synthInstance? (← mkAppM ``Subsingleton #[type]) + let ss ← synthInstance? (← mkAppM ``FastSubsingleton #[type]) if ss.isNone then return -- type is not a subsingleton let type ← normalize type -- Make sure type has been internalized diff --git a/Mathlib/Tactic/CC/Datatypes.lean b/Mathlib/Tactic/CC/Datatypes.lean index 6dc3e10fd6aa5..11aac8d38934e 100644 --- a/Mathlib/Tactic/CC/Datatypes.lean +++ b/Mathlib/Tactic/CC/Datatypes.lean @@ -3,9 +3,9 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Miyahara Kō -/ -import Lean.Meta.Tactic.Rfl import Batteries.Data.RBMap.Basic import Mathlib.Lean.Meta.Basic +import Mathlib.Lean.Meta.CongrTheorems import Mathlib.Data.Ordering.Basic /-! @@ -428,7 +428,8 @@ Note that this only works for two-argument relations: `ModEq n` and `ModEq m` ar same. -/ abbrev SymmCongruences := Std.HashMap SymmCongruencesKey (List (Expr × Name)) -/-- Stores the root representatives of subsingletons. -/ +/-- Stores the root representatives of subsingletons, this uses `FastSingleton` instead of +`Subsingleton`. -/ abbrev SubsingletonReprs := RBExprMap Expr /-- Stores the root representatives of `.instImplicit` arguments. -/ diff --git a/Mathlib/Tactic/CC/MkProof.lean b/Mathlib/Tactic/CC/MkProof.lean index 5f17a75846cc5..25140ed57c1d8 100644 --- a/Mathlib/Tactic/CC/MkProof.lean +++ b/Mathlib/Tactic/CC/MkProof.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Miyahara Kō -/ import Batteries.Data.RBMap.Alter -import Mathlib.Logic.Basic import Mathlib.Tactic.CC.Datatypes import Mathlib.Tactic.CC.Lemmas import Mathlib.Tactic.Relation.Rfl diff --git a/Mathlib/Tactic/CongrExclamation.lean b/Mathlib/Tactic/CongrExclamation.lean index 3bdb8ef60024a..dfa8e21eef0fe 100644 --- a/Mathlib/Tactic/CongrExclamation.lean +++ b/Mathlib/Tactic/CongrExclamation.lean @@ -425,11 +425,6 @@ def Lean.MVarId.congrImplies?' (mvarId : MVarId) : MetaM (Option (List MVarId)) | throwError "unexpected number of goals" return [mvarId₁, mvarId₂] -protected theorem FastSubsingleton.helim {α β : Sort u} [FastSubsingleton α] - (h₂ : α = β) (a : α) (b : β) : HEq a b := by - have : Subsingleton α := FastSubsingleton.inst - exact Subsingleton.helim h₂ a b - /-- Try to apply `Subsingleton.helim` if the goal is a `HEq`. Tries synthesizing a `Subsingleton` instance for both the LHS and the RHS. diff --git a/MathlibTest/cc.lean b/MathlibTest/cc.lean index 7196296010426..1263e28bba6fa 100644 --- a/MathlibTest/cc.lean +++ b/MathlibTest/cc.lean @@ -250,7 +250,7 @@ axiom C : (a : A) → B a → Type axiom D : (a : A) → (ba : B a) → C a ba → Type axiom E : (a : A) → (ba : B a) → (cba : C a ba) → D a ba cba → Type axiom F : (a : A) → (ba : B a) → (cba : C a ba) → (dcba : D a ba cba) → E a ba cba dcba → Type -axiom C_ss : ∀ a ba, Subsingleton (C a ba) +axiom C_ss : ∀ a ba, Lean.Meta.FastSubsingleton (C a ba) axiom a1 : A axiom a2 : A axiom a3 : A diff --git a/scripts/noshake.json b/scripts/noshake.json index 1eaa58abc994d..2732e7a608dbe 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -303,8 +303,10 @@ "Mathlib.Tactic.CategoryTheory.BicategoryCoherence": ["Mathlib.CategoryTheory.Bicategory.Coherence", "Mathlib.Tactic.CategoryTheory.BicategoricalComp"], + "Mathlib.Tactic.CC.Datatypes": + ["Mathlib.Lean.Meta.CongrTheorems", "Mathlib.Lean.Meta.Datatypes"], "Mathlib.Tactic.CC.MkProof": - ["Mathlib.Logic.Basic", "Mathlib.Tactic.CC.Lemmas"], + ["Mathlib.Tactic.CC.Lemmas"], "Mathlib.Tactic.ByContra": ["Batteries.Tactic.Init"], "Mathlib.Tactic.Bound.Init": ["Aesop.Frontend.Command"], "Mathlib.Tactic.Bound.Attribute": From 1f4b3960f39a3a1c34ed99e178c78a94016da6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= Date: Tue, 28 Jan 2025 17:39:54 +0000 Subject: [PATCH 612/681] doc(Mathlib/Data/PFunctor/M): fix typo & style (#21150) --- Mathlib/Data/PFunctor/Univariate/M.lean | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Mathlib/Data/PFunctor/Univariate/M.lean b/Mathlib/Data/PFunctor/Univariate/M.lean index 70b6e183f4a7e..0d37382ac25ee 100644 --- a/Mathlib/Data/PFunctor/Univariate/M.lean +++ b/Mathlib/Data/PFunctor/Univariate/M.lean @@ -161,7 +161,7 @@ end Approx open Approx /-- Internal definition for `M`. It is needed to avoid name clashes -between `M.mk` and `M.cases_on` and the declarations generated for +between `M.mk` and `M.casesOn` and the declarations generated for the structure -/ structure MIntl where /-- An `n`-th level approximation, for each depth `n` -/ @@ -378,8 +378,7 @@ theorem casesOn_mk' {r : M F → Sort*} {a} (x : F.B a → M F) /-- `IsPath p x` tells us if `p` is a valid path through `x` -/ inductive IsPath : Path F → M F → Prop | nil (x : M F) : IsPath [] x - | - cons (xs : Path F) {a} (x : M F) (f : F.B a → M F) (i : F.B a) : + | cons (xs : Path F) {a} (x : M F) (f : F.B a → M F) (i : F.B a) : x = M.mk ⟨a, f⟩ → IsPath xs (f i) → IsPath (⟨a, i⟩ :: xs) x theorem isPath_cons {xs : Path F} {a a'} {f : F.B a → M F} {i : F.B a'} : From 2fc44e9c4aa0b14de7885879e499fb00c1b8e093 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:39:55 +0000 Subject: [PATCH 613/681] chore: prepare for lean version bump (#21184) --- Mathlib/Algebra/FreeMonoid/Basic.lean | 2 +- Mathlib/Algebra/Group/Pi/Lemmas.lean | 2 +- Mathlib/Algebra/Group/Prod.lean | 2 +- Mathlib/Algebra/LinearRecurrence.lean | 10 ++++---- .../Combinatorics/Enumerative/DyckWord.lean | 2 +- Mathlib/Computability/Primrec.lean | 2 +- Mathlib/Computability/RegularExpressions.lean | 2 +- Mathlib/Computability/Tape.lean | 2 +- Mathlib/Data/List/Basic.lean | 23 ++++++++++++------- Mathlib/Data/List/MinMax.lean | 2 +- Mathlib/Data/List/Monad.lean | 6 ++--- Mathlib/Data/List/Permutation.lean | 2 +- Mathlib/GroupTheory/Perm/Cycle/Type.lean | 4 ++-- .../LegendreSymbol/JacobiSymbol.lean | 4 ++-- .../HomogeneousLocalization.lean | 2 +- 15 files changed, 37 insertions(+), 30 deletions(-) diff --git a/Mathlib/Algebra/FreeMonoid/Basic.lean b/Mathlib/Algebra/FreeMonoid/Basic.lean index 7340041857cfc..596248f983117 100644 --- a/Mathlib/Algebra/FreeMonoid/Basic.lean +++ b/Mathlib/Algebra/FreeMonoid/Basic.lean @@ -372,7 +372,7 @@ theorem map_apply_map_symm_eq {x : FreeMonoid β} (e : α ≃ β) : instance uniqueUnits : Unique (FreeMonoid α)ˣ where uniq u := Units.ext <| toList.injective <| have : toList u.val ++ toList u.inv = [] := DFunLike.congr_arg toList u.val_inv - (List.append_eq_nil.mp this).1 + (List.append_eq_nil_iff.mp this).1 @[to_additive (attr := simp)] theorem map_surjective {f : α → β} : Function.Surjective (map f) ↔ Function.Surjective f := by diff --git a/Mathlib/Algebra/Group/Pi/Lemmas.lean b/Mathlib/Algebra/Group/Pi/Lemmas.lean index 697d42405d54c..b73a9e5ea8db5 100644 --- a/Mathlib/Algebra/Group/Pi/Lemmas.lean +++ b/Mathlib/Algebra/Group/Pi/Lemmas.lean @@ -338,7 +338,7 @@ theorem Pi.semiconjBy_iff {x y z : ∀ i, f i} : SemiconjBy x y z ↔ ∀ i, SemiconjBy (x i) (y i) (z i) := funext_iff @[to_additive] -theorem Commute.pi {x y : ∀ i, f i} (h : ∀ i, Commute (x i) (y i)) : Commute x y := .pi h +theorem Commute.pi {x y : ∀ i, f i} (h : ∀ i, Commute (x i) (y i)) : Commute x y := SemiconjBy.pi h @[to_additive] theorem Pi.commute_iff {x y : ∀ i, f i} : Commute x y ↔ ∀ i, Commute (x i) (y i) := semiconjBy_iff diff --git a/Mathlib/Algebra/Group/Prod.lean b/Mathlib/Algebra/Group/Prod.lean index aa462854b7086..f3a94d3d34aa6 100644 --- a/Mathlib/Algebra/Group/Prod.lean +++ b/Mathlib/Algebra/Group/Prod.lean @@ -260,7 +260,7 @@ theorem Prod.semiconjBy_iff {x y z : M × N} : @[to_additive AddCommute.prod] theorem Commute.prod {x y : M × N} (hm : Commute x.1 y.1) (hn : Commute x.2 y.2) : Commute x y := - .prod hm hn + SemiconjBy.prod hm hn @[to_additive] theorem Prod.commute_iff {x y : M × N} : diff --git a/Mathlib/Algebra/LinearRecurrence.lean b/Mathlib/Algebra/LinearRecurrence.lean index a07f5edb8399f..b9fe57a324105 100644 --- a/Mathlib/Algebra/LinearRecurrence.lean +++ b/Mathlib/Algebra/LinearRecurrence.lean @@ -92,11 +92,11 @@ theorem eq_mk_of_is_sol_of_eq_init {u : ℕ → α} {init : Fin E.order → α} rw [mkSol] split_ifs with h' · exact mod_cast heq ⟨n, h'⟩ - rw [← tsub_add_cancel_of_le (le_of_not_lt h'), h (n - E.order)] - congr with k - have : n - E.order + k < n := by omega - rw [eq_mk_of_is_sol_of_eq_init h heq (n - E.order + k)] - simp + · rw [← tsub_add_cancel_of_le (le_of_not_lt h'), h (n - E.order)] + congr with k + have : n - E.order + k < n := by omega + rw [eq_mk_of_is_sol_of_eq_init h heq (n - E.order + k)] + simp /-- If `u` is a solution to `E` and `init` designates its first `E.order` values, then `u = E.mkSol init`. This proves that `E.mkSol init` is the only solution diff --git a/Mathlib/Combinatorics/Enumerative/DyckWord.lean b/Mathlib/Combinatorics/Enumerative/DyckWord.lean index 5a8e966e55c59..a48532e748a04 100644 --- a/Mathlib/Combinatorics/Enumerative/DyckWord.lean +++ b/Mathlib/Combinatorics/Enumerative/DyckWord.lean @@ -97,7 +97,7 @@ lemma toList_ne_nil : p.toList ≠ [] ↔ p ≠ 0 := toList_eq_nil.ne instance : Unique (AddUnits DyckWord) where uniq p := by obtain ⟨a, b, h, -⟩ := p - obtain ⟨ha, hb⟩ := append_eq_nil.mp (toList_eq_nil.mpr h) + obtain ⟨ha, hb⟩ := append_eq_nil_iff.mp (toList_eq_nil.mpr h) congr · exact toList_eq_nil.mp ha · exact toList_eq_nil.mp hb diff --git a/Mathlib/Computability/Primrec.lean b/Mathlib/Computability/Primrec.lean index 20b710c3ba844..a4c9369593bb2 100644 --- a/Mathlib/Computability/Primrec.lean +++ b/Mathlib/Computability/Primrec.lean @@ -333,7 +333,7 @@ theorem const (x : σ) : Primrec₂ fun (_ : α) (_ : β) => x := Primrec.const _ protected theorem pair : Primrec₂ (@Prod.mk α β) := - .pair .fst .snd + Primrec.pair .fst .snd theorem left : Primrec₂ fun (a : α) (_ : β) => a := .fst diff --git a/Mathlib/Computability/RegularExpressions.lean b/Mathlib/Computability/RegularExpressions.lean index 4e10a5bf7e78c..8755552260ec8 100644 --- a/Mathlib/Computability/RegularExpressions.lean +++ b/Mathlib/Computability/RegularExpressions.lean @@ -231,7 +231,7 @@ theorem mul_rmatch_iff (P Q : RegularExpression α) (x : List α) : rw [rmatch, rmatch] rwa [Bool.and_eq_true_iff] at h · rintro ⟨t, u, h₁, h₂⟩ - cases' List.append_eq_nil.1 h₁.symm with ht hu + cases' List.append_eq_nil_iff.1 h₁.symm with ht hu subst ht subst hu repeat rw [rmatch] at h₂ diff --git a/Mathlib/Computability/Tape.lean b/Mathlib/Computability/Tape.lean index cf293a33770e0..920c5c776721a 100644 --- a/Mathlib/Computability/Tape.lean +++ b/Mathlib/Computability/Tape.lean @@ -377,7 +377,7 @@ theorem ListBlank.append_assoc {Γ} [Inhabited Γ] (l₁ l₂ : List Γ) (l₃ : element is sent to a sequence of default elements. -/ def ListBlank.flatMap {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ') (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by - apply l.liftOn (fun l ↦ ListBlank.mk (List.flatMap l f)) + apply l.liftOn (fun l ↦ ListBlank.mk (l.flatMap f)) rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine Quotient.sound' (Or.inl ⟨i * n, ?_⟩) rw [List.flatMap_append, mul_comm]; congr induction' i with i IH diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index d51295c269ce1..43a1475c35f4b 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -29,6 +29,10 @@ open Nat hiding one_pos namespace List +-- Renamed in lean core; to be removed with the version bump. +alias replicate_append_replicate := append_replicate_replicate +alias append_eq_nil_iff := append_eq_nil + universe u v w variable {ι : Type*} {α : Type u} {β : Type v} {γ : Type w} {l₁ l₂ : List α} @@ -208,7 +212,7 @@ theorem eq_replicate_length {a : α} : ∀ {l : List α}, l = replicate l.length | (b :: l) => by simp [eq_replicate_length, replicate_succ] theorem replicate_add (m n) (a : α) : replicate (m + n) a = replicate m a ++ replicate n a := by - rw [append_replicate_replicate] + rw [replicate_append_replicate] theorem replicate_subset_singleton (n) (a : α) : replicate n a ⊆ [a] := fun _ h => mem_singleton.2 (eq_of_mem_replicate h) @@ -670,19 +674,19 @@ variable [DecidableEq α] -- indexOf_cons_eq _ rfl @[simp] -theorem indexOf_cons_self (a : α) (l : List α) : indexOf a (a :: l) = 0 := by +theorem indexOf_cons_self {a : α} {l : List α} : indexOf a (a :: l) = 0 := by rw [indexOf, findIdx_cons, beq_self_eq_true, cond] -- fun e => if_pos e theorem indexOf_cons_eq {a b : α} (l : List α) : b = a → indexOf a (b :: l) = 0 - | e => by rw [← e]; exact indexOf_cons_self b l + | e => by rw [← e]; exact indexOf_cons_self -- fun n => if_neg n @[simp] theorem indexOf_cons_ne {a b : α} (l : List α) : b ≠ a → indexOf a (b :: l) = succ (indexOf a l) | h => by simp only [indexOf, findIdx_cons, Bool.cond_eq_ite, beq_iff_eq, h, ite_false] -theorem indexOf_eq_length {a : α} {l : List α} : indexOf a l = length l ↔ a ∉ l := by +theorem indexOf_eq_length_iff {a : α} {l : List α} : indexOf a l = length l ↔ a ∉ l := by induction' l with b l ih · exact iff_of_true rfl (not_mem_nil _) simp only [length, mem_cons, indexOf_cons, eq_comm] @@ -693,9 +697,12 @@ theorem indexOf_eq_length {a : α} {l : List α} : indexOf a l = length l ↔ a rw [← ih] exact succ_inj' +@[deprecated (since := "2025-01-28")] +alias indexOf_eq_length := indexOf_eq_length_iff + @[simp] theorem indexOf_of_not_mem {l : List α} {a : α} : a ∉ l → indexOf a l = length l := - indexOf_eq_length.2 + indexOf_eq_length_iff.2 theorem indexOf_le_length {a : α} {l : List α} : indexOf a l ≤ length l := by induction' l with b l ih; · rfl @@ -705,8 +712,8 @@ theorem indexOf_le_length {a : α} {l : List α} : indexOf a l ≤ length l := b · rw [if_neg h]; exact succ_le_succ ih theorem indexOf_lt_length_iff {a} {l : List α} : indexOf a l < length l ↔ a ∈ l := - ⟨fun h => Decidable.byContradiction fun al => Nat.ne_of_lt h <| indexOf_eq_length.2 al, - fun al => (lt_of_le_of_ne indexOf_le_length) fun h => indexOf_eq_length.1 h al⟩ + ⟨fun h => Decidable.byContradiction fun al => Nat.ne_of_lt h <| indexOf_eq_length_iff.2 al, + fun al => (lt_of_le_of_ne indexOf_le_length) fun h => indexOf_eq_length_iff.1 h al⟩ @[deprecated (since := "2025-01-22")] alias indexOf_lt_length := indexOf_lt_length_iff @@ -875,7 +882,7 @@ theorem flatMap_pure_eq_map (f : α → β) (l : List α) : l.flatMap (pure ∘ @[deprecated (since := "2024-10-16")] alias bind_pure_eq_map := flatMap_pure_eq_map theorem flatMap_congr {l : List α} {f g : α → List β} (h : ∀ x ∈ l, f x = g x) : - List.flatMap l f = List.flatMap l g := + l.flatMap f = l.flatMap g := (congr_arg List.flatten <| map_congr_left h :) @[deprecated (since := "2024-10-16")] alias bind_congr := flatMap_congr diff --git a/Mathlib/Data/List/MinMax.lean b/Mathlib/Data/List/MinMax.lean index 71564ef6cb848..241a87b598d88 100644 --- a/Mathlib/Data/List/MinMax.lean +++ b/Mathlib/Data/List/MinMax.lean @@ -38,7 +38,7 @@ def argAux (a : Option α) (b : α) : Option α := @[simp] theorem foldl_argAux_eq_none : l.foldl (argAux r) o = none ↔ l = [] ∧ o = none := List.reverseRecOn l (by simp) fun tl hd => by - simp only [foldl_append, foldl_cons, argAux, foldl_nil, append_eq_nil, and_false, false_and, + simp only [foldl_append, foldl_cons, argAux, foldl_nil, append_eq_nil_iff, and_false, false_and, iff_false] cases foldl (argAux r) o tl · simp diff --git a/Mathlib/Data/List/Monad.lean b/Mathlib/Data/List/Monad.lean index 3132c8376d922..0c420b1774ff6 100644 --- a/Mathlib/Data/List/Monad.lean +++ b/Mathlib/Data/List/Monad.lean @@ -16,9 +16,9 @@ namespace List variable {α : Type u} instance instMonad : Monad List.{u} where - pure := @List.singleton - bind := @List.flatMap - map := @List.map + pure x := [x] + bind l f := l.flatMap f + map f l := l.map f @[simp] theorem pure_def (a : α) : pure a = [a] := rfl diff --git a/Mathlib/Data/List/Permutation.lean b/Mathlib/Data/List/Permutation.lean index bdd3205fa2f21..d598a0ba42d67 100644 --- a/Mathlib/Data/List/Permutation.lean +++ b/Mathlib/Data/List/Permutation.lean @@ -326,7 +326,7 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) : map (cons c) ((permutations'Aux a l).flatMap (permutations'Aux b)) := by intros a' b' simp only [flatMap_map, permutations'Aux] - show List.flatMap (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++ + show (permutations'Aux _ l).flatMap (fun a => ([b' :: c :: a] ++ map (cons c) (permutations'Aux _ a))) ~ _ refine (flatMap_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans ?_ rw [← map_eq_flatMap, ← map_flatMap] diff --git a/Mathlib/GroupTheory/Perm/Cycle/Type.lean b/Mathlib/GroupTheory/Perm/Cycle/Type.lean index e9a7dd8bc94db..ebbd77c65b371 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Type.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Type.lean @@ -406,8 +406,8 @@ theorem zero_eq : vectorsProdEqOne G 0 = {Vector.nil} := Set.eq_singleton_iff_unique_mem.mpr ⟨Eq.refl (1 : G), fun v _ => v.eq_nil⟩ theorem one_eq : vectorsProdEqOne G 1 = {Vector.nil.cons 1} := by - simp_rw [Set.eq_singleton_iff_unique_mem, mem_iff, Vector.toList_singleton, List.prod_singleton, - Vector.head_cons, true_and] + simp_rw [Set.eq_singleton_iff_unique_mem, mem_iff, List.Vector.toList_singleton, + List.prod_singleton, List.Vector.head_cons, true_and] exact fun v hv => v.cons_head_tail.symm.trans (congr_arg₂ Vector.cons hv v.tail.eq_nil) instance zeroUnique : Unique (vectorsProdEqOne G 0) := by diff --git a/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean b/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean index f408526e3fb67..d609a2dcc3395 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean @@ -508,10 +508,10 @@ open NumberTheorySymbols jacobiSym private def fastJacobiSymAux (a b : ℕ) (flip : Bool) (ha0 : a > 0) : ℤ := if ha4 : a % 4 = 0 then fastJacobiSymAux (a / 4) b flip - (a.div_pos (Nat.le_of_dvd ha0 (Nat.dvd_of_mod_eq_zero ha4)) (by decide)) + (Nat.div_pos (Nat.le_of_dvd ha0 (Nat.dvd_of_mod_eq_zero ha4)) (by decide)) else if ha2 : a % 2 = 0 then fastJacobiSymAux (a / 2) b (xor (b % 8 = 3 ∨ b % 8 = 5) flip) - (a.div_pos (Nat.le_of_dvd ha0 (Nat.dvd_of_mod_eq_zero ha2)) (by decide)) + (Nat.div_pos (Nat.le_of_dvd ha0 (Nat.dvd_of_mod_eq_zero ha2)) (by decide)) else if ha1 : a = 1 then if flip then -1 else 1 else if hba : b % a = 0 then diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean index 5db79f945e9dd..bbf91f8c56ddb 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean @@ -714,7 +714,7 @@ def awayMapₐ : Away 𝒜 f →ₐ[𝒜 0] Away 𝒜 x where /-- This is a convenient constructor for `Away 𝒜 f` when `f` is homogeneous. `Away.mk 𝒜 hf n x hx` is the fraction `x / f ^ n`. -/ protected def Away.mk {d : ι} (hf : f ∈ 𝒜 d) (n : ℕ) (x : A) (hx : x ∈ 𝒜 (n • d)) : Away 𝒜 f := - .mk ⟨n • d, ⟨x, hx⟩, ⟨f ^ n, SetLike.pow_mem_graded n hf⟩, ⟨n, rfl⟩⟩ + HomogeneousLocalization.mk ⟨n • d, ⟨x, hx⟩, ⟨f ^ n, SetLike.pow_mem_graded n hf⟩, ⟨n, rfl⟩⟩ @[simp] lemma Away.val_mk {d : ι} (n : ℕ) (hf : f ∈ 𝒜 d) (x : A) (hx : x ∈ 𝒜 (n • d)) : From edd636fc612442a540d77efd4fdbc9308de8c222 Mon Sep 17 00:00:00 2001 From: Stefan Kebekus Date: Tue, 28 Jan 2025 19:06:41 +0000 Subject: [PATCH 614/681] feat: establish additivity of MeromorphicAt.order under multiplication of meromorphic functions (#21015) These theorems are used in [Project VD](https://github.com/kebekus/ProjectVD), which aims to formalize Value Distribution Theory for meromorphic functions on the complex plane. --- Mathlib/Analysis/Analytic/Meromorphic.lean | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Mathlib/Analysis/Analytic/Meromorphic.lean b/Mathlib/Analysis/Analytic/Meromorphic.lean index 86a7ea98ddcc0..ff69888be1dc2 100644 --- a/Mathlib/Analysis/Analytic/Meromorphic.lean +++ b/Mathlib/Analysis/Analytic/Meromorphic.lean @@ -278,6 +278,30 @@ lemma _root_.AnalyticAt.meromorphicAt_order {f : 𝕜 → E} {x : 𝕜} (hf : An rcases (hf.order_eq_nat_iff _).mp hn.symm with ⟨g, h1, h2, h3⟩ exact ⟨g, h1, h2, h3.filter_mono nhdsWithin_le_nhds⟩ +/-- The order is additive when multiplying scalar-valued and vector-valued meromorphic functions. -/ +theorem order_smul {f : 𝕜 → 𝕜} {g : 𝕜 → E} {x : 𝕜} + (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + (hf.smul hg).order = hf.order + hg.order := by + -- Trivial cases: one of the functions vanishes around z₀ + cases' h₂f : hf.order with m h₂f + · simp only [top_add, order_eq_top_iff] at h₂f ⊢ + filter_upwards [h₂f] with z hz using by simp [hz] + cases' h₂g : hg.order with n h₂f + · simp only [add_top, order_eq_top_iff] at h₂g ⊢ + filter_upwards [h₂g] with z hz using by simp [hz] + -- Non-trivial case: both functions do not vanish around z₀ + rw [← WithTop.coe_add, order_eq_int_iff] + obtain ⟨F, h₁F, h₂F, h₃F⟩ := (hf.order_eq_int_iff _).1 h₂f + obtain ⟨G, h₁G, h₂G, h₃G⟩ := (hg.order_eq_int_iff _).1 h₂g + use F • G, h₁F.smul h₁G, by simp [h₂F, h₂G] + filter_upwards [self_mem_nhdsWithin, h₃F, h₃G] with a ha hfa hga + simp [hfa, hga, smul_comm (F a), zpow_add₀ (sub_ne_zero.mpr ha), mul_smul] + +/-- The order is additive when multiplying meromorphic functions. -/ +theorem order_mul {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : + (hf.mul hg).order = hf.order + hg.order := + hf.order_smul hg + lemma iff_eventuallyEq_zpow_smul_analyticAt {f : 𝕜 → E} {x : 𝕜} : MeromorphicAt f x ↔ ∃ (n : ℤ) (g : 𝕜 → E), AnalyticAt 𝕜 g x ∧ ∀ᶠ z in 𝓝[≠] x, f z = (z - x) ^ n • g z := by refine ⟨fun ⟨n, hn⟩ ↦ ⟨-n, _, ⟨hn, eventually_nhdsWithin_iff.mpr ?_⟩⟩, ?_⟩ From 090d323e8ca9c45ee4cb6e4bcbd28dd58eeab426 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Tue, 28 Jan 2025 21:14:11 +0000 Subject: [PATCH 615/681] chore: review adaptation notes (#21176) --- .../Abelian/DiagramLemmas/Four.lean | 6 ------ .../Abelian/InjectiveResolution.lean | 1 - Mathlib/CategoryTheory/CofilteredSystem.lean | 16 ++++------------ .../Limits/Shapes/Pullback/Mono.lean | 8 -------- Mathlib/Control/Fold.lean | 16 +--------------- Mathlib/Data/DFinsupp/WellFounded.lean | 4 +--- Mathlib/Data/Rel.lean | 2 -- Mathlib/Data/Subtype.lean | 1 - Mathlib/Geometry/Euclidean/Inversion/Basic.lean | 1 - .../Geometry/Euclidean/Inversion/Calculus.lean | 4 +--- Mathlib/Logic/Function/Defs.lean | 1 - Mathlib/Probability/Process/HittingTime.lean | 1 - Mathlib/Topology/List.lean | 2 -- MathlibTest/MoveAdd.lean | 13 ++++++------- 14 files changed, 13 insertions(+), 63 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean index 5812a21f56858..b81f5bddd383a 100644 --- a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean +++ b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/Four.lean @@ -128,12 +128,6 @@ section Five variable {R₁ R₂ : ComposableArrows C 4} (hR₁ : R₁.Exact) (hR₂ : R₂.Exact) (φ : R₁ ⟶ R₂) include hR₁ hR₂ -#adaptation_note /-- nightly-2024-03-11 -We turn off simprocs here. -Ideally someone will investigate whether `simp` lemmas can be rearranged -so that this works without the `set_option`, -*or* come up with a proposal regarding finer control of disabling simprocs. -/ -set_option simprocs false in /-- The five lemma. -/ theorem isIso_of_epi_of_isIso_of_isIso_of_mono (h₀ : Epi (app' φ 0)) (h₁ : IsIso (app' φ 1)) (h₂ : IsIso (app' φ 3)) (h₃ : Mono (app' φ 4)) : IsIso (app' φ 2) := by diff --git a/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean b/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean index 9110373e9c67a..dac1bafa0aea2 100644 --- a/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean +++ b/Mathlib/CategoryTheory/Abelian/InjectiveResolution.lean @@ -298,7 +298,6 @@ lemma ofCocomplex_d_0_1 : (ofCocomplex Z).d 0 1 = d (Injective.ι Z) := by simp [ofCocomplex] -#adaptation_note /-- Since nightly-2024-03-11, this takes forever now -/ lemma ofCocomplex_exactAt_succ (n : ℕ) : (ofCocomplex Z).ExactAt (n + 1) := by rw [HomologicalComplex.exactAt_iff' _ n (n + 1) (n + 1 + 1) (by simp) (by simp)] diff --git a/Mathlib/CategoryTheory/CofilteredSystem.lean b/Mathlib/CategoryTheory/CofilteredSystem.lean index a3088857c8cf8..103f619ddd652 100644 --- a/Mathlib/CategoryTheory/CofilteredSystem.lean +++ b/Mathlib/CategoryTheory/CofilteredSystem.lean @@ -170,15 +170,11 @@ def toPreimages : J ⥤ Type v where rw [← mem_preimage, preimage_preimage, mem_preimage] convert h (g ≫ f); rw [F.map_comp]; rfl map_id j := by - #adaptation_note /-- nightly-2024-03-16: simp was - simp (config := { unfoldPartialApp := true }) only [MapsTo.restrict, Subtype.map, F.map_id] -/ - simp only [MapsTo.restrict, Subtype.map_def, F.map_id] + simp +unfoldPartialApp only [MapsTo.restrict, Subtype.map, F.map_id] ext rfl map_comp f g := by - #adaptation_note /-- nightly-2024-03-16: simp was - simp (config := { unfoldPartialApp := true }) only [MapsTo.restrict, Subtype.map, F.map_comp] -/ - simp only [MapsTo.restrict, Subtype.map_def, F.map_comp] + simp +unfoldPartialApp only [MapsTo.restrict, Subtype.map, F.map_comp] rfl instance toPreimages_finite [∀ j, Finite (F.obj j)] : ∀ j, Finite ((F.toPreimages s).obj j) := @@ -253,15 +249,11 @@ def toEventualRanges : J ⥤ Type v where obj j := F.eventualRange j map f := (F.eventualRange_mapsTo f).restrict _ _ _ map_id i := by - #adaptation_note /--- nightly-2024-03-16: simp was - simp (config := { unfoldPartialApp := true }) only [MapsTo.restrict, Subtype.map, F.map_id] -/ - simp only [MapsTo.restrict, Subtype.map_def, F.map_id] + simp +unfoldPartialApp only [MapsTo.restrict, Subtype.map, F.map_id] ext rfl map_comp _ _ := by - #adaptation_note /-- nightly-2024-03-16: simp was - simp (config := { unfoldPartialApp := true }) only [MapsTo.restrict, Subtype.map, F.map_comp] -/ - simp only [MapsTo.restrict, Subtype.map_def, F.map_comp] + simp +unfoldPartialApp only [MapsTo.restrict, Subtype.map, F.map_comp] rfl instance toEventualRanges_finite [∀ j, Finite (F.obj j)] : ∀ j, Finite (F.toEventualRanges.obj j) := diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean index 315be3a49b8d5..9574c46013341 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean @@ -160,11 +160,7 @@ instance hasPullback_of_right_factors_mono : HasPullback i (f ≫ i) := by instance pullback_snd_iso_of_right_factors_mono : IsIso (pullback.snd i (f ≫ i)) := by - #adaptation_note /-- nightly-testing 2024-04-01 - this could not be placed directly in the `show from` without `dsimp` -/ have := limit.isoLimitCone_hom_π ⟨_, pullbackIsPullbackOfCompMono (𝟙 _) f i⟩ WalkingCospan.right - dsimp only [cospan_right, id_eq, eq_mpr_eq_cast, PullbackCone.mk_pt, PullbackCone.mk_π_app, - Functor.const_obj_obj, cospan_one] at this convert (congrArg IsIso (show _ ≫ pullback.snd (𝟙 Z) f = _ from this)).mp inferInstance · exact (Category.id_comp _).symm · exact (Category.id_comp _).symm @@ -176,11 +172,7 @@ instance hasPullback_of_left_factors_mono : HasPullback (f ≫ i) i := by instance pullback_snd_iso_of_left_factors_mono : IsIso (pullback.fst (f ≫ i) i) := by - #adaptation_note /-- nightly-testing 2024-04-01 - this could not be placed directly in the `show from` without `dsimp` -/ have := limit.isoLimitCone_hom_π ⟨_, pullbackIsPullbackOfCompMono f (𝟙 _) i⟩ WalkingCospan.left - dsimp only [cospan_left, id_eq, eq_mpr_eq_cast, PullbackCone.mk_pt, PullbackCone.mk_π_app, - Functor.const_obj_obj, cospan_one] at this convert (congrArg IsIso (show _ ≫ pullback.fst f (𝟙 Z) = _ from this)).mp inferInstance · exact (Category.id_comp _).symm · exact (Category.id_comp _).symm diff --git a/Mathlib/Control/Fold.lean b/Mathlib/Control/Fold.lean index 62e4e80dddadb..fd6adaeacbf13 100644 --- a/Mathlib/Control/Fold.lean +++ b/Mathlib/Control/Fold.lean @@ -118,10 +118,7 @@ def Foldl.ofFreeMonoid (f : β → α → β) : FreeMonoid α →* Monoid.Foldl map_one' := rfl map_mul' := by intros - #adaptation_note /-- nightly-2024-03-16: simp was - simp only [FreeMonoid.toList_mul, flip, unop_op, List.foldl_append, op_inj] -/ - simp only [FreeMonoid.toList_mul, unop_op, List.foldl_append, op_inj, Function.flip_def, - List.foldl_append] + simp only [FreeMonoid.toList_mul, unop_op, List.foldl_append, op_inj, Function.flip_def] rfl abbrev Foldr (α : Type u) : Type u := @@ -280,9 +277,6 @@ theorem foldr.ofFreeMonoid_comp_of (f : β → α → α) : theorem foldlm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : α → β → m α) : foldlM.ofFreeMonoid f ∘ FreeMonoid.of = foldlM.mk ∘ flip f := by ext1 x - #adaptation_note /-- nightly-2024-03-16: simp was - simp only [foldlM.ofFreeMonoid, flip, MonoidHom.coe_mk, OneHom.coe_mk, Function.comp_apply, - FreeMonoid.toList_of, List.foldlM_cons, List.foldlM_nil, bind_pure, foldlM.mk, op_inj] -/ simp only [foldlM.ofFreeMonoid, Function.flip_def, MonoidHom.coe_mk, OneHom.coe_mk, Function.comp_apply, FreeMonoid.toList_of, List.foldlM_cons, List.foldlM_nil, bind_pure, foldlM.mk, op_inj] @@ -292,8 +286,6 @@ theorem foldlm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : α → β theorem foldrm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : β → α → m α) : foldrM.ofFreeMonoid f ∘ FreeMonoid.of = foldrM.mk ∘ f := by ext - #adaptation_note /-- nightly-2024-03-16: simp was - simp [(· ∘ ·), foldrM.ofFreeMonoid, foldrM.mk, flip] -/ simp [(· ∘ ·), foldrM.ofFreeMonoid, foldrM.mk, Function.flip_def] theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMonoid.of xs) := @@ -306,8 +298,6 @@ theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMon simp only [FreeMonoid.reverse_reverse, List.foldr_reverse, List.foldl_flip_cons_eq_append, List.append_nil, List.reverse_reverse] _ = (unop (Foldl.ofFreeMonoid (flip cons) (foldMap FreeMonoid.of xs)) []).reverse := by - #adaptation_note /-- nightly-2024-03-16: simp was - simp [flip, List.foldr_reverse, Foldl.ofFreeMonoid, unop_op] -/ simp [Function.flip_def, List.foldr_reverse, Foldl.ofFreeMonoid, unop_op] _ = toList xs := by rw [foldMap_hom_free (Foldl.ofFreeMonoid (flip <| @cons α))] @@ -337,8 +327,6 @@ theorem toList_map (f : α → β) (xs : t α) : toList (f <$> xs) = f <$> toLis @[simp] theorem foldl_map (g : β → γ) (f : α → γ → α) (a : α) (l : t β) : foldl f a (g <$> l) = foldl (fun x y => f x (g y)) a l := by - #adaptation_note /-- nightly-2024-03-16: simp was - simp only [foldl, foldMap_map, (· ∘ ·), flip] -/ simp only [foldl, foldMap_map, Function.comp_def, Function.flip_def] @[simp] @@ -382,8 +370,6 @@ theorem foldrm_toList (f : α → β → m β) (x : β) (xs : t α) : @[simp] theorem foldlm_map (g : β → γ) (f : α → γ → m α) (a : α) (l : t β) : foldlm f a (g <$> l) = foldlm (fun x y => f x (g y)) a l := by - #adaptation_note /-- nightly-2024-03-16: simp was - simp only [foldlm, foldMap_map, (· ∘ ·), flip] -/ simp only [foldlm, foldMap_map, Function.comp_def, Function.flip_def] @[simp] diff --git a/Mathlib/Data/DFinsupp/WellFounded.lean b/Mathlib/Data/DFinsupp/WellFounded.lean index 4b312a0571ec7..ac37b3707bd63 100644 --- a/Mathlib/Data/DFinsupp/WellFounded.lean +++ b/Mathlib/Data/DFinsupp/WellFounded.lean @@ -212,9 +212,7 @@ protected theorem DFinsupp.wellFoundedLT [∀ i, Zero (α i)] [∀ i, Preorder ( refine Lex.wellFounded' ?_ (fun i ↦ IsWellFounded.wf) ?_ · rintro i ⟨a⟩ apply hbot - · #adaptation_note /-- nightly-2024-03-16: simp was - simp (config := { unfoldPartialApp := true }) only [Function.swap] -/ - simp only [Function.swap_def] + · simp +unfoldPartialApp only [Function.swap] exact IsWellFounded.wf refine Subrelation.wf (fun h => ?_) <| InvImage.wf (mapRange e fun _ ↦ rfl) this have := IsStrictOrder.swap (@WellOrderingRel ι) diff --git a/Mathlib/Data/Rel.lean b/Mathlib/Data/Rel.lean index ced1fb359df56..cae0b3a83e60e 100644 --- a/Mathlib/Data/Rel.lean +++ b/Mathlib/Data/Rel.lean @@ -136,12 +136,10 @@ theorem inv_comp (r : Rel α β) (s : Rel β γ) : inv (r • s) = inv s • inv @[simp] theorem inv_bot : (⊥ : Rel α β).inv = (⊥ : Rel β α) := by - #adaptation_note /-- nightly-2024-03-16: simp was `simp [Bot.bot, inv, flip]` -/ simp [Bot.bot, inv, Function.flip_def] @[simp] theorem inv_top : (⊤ : Rel α β).inv = (⊤ : Rel β α) := by - #adaptation_note /-- nightly-2024-03-16: simp was `simp [Top.top, inv, flip]` -/ simp [Top.top, inv, Function.flip_def] /-- Image of a set under a relation -/ diff --git a/Mathlib/Data/Subtype.lean b/Mathlib/Data/Subtype.lean index ea0164bca8d41..ebde31a801bf5 100644 --- a/Mathlib/Data/Subtype.lean +++ b/Mathlib/Data/Subtype.lean @@ -155,7 +155,6 @@ def map {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀ a, p a → Subtype p → Subtype q := fun x ↦ ⟨f x, h x x.prop⟩ -#adaptation_note /-- nightly-2024-03-16: added to replace simp [Subtype.map] -/ theorem map_def {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀ a, p a → q (f a)) : map f h = fun x ↦ ⟨f x, h x x.prop⟩ := rfl diff --git a/Mathlib/Geometry/Euclidean/Inversion/Basic.lean b/Mathlib/Geometry/Euclidean/Inversion/Basic.lean index ef7c492a1d056..7fc9dd70fae57 100644 --- a/Mathlib/Geometry/Euclidean/Inversion/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Inversion/Basic.lean @@ -40,7 +40,6 @@ sphere. -/ def inversion (c : P) (R : ℝ) (x : P) : P := (R / dist x c) ^ 2 • (x -ᵥ c) +ᵥ c -#adaptation_note /-- nightly-2024-03-16: added to replace simp [inversion] -/ theorem inversion_def : inversion = fun (c : P) (R : ℝ) (x : P) => (R / dist x c) ^ 2 • (x -ᵥ c) +ᵥ c := rfl diff --git a/Mathlib/Geometry/Euclidean/Inversion/Calculus.lean b/Mathlib/Geometry/Euclidean/Inversion/Calculus.lean index 877daf129a72a..f948ab3a60200 100644 --- a/Mathlib/Geometry/Euclidean/Inversion/Calculus.lean +++ b/Mathlib/Geometry/Euclidean/Inversion/Calculus.lean @@ -89,9 +89,7 @@ theorem hasFDerivAt_inversion (hx : x ≠ c) : ((R / dist x c) ^ 2 • (reflection (ℝ ∙ (x - c))ᗮ : F →L[ℝ] F)) x := by rcases add_left_surjective c x with ⟨x, rfl⟩ have : HasFDerivAt (inversion c R) (?_ : F →L[ℝ] F) (c + x) := by - #adaptation_note /-- nightly-2024-03-16: simp was - simp (config := { unfoldPartialApp := true }) only [inversion] -/ - simp only [inversion_def] + simp +unfoldPartialApp only [inversion] simp_rw [dist_eq_norm, div_pow, div_eq_mul_inv] have A := (hasFDerivAt_id (𝕜 := ℝ) (c + x)).sub_const c have B := ((hasDerivAt_inv <| by simpa using hx).comp_hasFDerivAt _ A.norm_sq).const_mul diff --git a/Mathlib/Logic/Function/Defs.lean b/Mathlib/Logic/Function/Defs.lean index 0caf5f335d524..8196c2377e17e 100644 --- a/Mathlib/Logic/Function/Defs.lean +++ b/Mathlib/Logic/Function/Defs.lean @@ -48,7 +48,6 @@ scoped infixl:2 " on " => onFun abbrev swap {φ : α → β → Sort u₃} (f : ∀ x y, φ x y) : ∀ y x, φ x y := fun y x => f x y -#adaptation_note /-- nightly-2024-03-16: added to replace simp [Function.swap] -/ theorem swap_def {φ : α → β → Sort u₃} (f : ∀ x y, φ x y) : swap f = fun y x => f x y := rfl -- Porting note: removed, it was never used diff --git a/Mathlib/Probability/Process/HittingTime.lean b/Mathlib/Probability/Process/HittingTime.lean index 5ac75975d6483..7610ba2b87de1 100644 --- a/Mathlib/Probability/Process/HittingTime.lean +++ b/Mathlib/Probability/Process/HittingTime.lean @@ -53,7 +53,6 @@ noncomputable def hitting [Preorder ι] [InfSet ι] (u : ι → Ω → β) fun x => if ∃ j ∈ Set.Icc n m, u j x ∈ s then sInf (Set.Icc n m ∩ {i : ι | u i x ∈ s}) else m -#adaptation_note /-- nightly-2024-03-16: added to replace simp [hitting] -/ open scoped Classical in theorem hitting_def [Preorder ι] [InfSet ι] (u : ι → Ω → β) (s : Set β) (n m : ι) : hitting u s n m = diff --git a/Mathlib/Topology/List.lean b/Mathlib/Topology/List.lean index be04e98105dbd..10a7e8b0991c0 100644 --- a/Mathlib/Topology/List.lean +++ b/Mathlib/Topology/List.lean @@ -56,8 +56,6 @@ theorem nhds_list (as : List α) : 𝓝 as = traverse 𝓝 as := by have : List.Forall₂ (fun a s => IsOpen s ∧ a ∈ s) u v := by refine List.Forall₂.flip ?_ replace hv := hv.flip - #adaptation_note /-- nightly-2024-03-16: simp was - simp only [List.forall₂_and_left, flip] at hv ⊢ -/ simp only [List.forall₂_and_left, Function.flip_def] at hv ⊢ exact ⟨hv.1, hu.flip⟩ refine mem_of_superset ?_ hvs diff --git a/MathlibTest/MoveAdd.lean b/MathlibTest/MoveAdd.lean index 74d7a9fd44d70..e091e08e058a7 100644 --- a/MathlibTest/MoveAdd.lean +++ b/MathlibTest/MoveAdd.lean @@ -108,13 +108,12 @@ example {a b c d e : Prop} (h : a ∨ b ∨ c ∨ d ∨ e) : a ∨ c ∨ e ∨ b end left_assoc -#adaptation_note /-- nightly-2024-03-11 -This test is now failing with `unknown free variable '_fvar.36787'` -/ --- example (k : ℕ) (h0 : 0 + 2 = 9 + 0) (h9 : k + 2 = k + 9) : k + 2 = 9 + k := by --- induction' k with k _ih --- · exact h0 --- · move_add [9] --- exact h9 +example (k : ℕ) (h0 : 0 + 2 = 9 + 0) (h9 : k + 2 = k + 9) : k + 2 = 9 + k := by + induction k with + | zero => exact h0 + | succ n _ => + move_add [9] + exact h9 -- Testing internals of the tactic `move_add`. section tactic From 62e47425fe265fa35eeeaedbfc49d9aff0157ccc Mon Sep 17 00:00:00 2001 From: grunweg Date: Tue, 28 Jan 2025 22:03:07 +0000 Subject: [PATCH 616/681] chore: remove non-emptiness hypotheses in the disjoint union of manifolds (#21066) The previous code assumed both manifolds were non-empty: this is in fact not necessary. (When doing bordism theory, such unions are meaningful: a cobordism between a manifold M and "the empty set" is supposed to have boundary M union the empty set, so we need to speak about this.) Besides, the code only gets marginally longer, so this change might be worth it independently. From my bordism theory project. Co-authored-by: Michael Rothgang --- Mathlib/Geometry/Manifold/ChartedSpace.lean | 2 +- .../Geometry/Manifold/InteriorBoundary.lean | 5 ++-- Mathlib/Geometry/Manifold/IsManifold.lean | 2 +- Mathlib/Topology/PartialHomeomorph.lean | 23 ++++++++++--------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index 7bcb7a3778950..c5f523f226b65 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -851,7 +851,7 @@ theorem piChartedSpace_chartAt {ι : Type*} [Finite ι] (H : ι → Type*) section sum variable [TopologicalSpace H] [TopologicalSpace M] [TopologicalSpace M'] - [cm : ChartedSpace H M] [cm' : ChartedSpace H M'] [Nonempty H] [Nonempty M] [Nonempty M'] + [cm : ChartedSpace H M] [cm' : ChartedSpace H M'] [Nonempty H] /-- The disjoint union of two charted spaces on `H` is a charted space over `H`. -/ instance ChartedSpace.sum : ChartedSpace H (M ⊕ M') where diff --git a/Mathlib/Geometry/Manifold/InteriorBoundary.lean b/Mathlib/Geometry/Manifold/InteriorBoundary.lean index 7f6c2a06f8852..4feb7faf82ea2 100644 --- a/Mathlib/Geometry/Manifold/InteriorBoundary.lean +++ b/Mathlib/Geometry/Manifold/InteriorBoundary.lean @@ -250,12 +250,11 @@ end prod section disjointUnion variable {M' : Type*} [TopologicalSpace M'] [ChartedSpace H M'] {n : WithTop ℕ∞} - [hM : IsManifold I n M] [hM' : IsManifold I n M'] - [Nonempty M] [Nonempty M'] [Nonempty H] + [hM : IsManifold I n M] [hM' : IsManifold I n M'] [Nonempty H] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {J : Type*} {J : ModelWithCorners 𝕜 E' H'} {N N' : Type*} [TopologicalSpace N] [TopologicalSpace N'] [ChartedSpace H' N] [ChartedSpace H' N'] - [IsManifold J n N] [IsManifold J n N'] [Nonempty N] [Nonempty N'] [Nonempty H'] + [IsManifold J n N] [IsManifold J n N'] [Nonempty H'] open Topology diff --git a/Mathlib/Geometry/Manifold/IsManifold.lean b/Mathlib/Geometry/Manifold/IsManifold.lean index 69d14ee8012e6..069cea5c3f202 100644 --- a/Mathlib/Geometry/Manifold/IsManifold.lean +++ b/Mathlib/Geometry/Manifold/IsManifold.lean @@ -829,7 +829,7 @@ variable {M' : Type*} [TopologicalSpace M'] [ChartedSpace H M'] /-- The disjoint union of two `C^n` manifolds modelled on `(E, H)` is a `C^n` manifold modeled on `(E, H)`. -/ -instance disjointUnion [Nonempty M] [Nonempty M'] [Nonempty H] : IsManifold I n (M ⊕ M') where +instance disjointUnion [Nonempty H] : IsManifold I n (M ⊕ M') where compatible {e} e' he he' := by obtain (⟨f, hf, hef⟩ | ⟨f, hf, hef⟩) := ChartedSpace.mem_atlas_sum he · obtain (⟨f', hf', he'f'⟩ | ⟨f', hf', he'f'⟩) := ChartedSpace.mem_atlas_sum he' diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index a178c181fd1cd..c0004b4df3cba 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -1326,15 +1326,14 @@ theorem subtypeRestr_symm_eqOn_of_le {U V : Opens X} (hU : Nonempty U) (hV : Non end subtypeRestr variable {X X' Z : Type*} [TopologicalSpace X] [TopologicalSpace X'] [TopologicalSpace Z] - [Nonempty X] [Nonempty Z] {f : X → X'} + [Nonempty Z] {f : X → X'} /-- Extend a partial homeomorphism `e : X → Z` to `X' → Z`, using an open embedding `ι : X → X'`. On `ι(X)`, the extension is specified by `e`; its value elsewhere is arbitrary (and uninteresting). -/ -noncomputable def lift_openEmbedding - (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : +noncomputable def lift_openEmbedding (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : PartialHomeomorph X' Z where - toFun := extend f e (Classical.arbitrary (α := X' → Z)) + toFun := extend f e (fun _ ↦ (Classical.arbitrary Z)) invFun := f ∘ e.invFun source := f '' e.source target := e.target @@ -1352,7 +1351,9 @@ noncomputable def lift_openEmbedding open_source := hf.isOpenMap _ e.open_source open_target := e.open_target continuousOn_toFun := by - set F := (extend f (↑e) (Classical.arbitrary (X' → Z))) with F_eq + by_cases Nonempty X; swap + · intro x hx; simp_all + set F := (extend f e (fun _ ↦ (Classical.arbitrary Z))) with F_eq have heq : EqOn F (e ∘ (hf.toPartialHomeomorph).symm) (f '' e.source) := by intro x ⟨x₀, hx₀, hxx₀⟩ rw [← hxx₀, F_eq, hf.injective.extend_apply e, comp_apply, hf.toPartialHomeomorph_left_inv] @@ -1360,15 +1361,15 @@ noncomputable def lift_openEmbedding apply e.continuousOn_toFun.comp; swap · intro x' ⟨x, hx, hx'x⟩ rw [← hx'x, hf.toPartialHomeomorph_left_inv]; exact hx - have : ContinuousOn (hf.toPartialHomeomorph).symm (f '' univ) := by - apply (hf.toPartialHomeomorph).continuousOn_invFun + have : ContinuousOn (hf.toPartialHomeomorph).symm (f '' univ) := + (hf.toPartialHomeomorph).continuousOn_invFun apply this.mono; gcongr; exact fun ⦃a⦄ a ↦ trivial - apply ContinuousOn.congr this heq + exact ContinuousOn.congr this heq continuousOn_invFun := hf.continuous.comp_continuousOn e.continuousOn_invFun @[simp] lemma lift_openEmbedding_toFun (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : - (e.lift_openEmbedding hf) = extend f e (Classical.arbitrary (α := (X' → Z))) := rfl + (e.lift_openEmbedding hf) = extend f e (fun _ ↦ (Classical.arbitrary Z)) := rfl lemma lift_openEmbedding_apply (e : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) {x : X} : (lift_openEmbedding e hf) (f x) = e x := by @@ -1404,8 +1405,8 @@ lemma lift_openEmbedding_trans_apply @[simp] lemma lift_openEmbedding_trans (e e' : PartialHomeomorph X Z) (hf : IsOpenEmbedding f) : (e.lift_openEmbedding hf).symm.trans (e'.lift_openEmbedding hf) = e.symm.trans e' := by - ext x - · exact e.lift_openEmbedding_trans_apply e' hf x + ext z + · exact e.lift_openEmbedding_trans_apply e' hf z · simp [hf.injective.extend_apply e] · simp_rw [PartialHomeomorph.trans_source, e.lift_openEmbedding_symm_source, e.symm_source, e.lift_openEmbedding_symm, e'.lift_openEmbedding_source] From f3eaa8093bc0fa45145db394b1681d4667a4b509 Mon Sep 17 00:00:00 2001 From: Sina Hazratpour Date: Tue, 28 Jan 2025 22:24:10 +0000 Subject: [PATCH 617/681] feat (CategoryTheory): constructing chosen finite products for the preorder category of a meet-semilattice with a top element (#21094) The preorder category of a meet-semilattice `C` with a top element has chosen finite products. Motivation: I plan to use the induced monoidal structure to show that the preorder category of a distributive lattice is distributive. See this PR on Monoidal and cartesian distributive categories: #20182 --- Mathlib.lean | 2 + .../ChosenFiniteProducts/InfSemilattice.lean | 42 +++++++++++ Mathlib/CategoryTheory/Limits/Preorder.lean | 75 +++++++++++++++++++ .../Limits/Shapes/Preorder/Basic.lean | 14 +--- 4 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 Mathlib/CategoryTheory/ChosenFiniteProducts/InfSemilattice.lean create mode 100644 Mathlib/CategoryTheory/Limits/Preorder.lean diff --git a/Mathlib.lean b/Mathlib.lean index 38b9f5aa9552a..32a903e0b0f3c 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1734,6 +1734,7 @@ import Mathlib.CategoryTheory.Category.ULift import Mathlib.CategoryTheory.ChosenFiniteProducts import Mathlib.CategoryTheory.ChosenFiniteProducts.Cat import Mathlib.CategoryTheory.ChosenFiniteProducts.FunctorCategory +import Mathlib.CategoryTheory.ChosenFiniteProducts.InfSemilattice import Mathlib.CategoryTheory.Closed.Cartesian import Mathlib.CategoryTheory.Closed.Enrichment import Mathlib.CategoryTheory.Closed.Functor @@ -1942,6 +1943,7 @@ import Mathlib.CategoryTheory.Limits.MorphismProperty import Mathlib.CategoryTheory.Limits.Opposites import Mathlib.CategoryTheory.Limits.Over import Mathlib.CategoryTheory.Limits.Pi +import Mathlib.CategoryTheory.Limits.Preorder import Mathlib.CategoryTheory.Limits.Preserves.Basic import Mathlib.CategoryTheory.Limits.Preserves.Filtered import Mathlib.CategoryTheory.Limits.Preserves.Finite diff --git a/Mathlib/CategoryTheory/ChosenFiniteProducts/InfSemilattice.lean b/Mathlib/CategoryTheory/ChosenFiniteProducts/InfSemilattice.lean new file mode 100644 index 0000000000000..ae74a6c833fad --- /dev/null +++ b/Mathlib/CategoryTheory/ChosenFiniteProducts/InfSemilattice.lean @@ -0,0 +1,42 @@ +/- +Copyright (c) 2025 Sina Hazratpour. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sina Hazratpour +-/ + +import Mathlib.CategoryTheory.ChosenFiniteProducts +import Mathlib.CategoryTheory.Limits.Preorder + +/-! +# Chosen finite products for the preorder category of a meet-semilattice with a greatest element + +The preorder category of a meet-semilattice `C` with a greatest element has chosen finite products. + +A symmetric monoidal structure on the preorder category is automatically provided by the +instances `monoidalOfChosenFiniteProducts` and `ChosenFiniteProducts.instSymmetricCategory`. + +-/ + +namespace CategoryTheory + +open Category MonoidalCategory + +universe u + +variable (C : Type u) [SemilatticeInf C] [OrderTop C] + +namespace SemilatticeInf + +/-- Chosen finite products for the preorder category of a meet-semilattice with a greatest element-/ +noncomputable scoped instance chosenFiniteProducts : ChosenFiniteProducts C where + terminal := ⟨_, Preorder.isTerminalTop C⟩ + product X Y := ⟨_, Preorder.isLimitBinaryFan X Y⟩ + +lemma tensorObj {C : Type u} [SemilatticeInf C] [OrderTop C] {X Y : C} : X ⊗ Y = X ⊓ Y := rfl + +lemma tensorUnit {C : Type u} [SemilatticeInf C] [OrderTop C] : + 𝟙_ C = ⊤ := rfl + +end SemilatticeInf + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Preorder.lean b/Mathlib/CategoryTheory/Limits/Preorder.lean new file mode 100644 index 0000000000000..605ebbea32e56 --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Preorder.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2025 Sina Hazratpour. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sina Hazratpour, Joël Riou +-/ + +import Mathlib.CategoryTheory.Limits.Shapes.BinaryProducts + +/-! +# (Co)limits in a preorder category + +We provide basic results about the nullary and binary (co)products in the associated category of +a preordered type. + +-/ + +universe u + +open CategoryTheory Limits + +namespace Preorder + +variable (C : Type u) + +section OrderBot + +variable [Preorder C] [OrderBot C] + +/-- The least element in a preordered type is initial in the category +associated to this preorder. -/ +def isInitialBot : IsInitial (⊥ : C) := IsInitial.ofUnique _ + +instance : HasInitial C := hasInitial_of_unique ⊥ + +end OrderBot + +section OrderTop + +variable [Preorder C] [OrderTop C] + +/-- The greatest element of a preordered type is terminal in the category +associated to this preorder. -/ +def isTerminalTop : IsTerminal (⊤ : C) := IsTerminal.ofUnique _ + +instance : HasTerminal C := hasTerminal_of_unique ⊤ + +end OrderTop + +section SemilatticeInf + +variable {C} [SemilatticeInf C] + +/-- The infimum of two elements in a preordered type is a binary product in +the category associated to this preorder. -/ +def isLimitBinaryFan (X Y : C) : + IsLimit (BinaryFan.mk (P := X ⊓ Y) (homOfLE inf_le_left) (homOfLE inf_le_right)) := + BinaryFan.isLimitMk (fun s ↦ homOfLE (le_inf (leOfHom s.fst) (leOfHom s.snd))) + (by intros; rfl) (by intros; rfl) (by intros; rfl) + +end SemilatticeInf + +section SemilatticeSup + +variable {C} [SemilatticeSup C] + +/-- The supremum of two elements in a preordered type is a binary coproduct +in the category associated to this preorder. -/ +def isColimitBinaryCofan (X Y : C) : + IsColimit (BinaryCofan.mk (P := X ⊔ Y) (homOfLE le_sup_left) (homOfLE le_sup_right)) := + BinaryCofan.isColimitMk (fun s ↦ homOfLE (sup_le (leOfHom s.inl) (leOfHom s.inr))) + (by intros; rfl) (by intros; rfl) (by intros; rfl) + +end SemilatticeSup + +end Preorder diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean index fd2ca7692b49c..cf21ab0f2fbac 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Preorder/Basic.lean @@ -3,7 +3,7 @@ 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.CategoryTheory.Limits.Shapes.Terminal +import Mathlib.CategoryTheory.Limits.Preorder /-! # Limits and colimits indexed by preorders @@ -27,12 +27,6 @@ section OrderBot variable [OrderBot J] -/-- The least element in a preordered type is initial in the category -associated to this preorder. -/ -def isInitialBot : IsInitial (⊥ : J) := IsInitial.ofUnique _ - -instance : HasInitial J := hasInitial_of_unique ⊥ - instance : HasLimitsOfShape J C := ⟨fun _ ↦ by infer_instance⟩ end OrderBot @@ -41,12 +35,6 @@ section OrderTop variable [OrderTop J] -/-- The greatest element of a preordered type is terminal in the category -associated to this preorder. -/ -def isTerminalBot : IsTerminal (⊤ : J) := IsTerminal.ofUnique _ - -instance : HasTerminal J := hasTerminal_of_unique ⊤ - instance : HasColimitsOfShape J C := ⟨fun _ ↦ by infer_instance⟩ end OrderTop From de76150344880050f288c6fb6bc17695444c52f6 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Wed, 29 Jan 2025 00:09:19 +0000 Subject: [PATCH 618/681] feat(Algebra): add `MonoidHom.coe_id` (#21189) We have this as a `@[simp]` lemma for most algebraic structures: `RingHom`, `LinearMap`, ... I need this for the concrete category refactor, since we will get a lot of `@[simp]` lemmas about unapplied / partially applied functions, including `id`. --- Mathlib/Algebra/Group/Hom/Defs.lean | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Mathlib/Algebra/Group/Hom/Defs.lean b/Mathlib/Algebra/Group/Hom/Defs.lean index 2ffc6457f0b71..08c5149911c7e 100644 --- a/Mathlib/Algebra/Group/Hom/Defs.lean +++ b/Mathlib/Algebra/Group/Hom/Defs.lean @@ -706,6 +706,15 @@ def MonoidHom.id (M : Type*) [MulOneClass M] : M →* M where map_one' := rfl map_mul' _ _ := rfl +@[to_additive (attr := simp)] +lemma OneHom.coe_id {M : Type*} [One M] : (OneHom.id M : M → M) = _root_.id := rfl + +@[to_additive (attr := simp)] +lemma MulHom.coe_id {M : Type*} [Mul M] : (MulHom.id M : M → M) = _root_.id := rfl + +@[to_additive (attr := simp)] +lemma MonoidHom.coe_id {M : Type*} [MulOneClass M] : (MonoidHom.id M : M → M) = _root_.id := rfl + /-- Composition of `OneHom`s as a `OneHom`. -/ @[to_additive "Composition of `ZeroHom`s as a `ZeroHom`."] def OneHom.comp [One M] [One N] [One P] (hnp : OneHom N P) (hmn : OneHom M N) : OneHom M P where From b53998a5b3fad1f750267986708c28bcf5426461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miyahara=20K=C5=8D?= <52843868+Komyyy@users.noreply.github.com> Date: Wed, 29 Jan 2025 04:14:22 +0000 Subject: [PATCH 619/681] doc(Mathlib/NumberTheory/Dioph): fix a misported name (#21207) --- Mathlib/NumberTheory/Dioph.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/NumberTheory/Dioph.lean b/Mathlib/NumberTheory/Dioph.lean index 6c7c378d55eb4..2b065a6f7dd2e 100644 --- a/Mathlib/NumberTheory/Dioph.lean +++ b/Mathlib/NumberTheory/Dioph.lean @@ -26,7 +26,7 @@ there exists `t : ℕ^β` with `p (v, t) = 0`. * `Dioph`: a predicate stating that a set is Diophantine, i.e. a set `S ⊆ ℕ^α` is Diophantine if there exists a polynomial on `α ⊕ β` such that `v ∈ S` iff there exists `t : ℕ^β` with `p (v, t) = 0`. -* `dioph_fn`: a predicate on a function stating that it is Diophantine in the sense that its graph +* `DiophFn`: a predicate on a function stating that it is Diophantine in the sense that its graph is Diophantine as a set. ## Main statements From 5ec765ec4e0911203fa07c0f728429ad9c5fd0a9 Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 29 Jan 2025 05:05:14 +0000 Subject: [PATCH 620/681] chore: cleanup simp priorities in Algebra/Homology/ (#21157) --- Mathlib/Algebra/Homology/Additive.lean | 2 +- .../Homology/DerivedCategory/Ext/Basic.lean | 4 ++-- .../Algebra/Homology/HomologicalComplex.lean | 4 +--- Mathlib/Algebra/Homology/Homotopy.lean | 20 +++++++++---------- .../Algebra/Homology/HomotopyCategory.lean | 1 - .../HomotopyCategory/MappingCone.lean | 4 ++-- .../Homology/ShortComplex/Abelian.lean | 4 ++-- 7 files changed, 18 insertions(+), 21 deletions(-) diff --git a/Mathlib/Algebra/Homology/Additive.lean b/Mathlib/Algebra/Homology/Additive.lean index 86d5e417b4051..a5c9c7078277a 100644 --- a/Mathlib/Algebra/Homology/Additive.lean +++ b/Mathlib/Algebra/Homology/Additive.lean @@ -170,7 +170,7 @@ theorem NatTrans.mapHomologicalComplex_comp (c : ComplexShape ι) {F G H : W₁ NatTrans.mapHomologicalComplex α c ≫ NatTrans.mapHomologicalComplex β c := by aesop_cat -@[reassoc (attr := simp 1100)] +@[reassoc] theorem NatTrans.mapHomologicalComplex_naturality {c : ComplexShape ι} {F G : W₁ ⥤ W₂} [F.PreservesZeroMorphisms] [G.PreservesZeroMorphisms] (α : F ⟶ G) {C D : HomologicalComplex W₁ c} (f : C ⟶ D) : diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean index 908ef5c957030..4aae573cb738d 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean @@ -160,12 +160,12 @@ lemma mk₀_hom [HasDerivedCategory.{w'} C] (f : X ⟶ Y) : (mk₀ f).hom = ShiftedHom.mk₀ _ (by simp) ((singleFunctor C 0).map f) := by apply SmallShiftedHom.equiv_mk₀ -@[simp 1100] +@[simp] lemma mk₀_comp_mk₀ (f : X ⟶ Y) (g : Y ⟶ Z) : (mk₀ f).comp (mk₀ g) (zero_add 0) = mk₀ (f ≫ g) := by letI := HasDerivedCategory.standard C; ext; simp -@[simp 1100] +@[simp] lemma mk₀_comp_mk₀_assoc (f : X ⟶ Y) (g : Y ⟶ Z) {n : ℕ} (α : Ext Z T n) : (mk₀ f).comp ((mk₀ g).comp α (zero_add n)) (zero_add n) = (mk₀ (f ≫ g)).comp α (zero_add n) := by diff --git a/Mathlib/Algebra/Homology/HomologicalComplex.lean b/Mathlib/Algebra/Homology/HomologicalComplex.lean index 9fc057de9025d..f09f0593e1d0f 100644 --- a/Mathlib/Algebra/Homology/HomologicalComplex.lean +++ b/Mathlib/Algebra/Homology/HomologicalComplex.lean @@ -469,7 +469,7 @@ theorem dFrom_comp_xNextIso {i j : ι} (r : c.Rel i j) : theorem dFrom_comp_xNextIsoSelf {i : ι} (h : ¬c.Rel i (c.next i)) : C.dFrom i ≫ (C.xNextIsoSelf h).hom = 0 := by simp [h] -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem dTo_comp_dFrom (j : ι) : C.dTo j ≫ C.dFrom j = 0 := C.d_comp_d _ _ _ @@ -552,14 +552,12 @@ theorem next_eq (f : Hom C₁ C₂) {i j : ι} (w : c.Rel i j) : theorem comm_from (f : Hom C₁ C₂) (i : ι) : f.f i ≫ C₂.dFrom i = C₁.dFrom i ≫ f.next i := f.comm _ _ -attribute [simp 1100] comm_from_assoc attribute [simp] comm_from_apply @[reassoc, elementwise] theorem comm_to (f : Hom C₁ C₂) (j : ι) : f.prev j ≫ C₂.dTo j = C₁.dTo j ≫ f.f j := f.comm _ _ -attribute [simp 1100] comm_to_assoc attribute [simp] comm_to_apply /-- A morphism of chain complexes diff --git a/Mathlib/Algebra/Homology/Homotopy.lean b/Mathlib/Algebra/Homology/Homotopy.lean index bb13f21e29877..8e8923988a0cf 100644 --- a/Mathlib/Algebra/Homology/Homotopy.lean +++ b/Mathlib/Algebra/Homology/Homotopy.lean @@ -51,12 +51,12 @@ lemma dNext_eq_zero (f : ∀ i j, C.X i ⟶ D.X j) (i : ι) (hi : ¬ c.Rel i (c. dsimp [dNext] rw [shape _ _ _ hi, zero_comp] -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem dNext_comp_left (f : C ⟶ D) (g : ∀ i j, D.X i ⟶ E.X j) (i : ι) : (dNext i fun i j => f.f i ≫ g i j) = f.f i ≫ dNext i g := (f.comm_assoc _ _ _).symm -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem dNext_comp_right (f : ∀ i j, C.X i ⟶ D.X j) (g : D ⟶ E) (i : ι) : (dNext i fun i j => f i j ≫ g.f j) = dNext i f ≫ g.f i := (assoc _ _ _).symm @@ -85,12 +85,12 @@ theorem prevD_eq (f : ∀ i j, C.X i ⟶ D.X j) {j j' : ι} (w : c.Rel j' j) : obtain rfl := c.prev_eq' w rfl -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem prevD_comp_left (f : C ⟶ D) (g : ∀ i j, D.X i ⟶ E.X j) (j : ι) : (prevD j fun i j => f.f i ≫ g i j) = f.f j ≫ prevD j g := assoc _ _ _ -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem prevD_comp_right (f : ∀ i j, C.X i ⟶ D.X j) (g : D ⟶ E) (j : ι) : (prevD j fun i j => f i j ≫ g.f j) = prevD j f ≫ g.f j := by dsimp [prevD] @@ -426,21 +426,21 @@ section MkInductive variable {P Q : ChainComplex V ℕ} -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem prevD_chainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (j : ℕ) : prevD j f = f j (j + 1) ≫ Q.d _ _ := by dsimp [prevD] have : (ComplexShape.down ℕ).prev j = j + 1 := ChainComplex.prev ℕ j congr 2 -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem dNext_succ_chainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (i : ℕ) : dNext (i + 1) f = P.d _ _ ≫ f i (i + 1) := by dsimp [dNext] have : (ComplexShape.down ℕ).next (i + 1) = i := ChainComplex.next_nat_succ _ congr 2 -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem dNext_zero_chainComplex (f : ∀ i j, P.X i ⟶ Q.X j) : dNext 0 f = 0 := by dsimp [dNext] rw [P.shape, zero_comp] @@ -556,21 +556,21 @@ section MkCoinductive variable {P Q : CochainComplex V ℕ} -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem dNext_cochainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (j : ℕ) : dNext j f = P.d _ _ ≫ f (j + 1) j := by dsimp [dNext] have : (ComplexShape.up ℕ).next j = j + 1 := CochainComplex.next ℕ j congr 2 -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem prevD_succ_cochainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (i : ℕ) : prevD (i + 1) f = f (i + 1) _ ≫ Q.d i (i + 1) := by dsimp [prevD] have : (ComplexShape.up ℕ).prev (i + 1) = i := CochainComplex.prev_nat_succ i congr 2 -@[simp 1100] +-- This is not a simp lemma; the LHS already simplifies. theorem prevD_zero_cochainComplex (f : ∀ i j, P.X i ⟶ Q.X j) : prevD 0 f = 0 := by dsimp [prevD] rw [Q.shape, comp_zero] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory.lean b/Mathlib/Algebra/Homology/HomotopyCategory.lean index 93400ddd35d94..b4ecba4a3831a 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory.lean @@ -121,7 +121,6 @@ def homotopyOutMap {C D : HomologicalComplex V c} (f : C ⟶ D) : apply homotopyOfEq simp -@[simp 1100] theorem quotient_map_out_comp_out {C D E : HomotopyCategory V c} (f : C ⟶ D) (g : D ⟶ E) : (quotient V c).map (Quot.out f ≫ Quot.out g) = f ≫ g := by simp diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean index 57a474997c34a..aebf5de588e5a 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean @@ -241,10 +241,10 @@ lemma inl_v_d (i j k : ℤ) (hij : i + (-1) = j) (hik : k + (-1) = i) : rw [homotopyCofiber.inlX_d φ j i k (by dsimp; omega) (by dsimp; omega)] abel -@[reassoc (attr := simp 1100)] +@[reassoc] lemma inr_f_d (n₁ n₂ : ℤ) : (inr φ).f n₁ ≫ (mappingCone φ).d n₁ n₂ = G.d n₁ n₂ ≫ (inr φ).f n₂ := by - apply Hom.comm + simp @[reassoc] lemma d_fst_v (i j k : ℤ) (hij : i + 1 = j) (hjk : j + 1 = k) : diff --git a/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean b/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean index ad19544a15033..806aabbe91340 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Abelian.lean @@ -50,10 +50,10 @@ lemma abelianImageToKernel_comp_kernel_ι : instance : Mono S.abelianImageToKernel := mono_of_mono_fac S.abelianImageToKernel_comp_kernel_ι -@[reassoc (attr := simp 1100)] +@[reassoc] lemma abelianImageToKernel_comp_kernel_ι_comp_cokernel_π : S.abelianImageToKernel ≫ kernel.ι S.g ≫ cokernel.π S.f = 0 := by - simp only [abelianImageToKernel_comp_kernel_ι_assoc, kernel.condition] + simp /-- `Abelian.image S.f` is the kernel of `kernel.ι S.g ≫ cokernel.π S.f` -/ noncomputable def abelianImageToKernelIsKernel : From 40e016552572b4add948e6b091a02af0ae84f0e8 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 29 Jan 2025 05:19:33 +0000 Subject: [PATCH 621/681] chore(Perm/Fin): generalize from `Fin n.succ` to `Fin n` (#21193) ... adding `[NeZero n]` as needed. Cherry-picked from #21112 --- Mathlib/GroupTheory/Perm/Fin.lean | 41 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/Mathlib/GroupTheory/Perm/Fin.lean b/Mathlib/GroupTheory/Perm/Fin.lean index 6d0fa972e68ea..ce47c8d3ed178 100644 --- a/Mathlib/GroupTheory/Perm/Fin.lean +++ b/Mathlib/GroupTheory/Perm/Fin.lean @@ -142,13 +142,13 @@ def cycleRange {n : ℕ} (i : Fin n) : Perm (Fin n) := ext simp)) -theorem cycleRange_of_gt {n : ℕ} {i j : Fin n.succ} (h : i < j) : cycleRange i j = j := by +theorem cycleRange_of_gt {n : ℕ} {i j : Fin n} (h : i < j) : cycleRange i j = j := by rw [cycleRange, ofLeftInverse'_eq_ofInjective, ← Function.Embedding.toEquivRange_eq_ofInjective, ← viaFintypeEmbedding, viaFintypeEmbedding_apply_not_mem_range] simpa -theorem cycleRange_of_le {n : ℕ} {i j : Fin n.succ} (h : j ≤ i) : +theorem cycleRange_of_le {n : ℕ} [NeZero n] {i j : Fin n} (h : j ≤ i) : cycleRange i j = if j = i then 0 else j + 1 := by cases n · subsingleton @@ -165,8 +165,10 @@ theorem cycleRange_of_le {n : ℕ} {i j : Fin n.succ} (h : j ≤ i) : · rw [Fin.val_add_one_of_lt] exact lt_of_lt_of_le (lt_of_le_of_ne h (mt (congr_arg _) heq)) (le_last i) -theorem coe_cycleRange_of_le {n : ℕ} {i j : Fin n.succ} (h : j ≤ i) : +theorem coe_cycleRange_of_le {n : ℕ} {i j : Fin n} (h : j ≤ i) : (cycleRange i j : ℕ) = if j = i then 0 else (j : ℕ) + 1 := by + cases' n with n + · exact absurd le_rfl i.pos.not_le rw [cycleRange_of_le h] split_ifs with h' · rfl @@ -176,20 +178,20 @@ theorem coe_cycleRange_of_le {n : ℕ} {i j : Fin n.succ} (h : j ≤ i) : (j : ℕ) < i := Fin.lt_iff_val_lt_val.mp (lt_of_le_of_ne h h') _ ≤ n := Nat.lt_succ_iff.mp i.2) -theorem cycleRange_of_lt {n : ℕ} {i j : Fin n.succ} (h : j < i) : cycleRange i j = j + 1 := by +theorem cycleRange_of_lt {n : ℕ} [NeZero n] {i j : Fin n} (h : j < i) : cycleRange i j = j + 1 := by rw [cycleRange_of_le h.le, if_neg h.ne] -theorem coe_cycleRange_of_lt {n : ℕ} {i j : Fin n.succ} (h : j < i) : +theorem coe_cycleRange_of_lt {n : ℕ} {i j : Fin n} (h : j < i) : (cycleRange i j : ℕ) = j + 1 := by rw [coe_cycleRange_of_le h.le, if_neg h.ne] -theorem cycleRange_of_eq {n : ℕ} {i j : Fin n.succ} (h : j = i) : cycleRange i j = 0 := by +theorem cycleRange_of_eq {n : ℕ} [NeZero n] {i j : Fin n} (h : j = i) : cycleRange i j = 0 := by rw [cycleRange_of_le h.le, if_pos h] @[simp] -theorem cycleRange_self {n : ℕ} (i : Fin n.succ) : cycleRange i i = 0 := +theorem cycleRange_self {n : ℕ} [NeZero n] (i : Fin n) : cycleRange i i = 0 := cycleRange_of_eq rfl -theorem cycleRange_apply {n : ℕ} (i j : Fin n.succ) : +theorem cycleRange_apply {n : ℕ} [NeZero n] (i j : Fin n) : cycleRange i j = if j < i then j + 1 else if j = i then 0 else j := by split_ifs with h₁ h₂ · exact cycleRange_of_lt h₁ @@ -197,11 +199,11 @@ theorem cycleRange_apply {n : ℕ} (i j : Fin n.succ) : · exact cycleRange_of_gt (lt_of_le_of_ne (le_of_not_gt h₁) (Ne.symm h₂)) @[simp] -theorem cycleRange_zero (n : ℕ) : cycleRange (0 : Fin n.succ) = 1 := by +theorem cycleRange_zero (n : ℕ) [NeZero n] : cycleRange (0 : Fin n) = 1 := by ext j - refine Fin.cases ?_ (fun j => ?_) j + rcases (Fin.zero_le' j).eq_or_lt with rfl | hj · simp - · rw [cycleRange_of_gt (Fin.succ_pos j), one_apply] + · rw [cycleRange_of_gt hj, one_apply] @[simp] theorem cycleRange_last (n : ℕ) : cycleRange (last n) = finRotate (n + 1) := by @@ -209,10 +211,12 @@ theorem cycleRange_last (n : ℕ) : cycleRange (last n) = finRotate (n + 1) := b rw [coe_cycleRange_of_le (le_last _), coe_finRotate] @[simp] -theorem cycleRange_zero' {n : ℕ} (h : 0 < n) : cycleRange ⟨0, h⟩ = 1 := by - cases' n with n - · cases h - exact cycleRange_zero n +theorem cycleRange_mk_zero {n : ℕ} (h : 0 < n) : cycleRange ⟨0, h⟩ = 1 := + have : NeZero n := .of_pos h + cycleRange_zero n + +@[deprecated (since := "2025-01-28")] +alias cycleRange_zero' := cycleRange_mk_zero @[simp] theorem sign_cycleRange {n : ℕ} (i : Fin n) : Perm.sign (cycleRange i) = (-1) ^ (i : ℕ) := by @@ -248,7 +252,7 @@ theorem cycleRange_succAbove {n : ℕ} (i : Fin (n + 1)) (j : Fin n) : · rw [Fin.succAbove_of_le_castSucc _ _ h, Fin.cycleRange_of_gt (Fin.le_castSucc_iff.mp h)] @[simp] -theorem cycleRange_symm_zero {n : ℕ} (i : Fin (n + 1)) : i.cycleRange.symm 0 = i := +theorem cycleRange_symm_zero {n : ℕ} [NeZero n] (i : Fin n) : i.cycleRange.symm 0 = i := i.cycleRange.injective (by simp) @[simp] @@ -256,14 +260,15 @@ theorem cycleRange_symm_succ {n : ℕ} (i : Fin (n + 1)) (j : Fin n) : i.cycleRange.symm j.succ = i.succAbove j := i.cycleRange.injective (by simp) -theorem isCycle_cycleRange {n : ℕ} {i : Fin (n + 1)} (h0 : i ≠ 0) : IsCycle (cycleRange i) := by +theorem isCycle_cycleRange {n : ℕ} [NeZero n] {i : Fin n} (h0 : i ≠ 0) : + IsCycle (cycleRange i) := by cases' i with i hi cases i · exact (h0 rfl).elim exact isCycle_finRotate.extendDomain _ @[simp] -theorem cycleType_cycleRange {n : ℕ} {i : Fin (n + 1)} (h0 : i ≠ 0) : +theorem cycleType_cycleRange {n : ℕ} [NeZero n] {i : Fin n} (h0 : i ≠ 0) : cycleType (cycleRange i) = {(i + 1 : ℕ)} := by cases' i with i hi cases i From 93b9df377023dd8bce52656e332e574e02bd179a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 29 Jan 2025 05:39:13 +0000 Subject: [PATCH 622/681] feat(Order): Fin.orderHom_injective_iff (#21119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR adds a lemma `Fin.orderHom_injective_iff` which says that a monotone map `f : Fin (n + 1) →o α` is injective iff `f i.castSucc ≠ f i.succ` for all `i`. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib/Order/Fin/Basic.lean | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Mathlib/Order/Fin/Basic.lean b/Mathlib/Order/Fin/Basic.lean index b96bc794c18a1..909ffef89bf33 100644 --- a/Mathlib/Order/Fin/Basic.lean +++ b/Mathlib/Order/Fin/Basic.lean @@ -133,6 +133,16 @@ lemma strictAnti_iff_succ_lt : StrictAnti f ↔ ∀ i : Fin n, f i.succ < f (cas lemma antitone_iff_succ_le : Antitone f ↔ ∀ i : Fin n, f i.succ ≤ f (castSucc i) := antitone_iff_forall_lt.trans <| liftFun_iff_succ (· ≥ ·) +lemma orderHom_injective_iff {α : Type*} [PartialOrder α] {n : ℕ} (f : Fin (n + 1) →o α) : + Function.Injective f ↔ ∀ (i : Fin n), f i.castSucc ≠ f i.succ := by + constructor + · intro hf i hi + have := hf hi + simp [Fin.ext_iff] at this + · intro hf + refine (strictMono_iff_lt_succ (f := f).2 fun i ↦ ?_).injective + exact lt_of_le_of_ne (f.monotone (Fin.castSucc_le_succ i)) (hf i) + end FromFin /-! #### Monotonicity -/ From 35d9e5d1c42d9e10355c062dbf1ea6c7ed9d8277 Mon Sep 17 00:00:00 2001 From: Yakov Pechersky Date: Wed, 29 Jan 2025 05:39:15 +0000 Subject: [PATCH 623/681] feat(Nonarchimedean): cauchySeq_of_tendsto_div_nhds_one (#21153) Convergence of a sequence in nonarchimedean spaces only requires differences to go to zero Co-authored-by: Yakov Pechersky --- .../Algebra/InfiniteSum/Nonarchimedean.lean | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Nonarchimedean.lean b/Mathlib/Topology/Algebra/InfiniteSum/Nonarchimedean.lean index afef581ea8ffb..70a2cc032d21e 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Nonarchimedean.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Nonarchimedean.lean @@ -55,6 +55,32 @@ theorem cauchySeq_prod_of_tendsto_cofinite_one {f : α → G} (hf : Tendsto f co intro i hi simpa using Finset.disjoint_left.mp ht hi +/-- Let `G` be a nonarchimedean abelian group, and let `f : ℕ → G` be a function +such that the quotients `f (n + 1) / f n` tend to one. Then the function is a Cauchy sequence. -/ +@[to_additive "Let `G` be a nonarchimedean additive abelian group, and let `f : ℕ → G` be a +function such that the differences `f (n + 1) - f n` tend to zero. +Then the function is a Cauchy sequence."] +lemma cauchySeq_of_tendsto_div_nhds_one {f : ℕ → G} + (hf : Tendsto (fun n ↦ f (n + 1) / f n) atTop (𝓝 1)) : + CauchySeq f := by + suffices Tendsto (fun p : ℕ × ℕ ↦ f p.2 / f p.1) atTop (𝓝 1) by simpa [CauchySeq, + cauchy_map_iff, prod_atTop_atTop_eq, uniformity_eq_comap_nhds_one G, atTop_neBot] + rw [tendsto_atTop'] + intro s hs + obtain ⟨t, ht⟩ := is_nonarchimedean s hs + obtain ⟨N, hN⟩ : ∃ N : ℕ, ∀ b, N ≤ b → f (b + 1) / f b ∈ t := by + simpa using tendsto_def.mp hf t t.mem_nhds_one + refine ⟨(N, N), ?_⟩ + rintro ⟨M, M'⟩ ⟨(hMN : N ≤ M), (hMN' : N ≤ M')⟩ + apply ht + wlog h : M ≤ M' generalizing M M' + · simpa [inv_div] using t.inv_mem <| this _ _ hMN' hMN (le_of_not_ge h) + obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_le h + clear h hMN' + induction k with + | zero => simpa using one_mem t + | succ k ih => simpa using t.mul_mem (hN _ (by omega : N ≤ M + k)) ih + /-- Let `G` be a complete nonarchimedean multiplicative abelian group, and let `f : α → G` be a function that tends to one on the filter of cofinite sets. Then `f` is unconditionally multipliable. -/ From e090c4ef98762f783f04e76e0b536b2b94e9e440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Degenne?= Date: Wed, 29 Jan 2025 06:49:04 +0000 Subject: [PATCH 624/681] feat: the moment generating function is analytic (#20151) Define a complex-valued moment generating function and prove that it is holomorphic. As a consequence, the moment generating function is analytic on the interior of the interval on which it is finite. --- Mathlib.lean | 2 + Mathlib/Analysis/Analytic/OfScalars.lean | 5 + .../Analysis/Calculus/IteratedDeriv/Defs.lean | 18 ++ Mathlib/Analysis/Complex/Basic.lean | 4 +- .../SpecialFunctions/Complex/Analytic.lean | 44 +++ .../MeasureTheory/Integral/SetIntegral.lean | 2 + Mathlib/Probability/Moments/Basic.lean | 11 + Mathlib/Probability/Moments/ComplexMGF.lean | 298 ++++++++++++++++++ .../Probability/Moments/IntegrableExpMul.lean | 57 ++++ Mathlib/Probability/Moments/MGFAnalytic.lean | 124 ++++++++ 10 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 Mathlib/Probability/Moments/ComplexMGF.lean create mode 100644 Mathlib/Probability/Moments/MGFAnalytic.lean diff --git a/Mathlib.lean b/Mathlib.lean index 32a903e0b0f3c..87b4478563b25 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4390,7 +4390,9 @@ import Mathlib.Probability.Martingale.OptionalSampling import Mathlib.Probability.Martingale.OptionalStopping import Mathlib.Probability.Martingale.Upcrossing import Mathlib.Probability.Moments.Basic +import Mathlib.Probability.Moments.ComplexMGF import Mathlib.Probability.Moments.IntegrableExpMul +import Mathlib.Probability.Moments.MGFAnalytic import Mathlib.Probability.Notation import Mathlib.Probability.ProbabilityMassFunction.Basic import Mathlib.Probability.ProbabilityMassFunction.Binomial diff --git a/Mathlib/Analysis/Analytic/OfScalars.lean b/Mathlib/Analysis/Analytic/OfScalars.lean index 5674b07141092..555c1c81c911a 100644 --- a/Mathlib/Analysis/Analytic/OfScalars.lean +++ b/Mathlib/Analysis/Analytic/OfScalars.lean @@ -82,6 +82,11 @@ theorem ofScalars_apply_zero (n : ℕ) : rw [ofScalars] cases n <;> simp +@[simp] +lemma coeff_ofScalars {𝕜 : Type*} [NontriviallyNormedField 𝕜] {p : ℕ → 𝕜} {n : ℕ} : + (FormalMultilinearSeries.ofScalars 𝕜 p).coeff n = p n := by + simp [FormalMultilinearSeries.coeff, FormalMultilinearSeries.ofScalars, List.prod_ofFn] + theorem ofScalars_add (c' : ℕ → 𝕜) : ofScalars E (c + c') = ofScalars E c + ofScalars E c' := by unfold ofScalars simp_rw [Pi.add_apply, Pi.add_def _ _] diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean index bd390d2a8ebcb..d51fff9a736c0 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean @@ -290,3 +290,21 @@ theorem iteratedDeriv_eq_iterate : iteratedDeriv n f = deriv^[n] f := by derivative. -/ theorem iteratedDeriv_succ' : iteratedDeriv (n + 1) f = iteratedDeriv n (deriv f) := by rw [iteratedDeriv_eq_iterate, iteratedDeriv_eq_iterate]; rfl + +lemma AnalyticAt.hasFPowerSeriesAt {𝕜 : Type*} [NontriviallyNormedField 𝕜] [CompleteSpace 𝕜] + [CharZero 𝕜] {f : 𝕜 → 𝕜} {x : 𝕜} (h : AnalyticAt 𝕜 f x) : + HasFPowerSeriesAt f + (FormalMultilinearSeries.ofScalars 𝕜 (fun n ↦ iteratedDeriv n f x / n.factorial)) x := by + obtain ⟨p, hp⟩ := h + convert hp + obtain ⟨r, hpr⟩ := hp + ext n u + have h_fact_smul := hpr.factorial_smul 1 + simp only [FormalMultilinearSeries.apply_eq_prod_smul_coeff, Finset.prod_const, Finset.card_univ, + Fintype.card_fin, smul_eq_mul, nsmul_eq_mul, one_pow, one_mul] at h_fact_smul + simp only [FormalMultilinearSeries.apply_eq_prod_smul_coeff, + FormalMultilinearSeries.coeff_ofScalars, smul_eq_mul, mul_eq_mul_left_iff] + left + rw [div_eq_iff, mul_comm, h_fact_smul, ← iteratedDeriv_eq_iteratedFDeriv] + norm_cast + exact Nat.factorial_ne_zero _ diff --git a/Mathlib/Analysis/Complex/Basic.lean b/Mathlib/Analysis/Complex/Basic.lean index af99bc7e8dd7f..3d4217f58338e 100644 --- a/Mathlib/Analysis/Complex/Basic.lean +++ b/Mathlib/Analysis/Complex/Basic.lean @@ -177,11 +177,11 @@ theorem norm_int_of_nonneg {n : ℤ} (hn : 0 ≤ n) : ‖(n : ℂ)‖ = n := by lemma normSq_eq_norm_sq (z : ℂ) : normSq z = ‖z‖ ^ 2 := by rw [normSq_eq_abs, norm_eq_abs] -@[continuity] +@[continuity, fun_prop] theorem continuous_abs : Continuous abs := continuous_norm -@[continuity] +@[continuity, fun_prop] theorem continuous_normSq : Continuous normSq := by simpa [← normSq_eq_abs] using continuous_abs.pow 2 diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean index 45424cd36fd7d..aec0cfaa5eab1 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean @@ -73,3 +73,47 @@ theorem AnalyticOn.cpow (fs : AnalyticOn ℂ f s) (gs : AnalyticOn ℂ g s) 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) + +section ReOfReal + +variable {f : ℂ → ℂ} {s : Set ℝ} {x : ℝ} + +lemma AnalyticAt.re_ofReal (hf : AnalyticAt ℂ f x) : + AnalyticAt ℝ (fun x : ℝ ↦ (f x).re) x := + (Complex.reCLM.analyticAt _).comp (hf.restrictScalars.comp (Complex.ofRealCLM.analyticAt _)) + +lemma AnalyticAt.im_ofReal (hf : AnalyticAt ℂ f x) : + AnalyticAt ℝ (fun x : ℝ ↦ (f x).im) x := + (Complex.imCLM.analyticAt _).comp (hf.restrictScalars.comp (Complex.ofRealCLM.analyticAt _)) + +lemma AnalyticWithinAt.re_ofReal (hf : AnalyticWithinAt ℂ f (ofReal '' s) x) : + AnalyticWithinAt ℝ (fun x : ℝ ↦ (f x).re) s x := + ((Complex.reCLM.analyticWithinAt _ _).comp hf.restrictScalars (mapsTo_image f _)).comp + (Complex.ofRealCLM.analyticWithinAt _ _) (mapsTo_image ofReal s) + +lemma AnalyticWithinAt.im_ofReal (hf : AnalyticWithinAt ℂ f (ofReal '' s) x) : + AnalyticWithinAt ℝ (fun x : ℝ ↦ (f x).im) s x := + ((Complex.imCLM.analyticWithinAt _ _).comp hf.restrictScalars (mapsTo_image f _)).comp + (Complex.ofRealCLM.analyticWithinAt _ _) (mapsTo_image ofReal s) + +lemma AnalyticOn.re_ofReal (hf : AnalyticOn ℂ f (ofReal '' s)) : + AnalyticOn ℝ (fun x : ℝ ↦ (f x).re) s := + ((Complex.reCLM.analyticOn _).comp hf.restrictScalars (mapsTo_image f _)).comp + (Complex.ofRealCLM.analyticOn _) (mapsTo_image ofReal s) + +lemma AnalyticOn.im_ofReal (hf : AnalyticOn ℂ f (ofReal '' s)) : + AnalyticOn ℝ (fun x : ℝ ↦ (f x).im) s := + ((Complex.imCLM.analyticOn _).comp hf.restrictScalars (mapsTo_image f _)).comp + (Complex.ofRealCLM.analyticOn _) (mapsTo_image ofReal s) + +lemma AnalyticOnNhd.re_ofReal (hf : AnalyticOnNhd ℂ f (ofReal '' s)) : + AnalyticOnNhd ℝ (fun x : ℝ ↦ (f x).re) s := + ((Complex.reCLM.analyticOnNhd _).comp hf.restrictScalars (mapsTo_image f _)).comp + (Complex.ofRealCLM.analyticOnNhd _) (mapsTo_image ofReal s) + +lemma AnalyticOnNhd.im_ofReal (hf : AnalyticOnNhd ℂ f (ofReal '' s)) : + AnalyticOnNhd ℝ (fun x : ℝ ↦ (f x).im) s := + ((Complex.imCLM.analyticOnNhd _).comp hf.restrictScalars (mapsTo_image f _)).comp + (Complex.ofRealCLM.analyticOnNhd _) (mapsTo_image ofReal s) + +end ReOfReal diff --git a/Mathlib/MeasureTheory/Integral/SetIntegral.lean b/Mathlib/MeasureTheory/Integral/SetIntegral.lean index 0a85688f8e170..23d609eefe525 100644 --- a/Mathlib/MeasureTheory/Integral/SetIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/SetIntegral.lean @@ -1332,6 +1332,8 @@ end ContinuousMap theorem integral_ofReal {f : X → ℝ} : ∫ x, (f x : 𝕜) ∂μ = ↑(∫ x, f x ∂μ) := (@RCLike.ofRealLI 𝕜 _).integral_comp_comm f +theorem integral_complex_ofReal {f : X → ℝ} : ∫ x, (f x : ℂ) ∂μ = ∫ x, f x ∂μ := integral_ofReal + theorem integral_re {f : X → 𝕜} (hf : Integrable f μ) : ∫ x, RCLike.re (f x) ∂μ = RCLike.re (∫ x, f x ∂μ) := (@RCLike.reCLM 𝕜 _).integral_comp_comm hf diff --git a/Mathlib/Probability/Moments/Basic.lean b/Mathlib/Probability/Moments/Basic.lean index ec9aaa1d55422..edcfe1a187ce9 100644 --- a/Mathlib/Probability/Moments/Basic.lean +++ b/Mathlib/Probability/Moments/Basic.lean @@ -184,6 +184,12 @@ theorem mgf_pos [IsProbabilityMeasure μ] (h_int_X : Integrable (fun ω => exp ( 0 < mgf X μ t := mgf_pos' (IsProbabilityMeasure.ne_zero μ) h_int_X +lemma mgf_pos_iff [hμ : NeZero μ] : + 0 < mgf X μ t ↔ Integrable (fun ω ↦ exp (t * X ω)) μ := by + refine ⟨fun h ↦ ?_, fun h ↦ mgf_pos' hμ.out h⟩ + contrapose! h with h + simp [mgf_undef h] + lemma exp_cgf_of_neZero [hμ : NeZero μ] (hX : Integrable (fun ω ↦ exp (t * X ω)) μ) : exp (cgf X μ t) = mgf X μ t := by rw [cgf, exp_log (mgf_pos' hμ.out hX)] @@ -196,6 +202,11 @@ lemma mgf_id_map (hX : AEMeasurable X μ) : mgf id (μ.map X) = mgf X μ := by · rfl · exact (measurable_const_mul _).exp.aestronglyMeasurable +lemma mgf_congr_identDistrib {Ω' : Type*} {mΩ' : MeasurableSpace Ω'} {μ' : Measure Ω'} + {Y : Ω' → ℝ} (h : IdentDistrib X Y μ μ') : + mgf X μ = mgf Y μ' := by + rw [← mgf_id_map h.aemeasurable_fst, ← mgf_id_map h.aemeasurable_snd, h.map_eq] + theorem mgf_neg : mgf (-X) μ t = mgf X μ (-t) := by simp_rw [mgf, Pi.neg_apply, mul_neg, neg_mul] theorem cgf_neg : cgf (-X) μ t = cgf X μ (-t) := by simp_rw [cgf, mgf_neg] diff --git a/Mathlib/Probability/Moments/ComplexMGF.lean b/Mathlib/Probability/Moments/ComplexMGF.lean new file mode 100644 index 0000000000000..1849cec292373 --- /dev/null +++ b/Mathlib/Probability/Moments/ComplexMGF.lean @@ -0,0 +1,298 @@ +/- +Copyright (c) 2025 Rémy Degenne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Rémy Degenne +-/ +import Mathlib.Analysis.Analytic.IsolatedZeros +import Mathlib.Analysis.Calculus.ParametricIntegral +import Mathlib.Analysis.Complex.CauchyIntegral +import Mathlib.Probability.Moments.Basic +import Mathlib.Probability.Moments.IntegrableExpMul + +/-! +# The complex-valued moment generating function + +The moment generating function (mgf) is `t : ℝ ↦ μ[fun ω ↦ rexp (t * X ω)]`. It can be extended to +a complex function `z : ℂ ↦ μ[fun ω ↦ cexp (z * X ω)]`, which we call `complexMGF X μ`. +That function is holomorphic on the vertical strip with base the interior of the interval +of definition of the mgf. +On the vertical line that goes through 0, `complexMGF X μ` is equal to the characteristic function. +This allows us to link properties of the characteristic function and the mgf (mostly deducing +properties of the mgf from those of the characteristic function). + +## Main definitions + +* `complexMGF X μ`: the function `z : ℂ ↦ μ[fun ω ↦ cexp (z * X ω)]`. + +## Main results + +* `complexMGF_ofReal`: for `x : ℝ`, `complexMGF X μ x = mgf X μ x`. + +* `hasDerivAt_complexMGF`: for all `z : ℂ` such that the real part `z.re` belongs to the interior + of the interval of definition of the mgf, `complexMGF X μ` is differentiable at `z` + with derivative `μ[X * exp (z * X)]`. +* `differentiableOn_complexMGF`: `complexMGF X μ` is holomorphic on the vertical strip + `{z | z.re ∈ interior (integrableExpSet X μ)}`. +* `analyticOn_complexMGF`: `complexMGF X μ` is analytic on the vertical strip + `{z | z.re ∈ interior (integrableExpSet X μ)}`. + +* `eqOn_complexMGF_of_mgf`: if two random variables have the same moment generating function, + then they have the same `complexMGF` on the vertical strip + `{z | z.re ∈ interior (integrableExpSet X μ)}`. + Once we know that equal `mgf` implies equal distributions, we will be able to show that + the `complexMGF` are equal everywhere, not only on the strip. + This lemma will be used in the proof of the equality of distributions. + +## TODO + +Once we have a definition for the characteristic function, we will be able to prove the following. + +* `x : ℝ ↦ complexMGF X μ (I * x)` is equal to the characteristic function of + the random variable `X`. +* As a consequence, if two random variables have same `mgf`, then they have the same + characteristic function and the same distribution. + +-/ + + +open MeasureTheory Filter Finset Real Complex + +open scoped MeasureTheory ProbabilityTheory ENNReal NNReal Topology + +namespace ProbabilityTheory + +variable {Ω ι : Type*} {m : MeasurableSpace Ω} {X : Ω → ℝ} {μ : Measure Ω} {t u v : ℝ} {z ε : ℂ} + +/-- Complex extension of the moment generating function. -/ +noncomputable +def complexMGF (X : Ω → ℝ) (μ : Measure Ω) (z : ℂ) : ℂ := μ[fun ω ↦ cexp (z * X ω)] + +lemma complexMGF_undef (hX : AEMeasurable X μ) (h : ¬ Integrable (fun ω ↦ rexp (z.re * X ω)) μ) : + complexMGF X μ z = 0 := by + rw [complexMGF, integral_undef] + rw [← integrable_norm_iff (AEMeasurable.aestronglyMeasurable <| by fun_prop)] + simpa [Complex.norm_eq_abs, Complex.abs_exp] using h + +lemma complexMGF_id_map (hX : AEMeasurable X μ) : complexMGF id (μ.map X) = complexMGF X μ := by + ext t + rw [complexMGF, integral_map hX] + · rfl + · exact AEMeasurable.aestronglyMeasurable <| by fun_prop + +lemma complexMGF_congr_identDistrib {Ω' : Type*} {mΩ' : MeasurableSpace Ω'} {μ' : Measure Ω'} + {Y : Ω' → ℝ} (h : IdentDistrib X Y μ μ') : + complexMGF X μ = complexMGF Y μ' := by + rw [← complexMGF_id_map h.aemeasurable_fst, ← complexMGF_id_map h.aemeasurable_snd, h.map_eq] + +lemma abs_complexMGF_le_mgf : abs (complexMGF X μ z) ≤ mgf X μ z.re := by + rw [complexMGF, ← re_add_im z] + simp_rw [add_mul, Complex.exp_add, re_add_im, ← Complex.norm_eq_abs] + calc ‖∫ ω, cexp (z.re * X ω) * cexp (z.im * I * X ω) ∂μ‖ + _ ≤ ∫ ω, ‖cexp (z.re * X ω) * cexp (z.im * I * X ω)‖ ∂μ := norm_integral_le_integral_norm _ + _ = ∫ ω, rexp (z.re * X ω) ∂μ := by simp [Complex.abs_exp] + +lemma complexMGF_ofReal (x : ℝ) : complexMGF X μ x = mgf X μ x := by + rw [complexMGF, mgf, ← integral_complex_ofReal] + norm_cast + +lemma re_complexMGF_ofReal (x : ℝ) : (complexMGF X μ x).re = mgf X μ x := by + simp [complexMGF_ofReal] + +lemma re_complexMGF_ofReal' : (fun x : ℝ ↦ (complexMGF X μ x).re) = mgf X μ := by + ext x + exact re_complexMGF_ofReal x + +section Analytic + +/-- For `z : ℂ` with `z.re ∈ interior (integrableExpSet X μ)`, the derivative of the function +`z' ↦ μ[X ^ n * cexp (z' * X)]` at `z` is `μ[X ^ (n + 1) * cexp (z * X)]`. -/ +lemma hasDerivAt_integral_pow_mul_exp (hz : z.re ∈ interior (integrableExpSet X μ)) (n : ℕ) : + HasDerivAt (fun z ↦ μ[fun ω ↦ X ω ^ n * cexp (z * X ω)]) + μ[fun ω ↦ X ω ^ (n + 1) * cexp (z * X ω)] z := by + have hX : AEMeasurable X μ := aemeasurable_of_mem_interior_integrableExpSet hz + have hz' := hz + rw [mem_interior_iff_mem_nhds, mem_nhds_iff_exists_Ioo_subset] at hz' + obtain ⟨l, u, hlu, h_subset⟩ := hz' + let t := ((z.re - l) ⊓ (u - z.re)) / 2 + have h_pos : 0 < (z.re - l) ⊓ (u - z.re) := by simp [hlu.1, hlu.2] + have ht : 0 < t := half_pos h_pos + refine (hasDerivAt_integral_of_dominated_loc_of_deriv_le + (bound := fun ω ↦ |X ω| ^ (n + 1) * rexp (z.re * X ω + t/2 * |X ω|)) + (F := fun z ω ↦ X ω ^ n * cexp (z * X ω)) + (F' := fun z ω ↦ X ω ^ (n + 1) * cexp (z * X ω)) (half_pos ht) ?_ ?_ ?_ ?_ ?_ ?_).2 + · exact .of_forall fun z ↦ AEMeasurable.aestronglyMeasurable (by fun_prop) + · exact integrable_pow_mul_cexp_of_re_mem_interior_integrableExpSet hz n + · exact AEMeasurable.aestronglyMeasurable (by fun_prop) + · refine ae_of_all _ fun ω ε hε ↦ ?_ + simp only [norm_mul, norm_pow, norm_real, Real.norm_eq_abs, Complex.norm_eq_abs] + rw [Complex.abs_ofReal, Complex.abs_exp] + simp only [mul_re, ofReal_re, ofReal_im, mul_zero, sub_zero] + gcongr + have : ε = z + (ε - z) := by simp + rw [this, add_re, add_mul] + gcongr _ + ?_ + refine (le_abs_self _).trans ?_ + rw [abs_mul] + gcongr + refine (abs_re_le_abs _).trans ?_ + simp only [Metric.mem_ball, dist_eq_norm, Complex.norm_eq_abs] at hε + exact hε.le + · refine integrable_pow_abs_mul_exp_add_of_integrable_exp_mul ?_ ?_ ?_ ?_ (t := t) (n + 1) + · exact h_subset (add_half_inf_sub_mem_Ioo hlu) + · exact h_subset (sub_half_inf_sub_mem_Ioo hlu) + · positivity + · exact lt_of_lt_of_le (by simp [ht]) (le_abs_self _) + · refine ae_of_all _ fun ω ε hε ↦ ?_ + simp only + simp_rw [pow_succ, mul_assoc] + refine HasDerivAt.const_mul _ ?_ + simp_rw [← smul_eq_mul, Complex.exp_eq_exp_ℂ] + convert hasDerivAt_exp_smul_const (X ω : ℂ) ε using 1 + rw [smul_eq_mul, mul_comm] + +/-- For all `z : ℂ` with `z.re ∈ interior (integrableExpSet X μ)`, +`complexMGF X μ` is differentiable at `z` with derivative `μ[X * exp (z * X)]`. -/ +theorem hasDerivAt_complexMGF (hz : z.re ∈ interior (integrableExpSet X μ)) : + HasDerivAt (complexMGF X μ) μ[fun ω ↦ X ω * cexp (z * X ω)] z := by + convert hasDerivAt_integral_pow_mul_exp hz 0 + · simp [complexMGF] + · simp + +/-- `complexMGF X μ` is holomorphic on the vertical strip +`{z | z.re ∈ interior (integrableExpSet X μ)}`. -/ +theorem differentiableOn_complexMGF : + DifferentiableOn ℂ (complexMGF X μ) {z | z.re ∈ interior (integrableExpSet X μ)} := by + intro z hz + have h := hasDerivAt_complexMGF hz + rw [hasDerivAt_iff_hasFDerivAt] at h + exact h.hasFDerivWithinAt.differentiableWithinAt + +theorem analyticOnNhd_complexMGF : + AnalyticOnNhd ℂ (complexMGF X μ) {z | z.re ∈ interior (integrableExpSet X μ)} := + differentiableOn_complexMGF.analyticOnNhd (isOpen_interior.preimage Complex.continuous_re) + +/-- `complexMGF X μ` is analytic on the vertical strip + `{z | z.re ∈ interior (integrableExpSet X μ)}`. -/ +theorem analyticOn_complexMGF : + AnalyticOn ℂ (complexMGF X μ) {z | z.re ∈ interior (integrableExpSet X μ)} := + analyticOnNhd_complexMGF.analyticOn + +/-- `complexMGF X μ` is analytic at any point `z` with `z.re ∈ interior (integrableExpSet X μ)`. -/ +lemma analyticAt_complexMGF (hz : z.re ∈ interior (integrableExpSet X μ)) : + AnalyticAt ℂ (complexMGF X μ) z := + analyticOnNhd_complexMGF z hz + +end Analytic + +section Deriv + +/-! ### Iterated derivatives of `complexMGF` -/ + +lemma hasDerivAt_iteratedDeriv_complexMGF (hz : z.re ∈ interior (integrableExpSet X μ)) (n : ℕ) : + HasDerivAt (iteratedDeriv n (complexMGF X μ)) μ[fun ω ↦ X ω ^ (n + 1) * cexp (z * X ω)] z := by + induction n generalizing z with + | zero => simp [hasDerivAt_complexMGF hz] + | succ n hn => + rw [iteratedDeriv_succ] + have : deriv (iteratedDeriv n (complexMGF X μ)) + =ᶠ[𝓝 z] fun z ↦ μ[fun ω ↦ X ω ^ (n + 1) * cexp (z * X ω)] := by + have h_mem : ∀ᶠ y in 𝓝 z, y.re ∈ interior (integrableExpSet X μ) := by + refine IsOpen.eventually_mem ?_ hz + exact isOpen_interior.preimage Complex.continuous_re + filter_upwards [h_mem] with y hy using HasDerivAt.deriv (hn hy) + rw [EventuallyEq.hasDerivAt_iff this] + exact hasDerivAt_integral_pow_mul_exp hz (n + 1) + +/-- For `z : ℂ` with `z.re ∈ interior (integrableExpSet X μ)`, the n-th derivative of the function +`complexMGF X μ` at `z` is `μ[X ^ n * cexp (z * X)]`. -/ +lemma iteratedDeriv_complexMGF (hz : z.re ∈ interior (integrableExpSet X μ)) (n : ℕ) : + iteratedDeriv n (complexMGF X μ) z = μ[fun ω ↦ X ω ^ n * cexp (z * X ω)] := by + induction n generalizing z with + | zero => simp [complexMGF] + | succ n hn => + rw [iteratedDeriv_succ] + exact (hasDerivAt_iteratedDeriv_complexMGF hz n).deriv + +end Deriv + +section EqOfMGF + +/-! We prove that if two random variables have the same `mgf`, then +they also have the same `complexMGF`.-/ + +variable {Ω' : Type*} {mΩ' : MeasurableSpace Ω'} {Y : Ω' → ℝ} {μ' : Measure Ω'} + +/-- If two random variables have the same moment generating function then they have +the same `integrableExpSet`. -/ +lemma integrableExpSet_eq_of_mgf' (hXY : mgf X μ = mgf Y μ') (hμμ' : μ = 0 ↔ μ' = 0) : + integrableExpSet X μ = integrableExpSet Y μ' := by + ext t + simp only [integrableExpSet, Set.mem_setOf_eq] + by_cases hμ : μ = 0 + · simp [hμ, hμμ'.mp hμ] + have : NeZero μ := ⟨hμ⟩ + have : NeZero μ' := ⟨(not_iff_not.mpr hμμ').mp hμ⟩ + rw [← mgf_pos_iff, ← mgf_pos_iff, hXY] + +/-- If two random variables have the same moment generating function then they have +the same `integrableExpSet`. -/ +lemma integrableExpSet_eq_of_mgf [IsProbabilityMeasure μ] + (hXY : mgf X μ = mgf Y μ') : + integrableExpSet X μ = integrableExpSet Y μ' := by + refine integrableExpSet_eq_of_mgf' hXY ?_ + simp only [IsProbabilityMeasure.ne_zero, false_iff] + suffices mgf Y μ' 0 ≠ 0 by + intro h_contra + simp [h_contra] at this + rw [← hXY] + exact (mgf_pos (by simp)).ne' + +/-- If two random variables have the same moment generating function then they have +the same `complexMGF` on the vertical strip `{z | z.re ∈ interior (integrableExpSet X μ)}`. + +TODO: once we know that equal `mgf` implies equal distributions, we will be able to show that +the `complexMGF` are equal everywhere, not only on the strip. +This lemma will be used in the proof of the equality of distributions. -/ +lemma eqOn_complexMGF_of_mgf' (hXY : mgf X μ = mgf Y μ') (hμμ' : μ = 0 ↔ μ' = 0) : + Set.EqOn (complexMGF X μ) (complexMGF Y μ') {z | z.re ∈ interior (integrableExpSet X μ)} := by + by_cases h_empty : interior (integrableExpSet X μ) = ∅ + · simp [h_empty] + rw [← ne_eq, ← Set.nonempty_iff_ne_empty] at h_empty + obtain ⟨t, ht⟩ := h_empty + have hX : AnalyticOnNhd ℂ (complexMGF X μ) {z | z.re ∈ interior (integrableExpSet X μ)} := + analyticOnNhd_complexMGF + have hY : AnalyticOnNhd ℂ (complexMGF Y μ') {z | z.re ∈ interior (integrableExpSet Y μ')} := + analyticOnNhd_complexMGF + rw [integrableExpSet_eq_of_mgf' hXY hμμ'] at hX ht ⊢ + refine AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq hX hY + (convex_integrableExpSet.interior.linear_preimage reLm).isPreconnected + (z₀ := (t : ℂ)) (by simp [ht]) ?_ + have h_real : ∃ᶠ (x : ℝ) in 𝓝[≠] t, complexMGF X μ x = complexMGF Y μ' x := by + refine .of_forall fun y ↦ ?_ + rw [complexMGF_ofReal, complexMGF_ofReal, hXY] + rw [frequently_iff_seq_forall] at h_real ⊢ + obtain ⟨xs, hx_tendsto, hx_eq⟩ := h_real + refine ⟨fun n ↦ xs n, ?_, fun n ↦ ?_⟩ + · rw [tendsto_nhdsWithin_iff] at hx_tendsto ⊢ + constructor + · rw [tendsto_ofReal_iff] + exact hx_tendsto.1 + · simpa using hx_tendsto.2 + · simp [hx_eq] + +/-- If two random variables have the same moment generating function then they have +the same `complexMGF` on the vertical strip `{z | z.re ∈ interior (integrableExpSet X μ)}`. -/ +lemma eqOn_complexMGF_of_mgf [IsProbabilityMeasure μ] + (hXY : mgf X μ = mgf Y μ') : + Set.EqOn (complexMGF X μ) (complexMGF Y μ') {z | z.re ∈ interior (integrableExpSet X μ)} := by + refine eqOn_complexMGF_of_mgf' hXY ?_ + simp only [IsProbabilityMeasure.ne_zero, false_iff] + suffices mgf Y μ' 0 ≠ 0 by + intro h_contra + simp [h_contra] at this + rw [← hXY] + exact (mgf_pos (by simp)).ne' + +end EqOfMGF + +end ProbabilityTheory diff --git a/Mathlib/Probability/Moments/IntegrableExpMul.lean b/Mathlib/Probability/Moments/IntegrableExpMul.lean index f2135d63a157e..2670a7c181b61 100644 --- a/Mathlib/Probability/Moments/IntegrableExpMul.lean +++ b/Mathlib/Probability/Moments/IntegrableExpMul.lean @@ -539,6 +539,63 @@ lemma memℒp_of_mem_interior_integrableExpSet (h : 0 ∈ interior (integrableEx simp only [norm_eq_abs, ENNReal.coe_toReal] exact integrable_rpow_abs_of_mem_interior_integrableExpSet h p.2 +section Complex + +open Complex + +variable {z : ℂ} + +lemma integrable_cexp_mul_of_re_mem_integrableExpSet (hX : AEMeasurable X μ) + (hz : z.re ∈ integrableExpSet X μ) : + Integrable (fun ω ↦ cexp (z * X ω)) μ := by + rw [← integrable_norm_iff] + · simpa [Complex.norm_eq_abs, Complex.abs_exp] using hz + · exact AEMeasurable.aestronglyMeasurable (by fun_prop) + +lemma integrable_cexp_mul_of_re_mem_interior_integrableExpSet + (hz : z.re ∈ interior (integrableExpSet X μ)) : + Integrable (fun ω ↦ cexp (z * X ω)) μ := + integrable_cexp_mul_of_re_mem_integrableExpSet + (aemeasurable_of_mem_interior_integrableExpSet hz) (interior_subset hz) + +lemma integrable_rpow_abs_mul_cexp_of_re_mem_interior_integrableExpSet + (hz : z.re ∈ interior (integrableExpSet X μ)) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ (|X ω| ^ p : ℝ) * cexp (z * X ω)) μ := by + have hX : AEMeasurable X μ := aemeasurable_of_mem_interior_integrableExpSet hz + rw [← integrable_norm_iff] + swap; · exact AEMeasurable.aestronglyMeasurable (by fun_prop) + simpa [abs_rpow_of_nonneg (abs_nonneg _), Complex.abs_exp] + using integrable_rpow_abs_mul_exp_of_mem_interior_integrableExpSet hz hp + +lemma integrable_pow_abs_mul_cexp_of_re_mem_interior_integrableExpSet + (hz : z.re ∈ interior (integrableExpSet X μ)) (n : ℕ) : + Integrable (fun ω ↦ |X ω| ^ n * cexp (z * X ω)) μ := by + convert integrable_rpow_abs_mul_cexp_of_re_mem_interior_integrableExpSet hz (Nat.cast_nonneg n) + simp + +lemma integrable_rpow_mul_cexp_of_re_mem_interior_integrableExpSet + (hz : z.re ∈ interior (integrableExpSet X μ)) {p : ℝ} (hp : 0 ≤ p) : + Integrable (fun ω ↦ (X ω ^ p : ℝ) * cexp (z * X ω)) μ := by + have hX : AEMeasurable X μ := aemeasurable_of_mem_interior_integrableExpSet hz + rw [← integrable_norm_iff] + swap; · exact AEMeasurable.aestronglyMeasurable (by fun_prop) + simp only [norm_mul, norm_real, Real.norm_eq_abs, Complex.norm_eq_abs, Complex.abs_exp, mul_re, + ofReal_re, ofReal_im, mul_zero, sub_zero, Complex.abs_ofReal] + refine (integrable_rpow_abs_mul_exp_of_mem_interior_integrableExpSet hz hp).mono ?_ ?_ + · exact AEMeasurable.aestronglyMeasurable (by fun_prop) + refine ae_of_all _ fun ω ↦ ?_ + simp only [norm_mul, Real.norm_eq_abs, abs_abs, Real.abs_exp] + gcongr + exact abs_rpow_le_abs_rpow _ _ + +lemma integrable_pow_mul_cexp_of_re_mem_interior_integrableExpSet + (hz : z.re ∈ interior (integrableExpSet X μ)) (n : ℕ) : + Integrable (fun ω ↦ X ω ^ n * cexp (z * X ω)) μ := by + convert integrable_rpow_mul_cexp_of_re_mem_interior_integrableExpSet hz (Nat.cast_nonneg n) + simp + +end Complex + end IntegrableExpSet end FiniteMoments diff --git a/Mathlib/Probability/Moments/MGFAnalytic.lean b/Mathlib/Probability/Moments/MGFAnalytic.lean new file mode 100644 index 0000000000000..57f5d8242d2e6 --- /dev/null +++ b/Mathlib/Probability/Moments/MGFAnalytic.lean @@ -0,0 +1,124 @@ +/- +Copyright (c) 2025 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.Moments.ComplexMGF +import Mathlib.Analysis.SpecialFunctions.Complex.Analytic + +/-! +# The moment generating function is analytic + +The moment generating function `mgf X μ` of a random variable `X` with respect to a measure `μ` +is analytic on the interior of `integrableExpSet X μ`, the interval on which it is defined. + +## Main results + +* `analyticOn_mgf`: the moment generating function is analytic on the interior of the interval + on which it is defined. +* `iteratedDeriv_mgf`: the n-th derivative of the mgf at `t` is `μ[X ^ n * exp (t * X)]`. + +-/ + + +open MeasureTheory Filter Finset Real + +open scoped MeasureTheory ProbabilityTheory ENNReal NNReal Topology Nat + +namespace ProbabilityTheory + +variable {Ω ι : Type*} {m : MeasurableSpace Ω} {X : Ω → ℝ} {μ : Measure Ω} {t u v : ℝ} + +section Deriv + +/-- For `t : ℝ` with `t ∈ interior (integrableExpSet X μ)`, the derivative of the function +`x ↦ μ[X ^ n * rexp (x * X)]` at `t` is `μ[X ^ (n + 1) * rexp (t * X)]`. -/ +lemma hasDerivAt_integral_pow_mul_exp_real (ht : t ∈ interior (integrableExpSet X μ)) (n : ℕ) : + HasDerivAt (fun t ↦ μ[fun ω ↦ X ω ^ n * rexp (t * X ω)]) + μ[fun ω ↦ X ω ^ (n + 1) * rexp (t * X ω)] t := by + have h_re_of_mem n t (ht' : t ∈ interior (integrableExpSet X μ)) : + (∫ ω, X ω ^ n * Complex.exp (t * X ω) ∂μ).re = ∫ ω, X ω ^ n * rexp (t * X ω) ∂μ := by + rw [← RCLike.re_eq_complex_re, ← integral_re] + · norm_cast + · refine integrable_pow_mul_cexp_of_re_mem_interior_integrableExpSet ?_ n + simpa using ht' + have h_re n : ∀ᶠ t' : ℝ in 𝓝 t, (∫ ω, X ω ^ n * Complex.exp (t' * X ω) ∂μ).re + = ∫ ω, X ω ^ n * rexp (t' * X ω) ∂μ := by + filter_upwards [isOpen_interior.eventually_mem ht] with t ht' using h_re_of_mem n t ht' + rw [← EventuallyEq.hasDerivAt_iff (h_re _), ← h_re_of_mem _ t ht] + exact (hasDerivAt_integral_pow_mul_exp (by simp [ht]) n).real_of_complex + +/-- For `t ∈ interior (integrableExpSet X μ)`, the derivative of `mgf X μ` at `t` is +`μ[X * exp (t * X)]`. -/ +lemma hasDerivAt_mgf (h : t ∈ interior (integrableExpSet X μ)) : + HasDerivAt (mgf X μ) (μ[fun ω ↦ X ω * exp (t * X ω)]) t := by + convert hasDerivAt_integral_pow_mul_exp_real h 0 + · simp [mgf] + · simp + +lemma hasDerivAt_iteratedDeriv_mgf (ht : t ∈ interior (integrableExpSet X μ)) (n : ℕ) : + HasDerivAt (iteratedDeriv n (mgf X μ)) μ[fun ω ↦ X ω ^ (n + 1) * exp (t * X ω)] t := by + induction n generalizing t with + | zero => simp [hasDerivAt_mgf ht] + | succ n hn => + rw [iteratedDeriv_succ] + have : deriv (iteratedDeriv n (mgf X μ)) + =ᶠ[𝓝 t] fun t ↦ μ[fun ω ↦ X ω ^ (n + 1) * exp (t * X ω)] := by + have h_mem : ∀ᶠ y in 𝓝 t, y ∈ interior (integrableExpSet X μ) := + isOpen_interior.eventually_mem ht + filter_upwards [h_mem] with y hy using HasDerivAt.deriv (hn hy) + rw [EventuallyEq.hasDerivAt_iff this] + exact hasDerivAt_integral_pow_mul_exp_real ht (n + 1) + +/-- For `t ∈ interior (integrableExpSet X μ)`, the n-th derivative of `mgf X μ` at `t` is +`μ[X ^ n * exp (t * X)]`. -/ +lemma iteratedDeriv_mgf (ht : t ∈ interior (integrableExpSet X μ)) (n : ℕ) : + iteratedDeriv n (mgf X μ) t = μ[fun ω ↦ X ω ^ n * exp (t * X ω)] := by + induction n generalizing t with + | zero => simp [mgf] + | succ n hn => + rw [iteratedDeriv_succ] + exact (hasDerivAt_iteratedDeriv_mgf ht n).deriv + +/-- The derivatives of the moment generating function at zero are the moments. -/ +lemma iteratedDeriv_mgf_zero (h : 0 ∈ interior (integrableExpSet X μ)) (n : ℕ) : + iteratedDeriv n (mgf X μ) 0 = μ[X ^ n] := by + simp [iteratedDeriv_mgf h n] + +/-- For `t ∈ interior (integrableExpSet X μ)`, the derivative of `mgf X μ` at `t` is +`μ[X * exp (t * X)]`. -/ +lemma deriv_mgf (h : t ∈ interior (integrableExpSet X μ)) : + deriv (mgf X μ) t = μ[fun ω ↦ X ω * exp (t * X ω)] := + (hasDerivAt_mgf h).deriv + +lemma deriv_mgf_zero (h : 0 ∈ interior (integrableExpSet X μ)) : deriv (mgf X μ) 0 = μ[X] := by + simp [deriv_mgf h] + +end Deriv + +section Analytic + +/-- The moment generating function is analytic at every `t ∈ interior (integrableExpSet X μ)`. -/ +lemma analyticAt_mgf (ht : t ∈ interior (integrableExpSet X μ)) : + AnalyticAt ℝ (mgf X μ) t := by + rw [← re_complexMGF_ofReal'] + exact (analyticAt_complexMGF (by simp [ht])).re_ofReal + +lemma analyticOnNhd_mgf : AnalyticOnNhd ℝ (mgf X μ) (interior (integrableExpSet X μ)) := + fun _ hx ↦ analyticAt_mgf hx + +/-- The moment generating function is analytic on the interior of the interval on which it is +defined. -/ +lemma analyticOn_mgf : AnalyticOn ℝ (mgf X μ) (interior (integrableExpSet X μ)) := + analyticOnNhd_mgf.analyticOn + +lemma hasFPowerSeriesAt_mgf (hv : v ∈ interior (integrableExpSet X μ)) : + HasFPowerSeriesAt (mgf X μ) + (FormalMultilinearSeries.ofScalars ℝ + (fun n ↦ (μ[fun ω ↦ X ω ^ n * exp (v * X ω)] : ℝ) / n !)) v := by + convert (analyticAt_mgf hv).hasFPowerSeriesAt + rw [iteratedDeriv_mgf hv] + +end Analytic + +end ProbabilityTheory From 49af10902272915cb5d4038bfc63af004050e270 Mon Sep 17 00:00:00 2001 From: kvanvels Date: Wed, 29 Jan 2025 07:05:48 +0000 Subject: [PATCH 625/681] chore: replace open scoped Classical with open scoped Classical in or classical (#20898) reduces some technical debt by replacing "open scoped classical" with (open scoped classical in) for theorem declarations and/or adding a "classical' tactic to a tactic proof. I followed the example in PR https://github.com/leanprover-community/mathlib4/pull/20325. I made the PR smaller than before and concentrated on FieldTheory and GroupTheory files. --- Mathlib/FieldTheory/Minpoly/Basic.lean | 3 ++- Mathlib/FieldTheory/Minpoly/Field.lean | 2 +- Mathlib/FieldTheory/RatFunc/AsPolynomial.lean | 2 -- Mathlib/FieldTheory/RatFunc/Basic.lean | 15 +++++++++++++-- Mathlib/FieldTheory/RatFunc/Defs.lean | 2 -- Mathlib/GroupTheory/CommutingProbability.lean | 3 +-- Mathlib/GroupTheory/Coxeter/Length.lean | 5 ++++- Mathlib/GroupTheory/Exponent.lean | 7 +++++-- Mathlib/GroupTheory/FreeAbelianGroup.lean | 3 +-- Mathlib/GroupTheory/FreeAbelianGroupFinsupp.lean | 3 +-- .../GroupTheory/FreeGroup/NielsenSchreier.lean | 3 +-- Mathlib/GroupTheory/Nilpotent.lean | 10 ++++++++-- Mathlib/GroupTheory/Perm/ViaEmbedding.lean | 7 +++++-- Mathlib/GroupTheory/QuotientGroup/Finite.lean | 3 +-- Mathlib/GroupTheory/Schreier.lean | 3 +-- Mathlib/GroupTheory/SchurZassenhaus.lean | 2 -- 16 files changed, 44 insertions(+), 29 deletions(-) diff --git a/Mathlib/FieldTheory/Minpoly/Basic.lean b/Mathlib/FieldTheory/Minpoly/Basic.lean index 0b88000978e5f..8c19cd2535cbd 100644 --- a/Mathlib/FieldTheory/Minpoly/Basic.lean +++ b/Mathlib/FieldTheory/Minpoly/Basic.lean @@ -15,7 +15,6 @@ such as irreducibility under the assumption `B` is a domain. -/ -open scoped Classical open Polynomial Set Function variable {A B B' : Type*} @@ -24,6 +23,7 @@ section MinPolyDef variable (A) [CommRing A] [Ring B] [Algebra A B] +open scoped Classical in /-- Suppose `x : B`, where `B` is an `A`-algebra. The minimal polynomial `minpoly A x` of `x` @@ -64,6 +64,7 @@ theorem ne_zero_iff [Nontrivial A] : minpoly A x ≠ 0 ↔ IsIntegral A x := theorem algHom_eq (f : B →ₐ[A] B') (hf : Function.Injective f) (x : B) : minpoly A (f x) = minpoly A x := by + classical simp_rw [minpoly, isIntegral_algHom_iff _ hf, ← Polynomial.aeval_def, aeval_algHom, AlgHom.comp_apply, _root_.map_eq_zero_iff f hf] diff --git a/Mathlib/FieldTheory/Minpoly/Field.lean b/Mathlib/FieldTheory/Minpoly/Field.lean index 0652b50888c6b..b3f90cac4e69d 100644 --- a/Mathlib/FieldTheory/Minpoly/Field.lean +++ b/Mathlib/FieldTheory/Minpoly/Field.lean @@ -18,7 +18,6 @@ are irreducible, and uniquely determined by their defining property. -/ -open scoped Classical open Polynomial Set Function minpoly namespace minpoly @@ -181,6 +180,7 @@ theorem neg {B : Type*} [CommRing B] [Algebra A B] (x : B) : section AlgHomFintype +open scoped Classical in /-- A technical finiteness result. -/ noncomputable def Fintype.subtypeProd {E : Type*} {X : Set E} (hX : X.Finite) {L : Type*} (F : E → Multiset L) : Fintype (∀ x : X, { l : L // l ∈ F x }) := diff --git a/Mathlib/FieldTheory/RatFunc/AsPolynomial.lean b/Mathlib/FieldTheory/RatFunc/AsPolynomial.lean index 14a02db0ca588..5c4ceecc798cc 100644 --- a/Mathlib/FieldTheory/RatFunc/AsPolynomial.lean +++ b/Mathlib/FieldTheory/RatFunc/AsPolynomial.lean @@ -32,8 +32,6 @@ namespace RatFunc section Eval -open scoped Classical - open scoped nonZeroDivisors Polynomial open RatFunc diff --git a/Mathlib/FieldTheory/RatFunc/Basic.lean b/Mathlib/FieldTheory/RatFunc/Basic.lean index c5ca7de7845f5..9a1cde7fbd08b 100644 --- a/Mathlib/FieldTheory/RatFunc/Basic.lean +++ b/Mathlib/FieldTheory/RatFunc/Basic.lean @@ -48,8 +48,6 @@ universe u v noncomputable section -open scoped Classical - open scoped nonZeroDivisors Polynomial variable {K : Type u} @@ -320,6 +318,8 @@ open RatFunc variable {G₀ L R S F : Type*} [CommGroupWithZero G₀] [Field L] [CommRing R] [CommRing S] variable [FunLike F R[X] S[X]] + +open scoped Classical in /-- Lift a monoid homomorphism that maps polynomials `φ : R[X] →* S[X]` to a `RatFunc R →* RatFunc S`, on the condition that `φ` maps non zero divisors to non zero divisors, @@ -741,6 +741,7 @@ open GCDMonoid Polynomial variable [Field K] +open scoped Classical in /-- `RatFunc.numDenom` are numerator and denominator of a rational function over a field, normalized such that the denominator is monic. -/ def numDenom (x : RatFunc K) : K[X] × K[X] := @@ -775,6 +776,7 @@ def numDenom (x : RatFunc K) : K[X] × K[X] := rw [inv_div, mul_comm, mul_div_assoc, ← mul_assoc, inv_inv, mul_inv_cancel₀ ha', one_mul, inv_div]) +open scoped Classical in @[simp] theorem numDenom_div (p : K[X]) {q : K[X]} (hq : q ≠ 0) : numDenom (algebraMap _ _ p / algebraMap _ _ q) = @@ -790,6 +792,7 @@ normalized such that the denominator is monic. -/ def num (x : RatFunc K) : K[X] := x.numDenom.1 +open scoped Classical in private theorem num_div' (p : K[X]) {q : K[X]} (hq : q ≠ 0) : num (algebraMap _ _ p / algebraMap _ _ q) = Polynomial.C (q / gcd p q).leadingCoeff⁻¹ * (p / gcd p q) := by @@ -798,6 +801,7 @@ private theorem num_div' (p : K[X]) {q : K[X]} (hq : q ≠ 0) : @[simp] theorem num_zero : num (0 : RatFunc K) = 0 := by convert num_div' (0 : K[X]) one_ne_zero <;> simp +open scoped Classical in @[simp] theorem num_div (p q : K[X]) : num (algebraMap _ _ p / algebraMap _ _ q) = @@ -814,10 +818,12 @@ theorem num_algebraMap (p : K[X]) : num (algebraMap _ _ p) = p := by convert num theorem num_div_dvd (p : K[X]) {q : K[X]} (hq : q ≠ 0) : num (algebraMap _ _ p / algebraMap _ _ q) ∣ p := by + classical rw [num_div _ q, C_mul_dvd] · exact EuclideanDomain.div_dvd_of_dvd (gcd_dvd_left p q) · simpa only [Ne, inv_eq_zero, Polynomial.leadingCoeff_eq_zero] using right_div_gcd_ne_zero hq +open scoped Classical in /-- A version of `num_div_dvd` with the LHS in simp normal form -/ @[simp] theorem num_div_dvd' (p : K[X]) {q : K[X]} (hq : q ≠ 0) : @@ -828,6 +834,7 @@ normalized such that it is monic. -/ def denom (x : RatFunc K) : K[X] := x.numDenom.2 +open scoped Classical in @[simp] theorem denom_div (p : K[X]) {q : K[X]} (hq : q ≠ 0) : denom (algebraMap _ _ p / algebraMap _ _ q) = @@ -835,6 +842,7 @@ theorem denom_div (p : K[X]) {q : K[X]} (hq : q ≠ 0) : rw [denom, numDenom_div _ hq] theorem monic_denom (x : RatFunc K) : (denom x).Monic := by + classical induction x using RatFunc.induction_on with | f p q hq => rw [denom_div p hq, mul_comm] @@ -857,6 +865,7 @@ theorem denom_algebraMap (p : K[X]) : denom (algebraMap _ (RatFunc K) p) = 1 := @[simp] theorem denom_div_dvd (p q : K[X]) : denom (algebraMap _ _ p / algebraMap _ _ q) ∣ q := by + classical by_cases hq : q = 0 · simp [hq] rw [denom_div _ hq, C_mul_dvd] @@ -865,6 +874,7 @@ theorem denom_div_dvd (p q : K[X]) : denom (algebraMap _ _ p / algebraMap _ _ q) @[simp] theorem num_div_denom (x : RatFunc K) : algebraMap _ _ (num x) / algebraMap _ _ (denom x) = x := by + classical induction' x using RatFunc.induction_on with p q hq have q_div_ne_zero : q / gcd p q ≠ 0 := right_div_gcd_ne_zero hq rw [num_div p q, denom_div p hq, RingHom.map_mul, RingHom.map_mul, mul_div_mul_left, @@ -878,6 +888,7 @@ theorem num_div_denom (x : RatFunc K) : algebraMap _ _ (num x) / algebraMap _ _ exact inv_ne_zero (Polynomial.leadingCoeff_ne_zero.mpr q_div_ne_zero) theorem isCoprime_num_denom (x : RatFunc K) : IsCoprime x.num x.denom := by + classical induction' x using RatFunc.induction_on with p q hq rw [num_div, denom_div _ hq] exact (isCoprime_mul_unit_left diff --git a/Mathlib/FieldTheory/RatFunc/Defs.lean b/Mathlib/FieldTheory/RatFunc/Defs.lean index a0e7e1e83de5b..c3fc63ae2deaa 100644 --- a/Mathlib/FieldTheory/RatFunc/Defs.lean +++ b/Mathlib/FieldTheory/RatFunc/Defs.lean @@ -48,8 +48,6 @@ the codomain is not a field or even an integral domain. noncomputable section -open scoped Classical - open scoped nonZeroDivisors Polynomial universe u v diff --git a/Mathlib/GroupTheory/CommutingProbability.lean b/Mathlib/GroupTheory/CommutingProbability.lean index 606360fa0cce6..815d7acb04b4e 100644 --- a/Mathlib/GroupTheory/CommutingProbability.lean +++ b/Mathlib/GroupTheory/CommutingProbability.lean @@ -26,8 +26,6 @@ assert_not_exists Ideal TwoSidedIdeal noncomputable section -open scoped Classical - open Fintype variable (M : Type*) [Mul M] @@ -79,6 +77,7 @@ variable {M} theorem commProb_eq_one_iff [h : Nonempty M] : commProb M = 1 ↔ Std.Commutative ((· * ·) : M → M → M) := by + classical haveI := Fintype.ofFinite M rw [commProb, ← Set.coe_setOf, Nat.card_eq_fintype_card, Nat.card_eq_fintype_card] rw [div_eq_one_iff_eq, ← Nat.cast_pow, Nat.cast_inj, sq, ← card_prod, diff --git a/Mathlib/GroupTheory/Coxeter/Length.lean b/Mathlib/GroupTheory/Coxeter/Length.lean index aff28c1d3b685..c987abb55aa89 100644 --- a/Mathlib/GroupTheory/Coxeter/Length.lean +++ b/Mathlib/GroupTheory/Coxeter/Length.lean @@ -50,7 +50,7 @@ assert_not_exists TwoSidedIdeal namespace CoxeterSystem -open List Matrix Function Classical +open List Matrix Function variable {B : Type*} variable {W : Type*} [Group W] @@ -65,6 +65,7 @@ private theorem exists_word_with_prod (w : W) : ∃ n ω, ω.length = n ∧ π rcases cs.wordProd_surjective w with ⟨ω, rfl⟩ use ω.length, ω +open scoped Classical in /-- The length of `w`; i.e., the minimum number of simple reflections that must be multiplied to form `w`. -/ noncomputable def length (w : W) : ℕ := Nat.find (cs.exists_word_with_prod w) @@ -72,9 +73,11 @@ noncomputable def length (w : W) : ℕ := Nat.find (cs.exists_word_with_prod w) local prefix:100 "ℓ" => cs.length theorem exists_reduced_word (w : W) : ∃ ω, ω.length = ℓ w ∧ w = π ω := by + classical have := Nat.find_spec (cs.exists_word_with_prod w) tauto +open scoped Classical in theorem length_wordProd_le (ω : List B) : ℓ (π ω) ≤ ω.length := Nat.find_min' (cs.exists_word_with_prod (π ω)) ⟨ω, by tauto⟩ diff --git a/Mathlib/GroupTheory/Exponent.lean b/Mathlib/GroupTheory/Exponent.lean index 8adffc6d68bd0..0aa68664c8997 100644 --- a/Mathlib/GroupTheory/Exponent.lean +++ b/Mathlib/GroupTheory/Exponent.lean @@ -47,8 +47,6 @@ universe u variable {G : Type u} -open scoped Classical - namespace Monoid section Monoid @@ -63,6 +61,7 @@ variable (G) [Monoid G] def ExponentExists := ∃ n, 0 < n ∧ ∀ g : G, g ^ n = 1 +open scoped Classical in /-- The exponent of a group is the smallest positive integer `n` such that `g ^ n = 1` for all `g ∈ G` if it exists, otherwise it is zero by convention. -/ @[to_additive @@ -132,6 +131,7 @@ theorem exponent_eq_zero_iff_forall : exponent G = 0 ↔ ∀ n > 0, ∃ g : G, g @[to_additive exponent_nsmul_eq_zero] theorem pow_exponent_eq_one (g : G) : g ^ exponent G = 1 := by + classical by_cases h : ExponentExists G · simp_rw [exponent, dif_pos h] exact (Nat.find_spec h).2 g @@ -150,6 +150,7 @@ theorem exponent_pos_of_exists (n : ℕ) (hpos : 0 < n) (hG : ∀ g : G, g ^ n = @[to_additive] theorem exponent_min' (n : ℕ) (hpos : 0 < n) (hG : ∀ g : G, g ^ n = 1) : exponent G ≤ n := by + classical rw [exponent, dif_pos] · apply Nat.find_min' exact ⟨hpos, hG⟩ @@ -467,6 +468,7 @@ theorem exponent_eq_iSup_orderOf (h : ∀ g : G, 0 < orderOf g) : simp_rw [Set.mem_range, exists_exists_eq_and] exact ⟨g, hx⟩ +open scoped Classical in @[to_additive] theorem exponent_eq_iSup_orderOf' : exponent G = if ∃ g : G, orderOf g = 0 then 0 else ⨆ g : G, orderOf g := by @@ -541,6 +543,7 @@ open Finset Monoid @[to_additive] theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoid (M i)] {j : ι} (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by + classical rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢ push_neg at hj ⊢ peel hj with n hn _ diff --git a/Mathlib/GroupTheory/FreeAbelianGroup.lean b/Mathlib/GroupTheory/FreeAbelianGroup.lean index 030548d59fea5..60054af51dd65 100644 --- a/Mathlib/GroupTheory/FreeAbelianGroup.lean +++ b/Mathlib/GroupTheory/FreeAbelianGroup.lean @@ -129,8 +129,7 @@ end lift section -open scoped Classical - +open scoped Classical in theorem of_injective : Function.Injective (of : α → FreeAbelianGroup α) := fun x y hoxy ↦ Classical.by_contradiction fun hxy : x ≠ y ↦ let f : FreeAbelianGroup α →+ ℤ := lift fun z ↦ if x = z then (1 : ℤ) else 0 diff --git a/Mathlib/GroupTheory/FreeAbelianGroupFinsupp.lean b/Mathlib/GroupTheory/FreeAbelianGroupFinsupp.lean index 477433e03185a..95d573ec602a6 100644 --- a/Mathlib/GroupTheory/FreeAbelianGroupFinsupp.lean +++ b/Mathlib/GroupTheory/FreeAbelianGroupFinsupp.lean @@ -161,8 +161,7 @@ theorem support_nsmul (k : ℕ) (h : k ≠ 0) (a : FreeAbelianGroup X) : apply support_zsmul k _ a exact mod_cast h -open scoped Classical - +open scoped Classical in theorem support_add (a b : FreeAbelianGroup X) : support (a + b) ⊆ a.support ∪ b.support := by simp only [support, AddMonoidHom.map_add] apply Finsupp.support_add diff --git a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean index 2343d928c711c..7cb094aec1a0f 100644 --- a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean +++ b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean @@ -50,8 +50,6 @@ free group, free groupoid, Nielsen-Schreier noncomputable section -open scoped Classical - universe v u /- Porting note: ./././Mathport/Syntax/Translate/Command.lean:229:11:unsupported: @@ -210,6 +208,7 @@ def functorOfMonoidHom {X} [Monoid X] (f : End (root' T) →* X) : rw [comp_as_mul, ← f.map_mul] simp only [IsIso.inv_hom_id_assoc, loopOfHom, End.mul_def, Category.assoc] +open scoped Classical in /-- Given a free groupoid and an arborescence of its generating quiver, the vertex group at the root is freely generated by loops coming from generating arrows in the complement of the tree. -/ diff --git a/Mathlib/GroupTheory/Nilpotent.lean b/Mathlib/GroupTheory/Nilpotent.lean index 2b1d6262d8668..8c188f330ea88 100644 --- a/Mathlib/GroupTheory/Nilpotent.lean +++ b/Mathlib/GroupTheory/Nilpotent.lean @@ -355,23 +355,24 @@ theorem nilpotent_iff_lowerCentralSeries : IsNilpotent G ↔ ∃ n, lowerCentral section Classical -open scoped Classical - variable [hG : IsNilpotent G] variable (G) +open scoped Classical in /-- The nilpotency class of a nilpotent group is the smallest natural `n` such that the `n`'th term of the upper central series is `G`. -/ noncomputable def Group.nilpotencyClass : ℕ := Nat.find (IsNilpotent.nilpotent G) variable {G} +open scoped Classical in @[simp] theorem upperCentralSeries_nilpotencyClass : upperCentralSeries G (Group.nilpotencyClass G) = ⊤ := Nat.find_spec (IsNilpotent.nilpotent G) theorem upperCentralSeries_eq_top_iff_nilpotencyClass_le {n : ℕ} : upperCentralSeries G n = ⊤ ↔ Group.nilpotencyClass G ≤ n := by + classical constructor · intro h exact Nat.find_le h @@ -379,6 +380,7 @@ theorem upperCentralSeries_eq_top_iff_nilpotencyClass_le {n : ℕ} : rw [eq_top_iff, ← upperCentralSeries_nilpotencyClass] exact upperCentralSeries_mono _ h +open scoped Classical in /-- The nilpotency class of a nilpotent `G` is equal to the smallest `n` for which an ascending central series reaches `G` in its `n`'th term. -/ theorem least_ascending_central_series_length_eq_nilpotencyClass : @@ -391,6 +393,7 @@ theorem least_ascending_central_series_length_eq_nilpotencyClass : rw [← top_le_iff, ← hn] exact ascending_central_series_le_upper H hH n +open scoped Classical in /-- The nilpotency class of a nilpotent `G` is equal to the smallest `n` for which the descending central series reaches `⊥` in its `n`'th term. -/ theorem least_descending_central_series_length_eq_nilpotencyClass : @@ -409,6 +412,7 @@ theorem least_descending_central_series_length_eq_nilpotencyClass : rw [tsub_self] exact hH.1 +open scoped Classical in /-- The nilpotency class of a nilpotent `G` is equal to the length of the lower central series. -/ theorem lowerCentralSeries_length_eq_nilpotencyClass : Nat.find (nilpotent_iff_lowerCentralSeries.mp hG) = Group.nilpotencyClass (G := G) := by @@ -423,11 +427,13 @@ theorem lowerCentralSeries_length_eq_nilpotencyClass : @[simp] theorem lowerCentralSeries_nilpotencyClass : lowerCentralSeries G (Group.nilpotencyClass G) = ⊥ := by + classical rw [← lowerCentralSeries_length_eq_nilpotencyClass] exact Nat.find_spec (nilpotent_iff_lowerCentralSeries.mp hG) theorem lowerCentralSeries_eq_bot_iff_nilpotencyClass_le {n : ℕ} : lowerCentralSeries G n = ⊥ ↔ Group.nilpotencyClass G ≤ n := by + classical constructor · intro h rw [← lowerCentralSeries_length_eq_nilpotencyClass] diff --git a/Mathlib/GroupTheory/Perm/ViaEmbedding.lean b/Mathlib/GroupTheory/Perm/ViaEmbedding.lean index 4d0a88429acab..7193c769d6b76 100644 --- a/Mathlib/GroupTheory/Perm/ViaEmbedding.lean +++ b/Mathlib/GroupTheory/Perm/ViaEmbedding.lean @@ -19,18 +19,20 @@ namespace Perm variable (e : Perm α) (ι : α ↪ β) -open scoped Classical - +open scoped Classical in /-- Noncomputable version of `Equiv.Perm.viaFintypeEmbedding` that does not assume `Fintype` -/ noncomputable def viaEmbedding : Perm β := extendDomain e (ofInjective ι.1 ι.2) +open scoped Classical in theorem viaEmbedding_apply (x : α) : e.viaEmbedding ι (ι x) = ι (e x) := extendDomain_apply_image e (ofInjective ι.1 ι.2) x +open scoped Classical in theorem viaEmbedding_apply_of_not_mem (x : β) (hx : x ∉ Set.range ι) : e.viaEmbedding ι x = x := extendDomain_apply_not_subtype e (ofInjective ι.1 ι.2) hx +open scoped Classical in /-- `viaEmbedding` as a group homomorphism -/ noncomputable def viaEmbeddingHom : Perm α →* Perm β := extendDomainHom (ofInjective ι.1 ι.2) @@ -38,6 +40,7 @@ noncomputable def viaEmbeddingHom : Perm α →* Perm β := theorem viaEmbeddingHom_apply : viaEmbeddingHom ι e = viaEmbedding e ι := rfl +open scoped Classical in theorem viaEmbeddingHom_injective : Function.Injective (viaEmbeddingHom ι) := extendDomainHom_injective (ofInjective ι.1 ι.2) diff --git a/Mathlib/GroupTheory/QuotientGroup/Finite.lean b/Mathlib/GroupTheory/QuotientGroup/Finite.lean index d21f2e376e373..c27b649ddef25 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Finite.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Finite.lean @@ -20,13 +20,12 @@ universe u v w x namespace Group -open scoped Classical - open QuotientGroup Subgroup variable {F G H : Type u} [Group F] [Group G] [Group H] [Fintype F] [Fintype H] variable (f : F →* G) (g : G →* H) +open scoped Classical in /-- If `F` and `H` are finite such that `ker(G →* H) ≤ im(F →* G)`, then `G` is finite. -/ @[to_additive "If `F` and `H` are finite such that `ker(G →+ H) ≤ im(F →+ G)`, then `G` is finite."] noncomputable def fintypeOfKerLeRange (h : g.ker ≤ f.range) : Fintype G := diff --git a/Mathlib/GroupTheory/Schreier.lean b/Mathlib/GroupTheory/Schreier.lean index d7bbfc3d60879..b0d77367ab543 100644 --- a/Mathlib/GroupTheory/Schreier.lean +++ b/Mathlib/GroupTheory/Schreier.lean @@ -29,12 +29,11 @@ section CommGroup open Subgroup -open scoped Classical - variable (G : Type*) [CommGroup G] [Group.FG G] @[to_additive] theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by + classical obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const] let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _ diff --git a/Mathlib/GroupTheory/SchurZassenhaus.lean b/Mathlib/GroupTheory/SchurZassenhaus.lean index b36b24b2c9fa8..0611210466d31 100644 --- a/Mathlib/GroupTheory/SchurZassenhaus.lean +++ b/Mathlib/GroupTheory/SchurZassenhaus.lean @@ -117,8 +117,6 @@ private theorem exists_right_complement'_of_coprime_aux (hH : Nat.Coprime (Nat.c end SchurZassenhausAbelian -open scoped Classical - universe u namespace SchurZassenhausInduction From ae5c229a7745fea2de04d7244f6ba39895112046 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Wed, 29 Jan 2025 07:42:24 +0000 Subject: [PATCH 626/681] chore: process some adaptation notes (#21209) --- Mathlib/Algebra/Lie/CartanExists.lean | 2 -- .../Sites/Coherent/SheafComparison.lean | 16 ++-------------- Mathlib/CategoryTheory/Sites/Grothendieck.lean | 8 +------- Mathlib/Data/DFinsupp/Order.lean | 9 +-------- 4 files changed, 4 insertions(+), 31 deletions(-) diff --git a/Mathlib/Algebra/Lie/CartanExists.lean b/Mathlib/Algebra/Lie/CartanExists.lean index 4e3acbb133d81..4574da2c84187 100644 --- a/Mathlib/Algebra/Lie/CartanExists.lean +++ b/Mathlib/Algebra/Lie/CartanExists.lean @@ -119,8 +119,6 @@ variable {K L : Type*} [Field K] [LieRing L] [LieAlgebra K L] [Module.Finite K L open Module LieSubalgebra LieSubmodule Polynomial Cardinal LieModule engel_isBot_of_isMin -#adaptation_note /-- otherwise there is a spurious warning on `contrapose!` below. -/ -set_option linter.unusedVariables false in /-- Let `L` be a Lie algebra of dimension `n` over a field `K` with at least `n` elements. Given a Lie subalgebra `U` of `L`, and an element `x ∈ U` such that `U ≤ engel K x`. Suppose that `engel K x` is minimal amongst the Engel subalgebras `engel K y` for `y ∈ U`. diff --git a/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean b/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean index 5137ac167f17e..820d2cdb384be 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean @@ -87,13 +87,7 @@ instance : haveI := F.reflects_precoherent; F.IsDenseSubsite (coherentTopology C) (coherentTopology D) where functorPushforward_mem_iff := by rw [eq_induced F] - #adaptation_note - /-- - This proof used to be `rfl`, - but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. - It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 - -/ - exact Iff.rfl + rfl lemma coverPreserving : haveI := F.reflects_precoherent CoverPreserving (coherentTopology _) (coherentTopology _) F := @@ -191,13 +185,7 @@ instance : haveI := F.reflects_preregular; F.IsDenseSubsite (regularTopology C) (regularTopology D) where functorPushforward_mem_iff := by rw [eq_induced F] - #adaptation_note - /-- - This proof used to be `rfl`, - but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. - It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 - -/ - exact Iff.rfl + rfl lemma coverPreserving : haveI := F.reflects_preregular CoverPreserving (regularTopology _) (regularTopology _) F := diff --git a/Mathlib/CategoryTheory/Sites/Grothendieck.lean b/Mathlib/CategoryTheory/Sites/Grothendieck.lean index 816a9f82f51ce..d581e6a006f6a 100644 --- a/Mathlib/CategoryTheory/Sites/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Sites/Grothendieck.lean @@ -265,13 +265,7 @@ lemma mem_sInf (s : Set (GrothendieckTopology C)) {X : C} (S : Sieve X) : @[stacks 00Z7] theorem isGLB_sInf (s : Set (GrothendieckTopology C)) : IsGLB s (sInf s) := by refine @IsGLB.of_image _ _ _ _ sieves ?_ _ _ ?_ - · #adaptation_note - /-- - This proof used to be `rfl`, - but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. - It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 - -/ - exact Iff.rfl + · rfl · exact _root_.isGLB_sInf _ /-- Construct a complete lattice from the `Inf`, but make the trivial and discrete topologies diff --git a/Mathlib/Data/DFinsupp/Order.lean b/Mathlib/Data/DFinsupp/Order.lean index 9201ee22c9791..0ea38f0ada120 100644 --- a/Mathlib/Data/DFinsupp/Order.lean +++ b/Mathlib/Data/DFinsupp/Order.lean @@ -44,14 +44,7 @@ lemma le_def : f ≤ g ↔ ∀ i, f i ≤ g i := Iff.rfl def orderEmbeddingToFun : (Π₀ i, α i) ↪o ∀ i, α i where toFun := DFunLike.coe inj' := DFunLike.coe_injective - map_rel_iff' := - #adaptation_note - /-- - This proof used to be `rfl`, - but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. - It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 - -/ - Iff.rfl + map_rel_iff' := Iff.rfl @[simp, norm_cast] lemma coe_orderEmbeddingToFun : ⇑(orderEmbeddingToFun (α := α)) = DFunLike.coe := rfl From 4e771ba3e24c73e489012dd11b189e55723b440e Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 29 Jan 2025 08:03:56 +0000 Subject: [PATCH 627/681] chore: deprecate unused material about `List.mapIdx` (#21201) As of 2025-01-29, these specification lemmas for `List.mapIdx`, `List.mapIdxM`, `List.foldlIdx` and `List.foldrIdx` are not used anywhere in Mathlib. Moreover, with `List.enum` and `List.enumFrom` being replaced by `List.zipIdx` in Lean's `nightly-2025-01-29` release, they now use deprecated functions and theorems. Rather than updating this unused material, we are deprecating it. Anyone wanting to restore this material is welcome to do so, but will need to update uses of `List.enum` and `List.enumFrom` to use `List.zipIdx` instead. However, note that this material will later be implemented in the Lean standard library. --- Mathlib/Data/List/Indexes.lean | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/Mathlib/Data/List/Indexes.lean b/Mathlib/Data/List/Indexes.lean index 6d8b49e231af6..e307495cd9f2c 100644 --- a/Mathlib/Data/List/Indexes.lean +++ b/Mathlib/Data/List/Indexes.lean @@ -9,6 +9,14 @@ import Mathlib.Data.List.Basic # Lemmas about List.*Idx functions. Some specification lemmas for `List.mapIdx`, `List.mapIdxM`, `List.foldlIdx` and `List.foldrIdx`. + +As of 2025-01-29, these are not used anywhere in Mathlib. Moreover, with +`List.enum` and `List.enumFrom` being replaced by `List.zipIdx` +in Lean's `nightly-2025-01-29` release, they now use deprecated functions and theorems. +Rather than updating this unused material, we are deprecating it. +Anyone wanting to restore this material is welcome to do so, but will need to update uses of +`List.enum` and `List.enumFrom` to use `List.zipIdx` instead. +However, note that this material will later be implemented in the Lean standard library. -/ assert_not_exists MonoidWithZero @@ -34,7 +42,7 @@ theorem mapIdx_append_one : ∀ {f : ℕ → α → β} {l : List α} {e : α}, mapIdx f (l ++ [e]) = mapIdx f l ++ [f l.length e] := mapIdx_concat -@[local simp] +@[deprecated "Deprecated without replacement." (since := "2025-01-29"), local simp] theorem map_enumFrom_eq_zipWith : ∀ (l : List α) (n : ℕ) (f : ℕ → α → β), map (uncurry f) (enumFrom n l) = zipWith (fun i ↦ f (i + n)) (range (length l)) l := by intro l @@ -60,6 +68,7 @@ theorem map_enumFrom_eq_zipWith : ∀ (l : List α) (n : ℕ) (f : ℕ → α @[deprecated (since := "2024-10-15")] alias mapIdx_eq_nil := mapIdx_eq_nil_iff +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem get_mapIdx (l : List α) (f : ℕ → α → β) (i : ℕ) (h : i < l.length) (h' : i < (l.mapIdx f).length := h.trans_le length_mapIdx.ge) : (l.mapIdx f).get ⟨i, h'⟩ = f i (l.get ⟨i, h⟩) := by @@ -152,30 +161,41 @@ section FoldrIdx -- Porting note: Changed argument order of `foldrIdxSpec` to align better with `foldrIdx`. /-- Specification of `foldrIdx`. -/ +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] def foldrIdxSpec (f : ℕ → α → β → β) (b : β) (as : List α) (start : ℕ) : β := foldr (uncurry f) b <| enumFrom start as +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldrIdxSpec_cons (f : ℕ → α → β → β) (b a as start) : foldrIdxSpec f b (a :: as) start = f start a (foldrIdxSpec f b as (start + 1)) := rfl +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldrIdx_eq_foldrIdxSpec (f : ℕ → α → β → β) (b as start) : foldrIdx f b as start = foldrIdxSpec f b as start := by induction as generalizing start · rfl · simp only [foldrIdx, foldrIdxSpec_cons, *] +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldrIdx_eq_foldr_enum (f : ℕ → α → β → β) (b : β) (as : List α) : foldrIdx f b as = foldr (uncurry f) b (enum as) := by simp only [foldrIdx, foldrIdxSpec, foldrIdx_eq_foldrIdxSpec, enum] end FoldrIdx +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem indexesValues_eq_filter_enum (p : α → Prop) [DecidablePred p] (as : List α) : indexesValues p as = filter (p ∘ Prod.snd) (enum as) := by simp (config := { unfoldPartialApp := true }) [indexesValues, foldrIdx_eq_foldr_enum, uncurry, filter_eq_foldr, cond_eq_if] +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem findIdxs_eq_map_indexesValues (p : α → Prop) [DecidablePred p] (as : List α) : findIdxs p as = map Prod.fst (indexesValues p as) := by simp (config := { unfoldPartialApp := true }) only [indexesValues_eq_filter_enum, @@ -186,19 +206,26 @@ section FoldlIdx -- Porting note: Changed argument order of `foldlIdxSpec` to align better with `foldlIdx`. /-- Specification of `foldlIdx`. -/ +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] def foldlIdxSpec (f : ℕ → α → β → α) (a : α) (bs : List β) (start : ℕ) : α := foldl (fun a p ↦ f p.fst a p.snd) a <| enumFrom start bs +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldlIdxSpec_cons (f : ℕ → α → β → α) (a b bs start) : foldlIdxSpec f a (b :: bs) start = foldlIdxSpec f (f start a b) bs (start + 1) := rfl +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldlIdx_eq_foldlIdxSpec (f : ℕ → α → β → α) (a bs start) : foldlIdx f a bs start = foldlIdxSpec f a bs start := by induction bs generalizing start a · rfl · simp [foldlIdxSpec, *] +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldlIdx_eq_foldl_enum (f : ℕ → α → β → α) (a : α) (bs : List β) : foldlIdx f a bs = foldl (fun a p ↦ f p.fst a p.snd) a (enum bs) := by simp only [foldlIdx, foldlIdxSpec, foldlIdx_eq_foldlIdxSpec, enum] @@ -210,11 +237,15 @@ section FoldIdxM -- Porting note: `foldrM_eq_foldr` now depends on `[LawfulMonad m]` variable {m : Type u → Type v} [Monad m] +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldrIdxM_eq_foldrM_enum {β} (f : ℕ → α → β → m β) (b : β) (as : List α) [LawfulMonad m] : foldrIdxM f b as = foldrM (uncurry f) b (enum as) := by simp (config := { unfoldPartialApp := true }) only [foldrIdxM, foldrM_eq_foldr, foldrIdx_eq_foldr_enum, uncurry] +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem foldlIdxM_eq_foldlM_enum [LawfulMonad m] {β} (f : ℕ → β → α → m β) (b : β) (as : List α) : foldlIdxM f b as = List.foldlM (fun b p ↦ f p.fst b p.snd) b (enum as) := by rw [foldlIdxM, foldlM_eq_foldl, foldlIdx_eq_foldl_enum] @@ -227,15 +258,20 @@ section MapIdxM variable {m : Type u → Type v} [Monad m] /-- Specification of `mapIdxMAux`. -/ +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] def mapIdxMAuxSpec {β} (f : ℕ → α → m β) (start : ℕ) (as : List α) : m (List β) := List.traverse (uncurry f) <| enumFrom start as -- Note: `traverse` the class method would require a less universe-polymorphic -- `m : Type u → Type u`. +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem mapIdxMAuxSpec_cons {β} (f : ℕ → α → m β) (start : ℕ) (a : α) (as : List α) : mapIdxMAuxSpec f start (a :: as) = cons <$> f start a <*> mapIdxMAuxSpec f (start + 1) as := rfl +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem mapIdxMGo_eq_mapIdxMAuxSpec [LawfulMonad m] {β} (f : ℕ → α → m β) (arr : Array β) (as : List α) : mapIdxM.go f as arr = (arr.toList ++ ·) <$> mapIdxMAuxSpec f arr.size as := by @@ -259,6 +295,8 @@ theorem mapIdxMGo_eq_mapIdxMAuxSpec simp only [Array.push_toList, append_assoc, singleton_append, Array.size_push, map_eq_pure_bind] +set_option linter.deprecated false in +@[deprecated "Deprecated without replacement." (since := "2025-01-29")] theorem mapIdxM_eq_mmap_enum [LawfulMonad m] {β} (f : ℕ → α → m β) (as : List α) : as.mapIdxM f = List.traverse (uncurry f) (enum as) := by simp only [mapIdxM, mapIdxMGo_eq_mapIdxMAuxSpec, Array.toList_toArray, From b69a633357a217d3a5ecb9a74830fdd59f81616c Mon Sep 17 00:00:00 2001 From: damiano Date: Wed, 29 Jan 2025 08:16:57 +0000 Subject: [PATCH 628/681] fix(CI): remove also maintainer-merge label on `bors ` (#21211) If a PR is `delegated` or `ready-to-merge`, the `maintainer-merge` label is no longer needed and removing the label helps with #queueboard filtering. --- .github/workflows/maintainer_bors.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maintainer_bors.yml b/.github/workflows/maintainer_bors.yml index 10a12e5f3a439..1f6e215d7fa1e 100644 --- a/.github/workflows/maintainer_bors.yml +++ b/.github/workflows/maintainer_bors.yml @@ -77,13 +77,15 @@ jobs: ( steps.user_permission.outputs.require-result == 'true' || steps.merge_or_delegate.outputs.bot == 'true' ) }} id: remove_labels - name: Remove "awaiting-author" + name: Remove "awaiting-author" and "maintainer-merge" # we use curl rather than octokit/request-action so that the job won't fail # (and send an annoying email) if the labels don't exist run: | - curl --request DELETE \ - --url "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}${{ github.event.pull_request.number }}/labels/awaiting-author" \ - --header 'authorization: Bearer ${{ secrets.TRIAGE_TOKEN }}' + for label in awaiting-author maintainer-merge; do + curl --request DELETE \ + --url "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}${{ github.event.pull_request.number }}/labels/${label}" \ + --header 'authorization: Bearer ${{ secrets.TRIAGE_TOKEN }}' + done - name: Set up Python if: ${{ ! steps.merge_or_delegate.outputs.mOrD == '' && From 6dc054c5e5bf3319db31336dae7ac21eda527891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 29 Jan 2025 09:23:51 +0000 Subject: [PATCH 629/681] feat(CategoryTheory): Subpresheaf is a complete lattice (#20840) The type of subpresheaves of a given presheaf of sets is a complete lattice. --- .../Sites/LocallySurjective.lean | 2 +- Mathlib/CategoryTheory/Subpresheaf/Basic.lean | 111 +++++++++++++++--- 2 files changed, 98 insertions(+), 15 deletions(-) diff --git a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean index a4fe2b6272f33..390f9e08622c4 100644 --- a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean @@ -93,7 +93,7 @@ instance {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) [IsLocallySurjective J f] : theorem isLocallySurjective_iff_imagePresheaf_sheafify_eq_top {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) : IsLocallySurjective J f ↔ (Subpresheaf.range (whiskerRight f (forget A))).sheafify J = ⊤ := by - simp only [Subpresheaf.ext_iff, funext_iff, Set.ext_iff, top_subpresheaf_obj, + simp only [Subpresheaf.ext_iff, funext_iff, Set.ext_iff, Subpresheaf.top_obj, Set.top_eq_univ, Set.mem_univ, iff_true] exact ⟨fun H _ => H.imageSieve_mem, fun H => ⟨H _⟩⟩ diff --git a/Mathlib/CategoryTheory/Subpresheaf/Basic.lean b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean index 2a751fadcfb62..890d33e462b17 100644 --- a/Mathlib/CategoryTheory/Subpresheaf/Basic.lean +++ b/Mathlib/CategoryTheory/Subpresheaf/Basic.lean @@ -1,10 +1,11 @@ /- Copyright (c) 2022 Andrew Yang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Andrew Yang +Authors: Andrew Yang, Joël Riou -/ import Mathlib.CategoryTheory.Elementwise -import Mathlib.Data.Set.Basic +import Mathlib.Data.Set.Lattice +import Mathlib.Order.CompleteLattice /-! @@ -46,17 +47,99 @@ variable {F F' F'' : Cᵒᵖ ⥤ Type w} (G G' : Subpresheaf F) instance : PartialOrder (Subpresheaf F) := PartialOrder.lift Subpresheaf.obj (fun _ _ => Subpresheaf.ext) -lemma Subpresheaf.le_def (S T : Subpresheaf F) : S ≤ T ↔ ∀ U, S.obj U ≤ T.obj U := Iff.rfl +instance : CompleteLattice (Subpresheaf F) where + sup F G := + { obj U := F.obj U ⊔ G.obj U + map _ _ := by + rintro (h|h) + · exact Or.inl (F.map _ h) + · exact Or.inr (G.map _ h) } + le_sup_left _ _ _ := by simp + le_sup_right _ _ _ := by simp + sup_le F G H h₁ h₂ U := by + rintro x (h|h) + · exact h₁ _ h + · exact h₂ _ h + inf S T := + { obj U := S.obj U ⊓ T.obj U + map _ _ h := ⟨S.map _ h.1, T.map _ h.2⟩} + inf_le_left _ _ _ _ h := h.1 + inf_le_right _ _ _ _ h := h.2 + le_inf _ _ _ h₁ h₂ _ _ h := ⟨h₁ _ h, h₂ _ h⟩ + sSup S := + { obj U := sSup (Set.image (fun T ↦ T.obj U) S) + map f x hx := by + obtain ⟨_, ⟨F, h, rfl⟩, h'⟩ := hx + simp only [Set.sSup_eq_sUnion, Set.sUnion_image, Set.preimage_iUnion, + Set.mem_iUnion, Set.mem_preimage, exists_prop] + exact ⟨_, h, F.map f h'⟩ } + le_sSup _ _ _ _ _ := by aesop + sSup_le _ _ _ _ _ := by aesop + sInf S := + { obj U := sInf (Set.image (fun T ↦ T.obj U) S) + map f x hx := by + rintro _ ⟨F, h, rfl⟩ + exact F.map f (hx _ ⟨_, h, rfl⟩) } + sInf_le _ _ _ _ _ := by aesop + le_sInf _ _ _ _ _ := by aesop + bot := + { obj U := ⊥ + map := by simp } + bot_le _ _ := bot_le + top := + { obj U := ⊤ + map := by simp } + le_top _ _ := le_top + +namespace Subpresheaf + +lemma le_def (S T : Subpresheaf F) : S ≤ T ↔ ∀ U, S.obj U ≤ T.obj U := Iff.rfl + +variable (F) + +@[simp] lemma top_obj (i : Cᵒᵖ) : (⊤ : Subpresheaf F).obj i = ⊤ := rfl +@[simp] lemma bot_obj (i : Cᵒᵖ) : (⊥ : Subpresheaf F).obj i = ⊥ := rfl + +variable {F} + +lemma sSup_obj (S : Set (Subpresheaf F)) (U : Cᵒᵖ) : + (sSup S).obj U = sSup (Set.image (fun T ↦ T.obj U) S) := rfl + +lemma sInf_obj (S : Set (Subpresheaf F)) (U : Cᵒᵖ) : + (sInf S).obj U = sInf (Set.image (fun T ↦ T.obj U) S) := rfl -instance : Top (Subpresheaf F) := - ⟨⟨fun _ => ⊤, @fun U _ _ x _ => by simp⟩⟩ +@[simp] +lemma iSup_obj {ι : Type*} (S : ι → Subpresheaf F) (U : Cᵒᵖ) : + (⨆ i, S i).obj U = ⋃ i, (S i).obj U := by + simp [iSup, sSup_obj] + +@[simp] +lemma iInf_obj {ι : Type*} (S : ι → Subpresheaf F) (U : Cᵒᵖ) : + (⨅ i, S i).obj U = ⋂ i, (S i).obj U := by + simp [iInf, sInf_obj] + +@[simp] +lemma max_obj (S T : Subpresheaf F) (i : Cᵒᵖ) : + (S ⊔ T).obj i = S.obj i ∪ T.obj i := rfl + +@[simp] +lemma min_obj (S T : Subpresheaf F) (i : Cᵒᵖ) : + (S ⊓ T).obj i = S.obj i ∩ T.obj i := rfl + +lemma max_min (S₁ S₂ T : Subpresheaf F) : + (S₁ ⊔ S₂) ⊓ T = (S₁ ⊓ T) ⊔ (S₂ ⊓ T) := by + aesop + +lemma iSup_min {ι : Type*} (S : ι → Subpresheaf F) (T : Subpresheaf F) : + (⨆ i, S i) ⊓ T = ⨆ i, S i ⊓ T := by + aesop instance : Nonempty (Subpresheaf F) := inferInstance /-- The subpresheaf as a presheaf. -/ @[simps!] -def Subpresheaf.toPresheaf : Cᵒᵖ ⥤ Type w where +def toPresheaf : Cᵒᵖ ⥤ Type w where obj U := G.obj U map := @fun _ _ i x => ⟨F.map i x, G.map i x.prop⟩ map_id X := by @@ -73,7 +156,7 @@ instance {U} : CoeHead (G.toPresheaf.obj U) (F.obj U) where /-- The inclusion of a subpresheaf to the original presheaf. -/ @[simps] -def Subpresheaf.ι : G.toPresheaf ⟶ F where app _ x := x +def ι : G.toPresheaf ⟶ F where app _ x := x instance : Mono G.ι := ⟨@fun _ _ _ e => @@ -82,7 +165,7 @@ instance : Mono G.ι := /-- The inclusion of a subpresheaf to a larger subpresheaf -/ @[simps] -def Subpresheaf.homOfLe {G G' : Subpresheaf F} (h : G ≤ G') : G.toPresheaf ⟶ G'.toPresheaf where +def homOfLe {G G' : Subpresheaf F} (h : G ≤ G') : G.toPresheaf ⟶ G'.toPresheaf where app U x := ⟨x, h U x.prop⟩ instance {G G' : Subpresheaf F} (h : G ≤ G') : Mono (Subpresheaf.homOfLe h) := @@ -93,7 +176,7 @@ instance {G G' : Subpresheaf F} (h : G ≤ G') : Mono (Subpresheaf.homOfLe h) := Subtype.ext <| (congr_arg Subtype.val <| (congr_fun (congr_app e U) x :) :)⟩ @[reassoc (attr := simp)] -theorem Subpresheaf.homOfLe_ι {G G' : Subpresheaf F} (h : G ≤ G') : +theorem homOfLe_ι {G G' : Subpresheaf F} (h : G ≤ G') : Subpresheaf.homOfLe h ≫ G'.ι = G.ι := by ext rfl @@ -104,7 +187,7 @@ instance : IsIso (Subpresheaf.ι (⊤ : Subpresheaf F)) := by rw [isIso_iff_bijective] exact ⟨Subtype.coe_injective, fun x => ⟨⟨x, _root_.trivial⟩, rfl⟩⟩ -theorem Subpresheaf.eq_top_iff_isIso : G = ⊤ ↔ IsIso G.ι := by +theorem eq_top_iff_isIso : G = ⊤ ↔ IsIso G.ι := by constructor · rintro rfl infer_instance @@ -114,12 +197,12 @@ theorem Subpresheaf.eq_top_iff_isIso : G = ⊤ ↔ IsIso G.ι := by rw [← IsIso.inv_hom_id_apply (G.ι.app U) x] exact ((inv (G.ι.app U)) x).2 -theorem Subpresheaf.nat_trans_naturality (f : F' ⟶ G.toPresheaf) {U V : Cᵒᵖ} (i : U ⟶ V) +theorem nat_trans_naturality (f : F' ⟶ G.toPresheaf) {U V : Cᵒᵖ} (i : U ⟶ V) (x : F'.obj U) : (f.app V (F'.map i x)).1 = F.map i (f.app U x).1 := congr_arg Subtype.val (FunctorToTypes.naturality _ _ f i x) -@[simp] -theorem top_subpresheaf_obj (U) : (⊤ : Subpresheaf F).obj U = ⊤ := - rfl +end Subpresheaf + +@[deprecated (since := "2025-01-23")] alias top_subpresheaf_obj := Subpresheaf.top_obj end CategoryTheory From cc1af226ce0261209e5d483a3adeef8d125cfbdd Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Wed, 29 Jan 2025 09:37:07 +0000 Subject: [PATCH 630/681] chore: cleanup simp priorities in CategoryTheory/ (#21164) --- .../SimplicialObject/Split.lean | 3 ++- Mathlib/CategoryTheory/Action/Basic.lean | 2 +- Mathlib/CategoryTheory/Limits/Cones.lean | 2 -- Mathlib/CategoryTheory/Limits/Shapes/Types.lean | 4 +++- .../Limits/Shapes/WideEqualizers.lean | 16 ++++++---------- Mathlib/CategoryTheory/Shift/ShiftSequence.lean | 8 ++++---- Mathlib/CategoryTheory/Shift/ShiftedHom.lean | 2 +- Mathlib/Topology/Category/TopCat/Opens.lean | 9 +++------ 8 files changed, 20 insertions(+), 26 deletions(-) diff --git a/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean b/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean index 9061d57109b29..8edfd646e7dee 100644 --- a/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean +++ b/Mathlib/AlgebraicTopology/SimplicialObject/Split.lean @@ -376,7 +376,8 @@ theorem comp_f {S₁ S₂ S₃ : Split C} (Φ₁₂ : S₁ ⟶ S₂) (Φ₂₃ : (Φ₁₂ ≫ Φ₂₃).f n = Φ₁₂.f n ≫ Φ₂₃.f n := rfl -@[reassoc (attr := simp 1100)] +-- This is not a `@[simp]` lemma as it can later be proved by `simp`. +@[reassoc] theorem cofan_inj_naturality_symm {S₁ S₂ : Split C} (Φ : S₁ ⟶ S₂) {Δ : SimplexCategoryᵒᵖ} (A : Splitting.IndexSet Δ) : (S₁.s.cofan Δ).inj A ≫ Φ.F.app Δ = Φ.f A.1.unop.len ≫ (S₂.s.cofan Δ).inj A := by diff --git a/Mathlib/CategoryTheory/Action/Basic.lean b/Mathlib/CategoryTheory/Action/Basic.lean index 1c61d3fcf4c62..f68dccaad46f2 100644 --- a/Mathlib/CategoryTheory/Action/Basic.lean +++ b/Mathlib/CategoryTheory/Action/Basic.lean @@ -42,7 +42,7 @@ namespace Action variable {V} -@[simp 1100] +@[simp] theorem ρ_one {G : MonCat.{u}} (A : Action V G) : A.ρ 1 = 𝟙 A.V := by rw [MonoidHom.map_one]; rfl /-- When a group acts, we can lift the action to the group of automorphisms. -/ diff --git a/Mathlib/CategoryTheory/Limits/Cones.lean b/Mathlib/CategoryTheory/Limits/Cones.lean index 57bf33aa6b3ab..c5a23c859f29d 100644 --- a/Mathlib/CategoryTheory/Limits/Cones.lean +++ b/Mathlib/CategoryTheory/Limits/Cones.lean @@ -169,8 +169,6 @@ theorem Cocone.w {F : J ⥤ C} (c : Cocone F) {j j' : J} (f : j ⟶ j') : rw [c.ι.naturality f] apply comp_id -attribute [simp 1001] Cocone.w_assoc - end variable {F : J ⥤ C} diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean index 5d87af2751e5f..99b3d3e5f71a0 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean @@ -55,6 +55,8 @@ example [UnivLE.{v, u}] : HasProducts.{v} (Type u) := inferInstance instance : HasProducts.{v} (Type v) := inferInstance /-- A restatement of `Types.Limit.lift_π_apply` that uses `Pi.π` and `Pi.lift`. -/ +-- The increased `@[simp]` priority here results in a minor speed up in +-- `Mathlib.CategoryTheory.Sites.EqualizerSheafCondition`. @[simp 1001] theorem pi_lift_π_apply {β : Type v} [Small.{u} β] (f : β → Type u) {P : Type u} (s : ∀ b, P ⟶ f b) (b : β) (x : P) : @@ -69,7 +71,7 @@ theorem pi_lift_π_apply' {β : Type v} (f : β → Type v) {P : Type v} simp /-- A restatement of `Types.Limit.map_π_apply` that uses `Pi.π` and `Pi.map`. -/ -@[simp 1001] +@[simp] theorem pi_map_π_apply {β : Type v} [Small.{u} β] {f g : β → Type u} (α : ∀ j, f j ⟶ g j) (b : β) (x) : (Pi.π g b : ∏ᶜ g → g b) (Pi.map α x) = α b ((Pi.π f b : ∏ᶜ f → f b) x) := diff --git a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean index 349e66c0e30f5..04dfbf1805cde 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean @@ -517,11 +517,9 @@ abbrev wideEqualizer.ι : wideEqualizer f ⟶ X := abbrev wideEqualizer.trident : Trident f := limit.cone (parallelFamily f) -@[simp] theorem wideEqualizer.trident_ι : (wideEqualizer.trident f).ι = wideEqualizer.ι f := rfl -@[simp 1100] theorem wideEqualizer.trident_π_app_zero : (wideEqualizer.trident f).π.app zero = wideEqualizer.ι f := rfl @@ -543,11 +541,11 @@ abbrev wideEqualizer.lift [Nonempty J] {W : C} (k : W ⟶ X) (h : ∀ j₁ j₂, W ⟶ wideEqualizer f := limit.lift (parallelFamily f) (Trident.ofι k h) -@[reassoc (attr := simp 1100)] +@[reassoc] theorem wideEqualizer.lift_ι [Nonempty J] {W : C} (k : W ⟶ X) (h : ∀ j₁ j₂, k ≫ f j₁ = k ≫ f j₂) : - wideEqualizer.lift k h ≫ wideEqualizer.ι f = k := - limit.lift_π _ _ + wideEqualizer.lift k h ≫ wideEqualizer.ι f = k := by + simp /-- A morphism `k : W ⟶ X` satisfying `∀ j₁ j₂, k ≫ f j₁ = k ≫ f j₂` induces a morphism `l : W ⟶ wideEqualizer f` satisfying `l ≫ wideEqualizer.ι f = k`. -/ @@ -604,11 +602,9 @@ abbrev wideCoequalizer.π : Y ⟶ wideCoequalizer f := abbrev wideCoequalizer.cotrident : Cotrident f := colimit.cocone (parallelFamily f) -@[simp] theorem wideCoequalizer.cotrident_π : (wideCoequalizer.cotrident f).π = wideCoequalizer.π f := rfl -@[simp 1100] theorem wideCoequalizer.cotrident_ι_app_one : (wideCoequalizer.cotrident f).ι.app one = wideCoequalizer.π f := rfl @@ -631,11 +627,11 @@ abbrev wideCoequalizer.desc [Nonempty J] {W : C} (k : Y ⟶ W) (h : ∀ j₁ j wideCoequalizer f ⟶ W := colimit.desc (parallelFamily f) (Cotrident.ofπ k h) -@[reassoc (attr := simp 1100)] +@[reassoc] theorem wideCoequalizer.π_desc [Nonempty J] {W : C} (k : Y ⟶ W) (h : ∀ j₁ j₂, f j₁ ≫ k = f j₂ ≫ k) : - wideCoequalizer.π f ≫ wideCoequalizer.desc k h = k := - colimit.ι_desc _ _ + wideCoequalizer.π f ≫ wideCoequalizer.desc k h = k := by + simp /-- Any morphism `k : Y ⟶ W` satisfying `∀ j₁ j₂, f j₁ ≫ k = f j₂ ≫ k` induces a morphism `l : wideCoequalizer f ⟶ W` satisfying `wideCoequalizer.π ≫ g = l`. -/ diff --git a/Mathlib/CategoryTheory/Shift/ShiftSequence.lean b/Mathlib/CategoryTheory/Shift/ShiftSequence.lean index 78359306417b7..fce6ef65bd5b5 100644 --- a/Mathlib/CategoryTheory/Shift/ShiftSequence.lean +++ b/Mathlib/CategoryTheory/Shift/ShiftSequence.lean @@ -85,17 +85,17 @@ def shiftIso (n a a' : M) (ha' : n + a = a') : shiftFunctor C n ⋙ F.shift a ≅ F.shift a' := ShiftSequence.shiftIso n a a' ha' -@[reassoc (attr := simp 1100)] +@[reassoc (attr := simp)] lemma shiftIso_hom_naturality {X Y : C} (n a a' : M) (ha' : n + a = a') (f : X ⟶ Y) : (shift F a).map (f⟦n⟧') ≫ (shiftIso F n a a' ha').hom.app Y = (shiftIso F n a a' ha').hom.app X ≫ (shift F a').map f := (F.shiftIso n a a' ha').hom.naturality f -@[reassoc (attr := simp 1100)] +@[reassoc] lemma shiftIso_inv_naturality {X Y : C} (n a a' : M) (ha' : n + a = a') (f : X ⟶ Y) : (shift F a').map f ≫ (shiftIso F n a a' ha').inv.app Y = - (shiftIso F n a a' ha').inv.app X ≫ (shift F a).map (f⟦n⟧') := - (F.shiftIso n a a' ha').inv.naturality f + (shiftIso F n a a' ha').inv.app X ≫ (shift F a).map (f⟦n⟧') := by + simp variable (M) diff --git a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean index 09bea544345c6..0f182e8d965ba 100644 --- a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean +++ b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean @@ -92,7 +92,7 @@ lemma comp_mk₀_id {a : M} (f : ShiftedHom X Y a) (m₀ : M) (hm₀ : m₀ = 0) f.comp (mk₀ m₀ hm₀ (𝟙 Y)) (by rw [hm₀, zero_add]) = f := by simp [comp_mk₀] -@[simp 1100] +@[simp] lemma mk₀_comp_mk₀ (f : X ⟶ Y) (g : Y ⟶ Z) {a b c : M} (h : b + a = c) (ha : a = 0) (hb : b = 0) : (mk₀ a ha f).comp (mk₀ b hb g) h = mk₀ c (by rw [← h, ha, hb, add_zero]) (f ≫ g) := by diff --git a/Mathlib/Topology/Category/TopCat/Opens.lean b/Mathlib/Topology/Category/TopCat/Opens.lean index 4e4930958fd0e..cd24b21e34cb9 100644 --- a/Mathlib/Topology/Category/TopCat/Opens.lean +++ b/Mathlib/Topology/Category/TopCat/Opens.lean @@ -154,16 +154,13 @@ theorem map_id_obj (U : Opens X) : (map (𝟙 X)).obj U = U := let ⟨_, _⟩ := U rfl -@[simp 1100] +@[simp] theorem map_id_obj' (U) (p) : (map (𝟙 X)).obj ⟨U, p⟩ = ⟨U, p⟩ := rfl -@[simp 1100] -theorem map_id_obj_unop (U : (Opens X)ᵒᵖ) : (map (𝟙 X)).obj (unop U) = unop U := - let ⟨_, _⟩ := U.unop - rfl +theorem map_id_obj_unop (U : (Opens X)ᵒᵖ) : (map (𝟙 X)).obj (unop U) = unop U := by + simp -@[simp 1100] theorem op_map_id_obj (U : (Opens X)ᵒᵖ) : (map (𝟙 X)).op.obj U = U := by simp @[simp] From 5e04c482780fea645792eae044b671d519f53ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 29 Jan 2025 09:37:08 +0000 Subject: [PATCH 631/681] feat(CategoryTheory): the subpresheaf of types generated by a section (#21174) --- Mathlib.lean | 1 + .../CategoryTheory/Subpresheaf/OfSection.lean | 105 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 Mathlib/CategoryTheory/Subpresheaf/OfSection.lean diff --git a/Mathlib.lean b/Mathlib.lean index 87b4478563b25..873393da66619 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2268,6 +2268,7 @@ import Mathlib.CategoryTheory.Subobject.Types import Mathlib.CategoryTheory.Subobject.WellPowered import Mathlib.CategoryTheory.Subpresheaf.Basic import Mathlib.CategoryTheory.Subpresheaf.Image +import Mathlib.CategoryTheory.Subpresheaf.OfSection import Mathlib.CategoryTheory.Subpresheaf.Sieves import Mathlib.CategoryTheory.Subterminal import Mathlib.CategoryTheory.Sums.Associator diff --git a/Mathlib/CategoryTheory/Subpresheaf/OfSection.lean b/Mathlib/CategoryTheory/Subpresheaf/OfSection.lean new file mode 100644 index 0000000000000..3bb6facb0c17f --- /dev/null +++ b/Mathlib/CategoryTheory/Subpresheaf/OfSection.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Subpresheaf.Image +import Mathlib.CategoryTheory.Yoneda + +/-! +# The subpresheaf generated by a section + +Given a presheaf of types `F : Cᵒᵖ ⥤ Type w` and a section `x : F.obj X`, +we define `Subpresheaf.ofSection x : Subpresheaf F` as the subpresheaf +of `F` generated by `x`. + +-/ + +universe w v u + +namespace CategoryTheory + +variable {C : Type u} [Category.{v} C] + +namespace Subpresheaf + +section + +variable {F : Cᵒᵖ ⥤ Type w} {X : Cᵒᵖ} (x : F.obj X) + +/-- The subpresheaf of `F : Cᵒᵖ ⥤ Type w` that is generated +by a section `x : F.obj X`. -/ +@[simps (config := .lemmasOnly)] +def ofSection : Subpresheaf F where + obj U := setOf (fun u ↦ ∃ (f : X ⟶ U), F.map f x = u) + map {U V} g := by + rintro _ ⟨f, rfl⟩ + exact ⟨f ≫ g, by simp⟩ + +lemma mem_ofSection_obj : x ∈ (ofSection x).obj X := ⟨𝟙 _, by simp⟩ + +@[simp] +lemma ofSection_le_iff (G : Subpresheaf F) : + ofSection x ≤ G ↔ x ∈ G.obj X := by + constructor + · intro hx + exact hx _ (mem_ofSection_obj x) + · rintro hx U _ ⟨f, rfl⟩ + exact G.map f hx + +@[simp] +lemma ofSection_image {F' : Cᵒᵖ ⥤ Type w} (f : F ⟶ F') : + (ofSection x).image f = ofSection (f.app _ x) := by + apply le_antisymm + · rw [image_le_iff, ofSection_le_iff, preimage_obj, Set.mem_preimage] + exact ⟨𝟙 X, by simp⟩ + · simp only [ofSection_le_iff, image_obj, Set.mem_image] + exact ⟨x, mem_ofSection_obj x, rfl⟩ + +end + +section + +variable {F : Cᵒᵖ ⥤ Type v} + +lemma ofSection_eq_range {X : Cᵒᵖ} (x : F.obj X) : + ofSection x = range (yonedaEquiv.symm x) := by + ext U y + simp only [ofSection_obj, Set.mem_setOf_eq, Opposite.op_unop, range_obj, yoneda_obj_obj, + Set.mem_range] + constructor + · rintro ⟨f, rfl⟩ + exact ⟨f.unop, rfl⟩ + · rintro ⟨f, rfl⟩ + exact ⟨f.op, rfl⟩ + +lemma range_eq_ofSection {X : C} (f : yoneda.obj X ⟶ F) : + range f = ofSection (yonedaEquiv f) := by + rw [ofSection_eq_range, Equiv.symm_apply_apply] + +end + +section + +variable {F : Cᵒᵖ ⥤ Type max v w} + +lemma ofSection_eq_range' {X : Cᵒᵖ} (x : F.obj X) : + ofSection x = range ((yonedaCompUliftFunctorEquiv F X.unop).symm x) := by + ext U y + simp only [Opposite.op_unop, range_obj, Functor.comp_obj, yoneda_obj_obj, uliftFunctor_obj, + Set.mem_range, ULift.exists] + constructor + · rintro ⟨f, rfl⟩ + exact ⟨f.unop, rfl⟩ + · rintro ⟨f, rfl⟩ + exact ⟨f.op, rfl⟩ + +lemma range_eq_ofSection' {X : C} (f : yoneda.obj X ⋙ uliftFunctor.{w} ⟶ F) : + range f = ofSection ((yonedaCompUliftFunctorEquiv F X) f) := by + rw [ofSection_eq_range', Equiv.symm_apply_apply] + +end + +end Subpresheaf + +end CategoryTheory From 9219f8aa80f05d86cbfb731a98a4ae8c4f5d093a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Staromiejski?= Date: Wed, 29 Jan 2025 10:27:24 +0000 Subject: [PATCH 632/681] feat(RingTheory/IntegralClosure): product of integral algebras is integral (#21191) Pair of integral elements is an integral element of the product algebra. Product of integral algebras is an integral algebra. --- .../IntegralClosure/Algebra/Basic.lean | 15 +++++++++---- .../IntegralClosure/IsIntegral/Basic.lean | 21 +++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean index 69833b5a71fed..c8e7297bf65f1 100644 --- a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean @@ -210,8 +210,15 @@ def integralClosure : Subalgebra R A where mul_mem' := IsIntegral.mul algebraMap_mem' _ := isIntegral_algebraMap -end - -theorem mem_integralClosure_iff (R A : Type*) [CommRing R] [CommRing A] [Algebra R A] {a : A} : - a ∈ integralClosure R A ↔ IsIntegral R a := +theorem mem_integralClosure_iff {a : A} : a ∈ integralClosure R A ↔ IsIntegral R a := Iff.rfl + +variable {R} {A B : Type*} [Ring A] [Algebra R A] [Ring B] [Algebra R B] + +/-- Product of two integral algebras is an integral algebra. -/ +instance Algebra.IsIntegral.prod [Algebra.IsIntegral R A] [Algebra.IsIntegral R B] : + Algebra.IsIntegral R (A × B) := + Algebra.isIntegral_def.mpr fun x ↦ + (Algebra.isIntegral_def.mp ‹_› x.1).pair (Algebra.isIntegral_def.mp ‹_› x.2) + +end diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean index c40c5bce9c177..5e75b8a8f6cd1 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean @@ -214,3 +214,24 @@ theorem isNoetherian_adjoin_finset [IsNoetherianRing R] (s : Finset A) isNoetherian_of_fg_of_noetherian _ (fg_adjoin_of_finite s.finite_toSet hs) end + +section Prod + +variable {R A B : Type*} +variable [CommRing R] [Ring A] [Ring B] [Algebra R A] [Algebra R B] + +/-- An element of a product algebra is integral if each component is integral. -/ +theorem IsIntegral.pair {x : A × B} (hx₁ : IsIntegral R x.1) (hx₂ : IsIntegral R x.2) : + IsIntegral R x := by + obtain ⟨p₁, ⟨hp₁Monic, hp₁Eval⟩⟩ := hx₁ + obtain ⟨p₂, ⟨hp₂Monic, hp₂Eval⟩⟩ := hx₂ + refine ⟨p₁ * p₂, ⟨hp₁Monic.mul hp₂Monic, ?_⟩⟩ + rw [← aeval_def] at * + rw [aeval_prod_apply, aeval_mul, hp₁Eval, zero_mul, aeval_mul, hp₂Eval, mul_zero, + Prod.zero_eq_mk] + +/-- An element of a product algebra is integral iff each component is integral. -/ +theorem IsIntegral.pair_iff {x : A × B} : IsIntegral R x ↔ IsIntegral R x.1 ∧ IsIntegral R x.2 := + ⟨fun h ↦ ⟨h.map (AlgHom.fst R A B), h.map (AlgHom.snd R A B)⟩, fun h ↦ h.1.pair h.2⟩ + +end Prod From 5ff0a4782ee8ac78210032b135f7037e8c895153 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Wed, 29 Jan 2025 10:50:05 +0000 Subject: [PATCH 633/681] chore: reformat adaptation notes (#21208) almost all adaptation notes are now of the form #adaptation_note /-- some-identifier text explaining the adaptation -/ where `some-identifier` is a github url, or a nightly. --- Mathlib/Algebra/Category/Ring/Epi.lean | 3 +- Mathlib/Algebra/DualNumber.lean | 24 ++++------------ Mathlib/Algebra/Free.lean | 16 +++++------ Mathlib/Algebra/Homology/Single.lean | 4 +-- Mathlib/Algebra/Lie/Semisimple/Basic.lean | 3 +- .../Algebra/Module/LinearMap/Polynomial.lean | 7 ++--- Mathlib/Algebra/Polynomial/RingDivision.lean | 1 - .../Morphisms/QuasiCompact.lean | 5 ++-- Mathlib/Analysis/Analytic/CPolynomial.lean | 4 +-- .../ContinuousFunctionalCalculus/Order.lean | 3 +- .../Calculus/ContDiff/FTaylorSeries.lean | 12 +++----- .../Calculus/FormalMultilinearSeries.lean | 7 ++--- Mathlib/Analysis/Complex/TaylorSeries.lean | 5 ++-- .../Complex/UpperHalfPlane/Metric.lean | 7 ++--- Mathlib/Analysis/Convex/Basic.lean | 4 +-- .../FunctionalSpaces/SobolevInequality.lean | 8 +++--- Mathlib/Analysis/Normed/Lp/PiLp.lean | 7 ++--- .../Normed/Operator/BoundedLinearMaps.lean | 7 ++--- .../NormedSpace/HahnBanach/Extension.lean | 3 +- .../NormedSpace/OperatorNorm/Bilinear.lean | 7 ++--- Mathlib/CategoryTheory/GradedObject.lean | 7 ++--- .../CategoryTheory/GradedObject/Monoidal.lean | 5 ++-- .../CategoryTheory/Limits/Shapes/Kernels.lean | 6 ++-- Mathlib/CategoryTheory/Monoidal/Mod_.lean | 7 ++--- Mathlib/CategoryTheory/Monoidal/Mon_.lean | 7 ++--- .../CategoryTheory/Monoidal/Rigid/Basic.lean | 6 ++-- .../Sites/NonabelianCohomology/H1.lean | 7 ++--- .../Additive/PluenneckeRuzsa.lean | 3 +- .../Combinatorics/SimpleGraph/Matching.lean | 8 ++---- Mathlib/Computability/RegularExpressions.lean | 14 +++++----- Mathlib/Data/Bool/Basic.lean | 4 +-- Mathlib/Data/DFinsupp/Sigma.lean | 6 ++-- Mathlib/Data/Finsupp/Basic.lean | 8 +++--- Mathlib/Data/List/Basic.lean | 9 +++--- Mathlib/Data/Sign.lean | 7 ++--- Mathlib/FieldTheory/KummerExtension.lean | 6 ++-- Mathlib/FieldTheory/Relrank.lean | 6 ++-- .../Manifold/MFDeriv/NormedSpace.lean | 28 ++++++------------- .../FreeGroup/NielsenSchreier.lean | 8 ++---- .../BilinearForm/Properties.lean | 4 +-- Mathlib/LinearAlgebra/Dual.lean | 6 ++-- Mathlib/LinearAlgebra/Orientation.lean | 4 +-- Mathlib/LinearAlgebra/Semisimple.lean | 9 ++---- Mathlib/MeasureTheory/Group/Measure.lean | 4 +-- .../MeasurableSpace/Embedding.lean | 4 +-- Mathlib/ModelTheory/PartialEquiv.lean | 3 +- .../ClassNumber/AdmissibleAbsoluteValue.lean | 4 +-- Mathlib/NumberTheory/Cyclotomic/Rat.lean | 6 ++-- .../NumberTheory/LSeries/Nonvanishing.lean | 7 ++--- .../NumberField/Units/DirichletTheorem.lean | 4 +-- .../NumberField/Units/Regulator.lean | 4 +-- Mathlib/RingTheory/Ideal/Operations.lean | 16 ++++------- Mathlib/RingTheory/Jacobson/Ring.lean | 7 ++--- Mathlib/RingTheory/TensorProduct/Basic.lean | 8 ++---- Mathlib/Tactic/NormNum/Pow.lean | 4 +-- Mathlib/Topology/Algebra/Ring/Basic.lean | 3 +- .../Compactness/CompactlyGeneratedSpace.lean | 9 ++---- 57 files changed, 143 insertions(+), 252 deletions(-) diff --git a/Mathlib/Algebra/Category/Ring/Epi.lean b/Mathlib/Algebra/Category/Ring/Epi.lean index ae3808ac12470..4ba86a9d7d7c3 100644 --- a/Mathlib/Algebra/Category/Ring/Epi.lean +++ b/Mathlib/Algebra/Category/Ring/Epi.lean @@ -23,8 +23,7 @@ lemma CommRingCat.epi_iff_tmul_eq_tmul {R S : Type u} [CommRing R] [CommRing S] ∀ s : S, s ⊗ₜ[R] 1 = 1 ⊗ₜ s := by constructor · intro H - #adaptation_note - /-- After https://github.com/leanprover/lean4/pull/6024 + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we need to add `(R := R) (A := S)` in the next line to deal with unification issues. -/ have := H.1 (CommRingCat.ofHom <| Algebra.TensorProduct.includeLeftRingHom (R := R)) (CommRingCat.ofHom <| (Algebra.TensorProduct.includeRight (R := R) (A := S)).toRingHom) diff --git a/Mathlib/Algebra/DualNumber.lean b/Mathlib/Algebra/DualNumber.lean index 6e2ef4a79c866..2eca2386d1566 100644 --- a/Mathlib/Algebra/DualNumber.lean +++ b/Mathlib/Algebra/DualNumber.lean @@ -149,36 +149,24 @@ theorem lift_apply_apply (fe : {_fe : (A →ₐ[R] B) × B // _}) (a : A[ε]) : @[simp] theorem coe_lift_symm_apply (F : A[ε] →ₐ[R] B) : (lift.symm F).val = (F.comp (inlAlgHom _ _ _), F ε) := rfl -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{fe : (A →ₐ[R] B) × B // _}`. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/5338 +The new unused variable linter flags `{fe : (A →ₐ[R] B) × B // _}`. -/ set_option linter.unusedVariables false in /-- When applied to `inl`, `DualNumber.lift` applies the map `f : A →ₐ[R] B`. -/ @[simp] theorem lift_apply_inl (fe : {fe : (A →ₐ[R] B) × B // _}) (a : A) : lift fe (inl a : A[ε]) = fe.val.1 a := by rw [lift_apply_apply, fst_inl, snd_inl, map_zero, zero_mul, add_zero] -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{fe : (A →ₐ[R] B) × B // _}`. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/5338 +The new unused variable linter flags `{fe : (A →ₐ[R] B) × B // _}`. -/ set_option linter.unusedVariables false in /-- Scaling on the left is sent by `DualNumber.lift` to multiplication on the left -/ @[simp] theorem lift_smul (fe : {fe : (A →ₐ[R] B) × B // _}) (a : A) (ad : A[ε]) : lift fe (a • ad) = fe.val.1 a * lift fe ad := by rw [← inl_mul_eq_smul, map_mul, lift_apply_inl] -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{fe : (A →ₐ[R] B) × B // _}`. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/5338 +The new unused variable linter flags `{fe : (A →ₐ[R] B) × B // _}`. -/ set_option linter.unusedVariables false in /-- Scaling on the right is sent by `DualNumber.lift` to multiplication on the right -/ @[simp] theorem lift_op_smul (fe : {fe : (A →ₐ[R] B) × B // _}) (a : A) (ad : A[ε]) : diff --git a/Mathlib/Algebra/Free.lean b/Mathlib/Algebra/Free.lean index c0663264e177d..0fbfaa9678903 100644 --- a/Mathlib/Algebra/Free.lean +++ b/Mathlib/Algebra/Free.lean @@ -80,8 +80,8 @@ theorem hom_ext {β : Type v} [Mul β] {f g : FreeMagma α →ₙ* β} (h : f end FreeMagma -#adaptation_note /-- around nightly-2024-02-25, we need to write `mul x y` in the second pattern, -instead of `x * y`. --/ +#adaptation_note /-- nightly-2024-02-25 +we need to write `mul x y` in the second pattern, instead of `x * y`. --/ /-- Lifts a function `α → β` to a magma homomorphism `FreeMagma α → β` given a magma `β`. -/ def FreeMagma.liftAux {α : Type u} {β : Type v} [Mul β] (f : α → β) : FreeMagma α → β | FreeMagma.of x => f x @@ -185,8 +185,8 @@ end Category end FreeMagma -#adaptation_note /-- around nightly-2024-02-25, we need to write `mul x y` in the second pattern, - instead of `x * y`. -/ +#adaptation_note /-- nightly-2024-02-25 +we need to write `mul x y` in the second pattern, instead of `x * y`. -/ /-- `FreeMagma` is traversable. -/ protected def FreeMagma.traverse {m : Type u → Type u} [Applicative m] {α β : Type u} (F : α → m β) : FreeMagma α → m (FreeMagma β) @@ -262,8 +262,8 @@ end Category end FreeMagma -#adaptation_note /-- around nightly-2024-02-25, we need to write `mul x y` in the second pattern, -instead of `x * y`. -/ +#adaptation_note /-- nightly-2024-02-25 +we need to write `mul x y` in the second pattern, instead of `x * y`. -/ /-- Representation of an element of a free magma. -/ protected def FreeMagma.repr {α : Type u} [Repr α] : FreeMagma α → Lean.Format | FreeMagma.of x => repr x @@ -279,8 +279,8 @@ attribute [to_additive existing] FreeMagma.repr @[to_additive] instance {α : Type u} [Repr α] : Repr (FreeMagma α) := ⟨fun o _ => FreeMagma.repr o⟩ -#adaptation_note /-- around nightly-2024-02-25, we need to write `mul x y` in the second pattern, -instead of `x * y`. -/ +#adaptation_note /-- nightly-2024-02-25 +we need to write `mul x y` in the second pattern, instead of `x * y`. -/ /-- Length of an element of a free magma. -/ def FreeMagma.length {α : Type u} : FreeMagma α → ℕ | FreeMagma.of _x => 1 diff --git a/Mathlib/Algebra/Homology/Single.lean b/Mathlib/Algebra/Homology/Single.lean index b6dc763c87a95..16d9d5943f732 100644 --- a/Mathlib/Algebra/Homology/Single.lean +++ b/Mathlib/Algebra/Homology/Single.lean @@ -44,8 +44,8 @@ noncomputable def single (j : ι) : V ⥤ HomologicalComplex V c where split_ifs with h · subst h simp - · #adaptation_note /-- after nightly-2024-03-07, the previous sensible proof - `rw [if_neg h]; simp` fails with "motive not type correct". + · #adaptation_note /-- nightly-2024-03-07 + the previous sensible proof `rw [if_neg h]; simp` fails with "motive not type correct". The following is horrible. -/ convert (id_zero (C := V)).symm all_goals simp [if_neg h] diff --git a/Mathlib/Algebra/Lie/Semisimple/Basic.lean b/Mathlib/Algebra/Lie/Semisimple/Basic.lean index 0697232c790f3..28001afd61610 100644 --- a/Mathlib/Algebra/Lie/Semisimple/Basic.lean +++ b/Mathlib/Algebra/Lie/Semisimple/Basic.lean @@ -212,8 +212,7 @@ lemma finitelyAtomistic : ∀ s : Finset (LieIdeal R L), ↑s ⊆ {I : LieIdeal set K := s'.sup id suffices I ≤ K by obtain ⟨t, hts', htI⟩ := finitelyAtomistic s' hs'S I this - #adaptation_note - /-- Prior to https://github.com/leanprover/lean4/pull/6024 + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we could write `hts'.trans hs'.subset` instead of `Finset.Subset.trans hts' hs'.subset` in the next line. -/ exact ⟨t, Finset.Subset.trans hts' hs'.subset, htI⟩ diff --git a/Mathlib/Algebra/Module/LinearMap/Polynomial.lean b/Mathlib/Algebra/Module/LinearMap/Polynomial.lean index 5637e7a41bdf3..a5f9f7bb8180f 100644 --- a/Mathlib/Algebra/Module/LinearMap/Polynomial.lean +++ b/Mathlib/Algebra/Module/LinearMap/Polynomial.lean @@ -253,11 +253,8 @@ lemma polyCharpolyAux_baseChange (A : Type*) [CommRing A] [Algebra R A] : simp only [RingHom.coe_comp, RingHom.coe_coe, Function.comp_apply, map_X, bind₁_X_right] classical rw [toMvPolynomial_comp _ (basis A (Basis.end bₘ)), ← toMvPolynomial_baseChange] - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/4119 we either need to specify the `M₂` argument, - or use `set_option maxSynthPendingDepth 2 in`. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 + we either need to specify the `M₂` argument, or use `set_option maxSynthPendingDepth 2 in`. -/ suffices toMvPolynomial (M₂ := (Module.End A (TensorProduct R A M))) (basis A bₘ.end) (basis A bₘ).end (tensorProduct R A M M) ij = X ij by rw [this, bind₁_X_right] diff --git a/Mathlib/Algebra/Polynomial/RingDivision.lean b/Mathlib/Algebra/Polynomial/RingDivision.lean index eb2061427a125..918724e6d9f4d 100644 --- a/Mathlib/Algebra/Polynomial/RingDivision.lean +++ b/Mathlib/Algebra/Polynomial/RingDivision.lean @@ -234,7 +234,6 @@ theorem rootMultiplicity_mul {p q : R[X]} {x : R} (hpq : p * q ≠ 0) : multiplicity_mul (prime_X_sub_C x) (finiteMultiplicity_X_sub_C _ hpq)] open Multiset in -set_option linter.unusedVariables false in theorem exists_multiset_roots [DecidableEq R] : ∀ {p : R[X]} (_ : p ≠ 0), ∃ s : Multiset R, (Multiset.card s : WithBot ℕ) ≤ degree p ∧ ∀ a, s.count a = rootMultiplicity a p diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean index 4fa80786dbe0c..a941013a085e5 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean @@ -248,9 +248,8 @@ theorem exists_pow_mul_eq_zero_of_res_basicOpen_eq_zero_of_isAffineOpen (X : Sch (H : x |_ (X.basicOpen f) = 0) : ∃ n : ℕ, f ^ n * x = 0 := by rw [← map_zero (X.presheaf.map (homOfLE <| X.basicOpen_le f : X.basicOpen f ⟶ U).op).hom] at H - #adaptation_note - /-- - Prior to nightly-2024-09-29, we could use dot notation here: + #adaptation_note /-- nightly-2024-09-29 + we could use dot notation here: `(hU.isLocalization_basicOpen f).exists_of_eq H` This is no longer possible; likely changing the signature of `IsLocalization.Away.exists_of_eq` is in order. diff --git a/Mathlib/Analysis/Analytic/CPolynomial.lean b/Mathlib/Analysis/Analytic/CPolynomial.lean index d41f5fdabed38..838c7af23b5b8 100644 --- a/Mathlib/Analysis/Analytic/CPolynomial.lean +++ b/Mathlib/Analysis/Analytic/CPolynomial.lean @@ -396,8 +396,8 @@ lemma changeOriginSeriesTerm_bound (p : FormalMultilinearSeries 𝕜 E F) {n : (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (k l : ℕ) {s : Finset (Fin (k + l))} (hs : s.card = l) (hkl : n ≤ k + l) : p.changeOriginSeriesTerm k l s hs = 0 := by - #adaptation_note - /-- `set_option maxSynthPendingDepth 2` required after https://github.com/leanprover/lean4/pull/4119 -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 + `set_option maxSynthPendingDepth 2` required after https://github.com/leanprover/lean4/pull/4119 -/ set_option maxSynthPendingDepth 2 in rw [changeOriginSeriesTerm, hn _ hkl, map_zero] diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean index c093bde67133c..62ae49c6840de 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean @@ -291,7 +291,8 @@ lemma le_iff_norm_sqrt_mul_rpow {a b : A} (hbu : IsUnit b) (ha : 0 ≤ a) (hb : lift b to Aˣ using hbu have hbab : 0 ≤ (b : A) ^ (-(1 / 2) : ℝ) * a * (b : A) ^ (-(1 / 2) : ℝ) := conjugate_nonneg_of_nonneg ha rpow_nonneg - #adaptation_note /-- 2024-11-10 added `(R := A)` -/ + #adaptation_note /-- 2024-11-10 + added `(R := A)` -/ conv_rhs => rw [← sq_le_one_iff₀ (norm_nonneg _), sq, ← CStarRing.norm_star_mul_self, star_mul, IsSelfAdjoint.of_nonneg (R := A) sqrt_nonneg, IsSelfAdjoint.of_nonneg rpow_nonneg, diff --git a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean index 7cc8a905e12ec..9ed44eadb3647 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean @@ -279,11 +279,8 @@ theorem hasFTaylorSeriesUpToOn_succ_iff_left {n : ℕ} : rw [this] exact h.2.2 -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4119, -without `set_option maxSynthPendingDepth 2` this proof needs substantial repair. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 +without `set_option maxSynthPendingDepth 2` this proof needs substantial repair. -/ set_option maxSynthPendingDepth 2 in -- Porting note: this was split out from `hasFTaylorSeriesUpToOn_succ_iff_right` to avoid a timeout. theorem HasFTaylorSeriesUpToOn.shift_of_succ @@ -489,9 +486,8 @@ theorem iteratedFDerivWithin_succ_apply_right {n : ℕ} (hs : UniqueDiffOn 𝕜 rw [fderivWithin_congr A (A x hx)] _ = (I ∘ fderivWithin 𝕜 (iteratedFDerivWithin 𝕜 n (fderivWithin 𝕜 f s) s) s x : E → E[×n + 1]→L[𝕜] F) (m 0) (tail m) := by - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/4119 we need to either use + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 + we need to either use `set_option maxSynthPendingDepth 2 in` or fill in an explicit argument as ``` diff --git a/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean b/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean index 4254d8378f1d6..78250c59bb934 100644 --- a/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean +++ b/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean @@ -64,11 +64,8 @@ end Module namespace FormalMultilinearSeries -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4481 -the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4481 +the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. -/ @[simp, nolint simpNF] theorem zero_apply (n : ℕ) : (0 : FormalMultilinearSeries 𝕜 E F) n = 0 := rfl diff --git a/Mathlib/Analysis/Complex/TaylorSeries.lean b/Mathlib/Analysis/Complex/TaylorSeries.lean index dbd3037467b3a..4c7a2f85e0047 100644 --- a/Mathlib/Analysis/Complex/TaylorSeries.lean +++ b/Mathlib/Analysis/Complex/TaylorSeries.lean @@ -24,9 +24,8 @@ see `Complex.hasSum_taylorSeries_of_entire`, `Complex.taylorSeries_eq_of_entire` `Complex.taylorSeries_eq_of_entire'`. -/ -#adaptation_note -/-- -Due to https://github.com/leanprover/lean4/issues/5126, we've had to change all +#adaptation_note /-- https://github.com/leanprover/lean4/issues/5126 +we've had to change all the `⦃⦄` stricit implicit variable statements in this file to normal `{}` implicit variables. Once this issue is fixed, we should change them back. For now it doesn't break anything downstream. diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean index c92c0c0ce665b..eba4e36e6505b 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean @@ -157,11 +157,8 @@ theorem cmp_dist_eq_cmp_dist_coe_center (z w : ℍ) (r : ℝ) : ((mul_neg_of_pos_of_neg w.im_pos (sinh_neg_iff.2 hr₀)).trans_le dist_nonneg).cmp_eq_gt.symm] have hr₀' : 0 ≤ w.im * Real.sinh r := by positivity have hzw₀ : 0 < 2 * z.im * w.im := by positivity - #adaptation_note - /-- - After the bug fix in https://github.com/leanprover/lean4/pull/6024, - we need to give Lean the hint `(y := w.im * Real.sinh r)`. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 + we need to give Lean the hint `(y := w.im * Real.sinh r)`. -/ simp only [← cosh_strictMonoOn.cmp_map_eq dist_nonneg hr₀, ← (pow_left_strictMonoOn₀ two_ne_zero).cmp_map_eq dist_nonneg (y := w.im * Real.sinh r) hr₀', dist_coe_center_sq] diff --git a/Mathlib/Analysis/Convex/Basic.lean b/Mathlib/Analysis/Convex/Basic.lean index cbf1474ae125f..1894c691b8c59 100644 --- a/Mathlib/Analysis/Convex/Basic.lean +++ b/Mathlib/Analysis/Convex/Basic.lean @@ -624,8 +624,8 @@ theorem single_mem_stdSimplex (i : ι) : Pi.single i 1 ∈ stdSimplex 𝕜 ι := theorem ite_eq_mem_stdSimplex (i : ι) : (if i = · then (1 : 𝕜) else 0) ∈ stdSimplex 𝕜 ι := by simpa only [@eq_comm _ i, ← Pi.single_apply] using single_mem_stdSimplex 𝕜 i -#adaptation_note /-- as of `nightly-2024-03-11`, we need a type annotation on the segment in the -following two lemmas. -/ +#adaptation_note /-- nightly-2024-03-11 +we need a type annotation on the segment in the following two lemmas. -/ /-- The edges are contained in the simplex. -/ lemma segment_single_subset_stdSimplex (i j : ι) : diff --git a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean index df47835cf9bfe..f6b41f8197a66 100644 --- a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean +++ b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean @@ -680,8 +680,8 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_le [FiniteDimensional ℝ F] have hp' : p'⁻¹ = p⁻¹ - (finrank ℝ E : ℝ)⁻¹ := by rw [inv_inv, NNReal.coe_sub] · simp - · #adaptation_note - /-- This should just be `gcongr`, but this is not working as of nightly-2024-11-20. + · #adaptation_note /-- nightly-2024-11-20 + This should just be `gcongr`, but this is not working as of nightly-2024-11-20. Possibly related to #19262 (since this proof fails at `with_reducible_and_instances`). -/ exact inv_anti₀ (by positivity) h2p.le have : (q : ℝ≥0∞) ≤ p' := by @@ -691,8 +691,8 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_le [FiniteDimensional ℝ F] · dsimp have : 0 < p⁻¹ - (finrank ℝ E : ℝ≥0)⁻¹ := by simp only [tsub_pos_iff_lt] - #adaptation_note - /-- This should just be `gcongr`, but this is not working as of nightly-2024-11-20. + #adaptation_note /-- nightly-2024-11-20 + This should just be `gcongr`, but this is not working as of nightly-2024-11-20. Possibly related to #19262 (since this proof fails at `with_reducible_and_instances`). -/ exact inv_strictAnti₀ (by positivity) h2p positivity diff --git a/Mathlib/Analysis/Normed/Lp/PiLp.lean b/Mathlib/Analysis/Normed/Lp/PiLp.lean index 0c311a281bb35..dfd02e7678382 100644 --- a/Mathlib/Analysis/Normed/Lp/PiLp.lean +++ b/Mathlib/Analysis/Normed/Lp/PiLp.lean @@ -95,13 +95,10 @@ variable [Semiring 𝕜] [∀ i, SeminormedAddCommGroup (β i)] variable [∀ i, Module 𝕜 (β i)] (c : 𝕜) variable (x y : PiLp p β) (i : ι) -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4481 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4481 the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. -(It appears to also be unused in Mathlib.) --/ +(It appears to also be unused in Mathlib.) -/ @[simp, nolint simpNF] theorem zero_apply : (0 : PiLp p β) i = 0 := rfl diff --git a/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean b/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean index 9ad44b68f8091..72c464afef4f1 100644 --- a/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean +++ b/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean @@ -193,12 +193,9 @@ theorem isBoundedLinearMap_prod_multilinear {E : ι → Type*} [∀ i, Seminorme (ContinuousMultilinearMap.prodL 𝕜 E F G).toContinuousLinearEquiv |>.toContinuousLinearMap.isBoundedLinearMap -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/6024 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to add the named arguments `(ι := ι) (G := F)` -to `ContinuousMultilinearMap.compContinuousLinearMapL`. --/ +to `ContinuousMultilinearMap.compContinuousLinearMapL`. -/ /-- Given a fixed continuous linear map `g`, associating to a continuous multilinear map `f` the continuous multilinear map `f (g m₁, ..., g mₙ)` is a bounded linear operation. -/ theorem isBoundedLinearMap_continuousMultilinearMap_comp_linear (g : G →L[𝕜] E) : diff --git a/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean b/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean index 59589fe924618..4ce0cf8cdda55 100644 --- a/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean +++ b/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean @@ -145,8 +145,7 @@ variable {E : Type u} [NormedAddCommGroup E] [NormedSpace 𝕜 E] open ContinuousLinearEquiv Submodule theorem coord_norm' {x : E} (h : x ≠ 0) : ‖(‖x‖ : 𝕜) • coord 𝕜 x h‖ = 1 := by - #adaptation_note - /-- + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 `set_option maxSynthPendingDepth 2` required after https://github.com/leanprover/lean4/pull/4119 Alternatively, we can add: ``` diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean index 8193941231cfa..471a7a72a27a8 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean @@ -146,11 +146,8 @@ def flip (f : E →SL[σ₁₃] F →SL[σ₂₃] G) : F →SL[σ₂₃] E →SL ‖f‖ fun y x => (f.le_opNorm₂ x y).trans_eq <| by simp only [mul_right_comm] private theorem le_norm_flip (f : E →SL[σ₁₃] F →SL[σ₂₃] G) : ‖f‖ ≤ ‖flip f‖ := - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/4119 we either need - to specify the `f.flip` argument, or use `set_option maxSynthPendingDepth 2 in`. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 + we either need to specify the `f.flip` argument, or use `set_option maxSynthPendingDepth 2 in`. -/ f.opNorm_le_bound₂ (norm_nonneg f.flip) fun x y => by rw [mul_right_comm] exact (flip f).le_opNorm₂ y x diff --git a/Mathlib/CategoryTheory/GradedObject.lean b/Mathlib/CategoryTheory/GradedObject.lean index 60536139bb717..0b144c7428315 100644 --- a/Mathlib/CategoryTheory/GradedObject.lean +++ b/Mathlib/CategoryTheory/GradedObject.lean @@ -216,11 +216,8 @@ theorem shiftFunctor_map_apply {β : Type*} [AddCommGroup β] (s : β) instance [HasZeroMorphisms C] (β : Type w) (X Y : GradedObject β C) : Zero (X ⟶ Y) := ⟨fun _ => 0⟩ -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4481 -the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4481 +the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. -/ @[simp, nolint simpNF] theorem zero_apply [HasZeroMorphisms C] (β : Type w) (X Y : GradedObject β C) (b : β) : (0 : X ⟶ Y) b = 0 := diff --git a/Mathlib/CategoryTheory/GradedObject/Monoidal.lean b/Mathlib/CategoryTheory/GradedObject/Monoidal.lean index b10fab11e47d8..3467d00d9731f 100644 --- a/Mathlib/CategoryTheory/GradedObject/Monoidal.lean +++ b/Mathlib/CategoryTheory/GradedObject/Monoidal.lean @@ -312,9 +312,8 @@ lemma associator_naturality (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ [HasGoodTensor₁₂Tensor Y₁ Y₂ Y₃] [HasGoodTensorTensor₂₃ Y₁ Y₂ Y₃] : tensorHom (tensorHom f₁ f₂) f₃ ≫ (associator Y₁ Y₂ Y₃).hom = (associator X₁ X₂ X₃).hom ≫ tensorHom f₁ (tensorHom f₂ f₃) := by - #adaptation_note - /-- this used to be aesop_cat, but that broke with - https://github.com/leanprover/lean4/pull/4154 -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4154 + this used to be aesop_cat -/ ext x i₁ i₂ i₃ h : 2 simp only [categoryOfGradedObjects_comp, ιTensorObj₃'_tensorHom_assoc, associator_conjugation, ιTensorObj₃'_associator_hom, assoc, Iso.inv_hom_id_assoc, diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean index 6e11689c3fc8b..6dc28a06e73c9 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean @@ -420,7 +420,8 @@ def kernelCompMono {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasKernel f] [Mono g simp) inv := kernel.lift _ (kernel.ι _) (by simp) -#adaptation_note /-- nightly-2024-04-01 The `symm` wasn't previously necessary. -/ +#adaptation_note /-- nightly-2024-04-01 +The `symm` wasn't previously necessary. -/ instance hasKernel_iso_comp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] [HasKernel g] : HasKernel (f ≫ g) where exists_limit := @@ -874,7 +875,8 @@ theorem cokernel_not_mono_of_nonzero (w : f ≠ 0) : ¬Mono (cokernel.π f) := f theorem cokernel_not_iso_of_nonzero (w : f ≠ 0) : IsIso (cokernel.π f) → False := fun _ => cokernel_not_mono_of_nonzero w inferInstance -#adaptation_note /-- nightly-2024-04-01 The `symm` wasn't previously necessary. -/ +#adaptation_note /-- nightly-2024-04-01 +The `symm` wasn't previously necessary. -/ -- TODO the remainder of this section has obvious generalizations to `HasCoequalizer f g`. instance hasCokernel_comp_iso {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [HasCokernel f] [IsIso g] : HasCokernel (f ≫ g) where diff --git a/Mathlib/CategoryTheory/Monoidal/Mod_.lean b/Mathlib/CategoryTheory/Monoidal/Mod_.lean index cfb9163cb552c..570447a4586ad 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mod_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mod_.lean @@ -88,14 +88,11 @@ def forget : Mod_ A ⥤ C where open CategoryTheory.MonoidalCategory -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/6053 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/6053 we needed to increase the `maxHeartbeats` limit if we didn't write an explicit proof for `map_id` and `map_comp`. -This may indicate a configuration problem in Aesop. --/ +This may indicate a configuration problem in Aesop. -/ /-- A morphism of monoid objects induces a "restriction" or "comap" functor between the categories of module objects. -/ diff --git a/Mathlib/CategoryTheory/Monoidal/Mon_.lean b/Mathlib/CategoryTheory/Monoidal/Mon_.lean index f87726f0ec820..b03e0f9b350c3 100644 --- a/Mathlib/CategoryTheory/Monoidal/Mon_.lean +++ b/Mathlib/CategoryTheory/Monoidal/Mon_.lean @@ -246,14 +246,11 @@ namespace CategoryTheory.Functor variable {C} {D : Type u₂} [Category.{v₂} D] [MonoidalCategory.{v₂} D] -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/6053 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/6053 we needed to increase the `maxHeartbeats` limit if we didn't write an explicit proof for `map_id` and `map_comp`. -This may indicate a configuration problem in Aesop. --/ +This may indicate a configuration problem in Aesop. -/ -- TODO: mapMod F A : Mod A ⥤ Mod (F.mapMon A) /-- A lax monoidal functor takes monoid objects to monoid objects. diff --git a/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean index 09afedcc3b9aa..86dba8755a920 100644 --- a/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Rigid/Basic.lean @@ -148,12 +148,10 @@ attribute [instance] HasLeftDual.exact open ExactPairing HasRightDual HasLeftDual MonoidalCategory -#adaptation_note -/-- +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4596 The overlapping notation for `leftDual` and `leftAdjointMate` become more problematic in after https://github.com/leanprover/lean4/pull/4596, and we sometimes have to disambiguate with -e.g. `(ᘁX : C)` where previously just `ᘁX` was enough. --/ +e.g. `(ᘁX : C)` where previously just `ᘁX` was enough. -/ @[inherit_doc] prefix:1024 "ᘁ" => leftDual @[inherit_doc] postfix:1024 "ᘁ" => rightDual diff --git a/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean b/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean index b15c8b4f9117f..4452691a4e8ba 100644 --- a/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean +++ b/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean @@ -57,11 +57,8 @@ instance : Group (ZeroCochain G U) := Pi.group namespace Cochain₀ -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4481 -the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4481 +the `simpNF` linter incorrectly claims this lemma can't be applied by `simp`. -/ @[simp, nolint simpNF] lemma one_apply (i : I) : (1 : ZeroCochain G U) i = 1 := rfl diff --git a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean index 99b4e12ea6411..add552a2ee67a 100644 --- a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean +++ b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean @@ -182,7 +182,8 @@ theorem ruzsa_triangle_inequality_mul_mul_mul (A B C : Finset G) : refine le_trans ?_ (mul_le_mul (hUA _ hB') (cast_le.2 <| card_le_card <| mul_subset_mul_right hU.2) (zero_le _) (zero_le _)) - #adaptation_note /-- 2024-11-01 `le_div_iff₀` is synthesizing wrong `GroupWithZero` without `@` -/ + #adaptation_note /-- 2024-11-01 + `le_div_iff₀` is synthesizing wrong `GroupWithZero` without `@` -/ rw [← mul_div_right_comm, ← mul_assoc, @le_div_iff₀ _ (_) _ _ _ _ _ _ _ (cast_pos.2 hU.1.card_pos)] exact mod_cast pluennecke_petridis_inequality_mul C (mul_aux hU.1 hU.2 hUA) diff --git a/Mathlib/Combinatorics/SimpleGraph/Matching.lean b/Mathlib/Combinatorics/SimpleGraph/Matching.lean index 9f069cf54b51b..310d9aa562bd1 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Matching.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Matching.lean @@ -256,13 +256,11 @@ section Finite lemma even_card_of_isPerfectMatching [Fintype V] [DecidableEq V] [DecidableRel G.Adj] (c : ConnectedComponent G) (hM : M.IsPerfectMatching) : Even (Fintype.card c.supp) := by - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/5020, some instances that use the chain of coercions + #adaptation_note /-- https://github.com/leanprover/lean4/pull/5020 + some instances that use the chain of coercions `[SetLike X], X → Set α → Sort _` are blocked by the discrimination tree. This can be fixed by redeclaring the instance for `X` - using the double coercion but the proper fix seems to avoid the double coercion. - -/ + using the double coercion but the proper fix seems to avoid the double coercion. -/ letI : DecidablePred fun x ↦ x ∈ (M.induce c.supp).verts := fun a ↦ G.instDecidableMemSupp c a simpa using (hM.induce_connectedComponent_isMatching c).even_card diff --git a/Mathlib/Computability/RegularExpressions.lean b/Mathlib/Computability/RegularExpressions.lean index 8755552260ec8..a1922965cec30 100644 --- a/Mathlib/Computability/RegularExpressions.lean +++ b/Mathlib/Computability/RegularExpressions.lean @@ -92,7 +92,7 @@ theorem comp_def (P Q : RegularExpression α) : comp P Q = P * Q := rfl -- This was renamed to `matches'` during the port of Lean 4 as `matches` is a reserved word. -#adaptation_note /-- around nightly-2024-02-25, +#adaptation_note /-- nightly-2024-02-25 we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ /-- `matches' P` provides a language which contains all strings that `P` matches -/ -- Porting note: was '@[simp] but removed based on @@ -136,7 +136,7 @@ theorem matches'_pow (P : RegularExpression α) : ∀ n : ℕ, (P ^ n).matches' theorem matches'_star (P : RegularExpression α) : P.star.matches' = P.matches'∗ := rfl -#adaptation_note /-- around nightly-2024-02-25, +#adaptation_note /-- nightly-2024-02-25 we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ /-- `matchEpsilon P` is true if and only if `P` matches the empty string -/ def matchEpsilon : RegularExpression α → Bool @@ -150,7 +150,7 @@ def matchEpsilon : RegularExpression α → Bool section DecidableEq variable [DecidableEq α] -#adaptation_note /-- around nightly-2024-02-25, +#adaptation_note /-- nightly-2024-02-25 we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ /-- `P.deriv a` matches `x` if `P` matches `a :: x`, the Brzozowski derivative of `P` with respect to `a` -/ @@ -343,7 +343,7 @@ instance (P : RegularExpression α) : DecidablePred (· ∈ P.matches') := fun _ end DecidableEq -#adaptation_note /-- around nightly-2024-02-25, +#adaptation_note /-- nightly-2024-02-25 we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ /-- Map the alphabet of a regular expression. -/ @[simp] @@ -361,7 +361,7 @@ protected theorem map_pow (f : α → β) (P : RegularExpression α) : | 0 => by unfold map; rfl | n + 1 => (congr_arg (· * map f P) (RegularExpression.map_pow f P n) :) -#adaptation_note /-- around nightly-2024-02-25, +#adaptation_note /-- nightly-2024-02-25 we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ @[simp] theorem map_id : ∀ P : RegularExpression α, P.map id = P @@ -372,7 +372,7 @@ theorem map_id : ∀ P : RegularExpression α, P.map id = P | comp R S => by simp_rw [map, map_id]; rfl | star R => by simp_rw [map, map_id] -#adaptation_note /-- around nightly-2024-02-25, +#adaptation_note /-- nightly-2024-02-25 we need to write `comp x y` in the pattern `comp P Q`, instead of `x * y`. -/ @[simp] theorem map_map (g : β → γ) (f : α → β) : ∀ P : RegularExpression α, (P.map f).map g = P.map (g ∘ f) @@ -383,7 +383,7 @@ theorem map_map (g : β → γ) (f : α → β) : ∀ P : RegularExpression α, | comp R S => by simp only [map, Function.comp_apply, map_map] | star R => by simp only [map, Function.comp_apply, map_map] -#adaptation_note /-- around nightly-2024-02-25, +#adaptation_note /-- nightly-2024-02-25 we need to write `comp x y` in the pattern `comp R S`, instead of `x * y` (and the `erw` was just `rw`). -/ /-- The language of the map is the map of the language. -/ diff --git a/Mathlib/Data/Bool/Basic.lean b/Mathlib/Data/Bool/Basic.lean index 5f5bfc9ba28c8..0857104a5b71e 100644 --- a/Mathlib/Data/Bool/Basic.lean +++ b/Mathlib/Data/Bool/Basic.lean @@ -49,8 +49,8 @@ theorem or_eq_true_eq_eq_true_or_eq_true (a b : Bool) : theorem not_eq_true_eq_eq_false (a : Bool) : (not a = true) = (a = false) := by cases a <;> simp -#adaptation_note /-- this is no longer a simp lemma, - as after nightly-2024-03-05 the LHS simplifies. -/ +#adaptation_note /-- nightly-2024-03-05 +this is no longer a simp lemma, as the LHS simplifies. -/ theorem and_eq_false_eq_eq_false_or_eq_false (a b : Bool) : ((a && b) = false) = (a = false ∨ b = false) := by cases a <;> cases b <;> simp diff --git a/Mathlib/Data/DFinsupp/Sigma.lean b/Mathlib/Data/DFinsupp/Sigma.lean index 10d83e6df6193..c0fd6d64a85c2 100644 --- a/Mathlib/Data/DFinsupp/Sigma.lean +++ b/Mathlib/Data/DFinsupp/Sigma.lean @@ -63,8 +63,7 @@ theorem sigmaCurry_zero [∀ i j, Zero (δ i j)] : @[simp] theorem sigmaCurry_add [∀ i j, AddZeroClass (δ i j)] (f g : Π₀ (i : Σ _, _), δ i.1 i.2) : - #adaptation_note - /-- After https://github.com/leanprover/lean4/pull/6024 + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to add the `(_ : Π₀ (i) (j), δ i j)` type annotation. -/ sigmaCurry (f + g) = (sigmaCurry f + sigmaCurry g : Π₀ (i) (j), δ i j) := by ext (i j) @@ -73,8 +72,7 @@ theorem sigmaCurry_add [∀ i j, AddZeroClass (δ i j)] (f g : Π₀ (i : Σ _, @[simp] theorem sigmaCurry_smul [Monoid γ] [∀ i j, AddMonoid (δ i j)] [∀ i j, DistribMulAction γ (δ i j)] (r : γ) (f : Π₀ (i : Σ _, _), δ i.1 i.2) : - #adaptation_note - /-- After https://github.com/leanprover/lean4/pull/6024 + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to add the `(_ : Π₀ (i) (j), δ i j)` type annotation. -/ sigmaCurry (r • f) = (r • sigmaCurry f : Π₀ (i) (j), δ i j) := by ext (i j) diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index 6abe2e3b9c254..8edd359b3d1c9 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -1466,8 +1466,8 @@ theorem extendDomain_subtypeDomain (f : α →₀ M) (hf : ∀ a ∈ f.support, ext a by_cases h : P a · exact dif_pos h - · #adaptation_note - /-- Prior to nightly-2024-06-18, this `rw` was done by `dsimp`. -/ + · #adaptation_note /-- nightly-2024-06-18 + this `rw` was done by `dsimp`. -/ rw [extendDomain_toFun] dsimp rw [if_neg h, eq_comm, ← not_mem_support_iff] @@ -1478,8 +1478,8 @@ theorem extendDomain_subtypeDomain (f : α →₀ M) (hf : ∀ a ∈ f.support, theorem extendDomain_single (a : Subtype P) (m : M) : (single a m).extendDomain = single a.val m := by ext a' - #adaptation_note - /-- Prior to nightly-2024-06-18, this `rw` was instead `dsimp only`. -/ + #adaptation_note /-- nightly-2024-06-18 + this `rw` was instead `dsimp only`. -/ rw [extendDomain_toFun] obtain rfl | ha := eq_or_ne a.val a' · simp_rw [single_eq_same, dif_pos a.prop] diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 43a1475c35f4b..187b3b0cb21bc 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -383,7 +383,8 @@ theorem getLastI_eq_getLast? [Inhabited α] : ∀ l : List α, l.getLastI = l.ge | [_, _, _] => rfl | _ :: _ :: c :: l => by simp [getLastI, getLastI_eq_getLast? (c :: l)] -#adaptation_note /-- 2024-07-10: removed `@[simp]` since the LHS simplifies using the simp set. -/ +#adaptation_note /-- 2024-07-10 +removed `@[simp]` since the LHS simplifies using the simp set. -/ theorem getLast?_append_cons : ∀ (l₁ : List α) (a : α) (l₂ : List α), getLast? (l₁ ++ a :: l₂) = getLast? (a :: l₂) | [], _, _ => rfl @@ -1677,11 +1678,9 @@ theorem filter_eq_foldr (p : α → Bool) (l : List α) : filter p l = foldr (fun a out => bif p a then a :: out else out) [] l := by induction l <;> simp [*, filter]; rfl -#adaptation_note -/-- +#adaptation_note /-- nightly-2024-07-27 This has to be temporarily renamed to avoid an unintentional collision. -The prime should be removed at nightly-2024-07-27. --/ +The prime should be removed at nightly-2024-07-27. -/ @[simp] theorem filter_subset' (l : List α) : filter p l ⊆ l := (filter_sublist l).subset diff --git a/Mathlib/Data/Sign.lean b/Mathlib/Data/Sign.lean index 4607e88ca0d3e..ffb6b9cb726db 100644 --- a/Mathlib/Data/Sign.lean +++ b/Mathlib/Data/Sign.lean @@ -115,11 +115,8 @@ instance : BoundedOrder SignType where le_top := LE.of_pos bot := -1 bot_le := - #adaptation_note - /-- - Added `by exact` after https://github.com/leanprover/lean4/pull/6053, - but don't understand why it was needed. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6053 + Added `by exact`, but don't understand why it was needed. -/ by exact LE.of_neg instance : HasDistribNeg SignType := diff --git a/Mathlib/FieldTheory/KummerExtension.lean b/Mathlib/FieldTheory/KummerExtension.lean index 50462a0390dac..352ba6623e838 100644 --- a/Mathlib/FieldTheory/KummerExtension.lean +++ b/Mathlib/FieldTheory/KummerExtension.lean @@ -175,10 +175,8 @@ theorem Polynomial.separable_X_pow_sub_C_of_irreducible : (X ^ n - C a).Separabl AdjoinRoot.algebraMap_eq, X_pow_sub_C_eq_prod (hζ.map_of_injective (algebraMap K _).injective) hn (root_X_pow_sub_C_pow n a), separable_prod_X_sub_C_iff'] - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/5376 we need to provide this helper instance. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/5376 + we need to provide this helper instance. -/ have : MonoidHomClass (K →+* K[n√a]) K K[n√a] := inferInstance exact (hζ.map_of_injective (algebraMap K K[n√a]).injective).injOn_pow_mul (root_X_pow_sub_C_ne_zero (lt_of_le_of_ne (show 1 ≤ n from hn) (Ne.symm hn')) _) diff --git a/Mathlib/FieldTheory/Relrank.lean b/Mathlib/FieldTheory/Relrank.lean index 2ed666bbdae0a..aa621bbab5393 100644 --- a/Mathlib/FieldTheory/Relrank.lean +++ b/Mathlib/FieldTheory/Relrank.lean @@ -35,12 +35,10 @@ variable {E : Type v} [Field E] {L : Type w} [Field L] variable (A B C : Subfield E) -#adaptation_note -/-- +#adaptation_note /-- nightly-2024-11-14 This `synthInstance.maxHeartbeats` (and below) was required after nightly-2024-11-14; it's not exactly clear why, but we were very close to the limit previously, -so probably we should not particularly blame changes in Lean, and instead optimize in Mathlib. --/ +so probably we should not particularly blame changes in Lean, and instead optimize in Mathlib. -/ set_option synthInstance.maxHeartbeats 400000 in /-- `Subfield.relrank A B` is defined to be `[B : A ⊓ B]` as a `Cardinal`, in particular, when `A ≤ B` it is `[B : A]`, the degree of the field extension `B / A`. diff --git a/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean b/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean index d920ed0074190..158ebd2729aa1 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean @@ -81,12 +81,9 @@ end Module /-! ### Linear maps between normed spaces are differentiable -/ -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/6024 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to add the named arguments `𝕜 := 𝕜` and `F := ((F₂ →L[𝕜] F₃) →L[𝕜] F₁ →L[𝕜] F₃))` -to `ContinuousLinearMap.differentiable`. --/ +to `ContinuousLinearMap.differentiable`. -/ theorem MDifferentiableWithinAt.clm_precomp {f : M → F₁ →L[𝕜] F₂} {s : Set M} {x : M} (hf : MDifferentiableWithinAt I 𝓘(𝕜, F₁ →L[𝕜] F₂) f s x) : MDifferentiableWithinAt I 𝓘(𝕜, (F₂ →L[𝕜] F₃) →L[𝕜] (F₁ →L[𝕜] F₃)) @@ -95,12 +92,9 @@ theorem MDifferentiableWithinAt.clm_precomp {f : M → F₁ →L[𝕜] F₂} {s (ContinuousLinearMap.differentiable (𝕜 := 𝕜) (F := ((F₂ →L[𝕜] F₃) →L[𝕜] F₁ →L[𝕜] F₃)) (ContinuousLinearMap.compL 𝕜 F₁ F₂ F₃).flip) hf -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/6024 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to add the named arguments `𝕜 := 𝕜` and `F := ((F₂ →L[𝕜] F₃) →L[𝕜] F₁ →L[𝕜] F₃))` -to `ContinuousLinearMap.differentiable`. --/ +to `ContinuousLinearMap.differentiable`. -/ nonrec theorem MDifferentiableAt.clm_precomp {f : M → F₁ →L[𝕜] F₂} {x : M} (hf : MDifferentiableAt I 𝓘(𝕜, F₁ →L[𝕜] F₂) f x) : MDifferentiableAt I 𝓘(𝕜, (F₂ →L[𝕜] F₃) →L[𝕜] (F₁ →L[𝕜] F₃)) @@ -121,12 +115,9 @@ theorem MDifferentiable.clm_precomp (fun y ↦ (f y).precomp F₃ : M → (F₂ →L[𝕜] F₃) →L[𝕜] (F₁ →L[𝕜] F₃)) := fun x ↦ (hf x).clm_precomp -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/6024 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to add the named arguments `𝕜 := 𝕜` and `F := ((F₁ →L[𝕜] F₂) →L[𝕜] (F₁ →L[𝕜] F₃))` -to `ContinuousLinearMap.differentiable`. --/ +to `ContinuousLinearMap.differentiable`. -/ theorem MDifferentiableWithinAt.clm_postcomp {f : M → F₂ →L[𝕜] F₃} {s : Set M} {x : M} (hf : MDifferentiableWithinAt I 𝓘(𝕜, F₂ →L[𝕜] F₃) f s x) : MDifferentiableWithinAt I 𝓘(𝕜, (F₁ →L[𝕜] F₂) →L[𝕜] (F₁ →L[𝕜] F₃)) @@ -136,12 +127,9 @@ theorem MDifferentiableWithinAt.clm_postcomp {f : M → F₂ →L[𝕜] F₃} {s (ContinuousLinearMap.differentiable (𝕜 := 𝕜) (F := ((F₁ →L[𝕜] F₂) →L[𝕜] F₁ →L[𝕜] F₃)) (ContinuousLinearMap.compL 𝕜 F₁ F₂ F₃)) hf -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/6024 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to add the named arguments `𝕜 := 𝕜` and `F := ((F₁ →L[𝕜] F₂) →L[𝕜] (F₁ →L[𝕜] F₃))` -to `ContinuousLinearMap.differentiable`. --/ +to `ContinuousLinearMap.differentiable`. -/ theorem MDifferentiableAt.clm_postcomp {f : M → F₂ →L[𝕜] F₃} {x : M} (hf : MDifferentiableAt I 𝓘(𝕜, F₂ →L[𝕜] F₃) f x) : MDifferentiableAt I 𝓘(𝕜, (F₁ →L[𝕜] F₂) →L[𝕜] (F₁ →L[𝕜] F₃)) diff --git a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean index 7cb094aec1a0f..ce18362bd2a60 100644 --- a/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean +++ b/Mathlib/GroupTheory/FreeGroup/NielsenSchreier.lean @@ -93,12 +93,8 @@ theorem ext_functor {G} [Groupoid.{v} G] [IsFreeGroupoid G] {X : Type v} [Group let ⟨_, _, u⟩ := @unique_lift G _ _ X _ fun (a b : Generators G) (e : a ⟶ b) => g.map (of e) _root_.trans (u _ h) (u _ fun _ _ _ => rfl).symm -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{ e // _ }`. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/5338 +The new unused variable linter flags `{ e // _ }`. -/ set_option linter.unusedVariables false in /-- An action groupoid over a free group is free. More generally, one could show that the groupoid of elements over a free groupoid is free, but this version is easier to prove and suffices for our diff --git a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean index 1c1eeeec108bc..8ae2bfd5616d2 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean @@ -275,8 +275,8 @@ noncomputable def dualBasis (B : BilinForm K V) (hB : B.Nondegenerate) (b : Basi theorem dualBasis_repr_apply (B : BilinForm K V) (hB : B.Nondegenerate) (b : Basis ι K V) (x i) : (B.dualBasis hB b).repr x i = B x (b i) := by - #adaptation_note - /-- Before https://github.com/leanprover/lean4/pull/4814, we did not need the `@` in front of `toDual_def` in the `rw`. + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4814 + we did not need the `@` in front of `toDual_def` in the `rw`. I'm confused! -/ rw [dualBasis, Basis.map_repr, LinearEquiv.symm_symm, LinearEquiv.trans_apply, Basis.dualBasis_repr, @toDual_def] diff --git a/Mathlib/LinearAlgebra/Dual.lean b/Mathlib/LinearAlgebra/Dual.lean index a6c69a3ba7efa..295a03c7af209 100644 --- a/Mathlib/LinearAlgebra/Dual.lean +++ b/Mathlib/LinearAlgebra/Dual.lean @@ -1712,9 +1712,7 @@ theorem finiteDimensional_quot_dualCoannihilator_iff {W : Submodule K (Dual K V) FiniteDimensional K (V ⧸ W.dualCoannihilator) ↔ FiniteDimensional K W := ⟨fun _ ↦ FiniteDimensional.of_injective _ W.flip_quotDualCoannihilatorToDual_injective, fun _ ↦ by - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/4119 + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 the `Free K W` instance isn't found unless we use `set_option maxSynthPendingDepth 2`, or add explicit instances: ``` @@ -1896,4 +1894,4 @@ noncomputable def dualDistribEquiv : Dual R M ⊗[R] Dual R N ≃ₗ[R] Dual R ( end TensorProduct -set_option linter.style.longFile 2100 +set_option linter.style.longFile 2000 diff --git a/Mathlib/LinearAlgebra/Orientation.lean b/Mathlib/LinearAlgebra/Orientation.lean index 549ff52629c7b..004d248871f55 100644 --- a/Mathlib/LinearAlgebra/Orientation.lean +++ b/Mathlib/LinearAlgebra/Orientation.lean @@ -337,8 +337,8 @@ theorem eq_or_eq_neg [FiniteDimensional R M] (x₁ x₂ : Orientation R M ι) -- Porting note: this needs to be made explicit for the simp below have orientation_neg_neg : ∀ f : Basis ι R M, - -Basis.orientation f = Basis.orientation f := by - #adaptation_note - /-- `set_option maxSynthPendingDepth 2` required after https://github.com/leanprover/lean4/pull/4119 -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 + `set_option maxSynthPendingDepth 2` required -/ set_option maxSynthPendingDepth 2 in simp rcases e.orientation_eq_or_eq_neg x₁ with (h₁ | h₁) <;> rcases e.orientation_eq_or_eq_neg x₂ with (h₂ | h₂) <;> simp [h₁, h₂, orientation_neg_neg] diff --git a/Mathlib/LinearAlgebra/Semisimple.lean b/Mathlib/LinearAlgebra/Semisimple.lean index feb4bde80dc93..4135e45fe83c2 100644 --- a/Mathlib/LinearAlgebra/Semisimple.lean +++ b/Mathlib/LinearAlgebra/Semisimple.lean @@ -274,13 +274,10 @@ theorem IsSemisimple.of_mem_adjoin_pair {a : End K M} (ha : a ∈ Algebra.adjoin (AdjoinRoot.powerBasis' <| minpoly.monic <| Algebra.IsIntegral.isIntegral f).finite have : Module.Finite R S := (AdjoinRoot.powerBasis' <| (minpoly.monic <| Algebra.IsIntegral.isIntegral g).map _).finite - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/4119 we either need - to specify the `(S := R)` argument, or use `set_option maxSynthPendingDepth 2 in`. + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 + we either need to specify the `(S := R)` argument, or use `set_option maxSynthPendingDepth 2 in`. - In either case this step is too slow! - -/ + In either case this step is too slow! -/ set_option maxSynthPendingDepth 2 in have : IsScalarTower K R S := .of_algebraMap_eq fun _ ↦ rfl have : Module.Finite K S := .trans R S diff --git a/Mathlib/MeasureTheory/Group/Measure.lean b/Mathlib/MeasureTheory/Group/Measure.lean index 0dc9999c175a6..62c46156f922a 100644 --- a/Mathlib/MeasureTheory/Group/Measure.lean +++ b/Mathlib/MeasureTheory/Group/Measure.lean @@ -764,9 +764,7 @@ nonrec theorem _root_.MulEquiv.isHaarMeasure_map [BorelSpace G] [TopologicalGrou [TopologicalGroup H] (e : G ≃* H) (he : Continuous e) (hesymm : Continuous e.symm) : IsHaarMeasure (Measure.map e μ) := let f : G ≃ₜ H := .mk e - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/6024 + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we needed to write `e.toMonoidHom` instead of just `e`, to avoid unification issues. -/ isHaarMeasure_map μ e.toMonoidHom he e.surjective f.isClosedEmbedding.tendsto_cocompact diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean index b7600589ddd7c..14e6554bcb7bd 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean @@ -504,9 +504,7 @@ def arrowProdEquivProdArrow (α β γ : Type*) [MeasurableSpace α] [MeasurableS __ := Equiv.arrowProdEquivProdArrow α β γ measurable_toFun _ h := by simp_rw [Equiv.arrowProdEquivProdArrow, coe_fn_mk] - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/6024 + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 we need provide the type hints `(a : γ → α × β)`, to avoid unification issues. -/ exact MeasurableSet.preimage h (Measurable.prod_mk diff --git a/Mathlib/ModelTheory/PartialEquiv.lean b/Mathlib/ModelTheory/PartialEquiv.lean index 6a0442f49b37a..2c595a9111371 100644 --- a/Mathlib/ModelTheory/PartialEquiv.lean +++ b/Mathlib/ModelTheory/PartialEquiv.lean @@ -347,7 +347,8 @@ lemma partialEquivLimit_comp_inclusion {i : ι} : theorem le_partialEquivLimit (i : ι) : S i ≤ partialEquivLimit S := ⟨le_iSup (f := fun i ↦ (S i).dom) _, by - #adaptation_note /-- After https://github.com/leanprover/lean4/pull/5020, these two `simp` calls cannot be combined. -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/5020 + these two `simp` calls cannot be combined. -/ simp only [partialEquivLimit_comp_inclusion] simp only [cod_partialEquivLimit, dom_partialEquivLimit, ← Embedding.comp_assoc, subtype_comp_inclusion]⟩ diff --git a/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean b/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean index 7e288de6b9c30..bff8147059e58 100644 --- a/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean +++ b/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean @@ -98,8 +98,8 @@ theorem exists_approx_aux (n : ℕ) (h : abv.IsAdmissible) : · rwa [Finset.length_toList] · ext simpa [(Finset.nodup_toList _).getElem_inj_iff] using h - · #adaptation_note - /-- This proof was nicer prior to https://github.com/leanprover/lean4/pull/4400. + · #adaptation_note /-- https://github.com/leanprover/lean4/pull/4400 + This proof was nicer before. Please feel welcome to improve it, by avoiding use of `List.get` in favour of `GetElem`. -/ have : ∀ i h, t ((Finset.univ.filter fun x ↦ t x = s).toList.get ⟨i, h⟩) = s := fun i h ↦ (Finset.mem_filter.mp (Finset.mem_toList.mp (List.get_mem _ ⟨i, h⟩))).2 diff --git a/Mathlib/NumberTheory/Cyclotomic/Rat.lean b/Mathlib/NumberTheory/Cyclotomic/Rat.lean index dad9eca2e6965..6f56aadeff7a6 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Rat.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Rat.lean @@ -214,12 +214,10 @@ theorem integralPowerBasis_gen [hcycl : IsCyclotomicExtension {p ^ k} ℚ K] simp only [adjoinEquivRingOfIntegers_apply, IsIntegralClosure.algebraMap_lift] rfl -#adaptation_note -/-- +#adaptation_note /-- https://github.com/leanprover/lean4/pull/5338 We name `hcycl` so it can be used as a named argument, but since https://github.com/leanprover/lean4/pull/5338, this is considered unused, -so we need to disable the linter. --/ +so we need to disable the linter. -/ set_option linter.unusedVariables false in @[simp] theorem integralPowerBasis_dim [hcycl : IsCyclotomicExtension {p ^ k} ℚ K] diff --git a/Mathlib/NumberTheory/LSeries/Nonvanishing.lean b/Mathlib/NumberTheory/LSeries/Nonvanishing.lean index 24e61f8fb2458..c9d59f72fadfd 100644 --- a/Mathlib/NumberTheory/LSeries/Nonvanishing.lean +++ b/Mathlib/NumberTheory/LSeries/Nonvanishing.lean @@ -374,11 +374,8 @@ private lemma LFunction_ne_zero_of_not_quadratic_or_ne_one {t : ℝ} (h : χ ^ 2 -- go via absolute value to translate into a statement over `ℝ` replace H := (H₀.trans H).norm_right simp only [norm_eq_abs, abs_ofReal] at H - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/6024 - we needed to add `(F' := ℝ)` to `H.of_norm_right`. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 + we needed to add `(F' := ℝ)` to `H.of_norm_right`. -/ exact isLittleO_irrefl (.of_forall (fun _ ↦ one_ne_zero)) <| (H.of_norm_right (F' := ℝ)).trans_isLittleO <| isLittleO_id_one.mono nhdsWithin_le_nhds diff --git a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean index 1d17123834ee7..88da50e57f12c 100644 --- a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean +++ b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean @@ -400,9 +400,7 @@ theorem logEmbeddingQuot_injective : Function.comp_apply, EmbeddingLike.apply_eq_iff_eq] at h exact (EmbeddingLike.apply_eq_iff_eq _).mp <| (QuotientGroup.kerLift_injective _).eq_iff.mp h -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4119 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 the `Module ℤ (Additive ((𝓞 K)ˣ ⧸ NumberField.Units.torsion K))` instance required below isn't found unless we use `set_option maxSynthPendingDepth 2`, or add explicit instances: diff --git a/Mathlib/NumberTheory/NumberField/Units/Regulator.lean b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean index cd7cb76b5bf07..2f09783cc3433 100644 --- a/Mathlib/NumberTheory/NumberField/Units/Regulator.lean +++ b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean @@ -44,9 +44,7 @@ theorem regulator_ne_zero : regulator K ≠ 0 := ZLattice.covolume_ne_zero (unit theorem regulator_pos : 0 < regulator K := ZLattice.covolume_pos (unitLattice K) volume -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/4119 +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 the `Module ℤ (Additive ((𝓞 K)ˣ ⧸ NumberField.Units.torsion K))` instance required below isn't found unless we use `set_option maxSynthPendingDepth 2`, or add explicit instances: diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index 1c18bee75de0d..de11be3c0f851 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -356,22 +356,18 @@ theorem prod_mem_prod {ι : Type*} {s : Finset ι} {I : ι → Ideal R} {x : ι theorem mul_le_right : I * J ≤ I := Ideal.mul_le.2 fun _ hr _ _ => I.mul_mem_right _ hr -#adaptation_note -/-- -On nightly-2024-11-12, we had to add `nolint simpNF` to the following lemma, +#adaptation_note /-- nightly-2024-11-12 +we had to add `nolint simpNF` to the following lemma, as otherwise we get a deterministic timeout in typeclass inference. -This should be investigated. --/ +This should be investigated. -/ @[simp, nolint simpNF] theorem sup_mul_right_self : I ⊔ I * J = I := sup_eq_left.2 Ideal.mul_le_right -#adaptation_note -/-- -On nightly-2024-11-12, we had to add `nolint simpNF` to the following lemma, +#adaptation_note /-- nightly-2024-11-12 +we had to add `nolint simpNF` to the following lemma, as otherwise we get a deterministic timeout in typeclass inference. -This should be investigated. --/ +This should be investigated. -/ @[simp, nolint simpNF] theorem mul_right_self_sup : I * J ⊔ I = I := sup_eq_right.2 Ideal.mul_le_right diff --git a/Mathlib/RingTheory/Jacobson/Ring.lean b/Mathlib/RingTheory/Jacobson/Ring.lean index 68129d02d2fcb..aca96b49168c8 100644 --- a/Mathlib/RingTheory/Jacobson/Ring.lean +++ b/Mathlib/RingTheory/Jacobson/Ring.lean @@ -702,11 +702,8 @@ lemma finite_of_finite_type_of_isJacobsonRing (R S : Type*) [CommRing R] [Field obtain ⟨ι, hι, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial'.mp ‹_› have : (algebraMap R S).IsIntegral := by rw [← f.comp_algebraMap] - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/6024 - we needed to write `f.toRingHom` instead of just `f`, to avoid unification issues. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 + we needed to write `f.toRingHom` instead of just `f`, to avoid unification issues. -/ exact MvPolynomial.comp_C_integral_of_surjective_of_isJacobsonRing f.toRingHom hf have : Algebra.IsIntegral R S := Algebra.isIntegral_def.mpr this exact Algebra.IsIntegral.finite diff --git a/Mathlib/RingTheory/TensorProduct/Basic.lean b/Mathlib/RingTheory/TensorProduct/Basic.lean index 23244caec6a64..d1e5a3d2fd7c1 100644 --- a/Mathlib/RingTheory/TensorProduct/Basic.lean +++ b/Mathlib/RingTheory/TensorProduct/Basic.lean @@ -636,11 +636,9 @@ tensors can be directly applied by the caller (without needing `TensorProduct.on def algHomOfLinearMapTensorProduct (f : A ⊗[R] B →ₗ[S] C) (h_mul : ∀ (a₁ a₂ : A) (b₁ b₂ : B), f ((a₁ * a₂) ⊗ₜ (b₁ * b₂)) = f (a₁ ⊗ₜ b₁) * f (a₂ ⊗ₜ b₂)) (h_one : f (1 ⊗ₜ[R] 1) = 1) : A ⊗[R] B →ₐ[S] C := - #adaptation_note - /-- - After https://github.com/leanprover/lean4/pull/4119 we either need to specify - the `(R := S) (A := A ⊗[R] B)` arguments, or use `set_option maxSynthPendingDepth 2 in`. - -/ + #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 + we either need to specify the `(R := S) (A := A ⊗[R] B)` arguments, + or use `set_option maxSynthPendingDepth 2 in`. -/ AlgHom.ofLinearMap f h_one <| (f.map_mul_iff (R := S) (A := A ⊗[R] B)).2 <| by -- these instances are needed by the statement of `ext`, but not by the current definition. letI : Algebra R C := RestrictScalars.algebra R S C diff --git a/Mathlib/Tactic/NormNum/Pow.lean b/Mathlib/Tactic/NormNum/Pow.lean index 467a97ad68b3f..e5c8e7cd6b332 100644 --- a/Mathlib/Tactic/NormNum/Pow.lean +++ b/Mathlib/Tactic/NormNum/Pow.lean @@ -235,9 +235,7 @@ theorem isRat_zpow_neg {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb : IsRat (a^b) num den := by rwa [pb.out, Int.cast_negOfNat, zpow_neg, zpow_natCast] -#adaptation_note -/-- -Prior to https://github.com/leanprover/lean4/pull/4096, +#adaptation_note /-- https://github.com/leanprover/lean4/pull/4096 the repeated ``` have h : $e =Q (HPow.hPow (γ := $α) $a $b) := ⟨⟩ diff --git a/Mathlib/Topology/Algebra/Ring/Basic.lean b/Mathlib/Topology/Algebra/Ring/Basic.lean index 613f1181d73b9..84c683b719cfe 100644 --- a/Mathlib/Topology/Algebra/Ring/Basic.lean +++ b/Mathlib/Topology/Algebra/Ring/Basic.lean @@ -183,7 +183,8 @@ instance [NonUnitalNonAssocRing α] [NonUnitalNonAssocRing β] [TopologicalRing end -#adaptation_note /-- nightly-2024-04-08, needed to help `Pi.instTopologicalSemiring` -/ +#adaptation_note /-- nightly-2024-04-08 +needed to help `Pi.instTopologicalSemiring` -/ instance {β : Type*} {C : β → Type*} [∀ b, TopologicalSpace (C b)] [∀ b, NonUnitalNonAssocSemiring (C b)] [∀ b, TopologicalSemiring (C b)] : ContinuousAdd ((b : β) → C b) := diff --git a/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean b/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean index 09080f8e326cd..0939e3bde7b5e 100644 --- a/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean +++ b/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean @@ -94,12 +94,9 @@ instance (X : Type v) [t : TopologicalSpace X] [DiscreteTopology X] : rw [DiscreteTopology.eq_bot (t := t)] exact bot_le -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `[tY : TopologicalSpace Y]`, but we want to use this as a named argument. --/ +#adaptation_note /-- https://github.com/leanprover/lean4/pull/5338 +The new unused variable linter flags `[tY : TopologicalSpace Y]`, +but we want to use this as a named argument. -/ set_option linter.unusedVariables false in /-- Let `f : X → Y`. Suppose that to prove that `f` is continuous, it suffices to show that for every compact Hausdorff space `K` and every continuous map `g : K → X`, `f ∘ g` is continuous. From c6e9ee396fc501cdc740b21627b2179e04f1c35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 29 Jan 2025 11:17:56 +0000 Subject: [PATCH 634/681] feat(Algebra/Homology/Embedding): the homology of truncLE (#19574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given an embedding `e` of complex shapes that satisfies `IsTruncLE`, we show that the morphism `K.ιTruncLE e : K.truncLE e ⟶ K` induces a quasi-isomorphism in degree `e.f i` for all `i`. This is the dual result of #19572. Co-authored-by: Joël Riou <37772949+joelriou@users.noreply.github.com> --- Mathlib.lean | 1 + .../Homology/Embedding/TruncGEHomology.lean | 7 +- .../Homology/Embedding/TruncLEHomology.lean | 79 ++++++++++++++++++ Mathlib/Algebra/Homology/Opposite.lean | 81 +++++++++++++++++++ 4 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 Mathlib/Algebra/Homology/Embedding/TruncLEHomology.lean diff --git a/Mathlib.lean b/Mathlib.lean index 873393da66619..2570f69670348 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -451,6 +451,7 @@ import Mathlib.Algebra.Homology.Embedding.StupidTrunc import Mathlib.Algebra.Homology.Embedding.TruncGE import Mathlib.Algebra.Homology.Embedding.TruncGEHomology import Mathlib.Algebra.Homology.Embedding.TruncLE +import Mathlib.Algebra.Homology.Embedding.TruncLEHomology import Mathlib.Algebra.Homology.ExactSequence import Mathlib.Algebra.Homology.Factorizations.Basic import Mathlib.Algebra.Homology.Functor diff --git a/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean b/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean index d39f0d57c6052..33aa50866daca 100644 --- a/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean +++ b/Mathlib/Algebra/Homology/Embedding/TruncGEHomology.lean @@ -10,8 +10,8 @@ import Mathlib.Algebra.Homology.QuasiIso /-! # The homology of a canonical truncation -Given an embedding of complex shapes `e : Embedding c c'`, we shall -relate the homology of `K : HomologicalComplex C c'` and of +Given an embedding of complex shapes `e : Embedding c c'`, +we relate the homology of `K : HomologicalComplex C c'` and of `K.truncGE e : HomologicalComplex C c'`. The main result is that `K.πTruncGE e : K ⟶ K.truncGE e` induces a @@ -50,7 +50,8 @@ lemma hasHomology_of_not_mem_boundary (hj : ¬ e.BoundaryGE j) : (K.truncGE' e).HasHomology j := hasHomology_sc'_of_not_mem_boundary K e _ j _ rfl rfl hj -lemma quasiIsoAt_restrictionToTruncGE'_f (hj : ¬ e.BoundaryGE j) +/-- `K.restrictionToTruncGE' e` is a quasi-isomorphism in degrees that are not at the boundary. -/ +lemma quasiIsoAt_restrictionToTruncGE' (hj : ¬ e.BoundaryGE j) [(K.restriction e).HasHomology j] [(K.truncGE' e).HasHomology j] : QuasiIsoAt (K.restrictionToTruncGE' e) j := by rw [quasiIsoAt_iff] diff --git a/Mathlib/Algebra/Homology/Embedding/TruncLEHomology.lean b/Mathlib/Algebra/Homology/Embedding/TruncLEHomology.lean new file mode 100644 index 0000000000000..4e0871f9545d5 --- /dev/null +++ b/Mathlib/Algebra/Homology/Embedding/TruncLEHomology.lean @@ -0,0 +1,79 @@ +/- +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.Homology.Embedding.TruncGEHomology +import Mathlib.Algebra.Homology.Embedding.TruncLE + +/-! # The homology of a canonical truncation + +Given an embedding of complex shapes `e : Embedding c c'`, +we relate the homology of `K : HomologicalComplex C c'` and of +`K.truncLE e : HomologicalComplex C c'`. + +The main result is that `K.ιTruncLE e : K.truncLE e ⟶ K` induces a +quasi-isomorphism in degree `e.f i` for all `i`. (Note that the complex +`K.truncLE e` is exact in degrees that are not in the image of `e.f`.) + +All the results are obtained by dualising the results in the file `Embedding.TruncGEHomology`. + +-/ + +open CategoryTheory Category Limits + +namespace HomologicalComplex + +variable {ι ι' : Type*} {c : ComplexShape ι} {c' : ComplexShape ι'} + {C : Type*} [Category C] [HasZeroMorphisms C] + (K L : HomologicalComplex C c') (φ : K ⟶ L) (e : c.Embedding c') [e.IsTruncLE] + [∀ i', K.HasHomology i'] [∀ i', L.HasHomology i'] + +namespace truncLE' + +/-- `K.truncLE'ToRestriction e` is a quasi-isomorphism in degrees that are not at the boundary. -/ +lemma quasiIsoAt_truncLE'ToRestriction (j : ι) (hj : ¬ e.BoundaryLE j) + [(K.restriction e).HasHomology j] [(K.truncLE' e).HasHomology j] : + QuasiIsoAt (K.truncLE'ToRestriction e) j := by + dsimp only [truncLE'ToRestriction] + have : (K.op.restriction e.op).HasHomology j := + inferInstanceAs ((K.restriction e).op.HasHomology j) + rw [quasiIsoAt_unopFunctor_map_iff] + exact truncGE'.quasiIsoAt_restrictionToTruncGE' K.op e.op j (by simpa) + +instance truncLE'_hasHomology (i : ι) : (K.truncLE' e).HasHomology i := + inferInstanceAs ((K.op.truncGE' e.op).unop.HasHomology i) + +end truncLE' + +variable [HasZeroObject C] + +instance (i' : ι') : (K.truncLE e).HasHomology i' := + inferInstanceAs ((K.op.truncGE e.op).unop.HasHomology i') + +lemma quasiIsoAt_ιTruncLE {j : ι} {j' : ι'} (hj' : e.f j = j') : + QuasiIsoAt (K.ιTruncLE e) j' := by + have := K.op.quasiIsoAt_πTruncGE e.op hj' + exact inferInstanceAs (QuasiIsoAt ((unopFunctor _ _ ).map (K.op.πTruncGE e.op).op) j') + +instance (i : ι) : QuasiIsoAt (K.ιTruncLE e) (e.f i) := K.quasiIsoAt_ιTruncLE e rfl + +lemma quasiIso_ιTruncLE_iff_isSupported : + QuasiIso (K.ιTruncLE e) ↔ K.IsSupported e := by + rw [← quasiIso_opFunctor_map_iff, ← isSupported_op_iff] + exact K.op.quasiIso_πTruncGE_iff_isSupported e.op + +lemma acyclic_truncLE_iff_isSupportedOutside : + (K.truncLE e).Acyclic ↔ K.IsSupportedOutside e := by + rw [← acyclic_op_iff, ← isSupportedOutside_op_iff] + exact K.op.acyclic_truncGE_iff_isSupportedOutside e.op + +variable {K L} + +lemma quasiIso_truncLEMap_iff : + QuasiIso (truncLEMap φ e) ↔ ∀ (i : ι) (i' : ι') (_ : e.f i = i'), QuasiIsoAt φ i' := by + rw [← quasiIso_opFunctor_map_iff] + simp only [← quasiIsoAt_opFunctor_map_iff φ] + apply quasiIso_truncGEMap_iff + +end HomologicalComplex diff --git a/Mathlib/Algebra/Homology/Opposite.lean b/Mathlib/Algebra/Homology/Opposite.lean index 5bbd8fee09f16..cb42b8f38d5d4 100644 --- a/Mathlib/Algebra/Homology/Opposite.lean +++ b/Mathlib/Algebra/Homology/Opposite.lean @@ -7,6 +7,7 @@ import Mathlib.CategoryTheory.Abelian.Opposite import Mathlib.Algebra.Homology.Additive import Mathlib.Algebra.Homology.ImageToKernel import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex +import Mathlib.Algebra.Homology.QuasiIso /-! # Opposite categories of complexes @@ -221,6 +222,86 @@ instance (K : HomologicalComplex Vᵒᵖ c) (i : ι) [K.HasHomology i] : variable {V c} +@[simp] +lemma quasiIsoAt_opFunctor_map_iff + {K L : HomologicalComplex V c} (φ : K ⟶ L) (i : ι) + [K.HasHomology i] [L.HasHomology i] : + QuasiIsoAt ((opFunctor _ _).map φ.op) i ↔ QuasiIsoAt φ i := by + simp only [quasiIsoAt_iff] + exact ShortComplex.quasiIso_opMap_iff ((shortComplexFunctor V c i).map φ) + +@[simp] +lemma quasiIsoAt_unopFunctor_map_iff + {K L : HomologicalComplex Vᵒᵖ c} (φ : K ⟶ L) (i : ι) + [K.HasHomology i] [L.HasHomology i] : + QuasiIsoAt ((unopFunctor _ _).map φ.op) i ↔ QuasiIsoAt φ i := by + rw [← quasiIsoAt_opFunctor_map_iff] + rfl + +instance {K L : HomologicalComplex V c} (φ : K ⟶ L) (i : ι) + [K.HasHomology i] [L.HasHomology i] [QuasiIsoAt φ i] : + QuasiIsoAt ((opFunctor _ _).map φ.op) i := by + rw [quasiIsoAt_opFunctor_map_iff] + infer_instance + +instance {K L : HomologicalComplex Vᵒᵖ c} (φ : K ⟶ L) (i : ι) + [K.HasHomology i] [L.HasHomology i] [QuasiIsoAt φ i] : + QuasiIsoAt ((unopFunctor _ _).map φ.op) i := by + rw [quasiIsoAt_unopFunctor_map_iff] + infer_instance + +@[simp] +lemma quasiIso_opFunctor_map_iff + {K L : HomologicalComplex V c} (φ : K ⟶ L) + [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] : + QuasiIso ((opFunctor _ _).map φ.op) ↔ QuasiIso φ := by + simp only [quasiIso_iff, quasiIsoAt_opFunctor_map_iff] + +@[simp] +lemma quasiIso_unopFunctor_map_iff + {K L : HomologicalComplex Vᵒᵖ c} (φ : K ⟶ L) + [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] : + QuasiIso ((unopFunctor _ _).map φ.op) ↔ QuasiIso φ := by + simp only [quasiIso_iff, quasiIsoAt_unopFunctor_map_iff] + +instance {K L : HomologicalComplex V c} (φ : K ⟶ L) + [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] [QuasiIso φ] : + QuasiIso ((opFunctor _ _).map φ.op) := by + rw [quasiIso_opFunctor_map_iff] + infer_instance + +instance {K L : HomologicalComplex Vᵒᵖ c} (φ : K ⟶ L) + [∀ i, K.HasHomology i] [∀ i, L.HasHomology i] [QuasiIso φ] : + QuasiIso ((unopFunctor _ _).map φ.op) := by + rw [quasiIso_unopFunctor_map_iff] + infer_instance + +lemma ExactAt.op {K : HomologicalComplex V c} {i : ι} (h : K.ExactAt i) : + K.op.ExactAt i := + ShortComplex.Exact.op h + +lemma ExactAt.unop {K : HomologicalComplex Vᵒᵖ c} {i : ι} (h : K.ExactAt i) : + K.unop.ExactAt i := + ShortComplex.Exact.unop h + +@[simp] +lemma exactAt_op_iff (K : HomologicalComplex V c) {i : ι} : + K.op.ExactAt i ↔ K.ExactAt i := + ⟨fun h ↦ h.unop, fun h ↦ h.op⟩ + +lemma Acyclic.op {K : HomologicalComplex V c} (h : K.Acyclic) : + K.op.Acyclic := + fun i ↦ (h i).op + +lemma Acyclic.unop {K : HomologicalComplex Vᵒᵖ c} (h : K.Acyclic) : + K.unop.Acyclic := + fun i ↦ (h i).unop + +@[simp] +lemma acyclic_op_iff (K : HomologicalComplex V c) : + K.op.Acyclic ↔ K.Acyclic := + ⟨fun h ↦ h.unop, fun h ↦ h.op⟩ + /-- If `K` is a homological complex, then the homology of `K.op` identifies to the opposite of the homology of `K`. -/ def homologyOp (K : HomologicalComplex V c) (i : ι) [K.HasHomology i] : From 668ab19bddd137259659e69f7e5513bad62abc89 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Wed, 29 Jan 2025 11:17:57 +0000 Subject: [PATCH 635/681] chore: clean up adaptation note (#21210) --- Mathlib/Data/List/Defs.lean | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Mathlib/Data/List/Defs.lean b/Mathlib/Data/List/Defs.lean index 9718d8cc7eb2c..a0351827a88e0 100644 --- a/Mathlib/Data/List/Defs.lean +++ b/Mathlib/Data/List/Defs.lean @@ -488,10 +488,6 @@ theorem length_mapAccumr₂ : end MapAccumr -/- #adaptation_note: this attribute should be removed after Mathlib moves to v4.15.0-rc1. -/ -set_option allowUnsafeReducibility true in -attribute [semireducible] Fin.foldr.loop - section Deprecated @[deprecated List.mem_cons (since := "2024-08-10")] From 23e223e4cbe6f55c49ca01f8a94496ba84981f9c Mon Sep 17 00:00:00 2001 From: Xavier Roblot Date: Wed, 29 Jan 2025 11:58:51 +0000 Subject: [PATCH 636/681] feat(NumberTheory/AbelSummation): relax some hypothesis (#21214) Replace `IntegrableOn` by the weaker `LocallyIntegrableOn` at several places. Co-authored-by: Xavier Roblot <46200072+xroblot@users.noreply.github.com> --- Mathlib/NumberTheory/AbelSummation.lean | 28 ++++++++++++---------- Mathlib/NumberTheory/LSeries/SumCoeff.lean | 9 +++---- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Mathlib/NumberTheory/AbelSummation.lean b/Mathlib/NumberTheory/AbelSummation.lean index e31f094ec8fa5..3594e9a1f4abe 100644 --- a/Mathlib/NumberTheory/AbelSummation.lean +++ b/Mathlib/NumberTheory/AbelSummation.lean @@ -237,20 +237,21 @@ section limit open Filter Topology abelSummationProof intervalIntegral theorem locallyIntegrableOn_mul_sum_Icc {m : ℕ} (ha : 0 ≤ a) {g : ℝ → 𝕜} - (hg : IntegrableOn g (Set.Ici a)) : + (hg : LocallyIntegrableOn g (Set.Ici a)) : LocallyIntegrableOn (fun t ↦ g t * ∑ k ∈ Icc m ⌊t⌋₊, c k) (Set.Ici a) := by refine (locallyIntegrableOn_iff isLocallyClosed_Ici).mpr fun K hK₁ hK₂ ↦ ?_ by_cases hK₃ : K.Nonempty · have h_inf : a ≤ sInf K := (hK₁ (hK₂.sInf_mem hK₃)) refine IntegrableOn.mono_set ?_ (Bornology.IsBounded.subset_Icc_sInf_sSup hK₂.isBounded) - refine integrableOn_mul_sum_Icc _ (ha.trans h_inf) (hg.mono_set ?_) + refine integrableOn_mul_sum_Icc _ (ha.trans h_inf) ?_ + refine hg.integrableOn_compact_subset ?_ isCompact_Icc exact (Set.Icc_subset_Ici_iff (Real.sInf_le_sSup _ hK₂.bddBelow hK₂.bddAbove)).mpr h_inf · rw [Set.not_nonempty_iff_eq_empty.mp hK₃] exact integrableOn_empty theorem tendsto_sum_mul_atTop_nhds_one_sub_integral (hf_diff : ∀ t ∈ Set.Ici 0, DifferentiableAt ℝ f t) - (hf_int : IntegrableOn (deriv f) (Set.Ici 0)) {l : 𝕜} + (hf_int : LocallyIntegrableOn (deriv f) (Set.Ici 0)) {l : 𝕜} (h_lim : Tendsto (fun n : ℕ ↦ f n * ∑ k ∈ Icc 0 n, c k) atTop (𝓝 l)) {g : ℝ → 𝕜} (hg_dom : (fun t ↦ deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) =O[atTop] g) (hg_int : IntegrableAtFilter g atTop) : @@ -264,12 +265,12 @@ theorem tendsto_sum_mul_atTop_nhds_one_sub_integral <| (locallyIntegrableOn_mul_sum_Icc c le_rfl hf_int).integrableOn_of_isBigO_atTop hg_dom hg_int refine (h_lim.sub h_lim').congr (fun _ ↦ ?_) - rw [sum_mul_eq_sub_integral_mul' _ _ (fun t ht ↦ hf_diff _ ht.1) - (hf_int.mono_set Set.Icc_subset_Ici_self)] + rw [sum_mul_eq_sub_integral_mul' _ _ (fun t ht ↦ hf_diff _ ht.1)] + exact hf_int.integrableOn_compact_subset Set.Icc_subset_Ici_self isCompact_Icc theorem tendsto_sum_mul_atTop_nhds_one_sub_integral₀ (hc : c 0 = 0) (hf_diff : ∀ t ∈ Set.Ici 1, DifferentiableAt ℝ f t) - (hf_int : IntegrableOn (deriv f) (Set.Ici 1)) {l : 𝕜} + (hf_int : LocallyIntegrableOn (deriv f) (Set.Ici 1)) {l : 𝕜} (h_lim: Tendsto (fun n : ℕ ↦ f n * ∑ k ∈ Icc 0 n, c k) atTop (𝓝 l)) {g : ℝ → ℝ} (hg_dom : (fun t ↦ deriv f t * ∑ k ∈ Icc 0 ⌊t⌋₊, c k) =O[atTop] g) (hg_int : IntegrableAtFilter g atTop) : @@ -286,8 +287,8 @@ theorem tendsto_sum_mul_atTop_nhds_one_sub_integral₀ (hc : c 0 = 0) <| (locallyIntegrableOn_mul_sum_Icc c zero_le_one hf_int).integrableOn_of_isBigO_atTop hg_dom hg_int refine (h_lim.sub h_lim').congr (fun _ ↦ ?_) - rw [sum_mul_eq_sub_integral_mul₀' _ hc _ (fun t ht ↦ hf_diff _ ht.1) - (hf_int.mono_set Set.Icc_subset_Ici_self)] + rw [sum_mul_eq_sub_integral_mul₀' _ hc _ (fun t ht ↦ hf_diff _ ht.1)] + exact hf_int.integrableOn_compact_subset Set.Icc_subset_Ici_self isCompact_Icc end limit @@ -297,7 +298,7 @@ open Filter abelSummationProof private theorem summable_mul_of_bigO_atTop_aux (m : ℕ) (h_bdd : (fun n : ℕ ↦ ‖f n‖ * ∑ k ∈ Icc 0 n, ‖c k‖) =O[atTop] fun _ ↦ (1 : ℝ)) - (hf_int : IntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici (m : ℝ))) + (hf_int : LocallyIntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici (m : ℝ))) (hf : ∀ n : ℕ, ∑ k ∈ Icc 0 n, ‖f k‖ * ‖c k‖ = ‖f n‖ * ∑ k ∈ Icc 0 n, ‖c k‖ - ∫ (t : ℝ) in Set.Ioc ↑m ↑n, deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖) @@ -337,19 +338,19 @@ private theorem summable_mul_of_bigO_atTop_aux (m : ℕ) theorem summable_mul_of_bigO_atTop (hf_diff : ∀ t ∈ Set.Ici 0, DifferentiableAt ℝ (fun x ↦ ‖f x‖) t) - (hf_int : IntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici 0)) + (hf_int : LocallyIntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici 0)) (h_bdd : (fun n : ℕ ↦ ‖f n‖ * ∑ k ∈ Icc 0 n, ‖c k‖) =O[atTop] fun _ ↦ (1 : ℝ)) {g : ℝ → ℝ} (hg₁ : (fun t ↦ deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 0 ⌊t⌋₊, ‖c k‖) =O[atTop] g) (hg₂ : IntegrableAtFilter g atTop) : Summable (fun n : ℕ ↦ f n * c n) := by refine summable_mul_of_bigO_atTop_aux c 0 h_bdd (by rwa [Nat.cast_zero]) (fun n ↦ ?_) hg₁ hg₂ exact_mod_cast sum_mul_eq_sub_integral_mul' _ _ (fun _ ht ↦ hf_diff _ ht.1) - (hf_int.mono_set Set.Icc_subset_Ici_self) + (hf_int.integrableOn_compact_subset Set.Icc_subset_Ici_self isCompact_Icc) /-- A version of `summable_mul_of_bigO_atTop` that can be useful to avoid difficulties near zero. -/ theorem summable_mul_of_bigO_atTop' (hf_diff : ∀ t ∈ Set.Ici 1, DifferentiableAt ℝ (fun x ↦ ‖f x‖) t) - (hf_int : IntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici 1)) + (hf_int : LocallyIntegrableOn (deriv (fun t ↦ ‖f t‖)) (Set.Ici 1)) (h_bdd : (fun n : ℕ ↦ ‖f n‖ * ∑ k ∈ Icc 1 n, ‖c k‖) =O[atTop] fun _ ↦ (1 : ℝ)) {g : ℝ → ℝ} (hg₁ : (fun t ↦ deriv (fun t ↦ ‖f t‖) t * ∑ k ∈ Icc 1 ⌊t⌋₊, ‖c k‖) =O[atTop] g) (hg₂ : IntegrableAtFilter g atTop) : @@ -363,7 +364,8 @@ theorem summable_mul_of_bigO_atTop' refine Summable.congr_atTop (summable_mul_of_bigO_atTop_aux (fun n ↦ if n = 0 then 0 else c n) 1 h_bdd (by rwa [Nat.cast_one]) (fun n ↦ ?_) hg₁ hg₂) ?_ · exact_mod_cast sum_mul_eq_sub_integral_mul₀' _ (by simp only [reduceIte, norm_zero]) n - (fun _ ht ↦ hf_diff _ ht.1) (hf_int.mono_set Set.Icc_subset_Ici_self) + (fun _ ht ↦ hf_diff _ ht.1) + (hf_int.integrableOn_compact_subset Set.Icc_subset_Ici_self isCompact_Icc) · filter_upwards [eventually_ne_atTop 0] with k hk simp_rw [if_neg hk] diff --git a/Mathlib/NumberTheory/LSeries/SumCoeff.lean b/Mathlib/NumberTheory/LSeries/SumCoeff.lean index 35a11908fb0fe..3c70a12320fde 100644 --- a/Mathlib/NumberTheory/LSeries/SumCoeff.lean +++ b/Mathlib/NumberTheory/LSeries/SumCoeff.lean @@ -51,8 +51,8 @@ private theorem LSeriesSummable_of_sum_norm_bigO_aux (hf : f 0 = 0) simp_rw [LSeriesSummable, funext (LSeries.term_def₀ hf s), mul_comm (f _)] refine summable_mul_of_bigO_atTop' (f := fun t ↦ (t : ℂ) ^ (-s)) (g := fun t ↦ t ^ (-(s.re + 1) + r)) _ h₃ ?_ ?_ ?_ ?_ - · refine integrableOn_Ici_iff_integrableOn_Ioi.mpr - (integrableOn_Ioi_deriv_norm_ofReal_cpow zero_lt_one ?_) + · refine (integrableOn_Ici_iff_integrableOn_Ioi.mpr + (integrableOn_Ioi_deriv_norm_ofReal_cpow zero_lt_one ?_)).locallyIntegrableOn exact neg_re _ ▸ neg_nonpos.mpr <| hr.trans hs.le · refine (IsBigO.mul_atTop_rpow_natCast_of_isBigO_rpow _ _ _ ?_ hO h₂).congr_right (by simp) exact (norm_ofReal_cpow_eventually_eq_atTop _).isBigO.natCast_atTop @@ -108,8 +108,9 @@ private theorem LSeries_eq_mul_integral_aux {f : ℕ → ℂ} (hf : f 0 = 0) {r rw [deriv_ofReal_cpow_const (zero_lt_one.trans ht).ne', h₄] · ring_nf · exact neg_ne_zero.mpr <| ne_zero_of_re_pos (hr.trans_lt hs) - · refine integrableOn_Ici_iff_integrableOn_Ioi.mpr <| - integrableOn_Ioi_deriv_ofReal_cpow zero_lt_one (by simpa using hr.trans_lt hs) + · refine (integrableOn_Ici_iff_integrableOn_Ioi.mpr <| + integrableOn_Ioi_deriv_ofReal_cpow zero_lt_one + (by simpa using hr.trans_lt hs)).locallyIntegrableOn · have hlim : Tendsto (fun n : ℕ ↦ (n : ℝ) ^ (-(s.re - r))) atTop (𝓝 0) := (tendsto_rpow_neg_atTop (by rwa [sub_pos])).comp tendsto_natCast_atTop_atTop refine (IsBigO.mul_atTop_rpow_natCast_of_isBigO_rpow (-s.re) _ _ ?_ hO ?_).trans_tendsto hlim From 9940916465bd76d082431f2b30c68066ee93978d Mon Sep 17 00:00:00 2001 From: grunweg Date: Wed, 29 Jan 2025 13:57:05 +0000 Subject: [PATCH 637/681] chore(Geometry/Manifold): create IsManifold directory (#21218) Rename IsManifold.lean to IsManifold/Basic.lean, in preparating for a future commit splitting this file into several. Move InteriorBoundary.lean to this new directory. --- Mathlib.lean | 4 ++-- Mathlib/Geometry/Manifold/AnalyticManifold.lean | 2 +- Mathlib/Geometry/Manifold/ContMDiff/Defs.lean | 2 +- Mathlib/Geometry/Manifold/Instances/Real.lean | 4 ++-- Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean | 2 +- .../Manifold/{IsManifold.lean => IsManifold/Basic.lean} | 0 .../Geometry/Manifold/{ => IsManifold}/InteriorBoundary.lean | 2 +- Mathlib/Geometry/Manifold/MFDeriv/Defs.lean | 2 +- Mathlib/Geometry/Manifold/Metrizable.lean | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) rename Mathlib/Geometry/Manifold/{IsManifold.lean => IsManifold/Basic.lean} (100%) rename Mathlib/Geometry/Manifold/{ => IsManifold}/InteriorBoundary.lean (99%) diff --git a/Mathlib.lean b/Mathlib.lean index 2570f69670348..8292b7c698346 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3233,8 +3233,8 @@ import Mathlib.Geometry.Manifold.IntegralCurve.Basic import Mathlib.Geometry.Manifold.IntegralCurve.ExistUnique import Mathlib.Geometry.Manifold.IntegralCurve.Transform import Mathlib.Geometry.Manifold.IntegralCurve.UniformTime -import Mathlib.Geometry.Manifold.InteriorBoundary -import Mathlib.Geometry.Manifold.IsManifold +import Mathlib.Geometry.Manifold.IsManifold.Basic +import Mathlib.Geometry.Manifold.IsManifold.InteriorBoundary import Mathlib.Geometry.Manifold.LocalDiffeomorph import Mathlib.Geometry.Manifold.LocalInvariantProperties import Mathlib.Geometry.Manifold.MFDeriv.Atlas diff --git a/Mathlib/Geometry/Manifold/AnalyticManifold.lean b/Mathlib/Geometry/Manifold/AnalyticManifold.lean index 9b6c9a3025046..700a30607806f 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.Geometry.Manifold.IsManifold +import Mathlib.Geometry.Manifold.IsManifold.Basic /-! # Analytic manifolds (possibly with boundary or corners) diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean index 4bb05df82f4ff..ee537cfccc4d7 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Floris van Doorn -/ -import Mathlib.Geometry.Manifold.IsManifold +import Mathlib.Geometry.Manifold.IsManifold.Basic import Mathlib.Geometry.Manifold.LocalInvariantProperties /-! diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index 78db01d88e9e2..f18b90045c1e6 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -3,8 +3,8 @@ Copyright (c) 2019 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.Geometry.Manifold.InteriorBoundary -import Mathlib.Geometry.Manifold.IsManifold +import Mathlib.Geometry.Manifold.IsManifold.Basic +import Mathlib.Geometry.Manifold.IsManifold.InteriorBoundary import Mathlib.Analysis.InnerProductSpace.PiL2 /-! diff --git a/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean b/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean index 9a921471207e6..3f35ee20c69bf 100644 --- a/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean +++ b/Mathlib/Geometry/Manifold/IntegralCurve/ExistUnique.lean @@ -6,7 +6,7 @@ Authors: Winston Yin import Mathlib.Analysis.ODE.Gronwall import Mathlib.Analysis.ODE.PicardLindelof import Mathlib.Geometry.Manifold.IntegralCurve.Transform -import Mathlib.Geometry.Manifold.InteriorBoundary +import Mathlib.Geometry.Manifold.IsManifold.InteriorBoundary /-! # Existence and uniqueness of integral curves diff --git a/Mathlib/Geometry/Manifold/IsManifold.lean b/Mathlib/Geometry/Manifold/IsManifold/Basic.lean similarity index 100% rename from Mathlib/Geometry/Manifold/IsManifold.lean rename to Mathlib/Geometry/Manifold/IsManifold/Basic.lean diff --git a/Mathlib/Geometry/Manifold/InteriorBoundary.lean b/Mathlib/Geometry/Manifold/IsManifold/InteriorBoundary.lean similarity index 99% rename from Mathlib/Geometry/Manifold/InteriorBoundary.lean rename to Mathlib/Geometry/Manifold/IsManifold/InteriorBoundary.lean index 4feb7faf82ea2..9cc24f55b4158 100644 --- a/Mathlib/Geometry/Manifold/InteriorBoundary.lean +++ b/Mathlib/Geometry/Manifold/IsManifold/InteriorBoundary.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Rothgang -/ -import Mathlib.Geometry.Manifold.IsManifold +import Mathlib.Geometry.Manifold.IsManifold.Basic /-! # Interior and boundary of a manifold diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean index c269a880e9c26..8fae4d69ee6bd 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Floris van Doorn -/ -import Mathlib.Geometry.Manifold.IsManifold +import Mathlib.Geometry.Manifold.IsManifold.Basic import Mathlib.Geometry.Manifold.LocalInvariantProperties /-! diff --git a/Mathlib/Geometry/Manifold/Metrizable.lean b/Mathlib/Geometry/Manifold/Metrizable.lean index 5427ae259b734..fa2cb6d5dd892 100644 --- a/Mathlib/Geometry/Manifold/Metrizable.lean +++ b/Mathlib/Geometry/Manifold/Metrizable.lean @@ -3,7 +3,7 @@ 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.Geometry.Manifold.IsManifold +import Mathlib.Geometry.Manifold.IsManifold.Basic import Mathlib.Topology.Compactness.Paracompact import Mathlib.Topology.Metrizable.Urysohn From 079bdfd34fc207343718cf01d94f49ffd3b490f9 Mon Sep 17 00:00:00 2001 From: kvanvels Date: Wed, 29 Jan 2025 14:04:40 +0000 Subject: [PATCH 638/681] chore:(MeasureTheory) replace `open scoped Classical` with `open scoped Classical in` or `classical` in a tactic proof. (#21217) reduces some technical debt by replacing `open scoped Classical` with `open scoped classical in` or adding `classical` tactic to a tactic proof. --- .../MeasureTheory/Covering/Besicovitch.lean | 5 ++++- .../MeasureTheory/Decomposition/Jordan.lean | 3 +-- .../Decomposition/RadonNikodym.lean | 2 +- .../Decomposition/SignedHahn.lean | 6 ++++- .../Decomposition/SignedLebesgue.lean | 2 +- .../Function/AEMeasurableOrder.lean | 2 +- .../ConditionalExpectation/CondexpL1.lean | 3 +-- Mathlib/MeasureTheory/Function/Egorov.lean | 1 - Mathlib/MeasureTheory/Function/L1Space.lean | 3 ++- .../MeasureTheory/Function/SimpleFunc.lean | 22 ++++++++++++++++++- .../Function/SimpleFuncDense.lean | 1 - .../Function/SimpleFuncDenseLp.lean | 2 +- .../Function/UniformIntegrable.lean | 3 ++- .../Integral/DivergenceTheorem.lean | 2 +- .../Integral/FundThmCalculus.lean | 3 +-- .../Integral/IntervalIntegral.lean | 3 +-- Mathlib/MeasureTheory/Integral/Prod.lean | 3 ++- .../MeasureTheory/Integral/SetIntegral.lean | 3 ++- Mathlib/MeasureTheory/MeasurableSpace/Pi.lean | 2 +- 19 files changed, 48 insertions(+), 23 deletions(-) diff --git a/Mathlib/MeasureTheory/Covering/Besicovitch.lean b/Mathlib/MeasureTheory/Covering/Besicovitch.lean index 9f8b24ead46f2..b2868a890cc06 100644 --- a/Mathlib/MeasureTheory/Covering/Besicovitch.lean +++ b/Mathlib/MeasureTheory/Covering/Besicovitch.lean @@ -102,7 +102,7 @@ universe u open Metric Set Filter Fin MeasureTheory TopologicalSpace -open scoped Topology Classical ENNReal MeasureTheory NNReal +open scoped Topology ENNReal MeasureTheory NNReal /-! ### Satellite configurations @@ -528,6 +528,7 @@ theorem exist_finset_disjoint_balls_large_measure (μ : Measure α) [IsFiniteMea (rpos : ∀ x ∈ s, 0 < r x) (rle : ∀ x ∈ s, r x ≤ 1) : ∃ t : Finset α, ↑t ⊆ s ∧ μ (s \ ⋃ x ∈ t, closedBall x (r x)) ≤ N / (N + 1) * μ s ∧ (t : Set α).PairwiseDisjoint fun x => closedBall x (r x) := by + classical -- exclude the trivial case where `μ s = 0`. rcases le_or_lt (μ s) 0 with (hμs | hμs) · have : μ s = 0 := le_bot_iff.1 hμs @@ -667,6 +668,7 @@ theorem exists_disjoint_closedBall_covering_ae_of_finiteMeasure_aux (μ : Measur ∃ t : Set (α × ℝ), t.Countable ∧ (∀ p ∈ t, p.1 ∈ s) ∧ (∀ p ∈ t, p.2 ∈ f p.1) ∧ μ (s \ ⋃ (p : α × ℝ) (_ : p ∈ t), closedBall p.1 p.2) = 0 ∧ t.PairwiseDisjoint fun p => closedBall p.1 p.2 := by + classical rcases HasBesicovitchCovering.no_satelliteConfig (α := α) with ⟨N, τ, hτ, hN⟩ /- Introduce a property `P` on finsets saying that we have a nice disjoint covering of a subset of `s` by admissible balls. -/ @@ -862,6 +864,7 @@ theorem exists_closedBall_covering_tsum_measure_le (μ : Measure α) [SFinite μ disjoint subfamilies. Making sure that they are all included in a neighborhood `v` of `s'` of measure at most `ε / (2 N)`, the sum of their measures is at most `ε / 2`, completing the proof. -/ + classical obtain ⟨u, su, u_open, μu⟩ : ∃ U, U ⊇ s ∧ IsOpen U ∧ μ U ≤ μ s + ε / 2 := Set.exists_isOpen_le_add _ _ (by diff --git a/Mathlib/MeasureTheory/Decomposition/Jordan.lean b/Mathlib/MeasureTheory/Decomposition/Jordan.lean index ce9122ea87126..e4c8c69908a4c 100644 --- a/Mathlib/MeasureTheory/Decomposition/Jordan.lean +++ b/Mathlib/MeasureTheory/Decomposition/Jordan.lean @@ -43,7 +43,7 @@ Jordan decomposition theorem noncomputable section -open scoped Classical MeasureTheory ENNReal NNReal +open scoped MeasureTheory ENNReal NNReal variable {α : Type*} [MeasurableSpace α] @@ -185,7 +185,6 @@ end JordanDecomposition namespace SignedMeasure -open scoped Classical open JordanDecomposition Measure Set VectorMeasure variable {s : SignedMeasure α} diff --git a/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean b/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean index d0c1bf8f1d942..f8f7b82e72071 100644 --- a/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean +++ b/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean @@ -43,7 +43,7 @@ Radon-Nikodym theorem noncomputable section -open scoped Classical MeasureTheory NNReal ENNReal +open scoped MeasureTheory NNReal ENNReal variable {α β : Type*} {m : MeasurableSpace α} diff --git a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean index 0a690c953d507..003de465b8ccb 100644 --- a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean +++ b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean @@ -37,7 +37,7 @@ Hahn decomposition theorem noncomputable section -open scoped Classical NNReal ENNReal MeasureTheory +open scoped NNReal ENNReal MeasureTheory variable {α β : Type*} [MeasurableSpace α] variable {M : Type*} [AddCommMonoid M] [TopologicalSpace M] [OrderedAddCommMonoid M] @@ -99,6 +99,7 @@ private theorem existsNatOneDivLTMeasure_of_not_negative (hi : ¬s ≤[i] 0) : let ⟨n, hn⟩ := exists_nat_one_div_lt hj ⟨n, k, hj₂, hj₁, hn⟩ +open scoped Classical in /-- Given the set `i`, if `i` is not negative, `findExistsOneDivLT s i` is the least natural number `n` such that `ExistsOneDivLT s i n`, otherwise, it returns 0. -/ private def findExistsOneDivLT (s : SignedMeasure α) (i : Set α) : ℕ := @@ -111,9 +112,11 @@ private theorem findExistsOneDivLT_spec (hi : ¬s ≤[i] 0) : private theorem findExistsOneDivLT_min (hi : ¬s ≤[i] 0) {m : ℕ} (hm : m < findExistsOneDivLT s i) : ¬ExistsOneDivLT s i m := by + classical rw [findExistsOneDivLT, dif_pos hi] at hm exact Nat.find_min _ hm +open scoped Classical in /-- Given the set `i`, if `i` is not negative, `someExistsOneDivLT` chooses the set `k` from `ExistsOneDivLT s i (findExistsOneDivLT s i)`, otherwise, it returns the empty set. -/ @@ -222,6 +225,7 @@ private theorem restrictNonposSeq_disjoint : Pairwise (Disjoint on restrictNonpo private theorem exists_subset_restrict_nonpos' (hi₁ : MeasurableSet i) (hi₂ : s i < 0) (hn : ¬∀ n : ℕ, ¬s ≤[i \ ⋃ l < n, restrictNonposSeq s i l] 0) : ∃ j : Set α, MeasurableSet j ∧ j ⊆ i ∧ s ≤[j] 0 ∧ s j < 0 := by + classical by_cases h : s ≤[i] 0 · exact ⟨i, hi₁, Set.Subset.refl _, h, hi₂⟩ push_neg at hn diff --git a/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean b/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean index 354c4e16c0210..c20637659cb29 100644 --- a/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean +++ b/Mathlib/MeasureTheory/Decomposition/SignedLebesgue.lean @@ -42,7 +42,7 @@ Lebesgue decomposition theorem noncomputable section -open scoped Classical MeasureTheory NNReal ENNReal +open scoped MeasureTheory NNReal ENNReal open Set diff --git a/Mathlib/MeasureTheory/Function/AEMeasurableOrder.lean b/Mathlib/MeasureTheory/Function/AEMeasurableOrder.lean index 0f4dba7c8de33..a26a30a2fad26 100644 --- a/Mathlib/MeasureTheory/Function/AEMeasurableOrder.lean +++ b/Mathlib/MeasureTheory/Function/AEMeasurableOrder.lean @@ -23,7 +23,6 @@ as possible. open MeasureTheory Set TopologicalSpace -open scoped Classical open ENNReal NNReal /-- If a function `f : α → β` is such that the level sets `{f < p}` and `{q < f}` have measurable @@ -36,6 +35,7 @@ theorem MeasureTheory.aemeasurable_of_exist_almost_disjoint_supersets {α : Type (h : ∀ p ∈ s, ∀ q ∈ s, p < q → ∃ u v, MeasurableSet u ∧ MeasurableSet v ∧ { x | f x < p } ⊆ u ∧ { x | q < f x } ⊆ v ∧ μ (u ∩ v) = 0) : AEMeasurable f μ := by + classical haveI : Encodable s := s_count.toEncodable have h' : ∀ p q, ∃ u v, MeasurableSet u ∧ MeasurableSet v ∧ { x | f x < p } ⊆ u ∧ { x | q < f x } ⊆ v ∧ (p ∈ s → q ∈ s → p < q → μ (u ∩ v) = 0) := by diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean index 59eff72389d34..5bb82053bb176 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean @@ -170,11 +170,10 @@ alias condexpIndL1Fin_disjoint_union := condExpIndL1Fin_disjoint_union end CondexpIndL1Fin -open scoped Classical - section CondexpIndL1 +open scoped Classical in /-- Conditional expectation of the indicator of a set, as a function in L1. Its value for sets which are not both measurable and of finite measure is not used: we set it to 0. -/ def condExpIndL1 {m m0 : MeasurableSpace α} (hm : m ≤ m0) (μ : Measure α) (s : Set α) diff --git a/Mathlib/MeasureTheory/Function/Egorov.lean b/Mathlib/MeasureTheory/Function/Egorov.lean index 9e40665728a34..104398ecddfc9 100644 --- a/Mathlib/MeasureTheory/Function/Egorov.lean +++ b/Mathlib/MeasureTheory/Function/Egorov.lean @@ -23,7 +23,6 @@ convergence in measure. noncomputable section -open scoped Classical open MeasureTheory NNReal ENNReal Topology namespace MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 11feddd7f0440..ddb275e70d230 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -48,7 +48,6 @@ integrable, function space, l1 noncomputable section -open scoped Classical open Topology ENNReal MeasureTheory NNReal open Set Filter TopologicalSpace ENNReal EMetric MeasureTheory @@ -529,6 +528,7 @@ theorem integrable_zero_measure {_ : MeasurableSpace α} {f : α → β} : theorem integrable_finset_sum_measure {ι} {m : MeasurableSpace α} {f : α → β} {μ : ι → Measure α} {s : Finset ι} : Integrable f (∑ i ∈ s, μ i) ↔ ∀ i ∈ s, Integrable f (μ i) := by + classical induction s using Finset.induction_on <;> simp [*] theorem Integrable.smul_measure {f : α → β} (h : Integrable f μ) {c : ℝ≥0∞} (hc : c ≠ ∞) : @@ -559,6 +559,7 @@ theorem Integrable.to_average {f : α → β} (h : Integrable f μ) : Integrable · apply h.smul_measure simpa +open scoped Classical in theorem integrable_average [IsFiniteMeasure μ] {f : α → β} : Integrable f ((μ univ)⁻¹ • μ) ↔ Integrable f μ := (eq_or_ne μ 0).by_cases (fun h => by simp [h]) fun h => diff --git a/Mathlib/MeasureTheory/Function/SimpleFunc.lean b/Mathlib/MeasureTheory/Function/SimpleFunc.lean index 3d030c368a939..80239aa069a9a 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFunc.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFunc.lean @@ -28,7 +28,6 @@ open Filter ENNReal open Function (support) -open scoped Classical open Topology NNReal ENNReal MeasureTheory namespace MeasureTheory @@ -177,6 +176,7 @@ theorem sum_range_measure_preimage_singleton (f : α →ₛ β) (μ : Measure α (∑ y ∈ f.range, μ (f ⁻¹' {y})) = μ univ := by rw [f.sum_measure_preimage_singleton, coe_range, preimage_range] +open scoped Classical in /-- If-then-else as a `SimpleFunc`. -/ def piecewise (s : Set α) (hs : MeasurableSet s) (f g : α →ₛ β) : α →ₛ β := ⟨s.piecewise f g, fun _ => @@ -184,15 +184,18 @@ def piecewise (s : Set α) (hs : MeasurableSet s) (f g : α →ₛ β) : α → f.measurable.piecewise hs g.measurable trivial, (f.finite_range.union g.finite_range).subset range_ite_subset⟩ +open scoped Classical in @[simp] theorem coe_piecewise {s : Set α} (hs : MeasurableSet s) (f g : α →ₛ β) : ⇑(piecewise s hs f g) = s.piecewise f g := rfl +open scoped Classical in theorem piecewise_apply {s : Set α} (hs : MeasurableSet s) (f g : α →ₛ β) (a) : piecewise s hs f g a = if a ∈ s then f a else g a := rfl +open scoped Classical in @[simp] theorem piecewise_compl {s : Set α} (hs : MeasurableSet sᶜ) (f g : α →ₛ β) : piecewise sᶜ hs f g = piecewise s hs.of_compl g f := @@ -206,6 +209,7 @@ theorem piecewise_univ (f g : α →ₛ β) : piecewise univ MeasurableSet.univ theorem piecewise_empty (f g : α →ₛ β) : piecewise ∅ MeasurableSet.empty f g = g := coe_injective <| by simp +open scoped Classical in @[simp] theorem piecewise_same (f : α →ₛ β) {s : Set α} (hs : MeasurableSet s) : piecewise s hs f f = f := @@ -215,6 +219,7 @@ theorem support_indicator [Zero β] {s : Set α} (hs : MeasurableSet s) (f : α Function.support (f.piecewise s hs (SimpleFunc.const α 0)) = s ∩ Function.support f := Set.support_indicator +open scoped Classical in theorem range_indicator {s : Set α} (hs : MeasurableSet s) (hs_nonempty : s.Nonempty) (hs_ne_univ : s ≠ univ) (x y : β) : (piecewise s hs (const α x) (const α y)).range = {x, y} := by @@ -261,12 +266,14 @@ theorem range_map [DecidableEq γ] (g : β → γ) (f : α →ₛ β) : (f.map g theorem map_const (g : β → γ) (b : β) : (const α b).map g = const α (g b) := rfl +open scoped Classical in theorem map_preimage (f : α →ₛ β) (g : β → γ) (s : Set γ) : f.map g ⁻¹' s = f ⁻¹' ↑{b ∈ f.range | g b ∈ s} := by simp only [coe_range, sep_mem_eq, coe_map, Finset.coe_filter, ← mem_preimage, inter_comm, preimage_inter_range, ← Finset.mem_coe] exact preimage_comp +open scoped Classical in theorem map_preimage_singleton (f : α →ₛ β) (g : β → γ) (c : γ) : f.map g ⁻¹' {c} = f ⁻¹' ↑{b ∈ f.range | g b = c} := map_preimage _ _ _ @@ -560,6 +567,7 @@ instance instPreorder : Preorder (α →ₛ β) := Preorder.lift (⇑) @[gcongr] protected alias ⟨_, GCongr.coe_le_coe⟩ := coe_le_coe @[gcongr] protected alias ⟨_, GCongr.coe_lt_coe⟩ := coe_lt_coe +open scoped Classical in @[gcongr] lemma piecewise_mono (hf : ∀ a ∈ s, f₁ a ≤ f₂ a) (hg : ∀ a ∉ s, g₁ a ≤ g₂ a) : piecewise s hs f₁ g₁ ≤ piecewise s hs f₂ g₂ := Set.piecewise_mono hf hg @@ -600,6 +608,7 @@ instance instBoundedOrder [LE β] [BoundedOrder β] : BoundedOrder (α →ₛ β theorem finset_sup_apply [SemilatticeSup β] [OrderBot β] {f : γ → α →ₛ β} (s : Finset γ) (a : α) : s.sup f a = s.sup fun c => f c a := by + classical refine Finset.induction_on s rfl ?_ intro a s _ ih rw [Finset.sup_insert, Finset.sup_insert, sup_apply, ih] @@ -608,6 +617,7 @@ section Restrict variable [Zero β] +open scoped Classical in /-- Restrict a simple function `f : α →ₛ β` to a set `s`. If `s` is measurable, then `f.restrict s a = if a ∈ s then f a else 0`, otherwise `f.restrict s = const α 0`. -/ def restrict (f : α →ₛ β) (s : Set α) : α →ₛ β := @@ -620,6 +630,7 @@ theorem restrict_of_not_measurable {f : α →ₛ β} {s : Set α} (hs : ¬Measu @[simp] theorem coe_restrict (f : α →ₛ β) {s : Set α} (hs : MeasurableSet s) : ⇑(restrict f s) = indicator s f := by + classical rw [restrict, dif_pos hs, coe_piecewise, coe_zero, piecewise_eq_indicator] @[simp] @@ -628,6 +639,7 @@ theorem restrict_univ (f : α →ₛ β) : restrict f univ = f := by simp [restr @[simp] theorem restrict_empty (f : α →ₛ β) : restrict f ∅ = 0 := by simp [restrict] +open scoped Classical in theorem map_restrict_of_zero [Zero γ] {g : β → γ} (hg : g 0 = 0) (f : α →ₛ β) (s : Set α) : (f.restrict s).map g = (f.map g).restrict s := ext fun x => @@ -657,6 +669,7 @@ theorem mem_restrict_range {r : β} {s : Set α} {f : α →ₛ β} (hs : Measur r ∈ (restrict f s).range ↔ r = 0 ∧ s ≠ univ ∨ r ∈ f '' s := by rw [← Finset.mem_coe, coe_range, coe_restrict _ hs, mem_range_indicator] +open scoped Classical in theorem mem_image_of_mem_range_restrict {r : β} {s : Set α} {f : α →ₛ β} (hr : r ∈ (restrict f s).range) (h0 : r ≠ 0) : r ∈ f '' s := if hs : MeasurableSet s then by simpa [mem_restrict_range hs, h0, -mem_range] using hr @@ -664,6 +677,7 @@ theorem mem_image_of_mem_range_restrict {r : β} {s : Set α} {f : α →ₛ β} rw [restrict_of_not_measurable hs] at hr exact (h0 <| eq_zero_of_mem_range_zero hr).elim +open scoped Classical in @[gcongr, mono] theorem restrict_mono [Preorder β] (s : Set α) {f g : α →ₛ β} (H : f ≤ g) : f.restrict s ≤ g.restrict s := @@ -685,6 +699,7 @@ of the set `{i k | k ≤ n ∧ i k ≤ f a}`, see `approx_apply` and `iSup_appro def approx (i : ℕ → β) (f : α → β) (n : ℕ) : α →ₛ β := (Finset.range n).sup fun k => restrict (const α (i k)) { a : α | i k ≤ f a } +open scoped Classical in theorem approx_apply [TopologicalSpace β] [OrderClosedTopology β] [MeasurableSpace β] [OpensMeasurableSpace β] {i : ℕ → β} {f : α → β} {n : ℕ} (a : α) (hf : Measurable f) : (approx i f n : α →ₛ β) a = (Finset.range n).sup fun k => if i k ≤ f a then i k else 0 := by @@ -904,6 +919,7 @@ theorem lintegral_sum {m : MeasurableSpace α} {ι} (f : α →ₛ ℝ≥0∞) ( ENNReal.tsum_mul_left] apply ENNReal.tsum_comm +open scoped Classical in theorem restrict_lintegral (f : α →ₛ ℝ≥0∞) {s : Set α} (hs : MeasurableSet s) : (restrict f s).lintegral μ = ∑ r ∈ f.range, r * μ (f ⁻¹' {r} ∩ s) := calc @@ -1006,6 +1022,7 @@ section FinMeasSupp open Finset Function +open scoped Classical in theorem support_eq [MeasurableSpace α] [Zero β] (f : α →ₛ β) : support f = ⋃ y ∈ {y ∈ f.range | y ≠ 0}, f ⁻¹' {y} := Set.ext fun x => by @@ -1020,6 +1037,7 @@ theorem measurableSet_support [MeasurableSpace α] (f : α →ₛ β) : Measurab lemma measure_support_lt_top (f : α →ₛ β) (hf : ∀ y, y ≠ 0 → μ (f ⁻¹' {y}) < ∞) : μ (support f) < ∞ := by + classical rw [support_eq] refine (measure_biUnion_finset_le _ _).trans_lt (ENNReal.sum_lt_top.mpr fun y hy => ?_) rw [Finset.mem_filter] at hy @@ -1034,6 +1052,7 @@ theorem finMeasSupp_iff_support : f.FinMeasSupp μ ↔ μ (support f) < ∞ := Iff.rfl theorem finMeasSupp_iff : f.FinMeasSupp μ ↔ ∀ y, y ≠ 0 → μ (f ⁻¹' {y}) < ∞ := by + classical constructor · refine fun h y hy => lt_of_le_of_lt (measure_mono ?_) h exact fun x hx (H : f x = 0) => hy <| H ▸ Eq.symm hx @@ -1124,6 +1143,7 @@ protected theorem induction {α γ} [MeasurableSpace α] [AddMonoid γ] {P : Sim P (SimpleFunc.piecewise s hs (SimpleFunc.const _ c) (SimpleFunc.const _ 0))) (h_add : ∀ ⦃f g : SimpleFunc α γ⦄, Disjoint (support f) (support g) → P f → P g → P (f + g)) (f : SimpleFunc α γ) : P f := by + classical generalize h : f.range \ {0} = s rw [← Finset.coe_inj, Finset.coe_sdiff, Finset.coe_singleton, SimpleFunc.coe_range] at h induction s using Finset.induction generalizing f with diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDense.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDense.lean index d8993de25b264..a764aa7f10af5 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDense.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDense.lean @@ -34,7 +34,6 @@ by a sequence of simple functions. open Set Function Filter TopologicalSpace ENNReal EMetric Finset -open scoped Classical open Topology ENNReal MeasureTheory variable {α β ι E F 𝕜 : Type*} diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index 69360af72aed9..99112b7f98878 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -45,7 +45,7 @@ noncomputable section open Set Function Filter TopologicalSpace ENNReal EMetric Finset -open scoped Classical Topology ENNReal MeasureTheory +open scoped Topology ENNReal MeasureTheory variable {α β ι E F 𝕜 : Type*} diff --git a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean index 58d1ce643a517..e8f2bc92787aa 100644 --- a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean @@ -45,7 +45,7 @@ uniform integrable, uniformly absolutely continuous integral, Vitali convergence noncomputable section -open scoped Classical MeasureTheory NNReal ENNReal Topology +open scoped MeasureTheory NNReal ENNReal Topology namespace MeasureTheory @@ -126,6 +126,7 @@ protected theorem sub (hf : UnifIntegrable f p μ) (hg : UnifIntegrable g p μ) protected theorem ae_eq (hf : UnifIntegrable f p μ) (hfg : ∀ n, f n =ᵐ[μ] g n) : UnifIntegrable g p μ := by + classical intro ε hε obtain ⟨δ, hδ_pos, hfδ⟩ := hf hε refine ⟨δ, hδ_pos, fun n s hs hμs => (le_of_eq <| eLpNorm_congr_ae ?_).trans (hfδ n s hs hμs)⟩ diff --git a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean index 827108c784d82..95aead3dd63b1 100644 --- a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean +++ b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean @@ -56,7 +56,7 @@ divergence theorem, Bochner integral open Set Finset TopologicalSpace Function BoxIntegral MeasureTheory Filter -open scoped Classical Topology Interval +open scoped Topology Interval universe u diff --git a/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean b/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean index 9eec63db434d4..788e73736ccf9 100644 --- a/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean +++ b/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean @@ -141,10 +141,9 @@ integral, fundamental theorem of calculus, FTC-1, FTC-2, change of variables in noncomputable section -open scoped Classical open MeasureTheory Set Filter Function -open scoped Classical Topology Filter ENNReal Interval NNReal +open scoped Topology Filter ENNReal Interval NNReal variable {ι 𝕜 E A : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] diff --git a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean index bfb8d81c0bd4a..338687b657efa 100644 --- a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean @@ -49,10 +49,9 @@ integral noncomputable section -open scoped Classical open MeasureTheory Set Filter Function -open scoped Classical Topology Filter ENNReal Interval NNReal +open scoped Topology Filter ENNReal Interval NNReal variable {ι 𝕜 E F A : Type*} [NormedAddCommGroup E] diff --git a/Mathlib/MeasureTheory/Integral/Prod.lean b/Mathlib/MeasureTheory/Integral/Prod.lean index ac9f5a09023f9..193e5df6d8fb3 100644 --- a/Mathlib/MeasureTheory/Integral/Prod.lean +++ b/Mathlib/MeasureTheory/Integral/Prod.lean @@ -35,7 +35,7 @@ product measure, Fubini's theorem, Fubini-Tonelli theorem noncomputable section -open scoped Classical Topology ENNReal MeasureTheory +open scoped Topology ENNReal MeasureTheory open Set Function Real ENNReal @@ -70,6 +70,7 @@ variable [NormedSpace ℝ E] This version has `f` in curried form. -/ theorem MeasureTheory.StronglyMeasurable.integral_prod_right [SFinite ν] ⦃f : α → β → E⦄ (hf : StronglyMeasurable (uncurry f)) : StronglyMeasurable fun x => ∫ y, f x y ∂ν := by + classical by_cases hE : CompleteSpace E; swap; · simp [integral, hE, stronglyMeasurable_const] borelize E haveI : SeparableSpace (range (uncurry f) ∪ {0} : Set E) := diff --git a/Mathlib/MeasureTheory/Integral/SetIntegral.lean b/Mathlib/MeasureTheory/Integral/SetIntegral.lean index 23d609eefe525..05f685c4df4b5 100644 --- a/Mathlib/MeasureTheory/Integral/SetIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/SetIntegral.lean @@ -54,7 +54,7 @@ assert_not_exists InnerProductSpace noncomputable section open Filter Function MeasureTheory RCLike Set TopologicalSpace Topology -open scoped Classical ENNReal NNReal +open scoped ENNReal NNReal variable {X Y E F : Type*} @@ -141,6 +141,7 @@ theorem integral_finset_biUnion {ι : Type*} (t : Finset ι) {s : ι → Set X} (hs : ∀ i ∈ t, MeasurableSet (s i)) (h's : Set.Pairwise (↑t) (Disjoint on s)) (hf : ∀ i ∈ t, IntegrableOn f (s i) μ) : ∫ x in ⋃ i ∈ t, s i, f x ∂μ = ∑ i ∈ t, ∫ x in s i, f x ∂μ := by + classical induction' t using Finset.induction_on with a t hat IH hs h's · simp · simp only [Finset.coe_insert, Finset.forall_mem_insert, Set.pairwise_insert, diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Pi.lean b/Mathlib/MeasureTheory/MeasurableSpace/Pi.lean index 82e1418f467fc..fc311ca2b168c 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Pi.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Pi.lean @@ -20,7 +20,6 @@ generate the σ-algebra on the indexed product of `α i`s. noncomputable section open Function Set Filter MeasurableSpace Encodable -open scoped Classical variable {ι : Type*} {α : ι → Type*} @@ -63,6 +62,7 @@ theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCoun theorem generateFrom_pi_eq {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) : (@MeasurableSpace.pi _ _ fun i => generateFrom (C i)) = generateFrom (pi univ '' pi univ C) := by + classical cases nonempty_encodable ι apply le_antisymm · refine iSup_le ?_; intro i; rw [comap_generateFrom] From 05fd3e92780d6d9f40d6437b9b4672c1a4b0a28f Mon Sep 17 00:00:00 2001 From: Christopher Hoskin Date: Wed, 29 Jan 2025 14:31:06 +0000 Subject: [PATCH 639/681] refactor(LinearAlgebra/QuadraticForm/TensorProduct): baseChange_ext for Quadratic Maps (#21198) `baseChange_ext` works just as well for quadratic maps as quadratic forms. Co-authored-by: Eric Wieser --- Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean index 7a26465a9f79c..6854ebb704c2f 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean @@ -27,7 +27,7 @@ section CommRing variable [CommRing R] [CommRing A] variable [AddCommGroup M₁] [AddCommGroup M₂] [AddCommGroup N₁] [AddCommGroup N₂] variable [Algebra R A] [Module R M₁] [Module A M₁] [Module R N₁] [Module A N₁] -variable [SMulCommClass R A M₁] [IsScalarTower R A M₁] [SMulCommClass R A N₁] [IsScalarTower R A N₁] +variable [SMulCommClass R A M₁] [IsScalarTower R A M₁] [IsScalarTower R A N₁] variable [Module R M₂] [Module R N₂] section InvertibleTwo @@ -144,13 +144,13 @@ end QuadraticForm end InvertibleTwo -/-- If two quadratic forms from `A ⊗[R] M₂` agree on elements of the form `1 ⊗ m`, they are equal. +/-- If two quadratic maps from `A ⊗[R] M₂` agree on elements of the form `1 ⊗ m`, they are equal. -In other words, if a base change exists for a quadratic form, it is unique. +In other words, if a base change exists for a quadratic map, it is unique. Note that unlike `QuadraticForm.baseChange`, this does not need `Invertible (2 : R)`. -/ @[ext] -theorem baseChange_ext ⦃Q₁ Q₂ : QuadraticForm A (A ⊗[R] M₂)⦄ +theorem baseChange_ext ⦃Q₁ Q₂ : QuadraticMap A (A ⊗[R] M₂) N₁⦄ (h : ∀ m, Q₁ (1 ⊗ₜ m) = Q₂ (1 ⊗ₜ m)) : Q₁ = Q₂ := by replace h (a m) : Q₁ (a ⊗ₜ m) = Q₂ (a ⊗ₜ m) := by @@ -166,6 +166,6 @@ theorem baseChange_ext ⦃Q₁ Q₂ : QuadraticForm A (A ⊗[R] M₂)⦄ rw [← TensorProduct.tmul_add, h, h, h] replace := congr($this x y) dsimp [polar] at this - linear_combination this + hx + hy + linear_combination (norm := module) this + hx + hy end CommRing From 5818e47b974337a0a26cb2574de5401021e10044 Mon Sep 17 00:00:00 2001 From: Jakob von Raumer Date: Wed, 29 Jan 2025 14:41:01 +0000 Subject: [PATCH 640/681] feat(CategoryTheory) : pull back preadditivity along fully faithful functors (#21170) --- Mathlib.lean | 1 + Mathlib/CategoryTheory/Abelian/Transfer.lean | 24 +++---- .../CategoryTheory/Preadditive/Transfer.lean | 63 +++++++++++++++++++ 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 Mathlib/CategoryTheory/Preadditive/Transfer.lean diff --git a/Mathlib.lean b/Mathlib.lean index 8292b7c698346..191f468f0c180 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2149,6 +2149,7 @@ import Mathlib.CategoryTheory.Preadditive.Projective import Mathlib.CategoryTheory.Preadditive.ProjectiveResolution import Mathlib.CategoryTheory.Preadditive.Schur import Mathlib.CategoryTheory.Preadditive.SingleObj +import Mathlib.CategoryTheory.Preadditive.Transfer import Mathlib.CategoryTheory.Preadditive.Yoneda.Basic import Mathlib.CategoryTheory.Preadditive.Yoneda.Injective import Mathlib.CategoryTheory.Preadditive.Yoneda.Limits diff --git a/Mathlib/CategoryTheory/Abelian/Transfer.lean b/Mathlib/CategoryTheory/Abelian/Transfer.lean index 20ca075bae757..114d4d2a53902 100644 --- a/Mathlib/CategoryTheory/Abelian/Transfer.lean +++ b/Mathlib/CategoryTheory/Abelian/Transfer.lean @@ -8,6 +8,7 @@ import Mathlib.CategoryTheory.Abelian.Basic import Mathlib.CategoryTheory.Adjunction.Limits import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Kernels import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor +import Mathlib.CategoryTheory.Preadditive.Transfer /-! # Transferring "abelian-ness" across a functor @@ -202,21 +203,14 @@ lemma inverse_map_add {P Q : ShrinkHoms C} (f g : P ⟶ Q) : variable (C) -noncomputable instance preadditive : - Preadditive.{w} (ShrinkHoms C) where - homGroup := homGroup - add_comp _ _ _ _ _ _ := by - apply (inverse C).map_injective - simp only [inverse_map_add, Functor.map_comp, Preadditive.add_comp] - comp_add _ _ _ _ _ _ := by - apply (inverse C).map_injective - simp only [inverse_map_add, Functor.map_comp, Preadditive.comp_add] - -instance : (inverse C).Additive where - map_add := by apply inverse_map_add - -instance : (functor C).Additive where - map_add := by apply functor_map_add +instance preadditive : Preadditive.{w} (ShrinkHoms C) := + .ofFullyFaithful (equivalence C).fullyFaithfulInverse + +instance : (inverse C).Additive := + (equivalence C).symm.fullyFaithfulFunctor.additive_ofFullyFaithful + +instance : (functor C).Additive := + (equivalence C).symm.additive_inverse_of_FullyFaithful instance hasLimitsOfShape (J : Type*) [Category J] [HasLimitsOfShape J C] : HasLimitsOfShape.{_, _, w} J (ShrinkHoms C) := diff --git a/Mathlib/CategoryTheory/Preadditive/Transfer.lean b/Mathlib/CategoryTheory/Preadditive/Transfer.lean new file mode 100644 index 0000000000000..273c431bbe7b0 --- /dev/null +++ b/Mathlib/CategoryTheory/Preadditive/Transfer.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2025 Jakob von Raumer. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jakob von Raumer +-/ +import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor +import Mathlib.Algebra.Equiv.TransferInstance + +/-! +# Pulling back a preadditive structure along a fully faithful functor + +A preadditive structure on a category `D` transfers to a preadditive structure on `C` for a given +fully faithful functor `F : C ⥤ D`. +-/ +namespace CategoryTheory + +open Limits + +universe v₁ v₂ u₁ u₂ + +variable {C : Type u₁} [Category.{v₁} C] +variable {D : Type u₂} [Category.{v₂} D] [Preadditive D] +variable {F : C ⥤ D} (hF : F.FullyFaithful) + +namespace Preadditive + + +/-- If `D` is a preadditive category, any fully faithful functor `F : C ⥤ D` induces a preadditive +structure on `C`. -/ +def ofFullyFaithful : Preadditive C where + homGroup P Q := hF.homEquiv.addCommGroup + add_comp P Q R f f' g := hF.map_injective (by simp [Equiv.add_def]) + comp_add P Q R f g g' := hF.map_injective (by simp [Equiv.add_def]) + +end Preadditive + +open Preadditive +namespace Functor.FullyFaithful + +/-- The preadditive structure on `C` induced by a fully faithful functor `F : C ⥤ D` makes `F` an +additive functor. -/ +lemma additive_ofFullyFaithful : + letI : Preadditive C := Preadditive.ofFullyFaithful hF + F.Additive := + letI : Preadditive C := Preadditive.ofFullyFaithful hF + { map_add := by simp [Equiv.add_def] } + +end Functor.FullyFaithful + +namespace Equivalence + +/-- The preadditive structure on `C` induced by an equivalence `e : C ≌ D` makes `e.inverse` an +additive functor. -/ +lemma additive_inverse_of_FullyFaithful (e : C ≌ D) : + letI : Preadditive C := ofFullyFaithful e.fullyFaithfulFunctor + e.inverse.Additive := + letI : Preadditive C := ofFullyFaithful e.fullyFaithfulFunctor + letI : e.functor.Additive := e.fullyFaithfulFunctor.additive_ofFullyFaithful + e.inverse_additive + +end Equivalence + +end CategoryTheory From 3cbf001210ddcf4c05ca37bb6c33bd4769616089 Mon Sep 17 00:00:00 2001 From: ooovi Date: Wed, 29 Jan 2025 15:23:11 +0000 Subject: [PATCH 641/681] feat(Data/Nat/Choose) : An upper bound on the binomial coefficient (#20735) Add a theorem bounding `(n+1).choose k` from above by `2^n`. Co-authored-by: ooovi <79147175+ooovi@users.noreply.github.com> --- Mathlib/Data/Nat/Choose/Bounds.lean | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Mathlib/Data/Nat/Choose/Bounds.lean b/Mathlib/Data/Nat/Choose/Bounds.lean index d4b21ddf606d9..e89df1b02a1ad 100644 --- a/Mathlib/Data/Nat/Choose/Bounds.lean +++ b/Mathlib/Data/Nat/Choose/Bounds.lean @@ -50,4 +50,20 @@ theorem pow_le_choose (r n : ℕ) : ((n + 1 - r : ℕ) ^ r : α) / r ! ≤ n.cho exact n.pow_sub_le_descFactorial r exact mod_cast r.factorial_pos +theorem choose_succ_le_two_pow (n k : ℕ) : (n + 1).choose k ≤ 2 ^ n := by + by_cases lt : n + 1 < k + · simp [choose_eq_zero_of_lt lt] + · cases' n with n + · cases k <;> simp_all + · cases' k with k + · rw [choose_zero_right] + exact Nat.one_le_two_pow + · rw [choose_succ_succ', two_pow_succ] + exact Nat.add_le_add (choose_succ_le_two_pow n k) (choose_succ_le_two_pow n (k + 1)) + +theorem choose_le_two_pow (n k : ℕ) (p : 0 < n) : n.choose k < 2 ^ n := by + refine lt_of_le_of_lt ?_ (Nat.two_pow_pred_lt_two_pow p) + rw [← Nat.sub_add_cancel p] + exact choose_succ_le_two_pow (n - 1) k + end Nat From fb2efae8b6c0e79bd5595f7b36e097b816fa62cd Mon Sep 17 00:00:00 2001 From: kvanvels Date: Wed, 29 Jan 2025 15:56:16 +0000 Subject: [PATCH 642/681] chore: replace `open scoped Classical` with `open scoped Classical in` or `classical` in a tactic proof (#21220) reduces some technical debt by replacing `open scoped classical` with `open scoped classical in` or adding a `classical` tactic to a tactic proof. --- .../ClassNumber/FunctionField.lean | 3 +- .../LSeries/DirichletContinuation.lean | 5 ++- .../NumberTheory/LSeries/HurwitzZetaEven.lean | 2 +- Mathlib/NumberTheory/LSeries/ZMod.lean | 2 +- .../ModularForms/JacobiTheta/Bounds.lean | 2 +- .../NumberTheory/NumberField/AdeleRing.lean | 3 +- .../NumberField/CanonicalEmbedding/Basic.lean | 14 ++++++--- .../CanonicalEmbedding/ConvexBody.lean | 31 ++++++++++++++----- .../NumberTheory/NumberField/Embeddings.lean | 20 +++++++++++- .../NumberField/Units/Regulator.lean | 8 ++++- Mathlib/NumberTheory/Padics/RingHoms.lean | 2 +- .../RamificationInertia/Basic.lean | 13 ++++++-- .../Probability/Distributions/Uniform.lean | 14 ++++++++- .../Probability/Kernel/Composition/Basic.lean | 4 +-- Mathlib/Probability/Process/Filtration.lean | 5 ++- .../Spectrum/Maximal/Localization.lean | 5 +-- 16 files changed, 102 insertions(+), 31 deletions(-) diff --git a/Mathlib/NumberTheory/ClassNumber/FunctionField.lean b/Mathlib/NumberTheory/ClassNumber/FunctionField.lean index 04ead5e691263..6c6aecd30fe2d 100644 --- a/Mathlib/NumberTheory/ClassNumber/FunctionField.lean +++ b/Mathlib/NumberTheory/ClassNumber/FunctionField.lean @@ -29,12 +29,11 @@ variable [Algebra Fq[X] F] [Algebra (RatFunc Fq) F] variable [IsScalarTower Fq[X] (RatFunc Fq) F] variable [FunctionField Fq F] [Algebra.IsSeparable (RatFunc Fq) F] -open scoped Classical - namespace RingOfIntegers open FunctionField +open scoped Classical in noncomputable instance : Fintype (ClassGroup (ringOfIntegers Fq F)) := ClassGroup.fintypeOfAdmissibleOfFinite (RatFunc Fq) F (Polynomial.cardPowDegreeIsAdmissible : diff --git a/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean b/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean index 4b59c880997f0..46c73ec9805a3 100644 --- a/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean +++ b/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean @@ -38,7 +38,7 @@ All definitions and theorems are in the `DirichletCharacter` namespace. `completedLFunction χ s = N ^ (s - 1 / 2) * rootNumber χ * completedLFunction χ⁻¹ s`. -/ -open HurwitzZeta Complex Finset Classical ZMod Filter +open HurwitzZeta Complex Finset ZMod Filter open scoped Real Topology @@ -198,6 +198,7 @@ section gammaFactor omit [NeZero N] -- not required for these declarations +open scoped Classical in /-- The Archimedean Gamma factor: `Gammaℝ s` if `χ` is even, and `Gammaℝ (s + 1)` otherwise. -/ noncomputable def gammaFactor (χ : DirichletCharacter ℂ N) (s : ℂ) := if χ.Even then Gammaℝ s else Gammaℝ (s + 1) @@ -258,6 +259,7 @@ lemma LFunction_eq_completed_div_gammaFactor (χ : DirichletCharacter ℂ N) (s · exact LFunction_eq_completed_div_gammaFactor_even hχ.to_fun _ (h.imp_right χ.map_zero') · apply LFunction_eq_completed_div_gammaFactor_odd hχ.to_fun +open scoped Classical in /-- Global root number of `χ` (for `χ` primitive; junk otherwise). Defined as `gaussSum χ stdAddChar / I ^ a / N ^ (1 / 2)`, where `a = 0` if even, `a = 1` if odd. (The factor @@ -277,6 +279,7 @@ namespace IsPrimitive /-- **Functional equation** for primitive Dirichlet L-functions. -/ theorem completedLFunction_one_sub {χ : DirichletCharacter ℂ N} (hχ : IsPrimitive χ) (s : ℂ) : completedLFunction χ (1 - s) = N ^ (s - 1 / 2) * rootNumber χ * completedLFunction χ⁻¹ s := by + classical -- First handle special case of Riemann zeta rcases eq_or_ne N 1 with rfl | hN · simp only [completedLFunction_modOne_eq, completedRiemannZeta_one_sub, Nat.cast_one, one_cpow, diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean b/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean index 9782d336636d6..ceccbcc2a6eab 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean @@ -46,7 +46,7 @@ multiples of `1 / s` and `1 / (1 - s)`. -/ noncomputable section -open Complex Filter Topology Asymptotics Real Set Classical MeasureTheory +open Complex Filter Topology Asymptotics Real Set MeasureTheory namespace HurwitzZeta diff --git a/Mathlib/NumberTheory/LSeries/ZMod.lean b/Mathlib/NumberTheory/LSeries/ZMod.lean index e25eb91d29554..67ee56461069a 100644 --- a/Mathlib/NumberTheory/LSeries/ZMod.lean +++ b/Mathlib/NumberTheory/LSeries/ZMod.lean @@ -55,7 +55,7 @@ Results for completed L-functions: the functional equation relating `completedLFunction Φ (1 - s)` to `completedLFunction (𝓕 Φ) s`. -/ -open HurwitzZeta Complex ZMod Finset Classical Topology Filter Set +open HurwitzZeta Complex ZMod Finset Topology Filter Set open scoped Real diff --git a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean b/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean index b106e2e0d0de9..321736dea55cb 100644 --- a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean +++ b/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean @@ -34,7 +34,7 @@ hence Dirichlet L-functions, etc). `∞`. -/ -open Set Filter Topology Asymptotics Real Classical +open Set Filter Topology Asymptotics Real noncomputable section diff --git a/Mathlib/NumberTheory/NumberField/AdeleRing.lean b/Mathlib/NumberTheory/NumberField/AdeleRing.lean index 927332bf8bdeb..fcbefa15560a6 100644 --- a/Mathlib/NumberTheory/NumberField/AdeleRing.lean +++ b/Mathlib/NumberTheory/NumberField/AdeleRing.lean @@ -39,8 +39,6 @@ namespace NumberField open InfinitePlace AbsoluteValue.Completion InfinitePlace.Completion DedekindDomain IsDedekindDomain -open scoped Classical - /-! ## The infinite adele ring The infinite adele ring is the finite product of completions of a number field over its @@ -76,6 +74,7 @@ theorem algebraMap_apply (x : K) (v : InfinitePlace K) : instance locallyCompactSpace [NumberField K] : LocallyCompactSpace (InfiniteAdeleRing K) := Pi.locallyCompactSpace_of_finite +open scoped Classical in /-- The ring isomorphism between the infinite adele ring of a number field and the space `ℝ ^ r₁ × ℂ ^ r₂`, where `(r₁, r₂)` is the signature of the number field. -/ abbrev ringEquiv_mixedSpace : diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean index 46dd10425cc97..8d446e73f8ab6 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean @@ -309,10 +309,9 @@ end commMap noncomputable section norm -open scoped Classical - variable {K} +open scoped Classical in /-- The norm at the infinite place `w` of an element of the mixed space. --/ def normAtPlace (w : InfinitePlace K) : (mixedSpace K) →*₀ ℝ where toFun x := if hw : IsReal w then ‖x.1 ⟨w, hw⟩‖ else ‖x.2 ⟨w, not_isReal_iff_isComplex.mp hw⟩‖ @@ -380,6 +379,7 @@ theorem exists_normAtPlace_ne_zero_iff {x : mixedSpace K} : variable [NumberField K] +open scoped Classical in theorem nnnorm_eq_sup_normAtPlace (x : mixedSpace K) : ‖x‖₊ = univ.sup fun w ↦ ⟨normAtPlace w x, normAtPlace_nonneg w x⟩ := by have : @@ -395,6 +395,7 @@ theorem nnnorm_eq_sup_normAtPlace (x : mixedSpace K) : · ext w simp [normAtPlace_apply_isComplex w.prop] +open scoped Classical in theorem norm_eq_sup'_normAtPlace (x : mixedSpace K) : ‖x‖ = univ.sup' univ_nonempty fun w ↦ normAtPlace w x := by rw [← coe_nnnorm, nnnorm_eq_sup_normAtPlace, ← sup'_eq_sup univ_nonempty, ← NNReal.val_eq_coe, @@ -460,8 +461,6 @@ end norm noncomputable section stdBasis -open scoped Classical - open Complex MeasureTheory MeasureTheory.Measure ZSpan Matrix ComplexConjugate variable [NumberField K] @@ -469,6 +468,7 @@ variable [NumberField K] /-- The type indexing the basis `stdBasis`. -/ abbrev index := {w : InfinitePlace K // IsReal w} ⊕ ({w : InfinitePlace K // IsComplex w}) × (Fin 2) +open scoped Classical in /-- The `ℝ`-basis of the mixed space of `K` formed by the vector equal to `1` at `w` and `0` elsewhere for `IsReal w` and by the couple of vectors equal to `1` (resp. `I`) at `w` and `0` elsewhere for `IsComplex w`. -/ @@ -494,6 +494,7 @@ theorem stdBasis_apply_ofIsComplex_snd (x : mixedSpace K) variable (K) +open scoped Classical in theorem fundamentalDomain_stdBasis : fundamentalDomain (stdBasis K) = (Set.univ.pi fun _ => Set.Ico 0 1) ×ˢ @@ -501,6 +502,7 @@ theorem fundamentalDomain_stdBasis : ext simp [stdBasis, mem_fundamentalDomain, Complex.measurableEquivPi] +open scoped Classical in theorem volume_fundamentalDomain_stdBasis : volume (fundamentalDomain (stdBasis K)) = 1 := by rw [fundamentalDomain_stdBasis, volume_eq_prod, prod_prod, volume_pi, volume_pi, pi_pi, pi_pi, @@ -508,6 +510,7 @@ theorem volume_fundamentalDomain_stdBasis : sub_zero, ENNReal.ofReal_one, prod_const_one, prod_const_one, prod_const_one, one_mul] exact (MeasurableSet.pi Set.countable_univ (fun _ _ => measurableSet_Ico)).nullMeasurableSet +open scoped Classical in /-- The `Equiv` between `index K` and `K →+* ℂ` defined by sending a real infinite place `w` to the unique corresponding embedding `w.embedding`, and the pair `⟨w, 0⟩` (resp. `⟨w, 1⟩`) for a complex infinite place `w` to `w.embedding` (resp. `conjugate w.embedding`). -/ @@ -544,6 +547,7 @@ theorem indexEquiv_apply_ofIsComplex_snd (w : {w : InfinitePlace K // IsComplex variable (K) +open scoped Classical in /-- The matrix that gives the representation on `stdBasis` of the image by `commMap` of an element `x` of `(K →+* ℂ) → ℂ` fixed by the map `x_φ ↦ conj x_(conjugate φ)`, see `stdBasis_repr_eq_matrixToStdBasis_mul`. -/ @@ -551,6 +555,7 @@ def matrixToStdBasis : Matrix (index K) (index K) ℂ := fromBlocks (diagonal fun _ => 1) 0 0 <| reindex (Equiv.prodComm _ _) (Equiv.prodComm _ _) (blockDiagonal (fun _ => (2 : ℂ)⁻¹ • !![1, 1; - I, I])) +open scoped Classical in theorem det_matrixToStdBasis : (matrixToStdBasis K).det = (2⁻¹ * I) ^ nrComplexPlaces K := calc @@ -563,6 +568,7 @@ theorem det_matrixToStdBasis : _ = (2⁻¹ * Complex.I) ^ Fintype.card {w : InfinitePlace K // IsComplex w} := by rw [prod_const, Fintype.card] +open scoped Classical in /-- Let `x : (K →+* ℂ) → ℂ` such that `x_φ = conj x_(conj φ)` for all `φ : K →+* ℂ`, then the representation of `commMap K x` on `stdBasis` is given (up to reindexing) by the product of `matrixToStdBasis` by `x`. -/ diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean index 0eb57e9a67069..fe204bdeade80 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean @@ -74,8 +74,6 @@ theorem convexBodyLT_convex : Convex ℝ (convexBodyLT K f) := open Fintype MeasureTheory MeasureTheory.Measure ENNReal -open scoped Classical - variable [NumberField K] /-- The fudge factor that appears in the formula for the volume of `convexBodyLT`. -/ @@ -88,6 +86,7 @@ theorem convexBodyLTFactor_ne_zero : convexBodyLTFactor K ≠ 0 := theorem one_le_convexBodyLTFactor : 1 ≤ convexBodyLTFactor K := one_le_mul (one_le_pow₀ one_le_two) (one_le_pow₀ (one_le_two.trans Real.two_le_pi)) +open scoped Classical in /-- The volume of `(ConvexBodyLt K f)` where `convexBodyLT K f` is the set of points `x` such that `‖x w‖ < f w` for all infinite places `w`. -/ theorem convexBodyLT_volume : @@ -122,6 +121,7 @@ but one and choose the value at the remaining place so that we can apply `exists_ne_zero_mem_ringOfIntegers_lt`. -/ theorem adjust_f {w₁ : InfinitePlace K} (B : ℝ≥0) (hf : ∀ w, w ≠ w₁ → f w ≠ 0) : ∃ g : InfinitePlace K → ℝ≥0, (∀ w, w ≠ w₁ → g w = f w) ∧ ∏ w, (g w) ^ mult w = B := by + classical let S := ∏ w ∈ Finset.univ.erase w₁, (f w) ^ mult w refine ⟨Function.update f w₁ ((B * S⁻¹) ^ (mult w₁ : ℝ)⁻¹), ?_, ?_⟩ · exact fun w hw => Function.update_of_ne hw _ f @@ -139,10 +139,9 @@ section convexBodyLT' open Metric ENNReal NNReal -open scoped Classical - variable (f : InfinitePlace K → ℝ≥0) (w₀ : {w : InfinitePlace K // IsComplex w}) +open scoped Classical in /-- A version of `convexBodyLT` with an additional condition at a fixed complex place. This is needed to ensure the element constructed is not real, see for example `exists_primitive_element_lt_of_isComplex`. @@ -191,8 +190,6 @@ theorem convexBodyLT'_convex : Convex ℝ (convexBodyLT' K f w₀) := by open MeasureTheory MeasureTheory.Measure -open scoped Classical - variable [NumberField K] /-- The fudge factor that appears in the formula for the volume of `convexBodyLT'`. -/ @@ -205,6 +202,7 @@ theorem convexBodyLT'Factor_ne_zero : convexBodyLT'Factor K ≠ 0 := theorem one_le_convexBodyLT'Factor : 1 ≤ convexBodyLT'Factor K := one_le_mul (one_le_pow₀ one_le_two) (one_le_pow₀ (one_le_two.trans Real.two_le_pi)) +open scoped Classical in theorem convexBodyLT'_volume : volume (convexBodyLT' K f w₀) = convexBodyLT'Factor K * ∏ w, (f w) ^ (mult w) := by have vol_box : ∀ B : ℝ≥0, volume {x : ℂ | |x.re| < 1 ∧ |x.im| < B^2} = 4*B^2 := by @@ -258,7 +256,7 @@ section convexBodySum open ENNReal MeasureTheory Fintype -open scoped Real Classical NNReal +open scoped Real NNReal variable [NumberField K] (B : ℝ) variable {K} @@ -270,6 +268,7 @@ noncomputable abbrev convexBodySumFun (x : mixedSpace K) : ℝ := ∑ w, mult w theorem convexBodySumFun_apply (x : mixedSpace K) : convexBodySumFun x = ∑ w, mult w * normAtPlace w x := rfl +open scoped Classical in theorem convexBodySumFun_apply' (x : mixedSpace K) : convexBodySumFun x = ∑ w, ‖x.1 w‖ + 2 * ∑ w, ‖x.2 w‖ := by simp_rw [convexBodySumFun_apply, ← Finset.sum_add_sum_compl {w | IsReal w}.toFinset, @@ -310,6 +309,7 @@ theorem convexBodySumFun_eq_zero_iff (x : mixedSpace K) : (mem_nonZeroDivisors_iff_ne_zero.mpr <| Nat.cast_ne_zero.mpr mult_ne_zero)] simp_rw [Finset.mem_univ, true_implies] +open scoped Classical in theorem norm_le_convexBodySumFun (x : mixedSpace K) : ‖x‖ ≤ convexBodySumFun x := by rw [norm_eq_sup'_normAtPlace] refine (Finset.sup'_le_iff _ _).mpr fun w _ ↦ ?_ @@ -333,6 +333,7 @@ theorem convexBodySumFun_continuous : `∑ w real, ‖x w‖ + 2 * ∑ w complex, ‖x w‖ ≤ B`. -/ abbrev convexBodySum : Set (mixedSpace K) := { x | convexBodySumFun x ≤ B } +open scoped Classical in theorem convexBodySum_volume_eq_zero_of_le_zero {B} (hB : B ≤ 0) : volume (convexBodySum K B) = 0 := by obtain hB | hB := lt_or_eq_of_le hB @@ -363,12 +364,14 @@ theorem convexBodySum_convex : Convex ℝ (convexBodySum K B) := by exact (abs_eq_self.mpr h).symm theorem convexBodySum_isBounded : Bornology.IsBounded (convexBodySum K B) := by + classical refine Metric.isBounded_iff.mpr ⟨B + B, fun x hx y hy => ?_⟩ refine le_trans (norm_sub_le x y) (add_le_add ?_ ?_) · exact le_trans (norm_le_convexBodySumFun x) hx · exact le_trans (norm_le_convexBodySumFun y) hy theorem convexBodySum_compact : IsCompact (convexBodySum K B) := by + classical rw [Metric.isCompact_iff_isClosed_bounded] refine ⟨?_, convexBodySum_isBounded K B⟩ convert IsClosed.preimage (convexBodySumFun_continuous K) (isClosed_Icc : IsClosed (Set.Icc 0 B)) @@ -385,6 +388,7 @@ theorem convexBodySumFactor_ne_zero : convexBodySumFactor K ≠ 0 := by (pow_ne_zero _ (div_ne_zero NNReal.pi_ne_zero two_ne_zero)) open MeasureTheory MeasureTheory.Measure Real in +open scoped Classical in theorem convexBodySum_volume : volume (convexBodySum K B) = (convexBodySumFactor K) * (.ofReal B) ^ (finrank ℚ K) := by obtain hB | hB := le_or_lt B 0 @@ -440,13 +444,13 @@ end convexBodySum section minkowski -open scoped Classical open MeasureTheory MeasureTheory.Measure Module ZSpan Real Submodule open scoped ENNReal NNReal nonZeroDivisors IntermediateField variable [NumberField K] (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) +open scoped Classical in /-- The bound that appears in **Minkowski Convex Body theorem**, see `MeasureTheory.exists_ne_zero_mem_lattice_of_measure_mul_two_pow_lt_measure`. See `NumberField.mixedEmbedding.volume_fundamentalDomain_idealLatticeBasis_eq` and @@ -456,6 +460,7 @@ noncomputable def minkowskiBound : ℝ≥0∞ := volume (fundamentalDomain (fractionalIdealLatticeBasis K I)) * (2 : ℝ≥0∞) ^ (finrank ℝ (mixedSpace K)) +open scoped Classical in theorem volume_fundamentalDomain_fractionalIdealLatticeBasis : volume (fundamentalDomain (fractionalIdealLatticeBasis K I)) = .ofReal (FractionalIdeal.absNorm I.1) * volume (fundamentalDomain (latticeBasis K)) := by @@ -471,17 +476,20 @@ theorem volume_fundamentalDomain_fractionalIdealLatticeBasis : rw [mixedEmbedding.det_basisOfFractionalIdeal_eq_norm] theorem minkowskiBound_lt_top : minkowskiBound K I < ⊤ := by + classical refine ENNReal.mul_lt_top ?_ ?_ · exact (fundamentalDomain_isBounded _).measure_lt_top · exact ENNReal.pow_lt_top (lt_top_iff_ne_top.mpr ENNReal.two_ne_top) _ theorem minkowskiBound_pos : 0 < minkowskiBound K I := by + classical refine zero_lt_iff.mpr (mul_ne_zero ?_ ?_) · exact ZSpan.measure_fundamentalDomain_ne_zero _ · exact ENNReal.pow_ne_zero two_ne_zero _ variable {f : InfinitePlace K → ℝ≥0} (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) +open scoped Classical in /-- Let `I` be a fractional ideal of `K`. Assume that `f : InfinitePlace K → ℝ≥0` is such that `minkowskiBound K I < volume (convexBodyLT K f)` where `convexBodyLT K f` is the set of points `x` such that `‖x w‖ < f w` for all infinite places `w` (see `convexBodyLT_volume` for @@ -499,6 +507,7 @@ theorem exists_ne_zero_mem_ideal_lt (h : minkowskiBound K I < volume (convexBody obtain ⟨a, ha, rfl⟩ := hx exact ⟨a, ha, by simpa using h_nz, (convexBodyLT_mem K f).mp h_mem⟩ +open scoped Classical in /-- A version of `exists_ne_zero_mem_ideal_lt` where the absolute value of the real part of `a` is smaller than `1` at some fixed complex place. This is useful to ensure that `a` is not real. -/ theorem exists_ne_zero_mem_ideal_lt' (w₀ : {w : InfinitePlace K // IsComplex w}) @@ -515,6 +524,7 @@ theorem exists_ne_zero_mem_ideal_lt' (w₀ : {w : InfinitePlace K // IsComplex w obtain ⟨a, ha, rfl⟩ := hx exact ⟨a, ha, by simpa using h_nz, (convexBodyLT'_mem K f w₀).mp h_mem⟩ +open scoped Classical in /-- A version of `exists_ne_zero_mem_ideal_lt` for the ring of integers of `K`. -/ theorem exists_ne_zero_mem_ringOfIntegers_lt (h : minkowskiBound K ↑1 < volume (convexBodyLT K f)) : ∃ a : 𝓞 K, a ≠ 0 ∧ ∀ w : InfinitePlace K, w a < f w := by @@ -522,6 +532,7 @@ theorem exists_ne_zero_mem_ringOfIntegers_lt (h : minkowskiBound K ↑1 < volume obtain ⟨a, rfl⟩ := (FractionalIdeal.mem_one_iff _).mp h_mem exact ⟨a, RingOfIntegers.coe_ne_zero_iff.mp h_nz, h_bd⟩ +open scoped Classical in /-- A version of `exists_ne_zero_mem_ideal_lt'` for the ring of integers of `K`. -/ theorem exists_ne_zero_mem_ringOfIntegers_lt' (w₀ : {w : InfinitePlace K // IsComplex w}) (h : minkowskiBound K ↑1 < volume (convexBodyLT' K f w₀)) : @@ -535,6 +546,7 @@ theorem exists_primitive_element_lt_of_isReal {w₀ : InfinitePlace K} (hw₀ : (hB : minkowskiBound K ↑1 < convexBodyLTFactor K * B) : ∃ a : 𝓞 K, ℚ⟮(a : K)⟯ = ⊤ ∧ ∀ w : InfinitePlace K, w a < max B 1 := by + classical have : minkowskiBound K ↑1 < volume (convexBodyLT K (fun w ↦ if w = w₀ then B else 1)) := by rw [convexBodyLT_volume, ← Finset.prod_erase_mul _ _ (Finset.mem_univ w₀)] simp_rw [ite_pow, one_pow] @@ -551,6 +563,7 @@ theorem exists_primitive_element_lt_of_isComplex {w₀ : InfinitePlace K} (hw₀ {B : ℝ≥0} (hB : minkowskiBound K ↑1 < convexBodyLT'Factor K * B) : ∃ a : 𝓞 K, ℚ⟮(a : K)⟯ = ⊤ ∧ ∀ w : InfinitePlace K, w a < Real.sqrt (1 + B ^ 2) := by + classical have : minkowskiBound K ↑1 < volume (convexBodyLT' K (fun w ↦ if w = w₀ then NNReal.sqrt B else 1) ⟨w₀, hw₀⟩) := by rw [convexBodyLT'_volume, ← Finset.prod_erase_mul _ _ (Finset.mem_univ w₀)] @@ -577,6 +590,7 @@ theorem exists_primitive_element_lt_of_isComplex {w₀ : InfinitePlace K} (hw₀ rw [NNReal.coe_one, Real.le_sqrt' zero_lt_one, one_pow] norm_num +open scoped Classical in /-- Let `I` be a fractional ideal of `K`. Assume that `B : ℝ` is such that `minkowskiBound K I < volume (convexBodySum K B)` where `convexBodySum K B` is the set of points `x` such that `∑ w real, ‖x w‖ + 2 * ∑ w complex, ‖x w‖ ≤ B` (see `convexBodySum_volume` for @@ -615,6 +629,7 @@ theorem exists_ne_zero_mem_ideal_of_norm_le {B : ℝ} · rw [← Nat.cast_sum, sum_mult_eq, Nat.cast_pos] exact finrank_pos +open scoped Classical in theorem exists_ne_zero_mem_ringOfIntegers_of_norm_le {B : ℝ} (h : (minkowskiBound K ↑1) ≤ volume (convexBodySum K B)) : ∃ a : 𝓞 K, a ≠ 0 ∧ |Algebra.norm ℚ (a : K)| ≤ (B / finrank ℚ K) ^ finrank ℚ K := by diff --git a/Mathlib/NumberTheory/NumberField/Embeddings.lean b/Mathlib/NumberTheory/NumberField/Embeddings.lean index b14ba38413d3d..d92da2e2f64b2 100644 --- a/Mathlib/NumberTheory/NumberField/Embeddings.lean +++ b/Mathlib/NumberTheory/NumberField/Embeddings.lean @@ -30,7 +30,7 @@ for `x ∈ K`, we have `Π_w ‖x‖_w = |norm(x)|` where the product is over th number field, embeddings, places, infinite places -/ -open scoped Classical Finset +open scoped Finset namespace NumberField.Embeddings @@ -97,6 +97,7 @@ variable (K A) /-- Let `B` be a real number. The set of algebraic integers in `K` whose conjugates are all smaller in norm than `B` is finite. -/ theorem finite_of_norm_le (B : ℝ) : {x : K | IsIntegral ℤ x ∧ ∀ φ : K →+* A, ‖φ x‖ ≤ B}.Finite := by + classical let C := Nat.ceil (max B 1 ^ finrank ℚ K * (finrank ℚ K).choose (finrank ℚ K / 2)) have := bUnion_roots_finite (algebraMap ℤ K) (finrank ℚ K) (finite_Icc (-C : ℤ) C) refine this.subset fun x hx => ?_; simp_rw [mem_iUnion] @@ -422,6 +423,7 @@ lemma isComplex_mk_iff {φ : K →+* ℂ} : theorem not_isReal_of_mk_isComplex {φ : K →+* ℂ} (h : IsComplex (mk φ)) : ¬ ComplexEmbedding.IsReal φ := by rwa [← isComplex_mk_iff] +open scoped Classical in /-- The multiplicity of an infinite place, that is the number of distinct complex embeddings that define it, see `card_filter_mk_eq`. -/ noncomputable def mult (w : InfinitePlace K) : ℕ := if (IsReal w) then 1 else 2 @@ -437,6 +439,7 @@ theorem one_le_mult {w : InfinitePlace K} : (1 : ℝ) ≤ mult w := by rw [← Nat.cast_one, Nat.cast_le] exact mult_pos +open scoped Classical in theorem card_filter_mk_eq [NumberField K] (w : InfinitePlace K) : #{φ | mk φ = w} = mult w := by conv_lhs => congr; congr; ext @@ -450,11 +453,13 @@ theorem card_filter_mk_eq [NumberField K] (w : InfinitePlace K) : #{φ | mk φ = · refine Finset.card_pair ?_ rwa [Ne, eq_comm, ← ComplexEmbedding.isReal_iff, ← isReal_iff] +open scoped Classical in noncomputable instance NumberField.InfinitePlace.fintype [NumberField K] : Fintype (InfinitePlace K) := Set.fintypeRange _ theorem sum_mult_eq [NumberField K] : ∑ w : InfinitePlace K, mult w = Module.finrank ℚ K := by + classical rw [← Embeddings.card K ℂ, Fintype.card, Finset.card_eq_sum_ones, ← Finset.univ.sum_fiberwise (fun φ => InfinitePlace.mk φ)] exact Finset.sum_congr rfl @@ -490,6 +495,7 @@ variable [NumberField K] `‖·‖_w` is the normalized absolute value for `w`. -/ theorem prod_eq_abs_norm (x : K) : ∏ w : InfinitePlace K, w x ^ mult w = abs (Algebra.norm ℚ x) := by + classical convert (congr_arg Complex.abs (@Algebra.norm_eq_prod_embeddings ℚ _ _ _ _ ℂ _ _ _ _ _ x)).symm · rw [map_prod, ← Fintype.prod_equiv RingHom.equivRatAlgHom (fun f => Complex.abs (f x)) (fun φ => Complex.abs (φ x)) fun _ => by simp [RingHom.equivRatAlgHom_apply]; rfl] @@ -555,25 +561,30 @@ section NumberField variable [NumberField K] +open scoped Classical in /-- The number of infinite real places of the number field `K`. -/ noncomputable abbrev nrRealPlaces := card { w : InfinitePlace K // IsReal w } @[deprecated (since := "2024-10-24")] alias NrRealPlaces := nrRealPlaces +open scoped Classical in /-- The number of infinite complex places of the number field `K`. -/ noncomputable abbrev nrComplexPlaces := card { w : InfinitePlace K // IsComplex w } @[deprecated (since := "2024-10-24")] alias NrComplexPlaces := nrComplexPlaces +open scoped Classical in theorem card_real_embeddings : card { φ : K →+* ℂ // ComplexEmbedding.IsReal φ } = nrRealPlaces K := Fintype.card_congr mkReal theorem card_eq_nrRealPlaces_add_nrComplexPlaces : Fintype.card (InfinitePlace K) = nrRealPlaces K + nrComplexPlaces K := by + classical convert Fintype.card_subtype_or_disjoint (IsReal (K := K)) (IsComplex (K := K)) (disjoint_isReal_isComplex K) using 1 exact (Fintype.card_of_subtype _ (fun w ↦ ⟨fun _ ↦ isReal_or_isComplex w, fun _ ↦ by simp⟩)).symm +open scoped Classical in theorem card_complex_embeddings : card { φ : K →+* ℂ // ¬ComplexEmbedding.IsReal φ } = 2 * nrComplexPlaces K := by suffices ∀ w : { w : InfinitePlace K // IsComplex w }, @@ -593,6 +604,7 @@ theorem card_complex_embeddings : theorem card_add_two_mul_card_eq_rank : nrRealPlaces K + 2 * nrComplexPlaces K = finrank ℚ K := by + classical rw [← card_real_embeddings, ← card_complex_embeddings, Fintype.card_subtype_compl, ← Embeddings.card K ℂ, Nat.add_sub_of_le] exact Fintype.card_subtype_le _ @@ -838,6 +850,7 @@ variable (k w) lemma nat_card_stabilizer_eq_one_or_two : Nat.card (Stab w) = 1 ∨ Nat.card (Stab w) = 2 := by + classical rw [← SetLike.coe_sort_coe, ← mk_embedding w] by_cases h : ∃ σ, ComplexEmbedding.IsConj (k := k) (embedding w) σ · obtain ⟨σ, hσ⟩ := h @@ -869,6 +882,7 @@ lemma not_isUnramified_iff_card_stabilizer_eq_two [IsGalois k K] : rw [isUnramified_iff_card_stabilizer_eq_one] obtain (e|e) := nat_card_stabilizer_eq_one_or_two k w <;> rw [e] <;> decide +open scoped Classical in lemma card_stabilizer [IsGalois k K] : Nat.card (Stab w) = if IsUnramified k w then 1 else 2 := by split @@ -934,6 +948,7 @@ variable (k K) variable [NumberField K] open Finset in +open scoped Classical in lemma card_isUnramified [NumberField k] [IsGalois k K] : #{w : InfinitePlace K | w.IsUnramified k} = #{w : InfinitePlace k | w.IsUnramifiedIn K} * finrank k K := by @@ -956,6 +971,7 @@ lemma card_isUnramified [NumberField k] [IsGalois k K] : · simp [isUnramifiedIn_comap] open Finset in +open scoped Classical in lemma card_isUnramified_compl [NumberField k] [IsGalois k K] : #({w : InfinitePlace K | w.IsUnramified k} : Finset _)ᶜ = #({w : InfinitePlace k | w.IsUnramifiedIn K} : Finset _)ᶜ * (finrank k K / 2) := by @@ -977,6 +993,7 @@ lemma card_isUnramified_compl [NumberField k] [IsGalois k K] : rwa [← isUnramifiedIn_comap] · simp [isUnramifiedIn_comap] +open scoped Classical in lemma card_eq_card_isUnramifiedIn [NumberField k] [IsGalois k K] : Fintype.card (InfinitePlace K) = #{w : InfinitePlace k | w.IsUnramifiedIn K} * finrank k K + @@ -1038,6 +1055,7 @@ open Module in lemma IsUnramifiedAtInfinitePlaces.card_infinitePlace [NumberField k] [NumberField K] [IsGalois k K] [IsUnramifiedAtInfinitePlaces k K] : Fintype.card (InfinitePlace K) = Fintype.card (InfinitePlace k) * finrank k K := by + classical rw [InfinitePlace.card_eq_card_isUnramifiedIn (k := k) (K := K), Finset.filter_true_of_mem, Finset.card_univ, Finset.card_eq_zero.mpr, zero_mul, add_zero] · exact Finset.compl_univ diff --git a/Mathlib/NumberTheory/NumberField/Units/Regulator.lean b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean index 2f09783cc3433..31347cb3073d0 100644 --- a/Mathlib/NumberTheory/NumberField/Units/Regulator.lean +++ b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean @@ -32,16 +32,19 @@ namespace NumberField.Units variable (K : Type*) [Field K] -open MeasureTheory Classical NumberField.InfinitePlace +open MeasureTheory NumberField.InfinitePlace NumberField NumberField.Units.dirichletUnitTheorem variable [NumberField K] +open scoped Classical in /-- The regulator of a number field `K`. -/ def regulator : ℝ := ZLattice.covolume (unitLattice K) +open scoped Classical in theorem regulator_ne_zero : regulator K ≠ 0 := ZLattice.covolume_ne_zero (unitLattice K) volume +open scoped Classical in theorem regulator_pos : 0 < regulator K := ZLattice.covolume_pos (unitLattice K) volume #adaptation_note /-- https://github.com/leanprover/lean4/pull/4119 @@ -54,6 +57,7 @@ local instance : CommGroup (𝓞 K)ˣ := inferInstance -/ set_option maxSynthPendingDepth 2 -- Note this is active for the remainder of the file. +open scoped Classical in theorem regulator_eq_det' (e : {w : InfinitePlace K // w ≠ w₀} ≃ Fin (rank K)) : regulator K = |(Matrix.of fun i ↦ logEmbedding K (Additive.ofMul (fundSystem K (e i)))).det| := by @@ -61,6 +65,7 @@ theorem regulator_eq_det' (e : {w : InfinitePlace K // w ≠ w₀} ≃ Fin (rank (((basisModTorsion K).map (logEmbeddingEquiv K)).reindex e.symm), Basis.coe_reindex, Function.comp_def, Basis.map_apply, ← fundSystem_mk, Equiv.symm_symm, logEmbeddingEquiv_apply] +open scoped Classical in /-- Let `u : Fin (rank K) → (𝓞 K)ˣ` be a family of units and let `w₁` and `w₂` be two infinite places. Then, the two square matrices with entries `(mult w * log w (u i))_i, {w ≠ w_i}`, `i = 1,2`, have the same determinant in absolute value. -/ @@ -96,6 +101,7 @@ theorem abs_det_eq_abs_det (u : Fin (rank K) → (𝓞 K)ˣ) Units.norm, Rat.cast_one, Real.log_one] exact fun _ _ ↦ pow_ne_zero _ <| (map_ne_zero _).mpr (coe_ne_zero _) +open scoped Classical in /-- For any infinite place `w'`, the regulator is equal to the absolute value of the determinant of the matrix `(mult w * log w (fundSystem K i)))_i, {w ≠ w'}`. -/ theorem regulator_eq_det (w' : InfinitePlace K) (e : {w // w ≠ w'} ≃ Fin (rank K)) : diff --git a/Mathlib/NumberTheory/Padics/RingHoms.lean b/Mathlib/NumberTheory/Padics/RingHoms.lean index f16855f13878b..f6b9067b3e3c9 100644 --- a/Mathlib/NumberTheory/Padics/RingHoms.lean +++ b/Mathlib/NumberTheory/Padics/RingHoms.lean @@ -41,7 +41,6 @@ The constructions of the ring homomorphisms go through an auxiliary constructor noncomputable section -open scoped Classical open Nat IsLocalRing Padic namespace PadicInt @@ -293,6 +292,7 @@ def residueField : IsLocalRing.ResidueField ℤ_[p] ≃+* ZMod p := by exact_mod_cast (@PadicInt.ker_toZMod p _) ▸ RingHom.quotientKerEquivOfSurjective (ZMod.ringHom_surjective PadicInt.toZMod) +open scoped Classical in /-- `appr n x` gives a value `v : ℕ` such that `x` and `↑v : ℤ_p` are congruent mod `p^n`. See `appr_spec`. -/ -- Porting note: removing irreducible solves a lot of problems diff --git a/Mathlib/NumberTheory/RamificationInertia/Basic.lean b/Mathlib/NumberTheory/RamificationInertia/Basic.lean index 24f96fd9081fb..137fee8752dbb 100644 --- a/Mathlib/NumberTheory/RamificationInertia/Basic.lean +++ b/Mathlib/NumberTheory/RamificationInertia/Basic.lean @@ -675,25 +675,27 @@ end FactLeComap section FactorsMap -open scoped Classical - /-! ## Properties of the factors of `p.map (algebraMap R S)` -/ variable [IsDedekindDomain S] [Algebra R S] +open scoped Classical in theorem Factors.ne_bot (P : (factors (map (algebraMap R S) p)).toFinset) : (P : Ideal S) ≠ ⊥ := (prime_of_factor _ (Multiset.mem_toFinset.mp P.2)).ne_zero +open scoped Classical in instance Factors.isPrime (P : (factors (map (algebraMap R S) p)).toFinset) : IsPrime (P : Ideal S) := Ideal.isPrime_of_prime (prime_of_factor _ (Multiset.mem_toFinset.mp P.2)) +open scoped Classical in theorem Factors.ramificationIdx_ne_zero (P : (factors (map (algebraMap R S) p)).toFinset) : ramificationIdx (algebraMap R S) p P ≠ 0 := IsDedekindDomain.ramificationIdx_ne_zero (ne_zero_of_mem_factors (Multiset.mem_toFinset.mp P.2)) (Factors.isPrime p P) (Ideal.le_of_dvd (dvd_of_mem_factors (Multiset.mem_toFinset.mp P.2))) +open scoped Classical in instance Factors.fact_ramificationIdx_neZero (P : (factors (map (algebraMap R S) p)).toFinset) : NeZero (ramificationIdx (algebraMap R S) p P) := ⟨Factors.ramificationIdx_ne_zero p P⟩ @@ -702,14 +704,17 @@ set_option synthInstance.checkSynthOrder false -- Porting note: this is okay since, as noted above, in this file the value of `f` can be inferred attribute [local instance] Quotient.algebraQuotientOfRamificationIdxNeZero +open scoped Classical in instance Factors.isScalarTower (P : (factors (map (algebraMap R S) p)).toFinset) : IsScalarTower R (R ⧸ p) (S ⧸ (P : Ideal S)) := IsScalarTower.of_algebraMap_eq' rfl +open scoped Classical in instance Factors.liesOver [p.IsMaximal] (P : (factors (map (algebraMap R S) p)).toFinset) : P.1.LiesOver p := ⟨(comap_eq_of_scalar_tower_quotient (algebraMap (R ⧸ p) (S ⧸ P.1)).injective).symm⟩ +open scoped Classical in theorem Factors.finrank_pow_ramificationIdx [p.IsMaximal] (P : (factors (map (algebraMap R S) p)).toFinset) : finrank (R ⧸ p) (S ⧸ (P : Ideal S) ^ ramificationIdx (algebraMap R S) p P) = @@ -717,6 +722,7 @@ theorem Factors.finrank_pow_ramificationIdx [p.IsMaximal] rw [finrank_prime_pow_ramificationIdx, inertiaDeg_algebraMap] exacts [Factors.ne_bot p P, NeZero.ne _] +open scoped Classical in instance Factors.finiteDimensional_quotient_pow [Module.Finite R S] [p.IsMaximal] (P : (factors (map (algebraMap R S) p)).toFinset) : FiniteDimensional (R ⧸ p) (S ⧸ (P : Ideal S) ^ ramificationIdx (algebraMap R S) p P) := by @@ -726,6 +732,7 @@ instance Factors.finiteDimensional_quotient_pow [Module.Finite R S] [p.IsMaximal universe w +open scoped Classical in /-- **Chinese remainder theorem** for a ring of integers: if the prime ideal `p : Ideal R` factors in `S` as `∏ i, P i ^ e i`, then `S ⧸ I` factors as `Π i, R ⧸ (P i ^ e i)`. -/ noncomputable def Factors.piQuotientEquiv (p : Ideal R) (hp : map (algebraMap R S) p ≠ ⊥) : @@ -752,6 +759,7 @@ theorem Factors.piQuotientEquiv_map (p : Ideal R) (hp : map (algebraMap R S) p variable (S) +open scoped Classical in /-- **Chinese remainder theorem** for a ring of integers: if the prime ideal `p : Ideal R` factors in `S` as `∏ i, P i ^ e i`, then `S ⧸ I` factors `R ⧸ I`-linearly as `Π i, R ⧸ (P i ^ e i)`. -/ @@ -767,6 +775,7 @@ noncomputable def Factors.piQuotientLinearEquiv (p : Ideal R) (hp : map (algebra RingHomCompTriple.comp_apply, Pi.mul_apply, Pi.algebraMap_apply] congr } +open scoped Classical in /-- The **fundamental identity** of ramification index `e` and inertia degree `f`: for `P` ranging over the primes lying over `p`, `∑ P, e P * f P = [Frac(S) : Frac(R)]`; here `S` is a finite `R`-module (and thus `Frac(S) : Frac(R)` is a finite extension) and `p` diff --git a/Mathlib/Probability/Distributions/Uniform.lean b/Mathlib/Probability/Distributions/Uniform.lean index 2e4daec4ac77e..4c50fb841441c 100644 --- a/Mathlib/Probability/Distributions/Uniform.lean +++ b/Mathlib/Probability/Distributions/Uniform.lean @@ -209,12 +209,13 @@ namespace PMF variable {α : Type*} -open scoped Classical NNReal ENNReal +open scoped NNReal ENNReal section UniformOfFinset /-- Uniform distribution taking the same non-zero probability on the nonempty finset `s` -/ def uniformOfFinset (s : Finset α) (hs : s.Nonempty) : PMF α := by + classical refine ofFinset (fun a => if a ∈ s then s.card⁻¹ else 0) s ?_ ?_ · simp only [Finset.sum_ite_mem, Finset.inter_self, Finset.sum_const, nsmul_eq_mul] have : (s.card : ℝ≥0∞) ≠ 0 := by @@ -225,6 +226,7 @@ def uniformOfFinset (s : Finset α) (hs : s.Nonempty) : PMF α := by variable {s : Finset α} (hs : s.Nonempty) {a : α} +open scoped Classical in @[simp] theorem uniformOfFinset_apply (a : α) : uniformOfFinset s hs a = if a ∈ s then (s.card : ℝ≥0∞)⁻¹ else 0 := @@ -249,6 +251,7 @@ section Measure variable (t : Set α) +open scoped Classical in @[simp] theorem toOuterMeasure_uniformOfFinset_apply : (uniformOfFinset s hs).toOuterMeasure t = (s.filter (· ∈ t)).card / s.card := @@ -266,6 +269,7 @@ theorem toOuterMeasure_uniformOfFinset_apply : _ = (s.filter (· ∈ t)).card / s.card := by simp only [div_eq_mul_inv, Finset.sum_const, nsmul_eq_mul] +open scoped Classical in @[simp] theorem toMeasure_uniformOfFinset_apply [MeasurableSpace α] (ht : MeasurableSet t) : (uniformOfFinset s hs).toMeasure t = (s.filter (· ∈ t)).card / s.card := @@ -298,11 +302,13 @@ section Measure variable (s : Set α) +open scoped Classical in theorem toOuterMeasure_uniformOfFintype_apply : (uniformOfFintype α).toOuterMeasure s = Fintype.card s / Fintype.card α := by rw [uniformOfFintype, toOuterMeasure_uniformOfFinset_apply,Fintype.card_ofFinset] rfl +open scoped Classical in theorem toMeasure_uniformOfFintype_apply [MeasurableSpace α] (hs : MeasurableSet s) : (uniformOfFintype α).toMeasure s = Fintype.card s / Fintype.card α := by simp [uniformOfFintype, hs] @@ -313,6 +319,7 @@ end UniformOfFintype section OfMultiset +open scoped Classical in /-- Given a non-empty multiset `s` we construct the `PMF` which sends `a` to the fraction of elements in `s` that are `a`. -/ def ofMultiset (s : Multiset α) (hs : s ≠ 0) : PMF α := @@ -334,14 +341,17 @@ def ofMultiset (s : Multiset α) (hs : s ≠ 0) : PMF α := variable {s : Multiset α} (hs : s ≠ 0) +open scoped Classical in @[simp] theorem ofMultiset_apply (a : α) : ofMultiset s hs a = s.count a / (Multiset.card s) := rfl +open scoped Classical in @[simp] theorem support_ofMultiset : (ofMultiset s hs).support = s.toFinset := Set.ext (by simp [mem_support_iff, hs]) +open scoped Classical in theorem mem_support_ofMultiset_iff (a : α) : a ∈ (ofMultiset s hs).support ↔ a ∈ s.toFinset := by simp @@ -353,6 +363,7 @@ section Measure variable (t : Set α) +open scoped Classical in @[simp] theorem toOuterMeasure_ofMultiset_apply : (ofMultiset s hs).toOuterMeasure t = @@ -361,6 +372,7 @@ theorem toOuterMeasure_ofMultiset_apply : refine tsum_congr fun x => ?_ by_cases hx : x ∈ t <;> simp [Set.indicator, hx, div_eq_mul_inv] +open scoped Classical in @[simp] theorem toMeasure_ofMultiset_apply [MeasurableSpace α] (ht : MeasurableSet t) : (ofMultiset s hs).toMeasure t = (∑' x, (s.filter (· ∈ t)).count x : ℝ≥0∞) / (Multiset.card s) := diff --git a/Mathlib/Probability/Kernel/Composition/Basic.lean b/Mathlib/Probability/Kernel/Composition/Basic.lean index c5cdd7bb8284a..3a6ccc33841e1 100644 --- a/Mathlib/Probability/Kernel/Composition/Basic.lean +++ b/Mathlib/Probability/Kernel/Composition/Basic.lean @@ -158,8 +158,7 @@ theorem measurable_compProdFun (κ : Kernel α β) [IsSFiniteKernel κ] (η : Ke @[deprecated (since := "2024-08-30")] alias measurable_compProdFun_of_finite := measurable_compProdFun -open scoped Classical - +open scoped Classical in /-- Composition-Product of kernels. For s-finite kernels, it satisfies `∫⁻ bc, f bc ∂(compProd κ η a) = ∫⁻ b, ∫⁻ c, f (b, c) ∂(η (a, b)) ∂(κ a)` (see `ProbabilityTheory.Kernel.lintegral_compProd`). @@ -259,6 +258,7 @@ lemma compProd_preimage_fst {s : Set β} (hs : MeasurableSet s) (κ : Kernel α lemma compProd_deterministic_apply [MeasurableSingletonClass γ] {f : α × β → γ} (hf : Measurable f) {s : Set (β × γ)} (hs : MeasurableSet s) (κ : Kernel α β) [IsSFiniteKernel κ] (x : α) : (κ ⊗ₖ deterministic f hf) x s = κ x {b | (b, f (x, b)) ∈ s} := by + classical simp only [deterministic_apply, measurableSet_setOf, Set.mem_setOf_eq, Measure.dirac_apply, Set.mem_setOf_eq, Set.indicator_apply, Pi.one_apply, compProd_apply hs] let t := {b | (b, f (x, b)) ∈ s} diff --git a/Mathlib/Probability/Process/Filtration.lean b/Mathlib/Probability/Process/Filtration.lean index 82b1ace233b96..1c4556148126c 100644 --- a/Mathlib/Probability/Process/Filtration.lean +++ b/Mathlib/Probability/Process/Filtration.lean @@ -33,7 +33,7 @@ filtration, stochastic process open Filter Order TopologicalSpace -open scoped Classical MeasureTheory NNReal ENNReal Topology +open scoped MeasureTheory NNReal ENNReal Topology namespace MeasureTheory @@ -133,6 +133,7 @@ theorem sSup_def (s : Set (Filtration ι m)) (i : ι) : sSup s i = sSup ((fun f : Filtration ι m => f i) '' s) := rfl +open scoped Classical in noncomputable instance : InfSet (Filtration ι m) := ⟨fun s => { seq := fun i => if Set.Nonempty s then sInf ((fun f : Filtration ι m => f i) '' s) else m @@ -151,6 +152,7 @@ noncomputable instance : InfSet (Filtration ι m) := obtain ⟨f, hf_mem⟩ := h_nonempty exact le_trans (sInf_le ⟨f, hf_mem, rfl⟩) (f.le i) }⟩ +open scoped Classical in theorem sInf_def (s : Set (Filtration ι m)) (i : ι) : sInf s i = if Set.Nonempty s then sInf ((fun f : Filtration ι m => f i) '' s) else m := rfl @@ -295,6 +297,7 @@ section Limit variable {E : Type*} [Zero E] [TopologicalSpace E] {ℱ : Filtration ι m} {f : ι → Ω → E} {μ : Measure Ω} +open scoped Classical in /-- Given a process `f` and a filtration `ℱ`, if `f` converges to some `g` almost everywhere and `g` is `⨆ n, ℱ n`-measurable, then `limitProcess f ℱ μ` chooses said `g`, else it returns 0. diff --git a/Mathlib/RingTheory/Spectrum/Maximal/Localization.lean b/Mathlib/RingTheory/Spectrum/Maximal/Localization.lean index d0723e00ec9b5..b41a0bebd9a72 100644 --- a/Mathlib/RingTheory/Spectrum/Maximal/Localization.lean +++ b/Mathlib/RingTheory/Spectrum/Maximal/Localization.lean @@ -15,8 +15,6 @@ Localization results. noncomputable section -open scoped Classical - variable (R S P : Type*) [CommSemiring R] [CommSemiring S] [CommSemiring P] namespace MaximalSpectrum @@ -121,6 +119,7 @@ variable {ι} (R : ι → Type*) [∀ i, CommSemiring (R i)] [∀ i, Nontrivial theorem toPiLocalization_not_surjective_of_infinite [Infinite ι] : ¬ Function.Surjective (toPiLocalization (Π i, R i)) := fun surj ↦ by + classical have ⟨J, max, nmem⟩ := PrimeSpectrum.exists_maximal_nmem_range_sigmaToPi_of_infinite R obtain ⟨r, hr⟩ := surj (Function.update 0 ⟨J, max⟩ 1) have : r = 0 := funext fun i ↦ toPiLocalization_injective _ <| funext fun I ↦ by @@ -172,6 +171,7 @@ localizations at maximal ideals. -/ def piLocalizationToMaximal : PiLocalization R →+* MaximalSpectrum.PiLocalization R := Pi.ringHom fun I ↦ Pi.evalRingHom _ I.toPrimeSpectrum +open scoped Classical in theorem piLocalizationToMaximal_surjective : Function.Surjective (piLocalizationToMaximal R) := fun r ↦ ⟨fun I ↦ if h : I.1.IsMaximal then r ⟨_, h⟩ else 0, funext fun _ ↦ dif_pos _⟩ @@ -197,6 +197,7 @@ variable {S} theorem isMaximal_of_toPiLocalization_surjective (surj : Function.Surjective (toPiLocalization R)) (I : PrimeSpectrum R) : I.1.IsMaximal := by + classical have ⟨J, max, le⟩ := I.1.exists_le_maximal I.2.ne_top obtain ⟨r, hr⟩ := surj (Function.update 0 ⟨J, max.isPrime⟩ 1) by_contra h From f6cd292855bf903995f6f6bd9c37d02c78d7d485 Mon Sep 17 00:00:00 2001 From: Etienne Date: Wed, 29 Jan 2025 18:12:01 +0000 Subject: [PATCH 643/681] chore(MeasureTheory/Function/L1Space): split L1Space into HasFiniteIntegral, Integrable and AEEqFun (#21231) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the too long file `L1Space` into three files: - `HasFiniteIntegral` contains the corresponding predicate and associated lemmas. - `Integrable` contains the corresponding predicate and associated lemmas. - `AEEqFun` links the `Integrable` predicate with the L1 space `α →₁[μ] β`. --- Mathlib.lean | 4 +- .../MeasureTheory/Decomposition/Lebesgue.lean | 2 +- .../Function/L1Space/AEEqFun.lean | 231 +++++++ .../Function/L1Space/HasFiniteIntegral.lean | 398 ++++++++++++ .../{L1Space.lean => L1Space/Integrable.lean} | 579 +----------------- .../Function/SimpleFuncDenseLp.lean | 2 +- Mathlib/MeasureTheory/Function/UnifTight.lean | 1 - .../Function/UniformIntegrable.lean | 2 +- .../MeasureTheory/Integral/IntegrableOn.lean | 2 +- .../Probability/Independence/Integrable.lean | 2 +- .../Probability/Moments/IntegrableExpMul.lean | 2 +- 11 files changed, 647 insertions(+), 578 deletions(-) create mode 100644 Mathlib/MeasureTheory/Function/L1Space/AEEqFun.lean create mode 100644 Mathlib/MeasureTheory/Function/L1Space/HasFiniteIntegral.lean rename Mathlib/MeasureTheory/Function/{L1Space.lean => L1Space/Integrable.lean} (63%) diff --git a/Mathlib.lean b/Mathlib.lean index 191f468f0c180..520a3ec30a90c 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -3772,7 +3772,9 @@ import Mathlib.MeasureTheory.Function.EssSup import Mathlib.MeasureTheory.Function.Floor import Mathlib.MeasureTheory.Function.Intersectivity import Mathlib.MeasureTheory.Function.Jacobian -import Mathlib.MeasureTheory.Function.L1Space +import Mathlib.MeasureTheory.Function.L1Space.AEEqFun +import Mathlib.MeasureTheory.Function.L1Space.HasFiniteIntegral +import Mathlib.MeasureTheory.Function.L1Space.Integrable import Mathlib.MeasureTheory.Function.L2Space import Mathlib.MeasureTheory.Function.LocallyIntegrable import Mathlib.MeasureTheory.Function.LpOrder diff --git a/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean b/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean index f1cececd23a18..ca9899a429ecc 100644 --- a/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean @@ -5,7 +5,7 @@ Authors: Kexing Ying -/ import Mathlib.MeasureTheory.Decomposition.UnsignedHahn import Mathlib.MeasureTheory.Function.AEEqOfLIntegral -import Mathlib.MeasureTheory.Function.L1Space +import Mathlib.MeasureTheory.Function.L1Space.Integrable import Mathlib.MeasureTheory.Measure.Sub /-! diff --git a/Mathlib/MeasureTheory/Function/L1Space/AEEqFun.lean b/Mathlib/MeasureTheory/Function/L1Space/AEEqFun.lean new file mode 100644 index 0000000000000..b63aa09f634b4 --- /dev/null +++ b/Mathlib/MeasureTheory/Function/L1Space/AEEqFun.lean @@ -0,0 +1,231 @@ +/- +Copyright (c) 2019 Zhouhang Zhou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Zhouhang Zhou +-/ +import Mathlib.MeasureTheory.Function.L1Space.Integrable + +/-! +# `L¹` space + +In this file we establish an API between `Integrable` and the space `L¹` of equivalence +classes of integrable functions, already defined as a special case of `L^p` spaces for `p = 1`. + +## Notation + +* `α →₁[μ] β` is the type of `L¹` space, where `α` is a `MeasureSpace` and `β` is a + `NormedAddCommGroup`. `f : α →ₘ β` is a "function" in `L¹`. + In comments, `[f]` is also used to denote an `L¹` function. + + `₁` can be typed as `\1`. + +## Tags + +function space, l1 + +-/ + +noncomputable section + +open EMetric ENNReal Filter MeasureTheory NNReal Set + +variable {α β : Type*} {m : MeasurableSpace α} {μ ν : Measure α} +variable [NormedAddCommGroup β] + +namespace MeasureTheory + +namespace AEEqFun + +section + +/-- A class of almost everywhere equal functions is `Integrable` if its function representative +is integrable. -/ +def Integrable (f : α →ₘ[μ] β) : Prop := + MeasureTheory.Integrable f μ + +theorem integrable_mk {f : α → β} (hf : AEStronglyMeasurable f μ) : + Integrable (mk f hf : α →ₘ[μ] β) ↔ MeasureTheory.Integrable f μ := by + simp only [Integrable] + apply integrable_congr + exact coeFn_mk f hf + +theorem integrable_coeFn {f : α →ₘ[μ] β} : MeasureTheory.Integrable f μ ↔ Integrable f := by + rw [← integrable_mk, mk_coeFn] + +theorem integrable_zero : Integrable (0 : α →ₘ[μ] β) := + (MeasureTheory.integrable_zero α β μ).congr (coeFn_mk _ _).symm + +end + +section + +theorem Integrable.neg {f : α →ₘ[μ] β} : Integrable f → Integrable (-f) := + induction_on f fun _f hfm hfi => (integrable_mk _).2 ((integrable_mk hfm).1 hfi).neg + +section + +theorem integrable_iff_mem_L1 {f : α →ₘ[μ] β} : Integrable f ↔ f ∈ (α →₁[μ] β) := by + rw [← integrable_coeFn, ← memℒp_one_iff_integrable, Lp.mem_Lp_iff_memℒp] + +theorem Integrable.add {f g : α →ₘ[μ] β} : Integrable f → Integrable g → Integrable (f + g) := by + refine induction_on₂ f g fun f hf g hg hfi hgi => ?_ + simp only [integrable_mk, mk_add_mk] at hfi hgi ⊢ + exact hfi.add hgi + +theorem Integrable.sub {f g : α →ₘ[μ] β} (hf : Integrable f) (hg : Integrable g) : + Integrable (f - g) := + (sub_eq_add_neg f g).symm ▸ hf.add hg.neg + +end + +section BoundedSMul + +variable {𝕜 : Type*} [NormedRing 𝕜] [Module 𝕜 β] [BoundedSMul 𝕜 β] + +theorem Integrable.smul {c : 𝕜} {f : α →ₘ[μ] β} : Integrable f → Integrable (c • f) := + induction_on f fun _f hfm hfi => (integrable_mk _).2 <| + by simpa using ((integrable_mk hfm).1 hfi).smul c + +end BoundedSMul + +end + +end AEEqFun + +namespace L1 + + +theorem integrable_coeFn (f : α →₁[μ] β) : Integrable f μ := by + rw [← memℒp_one_iff_integrable] + exact Lp.memℒp f + +theorem hasFiniteIntegral_coeFn (f : α →₁[μ] β) : HasFiniteIntegral f μ := + (integrable_coeFn f).hasFiniteIntegral + +theorem stronglyMeasurable_coeFn (f : α →₁[μ] β) : StronglyMeasurable f := + Lp.stronglyMeasurable f + +theorem measurable_coeFn [MeasurableSpace β] [BorelSpace β] (f : α →₁[μ] β) : Measurable f := + (Lp.stronglyMeasurable f).measurable + +theorem aestronglyMeasurable_coeFn (f : α →₁[μ] β) : AEStronglyMeasurable f μ := + Lp.aestronglyMeasurable f + +theorem aemeasurable_coeFn [MeasurableSpace β] [BorelSpace β] (f : α →₁[μ] β) : AEMeasurable f μ := + (Lp.stronglyMeasurable f).measurable.aemeasurable + +theorem edist_def (f g : α →₁[μ] β) : edist f g = ∫⁻ a, edist (f a) (g a) ∂μ := by + simp only [Lp.edist_def, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_enorm, Pi.sub_apply, + one_toReal, ENNReal.rpow_one, ne_eq, not_false_eq_true, div_self, ite_false] + simp [edist_eq_enorm_sub] + +theorem dist_def (f g : α →₁[μ] β) : dist f g = (∫⁻ a, edist (f a) (g a) ∂μ).toReal := by + simp_rw [dist_edist, edist_def] + +theorem norm_def (f : α →₁[μ] β) : ‖f‖ = (∫⁻ a, ‖f a‖ₑ ∂μ).toReal := by + simp [Lp.norm_def, eLpNorm, eLpNorm'_eq_lintegral_enorm] + +/-- Computing the norm of a difference between two L¹-functions. Note that this is not a + special case of `norm_def` since `(f - g) x` and `f x - g x` are not equal + (but only a.e.-equal). -/ +theorem norm_sub_eq_lintegral (f g : α →₁[μ] β) : ‖f - g‖ = (∫⁻ x, ‖f x - g x‖ₑ ∂μ).toReal := by + rw [norm_def] + congr 1 + rw [lintegral_congr_ae] + filter_upwards [Lp.coeFn_sub f g] with _ ha + simp only [ha, Pi.sub_apply] + +theorem ofReal_norm_eq_lintegral (f : α →₁[μ] β) : ENNReal.ofReal ‖f‖ = ∫⁻ x, ‖f x‖ₑ ∂μ := by + rw [norm_def, ENNReal.ofReal_toReal] + exact ne_of_lt (hasFiniteIntegral_coeFn f) + +/-- Computing the norm of a difference between two L¹-functions. Note that this is not a + special case of `ofReal_norm_eq_lintegral` since `(f - g) x` and `f x - g x` are not equal + (but only a.e.-equal). -/ +theorem ofReal_norm_sub_eq_lintegral (f g : α →₁[μ] β) : + ENNReal.ofReal ‖f - g‖ = ∫⁻ x, ‖f x - g x‖ₑ ∂μ := by + simp_rw [ofReal_norm_eq_lintegral, ← edist_zero_eq_enorm] + apply lintegral_congr_ae + filter_upwards [Lp.coeFn_sub f g] with _ ha + simp only [ha, Pi.sub_apply] + +end L1 + +namespace Integrable + + +/-- Construct the equivalence class `[f]` of an integrable function `f`, as a member of the +space `Lp β 1 μ`. -/ +def toL1 (f : α → β) (hf : Integrable f μ) : α →₁[μ] β := + (memℒp_one_iff_integrable.2 hf).toLp f + +@[simp] +theorem toL1_coeFn (f : α →₁[μ] β) (hf : Integrable f μ) : hf.toL1 f = f := by + simp [Integrable.toL1] + +theorem coeFn_toL1 {f : α → β} (hf : Integrable f μ) : hf.toL1 f =ᵐ[μ] f := + AEEqFun.coeFn_mk _ _ + +@[simp] +theorem toL1_zero (h : Integrable (0 : α → β) μ) : h.toL1 0 = 0 := + rfl + +@[simp] +theorem toL1_eq_mk (f : α → β) (hf : Integrable f μ) : + (hf.toL1 f : α →ₘ[μ] β) = AEEqFun.mk f hf.aestronglyMeasurable := + rfl + +@[simp] +theorem toL1_eq_toL1_iff (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : + toL1 f hf = toL1 g hg ↔ f =ᵐ[μ] g := + Memℒp.toLp_eq_toLp_iff _ _ + +theorem toL1_add (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : + toL1 (f + g) (hf.add hg) = toL1 f hf + toL1 g hg := + rfl + +theorem toL1_neg (f : α → β) (hf : Integrable f μ) : toL1 (-f) (Integrable.neg hf) = -toL1 f hf := + rfl + +theorem toL1_sub (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : + toL1 (f - g) (hf.sub hg) = toL1 f hf - toL1 g hg := + rfl + +theorem norm_toL1 (f : α → β) (hf : Integrable f μ) : + ‖hf.toL1 f‖ = (∫⁻ a, edist (f a) 0 ∂μ).toReal := by + simp [toL1, Lp.norm_toLp, eLpNorm, eLpNorm'_eq_lintegral_enorm] + +theorem enorm_toL1 {f : α → β} (hf : Integrable f μ) : ‖hf.toL1 f‖ₑ = ∫⁻ a, ‖f a‖ₑ ∂μ := by + simpa [Integrable.toL1, eLpNorm, eLpNorm', enorm] using ENNReal.coe_toNNReal hf.2.ne + +@[deprecated (since := "2025-01-20")] alias nnnorm_toL1 := enorm_toL1 + +theorem norm_toL1_eq_lintegral_norm (f : α → β) (hf : Integrable f μ) : + ‖hf.toL1 f‖ = ENNReal.toReal (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) := by + rw [norm_toL1, lintegral_norm_eq_lintegral_edist] + +@[simp] +theorem edist_toL1_toL1 (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : + edist (hf.toL1 f) (hg.toL1 g) = ∫⁻ a, edist (f a) (g a) ∂μ := by + simp only [toL1, Lp.edist_toLp_toLp, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_enorm, + Pi.sub_apply, one_toReal, ENNReal.rpow_one, ne_eq, not_false_eq_true, div_self, ite_false] + simp [edist_eq_enorm_sub] + +theorem edist_toL1_zero (f : α → β) (hf : Integrable f μ) : + edist (hf.toL1 f) 0 = ∫⁻ a, edist (f a) 0 ∂μ := by + simp only [edist_zero_right, Lp.enorm_def, toL1_eq_mk, eLpNorm_aeeqFun] + apply eLpNorm_one_eq_lintegral_enorm + +variable {𝕜 : Type*} [NormedRing 𝕜] [Module 𝕜 β] [BoundedSMul 𝕜 β] + +theorem toL1_smul (f : α → β) (hf : Integrable f μ) (k : 𝕜) : + toL1 (fun a => k • f a) (hf.smul k) = k • toL1 f hf := + rfl + +theorem toL1_smul' (f : α → β) (hf : Integrable f μ) (k : 𝕜) : + toL1 (k • f) (hf.smul k) = k • toL1 f hf := + rfl + +end Integrable + +end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/L1Space/HasFiniteIntegral.lean b/Mathlib/MeasureTheory/Function/L1Space/HasFiniteIntegral.lean new file mode 100644 index 0000000000000..8aee3621a62b0 --- /dev/null +++ b/Mathlib/MeasureTheory/Function/L1Space/HasFiniteIntegral.lean @@ -0,0 +1,398 @@ +/- +Copyright (c) 2019 Zhouhang Zhou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Zhouhang Zhou +-/ +import Mathlib.MeasureTheory.Function.StronglyMeasurable.Basic +import Mathlib.MeasureTheory.Measure.WithDensity + +/-! +# Function with finite integral + +In this file we define the predicate `HasFiniteIntegral`, which is then used to define the +predicate `Integrable` in the corresponding file. + +## Main definition + +* Let `f : α → β` be a function, where `α` is a `MeasureSpace` and `β` a `NormedAddCommGroup`. + Then `HasFiniteIntegral f` means `∫⁻ a, ‖f a‖ₑ < ∞`. + +## Tags + +finite integral + +-/ + + +noncomputable section + +open Topology ENNReal MeasureTheory NNReal + +open Set Filter TopologicalSpace ENNReal EMetric MeasureTheory + +variable {α β γ ε : Type*} {m : MeasurableSpace α} {μ ν : Measure α} +variable [NormedAddCommGroup β] [NormedAddCommGroup γ] [ENorm ε] + +namespace MeasureTheory + +/-! ### Some results about the Lebesgue integral involving a normed group -/ + +lemma lintegral_enorm_eq_lintegral_edist (f : α → β) : + ∫⁻ a, ‖f a‖ₑ ∂μ = ∫⁻ a, edist (f a) 0 ∂μ := by simp only [edist_zero_eq_enorm] + +@[deprecated (since := "2025-01-20")] +alias lintegral_nnnorm_eq_lintegral_edist := lintegral_enorm_eq_lintegral_edist + +theorem lintegral_norm_eq_lintegral_edist (f : α → β) : + ∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ = ∫⁻ a, edist (f a) 0 ∂μ := by + simp only [ofReal_norm_eq_enorm, edist_zero_eq_enorm] + +theorem lintegral_edist_triangle {f g h : α → β} (hf : AEStronglyMeasurable f μ) + (hh : AEStronglyMeasurable h μ) : + (∫⁻ a, edist (f a) (g a) ∂μ) ≤ (∫⁻ a, edist (f a) (h a) ∂μ) + ∫⁻ a, edist (g a) (h a) ∂μ := by + rw [← lintegral_add_left' (hf.edist hh)] + refine lintegral_mono fun a => ?_ + apply edist_triangle_right + +-- Yaël: Why do the following four lemmas even exist? +theorem lintegral_enorm_zero : ∫⁻ _ : α, ‖(0 : β)‖ₑ ∂μ = 0 := by simp + +theorem lintegral_enorm_add_left {f : α → β} (hf : AEStronglyMeasurable f μ) (g : α → γ) : + ∫⁻ a, ‖f a‖ₑ + ‖g a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ + ∫⁻ a, ‖g a‖ₑ ∂μ := + lintegral_add_left' hf.enorm _ + +theorem lintegral_enorm_add_right (f : α → β) {g : α → γ} (hg : AEStronglyMeasurable g μ) : + ∫⁻ a, ‖f a‖ₑ + ‖g a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ + ∫⁻ a, ‖g a‖ₑ ∂μ := + lintegral_add_right' _ hg.enorm + +theorem lintegral_enorm_neg {f : α → β} : ∫⁻ a, ‖(-f) a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ := by simp + +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_zero := lintegral_enorm_zero +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_add_left := lintegral_enorm_add_left +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_add_right := lintegral_enorm_add_right +@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_neg := lintegral_enorm_neg + +/-! ### The predicate `HasFiniteIntegral` -/ + + +/-- `HasFiniteIntegral f μ` means that the integral `∫⁻ a, ‖f a‖ ∂μ` is finite. + `HasFiniteIntegral f` means `HasFiniteIntegral f volume`. -/ +def HasFiniteIntegral {_ : MeasurableSpace α} (f : α → ε) + (μ : Measure α := by volume_tac) : Prop := + ∫⁻ a, ‖f a‖ₑ ∂μ < ∞ + +theorem hasFiniteIntegral_def {_ : MeasurableSpace α} (f : α → ε) (μ : Measure α) : + HasFiniteIntegral f μ ↔ (∫⁻ a, ‖f a‖ₑ ∂μ < ∞) := + Iff.rfl + +theorem hasFiniteIntegral_iff_enorm {f : α → β} : HasFiniteIntegral f μ ↔ ∫⁻ a, ‖f a‖ₑ ∂μ < ∞ := by + simp only [HasFiniteIntegral, ofReal_norm_eq_enorm, enorm_eq_nnnorm] + +@[deprecated (since := "2025-01-20")] +alias hasFiniteIntegral_iff_nnnorm := hasFiniteIntegral_iff_enorm + +theorem hasFiniteIntegral_iff_norm (f : α → β) : + HasFiniteIntegral f μ ↔ (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) < ∞ := by + simp only [hasFiniteIntegral_iff_enorm, ofReal_norm_eq_enorm] + +theorem hasFiniteIntegral_iff_edist (f : α → β) : + HasFiniteIntegral f μ ↔ (∫⁻ a, edist (f a) 0 ∂μ) < ∞ := by + simp only [hasFiniteIntegral_iff_norm, edist_dist, dist_zero_right] + +theorem hasFiniteIntegral_iff_ofReal {f : α → ℝ} (h : 0 ≤ᵐ[μ] f) : + HasFiniteIntegral f μ ↔ (∫⁻ a, ENNReal.ofReal (f a) ∂μ) < ∞ := by + rw [hasFiniteIntegral_iff_enorm, lintegral_enorm_of_ae_nonneg h] + +theorem hasFiniteIntegral_iff_ofNNReal {f : α → ℝ≥0} : + HasFiniteIntegral (fun x => (f x : ℝ)) μ ↔ (∫⁻ a, f a ∂μ) < ∞ := by + simp [hasFiniteIntegral_iff_norm] + +theorem HasFiniteIntegral.mono {f : α → β} {g : α → γ} (hg : HasFiniteIntegral g μ) + (h : ∀ᵐ a ∂μ, ‖f a‖ ≤ ‖g a‖) : HasFiniteIntegral f μ := by + simp only [hasFiniteIntegral_iff_norm] at * + calc + (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) ≤ ∫⁻ a : α, ENNReal.ofReal ‖g a‖ ∂μ := + lintegral_mono_ae (h.mono fun a h => ofReal_le_ofReal h) + _ < ∞ := hg + +theorem HasFiniteIntegral.mono' {f : α → β} {g : α → ℝ} (hg : HasFiniteIntegral g μ) + (h : ∀ᵐ a ∂μ, ‖f a‖ ≤ g a) : HasFiniteIntegral f μ := + hg.mono <| h.mono fun _x hx => le_trans hx (le_abs_self _) + +theorem HasFiniteIntegral.congr' {f : α → β} {g : α → γ} (hf : HasFiniteIntegral f μ) + (h : ∀ᵐ a ∂μ, ‖f a‖ = ‖g a‖) : HasFiniteIntegral g μ := + hf.mono <| EventuallyEq.le <| EventuallyEq.symm h + +theorem hasFiniteIntegral_congr' {f : α → β} {g : α → γ} (h : ∀ᵐ a ∂μ, ‖f a‖ = ‖g a‖) : + HasFiniteIntegral f μ ↔ HasFiniteIntegral g μ := + ⟨fun hf => hf.congr' h, fun hg => hg.congr' <| EventuallyEq.symm h⟩ + +theorem HasFiniteIntegral.congr {f g : α → β} (hf : HasFiniteIntegral f μ) (h : f =ᵐ[μ] g) : + HasFiniteIntegral g μ := + hf.congr' <| h.fun_comp norm + +theorem hasFiniteIntegral_congr {f g : α → β} (h : f =ᵐ[μ] g) : + HasFiniteIntegral f μ ↔ HasFiniteIntegral g μ := + hasFiniteIntegral_congr' <| h.fun_comp norm + +theorem hasFiniteIntegral_const_iff {c : β} : + HasFiniteIntegral (fun _ : α => c) μ ↔ c = 0 ∨ IsFiniteMeasure μ := by + simp [hasFiniteIntegral_iff_enorm, lintegral_const, lt_top_iff_ne_top, ENNReal.mul_eq_top, + or_iff_not_imp_left, isFiniteMeasure_iff] + +lemma hasFiniteIntegral_const_iff_isFiniteMeasure {c : β} (hc : c ≠ 0) : + HasFiniteIntegral (fun _ ↦ c) μ ↔ IsFiniteMeasure μ := by + simp [hasFiniteIntegral_const_iff, hc, isFiniteMeasure_iff] + +theorem hasFiniteIntegral_const [IsFiniteMeasure μ] (c : β) : + HasFiniteIntegral (fun _ : α => c) μ := + hasFiniteIntegral_const_iff.2 <| .inr ‹_› + +theorem HasFiniteIntegral.of_mem_Icc [IsFiniteMeasure μ] (a b : ℝ) {X : α → ℝ} + (h : ∀ᵐ ω ∂μ, X ω ∈ Set.Icc a b) : + HasFiniteIntegral X μ := by + apply (hasFiniteIntegral_const (max ‖a‖ ‖b‖)).mono' + filter_upwards [h.mono fun ω h ↦ h.1, h.mono fun ω h ↦ h.2] with ω using abs_le_max_abs_abs + +theorem hasFiniteIntegral_of_bounded [IsFiniteMeasure μ] {f : α → β} {C : ℝ} + (hC : ∀ᵐ a ∂μ, ‖f a‖ ≤ C) : HasFiniteIntegral f μ := + (hasFiniteIntegral_const C).mono' hC + +theorem HasFiniteIntegral.of_finite [Finite α] [IsFiniteMeasure μ] {f : α → β} : + HasFiniteIntegral f μ := + let ⟨_⟩ := nonempty_fintype α + hasFiniteIntegral_of_bounded <| ae_of_all μ <| norm_le_pi_norm f + +theorem HasFiniteIntegral.mono_measure {f : α → β} (h : HasFiniteIntegral f ν) (hμ : μ ≤ ν) : + HasFiniteIntegral f μ := + lt_of_le_of_lt (lintegral_mono' hμ le_rfl) h + +theorem HasFiniteIntegral.add_measure {f : α → β} (hμ : HasFiniteIntegral f μ) + (hν : HasFiniteIntegral f ν) : HasFiniteIntegral f (μ + ν) := by + simp only [HasFiniteIntegral, lintegral_add_measure] at * + exact add_lt_top.2 ⟨hμ, hν⟩ + +theorem HasFiniteIntegral.left_of_add_measure {f : α → β} (h : HasFiniteIntegral f (μ + ν)) : + HasFiniteIntegral f μ := + h.mono_measure <| Measure.le_add_right <| le_rfl + +theorem HasFiniteIntegral.right_of_add_measure {f : α → β} (h : HasFiniteIntegral f (μ + ν)) : + HasFiniteIntegral f ν := + h.mono_measure <| Measure.le_add_left <| le_rfl + +@[simp] +theorem hasFiniteIntegral_add_measure {f : α → β} : + HasFiniteIntegral f (μ + ν) ↔ HasFiniteIntegral f μ ∧ HasFiniteIntegral f ν := + ⟨fun h => ⟨h.left_of_add_measure, h.right_of_add_measure⟩, fun h => h.1.add_measure h.2⟩ + +theorem HasFiniteIntegral.smul_measure {f : α → β} (h : HasFiniteIntegral f μ) {c : ℝ≥0∞} + (hc : c ≠ ∞) : HasFiniteIntegral f (c • μ) := by + simp only [HasFiniteIntegral, lintegral_smul_measure] at * + exact mul_lt_top hc.lt_top h + +@[simp] +theorem hasFiniteIntegral_zero_measure {m : MeasurableSpace α} (f : α → β) : + HasFiniteIntegral f (0 : Measure α) := by + simp only [HasFiniteIntegral, lintegral_zero_measure, zero_lt_top] + +variable (α β μ) + +@[simp] +theorem hasFiniteIntegral_zero : HasFiniteIntegral (fun _ : α => (0 : β)) μ := by + simp [hasFiniteIntegral_iff_enorm] + +variable {α β μ} + +theorem HasFiniteIntegral.neg {f : α → β} (hfi : HasFiniteIntegral f μ) : + HasFiniteIntegral (-f) μ := by simpa [hasFiniteIntegral_iff_enorm] using hfi + +@[simp] +theorem hasFiniteIntegral_neg_iff {f : α → β} : HasFiniteIntegral (-f) μ ↔ HasFiniteIntegral f μ := + ⟨fun h => neg_neg f ▸ h.neg, HasFiniteIntegral.neg⟩ + +theorem HasFiniteIntegral.norm {f : α → β} (hfi : HasFiniteIntegral f μ) : + HasFiniteIntegral (fun a => ‖f a‖) μ := by simpa [hasFiniteIntegral_iff_enorm] using hfi + +theorem hasFiniteIntegral_norm_iff (f : α → β) : + HasFiniteIntegral (fun a => ‖f a‖) μ ↔ HasFiniteIntegral f μ := + hasFiniteIntegral_congr' <| Eventually.of_forall fun x => norm_norm (f x) + +theorem hasFiniteIntegral_toReal_of_lintegral_ne_top {f : α → ℝ≥0∞} (hf : ∫⁻ x, f x ∂μ ≠ ∞) : + HasFiniteIntegral (fun x ↦ (f x).toReal) μ := by + have h x : ‖(f x).toReal‖ₑ = .ofReal (f x).toReal := by + rw [Real.enorm_of_nonneg ENNReal.toReal_nonneg] + simp_rw [hasFiniteIntegral_iff_enorm, h] + refine lt_of_le_of_lt (lintegral_mono fun x => ?_) (lt_top_iff_ne_top.2 hf) + by_cases hfx : f x = ∞ + · simp [hfx] + · lift f x to ℝ≥0 using hfx with fx h + simp [← h, ← NNReal.coe_le_coe] + +lemma hasFiniteIntegral_toReal_iff {f : α → ℝ≥0∞} (hf : ∀ᵐ x ∂μ, f x ≠ ∞) : + HasFiniteIntegral (fun x ↦ (f x).toReal) μ ↔ ∫⁻ x, f x ∂μ ≠ ∞ := by + have : ∀ᵐ x ∂μ, .ofReal (f x).toReal = f x := by filter_upwards [hf] with x hx; simp [hx] + simp [hasFiniteIntegral_iff_enorm, Real.enorm_of_nonneg ENNReal.toReal_nonneg, + lintegral_congr_ae this, lt_top_iff_ne_top] + +theorem isFiniteMeasure_withDensity_ofReal {f : α → ℝ} (hfi : HasFiniteIntegral f μ) : + IsFiniteMeasure (μ.withDensity fun x => ENNReal.ofReal <| f x) := by + refine isFiniteMeasure_withDensity ((lintegral_mono fun x => ?_).trans_lt hfi).ne + exact Real.ofReal_le_enorm (f x) + +section DominatedConvergence + +variable {F : ℕ → α → β} {f : α → β} {bound : α → ℝ} + +theorem all_ae_ofReal_F_le_bound (h : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) : + ∀ n, ∀ᵐ a ∂μ, ENNReal.ofReal ‖F n a‖ ≤ ENNReal.ofReal (bound a) := fun n => + (h n).mono fun _ h => ENNReal.ofReal_le_ofReal h + +theorem all_ae_tendsto_ofReal_norm (h : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop <| 𝓝 <| f a) : + ∀ᵐ a ∂μ, Tendsto (fun n => ENNReal.ofReal ‖F n a‖) atTop <| 𝓝 <| ENNReal.ofReal ‖f a‖ := + h.mono fun _ h => tendsto_ofReal <| Tendsto.comp (Continuous.tendsto continuous_norm _) h + +theorem all_ae_ofReal_f_le_bound (h_bound : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) + (h_lim : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop (𝓝 (f a))) : + ∀ᵐ a ∂μ, ENNReal.ofReal ‖f a‖ ≤ ENNReal.ofReal (bound a) := by + have F_le_bound := all_ae_ofReal_F_le_bound h_bound + rw [← ae_all_iff] at F_le_bound + apply F_le_bound.mp ((all_ae_tendsto_ofReal_norm h_lim).mono _) + intro a tendsto_norm F_le_bound + exact le_of_tendsto' tendsto_norm F_le_bound + +theorem hasFiniteIntegral_of_dominated_convergence {F : ℕ → α → β} {f : α → β} {bound : α → ℝ} + (bound_hasFiniteIntegral : HasFiniteIntegral bound μ) + (h_bound : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) + (h_lim : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop (𝓝 (f a))) : HasFiniteIntegral f μ := by + /- `‖F n a‖ ≤ bound a` and `‖F n a‖ --> ‖f a‖` implies `‖f a‖ ≤ bound a`, + and so `∫ ‖f‖ ≤ ∫ bound < ∞` since `bound` is has_finite_integral -/ + rw [hasFiniteIntegral_iff_norm] + calc + (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) ≤ ∫⁻ a, ENNReal.ofReal (bound a) ∂μ := + lintegral_mono_ae <| all_ae_ofReal_f_le_bound h_bound h_lim + _ < ∞ := by + rw [← hasFiniteIntegral_iff_ofReal] + · exact bound_hasFiniteIntegral + exact (h_bound 0).mono fun a h => le_trans (norm_nonneg _) h + +theorem tendsto_lintegral_norm_of_dominated_convergence {F : ℕ → α → β} {f : α → β} {bound : α → ℝ} + (F_measurable : ∀ n, AEStronglyMeasurable (F n) μ) + (bound_hasFiniteIntegral : HasFiniteIntegral bound μ) + (h_bound : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) + (h_lim : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop (𝓝 (f a))) : + Tendsto (fun n => ∫⁻ a, ENNReal.ofReal ‖F n a - f a‖ ∂μ) atTop (𝓝 0) := by + have f_measurable : AEStronglyMeasurable f μ := + aestronglyMeasurable_of_tendsto_ae _ F_measurable h_lim + let b a := 2 * ENNReal.ofReal (bound a) + /- `‖F n a‖ ≤ bound a` and `F n a --> f a` implies `‖f a‖ ≤ bound a`, and thus by the + triangle inequality, have `‖F n a - f a‖ ≤ 2 * (bound a)`. -/ + have hb : ∀ n, ∀ᵐ a ∂μ, ENNReal.ofReal ‖F n a - f a‖ ≤ b a := by + intro n + filter_upwards [all_ae_ofReal_F_le_bound h_bound n, + all_ae_ofReal_f_le_bound h_bound h_lim] with a h₁ h₂ + calc + ENNReal.ofReal ‖F n a - f a‖ ≤ ENNReal.ofReal ‖F n a‖ + ENNReal.ofReal ‖f a‖ := by + rw [← ENNReal.ofReal_add] + · apply ofReal_le_ofReal + apply norm_sub_le + · exact norm_nonneg _ + · exact norm_nonneg _ + _ ≤ ENNReal.ofReal (bound a) + ENNReal.ofReal (bound a) := add_le_add h₁ h₂ + _ = b a := by rw [← two_mul] + -- On the other hand, `F n a --> f a` implies that `‖F n a - f a‖ --> 0` + have h : ∀ᵐ a ∂μ, Tendsto (fun n => ENNReal.ofReal ‖F n a - f a‖) atTop (𝓝 0) := by + rw [← ENNReal.ofReal_zero] + refine h_lim.mono fun a h => (continuous_ofReal.tendsto _).comp ?_ + rwa [← tendsto_iff_norm_sub_tendsto_zero] + /- Therefore, by the dominated convergence theorem for nonnegative integration, have + ` ∫ ‖f a - F n a‖ --> 0 ` -/ + suffices Tendsto (fun n => ∫⁻ a, ENNReal.ofReal ‖F n a - f a‖ ∂μ) atTop (𝓝 (∫⁻ _ : α, 0 ∂μ)) by + rwa [lintegral_zero] at this + -- Using the dominated convergence theorem. + refine tendsto_lintegral_of_dominated_convergence' _ ?_ hb ?_ ?_ + -- Show `fun a => ‖f a - F n a‖` is almost everywhere measurable for all `n` + · exact fun n => + measurable_ofReal.comp_aemeasurable ((F_measurable n).sub f_measurable).norm.aemeasurable + -- Show `2 * bound` `HasFiniteIntegral` + · rw [hasFiniteIntegral_iff_ofReal] at bound_hasFiniteIntegral + · calc + ∫⁻ a, b a ∂μ = 2 * ∫⁻ a, ENNReal.ofReal (bound a) ∂μ := by + rw [lintegral_const_mul'] + exact coe_ne_top + _ ≠ ∞ := mul_ne_top coe_ne_top bound_hasFiniteIntegral.ne + filter_upwards [h_bound 0] with _ h using le_trans (norm_nonneg _) h + -- Show `‖f a - F n a‖ --> 0` + · exact h + +end DominatedConvergence + +section PosPart + +/-! Lemmas used for defining the positive part of an `L¹` function -/ + + +theorem HasFiniteIntegral.max_zero {f : α → ℝ} (hf : HasFiniteIntegral f μ) : + HasFiniteIntegral (fun a => max (f a) 0) μ := + hf.mono <| Eventually.of_forall fun x => by simp [abs_le, le_abs_self] + +theorem HasFiniteIntegral.min_zero {f : α → ℝ} (hf : HasFiniteIntegral f μ) : + HasFiniteIntegral (fun a => min (f a) 0) μ := + hf.mono <| Eventually.of_forall fun x => by simpa [abs_le] using neg_abs_le _ + +end PosPart + +section NormedSpace + +variable {𝕜 : Type*} + +theorem HasFiniteIntegral.smul [NormedAddCommGroup 𝕜] [SMulZeroClass 𝕜 β] [BoundedSMul 𝕜 β] (c : 𝕜) + {f : α → β} : HasFiniteIntegral f μ → HasFiniteIntegral (c • f) μ := by + simp only [HasFiniteIntegral]; intro hfi + calc + ∫⁻ a : α, ‖c • f a‖ₑ ∂μ ≤ ∫⁻ a : α, ‖c‖ₑ * ‖f a‖ₑ ∂μ := lintegral_mono fun i ↦ enorm_smul_le + _ < ∞ := by + rw [lintegral_const_mul'] + exacts [mul_lt_top coe_lt_top hfi, coe_ne_top] + +theorem hasFiniteIntegral_smul_iff [NormedRing 𝕜] [MulActionWithZero 𝕜 β] [BoundedSMul 𝕜 β] {c : 𝕜} + (hc : IsUnit c) (f : α → β) : HasFiniteIntegral (c • f) μ ↔ HasFiniteIntegral f μ := by + obtain ⟨c, rfl⟩ := hc + constructor + · intro h + simpa only [smul_smul, Units.inv_mul, one_smul] using h.smul ((c⁻¹ : 𝕜ˣ) : 𝕜) + exact HasFiniteIntegral.smul _ + +theorem HasFiniteIntegral.const_mul [NormedRing 𝕜] {f : α → 𝕜} (h : HasFiniteIntegral f μ) (c : 𝕜) : + HasFiniteIntegral (fun x => c * f x) μ := + h.smul c + +theorem HasFiniteIntegral.mul_const [NormedRing 𝕜] {f : α → 𝕜} (h : HasFiniteIntegral f μ) (c : 𝕜) : + HasFiniteIntegral (fun x => f x * c) μ := + h.smul (MulOpposite.op c) + +section count + +variable [MeasurableSingletonClass α] {f : α → β} + +/-- A function has finite integral for the counting measure iff its norm is summable. -/ +lemma hasFiniteIntegral_count_iff : + HasFiniteIntegral f Measure.count ↔ Summable (‖f ·‖) := by + simp only [hasFiniteIntegral_iff_enorm, enorm, lintegral_count, lt_top_iff_ne_top, + tsum_coe_ne_top_iff_summable, ← summable_coe, coe_nnnorm] + +end count + +section restrict + +variable {E : Type*} [NormedAddCommGroup E] {f : α → E} + +lemma HasFiniteIntegral.restrict (h : HasFiniteIntegral f μ) {s : Set α} : + HasFiniteIntegral f (μ.restrict s) := by + refine lt_of_le_of_lt ?_ h + simpa [Measure.restrict_univ] using lintegral_mono_set (subset_univ s) + +end restrict + +end NormedSpace + +end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space/Integrable.lean similarity index 63% rename from Mathlib/MeasureTheory/Function/L1Space.lean rename to Mathlib/MeasureTheory/Function/L1Space/Integrable.lean index ddb275e70d230..37cfdc0b9cc29 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space/Integrable.lean @@ -3,35 +3,23 @@ Copyright (c) 2019 Zhouhang Zhou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Zhouhang Zhou -/ +import Mathlib.MeasureTheory.Function.L1Space.HasFiniteIntegral import Mathlib.MeasureTheory.Function.LpOrder import Mathlib.MeasureTheory.Function.StronglyMeasurable.Lemmas /-! -# Integrable functions and `L¹` space +# Integrable functions -In the first part of this file, the predicate `Integrable` is defined and basic properties of +In this file, the predicate `Integrable` is defined and basic properties of integrable functions are proved. Such a predicate is already available under the name `Memℒp 1`. We give a direct definition which -is easier to use, and show that it is equivalent to `Memℒp 1` +is easier to use, and show that it is equivalent to `Memℒp 1`. -In the second part, we establish an API between `Integrable` and the space `L¹` of equivalence -classes of integrable functions, already defined as a special case of `L^p` spaces for `p = 1`. +## Main definition -## Notation - -* `α →₁[μ] β` is the type of `L¹` space, where `α` is a `MeasureSpace` and `β` is a - `NormedAddCommGroup` with a `SecondCountableTopology`. `f : α →ₘ β` is a "function" in `L¹`. - In comments, `[f]` is also used to denote an `L¹` function. - - `₁` can be typed as `\1`. - -## Main definitions - -* Let `f : α → β` be a function, where `α` is a `MeasureSpace` and `β` a `NormedAddCommGroup`. - Then `HasFiniteIntegral f` means `∫⁻ a, ‖f a‖ₑ < ∞`. - -* If `β` is moreover a `MeasurableSpace` then `f` is called `Integrable` if +* Let `f : α → β` be a function, where `α` is a `MeasureSpace` and `β` a `NormedAddCommGroup` + which also a `MeasurableSpace`. Then `f` is called `Integrable` if `f` is `Measurable` and `HasFiniteIntegral f` holds. ## Implementation notes @@ -41,359 +29,20 @@ To prove something for an arbitrary integrable function, a useful theorem is ## Tags -integrable, function space, l1 +integrable -/ noncomputable section -open Topology ENNReal MeasureTheory NNReal - -open Set Filter TopologicalSpace ENNReal EMetric MeasureTheory +open EMetric ENNReal Filter MeasureTheory NNReal Set variable {α β γ δ ε : Type*} {m : MeasurableSpace α} {μ ν : Measure α} [MeasurableSpace δ] variable [NormedAddCommGroup β] [NormedAddCommGroup γ] [ENorm ε] namespace MeasureTheory -/-! ### Some results about the Lebesgue integral involving a normed group -/ - -lemma lintegral_enorm_eq_lintegral_edist (f : α → β) : - ∫⁻ a, ‖f a‖ₑ ∂μ = ∫⁻ a, edist (f a) 0 ∂μ := by simp only [edist_zero_eq_enorm] - -@[deprecated (since := "2025-01-20")] -alias lintegral_nnnorm_eq_lintegral_edist := lintegral_enorm_eq_lintegral_edist - -theorem lintegral_norm_eq_lintegral_edist (f : α → β) : - ∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ = ∫⁻ a, edist (f a) 0 ∂μ := by - simp only [ofReal_norm_eq_enorm, edist_zero_eq_enorm] - -theorem lintegral_edist_triangle {f g h : α → β} (hf : AEStronglyMeasurable f μ) - (hh : AEStronglyMeasurable h μ) : - (∫⁻ a, edist (f a) (g a) ∂μ) ≤ (∫⁻ a, edist (f a) (h a) ∂μ) + ∫⁻ a, edist (g a) (h a) ∂μ := by - rw [← lintegral_add_left' (hf.edist hh)] - refine lintegral_mono fun a => ?_ - apply edist_triangle_right - --- Yaël: Why do the following four lemmas even exist? -theorem lintegral_enorm_zero : ∫⁻ _ : α, ‖(0 : β)‖ₑ ∂μ = 0 := by simp - -theorem lintegral_enorm_add_left {f : α → β} (hf : AEStronglyMeasurable f μ) (g : α → γ) : - ∫⁻ a, ‖f a‖ₑ + ‖g a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ + ∫⁻ a, ‖g a‖ₑ ∂μ := - lintegral_add_left' hf.enorm _ - -theorem lintegral_enorm_add_right (f : α → β) {g : α → γ} (hg : AEStronglyMeasurable g μ) : - ∫⁻ a, ‖f a‖ₑ + ‖g a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ + ∫⁻ a, ‖g a‖ₑ ∂μ := - lintegral_add_right' _ hg.enorm - -theorem lintegral_enorm_neg {f : α → β} : ∫⁻ a, ‖(-f) a‖ₑ ∂μ = ∫⁻ a, ‖f a‖ₑ ∂μ := by simp - -@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_zero := lintegral_enorm_zero -@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_add_left := lintegral_enorm_add_left -@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_add_right := lintegral_enorm_add_right -@[deprecated (since := "2025-01-21")] alias lintegral_nnnorm_neg := lintegral_enorm_neg - -/-! ### The predicate `HasFiniteIntegral` -/ - - -/-- `HasFiniteIntegral f μ` means that the integral `∫⁻ a, ‖f a‖ ∂μ` is finite. - `HasFiniteIntegral f` means `HasFiniteIntegral f volume`. -/ -def HasFiniteIntegral {_ : MeasurableSpace α} (f : α → ε) - (μ : Measure α := by volume_tac) : Prop := - ∫⁻ a, ‖f a‖ₑ ∂μ < ∞ - -theorem hasFiniteIntegral_def {_ : MeasurableSpace α} (f : α → ε) (μ : Measure α) : - HasFiniteIntegral f μ ↔ (∫⁻ a, ‖f a‖ₑ ∂μ < ∞) := - Iff.rfl - -theorem hasFiniteIntegral_iff_enorm {f : α → β} : HasFiniteIntegral f μ ↔ ∫⁻ a, ‖f a‖ₑ ∂μ < ∞ := by - simp only [HasFiniteIntegral, ofReal_norm_eq_enorm, enorm_eq_nnnorm] - -@[deprecated (since := "2025-01-20")] -alias hasFiniteIntegral_iff_nnnorm := hasFiniteIntegral_iff_enorm - -theorem hasFiniteIntegral_iff_norm (f : α → β) : - HasFiniteIntegral f μ ↔ (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) < ∞ := by - simp only [hasFiniteIntegral_iff_enorm, ofReal_norm_eq_enorm] - -theorem hasFiniteIntegral_iff_edist (f : α → β) : - HasFiniteIntegral f μ ↔ (∫⁻ a, edist (f a) 0 ∂μ) < ∞ := by - simp only [hasFiniteIntegral_iff_norm, edist_dist, dist_zero_right] - -theorem hasFiniteIntegral_iff_ofReal {f : α → ℝ} (h : 0 ≤ᵐ[μ] f) : - HasFiniteIntegral f μ ↔ (∫⁻ a, ENNReal.ofReal (f a) ∂μ) < ∞ := by - rw [hasFiniteIntegral_iff_enorm, lintegral_enorm_of_ae_nonneg h] - -theorem hasFiniteIntegral_iff_ofNNReal {f : α → ℝ≥0} : - HasFiniteIntegral (fun x => (f x : ℝ)) μ ↔ (∫⁻ a, f a ∂μ) < ∞ := by - simp [hasFiniteIntegral_iff_norm] - -theorem HasFiniteIntegral.mono {f : α → β} {g : α → γ} (hg : HasFiniteIntegral g μ) - (h : ∀ᵐ a ∂μ, ‖f a‖ ≤ ‖g a‖) : HasFiniteIntegral f μ := by - simp only [hasFiniteIntegral_iff_norm] at * - calc - (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) ≤ ∫⁻ a : α, ENNReal.ofReal ‖g a‖ ∂μ := - lintegral_mono_ae (h.mono fun a h => ofReal_le_ofReal h) - _ < ∞ := hg - -theorem HasFiniteIntegral.mono' {f : α → β} {g : α → ℝ} (hg : HasFiniteIntegral g μ) - (h : ∀ᵐ a ∂μ, ‖f a‖ ≤ g a) : HasFiniteIntegral f μ := - hg.mono <| h.mono fun _x hx => le_trans hx (le_abs_self _) - -theorem HasFiniteIntegral.congr' {f : α → β} {g : α → γ} (hf : HasFiniteIntegral f μ) - (h : ∀ᵐ a ∂μ, ‖f a‖ = ‖g a‖) : HasFiniteIntegral g μ := - hf.mono <| EventuallyEq.le <| EventuallyEq.symm h - -theorem hasFiniteIntegral_congr' {f : α → β} {g : α → γ} (h : ∀ᵐ a ∂μ, ‖f a‖ = ‖g a‖) : - HasFiniteIntegral f μ ↔ HasFiniteIntegral g μ := - ⟨fun hf => hf.congr' h, fun hg => hg.congr' <| EventuallyEq.symm h⟩ - -theorem HasFiniteIntegral.congr {f g : α → β} (hf : HasFiniteIntegral f μ) (h : f =ᵐ[μ] g) : - HasFiniteIntegral g μ := - hf.congr' <| h.fun_comp norm - -theorem hasFiniteIntegral_congr {f g : α → β} (h : f =ᵐ[μ] g) : - HasFiniteIntegral f μ ↔ HasFiniteIntegral g μ := - hasFiniteIntegral_congr' <| h.fun_comp norm - -theorem hasFiniteIntegral_const_iff {c : β} : - HasFiniteIntegral (fun _ : α => c) μ ↔ c = 0 ∨ IsFiniteMeasure μ := by - simp [hasFiniteIntegral_iff_enorm, lintegral_const, lt_top_iff_ne_top, ENNReal.mul_eq_top, - or_iff_not_imp_left, isFiniteMeasure_iff] - -lemma hasFiniteIntegral_const_iff_isFiniteMeasure {c : β} (hc : c ≠ 0) : - HasFiniteIntegral (fun _ ↦ c) μ ↔ IsFiniteMeasure μ := by - simp [hasFiniteIntegral_const_iff, hc, isFiniteMeasure_iff] - -theorem hasFiniteIntegral_const [IsFiniteMeasure μ] (c : β) : - HasFiniteIntegral (fun _ : α => c) μ := - hasFiniteIntegral_const_iff.2 <| .inr ‹_› - -theorem HasFiniteIntegral.of_mem_Icc [IsFiniteMeasure μ] (a b : ℝ) {X : α → ℝ} - (h : ∀ᵐ ω ∂μ, X ω ∈ Set.Icc a b) : - HasFiniteIntegral X μ := by - apply (hasFiniteIntegral_const (max ‖a‖ ‖b‖)).mono' - filter_upwards [h.mono fun ω h ↦ h.1, h.mono fun ω h ↦ h.2] with ω using abs_le_max_abs_abs - -theorem hasFiniteIntegral_of_bounded [IsFiniteMeasure μ] {f : α → β} {C : ℝ} - (hC : ∀ᵐ a ∂μ, ‖f a‖ ≤ C) : HasFiniteIntegral f μ := - (hasFiniteIntegral_const C).mono' hC - -theorem HasFiniteIntegral.of_finite [Finite α] [IsFiniteMeasure μ] {f : α → β} : - HasFiniteIntegral f μ := - let ⟨_⟩ := nonempty_fintype α - hasFiniteIntegral_of_bounded <| ae_of_all μ <| norm_le_pi_norm f - -theorem HasFiniteIntegral.mono_measure {f : α → β} (h : HasFiniteIntegral f ν) (hμ : μ ≤ ν) : - HasFiniteIntegral f μ := - lt_of_le_of_lt (lintegral_mono' hμ le_rfl) h - -theorem HasFiniteIntegral.add_measure {f : α → β} (hμ : HasFiniteIntegral f μ) - (hν : HasFiniteIntegral f ν) : HasFiniteIntegral f (μ + ν) := by - simp only [HasFiniteIntegral, lintegral_add_measure] at * - exact add_lt_top.2 ⟨hμ, hν⟩ - -theorem HasFiniteIntegral.left_of_add_measure {f : α → β} (h : HasFiniteIntegral f (μ + ν)) : - HasFiniteIntegral f μ := - h.mono_measure <| Measure.le_add_right <| le_rfl - -theorem HasFiniteIntegral.right_of_add_measure {f : α → β} (h : HasFiniteIntegral f (μ + ν)) : - HasFiniteIntegral f ν := - h.mono_measure <| Measure.le_add_left <| le_rfl - -@[simp] -theorem hasFiniteIntegral_add_measure {f : α → β} : - HasFiniteIntegral f (μ + ν) ↔ HasFiniteIntegral f μ ∧ HasFiniteIntegral f ν := - ⟨fun h => ⟨h.left_of_add_measure, h.right_of_add_measure⟩, fun h => h.1.add_measure h.2⟩ - -theorem HasFiniteIntegral.smul_measure {f : α → β} (h : HasFiniteIntegral f μ) {c : ℝ≥0∞} - (hc : c ≠ ∞) : HasFiniteIntegral f (c • μ) := by - simp only [HasFiniteIntegral, lintegral_smul_measure] at * - exact mul_lt_top hc.lt_top h - -@[simp] -theorem hasFiniteIntegral_zero_measure {m : MeasurableSpace α} (f : α → β) : - HasFiniteIntegral f (0 : Measure α) := by - simp only [HasFiniteIntegral, lintegral_zero_measure, zero_lt_top] - -variable (α β μ) - -@[simp] -theorem hasFiniteIntegral_zero : HasFiniteIntegral (fun _ : α => (0 : β)) μ := by - simp [hasFiniteIntegral_iff_enorm] - -variable {α β μ} - -theorem HasFiniteIntegral.neg {f : α → β} (hfi : HasFiniteIntegral f μ) : - HasFiniteIntegral (-f) μ := by simpa [hasFiniteIntegral_iff_enorm] using hfi - -@[simp] -theorem hasFiniteIntegral_neg_iff {f : α → β} : HasFiniteIntegral (-f) μ ↔ HasFiniteIntegral f μ := - ⟨fun h => neg_neg f ▸ h.neg, HasFiniteIntegral.neg⟩ - -theorem HasFiniteIntegral.norm {f : α → β} (hfi : HasFiniteIntegral f μ) : - HasFiniteIntegral (fun a => ‖f a‖) μ := by simpa [hasFiniteIntegral_iff_enorm] using hfi - -theorem hasFiniteIntegral_norm_iff (f : α → β) : - HasFiniteIntegral (fun a => ‖f a‖) μ ↔ HasFiniteIntegral f μ := - hasFiniteIntegral_congr' <| Eventually.of_forall fun x => norm_norm (f x) - -theorem hasFiniteIntegral_toReal_of_lintegral_ne_top {f : α → ℝ≥0∞} (hf : ∫⁻ x, f x ∂μ ≠ ∞) : - HasFiniteIntegral (fun x ↦ (f x).toReal) μ := by - have h x : ‖(f x).toReal‖ₑ = .ofReal (f x).toReal := by - rw [Real.enorm_of_nonneg ENNReal.toReal_nonneg] - simp_rw [hasFiniteIntegral_iff_enorm, h] - refine lt_of_le_of_lt (lintegral_mono fun x => ?_) (lt_top_iff_ne_top.2 hf) - by_cases hfx : f x = ∞ - · simp [hfx] - · lift f x to ℝ≥0 using hfx with fx h - simp [← h, ← NNReal.coe_le_coe] - -lemma hasFiniteIntegral_toReal_iff {f : α → ℝ≥0∞} (hf : ∀ᵐ x ∂μ, f x ≠ ∞) : - HasFiniteIntegral (fun x ↦ (f x).toReal) μ ↔ ∫⁻ x, f x ∂μ ≠ ∞ := by - have : ∀ᵐ x ∂μ, .ofReal (f x).toReal = f x := by filter_upwards [hf] with x hx; simp [hx] - simp [hasFiniteIntegral_iff_enorm, Real.enorm_of_nonneg ENNReal.toReal_nonneg, - lintegral_congr_ae this, lt_top_iff_ne_top] - -theorem isFiniteMeasure_withDensity_ofReal {f : α → ℝ} (hfi : HasFiniteIntegral f μ) : - IsFiniteMeasure (μ.withDensity fun x => ENNReal.ofReal <| f x) := by - refine isFiniteMeasure_withDensity ((lintegral_mono fun x => ?_).trans_lt hfi).ne - exact Real.ofReal_le_enorm (f x) - -section DominatedConvergence - -variable {F : ℕ → α → β} {f : α → β} {bound : α → ℝ} - -theorem all_ae_ofReal_F_le_bound (h : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) : - ∀ n, ∀ᵐ a ∂μ, ENNReal.ofReal ‖F n a‖ ≤ ENNReal.ofReal (bound a) := fun n => - (h n).mono fun _ h => ENNReal.ofReal_le_ofReal h - -theorem all_ae_tendsto_ofReal_norm (h : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop <| 𝓝 <| f a) : - ∀ᵐ a ∂μ, Tendsto (fun n => ENNReal.ofReal ‖F n a‖) atTop <| 𝓝 <| ENNReal.ofReal ‖f a‖ := - h.mono fun _ h => tendsto_ofReal <| Tendsto.comp (Continuous.tendsto continuous_norm _) h - -theorem all_ae_ofReal_f_le_bound (h_bound : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) - (h_lim : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop (𝓝 (f a))) : - ∀ᵐ a ∂μ, ENNReal.ofReal ‖f a‖ ≤ ENNReal.ofReal (bound a) := by - have F_le_bound := all_ae_ofReal_F_le_bound h_bound - rw [← ae_all_iff] at F_le_bound - apply F_le_bound.mp ((all_ae_tendsto_ofReal_norm h_lim).mono _) - intro a tendsto_norm F_le_bound - exact le_of_tendsto' tendsto_norm F_le_bound - -theorem hasFiniteIntegral_of_dominated_convergence {F : ℕ → α → β} {f : α → β} {bound : α → ℝ} - (bound_hasFiniteIntegral : HasFiniteIntegral bound μ) - (h_bound : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) - (h_lim : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop (𝓝 (f a))) : HasFiniteIntegral f μ := by - /- `‖F n a‖ ≤ bound a` and `‖F n a‖ --> ‖f a‖` implies `‖f a‖ ≤ bound a`, - and so `∫ ‖f‖ ≤ ∫ bound < ∞` since `bound` is has_finite_integral -/ - rw [hasFiniteIntegral_iff_norm] - calc - (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) ≤ ∫⁻ a, ENNReal.ofReal (bound a) ∂μ := - lintegral_mono_ae <| all_ae_ofReal_f_le_bound h_bound h_lim - _ < ∞ := by - rw [← hasFiniteIntegral_iff_ofReal] - · exact bound_hasFiniteIntegral - exact (h_bound 0).mono fun a h => le_trans (norm_nonneg _) h - -theorem tendsto_lintegral_norm_of_dominated_convergence {F : ℕ → α → β} {f : α → β} {bound : α → ℝ} - (F_measurable : ∀ n, AEStronglyMeasurable (F n) μ) - (bound_hasFiniteIntegral : HasFiniteIntegral bound μ) - (h_bound : ∀ n, ∀ᵐ a ∂μ, ‖F n a‖ ≤ bound a) - (h_lim : ∀ᵐ a ∂μ, Tendsto (fun n => F n a) atTop (𝓝 (f a))) : - Tendsto (fun n => ∫⁻ a, ENNReal.ofReal ‖F n a - f a‖ ∂μ) atTop (𝓝 0) := by - have f_measurable : AEStronglyMeasurable f μ := - aestronglyMeasurable_of_tendsto_ae _ F_measurable h_lim - let b a := 2 * ENNReal.ofReal (bound a) - /- `‖F n a‖ ≤ bound a` and `F n a --> f a` implies `‖f a‖ ≤ bound a`, and thus by the - triangle inequality, have `‖F n a - f a‖ ≤ 2 * (bound a)`. -/ - have hb : ∀ n, ∀ᵐ a ∂μ, ENNReal.ofReal ‖F n a - f a‖ ≤ b a := by - intro n - filter_upwards [all_ae_ofReal_F_le_bound h_bound n, - all_ae_ofReal_f_le_bound h_bound h_lim] with a h₁ h₂ - calc - ENNReal.ofReal ‖F n a - f a‖ ≤ ENNReal.ofReal ‖F n a‖ + ENNReal.ofReal ‖f a‖ := by - rw [← ENNReal.ofReal_add] - · apply ofReal_le_ofReal - apply norm_sub_le - · exact norm_nonneg _ - · exact norm_nonneg _ - _ ≤ ENNReal.ofReal (bound a) + ENNReal.ofReal (bound a) := add_le_add h₁ h₂ - _ = b a := by rw [← two_mul] - -- On the other hand, `F n a --> f a` implies that `‖F n a - f a‖ --> 0` - have h : ∀ᵐ a ∂μ, Tendsto (fun n => ENNReal.ofReal ‖F n a - f a‖) atTop (𝓝 0) := by - rw [← ENNReal.ofReal_zero] - refine h_lim.mono fun a h => (continuous_ofReal.tendsto _).comp ?_ - rwa [← tendsto_iff_norm_sub_tendsto_zero] - /- Therefore, by the dominated convergence theorem for nonnegative integration, have - ` ∫ ‖f a - F n a‖ --> 0 ` -/ - suffices Tendsto (fun n => ∫⁻ a, ENNReal.ofReal ‖F n a - f a‖ ∂μ) atTop (𝓝 (∫⁻ _ : α, 0 ∂μ)) by - rwa [lintegral_zero] at this - -- Using the dominated convergence theorem. - refine tendsto_lintegral_of_dominated_convergence' _ ?_ hb ?_ ?_ - -- Show `fun a => ‖f a - F n a‖` is almost everywhere measurable for all `n` - · exact fun n => - measurable_ofReal.comp_aemeasurable ((F_measurable n).sub f_measurable).norm.aemeasurable - -- Show `2 * bound` `HasFiniteIntegral` - · rw [hasFiniteIntegral_iff_ofReal] at bound_hasFiniteIntegral - · calc - ∫⁻ a, b a ∂μ = 2 * ∫⁻ a, ENNReal.ofReal (bound a) ∂μ := by - rw [lintegral_const_mul'] - exact coe_ne_top - _ ≠ ∞ := mul_ne_top coe_ne_top bound_hasFiniteIntegral.ne - filter_upwards [h_bound 0] with _ h using le_trans (norm_nonneg _) h - -- Show `‖f a - F n a‖ --> 0` - · exact h - -end DominatedConvergence - -section PosPart - -/-! Lemmas used for defining the positive part of an `L¹` function -/ - - -theorem HasFiniteIntegral.max_zero {f : α → ℝ} (hf : HasFiniteIntegral f μ) : - HasFiniteIntegral (fun a => max (f a) 0) μ := - hf.mono <| Eventually.of_forall fun x => by simp [abs_le, le_abs_self] - -theorem HasFiniteIntegral.min_zero {f : α → ℝ} (hf : HasFiniteIntegral f μ) : - HasFiniteIntegral (fun a => min (f a) 0) μ := - hf.mono <| Eventually.of_forall fun x => by simpa [abs_le] using neg_abs_le _ - -end PosPart - -section NormedSpace - -variable {𝕜 : Type*} - -theorem HasFiniteIntegral.smul [NormedAddCommGroup 𝕜] [SMulZeroClass 𝕜 β] [BoundedSMul 𝕜 β] (c : 𝕜) - {f : α → β} : HasFiniteIntegral f μ → HasFiniteIntegral (c • f) μ := by - simp only [HasFiniteIntegral]; intro hfi - calc - ∫⁻ a : α, ‖c • f a‖ₑ ∂μ ≤ ∫⁻ a : α, ‖c‖ₑ * ‖f a‖ₑ ∂μ := lintegral_mono fun i ↦ enorm_smul_le - _ < ∞ := by - rw [lintegral_const_mul'] - exacts [mul_lt_top coe_lt_top hfi, coe_ne_top] - -theorem hasFiniteIntegral_smul_iff [NormedRing 𝕜] [MulActionWithZero 𝕜 β] [BoundedSMul 𝕜 β] {c : 𝕜} - (hc : IsUnit c) (f : α → β) : HasFiniteIntegral (c • f) μ ↔ HasFiniteIntegral f μ := by - obtain ⟨c, rfl⟩ := hc - constructor - · intro h - simpa only [smul_smul, Units.inv_mul, one_smul] using h.smul ((c⁻¹ : 𝕜ˣ) : 𝕜) - exact HasFiniteIntegral.smul _ - -theorem HasFiniteIntegral.const_mul [NormedRing 𝕜] {f : α → 𝕜} (h : HasFiniteIntegral f μ) (c : 𝕜) : - HasFiniteIntegral (fun x => c * f x) μ := - h.smul c - -theorem HasFiniteIntegral.mul_const [NormedRing 𝕜] {f : α → 𝕜} (h : HasFiniteIntegral f μ) (c : 𝕜) : - HasFiniteIntegral (fun x => f x * c) μ := - h.smul (MulOpposite.op c) - -end NormedSpace - /-! ### The predicate `Integrable` -/ variable [TopologicalSpace ε] @@ -932,12 +581,6 @@ section count variable [MeasurableSingletonClass α] {f : α → β} -/-- A function has finite integral for the counting measure iff its norm is summable. -/ -lemma hasFiniteIntegral_count_iff : - HasFiniteIntegral f Measure.count ↔ Summable (‖f ·‖) := by - simp only [hasFiniteIntegral_iff_enorm, enorm, lintegral_count, lt_top_iff_ne_top, - tsum_coe_ne_top_iff_summable, ← summable_coe, coe_nnnorm] - /-- A function is integrable for the counting measure iff its norm is summable. -/ lemma integrable_count_iff : Integrable f Measure.count ↔ Summable (‖f ·‖) := by @@ -1305,212 +948,10 @@ theorem integrable_of_forall_fin_meas_le [SigmaFinite μ] (C : ℝ≥0∞) (hC : end SigmaFinite -/-! ### The predicate `Integrable` on measurable functions modulo a.e.-equality -/ - - -namespace AEEqFun - -section - -/-- A class of almost everywhere equal functions is `Integrable` if its function representative -is integrable. -/ -def Integrable (f : α →ₘ[μ] β) : Prop := - MeasureTheory.Integrable f μ - -theorem integrable_mk {f : α → β} (hf : AEStronglyMeasurable f μ) : - Integrable (mk f hf : α →ₘ[μ] β) ↔ MeasureTheory.Integrable f μ := by - simp only [Integrable] - apply integrable_congr - exact coeFn_mk f hf - -theorem integrable_coeFn {f : α →ₘ[μ] β} : MeasureTheory.Integrable f μ ↔ Integrable f := by - rw [← integrable_mk, mk_coeFn] - -theorem integrable_zero : Integrable (0 : α →ₘ[μ] β) := - (MeasureTheory.integrable_zero α β μ).congr (coeFn_mk _ _).symm - -end - -section - -theorem Integrable.neg {f : α →ₘ[μ] β} : Integrable f → Integrable (-f) := - induction_on f fun _f hfm hfi => (integrable_mk _).2 ((integrable_mk hfm).1 hfi).neg - -section - -theorem integrable_iff_mem_L1 {f : α →ₘ[μ] β} : Integrable f ↔ f ∈ (α →₁[μ] β) := by - rw [← integrable_coeFn, ← memℒp_one_iff_integrable, Lp.mem_Lp_iff_memℒp] - -theorem Integrable.add {f g : α →ₘ[μ] β} : Integrable f → Integrable g → Integrable (f + g) := by - refine induction_on₂ f g fun f hf g hg hfi hgi => ?_ - simp only [integrable_mk, mk_add_mk] at hfi hgi ⊢ - exact hfi.add hgi - -theorem Integrable.sub {f g : α →ₘ[μ] β} (hf : Integrable f) (hg : Integrable g) : - Integrable (f - g) := - (sub_eq_add_neg f g).symm ▸ hf.add hg.neg - -end - -section BoundedSMul - -variable {𝕜 : Type*} [NormedRing 𝕜] [Module 𝕜 β] [BoundedSMul 𝕜 β] - -theorem Integrable.smul {c : 𝕜} {f : α →ₘ[μ] β} : Integrable f → Integrable (c • f) := - induction_on f fun _f hfm hfi => (integrable_mk _).2 <| - by simpa using ((integrable_mk hfm).1 hfi).smul c - -end BoundedSMul - -end - -end AEEqFun - -namespace L1 - - -theorem integrable_coeFn (f : α →₁[μ] β) : Integrable f μ := by - rw [← memℒp_one_iff_integrable] - exact Lp.memℒp f - -theorem hasFiniteIntegral_coeFn (f : α →₁[μ] β) : HasFiniteIntegral f μ := - (integrable_coeFn f).hasFiniteIntegral - -theorem stronglyMeasurable_coeFn (f : α →₁[μ] β) : StronglyMeasurable f := - Lp.stronglyMeasurable f - -theorem measurable_coeFn [MeasurableSpace β] [BorelSpace β] (f : α →₁[μ] β) : Measurable f := - (Lp.stronglyMeasurable f).measurable - -theorem aestronglyMeasurable_coeFn (f : α →₁[μ] β) : AEStronglyMeasurable f μ := - Lp.aestronglyMeasurable f - -theorem aemeasurable_coeFn [MeasurableSpace β] [BorelSpace β] (f : α →₁[μ] β) : AEMeasurable f μ := - (Lp.stronglyMeasurable f).measurable.aemeasurable - -theorem edist_def (f g : α →₁[μ] β) : edist f g = ∫⁻ a, edist (f a) (g a) ∂μ := by - simp only [Lp.edist_def, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_enorm, Pi.sub_apply, - one_toReal, ENNReal.rpow_one, ne_eq, not_false_eq_true, div_self, ite_false] - simp [edist_eq_enorm_sub] - -theorem dist_def (f g : α →₁[μ] β) : dist f g = (∫⁻ a, edist (f a) (g a) ∂μ).toReal := by - simp_rw [dist_edist, edist_def] - -theorem norm_def (f : α →₁[μ] β) : ‖f‖ = (∫⁻ a, ‖f a‖ₑ ∂μ).toReal := by - simp [Lp.norm_def, eLpNorm, eLpNorm'_eq_lintegral_enorm] - -/-- Computing the norm of a difference between two L¹-functions. Note that this is not a - special case of `norm_def` since `(f - g) x` and `f x - g x` are not equal - (but only a.e.-equal). -/ -theorem norm_sub_eq_lintegral (f g : α →₁[μ] β) : ‖f - g‖ = (∫⁻ x, ‖f x - g x‖ₑ ∂μ).toReal := by - rw [norm_def] - congr 1 - rw [lintegral_congr_ae] - filter_upwards [Lp.coeFn_sub f g] with _ ha - simp only [ha, Pi.sub_apply] - -theorem ofReal_norm_eq_lintegral (f : α →₁[μ] β) : ENNReal.ofReal ‖f‖ = ∫⁻ x, ‖f x‖ₑ ∂μ := by - rw [norm_def, ENNReal.ofReal_toReal] - exact ne_of_lt (hasFiniteIntegral_coeFn f) - -/-- Computing the norm of a difference between two L¹-functions. Note that this is not a - special case of `ofReal_norm_eq_lintegral` since `(f - g) x` and `f x - g x` are not equal - (but only a.e.-equal). -/ -theorem ofReal_norm_sub_eq_lintegral (f g : α →₁[μ] β) : - ENNReal.ofReal ‖f - g‖ = ∫⁻ x, ‖f x - g x‖ₑ ∂μ := by - simp_rw [ofReal_norm_eq_lintegral, ← edist_zero_eq_enorm] - apply lintegral_congr_ae - filter_upwards [Lp.coeFn_sub f g] with _ ha - simp only [ha, Pi.sub_apply] - -end L1 - -namespace Integrable - - -/-- Construct the equivalence class `[f]` of an integrable function `f`, as a member of the -space `L1 β 1 μ`. -/ -def toL1 (f : α → β) (hf : Integrable f μ) : α →₁[μ] β := - (memℒp_one_iff_integrable.2 hf).toLp f - -@[simp] -theorem toL1_coeFn (f : α →₁[μ] β) (hf : Integrable f μ) : hf.toL1 f = f := by - simp [Integrable.toL1] - -theorem coeFn_toL1 {f : α → β} (hf : Integrable f μ) : hf.toL1 f =ᵐ[μ] f := - AEEqFun.coeFn_mk _ _ - -@[simp] -theorem toL1_zero (h : Integrable (0 : α → β) μ) : h.toL1 0 = 0 := - rfl - -@[simp] -theorem toL1_eq_mk (f : α → β) (hf : Integrable f μ) : - (hf.toL1 f : α →ₘ[μ] β) = AEEqFun.mk f hf.aestronglyMeasurable := - rfl - -@[simp] -theorem toL1_eq_toL1_iff (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : - toL1 f hf = toL1 g hg ↔ f =ᵐ[μ] g := - Memℒp.toLp_eq_toLp_iff _ _ - -theorem toL1_add (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : - toL1 (f + g) (hf.add hg) = toL1 f hf + toL1 g hg := - rfl - -theorem toL1_neg (f : α → β) (hf : Integrable f μ) : toL1 (-f) (Integrable.neg hf) = -toL1 f hf := - rfl - -theorem toL1_sub (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : - toL1 (f - g) (hf.sub hg) = toL1 f hf - toL1 g hg := - rfl - -theorem norm_toL1 (f : α → β) (hf : Integrable f μ) : - ‖hf.toL1 f‖ = (∫⁻ a, edist (f a) 0 ∂μ).toReal := by - simp [toL1, Lp.norm_toLp, eLpNorm, eLpNorm'_eq_lintegral_enorm] - -theorem enorm_toL1 {f : α → β} (hf : Integrable f μ) : ‖hf.toL1 f‖ₑ = ∫⁻ a, ‖f a‖ₑ ∂μ := by - simpa [Integrable.toL1, eLpNorm, eLpNorm', enorm] using ENNReal.coe_toNNReal hf.2.ne - -@[deprecated (since := "2025-01-20")] alias nnnorm_toL1 := enorm_toL1 - -theorem norm_toL1_eq_lintegral_norm (f : α → β) (hf : Integrable f μ) : - ‖hf.toL1 f‖ = ENNReal.toReal (∫⁻ a, ENNReal.ofReal ‖f a‖ ∂μ) := by - rw [norm_toL1, lintegral_norm_eq_lintegral_edist] - -@[simp] -theorem edist_toL1_toL1 (f g : α → β) (hf : Integrable f μ) (hg : Integrable g μ) : - edist (hf.toL1 f) (hg.toL1 g) = ∫⁻ a, edist (f a) (g a) ∂μ := by - simp only [toL1, Lp.edist_toLp_toLp, eLpNorm, one_ne_zero, eLpNorm'_eq_lintegral_enorm, - Pi.sub_apply, one_toReal, ENNReal.rpow_one, ne_eq, not_false_eq_true, div_self, ite_false] - simp [edist_eq_enorm_sub] - -theorem edist_toL1_zero (f : α → β) (hf : Integrable f μ) : - edist (hf.toL1 f) 0 = ∫⁻ a, edist (f a) 0 ∂μ := by - simp only [edist_zero_right, Lp.enorm_def, toL1_eq_mk, eLpNorm_aeeqFun] - apply eLpNorm_one_eq_lintegral_enorm - -variable {𝕜 : Type*} [NormedRing 𝕜] [Module 𝕜 β] [BoundedSMul 𝕜 β] - -theorem toL1_smul (f : α → β) (hf : Integrable f μ) (k : 𝕜) : - toL1 (fun a => k • f a) (hf.smul k) = k • toL1 f hf := - rfl - -theorem toL1_smul' (f : α → β) (hf : Integrable f μ) (k : 𝕜) : - toL1 (k • f) (hf.smul k) = k • toL1 f hf := - rfl - -end Integrable - section restrict variable {E : Type*} [NormedAddCommGroup E] {f : α → E} -lemma HasFiniteIntegral.restrict (h : HasFiniteIntegral f μ) {s : Set α} : - HasFiniteIntegral f (μ.restrict s) := by - refine lt_of_le_of_lt ?_ h - simpa [Measure.restrict_univ] using lintegral_mono_set (subset_univ s) - /-- One should usually use `MeasureTheory.Integrable.IntegrableOn` instead. -/ lemma Integrable.restrict (hf : Integrable f μ) {s : Set α} : Integrable f (μ.restrict s) := hf.mono_measure Measure.restrict_le_self @@ -1568,5 +1009,3 @@ lemma integrable_prod {f : α → E × F} : ⟨fun h ↦ ⟨h.fst, h.snd⟩, fun h ↦ h.1.prod_mk h.2⟩ end MeasureTheory - -set_option linter.style.longFile 1700 diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index 99112b7f98878..a7d019b6e5ebe 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Zhouhang Zhou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Zhouhang Zhou, Yury Kudryashov, Heather Macbeth -/ -import Mathlib.MeasureTheory.Function.L1Space +import Mathlib.MeasureTheory.Function.L1Space.AEEqFun import Mathlib.MeasureTheory.Function.SimpleFuncDense /-! diff --git a/Mathlib/MeasureTheory/Function/UnifTight.lean b/Mathlib/MeasureTheory/Function/UnifTight.lean index 6c36077b3a716..1b98552847b15 100644 --- a/Mathlib/MeasureTheory/Function/UnifTight.lean +++ b/Mathlib/MeasureTheory/Function/UnifTight.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Igor Khavkine -/ import Mathlib.MeasureTheory.Function.ConvergenceInMeasure -import Mathlib.MeasureTheory.Function.L1Space import Mathlib.MeasureTheory.Function.UniformIntegrable /-! diff --git a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean index e8f2bc92787aa..8ba93267f9ee7 100644 --- a/Mathlib/MeasureTheory/Function/UniformIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/UniformIntegrable.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kexing Ying -/ import Mathlib.MeasureTheory.Function.ConvergenceInMeasure -import Mathlib.MeasureTheory.Function.L1Space +import Mathlib.MeasureTheory.Function.L1Space.Integrable /-! # Uniform integrability diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index e46bfe3e48acd..d5c7a91ba8e6a 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Rémy Degenne. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Zhouhang Zhou, Yury Kudryashov -/ -import Mathlib.MeasureTheory.Function.L1Space +import Mathlib.MeasureTheory.Function.L1Space.Integrable import Mathlib.Analysis.NormedSpace.IndicatorFunction /-! # Functions integrable on a set and at a filter diff --git a/Mathlib/Probability/Independence/Integrable.lean b/Mathlib/Probability/Independence/Integrable.lean index c33b372d816a2..0d06f7f91d98f 100644 --- a/Mathlib/Probability/Independence/Integrable.lean +++ b/Mathlib/Probability/Independence/Integrable.lean @@ -3,7 +3,7 @@ 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.MeasureTheory.Function.L1Space.Integrable import Mathlib.Probability.Independence.Basic /-! diff --git a/Mathlib/Probability/Moments/IntegrableExpMul.lean b/Mathlib/Probability/Moments/IntegrableExpMul.lean index 2670a7c181b61..74d8ee95ca940 100644 --- a/Mathlib/Probability/Moments/IntegrableExpMul.lean +++ b/Mathlib/Probability/Moments/IntegrableExpMul.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 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.Function.L1Space +import Mathlib.MeasureTheory.Function.L1Space.Integrable import Mathlib.MeasureTheory.Order.Group.Lattice /-! From b7ce26aaad6985218edd7cc8caa517846e25be1f Mon Sep 17 00:00:00 2001 From: kvanvels Date: Wed, 29 Jan 2025 18:25:29 +0000 Subject: [PATCH 644/681] chore: replace `open scoped Classical`with `open scoped Classical in` or `classical` in a tactic proof (#21228) reduces some technical debt by replacing `open scoped classical` with `open scoped classical in` or adding a `classical tactic` to a tactic proof. Used explicit `Classical.arbitrary` in two spots in Mathlib/Order/DirectedInverseSystem.lean --- Mathlib/Analysis/SpecialFunctions/Log/Summable.lean | 2 +- Mathlib/MeasureTheory/Constructions/Pi.lean | 5 ++++- .../Function/ConditionalExpectation/Basic.lean | 5 ++++- Mathlib/Order/DirectedInverseSystem.lean | 6 ++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean b/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean index 3c1969101ea96..0bb757f1e28ba 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Summable.lean @@ -22,7 +22,7 @@ products. open Filter Function Complex Real -open scoped Interval Topology BigOperators Nat Classical Complex +open scoped Interval Topology BigOperators Nat Complex variable {ι : Type*} diff --git a/Mathlib/MeasureTheory/Constructions/Pi.lean b/Mathlib/MeasureTheory/Constructions/Pi.lean index d2ad209b30457..e81c5ea04ae2f 100644 --- a/Mathlib/MeasureTheory/Constructions/Pi.lean +++ b/Mathlib/MeasureTheory/Constructions/Pi.lean @@ -54,7 +54,7 @@ noncomputable section open Function Set MeasureTheory.OuterMeasure Filter MeasurableSpace Encodable -open scoped Classical Topology ENNReal +open scoped Topology ENNReal universe u v @@ -168,6 +168,7 @@ open List MeasurableEquiv variable [Encodable ι] +open scoped Classical in /-- The product measure on an encodable finite type, defined by mapping `Measure.tprod` along the equivalence `MeasurableEquiv.piMeasurableEquivTProd`. The definition `MeasureTheory.Measure.pi` should be used instead of this one. -/ @@ -176,6 +177,7 @@ def pi' : Measure (∀ i, α i) := theorem pi'_pi [∀ i, SigmaFinite (μ i)] (s : ∀ i, Set (α i)) : pi' μ (pi univ s) = ∏ i, μ i (s i) := by + classical rw [pi'] rw [← MeasurableEquiv.piMeasurableEquivTProd_symm_apply, MeasurableEquiv.map_apply, MeasurableEquiv.piMeasurableEquivTProd_symm_apply, elim_preimage_pi, tprod_tprod _ μ, ← @@ -342,6 +344,7 @@ theorem pi_empty_univ {α : Type*} [Fintype α] [IsEmpty α] {β : α → Type*} theorem pi_eval_preimage_null {i : ι} {s : Set (α i)} (hs : μ i s = 0) : Measure.pi μ (eval i ⁻¹' s) = 0 := by + classical -- WLOG, `s` is measurable rcases exists_measurable_superset_of_null hs with ⟨t, hst, _, hμt⟩ suffices Measure.pi μ (eval i ⁻¹' t) = 0 from measure_mono_null (preimage_mono hst) this diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index e5fb77b18b62e..98df7b831fb53 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -69,7 +69,7 @@ conditional expectation, conditional expected value -/ open TopologicalSpace MeasureTheory.Lp Filter -open scoped Classical ENNReal Topology MeasureTheory +open scoped ENNReal Topology MeasureTheory namespace MeasureTheory -- 𝕜 for ℝ or ℂ @@ -80,6 +80,7 @@ variable {α β E 𝕜 : Type*} [RCLike 𝕜] {m m₀ : MeasurableSpace α} {μ section NormedAddCommGroup variable [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] +open scoped Classical in variable (m) in /-- Conditional expectation of a function. It is defined as 0 if any one of the following conditions is true: @@ -108,6 +109,7 @@ theorem condExp_of_not_sigmaFinite (hm : m ≤ m₀) (hμm_not : ¬SigmaFinite ( @[deprecated (since := "2025-01-21")] alias condexp_of_not_sigmaFinite := condExp_of_not_sigmaFinite +open scoped Classical in theorem condExp_of_sigmaFinite (hm : m ≤ m₀) [hμm : SigmaFinite (μ.trim hm)] : μ[f|m] = if Integrable f μ then @@ -320,6 +322,7 @@ theorem condExp_add (hf : Integrable f μ) (hg : Integrable g μ) (m : Measurabl theorem condExp_finset_sum {ι : Type*} {s : Finset ι} {f : ι → α → E} (hf : ∀ i ∈ s, Integrable (f i) μ) (m : MeasurableSpace α) : μ[∑ i ∈ s, f i|m] =ᵐ[μ] ∑ i ∈ s, μ[f i|m] := by + classical induction' s using Finset.induction_on with i s his heq hf · rw [Finset.sum_empty, Finset.sum_empty, condExp_zero] · rw [Finset.sum_insert his, Finset.sum_insert his] diff --git a/Mathlib/Order/DirectedInverseSystem.lean b/Mathlib/Order/DirectedInverseSystem.lean index 943b33a61c228..fe714d8d38863 100644 --- a/Mathlib/Order/DirectedInverseSystem.lean +++ b/Mathlib/Order/DirectedInverseSystem.lean @@ -144,15 +144,13 @@ theorem mk_injective (h : ∀ i j hij, Function.Injective (f i j hij)) (i) : section map₀ -open Classical (arbitrary) - variable [Nonempty ι] (ih : ∀ i, F i) /-- "Nullary map" to construct an element in the direct limit. -/ -noncomputable def map₀ : DirectLimit F f := ⟦⟨arbitrary ι, ih _⟩⟧ +noncomputable def map₀ : DirectLimit F f := ⟦⟨Classical.arbitrary ι, ih _⟩⟧ theorem map₀_def (compat : ∀ i j h, f i j h (ih i) = ih j) (i) : map₀ f ih = ⟦⟨i, ih i⟩⟧ := - have ⟨j, hcj, hij⟩ := exists_ge_ge (arbitrary ι) i + have ⟨j, hcj, hij⟩ := exists_ge_ge (Classical.arbitrary ι) i Quotient.sound ⟨j, hcj, hij, (compat ..).trans (compat ..).symm⟩ end map₀ From ec45ea12b4eaaab1c0fc1442f4778f2f27ac3960 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Wed, 29 Jan 2025 19:02:02 +0000 Subject: [PATCH 645/681] chore: remove some adaptation notes about unused variable linter (#21212) --- Mathlib/Algebra/GroupWithZero/Hom.lean | 7 ------- Mathlib/Algebra/Polynomial/RingDivision.lean | 5 ----- .../AlgebraicTopology/SimplicialSet/Boundary.lean | 7 ------- Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean | 7 ------- Mathlib/Analysis/SpecialFunctions/Pow/Real.lean | 8 -------- .../CategoryTheory/Adjunction/Lifting/Left.lean | 7 ------- Mathlib/CategoryTheory/Monad/Monadicity.lean | 7 ------- Mathlib/Data/Nat/Log.lean | 8 -------- Mathlib/Tactic/NormNum/Basic.lean | 8 -------- Mathlib/Tactic/NormNum/DivMod.lean | 8 -------- Mathlib/Tactic/NormNum/Eq.lean | 8 -------- Mathlib/Tactic/NormNum/GCD.lean | 8 -------- Mathlib/Tactic/NormNum/Ineq.lean | 8 -------- Mathlib/Tactic/NormNum/Inv.lean | 8 -------- Mathlib/Tactic/NormNum/LegendreSymbol.lean | 8 -------- Mathlib/Tactic/NormNum/Pow.lean | 8 -------- Mathlib/Topology/SeparatedMap.lean | 14 -------------- 17 files changed, 134 deletions(-) diff --git a/Mathlib/Algebra/GroupWithZero/Hom.lean b/Mathlib/Algebra/GroupWithZero/Hom.lean index f30ace0a86cbc..5f4976f69371a 100644 --- a/Mathlib/Algebra/GroupWithZero/Hom.lean +++ b/Mathlib/Algebra/GroupWithZero/Hom.lean @@ -40,13 +40,6 @@ open Function namespace NeZero variable {F α β : Type*} [Zero α] [Zero β] [FunLike F α β] [ZeroHomClass F α β] {a : α} -#adaptation_note -/-- -We name `neZero` so it can be used as a named argument, -but since https://github.com/leanprover/lean4/pull/5338, this is considered unused, -so we need to disable the linter. --/ -set_option linter.unusedVariables false in lemma of_map (f : F) [neZero : NeZero (f a)] : NeZero a := ⟨fun h ↦ ne (f a) <| by rw [h]; exact ZeroHomClass.map_zero f⟩ diff --git a/Mathlib/Algebra/Polynomial/RingDivision.lean b/Mathlib/Algebra/Polynomial/RingDivision.lean index 918724e6d9f4d..9be07ffaeff4d 100644 --- a/Mathlib/Algebra/Polynomial/RingDivision.lean +++ b/Mathlib/Algebra/Polynomial/RingDivision.lean @@ -244,11 +244,6 @@ theorem exists_multiset_roots [DecidableEq R] : have hpd : 0 < degree p := degree_pos_of_root hp hx have hd0 : p /ₘ (X - C x) ≠ 0 := fun h => by rw [← mul_divByMonic_eq_iff_isRoot.2 hx, h, mul_zero] at hp; exact hp rfl - #adaptation_note - /-- - Since https://github.com/leanprover/lean4/pull/5338, this is considered unused, - because it is only used in the decreasing_by clause. - -/ have wf : degree (p /ₘ (X - C x)) < degree p := degree_divByMonic_lt _ (monic_X_sub_C x) hp ((degree_X_sub_C x).symm ▸ by decide) let ⟨t, htd, htr⟩ := @exists_multiset_roots _ (p /ₘ (X - C x)) hd0 diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean index 58805409d1ceb..e9f81272b8ff2 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Boundary.lean @@ -41,13 +41,6 @@ def boundary (n : ℕ) : SSet.{u} where /-- The boundary `∂Δ[n]` of the `n`-th standard simplex -/ scoped[Simplicial] notation3 "∂Δ[" n "]" => SSet.boundary n -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{ α : Δ[n].obj m // _ }`. --/ -set_option linter.unusedVariables false in /-- The inclusion of the boundary of the `n`-th standard simplex into that standard simplex. -/ def boundaryInclusion (n : ℕ) : ∂Δ[n] ⟶ Δ[n] where app m (α : { α : Δ[n].obj m // _ }) := α diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean index ef8c001fd1d79..6eb839414c759 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Horn.lean @@ -35,13 +35,6 @@ def horn (n : ℕ) (i : Fin (n + 1)) : SSet where /-- The `i`-th horn `Λ[n, i]` of the standard `n`-simplex -/ scoped[Simplicial] notation3 "Λ[" n ", " i "]" => SSet.horn (n : ℕ) i -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{ α : Δ[n].obj m // _ }`. --/ -set_option linter.unusedVariables false in /-- The inclusion of the `i`-th horn of the `n`-th standard simplex into that standard simplex. -/ def hornInclusion (n : ℕ) (i : Fin (n + 1)) : Λ[n, i] ⟶ Δ[n] where app m (α : { α : Δ[n].obj m // _ }) := α diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index fabc68692ced8..0a8b78fdc039e 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -1103,14 +1103,6 @@ theorem isRat_rpow_neg {a b : ℝ} {nb : ℕ} IsRat (a ^ b) num den := by rwa [pb.out, Real.rpow_intCast] -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - /-- Evaluates expressions of the form `a ^ b` when `a` and `b` are both reals. -/ @[norm_num (_ : ℝ) ^ (_ : ℝ)] def evalRPow : NormNumExt where eval {u α} e := do diff --git a/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean b/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean index 432970c912ce8..508de191a1af9 100644 --- a/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean +++ b/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean @@ -122,13 +122,6 @@ variable [HasReflexiveCoequalizers A] noncomputable def constructLeftAdjointObj (Y : B) : A := coequalizer (F'.map (U.map (adj₁.counit.app Y))) (otherMap _ _ adj₁ adj₂ Y) -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{ z : F.obj (U.obj X) ⟶ R.obj Y // _ }`. --/ -set_option linter.unusedVariables false in /-- The homset equivalence which helps show that `R` is a right adjoint. -/ @[simps!] noncomputable def constructLeftAdjointEquiv [∀ X : B, RegularEpi (adj₁.counit.app X)] (Y : A) diff --git a/Mathlib/CategoryTheory/Monad/Monadicity.lean b/Mathlib/CategoryTheory/Monad/Monadicity.lean index 8947ae28924ea..b18ae5ed47930 100644 --- a/Mathlib/CategoryTheory/Monad/Monadicity.lean +++ b/Mathlib/CategoryTheory/Monad/Monadicity.lean @@ -79,13 +79,6 @@ def comparisonLeftAdjointObj (A : adj.toMonad.Algebra) [HasCoequalizer (F.map A.a) (adj.counit.app _)] : D := coequalizer (F.map A.a) (adj.counit.app _) -#adaptation_note -/-- -The new unused variable linter in -https://github.com/leanprover/lean4/pull/5338 -flags `{ f : F.obj A.A ⟶ B // _ }`. --/ -set_option linter.unusedVariables false in /-- We have a bijection of homsets which will be used to construct the left adjoint to the comparison functor. diff --git a/Mathlib/Data/Nat/Log.lean b/Mathlib/Data/Nat/Log.lean index 2d4196b2fe33a..f576bc2d52e16 100644 --- a/Mathlib/Data/Nat/Log.lean +++ b/Mathlib/Data/Nat/Log.lean @@ -24,14 +24,6 @@ assert_not_exists OrderTop namespace Nat -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/5338 we just unused argument warnings, -but these are used in the decreasing by blocks. -If instead we inline the `have` blocks, the unusedHavesSuffices linter triggers. --/ -set_option linter.unusedVariables false - /-! ### Floor logarithm -/ diff --git a/Mathlib/Tactic/NormNum/Basic.lean b/Mathlib/Tactic/NormNum/Basic.lean index a1d9e39f9a55b..91ce6bebb6980 100644 --- a/Mathlib/Tactic/NormNum/Basic.lean +++ b/Mathlib/Tactic/NormNum/Basic.lean @@ -25,14 +25,6 @@ See other files in this directory for many more plugins. universe u -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - namespace Mathlib open Lean open Meta diff --git a/Mathlib/Tactic/NormNum/DivMod.lean b/Mathlib/Tactic/NormNum/DivMod.lean index 90f6938e16c6b..c07a80e7e9788 100644 --- a/Mathlib/Tactic/NormNum/DivMod.lean +++ b/Mathlib/Tactic/NormNum/DivMod.lean @@ -13,14 +13,6 @@ This file adds support for the `%`, `/`, and `∣` (divisibility) operators on ` to the `norm_num` tactic. -/ -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - namespace Mathlib open Lean open Meta diff --git a/Mathlib/Tactic/NormNum/Eq.lean b/Mathlib/Tactic/NormNum/Eq.lean index d467ab0571729..277f0479a4a02 100644 --- a/Mathlib/Tactic/NormNum/Eq.lean +++ b/Mathlib/Tactic/NormNum/Eq.lean @@ -11,14 +11,6 @@ import Mathlib.Tactic.NormNum.Inv variable {α : Type*} -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - open Lean Meta Qq namespace Mathlib.Meta.NormNum diff --git a/Mathlib/Tactic/NormNum/GCD.lean b/Mathlib/Tactic/NormNum/GCD.lean index c9bcc4f4c2c98..cb0a2aa2d169a 100644 --- a/Mathlib/Tactic/NormNum/GCD.lean +++ b/Mathlib/Tactic/NormNum/GCD.lean @@ -16,14 +16,6 @@ Note that `Nat.coprime` is reducible and defined in terms of `Nat.gcd`, so the ` also indirectly provides a `Nat.coprime` extension. -/ -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - namespace Tactic namespace NormNum diff --git a/Mathlib/Tactic/NormNum/Ineq.lean b/Mathlib/Tactic/NormNum/Ineq.lean index 44013a8b76ced..0c27395a582be 100644 --- a/Mathlib/Tactic/NormNum/Ineq.lean +++ b/Mathlib/Tactic/NormNum/Ineq.lean @@ -13,14 +13,6 @@ import Mathlib.Algebra.Order.Ring.Cast # `norm_num` extensions for inequalities. -/ -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - open Lean Meta Qq namespace Mathlib.Meta.NormNum diff --git a/Mathlib/Tactic/NormNum/Inv.lean b/Mathlib/Tactic/NormNum/Inv.lean index c722b8cf4c587..82c34adb85e5a 100644 --- a/Mathlib/Tactic/NormNum/Inv.lean +++ b/Mathlib/Tactic/NormNum/Inv.lean @@ -13,14 +13,6 @@ import Mathlib.Algebra.Field.Basic variable {u : Lean.Level} -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - namespace Mathlib.Meta.NormNum open Lean.Meta Qq diff --git a/Mathlib/Tactic/NormNum/LegendreSymbol.lean b/Mathlib/Tactic/NormNum/LegendreSymbol.lean index 166fc060cfcdc..dfb3def6ba7c4 100644 --- a/Mathlib/Tactic/NormNum/LegendreSymbol.lean +++ b/Mathlib/Tactic/NormNum/LegendreSymbol.lean @@ -356,14 +356,6 @@ namespace NormNum open Lean Elab Tactic Qq Mathlib.Meta.NormNum -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - /-- This is the `norm_num` plug-in that evaluates Jacobi symbols. -/ @[norm_num jacobiSym _ _] def evalJacobiSym : NormNumExt where eval {u α} e := do diff --git a/Mathlib/Tactic/NormNum/Pow.lean b/Mathlib/Tactic/NormNum/Pow.lean index e5c8e7cd6b332..72ced934fd53d 100644 --- a/Mathlib/Tactic/NormNum/Pow.lean +++ b/Mathlib/Tactic/NormNum/Pow.lean @@ -10,14 +10,6 @@ import Mathlib.Tactic.NormNum.Basic ## `norm_num` plugin for `^`. -/ -#adaptation_note -/-- -Since https://github.com/leanprover/lean4/pull/5338, -the unused variable linter can not see usages of variables in -`haveI' : ⋯ =Q ⋯ := ⟨⟩` clauses, so generates many false positives. --/ -set_option linter.unusedVariables false - namespace Mathlib open Lean open Meta diff --git a/Mathlib/Topology/SeparatedMap.lean b/Mathlib/Topology/SeparatedMap.lean index 61b7da0770428..5773590ffc317 100644 --- a/Mathlib/Topology/SeparatedMap.lean +++ b/Mathlib/Topology/SeparatedMap.lean @@ -183,25 +183,11 @@ section eqLocus variable {f : X → Y} {g₁ g₂ : A → X} (h₁ : Continuous g₁) (h₂ : Continuous g₂) include h₁ h₂ -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/5338, -the unused variable linter flags `g` here, -but it is used in a type ascription to direct `fun_prop`. --/ -set_option linter.unusedVariables false in theorem IsSeparatedMap.isClosed_eqLocus (sep : IsSeparatedMap f) (he : f ∘ g₁ = f ∘ g₂) : IsClosed {a | g₁ a = g₂ a} := let g : A → f.Pullback f := fun a ↦ ⟨⟨g₁ a, g₂ a⟩, congr_fun he a⟩ (isSeparatedMap_iff_isClosed_diagonal.mp sep).preimage (by fun_prop : Continuous g) -#adaptation_note -/-- -After https://github.com/leanprover/lean4/pull/5338, -the unused variable linter flags `g` here, -but it is used in a type ascription to direct `fun_prop`. --/ -set_option linter.unusedVariables false in theorem IsLocallyInjective.isOpen_eqLocus (inj : IsLocallyInjective f) (he : f ∘ g₁ = f ∘ g₂) : IsOpen {a | g₁ a = g₂ a} := let g : A → f.Pullback f := fun a ↦ ⟨⟨g₁ a, g₂ a⟩, congr_fun he a⟩ From 87eb9968ee15f7acd4b141cc385450a11a4710e6 Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Wed, 29 Jan 2025 19:39:44 +0000 Subject: [PATCH 646/681] chore(scripts/technical-debt-metrics.sh): fix counters, so that 0 is 0 (#21221) --- Mathlib/Tactic/Linter/TextBased.lean | 4 ++-- scripts/technical-debt-metrics.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Mathlib/Tactic/Linter/TextBased.lean b/Mathlib/Tactic/Linter/TextBased.lean index c0df2b14e30da..5786f3360de33 100644 --- a/Mathlib/Tactic/Linter/TextBased.lean +++ b/Mathlib/Tactic/Linter/TextBased.lean @@ -51,8 +51,8 @@ deriving BEq /-- Possible errors that text-based linters can report. -/ -- We collect these in one inductive type to centralise error reporting. inductive StyleError where - /-- The bare string "Adaptation note" (or variants thereof): instead, the - #adaptation_note command should be used. -/ + /-- The bare string "Adaptation note" (or variants thereof): + instead, the #adaptation_note command should be used. -/ | adaptationNote /-- A line ends with windows line endings (\r\n) instead of unix ones (\n). -/ | windowsLineEnding diff --git a/scripts/technical-debt-metrics.sh b/scripts/technical-debt-metrics.sh index efe28e4c7e85d..cb037e7bf8b23 100755 --- a/scripts/technical-debt-metrics.sh +++ b/scripts/technical-debt-metrics.sh @@ -77,7 +77,7 @@ titlesPathsAndRegexes=( "porting notes" "*" "Porting note" "backwards compatibility flags" "*" "set_option.*backward" "skipAssignedInstances flags" "*" "set_option tactic.skipAssignedInstances" - "adaptation notes" "*" "adaptation_note" + "adaptation notes" ":^Mathlib/Tactic/AdaptationNote.lean" "^[· ]*#adaptation_note" "disabled simpNF lints" "*" "nolint simpNF" "erw" "*" "erw \[" "maxHeartBeats modifications" ":^MathlibTest" "^ *set_option .*maxHeartbeats" @@ -93,7 +93,7 @@ for i in ${!titlesPathsAndRegexes[@]}; do then fl="-i" # just for porting notes we ignore the case in the regex else fl="--" fi - printf '%s|%s\n' "$(git grep "${fl}" "${regex}" -- "${pathspec}" | wc -l)" "${title}" + printf '%s|%s\n' "$(git grep "${fl}" "${regex}" -- ":^scripts" "${pathspec}" | wc -l)" "${title}" fi done From feedd829ebf167d5585f91fbb6a777f83ea4b8f8 Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot <150093616+mathlib-bors@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:56:36 +0000 Subject: [PATCH 647/681] chore: update Mathlib dependencies 2025-01-29 (#21236) 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 7373536114b5d..d25a63116d4b6 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "383137545783429af1317226778fd44869a711e2", + "rev": "61dd72099e98719d33239933316e12894677a843", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From 2b40940d6b55bca03583a899ea8dd4df6fca3f75 Mon Sep 17 00:00:00 2001 From: John Talbot Date: Wed, 29 Jan 2025 21:01:32 +0000 Subject: [PATCH 648/681] feat(SimpleGraph/Clique): graphs without one cliques (#21183) A simple graph is cliqueFree one iff it has no vertices. Co-authored-by: Lian Tattersall --- Mathlib/Combinatorics/SimpleGraph/Clique.lean | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mathlib/Combinatorics/SimpleGraph/Clique.lean b/Mathlib/Combinatorics/SimpleGraph/Clique.lean index 7738b767a8d3a..433d517a5cba7 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Clique.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Clique.lean @@ -367,6 +367,10 @@ protected theorem CliqueFree.replaceVertex [DecidableEq α] (h : G.CliqueFree n) conv at hφ => enter [a, b]; rw [G.adj_replaceVertex_iff_of_ne _ (mt a) (mt b)] exact hφ +@[simp] +lemma cliqueFree_one : G.CliqueFree 1 ↔ IsEmpty α := by + simp [CliqueFree, isEmpty_iff] + @[simp] theorem cliqueFree_two : G.CliqueFree 2 ↔ G = ⊥ := by classical From 3ba0a0285e367a4dfa743b2dec23f044727b7356 Mon Sep 17 00:00:00 2001 From: Peter Pfaffelhuber Date: Wed, 29 Jan 2025 21:38:11 +0000 Subject: [PATCH 649/681] feat(MeasureTheory/SetSemiring.lean, Order/CompleteLattice.lean): change SetSemiring allow writing unions as disjoint unions (#20931) We show that a union of sets in a semiring can be written as the disjoint unions of sets in the semiring, and add several lemmas. First PR in a work towards the Caratheodory extension theorem, when starting with a `SetSemiring`. Co-authored-by: pfaffelh --- Mathlib/MeasureTheory/Measure/AddContent.lean | 16 +- Mathlib/MeasureTheory/SetSemiring.lean | 331 +++++++++++++----- Mathlib/Order/CompleteLattice.lean | 12 + 3 files changed, 265 insertions(+), 94 deletions(-) diff --git a/Mathlib/MeasureTheory/Measure/AddContent.lean b/Mathlib/MeasureTheory/Measure/AddContent.lean index 2332cc948c41d..3475421c5788a 100644 --- a/Mathlib/MeasureTheory/Measure/AddContent.lean +++ b/Mathlib/MeasureTheory/Measure/AddContent.lean @@ -109,27 +109,27 @@ lemma addContent_union' (hs : s ∈ C) (ht : t ∈ C) (hst : s ∪ t ∈ C) (h_d section IsSetSemiring -lemma addContent_eq_add_diffFinset₀_of_subset (hC : IsSetSemiring C) +lemma addContent_eq_add_disjointOfDiffUnion_of_subset (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) (hI_ss : ∀ t ∈ I, t ⊆ s) (h_dis : PairwiseDisjoint (I : Set (Set α)) id) : - m s = ∑ i ∈ I, m i + ∑ i ∈ hC.diffFinset₀ hs hI, m i := by + m s = ∑ i ∈ I, m i + ∑ i ∈ hC.disjointOfDiffUnion hs hI, m i := by classical - conv_lhs => rw [← hC.sUnion_union_diffFinset₀_of_subset hs hI hI_ss] + conv_lhs => rw [← hC.sUnion_union_disjointOfDiffUnion_of_subset hs hI hI_ss] rw [addContent_sUnion] · rw [sum_union] - exact hC.disjoint_diffFinset₀ hs hI + exact hC.disjoint_disjointOfDiffUnion hs hI · rw [coe_union] - exact Set.union_subset hI (hC.diffFinset₀_subset hs hI) + exact Set.union_subset hI (hC.disjointOfDiffUnion_subset hs hI) · rw [coe_union] - exact hC.pairwiseDisjoint_union_diffFinset₀ hs hI h_dis - · rwa [hC.sUnion_union_diffFinset₀_of_subset hs hI hI_ss] + exact hC.pairwiseDisjoint_union_disjointOfDiffUnion hs hI h_dis + · rwa [hC.sUnion_union_disjointOfDiffUnion_of_subset hs hI hI_ss] lemma sum_addContent_le_of_subset (hC : IsSetSemiring C) (h_ss : ↑I ⊆ C) (h_dis : PairwiseDisjoint (I : Set (Set α)) id) (ht : t ∈ C) (hJt : ∀ s ∈ I, s ⊆ t) : ∑ u ∈ I, m u ≤ m t := by classical - rw [addContent_eq_add_diffFinset₀_of_subset hC ht h_ss hJt h_dis] + rw [addContent_eq_add_disjointOfDiffUnion_of_subset hC ht h_ss hJt h_dis] exact le_add_right le_rfl lemma addContent_mono (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) diff --git a/Mathlib/MeasureTheory/SetSemiring.lean b/Mathlib/MeasureTheory/SetSemiring.lean index 503f9ca6b3e8d..976dcb2c87dc3 100644 --- a/Mathlib/MeasureTheory/SetSemiring.lean +++ b/Mathlib/MeasureTheory/SetSemiring.lean @@ -6,6 +6,7 @@ Authors: Rémy Degenne, Peter Pfaffelhuber import Mathlib.Data.Nat.Lattice import Mathlib.Data.Set.Accumulate import Mathlib.Data.Set.Pairwise.Lattice +import Mathlib.Order.CompleteLattice import Mathlib.MeasureTheory.PiSystem /-! # Semirings and rings of sets @@ -24,19 +25,27 @@ A ring of sets is a set of sets containing `∅`, stable by union, set differenc ## Main definitions * `MeasureTheory.IsSetSemiring C`: property of being a semi-ring of sets. -* `MeasureTheory.IsSetSemiring.diffFinset hs ht`: for `s, t` in a semi-ring `C` +* `MeasureTheory.IsSetSemiring.disjointOfDiff hs ht`: for `s, t` in a semi-ring `C` (with `hC : IsSetSemiring C`) with `hs : s ∈ C`, `ht : t ∈ C`, this is a `Finset` of - pairwise disjoint sets such that `s \ t = ⋃₀ hC.diffFinset hs ht`. -* `MeasureTheory.IsSetSemiring.diffFinset₀ hs hI`: for `hs : s ∈ C` and a finset `I` of sets in `C` - (with `hI : ↑I ⊆ C`), this is a `Finset` of pairwise disjoint sets such that - `s \ ⋃₀ I = ⋃₀ hC.diffFinset₀ hs hI`. + pairwise disjoint sets such that `s \ t = ⋃₀ hC.disjointOfDiff hs ht`. +* `MeasureTheory.IsSetSemiring.disjointOfDiffUnion hs hI`: for `hs : s ∈ C` and a finset + `I` of sets in `C` (with `hI : ↑I ⊆ C`), this is a `Finset` of pairwise disjoint sets such that + `s \ ⋃₀ I = ⋃₀ hC.disjointOfDiffUnion hs hI`. +* `MeasureTheory.IsSetSemiring.disjointOfUnion hJ`: for `hJ ⊆ C`, this is a + `Finset` of pairwise disjoint sets such that `⋃₀ J = ⋃₀ hC.disjointOfUnion hJ`. * `MeasureTheory.IsSetRing`: property of being a ring of sets. ## Main statements * `MeasureTheory.IsSetSemiring.exists_disjoint_finset_diff_eq`: the existence of the `Finset` given - by the definition `IsSetSemiring.diffFinset₀` (see above). + by the definition `IsSetSemiring.disjointOfDiffUnion` (see above). +* `MeasureTheory.IsSetSemiring.disjointOfUnion_props`: In a `hC : IsSetSemiring C`, + for a `J : Finset (Set α)` with `J ⊆ C`, there is + for every `x in J` some `K x ⊆ C` finite, such that + * `⋃ x ∈ J, K x` are pairwise disjoint and do not contain ∅, + * `⋃ s ∈ K x, s ⊆ x`, + * `⋃ x ∈ J, x = ⋃ x ∈ J, ⋃ s ∈ K x, s`. -/ @@ -58,84 +67,86 @@ namespace IsSetSemiring lemma isPiSystem (hC : IsSetSemiring C) : IsPiSystem C := fun s hs t ht _ ↦ hC.inter_mem s hs t ht -section diffFinset +section disjointOfDiff open scoped Classical in /-- In a semi-ring of sets `C`, for all sets `s, t ∈ C`, `s \ t` is equal to a disjoint union of finitely many sets in `C`. The finite set of sets in the union is not unique, but this definition gives an arbitrary `Finset (Set α)` that satisfies the equality. -We remove the empty set to ensure that `t ∉ hC.diffFinset hs ht` even if `t = ∅`. -/ -noncomputable def diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : +We remove the empty set to ensure that `t ∉ hC.disjointOfDiff hs ht` even if `t = ∅`. -/ +noncomputable def disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : Finset (Set α) := (hC.diff_eq_sUnion' s hs t ht).choose \ {∅} -lemma empty_not_mem_diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : - ∅ ∉ hC.diffFinset hs ht := by +lemma empty_nmem_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : + ∅ ∉ hC.disjointOfDiff hs ht := by classical - simp only [diffFinset, mem_sdiff, Finset.mem_singleton, eq_self_iff_true, not_true, - and_false, not_false_iff] + simp only [disjointOfDiff, mem_sdiff, Finset.mem_singleton, eq_self_iff_true, + not_true, and_false, not_false_iff] -lemma diffFinset_subset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : - ↑(hC.diffFinset hs ht) ⊆ C := by +lemma subset_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : + ↑(hC.disjointOfDiff hs ht) ⊆ C := by classical - simp only [diffFinset, coe_sdiff, coe_singleton, diff_singleton_subset_iff] + simp only [disjointOfDiff, coe_sdiff, coe_singleton, diff_singleton_subset_iff] exact (hC.diff_eq_sUnion' s hs t ht).choose_spec.1.trans (Set.subset_insert _ _) -lemma pairwiseDisjoint_diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : - PairwiseDisjoint (hC.diffFinset hs ht : Set (Set α)) id := by +lemma pairwiseDisjoint_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : + PairwiseDisjoint (hC.disjointOfDiff hs ht : Set (Set α)) id := by classical - simp only [diffFinset, coe_sdiff, coe_singleton] + simp only [disjointOfDiff, coe_sdiff, coe_singleton] exact Set.PairwiseDisjoint.subset (hC.diff_eq_sUnion' s hs t ht).choose_spec.2.1 diff_subset -lemma sUnion_diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : - ⋃₀ hC.diffFinset hs ht = s \ t := by +lemma sUnion_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : + ⋃₀ hC.disjointOfDiff hs ht = s \ t := by classical rw [(hC.diff_eq_sUnion' s hs t ht).choose_spec.2.2] - simp only [diffFinset, coe_sdiff, coe_singleton, diff_singleton_subset_iff] + simp only [disjointOfDiff, coe_sdiff, coe_singleton, diff_singleton_subset_iff] rw [sUnion_diff_singleton_empty] -lemma not_mem_diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : - t ∉ hC.diffFinset hs ht := by +lemma nmem_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : + t ∉ hC.disjointOfDiff hs ht := by intro hs_mem suffices t ⊆ s \ t by have h := @disjoint_sdiff_self_right _ t s _ specialize h le_rfl this simp only [Set.bot_eq_empty, Set.le_eq_subset, subset_empty_iff] at h - refine hC.empty_not_mem_diffFinset hs ht ?_ + refine hC.empty_nmem_disjointOfDiff hs ht ?_ rwa [← h] - rw [← hC.sUnion_diffFinset hs ht] + rw [← hC.sUnion_disjointOfDiff hs ht] exact subset_sUnion_of_mem hs_mem -lemma sUnion_insert_diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) (hst : t ⊆ s) : - ⋃₀ insert t (hC.diffFinset hs ht) = s := by - conv_rhs => rw [← union_diff_cancel hst, ← hC.sUnion_diffFinset hs ht] +lemma sUnion_insert_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) + (ht : t ∈ C) (hst : t ⊆ s) : + ⋃₀ insert t (hC.disjointOfDiff hs ht) = s := by + conv_rhs => rw [← union_diff_cancel hst, ← hC.sUnion_disjointOfDiff hs ht] simp only [mem_coe, sUnion_insert] -lemma disjoint_sUnion_diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : - Disjoint t (⋃₀ hC.diffFinset hs ht) := by - rw [hC.sUnion_diffFinset] +lemma disjoint_sUnion_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : + Disjoint t (⋃₀ hC.disjointOfDiff hs ht) := by + rw [hC.sUnion_disjointOfDiff] exact disjoint_sdiff_right -lemma pairwiseDisjoint_insert_diffFinset (hC : IsSetSemiring C) (hs : s ∈ C) (ht : t ∈ C) : - PairwiseDisjoint (insert t (hC.diffFinset hs ht) : Set (Set α)) id := by - have h := hC.pairwiseDisjoint_diffFinset hs ht - refine PairwiseDisjoint.insert_of_not_mem h (hC.not_mem_diffFinset hs ht) fun u hu ↦ ?_ +lemma pairwiseDisjoint_insert_disjointOfDiff (hC : IsSetSemiring C) (hs : s ∈ C) + (ht : t ∈ C) : + PairwiseDisjoint (insert t (hC.disjointOfDiff hs ht) : Set (Set α)) id := by + have h := hC.pairwiseDisjoint_disjointOfDiff hs ht + refine PairwiseDisjoint.insert_of_not_mem h (hC.nmem_disjointOfDiff hs ht) fun u hu ↦ ?_ simp_rw [id] - refine Disjoint.mono_right ?_ (hC.disjoint_sUnion_diffFinset hs ht) + refine Disjoint.mono_right ?_ (hC.disjoint_sUnion_disjointOfDiff hs ht) simp only [Set.le_eq_subset] exact subset_sUnion_of_mem hu -end diffFinset +end disjointOfDiff -section diffFinset₀ +section disjointOfDiffUnion variable {I : Finset (Set α)} /-- In a semiring of sets `C`, for all set `s ∈ C` and finite set of sets `I ⊆ C`, there is a finite set of sets in `C` whose union is `s \ ⋃₀ I`. -See `IsSetSemiring.diffFinset₀` for a definition that gives such a set. -/ +See `IsSetSemiring.disjointOfDiffUnion` for a definition that gives such a set. -/ lemma exists_disjoint_finset_diff_eq (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : ∃ J : Finset (Set α), ↑J ⊆ C ∧ PairwiseDisjoint (J : Set (Set α)) id ∧ s \ ⋃₀ I = ⋃₀ J := by @@ -151,14 +162,14 @@ lemma exists_disjoint_finset_diff_eq (hC : IsSetSemiring C) (hs : s ∈ C) (hI : rw [coe_insert] at hI have ht : t ∈ C := hI (Set.mem_insert _ _) obtain ⟨J, h_ss, h_dis, h_eq⟩ := h ((Set.subset_insert _ _).trans hI) - let Ju : ∀ u ∈ C, Finset (Set α) := fun u hu ↦ hC.diffFinset hu ht + let Ju : ∀ u ∈ C, Finset (Set α) := fun u hu ↦ hC.disjointOfDiff hu ht have hJu_subset : ∀ (u) (hu : u ∈ C), ↑(Ju u hu) ⊆ C := by intro u hu x hx - exact hC.diffFinset_subset hu ht hx + exact hC.subset_disjointOfDiff hu ht hx have hJu_disj : ∀ (u) (hu : u ∈ C), (Ju u hu : Set (Set α)).PairwiseDisjoint id := fun u hu ↦ - hC.pairwiseDisjoint_diffFinset hu ht + hC.pairwiseDisjoint_disjointOfDiff hu ht have hJu_sUnion : ∀ (u) (hu : u ∈ C), ⋃₀ (Ju u hu : Set (Set α)) = u \ t := - fun u hu ↦ hC.sUnion_diffFinset hu ht + fun u hu ↦ hC.sUnion_disjointOfDiff hu ht have hJu_disj' : ∀ (u) (hu : u ∈ C) (v) (hv : v ∈ C) (_h_dis : Disjoint u v), Disjoint (⋃₀ (Ju u hu : Set (Set α))) (⋃₀ ↑(Ju v hv)) := by intro u hu v hv huv_disj @@ -202,80 +213,228 @@ lemma exists_disjoint_finset_diff_eq (hC : IsSetSemiring C) (hs : s ∈ C) (hI : open scoped Classical in /-- In a semiring of sets `C`, for all set `s ∈ C` and finite set of sets `I ⊆ C`, -`diffFinset₀` is a finite set of sets in `C` such that `s \ ⋃₀ I = ⋃₀ (hC.diffFinset₀ hs I hI)`. -`diffFinset` is a special case of `diffFinset₀` where `I` is a singleton. -/ -noncomputable def diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : Finset (Set α) := +`disjointOfDiffUnion` is a finite set of sets in `C` such that +`s \ ⋃₀ I = ⋃₀ (hC.disjointOfDiffUnion hs I hI)`. +`disjointOfDiff` is a special case of `disjointOfDiffUnion` where `I` is a +singleton. -/ +noncomputable def disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) + (hI : ↑I ⊆ C) : Finset (Set α) := (hC.exists_disjoint_finset_diff_eq hs hI).choose \ {∅} -lemma empty_not_mem_diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : - ∅ ∉ hC.diffFinset₀ hs hI := by +lemma empty_nmem_disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) + (hI : ↑I ⊆ C) : + ∅ ∉ hC.disjointOfDiffUnion hs hI := by classical - simp only [diffFinset₀, mem_sdiff, Finset.mem_singleton, eq_self_iff_true, not_true, - and_false, not_false_iff] + simp only [disjointOfDiffUnion, mem_sdiff, Finset.mem_singleton, eq_self_iff_true, + not_true, and_false, not_false_iff] -lemma diffFinset₀_subset (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : - ↑(hC.diffFinset₀ hs hI) ⊆ C := by +lemma disjointOfDiffUnion_subset (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : + ↑(hC.disjointOfDiffUnion hs hI) ⊆ C := by classical - simp only [diffFinset₀, coe_sdiff, coe_singleton, diff_singleton_subset_iff] + simp only [disjointOfDiffUnion, coe_sdiff, coe_singleton, diff_singleton_subset_iff] exact (hC.exists_disjoint_finset_diff_eq hs hI).choose_spec.1.trans (Set.subset_insert _ _) -lemma pairwiseDisjoint_diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : - PairwiseDisjoint (hC.diffFinset₀ hs hI : Set (Set α)) id := by +lemma pairwiseDisjoint_disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) + (hI : ↑I ⊆ C) : PairwiseDisjoint (hC.disjointOfDiffUnion hs hI : Set (Set α)) id := by classical - simp only [diffFinset₀, coe_sdiff, coe_singleton] + simp only [disjointOfDiffUnion, coe_sdiff, coe_singleton] exact Set.PairwiseDisjoint.subset (hC.exists_disjoint_finset_diff_eq hs hI).choose_spec.2.1 diff_subset -lemma diff_sUnion_eq_sUnion_diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : - s \ ⋃₀ I = ⋃₀ hC.diffFinset₀ hs hI := by +lemma diff_sUnion_eq_sUnion_disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) + (hI : ↑I ⊆ C) : s \ ⋃₀ I = ⋃₀ hC.disjointOfDiffUnion hs hI := by classical rw [(hC.exists_disjoint_finset_diff_eq hs hI).choose_spec.2.2] - simp only [diffFinset₀, coe_sdiff, coe_singleton, diff_singleton_subset_iff] + simp only [disjointOfDiffUnion, coe_sdiff, coe_singleton, diff_singleton_subset_iff] rw [sUnion_diff_singleton_empty] -lemma sUnion_diffFinset₀_subset (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : - ⋃₀ (hC.diffFinset₀ hs hI : Set (Set α)) ⊆ s := by - rw [← hC.diff_sUnion_eq_sUnion_diffFinset₀] +lemma sUnion_disjointOfDiffUnion_subset (hC : IsSetSemiring C) (hs : s ∈ C) + (hI : ↑I ⊆ C) : ⋃₀ (hC.disjointOfDiffUnion hs hI : Set (Set α)) ⊆ s := by + rw [← hC.diff_sUnion_eq_sUnion_disjointOfDiffUnion] exact diff_subset -lemma disjoint_sUnion_diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : - Disjoint (⋃₀ (I : Set (Set α))) (⋃₀ hC.diffFinset₀ hs hI) := by - rw [← hC.diff_sUnion_eq_sUnion_diffFinset₀]; exact Set.disjoint_sdiff_right - -lemma disjoint_diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : - Disjoint I (hC.diffFinset₀ hs hI) := by +lemma subset_of_diffUnion_disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) + (t : Set α) (ht : t ∈ (hC.disjointOfDiffUnion hs hI : Set (Set α))) : + t ⊆ s \ ⋃₀ I := by + revert t ht + rw [← sUnion_subset_iff, hC.diff_sUnion_eq_sUnion_disjointOfDiffUnion hs hI] + +lemma subset_of_mem_disjointOfDiffUnion (hC : IsSetSemiring C) {I : Finset (Set α)} + (hs : s ∈ C) (hI : ↑I ⊆ C) (t : Set α) + (ht : t ∈ (hC.disjointOfDiffUnion hs hI : Set (Set α))) : + t ⊆ s := by + apply le_trans <| hC.subset_of_diffUnion_disjointOfDiffUnion hs hI t ht + exact sdiff_le (a := s) (b := ⋃₀ I) + +lemma disjoint_sUnion_disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) + (hI : ↑I ⊆ C) : + Disjoint (⋃₀ (I : Set (Set α))) (⋃₀ hC.disjointOfDiffUnion hs hI) := by + rw [← hC.diff_sUnion_eq_sUnion_disjointOfDiffUnion]; exact Set.disjoint_sdiff_right + +lemma disjoint_disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) : + Disjoint I (hC.disjointOfDiffUnion hs hI) := by by_contra h rw [Finset.not_disjoint_iff] at h - obtain ⟨u, huI, hu_diffFinset₀⟩ := h - have h_disj : u ≤ ⊥ := hC.disjoint_sUnion_diffFinset₀ hs hI (subset_sUnion_of_mem huI) - (subset_sUnion_of_mem hu_diffFinset₀) + obtain ⟨u, huI, hu_disjointOfDiffUnion⟩ := h + have h_disj : u ≤ ⊥ := + hC.disjoint_sUnion_disjointOfDiffUnion hs hI (subset_sUnion_of_mem huI) + (subset_sUnion_of_mem hu_disjointOfDiffUnion) simp only [Set.bot_eq_empty, Set.le_eq_subset, subset_empty_iff] at h_disj - refine hC.empty_not_mem_diffFinset₀ hs hI ?_ - rwa [h_disj] at hu_diffFinset₀ + refine hC.empty_nmem_disjointOfDiffUnion hs hI ?_ + rwa [h_disj] at hu_disjointOfDiffUnion -lemma pairwiseDisjoint_union_diffFinset₀ (hC : IsSetSemiring C) (hs : s ∈ C) +lemma pairwiseDisjoint_union_disjointOfDiffUnion (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) (h_dis : PairwiseDisjoint (I : Set (Set α)) id) : - PairwiseDisjoint (I ∪ hC.diffFinset₀ hs hI : Set (Set α)) id := by + PairwiseDisjoint (I ∪ hC.disjointOfDiffUnion hs hI : Set (Set α)) id := by rw [pairwiseDisjoint_union] - refine ⟨h_dis, hC.pairwiseDisjoint_diffFinset₀ hs hI, fun u hu v hv _ ↦ ?_⟩ + refine ⟨h_dis, hC.pairwiseDisjoint_disjointOfDiffUnion hs hI, fun u hu v hv _ ↦ ?_⟩ simp_rw [id] exact disjoint_of_subset (subset_sUnion_of_mem hu) (subset_sUnion_of_mem hv) - (hC.disjoint_sUnion_diffFinset₀ hs hI) + (hC.disjoint_sUnion_disjointOfDiffUnion hs hI) -lemma sUnion_union_sUnion_diffFinset₀_of_subset (hC : IsSetSemiring C) (hs : s ∈ C) - (hI : ↑I ⊆ C) (hI_ss : ∀ t ∈ I, t ⊆ s) : - ⋃₀ I ∪ ⋃₀ hC.diffFinset₀ hs hI = s := by +lemma sUnion_union_sUnion_disjointOfDiffUnion_of_subset (hC : IsSetSemiring C) + (hs : s ∈ C) (hI : ↑I ⊆ C) (hI_ss : ∀ t ∈ I, t ⊆ s) : + ⋃₀ I ∪ ⋃₀ hC.disjointOfDiffUnion hs hI = s := by conv_rhs => rw [← union_diff_cancel (Set.sUnion_subset hI_ss : ⋃₀ ↑I ⊆ s), - hC.diff_sUnion_eq_sUnion_diffFinset₀ hs hI] + hC.diff_sUnion_eq_sUnion_disjointOfDiffUnion hs hI] -lemma sUnion_union_diffFinset₀_of_subset (hC : IsSetSemiring C) (hs : s ∈ C) +lemma sUnion_union_disjointOfDiffUnion_of_subset (hC : IsSetSemiring C) (hs : s ∈ C) (hI : ↑I ⊆ C) (hI_ss : ∀ t ∈ I, t ⊆ s) [DecidableEq (Set α)] : - ⋃₀ ↑(I ∪ hC.diffFinset₀ hs hI) = s := by - conv_rhs => rw [← sUnion_union_sUnion_diffFinset₀_of_subset hC hs hI hI_ss] + ⋃₀ ↑(I ∪ hC.disjointOfDiffUnion hs hI) = s := by + conv_rhs => rw [← sUnion_union_sUnion_disjointOfDiffUnion_of_subset hC hs hI hI_ss] simp_rw [coe_union] rw [sUnion_union] -end diffFinset₀ +end disjointOfDiffUnion + +section disjointOfUnion + + +variable {j : Set α} {J : Finset (Set α)} + +open Set MeasureTheory Order + +theorem disjointOfUnion_props (hC : IsSetSemiring C) (h1 : ↑J ⊆ C) : + ∃ K : Set α → Finset (Set α), + PairwiseDisjoint J K + ∧ (∀ i ∈ J, ↑(K i) ⊆ C) + ∧ PairwiseDisjoint (⋃ x ∈ J, (K x : Set (Set α))) id + ∧ (∀ j ∈ J, ⋃₀ K j ⊆ j) + ∧ (∀ j ∈ J, ∅ ∉ K j) + ∧ ⋃₀ J = ⋃₀ (⋃ x ∈ J, (K x : Set (Set α))) := by + classical + induction J using Finset.cons_induction with + | empty => simp + | cons s J hJ hind => + rw [cons_eq_insert, coe_insert, Set.insert_subset_iff] at h1 + obtain ⟨K, hK0, ⟨hK1, hK2, hK3, hK4, hK5⟩⟩ := hind h1.2 + let K1 : Set α → Finset (Set α) := fun (t : Set α) ↦ + if t = s then (hC.disjointOfDiffUnion h1.1 h1.2) else K t + have hK1s : K1 s = hC.disjointOfDiffUnion h1.1 h1.2 := by simp [K1] + have hK1_of_ne t (ht : t ≠ s) : K1 t = K t := by simp [K1, ht] + use K1 + simp only [cons_eq_insert, disjiUnion_eq_biUnion, Finset.biUnion_insert, coe_union, coe_biUnion, + mem_coe, Set.union_subset_iff, iUnion_subset_iff, Finset.mem_insert, sUnion_subset_iff, + forall_eq_or_imp, coe_insert, sUnion_insert, exists_and_left, exists_prop] + -- two simplification rules for induction hypothesis + have ht1' : ∀ x ∈ J, K1 x = K x := fun x hx ↦ hK1_of_ne _ (fun h_eq ↦ hJ (h_eq ▸ hx)) + have ht2 : (⋃ x ∈ J, (K1 x : Set (Set α))) = ⋃ x ∈ J, ((K x : Set (Set α))) := by + apply iUnion₂_congr + intros x hx + exact_mod_cast hK1_of_ne _ (ne_of_mem_of_not_mem hx hJ) + simp only [hK1s] + refine ⟨?_, ⟨hC.disjointOfDiffUnion_subset h1.1 h1.2, ?_⟩, ?_, + ⟨hC.subset_of_mem_disjointOfDiffUnion h1.1 h1.2, ?_⟩, ?_, ?_⟩ + · apply Set.Pairwise.insert + · intro j hj i hi hij + rw [Function.onFun, ht1' j hj, ht1' i hi] + exact hK0 hj hi hij + · intro i hi _ + have h7 : Disjoint ↑(hC.disjointOfDiffUnion h1.1 h1.2) (K i : Set (Set α)) := by + refine disjoint_of_sSup_disjoint_of_le_of_le + (hC.subset_of_diffUnion_disjointOfDiffUnion h1.1 h1.2) ?_ + (@disjoint_sdiff_left _ (⋃₀ J) s) (Or.inl + (hC.empty_nmem_disjointOfDiffUnion h1.1 h1.2)) + simp only [mem_coe, Set.le_eq_subset] + apply sUnion_subset_iff.mp + exact (hK3 i hi).trans (subset_sUnion_of_mem hi) + have h8 : Function.onFun Disjoint K1 s i := by + refine Finset.disjoint_iff_inter_eq_empty.mpr ?_ + rw [ht1' i hi, hK1s] + rw [Set.disjoint_iff_inter_eq_empty] at h7 + exact_mod_cast h7 + exact ⟨h8, Disjoint.symm h8⟩ + · intros i hi + rw [ht1' i hi] + exact hK1 i hi + · simp only [iUnion_iUnion_eq_or_left] + refine pairwiseDisjoint_union.mpr ⟨?_, ?_, ?_⟩ + · rw [hK1s] + exact hC.pairwiseDisjoint_disjointOfDiffUnion h1.1 h1.2 + · simpa [ht2] + · simp only [mem_coe, mem_iUnion, exists_prop, ne_eq, id_eq, forall_exists_index, and_imp] + intros i hi j x hx h3 h4 + obtain ki : i ⊆ s \ ⋃₀ J := hC.subset_of_diffUnion_disjointOfDiffUnion h1.1 h1.2 _ + (hK1s ▸ hi) + obtain hx2 : j ⊆ x := subset_trans (subset_sUnion_of_mem (ht1' x hx ▸ h3)) (hK3 x hx) + obtain kj : j ⊆ ⋃₀ J := hx2.trans <| subset_sUnion_of_mem hx + exact disjoint_of_subset ki kj disjoint_sdiff_left + · intros a ha + simp_rw [hK1_of_ne _ (ne_of_mem_of_not_mem ha hJ)] + change ∀ t' ∈ (K a : Set (Set α)), t' ⊆ a + rw [← sUnion_subset_iff] + exact hK3 a ha + · refine ⟨hC.empty_nmem_disjointOfDiffUnion h1.1 h1.2, ?_⟩ + intros a ha + rw [ht1' a ha] + exact hK4 a ha + · simp only [iUnion_iUnion_eq_or_left, ht2, sUnion_union, ht2, K1] + simp_rw [apply_ite, hK5, + ← hC.diff_sUnion_eq_sUnion_disjointOfDiffUnion h1.1 h1.2, hK5] + simp only [↓reduceIte, diff_union_self] + +/-- For some `hJ : J ⊆ C` and `j : Set α`, where `hC : IsSetSemiring C`, this is +a `Finset (Set α)` such that `K j := hC.disjointOfUnion hJ` are disjoint +and `⋃₀ K j ⊆ j`, for `j ∈ J`. +Using these we write `⋃₀ J` as a disjoint union `⋃₀ J = ⋃₀ ⋃ x ∈ J, (K x)`. +See `MeasureTheory.IsSetSemiring.disjointOfUnion_props`.-/ +noncomputable def disjointOfUnion (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) (j : Set α) := + (hC.disjointOfUnion_props hJ).choose j + +lemma pairwiseDisjoint_disjointOfUnion (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) : + PairwiseDisjoint J (hC.disjointOfUnion hJ) := + (Exists.choose_spec (hC.disjointOfUnion_props hJ)).1 + +lemma disjointOfUnion_subset (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) (hj : j ∈ J) : + (disjointOfUnion hC hJ j : Set (Set α)) ⊆ C := + (Exists.choose_spec (hC.disjointOfUnion_props hJ)).2.1 _ hj + +lemma pairwiseDisjoint_biUnion_disjointOfUnion (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) : + PairwiseDisjoint (⋃ x ∈ J, (hC.disjointOfUnion hJ x : Set (Set α))) id := + (Exists.choose_spec (hC.disjointOfUnion_props hJ)).2.2.1 + +lemma pairwiseDisjoint_disjointOfUnion_of_mem (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) (hj : j ∈ J) : + PairwiseDisjoint (hC.disjointOfUnion hJ j : Set (Set α)) id := by + apply PairwiseDisjoint.subset (hC.pairwiseDisjoint_biUnion_disjointOfUnion hJ) + exact subset_iUnion₂_of_subset j hj fun ⦃a⦄ a ↦ a + +lemma disjointOfUnion_subset_of_mem (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) (hj : j ∈ J) : + ⋃₀ hC.disjointOfUnion hJ j ⊆ j := + (Exists.choose_spec (hC.disjointOfUnion_props hJ)).2.2.2.1 j hj + +lemma subset_of_mem_disjointOfUnion (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) (hj : j ∈ J) {x : Set α} + (hx : x ∈ (hC.disjointOfUnion hJ) j) : x ⊆ j := + sUnion_subset_iff.mp (hC.disjointOfUnion_subset_of_mem hJ hj) x hx + +lemma empty_nmem_disjointOfUnion (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) (hj : j ∈ J) : + ∅ ∉ hC.disjointOfUnion hJ j := + (Exists.choose_spec (hC.disjointOfUnion_props hJ)).2.2.2.2.1 j hj + +lemma sUnion_disjointOfUnion (hC : IsSetSemiring C) (hJ : ↑J ⊆ C) : + ⋃₀ ⋃ x ∈ J, (hC.disjointOfUnion hJ x : Set (Set α)) = ⋃₀ J + := (Exists.choose_spec (hC.disjointOfUnion_props hJ)).2.2.2.2.2.symm + +end disjointOfUnion end IsSetSemiring diff --git a/Mathlib/Order/CompleteLattice.lean b/Mathlib/Order/CompleteLattice.lean index 6dfb80d1a72f2..5e469fe3ff642 100644 --- a/Mathlib/Order/CompleteLattice.lean +++ b/Mathlib/Order/CompleteLattice.lean @@ -1739,6 +1739,18 @@ theorem disjoint_sSup_right {a : Set α} {b : α} (d : Disjoint b (sSup a)) {i} Disjoint b i := disjoint_iff_inf_le.mpr (iSup₂_le_iff.mp (iSup_inf_le_inf_sSup.trans d.le_bot) i hi :) +lemma disjoint_of_sSup_disjoint_of_le_of_le {a b : α} {c d : Set α} (hs : ∀ e ∈ c, e ≤ a) + (ht : ∀ e ∈ d, e ≤ b) (hd : Disjoint a b) (he : ⊥ ∉ c ∨ ⊥ ∉ d) : Disjoint c d := by + rw [disjoint_iff_forall_ne] + intros x hx y hy + rw [Disjoint.ne_iff] + · aesop + · exact Disjoint.mono (hs x hx) (ht y hy) hd + +lemma disjoint_of_sSup_disjoint {a b : Set α} (hd : Disjoint (sSup a) (sSup b)) + (he : ⊥ ∉ a ∨ ⊥ ∉ b) : Disjoint a b := + disjoint_of_sSup_disjoint_of_le_of_le (fun _ hc ↦ le_sSup hc) (fun _ hc ↦ le_sSup hc) hd he + end CompleteLattice -- See note [reducible non-instances] From 323ed6b5ce297555377a927ac5d0f38b73b825e8 Mon Sep 17 00:00:00 2001 From: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Date: Wed, 29 Jan 2025 22:18:35 +0000 Subject: [PATCH 650/681] feat: add new iteratedDeriv_const_smul/mul (#20288) These are consistent with the iteratedDerivWithin versions and replace the older deprecated and misnamed theorems. --- .../Calculus/IteratedDeriv/Lemmas.lean | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean index fb639723208c3..e797df9f8f6a7 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Lemmas.lean @@ -152,6 +152,18 @@ lemma iteratedDeriv_sub (hf : ContDiff 𝕜 n f) (hg : ContDiff 𝕜 n g) : iteratedDerivWithin_sub (Set.mem_univ _) uniqueDiffOn_univ (contDiffOn_univ.mpr hf) (contDiffOn_univ.mpr hg) +theorem iteratedDeriv_const_smul {n : ℕ} {f : 𝕜 → F} (h : ContDiffAt 𝕜 n f x) (c : 𝕜) : + iteratedDeriv n (c • f) x = c • iteratedDeriv n f x := by + simpa only [iteratedDerivWithin_univ] using + iteratedDerivWithin_const_smul (Set.mem_univ x) uniqueDiffOn_univ + c (contDiffWithinAt_univ.mpr h) + +theorem iteratedDeriv_const_mul {n : ℕ} {f : 𝕜 → 𝕜} (h : ContDiffAt 𝕜 n f x) (c : 𝕜) : + iteratedDeriv n (fun z => c * f z) x = c * iteratedDeriv n f x := by + simpa only [iteratedDerivWithin_univ] using + iteratedDerivWithin_const_mul (Set.mem_univ x) uniqueDiffOn_univ + c (contDiffWithinAt_univ.mpr h) + theorem iteratedDeriv_comp_const_smul {n : ℕ} {f : 𝕜 → F} (h : ContDiff 𝕜 n f) (c : 𝕜) : iteratedDeriv n (fun x => f (c * x)) = fun x => c ^ n • iteratedDeriv n f (c * x) := by funext x @@ -159,16 +171,10 @@ theorem iteratedDeriv_comp_const_smul {n : ℕ} {f : 𝕜 → F} (h : ContDiff iteratedDerivWithin_comp_const_smul (Set.mem_univ x) uniqueDiffOn_univ (contDiffOn_univ.mpr h) c (Set.mapsTo_univ _ _) -@[deprecated (since := "2024-12-20")] -alias iteratedDeriv_const_smul := iteratedDeriv_comp_const_smul - theorem iteratedDeriv_comp_const_mul {n : ℕ} {f : 𝕜 → 𝕜} (h : ContDiff 𝕜 n f) (c : 𝕜) : iteratedDeriv n (fun x => f (c * x)) = fun x => c ^ n * iteratedDeriv n f (c * x) := by simpa only [smul_eq_mul] using iteratedDeriv_comp_const_smul h c -@[deprecated (since := "2024-12-20")] -alias iteratedDeriv_const_mul := iteratedDeriv_comp_const_mul - lemma iteratedDeriv_comp_neg (n : ℕ) (f : 𝕜 → F) (a : 𝕜) : iteratedDeriv n (fun x ↦ f (-x)) a = (-1 : 𝕜) ^ n • iteratedDeriv n f (-a) := by induction' n with n ih generalizing a From b0e2db2f53338ae6bc3506cfc201840f090332c3 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 29 Jan 2025 22:41:56 +0000 Subject: [PATCH 651/681] feat(*/Fin/*): add 2 lemmas (#21229) This is a version of #21112 that doesn't use inline `NeZero` instances, thus doesn't break `simp` normal forms all over the place. --- Mathlib/Data/Fin/Basic.lean | 6 ++++++ Mathlib/Order/Fin/Basic.lean | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 6cfce6b1e1b72..331cbae4643f7 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -240,6 +240,12 @@ This one instead uses a `NeZero n` typeclass hypothesis. theorem val_zero' (n : ℕ) [NeZero n] : ((0 : Fin n) : ℕ) = 0 := rfl +/-- Fin.mk_zero` in `Lean` only applies in `Fin (n + 1)`. +This one instead uses a `NeZero n` typeclass hypothesis. +-/ +@[simp] +theorem mk_zero' (n : ℕ) [NeZero n] : (⟨0, pos_of_neZero n⟩ : Fin n) = 0 := rfl + /-- The `Fin.zero_le` in `Lean` only applies in `Fin (n+1)`. This one instead uses a `NeZero n` typeclass hypothesis. diff --git a/Mathlib/Order/Fin/Basic.lean b/Mathlib/Order/Fin/Basic.lean index 909ffef89bf33..8f534eba16e5a 100644 --- a/Mathlib/Order/Fin/Basic.lean +++ b/Mathlib/Order/Fin/Basic.lean @@ -95,6 +95,10 @@ theorem zero_eq_top {n : ℕ} [NeZero n] : (0 : Fin n) = ⊤ ↔ n = 1 := by theorem top_eq_zero {n : ℕ} [NeZero n] : (⊤ : Fin n) = 0 ↔ n = 1 := eq_comm.trans zero_eq_top +@[simp] +theorem cast_top {m n : ℕ} [NeZero m] [NeZero n] (h : m = n) : (⊤ : Fin m).cast h = ⊤ := by + simp [← val_inj, h] + section ToFin variable {α : Type*} [Preorder α] {f : α → Fin (n + 1)} From e6cdd0d13380d5cef56d70eff6de05b32758ad1a Mon Sep 17 00:00:00 2001 From: Bhavik Mehta Date: Wed, 29 Jan 2025 23:20:53 +0000 Subject: [PATCH 652/681] feat(Analysis/Convex): extreme points of doubly stochastic matrices (#17514) --- Mathlib/Analysis/Convex/Birkhoff.lean | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/Mathlib/Analysis/Convex/Birkhoff.lean b/Mathlib/Analysis/Convex/Birkhoff.lean index d69061ff3199b..3b8c6303e749c 100644 --- a/Mathlib/Analysis/Convex/Birkhoff.lean +++ b/Mathlib/Analysis/Convex/Birkhoff.lean @@ -5,6 +5,7 @@ Authors: Bhavik Mehta -/ import Mathlib.Analysis.Convex.Combination +import Mathlib.Analysis.Convex.Extreme import Mathlib.Combinatorics.Hall.Basic import Mathlib.Data.Matrix.DoublyStochastic import Mathlib.Tactic.Linarith @@ -18,10 +19,11 @@ import Mathlib.Tactic.Linarith combination of permutation matrices. * `doublyStochastic_eq_convexHull_perm`: The set of doubly stochastic matrices is the convex hull of the permutation matrices. +* `extremePoints_doublyStochastic`: The set of extreme points of the doubly stochastic matrices is + the set of permutation matrices. ## TODO -* Show that the extreme points of doubly stochastic matrices are the permutation matrices. * Show that for `x y : n → R`, `x` is majorized by `y` if and only if there is a doubly stochastic matrix `M` such that `M *ᵥ y = x`. @@ -169,4 +171,28 @@ theorem doublyStochastic_eq_convexHull_permMatrix : obtain ⟨w, hw1, hw2, hw3⟩ := exists_eq_sum_perm_of_mem_doublyStochastic hM exact mem_convexHull_of_exists_fintype w (·.permMatrix R) hw1 hw2 (by simp) hw3 +/-- +The set of extreme points of the doubly stochastic matrices is the set of permutation matrices. +-/ +theorem extremePoints_doublyStochastic : + Set.extremePoints R (doublyStochastic R n) = {σ.permMatrix R | σ : Equiv.Perm n} := by + refine subset_antisymm ?_ ?_ + · rw [doublyStochastic_eq_convexHull_permMatrix] + exact extremePoints_convexHull_subset + rintro _ ⟨σ, rfl⟩ + refine ⟨permMatrix_mem_doublyStochastic, fun x₁ hx₁ x₂ hx₂ hσ ↦ ?_⟩ + suffices ∀ i j : n, x₁ i j = x₂ i j by + obtain rfl : x₁ = x₂ := by simpa [← Matrix.ext_iff] + simp_all + intro i j + have h₁ : σ.permMatrix R i j ∈ openSegment R (x₁ i j) (x₂ i j) := + image_openSegment _ (entryLinearMap R R i j).toAffineMap x₁ x₂ ▸ ⟨_, hσ, rfl⟩ + by_contra! h + have h₂ : openSegment R (x₁ i j) (x₂ i j) ⊆ Set.Ioo 0 1 := by + rw [openSegment_eq_Ioo' h] + apply Set.Ioo_subset_Ioo <;> + simp_all [nonneg_of_mem_doublyStochastic, le_one_of_mem_doublyStochastic] + specialize h₂ h₁ + aesop + end LinearOrderedField From d9321524a0b448bef114a33c7cce879b2fdfde3e Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Wed, 29 Jan 2025 23:20:55 +0000 Subject: [PATCH 653/681] feat: `HasFDerivAt` for `Fin.cons` (#20407) I'm too lazy to add these for `Fin.snoc` as well, and I suspect people care much less about that. Strictly we need to repeat all these for `Matrix.vecCons` as well... --- Mathlib/Analysis/Calculus/Deriv/Prod.lean | 89 +++++++++- Mathlib/Analysis/Calculus/FDeriv/Prod.lean | 183 ++++++++++++++++++++- Mathlib/LinearAlgebra/Pi.lean | 22 ++- Mathlib/Topology/Algebra/Module/Equiv.lean | 22 +++ 4 files changed, 305 insertions(+), 11 deletions(-) diff --git a/Mathlib/Analysis/Calculus/Deriv/Prod.lean b/Mathlib/Analysis/Calculus/Deriv/Prod.lean index caa6c11683543..61e10a2f7aeef 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Prod.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Prod.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Gabriel Ebner. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Gabriel Ebner, Yury Kudryashov +Authors: Gabriel Ebner, Yury Kudryashov, Eric Wieser -/ import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.Calculus.FDeriv.Prod @@ -13,7 +13,7 @@ In this file we prove lemmas about derivatives of functions `f : 𝕜 → E × F `f : 𝕜 → (Π i, E i)`. For a more detailed overview of one-dimensional derivatives in mathlib, see the module docstring of -`analysis/calculus/deriv/basic`. +`Mathlib/Analysis/Calculus/Deriv/Basic.lean`. ## Keywords @@ -90,3 +90,88 @@ theorem deriv_pi (h : ∀ i, DifferentiableAt 𝕜 (fun x => φ x i) x) : (hasDerivAt_pi.2 fun i => (h i).hasDerivAt).deriv end Pi + + +/-! +### Derivatives of tuples `f : 𝕜 → Π i : Fin n.succ, F' i` + +These can be used to prove results about functions of the form `fun x ↦ ![f x, g x, h x]`, +as `Matrix.vecCons` is defeq to `Fin.cons`. +-/ +section PiFin + +variable {n : Nat} {F' : Fin n.succ → Type*} +variable [∀ i, NormedAddCommGroup (F' i)] [∀ i, NormedSpace 𝕜 (F' i)] +variable {φ : 𝕜 → F' 0} {φs : 𝕜 → ∀ i, F' (Fin.succ i)} + +theorem hasStrictDerivAt_finCons {φ' : Π i, F' i} : + HasStrictDerivAt (fun x => Fin.cons (φ x) (φs x)) φ' x ↔ + HasStrictDerivAt φ (φ' 0) x ∧ HasStrictDerivAt φs (fun i => φ' i.succ) x := + hasStrictFDerivAt_finCons + +/-- A variant of `hasStrictDerivAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasStrictDerivAt_finCons' {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} : + HasStrictDerivAt (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') x ↔ + HasStrictDerivAt φ φ' x ∧ HasStrictDerivAt φs φs' x := + hasStrictDerivAt_finCons + +theorem HasStrictDerivAt.finCons {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} + (h : HasStrictDerivAt φ φ' x) (hs : HasStrictDerivAt φs φs' x) : + HasStrictDerivAt (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') x := + hasStrictDerivAt_finCons'.mpr ⟨h, hs⟩ + +theorem hasDerivAtFilter_finCons {φ' : Π i, F' i} {l : Filter 𝕜} : + HasDerivAtFilter (fun x => Fin.cons (φ x) (φs x)) φ' x l ↔ + HasDerivAtFilter φ (φ' 0) x l ∧ HasDerivAtFilter φs (fun i => φ' i.succ) x l := + hasFDerivAtFilter_finCons + +/-- A variant of `hasDerivAtFilter_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasDerivAtFilter_finCons' {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} {l : Filter 𝕜} : + HasDerivAtFilter (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') x l ↔ + HasDerivAtFilter φ φ' x l ∧ HasDerivAtFilter φs φs' x l := + hasDerivAtFilter_finCons + +theorem HasDerivAtFilter.finCons {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} {l : Filter 𝕜} + (h : HasDerivAtFilter φ φ' x l) (hs : HasDerivAtFilter φs φs' x l) : + HasDerivAtFilter (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') x l := + hasDerivAtFilter_finCons'.mpr ⟨h, hs⟩ + +theorem hasDerivAt_finCons {φ' : Π i, F' i} : + HasDerivAt (fun x => Fin.cons (φ x) (φs x)) φ' x ↔ + HasDerivAt φ (φ' 0) x ∧ HasDerivAt φs (fun i => φ' i.succ) x := + hasDerivAtFilter_finCons + +/-- A variant of `hasDerivAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasDerivAt_finCons' {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} : + HasDerivAt (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') x ↔ + HasDerivAt φ φ' x ∧ HasDerivAt φs φs' x := + hasDerivAt_finCons + +theorem HasDerivAt.finCons {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} + (h : HasDerivAt φ φ' x) (hs : HasDerivAt φs φs' x) : + HasDerivAt (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') x := + hasDerivAt_finCons'.mpr ⟨h, hs⟩ + +theorem hasDerivWithinAt_finCons {φ' : Π i, F' i} : + HasDerivWithinAt (fun x => Fin.cons (φ x) (φs x)) φ' s x ↔ + HasDerivWithinAt φ (φ' 0) s x ∧ HasDerivWithinAt φs (fun i => φ' i.succ) s x := + hasDerivAtFilter_finCons + +/-- A variant of `hasDerivWithinAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasDerivWithinAt_finCons' {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} : + HasDerivWithinAt (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') s x ↔ + HasDerivWithinAt φ φ' s x ∧ HasDerivWithinAt φs φs' s x := + hasDerivAtFilter_finCons + +theorem HasDerivWithinAt.finCons {φ' : F' 0} {φs' : Π i, F' (Fin.succ i)} + (h : HasDerivWithinAt φ φ' s x) (hs : HasDerivWithinAt φs φs' s x) : + HasDerivWithinAt (fun x => Fin.cons (φ x) (φs x)) (Fin.cons φ' φs') s x := + hasDerivWithinAt_finCons'.mpr ⟨h, hs⟩ + +-- TODO: write the `Fin.cons` versions of `derivWithin_pi` and `deriv_pi` + +end PiFin diff --git a/Mathlib/Analysis/Calculus/FDeriv/Prod.lean b/Mathlib/Analysis/Calculus/FDeriv/Prod.lean index c5e33c862226a..892ed8c6dfa95 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Prod.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Prod.lean @@ -1,7 +1,7 @@ /- 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 +Authors: Jeremy Avigad, Sébastien Gouëzel, Yury Kudryashov, Eric Wieser -/ import Mathlib.Analysis.Calculus.FDeriv.Linear import Mathlib.Analysis.Calculus.FDeriv.Comp @@ -487,6 +487,187 @@ theorem fderiv_pi (h : ∀ i, DifferentiableAt 𝕜 (φ i) x) : end Pi +/-! +### Derivatives of tuples `f : E → Π i : Fin n.succ, F' i` + +These can be used to prove results about functions of the form `fun x ↦ ![f x, g x, h x]`, +as `Matrix.vecCons` is defeq to `Fin.cons`. +-/ +section PiFin + +variable {n : Nat} {F' : Fin n.succ → Type*} +variable [∀ i, NormedAddCommGroup (F' i)] [∀ i, NormedSpace 𝕜 (F' i)] +variable {φ : E → F' 0} {φs : E → ∀ i, F' (Fin.succ i)} + +theorem hasStrictFDerivAt_finCons {φ' : E →L[𝕜] Π i, F' i} : + HasStrictFDerivAt (fun x => Fin.cons (φ x) (φs x)) φ' x ↔ + HasStrictFDerivAt φ (.proj 0 ∘L φ') x ∧ + HasStrictFDerivAt φs (Pi.compRightL 𝕜 F' Fin.succ ∘L φ') x := by + rw [hasStrictFDerivAt_pi', Fin.forall_fin_succ, hasStrictFDerivAt_pi'] + dsimp [ContinuousLinearMap.comp, LinearMap.comp, Function.comp_def] + simp only [Fin.cons_zero, Fin.cons_succ] + +/-- A variant of `hasStrictFDerivAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasStrictFDerivAt_finCons' + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} : + HasStrictFDerivAt (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') x ↔ + HasStrictFDerivAt φ φ' x ∧ HasStrictFDerivAt φs φs' x := + hasStrictFDerivAt_finCons + +@[fun_prop] +theorem HasStrictFDerivAt.finCons + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} + (h : HasStrictFDerivAt φ φ' x) (hs : HasStrictFDerivAt φs φs' x) : + HasStrictFDerivAt (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') x := + hasStrictFDerivAt_finCons'.mpr ⟨h, hs⟩ + +theorem hasFDerivAtFilter_finCons + {φ' : E →L[𝕜] Π i, F' i} {l : Filter E} : + HasFDerivAtFilter (fun x => Fin.cons (φ x) (φs x)) φ' x l ↔ + HasFDerivAtFilter φ (.proj 0 ∘L φ') x l ∧ + HasFDerivAtFilter φs (Pi.compRightL 𝕜 F' Fin.succ ∘L φ') x l := by + rw [hasFDerivAtFilter_pi', Fin.forall_fin_succ, hasFDerivAtFilter_pi'] + dsimp [ContinuousLinearMap.comp, LinearMap.comp, Function.comp_def] + simp only [Fin.cons_zero, Fin.cons_succ] + +/-- A variant of `hasFDerivAtFilter_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasFDerivAtFilter_finCons' + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} {l : Filter E} : + HasFDerivAtFilter (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') x l ↔ + HasFDerivAtFilter φ φ' x l ∧ HasFDerivAtFilter φs φs' x l := + hasFDerivAtFilter_finCons + +theorem HasFDerivAtFilter.finCons + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} {l : Filter E} + (h : HasFDerivAtFilter φ φ' x l) (hs : HasFDerivAtFilter φs φs' x l) : + HasFDerivAtFilter (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') x l := + hasFDerivAtFilter_finCons'.mpr ⟨h, hs⟩ + +theorem hasFDerivAt_finCons + {φ' : E →L[𝕜] Π i, F' i} : + HasFDerivAt (fun x => Fin.cons (φ x) (φs x)) φ' x ↔ + HasFDerivAt φ (.proj 0 ∘L φ') x ∧ HasFDerivAt φs (Pi.compRightL 𝕜 F' Fin.succ ∘L φ') x := + hasFDerivAtFilter_finCons + +/-- A variant of `hasFDerivAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasFDerivAt_finCons' + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} : + HasFDerivAt (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') x ↔ + HasFDerivAt φ φ' x ∧ HasFDerivAt φs φs' x := + hasFDerivAt_finCons + +@[fun_prop] +theorem HasFDerivAt.finCons + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} + (h : HasFDerivAt φ φ' x) (hs : HasFDerivAt φs φs' x) : + HasFDerivAt (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') x := + hasFDerivAt_finCons'.mpr ⟨h, hs⟩ + +theorem hasFDerivWithinAt_finCons + {φ' : E →L[𝕜] Π i, F' i} : + HasFDerivWithinAt (fun x => Fin.cons (φ x) (φs x)) φ' s x ↔ + HasFDerivWithinAt φ (.proj 0 ∘L φ') s x ∧ + HasFDerivWithinAt φs (Pi.compRightL 𝕜 F' Fin.succ ∘L φ') s x := + hasFDerivAtFilter_finCons + +/-- A variant of `hasFDerivWithinAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem hasFDerivWithinAt_finCons' + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} : + HasFDerivWithinAt (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') s x ↔ + HasFDerivWithinAt φ φ' s x ∧ HasFDerivWithinAt φs φs' s x := + hasFDerivAtFilter_finCons + +@[fun_prop] +theorem HasFDerivWithinAt.finCons + {φ' : E →L[𝕜] F' 0} {φs' : E →L[𝕜] Π i, F' (Fin.succ i)} + (h : HasFDerivWithinAt φ φ' s x) (hs : HasFDerivWithinAt φs φs' s x) : + HasFDerivWithinAt (fun x => Fin.cons (φ x) (φs x)) (φ'.finCons φs') s x := + hasFDerivWithinAt_finCons'.mpr ⟨h, hs⟩ + +theorem differentiableWithinAt_finCons : + DifferentiableWithinAt 𝕜 (fun x => Fin.cons (φ x) (φs x)) s x ↔ + DifferentiableWithinAt 𝕜 φ s x ∧ DifferentiableWithinAt 𝕜 φs s x := by + rw [differentiableWithinAt_pi, Fin.forall_fin_succ, differentiableWithinAt_pi] + simp only [Fin.cons_zero, Fin.cons_succ] + +/-- A variant of `differentiableWithinAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem differentiableWithinAt_finCons' : + DifferentiableWithinAt 𝕜 (fun x => Fin.cons (φ x) (φs x)) s x ↔ + DifferentiableWithinAt 𝕜 φ s x ∧ DifferentiableWithinAt 𝕜 φs s x := + differentiableWithinAt_finCons + +@[fun_prop] +theorem DifferentiableWithinAt.finCons + (h : DifferentiableWithinAt 𝕜 φ s x) (hs : DifferentiableWithinAt 𝕜 φs s x) : + DifferentiableWithinAt 𝕜 (fun x => Fin.cons (φ x) (φs x)) s x := + differentiableWithinAt_finCons'.mpr ⟨h, hs⟩ + +theorem differentiableAt_finCons : + DifferentiableAt 𝕜 (fun x => Fin.cons (φ x) (φs x)) x ↔ + DifferentiableAt 𝕜 φ x ∧ DifferentiableAt 𝕜 φs x := by + rw [differentiableAt_pi, Fin.forall_fin_succ, differentiableAt_pi] + simp only [Fin.cons_zero, Fin.cons_succ] + +/-- A variant of `differentiableAt_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem differentiableAt_finCons' : + DifferentiableAt 𝕜 (fun x => Fin.cons (φ x) (φs x)) x ↔ + DifferentiableAt 𝕜 φ x ∧ DifferentiableAt 𝕜 φs x := + differentiableAt_finCons + +@[fun_prop] +theorem DifferentiableAt.finCons + (h : DifferentiableAt 𝕜 φ x) (hs : DifferentiableAt 𝕜 φs x) : + DifferentiableAt 𝕜 (fun x => Fin.cons (φ x) (φs x)) x := + differentiableAt_finCons'.mpr ⟨h, hs⟩ + +theorem differentiableOn_finCons : + DifferentiableOn 𝕜 (fun x => Fin.cons (φ x) (φs x)) s ↔ + DifferentiableOn 𝕜 φ s ∧ DifferentiableOn 𝕜 φs s := by + rw [differentiableOn_pi, Fin.forall_fin_succ, differentiableOn_pi] + simp only [Fin.cons_zero, Fin.cons_succ] + +/-- A variant of `differentiableOn_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem differentiableOn_finCons' : + DifferentiableOn 𝕜 (fun x => Fin.cons (φ x) (φs x)) s ↔ + DifferentiableOn 𝕜 φ s ∧ DifferentiableOn 𝕜 φs s := + differentiableOn_finCons + +@[fun_prop] +theorem DifferentiableOn.finCons + (h : DifferentiableOn 𝕜 φ s) (hs : DifferentiableOn 𝕜 φs s) : + DifferentiableOn 𝕜 (fun x => Fin.cons (φ x) (φs x)) s := + differentiableOn_finCons'.mpr ⟨h, hs⟩ + +theorem differentiable_finCons : + Differentiable 𝕜 (fun x => Fin.cons (φ x) (φs x)) ↔ + Differentiable 𝕜 φ ∧ Differentiable 𝕜 φs := by + rw [differentiable_pi, Fin.forall_fin_succ, differentiable_pi] + simp only [Fin.cons_zero, Fin.cons_succ] + +/-- A variant of `differentiable_finCons` where the derivative variables are free on the RHS +instead. -/ +theorem differentiable_finCons' : + Differentiable 𝕜 (fun x => Fin.cons (φ x) (φs x)) ↔ + Differentiable 𝕜 φ ∧ Differentiable 𝕜 φs := + differentiable_finCons + +@[fun_prop] +theorem Differentiable.finCons + (h : Differentiable 𝕜 φ) (hs : Differentiable 𝕜 φs) : + Differentiable 𝕜 (fun x => Fin.cons (φ x) (φs x)) := + differentiable_finCons'.mpr ⟨h, hs⟩ + +-- TODO: write the `Fin.cons` versions of `fderivWithin_pi` and `fderiv_pi` + +end PiFin + end CartesianProduct end diff --git a/Mathlib/LinearAlgebra/Pi.lean b/Mathlib/LinearAlgebra/Pi.lean index 38d4beb411b38..c638022cfd82a 100644 --- a/Mathlib/LinearAlgebra/Pi.lean +++ b/Mathlib/LinearAlgebra/Pi.lean @@ -11,6 +11,7 @@ import Mathlib.Algebra.Module.Submodule.Ker import Mathlib.Algebra.Module.Submodule.Range import Mathlib.Algebra.Module.Equiv.Basic import Mathlib.Logic.Equiv.Fin +import Mathlib.LinearAlgebra.Prod /-! # Pi types of modules @@ -571,6 +572,17 @@ noncomputable def Function.ExtendByZero.linearMap : (ι → R) →ₗ[R] η → end Extend +variable (R) in +/-- `Fin.consEquiv` as a continuous linear equivalence. -/ +@[simps] +def Fin.consLinearEquiv + {n : ℕ} (M : Fin n.succ → Type*) [Semiring R] [∀ i, AddCommMonoid (M i)] [∀ i, Module R (M i)] : + (M 0 × Π i, M (Fin.succ i)) ≃ₗ[R] (Π i, M i) where + __ := Fin.consEquiv M + map_add' x y := funext <| Fin.cases rfl (by simp) + map_smul' c x := funext <| Fin.cases rfl (by simp) + + /-! ### Bundled versions of `Matrix.vecCons` and `Matrix.vecEmpty` The idea of these definitions is to be able to define a map as `x ↦ ![f₁ x, f₂ x, f₃ x]`, where @@ -604,14 +616,8 @@ theorem LinearMap.vecEmpty_apply (m : M) : (LinearMap.vecEmpty : M →ₗ[R] Fin /-- A linear map into `Fin n.succ → M₃` can be built out of a map into `M₃` and a map into `Fin n → M₃`. -/ -def LinearMap.vecCons {n} (f : M →ₗ[R] M₂) (g : M →ₗ[R] Fin n → M₂) : M →ₗ[R] Fin n.succ → M₂ where - toFun m := Matrix.vecCons (f m) (g m) - map_add' x y := by - simp only [] - rw [f.map_add, g.map_add, Matrix.cons_add_cons (f x)] - map_smul' c x := by - simp only [] - rw [f.map_smul, g.map_smul, RingHom.id_apply, Matrix.smul_cons c (f x)] +def LinearMap.vecCons {n} (f : M →ₗ[R] M₂) (g : M →ₗ[R] Fin n → M₂) : M →ₗ[R] Fin n.succ → M₂ := + Fin.consLinearEquiv R (fun _ : Fin n.succ => M₂) ∘ₗ f.prod g @[simp] theorem LinearMap.vecCons_apply {n} (f : M →ₗ[R] M₂) (g : M →ₗ[R] Fin n → M₂) (m : M) : diff --git a/Mathlib/Topology/Algebra/Module/Equiv.lean b/Mathlib/Topology/Algebra/Module/Equiv.lean index 9df3e155b17c7..faaa18273a54c 100644 --- a/Mathlib/Topology/Algebra/Module/Equiv.lean +++ b/Mathlib/Topology/Algebra/Module/Equiv.lean @@ -852,6 +852,28 @@ def piFinTwo (M : Fin 2 → Type*) [∀ i, AddCommMonoid (M i)] [∀ i, Module R def finTwoArrow : (Fin 2 → M) ≃L[R] M × M := { piFinTwo R fun _ => M with toLinearEquiv := LinearEquiv.finTwoArrow R M } +section +variable {n : ℕ} {R : Type*} {M : Fin n.succ → Type*} {N : Type*} +variable [Semiring R] +variable [∀ i, AddCommMonoid (M i)] [∀ i, Module R (M i)] [∀ i, TopologicalSpace (M i)] + +variable (R M) in +/-- `Fin.consEquiv` as a continuous linear equivalence. -/ +@[simps!] +def _root_.Fin.consEquivL : (M 0 × Π i, M (Fin.succ i)) ≃L[R] (Π i, M i) where + __ := Fin.consLinearEquiv R M + continuous_toFun := continuous_id.fst.finCons continuous_id.snd + continuous_invFun := .prod_mk (continuous_apply 0) (by continuity) + +/-- `Fin.cons` in the codomain of continuous linear maps. -/ +abbrev _root_.ContinuousLinearMap.finCons + [AddCommMonoid N] [Module R N] [TopologicalSpace N] + (f : N →L[R] M 0) (fs : N →L[R] Π i, M (Fin.succ i)) : + N →L[R] Π i, M i := + Fin.consEquivL R M ∘L f.prod fs + +end + end end ContinuousLinearEquiv From 69a0a8515e9293ea97edc4870b9feb523bc5edf3 Mon Sep 17 00:00:00 2001 From: John Talbot Date: Wed, 29 Jan 2025 23:20:56 +0000 Subject: [PATCH 654/681] feat(SimpleGraph/Coloring): a graph is 0-colorable iff it has no vertices (#21185) Co-authored-by: Lian Tattersall --- Mathlib/Combinatorics/SimpleGraph/Coloring.lean | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean index 54483becc0906..c0fa0618bf9ad 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Coloring.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Coloring.lean @@ -137,6 +137,10 @@ theorem isEmpty_of_colorable_zero (h : G.Colorable 0) : IsEmpty V := by obtain ⟨i, hi⟩ := h.some v exact Nat.not_lt_zero _ hi +@[simp] +lemma colorable_zero_iff : G.Colorable 0 ↔ IsEmpty V := + ⟨G.isEmpty_of_colorable_zero, fun _ ↦ G.colorable_of_isEmpty 0⟩ + /-- The "tautological" coloring of a graph, using the vertices of the graph as colors. -/ def selfColoring : G.Coloring V := Coloring.mk id fun {_ _} => G.ne_of_adj From 789550e90736dcfa660101d5b715fc3a64dd0265 Mon Sep 17 00:00:00 2001 From: Fabrizio Barroero Date: Wed, 29 Jan 2025 23:20:57 +0000 Subject: [PATCH 655/681] feat(NumberTheory/NumberField/FinitePlaces): change one lemma (#21187) `lemma one_lt_norm: 1 < (absNorm v.asIdeal : NNReal)` becomes ` lemma one_lt_norm_nnreal : 1 < (absNorm v.asIdeal : NNReal)` and we add `lemma one_lt_norm : 1 < absNorm v.asIdeal ` --- .../NumberField/FinitePlaces.lean | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Mathlib/NumberTheory/NumberField/FinitePlaces.lean b/Mathlib/NumberTheory/NumberField/FinitePlaces.lean index d030b4900a54c..5d5cf658791b0 100644 --- a/Mathlib/NumberTheory/NumberField/FinitePlaces.lean +++ b/Mathlib/NumberTheory/NumberField/FinitePlaces.lean @@ -25,7 +25,7 @@ into a completion of `K` associated to a non-zero prime ideal of `𝓞 K`. number field, places, finite places -/ -open Ideal IsDedekindDomain HeightOneSpectrum NumberField WithZeroMulInt +open Ideal IsDedekindDomain HeightOneSpectrum WithZeroMulInt namespace NumberField @@ -33,9 +33,8 @@ section absoluteValue variable {K : Type*} [Field K] [NumberField K] (v : HeightOneSpectrum (𝓞 K)) -/-- The norm of a maximal ideal as an element of `ℝ≥0` is `> 1` -/ -lemma one_lt_norm : 1 < (absNorm v.asIdeal : NNReal) := by - norm_cast +/-- The norm of a maximal ideal is `> 1` -/ +lemma one_lt_norm : 1 < absNorm v.asIdeal := by by_contra! h apply IsPrime.ne_top v.isPrime rw [← absNorm_eq_one_iff] @@ -44,7 +43,12 @@ lemma one_lt_norm : 1 < (absNorm v.asIdeal : NNReal) := by exact (v.asIdeal.fintypeQuotientOfFreeOfNeBot v.ne_bot).finite omega -private lemma norm_ne_zero : (absNorm v.asIdeal : NNReal) ≠ 0 := ne_zero_of_lt (one_lt_norm v) +/-- The norm of a maximal ideal as an element of `ℝ≥0` is `> 1` -/ +lemma one_lt_norm_nnreal : 1 < (absNorm v.asIdeal : NNReal) := mod_cast one_lt_norm v + +/-- The norm of a maximal ideal as an element of `ℝ≥0` is `≠ 0` -/ +lemma norm_ne_zero : (absNorm v.asIdeal : NNReal) ≠ 0 := + ne_zero_of_lt (one_lt_norm_nnreal v) /-- The `v`-adic absolute value on `K` defined as the norm of `v` raised to negative `v`-adic valuation.-/ @@ -57,7 +61,7 @@ noncomputable def vadicAbv : AbsoluteValue K ℝ where -- the triangle inequality is implied by the ultrametric one apply le_trans _ <| max_le_add_of_nonneg (zero_le ((toNNReal (norm_ne_zero v)) (v.valuation x))) (zero_le ((toNNReal (norm_ne_zero v)) (v.valuation y))) - have h_mono := (toNNReal_strictMono (one_lt_norm v)).monotone + have h_mono := (toNNReal_strictMono (one_lt_norm_nnreal v)).monotone rw [← h_mono.map_max] --max goes inside withZeroMultIntToNNReal exact h_mono (v.valuation.map_add x y) @@ -80,7 +84,7 @@ noncomputable instance instRankOneValuedAdicCompletion : map_one' := rfl map_mul' := MonoidWithZeroHom.map_mul (toNNReal (norm_ne_zero v)) } - strictMono' := toNNReal_strictMono (one_lt_norm v) + strictMono' := toNNReal_strictMono (one_lt_norm_nnreal v) nontrivial' := by rcases Submodule.exists_mem_ne_zero_of_ne_bot v.ne_bot with ⟨x, hx1, hx2⟩ use (x : K) @@ -133,19 +137,19 @@ open FinitePlace /-- The `v`-adic norm of an integer is at most 1. -/ theorem norm_le_one (x : 𝓞 K) : ‖embedding v x‖ ≤ 1 := by - rw [norm_def', NNReal.coe_le_one, toNNReal_le_one_iff (one_lt_norm v)] + rw [norm_def', NNReal.coe_le_one, toNNReal_le_one_iff (one_lt_norm_nnreal v)] exact valuation_le_one v x /-- The `v`-adic norm of an integer is 1 if and only if it is not in the ideal. -/ theorem norm_eq_one_iff_not_mem (x : 𝓞 K) : ‖(embedding v) x‖ = 1 ↔ x ∉ v.asIdeal := by rw [norm_def_int, NNReal.coe_eq_one, toNNReal_eq_one_iff (v.intValuationDef x) - (norm_ne_zero v) (one_lt_norm v).ne', ← dvd_span_singleton, + (norm_ne_zero v) (one_lt_norm_nnreal v).ne', ← dvd_span_singleton, ← intValuation_lt_one_iff_dvd, not_lt] exact (intValuation_le_one v x).ge_iff_eq.symm /-- The `v`-adic norm of an integer is less than 1 if and only if it is in the ideal. -/ theorem norm_lt_one_iff_mem (x : 𝓞 K) : ‖embedding v x‖ < 1 ↔ x ∈ v.asIdeal := by - rw [norm_def_int, NNReal.coe_lt_one, toNNReal_lt_one_iff (one_lt_norm v), + rw [norm_def_int, NNReal.coe_lt_one, toNNReal_lt_one_iff (one_lt_norm_nnreal v), intValuation_lt_one_iff_dvd] exact dvd_span_singleton @@ -265,9 +269,9 @@ lemma embedding_mul_absNorm (v : HeightOneSpectrum (𝓞 K)) {x : 𝓞 K} (h_x_n WithZeroMulInt.toNNReal_neg_apply _ (v.valuation.ne_zero_iff.mpr (RingOfIntegers.coe_ne_zero_iff.mpr h_x_nezero))] push_cast - rw [← zpow_natCast, ← zpow_add₀ <| mod_cast (zero_lt_one.trans (one_lt_norm v)).ne'] + rw [← zpow_natCast, ← zpow_add₀ <| mod_cast (zero_lt_one.trans (one_lt_norm_nnreal v)).ne'] norm_cast - rw [zpow_eq_one_iff_right₀ (Nat.cast_nonneg' _) (mod_cast (one_lt_norm v).ne')] + rw [zpow_eq_one_iff_right₀ (Nat.cast_nonneg' _) (mod_cast (one_lt_norm_nnreal v).ne')] simp [valuation_eq_intValuationDef, intValuationDef_if_neg, h_x_nezero] end IsDedekindDomain.HeightOneSpectrum From 34763b00f636fdc06fa1f8676c408bbac3db7a53 Mon Sep 17 00:00:00 2001 From: "Yury G. Kudryashov" Date: Wed, 29 Jan 2025 23:20:58 +0000 Subject: [PATCH 656/681] chore(Order/SupIndep): review API (#21235) --- .../Eigenspace/Triangularizable.lean | 2 +- Mathlib/Order/SupIndep.lean | 109 +++++------------- 2 files changed, 32 insertions(+), 79 deletions(-) diff --git a/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean b/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean index fcb07a9d441a2..aa94d3765c668 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean @@ -219,7 +219,7 @@ theorem inf_iSup_genEigenspace [FiniteDimensional K V] (h : ∀ x ∈ p, f x ∈ rw [Algebra.algebraMap_eq_smul_one, ← End.genEigenspace_nat] apply aux μ' hμ' · have := this.supIndep' (m.support.erase μ) - apply Finset.supIndep_antimono_fun _ this + apply this.antitone_fun intro μ' hμ' rw [Algebra.algebraMap_eq_smul_one, ← End.genEigenspace_nat] apply aux μ' hμ' diff --git a/Mathlib/Order/SupIndep.lean b/Mathlib/Order/SupIndep.lean index 3642adc8ce776..4895b49790087 100644 --- a/Mathlib/Order/SupIndep.lean +++ b/Mathlib/Order/SupIndep.lean @@ -86,6 +86,7 @@ theorem SupIndep.subset (ht : t.SupIndep f) (h : s ⊆ t) : s.SupIndep f := fun theorem supIndep_empty (f : ι → α) : (∅ : Finset ι).SupIndep f := fun _ _ a ha => (not_mem_empty a ha).elim +@[simp] theorem supIndep_singleton (i : ι) (f : ι → α) : ({i} : Finset ι).SupIndep f := fun s hs j hji hj => by rw [eq_empty_of_ssubset_singleton ⟨hs, fun h => hj (h hji)⟩, sup_empty] @@ -95,47 +96,28 @@ theorem SupIndep.pairwiseDisjoint (hs : s.SupIndep f) : (s : Set ι).PairwiseDis fun _ ha _ hb hab => sup_singleton.subst <| hs (singleton_subset_iff.2 hb) ha <| not_mem_singleton.2 hab +@[deprecated (since := "2025-01-17")] alias sup_indep.pairwise_disjoint := SupIndep.pairwiseDisjoint + theorem SupIndep.le_sup_iff (hs : s.SupIndep f) (hts : t ⊆ s) (hi : i ∈ s) (hf : ∀ i, f i ≠ ⊥) : f i ≤ t.sup f ↔ i ∈ t := by refine ⟨fun h => ?_, le_sup⟩ by_contra hit exact hf i (disjoint_self.1 <| (hs hts hi hit).mono_right h) -theorem supIndep_antimono_fun {g : ι → α} (h : ∀ x ∈ s, f x ≤ g x) (h : s.SupIndep g) : - s.SupIndep f := by - classical - induction s using Finset.induction_on with - | empty => apply Finset.supIndep_empty - | @insert i s his IH => - rename_i hle - rw [Finset.supIndep_iff_disjoint_erase] at h ⊢ - intro j hj - simp_all only [Finset.mem_insert, or_true, implies_true, true_implies, forall_eq_or_imp, - Finset.erase_insert_eq_erase, not_false_eq_true, Finset.erase_eq_of_not_mem] - obtain rfl | hj := hj - · simp only [Finset.erase_insert_eq_erase] - apply h.left.mono hle.left - apply (Finset.sup_mono _).trans (Finset.sup_mono_fun hle.right) - exact Finset.erase_subset _ _ - · apply (h.right j hj).mono (hle.right j hj) (Finset.sup_mono_fun _) - intro k hk - simp only [Finset.mem_erase, ne_eq, Finset.mem_insert] at hk - obtain ⟨-, rfl | hk⟩ := hk - · exact hle.left - · exact hle.right k hk - -theorem SupIndep.image [DecidableEq ι] {s : Finset ι'} {g : ι' → ι} (hs : s.SupIndep (f ∘ g)) : - (s.image g).SupIndep f := by +theorem SupIndep.antitone_fun {g : ι → α} (hle : ∀ x ∈ s, f x ≤ g x) (h : s.SupIndep g) : + s.SupIndep f := fun _t hts i his hit ↦ + (h hts his hit).mono (hle i his) <| Finset.sup_mono_fun fun x hx ↦ hle x <| hts hx + +@[deprecated (since := "2025-01-17")] +alias supIndep_antimono_fun := SupIndep.antitone_fun + +protected theorem SupIndep.image [DecidableEq ι] {s : Finset ι'} {g : ι' → ι} + (hs : s.SupIndep (f ∘ g)) : (s.image g).SupIndep f := by intro t ht i hi hit - rw [mem_image] at hi - obtain ⟨i, hi, rfl⟩ := hi - haveI : DecidableEq ι' := Classical.decEq _ - suffices hts : t ⊆ (s.erase i).image g by - refine (supIndep_iff_disjoint_erase.1 hs i hi).mono_right ((sup_mono hts).trans ?_) - rw [sup_image] - rintro j hjt - obtain ⟨j, hj, rfl⟩ := mem_image.1 (ht hjt) - exact mem_image_of_mem _ (mem_erase.2 ⟨ne_of_apply_ne g (ne_of_mem_of_not_mem hjt hit), hj⟩) + rcases subset_image_iff.mp ht with ⟨t, hts, rfl⟩ + rcases mem_image.mp hi with ⟨i, his, rfl⟩ + rw [sup_image] + exact hs hts his (hit <| mem_image_of_mem _ ·) theorem supIndep_map {s : Finset ι'} {g : ι' ↪ ι} : (s.map g).SupIndep f ↔ s.SupIndep (f ∘ g) := by refine ⟨fun hs t ht i hi hit => ?_, fun hs => ?_⟩ @@ -147,24 +129,11 @@ theorem supIndep_map {s : Finset ι'} {g : ι' ↪ ι} : (s.map g).SupIndep f @[simp] theorem supIndep_pair [DecidableEq ι] {i j : ι} (hij : i ≠ j) : - ({i, j} : Finset ι).SupIndep f ↔ Disjoint (f i) (f j) := - ⟨fun h => h.pairwiseDisjoint (by simp) (by simp) hij, - fun h => by - rw [supIndep_iff_disjoint_erase] - intro k hk - rw [Finset.mem_insert, Finset.mem_singleton] at hk - obtain rfl | rfl := hk - · convert h using 1 - rw [Finset.erase_insert, Finset.sup_singleton] - simpa using hij - · convert h.symm using 1 - have : ({i, k} : Finset ι).erase k = {i} := by - ext - rw [mem_erase, mem_insert, mem_singleton, mem_singleton, and_or_left, Ne, - not_and_self_iff, or_false, and_iff_right_of_imp] - rintro rfl - exact hij - rw [this, Finset.sup_singleton]⟩ + ({i, j} : Finset ι).SupIndep f ↔ Disjoint (f i) (f j) := by + suffices Disjoint (f i) (f j) → Disjoint (f j) ((Finset.erase {i, j} j).sup f) by + simpa [supIndep_iff_disjoint_erase, hij] + rw [pair_comm] + simp [hij.symm, disjoint_comm] theorem supIndep_univ_bool (f : Bool → α) : (Finset.univ : Finset Bool).SupIndep f ↔ Disjoint (f false) (f true) := @@ -174,29 +143,14 @@ theorem supIndep_univ_bool (f : Bool → α) : @[simp] theorem supIndep_univ_fin_two (f : Fin 2 → α) : (Finset.univ : Finset (Fin 2)).SupIndep f ↔ Disjoint (f 0) (f 1) := - haveI : (0 : Fin 2) ≠ 1 := by simp + have : (0 : Fin 2) ≠ 1 := by simp supIndep_pair this -theorem SupIndep.attach (hs : s.SupIndep f) : s.attach.SupIndep fun a => f a := by - intro t _ i _ hi - classical - have : (fun (a : { x // x ∈ s }) => f ↑a) = f ∘ (fun a : { x // x ∈ s } => ↑a) := rfl - rw [this, ← Finset.sup_image] - refine hs (image_subset_iff.2 fun (j : { x // x ∈ s }) _ => j.2) i.2 fun hi' => hi ?_ - rw [mem_image] at hi' - obtain ⟨j, hj, hji⟩ := hi' - rwa [Subtype.ext hji] at hj - @[simp] theorem supIndep_attach : (s.attach.SupIndep fun a => f a) ↔ s.SupIndep f := by - refine ⟨fun h t ht i his hit => ?_, SupIndep.attach⟩ - classical - convert h (filter_subset (fun (i : { x // x ∈ s }) => (i : ι) ∈ t) _) (mem_attach _ ⟨i, ‹_›⟩) - fun hi => hit <| by simpa using hi using 1 - refine eq_of_forall_ge_iff ?_ - simp only [Finset.sup_le_iff, mem_filter, mem_attach, true_and, Function.comp_apply, - Subtype.forall, Subtype.coe_mk] - exact fun a => forall_congr' fun j => ⟨fun h _ => h, fun h hj => h (ht hj) hj⟩ + simpa [Finset.attach_map_val] using (supIndep_map (s := s.attach) (g := .subtype _)).symm + +alias ⟨_, SupIndep.attach⟩ := supIndep_attach end Lattice @@ -208,11 +162,10 @@ theorem supIndep_iff_pairwiseDisjoint : s.SupIndep f ↔ (s : Set ι).PairwiseDi ⟨SupIndep.pairwiseDisjoint, fun hs _ ht _ hi hit => Finset.disjoint_sup_right.2 fun _ hj => hs hi (ht hj) (ne_of_mem_of_not_mem hj hit).symm⟩ -alias ⟨sup_indep.pairwise_disjoint, _root_.Set.PairwiseDisjoint.supIndep⟩ := - supIndep_iff_pairwiseDisjoint +alias ⟨_, _root_.Set.PairwiseDisjoint.supIndep⟩ := supIndep_iff_pairwiseDisjoint /-- Bind operation for `SupIndep`. -/ -theorem SupIndep.sup [DecidableEq ι] {s : Finset ι'} {g : ι' → Finset ι} {f : ι → α} +protected theorem SupIndep.sup [DecidableEq ι] {s : Finset ι'} {g : ι' → Finset ι} {f : ι → α} (hs : s.SupIndep fun i => (g i).sup f) (hg : ∀ i' ∈ s, (g i').SupIndep f) : (s.sup g).SupIndep f := by simp_rw [supIndep_iff_pairwiseDisjoint] at hs hg ⊢ @@ -220,15 +173,15 @@ theorem SupIndep.sup [DecidableEq ι] {s : Finset ι'} {g : ι' → Finset ι} { exact hs.biUnion_finset hg /-- Bind operation for `SupIndep`. -/ -theorem SupIndep.biUnion [DecidableEq ι] {s : Finset ι'} {g : ι' → Finset ι} {f : ι → α} +protected theorem SupIndep.biUnion [DecidableEq ι] {s : Finset ι'} {g : ι' → Finset ι} {f : ι → α} (hs : s.SupIndep fun i => (g i).sup f) (hg : ∀ i' ∈ s, (g i').SupIndep f) : (s.biUnion g).SupIndep f := by rw [← sup_eq_biUnion] exact hs.sup hg /-- Bind operation for `SupIndep`. -/ -theorem SupIndep.sigma {β : ι → Type*} {s : Finset ι} {g : ∀ i, Finset (β i)} {f : Sigma β → α} - (hs : s.SupIndep fun i => (g i).sup fun b => f ⟨i, b⟩) +protected theorem SupIndep.sigma {β : ι → Type*} {s : Finset ι} {g : ∀ i, Finset (β i)} + {f : Sigma β → α} (hs : s.SupIndep fun i => (g i).sup fun b => f ⟨i, b⟩) (hg : ∀ i ∈ s, (g i).SupIndep fun b => f ⟨i, b⟩) : (s.sigma g).SupIndep f := by rintro t ht ⟨i, b⟩ hi hit rw [Finset.disjoint_sup_right] @@ -242,7 +195,7 @@ theorem SupIndep.sigma {β : ι → Type*} {s : Finset ι} {g : ∀ i, Finset ( · convert le_sup (α := α) hi.2; simp · convert le_sup (α := α) hj.2; simp -theorem SupIndep.product {s : Finset ι} {t : Finset ι'} {f : ι × ι' → α} +protected theorem SupIndep.product {s : Finset ι} {t : Finset ι'} {f : ι × ι' → α} (hs : s.SupIndep fun i => t.sup fun i' => f (i, i')) (ht : t.SupIndep fun i' => s.sup fun i => f (i, i')) : (s ×ˢ t).SupIndep f := by rintro u hu ⟨i, i'⟩ hi hiu From 2ae8c98d00ee17646cdea2d980888655d47c9357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Dupuis?= Date: Wed, 29 Jan 2025 23:58:53 +0000 Subject: [PATCH 657/681] =?UTF-8?q?feat(CStarAlgebra):=20matrices=20with?= =?UTF-8?q?=20entries=20in=20a=20C=E2=8B=86-algebra=20(#15277)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR creates the type `CstarMatrix m n A` as a copy of `Matrix m n A` meant for the case where `A` is a C⋆-algebra. Most notably, we show that square matrices with entries in a C⋆-algebra form a C⋆-algebra. - [x] depends on: #15244 - [x] depends on: #15274 Co-authored-by: Frédéric Dupuis <31101893+dupuisf@users.noreply.github.com> --- Mathlib.lean | 1 + .../Analysis/CStarAlgebra/CStarMatrix.lean | 684 ++++++++++++++++++ .../CStarAlgebra/Module/Constructions.lean | 7 + .../Analysis/CStarAlgebra/Module/Synonym.lean | 54 +- Mathlib/Data/Finset/Lattice/Fold.lean | 5 + Mathlib/Topology/Instances/Matrix.lean | 49 +- 6 files changed, 769 insertions(+), 31 deletions(-) create mode 100644 Mathlib/Analysis/CStarAlgebra/CStarMatrix.lean diff --git a/Mathlib.lean b/Mathlib.lean index 520a3ec30a90c..f62f59976932f 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1169,6 +1169,7 @@ import Mathlib.Analysis.BoxIntegral.Partition.Tagged import Mathlib.Analysis.BoxIntegral.UnitPartition import Mathlib.Analysis.CStarAlgebra.ApproximateUnit import Mathlib.Analysis.CStarAlgebra.Basic +import Mathlib.Analysis.CStarAlgebra.CStarMatrix import Mathlib.Analysis.CStarAlgebra.Classes import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances diff --git a/Mathlib/Analysis/CStarAlgebra/CStarMatrix.lean b/Mathlib/Analysis/CStarAlgebra/CStarMatrix.lean new file mode 100644 index 0000000000000..27bbb72bc3611 --- /dev/null +++ b/Mathlib/Analysis/CStarAlgebra/CStarMatrix.lean @@ -0,0 +1,684 @@ +/- +Copyright (c) 2025 Frédéric Dupuis. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Frédéric Dupuis +-/ + +import Mathlib.Analysis.CStarAlgebra.Module.Constructions +import Mathlib.Analysis.Matrix +import Mathlib.Topology.UniformSpace.Matrix + +/-! +# Matrices with entries in a C⋆-algebra + +This file creates a type copy of `Matrix m n A` called `CStarMatrix m n A` meant for matrices with +entries in a C⋆-algebra `A`. Its action on `C⋆ᵐᵒᵈ (n → A)` (via `Matrix.mulVec`) gives +it the operator norm, and this norm makes `CStarMatrix n n A` a C⋆-algebra. + +## Main declarations + ++ `CStarMatrix m n A`: the type copy ++ `CStarMatrix.instNonUnitalCStarAlgebra`: square matrices with entries in a non-unital C⋆-algebra + form a non-unital C⋆-algebra ++ `CStarMatrix.instCStarAlgebra`: square matrices with entries in a unital C⋆-algebra form a + unital C⋆-algebra + +## Implementation notes + +The norm on this type induces the product uniformity and bornology, but these are not defeq to +`Pi.uniformSpace` and `Pi.instBornology`. Hence, we prove the equality to the Pi instances and +replace the uniformity and bornology by the Pi ones when registering the +`NormedAddCommGroup (CStarMatrix m n A)` instance. See the docstring of the `TopologyAux` section +below for more details. +-/ + +open scoped ComplexOrder Topology Uniformity Bornology Matrix NNReal InnerProductSpace + WithCStarModule + +/-- Type copy `Matrix m n A` meant for matrices with entries in a C⋆-algebra. This is +a C⋆-algebra when `m = n`. -/ +def CStarMatrix (m : Type*) (n : Type*) (A : Type*) := Matrix m n A + +namespace CStarMatrix + +variable {m n A B R S : Type*} + +section basic + +variable (m n A) in +/-- The equivalence between `Matrix m n A` and `CStarMatrix m n A`. -/ +def ofMatrix {m n A : Type*} : Matrix m n A ≃ CStarMatrix m n A := Equiv.refl _ + +@[simp] +lemma ofMatrix_apply {M : Matrix m n A} {i : m} : (ofMatrix M) i = M i := rfl + +@[simp] +lemma ofMatrix_symm_apply {M : CStarMatrix m n A} {i : m} : (ofMatrix.symm M) i = M i := rfl + +theorem ext_iff {M N : CStarMatrix m n A} : (∀ i j, M i j = N i j) ↔ M = N := + ⟨fun h => funext fun i => funext <| h i, fun h => by simp [h]⟩ + +@[ext] +lemma ext {M₁ M₂ : CStarMatrix m n A} (h : ∀ i j, M₁ i j = M₂ i j) : M₁ = M₂ := ext_iff.mp h + +/-- `M.map f` is the matrix obtained by applying `f` to each entry of the matrix `M`. -/ +def map (M : CStarMatrix m n A) (f : A → B) : CStarMatrix m n B := + ofMatrix fun i j => f (M i j) + +@[simp] +theorem map_apply {M : CStarMatrix m n A} {f : A → B} {i : m} {j : n} : M.map f i j = f (M i j) := + rfl + +@[simp] +theorem map_id (M : CStarMatrix m n A) : M.map id = M := by + ext + rfl + +@[simp] +theorem map_id' (M : CStarMatrix m n A) : M.map (·) = M := map_id M + +theorem map_map {C : Type*} {M : Matrix m n A} {f : A → B} {g : B → C} : + (M.map f).map g = M.map (g ∘ f) := by ext; rfl + +theorem map_injective {f : A → B} (hf : Function.Injective f) : + Function.Injective fun M : CStarMatrix m n A => M.map f := fun _ _ h => + ext fun i j => hf <| ext_iff.mpr h i j + +/-- The transpose of a matrix. -/ +def transpose (M : CStarMatrix m n A) : CStarMatrix n m A := + ofMatrix fun x y => M y x + +@[simp] +theorem transpose_apply (M : CStarMatrix m n A) (i j) : transpose M i j = M j i := + rfl + +/-- The conjugate transpose of a matrix defined in term of `star`. -/ +def conjTranspose [Star A] (M : CStarMatrix m n A) : CStarMatrix n m A := + M.transpose.map star + +instance instStar [Star A] : Star (CStarMatrix n n A) where + star M := M.conjTranspose + +instance instInvolutiveStar [InvolutiveStar A] : InvolutiveStar (CStarMatrix n n A) where + star_involutive := star_involutive (R := Matrix n n A) + +instance instInhabited [Inhabited A] : Inhabited (CStarMatrix m n A) := + inferInstanceAs <| Inhabited <| m → n → A + +instance instDecidableEq [DecidableEq A] [Fintype m] [Fintype n] : + DecidableEq (CStarMatrix m n A) := + Fintype.decidablePiFintype + +instance {n m} [Fintype m] [DecidableEq m] [Fintype n] [DecidableEq n] (α) [Fintype α] : + Fintype (CStarMatrix m n α) := inferInstanceAs (Fintype (m → n → α)) + +instance {n m} [Finite m] [Finite n] (α) [Finite α] : + Finite (CStarMatrix m n α) := inferInstanceAs (Finite (m → n → α)) + +instance instAdd [Add A] : Add (CStarMatrix m n A) := + Pi.instAdd + +instance instAddSemigroup [AddSemigroup A] : AddSemigroup (CStarMatrix m n A) := + Pi.addSemigroup + +instance instAddCommSemigroup [AddCommSemigroup A] : AddCommSemigroup (CStarMatrix m n A) := + Pi.addCommSemigroup + +instance instZero [Zero A] : Zero (CStarMatrix m n A) := + Pi.instZero + +instance instAddZeroClass [AddZeroClass A] : AddZeroClass (CStarMatrix m n A) := + Pi.addZeroClass + +instance instAddMonoid [AddMonoid A] : AddMonoid (CStarMatrix m n A) := + Pi.addMonoid + +instance instAddCommMonoid [AddCommMonoid A] : AddCommMonoid (CStarMatrix m n A) := + Pi.addCommMonoid + +instance instNeg [Neg A] : Neg (CStarMatrix m n A) := + Pi.instNeg + +instance instSub [Sub A] : Sub (CStarMatrix m n A) := + Pi.instSub + +instance instAddGroup [AddGroup A] : AddGroup (CStarMatrix m n A) := + Pi.addGroup + +instance instAddCommGroup [AddCommGroup A] : AddCommGroup (CStarMatrix m n A) := + Pi.addCommGroup + +instance instUnique [Unique A] : Unique (CStarMatrix m n A) := + Pi.unique + +instance instSubsingleton [Subsingleton A] : Subsingleton (CStarMatrix m n A) := + inferInstanceAs <| Subsingleton <| m → n → A + +instance instNontrivial [Nonempty m] [Nonempty n] [Nontrivial A] : Nontrivial (CStarMatrix m n A) := + Function.nontrivial + +instance instSMul [SMul R A] : SMul R (CStarMatrix m n A) := + Pi.instSMul + +instance instSMulCommClass [SMul R A] [SMul S A] [SMulCommClass R S A] : + SMulCommClass R S (CStarMatrix m n A) := + Pi.smulCommClass + +instance instIsScalarTower [SMul R S] [SMul R A] [SMul S A] [IsScalarTower R S A] : + IsScalarTower R S (CStarMatrix m n A) := + Pi.isScalarTower + +instance instIsCentralScalar [SMul R A] [SMul Rᵐᵒᵖ A] [IsCentralScalar R A] : + IsCentralScalar R (CStarMatrix m n A) := + Pi.isCentralScalar + +instance instMulAction [Monoid R] [MulAction R A] : MulAction R (CStarMatrix m n A) := + Pi.mulAction _ + +instance instDistribMulAction [Monoid R] [AddMonoid A] [DistribMulAction R A] : + DistribMulAction R (CStarMatrix m n A) := + Pi.distribMulAction _ + +instance instModule [Semiring R] [AddCommMonoid A] [Module R A] : Module R (CStarMatrix m n A) := + Pi.module _ _ _ + +@[simp, nolint simpNF] +theorem zero_apply [Zero A] (i : m) (j : n) : (0 : CStarMatrix m n A) i j = 0 := rfl + +@[simp] theorem add_apply [Add A] (M N : CStarMatrix m n A) (i : m) (j : n) : + (M + N) i j = (M i j) + (N i j) := rfl + +@[simp] theorem smul_apply [SMul B A] (r : B) (M : Matrix m n A) (i : m) (j : n) : + (r • M) i j = r • (M i j) := rfl + +@[simp] theorem sub_apply [Sub A] (M N : Matrix m n A) (i : m) (j : n) : + (M - N) i j = (M i j) - (N i j) := rfl + +@[simp] theorem neg_apply [Neg A] (M : Matrix m n A) (i : m) (j : n) : + (-M) i j = -(M i j) := rfl + +/-! simp-normal form pulls `of` to the outside, to match the `Matrix` API. -/ + +@[simp] theorem of_zero [Zero A] : ofMatrix (0 : Matrix m n A) = 0 := rfl + +@[simp] theorem of_add_of [Add A] (f g : Matrix m n A) : + ofMatrix f + ofMatrix g = ofMatrix (f + g) := rfl + +@[simp] +theorem of_sub_of [Sub A] (f g : Matrix m n A) : ofMatrix f - ofMatrix g = ofMatrix (f - g) := + rfl + +@[simp] theorem neg_of [Neg A] (f : Matrix m n A) : -ofMatrix f = ofMatrix (-f) := rfl + +@[simp] theorem smul_of [SMul R A] (r : R) (f : Matrix m n A) : + r • ofMatrix f = ofMatrix (r • f) := rfl + +instance instStarAddMonoid [AddMonoid A] [StarAddMonoid A] : StarAddMonoid (CStarMatrix n n A) where + star_add := star_add (R := Matrix n n A) + +instance instStarModule [Star R] [Star A] [SMul R A] [StarModule R A] : + StarModule R (CStarMatrix n n A) where + star_smul := star_smul (A := Matrix n n A) + +/-- The equivalence to matrices, bundled as a linear equivalence. -/ +def ofMatrixₗ [AddCommMonoid A] [Semiring R] [Module R A] : + (Matrix m n A) ≃ₗ[R] CStarMatrix m n A := LinearEquiv.refl _ _ + +section zero_one + +variable [Zero A] [One A] [DecidableEq n] + +instance instOne : One (CStarMatrix n n A) := inferInstanceAs <| One (Matrix n n A) + +theorem one_apply {i j} : (1 : CStarMatrix n n A) i j = if i = j then 1 else 0 := rfl + +@[simp] +theorem one_apply_eq (i) : (1 : CStarMatrix n n A) i i = 1 := Matrix.one_apply_eq _ + +@[simp] theorem one_apply_ne {i j} : i ≠ j → (1 : CStarMatrix n n A) i j = 0 := Matrix.one_apply_ne + +theorem one_apply_ne' {i j} : j ≠ i → (1 : CStarMatrix n n A) i j = 0 := Matrix.one_apply_ne' + +instance instAddMonoidWithOne [AddMonoidWithOne A] : AddMonoidWithOne (CStarMatrix n n A) where + +instance instAddGroupWithOne [AddGroupWithOne A] : AddGroupWithOne (CStarMatrix n n A) where + __ := instAddGroup + __ := instAddMonoidWithOne + +instance instAddCommMonoidWithOne [AddCommMonoidWithOne A] : + AddCommMonoidWithOne (CStarMatrix n n A) where + __ := instAddCommMonoid + __ := instAddMonoidWithOne + +instance instAddCommGroupWithOne [AddCommGroupWithOne A] : + AddCommGroupWithOne (CStarMatrix n n A) where + __ := instAddCommGroup + __ := instAddGroupWithOne + +-- We want to be lower priority than `instHMul`, but without this we can't have operands with +-- implicit dimensions. +@[default_instance 100] +instance {l : Type*} [Fintype m] [Mul A] [AddCommMonoid A] : + HMul (CStarMatrix l m A) (CStarMatrix m n A) (CStarMatrix l n A) where + hMul M N := ofMatrix (ofMatrix.symm M * ofMatrix.symm N) + +instance [Fintype n] [Mul A] [AddCommMonoid A] : Mul (CStarMatrix n n A) where mul M N := M * N + +end zero_one + +theorem mul_apply {l : Type*} [Fintype m] [Mul A] [AddCommMonoid A] {M : CStarMatrix l m A} + {N : CStarMatrix m n A} {i k} : (M * N) i k = ∑ j, M i j * N j k := rfl + +theorem mul_apply' {l : Type*} [Fintype m] [Mul A] [AddCommMonoid A] {M : CStarMatrix l m A} + {N : CStarMatrix m n A} {i k} : (M * N) i k = (fun j => M i j) ⬝ᵥ fun j => N j k := rfl + +@[simp] +theorem smul_mul {l : Type*} [Fintype n] [Monoid R] [AddCommMonoid A] [Mul A] [DistribMulAction R A] + [IsScalarTower R A A] (a : R) (M : CStarMatrix m n A) (N : CStarMatrix n l A) : + (a • M) * N = a • (M * N) := Matrix.smul_mul a M N + +theorem mul_smul {l : Type*} [Fintype n] [Monoid R] [AddCommMonoid A] [Mul A] [DistribMulAction R A] + [SMulCommClass R A A] (M : Matrix m n A) (a : R) (N : Matrix n l A) : + M * (a • N) = a • (M * N) := Matrix.mul_smul M a N + +instance instNonUnitalNonAssocSemiring [Fintype n] [NonUnitalNonAssocSemiring A] : + NonUnitalNonAssocSemiring (CStarMatrix n n A) := + inferInstanceAs <| NonUnitalNonAssocSemiring (Matrix n n A) + +instance instNonUnitalNonAssocRing [Fintype n] [NonUnitalNonAssocRing A] : + NonUnitalNonAssocRing (CStarMatrix n n A) := + inferInstanceAs <| NonUnitalNonAssocRing (Matrix n n A) + +instance instNonUnitalSemiring [Fintype n] [NonUnitalSemiring A] : + NonUnitalSemiring (CStarMatrix n n A) := + inferInstanceAs <| NonUnitalSemiring (Matrix n n A) + +instance instNonAssocSemiring [Fintype n] [DecidableEq n] [NonAssocSemiring A] : + NonAssocSemiring (CStarMatrix n n A) := + inferInstanceAs <| NonAssocSemiring (Matrix n n A) + +instance instNonUnitalRing [Fintype n] [NonUnitalRing A] : + NonUnitalRing (CStarMatrix n n A) := + inferInstanceAs <| NonUnitalRing (Matrix n n A) + +instance instNonAssocRing [Fintype n] [DecidableEq n] [NonAssocRing A] : + NonAssocRing (CStarMatrix n n A) := + inferInstanceAs <| NonAssocRing (Matrix n n A) + +instance instSemiring [Fintype n] [DecidableEq n] [Semiring A] : + Semiring (CStarMatrix n n A) := + inferInstanceAs <| Semiring (Matrix n n A) + +instance instRing [Fintype n] [DecidableEq n] [Ring A] : Ring (CStarMatrix n n A) := + inferInstanceAs <| Ring (Matrix n n A) + +/-- `ofMatrix` bundled as a ring equivalence. -/ +def ofMatrixRingEquiv [Fintype n] [Semiring A] : + Matrix n n A ≃+* CStarMatrix n n A := + { ofMatrix with + map_mul' := fun _ _ => rfl + map_add' := fun _ _ => rfl } + +instance instStarRing [Fintype n] [NonUnitalSemiring A] [StarRing A] : + StarRing (CStarMatrix n n A) := inferInstanceAs <| StarRing (Matrix n n A) + +instance instAlgebra [Fintype n] [DecidableEq n] [CommSemiring R] [Semiring A] [Algebra R A] : + Algebra R (CStarMatrix n n A) := inferInstanceAs <| Algebra R (Matrix n n A) + +/-- `ofMatrix` bundled as a star algebra equivalence. -/ +def ofMatrixStarAlgEquiv [Fintype n] [SMul ℂ A] [Semiring A] [StarRing A] : + Matrix n n A ≃⋆ₐ[ℂ] CStarMatrix n n A := + { ofMatrixRingEquiv with + map_star' := fun _ => rfl + map_smul' := fun _ _ => rfl } + +lemma ofMatrix_eq_ofMatrixStarAlgEquiv [Fintype n] [SMul ℂ A] [Semiring A] [StarRing A] : + (ofMatrix : Matrix n n A → CStarMatrix n n A) + = (ofMatrixStarAlgEquiv : Matrix n n A → CStarMatrix n n A) := rfl + +end basic + +variable [Fintype m] [Fintype n] [NonUnitalCStarAlgebra A] [PartialOrder A] [StarOrderedRing A] + + +/-- Interpret a `CStarMatrix m n A` as a continuous linear map acting on `C⋆ᵐᵒᵈ (n → A)`. -/ +def toCLM : CStarMatrix m n A →ₗ[ℂ] (C⋆ᵐᵒᵈ (n → A)) →L[ℂ] (C⋆ᵐᵒᵈ (m → A)) where + toFun M := { toFun := (WithCStarModule.equivL ℂ).symm ∘ M.mulVec ∘ WithCStarModule.equivL ℂ + map_add' := M.mulVec_add + map_smul' := M.mulVec_smul + cont := by + simp only [LinearMap.coe_mk, AddHom.coe_mk] + exact Continuous.comp (by fun_prop) (by fun_prop) } + map_add' M₁ M₂ := by + ext + simp only [ContinuousLinearMap.coe_mk', LinearMap.coe_mk, AddHom.coe_mk, Function.comp_apply, + WithCStarModule.equivL_apply, WithCStarModule.equivL_symm_apply, + WithCStarModule.equiv_symm_pi_apply, ContinuousLinearMap.add_apply, WithCStarModule.add_apply] + rw [Matrix.add_mulVec, Pi.add_apply] + map_smul' c M := by + ext x i + simp only [ContinuousLinearMap.coe_mk', LinearMap.coe_mk, AddHom.coe_mk, Function.comp_apply, + WithCStarModule.equivL_apply, WithCStarModule.equivL_symm_apply, + WithCStarModule.equiv_symm_pi_apply, Matrix.mulVec, dotProduct, + WithCStarModule.equiv_pi_apply, RingHom.id_apply, ContinuousLinearMap.coe_smul', + Pi.smul_apply, WithCStarModule.smul_apply, Finset.smul_sum] + congr + ext j + rw [CStarMatrix.smul_apply, smul_mul_assoc] + +lemma toCLM_apply {M : CStarMatrix m n A} {v : C⋆ᵐᵒᵈ (n → A)} : + toCLM M v = (WithCStarModule.equiv _).symm (M.mulVec v) := rfl + +lemma toCLM_apply_eq_sum {M : CStarMatrix m n A} {v : C⋆ᵐᵒᵈ (n → A)} : + toCLM M v = (WithCStarModule.equiv _).symm (fun i => ∑ j, M i j * v j) := by + ext i + simp [toCLM_apply, Matrix.mulVec, dotProduct] + +/-- Interpret a `CStarMatrix m n A` as a continuous linear map acting on `C⋆ᵐᵒᵈ (n → A)`. This +version is specialized to the case `m = n` and is bundled as a non-unital algebra homomorphism. -/ +def toCLMNonUnitalAlgHom : CStarMatrix n n A →ₙₐ[ℂ] (C⋆ᵐᵒᵈ (n → A)) →L[ℂ] (C⋆ᵐᵒᵈ (n → A)) := + { toCLM (n := n) (m := n) with + map_zero' := by ext1; simp + map_mul' := by intros; ext; simp [toCLM] } + +lemma toCLMNonUnitalAlgHom_eq_toCLM {M : CStarMatrix n n A} : + toCLMNonUnitalAlgHom (A := A) M = toCLM M := rfl + +open WithCStarModule in +@[simp high] +lemma toCLM_apply_single [DecidableEq n] {M : CStarMatrix m n A} {j : n} (a : A) : + (toCLM M) (equiv _ |>.symm <| Pi.single j a) = (equiv _).symm (fun i => M i j * a) := by + ext + simp [toCLM_apply, EmbeddingLike.apply_eq_iff_eq, equiv, Equiv.refl] + +open WithCStarModule in +lemma toCLM_apply_single_apply [DecidableEq n] {M : CStarMatrix m n A} {i : m} {j : n} (a : A) : + (toCLM M) (equiv _ |>.symm <| Pi.single j a) i = M i j * a := by simp + +open WithCStarModule in +lemma mul_entry_mul_eq_inner_toCLM [DecidableEq m] [DecidableEq n] {M : CStarMatrix m n A} + {i : m} {j : n} (a b : A) : + star a * M i j * b + = ⟪equiv _ |>.symm (Pi.single i a), toCLM M (equiv _ |>.symm <| Pi.single j b)⟫_A := by + simp [mul_assoc, inner_def] + +lemma toCLM_injective [DecidableEq n] : Function.Injective (toCLM (A := A) (m := m) (n := n)) := by + rw [injective_iff_map_eq_zero] + intro M h + ext i j + rw [Matrix.zero_apply, ← norm_eq_zero, ← sq_eq_zero_iff, sq, ← CStarRing.norm_self_mul_star, + ← toCLM_apply_single_apply] + simp [h] + +open WithCStarModule in +lemma inner_toCLM_conjTranspose_left {M : CStarMatrix m n A} {v : C⋆ᵐᵒᵈ (m → A)} + {w : C⋆ᵐᵒᵈ (n → A)} : ⟪toCLM Mᴴ v, w⟫_A = ⟪v, toCLM M w⟫_A := by + simp only [toCLM_apply_eq_sum, pi_inner, equiv_symm_pi_apply, inner_def, Finset.mul_sum, + Matrix.conjTranspose_apply, star_sum, star_mul, star_star, Finset.sum_mul] + rw [Finset.sum_comm] + simp_rw [mul_assoc] + +lemma inner_toCLM_conjTranspose_right {M : CStarMatrix m n A} {v : C⋆ᵐᵒᵈ (n → A)} + {w : C⋆ᵐᵒᵈ (m → A)} : ⟪v, toCLM Mᴴ w⟫_A = ⟪toCLM M v, w⟫_A := by + apply Eq.symm + simpa using inner_toCLM_conjTranspose_left (M := Mᴴ) (v := v) (w := w) + +/-- The operator norm on `CStarMatrix m n A`. -/ +noncomputable instance instNorm : Norm (CStarMatrix m n A) where + norm M := ‖toCLM M‖ + +lemma norm_def {M : CStarMatrix m n A} : ‖M‖ = ‖toCLM M‖ := rfl + +lemma norm_def' {M : CStarMatrix n n A} : ‖M‖ = ‖toCLMNonUnitalAlgHom (A := A) M‖ := rfl + +set_option maxSynthPendingDepth 2 in +lemma normedSpaceCore [DecidableEq n]: NormedSpace.Core ℂ (CStarMatrix m n A) where + norm_nonneg M := (toCLM M).opNorm_nonneg + norm_smul c M := by rw [norm_def, norm_def, map_smul, norm_smul _ (toCLM M)] + norm_triangle M₁ M₂ := by simpa [← map_add] using norm_add_le (toCLM M₁) (toCLM M₂) + norm_eq_zero_iff := by + simpa only [norm_def, norm_eq_zero, ← injective_iff_map_eq_zero'] using toCLM_injective + +open WithCStarModule in +lemma norm_entry_le_norm [DecidableEq n] {M : CStarMatrix m n A} {i : m} {j : n} : + ‖M i j‖ ≤ ‖M‖ := by + suffices ‖M i j‖ * ‖M i j‖ ≤ ‖M‖ * ‖M i j‖ by + obtain (h | h) := eq_zero_or_norm_pos (M i j) + · set_option maxSynthPendingDepth 2 in + simp [h, norm_def] + · exact le_of_mul_le_mul_right this h + rw [← CStarRing.norm_self_mul_star, ← toCLM_apply_single_apply] + apply norm_apply_le_norm _ _ |>.trans + apply (toCLM M).le_opNorm _ |>.trans + simp [norm_def] + +open CStarModule in +lemma norm_le_of_forall_inner_le {M : CStarMatrix m n A} {C : ℝ≥0} + (h : ∀ v w, ‖⟪w, toCLM M v⟫_A‖ ≤ C * ‖v‖ * ‖w‖) : ‖M‖ ≤ C := by + refine (toCLM M).opNorm_le_bound (by simp) fun v ↦ ?_ + obtain (h₀ | h₀) := (norm_nonneg (toCLM M v)).eq_or_lt + · rw [← h₀] + positivity + · refine le_of_mul_le_mul_right ?_ h₀ + simpa [← sq, norm_sq_eq] using h .. + +end CStarMatrix + +section TopologyAux +/- +## Replacing the uniformity and bornology + +Note that while the norm that we have defined on `CStarMatrix m n A` induces the product uniformity, +it is not defeq to `Pi.uniformSpace`. In this section, we show that the norm indeed does induce +the product topology and use this fact to properly set up the +`NormedAddCommGroup (CStarMatrix m n A)` instance such that the uniformity is still +`Pi.uniformSpace` and the bornology is `Pi.instBornology`. + +To do this, we locally register a `NormedAddCommGroup` instance on `CStarMatrix` which registers +the "bad" topology, and we also locally use the matrix norm `Matrix.normedAddCommGroup` +(which takes the norm of the biggest entry as the norm of the matrix) +in order to show that the map `ofMatrix` is bilipschitz. We then finally register the +`NormedAddCommGroup (C⋆ᵐᵒᵈ (n → A))` instance via `NormedAddCommGroup.ofCoreReplaceAll`. +-/ + +namespace CStarMatrix + +variable {m n A : Type*} [Fintype m] [Fintype n] [DecidableEq n] + [NonUnitalCStarAlgebra A] [PartialOrder A] [StarOrderedRing A] + +private noncomputable def normedAddCommGroupAux : NormedAddCommGroup (CStarMatrix m n A) := + .ofCore CStarMatrix.normedSpaceCore + +attribute [local instance] normedAddCommGroupAux + +private def normedSpaceAux : NormedSpace ℂ (CStarMatrix m n A) := + .ofCore CStarMatrix.normedSpaceCore + +/- In this `Aux` section, we locally activate the following instances: a norm on `CStarMatrix` + which induces a topology that is not defeq with the matrix one, and the elementwise norm on + matrices, in order to show that the two topologies are in fact equal -/ +attribute [local instance] normedSpaceAux Matrix.normedAddCommGroup Matrix.normedSpace + +private lemma nnnorm_le_of_forall_inner_le {M : CStarMatrix m n A} {C : ℝ≥0} + (h : ∀ v w, ‖⟪w, CStarMatrix.toCLM M v⟫_A‖₊ ≤ C * ‖v‖₊ * ‖w‖₊) : ‖M‖₊ ≤ C := + CStarMatrix.norm_le_of_forall_inner_le fun v w => h v w + +open Finset in +private lemma lipschitzWith_toMatrixAux [DecidableEq m] : + LipschitzWith 1 (ofMatrixₗ.symm (R := ℂ) : CStarMatrix m n A → Matrix m n A) := by + refine AddMonoidHomClass.lipschitz_of_bound_nnnorm _ _ fun M => ?_ + rw [one_mul, ← NNReal.coe_le_coe, coe_nnnorm, coe_nnnorm, Matrix.norm_le_iff (norm_nonneg _)] + exact fun _ _ ↦ CStarMatrix.norm_entry_le_norm + +open CStarMatrix WithCStarModule in +private lemma antilipschitzWith_toMatrixAux : + AntilipschitzWith (Fintype.card m * Fintype.card n) + (ofMatrixₗ.symm (R := ℂ) : CStarMatrix m n A → Matrix m n A) := by + refine AddMonoidHomClass.antilipschitz_of_bound _ fun M => ?_ + calc + ‖M‖ ≤ ∑ i, ∑ j, ‖M i j‖ := by + rw [norm_def] + refine (toCLM M).opNorm_le_bound (by positivity) fun v => ?_ + simp only [toCLM_apply_eq_sum, equiv_symm_pi_apply, Finset.sum_mul] + apply pi_norm_le_sum_norm _ |>.trans + gcongr with i _ + apply norm_sum_le _ _ |>.trans + gcongr with j _ + apply norm_mul_le _ _ |>.trans + gcongr + exact norm_apply_le_norm v j + _ ≤ ∑ _ : m, ∑ _ : n, ‖ofMatrixₗ.symm (R := ℂ) M‖ := by + gcongr with i _ j _ + exact ofMatrixₗ.symm (R := ℂ) M |>.norm_entry_le_entrywise_sup_norm + _ = _ := by simp [mul_assoc] + +private lemma uniformInducing_toMatrixAux [DecidableEq m] : + IsUniformInducing (ofMatrix.symm : CStarMatrix m n A → Matrix m n A) := + AntilipschitzWith.isUniformInducing antilipschitzWith_toMatrixAux + lipschitzWith_toMatrixAux.uniformContinuous + +private lemma uniformity_eq_aux [DecidableEq m] : + 𝓤 (CStarMatrix m n A) = (𝓤[Pi.uniformSpace _] : + Filter (CStarMatrix m n A × CStarMatrix m n A)) := by + have : + (fun x : CStarMatrix m n A × CStarMatrix m n A => ⟨ofMatrix.symm x.1, ofMatrix.symm x.2⟩) + = id := by + ext i <;> rfl + rw [← uniformInducing_toMatrixAux.comap_uniformity, this, Filter.comap_id] + rfl + +open Bornology in +private lemma cobounded_eq_aux [DecidableEq m] : + cobounded (CStarMatrix m n A) = @cobounded _ Pi.instBornology := by + have : cobounded (CStarMatrix m n A) = Filter.comap ofMatrix.symm (cobounded _) := by + refine le_antisymm ?_ ?_ + · exact antilipschitzWith_toMatrixAux.tendsto_cobounded.le_comap + · exact lipschitzWith_toMatrixAux.comap_cobounded_le + exact this.trans Filter.comap_id + +end CStarMatrix + +end TopologyAux + +namespace CStarMatrix + +section non_unital + +variable {A : Type*} [NonUnitalCStarAlgebra A] [PartialOrder A] [StarOrderedRing A] + +variable {m n : Type*} [Fintype m] [Fintype n] [DecidableEq m] + +instance instTopologicalSpace : TopologicalSpace (CStarMatrix m n A) := Pi.topologicalSpace +instance instUniformSpace : UniformSpace (CStarMatrix m n A) := Pi.uniformSpace _ +instance instBornology : Bornology (CStarMatrix m n A) := Pi.instBornology +instance instCompleteSpace : CompleteSpace (CStarMatrix m n A) := Pi.complete _ +instance instT2Space : T2Space (CStarMatrix m n A) := Pi.t2Space +instance instT3Space : T3Space (CStarMatrix m n A) := _root_.instT3Space + +instance instTopologicalAddGroup : TopologicalAddGroup (CStarMatrix m n A) := + Pi.topologicalAddGroup + +instance instUniformAddGroup : UniformAddGroup (CStarMatrix m n A) := + Pi.instUniformAddGroup + +instance instContinuousSMul {R : Type*} [SMul R A] [TopologicalSpace R] [ContinuousSMul R A] : + ContinuousSMul R (CStarMatrix m n A) := instContinuousSMulForall + +noncomputable instance instNormedAddCommGroup [DecidableEq n] : + NormedAddCommGroup (CStarMatrix m n A) := + .ofCoreReplaceAll CStarMatrix.normedSpaceCore + CStarMatrix.uniformity_eq_aux.symm + fun _ => Filter.ext_iff.1 CStarMatrix.cobounded_eq_aux.symm _ + +instance instNormedSpace [DecidableEq n] : NormedSpace ℂ (CStarMatrix m n A) := + .ofCore CStarMatrix.normedSpaceCore + +noncomputable instance instNonUnitalNormedRing [DecidableEq n] : + NonUnitalNormedRing (CStarMatrix n n A) where + dist_eq _ _ := rfl + norm_mul _ _ := by + set_option maxSynthPendingDepth 2 in + simpa only [norm_def', map_mul] using norm_mul_le _ _ + +open ContinuousLinearMap CStarModule in +/-- Matrices with entries in a C⋆-algebra form a C⋆-algebra. -/ +instance instCStarRing [DecidableEq n] : CStarRing (CStarMatrix n n A) where + norm_mul_self_le M := by + have hmain : ‖M‖ ≤ √‖star M * M‖ := by + change ‖toCLM M‖ ≤ √‖star M * M‖ + rw [opNorm_le_iff (by positivity)] + intro v + rw [norm_eq_sqrt_norm_inner_self, ← inner_toCLM_conjTranspose_right] + have h₁ : ‖⟪v, (toCLM Mᴴ) ((toCLM M) v)⟫_A‖ ≤ ‖star M * M‖ * ‖v‖ ^ 2 := calc + _ ≤ ‖v‖ * ‖(toCLM Mᴴ) (toCLM M v)‖ := norm_inner_le (C⋆ᵐᵒᵈ (n → A)) + _ ≤ ‖v‖ * ‖(toCLM Mᴴ).comp (toCLM M)‖ * ‖v‖ := by + rw [mul_assoc] + gcongr + rw [← ContinuousLinearMap.comp_apply] + exact le_opNorm ((toCLM Mᴴ).comp (toCLM M)) v + _ = ‖(toCLM Mᴴ).comp (toCLM M)‖ * ‖v‖ ^ 2 := by ring + _ = ‖star M * M‖ * ‖v‖ ^ 2 := by + congr + simp only [← toCLMNonUnitalAlgHom_eq_toCLM, Matrix.star_eq_conjTranspose, + map_mul] + rfl + have h₂ : ‖v‖ = √(‖v‖ ^ 2) := by simp + rw [h₂, ← Real.sqrt_mul] + gcongr + positivity + rw [← pow_two, ← Real.sqrt_le_sqrt_iff (by positivity)] + simp [hmain] + +/-- Matrices with entries in a non-unital C⋆-algebra form a non-unital C⋆-algebra. -/ +noncomputable instance instNonUnitalCStarAlgebra [DecidableEq n] : + NonUnitalCStarAlgebra (CStarMatrix n n A) where + smul_assoc x y z := by simp + smul_comm m a b := (Matrix.mul_smul _ _ _).symm + +instance instPartialOrder [DecidableEq n] : + PartialOrder (CStarMatrix n n A) := CStarAlgebra.spectralOrder _ +instance instStarOrderedRing [DecidableEq n] : + StarOrderedRing (CStarMatrix n n A) := CStarAlgebra.spectralOrderedRing _ + +end non_unital + +section unital + +variable {A : Type*} [CStarAlgebra A] [PartialOrder A] [StarOrderedRing A] + +variable {n : Type*} [Fintype n] [DecidableEq n] + +noncomputable instance instNormedRing : NormedRing (CStarMatrix n n A) where + dist_eq _ _ := rfl + norm_mul := norm_mul_le + +noncomputable instance instNormedAlgebra : NormedAlgebra ℂ (CStarMatrix n n A) where + norm_smul_le r M := by simpa only [norm_def, map_smul] using (toCLM M).opNorm_smul_le r + +/-- Matrices with entries in a unital C⋆-algebra form a unital C⋆-algebra. -/ +noncomputable instance instCStarAlgebra [DecidableEq n] : CStarAlgebra (CStarMatrix n n A) where + +end unital + +section + +variable {m n A : Type*} [NonUnitalCStarAlgebra A] + +lemma uniformEmbedding_ofMatrix : + IsUniformEmbedding (ofMatrix : Matrix m n A → CStarMatrix m n A) where + comap_uniformity := Filter.comap_id' + injective := fun ⦃_ _⦄ a ↦ a + +/-- `ofMatrix` bundled as a continuous linear equivalence. -/ +def ofMatrixL : Matrix m n A ≃L[ℂ] CStarMatrix m n A := + { ofMatrixₗ with + continuous_toFun := continuous_id + continuous_invFun := continuous_id } + +lemma ofMatrix_eq_ofMatrixL : + (ofMatrix : Matrix m n A → CStarMatrix m n A) + = (ofMatrixL : Matrix m n A → CStarMatrix m n A) := rfl + +end + +end CStarMatrix diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Constructions.lean b/Mathlib/Analysis/CStarAlgebra/Module/Constructions.lean index 64d2ba88bc9c2..872bf20de1001 100644 --- a/Mathlib/Analysis/CStarAlgebra/Module/Constructions.lean +++ b/Mathlib/Analysis/CStarAlgebra/Module/Constructions.lean @@ -296,6 +296,13 @@ private lemma isBounded_pi_iff_aux (s : Set (C⋆ᵐᵒᵈ (Π i, E i))) : end Aux +noncomputable instance : PseudoMetricSpace (C⋆ᵐᵒᵈ (Π i, E i)) := + .ofSeminormedAddCommGroupCoreReplaceAll + normedSpaceCore.toCore uniformity_pi_eq_aux isBounded_pi_iff_aux + +noncomputable instance : SeminormedAddCommGroup (C⋆ᵐᵒᵈ (Π i, E i)) := + .ofCoreReplaceAll normedSpaceCore.toCore uniformity_pi_eq_aux isBounded_pi_iff_aux + noncomputable instance : NormedAddCommGroup (C⋆ᵐᵒᵈ (Π i, E i)) := .ofCoreReplaceAll normedSpaceCore uniformity_pi_eq_aux isBounded_pi_iff_aux diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean index 95c7421f62a16..02b57dc8603b2 100644 --- a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean +++ b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean @@ -6,6 +6,8 @@ Authors: Jireh Loreaux import Mathlib.RingTheory.Finiteness.Defs import Mathlib.Topology.Bornology.Constructions import Mathlib.Topology.UniformSpace.Equiv +import Mathlib.Topology.Algebra.Module.Equiv +import Mathlib.Topology.Algebra.UniformGroup.Basic /-! # Type synonym for types with a `CStarModule` structure @@ -75,11 +77,21 @@ instance instUnique [Unique E] : Unique (WithCStarModule E) := ‹Unique E› /-! ## `WithCStarModule E` inherits various module-adjacent structures from `E`. -/ +instance instZero [Zero E] : Zero (WithCStarModule E) := ‹Zero E› +instance instAdd [Add E] : Add (WithCStarModule E) := ‹Add E› +instance instSub [Sub E] : Sub (WithCStarModule E) := ‹Sub E› +instance instNeg [Neg E] : Neg (WithCStarModule E) := ‹Neg E› +instance instAddMonoid [AddMonoid E] : AddMonoid (WithCStarModule E) := ‹AddMonoid E› +instance instSubNegMonoid [SubNegMonoid E] : SubNegMonoid (WithCStarModule E) := ‹SubNegMonoid E› +instance instSubNegZeroMonoid [SubNegZeroMonoid E] : SubNegZeroMonoid (WithCStarModule E) := + ‹SubNegZeroMonoid E› + instance instAddCommGroup [AddCommGroup E] : AddCommGroup (WithCStarModule E) := ‹AddCommGroup E› + instance instSMul {R : Type*} [SMul R E] : SMul R (WithCStarModule E) := ‹SMul R E› + instance instModule {R : Type*} [Semiring R] [AddCommGroup E] [Module R E] : - Module R (WithCStarModule E) := - ‹Module R E› + Module R (WithCStarModule E) := ‹Module R E› instance instIsScalarTower [SMul R R'] [SMul R E] [SMul R' E] [IsScalarTower R R' E] : IsScalarTower R R' (WithCStarModule E) := @@ -89,11 +101,6 @@ instance instSMulCommClass [SMul R E] [SMul R' E] [SMulCommClass R R' E] : SMulCommClass R R' (WithCStarModule E) := ‹SMulCommClass R R' E› -instance instModuleFinite [Semiring R] [AddCommGroup E] [Module R E] [Module.Finite R E] : - Module.Finite R (WithCStarModule E) := - ‹Module.Finite R E› - - section Equiv variable {R E} @@ -151,6 +158,12 @@ theorem equiv_symm_smul : (equiv E).symm (c • x') = c • (equiv E).symm x' := end Equiv +/-- `WithCStarModule.equiv` as an additive equivalence. -/ +def addEquiv [AddCommGroup E] : C⋆ᵐᵒᵈ E ≃+ E := + { AddEquiv.refl _ with + toFun := equiv _ + invFun := (equiv _).symm } + /-- `WithCStarModule.equiv` as a linear equivalence. -/ @[simps (config := .asFn)] def linearEquiv [Semiring R] [AddCommGroup E] [Module R E] : C⋆ᵐᵒᵈ E ≃ₗ[R] E := @@ -158,6 +171,16 @@ def linearEquiv [Semiring R] [AddCommGroup E] [Module R E] : C⋆ᵐᵒᵈ E ≃ toFun := equiv _ invFun := (equiv _).symm } +lemma map_top_submodule {R : Type*} [Semiring R] [AddCommGroup E] [Module R E] : + (⊤ : Submodule R E).map (linearEquiv R E).symm = ⊤ := by + ext x + refine ⟨fun _ => trivial, fun _ => ?_⟩ + rw [Submodule.mem_map] + exact ⟨linearEquiv R E x, by simp⟩ + +instance instModuleFinite [Semiring R] [AddCommGroup E] [Module R E] [Module.Finite R E] : + Module.Finite R (WithCStarModule E) := inferInstanceAs (Module.Finite R E) + /-! ## `WithCStarModule E` inherits the uniformity and bornology from `E`. -/ variable {E} @@ -170,9 +193,26 @@ instance [Bornology E] : Bornology (C⋆ᵐᵒᵈ E) := Bornology.induced <| equ def uniformEquiv [UniformSpace E] : C⋆ᵐᵒᵈ E ≃ᵤ E := equiv E |>.toUniformEquivOfIsUniformInducing ⟨rfl⟩ +/-- `WithCStarModule.equiv` as a continuous linear equivalence between `C⋆ᵐᵒᵈ E` and `E`. -/ +@[simps! apply symm_apply] +def equivL [Semiring R] [AddCommGroup E] [UniformSpace E] [Module R E] : C⋆ᵐᵒᵈ E ≃L[R] E := + { linearEquiv R E with + continuous_toFun := UniformEquiv.continuous uniformEquiv + continuous_invFun := UniformEquiv.continuous uniformEquiv.symm } + instance [UniformSpace E] [CompleteSpace E] : CompleteSpace (C⋆ᵐᵒᵈ E) := uniformEquiv.completeSpace_iff.mpr inferInstance +instance [AddCommGroup E] [UniformSpace E] [ContinuousAdd E] : ContinuousAdd (C⋆ᵐᵒᵈ E) := + ContinuousAdd.induced (addEquiv E) + +instance [AddCommGroup E] [UniformSpace E] [UniformAddGroup E] : UniformAddGroup (C⋆ᵐᵒᵈ E) := + UniformAddGroup.comap (addEquiv E) + +instance [Semiring R] [TopologicalSpace R] [AddCommGroup E] [UniformSpace E] [Module R E] + [ContinuousSMul R E] : ContinuousSMul R (C⋆ᵐᵒᵈ E) := + ContinuousSMul.induced (linearEquiv R E) + end Basic /-! ## Prod diff --git a/Mathlib/Data/Finset/Lattice/Fold.lean b/Mathlib/Data/Finset/Lattice/Fold.lean index 0a04809d8a4e6..c5ae9f5e4dcdb 100644 --- a/Mathlib/Data/Finset/Lattice/Fold.lean +++ b/Mathlib/Data/Finset/Lattice/Fold.lean @@ -250,6 +250,11 @@ theorem sup_mem (s : Set α) (w₁ : ⊥ ∈ s) (w₂ : ∀ᵉ (x ∈ s) (y ∈ protected theorem sup_eq_bot_iff (f : β → α) (S : Finset β) : S.sup f = ⊥ ↔ ∀ s ∈ S, f s = ⊥ := by classical induction' S using Finset.induction with a S _ hi <;> simp [*] +@[simp] +theorem sup_eq_bot_of_isEmpty [IsEmpty β] (f : β → α) (S : Finset β) : S.sup f = ⊥ := by + rw [Finset.sup_eq_bot_iff] + exact fun x _ => False.elim <| IsEmpty.false x + end Sup theorem sup_eq_iSup [CompleteLattice β] (s : Finset α) (f : α → β) : s.sup f = ⨆ a ∈ s, f a := diff --git a/Mathlib/Topology/Instances/Matrix.lean b/Mathlib/Topology/Instances/Matrix.lean index 13decc88c4c0a..c465b090b6545 100644 --- a/Mathlib/Topology/Instances/Matrix.lean +++ b/Mathlib/Topology/Instances/Matrix.lean @@ -73,16 +73,17 @@ theorem Continuous.matrix_elem {A : X → Matrix m n R} (hA : Continuous A) (i : Continuous fun x => A x i j := (continuous_apply_apply i j).comp hA -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_map [TopologicalSpace S] {A : X → Matrix m n S} {f : S → R} (hA : Continuous A) (hf : Continuous f) : Continuous fun x => (A x).map f := continuous_matrix fun _ _ => hf.comp <| hA.matrix_elem _ _ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_transpose {A : X → Matrix m n R} (hA : Continuous A) : Continuous fun x => (A x)ᵀ := continuous_matrix fun i j => hA.matrix_elem j i +@[continuity, fun_prop] theorem Continuous.matrix_conjTranspose [Star R] [ContinuousStar R] {A : X → Matrix m n R} (hA : Continuous A) : Continuous fun x => (A x)ᴴ := hA.matrix_transpose.matrix_map continuous_star @@ -90,22 +91,22 @@ theorem Continuous.matrix_conjTranspose [Star R] [ContinuousStar R] {A : X → M instance [Star R] [ContinuousStar R] : ContinuousStar (Matrix m m R) := ⟨continuous_id.matrix_conjTranspose⟩ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_col {ι : Type*} {A : X → n → R} (hA : Continuous A) : Continuous fun x => col ι (A x) := continuous_matrix fun i _ => (continuous_apply i).comp hA -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_row {ι : Type*} {A : X → n → R} (hA : Continuous A) : Continuous fun x => row ι (A x) := continuous_matrix fun _ _ => (continuous_apply _).comp hA -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_diagonal [Zero R] [DecidableEq n] {A : X → n → R} (hA : Continuous A) : Continuous fun x => diagonal (A x) := continuous_matrix fun i _ => ((continuous_apply i).comp hA).if_const _ continuous_zero -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_dotProduct [Fintype n] [Mul R] [AddCommMonoid R] [ContinuousAdd R] [ContinuousMul R] {A : X → n → R} {B : X → n → R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => dotProduct (A x) (B x) := @@ -113,7 +114,7 @@ theorem Continuous.matrix_dotProduct [Fintype n] [Mul R] [AddCommMonoid R] [Cont ((continuous_apply i).comp hA).mul ((continuous_apply i).comp hB) /-- For square matrices the usual `continuous_mul` can be used. -/ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_mul [Fintype n] [Mul R] [AddCommMonoid R] [ContinuousAdd R] [ContinuousMul R] {A : X → Matrix m n R} {B : X → Matrix n p R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => A x * B x := @@ -130,34 +131,34 @@ instance [Fintype n] [NonUnitalNonAssocSemiring R] [TopologicalSemiring R] : instance Matrix.topologicalRing [Fintype n] [NonUnitalNonAssocRing R] [TopologicalRing R] : TopologicalRing (Matrix n n R) where -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_vecMulVec [Mul R] [ContinuousMul R] {A : X → m → R} {B : X → n → R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => vecMulVec (A x) (B x) := continuous_matrix fun _ _ => ((continuous_apply _).comp hA).mul ((continuous_apply _).comp hB) -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_mulVec [NonUnitalNonAssocSemiring R] [ContinuousAdd R] [ContinuousMul R] [Fintype n] {A : X → Matrix m n R} {B : X → n → R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => A x *ᵥ B x := continuous_pi fun i => ((continuous_apply i).comp hA).matrix_dotProduct hB -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_vecMul [NonUnitalNonAssocSemiring R] [ContinuousAdd R] [ContinuousMul R] [Fintype m] {A : X → m → R} {B : X → Matrix m n R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => A x ᵥ* B x := continuous_pi fun _i => hA.matrix_dotProduct <| continuous_pi fun _j => hB.matrix_elem _ _ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_submatrix {A : X → Matrix l n R} (hA : Continuous A) (e₁ : m → l) (e₂ : p → n) : Continuous fun x => (A x).submatrix e₁ e₂ := continuous_matrix fun _i _j => hA.matrix_elem _ _ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_reindex {A : X → Matrix l n R} (hA : Continuous A) (e₁ : l ≃ m) (e₂ : n ≃ p) : Continuous fun x => reindex e₁ e₂ (A x) := hA.matrix_submatrix _ _ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_diag {A : X → Matrix n n R} (hA : Continuous A) : Continuous fun x => Matrix.diag (A x) := continuous_pi fun _ => hA.matrix_elem _ _ @@ -166,19 +167,19 @@ theorem Continuous.matrix_diag {A : X → Matrix n n R} (hA : Continuous A) : theorem continuous_matrix_diag : Continuous (Matrix.diag : Matrix n n R → n → R) := show Continuous fun x : Matrix n n R => Matrix.diag x from continuous_id.matrix_diag -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_trace [Fintype n] [AddCommMonoid R] [ContinuousAdd R] {A : X → Matrix n n R} (hA : Continuous A) : Continuous fun x => trace (A x) := continuous_finset_sum _ fun _ _ => hA.matrix_elem _ _ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_det [Fintype n] [DecidableEq n] [CommRing R] [TopologicalRing R] {A : X → Matrix n n R} (hA : Continuous A) : Continuous fun x => (A x).det := by simp_rw [Matrix.det_apply] refine continuous_finset_sum _ fun l _ => Continuous.const_smul ?_ _ exact continuous_finset_prod _ fun l _ => hA.matrix_elem _ _ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_updateCol [DecidableEq n] (i : n) {A : X → Matrix m n R} {B : X → m → R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => (A x).updateCol i (B x) := @@ -189,18 +190,18 @@ theorem Continuous.matrix_updateCol [DecidableEq n] (i : n) {A : X → Matrix m @[deprecated (since := "2024-12-11")] alias Continuous.matrix_updateColumn := Continuous.matrix_updateCol -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_updateRow [DecidableEq m] (i : m) {A : X → Matrix m n R} {B : X → n → R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => (A x).updateRow i (B x) := hA.update i hB -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_cramer [Fintype n] [DecidableEq n] [CommRing R] [TopologicalRing R] {A : X → Matrix n n R} {B : X → n → R} (hA : Continuous A) (hB : Continuous B) : Continuous fun x => cramer (A x) (B x) := continuous_pi fun _ => (hA.matrix_updateCol _ hB).matrix_det -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_adjugate [Fintype n] [DecidableEq n] [CommRing R] [TopologicalRing R] {A : X → Matrix n n R} (hA : Continuous A) : Continuous fun x => (A x).adjugate := continuous_matrix fun _j k => @@ -215,7 +216,7 @@ theorem continuousAt_matrix_inv [Fintype n] [DecidableEq n] [CommRing R] [Topolo -- lemmas about functions in `Data/Matrix/Block.lean` section BlockMatrices -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_fromBlocks {A : X → Matrix n l R} {B : X → Matrix n m R} {C : X → Matrix p l R} {D : X → Matrix p m R} (hA : Continuous A) (hB : Continuous B) (hC : Continuous C) (hD : Continuous D) : @@ -223,18 +224,18 @@ theorem Continuous.matrix_fromBlocks {A : X → Matrix n l R} {B : X → Matrix continuous_matrix <| by rintro (i | i) (j | j) <;> refine Continuous.matrix_elem ?_ i j <;> assumption -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_blockDiagonal [Zero R] [DecidableEq p] {A : X → p → Matrix m n R} (hA : Continuous A) : Continuous fun x => blockDiagonal (A x) := continuous_matrix fun ⟨i₁, i₂⟩ ⟨j₁, _j₂⟩ => (((continuous_apply i₂).comp hA).matrix_elem i₁ j₁).if_const _ continuous_zero -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_blockDiag {A : X → Matrix (m × p) (n × p) R} (hA : Continuous A) : Continuous fun x => blockDiag (A x) := continuous_pi fun _i => continuous_matrix fun _j _k => hA.matrix_elem _ _ -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_blockDiagonal' [Zero R] [DecidableEq l] {A : X → ∀ i, Matrix (m' i) (n' i) R} (hA : Continuous A) : Continuous fun x => blockDiagonal' (A x) := @@ -245,7 +246,7 @@ theorem Continuous.matrix_blockDiagonal' [Zero R] [DecidableEq l] exact ((continuous_apply i₁).comp hA).matrix_elem i₂ j₂ · exact continuous_const -@[continuity] +@[continuity, fun_prop] theorem Continuous.matrix_blockDiag' {A : X → Matrix (Σi, m' i) (Σi, n' i) R} (hA : Continuous A) : Continuous fun x => blockDiag' (A x) := continuous_pi fun _i => continuous_matrix fun _j _k => hA.matrix_elem _ _ From 8ec167c66ce66f1e04b98ca03b2a9bb328d5bec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 30 Jan 2025 00:35:50 +0000 Subject: [PATCH 658/681] chore(SetTheory/Ordinal/Exponential): redefine ordinal exponential without `bsup` (#19145) `Ordinal.bsup` is planned to be deprecated. --- Mathlib/SetTheory/Ordinal/Exponential.lean | 56 +++++++++++++--------- Mathlib/SetTheory/Ordinal/Notation.lean | 6 +-- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/Mathlib/SetTheory/Ordinal/Exponential.lean b/Mathlib/SetTheory/Ordinal/Exponential.lean index 59b0607db2df3..c58e66d7ac7e6 100644 --- a/Mathlib/SetTheory/Ordinal/Exponential.lean +++ b/Mathlib/SetTheory/Ordinal/Exponential.lean @@ -21,16 +21,24 @@ universe u v w namespace Ordinal -/-- The ordinal exponential, defined by transfinite recursion. -/ -instance pow : Pow Ordinal Ordinal := - ⟨fun a b => if a = 0 then 1 - b else limitRecOn b 1 (fun _ IH => IH * a) fun b _ => bsup.{u, u} b⟩ +/-- The ordinal exponential, defined by transfinite recursion. -theorem opow_def (a b : Ordinal) : - a ^ b = if a = 0 then 1 - b else limitRecOn b 1 (fun _ IH => IH * a) fun b _ => bsup.{u, u} b := - rfl +We call this `opow` in theorems in order to disambiguate from other exponentials. -/ +instance instPow : Pow Ordinal Ordinal := + ⟨fun a b ↦ if a = 0 then 1 - b else + limitRecOn b 1 (fun _ x ↦ x * a) fun o _ f ↦ ⨆ x : Iio o, f x.1 x.2⟩ + +private theorem opow_of_ne_zero {a b : Ordinal} (h : a ≠ 0) : a ^ b = + limitRecOn b 1 (fun _ x ↦ x * a) fun o _ f ↦ ⨆ x : Iio o, f x.1 x.2 := + if_neg h --- Porting note: `if_pos rfl` → `if_true` -theorem zero_opow' (a : Ordinal) : 0 ^ a = 1 - a := by simp only [opow_def, if_true] +/-- `0 ^ a = 1` if `a = 0` and `0 ^ a = 0` otherwise. -/ +theorem zero_opow' (a : Ordinal) : 0 ^ a = 1 - a := + if_pos rfl + +theorem zero_opow_le (a : Ordinal) : (0 : Ordinal) ^ a ≤ 1 := by + rw [zero_opow'] + exact sub_le_self 1 a @[simp] theorem zero_opow {a : Ordinal} (a0 : a ≠ 0) : (0 : Ordinal) ^ a = 0 := by @@ -38,29 +46,34 @@ theorem zero_opow {a : Ordinal} (a0 : a ≠ 0) : (0 : Ordinal) ^ a = 0 := by @[simp] theorem opow_zero (a : Ordinal) : a ^ (0 : Ordinal) = 1 := by - by_cases h : a = 0 - · simp only [opow_def, if_pos h, sub_zero] - · simp only [opow_def, if_neg h, limitRecOn_zero] + obtain rfl | h := eq_or_ne a 0 + · rw [zero_opow', Ordinal.sub_zero] + · rw [opow_of_ne_zero h, limitRecOn_zero] @[simp] -theorem opow_succ (a b : Ordinal) : a ^ succ b = a ^ b * a := - if h : a = 0 then by subst a; simp only [zero_opow (succ_ne_zero _), mul_zero] - else by simp only [opow_def, limitRecOn_succ, if_neg h] +theorem opow_succ (a b : Ordinal) : a ^ succ b = a ^ b * a := by + obtain rfl | h := eq_or_ne a 0 + · rw [zero_opow (succ_ne_zero b), mul_zero] + · rw [opow_of_ne_zero h, opow_of_ne_zero h, limitRecOn_succ] -theorem opow_limit {a b : Ordinal} (a0 : a ≠ 0) (h : IsLimit b) : - a ^ b = bsup.{u, u} b fun c _ => a ^ c := by - simp only [opow_def, if_neg a0]; rw [limitRecOn_limit _ _ _ _ h] +theorem opow_limit {a b : Ordinal} (ha : a ≠ 0) (hb : IsLimit b) : + a ^ b = ⨆ x : Iio b, a ^ x.1 := by + simp_rw [opow_of_ne_zero ha, limitRecOn_limit _ _ _ _ hb] theorem opow_le_of_limit {a b c : Ordinal} (a0 : a ≠ 0) (h : IsLimit b) : - a ^ b ≤ c ↔ ∀ b' < b, a ^ b' ≤ c := by rw [opow_limit a0 h, bsup_le_iff] + a ^ b ≤ c ↔ ∀ b' < b, a ^ b' ≤ c := by + rw [opow_limit a0 h, Ordinal.iSup_le_iff, Subtype.forall] + rfl theorem lt_opow_of_limit {a b c : Ordinal} (b0 : b ≠ 0) (h : IsLimit c) : a < b ^ c ↔ ∃ c' < c, a < b ^ c' := by - rw [← not_iff_not, not_exists]; simp only [not_lt, opow_le_of_limit b0 h, exists_prop, not_and] + rw [← not_iff_not, not_exists] + simp only [not_lt, opow_le_of_limit b0 h, exists_prop, not_and] @[simp] theorem opow_one (a : Ordinal) : a ^ (1 : Ordinal) = a := by - rw [← succ_zero, opow_succ]; simp only [opow_zero, one_mul] + rw [← succ_zero, opow_succ] + simp only [opow_zero, one_mul] @[simp] theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by @@ -317,8 +330,7 @@ theorem lt_opow_succ_log_self {b : Ordinal} (hb : 1 < b) (x : Ordinal) : theorem opow_log_le_self (b : Ordinal) {x : Ordinal} (hx : x ≠ 0) : b ^ log b x ≤ x := by rcases eq_or_ne b 0 with (rfl | b0) - · rw [zero_opow'] - exact (sub_le_self _ _).trans (one_le_iff_ne_zero.2 hx) + · exact (zero_opow_le _).trans (one_le_iff_ne_zero.2 hx) rcases lt_or_eq_of_le (one_le_iff_ne_zero.2 b0) with (hb | rfl) · refine le_of_not_lt fun h => (lt_succ (log b x)).not_le ?_ have := @csInf_le' _ _ { o | x < b ^ o } _ h diff --git a/Mathlib/SetTheory/Ordinal/Notation.lean b/Mathlib/SetTheory/Ordinal/Notation.lean index 9d81bb8ff98ac..acc0ddcba26a4 100644 --- a/Mathlib/SetTheory/Ordinal/Notation.lean +++ b/Mathlib/SetTheory/Ordinal/Notation.lean @@ -749,11 +749,11 @@ instance nf_opow (o₁ o₂) [NF o₁] [NF o₂] : NF (o₁ ^ o₂) := by haveI := (nf_repr_split' e₂).1 cases' a with a0 n a' · cases' m with m - · by_cases o₂ = 0 <;> simp only [(· ^ ·), Pow.pow, pow, opow, opowAux2, *] <;> decide + · by_cases o₂ = 0 <;> simp only [(· ^ ·), Pow.pow, opow, opowAux2, *] <;> decide · by_cases m = 0 - · simp only [(· ^ ·), Pow.pow, pow, opow, opowAux2, *, zero_def] + · simp only [(· ^ ·), Pow.pow, opow, opowAux2, *, zero_def] decide - · simp only [(· ^ ·), Pow.pow, pow, opow, opowAux2, mulNat_eq_mul, ofNat, *] + · simp only [(· ^ ·), Pow.pow, opow, opowAux2, mulNat_eq_mul, ofNat, *] infer_instance · simp only [(· ^ ·), Pow.pow, opow, opowAux2, e₁, split_eq_scale_split' e₂, mulNat_eq_mul] have := na.fst From 0cd97635eeb3d1664849b635deb111ee719387a9 Mon Sep 17 00:00:00 2001 From: Peter Nelson <71660771+apnelson1@users.noreply.github.com> Date: Thu, 30 Jan 2025 00:58:35 +0000 Subject: [PATCH 659/681] feat(Data/Matroid/Circuit): better junk values for `fundCircuit` (#21240) The definition of fundamental circuits in #21145 was suboptimal, in that its junk values were unstable. We slightly modify the definition so that the fundamental circuit of a non-element `e` of the ground set is a singleton `{e}`. This removes assumptions from a couple of existing lemmas, and crucially makes the useful lemma `Matroid.fundCircuit_restrict_univ` true, where it wasn't before. --- Mathlib/Data/Matroid/Circuit.lean | 79 +++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/Mathlib/Data/Matroid/Circuit.lean b/Mathlib/Data/Matroid/Circuit.lean index cd068114bce61..d074210e88295 100644 --- a/Mathlib/Data/Matroid/Circuit.lean +++ b/Mathlib/Data/Matroid/Circuit.lean @@ -31,8 +31,8 @@ Since `Matroid.fundCircuit M e I` is only sensible if `I` is independent and `e to avoid hypotheses being explicitly included in the definition, junk values need to be chosen if either hypothesis fails. The definition is chosen so that the junk values satisfy -`M.fundCircuit e I = {e}` for `e ∈ I` and -`M.fundCircuit e I = insert e I` if `e ∉ M.closure I`. +`M.fundCircuit e I = {e}` for `e ∈ I` or `e ∉ M.E` and +`M.fundCircuit e I = insert e I` if `e ∈ M.E \ M.closure I`. These make the useful statement `e ∈ M.fundCircuit e I ⊆ insert e I` true unconditionally. -/ @@ -193,14 +193,16 @@ lemma restrict_circuit_iff (hR : R ⊆ M.E := by aesop_mat) : `M.fundCircuit e I` is the unique circuit contained in `insert e I`. For the fact that this is a circuit, see `Matroid.Indep.fundCircuit_circuit`, and the fact that it is unique, see `Matroid.Circuit.eq_fundCircuit_of_subset`. -Has the junk value `{e}` if `e ∈ I` and `insert e I` if `e ∉ M.closure I`. -/ +Has the junk value `{e}` if `e ∈ I` or `e ∉ M.E`, and `insert e I` if `e ∈ M.E \ M.closure I`. -/ def fundCircuit (M : Matroid α) (e : α) (I : Set α) : Set α := - insert e (I ∩ (⋂₀ {J | J ⊆ I ∧ e ∈ M.closure J})) + insert e (I ∩ ⋂₀ {J | J ⊆ I ∧ M.closure {e} ⊆ M.closure J}) lemma fundCircuit_eq_sInter (he : e ∈ M.closure I) : M.fundCircuit e I = insert e (⋂₀ {J | J ⊆ I ∧ e ∈ M.closure J}) := by - rw [fundCircuit, inter_eq_self_of_subset_right] - exact sInter_subset_of_mem ⟨Subset.rfl, he⟩ + rw [fundCircuit] + simp_rw [closure_subset_closure_iff_subset_closure + (show {e} ⊆ M.E by simpa using mem_ground_of_mem_closure he), singleton_subset_iff] + rw [inter_eq_self_of_subset_right (sInter_subset_of_mem (by simpa))] lemma fundCircuit_subset_insert (M : Matroid α) (e : α) (I : Set α) : M.fundCircuit e I ⊆ insert e I := @@ -213,28 +215,33 @@ lemma fundCircuit_subset_ground (he : e ∈ M.E) (hI : I ⊆ M.E := by aesop_mat lemma mem_fundCircuit (M : Matroid α) (e : α) (I : Set α) : e ∈ fundCircuit M e I := mem_insert .. +lemma fundCircuit_diff_eq_inter (M : Matroid α) (heI : e ∉ I) : + (M.fundCircuit e I) \ {e} = (M.fundCircuit e I) ∩ I := + (subset_inter diff_subset (by simp [fundCircuit_subset_insert])).antisymm + (subset_diff_singleton inter_subset_left (by simp [heI])) + /-- The fundamental circuit of `e` and `X` has the junk value `{e}` if `e ∈ X` -/ -lemma fundCircuit_eq_of_mem (heX : e ∈ X) (heE : e ∈ M.E := by aesop_mat) : - M.fundCircuit e X = {e} := by - suffices h : ∀ a ∈ X, (∀ I ⊆ X, e ∈ M.closure I → a ∈ I) → a = e by +lemma fundCircuit_eq_of_mem (heX : e ∈ X) : M.fundCircuit e X = {e} := by + suffices h : ∀ a ∈ X, (∀ t ⊆ X, M.closure {e} ⊆ M.closure t → a ∈ t) → a = e by simpa [subset_antisymm_iff, fundCircuit] - exact fun f hfX h ↦ h {e} (by simpa) (mem_closure_of_mem' _ rfl) + exact fun b hbX h ↦ h _ (singleton_subset_iff.2 heX) Subset.rfl -/-- A version of `Matroid.fundCircuit_eq_of_mem` that applies when `X ⊆ M.E` instead of `e ∈ X`.-/ -lemma fundCircuit_eq_of_mem' (heX : e ∈ X) (hX : X ⊆ M.E := by aesop_mat) : - M.fundCircuit e X = {e} := by - rwa [fundCircuit_eq_of_mem] +lemma fundCircuit_eq_of_not_mem_ground (heX : e ∉ M.E) : M.fundCircuit e X = {e} := by + suffices h : ∀ a ∈ X, (∀ t ⊆ X, M.closure {e} ⊆ M.closure t → a ∈ t) → a = e by + simpa [subset_antisymm_iff, fundCircuit] + simp_rw [← M.closure_inter_ground {e}, singleton_inter_eq_empty.2 heX] + exact fun a haX h ↦ by simpa using h ∅ (empty_subset X) rfl.subset lemma Indep.fundCircuit_circuit (hI : M.Indep I) (hecl : e ∈ M.closure I) (heI : e ∉ I) : M.Circuit (M.fundCircuit e I) := by - apply (hI.inter_right _).insert_circuit_of_forall (by simp [heI]) - · rw [(hI.subset _).closure_inter_eq_inter_closure, mem_inter_iff, and_iff_right hecl, - hI.closure_sInter_eq_biInter_closure_of_forall_subset _ (by simp +contextual)] - · simp - · exact ⟨I, rfl.subset, hecl⟩ - exact union_subset rfl.subset (sInter_subset_of_mem ⟨rfl.subset, hecl⟩) - simp only [mem_inter_iff, mem_sInter, mem_setOf_eq, and_imp] - exact fun f hfI hf hecl ↦ (hf _ (diff_subset.trans inter_subset_left) hecl).2 rfl + have aux : ⋂₀ {J | J ⊆ I ∧ e ∈ M.closure J} ⊆ I := sInter_subset_of_mem (by simpa) + rw [fundCircuit_eq_sInter hecl] + refine (hI.subset aux).insert_circuit_of_forall ?_ ?_ ?_ + · simp [show ∃ x ⊆ I, e ∈ M.closure x ∧ e ∉ x from ⟨I, by simp [hecl, heI]⟩] + · rw [hI.closure_sInter_eq_biInter_closure_of_forall_subset ⟨I, by simpa⟩ (by simp +contextual)] + simp + simp only [mem_sInter, mem_setOf_eq, and_imp] + exact fun f hf hecl ↦ (hf _ (diff_subset.trans aux) hecl).2 rfl lemma Indep.mem_fundCircuit_iff (hI : M.Indep I) (hecl : e ∈ M.closure I) (heI : e ∉ I) : x ∈ M.fundCircuit e I ↔ M.Indep (insert e I \ {x}) := by @@ -260,10 +267,34 @@ lemma Circuit.eq_fundCircuit_of_subset (hC : M.Circuit C) (hI : M.Indep I) (hCss · rw [hI.mem_closure_iff] exact .inl (hC.dep.superset hCss (insert_subset (hC.subset_ground heC) hI.subset_ground)) exact hC.not_indep (hI.subset (hCss.trans (by simp [heI]))) - refine insert_subset heC (inter_subset_right.trans ?_) - refine (sInter_subset_of_mem (t := C \ {e}) ?_).trans diff_subset + rw [fundCircuit_eq_sInter <| + M.closure_subset_closure hCeI <| hC.mem_closure_diff_singleton_of_mem heC] + refine insert_subset heC <| (sInter_subset_of_mem (t := C \ {e}) ?_).trans diff_subset simp [hCss, hC.mem_closure_diff_singleton_of_mem heC] +lemma fundCircuit_restrict {R : Set α} (hIR : I ⊆ R) (heR : e ∈ R) (hR : R ⊆ M.E) : + (M ↾ R).fundCircuit e I = M.fundCircuit e I := by + simp_rw [fundCircuit, M.restrict_closure_eq (R := R) (X := {e}) (by simpa)] + refine subset_antisymm (insert_subset_insert (inter_subset_inter_right _ ?_)) + (insert_subset_insert (inter_subset_inter_right _ ?_)) + · refine subset_sInter fun J ⟨hJI, heJ⟩ ↦ sInter_subset_of_mem ⟨hJI, ?_⟩ + simp only [restrict_closure_eq', union_subset_iff, subset_union_right, and_true] + refine (inter_subset_inter_left _ ?_).trans subset_union_left + rwa [inter_eq_self_of_subset_left (hJI.trans hIR)] + refine subset_sInter fun J ⟨hJI, heJ⟩ ↦ sInter_subset_of_mem + ⟨hJI, M.closure_subset_closure_of_subset_closure ?_⟩ + rw [restrict_closure_eq _ (hJI.trans hIR) hR] at heJ + simp only [subset_inter_iff, inter_subset_right, and_true] at heJ + exact subset_trans (by simpa [M.mem_closure_of_mem' (mem_singleton e) (hR heR)]) heJ + +@[simp] lemma fundCircuit_restrict_univ (M : Matroid α) : + (M ↾ univ).fundCircuit e I = M.fundCircuit e I := by + have aux (A B) : M.closure A ⊆ B ∪ univ \ M.E ↔ M.closure A ⊆ B := by + refine ⟨fun h ↦ ?_, fun h ↦ h.trans subset_union_left⟩ + refine (subset_inter h (M.closure_subset_ground A)).trans ?_ + simp [union_inter_distrib_right] + simp [fundCircuit, aux] + /-! ### Dependence -/ lemma Dep.exists_circuit_subset (hX : M.Dep X) : ∃ C, C ⊆ X ∧ M.Circuit C := by From 956d5148ea1e16f4c0ba1e6f94600d9d200a2967 Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 30 Jan 2025 02:02:06 +0000 Subject: [PATCH 660/681] fix(tech debt): allow multiple paths for adaptation notes (#21241) Reported on [Zulip](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Technical.20Debt.20Counters/near/496481255). --- scripts/technical-debt-metrics.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/technical-debt-metrics.sh b/scripts/technical-debt-metrics.sh index cb037e7bf8b23..0aeb305269931 100755 --- a/scripts/technical-debt-metrics.sh +++ b/scripts/technical-debt-metrics.sh @@ -73,11 +73,14 @@ computeDiff () { # The script uses the fact that a line represents a technical debt if and only if the text before # the first `|` is a number. This is then used for comparison and formatting. tdc () { +# We perform word-splitting "by hand" in the "middle" entries. +# See also the comment on the `read` line in the for-loop that follows the definition of this array. titlesPathsAndRegexes=( "porting notes" "*" "Porting note" "backwards compatibility flags" "*" "set_option.*backward" "skipAssignedInstances flags" "*" "set_option tactic.skipAssignedInstances" - "adaptation notes" ":^Mathlib/Tactic/AdaptationNote.lean" "^[· ]*#adaptation_note" + "adaptation notes" ":^Mathlib/Tactic/AdaptationNote.lean :^Mathlib/Tactic/Linter" + "^[· ]*#adaptation_note" "disabled simpNF lints" "*" "nolint simpNF" "erw" "*" "erw \[" "maxHeartBeats modifications" ":^MathlibTest" "^ *set_option .*maxHeartbeats" @@ -87,13 +90,15 @@ for i in ${!titlesPathsAndRegexes[@]}; do # loop on every 3rd entry and name that entry and the following two if (( i % 3 == 0 )); then title="${titlesPathsAndRegexes[$i]}" - pathspec="${titlesPathsAndRegexes[$(( i + 1 ))]}" + # Here we perform word-splitting: `pathspec` is an array whose entries are the "words" in + # the string `"${titlesPathsAndRegexes[$(( i + 1 ))]}"`. + read -r -a pathspec <<< "${titlesPathsAndRegexes[$(( i + 1 ))]}" regex="${titlesPathsAndRegexes[$(( i + 2 ))]}" if [ "${title}" == "porting notes" ] then fl="-i" # just for porting notes we ignore the case in the regex else fl="--" fi - printf '%s|%s\n' "$(git grep "${fl}" "${regex}" -- ":^scripts" "${pathspec}" | wc -l)" "${title}" + printf '%s|%s\n' "$(git grep "${fl}" "${regex}" -- ":^scripts" "${pathspec[@]}" | wc -l)" "${title}" fi done From 16e417ea1db9867753f0618a2a4446ebe6f7583a Mon Sep 17 00:00:00 2001 From: Johan Commelin Date: Thu, 30 Jan 2025 03:33:25 +0000 Subject: [PATCH 661/681] chore: process a few porting notes (#21227) --- Mathlib/Dynamics/PeriodicPts/Defs.lean | 4 +--- Mathlib/InformationTheory/Hamming.lean | 1 - Mathlib/Testing/Plausible/Functions.lean | 4 ---- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Mathlib/Dynamics/PeriodicPts/Defs.lean b/Mathlib/Dynamics/PeriodicPts/Defs.lean index 7dcc0f82ad5b8..9135c0703e29f 100644 --- a/Mathlib/Dynamics/PeriodicPts/Defs.lean +++ b/Mathlib/Dynamics/PeriodicPts/Defs.lean @@ -201,8 +201,7 @@ theorem isPeriodicPt_of_mem_periodicPts_of_isPeriodicPt_iterate (hx : x ∈ peri (hm : IsPeriodicPt f m (f^[n] x)) : IsPeriodicPt f m x := by rcases hx with ⟨r, hr, hr'⟩ suffices n ≤ (n / r + 1) * r by - -- Porting note: convert used to unfold IsPeriodicPt - change _ = _ + unfold IsPeriodicPt IsFixedPt convert (hm.apply_iterate ((n / r + 1) * r - n)).eq <;> rw [← iterate_add_apply, Nat.sub_add_cancel this, iterate_mul, (hr'.iterate _).eq] rw [Nat.add_mul, one_mul] @@ -333,7 +332,6 @@ theorem not_isPeriodicPt_of_pos_of_lt_minimalPeriod : theorem IsPeriodicPt.minimalPeriod_dvd (hx : IsPeriodicPt f n x) : minimalPeriod f x ∣ n := (eq_or_lt_of_le <| n.zero_le).elim (fun hn0 => hn0 ▸ Nat.dvd_zero _) fun hn0 => - -- Porting note: `Nat.dvd_iff_mod_eq_zero` gained explicit arguments Nat.dvd_iff_mod_eq_zero.2 <| (hx.mod <| isPeriodicPt_minimalPeriod f x).eq_zero_of_lt_minimalPeriod <| Nat.mod_lt _ <| hx.minimalPeriod_pos hn0 diff --git a/Mathlib/InformationTheory/Hamming.lean b/Mathlib/InformationTheory/Hamming.lean index 47a11f3d84615..8f3052167ecdd 100644 --- a/Mathlib/InformationTheory/Hamming.lean +++ b/Mathlib/InformationTheory/Hamming.lean @@ -386,7 +386,6 @@ theorem nndist_eq_hammingDist (x y : Hamming β) : nndist x y = hammingDist (ofHamming x) (ofHamming y) := rfl --- Porting note (https://github.com/leanprover-community/mathlib4/issues/10754): new instance instance : DiscreteTopology (Hamming β) := ⟨rfl⟩ instance : MetricSpace (Hamming β) := .ofT0PseudoMetricSpace _ diff --git a/Mathlib/Testing/Plausible/Functions.lean b/Mathlib/Testing/Plausible/Functions.lean index a8801b6e6b2ad..4238129cc0357 100644 --- a/Mathlib/Testing/Plausible/Functions.lean +++ b/Mathlib/Testing/Plausible/Functions.lean @@ -312,10 +312,6 @@ protected def shrinkPerm {α : Type} [DecidableEq α] : pure <| Perm.slice (i * n) n xs --- Porting note: removed, there is no `sizeof` in the new `Sampleable` --- instance [SizeOf α] : SizeOf (InjectiveFunction α) := --- ⟨fun ⟨xs, _, _⟩ => SizeOf.sizeOf (xs.map Sigma.fst)⟩ - /-- Shrink an injective function slicing a segment in the middle of the domain and removing the corresponding elements in the codomain, hence maintaining the property that one is a permutation of the other. From 14589bd79645c3d7bda26ea6e053d99aa21cab9c Mon Sep 17 00:00:00 2001 From: mathlib4-update-dependencies-bot Date: Thu, 30 Jan 2025 03:59:40 +0000 Subject: [PATCH 662/681] chore: update Mathlib dependencies 2025-01-30 (#21247) This PR updates the Mathlib dependencies. Co-authored-by: F. G. Dorais Co-authored-by: mathlib-bors <150093616+mathlib-bors@users.noreply.github.com> Co-authored-by: Kim Morrison --- Mathlib/Data/Int/Bitwise.lean | 6 +----- lake-manifest.json | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Mathlib/Data/Int/Bitwise.lean b/Mathlib/Data/Int/Bitwise.lean index 3e4f9127bad67..d2f3c2b1a177f 100644 --- a/Mathlib/Data/Int/Bitwise.lean +++ b/Mathlib/Data/Int/Bitwise.lean @@ -6,6 +6,7 @@ Authors: Jeremy Avigad import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Data.Nat.Bitwise import Mathlib.Data.Nat.Size +import Batteries.Data.Int /-! # Bitwise operations on integers @@ -34,11 +35,6 @@ def bodd : ℤ → Bool def bit (b : Bool) : ℤ → ℤ := cond b (2 * · + 1) (2 * ·) -/-- `testBit m n` returns whether the `(n+1)ˢᵗ` least significant bit is `1` or `0`-/ -def testBit : ℤ → ℕ → Bool - | (m : ℕ), n => Nat.testBit m n - | -[m +1], n => !(Nat.testBit m n) - /-- `Int.natBitwise` is an auxiliary definition for `Int.bitwise`. -/ def natBitwise (f : Bool → Bool → Bool) (m n : ℕ) : ℤ := cond (f false false) -[ Nat.bitwise (fun x y => not (f x y)) m n +1] (Nat.bitwise f m n) diff --git a/lake-manifest.json b/lake-manifest.json index d25a63116d4b6..3ca57bbaed1b2 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "61dd72099e98719d33239933316e12894677a843", + "rev": "9a3a71e5626f03b45c7533ce625dc7ba7f46d6ab", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", From e6b6302bd4784e1fc139c4f03b06efd186218e78 Mon Sep 17 00:00:00 2001 From: Scott Carnahan <128885296+ScottCarnahan@users.noreply.github.com> Date: Thu, 30 Jan 2025 06:00:14 +0000 Subject: [PATCH 663/681] feat(RingTheory/HahnSeries): define powerSeriesFamily (#20205) This PR defines a summable family of power series whose elements are non-negative powers of a fixed Hahn series times the coefficients of a formal power series. We will use it to define algebra homomorphisms from rings of formal power series to Hahn series. --- Mathlib.lean | 1 + Mathlib/RingTheory/HahnSeries/Addition.lean | 20 +++- Mathlib/RingTheory/HahnSeries/HEval.lean | 114 ++++++++++++++++++++ 3 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 Mathlib/RingTheory/HahnSeries/HEval.lean diff --git a/Mathlib.lean b/Mathlib.lean index f62f59976932f..a16a9e698db7c 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4543,6 +4543,7 @@ import Mathlib.RingTheory.GradedAlgebra.Noetherian import Mathlib.RingTheory.GradedAlgebra.Radical import Mathlib.RingTheory.HahnSeries.Addition import Mathlib.RingTheory.HahnSeries.Basic +import Mathlib.RingTheory.HahnSeries.HEval import Mathlib.RingTheory.HahnSeries.Multiplication import Mathlib.RingTheory.HahnSeries.PowerSeries import Mathlib.RingTheory.HahnSeries.Summable diff --git a/Mathlib/RingTheory/HahnSeries/Addition.lean b/Mathlib/RingTheory/HahnSeries/Addition.lean index 01acbffb87646..540db756a8086 100644 --- a/Mathlib/RingTheory/HahnSeries/Addition.lean +++ b/Mathlib/RingTheory/HahnSeries/Addition.lean @@ -3,9 +3,10 @@ Copyright (c) 2021 Aaron Anderson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ -import Mathlib.RingTheory.HahnSeries.Basic +import Mathlib.Algebra.BigOperators.Group.Finset.Basic import Mathlib.Algebra.Module.Basic import Mathlib.Algebra.Module.LinearMap.Defs +import Mathlib.RingTheory.HahnSeries.Basic /-! # Additive properties of Hahn series @@ -26,7 +27,7 @@ open Finset Function noncomputable section -variable {Γ Γ' R S U V : Type*} +variable {Γ Γ' R S U V α : Type*} namespace HahnSeries @@ -233,12 +234,25 @@ end Domain end AddMonoid -instance [AddCommMonoid R] : AddCommMonoid (HahnSeries Γ R) := +section AddCommMonoid + +variable [AddCommMonoid R] + +instance : AddCommMonoid (HahnSeries Γ R) := { inferInstanceAs (AddMonoid (HahnSeries Γ R)) with add_comm := fun x y => by ext apply add_comm } +open BigOperators + +@[simp] +theorem coeff_sum {s : Finset α} {x : α → HahnSeries Γ R} (g : Γ) : + (∑ i ∈ s, x i).coeff g = ∑ i ∈ s, (x i).coeff g := + cons_induction rfl (fun i s his hsum => by rw [sum_cons, sum_cons, add_coeff, hsum]) s + +end AddCommMonoid + section AddGroup variable [AddGroup R] diff --git a/Mathlib/RingTheory/HahnSeries/HEval.lean b/Mathlib/RingTheory/HahnSeries/HEval.lean new file mode 100644 index 0000000000000..8af129c21ad4c --- /dev/null +++ b/Mathlib/RingTheory/HahnSeries/HEval.lean @@ -0,0 +1,114 @@ +/- +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.RingTheory.HahnSeries.Summable +import Mathlib.RingTheory.PowerSeries.Basic + +/-! +# A summable family given by a power series + +## Main Definitions + * `HahnSeries.SummableFamily.powerSeriesFamily`: A summable family of Hahn series whose elements + are non-negative powers of a fixed positive-order Hahn series multiplied by the coefficients of a + formal power series. + +## TODO + * `PowerSeries.heval`: An `R`-algebra homomorphism from `PowerSeries R` to `HahnSeries Γ R` taking + `X` to a positive order Hahn Series. + +-/ + +open Finset Function + +open Pointwise + +noncomputable section + +variable {Γ Γ' R V α β σ : Type*} + +namespace HahnSeries + +namespace SummableFamily + +section PowerSeriesFamily + +variable [LinearOrderedCancelAddCommMonoid Γ] [CommRing R] + +variable [CommRing V] [Algebra R V] {x : HahnSeries Γ V} (hx : 0 < x.orderTop) (f : PowerSeries R) + +/-- A summable family given by scalar multiples of powers of a positive order Hahn series. + +The scalar multiples are given by the coefficients of a power series. -/ +abbrev powerSeriesFamily : SummableFamily Γ V ℕ := + smulFamily (fun n => f.coeff R n) (powers x hx) + +@[simp] +theorem powerSeriesFamily_apply (n : ℕ) : + powerSeriesFamily hx f n = f.coeff R n • x ^ n := + rfl + +theorem powerSeriesFamily_add (g : PowerSeries R) : + powerSeriesFamily hx (f + g) = powerSeriesFamily hx f + powerSeriesFamily hx g := by + ext1 n + simp [add_smul] + +theorem powerSeriesFamily_smul (r : R) : + powerSeriesFamily hx (r • f) = HahnSeries.single (0 : Γ) r • powerSeriesFamily hx f := by + ext1 n + simp [mul_smul] + +theorem support_powerSeriesFamily_subset (hx : 0 < x.orderTop) (a b : PowerSeries R) (g : Γ) : + ((powerSeriesFamily hx (a * b)).coeff g).support ⊆ + (((powerSeriesFamily hx a).mul (powerSeriesFamily hx b)).coeff g).support.image + fun i => i.1 + i.2 := by + simp only [coeff_support, smulFamily_toFun, HahnSeries.smul_coeff, Set.Finite.toFinset_subset, + coe_image, support_subset_iff, Set.mem_image, Prod.exists] + intro n hn + simp_rw [PowerSeries.coeff_mul, sum_smul, mul_smul] at hn + have he := exists_ne_zero_of_sum_ne_zero hn + simp only [powers_toFun, mem_antidiagonal] at he + use he.choose.1, he.choose.2 + refine ⟨?_, he.choose_spec.1⟩ + simp only [mul_toFun, smulFamily_toFun, powers_toFun, Algebra.mul_smul_comm, + Algebra.smul_mul_assoc, HahnSeries.smul_coeff, Set.Finite.coe_toFinset, ne_eq, Prod.mk.eta, + Function.mem_support] + rw [← pow_add, smul_comm, he.choose_spec.1] + exact he.choose_spec.2 + +theorem hsum_powerSeriesFamily_mul (hx : 0 < x.orderTop) (a b : PowerSeries R) : + (powerSeriesFamily hx (a * b)).hsum = + ((powerSeriesFamily hx a).mul (powerSeriesFamily hx b)).hsum := by + ext g + simp only [powerSeriesFamily_apply, PowerSeries.coeff_mul, Finset.sum_smul, ← Finset.sum_product, + hsum_coeff_eq_sum, mul_toFun] + rw [sum_subset (support_powerSeriesFamily_subset hx a b g)] + · rw [← coeff_sum, sum_sigma', coeff_sum] + refine (Finset.sum_of_injOn (fun x => ⟨x.1 + x.2, x⟩) (fun _ _ _ _ => by simp_all) ?_ ?_ + (fun _ _ => by simp only [smul_mul_smul_comm, pow_add])).symm + · intro ij hij + simp only [coe_sigma, coe_image, Set.mem_sigma_iff, Set.mem_image, Prod.exists, mem_coe, + mem_antidiagonal, and_true] + use ij.1, ij.2 + simp_all + · intro i hi his + have hisc : ∀ j k : ℕ, ⟨j + k, (j, k)⟩ = i → (PowerSeries.coeff R k) b • + (PowerSeries.coeff R j a • (x ^ j * x ^ k).coeff g) = 0 := by + intro m n + contrapose! + simp only [coeff_support, mul_toFun, smulFamily_toFun, Algebra.mul_smul_comm, + Algebra.smul_mul_assoc, Set.Finite.coe_toFinset, Set.mem_image, + Prod.exists, not_exists, not_and] at his + exact his m n + simp only [mem_sigma, mem_antidiagonal] at hi + rw [mul_comm ((PowerSeries.coeff R i.snd.1) a), ← hi.2, mul_smul, pow_add] + exact hisc i.snd.1 i.snd.2 <| Sigma.eq hi.2 (by simp) + · intro i hi his + simpa [PowerSeries.coeff_mul, sum_smul] using his + +end PowerSeriesFamily + +end SummableFamily + +end HahnSeries From d9b81fae5469664a22397ee2c74f42610bc5a5dd Mon Sep 17 00:00:00 2001 From: Kim Morrison Date: Thu, 30 Jan 2025 06:09:24 +0000 Subject: [PATCH 664/681] chore: fix escaping in create-adaptation-pr.sh (#21246) --- scripts/create-adaptation-pr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create-adaptation-pr.sh b/scripts/create-adaptation-pr.sh index f8b5deb203b7e..b6b193883d576 100755 --- a/scripts/create-adaptation-pr.sh +++ b/scripts/create-adaptation-pr.sh @@ -198,7 +198,7 @@ if git diff --name-only bump/$BUMPVERSION bump/nightly-$NIGHTLYDATE | grep -q .; echo "### [auto] post a link to the PR on Zulip" zulip_title="#$pr_number adaptations for nightly-$NIGHTLYDATE" - zulip_body="> $pr_title #$pr_number"$'\n\nPlease review this PR. At the end of the month this diff will land in `master`.' + zulip_body=$(printf "> %s\n\nPlease review this PR. At the end of the month this diff will land in \`master\`." "$pr_title #$pr_number") echo "Posting the link to the PR in a new thread on the #nightly-testing channel on Zulip" echo "Here is the message:" From 1db0a08e302066b96bd204e7aba61c6add2fa625 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 30 Jan 2025 06:18:02 +0000 Subject: [PATCH 665/681] feat: lemmas about `Matrix.comp` for `diagonal` and `stdBasis` (#21181) --- Mathlib/Data/Matrix/Composition.lean | 89 ++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/Mathlib/Data/Matrix/Composition.lean b/Mathlib/Data/Matrix/Composition.lean index b1d7909c4817e..913f79d916802 100644 --- a/Mathlib/Data/Matrix/Composition.lean +++ b/Mathlib/Data/Matrix/Composition.lean @@ -1,10 +1,11 @@ /- Copyright (c) 2024 Yunzhou Xie. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kevin Buzzard, Yunzhou Xie +Authors: Kevin Buzzard, Yunzhou Xie, Eric Wieser -/ import Mathlib.Data.Matrix.Basic +import Mathlib.Data.Matrix.Basis /-! # Composition of matrices @@ -24,7 +25,7 @@ Semiring, and Algebra over a CommSemiring K. namespace Matrix -variable (I J K L R : Type*) +variable (I J K L R R' : Type*) /-- I by J matrix where each entry is a K by L matrix is equivalent to I × K by J × L matrix -/ @@ -35,6 +36,72 @@ def comp : Matrix I J (Matrix K L R) ≃ Matrix (I × K) (J × L) R where left_inv _ := rfl right_inv _ := rfl +section Basic +variable {R I J K L} + +theorem comp_map_map (M : Matrix I J (Matrix K L R)) (f : R → R') : + comp I J K L _ (M.map (fun M' => M'.map f)) = (comp I J K L _ M).map f := rfl + +@[simp] +theorem comp_stdBasisMatrix_stdBasisMatrix + [DecidableEq I] [DecidableEq J] [DecidableEq K] [DecidableEq L] [Zero R] (i j k l r) : + comp I J K L R (stdBasisMatrix i j (stdBasisMatrix k l r)) + = stdBasisMatrix (i, k) (j, l) r := by + ext ⟨i', k'⟩ ⟨j', l'⟩ + dsimp [comp_apply] + obtain hi | rfl := ne_or_eq i i' + · rw [StdBasisMatrix.apply_of_row_ne hi, + StdBasisMatrix.apply_of_row_ne (ne_of_apply_ne Prod.fst hi), Matrix.zero_apply] + obtain hj | rfl := ne_or_eq j j' + · rw [StdBasisMatrix.apply_of_col_ne _ _ hj, + StdBasisMatrix.apply_of_col_ne _ _ (ne_of_apply_ne Prod.fst hj), Matrix.zero_apply] + rw [StdBasisMatrix.apply_same] + obtain hk | rfl := ne_or_eq k k' + · rw [StdBasisMatrix.apply_of_row_ne hk, + StdBasisMatrix.apply_of_row_ne (ne_of_apply_ne Prod.snd hk)] + obtain hj | rfl := ne_or_eq l l' + · rw [StdBasisMatrix.apply_of_col_ne _ _ hj, + StdBasisMatrix.apply_of_col_ne _ _ (ne_of_apply_ne Prod.snd hj)] + rw [StdBasisMatrix.apply_same, StdBasisMatrix.apply_same] + +@[simp] +theorem comp_symm_stdBasisMatrix + [DecidableEq I] [DecidableEq J] [DecidableEq K] [DecidableEq L] [Zero R] (ii jj r) : + (comp I J K L R).symm (stdBasisMatrix ii jj r) = + (stdBasisMatrix ii.1 jj.1 (stdBasisMatrix ii.2 jj.2 r)) := + (comp I J K L R).symm_apply_eq.2 <| comp_stdBasisMatrix_stdBasisMatrix _ _ _ _ _ |>.symm + + +@[simp] +theorem comp_diagonal_diagonal [DecidableEq I] [DecidableEq J] [Zero R] (d : I → J → R) : + comp I I J J R (diagonal fun i => diagonal fun j => d i j) + = diagonal fun ij => d ij.1 ij.2 := by + ext ⟨i₁, j₁⟩ ⟨i₂, j₂⟩ + dsimp [comp_apply] + obtain hi | rfl := ne_or_eq i₁ i₂ + · rw [diagonal_apply_ne _ hi, diagonal_apply_ne _ (ne_of_apply_ne Prod.fst hi), + Matrix.zero_apply] + rw [diagonal_apply_eq] + obtain hj | rfl := ne_or_eq j₁ j₂ + · rw [diagonal_apply_ne _ hj, diagonal_apply_ne _ (ne_of_apply_ne Prod.snd hj)] + rw [diagonal_apply_eq, diagonal_apply_eq] + +@[simp] +theorem comp_symm_diagonal [DecidableEq I] [DecidableEq J] [Zero R] (d : I × J → R) : + (comp I I J J R).symm (diagonal d) = diagonal fun i => diagonal fun j => d (i, j) := + (comp I I J J R).symm_apply_eq.2 <| (comp_diagonal_diagonal fun i j => d (i, j)).symm + +theorem comp_transpose (M : Matrix I J (Matrix K L R)) : + comp J I K L R Mᵀ = (comp _ _ _ _ R <| M.map (·ᵀ))ᵀ := rfl + +theorem comp_map_transpose (M : Matrix I J (Matrix K L R)) : + comp I J L K R (M.map (·ᵀ)) = (comp _ _ _ _ R Mᵀ)ᵀ := rfl + +theorem comp_symm_transpose (M : Matrix (I × K) (J × L) R) : + (comp J I L K R).symm Mᵀ = (((comp I J K L R).symm M).map (·ᵀ))ᵀ := rfl + +end Basic + section AddCommMonoid variable [AddCommMonoid R] @@ -92,17 +159,17 @@ variable (K : Type*) [CommSemiring K] [Semiring R] [Fintype I] [Fintype J] [Alge variable [DecidableEq I] [DecidableEq J] /-- `Matrix.comp` as `AlgEquiv` -/ -@[simps!] def compAlgEquiv : Matrix I I (Matrix J J R) ≃ₐ[K] Matrix (I × J) (I × J) R where __ := Matrix.compRingEquiv I J R - commutes' c := by - ext _ _ - simp only [compRingEquiv, compAddEquiv, comp, AddEquiv.toEquiv_eq_coe, RingEquiv.toEquiv_eq_coe, - Equiv.toFun_as_coe, EquivLike.coe_coe, RingEquiv.coe_mk, AddEquiv.coe_mk, Equiv.coe_fn_mk, - algebraMap_eq_diagonal] - rw [Pi.algebraMap_def, Pi.algebraMap_def, Algebra.algebraMap_eq_smul_one', - Algebra.algebraMap_eq_smul_one', ← diagonal_one, diagonal_apply, diagonal_apply] - aesop + commutes' _ := comp_diagonal_diagonal _ + +@[simp] +theorem compAlgEquiv_apply (M : Matrix I I (Matrix J J R)) : + compAlgEquiv I J R K M = comp I I J J R M := rfl + +@[simp] +theorem compAlgEquiv_symm_apply (M : Matrix (I × J) (I × J) R) : + (compAlgEquiv I J R K).symm M = (comp I I J J R).symm M := rfl end Algebra From 969f14dc96caa46f3d9ee3cf7ed8c90de047e30b Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 30 Jan 2025 06:18:03 +0000 Subject: [PATCH 666/681] feat: `ext` lemmas for `stdBasisMatrix` (#21200) Additive and linear maps from matrices agree if they agree on `stdBasisMatrix`. Co-authored-by: Eric Wieser --- Mathlib/Data/Matrix/Basis.lean | 49 +++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/Mathlib/Data/Matrix/Basis.lean b/Mathlib/Data/Matrix/Basis.lean index d7eeeed30a977..23c8484a604fd 100644 --- a/Mathlib/Data/Matrix/Basis.lean +++ b/Mathlib/Data/Matrix/Basis.lean @@ -15,7 +15,7 @@ at position `(i, j)`, and zeroes elsewhere. assert_not_exists Matrix.trace variable {l m n : Type*} -variable {R α : Type*} +variable {R α β : Type*} namespace Matrix @@ -124,6 +124,53 @@ protected theorem induction_on simpa using h_std_basis default default 0) h_add h_std_basis +/-- `Matrix.stdBasisMatrix` as a bundled additive map. -/ +@[simps] +def stdBasisMatrixAddMonoidHom [AddCommMonoid α] (i : m) (j : n) : α →+ Matrix m n α where + toFun := stdBasisMatrix i j + map_zero' := stdBasisMatrix_zero _ _ + map_add' _ _ := stdBasisMatrix_add _ _ _ _ + +variable (R) +/-- `Matrix.stdBasisMatrix` as a bundled linear map. -/ +@[simps!] +def stdBasisMatrixLinearMap [Semiring R] [AddCommMonoid α] [Module R α] (i : m) (j : n) : + α →ₗ[R] Matrix m n α where + __ := stdBasisMatrixAddMonoidHom i j + map_smul' _ _:= smul_stdBasisMatrix _ _ _ _ |>.symm + +section ext + +/-- Additive maps from finite matrices are equal if they agree on the standard basis. + +See note [partially-applied ext lemmas]. -/ +@[local ext] +theorem ext_addMonoidHom + [Finite m] [Finite n] [AddCommMonoid α] [AddCommMonoid β] ⦃f g : Matrix m n α →+ β⦄ + (h : ∀ i j, f.comp (stdBasisMatrixAddMonoidHom i j) = g.comp (stdBasisMatrixAddMonoidHom i j)) : + f = g := by + cases nonempty_fintype m + cases nonempty_fintype n + ext x + rw [matrix_eq_sum_stdBasisMatrix x] + simp_rw [map_sum] + congr! 2 + exact DFunLike.congr_fun (h _ _) _ + +/-- Linear maps from finite matrices are equal if they agree on the standard basis. + +See note [partially-applied ext lemmas]. -/ +@[local ext] +theorem ext_linearMap + [Finite m] [Finite n][Semiring R] [AddCommMonoid α] [AddCommMonoid β] [Module R α] [Module R β] + ⦃f g : Matrix m n α →ₗ[R] β⦄ + (h : ∀ i j, f ∘ₗ stdBasisMatrixLinearMap R i j = g ∘ₗ stdBasisMatrixLinearMap R i j) : + f = g := + LinearMap.toAddMonoidHom_injective <| ext_addMonoidHom fun i j => + congrArg LinearMap.toAddMonoidHom <| h i j + +end ext + namespace StdBasisMatrix section From 132efc702f743d24550d2b85b029ea64ffafbcab Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Thu, 30 Jan 2025 07:11:46 +0000 Subject: [PATCH 667/681] feat(Algebra/Category): concrete category refactor for `Grp` (#21192) This is a step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This PR updates the concrete category definitions of `Grp`, `AddGrp`, `CommGrp` and `AddCommGrp` to match the standard set by `AlgebraCat`, `ModuleCat` and `RingCat`: * Package objects and homs into structures. * Replace `HasForget` with `ConcreteCategory`. * Set up a good `@[simp]` set. * Ensure constructors and projections are reducible. See `MathlibTest/CategoryTheory/ConcreteCategory/Grp.lean` for the specification of all the new functionality. In particular, we can drop `coe_of` from the `@[simp]` set, which means we can re-enable some `@[simps]` attributes downstream. (I did the ones I came across, but we'd need to go through the library more carefully to get them all.) Overall I think we get a good cleanup, even if there are a handful of places where we have to fight more against the `HasForget`/`ConcreteCategory` non-reducible defeq. Those should go away as `HasForget` is obsoleted further. I have not tried to look for code that can be cleaned up now, only at what broke. I want to get started on cleanup when the other concrete category instances are in. --- Mathlib/Algebra/Category/Grp/AB.lean | 30 +- Mathlib/Algebra/Category/Grp/Adjunctions.lean | 84 ++-- Mathlib/Algebra/Category/Grp/Basic.lean | 468 ++++++++++++------ Mathlib/Algebra/Category/Grp/Biproducts.lean | 45 +- Mathlib/Algebra/Category/Grp/Colimits.lean | 33 +- .../Category/Grp/EnoughInjectives.lean | 2 +- Mathlib/Algebra/Category/Grp/EpiMono.lean | 136 +++-- .../Grp/EquivalenceGroupAddGroup.lean | 8 +- .../Category/Grp/FilteredColimits.lean | 31 +- Mathlib/Algebra/Category/Grp/FiniteGrp.lean | 10 +- .../Category/Grp/ForgetCorepresentable.lean | 12 +- Mathlib/Algebra/Category/Grp/Images.lean | 47 +- Mathlib/Algebra/Category/Grp/Injective.lean | 4 +- Mathlib/Algebra/Category/Grp/Kernels.lean | 14 +- .../Algebra/Category/Grp/LargeColimits.lean | 11 +- Mathlib/Algebra/Category/Grp/Limits.lean | 43 +- Mathlib/Algebra/Category/Grp/Preadditive.lean | 45 +- Mathlib/Algebra/Category/Grp/Ulift.lean | 6 +- .../Category/Grp/ZModuleEquivalence.lean | 4 +- Mathlib/Algebra/Category/ModuleCat/Basic.lean | 14 +- .../Category/ModuleCat/FilteredColimits.lean | 8 +- .../Algebra/Category/ModuleCat/Presheaf.lean | 8 +- .../Category/ModuleCat/Presheaf/Sheafify.lean | 39 +- .../Algebra/Category/ModuleCat/Tannaka.lean | 8 +- Mathlib/Algebra/Category/Ring/Basic.lean | 2 +- Mathlib/Algebra/Category/Semigrp/Basic.lean | 3 +- .../Algebra/Homology/ConcreteCategory.lean | 28 +- .../DerivedCategory/Ext/ExactSequences.lean | 31 +- .../Homology/HomotopyCategory/HomComplex.lean | 12 +- Mathlib/Algebra/Homology/ImageToKernel.lean | 2 +- Mathlib/Algebra/Homology/ShortComplex/Ab.lean | 28 +- .../ShortComplex/ConcreteCategory.lean | 6 +- .../AlgebraicTopology/TopologicalSimplex.lean | 2 +- .../Normed/Group/SemiNormedGrp/Kernels.lean | 14 +- Mathlib/CategoryTheory/Action/Basic.lean | 21 +- .../ConcreteCategory/Basic.lean | 26 +- .../Galois/Prorepresentability.lean | 8 +- .../Limits/Shapes/ConcreteCategory.lean | 7 +- .../Preadditive/Yoneda/Basic.lean | 8 +- .../Sites/ConcreteSheafification.lean | 39 +- .../Sites/LocallySurjective.lean | 12 +- Mathlib/FieldTheory/Galois/Profinite.lean | 3 +- Mathlib/Order/Category/NonemptyFinLinOrd.lean | 2 +- Mathlib/RepresentationTheory/Invariants.lean | 4 +- .../Algebra/Category/ProfiniteGrp/Basic.lean | 8 +- .../Algebra/Category/ProfiniteGrp/Limits.lean | 6 +- Mathlib/Topology/Category/CompHaus/Basic.lean | 2 +- .../Topology/Category/Profinite/Basic.lean | 4 +- .../Category/TopCat/Limits/Products.lean | 8 +- .../Category/TopCat/Limits/Pullbacks.lean | 27 +- Mathlib/Topology/Gluing.lean | 5 +- .../Topology/Sheaves/LocallySurjective.lean | 2 +- Mathlib/Topology/Sheaves/Presheaf.lean | 4 +- .../Sheaves/SheafCondition/UniqueGluing.lean | 14 +- Mathlib/Topology/Sheaves/Stalks.lean | 23 +- .../CategoryTheory/ConcreteCategory/Grp.lean | 50 ++ 56 files changed, 896 insertions(+), 625 deletions(-) create mode 100644 MathlibTest/CategoryTheory/ConcreteCategory/Grp.lean diff --git a/Mathlib/Algebra/Category/Grp/AB.lean b/Mathlib/Algebra/Category/Grp/AB.lean index 3038d2cedbcac..dc11dad061a23 100644 --- a/Mathlib/Algebra/Category/Grp/AB.lean +++ b/Mathlib/Algebra/Category/Grp/AB.lean @@ -31,16 +31,20 @@ noncomputable instance : simp only [ShortComplex.ab_exact_iff_ker_le_range] at hS ⊢ intro x (hx : _ = _) dsimp at hx - rcases Concrete.colimit_exists_rep S.X₂ x with ⟨j, y, rfl⟩ - rw [← CategoryTheory.comp_apply, colimMap_eq, colimit.ι_map, CategoryTheory.comp_apply, - ← map_zero (by exact colimit.ι S.X₃ j : (S.X₃).obj j →+ ↑(colimit S.X₃))] at hx + -- The type ascription around `rfl` works around a `HasForget`/`ConcreteCategory` mismatch, + -- and should be removed when `Concrete.colimit_exists_rep` takes `ConcreteCategory`. + rcases Concrete.colimit_exists_rep S.X₂ x with ⟨j, y, (rfl : (colimit.ι S.X₂ j) y = _)⟩ + rw [← ConcreteCategory.comp_apply, colimMap_eq, colimit.ι_map, ConcreteCategory.comp_apply, + ← map_zero (colimit.ι S.X₃ j).hom] at hx + -- The type ascription around `hk` works around a `HasForget`/`ConcreteCategory` mismatch, + -- and should be removed when `Concrete.colimit_exists_rep` takes `ConcreteCategory`. rcases Concrete.colimit_exists_of_rep_eq.{u, u, u} S.X₃ _ _ hx - with ⟨k, e₁, e₂, hk : _ = S.X₃.map e₂ 0⟩ - rw [map_zero, ← CategoryTheory.comp_apply, ← NatTrans.naturality, CategoryTheory.comp_apply] + with ⟨k, e₁, e₂, hk : (S.X₃.map e₁) _ = S.X₃.map e₂ 0⟩ + rw [map_zero, ← ConcreteCategory.comp_apply, ← NatTrans.naturality, ConcreteCategory.comp_apply] at hk rcases hS k hk with ⟨t, ht⟩ use colimit.ι S.X₁ k t - erw [← CategoryTheory.comp_apply, colimit.ι_map, CategoryTheory.comp_apply, ht] + erw [← ConcreteCategory.comp_apply, colimit.ι_map, ConcreteCategory.comp_apply, ht] exact colimit.w_apply S.X₂ e₁ y) noncomputable instance : @@ -66,13 +70,13 @@ instance : HasExactLimitsOfShape (Discrete J) (AddCommGrp.{u}) := by let iY : limit Y ≅ AddCommGrp.of ((i : J) → Y.obj ⟨i⟩) := (Pi.isoLimit Y).symm ≪≫ (limit.isLimit _).conePointUniqueUpToIso (AddCommGrp.HasLimit.productLimitCone _).isLimit have : Pi.map (fun i ↦ f.app ⟨i⟩) = iX.inv ≫ lim.map f ≫ iY.hom := by - simp only [AddCommGrp.coe_of, Functor.comp_obj, Discrete.functor_obj_eq_as, Discrete.mk_as, - Pi.isoLimit, IsLimit.conePointUniqueUpToIso, limit.cone, - AddCommGrp.HasLimit.productLimitCone, Iso.trans_inv, Functor.mapIso_inv, - IsLimit.uniqueUpToIso_inv, Cones.forget_map, IsLimit.liftConeMorphism_hom, - limit.isLimit_lift, Iso.symm_inv, Functor.mapIso_hom, IsLimit.uniqueUpToIso_hom, lim_obj, - lim_map, Iso.trans_hom, Iso.symm_hom, AddCommGrp.HasLimit.lift, Functor.const_obj_obj, - Category.assoc, limit.lift_map_assoc, Pi.cone_pt, iX, iY] + simp only [Functor.comp_obj, Discrete.functor_obj_eq_as, Discrete.mk_as, Pi.isoLimit, + IsLimit.conePointUniqueUpToIso, limit.cone, AddCommGrp.HasLimit.productLimitCone, + Iso.trans_inv, Functor.mapIso_inv, IsLimit.uniqueUpToIso_inv, Cones.forget_map, + IsLimit.liftConeMorphism_hom, limit.isLimit_lift, Iso.symm_inv, Functor.mapIso_hom, + IsLimit.uniqueUpToIso_hom, lim_obj, lim_map, Iso.trans_hom, Iso.symm_hom, + AddCommGrp.HasLimit.lift, Functor.const_obj_obj, Category.assoc, limit.lift_map_assoc, + Pi.cone_pt, iX, iY] ext g j change _ = (_ ≫ limit.π (Discrete.functor fun j ↦ Y.obj { as := j }) ⟨j⟩) _ simp only [Discrete.functor_obj_eq_as, Functor.comp_obj, Discrete.mk_as, productIsProduct', diff --git a/Mathlib/Algebra/Category/Grp/Adjunctions.lean b/Mathlib/Algebra/Category/Grp/Adjunctions.lean index a105b0a20ccac..6f09e708ff764 100644 --- a/Mathlib/Algebra/Category/Grp/Adjunctions.lean +++ b/Mathlib/Algebra/Category/Grp/Adjunctions.lean @@ -45,9 +45,9 @@ free abelian group with generators `x : X`. -/ def free : Type u ⥤ AddCommGrp where obj α := of (FreeAbelianGroup α) - map := FreeAbelianGroup.map - map_id _ := AddMonoidHom.ext FreeAbelianGroup.map_id_apply - map_comp _ _ := AddMonoidHom.ext FreeAbelianGroup.map_comp_apply + map f := ofHom (FreeAbelianGroup.map f) + map_id _ := AddCommGrp.ext FreeAbelianGroup.map_id_apply + map_comp _ _ := AddCommGrp.ext FreeAbelianGroup.map_comp_apply @[simp] theorem free_obj_coe {α : Type u} : (free.obj α : Type u) = FreeAbelianGroup α := @@ -64,12 +64,12 @@ theorem free_map_coe {α β : Type u} {f : α → β} (x : FreeAbelianGroup α) -/ def adj : free ⊣ forget AddCommGrp.{u} := Adjunction.mkOfHomEquiv - { homEquiv := fun _ _ => FreeAbelianGroup.lift.symm + { homEquiv := fun _ _ => ConcreteCategory.homEquiv.trans FreeAbelianGroup.lift.symm -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): used to be just `by intros; ext; rfl`. homEquiv_naturality_left_symm := by intros ext - simp only [Equiv.symm_symm] + simp apply FreeAbelianGroup.lift_comp } instance : free.{u}.IsLeftAdjoint := @@ -110,28 +110,20 @@ namespace Grp -/ def free : Type u ⥤ Grp where obj α := of (FreeGroup α) - map := FreeGroup.map - map_id := by - -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - intros; ext1; erw [← FreeGroup.map.unique] <;> intros <;> rfl - map_comp := by - -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - intros; ext1; erw [← FreeGroup.map.unique] <;> intros <;> rfl + map f := ofHom (FreeGroup.map f) /-- The free-forgetful adjunction for groups. -/ def adj : free ⊣ forget Grp.{u} := Adjunction.mkOfHomEquiv - { homEquiv := fun _ _ => FreeGroup.lift.symm - -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): used to be just `by intros; ext1; rfl`. + { homEquiv := fun _ _ => ConcreteCategory.homEquiv.trans FreeGroup.lift.symm homEquiv_naturality_left_symm := by intros - ext1 - simp only [Equiv.symm_symm] - apply Eq.symm - apply FreeGroup.lift.unique + ext : 1 + -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): `ext` doesn't apply this theorem anymore + apply FreeGroup.ext_hom intros - apply FreeGroup.lift.of } + rfl } instance : (forget Grp.{u}).IsRightAdjoint := ⟨_, ⟨adj⟩⟩ @@ -142,22 +134,30 @@ section Abelianization -/ def abelianize : Grp.{u} ⥤ CommGrp.{u} where obj G := CommGrp.of (Abelianization G) - map f := Abelianization.lift (Abelianization.of.comp f) + map f := CommGrp.ofHom (Abelianization.lift (Abelianization.of.comp f.hom)) map_id := by - intros; simp only [coe_id] - apply (Equiv.apply_eq_iff_eq_symm_apply Abelianization.lift).mpr; rfl + intros + simp only [coe_id] + ext : 1 + apply (Equiv.apply_eq_iff_eq_symm_apply Abelianization.lift).mpr + rfl map_comp := by - intros; simp only [coe_comp] - apply (Equiv.apply_eq_iff_eq_symm_apply Abelianization.lift).mpr; rfl + intros + simp only [coe_comp] + ext : 1 + apply (Equiv.apply_eq_iff_eq_symm_apply Abelianization.lift).mpr + rfl /-- The abelianization-forgetful adjuction from `Group` to `CommGroup`. -/ def abelianizeAdj : abelianize ⊣ forget₂ CommGrp.{u} Grp.{u} := Adjunction.mkOfHomEquiv - { homEquiv := fun _ _ => Abelianization.lift.symm + { homEquiv := fun _ _ => ((ConcreteCategory.homEquiv (C := CommGrp)).trans + Abelianization.lift.symm).trans + (ConcreteCategory.homEquiv (C := Grp)).symm -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): used to be just `by intros; ext1; rfl`. homEquiv_naturality_left_symm := by intros - ext1 + ext simp only [Equiv.symm_symm] apply Eq.symm apply Abelianization.lift.unique @@ -173,19 +173,19 @@ end Grp def MonCat.units : MonCat.{u} ⥤ Grp.{u} where obj R := Grp.of Rˣ map f := Grp.ofHom <| Units.map f - map_id _ := MonoidHom.ext fun _ => Units.ext rfl - map_comp _ _ := MonoidHom.ext fun _ => Units.ext rfl + map_id _ := Grp.ext fun _ => Units.ext rfl + map_comp _ _ := Grp.ext fun _ => Units.ext rfl /-- The forgetful-units adjunction between `Grp` and `MonCat`. -/ def Grp.forget₂MonAdj : forget₂ Grp MonCat ⊣ MonCat.units.{u} := Adjunction.mk' { homEquiv := fun _ Y ↦ - { toFun := fun f => MonoidHom.toHomUnits f - invFun := fun f => (Units.coeHom Y).comp f + { toFun := fun f => ofHom (MonoidHom.toHomUnits f) + invFun := fun f => (Units.coeHom Y).comp f.hom left_inv := fun _ => MonoidHom.ext fun _ => rfl - right_inv := fun _ => MonoidHom.ext fun _ => Units.ext rfl } + right_inv := fun _ => Grp.ext fun _ => Units.ext rfl } unit := - { app := fun X => { (@toUnits X _).toMonoidHom with } - naturality := fun _ _ _ => MonoidHom.ext fun _ => Units.ext rfl } + { app := fun X => ofHom { (@toUnits X _).toMonoidHom with } + naturality := fun _ _ _ => Grp.ext fun _ => Units.ext rfl } counit := { app := fun X => Units.coeHom X naturality := by intros; exact MonoidHom.ext fun x => rfl } } @@ -198,23 +198,19 @@ instance : MonCat.units.{u}.IsRightAdjoint := def CommMonCat.units : CommMonCat.{u} ⥤ CommGrp.{u} where obj R := CommGrp.of Rˣ map f := CommGrp.ofHom <| Units.map f - map_id _ := MonoidHom.ext fun _ => Units.ext rfl - map_comp _ _ := MonoidHom.ext fun _ => Units.ext rfl + map_id _ := CommGrp.ext fun _ => Units.ext rfl + map_comp _ _ := CommGrp.ext fun _ => Units.ext rfl /-- The forgetful-units adjunction between `CommGrp` and `CommMonCat`. -/ def CommGrp.forget₂CommMonAdj : forget₂ CommGrp CommMonCat ⊣ CommMonCat.units.{u} := Adjunction.mk' { homEquiv := fun _ Y ↦ - { toFun := fun f => MonoidHom.toHomUnits f - invFun := fun f => (Units.coeHom Y).comp f + { toFun := fun f => ofHom (MonoidHom.toHomUnits f) + invFun := fun f => (Units.coeHom Y).comp f.hom left_inv := fun _ => MonoidHom.ext fun _ => rfl - right_inv := fun _ => MonoidHom.ext fun _ => Units.ext rfl } - unit := - { app := fun X => { (@toUnits X _).toMonoidHom with } - naturality := fun _ _ _ => MonoidHom.ext fun _ => Units.ext rfl } - counit := - { app := fun X => Units.coeHom X - naturality := by intros; exact MonoidHom.ext fun x => rfl } } + right_inv := fun _ => CommGrp.ext fun _ => Units.ext rfl } + unit := { app := fun X => ofHom { (@toUnits X _).toMonoidHom with } } + counit := { app := fun X => Units.coeHom X } } instance : CommMonCat.units.{u}.IsRightAdjoint := ⟨_, ⟨CommGrp.forget₂CommMonAdj⟩⟩ diff --git a/Mathlib/Algebra/Category/Grp/Basic.lean b/Mathlib/Algebra/Category/Grp/Basic.lean index 356b887d22a5c..6377a92fe08f5 100644 --- a/Mathlib/Algebra/Category/Grp/Basic.lean +++ b/Mathlib/Algebra/Category/Grp/Basic.lean @@ -24,43 +24,89 @@ universe u v open CategoryTheory +/-- The category of additive groups and group morphisms. -/ +structure AddGrp : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : AddGroup carrier] + /-- The category of groups and group morphisms. -/ @[to_additive] -def Grp : Type (u + 1) := - Bundled Group +structure Grp : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : Group carrier] + +attribute [instance] AddGrp.str Grp.str +attribute [to_additive existing] Grp.carrier Grp.str -/-- The category of additive groups and group morphisms -/ -add_decl_doc AddGrp +initialize_simps_projections AddGrp (carrier → coe, -str) +initialize_simps_projections Grp (carrier → coe, -str) namespace Grp @[to_additive] -instance : BundledHom.ParentProjection - (fun {α : Type*} (h : Group α) => h.toDivInvMonoid.toMonoid) := ⟨⟩ +instance : CoeSort Grp (Type u) := + ⟨Grp.carrier⟩ -deriving instance LargeCategory for Grp -attribute [to_additive] instGrpLargeCategory +attribute [coe] AddGrp.carrier Grp.carrier -@[to_additive] -instance hasForget : HasForget Grp := by - dsimp only [Grp] - infer_instance +/-- Construct a bundled `Grp` from the underlying type and typeclass. -/ +@[to_additive "Construct a bundled `AddGrp` from the underlying type and typeclass."] +abbrev of (M : Type u) [Group M] : Grp := ⟨M⟩ -@[to_additive] -instance : CoeSort Grp Type* where - coe X := X.α +end Grp -@[to_additive] -instance (X : Grp) : Group X := X.str +/-- The type of morphisms in `AddGrp R`. -/ +@[ext] +structure AddGrp.Hom (A B : AddGrp.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →+ B + +/-- The type of morphisms in `Grp R`. -/ +@[to_additive, ext] +structure Grp.Hom (A B : Grp.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →* B + +attribute [to_additive existing AddGrp.Hom.mk] Grp.Hom.mk + +namespace Grp --- Porting note (https://github.com/leanprover-community/mathlib4/pull/10670): this instance was not necessary in mathlib @[to_additive] -instance {X Y : Grp} : CoeFun (X ⟶ Y) fun _ => X → Y where - coe (f : X →* Y) := f +instance : Category Grp.{u} where + Hom X Y := Hom X Y + id X := ⟨MonoidHom.id X⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ @[to_additive] -instance instFunLike (X Y : Grp) : FunLike (X ⟶ Y) X Y := - show FunLike (X →* Y) X Y from inferInstance +instance : ConcreteCategory Grp (· →* ·) where + hom := Hom.hom' + ofHom := Hom.mk + +/-- Turn a morphism in `Grp` back into a `MonoidHom`. -/ +@[to_additive "Turn a morphism in `AddGrp` back into an `AddMonoidHom`."] +abbrev Hom.hom {X Y : Grp.{u}} (f : Hom X Y) := + ConcreteCategory.hom (C := Grp) f + +/-- Typecheck a `MonoidHom` as a morphism in `Grp`. -/ +@[to_additive "Typecheck an `AddMonoidHom` as a morphism in `AddGrp`. "] +abbrev ofHom {X Y : Type u} [Group X] [Group Y] (f : X →* Y) : of X ⟶ of Y := + ConcreteCategory.ofHom (C := Grp) f + +variable {R} in +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (X Y : Grp.{u}) (f : Hom X Y) := + f.hom + +initialize_simps_projections Hom (hom' → hom) +initialize_simps_projections AddGrp.Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[to_additive (attr := simp)] lemma coe_id {X : Grp} : (𝟙 X : X → X) = id := rfl @@ -68,76 +114,107 @@ lemma coe_id {X : Grp} : (𝟙 X : X → X) = id := rfl @[to_additive (attr := simp)] lemma coe_comp {X Y Z : Grp} {f : X ⟶ Y} {g : Y ⟶ Z} : (f ≫ g : X → Z) = g ∘ f := rfl -@[to_additive] -lemma comp_def {X Y Z : Grp} {f : X ⟶ Y} {g : Y ⟶ Z} : f ≫ g = g.comp f := rfl +@[to_additive (attr := deprecated "Use hom_comp instead" (since := "2025-01-28"))] +lemma comp_def {X Y Z : Grp} {f : X ⟶ Y} {g : Y ⟶ Z} : (f ≫ g).hom = g.hom.comp f.hom := rfl @[simp] lemma forget_map {X Y : Grp} (f : X ⟶ Y) : (forget Grp).map f = (f : X → Y) := rfl @[to_additive (attr := ext)] lemma ext {X Y : Grp} {f g : X ⟶ Y} (w : ∀ x : X, f x = g x) : f = g := - MonoidHom.ext w + ConcreteCategory.hom_ext _ _ w -/-- Construct a bundled `Group` from the underlying type and typeclass. -/ @[to_additive] -def of (X : Type u) [Group X] : Grp := - Bundled.of X +-- This is not `simp` to avoid rewriting in types of terms. +theorem coe_of (R : Type u) [Group R] : ↑(Grp.of R) = R := + rfl + +@[to_additive (attr := simp)] +lemma hom_id {X : Grp} : (𝟙 X : X ⟶ X).hom = MonoidHom.id X := rfl -/-- Construct a bundled `AddGroup` from the underlying type and typeclass. -/ -add_decl_doc AddGrp.of +/- Provided for rewriting. -/ +@[to_additive] +lemma id_apply (X : Grp) (x : X) : + (𝟙 X : X ⟶ X) x = x := by simp @[to_additive (attr := simp)] -theorem coe_of (R : Type u) [Group R] : ↑(Grp.of R) = R := - rfl +lemma hom_comp {X Y T : Grp} (f : X ⟶ Y) (g : Y ⟶ T) : + (f ≫ g).hom = g.hom.comp f.hom := rfl + +/- Provided for rewriting. -/ +@[to_additive] +lemma comp_apply {X Y T : Grp} (f : X ⟶ Y) (g : Y ⟶ T) (x : X) : + (f ≫ g) x = g (f x) := by simp + +@[to_additive (attr := ext)] +lemma hom_ext {X Y : Grp} {f g : X ⟶ Y} (hf : f.hom = g.hom) : f = g := + Hom.ext hf @[to_additive (attr := simp)] -theorem coe_comp' {G H K : Type _} [Group G] [Group H] [Group K] (f : G →* H) (g : H →* K) : - @DFunLike.coe (G →* K) G (fun _ ↦ K) MonoidHom.instFunLike (CategoryStruct.comp - (X := Grp.of G) (Y := Grp.of H) (Z := Grp.of K) f g) = g ∘ f := - rfl +lemma hom_ofHom {R S : Type u} [Group R] [Group S] (f : R →* S) : (ofHom f).hom = f := rfl + +@[to_additive (attr := simp)] +lemma ofHom_hom {X Y : Grp} (f : X ⟶ Y) : + ofHom (Hom.hom f) = f := rfl @[to_additive (attr := simp)] -theorem coe_id' {G : Type _} [Group G] : - @DFunLike.coe (G →* G) G (fun _ ↦ G) MonoidHom.instFunLike - (CategoryStruct.id (X := Grp.of G)) = id := +lemma ofHom_id {X : Type u} [Group X] : ofHom (MonoidHom.id X) = 𝟙 (of X) := rfl + +@[to_additive (attr := simp)] +lemma ofHom_comp {X Y Z : Type u} [Group X] [Group Y] [Group Z] + (f : X →* Y) (g : Y →* Z) : + ofHom (g.comp f) = ofHom f ≫ ofHom g := rfl +@[to_additive] +lemma ofHom_apply {X Y : Type u} [Group X] [Group Y] (f : X →* Y) (x : X) : + (ofHom f) x = f x := rfl + +@[to_additive (attr := simp)] +lemma inv_hom_apply {X Y : Grp} (e : X ≅ Y) (x : X) : e.inv (e.hom x) = x := by + rw [← comp_apply] + simp + +@[to_additive (attr := simp)] +lemma hom_inv_apply {X Y : Grp} (e : X ≅ Y) (s : Y) : e.hom (e.inv s) = s := by + rw [← comp_apply] + simp + +@[to_additive (attr := deprecated "use `coe_comp` instead" (since := "2025-01-28"))] +alias coe_comp' := coe_comp + +@[to_additive (attr := deprecated "use `coe_id` instead" (since := "2025-01-28"))] +alias coe_id' := coe_id + @[to_additive] instance : Inhabited Grp := ⟨Grp.of PUnit⟩ @[to_additive hasForgetToAddMonCat] -instance hasForgetToMonCat : HasForget₂ Grp MonCat := - BundledHom.forget₂ _ _ +instance hasForgetToMonCat : HasForget₂ Grp MonCat where + forget₂.obj X := MonCat.of X + forget₂.map f := MonCat.ofHom f.hom + +@[to_additive (attr := simp)] lemma forget₂_map_ofHom {X Y : Type u} [Group X] [Group Y] + (f : X →* Y) : + (forget₂ Grp MonCat).map (ofHom f) = MonCat.ofHom f := rfl @[to_additive] instance : Coe Grp.{u} MonCat.{u} where coe := (forget₂ Grp MonCat).obj @[to_additive] -instance (G H : Grp) : One (G ⟶ H) := (inferInstance : One (MonoidHom G H)) +instance (G H : Grp) : One (G ⟶ H) where + one := ofHom 1 @[to_additive (attr := simp)] theorem one_apply (G H : Grp) (g : G) : ((1 : G ⟶ H) : G → H) g = 1 := rfl -/-- Typecheck a `MonoidHom` as a morphism in `Grp`. -/ -@[to_additive] -def ofHom {X Y : Type u} [Group X] [Group Y] (f : X →* Y) : of X ⟶ of Y := - f - -/-- Typecheck an `AddMonoidHom` as a morphism in `AddGroup`. -/ -add_decl_doc AddGrp.ofHom - -@[to_additive] -theorem ofHom_apply {X Y : Type _} [Group X] [Group Y] (f : X →* Y) (x : X) : - (ofHom f) x = f x := - rfl - @[to_additive] lemma ofHom_injective {X Y : Type u} [Group X] [Group Y] : Function.Injective (fun (f : X →* Y) ↦ ofHom f) := by intro _ _ h ext - apply DFunLike.congr_fun h + apply ConcreteCategory.congr_hom h @[to_additive] instance ofUnique (G : Type*) [Group G] [i : Unique G] : Unique (Grp.of G) := i @@ -147,24 +224,35 @@ instance ofUnique (G : Type*) [Group G] [i : Unique G] : Unique (Grp.of G) := i example {R S : Grp} (i : R ⟶ S) (r : R) (h : r = 1) : i r = 1 := by simp [h] /-- Universe lift functor for groups. -/ -@[to_additive (attr := simps) +@[to_additive (attr := simps obj map) "Universe lift functor for additive groups."] def uliftFunctor : Grp.{v} ⥤ Grp.{max v u} where obj X := Grp.of (ULift.{u, v} X) map {_ _} f := Grp.ofHom <| - MulEquiv.ulift.symm.toMonoidHom.comp <| f.comp MulEquiv.ulift.toMonoidHom + MulEquiv.ulift.symm.toMonoidHom.comp <| f.hom.comp MulEquiv.ulift.toMonoidHom map_id X := by rfl map_comp {X Y Z} f g := by rfl end Grp -/-- The category of commutative groups and group morphisms. -/ +/-- The category of additive groups and group morphisms. -/ +structure AddCommGrp : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : AddCommGroup carrier] + +/-- The category of groups and group morphisms. -/ @[to_additive] -def CommGrp : Type (u + 1) := - Bundled CommGroup +structure CommGrp : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : CommGroup carrier] -/-- The category of additive commutative groups and group morphisms. -/ -add_decl_doc AddCommGrp +attribute [instance] AddCommGrp.str CommGrp.str +attribute [to_additive existing] CommGrp.carrier CommGrp.str + +initialize_simps_projections AddCommGrp (carrier → coe, -str) +initialize_simps_projections CommGrp (carrier → coe, -str) /-- `Ab` is an abbreviation for `AddCommGroup`, for the sake of mathematicians' sanity. -/ abbrev Ab := AddCommGrp @@ -172,31 +260,67 @@ abbrev Ab := AddCommGrp namespace CommGrp @[to_additive] -instance : BundledHom.ParentProjection @CommGroup.toGroup := ⟨⟩ +instance : CoeSort CommGrp (Type u) := + ⟨CommGrp.carrier⟩ -deriving instance LargeCategory for CommGrp -attribute [to_additive] instCommGrpLargeCategory +attribute [coe] AddCommGrp.carrier CommGrp.carrier -@[to_additive] -instance hasForget : HasForget CommGrp := by - dsimp only [CommGrp] - infer_instance +/-- Construct a bundled `CommGrp` from the underlying type and typeclass. -/ +@[to_additive "Construct a bundled `AddCommGrp` from the underlying type and typeclass."] +abbrev of (M : Type u) [CommGroup M] : CommGrp := ⟨M⟩ -@[to_additive] -instance : CoeSort CommGrp Type* where - coe X := X.α +end CommGrp -@[to_additive] -instance commGroupInstance (X : CommGrp) : CommGroup X := X.str +/-- The type of morphisms in `AddCommGrp R`. -/ +@[ext] +structure AddCommGrp.Hom (A B : AddCommGrp.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →+ B + +/-- The type of morphisms in `CommGrp R`. -/ +@[to_additive, ext] +structure CommGrp.Hom (A B : CommGrp.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →* B + +attribute [to_additive existing AddCommGrp.Hom.mk] CommGrp.Hom.mk + +namespace CommGrp --- Porting note (https://github.com/leanprover-community/mathlib4/pull/10670): this instance was not necessary in mathlib @[to_additive] -instance {X Y : CommGrp} : CoeFun (X ⟶ Y) fun _ => X → Y where - coe (f : X →* Y) := f +instance : Category CommGrp.{u} where + Hom X Y := Hom X Y + id X := ⟨MonoidHom.id X⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ @[to_additive] -instance instFunLike (X Y : CommGrp) : FunLike (X ⟶ Y) X Y := - show FunLike (X →* Y) X Y from inferInstance +instance : ConcreteCategory CommGrp (· →* ·) where + hom := Hom.hom' + ofHom := Hom.mk + +/-- Turn a morphism in `CommGrp` back into a `MonoidHom`. -/ +@[to_additive "Turn a morphism in `AddCommGrp` back into an `AddMonoidHom`."] +abbrev Hom.hom {X Y : CommGrp.{u}} (f : Hom X Y) := + ConcreteCategory.hom (C := CommGrp) f + +/-- Typecheck a `MonoidHom` as a morphism in `CommGrp`. -/ +@[to_additive "Typecheck an `AddMonoidHom` as a morphism in `AddCommGrp`. "] +abbrev ofHom {X Y : Type u} [CommGroup X] [CommGroup Y] (f : X →* Y) : of X ⟶ of Y := + ConcreteCategory.ofHom (C := CommGrp) f + +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +@[to_additive "Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas."] +def Hom.Simps.hom (X Y : CommGrp.{u}) (f : Hom X Y) := + f.hom + +initialize_simps_projections Hom (hom' → hom) +initialize_simps_projections AddCommGrp.Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[to_additive (attr := simp)] lemma coe_id {X : CommGrp} : (𝟙 X : X → X) = id := rfl @@ -204,8 +328,8 @@ lemma coe_id {X : CommGrp} : (𝟙 X : X → X) = id := rfl @[to_additive (attr := simp)] lemma coe_comp {X Y Z : CommGrp} {f : X ⟶ Y} {g : Y ⟶ Z} : (f ≫ g : X → Z) = g ∘ f := rfl -@[to_additive] -lemma comp_def {X Y Z : CommGrp} {f : X ⟶ Y} {g : Y ⟶ Z} : f ≫ g = g.comp f := rfl +@[to_additive (attr := deprecated "Use hom_comp instead" (since := "2025-01-28"))] +lemma comp_def {X Y Z : CommGrp} {f : X ⟶ Y} {g : Y ⟶ Z} : (f ≫ g).hom = g.hom.comp f.hom := rfl @[to_additive (attr := simp)] lemma forget_map {X Y : CommGrp} (f : X ⟶ Y) : @@ -214,93 +338,129 @@ lemma forget_map {X Y : CommGrp} (f : X ⟶ Y) : @[to_additive (attr := ext)] lemma ext {X Y : CommGrp} {f g : X ⟶ Y} (w : ∀ x : X, f x = g x) : f = g := - MonoidHom.ext w + ConcreteCategory.hom_ext _ _ w -/-- Construct a bundled `CommGroup` from the underlying type and typeclass. -/ @[to_additive] -def of (G : Type u) [CommGroup G] : CommGrp := - Bundled.of G +instance : Inhabited CommGrp := + ⟨CommGrp.of PUnit⟩ -/-- Construct a bundled `AddCommGroup` from the underlying type and typeclass. -/ -add_decl_doc AddCommGrp.of +@[to_additive] +-- This is not `simp` to avoid rewriting in types of terms. +theorem coe_of (R : Type u) [CommGroup R] : ↑(CommGrp.of R) = R := + rfl + +@[to_additive (attr := simp)] +lemma hom_id {X : CommGrp} : (𝟙 X : X ⟶ X).hom = MonoidHom.id X := rfl +/- Provided for rewriting. -/ @[to_additive] -instance : Inhabited CommGrp := - ⟨CommGrp.of PUnit⟩ +lemma id_apply (X : CommGrp) (x : X) : + (𝟙 X : X ⟶ X) x = x := by simp @[to_additive (attr := simp)] -theorem coe_of (R : Type u) [CommGroup R] : (CommGrp.of R : Type u) = R := - rfl +lemma hom_comp {X Y T : CommGrp} (f : X ⟶ Y) (g : Y ⟶ T) : + (f ≫ g).hom = g.hom.comp f.hom := rfl + +/- Provided for rewriting. -/ +@[to_additive] +lemma comp_apply {X Y T : CommGrp} (f : X ⟶ Y) (g : Y ⟶ T) (x : X) : + (f ≫ g) x = g (f x) := by simp + +@[to_additive (attr := ext)] +lemma hom_ext {X Y : CommGrp} {f g : X ⟶ Y} (hf : f.hom = g.hom) : f = g := + Hom.ext hf @[to_additive (attr := simp)] -theorem coe_comp' {G H K : Type _} [CommGroup G] [CommGroup H] [CommGroup K] - (f : G →* H) (g : H →* K) : - @DFunLike.coe (G →* K) G (fun _ ↦ K) MonoidHom.instFunLike (CategoryStruct.comp - (X := CommGrp.of G) (Y := CommGrp.of H) (Z := CommGrp.of K) f g) = g ∘ f := - rfl +lemma hom_ofHom {X Y : Type u} [CommGroup X] [CommGroup Y] (f : X →* Y) : + (ofHom f).hom = f := rfl + +@[to_additive (attr := simp)] +lemma ofHom_hom {X Y : CommGrp} (f : X ⟶ Y) : + ofHom (Hom.hom f) = f := rfl @[to_additive (attr := simp)] -theorem coe_id' {G : Type _} [CommGroup G] : - @DFunLike.coe (G →* G) G (fun _ ↦ G) MonoidHom.instFunLike - (CategoryStruct.id (X := CommGrp.of G)) = id := +lemma ofHom_id {X : Type u} [CommGroup X] : ofHom (MonoidHom.id X) = 𝟙 (of X) := rfl + +@[to_additive (attr := simp)] +lemma ofHom_comp {X Y Z : Type u} [CommGroup X] [CommGroup Y] [CommGroup Z] + (f : X →* Y) (g : Y →* Z) : + ofHom (g.comp f) = ofHom f ≫ ofHom g := rfl +@[to_additive] +lemma ofHom_apply {X Y : Type u} [CommGroup X] [CommGroup Y] (f : X →* Y) (x : X) : + (ofHom f) x = f x := rfl + +@[to_additive (attr := simp)] +lemma inv_hom_apply {X Y : CommGrp} (e : X ≅ Y) (x : X) : e.inv (e.hom x) = x := by + rw [← comp_apply] + simp + +@[to_additive (attr := simp)] +lemma hom_inv_apply {X Y : CommGrp} (e : X ≅ Y) (s : Y) : e.hom (e.inv s) = s := by + rw [← comp_apply] + simp + +@[to_additive (attr := deprecated "use `coe_comp` instead" (since := "2025-01-28"))] +alias coe_comp' := coe_comp + +@[to_additive (attr := deprecated "use `coe_id` instead" (since := "2025-01-28"))] +alias coe_id' := coe_id + @[to_additive] instance ofUnique (G : Type*) [CommGroup G] [i : Unique G] : Unique (CommGrp.of G) := i @[to_additive] -instance hasForgetToGroup : HasForget₂ CommGrp Grp := - BundledHom.forget₂ _ _ +instance hasForgetToGroup : HasForget₂ CommGrp Grp where + forget₂.obj X := Grp.of X + forget₂.map f := Grp.ofHom f.hom + +@[to_additive (attr := simp)] lemma forget₂_grp_map_ofHom {X Y : Type u} [CommGroup X] [CommGroup Y] + (f : X →* Y) : + (forget₂ CommGrp Grp).map (ofHom f) = Grp.ofHom f := rfl @[to_additive] instance : Coe CommGrp.{u} Grp.{u} where coe := (forget₂ CommGrp Grp).obj @[to_additive hasForgetToAddCommMonCat] -instance hasForgetToCommMonCat : HasForget₂ CommGrp CommMonCat := - InducedCategory.hasForget₂ fun G : CommGrp => CommMonCat.of G +instance hasForgetToCommMonCat : HasForget₂ CommGrp CommMonCat where + forget₂.obj X := CommMonCat.of X + forget₂.map f := CommMonCat.ofHom f.hom + +@[to_additive (attr := simp)] lemma forget₂_commMonCat_map_ofHom {X Y : Type u} + [CommGroup X] [CommGroup Y] (f : X →* Y) : + (forget₂ CommGrp CommMonCat).map (ofHom f) = CommMonCat.ofHom f := rfl @[to_additive] instance : Coe CommGrp.{u} CommMonCat.{u} where coe := (forget₂ CommGrp CommMonCat).obj @[to_additive] -instance (G H : CommGrp) : One (G ⟶ H) := (inferInstance : One (MonoidHom G H)) +instance (G H : CommGrp) : One (G ⟶ H) where + one := ofHom 1 @[to_additive (attr := simp)] theorem one_apply (G H : CommGrp) (g : G) : ((1 : G ⟶ H) : G → H) g = 1 := rfl -/-- Typecheck a `MonoidHom` as a morphism in `CommGroup`. -/ -@[to_additive] -def ofHom {X Y : Type u} [CommGroup X] [CommGroup Y] (f : X →* Y) : of X ⟶ of Y := - f - -/-- Typecheck an `AddMonoidHom` as a morphism in `AddCommGroup`. -/ -add_decl_doc AddCommGrp.ofHom - -@[to_additive (attr := simp)] -theorem ofHom_apply {X Y : Type _} [CommGroup X] [CommGroup Y] (f : X →* Y) (x : X) : - @DFunLike.coe (X →* Y) X (fun _ ↦ Y) _ (ofHom f) x = f x := - rfl - @[to_additive] lemma ofHom_injective {X Y : Type u} [CommGroup X] [CommGroup Y] : Function.Injective (fun (f : X →* Y) ↦ ofHom f) := by intro _ _ h ext - apply DFunLike.congr_fun h + apply ConcreteCategory.congr_hom h -- We verify that simp lemmas apply when coercing morphisms to functions. @[to_additive] example {R S : CommGrp} (i : R ⟶ S) (r : R) (h : r = 1) : i r = 1 := by simp [h] /-- Universe lift functor for commutative groups. -/ -@[to_additive (attr := simps) +@[to_additive (attr := simps obj map) "Universe lift functor for additive commutative groups."] def uliftFunctor : CommGrp.{v} ⥤ CommGrp.{max v u} where obj X := CommGrp.of (ULift.{u, v} X) map {_ _} f := CommGrp.ofHom <| - MulEquiv.ulift.symm.toMonoidHom.comp <| f.comp MulEquiv.ulift.toMonoidHom + MulEquiv.ulift.symm.toMonoidHom.comp <| f.hom.comp MulEquiv.ulift.toMonoidHom map_id X := by rfl map_comp {X Y Z} f g := by rfl @@ -313,21 +473,17 @@ namespace AddCommGrp -- TODO generalize this, requiring a `ULiftInstances.lean` file /-- Any element of an abelian group gives a unique morphism from `ℤ` sending `1` to that element. -/ +@[simps!] def asHom {G : AddCommGrp.{0}} (g : G) : AddCommGrp.of ℤ ⟶ G := - zmultiplesHom G g - -@[simp] -theorem asHom_apply {G : AddCommGrp.{0}} (g : G) (i : ℤ) : - @DFunLike.coe (ℤ →+ ↑G) ℤ (fun _ ↦ ↑G) _ (asHom g) i = i • g := - rfl + ofHom (zmultiplesHom G g) theorem asHom_injective {G : AddCommGrp.{0}} : Function.Injective (@asHom G) := fun h k w => by - convert congr_arg (fun k : AddCommGrp.of ℤ ⟶ G => (k : ℤ → G) (1 : ℤ)) w <;> simp + simpa using CategoryTheory.congr_fun w 1 @[ext] theorem int_hom_ext {G : AddCommGrp.{0}} (f g : AddCommGrp.of ℤ ⟶ G) (w : f (1 : ℤ) = g (1 : ℤ)) : f = g := - @AddMonoidHom.ext_int G _ f g w + hom_ext (AddMonoidHom.ext_int w) -- TODO: this argument should be generalised to the situation where -- the forgetful functor is representable. @@ -342,8 +498,8 @@ end AddCommGrp /-- Build an isomorphism in the category `Grp` from a `MulEquiv` between `Group`s. -/ @[to_additive (attr := simps)] def MulEquiv.toGrpIso {X Y : Grp} (e : X ≃* Y) : X ≅ Y where - hom := e.toMonoidHom - inv := e.symm.toMonoidHom + hom := Grp.ofHom e.toMonoidHom + inv := Grp.ofHom e.symm.toMonoidHom /-- Build an isomorphism in the category `AddGroup` from an `AddEquiv` between `AddGroup`s. -/ add_decl_doc AddEquiv.toAddGrpIso @@ -352,8 +508,8 @@ add_decl_doc AddEquiv.toAddGrpIso between `CommGroup`s. -/ @[to_additive (attr := simps)] def MulEquiv.toCommGrpIso {X Y : CommGrp} (e : X ≃* Y) : X ≅ Y where - hom := e.toMonoidHom - inv := e.symm.toMonoidHom + hom := CommGrp.ofHom e.toMonoidHom + inv := CommGrp.ofHom e.symm.toMonoidHom /-- Build an isomorphism in the category `AddCommGrp` from an `AddEquiv` between `AddCommGroup`s. -/ @@ -364,7 +520,7 @@ namespace CategoryTheory.Iso /-- Build a `MulEquiv` from an isomorphism in the category `Grp`. -/ @[to_additive (attr := simp)] def groupIsoToMulEquiv {X Y : Grp} (i : X ≅ Y) : X ≃* Y := - MonoidHom.toMulEquiv i.hom i.inv i.hom_inv_id i.inv_hom_id + MonoidHom.toMulEquiv i.hom.hom i.inv.hom (by ext; simp) (by ext; simp) /-- Build an `addEquiv` from an isomorphism in the category `AddGroup` -/ add_decl_doc addGroupIsoToAddEquiv @@ -372,7 +528,7 @@ add_decl_doc addGroupIsoToAddEquiv /-- Build a `MulEquiv` from an isomorphism in the category `CommGroup`. -/ @[to_additive (attr := simps!)] def commGroupIsoToMulEquiv {X Y : CommGrp} (i : X ≅ Y) : X ≃* Y := - MonoidHom.toMulEquiv i.hom i.inv i.hom_inv_id i.inv_hom_id + MonoidHom.toMulEquiv i.hom.hom i.inv.hom (by ext; simp) (by ext; simp) /-- Build an `AddEquiv` from an isomorphism in the category `AddCommGroup`. -/ add_decl_doc addCommGroupIsoToAddEquiv @@ -406,11 +562,11 @@ namespace CategoryTheory.Aut /-- The (bundled) group of automorphisms of a type is isomorphic to the (bundled) group of permutations. -/ def isoPerm {α : Type u} : Grp.of (Aut α) ≅ Grp.of (Equiv.Perm α) where - hom := + hom := Grp.ofHom { toFun := fun g => g.toEquiv map_one' := by aesop map_mul' := by aesop } - inv := + inv := Grp.ofHom { toFun := fun g => g.toIso map_one' := by aesop map_mul' := by aesop } @@ -457,19 +613,29 @@ abbrev CommGrpMax.{u1, u2} := CommGrp.{max u1 u2} abbrev AddCommGrpMax.{u1, u2} := AddCommGrp.{max u1 u2} /-! -`@[simp]` lemmas for `MonoidHom.comp` and categorical identities. +Deprecated lemmas for `MonoidHom.comp` and categorical identities. -/ -@[to_additive (attr := simp)] theorem MonoidHom.comp_id_grp - {G : Grp.{u}} {H : Type u} [Group H] (f : G →* H) : f.comp (𝟙 G) = f := - Category.id_comp (Grp.ofHom f) -@[to_additive (attr := simp)] theorem MonoidHom.id_grp_comp - {G : Type u} [Group G] {H : Grp.{u}} (f : G →* H) : MonoidHom.comp (𝟙 H) f = f := - Category.comp_id (Grp.ofHom f) - -@[to_additive (attr := simp)] theorem MonoidHom.comp_id_commGrp - {G : CommGrp.{u}} {H : Type u} [CommGroup H] (f : G →* H) : f.comp (𝟙 G) = f := - Category.id_comp (CommGrp.ofHom f) -@[to_additive (attr := simp)] theorem MonoidHom.id_commGrp_comp - {G : Type u} [CommGroup G] {H : CommGrp.{u}} (f : G →* H) : MonoidHom.comp (𝟙 H) f = f := - Category.comp_id (CommGrp.ofHom f) +@[to_additive (attr := deprecated + "Proven by `simp only [Grp.hom_id, comp_id]`" + (since := "2025-01-28"))] +theorem MonoidHom.comp_id_grp {G : Grp.{u}} {H : Type u} [Monoid H] (f : G →* H) : + f.comp (Grp.Hom.hom (𝟙 G)) = f := by simp +@[to_additive (attr := deprecated + "Proven by `simp only [Grp.hom_id, id_comp]`" + (since := "2025-01-28"))] +theorem MonoidHom.id_grp_comp {G : Type u} [Monoid G] {H : Grp.{u}} (f : G →* H) : + MonoidHom.comp (Grp.Hom.hom (𝟙 H)) f = f := by simp + +@[to_additive (attr := deprecated + "Proven by `simp only [CommGrp.hom_id, comp_id]`" + (since := "2025-01-28"))] +theorem MonoidHom.comp_id_commGrp {G : CommGrp.{u}} {H : Type u} [Monoid H] (f : G →* H) : + f.comp (CommGrp.Hom.hom (𝟙 G)) = f := by + simp +@[to_additive (attr := deprecated + "Proven by `simp only [CommGrp.hom_id, id_comp]`" + (since := "2025-01-28"))] +theorem MonoidHom.id_commGrp_comp {G : Type u} [Monoid G] {H : CommGrp.{u}} (f : G →* H) : + MonoidHom.comp (CommGrp.Hom.hom (𝟙 H)) f = f := by + simp diff --git a/Mathlib/Algebra/Category/Grp/Biproducts.lean b/Mathlib/Algebra/Category/Grp/Biproducts.lean index b6ea983322210..5f51134683c91 100644 --- a/Mathlib/Algebra/Category/Grp/Biproducts.lean +++ b/Mathlib/Algebra/Category/Grp/Biproducts.lean @@ -41,10 +41,11 @@ def binaryProductLimitCone (G H : AddCommGrp.{u}) : Limits.LimitCone (pair G H) π := { app := fun j => Discrete.casesOn j fun j => - WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H) + WalkingPair.casesOn j (ofHom (AddMonoidHom.fst G H)) (ofHom (AddMonoidHom.snd G H)) naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> rfl } } isLimit := - { lift := fun s => AddMonoidHom.prod (s.π.app ⟨WalkingPair.left⟩) (s.π.app ⟨WalkingPair.right⟩) + { lift := fun s => ofHom <| + AddMonoidHom.prod (s.π.app ⟨WalkingPair.left⟩).hom (s.π.app ⟨WalkingPair.right⟩).hom fac := by rintro s (⟨⟩ | ⟨⟩) <;> rfl uniq := fun s m w => by simp_rw [← w ⟨WalkingPair.left⟩, ← w ⟨WalkingPair.right⟩] @@ -52,12 +53,12 @@ def binaryProductLimitCone (G H : AddCommGrp.{u}) : Limits.LimitCone (pair G H) @[simp] theorem binaryProductLimitCone_cone_π_app_left (G H : AddCommGrp.{u}) : - (binaryProductLimitCone G H).cone.π.app ⟨WalkingPair.left⟩ = AddMonoidHom.fst G H := + (binaryProductLimitCone G H).cone.π.app ⟨WalkingPair.left⟩ = ofHom (AddMonoidHom.fst G H) := rfl @[simp] theorem binaryProductLimitCone_cone_π_app_right (G H : AddCommGrp.{u}) : - (binaryProductLimitCone G H).cone.π.app ⟨WalkingPair.right⟩ = AddMonoidHom.snd G H := + (binaryProductLimitCone G H).cone.π.app ⟨WalkingPair.right⟩ = ofHom (AddMonoidHom.snd G H) := rfl /-- We verify that the biproduct in `AddCommGrp` is isomorphic to @@ -69,12 +70,12 @@ noncomputable def biprodIsoProd (G H : AddCommGrp.{u}) : @[simp, elementwise] theorem biprodIsoProd_inv_comp_fst (G H : AddCommGrp.{u}) : - (biprodIsoProd G H).inv ≫ biprod.fst = AddMonoidHom.fst G H := + (biprodIsoProd G H).inv ≫ biprod.fst = ofHom (AddMonoidHom.fst G H) := IsLimit.conePointUniqueUpToIso_inv_comp _ _ (Discrete.mk WalkingPair.left) @[simp, elementwise] theorem biprodIsoProd_inv_comp_snd (G H : AddCommGrp.{u}) : - (biprodIsoProd G H).inv ≫ biprod.snd = AddMonoidHom.snd G H := + (biprodIsoProd G H).inv ≫ biprod.snd = ofHom (AddMonoidHom.snd G H) := IsLimit.conePointUniqueUpToIso_inv_comp _ _ (Discrete.mk WalkingPair.right) namespace HasLimit @@ -84,19 +85,16 @@ variable {J : Type w} (f : J → AddCommGrp.{max w u}) /-- The map from an arbitrary cone over an indexed family of abelian groups to the cartesian product of those groups. -/ --- This was marked `@[simps]` until we made `AddCommGrp.coe_of` a simp lemma, --- after which the simp normal form linter complains. --- The generated simp lemmas were not used in Mathlib. --- Possible solution: higher priority function coercions that remove the `of`? --- @[simps] -def lift (s : Fan f) : s.pt ⟶ AddCommGrp.of (∀ j, f j) where - toFun x j := s.π.app ⟨j⟩ x - map_zero' := by - simp only [Functor.const_obj_obj, map_zero] - rfl - map_add' x y := by - simp only [Functor.const_obj_obj, map_add] - rfl +@[simps!] +def lift (s : Fan f) : s.pt ⟶ AddCommGrp.of (∀ j, f j) := + ofHom + { toFun x j := s.π.app ⟨j⟩ x + map_zero' := by + simp only [Functor.const_obj_obj, map_zero] + rfl + map_add' x y := by + simp only [Functor.const_obj_obj, map_add] + rfl } /-- Construct limit data for a product in `AddCommGrp`, using `AddCommGrp.of (∀ j, F.obj j)`. @@ -105,14 +103,13 @@ def lift (s : Fan f) : s.pt ⟶ AddCommGrp.of (∀ j, f j) where def productLimitCone : Limits.LimitCone (Discrete.functor f) where cone := { pt := AddCommGrp.of (∀ j, f j) - π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => f j) j.as } + π := Discrete.natTrans fun j => ofHom <| Pi.evalAddMonoidHom (fun j => f j) j.as } isLimit := { lift := lift.{_, u} f fac := fun _ _ => rfl uniq := fun s m w => by - ext x - funext j - exact congr_arg (fun g : s.pt ⟶ f j => (g : s.pt → f j) x) (w ⟨j⟩) } + ext x j + exact CategoryTheory.congr_fun (w ⟨j⟩) x } end HasLimit @@ -129,7 +126,7 @@ noncomputable def biproductIsoPi (f : J → AddCommGrp.{u}) : @[simp, elementwise] theorem biproductIsoPi_inv_comp_π (f : J → AddCommGrp.{u}) (j : J) : - (biproductIsoPi f).inv ≫ biproduct.π f j = Pi.evalAddMonoidHom (fun j => f j) j := + (biproductIsoPi f).inv ≫ biproduct.π f j = ofHom (Pi.evalAddMonoidHom (fun j => f j) j) := IsLimit.conePointUniqueUpToIso_inv_comp _ _ (Discrete.mk j) end AddCommGrp diff --git a/Mathlib/Algebra/Category/Grp/Colimits.lean b/Mathlib/Algebra/Category/Grp/Colimits.lean index f74b2fe7db828..3f491dd2cf84f 100644 --- a/Mathlib/Algebra/Category/Grp/Colimits.lean +++ b/Mathlib/Algebra/Category/Grp/Colimits.lean @@ -67,7 +67,7 @@ variable (c : Cocone F) /-- (implementation detail) Part of the universal property of the colimit cocone, but without assuming that `Quot F` lives in the correct universe. -/ def Quot.desc [DecidableEq J] : Quot.{w} F →+ c.pt := by - refine QuotientAddGroup.lift _ (DFinsupp.sumAddHom c.ι.app) ?_ + refine QuotientAddGroup.lift _ (DFinsupp.sumAddHom fun x => (c.ι.app x).hom) ?_ dsimp rw [AddSubgroup.closure_le] intro _ ⟨_, _, _, _, eq⟩ @@ -140,7 +140,7 @@ lemma quotUliftToQuot_ι [DecidableEq J] (j : J) (x : (F ⋙ uliftFunctor.{u'}). dsimp [quotUliftToQuot, Quot.ι] conv_lhs => erw [AddMonoidHom.comp_apply (QuotientAddGroup.mk' (Relations (F ⋙ uliftFunctor))) (DFinsupp.singleAddHom _ j), QuotientAddGroup.lift_mk'] - simp only [Functor.comp_obj, uliftFunctor_obj, coe_of, DFinsupp.singleAddHom_apply, + simp only [Functor.comp_obj, uliftFunctor_obj, DFinsupp.singleAddHom_apply, DFinsupp.sumAddHom_single, AddMonoidHom.coe_comp, AddMonoidHom.coe_coe, Function.comp_apply] rfl @@ -170,8 +170,8 @@ lemma Quot.desc_quotQuotUliftAddEquiv [DecidableEq J] (c : Cocone F) : AddEquiv.ulift.symm.toAddMonoidHom.comp (Quot.desc F c) := by refine Quot.addMonoidHom_ext _ (fun j a ↦ ?_) dsimp - simp only [quotToQuotUlift_ι, Functor.comp_obj, uliftFunctor_obj, coe_of, ι_desc, - Functor.const_obj_obj] + simp only [quotToQuotUlift_ι, Functor.comp_obj, uliftFunctor_obj, ι_desc, + Functor.const_obj_obj, AddMonoidHom.coe_comp, AddMonoidHom.coe_coe, Function.comp_apply, ι_desc] erw [Quot.ι_desc] rfl @@ -181,10 +181,10 @@ induces a cocone on `F` as long as the universes work out. @[simps] def toCocone [DecidableEq J] {A : Type w} [AddCommGroup A] (f : Quot F →+ A) : Cocone F where pt := AddCommGrp.of A - ι := { app := fun j => f.comp (Quot.ι F j) } + ι.app j := ofHom <| f.comp (Quot.ι F j) lemma Quot.desc_toCocone_desc [DecidableEq J] {A : Type w} [AddCommGroup A] (f : Quot F →+ A) - (hc : IsColimit c) : (hc.desc (toCocone F f)).comp (Quot.desc F c) = f := by + (hc : IsColimit c) : (hc.desc (toCocone F f)).hom.comp (Quot.desc F c) = f := by refine Quot.addMonoidHom_ext F (fun j x ↦ ?_) rw [AddMonoidHom.comp_apply, ι_desc] change (c.ι.app j ≫ hc.desc (toCocone F f)) _ = _ @@ -215,14 +215,14 @@ noncomputable def isColimit_of_bijective_desc [DecidableEq J] obtain ⟨x, rfl⟩ := h.2 x dsimp rw [← AddEquiv.ofBijective_apply _ h, AddEquiv.symm_apply_apply] - suffices eq : m.comp (AddEquiv.ofBijective (Quot.desc F c) h) = Quot.desc F s by + suffices eq : m.hom.comp (AddEquiv.ofBijective (Quot.desc F c) h) = Quot.desc F s by rw [← eq]; rfl exact Quot.addMonoidHom_ext F (by simp [← hm]) /-- (internal implementation) The colimit cocone of a functor `F`, implemented as a quotient of `DFinsupp (fun j ↦ F.obj j)`, under the assumption that said quotient is small. -/ -@[simps] +@[simps pt ι_app] noncomputable def colimitCocone [DecidableEq J] [Small.{w} (Quot.{w} F)] : Cocone F where pt := AddCommGrp.of (Shrink (Quot F)) ι := @@ -231,8 +231,6 @@ noncomputable def colimitCocone [DecidableEq J] [Small.{w} (Quot.{w} F)] : Cocon naturality _ _ _ := by ext dsimp - simp only [Category.comp_id, ofHom_apply, AddMonoidHom.coe_comp, AddMonoidHom.coe_coe, - Function.comp_apply] change Shrink.addEquiv.symm _ = _ rw [Quot.map_ι] } @@ -240,7 +238,7 @@ noncomputable def colimitCocone [DecidableEq J] [Small.{w} (Quot.{w} F)] : Cocon theorem Quot.desc_colimitCocone [DecidableEq J] (F : J ⥤ AddCommGrp.{w}) [Small.{w} (Quot F)] : Quot.desc F (colimitCocone F) = (Shrink.addEquiv (α := Quot F)).symm.toAddMonoidHom := by refine Quot.addMonoidHom_ext F (fun j x ↦ ?_) - simp only [colimitCocone_pt, coe_of, AddEquiv.toAddMonoidHom_eq_coe, AddMonoidHom.coe_coe] + simp only [colimitCocone_pt, AddEquiv.toAddMonoidHom_eq_coe, AddMonoidHom.coe_coe] erw [Quot.ι_desc] simp @@ -288,16 +286,17 @@ open QuotientAddGroup agrees with the usual group-theoretical quotient. -/ noncomputable def cokernelIsoQuotient {G H : AddCommGrp.{u}} (f : G ⟶ H) : - cokernel f ≅ AddCommGrp.of (H ⧸ AddMonoidHom.range f) where - hom := cokernel.desc f (mk' _) <| by + cokernel f ≅ AddCommGrp.of (H ⧸ AddMonoidHom.range f.hom) where + hom := cokernel.desc f (ofHom (mk' _)) <| by ext x + dsimp only [hom_comp, hom_ofHom] apply Quotient.sound apply leftRel_apply.mpr fconstructor · exact -x · simp only [add_zero, AddMonoidHom.map_neg] - inv := - QuotientAddGroup.lift _ (cokernel.π f) <| by + inv := ofHom <| + QuotientAddGroup.lift _ (cokernel.π f).hom <| by rintro _ ⟨x, rfl⟩ exact cokernel.condition_apply f x hom_inv_id := by @@ -306,6 +305,8 @@ noncomputable def cokernelIsoQuotient {G H : AddCommGrp.{u}} (f : G ⟶ H) : rfl inv_hom_id := by ext x - exact QuotientAddGroup.induction_on x <| cokernel.π_desc_apply f _ _ + dsimp only [hom_comp, hom_ofHom, hom_zero, AddMonoidHom.coe_comp, coe_mk', + Function.comp_apply, AddMonoidHom.zero_apply, id_eq, lift_mk, hom_id, AddMonoidHom.coe_id] + exact QuotientAddGroup.induction_on (α := H) x <| cokernel.π_desc_apply f _ _ end AddCommGrp diff --git a/Mathlib/Algebra/Category/Grp/EnoughInjectives.lean b/Mathlib/Algebra/Category/Grp/EnoughInjectives.lean index b43e1077c56c4..9a7e926e37ea1 100644 --- a/Mathlib/Algebra/Category/Grp/EnoughInjectives.lean +++ b/Mathlib/Algebra/Category/Grp/EnoughInjectives.lean @@ -33,7 +33,7 @@ instance enoughInjectives : EnoughInjectives AddCommGrp.{u} where presentation A_ := Nonempty.intro { J := of <| (CharacterModule A_) → ULift.{u} (AddCircle (1 : ℚ)) injective := injective_of_divisible _ - f := ⟨⟨fun a i ↦ ULift.up (i a), by aesop⟩, by aesop⟩ + f := ofHom ⟨⟨fun a i ↦ ULift.up (i a), by aesop⟩, by aesop⟩ mono := (AddCommGrp.mono_iff_injective _).mpr <| (injective_iff_map_eq_zero _).mpr fun _ h0 ↦ eq_zero_of_character_apply (congr_arg ULift.down <| congr_fun h0 ·) } diff --git a/Mathlib/Algebra/Category/Grp/EpiMono.lean b/Mathlib/Algebra/Category/Grp/EpiMono.lean index b1252eb15d7cd..eeddd4cdf99a0 100644 --- a/Mathlib/Algebra/Category/Grp/EpiMono.lean +++ b/Mathlib/Algebra/Category/Grp/EpiMono.lean @@ -67,28 +67,28 @@ namespace Grp -- Porting note: already have Group G but Lean can't use that @[to_additive] -instance (G : Grp) : Group G.α := +instance (G : Grp) : Group G.carrier := G.str variable {A B : Grp.{u}} (f : A ⟶ B) @[to_additive] -theorem ker_eq_bot_of_mono [Mono f] : f.ker = ⊥ := - MonoidHom.ker_eq_bot_of_cancel fun u _ => - (@cancel_mono _ _ _ _ _ f _ (show Grp.of f.ker ⟶ A from u) _).1 +theorem ker_eq_bot_of_mono [Mono f] : f.hom.ker = ⊥ := + MonoidHom.ker_eq_bot_of_cancel fun u v h => ConcreteCategory.ext_iff.mp <| + (@cancel_mono _ _ _ _ _ f _ (ofHom u) (ofHom v)).1 <| ConcreteCategory.ext h @[to_additive] -theorem mono_iff_ker_eq_bot : Mono f ↔ f.ker = ⊥ := +theorem mono_iff_ker_eq_bot : Mono f ↔ f.hom.ker = ⊥ := ⟨fun _ => ker_eq_bot_of_mono f, fun h => - ConcreteCategory.mono_of_injective _ <| (MonoidHom.ker_eq_bot_iff f).1 h⟩ + ConcreteCategory.mono_of_injective _ <| (MonoidHom.ker_eq_bot_iff f.hom).1 h⟩ @[to_additive] theorem mono_iff_injective : Mono f ↔ Function.Injective f := - Iff.trans (mono_iff_ker_eq_bot f) <| MonoidHom.ker_eq_bot_iff f + Iff.trans (mono_iff_ker_eq_bot f) <| MonoidHom.ker_eq_bot_iff f.hom namespace SurjectiveOfEpiAuxs -local notation3 "X" => Set.range (· • (f.range : Set B) : B → Set B) +local notation3 "X" => Set.range (· • (f.hom.range : Set B) : B → Set B) /-- Define `X'` to be the set of all left cosets with an extra point at "infinity". -/ @@ -128,53 +128,49 @@ theorem one_smul (x : X') : (1 : B) • x = x := simp only [one_leftCoset, Subtype.ext_iff_val] | ∞ => rfl -theorem fromCoset_eq_of_mem_range {b : B} (hb : b ∈ f.range) : - fromCoset ⟨b • ↑f.range, b, rfl⟩ = fromCoset ⟨f.range, 1, one_leftCoset _⟩ := by +theorem fromCoset_eq_of_mem_range {b : B} (hb : b ∈ f.hom.range) : + fromCoset ⟨b • ↑f.hom.range, b, rfl⟩ = fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩ := by congr - let b : B.α := b - change b • (f.range : Set B) = f.range - nth_rw 2 [show (f.range : Set B.α) = (1 : B) • f.range from (one_leftCoset _).symm] + nth_rw 2 [show (f.hom.range : Set B) = (1 : B) • f.hom.range from (one_leftCoset _).symm] rw [leftCoset_eq_iff, mul_one] exact Subgroup.inv_mem _ hb example (G : Type) [Group G] (S : Subgroup G) : Set G := S -theorem fromCoset_ne_of_nin_range {b : B} (hb : b ∉ f.range) : - fromCoset ⟨b • ↑f.range, b, rfl⟩ ≠ fromCoset ⟨f.range, 1, one_leftCoset _⟩ := by +theorem fromCoset_ne_of_nin_range {b : B} (hb : b ∉ f.hom.range) : + fromCoset ⟨b • ↑f.hom.range, b, rfl⟩ ≠ fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩ := by intro r simp only [fromCoset.injEq, Subtype.mk.injEq] at r - -- Porting note: annoying dance between types CoeSort.coe B, B.α, and B - let b' : B.α := b - change b' • (f.range : Set B) = f.range at r - nth_rw 2 [show (f.range : Set B.α) = (1 : B) • f.range from (one_leftCoset _).symm] at r + nth_rw 2 [show (f.hom.range : Set B) = (1 : B) • f.hom.range from (one_leftCoset _).symm] at r rw [leftCoset_eq_iff, mul_one] at r exact hb (inv_inv b ▸ Subgroup.inv_mem _ r) instance : DecidableEq X' := Classical.decEq _ -/-- Let `τ` be the permutation on `X'` exchanging `f.range` and the point at infinity. +/-- Let `τ` be the permutation on `X'` exchanging `f.hom.range` and the point at infinity. -/ noncomputable def tau : SX' := - Equiv.swap (fromCoset ⟨↑f.range, ⟨1, one_leftCoset _⟩⟩) ∞ + Equiv.swap (fromCoset ⟨↑f.hom.range, ⟨1, one_leftCoset _⟩⟩) ∞ local notation "τ" => tau f -theorem τ_apply_infinity : τ ∞ = fromCoset ⟨f.range, 1, one_leftCoset _⟩ := +theorem τ_apply_infinity : τ ∞ = fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩ := Equiv.swap_apply_right _ _ -theorem τ_apply_fromCoset : τ (fromCoset ⟨f.range, 1, one_leftCoset _⟩) = ∞ := +theorem τ_apply_fromCoset : τ (fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩) = ∞ := Equiv.swap_apply_left _ _ -theorem τ_apply_fromCoset' (x : B) (hx : x ∈ f.range) : - τ (fromCoset ⟨x • ↑f.range, ⟨x, rfl⟩⟩) = ∞ := +theorem τ_apply_fromCoset' (x : B) (hx : x ∈ f.hom.range) : + τ (fromCoset ⟨x • ↑f.hom.range, ⟨x, rfl⟩⟩) = ∞ := (fromCoset_eq_of_mem_range _ hx).symm ▸ τ_apply_fromCoset _ -theorem τ_symm_apply_fromCoset : Equiv.symm τ (fromCoset ⟨f.range, 1, one_leftCoset _⟩) = ∞ := by +theorem τ_symm_apply_fromCoset : + Equiv.symm τ (fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩) = ∞ := by rw [tau, Equiv.symm_swap, Equiv.swap_apply_left] theorem τ_symm_apply_infinity : - Equiv.symm τ ∞ = fromCoset ⟨f.range, 1, one_leftCoset _⟩ := by + Equiv.symm τ ∞ = fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩ := by rw [tau, Equiv.symm_swap, Equiv.swap_apply_right] /-- Let `g : B ⟶ S(X')` be defined as such that, for any `β : B`, `g(β)` is the function sending @@ -215,9 +211,10 @@ local notation "h" => h f /-! The strategy is the following: assuming `epi f` -* prove that `f.range = {x | h x = g x}`; +* prove that `f.hom.range = {x | h x = g x}`; * thus `f ≫ h = f ≫ g` so that `h = g`; -* but if `f` is not surjective, then some `x ∉ f.range`, then `h x ≠ g x` at the coset `f.range`. +* but if `f` is not surjective, then some `x ∉ f.hom.range`, then `h x ≠ g x` at the coset +`f.hom.range`. -/ @@ -227,70 +224,71 @@ theorem g_apply_fromCoset (x : B) (y : X) : theorem g_apply_infinity (x : B) : (g x) ∞ = ∞ := rfl -theorem h_apply_infinity (x : B) (hx : x ∈ f.range) : (h x) ∞ = ∞ := by +theorem h_apply_infinity (x : B) (hx : x ∈ f.hom.range) : (h x) ∞ = ∞ := by change ((τ).symm.trans (g x)).trans τ _ = _ simp only [MonoidHom.coe_mk, Equiv.toFun_as_coe, Equiv.coe_trans, Function.comp_apply] rw [τ_symm_apply_infinity, g_apply_fromCoset] simpa only using τ_apply_fromCoset' f x hx theorem h_apply_fromCoset (x : B) : - (h x) (fromCoset ⟨f.range, 1, one_leftCoset _⟩) = - fromCoset ⟨f.range, 1, one_leftCoset _⟩ := by + (h x) (fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩) = + fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩ := by change ((τ).symm.trans (g x)).trans τ _ = _ simp [-MonoidHom.coe_range, τ_symm_apply_fromCoset, g_apply_infinity, τ_apply_infinity] -theorem h_apply_fromCoset' (x : B) (b : B) (hb : b ∈ f.range) : - h x (fromCoset ⟨b • f.range, b, rfl⟩) = fromCoset ⟨b • ↑f.range, b, rfl⟩ := +theorem h_apply_fromCoset' (x : B) (b : B) (hb : b ∈ f.hom.range) : + h x (fromCoset ⟨b • f.hom.range, b, rfl⟩) = fromCoset ⟨b • ↑f.hom.range, b, rfl⟩ := (fromCoset_eq_of_mem_range _ hb).symm ▸ h_apply_fromCoset f x -theorem h_apply_fromCoset_nin_range (x : B) (hx : x ∈ f.range) (b : B) (hb : b ∉ f.range) : - h x (fromCoset ⟨b • f.range, b, rfl⟩) = fromCoset ⟨(x * b) • ↑f.range, x * b, rfl⟩ := by +theorem h_apply_fromCoset_nin_range (x : B) (hx : x ∈ f.hom.range) (b : B) (hb : b ∉ f.hom.range) : + h x (fromCoset ⟨b • f.hom.range, b, rfl⟩) = fromCoset ⟨(x * b) • ↑f.hom.range, x * b, rfl⟩ := by change ((τ).symm.trans (g x)).trans τ _ = _ simp only [tau, MonoidHom.coe_mk, Equiv.toFun_as_coe, Equiv.coe_trans, Function.comp_apply] rw [Equiv.symm_swap, - @Equiv.swap_apply_of_ne_of_ne X' _ (fromCoset ⟨f.range, 1, one_leftCoset _⟩) ∞ - (fromCoset ⟨b • ↑f.range, b, rfl⟩) (fromCoset_ne_of_nin_range _ hb) (by simp)] + @Equiv.swap_apply_of_ne_of_ne X' _ (fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩) ∞ + (fromCoset ⟨b • ↑f.hom.range, b, rfl⟩) (fromCoset_ne_of_nin_range _ hb) (by simp)] simp only [g_apply_fromCoset, leftCoset_assoc] refine Equiv.swap_apply_of_ne_of_ne (fromCoset_ne_of_nin_range _ fun r => hb ?_) (by simp) convert Subgroup.mul_mem _ (Subgroup.inv_mem _ hx) r rw [← mul_assoc, inv_mul_cancel, one_mul] -theorem agree : f.range = { x | h x = g x } := by +theorem agree : f.hom.range = { x | h x = g x } := by refine Set.ext fun b => ⟨?_, fun hb : h b = g b => by_contradiction fun r => ?_⟩ · rintro ⟨a, rfl⟩ change h (f a) = g (f a) ext ⟨⟨_, ⟨y, rfl⟩⟩⟩ · rw [g_apply_fromCoset] - by_cases m : y ∈ f.range + by_cases m : y ∈ f.hom.range · rw [h_apply_fromCoset' _ _ _ m, fromCoset_eq_of_mem_range _ m] change fromCoset _ = fromCoset ⟨f a • (y • _), _⟩ simp only [← fromCoset_eq_of_mem_range _ (Subgroup.mul_mem _ ⟨a, rfl⟩ m), smul_smul] · rw [h_apply_fromCoset_nin_range f (f a) ⟨_, rfl⟩ _ m] simp only [leftCoset_assoc] · rw [g_apply_infinity, h_apply_infinity f (f a) ⟨_, rfl⟩] - · have eq1 : (h b) (fromCoset ⟨f.range, 1, one_leftCoset _⟩) = - fromCoset ⟨f.range, 1, one_leftCoset _⟩ := by + · have eq1 : (h b) (fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩) = + fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩ := by change ((τ).symm.trans (g b)).trans τ _ = _ dsimp [tau] simp [g_apply_infinity f] have eq2 : - g b (fromCoset ⟨f.range, 1, one_leftCoset _⟩) = fromCoset ⟨b • ↑f.range, b, rfl⟩ := rfl + g b (fromCoset ⟨f.hom.range, 1, one_leftCoset _⟩) = fromCoset ⟨b • ↑f.hom.range, b, rfl⟩ := + rfl exact (fromCoset_ne_of_nin_range _ r).symm (by rw [← eq1, ← eq2, DFunLike.congr_fun hb]) -theorem comp_eq : (f ≫ show B ⟶ Grp.of SX' from g) = f ≫ show B ⟶ Grp.of SX' from h := by +theorem comp_eq : (f ≫ ofHom g) = f ≫ ofHom h := by ext a - change g (f a) = h (f a) + simp only [hom_comp, hom_ofHom, MonoidHom.coe_comp, Function.comp_apply] have : f a ∈ { b | h b = g b } := by rw [← agree] use a rw [this] -theorem g_ne_h (x : B) (hx : x ∉ f.range) : g ≠ h := by +theorem g_ne_h (x : B) (hx : x ∉ f.hom.range) : g ≠ h := by intro r replace r := - DFunLike.congr_fun (DFunLike.congr_fun r x) (fromCoset ⟨f.range, ⟨1, one_leftCoset _⟩⟩) + DFunLike.congr_fun (DFunLike.congr_fun r x) (fromCoset ⟨f.hom.range, ⟨1, one_leftCoset _⟩⟩) change _ = ((τ).symm.trans (g x)).trans τ _ at r - rw [g_apply_fromCoset, MonoidHom.coe_mk] at r + rw [g_apply_fromCoset] at r simp only [MonoidHom.coe_range, Subtype.coe_mk, Equiv.symm_swap, Equiv.toFun_as_coe, Equiv.coe_trans, Function.comp_apply] at r erw [Equiv.swap_apply_left, g_apply_infinity, Equiv.swap_apply_right] at r @@ -305,13 +303,13 @@ theorem surjective_of_epi [Epi f] : Function.Surjective f := by rcases r with ⟨b, hb⟩ exact SurjectiveOfEpiAuxs.g_ne_h f b (fun ⟨c, hc⟩ => hb _ hc) - ((cancel_epi f).1 (SurjectiveOfEpiAuxs.comp_eq f)) + (congr_arg Grp.Hom.hom ((cancel_epi f).1 (SurjectiveOfEpiAuxs.comp_eq f))) theorem epi_iff_surjective : Epi f ↔ Function.Surjective f := ⟨fun _ => surjective_of_epi f, ConcreteCategory.epi_of_surjective f⟩ -theorem epi_iff_range_eq_top : Epi f ↔ f.range = ⊤ := - Iff.trans (epi_iff_surjective _) (Subgroup.eq_top_iff' f.range).symm +theorem epi_iff_range_eq_top : Epi f ↔ f.hom.range = ⊤ := + Iff.trans (epi_iff_surjective _) (Subgroup.eq_top_iff' f.hom.range).symm end Grp @@ -327,8 +325,8 @@ theorem epi_iff_surjective : Epi f ↔ Function.Surjective f := by apply groupAddGroupEquivalence.inverse.map_epi rwa [Grp.epi_iff_surjective] at i1 -theorem epi_iff_range_eq_top : Epi f ↔ f.range = ⊤ := - Iff.trans (epi_iff_surjective _) (AddSubgroup.eq_top_iff' f.range).symm +theorem epi_iff_range_eq_top : Epi f ↔ f.hom.range = ⊤ := + Iff.trans (epi_iff_surjective _) (AddSubgroup.eq_top_iff' f.hom.range).symm end AddGrp @@ -353,37 +351,33 @@ namespace CommGrp variable {A B : CommGrp.{u}} (f : A ⟶ B) -- Porting note: again to help with non-transparency -private instance (A : CommGrp) : CommGroup A.α := A.str -private instance (A : CommGrp) : Group A.α := A.str.toGroup +private instance (A : CommGrp) : CommGroup A.carrier := A.str +private instance (A : CommGrp) : Group A.carrier := A.str.toGroup @[to_additive] -theorem ker_eq_bot_of_mono [Mono f] : f.ker = ⊥ := - MonoidHom.ker_eq_bot_of_cancel fun u _ => - (@cancel_mono _ _ _ _ _ f _ (show CommGrp.of f.ker ⟶ A from u) _).1 +theorem ker_eq_bot_of_mono [Mono f] : f.hom.ker = ⊥ := + MonoidHom.ker_eq_bot_of_cancel fun u v h => ConcreteCategory.ext_iff.mp <| + (@cancel_mono _ _ _ _ _ f _ (ofHom u) (ofHom v)).1 <| ConcreteCategory.ext h @[to_additive] -theorem mono_iff_ker_eq_bot : Mono f ↔ f.ker = ⊥ := +theorem mono_iff_ker_eq_bot : Mono f ↔ f.hom.ker = ⊥ := ⟨fun _ => ker_eq_bot_of_mono f, fun h => - ConcreteCategory.mono_of_injective _ <| (MonoidHom.ker_eq_bot_iff f).1 h⟩ + ConcreteCategory.mono_of_injective _ <| (MonoidHom.ker_eq_bot_iff f.hom).1 h⟩ @[to_additive] theorem mono_iff_injective : Mono f ↔ Function.Injective f := - Iff.trans (mono_iff_ker_eq_bot f) <| MonoidHom.ker_eq_bot_iff f + Iff.trans (mono_iff_ker_eq_bot f) <| MonoidHom.ker_eq_bot_iff f.hom @[to_additive] -theorem range_eq_top_of_epi [Epi f] : f.range = ⊤ := - MonoidHom.range_eq_top_of_cancel fun u v h => - (@cancel_epi _ _ _ _ _ f _ (show B ⟶ ⟨B ⧸ MonoidHom.range f, inferInstance⟩ from u) v).1 h +theorem range_eq_top_of_epi [Epi f] : f.hom.range = ⊤ := + MonoidHom.range_eq_top_of_cancel fun u v h => ConcreteCategory.ext_iff.mp <| + (@cancel_epi _ _ _ _ _ f _ (ofHom u) (ofHom v)).1 (ConcreteCategory.ext h) --- Porting note: again lack of transparency @[to_additive] -instance (G : CommGrp) : CommGroup <| (forget CommGrp).obj G := - G.str - -@[to_additive] -theorem epi_iff_range_eq_top : Epi f ↔ f.range = ⊤ := +theorem epi_iff_range_eq_top : Epi f ↔ f.hom.range = ⊤ := ⟨fun _ => range_eq_top_of_epi _, fun hf => - ConcreteCategory.epi_of_surjective _ <| MonoidHom.range_eq_top.mp hf⟩ + ConcreteCategory.epi_of_surjective _ <| show Function.Surjective f.hom from + MonoidHom.range_eq_top.mp hf⟩ @[to_additive] theorem epi_iff_surjective : Epi f ↔ Function.Surjective f := by diff --git a/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean b/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean index 892709d29b993..bcf2e1021df57 100644 --- a/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean +++ b/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean @@ -25,7 +25,7 @@ namespace Grp @[simps] def toAddGrp : Grp ⥤ AddGrp where obj X := AddGrp.of (Additive X) - map {_} {_} := MonoidHom.toAdditive + map {_} {_} f := AddGrp.ofHom f.hom.toAdditive end Grp @@ -36,7 +36,7 @@ namespace CommGrp @[simps] def toAddCommGrp : CommGrp ⥤ AddCommGrp where obj X := AddCommGrp.of (Additive X) - map {_} {_} := MonoidHom.toAdditive + map {_} {_} f := AddCommGrp.ofHom f.hom.toAdditive end CommGrp @@ -47,7 +47,7 @@ namespace AddGrp @[simps] def toGrp : AddGrp ⥤ Grp where obj X := Grp.of (Multiplicative X) - map {_} {_} := AddMonoidHom.toMultiplicative + map {_} {_} f := Grp.ofHom f.hom.toMultiplicative end AddGrp @@ -58,7 +58,7 @@ namespace AddCommGrp @[simps] def toCommGrp : AddCommGrp ⥤ CommGrp where obj X := CommGrp.of (Multiplicative X) - map {_} {_} := AddMonoidHom.toMultiplicative + map {_} {_} f := CommGrp.ofHom f.hom.toMultiplicative end AddCommGrp diff --git a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean index b68cb33f290ff..8e3c983dc3ac7 100644 --- a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean @@ -108,23 +108,25 @@ noncomputable def colimit : Grp.{max v u} := @[to_additive "The cocone over the proposed colimit additive group."] noncomputable def colimitCocone : Cocone F where pt := colimit.{v, u} F - ι := { (MonCat.FilteredColimits.colimitCocone (F ⋙ forget₂ Grp MonCat.{max v u})).ι with } + ι.app J := Grp.ofHom ((MonCat.FilteredColimits.colimitCocone (F ⋙ forget₂ Grp MonCat)).ι.app J) + ι.naturality _ _ f := (forget₂ _ MonCat).map_injective + ((MonCat.FilteredColimits.colimitCocone _).ι.naturality f) /-- The proposed colimit cocone is a colimit in `Grp`. -/ @[to_additive "The proposed colimit cocone is a colimit in `AddGroup`."] def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where - desc t := + desc t := Grp.ofHom <| MonCat.FilteredColimits.colimitDesc.{v, u} (F ⋙ forget₂ Grp MonCat.{max v u}) ((forget₂ Grp MonCat).mapCocone t) fac t j := - DFunLike.coe_injective <| + ConcreteCategory.coe_ext <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget Grp)).fac ((forget Grp).mapCocone t) j uniq t _ h := - DFunLike.coe_injective' <| + ConcreteCategory.coe_ext <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget Grp)).uniq ((forget Grp).mapCocone t) _ - fun j => funext fun x => DFunLike.congr_fun (h j) x + fun j => funext fun x => ConcreteCategory.congr_hom (h j) x @[to_additive forget₂AddMon_preservesFilteredColimits] noncomputable instance forget₂Mon_preservesFilteredColimits : @@ -175,25 +177,26 @@ noncomputable def colimit : CommGrp := @[to_additive "The cocone over the proposed colimit additive commutative group."] noncomputable def colimitCocone : Cocone F where pt := colimit.{v, u} F - ι := - { (Grp.FilteredColimits.colimitCocone - (F ⋙ forget₂ CommGrp Grp.{max v u})).ι with } + ι.app J := CommGrp.ofHom + ((Grp.FilteredColimits.colimitCocone (F ⋙ forget₂ CommGrp Grp)).ι.app J).hom + ι.naturality _ _ f := (forget₂ _ Grp).map_injective + ((Grp.FilteredColimits.colimitCocone _).ι.naturality f) /-- The proposed colimit cocone is a colimit in `CommGrp`. -/ @[to_additive "The proposed colimit cocone is a colimit in `AddCommGroup`."] def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where - desc t := - (Grp.FilteredColimits.colimitCoconeIsColimit.{v, u} + desc t := CommGrp.ofHom + ((Grp.FilteredColimits.colimitCoconeIsColimit.{v, u} (F ⋙ forget₂ CommGrp Grp.{max v u})).desc - ((forget₂ CommGrp Grp.{max v u}).mapCocone t) + ((forget₂ CommGrp Grp.{max v u}).mapCocone t)).hom fac t j := - DFunLike.coe_injective <| + ConcreteCategory.coe_ext <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommGrp)).fac ((forget CommGrp).mapCocone t) j uniq t _ h := - DFunLike.coe_injective <| + ConcreteCategory.coe_ext <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommGrp)).uniq - ((forget CommGrp).mapCocone t) _ fun j => funext fun x => DFunLike.congr_fun (h j) x + ((forget CommGrp).mapCocone t) _ fun j => funext fun x => ConcreteCategory.congr_hom (h j) x @[to_additive] noncomputable instance forget₂Group_preservesFilteredColimits : diff --git a/Mathlib/Algebra/Category/Grp/FiniteGrp.lean b/Mathlib/Algebra/Category/Grp/FiniteGrp.lean index bd6b281b3d46d..b1056d0ffa39f 100644 --- a/Mathlib/Algebra/Category/Grp/FiniteGrp.lean +++ b/Mathlib/Algebra/Category/Grp/FiniteGrp.lean @@ -44,7 +44,7 @@ instance : CoeSort FiniteGrp.{u} (Type u) where instance : Category FiniteGrp := InducedCategory.category FiniteGrp.toGrp @[to_additive] -instance : HasForget FiniteGrp := InducedCategory.hasForget FiniteGrp.toGrp +instance : ConcreteCategory FiniteGrp (· →* ·) := InducedCategory.concreteCategory FiniteGrp.toGrp @[to_additive] instance (G : FiniteGrp) : Group G := inferInstanceAs <| Group G.toGrp @@ -52,14 +52,6 @@ instance (G : FiniteGrp) : Group G := inferInstanceAs <| Group G.toGrp @[to_additive] instance (G : FiniteGrp) : Finite G := G.isFinite -@[to_additive] -instance (G H : FiniteGrp) : FunLike (G ⟶ H) G H := - inferInstanceAs <| FunLike (G →* H) G H - -@[to_additive] -instance (G H : FiniteGrp) : MonoidHomClass (G ⟶ H) G H := - inferInstanceAs <| MonoidHomClass (G →* H) G H - /-- Construct a term of `FiniteGrp` from a type endowed with the structure of a finite group. -/ @[to_additive "Construct a term of `FiniteAddGrp` from a type endowed with the structure of a finite additive group."] diff --git a/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean b/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean index 5583ecdd7e331..d8abf7d041a87 100644 --- a/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean +++ b/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean @@ -56,22 +56,26 @@ end AddMonoidHom /-- The forget functor `Grp.{u} ⥤ Type u` is corepresentable. -/ def Grp.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} (Multiplicative ℤ)))) ≅ forget Grp.{u} := - (NatIso.ofComponents (fun M => (MonoidHom.fromULiftMultiplicativeIntEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (MonoidHom.fromULiftMultiplicativeIntEquiv M.carrier)).toIso)) /-- The forget functor `CommGrp.{u} ⥤ Type u` is corepresentable. -/ def CommGrp.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} (Multiplicative ℤ)))) ≅ forget CommGrp.{u} := - (NatIso.ofComponents (fun M => (MonoidHom.fromULiftMultiplicativeIntEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (MonoidHom.fromULiftMultiplicativeIntEquiv M.carrier)).toIso)) /-- The forget functor `AddGrp.{u} ⥤ Type u` is corepresentable. -/ def AddGrp.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} ℤ))) ≅ forget AddGrp.{u} := - (NatIso.ofComponents (fun M => (AddMonoidHom.fromULiftIntEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (AddMonoidHom.fromULiftIntEquiv M.carrier)).toIso)) /-- The forget functor `AddCommGrp.{u} ⥤ Type u` is corepresentable. -/ def AddCommGrp.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} ℤ))) ≅ forget AddCommGrp.{u} := - (NatIso.ofComponents (fun M => (AddMonoidHom.fromULiftIntEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (AddMonoidHom.fromULiftIntEquiv M.carrier)).toIso)) instance Grp.forget_isCorepresentable : (forget Grp.{u}).IsCorepresentable := diff --git a/Mathlib/Algebra/Category/Grp/Images.lean b/Mathlib/Algebra/Category/Grp/Images.lean index e3f6641b97ec8..969adb23ea780 100644 --- a/Mathlib/Algebra/Category/Grp/Images.lean +++ b/Mathlib/Algebra/Category/Grp/Images.lean @@ -34,18 +34,18 @@ section -- implementation details of `IsImage` for `AddCommGrp`; use the API, not these /-- the image of a morphism in `AddCommGrp` is just the bundling of `AddMonoidHom.range f` -/ def image : AddCommGrp := - AddCommGrp.of (AddMonoidHom.range f) + AddCommGrp.of (AddMonoidHom.range f.hom) /-- the inclusion of `image f` into the target -/ def image.ι : image f ⟶ H := - f.range.subtype + ofHom f.hom.range.subtype instance : Mono (image.ι f) := ConcreteCategory.mono_of_injective (image.ι f) Subtype.val_injective /-- the corestriction map to the image -/ def factorThruImage : G ⟶ image f := - f.rangeRestrict + ofHom f.hom.rangeRestrict theorem image.fac : factorThruImage f ≫ image.ι f = f := by ext @@ -56,25 +56,26 @@ attribute [local simp] image.fac variable {f} /-- the universal property for the image factorisation -/ -noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I where - toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I) - map_zero' := by - haveI := F'.m_mono - apply injective_of_mono F'.m - change (F'.e ≫ F'.m) _ = _ - rw [F'.fac, AddMonoidHom.map_zero] - exact (Classical.indefiniteDescription (fun y => f y = 0) _).2 - map_add' := by - intro x y - haveI := F'.m_mono - apply injective_of_mono F'.m - rw [AddMonoidHom.map_add] - change (F'.e ≫ F'.m) _ = (F'.e ≫ F'.m) _ + (F'.e ≫ F'.m) _ - rw [F'.fac] - rw [(Classical.indefiniteDescription (fun z => f z = _) _).2] - rw [(Classical.indefiniteDescription (fun z => f z = _) _).2] - rw [(Classical.indefiniteDescription (fun z => f z = _) _).2] - rfl +noncomputable def image.lift (F' : MonoFactorisation f) : image f ⟶ F'.I := + ofHom + { toFun := (fun x => F'.e (Classical.indefiniteDescription _ x.2).1 : image f → F'.I) + map_zero' := by + haveI := F'.m_mono + apply injective_of_mono F'.m + change (F'.e ≫ F'.m) _ = _ + rw [F'.fac, AddMonoidHom.map_zero] + exact (Classical.indefiniteDescription (fun y => f y = 0) _).2 + map_add' := by + intro x y + haveI := F'.m_mono + apply injective_of_mono F'.m + rw [AddMonoidHom.map_add] + change (F'.e ≫ F'.m) _ = (F'.e ≫ F'.m) _ + (F'.e ≫ F'.m) _ + rw [F'.fac] + rw [(Classical.indefiniteDescription (fun z => f z = _) _).2] + rw [(Classical.indefiniteDescription (fun z => f z = _) _).2] + rw [(Classical.indefiniteDescription (fun z => f z = _) _).2] + rfl } theorem image.lift_fac (F' : MonoFactorisation f) : image.lift F' ≫ F'.m = image.ι f := by ext x @@ -100,7 +101,7 @@ noncomputable def isImage : IsImage (monoFactorisation f) where agrees with the usual group-theoretical range. -/ noncomputable def imageIsoRange {G H : AddCommGrp.{0}} (f : G ⟶ H) : - Limits.image f ≅ AddCommGrp.of f.range := + Limits.image f ≅ AddCommGrp.of f.hom.range := IsImage.isoExt (Image.isImage f) (isImage f) end AddCommGrp diff --git a/Mathlib/Algebra/Category/Grp/Injective.lean b/Mathlib/Algebra/Category/Grp/Injective.lean index a5f8e576a886a..fe5d86dc6079f 100644 --- a/Mathlib/Algebra/Category/Grp/Injective.lean +++ b/Mathlib/Algebra/Category/Grp/Injective.lean @@ -58,11 +58,11 @@ theorem Module.Baer.of_divisible [DivisibleBy A ℤ] : Module.Baer ℤ A := fun namespace AddCommGrp theorem injective_as_module_iff : Injective (ModuleCat.of ℤ A) ↔ - Injective (⟨A,inferInstance⟩ : AddCommGrp) := + Injective (C := AddCommGrp) (AddCommGrp.of A) := ((forget₂ (ModuleCat ℤ) AddCommGrp).asEquivalence.map_injective_iff (ModuleCat.of ℤ A)).symm instance injective_of_divisible [DivisibleBy A ℤ] : - Injective (⟨A,inferInstance⟩ : AddCommGrp) := + Injective (C := AddCommGrp) (AddCommGrp.of A) := (injective_as_module_iff A).mp <| Module.injective_object_of_injective_module (inj := (Module.Baer.of_divisible A).injective) diff --git a/Mathlib/Algebra/Category/Grp/Kernels.lean b/Mathlib/Algebra/Category/Grp/Kernels.lean index 577c21325b183..bedc42060e42a 100644 --- a/Mathlib/Algebra/Category/Grp/Kernels.lean +++ b/Mathlib/Algebra/Category/Grp/Kernels.lean @@ -21,25 +21,27 @@ variable {G H : AddCommGrp.{u}} (f : G ⟶ H) /-- The kernel cone induced by the concrete kernel. -/ def kernelCone : KernelFork f := - KernelFork.ofι (Z := of f.ker) f.ker.subtype <| ext fun x => x.casesOn fun _ hx => hx + KernelFork.ofι (Z := of f.hom.ker) (ofHom f.hom.ker.subtype) <| ext fun x => + x.casesOn fun _ hx => hx /-- 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 => mem_ker.mpr <| - by exact DFunLike.congr_fun s.condition c) + (fun s => ofHom <| s.ι.hom.codRestrict _ fun c => mem_ker.mpr <| + ConcreteCategory.congr_hom s.condition c) (fun _ => by rfl) - (fun _ _ h => ext fun x => Subtype.ext_iff_val.mpr <| by exact DFunLike.congr_fun h x) + (fun _ _ h => ext fun x => Subtype.ext_iff_val.mpr <| ConcreteCategory.congr_hom h x) /-- The cokernel cocone induced by the projection onto the quotient. -/ def cokernelCocone : CokernelCofork f := - CokernelCofork.ofπ (Z := of <| H ⧸ f.range) (mk' f.range) <| ext fun x => + CokernelCofork.ofπ (Z := of <| H ⧸ f.hom.range) (ofHom (mk' f.hom.range)) <| ext fun x => (eq_zero_iff _).mpr ⟨x, rfl⟩ /-- The projection onto the quotient is a cokernel in the categorical sense. -/ def cokernelIsColimit : IsColimit <| cokernelCocone f := Cofork.IsColimit.mk _ - (fun s => lift _ _ <| (range_le_ker_iff _ _).mpr <| CokernelCofork.condition s) + (fun s => ofHom <| lift _ _ <| (range_le_ker_iff _ _).mpr <| + congr_arg Hom.hom (CokernelCofork.condition s)) (fun _ => rfl) (fun _ _ h => have : Epi (cokernelCocone f).π := (epi_iff_surjective _).mpr <| mk'_surjective _ (cancel_epi (cokernelCocone f).π).mp <| by simpa only [parallelPair_obj_one] using h) diff --git a/Mathlib/Algebra/Category/Grp/LargeColimits.lean b/Mathlib/Algebra/Category/Grp/LargeColimits.lean index 9d0a40892ca36..2597e808e08ad 100644 --- a/Mathlib/Algebra/Category/Grp/LargeColimits.lean +++ b/Mathlib/Algebra/Category/Grp/LargeColimits.lean @@ -40,8 +40,9 @@ lemma isColimit_iff_bijective_desc [DecidableEq J] : apply ofHom_injective refine hc.hom_ext (fun j ↦ ?_) ext x - rw [CategoryTheory.comp_apply, CategoryTheory.comp_apply, ← Quot.ι_desc _ c j x] - exact ULift.down_injective (DFunLike.congr_fun eq (Quot.ι F j x)) + rw [ConcreteCategory.comp_apply, ConcreteCategory.comp_apply, ← Quot.ι_desc _ c j x] + simp only [hom_ofHom, AddMonoidHom.postcompEquiv_apply, AddMonoidHom.comp_apply] + exact DFunLike.congr_fun eq (Quot.ι F j x) · set c' : Cocone F := { pt := AddCommGrp.of (ULift (AddCircle (1 : ℚ))) ι := @@ -49,11 +50,9 @@ lemma isColimit_iff_bijective_desc [DecidableEq J] : (Quot.ι F j)) naturality {j j'} u := by ext - change ofHom ((AddEquiv.ulift.symm.toAddMonoidHom.comp χ).comp _) (F.map u _) = _ dsimp - rw [Quot.map_ι F (f := u)] - rfl } } - use AddEquiv.ulift.toAddMonoidHom.comp (hc.desc c') + rw [Quot.map_ι F (f := u)] } } + use AddEquiv.ulift.toAddMonoidHom.comp (hc.desc c').hom refine Quot.addMonoidHom_ext _ (fun j x ↦ ?_) dsimp rw [Quot.ι_desc] diff --git a/Mathlib/Algebra/Category/Grp/Limits.lean b/Mathlib/Algebra/Category/Grp/Limits.lean index bf20b86b85b04..905e3eb22d753 100644 --- a/Mathlib/Algebra/Category/Grp/Limits.lean +++ b/Mathlib/Algebra/Category/Grp/Limits.lean @@ -19,7 +19,6 @@ the underlying types are just the limits in the category of types. -/ - open CategoryTheory CategoryTheory.Limits universe v u w @@ -46,7 +45,7 @@ def sectionsSubgroup : Subgroup (∀ j, F.obj j) := inv_mem' := fun {a} ah j j' f => by simp only [Functor.comp_map, Pi.inv_apply, MonoidHom.map_inv, inv_inj] dsimp [Functor.sections] at ah ⊢ - rw [(F.map f).map_inv (a j), ah f] } + rw [(F.map f).hom.map_inv (a j), ah f] } @[to_additive] instance sectionsGroup : Group (F ⋙ forget Grp.{u}).sections := @@ -95,10 +94,10 @@ noncomputable instance Forget₂.createsLimit : { liftedCone := { pt := Grp.of (Types.Small.limitCone (F ⋙ forget Grp)).pt π := - { app := MonCat.limitπMonoidHom (F ⋙ forget₂ Grp MonCat) - naturality := + { app j := ofHom <| MonCat.limitπMonoidHom (F ⋙ forget₂ Grp MonCat) j + naturality i j h:= hom_ext <| (MonCat.HasLimits.limitCone - (F ⋙ forget₂ Grp MonCat.{u})).π.naturality } } + (F ⋙ forget₂ Grp MonCat.{u})).π.naturality h } } validLift := by apply IsLimit.uniqueUpToIso (MonCat.HasLimits.limitConeIsLimit.{v, u} _) t makesLimit := IsLimit.ofFaithful (forget₂ Grp MonCat.{u}) (MonCat.HasLimits.limitConeIsLimit _) @@ -262,9 +261,9 @@ noncomputable instance Forget₂.createsLimit : { liftedCone := { pt := CommGrp.of (Types.Small.limitCone.{v, u} (F ⋙ forget CommGrp)).pt π := - { app := MonCat.limitπMonoidHom - (F ⋙ forget₂ CommGrp Grp.{u} ⋙ forget₂ Grp MonCat.{u}) - naturality := (MonCat.HasLimits.limitCone _).π.naturality } } + { app j := ofHom <| MonCat.limitπMonoidHom + (F ⋙ forget₂ CommGrp Grp.{u} ⋙ forget₂ Grp MonCat.{u}) j + naturality i j h := hom_ext <| (MonCat.HasLimits.limitCone _).π.naturality h } } validLift := by apply IsLimit.uniqueUpToIso (Grp.limitConeIsLimit _) hc makesLimit := IsLimit.ofFaithful (forget₂ _ Grp.{u} ⋙ forget₂ _ MonCat.{u}) @@ -452,40 +451,35 @@ namespace AddCommGrp agrees with the usual group-theoretical kernel. -/ def kernelIsoKer {G H : AddCommGrp.{u}} (f : G ⟶ H) : - kernel f ≅ AddCommGrp.of f.ker where - hom := - { toFun := fun g => ⟨kernel.ι f g, DFunLike.congr_fun (kernel.condition f) g⟩ + kernel f ≅ AddCommGrp.of f.hom.ker where + hom := ofHom + { toFun := fun g => ⟨kernel.ι f g, ConcreteCategory.congr_hom (kernel.condition f) g⟩ map_zero' := by refine Subtype.ext ?_ - simp [(AddSubgroup.coe_zero _).symm] + simp only [Functor.comp_obj, map_zero, ZeroMemClass.coe_zero] map_add' := fun g g' => by refine Subtype.ext ?_ - change _ = _ + _ - dsimp simp } - inv := kernel.lift f (AddSubgroup.subtype f.ker) <| by ext x; exact x.2 + inv := kernel.lift f (ofHom (AddSubgroup.subtype f.hom.ker)) <| by ext x; exact x.2 hom_inv_id := by -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): it would be nice to do the next two steps by a single `ext`, -- but this will require thinking carefully about the relative priorities of `@[ext]` lemmas. refine equalizer.hom_ext ?_ - ext x - dsimp - apply DFunLike.congr_fun (kernel.lift_ι f _ _) + ext + simp inv_hom_id := by apply AddCommGrp.ext - simp only [AddMonoidHom.coe_mk, coe_id, coe_comp] rintro ⟨x, mem⟩ refine Subtype.ext ?_ - simp only [ZeroHom.coe_mk, Function.comp_apply, id_eq] - apply DFunLike.congr_fun (kernel.lift_ι f _ _) + apply ConcreteCategory.congr_hom (kernel.lift_ι f _ _) @[simp] theorem kernelIsoKer_hom_comp_subtype {G H : AddCommGrp.{u}} (f : G ⟶ H) : - (kernelIsoKer f).hom ≫ AddSubgroup.subtype f.ker = kernel.ι f := by ext; rfl + (kernelIsoKer f).hom ≫ ofHom (AddSubgroup.subtype f.hom.ker) = kernel.ι f := by ext; rfl @[simp] theorem kernelIsoKer_inv_comp_ι {G H : AddCommGrp.{u}} (f : G ⟶ H) : - (kernelIsoKer f).inv ≫ kernel.ι f = AddSubgroup.subtype f.ker := by + (kernelIsoKer f).inv ≫ kernel.ι f = ofHom (AddSubgroup.subtype f.hom.ker) := by ext simp [kernelIsoKer] @@ -493,7 +487,8 @@ theorem kernelIsoKer_inv_comp_ι {G H : AddCommGrp.{u}} (f : G ⟶ H) : agrees with the `AddSubgroup.subtype` map. -/ def kernelIsoKerOver {G H : AddCommGrp.{u}} (f : G ⟶ H) : - Over.mk (kernel.ι f) ≅ @Over.mk _ _ G (AddCommGrp.of f.ker) (AddSubgroup.subtype f.ker) := + Over.mk (kernel.ι f) ≅ @Over.mk _ _ G (AddCommGrp.of f.hom.ker) + (ofHom (AddSubgroup.subtype f.hom.ker)) := Over.isoMk (kernelIsoKer f) end AddCommGrp diff --git a/Mathlib/Algebra/Category/Grp/Preadditive.lean b/Mathlib/Algebra/Category/Grp/Preadditive.lean index 229f324800fe3..20b00a6be9627 100644 --- a/Mathlib/Algebra/Category/Grp/Preadditive.lean +++ b/Mathlib/Algebra/Category/Grp/Preadditive.lean @@ -16,13 +16,50 @@ universe u namespace AddCommGrp -instance (P Q : AddCommGrp) : AddCommGroup (P ⟶ Q) := - (inferInstance : AddCommGroup (AddMonoidHom P Q)) +variable {M N : AddCommGrp.{u}} + +instance : Add (M ⟶ N) where + add f g := ofHom (f.hom + g.hom) + +@[simp] lemma hom_add (f g : M ⟶ N) : (f + g).hom = f.hom + g.hom := rfl --- Porting note (https://github.com/leanprover-community/mathlib4/pull/10688): this lemma was not necessary in mathlib -@[simp] lemma hom_add_apply {P Q : AddCommGrp} (f g : P ⟶ Q) (x : P) : (f + g) x = f x + g x := rfl +instance : Zero (M ⟶ N) where + zero := ofHom 0 + +@[simp] lemma hom_zero : (0 : M ⟶ N).hom = 0 := rfl + +instance : SMul ℕ (M ⟶ N) where + smul n f := ofHom (n • f.hom) + +@[simp] lemma hom_nsmul (n : ℕ) (f : M ⟶ N) : (n • f).hom = n • f.hom := rfl + +instance : Neg (M ⟶ N) where + neg f := ofHom (-f.hom) + +@[simp] lemma hom_neg (f : M ⟶ N) : (-f).hom = -f.hom := rfl + +instance : Sub (M ⟶ N) where + sub f g := ofHom (f.hom - g.hom) + +@[simp] lemma hom_sub (f g : M ⟶ N) : (f - g).hom = f.hom - g.hom := rfl + +instance : SMul ℤ (M ⟶ N) where + smul n f := ofHom (n • f.hom) + +@[simp] lemma hom_zsmul (n : ℕ) (f : M ⟶ N) : (n • f).hom = n • f.hom := rfl + +instance (P Q : AddCommGrp) : AddCommGroup (P ⟶ Q) := + Function.Injective.addCommGroup (Hom.hom) ConcreteCategory.hom_injective + rfl (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) + instance : Preadditive AddCommGrp where +/-- `AddCommGrp.Hom.hom` bundled as an additive equivalence. -/ +@[simps!] +def homAddEquiv : (M ⟶ N) ≃+ (M →+ N) := + { ConcreteCategory.homEquiv (C := AddCommGrp) with + map_add' _ _ := rfl } + end AddCommGrp diff --git a/Mathlib/Algebra/Category/Grp/Ulift.lean b/Mathlib/Algebra/Category/Grp/Ulift.lean index 17c4fe820c0c4..b2b0a285efc94 100644 --- a/Mathlib/Algebra/Category/Grp/Ulift.lean +++ b/Mathlib/Algebra/Category/Grp/Ulift.lean @@ -79,7 +79,7 @@ namespace Grp "The universe lift functor for additive groups is fully faithful."] def uliftFunctorFullyFaithful : uliftFunctor.{u, v}.FullyFaithful where preimage f := Grp.ofHom (MulEquiv.ulift.toMonoidHom.comp - (f.comp MulEquiv.ulift.symm.toMonoidHom)) + (f.hom.comp MulEquiv.ulift.symm.toMonoidHom)) map_preimage _ := rfl preimage_map _ := rfl @@ -131,8 +131,8 @@ namespace CommGrp @[to_additive "The universe lift functor for commutative additive groups is fully faithful."] def uliftFunctorFullyFaithful : uliftFunctor.{u, v}.FullyFaithful where - preimage f := Grp.ofHom (MulEquiv.ulift.toMonoidHom.comp - (f.comp MulEquiv.ulift.symm.toMonoidHom)) + preimage f := CommGrp.ofHom (MulEquiv.ulift.toMonoidHom.comp + (f.hom.comp MulEquiv.ulift.symm.toMonoidHom)) map_preimage _ := rfl preimage_map _ := rfl diff --git a/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean b/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean index cd88f753ea5b8..6ef683b92d709 100644 --- a/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean +++ b/Mathlib/Algebra/Category/Grp/ZModuleEquivalence.lean @@ -32,9 +32,9 @@ instance forget₂_addCommGroup_full : (forget₂ (ModuleCat ℤ) AddCommGrp.{u} f := ⟨@ModuleCat.ofHom _ _ _ _ _ A.isModule _ B.isModule <| @LinearMap.mk _ _ _ _ _ _ _ _ _ A.isModule B.isModule { toFun := f, - map_add' := AddMonoidHom.map_add (show A.carrier →+ B.carrier from f) } + map_add' := AddMonoidHom.map_add f.hom } (fun n x => by - convert AddMonoidHom.map_zsmul (show A.carrier →+ B.carrier from f) x n <;> + convert AddMonoidHom.map_zsmul f.hom x n <;> ext <;> apply int_smul_eq_zsmul), rfl⟩ /-- The forgetful functor from `ℤ` modules to `AddCommGrp` is essentially surjective. -/ diff --git a/Mathlib/Algebra/Category/ModuleCat/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Basic.lean index 1692cf8873858..de5496ba5834c 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Basic.lean @@ -247,7 +247,7 @@ theorem forget₂_obj_moduleCat_of (X : Type v) [AddCommGroup X] [Module R X] : @[simp] theorem forget₂_map (X Y : ModuleCat R) (f : X ⟶ Y) : - (forget₂ (ModuleCat R) AddCommGrp).map f = f.hom.toAddMonoidHom := + (forget₂ (ModuleCat R) AddCommGrp).map f = AddCommGrp.ofHom f.hom := rfl instance : Inhabited (ModuleCat R) := @@ -473,14 +473,14 @@ variable (M N : ModuleCat.{v} R) /-- The scalar multiplication on an object of `ModuleCat R` considered as a morphism of rings from `R` to the endomorphisms of the underlying abelian group. -/ def smul : R →+* End ((forget₂ (ModuleCat R) AddCommGrp).obj M) where - toFun r := + toFun r := AddCommGrp.ofHom { toFun := fun (m : M) => r • m map_zero' := by dsimp; rw [smul_zero] map_add' := fun x y => by dsimp; rw [smul_add] } - map_one' := AddMonoidHom.ext (fun x => by dsimp; rw [one_smul]) - map_zero' := AddMonoidHom.ext (fun x => by dsimp; rw [zero_smul]; rfl) - map_mul' r s := AddMonoidHom.ext (fun (x : M) => (smul_smul r s x).symm) - map_add' r s := AddMonoidHom.ext (fun (x : M) => add_smul r s x) + map_one' := AddCommGrp.ext (fun x => by simp) + map_zero' := AddCommGrp.ext (fun x => by simp) + map_mul' r s := AddCommGrp.ext (fun (x : M) => (smul_smul r s x).symm) + map_add' r s := AddCommGrp.ext (fun (x : M) => add_smul r s x) lemma smul_naturality {M N : ModuleCat.{v} R} (f : M ⟶ N) (r : R) : (forget₂ (ModuleCat R) AddCommGrp).map f ≫ N.smul r = @@ -555,7 +555,7 @@ with the scalar multiplication. -/ @[simps] def homMk : M ⟶ N where hom'.toFun := φ - hom'.map_add' _ _ := φ.map_add _ _ + hom'.map_add' _ _ := φ.hom.map_add _ _ hom'.map_smul' r x := (congr_hom (hφ r) x).symm lemma forget₂_map_homMk : diff --git a/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean b/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean index 08ca1ad384315..ab99ed2d056fa 100644 --- a/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean @@ -133,8 +133,8 @@ def colimit : ModuleCatMax.{v, u, u} R := /-- The linear map from a given `R`-module in the diagram to the colimit module. -/ def coconeMorphism (j : J) : F.obj j ⟶ colimit F := ofHom - { (AddCommGrp.FilteredColimits.colimitCocone - (F ⋙ forget₂ (ModuleCat R) AddCommGrp.{max v u})).ι.app j with + { ((AddCommGrp.FilteredColimits.colimitCocone + (F ⋙ forget₂ (ModuleCat R) AddCommGrp.{max v u})).ι.app j).hom with map_smul' := fun r x => by erw [colimit_smul_mk_eq F r ⟨j, x⟩]; rfl } /-- The cocone over the proposed colimit module. -/ @@ -152,9 +152,9 @@ it is a linear map, i.e. preserves scalar multiplication. -/ def colimitDesc (t : Cocone F) : colimit F ⟶ t.pt := ofHom - { (AddCommGrp.FilteredColimits.colimitCoconeIsColimit + { ((AddCommGrp.FilteredColimits.colimitCoconeIsColimit (F ⋙ forget₂ (ModuleCatMax.{v, u} R) AddCommGrp.{max v u})).desc - ((forget₂ (ModuleCat R) AddCommGrp.{max v u}).mapCocone t) with + ((forget₂ (ModuleCat R) AddCommGrp.{max v u}).mapCocone t)).hom with map_smul' := fun r x => by refine Quot.inductionOn x ?_; clear x; intro x; obtain ⟨j, x⟩ := x erw [colimit_smul_mk_eq] diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean index 3fd18ca3d8336..15753b5a07d86 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean @@ -115,7 +115,7 @@ def isoMk (app : ∀ (X : Cᵒᵖ), M₁.obj X ≅ M₂.obj X) /-- The underlying presheaf of abelian groups of a presheaf of modules. -/ def presheaf : Cᵒᵖ ⥤ Ab where obj X := (forget₂ _ _).obj (M.obj X) - map f := AddMonoidHom.mk' (M.map f) (by simp) + map f := AddCommGrp.ofHom <| AddMonoidHom.mk' (M.map f) (by simp) @[simp] lemma presheaf_obj_coe (X : Cᵒᵖ) : @@ -123,7 +123,7 @@ lemma presheaf_obj_coe (X : Cᵒᵖ) : @[simp] lemma presheaf_map_apply_coe {X Y : Cᵒᵖ} (f : X ⟶ Y) (x : M.obj X) : - DFunLike.coe (α := M.obj X) (β := fun _ ↦ M.obj Y) (M.presheaf.map f) x = M.map f x := rfl + DFunLike.coe (α := M.obj X) (β := fun _ ↦ M.obj Y) (M.presheaf.map f).hom x = M.map f x := rfl instance (M : PresheafOfModules R) (X : Cᵒᵖ) : Module (R.obj X) (M.presheaf.obj X) := @@ -134,7 +134,7 @@ variable (R) in def toPresheaf : PresheafOfModules.{v} R ⥤ Cᵒᵖ ⥤ Ab where obj M := M.presheaf map f := - { app := fun X ↦ AddMonoidHom.mk' (Hom.app f X) (by simp) + { app := fun X ↦ AddCommGrp.ofHom <| AddMonoidHom.mk' (Hom.app f X) (by simp) naturality := fun X Y g ↦ by ext x; exact naturality_apply f g x } @[simp] @@ -144,7 +144,7 @@ lemma toPresheaf_obj_coe (X : Cᵒᵖ) : @[simp] lemma toPresheaf_map_app_apply (f : M₁ ⟶ M₂) (X : Cᵒᵖ) (x : M₁.obj X) : DFunLike.coe (α := M₁.obj X) (β := fun _ ↦ M₂.obj X) - (((toPresheaf R).map f).app X) x = f.app X x := rfl + (((toPresheaf R).map f).app X).hom x = f.app X x := rfl instance : (toPresheaf R).Faithful where map_injective {_ _ f g} h := by diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean index a1d35a63c69ed..1cd71c7594c0a 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean @@ -82,7 +82,8 @@ lemma isCompatible_map_smul_aux {Y Z : C} (f : Y ⟶ X) (g : Z ⟶ Y) · rw [hr₀', R.map_comp, RingCat.comp_apply, ← hr₀, ← RingCat.comp_apply, NatTrans.naturality, RingCat.comp_apply] · rw [hm₀', A.map_comp, AddCommGrp.coe_comp, Function.comp_apply, ← hm₀] - erw [NatTrans.naturality_apply] + erw [NatTrans.naturality_apply φ] + rfl -- `ConcreteCategory`/`HasForget` mismatch workaround variable (hr₀ : (r₀.map (whiskerRight α (forget _))).IsAmalgamation r) (hm₀ : (m₀.map (whiskerRight φ (forget _))).IsAmalgamation m) @@ -106,13 +107,14 @@ lemma isCompatible_map_smul : ((r₀.smul m₀).map (whiskerRight φ (forget _)) RingCat.comp_apply] have hb₀ : (φ.app (Opposite.op Z)) b₀ = (A.map (f₁.op ≫ g₁.op)) m := by dsimp [b₀] - erw [NatTrans.naturality_apply, hb₁, Functor.map_comp, CategoryTheory.comp_apply] + erw [NatTrans.naturality_apply φ, hb₁, Functor.map_comp, ConcreteCategory.comp_apply] + rfl -- `ConcreteCategory`/`HasForget` mismatch workaround have ha₀' : (α.app (Opposite.op Z)) a₀ = (R.map (f₂.op ≫ g₂.op)) r := by rw [ha₀, ← op_comp, fac, op_comp] have hb₀' : (φ.app (Opposite.op Z)) b₀ = (A.map (f₂.op ≫ g₂.op)) m := by rw [hb₀, ← op_comp, fac, op_comp] dsimp - erw [← NatTrans.naturality_apply, ← NatTrans.naturality_apply] + erw [← NatTrans.naturality_apply φ, ← NatTrans.naturality_apply φ] exact (isCompatible_map_smul_aux α φ hA r m f₁ g₁ a₁ a₀ b₁ b₀ ha₁ ha₀ hb₁ hb₀).trans (isCompatible_map_smul_aux α φ hA r m f₂ g₂ a₂ a₀ b₂ b₀ ha₂ ha₀' hb₂ hb₀').symm @@ -166,7 +168,7 @@ def SMulCandidate.mk' (S : Sieve X.unop) (hS : S ∈ J X.unop) · rw [← RingCat.comp_apply, NatTrans.naturality, RingCat.comp_apply, ha₀] apply (hr₀ _ hg).symm.trans simp [RingCat.forget_map] - · erw [NatTrans.naturality_apply, hb₀] + · erw [NatTrans.naturality_apply φ, hb₀] apply (hm₀ _ hg).symm.trans dsimp rw [Functor.map_comp] @@ -203,6 +205,7 @@ instance : Subsingleton (SMulCandidate α φ r m) where all_goals apply Presheaf.imageSieve_mem apply A.isSeparated _ _ hS intro Y f ⟨⟨r₀, hr₀⟩, ⟨m₀, hm₀⟩⟩ + show A.val.map f.op _ = A.val.map f.op _ -- `ConcreteCategory`/`HasForget` mismatch workaround rw [h₁ f.op r₀ hr₀ m₀ hm₀, h₂ f.op r₀ hr₀ m₀ hm₀] noncomputable instance : Unique (SMulCandidate α φ r m) := @@ -222,18 +225,22 @@ lemma map_smul_eq {Y : Cᵒᵖ} (f : X ⟶ Y) (r₀ : R₀.obj Y) (hr₀ : α.ap protected lemma one_smul : smul α φ 1 m = m := by apply A.isSeparated _ _ (Presheaf.imageSieve_mem J φ m) rintro Y f ⟨m₀, hm₀⟩ + show A.val.map f.op _ = _ -- `ConcreteCategory`/`HasForget` mismatch workaround rw [← hm₀, map_smul_eq α φ 1 m f.op 1 (by simp) m₀ hm₀, one_smul] + rfl -- `ConcreteCategory`/`HasForget` mismatch workaround protected lemma zero_smul : smul α φ 0 m = 0 := by apply A.isSeparated _ _ (Presheaf.imageSieve_mem J φ m) rintro Y f ⟨m₀, hm₀⟩ + show A.val.map f.op _ = A.val.map f.op _ -- `ConcreteCategory`/`HasForget` mismatch workaround rw [map_smul_eq α φ 0 m f.op 0 (by simp) m₀ hm₀, zero_smul, map_zero, - (A.val.map f.op).map_zero] + (A.val.map f.op).hom.map_zero] protected lemma smul_zero : smul α φ r 0 = 0 := by apply A.isSeparated _ _ (Presheaf.imageSieve_mem J α r) rintro Y f ⟨r₀, hr₀⟩ - rw [(A.val.map f.op).map_zero, map_smul_eq α φ r 0 f.op r₀ hr₀ 0 (by simp), + show A.val.map f.op _ = A.val.map f.op _ -- `ConcreteCategory`/`HasForget` mismatch workaround + rw [(A.val.map f.op).hom.map_zero, map_smul_eq α φ r 0 f.op r₀ hr₀ 0 (by simp), smul_zero, map_zero] protected lemma smul_add : smul α φ r (m + m') = smul α φ r m + smul α φ r m' := by @@ -242,11 +249,13 @@ protected lemma smul_add : smul α φ r (m + m') = smul α φ r m + smul α φ r refine J.intersection_covering (J.intersection_covering ?_ ?_) ?_ all_goals apply Presheaf.imageSieve_mem apply A.isSeparated _ _ hS - rintro Y f ⟨⟨⟨r₀, hr₀⟩, ⟨m₀ : M₀.obj _, hm₀⟩⟩, ⟨m₀' : M₀.obj _, hm₀'⟩⟩ - rw [(A.val.map f.op).map_add, map_smul_eq α φ r m f.op r₀ hr₀ m₀ hm₀, + rintro Y f ⟨⟨⟨r₀, hr₀⟩, ⟨m₀ : M₀.obj _, hm₀ : (φ.app _) _ = _⟩⟩, + ⟨m₀' : M₀.obj _, hm₀' : (φ.app _) _ = _⟩⟩ + show A.val.map f.op _ = A.val.map f.op _ -- `ConcreteCategory`/`HasForget` mismatch workaround + rw [(A.val.map f.op).hom.map_add, map_smul_eq α φ r m f.op r₀ hr₀ m₀ hm₀, map_smul_eq α φ r m' f.op r₀ hr₀ m₀' hm₀', map_smul_eq α φ r (m + m') f.op r₀ hr₀ (m₀ + m₀') - (by rw [map_add, map_add, hm₀, hm₀']), + (by rw [map_add, map_add, hm₀, hm₀']; rfl), smul_add, map_add] protected lemma add_smul : smul α φ (r + r') m = smul α φ r m + smul α φ r' m := by @@ -257,7 +266,8 @@ protected lemma add_smul : smul α φ (r + r') m = smul α φ r m + smul α φ r apply A.isSeparated _ _ hS rintro Y f ⟨⟨⟨r₀ : R₀.obj _, (hr₀ : (α.app (Opposite.op Y)) r₀ = (R.val.map f.op) r)⟩, ⟨r₀' : R₀.obj _, (hr₀' : (α.app (Opposite.op Y)) r₀' = (R.val.map f.op) r')⟩⟩, ⟨m₀, hm₀⟩⟩ - rw [(A.val.map f.op).map_add, map_smul_eq α φ r m f.op r₀ hr₀ m₀ hm₀, + show A.val.map f.op _ = A.val.map f.op _ -- `ConcreteCategory`/`HasForget` mismatch workaround + rw [(A.val.map f.op).hom.map_add, map_smul_eq α φ r m f.op r₀ hr₀ m₀ hm₀, map_smul_eq α φ r' m f.op r₀' hr₀' m₀ hm₀, map_smul_eq α φ (r + r') m f.op (r₀ + r₀') (by rw [map_add, map_add, hr₀, hr₀']) m₀ hm₀, add_smul, map_add] @@ -271,6 +281,7 @@ protected lemma mul_smul : smul α φ (r * r') m = smul α φ r (smul α φ r' m rintro Y f ⟨⟨⟨r₀ : R₀.obj _, (hr₀ : (α.app (Opposite.op Y)) r₀ = (R.val.map f.op) r)⟩, ⟨r₀' : R₀.obj _, (hr₀' : (α.app (Opposite.op Y)) r₀' = (R.val.map f.op) r')⟩⟩, ⟨m₀ : M₀.obj _, hm₀⟩⟩ + show A.val.map f.op _ = A.val.map f.op _ -- `ConcreteCategory`/`HasForget` mismatch workaround rw [map_smul_eq α φ (r * r') m f.op (r₀ * r₀') (by rw [map_mul, map_mul, hr₀, hr₀']) m₀ hm₀, mul_smul, map_smul_eq α φ r (smul α φ r' m) f.op r₀ hr₀ (r₀' • m₀) @@ -297,10 +308,12 @@ lemma map_smul : all_goals apply Presheaf.imageSieve_mem apply A.isSeparated _ _ hS rintro Y f ⟨⟨r₀, - (hr₀ : (α.app (Opposite.op Y)).hom r₀ = (R.val.map f.op).hom ((R.val.map π).hom r))⟩, ⟨m₀, hm₀⟩⟩ - rw [← CategoryTheory.comp_apply, ← Functor.map_comp, + (hr₀ : (α.app (Opposite.op Y)).hom r₀ = (R.val.map f.op).hom ((R.val.map π).hom r))⟩, + ⟨m₀, (hm₀ : (φ.app _) _ = _)⟩⟩ + show A.val.map f.op _ = A.val.map f.op _ -- `ConcreteCategory`/`HasForget` mismatch workaround + rw [← ConcreteCategory.comp_apply, ← Functor.map_comp, map_smul_eq α φ r m (π ≫ f.op) r₀ (by rw [hr₀, Functor.map_comp, RingCat.comp_apply]) m₀ - (by rw [hm₀, Functor.map_comp, CategoryTheory.comp_apply]), + (by rw [hm₀, Functor.map_comp, ConcreteCategory.comp_apply]; rfl), map_smul_eq α φ (R.val.map π r) (A.val.map π m) f.op r₀ hr₀ m₀ hm₀] end Sheafify diff --git a/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean b/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean index febe6bfa7f0fc..83478c76deccf 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Tannaka.lean @@ -42,13 +42,13 @@ def ringEquivEndForget₂ (R : Type u) [Ring R] : intros apply NatTrans.ext ext - simp only [AdditiveFunctor.of_fst, ModuleCat.forget₂_obj, AddCommGrp.coe_of, - AddCommGrp.ofHom_apply, DistribMulAction.toAddMonoidHom_apply, add_smul] + simp only [AdditiveFunctor.of_fst, ModuleCat.forget₂_obj, AddCommGrp.ofHom_apply, + DistribMulAction.toAddMonoidHom_apply, add_smul, AddCommGrp.hom_ofHom] rfl map_mul' := by intros apply NatTrans.ext ext - simp only [AdditiveFunctor.of_fst, ModuleCat.forget₂_obj, AddCommGrp.coe_of, - AddCommGrp.ofHom_apply, DistribMulAction.toAddMonoidHom_apply, mul_smul] + simp only [AdditiveFunctor.of_fst, ModuleCat.forget₂_obj, AddCommGrp.ofHom_apply, + DistribMulAction.toAddMonoidHom_apply, mul_smul, AddCommGrp.hom_ofHom] rfl diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index 8dd6aac24e41d..ce49902e3ee6b 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -316,7 +316,7 @@ instance hasForgetToSemiRingCat : HasForget₂ RingCat SemiRingCat where instance hasForgetToAddCommGrp : HasForget₂ RingCat AddCommGrp where forget₂ := { obj := fun R ↦ AddCommGrp.of R - map := fun f ↦ f.hom.toAddMonoidHom } + map := fun f ↦ AddCommGrp.ofHom f.hom.toAddMonoidHom } /-- Ring equivalence are isomorphisms in category of semirings -/ @[simps] diff --git a/Mathlib/Algebra/Category/Semigrp/Basic.lean b/Mathlib/Algebra/Category/Semigrp/Basic.lean index 7be4ed672212c..f587fda266623 100644 --- a/Mathlib/Algebra/Category/Semigrp/Basic.lean +++ b/Mathlib/Algebra/Category/Semigrp/Basic.lean @@ -209,7 +209,8 @@ def MulEquiv.toMagmaCatIso (e : X ≃* Y) : MagmaCat.of X ≅ MagmaCat.of Y wher inv := e.symm.toMulHom hom_inv_id := by ext - simp_rw [comp_apply, toMulHom_eq_coe, MagmaCat.mulEquiv_coe_eq, symm_apply_apply, id_apply] + simp_rw [CategoryTheory.comp_apply, toMulHom_eq_coe, MagmaCat.mulEquiv_coe_eq, symm_apply_apply, + CategoryTheory.id_apply] end diff --git a/Mathlib/Algebra/Homology/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ConcreteCategory.lean index 9c7f9f7bae473..2d27b01252ceb 100644 --- a/Mathlib/Algebra/Homology/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ConcreteCategory.lean @@ -75,20 +75,30 @@ lemma δ_apply (x₃ : (forget₂ C Ab).obj (S.X₃.X i)) (forget₂ C Ab).map (S.X₁.homologyπ j) (S.X₁.cyclesMk x₁ k hk (by have := hS.mono_f apply (Preadditive.mono_iff_injective (S.f.f k)).1 inferInstance - rw [← forget₂_comp_apply, ← HomologicalComplex.Hom.comm, forget₂_comp_apply, hx₁, - ← forget₂_comp_apply, HomologicalComplex.d_comp_d, Functor.map_zero, map_zero, - AddMonoidHom.zero_apply])) := by + -- Since `C` is only a `HasForget`, not a `ConcreteCategory` (for now), + -- we need to rewrite everything to `HasForget`. + have : ∀ {X Y : Ab} (f : X ⟶ Y), (f : X → Y) = + @DFunLike.coe _ _ _ (HasForget.toFunLike _ _ _) f := by intros; ext; rfl + rw [this, this, ← forget₂_comp_apply, ← HomologicalComplex.Hom.comm, forget₂_comp_apply, + ← this, ← this, hx₁, this, this, + ← forget₂_comp_apply, HomologicalComplex.d_comp_d, Functor.map_zero, ← this, ← this, + map_zero]; rfl)) := by + -- Since `C` is only a `HasForget`, not a `ConcreteCategory` (for now), + -- we need to rewrite everything to `HasForget`. + have : ∀ {X Y : Ab} (f : X ⟶ Y), (f : X → Y) = + @DFunLike.coe _ _ _ (HasForget.toFunLike _ _ _) f := by intros; ext; rfl refine hS.δ_apply' i j hij _ ((forget₂ C Ab).map (S.X₂.pOpcycles i) x₂) _ ?_ ?_ - · rw [← forget₂_comp_apply, ← forget₂_comp_apply, + · rw [this, this, ← forget₂_comp_apply, this, this, ← forget₂_comp_apply, HomologicalComplex.p_opcyclesMap, Functor.map_comp, CategoryTheory.comp_apply, - HomologicalComplex.homology_π_ι, forget₂_comp_apply, hx₂, HomologicalComplex.i_cyclesMk] + HomologicalComplex.homology_π_ι, forget₂_comp_apply, ← this, ← this, hx₂, ← this, + HomologicalComplex.i_cyclesMk] · apply (Preadditive.mono_iff_injective (S.X₂.iCycles j)).1 inferInstance conv_lhs => - rw [← forget₂_comp_apply, HomologicalComplex.cyclesMap_i, forget₂_comp_apply, - HomologicalComplex.i_cyclesMk, hx₁] + rw [this, this, ← forget₂_comp_apply, HomologicalComplex.cyclesMap_i, forget₂_comp_apply, + ← this ((forget₂ C Ab).map (S.X₁.iCycles j)), HomologicalComplex.i_cyclesMk, ← this, hx₁] conv_rhs => - rw [← forget₂_comp_apply, ← forget₂_comp_apply, - HomologicalComplex.pOpcycles_opcyclesToCycles_assoc, HomologicalComplex.toCycles_i] + rw [this, this, ← forget₂_comp_apply, this, ← forget₂_comp_apply, + HomologicalComplex.pOpcycles_opcyclesToCycles_assoc, HomologicalComplex.toCycles_i, ← this] end ShortExact diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean index 04d773c2ef94f..4eb09eac1879f 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean @@ -59,10 +59,9 @@ 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] + dsimp simp only [comp_assoc_of_third_deg_zero, mk₀_comp_mk₀, ShortComplex.zero, mk₀_zero, - comp_zero] - rfl)).Exact := by + comp_zero])).Exact := by letI := HasDerivedCategory.standard C have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₂ _ (hS.singleTriangle_distinguished) n @@ -80,10 +79,9 @@ 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] + dsimp simp only [comp_assoc_of_second_deg_zero, ShortComplex.ShortExact.comp_extClass, - comp_zero] - rfl)).Exact := by + comp_zero])).Exact := by letI := HasDerivedCategory.standard C have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₃ _ (hS.singleTriangle_distinguished) n₀ n₁ (by omega) @@ -100,9 +98,9 @@ lemma covariant_sequence_exact₁' : (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 + dsimp + simp only [comp_assoc_of_third_deg_zero, ShortComplex.ShortExact.extClass_comp, + comp_zero])).Exact := by letI := HasDerivedCategory.standard C have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₁ _ (hS.singleTriangle_distinguished) n₀ n₁ (by omega) @@ -185,9 +183,8 @@ lemma contravariant_sequence_exact₂' (n : ℕ) : (ShortComplex.mk (AddCommGrp.ofHom ((mk₀ S.g).precomp Y (zero_add n))) (AddCommGrp.ofHom ((mk₀ S.f).precomp Y (zero_add n))) (by ext - dsimp [AddCommGrp.ofHom] - simp only [mk₀_comp_mk₀_assoc, ShortComplex.zero, mk₀_zero, zero_comp] - rfl)).Exact := by + dsimp + simp only [mk₀_comp_mk₀_assoc, ShortComplex.zero, mk₀_zero, zero_comp])).Exact := by letI := HasDerivedCategory.standard C have := (preadditiveYoneda.obj ((singleFunctor C 0).obj Y)).homologySequence_exact₂ _ (op_distinguished _ hS.singleTriangle_distinguished) n @@ -205,9 +202,8 @@ lemma contravariant_sequence_exact₁' : (ShortComplex.mk (AddCommGrp.ofHom (((mk₀ S.f).precomp Y (zero_add n₀)))) (AddCommGrp.ofHom (hS.extClass.precomp Y h)) (by ext - dsimp [AddCommGrp.ofHom] - simp only [ShortComplex.ShortExact.extClass_comp_assoc] - rfl)).Exact := by + dsimp + simp only [ShortComplex.ShortExact.extClass_comp_assoc])).Exact := by letI := HasDerivedCategory.standard C have := (preadditiveYoneda.obj ((singleFunctor C 0).obj Y)).homologySequence_exact₃ _ (op_distinguished _ hS.singleTriangle_distinguished) n₀ n₁ (by omega) @@ -222,9 +218,8 @@ lemma contravariant_sequence_exact₃' : (ShortComplex.mk (AddCommGrp.ofHom (hS.extClass.precomp Y h)) (AddCommGrp.ofHom (((mk₀ S.g).precomp Y (zero_add n₁)))) (by ext - dsimp [AddCommGrp.ofHom] - simp only [ShortComplex.ShortExact.comp_extClass_assoc] - rfl)).Exact := by + dsimp + simp only [ShortComplex.ShortExact.comp_extClass_assoc])).Exact := by letI := HasDerivedCategory.standard C have := (preadditiveYoneda.obj ((singleFunctor C 0).obj Y)).homologySequence_exact₁ _ (op_distinguished _ hS.singleTriangle_distinguished) n₀ n₁ (by omega) diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean index febea094e706d..8985560ebfe5d 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/HomComplex.lean @@ -563,18 +563,12 @@ open HomComplex /-- The cochain complex of homomorphisms between two cochain complexes `F` and `G`. In degree `n : ℤ`, it consists of the abelian group `HomComplex.Cochain F G n`. -/ --- We also constructed the `d_apply` lemma using `@[simps]` --- until we made `AddCommGrp.coe_of` a simp lemma, --- after which the simp normal form linter complains. --- It was not used a simp lemma in Mathlib. --- Possible solution: higher priority function coercions that remove the `of`? --- @[simp] -@[simps! X] +@[simps! X d_hom_apply] def HomComplex : CochainComplex AddCommGrp ℤ where X i := AddCommGrp.of (Cochain F G i) d i j := AddCommGrp.ofHom (δ_hom ℤ F G i j) - shape _ _ hij := by ext; apply δ_shape _ _ hij - d_comp_d' _ _ _ _ _ := by ext; apply δ_δ + shape _ _ hij := by ext; simp [δ_shape _ _ hij] + d_comp_d' _ _ _ _ _ := by ext; simp [δ_δ] namespace HomComplex diff --git a/Mathlib/Algebra/Homology/ImageToKernel.lean b/Mathlib/Algebra/Homology/ImageToKernel.lean index a1bb4fbbd7a6a..b62f468146847 100644 --- a/Mathlib/Algebra/Homology/ImageToKernel.lean +++ b/Mathlib/Algebra/Homology/ImageToKernel.lean @@ -61,7 +61,7 @@ lemma imageToKernel_arrow_apply [HasForget V] (w : f ≫ g = 0) (x : (forget V).obj (Subobject.underlying.obj (imageSubobject f))) : (kernelSubobject g).arrow (imageToKernel f g w x) = (imageSubobject f).arrow x := by - rw [← comp_apply, imageToKernel_arrow] + rw [← CategoryTheory.comp_apply, imageToKernel_arrow] -- This is less useful as a `simp` lemma than it initially appears, -- as it "loses" the information the morphism factors through the image. diff --git a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean index f1b0f96f3b7a0..1d83ec6a04fbd 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean @@ -37,22 +37,22 @@ variable (S : ShortComplex Ab.{u}) @[simp] lemma ab_zero_apply (x : S.X₁) : S.g (S.f x) = 0 := by - rw [← CategoryTheory.comp_apply, S.zero] + rw [← ConcreteCategory.comp_apply, S.zero] rfl /-- The canonical additive morphism `S.X₁ →+ AddMonoidHom.ker S.g` induced by `S.f`. -/ @[simps!] -def abToCycles : S.X₁ →+ AddMonoidHom.ker S.g := +def abToCycles : S.X₁ →+ AddMonoidHom.ker S.g.hom := AddMonoidHom.mk' (fun x => ⟨S.f x, S.ab_zero_apply x⟩) (by aesop) /-- The explicit left homology data of a short complex of abelian group that is given by a kernel and a quotient given by the `AddMonoidHom` API. -/ @[simps] def abLeftHomologyData : S.LeftHomologyData where - K := AddCommGrp.of (AddMonoidHom.ker S.g) - H := AddCommGrp.of ((AddMonoidHom.ker S.g) ⧸ AddMonoidHom.range S.abToCycles) - i := (AddMonoidHom.ker S.g).subtype - π := QuotientAddGroup.mk' _ + K := AddCommGrp.of (AddMonoidHom.ker S.g.hom) + H := AddCommGrp.of ((AddMonoidHom.ker S.g.hom) ⧸ AddMonoidHom.range S.abToCycles) + i := AddCommGrp.ofHom <| (AddMonoidHom.ker S.g.hom).subtype + π := AddCommGrp.ofHom <| QuotientAddGroup.mk' _ wi := by ext ⟨_, hx⟩ exact hx @@ -65,12 +65,12 @@ def abLeftHomologyData : S.LeftHomologyData where hπ := AddCommGrp.cokernelIsColimit (AddCommGrp.ofHom S.abToCycles) @[simp] -lemma abLeftHomologyData_f' : S.abLeftHomologyData.f' = S.abToCycles := rfl +lemma abLeftHomologyData_f' : S.abLeftHomologyData.f' = AddCommGrp.ofHom S.abToCycles := rfl /-- Given a short complex `S` of abelian groups, this is the isomorphism between the abstract `S.cycles` of the homology API and the more concrete description as `AddMonoidHom.ker S.g`. -/ -noncomputable def abCyclesIso : S.cycles ≅ AddCommGrp.of (AddMonoidHom.ker S.g) := +noncomputable def abCyclesIso : S.cycles ≅ AddCommGrp.of (AddMonoidHom.ker S.g.hom) := S.abLeftHomologyData.cyclesIso -- This was a simp lemma until we made `AddCommGrp.coe_of` a simp lemma, @@ -78,10 +78,10 @@ noncomputable def abCyclesIso : S.cycles ≅ AddCommGrp.of (AddMonoidHom.ker S.g -- It was not used a simp lemma in Mathlib. -- Possible solution: higher priority function coercions that remove the `of`? -- @[simp] -lemma abCyclesIso_inv_apply_iCycles (x : AddMonoidHom.ker S.g) : +lemma abCyclesIso_inv_apply_iCycles (x : AddMonoidHom.ker S.g.hom) : S.iCycles (S.abCyclesIso.inv x) = x := by dsimp only [abCyclesIso] - rw [← CategoryTheory.comp_apply, S.abLeftHomologyData.cyclesIso_inv_comp_iCycles] + rw [← ConcreteCategory.comp_apply, S.abLeftHomologyData.cyclesIso_inv_comp_iCycles] rfl /-- Given a short complex `S` of abelian groups, this is the isomorphism between @@ -89,7 +89,7 @@ the abstract `S.homology` of the homology API and the more explicit quotient of `AddMonoidHom.ker S.g` by the image of `S.abToCycles : S.X₁ →+ AddMonoidHom.ker S.g`. -/ noncomputable def abHomologyIso : S.homology ≅ - AddCommGrp.of ((AddMonoidHom.ker S.g) ⧸ AddMonoidHom.range S.abToCycles) := + AddCommGrp.of ((AddMonoidHom.ker S.g.hom) ⧸ AddMonoidHom.range S.abToCycles) := S.abLeftHomologyData.homologyIso lemma exact_iff_surjective_abToCycles : @@ -121,15 +121,15 @@ lemma ab_exact_iff_function_exact : 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_ker_le_range : S.Exact ↔ S.g.hom.ker ≤ S.f.hom.range := S.ab_exact_iff -lemma ab_exact_iff_range_eq_ker : S.Exact ↔ S.f.range = S.g.ker := by +lemma ab_exact_iff_range_eq_ker : S.Exact ↔ S.f.hom.range = S.g.hom.ker := by rw [ab_exact_iff_ker_le_range] constructor · intro h refine le_antisymm ?_ h rintro _ ⟨x₁, rfl⟩ - rw [AddMonoidHom.mem_ker, ← CategoryTheory.comp_apply, S.zero] + rw [AddMonoidHom.mem_ker, ← ConcreteCategory.comp_apply, S.zero] rfl · intro h rw [h] diff --git a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean index 610dbd89fe414..e7b8c6c9a3621 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ConcreteCategory.lean @@ -32,7 +32,7 @@ lemma ShortComplex.zero_apply [Limits.HasZeroMorphisms C] [(forget₂ C Ab).PreservesZeroMorphisms] (S : ShortComplex C) (x : (forget₂ C Ab).obj S.X₁) : ((forget₂ C Ab).map S.g) (((forget₂ C Ab).map S.f) x) = 0 := by - rw [← CategoryTheory.comp_apply, ← Functor.map_comp, S.zero, Functor.map_zero] + rw [← ConcreteCategory.comp_apply, ← Functor.map_comp, S.zero, Functor.map_zero] rfl section preadditive @@ -112,8 +112,8 @@ lemma i_cyclesMk [S.HasHomology] (x₂ : (forget₂ C Ab).obj S.X₂) (hx₂ : ((forget₂ C Ab).map S.g) x₂ = 0) : (forget₂ C Ab).map S.iCycles (S.cyclesMk x₂ hx₂) = x₂ := by dsimp [cyclesMk] - erw [← CategoryTheory.comp_apply, S.mapCyclesIso_hom_iCycles (forget₂ C Ab), - ← CategoryTheory.comp_apply, abCyclesIso_inv_apply_iCycles ] + erw [← ConcreteCategory.comp_apply, S.mapCyclesIso_hom_iCycles (forget₂ C Ab), + ← ConcreteCategory.comp_apply, abCyclesIso_inv_apply_iCycles] end ShortComplex diff --git a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean index 7f2bbcf26e848..a3767b7e54152 100644 --- a/Mathlib/AlgebraicTopology/TopologicalSimplex.lean +++ b/Mathlib/AlgebraicTopology/TopologicalSimplex.lean @@ -81,7 +81,7 @@ def toTop : SimplexCategory ⥤ TopCat where apply toTopObj.ext funext i dsimp - simp only [comp_apply, TopCat.coe_of_of, ContinuousMap.coe_mk, coe_toTopMap] + simp only [CategoryTheory.comp_apply, TopCat.coe_of_of, ContinuousMap.coe_mk, coe_toTopMap] rw [← Finset.sum_biUnion] · apply Finset.sum_congr · exact Finset.ext (fun j => ⟨fun hj => by simpa using hj, fun hj => by simpa using hj⟩) diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean index 47c42654e11cd..8d809e5a93022 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean @@ -44,7 +44,7 @@ def cokernelCocone {X Y : SemiNormedGrp₁.{u}} (f : X ⟶ Y) : Cofork f 0 := -- SemiNormedGrp₁.mkHom_apply, SemiNormedGrp₁.zero_apply, -- ← NormedAddGroupHom.mem_ker, f.1.range.ker_normedMk, f.1.mem_range] -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [Limits.zero_comp, comp_apply, SemiNormedGrp₁.mkHom_apply, + erw [Limits.zero_comp, CategoryTheory.comp_apply, SemiNormedGrp₁.mkHom_apply, SemiNormedGrp₁.zero_apply, ← NormedAddGroupHom.mem_ker, f.1.range.ker_normedMk, f.1.mem_range] use x @@ -143,16 +143,10 @@ def cokernelCocone {X Y : SemiNormedGrp.{u}} (f : X ⟶ Y) : Cofork f 0 := @Cofork.ofπ _ _ _ _ _ _ (SemiNormedGrp.of (Y ⧸ NormedAddGroupHom.range f)) f.range.normedMk (by ext a - simp only [comp_apply, Limits.zero_comp] - -- Porting note: `simp` not firing on the below - rw [NormedAddGroupHom.zero_apply] - -- Porting note: Lean 3 didn't need this instance - letI : SeminormedAddCommGroup ((forget SemiNormedGrp).obj Y) := - (inferInstance : SeminormedAddCommGroup Y) - -- Porting note: again simp doesn't seem to be firing in the below line + simp only [coe_comp, Function.comp_apply, Limits.zero_comp, zero_apply] + -- Porting note: simp doesn't seem to be firing in the below line rw [← NormedAddGroupHom.mem_ker, f.range.ker_normedMk, f.mem_range] - -- This used to be `simp only [exists_apply_eq_apply]` before https://github.com/leanprover/lean4/pull/2644 - convert exists_apply_eq_apply f a) + simp only [exists_apply_eq_apply]) /-- Auxiliary definition for `HasCokernels SemiNormedGrp`. -/ noncomputable diff --git a/Mathlib/CategoryTheory/Action/Basic.lean b/Mathlib/CategoryTheory/Action/Basic.lean index f68dccaad46f2..5346896a39bc6 100644 --- a/Mathlib/CategoryTheory/Action/Basic.lean +++ b/Mathlib/CategoryTheory/Action/Basic.lean @@ -46,20 +46,21 @@ variable {V} theorem ρ_one {G : MonCat.{u}} (A : Action V G) : A.ρ 1 = 𝟙 A.V := by rw [MonoidHom.map_one]; rfl /-- When a group acts, we can lift the action to the group of automorphisms. -/ -@[simps] -def ρAut {G : Grp.{u}} (A : Action V (MonCat.of G)) : G ⟶ Grp.of (Aut A.V) where - toFun g := - { hom := A.ρ g - inv := A.ρ (g⁻¹ : G) - hom_inv_id := (A.ρ.map_mul (g⁻¹ : G) g).symm.trans (by rw [inv_mul_cancel, ρ_one]) - inv_hom_id := (A.ρ.map_mul g (g⁻¹ : G)).symm.trans (by rw [mul_inv_cancel, ρ_one]) } - map_one' := Aut.ext A.ρ.map_one - map_mul' x y := Aut.ext (A.ρ.map_mul x y) +@[simps!] +def ρAut {G : Grp.{u}} (A : Action V (MonCat.of G)) : G ⟶ Grp.of (Aut A.V) := + Grp.ofHom + { toFun g := + { hom := A.ρ g + inv := A.ρ (g⁻¹ : G) + hom_inv_id := (A.ρ.map_mul (g⁻¹ : G) g).symm.trans (by rw [inv_mul_cancel, ρ_one]) + inv_hom_id := (A.ρ.map_mul g (g⁻¹ : G)).symm.trans (by rw [mul_inv_cancel, ρ_one]) } + map_one' := Aut.ext A.ρ.map_one + map_mul' x y := Aut.ext (A.ρ.map_mul x y) } -- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), -- but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -- It would be worth fixing these, as `ρAut_apply_inv` is used in `erw` later. -attribute [nolint simpNF] Action.ρAut_apply_inv Action.ρAut_apply_hom +attribute [nolint simpNF] Action.ρAut_hom_apply_inv Action.ρAut_hom_apply_hom variable (G : MonCat.{u}) diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 5057020dc6114..88cc54531a515 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -185,7 +185,7 @@ instance forget₂_faithful (C : Type u) (D : Type u') [Category.{v} C] [HasForg instance InducedCategory.hasForget {C : Type u} {D : Type u'} [Category.{v'} D] [HasForget.{w} D] (f : C → D) : - HasForget (InducedCategory D f) where + HasForget (InducedCategory D f) where forget := inducedFunctor f ⋙ forget D instance InducedCategory.hasForget₂ {C : Type u} {D : Type u'} [Category.{v} D] @@ -426,6 +426,30 @@ abbrev Types.instConcreteCategory : ConcreteCategory (Type u) (fun X Y => X ⟶ end +open ConcreteCategory + +instance InducedCategory.concreteCategory {C : Type u} {D : Type u'} [Category.{v'} D] + {FD : D → D → Type*} {CD : D → Type w} [∀ X Y, FunLike (FD X Y) (CD X) (CD Y)] + [ConcreteCategory.{w} D FD] (f : C → D) : + ConcreteCategory (InducedCategory D f) (fun X Y => FD (f X) (f Y)) where + hom := hom (C := D) + ofHom := ofHom (C := D) + hom_ofHom := hom_ofHom (C := D) + ofHom_hom := ofHom_hom (C := D) + comp_apply := ConcreteCategory.comp_apply (C := D) + id_apply := ConcreteCategory.id_apply (C := D) + +instance FullSubcategory.concreteCategory {C : Type u} [Category.{v} C] + {FC : C → C → Type*} {CC : C → Type w} [∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] + [ConcreteCategory.{w} C FC] + (Z : C → Prop) : ConcreteCategory (FullSubcategory Z) (fun X Y => FC X.1 Y.1) where + hom := hom (C := C) + ofHom := ofHom (C := C) + hom_ofHom := hom_ofHom (C := C) + ofHom_hom := ofHom_hom (C := C) + comp_apply := ConcreteCategory.comp_apply (C := C) + id_apply := ConcreteCategory.id_apply (C := C) + end ConcreteCategory end CategoryTheory diff --git a/Mathlib/CategoryTheory/Galois/Prorepresentability.lean b/Mathlib/CategoryTheory/Galois/Prorepresentability.lean index 554c363a78c89..fc500c5bbe4e1 100644 --- a/Mathlib/CategoryTheory/Galois/Prorepresentability.lean +++ b/Mathlib/CategoryTheory/Galois/Prorepresentability.lean @@ -210,13 +210,7 @@ as an object of `C`. -/ @[simps] noncomputable def autGaloisSystem : PointedGaloisObject F ⥤ Grp.{u₂} where obj := fun A ↦ Grp.of <| Aut (A : C) - map := fun {A B} f ↦ (autMapHom f : Aut (A : C) →* Aut (B : C)) - map_id := fun A ↦ by - ext (σ : Aut A.obj) - simp - map_comp {A B C} f g := by - ext (σ : Aut A.obj) - simp + map := fun {A B} f ↦ Grp.ofHom (autMapHom f) /-- The limit of `autGaloisSystem`. -/ noncomputable def AutGalois : Type (max u₁ u₂) := diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean index daeb064872fed..177bf4d9fc82c 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean @@ -241,7 +241,7 @@ theorem widePullback_ext' {B : C} {ι : Type w} [Nonempty ι] {X : ι → C} (h : ∀ j, π f j x = π f j y) : x = y := by apply Concrete.widePullback_ext _ _ _ _ h inhabit ι - simp only [← π_arrow f default, comp_apply, h] + simp only [← π_arrow f default, CategoryTheory.comp_apply, h] end WidePullback @@ -255,7 +255,8 @@ theorem multiequalizer_ext {I : MulticospanIndex.{w, w'} C} [HasMultiequalizer I apply Concrete.limit_ext rintro (a | b) · apply h - · rw [← limit.w I.multicospan (WalkingMulticospan.Hom.fst b), comp_apply, comp_apply] + · rw [← limit.w I.multicospan (WalkingMulticospan.Hom.fst b), CategoryTheory.comp_apply, + CategoryTheory.comp_apply] simp [h] /-- An auxiliary equivalence to be used in `multiequalizerEquiv` below. -/ @@ -334,7 +335,7 @@ theorem widePushout_exists_rep' {B : C} {α : Type _} [Nonempty α] {X : α → rcases Concrete.widePushout_exists_rep f x with (⟨y, rfl⟩ | ⟨i, y, rfl⟩) · inhabit α use default, f _ y - simp only [← arrow_ι _ default, comp_apply] + simp only [← arrow_ι _ default, CategoryTheory.comp_apply] · use i, y end WidePushout diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean index 82e861ee09f3f..ebeadf9c0160b 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean @@ -52,13 +52,11 @@ structure, see `preadditiveYonedaObj`. def preadditiveYoneda : C ⥤ Cᵒᵖ ⥤ AddCommGrp.{v} where obj Y := preadditiveYonedaObj Y ⋙ forget₂ _ _ map f := - { app := fun _ => + { app := fun _ => AddCommGrp.ofHom { toFun := fun g => g ≫ f map_zero' := Limits.zero_comp map_add' := fun _ _ => add_comp _ _ _ _ _ _ } naturality := fun _ _ _ => AddCommGrp.ext fun _ => Category.assoc _ _ _ } - map_id _ := by ext; dsimp; simp - map_comp f g := by ext; dsimp; simp /-- The Yoneda embedding for preadditive categories sends an object `X` to the copresheaf sending an object `Y` to the `End X`-module of morphisms `X ⟶ Y`. @@ -79,14 +77,12 @@ structure, see `preadditiveCoyonedaObj`. def preadditiveCoyoneda : Cᵒᵖ ⥤ C ⥤ AddCommGrp.{v} where obj X := preadditiveCoyonedaObj X ⋙ forget₂ _ _ map f := - { app := fun _ => + { app := fun _ => AddCommGrp.ofHom { toFun := fun g => f.unop ≫ g map_zero' := Limits.comp_zero map_add' := fun _ _ => comp_add _ _ _ _ _ _ } naturality := fun _ _ _ => AddCommGrp.ext fun _ => Eq.symm <| Category.assoc _ _ _ } - map_id _ := by ext; dsimp; simp - map_comp f g := by ext; dsimp; simp instance additive_yonedaObj (X : C) : Functor.Additive (preadditiveYonedaObj X) where diff --git a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean index dad92afd416e4..dcea0256e4316 100644 --- a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean @@ -96,7 +96,7 @@ theorem pullback_refine {Y X : C} {P : Cᵒᵖ ⥤ D} {S T : J.Cover X} (h : S def mk {X : C} {P : Cᵒᵖ ⥤ D} (S : J.Cover X) (x : P.obj (op X)) : Meq P S := ⟨fun I => P.map I.f.op x, fun I => by dsimp - simp only [← comp_apply, ← P.map_comp, ← op_comp, I.r.w]⟩ + simp only [← CategoryTheory.comp_apply, ← P.map_comp, ← op_comp, I.r.w]⟩ theorem mk_apply {X : C} {P : Cᵒᵖ ⥤ D} (S : J.Cover X) (x : P.obj (op X)) (I : S.Arrow) : mk S x I = P.map I.f.op x := @@ -152,7 +152,7 @@ theorem res_mk_eq_mk_pullback {Y X : C} {P : Cᵒᵖ ⥤ D} {S : J.Cover X} (x : ext i simp only [Functor.op_obj, unop_op, pullback_obj, diagram_obj, Functor.comp_obj, diagramPullback_app, Meq.equiv_apply, Meq.pullback_apply] - rw [← comp_apply, Multiequalizer.lift_ι] + rw [← CategoryTheory.comp_apply, Multiequalizer.lift_ι] erw [Meq.equiv_symm_eq_apply] cases i; rfl @@ -162,13 +162,13 @@ theorem toPlus_mk {X : C} {P : Cᵒᵖ ⥤ D} (S : J.Cover X) (x : P.obj (op X)) let e : S ⟶ ⊤ := homOfLE (OrderTop.le_top _) rw [← colimit.w _ e.op] delta Cover.toMultiequalizer - rw [comp_apply] - erw [comp_apply] + rw [CategoryTheory.comp_apply] + erw [CategoryTheory.comp_apply] apply congr_arg dsimp [diagram] apply Concrete.multiequalizer_ext intro i - simp only [← comp_apply, Category.assoc, Multiequalizer.lift_ι, Category.comp_id, + simp only [← CategoryTheory.comp_apply, Category.assoc, Multiequalizer.lift_ι, Category.comp_id, Meq.equiv_symm_eq_apply] rfl @@ -177,17 +177,17 @@ theorem toPlus_apply {X : C} {P : Cᵒᵖ ⥤ D} (S : J.Cover X) (x : Meq P S) ( dsimp only [toPlus, plusObj] delta Cover.toMultiequalizer dsimp [mk] - erw [← comp_apply] - rw [ι_colimMap_assoc, colimit.ι_pre, comp_apply, comp_apply] + erw [← CategoryTheory.comp_apply] + rw [ι_colimMap_assoc, colimit.ι_pre, CategoryTheory.comp_apply, CategoryTheory.comp_apply] dsimp only [Functor.op] let e : (J.pullback I.f).obj (unop (op S)) ⟶ ⊤ := homOfLE (OrderTop.le_top _) rw [← colimit.w _ e.op] - erw [comp_apply] + erw [CategoryTheory.comp_apply] apply congr_arg apply Concrete.multiequalizer_ext intro i dsimp - erw [← comp_apply, ← comp_apply, ← comp_apply] + erw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply] rw [Multiequalizer.lift_ι, Multiequalizer.lift_ι, Multiequalizer.lift_ι] erw [Meq.equiv_symm_eq_apply] simpa using (x.condition (Cover.Relation.mk' (I.precompRelation i.f))).symm @@ -196,11 +196,11 @@ theorem toPlus_eq_mk {X : C} {P : Cᵒᵖ ⥤ D} (x : P.obj (op X)) : (J.toPlus P).app _ x = mk (Meq.mk ⊤ x) := by dsimp [mk, toPlus] delta Cover.toMultiequalizer - simp only [comp_apply] + simp only [CategoryTheory.comp_apply] apply congr_arg apply (Meq.equiv P ⊤).injective ext i - rw [Meq.equiv_apply, Equiv.apply_symm_apply, ← comp_apply, Multiequalizer.lift_ι] + rw [Meq.equiv_apply, Equiv.apply_symm_apply, ← CategoryTheory.comp_apply, Multiequalizer.lift_ι] rfl variable [∀ X : C, PreservesColimitsOfShape (J.Cover X)ᵒᵖ (forget D)] @@ -224,7 +224,7 @@ theorem eq_mk_iff_exists {X : C} {P : Cᵒᵖ ⥤ D} {S T : J.Cover X} (x : Meq convert hh all_goals dsimp [diagram] - erw [← comp_apply, Multiequalizer.lift_ι, Meq.equiv_symm_eq_apply] + erw [← CategoryTheory.comp_apply, Multiequalizer.lift_ι, Meq.equiv_symm_eq_apply] cases I; rfl · rintro ⟨S, h1, h2, e⟩ apply Concrete.colimit_rep_eq_of_exists @@ -235,7 +235,7 @@ theorem eq_mk_iff_exists {X : C} {P : Cᵒᵖ ⥤ D} {S T : J.Cover X} (x : Meq convert e all_goals dsimp - erw [← comp_apply, Multiequalizer.lift_ι] + erw [← CategoryTheory.comp_apply, Multiequalizer.lift_ι] erw [Meq.equiv_symm_eq_apply] cases i; rfl @@ -314,11 +314,12 @@ def meqOfSep (P : Cᵒᵖ ⥤ D) property := by intro II apply inj_of_sep P hsep - rw [← comp_apply, ← comp_apply, (J.toPlus P).naturality, (J.toPlus P).naturality, comp_apply, - comp_apply] + rw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply, (J.toPlus P).naturality, + (J.toPlus P).naturality, CategoryTheory.comp_apply, CategoryTheory.comp_apply] erw [toPlus_apply (T II.fst.fromMiddle) (t II.fst.fromMiddle) II.fst.toMiddle, - toPlus_apply (T II.snd.fromMiddle) (t II.snd.fromMiddle) II.snd.toMiddle, ← ht, ← ht, ← - comp_apply, ← comp_apply, ← (J.plusObj P).map_comp, ← (J.plusObj P).map_comp] + toPlus_apply (T II.snd.fromMiddle) (t II.snd.fromMiddle) II.snd.toMiddle, ← ht, ← ht, + ← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply, ← (J.plusObj P).map_comp, + ← (J.plusObj P).map_comp] rw [← op_comp, ← op_comp] exact s.condition (Cover.Relation.mk { hf := II.fst.from_middle_condition } @@ -396,7 +397,7 @@ theorem isSheaf_of_sep (P : Cᵒᵖ ⥤ D) intro I apply_fun Meq.equiv _ _ at h apply_fun fun e => e I at h - convert h <;> erw [Meq.equiv_apply, ← comp_apply, Multiequalizer.lift_ι] <;> rfl + convert h <;> erw [Meq.equiv_apply, ← CategoryTheory.comp_apply, Multiequalizer.lift_ι] <;> rfl · rintro (x : (multiequalizer (S.index _) : D)) obtain ⟨t, ht⟩ := exists_of_sep P hsep X S (Meq.equiv _ _ x) use t @@ -404,7 +405,7 @@ theorem isSheaf_of_sep (P : Cᵒᵖ ⥤ D) rw [← ht] ext i dsimp - erw [← comp_apply] + erw [← CategoryTheory.comp_apply] rw [Multiequalizer.lift_ι] rfl diff --git a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean index 390f9e08622c4..e45a2640c6fe8 100644 --- a/Mathlib/CategoryTheory/Sites/LocallySurjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallySurjective.lean @@ -47,7 +47,7 @@ def imageSieve {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) {U : C} (s : G.obj (op U)) : downward_closed := by rintro V W i ⟨t, ht⟩ j refine ⟨F.map j.op t, ?_⟩ - rw [op_comp, G.map_comp, comp_apply, ← ht, elementwise_of% f.naturality] + rw [op_comp, G.map_comp, CategoryTheory.comp_apply, ← ht, elementwise_of% f.naturality] theorem imageSieve_eq_sieveOfSection {F G : Cᵒᵖ ⥤ A} (f : F ⟶ G) {U : C} (s : G.obj (op U)) : imageSieve f s = (Subpresheaf.range (whiskerRight f (forget A))).sieveOfSection s := @@ -129,8 +129,8 @@ instance isLocallySurjective_comp {F₁ F₂ F₃ : Cᵒᵖ ⥤ A} (f₁ : F₁ imageSieve (f₁ ≫ f₂) s := by rintro V i ⟨W, i, j, H, ⟨t', ht'⟩, rfl⟩ refine ⟨t', ?_⟩ - rw [op_comp, F₃.map_comp, NatTrans.comp_app, comp_apply, comp_apply, ht', - elementwise_of% f₂.naturality, H.choose_spec] + rw [op_comp, F₃.map_comp, NatTrans.comp_app, CategoryTheory.comp_apply, + CategoryTheory.comp_apply, ht', elementwise_of% f₂.naturality, H.choose_spec] apply J.superset_covering this apply J.bind_covering · apply imageSieve_mem @@ -192,8 +192,8 @@ lemma isLocallyInjective_of_isLocallyInjective_of_isLocallySurjective apply J.superset_covering (Sieve.le_pullback_bind _ _ _ hf) apply equalizerSieve_mem J (f₁ ≫ f₂) dsimp - rw [comp_apply, comp_apply, app_localPreimage, app_localPreimage, - NatTrans.naturality_apply, NatTrans.naturality_apply, h] + rw [CategoryTheory.comp_apply, CategoryTheory.comp_apply, app_localPreimage, + app_localPreimage, NatTrans.naturality_apply, NatTrans.naturality_apply, h] lemma isLocallyInjective_of_isLocallyInjective_of_isLocallySurjective_fac {F₁ F₂ F₃ : Cᵒᵖ ⥤ A} {f₁ : F₁ ⟶ F₂} {f₂ : F₂ ⟶ F₃} (f₃ : F₁ ⟶ F₃) (fac : f₁ ≫ f₂ = f₃) @@ -218,7 +218,7 @@ lemma isLocallySurjective_of_isLocallySurjective_of_isLocallyInjective apply J.superset_covering (Sieve.le_pullback_bind _ _ _ hf) apply equalizerSieve_mem J f₂ rw [NatTrans.naturality_apply, ← app_localPreimage (f₁ ≫ f₂) _ _ hf, - NatTrans.comp_app, comp_apply] + NatTrans.comp_app, CategoryTheory.comp_apply] lemma isLocallySurjective_of_isLocallySurjective_of_isLocallyInjective_fac {F₁ F₂ F₃ : Cᵒᵖ ⥤ A} {f₁ : F₁ ⟶ F₂} {f₂ : F₂ ⟶ F₃} (f₃ : F₁ ⟶ F₃) (fac : f₁ ≫ f₂ = f₃) diff --git a/Mathlib/FieldTheory/Galois/Profinite.lean b/Mathlib/FieldTheory/Galois/Profinite.lean index 300f56169316b..aa3dfa714de11 100644 --- a/Mathlib/FieldTheory/Galois/Profinite.lean +++ b/Mathlib/FieldTheory/Galois/Profinite.lean @@ -52,7 +52,7 @@ namespace finGaloisGroupMap @[simp] lemma map_id (L : (FiniteGaloisIntermediateField k K)ᵒᵖ) : (finGaloisGroupMap (𝟙 L)) = 𝟙 L.unop.finGaloisGroup := - AlgEquiv.restrictNormalHom_id _ _ + ConcreteCategory.ext (AlgEquiv.restrictNormalHom_id _ _) @[simp] lemma map_comp {L₁ L₂ L₃ : (FiniteGaloisIntermediateField k K)ᵒᵖ} (f : L₁ ⟶ L₂) (g : L₂ ⟶ L₃) : @@ -68,6 +68,7 @@ lemma map_comp {L₁ L₂ L₃ : (FiniteGaloisIntermediateField k K)ᵒᵖ} (f : haveI : IsScalarTower k L₃ L₁ := IsScalarTower.of_algebraMap_eq' rfl haveI : IsScalarTower k L₃ L₂ := IsScalarTower.of_algebraMap_eq' rfl haveI : IsScalarTower L₃ L₂ L₁ := IsScalarTower.of_algebraMap_eq' rfl + ext : 1 apply IsScalarTower.AlgEquiv.restrictNormalHom_comp k L₃ L₂ L₁ end finGaloisGroupMap diff --git a/Mathlib/Order/Category/NonemptyFinLinOrd.lean b/Mathlib/Order/Category/NonemptyFinLinOrd.lean index b403f4df16856..aef85c696b258 100644 --- a/Mathlib/Order/Category/NonemptyFinLinOrd.lean +++ b/Mathlib/Order/Category/NonemptyFinLinOrd.lean @@ -170,7 +170,7 @@ theorem epi_iff_surjective {A B : NonemptyFinLinOrd.{u}} (f : A ⟶ B) : congr rw [← cancel_epi f] ext a - simp only [coe_of, comp_apply] + simp only [CategoryTheory.comp_apply] change ite _ _ _ = ite _ _ _ split_ifs with h₁ h₂ h₂ any_goals rfl diff --git a/Mathlib/RepresentationTheory/Invariants.lean b/Mathlib/RepresentationTheory/Invariants.lean index acf708f7c06b9..7678294b40532 100644 --- a/Mathlib/RepresentationTheory/Invariants.lean +++ b/Mathlib/RepresentationTheory/Invariants.lean @@ -123,8 +123,8 @@ theorem mem_invariants_iff_comm {X Y : Rep k G} (f : X.V →ₗ[k] Y.V) (g : G) dsimp rw [← LinearMap.comp_assoc, ← ModuleCat.hom_ofHom (Y.ρ g), ← ModuleCat.hom_ofHom f, ← ModuleCat.hom_comp, ← ModuleCat.hom_ofHom (X.ρ g⁻¹), ← ModuleCat.hom_comp, - Rep.ofHom_ρ, ← ρAut_apply_inv X g, Rep.ofHom_ρ, ← ρAut_apply_hom Y g, ← ModuleCat.hom_ext_iff, - Iso.inv_comp_eq, ρAut_apply_hom, ← ModuleCat.hom_ofHom (X.ρ g), + Rep.ofHom_ρ, ← ρAut_hom_apply_inv X g, Rep.ofHom_ρ, ← ρAut_hom_apply_hom Y g, + ← ModuleCat.hom_ext_iff, Iso.inv_comp_eq, ρAut_hom_apply_hom, ← ModuleCat.hom_ofHom (X.ρ g), ← ModuleCat.hom_comp, ← ModuleCat.hom_ext_iff] exact comm diff --git a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean index a916bde9ffec6..c6515864de4c0 100644 --- a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean +++ b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean @@ -162,14 +162,12 @@ def ofFiniteGrp (G : FiniteGrp) : ProfiniteGrp := instance : HasForget₂ FiniteGrp ProfiniteGrp where forget₂ := { obj := ofFiniteGrp - map := fun f => ⟨f, by continuity⟩ } + map := fun f => ⟨f.hom, by continuity⟩ } @[to_additive] instance : HasForget₂ ProfiniteGrp Grp where - forget₂ := { - obj := fun P => ⟨P, P.group⟩ - map := fun f => f.toMonoidHom - } + forget₂.obj P := Grp.of P + forget₂.map f := Grp.ofHom f.toMonoidHom /-- A closed subgroup of a profinite group is profinite. -/ def ofClosedSubgroup {G : ProfiniteGrp} (H : ClosedSubgroup G) : ProfiniteGrp := diff --git a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean index d231af692dbf8..c3ce6598e0eb7 100644 --- a/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean +++ b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Limits.lean @@ -43,9 +43,9 @@ instance (P : ProfiniteGrp) : SmallCategory (OpenNormalSubgroup P) := where `P : ProfiniteGrp`. -/ def toFiniteQuotientFunctor (P : ProfiniteGrp) : OpenNormalSubgroup P ⥤ FiniteGrp := { obj := fun H => FiniteGrp.of (P ⧸ H.toSubgroup) - map := fun fHK => QuotientGroup.map _ _ (.id _) (leOfHom fHK) - map_id _ := QuotientGroup.map_id _ - map_comp f g := (QuotientGroup.map_comp_map + map := fun fHK => FiniteGrp.ofHom (QuotientGroup.map _ _ (.id _) (leOfHom fHK)) + map_id _ := ConcreteCategory.ext <| QuotientGroup.map_id _ + map_comp f g := ConcreteCategory.ext <| (QuotientGroup.map_comp_map _ _ _ (.id _) (.id _) (leOfHom f) (leOfHom g)).symm } /--The `MonoidHom` from a profinite group `P` to the projective limit of its quotients by diff --git a/Mathlib/Topology/Category/CompHaus/Basic.lean b/Mathlib/Topology/Category/CompHaus/Basic.lean index e3e5ac0e6628e..705abf604355d 100644 --- a/Mathlib/Topology/Category/CompHaus/Basic.lean +++ b/Mathlib/Topology/Category/CompHaus/Basic.lean @@ -168,7 +168,7 @@ def limitCone {J : Type v} [SmallCategory J] (F : J ⥤ CompHaus.{max v u}) : Li naturality := by intro _ _ f ext ⟨x, hx⟩ - simp only [comp_apply, Functor.const_obj_map, id_apply] + simp only [CategoryTheory.comp_apply, Functor.const_obj_map, CategoryTheory.id_apply] exact (hx f).symm } } /-- The limit cone `CompHaus.limitCone F` is indeed a limit cone. -/ diff --git a/Mathlib/Topology/Category/Profinite/Basic.lean b/Mathlib/Topology/Category/Profinite/Basic.lean index e0da94050bcc9..30959b584c678 100644 --- a/Mathlib/Topology/Category/Profinite/Basic.lean +++ b/Mathlib/Topology/Category/Profinite/Basic.lean @@ -240,8 +240,8 @@ theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Funct apply ULift.ext dsimp [g, LocallyConstant.ofIsClopen] -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk, - Function.comp_apply, if_neg] + erw [CategoryTheory.comp_apply, ContinuousMap.coe_mk, CategoryTheory.comp_apply, + ContinuousMap.coe_mk, Function.comp_apply, if_neg] refine mt (fun α => hVU α) ?_ simp only [U, C, Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff] apply_fun fun e => (e y).down at H diff --git a/Mathlib/Topology/Category/TopCat/Limits/Products.lean b/Mathlib/Topology/Category/TopCat/Limits/Products.lean index 6a1dbd61c0562..e9caaf169d458 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Products.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Products.lean @@ -217,9 +217,9 @@ theorem range_prod_map {W X Y Z : TopCat.{u}} (f : W ⟶ Y) (g : X ⟶ Z) : · rintro ⟨y, rfl⟩ simp_rw [Set.mem_inter_iff, Set.mem_preimage, Set.mem_range] -- sizable changes in this proof after https://github.com/leanprover-community/mathlib4/pull/13170 - rw [← comp_apply, ← comp_apply] + rw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply] simp_rw [Limits.prod.map_fst, - Limits.prod.map_snd, comp_apply] + Limits.prod.map_snd, CategoryTheory.comp_apply] exact ⟨exists_apply_eq_apply _ _, exists_apply_eq_apply _ _⟩ · rintro ⟨⟨x₁, hx₁⟩, ⟨x₂, hx₂⟩⟩ use (prodIsoProd W X).inv (x₁, x₂) @@ -227,12 +227,12 @@ theorem range_prod_map {W X Y Z : TopCat.{u}} (f : W ⟶ Y) (g : X ⟶ Z) : apply Concrete.limit_ext rintro ⟨⟨⟩⟩ · change limit.π (pair Y Z) _ ((prod.map f g) _) = _ - erw [← comp_apply, Limits.prod.map_fst] + erw [← CategoryTheory.comp_apply, Limits.prod.map_fst] change (_ ≫ _ ≫ f) _ = _ rw [TopCat.prodIsoProd_inv_fst_assoc,TopCat.comp_app] exact hx₁ · change limit.π (pair Y Z) _ ((prod.map f g) _) = _ - erw [← comp_apply, Limits.prod.map_snd] + erw [← CategoryTheory.comp_apply, Limits.prod.map_snd] change (_ ≫ _ ≫ g) _ = _ rw [TopCat.prodIsoProd_inv_snd_assoc,TopCat.comp_app] exact hx₂ diff --git a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean index fe21e9bb40dc6..910c964c28b26 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean @@ -48,7 +48,7 @@ def pullbackCone (f : X ⟶ Z) (g : Y ⟶ Z) : PullbackCone f g := -- Next 2 lines were -- `rw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk]` -- `exact h` before https://github.com/leanprover/lean4/pull/2644 - rw [comp_apply, comp_apply] + rw [CategoryTheory.comp_apply, CategoryTheory.comp_apply] congr!) /-- The constructed cone is a limit. -/ @@ -69,12 +69,12 @@ def pullbackConeIsLimit (f : X ⟶ Z) (g : Y ⟶ Z) : IsLimit (pullbackCone f g) · delta pullbackCone ext a -- This used to be `rw`, but we need `rw; rfl` after https://github.com/leanprover/lean4/pull/2644 - rw [comp_apply, ContinuousMap.coe_mk] + rw [CategoryTheory.comp_apply, ContinuousMap.coe_mk] rfl · delta pullbackCone ext a -- This used to be `rw`, but we need `rw; rfl` after https://github.com/leanprover/lean4/pull/2644 - rw [comp_apply, ContinuousMap.coe_mk] + rw [CategoryTheory.comp_apply, ContinuousMap.coe_mk] rfl · intro m h₁ h₂ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): used to be `ext x`. @@ -150,7 +150,7 @@ theorem range_pullback_to_prod {X Y Z : TopCat} (f : X ⟶ Z) (g : Y ⟶ Z) : change (forget TopCat).map _ _ = _ -- new `change` after https://github.com/leanprover-community/mathlib4/pull/13170 apply Concrete.limit_ext rintro ⟨⟨⟩⟩ <;> - erw [← comp_apply, ← comp_apply, limit.lift_π] <;> -- now `erw` after https://github.com/leanprover-community/mathlib4/pull/13170 + erw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply, limit.lift_π] <;> -- now `erw` after https://github.com/leanprover-community/mathlib4/pull/13170 -- This used to be `simp` before https://github.com/leanprover/lean4/pull/2644 aesop_cat @@ -202,29 +202,30 @@ theorem range_pullback_map {W X Y Z S T : TopCat} (f₁ : W ⟶ S) (f₂ : X ⟶ constructor · rintro ⟨y, rfl⟩ simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_range] - rw [← comp_apply, ← comp_apply] - simp only [limit.lift_π, PullbackCone.mk_pt, PullbackCone.mk_π_app, comp_apply] + rw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply] + simp only [limit.lift_π, PullbackCone.mk_pt, PullbackCone.mk_π_app, CategoryTheory.comp_apply] exact ⟨exists_apply_eq_apply _ _, exists_apply_eq_apply _ _⟩ rintro ⟨⟨x₁, hx₁⟩, ⟨x₂, hx₂⟩⟩ have : f₁ x₁ = f₂ x₂ := by apply (TopCat.mono_iff_injective _).mp H₃ - rw [← comp_apply, eq₁, ← comp_apply, eq₂, - comp_apply, comp_apply, hx₁, hx₂, ← comp_apply, pullback.condition] + rw [← CategoryTheory.comp_apply, eq₁, ← CategoryTheory.comp_apply, eq₂, + CategoryTheory.comp_apply, CategoryTheory.comp_apply, hx₁, hx₂, ← CategoryTheory.comp_apply, + pullback.condition] rfl -- `rfl` was not needed before https://github.com/leanprover-community/mathlib4/pull/13170 use (pullbackIsoProdSubtype f₁ f₂).inv ⟨⟨x₁, x₂⟩, this⟩ change (forget TopCat).map _ _ = _ apply Concrete.limit_ext rintro (_ | _ | _) <;> - erw [← comp_apply, ← comp_apply] -- now `erw` after https://github.com/leanprover-community/mathlib4/pull/13170 + erw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply] -- now `erw` after https://github.com/leanprover-community/mathlib4/pull/13170 · simp only [Category.assoc, limit.lift_π, PullbackCone.mk_π_app_one] - simp only [cospan_one, pullbackIsoProdSubtype_inv_fst_assoc, comp_apply] + simp only [cospan_one, pullbackIsoProdSubtype_inv_fst_assoc, CategoryTheory.comp_apply] rw [pullbackFst_apply, hx₁, ← limit.w _ WalkingCospan.Hom.inl, cospan_map_inl, - comp_apply (g := g₁)] + CategoryTheory.comp_apply (g := g₁)] · simp only [cospan_left, limit.lift_π, PullbackCone.mk_pt, PullbackCone.mk_π_app, - pullbackIsoProdSubtype_inv_fst_assoc, comp_apply] + pullbackIsoProdSubtype_inv_fst_assoc, CategoryTheory.comp_apply] erw [hx₁] -- now `erw` after https://github.com/leanprover-community/mathlib4/pull/13170 · simp only [cospan_right, limit.lift_π, PullbackCone.mk_pt, PullbackCone.mk_π_app, - pullbackIsoProdSubtype_inv_snd_assoc, comp_apply] + pullbackIsoProdSubtype_inv_snd_assoc, CategoryTheory.comp_apply] erw [hx₂] -- now `erw` after https://github.com/leanprover-community/mathlib4/pull/13170 theorem pullback_fst_range {X Y S : TopCat} (f : X ⟶ S) (g : Y ⟶ S) : diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index bf2384b9dc371..e11b66b3b1c6a 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -196,8 +196,9 @@ theorem ι_eq_iff_rel (i j : D.J) (x : D.U i) (y : D.U j) : (ConcreteCategory.bijective_of_isIso (sigmaIsoSigma.{u, u} _).inv).2 x unfold InvImage MultispanIndex.fstSigmaMap MultispanIndex.sndSigmaMap simp only [forget_map_eq_coe] - erw [TopCat.comp_app, sigmaIsoSigma_inv_apply, ← comp_apply, ← comp_apply, - colimit.ι_desc_assoc, ← comp_apply, ← comp_apply, colimit.ι_desc_assoc] + erw [TopCat.comp_app, sigmaIsoSigma_inv_apply, ← CategoryTheory.comp_apply, + ← CategoryTheory.comp_apply, colimit.ι_desc_assoc, ← CategoryTheory.comp_apply, + ← CategoryTheory.comp_apply, colimit.ι_desc_assoc] -- previous line now `erw` after https://github.com/leanprover-community/mathlib4/pull/13170 erw [sigmaIsoSigma_hom_ι_apply, sigmaIsoSigma_hom_ι_apply] exact Or.inr ⟨y, ⟨rfl, rfl⟩⟩ diff --git a/Mathlib/Topology/Sheaves/LocallySurjective.lean b/Mathlib/Topology/Sheaves/LocallySurjective.lean index 32921d1029957..6a26cf0ba144b 100644 --- a/Mathlib/Topology/Sheaves/LocallySurjective.lean +++ b/Mathlib/Topology/Sheaves/LocallySurjective.lean @@ -109,7 +109,7 @@ theorem locally_surjective_iff_surjective_on_stalks (T : ℱ ⟶ 𝒢) : obtain ⟨W, hxW, hWV, hWU, h_eq⟩ := key_W refine ⟨W, hWU, ⟨ℱ.map hWV.op s, ?_⟩, hxW⟩ convert h_eq using 1 - simp only [← comp_apply, T.naturality] + simp only [← CategoryTheory.comp_apply, T.naturality] end SurjectiveOnStalks diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index f35935ec8b97b..5cfcb17e14a6e 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -130,14 +130,14 @@ theorem restrict_restrict {X : TopCat} {C : Type*} [Category C] [HasForget C] {F : X.Presheaf C} {U V W : Opens X} (e₁ : U ≤ V) (e₂ : V ≤ W) (x : F.obj (op W)) : x |_ V |_ U = x |_ U := by delta restrictOpen restrict - rw [← comp_apply, ← Functor.map_comp] + rw [← CategoryTheory.comp_apply, ← Functor.map_comp] rfl theorem map_restrict {X : TopCat} {C : Type*} [Category C] [HasForget C] {F G : X.Presheaf C} (e : F ⟶ G) {U V : Opens X} (h : U ≤ V) (x : F.obj (op V)) : e.app _ (x |_ U) = e.app _ x |_ U := by delta restrictOpen restrict - rw [← comp_apply, NatTrans.naturality, comp_apply] + rw [← CategoryTheory.comp_apply, NatTrans.naturality, CategoryTheory.comp_apply] open CategoryTheory.Limits diff --git a/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean b/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean index 43f8af284c79a..3ff71a0720c23 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/UniqueGluing.lean @@ -181,12 +181,12 @@ theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h refine ⟨F.1.map (eqToHom V_eq_supr_U).op gl, ?_, ?_⟩ · intro i - rw [← comp_apply, ← F.1.map_comp] + rw [← CategoryTheory.comp_apply, ← F.1.map_comp] exact gl_spec i · intro gl' gl'_spec convert congr_arg _ (gl_uniq (F.1.map (eqToHom V_eq_supr_U.symm).op gl') fun i => _) <;> - rw [← comp_apply, ← F.1.map_comp] - · rw [eqToHom_op, eqToHom_op, eqToHom_trans, eqToHom_refl, F.1.map_id, id_apply] + rw [← CategoryTheory.comp_apply, ← F.1.map_comp] + · rw [eqToHom_op, eqToHom_op, eqToHom_trans, eqToHom_refl, F.1.map_id, CategoryTheory.id_apply] · convert gl'_spec i @[ext] @@ -195,7 +195,7 @@ theorem eq_of_locally_eq (s t : F.1.obj (op (iSup U))) let sf : ∀ i : ι, F.1.obj (op (U i)) := fun i => F.1.map (Opens.leSupr U i).op s have sf_compatible : IsCompatible _ U sf := by intro i j - simp_rw [sf, ← comp_apply, ← F.1.map_comp] + simp_rw [sf, ← CategoryTheory.comp_apply, ← F.1.map_comp] rfl obtain ⟨gl, -, gl_uniq⟩ := F.existsUnique_gluing U sf sf_compatible trans gl @@ -215,11 +215,11 @@ theorem eq_of_locally_eq' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le) suffices F.1.map (eqToHom V_eq_supr_U.symm).op s = F.1.map (eqToHom V_eq_supr_U.symm).op t by convert congr_arg (F.1.map (eqToHom V_eq_supr_U).op) this <;> - rw [← comp_apply, ← F.1.map_comp, eqToHom_op, eqToHom_op, eqToHom_trans, eqToHom_refl, - F.1.map_id, id_apply] + rw [← CategoryTheory.comp_apply, ← F.1.map_comp, eqToHom_op, eqToHom_op, eqToHom_trans, + eqToHom_refl, F.1.map_id, CategoryTheory.id_apply] apply eq_of_locally_eq intro i - rw [← comp_apply, ← comp_apply, ← F.1.map_comp] + rw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply, ← F.1.map_comp] convert h i theorem eq_of_locally_eq₂ {U₁ U₂ V : Opens X} (i₁ : U₁ ⟶ V) (i₂ : U₂ ⟶ V) (hcover : V ≤ U₁ ⊔ U₂) diff --git a/Mathlib/Topology/Sheaves/Stalks.lean b/Mathlib/Topology/Sheaves/Stalks.lean index 2b6e732ac1bea..cfc4885a55d29 100644 --- a/Mathlib/Topology/Sheaves/Stalks.lean +++ b/Mathlib/Topology/Sheaves/Stalks.lean @@ -113,12 +113,14 @@ lemma map_germ_eq_Γgerm (F : X.Presheaf C) {U : Opens X} {i : U ⟶ ⊤} (x : X attribute [local instance] HasForget.instFunLike in theorem germ_res_apply (F : X.Presheaf C) {U V : Opens X} (i : U ⟶ V) (x : X) (hx : x ∈ U) [HasForget C] (s) : - F.germ U x hx (F.map i.op s) = F.germ V x (i.le hx) s := by rw [← comp_apply, germ_res] + F.germ U x hx (F.map i.op s) = F.germ V x (i.le hx) s := by + rw [← CategoryTheory.comp_apply, germ_res] attribute [local instance] HasForget.instFunLike in theorem germ_res_apply' (F : X.Presheaf C) {U V : Opens X} (i : op V ⟶ op U) (x : X) (hx : x ∈ U) [HasForget C] (s) : - F.germ U x hx (F.map i s) = F.germ V x (i.unop.le hx) s := by rw [← comp_apply, germ_res'] + F.germ U x hx (F.map i s) = F.germ V x (i.unop.le hx) s := by + rw [← CategoryTheory.comp_apply, germ_res'] attribute [local instance] HasForget.instFunLike in lemma Γgerm_res_apply (F : X.Presheaf C) @@ -143,8 +145,8 @@ attribute [local instance] HasForget.instFunLike in theorem stalkFunctor_map_germ_apply [HasForget C] {F G : X.Presheaf C} (U : Opens X) (x : X) (hx : x ∈ U) (f : F ⟶ G) (s) : (stalkFunctor C x).map f (F.germ U x hx s) = G.germ U x hx (f.app (op U) s) := by - rw [← comp_apply, ← stalkFunctor_map_germ] - exact (comp_apply _ _ _).symm + rw [← CategoryTheory.comp_apply, ← stalkFunctor_map_germ] + exact (CategoryTheory.comp_apply _ _ _).symm -- a variant of `stalkFunctor_map_germ_apply` that makes simpNF happy. attribute [local instance] HasForget.instFunLike in @@ -403,7 +405,8 @@ theorem germ_ext (F : X.Presheaf C) {U V : Opens X} {x : X} {hxU : x ∈ U} {hxV (W : Opens X) (hxW : x ∈ W) (iWU : W ⟶ U) (iWV : W ⟶ V) {sU : F.obj (op U)} {sV : F.obj (op V)} (ih : F.map iWU.op sU = F.map iWV.op sV) : F.germ _ x hxU sU = F.germ _ x hxV sV := by - rw [← F.germ_res iWU x hxW, ← F.germ_res iWV x hxW, comp_apply, comp_apply, ih] + rw [← F.germ_res iWU x hxW, ← F.germ_res iWV x hxW, CategoryTheory.comp_apply, + CategoryTheory.comp_apply, ih] variable [PreservesFilteredColimits (forget C)] @@ -436,7 +439,8 @@ theorem stalkFunctor_map_injective_of_app_injective {F G : Presheaf C X} (f : F rcases germ_exist F x t with ⟨U₂, hxU₂, t, rfl⟩ rw [stalkFunctor_map_germ_apply, stalkFunctor_map_germ_apply] at hst obtain ⟨W, hxW, iWU₁, iWU₂, heq⟩ := G.germ_eq x hxU₁ hxU₂ _ _ hst - rw [← comp_apply, ← comp_apply, ← f.naturality, ← f.naturality, comp_apply, comp_apply] at heq + rw [← CategoryTheory.comp_apply, ← CategoryTheory.comp_apply, ← f.naturality, ← f.naturality, + CategoryTheory.comp_apply, CategoryTheory.comp_apply] at heq replace heq := h W heq convert congr_arg (F.germ _ x hxW) heq using 1 exacts [(F.germ_res_apply iWU₁ x hxW s).symm, (F.germ_res_apply iWU₂ x hxW t).symm] @@ -533,7 +537,7 @@ theorem app_surjective_of_injective_of_locally_surjective {F G : Sheaf C X} (f : · use s apply G.eq_of_locally_eq' V U iVU V_cover intro x - rw [← comp_apply, ← f.1.naturality, comp_apply, s_spec, heq] + rw [← CategoryTheory.comp_apply, ← f.1.naturality, CategoryTheory.comp_apply, s_spec, heq] intro x y -- What's left to show here is that the sections `sf` are compatible, i.e. they agree on -- the intersections `V x ⊓ V y`. We prove this by showing that all germs are equal. @@ -543,7 +547,8 @@ theorem app_surjective_of_injective_of_locally_surjective {F G : Sheaf C X} (f : apply hinj z ((iVU x).le ((inf_le_left : V x ⊓ V y ≤ V x) hz)) dsimp only rw [stalkFunctor_map_germ_apply, stalkFunctor_map_germ_apply] - simp_rw [← comp_apply, f.1.naturality, comp_apply, heq, ← comp_apply, ← G.1.map_comp] + simp_rw [← CategoryTheory.comp_apply, f.1.naturality, CategoryTheory.comp_apply, heq, + ← CategoryTheory.comp_apply, ← G.1.map_comp] rfl theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X) @@ -562,7 +567,7 @@ theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F obtain ⟨V₂, hxV₂, iV₂V₁, iV₂U, heq⟩ := G.presheaf.germ_eq x hxV₁ hx _ _ hs₁ -- The restriction of `s₁` to that neighborhood is our desired local preimage. use V₂, hxV₂, iV₂U, F.1.map iV₂V₁.op s₁ - rw [← comp_apply, f.1.naturality, comp_apply, heq] + rw [← CategoryTheory.comp_apply, f.1.naturality, CategoryTheory.comp_apply, heq] theorem app_bijective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X) (h : ∀ x ∈ U, Function.Bijective ((stalkFunctor C x).map f.1)) : diff --git a/MathlibTest/CategoryTheory/ConcreteCategory/Grp.lean b/MathlibTest/CategoryTheory/ConcreteCategory/Grp.lean new file mode 100644 index 0000000000000..ccdb7fef7905b --- /dev/null +++ b/MathlibTest/CategoryTheory/ConcreteCategory/Grp.lean @@ -0,0 +1,50 @@ +import Mathlib.Algebra.Category.Grp.Basic + +universe v u + +open CategoryTheory Grp + +set_option maxHeartbeats 10000 +set_option synthInstance.maxHeartbeats 2000 + +/- We test if all the coercions and `map_add` lemmas trigger correctly. -/ + +example (X : Type u) [Group X] : ⇑(𝟙 (of X)) = id := by simp + +example {X Y : Type u} [Group X] [Group Y] (f : X →* Y) : + ⇑(ofHom f) = ⇑f := by simp + +example {X Y : Type u} [Group X] [Group Y] (f : X →* Y) + (x : X) : (ofHom f) x = f x := by simp + +example {X Y Z : Grp} (f : X ⟶ Y) (g : Y ⟶ Z) : ⇑(f ≫ g) = ⇑g ∘ ⇑f := by simp + +example {X Y Z : Type u} [Group X] [Group Y] [Group Z] + (f : X →* Y) (g : Y →* Z) : + ⇑(ofHom f ≫ ofHom g) = g ∘ f := by simp + +example {X Y : Type u} [Group X] [Group Y] {Z : Grp} + (f : X →* Y) (g : of Y ⟶ Z) : + ⇑(ofHom f ≫ g) = g ∘ f := by simp + +example {X Y : Grp} {Z : Type u} [Group Z] (f : X ⟶ Y) (g : Y ⟶ of Z) : + ⇑(f ≫ g) = g ∘ f := by simp + +example {Y Z : Grp} {X : Type u} [Group X] (f : of X ⟶ Y) (g : Y ⟶ Z) : + ⇑(f ≫ g) = g ∘ f := by simp + +example {X Y Z : Grp} (f : X ⟶ Y) (g : Y ⟶ Z) (x : X) : (f ≫ g) x = g (f x) := by simp + +example {X Y : Grp} (e : X ≅ Y) (x : X) : e.inv (e.hom x) = x := by simp + +example {X Y : Grp} (e : X ≅ Y) (y : Y) : e.hom (e.inv y) = y := by simp + +example (X : Grp) : ⇑(𝟙 X) = id := by simp + +example {X : Type*} [Group X] : ⇑(MonoidHom.id X) = id := by simp + +example {M N : Grp} (f : M ⟶ N) (x y : M) : f (x * y) = f x * f y := by + simp + +example {M N : Grp} (f : M ⟶ N) : f 1 = 1 := by + simp From 9571e4aeb3689e34e89f18bba35fda5ae7a1fcd5 Mon Sep 17 00:00:00 2001 From: Kyle Miller Date: Thu, 30 Jan 2025 09:06:19 +0000 Subject: [PATCH 668/681] feat: let `notation3` pretty print "overapplied" notations (#21239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR makes `notation3`s delaborators be able to handle "overapplied" functions — these are notations that expand to functions that might then be applied to arguments. The fundamental issue is that we need to know the arity of a function to be able to keep track of how many arguments are supposed to be matched for the notation and how many are supposed to be put toward normal app delaboration. With some changes to core in the last year, we now have a `withOverApp` combinator we can take advantage of. To make use of it, the `notation3` delaborator generator has been modified to compute arities while creating matchers. The effect is that we now observe ```lean import Mathlib.Algebra.BigOperators.Finprod variable (ι R : Type) (f : ι → R) [DecidableEq ι] [CommRing R] example : (∑ᶠ (i : ι), Pi.single i (f i)) = f := by -- ⊢ ∑ᶠ (i : ι), Pi.single i (f i) = f ext j -- ⊢ (∑ᶠ (i : ι), Pi.single i (f i)) j = f j sorry ``` where before this PR the state after `ext j` was `⊢ finsum (fun i => Pi.single i (f i)) j = f j`. Implementation note: matchers can be associated to multiple delaboration keys. Previously we would define a single delaborator and then give it multiple `delab` attributes per key. This is very rare to have more than one key. For simplicity, we now define a separate delaborator per key, since each can have its own arity processing. --- Mathlib/Util/Notation3.lean | 76 +++++++++++++++++++++++++------------ MathlibTest/notation3.lean | 8 ++-- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/Mathlib/Util/Notation3.lean b/Mathlib/Util/Notation3.lean index 17e8a9c0118e2..d5c79e7382d52 100644 --- a/Mathlib/Util/Notation3.lean +++ b/Mathlib/Util/Notation3.lean @@ -217,6 +217,24 @@ def setupLCtx (lctx : LocalContext) (boundNames : Array Name) : boundFVars := boundFVars.insert fvarId name return (lctx, boundFVars) +/-- +Represents a key to use when registering the `delab` attribute for a delaborator. +We use this to handle overapplication. +-/ +inductive DelabKey where + /-- The key `app.const` or `app` with a specific arity. -/ + | app (const : Option Name) (arity : Nat) + | other (key : Name) + deriving Repr + +/-- +Turns the `DelabKey` into a key that the `delab` attribute accepts. +-/ +def DelabKey.key : DelabKey → Name + | .app none _ => `app + | .app (some n) _ => `app ++ n + | .other key => key + /-- Given an expression, generate a matcher for it. The `boundFVars` hash map records which state variables certain fvars correspond to. The `localFVars` hash map records which local variable the matcher should use for an exact @@ -228,11 +246,11 @@ If it succeeds generating a matcher, returns 2. a `Term` that represents a `Matcher` for the given expression `e`. -/ partial def exprToMatcher (boundFVars : Std.HashMap FVarId Name) (localFVars : Std.HashMap FVarId Term) (e : Expr) : - OptionT TermElabM (List Name × Term) := do + OptionT TermElabM (List DelabKey × Term) := do match e with | .mvar .. => return ([], ← `(pure)) - | .const n _ => return ([`app ++ n], ← ``(matchExpr (Expr.isConstOf · $(quote n)))) - | .sort .. => return ([`sort], ← ``(matchExpr Expr.isSort)) + | .const n _ => return ([.app n 0], ← ``(matchExpr (Expr.isConstOf · $(quote n)))) + | .sort .. => return ([.other `sort], ← ``(matchExpr Expr.isSort)) | .fvar fvarId => if let some n := boundFVars[fvarId]? then -- This fvar is a pattern variable. @@ -245,14 +263,19 @@ partial def exprToMatcher (boundFVars : Std.HashMap FVarId Name) if n.hasMacroScopes then -- Match by just the type; this is likely an unnamed instance for example let (_, m) ← exprToMatcher boundFVars localFVars (← instantiateMVars (← inferType e)) - return ([`fvar], ← ``(matchTypeOf $m)) + return ([.other `fvar], ← ``(matchTypeOf $m)) else -- This is an fvar from a `variable`. Match by name and type. let (_, m) ← exprToMatcher boundFVars localFVars (← instantiateMVars (← inferType e)) - return ([`fvar], ← ``(matchFVar $(quote n) $m)) + return ([.other `fvar], ← ``(matchFVar $(quote n) $m)) | .app .. => e.withApp fun f args => do - let (keys, matchF) ← exprToMatcher boundFVars localFVars f + let (keys, matchF) ← + if let .const n _ := f then + pure ([.app n args.size], ← ``(matchExpr (Expr.isConstOf · $(quote n)))) + else + let (_, matchF) ← exprToMatcher boundFVars localFVars f + pure ([.app none args.size], matchF) let mut fty ← inferType f let mut matcher := matchF for arg in args do @@ -268,8 +291,8 @@ partial def exprToMatcher (boundFVars : Std.HashMap FVarId Name) else let (_, matchArg) ← exprToMatcher boundFVars localFVars arg matcher ← ``(matchApp $matcher $matchArg) - return (if keys.isEmpty then [`app] else keys, matcher) - | .lit (.natVal n) => return ([`lit], ← ``(natLitMatcher $(quote n))) + return (keys, matcher) + | .lit (.natVal n) => return ([.other `lit], ← ``(natLitMatcher $(quote n))) | .forallE n t b bi => let (_, matchDom) ← exprToMatcher boundFVars localFVars t withLocalDecl n bi t fun arg => withFreshMacroScope do @@ -277,7 +300,7 @@ partial def exprToMatcher (boundFVars : Std.HashMap FVarId Name) let body := b.instantiate1 arg let localFVars' := localFVars.insert arg.fvarId! n' let (_, matchBody) ← exprToMatcher boundFVars localFVars' body - return ([`forallE], ← ``(matchForall $matchDom (fun $n' => $matchBody))) + return ([.other `forallE], ← ``(matchForall $matchDom (fun $n' => $matchBody))) | .lam n t b bi => let (_, matchDom) ← exprToMatcher boundFVars localFVars t withLocalDecl n bi t fun arg => withFreshMacroScope do @@ -285,7 +308,7 @@ partial def exprToMatcher (boundFVars : Std.HashMap FVarId Name) let body := b.instantiate1 arg let localFVars' := localFVars.insert arg.fvarId! n' let (_, matchBody) ← exprToMatcher boundFVars localFVars' body - return ([`lam], ← ``(matchLambda $matchDom (fun $n' => $matchBody))) + return ([.other `lam], ← ``(matchLambda $matchDom (fun $n' => $matchBody))) | _ => trace[notation3] "can't generate matcher for {e}" failure @@ -297,7 +320,7 @@ Fails in the `OptionT` sense if it comes across something it's unable to handle. Also returns constant names that could serve as a key for a delaborator. For example, if it's for a function `f`, then `app.f`. -/ partial def mkExprMatcher (stx : Term) (boundNames : Array Name) : - OptionT TermElabM (List Name × Term) := do + OptionT TermElabM (List DelabKey × Term) := do let (lctx, boundFVars) ← setupLCtx (← getLCtx) boundNames withLCtx lctx (← getLocalInstances) do let patt ← @@ -360,7 +383,7 @@ Fails in the `OptionT` sense if a matcher couldn't be constructed. Also returns a delaborator key like in `mkExprMatcher`. Reminder: `$lit:ident : (scoped $scopedId:ident => $scopedTerm:Term)` -/ partial def mkScopedMatcher (lit scopeId : Name) (scopedTerm : Term) (boundNames : Array Name) : - OptionT TermElabM (List Name × Term) := do + OptionT TermElabM (List DelabKey × Term) := do -- Build the matcher for `scopedTerm` with `scopeId` as an additional variable let (keys, smatcher) ← mkExprMatcher scopedTerm (boundNames.push scopeId) return (keys, ← ``(matchScoped $(quote lit) $(quote scopeId) $smatcher)) @@ -389,7 +412,7 @@ partial def matchFoldl (lit x y : Name) (smatcher : Matcher) (sinit : Matcher) : /-- Create a `Term` that represents a matcher for `foldl` notation. Reminder: `( lit ","* => foldl (x y => scopedTerm) init)` -/ partial def mkFoldlMatcher (lit x y : Name) (scopedTerm init : Term) (boundNames : Array Name) : - OptionT TermElabM (List Name × Term) := do + OptionT TermElabM (List DelabKey × Term) := do -- Build the `scopedTerm` matcher with `x` and `y` as additional variables let boundNames' := boundNames |>.push x |>.push y let (keys, smatcher) ← mkExprMatcher scopedTerm boundNames' @@ -399,7 +422,7 @@ partial def mkFoldlMatcher (lit x y : Name) (scopedTerm init : Term) (boundNames /-- Create a `Term` that represents a matcher for `foldr` notation. Reminder: `( lit ","* => foldr (x y => scopedTerm) init)` -/ partial def mkFoldrMatcher (lit x y : Name) (scopedTerm init : Term) (boundNames : Array Name) : - OptionT TermElabM (List Name × Term) := do + OptionT TermElabM (List DelabKey × Term) := do -- Build the `scopedTerm` matcher with `x` and `y` as additional variables let boundNames' := boundNames |>.push x |>.push y let (keys, smatcher) ← mkExprMatcher scopedTerm boundNames' @@ -599,7 +622,6 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr liftTermElabM matchersM? if let some ms := matchers? then trace[notation3] "Matcher creation succeeded; assembling delaborator" - let delabName := name ++ `delab let matcher ← ms.foldrM (fun m t => `($(m.2) >=> $t)) (← `(pure)) trace[notation3] "matcher:{indentD matcher}" let mut result ← `(withHeadRefIfTagAppFns `($pat)) @@ -612,16 +634,22 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr `(let $id := MatchState.getFoldArray s $(quote name); $result) if hasBindersItem then result ← `(`(extBinders| $$(MatchState.getBinders s)*) >>= fun binders => $result) - elabCommand <| ← `(command| - /-- Pretty printer defined by `notation3` command. -/ - def $(Lean.mkIdent delabName) : Delab := whenPPOption getPPNotation <| - getExpr >>= fun e => $matcher MatchState.empty >>= fun s => $result) - trace[notation3] "Defined delaborator {currNamespace ++ delabName}" - let delabKeys := ms.foldr (·.1 ++ ·) [] - trace[notation3] "Adding `delab` attribute for keys {delabKeys}" + let delabKeys : List DelabKey := ms.foldr (·.1 ++ ·) [] for key in delabKeys do - elabCommand <| - ← `(command| attribute [$attrKind delab $(mkIdent key)] $(Lean.mkIdent delabName)) + trace[notation3] "Creating delaborator for key {repr key}" + let delabName := name ++ Name.mkSimple s!"delab_{key.key}" + let bodyCore ← `(getExpr >>= fun e => $matcher MatchState.empty >>= fun s => $result) + let body ← + match key with + | .app _ arity => ``(withOverApp $(quote arity) $bodyCore) + | _ => pure bodyCore + elabCommand <| ← `( + /-- Pretty printer defined by `notation3` command. -/ + def $(Lean.mkIdent delabName) : Delab := + whenPPOption getPPNotation <| whenNotPPOption getPPExplicit <| $body + -- Avoid scope issues by adding attribute afterwards. + attribute [$attrKind delab $(mkIdent key.key)] $(Lean.mkIdent delabName)) + trace[notation3] "Defined delaborator {currNamespace ++ delabName}" else logWarning s!"\ Was not able to generate a pretty printer for this notation. \ diff --git a/MathlibTest/notation3.lean b/MathlibTest/notation3.lean index 9b3fc8d5f1f25..eb3c3f1a020b3 100644 --- a/MathlibTest/notation3.lean +++ b/MathlibTest/notation3.lean @@ -89,9 +89,7 @@ notation3 "∃' " (...) ", " r:(scoped p => Exists p) => r def func (x : α) : α := x notation3 "func! " (...) ", " r:(scoped p => func p) => r --- Make sure it handles additional arguments. Should not consume `(· * 2)`. --- Note: right now this causes the notation to not pretty print at all. -/-- info: func (fun x ↦ x) fun x ↦ x * 2 : ℕ → ℕ -/ +/-- info: (func! (x : ℕ → ℕ), x) fun x ↦ x * 2 : ℕ → ℕ -/ #guard_msgs in #check (func! (x : Nat → Nat), x) (· * 2) structure MyUnit where @@ -236,8 +234,8 @@ info: [notation3] syntax declaration has name Test.termδNat (matchExpr✝ (Expr.isConstOf✝ · `Nat))) pure✝ >=> pure✝ -[notation3] Defined delaborator Test.termδNat.delab -[notation3] Adding `delab` attribute for keys [app.Inhabited.default] +[notation3] Creating delaborator for key Mathlib.Notation3.DelabKey.app (some `Inhabited.default) 2 +[notation3] Defined delaborator Test.termδNat.«delab_app.Inhabited.default» -/ #guard_msgs in set_option trace.notation3 true in From e61a8cf9c29f86813ea790e19988bf86a7f67463 Mon Sep 17 00:00:00 2001 From: damiano Date: Thu, 30 Jan 2025 11:04:55 +0000 Subject: [PATCH 669/681] feat: add author to maintainer merge message (#21254) --- .github/workflows/maintainer_merge.yml | 4 +++- scripts/maintainer_merge_message.sh | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maintainer_merge.yml b/.github/workflows/maintainer_merge.yml index 8be16fcfc4ed6..c998417a00a9d 100644 --- a/.github/workflows/maintainer_merge.yml +++ b/.github/workflows/maintainer_merge.yml @@ -19,6 +19,7 @@ jobs: # both set simultaneously: depending on the event that triggers the PR, usually only one is set env: AUTHOR: ${{ github.event.comment.user.login }}${{ github.event.review.user.login }} + PR_AUTHOR: ${{ github.event.issue.user.login }} PR_NUMBER: ${{ github.event.issue.number }}${{ github.event.pull_request.number }} COMMENT_EVENT: ${{ github.event.comment.body }} COMMENT_REVIEW: ${{ github.event.review.body }} @@ -32,6 +33,7 @@ jobs: - name: Find maintainer merge/delegate id: merge_or_delegate run: | + echo "PR author: ${PR_AUTHOR}" COMMENT="${COMMENT_EVENT}${COMMENT_REVIEW}" # we strip `\r` since line endings from GitHub contain this character @@ -81,7 +83,7 @@ jobs: echo "" message="$( - ./scripts/maintainer_merge_message.sh "${AUTHOR}" "${{ steps.merge_or_delegate.outputs.mOrD }}" "${EVENT_NAME}" "${PR_NUMBER}" "${PR_URL}" "${PR_TITLE_ISSUE}${PR_TITLE_PR}" "${COMMENT_EVENT}${COMMENT_REVIEW}" + ./scripts/maintainer_merge_message.sh "${AUTHOR}" "${{ steps.merge_or_delegate.outputs.mOrD }}" "${EVENT_NAME}" "${PR_NUMBER}" "${PR_URL}" "${PR_TITLE_ISSUE}${PR_TITLE_PR}" "${COMMENT_EVENT}${COMMENT_REVIEW}" "${PR_AUTHOR}" )" printf 'title<&2 echo "EVENT_NAME: '${EVENT_NAME}'" >&2 printf 'COMMENT\n%s\nEND COMMENT\n' "${PR_COMMENT}" -printf '%s requested a maintainer **%s** from %s on PR [#%s](%s):\n' "${AUTHOR}" "${M_or_D/$'?'/}" "${SOURCE}" "${PR}" "${URL}" +printf '%s requested a maintainer **%s** from %s on PR [#%s](%s) by %s:\n' "${AUTHOR}" "${M_or_D/$'?'/}" "${SOURCE}" "${PR}" "${URL}" "${PR_AUTHOR}" # if `maintainer merge/delegate` is followed by `?`, then print a `spoiler` with the full comment if [ ${M_or_D: -1} == $'?' ] then From b848c8d0c15bae84d026e1c3aa1f89bb78f87d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 30 Jan 2025 12:07:08 +0000 Subject: [PATCH 670/681] chore(Variance): golf API (#20814) --- .../Function/L1Space/Integrable.lean | 7 ++ Mathlib/Probability/Moments/Basic.lean | 4 +- Mathlib/Probability/Variance.lean | 97 +++++++++---------- 3 files changed, 55 insertions(+), 53 deletions(-) diff --git a/Mathlib/MeasureTheory/Function/L1Space/Integrable.lean b/Mathlib/MeasureTheory/Function/L1Space/Integrable.lean index 37cfdc0b9cc29..bae182dc73538 100644 --- a/Mathlib/MeasureTheory/Function/L1Space/Integrable.lean +++ b/Mathlib/MeasureTheory/Function/L1Space/Integrable.lean @@ -134,6 +134,13 @@ theorem Memℒp.integrable_norm_rpow' [IsFiniteMeasure μ] {f : α → β} {p : · simp [h_top, integrable_const] exact hf.integrable_norm_rpow h_zero h_top +lemma Memℒp.integrable_norm_pow {f : α → β} {p : ℕ} (hf : Memℒp f p μ) (hp : p ≠ 0) : + Integrable (fun x : α => ‖f x‖ ^ p) μ := by + simpa using hf.integrable_norm_rpow (mod_cast hp) (by simp) + +lemma Memℒp.integrable_norm_pow' [IsFiniteMeasure μ] {f : α → β} {p : ℕ} (hf : Memℒp f p μ) : + Integrable (fun x : α => ‖f x‖ ^ p) μ := by simpa using hf.integrable_norm_rpow' + lemma integrable_norm_rpow_iff {f : α → β} {p : ℝ≥0∞} (hf : AEStronglyMeasurable f μ) (p_zero : p ≠ 0) (p_top : p ≠ ∞) : Integrable (fun x : α => ‖f x‖ ^ p.toReal) μ ↔ Memℒp f p μ := by diff --git a/Mathlib/Probability/Moments/Basic.lean b/Mathlib/Probability/Moments/Basic.lean index edcfe1a187ce9..77fdebb9480ab 100644 --- a/Mathlib/Probability/Moments/Basic.lean +++ b/Mathlib/Probability/Moments/Basic.lean @@ -91,8 +91,8 @@ theorem centralMoment_one [IsZeroOrProbabilityMeasure μ] : centralMoment X 1 μ fun_prop rw [integral_undef this] -theorem centralMoment_two_eq_variance [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : - centralMoment X 2 μ = variance X μ := by rw [hX.variance_eq]; rfl +lemma centralMoment_two_eq_variance (hX : AEMeasurable X μ) : centralMoment X 2 μ = variance X μ := + (variance_eq_integral hX).symm section MomentGeneratingFunction diff --git a/Mathlib/Probability/Variance.lean b/Mathlib/Probability/Variance.lean index 886ceef0e7ebe..fd5c3c4d2881e 100644 --- a/Mathlib/Probability/Variance.lean +++ b/Mathlib/Probability/Variance.lean @@ -43,18 +43,19 @@ noncomputable section open scoped MeasureTheory ProbabilityTheory ENNReal NNReal namespace ProbabilityTheory +variable {Ω : Type*} {mΩ : MeasurableSpace Ω} {X : Ω → ℝ} {μ : Measure Ω} +variable (X μ) in -- Porting note: Consider if `evariance` or `eVariance` is better. Also, -- consider `eVariationOn` in `Mathlib.Analysis.BoundedVariation`. /-- The `ℝ≥0∞`-valued variance of a real-valued random variable defined as the Lebesgue integral of -`(X - 𝔼[X])^2`. -/ -def evariance {Ω : Type*} {_ : MeasurableSpace Ω} (X : Ω → ℝ) (μ : Measure Ω) : ℝ≥0∞ := - ∫⁻ ω, ‖X ω - μ[X]‖ₑ ^ 2 ∂μ +`‖X - 𝔼[X]‖^2`. -/ +def evariance : ℝ≥0∞ := ∫⁻ ω, ‖X ω - μ[X]‖ₑ ^ 2 ∂μ +variable (X μ) in /-- The `ℝ`-valued variance of a real-valued random variable defined by applying `ENNReal.toReal` to `evariance`. -/ -def variance {Ω : Type*} {_ : MeasurableSpace Ω} (X : Ω → ℝ) (μ : Measure Ω) : ℝ := - (evariance X μ).toReal +def variance : ℝ := (evariance X μ).toReal /-- The `ℝ≥0∞`-valued variance of the real-valued random variable `X` according to the measure `μ`. @@ -77,10 +78,7 @@ scoped notation "Var[" X " ; " μ "]" => ProbabilityTheory.variance X μ It is set to `0` if `X` has infinite variance. -/ scoped notation "Var[" X "]" => Var[X ; MeasureTheory.MeasureSpace.volume] -variable {Ω : Type*} {m : MeasurableSpace Ω} {X : Ω → ℝ} {μ : Measure Ω} - -theorem _root_.MeasureTheory.Memℒp.evariance_lt_top [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : - evariance X μ < ∞ := by +theorem evariance_lt_top [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : evariance X μ < ∞ := by have := ENNReal.pow_lt_top (hX.sub <| memℒp_const <| μ[X]).2 2 rw [eLpNorm_eq_lintegral_rpow_enorm two_ne_zero ENNReal.two_ne_top, ← ENNReal.rpow_two] at this simp only [ENNReal.toReal_ofNat, Pi.sub_apply, ENNReal.one_toReal, one_div] at this @@ -88,6 +86,9 @@ theorem _root_.MeasureTheory.Memℒp.evariance_lt_top [IsFiniteMeasure μ] (hX : simp_rw [ENNReal.rpow_two] at this exact this +lemma evariance_ne_top [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : evariance X μ ≠ ∞ := + (evariance_lt_top hX).ne + theorem evariance_eq_top [IsFiniteMeasure μ] (hXm : AEStronglyMeasurable X μ) (hX : ¬Memℒp X 2 μ) : evariance X μ = ∞ := by by_contra h @@ -103,55 +104,48 @@ theorem evariance_eq_top [IsFiniteMeasure μ] (hXm : AEStronglyMeasurable X μ) rw [Pi.add_apply, sub_add_cancel] theorem evariance_lt_top_iff_memℒp [IsFiniteMeasure μ] (hX : AEStronglyMeasurable X μ) : - evariance X μ < ∞ ↔ Memℒp X 2 μ := by - refine ⟨?_, MeasureTheory.Memℒp.evariance_lt_top⟩ - contrapose - rw [not_lt, top_le_iff] - exact evariance_eq_top hX - -theorem _root_.MeasureTheory.Memℒp.ofReal_variance_eq [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : - ENNReal.ofReal (variance X μ) = evariance X μ := by + evariance X μ < ∞ ↔ Memℒp X 2 μ where + mp := by contrapose!; rw [top_le_iff]; exact evariance_eq_top hX + mpr := evariance_lt_top + +lemma evariance_eq_top_iff [IsFiniteMeasure μ] (hX : AEStronglyMeasurable X μ) : + evariance X μ = ∞ ↔ ¬ Memℒp X 2 μ := by simp [← evariance_lt_top_iff_memℒp hX] + +theorem ofReal_variance [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : + .ofReal (variance X μ) = evariance X μ := by rw [variance, ENNReal.ofReal_toReal] - exact hX.evariance_lt_top.ne + exact evariance_ne_top hX + +protected alias _root_.MeasureTheory.Memℒp.evariance_lt_top := evariance_lt_top +protected alias _root_.MeasureTheory.Memℒp.evariance_ne_top := evariance_ne_top +protected alias _root_.MeasureTheory.Memℒp.ofReal_variance_eq := ofReal_variance -theorem evariance_eq_lintegral_ofReal (X : Ω → ℝ) (μ : Measure Ω) : +variable (X μ) in +theorem evariance_eq_lintegral_ofReal : evariance X μ = ∫⁻ ω, ENNReal.ofReal ((X ω - μ[X]) ^ 2) ∂μ := by - rw [evariance] - congr with ω - rw [pow_two, ← enorm_mul, ← pow_two, Real.enorm_of_nonneg (sq_nonneg _)] - -theorem _root_.MeasureTheory.Memℒp.variance_eq_of_integral_eq_zero (hX : Memℒp X 2 μ) - (hXint : μ[X] = 0) : variance X μ = μ[X ^ (2 : Nat)] := by - rw [variance, evariance_eq_lintegral_ofReal, ← ofReal_integral_eq_lintegral_ofReal, - ENNReal.toReal_ofReal (by positivity)] <;> - simp_rw [hXint, sub_zero] - · rfl - · convert hX.integrable_norm_rpow two_ne_zero ENNReal.two_ne_top with ω - simp only [Pi.sub_apply, Real.norm_eq_abs, ENNReal.toReal_ofNat, ENNReal.one_toReal, - Real.rpow_two, sq_abs, abs_pow] - · exact ae_of_all _ fun ω => pow_two_nonneg _ - -theorem _root_.MeasureTheory.Memℒp.variance_eq [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : - variance X μ = μ[(X - fun _ => μ[X] :) ^ (2 : Nat)] := by - rw [variance, evariance_eq_lintegral_ofReal, ← ofReal_integral_eq_lintegral_ofReal, - ENNReal.toReal_ofReal (by positivity)] - · rfl - · convert (hX.sub <| memℒp_const μ[X]).integrable_norm_rpow two_ne_zero ENNReal.two_ne_top - with ω - simp only [Pi.sub_apply, Real.norm_eq_abs, ENNReal.toReal_ofNat, ENNReal.one_toReal, - Real.rpow_two, sq_abs, abs_pow] - · exact ae_of_all _ fun ω => pow_two_nonneg _ + simp [evariance, ← enorm_pow, Real.enorm_of_nonneg (sq_nonneg _)] + +lemma variance_eq_integral (hX : AEMeasurable X μ) : Var[X ; μ] = ∫ ω, (X ω - μ[X]) ^ 2 ∂μ := by + simp [variance, evariance, toReal_enorm, ← integral_toReal ((hX.sub_const _).enorm.pow_const _) <| + .of_forall fun _ ↦ ENNReal.pow_lt_top enorm_lt_top _] + +lemma variance_of_integral_eq_zero (hX : AEMeasurable X μ) (hXint : μ[X] = 0) : + variance X μ = ∫ ω, X ω ^ 2 ∂μ := by + simp [variance_eq_integral hX, hXint] + +@[deprecated (since := "2025-01-23")] +alias _root_.MeasureTheory.Memℒp.variance_eq := variance_eq_integral + +@[deprecated (since := "2025-01-23")] +alias _root_.MeasureTheory.Memℒp.variance_eq_of_integral_eq_zero := variance_of_integral_eq_zero @[simp] theorem evariance_zero : evariance 0 μ = 0 := by simp [evariance] theorem evariance_eq_zero_iff (hX : AEMeasurable X μ) : evariance X μ = 0 ↔ X =ᵐ[μ] fun _ => μ[X] := by - rw [evariance, lintegral_eq_zero_iff'] - constructor <;> intro hX <;> filter_upwards [hX] with ω hω - · simpa [sub_eq_zero] using hω - · simp [hω] - · exact (hX.sub_const _).enorm.pow_const _ -- TODO `measurability` and `fun_prop` fail + simp [evariance, lintegral_eq_zero_iff' ((hX.sub_const _).enorm.pow_const _), EventuallyEq, + sub_eq_zero] theorem evariance_mul (c : ℝ) (X : Ω → ℝ) (μ : Measure Ω) : evariance (fun ω => c * X ω) μ = ENNReal.ofReal (c ^ 2) * evariance X μ := by @@ -184,7 +178,8 @@ theorem variance_smul' {A : Type*} [CommSemiring A] [Algebra A ℝ] (c : A) (X : theorem variance_def' [IsProbabilityMeasure μ] {X : Ω → ℝ} (hX : Memℒp X 2 μ) : variance X μ = μ[X ^ 2] - μ[X] ^ 2 := by - rw [hX.variance_eq, sub_sq', integral_sub', integral_add']; rotate_left + simp only [variance_eq_integral hX.aestronglyMeasurable.aemeasurable, sub_sq'] + rw [integral_sub, integral_add]; rotate_left · exact hX.integrable_sq · apply integrable_const · apply hX.integrable_sq.add @@ -218,7 +213,7 @@ theorem variance_le_expectation_sq [IsProbabilityMeasure μ] {X : Ω → ℝ} theorem evariance_def' [IsProbabilityMeasure μ] {X : Ω → ℝ} (hX : AEStronglyMeasurable X μ) : evariance X μ = (∫⁻ ω, ‖X ω‖ₑ ^ 2 ∂μ) - ENNReal.ofReal (μ[X] ^ 2) := by by_cases hℒ : Memℒp X 2 μ - · rw [← hℒ.ofReal_variance_eq, variance_def' hℒ, ENNReal.ofReal_sub _ (sq_nonneg _)] + · rw [← ofReal_variance hℒ, variance_def' hℒ, ENNReal.ofReal_sub _ (sq_nonneg _)] congr simp_rw [← enorm_pow, enorm] rw [lintegral_coe_eq_integral] From f17018b0143d62d3cb63b27ba75fa3085be4d1a7 Mon Sep 17 00:00:00 2001 From: Antoine Chambert-Loir Date: Thu, 30 Jan 2025 12:44:40 +0000 Subject: [PATCH 671/681] feat(Data/Finsupp/MonomialOrder) : lexicographic order on `Unique` (#20699) Two lemmas for lexicographic order on a`Unique` type are added. --- Mathlib/Data/Finsupp/Lex.lean | 17 +++++++++++++++++ Mathlib/Data/Finsupp/MonomialOrder.lean | 18 ++++++++---------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Mathlib/Data/Finsupp/Lex.lean b/Mathlib/Data/Finsupp/Lex.lean index d18f3ee749ed4..aac25e9584c7e 100644 --- a/Mathlib/Data/Finsupp/Lex.lean +++ b/Mathlib/Data/Finsupp/Lex.lean @@ -46,6 +46,16 @@ theorem lex_eq_invImage_dfinsupp_lex (r : α → α → Prop) (s : N → N → P instance [LT α] [LT N] : LT (Lex (α →₀ N)) := ⟨fun f g ↦ Finsupp.Lex (· < ·) (· < ·) (ofLex f) (ofLex g)⟩ +theorem lex_lt_iff [LT α] [LT N] {a b : Lex (α →₀ N)} : + a < b ↔ ∃ i, (∀ j, j < i → ofLex a j = ofLex b j) ∧ ofLex a i < ofLex b i := + Finsupp.lex_def + +theorem lex_lt_iff_of_unique [Preorder α] [LT N] [Unique α] {a b : Lex (α →₀ N)} : + a < b ↔ ofLex a default < ofLex b default := by + simp only [lex_lt_iff, Unique.exists_iff, and_iff_right_iff_imp] + refine fun _ j hj ↦ False.elim (lt_irrefl j ?_) + simpa only [Unique.uniq] using hj + theorem lex_lt_of_lt_of_preorder [Preorder N] (r) [IsStrictOrder α r] {x y : α →₀ N} (hlt : x < y) : ∃ i, (∀ j, r j i → x j ≤ y j ∧ y j ≤ x j) ∧ x i < y i := DFinsupp.lex_lt_of_lt_of_preorder r (id hlt : x.toDFinsupp < y.toDFinsupp) @@ -104,6 +114,13 @@ theorem lt_of_forall_lt_of_lt (a b : Lex (α →₀ N)) (i : α) : (∀ j < i, ofLex a j = ofLex b j) → ofLex a i < ofLex b i → a < b := fun h1 h2 ↦ ⟨i, h1, h2⟩ +theorem lex_le_iff_of_unique [Unique α] {a b : Lex (α →₀ N)} : + a ≤ b ↔ ofLex a default ≤ ofLex b default := by + simp only [le_iff_eq_or_lt, EmbeddingLike.apply_eq_iff_eq] + apply or_congr _ lex_lt_iff_of_unique + conv_lhs => rw [← toLex_ofLex a, ← toLex_ofLex b, toLex_inj] + simp only [Finsupp.ext_iff, Unique.forall_iff] + end NHasZero section Covariants diff --git a/Mathlib/Data/Finsupp/MonomialOrder.lean b/Mathlib/Data/Finsupp/MonomialOrder.lean index 788df94797c35..963c37cc62c18 100644 --- a/Mathlib/Data/Finsupp/MonomialOrder.lean +++ b/Mathlib/Data/Finsupp/MonomialOrder.lean @@ -113,16 +113,6 @@ noncomputable instance {α N : Type*} [LinearOrder α] [OrderedCancelAddCommMono le_of_add_le_add_left a b c h := by simpa only [add_le_add_iff_left] using h add_le_add_left a b h c := by simpa only [add_le_add_iff_left] using h -theorem Finsupp.lex_lt_iff {α N : Type*} [LinearOrder α] [LinearOrder N] [Zero N] - {a b : Lex (α →₀ N)} : - a < b ↔ ∃ i, (∀ j, j< i → ofLex a j = ofLex b j) ∧ ofLex a i < ofLex b i := - Finsupp.lex_def - -theorem Finsupp.lex_le_iff {α N : Type*} [LinearOrder α] [LinearOrder N] [Zero N] - {a b : Lex (α →₀ N)} : - a ≤ b ↔ a = b ∨ ∃ i, (∀ j, j< i → ofLex a j = ofLex b j) ∧ ofLex a i < ofLex b i := by - rw [le_iff_eq_or_lt, Finsupp.lex_lt_iff] - /-- for the lexicographic ordering, X 0 * X 1 < X 0 ^ 2 -/ example : toLex (Finsupp.single 0 2) > toLex (Finsupp.single 0 1 + Finsupp.single 1 1) := by use 0; simp @@ -152,4 +142,12 @@ theorem MonomialOrder.lex_le_iff [WellFoundedGT σ] {c d : σ →₀ ℕ} : theorem MonomialOrder.lex_lt_iff [WellFoundedGT σ] {c d : σ →₀ ℕ} : c ≺[lex] d ↔ toLex c < toLex d := Iff.rfl +theorem MonomialOrder.lex_lt_iff_of_unique [Unique σ] {c d : σ →₀ ℕ} : + c ≺[lex] d ↔ c default < d default := by + simp only [MonomialOrder.lex_lt_iff, Finsupp.lex_lt_iff_of_unique, ofLex_toLex] + +theorem MonomialOrder.lex_le_iff_of_unique [Unique σ] {c d : σ →₀ ℕ} : + c ≼[lex] d ↔ c default ≤ d default := by + simp only [MonomialOrder.lex_le_iff, Finsupp.lex_le_iff_of_unique, ofLex_toLex] + end Lex From 6f5142e8e3ad13beb41f66635c1a4f1405335fcd Mon Sep 17 00:00:00 2001 From: Christian Merten Date: Thu, 30 Jan 2025 13:06:09 +0000 Subject: [PATCH 672/681] feat(RingTheory/StandardSmooth): naive cotangent complex of a submersive presentation (#19748) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We show that `H¹(L_{S/R})` is trivial if `S` is `R`-standard smooth and that `Ω[S⁄R]` is free of rank `n` if `S` is `R`-standard smooth of relative dimension `n`. In particular this shows that standard smooth implies smooth and that standard smooth of relative dimension zero implies smooth and unramified. Co-authored-by: Christian Merten <136261474+chrisflav@users.noreply.github.com> --- Mathlib.lean | 1 + .../Smooth/StandardSmoothCotangent.lean | 276 ++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 Mathlib/RingTheory/Smooth/StandardSmoothCotangent.lean diff --git a/Mathlib.lean b/Mathlib.lean index a16a9e698db7c..095caa64e9c52 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4777,6 +4777,7 @@ import Mathlib.RingTheory.Smooth.Local import Mathlib.RingTheory.Smooth.Locus import Mathlib.RingTheory.Smooth.Pi import Mathlib.RingTheory.Smooth.StandardSmooth +import Mathlib.RingTheory.Smooth.StandardSmoothCotangent import Mathlib.RingTheory.Spectrum.Maximal.Basic import Mathlib.RingTheory.Spectrum.Maximal.Defs import Mathlib.RingTheory.Spectrum.Maximal.Localization diff --git a/Mathlib/RingTheory/Smooth/StandardSmoothCotangent.lean b/Mathlib/RingTheory/Smooth/StandardSmoothCotangent.lean new file mode 100644 index 0000000000000..9b7641dcf5cd6 --- /dev/null +++ b/Mathlib/RingTheory/Smooth/StandardSmoothCotangent.lean @@ -0,0 +1,276 @@ +/- +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.LinearAlgebra.Basis.Exact +import Mathlib.RingTheory.Kaehler.CotangentComplex +import Mathlib.RingTheory.Smooth.StandardSmooth +import Mathlib.RingTheory.Smooth.Kaehler +import Mathlib.RingTheory.Etale.Basic + +/-! +# Cotangent complex of a submersive presentation + +Let `P` be a submersive presentation of `S` as an `R`-algebra and +denote by `I` the kernel `R[X] → S`. We show + +- `SubmersivePresentation.free_cotangent`: `I ⧸ I ^ 2` is `S`-free on the classes of `P.relation i`. +- `SubmersivePresentation.subsingleton_h1Cotangent`: `H¹(L_{S/R}) = 0`. +- `SubmersivePresentation.free_kaehlerDifferential`: `Ω[S⁄R]` is `S`-free on the images of `dxᵢ` + where `i ∉ Set.range P.map`. +- `SubmersivePresentation.rank_kaehlerDifferential`: If `S` is non-trivial, the rank of + `Ω[S⁄R]` is the dimension of `P`. + +We also provide the corresponding instances for standard smooth algebras as corollaries. + +We keep the notation `I = ker(R[X] → S)` in all docstrings of this file. +-/ + +universe u + +namespace Algebra + +section + +variable {R S : Type*} [CommRing R] [CommRing S] [Algebra R S] + +open Extension MvPolynomial + +namespace PreSubmersivePresentation + +/-- +Given a pre-submersive presentation, this is the composition +`I ⧸ I ^ 2 → ⊕ S dxᵢ → ⊕ S dxᵢ` where the second direct sum runs over +all `i : P.rels` induced by the injection `P.map : P.rels → P.vars`. + +If `P` is submersive, this is an isomorphism. See `SubmersivePresentation.cotangentEquiv`. +-/ +noncomputable def cotangentComplexAux (P : PreSubmersivePresentation R S) : + P.toExtension.Cotangent →ₗ[S] P.rels → S := + Finsupp.linearEquivFunOnFinite S S P.rels ∘ₗ Finsupp.lcomapDomain _ P.map_inj ∘ₗ + P.cotangentSpaceBasis.repr.toLinearMap ∘ₗ P.toExtension.cotangentComplex + +lemma cotangentComplexAux_apply (P : PreSubmersivePresentation R S) (x : P.ker) (i : P.rels) : + P.cotangentComplexAux (Cotangent.mk x) i = (aeval P.val) (pderiv (P.map i) x.val) := by + dsimp only [cotangentComplexAux, LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, + cotangentComplex_mk] + simp only [Generators.toExtension_Ring, Finsupp.lcomapDomain_apply, + Finsupp.linearEquivFunOnFinite_apply, Finsupp.comapDomain_apply, + Generators.cotangentSpaceBasis_repr_tmul, one_mul] + +lemma cotangentComplexAux_zero_iff {P : PreSubmersivePresentation R S} (x : P.ker) : + P.cotangentComplexAux (Cotangent.mk x) = 0 ↔ + ∀ i : P.rels, (aeval P.val) (pderiv (P.map i) x.val) = 0 := by + rw [funext_iff] + simp_rw [cotangentComplexAux_apply, Pi.zero_apply] + +end PreSubmersivePresentation + +namespace SubmersivePresentation + +variable (P : SubmersivePresentation R S) + +lemma cotangentComplexAux_injective : Function.Injective P.cotangentComplexAux := by + rw [← LinearMap.ker_eq_bot, eq_bot_iff] + intro x hx + obtain ⟨(x : P.ker), rfl⟩ := Cotangent.mk_surjective x + rw [Submodule.mem_bot, Cotangent.mk_eq_zero_iff] + rw [LinearMap.mem_ker, P.cotangentComplexAux_zero_iff] at hx + have : x.val ∈ Ideal.span (Set.range P.relation) := by + rw [P.span_range_relation_eq_ker] + exact x.property + obtain ⟨c, hc⟩ := Finsupp.mem_ideal_span_range_iff_exists_finsupp.mp this + have heq (i : P.rels) : + aeval P.val (pderiv (P.map i) <| c.sum fun i a ↦ a * P.relation i) = 0 := by + rw [hc] + apply hx + simp only [Finsupp.sum, map_sum, Derivation.leibniz, smul_eq_mul, map_add, map_mul, + Presentation.aeval_val_relation, zero_mul, add_zero] at heq + have heq2 : ∑ i ∈ c.support, + aeval P.val (c i) • (fun j ↦ aeval P.val (pderiv (P.map j) (P.relation i))) = 0 := by + ext j + simp only [Finset.sum_apply, Pi.smul_apply, smul_eq_mul, Pi.zero_apply] + apply heq + have (i : P.rels) : aeval P.val (c i) = 0 := by + have := P.linearIndependent_aeval_val_pderiv_relation + rw [linearIndependent_iff''] at this + have := this c.support (fun i ↦ aeval P.val (c i)) + (by intro i; simp only [Finsupp.mem_support_iff, ne_eq, not_not]; intro h; simp [h]) heq2 + exact this i + show _ ∈ P.ker ^ 2 + rw [← hc] + apply Ideal.sum_mem + intro i hi + rw [pow_two] + apply Ideal.mul_mem_mul + · rw [P.ker_eq_ker_aeval_val] + simpa using this i + · exact P.relation_mem_ker i + +lemma cotangentComplexAux_surjective : Function.Surjective P.cotangentComplexAux := by + rw [← LinearMap.range_eq_top, _root_.eq_top_iff, ← P.basisDeriv.span_eq, Submodule.span_le] + rintro - ⟨i, rfl⟩ + use Cotangent.mk ⟨P.relation i, P.relation_mem_ker i⟩ + ext j + rw [P.cotangentComplexAux_apply] + simp + +/-- The isomorphism of `S`-modules between `I ⧸ I ^ 2` and `P.rels → S` given +by `P.relation i ↦ ∂ⱼ (P.relation i)`. -/ +@[simps! apply] +noncomputable def cotangentEquiv : P.toExtension.Cotangent ≃ₗ[S] P.rels → S := + LinearEquiv.ofBijective _ ⟨P.cotangentComplexAux_injective, P.cotangentComplexAux_surjective⟩ + +lemma cotangentComplex_injective : Function.Injective P.toExtension.cotangentComplex := by + have := P.cotangentComplexAux_injective + simp only [PreSubmersivePresentation.cotangentComplexAux, LinearMap.coe_comp, + LinearEquiv.coe_coe] at this + exact Function.Injective.of_comp (Function.Injective.of_comp <| Function.Injective.of_comp this) + +/-- If `P` is a submersive presentation, `H¹` of the associated cotangent complex vanishes. -/ +instance subsingleton_h1Cotangent : Subsingleton P.toExtension.H1Cotangent := by + rw [Algebra.Extension.subsingleton_h1Cotangent] + exact cotangentComplex_injective P + +/-- The classes of `P.relation i` form a basis of `I ⧸ I ^ 2`. -/ +@[stacks 00T7 "(3)"] +noncomputable def basisCotangent : Basis P.rels S P.toExtension.Cotangent := + ⟨cotangentEquiv P ≪≫ₗ (Finsupp.linearEquivFunOnFinite S S P.rels).symm⟩ + +@[stacks 00T7 "(3)"] +instance free_cotangent : Module.Free S P.toExtension.Cotangent := + Module.Free.of_basis P.basisCotangent + +/-- +If `P` is a submersive presentation, this is the section of the map +`I ⧸ I ^ 2 → ⊕ S dxᵢ` given by projecting to the summands indexed by `P.rels` and composing with the +inverse of `P.cotangentEquiv`. + +By `SubmersivePresentation.sectionCotangent_comp` this is indeed a section. +-/ +noncomputable def sectionCotangent : P.toExtension.CotangentSpace →ₗ[S] P.toExtension.Cotangent := + (cotangentEquiv P).symm ∘ₗ (Finsupp.linearEquivFunOnFinite S S P.rels).toLinearMap ∘ₗ + Finsupp.lcomapDomain _ P.map_inj ∘ₗ P.cotangentSpaceBasis.repr.toLinearMap + +lemma sectionCotangent_eq_iff (x : P.toExtension.CotangentSpace) (y : P.toExtension.Cotangent) : + sectionCotangent P x = y ↔ + ∀ i : P.rels, P.cotangentSpaceBasis.repr x (P.map i) = (P.cotangentComplexAux y) i := by + simp only [sectionCotangent, LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply] + rw [← (cotangentEquiv P).injective.eq_iff, funext_iff, LinearEquiv.apply_symm_apply] + simp + +lemma sectionCotangent_comp : + sectionCotangent P ∘ₗ P.toExtension.cotangentComplex = LinearMap.id := by + ext : 1 + simp only [LinearMap.coe_comp, Function.comp_apply, LinearMap.id_coe, id_eq] + rw [sectionCotangent_eq_iff] + intro i + rfl + +lemma sectionCotangent_zero_of_not_mem_range (i : P.vars) (hi : i ∉ Set.range P.map) : + (sectionCotangent P) (P.cotangentSpaceBasis i) = 0 := by + classical + contrapose hi + rw [sectionCotangent_eq_iff] at hi + simp only [Basis.repr_self, map_zero, Pi.zero_apply, not_forall, + Finsupp.single_apply, ite_eq_right_iff, Classical.not_imp, exists_and_right] at hi + obtain ⟨j, hij, _⟩ := hi + simp only [Set.mem_range, not_exists, not_forall, not_not] + use j + exact hij.symm + +/-- +Given a submersive presentation of `S` as `R`-algebra, any indexing type `κ` complementary to +the `P.rels` in `P.vars` indexes a basis of `Ω[S⁄R]`. +See `SubmersivePresentation.basisKaehler` for the special case `κ = (Set.range P.map)ᶜ`. +-/ +noncomputable def basisKaehlerOfIsCompl {κ : Type*} {f : κ → P.vars} + (hf : Function.Injective f) (hcompl : IsCompl (Set.range f) (Set.range P.map)) : + Basis κ S (Ω[S⁄R]) := by + apply P.cotangentSpaceBasis.ofSplitExact (sectionCotangent_comp P) + Extension.exact_cotangentComplex_toKaehler Extension.toKaehler_surjective hf (b := P.map) + · intro i + apply sectionCotangent_zero_of_not_mem_range _ _ + simp [← hcompl.compl_eq] + · simp only [sectionCotangent, LinearMap.coe_comp, Function.comp_assoc, LinearEquiv.coe_coe] + apply LinearIndependent.map' _ _ P.cotangentEquiv.symm.ker + convert (Pi.basisFun S P.rels).linearIndependent + classical + ext i j + simp only [Function.comp_apply, Basis.repr_self, Finsupp.linearEquivFunOnFinite_apply, + Pi.basisFun_apply, Finsupp.single_apply_left P.map_inj, Finsupp.single_eq_pi_single] + simp [Finsupp.single_eq_pi_single] + · exact hcompl.2 + +/-- Given a submersive presentation of `S` as `R`-algebra, the images of `dxᵢ` +for `i` in the complement of `P.rels` in `P.vars` form a basis of `Ω[S⁄R]`. -/ +@[stacks 00T7 "(2)"] +noncomputable def basisKaehler : + Basis ((Set.range P.map)ᶜ : Set _) S (Ω[S⁄R]) := + P.basisKaehlerOfIsCompl Subtype.val_injective <| by + rw [Subtype.range_coe_subtype] + exact IsCompl.symm isCompl_compl + +/-- If `P` is a submersive presentation of `S` as an `R`-algebra, `Ω[S⁄R]` is free. -/ +@[stacks 00T7 "(2)"] +theorem free_kaehlerDifferential (P : SubmersivePresentation R S) : + Module.Free S (Ω[S⁄R]) := + Module.Free.of_basis P.basisKaehler + +attribute [local instance] Fintype.ofFinite in +/-- If `P` is a submersive presentation of `S` as an `R`-algebra and `S` is nontrivial, +`Ω[S⁄R]` is free of rank the dimension of `P`, i.e. the number of generators minus the number +of relations. -/ +theorem rank_kaehlerDifferential [Nontrivial S] + (P : SubmersivePresentation R S) : Module.rank S (Ω[S⁄R]) = P.dimension := by + simp only [rank_eq_card_basis P.basisKaehler, Nat.cast_inj, Fintype.card_compl_set, + Presentation.dimension, Nat.card_eq_fintype_card, Set.card_range_of_injective P.map_inj] + +end SubmersivePresentation + +/-- If `S` is `R`-standard smooth, `Ω[S⁄R]` is a free `S`-module. -/ +instance IsStandardSmooth.free_kaehlerDifferential [IsStandardSmooth R S] : + Module.Free S (Ω[S⁄R]) := by + obtain ⟨⟨P⟩⟩ := ‹IsStandardSmooth R S› + exact P.free_kaehlerDifferential + +instance IsStandardSmooth.subsingleton_h1Cotangent [IsStandardSmooth R S] : + Subsingleton (H1Cotangent R S) := by + obtain ⟨⟨P⟩⟩ := ‹IsStandardSmooth R S› + exact P.equivH1Cotangent.symm.toEquiv.subsingleton + +/-- If `S` is non-trivial and `R`-standard smooth of relative dimension, `Ω[S⁄R]` is a free +`S`-module of rank `n`. -/ +theorem IsStandardSmoothOfRelativeDimension.rank_kaehlerDifferential [Nontrivial S] (n : ℕ) + [IsStandardSmoothOfRelativeDimension n R S] : + Module.rank S (Ω[S⁄R]) = n := by + obtain ⟨⟨P, hP⟩⟩ := ‹IsStandardSmoothOfRelativeDimension n R S› + rw [P.rank_kaehlerDifferential, hP] + +instance IsStandardSmoothOfRelationDimension.subsingleton_kaehlerDifferential + [IsStandardSmoothOfRelativeDimension 0 R S] : Subsingleton (Ω[S⁄R]) := by + cases subsingleton_or_nontrivial S + · exact Module.subsingleton S _ + haveI : IsStandardSmooth R S := IsStandardSmoothOfRelativeDimension.isStandardSmooth 0 + exact Module.subsingleton_of_rank_zero + (IsStandardSmoothOfRelativeDimension.rank_kaehlerDifferential 0) + +end + +variable {R S : Type u} [CommRing R] [CommRing S] [Algebra R S] + +instance (priority := 900) [IsStandardSmooth R S] : Smooth R S where + formallySmooth := by + rw [Algebra.FormallySmooth.iff_subsingleton_and_projective] + exact ⟨inferInstance, inferInstance⟩ + +/-- If `S` is `R`-standard smooth of relative dimension zero, it is étale. -/ +instance (priority := 900) [IsStandardSmoothOfRelativeDimension 0 R S] : Etale R S where + finitePresentation := (IsStandardSmoothOfRelativeDimension.isStandardSmooth 0).finitePresentation + formallyEtale := + have : IsStandardSmooth R S := IsStandardSmoothOfRelativeDimension.isStandardSmooth 0 + have : FormallyUnramified R S := ⟨inferInstance⟩ + Algebra.FormallyEtale.of_unramified_and_smooth + +end Algebra From 410dd1f6872c06759a7f51653be8e52d97dd8d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 30 Jan 2025 13:06:10 +0000 Subject: [PATCH 673/681] doc(Order/WellFounded): minor docstring improvements (#20776) We fix two typos and add two missing deprecation messages. --- Mathlib/Order/WellFounded.lean | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index 4123fe4543d71..3b818b1f54b98 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -11,7 +11,7 @@ import Mathlib.Order.Bounds.Defs A relation is well-founded if it can be used for induction: for each `x`, `(∀ y, r y x → P y) → P x` implies `P x`. Well-founded relations can be used for induction and recursion, including -construction of fixed points in the space of dependent functions `Π x : α , β x`. +construction of fixed points in the space of dependent functions `Π x : α, β x`. The predicate `WellFounded` is defined in the core library. In this file we prove some extra lemmas and provide a few new definitions: `WellFounded.min`, `WellFounded.sup`, and `WellFounded.succ`, @@ -55,7 +55,7 @@ theorem has_min {α} {r : α → α → Prop} (H : WellFounded r) (s : Set α) : If you're working with a nonempty linear order, consider defining a `ConditionallyCompleteLinearOrderBot` instance via -`WellFounded.conditionallyCompleteLinearOrderWithBot` and using `Inf` instead. -/ +`WellFoundedLT.conditionallyCompleteLinearOrderBot` and using `Inf` instead. -/ noncomputable def min {r : α → α → Prop} (H : WellFounded r) (s : Set α) (h : s.Nonempty) : α := Classical.choose (H.has_min s h) @@ -121,14 +121,14 @@ protected noncomputable def succ {r : α → α → Prop} (wf : WellFounded r) ( if h : ∃ y, r x y then wf.min { y | r x y } h else x set_option linter.deprecated false in -@[deprecated "No deprecation message was provided." (since := "2024-10-25")] +@[deprecated "`WellFounded.succ` is deprecated" (since := "2024-10-25")] protected theorem lt_succ {r : α → α → Prop} (wf : WellFounded r) {x : α} (h : ∃ y, r x y) : r x (wf.succ x) := by rw [WellFounded.succ, dif_pos h] apply min_mem set_option linter.deprecated false in -@[deprecated "No deprecation message was provided." (since := "2024-10-25")] +@[deprecated "`WellFounded.succ` is deprecated" (since := "2024-10-25")] protected theorem lt_succ_iff {r : α → α → Prop} [wo : IsWellOrder α r] {x : α} (h : ∃ y, r x y) (y : α) : r y (wo.wf.succ x) ↔ r y x ∨ y = x := by constructor From 5b3fe1250daaa15752d71bdbdf290b80e0098eec Mon Sep 17 00:00:00 2001 From: David Loeffler Date: Thu, 30 Jan 2025 15:01:41 +0000 Subject: [PATCH 674/681] chore(NumberTheory/LSeries): unsqueeze lots of terminal simps (#21133) --- .../NumberTheory/LSeries/AbstractFuncEq.lean | 16 +- Mathlib/NumberTheory/LSeries/Basic.lean | 62 +++--- Mathlib/NumberTheory/LSeries/Convergence.lean | 73 +++---- Mathlib/NumberTheory/LSeries/Convolution.lean | 38 ++-- Mathlib/NumberTheory/LSeries/Deriv.lean | 26 ++- Mathlib/NumberTheory/LSeries/Dirichlet.lean | 87 ++++----- .../LSeries/DirichletContinuation.lean | 24 +-- Mathlib/NumberTheory/LSeries/HurwitzZeta.lean | 6 +- .../NumberTheory/LSeries/HurwitzZetaEven.lean | 180 ++++++++---------- .../NumberTheory/LSeries/HurwitzZetaOdd.lean | 95 ++++----- .../LSeries/HurwitzZetaValues.lean | 46 ++--- Mathlib/NumberTheory/LSeries/Linearity.lean | 61 +++--- .../LSeries/MellinEqDirichlet.lean | 6 +- .../ModularForms/JacobiTheta/TwoVariable.lean | 1 + 14 files changed, 306 insertions(+), 415 deletions(-) diff --git a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean index ba2c0b35df07d..4266d87bfbdb6 100644 --- a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean +++ b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean @@ -177,12 +177,11 @@ variable (P : StrongFEPair E) /-- As `x → ∞`, `f x` decays faster than any power of `x`. -/ lemma hf_top' (r : ℝ) : P.f =O[atTop] (· ^ r) := by - simpa only [P.hf₀, sub_zero] using P.hf_top r + simpa [P.hf₀] using P.hf_top r /-- As `x → 0`, `f x` decays faster than any power of `x`. -/ lemma hf_zero' (r : ℝ) : P.f =O[𝓝[>] 0] (· ^ r) := by - have := P.hg₀ ▸ P.hf_zero r - simpa only [smul_zero, sub_zero] + simpa using (P.hg₀ ▸ P.hf_zero r :) /-! ## Main theorems on strong FE-pairs @@ -231,8 +230,7 @@ theorem functional_equation (s : ℂ) : simp_rw [P.h_feq' t ht, ← mul_smul] -- some simple `cpow` arithmetic to finish rw [cpow_neg, ofReal_cpow (le_of_lt ht)] - have : (t : ℂ) ^ (P.k : ℂ) ≠ 0 := by - simpa only [← ofReal_cpow (le_of_lt ht), ofReal_ne_zero] using (rpow_pos_of_pos ht _).ne' + have : (t : ℂ) ^ (P.k : ℂ) ≠ 0 := by simpa [← ofReal_cpow ht.le] using (rpow_pos_of_pos ht _).ne' field_simp [P.hε] end StrongFEPair @@ -397,13 +395,13 @@ 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 [hs, smul_zero] using differentiableAt_const (0 : E) + · simpa using (differentiableAt_inv hs).smul_const _ + · simp [hs] · rcases hs' with hs' | hs' · apply DifferentiableAt.smul_const apply (differentiableAt_const _).div ((differentiableAt_const _).sub (differentiable_id _)) - rwa [sub_ne_zero, ne_comm] - · simpa only [hs', smul_zero] using differentiableAt_const (0 : E) + simpa [sub_eq_zero, eq_comm] + · simp [hs'] /-- Relation between `Λ s` and the Mellin transform of `f - f₀`, where the latter is defined. -/ theorem hasMellin [CompleteSpace E] diff --git a/Mathlib/NumberTheory/LSeries/Basic.lean b/Mathlib/NumberTheory/LSeries/Basic.lean index 3f0a95887411d..4806de1b316c3 100644 --- a/Mathlib/NumberTheory/LSeries/Basic.lean +++ b/Mathlib/NumberTheory/LSeries/Basic.lean @@ -104,8 +104,8 @@ lemma pow_mul_term_eq (f : ℕ → ℂ) (s : ℂ) (n : ℕ) : lemma norm_term_eq (f : ℕ → ℂ) (s : ℂ) (n : ℕ) : ‖term f s n‖ = if n = 0 then 0 else ‖f n‖ / n ^ s.re := by rcases eq_or_ne n 0 with rfl | hn - · simp only [term_zero, norm_zero, ↓reduceIte] - · rw [if_neg hn, term_of_ne_zero hn, norm_div, norm_natCast_cpow_of_pos <| Nat.pos_of_ne_zero hn] + · simp + · simp [hn, norm_natCast_cpow_of_pos <| Nat.pos_of_ne_zero hn] lemma norm_term_le {f g : ℕ → ℂ} (s : ℂ) {n : ℕ} (h : ‖f n‖ ≤ ‖g n‖) : ‖term f s n‖ ≤ ‖term g s n‖ := by @@ -118,8 +118,8 @@ lemma norm_term_le_of_re_le_re (f : ℕ → ℂ) {s s' : ℂ} (h : s.re ≤ s'.r ‖term f s' n‖ ≤ ‖term f s n‖ := by simp only [norm_term_eq] split - next => rfl - next hn => gcongr; exact Nat.one_le_cast.mpr <| Nat.one_le_iff_ne_zero.mpr hn + · next => rfl + · next hn => gcongr; exact Nat.one_le_cast.mpr <| Nat.one_le_iff_ne_zero.mpr hn section positivity @@ -178,9 +178,9 @@ lemma LSeriesSummable.congr' {f g : ℕ → ℂ} (s : ℂ) (h : f =ᶠ[atTop] g) rw [eventuallyEq_iff_exists_mem] at h ⊢ obtain ⟨S, hS, hS'⟩ := h refine ⟨S \ {0}, diff_mem hS <| (Set.finite_singleton 0).compl_mem_cofinite, fun n hn ↦ ?_⟩ - simp only [Set.mem_diff, Set.mem_singleton_iff] at hn - simp only [term_of_ne_zero hn.2, hS' hn.1] - exact Eventually.mono this.symm fun n hn ↦ by simp only [hn, le_rfl] + rw [Set.mem_diff, Set.mem_singleton_iff] at hn + simp [hn.2, hS' hn.1] + exact this.symm.mono fun n hn ↦ by simp [hn] open Filter in /-- If `f` and `g` agree on large `n : ℕ`, then the `LSeries` of `f` converges at `s` @@ -195,8 +195,7 @@ theorem LSeries.eq_zero_of_not_LSeriesSummable (f : ℕ → ℂ) (s : ℂ) : @[simp] theorem LSeriesSummable_zero {s : ℂ} : LSeriesSummable 0 s := by - simp only [LSeriesSummable, funext (term_def 0 s), Pi.zero_apply, zero_div, ite_self, - summable_zero] + simp [LSeriesSummable, funext (term_def 0 s), summable_zero] /-- This states that the L-series of the sequence `f` converges absolutely at `s` and that the value there is `a`. -/ @@ -221,7 +220,7 @@ lemma LSeriesHasSum_iff {f : ℕ → ℂ} {s a : ℂ} : lemma LSeriesHasSum_congr {f g : ℕ → ℂ} (s a : ℂ) (h : ∀ {n}, n ≠ 0 → f n = g n) : LSeriesHasSum f s a ↔ LSeriesHasSum g s a := by - simp only [LSeriesHasSum_iff, LSeriesSummable_congr s h, LSeries_congr s h] + simp [LSeriesHasSum_iff, LSeriesSummable_congr s h, LSeries_congr s h] lemma LSeriesSummable.of_re_le_re {f : ℕ → ℂ} {s s' : ℂ} (h : s.re ≤ s'.re) (hf : LSeriesSummable f s) : LSeriesSummable f s' := by @@ -260,7 +259,7 @@ scoped[LSeries.notation] notation "δ" => delta @[simp] lemma LSeries_zero : LSeries 0 = 0 := by ext - simp only [LSeries, LSeries.term, Pi.zero_apply, zero_div, ite_self, tsum_zero] + simp [LSeries, LSeries.term] section delta @@ -272,16 +271,14 @@ open Nat Complex lemma term_delta (s : ℂ) (n : ℕ) : term δ s n = if n = 1 then 1 else 0 := by rcases eq_or_ne n 0 with rfl | hn - · simp only [term_zero, zero_ne_one, ↓reduceIte] - · simp only [ne_eq, hn, not_false_eq_true, term_of_ne_zero, delta] - rcases eq_or_ne n 1 with rfl | hn' - · simp only [↓reduceIte, cast_one, one_cpow, ne_eq, one_ne_zero, not_false_eq_true, div_self] - · simp only [hn', ↓reduceIte, zero_div] + · simp + · rcases eq_or_ne n 1 with hn' | hn' <;> + simp [hn, hn', delta] lemma mul_delta_eq_smul_delta {f : ℕ → ℂ} : f * δ = f 1 • δ := by ext n - simp only [Pi.mul_apply, delta, mul_ite, mul_one, mul_zero, Pi.smul_apply, smul_eq_mul] - split_ifs with hn <;> simp only [hn] + by_cases hn : n = 1 <;> + simp [hn, delta] lemma mul_delta {f : ℕ → ℂ} (h : f 1 = 1) : f * δ = δ := by rw [mul_delta_eq_smul_delta, h, one_smul] @@ -297,7 +294,7 @@ end LSeries /-- The L-series of `δ` is the constant function `1`. -/ lemma LSeries_delta : LSeries δ = 1 := by ext - simp only [LSeries, LSeries.term_delta, tsum_ite_eq, Pi.one_apply] + simp [LSeries, LSeries.term_delta] end delta @@ -335,31 +332,25 @@ lemma LSeriesSummable_of_le_const_mul_rpow {f : ℕ → ℂ} {x : ℝ} {s : ℂ} (h : ∃ C, ∀ n ≠ 0, ‖f n‖ ≤ C * n ^ (x - 1)) : LSeriesSummable f s := by obtain ⟨C, hC⟩ := h - have hC₀ : 0 ≤ C := by - specialize hC 1 one_ne_zero - simp only [Nat.cast_one, Real.one_rpow, mul_one] at hC - exact (norm_nonneg _).trans hC + have hC₀ : 0 ≤ C := (norm_nonneg <| f 1).trans <| by simpa using hC 1 one_ne_zero have hsum : Summable fun n : ℕ ↦ ‖(C : ℂ) / n ^ (s + (1 - x))‖ := by simp_rw [div_eq_mul_inv, norm_mul, ← cpow_neg] have hsx : -s.re + x - 1 < -1 := by linarith only [hs] refine Summable.mul_left _ <| Summable.of_norm_bounded_eventually_nat (fun n ↦ (n : ℝ) ^ (-s.re + x - 1)) ?_ ?_ - · simp only [Real.summable_nat_rpow, hsx] - · simp only [neg_add_rev, neg_sub, norm_norm, Filter.eventually_atTop] - refine ⟨1, fun n hn ↦ ?_⟩ + · simpa + · simp only [norm_norm, Filter.eventually_atTop] + refine ⟨1, fun n hn ↦ le_of_eq ?_⟩ simp only [norm_natCast_cpow_of_pos hn, add_re, sub_re, neg_re, ofReal_re, one_re] - convert le_refl ?_ using 2 - ring + ring_nf refine Summable.of_norm <| hsum.of_nonneg_of_le (fun _ ↦ norm_nonneg _) (fun n ↦ ?_) rcases n.eq_zero_or_pos with rfl | hn - · simp only [term_zero, norm_zero] - exact norm_nonneg _ + · simpa only [term_zero, norm_zero] using norm_nonneg _ have hn' : 0 < (n : ℝ) ^ s.re := Real.rpow_pos_of_pos (Nat.cast_pos.mpr hn) _ simp_rw [term_of_ne_zero hn.ne', norm_div, norm_natCast_cpow_of_pos hn, div_le_iff₀ hn', norm_eq_abs (C : ℂ), abs_ofReal, _root_.abs_of_nonneg hC₀, div_eq_mul_inv, mul_assoc, ← Real.rpow_neg <| Nat.cast_nonneg _, ← Real.rpow_add <| Nat.cast_pos.mpr hn] - simp only [add_re, sub_re, one_re, ofReal_re, neg_add_rev, neg_sub, neg_add_cancel_right] - exact hC n <| Nat.pos_iff_ne_zero.mp hn + simpa using hC n <| Nat.pos_iff_ne_zero.mp hn open Filter Finset Real Nat in /-- If `f = O(n^(x-1))` and `re s > x`, then the `LSeries` of `f` is summable at `s`. -/ @@ -386,12 +377,11 @@ lemma LSeriesSummable_of_isBigO_rpow {f : ℕ → ℂ} {x : ℝ} {s : ℂ} (hs : /-- If `f` is bounded, then its `LSeries` is summable at `s` when `re s > 1`. -/ theorem LSeriesSummable_of_bounded_of_one_lt_re {f : ℕ → ℂ} {m : ℝ} (h : ∀ n ≠ 0, Complex.abs (f n) ≤ m) {s : ℂ} (hs : 1 < s.re) : - LSeriesSummable f s := by - refine LSeriesSummable_of_le_const_mul_rpow hs ⟨m, fun n hn ↦ ?_⟩ - simp only [norm_eq_abs, sub_self, Real.rpow_zero, mul_one, h n hn] + LSeriesSummable f s := + LSeriesSummable_of_le_const_mul_rpow hs ⟨m, fun n hn ↦ by simp [h n hn]⟩ /-- If `f` is bounded, then its `LSeries` is summable at `s : ℝ` when `s > 1`. -/ theorem LSeriesSummable_of_bounded_of_one_lt_real {f : ℕ → ℂ} {m : ℝ} (h : ∀ n ≠ 0, Complex.abs (f n) ≤ m) {s : ℝ} (hs : 1 < s) : LSeriesSummable f s := - LSeriesSummable_of_bounded_of_one_lt_re h <| by simp only [ofReal_re, hs] + LSeriesSummable_of_bounded_of_one_lt_re h <| by simp [hs] diff --git a/Mathlib/NumberTheory/LSeries/Convergence.lean b/Mathlib/NumberTheory/LSeries/Convergence.lean index d54f658f77e00..c7b9d345d82bc 100644 --- a/Mathlib/NumberTheory/LSeries/Convergence.lean +++ b/Mathlib/NumberTheory/LSeries/Convergence.lean @@ -41,47 +41,42 @@ open LSeries lemma LSeriesSummable_of_abscissaOfAbsConv_lt_re {f : ℕ → ℂ} {s : ℂ} (hs : abscissaOfAbsConv f < s.re) : LSeriesSummable f s := by - simp only [abscissaOfAbsConv, sInf_lt_iff, Set.mem_image, Set.mem_setOf_eq, - exists_exists_and_eq_and, EReal.coe_lt_coe_iff] at hs - obtain ⟨y, hy, hys⟩ := hs + obtain ⟨y, hy, hys⟩ : ∃ a : ℝ, LSeriesSummable f a ∧ a < s.re := by + simpa [abscissaOfAbsConv, sInf_lt_iff] using hs exact hy.of_re_le_re <| ofReal_re y ▸ hys.le lemma LSeriesSummable_lt_re_of_abscissaOfAbsConv_lt_re {f : ℕ → ℂ} {s : ℂ} (hs : abscissaOfAbsConv f < s.re) : ∃ x : ℝ, x < s.re ∧ LSeriesSummable f x := by obtain ⟨x, hx₁, hx₂⟩ := EReal.exists_between_coe_real hs - exact ⟨x, EReal.coe_lt_coe_iff.mp hx₂, LSeriesSummable_of_abscissaOfAbsConv_lt_re hx₁⟩ + exact ⟨x, by simpa using hx₂, LSeriesSummable_of_abscissaOfAbsConv_lt_re hx₁⟩ lemma LSeriesSummable.abscissaOfAbsConv_le {f : ℕ → ℂ} {s : ℂ} (h : LSeriesSummable f s) : - abscissaOfAbsConv f ≤ s.re := by - refine sInf_le <| Membership.mem.out ?_ - simp only [Set.mem_setOf_eq, Set.mem_image, EReal.coe_eq_coe_iff, exists_eq_right] - exact h.of_re_le_re <| by simp only [ofReal_re, le_refl] + abscissaOfAbsConv f ≤ s.re := + sInf_le <| by simpa using h.of_re_le_re (by simp) lemma LSeries.abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable {f : ℕ → ℂ} {x : ℝ} (h : ∀ y : ℝ, x < y → LSeriesSummable f y) : abscissaOfAbsConv f ≤ x := by - refine sInf_le_iff.mpr fun y hy ↦ ?_ - simp only [mem_lowerBounds, Set.mem_image, Set.mem_setOf_eq, forall_exists_index, and_imp, - forall_apply_eq_imp_iff₂] at hy - have H (a : EReal) : x < a → y ≤ a := by - induction' a with a₀ - · simp only [not_lt_bot, le_bot_iff, IsEmpty.forall_iff] - · exact_mod_cast fun ha ↦ hy a₀ (h a₀ ha) - · simp only [EReal.coe_lt_top, le_top, forall_true_left] - exact Set.Ioi_subset_Ici_iff.mp H + refine sInf_le_iff.mpr fun y hy ↦ le_of_forall_gt_imp_ge_of_dense fun a ↦ ?_ + replace hy : ∀ (a : ℝ), LSeriesSummable f a → y ≤ a := by simpa [mem_lowerBounds] using hy + cases a with + | h_real a₀ => exact_mod_cast fun ha ↦ hy a₀ (h a₀ ha) + | h_bot => simp + | h_top => simp lemma LSeries.abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable' {f : ℕ → ℂ} {x : EReal} (h : ∀ y : ℝ, x < y → LSeriesSummable f y) : abscissaOfAbsConv f ≤ x := by - induction' x with y - · refine le_of_eq <| sInf_eq_bot.mpr fun y hy ↦ ?_ - induction' y with z - · simp only [gt_iff_lt, lt_self_iff_false] at hy - · exact ⟨z - 1, ⟨z-1, h (z - 1) <| EReal.bot_lt_coe _, rfl⟩, by norm_cast; exact sub_one_lt z⟩ - · exact ⟨0, ⟨0, h 0 <| EReal.bot_lt_coe 0, rfl⟩, EReal.zero_lt_top⟩ - · exact abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable <| by exact_mod_cast h - · exact le_top + cases x with + | h_real => exact abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable <| mod_cast h + | h_top => exact le_top + | h_bot => + refine le_of_eq <| sInf_eq_bot.mpr fun y hy ↦ ?_ + cases y with + | h_bot => simp at hy + | h_real y => exact ⟨_, ⟨_, h _ <| EReal.bot_lt_coe _, rfl⟩, mod_cast sub_one_lt y⟩ + | h_top => exact ⟨_, ⟨_, h _ <| EReal.bot_lt_coe 0, rfl⟩, EReal.zero_lt_top⟩ /-- If `‖f n‖` is bounded by a constant times `n^x`, then the abscissa of absolute convergence of `f` is bounded by `x + 1`. -/ @@ -108,35 +103,27 @@ lemma LSeries.abscissaOfAbsConv_le_of_isBigO_rpow {f : ℕ → ℂ} {x : ℝ} /-- If `f` is bounded, then the abscissa of absolute convergence of `f` is bounded above by `1`. -/ lemma LSeries.abscissaOfAbsConv_le_of_le_const {f : ℕ → ℂ} (h : ∃ C, ∀ n ≠ 0, ‖f n‖ ≤ C) : abscissaOfAbsConv f ≤ 1 := by - convert abscissaOfAbsConv_le_of_le_const_mul_rpow (x := 0) ?_ - · simp only [EReal.coe_zero, zero_add] - · simpa only [norm_eq_abs, Real.rpow_zero, mul_one] using h + simpa using abscissaOfAbsConv_le_of_le_const_mul_rpow (x := 0) (by simpa using h) open Filter in /-- If `f` is `O(1)`, then the abscissa of absolute convergence of `f` is bounded above by `1`. -/ -lemma LSeries.abscissaOfAbsConv_le_one_of_isBigO_one {f : ℕ → ℂ} (h : f =O[atTop] (1 : ℕ → ℝ)) : +lemma LSeries.abscissaOfAbsConv_le_one_of_isBigO_one {f : ℕ → ℂ} (h : f =O[atTop] fun _ ↦ (1 : ℝ)) : abscissaOfAbsConv f ≤ 1 := by - convert abscissaOfAbsConv_le_of_isBigO_rpow (x := 0) ?_ - · simp only [EReal.coe_zero, zero_add] - · simpa only [Real.rpow_zero] using h + simpa using abscissaOfAbsConv_le_of_isBigO_rpow (x := 0) (by simpa using h) /-- If `f` is real-valued and `x` is strictly greater than the abscissa of absolute convergence of `f`, then the real series `∑' n, f n / n ^ x` converges. -/ lemma LSeries.summable_real_of_abscissaOfAbsConv_lt {f : ℕ → ℝ} {x : ℝ} (h : abscissaOfAbsConv (f ·) < x) : Summable fun n : ℕ ↦ f n / (n : ℝ) ^ x := by - have h' : abscissaOfAbsConv (f ·) < (x : ℂ).re := by simpa only [ofReal_re] using h - have := LSeriesSummable_of_abscissaOfAbsConv_lt_re h' - rw [LSeriesSummable, show term _ _ = fun n ↦ _ from rfl] at this - conv at this => - enter [1, n] - rw [term_def, ← ofReal_natCast, ← ofReal_cpow n.cast_nonneg, ← ofReal_div, ← ofReal_zero, - ← apply_ite] - rw [summable_ofReal] at this + have aux : term (f ·) x = fun n ↦ ↑(if n = 0 then 0 else f n / (n : ℝ) ^ x) := by + ext n + simp [term_def, apply_ite ((↑) : ℝ → ℂ), ofReal_cpow n.cast_nonneg] + have := LSeriesSummable_of_abscissaOfAbsConv_lt_re (ofReal_re x ▸ h) + simp only [LSeriesSummable, aux, summable_ofReal] at this refine this.congr_cofinite ?_ - filter_upwards [Set.Finite.compl_mem_cofinite <| Set.finite_singleton 0] with n hn - simp only [Set.mem_compl_iff, Set.mem_singleton_iff] at hn - exact if_neg hn + filter_upwards [(Set.finite_singleton 0).compl_mem_cofinite] with n hn + using if_neg (by simpa using hn) /-- If `F` is a binary operation on `ℕ → ℂ` with the property that the `LSeries` of `F f g` converges whenever the `LSeries` of `f` and `g` do, then the abscissa of absolute convergence diff --git a/Mathlib/NumberTheory/LSeries/Convolution.lean b/Mathlib/NumberTheory/LSeries/Convolution.lean index eed4c45fbce01..8875e094acb81 100644 --- a/Mathlib/NumberTheory/LSeries/Convolution.lean +++ b/Mathlib/NumberTheory/LSeries/Convolution.lean @@ -40,10 +40,8 @@ def toArithmeticFunction {R : Type*} [Zero R] (f : ℕ → R) : ArithmeticFuncti lemma toArithmeticFunction_congr {R : Type*} [Zero R] {f f' : ℕ → R} (h : ∀ {n}, n ≠ 0 → f n = f' n) : toArithmeticFunction f = toArithmeticFunction f' := by - ext ⟨- | _⟩ - · simp only [zero_eq, ArithmeticFunction.map_zero] - · simp only [toArithmeticFunction, ArithmeticFunction.coe_mk, succ_ne_zero, ↓reduceIte, - ne_eq, not_false_eq_true, h] + ext + simp_all [toArithmeticFunction] /-- If we consider an arithmetic function just as a function and turn it back into an arithmetic function, it is the same as before. -/ @@ -52,7 +50,7 @@ lemma ArithmeticFunction.toArithmeticFunction_eq_self {R : Type*} [Zero R] (f : ArithmeticFunction R) : toArithmeticFunction f = f := by ext n - simp (config := {contextual := true}) [toArithmeticFunction, ArithmeticFunction.map_zero] + simp +contextual [toArithmeticFunction] /-- Dirichlet convolution of two sequences. @@ -66,28 +64,25 @@ scoped[LSeries.notation] infixl:70 " ⍟ " => LSeries.convolution lemma LSeries.convolution_congr {R : Type*} [Semiring R] {f f' g g' : ℕ → R} (hf : ∀ {n}, n ≠ 0 → f n = f' n) (hg : ∀ {n}, n ≠ 0 → g n = g' n) : f ⍟ g = f' ⍟ g' := by - simp only [convolution, toArithmeticFunction_congr hf, toArithmeticFunction_congr hg] + simp [convolution, toArithmeticFunction_congr hf, toArithmeticFunction_congr hg] /-- The product of two arithmetic functions defines the same function as the Dirichlet convolution of the functions defined by them. -/ lemma ArithmeticFunction.coe_mul {R : Type*} [Semiring R] (f g : ArithmeticFunction R) : f ⍟ g = ⇑(f * g) := by - simp only [convolution, ArithmeticFunction.toArithmeticFunction_eq_self] + simp [convolution] namespace LSeries lemma convolution_def {R : Type*} [Semiring R] (f g : ℕ → R) : f ⍟ g = fun n ↦ ∑ p ∈ n.divisorsAntidiagonal, f p.1 * g p.2 := by ext n - simp only [convolution, toArithmeticFunction, ArithmeticFunction.mul_apply, - ArithmeticFunction.coe_mk, mul_ite, mul_zero, ite_mul, zero_mul] - refine Finset.sum_congr rfl fun p hp ↦ ?_ - obtain ⟨h₁, h₂⟩ := ne_zero_of_mem_divisorsAntidiagonal hp - simp only [h₂, ↓reduceIte, h₁] + simpa [convolution, toArithmeticFunction] using + Finset.sum_congr rfl fun p hp ↦ by simp [ne_zero_of_mem_divisorsAntidiagonal hp] @[simp] lemma convolution_map_zero {R : Type*} [Semiring R] (f g : ℕ → R) : (f ⍟ g) 0 = 0 := by - simp only [convolution_def, divisorsAntidiagonal_zero, Finset.sum_empty] + simp [convolution_def] /-! @@ -99,12 +94,12 @@ in terms of a sum over `Nat.divisorsAntidiagonal`. -/ lemma term_convolution (f g : ℕ → ℂ) (s : ℂ) (n : ℕ) : term (f ⍟ g) s n = ∑ p ∈ n.divisorsAntidiagonal, term f s p.1 * term g s p.2 := by rcases eq_or_ne n 0 with rfl | hn - · simp only [term_zero, divisorsAntidiagonal_zero, Finset.sum_empty] + · simp -- now `n ≠ 0` rw [term_of_ne_zero hn, convolution_def, Finset.sum_div] refine Finset.sum_congr rfl fun p hp ↦ ?_ have ⟨hp₁, hp₂⟩ := ne_zero_of_mem_divisorsAntidiagonal hp - rw [term_of_ne_zero hp₁ f s, term_of_ne_zero hp₂ g s, mul_comm_div, div_div, ← mul_div_assoc, + rw [term_of_ne_zero hp₁, term_of_ne_zero hp₂, mul_comm_div, div_div, ← mul_div_assoc, ← natCast_mul_natCast_cpow, ← cast_mul, mul_comm p.2, (mem_divisorsAntidiagonal.mp hp).1] open Set in @@ -122,12 +117,11 @@ lemma term_convolution' (f g : ℕ → ℂ) (s : ℂ) : -- the right hand sum is over the union below, but in each term, one factor is always zero have hS : (fun p ↦ p.1 * p.2) ⁻¹' {0} = {0} ×ˢ univ ∪ univ ×ˢ {0} := by ext - simp only [mem_preimage, mem_singleton_iff, Nat.mul_eq_zero, mem_union, mem_prod, mem_univ, - and_true, true_and] + simp [Nat.mul_eq_zero, -singleton_prod, -prod_singleton] have : ∀ p : (fun p : ℕ × ℕ ↦ p.1 * p.2) ⁻¹' {0}, term f s p.val.1 * term g s p.val.2 = 0 := by - rintro ⟨⟨p₁, p₂⟩, hp⟩ - rcases hS ▸ hp with ⟨rfl, -⟩ | ⟨-, rfl⟩ <;> simp only [term_zero, zero_mul, mul_zero] - simp only [this, tsum_zero] + rintro ⟨⟨_, _⟩, hp⟩ + rcases hS ▸ hp with ⟨rfl, -⟩ | ⟨-, rfl⟩ <;> simp + simp [this] -- now `n ≠ 0` rw [show (fun p : ℕ × ℕ ↦ p.1 * p.2) ⁻¹' {n} = n.divisorsAntidiagonal by ext; simp [hn], Finset.tsum_subtype' n.divisorsAntidiagonal fun p ↦ term f s p.1 * term g s p.2, @@ -141,9 +135,9 @@ equals the product of their L-series, assuming both L-series converge. -/ lemma LSeriesHasSum.convolution {f g : ℕ → ℂ} {s a b : ℂ} (hf : LSeriesHasSum f s a) (hg : LSeriesHasSum g s b) : LSeriesHasSum (f ⍟ g) s (a * b) := by - simp only [LSeriesHasSum, term_convolution'] have hsum := summable_mul_of_summable_norm hf.summable.norm hg.summable.norm - exact (HasSum.mul hf hg hsum).tsum_fiberwise (fun p ↦ p.1 * p.2) + -- NB: this `simpa` is quite slow if un-squeezed + simpa only [LSeriesHasSum, term_convolution'] using (hf.mul hg hsum).tsum_fiberwise _ /-- The L-series of the convolution product `f ⍟ g` of two sequences `f` and `g` equals the product of their L-series, assuming both L-series converge. -/ diff --git a/Mathlib/NumberTheory/LSeries/Deriv.lean b/Mathlib/NumberTheory/LSeries/Deriv.lean index f8f5726a088aa..ea7afe39b45a3 100644 --- a/Mathlib/NumberTheory/LSeries/Deriv.lean +++ b/Mathlib/NumberTheory/LSeries/Deriv.lean @@ -41,7 +41,7 @@ noncomputable abbrev LSeries.logMul (f : ℕ → ℂ) (n : ℕ) : ℂ := log n * lemma LSeries.hasDerivAt_term (f : ℕ → ℂ) (n : ℕ) (s : ℂ) : HasDerivAt (fun z ↦ term f z n) (-(term (logMul f) s n)) s := by rcases eq_or_ne n 0 with rfl | hn - · simp only [term_zero, neg_zero, hasDerivAt_const] + · simp [hasDerivAt_const] simp_rw [term_of_ne_zero hn, ← neg_div, ← neg_mul, mul_comm, mul_div_assoc, div_eq_mul_inv, ← cpow_neg] exact HasDerivAt.const_mul (f n) (by simpa only [mul_comm, ← mul_neg_one (log n), ← mul_assoc] @@ -67,9 +67,8 @@ private lemma LSeries.LSeriesSummable_logMul_and_hasDerivAt {f : ℕ → ℂ} {s have H := hasSum_deriv_of_summable_norm h₀ h₁ h₂ h₃ hys simp_rw [(hasDerivAt_term f _ _).deriv] at H refine ⟨summable_neg_iff.mp H.summable, ?_⟩ - have H' := differentiableOn_tsum_of_summable_norm h₀ h₁ h₂ h₃ - simpa only [← H.tsum_eq, tsum_neg] - using (H'.differentiableAt <| IsOpen.mem_nhds h₂ hys).hasDerivAt + simpa [← H.tsum_eq, tsum_neg] using ((differentiableOn_tsum_of_summable_norm + h₀ h₁ h₂ h₃).differentiableAt <| h₂.mem_nhds hys).hasDerivAt /-- If `re s` is greater than the abscissa of absolute convergence of `f`, then the L-series of `f` is differentiable with derivative the negative of the L-series of the point-wise @@ -103,14 +102,13 @@ lemma LSeries.abscissaOfAbsConv_logMul {f : ℕ → ℂ} : abscissaOfAbsConv (logMul f) = abscissaOfAbsConv f := by apply le_antisymm <;> refine abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable' fun s hs ↦ ?_ · exact LSeriesSummable_logMul_of_lt_re <| by simp [hs] - · refine (LSeriesSummable_of_abscissaOfAbsConv_lt_re <| by simp only [ofReal_re, hs]) + · refine (LSeriesSummable_of_abscissaOfAbsConv_lt_re <| by simp [hs]) |>.norm.of_norm_bounded_eventually_nat (‖term (logMul f) s ·‖) ?_ filter_upwards [Filter.eventually_ge_atTop <| max 1 (Nat.ceil (Real.exp 1))] with n hn simp only [term_of_ne_zero (show n ≠ 0 by omega), logMul, norm_mul, mul_div_assoc, ← natCast_log, norm_real] refine le_mul_of_one_le_left (norm_nonneg _) (.trans ?_ <| Real.le_norm_self _) - rw [← Real.log_exp 1] - exact Real.log_le_log (Real.exp_pos 1) <| Nat.ceil_le.mp <| (le_max_right _ _).trans hn + simpa using Real.log_le_log (Real.exp_pos 1) <| Nat.ceil_le.mp <| (le_max_right _ _).trans hn /-! ### Higher derivatives of L-series @@ -121,24 +119,24 @@ is the same as that of `f`. -/ @[simp] lemma LSeries.absicssaOfAbsConv_logPowMul {f : ℕ → ℂ} {m : ℕ} : abscissaOfAbsConv (logMul^[m] f) = abscissaOfAbsConv f := by - induction' m with n ih - · simp only [Function.iterate_zero, id_eq] - · simp only [ih, Function.iterate_succ', Function.comp_def, abscissaOfAbsConv_logMul] + induction m with + | zero => simp + | succ n ih => simp [ih, Function.iterate_succ', Function.comp_def, + -Function.comp_apply, -Function.iterate_succ] /-- If `re s` is greater than the abscissa of absolute convergence of `f`, then the `m`th derivative of this L-series is `(-1)^m` times the L-series of `log^m * f`. -/ lemma LSeries_iteratedDeriv {f : ℕ → ℂ} (m : ℕ) {s : ℂ} (h : abscissaOfAbsConv f < s.re) : iteratedDeriv m (LSeries f) s = (-1) ^ m * LSeries (logMul^[m] f) s := by induction' m with m ih generalizing s - · simp only [iteratedDeriv_zero, pow_zero, Function.iterate_zero, id_eq, one_mul] + · simp · have ih' : {s | abscissaOfAbsConv f < re s}.EqOn (iteratedDeriv m (LSeries f)) ((-1) ^ m * LSeries (logMul^[m] f)) := fun _ hs ↦ ih hs have := derivWithin_congr ih' (ih h) simp_rw [derivWithin_of_isOpen (isOpen_re_gt_EReal _) h] at this rw [iteratedDeriv_succ, this] - simp only [Pi.mul_def, Pi.pow_apply, Pi.neg_apply, Pi.one_apply, deriv_const_mul_field', - pow_succ, mul_assoc, neg_one_mul, Function.iterate_succ', Function.comp_def, - LSeries_deriv <| absicssaOfAbsConv_logPowMul.symm ▸ h] + simp [Pi.mul_def, pow_succ, mul_assoc, Function.iterate_succ', Function.comp_def, + LSeries_deriv <| absicssaOfAbsConv_logPowMul.symm ▸ h, -Function.iterate_succ] /-! ### The L-series is holomorphic diff --git a/Mathlib/NumberTheory/LSeries/Dirichlet.lean b/Mathlib/NumberTheory/LSeries/Dirichlet.lean index 96724285e05ad..054b02fd1943f 100644 --- a/Mathlib/NumberTheory/LSeries/Dirichlet.lean +++ b/Mathlib/NumberTheory/LSeries/Dirichlet.lean @@ -36,7 +36,7 @@ open scoped LSeries.notation /-- `δ` is the function underlying the arithmetic function `1`. -/ lemma ArithmeticFunction.one_eq_delta : ↗(1 : ArithmeticFunction ℂ) = δ := by ext - simp only [one_apply, LSeries.delta] + simp [one_apply, LSeries.delta] section Moebius @@ -52,29 +52,25 @@ namespace ArithmeticFunction open LSeries Nat Complex lemma not_LSeriesSummable_moebius_at_one : ¬ LSeriesSummable ↗μ 1 := by - intro h - refine not_summable_one_div_on_primes <| summable_ofReal.mp <| Summable.of_neg ?_ - simp only [← Pi.neg_def, Set.indicator_comp_of_zero ofReal_zero, ofReal_inv, ofReal_natCast] - refine (h.indicator {n | n.Prime}).congr (fun n ↦ ?_) - by_cases hn : n ∈ {p | p.Prime} - · simp only [Pi.neg_apply, Set.indicator_of_mem hn, term_of_ne_zero hn.ne_zero, - moebius_apply_prime hn, cpow_one, push_cast, neg_div] - · simp only [one_div, Pi.neg_apply, Set.indicator_of_not_mem hn, ofReal_zero, neg_zero] + refine fun h ↦ not_summable_one_div_on_primes <| summable_ofReal.mp <| .of_neg ?_ + refine (h.indicator {n | n.Prime}).congr fun n ↦ ?_ + by_cases hn : n.Prime + · simp [hn, hn.ne_zero, moebius_apply_prime hn, push_cast, neg_div] + · simp [hn] /-- The L-series of the Möbius function converges absolutely at `s` if and only if `re s > 1`. -/ lemma LSeriesSummable_moebius_iff {s : ℂ} : LSeriesSummable ↗μ s ↔ 1 < s.re := by refine ⟨fun H ↦ ?_, LSeriesSummable_of_bounded_of_one_lt_re (m := 1) fun n _ ↦ ?_⟩ · by_contra! h - have h' : s.re ≤ (1 : ℂ).re := by simp only [one_re, h] - exact not_LSeriesSummable_moebius_at_one <| LSeriesSummable.of_re_le_re h' H + exact not_LSeriesSummable_moebius_at_one <| LSeriesSummable.of_re_le_re (by simpa) H · rw [abs_intCast] -- not done by `norm_cast` norm_cast exact abs_moebius_le_one /-- The abscissa of absolute convergence of the L-series of the Möbius function is `1`. -/ lemma abscissaOfAbsConv_moebius : abscissaOfAbsConv ↗μ = 1 := by - simpa only [abscissaOfAbsConv, LSeriesSummable_moebius_iff, ofReal_re, Set.Ioi_def, - EReal.image_coe_Ioi, EReal.coe_one] using csInf_Ioo <| EReal.coe_lt_top _ + simpa [abscissaOfAbsConv, LSeriesSummable_moebius_iff, Set.Ioi_def, EReal.image_coe_Ioi] + using csInf_Ioo <| EReal.coe_lt_top 1 end ArithmeticFunction @@ -90,7 +86,7 @@ open Nat open scoped ArithmeticFunction.zeta in lemma ArithmeticFunction.const_one_eq_zeta {R : Type*} [Semiring R] {n : ℕ} (hn : n ≠ 0) : (1 : ℕ → R) n = (ζ ·) n := by - simp only [Pi.one_apply, zeta_apply, hn, ↓reduceIte, cast_one] + simp [hn] lemma LSeries.one_convolution_eq_zeta_convolution {R : Type*} [Semiring R] (f : ℕ → R) : (1 : ℕ → R) ⍟ f = ((ArithmeticFunction.zeta ·) : ℕ → R) ⍟ f := @@ -111,14 +107,13 @@ lemma isMultiplicative_toArithmeticFunction {N : ℕ} {R : Type*} [CommMonoidWit (χ : DirichletCharacter R N) : (toArithmeticFunction (χ ·)).IsMultiplicative := by refine IsMultiplicative.iff_ne_zero.mpr ⟨?_, fun {m} {n} hm hn _ ↦ ?_⟩ - · simp only [toArithmeticFunction, coe_mk, one_ne_zero, ↓reduceIte, Nat.cast_one, map_one] - · simp only [toArithmeticFunction, coe_mk, mul_eq_zero, hm, hn, false_or, Nat.cast_mul, map_mul, - if_false] + · simp [toArithmeticFunction] + · simp [toArithmeticFunction, hm, hn] lemma apply_eq_toArithmeticFunction_apply {N : ℕ} {R : Type*} [CommMonoidWithZero R] (χ : DirichletCharacter R N) {n : ℕ} (hn : n ≠ 0) : χ n = toArithmeticFunction (χ ·) n := by - simp only [toArithmeticFunction, ArithmeticFunction.coe_mk, hn, ↓reduceIte] + simp [toArithmeticFunction, hn] open LSeries Nat Complex @@ -154,9 +149,9 @@ lemma modZero_eq_delta {χ : DirichletCharacter ℂ 0} : ↗χ = δ := by rcases eq_or_ne n 0 with rfl | hn · simp_rw [cast_zero, χ.map_nonunit not_isUnit_zero, delta, reduceCtorEq, if_false] rcases eq_or_ne n 1 with rfl | hn' - · simp only [cast_one, map_one, delta, ↓reduceIte] + · simp [delta] have : ¬ IsUnit (n : ZMod 0) := fun h ↦ hn' <| ZMod.eq_one_of_isUnit_natCast h - simp only [χ.map_nonunit this, delta, hn', ↓reduceIte] + simp_all [χ.map_nonunit this, delta] /-- The Dirichlet character mod `1` corresponds to the constant function `1`. -/ lemma modOne_eq_one {R : Type*} [CommSemiring R] {χ : DirichletCharacter R 1} : @@ -173,10 +168,10 @@ lemma not_LSeriesSummable_at_one {N : ℕ} (hN : N ≠ 0) (χ : DirichletCharact refine fun h ↦ (Real.not_summable_indicator_one_div_natCast hN 1) ?_ refine h.norm.of_nonneg_of_le (fun m ↦ Set.indicator_apply_nonneg (fun _ ↦ by positivity)) (fun n ↦ ?_) - rw [norm_term_eq, one_re, Real.rpow_one, Set.indicator] + simp only [norm_term_eq, Set.indicator, Set.mem_setOf_eq] split_ifs with h₁ h₂ - · rw [h₂, cast_zero, div_zero] - · rw [h₁, χ.map_one, norm_one] + · simp [h₂] + · simp [h₁, χ.map_one] all_goals positivity /-- The L-series of a Dirichlet character converges absolutely at `s` if `re s > 1`. -/ @@ -190,14 +185,14 @@ lemma LSeriesSummable_iff {N : ℕ} (hN : N ≠ 0) (χ : DirichletCharacter ℂ LSeriesSummable ↗χ s ↔ 1 < s.re := by refine ⟨fun H ↦ ?_, LSeriesSummable_of_one_lt_re χ⟩ by_contra! h - exact not_LSeriesSummable_at_one hN χ <| LSeriesSummable.of_re_le_re (by simp only [one_re, h]) H + exact not_LSeriesSummable_at_one hN χ <| LSeriesSummable.of_re_le_re (by simp [h]) H /-- The abscissa of absolute convergence of the L-series of a Dirichlet character mod `N > 0` is `1`. -/ lemma absicssaOfAbsConv_eq_one {N : ℕ} (hn : N ≠ 0) (χ : DirichletCharacter ℂ N) : abscissaOfAbsConv ↗χ = 1 := by - simpa only [abscissaOfAbsConv, LSeriesSummable_iff hn χ, ofReal_re, Set.Ioi_def, - EReal.image_coe_Ioi, EReal.coe_one] using csInf_Ioo <| EReal.coe_lt_top _ + simpa [abscissaOfAbsConv, LSeriesSummable_iff hn χ, Set.Ioi_def, EReal.image_coe_Ioi] + using csInf_Ioo <| EReal.coe_lt_top 1 /-- The L-series of the twist of `f` by a Dirichlet character converges at `s` if the L-series of `f` does. -/ @@ -205,8 +200,7 @@ lemma LSeriesSummable_mul {N : ℕ} (χ : DirichletCharacter ℂ N) {f : ℕ → (h : LSeriesSummable f s) : LSeriesSummable (↗χ * f) s := by refine .of_norm <| h.norm.of_nonneg_of_le (fun _ ↦ norm_nonneg _) fun n ↦ norm_term_le s ?_ - rw [Pi.mul_apply, norm_mul] - exact mul_le_of_le_one_left (norm_nonneg _) <| norm_le_one .. + simpa using mul_le_of_le_one_left (norm_nonneg <| f n) <| χ.norm_le_one n open scoped ArithmeticFunction.Moebius in /-- The L-series of a Dirichlet character `χ` and of the twist of `μ` by `χ` are multiplicative @@ -225,7 +219,7 @@ lemma LSeries.mul_mu_eq_one {N : ℕ} (χ : DirichletCharacter ℂ N) {s : ℂ} /-- The L-series of a Dirichlet character does not vanish on the right half-plane `re s > 1`. -/ lemma LSeries_ne_zero_of_one_lt_re {N : ℕ} (χ : DirichletCharacter ℂ N) {s : ℂ} (hs : 1 < s.re) : L ↗χ s ≠ 0 := - fun h ↦ by simpa only [h, zero_mul, zero_ne_one] using LSeries.mul_mu_eq_one χ hs + fun h ↦ by simpa [h] using LSeries.mul_mu_eq_one χ hs end DirichletCharacter @@ -271,12 +265,11 @@ lemma abscissaOfAbsConv_zeta : abscissaOfAbsConv ↗ζ = 1 := by /-- The L-series of the arithmetic function `ζ` equals the Riemann Zeta Function on its domain of convergence `1 < re s`. -/ lemma LSeries_zeta_eq_riemannZeta {s : ℂ} (hs : 1 < s.re) : L ↗ζ s = riemannZeta s := by - simp only [LSeries, natCoe_apply, zeta_apply, cast_ite, cast_zero, cast_one, - zeta_eq_tsum_one_div_nat_cpow hs] + suffices ∑' n, term (fun n ↦ if n = 0 then 0 else 1) s n = ∑' n : ℕ, 1 / (n : ℂ) ^ s by + simpa [LSeries, zeta_eq_tsum_one_div_nat_cpow hs] refine tsum_congr fun n ↦ ?_ - rcases eq_or_ne n 0 with rfl | hn - · simp only [term_zero, cast_zero, zero_cpow (ne_zero_of_one_lt_re hs), div_zero] - · simp only [term_of_ne_zero hn, hn, ↓reduceIte, one_div] + rcases eq_or_ne n 0 with hn | hn <;> + simp [hn, ne_zero_of_one_lt_re hs] /-- The L-series of the arithmetic function `ζ` equals the Riemann Zeta Function on its domain of convergence `1 < re s`. -/ @@ -287,13 +280,12 @@ lemma LSeriesHasSum_zeta {s : ℂ} (hs : 1 < s.re) : LSeriesHasSum ↗ζ s (riem lemma LSeries_zeta_mul_Lseries_moebius {s : ℂ} (hs : 1 < s.re) : L ↗ζ s * L ↗μ s = 1 := by rw [← LSeries_convolution' (LSeriesSummable_zeta_iff.mpr hs) (LSeriesSummable_moebius_iff.mpr hs)] - simp only [← natCoe_apply, ← intCoe_apply, coe_mul, coe_zeta_mul_coe_moebius, one_eq_delta, - LSeries_delta, Pi.one_apply] + simp [← natCoe_apply, ← intCoe_apply, coe_mul, one_eq_delta, LSeries_delta, -zeta_apply] /-- The L-series of the arithmetic function `ζ` does not vanish on the right half-plane `re s > 1`. -/ lemma LSeries_zeta_ne_zero_of_one_lt_re {s : ℂ} (hs : 1 < s.re) : L ↗ζ s ≠ 0 := - fun h ↦ by simpa only [h, zero_mul, zero_ne_one] using LSeries_zeta_mul_Lseries_moebius hs + fun h ↦ by simpa [h, -zeta_apply] using LSeries_zeta_mul_Lseries_moebius hs end ArithmeticFunction @@ -339,8 +331,7 @@ namespace ArithmeticFunction to an equality of complex sequences. -/ lemma convolution_vonMangoldt_zeta : ↗Λ ⍟ ↗ζ = ↗Complex.log := by ext n - simpa only [zeta_apply, apply_ite, cast_zero, cast_one, LSeries.convolution_def, mul_zero, - mul_one, mul_apply, natCoe_apply, ofReal_sum, ofReal_zero, log_apply, ofReal_log n.cast_nonneg] + simpa [apply_ite, LSeries.convolution_def, -vonMangoldt_mul_zeta] using congr_arg (ofReal <| · n) vonMangoldt_mul_zeta lemma convolution_vonMangoldt_const_one : ↗Λ ⍟ 1 = ↗Complex.log := @@ -351,12 +342,11 @@ lemma LSeriesSummable_vonMangoldt {s : ℂ} (hs : 1 < s.re) : LSeriesSummable have hf := LSeriesSummable_logMul_of_lt_re (show abscissaOfAbsConv 1 < s.re by rw [abscissaOfAbsConv_one]; exact_mod_cast hs) rw [LSeriesSummable, ← summable_norm_iff] at hf ⊢ - refine Summable.of_nonneg_of_le (fun _ ↦ norm_nonneg _) (fun n ↦ norm_term_le s ?_) hf + refine hf.of_nonneg_of_le (fun _ ↦ norm_nonneg _) (fun n ↦ norm_term_le s ?_) have hΛ : ‖↗Λ n‖ ≤ ‖Complex.log n‖ := by - simp only [norm_eq_abs, abs_ofReal, _root_.abs_of_nonneg vonMangoldt_nonneg, - ← Complex.natCast_log, _root_.abs_of_nonneg <| Real.log_natCast_nonneg n] - exact ArithmeticFunction.vonMangoldt_le_log - exact hΛ.trans <| by simp only [norm_eq_abs, norm_mul, Pi.one_apply, norm_one, mul_one, le_refl] + simpa [_root_.abs_of_nonneg, vonMangoldt_nonneg, ← natCast_log, Real.log_natCast_nonneg] + using vonMangoldt_le_log + exact hΛ.trans <| by simp end ArithmeticFunction @@ -379,9 +369,8 @@ equals the negative logarithmic derivative of the L-series of `χ` when `re s > lemma LSeries_twist_vonMangoldt_eq {N : ℕ} (χ : DirichletCharacter ℂ N) {s : ℂ} (hs : 1 < s.re) : L (↗χ * ↗Λ) s = - deriv (L ↗χ) s / L ↗χ s := by rcases eq_or_ne N 0 with rfl | hN - · simpa only [modZero_eq_delta, delta_mul_eq_smul_delta, vonMangoldt_apply_one, ofReal_zero, - zero_smul, LSeries_zero, Pi.zero_apply, LSeries_delta, Pi.one_apply, div_one, zero_eq_neg] - using deriv_const s 1 + · simpa [-deriv_const', modZero_eq_delta, delta_mul_eq_smul_delta, LSeries_delta] + using deriv_const s (1 : ℂ) -- now `N ≠ 0` have hχ : LSeriesSummable ↗χ s := (LSeriesSummable_iff hN χ).mpr hs have hs' : abscissaOfAbsConv ↗χ < s.re := by @@ -389,7 +378,7 @@ lemma LSeries_twist_vonMangoldt_eq {N : ℕ} (χ : DirichletCharacter ℂ N) {s have hΛ : LSeriesSummable (↗χ * ↗Λ) s := LSeriesSummable_twist_vonMangoldt χ hs rw [eq_div_iff <| LSeries_ne_zero_of_one_lt_re χ hs, ← LSeries_convolution' hΛ hχ, convolution_twist_vonMangoldt, LSeries_deriv hs', neg_neg] - exact LSeries_congr s fun _ ↦ by simp only [Pi.mul_apply, mul_comm, logMul] + exact LSeries_congr s fun _ ↦ by simp [mul_comm, logMul] end DirichletCharacter @@ -401,7 +390,7 @@ of the L-series of the constant sequence `1` on its domain of convergence `re s lemma LSeries_vonMangoldt_eq {s : ℂ} (hs : 1 < s.re) : L ↗Λ s = - deriv (L 1) s / L 1 s := by refine (LSeries_congr s fun {n} _ ↦ ?_).trans <| LSeries_modOne_eq ▸ LSeries_twist_vonMangoldt_eq χ₁ hs - simp only [Subsingleton.eq_one (n : ZMod 1), map_one, Pi.mul_apply, one_mul] + simp [Subsingleton.eq_one (n : ZMod 1)] /-- The L-series of the von Mangoldt function `Λ` equals the negative logarithmic derivative of the Riemann zeta function on its domain of convergence `re s > 1`. -/ diff --git a/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean b/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean index 46c73ec9805a3..54f4c028c2a77 100644 --- a/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean +++ b/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean @@ -137,7 +137,7 @@ private lemma LFunction_changeLevel_aux {M N : ℕ} [NeZero M] [NeZero N] (hMN : fun_prop · refine eventually_of_mem ?_ (fun t (ht : 1 < t.re) ↦ ?_) · exact (continuous_re.isOpen_preimage _ isOpen_Ioi).mem_nhds (by norm_num : 1 < (2 : ℂ).re) - · simpa only [LFunction_eq_LSeries _ ht] using LSeries_changeLevel hMN χ ht + · simpa [LFunction_eq_LSeries _ ht] using LSeries_changeLevel hMN χ ht /-- If `χ` is a Dirichlet character and its level `M` divides `N`, then we obtain the L function of `χ` considered as a Dirichlet character of level `N` from the L function of `χ` by multiplying @@ -205,11 +205,11 @@ noncomputable def gammaFactor (χ : DirichletCharacter ℂ N) (s : ℂ) := lemma Even.gammaFactor_def {χ : DirichletCharacter ℂ N} (hχ : χ.Even) (s : ℂ) : gammaFactor χ s = Gammaℝ s := by - simp only [gammaFactor, hχ, ↓reduceIte] + simp [gammaFactor, hχ] lemma Odd.gammaFactor_def {χ : DirichletCharacter ℂ N} (hχ : χ.Odd) (s : ℂ) : gammaFactor χ s = Gammaℝ (s + 1) := by - simp only [gammaFactor, hχ.not_even, ↓reduceIte] + simp [gammaFactor, hχ.not_even] end gammaFactor @@ -270,9 +270,9 @@ noncomputable def rootNumber (χ : DirichletCharacter ℂ N) : ℂ := /-- The root number of the unique Dirichlet character modulo 1 is 1. -/ lemma rootNumber_modOne (χ : DirichletCharacter ℂ 1) : rootNumber χ = 1 := by - simp only [rootNumber, gaussSum, ← singleton_eq_univ (1 : ZMod 1), sum_singleton, map_one, - (show stdAddChar (1 : ZMod 1) = 1 from AddChar.map_zero_eq_one _), one_mul, - (show χ.Even from map_one _), ite_true, pow_zero, div_one, Nat.cast_one, one_cpow] + simp [rootNumber, gaussSum, -univ_unique, ← singleton_eq_univ (1 : ZMod 1), + (show stdAddChar (1 : ZMod 1) = 1 from AddChar.map_zero_eq_one _), + (show χ.Even from map_one _)] namespace IsPrimitive @@ -282,8 +282,7 @@ theorem completedLFunction_one_sub {χ : DirichletCharacter ℂ N} (hχ : IsPrim classical -- First handle special case of Riemann zeta rcases eq_or_ne N 1 with rfl | hN - · simp only [completedLFunction_modOne_eq, completedRiemannZeta_one_sub, Nat.cast_one, one_cpow, - rootNumber_modOne, one_mul] + · simp [completedLFunction_modOne_eq, completedRiemannZeta_one_sub, rootNumber_modOne] -- facts about `χ` as function have h_sum : ∑ j, χ j = 0 := by refine χ.sum_eq_zero_of_ne_one (fun h ↦ hN.symm ?_) @@ -339,8 +338,7 @@ noncomputable abbrev LFunctionTrivChar₁ : ℂ → ℂ := lemma LFunctionTrivChar₁_apply_one_ne_zero : LFunctionTrivChar₁ n 1 ≠ 0 := by simp only [Function.update_self] refine Finset.prod_ne_zero_iff.mpr fun p hp ↦ ?_ - simpa only [ne_eq, sub_ne_zero, one_eq_inv, Nat.cast_eq_one] - using (Nat.prime_of_mem_primeFactors hp).ne_one + simpa [sub_ne_zero] using (Nat.prime_of_mem_primeFactors hp).ne_one /-- `s ↦ (s - 1) * L χ s` is an entire function when `χ` is a trivial Dirichlet character. -/ lemma differentiable_LFunctionTrivChar₁ : Differentiable ℂ (LFunctionTrivChar₁ n) := by @@ -350,8 +348,7 @@ lemma differentiable_LFunctionTrivChar₁ : Differentiable ℂ (LFunctionTrivCha (fun _ hs ↦ DifferentiableAt.differentiableWithinAt <| by fun_prop (disch := simp_all [hs])) fun _ hs ↦ Function.update_of_ne (Set.mem_diff_singleton.mp hs).2 .., continuousWithinAt_compl_self.mp ?_⟩ - simpa only [continuousWithinAt_compl_self, continuousAt_update_same] - using LFunctionTrivChar_residue_one + simpa using LFunctionTrivChar_residue_one lemma deriv_LFunctionTrivChar₁_apply_of_ne_one {s : ℂ} (hs : s ≠ 1) : deriv (LFunctionTrivChar₁ n) s = @@ -387,9 +384,8 @@ variable {n : ℕ} [NeZero n] {χ : DirichletCharacter ℂ n} is continuous away from the zeros of the L-function. -/ lemma continuousOn_neg_logDeriv_LFunction_of_nontriv (hχ : χ ≠ 1) : ContinuousOn (fun s ↦ -deriv (LFunction χ) s / LFunction χ s) {s | LFunction χ s ≠ 0} := by - simp only [neg_div] have h := differentiable_LFunction hχ - exact ((h.contDiff.continuous_deriv le_rfl).continuousOn.div + simpa [neg_div] using ((h.contDiff.continuous_deriv le_rfl).continuousOn.div h.continuous.continuousOn fun _ hw ↦ hw).neg end nontrivial diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean b/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean index 69091d6315bba..db0a47feb7759 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean @@ -92,14 +92,14 @@ determining what that value is). -/ lemma tendsto_hurwitzZeta_sub_one_div_nhds_one (a : UnitAddCircle) : Tendsto (fun s ↦ hurwitzZeta a s - 1 / (s - 1) / Gammaℝ s) (𝓝 1) (𝓝 (hurwitzZeta a 1)) := by simp only [hurwitzZeta, add_sub_right_comm] - refine (tendsto_hurwitzZetaEven_sub_one_div_nhds_one a).add ?_ - exact (differentiable_hurwitzZetaOdd a 1).continuousAt.tendsto + refine (tendsto_hurwitzZetaEven_sub_one_div_nhds_one a).add + (differentiable_hurwitzZetaOdd a 1).continuousAt.tendsto /-- The difference of two Hurwitz zeta functions is differentiable everywhere. -/ lemma differentiable_hurwitzZeta_sub_hurwitzZeta (a b : UnitAddCircle) : Differentiable ℂ (fun s ↦ hurwitzZeta a s - hurwitzZeta b s) := by simp only [hurwitzZeta, add_sub_add_comm] - refine (differentiable_hurwitzZetaEven_sub_hurwitzZetaEven a b).add (Differentiable.sub ?_ ?_) + refine (differentiable_hurwitzZetaEven_sub_hurwitzZetaEven a b).add (.sub ?_ ?_) all_goals apply differentiable_hurwitzZetaOdd /-! diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean b/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean index ceccbcc2a6eab..0b21a3ccf213b 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean @@ -65,76 +65,65 @@ completed Hurwit zeta function). See `evenKernel_def` for the defining formula, simp only [ofReal_add, ofReal_one, add_mul, one_mul, jacobiTheta₂_add_left'] have : cexp (-↑π * I * ((I * ↑x) + 2 * (↑ξ * I * ↑x))) = rexp (π * (x + 2 * ξ * x)) := by ring_nf - simp only [I_sq, mul_neg, mul_one, neg_mul, neg_neg, sub_neg_eq_add, ofReal_exp, ofReal_add, - ofReal_mul, ofReal_ofNat] + simp [I_sq] rw [this, re_ofReal_mul, ← mul_assoc, ← Real.exp_add] congr ring).lift a lemma evenKernel_def (a x : ℝ) : ↑(evenKernel ↑a x) = cexp (-π * a ^ 2 * x) * jacobiTheta₂ (a * I * x) (I * x) := by - unfold evenKernel - simp only [neg_mul, Function.Periodic.lift_coe, ofReal_mul, ofReal_exp, ofReal_neg, ofReal_pow, - re_eq_add_conj, jacobiTheta₂_conj, map_mul, conj_ofReal, conj_I, mul_neg, neg_neg, - jacobiTheta₂_neg_left, ← mul_two, mul_div_cancel_right₀ _ (two_ne_zero' ℂ)] + simp [evenKernel, re_eq_add_conj, jacobiTheta₂_conj, ← mul_two, + mul_div_cancel_right₀ _ (two_ne_zero' ℂ)] /-- For `x ≤ 0` the defining sum diverges, so the kernel is 0. -/ lemma evenKernel_undef (a : UnitAddCircle) {x : ℝ} (hx : x ≤ 0) : evenKernel a x = 0 := by - have : (I * ↑x).im ≤ 0 := by rwa [I_mul_im, ofReal_re] - induction' a using QuotientAddGroup.induction_on with a' - rw [← ofReal_inj, evenKernel_def, jacobiTheta₂_undef _ this, mul_zero, ofReal_zero] + induction a using QuotientAddGroup.induction_on with + | H a' => simp [← ofReal_inj, evenKernel_def, jacobiTheta₂_undef _ (by simpa : (I * ↑x).im ≤ 0)] /-- Cosine Hurwitz zeta kernel. See `cosKernel_def` for the defining formula, and `hasSum_int_cosKernel` for expression as a sum. -/ @[irreducible] def cosKernel (a : UnitAddCircle) (x : ℝ) : ℝ := (show Function.Periodic (fun ξ : ℝ ↦ re (jacobiTheta₂ ξ (I * x))) 1 by - intro ξ; simp_rw [ofReal_add, ofReal_one, jacobiTheta₂_add_left]).lift a + intro ξ; simp [jacobiTheta₂_add_left]).lift a lemma cosKernel_def (a x : ℝ) : ↑(cosKernel ↑a x) = jacobiTheta₂ a (I * x) := by - unfold cosKernel - simp only [Function.Periodic.lift_coe, re_eq_add_conj, jacobiTheta₂_conj, conj_ofReal, map_mul, - conj_I, neg_mul, neg_neg, ← mul_two, mul_div_cancel_right₀ _ (two_ne_zero' ℂ)] + simp [cosKernel, re_eq_add_conj, jacobiTheta₂_conj, ← mul_two, + mul_div_cancel_right₀ _ (two_ne_zero' ℂ)] lemma cosKernel_undef (a : UnitAddCircle) {x : ℝ} (hx : x ≤ 0) : cosKernel a x = 0 := by - induction' a using QuotientAddGroup.induction_on with a' - rw [← ofReal_inj, cosKernel_def, jacobiTheta₂_undef _ (by rwa [I_mul_im, ofReal_re]), ofReal_zero] + induction a using QuotientAddGroup.induction_on with + | H => simp [← ofReal_inj, cosKernel_def, jacobiTheta₂_undef _ (by simpa : (I * ↑x).im ≤ 0)] /-- For `a = 0`, both kernels agree. -/ lemma evenKernel_eq_cosKernel_of_zero : evenKernel 0 = cosKernel 0 := by ext1 x - simp only [← QuotientAddGroup.mk_zero, ← ofReal_inj, evenKernel_def, ofReal_zero, sq, mul_zero, - zero_mul, Complex.exp_zero, one_mul, cosKernel_def] + simp [← QuotientAddGroup.mk_zero, ← ofReal_inj, evenKernel_def, cosKernel_def] +@[simp] lemma evenKernel_neg (a : UnitAddCircle) (x : ℝ) : evenKernel (-a) x = evenKernel a x := by - induction' a using QuotientAddGroup.induction_on with a' - simp only [← QuotientAddGroup.mk_neg, ← ofReal_inj, evenKernel_def, ofReal_neg, neg_sq, neg_mul, - jacobiTheta₂_neg_left] + induction a using QuotientAddGroup.induction_on with + | H => simp [← QuotientAddGroup.mk_neg, ← ofReal_inj, evenKernel_def, jacobiTheta₂_neg_left] +@[simp] lemma cosKernel_neg (a : UnitAddCircle) (x : ℝ) : cosKernel (-a) x = cosKernel a x := by - induction' a using QuotientAddGroup.induction_on with a' - simp only [← QuotientAddGroup.mk_neg, ← ofReal_inj, cosKernel_def, ofReal_neg, - jacobiTheta₂_neg_left] + induction a using QuotientAddGroup.induction_on with + | H => simp [← QuotientAddGroup.mk_neg, ← ofReal_inj, cosKernel_def] lemma continuousOn_evenKernel (a : UnitAddCircle) : ContinuousOn (evenKernel a) (Ioi 0) := by induction' a using QuotientAddGroup.induction_on with a' apply continuous_re.comp_continuousOn (f := fun x ↦ (evenKernel a' x : ℂ)) - simp only [evenKernel_def a'] - refine continuousOn_of_forall_continuousAt (fun x hx ↦ ((Continuous.continuousAt ?_).mul ?_)) - · exact Complex.continuous_exp.comp (continuous_const.mul continuous_ofReal) - · have h := continuousAt_jacobiTheta₂ (a' * I * x) (?_ : 0 < im (I * x)) - · exact h.comp (f := fun u : ℝ ↦ (a' * I * u, I * u)) (by fun_prop) - · rwa [mul_im, I_re, I_im, zero_mul, one_mul, zero_add, ofReal_re] + simp only [evenKernel_def] + refine continuousOn_of_forall_continuousAt (fun x hx ↦ .mul (by fun_prop) ?_) + exact (continuousAt_jacobiTheta₂ (a' * I * x) <| by simpa).comp + (f := fun u : ℝ ↦ (a' * I * u, I * u)) (by fun_prop) lemma continuousOn_cosKernel (a : UnitAddCircle) : ContinuousOn (cosKernel a) (Ioi 0) := by induction' a using QuotientAddGroup.induction_on with a' apply continuous_re.comp_continuousOn (f := fun x ↦ (cosKernel a' x : ℂ)) simp only [cosKernel_def] refine continuousOn_of_forall_continuousAt (fun x hx ↦ ?_) - have : 0 < im (I * x) := by rwa [mul_im, I_re, I_im, zero_mul, one_mul, zero_add, ofReal_re] - exact (continuousAt_jacobiTheta₂ a' this).comp - (g := fun p : ℂ × ℂ ↦ jacobiTheta₂ p.1 p.2) - (f := fun u : ℝ ↦ ((a' : ℂ), I * u)) - (by fun_prop) + exact (continuousAt_jacobiTheta₂ a' <| by simpa).comp + (f := fun u : ℝ ↦ ((a' : ℂ), I * u)) (by fun_prop) lemma evenKernel_functional_equation (a : UnitAddCircle) (x : ℝ) : evenKernel a x = 1 / x ^ (1 / 2 : ℝ) * cosKernel a (1 / x) := by @@ -170,27 +159,22 @@ section asymp lemma hasSum_int_evenKernel (a : ℝ) {t : ℝ} (ht : 0 < t) : HasSum (fun n : ℤ ↦ rexp (-π * (n + a) ^ 2 * t)) (evenKernel a t) := by rw [← hasSum_ofReal, evenKernel_def] - have (n : ℤ) : ↑(rexp (-π * (↑n + a) ^ 2 * t)) = - cexp (-↑π * ↑a ^ 2 * ↑t) * jacobiTheta₂_term n (↑a * I * ↑t) (I * ↑t) := by + have (n : ℤ) : cexp (-(π * (n + a) ^ 2 * t)) = cexp (-(π * a ^ 2 * t)) * + jacobiTheta₂_term n (a * I * t) (I * t) := by rw [jacobiTheta₂_term, ← Complex.exp_add] - push_cast - congr ring_nf - simp only [I_sq, mul_neg, neg_mul, mul_one] - simp only [this] - apply (hasSum_jacobiTheta₂_term _ (by rwa [I_mul_im, ofReal_re])).mul_left + simp + simpa [this] using (hasSum_jacobiTheta₂_term _ (by simpa)).mul_left _ lemma hasSum_int_cosKernel (a : ℝ) {t : ℝ} (ht : 0 < t) : HasSum (fun n : ℤ ↦ cexp (2 * π * I * a * n) * rexp (-π * n ^ 2 * t)) ↑(cosKernel a t) := by rw [cosKernel_def a t] - have (n : ℤ) : cexp (2 * ↑π * I * ↑a * ↑n) * ↑(rexp (-π * ↑n ^ 2 * t)) = - jacobiTheta₂_term n (↑a) (I * ↑t) := by - rw [jacobiTheta₂_term, ofReal_exp, ← Complex.exp_add] - push_cast + have (n : ℤ) : cexp (2 * π * I * a * n) * cexp (-(π * n ^ 2 * t)) = + jacobiTheta₂_term n a (I * ↑t) := by + rw [jacobiTheta₂_term, ← Complex.exp_add] ring_nf - simp only [I_sq, mul_neg, neg_mul, mul_one, sub_eq_add_neg] - simp only [this] - exact hasSum_jacobiTheta₂_term _ (by rwa [I_mul_im, ofReal_re]) + simp [sub_eq_add_neg] + simpa [this] using hasSum_jacobiTheta₂_term _ (by simpa) /-- Modified version of `hasSum_int_evenKernel` omitting the constant term at `∞`. -/ lemma hasSum_int_evenKernel₀ (a : ℝ) {t : ℝ} (ht : 0 < t) : @@ -200,23 +184,17 @@ lemma hasSum_int_evenKernel₀ (a : ℝ) {t : ℝ} (ht : 0 < t) : simp_rw [AddCircle.coe_eq_zero_iff, zsmul_one] split_ifs with h · obtain ⟨k, rfl⟩ := h - simp_rw [← Int.cast_add, Int.cast_eq_zero, add_eq_zero_iff_eq_neg] - simpa only [Int.cast_add, neg_mul, Int.cast_neg, neg_add_cancel, ne_eq, OfNat.ofNat_ne_zero, - not_false_eq_true, zero_pow, mul_zero, zero_mul, Real.exp_zero] + simpa [← Int.cast_add, add_eq_zero_iff_eq_neg] using hasSum_ite_sub_hasSum (hasSum_int_evenKernel (k : ℝ) ht) (-k) · suffices ∀ (n : ℤ), n + a ≠ 0 by simpa [this] using hasSum_int_evenKernel a ht contrapose! h let ⟨n, hn⟩ := h - exact ⟨-n, by rwa [Int.cast_neg, neg_eq_iff_add_eq_zero]⟩ + exact ⟨-n, by simpa [neg_eq_iff_add_eq_zero]⟩ lemma hasSum_int_cosKernel₀ (a : ℝ) {t : ℝ} (ht : 0 < t) : HasSum (fun n : ℤ ↦ if n = 0 then 0 else cexp (2 * π * I * a * n) * rexp (-π * n ^ 2 * t)) (↑(cosKernel a t) - 1) := by - simpa? using hasSum_ite_sub_hasSum (hasSum_int_cosKernel a ht) 0 - says simpa only [neg_mul, ofReal_exp, ofReal_neg, ofReal_mul, ofReal_pow, ofReal_intCast, - Int.cast_zero, mul_zero, Complex.exp_zero, ne_eq, OfNat.ofNat_ne_zero, not_false_eq_true, - zero_pow, zero_mul, Real.exp_zero, ofReal_one, mul_one] using - hasSum_ite_sub_hasSum (hasSum_int_cosKernel a ht) 0 + simpa using hasSum_ite_sub_hasSum (hasSum_int_cosKernel a ht) 0 lemma hasSum_nat_cosKernel₀ (a : ℝ) {t : ℝ} (ht : 0 < t) : HasSum (fun n : ℕ ↦ 2 * Real.cos (2 * π * a * (n + 1)) * rexp (-π * (n + 1) ^ 2 * t)) @@ -244,9 +222,8 @@ lemma isBigO_atTop_evenKernel_sub (a : UnitAddCircle) : ∃ p : ℝ, 0 < p ∧ induction' a using QuotientAddGroup.induction_on with b obtain ⟨p, hp, hp'⟩ := HurwitzKernelBounds.isBigO_atTop_F_int_zero_sub b refine ⟨p, hp, (EventuallyEq.isBigO ?_).trans hp'⟩ - filter_upwards [eventually_gt_atTop 0] with t ht - simp only [← (hasSum_int_evenKernel b ht).tsum_eq, HurwitzKernelBounds.F_int, - HurwitzKernelBounds.f_int, pow_zero, one_mul, Function.Periodic.lift_coe] + filter_upwards [eventually_gt_atTop 0] with t h + simp [← (hasSum_int_evenKernel b h).tsum_eq, HurwitzKernelBounds.F_int, HurwitzKernelBounds.f_int] /-- The function `cosKernel a - 1` has exponential decay at `+∞`, for any `a`. -/ lemma isBigO_atTop_cosKernel_sub (a : UnitAddCircle) : @@ -254,9 +231,9 @@ lemma isBigO_atTop_cosKernel_sub (a : UnitAddCircle) : induction' a using QuotientAddGroup.induction_on with a obtain ⟨p, hp, hp'⟩ := HurwitzKernelBounds.isBigO_atTop_F_nat_zero_sub zero_le_one refine ⟨p, hp, (Eventually.isBigO ?_).trans (hp'.const_mul_left 2)⟩ - simp only [eq_false_intro one_ne_zero, if_false, sub_zero] filter_upwards [eventually_gt_atTop 0] with t ht - rw [← (hasSum_nat_cosKernel₀ a ht).tsum_eq, HurwitzKernelBounds.F_nat] + simp only [eq_false_intro one_ne_zero, if_false, sub_zero, + ← (hasSum_nat_cosKernel₀ a ht).tsum_eq, HurwitzKernelBounds.F_nat] apply tsum_of_norm_bounded ((HurwitzKernelBounds.summable_f_nat 0 1 ht).hasSum.mul_left 2) intro n rw [norm_mul, norm_mul, norm_two, mul_assoc, mul_le_mul_iff_of_pos_left two_pos, @@ -291,23 +268,19 @@ def hurwitzEvenFEPair (a : UnitAddCircle) : WeakFEPair ℂ where hg_top r := by obtain ⟨p, hp, hp'⟩ := isBigO_atTop_cosKernel_sub a rw [← isBigO_norm_left] at hp' ⊢ - have (x : ℝ) : ‖(ofReal ∘ cosKernel a) x - 1‖ = ‖cosKernel a x - 1‖ := by - rw [← norm_real, ofReal_sub, ofReal_one, Function.comp_apply] - simp only [this] - exact hp'.trans (isLittleO_exp_neg_mul_rpow_atTop hp _).isBigO - h_feq x hx := by - simp_rw [Function.comp_apply, one_mul, smul_eq_mul, ← ofReal_mul, - evenKernel_functional_equation, one_div x, one_div x⁻¹, inv_rpow (le_of_lt hx), - one_div, inv_inv] + simpa [← abs_ofReal] using hp'.trans (isLittleO_exp_neg_mul_rpow_atTop hp _).isBigO + h_feq x hx := by simp [← ofReal_mul, evenKernel_functional_equation, inv_rpow (le_of_lt hx)] +@[simp] lemma hurwitzEvenFEPair_zero_symm : (hurwitzEvenFEPair 0).symm = hurwitzEvenFEPair 0 := by unfold hurwitzEvenFEPair WeakFEPair.symm - congr 1 <;> simp only [evenKernel_eq_cosKernel_of_zero, inv_one, if_true] + congr 1 <;> simp [evenKernel_eq_cosKernel_of_zero] +@[simp] lemma hurwitzEvenFEPair_neg (a : UnitAddCircle) : hurwitzEvenFEPair (-a) = hurwitzEvenFEPair a := by unfold hurwitzEvenFEPair - congr 1 <;> simp only [Function.comp_def, evenKernel_neg, cosKernel_neg, neg_eq_zero] + congr 1 <;> simp [Function.comp_def] /-! ## Definition of the completed even Hurwitz zeta function @@ -364,21 +337,25 @@ lemma completedCosZeta_eq (a : UnitAddCircle) (s : ℂ) : ## Parity and functional equations -/ +@[simp] lemma completedHurwitzZetaEven_neg (a : UnitAddCircle) (s : ℂ) : completedHurwitzZetaEven (-a) s = completedHurwitzZetaEven a s := by - simp only [completedHurwitzZetaEven, hurwitzEvenFEPair_neg] + simp [completedHurwitzZetaEven] +@[simp] lemma completedHurwitzZetaEven₀_neg (a : UnitAddCircle) (s : ℂ) : completedHurwitzZetaEven₀ (-a) s = completedHurwitzZetaEven₀ a s := by - simp only [completedHurwitzZetaEven₀, hurwitzEvenFEPair_neg] + simp [completedHurwitzZetaEven₀] +@[simp] lemma completedCosZeta_neg (a : UnitAddCircle) (s : ℂ) : completedCosZeta (-a) s = completedCosZeta a s := by - simp only [completedCosZeta, hurwitzEvenFEPair_neg] + simp [completedCosZeta] +@[simp] lemma completedCosZeta₀_neg (a : UnitAddCircle) (s : ℂ) : completedCosZeta₀ (-a) s = completedCosZeta₀ a s := by - simp only [completedCosZeta₀, hurwitzEvenFEPair_neg] + simp [completedCosZeta₀] /-- Functional equation for the even Hurwitz zeta function. -/ lemma completedHurwitzZetaEven_one_sub (a : UnitAddCircle) (s : ℂ) : @@ -427,10 +404,8 @@ lemma differentiableAt_completedHurwitzZetaEven DifferentiableAt ℂ (completedHurwitzZetaEven a) s := by refine (((hurwitzEvenFEPair a).differentiableAt_Λ ?_ (Or.inl ?_)).comp s (differentiableAt_id.div_const _)).div_const _ - · simp only [ne_eq, div_eq_zero_iff, OfNat.ofNat_ne_zero, or_false] - rcases hs with h | h - · exact Or.inl h - · simp only [hurwitzEvenFEPair, one_div, h, ↓reduceIte, or_true] + · rcases hs with h | h <;> + simp [hurwitzEvenFEPair, h] · change s / 2 ≠ ↑(1 / 2 : ℝ) rw [ofReal_div, ofReal_one, ofReal_ofNat] exact hs' ∘ (div_left_inj' two_ne_zero).mp @@ -460,8 +435,8 @@ lemma differentiableAt_completedCosZeta · exact div_ne_zero_iff.mpr ⟨hs, two_ne_zero⟩ · change s / 2 ≠ ↑(1 / 2 : ℝ) ∨ (if a = 0 then 1 else 0) = 0 refine Or.imp (fun h ↦ ?_) (fun ha ↦ ?_) hs' - · simpa only [push_cast] using h ∘ (div_left_inj' two_ne_zero).mp - · simp_rw [eq_false_intro ha, if_false] + · simpa [push_cast] using h ∘ (div_left_inj' two_ne_zero).mp + · simpa lemma differentiable_completedCosZeta₀ (a : UnitAddCircle) : Differentiable ℂ (completedCosZeta₀ a) := @@ -489,14 +464,14 @@ lemma completedHurwitzZetaEven_residue_zero (a : UnitAddCircle) : have : -(if a = 0 then (1 : ℂ) else 0) = (if a = 0 then -1 else 0) := by { split_ifs <;> simp } simp only [this, push_cast, one_mul] at h1 refine (h1.comp <| zero_div (2 : ℂ) ▸ (tendsto_div_two_punctured_nhds 0)).congr (fun s ↦ ?_) - rw [completedHurwitzZetaEven, Function.comp_apply, div_mul_eq_mul_div, mul_div_assoc] + simp [completedHurwitzZetaEven, div_mul_eq_mul_div, mul_div_assoc] lemma completedCosZeta_residue_zero (a : UnitAddCircle) : Tendsto (fun s ↦ s * completedCosZeta a s) (𝓝[≠] 0) (𝓝 (-1)) := by have h1 : Tendsto (fun s : ℂ ↦ s * _) (𝓝[≠] 0) (𝓝 (-1)) := (hurwitzEvenFEPair a).symm.Λ_residue_zero refine (h1.comp <| zero_div (2 : ℂ) ▸ (tendsto_div_two_punctured_nhds 0)).congr (fun s ↦ ?_) - rw [completedCosZeta, Function.comp_apply, div_mul_eq_mul_div, mul_div_assoc] + simp [completedCosZeta, div_mul_eq_mul_div, mul_div_assoc] end FEPair @@ -513,7 +488,7 @@ lemma hasSum_int_completedCosZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : have hF t (ht : 0 < t) : HasSum (fun n : ℤ ↦ if n = 0 then 0 else c n * rexp (-π * n ^ 2 * t)) ((cosKernel a t - 1) / 2) := by refine ((hasSum_int_cosKernel₀ a ht).div_const 2).congr_fun fun n ↦ ?_ - split_ifs <;> simp only [zero_div, c, div_mul_eq_mul_div] + split_ifs <;> simp [c, div_mul_eq_mul_div] simp only [← Int.cast_eq_zero (α := ℝ)] at hF rw [show completedCosZeta a s = mellin (fun t ↦ (cosKernel a t - 1 : ℂ) / 2) (s / 2) by rw [mellin_div_const, completedCosZeta] @@ -526,7 +501,7 @@ lemma hasSum_int_completedCosZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : simp only [c, (by { push_cast; ring } : 2 * π * I * a * i = ↑(2 * π * a * i) * I), norm_div, RCLike.norm_ofNat, norm_norm, Complex.norm_exp_ofReal_mul_I, add_zero, norm_one, norm_of_nonneg (by positivity : 0 ≤ |(i : ℝ)| ^ s.re), div_right_comm, le_rfl] - · simp only [c, Int.cast_eq_zero, ← Int.cast_abs, ofReal_intCast, div_right_comm, mul_div_assoc] + · simp [c, ← Int.cast_abs, div_right_comm, mul_div_assoc] /-- Formula for `completedCosZeta` as a Dirichlet series in the convergence range (second version, with sum over `ℕ`). -/ @@ -586,7 +561,7 @@ lemma differentiableAt_update_of_residue · -- Easy case : `s ≠ 0` refine (claim s hs hs').congr_of_eventuallyEq ?_ filter_upwards [isOpen_compl_singleton.mem_nhds hs] with x hx - simp only [Function.update_of_ne hx] + simp [Function.update_of_ne hx] · -- Hard case : `s = 0` simp_rw [← claim2.limUnder_eq] have S_nhds : {(1 : ℂ)}ᶜ ∈ 𝓝 (0 : ℂ) := isOpen_compl_singleton.mem_nhds hs' @@ -608,11 +583,9 @@ noncomputable def hurwitzZetaEven (a : UnitAddCircle) := lemma hurwitzZetaEven_def_of_ne_or_ne {a : UnitAddCircle} {s : ℂ} (h : a ≠ 0 ∨ s ≠ 0) : hurwitzZetaEven a s = completedHurwitzZetaEven a s / Gammaℝ s := by rw [hurwitzZetaEven] - rcases ne_or_eq s 0 with h | rfl - · rw [Function.update_of_ne h] - · simpa only [Gammaℝ, Function.update_self, neg_zero, zero_div, cpow_zero, Complex.Gamma_zero, - mul_zero, div_zero, ite_eq_right_iff, div_eq_zero_iff, neg_eq_zero, one_ne_zero, - OfNat.ofNat_ne_zero, or_self, imp_false, ne_eq, not_true_eq_false, or_false] using h + rcases ne_or_eq s 0 with h' | rfl + · rw [Function.update_of_ne h'] + · simpa [Gammaℝ] using h lemma hurwitzZetaEven_apply_zero (a : UnitAddCircle) : hurwitzZetaEven a 0 = if a = 0 then -1 / 2 else 0 := @@ -620,15 +593,15 @@ lemma hurwitzZetaEven_apply_zero (a : UnitAddCircle) : lemma hurwitzZetaEven_neg (a : UnitAddCircle) (s : ℂ) : hurwitzZetaEven (-a) s = hurwitzZetaEven a s := by - simp_rw [hurwitzZetaEven, neg_eq_zero, completedHurwitzZetaEven_neg] + simp [hurwitzZetaEven] /-- The trivial zeroes of the even Hurwitz zeta function. -/ theorem hurwitzZetaEven_neg_two_mul_nat_add_one (a : UnitAddCircle) (n : ℕ) : hurwitzZetaEven a (-2 * (n + 1)) = 0 := by have : (-2 : ℂ) * (n + 1) ≠ 0 := mul_ne_zero (neg_ne_zero.mpr two_ne_zero) (Nat.cast_add_one_ne_zero n) - rw [hurwitzZetaEven, Function.update_of_ne this, - Gammaℝ_eq_zero_iff.mpr ⟨n + 1, by rw [neg_mul, Nat.cast_add_one]⟩, div_zero] + rw [hurwitzZetaEven, Function.update_of_ne this, Gammaℝ_eq_zero_iff.mpr ⟨n + 1, by simp⟩, + div_zero] /-- The Hurwitz zeta function is differentiable everywhere except at `s = 1`. This is true even in the delicate case `a = 0` and `s = 0` (where the completed zeta has a pole, but this is @@ -648,7 +621,7 @@ lemma hurwitzZetaEven_residue_one (a : UnitAddCircle) : <| (differentiable_Gammaℝ_inv.continuous.tendsto _).mono_left nhdsWithin_le_nhds refine this.congr' ?_ filter_upwards [eventually_ne_nhdsWithin one_ne_zero] with s hs - simp_rw [hurwitzZetaEven_def_of_ne_or_ne (Or.inr hs), mul_div_assoc] + simp [hurwitzZetaEven_def_of_ne_or_ne (Or.inr hs), mul_div_assoc] lemma differentiableAt_hurwitzZetaEven_sub_one_div (a : UnitAddCircle) : DifferentiableAt ℂ (fun s ↦ hurwitzZetaEven a s - 1 / (s - 1) / Gammaℝ s) 1 := by @@ -670,8 +643,7 @@ determining what that value is). -/ lemma tendsto_hurwitzZetaEven_sub_one_div_nhds_one (a : UnitAddCircle) : Tendsto (fun s ↦ hurwitzZetaEven a s - 1 / (s - 1) / Gammaℝ s) (𝓝 1) (𝓝 (hurwitzZetaEven a 1)) := by - simpa only [one_div, sub_self, div_zero, Gammaℝ_one, div_one, sub_zero] using - (differentiableAt_hurwitzZetaEven_sub_one_div a).continuousAt.tendsto + simpa using (differentiableAt_hurwitzZetaEven_sub_one_div a).continuousAt.tendsto lemma differentiable_hurwitzZetaEven_sub_hurwitzZetaEven (a b : UnitAddCircle) : Differentiable ℂ (fun s ↦ hurwitzZetaEven a s - hurwitzZetaEven b s) := by @@ -698,8 +670,7 @@ lemma hasSum_nat_hurwitzZetaEven (a : ℝ) {s : ℂ} (hs : 1 < re s) : HasSum (fun n : ℕ ↦ (1 / (↑|n + a| : ℂ) ^ s + 1 / (↑|n + 1 - a| : ℂ) ^ s) / 2) (hurwitzZetaEven a s) := by refine (hasSum_int_hurwitzZetaEven a hs).nat_add_neg_add_one.congr_fun fun n ↦ ?_ - simp only [← abs_neg (n + 1 - a), neg_sub', sub_neg_eq_add, add_div, Int.cast_natCast, - Int.cast_neg, Int.cast_add, Int.cast_one] + simp [← abs_neg (n + 1 - a), -neg_sub, neg_sub', add_div] /-- Formula for `hurwitzZetaEven` as a Dirichlet series in the convergence range, with sum over `ℕ` (version without absolute values, assuming `a ∈ Icc 0 1`) -/ @@ -709,7 +680,7 @@ lemma hasSum_nat_hurwitzZetaEven_of_mem_Icc {a : ℝ} (ha : a ∈ Icc 0 1) {s : refine (hasSum_nat_hurwitzZetaEven a hs).congr_fun fun n ↦ ?_ congr 2 <;> rw [_root_.abs_of_nonneg (by linarith [ha.1, ha.2])] <;> - simp only [one_div, ofReal_sub, ofReal_add, ofReal_natCast, ofReal_one] + simp /-! ## The un-completed cosine zeta @@ -725,7 +696,7 @@ lemma cosZeta_apply_zero (a : UnitAddCircle) : cosZeta a 0 = -1 / 2 := lemma cosZeta_neg (a : UnitAddCircle) (s : ℂ) : cosZeta (-a) s = cosZeta a s := by - simp_rw [cosZeta, completedCosZeta_neg] + simp [cosZeta] /-- The trivial zeroes of the cosine zeta function. -/ theorem cosZeta_neg_two_mul_nat_add_one (a : UnitAddCircle) (n : ℕ) : @@ -744,7 +715,7 @@ lemma differentiableAt_cosZeta (a : UnitAddCircle) {s : ℂ} (hs' : s ≠ 1 ∨ · apply ((differentiableAt_completedCosZeta a one_ne_zero hs').mul (differentiable_Gammaℝ_inv.differentiableAt)).congr_of_eventuallyEq filter_upwards [isOpen_compl_singleton.mem_nhds one_ne_zero] with x hx - simp_rw [cosZeta, Function.update_of_ne hx, div_eq_mul_inv] + rw [cosZeta, Function.update_of_ne hx, div_eq_mul_inv] /-- If `a ≠ 0` then the cosine zeta function is entire. -/ lemma differentiable_cosZeta_of_ne_zero {a : UnitAddCircle} (ha : a ≠ 0) : @@ -772,8 +743,7 @@ lemma hasSum_nat_cosZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : /-- Reformulation of `hasSum_nat_cosZeta` using `LSeriesHasSum`. -/ lemma LSeriesHasSum_cos (a : ℝ) {s : ℂ} (hs : 1 < re s) : LSeriesHasSum (Real.cos <| 2 * π * a * ·) s (cosZeta a s) := - (hasSum_nat_cosZeta a hs).congr_fun - (LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs) _) + (hasSum_nat_cosZeta a hs).congr_fun (LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs) _) /-! ## Functional equations for the un-completed zetas diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean b/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean index f59d387a00ae8..3b3b699c56df4 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean @@ -59,9 +59,8 @@ def jacobiTheta₂'' (z τ : ℂ) : ℂ := lemma jacobiTheta₂''_conj (z τ : ℂ) : conj (jacobiTheta₂'' z τ) = jacobiTheta₂'' (conj z) (-conj τ) := by - simp only [jacobiTheta₂'', jacobiTheta₂'_conj, jacobiTheta₂_conj, - ← exp_conj, conj_ofReal, conj_I, map_mul, map_add, map_div₀, mul_neg, map_pow, map_ofNat, - neg_mul, div_neg, neg_div, jacobiTheta₂'_neg_left, jacobiTheta₂_neg_left] + simp [jacobiTheta₂'', jacobiTheta₂'_conj, jacobiTheta₂_conj, ← exp_conj, map_ofNat, div_neg, + neg_div, jacobiTheta₂'_neg_left] /-- Restatement of `jacobiTheta₂'_add_left'`: the function `jacobiTheta₂''` is 1-periodic in `z`. -/ lemma jacobiTheta₂''_add_left (z τ : ℂ) : jacobiTheta₂'' (z + 1) τ = jacobiTheta₂'' z τ := by @@ -77,8 +76,7 @@ lemma jacobiTheta₂''_add_left (z τ : ℂ) : jacobiTheta₂'' (z + 1) τ = jac congrm (cexp ?_ * ?_) <;> ring lemma jacobiTheta₂''_neg_left (z τ : ℂ) : jacobiTheta₂'' (-z) τ = -jacobiTheta₂'' z τ := by - simp only [jacobiTheta₂'', jacobiTheta₂'_neg_left, jacobiTheta₂_neg_left, - neg_mul, neg_div, ← neg_add, mul_neg, neg_sq] + simp [jacobiTheta₂'', jacobiTheta₂'_neg_left, neg_div, -neg_add_rev, ← neg_add] lemma jacobiTheta₂'_functional_equation' (z τ : ℂ) : jacobiTheta₂' z τ = (-2 * π) / (-I * τ) ^ (3 / 2 : ℂ) * jacobiTheta₂'' z (-1 / τ) := by @@ -107,11 +105,10 @@ for an expression as a sum over `ℤ`. -/ @[irreducible] def oddKernel (a : UnitAddCircle) (x : ℝ) : ℝ := (show Function.Periodic (fun a : ℝ ↦ re (jacobiTheta₂'' a (I * x))) 1 by - intro a; simp only [ofReal_add, ofReal_one, jacobiTheta₂''_add_left]).lift a + intro a; simp [jacobiTheta₂''_add_left]).lift a lemma oddKernel_def (a x : ℝ) : ↑(oddKernel a x) = jacobiTheta₂'' a (I * x) := by - rw [oddKernel, Function.Periodic.lift_coe, ← conj_eq_iff_re, jacobiTheta₂''_conj, map_mul, - conj_I, neg_mul, neg_neg, conj_ofReal, conj_ofReal] + simp [oddKernel, ← conj_eq_iff_re, jacobiTheta₂''_conj] lemma oddKernel_def' (a x : ℝ) : ↑(oddKernel ↑a x) = cexp (-π * a ^ 2 * x) * (jacobiTheta₂' (a * I * x) (I * x) / (2 * π * I) + a * jacobiTheta₂ (a * I * x) (I * x)) := by @@ -122,40 +119,37 @@ lemma oddKernel_undef (a : UnitAddCircle) {x : ℝ} (hx : x ≤ 0) : oddKernel a induction' a using QuotientAddGroup.induction_on with a' rw [← ofReal_eq_zero, oddKernel_def', jacobiTheta₂_undef, jacobiTheta₂'_undef, zero_div, zero_add, mul_zero, mul_zero] <;> - rwa [I_mul_im, ofReal_re] + simpa /-- Auxiliary function appearing in the functional equation for the odd Hurwitz zeta kernel, equal to `∑ (n : ℕ), 2 * n * sin (2 * π * n * a) * exp (-π * n ^ 2 * x)`. See `hasSum_nat_sinKernel` for the defining sum. -/ @[irreducible] def sinKernel (a : UnitAddCircle) (x : ℝ) : ℝ := (show Function.Periodic (fun ξ : ℝ ↦ re (jacobiTheta₂' ξ (I * x) / (-2 * π))) 1 by - intro ξ; simp_rw [ofReal_add, ofReal_one, jacobiTheta₂'_add_left]).lift a + intro ξ; simp [jacobiTheta₂'_add_left]).lift a lemma sinKernel_def (a x : ℝ) : ↑(sinKernel ↑a x) = jacobiTheta₂' a (I * x) / (-2 * π) := by - rw [sinKernel, Function.Periodic.lift_coe, re_eq_add_conj, map_div₀, jacobiTheta₂'_conj] - simp_rw [map_mul, conj_I, conj_ofReal, map_neg, map_ofNat, neg_mul, neg_neg, add_self_div_two] + simp [sinKernel, re_eq_add_conj, jacobiTheta₂'_conj, map_ofNat] lemma sinKernel_undef (a : UnitAddCircle) {x : ℝ} (hx : x ≤ 0) : sinKernel a x = 0 := by - induction' a using QuotientAddGroup.induction_on with a' - rw [← ofReal_eq_zero, sinKernel_def, jacobiTheta₂'_undef _ (by rwa [I_mul_im, ofReal_re]), - zero_div] + induction a using QuotientAddGroup.induction_on with + | H a => rw [← ofReal_eq_zero, sinKernel_def, jacobiTheta₂'_undef _ (by simpa), zero_div] lemma oddKernel_neg (a : UnitAddCircle) (x : ℝ) : oddKernel (-a) x = -oddKernel a x := by - induction' a using QuotientAddGroup.induction_on with a' - rw [← ofReal_inj, ← QuotientAddGroup.mk_neg, oddKernel_def, ofReal_neg, ofReal_neg, oddKernel_def, - jacobiTheta₂''_neg_left] + induction a using QuotientAddGroup.induction_on with + | H a => simp [← ofReal_inj, ← QuotientAddGroup.mk_neg, oddKernel_def, jacobiTheta₂''_neg_left] -lemma oddKernel_zero (x : ℝ) : oddKernel 0 x = 0 := by - simpa only [neg_zero, eq_neg_self_iff] using oddKernel_neg 0 x +@[simp] lemma oddKernel_zero (x : ℝ) : oddKernel 0 x = 0 := by + simpa using oddKernel_neg 0 x lemma sinKernel_neg (a : UnitAddCircle) (x : ℝ) : sinKernel (-a) x = -sinKernel a x := by - induction' a using QuotientAddGroup.induction_on with a' - rw [← ofReal_inj, ← QuotientAddGroup.mk_neg, ofReal_neg, sinKernel_def, sinKernel_def, ofReal_neg, - jacobiTheta₂'_neg_left, neg_div] + induction a using QuotientAddGroup.induction_on with + | H a => simp [← ofReal_inj, ← QuotientAddGroup.mk_neg, sinKernel_def, jacobiTheta₂'_neg_left, + neg_div] -lemma sinKernel_zero (x : ℝ) : sinKernel 0 x = 0 := by - simpa only [neg_zero, eq_neg_self_iff] using sinKernel_neg 0 x +@[simp] lemma sinKernel_zero (x : ℝ) : sinKernel 0 x = 0 := by + simpa using sinKernel_neg 0 x /-- The odd kernel is continuous on `Ioi 0`. -/ lemma continuousOn_oddKernel (a : UnitAddCircle) : ContinuousOn (oddKernel a) (Ioi 0) := by @@ -237,9 +231,9 @@ lemma hasSum_int_sinKernel (a : ℝ) {t : ℝ} (ht : 0 < t) : HasSum eq_div_iff h, ofReal_mul, ofReal_mul, ofReal_pow, ofReal_neg, ofReal_intCast, mul_comm _ (-2 * π : ℂ), ← mul_assoc] congrm ?_ * cexp (?_ + ?_) - · simp only [neg_mul, mul_neg, neg_neg, mul_assoc] + · simp [mul_assoc] · exact mul_right_comm (2 * π * I) a n - · simp only [← mul_assoc, mul_comm _ I, I_mul_I, neg_one_mul] + · simp [← mul_assoc, mul_comm _ I] lemma hasSum_nat_sinKernel (a : ℝ) {t : ℝ} (ht : 0 < t) : HasSum (fun n : ℕ ↦ 2 * n * Real.sin (2 * π * a * n) * rexp (-π * n ^ 2 * t)) @@ -271,8 +265,8 @@ lemma isBigO_atTop_oddKernel (a : UnitAddCircle) : obtain ⟨p, hp, hp'⟩ := HurwitzKernelBounds.isBigO_atTop_F_int_one b refine ⟨p, hp, (Eventually.isBigO ?_).trans hp'⟩ filter_upwards [eventually_gt_atTop 0] with t ht - simpa only [← (hasSum_int_oddKernel b ht).tsum_eq, Real.norm_eq_abs, HurwitzKernelBounds.F_int, - HurwitzKernelBounds.f_int, pow_one, norm_mul, abs_of_nonneg (exp_pos _).le] using + simpa [← (hasSum_int_oddKernel b ht).tsum_eq, HurwitzKernelBounds.F_int, + HurwitzKernelBounds.f_int, abs_of_nonneg (exp_pos _).le] using norm_tsum_le_tsum_norm (hasSum_int_oddKernel b ht).summable.norm /-- The function `sinKernel a` has exponential decay at `+∞`, for any `a`. -/ @@ -318,16 +312,12 @@ def hurwitzOddFEPair (a : UnitAddCircle) : StrongFEPair ℂ where hf_top r := by let ⟨v, hv, hv'⟩ := isBigO_atTop_oddKernel a rw [← isBigO_norm_left] at hv' ⊢ - simp_rw [Function.comp_def, sub_zero, norm_real] - exact hv'.trans (isLittleO_exp_neg_mul_rpow_atTop hv _).isBigO + simpa using hv'.trans (isLittleO_exp_neg_mul_rpow_atTop hv _).isBigO hg_top r := by let ⟨v, hv, hv'⟩ := isBigO_atTop_sinKernel a rw [← isBigO_norm_left] at hv' ⊢ - simp_rw [Function.comp_def, sub_zero, norm_real] - exact hv'.trans (isLittleO_exp_neg_mul_rpow_atTop hv _).isBigO - h_feq x hx := by simp_rw [Function.comp_apply, one_mul, smul_eq_mul, ← ofReal_mul, - oddKernel_functional_equation a, one_div x, one_div x⁻¹, inv_rpow (le_of_lt hx), one_div, - inv_inv] + simpa using hv'.trans (isLittleO_exp_neg_mul_rpow_atTop hv _).isBigO + h_feq x hx := by simp [← ofReal_mul, oddKernel_functional_equation a, inv_rpow (le_of_lt hx)] end FEPair @@ -365,16 +355,13 @@ lemma differentiable_completedSinZeta (a : UnitAddCircle) : lemma completedHurwitzZetaOdd_neg (a : UnitAddCircle) (s : ℂ) : completedHurwitzZetaOdd (-a) s = -completedHurwitzZetaOdd a s := by - simp only [completedHurwitzZetaOdd, StrongFEPair.Λ, hurwitzOddFEPair, mellin, Function.comp_def, - oddKernel_neg, ofReal_neg, smul_neg] - rw [integral_neg, neg_div] + simp [completedHurwitzZetaOdd, StrongFEPair.Λ, hurwitzOddFEPair, mellin, oddKernel_neg, + integral_neg, neg_div] lemma completedSinZeta_neg (a : UnitAddCircle) (s : ℂ) : completedSinZeta (-a) s = -completedSinZeta a s := by - simp only [completedSinZeta, StrongFEPair.Λ, mellin, StrongFEPair.symm, WeakFEPair.symm, - hurwitzOddFEPair, Function.comp_def, sinKernel_neg, ofReal_neg, smul_neg] - rw [integral_neg, neg_div] - + simp [completedSinZeta, StrongFEPair.Λ, mellin, StrongFEPair.symm, WeakFEPair.symm, + hurwitzOddFEPair, sinKernel_neg, integral_neg, neg_div] /-- Functional equation for the odd Hurwitz zeta function. -/ theorem completedHurwitzZetaOdd_one_sub (a : UnitAddCircle) (s : ℂ) : @@ -387,7 +374,7 @@ theorem completedHurwitzZetaOdd_one_sub (a : UnitAddCircle) (s : ℂ) : /-- Functional equation for the odd Hurwitz zeta function (alternative form). -/ lemma completedSinZeta_one_sub (a : UnitAddCircle) (s : ℂ) : completedSinZeta a (1 - s) = completedHurwitzZetaOdd a s := by - rw [← completedHurwitzZetaOdd_one_sub, sub_sub_cancel] + simp [← completedHurwitzZetaOdd_one_sub] /-! ## Relation to the Dirichlet series for `1 < re s` @@ -410,11 +397,10 @@ lemma hasSum_int_completedSinZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : simp_rw [hc, div_right_comm] apply Summable.div_const apply Summable.of_nat_of_neg <;> - · simp only [Int.cast_neg, abs_neg, Int.cast_natCast, Nat.abs_cast] - rwa [summable_one_div_nat_rpow] + simpa refine (mellin_div_const .. ▸ hasSum_mellin_pi_mul_sq' (zero_lt_one.trans hs) hF h_sum).congr_fun fun n ↦ ?_ - simp only [Int.sign_eq_sign, SignType.intCast_cast, sign_intCast, ← Int.cast_abs, ofReal_intCast] + simp [Int.sign_eq_sign, ← Int.cast_abs] -- non-terminal simp OK when `ring` follows ring /-- Formula for `completedSinZeta` as a Dirichlet series in the convergence range @@ -428,8 +414,7 @@ lemma hasSum_nat_completedSinZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : refine this.congr_fun fun n ↦ ?_ rw [div_right_comm] rcases eq_or_ne n 0 with rfl | h - · simp only [Nat.cast_zero, mul_zero, Real.sin_zero, ofReal_zero, zero_div, mul_neg, - Int.sign_zero, Int.cast_zero, Complex.exp_zero, mul_one, neg_zero, add_zero] + · simp simp_rw [Int.sign_natCast_of_ne_zero h, Int.cast_one, ofReal_sin, Complex.sin] simp only [← mul_div_assoc, push_cast, mul_assoc (Gammaℝ _), ← mul_add] congr 3 @@ -446,7 +431,7 @@ lemma hasSum_int_completedHurwitzZetaOdd (a : ℝ) {s : ℂ} (hs : 1 < re s) : have hF t (ht : 0 < t) : HasSum (fun n ↦ c n * r n * rexp (-π * (r n) ^ 2 * t)) (oddKernel a t / 2) := by refine ((hasSum_ofReal.mpr (hasSum_int_oddKernel a ht)).div_const 2).congr_fun fun n ↦ ?_ - simp only [r, c, push_cast, div_mul_eq_mul_div, one_mul] + simp [r, c, push_cast, div_mul_eq_mul_div, -one_div] have h_sum : Summable fun i ↦ ‖c i‖ / |r i| ^ s.re := by simp_rw [c, ← mul_one_div ‖_‖] apply Summable.mul_left @@ -494,7 +479,7 @@ theorem hasSum_int_hurwitzZetaOdd (a : ℝ) {s : ℂ} (hs : 1 < re s) : HasSum (fun n : ℤ ↦ SignType.sign (n + a) / (↑|n + a| : ℂ) ^ s / 2) (hurwitzZetaOdd a s) := by refine ((hasSum_int_completedHurwitzZetaOdd a hs).div_const (Gammaℝ _)).congr_fun fun n ↦ ?_ have : 0 < re (s + 1) := by rw [add_re, one_re]; positivity - simp only [div_right_comm _ _ (Gammaℝ _), mul_div_cancel_left₀ _ (Gammaℝ_ne_zero_of_re_pos this)] + simp [div_right_comm _ _ (Gammaℝ _), mul_div_cancel_left₀ _ (Gammaℝ_ne_zero_of_re_pos this)] /-- Formula for `hurwitzZetaOdd` as a Dirichlet series in the convergence range, with sum over `ℕ` (version with absolute values) -/ @@ -517,7 +502,7 @@ lemma hasSum_nat_hurwitzZetaOdd_of_mem_Icc {a : ℝ} (ha : a ∈ Icc 0 1) {s : intro b hb rw [abs_of_nonneg (by positivity), (by simp : (n : ℂ) + b = ↑(n + b))] rcases lt_or_eq_of_le (by positivity : 0 ≤ n + b) with hb | hb - · rw [sign_pos hb, SignType.coe_one] + · simp [sign_pos hb] · rw [← hb, ofReal_zero, zero_cpow ((not_lt.mpr zero_le_one) ∘ (zero_re ▸ · ▸ hs)), div_zero, div_zero] @@ -542,14 +527,12 @@ lemma hasSum_nat_sinZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : · simp only [neg_mul, sub_mul, div_right_comm _ (2 : ℂ), Int.sign_natCast_of_ne_zero h, Int.cast_one, mul_one, mul_comm I, neg_neg, ← add_div, ← sub_eq_neg_add] congr 5 <;> ring - · simp only [Nat.cast_zero, Int.sign_zero, Int.cast_zero, mul_zero, zero_mul, neg_zero, - sub_self, zero_div, zero_add] + · simp /-- Reformulation of `hasSum_nat_sinZeta` using `LSeriesHasSum`. -/ lemma LSeriesHasSum_sin (a : ℝ) {s : ℂ} (hs : 1 < re s) : LSeriesHasSum (Real.sin <| 2 * π * a * ·) s (sinZeta a s) := - (hasSum_nat_sinZeta a hs).congr_fun - (LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs) _) + (hasSum_nat_sinZeta a hs).congr_fun (LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs) _) /-- The trivial zeroes of the odd Hurwitz zeta function. -/ theorem hurwitzZetaOdd_neg_two_mul_nat_sub_one (a : UnitAddCircle) (n : ℕ) : diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZetaValues.lean b/Mathlib/NumberTheory/LSeries/HurwitzZetaValues.lean index a4fa533e22e11..d93259715b0d4 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZetaValues.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZetaValues.lean @@ -54,17 +54,15 @@ theorem cosZeta_two_mul_nat (hk : k ≠ 0) (hx : x ∈ Icc 0 1) : (congr_arg ofReal (hasSum_one_div_nat_pow_mul_cos hk hx).tsum_eq).trans ?_ · rw [ofReal_tsum] refine tsum_congr fun n ↦ ?_ - rw [mul_comm (1 / _), mul_one_div, ofReal_div, mul_assoc (2 * π), mul_comm x n, ← mul_assoc, - ← Nat.cast_ofNat (R := ℂ), ← Nat.cast_mul, cpow_natCast, ofReal_pow, ofReal_natCast] - · simp only [ofReal_mul, ofReal_div, ofReal_pow, ofReal_natCast, ofReal_ofNat, - ofReal_neg, ofReal_one] + norm_cast + ring_nf + · push_cast congr 1 have : (Polynomial.bernoulli (2 * k)).map (algebraMap ℚ ℂ) = _ := (Polynomial.map_map (algebraMap ℚ ℝ) ofRealHom _).symm rw [this, ← ofRealHom_eq_coe, ← ofRealHom_eq_coe] - apply Polynomial.map_aeval_eq_aeval_map - simp only [Algebra.id.map_eq_id, RingHomCompTriple.comp_eq] - · rw [← Nat.cast_ofNat, ← Nat.cast_one, ← Nat.cast_mul, natCast_re, Nat.cast_lt] + apply Polynomial.map_aeval_eq_aeval_map (by simp) + · norm_cast omega /-- @@ -82,21 +80,16 @@ theorem sinZeta_two_mul_nat_add_one (hk : k ≠ 0) (hx : x ∈ Icc 0 1) : (congr_arg ofReal (hasSum_one_div_nat_pow_mul_sin hk hx).tsum_eq).trans ?_ · rw [ofReal_tsum] refine tsum_congr fun n ↦ ?_ - rw [mul_comm (1 / _), mul_one_div, ofReal_div, mul_assoc (2 * π), mul_comm x n, ← mul_assoc] - congr 1 - rw [← Nat.cast_ofNat, ← Nat.cast_mul, ← Nat.cast_add_one, cpow_natCast, ofReal_pow, - ofReal_natCast] - · simp only [ofReal_mul, ofReal_div, ofReal_pow, ofReal_natCast, ofReal_ofNat, - ofReal_neg, ofReal_one] + norm_cast + ring_nf + · push_cast congr 1 have : (Polynomial.bernoulli (2 * k + 1)).map (algebraMap ℚ ℂ) = _ := (Polynomial.map_map (algebraMap ℚ ℝ) ofRealHom _).symm rw [this, ← ofRealHom_eq_coe, ← ofRealHom_eq_coe] - apply Polynomial.map_aeval_eq_aeval_map - simp only [Algebra.id.map_eq_id, RingHomCompTriple.comp_eq] - · rw [← Nat.cast_ofNat, ← Nat.cast_one, ← Nat.cast_mul, ← Nat.cast_add_one, natCast_re, - Nat.cast_lt, lt_add_iff_pos_left] - exact mul_pos two_pos (Nat.pos_of_ne_zero hk) + apply Polynomial.map_aeval_eq_aeval_map (by simp) + · norm_cast + omega /-- Reformulation of `cosZeta_two_mul_nat` using `Gammaℂ`. -/ theorem cosZeta_two_mul_nat' (hk : k ≠ 0) (hx : x ∈ Icc (0 : ℝ) 1) : @@ -133,12 +126,10 @@ theorem hurwitzZetaEven_one_sub_two_mul_nat (hk : k ≠ 0) (hx : x ∈ Icc (0 : Ne, Int.cast_inj, ← Ne] refine ne_of_gt ((neg_nonpos_of_nonneg n.cast_nonneg).trans_lt (mul_pos two_pos ?_)) exact Nat.cast_pos.mpr (Nat.pos_of_ne_zero hk) - have h2 : (2 * k : ℂ) ≠ 1 := by norm_cast; simp only [mul_eq_one, OfNat.ofNat_ne_one, - false_and, not_false_eq_true] + have h2 : (2 * k : ℂ) ≠ 1 := by norm_cast; simp have h3 : Gammaℂ (2 * k) ≠ 0 := by refine mul_ne_zero (mul_ne_zero two_ne_zero ?_) (Gamma_ne_zero h1) - simp only [ne_eq, cpow_eq_zero_iff, mul_eq_zero, OfNat.ofNat_ne_zero, ofReal_eq_zero, - pi_ne_zero, Nat.cast_eq_zero, false_or, false_and, not_false_eq_true] + simp [pi_ne_zero] rw [hurwitzZetaEven_one_sub _ h1 (Or.inr h2), ← Gammaℂ, cosZeta_two_mul_nat' hk hx, ← mul_assoc, ← mul_div_assoc, mul_assoc, mul_div_cancel_left₀ _ h3, ← mul_div_assoc] congr 2 @@ -157,8 +148,7 @@ theorem hurwitzZetaOdd_neg_two_mul_nat (hk : k ≠ 0) (hx : x ∈ Icc (0 : ℝ) positivity have h3 : Gammaℂ (2 * k + 1) ≠ 0 := by refine mul_ne_zero (mul_ne_zero two_ne_zero ?_) (Gamma_ne_zero h1) - simp only [ne_eq, cpow_eq_zero_iff, mul_eq_zero, OfNat.ofNat_ne_zero, ofReal_eq_zero, - pi_ne_zero, Nat.cast_eq_zero, false_or, false_and, not_false_eq_true] + simp [pi_ne_zero] rw [(by simp : -(2 * k : ℂ) = 1 - (2 * k + 1)), hurwitzZetaOdd_one_sub _ h1, ← Gammaℂ, sinZeta_two_mul_nat_add_one' hk hx, ← mul_assoc, ← mul_div_assoc, mul_assoc, mul_div_cancel_left₀ _ h3, ← mul_div_assoc] @@ -177,7 +167,7 @@ private lemma hurwitzZeta_one_sub_two_mul_nat (hk : k ≠ 0) (hx : x ∈ Icc (0 suffices hurwitzZetaOdd x (1 - 2 * k) = 0 by rw [hurwitzZeta, this, add_zero, hurwitzZetaEven_one_sub_two_mul_nat hk hx] obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero hk - rw [Nat.cast_succ, show (1 : ℂ) - 2 * (k + 1) = - 2 * k - 1 by ring, + rw [Nat.cast_succ, show (1 : ℂ) - 2 * (k + 1) = -2 * k - 1 by ring, hurwitzZetaOdd_neg_two_mul_nat_sub_one] -- private because it is superseded by `hurwitzZeta_neg_nat` below @@ -187,7 +177,7 @@ private lemma hurwitzZeta_neg_two_mul_nat (hk : k ≠ 0) (hx : x ∈ Icc (0 : suffices hurwitzZetaEven x (-(2 * k)) = 0 by rw [hurwitzZeta, this, zero_add, hurwitzZetaOdd_neg_two_mul_nat hk hx] obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero hk - simpa only [Nat.cast_succ, ← neg_mul] using hurwitzZetaEven_neg_two_mul_nat_add_one x k + simpa using hurwitzZetaEven_neg_two_mul_nat_add_one x k /-- Values of Hurwitz zeta functions at (strictly) negative integers. @@ -215,13 +205,13 @@ theorem riemannZeta_two_mul_nat {k : ℕ} (hk : k ≠ 0) : * (π : ℂ) ^ (2 * k) * bernoulli (2 * k) / (2 * k)! := by convert congr_arg ((↑) : ℝ → ℂ) (hasSum_zeta_nat hk).tsum_eq · rw [← Nat.cast_two, ← Nat.cast_mul, zeta_nat_eq_tsum_of_gt_one (by omega)] - simp only [push_cast] + simp [push_cast] · norm_cast theorem riemannZeta_two : riemannZeta 2 = (π : ℂ) ^ 2 / 6 := by convert congr_arg ((↑) : ℝ → ℂ) hasSum_zeta_two.tsum_eq · rw [← Nat.cast_two, zeta_nat_eq_tsum_of_gt_one one_lt_two] - simp only [push_cast] + simp [push_cast] · norm_cast theorem riemannZeta_four : riemannZeta 4 = π ^ 4 / 90 := by diff --git a/Mathlib/NumberTheory/LSeries/Linearity.lean b/Mathlib/NumberTheory/LSeries/Linearity.lean index cdb545f78c2fb..ea85d5fff3ed1 100644 --- a/Mathlib/NumberTheory/LSeries/Linearity.lean +++ b/Mathlib/NumberTheory/LSeries/Linearity.lean @@ -19,48 +19,46 @@ of both L-series when adding two functions). open LSeries lemma LSeries.term_add (f g : ℕ → ℂ) (s : ℂ) : term (f + g) s = term f s + term g s := by - ext ⟨- | n⟩ - · simp only [term_zero, Pi.add_apply, add_zero] - · simp only [term_of_ne_zero (Nat.succ_ne_zero _), Pi.add_apply, add_div] + ext ⟨- | n⟩ <;> + simp [add_div] lemma LSeries.term_add_apply (f g : ℕ → ℂ) (s : ℂ) (n : ℕ) : term (f + g) s n = term f s n + term g s n := by - rw [term_add, Pi.add_apply] + simp [term_add] lemma LSeriesHasSum.add {f g : ℕ → ℂ} {s a b : ℂ} (hf : LSeriesHasSum f s a) (hg : LSeriesHasSum g s b) : LSeriesHasSum (f + g) s (a + b) := by - simpa only [LSeriesHasSum, term_add] using HasSum.add hf hg + simpa [LSeriesHasSum, term_add] using HasSum.add hf hg lemma LSeriesSummable.add {f g : ℕ → ℂ} {s : ℂ} (hf : LSeriesSummable f s) (hg : LSeriesSummable g s) : LSeriesSummable (f + g) s := by - simpa only [LSeriesSummable, ← term_add_apply] using Summable.add hf hg + simpa [LSeriesSummable, ← term_add_apply] using Summable.add hf hg @[simp] lemma LSeries_add {f g : ℕ → ℂ} {s : ℂ} (hf : LSeriesSummable f s) (hg : LSeriesSummable g s) : LSeries (f + g) s = LSeries f s + LSeries g s := by - simpa only [LSeries, term_add, Pi.add_apply] using tsum_add hf hg + simpa [LSeries, term_add] using tsum_add hf hg /-! ### Negation -/ lemma LSeries.term_neg (f : ℕ → ℂ) (s : ℂ) : term (-f) s = -term f s := by - ext ⟨- | n⟩ - · simp only [term_zero, Pi.neg_apply, neg_zero] - · simp only [term_of_ne_zero (Nat.succ_ne_zero _), Pi.neg_apply, Nat.cast_succ, neg_div] + ext ⟨- | n⟩ <;> + simp [neg_div] lemma LSeries.term_neg_apply (f : ℕ → ℂ) (s : ℂ) (n : ℕ) : term (-f) s n = -term f s n := by - rw [term_neg, Pi.neg_apply] + simp [term_neg] lemma LSeriesHasSum.neg {f : ℕ → ℂ} {s a : ℂ} (hf : LSeriesHasSum f s a) : LSeriesHasSum (-f) s (-a) := by - simpa only [LSeriesHasSum, term_neg] using HasSum.neg hf + simpa [LSeriesHasSum, term_neg] using HasSum.neg hf lemma LSeriesSummable.neg {f : ℕ → ℂ} {s : ℂ} (hf : LSeriesSummable f s) : LSeriesSummable (-f) s := by - simpa only [LSeriesSummable, term_neg] using Summable.neg hf + simpa [LSeriesSummable, term_neg] using Summable.neg hf @[simp] lemma LSeriesSummable.neg_iff {f : ℕ → ℂ} {s : ℂ} : @@ -69,7 +67,7 @@ lemma LSeriesSummable.neg_iff {f : ℕ → ℂ} {s : ℂ} : @[simp] lemma LSeries_neg (f : ℕ → ℂ) (s : ℂ) : LSeries (-f) s = -LSeries f s := by - simp only [LSeries, term_neg_apply, tsum_neg] + simp [LSeries, term_neg_apply, tsum_neg] /-! ### Subtraction @@ -85,43 +83,41 @@ lemma LSeries.term_sub_apply (f g : ℕ → ℂ) (s : ℂ) (n : ℕ) : lemma LSeriesHasSum.sub {f g : ℕ → ℂ} {s a b : ℂ} (hf : LSeriesHasSum f s a) (hg : LSeriesHasSum g s b) : LSeriesHasSum (f - g) s (a - b) := by - simpa only [LSeriesHasSum, term_sub] using HasSum.sub hf hg + simpa [LSeriesHasSum, term_sub] using HasSum.sub hf hg lemma LSeriesSummable.sub {f g : ℕ → ℂ} {s : ℂ} (hf : LSeriesSummable f s) (hg : LSeriesSummable g s) : LSeriesSummable (f - g) s := by - simpa only [LSeriesSummable, ← term_sub_apply] using Summable.sub hf hg + simpa [LSeriesSummable, ← term_sub_apply] using Summable.sub hf hg @[simp] lemma LSeries_sub {f g : ℕ → ℂ} {s : ℂ} (hf : LSeriesSummable f s) (hg : LSeriesSummable g s) : LSeries (f - g) s = LSeries f s - LSeries g s := by - simpa only [LSeries, term_sub, Pi.sub_apply] using tsum_sub hf hg + simpa [LSeries, term_sub] using tsum_sub hf hg /-! ### Scalar multiplication -/ lemma LSeries.term_smul (f : ℕ → ℂ) (c s : ℂ) : term (c • f) s = c • term f s := by - ext ⟨- | n⟩ - · simp only [term_zero, Pi.smul_apply, smul_eq_mul, mul_zero] - · simp only [term_of_ne_zero (Nat.succ_ne_zero _), Pi.smul_apply, smul_eq_mul, Nat.cast_succ, - mul_div_assoc] + ext ⟨- | n⟩ <;> + simp [mul_div_assoc] lemma LSeries.term_smul_apply (f : ℕ → ℂ) (c s : ℂ) (n : ℕ) : term (c • f) s n = c * term f s n := by - rw [term_smul, Pi.smul_apply, smul_eq_mul] + simp [term_smul] lemma LSeriesHasSum.smul {f : ℕ → ℂ} (c : ℂ) {s a : ℂ} (hf : LSeriesHasSum f s a) : LSeriesHasSum (c • f) s (c * a) := by - simpa only [LSeriesHasSum, term_smul, smul_eq_mul] using hf.const_smul c + simpa [LSeriesHasSum, term_smul] using hf.const_smul c lemma LSeriesSummable.smul {f : ℕ → ℂ} (c : ℂ) {s : ℂ} (hf : LSeriesSummable f s) : LSeriesSummable (c • f) s := by - simpa only [LSeriesSummable, term_smul, smul_eq_mul] using hf.const_smul c + simpa [LSeriesSummable, term_smul] using hf.const_smul c lemma LSeriesSummable.of_smul {f : ℕ → ℂ} {c s : ℂ} (hc : c ≠ 0) (hf : LSeriesSummable (c • f) s) : LSeriesSummable f s := by - simpa only [ne_eq, hc, not_false_eq_true, inv_smul_smul₀] using hf.smul (c⁻¹) + simpa [hc] using hf.smul (c⁻¹) lemma LSeriesSummable.smul_iff {f : ℕ → ℂ} {c s : ℂ} (hc : c ≠ 0) : LSeriesSummable (c • f) s ↔ LSeriesSummable f s := @@ -129,7 +125,7 @@ lemma LSeriesSummable.smul_iff {f : ℕ → ℂ} {c s : ℂ} (hc : c ≠ 0) : @[simp] lemma LSeries_smul (f : ℕ → ℂ) (c s : ℂ) : LSeries (c • f) s = c * LSeries f s := by - simp only [LSeries, term_smul_apply, tsum_mul_left] + simp [LSeries, term_smul_apply, tsum_mul_left] /-! ### Sums @@ -142,26 +138,25 @@ variable {ι : Type*} (f : ι → ℕ → ℂ) (S : Finset ι) (s : ℂ) @[simp] lemma LSeries.term_sum_apply (n : ℕ) : term (∑ i ∈ S, f i) s n = ∑ i ∈ S, term (f i) s n := by - rcases eq_or_ne n 0 with rfl | hn - · simp only [term_zero, Finset.sum_const_zero] - · simp only [ne_eq, hn, not_false_eq_true, term_of_ne_zero, Finset.sum_apply, Finset.sum_div] + rcases eq_or_ne n 0 with hn | hn <;> + simp [hn, Finset.sum_div] lemma LSeries.term_sum : term (∑ i ∈ S, f i) s = ∑ i ∈ S, term (f i) s := - funext fun _ ↦ by rw [Finset.sum_apply]; exact term_sum_apply f S s _ + funext fun _ ↦ by simp variable {f S s} lemma LSeriesHasSum.sum {a : ι → ℂ} (hf : ∀ i ∈ S, LSeriesHasSum (f i) s (a i)) : LSeriesHasSum (∑ i ∈ S, f i) s (∑ i ∈ S, a i) := by - simpa only [LSeriesHasSum, term_sum, Finset.sum_fn S fun i ↦ term (f i) s] using hasSum_sum hf + simpa [LSeriesHasSum, term_sum, Finset.sum_fn S fun i ↦ term (f i) s] using hasSum_sum hf lemma LSeriesSummable.sum (hf : ∀ i ∈ S, LSeriesSummable (f i) s) : LSeriesSummable (∑ i ∈ S, f i) s := by - simpa only [LSeriesSummable, ← term_sum_apply] using summable_sum hf + simpa [LSeriesSummable, ← term_sum_apply] using summable_sum hf @[simp] lemma LSeries_sum (hf : ∀ i ∈ S, LSeriesSummable (f i) s) : LSeries (∑ i ∈ S, f i) s = ∑ i ∈ S, LSeries (f i) s := by - simpa only [LSeries, term_sum, Finset.sum_apply] using tsum_sum hf + simpa [LSeries, term_sum] using tsum_sum hf end sum diff --git a/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean b/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean index 94e639487495f..c13f8dc139484 100644 --- a/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean +++ b/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean @@ -35,7 +35,7 @@ lemma hasSum_mellin {a : ι → ℂ} {p : ι → ℝ} {F : ℝ → ℂ} {s : ℂ rw [this, one_div, inv_cpow _ _ (arg_ofReal_of_nonneg hpi.le ▸ pi_pos.ne), div_eq_inv_mul] · -- integrability of terms rcases hp i with hai | hpi - · simpa only [hai, zero_mul, mul_zero] using integrable_zero _ _ _ + · simp [hai] simp_rw [← mul_assoc, mul_comm _ (a i), mul_assoc] have := Complex.GammaIntegral_convergent hs rw [← mul_zero (p i), ← integrableOn_Ioi_comp_mul_left_iff _ _ hpi] at this @@ -51,7 +51,7 @@ lemma hasSum_mellin {a : ι → ℂ} {p : ι → ℝ} {F : ℝ → ℂ} {s : ℂ simp_rw [← mul_assoc, mul_comm _ (a i), mul_assoc, norm_mul (a i), integral_mul_left] rw [← mul_div_assoc, mul_comm (Real.Gamma _), mul_div_assoc, norm_mul ‖a i‖, norm_norm] rcases hp i with hai | hpi - · simp only [hai, norm_zero, zero_mul] + · simp [hai] congr 1 have := Real.integral_rpow_mul_exp_neg_mul_Ioi hs hpi simp_rw [← neg_mul (p i), one_div, inv_rpow hpi.le, ← div_eq_inv_mul] at this @@ -96,7 +96,7 @@ lemma hasSum_mellin_pi_mul₀ {a : ι → ℂ} {p : ι → ℝ} {F : ℝ → ℂ exact Or.inr (lt_of_le_of_ne (hp i) (Ne.symm h)) have (i t) : (if p i = 0 then 0 else a i * rexp (-π * p i * t)) = a' i * rexp (-π * p i * t) := by - simp only [a', ite_mul, zero_mul] + simp [a'] simp_rw [this] at hF convert hasSum_mellin_pi_mul hp' hs hF ?_ using 2 with i · rcases eq_or_ne (p i) 0 with h | h <;> diff --git a/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean b/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean index ddbd353a5ea3e..0c1bfb0556469 100644 --- a/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean +++ b/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean @@ -402,6 +402,7 @@ lemma jacobiTheta₂_add_left' (z τ : ℂ) : ring_nf /-- The two-variable Jacobi theta function is even in `z`. -/ +@[simp] lemma jacobiTheta₂_neg_left (z τ : ℂ) : jacobiTheta₂ (-z) τ = jacobiTheta₂ z τ := by conv_lhs => rw [jacobiTheta₂, ← Equiv.tsum_eq (Equiv.neg ℤ)] refine tsum_congr (fun n ↦ ?_) From dc2c58755d15e0ae4b30f7bc2462ddad6e8b019f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 30 Jan 2025 15:46:03 +0000 Subject: [PATCH 675/681] feat: conditional variance (#21051) From my PhD (LeanCamCombi) Co-authored-by: Kexing Ying --- Mathlib.lean | 1 + .../ConditionalExpectation/Basic.lean | 2 +- .../Function/LpSeminorm/CompareExp.lean | 2 +- Mathlib/Probability/CondVar.lean | 175 ++++++++++++++++++ 4 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 Mathlib/Probability/CondVar.lean diff --git a/Mathlib.lean b/Mathlib.lean index 095caa64e9c52..72364f69268fc 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4345,6 +4345,7 @@ import Mathlib.Order.Zorn import Mathlib.Order.ZornAtoms import Mathlib.Probability.BorelCantelli import Mathlib.Probability.CDF +import Mathlib.Probability.CondVar import Mathlib.Probability.ConditionalExpectation import Mathlib.Probability.ConditionalProbability import Mathlib.Probability.Density diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index 98df7b831fb53..2c2f035853d21 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -98,7 +98,7 @@ noncomputable irreducible_def condExp (μ : Measure[m₀] α) (f : α → E) : @[deprecated (since := "2025-01-21")] alias condexp := condExp -- We define notation `μ[f|m]` for the conditional expectation of `f` with respect to `m`. -scoped notation μ "[" f "|" m "]" => MeasureTheory.condExp m μ f +@[inherit_doc] scoped notation μ "[" f "|" m "]" => MeasureTheory.condExp m μ f theorem condExp_of_not_le (hm_not : ¬m ≤ m₀) : μ[f|m] = 0 := by rw [condExp, dif_neg hm_not] diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean index e56b6c50caf6d..f4c629a7fb32b 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean @@ -378,7 +378,7 @@ end BoundedSMul section Mul -variable {α : Type*} [MeasurableSpace α] {𝕜 : Type*} [NormedRing 𝕜] {μ : Measure α} +variable {α : Type*} {_ : MeasurableSpace α} {𝕜 : Type*} [NormedRing 𝕜] {μ : Measure α} {p q r : ℝ≥0∞} {f : α → 𝕜} {φ : α → 𝕜} theorem Memℒp.mul (hf : Memℒp f r μ) (hφ : Memℒp φ q μ) (hpqr : 1 / p = 1 / q + 1 / r) : diff --git a/Mathlib/Probability/CondVar.lean b/Mathlib/Probability/CondVar.lean new file mode 100644 index 0000000000000..be6e539aad467 --- /dev/null +++ b/Mathlib/Probability/CondVar.lean @@ -0,0 +1,175 @@ +/- +Copyright (c) 2025 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies +-/ +import Mathlib.MeasureTheory.Function.ConditionalExpectation.Real +import Mathlib.MeasureTheory.Integral.Average +import Mathlib.Probability.Variance + +/-! +# Conditional variance + +This file defines the variance of a real-valued random variable conditional to a sigma-algebra. + +## TODO + +Define the Lebesgue conditional variance. See +[GibbsMeasure](https://github.com/james18lpc/GibbsMeasure) for a definition of the Lebesgue +conditional expectation). +-/ + +open MeasureTheory Filter +open scoped ENNReal + +namespace ProbabilityTheory +variable {Ω : Type*} {m₀ m m' : MeasurableSpace Ω} {hm : m ≤ m₀} {X Y : Ω → ℝ} {μ : Measure[m₀] Ω} + {s : Set Ω} + +variable (m X μ) in +/-- Conditional variance of a real-valued random variable. It is defined as `0` if any one of the +following conditions is true: +- `m` is not a sub-σ-algebra of `m₀`, +- `μ` is not σ-finite with respect to `m`, +- `X - μ[X | m]` is not square-integrable. -/ +noncomputable def condVar : Ω → ℝ := μ[(X - μ[X | m]) ^ 2 | m] + +@[inherit_doc] scoped notation "Var[" X " ; " μ " | " m "]" => condVar m X μ + +/-- Conditional variance of a real-valued random variable. It is defined as `0` if any one of the +following conditions is true: +- `m` is not a sub-σ-algebra of `m₀`, +- `volume` is not σ-finite with respect to `m`, +- `X - 𝔼[X | m]` is not square-integrable. -/ +scoped notation "Var[" f "|" m "]" => Var[f ; MeasureTheory.volume | m] + +lemma condVar_of_not_le (hm : ¬m ≤ m₀) : Var[X ; μ | m] = 0 := by rw [condVar, condExp_of_not_le hm] + +lemma condVar_of_not_sigmaFinite (hμm : ¬SigmaFinite (μ.trim hm)) : + Var[X ; μ | m] = 0 := by rw [condVar, condExp_of_not_sigmaFinite hm hμm] + +open scoped Classical in +lemma condVar_of_sigmaFinite [SigmaFinite (μ.trim hm)] : + Var[X ; μ | m] = + if Integrable (fun ω ↦ (X ω - (μ[X | m]) ω) ^ 2) μ then + if StronglyMeasurable[m] (fun ω ↦ (X ω - (μ[X | m]) ω) ^ 2) then + fun ω ↦ (X ω - (μ[X | m]) ω) ^ 2 + else aestronglyMeasurable_condExpL1.mk (condExpL1 hm μ fun ω ↦ (X ω - (μ[X | m]) ω) ^ 2) + else 0 := condExp_of_sigmaFinite _ + +lemma condVar_of_stronglyMeasurable [SigmaFinite (μ.trim hm)] + (hX : StronglyMeasurable[m] X) (hXint : Integrable ((X - μ[X | m]) ^ 2) μ) : + Var[X ; μ | m] = fun ω ↦ (X ω - (μ[X | m]) ω) ^ 2 := + condExp_of_stronglyMeasurable _ ((hX.sub stronglyMeasurable_condExp).pow _) hXint + +lemma condVar_of_not_integrable (hXint : ¬ Integrable (fun ω ↦ (X ω - (μ[X | m]) ω) ^ 2) μ) : + Var[X ; μ | m] = 0 := condExp_of_not_integrable hXint + +@[simp] lemma condVar_zero : Var[0 ; μ | m] = 0 := by simp [condVar] + +@[simp] +lemma condVar_const (hm : m ≤ m₀) (c : ℝ) : Var[fun _ ↦ c ; μ | m] = 0 := by + obtain rfl | hc := eq_or_ne c 0 + · simp [← Pi.zero_def] + by_cases hμm : IsFiniteMeasure μ + · simp [condVar, hm, Pi.pow_def] + · simp [condVar, condExp_of_not_integrable, integrable_const_iff_isFiniteMeasure hc, + integrable_const_iff_isFiniteMeasure <| pow_ne_zero _ hc, hμm, Pi.pow_def] + +lemma stronglyMeasurable_condVar : StronglyMeasurable[m] (Var[X ; μ | m]) := + stronglyMeasurable_condExp + +lemma condVar_congr_ae (h : X =ᵐ[μ] Y) : Var[X ; μ | m] =ᵐ[μ] Var[Y ; μ | m] := + condExp_congr_ae <| by filter_upwards [h, condExp_congr_ae h] with ω hω hω'; dsimp; rw [hω, hω'] + +lemma condVar_of_aestronglyMeasurable [hμm : SigmaFinite (μ.trim hm)] + (hX : AEStronglyMeasurable[m] X μ) (hXint : Integrable ((X - μ[X | m]) ^ 2) μ) : + Var[X ; μ | m] =ᵐ[μ] (X - μ[X | m]) ^ 2 := + condExp_of_aestronglyMeasurable' _ ((continuous_pow _).comp_aestronglyMeasurable + (hX.sub stronglyMeasurable_condExp.aestronglyMeasurable)) hXint + +lemma integrable_condVar : Integrable Var[X ; μ | m] μ := integrable_condExp + +/-- The integral of the conditional variance `Var[X | m]` over an `m`-measurable set is equal to +the integral of `(X - μ[X | m]) ^ 2` on that set. -/ +lemma setIntegral_condVar [SigmaFinite (μ.trim hm)] (hX : Integrable ((X - μ[X | m]) ^ 2) μ) + (hs : MeasurableSet[m] s) : + ∫ ω in s, (Var[X ; μ | m]) ω ∂μ = ∫ ω in s, (X ω - (μ[X | m]) ω) ^ 2 ∂μ := + setIntegral_condExp _ hX hs + +-- `(· ^ 2)` is a postfix operator called `_sq` in lemma names, but +-- `condVar_ae_eq_condExp_sq_sub_condExp_sq` is a bit ridiculous, so we exceptionally denote it by +-- `sq_` as it were a prefix. +lemma condVar_ae_eq_condExp_sq_sub_sq_condExp (hm : m ≤ m₀) [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : + Var[X ; μ | m] =ᵐ[μ] μ[X ^ 2 | m] - μ[X | m] ^ 2 := by + calc + Var[X ; μ | m] + _ = μ[X ^ 2 - 2 * X * μ[X | m] + μ[X | m] ^ 2 | m] := by rw [condVar, sub_sq] + _ =ᵐ[μ] μ[X ^ 2 | m] - 2 * μ[X | m] ^ 2 + μ[X | m] ^ 2 := by + have aux₀ : Integrable (X ^ 2) μ := hX.integrable_sq + have aux₁ : Integrable (2 * X * μ[X | m]) μ := by + rw [mul_assoc] + refine (memℒp_one_iff_integrable.1 <| hX.condExp.mul hX ?_).const_mul _ + simp [ENNReal.inv_two_add_inv_two] + have aux₂ : Integrable (μ[X | m] ^ 2) μ := hX.condExp.integrable_sq + filter_upwards [condExp_add (m := m) (aux₀.sub aux₁) aux₂, condExp_sub (m := m) aux₀ aux₁, + condExp_mul_of_stronglyMeasurable_right stronglyMeasurable_condExp aux₁ + ((hX.integrable one_le_two).const_mul _), condExp_ofNat (m := m) 2 X] + with ω hω₀ hω₁ hω₂ hω₃ + simp [hω₀, hω₁, hω₂, hω₃, condExp_const, + condExp_of_stronglyMeasurable hm (stronglyMeasurable_condExp.pow _) aux₂] + simp [mul_assoc, sq] + _ = μ[X ^ 2 | m] - μ[X | m] ^ 2 := by ring + +lemma condVar_ae_le_condExp_sq (hm : m ≤ m₀) [IsFiniteMeasure μ] (hX : Memℒp X 2 μ) : + Var[X ; μ | m] ≤ᵐ[μ] μ[X ^ 2 | m] := by + filter_upwards [condVar_ae_eq_condExp_sq_sub_sq_condExp hm hX] with ω hω + dsimp at hω + nlinarith + +/-- **Law of total variance** -/ +lemma integral_condVar_add_variance_condExp (hm : m ≤ m₀) [IsProbabilityMeasure μ] + (hX : Memℒp X 2 μ) : μ[Var[X ; μ | m]] + Var[μ[X | m] ; μ] = Var[X ; μ] := by + calc + μ[Var[X ; μ | m]] + Var[μ[X | m] ; μ] + _ = μ[(μ[X ^ 2 | m] - μ[X | m] ^ 2 : Ω → ℝ)] + (μ[μ[X | m] ^ 2] - μ[μ[X | m]] ^ 2) := by + congr 1 + · exact integral_congr_ae <| condVar_ae_eq_condExp_sq_sub_sq_condExp hm hX + · exact variance_def' hX.condExp + _ = μ[X ^ 2] - μ[μ[X | m] ^ 2] + (μ[μ[X | m] ^ 2] - μ[X] ^ 2) := by + rw [integral_sub' integrable_condExp, integral_condExp hm, integral_condExp hm] + exact hX.condExp.integrable_sq + _ = Var[X ; μ] := by rw [variance_def' hX]; ring + +lemma condVar_bot' [NeZero μ] (X : Ω → ℝ) : + Var[X ; μ | ⊥] = fun _ => ⨍ ω, (X ω - ⨍ ω', X ω' ∂μ) ^ 2 ∂μ := by + ext ω; simp [condVar, condExp_bot', average] + +lemma condVar_bot_ae_eq (X : Ω → ℝ) : + Var[X ; μ | ⊥] =ᵐ[μ] fun _ ↦ ⨍ ω, (X ω - ⨍ ω', X ω' ∂μ) ^ 2 ∂μ := by + obtain rfl | hμ := eq_zero_or_neZero μ + · rw [ae_zero] + exact eventually_bot + · exact .of_forall <| congr_fun (condVar_bot' X) + +lemma condVar_bot [IsProbabilityMeasure μ] (hX : AEMeasurable X μ) : + Var[X ; μ | ⊥] = fun _ω ↦ Var[X ; μ] := by + simp [condVar_bot', average_eq_integral, variance_eq_integral hX] + +lemma condVar_smul (c : ℝ) (X : Ω → ℝ) : Var[c • X ; μ | m] =ᵐ[μ] c ^ 2 • Var[X ; μ | m] := by + calc + Var[c • X ; μ | m] + _ =ᵐ[μ] μ[c ^ 2 • (X - μ[X | m]) ^ 2 | m] := by + rw [condVar] + refine condExp_congr_ae ?_ + filter_upwards [condExp_smul (m := m) c X] with ω hω + simp [hω, ← mul_sub, mul_pow] + _ =ᵐ[μ] c ^ 2 • Var[X ; μ | m] := condExp_smul .. + +@[simp] lemma condVar_neg (X : Ω → ℝ) : Var[-X ; μ | m] =ᵐ[μ] Var[X ; μ | m] := by + refine condExp_congr_ae ?_ + filter_upwards [condExp_neg (m := m) X] with ω hω + simp [condVar, hω] + ring + +end ProbabilityTheory From 344e1cfc04c1c3b0aef8dc9f66e3153a4c38823a Mon Sep 17 00:00:00 2001 From: Andrew Yang Date: Thu, 30 Jan 2025 15:54:57 +0000 Subject: [PATCH 676/681] =?UTF-8?q?feat(AlgebraicGeometry):=20`=CE=A0=20R?= =?UTF-8?q?=E1=B5=A2`-points=20of=20schemes=20(#20494)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mathlib.lean | 1 + .../GammaSpecAdjunction.lean | 9 ++ Mathlib/AlgebraicGeometry/Limits.lean | 57 ++++++- .../Morphisms/ClosedImmersion.lean | 20 +++ .../Morphisms/Immersion.lean | 11 +- .../Morphisms/QuasiSeparated.lean | 21 +++ Mathlib/AlgebraicGeometry/PointsPi.lean | 145 ++++++++++++++++++ 7 files changed, 262 insertions(+), 2 deletions(-) create mode 100644 Mathlib/AlgebraicGeometry/PointsPi.lean diff --git a/Mathlib.lean b/Mathlib.lean index 72364f69268fc..5415c3faa9371 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1055,6 +1055,7 @@ import Mathlib.AlgebraicGeometry.Morphisms.UniversallyInjective import Mathlib.AlgebraicGeometry.Noetherian import Mathlib.AlgebraicGeometry.OpenImmersion import Mathlib.AlgebraicGeometry.Over +import Mathlib.AlgebraicGeometry.PointsPi import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Basic import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Proper import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Scheme diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index 2506ebe79df0c..30a706d61de6e 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -556,6 +556,15 @@ def Spec.homEquiv {R S : CommRingCat} : (Spec S ⟶ Spec R) ≃ (R ⟶ S) where left_inv := Spec.map_preimage right_inv := Spec.preimage_map +@[simp] +lemma Spec.preimage_id {R : CommRingCat} : Spec.preimage (𝟙 (Spec R)) = 𝟙 R := + Spec.map_injective (by simp) + +@[simp, reassoc] +lemma Spec.preimage_comp {R S T : CommRingCat} (f : Spec R ⟶ Spec S) (g : Spec S ⟶ Spec T) : + Spec.preimage (f ≫ g) = Spec.preimage g ≫ Spec.preimage f := + Spec.map_injective (by simp) + end instance : Spec.toLocallyRingedSpace.IsRightAdjoint := diff --git a/Mathlib/AlgebraicGeometry/Limits.lean b/Mathlib/AlgebraicGeometry/Limits.lean index 6983cda062f3b..cfa0f9fb2cc05 100644 --- a/Mathlib/AlgebraicGeometry/Limits.lean +++ b/Mathlib/AlgebraicGeometry/Limits.lean @@ -315,6 +315,36 @@ lemma sigmaMk_mk (i) (x : f i) : refine (colimit.isoColimitCocone_ι_inv_assoc ⟨_, TopCat.sigmaCofanIsColimit _⟩ _ _).trans ?_ exact ι_comp_sigmaComparison Scheme.forgetToTop _ _ +open scoped Function in +lemma isOpenImmersion_sigmaDesc + {X : Scheme} (α : ∀ i, f i ⟶ X) [∀ i, IsOpenImmersion (α i)] + (hα : Pairwise (Disjoint on (Set.range <| α · |>.base))) : + IsOpenImmersion (Sigma.desc α) := by + rw [IsOpenImmersion.iff_stalk_iso] + constructor + · suffices Topology.IsOpenEmbedding ((Sigma.desc α).base ∘ sigmaMk f) by + convert this.comp (sigmaMk f).symm.isOpenEmbedding; ext; simp + refine .of_continuous_injective_isOpenMap ?_ ?_ ?_ + · fun_prop + · rintro ⟨ix, x⟩ ⟨iy, y⟩ e + have : (α ix).base x = (α iy).base y := by + simpa [← Scheme.comp_base_apply] using e + obtain rfl : ix = iy := by + by_contra h + exact Set.disjoint_iff_forall_ne.mp (hα h) ⟨x, rfl⟩ ⟨y, this.symm⟩ rfl + rw [(α ix).isOpenEmbedding.injective this] + · rw [isOpenMap_sigma] + intro i + simpa [← Scheme.comp_base_apply] using (α i).isOpenEmbedding.isOpenMap + · intro x + have ⟨y, hy⟩ := (sigmaOpenCover f).covers x + rw [← hy] + refine IsIso.of_isIso_fac_right (g := ((sigmaOpenCover f).map _).stalkMap y) + (h := (X.presheaf.stalkCongr (.of_eq ?_)).hom ≫ (α _).stalkMap _) ?_ + · simp [← Scheme.comp_base_apply] + · simp [← Scheme.stalkMap_comp, Scheme.stalkMap_congr_hom _ _ (Sigma.ι_desc _ _)] + + variable (X Y : Scheme.{u}) /-- (Implementation Detail) @@ -498,11 +528,36 @@ noncomputable def sigmaSpec (R : ι → CommRingCat) : (∐ fun i ↦ Spec (R i)) ⟶ Spec (.of (Π i, R i)) := Sigma.desc (fun i ↦ Spec.map (CommRingCat.ofHom (Pi.evalRingHom _ i))) -@[simp, reassoc] +@[reassoc (attr := simp)] lemma ι_sigmaSpec (R : ι → CommRingCat) (i) : Sigma.ι _ i ≫ sigmaSpec R = Spec.map (CommRingCat.ofHom (Pi.evalRingHom _ i)) := Sigma.ι_desc _ _ +instance (i) (R : ι → Type _) [∀ i, CommRing (R i)] : + IsOpenImmersion (Spec.map (CommRingCat.ofHom (Pi.evalRingHom (R ·) i))) := by + classical + letI := (Pi.evalRingHom R i).toAlgebra + have : IsLocalization.Away (Function.update (β := R) 0 i 1) (R i) := by + apply IsLocalization.away_of_isIdempotentElem_of_mul + · ext j; by_cases h : j = i <;> aesop + · intro x y + constructor + · intro e; ext j; by_cases h : j = i <;> aesop + · intro e; simpa using congr_fun e i + · exact Function.surjective_eval _ + exact IsOpenImmersion.of_isLocalization (Function.update 0 i 1) + +instance (R : ι → CommRingCat) : IsOpenImmersion (sigmaSpec R) := by + classical + apply isOpenImmersion_sigmaDesc + intro ix iy h + refine Set.disjoint_iff_forall_ne.mpr ?_ + rintro _ ⟨x, rfl⟩ _ ⟨y, rfl⟩ e + have : DFinsupp.single (β := (R ·)) iy 1 iy ∈ y.asIdeal := + (PrimeSpectrum.ext_iff.mp e).le (x := DFinsupp.single iy 1) + (show DFinsupp.single (β := (R ·)) iy 1 ix ∈ x.asIdeal by simp [h.symm]) + simp [← Ideal.eq_top_iff_one, y.2.ne_top] at this + instance [Finite ι] (R : ι → CommRingCat) : IsIso (sigmaSpec R) := by have : sigmaSpec R = (colimit.isoColimitCocone ⟨_, diff --git a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean index 988096eeac24d..c9fae92873c2a 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean @@ -252,6 +252,26 @@ theorem isAffine_surjective_of_isAffine [IsClosedImmersion f] : ((affineTargetImageFactorization f).appTop)).surjective.comp <| affineTargetImageInclusion_app_surjective f⟩ +lemma Spec_iff {R : CommRingCat} {f : X ⟶ Spec R} : + IsClosedImmersion f ↔ ∃ I : Ideal R, ∃ e : X ≅ Spec (.of <| R ⧸ I), + f = e.hom ≫ Spec.map (CommRingCat.ofHom (Ideal.Quotient.mk I)) := by + constructor + · intro H + obtain ⟨h₁, h₂⟩ := IsClosedImmersion.isAffine_surjective_of_isAffine f + let φ := (Scheme.ΓSpecIso R).inv ≫ f.appTop + refine ⟨RingHom.ker φ.1, Scheme.isoSpec _ ≪≫ Scheme.Spec.mapIso + (.op (RingEquiv.ofBijective φ.1.kerLift ?_).toCommRingCatIso), ?_⟩ + · exact ⟨φ.1.kerLift_injective, Ideal.Quotient.lift_surjective_of_surjective _ _ + (h₂.comp (Scheme.ΓSpecIso R).commRingCatIsoToRingEquiv.symm.surjective)⟩ + · simp only [Iso.trans_hom, Functor.mapIso_hom, Iso.op_hom, Scheme.Spec_map, + Quiver.Hom.unop_op, Category.assoc, ← Spec.map_comp] + show f = X.isoSpec.hom ≫ Spec.map φ + simp only [Scheme.isoSpec, asIso_hom, Spec.map_comp, ← Scheme.toSpecΓ_naturality_assoc, + ← SpecMap_ΓSpecIso_hom, φ] + simp only [← Spec.map_comp, Iso.inv_hom_id, Spec.map_id, Category.comp_id] + · rintro ⟨I, e, rfl⟩ + infer_instance + end IsClosedImmersion end Affine diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Immersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/Immersion.lean index ac23c6f14aa4b..a03d46fd9e830 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Immersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Immersion.lean @@ -23,7 +23,7 @@ if and only if it can be factored into a closed immersion followed by an open im universe v u -open CategoryTheory +open CategoryTheory Limits namespace AlgebraicGeometry @@ -172,6 +172,15 @@ instance : IsImmersion (pullback.diagonal f) := by rwa [morphismRestrict_ι, H, ← Scheme.topIso_hom, MorphismProperty.cancel_left_of_respectsIso (P := @IsImmersion)] at this +instance : IsImmersion (prod.lift (𝟙 X) (𝟙 X)) := by + rw [← MorphismProperty.cancel_right_of_respectsIso @IsImmersion _ (prodIsoPullback X X).hom] + convert inferInstanceAs (IsImmersion (pullback.diagonal (terminal.from X))) + ext : 1 <;> simp + +instance (f g : X ⟶ Y) : IsImmersion (equalizer.ι f g) := + MorphismProperty.of_isPullback (P := @IsImmersion) + (isPullback_equalizer_prod f g).flip inferInstance + end IsImmersion end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean index 1a8fab9fd2701..cc98f5e3fe6c5 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean @@ -5,6 +5,7 @@ Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.Morphisms.Constructors import Mathlib.AlgebraicGeometry.Morphisms.QuasiCompact +import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Equalizer import Mathlib.Topology.QuasiSeparated import Mathlib.Topology.Sheaves.CommRingCat @@ -170,6 +171,26 @@ theorem IsAffineOpen.isQuasiSeparated {X : Scheme} {U : X.Opens} (hU : IsAffineO rw [isQuasiSeparated_iff_quasiSeparatedSpace] exacts [@AlgebraicGeometry.quasiSeparatedSpace_of_isAffine _ hU, U.isOpen] +lemma quasiSeparatedSpace_iff_quasiCompact_prod_lift : + QuasiSeparatedSpace X ↔ QuasiCompact (prod.lift (𝟙 X) (𝟙 X)) := by + rw [← MorphismProperty.cancel_right_of_respectsIso @QuasiCompact _ (prodIsoPullback X X).hom, + ← HasAffineProperty.iff_of_isAffine (f := terminal.from X) (P := @QuasiSeparated), + quasiSeparated_iff] + congr! + ext : 1 <;> simp + +instance [QuasiSeparatedSpace X] : QuasiCompact (prod.lift (𝟙 X) (𝟙 X)) := by + rwa [← quasiSeparatedSpace_iff_quasiCompact_prod_lift] + +instance [QuasiSeparatedSpace Y] (f g : X ⟶ Y) : QuasiCompact (equalizer.ι f g) := + MorphismProperty.of_isPullback (P := @QuasiCompact) + (isPullback_equalizer_prod f g).flip inferInstance + +instance [CompactSpace X] [QuasiSeparatedSpace Y] (f g : X ⟶ Y) : + CompactSpace (equalizer f g).carrier := by + constructor + simpa using QuasiCompact.isCompact_preimage (f := equalizer.ι f g) _ isOpen_univ isCompact_univ + theorem QuasiSeparated.of_comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [QuasiSeparated (f ≫ g)] : QuasiSeparated f := by let 𝒰 := (Z.affineCover.pullbackCover g).bind fun x => Scheme.affineCover _ diff --git a/Mathlib/AlgebraicGeometry/PointsPi.lean b/Mathlib/AlgebraicGeometry/PointsPi.lean new file mode 100644 index 0000000000000..f430d0a60fda2 --- /dev/null +++ b/Mathlib/AlgebraicGeometry/PointsPi.lean @@ -0,0 +1,145 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.AlgebraicGeometry.Morphisms.Immersion + +/-! + +# `Π Rᵢ`-Points of Schemes + +We show that the canonical map `X(Π Rᵢ) ⟶ Π X(Rᵢ)` (`AlgebraicGeometry.pointsPi`) +is injective and surjective under various assumptions + +-/ + +open CategoryTheory Limits PrimeSpectrum + +namespace AlgebraicGeometry + +universe u v + +variable {ι : Type u} (R : ι → CommRingCat.{u}) + +lemma Ideal.span_eq_top_of_span_image_evalRingHom + {ι} {R : ι → Type*} [∀ i, CommRing (R i)] (s : Set (Π i, R i)) + (hs : s.Finite) (hs' : ∀ i, Ideal.span (Pi.evalRingHom (R ·) i '' s) = ⊤) : + Ideal.span s = ⊤ := by + simp only [Ideal.eq_top_iff_one, ← Subtype.range_val (s := s), ← Set.range_comp, + Finsupp.mem_ideal_span_range_iff_exists_finsupp] at hs' ⊢ + choose f hf using hs' + have : Fintype s := hs.fintype + refine ⟨Finsupp.equivFunOnFinite.symm fun i x ↦ f x i, ?_⟩ + ext i + simpa [Finsupp.sum_fintype] using hf i + +lemma eq_top_of_sigmaSpec_subset_of_isCompact + (U : (Spec (.of (Π i, R i))).Opens) (V : Set (Spec (.of (Π i, R i)))) + (hV : ↑(sigmaSpec R).opensRange ⊆ V) + (hV' : IsCompact (X := Spec (.of (Π i, R i))) V) + (hVU : V ⊆ U) : U = ⊤ := by + obtain ⟨s, hs⟩ := (PrimeSpectrum.isOpen_iff _).mp U.2 + obtain ⟨t, hts, ht, ht'⟩ : ∃ t ⊆ s, t.Finite ∧ V ⊆ ⋃ i ∈ t, (basicOpen i).1 := by + obtain ⟨t, ht⟩ := hV'.elim_finite_subcover + (fun i : s ↦ (basicOpen i.1).1) (fun _ ↦ (basicOpen _).2) + (by simpa [← Set.compl_iInter, ← zeroLocus_iUnion₂ (κ := (· ∈ s)), ← hs]) + exact ⟨t.map (Function.Embedding.subtype _), by simp, Finset.finite_toSet _, by simpa using ht⟩ + replace ht' : V ⊆ (zeroLocus t)ᶜ := by + simpa [← Set.compl_iInter, ← zeroLocus_iUnion₂ (κ := (· ∈ t))] using ht' + have (i) : Ideal.span (Pi.evalRingHom (R ·) i '' t) = ⊤ := by + rw [← zeroLocus_empty_iff_eq_top, zeroLocus_span, ← preimage_comap_zeroLocus, + ← Set.compl_univ_iff, ← Set.preimage_compl, Set.preimage_eq_univ_iff] + trans (Sigma.ι _ i ≫ sigmaSpec R).opensRange.1 + · simp; rfl + · rw [Scheme.Hom.opensRange_comp] + exact (Set.image_subset_range _ _).trans (hV.trans ht') + have : Ideal.span s = ⊤ := top_le_iff.mp + ((Ideal.span_eq_top_of_span_image_evalRingHom _ ht this).ge.trans (Ideal.span_mono hts)) + simpa [← zeroLocus_span s, zeroLocus_empty_iff_eq_top.mpr this] using hs + +lemma eq_bot_of_comp_quotientMk_eq_sigmaSpec (I : Ideal (Π i, R i)) + (f : (∐ fun i ↦ Spec (R i)) ⟶ Spec (.of ((Π i, R i) ⧸ I))) + (hf : f ≫ Spec.map (CommRingCat.ofHom (Ideal.Quotient.mk I)) = sigmaSpec R) : + I = ⊥ := by + refine le_bot_iff.mp fun x hx ↦ ?_ + ext i + simpa [← Category.assoc, Ideal.Quotient.eq_zero_iff_mem.mpr hx] using + congr((Spec.preimage (Sigma.ι (Spec <| R ·) i ≫ $hf)).hom x).symm + +/-- If `V` is a locally closed subscheme of `Spec (Π Rᵢ)` containing `∐ Spec Rᵢ`, then +`V = Spec (Π Rᵢ)`. -/ +lemma isIso_of_comp_eq_sigmaSpec {V : Scheme} + (f : (∐ fun i ↦ Spec (R i)) ⟶ V) (g : V ⟶ Spec (.of (Π i, R i))) + [IsImmersion g] [CompactSpace V] + (hU' : f ≫ g = sigmaSpec R) : IsIso g := by + have : g.coborderRange = ⊤ := by + apply eq_top_of_sigmaSpec_subset_of_isCompact (hVU := subset_coborder) + · simpa only [← hU'] using Set.range_comp_subset_range f.base g.base + · exact isCompact_range g.base.2 + have : IsClosedImmersion g := by + have : IsIso g.coborderRange.ι := by rw [this, ← Scheme.topIso_hom]; infer_instance + rw [← g.liftCoborder_ι] + infer_instance + obtain ⟨I, e, rfl⟩ := IsClosedImmersion.Spec_iff.mp this + obtain rfl := eq_bot_of_comp_quotientMk_eq_sigmaSpec R I (f ≫ e.hom) (by rwa [Category.assoc]) + show IsIso (e.hom ≫ Spec.map (RingEquiv.quotientBot _).toCommRingCatIso.inv) + infer_instance + +variable (X : Scheme) + +/-- The canonical map `X(Π Rᵢ) ⟶ Π X(Rᵢ)`. +This is injective if `X` is quasi-separated, surjective if `X` is affine, +or if `X` is compact and each `Rᵢ` is local. -/ +noncomputable +def pointsPi : (Spec (.of (Π i, R i)) ⟶ X) → Π i, Spec (R i) ⟶ X := + fun f i ↦ Spec.map (CommRingCat.ofHom (Pi.evalRingHom (R ·) i)) ≫ f + +lemma pointsPi_injective [QuasiSeparatedSpace X] : Function.Injective (pointsPi R X) := by + rintro f g e + have := isIso_of_comp_eq_sigmaSpec R (V := equalizer f g) + (equalizer.lift (sigmaSpec R) (by ext1 i; simpa using congr_fun e i)) + (equalizer.ι f g) (by simp) + rw [← cancel_epi (equalizer.ι f g), equalizer.condition] + +lemma pointsPi_surjective_of_isAffine [IsAffine X] : Function.Surjective (pointsPi R X) := by + rintro f + refine ⟨Spec.map (CommRingCat.ofHom + (Pi.ringHom fun i ↦ (Spec.preimage (f i ≫ X.isoSpec.hom)).1)) ≫ X.isoSpec.inv, ?_⟩ + ext i : 1 + simp only [pointsPi, ← Spec.map_comp_assoc, Iso.comp_inv_eq] + exact Spec.map_preimage _ + +lemma pointsPi_surjective [CompactSpace X] [∀ i, IsLocalRing (R i)] : + Function.Surjective (pointsPi R X) := by + intro f + let 𝒰 : X.OpenCover := X.affineCover.finiteSubcover + have (i) : IsAffine (𝒰.obj i) := isAffine_Spec _ + have (i) : ∃ j, Set.range (f i).base ⊆ (𝒰.map j).opensRange := by + refine ⟨𝒰.f ((f i).base (IsLocalRing.closedPoint (R i))), ?_⟩ + rintro _ ⟨x, rfl⟩ + exact ((IsLocalRing.specializes_closedPoint x).map (f i).base.2).mem_open + (𝒰.map _).opensRange.2 (𝒰.covers _) + choose j hj using this + have (j₀) := pointsPi_surjective_of_isAffine (ι := { i // j i = j₀ }) (R ·) (𝒰.obj j₀) + (fun i ↦ IsOpenImmersion.lift (𝒰.map j₀) (f i.1) (by rcases i with ⟨i, rfl⟩; exact hj i)) + choose g hg using this + simp_rw [funext_iff, pointsPi] at hg + let R' (j₀) := CommRingCat.of (Π i : { i // j i = j₀ }, R i) + let e : (Π i, R i) ≃+* Π j₀, R' j₀ := + { toFun f _ i := f i + invFun f i := f _ ⟨i, rfl⟩ + left_inv _ := rfl + right_inv _ := funext₂ fun j₀ i ↦ by rcases i with ⟨i, rfl⟩; rfl + map_mul' _ _ := rfl + map_add' _ _ := rfl } + refine ⟨Spec.map (CommRingCat.ofHom e.symm.toRingHom) ≫ inv (sigmaSpec R') ≫ + Sigma.desc fun j₀ ↦ g j₀ ≫ 𝒰.map j₀, ?_⟩ + ext i : 1 + have : (Pi.evalRingHom (R ·) i).comp e.symm.toRingHom = + (Pi.evalRingHom _ ⟨i, rfl⟩).comp (Pi.evalRingHom (R' ·) (j i)) := rfl + rw [pointsPi, ← Spec.map_comp_assoc, ← CommRingCat.ofHom_comp, this, CommRingCat.ofHom_comp, + Spec.map_comp_assoc, ← ι_sigmaSpec R', Category.assoc, IsIso.hom_inv_id_assoc, + Sigma.ι_desc, ← Category.assoc, hg, IsOpenImmersion.lift_fac] + +end AlgebraicGeometry From 91155b5c702e0b860d915aec89ed84ae4b712c10 Mon Sep 17 00:00:00 2001 From: Bolton Bailey Date: Thu, 30 Jan 2025 16:06:18 +0000 Subject: [PATCH 677/681] chore(Data/Finsupp/Basic): split SMul from file (#21230) This PR splits part of Data/Finsupp/Basic.lean related to SMul into a new SMul.lean file, addressing an instance of a long file linter trigger. --- Mathlib.lean | 1 + .../Category/ModuleCat/Projective.lean | 2 +- Mathlib/Algebra/MonoidAlgebra/Basic.lean | 2 +- Mathlib/Algebra/MonoidAlgebra/Defs.lean | 2 +- Mathlib/Algebra/SkewMonoidAlgebra/Basic.lean | 2 +- Mathlib/Data/Finsupp/Basic.lean | 197 +--------------- Mathlib/Data/Finsupp/Multiset.lean | 1 - Mathlib/Data/Finsupp/Order.lean | 1 + Mathlib/Data/Finsupp/SMul.lean | 217 ++++++++++++++++++ Mathlib/Data/Finsupp/ToDFinsupp.lean | 2 +- Mathlib/LinearAlgebra/Finsupp/Defs.lean | 2 +- Mathlib/LinearAlgebra/Finsupp/SumProd.lean | 2 +- 12 files changed, 227 insertions(+), 204 deletions(-) create mode 100644 Mathlib/Data/Finsupp/SMul.lean diff --git a/Mathlib.lean b/Mathlib.lean index 5415c3faa9371..cd32a5b65d8f1 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2638,6 +2638,7 @@ import Mathlib.Data.Finsupp.Notation import Mathlib.Data.Finsupp.Order import Mathlib.Data.Finsupp.PWO import Mathlib.Data.Finsupp.Pointwise +import Mathlib.Data.Finsupp.SMul import Mathlib.Data.Finsupp.SMulWithZero import Mathlib.Data.Finsupp.Single import Mathlib.Data.Finsupp.ToDFinsupp diff --git a/Mathlib/Algebra/Category/ModuleCat/Projective.lean b/Mathlib/Algebra/Category/ModuleCat/Projective.lean index 1947ab1f393c3..b8dabad8c1093 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Projective.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Projective.lean @@ -6,7 +6,7 @@ Authors: Markus Himmel, Kim Morrison import Mathlib.Algebra.Category.ModuleCat.EpiMono import Mathlib.Algebra.Module.Projective import Mathlib.CategoryTheory.Preadditive.Projective -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMul import Mathlib.LinearAlgebra.Finsupp.VectorSpace /-! diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index 4ed491fbb056d..a7b104c761768 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.Algebra.NonUnitalHom import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.Module.BigOperators import Mathlib.Algebra.MonoidAlgebra.Defs -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMul import Mathlib.LinearAlgebra.Finsupp.SumProd /-! diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index 9876076f4945c..d6da6c7a4ee38 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Yury Kudryashov, Kim Morrison -/ import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.Module.BigOperators -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMul import Mathlib.LinearAlgebra.Finsupp.LSum import Mathlib.Algebra.Module.Submodule.Basic diff --git a/Mathlib/Algebra/SkewMonoidAlgebra/Basic.lean b/Mathlib/Algebra/SkewMonoidAlgebra/Basic.lean index 1036046399aa4..81488c3684bb6 100644 --- a/Mathlib/Algebra/SkewMonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/SkewMonoidAlgebra/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 María Inés de Frutos Fernández. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: María Inés de Frutos Fernández, Xavier Généreux -/ -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMul /-! # Skew monoid algebras diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index 8edd359b3d1c9..ee0131993bc85 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -4,10 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Kim Morrison -/ import Mathlib.Algebra.BigOperators.Finsupp -import Mathlib.Algebra.Group.Action.Basic -import Mathlib.Algebra.Module.Basic -import Mathlib.Algebra.Regular.SMul -import Mathlib.Data.Finsupp.SMulWithZero +import Mathlib.Algebra.Module.Defs import Mathlib.Data.Rat.BigOperators /-! @@ -1206,196 +1203,6 @@ theorem sumFinsuppAddEquivProdFinsupp_symm_inr {α β : Type*} (fg : (α →₀ end Sum -/-! ### Declarations about scalar multiplication -/ - - -section - -variable [Zero M] [MonoidWithZero R] [MulActionWithZero R M] - -@[simp] -theorem single_smul (a b : α) (f : α → M) (r : R) : single a r b • f a = single a (r • f b) b := by - by_cases h : a = b <;> simp [h] - -end - -section - -variable [Monoid G] [MulAction G α] [AddCommMonoid M] - -/-- Scalar multiplication acting on the domain. - -This is not an instance as it would conflict with the action on the range. -See the `instance_diamonds` test for examples of such conflicts. -/ -def comapSMul : SMul G (α →₀ M) where smul g := mapDomain (g • ·) - -attribute [local instance] comapSMul - -theorem comapSMul_def (g : G) (f : α →₀ M) : g • f = mapDomain (g • ·) f := - rfl - -@[simp] -theorem comapSMul_single (g : G) (a : α) (b : M) : g • single a b = single (g • a) b := - mapDomain_single - -/-- `Finsupp.comapSMul` is multiplicative -/ -def comapMulAction : MulAction G (α →₀ M) where - one_smul f := by rw [comapSMul_def, one_smul_eq_id, mapDomain_id] - mul_smul g g' f := by - rw [comapSMul_def, comapSMul_def, comapSMul_def, ← comp_smul_left, mapDomain_comp] - -attribute [local instance] comapMulAction - -/-- `Finsupp.comapSMul` is distributive -/ -def comapDistribMulAction : DistribMulAction G (α →₀ M) where - smul_zero g := by - ext a - simp only [comapSMul_def] - simp - smul_add g f f' := by - ext - simp only [comapSMul_def] - simp [mapDomain_add] - -end - -section - -variable [Group G] [MulAction G α] [AddCommMonoid M] - -attribute [local instance] comapSMul comapMulAction comapDistribMulAction - -/-- When `G` is a group, `Finsupp.comapSMul` acts by precomposition with the action of `g⁻¹`. --/ -@[simp] -theorem comapSMul_apply (g : G) (f : α →₀ M) (a : α) : (g • f) a = f (g⁻¹ • a) := by - conv_lhs => rw [← smul_inv_smul g a] - exact mapDomain_apply (MulAction.injective g) _ (g⁻¹ • a) - -end - -section - -/-! -Throughout this section, some `Monoid` and `Semiring` arguments are specified with `{}` instead of -`[]`. See note [implicit instance arguments]. --/ - -theorem _root_.IsSMulRegular.finsupp [Zero M] [SMulZeroClass R M] {k : R} - (hk : IsSMulRegular M k) : IsSMulRegular (α →₀ M) k := - fun _ _ h => ext fun i => hk (DFunLike.congr_fun h i) - -instance faithfulSMul [Nonempty α] [Zero M] [SMulZeroClass R M] [FaithfulSMul R M] : - FaithfulSMul R (α →₀ M) where - eq_of_smul_eq_smul h := - let ⟨a⟩ := ‹Nonempty α› - eq_of_smul_eq_smul fun m : M => by simpa using DFunLike.congr_fun (h (single a m)) a - -variable (α M) - -instance distribMulAction [Monoid R] [AddMonoid M] [DistribMulAction R M] : - DistribMulAction R (α →₀ M) := - { Finsupp.distribSMul _ _ with - one_smul := fun x => ext fun y => one_smul R (x y) - mul_smul := fun r s x => ext fun y => mul_smul r s (x y) } - -instance module [Semiring R] [AddCommMonoid M] [Module R M] : Module R (α →₀ M) := - { toDistribMulAction := Finsupp.distribMulAction α M - zero_smul := fun _ => ext fun _ => zero_smul _ _ - add_smul := fun _ _ _ => ext fun _ => add_smul _ _ _ } - -variable {α M} - -@[simp] -theorem support_smul_eq [Semiring R] [AddCommMonoid M] [Module R M] [NoZeroSMulDivisors R M] {b : R} - (hb : b ≠ 0) {g : α →₀ M} : (b • g).support = g.support := - Finset.ext fun a => by simp [Finsupp.smul_apply, hb] - -section - -variable {p : α → Prop} [DecidablePred p] - -@[simp] -theorem filter_smul {_ : Monoid R} [AddMonoid M] [DistribMulAction R M] {b : R} {v : α →₀ M} : - (b • v).filter p = b • v.filter p := - DFunLike.coe_injective <| by - simp only [filter_eq_indicator, coe_smul] - exact Set.indicator_const_smul { x | p x } b v - -end - -theorem mapDomain_smul {_ : Monoid R} [AddCommMonoid M] [DistribMulAction R M] {f : α → β} (b : R) - (v : α →₀ M) : mapDomain f (b • v) = b • mapDomain f v := - mapDomain_mapRange _ _ _ _ (smul_add b) - -theorem smul_single' {_ : Semiring R} (c : R) (a : α) (b : R) : - c • Finsupp.single a b = Finsupp.single a (c * b) := by simp - -theorem smul_single_one [Semiring R] (a : α) (b : R) : b • single a (1 : R) = single a b := by - rw [smul_single, smul_eq_mul, mul_one] - -theorem comapDomain_smul [AddMonoid M] [Monoid R] [DistribMulAction R M] {f : α → β} (r : R) - (v : β →₀ M) (hfv : Set.InjOn f (f ⁻¹' ↑v.support)) - (hfrv : Set.InjOn f (f ⁻¹' ↑(r • v).support) := - hfv.mono <| Set.preimage_mono <| Finset.coe_subset.mpr support_smul) : - comapDomain f (r • v) hfrv = r • comapDomain f v hfv := by - ext - rfl - -/-- A version of `Finsupp.comapDomain_smul` that's easier to use. -/ -theorem comapDomain_smul_of_injective [AddMonoid M] [Monoid R] [DistribMulAction R M] {f : α → β} - (hf : Function.Injective f) (r : R) (v : β →₀ M) : - comapDomain f (r • v) hf.injOn = r • comapDomain f v hf.injOn := - comapDomain_smul _ _ _ _ - -end - -theorem sum_smul_index [Semiring R] [AddCommMonoid M] {g : α →₀ R} {b : R} {h : α → R → M} - (h0 : ∀ i, h i 0 = 0) : (b • g).sum h = g.sum fun i a => h i (b * a) := - Finsupp.sum_mapRange_index h0 - -theorem sum_smul_index' [AddMonoid M] [DistribSMul R M] [AddCommMonoid N] {g : α →₀ M} {b : R} - {h : α → M → N} (h0 : ∀ i, h i 0 = 0) : (b • g).sum h = g.sum fun i c => h i (b • c) := - Finsupp.sum_mapRange_index h0 - -/-- A version of `Finsupp.sum_smul_index'` for bundled additive maps. -/ -theorem sum_smul_index_addMonoidHom [AddMonoid M] [AddCommMonoid N] [DistribSMul R M] {g : α →₀ M} - {b : R} {h : α → M →+ N} : ((b • g).sum fun a => h a) = g.sum fun i c => h i (b • c) := - sum_mapRange_index fun i => (h i).map_zero - -instance noZeroSMulDivisors [Zero R] [Zero M] [SMulZeroClass R M] {ι : Type*} - [NoZeroSMulDivisors R M] : NoZeroSMulDivisors R (ι →₀ M) := - ⟨fun h => or_iff_not_imp_left.mpr fun hc => Finsupp.ext fun i => - (eq_zero_or_eq_zero_of_smul_eq_zero (DFunLike.ext_iff.mp h i)).resolve_left hc⟩ - -section DistribMulActionSemiHom -variable [Monoid R] [AddMonoid M] [AddMonoid N] [DistribMulAction R M] [DistribMulAction R N] - -/-- `Finsupp.single` as a `DistribMulActionSemiHom`. - -See also `Finsupp.lsingle` for the version as a linear map. -/ -def DistribMulActionHom.single (a : α) : M →+[R] α →₀ M := - { singleAddHom a with - map_smul' := fun k m => by - simp only - show singleAddHom a (k • m) = k • singleAddHom a m - change Finsupp.single a (k • m) = k • (Finsupp.single a m) - -- Porting note: because `singleAddHom_apply` is missing - simp only [smul_single] } - -theorem distribMulActionHom_ext {f g : (α →₀ M) →+[R] N} - (h : ∀ (a : α) (m : M), f (single a m) = g (single a m)) : f = g := - DistribMulActionHom.toAddMonoidHom_injective <| addHom_ext h - -/-- See note [partially-applied ext lemmas]. -/ -@[ext] -theorem distribMulActionHom_ext' {f g : (α →₀ M) →+[R] N} - (h : ∀ a : α, f.comp (DistribMulActionHom.single a) = g.comp (DistribMulActionHom.single a)) : - f = g := - distribMulActionHom_ext fun a => DistribMulActionHom.congr_fun (h a) - -end DistribMulActionSemiHom - section variable [Zero R] @@ -1637,5 +1444,3 @@ theorem sigmaFinsuppAddEquivPiFinsupp_apply {α : Type*} {ιs : η → Type*} [A end Sigma end Finsupp - -set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/Finsupp/Multiset.lean b/Mathlib/Data/Finsupp/Multiset.lean index 0ff33f764dd1d..b1b694edf0879 100644 --- a/Mathlib/Data/Finsupp/Multiset.lean +++ b/Mathlib/Data/Finsupp/Multiset.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Algebra.Order.Group.Finset -import Mathlib.Data.Finsupp.Basic import Mathlib.Data.Finsupp.Order /-! diff --git a/Mathlib/Data/Finsupp/Order.lean b/Mathlib/Data/Finsupp/Order.lean index 58f85f4f5fe19..6f572806c7370 100644 --- a/Mathlib/Data/Finsupp/Order.lean +++ b/Mathlib/Data/Finsupp/Order.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Order.BigOperators.Group.Finset import Mathlib.Algebra.Order.Module.Defs import Mathlib.Algebra.Order.Pi import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMulWithZero /-! # Pointwise order on finitely supported functions diff --git a/Mathlib/Data/Finsupp/SMul.lean b/Mathlib/Data/Finsupp/SMul.lean new file mode 100644 index 0000000000000..321d295280c4f --- /dev/null +++ b/Mathlib/Data/Finsupp/SMul.lean @@ -0,0 +1,217 @@ +/- +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, Kim Morrison +-/ +import Mathlib.Data.Finsupp.Basic +import Mathlib.Algebra.Module.Basic +import Mathlib.Algebra.Regular.SMul +import Mathlib.Data.Finsupp.SMulWithZero +import Mathlib.Algebra.Group.Action.Basic + +/-! +# Declarations about scalar multiplication on `Finsupp` + +## Implementation notes + +This file is a `noncomputable theory` and uses classical logic throughout. + +-/ + + +noncomputable section + +open Finset Function + +variable {α β M N G R : Type*} + +namespace Finsupp + +section + +variable [Zero M] [MonoidWithZero R] [MulActionWithZero R M] + +@[simp] +theorem single_smul (a b : α) (f : α → M) (r : R) : single a r b • f a = single a (r • f b) b := by + by_cases h : a = b <;> simp [h] + +end + +section + +variable [Monoid G] [MulAction G α] [AddCommMonoid M] + +/-- Scalar multiplication acting on the domain. + +This is not an instance as it would conflict with the action on the range. +See the `instance_diamonds` test for examples of such conflicts. -/ +def comapSMul : SMul G (α →₀ M) where smul g := mapDomain (g • ·) + +attribute [local instance] comapSMul + +theorem comapSMul_def (g : G) (f : α →₀ M) : g • f = mapDomain (g • ·) f := + rfl + +@[simp] +theorem comapSMul_single (g : G) (a : α) (b : M) : g • single a b = single (g • a) b := + mapDomain_single + +/-- `Finsupp.comapSMul` is multiplicative -/ +def comapMulAction : MulAction G (α →₀ M) where + one_smul f := by rw [comapSMul_def, one_smul_eq_id, mapDomain_id] + mul_smul g g' f := by + rw [comapSMul_def, comapSMul_def, comapSMul_def, ← comp_smul_left, mapDomain_comp] + +attribute [local instance] comapMulAction + +/-- `Finsupp.comapSMul` is distributive -/ +def comapDistribMulAction : DistribMulAction G (α →₀ M) where + smul_zero g := by + ext a + simp only [comapSMul_def] + simp + smul_add g f f' := by + ext + simp only [comapSMul_def] + simp [mapDomain_add] + +end + +section + +variable [Group G] [MulAction G α] [AddCommMonoid M] + +attribute [local instance] comapSMul comapMulAction comapDistribMulAction + +/-- When `G` is a group, `Finsupp.comapSMul` acts by precomposition with the action of `g⁻¹`. +-/ +@[simp] +theorem comapSMul_apply (g : G) (f : α →₀ M) (a : α) : (g • f) a = f (g⁻¹ • a) := by + conv_lhs => rw [← smul_inv_smul g a] + exact mapDomain_apply (MulAction.injective g) _ (g⁻¹ • a) + +end + +section + +/-! +Throughout this section, some `Monoid` and `Semiring` arguments are specified with `{}` instead of +`[]`. See note [implicit instance arguments]. +-/ + +theorem _root_.IsSMulRegular.finsupp [Zero M] [SMulZeroClass R M] {k : R} + (hk : IsSMulRegular M k) : IsSMulRegular (α →₀ M) k := + fun _ _ h => ext fun i => hk (DFunLike.congr_fun h i) + +instance faithfulSMul [Nonempty α] [Zero M] [SMulZeroClass R M] [FaithfulSMul R M] : + FaithfulSMul R (α →₀ M) where + eq_of_smul_eq_smul h := + let ⟨a⟩ := ‹Nonempty α› + eq_of_smul_eq_smul fun m : M => by simpa using DFunLike.congr_fun (h (single a m)) a + +variable (α M) + +instance distribMulAction [Monoid R] [AddMonoid M] [DistribMulAction R M] : + DistribMulAction R (α →₀ M) := + { Finsupp.distribSMul _ _ with + one_smul := fun x => ext fun y => one_smul R (x y) + mul_smul := fun r s x => ext fun y => mul_smul r s (x y) } + +instance module [Semiring R] [AddCommMonoid M] [Module R M] : Module R (α →₀ M) := + { toDistribMulAction := Finsupp.distribMulAction α M + zero_smul := fun _ => ext fun _ => zero_smul _ _ + add_smul := fun _ _ _ => ext fun _ => add_smul _ _ _ } + +variable {α M} + +@[simp] +theorem support_smul_eq [Semiring R] [AddCommMonoid M] [Module R M] [NoZeroSMulDivisors R M] {b : R} + (hb : b ≠ 0) {g : α →₀ M} : (b • g).support = g.support := + Finset.ext fun a => by simp [Finsupp.smul_apply, hb] + +section + +variable {p : α → Prop} [DecidablePred p] + +@[simp] +theorem filter_smul {_ : Monoid R} [AddMonoid M] [DistribMulAction R M] {b : R} {v : α →₀ M} : + (b • v).filter p = b • v.filter p := + DFunLike.coe_injective <| by + simp only [filter_eq_indicator, coe_smul] + exact Set.indicator_const_smul { x | p x } b v + +end + +theorem mapDomain_smul {_ : Monoid R} [AddCommMonoid M] [DistribMulAction R M] {f : α → β} (b : R) + (v : α →₀ M) : mapDomain f (b • v) = b • mapDomain f v := + mapDomain_mapRange _ _ _ _ (smul_add b) + +theorem smul_single' {_ : Semiring R} (c : R) (a : α) (b : R) : + c • Finsupp.single a b = Finsupp.single a (c * b) := by simp + +theorem smul_single_one [Semiring R] (a : α) (b : R) : b • single a (1 : R) = single a b := by + rw [smul_single, smul_eq_mul, mul_one] + +theorem comapDomain_smul [AddMonoid M] [Monoid R] [DistribMulAction R M] {f : α → β} (r : R) + (v : β →₀ M) (hfv : Set.InjOn f (f ⁻¹' ↑v.support)) + (hfrv : Set.InjOn f (f ⁻¹' ↑(r • v).support) := + hfv.mono <| Set.preimage_mono <| Finset.coe_subset.mpr support_smul) : + comapDomain f (r • v) hfrv = r • comapDomain f v hfv := by + ext + rfl + +/-- A version of `Finsupp.comapDomain_smul` that's easier to use. -/ +theorem comapDomain_smul_of_injective [AddMonoid M] [Monoid R] [DistribMulAction R M] {f : α → β} + (hf : Function.Injective f) (r : R) (v : β →₀ M) : + comapDomain f (r • v) hf.injOn = r • comapDomain f v hf.injOn := + comapDomain_smul _ _ _ _ + +end + +theorem sum_smul_index [Semiring R] [AddCommMonoid M] {g : α →₀ R} {b : R} {h : α → R → M} + (h0 : ∀ i, h i 0 = 0) : (b • g).sum h = g.sum fun i a => h i (b * a) := + Finsupp.sum_mapRange_index h0 + +theorem sum_smul_index' [AddMonoid M] [DistribSMul R M] [AddCommMonoid N] {g : α →₀ M} {b : R} + {h : α → M → N} (h0 : ∀ i, h i 0 = 0) : (b • g).sum h = g.sum fun i c => h i (b • c) := + Finsupp.sum_mapRange_index h0 + +/-- A version of `Finsupp.sum_smul_index'` for bundled additive maps. -/ +theorem sum_smul_index_addMonoidHom [AddMonoid M] [AddCommMonoid N] [DistribSMul R M] {g : α →₀ M} + {b : R} {h : α → M →+ N} : ((b • g).sum fun a => h a) = g.sum fun i c => h i (b • c) := + sum_mapRange_index fun i => (h i).map_zero + +instance noZeroSMulDivisors [Zero R] [Zero M] [SMulZeroClass R M] {ι : Type*} + [NoZeroSMulDivisors R M] : NoZeroSMulDivisors R (ι →₀ M) := + ⟨fun h => or_iff_not_imp_left.mpr fun hc => Finsupp.ext fun i => + (eq_zero_or_eq_zero_of_smul_eq_zero (DFunLike.ext_iff.mp h i)).resolve_left hc⟩ + +section DistribMulActionSemiHom +variable [Monoid R] [AddMonoid M] [AddMonoid N] [DistribMulAction R M] [DistribMulAction R N] + +/-- `Finsupp.single` as a `DistribMulActionSemiHom`. + +See also `Finsupp.lsingle` for the version as a linear map. -/ +def DistribMulActionHom.single (a : α) : M →+[R] α →₀ M := + { singleAddHom a with + map_smul' := fun k m => by + simp only + show singleAddHom a (k • m) = k • singleAddHom a m + change Finsupp.single a (k • m) = k • (Finsupp.single a m) + -- Porting note: because `singleAddHom_apply` is missing + simp only [smul_single] } + +theorem distribMulActionHom_ext {f g : (α →₀ M) →+[R] N} + (h : ∀ (a : α) (m : M), f (single a m) = g (single a m)) : f = g := + DistribMulActionHom.toAddMonoidHom_injective <| addHom_ext h + +/-- See note [partially-applied ext lemmas]. -/ +@[ext] +theorem distribMulActionHom_ext' {f g : (α →₀ M) →+[R] N} + (h : ∀ a : α, f.comp (DistribMulActionHom.single a) = g.comp (DistribMulActionHom.single a)) : + f = g := + distribMulActionHom_ext fun a => DistribMulActionHom.congr_fun (h a) + +end DistribMulActionSemiHom + +end Finsupp diff --git a/Mathlib/Data/Finsupp/ToDFinsupp.lean b/Mathlib/Data/Finsupp/ToDFinsupp.lean index 5174a0b7e5313..a88307479c0c3 100644 --- a/Mathlib/Data/Finsupp/ToDFinsupp.lean +++ b/Mathlib/Data/Finsupp/ToDFinsupp.lean @@ -5,7 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.Algebra.Module.Equiv.Defs import Mathlib.Data.DFinsupp.Module -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMul /-! # Conversion between `Finsupp` and homogeneous `DFinsupp` diff --git a/Mathlib/LinearAlgebra/Finsupp/Defs.lean b/Mathlib/LinearAlgebra/Finsupp/Defs.lean index 4b42fe2e28994..231b4559de7ce 100644 --- a/Mathlib/LinearAlgebra/Finsupp/Defs.lean +++ b/Mathlib/LinearAlgebra/Finsupp/Defs.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl -/ import Mathlib.Algebra.Module.Equiv.Defs import Mathlib.Algebra.Module.Pi -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMul /-! # Properties of the module `α →₀ M` diff --git a/Mathlib/LinearAlgebra/Finsupp/SumProd.lean b/Mathlib/LinearAlgebra/Finsupp/SumProd.lean index 71db91ba13f99..8d2de8b73eb78 100644 --- a/Mathlib/LinearAlgebra/Finsupp/SumProd.lean +++ b/Mathlib/LinearAlgebra/Finsupp/SumProd.lean @@ -6,7 +6,7 @@ Authors: Johannes Hölzl import Mathlib.Algebra.Module.Equiv.Defs import Mathlib.Algebra.Module.Pi import Mathlib.Algebra.Module.Prod -import Mathlib.Data.Finsupp.Basic +import Mathlib.Data.Finsupp.SMul /-! # Finsupps and sum/product types From 4f099bd210f1e8fd69959e6fce639d11f2fb0e69 Mon Sep 17 00:00:00 2001 From: Anne Baanen Date: Thu, 30 Jan 2025 16:37:34 +0000 Subject: [PATCH 678/681] feat(Algebra/Category): concrete category refactor for `MonCat` (#21222) This is a step towards a concrete category redesign, as outlined in this Zulip post: https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Concrete.20category.20class.20redesign/near/493903980 This PR updates the concrete category definitions of (Add)(Comm)MonCat to match the standard set by AlgebraCat, ModuleCat and RingCat: * Package objects and homs into structures. * Replace HasForget with ConcreteCategory. * Set up a good @[simp] set. * Ensure constructors and projections are reducible. See MathlibTest/CategoryTheory/ConcreteCategory/MonCat.lean for the specification of all the new functionality. Currently there are still a couple issues around actions and tensor products, where `simp [the_lemma]` doesn't work even though `simp [(the_lemma)]` does. Not sure why this is happening, the discrimination tree keys look perfectly normal and `trace.Meta.Tactic.simp` doesn't say anything useful. I have not tried to look for code that can be cleaned up now, only at what broke. I want to get started on cleanup when the other concrete category instances are in. --- Mathlib/Algebra/Category/Grp/Adjunctions.lean | 47 +- .../Category/Grp/FilteredColimits.lean | 9 +- Mathlib/Algebra/Category/Grp/Limits.lean | 5 +- Mathlib/Algebra/Category/GrpWithZero.lean | 5 +- .../Algebra/Category/MonCat/Adjunctions.lean | 31 +- Mathlib/Algebra/Category/MonCat/Basic.lean | 418 ++++++++++++------ Mathlib/Algebra/Category/MonCat/Colimits.lean | 34 +- .../Category/MonCat/FilteredColimits.lean | 88 ++-- .../MonCat/ForgetCorepresentable.lean | 12 +- Mathlib/Algebra/Category/MonCat/Limits.lean | 28 +- Mathlib/Algebra/Category/Ring/Basic.lean | 6 +- .../Category/Ring/FilteredColimits.lean | 16 +- .../Abelian/Pseudoelements.lean | 2 +- Mathlib/CategoryTheory/Action/Basic.lean | 38 +- Mathlib/CategoryTheory/Action/Concrete.lean | 9 +- Mathlib/CategoryTheory/Action/Monoidal.lean | 28 +- Mathlib/CategoryTheory/Galois/Examples.lean | 6 +- .../Monoidal/Internal/Types.lean | 12 +- Mathlib/CategoryTheory/SingleObj.lean | 8 +- Mathlib/RepresentationTheory/FDRep.lean | 10 +- .../GroupCohomology/Resolution.lean | 6 +- Mathlib/RepresentationTheory/Rep.lean | 4 +- .../ConcreteCategory/MonCat.lean | 50 +++ MathlibTest/MonCat.lean | 4 +- 24 files changed, 558 insertions(+), 318 deletions(-) create mode 100644 MathlibTest/CategoryTheory/ConcreteCategory/MonCat.lean diff --git a/Mathlib/Algebra/Category/Grp/Adjunctions.lean b/Mathlib/Algebra/Category/Grp/Adjunctions.lean index 6f09e708ff764..3f57ab7f389c8 100644 --- a/Mathlib/Algebra/Category/Grp/Adjunctions.lean +++ b/Mathlib/Algebra/Category/Grp/Adjunctions.lean @@ -31,7 +31,6 @@ category of abelian groups. abelian groups to groups. -/ - noncomputable section universe u @@ -169,35 +168,35 @@ end Abelianization end Grp /-- The functor taking a monoid to its subgroup of units. -/ -@[simps] +@[simps!] def MonCat.units : MonCat.{u} ⥤ Grp.{u} where obj R := Grp.of Rˣ - map f := Grp.ofHom <| Units.map f + map f := Grp.ofHom <| Units.map f.hom map_id _ := Grp.ext fun _ => Units.ext rfl map_comp _ _ := Grp.ext fun _ => Units.ext rfl /-- The forgetful-units adjunction between `Grp` and `MonCat`. -/ def Grp.forget₂MonAdj : forget₂ Grp MonCat ⊣ MonCat.units.{u} := Adjunction.mk' { - homEquiv := fun _ Y ↦ - { toFun := fun f => ofHom (MonoidHom.toHomUnits f) - invFun := fun f => (Units.coeHom Y).comp f.hom - left_inv := fun _ => MonoidHom.ext fun _ => rfl - right_inv := fun _ => Grp.ext fun _ => Units.ext rfl } + homEquiv _ Y := + { toFun f := ofHom (MonoidHom.toHomUnits f.hom) + invFun f := MonCat.ofHom ((Units.coeHom Y).comp f.hom) + left_inv _ := MonCat.ext fun _ => rfl + right_inv _ := Grp.ext fun _ => Units.ext rfl } unit := - { app := fun X => ofHom { (@toUnits X _).toMonoidHom with } - naturality := fun _ _ _ => Grp.ext fun _ => Units.ext rfl } + { app X := ofHom (@toUnits X _) + naturality _ _ _ := Grp.ext fun _ => Units.ext rfl } counit := - { app := fun X => Units.coeHom X - naturality := by intros; exact MonoidHom.ext fun x => rfl } } + { app X := MonCat.ofHom (Units.coeHom X) + naturality _ _ _ := MonCat.ext fun _ => rfl } } instance : MonCat.units.{u}.IsRightAdjoint := ⟨_, ⟨Grp.forget₂MonAdj⟩⟩ /-- The functor taking a monoid to its subgroup of units. -/ -@[simps] +@[simps!] def CommMonCat.units : CommMonCat.{u} ⥤ CommGrp.{u} where obj R := CommGrp.of Rˣ - map f := CommGrp.ofHom <| Units.map f + map f := CommGrp.ofHom <| Units.map f.hom map_id _ := CommGrp.ext fun _ => Units.ext rfl map_comp _ _ := CommGrp.ext fun _ => Units.ext rfl @@ -205,12 +204,20 @@ def CommMonCat.units : CommMonCat.{u} ⥤ CommGrp.{u} where def CommGrp.forget₂CommMonAdj : forget₂ CommGrp CommMonCat ⊣ CommMonCat.units.{u} := Adjunction.mk' { homEquiv := fun _ Y ↦ - { toFun := fun f => ofHom (MonoidHom.toHomUnits f) - invFun := fun f => (Units.coeHom Y).comp f.hom - left_inv := fun _ => MonoidHom.ext fun _ => rfl - right_inv := fun _ => CommGrp.ext fun _ => Units.ext rfl } - unit := { app := fun X => ofHom { (@toUnits X _).toMonoidHom with } } - counit := { app := fun X => Units.coeHom X } } + { toFun f := ofHom (MonoidHom.toHomUnits f.hom) + invFun f := CommMonCat.ofHom ((Units.coeHom Y).comp f.hom) + left_inv _ := CommMonCat.ext fun _ => rfl + right_inv _ := CommGrp.ext fun _ => Units.ext rfl } + unit.app X := ofHom toUnits.toMonoidHom + -- `aesop` can find the following proof but it takes `0.5`s. + unit.naturality _ _ _ := CommGrp.ext fun _ => Units.ext rfl + counit.app X := CommMonCat.ofHom (Units.coeHom X) + -- `aesop` can find the following proof but it takes `0.5`s. + counit.naturality _ _ _ := CommMonCat.ext fun _ => rfl + -- `aesop` can find the following proof but it takes `0.2`s. + homEquiv_unit := by intros; rfl + -- `aesop` can find the following proof but it takes `0.2`s. + homEquiv_counit := by intros; rfl } instance : CommMonCat.units.{u}.IsRightAdjoint := ⟨_, ⟨CommGrp.forget₂CommMonAdj⟩⟩ diff --git a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean index 8e3c983dc3ac7..4871bf67a4a0f 100644 --- a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean @@ -108,16 +108,17 @@ noncomputable def colimit : Grp.{max v u} := @[to_additive "The cocone over the proposed colimit additive group."] noncomputable def colimitCocone : Cocone F where pt := colimit.{v, u} F - ι.app J := Grp.ofHom ((MonCat.FilteredColimits.colimitCocone (F ⋙ forget₂ Grp MonCat)).ι.app J) + ι.app J := Grp.ofHom ((MonCat.FilteredColimits.colimitCocone + (F ⋙ forget₂ Grp MonCat)).ι.app J).hom ι.naturality _ _ f := (forget₂ _ MonCat).map_injective ((MonCat.FilteredColimits.colimitCocone _).ι.naturality f) /-- The proposed colimit cocone is a colimit in `Grp`. -/ @[to_additive "The proposed colimit cocone is a colimit in `AddGroup`."] def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where - desc t := Grp.ofHom <| - MonCat.FilteredColimits.colimitDesc.{v, u} (F ⋙ forget₂ Grp MonCat.{max v u}) - ((forget₂ Grp MonCat).mapCocone t) + desc t := Grp.ofHom + (MonCat.FilteredColimits.colimitDesc.{v, u} (F ⋙ forget₂ Grp MonCat.{max v u}) + ((forget₂ Grp MonCat).mapCocone t)).hom fac t j := ConcreteCategory.coe_ext <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget Grp)).fac diff --git a/Mathlib/Algebra/Category/Grp/Limits.lean b/Mathlib/Algebra/Category/Grp/Limits.lean index 905e3eb22d753..e5503315b1ad5 100644 --- a/Mathlib/Algebra/Category/Grp/Limits.lean +++ b/Mathlib/Algebra/Category/Grp/Limits.lean @@ -95,7 +95,7 @@ noncomputable instance Forget₂.createsLimit : { pt := Grp.of (Types.Small.limitCone (F ⋙ forget Grp)).pt π := { app j := ofHom <| MonCat.limitπMonoidHom (F ⋙ forget₂ Grp MonCat) j - naturality i j h:= hom_ext <| + naturality i j h:= hom_ext <| congr_arg MonCat.Hom.hom <| (MonCat.HasLimits.limitCone (F ⋙ forget₂ Grp MonCat.{u})).π.naturality h } } validLift := by apply IsLimit.uniqueUpToIso (MonCat.HasLimits.limitConeIsLimit.{v, u} _) t @@ -263,7 +263,8 @@ noncomputable instance Forget₂.createsLimit : π := { app j := ofHom <| MonCat.limitπMonoidHom (F ⋙ forget₂ CommGrp Grp.{u} ⋙ forget₂ Grp MonCat.{u}) j - naturality i j h := hom_ext <| (MonCat.HasLimits.limitCone _).π.naturality h } } + naturality i j h := hom_ext <| congr_arg MonCat.Hom.hom <| + (MonCat.HasLimits.limitCone _).π.naturality h } } validLift := by apply IsLimit.uniqueUpToIso (Grp.limitConeIsLimit _) hc makesLimit := IsLimit.ofFaithful (forget₂ _ Grp.{u} ⋙ forget₂ _ MonCat.{u}) diff --git a/Mathlib/Algebra/Category/GrpWithZero.lean b/Mathlib/Algebra/Category/GrpWithZero.lean index 217c743141244..7b63ccb5a2f17 100644 --- a/Mathlib/Algebra/Category/GrpWithZero.lean +++ b/Mathlib/Algebra/Category/GrpWithZero.lean @@ -6,6 +6,7 @@ Authors: Yaël Dillies import Mathlib.Algebra.Category.MonCat.Basic import Mathlib.Algebra.GroupWithZero.WithZero import Mathlib.CategoryTheory.Category.Bipointed +import Mathlib.CategoryTheory.ConcreteCategory.Bundled /-! # The category of groups with zero @@ -72,8 +73,8 @@ instance hasForgetToBipointed : HasForget₂ GrpWithZero Bipointed where instance hasForgetToMon : HasForget₂ GrpWithZero MonCat where forget₂ := - { obj := fun X => ⟨ X , _ ⟩ - map := fun f => f.toMonoidHom } + { obj := fun X => MonCat.of X + map := fun f => MonCat.ofHom f.toMonoidHom } /-- Constructs an isomorphism of groups with zero from a group isomorphism between them. -/ @[simps] diff --git a/Mathlib/Algebra/Category/MonCat/Adjunctions.lean b/Mathlib/Algebra/Category/MonCat/Adjunctions.lean index 256b8f3478523..d4219c84e035f 100644 --- a/Mathlib/Algebra/Category/MonCat/Adjunctions.lean +++ b/Mathlib/Algebra/Category/MonCat/Adjunctions.lean @@ -32,43 +32,38 @@ namespace MonCat @[to_additive (attr := simps) "The functor of adjoining a neutral element `zero` to a semigroup"] def adjoinOne : Semigrp.{u} ⥤ MonCat.{u} where obj S := MonCat.of (WithOne S) - map := WithOne.map - map_id _ := WithOne.map_id - map_comp := WithOne.map_comp + map f := ofHom (WithOne.map f) + map_id _ := MonCat.hom_ext WithOne.map_id + map_comp _ _ := MonCat.hom_ext (WithOne.map_comp _ _) @[to_additive] instance hasForgetToSemigroup : HasForget₂ MonCat Semigrp where forget₂ := { obj := fun M => Semigrp.of M - map := MonoidHom.toMulHom } + map f := f.hom.toMulHom } /-- The `adjoinOne`-forgetful adjunction from `Semigrp` to `MonCat`. -/ @[to_additive "The `adjoinZero`-forgetful adjunction from `AddSemigrp` to `AddMonCat`"] def adjoinOneAdj : adjoinOne ⊣ forget₂ MonCat.{u} Semigrp.{u} := Adjunction.mkOfHomEquiv - { homEquiv := fun _ _ => WithOne.lift.symm + { homEquiv := fun _ _ => ConcreteCategory.homEquiv.trans WithOne.lift.symm homEquiv_naturality_left_symm := by - intro S T M f g - ext x - simp only [Equiv.symm_symm, adjoinOne_map, coe_comp] - simp_rw [WithOne.map] - cases x - · rfl - · simp - rfl } + intros + ext ⟨_|_⟩ <;> simp <;> rfl } /-- The free functor `Type u ⥤ MonCat` sending a type `X` to the free monoid on `X`. -/ def free : Type u ⥤ MonCat.{u} where obj α := MonCat.of (FreeMonoid α) - map := FreeMonoid.map - map_id _ := FreeMonoid.hom_eq (fun _ => rfl) - map_comp _ _ := FreeMonoid.hom_eq (fun _ => rfl) + map f := ofHom (FreeMonoid.map f) + map_id _ := MonCat.hom_ext (FreeMonoid.hom_eq fun _ => rfl) + map_comp _ _ := MonCat.hom_ext (FreeMonoid.hom_eq fun _ => rfl) /-- The free-forgetful adjunction for monoids. -/ def adj : free ⊣ forget MonCat.{u} := Adjunction.mkOfHomEquiv - { homEquiv := fun _ _ => FreeMonoid.lift.symm - homEquiv_naturality_left_symm := fun _ _ => FreeMonoid.hom_eq (fun _ => rfl) } + -- The hint `(C := MonCat)` below speeds up the declaration by 10 times. + { homEquiv X Y := (ConcreteCategory.homEquiv (C := MonCat)).trans FreeMonoid.lift.symm + homEquiv_naturality_left_symm _ _ := MonCat.hom_ext (FreeMonoid.hom_eq fun _ => rfl) } instance : (forget MonCat.{u}).IsRightAdjoint := ⟨_, ⟨adj⟩⟩ diff --git a/Mathlib/Algebra/Category/MonCat/Basic.lean b/Mathlib/Algebra/Category/MonCat/Basic.lean index d4f9913d7d062..fe6007c4709ff 100644 --- a/Mathlib/Algebra/Category/MonCat/Basic.lean +++ b/Mathlib/Algebra/Category/MonCat/Basic.lean @@ -5,7 +5,7 @@ Authors: Kim Morrison -/ import Mathlib.Algebra.PUnitInstances.Algebra import Mathlib.Algebra.Group.ULift -import Mathlib.CategoryTheory.ConcreteCategory.BundledHom +import Mathlib.CategoryTheory.ConcreteCategory.Basic import Mathlib.CategoryTheory.Functor.ReflectsIso import Mathlib.Algebra.Ring.Action.Group @@ -24,59 +24,89 @@ universe u v open CategoryTheory -/-- The category of monoids and monoid morphisms. -/ +/-- The category of additive groups and group morphisms. -/ +structure AddMonCat : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : AddMonoid carrier] + +/-- The category of groups and group morphisms. -/ @[to_additive AddMonCat] -def MonCat : Type (u + 1) := - Bundled Monoid +structure MonCat : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : Monoid carrier] + +attribute [instance] AddMonCat.str MonCat.str +attribute [to_additive existing] MonCat.carrier MonCat.str -/-- The category of additive monoids and monoid morphisms. -/ -add_decl_doc AddMonCat +initialize_simps_projections AddMonCat (carrier → coe, -str) +initialize_simps_projections MonCat (carrier → coe, -str) namespace MonCat -/-- `MonoidHom` doesn't actually assume associativity. This alias is needed to make the category -theory machinery work. -/ @[to_additive] -abbrev AssocMonoidHom (M N : Type*) [Monoid M] [Monoid N] := - MonoidHom M N +instance : CoeSort MonCat (Type u) := + ⟨MonCat.carrier⟩ -/-- `AddMonoidHom` doesn't actually assume associativity. This alias is needed to make -the category theory machinery work. -/ -add_decl_doc AddMonCat.AssocAddMonoidHom +attribute [coe] AddMonCat.carrier MonCat.carrier -@[to_additive] -instance bundledHom : BundledHom AssocMonoidHom where - toFun {_ _} _ _ f := ⇑f - id _ := MonoidHom.id _ - comp _ _ _ := MonoidHom.comp +/-- Construct a bundled `MonCat` from the underlying type and typeclass. -/ +@[to_additive "Construct a bundled `AddMonCat` from the underlying type and typeclass."] +abbrev of (M : Type u) [Monoid M] : MonCat := ⟨M⟩ -deriving instance LargeCategory for MonCat -attribute [to_additive instAddMonCatLargeCategory] instMonCatLargeCategory +end MonCat --- Porting note: https://github.com/leanprover-community/mathlib4/issues/5020 -@[to_additive] -instance hasForget : HasForget MonCat := - BundledHom.hasForget _ +/-- The type of morphisms in `AddMonCat R`. -/ +@[ext] +structure AddMonCat.Hom (A B : AddMonCat.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →+ B -@[to_additive] -instance : CoeSort MonCat Type* where - coe X := X.α +/-- The type of morphisms in `MonCat R`. -/ +@[to_additive, ext] +structure MonCat.Hom (A B : MonCat.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →* B -@[to_additive] -instance (X : MonCat) : Monoid X := X.str +attribute [to_additive existing AddMonCat.Hom.mk] MonCat.Hom.mk --- Porting note (https://github.com/leanprover-community/mathlib4/pull/10670): this instance was not necessary in mathlib -@[to_additive] -instance {X Y : MonCat} : CoeFun (X ⟶ Y) fun _ => X → Y where - coe (f : X →* Y) := f +namespace MonCat @[to_additive] -instance instFunLike (X Y : MonCat) : FunLike (X ⟶ Y) X Y := - inferInstanceAs <| FunLike (X →* Y) X Y +instance : Category MonCat.{u} where + Hom X Y := Hom X Y + id X := ⟨MonoidHom.id X⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ @[to_additive] -instance instMonoidHomClass (X Y : MonCat) : MonoidHomClass (X ⟶ Y) X Y := - inferInstanceAs <| MonoidHomClass (X →* Y) X Y +instance : ConcreteCategory MonCat (· →* ·) where + hom := Hom.hom' + ofHom := Hom.mk + +/-- Turn a morphism in `MonCat` back into a `MonoidHom`. -/ +@[to_additive "Turn a morphism in `AddMonCat` back into an `AddMonoidHom`."] +abbrev Hom.hom {X Y : MonCat.{u}} (f : Hom X Y) := + ConcreteCategory.hom (C := MonCat) f + +/-- Typecheck a `MonoidHom` as a morphism in `MonCat`. -/ +@[to_additive "Typecheck an `AddMonoidHom` as a morphism in `AddMonCat`. "] +abbrev ofHom {X Y : Type u} [Monoid X] [Monoid Y] (f : X →* Y) : of X ⟶ of Y := + ConcreteCategory.ofHom (C := MonCat) f + +variable {R} in +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +def Hom.Simps.hom (X Y : MonCat.{u}) (f : Hom X Y) := + f.hom + +initialize_simps_projections Hom (hom' → hom) +initialize_simps_projections AddMonCat.Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[to_additive (attr := simp)] lemma coe_id {X : MonCat} : (𝟙 X : X → X) = id := rfl @@ -84,52 +114,85 @@ lemma coe_id {X : MonCat} : (𝟙 X : X → X) = id := rfl @[to_additive (attr := simp)] lemma coe_comp {X Y Z : MonCat} {f : X ⟶ Y} {g : Y ⟶ Z} : (f ≫ g : X → Z) = g ∘ f := rfl -@[to_additive (attr := simp)] lemma forget_map {X Y : MonCat} (f : X ⟶ Y) : +@[to_additive (attr := simp)] +lemma forget_map {X Y : MonCat} (f : X ⟶ Y) : (forget MonCat).map f = f := rfl @[to_additive (attr := ext)] lemma ext {X Y : MonCat} {f g : X ⟶ Y} (w : ∀ x : X, f x = g x) : f = g := - MonoidHom.ext w + ConcreteCategory.hom_ext _ _ w -/-- Construct a bundled `MonCat` from the underlying type and typeclass. -/ @[to_additive] -def of (M : Type u) [Monoid M] : MonCat := - Bundled.of M +-- This is not `simp` to avoid rewriting in types of terms. +theorem coe_of (M : Type u) [Monoid M] : (MonCat.of M : Type u) = M := rfl -/-- Construct a bundled `AddMonCat` from the underlying type and typeclass. -/ -add_decl_doc AddMonCat.of +@[to_additive (attr := simp)] +lemma hom_id {M : MonCat} : (𝟙 M : M ⟶ M).hom = MonoidHom.id M := rfl --- Porting note: removed `@[simp]` here, as it makes it harder to tell when to apply --- bundled or unbundled lemmas. --- (This change seems dangerous!) +/- Provided for rewriting. -/ @[to_additive] -theorem coe_of (R : Type u) [Monoid R] : (MonCat.of R : Type u) = R := rfl +lemma id_apply (M : MonCat) (x : M) : + (𝟙 M : M ⟶ M) x = x := by simp -@[to_additive] -instance : Inhabited MonCat := - -- The default instance for `Monoid PUnit` is derived via `CommRing` which breaks to_additive - ⟨@of PUnit (@DivInvMonoid.toMonoid _ (@Group.toDivInvMonoid _ - (@CommGroup.toGroup _ PUnit.commGroup)))⟩ +@[to_additive (attr := simp)] +lemma hom_comp {M N T : MonCat} (f : M ⟶ N) (g : N ⟶ T) : + (f ≫ g).hom = g.hom.comp f.hom := rfl -/-- Typecheck a `MonoidHom` as a morphism in `MonCat`. -/ +/- Provided for rewriting. -/ @[to_additive] -def ofHom {X Y : Type u} [Monoid X] [Monoid Y] (f : X →* Y) : of X ⟶ of Y := f +lemma comp_apply {M N T : MonCat} (f : M ⟶ N) (g : N ⟶ T) (x : M) : + (f ≫ g) x = g (f x) := by simp + +@[to_additive (attr := ext)] +lemma hom_ext {M N : MonCat} {f g : M ⟶ N} (hf : f.hom = g.hom) : f = g := + Hom.ext hf -/-- Typecheck an `AddMonoidHom` as a morphism in `AddMonCat`. -/ -add_decl_doc AddMonCat.ofHom +@[to_additive (attr := simp)] +lemma hom_ofHom {M N : Type u} [Monoid M] [Monoid N] (f : M →* N) : + (ofHom f).hom = f := rfl @[to_additive (attr := simp)] +lemma ofHom_hom {M N : MonCat} (f : M ⟶ N) : + ofHom (Hom.hom f) = f := rfl + +@[to_additive (attr := simp)] +lemma ofHom_id {M : Type u} [Monoid M] : ofHom (MonoidHom.id M) = 𝟙 (of M) := rfl + +@[to_additive (attr := simp)] +lemma ofHom_comp {M N P : Type u} [Monoid M] [Monoid N] [Monoid P] + (f : M →* N) (g : N →* P) : + ofHom (g.comp f) = ofHom f ≫ ofHom g := + rfl + +@[to_additive] lemma ofHom_apply {X Y : Type u} [Monoid X] [Monoid Y] (f : X →* Y) (x : X) : (ofHom f) x = f x := rfl ----- Porting note: added to ease the port of `CategoryTheory.Action.Basic` +@[to_additive (attr := simp)] +lemma inv_hom_apply {M N : MonCat} (e : M ≅ N) (x : M) : e.inv (e.hom x) = x := by + rw [← comp_apply] + simp + +@[to_additive (attr := simp)] +lemma hom_inv_apply {M N : MonCat} (e : M ≅ N) (s : N) : e.hom (e.inv s) = s := by + rw [← comp_apply] + simp + +@[to_additive] +instance : Inhabited MonCat := + -- The default instance for `Monoid PUnit` is derived via `CommRing` which breaks to_additive + ⟨@of PUnit (@DivInvMonoid.toMonoid _ (@Group.toDivInvMonoid _ + (@CommGroup.toGroup _ PUnit.commGroup)))⟩ + @[to_additive] instance (X Y : MonCat.{u}) : One (X ⟶ Y) := ⟨ofHom 1⟩ @[to_additive (attr := simp)] -lemma oneHom_apply (X Y : MonCat.{u}) (x : X) : (1 : X ⟶ Y) x = 1 := rfl +lemma hom_one (X Y : MonCat.{u}) : (1 : X ⟶ Y).hom = 1 := rfl + +@[to_additive] +lemma oneHom_apply (X Y : MonCat.{u}) (x : X) : (1 : X ⟶ Y).hom x = 1 := rfl ----- Porting note: added to ease the port of `CategoryTheory.Action.Basic` @[to_additive (attr := simp)] lemma one_of {A : Type*} [Monoid A] : (1 : MonCat.of A) = (1 : A) := rfl @@ -137,58 +200,101 @@ lemma one_of {A : Type*} [Monoid A] : (1 : MonCat.of A) = (1 : A) := rfl lemma mul_of {A : Type*} [Monoid A] (a b : A) : @HMul.hMul (MonCat.of A) (MonCat.of A) (MonCat.of A) _ a b = a * b := rfl -@[to_additive] -instance {G : Type*} [Group G] : Group (MonCat.of G) := by assumption - /-- Universe lift functor for monoids. -/ @[to_additive (attr := simps) "Universe lift functor for additive monoids."] def uliftFunctor : MonCat.{v} ⥤ MonCat.{max v u} where obj X := MonCat.of (ULift.{u, v} X) map {_ _} f := MonCat.ofHom <| - MulEquiv.ulift.symm.toMonoidHom.comp <| f.comp MulEquiv.ulift.toMonoidHom + MulEquiv.ulift.symm.toMonoidHom.comp <| f.hom.comp MulEquiv.ulift.toMonoidHom map_id X := by rfl map_comp {X Y Z} f g := by rfl end MonCat -/-- The category of commutative monoids and monoid morphisms. -/ +/-- The category of additive groups and group morphisms. -/ +structure AddCommMonCat : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : AddCommMonoid carrier] + +/-- The category of groups and group morphisms. -/ @[to_additive AddCommMonCat] -def CommMonCat : Type (u + 1) := - Bundled CommMonoid +structure CommMonCat : Type (u + 1) where + /-- The underlying type. -/ + (carrier : Type u) + [str : CommMonoid carrier] -/-- The category of additive commutative monoids and monoid morphisms. -/ -add_decl_doc AddCommMonCat +attribute [instance] AddCommMonCat.str CommMonCat.str +attribute [to_additive existing] CommMonCat.carrier CommMonCat.str + +initialize_simps_projections AddCommMonCat (carrier → coe, -str) +initialize_simps_projections CommMonCat (carrier → coe, -str) namespace CommMonCat @[to_additive] -instance : BundledHom.ParentProjection @CommMonoid.toMonoid := ⟨⟩ +instance : CoeSort CommMonCat (Type u) := + ⟨CommMonCat.carrier⟩ -deriving instance LargeCategory for CommMonCat -attribute [to_additive instAddCommMonCatLargeCategory] instCommMonCatLargeCategory +attribute [coe] AddCommMonCat.carrier CommMonCat.carrier --- Porting note: https://github.com/leanprover-community/mathlib4/issues/5020 -@[to_additive] -instance hasForget : HasForget CommMonCat := by - dsimp only [CommMonCat] - infer_instance +/-- Construct a bundled `CommMonCat` from the underlying type and typeclass. -/ +@[to_additive "Construct a bundled `AddCommMonCat` from the underlying type and typeclass."] +abbrev of (M : Type u) [CommMonoid M] : CommMonCat := ⟨M⟩ -@[to_additive] -instance : CoeSort CommMonCat Type* where - coe X := X.α +end CommMonCat -@[to_additive] -instance (X : CommMonCat) : CommMonoid X := X.str +/-- The type of morphisms in `AddCommMonCat R`. -/ +@[ext] +structure AddCommMonCat.Hom (A B : AddCommMonCat.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →+ B + +/-- The type of morphisms in `CommMonCat R`. -/ +@[to_additive, ext] +structure CommMonCat.Hom (A B : CommMonCat.{u}) where + private mk :: + /-- The underlying monoid homomorphism. -/ + hom' : A →* B + +attribute [to_additive existing AddCommMonCat.Hom.mk] CommMonCat.Hom.mk + +namespace CommMonCat --- Porting note (https://github.com/leanprover-community/mathlib4/pull/10670): this instance was not necessary in mathlib @[to_additive] -instance {X Y : CommMonCat} : CoeFun (X ⟶ Y) fun _ => X → Y where - coe (f : X →* Y) := f +instance : Category CommMonCat.{u} where + Hom X Y := Hom X Y + id X := ⟨MonoidHom.id X⟩ + comp f g := ⟨g.hom'.comp f.hom'⟩ @[to_additive] -instance instFunLike (X Y : CommMonCat) : FunLike (X ⟶ Y) X Y := - show FunLike (X →* Y) X Y by infer_instance +instance : ConcreteCategory CommMonCat (· →* ·) where + hom := Hom.hom' + ofHom := Hom.mk + +/-- Turn a morphism in `CommMonCat` back into a `MonoidHom`. -/ +@[to_additive "Turn a morphism in `AddCommMonCat` back into an `AddMonoidHom`."] +abbrev Hom.hom {X Y : CommMonCat.{u}} (f : Hom X Y) := + ConcreteCategory.hom (C := CommMonCat) f + +/-- Typecheck a `MonoidHom` as a morphism in `CommMonCat`. -/ +@[to_additive "Typecheck an `AddMonoidHom` as a morphism in `AddCommMonCat`. "] +abbrev ofHom {X Y : Type u} [CommMonoid X] [CommMonoid Y] (f : X →* Y) : of X ⟶ of Y := + ConcreteCategory.ofHom (C := CommMonCat) f + +/-- Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas. -/ +@[to_additive "Use the `ConcreteCategory.hom` projection for `@[simps]` lemmas."] +def Hom.Simps.hom (X Y : CommMonCat.{u}) (f : Hom X Y) := + f.hom + +initialize_simps_projections Hom (hom' → hom) +initialize_simps_projections AddCommMonCat.Hom (hom' → hom) + +/-! +The results below duplicate the `ConcreteCategory` simp lemmas, but we can keep them for `dsimp`. +-/ @[to_additive (attr := simp)] lemma coe_id {X : CommMonCat} : (𝟙 X : X → X) = id := rfl @@ -203,46 +309,88 @@ lemma forget_map {X Y : CommMonCat} (f : X ⟶ Y) : @[to_additive (attr := ext)] lemma ext {X Y : CommMonCat} {f g : X ⟶ Y} (w : ∀ x : X, f x = g x) : f = g := - MonoidHom.ext w + ConcreteCategory.hom_ext _ _ w + +@[to_additive (attr := simp)] +lemma hom_id {M : CommMonCat} : (𝟙 M : M ⟶ M).hom = MonoidHom.id M := rfl + +/- Provided for rewriting. -/ +@[to_additive] +lemma id_apply (M : CommMonCat) (x : M) : + (𝟙 M : M ⟶ M) x = x := by simp + +@[to_additive (attr := simp)] +lemma hom_comp {M N T : CommMonCat} (f : M ⟶ N) (g : N ⟶ T) : + (f ≫ g).hom = g.hom.comp f.hom := rfl + +/- Provided for rewriting. -/ +@[to_additive] +lemma comp_apply {M N T : CommMonCat} (f : M ⟶ N) (g : N ⟶ T) (x : M) : + (f ≫ g) x = g (f x) := by simp + +@[to_additive (attr := ext)] +lemma hom_ext {M N : CommMonCat} {f g : M ⟶ N} (hf : f.hom = g.hom) : f = g := + Hom.ext hf + +@[to_additive (attr := simp)] +lemma hom_ofHom {M N : Type u} [CommMonoid M] [CommMonoid N] (f : M →* N) : + (ofHom f).hom = f := rfl + +@[to_additive (attr := simp)] +lemma ofHom_hom {M N : CommMonCat} (f : M ⟶ N) : + ofHom (Hom.hom f) = f := rfl + +@[to_additive (attr := simp)] +lemma ofHom_id {M : Type u} [CommMonoid M] : ofHom (MonoidHom.id M) = 𝟙 (of M) := rfl + +@[to_additive (attr := simp)] +lemma ofHom_comp {M N P : Type u} [CommMonoid M] [CommMonoid N] [CommMonoid P] + (f : M →* N) (g : N →* P) : + ofHom (g.comp f) = ofHom f ≫ ofHom g := + rfl -/-- Construct a bundled `CommMonCat` from the underlying type and typeclass. -/ @[to_additive] -def of (M : Type u) [CommMonoid M] : CommMonCat := - Bundled.of M +lemma ofHom_apply {X Y : Type u} [CommMonoid X] [CommMonoid Y] (f : X →* Y) (x : X) : + (ofHom f) x = f x := rfl + +@[to_additive (attr := simp)] +lemma inv_hom_apply {M N : CommMonCat} (e : M ≅ N) (x : M) : e.inv (e.hom x) = x := by + rw [← comp_apply] + simp -/-- Construct a bundled `AddCommMonCat` from the underlying type and typeclass. -/ -add_decl_doc AddCommMonCat.of +@[to_additive (attr := simp)] +lemma hom_inv_apply {M N : CommMonCat} (e : M ≅ N) (s : N) : e.hom (e.inv s) = s := by + rw [← comp_apply] + simp @[to_additive] instance : Inhabited CommMonCat := -- The default instance for `CommMonoid PUnit` is derived via `CommRing` which breaks to_additive ⟨@of PUnit (@CommGroup.toCommMonoid _ PUnit.commGroup)⟩ --- Porting note: removed `@[simp]` here, as it makes it harder to tell when to apply --- bundled or unbundled lemmas. --- (This change seems dangerous!) @[to_additive] theorem coe_of (R : Type u) [CommMonoid R] : (CommMonCat.of R : Type u) = R := rfl @[to_additive hasForgetToAddMonCat] -instance hasForgetToMonCat : HasForget₂ CommMonCat MonCat := - BundledHom.forget₂ _ _ +instance hasForgetToMonCat : HasForget₂ CommMonCat MonCat where + forget₂ := + { obj R := MonCat.of R + map f := MonCat.ofHom f.hom } -@[to_additive] -instance : Coe CommMonCat.{u} MonCat.{u} where coe := (forget₂ CommMonCat MonCat).obj +@[to_additive (attr := simp)] lemma coe_forget₂_obj (X : CommMonCat) : + ((forget₂ CommMonCat MonCat).obj X : Type _) = X := rfl --- Porting note: this was added to make automation work (it already exists for MonCat) -/-- Typecheck a `MonoidHom` as a morphism in `CommMonCat`. -/ -@[to_additive] -def ofHom {X Y : Type u} [CommMonoid X] [CommMonoid Y] (f : X →* Y) : of X ⟶ of Y := f +@[to_additive (attr := simp)] lemma hom_forget₂_map {X Y : CommMonCat} + (f : X ⟶ Y) : + ((forget₂ CommMonCat MonCat).map f).hom = f.hom := rfl -/-- Typecheck an `AddMonoidHom` as a morphism in `AddCommMonCat`. -/ -add_decl_doc AddCommMonCat.ofHom +@[to_additive (attr := simp)] lemma forget₂_map_ofHom {X Y : Type u} [CommMonoid X] [CommMonoid Y] + (f : X →* Y) : + (forget₂ CommMonCat MonCat).map (ofHom f) = MonCat.ofHom f := rfl -@[to_additive (attr := simp)] -lemma ofHom_apply {X Y : Type u} [CommMonoid X] [CommMonoid Y] (f : X →* Y) (x : X) : - (ofHom f) x = f x := rfl +@[to_additive] +instance : Coe CommMonCat.{u} MonCat.{u} where coe := (forget₂ CommMonCat MonCat).obj /-- Universe lift functor for commutative monoids. -/ @[to_additive (attr := simps) @@ -250,7 +398,7 @@ lemma ofHom_apply {X Y : Type u} [CommMonoid X] [CommMonoid Y] (f : X →* Y) (x def uliftFunctor : CommMonCat.{v} ⥤ CommMonCat.{max v u} where obj X := CommMonCat.of (ULift.{u, v} X) map {_ _} f := CommMonCat.ofHom <| - MulEquiv.ulift.symm.toMonoidHom.comp <| f.comp MulEquiv.ulift.toMonoidHom + MulEquiv.ulift.symm.toMonoidHom.comp <| f.hom.comp MulEquiv.ulift.toMonoidHom map_id X := by rfl map_comp {X Y Z} f g := by rfl @@ -293,12 +441,12 @@ namespace CategoryTheory.Iso @[to_additive addMonCatIsoToAddEquiv "Build an `AddEquiv` from an isomorphism in the category\n`AddMonCat`."] def monCatIsoToMulEquiv {X Y : MonCat} (i : X ≅ Y) : X ≃* Y := - MonoidHom.toMulEquiv i.hom i.inv i.hom_inv_id i.inv_hom_id + MonoidHom.toMulEquiv i.hom.hom i.inv.hom (by ext; simp) (by ext; simp) /-- Build a `MulEquiv` from an isomorphism in the category `CommMonCat`. -/ @[to_additive "Build an `AddEquiv` from an isomorphism in the category\n`AddCommMonCat`."] def commMonCatIsoToMulEquiv {X Y : CommMonCat} (i : X ≅ Y) : X ≃* Y := - MonoidHom.toMulEquiv i.hom i.inv i.hom_inv_id i.inv_hom_id + MonoidHom.toMulEquiv i.hom.hom i.inv.hom (by ext; simp) (by ext; simp) end CategoryTheory.Iso @@ -330,18 +478,14 @@ add_decl_doc addEquivIsoAddCommMonCatIso instance MonCat.forget_reflects_isos : (forget MonCat.{u}).ReflectsIsomorphisms where reflects {X Y} f _ := by let i := asIso ((forget MonCat).map f) - -- Again a problem that exists already creeps into other things https://github.com/leanprover/lean4/pull/2644 - -- this used to be `by aesop`; see next declaration - let e : X ≃* Y := MulEquiv.mk i.toEquiv (MonoidHom.map_mul (show MonoidHom X Y from f)) + let e : X ≃* Y := { f.hom, i.toEquiv with } exact e.toMonCatIso.isIso_hom @[to_additive] instance CommMonCat.forget_reflects_isos : (forget CommMonCat.{u}).ReflectsIsomorphisms where reflects {X Y} f _ := by let i := asIso ((forget CommMonCat).map f) - let e : X ≃* Y := MulEquiv.mk i.toEquiv - -- Porting FIXME: this would ideally be `by aesop`, as in `MonCat.forget_reflects_isos` - (MonoidHom.map_mul (show MonoidHom X Y from f)) + let e : X ≃* Y := { f.hom, i.toEquiv with } exact e.toCommMonCatIso.isIso_hom -- Porting note: this was added in order to ensure that `forget₂ CommMonCat MonCat` @@ -349,7 +493,7 @@ instance CommMonCat.forget_reflects_isos : (forget CommMonCat.{u}).ReflectsIsomo -- we could have used `CategoryTheory.HasForget.ReflectsIso` alternatively @[to_additive] instance CommMonCat.forget₂_full : (forget₂ CommMonCat MonCat).Full where - map_surjective f := ⟨f, rfl⟩ + map_surjective f := ⟨ofHom f.hom, rfl⟩ example : (forget₂ CommMonCat MonCat).ReflectsIsomorphisms := inferInstance @@ -357,16 +501,26 @@ example : (forget₂ CommMonCat MonCat).ReflectsIsomorphisms := inferInstance `@[simp]` lemmas for `MonoidHom.comp` and categorical identities. -/ -@[to_additive (attr := simp)] theorem MonoidHom.comp_id_monCat - {G : MonCat.{u}} {H : Type u} [Monoid H] (f : G →* H) : f.comp (𝟙 G) = f := - Category.id_comp (MonCat.ofHom f) -@[to_additive (attr := simp)] theorem MonoidHom.id_monCat_comp - {G : Type u} [Monoid G] {H : MonCat.{u}} (f : G →* H) : MonoidHom.comp (𝟙 H) f = f := - Category.comp_id (MonCat.ofHom f) - -@[to_additive (attr := simp)] theorem MonoidHom.comp_id_commMonCat - {G : CommMonCat.{u}} {H : Type u} [CommMonoid H] (f : G →* H) : f.comp (𝟙 G) = f := - Category.id_comp (CommMonCat.ofHom f) -@[to_additive (attr := simp)] theorem MonoidHom.id_commMonCat_comp - {G : Type u} [CommMonoid G] {H : CommMonCat.{u}} (f : G →* H) : MonoidHom.comp (𝟙 H) f = f := - Category.comp_id (CommMonCat.ofHom f) +@[to_additive (attr := deprecated + "Proven by `simp only [MonCat.hom_id, comp_id]`" + (since := "2025-01-28"))] +theorem MonoidHom.comp_id_monCat {G : MonCat.{u}} {H : Type u} [Monoid H] (f : G →* H) : + f.comp (MonCat.Hom.hom (𝟙 G)) = f := by simp +@[to_additive (attr := deprecated + "Proven by `simp only [MonCat.hom_id, id_comp]`" + (since := "2025-01-28"))] +theorem MonoidHom.id_monCat_comp {G : Type u} [Monoid G] {H : MonCat.{u}} (f : G →* H) : + MonoidHom.comp (MonCat.Hom.hom (𝟙 H)) f = f := by simp + +@[to_additive (attr := deprecated + "Proven by `simp only [CommMonCat.hom_id, comp_id]`" + (since := "2025-01-28"))] +theorem MonoidHom.comp_id_commMonCat {G : CommMonCat.{u}} {H : Type u} [CommMonoid H] (f : G →* H) : + f.comp (CommMonCat.Hom.hom (𝟙 G)) = f := by + simp +@[to_additive (attr := deprecated + "Proven by `simp only [CommMonCat.hom_id, id_comp]`" + (since := "2025-01-28"))] +theorem MonoidHom.id_commMonCat_comp {G : Type u} [CommMonoid G] {H : CommMonCat.{u}} (f : G →* H) : + MonoidHom.comp (CommMonCat.Hom.hom (𝟙 H)) f = f := by + simp diff --git a/Mathlib/Algebra/Category/MonCat/Colimits.lean b/Mathlib/Algebra/Category/MonCat/Colimits.lean index 9e317a99bb362..7de16a0795a59 100644 --- a/Mathlib/Algebra/Category/MonCat/Colimits.lean +++ b/Mathlib/Algebra/Category/MonCat/Colimits.lean @@ -141,17 +141,18 @@ theorem quot_mul (x y : Prequotient F) : Quot.mk Setoid.r (mul x y) = /-- The bundled monoid giving the colimit of a diagram. -/ def colimit : MonCat := - ⟨ColimitType F, by infer_instance⟩ + of (ColimitType F) /-- The function from a given monoid in the diagram to the colimit monoid. -/ def coconeFun (j : J) (x : F.obj j) : ColimitType F := Quot.mk _ (Prequotient.of j x) /-- The monoid homomorphism from a given monoid in the diagram to the colimit monoid. -/ -def coconeMorphism (j : J) : F.obj j ⟶ colimit F where - toFun := coconeFun F j - map_one' := Quot.sound (Relation.one _) - map_mul' _ _ := Quot.sound (Relation.mul _ _ _) +def coconeMorphism (j : J) : F.obj j ⟶ colimit F := + ofHom + { toFun := coconeFun F j + map_one' := Quot.sound (Relation.one _) + map_mul' _ _ := Quot.sound (Relation.mul _ _ _) } @[simp] theorem cocone_naturality {j j' : J} (f : j ⟶ j') : @@ -188,8 +189,8 @@ def descFun (s : Cocone F) : ColimitType F → s.pt := by | symm x y _ h => exact h.symm | trans x y z _ _ h₁ h₂ => exact h₁.trans h₂ | map j j' f x => exact s.w_apply f x - | mul j x y => exact map_mul (s.ι.app j) x y - | one j => exact map_one (s.ι.app j) + | mul j x y => exact map_mul (s.ι.app j).hom x y + | one j => exact map_one (s.ι.app j).hom | mul_1 x x' y _ h => exact congr_arg (· * _) h | mul_2 x y y' _ h => exact congr_arg (_ * ·) h | mul_assoc x y z => exact mul_assoc _ _ _ @@ -197,15 +198,16 @@ def descFun (s : Cocone F) : ColimitType F → s.pt := by | mul_one x => exact mul_one _ /-- The monoid homomorphism from the colimit monoid to the cone point of any other cocone. -/ -def descMorphism (s : Cocone F) : colimit F ⟶ s.pt where - toFun := descFun F s - map_one' := rfl - map_mul' x y := by - induction x using Quot.inductionOn - induction y using Quot.inductionOn - dsimp [descFun] - rw [← quot_mul] - simp only [descFunLift] +def descMorphism (s : Cocone F) : colimit F ⟶ s.pt := + ofHom + { toFun := descFun F s + map_one' := rfl + map_mul' x y := by + induction x using Quot.inductionOn + induction y using Quot.inductionOn + dsimp [descFun] + rw [← quot_mul] + simp only [descFunLift] } /-- Evidence that the proposed colimit is the colimit. -/ def colimitIsColimit : IsColimit (colimitCocone F) where diff --git a/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean b/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean index d12f9961dbc01..248d4e9a1a39f 100644 --- a/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean @@ -101,7 +101,8 @@ theorem colimitMulAux_eq_of_rel_left {x x' y : Σ j, F.obj j} colimitMulAux.{v, u} F x y = colimitMulAux.{v, u} F x' y := by obtain ⟨j₁, x⟩ := x; obtain ⟨j₂, y⟩ := y; obtain ⟨j₃, x'⟩ := x' obtain ⟨l, f, g, hfg⟩ := hxx' - simp? at hfg says simp only [Functor.comp_obj, Functor.comp_map, forget_map] at hfg + simp? at hfg says + simp only [Functor.comp_obj, Functor.comp_map, ConcreteCategory.forget_map_eq_coe] at hfg obtain ⟨s, α, β, γ, h₁, h₂, h₃⟩ := IsFiltered.tulip (IsFiltered.leftToMax j₁ j₂) (IsFiltered.rightToMax j₁ j₂) (IsFiltered.rightToMax j₃ j₂) (IsFiltered.leftToMax j₃ j₂) f g @@ -233,18 +234,19 @@ noncomputable def colimit : MonCat.{max v u} := @[to_additive "The additive monoid homomorphism from a given additive monoid in the diagram to the colimit additive monoid."] -def coconeMorphism (j : J) : F.obj j ⟶ colimit F where - toFun := (Types.TypeMax.colimitCocone.{v, max v u, v} (F ⋙ forget MonCat)).ι.app j - map_one' := (colimit_one_eq F j).symm - map_mul' x y := by - convert (colimit_mul_mk_eq F ⟨j, x⟩ ⟨j, y⟩ j (𝟙 j) (𝟙 j)).symm - rw [F.map_id] - rfl +def coconeMorphism (j : J) : F.obj j ⟶ colimit F := + ofHom + { toFun := (Types.TypeMax.colimitCocone.{v, max v u, v} (F ⋙ forget MonCat)).ι.app j + map_one' := (colimit_one_eq F j).symm + map_mul' x y := by + convert (colimit_mul_mk_eq F ⟨j, x⟩ ⟨j, y⟩ j (𝟙 j) (𝟙 j)).symm + rw [F.map_id] + rfl } @[to_additive (attr := simp)] theorem cocone_naturality {j j' : J} (f : j ⟶ j') : F.map f ≫ coconeMorphism.{v, u} F j' = coconeMorphism F j := - MonoidHom.ext fun x => + MonCat.ext fun x => congr_fun ((Types.TypeMax.colimitCocone (F ⋙ forget MonCat)).ι.naturality f) x /-- The cocone over the proposed colimit monoid. -/ @@ -262,38 +264,39 @@ The only thing left to see is that it is a monoid homomorphism. to the cocone point. As a function, this is simply given by the induced map of the corresponding cocone in `Type`. The only thing left to see is that it is an additive monoid homomorphism."] -def colimitDesc (t : Cocone F) : colimit.{v, u} F ⟶ t.pt where - toFun := (Types.TypeMax.colimitCoconeIsColimit.{v, max v u, v} (F ⋙ forget MonCat)).desc - ((forget MonCat).mapCocone t) - map_one' := by - rw [colimit_one_eq F IsFiltered.nonempty.some] - exact MonoidHom.map_one _ - map_mul' x y := by - refine Quot.induction_on₂ x y ?_ - clear x y - intro x y - obtain ⟨i, x⟩ := x - obtain ⟨j, y⟩ := y - rw [colimit_mul_mk_eq F ⟨i, x⟩ ⟨j, y⟩ (max' i j) (IsFiltered.leftToMax i j) - (IsFiltered.rightToMax i j)] - dsimp [Types.TypeMax.colimitCoconeIsColimit] - -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [MonoidHom.map_mul] - -- Porting note: `rw` can't see through coercion is actually forgetful functor, - -- so can't rewrite `t.w_apply` - congr 1 <;> - exact t.w_apply _ _ +def colimitDesc (t : Cocone F) : colimit.{v, u} F ⟶ t.pt := + ofHom + { toFun := (Types.TypeMax.colimitCoconeIsColimit.{v, max v u, v} (F ⋙ forget MonCat)).desc + ((forget MonCat).mapCocone t) + map_one' := by + rw [colimit_one_eq F IsFiltered.nonempty.some] + exact MonoidHom.map_one _ + map_mul' x y := by + refine Quot.induction_on₂ x y ?_ + clear x y + intro x y + obtain ⟨i, x⟩ := x + obtain ⟨j, y⟩ := y + rw [colimit_mul_mk_eq F ⟨i, x⟩ ⟨j, y⟩ (max' i j) (IsFiltered.leftToMax i j) + (IsFiltered.rightToMax i j)] + dsimp [Types.TypeMax.colimitCoconeIsColimit] + -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 + erw [MonoidHom.map_mul] + -- Porting note: `rw` can't see through coercion is actually forgetful functor, + -- so can't rewrite `t.w_apply` + congr 1 <;> + exact t.w_apply _ _ } /-- The proposed colimit cocone is a colimit in `MonCat`. -/ @[to_additive "The proposed colimit cocone is a colimit in `AddMonCat`."] def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where desc := colimitDesc.{v, u} F - fac t j := MonoidHom.ext fun x => congr_fun ((Types.TypeMax.colimitCoconeIsColimit.{v, u} + fac t j := MonCat.ext fun x => congr_fun ((Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget MonCat)).fac ((forget MonCat).mapCocone t) j) x - uniq t m h := MonoidHom.ext fun y => congr_fun + uniq t m h := MonCat.ext fun y => congr_fun ((Types.TypeMax.colimitCoconeIsColimit (F ⋙ forget MonCat)).uniq ((forget MonCat).mapCocone t) ((forget MonCat).map m) - fun j => funext fun x => DFunLike.congr_fun (i := MonCat.instFunLike _ _) (h j) x) y + fun j => funext fun x => ConcreteCategory.congr_hom (h j) x) y @[to_additive] instance forget_preservesFilteredColimits : @@ -348,25 +351,28 @@ noncomputable def colimit : CommMonCat.{max v u} := @[to_additive "The cocone over the proposed colimit additive commutative monoid."] noncomputable def colimitCocone : Cocone F where pt := colimit.{v, u} F - ι := { (MonCat.FilteredColimits.colimitCocone.{v, u} - (F ⋙ forget₂ CommMonCat MonCat.{max v u})).ι with } + ι.app j := ofHom ((MonCat.FilteredColimits.colimitCocone.{v, u} + (F ⋙ forget₂ CommMonCat MonCat.{max v u})).ι.app j).hom + ι.naturality _ _ f := hom_ext <| congr_arg (MonCat.Hom.hom) + ((MonCat.FilteredColimits.colimitCocone.{v, u} + (F ⋙ forget₂ CommMonCat MonCat.{max v u})).ι.naturality f) /-- The proposed colimit cocone is a colimit in `CommMonCat`. -/ @[to_additive "The proposed colimit cocone is a colimit in `AddCommMonCat`."] def colimitCoconeIsColimit : IsColimit (colimitCocone.{v, u} F) where - desc t := - MonCat.FilteredColimits.colimitDesc.{v, u} (F ⋙ forget₂ CommMonCat MonCat.{max v u}) - ((forget₂ CommMonCat MonCat.{max v u}).mapCocone t) + desc t := ofHom + (MonCat.FilteredColimits.colimitDesc.{v, u} (F ⋙ forget₂ CommMonCat MonCat.{max v u}) + ((forget₂ CommMonCat MonCat.{max v u}).mapCocone t)).hom fac t j := - DFunLike.coe_injective (i := CommMonCat.instFunLike _ _) <| + ConcreteCategory.coe_ext <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommMonCat.{max v u})).fac ((forget CommMonCat).mapCocone t) j uniq t m h := - DFunLike.coe_injective (i := CommMonCat.instFunLike _ _) <| + ConcreteCategory.coe_ext <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget CommMonCat.{max v u})).uniq ((forget CommMonCat.{max v u}).mapCocone t) ((forget CommMonCat.{max v u}).map m) fun j => funext fun x => - DFunLike.congr_fun (i := CommMonCat.instFunLike _ _) (h j) x + CategoryTheory.congr_fun (h j) x @[to_additive forget₂AddMonPreservesFilteredColimits] noncomputable instance forget₂Mon_preservesFilteredColimits : diff --git a/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean b/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean index 28ed84e06487d..2b55d2d0195a6 100644 --- a/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean +++ b/Mathlib/Algebra/Category/MonCat/ForgetCorepresentable.lean @@ -57,23 +57,27 @@ end AddMonoidHom /-- The forgetful functor `MonCat.{u} ⥤ Type u` is corepresentable. -/ def MonCat.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} (Multiplicative ℕ)))) ≅ forget MonCat.{u} := - (NatIso.ofComponents (fun M => (MonoidHom.fromULiftMultiplicativeNatEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (MonoidHom.fromULiftMultiplicativeNatEquiv M.carrier)).toIso)) /-- The forgetful functor `CommMonCat.{u} ⥤ Type u` is corepresentable. -/ def CommMonCat.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} (Multiplicative ℕ)))) ≅ forget CommMonCat.{u} := - (NatIso.ofComponents (fun M => (MonoidHom.fromULiftMultiplicativeNatEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (MonoidHom.fromULiftMultiplicativeNatEquiv M.carrier)).toIso)) /-- The forgetful functor `AddMonCat.{u} ⥤ Type u` is corepresentable. -/ def AddMonCat.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} ℕ))) ≅ forget AddMonCat.{u} := - (NatIso.ofComponents (fun M => (AddMonoidHom.fromULiftNatEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (AddMonoidHom.fromULiftNatEquiv M.carrier)).toIso)) /-- The forgetful functor `AddCommMonCat.{u} ⥤ Type u` is corepresentable. -/ def AddCommMonCat.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} ℕ))) ≅ forget AddCommMonCat.{u} := - (NatIso.ofComponents (fun M => (AddMonoidHom.fromULiftNatEquiv M.α).toIso)) + (NatIso.ofComponents (fun M => (ConcreteCategory.homEquiv.trans + (AddMonoidHom.fromULiftNatEquiv M.carrier)).toIso)) instance MonCat.forget_isCorepresentable : (forget MonCat.{u}).IsCorepresentable := diff --git a/Mathlib/Algebra/Category/MonCat/Limits.lean b/Mathlib/Algebra/Category/MonCat/Limits.lean index 9c9d1b5433546..d5b9212e3bf6a 100644 --- a/Mathlib/Algebra/Category/MonCat/Limits.lean +++ b/Mathlib/Algebra/Category/MonCat/Limits.lean @@ -87,9 +87,9 @@ namespace HasLimits noncomputable def limitCone : Cone F := { pt := MonCat.of (Types.Small.limitCone (F ⋙ forget _)).pt π := - { app := limitπMonoidHom F - naturality := fun _ _ f => - DFunLike.coe_injective ((Types.Small.limitCone (F ⋙ forget _)).π.naturality f) } } + { app j := ofHom (limitπMonoidHom F j) + naturality := fun _ _ f => MonCat.ext fun x => + CategoryTheory.congr_hom ((Types.Small.limitCone (F ⋙ forget _)).π.naturality f) x } } /-- Witness that the limit cone in `MonCat` is a limit cone. (Internal use only; use the limits API.) @@ -97,7 +97,7 @@ noncomputable def limitCone : Cone F := @[to_additive "(Internal use only; use the limits API.)"] noncomputable def limitConeIsLimit : IsLimit (limitCone F) := by refine IsLimit.ofFaithful (forget MonCat) (Types.Small.limitConeIsLimit.{v,u} _) - (fun s => { toFun := _, map_one' := ?_, map_mul' := ?_ }) (fun s => rfl) + (fun s => ofHom { toFun := _, map_one' := ?_, map_mul' := ?_ }) (fun s => rfl) · simp only [Functor.mapCone_π_app, forget_map, map_one] rfl · intro x y @@ -163,14 +163,18 @@ noncomputable instance forget_createsLimit : have : Small.{u} (Functor.sections (F ⋙ forget MonCat)) := (Types.hasLimit_iff_small_sections _).mp (HasLimit.mk {cone := c, isLimit := t}) refine LiftsToLimit.mk (LiftableCone.mk - {pt := MonCat.of (Types.Small.limitCone (F ⋙ forget MonCat)).pt, π := NatTrans.mk - (limitπMonoidHom F) (MonCat.HasLimits.limitCone F).π.naturality} (Cones.ext + { pt := MonCat.of (Types.Small.limitCone (F ⋙ forget MonCat)).pt, + π := NatTrans.mk + (fun j => ofHom (limitπMonoidHom F j)) + (MonCat.HasLimits.limitCone F).π.naturality } + (Cones.ext ((Types.isLimitEquivSections t).trans (equivShrink _)).symm.toIso (fun _ ↦ funext (fun _ ↦ by simp; rfl)))) ?_ refine IsLimit.ofFaithful (forget MonCat.{u}) (Types.Small.limitConeIsLimit.{v,u} _) ?_ ?_ · intro _ - refine {toFun := (Types.Small.limitConeIsLimit.{v,u} _).lift ((forget MonCat).mapCone _), - map_one' := by simp; rfl, map_mul' := ?_ } + refine ofHom + { toFun := (Types.Small.limitConeIsLimit.{v,u} _).lift ((forget MonCat).mapCone _), + map_one' := by simp; rfl, map_mul' := ?_ } · intro x y simp only [Types.Small.limitConeIsLimit_lift, Functor.comp_obj, Functor.mapCone_pt, Functor.mapCone_π_app, forget_map, map_mul, mul_of] @@ -240,10 +244,10 @@ noncomputable instance forget₂CreatesLimit : CreatesLimit F (forget₂ CommMon { liftedCone := { pt := CommMonCat.of (Types.Small.limitCone (F ⋙ forget CommMonCat)).pt π := - { app := MonCat.limitπMonoidHom (F ⋙ forget₂ CommMonCat.{u} MonCat.{u}) - naturality := - (MonCat.HasLimits.limitCone - (F ⋙ forget₂ CommMonCat MonCat.{u})).π.naturality } } + { app j := ofHom (MonCat.limitπMonoidHom (F ⋙ forget₂ CommMonCat.{u} MonCat.{u}) j) + naturality _ _ j := ext <| fun x => congr_hom + ((MonCat.HasLimits.limitCone + (F ⋙ forget₂ CommMonCat MonCat.{u})).π.naturality j) x } } validLift := by apply IsLimit.uniqueUpToIso (MonCat.HasLimits.limitConeIsLimit _) t makesLimit := IsLimit.ofFaithful (forget₂ CommMonCat MonCat.{u}) diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index ce49902e3ee6b..67076fcd7c1be 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -153,12 +153,12 @@ instance {R : SemiRingCat} : Semiring ((forget SemiRingCat).obj R) := instance hasForgetToMonCat : HasForget₂ SemiRingCat MonCat where forget₂ := { obj := fun R ↦ MonCat.of R - map := fun f ↦ f.hom.toMonoidHom } + map := fun f ↦ MonCat.ofHom f.hom.toMonoidHom } instance hasForgetToAddCommMonCat : HasForget₂ SemiRingCat AddCommMonCat where forget₂ := { obj := fun R ↦ AddCommMonCat.of R - map := fun f ↦ f.hom.toAddMonoidHom } + map := fun f ↦ AddCommMonCat.ofHom f.hom.toAddMonoidHom } /-- Ring equivalence are isomorphisms in category of semirings -/ @[simps] @@ -472,7 +472,7 @@ instance hasForgetToSemiRingCat : HasForget₂ CommSemiRingCat SemiRingCat where instance hasForgetToCommMonCat : HasForget₂ CommSemiRingCat CommMonCat where forget₂ := { obj := fun R ↦ CommMonCat.of R - map := fun f ↦ f.hom.toMonoidHom } + map := fun f ↦ CommMonCat.ofHom f.hom.toMonoidHom } /-- Ring equivalence are isomorphisms in category of semirings -/ @[simps] diff --git a/Mathlib/Algebra/Category/Ring/FilteredColimits.lean b/Mathlib/Algebra/Category/Ring/FilteredColimits.lean index 1f10eb428fe0c..da76dcd8a894a 100644 --- a/Mathlib/Algebra/Category/Ring/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/Ring/FilteredColimits.lean @@ -112,22 +112,22 @@ def colimitCocone : Cocone F where pt := colimit.{v, u} F ι := { app := fun j => ofHom - { (MonCat.FilteredColimits.colimitCocone - (F ⋙ forget₂ SemiRingCatMax.{v, u} MonCat)).ι.app j, - (AddCommMonCat.FilteredColimits.colimitCocone - (F ⋙ forget₂ SemiRingCatMax.{v, u} AddCommMonCat)).ι.app j with } + { ((MonCat.FilteredColimits.colimitCocone + (F ⋙ forget₂ SemiRingCatMax.{v, u} MonCat)).ι.app j).hom, + ((AddCommMonCat.FilteredColimits.colimitCocone + (F ⋙ forget₂ SemiRingCatMax.{v, u} AddCommMonCat)).ι.app j).hom with } naturality := fun {_ _} f => hom_ext <| RingHom.coe_inj ((Types.TypeMax.colimitCocone (F ⋙ forget SemiRingCat)).ι.naturality f) } /-- The proposed colimit cocone is a colimit in `SemiRingCat`. -/ def colimitCoconeIsColimit : IsColimit <| colimitCocone.{v, u} F where desc t := ofHom - { (MonCat.FilteredColimits.colimitCoconeIsColimit.{v, u} + { ((MonCat.FilteredColimits.colimitCoconeIsColimit.{v, u} (F ⋙ forget₂ SemiRingCatMax.{v, u} MonCat)).desc - ((forget₂ SemiRingCatMax.{v, u} MonCat).mapCocone t), - (AddCommMonCat.FilteredColimits.colimitCoconeIsColimit.{v, u} + ((forget₂ SemiRingCatMax.{v, u} MonCat).mapCocone t)).hom, + ((AddCommMonCat.FilteredColimits.colimitCoconeIsColimit.{v, u} (F ⋙ forget₂ SemiRingCatMax.{v, u} AddCommMonCat)).desc - ((forget₂ SemiRingCatMax.{v, u} AddCommMonCat).mapCocone t) with } + ((forget₂ SemiRingCatMax.{v, u} AddCommMonCat).mapCocone t)).hom with } fac t j := hom_ext <| RingHom.coe_inj <| (Types.TypeMax.colimitCoconeIsColimit.{v, u} (F ⋙ forget SemiRingCatMax.{v, u})).fac diff --git a/Mathlib/CategoryTheory/Abelian/Pseudoelements.lean b/Mathlib/CategoryTheory/Abelian/Pseudoelements.lean index 8aa0fd2f01e4b..77297ef306231 100644 --- a/Mathlib/CategoryTheory/Abelian/Pseudoelements.lean +++ b/Mathlib/CategoryTheory/Abelian/Pseudoelements.lean @@ -389,7 +389,7 @@ theorem sub_of_eq_image {P Q : C} (f : P ⟶ Q) (x y : P) : Quotient.inductionOn₂ x y fun a a' h => match Quotient.exact h with | ⟨R, p, q, ep, _, comm⟩ => - let a'' : R ⟶ P := ↑(p ≫ a.hom) - ↑(q ≫ a'.hom) + let a'' : R ⟶ P := (p ≫ a.hom : R ⟶ P) - (q ≫ a'.hom : R ⟶ P) ⟨a'', ⟨show ⟦(a'' ≫ f : Over Q)⟧ = ⟦↑(0 : Q ⟶ Q)⟧ by dsimp at comm diff --git a/Mathlib/CategoryTheory/Action/Basic.lean b/Mathlib/CategoryTheory/Action/Basic.lean index 5346896a39bc6..8562a5df70953 100644 --- a/Mathlib/CategoryTheory/Action/Basic.lean +++ b/Mathlib/CategoryTheory/Action/Basic.lean @@ -42,8 +42,7 @@ namespace Action variable {V} -@[simp] -theorem ρ_one {G : MonCat.{u}} (A : Action V G) : A.ρ 1 = 𝟙 A.V := by rw [MonoidHom.map_one]; rfl +theorem ρ_one {G : MonCat.{u}} (A : Action V G) : A.ρ 1 = 𝟙 A.V := by simp /-- When a group acts, we can lift the action to the group of automorphisms. -/ @[simps!] @@ -52,15 +51,10 @@ def ρAut {G : Grp.{u}} (A : Action V (MonCat.of G)) : G ⟶ Grp.of (Aut A.V) := { toFun g := { hom := A.ρ g inv := A.ρ (g⁻¹ : G) - hom_inv_id := (A.ρ.map_mul (g⁻¹ : G) g).symm.trans (by rw [inv_mul_cancel, ρ_one]) - inv_hom_id := (A.ρ.map_mul g (g⁻¹ : G)).symm.trans (by rw [mul_inv_cancel, ρ_one]) } - map_one' := Aut.ext A.ρ.map_one - map_mul' x y := Aut.ext (A.ρ.map_mul x y) } - --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), --- but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing --- It would be worth fixing these, as `ρAut_apply_inv` is used in `erw` later. -attribute [nolint simpNF] Action.ρAut_hom_apply_inv Action.ρAut_hom_apply_hom + hom_inv_id := (A.ρ.hom.map_mul (g⁻¹ : G) g).symm.trans (by rw [inv_mul_cancel, ρ_one]) + inv_hom_id := (A.ρ.hom.map_mul g (g⁻¹ : G)).symm.trans (by rw [mul_inv_cancel, ρ_one]) } + map_one' := Aut.ext A.ρ.hom.map_one + map_mul' x y := Aut.ext (A.ρ.hom.map_mul x y) } variable (G : MonCat.{u}) @@ -87,7 +81,11 @@ commuting with the action of `G`. @[ext] structure Hom (M N : Action V G) where hom : M.V ⟶ N.V - comm : ∀ g : G, M.ρ g ≫ hom = hom ≫ N.ρ g := by aesop_cat + -- Have to insert type hint for `F`, otherwise it ends up as: + -- `(fun α β => ↑α →* β) (MonCat.of (End _)) G` + -- which `simp` reduces to `↑(MonCat.of (End _)) →* β` instead of `End _ →* β`. + -- Strangely enough, the `@[reassoc]` version works fine. + comm : ∀ g : G, DFunLike.coe (F := _ →* End _) M.ρ.hom g ≫ hom = hom ≫ N.ρ g := by aesop_cat namespace Hom @@ -171,8 +169,8 @@ def functor : Action V G ⥤ SingleObj G ⥤ V where obj M := { obj := fun _ => M.V map := fun g => M.ρ g - map_id := fun _ => M.ρ.map_one - map_comp := fun g h => M.ρ.map_mul h g } + map_id := fun _ => M.ρ.hom.map_one + map_comp := fun g h => M.ρ.hom.map_mul h g } map f := { app := fun _ => f.hom naturality := fun _ _ g => f.comm g } @@ -182,7 +180,7 @@ def functor : Action V G ⥤ SingleObj G ⥤ V where def inverse : (SingleObj G ⥤ V) ⥤ Action V G where obj F := { V := F.obj PUnit.unit - ρ := + ρ := MonCat.ofHom { toFun := fun g => F.map g map_one' := F.map_id PUnit.unit map_mul' := fun g h => F.map_comp h g } } @@ -276,8 +274,8 @@ def actionPunitEquivalence : Action V (MonCat.of PUnit) ≌ V where map := fun f => ⟨f, fun ⟨⟩ => by simp⟩ } unitIso := NatIso.ofComponents fun X => mkIso (Iso.refl _) fun ⟨⟩ => by - simp only [MonCat.oneHom_apply, MonCat.one_of, End.one_def, id_eq, Functor.comp_obj, - forget_obj, Iso.refl_hom, Category.comp_id] + simp only [MonCat.hom_one, MonoidHom.one_apply, MonCat.one_of, End.one_def, + Functor.comp_obj, Iso.refl_hom, Category.comp_id] exact ρ_one X counitIso := NatIso.ofComponents fun _ => Iso.refl _ @@ -326,12 +324,12 @@ the categories of `G`-actions within those categories. -/ def mapAction (F : V ⥤ W) (G : MonCat.{u}) : Action V G ⥤ Action W G where obj M := { V := F.obj M.V - ρ := + ρ := MonCat.ofHom { toFun := fun g => F.map (M.ρ g) - map_one' := by simp only [End.one_def, Action.ρ_one, F.map_id, MonCat.one_of] + map_one' := by simp map_mul' := fun g h => by dsimp - rw [map_mul, MonCat.mul_of, End.mul_def, End.mul_def, F.map_comp] } } + rw [map_mul, MonCat.mul_of, End.mul_def, F.map_comp] } } map f := { hom := F.map f.hom comm := fun g => by dsimp; rw [← F.map_comp, f.comm, F.map_comp] } diff --git a/Mathlib/CategoryTheory/Action/Concrete.lean b/Mathlib/CategoryTheory/Action/Concrete.lean index accafd5500e8d..c7ed68e30090b 100644 --- a/Mathlib/CategoryTheory/Action/Concrete.lean +++ b/Mathlib/CategoryTheory/Action/Concrete.lean @@ -24,7 +24,7 @@ namespace Action /-- Bundles a type `H` with a multiplicative action of `G` as an `Action`. -/ def ofMulAction (G H : Type u) [Monoid G] [MulAction G H] : Action (Type u) (MonCat.of G) where V := H - ρ := @MulAction.toEndHom _ _ _ (by assumption) + ρ := MonCat.ofHom <| @MulAction.toEndHom _ _ _ (by assumption) @[simp] theorem ofMulAction_apply {G H : Type u} [Monoid G] [MulAction G H] (g : G) (x : H) : @@ -80,7 +80,7 @@ instance (G : Type*) (X : Type*) [Monoid G] [MulAction G X] [Fintype X] : def ofMulAction (G : Type u) (H : FintypeCat.{u}) [Monoid G] [MulAction G H] : Action FintypeCat (MonCat.of G) where V := H - ρ := @MulAction.toEndHom _ _ _ (by assumption) + ρ := MonCat.ofHom <| @MulAction.toEndHom _ _ _ (by assumption) @[simp] theorem ofMulAction_apply {G : Type u} {H : FintypeCat.{u}} [Monoid G] [MulAction G H] @@ -174,12 +174,11 @@ instance instMulAction {G : MonCat.{u}} (X : Action V G) : smul g x := ((CategoryTheory.forget _).map (X.ρ g)) x one_smul x := by show ((CategoryTheory.forget _).map (X.ρ 1)) x = x - simp only [Action.ρ_one, FunctorToTypes.map_id_apply] + simp mul_smul g h x := by show (CategoryTheory.forget V).map (X.ρ (g * h)) x = ((CategoryTheory.forget V).map (X.ρ h) ≫ (CategoryTheory.forget V).map (X.ρ g)) x - rw [← Functor.map_comp, map_mul] - rfl + simp /- Specialize `instMulAction` to assist typeclass inference. -/ instance {G : MonCat.{u}} (X : Action FintypeCat G) : MulAction G X.V := Action.instMulAction X diff --git a/Mathlib/CategoryTheory/Action/Monoidal.lean b/Mathlib/CategoryTheory/Action/Monoidal.lean index 8bb4bce035d12..57ec668e21621 100644 --- a/Mathlib/CategoryTheory/Action/Monoidal.lean +++ b/Mathlib/CategoryTheory/Action/Monoidal.lean @@ -42,21 +42,30 @@ instance instMonoidalCategory : MonoidalCategory (Action V G) := /- Adding this solves `simpNF` linter report at `tensorUnit_ρ` -/ @[simp] theorem tensorUnit_ρ' {g : G} : - @DFunLike.coe (G →* MonCat.of (End (𝟙_ V))) _ _ _ (𝟙_ (Action V G)).ρ g = 𝟙 (𝟙_ V) := by + @DFunLike.coe (G →* MonCat.of (End (𝟙_ V))) _ _ _ (𝟙_ (Action V G)).ρ.hom g = 𝟙 (𝟙_ V) := by rfl @[simp] -theorem tensorUnit_ρ {g : G} : (𝟙_ (Action V G)).ρ g = 𝟙 (𝟙_ V) := +theorem tensorUnit_ρ {g : G} : + -- Have to hint `F` here, otherwise `simp` doesn't reduce `↑(MonCat.of (End _))` to `End _`. + DFunLike.coe (F := _ →* End _) + -- Have to hint `Y` here for `simpNF` reasons. + (ConcreteCategory.hom (Y := MonCat.of (End (𝟙_ V))) (𝟙_ (Action V G)).ρ) g = 𝟙 (𝟙_ V) := rfl /- Adding this solves `simpNF` linter report at `tensor_ρ` -/ @[simp] theorem tensor_ρ' {X Y : Action V G} {g : G} : - @DFunLike.coe (G →* MonCat.of (End (X.V ⊗ Y.V))) _ _ _ (X ⊗ Y).ρ g = X.ρ g ⊗ Y.ρ g := + @DFunLike.coe (G →* MonCat.of (End (X.V ⊗ Y.V))) _ _ _ (X ⊗ Y).ρ.hom g = X.ρ g ⊗ Y.ρ g := rfl @[simp] -theorem tensor_ρ {X Y : Action V G} {g : G} : (X ⊗ Y).ρ g = X.ρ g ⊗ Y.ρ g := +theorem tensor_ρ {X Y : Action V G} {g : G} : + -- Have to hint `F` here, otherwise `simp` doesn't reduce `↑(MonCat.of (End _))` to `End _`. + DFunLike.coe (F := _ →* End _) + -- Have to hint `Y` here for `simpNF` reasons. + (ConcreteCategory.hom (Y := MonCat.of (End (tensorObj X.V Y.V))) (X ⊗ Y).ρ) g = + X.ρ g ⊗ Y.ρ g := rfl /-- Given an object `X` isomorphic to the tensor unit of `V`, `X` equipped with the trivial action @@ -208,16 +217,17 @@ noncomputable def leftRegularTensorIso (G : Type u) [Group G] (X : Action (Type funext ⟨(x₁ : G), (x₂ : X.V)⟩ refine Prod.ext rfl ?_ change (X.ρ ((g * x₁)⁻¹ : G) * X.ρ g) x₂ = X.ρ _ _ - rw [mul_inv_rev, ← X.ρ.map_mul, inv_mul_cancel_right] } + rw [mul_inv_rev, ← X.ρ.hom.map_mul, inv_mul_cancel_right] } inv := { hom := fun g => ⟨g.1, X.ρ g.1 g.2⟩ comm := fun (g : G) => by funext ⟨(x₁ : G), (x₂ : X.V)⟩ refine Prod.ext rfl ?_ + dsimp [leftRegular] -- Unfold `leftRegular` so `rw` can see through `(leftRegular V).V = V` rw [tensor_ρ, tensor_ρ] dsimp -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [leftRegular_ρ_apply] + erw [leftRegular_ρ_hom_apply] rw [map_mul] rfl } hom_inv_id := by @@ -225,13 +235,15 @@ noncomputable def leftRegularTensorIso (G : Type u) [Group G] (X : Action (Type funext x refine Prod.ext rfl ?_ change (X.ρ x.1 * X.ρ (x.1⁻¹ : G)) x.2 = x.2 - rw [← X.ρ.map_mul, mul_inv_cancel, X.ρ.map_one, MonCat.one_of, End.one_def, types_id_apply] + rw [← X.ρ.hom.map_mul, mul_inv_cancel, X.ρ.hom.map_one, MonCat.one_of, End.one_def, + types_id_apply] inv_hom_id := by apply Hom.ext funext x refine Prod.ext rfl ?_ change (X.ρ (x.1⁻¹ : G) * X.ρ x.1) x.2 = x.2 - rw [← X.ρ.map_mul, inv_mul_cancel, X.ρ.map_one, MonCat.one_of, End.one_def, types_id_apply] + rw [← X.ρ.hom.map_mul, inv_mul_cancel, X.ρ.hom.map_one, MonCat.one_of, End.one_def, + types_id_apply] /-- The natural isomorphism of `G`-sets `Gⁿ⁺¹ ≅ G × Gⁿ`, where `G` acts by left multiplication on each factor. -/ diff --git a/Mathlib/CategoryTheory/Galois/Examples.lean b/Mathlib/CategoryTheory/Galois/Examples.lean index c985a304ca0e9..e834fe1198296 100644 --- a/Mathlib/CategoryTheory/Galois/Examples.lean +++ b/Mathlib/CategoryTheory/Galois/Examples.lean @@ -51,9 +51,9 @@ noncomputable def Action.imageComplement {X Y : Action FintypeCat (MonCat.of G)} calc (X.ρ g⁻¹ ≫ f.hom) x = (Y.ρ g⁻¹ * Y.ρ g) y.val := by rw [f.comm, FintypeCat.comp_apply, h]; rfl _ = y.val := by rw [← map_mul, inv_mul_cancel, Action.ρ_one, FintypeCat.id_apply] - map_one' := by simp only [Action.ρ_one]; rfl - map_mul' := fun g h ↦ FintypeCat.hom_ext _ _ <| fun y ↦ Subtype.ext <| by - exact congrFun (MonoidHom.map_mul Y.ρ g h) y.val + map_one' := by simp only [map_one, End.one_def, FintypeCat.id_apply, Subtype.coe_eta]; rfl + map_mul' := fun g h ↦ FintypeCat.hom_ext _ _ <| fun y ↦ Subtype.ext <| + congrFun (MonoidHom.map_mul Y.ρ.hom g h) y.val } /-- The inclusion from the complement of the image of `f : X ⟶ Y` into `Y`. -/ diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean b/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean index 35b5ae5310477..e65860e6b4569 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/Types.lean @@ -34,7 +34,7 @@ instance monMonoid (A : Mon_ (Type u)) : Monoid A.X where -/ noncomputable def functor : Mon_ (Type u) ⥤ MonCat.{u} where obj A := MonCat.of A.X - map f := + map f := MonCat.ofHom { toFun := f.hom map_one' := congr_fun f.one_hom PUnit.unit map_mul' := fun x y => congr_fun f.mul_hom (x, y) } @@ -70,11 +70,11 @@ noncomputable def monTypeEquivalenceMon : Mon_ (Type u) ≌ MonCat.{u} where counitIso := NatIso.ofComponents (fun A => - { hom := + { hom := MonCat.ofHom { toFun := id map_one' := rfl map_mul' := fun _ _ => rfl } - inv := + inv := MonCat.ofHom { toFun := id map_one' := rfl map_mul' := fun _ _ => rfl } }) @@ -100,7 +100,7 @@ instance commMonCommMonoid (A : CommMon_ (Type u)) : CommMonoid A.X := -/ noncomputable def functor : CommMon_ (Type u) ⥤ CommMonCat.{u} where obj A := CommMonCat.of A.X - map f := MonTypeEquivalenceMon.functor.map f + map f := CommMonCat.ofHom (MonTypeEquivalenceMon.functor.map f).hom /-- Converting a bundled commutative monoid to a commutative monoid object in `Type`. -/ @@ -131,11 +131,11 @@ noncomputable def commMonTypeEquivalenceCommMon : CommMon_ (Type u) ≌ CommMonC counitIso := NatIso.ofComponents (fun A => - { hom := + { hom := CommMonCat.ofHom { toFun := id map_one' := rfl map_mul' := fun _ _ => rfl } - inv := + inv := CommMonCat.ofHom { toFun := id map_one' := rfl map_mul' := fun _ _ => rfl } }) diff --git a/Mathlib/CategoryTheory/SingleObj.lean b/Mathlib/CategoryTheory/SingleObj.lean index b4844a38d181a..e0d75d8669d28 100644 --- a/Mathlib/CategoryTheory/SingleObj.lean +++ b/Mathlib/CategoryTheory/SingleObj.lean @@ -234,12 +234,14 @@ open CategoryTheory /-- The fully faithful functor from `MonCat` to `Cat`. -/ def toCat : MonCat ⥤ Cat where obj x := Cat.of (SingleObj x) - map {x y} f := SingleObj.mapHom x y f + map {x y} f := SingleObj.mapHom x y f.hom instance toCat_full : toCat.Full where - map_surjective := (SingleObj.mapHom _ _).surjective + map_surjective y := + let ⟨x, h⟩ := (SingleObj.mapHom _ _).surjective y + ⟨ofHom x, h⟩ instance toCat_faithful : toCat.Faithful where - map_injective h := by rwa [toCat, (SingleObj.mapHom _ _).apply_eq_iff_eq] at h + map_injective h := MonCat.hom_ext <| by rwa [toCat, (SingleObj.mapHom _ _).apply_eq_iff_eq] at h end MonCat diff --git a/Mathlib/RepresentationTheory/FDRep.lean b/Mathlib/RepresentationTheory/FDRep.lean index dae66e0f2aa47..f0a43daf7ef44 100644 --- a/Mathlib/RepresentationTheory/FDRep.lean +++ b/Mathlib/RepresentationTheory/FDRep.lean @@ -82,16 +82,17 @@ instance (V W : FDRep k G) : FiniteDimensional k (V ⟶ W) := /-- The monoid homomorphism corresponding to the action of `G` onto `V : FDRep k G`. -/ def ρ (V : FDRep k G) : G →* V →ₗ[k] V := - (ModuleCat.endRingEquiv _).toMonoidHom.comp (Action.ρ V) + (ModuleCat.endRingEquiv _).toMonoidHom.comp (Action.ρ V).hom @[simp] lemma endRingEquiv_symm_comp_ρ (V : FDRep k G) : - (MonoidHomClass.toMonoidHom (ModuleCat.endRingEquiv V.V.obj).symm).comp (ρ V) = Action.ρ V := + (MonoidHomClass.toMonoidHom (ModuleCat.endRingEquiv V.V.obj).symm).comp (ρ V) = + (Action.ρ V).hom := rfl @[simp] lemma endRingEquiv_comp_ρ (V : FDRep k G) : - (MonoidHomClass.toMonoidHom (ModuleCat.endRingEquiv V.V.obj)).comp (Action.ρ V) = ρ V := rfl + (MonoidHomClass.toMonoidHom (ModuleCat.endRingEquiv V.V.obj)).comp (Action.ρ V).hom = ρ V := rfl @[simp] lemma hom_action_ρ (V : FDRep k G) (g : G) : (Action.ρ V g).hom = ρ V g := rfl @@ -112,7 +113,8 @@ theorem Iso.conj_ρ {V W : FDRep k G} (i : V ≅ W) (g : G) : @[simps ρ] def of {V : Type u} [AddCommGroup V] [Module k V] [FiniteDimensional k V] (ρ : Representation k G V) : FDRep k G := - ⟨FGModuleCat.of k V, ρ ≫ MonCat.ofHom (ModuleCat.endRingEquiv _).symm.toMonoidHom⟩ + ⟨FGModuleCat.of k V, MonCat.ofHom ρ ≫ MonCat.ofHom + (ModuleCat.endRingEquiv (ModuleCat.of k V)).symm.toMonoidHom⟩ instance : HasForget₂ (FDRep k G) (Rep k G) where forget₂ := (forget₂ (FGModuleCat k) (ModuleCat k)).mapAction (MonCat.of G) diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean index ad038c15186b4..b2e5e6476ce21 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean @@ -205,8 +205,9 @@ theorem diagonalSucc_inv_single_left (g : G) (f : Gⁿ →₀ k) (r : k) : refine f.induction ?_ ?_ · simp only [TensorProduct.tmul_zero, map_zero] · intro a b x _ _ hx + -- `simp` doesn't pick up on `diagonalSucc_inv_single_single` unless it has parentheses. simp only [lift_apply, smul_single', mul_one, TensorProduct.tmul_add, map_add, - diagonalSucc_inv_single_single, hx, Finsupp.sum_single_index, mul_comm b, + (diagonalSucc_inv_single_single), hx, Finsupp.sum_single_index, mul_comm b, zero_mul, single_zero] theorem diagonalSucc_inv_single_right (g : G →₀ k) (f : Gⁿ) (r : k) : @@ -215,7 +216,8 @@ theorem diagonalSucc_inv_single_right (g : G →₀ k) (f : Gⁿ) (r : k) : refine g.induction ?_ ?_ · simp only [TensorProduct.zero_tmul, map_zero] · intro a b x _ _ hx - simp only [lift_apply, smul_single', map_add, hx, diagonalSucc_inv_single_single, + -- `simp` doesn't pick up on `diagonalSucc_inv_single_single` unless it has parentheses. + simp only [lift_apply, smul_single', map_add, hx, (diagonalSucc_inv_single_single), TensorProduct.add_tmul, Finsupp.sum_single_index, zero_mul, single_zero] end Rep diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index 5e1201f82dfad..6ecea75374cd5 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -61,7 +61,7 @@ instance (V : Rep k G) : Module k V := by -/ def ρ (V : Rep k G) : Representation k G V := -- Porting note: was `V.ρ` - (ModuleCat.endRingEquiv V.V).toMonoidHom.comp (Action.ρ V) + (ModuleCat.endRingEquiv V.V).toMonoidHom.comp (Action.ρ V).hom /-- Lift an unbundled representation to `Rep`. -/ def of {V : Type u} [AddCommGroup V] [Module k V] (ρ : G →* V →ₗ[k] V) : Rep k G := @@ -77,7 +77,7 @@ theorem of_ρ {V : Type u} [AddCommGroup V] [Module k V] (ρ : G →* V →ₗ[k rfl theorem Action_ρ_eq_ρ {A : Rep k G} : - Action.ρ A = (ModuleCat.endRingEquiv _).symm.toMonoidHom.comp A.ρ := + Action.ρ A = MonCat.ofHom ((ModuleCat.endRingEquiv _).symm.toMonoidHom.comp A.ρ) := rfl @[simp] diff --git a/MathlibTest/CategoryTheory/ConcreteCategory/MonCat.lean b/MathlibTest/CategoryTheory/ConcreteCategory/MonCat.lean new file mode 100644 index 0000000000000..3d38e2b4f16fb --- /dev/null +++ b/MathlibTest/CategoryTheory/ConcreteCategory/MonCat.lean @@ -0,0 +1,50 @@ +import Mathlib.Algebra.Category.MonCat.Basic + +universe v u + +open CategoryTheory MonCat + +set_option maxHeartbeats 10000 +set_option synthInstance.maxHeartbeats 2000 + +/- We test if all the coercions and `map_mul` lemmas trigger correctly. -/ + +example (X : Type u) [Monoid X] : ⇑(𝟙 (of X)) = id := by simp + +example {X Y : Type u} [Monoid X] [Monoid Y] (f : X →* Y) : + ⇑(ofHom f) = ⇑f := by simp + +example {X Y : Type u} [Monoid X] [Monoid Y] (f : X →* Y) + (x : X) : (ofHom f) x = f x := by simp + +example {X Y Z : MonCat} (f : X ⟶ Y) (g : Y ⟶ Z) : ⇑(f ≫ g) = ⇑g ∘ ⇑f := by simp + +example {X Y Z : Type u} [Monoid X] [Monoid Y] [Monoid Z] + (f : X →* Y) (g : Y →* Z) : + ⇑(ofHom f ≫ ofHom g) = g ∘ f := by simp + +example {X Y : Type u} [Monoid X] [Monoid Y] {Z : MonCat} + (f : X →* Y) (g : of Y ⟶ Z) : + ⇑(ofHom f ≫ g) = g ∘ f := by simp + +example {X Y : MonCat} {Z : Type u} [Monoid Z] (f : X ⟶ Y) (g : Y ⟶ of Z) : + ⇑(f ≫ g) = g ∘ f := by simp + +example {Y Z : MonCat} {X : Type u} [Monoid X] (f : of X ⟶ Y) (g : Y ⟶ Z) : + ⇑(f ≫ g) = g ∘ f := by simp + +example {X Y Z : MonCat} (f : X ⟶ Y) (g : Y ⟶ Z) (x : X) : (f ≫ g) x = g (f x) := by simp + +example {X Y : MonCat} (e : X ≅ Y) (x : X) : e.inv (e.hom x) = x := by simp + +example {X Y : MonCat} (e : X ≅ Y) (y : Y) : e.hom (e.inv y) = y := by simp + +example (X : MonCat) : ⇑(𝟙 X) = id := by simp + +example {X : Type*} [Monoid X] : ⇑(MonoidHom.id X) = id := by simp + +example {M N : MonCat} (f : M ⟶ N) (x y : M) : f (x * y) = f x * f y := by + simp + +example {M N : MonCat} (f : M ⟶ N) : f 1 = 1 := by + simp diff --git a/MathlibTest/MonCat.lean b/MathlibTest/MonCat.lean index 17975ad1b81cf..b092c514d8e1c 100644 --- a/MathlibTest/MonCat.lean +++ b/MathlibTest/MonCat.lean @@ -3,7 +3,7 @@ import Mathlib.Algebra.Category.MonCat.Basic -- We verify that the coercions of morphisms to functions work correctly: example {R S : MonCat} (f : R ⟶ S) : ↑R → ↑S := f --- Porting note: it's essential that simp lemmas for `→*` apply to morphisms. +-- It's essential that simp lemmas for `→*` apply to morphisms. example {R S : MonCat} (i : R ⟶ S) (r : R) (h : r = 1) : i r = 1 := by simp [h] example {R S : CommMonCat} (f : R ⟶ S) : ↑R → ↑S := f @@ -12,7 +12,7 @@ example {R S : CommMonCat} (i : R ⟶ S) (r : R) (h : r = 1) : i r = 1 := by sim -- We verify that when constructing a morphism in `CommMonCat`, -- when we construct the `toFun` field, the types are presented as `↑R`. -example (R : CommMonCat.{u}) : R ⟶ R := +example (R : CommMonCat.{u}) : R ⟶ R := CommMonCat.ofHom { toFun := fun x => by match_target (R : Type u) guard_hyp x : (R : Type u) From e547f5cbc2332791107ec5a4fa99da7672eb30b3 Mon Sep 17 00:00:00 2001 From: Adam Topaz Date: Thu, 30 Jan 2025 16:37:35 +0000 Subject: [PATCH 679/681] feat: the right Kan extension of a functor on a preorder is a sheaf (#21263) --- Mathlib.lean | 1 + .../Topology/Order/UpperLowerSetTopology.lean | 3 + Mathlib/Topology/Sheaves/Alexandrov.lean | 208 ++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 Mathlib/Topology/Sheaves/Alexandrov.lean diff --git a/Mathlib.lean b/Mathlib.lean index cd32a5b65d8f1..dea49620f4943 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5598,6 +5598,7 @@ import Mathlib.Topology.Sets.Closeds import Mathlib.Topology.Sets.Compacts import Mathlib.Topology.Sets.Opens import Mathlib.Topology.Sets.Order +import Mathlib.Topology.Sheaves.Alexandrov import Mathlib.Topology.Sheaves.CommRingCat import Mathlib.Topology.Sheaves.Forget import Mathlib.Topology.Sheaves.Functors diff --git a/Mathlib/Topology/Order/UpperLowerSetTopology.lean b/Mathlib/Topology/Order/UpperLowerSetTopology.lean index 19ca3cbaf5fcf..1c2c2390d6ebe 100644 --- a/Mathlib/Topology/Order/UpperLowerSetTopology.lean +++ b/Mathlib/Topology/Order/UpperLowerSetTopology.lean @@ -253,6 +253,9 @@ interval (-∞,a]. rw [closure_eq_lowerClosure, lowerClosure_singleton] rfl +lemma specializes_iff_le {a b : α} : a ⤳ b ↔ b ≤ a := by + simp only [specializes_iff_closure_subset, closure_singleton, Iic_subset_Iic] + end Preorder section maps diff --git a/Mathlib/Topology/Sheaves/Alexandrov.lean b/Mathlib/Topology/Sheaves/Alexandrov.lean new file mode 100644 index 0000000000000..b079866b5d234 --- /dev/null +++ b/Mathlib/Topology/Sheaves/Alexandrov.lean @@ -0,0 +1,208 @@ +/- +Copyright (c) 2025 Adam Topaz. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Justin Curry, Adam Topaz +-/ +import Mathlib.Combinatorics.Quiver.ReflQuiver +import Mathlib.Order.CompletePartialOrder +import Mathlib.Topology.Order.UpperLowerSetTopology +import Mathlib.Topology.Sheaves.SheafCondition.OpensLeCover + +/-! + +Let `X` be a preorder `≤`, and consider the associated Alexandrov topology on `X`. +Given a functor `F : X ⥤ C` to a complete category, we can extend `F` to a +presheaf on (the topological space) `X` by taking the right Kan extension along the canonical +functor `X ⥤ (Opens X)ᵒᵖ` sending `x : X` to the principal open `{y | x ≤ y}` in the +Alexandrov topology. + +This file proves that this presheaf is a sheaf. + +-/ + +noncomputable section + +universe v u +open CategoryTheory Limits Functor +open TopCat Presheaf Functor SheafCondition +open TopologicalSpace Topology + +variable + {X : Type v} [TopologicalSpace X] [Preorder X] [Topology.IsUpperSet X] + {C : Type u} [Category.{v} C] [HasLimits C] + (F : X ⥤ C) + +namespace Alexandrov + +/-- Given `x : X`, this is the principal open subset of `X` generated by `x`. -/ +def principalOpen (x : X) : Opens X := .mk { y | x ≤ y } <| by + rw [IsUpperSet.isOpen_iff_isUpperSet] + intro y z h1 h2 + exact le_trans h2 h1 + +lemma self_mem_principalOpen (x : X) : x ∈ principalOpen x := le_refl _ + +@[simp] +lemma principalOpen_le_iff {x : X} (U : Opens X) : + principalOpen x ≤ U ↔ x ∈ U := by + refine ⟨fun h => h <| self_mem_principalOpen _, fun hx y hy => ?_⟩ + · have := U.isOpen + rw [IsUpperSet.isOpen_iff_isUpperSet] at this + exact this hy hx + +lemma principalOpen_le {x y : X} (h : x ≤ y) : + principalOpen y ≤ principalOpen x := + fun _ hc => le_trans h hc + +variable (X) in +/-- The functor sending `x : X` to the principal open associated with `x`. -/ +@[simps] +def principals : X ⥤ (Opens X)ᵒᵖ where + obj x := .op <| principalOpen x + map {x y} f := .op <| principalOpen_le f.le |>.hom + +lemma exists_le_of_le_sup {ι : Type v} {x : X} + (Us : ι → Opens X) (h : principalOpen x ≤ iSup Us) : + ∃ i : ι, principalOpen x ≤ Us i := by + have : x ∈ iSup Us := h <| self_mem_principalOpen x + simp only [Opens.mem_iSup] at this + obtain ⟨i, hi⟩ := this + refine ⟨i, ?_⟩ + simpa + +/-- The right kan extension of `F` along `X ⥤ (Opens X)ᵒᵖ`. -/ +abbrev principalsKanExtension : (Opens X)ᵒᵖ ⥤ C := + (principals X).pointwiseRightKanExtension F + +/-- Given a structured arrow `f` with domain `U : Opens X` over `principals X`, +this functor sends `f` to its "generator", an element of `X`. -/ +abbrev generator (U : Opens X) : + StructuredArrow (.op U) (principals X) ⥤ X := + StructuredArrow.proj (.op U) (principals X) + +/-- Given a structured arrow `f` with domain `iSup Us` over `principals X`, +where `Us` is a family of `Opens X`, this functor sends `f` to the principal open +associated with it, considered as an object in the full subcategory of all `V : Opens X` +such that `V ≤ Us i` for some `i`. + +This definition is primarily meant to be used in `lowerCone`, and `isLimit` below. +-/ +@[simps] +def projSup {ι : Type v} (Us : ι → Opens X) : + StructuredArrow (.op <| iSup Us) (principals X) ⥤ + (FullSubcategory fun V => ∃ i, V ≤ Us i)ᵒᵖ where + obj f := .op <| .mk (principalOpen f.right) <| exists_le_of_le_sup Us f.hom.unop.le + map e := .op <| LE.le.hom <| principalOpen_le <| e.right.le + +variable {F} in +/-- This is an auxiliary definition which is only meant to be used in `isLimit` below. -/ +@[simps] +def lowerCone + {α : Type v} (Us : α → Opens X) + (S : Cone ((fullSubcategoryInclusion fun V => ∃ i, V ≤ Us i).op ⋙ principalsKanExtension F)) : + Cone (generator (iSup Us) ⋙ F) where + pt := S.pt + π := { + app := fun f => + S.π.app ((projSup Us).obj f) ≫ limit.π (generator (principalOpen f.right) ⋙ F) + ⟨.mk .unit, f.right, 𝟙 _⟩ + naturality := by + rintro x y e + simp only [Functor.const_obj_obj, Functor.comp_obj, Functor.const_obj_map, principals_obj, + Functor.op_obj, fullSubcategoryInclusion.obj, Functor.pointwiseRightKanExtension_obj, + Category.id_comp, Functor.comp_map, Category.assoc] + rw [← S.w ((projSup Us).map e), Category.assoc] + congr 1 + simp only [projSup_obj, Functor.comp_obj, Functor.op_obj, fullSubcategoryInclusion.obj, + Functor.pointwiseRightKanExtension_obj, projSup_map, homOfLE_leOfHom, Functor.comp_map, + Functor.op_map, Quiver.Hom.unop_op, fullSubcategoryInclusion.map, + Functor.pointwiseRightKanExtension_map, limit.lift_π] + let xx : StructuredArrow (Opposite.op (principalOpen x.right)) (principals X) := + ⟨.mk .unit, x.right, 𝟙 _⟩ + let yy : StructuredArrow (Opposite.op (principalOpen x.right)) (principals X) := + ⟨.mk .unit, y.right, .op <| LE.le.hom <| principalOpen_le e.right.le⟩ + let ee : xx ⟶ yy := { left := 𝟙 _, right := e.right } + exact limit.w + (StructuredArrow.proj (Opposite.op (principalOpen x.right)) (principals X) ⋙ F) ee + |>.symm + } + +/-- +This is the main construction in this file showing that the right Kan extension +of `F : X ⥤ C` along `principals : X ⥤ (Opens X)ᵒᵖ` is a sheaf, by showing that a certain +cone is a limit cone. + +See `is_sheaf_principalsKanExtension` for the main application. +-/ +def isLimit {X : TopCat.{v}} [Preorder X] [Topology.IsUpperSet X] + (F : X ⥤ C) + (α : Type v) (Us : α → Opens X) : + IsLimit (mapCone (principalsKanExtension F) (opensLeCoverCocone Us).op) where + lift S := limit.lift _ (lowerCone Us S) + fac := by + rintro S ⟨V, i, hV⟩ + dsimp [forget, opensLeCoverCocone] + ext ⟨_, x, f⟩ + simp only [comp_obj, StructuredArrow.proj_obj, Category.assoc, limit.lift_π, lowerCone_pt, + lowerCone_π_app, const_obj_obj, projSup_obj, StructuredArrow.map_obj_right, op_obj, + fullSubcategoryInclusion.obj, pointwiseRightKanExtension_obj] + have e : principalOpen x ≤ V := f.unop.le + let VV : (FullSubcategory fun V => ∃ i, V ≤ Us i) := ⟨V, i, hV⟩ + let xx : (FullSubcategory fun V => ∃ i, V ≤ Us i) := ⟨principalOpen x, i, le_trans e hV⟩ + let ee : xx ⟶ VV := e.hom + rw [← S.w ee.op, Category.assoc] + congr 1 + simp only [comp_obj, op_obj, fullSubcategoryInclusion.obj, pointwiseRightKanExtension_obj, + Functor.comp_map, op_map, Quiver.Hom.unop_op, fullSubcategoryInclusion.map, + pointwiseRightKanExtension_map, limit.lift_π, xx, VV] + congr + uniq := by + intro S m hm + dsimp + symm + ext ⟨_, x, f⟩ + simp only [lowerCone_pt, comp_obj, limit.lift_π, lowerCone_π_app, const_obj_obj, projSup_obj, + op_obj, fullSubcategoryInclusion.obj, pointwiseRightKanExtension_obj] + specialize hm ⟨principalOpen x, ?_⟩ + · apply exists_le_of_le_sup + exact f.unop.le + · rw [← hm] + simp only [mapCone_pt, Cocone.op_pt, pointwiseRightKanExtension_obj, principals_obj, + const_obj_obj, comp_obj, op_obj, fullSubcategoryInclusion.obj, mapCone_π_app, Cocone.op_π, + NatTrans.op_app, pointwiseRightKanExtension_map, Category.assoc, limit.lift_π] + congr + +theorem isSheaf_principalsKanExtension + {X : TopCat.{v}} [Preorder X] [Topology.IsUpperSet X] (F : X ⥤ C) : + Presheaf.IsSheaf (principalsKanExtension F) := by + rw [isSheaf_iff_isSheafOpensLeCover] + intro ι Us + constructor + apply isLimit + +end Alexandrov + +open Alexandrov + +/-- +The main theorem of this file. +If `X` is a topological space and preorder whose topology is the `UpperSet` topology associated +with the preorder, `F : X ⥤ C` is a functor into a complete category from the preorder category, +and `P : (Opens X)ᵒᵖ ⥤ C` denotes the right Kan extension of `F` along the +functor `X ⥤ (Open X)ᵒᵖ` which sends `x : X` to `{y | x ≤ y}`, then `P` is a sheaf. +-/ +theorem Topology.IsUpperSet.isSheaf_of_isRightKanExtension + (P : (Opens X)ᵒᵖ ⥤ C) + (η : Alexandrov.principals X ⋙ P ⟶ F) + [P.IsRightKanExtension η] : + Presheaf.IsSheaf (Opens.grothendieckTopology X) P := by + let γ : principals X ⋙ principalsKanExtension F ⟶ F := + (principals X).pointwiseRightKanExtensionCounit F + let _ : (principalsKanExtension F).IsRightKanExtension γ := inferInstance + have : P ≅ principalsKanExtension F := + @rightKanExtensionUnique _ _ _ _ _ _ _ _ _ _ (by assumption) _ _ (by assumption) + change TopCat.Presheaf.IsSheaf (X := TopCat.of X) P + rw [isSheaf_iso_iff this] + let _ : Preorder (TopCat.of X) := inferInstanceAs <| Preorder X + have _ : Topology.IsUpperSet (TopCat.of X) := inferInstanceAs <| Topology.IsUpperSet X + exact isSheaf_principalsKanExtension (X := TopCat.of X) F From 3da619bbabf44fff881851c0a844899472cb2381 Mon Sep 17 00:00:00 2001 From: Whysoserioushah Date: Thu, 30 Jan 2025 16:52:20 +0000 Subject: [PATCH 680/681] feat(Mathlib/Algebra/Central/TensorProduct): More on Central Algebras (#20991) Co-authored by: @jjaassoonn Co-authored-by: Whysoserioushah <109107491+Whysoserioushah@users.noreply.github.com> Co-authored-by: Junyan Xu --- Mathlib.lean | 1 + Mathlib/Algebra/Central/Basic.lean | 18 ++++- Mathlib/Algebra/Central/TensorProduct.lean | 84 ++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 Mathlib/Algebra/Central/TensorProduct.lean diff --git a/Mathlib.lean b/Mathlib.lean index dea49620f4943..847a095a60cb3 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -172,6 +172,7 @@ import Mathlib.Algebra.Category.Semigrp.Basic import Mathlib.Algebra.Central.Basic import Mathlib.Algebra.Central.Defs import Mathlib.Algebra.Central.Matrix +import Mathlib.Algebra.Central.TensorProduct import Mathlib.Algebra.CharP.Algebra import Mathlib.Algebra.CharP.Basic import Mathlib.Algebra.CharP.CharAndCard diff --git a/Mathlib/Algebra/Central/Basic.lean b/Mathlib/Algebra/Central/Basic.lean index 73136573fefe1..e0386ab247eab 100644 --- a/Mathlib/Algebra/Central/Basic.lean +++ b/Mathlib/Algebra/Central/Basic.lean @@ -23,7 +23,8 @@ universe u v namespace Algebra.IsCentral -variable (K : Type u) [CommSemiring K] (D : Type v) [Semiring D] [Algebra K D] [IsCentral K D] +variable (K : Type u) [CommSemiring K] (D D': Type v) [Semiring D] [Algebra K D] + [h : IsCentral K D] [Semiring D'] [Algebra K D'] @[simp] lemma center_eq_bot : Subalgebra.center K D = ⊥ := eq_bot_iff.2 IsCentral.out @@ -53,4 +54,19 @@ lemma baseField_essentially_unique obtain ⟨x', H⟩ := H exact ⟨x', (algebraMap K D).injective <| by simp [← H, algebraMap_eq_smul_one]⟩ +lemma of_algEquiv (e : D ≃ₐ[K] D') : IsCentral K D' where + out x hx := + have ⟨k, hk⟩ := h.1 ((MulEquivClass.apply_mem_center_iff e.symm).mpr hx) + ⟨k, by simpa [ofId] using congr(e $hk)⟩ + +open MulOpposite in +/-- Opposite algebra of a central algebra is central. This instance combined with the coming + `IsSimpleRing` instance for the opposite of central simple algebra will be an + inverse for an element in `BrauerGroup`, find out more about this in + `Mathlib.Algebra.BrauerGroup.Basic`. -/ +instance : IsCentral K Dᵐᵒᵖ where + out z hz := + have ⟨k, hk⟩ := h.1 (MulOpposite.unop_mem_center_iff.mpr hz) + ⟨k, by simpa using congr(op $hk)⟩ + end Algebra.IsCentral diff --git a/Mathlib/Algebra/Central/TensorProduct.lean b/Mathlib/Algebra/Central/TensorProduct.lean new file mode 100644 index 0000000000000..fc53bce1773ba --- /dev/null +++ b/Mathlib/Algebra/Central/TensorProduct.lean @@ -0,0 +1,84 @@ +/- +Copyright (c) 2025 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jujian Zhang, Yunzhou Xie +-/ + +import Mathlib.Algebra.Central.Basic +import Mathlib.RingTheory.Flat.Basic +import Mathlib.LinearAlgebra.Basis.VectorSpace + +/-! + +# Lemmas about tensor products of central algebras + +In this file we prove for algebras `B` and `C` over a field `K` that if `B ⊗[K] C` is a central +algebra and `B, C` nontrivial, then both `B` and `C` are central algebras. + +## Main Results + +- `Algebra.IsCentral.left_of_tensor_of_field`: If `B` `C` are `K`-algebras where `K` is a field, + `C` is nontrivial and `B ⊗[K] C` is a central algebra over `K`, then `B` is a + central algebra over `K`. +- `Algebra.IsCentral.right_of_tensor_of_field`: If `B` `C` are `K`-algebras where `K` is a field, + `C` is nontrivial and `B ⊗[K] C` is a central algebra over `K`, then `B` is a + central algebra over `K`. + +## Tags +Central Algebras, Central Simple Algebras, Noncommutative Algebra +-/ + +universe u v + +open TensorProduct + +variable (K B C : Type*) [CommSemiring K] [Semiring B] [Semiring C] [Algebra K B] [Algebra K C] + +lemma Algebra.TensorProduct.includeLeft_map_center_le : + (Subalgebra.center K B).map includeLeft ≤ Subalgebra.center K (B ⊗[K] C) := by + intro x hx + simp only [Subalgebra.mem_map, Subalgebra.mem_center_iff] at hx ⊢ + obtain ⟨b, hb0, rfl⟩ := hx + intro bc + induction bc using TensorProduct.induction_on with + | zero => simp + | tmul b' c => simp [hb0] + | add _ _ _ _ => simp_all [add_mul, mul_add] + +lemma Algebra.TensorProduct.includeRight_map_center_le : + (Subalgebra.center K C).map includeRight ≤ Subalgebra.center K (B ⊗[K] C) := fun x hx ↦ by + simp only [Subalgebra.mem_map, Subalgebra.mem_center_iff] at hx ⊢ + obtain ⟨c, hc0, rfl⟩ := hx + intro bc + induction bc using TensorProduct.induction_on with + | zero => simp + | tmul b c' => simp [hc0] + | add _ _ _ _ => simp_all [add_mul, mul_add] + +namespace Algebra.IsCentral + +open Algebra.TensorProduct in +lemma left_of_tensor (inj : Function.Injective (algebraMap K C)) [Module.Flat K B] + [hbc : Algebra.IsCentral K (B ⊗[K] C)] : IsCentral K B where + out := (Subalgebra.map_le.mp ((includeLeft_map_center_le K B C).trans hbc.1)).trans + fun _ ⟨k, hk⟩ ↦ ⟨k, includeLeft_injective (S := K) inj hk⟩ + +lemma right_of_tensor (inj : Function.Injective (algebraMap K B)) [Module.Flat K C] + [Algebra.IsCentral K (B ⊗[K] C)] : IsCentral K C := + have : IsCentral K (C ⊗[K] B) := IsCentral.of_algEquiv K _ _ <| Algebra.TensorProduct.comm _ _ _ + left_of_tensor K C B inj + +/-- Let `B` and `C` be two algebras over a field `K`, if `B ⊗[K] C` is central and `C` is + non-trivial, then `B` is central. -/ +lemma left_of_tensor_of_field (K B C : Type*) [Field K] [Ring B] [Ring C] [Nontrivial C] + [Algebra K B] [Algebra K C] [IsCentral K (B ⊗[K] C)] : IsCentral K B := + left_of_tensor K B C <| NoZeroSMulDivisors.algebraMap_injective K C + +/-- Let `B` and `C` be two algebras over a field `K`, if `B ⊗[K] C` is central and `A` is + non-trivial, then `B` is central. -/ +lemma right_of_tensor_of_field (K B C : Type*) [Field K] [Ring B] [Ring C] [Nontrivial B] + [Algebra K B] [Algebra K C] [IsCentral K (B ⊗[K] C)] : IsCentral K C := + right_of_tensor K B C <| NoZeroSMulDivisors.algebraMap_injective K B + + +end Algebra.IsCentral From 3d895fb3f8b1eed60cb10c5d48765b681a9100a7 Mon Sep 17 00:00:00 2001 From: Anatole Dedecker Date: Thu, 30 Jan 2025 18:56:45 +0000 Subject: [PATCH 681/681] feat: iff version of `le_of_forall_le` (#21264) Also rename `le_of_forall_le'` to `le_of_forall_ge`. --- Mathlib/Order/Basic.lean | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index 11f4a94f61cf1..d8faa63322623 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -419,9 +419,17 @@ theorem eq_of_forall_le_iff [PartialOrder α] {a b : α} (H : ∀ c, c ≤ a ↔ theorem le_of_forall_le [Preorder α] {a b : α} (H : ∀ c, c ≤ a → c ≤ b) : a ≤ b := H _ le_rfl -theorem le_of_forall_le' [Preorder α] {a b : α} (H : ∀ c, a ≤ c → b ≤ c) : b ≤ a := +theorem le_of_forall_ge [Preorder α] {a b : α} (H : ∀ c, a ≤ c → b ≤ c) : b ≤ a := H _ le_rfl +@[deprecated (since := "2025-01-30")] alias le_of_forall_le' := le_of_forall_ge + +theorem forall_le_iff_le [Preorder α] {a b : α} : (∀ ⦃c⦄, c ≤ a → c ≤ b) ↔ a ≤ b := + ⟨le_of_forall_le, fun h _ hca ↦ le_trans hca h⟩ + +theorem forall_le_iff_ge [Preorder α] {a b : α} : (∀ ⦃c⦄, a ≤ c → b ≤ c) ↔ b ≤ a := + ⟨le_of_forall_ge, fun h _ hca ↦ le_trans h hca⟩ + theorem le_of_forall_lt [LinearOrder α] {a b : α} (H : ∀ c, c < a → c < b) : a ≤ b := le_of_not_lt fun h ↦ lt_irrefl _ (H _ h)